Linux-2.6.12-rc2
Initial git repository build. I'm not bothering with the full history,
even though we have it. We can create a separate "historical" git
archive of that later if we want to, and in the meantime it's about
3.2GB when imported into git - space that would just make the early
git days unnecessarily complicated, when we don't have a lot of good
infrastructure for it.
Let it rip!
diff --git a/arch/ppc/4xx_io/Makefile b/arch/ppc/4xx_io/Makefile
new file mode 100644
index 0000000..6a8cd57
--- /dev/null
+++ b/arch/ppc/4xx_io/Makefile
@@ -0,0 +1,6 @@
+#
+# Makefile for the linux MPC4xx ppc-specific parts
+#
+
+
+obj-$(CONFIG_SERIAL_SICC) += serial_sicc.o
diff --git a/arch/ppc/4xx_io/serial_sicc.c b/arch/ppc/4xx_io/serial_sicc.c
new file mode 100644
index 0000000..e95c48d
--- /dev/null
+++ b/arch/ppc/4xx_io/serial_sicc.c
@@ -0,0 +1,2012 @@
+/*
+ * arch/ppc/4xx_io/serial_sicc.c
+ *
+ * Driver for IBM STB3xxx SICC serial port
+ *
+ * Based on drivers/char/serial_amba.c, by ARM Ltd.
+ *
+ * Copyright 2001 IBM Crop.
+ * Author: IBM China Research Lab
+ * Yudong Yang <yangyud@cn.ibm.com>
+ * Yi Ge <geyi@cn.ibm.com>
+ *
+ * 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
+ *
+ *
+ * This is a driver for SICC serial port on IBM Redwood 4 evaluation board.
+ * The driver support both as a console device and normal serial device and
+ * is compatible with normal ttyS* devices.
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/tty.h>
+#include <linux/tty_flip.h>
+#include <linux/major.h>
+#include <linux/string.h>
+#include <linux/fcntl.h>
+#include <linux/ptrace.h>
+#include <linux/ioport.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <linux/circ_buf.h>
+#include <linux/serial.h>
+#include <linux/console.h>
+#include <linux/sysrq.h>
+#include <linux/bitops.h>
+
+#include <asm/system.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/uaccess.h>
+#include <asm/serial.h>
+
+
+#include <linux/serialP.h>
+
+
+/* -----------------------------------------------------------------------------
+ * From STB03xxx SICC UART Specification
+ * -----------------------------------------------------------------------------
+ * UART Register Offsets.
+ */
+
+#define BL_SICC_LSR 0x0000000 /* line status register read/clear */
+#define BL_SICC_LSRS 0x0000001 /* set line status register read/set */
+#define BL_SICC_HSR 0x0000002 /* handshake status register r/clear */
+#define BL_SICC_HSRS 0x0000003 /* set handshake status register r/set */
+#define BL_SICC_BRDH 0x0000004 /* baudrate divisor high reg r/w */
+#define BL_SICC_BRDL 0x0000005 /* baudrate divisor low reg r/w */
+#define BL_SICC_LCR 0x0000006 /* control register r/w */
+#define BL_SICC_RCR 0x0000007 /* receiver command register r/w */
+#define BL_SICC_TxCR 0x0000008 /* transmitter command register r/w */
+#define BL_SICC_RBR 0x0000009 /* receive buffer r */
+#define BL_SICC_TBR 0x0000009 /* transmit buffer w */
+#define BL_SICC_CTL2 0x000000A /* added for Vesta */
+#define BL_SICC_IrCR 0x000000B /* added for Vesta IR */
+
+/* masks and definitions for serial port control register */
+
+#define _LCR_LM_MASK 0xc0 /* loop back modes */
+#define _LCR_DTR_MASK 0x20 /* data terminal ready 0-inactive */
+#define _LCR_RTS_MASK 0x10 /* request to send 0-inactive */
+#define _LCR_DB_MASK 0x08 /* data bits mask */
+#define _LCR_PE_MASK 0x04 /* parity enable */
+#define _LCR_PTY_MASK 0x02 /* parity */
+#define _LCR_SB_MASK 0x01 /* stop bit mask */
+
+#define _LCR_LM_NORM 0x00 /* normal operation */
+#define _LCR_LM_LOOP 0x40 /* internal loopback mode */
+#define _LCR_LM_ECHO 0x80 /* automatic echo mode */
+#define _LCR_LM_RES 0xc0 /* reserved */
+
+#define _LCR_DTR_ACTIVE _LCR_DTR_MASK /* DTR is active */
+#define _LCR_RTS_ACTIVE _LCR_RTS_MASK /* RTS is active */
+#define _LCR_DB_8_BITS _LCR_DB_MASK /* 8 data bits */
+#define _LCR_DB_7_BITS 0x00 /* 7 data bits */
+#define _LCR_PE_ENABLE _LCR_PE_MASK /* parity enabled */
+#define _LCR_PE_DISABLE 0x00 /* parity disabled */
+#define _LCR_PTY_EVEN 0x00 /* even parity */
+#define _LCR_PTY_ODD _LCR_PTY_MASK /* odd parity */
+#define _LCR_SB_1_BIT 0x00 /* one stop bit */
+#define _LCR_SB_2_BIT _LCR_SB_MASK /* two stop bit */
+
+/* serial port handshake register */
+
+#define _HSR_DIS_MASK 0x80 /* DSR input inactive error mask */
+#define _HSR_CS_MASK 0x40 /* CTS input inactive error mask */
+#define _HSR_DIS_ACT 0x00 /* dsr input is active */
+#define _HSR_DIS_INACT _HSR_DIS_MASK /* dsr input is inactive */
+#define _HSR_CS_ACT 0x00 /* cts input is active */
+#define _HSR_CS_INACT _HSR_CS_MASK /* cts input is active */
+
+/* serial port line status register */
+
+#define _LSR_RBR_MASK 0x80 /* receive buffer ready mask */
+#define _LSR_FE_MASK 0x40 /* framing error */
+#define _LSR_OE_MASK 0x20 /* overrun error */
+#define _LSR_PE_MASK 0x10 /* parity error */
+#define _LSR_LB_MASK 0x08 /* line break */
+#define _LSR_TBR_MASK 0x04 /* transmit buffer ready */
+#define _LSR_TSR_MASK 0x02 /* transmit shift register ready */
+
+#define _LSR_RBR_FULL _LSR_RBR_MASK /* receive buffer is full */
+#define _LSR_FE_ERROR _LSR_FE_MASK /* framing error detected */
+#define _LSR_OE_ERROR _LSR_OE_MASK /* overrun error detected */
+#define _LSR_PE_ERROR _LSR_PE_MASK /* parity error detected */
+#define _LSR_LB_BREAK _LSR_LB_MASK /* line break detected */
+#define _LSR_TBR_EMPTY _LSR_TBR_MASK /* transmit buffer is ready */
+#define _LSR_TSR_EMPTY _LSR_TSR_MASK /* transmit shift register is empty */
+#define _LSR_TX_ALL 0x06 /* all physical transmit is done */
+
+#define _LSR_RX_ERR (_LSR_LB_BREAK | _LSR_FE_MASK | _LSR_OE_MASK | \
+ _LSR_PE_MASK )
+
+/* serial port receiver command register */
+
+#define _RCR_ER_MASK 0x80 /* enable receiver mask */
+#define _RCR_DME_MASK 0x60 /* dma mode */
+#define _RCR_EIE_MASK 0x10 /* error interrupt enable mask */
+#define _RCR_PME_MASK 0x08 /* pause mode mask */
+
+#define _RCR_ER_ENABLE _RCR_ER_MASK /* receiver enabled */
+#define _RCR_DME_DISABLE 0x00 /* dma disabled */
+#define _RCR_DME_RXRDY 0x20 /* dma disabled, RxRDY interrupt enabled*/
+#define _RCR_DME_ENABLE2 0x40 /* dma enabled,receiver src channel 2 */
+#define _RCR_DME_ENABLE3 0x60 /* dma enabled,receiver src channel 3 */
+#define _RCR_PME_HARD _RCR_PME_MASK /* RTS controlled by hardware */
+#define _RCR_PME_SOFT 0x00 /* RTS controlled by software */
+
+/* serial port transmit command register */
+
+#define _TxCR_ET_MASK 0x80 /* transmiter enable mask */
+#define _TxCR_DME_MASK 0x60 /* dma mode mask */
+#define _TxCR_TIE_MASK 0x10 /* empty interrupt enable mask */
+#define _TxCR_EIE_MASK 0x08 /* error interrupt enable mask */
+#define _TxCR_SPE_MASK 0x04 /* stop/pause mask */
+#define _TxCR_TB_MASK 0x02 /* transmit break mask */
+
+#define _TxCR_ET_ENABLE _TxCR_ET_MASK /* transmiter enabled */
+#define _TxCR_DME_DISABLE 0x00 /* transmiter disabled, TBR intr disabled */
+#define _TxCR_DME_TBR 0x20 /* transmiter disabled, TBR intr enabled */
+#define _TxCR_DME_CHAN_2 0x40 /* dma enabled, destination chann 2 */
+#define _TxCR_DME_CHAN_3 0x60 /* dma enabled, destination chann 3 */
+
+/* serial ctl reg 2 - added for Vesta */
+
+#define _CTL2_EXTERN 0x80 /* */
+#define _CTL2_USEFIFO 0x40 /* */
+#define _CTL2_RESETRF 0x08 /* */
+#define _CTL2_RESETTF 0x04 /* */
+
+
+
+#define SERIAL_SICC_NAME "ttySICC"
+#define SERIAL_SICC_MAJOR 150
+#define SERIAL_SICC_MINOR 1
+#define SERIAL_SICC_NR 1
+
+#ifndef TRUE
+#define TRUE 1
+#endif
+#ifndef FALSE
+#define FALSE 0
+#endif
+
+/*
+ * Things needed by tty driver
+ */
+static struct tty_driver *siccnormal_driver;
+
+#if defined(CONFIG_SERIAL_SICC_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
+#define SUPPORT_SYSRQ
+#endif
+
+/*
+ * Things needed internally to this driver
+ */
+
+/*
+ * tmp_buf is used as a temporary buffer by serial_write. We need to
+ * lock it in case the copy_from_user blocks while swapping in a page,
+ * and some other program tries to do a serial write at the same time.
+ * Since the lock will only come under contention when the system is
+ * swapping and available memory is low, it makes sense to share one
+ * buffer across all the serial ports, since it significantly saves
+ * memory if large numbers of serial ports are open.
+ */
+static u_char *tmp_buf;
+static DECLARE_MUTEX(tmp_buf_sem);
+
+#define HIGH_BITS_OFFSET ((sizeof(long)-sizeof(int))*8)
+
+/* number of characters left in xmit buffer before we ask for more */
+#define WAKEUP_CHARS 256
+#define SICC_ISR_PASS_LIMIT 256
+
+#define EVT_WRITE_WAKEUP 0
+
+struct SICC_icount {
+ __u32 cts;
+ __u32 dsr;
+ __u32 rng;
+ __u32 dcd;
+ __u32 rx;
+ __u32 tx;
+ __u32 frame;
+ __u32 overrun;
+ __u32 parity;
+ __u32 brk;
+ __u32 buf_overrun;
+};
+
+/*
+ * Static information about the port
+ */
+struct SICC_port {
+ unsigned int uart_base;
+ unsigned int uart_base_phys;
+ unsigned int irqrx;
+ unsigned int irqtx;
+ unsigned int uartclk;
+ unsigned int fifosize;
+ unsigned int tiocm_support;
+ void (*set_mctrl)(struct SICC_port *, u_int mctrl);
+};
+
+/*
+ * This is the state information which is persistent across opens
+ */
+struct SICC_state {
+ struct SICC_icount icount;
+ unsigned int line;
+ unsigned int close_delay;
+ unsigned int closing_wait;
+ unsigned int custom_divisor;
+ unsigned int flags;
+ int count;
+ struct SICC_info *info;
+ spinlock_t sicc_lock;
+};
+
+#define SICC_XMIT_SIZE 1024
+/*
+ * This is the state information which is only valid when the port is open.
+ */
+struct SICC_info {
+ struct SICC_port *port;
+ struct SICC_state *state;
+ struct tty_struct *tty;
+ unsigned char x_char;
+ unsigned char old_status;
+ unsigned char read_status_mask;
+ unsigned char ignore_status_mask;
+ struct circ_buf xmit;
+ unsigned int flags;
+#ifdef SUPPORT_SYSRQ
+ unsigned long sysrq;
+#endif
+
+ unsigned int event;
+ unsigned int timeout;
+ unsigned int lcr_h;
+ unsigned int mctrl;
+ int blocked_open;
+
+ struct tasklet_struct tlet;
+
+ wait_queue_head_t open_wait;
+ wait_queue_head_t close_wait;
+ wait_queue_head_t delta_msr_wait;
+};
+
+#ifdef CONFIG_SERIAL_SICC_CONSOLE
+static struct console siccuart_cons;
+#endif
+static void siccuart_change_speed(struct SICC_info *info, struct termios *old_termios);
+static void siccuart_wait_until_sent(struct tty_struct *tty, int timeout);
+
+
+
+static void powerpcMtcic_cr(unsigned long value)
+{
+ mtdcr(DCRN_CICCR, value);
+}
+
+static unsigned long powerpcMfcic_cr(void)
+{
+ return mfdcr(DCRN_CICCR);
+}
+
+static unsigned long powerpcMfclkgpcr(void)
+{
+ return mfdcr(DCRN_SCCR);
+}
+
+static void sicc_set_mctrl_null(struct SICC_port *port, u_int mctrl)
+{
+}
+
+static struct SICC_port sicc_ports[SERIAL_SICC_NR] = {
+ {
+ .uart_base = 0,
+ .uart_base_phys = SICC0_IO_BASE,
+ .irqrx = SICC0_INTRX,
+ .irqtx = SICC0_INTTX,
+// .uartclk = 0,
+ .fifosize = 1,
+ .set_mctrl = sicc_set_mctrl_null,
+ }
+};
+
+static struct SICC_state sicc_state[SERIAL_SICC_NR];
+
+static void siccuart_enable_rx_interrupt(struct SICC_info *info)
+{
+ unsigned char cr;
+
+ cr = readb(info->port->uart_base+BL_SICC_RCR);
+ cr &= ~_RCR_DME_MASK;
+ cr |= _RCR_DME_RXRDY;
+ writeb(cr, info->port->uart_base+BL_SICC_RCR);
+}
+
+static void siccuart_disable_rx_interrupt(struct SICC_info *info)
+{
+ unsigned char cr;
+
+ cr = readb(info->port->uart_base+BL_SICC_RCR);
+ cr &= ~_RCR_DME_MASK;
+ cr |= _RCR_DME_DISABLE;
+ writeb(cr, info->port->uart_base+BL_SICC_RCR);
+}
+
+
+static void siccuart_enable_tx_interrupt(struct SICC_info *info)
+{
+ unsigned char cr;
+
+ cr = readb(info->port->uart_base+BL_SICC_TxCR);
+ cr &= ~_TxCR_DME_MASK;
+ cr |= _TxCR_DME_TBR;
+ writeb(cr, info->port->uart_base+BL_SICC_TxCR);
+}
+
+static void siccuart_disable_tx_interrupt(struct SICC_info *info)
+{
+ unsigned char cr;
+
+ cr = readb(info->port->uart_base+BL_SICC_TxCR);
+ cr &= ~_TxCR_DME_MASK;
+ cr |= _TxCR_DME_DISABLE;
+ writeb(cr, info->port->uart_base+BL_SICC_TxCR);
+}
+
+
+static void siccuart_stop(struct tty_struct *tty)
+{
+ struct SICC_info *info = tty->driver_data;
+ unsigned long flags;
+
+ /* disable interrupts while stopping serial port interrupts */
+ spin_lock_irqsave(&info->state->sicc_lock,flags);
+ siccuart_disable_tx_interrupt(info);
+ spin_unlock_irqrestore(&info->state->sicc_lock,flags);
+}
+
+static void siccuart_start(struct tty_struct *tty)
+{
+ struct SICC_info *info = tty->driver_data;
+ unsigned long flags;
+
+ /* disable interrupts while starting serial port interrupts */
+ spin_lock_irqsave(&info->state->sicc_lock,flags);
+ if (info->xmit.head != info->xmit.tail
+ && info->xmit.buf)
+ siccuart_enable_tx_interrupt(info);
+ spin_unlock_irqrestore(&info->state->sicc_lock,flags);
+}
+
+
+/*
+ * This routine is used by the interrupt handler to schedule
+ * processing in the software interrupt portion of the driver.
+ */
+static void siccuart_event(struct SICC_info *info, int event)
+{
+ info->event |= 1 << event;
+ tasklet_schedule(&info->tlet);
+}
+
+static void
+siccuart_rx_chars(struct SICC_info *info, struct pt_regs *regs)
+{
+ struct tty_struct *tty = info->tty;
+ unsigned int status, ch, rsr, flg, ignored = 0;
+ struct SICC_icount *icount = &info->state->icount;
+ struct SICC_port *port = info->port;
+
+ status = readb(port->uart_base+BL_SICC_LSR );
+ while (status & _LSR_RBR_FULL) {
+ ch = readb(port->uart_base+BL_SICC_RBR);
+
+ if (tty->flip.count >= TTY_FLIPBUF_SIZE)
+ goto ignore_char;
+ icount->rx++;
+
+ flg = TTY_NORMAL;
+
+ /*
+ * Note that the error handling code is
+ * out of the main execution path
+ */
+ rsr = readb(port->uart_base+BL_SICC_LSR);
+ if (rsr & _LSR_RX_ERR)
+ goto handle_error;
+#ifdef SUPPORT_SYSRQ
+ if (info->sysrq) {
+ if (ch && time_before(jiffies, info->sysrq)) {
+ handle_sysrq(ch, regs, NULL);
+ info->sysrq = 0;
+ goto ignore_char;
+ }
+ info->sysrq = 0;
+ }
+#endif
+ error_return:
+ *tty->flip.flag_buf_ptr++ = flg;
+ *tty->flip.char_buf_ptr++ = ch;
+ tty->flip.count++;
+ ignore_char:
+ status = readb(port->uart_base+BL_SICC_LSR );
+ }
+out:
+ tty_flip_buffer_push(tty);
+ return;
+
+handle_error:
+ if (rsr & _LSR_LB_BREAK) {
+ rsr &= ~(_LSR_FE_MASK | _LSR_PE_MASK);
+ icount->brk++;
+
+#ifdef SUPPORT_SYSRQ
+ if (info->state->line == siccuart_cons.index) {
+ if (!info->sysrq) {
+ info->sysrq = jiffies + HZ*5;
+ goto ignore_char;
+ }
+ }
+#endif
+ } else if (rsr & _LSR_PE_MASK)
+ icount->parity++;
+ else if (rsr & _LSR_FE_MASK)
+ icount->frame++;
+ if (rsr & _LSR_OE_MASK)
+ icount->overrun++;
+
+ if (rsr & info->ignore_status_mask) {
+ if (++ignored > 100)
+ goto out;
+ goto ignore_char;
+ }
+ rsr &= info->read_status_mask;
+
+ if (rsr & _LSR_LB_BREAK)
+ flg = TTY_BREAK;
+ else if (rsr & _LSR_PE_MASK)
+ flg = TTY_PARITY;
+ else if (rsr & _LSR_FE_MASK)
+ flg = TTY_FRAME;
+
+ if (rsr & _LSR_OE_MASK) {
+ /*
+ * CHECK: does overrun affect the current character?
+ * ASSUMPTION: it does not.
+ */
+ *tty->flip.flag_buf_ptr++ = flg;
+ *tty->flip.char_buf_ptr++ = ch;
+ tty->flip.count++;
+ if (tty->flip.count >= TTY_FLIPBUF_SIZE)
+ goto ignore_char;
+ ch = 0;
+ flg = TTY_OVERRUN;
+ }
+#ifdef SUPPORT_SYSRQ
+ info->sysrq = 0;
+#endif
+ goto error_return;
+}
+
+static void siccuart_tx_chars(struct SICC_info *info)
+{
+ struct SICC_port *port = info->port;
+ int count;
+ unsigned char status;
+
+
+ if (info->x_char) {
+ writeb(info->x_char, port->uart_base+ BL_SICC_TBR);
+ info->state->icount.tx++;
+ info->x_char = 0;
+ return;
+ }
+ if (info->xmit.head == info->xmit.tail
+ || info->tty->stopped
+ || info->tty->hw_stopped) {
+ siccuart_disable_tx_interrupt(info);
+ writeb(status&(~_LSR_RBR_MASK),port->uart_base+BL_SICC_LSR);
+ return;
+ }
+
+ count = port->fifosize;
+ do {
+ writeb(info->xmit.buf[info->xmit.tail], port->uart_base+ BL_SICC_TBR);
+ info->xmit.tail = (info->xmit.tail + 1) & (SICC_XMIT_SIZE - 1);
+ info->state->icount.tx++;
+ if (info->xmit.head == info->xmit.tail)
+ break;
+ } while (--count > 0);
+
+ if (CIRC_CNT(info->xmit.head,
+ info->xmit.tail,
+ SICC_XMIT_SIZE) < WAKEUP_CHARS)
+ siccuart_event(info, EVT_WRITE_WAKEUP);
+
+ if (info->xmit.head == info->xmit.tail) {
+ siccuart_disable_tx_interrupt(info);
+ }
+}
+
+
+static irqreturn_t siccuart_int_rx(int irq, void *dev_id, struct pt_regs *regs)
+{
+ struct SICC_info *info = dev_id;
+ siccuart_rx_chars(info, regs);
+ return IRQ_HANDLED;
+}
+
+
+static irqreturn_t siccuart_int_tx(int irq, void *dev_id, struct pt_regs *regs)
+{
+ struct SICC_info *info = dev_id;
+ siccuart_tx_chars(info);
+ return IRQ_HANDLED;
+}
+
+static void siccuart_tasklet_action(unsigned long data)
+{
+ struct SICC_info *info = (struct SICC_info *)data;
+ struct tty_struct *tty;
+
+ tty = info->tty;
+ if (!tty || !test_and_clear_bit(EVT_WRITE_WAKEUP, &info->event))
+ return;
+
+ if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
+ tty->ldisc.write_wakeup)
+ (tty->ldisc.write_wakeup)(tty);
+ wake_up_interruptible(&tty->write_wait);
+}
+
+static int siccuart_startup(struct SICC_info *info)
+{
+ unsigned long flags;
+ unsigned long page;
+ int retval = 0;
+
+ if (info->flags & ASYNC_INITIALIZED) {
+ return 0;
+ }
+
+ page = get_zeroed_page(GFP_KERNEL);
+ if (!page)
+ return -ENOMEM;
+
+ if (info->port->uart_base == 0)
+ info->port->uart_base = (int)ioremap(info->port->uart_base_phys, PAGE_SIZE);
+ if (info->port->uart_base == 0) {
+ free_page(page);
+ return -ENOMEM;
+ }
+
+ /* lock access to info while doing setup */
+ spin_lock_irqsave(&info->state->sicc_lock,flags);
+
+ if (info->xmit.buf)
+ free_page(page);
+ else
+ info->xmit.buf = (unsigned char *) page;
+
+
+ info->mctrl = 0;
+ if (info->tty->termios->c_cflag & CBAUD)
+ info->mctrl = TIOCM_RTS | TIOCM_DTR;
+ info->port->set_mctrl(info->port, info->mctrl);
+
+ /*
+ * initialise the old status of the modem signals
+ */
+ info->old_status = 0; // UART_GET_FR(info->port) & AMBA_UARTFR_MODEM_ANY;
+
+
+ if (info->tty)
+ clear_bit(TTY_IO_ERROR, &info->tty->flags);
+ info->xmit.head = info->xmit.tail = 0;
+
+ /*
+ * Set up the tty->alt_speed kludge
+ */
+ if (info->tty) {
+ if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
+ info->tty->alt_speed = 57600;
+ if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
+ info->tty->alt_speed = 115200;
+ if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI)
+ info->tty->alt_speed = 230400;
+ if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP)
+ info->tty->alt_speed = 460800;
+ }
+
+
+ writeb( 0x00, info->port->uart_base + BL_SICC_IrCR ); // disable IrDA
+
+
+ /*
+ * and set the speed of the serial port
+ */
+ siccuart_change_speed(info, 0);
+
+ // enable rx/tx ports
+ writeb(_RCR_ER_ENABLE /*| _RCR_PME_HARD*/, info->port->uart_base + BL_SICC_RCR);
+ writeb(_TxCR_ET_ENABLE , info->port->uart_base + BL_SICC_TxCR);
+
+ readb(info->port->uart_base + BL_SICC_RBR); // clear rx port
+
+ writeb(0xf8, info->port->uart_base + BL_SICC_LSR); /* reset bits 0-4 of LSR */
+
+ /*
+ * Finally, enable interrupts
+ */
+
+ /*
+ * Allocate the IRQ
+ */
+ retval = request_irq(info->port->irqrx, siccuart_int_rx, 0, "SICC rx", info);
+ if (retval) {
+ if (capable(CAP_SYS_ADMIN)) {
+ if (info->tty)
+ set_bit(TTY_IO_ERROR, &info->tty->flags);
+ retval = 0;
+ }
+ goto errout;
+ }
+ retval = request_irq(info->port->irqtx, siccuart_int_tx, 0, "SICC tx", info);
+ if (retval) {
+ if (capable(CAP_SYS_ADMIN)) {
+ if (info->tty)
+ set_bit(TTY_IO_ERROR, &info->tty->flags);
+ retval = 0;
+ }
+ free_irq(info->port->irqrx, info);
+ goto errout;
+ }
+
+ siccuart_enable_rx_interrupt(info);
+
+ info->flags |= ASYNC_INITIALIZED;
+ spin_unlock_irqrestore(&info->state->sicc_lock,flags);
+ return 0;
+
+
+errout:
+ spin_unlock_irqrestore(&info->state->sicc_lock,flags);
+ return retval;
+}
+
+/*
+ * This routine will shutdown a serial port; interrupts are disabled, and
+ * DTR is dropped if the hangup on close termio flag is on.
+ */
+static void siccuart_shutdown(struct SICC_info *info)
+{
+ unsigned long flags;
+
+ if (!(info->flags & ASYNC_INITIALIZED))
+ return;
+
+ /* lock while shutting down port */
+ spin_lock_irqsave(&info->state->sicc_lock,flags); /* Disable interrupts */
+
+ /*
+ * clear delta_msr_wait queue to avoid mem leaks: we may free the irq
+ * here so the queue might never be woken up
+ */
+ wake_up_interruptible(&info->delta_msr_wait);
+
+ /*
+ * disable all interrupts, disable the port
+ */
+ siccuart_disable_rx_interrupt(info);
+ siccuart_disable_tx_interrupt(info);
+
+ /*
+ * Free the IRQ
+ */
+ free_irq(info->port->irqtx, info);
+ free_irq(info->port->irqrx, info);
+
+ if (info->xmit.buf) {
+ unsigned long pg = (unsigned long) info->xmit.buf;
+ info->xmit.buf = NULL;
+ free_page(pg);
+ }
+
+
+ if (!info->tty || (info->tty->termios->c_cflag & HUPCL))
+ info->mctrl &= ~(TIOCM_DTR|TIOCM_RTS);
+ info->port->set_mctrl(info->port, info->mctrl);
+
+ /* kill off our tasklet */
+ tasklet_kill(&info->tlet);
+ if (info->tty)
+ set_bit(TTY_IO_ERROR, &info->tty->flags);
+
+ info->flags &= ~ASYNC_INITIALIZED;
+
+ spin_unlock_irqrestore(&info->state->sicc_lock,flags);
+}
+
+
+static void siccuart_change_speed(struct SICC_info *info, struct termios *old_termios)
+{
+ unsigned int lcr_h, baud, quot, cflag, old_rcr, old_tcr, bits;
+ unsigned long flags;
+
+ if (!info->tty || !info->tty->termios)
+ return;
+
+ cflag = info->tty->termios->c_cflag;
+
+ pr_debug("siccuart_set_cflag(0x%x) called\n", cflag);
+ /* byte size and parity */
+ switch (cflag & CSIZE) {
+ case CS7: lcr_h = _LCR_PE_DISABLE | _LCR_DB_7_BITS | _LCR_SB_1_BIT; bits = 9; break;
+ default: lcr_h = _LCR_PE_DISABLE | _LCR_DB_8_BITS | _LCR_SB_1_BIT; bits = 10; break; // CS8
+ }
+ if (cflag & CSTOPB) {
+ lcr_h |= _LCR_SB_2_BIT;
+ bits ++;
+ }
+ if (cflag & PARENB) {
+ lcr_h |= _LCR_PE_ENABLE;
+ bits++;
+ if (!(cflag & PARODD))
+ lcr_h |= _LCR_PTY_ODD;
+ else
+ lcr_h |= _LCR_PTY_EVEN;
+ }
+
+ do {
+ /* Determine divisor based on baud rate */
+ baud = tty_get_baud_rate(info->tty);
+ if (!baud)
+ baud = 9600;
+
+
+ {
+ // here is ppc403SetBaud(com_port, baud);
+ unsigned long divisor, clockSource, temp;
+
+ /* Ensure CICCR[7] is 0 to select Internal Baud Clock */
+ powerpcMtcic_cr((unsigned long)(powerpcMfcic_cr() & 0xFEFFFFFF));
+
+ /* Determine Internal Baud Clock Frequency */
+ /* powerpcMfclkgpcr() reads DCR 0x120 - the*/
+ /* SCCR (Serial Clock Control Register) on Vesta */
+ temp = powerpcMfclkgpcr();
+
+ if(temp & 0x00000080) {
+ clockSource = 324000000;
+ }
+ else {
+ clockSource = 216000000;
+ }
+ clockSource = clockSource/(unsigned long)((temp&0x00FC0000)>>18);
+ divisor = clockSource/(16*baud) - 1;
+ /* divisor has only 12 bits of resolution */
+ if(divisor>0x00000FFF){
+ divisor=0x00000FFF;
+ }
+
+ quot = divisor;
+ }
+
+ if (baud == 38400 &&
+ ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST))
+ quot = info->state->custom_divisor;
+
+ if (!quot && old_termios) {
+ info->tty->termios->c_cflag &= ~CBAUD;
+ info->tty->termios->c_cflag |= (old_termios->c_cflag & CBAUD);
+ old_termios = NULL;
+ }
+ } while (quot == 0 && old_termios);
+
+ /* As a last resort, if the quotient is zero, default to 9600 bps */
+ if (!quot)
+ quot = (info->port->uartclk / (16 * 9600)) - 1;
+
+ info->timeout = info->port->fifosize * HZ * bits / baud;
+ info->timeout += HZ/50; /* Add .02 seconds of slop */
+
+ if (cflag & CRTSCTS)
+ info->flags |= ASYNC_CTS_FLOW;
+ else
+ info->flags &= ~ASYNC_CTS_FLOW;
+ if (cflag & CLOCAL)
+ info->flags &= ~ASYNC_CHECK_CD;
+ else
+ info->flags |= ASYNC_CHECK_CD;
+
+ /*
+ * Set up parity check flag
+ */
+#define RELEVENT_IFLAG(iflag) ((iflag) & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK))
+
+ info->read_status_mask = _LSR_OE_MASK;
+ if (I_INPCK(info->tty))
+ info->read_status_mask |= _LSR_FE_MASK | _LSR_PE_MASK;
+ if (I_BRKINT(info->tty) || I_PARMRK(info->tty))
+ info->read_status_mask |= _LSR_LB_MASK;
+
+ /*
+ * Characters to ignore
+ */
+ info->ignore_status_mask = 0;
+ if (I_IGNPAR(info->tty))
+ info->ignore_status_mask |= _LSR_FE_MASK | _LSR_PE_MASK;
+ if (I_IGNBRK(info->tty)) {
+ info->ignore_status_mask |= _LSR_LB_MASK;
+ /*
+ * If we're ignoring parity and break indicators,
+ * ignore overruns to (for real raw support).
+ */
+ if (I_IGNPAR(info->tty))
+ info->ignore_status_mask |= _LSR_OE_MASK;
+ }
+
+ /* disable interrupts while reading and clearing registers */
+ spin_lock_irqsave(&info->state->sicc_lock,flags);
+
+ old_rcr = readb(info->port->uart_base + BL_SICC_RCR);
+ old_tcr = readb(info->port->uart_base + BL_SICC_TxCR);
+
+
+ writeb(0, info->port->uart_base + BL_SICC_RCR);
+ writeb(0, info->port->uart_base + BL_SICC_TxCR);
+
+ /*RLBtrace (&ppc403Chan0, 0x2000000c, 0, 0);*/
+
+
+ spin_unlock_irqrestore(&info->state->sicc_lock,flags);
+
+
+ /* Set baud rate */
+ writeb((quot & 0x00000F00)>>8, info->port->uart_base + BL_SICC_BRDH );
+ writeb( quot & 0x00000FF, info->port->uart_base + BL_SICC_BRDL );
+
+ /* Set CTL2 reg to use external clock (ExtClk) and enable FIFOs. */
+ /* For now, do NOT use FIFOs since 403 UART did not have this */
+ /* capability and this driver was inherited from 403UART. */
+ writeb(_CTL2_EXTERN, info->port->uart_base + BL_SICC_CTL2);
+
+ writeb(lcr_h, info->port->uart_base + BL_SICC_LCR);
+
+ writeb(old_rcr, info->port->uart_base + BL_SICC_RCR); // restore rcr
+ writeb(old_tcr, info->port->uart_base + BL_SICC_TxCR); // restore txcr
+
+}
+
+
+static void siccuart_put_char(struct tty_struct *tty, u_char ch)
+{
+ struct SICC_info *info = tty->driver_data;
+ unsigned long flags;
+
+ if (!tty || !info->xmit.buf)
+ return;
+
+ /* lock info->xmit while adding character to tx buffer */
+ spin_lock_irqsave(&info->state->sicc_lock,flags);
+ if (CIRC_SPACE(info->xmit.head, info->xmit.tail, SICC_XMIT_SIZE) != 0) {
+ info->xmit.buf[info->xmit.head] = ch;
+ info->xmit.head = (info->xmit.head + 1) & (SICC_XMIT_SIZE - 1);
+ }
+ spin_unlock_irqrestore(&info->state->sicc_lock,flags);
+}
+
+static void siccuart_flush_chars(struct tty_struct *tty)
+{
+ struct SICC_info *info = tty->driver_data;
+ unsigned long flags;
+
+ if (info->xmit.head == info->xmit.tail
+ || tty->stopped
+ || tty->hw_stopped
+ || !info->xmit.buf)
+ return;
+
+ /* disable interrupts while transmitting characters */
+ spin_lock_irqsave(&info->state->sicc_lock,flags);
+ siccuart_enable_tx_interrupt(info);
+ spin_unlock_irqrestore(&info->state->sicc_lock,flags);
+}
+
+static int siccuart_write(struct tty_struct *tty,
+ const u_char * buf, int count)
+{
+ struct SICC_info *info = tty->driver_data;
+ unsigned long flags;
+ int c, ret = 0;
+
+ if (!tty || !info->xmit.buf || !tmp_buf)
+ return 0;
+
+ /* lock info->xmit while removing characters from buffer */
+ spin_lock_irqsave(&info->state->sicc_lock,flags);
+ while (1) {
+ c = CIRC_SPACE_TO_END(info->xmit.head,
+ info->xmit.tail,
+ SICC_XMIT_SIZE);
+ if (count < c)
+ c = count;
+ if (c <= 0)
+ break;
+ memcpy(info->xmit.buf + info->xmit.head, buf, c);
+ info->xmit.head = (info->xmit.head + c) &
+ (SICC_XMIT_SIZE - 1);
+ buf += c;
+ count -= c;
+ ret += c;
+ }
+ if (info->xmit.head != info->xmit.tail
+ && !tty->stopped
+ && !tty->hw_stopped)
+ siccuart_enable_tx_interrupt(info);
+ spin_unlock_irqrestore(&info->state->sicc_lock,flags);
+ return ret;
+}
+
+static int siccuart_write_room(struct tty_struct *tty)
+{
+ struct SICC_info *info = tty->driver_data;
+
+ return CIRC_SPACE(info->xmit.head, info->xmit.tail, SICC_XMIT_SIZE);
+}
+
+static int siccuart_chars_in_buffer(struct tty_struct *tty)
+{
+ struct SICC_info *info = tty->driver_data;
+
+ return CIRC_CNT(info->xmit.head, info->xmit.tail, SICC_XMIT_SIZE);
+}
+
+static void siccuart_flush_buffer(struct tty_struct *tty)
+{
+ struct SICC_info *info = tty->driver_data;
+ unsigned long flags;
+
+ pr_debug("siccuart_flush_buffer(%d) called\n", tty->index);
+ /* lock info->xmit while zeroing buffer counts */
+ spin_lock_irqsave(&info->state->sicc_lock,flags);
+ info->xmit.head = info->xmit.tail = 0;
+ spin_unlock_irqrestore(&info->state->sicc_lock,flags);
+ wake_up_interruptible(&tty->write_wait);
+ if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
+ tty->ldisc.write_wakeup)
+ (tty->ldisc.write_wakeup)(tty);
+}
+
+/*
+ * This function is used to send a high-priority XON/XOFF character to
+ * the device
+ */
+static void siccuart_send_xchar(struct tty_struct *tty, char ch)
+{
+ struct SICC_info *info = tty->driver_data;
+
+ info->x_char = ch;
+ if (ch)
+ siccuart_enable_tx_interrupt(info);
+}
+
+static void siccuart_throttle(struct tty_struct *tty)
+{
+ struct SICC_info *info = tty->driver_data;
+ unsigned long flags;
+
+ if (I_IXOFF(tty))
+ siccuart_send_xchar(tty, STOP_CHAR(tty));
+
+ if (tty->termios->c_cflag & CRTSCTS) {
+ /* disable interrupts while setting modem control lines */
+ spin_lock_irqsave(&info->state->sicc_lock,flags);
+ info->mctrl &= ~TIOCM_RTS;
+ info->port->set_mctrl(info->port, info->mctrl);
+ spin_unlock_irqrestore(&info->state->sicc_lock,flags);
+ }
+}
+
+static void siccuart_unthrottle(struct tty_struct *tty)
+{
+ struct SICC_info *info = (struct SICC_info *) tty->driver_data;
+ unsigned long flags;
+
+ if (I_IXOFF(tty)) {
+ if (info->x_char)
+ info->x_char = 0;
+ else
+ siccuart_send_xchar(tty, START_CHAR(tty));
+ }
+
+ if (tty->termios->c_cflag & CRTSCTS) {
+ /* disable interrupts while setting modem control lines */
+ spin_lock_irqsave(&info->state->sicc_lock,flags);
+ info->mctrl |= TIOCM_RTS;
+ info->port->set_mctrl(info->port, info->mctrl);
+ spin_unlock_irqrestore(&info->state->sicc_lock,flags);
+ }
+}
+
+static int get_serial_info(struct SICC_info *info, struct serial_struct *retinfo)
+{
+ struct SICC_state *state = info->state;
+ struct SICC_port *port = info->port;
+ struct serial_struct tmp;
+
+ memset(&tmp, 0, sizeof(tmp));
+ tmp.type = 0;
+ tmp.line = state->line;
+ tmp.port = port->uart_base;
+ if (HIGH_BITS_OFFSET)
+ tmp.port_high = port->uart_base >> HIGH_BITS_OFFSET;
+ tmp.irq = port->irqrx;
+ tmp.flags = 0;
+ tmp.xmit_fifo_size = port->fifosize;
+ tmp.baud_base = port->uartclk / 16;
+ tmp.close_delay = state->close_delay;
+ tmp.closing_wait = state->closing_wait;
+ tmp.custom_divisor = state->custom_divisor;
+
+ if (copy_to_user(retinfo, &tmp, sizeof(*retinfo)))
+ return -EFAULT;
+ return 0;
+}
+
+static int set_serial_info(struct SICC_info *info,
+ struct serial_struct *newinfo)
+{
+ struct serial_struct new_serial;
+ struct SICC_state *state, old_state;
+ struct SICC_port *port;
+ unsigned long new_port;
+ unsigned int i, change_irq, change_port;
+ int retval = 0;
+
+ if (copy_from_user(&new_serial, newinfo, sizeof(new_serial)))
+ return -EFAULT;
+
+ state = info->state;
+ old_state = *state;
+ port = info->port;
+
+ new_port = new_serial.port;
+ if (HIGH_BITS_OFFSET)
+ new_port += (unsigned long) new_serial.port_high << HIGH_BITS_OFFSET;
+
+ change_irq = new_serial.irq != port->irqrx;
+ change_port = new_port != port->uart_base;
+
+ if (!capable(CAP_SYS_ADMIN)) {
+ if (change_irq || change_port ||
+ (new_serial.baud_base != port->uartclk / 16) ||
+ (new_serial.close_delay != state->close_delay) ||
+ (new_serial.xmit_fifo_size != port->fifosize) ||
+ ((new_serial.flags & ~ASYNC_USR_MASK) !=
+ (state->flags & ~ASYNC_USR_MASK)))
+ return -EPERM;
+ state->flags = ((state->flags & ~ASYNC_USR_MASK) |
+ (new_serial.flags & ASYNC_USR_MASK));
+ info->flags = ((info->flags & ~ASYNC_USR_MASK) |
+ (new_serial.flags & ASYNC_USR_MASK));
+ state->custom_divisor = new_serial.custom_divisor;
+ goto check_and_exit;
+ }
+
+ if ((new_serial.irq >= NR_IRQS) || (new_serial.irq < 0) ||
+ (new_serial.baud_base < 9600))
+ return -EINVAL;
+
+ if (new_serial.type && change_port) {
+ for (i = 0; i < SERIAL_SICC_NR; i++)
+ if ((port != sicc_ports + i) &&
+ sicc_ports[i].uart_base != new_port)
+ return -EADDRINUSE;
+ }
+
+ if ((change_port || change_irq) && (state->count > 1))
+ return -EBUSY;
+
+ /*
+ * OK, past this point, all the error checking has been done.
+ * At this point, we start making changes.....
+ */
+ port->uartclk = new_serial.baud_base * 16;
+ state->flags = ((state->flags & ~ASYNC_FLAGS) |
+ (new_serial.flags & ASYNC_FLAGS));
+ info->flags = ((state->flags & ~ASYNC_INTERNAL_FLAGS) |
+ (info->flags & ASYNC_INTERNAL_FLAGS));
+ state->custom_divisor = new_serial.custom_divisor;
+ state->close_delay = new_serial.close_delay * HZ / 100;
+ state->closing_wait = new_serial.closing_wait * HZ / 100;
+ info->tty->low_latency = (info->flags & ASYNC_LOW_LATENCY) ? 1 : 0;
+ port->fifosize = new_serial.xmit_fifo_size;
+
+ if (change_port || change_irq) {
+ /*
+ * We need to shutdown the serial port at the old
+ * port/irq combination.
+ */
+ siccuart_shutdown(info);
+ port->irqrx = new_serial.irq;
+ port->uart_base = new_port;
+ }
+
+check_and_exit:
+ if (!port->uart_base)
+ return 0;
+ if (info->flags & ASYNC_INITIALIZED) {
+ if ((old_state.flags & ASYNC_SPD_MASK) !=
+ (state->flags & ASYNC_SPD_MASK) ||
+ (old_state.custom_divisor != state->custom_divisor)) {
+ if ((state->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
+ info->tty->alt_speed = 57600;
+ if ((state->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
+ info->tty->alt_speed = 115200;
+ if ((state->flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI)
+ info->tty->alt_speed = 230400;
+ if ((state->flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP)
+ info->tty->alt_speed = 460800;
+ siccuart_change_speed(info, NULL);
+ }
+ } else
+ retval = siccuart_startup(info);
+ return retval;
+}
+
+
+/*
+ * get_lsr_info - get line status register info
+ */
+static int get_lsr_info(struct SICC_info *info, unsigned int *value)
+{
+ unsigned int result, status;
+ unsigned long flags;
+
+ /* disable interrupts while reading status from port */
+ spin_lock_irqsave(&info->state->sicc_lock,flags);
+ status = readb(info->port->uart_base + BL_SICC_LSR);
+ spin_unlock_irqrestore(&info->state->sicc_lock,flags);
+ result = status & _LSR_TSR_EMPTY ? TIOCSER_TEMT : 0;
+
+ /*
+ * If we're about to load something into the transmit
+ * register, we'll pretend the transmitter isn't empty to
+ * avoid a race condition (depending on when the transmit
+ * interrupt happens).
+ */
+ if (info->x_char ||
+ ((CIRC_CNT(info->xmit.head, info->xmit.tail,
+ SICC_XMIT_SIZE) > 0) &&
+ !info->tty->stopped && !info->tty->hw_stopped))
+ result &= TIOCSER_TEMT;
+
+ return put_user(result, value);
+}
+
+static int get_modem_info(struct SICC_info *info, unsigned int *value)
+{
+ unsigned int result = info->mctrl;
+
+ return put_user(result, value);
+}
+
+static int set_modem_info(struct SICC_info *info, unsigned int cmd,
+ unsigned int *value)
+{
+ unsigned int arg, old;
+ unsigned long flags;
+
+ if (get_user(arg, value))
+ return -EFAULT;
+
+ old = info->mctrl;
+ switch (cmd) {
+ case TIOCMBIS:
+ info->mctrl |= arg;
+ break;
+
+ case TIOCMBIC:
+ info->mctrl &= ~arg;
+ break;
+
+ case TIOCMSET:
+ info->mctrl = arg;
+ break;
+
+ default:
+ return -EINVAL;
+ }
+ /* disable interrupts while setting modem control lines */
+ spin_lock_irqsave(&info->state->sicc_lock,flags);
+ if (old != info->mctrl)
+ info->port->set_mctrl(info->port, info->mctrl);
+ spin_unlock_irqrestore(&info->state->sicc_lock,flags);
+ return 0;
+}
+
+static void siccuart_break_ctl(struct tty_struct *tty, int break_state)
+{
+ struct SICC_info *info = tty->driver_data;
+ unsigned long flags;
+ unsigned int lcr_h;
+
+
+ /* disable interrupts while setting break state */
+ spin_lock_irqsave(&info->state->sicc_lock,flags);
+ lcr_h = readb(info->port + BL_SICC_LSR);
+ if (break_state == -1)
+ lcr_h |= _LSR_LB_MASK;
+ else
+ lcr_h &= ~_LSR_LB_MASK;
+ writeb(lcr_h, info->port + BL_SICC_LSRS);
+ spin_unlock_irqrestore(&info->state->sicc_lock,flags);
+}
+
+static int siccuart_ioctl(struct tty_struct *tty, struct file *file,
+ unsigned int cmd, unsigned long arg)
+{
+ struct SICC_info *info = tty->driver_data;
+ struct SICC_icount cnow;
+ struct serial_icounter_struct icount;
+ unsigned long flags;
+
+ if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) &&
+ (cmd != TIOCSERCONFIG) && (cmd != TIOCSERGSTRUCT) &&
+ (cmd != TIOCMIWAIT) && (cmd != TIOCGICOUNT)) {
+ if (tty->flags & (1 << TTY_IO_ERROR))
+ return -EIO;
+ }
+
+ switch (cmd) {
+ case TIOCMGET:
+ return get_modem_info(info, (unsigned int *)arg);
+ case TIOCMBIS:
+ case TIOCMBIC:
+ case TIOCMSET:
+ return set_modem_info(info, cmd, (unsigned int *)arg);
+ case TIOCGSERIAL:
+ return get_serial_info(info,
+ (struct serial_struct *)arg);
+ case TIOCSSERIAL:
+ return set_serial_info(info,
+ (struct serial_struct *)arg);
+ case TIOCSERGETLSR: /* Get line status register */
+ return get_lsr_info(info, (unsigned int *)arg);
+ /*
+ * Wait for any of the 4 modem inputs (DCD,RI,DSR,CTS) to change
+ * - mask passed in arg for lines of interest
+ * (use |'ed TIOCM_RNG/DSR/CD/CTS for masking)
+ * Caller should use TIOCGICOUNT to see which one it was
+ */
+ case TIOCMIWAIT:
+ return 0;
+ /*
+ * Get counter of input serial line interrupts (DCD,RI,DSR,CTS)
+ * Return: write counters to the user passed counter struct
+ * NB: both 1->0 and 0->1 transitions are counted except for
+ * RI where only 0->1 is counted.
+ */
+ case TIOCGICOUNT:
+ /* disable interrupts while getting interrupt count */
+ spin_lock_irqsave(&info->state->sicc_lock,flags);
+ cnow = info->state->icount;
+ spin_unlock_irqrestore(&info->state->sicc_lock,flags);
+ icount.cts = cnow.cts;
+ icount.dsr = cnow.dsr;
+ icount.rng = cnow.rng;
+ icount.dcd = cnow.dcd;
+ icount.rx = cnow.rx;
+ icount.tx = cnow.tx;
+ icount.frame = cnow.frame;
+ icount.overrun = cnow.overrun;
+ icount.parity = cnow.parity;
+ icount.brk = cnow.brk;
+ icount.buf_overrun = cnow.buf_overrun;
+
+ return copy_to_user((void *)arg, &icount, sizeof(icount))
+ ? -EFAULT : 0;
+
+ default:
+ return -ENOIOCTLCMD;
+ }
+ return 0;
+}
+
+static void siccuart_set_termios(struct tty_struct *tty, struct termios *old_termios)
+{
+ struct SICC_info *info = tty->driver_data;
+ unsigned long flags;
+ unsigned int cflag = tty->termios->c_cflag;
+
+ if ((cflag ^ old_termios->c_cflag) == 0 &&
+ RELEVENT_IFLAG(tty->termios->c_iflag ^ old_termios->c_iflag) == 0)
+ return;
+
+ siccuart_change_speed(info, old_termios);
+
+ /* Handle transition to B0 status */
+ if ((old_termios->c_cflag & CBAUD) &&
+ !(cflag & CBAUD)) {
+ /* disable interrupts while setting break state */
+ spin_lock_irqsave(&info->state->sicc_lock,flags);
+ info->mctrl &= ~(TIOCM_RTS | TIOCM_DTR);
+ info->port->set_mctrl(info->port, info->mctrl);
+ spin_unlock_irqrestore(&info->state->sicc_lock,flags);
+ }
+
+ /* Handle transition away from B0 status */
+ if (!(old_termios->c_cflag & CBAUD) &&
+ (cflag & CBAUD)) {
+ /* disable interrupts while setting break state */
+ spin_lock_irqsave(&info->state->sicc_lock,flags);
+ info->mctrl |= TIOCM_DTR;
+ if (!(cflag & CRTSCTS) ||
+ !test_bit(TTY_THROTTLED, &tty->flags))
+ info->mctrl |= TIOCM_RTS;
+ info->port->set_mctrl(info->port, info->mctrl);
+ spin_unlock_irqrestore(&info->state->sicc_lock,flags);
+ }
+
+ /* Handle turning off CRTSCTS */
+ if ((old_termios->c_cflag & CRTSCTS) &&
+ !(cflag & CRTSCTS)) {
+ tty->hw_stopped = 0;
+ siccuart_start(tty);
+ }
+
+#if 0
+ /*
+ * No need to wake up processes in open wait, since they
+ * sample the CLOCAL flag once, and don't recheck it.
+ * XXX It's not clear whether the current behavior is correct
+ * or not. Hence, this may change.....
+ */
+ if (!(old_termios->c_cflag & CLOCAL) &&
+ (tty->termios->c_cflag & CLOCAL))
+ wake_up_interruptible(&info->open_wait);
+#endif
+}
+
+static void siccuart_close(struct tty_struct *tty, struct file *filp)
+{
+ struct SICC_info *info = tty->driver_data;
+ struct SICC_state *state;
+ unsigned long flags;
+
+ if (!info)
+ return;
+
+ state = info->state;
+
+ //pr_debug("siccuart_close() called\n");
+
+ /* lock tty->driver_data while closing port */
+ spin_lock_irqsave(&info->state->sicc_lock,flags);
+
+ if (tty_hung_up_p(filp)) {
+ goto quick_close;
+ }
+
+ if ((tty->count == 1) && (state->count != 1)) {
+ /*
+ * Uh, oh. tty->count is 1, which means that the tty
+ * structure will be freed. state->count should always
+ * be one in these conditions. If it's greater than
+ * one, we've got real problems, since it means the
+ * serial port won't be shutdown.
+ */
+ printk("siccuart_close: bad serial port count; tty->count is 1, state->count is %d\n", state->count);
+ state->count = 1;
+ }
+ if (--state->count < 0) {
+ printk("rs_close: bad serial port count for %s: %d\n", tty->name, state->count);
+ state->count = 0;
+ }
+ if (state->count) {
+ goto quick_close;
+ }
+ info->flags |= ASYNC_CLOSING;
+ spin_unlock_irqrestore(&info->state->sicc_lock,flags);
+ /*
+ * Now we wait for the transmit buffer to clear; and we notify
+ * the line discipline to only process XON/XOFF characters.
+ */
+ tty->closing = 1;
+ if (info->state->closing_wait != ASYNC_CLOSING_WAIT_NONE)
+ tty_wait_until_sent(tty, info->state->closing_wait);
+ /*
+ * At this point, we stop accepting input. To do this, we
+ * disable the receive line status interrupts.
+ */
+ if (info->flags & ASYNC_INITIALIZED) {
+ siccuart_disable_rx_interrupt(info);
+ /*
+ * Before we drop DTR, make sure the UART transmitter
+ * has completely drained; this is especially
+ * important if there is a transmit FIFO!
+ */
+ siccuart_wait_until_sent(tty, info->timeout);
+ }
+ siccuart_shutdown(info);
+ if (tty->driver->flush_buffer)
+ tty->driver->flush_buffer(tty);
+ if (tty->ldisc.flush_buffer)
+ tty->ldisc.flush_buffer(tty);
+ tty->closing = 0;
+ info->event = 0;
+ info->tty = NULL;
+ if (info->blocked_open) {
+ if (info->state->close_delay) {
+ set_current_state(TASK_INTERRUPTIBLE);
+ schedule_timeout(info->state->close_delay);
+ }
+ wake_up_interruptible(&info->open_wait);
+ }
+ info->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING);
+ wake_up_interruptible(&info->close_wait);
+ return;
+
+quick_close:
+ spin_unlock_irqrestore(&info->state->sicc_lock,flags);
+ return;
+}
+
+static void siccuart_wait_until_sent(struct tty_struct *tty, int timeout)
+{
+ struct SICC_info *info = (struct SICC_info *) tty->driver_data;
+ unsigned long char_time, expire;
+
+ if (info->port->fifosize == 0)
+ return;
+
+ /*
+ * Set the check interval to be 1/5 of the estimated time to
+ * send a single character, and make it at least 1. The check
+ * interval should also be less than the timeout.
+ *
+ * Note: we have to use pretty tight timings here to satisfy
+ * the NIST-PCTS.
+ */
+ char_time = (info->timeout - HZ/50) / info->port->fifosize;
+ char_time = char_time / 5;
+ if (char_time == 0)
+ char_time = 1;
+
+ // Crazy!! sometimes the input arg 'timeout' can be negtive numbers :-(
+ if (timeout >= 0 && timeout < char_time)
+ char_time = timeout;
+ /*
+ * If the transmitter hasn't cleared in twice the approximate
+ * amount of time to send the entire FIFO, it probably won't
+ * ever clear. This assumes the UART isn't doing flow
+ * control, which is currently the case. Hence, if it ever
+ * takes longer than info->timeout, this is probably due to a
+ * UART bug of some kind. So, we clamp the timeout parameter at
+ * 2*info->timeout.
+ */
+ if (!timeout || timeout > 2 * info->timeout)
+ timeout = 2 * info->timeout;
+
+ expire = jiffies + timeout;
+ pr_debug("siccuart_wait_until_sent(%d), jiff=%lu, expire=%lu char_time=%lu...\n",
+ tty->index, jiffies,
+ expire, char_time);
+ while ((readb(info->port->uart_base + BL_SICC_LSR) & _LSR_TX_ALL) != _LSR_TX_ALL) {
+ set_current_state(TASK_INTERRUPTIBLE);
+ schedule_timeout(char_time);
+ if (signal_pending(current))
+ break;
+ if (timeout && time_after(jiffies, expire))
+ break;
+ }
+ set_current_state(TASK_RUNNING);
+}
+
+static void siccuart_hangup(struct tty_struct *tty)
+{
+ struct SICC_info *info = tty->driver_data;
+ struct SICC_state *state = info->state;
+
+ siccuart_flush_buffer(tty);
+ if (info->flags & ASYNC_CLOSING)
+ return;
+ siccuart_shutdown(info);
+ info->event = 0;
+ state->count = 0;
+ info->flags &= ~ASYNC_NORMAL_ACTIVE;
+ info->tty = NULL;
+ wake_up_interruptible(&info->open_wait);
+}
+
+static int block_til_ready(struct tty_struct *tty, struct file *filp,
+ struct SICC_info *info)
+{
+ DECLARE_WAITQUEUE(wait, current);
+ struct SICC_state *state = info->state;
+ unsigned long flags;
+ int do_clocal = 0, extra_count = 0, retval;
+
+ /*
+ * If the device is in the middle of being closed, then block
+ * until it's done, and then try again.
+ */
+ if (tty_hung_up_p(filp) ||
+ (info->flags & ASYNC_CLOSING)) {
+ if (info->flags & ASYNC_CLOSING)
+ interruptible_sleep_on(&info->close_wait);
+ return (info->flags & ASYNC_HUP_NOTIFY) ?
+ -EAGAIN : -ERESTARTSYS;
+ }
+
+ /*
+ * If non-blocking mode is set, or the port is not enabled,
+ * then make the check up front and then exit.
+ */
+ if ((filp->f_flags & O_NONBLOCK) ||
+ (tty->flags & (1 << TTY_IO_ERROR))) {
+ info->flags |= ASYNC_NORMAL_ACTIVE;
+ return 0;
+ }
+
+ if (tty->termios->c_cflag & CLOCAL)
+ do_clocal = 1;
+
+ /*
+ * Block waiting for the carrier detect and the line to become
+ * free (i.e., not in use by the callout). While we are in
+ * this loop, state->count is dropped by one, so that
+ * rs_close() knows when to free things. We restore it upon
+ * exit, either normal or abnormal.
+ */
+ retval = 0;
+ add_wait_queue(&info->open_wait, &wait);
+ /* lock while decrementing state->count */
+ spin_lock_irqsave(&info->state->sicc_lock,flags);
+ if (!tty_hung_up_p(filp)) {
+ extra_count = 1;
+ state->count--;
+ }
+ spin_unlock_irqrestore(&info->state->sicc_lock,flags);
+ info->blocked_open++;
+ while (1) {
+ /* disable interrupts while setting modem control lines */
+ spin_lock_irqsave(&info->state->sicc_lock,flags);
+ if (tty->termios->c_cflag & CBAUD) {
+ info->mctrl = TIOCM_DTR | TIOCM_RTS;
+ info->port->set_mctrl(info->port, info->mctrl);
+ }
+ spin_unlock_irqrestore(&info->state->sicc_lock,flags);
+ set_current_state(TASK_INTERRUPTIBLE);
+ if (tty_hung_up_p(filp) ||
+ !(info->flags & ASYNC_INITIALIZED)) {
+ if (info->flags & ASYNC_HUP_NOTIFY)
+ retval = -EAGAIN;
+ else
+ retval = -ERESTARTSYS;
+ break;
+ }
+ if (!(info->flags & ASYNC_CLOSING) &&
+ (do_clocal /*|| (UART_GET_FR(info->port) & SICC_UARTFR_DCD)*/))
+ break;
+ if (signal_pending(current)) {
+ retval = -ERESTARTSYS;
+ break;
+ }
+ schedule();
+ }
+ set_current_state(TASK_RUNNING);
+ remove_wait_queue(&info->open_wait, &wait);
+ if (extra_count)
+ state->count++;
+ info->blocked_open--;
+ if (retval)
+ return retval;
+ info->flags |= ASYNC_NORMAL_ACTIVE;
+ return 0;
+}
+
+static struct SICC_info *siccuart_get(int line)
+{
+ struct SICC_info *info;
+ struct SICC_state *state = sicc_state + line;
+
+ state->count++;
+ if (state->info)
+ return state->info;
+ info = kmalloc(sizeof(struct SICC_info), GFP_KERNEL);
+ if (info) {
+ memset(info, 0, sizeof(struct SICC_info));
+ init_waitqueue_head(&info->open_wait);
+ init_waitqueue_head(&info->close_wait);
+ init_waitqueue_head(&info->delta_msr_wait);
+ info->flags = state->flags;
+ info->state = state;
+ info->port = sicc_ports + line;
+ tasklet_init(&info->tlet, siccuart_tasklet_action,
+ (unsigned long)info);
+ }
+ if (state->info) {
+ kfree(info);
+ return state->info;
+ }
+ state->info = info;
+ return info;
+}
+
+static int siccuart_open(struct tty_struct *tty, struct file *filp)
+{
+ struct SICC_info *info;
+ int retval, line = tty->index;
+
+
+ // is this a line that we've got?
+ if (line >= SERIAL_SICC_NR) {
+ return -ENODEV;
+ }
+
+ info = siccuart_get(line);
+ if (!info)
+ return -ENOMEM;
+
+ tty->driver_data = info;
+ info->tty = tty;
+ info->tty->low_latency = (info->flags & ASYNC_LOW_LATENCY) ? 1 : 0;
+
+ /*
+ * Make sure we have the temporary buffer allocated
+ */
+ if (!tmp_buf) {
+ unsigned long page = get_zeroed_page(GFP_KERNEL);
+ if (tmp_buf)
+ free_page(page);
+ else if (!page) {
+ return -ENOMEM;
+ }
+ tmp_buf = (u_char *)page;
+ }
+
+ /*
+ * If the port is in the middle of closing, bail out now.
+ */
+ if (tty_hung_up_p(filp) ||
+ (info->flags & ASYNC_CLOSING)) {
+ if (info->flags & ASYNC_CLOSING)
+ interruptible_sleep_on(&info->close_wait);
+ return -EAGAIN;
+ }
+
+ /*
+ * Start up the serial port
+ */
+ retval = siccuart_startup(info);
+ if (retval) {
+ return retval;
+ }
+
+ retval = block_til_ready(tty, filp, info);
+ if (retval) {
+ return retval;
+ }
+
+#ifdef CONFIG_SERIAL_SICC_CONSOLE
+ if (siccuart_cons.cflag && siccuart_cons.index == line) {
+ tty->termios->c_cflag = siccuart_cons.cflag;
+ siccuart_cons.cflag = 0;
+ siccuart_change_speed(info, NULL);
+ }
+#endif
+ return 0;
+}
+
+static struct tty_operations sicc_ops = {
+ .open = siccuart_open,
+ .close = siccuart_close,
+ .write = siccuart_write,
+ .put_char = siccuart_put_char,
+ .flush_chars = siccuart_flush_chars,
+ .write_room = siccuart_write_room,
+ .chars_in_buffer = siccuart_chars_in_buffer,
+ .flush_buffer = siccuart_flush_buffer,
+ .ioctl = siccuart_ioctl,
+ .throttle = siccuart_throttle,
+ .unthrottle = siccuart_unthrottle,
+ .send_xchar = siccuart_send_xchar,
+ .set_termios = siccuart_set_termios,
+ .stop = siccuart_stop,
+ .start = siccuart_start,
+ .hangup = siccuart_hangup,
+ .break_ctl = siccuart_break_ctl,
+ .wait_until_sent = siccuart_wait_until_sent,
+};
+
+int __init siccuart_init(void)
+{
+ int i;
+ siccnormal_driver = alloc_tty_driver(SERIAL_SICC_NR);
+ if (!siccnormal_driver)
+ return -ENOMEM;
+ printk("IBM Vesta SICC serial port driver V 0.1 by Yudong Yang and Yi Ge / IBM CRL .\n");
+ siccnormal_driver->driver_name = "serial_sicc";
+ siccnormal_driver->owner = THIS_MODULE;
+ siccnormal_driver->name = SERIAL_SICC_NAME;
+ siccnormal_driver->major = SERIAL_SICC_MAJOR;
+ siccnormal_driver->minor_start = SERIAL_SICC_MINOR;
+ siccnormal_driver->type = TTY_DRIVER_TYPE_SERIAL;
+ siccnormal_driver->subtype = SERIAL_TYPE_NORMAL;
+ siccnormal_driver->init_termios = tty_std_termios;
+ siccnormal_driver->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
+ siccnormal_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_NO_DEVFS;
+ tty_set_operations(siccnormal_driver, &sicc_ops);
+
+ if (tty_register_driver(siccnormal_driver))
+ panic("Couldn't register SICC serial driver\n");
+
+ for (i = 0; i < SERIAL_SICC_NR; i++) {
+ struct SICC_state *state = sicc_state + i;
+ state->line = i;
+ state->close_delay = 5 * HZ / 10;
+ state->closing_wait = 30 * HZ;
+ spin_lock_init(&state->sicc_lock);
+ }
+
+
+ return 0;
+}
+
+__initcall(siccuart_init);
+
+#ifdef CONFIG_SERIAL_SICC_CONSOLE
+/************** console driver *****************/
+
+/*
+ * This code is currently never used; console->read is never called.
+ * Therefore, although we have an implementation, we don't use it.
+ * FIXME: the "const char *s" should be fixed to "char *s" some day.
+ * (when the definition in include/linux/console.h is also fixed)
+ */
+#ifdef used_and_not_const_char_pointer
+static int siccuart_console_read(struct console *co, const char *s, u_int count)
+{
+ struct SICC_port *port = &sicc_ports[co->index];
+ unsigned int status;
+ char *w;
+ int c;
+
+ pr_debug("siccuart_console_read() called\n");
+
+ c = 0;
+ w = s;
+ while (c < count) {
+ if(readb(port->uart_base + BL_SICC_LSR) & _LSR_RBR_FULL) {
+ *w++ = readb(port->uart_base + BL_SICC_RBR);
+ c++;
+ } else {
+ // nothing more to get, return
+ return c;
+ }
+ }
+ // return the count
+ return c;
+}
+#endif
+
+/*
+ * Print a string to the serial port trying not to disturb
+ * any possible real use of the port...
+ *
+ * The console_lock must be held when we get here.
+ */
+static void siccuart_console_write(struct console *co, const char *s, u_int count)
+{
+ struct SICC_port *port = &sicc_ports[co->index];
+ unsigned int old_cr;
+ int i;
+
+ /*
+ * First save the CR then disable the interrupts
+ */
+ old_cr = readb(port->uart_base + BL_SICC_TxCR);
+ writeb(old_cr & ~_TxCR_DME_MASK, port->uart_base + BL_SICC_TxCR);
+
+ /*
+ * Now, do each character
+ */
+ for (i = 0; i < count; i++) {
+ while ((readb(port->uart_base + BL_SICC_LSR)&_LSR_TX_ALL) != _LSR_TX_ALL);
+ writeb(s[i], port->uart_base + BL_SICC_TBR);
+ if (s[i] == '\n') {
+ while ((readb(port->uart_base + BL_SICC_LSR)&_LSR_TX_ALL) != _LSR_TX_ALL);
+ writeb('\r', port->uart_base + BL_SICC_TBR);
+ }
+ }
+
+ /*
+ * Finally, wait for transmitter to become empty
+ * and restore the TCR
+ */
+ while ((readb(port->uart_base + BL_SICC_LSR)&_LSR_TX_ALL) != _LSR_TX_ALL);
+ writeb(old_cr, port->uart_base + BL_SICC_TxCR);
+}
+
+/*
+ * Receive character from the serial port
+ */
+static int siccuart_console_wait_key(struct console *co)
+{
+ struct SICC_port *port = &sicc_ports[co->index];
+ int c;
+
+ while(!(readb(port->uart_base + BL_SICC_LSR) & _LSR_RBR_FULL));
+ c = readb(port->uart_base + BL_SICC_RBR);
+ return c;
+}
+
+static struct tty_driver *siccuart_console_device(struct console *c, int *index)
+{
+ *index = c->index;
+ return siccnormal_driver;
+}
+
+static int __init siccuart_console_setup(struct console *co, char *options)
+{
+ struct SICC_port *port;
+ int baud = 9600;
+ int bits = 8;
+ int parity = 'n';
+ u_int cflag = CREAD | HUPCL | CLOCAL;
+ u_int lcr_h, quot;
+
+
+ if (co->index >= SERIAL_SICC_NR)
+ co->index = 0;
+
+ port = &sicc_ports[co->index];
+
+ if (port->uart_base == 0)
+ port->uart_base = (int)ioremap(port->uart_base_phys, PAGE_SIZE);
+
+ if (options) {
+ char *s = options;
+ baud = simple_strtoul(s, NULL, 10);
+ while (*s >= '0' && *s <= '9')
+ s++;
+ if (*s) parity = *s++;
+ if (*s) bits = *s - '0';
+ }
+
+ /*
+ * Now construct a cflag setting.
+ */
+ switch (baud) {
+ case 1200: cflag |= B1200; break;
+ case 2400: cflag |= B2400; break;
+ case 4800: cflag |= B4800; break;
+ default: cflag |= B9600; baud = 9600; break;
+ case 19200: cflag |= B19200; break;
+ case 38400: cflag |= B38400; break;
+ case 57600: cflag |= B57600; break;
+ case 115200: cflag |= B115200; break;
+ }
+ switch (bits) {
+ case 7: cflag |= CS7; lcr_h = _LCR_PE_DISABLE | _LCR_DB_7_BITS | _LCR_SB_1_BIT; break;
+ default: cflag |= CS8; lcr_h = _LCR_PE_DISABLE | _LCR_DB_8_BITS | _LCR_SB_1_BIT; break;
+ }
+ switch (parity) {
+ case 'o':
+ case 'O': cflag |= PARODD; lcr_h |= _LCR_PTY_ODD; break;
+ case 'e':
+ case 'E': cflag |= PARENB; lcr_h |= _LCR_PE_ENABLE | _LCR_PTY_ODD; break;
+ }
+
+ co->cflag = cflag;
+
+
+ {
+ // a copy of is inserted here ppc403SetBaud(com_port, (int)9600);
+ unsigned long divisor, clockSource, temp;
+ unsigned int rate = baud;
+
+ /* Ensure CICCR[7] is 0 to select Internal Baud Clock */
+ powerpcMtcic_cr((unsigned long)(powerpcMfcic_cr() & 0xFEFFFFFF));
+
+ /* Determine Internal Baud Clock Frequency */
+ /* powerpcMfclkgpcr() reads DCR 0x120 - the*/
+ /* SCCR (Serial Clock Control Register) on Vesta */
+ temp = powerpcMfclkgpcr();
+
+ if(temp & 0x00000080) {
+ clockSource = 324000000;
+ }
+ else {
+ clockSource = 216000000;
+ }
+ clockSource = clockSource/(unsigned long)((temp&0x00FC0000)>>18);
+ divisor = clockSource/(16*rate) - 1;
+ /* divisor has only 12 bits of resolution */
+ if(divisor>0x00000FFF){
+ divisor=0x00000FFF;
+ }
+
+ quot = divisor;
+ }
+
+ writeb((quot & 0x00000F00)>>8, port->uart_base + BL_SICC_BRDH );
+ writeb( quot & 0x00000FF, port->uart_base + BL_SICC_BRDL );
+
+ /* Set CTL2 reg to use external clock (ExtClk) and enable FIFOs. */
+ /* For now, do NOT use FIFOs since 403 UART did not have this */
+ /* capability and this driver was inherited from 403UART. */
+ writeb(_CTL2_EXTERN, port->uart_base + BL_SICC_CTL2);
+
+ writeb(lcr_h, port->uart_base + BL_SICC_LCR);
+ writeb(_RCR_ER_ENABLE | _RCR_PME_HARD, port->uart_base + BL_SICC_RCR);
+ writeb( _TxCR_ET_ENABLE , port->uart_base + BL_SICC_TxCR);
+
+ // writeb(, info->port->uart_base + BL_SICC_RCR );
+ /*
+ * Transmitter Command Register: Transmitter enabled & DMA + TBR interrupt
+ * + Transmitter Empty interrupt + Transmitter error interrupt disabled &
+ * Stop mode when CTS active enabled & Transmit Break + Pattern Generation
+ * mode disabled.
+ */
+
+ writeb( 0x00, port->uart_base + BL_SICC_IrCR ); // disable IrDA
+
+ readb(port->uart_base + BL_SICC_RBR);
+
+ writeb(0xf8, port->uart_base + BL_SICC_LSR); /* reset bits 0-4 of LSR */
+
+ /* we will enable the port as we need it */
+
+ return 0;
+}
+
+static struct console siccuart_cons =
+{
+ .name = SERIAL_SICC_NAME,
+ .write = siccuart_console_write,
+#ifdef used_and_not_const_char_pointer
+ .read = siccuart_console_read,
+#endif
+ .device = siccuart_console_device,
+ .wait_key = siccuart_console_wait_key,
+ .setup = siccuart_console_setup,
+ .flags = CON_PRINTBUFFER,
+ .index = -1,
+};
+
+void __init sicc_console_init(void)
+{
+ register_console(&siccuart_cons);
+}
+
+#endif /* CONFIG_SERIAL_SICC_CONSOLE */
diff --git a/arch/ppc/8260_io/Kconfig b/arch/ppc/8260_io/Kconfig
new file mode 100644
index 0000000..ea9651e
--- /dev/null
+++ b/arch/ppc/8260_io/Kconfig
@@ -0,0 +1,65 @@
+#
+# CPM2 Communication options
+#
+
+menu "CPM2 Options"
+ depends on CPM2
+
+config SCC_ENET
+ bool "CPM SCC Ethernet"
+ depends on NET_ETHERNET
+
+#
+# CONFIG_FEC_ENET is only used to get netdevices to call our init
+# function. Any combination of FCC1,2,3 are supported.
+#
+config FEC_ENET
+ bool "FCC Ethernet"
+ depends on NET_ETHERNET
+
+config FCC1_ENET
+ bool "Ethernet on FCC1"
+ depends on FEC_ENET
+ help
+ Use CPM2 fast Ethernet controller 1 to drive Ethernet (default).
+
+config FCC2_ENET
+ bool "Ethernet on FCC2"
+ depends on FEC_ENET
+ help
+ Use CPM2 fast Ethernet controller 2 to drive Ethernet.
+
+config FCC3_ENET
+ bool "Ethernet on FCC3"
+ depends on FEC_ENET
+ help
+ Use CPM2 fast Ethernet controller 3 to drive Ethernet.
+
+config USE_MDIO
+ bool "Use MDIO for PHY configuration"
+ depends on FEC_ENET
+
+choice
+ prompt "Type of PHY"
+ depends on 8260 && USE_MDIO
+ default FCC_GENERIC_PHY
+
+config FCC_LXT970
+ bool "LXT970"
+
+config FCC_LXT971
+ bool "LXT971"
+
+config FCC_QS6612
+ bool "QS6612"
+
+config FCC_DM9131
+ bool "DM9131"
+
+config FCC_DM9161
+ bool "DM9161"
+
+config FCC_GENERIC_PHY
+ bool "Generic"
+endchoice
+endmenu
diff --git a/arch/ppc/8260_io/Makefile b/arch/ppc/8260_io/Makefile
new file mode 100644
index 0000000..971f292
--- /dev/null
+++ b/arch/ppc/8260_io/Makefile
@@ -0,0 +1,6 @@
+#
+# Makefile for the linux ppc-specific parts of comm processor (v2)
+#
+
+obj-$(CONFIG_FEC_ENET) += fcc_enet.o
+obj-$(CONFIG_SCC_ENET) += enet.o
diff --git a/arch/ppc/8260_io/enet.c b/arch/ppc/8260_io/enet.c
new file mode 100644
index 0000000..ac6d55f
--- /dev/null
+++ b/arch/ppc/8260_io/enet.c
@@ -0,0 +1,867 @@
+/*
+ * Ethernet driver for Motorola MPC8260.
+ * Copyright (c) 1999 Dan Malek (dmalek@jlc.net)
+ * Copyright (c) 2000 MontaVista Software Inc. (source@mvista.com)
+ * 2.3.99 Updates
+ *
+ * I copied this from the 8xx CPM Ethernet driver, so follow the
+ * credits back through that.
+ *
+ * This version of the driver is somewhat selectable for the different
+ * processor/board combinations. It works for the boards I know about
+ * now, and should be easily modified to include others. Some of the
+ * configuration information is contained in <asm/commproc.h> and the
+ * remainder is here.
+ *
+ * Buffer descriptors are kept in the CPM dual port RAM, and the frame
+ * buffers are in the host memory.
+ *
+ * Right now, I am very watseful with the buffers. I allocate memory
+ * pages and then divide them into 2K frame buffers. This way I know I
+ * have buffers large enough to hold one frame within one buffer descriptor.
+ * Once I get this working, I will use 64 or 128 byte CPM buffers, which
+ * will be much more memory efficient and will easily handle lots of
+ * small packets.
+ *
+ */
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/string.h>
+#include <linux/ptrace.h>
+#include <linux/errno.h>
+#include <linux/ioport.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/spinlock.h>
+#include <linux/bitops.h>
+
+#include <asm/immap_cpm2.h>
+#include <asm/pgtable.h>
+#include <asm/mpc8260.h>
+#include <asm/uaccess.h>
+#include <asm/cpm2.h>
+#include <asm/irq.h>
+
+/*
+ * Theory of Operation
+ *
+ * The MPC8260 CPM performs the Ethernet processing on an SCC. It can use
+ * an aribtrary number of buffers on byte boundaries, but must have at
+ * least two receive buffers to prevent constant overrun conditions.
+ *
+ * The buffer descriptors are allocated from the CPM dual port memory
+ * with the data buffers allocated from host memory, just like all other
+ * serial communication protocols. The host memory buffers are allocated
+ * from the free page pool, and then divided into smaller receive and
+ * transmit buffers. The size of the buffers should be a power of two,
+ * since that nicely divides the page. This creates a ring buffer
+ * structure similar to the LANCE and other controllers.
+ *
+ * Like the LANCE driver:
+ * The driver runs as two independent, single-threaded flows of control. One
+ * is the send-packet routine, which enforces single-threaded use by the
+ * cep->tx_busy flag. The other thread is the interrupt handler, which is
+ * single threaded by the hardware and other software.
+ */
+
+/* The transmitter timeout
+ */
+#define TX_TIMEOUT (2*HZ)
+
+/* The number of Tx and Rx buffers. These are allocated from the page
+ * pool. The code may assume these are power of two, so it is best
+ * to keep them that size.
+ * We don't need to allocate pages for the transmitter. We just use
+ * the skbuffer directly.
+ */
+#define CPM_ENET_RX_PAGES 4
+#define CPM_ENET_RX_FRSIZE 2048
+#define CPM_ENET_RX_FRPPG (PAGE_SIZE / CPM_ENET_RX_FRSIZE)
+#define RX_RING_SIZE (CPM_ENET_RX_FRPPG * CPM_ENET_RX_PAGES)
+#define TX_RING_SIZE 8 /* Must be power of two */
+#define TX_RING_MOD_MASK 7 /* for this to work */
+
+/* The CPM stores dest/src/type, data, and checksum for receive packets.
+ */
+#define PKT_MAXBUF_SIZE 1518
+#define PKT_MINBUF_SIZE 64
+#define PKT_MAXBLR_SIZE 1520
+
+/* The CPM buffer descriptors track the ring buffers. The rx_bd_base and
+ * tx_bd_base always point to the base of the buffer descriptors. The
+ * cur_rx and cur_tx point to the currently available buffer.
+ * The dirty_tx tracks the current buffer that is being sent by the
+ * controller. The cur_tx and dirty_tx are equal under both completely
+ * empty and completely full conditions. The empty/ready indicator in
+ * the buffer descriptor determines the actual condition.
+ */
+struct scc_enet_private {
+ /* The saved address of a sent-in-place packet/buffer, for skfree(). */
+ struct sk_buff* tx_skbuff[TX_RING_SIZE];
+ ushort skb_cur;
+ ushort skb_dirty;
+
+ /* CPM dual port RAM relative addresses.
+ */
+ cbd_t *rx_bd_base; /* Address of Rx and Tx buffers. */
+ cbd_t *tx_bd_base;
+ cbd_t *cur_rx, *cur_tx; /* The next free ring entry */
+ cbd_t *dirty_tx; /* The ring entries to be free()ed. */
+ scc_t *sccp;
+ struct net_device_stats stats;
+ uint tx_full;
+ spinlock_t lock;
+};
+
+static int scc_enet_open(struct net_device *dev);
+static int scc_enet_start_xmit(struct sk_buff *skb, struct net_device *dev);
+static int scc_enet_rx(struct net_device *dev);
+static irqreturn_t scc_enet_interrupt(int irq, void *dev_id, struct pt_regs *);
+static int scc_enet_close(struct net_device *dev);
+static struct net_device_stats *scc_enet_get_stats(struct net_device *dev);
+static void set_multicast_list(struct net_device *dev);
+
+/* These will be configurable for the SCC choice.
+*/
+#define CPM_ENET_BLOCK CPM_CR_SCC1_SBLOCK
+#define CPM_ENET_PAGE CPM_CR_SCC1_PAGE
+#define PROFF_ENET PROFF_SCC1
+#define SCC_ENET 0
+#define SIU_INT_ENET SIU_INT_SCC1
+
+/* These are both board and SCC dependent....
+*/
+#define PD_ENET_RXD ((uint)0x00000001)
+#define PD_ENET_TXD ((uint)0x00000002)
+#define PD_ENET_TENA ((uint)0x00000004)
+#define PC_ENET_RENA ((uint)0x00020000)
+#define PC_ENET_CLSN ((uint)0x00000004)
+#define PC_ENET_TXCLK ((uint)0x00000800)
+#define PC_ENET_RXCLK ((uint)0x00000400)
+#define CMX_CLK_ROUTE ((uint)0x25000000)
+#define CMX_CLK_MASK ((uint)0xff000000)
+
+/* Specific to a board.
+*/
+#define PC_EST8260_ENET_LOOPBACK ((uint)0x80000000)
+#define PC_EST8260_ENET_SQE ((uint)0x40000000)
+#define PC_EST8260_ENET_NOTFD ((uint)0x20000000)
+
+static int
+scc_enet_open(struct net_device *dev)
+{
+
+ /* I should reset the ring buffers here, but I don't yet know
+ * a simple way to do that.
+ */
+ netif_start_queue(dev);
+ return 0; /* Always succeed */
+}
+
+static int
+scc_enet_start_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+ struct scc_enet_private *cep = (struct scc_enet_private *)dev->priv;
+ volatile cbd_t *bdp;
+
+
+ /* Fill in a Tx ring entry */
+ bdp = cep->cur_tx;
+
+#ifndef final_version
+ if (bdp->cbd_sc & BD_ENET_TX_READY) {
+ /* Ooops. All transmit buffers are full. Bail out.
+ * This should not happen, since cep->tx_full should be set.
+ */
+ printk("%s: tx queue full!.\n", dev->name);
+ return 1;
+ }
+#endif
+
+ /* Clear all of the status flags.
+ */
+ bdp->cbd_sc &= ~BD_ENET_TX_STATS;
+
+ /* If the frame is short, tell CPM to pad it.
+ */
+ if (skb->len <= ETH_ZLEN)
+ bdp->cbd_sc |= BD_ENET_TX_PAD;
+ else
+ bdp->cbd_sc &= ~BD_ENET_TX_PAD;
+
+ /* Set buffer length and buffer pointer.
+ */
+ bdp->cbd_datlen = skb->len;
+ bdp->cbd_bufaddr = __pa(skb->data);
+
+ /* Save skb pointer.
+ */
+ cep->tx_skbuff[cep->skb_cur] = skb;
+
+ cep->stats.tx_bytes += skb->len;
+ cep->skb_cur = (cep->skb_cur+1) & TX_RING_MOD_MASK;
+
+ spin_lock_irq(&cep->lock);
+
+ /* Send it on its way. Tell CPM its ready, interrupt when done,
+ * its the last BD of the frame, and to put the CRC on the end.
+ */
+ bdp->cbd_sc |= (BD_ENET_TX_READY | BD_ENET_TX_INTR | BD_ENET_TX_LAST | BD_ENET_TX_TC);
+
+ dev->trans_start = jiffies;
+
+ /* If this was the last BD in the ring, start at the beginning again.
+ */
+ if (bdp->cbd_sc & BD_ENET_TX_WRAP)
+ bdp = cep->tx_bd_base;
+ else
+ bdp++;
+
+ if (bdp->cbd_sc & BD_ENET_TX_READY) {
+ netif_stop_queue(dev);
+ cep->tx_full = 1;
+ }
+
+ cep->cur_tx = (cbd_t *)bdp;
+
+ spin_unlock_irq(&cep->lock);
+
+ return 0;
+}
+
+static void
+scc_enet_timeout(struct net_device *dev)
+{
+ struct scc_enet_private *cep = (struct scc_enet_private *)dev->priv;
+
+ printk("%s: transmit timed out.\n", dev->name);
+ cep->stats.tx_errors++;
+#ifndef final_version
+ {
+ int i;
+ cbd_t *bdp;
+ printk(" Ring data dump: cur_tx %p%s cur_rx %p.\n",
+ cep->cur_tx, cep->tx_full ? " (full)" : "",
+ cep->cur_rx);
+ bdp = cep->tx_bd_base;
+ printk(" Tx @base %p :\n", bdp);
+ for (i = 0 ; i < TX_RING_SIZE; i++, bdp++)
+ printk("%04x %04x %08x\n",
+ bdp->cbd_sc,
+ bdp->cbd_datlen,
+ bdp->cbd_bufaddr);
+ bdp = cep->rx_bd_base;
+ printk(" Rx @base %p :\n", bdp);
+ for (i = 0 ; i < RX_RING_SIZE; i++, bdp++)
+ printk("%04x %04x %08x\n",
+ bdp->cbd_sc,
+ bdp->cbd_datlen,
+ bdp->cbd_bufaddr);
+ }
+#endif
+ if (!cep->tx_full)
+ netif_wake_queue(dev);
+}
+
+/* The interrupt handler.
+ * This is called from the CPM handler, not the MPC core interrupt.
+ */
+static irqreturn_t
+scc_enet_interrupt(int irq, void * dev_id, struct pt_regs * regs)
+{
+ struct net_device *dev = dev_id;
+ volatile struct scc_enet_private *cep;
+ volatile cbd_t *bdp;
+ ushort int_events;
+ int must_restart;
+
+ cep = (struct scc_enet_private *)dev->priv;
+
+ /* Get the interrupt events that caused us to be here.
+ */
+ int_events = cep->sccp->scc_scce;
+ cep->sccp->scc_scce = int_events;
+ must_restart = 0;
+
+ /* Handle receive event in its own function.
+ */
+ if (int_events & SCCE_ENET_RXF)
+ scc_enet_rx(dev_id);
+
+ /* Check for a transmit error. The manual is a little unclear
+ * about this, so the debug code until I get it figured out. It
+ * appears that if TXE is set, then TXB is not set. However,
+ * if carrier sense is lost during frame transmission, the TXE
+ * bit is set, "and continues the buffer transmission normally."
+ * I don't know if "normally" implies TXB is set when the buffer
+ * descriptor is closed.....trial and error :-).
+ */
+
+ /* Transmit OK, or non-fatal error. Update the buffer descriptors.
+ */
+ if (int_events & (SCCE_ENET_TXE | SCCE_ENET_TXB)) {
+ spin_lock(&cep->lock);
+ bdp = cep->dirty_tx;
+ while ((bdp->cbd_sc&BD_ENET_TX_READY)==0) {
+ if ((bdp==cep->cur_tx) && (cep->tx_full == 0))
+ break;
+
+ if (bdp->cbd_sc & BD_ENET_TX_HB) /* No heartbeat */
+ cep->stats.tx_heartbeat_errors++;
+ if (bdp->cbd_sc & BD_ENET_TX_LC) /* Late collision */
+ cep->stats.tx_window_errors++;
+ if (bdp->cbd_sc & BD_ENET_TX_RL) /* Retrans limit */
+ cep->stats.tx_aborted_errors++;
+ if (bdp->cbd_sc & BD_ENET_TX_UN) /* Underrun */
+ cep->stats.tx_fifo_errors++;
+ if (bdp->cbd_sc & BD_ENET_TX_CSL) /* Carrier lost */
+ cep->stats.tx_carrier_errors++;
+
+
+ /* No heartbeat or Lost carrier are not really bad errors.
+ * The others require a restart transmit command.
+ */
+ if (bdp->cbd_sc &
+ (BD_ENET_TX_LC | BD_ENET_TX_RL | BD_ENET_TX_UN)) {
+ must_restart = 1;
+ cep->stats.tx_errors++;
+ }
+
+ cep->stats.tx_packets++;
+
+ /* Deferred means some collisions occurred during transmit,
+ * but we eventually sent the packet OK.
+ */
+ if (bdp->cbd_sc & BD_ENET_TX_DEF)
+ cep->stats.collisions++;
+
+ /* Free the sk buffer associated with this last transmit.
+ */
+ dev_kfree_skb_irq(cep->tx_skbuff[cep->skb_dirty]);
+ cep->skb_dirty = (cep->skb_dirty + 1) & TX_RING_MOD_MASK;
+
+ /* Update pointer to next buffer descriptor to be transmitted.
+ */
+ if (bdp->cbd_sc & BD_ENET_TX_WRAP)
+ bdp = cep->tx_bd_base;
+ else
+ bdp++;
+
+ /* I don't know if we can be held off from processing these
+ * interrupts for more than one frame time. I really hope
+ * not. In such a case, we would now want to check the
+ * currently available BD (cur_tx) and determine if any
+ * buffers between the dirty_tx and cur_tx have also been
+ * sent. We would want to process anything in between that
+ * does not have BD_ENET_TX_READY set.
+ */
+
+ /* Since we have freed up a buffer, the ring is no longer
+ * full.
+ */
+ if (cep->tx_full) {
+ cep->tx_full = 0;
+ if (netif_queue_stopped(dev)) {
+ netif_wake_queue(dev);
+ }
+ }
+
+ cep->dirty_tx = (cbd_t *)bdp;
+ }
+
+ if (must_restart) {
+ volatile cpm_cpm2_t *cp;
+
+ /* Some transmit errors cause the transmitter to shut
+ * down. We now issue a restart transmit. Since the
+ * errors close the BD and update the pointers, the restart
+ * _should_ pick up without having to reset any of our
+ * pointers either.
+ */
+
+ cp = cpmp;
+ cp->cp_cpcr =
+ mk_cr_cmd(CPM_ENET_PAGE, CPM_ENET_BLOCK, 0,
+ CPM_CR_RESTART_TX) | CPM_CR_FLG;
+ while (cp->cp_cpcr & CPM_CR_FLG);
+ }
+ spin_unlock(&cep->lock);
+ }
+
+ /* Check for receive busy, i.e. packets coming but no place to
+ * put them. This "can't happen" because the receive interrupt
+ * is tossing previous frames.
+ */
+ if (int_events & SCCE_ENET_BSY) {
+ cep->stats.rx_dropped++;
+ printk("SCC ENET: BSY can't happen.\n");
+ }
+
+ return IRQ_HANDLED;
+}
+
+/* During a receive, the cur_rx points to the current incoming buffer.
+ * When we update through the ring, if the next incoming buffer has
+ * not been given to the system, we just set the empty indicator,
+ * effectively tossing the packet.
+ */
+static int
+scc_enet_rx(struct net_device *dev)
+{
+ struct scc_enet_private *cep;
+ volatile cbd_t *bdp;
+ struct sk_buff *skb;
+ ushort pkt_len;
+
+ cep = (struct scc_enet_private *)dev->priv;
+
+ /* First, grab all of the stats for the incoming packet.
+ * These get messed up if we get called due to a busy condition.
+ */
+ bdp = cep->cur_rx;
+
+for (;;) {
+ if (bdp->cbd_sc & BD_ENET_RX_EMPTY)
+ break;
+
+#ifndef final_version
+ /* Since we have allocated space to hold a complete frame, both
+ * the first and last indicators should be set.
+ */
+ if ((bdp->cbd_sc & (BD_ENET_RX_FIRST | BD_ENET_RX_LAST)) !=
+ (BD_ENET_RX_FIRST | BD_ENET_RX_LAST))
+ printk("CPM ENET: rcv is not first+last\n");
+#endif
+
+ /* Frame too long or too short.
+ */
+ if (bdp->cbd_sc & (BD_ENET_RX_LG | BD_ENET_RX_SH))
+ cep->stats.rx_length_errors++;
+ if (bdp->cbd_sc & BD_ENET_RX_NO) /* Frame alignment */
+ cep->stats.rx_frame_errors++;
+ if (bdp->cbd_sc & BD_ENET_RX_CR) /* CRC Error */
+ cep->stats.rx_crc_errors++;
+ if (bdp->cbd_sc & BD_ENET_RX_OV) /* FIFO overrun */
+ cep->stats.rx_crc_errors++;
+
+ /* Report late collisions as a frame error.
+ * On this error, the BD is closed, but we don't know what we
+ * have in the buffer. So, just drop this frame on the floor.
+ */
+ if (bdp->cbd_sc & BD_ENET_RX_CL) {
+ cep->stats.rx_frame_errors++;
+ }
+ else {
+
+ /* Process the incoming frame.
+ */
+ cep->stats.rx_packets++;
+ pkt_len = bdp->cbd_datlen;
+ cep->stats.rx_bytes += pkt_len;
+
+ /* This does 16 byte alignment, much more than we need.
+ * The packet length includes FCS, but we don't want to
+ * include that when passing upstream as it messes up
+ * bridging applications.
+ */
+ skb = dev_alloc_skb(pkt_len-4);
+
+ if (skb == NULL) {
+ printk("%s: Memory squeeze, dropping packet.\n", dev->name);
+ cep->stats.rx_dropped++;
+ }
+ else {
+ skb->dev = dev;
+ skb_put(skb,pkt_len-4); /* Make room */
+ eth_copy_and_sum(skb,
+ (unsigned char *)__va(bdp->cbd_bufaddr),
+ pkt_len-4, 0);
+ skb->protocol=eth_type_trans(skb,dev);
+ netif_rx(skb);
+ }
+ }
+
+ /* Clear the status flags for this buffer.
+ */
+ bdp->cbd_sc &= ~BD_ENET_RX_STATS;
+
+ /* Mark the buffer empty.
+ */
+ bdp->cbd_sc |= BD_ENET_RX_EMPTY;
+
+ /* Update BD pointer to next entry.
+ */
+ if (bdp->cbd_sc & BD_ENET_RX_WRAP)
+ bdp = cep->rx_bd_base;
+ else
+ bdp++;
+
+ }
+ cep->cur_rx = (cbd_t *)bdp;
+
+ return 0;
+}
+
+static int
+scc_enet_close(struct net_device *dev)
+{
+ /* Don't know what to do yet.
+ */
+ netif_stop_queue(dev);
+
+ return 0;
+}
+
+static struct net_device_stats *scc_enet_get_stats(struct net_device *dev)
+{
+ struct scc_enet_private *cep = (struct scc_enet_private *)dev->priv;
+
+ return &cep->stats;
+}
+
+/* Set or clear the multicast filter for this adaptor.
+ * Skeleton taken from sunlance driver.
+ * The CPM Ethernet implementation allows Multicast as well as individual
+ * MAC address filtering. Some of the drivers check to make sure it is
+ * a group multicast address, and discard those that are not. I guess I
+ * will do the same for now, but just remove the test if you want
+ * individual filtering as well (do the upper net layers want or support
+ * this kind of feature?).
+ */
+
+static void set_multicast_list(struct net_device *dev)
+{
+ struct scc_enet_private *cep;
+ struct dev_mc_list *dmi;
+ u_char *mcptr, *tdptr;
+ volatile scc_enet_t *ep;
+ int i, j;
+ cep = (struct scc_enet_private *)dev->priv;
+
+ /* Get pointer to SCC area in parameter RAM.
+ */
+ ep = (scc_enet_t *)dev->base_addr;
+
+ if (dev->flags&IFF_PROMISC) {
+
+ /* Log any net taps. */
+ printk("%s: Promiscuous mode enabled.\n", dev->name);
+ cep->sccp->scc_psmr |= SCC_PSMR_PRO;
+ } else {
+
+ cep->sccp->scc_psmr &= ~SCC_PSMR_PRO;
+
+ if (dev->flags & IFF_ALLMULTI) {
+ /* Catch all multicast addresses, so set the
+ * filter to all 1's.
+ */
+ ep->sen_gaddr1 = 0xffff;
+ ep->sen_gaddr2 = 0xffff;
+ ep->sen_gaddr3 = 0xffff;
+ ep->sen_gaddr4 = 0xffff;
+ }
+ else {
+ /* Clear filter and add the addresses in the list.
+ */
+ ep->sen_gaddr1 = 0;
+ ep->sen_gaddr2 = 0;
+ ep->sen_gaddr3 = 0;
+ ep->sen_gaddr4 = 0;
+
+ dmi = dev->mc_list;
+
+ for (i=0; i<dev->mc_count; i++) {
+
+ /* Only support group multicast for now.
+ */
+ if (!(dmi->dmi_addr[0] & 1))
+ continue;
+
+ /* The address in dmi_addr is LSB first,
+ * and taddr is MSB first. We have to
+ * copy bytes MSB first from dmi_addr.
+ */
+ mcptr = (u_char *)dmi->dmi_addr + 5;
+ tdptr = (u_char *)&ep->sen_taddrh;
+ for (j=0; j<6; j++)
+ *tdptr++ = *mcptr--;
+
+ /* Ask CPM to run CRC and set bit in
+ * filter mask.
+ */
+ cpmp->cp_cpcr = mk_cr_cmd(CPM_ENET_PAGE,
+ CPM_ENET_BLOCK, 0,
+ CPM_CR_SET_GADDR) | CPM_CR_FLG;
+ /* this delay is necessary here -- Cort */
+ udelay(10);
+ while (cpmp->cp_cpcr & CPM_CR_FLG);
+ }
+ }
+ }
+}
+
+/* Initialize the CPM Ethernet on SCC.
+ */
+static int __init scc_enet_init(void)
+{
+ struct net_device *dev;
+ struct scc_enet_private *cep;
+ int i, j, err;
+ uint dp_offset;
+ unsigned char *eap;
+ unsigned long mem_addr;
+ bd_t *bd;
+ volatile cbd_t *bdp;
+ volatile cpm_cpm2_t *cp;
+ volatile scc_t *sccp;
+ volatile scc_enet_t *ep;
+ volatile cpm2_map_t *immap;
+ volatile iop_cpm2_t *io;
+
+ cp = cpmp; /* Get pointer to Communication Processor */
+
+ immap = (cpm2_map_t *)CPM_MAP_ADDR; /* and to internal registers */
+ io = &immap->im_ioport;
+
+ bd = (bd_t *)__res;
+
+ /* Create an Ethernet device instance.
+ */
+ dev = alloc_etherdev(sizeof(*cep));
+ if (!dev)
+ return -ENOMEM;
+
+ cep = dev->priv;
+ spin_lock_init(&cep->lock);
+
+ /* Get pointer to SCC area in parameter RAM.
+ */
+ ep = (scc_enet_t *)(&immap->im_dprambase[PROFF_ENET]);
+
+ /* And another to the SCC register area.
+ */
+ sccp = (volatile scc_t *)(&immap->im_scc[SCC_ENET]);
+ cep->sccp = (scc_t *)sccp; /* Keep the pointer handy */
+
+ /* Disable receive and transmit in case someone left it running.
+ */
+ sccp->scc_gsmrl &= ~(SCC_GSMRL_ENR | SCC_GSMRL_ENT);
+
+ /* Configure port C and D pins for SCC Ethernet. This
+ * won't work for all SCC possibilities....it will be
+ * board/port specific.
+ */
+ io->iop_pparc |=
+ (PC_ENET_RENA | PC_ENET_CLSN | PC_ENET_TXCLK | PC_ENET_RXCLK);
+ io->iop_pdirc &=
+ ~(PC_ENET_RENA | PC_ENET_CLSN | PC_ENET_TXCLK | PC_ENET_RXCLK);
+ io->iop_psorc &=
+ ~(PC_ENET_RENA | PC_ENET_TXCLK | PC_ENET_RXCLK);
+ io->iop_psorc |= PC_ENET_CLSN;
+
+ io->iop_ppard |= (PD_ENET_RXD | PD_ENET_TXD | PD_ENET_TENA);
+ io->iop_pdird |= (PD_ENET_TXD | PD_ENET_TENA);
+ io->iop_pdird &= ~PD_ENET_RXD;
+ io->iop_psord |= PD_ENET_TXD;
+ io->iop_psord &= ~(PD_ENET_RXD | PD_ENET_TENA);
+
+ /* Configure Serial Interface clock routing.
+ * First, clear all SCC bits to zero, then set the ones we want.
+ */
+ immap->im_cpmux.cmx_scr &= ~CMX_CLK_MASK;
+ immap->im_cpmux.cmx_scr |= CMX_CLK_ROUTE;
+
+ /* Allocate space for the buffer descriptors in the DP ram.
+ * These are relative offsets in the DP ram address space.
+ * Initialize base addresses for the buffer descriptors.
+ */
+ dp_offset = cpm_dpalloc(sizeof(cbd_t) * RX_RING_SIZE, 8);
+ ep->sen_genscc.scc_rbase = dp_offset;
+ cep->rx_bd_base = (cbd_t *)cpm_dpram_addr(dp_offset);
+
+ dp_offset = cpm_dpalloc(sizeof(cbd_t) * TX_RING_SIZE, 8);
+ ep->sen_genscc.scc_tbase = dp_offset;
+ cep->tx_bd_base = (cbd_t *)cpm_dpram_addr(dp_offset);
+
+ cep->dirty_tx = cep->cur_tx = cep->tx_bd_base;
+ cep->cur_rx = cep->rx_bd_base;
+
+ ep->sen_genscc.scc_rfcr = CPMFCR_GBL | CPMFCR_EB;
+ ep->sen_genscc.scc_tfcr = CPMFCR_GBL | CPMFCR_EB;
+
+ /* Set maximum bytes per receive buffer.
+ * This appears to be an Ethernet frame size, not the buffer
+ * fragment size. It must be a multiple of four.
+ */
+ ep->sen_genscc.scc_mrblr = PKT_MAXBLR_SIZE;
+
+ /* Set CRC preset and mask.
+ */
+ ep->sen_cpres = 0xffffffff;
+ ep->sen_cmask = 0xdebb20e3;
+
+ ep->sen_crcec = 0; /* CRC Error counter */
+ ep->sen_alec = 0; /* alignment error counter */
+ ep->sen_disfc = 0; /* discard frame counter */
+
+ ep->sen_pads = 0x8888; /* Tx short frame pad character */
+ ep->sen_retlim = 15; /* Retry limit threshold */
+
+ ep->sen_maxflr = PKT_MAXBUF_SIZE; /* maximum frame length register */
+ ep->sen_minflr = PKT_MINBUF_SIZE; /* minimum frame length register */
+
+ ep->sen_maxd1 = PKT_MAXBLR_SIZE; /* maximum DMA1 length */
+ ep->sen_maxd2 = PKT_MAXBLR_SIZE; /* maximum DMA2 length */
+
+ /* Clear hash tables.
+ */
+ ep->sen_gaddr1 = 0;
+ ep->sen_gaddr2 = 0;
+ ep->sen_gaddr3 = 0;
+ ep->sen_gaddr4 = 0;
+ ep->sen_iaddr1 = 0;
+ ep->sen_iaddr2 = 0;
+ ep->sen_iaddr3 = 0;
+ ep->sen_iaddr4 = 0;
+
+ /* Set Ethernet station address.
+ *
+ * This is supplied in the board information structure, so we
+ * copy that into the controller.
+ */
+ eap = (unsigned char *)&(ep->sen_paddrh);
+ for (i=5; i>=0; i--)
+ *eap++ = dev->dev_addr[i] = bd->bi_enetaddr[i];
+
+ ep->sen_pper = 0; /* 'cause the book says so */
+ ep->sen_taddrl = 0; /* temp address (LSB) */
+ ep->sen_taddrm = 0;
+ ep->sen_taddrh = 0; /* temp address (MSB) */
+
+ /* Now allocate the host memory pages and initialize the
+ * buffer descriptors.
+ */
+ bdp = cep->tx_bd_base;
+ for (i=0; i<TX_RING_SIZE; i++) {
+
+ /* Initialize the BD for every fragment in the page.
+ */
+ bdp->cbd_sc = 0;
+ bdp->cbd_bufaddr = 0;
+ bdp++;
+ }
+
+ /* Set the last buffer to wrap.
+ */
+ bdp--;
+ bdp->cbd_sc |= BD_SC_WRAP;
+
+ bdp = cep->rx_bd_base;
+ for (i=0; i<CPM_ENET_RX_PAGES; i++) {
+
+ /* Allocate a page.
+ */
+ mem_addr = __get_free_page(GFP_KERNEL);
+ /* BUG: no check for failure */
+
+ /* Initialize the BD for every fragment in the page.
+ */
+ for (j=0; j<CPM_ENET_RX_FRPPG; j++) {
+ bdp->cbd_sc = BD_ENET_RX_EMPTY | BD_ENET_RX_INTR;
+ bdp->cbd_bufaddr = __pa(mem_addr);
+ mem_addr += CPM_ENET_RX_FRSIZE;
+ bdp++;
+ }
+ }
+
+ /* Set the last buffer to wrap.
+ */
+ bdp--;
+ bdp->cbd_sc |= BD_SC_WRAP;
+
+ /* Let's re-initialize the channel now. We have to do it later
+ * than the manual describes because we have just now finished
+ * the BD initialization.
+ */
+ cpmp->cp_cpcr = mk_cr_cmd(CPM_ENET_PAGE, CPM_ENET_BLOCK, 0,
+ CPM_CR_INIT_TRX) | CPM_CR_FLG;
+ while (cp->cp_cpcr & CPM_CR_FLG);
+
+ cep->skb_cur = cep->skb_dirty = 0;
+
+ sccp->scc_scce = 0xffff; /* Clear any pending events */
+
+ /* Enable interrupts for transmit error, complete frame
+ * received, and any transmit buffer we have also set the
+ * interrupt flag.
+ */
+ sccp->scc_sccm = (SCCE_ENET_TXE | SCCE_ENET_RXF | SCCE_ENET_TXB);
+
+ /* Install our interrupt handler.
+ */
+ request_irq(SIU_INT_ENET, scc_enet_interrupt, 0, "enet", dev);
+ /* BUG: no check for failure */
+
+ /* Set GSMR_H to enable all normal operating modes.
+ * Set GSMR_L to enable Ethernet to MC68160.
+ */
+ sccp->scc_gsmrh = 0;
+ sccp->scc_gsmrl = (SCC_GSMRL_TCI | SCC_GSMRL_TPL_48 | SCC_GSMRL_TPP_10 | SCC_GSMRL_MODE_ENET);
+
+ /* Set sync/delimiters.
+ */
+ sccp->scc_dsr = 0xd555;
+
+ /* Set processing mode. Use Ethernet CRC, catch broadcast, and
+ * start frame search 22 bit times after RENA.
+ */
+ sccp->scc_psmr = (SCC_PSMR_ENCRC | SCC_PSMR_NIB22);
+
+ /* It is now OK to enable the Ethernet transmitter.
+ * Unfortunately, there are board implementation differences here.
+ */
+ io->iop_pparc &= ~(PC_EST8260_ENET_LOOPBACK |
+ PC_EST8260_ENET_SQE | PC_EST8260_ENET_NOTFD);
+ io->iop_psorc &= ~(PC_EST8260_ENET_LOOPBACK |
+ PC_EST8260_ENET_SQE | PC_EST8260_ENET_NOTFD);
+ io->iop_pdirc |= (PC_EST8260_ENET_LOOPBACK |
+ PC_EST8260_ENET_SQE | PC_EST8260_ENET_NOTFD);
+ io->iop_pdatc &= ~(PC_EST8260_ENET_LOOPBACK | PC_EST8260_ENET_SQE);
+ io->iop_pdatc |= PC_EST8260_ENET_NOTFD;
+
+ dev->base_addr = (unsigned long)ep;
+
+ /* The CPM Ethernet specific entries in the device structure. */
+ dev->open = scc_enet_open;
+ dev->hard_start_xmit = scc_enet_start_xmit;
+ dev->tx_timeout = scc_enet_timeout;
+ dev->watchdog_timeo = TX_TIMEOUT;
+ dev->stop = scc_enet_close;
+ dev->get_stats = scc_enet_get_stats;
+ dev->set_multicast_list = set_multicast_list;
+
+ /* And last, enable the transmit and receive processing.
+ */
+ sccp->scc_gsmrl |= (SCC_GSMRL_ENR | SCC_GSMRL_ENT);
+
+ err = register_netdev(dev);
+ if (err) {
+ free_netdev(dev);
+ return err;
+ }
+
+ printk("%s: SCC ENET Version 0.1, ", dev->name);
+ for (i=0; i<5; i++)
+ printk("%02x:", dev->dev_addr[i]);
+ printk("%02x\n", dev->dev_addr[5]);
+
+ return 0;
+}
+
+module_init(scc_enet_init);
diff --git a/arch/ppc/8260_io/fcc_enet.c b/arch/ppc/8260_io/fcc_enet.c
new file mode 100644
index 0000000..2086c6a
--- /dev/null
+++ b/arch/ppc/8260_io/fcc_enet.c
@@ -0,0 +1,2395 @@
+/*
+ * Fast Ethernet Controller (FCC) driver for Motorola MPC8260.
+ * Copyright (c) 2000 MontaVista Software, Inc. Dan Malek (dmalek@jlc.net)
+ *
+ * This version of the driver is a combination of the 8xx fec and
+ * 8260 SCC Ethernet drivers. This version has some additional
+ * configuration options, which should probably be moved out of
+ * here. This driver currently works for the EST SBC8260,
+ * SBS Diablo/BCM, Embedded Planet RPX6, TQM8260, and others.
+ *
+ * Right now, I am very watseful with the buffers. I allocate memory
+ * pages and then divide them into 2K frame buffers. This way I know I
+ * have buffers large enough to hold one frame within one buffer descriptor.
+ * Once I get this working, I will use 64 or 128 byte CPM buffers, which
+ * will be much more memory efficient and will easily handle lots of
+ * small packets. Since this is a cache coherent processor and CPM,
+ * I could also preallocate SKB's and use them directly on the interface.
+ *
+ * 2004-12 Leo Li (leoli@freescale.com)
+ * - Rework the FCC clock configuration part, make it easier to configure.
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/string.h>
+#include <linux/ptrace.h>
+#include <linux/errno.h>
+#include <linux/ioport.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/spinlock.h>
+#include <linux/mii.h>
+#include <linux/workqueue.h>
+#include <linux/bitops.h>
+
+#include <asm/immap_cpm2.h>
+#include <asm/pgtable.h>
+#include <asm/mpc8260.h>
+#include <asm/irq.h>
+#include <asm/uaccess.h>
+#include <asm/signal.h>
+
+/* We can't use the PHY interrupt if we aren't using MDIO. */
+#if !defined(CONFIG_USE_MDIO)
+#undef PHY_INTERRUPT
+#endif
+
+/* If we have a PHY interrupt, we will advertise both full-duplex and half-
+ * duplex capabilities. If we don't have a PHY interrupt, then we will only
+ * advertise half-duplex capabilities.
+ */
+#define MII_ADVERTISE_HALF (ADVERTISE_100HALF | ADVERTISE_10HALF | \
+ ADVERTISE_CSMA)
+#define MII_ADVERTISE_ALL (ADVERTISE_100FULL | ADVERTISE_10FULL | \
+ MII_ADVERTISE_HALF)
+#ifdef PHY_INTERRUPT
+#define MII_ADVERTISE_DEFAULT MII_ADVERTISE_ALL
+#else
+#define MII_ADVERTISE_DEFAULT MII_ADVERTISE_HALF
+#endif
+#include <asm/cpm2.h>
+
+/* The transmitter timeout
+ */
+#define TX_TIMEOUT (2*HZ)
+
+#ifdef CONFIG_USE_MDIO
+/* Forward declarations of some structures to support different PHYs */
+
+typedef struct {
+ uint mii_data;
+ void (*funct)(uint mii_reg, struct net_device *dev);
+} phy_cmd_t;
+
+typedef struct {
+ uint id;
+ char *name;
+
+ const phy_cmd_t *config;
+ const phy_cmd_t *startup;
+ const phy_cmd_t *ack_int;
+ const phy_cmd_t *shutdown;
+} phy_info_t;
+
+/* values for phy_status */
+
+#define PHY_CONF_ANE 0x0001 /* 1 auto-negotiation enabled */
+#define PHY_CONF_LOOP 0x0002 /* 1 loopback mode enabled */
+#define PHY_CONF_SPMASK 0x00f0 /* mask for speed */
+#define PHY_CONF_10HDX 0x0010 /* 10 Mbit half duplex supported */
+#define PHY_CONF_10FDX 0x0020 /* 10 Mbit full duplex supported */
+#define PHY_CONF_100HDX 0x0040 /* 100 Mbit half duplex supported */
+#define PHY_CONF_100FDX 0x0080 /* 100 Mbit full duplex supported */
+
+#define PHY_STAT_LINK 0x0100 /* 1 up - 0 down */
+#define PHY_STAT_FAULT 0x0200 /* 1 remote fault */
+#define PHY_STAT_ANC 0x0400 /* 1 auto-negotiation complete */
+#define PHY_STAT_SPMASK 0xf000 /* mask for speed */
+#define PHY_STAT_10HDX 0x1000 /* 10 Mbit half duplex selected */
+#define PHY_STAT_10FDX 0x2000 /* 10 Mbit full duplex selected */
+#define PHY_STAT_100HDX 0x4000 /* 100 Mbit half duplex selected */
+#define PHY_STAT_100FDX 0x8000 /* 100 Mbit full duplex selected */
+#endif /* CONFIG_USE_MDIO */
+
+/* The number of Tx and Rx buffers. These are allocated from the page
+ * pool. The code may assume these are power of two, so it is best
+ * to keep them that size.
+ * We don't need to allocate pages for the transmitter. We just use
+ * the skbuffer directly.
+ */
+#define FCC_ENET_RX_PAGES 16
+#define FCC_ENET_RX_FRSIZE 2048
+#define FCC_ENET_RX_FRPPG (PAGE_SIZE / FCC_ENET_RX_FRSIZE)
+#define RX_RING_SIZE (FCC_ENET_RX_FRPPG * FCC_ENET_RX_PAGES)
+#define TX_RING_SIZE 16 /* Must be power of two */
+#define TX_RING_MOD_MASK 15 /* for this to work */
+
+/* The FCC stores dest/src/type, data, and checksum for receive packets.
+ * size includes support for VLAN
+ */
+#define PKT_MAXBUF_SIZE 1522
+#define PKT_MINBUF_SIZE 64
+
+/* Maximum input DMA size. Must be a should(?) be a multiple of 4.
+ * size includes support for VLAN
+ */
+#define PKT_MAXDMA_SIZE 1524
+
+/* Maximum input buffer size. Must be a multiple of 32.
+*/
+#define PKT_MAXBLR_SIZE 1536
+
+static int fcc_enet_open(struct net_device *dev);
+static int fcc_enet_start_xmit(struct sk_buff *skb, struct net_device *dev);
+static int fcc_enet_rx(struct net_device *dev);
+static irqreturn_t fcc_enet_interrupt(int irq, void *dev_id, struct pt_regs *);
+static int fcc_enet_close(struct net_device *dev);
+static struct net_device_stats *fcc_enet_get_stats(struct net_device *dev);
+/* static void set_multicast_list(struct net_device *dev); */
+static void fcc_restart(struct net_device *dev, int duplex);
+static void fcc_stop(struct net_device *dev);
+static int fcc_enet_set_mac_address(struct net_device *dev, void *addr);
+
+/* These will be configurable for the FCC choice.
+ * Multiple ports can be configured. There is little choice among the
+ * I/O pins to the PHY, except the clocks. We will need some board
+ * dependent clock selection.
+ * Why in the hell did I put these inside #ifdef's? I dunno, maybe to
+ * help show what pins are used for each device.
+ */
+
+/* Since the CLK setting changes greatly from board to board, I changed
+ * it to a easy way. You just need to specify which CLK number to use.
+ * Note that only limited choices can be make on each port.
+ */
+
+/* FCC1 Clock Source Configuration. There are board specific.
+ Can only choose from CLK9-12 */
+#ifdef CONFIG_SBC82xx
+#define F1_RXCLK 9
+#define F1_TXCLK 10
+#elif defined(CONFIG_ADS8272)
+#define F1_RXCLK 11
+#define F1_TXCLK 10
+#else
+#define F1_RXCLK 12
+#define F1_TXCLK 11
+#endif
+
+/* FCC2 Clock Source Configuration. There are board specific.
+ Can only choose from CLK13-16 */
+#ifdef CONFIG_ADS8272
+#define F2_RXCLK 15
+#define F2_TXCLK 16
+#else
+#define F2_RXCLK 13
+#define F2_TXCLK 14
+#endif
+
+/* FCC3 Clock Source Configuration. There are board specific.
+ Can only choose from CLK13-16 */
+#define F3_RXCLK 15
+#define F3_TXCLK 16
+
+/* Automatically generates register configurations */
+#define PC_CLK(x) ((uint)(1<<(x-1))) /* FCC CLK I/O ports */
+
+#define CMXFCR_RF1CS(x) ((uint)((x-5)<<27)) /* FCC1 Receive Clock Source */
+#define CMXFCR_TF1CS(x) ((uint)((x-5)<<24)) /* FCC1 Transmit Clock Source */
+#define CMXFCR_RF2CS(x) ((uint)((x-9)<<19)) /* FCC2 Receive Clock Source */
+#define CMXFCR_TF2CS(x) ((uint)((x-9)<<16)) /* FCC2 Transmit Clock Source */
+#define CMXFCR_RF3CS(x) ((uint)((x-9)<<11)) /* FCC3 Receive Clock Source */
+#define CMXFCR_TF3CS(x) ((uint)((x-9)<<8)) /* FCC3 Transmit Clock Source */
+
+#define PC_F1RXCLK PC_CLK(F1_RXCLK)
+#define PC_F1TXCLK PC_CLK(F1_TXCLK)
+#define CMX1_CLK_ROUTE (CMXFCR_RF1CS(F1_RXCLK) | CMXFCR_TF1CS(F1_TXCLK))
+#define CMX1_CLK_MASK ((uint)0xff000000)
+
+#define PC_F2RXCLK PC_CLK(F2_RXCLK)
+#define PC_F2TXCLK PC_CLK(F2_TXCLK)
+#define CMX2_CLK_ROUTE (CMXFCR_RF2CS(F2_RXCLK) | CMXFCR_TF2CS(F2_TXCLK))
+#define CMX2_CLK_MASK ((uint)0x00ff0000)
+
+#define PC_F3RXCLK PC_CLK(F3_RXCLK)
+#define PC_F3TXCLK PC_CLK(F3_TXCLK)
+#define CMX3_CLK_ROUTE (CMXFCR_RF3CS(F3_RXCLK) | CMXFCR_TF3CS(F3_TXCLK))
+#define CMX3_CLK_MASK ((uint)0x0000ff00)
+
+
+/* I/O Pin assignment for FCC1. I don't yet know the best way to do this,
+ * but there is little variation among the choices.
+ */
+#define PA1_COL ((uint)0x00000001)
+#define PA1_CRS ((uint)0x00000002)
+#define PA1_TXER ((uint)0x00000004)
+#define PA1_TXEN ((uint)0x00000008)
+#define PA1_RXDV ((uint)0x00000010)
+#define PA1_RXER ((uint)0x00000020)
+#define PA1_TXDAT ((uint)0x00003c00)
+#define PA1_RXDAT ((uint)0x0003c000)
+#define PA1_PSORA_BOUT (PA1_RXDAT | PA1_TXDAT)
+#define PA1_PSORA_BIN (PA1_COL | PA1_CRS | PA1_TXER | PA1_TXEN | \
+ PA1_RXDV | PA1_RXER)
+#define PA1_DIRA_BOUT (PA1_RXDAT | PA1_CRS | PA1_COL | PA1_RXER | PA1_RXDV)
+#define PA1_DIRA_BIN (PA1_TXDAT | PA1_TXEN | PA1_TXER)
+
+
+/* I/O Pin assignment for FCC2. I don't yet know the best way to do this,
+ * but there is little variation among the choices.
+ */
+#define PB2_TXER ((uint)0x00000001)
+#define PB2_RXDV ((uint)0x00000002)
+#define PB2_TXEN ((uint)0x00000004)
+#define PB2_RXER ((uint)0x00000008)
+#define PB2_COL ((uint)0x00000010)
+#define PB2_CRS ((uint)0x00000020)
+#define PB2_TXDAT ((uint)0x000003c0)
+#define PB2_RXDAT ((uint)0x00003c00)
+#define PB2_PSORB_BOUT (PB2_RXDAT | PB2_TXDAT | PB2_CRS | PB2_COL | \
+ PB2_RXER | PB2_RXDV | PB2_TXER)
+#define PB2_PSORB_BIN (PB2_TXEN)
+#define PB2_DIRB_BOUT (PB2_RXDAT | PB2_CRS | PB2_COL | PB2_RXER | PB2_RXDV)
+#define PB2_DIRB_BIN (PB2_TXDAT | PB2_TXEN | PB2_TXER)
+
+
+/* I/O Pin assignment for FCC3. I don't yet know the best way to do this,
+ * but there is little variation among the choices.
+ */
+#define PB3_RXDV ((uint)0x00004000)
+#define PB3_RXER ((uint)0x00008000)
+#define PB3_TXER ((uint)0x00010000)
+#define PB3_TXEN ((uint)0x00020000)
+#define PB3_COL ((uint)0x00040000)
+#define PB3_CRS ((uint)0x00080000)
+#ifndef CONFIG_RPX8260
+#define PB3_TXDAT ((uint)0x0f000000)
+#define PC3_TXDAT ((uint)0x00000000)
+#else
+#define PB3_TXDAT ((uint)0x0f000000)
+#define PC3_TXDAT 0
+#endif
+#define PB3_RXDAT ((uint)0x00f00000)
+#define PB3_PSORB_BOUT (PB3_RXDAT | PB3_TXDAT | PB3_CRS | PB3_COL | \
+ PB3_RXER | PB3_RXDV | PB3_TXER | PB3_TXEN)
+#define PB3_PSORB_BIN (0)
+#define PB3_DIRB_BOUT (PB3_RXDAT | PB3_CRS | PB3_COL | PB3_RXER | PB3_RXDV)
+#define PB3_DIRB_BIN (PB3_TXDAT | PB3_TXEN | PB3_TXER)
+
+#define PC3_PSORC_BOUT (PC3_TXDAT)
+#define PC3_PSORC_BIN (0)
+#define PC3_DIRC_BOUT (0)
+#define PC3_DIRC_BIN (PC3_TXDAT)
+
+
+/* MII status/control serial interface.
+*/
+#if defined(CONFIG_RPX8260)
+/* The EP8260 doesn't use Port C for MDIO */
+#define PC_MDIO ((uint)0x00000000)
+#define PC_MDCK ((uint)0x00000000)
+#elif defined(CONFIG_TQM8260)
+/* TQM8260 has MDIO and MDCK on PC30 and PC31 respectively */
+#define PC_MDIO ((uint)0x00000002)
+#define PC_MDCK ((uint)0x00000001)
+#elif defined(CONFIG_ADS8272)
+#define PC_MDIO ((uint)0x00002000)
+#define PC_MDCK ((uint)0x00001000)
+#elif defined(CONFIG_EST8260) || defined(CONFIG_ADS8260) || defined(CONFIG_PQ2FADS)
+#define PC_MDIO ((uint)0x00400000)
+#define PC_MDCK ((uint)0x00200000)
+#else
+#define PC_MDIO ((uint)0x00000004)
+#define PC_MDCK ((uint)0x00000020)
+#endif
+
+#if defined(CONFIG_USE_MDIO) && (!defined(PC_MDIO) || !defined(PC_MDCK))
+#error "Must define PC_MDIO and PC_MDCK if using MDIO"
+#endif
+
+/* PHY addresses */
+/* default to dynamic config of phy addresses */
+#define FCC1_PHY_ADDR 0
+#ifdef CONFIG_PQ2FADS
+#define FCC2_PHY_ADDR 0
+#else
+#define FCC2_PHY_ADDR 2
+#endif
+#define FCC3_PHY_ADDR 3
+
+/* A table of information for supporting FCCs. This does two things.
+ * First, we know how many FCCs we have and they are always externally
+ * numbered from zero. Second, it holds control register and I/O
+ * information that could be different among board designs.
+ */
+typedef struct fcc_info {
+ uint fc_fccnum;
+ uint fc_phyaddr;
+ uint fc_cpmblock;
+ uint fc_cpmpage;
+ uint fc_proff;
+ uint fc_interrupt;
+ uint fc_trxclocks;
+ uint fc_clockroute;
+ uint fc_clockmask;
+ uint fc_mdio;
+ uint fc_mdck;
+} fcc_info_t;
+
+static fcc_info_t fcc_ports[] = {
+#ifdef CONFIG_FCC1_ENET
+ { 0, FCC1_PHY_ADDR, CPM_CR_FCC1_SBLOCK, CPM_CR_FCC1_PAGE, PROFF_FCC1, SIU_INT_FCC1,
+ (PC_F1RXCLK | PC_F1TXCLK), CMX1_CLK_ROUTE, CMX1_CLK_MASK,
+ PC_MDIO, PC_MDCK },
+#endif
+#ifdef CONFIG_FCC2_ENET
+ { 1, FCC2_PHY_ADDR, CPM_CR_FCC2_SBLOCK, CPM_CR_FCC2_PAGE, PROFF_FCC2, SIU_INT_FCC2,
+ (PC_F2RXCLK | PC_F2TXCLK), CMX2_CLK_ROUTE, CMX2_CLK_MASK,
+ PC_MDIO, PC_MDCK },
+#endif
+#ifdef CONFIG_FCC3_ENET
+ { 2, FCC3_PHY_ADDR, CPM_CR_FCC3_SBLOCK, CPM_CR_FCC3_PAGE, PROFF_FCC3, SIU_INT_FCC3,
+ (PC_F3RXCLK | PC_F3TXCLK), CMX3_CLK_ROUTE, CMX3_CLK_MASK,
+ PC_MDIO, PC_MDCK },
+#endif
+};
+
+/* The FCC buffer descriptors track the ring buffers. The rx_bd_base and
+ * tx_bd_base always point to the base of the buffer descriptors. The
+ * cur_rx and cur_tx point to the currently available buffer.
+ * The dirty_tx tracks the current buffer that is being sent by the
+ * controller. The cur_tx and dirty_tx are equal under both completely
+ * empty and completely full conditions. The empty/ready indicator in
+ * the buffer descriptor determines the actual condition.
+ */
+struct fcc_enet_private {
+ /* The saved address of a sent-in-place packet/buffer, for skfree(). */
+ struct sk_buff* tx_skbuff[TX_RING_SIZE];
+ ushort skb_cur;
+ ushort skb_dirty;
+
+ /* CPM dual port RAM relative addresses.
+ */
+ cbd_t *rx_bd_base; /* Address of Rx and Tx buffers. */
+ cbd_t *tx_bd_base;
+ cbd_t *cur_rx, *cur_tx; /* The next free ring entry */
+ cbd_t *dirty_tx; /* The ring entries to be free()ed. */
+ volatile fcc_t *fccp;
+ volatile fcc_enet_t *ep;
+ struct net_device_stats stats;
+ uint tx_free;
+ spinlock_t lock;
+
+#ifdef CONFIG_USE_MDIO
+ uint phy_id;
+ uint phy_id_done;
+ uint phy_status;
+ phy_info_t *phy;
+ struct work_struct phy_relink;
+ struct work_struct phy_display_config;
+
+ uint sequence_done;
+
+ uint phy_addr;
+#endif /* CONFIG_USE_MDIO */
+
+ int link;
+ int old_link;
+ int full_duplex;
+
+ fcc_info_t *fip;
+};
+
+static void init_fcc_shutdown(fcc_info_t *fip, struct fcc_enet_private *cep,
+ volatile cpm2_map_t *immap);
+static void init_fcc_startup(fcc_info_t *fip, struct net_device *dev);
+static void init_fcc_ioports(fcc_info_t *fip, volatile iop_cpm2_t *io,
+ volatile cpm2_map_t *immap);
+static void init_fcc_param(fcc_info_t *fip, struct net_device *dev,
+ volatile cpm2_map_t *immap);
+
+#ifdef CONFIG_USE_MDIO
+static int mii_queue(struct net_device *dev, int request, void (*func)(uint, struct net_device *));
+static uint mii_send_receive(fcc_info_t *fip, uint cmd);
+static void mii_do_cmd(struct net_device *dev, const phy_cmd_t *c);
+
+/* Make MII read/write commands for the FCC.
+*/
+#define mk_mii_read(REG) (0x60020000 | (((REG) & 0x1f) << 18))
+#define mk_mii_write(REG, VAL) (0x50020000 | (((REG) & 0x1f) << 18) | \
+ ((VAL) & 0xffff))
+#define mk_mii_end 0
+#endif /* CONFIG_USE_MDIO */
+
+
+static int
+fcc_enet_start_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+ struct fcc_enet_private *cep = (struct fcc_enet_private *)dev->priv;
+ volatile cbd_t *bdp;
+
+ /* Fill in a Tx ring entry */
+ bdp = cep->cur_tx;
+
+#ifndef final_version
+ if (!cep->tx_free || (bdp->cbd_sc & BD_ENET_TX_READY)) {
+ /* Ooops. All transmit buffers are full. Bail out.
+ * This should not happen, since the tx queue should be stopped.
+ */
+ printk("%s: tx queue full!.\n", dev->name);
+ return 1;
+ }
+#endif
+
+ /* Clear all of the status flags. */
+ bdp->cbd_sc &= ~BD_ENET_TX_STATS;
+
+ /* If the frame is short, tell CPM to pad it. */
+ if (skb->len <= ETH_ZLEN)
+ bdp->cbd_sc |= BD_ENET_TX_PAD;
+ else
+ bdp->cbd_sc &= ~BD_ENET_TX_PAD;
+
+ /* Set buffer length and buffer pointer. */
+ bdp->cbd_datlen = skb->len;
+ bdp->cbd_bufaddr = __pa(skb->data);
+
+ spin_lock_irq(&cep->lock);
+
+ /* Save skb pointer. */
+ cep->tx_skbuff[cep->skb_cur] = skb;
+
+ cep->stats.tx_bytes += skb->len;
+ cep->skb_cur = (cep->skb_cur+1) & TX_RING_MOD_MASK;
+
+ /* Send it on its way. Tell CPM its ready, interrupt when done,
+ * its the last BD of the frame, and to put the CRC on the end.
+ */
+ bdp->cbd_sc |= (BD_ENET_TX_READY | BD_ENET_TX_INTR | BD_ENET_TX_LAST | BD_ENET_TX_TC);
+
+#if 0
+ /* Errata says don't do this. */
+ cep->fccp->fcc_ftodr = 0x8000;
+#endif
+ dev->trans_start = jiffies;
+
+ /* If this was the last BD in the ring, start at the beginning again. */
+ if (bdp->cbd_sc & BD_ENET_TX_WRAP)
+ bdp = cep->tx_bd_base;
+ else
+ bdp++;
+
+ if (!--cep->tx_free)
+ netif_stop_queue(dev);
+
+ cep->cur_tx = (cbd_t *)bdp;
+
+ spin_unlock_irq(&cep->lock);
+
+ return 0;
+}
+
+
+static void
+fcc_enet_timeout(struct net_device *dev)
+{
+ struct fcc_enet_private *cep = (struct fcc_enet_private *)dev->priv;
+
+ printk("%s: transmit timed out.\n", dev->name);
+ cep->stats.tx_errors++;
+#ifndef final_version
+ {
+ int i;
+ cbd_t *bdp;
+ printk(" Ring data dump: cur_tx %p tx_free %d cur_rx %p.\n",
+ cep->cur_tx, cep->tx_free,
+ cep->cur_rx);
+ bdp = cep->tx_bd_base;
+ printk(" Tx @base %p :\n", bdp);
+ for (i = 0 ; i < TX_RING_SIZE; i++, bdp++)
+ printk("%04x %04x %08x\n",
+ bdp->cbd_sc,
+ bdp->cbd_datlen,
+ bdp->cbd_bufaddr);
+ bdp = cep->rx_bd_base;
+ printk(" Rx @base %p :\n", bdp);
+ for (i = 0 ; i < RX_RING_SIZE; i++, bdp++)
+ printk("%04x %04x %08x\n",
+ bdp->cbd_sc,
+ bdp->cbd_datlen,
+ bdp->cbd_bufaddr);
+ }
+#endif
+ if (cep->tx_free)
+ netif_wake_queue(dev);
+}
+
+/* The interrupt handler. */
+static irqreturn_t
+fcc_enet_interrupt(int irq, void * dev_id, struct pt_regs * regs)
+{
+ struct net_device *dev = dev_id;
+ volatile struct fcc_enet_private *cep;
+ volatile cbd_t *bdp;
+ ushort int_events;
+ int must_restart;
+
+ cep = (struct fcc_enet_private *)dev->priv;
+
+ /* Get the interrupt events that caused us to be here.
+ */
+ int_events = cep->fccp->fcc_fcce;
+ cep->fccp->fcc_fcce = (int_events & cep->fccp->fcc_fccm);
+ must_restart = 0;
+
+#ifdef PHY_INTERRUPT
+ /* We have to be careful here to make sure that we aren't
+ * interrupted by a PHY interrupt.
+ */
+ disable_irq_nosync(PHY_INTERRUPT);
+#endif
+
+ /* Handle receive event in its own function.
+ */
+ if (int_events & FCC_ENET_RXF)
+ fcc_enet_rx(dev_id);
+
+ /* Check for a transmit error. The manual is a little unclear
+ * about this, so the debug code until I get it figured out. It
+ * appears that if TXE is set, then TXB is not set. However,
+ * if carrier sense is lost during frame transmission, the TXE
+ * bit is set, "and continues the buffer transmission normally."
+ * I don't know if "normally" implies TXB is set when the buffer
+ * descriptor is closed.....trial and error :-).
+ */
+
+ /* Transmit OK, or non-fatal error. Update the buffer descriptors.
+ */
+ if (int_events & (FCC_ENET_TXE | FCC_ENET_TXB)) {
+ spin_lock(&cep->lock);
+ bdp = cep->dirty_tx;
+ while ((bdp->cbd_sc&BD_ENET_TX_READY)==0) {
+ if (cep->tx_free == TX_RING_SIZE)
+ break;
+
+ if (bdp->cbd_sc & BD_ENET_TX_HB) /* No heartbeat */
+ cep->stats.tx_heartbeat_errors++;
+ if (bdp->cbd_sc & BD_ENET_TX_LC) /* Late collision */
+ cep->stats.tx_window_errors++;
+ if (bdp->cbd_sc & BD_ENET_TX_RL) /* Retrans limit */
+ cep->stats.tx_aborted_errors++;
+ if (bdp->cbd_sc & BD_ENET_TX_UN) /* Underrun */
+ cep->stats.tx_fifo_errors++;
+ if (bdp->cbd_sc & BD_ENET_TX_CSL) /* Carrier lost */
+ cep->stats.tx_carrier_errors++;
+
+
+ /* No heartbeat or Lost carrier are not really bad errors.
+ * The others require a restart transmit command.
+ */
+ if (bdp->cbd_sc &
+ (BD_ENET_TX_LC | BD_ENET_TX_RL | BD_ENET_TX_UN)) {
+ must_restart = 1;
+ cep->stats.tx_errors++;
+ }
+
+ cep->stats.tx_packets++;
+
+ /* Deferred means some collisions occurred during transmit,
+ * but we eventually sent the packet OK.
+ */
+ if (bdp->cbd_sc & BD_ENET_TX_DEF)
+ cep->stats.collisions++;
+
+ /* Free the sk buffer associated with this last transmit. */
+ dev_kfree_skb_irq(cep->tx_skbuff[cep->skb_dirty]);
+ cep->tx_skbuff[cep->skb_dirty] = NULL;
+ cep->skb_dirty = (cep->skb_dirty + 1) & TX_RING_MOD_MASK;
+
+ /* Update pointer to next buffer descriptor to be transmitted. */
+ if (bdp->cbd_sc & BD_ENET_TX_WRAP)
+ bdp = cep->tx_bd_base;
+ else
+ bdp++;
+
+ /* I don't know if we can be held off from processing these
+ * interrupts for more than one frame time. I really hope
+ * not. In such a case, we would now want to check the
+ * currently available BD (cur_tx) and determine if any
+ * buffers between the dirty_tx and cur_tx have also been
+ * sent. We would want to process anything in between that
+ * does not have BD_ENET_TX_READY set.
+ */
+
+ /* Since we have freed up a buffer, the ring is no longer
+ * full.
+ */
+ if (!cep->tx_free++) {
+ if (netif_queue_stopped(dev)) {
+ netif_wake_queue(dev);
+ }
+ }
+
+ cep->dirty_tx = (cbd_t *)bdp;
+ }
+
+ if (must_restart) {
+ volatile cpm_cpm2_t *cp;
+
+ /* Some transmit errors cause the transmitter to shut
+ * down. We now issue a restart transmit. Since the
+ * errors close the BD and update the pointers, the restart
+ * _should_ pick up without having to reset any of our
+ * pointers either. Also, To workaround 8260 device erratum
+ * CPM37, we must disable and then re-enable the transmitter
+ * following a Late Collision, Underrun, or Retry Limit error.
+ */
+ cep->fccp->fcc_gfmr &= ~FCC_GFMR_ENT;
+ udelay(10); /* wait a few microseconds just on principle */
+ cep->fccp->fcc_gfmr |= FCC_GFMR_ENT;
+
+ cp = cpmp;
+ cp->cp_cpcr =
+ mk_cr_cmd(cep->fip->fc_cpmpage, cep->fip->fc_cpmblock,
+ 0x0c, CPM_CR_RESTART_TX) | CPM_CR_FLG;
+ while (cp->cp_cpcr & CPM_CR_FLG);
+ }
+ spin_unlock(&cep->lock);
+ }
+
+ /* Check for receive busy, i.e. packets coming but no place to
+ * put them.
+ */
+ if (int_events & FCC_ENET_BSY) {
+ cep->fccp->fcc_fcce = FCC_ENET_BSY;
+ cep->stats.rx_dropped++;
+ }
+
+#ifdef PHY_INTERRUPT
+ enable_irq(PHY_INTERRUPT);
+#endif
+ return IRQ_HANDLED;
+}
+
+/* During a receive, the cur_rx points to the current incoming buffer.
+ * When we update through the ring, if the next incoming buffer has
+ * not been given to the system, we just set the empty indicator,
+ * effectively tossing the packet.
+ */
+static int
+fcc_enet_rx(struct net_device *dev)
+{
+ struct fcc_enet_private *cep;
+ volatile cbd_t *bdp;
+ struct sk_buff *skb;
+ ushort pkt_len;
+
+ cep = (struct fcc_enet_private *)dev->priv;
+
+ /* First, grab all of the stats for the incoming packet.
+ * These get messed up if we get called due to a busy condition.
+ */
+ bdp = cep->cur_rx;
+
+for (;;) {
+ if (bdp->cbd_sc & BD_ENET_RX_EMPTY)
+ break;
+
+#ifndef final_version
+ /* Since we have allocated space to hold a complete frame, both
+ * the first and last indicators should be set.
+ */
+ if ((bdp->cbd_sc & (BD_ENET_RX_FIRST | BD_ENET_RX_LAST)) !=
+ (BD_ENET_RX_FIRST | BD_ENET_RX_LAST))
+ printk("CPM ENET: rcv is not first+last\n");
+#endif
+
+ /* Frame too long or too short. */
+ if (bdp->cbd_sc & (BD_ENET_RX_LG | BD_ENET_RX_SH))
+ cep->stats.rx_length_errors++;
+ if (bdp->cbd_sc & BD_ENET_RX_NO) /* Frame alignment */
+ cep->stats.rx_frame_errors++;
+ if (bdp->cbd_sc & BD_ENET_RX_CR) /* CRC Error */
+ cep->stats.rx_crc_errors++;
+ if (bdp->cbd_sc & BD_ENET_RX_OV) /* FIFO overrun */
+ cep->stats.rx_crc_errors++;
+ if (bdp->cbd_sc & BD_ENET_RX_CL) /* Late Collision */
+ cep->stats.rx_frame_errors++;
+
+ if (!(bdp->cbd_sc &
+ (BD_ENET_RX_LG | BD_ENET_RX_SH | BD_ENET_RX_NO | BD_ENET_RX_CR
+ | BD_ENET_RX_OV | BD_ENET_RX_CL)))
+ {
+ /* Process the incoming frame. */
+ cep->stats.rx_packets++;
+
+ /* Remove the FCS from the packet length. */
+ pkt_len = bdp->cbd_datlen - 4;
+ cep->stats.rx_bytes += pkt_len;
+
+ /* This does 16 byte alignment, much more than we need. */
+ skb = dev_alloc_skb(pkt_len);
+
+ if (skb == NULL) {
+ printk("%s: Memory squeeze, dropping packet.\n", dev->name);
+ cep->stats.rx_dropped++;
+ }
+ else {
+ skb->dev = dev;
+ skb_put(skb,pkt_len); /* Make room */
+ eth_copy_and_sum(skb,
+ (unsigned char *)__va(bdp->cbd_bufaddr),
+ pkt_len, 0);
+ skb->protocol=eth_type_trans(skb,dev);
+ netif_rx(skb);
+ }
+ }
+
+ /* Clear the status flags for this buffer. */
+ bdp->cbd_sc &= ~BD_ENET_RX_STATS;
+
+ /* Mark the buffer empty. */
+ bdp->cbd_sc |= BD_ENET_RX_EMPTY;
+
+ /* Update BD pointer to next entry. */
+ if (bdp->cbd_sc & BD_ENET_RX_WRAP)
+ bdp = cep->rx_bd_base;
+ else
+ bdp++;
+
+ }
+ cep->cur_rx = (cbd_t *)bdp;
+
+ return 0;
+}
+
+static int
+fcc_enet_close(struct net_device *dev)
+{
+#ifdef CONFIG_USE_MDIO
+ struct fcc_enet_private *fep = dev->priv;
+#endif
+
+ netif_stop_queue(dev);
+ fcc_stop(dev);
+#ifdef CONFIG_USE_MDIO
+ if (fep->phy)
+ mii_do_cmd(dev, fep->phy->shutdown);
+#endif
+
+ return 0;
+}
+
+static struct net_device_stats *fcc_enet_get_stats(struct net_device *dev)
+{
+ struct fcc_enet_private *cep = (struct fcc_enet_private *)dev->priv;
+
+ return &cep->stats;
+}
+
+#ifdef CONFIG_USE_MDIO
+
+/* NOTE: Most of the following comes from the FEC driver for 860. The
+ * overall structure of MII code has been retained (as it's proved stable
+ * and well-tested), but actual transfer requests are processed "at once"
+ * instead of being queued (there's no interrupt-driven MII transfer
+ * mechanism, one has to toggle the data/clock bits manually).
+ */
+static int
+mii_queue(struct net_device *dev, int regval, void (*func)(uint, struct net_device *))
+{
+ struct fcc_enet_private *fep;
+ int retval, tmp;
+
+ /* Add PHY address to register command. */
+ fep = dev->priv;
+ regval |= fep->phy_addr << 23;
+
+ retval = 0;
+
+ tmp = mii_send_receive(fep->fip, regval);
+ if (func)
+ func(tmp, dev);
+
+ return retval;
+}
+
+static void mii_do_cmd(struct net_device *dev, const phy_cmd_t *c)
+{
+ int k;
+
+ if(!c)
+ return;
+
+ for(k = 0; (c+k)->mii_data != mk_mii_end; k++)
+ mii_queue(dev, (c+k)->mii_data, (c+k)->funct);
+}
+
+static void mii_parse_sr(uint mii_reg, struct net_device *dev)
+{
+ volatile struct fcc_enet_private *fep = dev->priv;
+ uint s = fep->phy_status;
+
+ s &= ~(PHY_STAT_LINK | PHY_STAT_FAULT | PHY_STAT_ANC);
+
+ if (mii_reg & BMSR_LSTATUS)
+ s |= PHY_STAT_LINK;
+ if (mii_reg & BMSR_RFAULT)
+ s |= PHY_STAT_FAULT;
+ if (mii_reg & BMSR_ANEGCOMPLETE)
+ s |= PHY_STAT_ANC;
+
+ fep->phy_status = s;
+}
+
+static void mii_parse_cr(uint mii_reg, struct net_device *dev)
+{
+ volatile struct fcc_enet_private *fep = dev->priv;
+ uint s = fep->phy_status;
+
+ s &= ~(PHY_CONF_ANE | PHY_CONF_LOOP);
+
+ if (mii_reg & BMCR_ANENABLE)
+ s |= PHY_CONF_ANE;
+ if (mii_reg & BMCR_LOOPBACK)
+ s |= PHY_CONF_LOOP;
+
+ fep->phy_status = s;
+}
+
+static void mii_parse_anar(uint mii_reg, struct net_device *dev)
+{
+ volatile struct fcc_enet_private *fep = dev->priv;
+ uint s = fep->phy_status;
+
+ s &= ~(PHY_CONF_SPMASK);
+
+ if (mii_reg & ADVERTISE_10HALF)
+ s |= PHY_CONF_10HDX;
+ if (mii_reg & ADVERTISE_10FULL)
+ s |= PHY_CONF_10FDX;
+ if (mii_reg & ADVERTISE_100HALF)
+ s |= PHY_CONF_100HDX;
+ if (mii_reg & ADVERTISE_100FULL)
+ s |= PHY_CONF_100FDX;
+
+ fep->phy_status = s;
+}
+
+/* ------------------------------------------------------------------------- */
+/* Generic PHY support. Should work for all PHYs, but does not support link
+ * change interrupts.
+ */
+#ifdef CONFIG_FCC_GENERIC_PHY
+
+static phy_info_t phy_info_generic = {
+ 0x00000000, /* 0-->match any PHY */
+ "GENERIC",
+
+ (const phy_cmd_t []) { /* config */
+ /* advertise only half-duplex capabilities */
+ { mk_mii_write(MII_ADVERTISE, MII_ADVERTISE_HALF),
+ mii_parse_anar },
+
+ /* enable auto-negotiation */
+ { mk_mii_write(MII_BMCR, BMCR_ANENABLE), mii_parse_cr },
+ { mk_mii_end, }
+ },
+ (const phy_cmd_t []) { /* startup */
+ /* restart auto-negotiation */
+ { mk_mii_write(MII_BMCR, BMCR_ANENABLE | BMCR_ANRESTART),
+ NULL },
+ { mk_mii_end, }
+ },
+ (const phy_cmd_t []) { /* ack_int */
+ /* We don't actually use the ack_int table with a generic
+ * PHY, but putting a reference to mii_parse_sr here keeps
+ * us from getting a compiler warning about unused static
+ * functions in the case where we only compile in generic
+ * PHY support.
+ */
+ { mk_mii_read(MII_BMSR), mii_parse_sr },
+ { mk_mii_end, }
+ },
+ (const phy_cmd_t []) { /* shutdown */
+ { mk_mii_end, }
+ },
+};
+#endif /* ifdef CONFIG_FCC_GENERIC_PHY */
+
+/* ------------------------------------------------------------------------- */
+/* The Level one LXT970 is used by many boards */
+
+#ifdef CONFIG_FCC_LXT970
+
+#define MII_LXT970_MIRROR 16 /* Mirror register */
+#define MII_LXT970_IER 17 /* Interrupt Enable Register */
+#define MII_LXT970_ISR 18 /* Interrupt Status Register */
+#define MII_LXT970_CONFIG 19 /* Configuration Register */
+#define MII_LXT970_CSR 20 /* Chip Status Register */
+
+static void mii_parse_lxt970_csr(uint mii_reg, struct net_device *dev)
+{
+ volatile struct fcc_enet_private *fep = dev->priv;
+ uint s = fep->phy_status;
+
+ s &= ~(PHY_STAT_SPMASK);
+
+ if (mii_reg & 0x0800) {
+ if (mii_reg & 0x1000)
+ s |= PHY_STAT_100FDX;
+ else
+ s |= PHY_STAT_100HDX;
+ } else {
+ if (mii_reg & 0x1000)
+ s |= PHY_STAT_10FDX;
+ else
+ s |= PHY_STAT_10HDX;
+ }
+
+ fep->phy_status = s;
+}
+
+static phy_info_t phy_info_lxt970 = {
+ 0x07810000,
+ "LXT970",
+
+ (const phy_cmd_t []) { /* config */
+#if 0
+// { mk_mii_write(MII_ADVERTISE, 0x0021), NULL },
+
+ /* Set default operation of 100-TX....for some reason
+ * some of these bits are set on power up, which is wrong.
+ */
+ { mk_mii_write(MII_LXT970_CONFIG, 0), NULL },
+#endif
+ { mk_mii_read(MII_BMCR), mii_parse_cr },
+ { mk_mii_read(MII_ADVERTISE), mii_parse_anar },
+ { mk_mii_end, }
+ },
+ (const phy_cmd_t []) { /* startup - enable interrupts */
+ { mk_mii_write(MII_LXT970_IER, 0x0002), NULL },
+ { mk_mii_write(MII_BMCR, 0x1200), NULL }, /* autonegotiate */
+ { mk_mii_end, }
+ },
+ (const phy_cmd_t []) { /* ack_int */
+ /* read SR and ISR to acknowledge */
+
+ { mk_mii_read(MII_BMSR), mii_parse_sr },
+ { mk_mii_read(MII_LXT970_ISR), NULL },
+
+ /* find out the current status */
+
+ { mk_mii_read(MII_LXT970_CSR), mii_parse_lxt970_csr },
+ { mk_mii_end, }
+ },
+ (const phy_cmd_t []) { /* shutdown - disable interrupts */
+ { mk_mii_write(MII_LXT970_IER, 0x0000), NULL },
+ { mk_mii_end, }
+ },
+};
+
+#endif /* CONFIG_FEC_LXT970 */
+
+/* ------------------------------------------------------------------------- */
+/* The Level one LXT971 is used on some of my custom boards */
+
+#ifdef CONFIG_FCC_LXT971
+
+/* register definitions for the 971 */
+
+#define MII_LXT971_PCR 16 /* Port Control Register */
+#define MII_LXT971_SR2 17 /* Status Register 2 */
+#define MII_LXT971_IER 18 /* Interrupt Enable Register */
+#define MII_LXT971_ISR 19 /* Interrupt Status Register */
+#define MII_LXT971_LCR 20 /* LED Control Register */
+#define MII_LXT971_TCR 30 /* Transmit Control Register */
+
+/*
+ * I had some nice ideas of running the MDIO faster...
+ * The 971 should support 8MHz and I tried it, but things acted really
+ * weird, so 2.5 MHz ought to be enough for anyone...
+ */
+
+static void mii_parse_lxt971_sr2(uint mii_reg, struct net_device *dev)
+{
+ volatile struct fcc_enet_private *fep = dev->priv;
+ uint s = fep->phy_status;
+
+ s &= ~(PHY_STAT_SPMASK);
+
+ if (mii_reg & 0x4000) {
+ if (mii_reg & 0x0200)
+ s |= PHY_STAT_100FDX;
+ else
+ s |= PHY_STAT_100HDX;
+ } else {
+ if (mii_reg & 0x0200)
+ s |= PHY_STAT_10FDX;
+ else
+ s |= PHY_STAT_10HDX;
+ }
+ if (mii_reg & 0x0008)
+ s |= PHY_STAT_FAULT;
+
+ fep->phy_status = s;
+}
+
+static phy_info_t phy_info_lxt971 = {
+ 0x0001378e,
+ "LXT971",
+
+ (const phy_cmd_t []) { /* config */
+ /* configure link capabilities to advertise */
+ { mk_mii_write(MII_ADVERTISE, MII_ADVERTISE_DEFAULT),
+ mii_parse_anar },
+
+ /* enable auto-negotiation */
+ { mk_mii_write(MII_BMCR, BMCR_ANENABLE), mii_parse_cr },
+ { mk_mii_end, }
+ },
+ (const phy_cmd_t []) { /* startup - enable interrupts */
+ { mk_mii_write(MII_LXT971_IER, 0x00f2), NULL },
+
+ /* restart auto-negotiation */
+ { mk_mii_write(MII_BMCR, BMCR_ANENABLE | BMCR_ANRESTART),
+ NULL },
+ { mk_mii_end, }
+ },
+ (const phy_cmd_t []) { /* ack_int */
+ /* find out the current status */
+ { mk_mii_read(MII_BMSR), NULL },
+ { mk_mii_read(MII_BMSR), mii_parse_sr },
+ { mk_mii_read(MII_LXT971_SR2), mii_parse_lxt971_sr2 },
+
+ /* we only need to read ISR to acknowledge */
+ { mk_mii_read(MII_LXT971_ISR), NULL },
+ { mk_mii_end, }
+ },
+ (const phy_cmd_t []) { /* shutdown - disable interrupts */
+ { mk_mii_write(MII_LXT971_IER, 0x0000), NULL },
+ { mk_mii_end, }
+ },
+};
+
+#endif /* CONFIG_FCC_LXT971 */
+
+/* ------------------------------------------------------------------------- */
+/* The Quality Semiconductor QS6612 is used on the RPX CLLF */
+
+#ifdef CONFIG_FCC_QS6612
+
+/* register definitions */
+
+#define MII_QS6612_MCR 17 /* Mode Control Register */
+#define MII_QS6612_FTR 27 /* Factory Test Register */
+#define MII_QS6612_MCO 28 /* Misc. Control Register */
+#define MII_QS6612_ISR 29 /* Interrupt Source Register */
+#define MII_QS6612_IMR 30 /* Interrupt Mask Register */
+#define MII_QS6612_PCR 31 /* 100BaseTx PHY Control Reg. */
+
+static void mii_parse_qs6612_pcr(uint mii_reg, struct net_device *dev)
+{
+ volatile struct fcc_enet_private *fep = dev->priv;
+ uint s = fep->phy_status;
+
+ s &= ~(PHY_STAT_SPMASK);
+
+ switch((mii_reg >> 2) & 7) {
+ case 1: s |= PHY_STAT_10HDX; break;
+ case 2: s |= PHY_STAT_100HDX; break;
+ case 5: s |= PHY_STAT_10FDX; break;
+ case 6: s |= PHY_STAT_100FDX; break;
+ }
+
+ fep->phy_status = s;
+}
+
+static phy_info_t phy_info_qs6612 = {
+ 0x00181440,
+ "QS6612",
+
+ (const phy_cmd_t []) { /* config */
+// { mk_mii_write(MII_ADVERTISE, 0x061), NULL }, /* 10 Mbps */
+
+ /* The PHY powers up isolated on the RPX,
+ * so send a command to allow operation.
+ */
+
+ { mk_mii_write(MII_QS6612_PCR, 0x0dc0), NULL },
+
+ /* parse cr and anar to get some info */
+
+ { mk_mii_read(MII_BMCR), mii_parse_cr },
+ { mk_mii_read(MII_ADVERTISE), mii_parse_anar },
+ { mk_mii_end, }
+ },
+ (const phy_cmd_t []) { /* startup - enable interrupts */
+ { mk_mii_write(MII_QS6612_IMR, 0x003a), NULL },
+ { mk_mii_write(MII_BMCR, 0x1200), NULL }, /* autonegotiate */
+ { mk_mii_end, }
+ },
+ (const phy_cmd_t []) { /* ack_int */
+
+ /* we need to read ISR, SR and ANER to acknowledge */
+
+ { mk_mii_read(MII_QS6612_ISR), NULL },
+ { mk_mii_read(MII_BMSR), mii_parse_sr },
+ { mk_mii_read(MII_EXPANSION), NULL },
+
+ /* read pcr to get info */
+
+ { mk_mii_read(MII_QS6612_PCR), mii_parse_qs6612_pcr },
+ { mk_mii_end, }
+ },
+ (const phy_cmd_t []) { /* shutdown - disable interrupts */
+ { mk_mii_write(MII_QS6612_IMR, 0x0000), NULL },
+ { mk_mii_end, }
+ },
+};
+
+
+#endif /* CONFIG_FEC_QS6612 */
+
+
+/* ------------------------------------------------------------------------- */
+/* The Davicom DM9131 is used on the HYMOD board */
+
+#ifdef CONFIG_FCC_DM9131
+
+/* register definitions */
+
+#define MII_DM9131_ACR 16 /* Aux. Config Register */
+#define MII_DM9131_ACSR 17 /* Aux. Config/Status Register */
+#define MII_DM9131_10TCSR 18 /* 10BaseT Config/Status Reg. */
+#define MII_DM9131_INTR 21 /* Interrupt Register */
+#define MII_DM9131_RECR 22 /* Receive Error Counter Reg. */
+#define MII_DM9131_DISCR 23 /* Disconnect Counter Register */
+
+static void mii_parse_dm9131_acsr(uint mii_reg, struct net_device *dev)
+{
+ volatile struct fcc_enet_private *fep = dev->priv;
+ uint s = fep->phy_status;
+
+ s &= ~(PHY_STAT_SPMASK);
+
+ switch ((mii_reg >> 12) & 0xf) {
+ case 1: s |= PHY_STAT_10HDX; break;
+ case 2: s |= PHY_STAT_10FDX; break;
+ case 4: s |= PHY_STAT_100HDX; break;
+ case 8: s |= PHY_STAT_100FDX; break;
+ }
+
+ fep->phy_status = s;
+}
+
+static phy_info_t phy_info_dm9131 = {
+ 0x00181b80,
+ "DM9131",
+
+ (const phy_cmd_t []) { /* config */
+ /* parse cr and anar to get some info */
+ { mk_mii_read(MII_BMCR), mii_parse_cr },
+ { mk_mii_read(MII_ADVERTISE), mii_parse_anar },
+ { mk_mii_end, }
+ },
+ (const phy_cmd_t []) { /* startup - enable interrupts */
+ { mk_mii_write(MII_DM9131_INTR, 0x0002), NULL },
+ { mk_mii_write(MII_BMCR, 0x1200), NULL }, /* autonegotiate */
+ { mk_mii_end, }
+ },
+ (const phy_cmd_t []) { /* ack_int */
+
+ /* we need to read INTR, SR and ANER to acknowledge */
+
+ { mk_mii_read(MII_DM9131_INTR), NULL },
+ { mk_mii_read(MII_BMSR), mii_parse_sr },
+ { mk_mii_read(MII_EXPANSION), NULL },
+
+ /* read acsr to get info */
+
+ { mk_mii_read(MII_DM9131_ACSR), mii_parse_dm9131_acsr },
+ { mk_mii_end, }
+ },
+ (const phy_cmd_t []) { /* shutdown - disable interrupts */
+ { mk_mii_write(MII_DM9131_INTR, 0x0f00), NULL },
+ { mk_mii_end, }
+ },
+};
+
+
+#endif /* CONFIG_FEC_DM9131 */
+#ifdef CONFIG_FCC_DM9161
+/* ------------------------------------------------------------------------- */
+/* DM9161 Control register values */
+#define MIIM_DM9161_CR_STOP 0x0400
+#define MIIM_DM9161_CR_RSTAN 0x1200
+
+#define MIIM_DM9161_SCR 0x10
+#define MIIM_DM9161_SCR_INIT 0x0610
+
+/* DM9161 Specified Configuration and Status Register */
+#define MIIM_DM9161_SCSR 0x11
+#define MIIM_DM9161_SCSR_100F 0x8000
+#define MIIM_DM9161_SCSR_100H 0x4000
+#define MIIM_DM9161_SCSR_10F 0x2000
+#define MIIM_DM9161_SCSR_10H 0x1000
+/* DM9161 10BT register */
+#define MIIM_DM9161_10BTCSR 0x12
+#define MIIM_DM9161_10BTCSR_INIT 0x7800
+/* DM9161 Interrupt Register */
+#define MIIM_DM9161_INTR 0x15
+#define MIIM_DM9161_INTR_PEND 0x8000
+#define MIIM_DM9161_INTR_DPLX_MASK 0x0800
+#define MIIM_DM9161_INTR_SPD_MASK 0x0400
+#define MIIM_DM9161_INTR_LINK_MASK 0x0200
+#define MIIM_DM9161_INTR_MASK 0x0100
+#define MIIM_DM9161_INTR_DPLX_CHANGE 0x0010
+#define MIIM_DM9161_INTR_SPD_CHANGE 0x0008
+#define MIIM_DM9161_INTR_LINK_CHANGE 0x0004
+#define MIIM_DM9161_INTR_INIT 0x0000
+#define MIIM_DM9161_INTR_STOP \
+(MIIM_DM9161_INTR_DPLX_MASK | MIIM_DM9161_INTR_SPD_MASK \
+ | MIIM_DM9161_INTR_LINK_MASK | MIIM_DM9161_INTR_MASK)
+
+static void mii_parse_dm9161_sr(uint mii_reg, struct net_device * dev)
+{
+ volatile struct fcc_enet_private *fep = dev->priv;
+ uint regstat, timeout=0xffff;
+
+ while(!(mii_reg & 0x0020) && timeout--)
+ {
+ regstat=mk_mii_read(MII_BMSR);
+ regstat |= fep->phy_addr <<23;
+ mii_reg = mii_send_receive(fep->fip,regstat);
+ }
+
+ mii_parse_sr(mii_reg, dev);
+}
+
+static void mii_parse_dm9161_scsr(uint mii_reg, struct net_device * dev)
+{
+ volatile struct fcc_enet_private *fep = dev->priv;
+ uint s = fep->phy_status;
+
+ s &= ~(PHY_STAT_SPMASK);
+ switch((mii_reg >>12) & 0xf) {
+ case 1:
+ {
+ s |= PHY_STAT_10HDX;
+ printk("10BaseT Half Duplex\n");
+ break;
+ }
+ case 2:
+ {
+ s |= PHY_STAT_10FDX;
+ printk("10BaseT Full Duplex\n");
+ break;
+ }
+ case 4:
+ {
+ s |= PHY_STAT_100HDX;
+ printk("100BaseT Half Duplex\n");
+ break;
+ }
+ case 8:
+ {
+ s |= PHY_STAT_100FDX;
+ printk("100BaseT Full Duplex\n");
+ break;
+ }
+ }
+
+ fep->phy_status = s;
+
+}
+
+static void mii_dm9161_wait(uint mii_reg, struct net_device *dev)
+{
+ int timeout = HZ;
+
+ /* Davicom takes a bit to come up after a reset,
+ * so wait here for a bit */
+ set_current_state(TASK_UNINTERRUPTIBLE);
+ schedule_timeout(timeout);
+}
+
+static phy_info_t phy_info_dm9161 = {
+ 0x00181b88,
+ "Davicom DM9161E",
+ (const phy_cmd_t[]) { /* config */
+ { mk_mii_write(MII_BMCR, MIIM_DM9161_CR_STOP), NULL},
+ /* Do not bypass the scrambler/descrambler */
+ { mk_mii_write(MIIM_DM9161_SCR, MIIM_DM9161_SCR_INIT), NULL},
+ /* Configure 10BTCSR register */
+ { mk_mii_write(MIIM_DM9161_10BTCSR, MIIM_DM9161_10BTCSR_INIT),NULL},
+ /* Configure some basic stuff */
+ { mk_mii_write(MII_BMCR, 0x1000), NULL},
+ { mk_mii_read(MII_BMCR), mii_parse_cr },
+ { mk_mii_read(MII_ADVERTISE), mii_parse_anar },
+ { mk_mii_end,}
+ },
+ (const phy_cmd_t[]) { /* startup */
+ /* Restart Auto Negotiation */
+ { mk_mii_write(MII_BMCR, MIIM_DM9161_CR_RSTAN), NULL},
+ /* Status is read once to clear old link state */
+ { mk_mii_read(MII_BMSR), mii_dm9161_wait},
+ /* Auto-negotiate */
+ { mk_mii_read(MII_BMSR), mii_parse_dm9161_sr},
+ /* Read the status */
+ { mk_mii_read(MIIM_DM9161_SCSR), mii_parse_dm9161_scsr},
+ /* Clear any pending interrupts */
+ { mk_mii_read(MIIM_DM9161_INTR), NULL},
+ /* Enable Interrupts */
+ { mk_mii_write(MIIM_DM9161_INTR, MIIM_DM9161_INTR_INIT), NULL},
+ { mk_mii_end,}
+ },
+ (const phy_cmd_t[]) { /* ack_int */
+ { mk_mii_read(MIIM_DM9161_INTR), NULL},
+#if 0
+ { mk_mii_read(MII_BMSR), NULL},
+ { mk_mii_read(MII_BMSR), mii_parse_dm9161_sr},
+ { mk_mii_read(MIIM_DM9161_SCSR), mii_parse_dm9161_scsr},
+#endif
+ { mk_mii_end,}
+ },
+ (const phy_cmd_t[]) { /* shutdown */
+ { mk_mii_read(MIIM_DM9161_INTR),NULL},
+ { mk_mii_write(MIIM_DM9161_INTR, MIIM_DM9161_INTR_STOP), NULL},
+ { mk_mii_end,}
+ },
+};
+#endif /* CONFIG_FCC_DM9161 */
+
+static phy_info_t *phy_info[] = {
+
+#ifdef CONFIG_FCC_LXT970
+ &phy_info_lxt970,
+#endif /* CONFIG_FEC_LXT970 */
+
+#ifdef CONFIG_FCC_LXT971
+ &phy_info_lxt971,
+#endif /* CONFIG_FEC_LXT971 */
+
+#ifdef CONFIG_FCC_QS6612
+ &phy_info_qs6612,
+#endif /* CONFIG_FEC_QS6612 */
+
+#ifdef CONFIG_FCC_DM9131
+ &phy_info_dm9131,
+#endif /* CONFIG_FEC_DM9131 */
+
+#ifdef CONFIG_FCC_DM9161
+ &phy_info_dm9161,
+#endif /* CONFIG_FCC_DM9161 */
+
+#ifdef CONFIG_FCC_GENERIC_PHY
+ /* Generic PHY support. This must be the last PHY in the table.
+ * It will be used to support any PHY that doesn't match a previous
+ * entry in the table.
+ */
+ &phy_info_generic,
+#endif /* CONFIG_FCC_GENERIC_PHY */
+
+ NULL
+};
+
+static void mii_display_status(void *data)
+{
+ struct net_device *dev = data;
+ volatile struct fcc_enet_private *fep = dev->priv;
+ uint s = fep->phy_status;
+
+ if (!fep->link && !fep->old_link) {
+ /* Link is still down - don't print anything */
+ return;
+ }
+
+ printk("%s: status: ", dev->name);
+
+ if (!fep->link) {
+ printk("link down");
+ } else {
+ printk("link up");
+
+ switch(s & PHY_STAT_SPMASK) {
+ case PHY_STAT_100FDX: printk(", 100 Mbps Full Duplex"); break;
+ case PHY_STAT_100HDX: printk(", 100 Mbps Half Duplex"); break;
+ case PHY_STAT_10FDX: printk(", 10 Mbps Full Duplex"); break;
+ case PHY_STAT_10HDX: printk(", 10 Mbps Half Duplex"); break;
+ default:
+ printk(", Unknown speed/duplex");
+ }
+
+ if (s & PHY_STAT_ANC)
+ printk(", auto-negotiation complete");
+ }
+
+ if (s & PHY_STAT_FAULT)
+ printk(", remote fault");
+
+ printk(".\n");
+}
+
+static void mii_display_config(void *data)
+{
+ struct net_device *dev = data;
+ volatile struct fcc_enet_private *fep = dev->priv;
+ uint s = fep->phy_status;
+
+ printk("%s: config: auto-negotiation ", dev->name);
+
+ if (s & PHY_CONF_ANE)
+ printk("on");
+ else
+ printk("off");
+
+ if (s & PHY_CONF_100FDX)
+ printk(", 100FDX");
+ if (s & PHY_CONF_100HDX)
+ printk(", 100HDX");
+ if (s & PHY_CONF_10FDX)
+ printk(", 10FDX");
+ if (s & PHY_CONF_10HDX)
+ printk(", 10HDX");
+ if (!(s & PHY_CONF_SPMASK))
+ printk(", No speed/duplex selected?");
+
+ if (s & PHY_CONF_LOOP)
+ printk(", loopback enabled");
+
+ printk(".\n");
+
+ fep->sequence_done = 1;
+}
+
+static void mii_relink(struct net_device *dev)
+{
+ struct fcc_enet_private *fep = dev->priv;
+ int duplex = 0;
+
+ fep->old_link = fep->link;
+ fep->link = (fep->phy_status & PHY_STAT_LINK) ? 1 : 0;
+
+#ifdef MDIO_DEBUG
+ printk(" mii_relink: link=%d\n", fep->link);
+#endif
+
+ if (fep->link) {
+ if (fep->phy_status
+ & (PHY_STAT_100FDX | PHY_STAT_10FDX))
+ duplex = 1;
+ fcc_restart(dev, duplex);
+#ifdef MDIO_DEBUG
+ printk(" mii_relink: duplex=%d\n", duplex);
+#endif
+ }
+}
+
+static void mii_queue_relink(uint mii_reg, struct net_device *dev)
+{
+ struct fcc_enet_private *fep = dev->priv;
+
+ mii_relink(dev);
+
+ schedule_work(&fep->phy_relink);
+}
+
+static void mii_queue_config(uint mii_reg, struct net_device *dev)
+{
+ struct fcc_enet_private *fep = dev->priv;
+
+ schedule_work(&fep->phy_display_config);
+}
+
+phy_cmd_t phy_cmd_relink[] = { { mk_mii_read(MII_BMCR), mii_queue_relink },
+ { mk_mii_end, } };
+phy_cmd_t phy_cmd_config[] = { { mk_mii_read(MII_BMCR), mii_queue_config },
+ { mk_mii_end, } };
+
+
+/* Read remainder of PHY ID.
+*/
+static void
+mii_discover_phy3(uint mii_reg, struct net_device *dev)
+{
+ struct fcc_enet_private *fep;
+ int i;
+
+ fep = dev->priv;
+ printk("mii_reg: %08x\n", mii_reg);
+ fep->phy_id |= (mii_reg & 0xffff);
+
+ for(i = 0; phy_info[i]; i++)
+ if((phy_info[i]->id == (fep->phy_id >> 4)) || !phy_info[i]->id)
+ break;
+
+ if(!phy_info[i])
+ panic("%s: PHY id 0x%08x is not supported!\n",
+ dev->name, fep->phy_id);
+
+ fep->phy = phy_info[i];
+ fep->phy_id_done = 1;
+
+ printk("%s: Phy @ 0x%x, type %s (0x%08x)\n",
+ dev->name, fep->phy_addr, fep->phy->name, fep->phy_id);
+}
+
+/* Scan all of the MII PHY addresses looking for someone to respond
+ * with a valid ID. This usually happens quickly.
+ */
+static void
+mii_discover_phy(uint mii_reg, struct net_device *dev)
+{
+ struct fcc_enet_private *fep;
+ uint phytype;
+
+ fep = dev->priv;
+
+ if ((phytype = (mii_reg & 0xffff)) != 0xffff) {
+
+ /* Got first part of ID, now get remainder. */
+ fep->phy_id = phytype << 16;
+ mii_queue(dev, mk_mii_read(MII_PHYSID2), mii_discover_phy3);
+ } else {
+ fep->phy_addr++;
+ if (fep->phy_addr < 32) {
+ mii_queue(dev, mk_mii_read(MII_PHYSID1),
+ mii_discover_phy);
+ } else {
+ printk("fec: No PHY device found.\n");
+ }
+ }
+}
+#endif /* CONFIG_USE_MDIO */
+
+#ifdef PHY_INTERRUPT
+/* This interrupt occurs when the PHY detects a link change. */
+static irqreturn_t
+mii_link_interrupt(int irq, void * dev_id, struct pt_regs * regs)
+{
+ struct net_device *dev = dev_id;
+ struct fcc_enet_private *fep = dev->priv;
+ fcc_info_t *fip = fep->fip;
+
+ if (fep->phy) {
+ /* We don't want to be interrupted by an FCC
+ * interrupt here.
+ */
+ disable_irq_nosync(fip->fc_interrupt);
+
+ mii_do_cmd(dev, fep->phy->ack_int);
+ /* restart and display status */
+ mii_do_cmd(dev, phy_cmd_relink);
+
+ enable_irq(fip->fc_interrupt);
+ }
+ return IRQ_HANDLED;
+}
+#endif /* ifdef PHY_INTERRUPT */
+
+#if 0 /* This should be fixed someday */
+/* Set or clear the multicast filter for this adaptor.
+ * Skeleton taken from sunlance driver.
+ * The CPM Ethernet implementation allows Multicast as well as individual
+ * MAC address filtering. Some of the drivers check to make sure it is
+ * a group multicast address, and discard those that are not. I guess I
+ * will do the same for now, but just remove the test if you want
+ * individual filtering as well (do the upper net layers want or support
+ * this kind of feature?).
+ */
+static void
+set_multicast_list(struct net_device *dev)
+{
+ struct fcc_enet_private *cep;
+ struct dev_mc_list *dmi;
+ u_char *mcptr, *tdptr;
+ volatile fcc_enet_t *ep;
+ int i, j;
+
+ cep = (struct fcc_enet_private *)dev->priv;
+
+return;
+ /* Get pointer to FCC area in parameter RAM.
+ */
+ ep = (fcc_enet_t *)dev->base_addr;
+
+ if (dev->flags&IFF_PROMISC) {
+
+ /* Log any net taps. */
+ printk("%s: Promiscuous mode enabled.\n", dev->name);
+ cep->fccp->fcc_fpsmr |= FCC_PSMR_PRO;
+ } else {
+
+ cep->fccp->fcc_fpsmr &= ~FCC_PSMR_PRO;
+
+ if (dev->flags & IFF_ALLMULTI) {
+ /* Catch all multicast addresses, so set the
+ * filter to all 1's.
+ */
+ ep->fen_gaddrh = 0xffffffff;
+ ep->fen_gaddrl = 0xffffffff;
+ }
+ else {
+ /* Clear filter and add the addresses in the list.
+ */
+ ep->fen_gaddrh = 0;
+ ep->fen_gaddrl = 0;
+
+ dmi = dev->mc_list;
+
+ for (i=0; i<dev->mc_count; i++, dmi = dmi->next) {
+
+ /* Only support group multicast for now.
+ */
+ if (!(dmi->dmi_addr[0] & 1))
+ continue;
+
+ /* The address in dmi_addr is LSB first,
+ * and taddr is MSB first. We have to
+ * copy bytes MSB first from dmi_addr.
+ */
+ mcptr = (u_char *)dmi->dmi_addr + 5;
+ tdptr = (u_char *)&ep->fen_taddrh;
+ for (j=0; j<6; j++)
+ *tdptr++ = *mcptr--;
+
+ /* Ask CPM to run CRC and set bit in
+ * filter mask.
+ */
+ cpmp->cp_cpcr = mk_cr_cmd(cep->fip->fc_cpmpage,
+ cep->fip->fc_cpmblock, 0x0c,
+ CPM_CR_SET_GADDR) | CPM_CR_FLG;
+ udelay(10);
+ while (cpmp->cp_cpcr & CPM_CR_FLG);
+ }
+ }
+ }
+}
+#endif /* if 0 */
+
+
+/* Set the individual MAC address.
+ */
+int fcc_enet_set_mac_address(struct net_device *dev, void *p)
+{
+ struct sockaddr *addr= (struct sockaddr *) p;
+ struct fcc_enet_private *cep;
+ volatile fcc_enet_t *ep;
+ unsigned char *eap;
+ int i;
+
+ cep = (struct fcc_enet_private *)(dev->priv);
+ ep = cep->ep;
+
+ if (netif_running(dev))
+ return -EBUSY;
+
+ memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
+
+ eap = (unsigned char *) &(ep->fen_paddrh);
+ for (i=5; i>=0; i--)
+ *eap++ = addr->sa_data[i];
+
+ return 0;
+}
+
+
+/* Initialize the CPM Ethernet on FCC.
+ */
+static int __init fec_enet_init(void)
+{
+ struct net_device *dev;
+ struct fcc_enet_private *cep;
+ fcc_info_t *fip;
+ int i, np, err;
+ volatile cpm2_map_t *immap;
+ volatile iop_cpm2_t *io;
+
+ immap = (cpm2_map_t *)CPM_MAP_ADDR; /* and to internal registers */
+ io = &immap->im_ioport;
+
+ np = sizeof(fcc_ports) / sizeof(fcc_info_t);
+ fip = fcc_ports;
+
+ while (np-- > 0) {
+ /* Create an Ethernet device instance.
+ */
+ dev = alloc_etherdev(sizeof(*cep));
+ if (!dev)
+ return -ENOMEM;
+
+ cep = dev->priv;
+ spin_lock_init(&cep->lock);
+ cep->fip = fip;
+
+ init_fcc_shutdown(fip, cep, immap);
+ init_fcc_ioports(fip, io, immap);
+ init_fcc_param(fip, dev, immap);
+
+ dev->base_addr = (unsigned long)(cep->ep);
+
+ /* The CPM Ethernet specific entries in the device
+ * structure.
+ */
+ dev->open = fcc_enet_open;
+ dev->hard_start_xmit = fcc_enet_start_xmit;
+ dev->tx_timeout = fcc_enet_timeout;
+ dev->watchdog_timeo = TX_TIMEOUT;
+ dev->stop = fcc_enet_close;
+ dev->get_stats = fcc_enet_get_stats;
+ /* dev->set_multicast_list = set_multicast_list; */
+ dev->set_mac_address = fcc_enet_set_mac_address;
+
+ init_fcc_startup(fip, dev);
+
+ err = register_netdev(dev);
+ if (err) {
+ free_netdev(dev);
+ return err;
+ }
+
+ printk("%s: FCC ENET Version 0.3, ", dev->name);
+ for (i=0; i<5; i++)
+ printk("%02x:", dev->dev_addr[i]);
+ printk("%02x\n", dev->dev_addr[5]);
+
+#ifdef CONFIG_USE_MDIO
+ /* Queue up command to detect the PHY and initialize the
+ * remainder of the interface.
+ */
+ cep->phy_id_done = 0;
+ cep->phy_addr = fip->fc_phyaddr;
+ mii_queue(dev, mk_mii_read(MII_PHYSID1), mii_discover_phy);
+ INIT_WORK(&cep->phy_relink, mii_display_status, dev);
+ INIT_WORK(&cep->phy_display_config, mii_display_config, dev);
+#endif /* CONFIG_USE_MDIO */
+
+ fip++;
+ }
+
+ return 0;
+}
+module_init(fec_enet_init);
+
+/* Make sure the device is shut down during initialization.
+*/
+static void __init
+init_fcc_shutdown(fcc_info_t *fip, struct fcc_enet_private *cep,
+ volatile cpm2_map_t *immap)
+{
+ volatile fcc_enet_t *ep;
+ volatile fcc_t *fccp;
+
+ /* Get pointer to FCC area in parameter RAM.
+ */
+ ep = (fcc_enet_t *)(&immap->im_dprambase[fip->fc_proff]);
+
+ /* And another to the FCC register area.
+ */
+ fccp = (volatile fcc_t *)(&immap->im_fcc[fip->fc_fccnum]);
+ cep->fccp = fccp; /* Keep the pointers handy */
+ cep->ep = ep;
+
+ /* Disable receive and transmit in case someone left it running.
+ */
+ fccp->fcc_gfmr &= ~(FCC_GFMR_ENR | FCC_GFMR_ENT);
+}
+
+/* Initialize the I/O pins for the FCC Ethernet.
+*/
+static void __init
+init_fcc_ioports(fcc_info_t *fip, volatile iop_cpm2_t *io,
+ volatile cpm2_map_t *immap)
+{
+
+ /* FCC1 pins are on port A/C. FCC2/3 are port B/C.
+ */
+ if (fip->fc_proff == PROFF_FCC1) {
+ /* Configure port A and C pins for FCC1 Ethernet.
+ */
+ io->iop_pdira &= ~PA1_DIRA_BOUT;
+ io->iop_pdira |= PA1_DIRA_BIN;
+ io->iop_psora &= ~PA1_PSORA_BOUT;
+ io->iop_psora |= PA1_PSORA_BIN;
+ io->iop_ppara |= (PA1_DIRA_BOUT | PA1_DIRA_BIN);
+ }
+ if (fip->fc_proff == PROFF_FCC2) {
+ /* Configure port B and C pins for FCC Ethernet.
+ */
+ io->iop_pdirb &= ~PB2_DIRB_BOUT;
+ io->iop_pdirb |= PB2_DIRB_BIN;
+ io->iop_psorb &= ~PB2_PSORB_BOUT;
+ io->iop_psorb |= PB2_PSORB_BIN;
+ io->iop_pparb |= (PB2_DIRB_BOUT | PB2_DIRB_BIN);
+ }
+ if (fip->fc_proff == PROFF_FCC3) {
+ /* Configure port B and C pins for FCC Ethernet.
+ */
+ io->iop_pdirb &= ~PB3_DIRB_BOUT;
+ io->iop_pdirb |= PB3_DIRB_BIN;
+ io->iop_psorb &= ~PB3_PSORB_BOUT;
+ io->iop_psorb |= PB3_PSORB_BIN;
+ io->iop_pparb |= (PB3_DIRB_BOUT | PB3_DIRB_BIN);
+
+ io->iop_pdirc &= ~PC3_DIRC_BOUT;
+ io->iop_pdirc |= PC3_DIRC_BIN;
+ io->iop_psorc &= ~PC3_PSORC_BOUT;
+ io->iop_psorc |= PC3_PSORC_BIN;
+ io->iop_pparc |= (PC3_DIRC_BOUT | PC3_DIRC_BIN);
+
+ }
+
+ /* Port C has clocks......
+ */
+ io->iop_psorc &= ~(fip->fc_trxclocks);
+ io->iop_pdirc &= ~(fip->fc_trxclocks);
+ io->iop_pparc |= fip->fc_trxclocks;
+
+#ifdef CONFIG_USE_MDIO
+ /* ....and the MII serial clock/data.
+ */
+ io->iop_pdatc |= (fip->fc_mdio | fip->fc_mdck);
+ io->iop_podrc &= ~(fip->fc_mdio | fip->fc_mdck);
+ io->iop_pdirc |= (fip->fc_mdio | fip->fc_mdck);
+ io->iop_pparc &= ~(fip->fc_mdio | fip->fc_mdck);
+#endif /* CONFIG_USE_MDIO */
+
+ /* Configure Serial Interface clock routing.
+ * First, clear all FCC bits to zero,
+ * then set the ones we want.
+ */
+ immap->im_cpmux.cmx_fcr &= ~(fip->fc_clockmask);
+ immap->im_cpmux.cmx_fcr |= fip->fc_clockroute;
+}
+
+static void __init
+init_fcc_param(fcc_info_t *fip, struct net_device *dev,
+ volatile cpm2_map_t *immap)
+{
+ unsigned char *eap;
+ unsigned long mem_addr;
+ bd_t *bd;
+ int i, j;
+ struct fcc_enet_private *cep;
+ volatile fcc_enet_t *ep;
+ volatile cbd_t *bdp;
+ volatile cpm_cpm2_t *cp;
+
+ cep = (struct fcc_enet_private *)(dev->priv);
+ ep = cep->ep;
+ cp = cpmp;
+
+ bd = (bd_t *)__res;
+
+ /* Zero the whole thing.....I must have missed some individually.
+ * It works when I do this.
+ */
+ memset((char *)ep, 0, sizeof(fcc_enet_t));
+
+ /* Allocate space for the buffer descriptors from regular memory.
+ * Initialize base addresses for the buffer descriptors.
+ */
+ cep->rx_bd_base = (cbd_t *)kmalloc(sizeof(cbd_t) * RX_RING_SIZE,
+ GFP_KERNEL | GFP_DMA);
+ ep->fen_genfcc.fcc_rbase = __pa(cep->rx_bd_base);
+ cep->tx_bd_base = (cbd_t *)kmalloc(sizeof(cbd_t) * TX_RING_SIZE,
+ GFP_KERNEL | GFP_DMA);
+ ep->fen_genfcc.fcc_tbase = __pa(cep->tx_bd_base);
+
+ cep->dirty_tx = cep->cur_tx = cep->tx_bd_base;
+ cep->cur_rx = cep->rx_bd_base;
+
+ ep->fen_genfcc.fcc_rstate = (CPMFCR_GBL | CPMFCR_EB) << 24;
+ ep->fen_genfcc.fcc_tstate = (CPMFCR_GBL | CPMFCR_EB) << 24;
+
+ /* Set maximum bytes per receive buffer.
+ * It must be a multiple of 32.
+ */
+ ep->fen_genfcc.fcc_mrblr = PKT_MAXBLR_SIZE;
+
+ /* Allocate space in the reserved FCC area of DPRAM for the
+ * internal buffers. No one uses this space (yet), so we
+ * can do this. Later, we will add resource management for
+ * this area.
+ */
+ mem_addr = CPM_FCC_SPECIAL_BASE + (fip->fc_fccnum * 128);
+ ep->fen_genfcc.fcc_riptr = mem_addr;
+ ep->fen_genfcc.fcc_tiptr = mem_addr+32;
+ ep->fen_padptr = mem_addr+64;
+ memset((char *)(&(immap->im_dprambase[(mem_addr+64)])), 0x88, 32);
+
+ ep->fen_genfcc.fcc_rbptr = 0;
+ ep->fen_genfcc.fcc_tbptr = 0;
+ ep->fen_genfcc.fcc_rcrc = 0;
+ ep->fen_genfcc.fcc_tcrc = 0;
+ ep->fen_genfcc.fcc_res1 = 0;
+ ep->fen_genfcc.fcc_res2 = 0;
+
+ ep->fen_camptr = 0; /* CAM isn't used in this driver */
+
+ /* Set CRC preset and mask.
+ */
+ ep->fen_cmask = 0xdebb20e3;
+ ep->fen_cpres = 0xffffffff;
+
+ ep->fen_crcec = 0; /* CRC Error counter */
+ ep->fen_alec = 0; /* alignment error counter */
+ ep->fen_disfc = 0; /* discard frame counter */
+ ep->fen_retlim = 15; /* Retry limit threshold */
+ ep->fen_pper = 0; /* Normal persistence */
+
+ /* Clear hash filter tables.
+ */
+ ep->fen_gaddrh = 0;
+ ep->fen_gaddrl = 0;
+ ep->fen_iaddrh = 0;
+ ep->fen_iaddrl = 0;
+
+ /* Clear the Out-of-sequence TxBD.
+ */
+ ep->fen_tfcstat = 0;
+ ep->fen_tfclen = 0;
+ ep->fen_tfcptr = 0;
+
+ ep->fen_mflr = PKT_MAXBUF_SIZE; /* maximum frame length register */
+ ep->fen_minflr = PKT_MINBUF_SIZE; /* minimum frame length register */
+
+ /* Set Ethernet station address.
+ *
+ * This is supplied in the board information structure, so we
+ * copy that into the controller.
+ * So, far we have only been given one Ethernet address. We make
+ * it unique by setting a few bits in the upper byte of the
+ * non-static part of the address.
+ */
+ eap = (unsigned char *)&(ep->fen_paddrh);
+ for (i=5; i>=0; i--) {
+
+/*
+ * The EP8260 only uses FCC3, so we can safely give it the real
+ * MAC address.
+ */
+#ifdef CONFIG_SBC82xx
+ if (i == 5) {
+ /* bd->bi_enetaddr holds the SCC0 address; the FCC
+ devices count up from there */
+ dev->dev_addr[i] = bd->bi_enetaddr[i] & ~3;
+ dev->dev_addr[i] += 1 + fip->fc_fccnum;
+ *eap++ = dev->dev_addr[i];
+ }
+#else
+#ifndef CONFIG_RPX8260
+ if (i == 3) {
+ dev->dev_addr[i] = bd->bi_enetaddr[i];
+ dev->dev_addr[i] |= (1 << (7 - fip->fc_fccnum));
+ *eap++ = dev->dev_addr[i];
+ } else
+#endif
+ {
+ *eap++ = dev->dev_addr[i] = bd->bi_enetaddr[i];
+ }
+#endif
+ }
+
+ ep->fen_taddrh = 0;
+ ep->fen_taddrm = 0;
+ ep->fen_taddrl = 0;
+
+ ep->fen_maxd1 = PKT_MAXDMA_SIZE; /* maximum DMA1 length */
+ ep->fen_maxd2 = PKT_MAXDMA_SIZE; /* maximum DMA2 length */
+
+ /* Clear stat counters, in case we ever enable RMON.
+ */
+ ep->fen_octc = 0;
+ ep->fen_colc = 0;
+ ep->fen_broc = 0;
+ ep->fen_mulc = 0;
+ ep->fen_uspc = 0;
+ ep->fen_frgc = 0;
+ ep->fen_ospc = 0;
+ ep->fen_jbrc = 0;
+ ep->fen_p64c = 0;
+ ep->fen_p65c = 0;
+ ep->fen_p128c = 0;
+ ep->fen_p256c = 0;
+ ep->fen_p512c = 0;
+ ep->fen_p1024c = 0;
+
+ ep->fen_rfthr = 0; /* Suggested by manual */
+ ep->fen_rfcnt = 0;
+ ep->fen_cftype = 0;
+
+ /* Now allocate the host memory pages and initialize the
+ * buffer descriptors.
+ */
+ bdp = cep->tx_bd_base;
+ for (i=0; i<TX_RING_SIZE; i++) {
+
+ /* Initialize the BD for every fragment in the page.
+ */
+ bdp->cbd_sc = 0;
+ bdp->cbd_datlen = 0;
+ bdp->cbd_bufaddr = 0;
+ bdp++;
+ }
+
+ /* Set the last buffer to wrap.
+ */
+ bdp--;
+ bdp->cbd_sc |= BD_SC_WRAP;
+
+ bdp = cep->rx_bd_base;
+ for (i=0; i<FCC_ENET_RX_PAGES; i++) {
+
+ /* Allocate a page.
+ */
+ mem_addr = __get_free_page(GFP_KERNEL);
+
+ /* Initialize the BD for every fragment in the page.
+ */
+ for (j=0; j<FCC_ENET_RX_FRPPG; j++) {
+ bdp->cbd_sc = BD_ENET_RX_EMPTY | BD_ENET_RX_INTR;
+ bdp->cbd_datlen = 0;
+ bdp->cbd_bufaddr = __pa(mem_addr);
+ mem_addr += FCC_ENET_RX_FRSIZE;
+ bdp++;
+ }
+ }
+
+ /* Set the last buffer to wrap.
+ */
+ bdp--;
+ bdp->cbd_sc |= BD_SC_WRAP;
+
+ /* Let's re-initialize the channel now. We have to do it later
+ * than the manual describes because we have just now finished
+ * the BD initialization.
+ */
+ cp->cp_cpcr = mk_cr_cmd(fip->fc_cpmpage, fip->fc_cpmblock, 0x0c,
+ CPM_CR_INIT_TRX) | CPM_CR_FLG;
+ while (cp->cp_cpcr & CPM_CR_FLG);
+
+ cep->skb_cur = cep->skb_dirty = 0;
+}
+
+/* Let 'er rip.
+*/
+static void __init
+init_fcc_startup(fcc_info_t *fip, struct net_device *dev)
+{
+ volatile fcc_t *fccp;
+ struct fcc_enet_private *cep;
+
+ cep = (struct fcc_enet_private *)(dev->priv);
+ fccp = cep->fccp;
+
+#ifdef CONFIG_RPX8260
+#ifdef PHY_INTERRUPT
+ /* Route PHY interrupt to IRQ. The following code only works for
+ * IRQ1 - IRQ7. It does not work for Port C interrupts.
+ */
+ *((volatile u_char *) (RPX_CSR_ADDR + 13)) &= ~BCSR13_FETH_IRQMASK;
+ *((volatile u_char *) (RPX_CSR_ADDR + 13)) |=
+ ((PHY_INTERRUPT - SIU_INT_IRQ1 + 1) << 4);
+#endif
+ /* Initialize MDIO pins. */
+ *((volatile u_char *) (RPX_CSR_ADDR + 4)) &= ~BCSR4_MII_MDC;
+ *((volatile u_char *) (RPX_CSR_ADDR + 4)) |=
+ BCSR4_MII_READ | BCSR4_MII_MDIO;
+ /* Enable external LXT971 PHY. */
+ *((volatile u_char *) (RPX_CSR_ADDR + 4)) |= BCSR4_EN_PHY;
+ udelay(1000);
+ *((volatile u_char *) (RPX_CSR_ADDR+ 4)) |= BCSR4_EN_MII;
+ udelay(1000);
+#endif /* ifdef CONFIG_RPX8260 */
+
+ fccp->fcc_fcce = 0xffff; /* Clear any pending events */
+
+ /* Leave FCC interrupts masked for now. Will be unmasked by
+ * fcc_restart().
+ */
+ fccp->fcc_fccm = 0;
+
+ /* Install our interrupt handler.
+ */
+ if (request_irq(fip->fc_interrupt, fcc_enet_interrupt, 0, "fenet",
+ dev) < 0)
+ printk("Can't get FCC IRQ %d\n", fip->fc_interrupt);
+
+#ifdef PHY_INTERRUPT
+#ifdef CONFIG_ADS8272
+ if (request_irq(PHY_INTERRUPT, mii_link_interrupt, SA_SHIRQ,
+ "mii", dev) < 0)
+ printk(KERN_CRIT "Can't get MII IRQ %d\n", PHY_INTERRUPT);
+#else
+ /* Make IRQn edge triggered. This does not work if PHY_INTERRUPT is
+ * on Port C.
+ */
+ ((volatile cpm2_map_t *) CPM_MAP_ADDR)->im_intctl.ic_siexr |=
+ (1 << (14 - (PHY_INTERRUPT - SIU_INT_IRQ1)));
+
+ if (request_irq(PHY_INTERRUPT, mii_link_interrupt, 0,
+ "mii", dev) < 0)
+ printk(KERN_CRIT "Can't get MII IRQ %d\n", PHY_INTERRUPT);
+#endif
+#endif /* PHY_INTERRUPT */
+
+ /* Set GFMR to enable Ethernet operating mode.
+ */
+ fccp->fcc_gfmr = (FCC_GFMR_TCI | FCC_GFMR_MODE_ENET);
+
+ /* Set sync/delimiters.
+ */
+ fccp->fcc_fdsr = 0xd555;
+
+ /* Set protocol specific processing mode for Ethernet.
+ * This has to be adjusted for Full Duplex operation after we can
+ * determine how to detect that.
+ */
+ fccp->fcc_fpsmr = FCC_PSMR_ENCRC;
+
+#ifdef CONFIG_PQ2ADS
+ /* Enable the PHY. */
+ *(volatile uint *)(BCSR_ADDR + 4) &= ~BCSR1_FETHIEN;
+ *(volatile uint *)(BCSR_ADDR + 4) |= BCSR1_FETH_RST;
+#endif
+#if defined(CONFIG_PQ2ADS) || defined(CONFIG_PQ2FADS)
+ /* Enable the 2nd PHY. */
+ *(volatile uint *)(BCSR_ADDR + 12) &= ~BCSR3_FETHIEN2;
+ *(volatile uint *)(BCSR_ADDR + 12) |= BCSR3_FETH2_RST;
+#endif
+
+#if defined(CONFIG_USE_MDIO) || defined(CONFIG_TQM8260)
+ /* start in full duplex mode, and negotiate speed
+ */
+ fcc_restart (dev, 1);
+#else
+ /* start in half duplex mode
+ */
+ fcc_restart (dev, 0);
+#endif
+}
+
+#ifdef CONFIG_USE_MDIO
+/* MII command/status interface.
+ * I'm not going to describe all of the details. You can find the
+ * protocol definition in many other places, including the data sheet
+ * of most PHY parts.
+ * I wonder what "they" were thinking (maybe weren't) when they leave
+ * the I2C in the CPM but I have to toggle these bits......
+ */
+#ifdef CONFIG_RPX8260
+ /* The EP8260 has the MDIO pins in a BCSR instead of on Port C
+ * like most other boards.
+ */
+#define MDIO_ADDR ((volatile u_char *)(RPX_CSR_ADDR + 4))
+#define MAKE_MDIO_OUTPUT *MDIO_ADDR &= ~BCSR4_MII_READ
+#define MAKE_MDIO_INPUT *MDIO_ADDR |= BCSR4_MII_READ | BCSR4_MII_MDIO
+#define OUT_MDIO(bit) \
+ if (bit) \
+ *MDIO_ADDR |= BCSR4_MII_MDIO; \
+ else \
+ *MDIO_ADDR &= ~BCSR4_MII_MDIO;
+#define IN_MDIO (*MDIO_ADDR & BCSR4_MII_MDIO)
+#define OUT_MDC(bit) \
+ if (bit) \
+ *MDIO_ADDR |= BCSR4_MII_MDC; \
+ else \
+ *MDIO_ADDR &= ~BCSR4_MII_MDC;
+#else /* ifdef CONFIG_RPX8260 */
+ /* This is for the usual case where the MDIO pins are on Port C.
+ */
+#define MDIO_ADDR (((volatile cpm2_map_t *)CPM_MAP_ADDR)->im_ioport)
+#define MAKE_MDIO_OUTPUT MDIO_ADDR.iop_pdirc |= fip->fc_mdio
+#define MAKE_MDIO_INPUT MDIO_ADDR.iop_pdirc &= ~fip->fc_mdio
+#define OUT_MDIO(bit) \
+ if (bit) \
+ MDIO_ADDR.iop_pdatc |= fip->fc_mdio; \
+ else \
+ MDIO_ADDR.iop_pdatc &= ~fip->fc_mdio;
+#define IN_MDIO ((MDIO_ADDR.iop_pdatc) & fip->fc_mdio)
+#define OUT_MDC(bit) \
+ if (bit) \
+ MDIO_ADDR.iop_pdatc |= fip->fc_mdck; \
+ else \
+ MDIO_ADDR.iop_pdatc &= ~fip->fc_mdck;
+#endif /* ifdef CONFIG_RPX8260 */
+
+static uint
+mii_send_receive(fcc_info_t *fip, uint cmd)
+{
+ uint retval;
+ int read_op, i, off;
+ const int us = 1;
+
+ read_op = ((cmd & 0xf0000000) == 0x60000000);
+
+ /* Write preamble
+ */
+ OUT_MDIO(1);
+ MAKE_MDIO_OUTPUT;
+ OUT_MDIO(1);
+ for (i = 0; i < 32; i++)
+ {
+ udelay(us);
+ OUT_MDC(1);
+ udelay(us);
+ OUT_MDC(0);
+ }
+
+ /* Write data
+ */
+ for (i = 0, off = 31; i < (read_op ? 14 : 32); i++, --off)
+ {
+ OUT_MDIO((cmd >> off) & 0x00000001);
+ udelay(us);
+ OUT_MDC(1);
+ udelay(us);
+ OUT_MDC(0);
+ }
+
+ retval = cmd;
+
+ if (read_op)
+ {
+ retval >>= 16;
+
+ MAKE_MDIO_INPUT;
+ udelay(us);
+ OUT_MDC(1);
+ udelay(us);
+ OUT_MDC(0);
+
+ for (i = 0; i < 16; i++)
+ {
+ udelay(us);
+ OUT_MDC(1);
+ udelay(us);
+ retval <<= 1;
+ if (IN_MDIO)
+ retval++;
+ OUT_MDC(0);
+ }
+ }
+
+ MAKE_MDIO_INPUT;
+ udelay(us);
+ OUT_MDC(1);
+ udelay(us);
+ OUT_MDC(0);
+
+ return retval;
+}
+#endif /* CONFIG_USE_MDIO */
+
+static void
+fcc_stop(struct net_device *dev)
+{
+ struct fcc_enet_private *fep= (struct fcc_enet_private *)(dev->priv);
+ volatile fcc_t *fccp = fep->fccp;
+ fcc_info_t *fip = fep->fip;
+ volatile fcc_enet_t *ep = fep->ep;
+ volatile cpm_cpm2_t *cp = cpmp;
+ volatile cbd_t *bdp;
+ int i;
+
+ if ((fccp->fcc_gfmr & (FCC_GFMR_ENR | FCC_GFMR_ENT)) == 0)
+ return; /* already down */
+
+ fccp->fcc_fccm = 0;
+
+ /* issue the graceful stop tx command */
+ while (cp->cp_cpcr & CPM_CR_FLG);
+ cp->cp_cpcr = mk_cr_cmd(fip->fc_cpmpage, fip->fc_cpmblock,
+ 0x0c, CPM_CR_GRA_STOP_TX) | CPM_CR_FLG;
+ while (cp->cp_cpcr & CPM_CR_FLG);
+
+ /* Disable transmit/receive */
+ fccp->fcc_gfmr &= ~(FCC_GFMR_ENR | FCC_GFMR_ENT);
+
+ /* issue the restart tx command */
+ fccp->fcc_fcce = FCC_ENET_GRA;
+ while (cp->cp_cpcr & CPM_CR_FLG);
+ cp->cp_cpcr = mk_cr_cmd(fip->fc_cpmpage, fip->fc_cpmblock,
+ 0x0c, CPM_CR_RESTART_TX) | CPM_CR_FLG;
+ while (cp->cp_cpcr & CPM_CR_FLG);
+
+ /* free tx buffers */
+ fep->skb_cur = fep->skb_dirty = 0;
+ for (i=0; i<=TX_RING_MOD_MASK; i++) {
+ if (fep->tx_skbuff[i] != NULL) {
+ dev_kfree_skb(fep->tx_skbuff[i]);
+ fep->tx_skbuff[i] = NULL;
+ }
+ }
+ fep->dirty_tx = fep->cur_tx = fep->tx_bd_base;
+ fep->tx_free = TX_RING_SIZE;
+ ep->fen_genfcc.fcc_tbptr = ep->fen_genfcc.fcc_tbase;
+
+ /* Initialize the tx buffer descriptors. */
+ bdp = fep->tx_bd_base;
+ for (i=0; i<TX_RING_SIZE; i++) {
+ bdp->cbd_sc = 0;
+ bdp->cbd_datlen = 0;
+ bdp->cbd_bufaddr = 0;
+ bdp++;
+ }
+ /* Set the last buffer to wrap. */
+ bdp--;
+ bdp->cbd_sc |= BD_SC_WRAP;
+}
+
+static void
+fcc_restart(struct net_device *dev, int duplex)
+{
+ struct fcc_enet_private *fep = (struct fcc_enet_private *)(dev->priv);
+ volatile fcc_t *fccp = fep->fccp;
+
+ /* stop any transmissions in progress */
+ fcc_stop(dev);
+
+ if (duplex)
+ fccp->fcc_fpsmr |= FCC_PSMR_FDE | FCC_PSMR_LPB;
+ else
+ fccp->fcc_fpsmr &= ~(FCC_PSMR_FDE | FCC_PSMR_LPB);
+
+ /* Enable interrupts for transmit error, complete frame
+ * received, and any transmit buffer we have also set the
+ * interrupt flag.
+ */
+ fccp->fcc_fccm = (FCC_ENET_TXE | FCC_ENET_RXF | FCC_ENET_TXB);
+
+ /* Enable transmit/receive */
+ fccp->fcc_gfmr |= FCC_GFMR_ENR | FCC_GFMR_ENT;
+}
+
+static int
+fcc_enet_open(struct net_device *dev)
+{
+ struct fcc_enet_private *fep = dev->priv;
+
+#ifdef CONFIG_USE_MDIO
+ fep->sequence_done = 0;
+ fep->link = 0;
+
+ if (fep->phy) {
+ fcc_restart(dev, 0); /* always start in half-duplex */
+ mii_do_cmd(dev, fep->phy->ack_int);
+ mii_do_cmd(dev, fep->phy->config);
+ mii_do_cmd(dev, phy_cmd_config); /* display configuration */
+ while(!fep->sequence_done)
+ schedule();
+
+ mii_do_cmd(dev, fep->phy->startup);
+ netif_start_queue(dev);
+ return 0; /* Success */
+ }
+ return -ENODEV; /* No PHY we understand */
+#else
+ fep->link = 1;
+ fcc_restart(dev, 0); /* always start in half-duplex */
+ netif_start_queue(dev);
+ return 0; /* Always succeed */
+#endif /* CONFIG_USE_MDIO */
+}
+
diff --git a/arch/ppc/8xx_io/Kconfig b/arch/ppc/8xx_io/Kconfig
new file mode 100644
index 0000000..9e2227e
--- /dev/null
+++ b/arch/ppc/8xx_io/Kconfig
@@ -0,0 +1,138 @@
+#
+# MPC8xx Communication options
+#
+
+menu "MPC8xx CPM Options"
+ depends on 8xx
+
+config SCC_ENET
+ bool "CPM SCC Ethernet"
+ depends on NET_ETHERNET
+ help
+ Enable Ethernet support via the Motorola MPC8xx serial
+ communications controller.
+
+choice
+ prompt "SCC used for Ethernet"
+ depends on SCC_ENET
+ default SCC1_ENET
+
+config SCC1_ENET
+ bool "SCC1"
+ help
+ Use MPC8xx serial communications controller 1 to drive Ethernet
+ (default).
+
+config SCC2_ENET
+ bool "SCC2"
+ help
+ Use MPC8xx serial communications controller 2 to drive Ethernet.
+
+config SCC3_ENET
+ bool "SCC3"
+ help
+ Use MPC8xx serial communications controller 3 to drive Ethernet.
+
+endchoice
+
+config FEC_ENET
+ bool "860T FEC Ethernet"
+ depends on NET_ETHERNET
+ help
+ Enable Ethernet support via the Fast Ethernet Controller (FCC) on
+ the Motorola MPC8260.
+
+config USE_MDIO
+ bool "Use MDIO for PHY configuration"
+ depends on FEC_ENET
+ help
+ On some boards the hardware configuration of the ethernet PHY can be
+ used without any software interaction over the MDIO interface, so
+ all MII code can be omitted. Say N here if unsure or if you don't
+ need link status reports.
+
+config FEC_AM79C874
+ bool "Support AMD79C874 PHY"
+ depends on USE_MDIO
+
+config FEC_LXT970
+ bool "Support LXT970 PHY"
+ depends on USE_MDIO
+
+config FEC_LXT971
+ bool "Support LXT971 PHY"
+ depends on USE_MDIO
+
+config FEC_QS6612
+ bool "Support QS6612 PHY"
+ depends on USE_MDIO
+
+config ENET_BIG_BUFFERS
+ bool "Use Big CPM Ethernet Buffers"
+ depends on NET_ETHERNET
+ help
+ Allocate large buffers for MPC8xx Etherenet. Increases throughput
+ and decreases the likelihood of dropped packets, but costs memory.
+
+config HTDMSOUND
+ bool "Embedded Planet HIOX Audio"
+ depends on SOUND=y
+
+# This doesn't really belong here, but it is convenient to ask
+# 8xx specific questions.
+comment "Generic MPC8xx Options"
+
+config 8xx_COPYBACK
+ bool "Copy-Back Data Cache (else Writethrough)"
+ help
+ Saying Y here will cause the cache on an MPC8xx processor to be used
+ in Copy-Back mode. If you say N here, it is used in Writethrough
+ mode.
+
+ If in doubt, say Y here.
+
+config 8xx_CPU6
+ bool "CPU6 Silicon Errata (860 Pre Rev. C)"
+ help
+ MPC860 CPUs, prior to Rev C have some bugs in the silicon, which
+ require workarounds for Linux (and most other OSes to work). If you
+ get a BUG() very early in boot, this might fix the problem. For
+ more details read the document entitled "MPC860 Family Device Errata
+ Reference" on Motorola's website. This option also incurs a
+ performance hit.
+
+ If in doubt, say N here.
+
+choice
+ prompt "Microcode patch selection"
+ default NO_UCODE_PATCH
+ help
+ Help not implemented yet, coming soon.
+
+config NO_UCODE_PATCH
+ bool "None"
+
+config USB_SOF_UCODE_PATCH
+ bool "USB SOF patch"
+ help
+ Help not implemented yet, coming soon.
+
+config I2C_SPI_UCODE_PATCH
+ bool "I2C/SPI relocation patch"
+ help
+ Help not implemented yet, coming soon.
+
+config I2C_SPI_SMC1_UCODE_PATCH
+ bool "I2C/SPI/SMC1 relocation patch"
+ help
+ Help not implemented yet, coming soon.
+
+endchoice
+
+config UCODE_PATCH
+ bool
+ default y
+ depends on !NO_UCODE_PATCH
+
+endmenu
+
diff --git a/arch/ppc/8xx_io/Makefile b/arch/ppc/8xx_io/Makefile
new file mode 100644
index 0000000..d876018
--- /dev/null
+++ b/arch/ppc/8xx_io/Makefile
@@ -0,0 +1,10 @@
+#
+# Makefile for the linux MPC8xx ppc-specific parts of comm processor
+#
+
+obj-y := commproc.o
+
+obj-$(CONFIG_FEC_ENET) += fec.o
+obj-$(CONFIG_SCC_ENET) += enet.o
+obj-$(CONFIG_UCODE_PATCH) += micropatch.o
+obj-$(CONFIG_HTDMSOUND) += cs4218_tdm.o
diff --git a/arch/ppc/8xx_io/commproc.c b/arch/ppc/8xx_io/commproc.c
new file mode 100644
index 0000000..0cc2e7a
--- /dev/null
+++ b/arch/ppc/8xx_io/commproc.c
@@ -0,0 +1,464 @@
+/*
+ * General Purpose functions for the global management of the
+ * Communication Processor Module.
+ * Copyright (c) 1997 Dan Malek (dmalek@jlc.net)
+ *
+ * In addition to the individual control of the communication
+ * channels, there are a few functions that globally affect the
+ * communication processor.
+ *
+ * Buffer descriptors must be allocated from the dual ported memory
+ * space. The allocator for that is here. When the communication
+ * process is reset, we reclaim the memory available. There is
+ * currently no deallocator for this memory.
+ * The amount of space available is platform dependent. On the
+ * MBX, the EPPC software loads additional microcode into the
+ * communication processor, and uses some of the DP ram for this
+ * purpose. Current, the first 512 bytes and the last 256 bytes of
+ * memory are used. Right now I am conservative and only use the
+ * memory that can never be used for microcode. If there are
+ * applications that require more DP ram, we can expand the boundaries
+ * but then we have to be careful of any downloaded microcode.
+ */
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/dma-mapping.h>
+#include <linux/param.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/module.h>
+#include <asm/mpc8xx.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <asm/8xx_immap.h>
+#include <asm/commproc.h>
+#include <asm/io.h>
+#include <asm/tlbflush.h>
+#include <asm/rheap.h>
+
+extern int get_pteptr(struct mm_struct *mm, unsigned long addr, pte_t **ptep);
+
+static void m8xx_cpm_dpinit(void);
+static uint host_buffer; /* One page of host buffer */
+static uint host_end; /* end + 1 */
+cpm8xx_t *cpmp; /* Pointer to comm processor space */
+
+/* CPM interrupt vector functions.
+*/
+struct cpm_action {
+ void (*handler)(void *, struct pt_regs * regs);
+ void *dev_id;
+};
+static struct cpm_action cpm_vecs[CPMVEC_NR];
+static irqreturn_t cpm_interrupt(int irq, void * dev, struct pt_regs * regs);
+static irqreturn_t cpm_error_interrupt(int irq, void *dev, struct pt_regs * regs);
+static void alloc_host_memory(void);
+/* Define a table of names to identify CPM interrupt handlers in
+ * /proc/interrupts.
+ */
+const char *cpm_int_name[] =
+ { "error", "PC4", "PC5", "SMC2",
+ "SMC1", "SPI", "PC6", "Timer 4",
+ "", "PC7", "PC8", "PC9",
+ "Timer 3", "", "PC10", "PC11",
+ "I2C", "RISC Timer", "Timer 2", "",
+ "IDMA2", "IDMA1", "SDMA error", "PC12",
+ "PC13", "Timer 1", "PC14", "SCC4",
+ "SCC3", "SCC2", "SCC1", "PC15"
+ };
+
+static void
+cpm_mask_irq(unsigned int irq)
+{
+ int cpm_vec = irq - CPM_IRQ_OFFSET;
+
+ ((immap_t *)IMAP_ADDR)->im_cpic.cpic_cimr &= ~(1 << cpm_vec);
+}
+
+static void
+cpm_unmask_irq(unsigned int irq)
+{
+ int cpm_vec = irq - CPM_IRQ_OFFSET;
+
+ ((immap_t *)IMAP_ADDR)->im_cpic.cpic_cimr |= (1 << cpm_vec);
+}
+
+static void
+cpm_ack(unsigned int irq)
+{
+ /* We do not need to do anything here. */
+}
+
+static void
+cpm_eoi(unsigned int irq)
+{
+ int cpm_vec = irq - CPM_IRQ_OFFSET;
+
+ ((immap_t *)IMAP_ADDR)->im_cpic.cpic_cisr = (1 << cpm_vec);
+}
+
+struct hw_interrupt_type cpm_pic = {
+ .typename = " CPM ",
+ .enable = cpm_unmask_irq,
+ .disable = cpm_mask_irq,
+ .ack = cpm_ack,
+ .end = cpm_eoi,
+};
+
+extern void flush_tlb_page(struct vm_area_struct *vma, unsigned long vmaddr);
+
+void
+m8xx_cpm_reset(uint bootpage)
+{
+ volatile immap_t *imp;
+ volatile cpm8xx_t *commproc;
+ pte_t *pte;
+
+ imp = (immap_t *)IMAP_ADDR;
+ commproc = (cpm8xx_t *)&imp->im_cpm;
+
+#ifdef CONFIG_UCODE_PATCH
+ /* Perform a reset.
+ */
+ commproc->cp_cpcr = (CPM_CR_RST | CPM_CR_FLG);
+
+ /* Wait for it.
+ */
+ while (commproc->cp_cpcr & CPM_CR_FLG);
+
+ cpm_load_patch(imp);
+#endif
+
+ /* Set SDMA Bus Request priority 5.
+ * On 860T, this also enables FEC priority 6. I am not sure
+ * this is what we realy want for some applications, but the
+ * manual recommends it.
+ * Bit 25, FAM can also be set to use FEC aggressive mode (860T).
+ */
+ imp->im_siu_conf.sc_sdcr = 1;
+
+ /* Reclaim the DP memory for our use. */
+ m8xx_cpm_dpinit();
+
+ /* get the PTE for the bootpage */
+ if (!get_pteptr(&init_mm, bootpage, &pte))
+ panic("get_pteptr failed\n");
+
+ /* and make it uncachable */
+ pte_val(*pte) |= _PAGE_NO_CACHE;
+ _tlbie(bootpage);
+
+ host_buffer = bootpage;
+ host_end = host_buffer + PAGE_SIZE;
+
+ /* Tell everyone where the comm processor resides.
+ */
+ cpmp = (cpm8xx_t *)commproc;
+}
+
+/* We used to do this earlier, but have to postpone as long as possible
+ * to ensure the kernel VM is now running.
+ */
+static void
+alloc_host_memory(void)
+{
+ dma_addr_t physaddr;
+
+ /* Set the host page for allocation.
+ */
+ host_buffer = (uint)dma_alloc_coherent(NULL, PAGE_SIZE, &physaddr,
+ GFP_KERNEL);
+ host_end = host_buffer + PAGE_SIZE;
+}
+
+/* This is called during init_IRQ. We used to do it above, but this
+ * was too early since init_IRQ was not yet called.
+ */
+static struct irqaction cpm_error_irqaction = {
+ .handler = cpm_error_interrupt,
+ .mask = CPU_MASK_NONE,
+};
+static struct irqaction cpm_interrupt_irqaction = {
+ .handler = cpm_interrupt,
+ .mask = CPU_MASK_NONE,
+ .name = "CPM cascade",
+};
+
+void
+cpm_interrupt_init(void)
+{
+ int i;
+
+ /* Initialize the CPM interrupt controller.
+ */
+ ((immap_t *)IMAP_ADDR)->im_cpic.cpic_cicr =
+ (CICR_SCD_SCC4 | CICR_SCC_SCC3 | CICR_SCB_SCC2 | CICR_SCA_SCC1) |
+ ((CPM_INTERRUPT/2) << 13) | CICR_HP_MASK;
+ ((immap_t *)IMAP_ADDR)->im_cpic.cpic_cimr = 0;
+
+ /* install the CPM interrupt controller routines for the CPM
+ * interrupt vectors
+ */
+ for ( i = CPM_IRQ_OFFSET ; i < CPM_IRQ_OFFSET + NR_CPM_INTS ; i++ )
+ irq_desc[i].handler = &cpm_pic;
+
+ /* Set our interrupt handler with the core CPU. */
+ if (setup_irq(CPM_INTERRUPT, &cpm_interrupt_irqaction))
+ panic("Could not allocate CPM IRQ!");
+
+ /* Install our own error handler. */
+ cpm_error_irqaction.name = cpm_int_name[CPMVEC_ERROR];
+ if (setup_irq(CPM_IRQ_OFFSET + CPMVEC_ERROR, &cpm_error_irqaction))
+ panic("Could not allocate CPM error IRQ!");
+
+ ((immap_t *)IMAP_ADDR)->im_cpic.cpic_cicr |= CICR_IEN;
+}
+
+/*
+ * Get the CPM interrupt vector.
+ */
+int
+cpm_get_irq(struct pt_regs *regs)
+{
+ int cpm_vec;
+
+ /* Get the vector by setting the ACK bit and then reading
+ * the register.
+ */
+ ((volatile immap_t *)IMAP_ADDR)->im_cpic.cpic_civr = 1;
+ cpm_vec = ((volatile immap_t *)IMAP_ADDR)->im_cpic.cpic_civr;
+ cpm_vec >>= 11;
+
+ return cpm_vec;
+}
+
+/* CPM interrupt controller cascade interrupt.
+*/
+static irqreturn_t
+cpm_interrupt(int irq, void * dev, struct pt_regs * regs)
+{
+ /* This interrupt handler never actually gets called. It is
+ * installed only to unmask the CPM cascade interrupt in the SIU
+ * and to make the CPM cascade interrupt visible in /proc/interrupts.
+ */
+ return IRQ_HANDLED;
+}
+
+/* The CPM can generate the error interrupt when there is a race condition
+ * between generating and masking interrupts. All we have to do is ACK it
+ * and return. This is a no-op function so we don't need any special
+ * tests in the interrupt handler.
+ */
+static irqreturn_t
+cpm_error_interrupt(int irq, void *dev, struct pt_regs *regs)
+{
+ return IRQ_HANDLED;
+}
+
+/* A helper function to translate the handler prototype required by
+ * request_irq() to the handler prototype required by cpm_install_handler().
+ */
+static irqreturn_t
+cpm_handler_helper(int irq, void *dev_id, struct pt_regs *regs)
+{
+ int cpm_vec = irq - CPM_IRQ_OFFSET;
+
+ (*cpm_vecs[cpm_vec].handler)(dev_id, regs);
+
+ return IRQ_HANDLED;
+}
+
+/* Install a CPM interrupt handler.
+ * This routine accepts a CPM interrupt vector in the range 0 to 31.
+ * This routine is retained for backward compatibility. Rather than using
+ * this routine to install a CPM interrupt handler, you can now use
+ * request_irq() with an IRQ in the range CPM_IRQ_OFFSET to
+ * CPM_IRQ_OFFSET + NR_CPM_INTS - 1 (16 to 47).
+ *
+ * Notice that the prototype of the interrupt handler function must be
+ * different depending on whether you install the handler with
+ * request_irq() or cpm_install_handler().
+ */
+void
+cpm_install_handler(int cpm_vec, void (*handler)(void *, struct pt_regs *regs),
+ void *dev_id)
+{
+ int err;
+
+ /* If null handler, assume we are trying to free the IRQ.
+ */
+ if (!handler) {
+ free_irq(CPM_IRQ_OFFSET + cpm_vec, dev_id);
+ return;
+ }
+
+ if (cpm_vecs[cpm_vec].handler != 0)
+ printk(KERN_INFO "CPM interrupt %x replacing %x\n",
+ (uint)handler, (uint)cpm_vecs[cpm_vec].handler);
+ cpm_vecs[cpm_vec].handler = handler;
+ cpm_vecs[cpm_vec].dev_id = dev_id;
+
+ if ((err = request_irq(CPM_IRQ_OFFSET + cpm_vec, cpm_handler_helper,
+ 0, cpm_int_name[cpm_vec], dev_id)))
+ printk(KERN_ERR "request_irq() returned %d for CPM vector %d\n",
+ err, cpm_vec);
+}
+
+/* Free a CPM interrupt handler.
+ * This routine accepts a CPM interrupt vector in the range 0 to 31.
+ * This routine is retained for backward compatibility.
+ */
+void
+cpm_free_handler(int cpm_vec)
+{
+ request_irq(CPM_IRQ_OFFSET + cpm_vec, NULL, 0, 0,
+ cpm_vecs[cpm_vec].dev_id);
+
+ cpm_vecs[cpm_vec].handler = NULL;
+ cpm_vecs[cpm_vec].dev_id = NULL;
+}
+
+/* We also own one page of host buffer space for the allocation of
+ * UART "fifos" and the like.
+ */
+uint
+m8xx_cpm_hostalloc(uint size)
+{
+ uint retloc;
+
+ if (host_buffer == 0)
+ alloc_host_memory();
+
+ if ((host_buffer + size) >= host_end)
+ return(0);
+
+ retloc = host_buffer;
+ host_buffer += size;
+
+ return(retloc);
+}
+
+/* Set a baud rate generator. This needs lots of work. There are
+ * four BRGs, any of which can be wired to any channel.
+ * The internal baud rate clock is the system clock divided by 16.
+ * This assumes the baudrate is 16x oversampled by the uart.
+ */
+#define BRG_INT_CLK (((bd_t *)__res)->bi_intfreq)
+#define BRG_UART_CLK (BRG_INT_CLK/16)
+#define BRG_UART_CLK_DIV16 (BRG_UART_CLK/16)
+
+void
+cpm_setbrg(uint brg, uint rate)
+{
+ volatile uint *bp;
+
+ /* This is good enough to get SMCs running.....
+ */
+ bp = (uint *)&cpmp->cp_brgc1;
+ bp += brg;
+ /* The BRG has a 12-bit counter. For really slow baud rates (or
+ * really fast processors), we may have to further divide by 16.
+ */
+ if (((BRG_UART_CLK / rate) - 1) < 4096)
+ *bp = (((BRG_UART_CLK / rate) - 1) << 1) | CPM_BRG_EN;
+ else
+ *bp = (((BRG_UART_CLK_DIV16 / rate) - 1) << 1) |
+ CPM_BRG_EN | CPM_BRG_DIV16;
+}
+
+/*
+ * dpalloc / dpfree bits.
+ */
+static spinlock_t cpm_dpmem_lock;
+/*
+ * 16 blocks should be enough to satisfy all requests
+ * until the memory subsystem goes up...
+ */
+static rh_block_t cpm_boot_dpmem_rh_block[16];
+static rh_info_t cpm_dpmem_info;
+
+#define CPM_DPMEM_ALIGNMENT 8
+
+void m8xx_cpm_dpinit(void)
+{
+ cpm8xx_t *cp = &((immap_t *)IMAP_ADDR)->im_cpm;
+
+ spin_lock_init(&cpm_dpmem_lock);
+
+ /* Initialize the info header */
+ rh_init(&cpm_dpmem_info, CPM_DPMEM_ALIGNMENT,
+ sizeof(cpm_boot_dpmem_rh_block) /
+ sizeof(cpm_boot_dpmem_rh_block[0]),
+ cpm_boot_dpmem_rh_block);
+
+ /*
+ * Attach the usable dpmem area.
+ * XXX: This is actually crap. CPM_DATAONLY_BASE and
+ * CPM_DATAONLY_SIZE are a subset of the available dparm. It varies
+ * with the processor and the microcode patches applied / activated.
+ * But the following should be at least safe.
+ */
+ rh_attach_region(&cpm_dpmem_info, (void *)CPM_DATAONLY_BASE, CPM_DATAONLY_SIZE);
+}
+
+/*
+ * Allocate the requested size worth of DP memory.
+ * This function used to return an index into the DPRAM area.
+ * Now it returns the actuall physical address of that area.
+ * use m8xx_cpm_dpram_offset() to get the index
+ */
+uint cpm_dpalloc(uint size, uint align)
+{
+ void *start;
+ unsigned long flags;
+
+ spin_lock_irqsave(&cpm_dpmem_lock, flags);
+ cpm_dpmem_info.alignment = align;
+ start = rh_alloc(&cpm_dpmem_info, size, "commproc");
+ spin_unlock_irqrestore(&cpm_dpmem_lock, flags);
+
+ return (uint)start;
+}
+EXPORT_SYMBOL(cpm_dpalloc);
+
+int cpm_dpfree(uint offset)
+{
+ int ret;
+ unsigned long flags;
+
+ spin_lock_irqsave(&cpm_dpmem_lock, flags);
+ ret = rh_free(&cpm_dpmem_info, (void *)offset);
+ spin_unlock_irqrestore(&cpm_dpmem_lock, flags);
+
+ return ret;
+}
+EXPORT_SYMBOL(cpm_dpfree);
+
+uint cpm_dpalloc_fixed(uint offset, uint size, uint align)
+{
+ void *start;
+ unsigned long flags;
+
+ spin_lock_irqsave(&cpm_dpmem_lock, flags);
+ cpm_dpmem_info.alignment = align;
+ start = rh_alloc_fixed(&cpm_dpmem_info, (void *)offset, size, "commproc");
+ spin_unlock_irqrestore(&cpm_dpmem_lock, flags);
+
+ return (uint)start;
+}
+EXPORT_SYMBOL(cpm_dpalloc_fixed);
+
+void cpm_dpdump(void)
+{
+ rh_dump(&cpm_dpmem_info);
+}
+EXPORT_SYMBOL(cpm_dpdump);
+
+void *cpm_dpram_addr(uint offset)
+{
+ return ((immap_t *)IMAP_ADDR)->im_cpm.cp_dpmem + offset;
+}
+EXPORT_SYMBOL(cpm_dpram_addr);
diff --git a/arch/ppc/8xx_io/cs4218.h b/arch/ppc/8xx_io/cs4218.h
new file mode 100644
index 0000000..a3c38c5
--- /dev/null
+++ b/arch/ppc/8xx_io/cs4218.h
@@ -0,0 +1,167 @@
+#ifndef _cs4218_h_
+/*
+ * Hacked version of linux/drivers/sound/dmasound/dmasound.h
+ *
+ *
+ * Minor numbers for the sound driver.
+ *
+ * Unfortunately Creative called the codec chip of SB as a DSP. For this
+ * reason the /dev/dsp is reserved for digitized audio use. There is a
+ * device for true DSP processors but it will be called something else.
+ * In v3.0 it's /dev/sndproc but this could be a temporary solution.
+ */
+#define _cs4218_h_
+
+#include <linux/types.h>
+#include <linux/config.h>
+
+#define SND_NDEVS 256 /* Number of supported devices */
+#define SND_DEV_CTL 0 /* Control port /dev/mixer */
+#define SND_DEV_SEQ 1 /* Sequencer output /dev/sequencer (FM
+ synthesizer and MIDI output) */
+#define SND_DEV_MIDIN 2 /* Raw midi access */
+#define SND_DEV_DSP 3 /* Digitized voice /dev/dsp */
+#define SND_DEV_AUDIO 4 /* Sparc compatible /dev/audio */
+#define SND_DEV_DSP16 5 /* Like /dev/dsp but 16 bits/sample */
+#define SND_DEV_STATUS 6 /* /dev/sndstat */
+/* #7 not in use now. Was in 2.4. Free for use after v3.0. */
+#define SND_DEV_SEQ2 8 /* /dev/sequencer, level 2 interface */
+#define SND_DEV_SNDPROC 9 /* /dev/sndproc for programmable devices */
+#define SND_DEV_PSS SND_DEV_SNDPROC
+
+/* switch on various prinks */
+#define DEBUG_DMASOUND 1
+
+#define MAX_AUDIO_DEV 5
+#define MAX_MIXER_DEV 4
+#define MAX_SYNTH_DEV 3
+#define MAX_MIDI_DEV 6
+#define MAX_TIMER_DEV 3
+
+#define MAX_CATCH_RADIUS 10
+
+#define le2be16(x) (((x)<<8 & 0xff00) | ((x)>>8 & 0x00ff))
+#define le2be16dbl(x) (((x)<<8 & 0xff00ff00) | ((x)>>8 & 0x00ff00ff))
+
+#define IOCTL_IN(arg, ret) \
+ do { int error = get_user(ret, (int *)(arg)); \
+ if (error) return error; \
+ } while (0)
+#define IOCTL_OUT(arg, ret) ioctl_return((int *)(arg), ret)
+
+static inline int ioctl_return(int *addr, int value)
+{
+ return value < 0 ? value : put_user(value, addr);
+}
+
+#define HAS_RECORD
+
+ /*
+ * Initialization
+ */
+
+/* description of the set-up applies to either hard or soft settings */
+
+typedef struct {
+ int format; /* AFMT_* */
+ int stereo; /* 0 = mono, 1 = stereo */
+ int size; /* 8/16 bit*/
+ int speed; /* speed */
+} SETTINGS;
+
+ /*
+ * Machine definitions
+ */
+
+typedef struct {
+ const char *name;
+ const char *name2;
+ void (*open)(void);
+ void (*release)(void);
+ void *(*dma_alloc)(unsigned int, int);
+ void (*dma_free)(void *, unsigned int);
+ int (*irqinit)(void);
+#ifdef MODULE
+ void (*irqcleanup)(void);
+#endif
+ void (*init)(void);
+ void (*silence)(void);
+ int (*setFormat)(int);
+ int (*setVolume)(int);
+ int (*setBass)(int);
+ int (*setTreble)(int);
+ int (*setGain)(int);
+ void (*play)(void);
+ void (*record)(void); /* optional */
+ void (*mixer_init)(void); /* optional */
+ int (*mixer_ioctl)(u_int, u_long); /* optional */
+ int (*write_sq_setup)(void); /* optional */
+ int (*read_sq_setup)(void); /* optional */
+ int (*sq_open)(mode_t); /* optional */
+ int (*state_info)(char *, size_t); /* optional */
+ void (*abort_read)(void); /* optional */
+ int min_dsp_speed;
+ int max_dsp_speed;
+ int version ;
+ int hardware_afmts ; /* OSS says we only return h'ware info */
+ /* when queried via SNDCTL_DSP_GETFMTS */
+ int capabilities ; /* low-level reply to SNDCTL_DSP_GETCAPS */
+ SETTINGS default_hard ; /* open() or init() should set something valid */
+ SETTINGS default_soft ; /* you can make it look like old OSS, if you want to */
+} MACHINE;
+
+ /*
+ * Low level stuff
+ */
+
+typedef struct {
+ ssize_t (*ct_ulaw)(const u_char *, size_t, u_char *, ssize_t *, ssize_t);
+ ssize_t (*ct_alaw)(const u_char *, size_t, u_char *, ssize_t *, ssize_t);
+ ssize_t (*ct_s8)(const u_char *, size_t, u_char *, ssize_t *, ssize_t);
+ ssize_t (*ct_u8)(const u_char *, size_t, u_char *, ssize_t *, ssize_t);
+ ssize_t (*ct_s16be)(const u_char *, size_t, u_char *, ssize_t *, ssize_t);
+ ssize_t (*ct_u16be)(const u_char *, size_t, u_char *, ssize_t *, ssize_t);
+ ssize_t (*ct_s16le)(const u_char *, size_t, u_char *, ssize_t *, ssize_t);
+ ssize_t (*ct_u16le)(const u_char *, size_t, u_char *, ssize_t *, ssize_t);
+} TRANS;
+
+
+ /*
+ * Sound queue stuff, the heart of the driver
+ */
+
+struct sound_queue {
+ /* buffers allocated for this queue */
+ int numBufs; /* real limits on what the user can have */
+ int bufSize; /* in bytes */
+ char **buffers;
+
+ /* current parameters */
+ int locked ; /* params cannot be modified when != 0 */
+ int user_frags ; /* user requests this many */
+ int user_frag_size ; /* of this size */
+ int max_count; /* actual # fragments <= numBufs */
+ int block_size; /* internal block size in bytes */
+ int max_active; /* in-use fragments <= max_count */
+
+ /* it shouldn't be necessary to declare any of these volatile */
+ int front, rear, count;
+ int rear_size;
+ /*
+ * The use of the playing field depends on the hardware
+ *
+ * Atari, PMac: The number of frames that are loaded/playing
+ *
+ * Amiga: Bit 0 is set: a frame is loaded
+ * Bit 1 is set: a frame is playing
+ */
+ int active;
+ wait_queue_head_t action_queue, open_queue, sync_queue;
+ int open_mode;
+ int busy, syncing, xruns, died;
+};
+
+#define SLEEP(queue) interruptible_sleep_on_timeout(&queue, HZ)
+#define WAKE_UP(queue) (wake_up_interruptible(&queue))
+
+#endif /* _cs4218_h_ */
diff --git a/arch/ppc/8xx_io/cs4218_tdm.c b/arch/ppc/8xx_io/cs4218_tdm.c
new file mode 100644
index 0000000..89fe0ce
--- /dev/null
+++ b/arch/ppc/8xx_io/cs4218_tdm.c
@@ -0,0 +1,2836 @@
+
+/* This is a modified version of linux/drivers/sound/dmasound.c to
+ * support the CS4218 codec on the 8xx TDM port. Thanks to everyone
+ * that contributed to the dmasound software (which includes me :-).
+ *
+ * The CS4218 is configured in Mode 4, sub-mode 0. This provides
+ * left/right data only on the TDM port, as a 32-bit word, per frame
+ * pulse. The control of the CS4218 is provided by some other means,
+ * like the SPI port.
+ * Dan Malek (dmalek@jlc.net)
+ */
+
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/timer.h>
+#include <linux/major.h>
+#include <linux/config.h>
+#include <linux/fcntl.h>
+#include <linux/errno.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+#include <linux/sound.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+
+#include <asm/system.h>
+#include <asm/irq.h>
+#include <asm/pgtable.h>
+#include <asm/uaccess.h>
+#include <asm/io.h>
+
+/* Should probably do something different with this path name.....
+ * Actually, I should just stop using it...
+ */
+#include "cs4218.h"
+#include <linux/soundcard.h>
+
+#include <asm/mpc8xx.h>
+#include <asm/8xx_immap.h>
+#include <asm/commproc.h>
+
+#define DMASND_CS4218 5
+
+#define MAX_CATCH_RADIUS 10
+#define MIN_BUFFERS 4
+#define MIN_BUFSIZE 4
+#define MAX_BUFSIZE 128
+
+#define HAS_8BIT_TABLES
+
+static int sq_unit = -1;
+static int mixer_unit = -1;
+static int state_unit = -1;
+static int irq_installed = 0;
+static char **sound_buffers = NULL;
+static char **sound_read_buffers = NULL;
+
+static DEFINE_SPINLOCK(cs4218_lock);
+
+/* Local copies of things we put in the control register. Output
+ * volume, like most codecs is really attenuation.
+ */
+static int cs4218_rate_index;
+
+/*
+ * Stuff for outputting a beep. The values range from -327 to +327
+ * so we can multiply by an amplitude in the range 0..100 to get a
+ * signed short value to put in the output buffer.
+ */
+static short beep_wform[256] = {
+ 0, 40, 79, 117, 153, 187, 218, 245,
+ 269, 288, 304, 316, 323, 327, 327, 324,
+ 318, 310, 299, 288, 275, 262, 249, 236,
+ 224, 213, 204, 196, 190, 186, 183, 182,
+ 182, 183, 186, 189, 192, 196, 200, 203,
+ 206, 208, 209, 209, 209, 207, 204, 201,
+ 197, 193, 188, 183, 179, 174, 170, 166,
+ 163, 161, 160, 159, 159, 160, 161, 162,
+ 164, 166, 168, 169, 171, 171, 171, 170,
+ 169, 167, 163, 159, 155, 150, 144, 139,
+ 133, 128, 122, 117, 113, 110, 107, 105,
+ 103, 103, 103, 103, 104, 104, 105, 105,
+ 105, 103, 101, 97, 92, 86, 78, 68,
+ 58, 45, 32, 18, 3, -11, -26, -41,
+ -55, -68, -79, -88, -95, -100, -102, -102,
+ -99, -93, -85, -75, -62, -48, -33, -16,
+ 0, 16, 33, 48, 62, 75, 85, 93,
+ 99, 102, 102, 100, 95, 88, 79, 68,
+ 55, 41, 26, 11, -3, -18, -32, -45,
+ -58, -68, -78, -86, -92, -97, -101, -103,
+ -105, -105, -105, -104, -104, -103, -103, -103,
+ -103, -105, -107, -110, -113, -117, -122, -128,
+ -133, -139, -144, -150, -155, -159, -163, -167,
+ -169, -170, -171, -171, -171, -169, -168, -166,
+ -164, -162, -161, -160, -159, -159, -160, -161,
+ -163, -166, -170, -174, -179, -183, -188, -193,
+ -197, -201, -204, -207, -209, -209, -209, -208,
+ -206, -203, -200, -196, -192, -189, -186, -183,
+ -182, -182, -183, -186, -190, -196, -204, -213,
+ -224, -236, -249, -262, -275, -288, -299, -310,
+ -318, -324, -327, -327, -323, -316, -304, -288,
+ -269, -245, -218, -187, -153, -117, -79, -40,
+};
+
+#define BEEP_SPEED 5 /* 22050 Hz sample rate */
+#define BEEP_BUFLEN 512
+#define BEEP_VOLUME 15 /* 0 - 100 */
+
+static int beep_volume = BEEP_VOLUME;
+static int beep_playing = 0;
+static int beep_state = 0;
+static short *beep_buf;
+static void (*orig_mksound)(unsigned int, unsigned int);
+
+/* This is found someplace else......I guess in the keyboard driver
+ * we don't include.
+ */
+static void (*kd_mksound)(unsigned int, unsigned int);
+
+static int catchRadius = 0;
+static int numBufs = 4, bufSize = 32;
+static int numReadBufs = 4, readbufSize = 32;
+
+
+/* TDM/Serial transmit and receive buffer descriptors.
+*/
+static volatile cbd_t *rx_base, *rx_cur, *tx_base, *tx_cur;
+
+MODULE_PARM(catchRadius, "i");
+MODULE_PARM(numBufs, "i");
+MODULE_PARM(bufSize, "i");
+MODULE_PARM(numreadBufs, "i");
+MODULE_PARM(readbufSize, "i");
+
+#define arraysize(x) (sizeof(x)/sizeof(*(x)))
+#define le2be16(x) (((x)<<8 & 0xff00) | ((x)>>8 & 0x00ff))
+#define le2be16dbl(x) (((x)<<8 & 0xff00ff00) | ((x)>>8 & 0x00ff00ff))
+
+#define IOCTL_IN(arg, ret) \
+ do { int error = get_user(ret, (int *)(arg)); \
+ if (error) return error; \
+ } while (0)
+#define IOCTL_OUT(arg, ret) ioctl_return((int *)(arg), ret)
+
+/* CS4218 serial port control in mode 4.
+*/
+#define CS_INTMASK ((uint)0x40000000)
+#define CS_DO1 ((uint)0x20000000)
+#define CS_LATTEN ((uint)0x1f000000)
+#define CS_RATTEN ((uint)0x00f80000)
+#define CS_MUTE ((uint)0x00040000)
+#define CS_ISL ((uint)0x00020000)
+#define CS_ISR ((uint)0x00010000)
+#define CS_LGAIN ((uint)0x0000f000)
+#define CS_RGAIN ((uint)0x00000f00)
+
+#define CS_LATTEN_SET(X) (((X) & 0x1f) << 24)
+#define CS_RATTEN_SET(X) (((X) & 0x1f) << 19)
+#define CS_LGAIN_SET(X) (((X) & 0x0f) << 12)
+#define CS_RGAIN_SET(X) (((X) & 0x0f) << 8)
+
+#define CS_LATTEN_GET(X) (((X) >> 24) & 0x1f)
+#define CS_RATTEN_GET(X) (((X) >> 19) & 0x1f)
+#define CS_LGAIN_GET(X) (((X) >> 12) & 0x0f)
+#define CS_RGAIN_GET(X) (((X) >> 8) & 0x0f)
+
+/* The control register is effectively write only. We have to keep a copy
+ * of what we write.
+ */
+static uint cs4218_control;
+
+/* A place to store expanding information.
+*/
+static int expand_bal;
+static int expand_data;
+
+/* Since I can't make the microcode patch work for the SPI, I just
+ * clock the bits using software.
+ */
+static void sw_spi_init(void);
+static void sw_spi_io(u_char *obuf, u_char *ibuf, uint bcnt);
+static uint cs4218_ctl_write(uint ctlreg);
+
+/*** Some low level helpers **************************************************/
+
+/* 16 bit mu-law */
+
+static short ulaw2dma16[] = {
+ -32124, -31100, -30076, -29052, -28028, -27004, -25980, -24956,
+ -23932, -22908, -21884, -20860, -19836, -18812, -17788, -16764,
+ -15996, -15484, -14972, -14460, -13948, -13436, -12924, -12412,
+ -11900, -11388, -10876, -10364, -9852, -9340, -8828, -8316,
+ -7932, -7676, -7420, -7164, -6908, -6652, -6396, -6140,
+ -5884, -5628, -5372, -5116, -4860, -4604, -4348, -4092,
+ -3900, -3772, -3644, -3516, -3388, -3260, -3132, -3004,
+ -2876, -2748, -2620, -2492, -2364, -2236, -2108, -1980,
+ -1884, -1820, -1756, -1692, -1628, -1564, -1500, -1436,
+ -1372, -1308, -1244, -1180, -1116, -1052, -988, -924,
+ -876, -844, -812, -780, -748, -716, -684, -652,
+ -620, -588, -556, -524, -492, -460, -428, -396,
+ -372, -356, -340, -324, -308, -292, -276, -260,
+ -244, -228, -212, -196, -180, -164, -148, -132,
+ -120, -112, -104, -96, -88, -80, -72, -64,
+ -56, -48, -40, -32, -24, -16, -8, 0,
+ 32124, 31100, 30076, 29052, 28028, 27004, 25980, 24956,
+ 23932, 22908, 21884, 20860, 19836, 18812, 17788, 16764,
+ 15996, 15484, 14972, 14460, 13948, 13436, 12924, 12412,
+ 11900, 11388, 10876, 10364, 9852, 9340, 8828, 8316,
+ 7932, 7676, 7420, 7164, 6908, 6652, 6396, 6140,
+ 5884, 5628, 5372, 5116, 4860, 4604, 4348, 4092,
+ 3900, 3772, 3644, 3516, 3388, 3260, 3132, 3004,
+ 2876, 2748, 2620, 2492, 2364, 2236, 2108, 1980,
+ 1884, 1820, 1756, 1692, 1628, 1564, 1500, 1436,
+ 1372, 1308, 1244, 1180, 1116, 1052, 988, 924,
+ 876, 844, 812, 780, 748, 716, 684, 652,
+ 620, 588, 556, 524, 492, 460, 428, 396,
+ 372, 356, 340, 324, 308, 292, 276, 260,
+ 244, 228, 212, 196, 180, 164, 148, 132,
+ 120, 112, 104, 96, 88, 80, 72, 64,
+ 56, 48, 40, 32, 24, 16, 8, 0,
+};
+
+/* 16 bit A-law */
+
+static short alaw2dma16[] = {
+ -5504, -5248, -6016, -5760, -4480, -4224, -4992, -4736,
+ -7552, -7296, -8064, -7808, -6528, -6272, -7040, -6784,
+ -2752, -2624, -3008, -2880, -2240, -2112, -2496, -2368,
+ -3776, -3648, -4032, -3904, -3264, -3136, -3520, -3392,
+ -22016, -20992, -24064, -23040, -17920, -16896, -19968, -18944,
+ -30208, -29184, -32256, -31232, -26112, -25088, -28160, -27136,
+ -11008, -10496, -12032, -11520, -8960, -8448, -9984, -9472,
+ -15104, -14592, -16128, -15616, -13056, -12544, -14080, -13568,
+ -344, -328, -376, -360, -280, -264, -312, -296,
+ -472, -456, -504, -488, -408, -392, -440, -424,
+ -88, -72, -120, -104, -24, -8, -56, -40,
+ -216, -200, -248, -232, -152, -136, -184, -168,
+ -1376, -1312, -1504, -1440, -1120, -1056, -1248, -1184,
+ -1888, -1824, -2016, -1952, -1632, -1568, -1760, -1696,
+ -688, -656, -752, -720, -560, -528, -624, -592,
+ -944, -912, -1008, -976, -816, -784, -880, -848,
+ 5504, 5248, 6016, 5760, 4480, 4224, 4992, 4736,
+ 7552, 7296, 8064, 7808, 6528, 6272, 7040, 6784,
+ 2752, 2624, 3008, 2880, 2240, 2112, 2496, 2368,
+ 3776, 3648, 4032, 3904, 3264, 3136, 3520, 3392,
+ 22016, 20992, 24064, 23040, 17920, 16896, 19968, 18944,
+ 30208, 29184, 32256, 31232, 26112, 25088, 28160, 27136,
+ 11008, 10496, 12032, 11520, 8960, 8448, 9984, 9472,
+ 15104, 14592, 16128, 15616, 13056, 12544, 14080, 13568,
+ 344, 328, 376, 360, 280, 264, 312, 296,
+ 472, 456, 504, 488, 408, 392, 440, 424,
+ 88, 72, 120, 104, 24, 8, 56, 40,
+ 216, 200, 248, 232, 152, 136, 184, 168,
+ 1376, 1312, 1504, 1440, 1120, 1056, 1248, 1184,
+ 1888, 1824, 2016, 1952, 1632, 1568, 1760, 1696,
+ 688, 656, 752, 720, 560, 528, 624, 592,
+ 944, 912, 1008, 976, 816, 784, 880, 848,
+};
+
+
+/*** Translations ************************************************************/
+
+
+static ssize_t cs4218_ct_law(const u_char *userPtr, size_t userCount,
+ u_char frame[], ssize_t *frameUsed,
+ ssize_t frameLeft);
+static ssize_t cs4218_ct_s8(const u_char *userPtr, size_t userCount,
+ u_char frame[], ssize_t *frameUsed,
+ ssize_t frameLeft);
+static ssize_t cs4218_ct_u8(const u_char *userPtr, size_t userCount,
+ u_char frame[], ssize_t *frameUsed,
+ ssize_t frameLeft);
+static ssize_t cs4218_ct_s16(const u_char *userPtr, size_t userCount,
+ u_char frame[], ssize_t *frameUsed,
+ ssize_t frameLeft);
+static ssize_t cs4218_ct_u16(const u_char *userPtr, size_t userCount,
+ u_char frame[], ssize_t *frameUsed,
+ ssize_t frameLeft);
+static ssize_t cs4218_ctx_law(const u_char *userPtr, size_t userCount,
+ u_char frame[], ssize_t *frameUsed,
+ ssize_t frameLeft);
+static ssize_t cs4218_ctx_s8(const u_char *userPtr, size_t userCount,
+ u_char frame[], ssize_t *frameUsed,
+ ssize_t frameLeft);
+static ssize_t cs4218_ctx_u8(const u_char *userPtr, size_t userCount,
+ u_char frame[], ssize_t *frameUsed,
+ ssize_t frameLeft);
+static ssize_t cs4218_ctx_s16(const u_char *userPtr, size_t userCount,
+ u_char frame[], ssize_t *frameUsed,
+ ssize_t frameLeft);
+static ssize_t cs4218_ctx_u16(const u_char *userPtr, size_t userCount,
+ u_char frame[], ssize_t *frameUsed,
+ ssize_t frameLeft);
+static ssize_t cs4218_ct_s16_read(const u_char *userPtr, size_t userCount,
+ u_char frame[], ssize_t *frameUsed,
+ ssize_t frameLeft);
+static ssize_t cs4218_ct_u16_read(const u_char *userPtr, size_t userCount,
+ u_char frame[], ssize_t *frameUsed,
+ ssize_t frameLeft);
+
+
+/*** Low level stuff *********************************************************/
+
+struct cs_sound_settings {
+ MACHINE mach; /* machine dependent things */
+ SETTINGS hard; /* hardware settings */
+ SETTINGS soft; /* software settings */
+ SETTINGS dsp; /* /dev/dsp default settings */
+ TRANS *trans_write; /* supported translations for playback */
+ TRANS *trans_read; /* supported translations for record */
+ int volume_left; /* volume (range is machine dependent) */
+ int volume_right;
+ int bass; /* tone (range is machine dependent) */
+ int treble;
+ int gain;
+ int minDev; /* minor device number currently open */
+};
+
+static struct cs_sound_settings sound;
+
+static void *CS_Alloc(unsigned int size, int flags);
+static void CS_Free(void *ptr, unsigned int size);
+static int CS_IrqInit(void);
+#ifdef MODULE
+static void CS_IrqCleanup(void);
+#endif /* MODULE */
+static void CS_Silence(void);
+static void CS_Init(void);
+static void CS_Play(void);
+static void CS_Record(void);
+static int CS_SetFormat(int format);
+static int CS_SetVolume(int volume);
+static void cs4218_tdm_tx_intr(void *devid);
+static void cs4218_tdm_rx_intr(void *devid);
+static void cs4218_intr(void *devid, struct pt_regs *regs);
+static int cs_get_volume(uint reg);
+static int cs_volume_setter(int volume, int mute);
+static int cs_get_gain(uint reg);
+static int cs_set_gain(int gain);
+static void cs_mksound(unsigned int hz, unsigned int ticks);
+static void cs_nosound(unsigned long xx);
+
+/*** Mid level stuff *********************************************************/
+
+
+static void sound_silence(void);
+static void sound_init(void);
+static int sound_set_format(int format);
+static int sound_set_speed(int speed);
+static int sound_set_stereo(int stereo);
+static int sound_set_volume(int volume);
+
+static ssize_t sound_copy_translate(const u_char *userPtr,
+ size_t userCount,
+ u_char frame[], ssize_t *frameUsed,
+ ssize_t frameLeft);
+static ssize_t sound_copy_translate_read(const u_char *userPtr,
+ size_t userCount,
+ u_char frame[], ssize_t *frameUsed,
+ ssize_t frameLeft);
+
+
+/*
+ * /dev/mixer abstraction
+ */
+
+struct sound_mixer {
+ int busy;
+ int modify_counter;
+};
+
+static struct sound_mixer mixer;
+
+static struct sound_queue sq;
+static struct sound_queue read_sq;
+
+#define sq_block_address(i) (sq.buffers[i])
+#define SIGNAL_RECEIVED (signal_pending(current))
+#define NON_BLOCKING(open_mode) (open_mode & O_NONBLOCK)
+#define ONE_SECOND HZ /* in jiffies (100ths of a second) */
+#define NO_TIME_LIMIT 0xffffffff
+
+/*
+ * /dev/sndstat
+ */
+
+struct sound_state {
+ int busy;
+ char buf[512];
+ int len, ptr;
+};
+
+static struct sound_state state;
+
+/*** Common stuff ********************************************************/
+
+static long long sound_lseek(struct file *file, long long offset, int orig);
+
+/*** Config & Setup **********************************************************/
+
+void dmasound_setup(char *str, int *ints);
+
+/*** Translations ************************************************************/
+
+
+/* ++TeSche: radically changed for new expanding purposes...
+ *
+ * These two routines now deal with copying/expanding/translating the samples
+ * from user space into our buffer at the right frequency. They take care about
+ * how much data there's actually to read, how much buffer space there is and
+ * to convert samples into the right frequency/encoding. They will only work on
+ * complete samples so it may happen they leave some bytes in the input stream
+ * if the user didn't write a multiple of the current sample size. They both
+ * return the number of bytes they've used from both streams so you may detect
+ * such a situation. Luckily all programs should be able to cope with that.
+ *
+ * I think I've optimized anything as far as one can do in plain C, all
+ * variables should fit in registers and the loops are really short. There's
+ * one loop for every possible situation. Writing a more generalized and thus
+ * parameterized loop would only produce slower code. Feel free to optimize
+ * this in assembler if you like. :)
+ *
+ * I think these routines belong here because they're not yet really hardware
+ * independent, especially the fact that the Falcon can play 16bit samples
+ * only in stereo is hardcoded in both of them!
+ *
+ * ++geert: split in even more functions (one per format)
+ */
+
+static ssize_t cs4218_ct_law(const u_char *userPtr, size_t userCount,
+ u_char frame[], ssize_t *frameUsed,
+ ssize_t frameLeft)
+{
+ short *table = sound.soft.format == AFMT_MU_LAW ? ulaw2dma16: alaw2dma16;
+ ssize_t count, used;
+ short *p = (short *) &frame[*frameUsed];
+ int val, stereo = sound.soft.stereo;
+
+ frameLeft >>= 2;
+ if (stereo)
+ userCount >>= 1;
+ used = count = min(userCount, frameLeft);
+ while (count > 0) {
+ u_char data;
+ if (get_user(data, userPtr++))
+ return -EFAULT;
+ val = table[data];
+ *p++ = val;
+ if (stereo) {
+ if (get_user(data, userPtr++))
+ return -EFAULT;
+ val = table[data];
+ }
+ *p++ = val;
+ count--;
+ }
+ *frameUsed += used * 4;
+ return stereo? used * 2: used;
+}
+
+
+static ssize_t cs4218_ct_s8(const u_char *userPtr, size_t userCount,
+ u_char frame[], ssize_t *frameUsed,
+ ssize_t frameLeft)
+{
+ ssize_t count, used;
+ short *p = (short *) &frame[*frameUsed];
+ int val, stereo = sound.soft.stereo;
+
+ frameLeft >>= 2;
+ if (stereo)
+ userCount >>= 1;
+ used = count = min(userCount, frameLeft);
+ while (count > 0) {
+ u_char data;
+ if (get_user(data, userPtr++))
+ return -EFAULT;
+ val = data << 8;
+ *p++ = val;
+ if (stereo) {
+ if (get_user(data, userPtr++))
+ return -EFAULT;
+ val = data << 8;
+ }
+ *p++ = val;
+ count--;
+ }
+ *frameUsed += used * 4;
+ return stereo? used * 2: used;
+}
+
+
+static ssize_t cs4218_ct_u8(const u_char *userPtr, size_t userCount,
+ u_char frame[], ssize_t *frameUsed,
+ ssize_t frameLeft)
+{
+ ssize_t count, used;
+ short *p = (short *) &frame[*frameUsed];
+ int val, stereo = sound.soft.stereo;
+
+ frameLeft >>= 2;
+ if (stereo)
+ userCount >>= 1;
+ used = count = min(userCount, frameLeft);
+ while (count > 0) {
+ u_char data;
+ if (get_user(data, userPtr++))
+ return -EFAULT;
+ val = (data ^ 0x80) << 8;
+ *p++ = val;
+ if (stereo) {
+ if (get_user(data, userPtr++))
+ return -EFAULT;
+ val = (data ^ 0x80) << 8;
+ }
+ *p++ = val;
+ count--;
+ }
+ *frameUsed += used * 4;
+ return stereo? used * 2: used;
+}
+
+
+/* This is the default format of the codec. Signed, 16-bit stereo
+ * generated by an application shouldn't have to be copied at all.
+ * We should just get the phsical address of the buffers and update
+ * the TDM BDs directly.
+ */
+static ssize_t cs4218_ct_s16(const u_char *userPtr, size_t userCount,
+ u_char frame[], ssize_t *frameUsed,
+ ssize_t frameLeft)
+{
+ ssize_t count, used;
+ int stereo = sound.soft.stereo;
+ short *fp = (short *) &frame[*frameUsed];
+
+ frameLeft >>= 2;
+ userCount >>= (stereo? 2: 1);
+ used = count = min(userCount, frameLeft);
+ if (!stereo) {
+ short *up = (short *) userPtr;
+ while (count > 0) {
+ short data;
+ if (get_user(data, up++))
+ return -EFAULT;
+ *fp++ = data;
+ *fp++ = data;
+ count--;
+ }
+ } else {
+ if (copy_from_user(fp, userPtr, count * 4))
+ return -EFAULT;
+ }
+ *frameUsed += used * 4;
+ return stereo? used * 4: used * 2;
+}
+
+static ssize_t cs4218_ct_u16(const u_char *userPtr, size_t userCount,
+ u_char frame[], ssize_t *frameUsed,
+ ssize_t frameLeft)
+{
+ ssize_t count, used;
+ int mask = (sound.soft.format == AFMT_U16_LE? 0x0080: 0x8000);
+ int stereo = sound.soft.stereo;
+ short *fp = (short *) &frame[*frameUsed];
+ short *up = (short *) userPtr;
+
+ frameLeft >>= 2;
+ userCount >>= (stereo? 2: 1);
+ used = count = min(userCount, frameLeft);
+ while (count > 0) {
+ int data;
+ if (get_user(data, up++))
+ return -EFAULT;
+ data ^= mask;
+ *fp++ = data;
+ if (stereo) {
+ if (get_user(data, up++))
+ return -EFAULT;
+ data ^= mask;
+ }
+ *fp++ = data;
+ count--;
+ }
+ *frameUsed += used * 4;
+ return stereo? used * 4: used * 2;
+}
+
+
+static ssize_t cs4218_ctx_law(const u_char *userPtr, size_t userCount,
+ u_char frame[], ssize_t *frameUsed,
+ ssize_t frameLeft)
+{
+ unsigned short *table = (unsigned short *)
+ (sound.soft.format == AFMT_MU_LAW ? ulaw2dma16: alaw2dma16);
+ unsigned int data = expand_data;
+ unsigned int *p = (unsigned int *) &frame[*frameUsed];
+ int bal = expand_bal;
+ int hSpeed = sound.hard.speed, sSpeed = sound.soft.speed;
+ int utotal, ftotal;
+ int stereo = sound.soft.stereo;
+
+ frameLeft >>= 2;
+ if (stereo)
+ userCount >>= 1;
+ ftotal = frameLeft;
+ utotal = userCount;
+ while (frameLeft) {
+ u_char c;
+ if (bal < 0) {
+ if (userCount == 0)
+ break;
+ if (get_user(c, userPtr++))
+ return -EFAULT;
+ data = table[c];
+ if (stereo) {
+ if (get_user(c, userPtr++))
+ return -EFAULT;
+ data = (data << 16) + table[c];
+ } else
+ data = (data << 16) + data;
+ userCount--;
+ bal += hSpeed;
+ }
+ *p++ = data;
+ frameLeft--;
+ bal -= sSpeed;
+ }
+ expand_bal = bal;
+ expand_data = data;
+ *frameUsed += (ftotal - frameLeft) * 4;
+ utotal -= userCount;
+ return stereo? utotal * 2: utotal;
+}
+
+
+static ssize_t cs4218_ctx_s8(const u_char *userPtr, size_t userCount,
+ u_char frame[], ssize_t *frameUsed,
+ ssize_t frameLeft)
+{
+ unsigned int *p = (unsigned int *) &frame[*frameUsed];
+ unsigned int data = expand_data;
+ int bal = expand_bal;
+ int hSpeed = sound.hard.speed, sSpeed = sound.soft.speed;
+ int stereo = sound.soft.stereo;
+ int utotal, ftotal;
+
+ frameLeft >>= 2;
+ if (stereo)
+ userCount >>= 1;
+ ftotal = frameLeft;
+ utotal = userCount;
+ while (frameLeft) {
+ u_char c;
+ if (bal < 0) {
+ if (userCount == 0)
+ break;
+ if (get_user(c, userPtr++))
+ return -EFAULT;
+ data = c << 8;
+ if (stereo) {
+ if (get_user(c, userPtr++))
+ return -EFAULT;
+ data = (data << 16) + (c << 8);
+ } else
+ data = (data << 16) + data;
+ userCount--;
+ bal += hSpeed;
+ }
+ *p++ = data;
+ frameLeft--;
+ bal -= sSpeed;
+ }
+ expand_bal = bal;
+ expand_data = data;
+ *frameUsed += (ftotal - frameLeft) * 4;
+ utotal -= userCount;
+ return stereo? utotal * 2: utotal;
+}
+
+
+static ssize_t cs4218_ctx_u8(const u_char *userPtr, size_t userCount,
+ u_char frame[], ssize_t *frameUsed,
+ ssize_t frameLeft)
+{
+ unsigned int *p = (unsigned int *) &frame[*frameUsed];
+ unsigned int data = expand_data;
+ int bal = expand_bal;
+ int hSpeed = sound.hard.speed, sSpeed = sound.soft.speed;
+ int stereo = sound.soft.stereo;
+ int utotal, ftotal;
+
+ frameLeft >>= 2;
+ if (stereo)
+ userCount >>= 1;
+ ftotal = frameLeft;
+ utotal = userCount;
+ while (frameLeft) {
+ u_char c;
+ if (bal < 0) {
+ if (userCount == 0)
+ break;
+ if (get_user(c, userPtr++))
+ return -EFAULT;
+ data = (c ^ 0x80) << 8;
+ if (stereo) {
+ if (get_user(c, userPtr++))
+ return -EFAULT;
+ data = (data << 16) + ((c ^ 0x80) << 8);
+ } else
+ data = (data << 16) + data;
+ userCount--;
+ bal += hSpeed;
+ }
+ *p++ = data;
+ frameLeft--;
+ bal -= sSpeed;
+ }
+ expand_bal = bal;
+ expand_data = data;
+ *frameUsed += (ftotal - frameLeft) * 4;
+ utotal -= userCount;
+ return stereo? utotal * 2: utotal;
+}
+
+
+static ssize_t cs4218_ctx_s16(const u_char *userPtr, size_t userCount,
+ u_char frame[], ssize_t *frameUsed,
+ ssize_t frameLeft)
+{
+ unsigned int *p = (unsigned int *) &frame[*frameUsed];
+ unsigned int data = expand_data;
+ unsigned short *up = (unsigned short *) userPtr;
+ int bal = expand_bal;
+ int hSpeed = sound.hard.speed, sSpeed = sound.soft.speed;
+ int stereo = sound.soft.stereo;
+ int utotal, ftotal;
+
+ frameLeft >>= 2;
+ userCount >>= (stereo? 2: 1);
+ ftotal = frameLeft;
+ utotal = userCount;
+ while (frameLeft) {
+ unsigned short c;
+ if (bal < 0) {
+ if (userCount == 0)
+ break;
+ if (get_user(data, up++))
+ return -EFAULT;
+ if (stereo) {
+ if (get_user(c, up++))
+ return -EFAULT;
+ data = (data << 16) + c;
+ } else
+ data = (data << 16) + data;
+ userCount--;
+ bal += hSpeed;
+ }
+ *p++ = data;
+ frameLeft--;
+ bal -= sSpeed;
+ }
+ expand_bal = bal;
+ expand_data = data;
+ *frameUsed += (ftotal - frameLeft) * 4;
+ utotal -= userCount;
+ return stereo? utotal * 4: utotal * 2;
+}
+
+
+static ssize_t cs4218_ctx_u16(const u_char *userPtr, size_t userCount,
+ u_char frame[], ssize_t *frameUsed,
+ ssize_t frameLeft)
+{
+ int mask = (sound.soft.format == AFMT_U16_LE? 0x0080: 0x8000);
+ unsigned int *p = (unsigned int *) &frame[*frameUsed];
+ unsigned int data = expand_data;
+ unsigned short *up = (unsigned short *) userPtr;
+ int bal = expand_bal;
+ int hSpeed = sound.hard.speed, sSpeed = sound.soft.speed;
+ int stereo = sound.soft.stereo;
+ int utotal, ftotal;
+
+ frameLeft >>= 2;
+ userCount >>= (stereo? 2: 1);
+ ftotal = frameLeft;
+ utotal = userCount;
+ while (frameLeft) {
+ unsigned short c;
+ if (bal < 0) {
+ if (userCount == 0)
+ break;
+ if (get_user(data, up++))
+ return -EFAULT;
+ data ^= mask;
+ if (stereo) {
+ if (get_user(c, up++))
+ return -EFAULT;
+ data = (data << 16) + (c ^ mask);
+ } else
+ data = (data << 16) + data;
+ userCount--;
+ bal += hSpeed;
+ }
+ *p++ = data;
+ frameLeft--;
+ bal -= sSpeed;
+ }
+ expand_bal = bal;
+ expand_data = data;
+ *frameUsed += (ftotal - frameLeft) * 4;
+ utotal -= userCount;
+ return stereo? utotal * 4: utotal * 2;
+}
+
+static ssize_t cs4218_ct_s8_read(const u_char *userPtr, size_t userCount,
+ u_char frame[], ssize_t *frameUsed,
+ ssize_t frameLeft)
+{
+ ssize_t count, used;
+ short *p = (short *) &frame[*frameUsed];
+ int val, stereo = sound.soft.stereo;
+
+ frameLeft >>= 2;
+ if (stereo)
+ userCount >>= 1;
+ used = count = min(userCount, frameLeft);
+ while (count > 0) {
+ u_char data;
+
+ val = *p++;
+ data = val >> 8;
+ if (put_user(data, (u_char *)userPtr++))
+ return -EFAULT;
+ if (stereo) {
+ val = *p;
+ data = val >> 8;
+ if (put_user(data, (u_char *)userPtr++))
+ return -EFAULT;
+ }
+ p++;
+ count--;
+ }
+ *frameUsed += used * 4;
+ return stereo? used * 2: used;
+}
+
+
+static ssize_t cs4218_ct_u8_read(const u_char *userPtr, size_t userCount,
+ u_char frame[], ssize_t *frameUsed,
+ ssize_t frameLeft)
+{
+ ssize_t count, used;
+ short *p = (short *) &frame[*frameUsed];
+ int val, stereo = sound.soft.stereo;
+
+ frameLeft >>= 2;
+ if (stereo)
+ userCount >>= 1;
+ used = count = min(userCount, frameLeft);
+ while (count > 0) {
+ u_char data;
+
+ val = *p++;
+ data = (val >> 8) ^ 0x80;
+ if (put_user(data, (u_char *)userPtr++))
+ return -EFAULT;
+ if (stereo) {
+ val = *p;
+ data = (val >> 8) ^ 0x80;
+ if (put_user(data, (u_char *)userPtr++))
+ return -EFAULT;
+ }
+ p++;
+ count--;
+ }
+ *frameUsed += used * 4;
+ return stereo? used * 2: used;
+}
+
+
+static ssize_t cs4218_ct_s16_read(const u_char *userPtr, size_t userCount,
+ u_char frame[], ssize_t *frameUsed,
+ ssize_t frameLeft)
+{
+ ssize_t count, used;
+ int stereo = sound.soft.stereo;
+ short *fp = (short *) &frame[*frameUsed];
+
+ frameLeft >>= 2;
+ userCount >>= (stereo? 2: 1);
+ used = count = min(userCount, frameLeft);
+ if (!stereo) {
+ short *up = (short *) userPtr;
+ while (count > 0) {
+ short data;
+ data = *fp;
+ if (put_user(data, up++))
+ return -EFAULT;
+ fp+=2;
+ count--;
+ }
+ } else {
+ if (copy_to_user((u_char *)userPtr, fp, count * 4))
+ return -EFAULT;
+ }
+ *frameUsed += used * 4;
+ return stereo? used * 4: used * 2;
+}
+
+static ssize_t cs4218_ct_u16_read(const u_char *userPtr, size_t userCount,
+ u_char frame[], ssize_t *frameUsed,
+ ssize_t frameLeft)
+{
+ ssize_t count, used;
+ int mask = (sound.soft.format == AFMT_U16_LE? 0x0080: 0x8000);
+ int stereo = sound.soft.stereo;
+ short *fp = (short *) &frame[*frameUsed];
+ short *up = (short *) userPtr;
+
+ frameLeft >>= 2;
+ userCount >>= (stereo? 2: 1);
+ used = count = min(userCount, frameLeft);
+ while (count > 0) {
+ int data;
+
+ data = *fp++;
+ data ^= mask;
+ if (put_user(data, up++))
+ return -EFAULT;
+ if (stereo) {
+ data = *fp;
+ data ^= mask;
+ if (put_user(data, up++))
+ return -EFAULT;
+ }
+ fp++;
+ count--;
+ }
+ *frameUsed += used * 4;
+ return stereo? used * 4: used * 2;
+}
+
+static TRANS transCSNormal = {
+ cs4218_ct_law, cs4218_ct_law, cs4218_ct_s8, cs4218_ct_u8,
+ cs4218_ct_s16, cs4218_ct_u16, cs4218_ct_s16, cs4218_ct_u16
+};
+
+static TRANS transCSExpand = {
+ cs4218_ctx_law, cs4218_ctx_law, cs4218_ctx_s8, cs4218_ctx_u8,
+ cs4218_ctx_s16, cs4218_ctx_u16, cs4218_ctx_s16, cs4218_ctx_u16
+};
+
+static TRANS transCSNormalRead = {
+ NULL, NULL, cs4218_ct_s8_read, cs4218_ct_u8_read,
+ cs4218_ct_s16_read, cs4218_ct_u16_read,
+ cs4218_ct_s16_read, cs4218_ct_u16_read
+};
+
+/*** Low level stuff *********************************************************/
+
+static void *CS_Alloc(unsigned int size, int flags)
+{
+ int order;
+
+ size >>= 13;
+ for (order=0; order < 5; order++) {
+ if (size == 0)
+ break;
+ size >>= 1;
+ }
+ return (void *)__get_free_pages(flags, order);
+}
+
+static void CS_Free(void *ptr, unsigned int size)
+{
+ int order;
+
+ size >>= 13;
+ for (order=0; order < 5; order++) {
+ if (size == 0)
+ break;
+ size >>= 1;
+ }
+ free_pages((ulong)ptr, order);
+}
+
+static int __init CS_IrqInit(void)
+{
+ cpm_install_handler(CPMVEC_SMC2, cs4218_intr, NULL);
+ return 1;
+}
+
+#ifdef MODULE
+static void CS_IrqCleanup(void)
+{
+ volatile smc_t *sp;
+ volatile cpm8xx_t *cp;
+
+ /* First disable transmitter and receiver.
+ */
+ sp = &cpmp->cp_smc[1];
+ sp->smc_smcmr &= ~(SMCMR_REN | SMCMR_TEN);
+
+ /* And now shut down the SMC.
+ */
+ cp = cpmp; /* Get pointer to Communication Processor */
+ cp->cp_cpcr = mk_cr_cmd(CPM_CR_CH_SMC2,
+ CPM_CR_STOP_TX) | CPM_CR_FLG;
+ while (cp->cp_cpcr & CPM_CR_FLG);
+
+ /* Release the interrupt handler.
+ */
+ cpm_free_handler(CPMVEC_SMC2);
+
+ if (beep_buf)
+ kfree(beep_buf);
+ kd_mksound = orig_mksound;
+}
+#endif /* MODULE */
+
+static void CS_Silence(void)
+{
+ volatile smc_t *sp;
+
+ /* Disable transmitter.
+ */
+ sp = &cpmp->cp_smc[1];
+ sp->smc_smcmr &= ~SMCMR_TEN;
+}
+
+/* Frequencies depend upon external oscillator. There are two
+ * choices, 12.288 and 11.2896 MHz. The RPCG audio supports both through
+ * and external control register selection bit.
+ */
+static int cs4218_freqs[] = {
+ /* 12.288 11.2896 */
+ 48000, 44100,
+ 32000, 29400,
+ 24000, 22050,
+ 19200, 17640,
+ 16000, 14700,
+ 12000, 11025,
+ 9600, 8820,
+ 8000, 7350
+};
+
+static void CS_Init(void)
+{
+ int i, tolerance;
+
+ switch (sound.soft.format) {
+ case AFMT_S16_LE:
+ case AFMT_U16_LE:
+ sound.hard.format = AFMT_S16_LE;
+ break;
+ default:
+ sound.hard.format = AFMT_S16_BE;
+ break;
+ }
+ sound.hard.stereo = 1;
+ sound.hard.size = 16;
+
+ /*
+ * If we have a sample rate which is within catchRadius percent
+ * of the requested value, we don't have to expand the samples.
+ * Otherwise choose the next higher rate.
+ */
+ i = (sizeof(cs4218_freqs) / sizeof(int));
+ do {
+ tolerance = catchRadius * cs4218_freqs[--i] / 100;
+ } while (sound.soft.speed > cs4218_freqs[i] + tolerance && i > 0);
+ if (sound.soft.speed >= cs4218_freqs[i] - tolerance)
+ sound.trans_write = &transCSNormal;
+ else
+ sound.trans_write = &transCSExpand;
+ sound.trans_read = &transCSNormalRead;
+ sound.hard.speed = cs4218_freqs[i];
+ cs4218_rate_index = i;
+
+ /* The CS4218 has seven selectable clock dividers for the sample
+ * clock. The HIOX then provides one of two external rates.
+ * An even numbered frequency table index uses the high external
+ * clock rate.
+ */
+ *(uint *)HIOX_CSR4_ADDR &= ~(HIOX_CSR4_AUDCLKHI | HIOX_CSR4_AUDCLKSEL);
+ if ((i & 1) == 0)
+ *(uint *)HIOX_CSR4_ADDR |= HIOX_CSR4_AUDCLKHI;
+ i >>= 1;
+ *(uint *)HIOX_CSR4_ADDR |= (i & HIOX_CSR4_AUDCLKSEL);
+
+ expand_bal = -sound.soft.speed;
+}
+
+static int CS_SetFormat(int format)
+{
+ int size;
+
+ switch (format) {
+ case AFMT_QUERY:
+ return sound.soft.format;
+ case AFMT_MU_LAW:
+ case AFMT_A_LAW:
+ case AFMT_U8:
+ case AFMT_S8:
+ size = 8;
+ break;
+ case AFMT_S16_BE:
+ case AFMT_U16_BE:
+ case AFMT_S16_LE:
+ case AFMT_U16_LE:
+ size = 16;
+ break;
+ default: /* :-) */
+ printk(KERN_ERR "dmasound: unknown format 0x%x, using AFMT_U8\n",
+ format);
+ size = 8;
+ format = AFMT_U8;
+ }
+
+ sound.soft.format = format;
+ sound.soft.size = size;
+ if (sound.minDev == SND_DEV_DSP) {
+ sound.dsp.format = format;
+ sound.dsp.size = size;
+ }
+
+ CS_Init();
+
+ return format;
+}
+
+/* Volume is the amount of attenuation we tell the codec to impose
+ * on the outputs. There are 32 levels, with 0 the "loudest".
+ */
+#define CS_VOLUME_TO_MASK(x) (31 - ((((x) - 1) * 31) / 99))
+#define CS_MASK_TO_VOLUME(y) (100 - ((y) * 99 / 31))
+
+static int cs_get_volume(uint reg)
+{
+ int volume;
+
+ volume = CS_MASK_TO_VOLUME(CS_LATTEN_GET(reg));
+ volume |= CS_MASK_TO_VOLUME(CS_RATTEN_GET(reg)) << 8;
+ return volume;
+}
+
+static int cs_volume_setter(int volume, int mute)
+{
+ uint tempctl;
+
+ if (mute && volume == 0) {
+ tempctl = cs4218_control | CS_MUTE;
+ } else {
+ tempctl = cs4218_control & ~CS_MUTE;
+ tempctl = tempctl & ~(CS_LATTEN | CS_RATTEN);
+ tempctl |= CS_LATTEN_SET(CS_VOLUME_TO_MASK(volume & 0xff));
+ tempctl |= CS_RATTEN_SET(CS_VOLUME_TO_MASK((volume >> 8) & 0xff));
+ volume = cs_get_volume(tempctl);
+ }
+ if (tempctl != cs4218_control) {
+ cs4218_ctl_write(tempctl);
+ }
+ return volume;
+}
+
+
+/* Gain has 16 steps from 0 to 15. These are in 1.5dB increments from
+ * 0 (no gain) to 22.5 dB.
+ */
+#define CS_RECLEVEL_TO_GAIN(v) \
+ ((v) < 0 ? 0 : (v) > 100 ? 15 : (v) * 3 / 20)
+#define CS_GAIN_TO_RECLEVEL(v) (((v) * 20 + 2) / 3)
+
+static int cs_get_gain(uint reg)
+{
+ int gain;
+
+ gain = CS_GAIN_TO_RECLEVEL(CS_LGAIN_GET(reg));
+ gain |= CS_GAIN_TO_RECLEVEL(CS_RGAIN_GET(reg)) << 8;
+ return gain;
+}
+
+static int cs_set_gain(int gain)
+{
+ uint tempctl;
+
+ tempctl = cs4218_control & ~(CS_LGAIN | CS_RGAIN);
+ tempctl |= CS_LGAIN_SET(CS_RECLEVEL_TO_GAIN(gain & 0xff));
+ tempctl |= CS_RGAIN_SET(CS_RECLEVEL_TO_GAIN((gain >> 8) & 0xff));
+ gain = cs_get_gain(tempctl);
+
+ if (tempctl != cs4218_control) {
+ cs4218_ctl_write(tempctl);
+ }
+ return gain;
+}
+
+static int CS_SetVolume(int volume)
+{
+ return cs_volume_setter(volume, CS_MUTE);
+}
+
+static void CS_Play(void)
+{
+ int i, count;
+ unsigned long flags;
+ volatile cbd_t *bdp;
+ volatile cpm8xx_t *cp;
+
+ /* Protect buffer */
+ spin_lock_irqsave(&cs4218_lock, flags);
+#if 0
+ if (awacs_beep_state) {
+ /* sound takes precedence over beeps */
+ out_le32(&awacs_txdma->control, (RUN|PAUSE|FLUSH|WAKE) << 16);
+ out_le32(&awacs->control,
+ (in_le32(&awacs->control) & ~0x1f00)
+ | (awacs_rate_index << 8));
+ out_le32(&awacs->byteswap, sound.hard.format != AFMT_S16_BE);
+ out_le32(&awacs_txdma->cmdptr, virt_to_bus(&(awacs_tx_cmds[(sq.front+sq.active) % sq.max_count])));
+
+ beep_playing = 0;
+ awacs_beep_state = 0;
+ }
+#endif
+ i = sq.front + sq.active;
+ if (i >= sq.max_count)
+ i -= sq.max_count;
+ while (sq.active < 2 && sq.active < sq.count) {
+ count = (sq.count == sq.active + 1)?sq.rear_size:sq.block_size;
+ if (count < sq.block_size && !sq.syncing)
+ /* last block not yet filled, and we're not syncing. */
+ break;
+
+ bdp = &tx_base[i];
+ bdp->cbd_datlen = count;
+
+ flush_dcache_range((ulong)sound_buffers[i],
+ (ulong)(sound_buffers[i] + count));
+
+ if (++i >= sq.max_count)
+ i = 0;
+
+ if (sq.active == 0) {
+ /* The SMC does not load its fifo until the first
+ * TDM frame pulse, so the transmit data gets shifted
+ * by one word. To compensate for this, we incorrectly
+ * transmit the first buffer and shorten it by one
+ * word. Subsequent buffers are then aligned properly.
+ */
+ bdp->cbd_datlen -= 2;
+
+ /* Start up the SMC Transmitter.
+ */
+ cp = cpmp;
+ cp->cp_smc[1].smc_smcmr |= SMCMR_TEN;
+ cp->cp_cpcr = mk_cr_cmd(CPM_CR_CH_SMC2,
+ CPM_CR_RESTART_TX) | CPM_CR_FLG;
+ while (cp->cp_cpcr & CPM_CR_FLG);
+ }
+
+ /* Buffer is ready now.
+ */
+ bdp->cbd_sc |= BD_SC_READY;
+
+ ++sq.active;
+ }
+ spin_unlock_irqrestore(&cs4218_lock, flags);
+}
+
+
+static void CS_Record(void)
+{
+ unsigned long flags;
+ volatile smc_t *sp;
+
+ if (read_sq.active)
+ return;
+
+ /* Protect buffer */
+ spin_lock_irqsave(&cs4218_lock, flags);
+
+ /* This is all we have to do......Just start it up.
+ */
+ sp = &cpmp->cp_smc[1];
+ sp->smc_smcmr |= SMCMR_REN;
+
+ read_sq.active = 1;
+
+ spin_unlock_irqrestore(&cs4218_lock, flags);
+}
+
+
+static void
+cs4218_tdm_tx_intr(void *devid)
+{
+ int i = sq.front;
+ volatile cbd_t *bdp;
+
+ while (sq.active > 0) {
+ bdp = &tx_base[i];
+ if (bdp->cbd_sc & BD_SC_READY)
+ break; /* this frame is still going */
+ --sq.count;
+ --sq.active;
+ if (++i >= sq.max_count)
+ i = 0;
+ }
+ if (i != sq.front)
+ WAKE_UP(sq.action_queue);
+ sq.front = i;
+
+ CS_Play();
+
+ if (!sq.active)
+ WAKE_UP(sq.sync_queue);
+}
+
+
+static void
+cs4218_tdm_rx_intr(void *devid)
+{
+
+ /* We want to blow 'em off when shutting down.
+ */
+ if (read_sq.active == 0)
+ return;
+
+ /* Check multiple buffers in case we were held off from
+ * interrupt processing for a long time. Geeze, I really hope
+ * this doesn't happen.
+ */
+ while ((rx_base[read_sq.rear].cbd_sc & BD_SC_EMPTY) == 0) {
+
+ /* Invalidate the data cache range for this buffer.
+ */
+ invalidate_dcache_range(
+ (uint)(sound_read_buffers[read_sq.rear]),
+ (uint)(sound_read_buffers[read_sq.rear] + read_sq.block_size));
+
+ /* Make buffer available again and move on.
+ */
+ rx_base[read_sq.rear].cbd_sc |= BD_SC_EMPTY;
+ read_sq.rear++;
+
+ /* Wrap the buffer ring.
+ */
+ if (read_sq.rear >= read_sq.max_active)
+ read_sq.rear = 0;
+
+ /* If we have caught up to the front buffer, bump it.
+ * This will cause weird (but not fatal) results if the
+ * read loop is currently using this buffer. The user is
+ * behind in this case anyway, so weird things are going
+ * to happen.
+ */
+ if (read_sq.rear == read_sq.front) {
+ read_sq.front++;
+ if (read_sq.front >= read_sq.max_active)
+ read_sq.front = 0;
+ }
+ }
+
+ WAKE_UP(read_sq.action_queue);
+}
+
+static void cs_nosound(unsigned long xx)
+{
+ unsigned long flags;
+
+ /* not sure if this is needed, since hardware command is #if 0'd */
+ spin_lock_irqsave(&cs4218_lock, flags);
+ if (beep_playing) {
+#if 0
+ st_le16(&beep_dbdma_cmd->command, DBDMA_STOP);
+#endif
+ beep_playing = 0;
+ }
+ spin_unlock_irqrestore(&cs4218_lock, flags);
+}
+
+static struct timer_list beep_timer = TIMER_INITIALIZER(cs_nosound, 0, 0);
+};
+
+static void cs_mksound(unsigned int hz, unsigned int ticks)
+{
+ unsigned long flags;
+ int beep_speed = BEEP_SPEED;
+ int srate = cs4218_freqs[beep_speed];
+ int period, ncycles, nsamples;
+ int i, j, f;
+ short *p;
+ static int beep_hz_cache;
+ static int beep_nsamples_cache;
+ static int beep_volume_cache;
+
+ if (hz <= srate / BEEP_BUFLEN || hz > srate / 2) {
+#if 1
+ /* this is a hack for broken X server code */
+ hz = 750;
+ ticks = 12;
+#else
+ /* cancel beep currently playing */
+ awacs_nosound(0);
+ return;
+#endif
+ }
+ /* lock while modifying beep_timer */
+ spin_lock_irqsave(&cs4218_lock, flags);
+ del_timer(&beep_timer);
+ if (ticks) {
+ beep_timer.expires = jiffies + ticks;
+ add_timer(&beep_timer);
+ }
+ if (beep_playing || sq.active || beep_buf == NULL) {
+ spin_unlock_irqrestore(&cs4218_lock, flags);
+ return; /* too hard, sorry :-( */
+ }
+ beep_playing = 1;
+#if 0
+ st_le16(&beep_dbdma_cmd->command, OUTPUT_MORE + BR_ALWAYS);
+#endif
+ spin_unlock_irqrestore(&cs4218_lock, flags);
+
+ if (hz == beep_hz_cache && beep_volume == beep_volume_cache) {
+ nsamples = beep_nsamples_cache;
+ } else {
+ period = srate * 256 / hz; /* fixed point */
+ ncycles = BEEP_BUFLEN * 256 / period;
+ nsamples = (period * ncycles) >> 8;
+ f = ncycles * 65536 / nsamples;
+ j = 0;
+ p = beep_buf;
+ for (i = 0; i < nsamples; ++i, p += 2) {
+ p[0] = p[1] = beep_wform[j >> 8] * beep_volume;
+ j = (j + f) & 0xffff;
+ }
+ beep_hz_cache = hz;
+ beep_volume_cache = beep_volume;
+ beep_nsamples_cache = nsamples;
+ }
+
+#if 0
+ st_le16(&beep_dbdma_cmd->req_count, nsamples*4);
+ st_le16(&beep_dbdma_cmd->xfer_status, 0);
+ st_le32(&beep_dbdma_cmd->cmd_dep, virt_to_bus(beep_dbdma_cmd));
+ st_le32(&beep_dbdma_cmd->phy_addr, virt_to_bus(beep_buf));
+ awacs_beep_state = 1;
+
+ spin_lock_irqsave(&cs4218_lock, flags);
+ if (beep_playing) { /* i.e. haven't been terminated already */
+ out_le32(&awacs_txdma->control, (RUN|WAKE|FLUSH|PAUSE) << 16);
+ out_le32(&awacs->control,
+ (in_le32(&awacs->control) & ~0x1f00)
+ | (beep_speed << 8));
+ out_le32(&awacs->byteswap, 0);
+ out_le32(&awacs_txdma->cmdptr, virt_to_bus(beep_dbdma_cmd));
+ out_le32(&awacs_txdma->control, RUN | (RUN << 16));
+ }
+ spin_unlock_irqrestore(&cs4218_lock, flags);
+#endif
+}
+
+static MACHINE mach_cs4218 = {
+ .owner = THIS_MODULE,
+ .name = "HIOX CS4218",
+ .name2 = "Built-in Sound",
+ .dma_alloc = CS_Alloc,
+ .dma_free = CS_Free,
+ .irqinit = CS_IrqInit,
+#ifdef MODULE
+ .irqcleanup = CS_IrqCleanup,
+#endif /* MODULE */
+ .init = CS_Init,
+ .silence = CS_Silence,
+ .setFormat = CS_SetFormat,
+ .setVolume = CS_SetVolume,
+ .play = CS_Play
+};
+
+
+/*** Mid level stuff *********************************************************/
+
+
+static void sound_silence(void)
+{
+ /* update hardware settings one more */
+ (*sound.mach.init)();
+
+ (*sound.mach.silence)();
+}
+
+
+static void sound_init(void)
+{
+ (*sound.mach.init)();
+}
+
+
+static int sound_set_format(int format)
+{
+ return(*sound.mach.setFormat)(format);
+}
+
+
+static int sound_set_speed(int speed)
+{
+ if (speed < 0)
+ return(sound.soft.speed);
+
+ sound.soft.speed = speed;
+ (*sound.mach.init)();
+ if (sound.minDev == SND_DEV_DSP)
+ sound.dsp.speed = sound.soft.speed;
+
+ return(sound.soft.speed);
+}
+
+
+static int sound_set_stereo(int stereo)
+{
+ if (stereo < 0)
+ return(sound.soft.stereo);
+
+ stereo = !!stereo; /* should be 0 or 1 now */
+
+ sound.soft.stereo = stereo;
+ if (sound.minDev == SND_DEV_DSP)
+ sound.dsp.stereo = stereo;
+ (*sound.mach.init)();
+
+ return(stereo);
+}
+
+
+static int sound_set_volume(int volume)
+{
+ return(*sound.mach.setVolume)(volume);
+}
+
+static ssize_t sound_copy_translate(const u_char *userPtr,
+ size_t userCount,
+ u_char frame[], ssize_t *frameUsed,
+ ssize_t frameLeft)
+{
+ ssize_t (*ct_func)(const u_char *, size_t, u_char *, ssize_t *, ssize_t) = NULL;
+
+ switch (sound.soft.format) {
+ case AFMT_MU_LAW:
+ ct_func = sound.trans_write->ct_ulaw;
+ break;
+ case AFMT_A_LAW:
+ ct_func = sound.trans_write->ct_alaw;
+ break;
+ case AFMT_S8:
+ ct_func = sound.trans_write->ct_s8;
+ break;
+ case AFMT_U8:
+ ct_func = sound.trans_write->ct_u8;
+ break;
+ case AFMT_S16_BE:
+ ct_func = sound.trans_write->ct_s16be;
+ break;
+ case AFMT_U16_BE:
+ ct_func = sound.trans_write->ct_u16be;
+ break;
+ case AFMT_S16_LE:
+ ct_func = sound.trans_write->ct_s16le;
+ break;
+ case AFMT_U16_LE:
+ ct_func = sound.trans_write->ct_u16le;
+ break;
+ }
+ if (ct_func)
+ return ct_func(userPtr, userCount, frame, frameUsed, frameLeft);
+ else
+ return 0;
+}
+
+static ssize_t sound_copy_translate_read(const u_char *userPtr,
+ size_t userCount,
+ u_char frame[], ssize_t *frameUsed,
+ ssize_t frameLeft)
+{
+ ssize_t (*ct_func)(const u_char *, size_t, u_char *, ssize_t *, ssize_t) = NULL;
+
+ switch (sound.soft.format) {
+ case AFMT_MU_LAW:
+ ct_func = sound.trans_read->ct_ulaw;
+ break;
+ case AFMT_A_LAW:
+ ct_func = sound.trans_read->ct_alaw;
+ break;
+ case AFMT_S8:
+ ct_func = sound.trans_read->ct_s8;
+ break;
+ case AFMT_U8:
+ ct_func = sound.trans_read->ct_u8;
+ break;
+ case AFMT_S16_BE:
+ ct_func = sound.trans_read->ct_s16be;
+ break;
+ case AFMT_U16_BE:
+ ct_func = sound.trans_read->ct_u16be;
+ break;
+ case AFMT_S16_LE:
+ ct_func = sound.trans_read->ct_s16le;
+ break;
+ case AFMT_U16_LE:
+ ct_func = sound.trans_read->ct_u16le;
+ break;
+ }
+ if (ct_func)
+ return ct_func(userPtr, userCount, frame, frameUsed, frameLeft);
+ else
+ return 0;
+}
+
+
+/*
+ * /dev/mixer abstraction
+ */
+
+static int mixer_open(struct inode *inode, struct file *file)
+{
+ mixer.busy = 1;
+ return nonseekable_open(inode, file);
+}
+
+
+static int mixer_release(struct inode *inode, struct file *file)
+{
+ mixer.busy = 0;
+ return 0;
+}
+
+
+static int mixer_ioctl(struct inode *inode, struct file *file, u_int cmd,
+ u_long arg)
+{
+ int data;
+ uint tmpcs;
+
+ if (_SIOC_DIR(cmd) & _SIOC_WRITE)
+ mixer.modify_counter++;
+ if (cmd == OSS_GETVERSION)
+ return IOCTL_OUT(arg, SOUND_VERSION);
+ switch (cmd) {
+ case SOUND_MIXER_INFO: {
+ mixer_info info;
+ strlcpy(info.id, "CS4218_TDM", sizeof(info.id));
+ strlcpy(info.name, "CS4218_TDM", sizeof(info.name));
+ info.name[sizeof(info.name)-1] = 0;
+ info.modify_counter = mixer.modify_counter;
+ if (copy_to_user((int *)arg, &info, sizeof(info)))
+ return -EFAULT;
+ return 0;
+ }
+ case SOUND_MIXER_READ_DEVMASK:
+ data = SOUND_MASK_VOLUME | SOUND_MASK_LINE
+ | SOUND_MASK_MIC | SOUND_MASK_RECLEV
+ | SOUND_MASK_ALTPCM;
+ return IOCTL_OUT(arg, data);
+ case SOUND_MIXER_READ_RECMASK:
+ data = SOUND_MASK_LINE | SOUND_MASK_MIC;
+ return IOCTL_OUT(arg, data);
+ case SOUND_MIXER_READ_RECSRC:
+ if (cs4218_control & CS_DO1)
+ data = SOUND_MASK_LINE;
+ else
+ data = SOUND_MASK_MIC;
+ return IOCTL_OUT(arg, data);
+ case SOUND_MIXER_WRITE_RECSRC:
+ IOCTL_IN(arg, data);
+ data &= (SOUND_MASK_LINE | SOUND_MASK_MIC);
+ if (data & SOUND_MASK_LINE)
+ tmpcs = cs4218_control |
+ (CS_ISL | CS_ISR | CS_DO1);
+ if (data & SOUND_MASK_MIC)
+ tmpcs = cs4218_control &
+ ~(CS_ISL | CS_ISR | CS_DO1);
+ if (tmpcs != cs4218_control)
+ cs4218_ctl_write(tmpcs);
+ return IOCTL_OUT(arg, data);
+ case SOUND_MIXER_READ_STEREODEVS:
+ data = SOUND_MASK_VOLUME | SOUND_MASK_RECLEV;
+ return IOCTL_OUT(arg, data);
+ case SOUND_MIXER_READ_CAPS:
+ return IOCTL_OUT(arg, 0);
+ case SOUND_MIXER_READ_VOLUME:
+ data = (cs4218_control & CS_MUTE)? 0:
+ cs_get_volume(cs4218_control);
+ return IOCTL_OUT(arg, data);
+ case SOUND_MIXER_WRITE_VOLUME:
+ IOCTL_IN(arg, data);
+ return IOCTL_OUT(arg, sound_set_volume(data));
+ case SOUND_MIXER_WRITE_ALTPCM: /* really bell volume */
+ IOCTL_IN(arg, data);
+ beep_volume = data & 0xff;
+ /* fall through */
+ case SOUND_MIXER_READ_ALTPCM:
+ return IOCTL_OUT(arg, beep_volume);
+ case SOUND_MIXER_WRITE_RECLEV:
+ IOCTL_IN(arg, data);
+ data = cs_set_gain(data);
+ return IOCTL_OUT(arg, data);
+ case SOUND_MIXER_READ_RECLEV:
+ data = cs_get_gain(cs4218_control);
+ return IOCTL_OUT(arg, data);
+ }
+
+ return -EINVAL;
+}
+
+
+static struct file_operations mixer_fops =
+{
+ .owner = THIS_MODULE,
+ .llseek = sound_lseek,
+ .ioctl = mixer_ioctl,
+ .open = mixer_open,
+ .release = mixer_release,
+};
+
+
+static void __init mixer_init(void)
+{
+ mixer_unit = register_sound_mixer(&mixer_fops, -1);
+ if (mixer_unit < 0)
+ return;
+
+ mixer.busy = 0;
+ sound.treble = 0;
+ sound.bass = 0;
+
+ /* Set Line input, no gain, no attenuation.
+ */
+ cs4218_control = CS_ISL | CS_ISR | CS_DO1;
+ cs4218_control |= CS_LGAIN_SET(0) | CS_RGAIN_SET(0);
+ cs4218_control |= CS_LATTEN_SET(0) | CS_RATTEN_SET(0);
+ cs4218_ctl_write(cs4218_control);
+}
+
+
+/*
+ * Sound queue stuff, the heart of the driver
+ */
+
+
+static int sq_allocate_buffers(void)
+{
+ int i;
+
+ if (sound_buffers)
+ return 0;
+ sound_buffers = kmalloc (numBufs * sizeof(char *), GFP_KERNEL);
+ if (!sound_buffers)
+ return -ENOMEM;
+ for (i = 0; i < numBufs; i++) {
+ sound_buffers[i] = sound.mach.dma_alloc (bufSize << 10, GFP_KERNEL);
+ if (!sound_buffers[i]) {
+ while (i--)
+ sound.mach.dma_free (sound_buffers[i], bufSize << 10);
+ kfree (sound_buffers);
+ sound_buffers = 0;
+ return -ENOMEM;
+ }
+ }
+ return 0;
+}
+
+
+static void sq_release_buffers(void)
+{
+ int i;
+
+ if (sound_buffers) {
+ for (i = 0; i < numBufs; i++)
+ sound.mach.dma_free (sound_buffers[i], bufSize << 10);
+ kfree (sound_buffers);
+ sound_buffers = 0;
+ }
+}
+
+
+static int sq_allocate_read_buffers(void)
+{
+ int i;
+
+ if (sound_read_buffers)
+ return 0;
+ sound_read_buffers = kmalloc(numReadBufs * sizeof(char *), GFP_KERNEL);
+ if (!sound_read_buffers)
+ return -ENOMEM;
+ for (i = 0; i < numBufs; i++) {
+ sound_read_buffers[i] = sound.mach.dma_alloc (readbufSize<<10,
+ GFP_KERNEL);
+ if (!sound_read_buffers[i]) {
+ while (i--)
+ sound.mach.dma_free (sound_read_buffers[i],
+ readbufSize << 10);
+ kfree (sound_read_buffers);
+ sound_read_buffers = 0;
+ return -ENOMEM;
+ }
+ }
+ return 0;
+}
+
+static void sq_release_read_buffers(void)
+{
+ int i;
+
+ if (sound_read_buffers) {
+ cpmp->cp_smc[1].smc_smcmr &= ~SMCMR_REN;
+ for (i = 0; i < numReadBufs; i++)
+ sound.mach.dma_free (sound_read_buffers[i],
+ bufSize << 10);
+ kfree (sound_read_buffers);
+ sound_read_buffers = 0;
+ }
+}
+
+
+static void sq_setup(int numBufs, int bufSize, char **write_buffers)
+{
+ int i;
+ volatile cbd_t *bdp;
+ volatile cpm8xx_t *cp;
+ volatile smc_t *sp;
+
+ /* Make sure the SMC transmit is shut down.
+ */
+ cp = cpmp;
+ sp = &cpmp->cp_smc[1];
+ sp->smc_smcmr &= ~SMCMR_TEN;
+
+ sq.max_count = numBufs;
+ sq.max_active = numBufs;
+ sq.block_size = bufSize;
+ sq.buffers = write_buffers;
+
+ sq.front = sq.count = 0;
+ sq.rear = -1;
+ sq.syncing = 0;
+ sq.active = 0;
+
+ bdp = tx_base;
+ for (i=0; i<numBufs; i++) {
+ bdp->cbd_bufaddr = virt_to_bus(write_buffers[i]);
+ bdp++;
+ }
+
+ /* This causes the SMC to sync up with the first buffer again.
+ */
+ cp->cp_cpcr = mk_cr_cmd(CPM_CR_CH_SMC2, CPM_CR_INIT_TX) | CPM_CR_FLG;
+ while (cp->cp_cpcr & CPM_CR_FLG);
+}
+
+static void read_sq_setup(int numBufs, int bufSize, char **read_buffers)
+{
+ int i;
+ volatile cbd_t *bdp;
+ volatile cpm8xx_t *cp;
+ volatile smc_t *sp;
+
+ /* Make sure the SMC receive is shut down.
+ */
+ cp = cpmp;
+ sp = &cpmp->cp_smc[1];
+ sp->smc_smcmr &= ~SMCMR_REN;
+
+ read_sq.max_count = numBufs;
+ read_sq.max_active = numBufs;
+ read_sq.block_size = bufSize;
+ read_sq.buffers = read_buffers;
+
+ read_sq.front = read_sq.count = 0;
+ read_sq.rear = 0;
+ read_sq.rear_size = 0;
+ read_sq.syncing = 0;
+ read_sq.active = 0;
+
+ bdp = rx_base;
+ for (i=0; i<numReadBufs; i++) {
+ bdp->cbd_bufaddr = virt_to_bus(read_buffers[i]);
+ bdp->cbd_datlen = read_sq.block_size;
+ bdp++;
+ }
+
+ /* This causes the SMC to sync up with the first buffer again.
+ */
+ cp->cp_cpcr = mk_cr_cmd(CPM_CR_CH_SMC2, CPM_CR_INIT_RX) | CPM_CR_FLG;
+ while (cp->cp_cpcr & CPM_CR_FLG);
+}
+
+
+static void sq_play(void)
+{
+ (*sound.mach.play)();
+}
+
+
+/* ++TeSche: radically changed this one too */
+
+static ssize_t sq_write(struct file *file, const char *src, size_t uLeft,
+ loff_t *ppos)
+{
+ ssize_t uWritten = 0;
+ u_char *dest;
+ ssize_t uUsed, bUsed, bLeft;
+
+ /* ++TeSche: Is something like this necessary?
+ * Hey, that's an honest question! Or does any other part of the
+ * filesystem already checks this situation? I really don't know.
+ */
+ if (uLeft == 0)
+ return 0;
+
+ /* The interrupt doesn't start to play the last, incomplete frame.
+ * Thus we can append to it without disabling the interrupts! (Note
+ * also that sq.rear isn't affected by the interrupt.)
+ */
+
+ if (sq.count > 0 && (bLeft = sq.block_size-sq.rear_size) > 0) {
+ dest = sq_block_address(sq.rear);
+ bUsed = sq.rear_size;
+ uUsed = sound_copy_translate(src, uLeft, dest, &bUsed, bLeft);
+ if (uUsed <= 0)
+ return uUsed;
+ src += uUsed;
+ uWritten += uUsed;
+ uLeft -= uUsed;
+ sq.rear_size = bUsed;
+ }
+
+ do {
+ while (sq.count == sq.max_active) {
+ sq_play();
+ if (NON_BLOCKING(sq.open_mode))
+ return uWritten > 0 ? uWritten : -EAGAIN;
+ SLEEP(sq.action_queue);
+ if (SIGNAL_RECEIVED)
+ return uWritten > 0 ? uWritten : -EINTR;
+ }
+
+ /* Here, we can avoid disabling the interrupt by first
+ * copying and translating the data, and then updating
+ * the sq variables. Until this is done, the interrupt
+ * won't see the new frame and we can work on it
+ * undisturbed.
+ */
+
+ dest = sq_block_address((sq.rear+1) % sq.max_count);
+ bUsed = 0;
+ bLeft = sq.block_size;
+ uUsed = sound_copy_translate(src, uLeft, dest, &bUsed, bLeft);
+ if (uUsed <= 0)
+ break;
+ src += uUsed;
+ uWritten += uUsed;
+ uLeft -= uUsed;
+ if (bUsed) {
+ sq.rear = (sq.rear+1) % sq.max_count;
+ sq.rear_size = bUsed;
+ sq.count++;
+ }
+ } while (bUsed); /* uUsed may have been 0 */
+
+ sq_play();
+
+ return uUsed < 0? uUsed: uWritten;
+}
+
+
+/***********/
+
+/* Here is how the values are used for reading.
+ * The value 'active' simply indicates the DMA is running. This is
+ * done so the driver semantics are DMA starts when the first read is
+ * posted. The value 'front' indicates the buffer we should next
+ * send to the user. The value 'rear' indicates the buffer the DMA is
+ * currently filling. When 'front' == 'rear' the buffer "ring" is
+ * empty (we always have an empty available). The 'rear_size' is used
+ * to track partial offsets into the current buffer. Right now, I just keep
+ * The DMA running. If the reader can't keep up, the interrupt tosses
+ * the oldest buffer. We could also shut down the DMA in this case.
+ */
+static ssize_t sq_read(struct file *file, char *dst, size_t uLeft,
+ loff_t *ppos)
+{
+
+ ssize_t uRead, bLeft, bUsed, uUsed;
+
+ if (uLeft == 0)
+ return 0;
+
+ if (!read_sq.active)
+ CS_Record(); /* Kick off the record process. */
+
+ uRead = 0;
+
+ /* Move what the user requests, depending upon other options.
+ */
+ while (uLeft > 0) {
+
+ /* When front == rear, the DMA is not done yet.
+ */
+ while (read_sq.front == read_sq.rear) {
+ if (NON_BLOCKING(read_sq.open_mode)) {
+ return uRead > 0 ? uRead : -EAGAIN;
+ }
+ SLEEP(read_sq.action_queue);
+ if (SIGNAL_RECEIVED)
+ return uRead > 0 ? uRead : -EINTR;
+ }
+
+ /* The amount we move is either what is left in the
+ * current buffer or what the user wants.
+ */
+ bLeft = read_sq.block_size - read_sq.rear_size;
+ bUsed = read_sq.rear_size;
+ uUsed = sound_copy_translate_read(dst, uLeft,
+ read_sq.buffers[read_sq.front], &bUsed, bLeft);
+ if (uUsed <= 0)
+ return uUsed;
+ dst += uUsed;
+ uRead += uUsed;
+ uLeft -= uUsed;
+ read_sq.rear_size += bUsed;
+ if (read_sq.rear_size >= read_sq.block_size) {
+ read_sq.rear_size = 0;
+ read_sq.front++;
+ if (read_sq.front >= read_sq.max_active)
+ read_sq.front = 0;
+ }
+ }
+ return uRead;
+}
+
+static int sq_open(struct inode *inode, struct file *file)
+{
+ int rc = 0;
+
+ if (file->f_mode & FMODE_WRITE) {
+ if (sq.busy) {
+ rc = -EBUSY;
+ if (NON_BLOCKING(file->f_flags))
+ goto err_out;
+ rc = -EINTR;
+ while (sq.busy) {
+ SLEEP(sq.open_queue);
+ if (SIGNAL_RECEIVED)
+ goto err_out;
+ }
+ }
+ sq.busy = 1; /* Let's play spot-the-race-condition */
+
+ if (sq_allocate_buffers()) goto err_out_nobusy;
+
+ sq_setup(numBufs, bufSize<<10,sound_buffers);
+ sq.open_mode = file->f_mode;
+ }
+
+
+ if (file->f_mode & FMODE_READ) {
+ if (read_sq.busy) {
+ rc = -EBUSY;
+ if (NON_BLOCKING(file->f_flags))
+ goto err_out;
+ rc = -EINTR;
+ while (read_sq.busy) {
+ SLEEP(read_sq.open_queue);
+ if (SIGNAL_RECEIVED)
+ goto err_out;
+ }
+ rc = 0;
+ }
+ read_sq.busy = 1;
+ if (sq_allocate_read_buffers()) goto err_out_nobusy;
+
+ read_sq_setup(numReadBufs,readbufSize<<10, sound_read_buffers);
+ read_sq.open_mode = file->f_mode;
+ }
+
+ /* Start up the 4218 by:
+ * Reset.
+ * Enable, unreset.
+ */
+ *((volatile uint *)HIOX_CSR4_ADDR) &= ~HIOX_CSR4_RSTAUDIO;
+ eieio();
+ *((volatile uint *)HIOX_CSR4_ADDR) |= HIOX_CSR4_ENAUDIO;
+ mdelay(50);
+ *((volatile uint *)HIOX_CSR4_ADDR) |= HIOX_CSR4_RSTAUDIO;
+
+ /* We need to send the current control word in case someone
+ * opened /dev/mixer and changed things while we were shut
+ * down. Chances are good the initialization that follows
+ * would have done this, but it is still possible it wouldn't.
+ */
+ cs4218_ctl_write(cs4218_control);
+
+ sound.minDev = iminor(inode) & 0x0f;
+ sound.soft = sound.dsp;
+ sound.hard = sound.dsp;
+ sound_init();
+ if ((iminor(inode) & 0x0f) == SND_DEV_AUDIO) {
+ sound_set_speed(8000);
+ sound_set_stereo(0);
+ sound_set_format(AFMT_MU_LAW);
+ }
+
+ return nonseekable_open(inode, file);
+
+err_out_nobusy:
+ if (file->f_mode & FMODE_WRITE) {
+ sq.busy = 0;
+ WAKE_UP(sq.open_queue);
+ }
+ if (file->f_mode & FMODE_READ) {
+ read_sq.busy = 0;
+ WAKE_UP(read_sq.open_queue);
+ }
+err_out:
+ return rc;
+}
+
+
+static void sq_reset(void)
+{
+ sound_silence();
+ sq.active = 0;
+ sq.count = 0;
+ sq.front = (sq.rear+1) % sq.max_count;
+#if 0
+ init_tdm_buffers();
+#endif
+}
+
+
+static int sq_fsync(struct file *filp, struct dentry *dentry)
+{
+ int rc = 0;
+
+ sq.syncing = 1;
+ sq_play(); /* there may be an incomplete frame waiting */
+
+ while (sq.active) {
+ SLEEP(sq.sync_queue);
+ if (SIGNAL_RECEIVED) {
+ /* While waiting for audio output to drain, an
+ * interrupt occurred. Stop audio output immediately
+ * and clear the queue. */
+ sq_reset();
+ rc = -EINTR;
+ break;
+ }
+ }
+
+ sq.syncing = 0;
+ return rc;
+}
+
+static int sq_release(struct inode *inode, struct file *file)
+{
+ int rc = 0;
+
+ if (sq.busy)
+ rc = sq_fsync(file, file->f_dentry);
+ sound.soft = sound.dsp;
+ sound.hard = sound.dsp;
+ sound_silence();
+
+ sq_release_read_buffers();
+ sq_release_buffers();
+
+ if (file->f_mode & FMODE_READ) {
+ read_sq.busy = 0;
+ WAKE_UP(read_sq.open_queue);
+ }
+
+ if (file->f_mode & FMODE_WRITE) {
+ sq.busy = 0;
+ WAKE_UP(sq.open_queue);
+ }
+
+ /* Shut down the SMC.
+ */
+ cpmp->cp_smc[1].smc_smcmr &= ~(SMCMR_TEN | SMCMR_REN);
+
+ /* Shut down the codec.
+ */
+ *((volatile uint *)HIOX_CSR4_ADDR) |= HIOX_CSR4_RSTAUDIO;
+ eieio();
+ *((volatile uint *)HIOX_CSR4_ADDR) &= ~HIOX_CSR4_ENAUDIO;
+
+ /* Wake up a process waiting for the queue being released.
+ * Note: There may be several processes waiting for a call
+ * to open() returning. */
+
+ return rc;
+}
+
+
+static int sq_ioctl(struct inode *inode, struct file *file, u_int cmd,
+ u_long arg)
+{
+ u_long fmt;
+ int data;
+#if 0
+ int size, nbufs;
+#else
+ int size;
+#endif
+
+ switch (cmd) {
+ case SNDCTL_DSP_RESET:
+ sq_reset();
+ return 0;
+ case SNDCTL_DSP_POST:
+ case SNDCTL_DSP_SYNC:
+ return sq_fsync(file, file->f_dentry);
+
+ /* ++TeSche: before changing any of these it's
+ * probably wise to wait until sound playing has
+ * settled down. */
+ case SNDCTL_DSP_SPEED:
+ sq_fsync(file, file->f_dentry);
+ IOCTL_IN(arg, data);
+ return IOCTL_OUT(arg, sound_set_speed(data));
+ case SNDCTL_DSP_STEREO:
+ sq_fsync(file, file->f_dentry);
+ IOCTL_IN(arg, data);
+ return IOCTL_OUT(arg, sound_set_stereo(data));
+ case SOUND_PCM_WRITE_CHANNELS:
+ sq_fsync(file, file->f_dentry);
+ IOCTL_IN(arg, data);
+ return IOCTL_OUT(arg, sound_set_stereo(data-1)+1);
+ case SNDCTL_DSP_SETFMT:
+ sq_fsync(file, file->f_dentry);
+ IOCTL_IN(arg, data);
+ return IOCTL_OUT(arg, sound_set_format(data));
+ case SNDCTL_DSP_GETFMTS:
+ fmt = 0;
+ if (sound.trans_write) {
+ if (sound.trans_write->ct_ulaw)
+ fmt |= AFMT_MU_LAW;
+ if (sound.trans_write->ct_alaw)
+ fmt |= AFMT_A_LAW;
+ if (sound.trans_write->ct_s8)
+ fmt |= AFMT_S8;
+ if (sound.trans_write->ct_u8)
+ fmt |= AFMT_U8;
+ if (sound.trans_write->ct_s16be)
+ fmt |= AFMT_S16_BE;
+ if (sound.trans_write->ct_u16be)
+ fmt |= AFMT_U16_BE;
+ if (sound.trans_write->ct_s16le)
+ fmt |= AFMT_S16_LE;
+ if (sound.trans_write->ct_u16le)
+ fmt |= AFMT_U16_LE;
+ }
+ return IOCTL_OUT(arg, fmt);
+ case SNDCTL_DSP_GETBLKSIZE:
+ size = sq.block_size
+ * sound.soft.size * (sound.soft.stereo + 1)
+ / (sound.hard.size * (sound.hard.stereo + 1));
+ return IOCTL_OUT(arg, size);
+ case SNDCTL_DSP_SUBDIVIDE:
+ break;
+#if 0 /* Sorry can't do this at the moment. The CPM allocated buffers
+ * long ago that can't be changed.
+ */
+ case SNDCTL_DSP_SETFRAGMENT:
+ if (sq.count || sq.active || sq.syncing)
+ return -EINVAL;
+ IOCTL_IN(arg, size);
+ nbufs = size >> 16;
+ if (nbufs < 2 || nbufs > numBufs)
+ nbufs = numBufs;
+ size &= 0xffff;
+ if (size >= 8 && size <= 30) {
+ size = 1 << size;
+ size *= sound.hard.size * (sound.hard.stereo + 1);
+ size /= sound.soft.size * (sound.soft.stereo + 1);
+ if (size > (bufSize << 10))
+ size = bufSize << 10;
+ } else
+ size = bufSize << 10;
+ sq_setup(numBufs, size, sound_buffers);
+ sq.max_active = nbufs;
+ return 0;
+#endif
+
+ default:
+ return mixer_ioctl(inode, file, cmd, arg);
+ }
+ return -EINVAL;
+}
+
+
+
+static struct file_operations sq_fops =
+{
+ .owner = THIS_MODULE,
+ .llseek = sound_lseek,
+ .read = sq_read, /* sq_read */
+ .write = sq_write,
+ .ioctl = sq_ioctl,
+ .open = sq_open,
+ .release = sq_release,
+};
+
+
+static void __init sq_init(void)
+{
+ sq_unit = register_sound_dsp(&sq_fops, -1);
+ if (sq_unit < 0)
+ return;
+
+ init_waitqueue_head(&sq.action_queue);
+ init_waitqueue_head(&sq.open_queue);
+ init_waitqueue_head(&sq.sync_queue);
+ init_waitqueue_head(&read_sq.action_queue);
+ init_waitqueue_head(&read_sq.open_queue);
+ init_waitqueue_head(&read_sq.sync_queue);
+
+ sq.busy = 0;
+ read_sq.busy = 0;
+
+ /* whatever you like as startup mode for /dev/dsp,
+ * (/dev/audio hasn't got a startup mode). note that
+ * once changed a new open() will *not* restore these!
+ */
+ sound.dsp.format = AFMT_S16_BE;
+ sound.dsp.stereo = 1;
+ sound.dsp.size = 16;
+
+ /* set minimum rate possible without expanding */
+ sound.dsp.speed = 8000;
+
+ /* before the first open to /dev/dsp this wouldn't be set */
+ sound.soft = sound.dsp;
+ sound.hard = sound.dsp;
+
+ sound_silence();
+}
+
+/*
+ * /dev/sndstat
+ */
+
+
+/* state.buf should not overflow! */
+
+static int state_open(struct inode *inode, struct file *file)
+{
+ char *buffer = state.buf, *mach = "", cs4218_buf[50];
+ int len = 0;
+
+ if (state.busy)
+ return -EBUSY;
+
+ state.ptr = 0;
+ state.busy = 1;
+
+ sprintf(cs4218_buf, "Crystal CS4218 on TDM, ");
+ mach = cs4218_buf;
+
+ len += sprintf(buffer+len, "%sDMA sound driver:\n", mach);
+
+ len += sprintf(buffer+len, "\tsound.format = 0x%x", sound.soft.format);
+ switch (sound.soft.format) {
+ case AFMT_MU_LAW:
+ len += sprintf(buffer+len, " (mu-law)");
+ break;
+ case AFMT_A_LAW:
+ len += sprintf(buffer+len, " (A-law)");
+ break;
+ case AFMT_U8:
+ len += sprintf(buffer+len, " (unsigned 8 bit)");
+ break;
+ case AFMT_S8:
+ len += sprintf(buffer+len, " (signed 8 bit)");
+ break;
+ case AFMT_S16_BE:
+ len += sprintf(buffer+len, " (signed 16 bit big)");
+ break;
+ case AFMT_U16_BE:
+ len += sprintf(buffer+len, " (unsigned 16 bit big)");
+ break;
+ case AFMT_S16_LE:
+ len += sprintf(buffer+len, " (signed 16 bit little)");
+ break;
+ case AFMT_U16_LE:
+ len += sprintf(buffer+len, " (unsigned 16 bit little)");
+ break;
+ }
+ len += sprintf(buffer+len, "\n");
+ len += sprintf(buffer+len, "\tsound.speed = %dHz (phys. %dHz)\n",
+ sound.soft.speed, sound.hard.speed);
+ len += sprintf(buffer+len, "\tsound.stereo = 0x%x (%s)\n",
+ sound.soft.stereo, sound.soft.stereo ? "stereo" : "mono");
+ len += sprintf(buffer+len, "\tsq.block_size = %d sq.max_count = %d"
+ " sq.max_active = %d\n",
+ sq.block_size, sq.max_count, sq.max_active);
+ len += sprintf(buffer+len, "\tsq.count = %d sq.rear_size = %d\n", sq.count,
+ sq.rear_size);
+ len += sprintf(buffer+len, "\tsq.active = %d sq.syncing = %d\n",
+ sq.active, sq.syncing);
+ state.len = len;
+ return nonseekable_open(inode, file);
+}
+
+
+static int state_release(struct inode *inode, struct file *file)
+{
+ state.busy = 0;
+ return 0;
+}
+
+
+static ssize_t state_read(struct file *file, char *buf, size_t count,
+ loff_t *ppos)
+{
+ int n = state.len - state.ptr;
+ if (n > count)
+ n = count;
+ if (n <= 0)
+ return 0;
+ if (copy_to_user(buf, &state.buf[state.ptr], n))
+ return -EFAULT;
+ state.ptr += n;
+ return n;
+}
+
+
+static struct file_operations state_fops =
+{
+ .owner = THIS_MODULE,
+ .llseek = sound_lseek,
+ .read = state_read,
+ .open = state_open,
+ .release = state_release,
+};
+
+
+static void __init state_init(void)
+{
+ state_unit = register_sound_special(&state_fops, SND_DEV_STATUS);
+ if (state_unit < 0)
+ return;
+ state.busy = 0;
+}
+
+
+/*** Common stuff ********************************************************/
+
+static long long sound_lseek(struct file *file, long long offset, int orig)
+{
+ return -ESPIPE;
+}
+
+
+/*** Config & Setup **********************************************************/
+
+
+int __init tdm8xx_sound_init(void)
+{
+ int i, has_sound;
+ uint dp_offset;
+ volatile uint *sirp;
+ volatile cbd_t *bdp;
+ volatile cpm8xx_t *cp;
+ volatile smc_t *sp;
+ volatile smc_uart_t *up;
+ volatile immap_t *immap;
+
+ has_sound = 0;
+
+ /* Program the SI/TSA to use TDMa, connected to SMC2, for 4 bytes.
+ */
+ cp = cpmp; /* Get pointer to Communication Processor */
+ immap = (immap_t *)IMAP_ADDR; /* and to internal registers */
+
+ /* Set all TDMa control bits to zero. This enables most features
+ * we want.
+ */
+ cp->cp_simode &= ~0x00000fff;
+
+ /* Enable common receive/transmit clock pins, use IDL format.
+ * Sync on falling edge, transmit rising clock, receive falling
+ * clock, delay 1 bit on both Tx and Rx. Common Tx/Rx clocks and
+ * sync.
+ * Connect SMC2 to TSA.
+ */
+ cp->cp_simode |= 0x80000141;
+
+ /* Configure port A pins for TDMa operation.
+ * The RPX-Lite (MPC850/823) loses SMC2 when TDM is used.
+ */
+ immap->im_ioport.iop_papar |= 0x01c0; /* Enable TDMa functions */
+ immap->im_ioport.iop_padir |= 0x00c0; /* Enable TDMa Tx/Rx */
+ immap->im_ioport.iop_padir &= ~0x0100; /* Enable L1RCLKa */
+
+ immap->im_ioport.iop_pcpar |= 0x0800; /* Enable L1RSYNCa */
+ immap->im_ioport.iop_pcdir &= ~0x0800;
+
+ /* Initialize the SI TDM routing table. We use TDMa only.
+ * The receive table and transmit table each have only one
+ * entry, to capture/send four bytes after each frame pulse.
+ * The 16-bit ram entry is 0000 0001 1000 1111. (SMC2)
+ */
+ cp->cp_sigmr = 0;
+ sirp = (uint *)cp->cp_siram;
+
+ *sirp = 0x018f0000; /* Receive entry */
+ sirp += 64;
+ *sirp = 0x018f0000; /* Tramsmit entry */
+
+ /* Enable single TDMa routing.
+ */
+ cp->cp_sigmr = 0x04;
+
+ /* Initialize the SMC for transparent operation.
+ */
+ sp = &cpmp->cp_smc[1];
+ up = (smc_uart_t *)&cp->cp_dparam[PROFF_SMC2];
+
+ /* We need to allocate a transmit and receive buffer
+ * descriptors from dual port ram.
+ */
+ dp_addr = cpm_dpalloc(sizeof(cbd_t) * numReadBufs, 8);
+
+ /* Set the physical address of the host memory
+ * buffers in the buffer descriptors, and the
+ * virtual address for us to work with.
+ */
+ bdp = (cbd_t *)&cp->cp_dpmem[dp_addr];
+ up->smc_rbase = dp_offset;
+ rx_cur = rx_base = (cbd_t *)bdp;
+
+ for (i=0; i<(numReadBufs-1); i++) {
+ bdp->cbd_bufaddr = 0;
+ bdp->cbd_datlen = 0;
+ bdp->cbd_sc = BD_SC_EMPTY | BD_SC_INTRPT;
+ bdp++;
+ }
+ bdp->cbd_bufaddr = 0;
+ bdp->cbd_datlen = 0;
+ bdp->cbd_sc = BD_SC_WRAP | BD_SC_EMPTY | BD_SC_INTRPT;
+
+ /* Now, do the same for the transmit buffers.
+ */
+ dp_offset = cpm_dpalloc(sizeof(cbd_t) * numBufs, 8);
+
+ bdp = (cbd_t *)&cp->cp_dpmem[dp_addr];
+ up->smc_tbase = dp_offset;
+ tx_cur = tx_base = (cbd_t *)bdp;
+
+ for (i=0; i<(numBufs-1); i++) {
+ bdp->cbd_bufaddr = 0;
+ bdp->cbd_datlen = 0;
+ bdp->cbd_sc = BD_SC_INTRPT;
+ bdp++;
+ }
+ bdp->cbd_bufaddr = 0;
+ bdp->cbd_datlen = 0;
+ bdp->cbd_sc = (BD_SC_WRAP | BD_SC_INTRPT);
+
+ /* Set transparent SMC mode.
+ * A few things are specific to our application. The codec interface
+ * is MSB first, hence the REVD selection. The CD/CTS pulse are
+ * used by the TSA to indicate the frame start to the SMC.
+ */
+ up->smc_rfcr = SCC_EB;
+ up->smc_tfcr = SCC_EB;
+ up->smc_mrblr = readbufSize * 1024;
+
+ /* Set 16-bit reversed data, transparent mode.
+ */
+ sp->smc_smcmr = smcr_mk_clen(15) |
+ SMCMR_SM_TRANS | SMCMR_REVD | SMCMR_BS;
+
+ /* Enable and clear events.
+ * Because of FIFO delays, all we need is the receive interrupt
+ * and we can process both the current receive and current
+ * transmit interrupt within a few microseconds of the transmit.
+ */
+ sp->smc_smce = 0xff;
+ sp->smc_smcm = SMCM_TXE | SMCM_TX | SMCM_RX;
+
+ /* Send the CPM an initialize command.
+ */
+ cp->cp_cpcr = mk_cr_cmd(CPM_CR_CH_SMC2,
+ CPM_CR_INIT_TRX) | CPM_CR_FLG;
+ while (cp->cp_cpcr & CPM_CR_FLG);
+
+ sound.mach = mach_cs4218;
+ has_sound = 1;
+
+ /* Initialize beep stuff */
+ orig_mksound = kd_mksound;
+ kd_mksound = cs_mksound;
+ beep_buf = (short *) kmalloc(BEEP_BUFLEN * 4, GFP_KERNEL);
+ if (beep_buf == NULL)
+ printk(KERN_WARNING "dmasound: no memory for "
+ "beep buffer\n");
+
+ if (!has_sound)
+ return -ENODEV;
+
+ /* Initialize the software SPI.
+ */
+ sw_spi_init();
+
+ /* Set up sound queue, /dev/audio and /dev/dsp. */
+
+ /* Set default settings. */
+ sq_init();
+
+ /* Set up /dev/sndstat. */
+ state_init();
+
+ /* Set up /dev/mixer. */
+ mixer_init();
+
+ if (!sound.mach.irqinit()) {
+ printk(KERN_ERR "DMA sound driver: Interrupt initialization failed\n");
+ return -ENODEV;
+ }
+#ifdef MODULE
+ irq_installed = 1;
+#endif
+
+ printk(KERN_INFO "DMA sound driver installed, using %d buffers of %dk.\n",
+ numBufs, bufSize);
+
+ return 0;
+}
+
+/* Due to FIFOs and bit delays, the transmit interrupt occurs a few
+ * microseconds ahead of the receive interrupt.
+ * When we get an interrupt, we service the transmit first, then
+ * check for a receive to prevent the overhead of returning through
+ * the interrupt handler only to get back here right away during
+ * full duplex operation.
+ */
+static void
+cs4218_intr(void *dev_id, struct pt_regs *regs)
+{
+ volatile smc_t *sp;
+ volatile cpm8xx_t *cp;
+
+ sp = &cpmp->cp_smc[1];
+
+ if (sp->smc_smce & SCCM_TX) {
+ sp->smc_smce = SCCM_TX;
+ cs4218_tdm_tx_intr((void *)sp);
+ }
+
+ if (sp->smc_smce & SCCM_RX) {
+ sp->smc_smce = SCCM_RX;
+ cs4218_tdm_rx_intr((void *)sp);
+ }
+
+ if (sp->smc_smce & SCCM_TXE) {
+ /* Transmit underrun. This happens with the application
+ * didn't keep up sending buffers. We tell the SMC to
+ * restart, which will cause it to poll the current (next)
+ * BD. If the user supplied data since this occurred,
+ * we just start running again. If they didn't, the SMC
+ * will poll the descriptor until data is placed there.
+ */
+ sp->smc_smce = SCCM_TXE;
+ cp = cpmp; /* Get pointer to Communication Processor */
+ cp->cp_cpcr = mk_cr_cmd(CPM_CR_CH_SMC2,
+ CPM_CR_RESTART_TX) | CPM_CR_FLG;
+ while (cp->cp_cpcr & CPM_CR_FLG);
+ }
+}
+
+
+#define MAXARGS 8 /* Should be sufficient for now */
+
+void __init dmasound_setup(char *str, int *ints)
+{
+ /* check the bootstrap parameter for "dmasound=" */
+
+ switch (ints[0]) {
+ case 3:
+ if ((ints[3] < 0) || (ints[3] > MAX_CATCH_RADIUS))
+ printk("dmasound_setup: invalid catch radius, using default = %d\n", catchRadius);
+ else
+ catchRadius = ints[3];
+ /* fall through */
+ case 2:
+ if (ints[1] < MIN_BUFFERS)
+ printk("dmasound_setup: invalid number of buffers, using default = %d\n", numBufs);
+ else
+ numBufs = ints[1];
+ if (ints[2] < MIN_BUFSIZE || ints[2] > MAX_BUFSIZE)
+ printk("dmasound_setup: invalid buffer size, using default = %d\n", bufSize);
+ else
+ bufSize = ints[2];
+ break;
+ case 0:
+ break;
+ default:
+ printk("dmasound_setup: invalid number of arguments\n");
+ }
+}
+
+/* Software SPI functions.
+ * These are on Port B.
+ */
+#define PB_SPICLK ((uint)0x00000002)
+#define PB_SPIMOSI ((uint)0x00000004)
+#define PB_SPIMISO ((uint)0x00000008)
+
+static
+void sw_spi_init(void)
+{
+ volatile cpm8xx_t *cp;
+ volatile uint *hcsr4;
+
+ hcsr4 = (volatile uint *)HIOX_CSR4_ADDR;
+ cp = cpmp; /* Get pointer to Communication Processor */
+
+ *hcsr4 &= ~HIOX_CSR4_AUDSPISEL; /* Disable SPI select */
+
+ /* Make these Port B signals general purpose I/O.
+ * First, make sure the clock is low.
+ */
+ cp->cp_pbdat &= ~PB_SPICLK;
+ cp->cp_pbpar &= ~(PB_SPICLK | PB_SPIMOSI | PB_SPIMISO);
+
+ /* Clock and Master Output are outputs.
+ */
+ cp->cp_pbdir |= (PB_SPICLK | PB_SPIMOSI);
+
+ /* Master Input.
+ */
+ cp->cp_pbdir &= ~PB_SPIMISO;
+
+}
+
+/* Write the CS4218 control word out the SPI port. While the
+ * the control word is going out, the status word is arriving.
+ */
+static
+uint cs4218_ctl_write(uint ctlreg)
+{
+ uint status;
+
+ sw_spi_io((u_char *)&ctlreg, (u_char *)&status, 4);
+
+ /* Shadow the control register.....I guess we could do
+ * the same for the status, but for now we just return it
+ * and let the caller decide.
+ */
+ cs4218_control = ctlreg;
+ return status;
+}
+
+static
+void sw_spi_io(u_char *obuf, u_char *ibuf, uint bcnt)
+{
+ int bits, i;
+ u_char outbyte, inbyte;
+ volatile cpm8xx_t *cp;
+ volatile uint *hcsr4;
+
+ hcsr4 = (volatile uint *)HIOX_CSR4_ADDR;
+ cp = cpmp; /* Get pointer to Communication Processor */
+
+ /* The timing on the bus is pretty slow. Code inefficiency
+ * and eieio() is our friend here :-).
+ */
+ cp->cp_pbdat &= ~PB_SPICLK;
+ *hcsr4 |= HIOX_CSR4_AUDSPISEL; /* Enable SPI select */
+ eieio();
+
+ /* Clock in/out the bytes. Data is valid on the falling edge
+ * of the clock. Data is MSB first.
+ */
+ for (i=0; i<bcnt; i++) {
+ outbyte = *obuf++;
+ inbyte = 0;
+ for (bits=0; bits<8; bits++) {
+ eieio();
+ cp->cp_pbdat |= PB_SPICLK;
+ eieio();
+ if (outbyte & 0x80)
+ cp->cp_pbdat |= PB_SPIMOSI;
+ else
+ cp->cp_pbdat &= ~PB_SPIMOSI;
+ eieio();
+ cp->cp_pbdat &= ~PB_SPICLK;
+ eieio();
+ outbyte <<= 1;
+ inbyte <<= 1;
+ if (cp->cp_pbdat & PB_SPIMISO)
+ inbyte |= 1;
+ }
+ *ibuf++ = inbyte;
+ }
+
+ *hcsr4 &= ~HIOX_CSR4_AUDSPISEL; /* Disable SPI select */
+ eieio();
+}
+
+void cleanup_module(void)
+{
+ if (irq_installed) {
+ sound_silence();
+#ifdef MODULE
+ sound.mach.irqcleanup();
+#endif
+ }
+
+ sq_release_read_buffers();
+ sq_release_buffers();
+
+ if (mixer_unit >= 0)
+ unregister_sound_mixer(mixer_unit);
+ if (state_unit >= 0)
+ unregister_sound_special(state_unit);
+ if (sq_unit >= 0)
+ unregister_sound_dsp(sq_unit);
+}
+
+module_init(tdm8xx_sound_init);
+module_exit(cleanup_module);
+
diff --git a/arch/ppc/8xx_io/enet.c b/arch/ppc/8xx_io/enet.c
new file mode 100644
index 0000000..4ea7158
--- /dev/null
+++ b/arch/ppc/8xx_io/enet.c
@@ -0,0 +1,971 @@
+/*
+ * Ethernet driver for Motorola MPC8xx.
+ * Copyright (c) 1997 Dan Malek (dmalek@jlc.net)
+ *
+ * I copied the basic skeleton from the lance driver, because I did not
+ * know how to write the Linux driver, but I did know how the LANCE worked.
+ *
+ * This version of the driver is somewhat selectable for the different
+ * processor/board combinations. It works for the boards I know about
+ * now, and should be easily modified to include others. Some of the
+ * configuration information is contained in <asm/commproc.h> and the
+ * remainder is here.
+ *
+ * Buffer descriptors are kept in the CPM dual port RAM, and the frame
+ * buffers are in the host memory.
+ *
+ * Right now, I am very watseful with the buffers. I allocate memory
+ * pages and then divide them into 2K frame buffers. This way I know I
+ * have buffers large enough to hold one frame within one buffer descriptor.
+ * Once I get this working, I will use 64 or 128 byte CPM buffers, which
+ * will be much more memory efficient and will easily handle lots of
+ * small packets.
+ *
+ */
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/string.h>
+#include <linux/ptrace.h>
+#include <linux/errno.h>
+#include <linux/ioport.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/spinlock.h>
+#include <linux/dma-mapping.h>
+#include <linux/bitops.h>
+
+#include <asm/8xx_immap.h>
+#include <asm/pgtable.h>
+#include <asm/mpc8xx.h>
+#include <asm/uaccess.h>
+#include <asm/commproc.h>
+
+/*
+ * Theory of Operation
+ *
+ * The MPC8xx CPM performs the Ethernet processing on SCC1. It can use
+ * an aribtrary number of buffers on byte boundaries, but must have at
+ * least two receive buffers to prevent constant overrun conditions.
+ *
+ * The buffer descriptors are allocated from the CPM dual port memory
+ * with the data buffers allocated from host memory, just like all other
+ * serial communication protocols. The host memory buffers are allocated
+ * from the free page pool, and then divided into smaller receive and
+ * transmit buffers. The size of the buffers should be a power of two,
+ * since that nicely divides the page. This creates a ring buffer
+ * structure similar to the LANCE and other controllers.
+ *
+ * Like the LANCE driver:
+ * The driver runs as two independent, single-threaded flows of control. One
+ * is the send-packet routine, which enforces single-threaded use by the
+ * cep->tx_busy flag. The other thread is the interrupt handler, which is
+ * single threaded by the hardware and other software.
+ *
+ * The send packet thread has partial control over the Tx ring and the
+ * 'cep->tx_busy' flag. It sets the tx_busy flag whenever it's queuing a Tx
+ * packet. If the next queue slot is empty, it clears the tx_busy flag when
+ * finished otherwise it sets the 'lp->tx_full' flag.
+ *
+ * The MBX has a control register external to the MPC8xx that has some
+ * control of the Ethernet interface. Information is in the manual for
+ * your board.
+ *
+ * The RPX boards have an external control/status register. Consult the
+ * programming documents for details unique to your board.
+ *
+ * For the TQM8xx(L) modules, there is no control register interface.
+ * All functions are directly controlled using I/O pins. See <asm/commproc.h>.
+ */
+
+/* The transmitter timeout
+ */
+#define TX_TIMEOUT (2*HZ)
+
+/* The number of Tx and Rx buffers. These are allocated from the page
+ * pool. The code may assume these are power of two, so it is best
+ * to keep them that size.
+ * We don't need to allocate pages for the transmitter. We just use
+ * the skbuffer directly.
+ */
+#ifdef CONFIG_ENET_BIG_BUFFERS
+#define CPM_ENET_RX_PAGES 32
+#define CPM_ENET_RX_FRSIZE 2048
+#define CPM_ENET_RX_FRPPG (PAGE_SIZE / CPM_ENET_RX_FRSIZE)
+#define RX_RING_SIZE (CPM_ENET_RX_FRPPG * CPM_ENET_RX_PAGES)
+#define TX_RING_SIZE 64 /* Must be power of two */
+#define TX_RING_MOD_MASK 63 /* for this to work */
+#else
+#define CPM_ENET_RX_PAGES 4
+#define CPM_ENET_RX_FRSIZE 2048
+#define CPM_ENET_RX_FRPPG (PAGE_SIZE / CPM_ENET_RX_FRSIZE)
+#define RX_RING_SIZE (CPM_ENET_RX_FRPPG * CPM_ENET_RX_PAGES)
+#define TX_RING_SIZE 8 /* Must be power of two */
+#define TX_RING_MOD_MASK 7 /* for this to work */
+#endif
+
+/* The CPM stores dest/src/type, data, and checksum for receive packets.
+ */
+#define PKT_MAXBUF_SIZE 1518
+#define PKT_MINBUF_SIZE 64
+#define PKT_MAXBLR_SIZE 1520
+
+/* The CPM buffer descriptors track the ring buffers. The rx_bd_base and
+ * tx_bd_base always point to the base of the buffer descriptors. The
+ * cur_rx and cur_tx point to the currently available buffer.
+ * The dirty_tx tracks the current buffer that is being sent by the
+ * controller. The cur_tx and dirty_tx are equal under both completely
+ * empty and completely full conditions. The empty/ready indicator in
+ * the buffer descriptor determines the actual condition.
+ */
+struct scc_enet_private {
+ /* The saved address of a sent-in-place packet/buffer, for skfree(). */
+ struct sk_buff* tx_skbuff[TX_RING_SIZE];
+ ushort skb_cur;
+ ushort skb_dirty;
+
+ /* CPM dual port RAM relative addresses.
+ */
+ cbd_t *rx_bd_base; /* Address of Rx and Tx buffers. */
+ cbd_t *tx_bd_base;
+ cbd_t *cur_rx, *cur_tx; /* The next free ring entry */
+ cbd_t *dirty_tx; /* The ring entries to be free()ed. */
+ scc_t *sccp;
+
+ /* Virtual addresses for the receive buffers because we can't
+ * do a __va() on them anymore.
+ */
+ unsigned char *rx_vaddr[RX_RING_SIZE];
+ struct net_device_stats stats;
+ uint tx_full;
+ spinlock_t lock;
+};
+
+static int scc_enet_open(struct net_device *dev);
+static int scc_enet_start_xmit(struct sk_buff *skb, struct net_device *dev);
+static int scc_enet_rx(struct net_device *dev);
+static void scc_enet_interrupt(void *dev_id, struct pt_regs *regs);
+static int scc_enet_close(struct net_device *dev);
+static struct net_device_stats *scc_enet_get_stats(struct net_device *dev);
+static void set_multicast_list(struct net_device *dev);
+
+/* Get this from various configuration locations (depends on board).
+*/
+/*static ushort my_enet_addr[] = { 0x0800, 0x3e26, 0x1559 };*/
+
+/* Typically, 860(T) boards use SCC1 for Ethernet, and other 8xx boards
+ * use SCC2. Some even may use SCC3.
+ * This is easily extended if necessary.
+ */
+#if defined(CONFIG_SCC3_ENET)
+#define CPM_CR_ENET CPM_CR_CH_SCC3
+#define PROFF_ENET PROFF_SCC3
+#define SCC_ENET 2 /* Index, not number! */
+#define CPMVEC_ENET CPMVEC_SCC3
+#elif defined(CONFIG_SCC2_ENET)
+#define CPM_CR_ENET CPM_CR_CH_SCC2
+#define PROFF_ENET PROFF_SCC2
+#define SCC_ENET 1 /* Index, not number! */
+#define CPMVEC_ENET CPMVEC_SCC2
+#elif defined(CONFIG_SCC1_ENET)
+#define CPM_CR_ENET CPM_CR_CH_SCC1
+#define PROFF_ENET PROFF_SCC1
+#define SCC_ENET 0 /* Index, not number! */
+#define CPMVEC_ENET CPMVEC_SCC1
+#else
+#error CONFIG_SCCx_ENET not defined
+#endif
+
+static int
+scc_enet_open(struct net_device *dev)
+{
+
+ /* I should reset the ring buffers here, but I don't yet know
+ * a simple way to do that.
+ */
+
+ netif_start_queue(dev);
+ return 0; /* Always succeed */
+}
+
+static int
+scc_enet_start_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+ struct scc_enet_private *cep = (struct scc_enet_private *)dev->priv;
+ volatile cbd_t *bdp;
+
+ /* Fill in a Tx ring entry */
+ bdp = cep->cur_tx;
+
+#ifndef final_version
+ if (bdp->cbd_sc & BD_ENET_TX_READY) {
+ /* Ooops. All transmit buffers are full. Bail out.
+ * This should not happen, since cep->tx_busy should be set.
+ */
+ printk("%s: tx queue full!.\n", dev->name);
+ return 1;
+ }
+#endif
+
+ /* Clear all of the status flags.
+ */
+ bdp->cbd_sc &= ~BD_ENET_TX_STATS;
+
+ /* If the frame is short, tell CPM to pad it.
+ */
+ if (skb->len <= ETH_ZLEN)
+ bdp->cbd_sc |= BD_ENET_TX_PAD;
+ else
+ bdp->cbd_sc &= ~BD_ENET_TX_PAD;
+
+ /* Set buffer length and buffer pointer.
+ */
+ bdp->cbd_datlen = skb->len;
+ bdp->cbd_bufaddr = __pa(skb->data);
+
+ /* Save skb pointer.
+ */
+ cep->tx_skbuff[cep->skb_cur] = skb;
+
+ cep->stats.tx_bytes += skb->len;
+ cep->skb_cur = (cep->skb_cur+1) & TX_RING_MOD_MASK;
+
+ /* Push the data cache so the CPM does not get stale memory
+ * data.
+ */
+ flush_dcache_range((unsigned long)(skb->data),
+ (unsigned long)(skb->data + skb->len));
+
+ spin_lock_irq(&cep->lock);
+
+ /* Send it on its way. Tell CPM its ready, interrupt when done,
+ * its the last BD of the frame, and to put the CRC on the end.
+ */
+ bdp->cbd_sc |= (BD_ENET_TX_READY | BD_ENET_TX_INTR | BD_ENET_TX_LAST | BD_ENET_TX_TC);
+
+ dev->trans_start = jiffies;
+
+ /* If this was the last BD in the ring, start at the beginning again.
+ */
+ if (bdp->cbd_sc & BD_ENET_TX_WRAP)
+ bdp = cep->tx_bd_base;
+ else
+ bdp++;
+
+ if (bdp->cbd_sc & BD_ENET_TX_READY) {
+ netif_stop_queue(dev);
+ cep->tx_full = 1;
+ }
+
+ cep->cur_tx = (cbd_t *)bdp;
+
+ spin_unlock_irq(&cep->lock);
+
+ return 0;
+}
+
+static void
+scc_enet_timeout(struct net_device *dev)
+{
+ struct scc_enet_private *cep = (struct scc_enet_private *)dev->priv;
+
+ printk("%s: transmit timed out.\n", dev->name);
+ cep->stats.tx_errors++;
+#ifndef final_version
+ {
+ int i;
+ cbd_t *bdp;
+ printk(" Ring data dump: cur_tx %p%s cur_rx %p.\n",
+ cep->cur_tx, cep->tx_full ? " (full)" : "",
+ cep->cur_rx);
+ bdp = cep->tx_bd_base;
+ for (i = 0 ; i < TX_RING_SIZE; i++, bdp++)
+ printk("%04x %04x %08x\n",
+ bdp->cbd_sc,
+ bdp->cbd_datlen,
+ bdp->cbd_bufaddr);
+ bdp = cep->rx_bd_base;
+ for (i = 0 ; i < RX_RING_SIZE; i++, bdp++)
+ printk("%04x %04x %08x\n",
+ bdp->cbd_sc,
+ bdp->cbd_datlen,
+ bdp->cbd_bufaddr);
+ }
+#endif
+ if (!cep->tx_full)
+ netif_wake_queue(dev);
+}
+
+/* The interrupt handler.
+ * This is called from the CPM handler, not the MPC core interrupt.
+ */
+static void
+scc_enet_interrupt(void *dev_id, struct pt_regs *regs)
+{
+ struct net_device *dev = dev_id;
+ volatile struct scc_enet_private *cep;
+ volatile cbd_t *bdp;
+ ushort int_events;
+ int must_restart;
+
+ cep = (struct scc_enet_private *)dev->priv;
+
+ /* Get the interrupt events that caused us to be here.
+ */
+ int_events = cep->sccp->scc_scce;
+ cep->sccp->scc_scce = int_events;
+ must_restart = 0;
+
+ /* Handle receive event in its own function.
+ */
+ if (int_events & SCCE_ENET_RXF)
+ scc_enet_rx(dev_id);
+
+ /* Check for a transmit error. The manual is a little unclear
+ * about this, so the debug code until I get it figured out. It
+ * appears that if TXE is set, then TXB is not set. However,
+ * if carrier sense is lost during frame transmission, the TXE
+ * bit is set, "and continues the buffer transmission normally."
+ * I don't know if "normally" implies TXB is set when the buffer
+ * descriptor is closed.....trial and error :-).
+ */
+
+ /* Transmit OK, or non-fatal error. Update the buffer descriptors.
+ */
+ if (int_events & (SCCE_ENET_TXE | SCCE_ENET_TXB)) {
+ spin_lock(&cep->lock);
+ bdp = cep->dirty_tx;
+ while ((bdp->cbd_sc&BD_ENET_TX_READY)==0) {
+ if ((bdp==cep->cur_tx) && (cep->tx_full == 0))
+ break;
+
+ if (bdp->cbd_sc & BD_ENET_TX_HB) /* No heartbeat */
+ cep->stats.tx_heartbeat_errors++;
+ if (bdp->cbd_sc & BD_ENET_TX_LC) /* Late collision */
+ cep->stats.tx_window_errors++;
+ if (bdp->cbd_sc & BD_ENET_TX_RL) /* Retrans limit */
+ cep->stats.tx_aborted_errors++;
+ if (bdp->cbd_sc & BD_ENET_TX_UN) /* Underrun */
+ cep->stats.tx_fifo_errors++;
+ if (bdp->cbd_sc & BD_ENET_TX_CSL) /* Carrier lost */
+ cep->stats.tx_carrier_errors++;
+
+
+ /* No heartbeat or Lost carrier are not really bad errors.
+ * The others require a restart transmit command.
+ */
+ if (bdp->cbd_sc &
+ (BD_ENET_TX_LC | BD_ENET_TX_RL | BD_ENET_TX_UN)) {
+ must_restart = 1;
+ cep->stats.tx_errors++;
+ }
+
+ cep->stats.tx_packets++;
+
+ /* Deferred means some collisions occurred during transmit,
+ * but we eventually sent the packet OK.
+ */
+ if (bdp->cbd_sc & BD_ENET_TX_DEF)
+ cep->stats.collisions++;
+
+ /* Free the sk buffer associated with this last transmit.
+ */
+ dev_kfree_skb_irq(cep->tx_skbuff[cep->skb_dirty]);
+ cep->skb_dirty = (cep->skb_dirty + 1) & TX_RING_MOD_MASK;
+
+ /* Update pointer to next buffer descriptor to be transmitted.
+ */
+ if (bdp->cbd_sc & BD_ENET_TX_WRAP)
+ bdp = cep->tx_bd_base;
+ else
+ bdp++;
+
+ /* I don't know if we can be held off from processing these
+ * interrupts for more than one frame time. I really hope
+ * not. In such a case, we would now want to check the
+ * currently available BD (cur_tx) and determine if any
+ * buffers between the dirty_tx and cur_tx have also been
+ * sent. We would want to process anything in between that
+ * does not have BD_ENET_TX_READY set.
+ */
+
+ /* Since we have freed up a buffer, the ring is no longer
+ * full.
+ */
+ if (cep->tx_full) {
+ cep->tx_full = 0;
+ if (netif_queue_stopped(dev))
+ netif_wake_queue(dev);
+ }
+
+ cep->dirty_tx = (cbd_t *)bdp;
+ }
+
+ if (must_restart) {
+ volatile cpm8xx_t *cp;
+
+ /* Some transmit errors cause the transmitter to shut
+ * down. We now issue a restart transmit. Since the
+ * errors close the BD and update the pointers, the restart
+ * _should_ pick up without having to reset any of our
+ * pointers either.
+ */
+ cp = cpmp;
+ cp->cp_cpcr =
+ mk_cr_cmd(CPM_CR_ENET, CPM_CR_RESTART_TX) | CPM_CR_FLG;
+ while (cp->cp_cpcr & CPM_CR_FLG);
+ }
+ spin_unlock(&cep->lock);
+ }
+
+ /* Check for receive busy, i.e. packets coming but no place to
+ * put them. This "can't happen" because the receive interrupt
+ * is tossing previous frames.
+ */
+ if (int_events & SCCE_ENET_BSY) {
+ cep->stats.rx_dropped++;
+ printk("CPM ENET: BSY can't happen.\n");
+ }
+
+ return;
+}
+
+/* During a receive, the cur_rx points to the current incoming buffer.
+ * When we update through the ring, if the next incoming buffer has
+ * not been given to the system, we just set the empty indicator,
+ * effectively tossing the packet.
+ */
+static int
+scc_enet_rx(struct net_device *dev)
+{
+ struct scc_enet_private *cep;
+ volatile cbd_t *bdp;
+ struct sk_buff *skb;
+ ushort pkt_len;
+
+ cep = (struct scc_enet_private *)dev->priv;
+
+ /* First, grab all of the stats for the incoming packet.
+ * These get messed up if we get called due to a busy condition.
+ */
+ bdp = cep->cur_rx;
+
+for (;;) {
+ if (bdp->cbd_sc & BD_ENET_RX_EMPTY)
+ break;
+
+#ifndef final_version
+ /* Since we have allocated space to hold a complete frame, both
+ * the first and last indicators should be set.
+ */
+ if ((bdp->cbd_sc & (BD_ENET_RX_FIRST | BD_ENET_RX_LAST)) !=
+ (BD_ENET_RX_FIRST | BD_ENET_RX_LAST))
+ printk("CPM ENET: rcv is not first+last\n");
+#endif
+
+ /* Frame too long or too short.
+ */
+ if (bdp->cbd_sc & (BD_ENET_RX_LG | BD_ENET_RX_SH))
+ cep->stats.rx_length_errors++;
+ if (bdp->cbd_sc & BD_ENET_RX_NO) /* Frame alignment */
+ cep->stats.rx_frame_errors++;
+ if (bdp->cbd_sc & BD_ENET_RX_CR) /* CRC Error */
+ cep->stats.rx_crc_errors++;
+ if (bdp->cbd_sc & BD_ENET_RX_OV) /* FIFO overrun */
+ cep->stats.rx_crc_errors++;
+
+ /* Report late collisions as a frame error.
+ * On this error, the BD is closed, but we don't know what we
+ * have in the buffer. So, just drop this frame on the floor.
+ */
+ if (bdp->cbd_sc & BD_ENET_RX_CL) {
+ cep->stats.rx_frame_errors++;
+ }
+ else {
+
+ /* Process the incoming frame.
+ */
+ cep->stats.rx_packets++;
+ pkt_len = bdp->cbd_datlen;
+ cep->stats.rx_bytes += pkt_len;
+
+ /* This does 16 byte alignment, much more than we need.
+ * The packet length includes FCS, but we don't want to
+ * include that when passing upstream as it messes up
+ * bridging applications.
+ */
+ skb = dev_alloc_skb(pkt_len-4);
+
+ if (skb == NULL) {
+ printk("%s: Memory squeeze, dropping packet.\n", dev->name);
+ cep->stats.rx_dropped++;
+ }
+ else {
+ skb->dev = dev;
+ skb_put(skb,pkt_len-4); /* Make room */
+ eth_copy_and_sum(skb,
+ cep->rx_vaddr[bdp - cep->rx_bd_base],
+ pkt_len-4, 0);
+ skb->protocol=eth_type_trans(skb,dev);
+ netif_rx(skb);
+ }
+ }
+
+ /* Clear the status flags for this buffer.
+ */
+ bdp->cbd_sc &= ~BD_ENET_RX_STATS;
+
+ /* Mark the buffer empty.
+ */
+ bdp->cbd_sc |= BD_ENET_RX_EMPTY;
+
+ /* Update BD pointer to next entry.
+ */
+ if (bdp->cbd_sc & BD_ENET_RX_WRAP)
+ bdp = cep->rx_bd_base;
+ else
+ bdp++;
+
+ }
+ cep->cur_rx = (cbd_t *)bdp;
+
+ return 0;
+}
+
+static int
+scc_enet_close(struct net_device *dev)
+{
+ /* Don't know what to do yet.
+ */
+ netif_stop_queue(dev);
+
+ return 0;
+}
+
+static struct net_device_stats *scc_enet_get_stats(struct net_device *dev)
+{
+ struct scc_enet_private *cep = (struct scc_enet_private *)dev->priv;
+
+ return &cep->stats;
+}
+
+/* Set or clear the multicast filter for this adaptor.
+ * Skeleton taken from sunlance driver.
+ * The CPM Ethernet implementation allows Multicast as well as individual
+ * MAC address filtering. Some of the drivers check to make sure it is
+ * a group multicast address, and discard those that are not. I guess I
+ * will do the same for now, but just remove the test if you want
+ * individual filtering as well (do the upper net layers want or support
+ * this kind of feature?).
+ */
+
+static void set_multicast_list(struct net_device *dev)
+{
+ struct scc_enet_private *cep;
+ struct dev_mc_list *dmi;
+ u_char *mcptr, *tdptr;
+ volatile scc_enet_t *ep;
+ int i, j;
+ cep = (struct scc_enet_private *)dev->priv;
+
+ /* Get pointer to SCC area in parameter RAM.
+ */
+ ep = (scc_enet_t *)dev->base_addr;
+
+ if (dev->flags&IFF_PROMISC) {
+
+ /* Log any net taps. */
+ printk("%s: Promiscuous mode enabled.\n", dev->name);
+ cep->sccp->scc_psmr |= SCC_PSMR_PRO;
+ } else {
+
+ cep->sccp->scc_psmr &= ~SCC_PSMR_PRO;
+
+ if (dev->flags & IFF_ALLMULTI) {
+ /* Catch all multicast addresses, so set the
+ * filter to all 1's.
+ */
+ ep->sen_gaddr1 = 0xffff;
+ ep->sen_gaddr2 = 0xffff;
+ ep->sen_gaddr3 = 0xffff;
+ ep->sen_gaddr4 = 0xffff;
+ }
+ else {
+ /* Clear filter and add the addresses in the list.
+ */
+ ep->sen_gaddr1 = 0;
+ ep->sen_gaddr2 = 0;
+ ep->sen_gaddr3 = 0;
+ ep->sen_gaddr4 = 0;
+
+ dmi = dev->mc_list;
+
+ for (i=0; i<dev->mc_count; i++) {
+
+ /* Only support group multicast for now.
+ */
+ if (!(dmi->dmi_addr[0] & 1))
+ continue;
+
+ /* The address in dmi_addr is LSB first,
+ * and taddr is MSB first. We have to
+ * copy bytes MSB first from dmi_addr.
+ */
+ mcptr = (u_char *)dmi->dmi_addr + 5;
+ tdptr = (u_char *)&ep->sen_taddrh;
+ for (j=0; j<6; j++)
+ *tdptr++ = *mcptr--;
+
+ /* Ask CPM to run CRC and set bit in
+ * filter mask.
+ */
+ cpmp->cp_cpcr = mk_cr_cmd(CPM_CR_ENET, CPM_CR_SET_GADDR) | CPM_CR_FLG;
+ /* this delay is necessary here -- Cort */
+ udelay(10);
+ while (cpmp->cp_cpcr & CPM_CR_FLG);
+ }
+ }
+ }
+}
+
+/* Initialize the CPM Ethernet on SCC. If EPPC-Bug loaded us, or performed
+ * some other network I/O, a whole bunch of this has already been set up.
+ * It is no big deal if we do it again, we just have to disable the
+ * transmit and receive to make sure we don't catch the CPM with some
+ * inconsistent control information.
+ */
+static int __init scc_enet_init(void)
+{
+ struct net_device *dev;
+ struct scc_enet_private *cep;
+ int i, j, k, err;
+ uint dp_offset;
+ unsigned char *eap, *ba;
+ dma_addr_t mem_addr;
+ bd_t *bd;
+ volatile cbd_t *bdp;
+ volatile cpm8xx_t *cp;
+ volatile scc_t *sccp;
+ volatile scc_enet_t *ep;
+ volatile immap_t *immap;
+
+ cp = cpmp; /* Get pointer to Communication Processor */
+
+ immap = (immap_t *)(mfspr(SPRN_IMMR) & 0xFFFF0000); /* and to internal registers */
+
+ bd = (bd_t *)__res;
+
+ dev = alloc_etherdev(sizeof(*cep));
+ if (!dev)
+ return -ENOMEM;
+
+ cep = dev->priv;
+ spin_lock_init(&cep->lock);
+
+ /* Get pointer to SCC area in parameter RAM.
+ */
+ ep = (scc_enet_t *)(&cp->cp_dparam[PROFF_ENET]);
+
+ /* And another to the SCC register area.
+ */
+ sccp = (volatile scc_t *)(&cp->cp_scc[SCC_ENET]);
+ cep->sccp = (scc_t *)sccp; /* Keep the pointer handy */
+
+ /* Disable receive and transmit in case EPPC-Bug started it.
+ */
+ sccp->scc_gsmrl &= ~(SCC_GSMRL_ENR | SCC_GSMRL_ENT);
+
+ /* Cookbook style from the MPC860 manual.....
+ * Not all of this is necessary if EPPC-Bug has initialized
+ * the network.
+ * So far we are lucky, all board configurations use the same
+ * pins, or at least the same I/O Port for these functions.....
+ * It can't last though......
+ */
+
+#if (defined(PA_ENET_RXD) && defined(PA_ENET_TXD))
+ /* Configure port A pins for Txd and Rxd.
+ */
+ immap->im_ioport.iop_papar |= (PA_ENET_RXD | PA_ENET_TXD);
+ immap->im_ioport.iop_padir &= ~(PA_ENET_RXD | PA_ENET_TXD);
+ immap->im_ioport.iop_paodr &= ~PA_ENET_TXD;
+#elif (defined(PB_ENET_RXD) && defined(PB_ENET_TXD))
+ /* Configure port B pins for Txd and Rxd.
+ */
+ immap->im_cpm.cp_pbpar |= (PB_ENET_RXD | PB_ENET_TXD);
+ immap->im_cpm.cp_pbdir &= ~(PB_ENET_RXD | PB_ENET_TXD);
+ immap->im_cpm.cp_pbodr &= ~PB_ENET_TXD;
+#else
+#error Exactly ONE pair of PA_ENET_[RT]XD, PB_ENET_[RT]XD must be defined
+#endif
+
+#if defined(PC_ENET_LBK)
+ /* Configure port C pins to disable External Loopback
+ */
+ immap->im_ioport.iop_pcpar &= ~PC_ENET_LBK;
+ immap->im_ioport.iop_pcdir |= PC_ENET_LBK;
+ immap->im_ioport.iop_pcso &= ~PC_ENET_LBK;
+ immap->im_ioport.iop_pcdat &= ~PC_ENET_LBK; /* Disable Loopback */
+#endif /* PC_ENET_LBK */
+
+ /* Configure port C pins to enable CLSN and RENA.
+ */
+ immap->im_ioport.iop_pcpar &= ~(PC_ENET_CLSN | PC_ENET_RENA);
+ immap->im_ioport.iop_pcdir &= ~(PC_ENET_CLSN | PC_ENET_RENA);
+ immap->im_ioport.iop_pcso |= (PC_ENET_CLSN | PC_ENET_RENA);
+
+ /* Configure port A for TCLK and RCLK.
+ */
+ immap->im_ioport.iop_papar |= (PA_ENET_TCLK | PA_ENET_RCLK);
+ immap->im_ioport.iop_padir &= ~(PA_ENET_TCLK | PA_ENET_RCLK);
+
+ /* Configure Serial Interface clock routing.
+ * First, clear all SCC bits to zero, then set the ones we want.
+ */
+ cp->cp_sicr &= ~SICR_ENET_MASK;
+ cp->cp_sicr |= SICR_ENET_CLKRT;
+
+ /* Manual says set SDDR, but I can't find anything with that
+ * name. I think it is a misprint, and should be SDCR. This
+ * has already been set by the communication processor initialization.
+ */
+
+ /* Allocate space for the buffer descriptors in the DP ram.
+ * These are relative offsets in the DP ram address space.
+ * Initialize base addresses for the buffer descriptors.
+ */
+ dp_offset = cpm_dpalloc(sizeof(cbd_t) * RX_RING_SIZE, 8);
+ ep->sen_genscc.scc_rbase = dp_offset;
+ cep->rx_bd_base = cpm_dpram_addr(dp_offset);
+
+ dp_offset = cpm_dpalloc(sizeof(cbd_t) * TX_RING_SIZE, 8);
+ ep->sen_genscc.scc_tbase = dp_offset;
+ cep->tx_bd_base = cpm_dpram_addr(dp_offset);
+
+ cep->dirty_tx = cep->cur_tx = cep->tx_bd_base;
+ cep->cur_rx = cep->rx_bd_base;
+
+ /* Issue init Rx BD command for SCC.
+ * Manual says to perform an Init Rx parameters here. We have
+ * to perform both Rx and Tx because the SCC may have been
+ * already running.
+ * In addition, we have to do it later because we don't yet have
+ * all of the BD control/status set properly.
+ cp->cp_cpcr = mk_cr_cmd(CPM_CR_ENET, CPM_CR_INIT_RX) | CPM_CR_FLG;
+ while (cp->cp_cpcr & CPM_CR_FLG);
+ */
+
+ /* Initialize function code registers for big-endian.
+ */
+ ep->sen_genscc.scc_rfcr = SCC_EB;
+ ep->sen_genscc.scc_tfcr = SCC_EB;
+
+ /* Set maximum bytes per receive buffer.
+ * This appears to be an Ethernet frame size, not the buffer
+ * fragment size. It must be a multiple of four.
+ */
+ ep->sen_genscc.scc_mrblr = PKT_MAXBLR_SIZE;
+
+ /* Set CRC preset and mask.
+ */
+ ep->sen_cpres = 0xffffffff;
+ ep->sen_cmask = 0xdebb20e3;
+
+ ep->sen_crcec = 0; /* CRC Error counter */
+ ep->sen_alec = 0; /* alignment error counter */
+ ep->sen_disfc = 0; /* discard frame counter */
+
+ ep->sen_pads = 0x8888; /* Tx short frame pad character */
+ ep->sen_retlim = 15; /* Retry limit threshold */
+
+ ep->sen_maxflr = PKT_MAXBUF_SIZE; /* maximum frame length register */
+ ep->sen_minflr = PKT_MINBUF_SIZE; /* minimum frame length register */
+
+ ep->sen_maxd1 = PKT_MAXBLR_SIZE; /* maximum DMA1 length */
+ ep->sen_maxd2 = PKT_MAXBLR_SIZE; /* maximum DMA2 length */
+
+ /* Clear hash tables.
+ */
+ ep->sen_gaddr1 = 0;
+ ep->sen_gaddr2 = 0;
+ ep->sen_gaddr3 = 0;
+ ep->sen_gaddr4 = 0;
+ ep->sen_iaddr1 = 0;
+ ep->sen_iaddr2 = 0;
+ ep->sen_iaddr3 = 0;
+ ep->sen_iaddr4 = 0;
+
+ /* Set Ethernet station address.
+ */
+ eap = (unsigned char *)&(ep->sen_paddrh);
+ for (i=5; i>=0; i--)
+ *eap++ = dev->dev_addr[i] = bd->bi_enetaddr[i];
+
+ ep->sen_pper = 0; /* 'cause the book says so */
+ ep->sen_taddrl = 0; /* temp address (LSB) */
+ ep->sen_taddrm = 0;
+ ep->sen_taddrh = 0; /* temp address (MSB) */
+
+ /* Now allocate the host memory pages and initialize the
+ * buffer descriptors.
+ */
+ bdp = cep->tx_bd_base;
+ for (i=0; i<TX_RING_SIZE; i++) {
+
+ /* Initialize the BD for every fragment in the page.
+ */
+ bdp->cbd_sc = 0;
+ bdp->cbd_bufaddr = 0;
+ bdp++;
+ }
+
+ /* Set the last buffer to wrap.
+ */
+ bdp--;
+ bdp->cbd_sc |= BD_SC_WRAP;
+
+ bdp = cep->rx_bd_base;
+ k = 0;
+ for (i=0; i<CPM_ENET_RX_PAGES; i++) {
+
+ /* Allocate a page.
+ */
+ ba = (unsigned char *)dma_alloc_coherent(NULL, PAGE_SIZE,
+ &mem_addr, GFP_KERNEL);
+ /* BUG: no check for failure */
+
+ /* Initialize the BD for every fragment in the page.
+ */
+ for (j=0; j<CPM_ENET_RX_FRPPG; j++) {
+ bdp->cbd_sc = BD_ENET_RX_EMPTY | BD_ENET_RX_INTR;
+ bdp->cbd_bufaddr = mem_addr;
+ cep->rx_vaddr[k++] = ba;
+ mem_addr += CPM_ENET_RX_FRSIZE;
+ ba += CPM_ENET_RX_FRSIZE;
+ bdp++;
+ }
+ }
+
+ /* Set the last buffer to wrap.
+ */
+ bdp--;
+ bdp->cbd_sc |= BD_SC_WRAP;
+
+ /* Let's re-initialize the channel now. We have to do it later
+ * than the manual describes because we have just now finished
+ * the BD initialization.
+ */
+ cp->cp_cpcr = mk_cr_cmd(CPM_CR_ENET, CPM_CR_INIT_TRX) | CPM_CR_FLG;
+ while (cp->cp_cpcr & CPM_CR_FLG);
+
+ cep->skb_cur = cep->skb_dirty = 0;
+
+ sccp->scc_scce = 0xffff; /* Clear any pending events */
+
+ /* Enable interrupts for transmit error, complete frame
+ * received, and any transmit buffer we have also set the
+ * interrupt flag.
+ */
+ sccp->scc_sccm = (SCCE_ENET_TXE | SCCE_ENET_RXF | SCCE_ENET_TXB);
+
+ /* Install our interrupt handler.
+ */
+ cpm_install_handler(CPMVEC_ENET, scc_enet_interrupt, dev);
+
+ /* Set GSMR_H to enable all normal operating modes.
+ * Set GSMR_L to enable Ethernet to MC68160.
+ */
+ sccp->scc_gsmrh = 0;
+ sccp->scc_gsmrl = (SCC_GSMRL_TCI | SCC_GSMRL_TPL_48 | SCC_GSMRL_TPP_10 | SCC_GSMRL_MODE_ENET);
+
+ /* Set sync/delimiters.
+ */
+ sccp->scc_dsr = 0xd555;
+
+ /* Set processing mode. Use Ethernet CRC, catch broadcast, and
+ * start frame search 22 bit times after RENA.
+ */
+ sccp->scc_psmr = (SCC_PSMR_ENCRC | SCC_PSMR_NIB22);
+
+ /* It is now OK to enable the Ethernet transmitter.
+ * Unfortunately, there are board implementation differences here.
+ */
+#if (!defined (PB_ENET_TENA) && defined (PC_ENET_TENA))
+ immap->im_ioport.iop_pcpar |= PC_ENET_TENA;
+ immap->im_ioport.iop_pcdir &= ~PC_ENET_TENA;
+#elif ( defined (PB_ENET_TENA) && !defined (PC_ENET_TENA))
+ cp->cp_pbpar |= PB_ENET_TENA;
+ cp->cp_pbdir |= PB_ENET_TENA;
+#else
+#error Configuration Error: define exactly ONE of PB_ENET_TENA, PC_ENET_TENA
+#endif
+
+#if defined(CONFIG_RPXLITE) || defined(CONFIG_RPXCLASSIC)
+ /* And while we are here, set the configuration to enable ethernet.
+ */
+ *((volatile uint *)RPX_CSR_ADDR) &= ~BCSR0_ETHLPBK;
+ *((volatile uint *)RPX_CSR_ADDR) |=
+ (BCSR0_ETHEN | BCSR0_COLTESTDIS | BCSR0_FULLDPLXDIS);
+#endif
+
+#ifdef CONFIG_BSEIP
+ /* BSE uses port B and C for PHY control.
+ */
+ cp->cp_pbpar &= ~(PB_BSE_POWERUP | PB_BSE_FDXDIS);
+ cp->cp_pbdir |= (PB_BSE_POWERUP | PB_BSE_FDXDIS);
+ cp->cp_pbdat |= (PB_BSE_POWERUP | PB_BSE_FDXDIS);
+
+ immap->im_ioport.iop_pcpar &= ~PC_BSE_LOOPBACK;
+ immap->im_ioport.iop_pcdir |= PC_BSE_LOOPBACK;
+ immap->im_ioport.iop_pcso &= ~PC_BSE_LOOPBACK;
+ immap->im_ioport.iop_pcdat &= ~PC_BSE_LOOPBACK;
+#endif
+
+#ifdef CONFIG_FADS
+ cp->cp_pbpar |= PB_ENET_TENA;
+ cp->cp_pbdir |= PB_ENET_TENA;
+
+ /* Enable the EEST PHY.
+ */
+ *((volatile uint *)BCSR1) &= ~BCSR1_ETHEN;
+#endif
+
+ dev->base_addr = (unsigned long)ep;
+#if 0
+ dev->name = "CPM_ENET";
+#endif
+
+ /* The CPM Ethernet specific entries in the device structure. */
+ dev->open = scc_enet_open;
+ dev->hard_start_xmit = scc_enet_start_xmit;
+ dev->tx_timeout = scc_enet_timeout;
+ dev->watchdog_timeo = TX_TIMEOUT;
+ dev->stop = scc_enet_close;
+ dev->get_stats = scc_enet_get_stats;
+ dev->set_multicast_list = set_multicast_list;
+
+ err = register_netdev(dev);
+ if (err) {
+ free_netdev(dev);
+ return err;
+ }
+
+ /* And last, enable the transmit and receive processing.
+ */
+ sccp->scc_gsmrl |= (SCC_GSMRL_ENR | SCC_GSMRL_ENT);
+
+ printk("%s: CPM ENET Version 0.2 on SCC%d, ", dev->name, SCC_ENET+1);
+ for (i=0; i<5; i++)
+ printk("%02x:", dev->dev_addr[i]);
+ printk("%02x\n", dev->dev_addr[5]);
+
+ return 0;
+}
+
+module_init(scc_enet_init);
diff --git a/arch/ppc/8xx_io/fec.c b/arch/ppc/8xx_io/fec.c
new file mode 100644
index 0000000..0730392
--- /dev/null
+++ b/arch/ppc/8xx_io/fec.c
@@ -0,0 +1,1973 @@
+/*
+ * Fast Ethernet Controller (FEC) driver for Motorola MPC8xx.
+ * Copyright (c) 1997 Dan Malek (dmalek@jlc.net)
+ *
+ * This version of the driver is specific to the FADS implementation,
+ * since the board contains control registers external to the processor
+ * for the control of the LevelOne LXT970 transceiver. The MPC860T manual
+ * describes connections using the internal parallel port I/O, which
+ * is basically all of Port D.
+ *
+ * Includes support for the following PHYs: QS6612, LXT970, LXT971/2.
+ *
+ * Right now, I am very wasteful with the buffers. I allocate memory
+ * pages and then divide them into 2K frame buffers. This way I know I
+ * have buffers large enough to hold one frame within one buffer descriptor.
+ * Once I get this working, I will use 64 or 128 byte CPM buffers, which
+ * will be much more memory efficient and will easily handle lots of
+ * small packets.
+ *
+ * Much better multiple PHY support by Magnus Damm.
+ * Copyright (c) 2000 Ericsson Radio Systems AB.
+ *
+ * Make use of MII for PHY control configurable.
+ * Some fixes.
+ * Copyright (c) 2000-2002 Wolfgang Denk, DENX Software Engineering.
+ *
+ * Support for AMD AM79C874 added.
+ * Thomas Lange, thomas@corelatus.com
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/string.h>
+#include <linux/ptrace.h>
+#include <linux/errno.h>
+#include <linux/ioport.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/spinlock.h>
+#include <linux/bitops.h>
+#ifdef CONFIG_FEC_PACKETHOOK
+#include <linux/pkthook.h>
+#endif
+
+#include <asm/8xx_immap.h>
+#include <asm/pgtable.h>
+#include <asm/mpc8xx.h>
+#include <asm/irq.h>
+#include <asm/uaccess.h>
+#include <asm/commproc.h>
+
+#ifdef CONFIG_USE_MDIO
+/* Forward declarations of some structures to support different PHYs
+*/
+
+typedef struct {
+ uint mii_data;
+ void (*funct)(uint mii_reg, struct net_device *dev);
+} phy_cmd_t;
+
+typedef struct {
+ uint id;
+ char *name;
+
+ const phy_cmd_t *config;
+ const phy_cmd_t *startup;
+ const phy_cmd_t *ack_int;
+ const phy_cmd_t *shutdown;
+} phy_info_t;
+#endif /* CONFIG_USE_MDIO */
+
+/* The number of Tx and Rx buffers. These are allocated from the page
+ * pool. The code may assume these are power of two, so it is best
+ * to keep them that size.
+ * We don't need to allocate pages for the transmitter. We just use
+ * the skbuffer directly.
+ */
+#ifdef CONFIG_ENET_BIG_BUFFERS
+#define FEC_ENET_RX_PAGES 16
+#define FEC_ENET_RX_FRSIZE 2048
+#define FEC_ENET_RX_FRPPG (PAGE_SIZE / FEC_ENET_RX_FRSIZE)
+#define RX_RING_SIZE (FEC_ENET_RX_FRPPG * FEC_ENET_RX_PAGES)
+#define TX_RING_SIZE 16 /* Must be power of two */
+#define TX_RING_MOD_MASK 15 /* for this to work */
+#else
+#define FEC_ENET_RX_PAGES 4
+#define FEC_ENET_RX_FRSIZE 2048
+#define FEC_ENET_RX_FRPPG (PAGE_SIZE / FEC_ENET_RX_FRSIZE)
+#define RX_RING_SIZE (FEC_ENET_RX_FRPPG * FEC_ENET_RX_PAGES)
+#define TX_RING_SIZE 8 /* Must be power of two */
+#define TX_RING_MOD_MASK 7 /* for this to work */
+#endif
+
+/* Interrupt events/masks.
+*/
+#define FEC_ENET_HBERR ((uint)0x80000000) /* Heartbeat error */
+#define FEC_ENET_BABR ((uint)0x40000000) /* Babbling receiver */
+#define FEC_ENET_BABT ((uint)0x20000000) /* Babbling transmitter */
+#define FEC_ENET_GRA ((uint)0x10000000) /* Graceful stop complete */
+#define FEC_ENET_TXF ((uint)0x08000000) /* Full frame transmitted */
+#define FEC_ENET_TXB ((uint)0x04000000) /* A buffer was transmitted */
+#define FEC_ENET_RXF ((uint)0x02000000) /* Full frame received */
+#define FEC_ENET_RXB ((uint)0x01000000) /* A buffer was received */
+#define FEC_ENET_MII ((uint)0x00800000) /* MII interrupt */
+#define FEC_ENET_EBERR ((uint)0x00400000) /* SDMA bus error */
+
+/*
+*/
+#define FEC_ECNTRL_PINMUX 0x00000004
+#define FEC_ECNTRL_ETHER_EN 0x00000002
+#define FEC_ECNTRL_RESET 0x00000001
+
+#define FEC_RCNTRL_BC_REJ 0x00000010
+#define FEC_RCNTRL_PROM 0x00000008
+#define FEC_RCNTRL_MII_MODE 0x00000004
+#define FEC_RCNTRL_DRT 0x00000002
+#define FEC_RCNTRL_LOOP 0x00000001
+
+#define FEC_TCNTRL_FDEN 0x00000004
+#define FEC_TCNTRL_HBC 0x00000002
+#define FEC_TCNTRL_GTS 0x00000001
+
+/* Delay to wait for FEC reset command to complete (in us)
+*/
+#define FEC_RESET_DELAY 50
+
+/* The FEC stores dest/src/type, data, and checksum for receive packets.
+ */
+#define PKT_MAXBUF_SIZE 1518
+#define PKT_MINBUF_SIZE 64
+#define PKT_MAXBLR_SIZE 1520
+
+/* The FEC buffer descriptors track the ring buffers. The rx_bd_base and
+ * tx_bd_base always point to the base of the buffer descriptors. The
+ * cur_rx and cur_tx point to the currently available buffer.
+ * The dirty_tx tracks the current buffer that is being sent by the
+ * controller. The cur_tx and dirty_tx are equal under both completely
+ * empty and completely full conditions. The empty/ready indicator in
+ * the buffer descriptor determines the actual condition.
+ */
+struct fec_enet_private {
+ /* The saved address of a sent-in-place packet/buffer, for skfree(). */
+ struct sk_buff* tx_skbuff[TX_RING_SIZE];
+ ushort skb_cur;
+ ushort skb_dirty;
+
+ /* CPM dual port RAM relative addresses.
+ */
+ cbd_t *rx_bd_base; /* Address of Rx and Tx buffers. */
+ cbd_t *tx_bd_base;
+ cbd_t *cur_rx, *cur_tx; /* The next free ring entry */
+ cbd_t *dirty_tx; /* The ring entries to be free()ed. */
+
+ /* Virtual addresses for the receive buffers because we can't
+ * do a __va() on them anymore.
+ */
+ unsigned char *rx_vaddr[RX_RING_SIZE];
+
+ struct net_device_stats stats;
+ uint tx_full;
+ spinlock_t lock;
+
+#ifdef CONFIG_USE_MDIO
+ uint phy_id;
+ uint phy_id_done;
+ uint phy_status;
+ uint phy_speed;
+ phy_info_t *phy;
+ struct tq_struct phy_task;
+
+ uint sequence_done;
+
+ uint phy_addr;
+#endif /* CONFIG_USE_MDIO */
+
+ int link;
+ int old_link;
+ int full_duplex;
+
+#ifdef CONFIG_FEC_PACKETHOOK
+ unsigned long ph_lock;
+ fec_ph_func *ph_rxhandler;
+ fec_ph_func *ph_txhandler;
+ __u16 ph_proto;
+ volatile __u32 *ph_regaddr;
+ void *ph_priv;
+#endif
+};
+
+static int fec_enet_open(struct net_device *dev);
+static int fec_enet_start_xmit(struct sk_buff *skb, struct net_device *dev);
+#ifdef CONFIG_USE_MDIO
+static void fec_enet_mii(struct net_device *dev);
+#endif /* CONFIG_USE_MDIO */
+static void fec_enet_interrupt(int irq, void * dev_id, struct pt_regs * regs);
+#ifdef CONFIG_FEC_PACKETHOOK
+static void fec_enet_tx(struct net_device *dev, __u32 regval);
+static void fec_enet_rx(struct net_device *dev, __u32 regval);
+#else
+static void fec_enet_tx(struct net_device *dev);
+static void fec_enet_rx(struct net_device *dev);
+#endif
+static int fec_enet_close(struct net_device *dev);
+static struct net_device_stats *fec_enet_get_stats(struct net_device *dev);
+static void set_multicast_list(struct net_device *dev);
+static void fec_restart(struct net_device *dev, int duplex);
+static void fec_stop(struct net_device *dev);
+static ushort my_enet_addr[3];
+
+#ifdef CONFIG_USE_MDIO
+/* MII processing. We keep this as simple as possible. Requests are
+ * placed on the list (if there is room). When the request is finished
+ * by the MII, an optional function may be called.
+ */
+typedef struct mii_list {
+ uint mii_regval;
+ void (*mii_func)(uint val, struct net_device *dev);
+ struct mii_list *mii_next;
+} mii_list_t;
+
+#define NMII 20
+mii_list_t mii_cmds[NMII];
+mii_list_t *mii_free;
+mii_list_t *mii_head;
+mii_list_t *mii_tail;
+
+static int mii_queue(struct net_device *dev, int request,
+ void (*func)(uint, struct net_device *));
+
+/* Make MII read/write commands for the FEC.
+*/
+#define mk_mii_read(REG) (0x60020000 | ((REG & 0x1f) << 18))
+#define mk_mii_write(REG, VAL) (0x50020000 | ((REG & 0x1f) << 18) | \
+ (VAL & 0xffff))
+#define mk_mii_end 0
+#endif /* CONFIG_USE_MDIO */
+
+/* Transmitter timeout.
+*/
+#define TX_TIMEOUT (2*HZ)
+
+#ifdef CONFIG_USE_MDIO
+/* Register definitions for the PHY.
+*/
+
+#define MII_REG_CR 0 /* Control Register */
+#define MII_REG_SR 1 /* Status Register */
+#define MII_REG_PHYIR1 2 /* PHY Identification Register 1 */
+#define MII_REG_PHYIR2 3 /* PHY Identification Register 2 */
+#define MII_REG_ANAR 4 /* A-N Advertisement Register */
+#define MII_REG_ANLPAR 5 /* A-N Link Partner Ability Register */
+#define MII_REG_ANER 6 /* A-N Expansion Register */
+#define MII_REG_ANNPTR 7 /* A-N Next Page Transmit Register */
+#define MII_REG_ANLPRNPR 8 /* A-N Link Partner Received Next Page Reg. */
+
+/* values for phy_status */
+
+#define PHY_CONF_ANE 0x0001 /* 1 auto-negotiation enabled */
+#define PHY_CONF_LOOP 0x0002 /* 1 loopback mode enabled */
+#define PHY_CONF_SPMASK 0x00f0 /* mask for speed */
+#define PHY_CONF_10HDX 0x0010 /* 10 Mbit half duplex supported */
+#define PHY_CONF_10FDX 0x0020 /* 10 Mbit full duplex supported */
+#define PHY_CONF_100HDX 0x0040 /* 100 Mbit half duplex supported */
+#define PHY_CONF_100FDX 0x0080 /* 100 Mbit full duplex supported */
+
+#define PHY_STAT_LINK 0x0100 /* 1 up - 0 down */
+#define PHY_STAT_FAULT 0x0200 /* 1 remote fault */
+#define PHY_STAT_ANC 0x0400 /* 1 auto-negotiation complete */
+#define PHY_STAT_SPMASK 0xf000 /* mask for speed */
+#define PHY_STAT_10HDX 0x1000 /* 10 Mbit half duplex selected */
+#define PHY_STAT_10FDX 0x2000 /* 10 Mbit full duplex selected */
+#define PHY_STAT_100HDX 0x4000 /* 100 Mbit half duplex selected */
+#define PHY_STAT_100FDX 0x8000 /* 100 Mbit full duplex selected */
+#endif /* CONFIG_USE_MDIO */
+
+#ifdef CONFIG_FEC_PACKETHOOK
+int
+fec_register_ph(struct net_device *dev, fec_ph_func *rxfun, fec_ph_func *txfun,
+ __u16 proto, volatile __u32 *regaddr, void *priv)
+{
+ struct fec_enet_private *fep;
+ int retval = 0;
+
+ fep = dev->priv;
+
+ if (test_and_set_bit(0, (void*)&fep->ph_lock) != 0) {
+ /* Someone is messing with the packet hook */
+ return -EAGAIN;
+ }
+ if (fep->ph_rxhandler != NULL || fep->ph_txhandler != NULL) {
+ retval = -EBUSY;
+ goto out;
+ }
+ fep->ph_rxhandler = rxfun;
+ fep->ph_txhandler = txfun;
+ fep->ph_proto = proto;
+ fep->ph_regaddr = regaddr;
+ fep->ph_priv = priv;
+
+ out:
+ fep->ph_lock = 0;
+
+ return retval;
+}
+
+
+int
+fec_unregister_ph(struct net_device *dev)
+{
+ struct fec_enet_private *fep;
+ int retval = 0;
+
+ fep = dev->priv;
+
+ if (test_and_set_bit(0, (void*)&fep->ph_lock) != 0) {
+ /* Someone is messing with the packet hook */
+ return -EAGAIN;
+ }
+
+ fep->ph_rxhandler = fep->ph_txhandler = NULL;
+ fep->ph_proto = 0;
+ fep->ph_regaddr = NULL;
+ fep->ph_priv = NULL;
+
+ fep->ph_lock = 0;
+
+ return retval;
+}
+
+EXPORT_SYMBOL(fec_register_ph);
+EXPORT_SYMBOL(fec_unregister_ph);
+
+#endif /* CONFIG_FEC_PACKETHOOK */
+
+static int
+fec_enet_start_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+ struct fec_enet_private *fep;
+ volatile fec_t *fecp;
+ volatile cbd_t *bdp;
+
+ fep = dev->priv;
+ fecp = (volatile fec_t*)dev->base_addr;
+
+ if (!fep->link) {
+ /* Link is down or autonegotiation is in progress. */
+ return 1;
+ }
+
+ /* Fill in a Tx ring entry */
+ bdp = fep->cur_tx;
+
+#ifndef final_version
+ if (bdp->cbd_sc & BD_ENET_TX_READY) {
+ /* Ooops. All transmit buffers are full. Bail out.
+ * This should not happen, since dev->tbusy should be set.
+ */
+ printk("%s: tx queue full!.\n", dev->name);
+ return 1;
+ }
+#endif
+
+ /* Clear all of the status flags.
+ */
+ bdp->cbd_sc &= ~BD_ENET_TX_STATS;
+
+ /* Set buffer length and buffer pointer.
+ */
+ bdp->cbd_bufaddr = __pa(skb->data);
+ bdp->cbd_datlen = skb->len;
+
+ /* Save skb pointer.
+ */
+ fep->tx_skbuff[fep->skb_cur] = skb;
+
+ fep->stats.tx_bytes += skb->len;
+ fep->skb_cur = (fep->skb_cur+1) & TX_RING_MOD_MASK;
+
+ /* Push the data cache so the CPM does not get stale memory
+ * data.
+ */
+ flush_dcache_range((unsigned long)skb->data,
+ (unsigned long)skb->data + skb->len);
+
+ /* disable interrupts while triggering transmit */
+ spin_lock_irq(&fep->lock);
+
+ /* Send it on its way. Tell FEC its ready, interrupt when done,
+ * its the last BD of the frame, and to put the CRC on the end.
+ */
+
+ bdp->cbd_sc |= (BD_ENET_TX_READY | BD_ENET_TX_INTR
+ | BD_ENET_TX_LAST | BD_ENET_TX_TC);
+
+ dev->trans_start = jiffies;
+
+ /* Trigger transmission start */
+ fecp->fec_x_des_active = 0x01000000;
+
+ /* If this was the last BD in the ring, start at the beginning again.
+ */
+ if (bdp->cbd_sc & BD_ENET_TX_WRAP) {
+ bdp = fep->tx_bd_base;
+ } else {
+ bdp++;
+ }
+
+ if (bdp->cbd_sc & BD_ENET_TX_READY) {
+ netif_stop_queue(dev);
+ fep->tx_full = 1;
+ }
+
+ fep->cur_tx = (cbd_t *)bdp;
+
+ spin_unlock_irq(&fep->lock);
+
+ return 0;
+}
+
+static void
+fec_timeout(struct net_device *dev)
+{
+ struct fec_enet_private *fep = dev->priv;
+
+ printk("%s: transmit timed out.\n", dev->name);
+ fep->stats.tx_errors++;
+#ifndef final_version
+ {
+ int i;
+ cbd_t *bdp;
+
+ printk("Ring data dump: cur_tx %lx%s, dirty_tx %lx cur_rx: %lx\n",
+ (unsigned long)fep->cur_tx, fep->tx_full ? " (full)" : "",
+ (unsigned long)fep->dirty_tx,
+ (unsigned long)fep->cur_rx);
+
+ bdp = fep->tx_bd_base;
+ printk(" tx: %u buffers\n", TX_RING_SIZE);
+ for (i = 0 ; i < TX_RING_SIZE; i++) {
+ printk(" %08x: %04x %04x %08x\n",
+ (uint) bdp,
+ bdp->cbd_sc,
+ bdp->cbd_datlen,
+ bdp->cbd_bufaddr);
+ bdp++;
+ }
+
+ bdp = fep->rx_bd_base;
+ printk(" rx: %lu buffers\n", RX_RING_SIZE);
+ for (i = 0 ; i < RX_RING_SIZE; i++) {
+ printk(" %08x: %04x %04x %08x\n",
+ (uint) bdp,
+ bdp->cbd_sc,
+ bdp->cbd_datlen,
+ bdp->cbd_bufaddr);
+ bdp++;
+ }
+ }
+#endif
+ if (!fep->tx_full)
+ netif_wake_queue(dev);
+}
+
+/* The interrupt handler.
+ * This is called from the MPC core interrupt.
+ */
+static void
+fec_enet_interrupt(int irq, void * dev_id, struct pt_regs * regs)
+{
+ struct net_device *dev = dev_id;
+ volatile fec_t *fecp;
+ uint int_events;
+#ifdef CONFIG_FEC_PACKETHOOK
+ struct fec_enet_private *fep = dev->priv;
+ __u32 regval;
+
+ if (fep->ph_regaddr) regval = *fep->ph_regaddr;
+#endif
+ fecp = (volatile fec_t*)dev->base_addr;
+
+ /* Get the interrupt events that caused us to be here.
+ */
+ while ((int_events = fecp->fec_ievent) != 0) {
+ fecp->fec_ievent = int_events;
+ if ((int_events & (FEC_ENET_HBERR | FEC_ENET_BABR |
+ FEC_ENET_BABT | FEC_ENET_EBERR)) != 0) {
+ printk("FEC ERROR %x\n", int_events);
+ }
+
+ /* Handle receive event in its own function.
+ */
+ if (int_events & FEC_ENET_RXF) {
+#ifdef CONFIG_FEC_PACKETHOOK
+ fec_enet_rx(dev, regval);
+#else
+ fec_enet_rx(dev);
+#endif
+ }
+
+ /* Transmit OK, or non-fatal error. Update the buffer
+ descriptors. FEC handles all errors, we just discover
+ them as part of the transmit process.
+ */
+ if (int_events & FEC_ENET_TXF) {
+#ifdef CONFIG_FEC_PACKETHOOK
+ fec_enet_tx(dev, regval);
+#else
+ fec_enet_tx(dev);
+#endif
+ }
+
+ if (int_events & FEC_ENET_MII) {
+#ifdef CONFIG_USE_MDIO
+ fec_enet_mii(dev);
+#else
+printk("%s[%d] %s: unexpected FEC_ENET_MII event\n", __FILE__,__LINE__,__FUNCTION__);
+#endif /* CONFIG_USE_MDIO */
+ }
+
+ }
+}
+
+
+static void
+#ifdef CONFIG_FEC_PACKETHOOK
+fec_enet_tx(struct net_device *dev, __u32 regval)
+#else
+fec_enet_tx(struct net_device *dev)
+#endif
+{
+ struct fec_enet_private *fep;
+ volatile cbd_t *bdp;
+ struct sk_buff *skb;
+
+ fep = dev->priv;
+ /* lock while transmitting */
+ spin_lock(&fep->lock);
+ bdp = fep->dirty_tx;
+
+ while ((bdp->cbd_sc&BD_ENET_TX_READY) == 0) {
+ if (bdp == fep->cur_tx && fep->tx_full == 0) break;
+
+ skb = fep->tx_skbuff[fep->skb_dirty];
+ /* Check for errors. */
+ if (bdp->cbd_sc & (BD_ENET_TX_HB | BD_ENET_TX_LC |
+ BD_ENET_TX_RL | BD_ENET_TX_UN |
+ BD_ENET_TX_CSL)) {
+ fep->stats.tx_errors++;
+ if (bdp->cbd_sc & BD_ENET_TX_HB) /* No heartbeat */
+ fep->stats.tx_heartbeat_errors++;
+ if (bdp->cbd_sc & BD_ENET_TX_LC) /* Late collision */
+ fep->stats.tx_window_errors++;
+ if (bdp->cbd_sc & BD_ENET_TX_RL) /* Retrans limit */
+ fep->stats.tx_aborted_errors++;
+ if (bdp->cbd_sc & BD_ENET_TX_UN) /* Underrun */
+ fep->stats.tx_fifo_errors++;
+ if (bdp->cbd_sc & BD_ENET_TX_CSL) /* Carrier lost */
+ fep->stats.tx_carrier_errors++;
+ } else {
+#ifdef CONFIG_FEC_PACKETHOOK
+ /* Packet hook ... */
+ if (fep->ph_txhandler &&
+ ((struct ethhdr *)skb->data)->h_proto
+ == fep->ph_proto) {
+ fep->ph_txhandler((__u8*)skb->data, skb->len,
+ regval, fep->ph_priv);
+ }
+#endif
+ fep->stats.tx_packets++;
+ }
+
+#ifndef final_version
+ if (bdp->cbd_sc & BD_ENET_TX_READY)
+ printk("HEY! Enet xmit interrupt and TX_READY.\n");
+#endif
+ /* Deferred means some collisions occurred during transmit,
+ * but we eventually sent the packet OK.
+ */
+ if (bdp->cbd_sc & BD_ENET_TX_DEF)
+ fep->stats.collisions++;
+
+ /* Free the sk buffer associated with this last transmit.
+ */
+#if 0
+printk("TXI: %x %x %x\n", bdp, skb, fep->skb_dirty);
+#endif
+ dev_kfree_skb_irq (skb/*, FREE_WRITE*/);
+ fep->tx_skbuff[fep->skb_dirty] = NULL;
+ fep->skb_dirty = (fep->skb_dirty + 1) & TX_RING_MOD_MASK;
+
+ /* Update pointer to next buffer descriptor to be transmitted.
+ */
+ if (bdp->cbd_sc & BD_ENET_TX_WRAP)
+ bdp = fep->tx_bd_base;
+ else
+ bdp++;
+
+ /* Since we have freed up a buffer, the ring is no longer
+ * full.
+ */
+ if (fep->tx_full) {
+ fep->tx_full = 0;
+ if (netif_queue_stopped(dev))
+ netif_wake_queue(dev);
+ }
+#ifdef CONFIG_FEC_PACKETHOOK
+ /* Re-read register. Not exactly guaranteed to be correct,
+ but... */
+ if (fep->ph_regaddr) regval = *fep->ph_regaddr;
+#endif
+ }
+ fep->dirty_tx = (cbd_t *)bdp;
+ spin_unlock(&fep->lock);
+}
+
+
+/* During a receive, the cur_rx points to the current incoming buffer.
+ * When we update through the ring, if the next incoming buffer has
+ * not been given to the system, we just set the empty indicator,
+ * effectively tossing the packet.
+ */
+static void
+#ifdef CONFIG_FEC_PACKETHOOK
+fec_enet_rx(struct net_device *dev, __u32 regval)
+#else
+fec_enet_rx(struct net_device *dev)
+#endif
+{
+ struct fec_enet_private *fep;
+ volatile fec_t *fecp;
+ volatile cbd_t *bdp;
+ struct sk_buff *skb;
+ ushort pkt_len;
+ __u8 *data;
+
+ fep = dev->priv;
+ fecp = (volatile fec_t*)dev->base_addr;
+
+ /* First, grab all of the stats for the incoming packet.
+ * These get messed up if we get called due to a busy condition.
+ */
+ bdp = fep->cur_rx;
+
+while (!(bdp->cbd_sc & BD_ENET_RX_EMPTY)) {
+
+#ifndef final_version
+ /* Since we have allocated space to hold a complete frame,
+ * the last indicator should be set.
+ */
+ if ((bdp->cbd_sc & BD_ENET_RX_LAST) == 0)
+ printk("FEC ENET: rcv is not +last\n");
+#endif
+
+ /* Check for errors. */
+ if (bdp->cbd_sc & (BD_ENET_RX_LG | BD_ENET_RX_SH | BD_ENET_RX_NO |
+ BD_ENET_RX_CR | BD_ENET_RX_OV)) {
+ fep->stats.rx_errors++;
+ if (bdp->cbd_sc & (BD_ENET_RX_LG | BD_ENET_RX_SH)) {
+ /* Frame too long or too short. */
+ fep->stats.rx_length_errors++;
+ }
+ if (bdp->cbd_sc & BD_ENET_RX_NO) /* Frame alignment */
+ fep->stats.rx_frame_errors++;
+ if (bdp->cbd_sc & BD_ENET_RX_CR) /* CRC Error */
+ fep->stats.rx_crc_errors++;
+ if (bdp->cbd_sc & BD_ENET_RX_OV) /* FIFO overrun */
+ fep->stats.rx_crc_errors++;
+ }
+
+ /* Report late collisions as a frame error.
+ * On this error, the BD is closed, but we don't know what we
+ * have in the buffer. So, just drop this frame on the floor.
+ */
+ if (bdp->cbd_sc & BD_ENET_RX_CL) {
+ fep->stats.rx_errors++;
+ fep->stats.rx_frame_errors++;
+ goto rx_processing_done;
+ }
+
+ /* Process the incoming frame.
+ */
+ fep->stats.rx_packets++;
+ pkt_len = bdp->cbd_datlen;
+ fep->stats.rx_bytes += pkt_len;
+ data = fep->rx_vaddr[bdp - fep->rx_bd_base];
+
+#ifdef CONFIG_FEC_PACKETHOOK
+ /* Packet hook ... */
+ if (fep->ph_rxhandler) {
+ if (((struct ethhdr *)data)->h_proto == fep->ph_proto) {
+ switch (fep->ph_rxhandler(data, pkt_len, regval,
+ fep->ph_priv)) {
+ case 1:
+ goto rx_processing_done;
+ break;
+ case 0:
+ break;
+ default:
+ fep->stats.rx_errors++;
+ goto rx_processing_done;
+ }
+ }
+ }
+
+ /* If it wasn't filtered - copy it to an sk buffer. */
+#endif
+
+ /* This does 16 byte alignment, exactly what we need.
+ * The packet length includes FCS, but we don't want to
+ * include that when passing upstream as it messes up
+ * bridging applications.
+ */
+ skb = dev_alloc_skb(pkt_len-4);
+
+ if (skb == NULL) {
+ printk("%s: Memory squeeze, dropping packet.\n", dev->name);
+ fep->stats.rx_dropped++;
+ } else {
+ skb->dev = dev;
+ skb_put(skb,pkt_len-4); /* Make room */
+ eth_copy_and_sum(skb, data, pkt_len-4, 0);
+ skb->protocol=eth_type_trans(skb,dev);
+ netif_rx(skb);
+ }
+ rx_processing_done:
+
+ /* Clear the status flags for this buffer.
+ */
+ bdp->cbd_sc &= ~BD_ENET_RX_STATS;
+
+ /* Mark the buffer empty.
+ */
+ bdp->cbd_sc |= BD_ENET_RX_EMPTY;
+
+ /* Update BD pointer to next entry.
+ */
+ if (bdp->cbd_sc & BD_ENET_RX_WRAP)
+ bdp = fep->rx_bd_base;
+ else
+ bdp++;
+
+#if 1
+ /* Doing this here will keep the FEC running while we process
+ * incoming frames. On a heavily loaded network, we should be
+ * able to keep up at the expense of system resources.
+ */
+ fecp->fec_r_des_active = 0x01000000;
+#endif
+#ifdef CONFIG_FEC_PACKETHOOK
+ /* Re-read register. Not exactly guaranteed to be correct,
+ but... */
+ if (fep->ph_regaddr) regval = *fep->ph_regaddr;
+#endif
+ } /* while (!(bdp->cbd_sc & BD_ENET_RX_EMPTY)) */
+ fep->cur_rx = (cbd_t *)bdp;
+
+#if 0
+ /* Doing this here will allow us to process all frames in the
+ * ring before the FEC is allowed to put more there. On a heavily
+ * loaded network, some frames may be lost. Unfortunately, this
+ * increases the interrupt overhead since we can potentially work
+ * our way back to the interrupt return only to come right back
+ * here.
+ */
+ fecp->fec_r_des_active = 0x01000000;
+#endif
+}
+
+
+#ifdef CONFIG_USE_MDIO
+static void
+fec_enet_mii(struct net_device *dev)
+{
+ struct fec_enet_private *fep;
+ volatile fec_t *ep;
+ mii_list_t *mip;
+ uint mii_reg;
+
+ fep = (struct fec_enet_private *)dev->priv;
+ ep = &(((immap_t *)IMAP_ADDR)->im_cpm.cp_fec);
+ mii_reg = ep->fec_mii_data;
+
+ if ((mip = mii_head) == NULL) {
+ printk("MII and no head!\n");
+ return;
+ }
+
+ if (mip->mii_func != NULL)
+ (*(mip->mii_func))(mii_reg, dev);
+
+ mii_head = mip->mii_next;
+ mip->mii_next = mii_free;
+ mii_free = mip;
+
+ if ((mip = mii_head) != NULL) {
+ ep->fec_mii_data = mip->mii_regval;
+
+ }
+}
+
+static int
+mii_queue(struct net_device *dev, int regval, void (*func)(uint, struct net_device *))
+{
+ struct fec_enet_private *fep;
+ unsigned long flags;
+ mii_list_t *mip;
+ int retval;
+
+ /* Add PHY address to register command.
+ */
+ fep = dev->priv;
+ regval |= fep->phy_addr << 23;
+
+ retval = 0;
+
+ /* lock while modifying mii_list */
+ spin_lock_irqsave(&fep->lock, flags);
+
+ if ((mip = mii_free) != NULL) {
+ mii_free = mip->mii_next;
+ mip->mii_regval = regval;
+ mip->mii_func = func;
+ mip->mii_next = NULL;
+ if (mii_head) {
+ mii_tail->mii_next = mip;
+ mii_tail = mip;
+ } else {
+ mii_head = mii_tail = mip;
+ (&(((immap_t *)IMAP_ADDR)->im_cpm.cp_fec))->fec_mii_data = regval;
+ }
+ } else {
+ retval = 1;
+ }
+
+ spin_unlock_irqrestore(&fep->lock, flags);
+
+ return(retval);
+}
+
+static void mii_do_cmd(struct net_device *dev, const phy_cmd_t *c)
+{
+ int k;
+
+ if(!c)
+ return;
+
+ for(k = 0; (c+k)->mii_data != mk_mii_end; k++)
+ mii_queue(dev, (c+k)->mii_data, (c+k)->funct);
+}
+
+static void mii_parse_sr(uint mii_reg, struct net_device *dev)
+{
+ struct fec_enet_private *fep = dev->priv;
+ volatile uint *s = &(fep->phy_status);
+
+ *s &= ~(PHY_STAT_LINK | PHY_STAT_FAULT | PHY_STAT_ANC);
+
+ if (mii_reg & 0x0004)
+ *s |= PHY_STAT_LINK;
+ if (mii_reg & 0x0010)
+ *s |= PHY_STAT_FAULT;
+ if (mii_reg & 0x0020)
+ *s |= PHY_STAT_ANC;
+
+ fep->link = (*s & PHY_STAT_LINK) ? 1 : 0;
+}
+
+static void mii_parse_cr(uint mii_reg, struct net_device *dev)
+{
+ struct fec_enet_private *fep = dev->priv;
+ volatile uint *s = &(fep->phy_status);
+
+ *s &= ~(PHY_CONF_ANE | PHY_CONF_LOOP);
+
+ if (mii_reg & 0x1000)
+ *s |= PHY_CONF_ANE;
+ if (mii_reg & 0x4000)
+ *s |= PHY_CONF_LOOP;
+}
+
+static void mii_parse_anar(uint mii_reg, struct net_device *dev)
+{
+ struct fec_enet_private *fep = dev->priv;
+ volatile uint *s = &(fep->phy_status);
+
+ *s &= ~(PHY_CONF_SPMASK);
+
+ if (mii_reg & 0x0020)
+ *s |= PHY_CONF_10HDX;
+ if (mii_reg & 0x0040)
+ *s |= PHY_CONF_10FDX;
+ if (mii_reg & 0x0080)
+ *s |= PHY_CONF_100HDX;
+ if (mii_reg & 0x00100)
+ *s |= PHY_CONF_100FDX;
+}
+#if 0
+static void mii_disp_reg(uint mii_reg, struct net_device *dev)
+{
+ printk("reg %u = 0x%04x\n", (mii_reg >> 18) & 0x1f, mii_reg & 0xffff);
+}
+#endif
+
+/* ------------------------------------------------------------------------- */
+/* The Level one LXT970 is used by many boards */
+
+#ifdef CONFIG_FEC_LXT970
+
+#define MII_LXT970_MIRROR 16 /* Mirror register */
+#define MII_LXT970_IER 17 /* Interrupt Enable Register */
+#define MII_LXT970_ISR 18 /* Interrupt Status Register */
+#define MII_LXT970_CONFIG 19 /* Configuration Register */
+#define MII_LXT970_CSR 20 /* Chip Status Register */
+
+static void mii_parse_lxt970_csr(uint mii_reg, struct net_device *dev)
+{
+ struct fec_enet_private *fep = dev->priv;
+ volatile uint *s = &(fep->phy_status);
+
+ *s &= ~(PHY_STAT_SPMASK);
+
+ if (mii_reg & 0x0800) {
+ if (mii_reg & 0x1000)
+ *s |= PHY_STAT_100FDX;
+ else
+ *s |= PHY_STAT_100HDX;
+ }
+ else {
+ if (mii_reg & 0x1000)
+ *s |= PHY_STAT_10FDX;
+ else
+ *s |= PHY_STAT_10HDX;
+ }
+}
+
+static phy_info_t phy_info_lxt970 = {
+ 0x07810000,
+ "LXT970",
+
+ (const phy_cmd_t []) { /* config */
+#if 0
+// { mk_mii_write(MII_REG_ANAR, 0x0021), NULL },
+
+ /* Set default operation of 100-TX....for some reason
+ * some of these bits are set on power up, which is wrong.
+ */
+ { mk_mii_write(MII_LXT970_CONFIG, 0), NULL },
+#endif
+ { mk_mii_read(MII_REG_CR), mii_parse_cr },
+ { mk_mii_read(MII_REG_ANAR), mii_parse_anar },
+ { mk_mii_end, }
+ },
+ (const phy_cmd_t []) { /* startup - enable interrupts */
+ { mk_mii_write(MII_LXT970_IER, 0x0002), NULL },
+ { mk_mii_write(MII_REG_CR, 0x1200), NULL }, /* autonegotiate */
+ { mk_mii_end, }
+ },
+ (const phy_cmd_t []) { /* ack_int */
+ /* read SR and ISR to acknowledge */
+
+ { mk_mii_read(MII_REG_SR), mii_parse_sr },
+ { mk_mii_read(MII_LXT970_ISR), NULL },
+
+ /* find out the current status */
+
+ { mk_mii_read(MII_LXT970_CSR), mii_parse_lxt970_csr },
+ { mk_mii_end, }
+ },
+ (const phy_cmd_t []) { /* shutdown - disable interrupts */
+ { mk_mii_write(MII_LXT970_IER, 0x0000), NULL },
+ { mk_mii_end, }
+ },
+};
+
+#endif /* CONFIG_FEC_LXT970 */
+
+/* ------------------------------------------------------------------------- */
+/* The Level one LXT971 is used on some of my custom boards */
+
+#ifdef CONFIG_FEC_LXT971
+
+/* register definitions for the 971 */
+
+#define MII_LXT971_PCR 16 /* Port Control Register */
+#define MII_LXT971_SR2 17 /* Status Register 2 */
+#define MII_LXT971_IER 18 /* Interrupt Enable Register */
+#define MII_LXT971_ISR 19 /* Interrupt Status Register */
+#define MII_LXT971_LCR 20 /* LED Control Register */
+#define MII_LXT971_TCR 30 /* Transmit Control Register */
+
+/*
+ * I had some nice ideas of running the MDIO faster...
+ * The 971 should support 8MHz and I tried it, but things acted really
+ * weird, so 2.5 MHz ought to be enough for anyone...
+ */
+
+static void mii_parse_lxt971_sr2(uint mii_reg, struct net_device *dev)
+{
+ struct fec_enet_private *fep = dev->priv;
+ volatile uint *s = &(fep->phy_status);
+
+ *s &= ~(PHY_STAT_SPMASK);
+
+ if (mii_reg & 0x4000) {
+ if (mii_reg & 0x0200)
+ *s |= PHY_STAT_100FDX;
+ else
+ *s |= PHY_STAT_100HDX;
+ }
+ else {
+ if (mii_reg & 0x0200)
+ *s |= PHY_STAT_10FDX;
+ else
+ *s |= PHY_STAT_10HDX;
+ }
+ if (mii_reg & 0x0008)
+ *s |= PHY_STAT_FAULT;
+}
+
+static phy_info_t phy_info_lxt971 = {
+ 0x0001378e,
+ "LXT971",
+
+ (const phy_cmd_t []) { /* config */
+// { mk_mii_write(MII_REG_ANAR, 0x021), NULL }, /* 10 Mbps, HD */
+ { mk_mii_read(MII_REG_CR), mii_parse_cr },
+ { mk_mii_read(MII_REG_ANAR), mii_parse_anar },
+ { mk_mii_end, }
+ },
+ (const phy_cmd_t []) { /* startup - enable interrupts */
+ { mk_mii_write(MII_LXT971_IER, 0x00f2), NULL },
+ { mk_mii_write(MII_REG_CR, 0x1200), NULL }, /* autonegotiate */
+
+ /* Somehow does the 971 tell me that the link is down
+ * the first read after power-up.
+ * read here to get a valid value in ack_int */
+
+ { mk_mii_read(MII_REG_SR), mii_parse_sr },
+ { mk_mii_end, }
+ },
+ (const phy_cmd_t []) { /* ack_int */
+ /* find out the current status */
+
+ { mk_mii_read(MII_REG_SR), mii_parse_sr },
+ { mk_mii_read(MII_LXT971_SR2), mii_parse_lxt971_sr2 },
+
+ /* we only need to read ISR to acknowledge */
+
+ { mk_mii_read(MII_LXT971_ISR), NULL },
+ { mk_mii_end, }
+ },
+ (const phy_cmd_t []) { /* shutdown - disable interrupts */
+ { mk_mii_write(MII_LXT971_IER, 0x0000), NULL },
+ { mk_mii_end, }
+ },
+};
+
+#endif /* CONFIG_FEC_LXT970 */
+
+
+/* ------------------------------------------------------------------------- */
+/* The Quality Semiconductor QS6612 is used on the RPX CLLF */
+
+#ifdef CONFIG_FEC_QS6612
+
+/* register definitions */
+
+#define MII_QS6612_MCR 17 /* Mode Control Register */
+#define MII_QS6612_FTR 27 /* Factory Test Register */
+#define MII_QS6612_MCO 28 /* Misc. Control Register */
+#define MII_QS6612_ISR 29 /* Interrupt Source Register */
+#define MII_QS6612_IMR 30 /* Interrupt Mask Register */
+#define MII_QS6612_PCR 31 /* 100BaseTx PHY Control Reg. */
+
+static void mii_parse_qs6612_pcr(uint mii_reg, struct net_device *dev)
+{
+ struct fec_enet_private *fep = dev->priv;
+ volatile uint *s = &(fep->phy_status);
+
+ *s &= ~(PHY_STAT_SPMASK);
+
+ switch((mii_reg >> 2) & 7) {
+ case 1: *s |= PHY_STAT_10HDX; break;
+ case 2: *s |= PHY_STAT_100HDX; break;
+ case 5: *s |= PHY_STAT_10FDX; break;
+ case 6: *s |= PHY_STAT_100FDX; break;
+ }
+}
+
+static phy_info_t phy_info_qs6612 = {
+ 0x00181440,
+ "QS6612",
+
+ (const phy_cmd_t []) { /* config */
+// { mk_mii_write(MII_REG_ANAR, 0x061), NULL }, /* 10 Mbps */
+
+ /* The PHY powers up isolated on the RPX,
+ * so send a command to allow operation.
+ */
+
+ { mk_mii_write(MII_QS6612_PCR, 0x0dc0), NULL },
+
+ /* parse cr and anar to get some info */
+
+ { mk_mii_read(MII_REG_CR), mii_parse_cr },
+ { mk_mii_read(MII_REG_ANAR), mii_parse_anar },
+ { mk_mii_end, }
+ },
+ (const phy_cmd_t []) { /* startup - enable interrupts */
+ { mk_mii_write(MII_QS6612_IMR, 0x003a), NULL },
+ { mk_mii_write(MII_REG_CR, 0x1200), NULL }, /* autonegotiate */
+ { mk_mii_end, }
+ },
+ (const phy_cmd_t []) { /* ack_int */
+
+ /* we need to read ISR, SR and ANER to acknowledge */
+
+ { mk_mii_read(MII_QS6612_ISR), NULL },
+ { mk_mii_read(MII_REG_SR), mii_parse_sr },
+ { mk_mii_read(MII_REG_ANER), NULL },
+
+ /* read pcr to get info */
+
+ { mk_mii_read(MII_QS6612_PCR), mii_parse_qs6612_pcr },
+ { mk_mii_end, }
+ },
+ (const phy_cmd_t []) { /* shutdown - disable interrupts */
+ { mk_mii_write(MII_QS6612_IMR, 0x0000), NULL },
+ { mk_mii_end, }
+ },
+};
+
+#endif /* CONFIG_FEC_QS6612 */
+
+/* ------------------------------------------------------------------------- */
+/* The Advanced Micro Devices AM79C874 is used on the ICU862 */
+
+#ifdef CONFIG_FEC_AM79C874
+
+/* register definitions for the 79C874 */
+
+#define MII_AM79C874_MFR 16 /* Miscellaneous Features Register */
+#define MII_AM79C874_ICSR 17 /* Interrupt Control/Status Register */
+#define MII_AM79C874_DR 18 /* Diagnostic Register */
+#define MII_AM79C874_PMLR 19 /* Power Management & Loopback Register */
+#define MII_AM79C874_MCR 21 /* Mode Control Register */
+#define MII_AM79C874_DC 23 /* Disconnect Counter */
+#define MII_AM79C874_REC 24 /* Receiver Error Counter */
+
+static void mii_parse_amd79c874_dr(uint mii_reg, struct net_device *dev, uint data)
+{
+ volatile struct fec_enet_private *fep = dev->priv;
+ uint s = fep->phy_status;
+
+ s &= ~(PHY_STAT_SPMASK);
+
+ /* Register 18: Bit 10 is data rate, 11 is Duplex */
+ switch ((mii_reg >> 10) & 3) {
+ case 0: s |= PHY_STAT_10HDX; break;
+ case 1: s |= PHY_STAT_100HDX; break;
+ case 2: s |= PHY_STAT_10FDX; break;
+ case 3: s |= PHY_STAT_100FDX; break;
+ }
+
+ fep->phy_status = s;
+}
+
+static phy_info_t phy_info_amd79c874 = {
+ 0x00022561,
+ "AM79C874",
+
+ (const phy_cmd_t []) { /* config */
+// { mk_mii_write(MII_REG_ANAR, 0x021), NULL }, /* 10 Mbps, HD */
+ { mk_mii_read(MII_REG_CR), mii_parse_cr },
+ { mk_mii_read(MII_REG_ANAR), mii_parse_anar },
+ { mk_mii_end, }
+ },
+ (const phy_cmd_t []) { /* startup - enable interrupts */
+ { mk_mii_write(MII_AM79C874_ICSR, 0xff00), NULL },
+ { mk_mii_write(MII_REG_CR, 0x1200), NULL }, /* autonegotiate */
+ { mk_mii_end, }
+ },
+ (const phy_cmd_t []) { /* ack_int */
+ /* find out the current status */
+
+ { mk_mii_read(MII_REG_SR), mii_parse_sr },
+ { mk_mii_read(MII_AM79C874_DR), mii_parse_amd79c874_dr },
+
+ /* we only need to read ICSR to acknowledge */
+
+ { mk_mii_read(MII_AM79C874_ICSR), NULL },
+ { mk_mii_end, }
+ },
+ (const phy_cmd_t []) { /* shutdown - disable interrupts */
+ { mk_mii_write(MII_AM79C874_ICSR, 0x0000), NULL },
+ { mk_mii_end, }
+ },
+};
+
+#endif /* CONFIG_FEC_AM79C874 */
+
+static phy_info_t *phy_info[] = {
+
+#ifdef CONFIG_FEC_LXT970
+ &phy_info_lxt970,
+#endif /* CONFIG_FEC_LXT970 */
+
+#ifdef CONFIG_FEC_LXT971
+ &phy_info_lxt971,
+#endif /* CONFIG_FEC_LXT971 */
+
+#ifdef CONFIG_FEC_QS6612
+ &phy_info_qs6612,
+#endif /* CONFIG_FEC_QS6612 */
+
+#ifdef CONFIG_FEC_AM79C874
+ &phy_info_amd79c874,
+#endif /* CONFIG_FEC_AM79C874 */
+
+ NULL
+};
+
+static void mii_display_status(struct net_device *dev)
+{
+ struct fec_enet_private *fep = dev->priv;
+ volatile uint *s = &(fep->phy_status);
+
+ if (!fep->link && !fep->old_link) {
+ /* Link is still down - don't print anything */
+ return;
+ }
+
+ printk("%s: status: ", dev->name);
+
+ if (!fep->link) {
+ printk("link down");
+ } else {
+ printk("link up");
+
+ switch(*s & PHY_STAT_SPMASK) {
+ case PHY_STAT_100FDX: printk(", 100 Mbps Full Duplex"); break;
+ case PHY_STAT_100HDX: printk(", 100 Mbps Half Duplex"); break;
+ case PHY_STAT_10FDX: printk(", 10 Mbps Full Duplex"); break;
+ case PHY_STAT_10HDX: printk(", 10 Mbps Half Duplex"); break;
+ default:
+ printk(", Unknown speed/duplex");
+ }
+
+ if (*s & PHY_STAT_ANC)
+ printk(", auto-negotiation complete");
+ }
+
+ if (*s & PHY_STAT_FAULT)
+ printk(", remote fault");
+
+ printk(".\n");
+}
+
+static void mii_display_config(struct net_device *dev)
+{
+ struct fec_enet_private *fep = dev->priv;
+ volatile uint *s = &(fep->phy_status);
+
+ printk("%s: config: auto-negotiation ", dev->name);
+
+ if (*s & PHY_CONF_ANE)
+ printk("on");
+ else
+ printk("off");
+
+ if (*s & PHY_CONF_100FDX)
+ printk(", 100FDX");
+ if (*s & PHY_CONF_100HDX)
+ printk(", 100HDX");
+ if (*s & PHY_CONF_10FDX)
+ printk(", 10FDX");
+ if (*s & PHY_CONF_10HDX)
+ printk(", 10HDX");
+ if (!(*s & PHY_CONF_SPMASK))
+ printk(", No speed/duplex selected?");
+
+ if (*s & PHY_CONF_LOOP)
+ printk(", loopback enabled");
+
+ printk(".\n");
+
+ fep->sequence_done = 1;
+}
+
+static void mii_relink(struct net_device *dev)
+{
+ struct fec_enet_private *fep = dev->priv;
+ int duplex;
+
+ fep->link = (fep->phy_status & PHY_STAT_LINK) ? 1 : 0;
+ mii_display_status(dev);
+ fep->old_link = fep->link;
+
+ if (fep->link) {
+ duplex = 0;
+ if (fep->phy_status
+ & (PHY_STAT_100FDX | PHY_STAT_10FDX))
+ duplex = 1;
+ fec_restart(dev, duplex);
+ }
+ else
+ fec_stop(dev);
+
+#if 0
+ enable_irq(fep->mii_irq);
+#endif
+
+}
+
+static void mii_queue_relink(uint mii_reg, struct net_device *dev)
+{
+ struct fec_enet_private *fep = dev->priv;
+
+ fep->phy_task.routine = (void *)mii_relink;
+ fep->phy_task.data = dev;
+ schedule_task(&fep->phy_task);
+}
+
+static void mii_queue_config(uint mii_reg, struct net_device *dev)
+{
+ struct fec_enet_private *fep = dev->priv;
+
+ fep->phy_task.routine = (void *)mii_display_config;
+ fep->phy_task.data = dev;
+ schedule_task(&fep->phy_task);
+}
+
+
+
+phy_cmd_t phy_cmd_relink[] = { { mk_mii_read(MII_REG_CR), mii_queue_relink },
+ { mk_mii_end, } };
+phy_cmd_t phy_cmd_config[] = { { mk_mii_read(MII_REG_CR), mii_queue_config },
+ { mk_mii_end, } };
+
+
+
+/* Read remainder of PHY ID.
+*/
+static void
+mii_discover_phy3(uint mii_reg, struct net_device *dev)
+{
+ struct fec_enet_private *fep;
+ int i;
+
+ fep = dev->priv;
+ fep->phy_id |= (mii_reg & 0xffff);
+
+ for(i = 0; phy_info[i]; i++)
+ if(phy_info[i]->id == (fep->phy_id >> 4))
+ break;
+
+ if(!phy_info[i])
+ panic("%s: PHY id 0x%08x is not supported!\n",
+ dev->name, fep->phy_id);
+
+ fep->phy = phy_info[i];
+ fep->phy_id_done = 1;
+
+ printk("%s: Phy @ 0x%x, type %s (0x%08x)\n",
+ dev->name, fep->phy_addr, fep->phy->name, fep->phy_id);
+}
+
+/* Scan all of the MII PHY addresses looking for someone to respond
+ * with a valid ID. This usually happens quickly.
+ */
+static void
+mii_discover_phy(uint mii_reg, struct net_device *dev)
+{
+ struct fec_enet_private *fep;
+ uint phytype;
+
+ fep = dev->priv;
+
+ if ((phytype = (mii_reg & 0xffff)) != 0xffff) {
+
+ /* Got first part of ID, now get remainder.
+ */
+ fep->phy_id = phytype << 16;
+ mii_queue(dev, mk_mii_read(MII_REG_PHYIR2), mii_discover_phy3);
+ } else {
+ fep->phy_addr++;
+ if (fep->phy_addr < 32) {
+ mii_queue(dev, mk_mii_read(MII_REG_PHYIR1),
+ mii_discover_phy);
+ } else {
+ printk("fec: No PHY device found.\n");
+ }
+ }
+}
+#endif /* CONFIG_USE_MDIO */
+
+/* This interrupt occurs when the PHY detects a link change.
+*/
+static void
+#ifdef CONFIG_RPXCLASSIC
+mii_link_interrupt(void *dev_id)
+#else
+mii_link_interrupt(int irq, void * dev_id, struct pt_regs * regs)
+#endif
+{
+#ifdef CONFIG_USE_MDIO
+ struct net_device *dev = dev_id;
+ struct fec_enet_private *fep = dev->priv;
+ volatile immap_t *immap = (immap_t *)IMAP_ADDR;
+ volatile fec_t *fecp = &(immap->im_cpm.cp_fec);
+ unsigned int ecntrl = fecp->fec_ecntrl;
+
+ /* We need the FEC enabled to access the MII
+ */
+ if ((ecntrl & FEC_ECNTRL_ETHER_EN) == 0) {
+ fecp->fec_ecntrl |= FEC_ECNTRL_ETHER_EN;
+ }
+#endif /* CONFIG_USE_MDIO */
+
+#if 0
+ disable_irq(fep->mii_irq); /* disable now, enable later */
+#endif
+
+
+#ifdef CONFIG_USE_MDIO
+ mii_do_cmd(dev, fep->phy->ack_int);
+ mii_do_cmd(dev, phy_cmd_relink); /* restart and display status */
+
+ if ((ecntrl & FEC_ECNTRL_ETHER_EN) == 0) {
+ fecp->fec_ecntrl = ecntrl; /* restore old settings */
+ }
+#else
+printk("%s[%d] %s: unexpected Link interrupt\n", __FILE__,__LINE__,__FUNCTION__);
+#endif /* CONFIG_USE_MDIO */
+
+}
+
+static int
+fec_enet_open(struct net_device *dev)
+{
+ struct fec_enet_private *fep = dev->priv;
+
+ /* I should reset the ring buffers here, but I don't yet know
+ * a simple way to do that.
+ */
+
+#ifdef CONFIG_USE_MDIO
+ fep->sequence_done = 0;
+ fep->link = 0;
+
+ if (fep->phy) {
+ mii_do_cmd(dev, fep->phy->ack_int);
+ mii_do_cmd(dev, fep->phy->config);
+ mii_do_cmd(dev, phy_cmd_config); /* display configuration */
+ while(!fep->sequence_done)
+ schedule();
+
+ mii_do_cmd(dev, fep->phy->startup);
+ netif_start_queue(dev);
+ return 0; /* Success */
+ }
+ return -ENODEV; /* No PHY we understand */
+#else
+ fep->link = 1;
+ netif_start_queue(dev);
+ return 0; /* Success */
+#endif /* CONFIG_USE_MDIO */
+
+}
+
+static int
+fec_enet_close(struct net_device *dev)
+{
+ /* Don't know what to do yet.
+ */
+ netif_stop_queue(dev);
+ fec_stop(dev);
+
+ return 0;
+}
+
+static struct net_device_stats *fec_enet_get_stats(struct net_device *dev)
+{
+ struct fec_enet_private *fep = (struct fec_enet_private *)dev->priv;
+
+ return &fep->stats;
+}
+
+/* Set or clear the multicast filter for this adaptor.
+ * Skeleton taken from sunlance driver.
+ * The CPM Ethernet implementation allows Multicast as well as individual
+ * MAC address filtering. Some of the drivers check to make sure it is
+ * a group multicast address, and discard those that are not. I guess I
+ * will do the same for now, but just remove the test if you want
+ * individual filtering as well (do the upper net layers want or support
+ * this kind of feature?).
+ */
+
+static void set_multicast_list(struct net_device *dev)
+{
+ struct fec_enet_private *fep;
+ volatile fec_t *ep;
+
+ fep = (struct fec_enet_private *)dev->priv;
+ ep = &(((immap_t *)IMAP_ADDR)->im_cpm.cp_fec);
+
+ if (dev->flags&IFF_PROMISC) {
+
+ /* Log any net taps. */
+ printk("%s: Promiscuous mode enabled.\n", dev->name);
+ ep->fec_r_cntrl |= FEC_RCNTRL_PROM;
+ } else {
+
+ ep->fec_r_cntrl &= ~FEC_RCNTRL_PROM;
+
+ if (dev->flags & IFF_ALLMULTI) {
+ /* Catch all multicast addresses, so set the
+ * filter to all 1's.
+ */
+ ep->fec_hash_table_high = 0xffffffff;
+ ep->fec_hash_table_low = 0xffffffff;
+ }
+#if 0
+ else {
+ /* Clear filter and add the addresses in the list.
+ */
+ ep->sen_gaddr1 = 0;
+ ep->sen_gaddr2 = 0;
+ ep->sen_gaddr3 = 0;
+ ep->sen_gaddr4 = 0;
+
+ dmi = dev->mc_list;
+
+ for (i=0; i<dev->mc_count; i++) {
+
+ /* Only support group multicast for now.
+ */
+ if (!(dmi->dmi_addr[0] & 1))
+ continue;
+
+ /* The address in dmi_addr is LSB first,
+ * and taddr is MSB first. We have to
+ * copy bytes MSB first from dmi_addr.
+ */
+ mcptr = (u_char *)dmi->dmi_addr + 5;
+ tdptr = (u_char *)&ep->sen_taddrh;
+ for (j=0; j<6; j++)
+ *tdptr++ = *mcptr--;
+
+ /* Ask CPM to run CRC and set bit in
+ * filter mask.
+ */
+ cpmp->cp_cpcr = mk_cr_cmd(CPM_CR_CH_SCC1, CPM_CR_SET_GADDR) | CPM_CR_FLG;
+ /* this delay is necessary here -- Cort */
+ udelay(10);
+ while (cpmp->cp_cpcr & CPM_CR_FLG);
+ }
+ }
+#endif
+ }
+}
+
+/* Initialize the FEC Ethernet on 860T.
+ */
+static int __init fec_enet_init(void)
+{
+ struct net_device *dev;
+ struct fec_enet_private *fep;
+ int i, j, k, err;
+ unsigned char *eap, *iap, *ba;
+ unsigned long mem_addr;
+ volatile cbd_t *bdp;
+ cbd_t *cbd_base;
+ volatile immap_t *immap;
+ volatile fec_t *fecp;
+ bd_t *bd;
+#ifdef CONFIG_SCC_ENET
+ unsigned char tmpaddr[6];
+#endif
+
+ immap = (immap_t *)IMAP_ADDR; /* pointer to internal registers */
+
+ bd = (bd_t *)__res;
+
+ dev = alloc_etherdev(sizeof(*fep));
+ if (!dev)
+ return -ENOMEM;
+
+ fep = dev->priv;
+
+ fecp = &(immap->im_cpm.cp_fec);
+
+ /* Whack a reset. We should wait for this.
+ */
+ fecp->fec_ecntrl = FEC_ECNTRL_PINMUX | FEC_ECNTRL_RESET;
+ for (i = 0;
+ (fecp->fec_ecntrl & FEC_ECNTRL_RESET) && (i < FEC_RESET_DELAY);
+ ++i) {
+ udelay(1);
+ }
+ if (i == FEC_RESET_DELAY) {
+ printk ("FEC Reset timeout!\n");
+ }
+
+ /* Set the Ethernet address. If using multiple Enets on the 8xx,
+ * this needs some work to get unique addresses.
+ */
+ eap = (unsigned char *)my_enet_addr;
+ iap = bd->bi_enetaddr;
+
+#ifdef CONFIG_SCC_ENET
+ /*
+ * If a board has Ethernet configured both on a SCC and the
+ * FEC, it needs (at least) 2 MAC addresses (we know that Sun
+ * disagrees, but anyway). For the FEC port, we create
+ * another address by setting one of the address bits above
+ * something that would have (up to now) been allocated.
+ */
+ for (i=0; i<6; i++)
+ tmpaddr[i] = *iap++;
+ tmpaddr[3] |= 0x80;
+ iap = tmpaddr;
+#endif
+
+ for (i=0; i<6; i++) {
+ dev->dev_addr[i] = *eap++ = *iap++;
+ }
+
+ /* Allocate memory for buffer descriptors.
+ */
+ if (((RX_RING_SIZE + TX_RING_SIZE) * sizeof(cbd_t)) > PAGE_SIZE) {
+ printk("FEC init error. Need more space.\n");
+ printk("FEC initialization failed.\n");
+ return 1;
+ }
+ cbd_base = (cbd_t *)consistent_alloc(GFP_KERNEL, PAGE_SIZE, &mem_addr);
+
+ /* Set receive and transmit descriptor base.
+ */
+ fep->rx_bd_base = cbd_base;
+ fep->tx_bd_base = cbd_base + RX_RING_SIZE;
+
+ fep->skb_cur = fep->skb_dirty = 0;
+
+ /* Initialize the receive buffer descriptors.
+ */
+ bdp = fep->rx_bd_base;
+ k = 0;
+ for (i=0; i<FEC_ENET_RX_PAGES; i++) {
+
+ /* Allocate a page.
+ */
+ ba = (unsigned char *)consistent_alloc(GFP_KERNEL, PAGE_SIZE, &mem_addr);
+ /* BUG: no check for failure */
+
+ /* Initialize the BD for every fragment in the page.
+ */
+ for (j=0; j<FEC_ENET_RX_FRPPG; j++) {
+ bdp->cbd_sc = BD_ENET_RX_EMPTY;
+ bdp->cbd_bufaddr = mem_addr;
+ fep->rx_vaddr[k++] = ba;
+ mem_addr += FEC_ENET_RX_FRSIZE;
+ ba += FEC_ENET_RX_FRSIZE;
+ bdp++;
+ }
+ }
+
+ /* Set the last buffer to wrap.
+ */
+ bdp--;
+ bdp->cbd_sc |= BD_SC_WRAP;
+
+#ifdef CONFIG_FEC_PACKETHOOK
+ fep->ph_lock = 0;
+ fep->ph_rxhandler = fep->ph_txhandler = NULL;
+ fep->ph_proto = 0;
+ fep->ph_regaddr = NULL;
+ fep->ph_priv = NULL;
+#endif
+
+ /* Install our interrupt handler.
+ */
+ if (request_irq(FEC_INTERRUPT, fec_enet_interrupt, 0, "fec", dev) != 0)
+ panic("Could not allocate FEC IRQ!");
+
+#ifdef CONFIG_RPXCLASSIC
+ /* Make Port C, bit 15 an input that causes interrupts.
+ */
+ immap->im_ioport.iop_pcpar &= ~0x0001;
+ immap->im_ioport.iop_pcdir &= ~0x0001;
+ immap->im_ioport.iop_pcso &= ~0x0001;
+ immap->im_ioport.iop_pcint |= 0x0001;
+ cpm_install_handler(CPMVEC_PIO_PC15, mii_link_interrupt, dev);
+
+ /* Make LEDS reflect Link status.
+ */
+ *((uint *) RPX_CSR_ADDR) &= ~BCSR2_FETHLEDMODE;
+#endif
+
+#ifdef PHY_INTERRUPT
+ ((immap_t *)IMAP_ADDR)->im_siu_conf.sc_siel |=
+ (0x80000000 >> PHY_INTERRUPT);
+
+ if (request_irq(PHY_INTERRUPT, mii_link_interrupt, 0, "mii", dev) != 0)
+ panic("Could not allocate MII IRQ!");
+#endif
+
+ dev->base_addr = (unsigned long)fecp;
+
+ /* The FEC Ethernet specific entries in the device structure. */
+ dev->open = fec_enet_open;
+ dev->hard_start_xmit = fec_enet_start_xmit;
+ dev->tx_timeout = fec_timeout;
+ dev->watchdog_timeo = TX_TIMEOUT;
+ dev->stop = fec_enet_close;
+ dev->get_stats = fec_enet_get_stats;
+ dev->set_multicast_list = set_multicast_list;
+
+#ifdef CONFIG_USE_MDIO
+ for (i=0; i<NMII-1; i++)
+ mii_cmds[i].mii_next = &mii_cmds[i+1];
+ mii_free = mii_cmds;
+#endif /* CONFIG_USE_MDIO */
+
+ /* Configure all of port D for MII.
+ */
+ immap->im_ioport.iop_pdpar = 0x1fff;
+
+ /* Bits moved from Rev. D onward.
+ */
+ if ((mfspr(SPRN_IMMR) & 0xffff) < 0x0501)
+ immap->im_ioport.iop_pddir = 0x1c58; /* Pre rev. D */
+ else
+ immap->im_ioport.iop_pddir = 0x1fff; /* Rev. D and later */
+
+#ifdef CONFIG_USE_MDIO
+ /* Set MII speed to 2.5 MHz
+ */
+ fecp->fec_mii_speed = fep->phy_speed =
+ (( (bd->bi_intfreq + 500000) / 2500000 / 2 ) & 0x3F ) << 1;
+#else
+ fecp->fec_mii_speed = 0; /* turn off MDIO */
+#endif /* CONFIG_USE_MDIO */
+
+ err = register_netdev(dev);
+ if (err) {
+ free_netdev(dev);
+ return err;
+ }
+
+ printk ("%s: FEC ENET Version 0.2, FEC irq %d"
+#ifdef PHY_INTERRUPT
+ ", MII irq %d"
+#endif
+ ", addr ",
+ dev->name, FEC_INTERRUPT
+#ifdef PHY_INTERRUPT
+ , PHY_INTERRUPT
+#endif
+ );
+ for (i=0; i<6; i++)
+ printk("%02x%c", dev->dev_addr[i], (i==5) ? '\n' : ':');
+
+#ifdef CONFIG_USE_MDIO /* start in full duplex mode, and negotiate speed */
+ fec_restart (dev, 1);
+#else /* always use half duplex mode only */
+ fec_restart (dev, 0);
+#endif
+
+#ifdef CONFIG_USE_MDIO
+ /* Queue up command to detect the PHY and initialize the
+ * remainder of the interface.
+ */
+ fep->phy_id_done = 0;
+ fep->phy_addr = 0;
+ mii_queue(dev, mk_mii_read(MII_REG_PHYIR1), mii_discover_phy);
+#endif /* CONFIG_USE_MDIO */
+
+ return 0;
+}
+module_init(fec_enet_init);
+
+/* This function is called to start or restart the FEC during a link
+ * change. This only happens when switching between half and full
+ * duplex.
+ */
+static void
+fec_restart(struct net_device *dev, int duplex)
+{
+ struct fec_enet_private *fep;
+ int i;
+ volatile cbd_t *bdp;
+ volatile immap_t *immap;
+ volatile fec_t *fecp;
+
+ immap = (immap_t *)IMAP_ADDR; /* pointer to internal registers */
+
+ fecp = &(immap->im_cpm.cp_fec);
+
+ fep = dev->priv;
+
+ /* Whack a reset. We should wait for this.
+ */
+ fecp->fec_ecntrl = FEC_ECNTRL_PINMUX | FEC_ECNTRL_RESET;
+ for (i = 0;
+ (fecp->fec_ecntrl & FEC_ECNTRL_RESET) && (i < FEC_RESET_DELAY);
+ ++i) {
+ udelay(1);
+ }
+ if (i == FEC_RESET_DELAY) {
+ printk ("FEC Reset timeout!\n");
+ }
+
+ /* Set station address.
+ */
+ fecp->fec_addr_low = (my_enet_addr[0] << 16) | my_enet_addr[1];
+ fecp->fec_addr_high = my_enet_addr[2];
+
+ /* Reset all multicast.
+ */
+ fecp->fec_hash_table_high = 0;
+ fecp->fec_hash_table_low = 0;
+
+ /* Set maximum receive buffer size.
+ */
+ fecp->fec_r_buff_size = PKT_MAXBLR_SIZE;
+ fecp->fec_r_hash = PKT_MAXBUF_SIZE;
+
+ /* Set receive and transmit descriptor base.
+ */
+ fecp->fec_r_des_start = iopa((uint)(fep->rx_bd_base));
+ fecp->fec_x_des_start = iopa((uint)(fep->tx_bd_base));
+
+ fep->dirty_tx = fep->cur_tx = fep->tx_bd_base;
+ fep->cur_rx = fep->rx_bd_base;
+
+ /* Reset SKB transmit buffers.
+ */
+ fep->skb_cur = fep->skb_dirty = 0;
+ for (i=0; i<=TX_RING_MOD_MASK; i++) {
+ if (fep->tx_skbuff[i] != NULL) {
+ dev_kfree_skb(fep->tx_skbuff[i]);
+ fep->tx_skbuff[i] = NULL;
+ }
+ }
+
+ /* Initialize the receive buffer descriptors.
+ */
+ bdp = fep->rx_bd_base;
+ for (i=0; i<RX_RING_SIZE; i++) {
+
+ /* Initialize the BD for every fragment in the page.
+ */
+ bdp->cbd_sc = BD_ENET_RX_EMPTY;
+ bdp++;
+ }
+
+ /* Set the last buffer to wrap.
+ */
+ bdp--;
+ bdp->cbd_sc |= BD_SC_WRAP;
+
+ /* ...and the same for transmmit.
+ */
+ bdp = fep->tx_bd_base;
+ for (i=0; i<TX_RING_SIZE; i++) {
+
+ /* Initialize the BD for every fragment in the page.
+ */
+ bdp->cbd_sc = 0;
+ bdp->cbd_bufaddr = 0;
+ bdp++;
+ }
+
+ /* Set the last buffer to wrap.
+ */
+ bdp--;
+ bdp->cbd_sc |= BD_SC_WRAP;
+
+ /* Enable MII mode.
+ */
+ if (duplex) {
+ fecp->fec_r_cntrl = FEC_RCNTRL_MII_MODE; /* MII enable */
+ fecp->fec_x_cntrl = FEC_TCNTRL_FDEN; /* FD enable */
+ }
+ else {
+ fecp->fec_r_cntrl = FEC_RCNTRL_MII_MODE | FEC_RCNTRL_DRT;
+ fecp->fec_x_cntrl = 0;
+ }
+ fep->full_duplex = duplex;
+
+ /* Enable big endian and don't care about SDMA FC.
+ */
+ fecp->fec_fun_code = 0x78000000;
+
+#ifdef CONFIG_USE_MDIO
+ /* Set MII speed.
+ */
+ fecp->fec_mii_speed = fep->phy_speed;
+#endif /* CONFIG_USE_MDIO */
+
+ /* Clear any outstanding interrupt.
+ */
+ fecp->fec_ievent = 0xffc0;
+
+ fecp->fec_ivec = (FEC_INTERRUPT/2) << 29;
+
+ /* Enable interrupts we wish to service.
+ */
+ fecp->fec_imask = ( FEC_ENET_TXF | FEC_ENET_TXB |
+ FEC_ENET_RXF | FEC_ENET_RXB | FEC_ENET_MII );
+
+ /* And last, enable the transmit and receive processing.
+ */
+ fecp->fec_ecntrl = FEC_ECNTRL_PINMUX | FEC_ECNTRL_ETHER_EN;
+ fecp->fec_r_des_active = 0x01000000;
+}
+
+static void
+fec_stop(struct net_device *dev)
+{
+ volatile immap_t *immap;
+ volatile fec_t *fecp;
+ struct fec_enet_private *fep;
+ int i;
+
+ immap = (immap_t *)IMAP_ADDR; /* pointer to internal registers */
+
+ fecp = &(immap->im_cpm.cp_fec);
+
+ if ((fecp->fec_ecntrl & FEC_ECNTRL_ETHER_EN) == 0)
+ return; /* already down */
+
+ fep = dev->priv;
+
+
+ fecp->fec_x_cntrl = 0x01; /* Graceful transmit stop */
+
+ for (i = 0;
+ ((fecp->fec_ievent & 0x10000000) == 0) && (i < FEC_RESET_DELAY);
+ ++i) {
+ udelay(1);
+ }
+ if (i == FEC_RESET_DELAY) {
+ printk ("FEC timeout on graceful transmit stop\n");
+ }
+
+ /* Clear outstanding MII command interrupts.
+ */
+ fecp->fec_ievent = FEC_ENET_MII;
+
+ /* Enable MII command finished interrupt
+ */
+ fecp->fec_ivec = (FEC_INTERRUPT/2) << 29;
+ fecp->fec_imask = FEC_ENET_MII;
+
+#ifdef CONFIG_USE_MDIO
+ /* Set MII speed.
+ */
+ fecp->fec_mii_speed = fep->phy_speed;
+#endif /* CONFIG_USE_MDIO */
+
+ /* Disable FEC
+ */
+ fecp->fec_ecntrl &= ~(FEC_ECNTRL_ETHER_EN);
+}
diff --git a/arch/ppc/8xx_io/micropatch.c b/arch/ppc/8xx_io/micropatch.c
new file mode 100644
index 0000000..312af07
--- /dev/null
+++ b/arch/ppc/8xx_io/micropatch.c
@@ -0,0 +1,744 @@
+
+/* Microcode patches for the CPM as supplied by Motorola.
+ * This is the one for IIC/SPI. There is a newer one that
+ * also relocates SMC2, but this would require additional changes
+ * to uart.c, so I am holding off on that for a moment.
+ */
+#include <linux/config.h>
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/param.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/interrupt.h>
+#include <asm/irq.h>
+#include <asm/mpc8xx.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <asm/8xx_immap.h>
+#include <asm/commproc.h>
+
+/*
+ * I2C/SPI relocation patch arrays.
+ */
+
+#ifdef CONFIG_I2C_SPI_UCODE_PATCH
+
+uint patch_2000[] = {
+ 0x7FFFEFD9,
+ 0x3FFD0000,
+ 0x7FFB49F7,
+ 0x7FF90000,
+ 0x5FEFADF7,
+ 0x5F89ADF7,
+ 0x5FEFAFF7,
+ 0x5F89AFF7,
+ 0x3A9CFBC8,
+ 0xE7C0EDF0,
+ 0x77C1E1BB,
+ 0xF4DC7F1D,
+ 0xABAD932F,
+ 0x4E08FDCF,
+ 0x6E0FAFF8,
+ 0x7CCF76CF,
+ 0xFD1FF9CF,
+ 0xABF88DC6,
+ 0xAB5679F7,
+ 0xB0937383,
+ 0xDFCE79F7,
+ 0xB091E6BB,
+ 0xE5BBE74F,
+ 0xB3FA6F0F,
+ 0x6FFB76CE,
+ 0xEE0DF9CF,
+ 0x2BFBEFEF,
+ 0xCFEEF9CF,
+ 0x76CEAD24,
+ 0x90B2DF9A,
+ 0x7FDDD0BF,
+ 0x4BF847FD,
+ 0x7CCF76CE,
+ 0xCFEF7E1F,
+ 0x7F1D7DFD,
+ 0xF0B6EF71,
+ 0x7FC177C1,
+ 0xFBC86079,
+ 0xE722FBC8,
+ 0x5FFFDFFF,
+ 0x5FB2FFFB,
+ 0xFBC8F3C8,
+ 0x94A67F01,
+ 0x7F1D5F39,
+ 0xAFE85F5E,
+ 0xFFDFDF96,
+ 0xCB9FAF7D,
+ 0x5FC1AFED,
+ 0x8C1C5FC1,
+ 0xAFDD5FC3,
+ 0xDF9A7EFD,
+ 0xB0B25FB2,
+ 0xFFFEABAD,
+ 0x5FB2FFFE,
+ 0x5FCE600B,
+ 0xE6BB600B,
+ 0x5FCEDFC6,
+ 0x27FBEFDF,
+ 0x5FC8CFDE,
+ 0x3A9CE7C0,
+ 0xEDF0F3C8,
+ 0x7F0154CD,
+ 0x7F1D2D3D,
+ 0x363A7570,
+ 0x7E0AF1CE,
+ 0x37EF2E68,
+ 0x7FEE10EC,
+ 0xADF8EFDE,
+ 0xCFEAE52F,
+ 0x7D0FE12B,
+ 0xF1CE5F65,
+ 0x7E0A4DF8,
+ 0xCFEA5F72,
+ 0x7D0BEFEE,
+ 0xCFEA5F74,
+ 0xE522EFDE,
+ 0x5F74CFDA,
+ 0x0B627385,
+ 0xDF627E0A,
+ 0x30D8145B,
+ 0xBFFFF3C8,
+ 0x5FFFDFFF,
+ 0xA7F85F5E,
+ 0xBFFE7F7D,
+ 0x10D31450,
+ 0x5F36BFFF,
+ 0xAF785F5E,
+ 0xBFFDA7F8,
+ 0x5F36BFFE,
+ 0x77FD30C0,
+ 0x4E08FDCF,
+ 0xE5FF6E0F,
+ 0xAFF87E1F,
+ 0x7E0FFD1F,
+ 0xF1CF5F1B,
+ 0xABF80D5E,
+ 0x5F5EFFEF,
+ 0x79F730A2,
+ 0xAFDD5F34,
+ 0x47F85F34,
+ 0xAFED7FDD,
+ 0x50B24978,
+ 0x47FD7F1D,
+ 0x7DFD70AD,
+ 0xEF717EC1,
+ 0x6BA47F01,
+ 0x2D267EFD,
+ 0x30DE5F5E,
+ 0xFFFD5F5E,
+ 0xFFEF5F5E,
+ 0xFFDF0CA0,
+ 0xAFED0A9E,
+ 0xAFDD0C3A,
+ 0x5F3AAFBD,
+ 0x7FBDB082,
+ 0x5F8247F8
+};
+
+uint patch_2f00[] = {
+ 0x3E303430,
+ 0x34343737,
+ 0xABF7BF9B,
+ 0x994B4FBD,
+ 0xBD599493,
+ 0x349FFF37,
+ 0xFB9B177D,
+ 0xD9936956,
+ 0xBBFDD697,
+ 0xBDD2FD11,
+ 0x31DB9BB3,
+ 0x63139637,
+ 0x93733693,
+ 0x193137F7,
+ 0x331737AF,
+ 0x7BB9B999,
+ 0xBB197957,
+ 0x7FDFD3D5,
+ 0x73B773F7,
+ 0x37933B99,
+ 0x1D115316,
+ 0x99315315,
+ 0x31694BF4,
+ 0xFBDBD359,
+ 0x31497353,
+ 0x76956D69,
+ 0x7B9D9693,
+ 0x13131979,
+ 0x79376935
+};
+#endif
+
+/*
+ * I2C/SPI/SMC1 relocation patch arrays.
+ */
+
+#ifdef CONFIG_I2C_SPI_SMC1_UCODE_PATCH
+
+uint patch_2000[] = {
+ 0x3fff0000,
+ 0x3ffd0000,
+ 0x3ffb0000,
+ 0x3ff90000,
+ 0x5f13eff8,
+ 0x5eb5eff8,
+ 0x5f88adf7,
+ 0x5fefadf7,
+ 0x3a9cfbc8,
+ 0x77cae1bb,
+ 0xf4de7fad,
+ 0xabae9330,
+ 0x4e08fdcf,
+ 0x6e0faff8,
+ 0x7ccf76cf,
+ 0xfdaff9cf,
+ 0xabf88dc8,
+ 0xab5879f7,
+ 0xb0925d8d,
+ 0xdfd079f7,
+ 0xb090e6bb,
+ 0xe5bbe74f,
+ 0x9e046f0f,
+ 0x6ffb76ce,
+ 0xee0cf9cf,
+ 0x2bfbefef,
+ 0xcfeef9cf,
+ 0x76cead23,
+ 0x90b3df99,
+ 0x7fddd0c1,
+ 0x4bf847fd,
+ 0x7ccf76ce,
+ 0xcfef77ca,
+ 0x7eaf7fad,
+ 0x7dfdf0b7,
+ 0xef7a7fca,
+ 0x77cafbc8,
+ 0x6079e722,
+ 0xfbc85fff,
+ 0xdfff5fb3,
+ 0xfffbfbc8,
+ 0xf3c894a5,
+ 0xe7c9edf9,
+ 0x7f9a7fad,
+ 0x5f36afe8,
+ 0x5f5bffdf,
+ 0xdf95cb9e,
+ 0xaf7d5fc3,
+ 0xafed8c1b,
+ 0x5fc3afdd,
+ 0x5fc5df99,
+ 0x7efdb0b3,
+ 0x5fb3fffe,
+ 0xabae5fb3,
+ 0xfffe5fd0,
+ 0x600be6bb,
+ 0x600b5fd0,
+ 0xdfc827fb,
+ 0xefdf5fca,
+ 0xcfde3a9c,
+ 0xe7c9edf9,
+ 0xf3c87f9e,
+ 0x54ca7fed,
+ 0x2d3a3637,
+ 0x756f7e9a,
+ 0xf1ce37ef,
+ 0x2e677fee,
+ 0x10ebadf8,
+ 0xefdecfea,
+ 0xe52f7d9f,
+ 0xe12bf1ce,
+ 0x5f647e9a,
+ 0x4df8cfea,
+ 0x5f717d9b,
+ 0xefeecfea,
+ 0x5f73e522,
+ 0xefde5f73,
+ 0xcfda0b61,
+ 0x5d8fdf61,
+ 0xe7c9edf9,
+ 0x7e9a30d5,
+ 0x1458bfff,
+ 0xf3c85fff,
+ 0xdfffa7f8,
+ 0x5f5bbffe,
+ 0x7f7d10d0,
+ 0x144d5f33,
+ 0xbfffaf78,
+ 0x5f5bbffd,
+ 0xa7f85f33,
+ 0xbffe77fd,
+ 0x30bd4e08,
+ 0xfdcfe5ff,
+ 0x6e0faff8,
+ 0x7eef7e9f,
+ 0xfdeff1cf,
+ 0x5f17abf8,
+ 0x0d5b5f5b,
+ 0xffef79f7,
+ 0x309eafdd,
+ 0x5f3147f8,
+ 0x5f31afed,
+ 0x7fdd50af,
+ 0x497847fd,
+ 0x7f9e7fed,
+ 0x7dfd70a9,
+ 0xef7e7ece,
+ 0x6ba07f9e,
+ 0x2d227efd,
+ 0x30db5f5b,
+ 0xfffd5f5b,
+ 0xffef5f5b,
+ 0xffdf0c9c,
+ 0xafed0a9a,
+ 0xafdd0c37,
+ 0x5f37afbd,
+ 0x7fbdb081,
+ 0x5f8147f8,
+ 0x3a11e710,
+ 0xedf0ccdd,
+ 0xf3186d0a,
+ 0x7f0e5f06,
+ 0x7fedbb38,
+ 0x3afe7468,
+ 0x7fedf4fc,
+ 0x8ffbb951,
+ 0xb85f77fd,
+ 0xb0df5ddd,
+ 0xdefe7fed,
+ 0x90e1e74d,
+ 0x6f0dcbf7,
+ 0xe7decfed,
+ 0xcb74cfed,
+ 0xcfeddf6d,
+ 0x91714f74,
+ 0x5dd2deef,
+ 0x9e04e7df,
+ 0xefbb6ffb,
+ 0xe7ef7f0e,
+ 0x9e097fed,
+ 0xebdbeffa,
+ 0xeb54affb,
+ 0x7fea90d7,
+ 0x7e0cf0c3,
+ 0xbffff318,
+ 0x5fffdfff,
+ 0xac59efea,
+ 0x7fce1ee5,
+ 0xe2ff5ee1,
+ 0xaffbe2ff,
+ 0x5ee3affb,
+ 0xf9cc7d0f,
+ 0xaef8770f,
+ 0x7d0fb0c6,
+ 0xeffbbfff,
+ 0xcfef5ede,
+ 0x7d0fbfff,
+ 0x5ede4cf8,
+ 0x7fddd0bf,
+ 0x49f847fd,
+ 0x7efdf0bb,
+ 0x7fedfffd,
+ 0x7dfdf0b7,
+ 0xef7e7e1e,
+ 0x5ede7f0e,
+ 0x3a11e710,
+ 0xedf0ccab,
+ 0xfb18ad2e,
+ 0x1ea9bbb8,
+ 0x74283b7e,
+ 0x73c2e4bb,
+ 0x2ada4fb8,
+ 0xdc21e4bb,
+ 0xb2a1ffbf,
+ 0x5e2c43f8,
+ 0xfc87e1bb,
+ 0xe74ffd91,
+ 0x6f0f4fe8,
+ 0xc7ba32e2,
+ 0xf396efeb,
+ 0x600b4f78,
+ 0xe5bb760b,
+ 0x53acaef8,
+ 0x4ef88b0e,
+ 0xcfef9e09,
+ 0xabf8751f,
+ 0xefef5bac,
+ 0x741f4fe8,
+ 0x751e760d,
+ 0x7fdbf081,
+ 0x741cafce,
+ 0xefcc7fce,
+ 0x751e70ac,
+ 0x741ce7bb,
+ 0x3372cfed,
+ 0xafdbefeb,
+ 0xe5bb760b,
+ 0x53f2aef8,
+ 0xafe8e7eb,
+ 0x4bf8771e,
+ 0x7e247fed,
+ 0x4fcbe2cc,
+ 0x7fbc30a9,
+ 0x7b0f7a0f,
+ 0x34d577fd,
+ 0x308b5db7,
+ 0xde553e5f,
+ 0xaf78741f,
+ 0x741f30f0,
+ 0xcfef5e2c,
+ 0x741f3eac,
+ 0xafb8771e,
+ 0x5e677fed,
+ 0x0bd3e2cc,
+ 0x741ccfec,
+ 0xe5ca53cd,
+ 0x6fcb4f74,
+ 0x5dadde4b,
+ 0x2ab63d38,
+ 0x4bb3de30,
+ 0x751f741c,
+ 0x6c42effa,
+ 0xefea7fce,
+ 0x6ffc30be,
+ 0xefec3fca,
+ 0x30b3de2e,
+ 0xadf85d9e,
+ 0xaf7daefd,
+ 0x5d9ede2e,
+ 0x5d9eafdd,
+ 0x761f10ac,
+ 0x1da07efd,
+ 0x30adfffe,
+ 0x4908fb18,
+ 0x5fffdfff,
+ 0xafbb709b,
+ 0x4ef85e67,
+ 0xadf814ad,
+ 0x7a0f70ad,
+ 0xcfef50ad,
+ 0x7a0fde30,
+ 0x5da0afed,
+ 0x3c12780f,
+ 0xefef780f,
+ 0xefef790f,
+ 0xa7f85e0f,
+ 0xffef790f,
+ 0xefef790f,
+ 0x14adde2e,
+ 0x5d9eadfd,
+ 0x5e2dfffb,
+ 0xe79addfd,
+ 0xeff96079,
+ 0x607ae79a,
+ 0xddfceff9,
+ 0x60795dff,
+ 0x607acfef,
+ 0xefefefdf,
+ 0xefbfef7f,
+ 0xeeffedff,
+ 0xebffe7ff,
+ 0xafefafdf,
+ 0xafbfaf7f,
+ 0xaeffadff,
+ 0xabffa7ff,
+ 0x6fef6fdf,
+ 0x6fbf6f7f,
+ 0x6eff6dff,
+ 0x6bff67ff,
+ 0x2fef2fdf,
+ 0x2fbf2f7f,
+ 0x2eff2dff,
+ 0x2bff27ff,
+ 0x4e08fd1f,
+ 0xe5ff6e0f,
+ 0xaff87eef,
+ 0x7e0ffdef,
+ 0xf11f6079,
+ 0xabf8f542,
+ 0x7e0af11c,
+ 0x37cfae3a,
+ 0x7fec90be,
+ 0xadf8efdc,
+ 0xcfeae52f,
+ 0x7d0fe12b,
+ 0xf11c6079,
+ 0x7e0a4df8,
+ 0xcfea5dc4,
+ 0x7d0befec,
+ 0xcfea5dc6,
+ 0xe522efdc,
+ 0x5dc6cfda,
+ 0x4e08fd1f,
+ 0x6e0faff8,
+ 0x7c1f761f,
+ 0xfdeff91f,
+ 0x6079abf8,
+ 0x761cee24,
+ 0xf91f2bfb,
+ 0xefefcfec,
+ 0xf91f6079,
+ 0x761c27fb,
+ 0xefdf5da7,
+ 0xcfdc7fdd,
+ 0xd09c4bf8,
+ 0x47fd7c1f,
+ 0x761ccfcf,
+ 0x7eef7fed,
+ 0x7dfdf093,
+ 0xef7e7f1e,
+ 0x771efb18,
+ 0x6079e722,
+ 0xe6bbe5bb,
+ 0xae0ae5bb,
+ 0x600bae85,
+ 0xe2bbe2bb,
+ 0xe2bbe2bb,
+ 0xaf02e2bb,
+ 0xe2bb2ff9,
+ 0x6079e2bb
+};
+
+uint patch_2f00[] = {
+ 0x30303030,
+ 0x3e3e3434,
+ 0xabbf9b99,
+ 0x4b4fbdbd,
+ 0x59949334,
+ 0x9fff37fb,
+ 0x9b177dd9,
+ 0x936956bb,
+ 0xfbdd697b,
+ 0xdd2fd113,
+ 0x1db9f7bb,
+ 0x36313963,
+ 0x79373369,
+ 0x3193137f,
+ 0x7331737a,
+ 0xf7bb9b99,
+ 0x9bb19795,
+ 0x77fdfd3d,
+ 0x573b773f,
+ 0x737933f7,
+ 0xb991d115,
+ 0x31699315,
+ 0x31531694,
+ 0xbf4fbdbd,
+ 0x35931497,
+ 0x35376956,
+ 0xbd697b9d,
+ 0x96931313,
+ 0x19797937,
+ 0x6935af78,
+ 0xb9b3baa3,
+ 0xb8788683,
+ 0x368f78f7,
+ 0x87778733,
+ 0x3ffffb3b,
+ 0x8e8f78b8,
+ 0x1d118e13,
+ 0xf3ff3f8b,
+ 0x6bd8e173,
+ 0xd1366856,
+ 0x68d1687b,
+ 0x3daf78b8,
+ 0x3a3a3f87,
+ 0x8f81378f,
+ 0xf876f887,
+ 0x77fd8778,
+ 0x737de8d6,
+ 0xbbf8bfff,
+ 0xd8df87f7,
+ 0xfd876f7b,
+ 0x8bfff8bd,
+ 0x8683387d,
+ 0xb873d87b,
+ 0x3b8fd7f8,
+ 0xf7338883,
+ 0xbb8ee1f8,
+ 0xef837377,
+ 0x3337b836,
+ 0x817d11f8,
+ 0x7378b878,
+ 0xd3368b7d,
+ 0xed731b7d,
+ 0x833731f3,
+ 0xf22f3f23
+};
+
+uint patch_2e00[] = {
+ 0x27eeeeee,
+ 0xeeeeeeee,
+ 0xeeeeeeee,
+ 0xeeeeeeee,
+ 0xee4bf4fb,
+ 0xdbd259bb,
+ 0x1979577f,
+ 0xdfd2d573,
+ 0xb773f737,
+ 0x4b4fbdbd,
+ 0x25b9b177,
+ 0xd2d17376,
+ 0x956bbfdd,
+ 0x697bdd2f,
+ 0xff9f79ff,
+ 0xff9ff22f
+};
+#endif
+
+/*
+ * USB SOF patch arrays.
+ */
+
+#ifdef CONFIG_USB_SOF_UCODE_PATCH
+
+uint patch_2000[] = {
+ 0x7fff0000,
+ 0x7ffd0000,
+ 0x7ffb0000,
+ 0x49f7ba5b,
+ 0xba383ffb,
+ 0xf9b8b46d,
+ 0xe5ab4e07,
+ 0xaf77bffe,
+ 0x3f7bbf79,
+ 0xba5bba38,
+ 0xe7676076,
+ 0x60750000
+};
+
+uint patch_2f00[] = {
+ 0x3030304c,
+ 0xcab9e441,
+ 0xa1aaf220
+};
+#endif
+
+void
+cpm_load_patch(volatile immap_t *immr)
+{
+ volatile uint *dp; /* Dual-ported RAM. */
+ volatile cpm8xx_t *commproc;
+ volatile iic_t *iip;
+ volatile spi_t *spp;
+ volatile smc_uart_t *smp;
+ int i;
+
+ commproc = (cpm8xx_t *)&immr->im_cpm;
+
+#ifdef CONFIG_USB_SOF_UCODE_PATCH
+ commproc->cp_rccr = 0;
+
+ dp = (uint *)(commproc->cp_dpmem);
+ for (i=0; i<(sizeof(patch_2000)/4); i++)
+ *dp++ = patch_2000[i];
+
+ dp = (uint *)&(commproc->cp_dpmem[0x0f00]);
+ for (i=0; i<(sizeof(patch_2f00)/4); i++)
+ *dp++ = patch_2f00[i];
+
+ commproc->cp_rccr = 0x0009;
+
+ printk("USB SOF microcode patch installed\n");
+#endif /* CONFIG_USB_SOF_UCODE_PATCH */
+
+#if defined(CONFIG_I2C_SPI_UCODE_PATCH) || \
+ defined(CONFIG_I2C_SPI_SMC1_UCODE_PATCH)
+
+ commproc->cp_rccr = 0;
+
+ dp = (uint *)(commproc->cp_dpmem);
+ for (i=0; i<(sizeof(patch_2000)/4); i++)
+ *dp++ = patch_2000[i];
+
+ dp = (uint *)&(commproc->cp_dpmem[0x0f00]);
+ for (i=0; i<(sizeof(patch_2f00)/4); i++)
+ *dp++ = patch_2f00[i];
+
+ iip = (iic_t *)&commproc->cp_dparam[PROFF_IIC];
+# define RPBASE 0x0500
+ iip->iic_rpbase = RPBASE;
+
+ /* Put SPI above the IIC, also 32-byte aligned.
+ */
+ i = (RPBASE + sizeof(iic_t) + 31) & ~31;
+ spp = (spi_t *)&commproc->cp_dparam[PROFF_SPI];
+ spp->spi_rpbase = i;
+
+# if defined(CONFIG_I2C_SPI_UCODE_PATCH)
+ commproc->cp_cpmcr1 = 0x802a;
+ commproc->cp_cpmcr2 = 0x8028;
+ commproc->cp_cpmcr3 = 0x802e;
+ commproc->cp_cpmcr4 = 0x802c;
+ commproc->cp_rccr = 1;
+
+ printk("I2C/SPI microcode patch installed.\n");
+# endif /* CONFIG_I2C_SPI_UCODE_PATCH */
+
+# if defined(CONFIG_I2C_SPI_SMC1_UCODE_PATCH)
+
+ dp = (uint *)&(commproc->cp_dpmem[0x0e00]);
+ for (i=0; i<(sizeof(patch_2e00)/4); i++)
+ *dp++ = patch_2e00[i];
+
+ commproc->cp_cpmcr1 = 0x8080;
+ commproc->cp_cpmcr2 = 0x808a;
+ commproc->cp_cpmcr3 = 0x8028;
+ commproc->cp_cpmcr4 = 0x802a;
+ commproc->cp_rccr = 3;
+
+ smp = (smc_uart_t *)&commproc->cp_dparam[PROFF_SMC1];
+ smp->smc_rpbase = 0x1FC0;
+
+ printk("I2C/SPI/SMC1 microcode patch installed.\n");
+# endif /* CONFIG_I2C_SPI_SMC1_UCODE_PATCH) */
+
+#endif /* some variation of the I2C/SPI patch was selected */
+}
+
+/*
+ * Take this entire routine out, since no one calls it and its
+ * logic is suspect.
+ */
+
+#if 0
+void
+verify_patch(volatile immap_t *immr)
+{
+ volatile uint *dp;
+ volatile cpm8xx_t *commproc;
+ int i;
+
+ commproc = (cpm8xx_t *)&immr->im_cpm;
+
+ printk("cp_rccr %x\n", commproc->cp_rccr);
+ commproc->cp_rccr = 0;
+
+ dp = (uint *)(commproc->cp_dpmem);
+ for (i=0; i<(sizeof(patch_2000)/4); i++)
+ if (*dp++ != patch_2000[i]) {
+ printk("patch_2000 bad at %d\n", i);
+ dp--;
+ printk("found 0x%X, wanted 0x%X\n", *dp, patch_2000[i]);
+ break;
+ }
+
+ dp = (uint *)&(commproc->cp_dpmem[0x0f00]);
+ for (i=0; i<(sizeof(patch_2f00)/4); i++)
+ if (*dp++ != patch_2f00[i]) {
+ printk("patch_2f00 bad at %d\n", i);
+ dp--;
+ printk("found 0x%X, wanted 0x%X\n", *dp, patch_2f00[i]);
+ break;
+ }
+
+ commproc->cp_rccr = 0x0009;
+}
+#endif
diff --git a/arch/ppc/Kconfig b/arch/ppc/Kconfig
new file mode 100644
index 0000000..813c6c9
--- /dev/null
+++ b/arch/ppc/Kconfig
@@ -0,0 +1,1317 @@
+# For a description of the syntax of this configuration file,
+# see Documentation/kbuild/kconfig-language.txt.
+#
+
+mainmenu "Linux/PowerPC Kernel Configuration"
+
+config MMU
+ bool
+ default y
+
+config UID16
+ bool
+
+config GENERIC_HARDIRQS
+ bool
+ default y
+
+config RWSEM_GENERIC_SPINLOCK
+ bool
+
+config RWSEM_XCHGADD_ALGORITHM
+ bool
+ default y
+
+config GENERIC_CALIBRATE_DELAY
+ bool
+ default y
+
+config HAVE_DEC_LOCK
+ bool
+ default y
+
+config PPC
+ bool
+ default y
+
+config PPC32
+ bool
+ default y
+
+# All PPCs use generic nvram driver through ppc_md
+config GENERIC_NVRAM
+ bool
+ default y
+
+source "init/Kconfig"
+
+menu "Processor"
+
+choice
+ prompt "Processor Type"
+ default 6xx
+
+config 6xx
+ bool "6xx/7xx/74xx/52xx/82xx/83xx"
+ help
+ There are four types of PowerPC chips supported. The more common
+ types (601, 603, 604, 740, 750, 7400), the Motorola embedded
+ versions (821, 823, 850, 855, 860, 52xx, 82xx, 83xx), the IBM embedded
+ versions (403 and 405) and the high end 64 bit Power processors
+ (POWER 3, POWER4, and IBM 970 also known as G5)
+ Unless you are building a kernel for one of the embedded processor
+ systems, 64 bit IBM RS/6000 or an Apple G5, choose 6xx.
+ Note that the kernel runs in 32-bit mode even on 64-bit chips.
+ Also note that because the 52xx, 82xx, & 83xx family has a 603e core,
+ specific support for that chipset is asked later on.
+
+config 40x
+ bool "40x"
+
+config 44x
+ bool "44x"
+
+config POWER3
+ bool "POWER3"
+
+config POWER4
+ bool "POWER4 and 970 (G5)"
+
+config 8xx
+ depends on BROKEN
+ bool "8xx"
+
+config E500
+ bool "e500"
+
+endchoice
+
+config BOOKE
+ bool
+ depends on E500
+ default y
+
+config FSL_BOOKE
+ bool
+ depends on E500
+ default y
+
+config PTE_64BIT
+ bool
+ depends on 44x
+ default y
+
+config PHYS_64BIT
+ bool
+ depends on 44x
+ default y
+
+config ALTIVEC
+ bool "AltiVec Support"
+ depends on 6xx || POWER4
+ depends on !8260 && !83xx
+ ---help---
+ This option enables kernel support for the Altivec extensions to the
+ PowerPC processor. The kernel currently supports saving and restoring
+ altivec registers, and turning on the 'altivec enable' bit so user
+ processes can execute altivec instructions.
+
+ This option is only usefully if you have a processor that supports
+ altivec (G4, otherwise known as 74xx series), but does not have
+ any affect on a non-altivec cpu (it does, however add code to the
+ kernel).
+
+ If in doubt, say Y here.
+
+config SPE
+ bool "SPE Support"
+ depends on E500
+ ---help---
+ This option enables kernel support for the Signal Processing
+ Extensions (SPE) to the PowerPC processor. The kernel currently
+ supports saving and restoring SPE registers, and turning on the
+ 'spe enable' bit so user processes can execute SPE instructions.
+
+ This option is only usefully if you have a processor that supports
+ SPE (e500, otherwise known as 85xx series), but does not have any
+ affect on a non-spe cpu (it does, however add code to the kernel).
+
+ If in doubt, say Y here.
+
+config TAU
+ bool "Thermal Management Support"
+ depends on 6xx && !8260 && !83xx
+ help
+ G3 and G4 processors have an on-chip temperature sensor called the
+ 'Thermal Assist Unit (TAU)', which, in theory, can measure the on-die
+ temperature within 2-4 degrees Celsius. This option shows the current
+ on-die temperature in /proc/cpuinfo if the cpu supports it.
+
+ Unfortunately, on some chip revisions, this sensor is very inaccurate
+ and in some cases, does not work at all, so don't assume the cpu
+ temp is actually what /proc/cpuinfo says it is.
+
+config TAU_INT
+ bool "Interrupt driven TAU driver (DANGEROUS)"
+ depends on TAU
+ ---help---
+ The TAU supports an interrupt driven mode which causes an interrupt
+ whenever the temperature goes out of range. This is the fastest way
+ to get notified the temp has exceeded a range. With this option off,
+ a timer is used to re-check the temperature periodically.
+
+ However, on some cpus it appears that the TAU interrupt hardware
+ is buggy and can cause a situation which would lead unexplained hard
+ lockups.
+
+ Unless you are extending the TAU driver, or enjoy kernel/hardware
+ debugging, leave this option off.
+
+config TAU_AVERAGE
+ bool "Average high and low temp"
+ depends on TAU
+ ---help---
+ The TAU hardware can compare the temperature to an upper and lower
+ bound. The default behavior is to show both the upper and lower
+ bound in /proc/cpuinfo. If the range is large, the temperature is
+ either changing a lot, or the TAU hardware is broken (likely on some
+ G4's). If the range is small (around 4 degrees), the temperature is
+ relatively stable. If you say Y here, a single temperature value,
+ halfway between the upper and lower bounds, will be reported in
+ /proc/cpuinfo.
+
+ If in doubt, say N here.
+
+config MATH_EMULATION
+ bool "Math emulation"
+ depends on 4xx || 8xx || E500
+ ---help---
+ Some PowerPC chips designed for embedded applications do not have
+ a floating-point unit and therefore do not implement the
+ floating-point instructions in the PowerPC instruction set. If you
+ say Y here, the kernel will include code to emulate a floating-point
+ unit, which will allow programs that use floating-point
+ instructions to run.
+
+ If you have an Apple machine or an IBM RS/6000 or pSeries machine,
+ or any machine with a 6xx, 7xx or 7xxx series processor, say N
+ here. Saying Y here will not hurt performance (on any machine) but
+ will increase the size of the kernel.
+
+source "drivers/cpufreq/Kconfig"
+
+config CPU_FREQ_PMAC
+ bool "Support for Apple PowerBooks"
+ depends on CPU_FREQ && ADB_PMU
+ select CPU_FREQ_TABLE
+ help
+ This adds support for frequency switching on Apple PowerBooks,
+ this currently includes some models of iBook & Titanium
+ PowerBook.
+
+config PPC601_SYNC_FIX
+ bool "Workarounds for PPC601 bugs"
+ depends on 6xx && (PPC_PREP || PPC_PMAC)
+ help
+ Some versions of the PPC601 (the first PowerPC chip) have bugs which
+ mean that extra synchronization instructions are required near
+ certain instructions, typically those that make major changes to the
+ CPU state. These extra instructions reduce performance slightly.
+ If you say N here, these extra instructions will not be included,
+ resulting in a kernel which will run faster but may not run at all
+ on some systems with the PPC601 chip.
+
+ If in doubt, say Y here.
+
+source arch/ppc/platforms/4xx/Kconfig
+source arch/ppc/platforms/85xx/Kconfig
+
+config PPC64BRIDGE
+ bool
+ depends on POWER3 || POWER4
+ default y
+
+config PPC_STD_MMU
+ bool
+ depends on 6xx || POWER3 || POWER4
+ default y
+
+config NOT_COHERENT_CACHE
+ bool
+ depends on 4xx || 8xx
+ default y
+
+endmenu
+
+menu "Platform options"
+
+choice
+ prompt "8xx Machine Type"
+ depends on 8xx
+ default RPXLITE
+
+config RPXLITE
+ bool "RPX-Lite"
+ ---help---
+ Single-board computers based around the PowerPC MPC8xx chips and
+ intended for embedded applications. The following types are
+ supported:
+
+ RPX-Lite:
+ Embedded Planet RPX Lite. PC104 form-factor SBC based on the MPC823.
+
+ RPX-Classic:
+ Embedded Planet RPX Classic Low-fat. Credit-card-size SBC based on
+ the MPC 860
+
+ BSE-IP:
+ Bright Star Engineering ip-Engine.
+
+ TQM823L:
+ TQM850L:
+ TQM855L:
+ TQM860L:
+ MPC8xx based family of mini modules, half credit card size,
+ up to 64 MB of RAM, 8 MB Flash, (Fast) Ethernet, 2 x serial ports,
+ 2 x CAN bus interface, ...
+ Manufacturer: TQ Components, www.tq-group.de
+ Date of Release: October (?) 1999
+ End of Life: not yet :-)
+ URL:
+ - module: <http://www.denx.de/PDF/TQM8xxLHWM201.pdf>
+ - starter kit: <http://www.denx.de/PDF/STK8xxLHWM201.pdf>
+ - images: <http://www.denx.de/embedded-ppc-en.html>
+
+ FPS850L:
+ FingerPrint Sensor System (based on TQM850L)
+ Manufacturer: IKENDI AG, <http://www.ikendi.com/>
+ Date of Release: November 1999
+ End of life: end 2000 ?
+ URL: see TQM850L
+
+ SPD823TS:
+ MPC823 based board used in the "Tele Server" product
+ Manufacturer: Speech Design, <http://www.speech-design.de/>
+ Date of Release: Mid 2000 (?)
+ End of life: -
+ URL: <http://www.speech-design.de/>
+ select "English", then "Teleteam Solutions", then "TeleServer"
+
+ IVMS8:
+ MPC860 based board used in the "Integrated Voice Mail System",
+ Small Version (8 voice channels)
+ Manufacturer: Speech Design, <http://www.speech-design.de/>
+ Date of Release: December 2000 (?)
+ End of life: -
+ URL: <http://www.speech-design.de/>
+
+ IVML24:
+ MPC860 based board used in the "Integrated Voice Mail System",
+ Large Version (24 voice channels)
+ Manufacturer: Speech Design, <http://www.speech-design.de/>
+ Date of Release: March 2001 (?)
+ End of life: -
+ URL: <http://www.speech-design.de/>
+
+ SM850:
+ Service Module (based on TQM850L)
+ Manufacturer: Dependable Computer Systems, <http://www.decomsys.com/>
+ Date of Release: end 2000 (?)
+ End of life: mid 2001 (?)
+ URL: <http://www.tz-mikroelektronik.de/ServiceModule/index.html>
+
+ HERMES:
+ Hermes-Pro ISDN/LAN router with integrated 8 x hub
+ Manufacturer: Multidata Gesellschaft fur Datentechnik und Informatik
+ <http://www.multidata.de/>
+ Date of Release: 2000 (?)
+ End of life: -
+ URL: <http://www.multidata.de/english/products/hpro.htm>
+
+ IP860:
+ VMEBus IP (Industry Pack) carrier board with MPC860
+ Manufacturer: MicroSys GmbH, <http://www.microsys.de/>
+ Date of Release: ?
+ End of life: -
+ URL: <http://www.microsys.de/html/ip860.html>
+
+ PCU_E:
+ PCU = Peripheral Controller Unit, Extended
+ Manufacturer: Siemens AG, ICN (Information and Communication Networks)
+ <http://www.siemens.de/page/1,3771,224315-1-999_2_226207-0,00.html>
+ Date of Release: April 2001
+ End of life: August 2001
+ URL: n. a.
+
+config RPXCLASSIC
+ bool "RPX-Classic"
+ help
+ The RPX-Classic is a single-board computer based on the Motorola
+ MPC860. It features 16MB of DRAM and a variable amount of flash,
+ I2C EEPROM, thermal monitoring, a PCMCIA slot, a DIP switch and two
+ LEDs. Variants with Ethernet ports exist. Say Y here to support it
+ directly.
+
+config BSEIP
+ bool "BSE-IP"
+ help
+ Say Y here to support the Bright Star Engineering ipEngine SBC.
+ This is a credit-card-sized device featuring a MPC823 processor,
+ 26MB DRAM, 4MB flash, Ethernet, a 16K-gate FPGA, USB, an LCD/video
+ controller, and two RS232 ports.
+
+config FADS
+ bool "FADS"
+
+config TQM823L
+ bool "TQM823L"
+ help
+ Say Y here to support the TQM823L, one of an MPC8xx-based family of
+ mini SBCs (half credit-card size) from TQ Components first released
+ in late 1999. Technical references are at
+ <http://www.denx.de/PDF/TQM8xxLHWM201.pdf>, and
+ <http://www.denx.de/PDF/STK8xxLHWM201.pdf>, and an image at
+ <http://www.denx.de/embedded-ppc-en.html>.
+
+config TQM850L
+ bool "TQM850L"
+ help
+ Say Y here to support the TQM850L, one of an MPC8xx-based family of
+ mini SBCs (half credit-card size) from TQ Components first released
+ in late 1999. Technical references are at
+ <http://www.denx.de/PDF/TQM8xxLHWM201.pdf>, and
+ <http://www.denx.de/PDF/STK8xxLHWM201.pdf>, and an image at
+ <http://www.denx.de/embedded-ppc-en.html>.
+
+config TQM855L
+ bool "TQM855L"
+ help
+ Say Y here to support the TQM855L, one of an MPC8xx-based family of
+ mini SBCs (half credit-card size) from TQ Components first released
+ in late 1999. Technical references are at
+ <http://www.denx.de/PDF/TQM8xxLHWM201.pdf>, and
+ <http://www.denx.de/PDF/STK8xxLHWM201.pdf>, and an image at
+ <http://www.denx.de/embedded-ppc-en.html>.
+
+config TQM860L
+ bool "TQM860L"
+ help
+ Say Y here to support the TQM860L, one of an MPC8xx-based family of
+ mini SBCs (half credit-card size) from TQ Components first released
+ in late 1999. Technical references are at
+ <http://www.denx.de/PDF/TQM8xxLHWM201.pdf>, and
+ <http://www.denx.de/PDF/STK8xxLHWM201.pdf>, and an image at
+ <http://www.denx.de/embedded-ppc-en.html>.
+
+config FPS850L
+ bool "FPS850L"
+
+config SPD823TS
+ bool "SPD823TS"
+ help
+ Say Y here to support the Speech Design 823 Tele-Server from Speech
+ Design, released in 2000. The manufacturer's website is at
+ <http://www.speech-design.de/>.
+
+config IVMS8
+ bool "IVMS8"
+ help
+ Say Y here to support the Integrated Voice-Mail Small 8-channel SBC
+ from Speech Design, released March 2001. The manufacturer's website
+ is at <http://www.speech-design.de/>.
+
+config IVML24
+ bool "IVML24"
+ help
+ Say Y here to support the Integrated Voice-Mail Large 24-channel SBC
+ from Speech Design, released March 2001. The manufacturer's website
+ is at <http://www.speech-design.de/>.
+
+config SM850
+ bool "SM850"
+ help
+ Say Y here to support the Service Module 850 from Dependable
+ Computer Systems, an SBC based on the TQM850L module by TQ
+ Components. This board is no longer in production. The
+ manufacturer's website is at <http://www.decomsys.com/>.
+
+config HERMES_PRO
+ bool "HERMES"
+
+config IP860
+ bool "IP860"
+
+config LWMON
+ bool "LWMON"
+
+config PCU_E
+ bool "PCU_E"
+
+config CCM
+ bool "CCM"
+
+config LANTEC
+ bool "LANTEC"
+
+config MBX
+ bool "MBX"
+ help
+ MBX is a line of Motorola single-board computer based around the
+ MPC821 and MPC860 processors, and intended for embedded-controller
+ applications. Say Y here to support these boards directly.
+
+config WINCEPT
+ bool "WinCept"
+ help
+ The Wincept 100/110 is a Motorola single-board computer based on the
+ MPC821 PowerPC, introduced in 1998 and designed to be used in
+ thin-client machines. Say Y to support it directly.
+
+endchoice
+
+choice
+ prompt "Machine Type"
+ depends on 6xx || POWER3 || POWER4
+ default PPC_MULTIPLATFORM
+ ---help---
+ Linux currently supports several different kinds of PowerPC-based
+ machines: Apple Power Macintoshes and clones (such as the Motorola
+ Starmax series), PReP (PowerPC Reference Platform) machines (such
+ as the Motorola PowerStacks, Motorola cPCI/VME embedded systems,
+ and some IBM RS/6000 systems), CHRP (Common Hardware Reference
+ Platform) machines (including all of the recent IBM RS/6000 and
+ pSeries machines), and several embedded PowerPC systems containing
+ 4xx, 6xx, 7xx, 8xx, 74xx, and 82xx processors. Currently, the
+ default option is to build a kernel which works on the first three.
+
+ Select CHRP/PowerMac/PReP if configuring for an IBM RS/6000 or
+ pSeries machine, a Power Macintosh (including iMacs, iBooks and
+ Powerbooks), or a PReP machine.
+
+ Select Gemini if configuring for a Synergy Microsystems' Gemini
+ series Single Board Computer. More information is available at:
+ <http://www.synergymicro.com/PressRel/97_10_15.html>.
+
+ Select APUS if configuring for a PowerUP Amiga. More information is
+ available at: <http://linux-apus.sourceforge.net/>.
+
+config PPC_MULTIPLATFORM
+ bool "CHRP/PowerMac/PReP"
+
+config APUS
+ bool "Amiga-APUS"
+ help
+ Select APUS if configuring for a PowerUP Amiga.
+ More information is available at:
+ <http://linux-apus.sourceforge.net/>.
+
+config KATANA
+ bool "Artesyn-Katana"
+ help
+ Select KATANA if configuring an Artesyn KATANA 750i or 3750
+ cPCI board.
+
+config WILLOW
+ bool "Cogent-Willow"
+
+config CPCI690
+ bool "Force-CPCI690"
+ help
+ Select CPCI690 if configuring a Force CPCI690 cPCI board.
+
+config PCORE
+ bool "Force-PowerCore"
+
+config POWERPMC250
+ bool "Force-PowerPMC250"
+
+config CHESTNUT
+ bool "IBM 750FX Eval board or 750GX Eval board"
+ help
+ Select CHESTNUT if configuring an IBM 750FX Eval Board or a
+ IBM 750GX Eval board.
+
+config SPRUCE
+ bool "IBM-Spruce"
+
+config HDPU
+ bool "Sky-HDPU"
+ help
+ Select HDPU if configuring a Sky Computers Compute Blade.
+
+config HDPU_FEATURES
+ depends HDPU
+ tristate "HDPU-Features"
+ help
+ Select to enable HDPU enhanced features.
+
+config EV64260
+ bool "Marvell-EV64260BP"
+ help
+ Select EV64260 if configuring a Marvell (formerly Galileo)
+ EV64260BP Evaluation platform.
+
+config LOPEC
+ bool "Motorola-LoPEC"
+
+config MCPN765
+ bool "Motorola-MCPN765"
+
+config MVME5100
+ bool "Motorola-MVME5100"
+
+config PPLUS
+ bool "Motorola-PowerPlus"
+
+config PRPMC750
+ bool "Motorola-PrPMC750"
+
+config PRPMC800
+ bool "Motorola-PrPMC800"
+
+config SANDPOINT
+ bool "Motorola-Sandpoint"
+ help
+ Select SANDPOINT if configuring for a Motorola Sandpoint X3
+ (any flavor).
+
+config RADSTONE_PPC7D
+ bool "Radstone Technology PPC7D board"
+
+config ADIR
+ bool "SBS-Adirondack"
+
+config K2
+ bool "SBS-K2"
+
+config PAL4
+ bool "SBS-Palomar4"
+
+config GEMINI
+ bool "Synergy-Gemini"
+ help
+ Select Gemini if configuring for a Synergy Microsystems' Gemini
+ series Single Board Computer. More information is available at:
+ <http://www.synergymicro.com/PressRel/97_10_15.html>.
+
+config EST8260
+ bool "EST8260"
+ ---help---
+ The EST8260 is a single-board computer manufactured by Wind River
+ Systems, Inc. (formerly Embedded Support Tools Corp.) and based on
+ the MPC8260. Wind River Systems has a website at
+ <http://www.windriver.com/>, but the EST8260 cannot be found on it
+ and has probably been discontinued or rebadged.
+
+config SBC82xx
+ bool "SBC82xx"
+ ---help---
+ SBC PowerQUICC II, single-board computer with MPC82xx CPU
+ Manufacturer: Wind River Systems, Inc.
+ Date of Release: May 2003
+ End of Life: -
+ URL: <http://www.windriver.com/>
+
+config SBS8260
+ bool "SBS8260"
+
+config RPX8260
+ bool "RPXSUPER"
+
+config TQM8260
+ bool "TQM8260"
+ ---help---
+ MPC8260 based module, little larger than credit card,
+ up to 128 MB global + 64 MB local RAM, 32 MB Flash,
+ 32 kB EEPROM, 256 kB L@ Cache, 10baseT + 100baseT Ethernet,
+ 2 x serial ports, ...
+ Manufacturer: TQ Components, www.tq-group.de
+ Date of Release: June 2001
+ End of Life: not yet :-)
+ URL: <http://www.denx.de/PDF/TQM82xx_SPEC_Rev005.pdf>
+
+config ADS8272
+ bool "ADS8272"
+
+config PQ2FADS
+ bool "Freescale-PQ2FADS"
+ help
+ Select PQ2FADS if you wish to configure for a Freescale
+ PQ2FADS board (-VR or -ZU).
+
+config LITE5200
+ bool "Freescale LITE5200 / (IceCube)"
+ select PPC_MPC52xx
+ help
+ Support for the LITE5200 dev board for the MPC5200 from Freescale.
+ This is for the LITE5200 version 2.0 board. Don't know if it changes
+ much but it's only been tested on this board version. I think this
+ board is also known as IceCube.
+
+config MPC834x_SYS
+ bool "Freescale MPC834x SYS"
+ help
+ This option enables support for the MPC 834x SYS evaluation board.
+
+endchoice
+
+config PQ2ADS
+ bool
+ depends on ADS8272
+ default y
+
+config TQM8xxL
+ bool
+ depends on 8xx && (TQM823L || TQM850L || FPS850L || TQM855L || TQM860L || SM850)
+ default y
+
+config EMBEDDEDBOOT
+ bool
+ depends on 8xx || 8260
+ default y
+
+config PPC_MPC52xx
+ bool
+
+config 8260
+ bool "CPM2 Support" if WILLOW
+ depends on 6xx
+ default y if TQM8260 || RPX8260 || EST8260 || SBS8260 || SBC82xx || PQ2FADS
+ help
+ The MPC8260 is a typical embedded CPU made by Motorola. Selecting
+ this option means that you wish to build a kernel for a machine with
+ an 8260 class CPU.
+
+config 8272
+ bool
+ depends on 6xx
+ default y if ADS8272
+ select 8260
+ help
+ The MPC8272 CPM has a different internal dpram setup than other CPM2
+ devices
+
+config 83xx
+ bool
+ default y if MPC834x_SYS
+
+config MPC834x
+ bool
+ default y if MPC834x_SYS
+
+config CPM2
+ bool
+ depends on 8260 || MPC8560 || MPC8555
+ default y
+ help
+ The CPM2 (Communications Processor Module) is a coprocessor on
+ embedded CPUs made by Motorola. Selecting this option means that
+ you wish to build a kernel for a machine with a CPM2 coprocessor
+ on it (826x, 827x, 8560).
+
+config PPC_CHRP
+ bool
+ depends on PPC_MULTIPLATFORM
+ default y
+
+config PPC_PMAC
+ bool
+ depends on PPC_MULTIPLATFORM
+ default y
+
+config PPC_PMAC64
+ bool
+ depends on PPC_PMAC && POWER4
+ default y
+
+config PPC_PREP
+ bool
+ depends on PPC_MULTIPLATFORM
+ default y
+
+config PPC_OF
+ bool
+ depends on PPC_PMAC || PPC_CHRP
+ default y
+
+config PPC_GEN550
+ bool
+ depends on SANDPOINT || MCPN765 || SPRUCE || PPLUS || PCORE || \
+ PRPMC750 || K2 || PRPMC800 || LOPEC || \
+ (EV64260 && !SERIAL_MPSC) || CHESTNUT || RADSTONE_PPC7D || \
+ 83xx
+ default y
+
+config FORCE
+ bool
+ depends on 6xx && (PCORE || POWERPMC250)
+ default y
+
+config GT64260
+ bool
+ depends on EV64260 || CPCI690
+ default y
+
+config MV64360 # Really MV64360 & MV64460
+ bool
+ depends on CHESTNUT || KATANA || RADSTONE_PPC7D || HDPU
+ default y
+
+config MV64X60
+ bool
+ depends on (GT64260 || MV64360)
+ default y
+
+menu "Set bridge options"
+ depends on MV64X60
+
+config NOT_COHERENT_CACHE
+ bool "Turn off Cache Coherency"
+ default n
+ help
+ Some 64x60 bridges lock up when trying to enforce cache coherency.
+ When this option is selected, cache coherency will be turned off.
+ Note that this can cause other problems (e.g., stale data being
+ speculatively loaded via a cached mapping). Use at your own risk.
+
+config MV64X60_BASE
+ hex "Set bridge base used by firmware"
+ default "0xf1000000"
+ help
+ A firmware can leave the base address of the bridge's registers at
+ a non-standard location. If so, set this value to reflect the
+ address of that non-standard location.
+
+config MV64X60_NEW_BASE
+ hex "Set bridge base used by kernel"
+ default "0xf1000000"
+ help
+ If the current base address of the bridge's registers is not where
+ you want it, set this value to the address that you want it moved to.
+
+endmenu
+
+config NONMONARCH_SUPPORT
+ bool "Enable Non-Monarch Support"
+ depends on PRPMC800
+
+config HARRIER
+ bool
+ depends on PRPMC800
+ default y
+
+config EPIC_SERIAL_MODE
+ bool
+ depends on 6xx && (LOPEC || SANDPOINT)
+ default y
+
+config MPC10X_BRIDGE
+ bool
+ depends on PCORE || POWERPMC250 || LOPEC || SANDPOINT
+ default y
+
+config FSL_OCP
+ bool
+ depends on MPC10X_BRIDGE
+ default y
+
+config MPC10X_OPENPIC
+ bool
+ depends on POWERPMC250 || LOPEC || SANDPOINT
+ default y
+
+config MPC10X_STORE_GATHERING
+ bool "Enable MPC10x store gathering"
+ depends on MPC10X_BRIDGE
+
+config CPC710_DATA_GATHERING
+ bool "Enable CPC710 data gathering"
+ depends on K2
+
+config HARRIER_STORE_GATHERING
+ bool "Enable Harrier store gathering"
+ depends on HARRIER
+
+config MVME5100_IPMC761_PRESENT
+ bool "MVME5100 configured with an IPMC761"
+ depends on MVME5100
+
+config SPRUCE_BAUD_33M
+ bool "Spruce baud clock support"
+ depends on SPRUCE
+
+config PC_KEYBOARD
+ bool "PC PS/2 style Keyboard"
+ depends on 4xx || CPM2
+
+config PPCBUG_NVRAM
+ bool "Enable reading PPCBUG NVRAM during boot" if PPLUS || LOPEC
+ default y if PPC_PREP
+
+config SMP
+ bool "Symmetric multi-processing support"
+ ---help---
+ This enables support for systems with more than one CPU. If you have
+ a system with only one CPU, say N. If you have a system with more
+ than one CPU, say Y. Note that the kernel does not currently
+ support SMP machines with 603/603e/603ev or PPC750 ("G3") processors
+ since they have inadequate hardware support for multiprocessor
+ operation.
+
+ If you say N here, the kernel will run on single and multiprocessor
+ machines, but will use only one CPU of a multiprocessor machine. If
+ you say Y here, the kernel will run on single-processor machines.
+ On a single-processor machine, the kernel will run faster if you say
+ N here.
+
+ If you don't know what to do here, say N.
+
+config IRQ_ALL_CPUS
+ bool "Distribute interrupts on all CPUs by default"
+ depends on SMP
+ help
+ This option gives the kernel permission to distribute IRQs across
+ multiple CPUs. Saying N here will route all IRQs to the first
+ CPU. Generally saying Y is safe, although some problems have been
+ reported with SMP Power Macintoshes with this option enabled.
+
+config NR_CPUS
+ int "Maximum number of CPUs (2-32)"
+ range 2 32
+ depends on SMP
+ default "4"
+
+config PREEMPT
+ bool "Preemptible Kernel"
+ help
+ This option reduces the latency of the kernel when reacting to
+ real-time or interactive events by allowing a low priority process to
+ be preempted even if it is in kernel mode executing a system call.
+
+ Say Y here if you are building a kernel for a desktop, embedded
+ or real-time system. Say N if you are unsure.
+
+config HIGHMEM
+ bool "High memory support"
+
+source "fs/Kconfig.binfmt"
+
+config PROC_DEVICETREE
+ bool "Support for Open Firmware device tree in /proc"
+ depends on PPC_OF && PROC_FS
+ help
+ This option adds a device-tree directory under /proc which contains
+ an image of the device tree that the kernel copies from Open
+ Firmware. If unsure, say Y here.
+
+config PREP_RESIDUAL
+ bool "Support for PReP Residual Data"
+ depends on PPC_PREP
+ help
+ Some PReP systems have residual data passed to the kernel by the
+ firmware. This allows detection of memory size, devices present and
+ other useful pieces of information. Sometimes this information is
+ not present or incorrect, in which case it could lead to the machine
+ behaving incorrectly. If this happens, either disable PREP_RESIDUAL
+ or pass the 'noresidual' option to the kernel.
+
+ If you are running a PReP system, say Y here, otherwise say N.
+
+config PROC_PREPRESIDUAL
+ bool "Support for reading of PReP Residual Data in /proc"
+ depends on PREP_RESIDUAL && PROC_FS
+ help
+ Enabling this option will create a /proc/residual file which allows
+ you to get at the residual data on PReP systems. You will need a tool
+ (lsresidual) to parse it. If you aren't on a PReP system, you don't
+ want this.
+
+config CMDLINE_BOOL
+ bool "Default bootloader kernel arguments"
+
+config CMDLINE
+ string "Initial kernel command string"
+ depends on CMDLINE_BOOL
+ default "console=ttyS0,9600 console=tty0 root=/dev/sda2"
+ help
+ On some platforms, there is currently no way for the boot loader to
+ pass arguments to the kernel. For these platforms, you can supply
+ some command-line options at build time by entering them here. In
+ most cases you will need to specify the root device here.
+
+config AMIGA
+ bool
+ depends on APUS
+ default y
+ help
+ This option enables support for the Amiga series of computers.
+
+config ZORRO
+ bool
+ depends on APUS
+ default y
+ help
+ This enables support for the Zorro bus in the Amiga. If you have
+ expansion cards in your Amiga that conform to the Amiga
+ AutoConfig(tm) specification, say Y, otherwise N. Note that even
+ expansion cards that do not fit in the Zorro slots but fit in e.g.
+ the CPU slot may fall in this category, so you have to say Y to let
+ Linux use these.
+
+config ABSTRACT_CONSOLE
+ bool
+ depends on APUS
+ default y
+
+config APUS_FAST_EXCEPT
+ bool
+ depends on APUS
+ default y
+
+config AMIGA_PCMCIA
+ bool "Amiga 1200/600 PCMCIA support"
+ depends on APUS && EXPERIMENTAL
+ help
+ Include support in the kernel for pcmcia on Amiga 1200 and Amiga
+ 600. If you intend to use pcmcia cards say Y; otherwise say N.
+
+config AMIGA_BUILTIN_SERIAL
+ tristate "Amiga builtin serial support"
+ depends on APUS
+ help
+ If you want to use your Amiga's built-in serial port in Linux,
+ answer Y.
+
+ To compile this driver as a module, choose M here.
+
+config GVPIOEXT
+ tristate "GVP IO-Extender support"
+ depends on APUS
+ help
+ If you want to use a GVP IO-Extender serial card in Linux, say Y.
+ Otherwise, say N.
+
+config GVPIOEXT_LP
+ tristate "GVP IO-Extender parallel printer support"
+ depends on GVPIOEXT
+ help
+ Say Y to enable driving a printer from the parallel port on your
+ GVP IO-Extender card, N otherwise.
+
+config GVPIOEXT_PLIP
+ tristate "GVP IO-Extender PLIP support"
+ depends on GVPIOEXT
+ help
+ Say Y to enable doing IP over the parallel port on your GVP
+ IO-Extender card, N otherwise.
+
+config MULTIFACE_III_TTY
+ tristate "Multiface Card III serial support"
+ depends on APUS
+ help
+ If you want to use a Multiface III card's serial port in Linux,
+ answer Y.
+
+ To compile this driver as a module, choose M here.
+
+config A2232
+ tristate "Commodore A2232 serial support (EXPERIMENTAL)"
+ depends on EXPERIMENTAL && APUS
+ ---help---
+ This option supports the 2232 7-port serial card shipped with the
+ Amiga 2000 and other Zorro-bus machines, dating from 1989. At
+ a max of 19,200 bps, the ports are served by a 6551 ACIA UART chip
+ each, plus a 8520 CIA, and a master 6502 CPU and buffer as well. The
+ ports were connected with 8 pin DIN connectors on the card bracket,
+ for which 8 pin to DB25 adapters were supplied. The card also had
+ jumpers internally to toggle various pinning configurations.
+
+ This driver can be built as a module; but then "generic_serial"
+ will also be built as a module. This has to be loaded before
+ "ser_a2232". If you want to do this, answer M here.
+
+config WHIPPET_SERIAL
+ tristate "Hisoft Whippet PCMCIA serial support"
+ depends on AMIGA_PCMCIA
+ help
+ HiSoft has a web page at <http://www.hisoft.co.uk/>, but there
+ is no listing for the Whippet in their Amiga section.
+
+config APNE
+ tristate "PCMCIA NE2000 support"
+ depends on AMIGA_PCMCIA
+ help
+ If you have a PCMCIA NE2000 compatible adapter, say Y. Otherwise,
+ say N.
+
+ To compile this driver as a module, choose M here: the
+ module will be called apne.
+
+config SERIAL_CONSOLE
+ bool "Support for serial port console"
+ depends on APUS && (AMIGA_BUILTIN_SERIAL=y || GVPIOEXT=y || MULTIFACE_III_TTY=y)
+
+config HEARTBEAT
+ bool "Use power LED as a heartbeat"
+ depends on APUS
+ help
+ Use the power-on LED on your machine as a load meter. The exact
+ behavior is platform-dependent, but normally the flash frequency is
+ a hyperbolic function of the 5-minute load average.
+
+config PROC_HARDWARE
+ bool "/proc/hardware support"
+ depends on APUS
+
+source "drivers/zorro/Kconfig"
+
+source kernel/power/Kconfig
+
+endmenu
+
+menu "Bus options"
+
+config ISA
+ bool "Support for ISA-bus hardware"
+ depends on PPC_PREP || PPC_CHRP
+ help
+ Find out whether you have ISA slots on your motherboard. ISA is the
+ name of a bus system, i.e. the way the CPU talks to the other stuff
+ inside your box. If you have an Apple machine, say N here; if you
+ have an IBM RS/6000 or pSeries machine or a PReP machine, say Y. If
+ you have an embedded board, consult your board documentation.
+
+config GENERIC_ISA_DMA
+ bool
+ depends on POWER3 || POWER4 || 6xx && !CPM2
+ default y
+
+config EISA
+ bool
+ help
+ The Extended Industry Standard Architecture (EISA) bus is a bus
+ architecture used on some older intel-based PCs.
+
+config SBUS
+ bool
+
+# Yes MCA RS/6000s exist but Linux-PPC does not currently support any
+config MCA
+ bool
+
+config PCI
+ bool "PCI support" if 40x || CPM2 || 83xx || 85xx || PPC_MPC52xx
+ default y if !40x && !CPM2 && !8xx && !APUS && !83xx && !85xx
+ default PCI_PERMEDIA if !4xx && !CPM2 && !8xx && APUS
+ default PCI_QSPAN if !4xx && !CPM2 && 8xx
+ help
+ Find out whether your system includes a PCI bus. PCI is the name of
+ a bus system, i.e. the way the CPU talks to the other stuff inside
+ your box. If you say Y here, the kernel will include drivers and
+ infrastructure code to support PCI bus devices.
+
+config PCI_DOMAINS
+ bool
+ default PCI
+
+config PCI_QSPAN
+ bool "QSpan PCI"
+ depends on !4xx && !CPM2 && 8xx
+ help
+ Say Y here if you have a system based on a Motorola 8xx-series
+ embedded processor with a QSPAN PCI interface, otherwise say N.
+
+config PCI_8260
+ bool
+ depends on PCI && 8260 && !8272
+ default y
+
+config 8260_PCI9
+ bool " Enable workaround for MPC826x erratum PCI 9"
+ depends on PCI_8260
+ default y
+
+choice
+ prompt " IDMA channel for PCI 9 workaround"
+ depends on 8260_PCI9
+
+config 8260_PCI9_IDMA1
+ bool "IDMA1"
+
+config 8260_PCI9_IDMA2
+ bool "IDMA2"
+
+config 8260_PCI9_IDMA3
+ bool "IDMA3"
+
+config 8260_PCI9_IDMA4
+ bool "IDMA4"
+
+endchoice
+
+config PCI_PERMEDIA
+ bool "PCI for Permedia2"
+ depends on !4xx && !8xx && APUS
+
+source "drivers/pci/Kconfig"
+
+source "drivers/pcmcia/Kconfig"
+
+endmenu
+
+menu "Advanced setup"
+
+config ADVANCED_OPTIONS
+ bool "Prompt for advanced kernel configuration options"
+ help
+ This option will enable prompting for a variety of advanced kernel
+ configuration options. These options can cause the kernel to not
+ work if they are set incorrectly, but can be used to optimize certain
+ aspects of kernel memory management.
+
+ Unless you know what you are doing, say N here.
+
+comment "Default settings for advanced configuration options are used"
+ depends on !ADVANCED_OPTIONS
+
+config HIGHMEM_START_BOOL
+ bool "Set high memory pool address"
+ depends on ADVANCED_OPTIONS && HIGHMEM
+ help
+ This option allows you to set the base address of the kernel virtual
+ area used to map high memory pages. This can be useful in
+ optimizing the layout of kernel virtual memory.
+
+ Say N here unless you know what you are doing.
+
+config HIGHMEM_START
+ hex "Virtual start address of high memory pool" if HIGHMEM_START_BOOL
+ default "0xfe000000"
+
+config LOWMEM_SIZE_BOOL
+ bool "Set maximum low memory"
+ depends on ADVANCED_OPTIONS
+ help
+ This option allows you to set the maximum amount of memory which
+ will be used as "low memory", that is, memory which the kernel can
+ access directly, without having to set up a kernel virtual mapping.
+ This can be useful in optimizing the layout of kernel virtual
+ memory.
+
+ Say N here unless you know what you are doing.
+
+config LOWMEM_SIZE
+ hex "Maximum low memory size (in bytes)" if LOWMEM_SIZE_BOOL
+ default "0x30000000"
+
+config KERNEL_START_BOOL
+ bool "Set custom kernel base address"
+ depends on ADVANCED_OPTIONS
+ help
+ This option allows you to set the kernel virtual address at which
+ the kernel will map low memory (the kernel image will be linked at
+ this address). This can be useful in optimizing the virtual memory
+ layout of the system.
+
+ Say N here unless you know what you are doing.
+
+config KERNEL_START
+ hex "Virtual address of kernel base" if KERNEL_START_BOOL
+ default "0xc0000000"
+
+config TASK_SIZE_BOOL
+ bool "Set custom user task size"
+ depends on ADVANCED_OPTIONS
+ help
+ This option allows you to set the amount of virtual address space
+ allocated to user tasks. This can be useful in optimizing the
+ virtual memory layout of the system.
+
+ Say N here unless you know what you are doing.
+
+config TASK_SIZE
+ hex "Size of user task space" if TASK_SIZE_BOOL
+ default "0x80000000"
+
+config CONSISTENT_START_BOOL
+ bool "Set custom consistent memory pool address"
+ depends on ADVANCED_OPTIONS && NOT_COHERENT_CACHE
+ help
+ This option allows you to set the base virtual address
+ of the the consistent memory pool. This pool of virtual
+ memory is used to make consistent memory allocations.
+
+config CONSISTENT_START
+ hex "Base virtual address of consistent memory pool" if CONSISTENT_START_BOOL
+ default "0xff100000" if NOT_COHERENT_CACHE
+
+config CONSISTENT_SIZE_BOOL
+ bool "Set custom consistent memory pool size"
+ depends on ADVANCED_OPTIONS && NOT_COHERENT_CACHE
+ help
+ This option allows you to set the size of the the
+ consistent memory pool. This pool of virtual memory
+ is used to make consistent memory allocations.
+
+config CONSISTENT_SIZE
+ hex "Size of consistent memory pool" if CONSISTENT_SIZE_BOOL
+ default "0x00200000" if NOT_COHERENT_CACHE
+
+config BOOT_LOAD_BOOL
+ bool "Set the boot link/load address"
+ depends on ADVANCED_OPTIONS && !PPC_MULTIPLATFORM
+ help
+ This option allows you to set the initial load address of the zImage
+ or zImage.initrd file. This can be useful if you are on a board
+ which has a small amount of memory.
+
+ Say N here unless you know what you are doing.
+
+config BOOT_LOAD
+ hex "Link/load address for booting" if BOOT_LOAD_BOOL
+ default "0x00400000" if 40x || 8xx || 8260
+ default "0x01000000" if 44x
+ default "0x00800000"
+
+config PIN_TLB
+ bool "Pinned Kernel TLBs (860 ONLY)"
+ depends on ADVANCED_OPTIONS && 8xx
+endmenu
+
+source "drivers/Kconfig"
+
+source "fs/Kconfig"
+
+source "arch/ppc/8xx_io/Kconfig"
+
+source "arch/ppc/8260_io/Kconfig"
+
+
+menu "IBM 40x options"
+ depends on 40x
+
+config SERIAL_SICC
+ bool "SICC Serial port"
+ depends on STB03xxx
+
+config UART1_DFLT_CONSOLE
+ bool
+ depends on SERIAL_SICC && UART0_TTYS1
+ default y
+
+config SERIAL_SICC_CONSOLE
+ bool
+ depends on SERIAL_SICC && UART0_TTYS1
+ default y
+
+endmenu
+
+source "lib/Kconfig"
+
+source "arch/ppc/oprofile/Kconfig"
+
+source "arch/ppc/Kconfig.debug"
+
+source "security/Kconfig"
+
+source "crypto/Kconfig"
diff --git a/arch/ppc/Kconfig.debug b/arch/ppc/Kconfig.debug
new file mode 100644
index 0000000..d2e1eea
--- /dev/null
+++ b/arch/ppc/Kconfig.debug
@@ -0,0 +1,72 @@
+menu "Kernel hacking"
+
+source "lib/Kconfig.debug"
+
+config KGDB
+ bool "Include kgdb kernel debugger"
+ depends on DEBUG_KERNEL && (BROKEN || PPC_GEN550 || 4xx)
+ select DEBUG_INFO
+ help
+ Include in-kernel hooks for kgdb, the Linux kernel source level
+ debugger. See <http://kgdb.sourceforge.net/> for more information.
+ Unless you are intending to debug the kernel, say N here.
+
+choice
+ prompt "Serial Port"
+ depends on KGDB
+ default KGDB_TTYS1
+
+config KGDB_TTYS0
+ bool "ttyS0"
+
+config KGDB_TTYS1
+ bool "ttyS1"
+
+config KGDB_TTYS2
+ bool "ttyS2"
+
+config KGDB_TTYS3
+ bool "ttyS3"
+
+endchoice
+
+config KGDB_CONSOLE
+ bool "Enable serial console thru kgdb port"
+ depends on KGDB && 8xx || CPM2
+ help
+ If you enable this, all serial console messages will be sent
+ over the gdb stub.
+ If unsure, say N.
+
+config XMON
+ bool "Include xmon kernel debugger"
+ depends on DEBUG_KERNEL
+ help
+ Include in-kernel hooks for the xmon kernel monitor/debugger.
+ Unless you are intending to debug the kernel, say N here.
+
+config BDI_SWITCH
+ bool "Include BDI-2000 user context switcher"
+ depends on DEBUG_KERNEL
+ help
+ Include in-kernel support for the Abatron BDI2000 debugger.
+ Unless you are intending to debug the kernel with one of these
+ machines, say N here.
+
+config BOOTX_TEXT
+ bool "Support for early boot text console (BootX or OpenFirmware only)"
+ depends PPC_OF
+ help
+ Say Y here to see progress messages from the boot firmware in text
+ mode. Requires either BootX or Open Firmware.
+
+config SERIAL_TEXT_DEBUG
+ bool "Support for early boot texts over serial port"
+ depends on 4xx || GT64260 || LOPEC || PPLUS || PRPMC800 || PPC_GEN550 || PPC_MPC52xx
+
+config PPC_OCP
+ bool
+ depends on IBM_OCP || FSL_OCP || XILINX_OCP
+ default y
+
+endmenu
diff --git a/arch/ppc/Makefile b/arch/ppc/Makefile
new file mode 100644
index 0000000..73cbdda
--- /dev/null
+++ b/arch/ppc/Makefile
@@ -0,0 +1,138 @@
+# This file is included by the global makefile so that you can add your own
+# architecture-specific flags and dependencies.
+#
+# This file is subject to the terms and conditions of the GNU General Public
+# License. See the file "COPYING" in the main directory of this archive
+# for more details.
+#
+# Copyright (C) 1994 by Linus Torvalds
+# Changes for PPC by Gary Thomas
+# Rewritten by Cort Dougan and Paul Mackerras
+#
+
+# This must match PAGE_OFFSET in include/asm-ppc/page.h.
+KERNELLOAD := $(CONFIG_KERNEL_START)
+
+HAS_BIARCH := $(call cc-option-yn, -m32)
+ifeq ($(HAS_BIARCH),y)
+AS := $(AS) -a32
+LD := $(LD) -m elf32ppc
+CC := $(CC) -m32
+endif
+
+LDFLAGS_vmlinux := -Ttext $(KERNELLOAD) -Bstatic
+CPPFLAGS += -Iarch/$(ARCH)
+AFLAGS += -Iarch/$(ARCH)
+CFLAGS += -Iarch/$(ARCH) -msoft-float -pipe \
+ -ffixed-r2 -mmultiple
+CPP = $(CC) -E $(CFLAGS)
+
+CHECKFLAGS += -D__powerpc__
+
+ifndef CONFIG_E500
+CFLAGS += -mstring
+endif
+
+cpu-as-$(CONFIG_PPC64BRIDGE) += -Wa,-mppc64bridge
+cpu-as-$(CONFIG_4xx) += -Wa,-m405
+cpu-as-$(CONFIG_6xx) += -Wa,-maltivec
+cpu-as-$(CONFIG_POWER4) += -Wa,-maltivec
+cpu-as-$(CONFIG_E500) += -Wa,-me500
+
+AFLAGS += $(cpu-as-y)
+CFLAGS += $(cpu-as-y)
+
+# Default to the common case.
+KBUILD_DEFCONFIG := common_defconfig
+
+head-y := arch/ppc/kernel/head.o
+head-$(CONFIG_8xx) := arch/ppc/kernel/head_8xx.o
+head-$(CONFIG_4xx) := arch/ppc/kernel/head_4xx.o
+head-$(CONFIG_44x) := arch/ppc/kernel/head_44x.o
+head-$(CONFIG_FSL_BOOKE) := arch/ppc/kernel/head_fsl_booke.o
+
+head-$(CONFIG_6xx) += arch/ppc/kernel/idle_6xx.o
+head-$(CONFIG_POWER4) += arch/ppc/kernel/idle_power4.o
+
+core-y += arch/ppc/kernel/ arch/ppc/platforms/ \
+ arch/ppc/mm/ arch/ppc/lib/ arch/ppc/syslib/
+core-$(CONFIG_4xx) += arch/ppc/platforms/4xx/
+core-$(CONFIG_83xx) += arch/ppc/platforms/83xx/
+core-$(CONFIG_85xx) += arch/ppc/platforms/85xx/
+core-$(CONFIG_MATH_EMULATION) += arch/ppc/math-emu/
+core-$(CONFIG_XMON) += arch/ppc/xmon/
+core-$(CONFIG_APUS) += arch/ppc/amiga/
+drivers-$(CONFIG_8xx) += arch/ppc/8xx_io/
+drivers-$(CONFIG_4xx) += arch/ppc/4xx_io/
+drivers-$(CONFIG_CPM2) += arch/ppc/8260_io/
+
+drivers-$(CONFIG_OPROFILE) += arch/ppc/oprofile/
+
+BOOT_TARGETS = zImage zImage.initrd znetboot znetboot.initrd vmlinux.sm
+
+.PHONY: $(BOOT_TARGETS)
+
+all: uImage zImage
+
+CPPFLAGS_vmlinux.lds := -Upowerpc
+
+# All the instructions talk about "make bzImage".
+bzImage: zImage
+
+boot := arch/$(ARCH)/boot
+
+$(BOOT_TARGETS): vmlinux
+ $(Q)$(MAKE) $(build)=$(boot) $@
+
+uImage: vmlinux
+ $(Q)$(MAKE) $(build)=$(boot)/images $(boot)/images/$@
+
+define archhelp
+ @echo '* zImage - Compressed kernel image (arch/$(ARCH)/boot/images/zImage.*)'
+ @echo ' uImage - Create a bootable image for U-Boot / PPCBoot'
+ @echo ' install - Install kernel using'
+ @echo ' (your) ~/bin/installkernel or'
+ @echo ' (distribution) /sbin/installkernel or'
+ @echo ' install to $$(INSTALL_PATH) and run lilo'
+ @echo ' *_defconfig - Select default config from arch/$(ARCH)/ppc/configs'
+endef
+
+archclean:
+ $(Q)$(MAKE) $(clean)=arch/ppc/boot
+
+prepare: include/asm-$(ARCH)/offsets.h checkbin
+
+arch/$(ARCH)/kernel/asm-offsets.s: include/asm include/linux/version.h \
+ include/config/MARKER
+
+include/asm-$(ARCH)/offsets.h: arch/$(ARCH)/kernel/asm-offsets.s
+ $(call filechk,gen-asm-offsets)
+
+# Use the file '.tmp_gas_check' for binutils tests, as gas won't output
+# to stdout and these checks are run even on install targets.
+TOUT := .tmp_gas_check
+# Ensure this is binutils 2.12.1 (or 2.12.90.0.7) or later for altivec
+# instructions.
+# gcc-3.4 and binutils-2.14 are a fatal combination.
+GCC_VERSION := $(call cc-version)
+
+checkbin:
+ @if test "$(GCC_VERSION)" = "0304" ; then \
+ if ! /bin/echo mftb 5 | $(AS) -v -mppc -many -o $(TOUT) >/dev/null 2>&1 ; then \
+ echo -n '*** ${VERSION}.${PATCHLEVEL} kernels no longer build '; \
+ echo 'correctly with gcc-3.4 and your version of binutils.'; \
+ echo '*** Please upgrade your binutils or downgrade your gcc'; \
+ false; \
+ fi ; \
+ fi
+ @if ! /bin/echo dssall | $(AS) -many -o $(TOUT) >/dev/null 2>&1 ; then \
+ echo -n '*** ${VERSION}.${PATCHLEVEL} kernels no longer build ' ; \
+ echo 'correctly with old versions of binutils.' ; \
+ echo '*** Please upgrade your binutils to 2.12.1 or newer' ; \
+ false ; \
+ fi
+
+CLEAN_FILES += include/asm-$(ARCH)/offsets.h \
+ arch/$(ARCH)/kernel/asm-offsets.s \
+ $(TOUT)
+
diff --git a/arch/ppc/amiga/Makefile b/arch/ppc/amiga/Makefile
new file mode 100644
index 0000000..59fec0a
--- /dev/null
+++ b/arch/ppc/amiga/Makefile
@@ -0,0 +1,8 @@
+#
+# Makefile for Linux arch/m68k/amiga source directory
+#
+
+obj-y := config.o amiints.o cia.o time.o bootinfo.o amisound.o \
+ chipram.o amiga_ksyms.o
+
+obj-$(CONFIG_AMIGA_PCMCIA) += pcmcia.o
diff --git a/arch/ppc/amiga/amiga_ksyms.c b/arch/ppc/amiga/amiga_ksyms.c
new file mode 100644
index 0000000..ec74e5b
--- /dev/null
+++ b/arch/ppc/amiga/amiga_ksyms.c
@@ -0,0 +1 @@
+#include "../../m68k/amiga/amiga_ksyms.c"
diff --git a/arch/ppc/amiga/amiints.c b/arch/ppc/amiga/amiints.c
new file mode 100644
index 0000000..91195e2
--- /dev/null
+++ b/arch/ppc/amiga/amiints.c
@@ -0,0 +1,323 @@
+/*
+ * arch/ppc/amiga/amiints.c -- Amiga Linux interrupt handling code
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file COPYING in the main directory of this archive
+ * for more details.
+ *
+ * 11/07/96: rewritten interrupt handling, irq lists are exists now only for
+ * this sources where it makes sense (VERTB/PORTS/EXTER) and you must
+ * be careful that dev_id for this sources is unique since this the
+ * only possibility to distinguish between different handlers for
+ * free_irq. irq lists also have different irq flags:
+ * - IRQ_FLG_FAST: handler is inserted at top of list (after other
+ * fast handlers)
+ * - IRQ_FLG_SLOW: handler is inserted at bottom of list and before
+ * they're executed irq level is set to the previous
+ * one, but handlers don't need to be reentrant, if
+ * reentrance occurred, slow handlers will be just
+ * called again.
+ * The whole interrupt handling for CIAs is moved to cia.c
+ * /Roman Zippel
+ *
+ * 07/08/99: rewamp of the interrupt handling - we now have two types of
+ * interrupts, normal and fast handlers, fast handlers being
+ * marked with SA_INTERRUPT and runs with all other interrupts
+ * disabled. Normal interrupts disable their own source but
+ * run with all other interrupt sources enabled.
+ * PORTS and EXTER interrupts are always shared even if the
+ * drivers do not explicitly mark this when calling
+ * request_irq which they really should do.
+ * This is similar to the way interrupts are handled on all
+ * other architectures and makes a ton of sense besides
+ * having the advantage of making it easier to share
+ * drivers.
+ * /Jes
+ */
+
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/kernel_stat.h>
+#include <linux/init.h>
+
+#include <asm/system.h>
+#include <asm/irq.h>
+#include <asm/traps.h>
+#include <asm/amigahw.h>
+#include <asm/amigaints.h>
+#include <asm/amipcmcia.h>
+
+#ifdef CONFIG_APUS
+#include <asm/amigappc.h>
+#endif
+
+extern void cia_init_IRQ(struct ciabase *base);
+
+unsigned short ami_intena_vals[AMI_STD_IRQS] = {
+ IF_VERTB, IF_COPER, IF_AUD0, IF_AUD1, IF_AUD2, IF_AUD3, IF_BLIT,
+ IF_DSKSYN, IF_DSKBLK, IF_RBF, IF_TBE, IF_SOFT, IF_PORTS, IF_EXTER
+};
+static const unsigned char ami_servers[AMI_STD_IRQS] = {
+ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1
+};
+
+static short ami_ablecount[AMI_IRQS];
+
+static void ami_badint(int irq, void *dev_id, struct pt_regs *fp)
+{
+/* num_spurious += 1;*/
+}
+
+/*
+ * void amiga_init_IRQ(void)
+ *
+ * Parameters: None
+ *
+ * Returns: Nothing
+ *
+ * This function should be called during kernel startup to initialize
+ * the amiga IRQ handling routines.
+ */
+
+__init
+void amiga_init_IRQ(void)
+{
+ int i;
+
+ for (i = 0; i < AMI_IRQS; i++)
+ ami_ablecount[i] = 0;
+
+ /* turn off PCMCIA interrupts */
+ if (AMIGAHW_PRESENT(PCMCIA))
+ gayle.inten = GAYLE_IRQ_IDE;
+
+ /* turn off all interrupts... */
+ custom.intena = 0x7fff;
+ custom.intreq = 0x7fff;
+
+#ifdef CONFIG_APUS
+ /* Clear any inter-CPU interrupt requests. Circumvents bug in
+ Blizzard IPL emulation HW (or so it appears). */
+ APUS_WRITE(APUS_INT_LVL, INTLVL_SETRESET | INTLVL_MASK);
+
+ /* Init IPL emulation. */
+ APUS_WRITE(APUS_REG_INT, REGINT_INTMASTER | REGINT_ENABLEIPL);
+ APUS_WRITE(APUS_IPL_EMU, IPLEMU_DISABLEINT);
+ APUS_WRITE(APUS_IPL_EMU, IPLEMU_SETRESET | IPLEMU_IPLMASK);
+#endif
+ /* ... and enable the master interrupt bit */
+ custom.intena = IF_SETCLR | IF_INTEN;
+
+ cia_init_IRQ(&ciaa_base);
+ cia_init_IRQ(&ciab_base);
+}
+
+/*
+ * Enable/disable a particular machine specific interrupt source.
+ * Note that this may affect other interrupts in case of a shared interrupt.
+ * This function should only be called for a _very_ short time to change some
+ * internal data, that may not be changed by the interrupt at the same time.
+ * ami_(enable|disable)_irq calls may also be nested.
+ */
+
+void amiga_enable_irq(unsigned int irq)
+{
+ if (irq >= AMI_IRQS) {
+ printk("%s: Unknown IRQ %d\n", __FUNCTION__, irq);
+ return;
+ }
+
+ ami_ablecount[irq]--;
+ if (ami_ablecount[irq]<0)
+ ami_ablecount[irq]=0;
+ else if (ami_ablecount[irq])
+ return;
+
+ /* No action for auto-vector interrupts */
+ if (irq >= IRQ_AMIGA_AUTO){
+ printk("%s: Trying to enable auto-vector IRQ %i\n",
+ __FUNCTION__, irq - IRQ_AMIGA_AUTO);
+ return;
+ }
+
+ if (irq >= IRQ_AMIGA_CIAA) {
+ cia_set_irq(irq, 0);
+ cia_able_irq(irq, 1);
+ return;
+ }
+
+ /* enable the interrupt */
+ custom.intena = IF_SETCLR | ami_intena_vals[irq];
+}
+
+void amiga_disable_irq(unsigned int irq)
+{
+ if (irq >= AMI_IRQS) {
+ printk("%s: Unknown IRQ %d\n", __FUNCTION__, irq);
+ return;
+ }
+
+ if (ami_ablecount[irq]++)
+ return;
+
+ /* No action for auto-vector interrupts */
+ if (irq >= IRQ_AMIGA_AUTO) {
+ printk("%s: Trying to disable auto-vector IRQ %i\n",
+ __FUNCTION__, irq - IRQ_AMIGA_AUTO);
+ return;
+ }
+
+ if (irq >= IRQ_AMIGA_CIAA) {
+ cia_able_irq(irq, 0);
+ return;
+ }
+
+ /* disable the interrupt */
+ custom.intena = ami_intena_vals[irq];
+}
+
+inline void amiga_do_irq(int irq, struct pt_regs *fp)
+{
+ irq_desc_t *desc = irq_desc + irq;
+ struct irqaction *action = desc->action;
+
+ kstat_cpu(0).irqs[irq]++;
+ action->handler(irq, action->dev_id, fp);
+}
+
+void amiga_do_irq_list(int irq, struct pt_regs *fp)
+{
+ irq_desc_t *desc = irq_desc + irq;
+ struct irqaction *action;
+
+ kstat_cpu(0).irqs[irq]++;
+
+ custom.intreq = ami_intena_vals[irq];
+
+ for (action = desc->action; action; action = action->next)
+ action->handler(irq, action->dev_id, fp);
+}
+
+/*
+ * The builtin Amiga hardware interrupt handlers.
+ */
+
+static void ami_int1(int irq, void *dev_id, struct pt_regs *fp)
+{
+ unsigned short ints = custom.intreqr & custom.intenar;
+
+ /* if serial transmit buffer empty, interrupt */
+ if (ints & IF_TBE) {
+ custom.intreq = IF_TBE;
+ amiga_do_irq(IRQ_AMIGA_TBE, fp);
+ }
+
+ /* if floppy disk transfer complete, interrupt */
+ if (ints & IF_DSKBLK) {
+ custom.intreq = IF_DSKBLK;
+ amiga_do_irq(IRQ_AMIGA_DSKBLK, fp);
+ }
+
+ /* if software interrupt set, interrupt */
+ if (ints & IF_SOFT) {
+ custom.intreq = IF_SOFT;
+ amiga_do_irq(IRQ_AMIGA_SOFT, fp);
+ }
+}
+
+static void ami_int3(int irq, void *dev_id, struct pt_regs *fp)
+{
+ unsigned short ints = custom.intreqr & custom.intenar;
+
+ /* if a blitter interrupt */
+ if (ints & IF_BLIT) {
+ custom.intreq = IF_BLIT;
+ amiga_do_irq(IRQ_AMIGA_BLIT, fp);
+ }
+
+ /* if a copper interrupt */
+ if (ints & IF_COPER) {
+ custom.intreq = IF_COPER;
+ amiga_do_irq(IRQ_AMIGA_COPPER, fp);
+ }
+
+ /* if a vertical blank interrupt */
+ if (ints & IF_VERTB)
+ amiga_do_irq_list(IRQ_AMIGA_VERTB, fp);
+}
+
+static void ami_int4(int irq, void *dev_id, struct pt_regs *fp)
+{
+ unsigned short ints = custom.intreqr & custom.intenar;
+
+ /* if audio 0 interrupt */
+ if (ints & IF_AUD0) {
+ custom.intreq = IF_AUD0;
+ amiga_do_irq(IRQ_AMIGA_AUD0, fp);
+ }
+
+ /* if audio 1 interrupt */
+ if (ints & IF_AUD1) {
+ custom.intreq = IF_AUD1;
+ amiga_do_irq(IRQ_AMIGA_AUD1, fp);
+ }
+
+ /* if audio 2 interrupt */
+ if (ints & IF_AUD2) {
+ custom.intreq = IF_AUD2;
+ amiga_do_irq(IRQ_AMIGA_AUD2, fp);
+ }
+
+ /* if audio 3 interrupt */
+ if (ints & IF_AUD3) {
+ custom.intreq = IF_AUD3;
+ amiga_do_irq(IRQ_AMIGA_AUD3, fp);
+ }
+}
+
+static void ami_int5(int irq, void *dev_id, struct pt_regs *fp)
+{
+ unsigned short ints = custom.intreqr & custom.intenar;
+
+ /* if serial receive buffer full interrupt */
+ if (ints & IF_RBF) {
+ /* acknowledge of IF_RBF must be done by the serial interrupt */
+ amiga_do_irq(IRQ_AMIGA_RBF, fp);
+ }
+
+ /* if a disk sync interrupt */
+ if (ints & IF_DSKSYN) {
+ custom.intreq = IF_DSKSYN;
+ amiga_do_irq(IRQ_AMIGA_DSKSYN, fp);
+ }
+}
+
+static void ami_int7(int irq, void *dev_id, struct pt_regs *fp)
+{
+ panic ("level 7 interrupt received\n");
+}
+
+#ifdef CONFIG_APUS
+/* The PPC irq handling links all handlers requested on the same vector
+ and executes them in a loop. Having ami_badint at the end of the chain
+ is a bad idea. */
+struct irqaction amiga_sys_irqaction[AUTO_IRQS] = {
+ { .handler = ami_badint, .name = "spurious int" },
+ { .handler = ami_int1, .name = "int1 handler" },
+ { 0, /* CIAA */ },
+ { .handler = ami_int3, .name = "int3 handler" },
+ { .handler = ami_int4, .name = "int4 handler" },
+ { .handler = ami_int5, .name = "int5 handler" },
+ { 0, /* CIAB */ },
+ { .handler = ami_int7, .name = "int7 handler" },
+};
+#else
+void (*amiga_default_handler[SYS_IRQS])(int, void *, struct pt_regs *) = {
+ ami_badint, ami_int1, ami_badint, ami_int3,
+ ami_int4, ami_int5, ami_badint, ami_int7
+};
+#endif
diff --git a/arch/ppc/amiga/amisound.c b/arch/ppc/amiga/amisound.c
new file mode 100644
index 0000000..2b86cbe
--- /dev/null
+++ b/arch/ppc/amiga/amisound.c
@@ -0,0 +1 @@
+#include "../../m68k/amiga/amisound.c"
diff --git a/arch/ppc/amiga/bootinfo.c b/arch/ppc/amiga/bootinfo.c
new file mode 100644
index 0000000..e2e9656
--- /dev/null
+++ b/arch/ppc/amiga/bootinfo.c
@@ -0,0 +1,80 @@
+/*
+ * arch/ppc/amiga/bootinfo.c
+ *
+ * Extracted from arch/m68k/kernel/setup.c.
+ * Should be properly generalized and put somewhere else.
+ * Jesper
+ */
+
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/init.h>
+
+#include <asm/setup.h>
+#include <asm/bootinfo.h>
+
+extern char cmd_line[CL_SIZE];
+
+extern int num_memory;
+extern int m68k_realnum_memory;
+extern struct mem_info memory[NUM_MEMINFO];
+extern struct mem_info m68k_memory[NUM_MEMINFO];
+extern struct mem_info ramdisk;
+
+extern int amiga_parse_bootinfo(const struct bi_record *);
+extern int atari_parse_bootinfo(const struct bi_record *);
+extern int mac_parse_bootinfo(const struct bi_record *);
+
+void __init parse_bootinfo(const struct bi_record *record)
+{
+ while (record->tag != BI_LAST) {
+ int unknown = 0;
+ const u_long *data = record->data;
+ switch (record->tag) {
+ case BI_MACHTYPE:
+ case BI_CPUTYPE:
+ case BI_FPUTYPE:
+ case BI_MMUTYPE:
+ /* Already set up by head.S */
+ break;
+
+ case BI_MEMCHUNK:
+ if (num_memory < NUM_MEMINFO) {
+ memory[num_memory].addr = data[0];
+ memory[num_memory].size = data[1];
+ num_memory++;
+
+ /* FIXME: duplicate for m68k drivers. */
+ m68k_memory[m68k_realnum_memory].addr = data[0];
+ m68k_memory[m68k_realnum_memory].size = data[1];
+ m68k_realnum_memory++;
+ } else
+ printk("parse_bootinfo: too many memory chunks\n");
+ break;
+
+ case BI_RAMDISK:
+ ramdisk.addr = data[0];
+ ramdisk.size = data[1];
+ break;
+
+ case BI_COMMAND_LINE:
+ strlcpy(cmd_line, (const char *)data, sizeof(cmd_line));
+ break;
+
+ default:
+ if (MACH_IS_AMIGA)
+ unknown = amiga_parse_bootinfo(record);
+ else if (MACH_IS_ATARI)
+ unknown = atari_parse_bootinfo(record);
+ else if (MACH_IS_MAC)
+ unknown = mac_parse_bootinfo(record);
+ else
+ unknown = 1;
+ }
+ if (unknown)
+ printk("parse_bootinfo: unknown tag 0x%04x ignored\n",
+ record->tag);
+ record = (struct bi_record *)((u_long)record+record->size);
+ }
+}
diff --git a/arch/ppc/amiga/chipram.c b/arch/ppc/amiga/chipram.c
new file mode 100644
index 0000000..e6ab3c6
--- /dev/null
+++ b/arch/ppc/amiga/chipram.c
@@ -0,0 +1 @@
+#include "../../m68k/amiga/chipram.c"
diff --git a/arch/ppc/amiga/cia.c b/arch/ppc/amiga/cia.c
new file mode 100644
index 0000000..ad96146
--- /dev/null
+++ b/arch/ppc/amiga/cia.c
@@ -0,0 +1,178 @@
+/*
+ * arch/ppc/amiga/cia.c - CIA support
+ *
+ * Copyright (C) 1996 Roman Zippel
+ *
+ * The concept of some functions bases on the original Amiga OS function
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file COPYING in the main directory of this archive
+ * for more details.
+ */
+
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/kernel_stat.h>
+#include <linux/init.h>
+
+#include <asm/irq.h>
+#include <asm/amigahw.h>
+#include <asm/amigaints.h>
+
+struct ciabase {
+ volatile struct CIA *cia;
+ u_char icr_mask, icr_data;
+ u_short int_mask;
+ int handler_irq, cia_irq, server_irq;
+ char *name;
+} ciaa_base = {
+ &ciaa, 0, 0, IF_PORTS,
+ IRQ_AMIGA_AUTO_2, IRQ_AMIGA_CIAA,
+ IRQ_AMIGA_PORTS,
+ "CIAA handler"
+}, ciab_base = {
+ &ciab, 0, 0, IF_EXTER,
+ IRQ_AMIGA_AUTO_6, IRQ_AMIGA_CIAB,
+ IRQ_AMIGA_EXTER,
+ "CIAB handler"
+};
+
+#define CIA_SET_BASE_ADJUST_IRQ(base, irq) \
+do { \
+ if (irq >= IRQ_AMIGA_CIAB) { \
+ base = &ciab_base; \
+ irq -= IRQ_AMIGA_CIAB; \
+ } else { \
+ base = &ciaa_base; \
+ irq -= IRQ_AMIGA_CIAA; \
+ } \
+} while (0)
+
+/*
+ * Cause or clear CIA interrupts, return old interrupt status.
+ */
+
+static unsigned char cia_set_irq_private(struct ciabase *base,
+ unsigned char mask)
+{
+ u_char old;
+
+ old = (base->icr_data |= base->cia->icr);
+ if (mask & CIA_ICR_SETCLR)
+ base->icr_data |= mask;
+ else
+ base->icr_data &= ~mask;
+ if (base->icr_data & base->icr_mask)
+ custom.intreq = IF_SETCLR | base->int_mask;
+ return old & base->icr_mask;
+}
+
+unsigned char cia_set_irq(unsigned int irq, int set)
+{
+ struct ciabase *base;
+ unsigned char mask;
+
+ if (irq >= IRQ_AMIGA_CIAB)
+ mask = (1 << (irq - IRQ_AMIGA_CIAB));
+ else
+ mask = (1 << (irq - IRQ_AMIGA_CIAA));
+ mask |= (set) ? CIA_ICR_SETCLR : 0;
+
+ CIA_SET_BASE_ADJUST_IRQ(base, irq);
+
+ return cia_set_irq_private(base, mask);
+}
+
+unsigned char cia_get_irq_mask(unsigned int irq)
+{
+ struct ciabase *base;
+
+ CIA_SET_BASE_ADJUST_IRQ(base, irq);
+
+ return base->cia->icr;
+}
+
+/*
+ * Enable or disable CIA interrupts, return old interrupt mask.
+ */
+
+static unsigned char cia_able_irq_private(struct ciabase *base,
+ unsigned char mask)
+{
+ u_char old;
+
+ old = base->icr_mask;
+ base->icr_data |= base->cia->icr;
+ base->cia->icr = mask;
+ if (mask & CIA_ICR_SETCLR)
+ base->icr_mask |= mask;
+ else
+ base->icr_mask &= ~mask;
+ base->icr_mask &= CIA_ICR_ALL;
+
+ if (base->icr_data & base->icr_mask)
+ custom.intreq = IF_SETCLR | base->int_mask;
+ return old;
+}
+
+unsigned char cia_able_irq(unsigned int irq, int enable)
+{
+ struct ciabase *base;
+ unsigned char mask;
+
+ if (irq >= IRQ_AMIGA_CIAB)
+ mask = (1 << (irq - IRQ_AMIGA_CIAB));
+ else
+ mask = (1 << (irq - IRQ_AMIGA_CIAA));
+ mask |= (enable) ? CIA_ICR_SETCLR : 0;
+
+ CIA_SET_BASE_ADJUST_IRQ(base, irq);
+
+ return cia_able_irq_private(base, mask);
+}
+
+static void cia_handler(int irq, void *dev_id, struct pt_regs *fp)
+{
+ struct ciabase *base = (struct ciabase *)dev_id;
+ irq_desc_t *desc;
+ struct irqaction *action;
+ int i;
+ unsigned char ints;
+
+ irq = base->cia_irq;
+ desc = irq_desc + irq;
+ ints = cia_set_irq_private(base, CIA_ICR_ALL);
+ custom.intreq = base->int_mask;
+ for (i = 0; i < CIA_IRQS; i++, irq++) {
+ if (ints & 1) {
+ kstat_cpu(0).irqs[irq]++;
+ action = desc->action;
+ action->handler(irq, action->dev_id, fp);
+ }
+ ints >>= 1;
+ desc++;
+ }
+ amiga_do_irq_list(base->server_irq, fp);
+}
+
+void __init cia_init_IRQ(struct ciabase *base)
+{
+ extern struct irqaction amiga_sys_irqaction[AUTO_IRQS];
+ struct irqaction *action;
+
+ /* clear any pending interrupt and turn off all interrupts */
+ cia_set_irq_private(base, CIA_ICR_ALL);
+ cia_able_irq_private(base, CIA_ICR_ALL);
+
+ /* install CIA handler */
+ action = &amiga_sys_irqaction[base->handler_irq-IRQ_AMIGA_AUTO];
+ action->handler = cia_handler;
+ action->dev_id = base;
+ action->name = base->name;
+ setup_irq(base->handler_irq, &amiga_sys_irqaction[base->handler_irq-IRQ_AMIGA_AUTO]);
+
+ custom.intena = IF_SETCLR | base->int_mask;
+}
diff --git a/arch/ppc/amiga/config.c b/arch/ppc/amiga/config.c
new file mode 100644
index 0000000..af881d7
--- /dev/null
+++ b/arch/ppc/amiga/config.c
@@ -0,0 +1,962 @@
+#define m68k_debug_device debug_device
+
+/*
+ * arch/ppc/amiga/config.c
+ *
+ * Copyright (C) 1993 Hamish Macdonald
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file COPYING in the main directory of this archive
+ * for more details.
+ */
+
+/*
+ * Miscellaneous Amiga stuff
+ */
+
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/kd.h>
+#include <linux/tty.h>
+#include <linux/console.h>
+#include <linux/init.h>
+#ifdef CONFIG_ZORRO
+#include <linux/zorro.h>
+#endif
+
+#include <asm/bootinfo.h>
+#include <asm/setup.h>
+#include <asm/system.h>
+#include <asm/pgtable.h>
+#include <asm/amigahw.h>
+#include <asm/amigaints.h>
+#include <asm/irq.h>
+#include <asm/machdep.h>
+#include <asm/io.h>
+
+unsigned long powerup_PCI_present;
+unsigned long powerup_BPPCPLUS_present;
+unsigned long amiga_model;
+unsigned long amiga_eclock;
+unsigned long amiga_masterclock;
+unsigned long amiga_colorclock;
+unsigned long amiga_chipset;
+unsigned char amiga_vblank;
+unsigned char amiga_psfreq;
+struct amiga_hw_present amiga_hw_present;
+
+static char s_a500[] __initdata = "A500";
+static char s_a500p[] __initdata = "A500+";
+static char s_a600[] __initdata = "A600";
+static char s_a1000[] __initdata = "A1000";
+static char s_a1200[] __initdata = "A1200";
+static char s_a2000[] __initdata = "A2000";
+static char s_a2500[] __initdata = "A2500";
+static char s_a3000[] __initdata = "A3000";
+static char s_a3000t[] __initdata = "A3000T";
+static char s_a3000p[] __initdata = "A3000+";
+static char s_a4000[] __initdata = "A4000";
+static char s_a4000t[] __initdata = "A4000T";
+static char s_cdtv[] __initdata = "CDTV";
+static char s_cd32[] __initdata = "CD32";
+static char s_draco[] __initdata = "Draco";
+static char *amiga_models[] __initdata = {
+ s_a500, s_a500p, s_a600, s_a1000, s_a1200, s_a2000, s_a2500, s_a3000,
+ s_a3000t, s_a3000p, s_a4000, s_a4000t, s_cdtv, s_cd32, s_draco,
+};
+
+static char amiga_model_name[13] = "Amiga ";
+
+extern char m68k_debug_device[];
+
+static void amiga_sched_init(irqreturn_t (*handler)(int, void *, struct pt_regs *));
+/* amiga specific irq functions */
+extern void amiga_init_IRQ (void);
+extern void (*amiga_default_handler[]) (int, void *, struct pt_regs *);
+extern int amiga_request_irq (unsigned int irq,
+ void (*handler)(int, void *, struct pt_regs *),
+ unsigned long flags, const char *devname,
+ void *dev_id);
+extern void amiga_free_irq (unsigned int irq, void *dev_id);
+extern void amiga_enable_irq (unsigned int);
+extern void amiga_disable_irq (unsigned int);
+static void amiga_get_model(char *model);
+static int amiga_get_hardware_list(char *buffer);
+/* amiga specific timer functions */
+static unsigned long amiga_gettimeoffset (void);
+static void a3000_gettod (int *, int *, int *, int *, int *, int *);
+static void a2000_gettod (int *, int *, int *, int *, int *, int *);
+static int amiga_hwclk (int, struct hwclk_time *);
+static int amiga_set_clock_mmss (unsigned long);
+#ifdef CONFIG_AMIGA_FLOPPY
+extern void amiga_floppy_setup(char *, int *);
+#endif
+static void amiga_reset (void);
+extern void amiga_init_sound(void);
+static void amiga_savekmsg_init(void);
+static void amiga_mem_console_write(struct console *co, const char *b,
+ unsigned int count);
+void amiga_serial_console_write(struct console *co, const char *s,
+ unsigned int count);
+static void amiga_debug_init(void);
+#ifdef CONFIG_HEARTBEAT
+static void amiga_heartbeat(int on);
+#endif
+
+static struct console amiga_console_driver = {
+ .name = "debug",
+ .flags = CON_PRINTBUFFER,
+ .index = -1,
+};
+
+
+ /*
+ * Motherboard Resources present in all Amiga models
+ */
+
+static struct {
+ struct resource _ciab, _ciaa, _custom, _kickstart;
+} mb_resources = {
+// { "Ranger Memory", 0x00c00000, 0x00c7ffff },
+ ._ciab = { "CIA B", 0x00bfd000, 0x00bfdfff },
+ ._ciaa = { "CIA A", 0x00bfe000, 0x00bfefff },
+ ._custom = { "Custom I/O", 0x00dff000, 0x00dfffff },
+ ._kickstart = { "Kickstart ROM", 0x00f80000, 0x00ffffff }
+};
+
+static struct resource rtc_resource = {
+ NULL, 0x00dc0000, 0x00dcffff
+};
+
+static struct resource ram_resource[NUM_MEMINFO];
+
+
+ /*
+ * Parse an Amiga-specific record in the bootinfo
+ */
+
+int amiga_parse_bootinfo(const struct bi_record *record)
+{
+ int unknown = 0;
+ const unsigned long *data = record->data;
+
+ switch (record->tag) {
+ case BI_AMIGA_MODEL:
+ {
+ unsigned long d = *data;
+
+ powerup_PCI_present = d & 0x100;
+ amiga_model = d & 0xff;
+ }
+ break;
+
+ case BI_AMIGA_ECLOCK:
+ amiga_eclock = *data;
+ break;
+
+ case BI_AMIGA_CHIPSET:
+ amiga_chipset = *data;
+ break;
+
+ case BI_AMIGA_CHIP_SIZE:
+ amiga_chip_size = *(const int *)data;
+ break;
+
+ case BI_AMIGA_VBLANK:
+ amiga_vblank = *(const unsigned char *)data;
+ break;
+
+ case BI_AMIGA_PSFREQ:
+ amiga_psfreq = *(const unsigned char *)data;
+ break;
+
+ case BI_AMIGA_AUTOCON:
+#ifdef CONFIG_ZORRO
+ if (zorro_num_autocon < ZORRO_NUM_AUTO) {
+ const struct ConfigDev *cd = (struct ConfigDev *)data;
+ struct zorro_dev *dev = &zorro_autocon[zorro_num_autocon++];
+ dev->rom = cd->cd_Rom;
+ dev->slotaddr = cd->cd_SlotAddr;
+ dev->slotsize = cd->cd_SlotSize;
+ dev->resource.start = (unsigned long)cd->cd_BoardAddr;
+ dev->resource.end = dev->resource.start+cd->cd_BoardSize-1;
+ } else
+ printk("amiga_parse_bootinfo: too many AutoConfig devices\n");
+#endif /* CONFIG_ZORRO */
+ break;
+
+ case BI_AMIGA_SERPER:
+ /* serial port period: ignored here */
+ break;
+
+ case BI_AMIGA_PUP_BRIDGE:
+ powerup_PCI_present = *(const unsigned short *)data;
+ break;
+
+ case BI_AMIGA_BPPC_SCSI:
+ powerup_BPPCPLUS_present = *(const unsigned short *)data;
+ break;
+
+ default:
+ unknown = 1;
+ }
+ return(unknown);
+}
+
+ /*
+ * Identify builtin hardware
+ */
+
+static void __init amiga_identify(void)
+{
+ /* Fill in some default values, if necessary */
+ if (amiga_eclock == 0)
+ amiga_eclock = 709379;
+
+ memset(&amiga_hw_present, 0, sizeof(amiga_hw_present));
+
+ printk("Amiga hardware found: ");
+ if (amiga_model >= AMI_500 && amiga_model <= AMI_DRACO) {
+ printk("[%s] ", amiga_models[amiga_model-AMI_500]);
+ strcat(amiga_model_name, amiga_models[amiga_model-AMI_500]);
+ }
+
+ switch(amiga_model) {
+ case AMI_UNKNOWN:
+ goto Generic;
+
+ case AMI_600:
+ case AMI_1200:
+ AMIGAHW_SET(A1200_IDE);
+ AMIGAHW_SET(PCMCIA);
+ case AMI_500:
+ case AMI_500PLUS:
+ case AMI_1000:
+ case AMI_2000:
+ case AMI_2500:
+ AMIGAHW_SET(A2000_CLK); /* Is this correct for all models? */
+ goto Generic;
+
+ case AMI_3000:
+ case AMI_3000T:
+ AMIGAHW_SET(AMBER_FF);
+ AMIGAHW_SET(MAGIC_REKICK);
+ /* fall through */
+ case AMI_3000PLUS:
+ AMIGAHW_SET(A3000_SCSI);
+ AMIGAHW_SET(A3000_CLK);
+ AMIGAHW_SET(ZORRO3);
+ goto Generic;
+
+ case AMI_4000T:
+ AMIGAHW_SET(A4000_SCSI);
+ /* fall through */
+ case AMI_4000:
+ AMIGAHW_SET(A4000_IDE);
+ AMIGAHW_SET(A3000_CLK);
+ AMIGAHW_SET(ZORRO3);
+ goto Generic;
+
+ case AMI_CDTV:
+ case AMI_CD32:
+ AMIGAHW_SET(CD_ROM);
+ AMIGAHW_SET(A2000_CLK); /* Is this correct? */
+ goto Generic;
+
+ Generic:
+ AMIGAHW_SET(AMI_VIDEO);
+ AMIGAHW_SET(AMI_BLITTER);
+ AMIGAHW_SET(AMI_AUDIO);
+ AMIGAHW_SET(AMI_FLOPPY);
+ AMIGAHW_SET(AMI_KEYBOARD);
+ AMIGAHW_SET(AMI_MOUSE);
+ AMIGAHW_SET(AMI_SERIAL);
+ AMIGAHW_SET(AMI_PARALLEL);
+ AMIGAHW_SET(CHIP_RAM);
+ AMIGAHW_SET(PAULA);
+
+ switch(amiga_chipset) {
+ case CS_OCS:
+ case CS_ECS:
+ case CS_AGA:
+ switch (custom.deniseid & 0xf) {
+ case 0x0c:
+ AMIGAHW_SET(DENISE_HR);
+ break;
+ case 0x08:
+ AMIGAHW_SET(LISA);
+ break;
+ }
+ break;
+ default:
+ AMIGAHW_SET(DENISE);
+ break;
+ }
+ switch ((custom.vposr>>8) & 0x7f) {
+ case 0x00:
+ AMIGAHW_SET(AGNUS_PAL);
+ break;
+ case 0x10:
+ AMIGAHW_SET(AGNUS_NTSC);
+ break;
+ case 0x20:
+ case 0x21:
+ AMIGAHW_SET(AGNUS_HR_PAL);
+ break;
+ case 0x30:
+ case 0x31:
+ AMIGAHW_SET(AGNUS_HR_NTSC);
+ break;
+ case 0x22:
+ case 0x23:
+ AMIGAHW_SET(ALICE_PAL);
+ break;
+ case 0x32:
+ case 0x33:
+ AMIGAHW_SET(ALICE_NTSC);
+ break;
+ }
+ AMIGAHW_SET(ZORRO);
+ break;
+
+ case AMI_DRACO:
+ panic("No support for Draco yet");
+
+ default:
+ panic("Unknown Amiga Model");
+ }
+
+#define AMIGAHW_ANNOUNCE(name, str) \
+ if (AMIGAHW_PRESENT(name)) \
+ printk(str)
+
+ AMIGAHW_ANNOUNCE(AMI_VIDEO, "VIDEO ");
+ AMIGAHW_ANNOUNCE(AMI_BLITTER, "BLITTER ");
+ AMIGAHW_ANNOUNCE(AMBER_FF, "AMBER_FF ");
+ AMIGAHW_ANNOUNCE(AMI_AUDIO, "AUDIO ");
+ AMIGAHW_ANNOUNCE(AMI_FLOPPY, "FLOPPY ");
+ AMIGAHW_ANNOUNCE(A3000_SCSI, "A3000_SCSI ");
+ AMIGAHW_ANNOUNCE(A4000_SCSI, "A4000_SCSI ");
+ AMIGAHW_ANNOUNCE(A1200_IDE, "A1200_IDE ");
+ AMIGAHW_ANNOUNCE(A4000_IDE, "A4000_IDE ");
+ AMIGAHW_ANNOUNCE(CD_ROM, "CD_ROM ");
+ AMIGAHW_ANNOUNCE(AMI_KEYBOARD, "KEYBOARD ");
+ AMIGAHW_ANNOUNCE(AMI_MOUSE, "MOUSE ");
+ AMIGAHW_ANNOUNCE(AMI_SERIAL, "SERIAL ");
+ AMIGAHW_ANNOUNCE(AMI_PARALLEL, "PARALLEL ");
+ AMIGAHW_ANNOUNCE(A2000_CLK, "A2000_CLK ");
+ AMIGAHW_ANNOUNCE(A3000_CLK, "A3000_CLK ");
+ AMIGAHW_ANNOUNCE(CHIP_RAM, "CHIP_RAM ");
+ AMIGAHW_ANNOUNCE(PAULA, "PAULA ");
+ AMIGAHW_ANNOUNCE(DENISE, "DENISE ");
+ AMIGAHW_ANNOUNCE(DENISE_HR, "DENISE_HR ");
+ AMIGAHW_ANNOUNCE(LISA, "LISA ");
+ AMIGAHW_ANNOUNCE(AGNUS_PAL, "AGNUS_PAL ");
+ AMIGAHW_ANNOUNCE(AGNUS_NTSC, "AGNUS_NTSC ");
+ AMIGAHW_ANNOUNCE(AGNUS_HR_PAL, "AGNUS_HR_PAL ");
+ AMIGAHW_ANNOUNCE(AGNUS_HR_NTSC, "AGNUS_HR_NTSC ");
+ AMIGAHW_ANNOUNCE(ALICE_PAL, "ALICE_PAL ");
+ AMIGAHW_ANNOUNCE(ALICE_NTSC, "ALICE_NTSC ");
+ AMIGAHW_ANNOUNCE(MAGIC_REKICK, "MAGIC_REKICK ");
+ AMIGAHW_ANNOUNCE(PCMCIA, "PCMCIA ");
+ if (AMIGAHW_PRESENT(ZORRO))
+ printk("ZORRO%s ", AMIGAHW_PRESENT(ZORRO3) ? "3" : "");
+ printk("\n");
+
+#undef AMIGAHW_ANNOUNCE
+}
+
+ /*
+ * Setup the Amiga configuration info
+ */
+
+void __init config_amiga(void)
+{
+ int i;
+
+ amiga_debug_init();
+ amiga_identify();
+
+ /* Some APUS boxes may have PCI memory, but ... */
+ iomem_resource.name = "Memory";
+ for (i = 0; i < 4; i++)
+ request_resource(&iomem_resource, &((struct resource *)&mb_resources)[i]);
+
+ mach_sched_init = amiga_sched_init;
+ mach_init_IRQ = amiga_init_IRQ;
+#ifndef CONFIG_APUS
+ mach_default_handler = &amiga_default_handler;
+ mach_request_irq = amiga_request_irq;
+ mach_free_irq = amiga_free_irq;
+ enable_irq = amiga_enable_irq;
+ disable_irq = amiga_disable_irq;
+#endif
+ mach_get_model = amiga_get_model;
+ mach_get_hardware_list = amiga_get_hardware_list;
+ mach_gettimeoffset = amiga_gettimeoffset;
+ if (AMIGAHW_PRESENT(A3000_CLK)){
+ mach_gettod = a3000_gettod;
+ rtc_resource.name = "A3000 RTC";
+ request_resource(&iomem_resource, &rtc_resource);
+ }
+ else{ /* if (AMIGAHW_PRESENT(A2000_CLK)) */
+ mach_gettod = a2000_gettod;
+ rtc_resource.name = "A2000 RTC";
+ request_resource(&iomem_resource, &rtc_resource);
+ }
+
+ mach_max_dma_address = 0xffffffff; /*
+ * default MAX_DMA=0xffffffff
+ * on all machines. If we don't
+ * do so, the SCSI code will not
+ * be able to allocate any mem
+ * for transfers, unless we are
+ * dealing with a Z2 mem only
+ * system. /Jes
+ */
+
+ mach_hwclk = amiga_hwclk;
+ mach_set_clock_mmss = amiga_set_clock_mmss;
+#ifdef CONFIG_AMIGA_FLOPPY
+ mach_floppy_setup = amiga_floppy_setup;
+#endif
+ mach_reset = amiga_reset;
+#ifdef CONFIG_HEARTBEAT
+ mach_heartbeat = amiga_heartbeat;
+#endif
+
+ /* Fill in the clock values (based on the 700 kHz E-Clock) */
+ amiga_masterclock = 40*amiga_eclock; /* 28 MHz */
+ amiga_colorclock = 5*amiga_eclock; /* 3.5 MHz */
+
+ /* clear all DMA bits */
+ custom.dmacon = DMAF_ALL;
+ /* ensure that the DMA master bit is set */
+ custom.dmacon = DMAF_SETCLR | DMAF_MASTER;
+
+ /* request all RAM */
+ for (i = 0; i < m68k_num_memory; i++) {
+ ram_resource[i].name =
+ (m68k_memory[i].addr >= 0x01000000) ? "32-bit Fast RAM" :
+ (m68k_memory[i].addr < 0x00c00000) ? "16-bit Fast RAM" :
+ "16-bit Slow RAM";
+ ram_resource[i].start = m68k_memory[i].addr;
+ ram_resource[i].end = m68k_memory[i].addr+m68k_memory[i].size-1;
+ request_resource(&iomem_resource, &ram_resource[i]);
+ }
+
+ /* initialize chipram allocator */
+ amiga_chip_init ();
+
+ /* debugging using chipram */
+ if (!strcmp( m68k_debug_device, "mem" )){
+ if (!AMIGAHW_PRESENT(CHIP_RAM))
+ printk("Warning: no chipram present for debugging\n");
+ else {
+ amiga_savekmsg_init();
+ amiga_console_driver.write = amiga_mem_console_write;
+ register_console(&amiga_console_driver);
+ }
+ }
+
+ /* our beloved beeper */
+ if (AMIGAHW_PRESENT(AMI_AUDIO))
+ amiga_init_sound();
+
+ /*
+ * if it is an A3000, set the magic bit that forces
+ * a hard rekick
+ */
+ if (AMIGAHW_PRESENT(MAGIC_REKICK))
+ *(unsigned char *)ZTWO_VADDR(0xde0002) |= 0x80;
+}
+
+static unsigned short jiffy_ticks;
+
+static void __init amiga_sched_init(irqreturn_t (*timer_routine)(int, void *,
+ struct pt_regs *))
+{
+ static struct resource sched_res = {
+ "timer", 0x00bfd400, 0x00bfd5ff,
+ };
+ jiffy_ticks = (amiga_eclock+HZ/2)/HZ;
+
+ if (request_resource(&mb_resources._ciab, &sched_res))
+ printk("Cannot allocate ciab.ta{lo,hi}\n");
+ ciab.cra &= 0xC0; /* turn off timer A, continuous mode, from Eclk */
+ ciab.talo = jiffy_ticks % 256;
+ ciab.tahi = jiffy_ticks / 256;
+
+ /* install interrupt service routine for CIAB Timer A
+ *
+ * Please don't change this to use ciaa, as it interferes with the
+ * SCSI code. We'll have to take a look at this later
+ */
+ request_irq(IRQ_AMIGA_CIAB_TA, timer_routine, 0, "timer", NULL);
+ /* start timer */
+ ciab.cra |= 0x11;
+}
+
+#define TICK_SIZE 10000
+
+extern unsigned char cia_get_irq_mask(unsigned int irq);
+
+/* This is always executed with interrupts disabled. */
+static unsigned long amiga_gettimeoffset (void)
+{
+ unsigned short hi, lo, hi2;
+ unsigned long ticks, offset = 0;
+
+ /* read CIA B timer A current value */
+ hi = ciab.tahi;
+ lo = ciab.talo;
+ hi2 = ciab.tahi;
+
+ if (hi != hi2) {
+ lo = ciab.talo;
+ hi = hi2;
+ }
+
+ ticks = hi << 8 | lo;
+
+ if (ticks > jiffy_ticks / 2)
+ /* check for pending interrupt */
+ if (cia_get_irq_mask(IRQ_AMIGA_CIAB) & CIA_ICR_TA)
+ offset = 10000;
+
+ ticks = jiffy_ticks - ticks;
+ ticks = (10000 * ticks) / jiffy_ticks;
+
+ return ticks + offset;
+}
+
+static void a3000_gettod (int *yearp, int *monp, int *dayp,
+ int *hourp, int *minp, int *secp)
+{
+ volatile struct tod3000 *tod = TOD_3000;
+
+ tod->cntrl1 = TOD3000_CNTRL1_HOLD;
+
+ *secp = tod->second1 * 10 + tod->second2;
+ *minp = tod->minute1 * 10 + tod->minute2;
+ *hourp = tod->hour1 * 10 + tod->hour2;
+ *dayp = tod->day1 * 10 + tod->day2;
+ *monp = tod->month1 * 10 + tod->month2;
+ *yearp = tod->year1 * 10 + tod->year2;
+
+ tod->cntrl1 = TOD3000_CNTRL1_FREE;
+}
+
+static void a2000_gettod (int *yearp, int *monp, int *dayp,
+ int *hourp, int *minp, int *secp)
+{
+ volatile struct tod2000 *tod = TOD_2000;
+
+ tod->cntrl1 = TOD2000_CNTRL1_HOLD;
+
+ while (tod->cntrl1 & TOD2000_CNTRL1_BUSY)
+ ;
+
+ *secp = tod->second1 * 10 + tod->second2;
+ *minp = tod->minute1 * 10 + tod->minute2;
+ *hourp = (tod->hour1 & 3) * 10 + tod->hour2;
+ *dayp = tod->day1 * 10 + tod->day2;
+ *monp = tod->month1 * 10 + tod->month2;
+ *yearp = tod->year1 * 10 + tod->year2;
+
+ if (!(tod->cntrl3 & TOD2000_CNTRL3_24HMODE)){
+ if (!(tod->hour1 & TOD2000_HOUR1_PM) && *hourp == 12)
+ *hourp = 0;
+ else if ((tod->hour1 & TOD2000_HOUR1_PM) && *hourp != 12)
+ *hourp += 12;
+ }
+
+ tod->cntrl1 &= ~TOD2000_CNTRL1_HOLD;
+}
+
+static int amiga_hwclk(int op, struct hwclk_time *t)
+{
+ if (AMIGAHW_PRESENT(A3000_CLK)) {
+ volatile struct tod3000 *tod = TOD_3000;
+
+ tod->cntrl1 = TOD3000_CNTRL1_HOLD;
+
+ if (!op) { /* read */
+ t->sec = tod->second1 * 10 + tod->second2;
+ t->min = tod->minute1 * 10 + tod->minute2;
+ t->hour = tod->hour1 * 10 + tod->hour2;
+ t->day = tod->day1 * 10 + tod->day2;
+ t->wday = tod->weekday;
+ t->mon = tod->month1 * 10 + tod->month2 - 1;
+ t->year = tod->year1 * 10 + tod->year2;
+ if (t->year <= 69)
+ t->year += 100;
+ } else {
+ tod->second1 = t->sec / 10;
+ tod->second2 = t->sec % 10;
+ tod->minute1 = t->min / 10;
+ tod->minute2 = t->min % 10;
+ tod->hour1 = t->hour / 10;
+ tod->hour2 = t->hour % 10;
+ tod->day1 = t->day / 10;
+ tod->day2 = t->day % 10;
+ if (t->wday != -1)
+ tod->weekday = t->wday;
+ tod->month1 = (t->mon + 1) / 10;
+ tod->month2 = (t->mon + 1) % 10;
+ if (t->year >= 100)
+ t->year -= 100;
+ tod->year1 = t->year / 10;
+ tod->year2 = t->year % 10;
+ }
+
+ tod->cntrl1 = TOD3000_CNTRL1_FREE;
+ } else /* if (AMIGAHW_PRESENT(A2000_CLK)) */ {
+ volatile struct tod2000 *tod = TOD_2000;
+
+ tod->cntrl1 = TOD2000_CNTRL1_HOLD;
+
+ while (tod->cntrl1 & TOD2000_CNTRL1_BUSY)
+ ;
+
+ if (!op) { /* read */
+ t->sec = tod->second1 * 10 + tod->second2;
+ t->min = tod->minute1 * 10 + tod->minute2;
+ t->hour = (tod->hour1 & 3) * 10 + tod->hour2;
+ t->day = tod->day1 * 10 + tod->day2;
+ t->wday = tod->weekday;
+ t->mon = tod->month1 * 10 + tod->month2 - 1;
+ t->year = tod->year1 * 10 + tod->year2;
+ if (t->year <= 69)
+ t->year += 100;
+
+ if (!(tod->cntrl3 & TOD2000_CNTRL3_24HMODE)){
+ if (!(tod->hour1 & TOD2000_HOUR1_PM) && t->hour == 12)
+ t->hour = 0;
+ else if ((tod->hour1 & TOD2000_HOUR1_PM) && t->hour != 12)
+ t->hour += 12;
+ }
+ } else {
+ tod->second1 = t->sec / 10;
+ tod->second2 = t->sec % 10;
+ tod->minute1 = t->min / 10;
+ tod->minute2 = t->min % 10;
+ if (tod->cntrl3 & TOD2000_CNTRL3_24HMODE)
+ tod->hour1 = t->hour / 10;
+ else if (t->hour >= 12)
+ tod->hour1 = TOD2000_HOUR1_PM +
+ (t->hour - 12) / 10;
+ else
+ tod->hour1 = t->hour / 10;
+ tod->hour2 = t->hour % 10;
+ tod->day1 = t->day / 10;
+ tod->day2 = t->day % 10;
+ if (t->wday != -1)
+ tod->weekday = t->wday;
+ tod->month1 = (t->mon + 1) / 10;
+ tod->month2 = (t->mon + 1) % 10;
+ if (t->year >= 100)
+ t->year -= 100;
+ tod->year1 = t->year / 10;
+ tod->year2 = t->year % 10;
+ }
+
+ tod->cntrl1 &= ~TOD2000_CNTRL1_HOLD;
+ }
+
+ return 0;
+}
+
+static int amiga_set_clock_mmss (unsigned long nowtime)
+{
+ short real_seconds = nowtime % 60, real_minutes = (nowtime / 60) % 60;
+
+ if (AMIGAHW_PRESENT(A3000_CLK)) {
+ volatile struct tod3000 *tod = TOD_3000;
+
+ tod->cntrl1 = TOD3000_CNTRL1_HOLD;
+
+ tod->second1 = real_seconds / 10;
+ tod->second2 = real_seconds % 10;
+ tod->minute1 = real_minutes / 10;
+ tod->minute2 = real_minutes % 10;
+
+ tod->cntrl1 = TOD3000_CNTRL1_FREE;
+ } else /* if (AMIGAHW_PRESENT(A2000_CLK)) */ {
+ volatile struct tod2000 *tod = TOD_2000;
+
+ tod->cntrl1 = TOD2000_CNTRL1_HOLD;
+
+ while (tod->cntrl1 & TOD2000_CNTRL1_BUSY)
+ ;
+
+ tod->second1 = real_seconds / 10;
+ tod->second2 = real_seconds % 10;
+ tod->minute1 = real_minutes / 10;
+ tod->minute2 = real_minutes % 10;
+
+ tod->cntrl1 &= ~TOD2000_CNTRL1_HOLD;
+ }
+
+ return 0;
+}
+
+static NORET_TYPE void amiga_reset( void )
+ ATTRIB_NORET;
+
+static void amiga_reset (void)
+{
+ for (;;);
+}
+
+
+ /*
+ * Debugging
+ */
+
+#define SAVEKMSG_MAXMEM 128*1024
+
+#define SAVEKMSG_MAGIC1 0x53415645 /* 'SAVE' */
+#define SAVEKMSG_MAGIC2 0x4B4D5347 /* 'KMSG' */
+
+struct savekmsg {
+ unsigned long magic1; /* SAVEKMSG_MAGIC1 */
+ unsigned long magic2; /* SAVEKMSG_MAGIC2 */
+ unsigned long magicptr; /* address of magic1 */
+ unsigned long size;
+ char data[0];
+};
+
+static struct savekmsg *savekmsg = NULL;
+
+static void amiga_mem_console_write(struct console *co, const char *s,
+ unsigned int count)
+{
+ if (savekmsg->size+count <= SAVEKMSG_MAXMEM-sizeof(struct savekmsg)) {
+ memcpy(savekmsg->data+savekmsg->size, s, count);
+ savekmsg->size += count;
+ }
+}
+
+static void amiga_savekmsg_init(void)
+{
+ static struct resource debug_res = { "Debug" };
+
+ savekmsg = amiga_chip_alloc_res(SAVEKMSG_MAXMEM, &debug_res);
+ savekmsg->magic1 = SAVEKMSG_MAGIC1;
+ savekmsg->magic2 = SAVEKMSG_MAGIC2;
+ savekmsg->magicptr = virt_to_phys(savekmsg);
+ savekmsg->size = 0;
+}
+
+static void amiga_serial_putc(char c)
+{
+ custom.serdat = (unsigned char)c | 0x100;
+ mb();
+ while (!(custom.serdatr & 0x2000))
+ ;
+}
+
+void amiga_serial_console_write(struct console *co, const char *s,
+ unsigned int count)
+{
+#if 0 /* def CONFIG_KGDB */
+ /* FIXME:APUS GDB doesn't seem to like O-packages before it is
+ properly connected with the target. */
+ __gdb_output_string (s, count);
+#else
+ while (count--) {
+ if (*s == '\n')
+ amiga_serial_putc('\r');
+ amiga_serial_putc(*s++);
+ }
+#endif
+}
+
+#ifdef CONFIG_SERIAL_CONSOLE
+void amiga_serial_puts(const char *s)
+{
+ amiga_serial_console_write(NULL, s, strlen(s));
+}
+
+int amiga_serial_console_wait_key(struct console *co)
+{
+ int ch;
+
+ while (!(custom.intreqr & IF_RBF))
+ barrier();
+ ch = custom.serdatr & 0xff;
+ /* clear the interrupt, so that another character can be read */
+ custom.intreq = IF_RBF;
+ return ch;
+}
+
+void amiga_serial_gets(struct console *co, char *s, int len)
+{
+ int ch, cnt = 0;
+
+ while (1) {
+ ch = amiga_serial_console_wait_key(co);
+
+ /* Check for backspace. */
+ if (ch == 8 || ch == 127) {
+ if (cnt == 0) {
+ amiga_serial_putc('\007');
+ continue;
+ }
+ cnt--;
+ amiga_serial_puts("\010 \010");
+ continue;
+ }
+
+ /* Check for enter. */
+ if (ch == 10 || ch == 13)
+ break;
+
+ /* See if line is too long. */
+ if (cnt >= len + 1) {
+ amiga_serial_putc(7);
+ cnt--;
+ continue;
+ }
+
+ /* Store and echo character. */
+ s[cnt++] = ch;
+ amiga_serial_putc(ch);
+ }
+ /* Print enter. */
+ amiga_serial_puts("\r\n");
+ s[cnt] = 0;
+}
+#endif
+
+static void __init amiga_debug_init(void)
+{
+ if (!strcmp( m68k_debug_device, "ser" )) {
+ /* no initialization required (?) */
+ amiga_console_driver.write = amiga_serial_console_write;
+ register_console(&amiga_console_driver);
+ }
+}
+
+#ifdef CONFIG_HEARTBEAT
+static void amiga_heartbeat(int on)
+{
+ if (on)
+ ciaa.pra &= ~2;
+ else
+ ciaa.pra |= 2;
+}
+#endif
+
+ /*
+ * Amiga specific parts of /proc
+ */
+
+static void amiga_get_model(char *model)
+{
+ strcpy(model, amiga_model_name);
+}
+
+
+static int amiga_get_hardware_list(char *buffer)
+{
+ int len = 0;
+
+ if (AMIGAHW_PRESENT(CHIP_RAM))
+ len += sprintf(buffer+len, "Chip RAM:\t%ldK\n", amiga_chip_size>>10);
+ len += sprintf(buffer+len, "PS Freq:\t%dHz\nEClock Freq:\t%ldHz\n",
+ amiga_psfreq, amiga_eclock);
+ if (AMIGAHW_PRESENT(AMI_VIDEO)) {
+ char *type;
+ switch(amiga_chipset) {
+ case CS_OCS:
+ type = "OCS";
+ break;
+ case CS_ECS:
+ type = "ECS";
+ break;
+ case CS_AGA:
+ type = "AGA";
+ break;
+ default:
+ type = "Old or Unknown";
+ break;
+ }
+ len += sprintf(buffer+len, "Graphics:\t%s\n", type);
+ }
+
+#define AMIGAHW_ANNOUNCE(name, str) \
+ if (AMIGAHW_PRESENT(name)) \
+ len += sprintf (buffer+len, "\t%s\n", str)
+
+ len += sprintf (buffer + len, "Detected hardware:\n");
+
+ AMIGAHW_ANNOUNCE(AMI_VIDEO, "Amiga Video");
+ AMIGAHW_ANNOUNCE(AMI_BLITTER, "Blitter");
+ AMIGAHW_ANNOUNCE(AMBER_FF, "Amber Flicker Fixer");
+ AMIGAHW_ANNOUNCE(AMI_AUDIO, "Amiga Audio");
+ AMIGAHW_ANNOUNCE(AMI_FLOPPY, "Floppy Controller");
+ AMIGAHW_ANNOUNCE(A3000_SCSI, "SCSI Controller WD33C93 (A3000 style)");
+ AMIGAHW_ANNOUNCE(A4000_SCSI, "SCSI Controller NCR53C710 (A4000T style)");
+ AMIGAHW_ANNOUNCE(A1200_IDE, "IDE Interface (A1200 style)");
+ AMIGAHW_ANNOUNCE(A4000_IDE, "IDE Interface (A4000 style)");
+ AMIGAHW_ANNOUNCE(CD_ROM, "Internal CD ROM drive");
+ AMIGAHW_ANNOUNCE(AMI_KEYBOARD, "Keyboard");
+ AMIGAHW_ANNOUNCE(AMI_MOUSE, "Mouse Port");
+ AMIGAHW_ANNOUNCE(AMI_SERIAL, "Serial Port");
+ AMIGAHW_ANNOUNCE(AMI_PARALLEL, "Parallel Port");
+ AMIGAHW_ANNOUNCE(A2000_CLK, "Hardware Clock (A2000 style)");
+ AMIGAHW_ANNOUNCE(A3000_CLK, "Hardware Clock (A3000 style)");
+ AMIGAHW_ANNOUNCE(CHIP_RAM, "Chip RAM");
+ AMIGAHW_ANNOUNCE(PAULA, "Paula 8364");
+ AMIGAHW_ANNOUNCE(DENISE, "Denise 8362");
+ AMIGAHW_ANNOUNCE(DENISE_HR, "Denise 8373");
+ AMIGAHW_ANNOUNCE(LISA, "Lisa 8375");
+ AMIGAHW_ANNOUNCE(AGNUS_PAL, "Normal/Fat PAL Agnus 8367/8371");
+ AMIGAHW_ANNOUNCE(AGNUS_NTSC, "Normal/Fat NTSC Agnus 8361/8370");
+ AMIGAHW_ANNOUNCE(AGNUS_HR_PAL, "Fat Hires PAL Agnus 8372");
+ AMIGAHW_ANNOUNCE(AGNUS_HR_NTSC, "Fat Hires NTSC Agnus 8372");
+ AMIGAHW_ANNOUNCE(ALICE_PAL, "PAL Alice 8374");
+ AMIGAHW_ANNOUNCE(ALICE_NTSC, "NTSC Alice 8374");
+ AMIGAHW_ANNOUNCE(MAGIC_REKICK, "Magic Hard Rekick");
+ AMIGAHW_ANNOUNCE(PCMCIA, "PCMCIA Slot");
+ if (AMIGAHW_PRESENT(ZORRO))
+ len += sprintf(buffer+len, "\tZorro II%s AutoConfig: %d Expansion "
+ "Device%s\n",
+ AMIGAHW_PRESENT(ZORRO3) ? "I" : "",
+ zorro_num_autocon, zorro_num_autocon == 1 ? "" : "s");
+
+#undef AMIGAHW_ANNOUNCE
+
+ return(len);
+}
+
+#ifdef CONFIG_APUS
+int get_hardware_list(char *buffer)
+{
+ extern int get_cpuinfo(char *buffer);
+ int len = 0;
+ char model[80];
+ u_long mem;
+ int i;
+
+ if (mach_get_model)
+ mach_get_model(model);
+ else
+ strcpy(model, "Unknown PowerPC");
+
+ len += sprintf(buffer+len, "Model:\t\t%s\n", model);
+ len += get_cpuinfo(buffer+len);
+ for (mem = 0, i = 0; i < m68k_realnum_memory; i++)
+ mem += m68k_memory[i].size;
+ len += sprintf(buffer+len, "System Memory:\t%ldK\n", mem>>10);
+
+ if (mach_get_hardware_list)
+ len += mach_get_hardware_list(buffer+len);
+
+ return(len);
+}
+#endif
diff --git a/arch/ppc/amiga/ints.c b/arch/ppc/amiga/ints.c
new file mode 100644
index 0000000..5d318e4
--- /dev/null
+++ b/arch/ppc/amiga/ints.c
@@ -0,0 +1,160 @@
+/*
+ * arch/ppc/amiga/ints.c
+ *
+ * Linux/m68k general interrupt handling code from arch/m68k/kernel/ints.c
+ * Needed to drive the m68k emulating IRQ hardware on the PowerUp boards.
+ */
+
+#include <linux/types.h>
+#include <linux/sched.h>
+#include <linux/kernel_stat.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/seq_file.h>
+
+#include <asm/setup.h>
+#include <asm/system.h>
+#include <asm/irq.h>
+#include <asm/traps.h>
+#include <asm/page.h>
+#include <asm/machdep.h>
+
+/* table for system interrupt handlers */
+static irq_handler_t irq_list[SYS_IRQS];
+
+static const char *default_names[SYS_IRQS] = {
+ "spurious int", "int1 handler", "int2 handler", "int3 handler",
+ "int4 handler", "int5 handler", "int6 handler", "int7 handler"
+};
+
+/* The number of spurious interrupts */
+volatile unsigned int num_spurious;
+
+#define NUM_IRQ_NODES 100
+static irq_node_t nodes[NUM_IRQ_NODES];
+
+
+/*
+ * void init_IRQ(void)
+ *
+ * Parameters: None
+ *
+ * Returns: Nothing
+ *
+ * This function should be called during kernel startup to initialize
+ * the IRQ handling routines.
+ */
+
+__init
+void m68k_init_IRQ(void)
+{
+ int i;
+
+ for (i = 0; i < SYS_IRQS; i++) {
+ if (mach_default_handler)
+ irq_list[i].handler = (*mach_default_handler)[i];
+ irq_list[i].flags = 0;
+ irq_list[i].dev_id = NULL;
+ irq_list[i].devname = default_names[i];
+ }
+
+ for (i = 0; i < NUM_IRQ_NODES; i++)
+ nodes[i].handler = NULL;
+
+ mach_init_IRQ ();
+}
+
+irq_node_t *new_irq_node(void)
+{
+ irq_node_t *node;
+ short i;
+
+ for (node = nodes, i = NUM_IRQ_NODES-1; i >= 0; node++, i--)
+ if (!node->handler)
+ return node;
+
+ printk ("new_irq_node: out of nodes\n");
+ return NULL;
+}
+
+int sys_request_irq(unsigned int irq,
+ void (*handler)(int, void *, struct pt_regs *),
+ unsigned long flags, const char *devname, void *dev_id)
+{
+ if (irq < IRQ1 || irq > IRQ7) {
+ printk("%s: Incorrect IRQ %d from %s\n",
+ __FUNCTION__, irq, devname);
+ return -ENXIO;
+ }
+
+#if 0
+ if (!(irq_list[irq].flags & IRQ_FLG_STD)) {
+ if (irq_list[irq].flags & IRQ_FLG_LOCK) {
+ printk("%s: IRQ %d from %s is not replaceable\n",
+ __FUNCTION__, irq, irq_list[irq].devname);
+ return -EBUSY;
+ }
+ if (!(flags & IRQ_FLG_REPLACE)) {
+ printk("%s: %s can't replace IRQ %d from %s\n",
+ __FUNCTION__, devname, irq, irq_list[irq].devname);
+ return -EBUSY;
+ }
+ }
+#endif
+
+ irq_list[irq].handler = handler;
+ irq_list[irq].flags = flags;
+ irq_list[irq].dev_id = dev_id;
+ irq_list[irq].devname = devname;
+ return 0;
+}
+
+void sys_free_irq(unsigned int irq, void *dev_id)
+{
+ if (irq < IRQ1 || irq > IRQ7) {
+ printk("%s: Incorrect IRQ %d\n", __FUNCTION__, irq);
+ return;
+ }
+
+ if (irq_list[irq].dev_id != dev_id)
+ printk("%s: Removing probably wrong IRQ %d from %s\n",
+ __FUNCTION__, irq, irq_list[irq].devname);
+
+ irq_list[irq].handler = (*mach_default_handler)[irq];
+ irq_list[irq].flags = 0;
+ irq_list[irq].dev_id = NULL;
+ irq_list[irq].devname = default_names[irq];
+}
+
+asmlinkage void process_int(unsigned long vec, struct pt_regs *fp)
+{
+ if (vec >= VEC_INT1 && vec <= VEC_INT7 && !MACH_IS_BVME6000) {
+ vec -= VEC_SPUR;
+ kstat_cpu(0).irqs[vec]++;
+ irq_list[vec].handler(vec, irq_list[vec].dev_id, fp);
+ } else {
+ if (mach_process_int)
+ mach_process_int(vec, fp);
+ else
+ panic("Can't process interrupt vector %ld\n", vec);
+ return;
+ }
+}
+
+int m68k_get_irq_list(struct seq_file *p, void *v)
+{
+ int i;
+
+ /* autovector interrupts */
+ if (mach_default_handler) {
+ for (i = 0; i < SYS_IRQS; i++) {
+ seq_printf(p, "auto %2d: %10u ", i,
+ i ? kstat_cpu(0).irqs[i] : num_spurious);
+ seq_puts(p, " ");
+ seq_printf(p, "%s\n", irq_list[i].devname);
+ }
+ }
+
+ mach_get_irq_list(p, v);
+ return 0;
+}
diff --git a/arch/ppc/amiga/pcmcia.c b/arch/ppc/amiga/pcmcia.c
new file mode 100644
index 0000000..5d29dc6
--- /dev/null
+++ b/arch/ppc/amiga/pcmcia.c
@@ -0,0 +1 @@
+#include "../../m68k/amiga/pcmcia.c"
diff --git a/arch/ppc/amiga/time.c b/arch/ppc/amiga/time.c
new file mode 100644
index 0000000..0073527
--- /dev/null
+++ b/arch/ppc/amiga/time.c
@@ -0,0 +1,58 @@
+#include <linux/config.h> /* CONFIG_HEARTBEAT */
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/param.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+
+#include <asm/machdep.h>
+#include <asm/io.h>
+
+#include <linux/timex.h>
+
+unsigned long m68k_get_rtc_time(void)
+{
+ unsigned int year, mon, day, hour, min, sec;
+
+ extern void arch_gettod(int *year, int *mon, int *day, int *hour,
+ int *min, int *sec);
+
+ arch_gettod (&year, &mon, &day, &hour, &min, &sec);
+
+ if ((year += 1900) < 1970)
+ year += 100;
+
+ return mktime(year, mon, day, hour, min, sec);
+}
+
+int m68k_set_rtc_time(unsigned long nowtime)
+{
+ if (mach_set_clock_mmss)
+ return mach_set_clock_mmss (nowtime);
+ return -1;
+}
+
+void apus_heartbeat (void)
+{
+#ifdef CONFIG_HEARTBEAT
+ static unsigned cnt = 0, period = 0, dist = 0;
+
+ if (cnt == 0 || cnt == dist)
+ mach_heartbeat( 1 );
+ else if (cnt == 7 || cnt == dist+7)
+ mach_heartbeat( 0 );
+
+ if (++cnt > period) {
+ cnt = 0;
+ /* The hyperbolic function below modifies the heartbeat period
+ * length in dependency of the current (5min) load. It goes
+ * through the points f(0)=126, f(1)=86, f(5)=51,
+ * f(inf)->30. */
+ period = ((672<<FSHIFT)/(5*avenrun[0]+(7<<FSHIFT))) + 30;
+ dist = period / 4;
+ }
+#endif
+ /* should be made smarter */
+ ppc_md.heartbeat_count = 1;
+}
diff --git a/arch/ppc/boot/Makefile b/arch/ppc/boot/Makefile
new file mode 100644
index 0000000..995f89b
--- /dev/null
+++ b/arch/ppc/boot/Makefile
@@ -0,0 +1,34 @@
+#
+# arch/ppc/boot/Makefile
+#
+# This file is subject to the terms and conditions of the GNU General Public
+# License. See the file "COPYING" in the main directory of this archive
+# for more details.
+#
+# Copyright (C) 1994 by Linus Torvalds
+# Adapted for PowerPC by Gary Thomas
+# modified by Cort (cort@cs.nmt.edu)
+#
+
+CFLAGS += -fno-builtin -D__BOOTER__ -Iarch/$(ARCH)/boot/include
+HOSTCFLAGS += -Iarch/$(ARCH)/boot/include
+
+BOOT_TARGETS = zImage zImage.initrd znetboot znetboot.initrd
+
+bootdir-y := simple
+bootdir-$(CONFIG_PPC_OF) += openfirmware
+subdir-y := lib common images
+subdir-$(CONFIG_PPC_OF) += of1275
+
+# for cleaning
+subdir- += simple openfirmware
+
+hostprogs-y := $(addprefix utils/, addnote mknote hack-coff mkprep mkbugboot mktree)
+
+.PHONY: $(BOOT_TARGETS) $(bootdir-y)
+
+$(BOOT_TARGETS): $(bootdir-y)
+
+$(bootdir-y): $(addprefix $(obj)/,$(subdir-y)) \
+ $(addprefix $(obj)/,$(hostprogs-y))
+ $(Q)$(MAKE) $(build)=$(obj)/$@ $(MAKECMDGOALS)
diff --git a/arch/ppc/boot/common/Makefile b/arch/ppc/boot/common/Makefile
new file mode 100644
index 0000000..f88d647
--- /dev/null
+++ b/arch/ppc/boot/common/Makefile
@@ -0,0 +1,13 @@
+#
+# arch/ppc/boot/common/Makefile
+#
+# This file is subject to the terms and conditions of the GNU General Public
+# License. See the file "COPYING" in the main directory of this archive
+# for more details.
+#
+# Tom Rini January 2001
+#
+
+lib-y := string.o util.o misc-common.o \
+ serial_stub.o bootinfo.o
+lib-$(CONFIG_SERIAL_8250_CONSOLE) += ns16550.o
diff --git a/arch/ppc/boot/common/bootinfo.c b/arch/ppc/boot/common/bootinfo.c
new file mode 100644
index 0000000..9c6e528
--- /dev/null
+++ b/arch/ppc/boot/common/bootinfo.c
@@ -0,0 +1,70 @@
+/*
+ * arch/ppc/common/bootinfo.c
+ *
+ * General bootinfo record utilities
+ * Author: Randy Vinson <rvinson@mvista.com>
+ *
+ * 2002 (c) MontaVista Software, Inc. This file is licensed under the terms
+ * of the GNU General Public License version 2. This program is licensed
+ * "as is" without any warranty of any kind, whether express or implied.
+ */
+
+#include <linux/types.h>
+#include <linux/string.h>
+#include <asm/bootinfo.h>
+
+#include "nonstdio.h"
+
+static struct bi_record * birec = NULL;
+
+static struct bi_record *
+__bootinfo_build(struct bi_record *rec, unsigned long tag, unsigned long size,
+ void *data)
+{
+ /* set the tag */
+ rec->tag = tag;
+
+ /* if the caller has any data, copy it */
+ if (size)
+ memcpy(rec->data, (char *)data, size);
+
+ /* set the record size */
+ rec->size = sizeof(struct bi_record) + size;
+
+ /* advance to the next available space */
+ rec = (struct bi_record *)((unsigned long)rec + rec->size);
+
+ return rec;
+}
+
+void
+bootinfo_init(struct bi_record *rec)
+{
+
+ /* save start of birec area */
+ birec = rec;
+
+ /* create an empty list */
+ rec = __bootinfo_build(rec, BI_FIRST, 0, NULL);
+ (void) __bootinfo_build(rec, BI_LAST, 0, NULL);
+
+}
+
+void
+bootinfo_append(unsigned long tag, unsigned long size, void * data)
+{
+
+ struct bi_record *rec = birec;
+
+ /* paranoia */
+ if ((rec == NULL) || (rec->tag != BI_FIRST))
+ return;
+
+ /* find the last entry in the list */
+ while (rec->tag != BI_LAST)
+ rec = (struct bi_record *)((ulong)rec + rec->size);
+
+ /* overlay BI_LAST record with new one and tag on a new BI_LAST */
+ rec = __bootinfo_build(rec, tag, size, data);
+ (void) __bootinfo_build(rec, BI_LAST, 0, NULL);
+}
diff --git a/arch/ppc/boot/common/crt0.S b/arch/ppc/boot/common/crt0.S
new file mode 100644
index 0000000..4d31b82
--- /dev/null
+++ b/arch/ppc/boot/common/crt0.S
@@ -0,0 +1,81 @@
+/* Copyright (c) 1997 Paul Mackerras <paulus@cs.anu.edu.au>
+ * Initial Power Macintosh COFF version.
+ * Copyright (c) 1999 Grant Erickson <grant@lcse.umn.edu>
+ * Modifications for IBM PowerPC 400-class processor evaluation
+ * boards.
+ *
+ * Module name: crt0.S
+ *
+ * Description:
+ * Boot loader execution entry point. Clears out .bss section as per
+ * ANSI C requirements. Invalidates and flushes the caches over the
+ * range covered by the boot loader's .text section. Sets up a stack
+ * below the .text section entry point.
+ *
+ * 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.
+ */
+
+#include <linux/config.h>
+#include <asm/ppc_asm.h>
+
+ .text
+
+ .globl _start
+_start:
+#ifdef XCOFF
+ .long __start,0,0
+
+ .globl __start
+__start:
+#endif
+
+ ## Flush and invalidate the caches for the range in memory covering
+ ## the .text section of the boot loader
+
+ lis r9,_start@h # r9 = &_start
+ lis r8,_etext@ha #
+ addi r8,r8,_etext@l # r8 = &_etext
+3: dcbf r0,r9 # Flush the data cache
+ icbi r0,r9 # Invalidate the instruction cache
+ addi r9,r9,0x10 # Increment by one cache line
+ cmplw cr0,r9,r8 # Are we at the end yet?
+ blt 3b # No, keep flushing and invalidating
+ sync # sync ; isync after flushing the icache
+ isync
+
+ ## Clear out the BSS as per ANSI C requirements
+
+ lis r7,_end@ha
+ addi r7,r7,_end@l # r7 = &_end
+ lis r8,__bss_start@ha #
+ addi r8,r8,__bss_start@l # r8 = &_bss_start
+
+ ## Determine how large an area, in number of words, to clear
+
+ subf r7,r8,r7 # r7 = &_end - &_bss_start + 1
+ addi r7,r7,3 # r7 += 3
+ srwi. r7,r7,2 # r7 = size in words.
+ beq 2f # If the size is zero, do not bother
+ addi r8,r8,-4 # r8 -= 4
+ mtctr r7 # SPRN_CTR = number of words to clear
+ li r0,0 # r0 = 0
+1: stwu r0,4(r8) # Clear out a word
+ bdnz 1b # If we are not done yet, keep clearing
+2:
+
+#ifdef CONFIG_40x
+ ## Set up the stack
+
+ lis r9,_start@h # r9 = &_start (text section entry)
+ ori r9,r9,_start@l
+ subi r1,r9,64 # Start the stack 64 bytes below _start
+ clrrwi r1,r1,4 # Make sure it is aligned on 16 bytes.
+ li r0,0
+ stwu r0,-16(r1)
+ mtlr r9
+#endif
+
+ b start # All done, start the real work.
diff --git a/arch/ppc/boot/common/misc-common.c b/arch/ppc/boot/common/misc-common.c
new file mode 100644
index 0000000..e79e6b3
--- /dev/null
+++ b/arch/ppc/boot/common/misc-common.c
@@ -0,0 +1,553 @@
+/*
+ * arch/ppc/boot/common/misc-common.c
+ *
+ * Misc. bootloader code (almost) all platforms can use
+ *
+ * Author: Johnnie Peters <jpeters@mvista.com>
+ * Editor: Tom Rini <trini@mvista.com>
+ *
+ * Derived from arch/ppc/boot/prep/misc.c
+ *
+ * 2000-2001 (c) MontaVista, Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+
+#include <stdarg.h> /* for va_ bits */
+#include <linux/config.h>
+#include <linux/string.h>
+#include <linux/zlib.h>
+#include "nonstdio.h"
+
+/* If we're on a PReP, assume we have a keyboard controller
+ * Also note, if we're not PReP, we assume you are a serial
+ * console - Tom */
+#if defined(CONFIG_PPC_PREP) && defined(CONFIG_VGA_CONSOLE)
+extern void cursor(int x, int y);
+extern void scroll(void);
+extern char *vidmem;
+extern int lines, cols;
+extern int orig_x, orig_y;
+extern int keyb_present;
+extern int CRT_tstc(void);
+extern int CRT_getc(void);
+#else
+int cursor(int x, int y) {return 0;}
+void scroll(void) {}
+char vidmem[1];
+#define lines 0
+#define cols 0
+int orig_x = 0;
+int orig_y = 0;
+#define keyb_present 0
+int CRT_tstc(void) {return 0;}
+int CRT_getc(void) {return 0;}
+#endif
+
+extern char *avail_ram;
+extern char *end_avail;
+extern char _end[];
+
+void puts(const char *);
+void putc(const char c);
+void puthex(unsigned long val);
+void gunzip(void *, int, unsigned char *, int *);
+static int _cvt(unsigned long val, char *buf, long radix, char *digits);
+
+void _vprintk(void(*putc)(const char), const char *fmt0, va_list ap);
+unsigned char *ISA_io = NULL;
+
+#if defined(CONFIG_SERIAL_CPM_CONSOLE) || defined(CONFIG_SERIAL_8250_CONSOLE) \
+ || defined(CONFIG_SERIAL_MPC52xx_CONSOLE) \
+ || defined(CONFIG_SERIAL_MPSC_CONSOLE)
+extern unsigned long com_port;
+
+extern int serial_tstc(unsigned long com_port);
+extern unsigned char serial_getc(unsigned long com_port);
+extern void serial_putc(unsigned long com_port, unsigned char c);
+#endif
+
+void pause(void)
+{
+ puts("pause\n");
+}
+
+void exit(void)
+{
+ puts("exit\n");
+ while(1);
+}
+
+int tstc(void)
+{
+#if defined(CONFIG_SERIAL_CPM_CONSOLE) || defined(CONFIG_SERIAL_8250_CONSOLE) \
+ || defined(CONFIG_SERIAL_MPC52xx_CONSOLE) \
+ || defined(CONFIG_SERIAL_MPSC_CONSOLE)
+ if(keyb_present)
+ return (CRT_tstc() || serial_tstc(com_port));
+ else
+ return (serial_tstc(com_port));
+#else
+ return CRT_tstc();
+#endif
+}
+
+int getc(void)
+{
+ while (1) {
+#if defined(CONFIG_SERIAL_CPM_CONSOLE) || defined(CONFIG_SERIAL_8250_CONSOLE) \
+ || defined(CONFIG_SERIAL_MPC52xx_CONSOLE) \
+ || defined(CONFIG_SERIAL_MPSC_CONSOLE)
+ if (serial_tstc(com_port))
+ return (serial_getc(com_port));
+#endif /* serial console */
+ if (keyb_present)
+ if(CRT_tstc())
+ return (CRT_getc());
+ }
+}
+
+void
+putc(const char c)
+{
+ int x,y;
+
+#if defined(CONFIG_SERIAL_CPM_CONSOLE) || defined(CONFIG_SERIAL_8250_CONSOLE) \
+ || defined(CONFIG_SERIAL_MPC52xx_CONSOLE) \
+ || defined(CONFIG_SERIAL_MPSC_CONSOLE)
+ serial_putc(com_port, c);
+ if ( c == '\n' )
+ serial_putc(com_port, '\r');
+#endif /* serial console */
+
+ x = orig_x;
+ y = orig_y;
+
+ if ( c == '\n' ) {
+ x = 0;
+ if ( ++y >= lines ) {
+ scroll();
+ y--;
+ }
+ } else if (c == '\r') {
+ x = 0;
+ } else if (c == '\b') {
+ if (x > 0) {
+ x--;
+ }
+ } else {
+ vidmem [ ( x + cols * y ) * 2 ] = c;
+ if ( ++x >= cols ) {
+ x = 0;
+ if ( ++y >= lines ) {
+ scroll();
+ y--;
+ }
+ }
+ }
+
+ cursor(x, y);
+
+ orig_x = x;
+ orig_y = y;
+}
+
+void puts(const char *s)
+{
+ int x,y;
+ char c;
+
+ x = orig_x;
+ y = orig_y;
+
+ while ( ( c = *s++ ) != '\0' ) {
+#if defined(CONFIG_SERIAL_CPM_CONSOLE) || defined(CONFIG_SERIAL_8250_CONSOLE) \
+ || defined(CONFIG_SERIAL_MPC52xx_CONSOLE) \
+ || defined(CONFIG_SERIAL_MPSC_CONSOLE)
+ serial_putc(com_port, c);
+ if ( c == '\n' ) serial_putc(com_port, '\r');
+#endif /* serial console */
+
+ if ( c == '\n' ) {
+ x = 0;
+ if ( ++y >= lines ) {
+ scroll();
+ y--;
+ }
+ } else if (c == '\b') {
+ if (x > 0) {
+ x--;
+ }
+ } else {
+ vidmem [ ( x + cols * y ) * 2 ] = c;
+ if ( ++x >= cols ) {
+ x = 0;
+ if ( ++y >= lines ) {
+ scroll();
+ y--;
+ }
+ }
+ }
+ }
+
+ cursor(x, y);
+
+ orig_x = x;
+ orig_y = y;
+}
+
+void error(char *x)
+{
+ puts("\n\n");
+ puts(x);
+ puts("\n\n -- System halted");
+
+ while(1); /* Halt */
+}
+
+static void *zalloc(unsigned size)
+{
+ void *p = avail_ram;
+
+ size = (size + 7) & -8;
+ avail_ram += size;
+ if (avail_ram > end_avail) {
+ puts("oops... out of memory\n");
+ pause();
+ }
+ return p;
+}
+
+#define HEAD_CRC 2
+#define EXTRA_FIELD 4
+#define ORIG_NAME 8
+#define COMMENT 0x10
+#define RESERVED 0xe0
+
+void gunzip(void *dst, int dstlen, unsigned char *src, int *lenp)
+{
+ z_stream s;
+ int r, i, flags;
+
+ /* skip header */
+ i = 10;
+ flags = src[3];
+ if (src[2] != Z_DEFLATED || (flags & RESERVED) != 0) {
+ puts("bad gzipped data\n");
+ exit();
+ }
+ if ((flags & EXTRA_FIELD) != 0)
+ i = 12 + src[10] + (src[11] << 8);
+ if ((flags & ORIG_NAME) != 0)
+ while (src[i++] != 0)
+ ;
+ if ((flags & COMMENT) != 0)
+ while (src[i++] != 0)
+ ;
+ if ((flags & HEAD_CRC) != 0)
+ i += 2;
+ if (i >= *lenp) {
+ puts("gunzip: ran out of data in header\n");
+ exit();
+ }
+
+ /* Initialize ourself. */
+ s.workspace = zalloc(zlib_inflate_workspacesize());
+ r = zlib_inflateInit2(&s, -MAX_WBITS);
+ if (r != Z_OK) {
+ puts("zlib_inflateInit2 returned "); puthex(r); puts("\n");
+ exit();
+ }
+ s.next_in = src + i;
+ s.avail_in = *lenp - i;
+ s.next_out = dst;
+ s.avail_out = dstlen;
+ r = zlib_inflate(&s, Z_FINISH);
+ if (r != Z_OK && r != Z_STREAM_END) {
+ puts("inflate returned "); puthex(r); puts("\n");
+ exit();
+ }
+ *lenp = s.next_out - (unsigned char *) dst;
+ zlib_inflateEnd(&s);
+}
+
+void
+puthex(unsigned long val)
+{
+
+ unsigned char buf[10];
+ int i;
+ for (i = 7; i >= 0; i--)
+ {
+ buf[i] = "0123456789ABCDEF"[val & 0x0F];
+ val >>= 4;
+ }
+ buf[8] = '\0';
+ puts(buf);
+}
+
+#define FALSE 0
+#define TRUE 1
+
+void
+_printk(char const *fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ _vprintk(putc, fmt, ap);
+ va_end(ap);
+ return;
+}
+
+#define is_digit(c) ((c >= '0') && (c <= '9'))
+
+void
+_vprintk(void(*putc)(const char), const char *fmt0, va_list ap)
+{
+ char c, sign, *cp = 0;
+ int left_prec, right_prec, zero_fill, length = 0, pad, pad_on_right;
+ char buf[32];
+ long val;
+ while ((c = *fmt0++))
+ {
+ if (c == '%')
+ {
+ c = *fmt0++;
+ left_prec = right_prec = pad_on_right = 0;
+ if (c == '-')
+ {
+ c = *fmt0++;
+ pad_on_right++;
+ }
+ if (c == '0')
+ {
+ zero_fill = TRUE;
+ c = *fmt0++;
+ } else
+ {
+ zero_fill = FALSE;
+ }
+ while (is_digit(c))
+ {
+ left_prec = (left_prec * 10) + (c - '0');
+ c = *fmt0++;
+ }
+ if (c == '.')
+ {
+ c = *fmt0++;
+ zero_fill++;
+ while (is_digit(c))
+ {
+ right_prec = (right_prec * 10) + (c - '0');
+ c = *fmt0++;
+ }
+ } else
+ {
+ right_prec = left_prec;
+ }
+ sign = '\0';
+ switch (c)
+ {
+ case 'd':
+ case 'x':
+ case 'X':
+ val = va_arg(ap, long);
+ switch (c)
+ {
+ case 'd':
+ if (val < 0)
+ {
+ sign = '-';
+ val = -val;
+ }
+ length = _cvt(val, buf, 10, "0123456789");
+ break;
+ case 'x':
+ length = _cvt(val, buf, 16, "0123456789abcdef");
+ break;
+ case 'X':
+ length = _cvt(val, buf, 16, "0123456789ABCDEF");
+ break;
+ }
+ cp = buf;
+ break;
+ case 's':
+ cp = va_arg(ap, char *);
+ length = strlen(cp);
+ break;
+ case 'c':
+ c = va_arg(ap, long /*char*/);
+ (*putc)(c);
+ continue;
+ default:
+ (*putc)('?');
+ }
+ pad = left_prec - length;
+ if (sign != '\0')
+ {
+ pad--;
+ }
+ if (zero_fill)
+ {
+ c = '0';
+ if (sign != '\0')
+ {
+ (*putc)(sign);
+ sign = '\0';
+ }
+ } else
+ {
+ c = ' ';
+ }
+ if (!pad_on_right)
+ {
+ while (pad-- > 0)
+ {
+ (*putc)(c);
+ }
+ }
+ if (sign != '\0')
+ {
+ (*putc)(sign);
+ }
+ while (length-- > 0)
+ {
+ (*putc)(c = *cp++);
+ if (c == '\n')
+ {
+ (*putc)('\r');
+ }
+ }
+ if (pad_on_right)
+ {
+ while (pad-- > 0)
+ {
+ (*putc)(c);
+ }
+ }
+ } else
+ {
+ (*putc)(c);
+ if (c == '\n')
+ {
+ (*putc)('\r');
+ }
+ }
+ }
+}
+
+int
+_cvt(unsigned long val, char *buf, long radix, char *digits)
+{
+ char temp[80];
+ char *cp = temp;
+ int length = 0;
+ if (val == 0)
+ { /* Special case */
+ *cp++ = '0';
+ } else
+ while (val)
+ {
+ *cp++ = digits[val % radix];
+ val /= radix;
+ }
+ while (cp != temp)
+ {
+ *buf++ = *--cp;
+ length++;
+ }
+ *buf = '\0';
+ return (length);
+}
+
+void
+_dump_buf_with_offset(unsigned char *p, int s, unsigned char *base)
+{
+ int i, c;
+ if ((unsigned int)s > (unsigned int)p)
+ {
+ s = (unsigned int)s - (unsigned int)p;
+ }
+ while (s > 0)
+ {
+ if (base)
+ {
+ _printk("%06X: ", (int)p - (int)base);
+ } else
+ {
+ _printk("%06X: ", p);
+ }
+ for (i = 0; i < 16; i++)
+ {
+ if (i < s)
+ {
+ _printk("%02X", p[i] & 0xFF);
+ } else
+ {
+ _printk(" ");
+ }
+ if ((i % 2) == 1) _printk(" ");
+ if ((i % 8) == 7) _printk(" ");
+ }
+ _printk(" |");
+ for (i = 0; i < 16; i++)
+ {
+ if (i < s)
+ {
+ c = p[i] & 0xFF;
+ if ((c < 0x20) || (c >= 0x7F)) c = '.';
+ } else
+ {
+ c = ' ';
+ }
+ _printk("%c", c);
+ }
+ _printk("|\n");
+ s -= 16;
+ p += 16;
+ }
+}
+
+void
+_dump_buf(unsigned char *p, int s)
+{
+ _printk("\n");
+ _dump_buf_with_offset(p, s, 0);
+}
+
+/* Very simple inb/outb routines. We declare ISA_io to be 0 above, and
+ * then modify it on platforms which need to. We do it like this
+ * because on some platforms we give inb/outb an exact location, and
+ * on others it's an offset from a given location. -- Tom
+ */
+
+void ISA_init(unsigned long base)
+{
+ ISA_io = (unsigned char *)base;
+}
+
+void
+outb(int port, unsigned char val)
+{
+ /* Ensure I/O operations complete */
+ __asm__ volatile("eieio");
+ ISA_io[port] = val;
+}
+
+unsigned char
+inb(int port)
+{
+ /* Ensure I/O operations complete */
+ __asm__ volatile("eieio");
+ return (ISA_io[port]);
+}
+
+/*
+ * Local variables:
+ * c-indent-level: 8
+ * c-basic-offset: 8
+ * tab-width: 8
+ * End:
+ */
diff --git a/arch/ppc/boot/common/ns16550.c b/arch/ppc/boot/common/ns16550.c
new file mode 100644
index 0000000..9017c54
--- /dev/null
+++ b/arch/ppc/boot/common/ns16550.c
@@ -0,0 +1,99 @@
+/*
+ * COM1 NS16550 support
+ */
+
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/serial.h>
+#include <linux/serial_reg.h>
+#include <asm/serial.h>
+
+#include "nonstdio.h"
+#include "serial.h"
+
+#define SERIAL_BAUD 9600
+
+extern unsigned long ISA_io;
+
+static struct serial_state rs_table[RS_TABLE_SIZE] = {
+ SERIAL_PORT_DFNS /* Defined in <asm/serial.h> */
+};
+
+static int shift;
+
+unsigned long serial_init(int chan, void *ignored)
+{
+ unsigned long com_port;
+ unsigned char lcr, dlm;
+
+ /* We need to find out which type io we're expecting. If it's
+ * 'SERIAL_IO_PORT', we get an offset from the isa_io_base.
+ * If it's 'SERIAL_IO_MEM', we can the exact location. -- Tom */
+ switch (rs_table[chan].io_type) {
+ case SERIAL_IO_PORT:
+ com_port = rs_table[chan].port;
+ break;
+ case SERIAL_IO_MEM:
+ com_port = (unsigned long)rs_table[chan].iomem_base;
+ break;
+ default:
+ /* We can't deal with it. */
+ return -1;
+ }
+
+ /* How far apart the registers are. */
+ shift = rs_table[chan].iomem_reg_shift;
+
+ /* save the LCR */
+ lcr = inb(com_port + (UART_LCR << shift));
+ /* Access baud rate */
+ outb(com_port + (UART_LCR << shift), 0x80);
+ dlm = inb(com_port + (UART_DLM << shift));
+ /*
+ * Test if serial port is unconfigured.
+ * We assume that no-one uses less than 110 baud or
+ * less than 7 bits per character these days.
+ * -- paulus.
+ */
+
+ if ((dlm <= 4) && (lcr & 2))
+ /* port is configured, put the old LCR back */
+ outb(com_port + (UART_LCR << shift), lcr);
+ else {
+ /* Input clock. */
+ outb(com_port + (UART_DLL << shift),
+ (BASE_BAUD / SERIAL_BAUD) & 0xFF);
+ outb(com_port + (UART_DLM << shift),
+ (BASE_BAUD / SERIAL_BAUD) >> 8);
+ /* 8 data, 1 stop, no parity */
+ outb(com_port + (UART_LCR << shift), 0x03);
+ /* RTS/DTR */
+ outb(com_port + (UART_MCR << shift), 0x03);
+ }
+ /* Clear & enable FIFOs */
+ outb(com_port + (UART_FCR << shift), 0x07);
+
+ return (com_port);
+}
+
+void
+serial_putc(unsigned long com_port, unsigned char c)
+{
+ while ((inb(com_port + (UART_LSR << shift)) & UART_LSR_THRE) == 0)
+ ;
+ outb(com_port, c);
+}
+
+unsigned char
+serial_getc(unsigned long com_port)
+{
+ while ((inb(com_port + (UART_LSR << shift)) & UART_LSR_DR) == 0)
+ ;
+ return inb(com_port);
+}
+
+int
+serial_tstc(unsigned long com_port)
+{
+ return ((inb(com_port + (UART_LSR << shift)) & UART_LSR_DR) != 0);
+}
diff --git a/arch/ppc/boot/common/serial_stub.c b/arch/ppc/boot/common/serial_stub.c
new file mode 100644
index 0000000..03dfaa0
--- /dev/null
+++ b/arch/ppc/boot/common/serial_stub.c
@@ -0,0 +1,23 @@
+/*
+ * arch/ppc/boot/common/serial_stub.c
+ *
+ * This is a few stub routines to make the boot code cleaner looking when
+ * there is no serial port support doesn't need to be closed, for example.
+ *
+ * Author: Tom Rini <trini@mvista.com>
+ *
+ * 2003 (c) MontaVista, Software, Inc. This file is licensed under the terms
+ * of the GNU General Public License version 2. This program is licensed "as
+ * is" without any warranty of any kind, whether express or implied.
+ */
+
+unsigned long __attribute__ ((weak))
+serial_init(int chan, void *ignored)
+{
+ return 0;
+}
+
+void __attribute__ ((weak))
+serial_close(unsigned long com_port)
+{
+}
diff --git a/arch/ppc/boot/common/string.S b/arch/ppc/boot/common/string.S
new file mode 100644
index 0000000..8016e43
--- /dev/null
+++ b/arch/ppc/boot/common/string.S
@@ -0,0 +1,150 @@
+/*
+ * String handling functions for PowerPC.
+ *
+ * Copyright (C) 1996 Paul Mackerras.
+ *
+ * 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.
+ */
+#define r0 0
+#define r3 3
+#define r4 4
+#define r5 5
+#define r6 6
+#define r7 7
+#define r8 8
+
+ .globl strlen
+strlen:
+ addi r4,r3,-1
+1: lbzu r0,1(r4)
+ cmpwi 0,r0,0
+ bne 1b
+ subf r3,r3,r4
+ blr
+
+ .globl memset
+memset:
+ rlwimi r4,r4,8,16,23
+ rlwimi r4,r4,16,0,15
+ addi r6,r3,-4
+ cmplwi 0,r5,4
+ blt 7f
+ stwu r4,4(r6)
+ beqlr
+ andi. r0,r6,3
+ add r5,r0,r5
+ subf r6,r0,r6
+ rlwinm r0,r5,32-2,2,31
+ mtctr r0
+ bdz 6f
+1: stwu r4,4(r6)
+ bdnz 1b
+6: andi. r5,r5,3
+7: cmpwi 0,r5,0
+ beqlr
+ mtctr r5
+ addi r6,r6,3
+8: stbu r4,1(r6)
+ bdnz 8b
+ blr
+
+ .globl memmove
+memmove:
+ cmplw 0,r3,r4
+ bgt backwards_memcpy
+ /* fall through */
+
+ .globl memcpy
+memcpy:
+ rlwinm. r7,r5,32-3,3,31 /* r0 = r5 >> 3 */
+ addi r6,r3,-4
+ addi r4,r4,-4
+ beq 2f /* if less than 8 bytes to do */
+ andi. r0,r6,3 /* get dest word aligned */
+ mtctr r7
+ bne 5f
+1: lwz r7,4(r4)
+ lwzu r8,8(r4)
+ stw r7,4(r6)
+ stwu r8,8(r6)
+ bdnz 1b
+ andi. r5,r5,7
+2: cmplwi 0,r5,4
+ blt 3f
+ lwzu r0,4(r4)
+ addi r5,r5,-4
+ stwu r0,4(r6)
+3: cmpwi 0,r5,0
+ beqlr
+ mtctr r5
+ addi r4,r4,3
+ addi r6,r6,3
+4: lbzu r0,1(r4)
+ stbu r0,1(r6)
+ bdnz 4b
+ blr
+5: subfic r0,r0,4
+ mtctr r0
+6: lbz r7,4(r4)
+ addi r4,r4,1
+ stb r7,4(r6)
+ addi r6,r6,1
+ bdnz 6b
+ subf r5,r0,r5
+ rlwinm. r7,r5,32-3,3,31
+ beq 2b
+ mtctr r7
+ b 1b
+
+ .globl backwards_memcpy
+backwards_memcpy:
+ rlwinm. r7,r5,32-3,3,31 /* r0 = r5 >> 3 */
+ add r6,r3,r5
+ add r4,r4,r5
+ beq 2f
+ andi. r0,r6,3
+ mtctr r7
+ bne 5f
+1: lwz r7,-4(r4)
+ lwzu r8,-8(r4)
+ stw r7,-4(r6)
+ stwu r8,-8(r6)
+ bdnz 1b
+ andi. r5,r5,7
+2: cmplwi 0,r5,4
+ blt 3f
+ lwzu r0,-4(r4)
+ subi r5,r5,4
+ stwu r0,-4(r6)
+3: cmpwi 0,r5,0
+ beqlr
+ mtctr r5
+4: lbzu r0,-1(r4)
+ stbu r0,-1(r6)
+ bdnz 4b
+ blr
+5: mtctr r0
+6: lbzu r7,-1(r4)
+ stbu r7,-1(r6)
+ bdnz 6b
+ subf r5,r0,r5
+ rlwinm. r7,r5,32-3,3,31
+ beq 2b
+ mtctr r7
+ b 1b
+
+ .globl memcmp
+memcmp:
+ cmpwi 0,r5,0
+ blelr
+ mtctr r5
+ addi r6,r3,-1
+ addi r4,r4,-1
+1: lbzu r3,1(r6)
+ lbzu r0,1(r4)
+ subf. r3,r0,r3
+ bdnzt 2,1b
+ blr
diff --git a/arch/ppc/boot/common/util.S b/arch/ppc/boot/common/util.S
new file mode 100644
index 0000000..47e6414
--- /dev/null
+++ b/arch/ppc/boot/common/util.S
@@ -0,0 +1,293 @@
+/*
+ * arch/ppc/boot/common/util.S
+ *
+ * Useful bootup functions, which are more easily done in asm than C.
+ *
+ * NOTE: Be very very careful about the registers you use here.
+ * We don't follow any ABI calling convention among the
+ * assembler functions that call each other, especially early
+ * in the initialization. Please preserve at least r3 and r4
+ * for these early functions, as they often contain information
+ * passed from boot roms into the C decompress function.
+ *
+ * Author: Tom Rini
+ * trini@mvista.com
+ * Derived from arch/ppc/boot/prep/head.S (Cort Dougan, many others).
+ *
+ * 2001-2004 (c) MontaVista, Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+
+#include <asm/processor.h>
+#include <asm/cache.h>
+#include <asm/ppc_asm.h>
+
+
+ .text
+
+#ifdef CONFIG_6xx
+ .globl disable_6xx_mmu
+disable_6xx_mmu:
+ /* Establish default MSR value, exception prefix 0xFFF.
+ * If necessary, this function must fix up the LR if we
+ * return to a different address space once the MMU is
+ * disabled.
+ */
+ li r8,MSR_IP|MSR_FP
+ mtmsr r8
+ isync
+
+ /* Test for a 601 */
+ mfpvr r10
+ srwi r10,r10,16
+ cmpwi 0,r10,1 /* 601 ? */
+ beq .clearbats_601
+
+ /* Clear BATs */
+ li r8,0
+ mtspr SPRN_DBAT0U,r8
+ mtspr SPRN_DBAT0L,r8
+ mtspr SPRN_DBAT1U,r8
+ mtspr SPRN_DBAT1L,r8
+ mtspr SPRN_DBAT2U,r8
+ mtspr SPRN_DBAT2L,r8
+ mtspr SPRN_DBAT3U,r8
+ mtspr SPRN_DBAT3L,r8
+.clearbats_601:
+ mtspr SPRN_IBAT0U,r8
+ mtspr SPRN_IBAT0L,r8
+ mtspr SPRN_IBAT1U,r8
+ mtspr SPRN_IBAT1L,r8
+ mtspr SPRN_IBAT2U,r8
+ mtspr SPRN_IBAT2L,r8
+ mtspr SPRN_IBAT3U,r8
+ mtspr SPRN_IBAT3L,r8
+ isync
+ sync
+ sync
+
+ /* Set segment registers */
+ li r8,16 /* load up segment register values */
+ mtctr r8 /* for context 0 */
+ lis r8,0x2000 /* Ku = 1, VSID = 0 */
+ li r10,0
+3: mtsrin r8,r10
+ addi r8,r8,0x111 /* increment VSID */
+ addis r10,r10,0x1000 /* address of next segment */
+ bdnz 3b
+ blr
+
+ .globl disable_6xx_l1cache
+disable_6xx_l1cache:
+ /* Enable, invalidate and then disable the L1 icache/dcache. */
+ li r8,0
+ ori r8,r8,(HID0_ICE|HID0_DCE|HID0_ICFI|HID0_DCI)
+ mfspr r11,SPRN_HID0
+ or r11,r11,r8
+ andc r10,r11,r8
+ isync
+ mtspr SPRN_HID0,r8
+ sync
+ isync
+ mtspr SPRN_HID0,r10
+ sync
+ isync
+ blr
+#endif
+
+ .globl _setup_L2CR
+_setup_L2CR:
+/*
+ * We should be skipping this section on CPUs where this results in an
+ * illegal instruction. If not, please send trini@kernel.crashing.org
+ * the PVR of your CPU.
+ */
+ /* Invalidate/disable L2 cache */
+ sync
+ isync
+ mfspr r8,SPRN_L2CR
+ rlwinm r8,r8,0,1,31
+ oris r8,r8,L2CR_L2I@h
+ sync
+ isync
+ mtspr SPRN_L2CR,r8
+ sync
+ isync
+
+ /* Wait for the invalidation to complete */
+ mfspr r8,SPRN_PVR
+ srwi r8,r8,16
+ cmplwi cr0,r8,0x8000 /* 7450 */
+ cmplwi cr1,r8,0x8001 /* 7455 */
+ cmplwi cr2,r8,0x8002 /* 7457 */
+ cror 4*cr0+eq,4*cr0+eq,4*cr1+eq /* Now test if any are true. */
+ cror 4*cr0+eq,4*cr0+eq,4*cr2+eq
+ bne 2f
+
+1: mfspr r8,SPRN_L2CR /* On 745x, poll L2I bit (bit 10) */
+ rlwinm. r9,r8,0,10,10
+ bne 1b
+ b 3f
+
+2: mfspr r8,SPRN_L2CR /* On 75x & 74[01]0, poll L2IP bit (bit 31) */
+ rlwinm. r9,r8,0,31,31
+ bne 2b
+
+3: rlwinm r8,r8,0,11,9 /* Turn off L2I bit */
+ sync
+ isync
+ mtspr SPRN_L2CR,r8
+ sync
+ isync
+ blr
+
+ .globl _setup_L3CR
+_setup_L3CR:
+ /* Invalidate/disable L3 cache */
+ sync
+ isync
+ mfspr r8,SPRN_L3CR
+ rlwinm r8,r8,0,1,31
+ ori r8,r8,L3CR_L3I@l
+ sync
+ isync
+ mtspr SPRN_L3CR,r8
+ sync
+ isync
+
+ /* Wait for the invalidation to complete */
+1: mfspr r8,SPRN_L3CR
+ rlwinm. r9,r8,0,21,21
+ bne 1b
+
+ rlwinm r8,r8,0,22,20 /* Turn off L3I bit */
+ sync
+ isync
+ mtspr SPRN_L3CR,r8
+ sync
+ isync
+ blr
+
+
+/* udelay (on non-601 processors) needs to know the period of the
+ * timebase in nanoseconds. This used to be hardcoded to be 60ns
+ * (period of 66MHz/4). Now a variable is used that is initialized to
+ * 60 for backward compatibility, but it can be overridden as necessary
+ * with code something like this:
+ * extern unsigned long timebase_period_ns;
+ * timebase_period_ns = 1000000000 / bd->bi_tbfreq;
+ */
+ .data
+ .globl timebase_period_ns
+timebase_period_ns:
+ .long 60
+
+ .text
+/*
+ * Delay for a number of microseconds
+ */
+ .globl udelay
+udelay:
+ mfspr r4,SPRN_PVR
+ srwi r4,r4,16
+ cmpwi 0,r4,1 /* 601 ? */
+ bne .udelay_not_601
+00: li r0,86 /* Instructions / microsecond? */
+ mtctr r0
+10: addi r0,r0,0 /* NOP */
+ bdnz 10b
+ subic. r3,r3,1
+ bne 00b
+ blr
+
+.udelay_not_601:
+ mulli r4,r3,1000 /* nanoseconds */
+ /* Change r4 to be the number of ticks using:
+ * (nanoseconds + (timebase_period_ns - 1 )) / timebase_period_ns
+ * timebase_period_ns defaults to 60 (16.6MHz) */
+ lis r5,timebase_period_ns@ha
+ lwz r5,timebase_period_ns@l(r5)
+ add r4,r4,r5
+ addi r4,r4,-1
+ divw r4,r4,r5 /* BUS ticks */
+1: mftbu r5
+ mftb r6
+ mftbu r7
+ cmpw 0,r5,r7
+ bne 1b /* Get [synced] base time */
+ addc r9,r6,r4 /* Compute end time */
+ addze r8,r5
+2: mftbu r5
+ cmpw 0,r5,r8
+ blt 2b
+ bgt 3f
+ mftb r6
+ cmpw 0,r6,r9
+ blt 2b
+3: blr
+
+ .section ".relocate_code","xa"
+/*
+ * Flush and enable instruction cache
+ * First, flush the data cache in case it was enabled and may be
+ * holding instructions for copy back.
+ */
+_GLOBAL(flush_instruction_cache)
+ mflr r6
+ bl flush_data_cache
+
+#ifdef CONFIG_8xx
+ lis r3, IDC_INVALL@h
+ mtspr SPRN_IC_CST, r3
+ lis r3, IDC_ENABLE@h
+ mtspr SPRN_IC_CST, r3
+ lis r3, IDC_DISABLE@h
+ mtspr SPRN_DC_CST, r3
+#elif CONFIG_4xx
+ lis r3,start@h # r9 = &_start
+ lis r4,_etext@ha
+ addi r4,r4,_etext@l # r8 = &_etext
+1: dcbf r0,r3 # Flush the data cache
+ icbi r0,r3 # Invalidate the instruction cache
+ addi r3,r3,0x10 # Increment by one cache line
+ cmplwi cr0,r3,r4 # Are we at the end yet?
+ blt 1b # No, keep flushing and invalidating
+#else
+ /* Enable, invalidate and then disable the L1 icache/dcache. */
+ li r3,0
+ ori r3,r3,(HID0_ICE|HID0_DCE|HID0_ICFI|HID0_DCI)
+ mfspr r4,SPRN_HID0
+ or r5,r4,r3
+ isync
+ mtspr SPRN_HID0,r5
+ sync
+ isync
+ ori r5,r4,HID0_ICE /* Enable cache */
+ mtspr SPRN_HID0,r5
+ sync
+ isync
+#endif
+ mtlr r6
+ blr
+
+#define NUM_CACHE_LINES 128*8
+#define cache_flush_buffer 0x1000
+
+/*
+ * Flush data cache
+ * Do this by just reading lots of stuff into the cache.
+ */
+_GLOBAL(flush_data_cache)
+ lis r3,cache_flush_buffer@h
+ ori r3,r3,cache_flush_buffer@l
+ li r4,NUM_CACHE_LINES
+ mtctr r4
+00: lwz r4,0(r3)
+ addi r3,r3,L1_CACHE_BYTES /* Next line, please */
+ bdnz 00b
+10: blr
+
+ .previous
+
diff --git a/arch/ppc/boot/images/Makefile b/arch/ppc/boot/images/Makefile
new file mode 100644
index 0000000..774de8e
--- /dev/null
+++ b/arch/ppc/boot/images/Makefile
@@ -0,0 +1,27 @@
+#
+# This dir holds all of the images for PPC machines.
+# Tom Rini January 2001
+
+MKIMAGE := $(srctree)/scripts/mkuboot.sh
+
+extra-y := vmlinux.bin vmlinux.gz
+
+OBJCOPYFLAGS_vmlinux.bin := -O binary
+$(obj)/vmlinux.bin: vmlinux FORCE
+ $(call if_changed,objcopy)
+
+$(obj)/vmlinux.gz: $(obj)/vmlinux.bin FORCE
+ $(call if_changed,gzip)
+
+quiet_cmd_uimage = UIMAGE $@
+ cmd_uimage = $(CONFIG_SHELL) $(MKIMAGE) -A ppc -O linux -T kernel \
+ -C gzip -a 00000000 -e 00000000 -n 'Linux-$(KERNELRELEASE)' \
+ -d $< $@
+
+targets += uImage
+$(obj)/uImage: $(obj)/vmlinux.gz
+ $(call if_changed,uimage)
+ @echo ' Image $@ is ready'
+
+# Files generated that shall be removed upon make clean
+clean-files := sImage vmapus vmlinux* miboot* zImage* uImage
diff --git a/arch/ppc/boot/include/cpc700.h b/arch/ppc/boot/include/cpc700.h
new file mode 100644
index 0000000..28cfcde
--- /dev/null
+++ b/arch/ppc/boot/include/cpc700.h
@@ -0,0 +1,26 @@
+
+#ifndef __PPC_BOOT_CPC700_H
+#define __PPC_BOOT_CPC700_H
+
+#define CPC700_MEM_CFGADDR 0xff500008
+#define CPC700_MEM_CFGDATA 0xff50000c
+
+#define CPC700_MB0SA 0x38
+#define CPC700_MB0EA 0x58
+#define CPC700_MB1SA 0x3c
+#define CPC700_MB1EA 0x5c
+#define CPC700_MB2SA 0x40
+#define CPC700_MB2EA 0x60
+#define CPC700_MB3SA 0x44
+#define CPC700_MB3EA 0x64
+#define CPC700_MB4SA 0x48
+#define CPC700_MB4EA 0x68
+
+static inline long
+cpc700_read_memreg(int reg)
+{
+ out_be32((volatile unsigned int *) CPC700_MEM_CFGADDR, reg);
+ return in_be32((volatile unsigned int *) CPC700_MEM_CFGDATA);
+}
+
+#endif
diff --git a/arch/ppc/boot/include/iso_font.h b/arch/ppc/boot/include/iso_font.h
new file mode 100644
index 0000000..bff050e
--- /dev/null
+++ b/arch/ppc/boot/include/iso_font.h
@@ -0,0 +1,257 @@
+static const unsigned char font[] = {
+/* 0x00 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+/* 0x01 */ 0x00,0x00,0x7E,0x81,0xA5,0x81,0x81,0xBD,0x99,0x81,0x81,0x7E,0x00,0x00,0x00,0x00,
+/* 0x02 */ 0x00,0x00,0x7E,0xFF,0xDB,0xFF,0xFF,0xC3,0xC3,0xE7,0xFF,0x7E,0x00,0x00,0x00,0x00,
+/* 0x03 */ 0x00,0x00,0x00,0x00,0x6C,0xFE,0xFE,0xFE,0xFE,0x7C,0x38,0x10,0x00,0x00,0x00,0x00,
+/* 0x04 */ 0x00,0x00,0x00,0x00,0x10,0x38,0x7C,0xFE,0x7C,0x38,0x10,0x00,0x00,0x00,0x00,0x00,
+/* 0x05 */ 0x00,0x00,0x00,0x18,0x3C,0x3C,0xE7,0xE7,0xE7,0x18,0x18,0x3C,0x00,0x00,0x00,0x00,
+/* 0x06 */ 0x00,0x00,0x00,0x18,0x3C,0x7E,0xFF,0xFF,0x7E,0x18,0x18,0x3C,0x00,0x00,0x00,0x00,
+/* 0x07 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x3C,0x3C,0x18,0x00,0x00,0x00,0x00,0x00,0x00,
+/* 0x08 */ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xE7,0xC3,0xC3,0xE7,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+/* 0x09 */ 0x00,0x00,0x00,0x00,0x00,0x3C,0x66,0x42,0x42,0x66,0x3C,0x00,0x00,0x00,0x00,0x00,
+/* 0x0A */ 0xFF,0xFF,0xFF,0xFF,0xFF,0xC3,0x99,0xBD,0xBD,0x99,0xC3,0xFF,0xFF,0xFF,0xFF,0xFF,
+/* 0x0B */ 0x00,0x00,0x3E,0x0E,0x1A,0x32,0x78,0xCC,0xCC,0xCC,0xCC,0x78,0x00,0x00,0x00,0x00,
+/* 0x0C */ 0x00,0x00,0x3C,0x66,0x66,0x66,0x66,0x3C,0x18,0x7E,0x18,0x18,0x00,0x00,0x00,0x00,
+/* 0x0D */ 0x00,0x00,0x30,0x38,0x3C,0x36,0x33,0x30,0x30,0x70,0xF0,0xE0,0x00,0x00,0x00,0x00,
+/* 0x0E */ 0x00,0x00,0x7F,0x63,0x7F,0x63,0x63,0x63,0x63,0x67,0xE7,0xE6,0xC0,0x00,0x00,0x00,
+/* 0x0F */ 0x00,0x00,0x00,0x18,0x18,0xDB,0x3C,0xE7,0x3C,0xDB,0x18,0x18,0x00,0x00,0x00,0x00,
+/* 0x10 */ 0x00,0x80,0xC0,0xE0,0xF0,0xF8,0xFE,0xF8,0xF0,0xE0,0xC0,0x80,0x00,0x00,0x00,0x00,
+/* 0x11 */ 0x00,0x02,0x06,0x0E,0x1E,0x3E,0xFE,0x3E,0x1E,0x0E,0x06,0x02,0x00,0x00,0x00,0x00,
+/* 0x12 */ 0x00,0x00,0x18,0x3C,0x7E,0x18,0x18,0x18,0x7E,0x3C,0x18,0x00,0x00,0x00,0x00,0x00,
+/* 0x13 */ 0x00,0x00,0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x00,0x66,0x66,0x00,0x00,0x00,0x00,
+/* 0x14 */ 0x00,0x00,0x7F,0xDB,0xDB,0xDB,0x7B,0x1B,0x1B,0x1B,0x1B,0x1B,0x00,0x00,0x00,0x00,
+/* 0x15 */ 0x00,0x7C,0xC6,0x60,0x38,0x6C,0xC6,0xC6,0x6C,0x38,0x0C,0xC6,0x7C,0x00,0x00,0x00,
+/* 0x16 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0xFE,0xFE,0xFE,0x00,0x00,0x00,0x00,
+/* 0x17 */ 0x00,0x00,0x18,0x3C,0x7E,0x18,0x18,0x18,0x7E,0x3C,0x18,0x7E,0x00,0x00,0x00,0x00,
+/* 0x18 */ 0x00,0x00,0x18,0x3C,0x7E,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x00,0x00,0x00,0x00,
+/* 0x19 */ 0x00,0x00,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x7E,0x3C,0x18,0x00,0x00,0x00,0x00,
+/* 0x1A */ 0x00,0x00,0x00,0x00,0x00,0x18,0x0C,0xFE,0x0C,0x18,0x00,0x00,0x00,0x00,0x00,0x00,
+/* 0x1B */ 0x00,0x00,0x00,0x00,0x00,0x30,0x60,0xFE,0x60,0x30,0x00,0x00,0x00,0x00,0x00,0x00,
+/* 0x1C */ 0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0xC0,0xC0,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,
+/* 0x1D */ 0x00,0x00,0x00,0x00,0x00,0x28,0x6C,0xFE,0x6C,0x28,0x00,0x00,0x00,0x00,0x00,0x00,
+/* 0x1E */ 0x00,0x00,0x00,0x00,0x10,0x38,0x38,0x7C,0x7C,0xFE,0xFE,0x00,0x00,0x00,0x00,0x00,
+/* 0x1F */ 0x00,0x00,0x00,0x00,0xFE,0xFE,0x7C,0x7C,0x38,0x38,0x10,0x00,0x00,0x00,0x00,0x00,
+/* 0x20 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+/* 0x21 */ 0x00,0x00,0x18,0x3C,0x3C,0x3C,0x18,0x18,0x18,0x00,0x18,0x18,0x00,0x00,0x00,0x00,
+/* 0x22 */ 0x00,0x66,0x66,0x66,0x24,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+/* 0x23 */ 0x00,0x00,0x00,0x6C,0x6C,0xFE,0x6C,0x6C,0x6C,0xFE,0x6C,0x6C,0x00,0x00,0x00,0x00,
+/* 0x24 */ 0x18,0x18,0x7C,0xC6,0xC2,0xC0,0x7C,0x06,0x06,0x86,0xC6,0x7C,0x18,0x18,0x00,0x00,
+/* 0x25 */ 0x00,0x00,0x00,0x00,0xC2,0xC6,0x0C,0x18,0x30,0x60,0xC6,0x86,0x00,0x00,0x00,0x00,
+/* 0x26 */ 0x00,0x00,0x38,0x6C,0x6C,0x38,0x76,0xDC,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00,
+/* 0x27 */ 0x00,0x30,0x30,0x30,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+/* 0x28 */ 0x00,0x00,0x0C,0x18,0x30,0x30,0x30,0x30,0x30,0x30,0x18,0x0C,0x00,0x00,0x00,0x00,
+/* 0x29 */ 0x00,0x00,0x30,0x18,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x18,0x30,0x00,0x00,0x00,0x00,
+/* 0x2A */ 0x00,0x00,0x00,0x00,0x00,0x66,0x3C,0xFF,0x3C,0x66,0x00,0x00,0x00,0x00,0x00,0x00,
+/* 0x2B */ 0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x7E,0x18,0x18,0x00,0x00,0x00,0x00,0x00,0x00,
+/* 0x2C */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x18,0x30,0x00,0x00,0x00,
+/* 0x2D */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+/* 0x2E */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x00,
+/* 0x2F */ 0x00,0x00,0x00,0x00,0x02,0x06,0x0C,0x18,0x30,0x60,0xC0,0x80,0x00,0x00,0x00,0x00,
+/* 0x30 */ 0x00,0x00,0x38,0x6C,0xC6,0xC6,0xD6,0xD6,0xC6,0xC6,0x6C,0x38,0x00,0x00,0x00,0x00,
+/* 0x31 */ 0x00,0x00,0x18,0x38,0x78,0x18,0x18,0x18,0x18,0x18,0x18,0x7E,0x00,0x00,0x00,0x00,
+/* 0x32 */ 0x00,0x00,0x7C,0xC6,0x06,0x0C,0x18,0x30,0x60,0xC0,0xC6,0xFE,0x00,0x00,0x00,0x00,
+/* 0x33 */ 0x00,0x00,0x7C,0xC6,0x06,0x06,0x3C,0x06,0x06,0x06,0xC6,0x7C,0x00,0x00,0x00,0x00,
+/* 0x34 */ 0x00,0x00,0x0C,0x1C,0x3C,0x6C,0xCC,0xFE,0x0C,0x0C,0x0C,0x1E,0x00,0x00,0x00,0x00,
+/* 0x35 */ 0x00,0x00,0xFE,0xC0,0xC0,0xC0,0xFC,0x06,0x06,0x06,0xC6,0x7C,0x00,0x00,0x00,0x00,
+/* 0x36 */ 0x00,0x00,0x38,0x60,0xC0,0xC0,0xFC,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00,
+/* 0x37 */ 0x00,0x00,0xFE,0xC6,0x06,0x06,0x0C,0x18,0x30,0x30,0x30,0x30,0x00,0x00,0x00,0x00,
+/* 0x38 */ 0x00,0x00,0x7C,0xC6,0xC6,0xC6,0x7C,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00,
+/* 0x39 */ 0x00,0x00,0x7C,0xC6,0xC6,0xC6,0x7E,0x06,0x06,0x06,0x0C,0x78,0x00,0x00,0x00,0x00,
+/* 0x3A */ 0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x00,0x00,
+/* 0x3B */ 0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x18,0x18,0x30,0x00,0x00,0x00,0x00,
+/* 0x3C */ 0x00,0x00,0x00,0x06,0x0C,0x18,0x30,0x60,0x30,0x18,0x0C,0x06,0x00,0x00,0x00,0x00,
+/* 0x3D */ 0x00,0x00,0x00,0x00,0x00,0x7E,0x00,0x00,0x7E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+/* 0x3E */ 0x00,0x00,0x00,0x60,0x30,0x18,0x0C,0x06,0x0C,0x18,0x30,0x60,0x00,0x00,0x00,0x00,
+/* 0x3F */ 0x00,0x00,0x7C,0xC6,0xC6,0x0C,0x18,0x18,0x18,0x00,0x18,0x18,0x00,0x00,0x00,0x00,
+/* 0x40 */ 0x00,0x00,0x00,0x7C,0xC6,0xC6,0xDE,0xDE,0xDE,0xDC,0xC0,0x7C,0x00,0x00,0x00,0x00,
+/* 0x41 */ 0x00,0x00,0x10,0x38,0x6C,0xC6,0xC6,0xFE,0xC6,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00,
+/* 0x42 */ 0x00,0x00,0xFC,0x66,0x66,0x66,0x7C,0x66,0x66,0x66,0x66,0xFC,0x00,0x00,0x00,0x00,
+/* 0x43 */ 0x00,0x00,0x3C,0x66,0xC2,0xC0,0xC0,0xC0,0xC0,0xC2,0x66,0x3C,0x00,0x00,0x00,0x00,
+/* 0x44 */ 0x00,0x00,0xF8,0x6C,0x66,0x66,0x66,0x66,0x66,0x66,0x6C,0xF8,0x00,0x00,0x00,0x00,
+/* 0x45 */ 0x00,0x00,0xFE,0x66,0x62,0x68,0x78,0x68,0x60,0x62,0x66,0xFE,0x00,0x00,0x00,0x00,
+/* 0x46 */ 0x00,0x00,0xFE,0x66,0x62,0x68,0x78,0x68,0x60,0x60,0x60,0xF0,0x00,0x00,0x00,0x00,
+/* 0x47 */ 0x00,0x00,0x3C,0x66,0xC2,0xC0,0xC0,0xDE,0xC6,0xC6,0x66,0x3A,0x00,0x00,0x00,0x00,
+/* 0x48 */ 0x00,0x00,0xC6,0xC6,0xC6,0xC6,0xFE,0xC6,0xC6,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00,
+/* 0x49 */ 0x00,0x00,0x3C,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00,
+/* 0x4A */ 0x00,0x00,0x1E,0x0C,0x0C,0x0C,0x0C,0x0C,0xCC,0xCC,0xCC,0x78,0x00,0x00,0x00,0x00,
+/* 0x4B */ 0x00,0x00,0xE6,0x66,0x66,0x6C,0x78,0x78,0x6C,0x66,0x66,0xE6,0x00,0x00,0x00,0x00,
+/* 0x4C */ 0x00,0x00,0xF0,0x60,0x60,0x60,0x60,0x60,0x60,0x62,0x66,0xFE,0x00,0x00,0x00,0x00,
+/* 0x4D */ 0x00,0x00,0xC6,0xEE,0xFE,0xFE,0xD6,0xC6,0xC6,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00,
+/* 0x4E */ 0x00,0x00,0xC6,0xE6,0xF6,0xFE,0xDE,0xCE,0xC6,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00,
+/* 0x4F */ 0x00,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00,
+/* 0x50 */ 0x00,0x00,0xFC,0x66,0x66,0x66,0x7C,0x60,0x60,0x60,0x60,0xF0,0x00,0x00,0x00,0x00,
+/* 0x51 */ 0x00,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xD6,0xDE,0x7C,0x0C,0x0E,0x00,0x00,
+/* 0x52 */ 0x00,0x00,0xFC,0x66,0x66,0x66,0x7C,0x6C,0x66,0x66,0x66,0xE6,0x00,0x00,0x00,0x00,
+/* 0x53 */ 0x00,0x00,0x7C,0xC6,0xC6,0x60,0x38,0x0C,0x06,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00,
+/* 0x54 */ 0x00,0x00,0x7E,0x7E,0x5A,0x18,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00,
+/* 0x55 */ 0x00,0x00,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00,
+/* 0x56 */ 0x00,0x00,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x6C,0x38,0x10,0x00,0x00,0x00,0x00,
+/* 0x57 */ 0x00,0x00,0xC6,0xC6,0xC6,0xC6,0xD6,0xD6,0xD6,0xFE,0xEE,0x6C,0x00,0x00,0x00,0x00,
+/* 0x58 */ 0x00,0x00,0xC6,0xC6,0x6C,0x7C,0x38,0x38,0x7C,0x6C,0xC6,0xC6,0x00,0x00,0x00,0x00,
+/* 0x59 */ 0x00,0x00,0x66,0x66,0x66,0x66,0x3C,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00,
+/* 0x5A */ 0x00,0x00,0xFE,0xC6,0x86,0x0C,0x18,0x30,0x60,0xC2,0xC6,0xFE,0x00,0x00,0x00,0x00,
+/* 0x5B */ 0x00,0x00,0x3C,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x3C,0x00,0x00,0x00,0x00,
+/* 0x5C */ 0x00,0x00,0x00,0x80,0xC0,0xE0,0x70,0x38,0x1C,0x0E,0x06,0x02,0x00,0x00,0x00,0x00,
+/* 0x5D */ 0x00,0x00,0x3C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x3C,0x00,0x00,0x00,0x00,
+/* 0x5E */ 0x10,0x38,0x6C,0xC6,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+/* 0x5F */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0x00,
+/* 0x60 */ 0x30,0x30,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+/* 0x61 */ 0x00,0x00,0x00,0x00,0x00,0x78,0x0C,0x7C,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00,
+/* 0x62 */ 0x00,0x00,0xE0,0x60,0x60,0x78,0x6C,0x66,0x66,0x66,0x66,0x7C,0x00,0x00,0x00,0x00,
+/* 0x63 */ 0x00,0x00,0x00,0x00,0x00,0x7C,0xC6,0xC0,0xC0,0xC0,0xC6,0x7C,0x00,0x00,0x00,0x00,
+/* 0x64 */ 0x00,0x00,0x1C,0x0C,0x0C,0x3C,0x6C,0xCC,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00,
+/* 0x65 */ 0x00,0x00,0x00,0x00,0x00,0x7C,0xC6,0xFE,0xC0,0xC0,0xC6,0x7C,0x00,0x00,0x00,0x00,
+/* 0x66 */ 0x00,0x00,0x38,0x6C,0x64,0x60,0xF0,0x60,0x60,0x60,0x60,0xF0,0x00,0x00,0x00,0x00,
+/* 0x67 */ 0x00,0x00,0x00,0x00,0x00,0x3E,0x66,0x66,0x66,0x66,0x66,0x3E,0x06,0x66,0x3C,0x00,
+/* 0x68 */ 0x00,0x00,0xE0,0x60,0x60,0x6C,0x76,0x66,0x66,0x66,0x66,0xE6,0x00,0x00,0x00,0x00,
+/* 0x69 */ 0x00,0x00,0x18,0x18,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00,
+/* 0x6A */ 0x00,0x00,0x06,0x06,0x00,0x0E,0x06,0x06,0x06,0x06,0x06,0x06,0x66,0x66,0x3C,0x00,
+/* 0x6B */ 0x00,0x00,0xE0,0x60,0x60,0x66,0x6C,0x78,0x78,0x6C,0x66,0xE6,0x00,0x00,0x00,0x00,
+/* 0x6C */ 0x00,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00,
+/* 0x6D */ 0x00,0x00,0x00,0x00,0x00,0x6C,0xFE,0xD6,0xD6,0xD6,0xC6,0xC6,0x00,0x00,0x00,0x00,
+/* 0x6E */ 0x00,0x00,0x00,0x00,0x00,0xDC,0x66,0x66,0x66,0x66,0x66,0x66,0x00,0x00,0x00,0x00,
+/* 0x6F */ 0x00,0x00,0x00,0x00,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00,
+/* 0x70 */ 0x00,0x00,0x00,0x00,0x00,0xFC,0x66,0x66,0x66,0x66,0x66,0x7C,0x60,0x60,0xF0,0x00,
+/* 0x71 */ 0x00,0x00,0x00,0x00,0x00,0x7E,0xCC,0xCC,0xCC,0xCC,0xCC,0x7C,0x0C,0x0C,0x1E,0x00,
+/* 0x72 */ 0x00,0x00,0x00,0x00,0x00,0xDC,0x76,0x66,0x60,0x60,0x60,0xF0,0x00,0x00,0x00,0x00,
+/* 0x73 */ 0x00,0x00,0x00,0x00,0x00,0x7C,0xC6,0x60,0x38,0x0C,0xC6,0x7C,0x00,0x00,0x00,0x00,
+/* 0x74 */ 0x00,0x00,0x10,0x30,0x30,0xFC,0x30,0x30,0x30,0x30,0x36,0x1C,0x00,0x00,0x00,0x00,
+/* 0x75 */ 0x00,0x00,0x00,0x00,0x00,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00,
+/* 0x76 */ 0x00,0x00,0x00,0x00,0x00,0x66,0x66,0x66,0x66,0x66,0x3C,0x18,0x00,0x00,0x00,0x00,
+/* 0x77 */ 0x00,0x00,0x00,0x00,0x00,0xC6,0xC6,0xD6,0xD6,0xD6,0xFE,0x6C,0x00,0x00,0x00,0x00,
+/* 0x78 */ 0x00,0x00,0x00,0x00,0x00,0xC6,0x6C,0x38,0x38,0x38,0x6C,0xC6,0x00,0x00,0x00,0x00,
+/* 0x79 */ 0x00,0x00,0x00,0x00,0x00,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7E,0x06,0x0C,0xF8,0x00,
+/* 0x7A */ 0x00,0x00,0x00,0x00,0x00,0xFE,0xCC,0x18,0x30,0x60,0xC6,0xFE,0x00,0x00,0x00,0x00,
+/* 0x7B */ 0x00,0x00,0x0E,0x18,0x18,0x18,0x70,0x18,0x18,0x18,0x18,0x0E,0x00,0x00,0x00,0x00,
+/* 0x7C */ 0x00,0x00,0x18,0x18,0x18,0x18,0x00,0x18,0x18,0x18,0x18,0x18,0x00,0x00,0x00,0x00,
+/* 0x7D */ 0x00,0x00,0x70,0x18,0x18,0x18,0x0E,0x18,0x18,0x18,0x18,0x70,0x00,0x00,0x00,0x00,
+/* 0x7E */ 0x00,0x00,0x76,0xDC,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+/* 0x7F */ 0x00,0x00,0x00,0x00,0x10,0x38,0x6C,0xC6,0xC6,0xC6,0xFE,0x00,0x00,0x00,0x00,0x00,
+/* 0x80 */ 0x00,0x00,0x3C,0x66,0xC2,0xC0,0xC0,0xC0,0xC2,0x66,0x3C,0x0C,0x06,0x7C,0x00,0x00,
+/* 0x81 */ 0x00,0x00,0xCC,0x00,0x00,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00,
+/* 0x82 */ 0x00,0x0C,0x18,0x30,0x00,0x7C,0xC6,0xC6,0xFE,0xC0,0xC6,0x7C,0x00,0x00,0x00,0x00,
+/* 0x83 */ 0x00,0x10,0x38,0x6C,0x00,0x78,0x0C,0x7C,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00,
+/* 0x84 */ 0x00,0x00,0xCC,0x00,0x00,0x78,0x0C,0x7C,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00,
+/* 0x85 */ 0x00,0x60,0x30,0x18,0x00,0x78,0x0C,0x7C,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00,
+/* 0x86 */ 0x00,0x38,0x6C,0x38,0x00,0x78,0x0C,0x7C,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00,
+/* 0x87 */ 0x00,0x00,0x00,0x00,0x3C,0x66,0x60,0x60,0x66,0x3C,0x0C,0x06,0x3C,0x00,0x00,0x00,
+/* 0x88 */ 0x00,0x10,0x38,0x6C,0x00,0x7C,0xC6,0xC6,0xFE,0xC0,0xC6,0x7C,0x00,0x00,0x00,0x00,
+/* 0x89 */ 0x00,0x00,0xC6,0x00,0x00,0x7C,0xC6,0xC6,0xFE,0xC0,0xC6,0x7C,0x00,0x00,0x00,0x00,
+/* 0x8A */ 0x00,0x60,0x30,0x18,0x00,0x7C,0xC6,0xC6,0xFE,0xC0,0xC6,0x7C,0x00,0x00,0x00,0x00,
+/* 0x8B */ 0x00,0x00,0x66,0x00,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00,
+/* 0x8C */ 0x00,0x18,0x3C,0x66,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00,
+/* 0x8D */ 0x00,0x60,0x30,0x18,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00,
+/* 0x8E */ 0x00,0xC6,0x00,0x10,0x38,0x6C,0xC6,0xC6,0xFE,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00,
+/* 0x8F */ 0x38,0x6C,0x38,0x00,0x38,0x6C,0xC6,0xC6,0xFE,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00,
+/* 0x90 */ 0x18,0x30,0x60,0x00,0xFE,0x66,0x60,0x7C,0x60,0x60,0x66,0xFE,0x00,0x00,0x00,0x00,
+/* 0x91 */ 0x00,0x00,0x00,0x00,0x00,0xCC,0x76,0x36,0x7E,0xD8,0xD8,0x6E,0x00,0x00,0x00,0x00,
+/* 0x92 */ 0x00,0x00,0x3E,0x6C,0xCC,0xCC,0xFE,0xCC,0xCC,0xCC,0xCC,0xCE,0x00,0x00,0x00,0x00,
+/* 0x93 */ 0x00,0x10,0x38,0x6C,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00,
+/* 0x94 */ 0x00,0x00,0xC6,0x00,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00,
+/* 0x95 */ 0x00,0x60,0x30,0x18,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00,
+/* 0x96 */ 0x00,0x30,0x78,0xCC,0x00,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00,
+/* 0x97 */ 0x00,0x60,0x30,0x18,0x00,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00,
+/* 0x98 */ 0x00,0x00,0xC6,0x00,0x00,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7E,0x06,0x0C,0x78,0x00,
+/* 0x99 */ 0x00,0xC6,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00,
+/* 0x9A */ 0x00,0xC6,0x00,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00,
+/* 0x9B */ 0x00,0x18,0x18,0x3C,0x66,0x60,0x60,0x60,0x66,0x3C,0x18,0x18,0x00,0x00,0x00,0x00,
+/* 0x9C */ 0x00,0x38,0x6C,0x64,0x60,0xF8,0x60,0x60,0x60,0x60,0xE6,0xFC,0x00,0x00,0x00,0x00,
+/* 0x9D */ 0x00,0x00,0x66,0x66,0x3C,0x18,0x7E,0x18,0x7E,0x18,0x18,0x18,0x00,0x00,0x00,0x00,
+/* 0x9E */ 0x00,0xF8,0xCC,0xCC,0xF8,0xC4,0xCC,0xDE,0xCC,0xCC,0xCC,0xC6,0x00,0x00,0x00,0x00,
+/* 0x9F */ 0x00,0x0E,0x1B,0x18,0x18,0x18,0x7E,0x18,0x18,0x18,0x18,0x18,0xD8,0x70,0x00,0x00,
+/* 0xA0 */ 0x00,0x18,0x30,0x60,0x00,0x78,0x0C,0x7C,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00,
+/* 0xA1 */ 0x00,0x0C,0x18,0x30,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00,
+/* 0xA2 */ 0x00,0x18,0x30,0x60,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00,
+/* 0xA3 */ 0x00,0x18,0x30,0x60,0x00,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00,
+/* 0xA4 */ 0x00,0x00,0x76,0xDC,0x00,0xDC,0x66,0x66,0x66,0x66,0x66,0x66,0x00,0x00,0x00,0x00,
+/* 0xA5 */ 0x76,0xDC,0x00,0xC6,0xE6,0xF6,0xFE,0xDE,0xCE,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00,
+/* 0xA6 */ 0x00,0x3C,0x6C,0x6C,0x3E,0x00,0x7E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+/* 0xA7 */ 0x00,0x38,0x6C,0x6C,0x38,0x00,0x7C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+/* 0xA8 */ 0x00,0x00,0x30,0x30,0x00,0x30,0x30,0x60,0xC0,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00,
+/* 0xA9 */ 0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0xC0,0xC0,0xC0,0xC0,0x00,0x00,0x00,0x00,0x00,
+/* 0xAA */ 0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0x06,0x06,0x06,0x06,0x00,0x00,0x00,0x00,0x00,
+/* 0xAB */ 0x00,0xC0,0xC0,0xC2,0xC6,0xCC,0x18,0x30,0x60,0xDC,0x86,0x0C,0x18,0x3E,0x00,0x00,
+/* 0xAC */ 0x00,0xC0,0xC0,0xC2,0xC6,0xCC,0x18,0x30,0x66,0xCE,0x9E,0x3E,0x06,0x06,0x00,0x00,
+/* 0xAD */ 0x00,0x00,0x18,0x18,0x00,0x18,0x18,0x18,0x3C,0x3C,0x3C,0x18,0x00,0x00,0x00,0x00,
+/* 0xAE */ 0x00,0x00,0x00,0x00,0x00,0x36,0x6C,0xD8,0x6C,0x36,0x00,0x00,0x00,0x00,0x00,0x00,
+/* 0xAF */ 0x00,0x00,0x00,0x00,0x00,0xD8,0x6C,0x36,0x6C,0xD8,0x00,0x00,0x00,0x00,0x00,0x00,
+/* 0xB0 */ 0x11,0x44,0x11,0x44,0x11,0x44,0x11,0x44,0x11,0x44,0x11,0x44,0x11,0x44,0x11,0x44,
+/* 0xB1 */ 0x55,0xAA,0x55,0xAA,0x55,0xAA,0x55,0xAA,0x55,0xAA,0x55,0xAA,0x55,0xAA,0x55,0xAA,
+/* 0xB2 */ 0xDD,0x77,0xDD,0x77,0xDD,0x77,0xDD,0x77,0xDD,0x77,0xDD,0x77,0xDD,0x77,0xDD,0x77,
+/* 0xB3 */ 0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,
+/* 0xB4 */ 0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xF8,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,
+/* 0xB5 */ 0x18,0x18,0x18,0x18,0x18,0xF8,0x18,0xF8,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,
+/* 0xB6 */ 0x36,0x36,0x36,0x36,0x36,0x36,0x36,0xF6,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,
+/* 0xB7 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,
+/* 0xB8 */ 0x00,0x00,0x00,0x00,0x00,0xF8,0x18,0xF8,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,
+/* 0xB9 */ 0x36,0x36,0x36,0x36,0x36,0xF6,0x06,0xF6,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,
+/* 0xBA */ 0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,
+/* 0xBB */ 0x00,0x00,0x00,0x00,0x00,0xFE,0x06,0xF6,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,
+/* 0xBC */ 0x36,0x36,0x36,0x36,0x36,0xF6,0x06,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+/* 0xBD */ 0x36,0x36,0x36,0x36,0x36,0x36,0x36,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+/* 0xBE */ 0x18,0x18,0x18,0x18,0x18,0xF8,0x18,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+/* 0xBF */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF8,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,
+/* 0xC0 */ 0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x1F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+/* 0xC1 */ 0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+/* 0xC2 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,
+/* 0xC3 */ 0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x1F,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,
+/* 0xC4 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+/* 0xC5 */ 0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xFF,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,
+/* 0xC6 */ 0x18,0x18,0x18,0x18,0x18,0x1F,0x18,0x1F,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,
+/* 0xC7 */ 0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x37,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,
+/* 0xC8 */ 0x36,0x36,0x36,0x36,0x36,0x37,0x30,0x3F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+/* 0xC9 */ 0x00,0x00,0x00,0x00,0x00,0x3F,0x30,0x37,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,
+/* 0xCA */ 0x36,0x36,0x36,0x36,0x36,0xF7,0x00,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+/* 0xCB */ 0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0xF7,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,
+/* 0xCC */ 0x36,0x36,0x36,0x36,0x36,0x37,0x30,0x37,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,
+/* 0xCD */ 0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+/* 0xCE */ 0x36,0x36,0x36,0x36,0x36,0xF7,0x00,0xF7,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,
+/* 0xCF */ 0x18,0x18,0x18,0x18,0x18,0xFF,0x00,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+/* 0xD0 */ 0x36,0x36,0x36,0x36,0x36,0x36,0x36,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+/* 0xD1 */ 0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0xFF,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,
+/* 0xD2 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,
+/* 0xD3 */ 0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x3F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+/* 0xD4 */ 0x18,0x18,0x18,0x18,0x18,0x1F,0x18,0x1F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+/* 0xD5 */ 0x00,0x00,0x00,0x00,0x00,0x1F,0x18,0x1F,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,
+/* 0xD6 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,
+/* 0xD7 */ 0x36,0x36,0x36,0x36,0x36,0x36,0x36,0xFF,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,
+/* 0xD8 */ 0x18,0x18,0x18,0x18,0x18,0xFF,0x18,0xFF,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,
+/* 0xD9 */ 0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+/* 0xDA */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,
+/* 0xDB */ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+/* 0xDC */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+/* 0xDD */ 0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,
+/* 0xDE */ 0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,
+/* 0xDF */ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+/* 0xE0 */ 0x00,0x00,0x00,0x00,0x00,0x76,0xDC,0xD8,0xD8,0xD8,0xDC,0x76,0x00,0x00,0x00,0x00,
+/* 0xE1 */ 0x00,0x00,0x7C,0xC6,0xC6,0xC6,0xFC,0xC6,0xC6,0xC6,0xC6,0xDC,0xC0,0xC0,0x00,0x00,
+/* 0xE2 */ 0x00,0x00,0xFE,0xC6,0xC6,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0x00,0x00,0x00,0x00,
+/* 0xE3 */ 0x00,0x00,0x00,0x00,0x00,0xFE,0x6C,0x6C,0x6C,0x6C,0x6C,0x6C,0x00,0x00,0x00,0x00,
+/* 0xE4 */ 0x00,0x00,0xFE,0xC6,0x60,0x30,0x18,0x18,0x30,0x60,0xC6,0xFE,0x00,0x00,0x00,0x00,
+/* 0xE5 */ 0x00,0x00,0x00,0x00,0x00,0x7E,0xD8,0xD8,0xD8,0xD8,0xD8,0x70,0x00,0x00,0x00,0x00,
+/* 0xE6 */ 0x00,0x00,0x00,0x00,0x00,0x66,0x66,0x66,0x66,0x66,0x7C,0x60,0xC0,0x00,0x00,0x00,
+/* 0xE7 */ 0x00,0x00,0x00,0x00,0x00,0x76,0xDC,0x18,0x18,0x18,0x18,0x18,0x00,0x00,0x00,0x00,
+/* 0xE8 */ 0x00,0x00,0x7E,0x18,0x3C,0x66,0x66,0x66,0x66,0x3C,0x18,0x7E,0x00,0x00,0x00,0x00,
+/* 0xE9 */ 0x00,0x00,0x38,0x6C,0xC6,0xC6,0xFE,0xC6,0xC6,0xC6,0x6C,0x38,0x00,0x00,0x00,0x00,
+/* 0xEA */ 0x00,0x00,0x38,0x6C,0xC6,0xC6,0xC6,0x6C,0x6C,0x6C,0x6C,0xEE,0x00,0x00,0x00,0x00,
+/* 0xEB */ 0x00,0x00,0x1E,0x30,0x18,0x0C,0x3E,0x66,0x66,0x66,0x66,0x3C,0x00,0x00,0x00,0x00,
+/* 0xEC */ 0x00,0x00,0x00,0x00,0x00,0x7E,0xDB,0xDB,0xDB,0x7E,0x00,0x00,0x00,0x00,0x00,0x00,
+/* 0xED */ 0x00,0x00,0x00,0x03,0x06,0x7E,0xDB,0xDB,0xF3,0x7E,0x60,0xC0,0x00,0x00,0x00,0x00,
+/* 0xEE */ 0x00,0x00,0x1C,0x30,0x60,0x60,0x7C,0x60,0x60,0x60,0x30,0x1C,0x00,0x00,0x00,0x00,
+/* 0xEF */ 0x00,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00,
+/* 0xF0 */ 0x00,0x00,0x00,0x00,0xFE,0x00,0x00,0xFE,0x00,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,
+/* 0xF1 */ 0x00,0x00,0x00,0x00,0x18,0x18,0x7E,0x18,0x18,0x00,0x00,0xFF,0x00,0x00,0x00,0x00,
+/* 0xF2 */ 0x00,0x00,0x00,0x30,0x18,0x0C,0x06,0x0C,0x18,0x30,0x00,0x7E,0x00,0x00,0x00,0x00,
+/* 0xF3 */ 0x00,0x00,0x00,0x0C,0x18,0x30,0x60,0x30,0x18,0x0C,0x00,0x7E,0x00,0x00,0x00,0x00,
+/* 0xF4 */ 0x00,0x0E,0x1B,0x1B,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,
+/* 0xF5 */ 0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xD8,0xD8,0xD8,0x70,0x00,0x00,0x00,0x00,
+/* 0xF6 */ 0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x7E,0x00,0x18,0x18,0x00,0x00,0x00,0x00,0x00,
+/* 0xF7 */ 0x00,0x00,0x00,0x00,0x00,0x76,0xDC,0x00,0x76,0xDC,0x00,0x00,0x00,0x00,0x00,0x00,
+/* 0xF8 */ 0x00,0x38,0x6C,0x6C,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+/* 0xF9 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+/* 0xFA */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+/* 0xFB */ 0x00,0x0F,0x0C,0x0C,0x0C,0x0C,0x0C,0xEC,0x6C,0x6C,0x3C,0x1C,0x00,0x00,0x00,0x00,
+/* 0xFC */ 0x00,0xD8,0x6C,0x6C,0x6C,0x6C,0x6C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+/* 0xFD */ 0x00,0x70,0xD8,0x30,0x60,0xC8,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+/* 0xFE */ 0x00,0x00,0x00,0x00,0x7C,0x7C,0x7C,0x7C,0x7C,0x7C,0x7C,0x00,0x00,0x00,0x00,0x00,
+};
diff --git a/arch/ppc/boot/include/mpc10x.h b/arch/ppc/boot/include/mpc10x.h
new file mode 100644
index 0000000..6cd40ec
--- /dev/null
+++ b/arch/ppc/boot/include/mpc10x.h
@@ -0,0 +1,65 @@
+/*
+ * arch/ppc/boot/include/mpc10.h
+ *
+ * Common defines for the Motorola SPS MPC106/8240/107 Host bridge/Mem
+ * ctrl/EPIC/etc.
+ *
+ * Author: Tom Rini <trini@mvista.com>
+ *
+ * This is a heavily stripped down version of:
+ * include/asm-ppc/mpc10x.h
+ *
+ * Author: Mark A. Greer
+ * mgreer@mvista.com
+ *
+ * 2001-2002 (c) MontaVista, Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+#ifndef __BOOT_MPC10X_H__
+#define __BOOT_MPC10X_H__
+
+/*
+ * The values here don't completely map everything but should work in most
+ * cases.
+ *
+ * MAP A (PReP Map)
+ * Processor: 0x80000000 - 0x807fffff -> PCI I/O: 0x00000000 - 0x007fffff
+ * Processor: 0xc0000000 - 0xdfffffff -> PCI MEM: 0x00000000 - 0x1fffffff
+ * PCI MEM: 0x80000000 -> Processor System Memory: 0x00000000
+ * EUMB mapped to: ioremap_base - 0x00100000 (ioremap_base - 1 MB)
+ *
+ * MAP B (CHRP Map)
+ * Processor: 0xfe000000 - 0xfebfffff -> PCI I/O: 0x00000000 - 0x00bfffff
+ * Processor: 0x80000000 - 0xbfffffff -> PCI MEM: 0x80000000 - 0xbfffffff
+ * PCI MEM: 0x00000000 -> Processor System Memory: 0x00000000
+ * EUMB mapped to: ioremap_base - 0x00100000 (ioremap_base - 1 MB)
+ */
+
+/* Define the type of map to use */
+#define MPC10X_MEM_MAP_A 1
+#define MPC10X_MEM_MAP_B 2
+
+/* Map A (PReP Map) Defines */
+#define MPC10X_MAPA_CNFG_ADDR 0x80000cf8
+#define MPC10X_MAPA_CNFG_DATA 0x80000cfc
+
+/* Map B (CHRP Map) Defines */
+#define MPC10X_MAPB_CNFG_ADDR 0xfec00000
+#define MPC10X_MAPB_CNFG_DATA 0xfee00000
+
+/* Define offsets for the memory controller registers in the config space */
+#define MPC10X_MCTLR_MEM_START_1 0x80 /* Banks 0-3 */
+#define MPC10X_MCTLR_MEM_START_2 0x84 /* Banks 4-7 */
+#define MPC10X_MCTLR_EXT_MEM_START_1 0x88 /* Banks 0-3 */
+#define MPC10X_MCTLR_EXT_MEM_START_2 0x8c /* Banks 4-7 */
+
+#define MPC10X_MCTLR_MEM_END_1 0x90 /* Banks 0-3 */
+#define MPC10X_MCTLR_MEM_END_2 0x94 /* Banks 4-7 */
+#define MPC10X_MCTLR_EXT_MEM_END_1 0x98 /* Banks 0-3 */
+#define MPC10X_MCTLR_EXT_MEM_END_2 0x9c /* Banks 4-7 */
+
+#define MPC10X_MCTLR_MEM_BANK_ENABLES 0xa0
+
+#endif /* __BOOT_MPC10X_H__ */
diff --git a/arch/ppc/boot/include/mpsc_defs.h b/arch/ppc/boot/include/mpsc_defs.h
new file mode 100644
index 0000000..2ce7bbb
--- /dev/null
+++ b/arch/ppc/boot/include/mpsc_defs.h
@@ -0,0 +1,146 @@
+/*
+ * drivers/serial/mpsc/mpsc_defs.h
+ *
+ * Register definitions for the Marvell Multi-Protocol Serial Controller (MPSC),
+ * Serial DMA Controller (SDMA), and Baud Rate Generator (BRG).
+ *
+ * Author: Mark A. Greer <mgreer@mvista.com>
+ *
+ * 2004 (c) MontaVista, Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+#ifndef _PPC_BOOT_MPSC_DEFS_H__
+#define _PPC_BOOT_MPSC_DEFS_H__
+
+#define MPSC_NUM_CTLRS 2
+
+/*
+ *****************************************************************************
+ *
+ * Multi-Protocol Serial Controller Interface Registers
+ *
+ *****************************************************************************
+ */
+
+/* Main Configuratino Register Offsets */
+#define MPSC_MMCRL 0x0000
+#define MPSC_MMCRH 0x0004
+#define MPSC_MPCR 0x0008
+#define MPSC_CHR_1 0x000c
+#define MPSC_CHR_2 0x0010
+#define MPSC_CHR_3 0x0014
+#define MPSC_CHR_4 0x0018
+#define MPSC_CHR_5 0x001c
+#define MPSC_CHR_6 0x0020
+#define MPSC_CHR_7 0x0024
+#define MPSC_CHR_8 0x0028
+#define MPSC_CHR_9 0x002c
+#define MPSC_CHR_10 0x0030
+#define MPSC_CHR_11 0x0034
+
+#define MPSC_MPCR_CL_5 0
+#define MPSC_MPCR_CL_6 1
+#define MPSC_MPCR_CL_7 2
+#define MPSC_MPCR_CL_8 3
+#define MPSC_MPCR_SBL_1 0
+#define MPSC_MPCR_SBL_2 3
+
+#define MPSC_CHR_2_TEV (1<<1)
+#define MPSC_CHR_2_TA (1<<7)
+#define MPSC_CHR_2_TTCS (1<<9)
+#define MPSC_CHR_2_REV (1<<17)
+#define MPSC_CHR_2_RA (1<<23)
+#define MPSC_CHR_2_CRD (1<<25)
+#define MPSC_CHR_2_EH (1<<31)
+#define MPSC_CHR_2_PAR_ODD 0
+#define MPSC_CHR_2_PAR_SPACE 1
+#define MPSC_CHR_2_PAR_EVEN 2
+#define MPSC_CHR_2_PAR_MARK 3
+
+/* MPSC Signal Routing */
+#define MPSC_MRR 0x0000
+#define MPSC_RCRR 0x0004
+#define MPSC_TCRR 0x0008
+
+/*
+ *****************************************************************************
+ *
+ * Serial DMA Controller Interface Registers
+ *
+ *****************************************************************************
+ */
+
+#define SDMA_SDC 0x0000
+#define SDMA_SDCM 0x0008
+#define SDMA_RX_DESC 0x0800
+#define SDMA_RX_BUF_PTR 0x0808
+#define SDMA_SCRDP 0x0810
+#define SDMA_TX_DESC 0x0c00
+#define SDMA_SCTDP 0x0c10
+#define SDMA_SFTDP 0x0c14
+
+#define SDMA_DESC_CMDSTAT_PE (1<<0)
+#define SDMA_DESC_CMDSTAT_CDL (1<<1)
+#define SDMA_DESC_CMDSTAT_FR (1<<3)
+#define SDMA_DESC_CMDSTAT_OR (1<<6)
+#define SDMA_DESC_CMDSTAT_BR (1<<9)
+#define SDMA_DESC_CMDSTAT_MI (1<<10)
+#define SDMA_DESC_CMDSTAT_A (1<<11)
+#define SDMA_DESC_CMDSTAT_AM (1<<12)
+#define SDMA_DESC_CMDSTAT_CT (1<<13)
+#define SDMA_DESC_CMDSTAT_C (1<<14)
+#define SDMA_DESC_CMDSTAT_ES (1<<15)
+#define SDMA_DESC_CMDSTAT_L (1<<16)
+#define SDMA_DESC_CMDSTAT_F (1<<17)
+#define SDMA_DESC_CMDSTAT_P (1<<18)
+#define SDMA_DESC_CMDSTAT_EI (1<<23)
+#define SDMA_DESC_CMDSTAT_O (1<<31)
+
+#define SDMA_DESC_DFLT (SDMA_DESC_CMDSTAT_O | \
+ SDMA_DESC_CMDSTAT_EI)
+
+#define SDMA_SDC_RFT (1<<0)
+#define SDMA_SDC_SFM (1<<1)
+#define SDMA_SDC_BLMR (1<<6)
+#define SDMA_SDC_BLMT (1<<7)
+#define SDMA_SDC_POVR (1<<8)
+#define SDMA_SDC_RIFB (1<<9)
+
+#define SDMA_SDCM_ERD (1<<7)
+#define SDMA_SDCM_AR (1<<15)
+#define SDMA_SDCM_STD (1<<16)
+#define SDMA_SDCM_TXD (1<<23)
+#define SDMA_SDCM_AT (1<<31)
+
+#define SDMA_0_CAUSE_RXBUF (1<<0)
+#define SDMA_0_CAUSE_RXERR (1<<1)
+#define SDMA_0_CAUSE_TXBUF (1<<2)
+#define SDMA_0_CAUSE_TXEND (1<<3)
+#define SDMA_1_CAUSE_RXBUF (1<<8)
+#define SDMA_1_CAUSE_RXERR (1<<9)
+#define SDMA_1_CAUSE_TXBUF (1<<10)
+#define SDMA_1_CAUSE_TXEND (1<<11)
+
+#define SDMA_CAUSE_RX_MASK (SDMA_0_CAUSE_RXBUF | SDMA_0_CAUSE_RXERR | \
+ SDMA_1_CAUSE_RXBUF | SDMA_1_CAUSE_RXERR)
+#define SDMA_CAUSE_TX_MASK (SDMA_0_CAUSE_TXBUF | SDMA_0_CAUSE_TXEND | \
+ SDMA_1_CAUSE_TXBUF | SDMA_1_CAUSE_TXEND)
+
+/* SDMA Interrupt registers */
+#define SDMA_INTR_CAUSE 0x0000
+#define SDMA_INTR_MASK 0x0080
+
+/*
+ *****************************************************************************
+ *
+ * Baud Rate Generator Interface Registers
+ *
+ *****************************************************************************
+ */
+
+#define BRG_BCR 0x0000
+#define BRG_BTR 0x0004
+
+#endif /*_PPC_BOOT_MPSC_DEFS_H__ */
diff --git a/arch/ppc/boot/include/nonstdio.h b/arch/ppc/boot/include/nonstdio.h
new file mode 100644
index 0000000..f2b5526
--- /dev/null
+++ b/arch/ppc/boot/include/nonstdio.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) Paul Mackerras 1997.
+ *
+ * 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 is sort of a catchall for I/O related functions. Stuff that
+ * wouldn't be in 'stdio.h' normally is here, and it's 'nonstdio.h'
+ * for a reason. -- Tom
+ */
+typedef int FILE;
+extern FILE *stdin, *stdout;
+#define NULL ((void *)0)
+#define EOF (-1)
+#define fopen(n, m) NULL
+#define fflush(f) 0
+#define fclose(f) 0
+#define perror(s) printf("%s: no files!\n", (s))
+
+extern int getc(void);
+extern int printf(const char *format, ...);
+extern int sprintf(char *str, const char *format, ...);
+extern int tstc(void);
+extern void exit(void);
+extern void outb(int port, unsigned char val);
+extern void putc(const char c);
+extern void puthex(unsigned long val);
+extern void puts(const char *);
+extern void udelay(long delay);
+extern unsigned char inb(int port);
+extern void board_isa_init(void);
+extern void ISA_init(unsigned long base);
diff --git a/arch/ppc/boot/include/of1275.h b/arch/ppc/boot/include/of1275.h
new file mode 100644
index 0000000..69173df
--- /dev/null
+++ b/arch/ppc/boot/include/of1275.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) Paul Mackerras 1997.
+ * Copyright (C) Leigh Brown 2002.
+ *
+ * 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.
+ */
+
+typedef void *prom_handle;
+typedef void *ihandle;
+typedef void *phandle;
+typedef int (*prom_entry)(void *);
+
+#define OF_INVALID_HANDLE ((prom_handle)-1UL)
+
+extern prom_entry of_prom_entry;
+
+/* function declarations */
+
+void * claim(unsigned int virt, unsigned int size, unsigned int align);
+int map(unsigned int phys, unsigned int virt, unsigned int size);
+void enter(void);
+void exit(void);
+phandle finddevice(const char *name);
+int getprop(phandle node, const char *name, void *buf, int buflen);
+void ofinit(prom_entry entry);
+int ofstdio(ihandle *stdin, ihandle *stdout, ihandle *stderr);
+int read(ihandle instance, void *buf, int buflen);
+void release(void *virt, unsigned int size);
+int write(ihandle instance, void *buf, int buflen);
+
+/* inlines */
+
+extern inline void pause(void)
+{
+ enter();
+}
diff --git a/arch/ppc/boot/include/rs6000.h b/arch/ppc/boot/include/rs6000.h
new file mode 100644
index 0000000..433f450
--- /dev/null
+++ b/arch/ppc/boot/include/rs6000.h
@@ -0,0 +1,243 @@
+/* IBM RS/6000 "XCOFF" file definitions for BFD.
+ Copyright (C) 1990, 1991 Free Software Foundation, Inc.
+ FIXME: Can someone provide a transliteration of this name into ASCII?
+ Using the following chars caused a compiler warning on HIUX (so I replaced
+ them with octal escapes), and isn't useful without an understanding of what
+ character set it is.
+ Written by Mimi Ph\373\364ng-Th\345o V\365 of IBM
+ and John Gilmore of Cygnus Support. */
+
+/********************** FILE HEADER **********************/
+
+struct external_filehdr {
+ char f_magic[2]; /* magic number */
+ char f_nscns[2]; /* number of sections */
+ char f_timdat[4]; /* time & date stamp */
+ char f_symptr[4]; /* file pointer to symtab */
+ char f_nsyms[4]; /* number of symtab entries */
+ char f_opthdr[2]; /* sizeof(optional hdr) */
+ char f_flags[2]; /* flags */
+};
+
+ /* IBM RS/6000 */
+#define U802WRMAGIC 0730 /* writeable text segments **chh** */
+#define U802ROMAGIC 0735 /* readonly sharable text segments */
+#define U802TOCMAGIC 0737 /* readonly text segments and TOC */
+
+#define BADMAG(x) \
+ ((x).f_magic != U802ROMAGIC && (x).f_magic != U802WRMAGIC && \
+ (x).f_magic != U802TOCMAGIC)
+
+#define FILHDR struct external_filehdr
+#define FILHSZ 20
+
+
+/********************** AOUT "OPTIONAL HEADER" **********************/
+
+
+typedef struct
+{
+ unsigned char magic[2]; /* type of file */
+ unsigned char vstamp[2]; /* version stamp */
+ unsigned char tsize[4]; /* text size in bytes, padded to FW bdry */
+ unsigned char dsize[4]; /* initialized data " " */
+ unsigned char bsize[4]; /* uninitialized data " " */
+ unsigned char entry[4]; /* entry pt. */
+ unsigned char text_start[4]; /* base of text used for this file */
+ unsigned char data_start[4]; /* base of data used for this file */
+ unsigned char o_toc[4]; /* address of TOC */
+ unsigned char o_snentry[2]; /* section number of entry point */
+ unsigned char o_sntext[2]; /* section number of .text section */
+ unsigned char o_sndata[2]; /* section number of .data section */
+ unsigned char o_sntoc[2]; /* section number of TOC */
+ unsigned char o_snloader[2]; /* section number of .loader section */
+ unsigned char o_snbss[2]; /* section number of .bss section */
+ unsigned char o_algntext[2]; /* .text alignment */
+ unsigned char o_algndata[2]; /* .data alignment */
+ unsigned char o_modtype[2]; /* module type (??) */
+ unsigned char o_cputype[2]; /* cpu type */
+ unsigned char o_maxstack[4]; /* max stack size (??) */
+ unsigned char o_maxdata[4]; /* max data size (??) */
+ unsigned char o_resv2[12]; /* reserved */
+}
+AOUTHDR;
+
+#define AOUTSZ 72
+#define SMALL_AOUTSZ (28)
+#define AOUTHDRSZ 72
+
+#define RS6K_AOUTHDR_OMAGIC 0x0107 /* old: text & data writeable */
+#define RS6K_AOUTHDR_NMAGIC 0x0108 /* new: text r/o, data r/w */
+#define RS6K_AOUTHDR_ZMAGIC 0x010B /* paged: text r/o, both page-aligned */
+
+
+/********************** SECTION HEADER **********************/
+
+
+struct external_scnhdr {
+ char s_name[8]; /* section name */
+ char s_paddr[4]; /* physical address, aliased s_nlib */
+ char s_vaddr[4]; /* virtual address */
+ char s_size[4]; /* section size */
+ char s_scnptr[4]; /* file ptr to raw data for section */
+ char s_relptr[4]; /* file ptr to relocation */
+ char s_lnnoptr[4]; /* file ptr to line numbers */
+ char s_nreloc[2]; /* number of relocation entries */
+ char s_nlnno[2]; /* number of line number entries*/
+ char s_flags[4]; /* flags */
+};
+
+/*
+ * names of "special" sections
+ */
+#define _TEXT ".text"
+#define _DATA ".data"
+#define _BSS ".bss"
+#define _PAD ".pad"
+#define _LOADER ".loader"
+
+#define SCNHDR struct external_scnhdr
+#define SCNHSZ 40
+
+/* XCOFF uses a special .loader section with type STYP_LOADER. */
+#define STYP_LOADER 0x1000
+
+/* XCOFF uses a special .debug section with type STYP_DEBUG. */
+#define STYP_DEBUG 0x2000
+
+/* XCOFF handles line number or relocation overflow by creating
+ another section header with STYP_OVRFLO set. */
+#define STYP_OVRFLO 0x8000
+
+/********************** LINE NUMBERS **********************/
+
+/* 1 line number entry for every "breakpointable" source line in a section.
+ * Line numbers are grouped on a per function basis; first entry in a function
+ * grouping will have l_lnno = 0 and in place of physical address will be the
+ * symbol table index of the function name.
+ */
+struct external_lineno {
+ union {
+ char l_symndx[4]; /* function name symbol index, iff l_lnno == 0*/
+ char l_paddr[4]; /* (physical) address of line number */
+ } l_addr;
+ char l_lnno[2]; /* line number */
+};
+
+
+#define LINENO struct external_lineno
+#define LINESZ 6
+
+
+/********************** SYMBOLS **********************/
+
+#define E_SYMNMLEN 8 /* # characters in a symbol name */
+#define E_FILNMLEN 14 /* # characters in a file name */
+#define E_DIMNUM 4 /* # array dimensions in auxiliary entry */
+
+struct external_syment
+{
+ union {
+ char e_name[E_SYMNMLEN];
+ struct {
+ char e_zeroes[4];
+ char e_offset[4];
+ } e;
+ } e;
+ char e_value[4];
+ char e_scnum[2];
+ char e_type[2];
+ char e_sclass[1];
+ char e_numaux[1];
+};
+
+
+
+#define N_BTMASK (017)
+#define N_TMASK (060)
+#define N_BTSHFT (4)
+#define N_TSHIFT (2)
+
+
+union external_auxent {
+ struct {
+ char x_tagndx[4]; /* str, un, or enum tag indx */
+ union {
+ struct {
+ char x_lnno[2]; /* declaration line number */
+ char x_size[2]; /* str/union/array size */
+ } x_lnsz;
+ char x_fsize[4]; /* size of function */
+ } x_misc;
+ union {
+ struct { /* if ISFCN, tag, or .bb */
+ char x_lnnoptr[4]; /* ptr to fcn line # */
+ char x_endndx[4]; /* entry ndx past block end */
+ } x_fcn;
+ struct { /* if ISARY, up to 4 dimen. */
+ char x_dimen[E_DIMNUM][2];
+ } x_ary;
+ } x_fcnary;
+ char x_tvndx[2]; /* tv index */
+ } x_sym;
+
+ union {
+ char x_fname[E_FILNMLEN];
+ struct {
+ char x_zeroes[4];
+ char x_offset[4];
+ } x_n;
+ } x_file;
+
+ struct {
+ char x_scnlen[4]; /* section length */
+ char x_nreloc[2]; /* # relocation entries */
+ char x_nlinno[2]; /* # line numbers */
+ } x_scn;
+
+ struct {
+ char x_tvfill[4]; /* tv fill value */
+ char x_tvlen[2]; /* length of .tv */
+ char x_tvran[2][2]; /* tv range */
+ } x_tv; /* info about .tv section (in auxent of symbol .tv)) */
+
+ struct {
+ unsigned char x_scnlen[4];
+ unsigned char x_parmhash[4];
+ unsigned char x_snhash[2];
+ unsigned char x_smtyp[1];
+ unsigned char x_smclas[1];
+ unsigned char x_stab[4];
+ unsigned char x_snstab[2];
+ } x_csect;
+
+};
+
+#define SYMENT struct external_syment
+#define SYMESZ 18
+#define AUXENT union external_auxent
+#define AUXESZ 18
+#define DBXMASK 0x80 /* for dbx storage mask */
+#define SYMNAME_IN_DEBUG(symptr) ((symptr)->n_sclass & DBXMASK)
+
+
+
+/********************** RELOCATION DIRECTIVES **********************/
+
+
+struct external_reloc {
+ char r_vaddr[4];
+ char r_symndx[4];
+ char r_size[1];
+ char r_type[1];
+};
+
+
+#define RELOC struct external_reloc
+#define RELSZ 10
+
+#define DEFAULT_DATA_SECTION_ALIGNMENT 4
+#define DEFAULT_BSS_SECTION_ALIGNMENT 4
+#define DEFAULT_TEXT_SECTION_ALIGNMENT 4
+/* For new sections we havn't heard of before */
+#define DEFAULT_SECTION_ALIGNMENT 4
diff --git a/arch/ppc/boot/include/serial.h b/arch/ppc/boot/include/serial.h
new file mode 100644
index 0000000..d710eab
--- /dev/null
+++ b/arch/ppc/boot/include/serial.h
@@ -0,0 +1,46 @@
+/*
+ * A really private header file for the (dumb) serial driver in arch/ppc/boot
+ *
+ * Shamelessly taken from include/linux/serialP.h:
+ *
+ * Copyright (C) 1997 by Theodore Ts'o.
+ *
+ * Redistribution of this file is permitted under the terms of the GNU
+ * Public License (GPL)
+ */
+
+#ifndef _PPC_BOOT_SERIALP_H
+#define _PPC_BOOT_SERIALP_H
+
+/*
+ * This is our internal structure for each serial port's state.
+ *
+ * Many fields are paralleled by the structure used by the serial_struct
+ * structure.
+ *
+ * Given that this is how SERIAL_PORT_DFNS are done, and that we need
+ * to use a few of their fields, we need to have our own copy of it.
+ */
+struct serial_state {
+ int magic;
+ int baud_base;
+ unsigned long port;
+ int irq;
+ int flags;
+ int hub6;
+ int type;
+ int line;
+ int revision; /* Chip revision (950) */
+ int xmit_fifo_size;
+ int custom_divisor;
+ int count;
+ u8 *iomem_base;
+ u16 iomem_reg_shift;
+ unsigned short close_delay;
+ unsigned short closing_wait; /* time to wait before closing */
+ unsigned long icount;
+ int io_type;
+ void *info;
+ void *dev;
+};
+#endif /* _PPC_BOOT_SERIAL_H */
diff --git a/arch/ppc/boot/ld.script b/arch/ppc/boot/ld.script
new file mode 100644
index 0000000..6ee602d
--- /dev/null
+++ b/arch/ppc/boot/ld.script
@@ -0,0 +1,88 @@
+OUTPUT_ARCH(powerpc)
+SECTIONS
+{
+ /* Read-only sections, merged into text segment: */
+ . = + SIZEOF_HEADERS;
+ .interp : { *(.interp) }
+ .hash : { *(.hash) }
+ .dynsym : { *(.dynsym) }
+ .dynstr : { *(.dynstr) }
+ .rel.text : { *(.rel.text) }
+ .rela.text : { *(.rela.text) }
+ .rel.data : { *(.rel.data) }
+ .rela.data : { *(.rela.data) }
+ .rel.rodata : { *(.rel.rodata) }
+ .rela.rodata : { *(.rela.rodata) }
+ .rel.got : { *(.rel.got) }
+ .rela.got : { *(.rela.got) }
+ .rel.ctors : { *(.rel.ctors) }
+ .rela.ctors : { *(.rela.ctors) }
+ .rel.dtors : { *(.rel.dtors) }
+ .rela.dtors : { *(.rela.dtors) }
+ .rel.bss : { *(.rel.bss) }
+ .rela.bss : { *(.rela.bss) }
+ .rel.plt : { *(.rel.plt) }
+ .rela.plt : { *(.rela.plt) }
+ .plt : { *(.plt) }
+ .text :
+ {
+ *(.text)
+ *(.fixup)
+ __relocate_start = .;
+ *(.relocate_code)
+ __relocate_end = .;
+ }
+ _etext = .;
+ PROVIDE (etext = .);
+
+ /* Read-write section, merged into data segment: */
+ . = ALIGN(4096);
+ .data :
+ {
+ *(.data)
+ *(.data1)
+ *(.data.boot)
+ *(.sdata)
+ *(.sdata2)
+ *(.got.plt) *(.got)
+ *(.dynamic)
+ *(.rodata)
+ *(.rodata.*)
+ *(.rodata1)
+ *(.got1)
+ __image_begin = .;
+ *(.image)
+ __image_end = .;
+ . = ALIGN(4096);
+ __ramdisk_begin = .;
+ *(.ramdisk)
+ __ramdisk_end = .;
+ . = ALIGN(4096);
+ __sysmap_begin = .;
+ *(.sysmap)
+ __sysmap_end = .;
+ CONSTRUCTORS
+ }
+ _edata = .;
+ PROVIDE (edata = .);
+
+ . = ALIGN(4096);
+ __bss_start = .;
+ .bss :
+ {
+ *(.sbss) *(.scommon)
+ *(.dynbss)
+ *(.bss)
+ *(COMMON)
+ }
+ _end = . ;
+ PROVIDE (end = .);
+
+ /DISCARD/ : {
+ *(__ksymtab)
+ *(__ksymtab_strings)
+ *(__bug_table)
+ *(__kcrctab)
+ }
+
+}
diff --git a/arch/ppc/boot/lib/Makefile b/arch/ppc/boot/lib/Makefile
new file mode 100644
index 0000000..d4077e6
--- /dev/null
+++ b/arch/ppc/boot/lib/Makefile
@@ -0,0 +1,23 @@
+#
+# Makefile for some libs needed by zImage.
+#
+
+CFLAGS_kbd.o := -Idrivers/char
+CFLAGS_vreset.o := -I$(srctree)/arch/ppc/boot/include
+
+zlib := infblock.c infcodes.c inffast.c inflate.c inftrees.c infutil.c
+
+lib-y += $(zlib:.c=.o) div64.o
+lib-$(CONFIG_VGA_CONSOLE) += vreset.o kbd.o
+
+
+# zlib files needs header from their original place
+EXTRA_CFLAGS += -Ilib/zlib_inflate
+
+quiet_cmd_copy_zlib = COPY $@
+ cmd_copy_zlib = cat $< > $@
+
+$(addprefix $(obj)/,$(zlib)): $(obj)/%: $(srctree)/lib/zlib_inflate/%
+ $(call cmd,copy_zlib)
+
+clean-files := $(zlib)
diff --git a/arch/ppc/boot/lib/div64.S b/arch/ppc/boot/lib/div64.S
new file mode 100644
index 0000000..3527569
--- /dev/null
+++ b/arch/ppc/boot/lib/div64.S
@@ -0,0 +1,58 @@
+/*
+ * Divide a 64-bit unsigned number by a 32-bit unsigned number.
+ * This routine assumes that the top 32 bits of the dividend are
+ * non-zero to start with.
+ * On entry, r3 points to the dividend, which get overwritten with
+ * the 64-bit quotient, and r4 contains the divisor.
+ * On exit, r3 contains the remainder.
+ *
+ * Copyright (C) 2002 Paul Mackerras, IBM Corp.
+ *
+ * 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.
+ */
+#include <asm/ppc_asm.h>
+#include <asm/processor.h>
+
+_GLOBAL(__div64_32)
+ lwz r5,0(r3) # get the dividend into r5/r6
+ lwz r6,4(r3)
+ cmplw r5,r4
+ li r7,0
+ li r8,0
+ blt 1f
+ divwu r7,r5,r4 # if dividend.hi >= divisor,
+ mullw r0,r7,r4 # quotient.hi = dividend.hi / divisor
+ subf. r5,r0,r5 # dividend.hi %= divisor
+ beq 3f
+1: mr r11,r5 # here dividend.hi != 0
+ andis. r0,r5,0xc000
+ bne 2f
+ cntlzw r0,r5 # we are shifting the dividend right
+ li r10,-1 # to make it < 2^32, and shifting
+ srw r10,r10,r0 # the divisor right the same amount,
+ add r9,r4,r10 # rounding up (so the estimate cannot
+ andc r11,r6,r10 # ever be too large, only too small)
+ andc r9,r9,r10
+ or r11,r5,r11
+ rotlw r9,r9,r0
+ rotlw r11,r11,r0
+ divwu r11,r11,r9 # then we divide the shifted quantities
+2: mullw r10,r11,r4 # to get an estimate of the quotient,
+ mulhwu r9,r11,r4 # multiply the estimate by the divisor,
+ subfc r6,r10,r6 # take the product from the divisor,
+ add r8,r8,r11 # and add the estimate to the accumulated
+ subfe. r5,r9,r5 # quotient
+ bne 1b
+3: cmplw r6,r4
+ blt 4f
+ divwu r0,r6,r4 # perform the remaining 32-bit division
+ mullw r10,r0,r4 # and get the remainder
+ add r8,r8,r0
+ subf r6,r10,r6
+4: stw r7,0(r3) # return the quotient in *r3
+ stw r8,4(r3)
+ mr r3,r6 # return the remainder in r3
+ blr
diff --git a/arch/ppc/boot/lib/kbd.c b/arch/ppc/boot/lib/kbd.c
new file mode 100644
index 0000000..3931727
--- /dev/null
+++ b/arch/ppc/boot/lib/kbd.c
@@ -0,0 +1,248 @@
+#include <linux/keyboard.h>
+
+#include "defkeymap.c" /* yeah I know it's bad -- Cort */
+
+
+unsigned char shfts, ctls, alts, caps;
+
+#define KBDATAP 0x60 /* kbd data port */
+#define KBSTATUSPORT 0x61 /* kbd status */
+#define KBSTATP 0x64 /* kbd status port */
+#define KBINRDY 0x01
+#define KBOUTRDY 0x02
+
+extern unsigned char inb(int port);
+extern void outb(int port, char val);
+extern void puts(const char *);
+extern void puthex(unsigned long val);
+extern void udelay(long x);
+
+static int kbd(int noblock)
+{
+ unsigned char dt, brk, val;
+ unsigned code;
+loop:
+ if (noblock) {
+ if ((inb(KBSTATP) & KBINRDY) == 0)
+ return (-1);
+ } else while((inb(KBSTATP) & KBINRDY) == 0) ;
+
+ dt = inb(KBDATAP);
+
+ brk = dt & 0x80; /* brk == 1 on key release */
+ dt = dt & 0x7f; /* keycode */
+
+ if (shfts)
+ code = shift_map[dt];
+ else if (ctls)
+ code = ctrl_map[dt];
+ else
+ code = plain_map[dt];
+
+ val = KVAL(code);
+ switch (KTYP(code) & 0x0f) {
+ case KT_LATIN:
+ if (brk)
+ break;
+ if (alts)
+ val |= 0x80;
+ if (val == 0x7f) /* map delete to backspace */
+ val = '\b';
+ return val;
+
+ case KT_LETTER:
+ if (brk)
+ break;
+ if (caps)
+ val -= 'a'-'A';
+ return val;
+
+ case KT_SPEC:
+ if (brk)
+ break;
+ if (val == KVAL(K_CAPS))
+ caps = !caps;
+ else if (val == KVAL(K_ENTER)) {
+enter: /* Wait for key up */
+ while (1) {
+ while((inb(KBSTATP) & KBINRDY) == 0) ;
+ dt = inb(KBDATAP);
+ if (dt & 0x80) /* key up */ break;
+ }
+ return 10;
+ }
+ break;
+
+ case KT_PAD:
+ if (brk)
+ break;
+ if (val < 10)
+ return val;
+ if (val == KVAL(K_PENTER))
+ goto enter;
+ break;
+
+ case KT_SHIFT:
+ switch (val) {
+ case KG_SHIFT:
+ case KG_SHIFTL:
+ case KG_SHIFTR:
+ shfts = brk ? 0 : 1;
+ break;
+ case KG_ALT:
+ case KG_ALTGR:
+ alts = brk ? 0 : 1;
+ break;
+ case KG_CTRL:
+ case KG_CTRLL:
+ case KG_CTRLR:
+ ctls = brk ? 0 : 1;
+ break;
+ }
+ break;
+
+ case KT_LOCK:
+ switch (val) {
+ case KG_SHIFT:
+ case KG_SHIFTL:
+ case KG_SHIFTR:
+ if (brk)
+ shfts = !shfts;
+ break;
+ case KG_ALT:
+ case KG_ALTGR:
+ if (brk)
+ alts = !alts;
+ break;
+ case KG_CTRL:
+ case KG_CTRLL:
+ case KG_CTRLR:
+ if (brk)
+ ctls = !ctls;
+ break;
+ }
+ break;
+ }
+ if (brk) return (-1); /* Ignore initial 'key up' codes */
+ goto loop;
+}
+
+static int __kbdreset(void)
+{
+ unsigned char c;
+ int i, t;
+
+ /* flush input queue */
+ t = 2000;
+ while ((inb(KBSTATP) & KBINRDY))
+ {
+ (void)inb(KBDATAP);
+ if (--t == 0)
+ return 1;
+ }
+ /* Send self-test */
+ t = 20000;
+ while (inb(KBSTATP) & KBOUTRDY)
+ if (--t == 0)
+ return 2;
+ outb(KBSTATP,0xAA);
+ t = 200000;
+ while ((inb(KBSTATP) & KBINRDY) == 0) /* wait input ready */
+ if (--t == 0)
+ return 3;
+ if ((c = inb(KBDATAP)) != 0x55)
+ {
+ puts("Keyboard self test failed - result:");
+ puthex(c);
+ puts("\n");
+ }
+ /* Enable interrupts and keyboard controller */
+ t = 20000;
+ while (inb(KBSTATP) & KBOUTRDY)
+ if (--t == 0) return 4;
+ outb(KBSTATP,0x60);
+ t = 20000;
+ while (inb(KBSTATP) & KBOUTRDY)
+ if (--t == 0) return 5;
+ outb(KBDATAP,0x45);
+ for (i = 0; i < 10000; i++) udelay(1);
+
+ t = 20000;
+ while (inb(KBSTATP) & KBOUTRDY)
+ if (--t == 0) return 6;
+ outb(KBSTATP,0x20);
+ t = 200000;
+ while ((inb(KBSTATP) & KBINRDY) == 0) /* wait input ready */
+ if (--t == 0) return 7;
+ if (! (inb(KBDATAP) & 0x40)) {
+ /*
+ * Quote from PS/2 System Reference Manual:
+ *
+ * "Address hex 0060 and address hex 0064 should be
+ * written only when the input-buffer-full bit and
+ * output-buffer-full bit in the Controller Status
+ * register are set 0." (KBINRDY and KBOUTRDY)
+ */
+ t = 200000;
+ while (inb(KBSTATP) & (KBINRDY | KBOUTRDY))
+ if (--t == 0) return 8;
+ outb(KBDATAP,0xF0);
+ t = 200000;
+ while (inb(KBSTATP) & (KBINRDY | KBOUTRDY))
+ if (--t == 0) return 9;
+ outb(KBDATAP,0x01);
+ }
+ t = 20000;
+ while (inb(KBSTATP) & KBOUTRDY)
+ if (--t == 0) return 10;
+ outb(KBSTATP,0xAE);
+ return 0;
+}
+
+static void kbdreset(void)
+{
+ int ret = __kbdreset();
+
+ if (ret) {
+ puts("__kbdreset failed: ");
+ puthex(ret);
+ puts("\n");
+ }
+}
+
+/* We have to actually read the keyboard when CRT_tstc is called,
+ * since the pending data might be a key release code, and therefore
+ * not valid data. In this case, kbd() will return -1, even though there's
+ * data to be read. Of course, we might actually read a valid key press,
+ * in which case it gets queued into key_pending for use by CRT_getc.
+ */
+
+static int kbd_reset = 0;
+
+static int key_pending = -1;
+
+int CRT_getc(void)
+{
+ int c;
+ if (!kbd_reset) {kbdreset(); kbd_reset++; }
+
+ if (key_pending != -1) {
+ c = key_pending;
+ key_pending = -1;
+ return c;
+ } else {
+ while ((c = kbd(0)) == 0) ;
+ return c;
+ }
+}
+
+int CRT_tstc(void)
+{
+ if (!kbd_reset) {kbdreset(); kbd_reset++; }
+
+ while (key_pending == -1 && ((inb(KBSTATP) & KBINRDY) != 0)) {
+ key_pending = kbd(1);
+ }
+
+ return (key_pending != -1);
+}
diff --git a/arch/ppc/boot/lib/vreset.c b/arch/ppc/boot/lib/vreset.c
new file mode 100644
index 0000000..463ba00
--- /dev/null
+++ b/arch/ppc/boot/lib/vreset.c
@@ -0,0 +1,805 @@
+/*
+ * vreset.c
+ *
+ * Initialize the VGA control registers to 80x25 text mode.
+ *
+ * Adapted from a program by:
+ * Steve Sellgren
+ * San Francisco Indigo Company
+ * sfindigo!sellgren@uunet.uu.net
+ *
+ * Original concept by:
+ * Gary Thomas <gdt@linuxppc.org>
+ * Adapted for Moto boxes by:
+ * Pat Kane & Mark Scott, 1996
+ * Adapted for IBM portables by:
+ * Takeshi Ishimoto
+ * Multi-console support:
+ * Terje Malmedal <terje.malmedal@usit.uio.no>
+ */
+
+#include "iso_font.h"
+#include "nonstdio.h"
+
+extern char *vidmem;
+extern int lines, cols;
+struct VaRegs;
+
+/*
+ * VGA Register
+ */
+struct VgaRegs
+{
+ unsigned short io_port;
+ unsigned char io_index;
+ unsigned char io_value;
+};
+
+void unlockVideo(int slot);
+void setTextRegs(struct VgaRegs *svp);
+void setTextCLUT(int shift);
+void clearVideoMemory(void);
+void loadFont(unsigned char *ISA_mem);
+
+static void mdelay(int ms)
+{
+ for (; ms > 0; --ms)
+ udelay(1000);
+}
+
+/*
+ * Default console text mode registers used to reset
+ * graphics adapter.
+ */
+#define NREGS 54
+#define ENDMK 0xFFFF /* End marker */
+
+#define S3Vendor 0x5333
+#define CirrusVendor 0x1013
+#define DiamondVendor 0x100E
+#define MatroxVendor 0x102B
+#define ParadiseVendor 0x101C
+
+struct VgaRegs GenVgaTextRegs[NREGS+1] = {
+ /* port index value */
+ /* SR Regs */
+ { 0x3c4, 0x1, 0x0 },
+ { 0x3c4, 0x2, 0x3 },
+ { 0x3c4, 0x3, 0x0 },
+ { 0x3c4, 0x4, 0x2 },
+ /* CR Regs */
+ { 0x3d4, 0x0, 0x5f },
+ { 0x3d4, 0x1, 0x4f },
+ { 0x3d4, 0x2, 0x50 },
+ { 0x3d4, 0x3, 0x82 },
+ { 0x3d4, 0x4, 0x55 },
+ { 0x3d4, 0x5, 0x81 },
+ { 0x3d4, 0x6, 0xbf },
+ { 0x3d4, 0x7, 0x1f },
+ { 0x3d4, 0x8, 0x00 },
+ { 0x3d4, 0x9, 0x4f },
+ { 0x3d4, 0xa, 0x0d },
+ { 0x3d4, 0xb, 0x0e },
+ { 0x3d4, 0xc, 0x00 },
+ { 0x3d4, 0xd, 0x00 },
+ { 0x3d4, 0xe, 0x00 },
+ { 0x3d4, 0xf, 0x00 },
+ { 0x3d4, 0x10, 0x9c },
+ { 0x3d4, 0x11, 0x8e },
+ { 0x3d4, 0x12, 0x8f },
+ { 0x3d4, 0x13, 0x28 },
+ { 0x3d4, 0x14, 0x1f },
+ { 0x3d4, 0x15, 0x96 },
+ { 0x3d4, 0x16, 0xb9 },
+ { 0x3d4, 0x17, 0xa3 },
+ /* GR Regs */
+ { 0x3ce, 0x0, 0x0 },
+ { 0x3ce, 0x1, 0x0 },
+ { 0x3ce, 0x2, 0x0 },
+ { 0x3ce, 0x3, 0x0 },
+ { 0x3ce, 0x4, 0x0 },
+ { 0x3ce, 0x5, 0x10 },
+ { 0x3ce, 0x6, 0xe },
+ { 0x3ce, 0x7, 0x0 },
+ { 0x3ce, 0x8, 0xff },
+ { ENDMK }
+};
+
+struct RGBColors
+{
+ unsigned char r, g, b;
+};
+
+/*
+ * Default console text mode color table.
+ * These values were obtained by booting Linux with
+ * text mode firmware & then dumping the registers.
+ */
+struct RGBColors TextCLUT[256] =
+{
+ /* red green blue */
+ { 0x0, 0x0, 0x0 },
+ { 0x0, 0x0, 0x2a },
+ { 0x0, 0x2a, 0x0 },
+ { 0x0, 0x2a, 0x2a },
+ { 0x2a, 0x0, 0x0 },
+ { 0x2a, 0x0, 0x2a },
+ { 0x2a, 0x2a, 0x0 },
+ { 0x2a, 0x2a, 0x2a },
+ { 0x0, 0x0, 0x15 },
+ { 0x0, 0x0, 0x3f },
+ { 0x0, 0x2a, 0x15 },
+ { 0x0, 0x2a, 0x3f },
+ { 0x2a, 0x0, 0x15 },
+ { 0x2a, 0x0, 0x3f },
+ { 0x2a, 0x2a, 0x15 },
+ { 0x2a, 0x2a, 0x3f },
+ { 0x0, 0x15, 0x0 },
+ { 0x0, 0x15, 0x2a },
+ { 0x0, 0x3f, 0x0 },
+ { 0x0, 0x3f, 0x2a },
+ { 0x2a, 0x15, 0x0 },
+ { 0x2a, 0x15, 0x2a },
+ { 0x2a, 0x3f, 0x0 },
+ { 0x2a, 0x3f, 0x2a },
+ { 0x0, 0x15, 0x15 },
+ { 0x0, 0x15, 0x3f },
+ { 0x0, 0x3f, 0x15 },
+ { 0x0, 0x3f, 0x3f },
+ { 0x2a, 0x15, 0x15 },
+ { 0x2a, 0x15, 0x3f },
+ { 0x2a, 0x3f, 0x15 },
+ { 0x2a, 0x3f, 0x3f },
+ { 0x15, 0x0, 0x0 },
+ { 0x15, 0x0, 0x2a },
+ { 0x15, 0x2a, 0x0 },
+ { 0x15, 0x2a, 0x2a },
+ { 0x3f, 0x0, 0x0 },
+ { 0x3f, 0x0, 0x2a },
+ { 0x3f, 0x2a, 0x0 },
+ { 0x3f, 0x2a, 0x2a },
+ { 0x15, 0x0, 0x15 },
+ { 0x15, 0x0, 0x3f },
+ { 0x15, 0x2a, 0x15 },
+ { 0x15, 0x2a, 0x3f },
+ { 0x3f, 0x0, 0x15 },
+ { 0x3f, 0x0, 0x3f },
+ { 0x3f, 0x2a, 0x15 },
+ { 0x3f, 0x2a, 0x3f },
+ { 0x15, 0x15, 0x0 },
+ { 0x15, 0x15, 0x2a },
+ { 0x15, 0x3f, 0x0 },
+ { 0x15, 0x3f, 0x2a },
+ { 0x3f, 0x15, 0x0 },
+ { 0x3f, 0x15, 0x2a },
+ { 0x3f, 0x3f, 0x0 },
+ { 0x3f, 0x3f, 0x2a },
+ { 0x15, 0x15, 0x15 },
+ { 0x15, 0x15, 0x3f },
+ { 0x15, 0x3f, 0x15 },
+ { 0x15, 0x3f, 0x3f },
+ { 0x3f, 0x15, 0x15 },
+ { 0x3f, 0x15, 0x3f },
+ { 0x3f, 0x3f, 0x15 },
+ { 0x3f, 0x3f, 0x3f },
+ { 0x39, 0xc, 0x5 },
+ { 0x15, 0x2c, 0xf },
+ { 0x26, 0x10, 0x3d },
+ { 0x29, 0x29, 0x38 },
+ { 0x4, 0x1a, 0xe },
+ { 0x2, 0x1e, 0x3a },
+ { 0x3c, 0x25, 0x33 },
+ { 0x3c, 0xc, 0x2c },
+ { 0x3f, 0x3, 0x2b },
+ { 0x1c, 0x9, 0x13 },
+ { 0x25, 0x2a, 0x35 },
+ { 0x1e, 0xa, 0x38 },
+ { 0x24, 0x8, 0x3 },
+ { 0x3, 0xe, 0x36 },
+ { 0xc, 0x6, 0x2a },
+ { 0x26, 0x3, 0x32 },
+ { 0x5, 0x2f, 0x33 },
+ { 0x3c, 0x35, 0x2f },
+ { 0x2d, 0x26, 0x3e },
+ { 0xd, 0xa, 0x10 },
+ { 0x25, 0x3c, 0x11 },
+ { 0xd, 0x4, 0x2e },
+ { 0x5, 0x19, 0x3e },
+ { 0xc, 0x13, 0x34 },
+ { 0x2b, 0x6, 0x24 },
+ { 0x4, 0x3, 0xd },
+ { 0x2f, 0x3c, 0xc },
+ { 0x2a, 0x37, 0x1f },
+ { 0xf, 0x12, 0x38 },
+ { 0x38, 0xe, 0x2a },
+ { 0x12, 0x2f, 0x19 },
+ { 0x29, 0x2e, 0x31 },
+ { 0x25, 0x13, 0x3e },
+ { 0x33, 0x3e, 0x33 },
+ { 0x1d, 0x2c, 0x25 },
+ { 0x15, 0x15, 0x5 },
+ { 0x32, 0x25, 0x39 },
+ { 0x1a, 0x7, 0x1f },
+ { 0x13, 0xe, 0x1d },
+ { 0x36, 0x17, 0x34 },
+ { 0xf, 0x15, 0x23 },
+ { 0x2, 0x35, 0xd },
+ { 0x15, 0x3f, 0xc },
+ { 0x14, 0x2f, 0xf },
+ { 0x19, 0x21, 0x3e },
+ { 0x27, 0x11, 0x2f },
+ { 0x38, 0x3f, 0x3c },
+ { 0x36, 0x2d, 0x15 },
+ { 0x16, 0x17, 0x2 },
+ { 0x1, 0xa, 0x3d },
+ { 0x1b, 0x11, 0x3f },
+ { 0x21, 0x3c, 0xd },
+ { 0x1a, 0x39, 0x3d },
+ { 0x8, 0xe, 0xe },
+ { 0x22, 0x21, 0x23 },
+ { 0x1e, 0x30, 0x5 },
+ { 0x1f, 0x22, 0x3d },
+ { 0x1e, 0x2f, 0xa },
+ { 0x0, 0x1c, 0xe },
+ { 0x0, 0x1c, 0x15 },
+ { 0x0, 0x1c, 0x1c },
+ { 0x0, 0x15, 0x1c },
+ { 0x0, 0xe, 0x1c },
+ { 0x0, 0x7, 0x1c },
+ { 0xe, 0xe, 0x1c },
+ { 0x11, 0xe, 0x1c },
+ { 0x15, 0xe, 0x1c },
+ { 0x18, 0xe, 0x1c },
+ { 0x1c, 0xe, 0x1c },
+ { 0x1c, 0xe, 0x18 },
+ { 0x1c, 0xe, 0x15 },
+ { 0x1c, 0xe, 0x11 },
+ { 0x1c, 0xe, 0xe },
+ { 0x1c, 0x11, 0xe },
+ { 0x1c, 0x15, 0xe },
+ { 0x1c, 0x18, 0xe },
+ { 0x1c, 0x1c, 0xe },
+ { 0x18, 0x1c, 0xe },
+ { 0x15, 0x1c, 0xe },
+ { 0x11, 0x1c, 0xe },
+ { 0xe, 0x1c, 0xe },
+ { 0xe, 0x1c, 0x11 },
+ { 0xe, 0x1c, 0x15 },
+ { 0xe, 0x1c, 0x18 },
+ { 0xe, 0x1c, 0x1c },
+ { 0xe, 0x18, 0x1c },
+ { 0xe, 0x15, 0x1c },
+ { 0xe, 0x11, 0x1c },
+ { 0x14, 0x14, 0x1c },
+ { 0x16, 0x14, 0x1c },
+ { 0x18, 0x14, 0x1c },
+ { 0x1a, 0x14, 0x1c },
+ { 0x1c, 0x14, 0x1c },
+ { 0x1c, 0x14, 0x1a },
+ { 0x1c, 0x14, 0x18 },
+ { 0x1c, 0x14, 0x16 },
+ { 0x1c, 0x14, 0x14 },
+ { 0x1c, 0x16, 0x14 },
+ { 0x1c, 0x18, 0x14 },
+ { 0x1c, 0x1a, 0x14 },
+ { 0x1c, 0x1c, 0x14 },
+ { 0x1a, 0x1c, 0x14 },
+ { 0x18, 0x1c, 0x14 },
+ { 0x16, 0x1c, 0x14 },
+ { 0x14, 0x1c, 0x14 },
+ { 0x14, 0x1c, 0x16 },
+ { 0x14, 0x1c, 0x18 },
+ { 0x14, 0x1c, 0x1a },
+ { 0x14, 0x1c, 0x1c },
+ { 0x14, 0x1a, 0x1c },
+ { 0x14, 0x18, 0x1c },
+ { 0x14, 0x16, 0x1c },
+ { 0x0, 0x0, 0x10 },
+ { 0x4, 0x0, 0x10 },
+ { 0x8, 0x0, 0x10 },
+ { 0xc, 0x0, 0x10 },
+ { 0x10, 0x0, 0x10 },
+ { 0x10, 0x0, 0xc },
+ { 0x10, 0x0, 0x8 },
+ { 0x10, 0x0, 0x4 },
+ { 0x10, 0x0, 0x0 },
+ { 0x10, 0x4, 0x0 },
+ { 0x10, 0x8, 0x0 },
+ { 0x10, 0xc, 0x0 },
+ { 0x10, 0x10, 0x0 },
+ { 0xc, 0x10, 0x0 },
+ { 0x8, 0x10, 0x0 },
+ { 0x4, 0x10, 0x0 },
+ { 0x0, 0x10, 0x0 },
+ { 0x0, 0x10, 0x4 },
+ { 0x0, 0x10, 0x8 },
+ { 0x0, 0x10, 0xc },
+ { 0x0, 0x10, 0x10 },
+ { 0x0, 0xc, 0x10 },
+ { 0x0, 0x8, 0x10 },
+ { 0x0, 0x4, 0x10 },
+ { 0x8, 0x8, 0x10 },
+ { 0xa, 0x8, 0x10 },
+ { 0xc, 0x8, 0x10 },
+ { 0xe, 0x8, 0x10 },
+ { 0x10, 0x8, 0x10 },
+ { 0x10, 0x8, 0xe },
+ { 0x10, 0x8, 0xc },
+ { 0x10, 0x8, 0xa },
+ { 0x10, 0x8, 0x8 },
+ { 0x10, 0xa, 0x8 },
+ { 0x10, 0xc, 0x8 },
+ { 0x10, 0xe, 0x8 },
+ { 0x10, 0x10, 0x8 },
+ { 0xe, 0x10, 0x8 },
+ { 0xc, 0x10, 0x8 },
+ { 0xa, 0x10, 0x8 },
+ { 0x8, 0x10, 0x8 },
+ { 0x8, 0x10, 0xa },
+ { 0x8, 0x10, 0xc },
+ { 0x8, 0x10, 0xe },
+ { 0x8, 0x10, 0x10 },
+ { 0x8, 0xe, 0x10 },
+ { 0x8, 0xc, 0x10 },
+ { 0x8, 0xa, 0x10 },
+ { 0xb, 0xb, 0x10 },
+ { 0xc, 0xb, 0x10 },
+ { 0xd, 0xb, 0x10 },
+ { 0xf, 0xb, 0x10 },
+ { 0x10, 0xb, 0x10 },
+ { 0x10, 0xb, 0xf },
+ { 0x10, 0xb, 0xd },
+ { 0x10, 0xb, 0xc },
+ { 0x10, 0xb, 0xb },
+ { 0x10, 0xc, 0xb },
+ { 0x10, 0xd, 0xb },
+ { 0x10, 0xf, 0xb },
+ { 0x10, 0x10, 0xb },
+ { 0xf, 0x10, 0xb },
+ { 0xd, 0x10, 0xb },
+ { 0xc, 0x10, 0xb },
+ { 0xb, 0x10, 0xb },
+ { 0xb, 0x10, 0xc },
+ { 0xb, 0x10, 0xd },
+ { 0xb, 0x10, 0xf },
+ { 0xb, 0x10, 0x10 },
+ { 0xb, 0xf, 0x10 },
+ { 0xb, 0xd, 0x10 },
+ { 0xb, 0xc, 0x10 },
+ { 0x0, 0x0, 0x0 },
+ { 0x0, 0x0, 0x0 },
+ { 0x0, 0x0, 0x0 },
+ { 0x0, 0x0, 0x0 },
+ { 0x0, 0x0, 0x0 },
+ { 0x0, 0x0, 0x0 },
+ { 0x0, 0x0, 0x0 }
+};
+
+unsigned char AC[21] = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x14, 0x07,
+ 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F,
+ 0x0C, 0x00, 0x0F, 0x08, 0x00};
+
+static int scanPCI(int start_slt);
+static int PCIVendor(int);
+#ifdef DEBUG
+static void printslots(void);
+#endif
+extern void puthex(unsigned long);
+extern void puts(const char *);
+static void unlockS3(void);
+
+static inline void
+outw(int port, unsigned short val)
+{
+ outb(port, val >> 8);
+ outb(port+1, val);
+}
+
+int
+vga_init(unsigned char *ISA_mem)
+{
+ int slot;
+ struct VgaRegs *VgaTextRegs;
+
+ /* See if VGA already in TEXT mode - exit if so! */
+ outb(0x3CE, 0x06);
+ if ((inb(0x3CF) & 0x01) == 0){
+ puts("VGA already in text mode\n");
+ return 0;
+ }
+
+ /* If no VGA responding in text mode, then we have some work to do...
+ */
+ slot = -1;
+ while((slot = scanPCI(slot)) > -1) { /* find video card in use */
+ unlockVideo(slot); /* enable I/O to card */
+ VgaTextRegs = GenVgaTextRegs;
+
+ switch (PCIVendor(slot)) {
+ default:
+ break;
+ case(S3Vendor):
+ unlockS3();
+ break;
+
+ case(CirrusVendor):
+ outw(0x3C4, 0x0612); /* unlock ext regs */
+ outw(0x3C4, 0x0700); /* reset ext sequence mode */
+ break;
+
+ case(ParadiseVendor): /* IBM Portable 850 */
+ outw(0x3ce, 0x0f05); /* unlock pardise registers */
+ outw(0x3c4, 0x0648);
+ outw(0x3d4, 0x2985);
+ outw(0x3d4, 0x34a6);
+ outb(0x3ce, 0x0b); /* disable linear addressing */
+ outb(0x3cf, inb(0x3cf) & ~0x30);
+ outw(0x3c4, 0x1400);
+ outb(0x3ce, 0x0e); /* disable 256 color mode */
+ outb(0x3cf, inb(0x3cf) & ~0x01);
+ outb(0xd00, 0xff); /* enable auto-centering */
+ if (!(inb(0xd01) & 0x03)) {
+ outb(0x3d4, 0x33);
+ outb(0x3d5, inb(0x3d5) & ~0x90);
+ outb(0x3d4, 0x32);
+ outb(0x3d5, inb(0x3d5) | 0x04);
+ outw(0x3d4, 0x0250);
+ outw(0x3d4, 0x07ba);
+ outw(0x3d4, 0x0900);
+ outw(0x3d4, 0x15e7);
+ outw(0x3d4, 0x2a95);
+ }
+ outw(0x3d4, 0x34a0);
+ break;
+
+ #if 0 /* Untested - probably doesn't work */
+ case(MatroxVendor):
+ case(DiamondVendor):
+ puts("VGA Chip Vendor ID: ");
+ puthex(PCIVendor(slot));
+ puts("\n");
+ mdelay(1000);
+ #endif
+ };
+
+ outw(0x3C4, 0x0120); /* disable video */
+ setTextRegs(VgaTextRegs); /* initial register setup */
+ setTextCLUT(0); /* load color lookup table */
+ loadFont(ISA_mem); /* load font */
+ setTextRegs(VgaTextRegs); /* reload registers */
+ outw(0x3C4, 0x0100); /* re-enable video */
+ clearVideoMemory();
+
+ if (PCIVendor(slot) == S3Vendor) {
+ outb(0x3c2, 0x63); /* MISC */
+ } /* endif */
+
+ #ifdef DEBUG
+ printslots();
+ mdelay(5000);
+ #endif
+
+ mdelay(1000); /* give time for the video monitor to come up */
+ }
+ return (1); /* 'CRT' I/O supported */
+}
+
+/*
+ * Write to VGA Attribute registers.
+ */
+void
+writeAttr(unsigned char index, unsigned char data, unsigned char videoOn)
+{
+ unsigned char v;
+ v = inb(0x3da); /* reset attr. address toggle */
+ if (videoOn)
+ outb(0x3c0, (index & 0x1F) | 0x20);
+ else
+ outb(0x3c0, (index & 0x1F));
+ outb(0x3c0, data);
+}
+
+void
+setTextRegs(struct VgaRegs *svp)
+{
+ int i;
+
+ /*
+ * saved settings
+ */
+ while( svp->io_port != ENDMK ) {
+ outb(svp->io_port, svp->io_index);
+ outb(svp->io_port+1, svp->io_value);
+ svp++;
+ }
+
+ outb(0x3c2, 0x67); /* MISC */
+ outb(0x3c6, 0xff); /* MASK */
+
+ for ( i = 0; i < 0x10; i++)
+ writeAttr(i, AC[i], 0); /* pallete */
+ writeAttr(0x10, 0x0c, 0); /* text mode */
+ writeAttr(0x11, 0x00, 0); /* overscan color (border) */
+ writeAttr(0x12, 0x0f, 0); /* plane enable */
+ writeAttr(0x13, 0x08, 0); /* pixel panning */
+ writeAttr(0x14, 0x00, 1); /* color select; video on */
+}
+
+void
+setTextCLUT(int shift)
+{
+ int i;
+
+ outb(0x3C6, 0xFF);
+ i = inb(0x3C7);
+ outb(0x3C8, 0);
+ i = inb(0x3C7);
+
+ for ( i = 0; i < 256; i++) {
+ outb(0x3C9, TextCLUT[i].r << shift);
+ outb(0x3C9, TextCLUT[i].g << shift);
+ outb(0x3C9, TextCLUT[i].b << shift);
+ }
+}
+
+void
+loadFont(unsigned char *ISA_mem)
+{
+ int i, j;
+ unsigned char *font_page = (unsigned char *) &ISA_mem[0xA0000];
+
+ outb(0x3C2, 0x67);
+ /*
+ * Load font
+ */
+ i = inb(0x3DA); /* Reset Attr toggle */
+
+ outb(0x3C0,0x30);
+ outb(0x3C0, 0x01); /* graphics mode */
+
+ outw(0x3C4, 0x0001); /* reset sequencer */
+ outw(0x3C4, 0x0204); /* write to plane 2 */
+ outw(0x3C4, 0x0406); /* enable plane graphics */
+ outw(0x3C4, 0x0003); /* reset sequencer */
+ outw(0x3CE, 0x0402); /* read plane 2 */
+ outw(0x3CE, 0x0500); /* write mode 0, read mode 0 */
+ outw(0x3CE, 0x0605); /* set graphics mode */
+
+ for (i = 0; i < sizeof(font); i += 16) {
+ for (j = 0; j < 16; j++) {
+ __asm__ volatile("eieio");
+ font_page[(2*i)+j] = font[i+j];
+ }
+ }
+}
+
+static void
+unlockS3(void)
+{
+ int s3_device_id;
+ outw(0x3d4, 0x3848);
+ outw(0x3d4, 0x39a5);
+ outb(0x3d4, 0x2d);
+ s3_device_id = inb(0x3d5) << 8;
+ outb(0x3d4, 0x2e);
+ s3_device_id |= inb(0x3d5);
+
+ if (s3_device_id != 0x8812) {
+ /* From the S3 manual */
+ outb(0x46E8, 0x10); /* Put into setup mode */
+ outb(0x3C3, 0x10);
+ outb(0x102, 0x01); /* Enable registers */
+ outb(0x46E8, 0x08); /* Enable video */
+ outb(0x3C3, 0x08);
+ outb(0x4AE8, 0x00);
+
+#if 0
+ outb(0x42E8, 0x80); /* Reset graphics engine? */
+#endif
+
+ outb(0x3D4, 0x38); /* Unlock all registers */
+ outb(0x3D5, 0x48);
+ outb(0x3D4, 0x39);
+ outb(0x3D5, 0xA5);
+ outb(0x3D4, 0x40);
+ outb(0x3D5, inb(0x3D5)|0x01);
+ outb(0x3D4, 0x33);
+ outb(0x3D5, inb(0x3D5)&~0x52);
+ outb(0x3D4, 0x35);
+ outb(0x3D5, inb(0x3D5)&~0x30);
+ outb(0x3D4, 0x3A);
+ outb(0x3D5, 0x00);
+ outb(0x3D4, 0x53);
+ outb(0x3D5, 0x00);
+ outb(0x3D4, 0x31);
+ outb(0x3D5, inb(0x3D5)&~0x4B);
+ outb(0x3D4, 0x58);
+
+ outb(0x3D5, 0);
+
+ outb(0x3D4, 0x54);
+ outb(0x3D5, 0x38);
+ outb(0x3D4, 0x60);
+ outb(0x3D5, 0x07);
+ outb(0x3D4, 0x61);
+ outb(0x3D5, 0x80);
+ outb(0x3D4, 0x62);
+ outb(0x3D5, 0xA1);
+ outb(0x3D4, 0x69); /* High order bits for cursor address */
+ outb(0x3D5, 0);
+
+ outb(0x3D4, 0x32);
+ outb(0x3D5, inb(0x3D5)&~0x10);
+ } else {
+ outw(0x3c4, 0x0806); /* IBM Portable 860 */
+ outw(0x3c4, 0x1041);
+ outw(0x3c4, 0x1128);
+ outw(0x3d4, 0x4000);
+ outw(0x3d4, 0x3100);
+ outw(0x3d4, 0x3a05);
+ outw(0x3d4, 0x6688);
+ outw(0x3d4, 0x5800); /* disable linear addressing */
+ outw(0x3d4, 0x4500); /* disable H/W cursor */
+ outw(0x3c4, 0x5410); /* enable auto-centering */
+ outw(0x3c4, 0x561f);
+ outw(0x3c4, 0x1b80); /* lock DCLK selection */
+ outw(0x3d4, 0x3900); /* lock S3 registers */
+ outw(0x3d4, 0x3800);
+ } /* endif */
+}
+
+/*
+ * cursor() sets an offset (0-1999) into the 80x25 text area.
+ */
+void
+cursor(int x, int y)
+{
+ int pos = (y*cols)+x;
+ outb(0x3D4, 14);
+ outb(0x3D5, pos >> 8);
+ outb(0x3D4, 15);
+ outb(0x3D5, pos);
+}
+
+void
+clearVideoMemory(void)
+{
+ int i, j;
+ for (i = 0; i < lines; i++) {
+ for (j = 0; j < cols; j++) {
+ vidmem[((i*cols)+j)*2] = 0x20; /* fill with space character */
+ vidmem[((i*cols)+j)*2+1] = 0x07; /* set bg & fg attributes */
+ }
+ }
+}
+
+/* ============ */
+
+
+#define NSLOTS 8
+#define NPCIREGS 5
+
+
+/*
+ should use devfunc number/indirect method to be totally safe on
+ all machines, this works for now on 3 slot Moto boxes
+*/
+
+struct PCI_ConfigInfo {
+ unsigned long * config_addr;
+ unsigned long regs[NPCIREGS];
+} PCI_slots [NSLOTS] = {
+
+ { (unsigned long *)0x80808000, {0xDEADBEEF,} }, /* onboard */
+ { (unsigned long *)0x80800800, {0xDEADBEEF,} }, /* onboard */
+ { (unsigned long *)0x80801000, {0xDEADBEEF,} }, /* onboard */
+ { (unsigned long *)0x80802000, {0xDEADBEEF,} }, /* onboard */
+ { (unsigned long *)0x80804000, {0xDEADBEEF,} }, /* onboard */
+ { (unsigned long *)0x80810000, {0xDEADBEEF,} }, /* slot A/1 */
+ { (unsigned long *)0x80820000, {0xDEADBEEF,} }, /* slot B/2 */
+ { (unsigned long *)0x80840000, {0xDEADBEEF,} } /* slot C/3 */
+};
+
+
+
+/*
+ * The following code modifies the PCI Command register
+ * to enable memory and I/O accesses.
+ */
+void
+unlockVideo(int slot)
+{
+ volatile unsigned char * ppci;
+
+ ppci = (unsigned char * )PCI_slots[slot].config_addr;
+ ppci[4] = 0x0003; /* enable memory and I/O accesses */
+ ppci[0x10] = 0x00000; /* turn off memory mapping */
+ ppci[0x11] = 0x00000; /* mem_base = 0 */
+ ppci[0x12] = 0x00000;
+ ppci[0x13] = 0x00000;
+ __asm__ volatile("eieio");
+
+ outb(0x3d4, 0x11);
+ outb(0x3d5, 0x0e); /* unlock CR0-CR7 */
+}
+
+long
+SwapBytes(long lv) /* turn little endian into big indian long */
+{
+ long t;
+ t = (lv&0x000000FF) << 24;
+ t |= (lv&0x0000FF00) << 8;
+ t |= (lv&0x00FF0000) >> 8;
+ t |= (lv&0xFF000000) >> 24;
+ return(t);
+}
+
+
+#define DEVID 0
+#define CMD 1
+#define CLASS 2
+#define MEMBASE 4
+
+int
+scanPCI(int start_slt)
+{
+ int slt, r;
+ struct PCI_ConfigInfo *pslot;
+ int theSlot = -1;
+ int highVgaSlot = 0;
+
+ for ( slt = start_slt + 1; slt < NSLOTS; slt++) {
+ pslot = &PCI_slots[slt];
+ for ( r = 0; r < NPCIREGS; r++) {
+ pslot->regs[r] = SwapBytes ( pslot->config_addr[r] );
+ }
+ /* card in slot ? */
+ if ( pslot->regs[DEVID] != 0xFFFFFFFF ) {
+ /* VGA ? */
+ if ( ((pslot->regs[CLASS] & 0xFFFFFF00) == 0x03000000) ||
+ ((pslot->regs[CLASS] & 0xFFFFFF00) == 0x00010000)) {
+ highVgaSlot = slt;
+ /* did firmware enable it ? */
+ if ( (pslot->regs[CMD] & 0x03) ) {
+ theSlot = slt;
+ break;
+ }
+ }
+ }
+ }
+
+ return ( theSlot );
+}
+
+/* return Vendor ID of card in the slot */
+static
+int PCIVendor(int slotnum) {
+ struct PCI_ConfigInfo *pslot;
+
+ pslot = &PCI_slots[slotnum];
+
+return (pslot->regs[DEVID] & 0xFFFF);
+}
+
+#ifdef DEBUG
+static
+void printslots(void)
+{
+ int i;
+#if 0
+ struct PCI_ConfigInfo *pslot;
+#endif
+ for(i=0; i < NSLOTS; i++) {
+#if 0
+ pslot = &PCI_slots[i];
+ printf("Slot: %d, Addr: %x, Vendor: %08x, Class: %08x\n",
+ i, pslot->config_addr, pslot->regs[0], pslot->regs[2]);
+#else
+ puts("PCI Slot number: "); puthex(i);
+ puts(" Vendor ID: ");
+ puthex(PCIVendor(i)); puts("\n");
+#endif
+ }
+}
+#endif /* DEBUG */
diff --git a/arch/ppc/boot/of1275/Makefile b/arch/ppc/boot/of1275/Makefile
new file mode 100644
index 0000000..02e6f23
--- /dev/null
+++ b/arch/ppc/boot/of1275/Makefile
@@ -0,0 +1,6 @@
+#
+# Makefile of1275 stuff
+#
+
+lib-y := claim.o enter.o exit.o finddevice.o getprop.o ofinit.o \
+ ofstdio.o read.o release.o write.o map.o
diff --git a/arch/ppc/boot/of1275/claim.c b/arch/ppc/boot/of1275/claim.c
new file mode 100644
index 0000000..e060292
--- /dev/null
+++ b/arch/ppc/boot/of1275/claim.c
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) Paul Mackerras 1997.
+ * Copyright (C) Leigh Brown 2002.
+ *
+ * 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.
+ */
+
+#include "of1275.h"
+
+void *
+claim(unsigned int virt, unsigned int size, unsigned int align)
+{
+ struct prom_args {
+ char *service;
+ int nargs;
+ int nret;
+ unsigned int virt;
+ unsigned int size;
+ unsigned int align;
+ void *ret;
+ } args;
+
+ args.service = "claim";
+ args.nargs = 3;
+ args.nret = 1;
+ args.virt = virt;
+ args.size = size;
+ args.align = align;
+ (*of_prom_entry)(&args);
+ return args.ret;
+}
diff --git a/arch/ppc/boot/of1275/enter.c b/arch/ppc/boot/of1275/enter.c
new file mode 100644
index 0000000..abe87a8
--- /dev/null
+++ b/arch/ppc/boot/of1275/enter.c
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) Paul Mackerras 1997.
+ * Copyright (C) Leigh Brown 2002.
+ *
+ * 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.
+ */
+
+#include "of1275.h"
+
+void
+enter(void)
+{
+ struct prom_args {
+ char *service;
+ } args;
+
+ args.service = "enter";
+ (*of_prom_entry)(&args);
+}
diff --git a/arch/ppc/boot/of1275/exit.c b/arch/ppc/boot/of1275/exit.c
new file mode 100644
index 0000000..b9f89b6
--- /dev/null
+++ b/arch/ppc/boot/of1275/exit.c
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) Paul Mackerras 1997.
+ * Copyright (C) Leigh Brown 2002.
+ *
+ * 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.
+ */
+
+#include "of1275.h"
+
+void
+exit(void)
+{
+ struct prom_args {
+ char *service;
+ } args;
+
+ for (;;) {
+ args.service = "exit";
+ (*of_prom_entry)(&args);
+ }
+}
diff --git a/arch/ppc/boot/of1275/finddevice.c b/arch/ppc/boot/of1275/finddevice.c
new file mode 100644
index 0000000..2c0f7cb
--- /dev/null
+++ b/arch/ppc/boot/of1275/finddevice.c
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) Paul Mackerras 1997.
+ * Copyright (C) Leigh Brown 2002.
+ *
+ * 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.
+ */
+
+#include "of1275.h"
+
+phandle
+finddevice(const char *name)
+{
+ struct prom_args {
+ char *service;
+ int nargs;
+ int nret;
+ const char *devspec;
+ phandle device;
+ } args;
+
+ args.service = "finddevice";
+ args.nargs = 1;
+ args.nret = 1;
+ args.devspec = name;
+ args.device = OF_INVALID_HANDLE;
+ (*of_prom_entry)(&args);
+ return args.device;
+}
diff --git a/arch/ppc/boot/of1275/getprop.c b/arch/ppc/boot/of1275/getprop.c
new file mode 100644
index 0000000..0cf75f0
--- /dev/null
+++ b/arch/ppc/boot/of1275/getprop.c
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) Paul Mackerras 1997.
+ * Copyright (C) Leigh Brown 2002.
+ *
+ * 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.
+ */
+
+#include "of1275.h"
+
+int
+getprop(phandle node, const char *name, void *buf, int buflen)
+{
+ struct prom_args {
+ char *service;
+ int nargs;
+ int nret;
+ phandle node;
+ const char *name;
+ void *buf;
+ int buflen;
+ int size;
+ } args;
+
+ args.service = "getprop";
+ args.nargs = 4;
+ args.nret = 1;
+ args.node = node;
+ args.name = name;
+ args.buf = buf;
+ args.buflen = buflen;
+ args.size = -1;
+ (*of_prom_entry)(&args);
+ return args.size;
+}
diff --git a/arch/ppc/boot/of1275/map.c b/arch/ppc/boot/of1275/map.c
new file mode 100644
index 0000000..443256c
--- /dev/null
+++ b/arch/ppc/boot/of1275/map.c
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) Paul Mackerras 1997.
+ * Copyright (C) Leigh Brown 2002.
+ *
+ * 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.
+ */
+
+#include "of1275.h"
+#include "nonstdio.h"
+
+extern ihandle of_prom_mmu;
+
+int
+map(unsigned int phys, unsigned int virt, unsigned int size)
+{
+ struct prom_args {
+ char *service;
+ int nargs;
+ int nret;
+ char *method;
+ ihandle mmu_ihandle;
+ int misc;
+ unsigned int size;
+ unsigned int virt;
+ unsigned int phys;
+ int ret0;
+ } args;
+
+ if (of_prom_mmu == 0) {
+ printf("map() called, no MMU found\n");
+ return -1;
+ }
+ args.service = "call-method";
+ args.nargs = 6;
+ args.nret = 1;
+ args.method = "map";
+ args.mmu_ihandle = of_prom_mmu;
+ args.misc = 0;
+ args.phys = phys;
+ args.virt = virt;
+ args.size = size;
+ (*of_prom_entry)(&args);
+
+ return (int)args.ret0;
+}
diff --git a/arch/ppc/boot/of1275/ofinit.c b/arch/ppc/boot/of1275/ofinit.c
new file mode 100644
index 0000000..0ee8af7
--- /dev/null
+++ b/arch/ppc/boot/of1275/ofinit.c
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) Paul Mackerras 1997.
+ * Copyright (C) Leigh Brown 2002.
+ *
+ * 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.
+ */
+
+#include "of1275.h"
+
+prom_entry of_prom_entry;
+ihandle of_prom_mmu;
+
+void
+ofinit(prom_entry prom_ptr)
+{
+ phandle chosen;
+
+ of_prom_entry = prom_ptr;
+
+ if ((chosen = finddevice("/chosen")) == OF_INVALID_HANDLE)
+ return;
+ if (getprop(chosen, "mmu", &of_prom_mmu, sizeof(ihandle)) != 4)
+ return;
+}
diff --git a/arch/ppc/boot/of1275/ofstdio.c b/arch/ppc/boot/of1275/ofstdio.c
new file mode 100644
index 0000000..10abbe3
--- /dev/null
+++ b/arch/ppc/boot/of1275/ofstdio.c
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) Paul Mackerras 1997.
+ * Copyright (C) Leigh Brown 2002.
+ *
+ * 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.
+ */
+
+#include "of1275.h"
+
+int
+ofstdio(ihandle *stdin, ihandle *stdout, ihandle *stderr)
+{
+ ihandle in, out;
+ phandle chosen;
+
+ if ((chosen = finddevice("/chosen")) == OF_INVALID_HANDLE)
+ goto err;
+ if (getprop(chosen, "stdout", &out, sizeof(out)) != 4)
+ goto err;
+ if (getprop(chosen, "stdin", &in, sizeof(in)) != 4)
+ goto err;
+
+ *stdin = in;
+ *stdout = out;
+ *stderr = out;
+ return 0;
+err:
+ return -1;
+}
diff --git a/arch/ppc/boot/of1275/read.c b/arch/ppc/boot/of1275/read.c
new file mode 100644
index 0000000..1228136
--- /dev/null
+++ b/arch/ppc/boot/of1275/read.c
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) Paul Mackerras 1997.
+ * Copyright (C) Leigh Brown 2002.
+ *
+ * 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.
+ */
+
+#include "of1275.h"
+
+int
+read(ihandle instance, void *buf, int buflen)
+{
+ struct prom_args {
+ char *service;
+ int nargs;
+ int nret;
+ ihandle instance;
+ void *buf;
+ int buflen;
+ int actual;
+ } args;
+
+ args.service = "read";
+ args.nargs = 3;
+ args.nret = 1;
+ args.instance = instance;
+ args.buf = buf;
+ args.buflen = buflen;
+ args.actual = -1;
+ (*of_prom_entry)(&args);
+ return args.actual;
+}
diff --git a/arch/ppc/boot/of1275/release.c b/arch/ppc/boot/of1275/release.c
new file mode 100644
index 0000000..28032d3
--- /dev/null
+++ b/arch/ppc/boot/of1275/release.c
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) Paul Mackerras 1997.
+ * Copyright (C) Leigh Brown 2002.
+ *
+ * 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.
+ */
+
+#include "of1275.h"
+
+void
+release(void *virt, unsigned int size)
+{
+ struct prom_args {
+ char *service;
+ int nargs;
+ int nret;
+ void *virt;
+ unsigned int size;
+ } args;
+
+ args.service = "release";
+ args.nargs = 2;
+ args.nret = 0;
+ args.virt = virt;
+ args.size = size;
+ (*of_prom_entry)(&args);
+}
diff --git a/arch/ppc/boot/of1275/write.c b/arch/ppc/boot/of1275/write.c
new file mode 100644
index 0000000..7361b9b
--- /dev/null
+++ b/arch/ppc/boot/of1275/write.c
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) Paul Mackerras 1997.
+ * Copyright (C) Leigh Brown 2002.
+ *
+ * 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.
+ */
+
+#include "of1275.h"
+
+int
+write(ihandle instance, void *buf, int buflen)
+{
+ struct prom_args {
+ char *service;
+ int nargs;
+ int nret;
+ ihandle instance;
+ void *buf;
+ int buflen;
+ int actual;
+ } args;
+
+ args.service = "write";
+ args.nargs = 3;
+ args.nret = 1;
+ args.instance = instance;
+ args.buf = buf;
+ args.buflen = buflen;
+ args.actual = -1;
+ (*of_prom_entry)(&args);
+ return args.actual;
+}
diff --git a/arch/ppc/boot/openfirmware/Makefile b/arch/ppc/boot/openfirmware/Makefile
new file mode 100644
index 0000000..4eacbd8
--- /dev/null
+++ b/arch/ppc/boot/openfirmware/Makefile
@@ -0,0 +1,188 @@
+# Makefile for making bootable images on various OpenFirmware machines.
+#
+# Paul Mackerras January 1997
+# XCOFF bootable images for PowerMacs
+# Geert Uytterhoeven September 1997
+# ELF bootable iamges for CHRP machines.
+# Tom Rini January 2001
+# Cleaned up, moved into arch/ppc/boot/pmac
+# Tom Rini July/August 2002
+# Merged 'chrp' and 'pmac' into 'openfirmware', and cleaned up the
+# rules.
+
+zImage.initrd znetboot.initrd: del-ramdisk-sec := -R .ramdisk
+zImage.initrd znetboot.initrd: initrd := .initrd
+
+
+boot := arch/ppc/boot
+common := $(boot)/common
+utils := $(boot)/utils
+bootlib := $(boot)/lib
+of1275 := $(boot)/of1275
+images := $(boot)/images
+
+OBJCOPY_ARGS := -O aixcoff-rs6000 -R .stab -R .stabstr -R .comment
+COFF_LD_ARGS := -T $(srctree)/$(boot)/ld.script -e _start -Ttext 0x00500000 \
+ -Bstatic
+CHRP_LD_ARGS := -T $(srctree)/$(boot)/ld.script -e _start -Ttext 0x00800000
+NEWWORLD_LD_ARGS:= -T $(srctree)/$(boot)/ld.script -e _start -Ttext 0x01000000
+
+COMMONOBJS := start.o misc.o common.o
+COFFOBJS := coffcrt0.o $(COMMONOBJS) coffmain.o
+CHRPOBJS := crt0.o $(COMMONOBJS) chrpmain.o
+NEWWORLDOBJS := crt0.o $(COMMONOBJS) newworldmain.o
+
+targets := $(COFFOBJS) $(CHRPOBJS) $(NEWWORLDOBJS) dummy.o
+COFFOBJS := $(addprefix $(obj)/, $(COFFOBJS))
+CHRPOBJS := $(addprefix $(obj)/, $(CHRPOBJS))
+NEWWORLDOBJS := $(addprefix $(obj)/, $(NEWWORLDOBJS))
+
+LIBS := lib/lib.a $(bootlib)/lib.a $(of1275)/lib.a $(common)/lib.a
+
+HACKCOFF := $(utils)/hack-coff
+
+ifdef CONFIG_SMP
+END := .smp
+endif
+ifdef CONFIG_PPC64BRIDGE
+END += .64
+endif
+
+
+$(images)/ramdisk.image.gz:
+ @echo ' MISSING $@'
+ @echo ' RAM disk image must be provided separately'
+ @/bin/false
+
+objcpxmon-$(CONFIG_XMON) := --add-section=.sysmap=System.map \
+ --set-section-flags=.sysmap=contents,alloc,load,readonly,data
+quiet_cmd_genimage = GEN $@
+ cmd_genimage = $(OBJCOPY) -R .comment \
+ --add-section=.image=$(images)/vmlinux.gz \
+ --set-section-flags=.image=contents,alloc,load,readonly,data \
+ $(objcpxmon-y) $< $@
+
+targets += image.o
+$(obj)/image.o: $(obj)/dummy.o $(images)/vmlinux.gz FORCE
+ $(call if_changed,genimage)
+
+# Place the ramdisk in the initrd image.
+quiet_cmd_genimage-initrd = GEN $@
+ cmd_genimage-initrd = $(OBJCOPY) $< $@ \
+ --add-section=.ramdisk=$(images)/ramdisk.image.gz \
+ --set-section-flags=.ramdisk=contents,alloc,load,readonly,data
+targets += image.initrd.o
+$(obj)/image.initrd.o: $(obj)/image.o $(images)/ramdisk.image.gz FORCE
+ $(call if_changed,genimage-initrd)
+
+# Create the note section for New-World PowerMacs.
+quiet_cmd_mknote = MKNOTE $@
+ cmd_mknote = $(utils)/mknote > $@
+targets += note
+$(obj)/note: $(utils)/mknote FORCE
+ $(call if_changed,mknote)
+
+
+$(obj)/coffcrt0.o: EXTRA_AFLAGS := -traditional -DXCOFF
+$(obj)/crt0.o: EXTRA_AFLAGS := -traditional
+targets += coffcrt0.o crt0.o
+$(obj)/coffcrt0.o $(obj)/crt0.o: $(common)/crt0.S FORCE
+ $(call if_changed_dep,as_o_S)
+
+quiet_cmd_gencoffb = COFF $@
+ cmd_gencoffb = $(LD) -o $@ $(COFF_LD_ARGS) $(COFFOBJS) $< $(LIBS) && \
+ $(OBJCOPY) $@ $@ -R .comment $(del-ramdisk-sec)
+targets += coffboot
+$(obj)/coffboot: $(obj)/image.o $(COFFOBJS) $(LIBS) $(srctree)/$(boot)/ld.script FORCE
+ $(call if_changed,gencoffb)
+targets += coffboot.initrd
+$(obj)/coffboot.initrd: $(obj)/image.initrd.o $(COFFOBJS) $(LIBS) \
+ $(srctree)/$(boot)/ld.script FORCE
+ $(call if_changed,gencoffb)
+
+
+quiet_cmd_gen-coff = COFF $@
+ cmd_gen-coff = $(OBJCOPY) $(OBJCOPY_ARGS) $< $@ && \
+ $(HACKCOFF) $@ && \
+ ln -sf $(notdir $@) $(images)/zImage$(initrd).pmac
+
+$(images)/vmlinux.coff: $(obj)/coffboot
+ $(call cmd,gen-coff)
+
+$(images)/vmlinux.initrd.coff: $(obj)/coffboot.initrd
+ $(call cmd,gen-coff)
+
+quiet_cmd_gen-elf-pmac = ELF $@
+ cmd_gen-elf-pmac = $(LD) $(NEWWORLD_LD_ARGS) -o $@ \
+ $(NEWWORLDOBJS) $(LIBS) $< && \
+ $(OBJCOPY) $@ $@ --add-section=.note=$(obj)/note \
+ -R .comment $(del-ramdisk-sec)
+
+$(images)/vmlinux.elf-pmac: $(obj)/image.o $(NEWWORLDOBJS) $(LIBS) \
+ $(obj)/note $(srctree)/$(boot)/ld.script
+ $(call cmd,gen-elf-pmac)
+$(images)/vmlinux.initrd.elf-pmac: $(obj)/image.initrd.o $(NEWWORLDOBJS) \
+ $(LIBS) $(obj)/note \
+ $(srctree)/$(boot)/ld.script
+ $(call cmd,gen-elf-pmac)
+
+quiet_cmd_gen-chrp = CHRP $@
+ cmd_gen-chrp = $(LD) $(CHRP_LD_ARGS) -o $@ $(CHRPOBJS) $< $(LIBS) && \
+ $(OBJCOPY) $@ $@ -R .comment $(del-ramdisk-sec)
+
+$(images)/zImage.chrp: $(obj)/image.o $(CHRPOBJS) $(LIBS) \
+ $(srctree)/$(boot)/ld.script
+ $(call cmd,gen-chrp)
+$(images)/zImage.initrd.chrp: $(obj)/image.initrd.o $(CHRPOBJS) $(LIBS) \
+ $(srctree)/$(boot)/ld.script
+ $(call cmd,gen-chrp)
+
+quiet_cmd_addnote = ADDNOTE $@
+ cmd_addnote = cat $< > $@ && $(utils)/addnote $@
+$(images)/zImage.chrp-rs6k $(images)/zImage.initrd.chrp-rs6k: \
+ %-rs6k: %
+ $(call cmd,addnote)
+
+quiet_cmd_gen-miboot = GEN $@
+ cmd_gen-miboot = $(OBJCOPY) $(OBJCOPY_ARGS) \
+ --add-section=$1=$(word 2, $^) $< $@
+$(images)/miboot.image: $(obj)/dummy.o $(images)/vmlinux.gz
+ $(call cmd,gen-miboot,image)
+
+$(images)/miboot.initrd.image: $(images)/miboot.image $(images)/ramdisk.image.gz
+ $(call cmd,gen-miboot,initrd)
+
+# The targets used on the make command-line
+
+.PHONY: zImage zImage.initrd
+zImage: $(images)/vmlinux.coff \
+ $(images)/vmlinux.elf-pmac \
+ $(images)/zImage.chrp \
+ $(images)/zImage.chrp-rs6k \
+ $(images)/miboot.image
+ @echo ' kernel: $@ is ready ($<)'
+zImage.initrd: $(images)/vmlinux.initrd.coff \
+ $(images)/vmlinux.initrd.elf-pmac \
+ $(images)/zImage.initrd.chrp \
+ $(images)/zImage.initrd.chrp-rs6k \
+ $(images)/miboot.initrd.image
+ @echo ' kernel: $@ is ready ($<)'
+
+TFTPIMAGE := /tftpboot/zImage
+
+.PHONY: znetboot znetboot.initrd
+znetboot: $(images)/vmlinux.coff \
+ $(images)/vmlinux.elf-pmac \
+ $(images)/zImage.chrp
+ cp $(images)/vmlinux.coff $(TFTPIMAGE).pmac$(END)
+ cp $(images)/vmlinux.elf-pmac $(TFTPIMAGE).pmac$(END).elf
+ cp $(images)/zImage.chrp $(TFTPIMAGE).chrp$(END)
+ @echo ' kernel: $@ is ready ($<)'
+znetboot.initrd:$(images)/vmlinux.initrd.coff \
+ $(images)/vmlinux.initrd.elf-pmac \
+ $(images)/zImage.initrd.chrp
+ cp $(images)/vmlinux.initrd.coff $(TFTPIMAGE).pmac$(END)
+ cp $(images)/vmlinux.initrd.elf-pmac $(TFTPIMAGE).pmac$(END).elf
+ cp $(images)/zImage.initrd.chrp $(TFTPIMAGE).chrp$(END)
+ @echo ' kernel: $@ is ready ($<)'
+
diff --git a/arch/ppc/boot/openfirmware/chrpmain.c b/arch/ppc/boot/openfirmware/chrpmain.c
new file mode 100644
index 0000000..6fb4f73
--- /dev/null
+++ b/arch/ppc/boot/openfirmware/chrpmain.c
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) Paul Mackerras 1997.
+ *
+ * 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.
+ */
+#include <linux/string.h>
+#include "nonstdio.h"
+#include "of1275.h"
+#include <asm/processor.h>
+#include <asm/page.h>
+
+/* Passed from the linker */
+extern char __image_begin, __image_end;
+extern char __ramdisk_begin, __ramdisk_end;
+extern char _start, _end;
+
+extern unsigned int heap_max;
+extern void flush_cache(void *, unsigned long);
+extern void gunzip(void *, int, unsigned char *, int *);
+extern void make_bi_recs(unsigned long addr, char *name, unsigned int mach,
+ unsigned int progend);
+
+char *avail_ram;
+char *begin_avail, *end_avail;
+char *avail_high;
+
+#define RAM_START 0x00000000
+#define RAM_END (64<<20)
+
+#define BOOT_START ((unsigned long)_start)
+#define BOOT_END ((unsigned long)(_end + 0xFFF) & ~0xFFF)
+
+#define RAM_FREE ((unsigned long)(_end+0x1000)&~0xFFF)
+#define PROG_START 0x00010000
+#define PROG_SIZE 0x007f0000 /* 8MB */
+
+#define SCRATCH_SIZE (128 << 10)
+
+static char scratch[SCRATCH_SIZE]; /* 1MB of scratch space for gunzip */
+
+typedef void (*kernel_start_t)(int, int, void *, unsigned int, unsigned int);
+
+void
+boot(int a1, int a2, void *prom)
+{
+ unsigned sa, len;
+ void *dst;
+ unsigned char *im;
+ unsigned int initrd_size, initrd_start;
+
+ printf("chrpboot starting: loaded at 0x%p\n\r", &_start);
+
+ initrd_size = &__ramdisk_end - &__ramdisk_begin;
+ if (initrd_size) {
+ initrd_start = (RAM_END - initrd_size) & ~0xFFF;
+ a1 = initrd_start;
+ a2 = initrd_size;
+ claim(initrd_start, RAM_END - initrd_start, 0);
+ printf("initial ramdisk moving 0x%x <- 0x%p (%x bytes)\n\r",
+ initrd_start, &__ramdisk_begin, initrd_size);
+ memcpy((char *)initrd_start, &__ramdisk_begin, initrd_size);
+ } else {
+ initrd_start = 0;
+ initrd_size = 0;
+ a2 = 0xdeadbeef;
+ }
+
+ im = &__image_begin;
+ len = &__image_end - &__image_begin;
+ /* claim 4MB starting at PROG_START */
+ claim(PROG_START, PROG_SIZE - PROG_START, 0);
+ dst = (void *) PROG_START;
+ if (im[0] == 0x1f && im[1] == 0x8b) {
+ avail_ram = scratch;
+ begin_avail = avail_high = avail_ram;
+ end_avail = scratch + sizeof(scratch);
+ printf("gunzipping (0x%p <- 0x%p:0x%p)...", dst, im, im+len);
+ gunzip(dst, 0x400000, im, &len);
+ printf("done %u bytes\n\r", len);
+ printf("%u bytes of heap consumed, max in use %u\n\r",
+ avail_high - begin_avail, heap_max);
+ } else {
+ memmove(dst, im, len);
+ }
+
+ flush_cache(dst, len);
+ make_bi_recs(((unsigned long) dst + len), "chrpboot", _MACH_chrp,
+ (PROG_START + PROG_SIZE));
+
+ sa = PROG_START;
+ printf("start address = 0x%x\n\r", sa);
+
+ (*(kernel_start_t)sa)(a1, a2, prom, initrd_start, initrd_size);
+
+ printf("returned?\n\r");
+
+ pause();
+}
diff --git a/arch/ppc/boot/openfirmware/coffmain.c b/arch/ppc/boot/openfirmware/coffmain.c
new file mode 100644
index 0000000..04ba9d5
--- /dev/null
+++ b/arch/ppc/boot/openfirmware/coffmain.c
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) Paul Mackerras 1997.
+ *
+ * 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.
+ */
+#include <linux/string.h>
+#include <asm/processor.h>
+#include <asm/page.h>
+
+#include "nonstdio.h"
+#include "of1275.h"
+
+/* Passed from the linker */
+extern char __image_begin, __image_end;
+extern char __ramdisk_begin[], __ramdisk_end;
+extern char _start, _end;
+
+extern char image_data[], initrd_data[];
+extern int initrd_len, image_len;
+extern unsigned int heap_max;
+extern void flush_cache(void *start, unsigned int len);
+extern void gunzip(void *, int, unsigned char *, int *);
+extern void make_bi_recs(unsigned long addr, char *name, unsigned int mach,
+ unsigned int progend);
+extern void setup_bats(unsigned long start);
+
+char *avail_ram;
+char *begin_avail, *end_avail;
+char *avail_high;
+
+#define SCRATCH_SIZE (128 << 10)
+
+static char heap[SCRATCH_SIZE];
+
+static unsigned long ram_start = 0;
+static unsigned long ram_end = 0x1000000;
+
+static unsigned long prog_start = 0x900000;
+static unsigned long prog_size = 0x700000;
+
+typedef void (*kernel_start_t)(int, int, void *);
+
+void boot(int a1, int a2, void *prom)
+{
+ unsigned sa, len;
+ void *dst;
+ unsigned char *im;
+ unsigned initrd_start, initrd_size;
+
+ printf("coffboot starting: loaded at 0x%p\n", &_start);
+ setup_bats(ram_start);
+
+ initrd_size = (char *)(&__ramdisk_end) - (char *)(&__ramdisk_begin);
+ if (initrd_size) {
+ initrd_start = (ram_end - initrd_size) & ~0xFFF;
+ a1 = initrd_start;
+ a2 = initrd_size;
+ claim(initrd_start, ram_end - initrd_start, 0);
+ printf("initial ramdisk moving 0x%x <- 0x%p (%x bytes)\n\r",
+ initrd_start, (char *)(&__ramdisk_begin), initrd_size);
+ memcpy((char *)initrd_start, (char *)(&__ramdisk_begin), initrd_size);
+ prog_size = initrd_start - prog_start;
+ } else
+ a2 = 0xdeadbeef;
+
+ im = (char *)(&__image_begin);
+ len = (char *)(&__image_end) - (char *)(&__image_begin);
+ /* claim 4MB starting at PROG_START */
+ claim(prog_start, prog_size, 0);
+ map(prog_start, prog_start, prog_size);
+ dst = (void *) prog_start;
+ if (im[0] == 0x1f && im[1] == 0x8b) {
+ /* set up scratch space */
+ begin_avail = avail_high = avail_ram = heap;
+ end_avail = heap + sizeof(heap);
+ printf("heap at 0x%p\n", avail_ram);
+ printf("gunzipping (0x%p <- 0x%p:0x%p)...", dst, im, im+len);
+ gunzip(dst, prog_size, im, &len);
+ printf("done %u bytes\n", len);
+ printf("%u bytes of heap consumed, max in use %u\n",
+ avail_high - begin_avail, heap_max);
+ } else {
+ memmove(dst, im, len);
+ }
+
+ flush_cache(dst, len);
+ make_bi_recs(((unsigned long) dst + len), "coffboot", _MACH_Pmac,
+ (prog_start + prog_size));
+
+ sa = (unsigned long)prog_start;
+ printf("start address = 0x%x\n", sa);
+
+ (*(kernel_start_t)sa)(a1, a2, prom);
+
+ printf("returned?\n");
+
+ pause();
+}
diff --git a/arch/ppc/boot/openfirmware/common.c b/arch/ppc/boot/openfirmware/common.c
new file mode 100644
index 0000000..9e69527
--- /dev/null
+++ b/arch/ppc/boot/openfirmware/common.c
@@ -0,0 +1,162 @@
+/*
+ * Copyright (C) Paul Mackerras 1997.
+ *
+ * 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.
+ */
+
+#include "nonstdio.h"
+#include "of1275.h"
+#include <linux/string.h>
+#include <linux/zlib.h>
+#include <asm/bootinfo.h>
+#include <asm/page.h>
+
+/* Information from the linker */
+extern char __sysmap_begin, __sysmap_end;
+
+extern int strcmp(const char *s1, const char *s2);
+extern char *avail_ram, *avail_high;
+extern char *end_avail;
+
+unsigned int heap_use, heap_max;
+
+struct memchunk {
+ unsigned int size;
+ struct memchunk *next;
+};
+
+static struct memchunk *freechunks;
+
+static void *zalloc(unsigned size)
+{
+ void *p;
+ struct memchunk **mpp, *mp;
+
+ size = (size + 7) & -8;
+ heap_use += size;
+ if (heap_use > heap_max)
+ heap_max = heap_use;
+ for (mpp = &freechunks; (mp = *mpp) != 0; mpp = &mp->next) {
+ if (mp->size == size) {
+ *mpp = mp->next;
+ return mp;
+ }
+ }
+ p = avail_ram;
+ avail_ram += size;
+ if (avail_ram > avail_high)
+ avail_high = avail_ram;
+ if (avail_ram > end_avail) {
+ printf("oops... out of memory\n\r");
+ pause();
+ }
+ return p;
+}
+
+#define HEAD_CRC 2
+#define EXTRA_FIELD 4
+#define ORIG_NAME 8
+#define COMMENT 0x10
+#define RESERVED 0xe0
+
+void gunzip(void *dst, int dstlen, unsigned char *src, int *lenp)
+{
+ z_stream s;
+ int r, i, flags;
+
+ /* skip header */
+ i = 10;
+ flags = src[3];
+ if (src[2] != Z_DEFLATED || (flags & RESERVED) != 0) {
+ printf("bad gzipped data\n\r");
+ exit();
+ }
+ if ((flags & EXTRA_FIELD) != 0)
+ i = 12 + src[10] + (src[11] << 8);
+ if ((flags & ORIG_NAME) != 0)
+ while (src[i++] != 0)
+ ;
+ if ((flags & COMMENT) != 0)
+ while (src[i++] != 0)
+ ;
+ if ((flags & HEAD_CRC) != 0)
+ i += 2;
+ if (i >= *lenp) {
+ printf("gunzip: ran out of data in header\n\r");
+ exit();
+ }
+
+ /* Initialize ourself. */
+ s.workspace = zalloc(zlib_inflate_workspacesize());
+ r = zlib_inflateInit2(&s, -MAX_WBITS);
+ if (r != Z_OK) {
+ printf("zlib_inflateInit2 returned %d\n\r", r);
+ exit();
+ }
+ s.next_in = src + i;
+ s.avail_in = *lenp - i;
+ s.next_out = dst;
+ s.avail_out = dstlen;
+ r = zlib_inflate(&s, Z_FINISH);
+ if (r != Z_OK && r != Z_STREAM_END) {
+ printf("inflate returned %d msg: %s\n\r", r, s.msg);
+ exit();
+ }
+ *lenp = s.next_out - (unsigned char *) dst;
+ zlib_inflateEnd(&s);
+}
+
+/* Make a bi_rec in OF. We need to be passed a name for BI_BOOTLOADER_ID,
+ * a machine type for BI_MACHTYPE, and the location where the end of the
+ * bootloader is (PROG_START + PROG_SIZE)
+ */
+void make_bi_recs(unsigned long addr, char *name, unsigned int mach,
+ unsigned long progend)
+{
+ unsigned long sysmap_size;
+ struct bi_record *rec;
+
+ /* Figure out the size of a possible System.map we're going to
+ * pass along.
+ * */
+ sysmap_size = (unsigned long)(&__sysmap_end) -
+ (unsigned long)(&__sysmap_begin);
+
+ /* leave a 1MB gap then align to the next 1MB boundary */
+ addr = _ALIGN(addr+ (1<<20) - 1, (1<<20));
+ /* oldworld machine seem very unhappy about this. -- Tom */
+ if (addr >= progend)
+ claim(addr, 0x1000, 0);
+
+ rec = (struct bi_record *)addr;
+ rec->tag = BI_FIRST;
+ rec->size = sizeof(struct bi_record);
+ rec = (struct bi_record *)((unsigned long)rec + rec->size);
+
+ rec->tag = BI_BOOTLOADER_ID;
+ sprintf( (char *)rec->data, name);
+ rec->size = sizeof(struct bi_record) + strlen(name) + 1;
+ rec = (struct bi_record *)((unsigned long)rec + rec->size);
+
+ rec->tag = BI_MACHTYPE;
+ rec->data[0] = mach;
+ rec->data[1] = 1;
+ rec->size = sizeof(struct bi_record) + 2 * sizeof(unsigned long);
+ rec = (struct bi_record *)((unsigned long)rec + rec->size);
+
+ if (sysmap_size) {
+ rec->tag = BI_SYSMAP;
+ rec->data[0] = (unsigned long)(&__sysmap_begin);
+ rec->data[1] = sysmap_size;
+ rec->size = sizeof(struct bi_record) + 2 *
+ sizeof(unsigned long);
+ rec = (struct bi_record *)((unsigned long)rec + rec->size);
+ }
+
+ rec->tag = BI_LAST;
+ rec->size = sizeof(struct bi_record);
+ rec = (struct bi_record *)((unsigned long)rec + rec->size);
+}
diff --git a/arch/ppc/boot/openfirmware/dummy.c b/arch/ppc/boot/openfirmware/dummy.c
new file mode 100644
index 0000000..31dbf45
--- /dev/null
+++ b/arch/ppc/boot/openfirmware/dummy.c
@@ -0,0 +1,4 @@
+int main(void)
+{
+ return 0;
+}
diff --git a/arch/ppc/boot/openfirmware/misc.S b/arch/ppc/boot/openfirmware/misc.S
new file mode 100644
index 0000000..ab9e897
--- /dev/null
+++ b/arch/ppc/boot/openfirmware/misc.S
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) Paul Mackerras 1997.
+ *
+ * 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.
+ */
+ .text
+
+/*
+ * Use the BAT2 & 3 registers to map the 1st 16MB of RAM to
+ * the address given as the 1st argument.
+ */
+ .globl setup_bats
+setup_bats:
+ mfpvr 5
+ rlwinm 5,5,16,16,31 /* r3 = 1 for 601, 4 for 604 */
+ cmpwi 0,5,1
+ li 0,0
+ bne 4f
+ mtibatl 3,0 /* invalidate BAT first */
+ ori 3,3,4 /* set up BAT registers for 601 */
+ li 4,0x7f
+ mtibatu 2,3
+ mtibatl 2,4
+ oris 3,3,0x80
+ oris 4,4,0x80
+ mtibatu 3,3
+ mtibatl 3,4
+ b 5f
+4: mtdbatu 3,0 /* invalidate BATs first */
+ mtibatu 3,0
+ ori 3,3,0xff /* set up BAT registers for 604 */
+ li 4,2
+ mtdbatl 2,4
+ mtdbatu 2,3
+ mtibatl 2,4
+ mtibatu 2,3
+ oris 3,3,0x80
+ oris 4,4,0x80
+ mtdbatl 3,4
+ mtdbatu 3,3
+ mtibatl 3,4
+ mtibatu 3,3
+5: sync
+ isync
+ blr
+
+/*
+ * Flush the dcache and invalidate the icache for a range of addresses.
+ *
+ * flush_cache(addr, len)
+ */
+ .global flush_cache
+flush_cache:
+ addi 4,4,0x1f /* len = (len + 0x1f) / 0x20 */
+ rlwinm. 4,4,27,5,31
+ mtctr 4
+ beqlr
+1: dcbf 0,3
+ icbi 0,3
+ addi 3,3,0x20
+ bdnz 1b
+ sync
+ isync
+ blr
diff --git a/arch/ppc/boot/openfirmware/newworldmain.c b/arch/ppc/boot/openfirmware/newworldmain.c
new file mode 100644
index 0000000..fa8a8f9
--- /dev/null
+++ b/arch/ppc/boot/openfirmware/newworldmain.c
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) Paul Mackerras 1997.
+ *
+ * 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.
+ */
+#include <linux/string.h>
+#include "nonstdio.h"
+#include "of1275.h"
+#include <asm/processor.h>
+#include <asm/page.h>
+
+/* Passed from the linker */
+extern char __image_begin, __image_end;
+extern char __ramdisk_begin[], __ramdisk_end;
+extern char _start, _end;
+
+extern unsigned int heap_max;
+extern void flush_cache(void *start, unsigned int len);
+extern void gunzip(void *, int, unsigned char *, int *);
+extern void make_bi_recs(unsigned long addr, char *name, unsigned int mach,
+ unsigned int progend);
+
+char *avail_ram;
+char *begin_avail, *end_avail;
+char *avail_high;
+
+
+#define RAM_END (16 << 20)
+
+#define PROG_START 0x00010000
+#define PROG_SIZE 0x007f0000
+
+#define SCRATCH_SIZE (128 << 10)
+
+typedef void (*kernel_start_t)(int, int, void *);
+
+void boot(int a1, int a2, void *prom)
+{
+ unsigned sa, len;
+ void *dst;
+ unsigned char *im;
+ unsigned initrd_start, initrd_size;
+
+ printf("chrpboot starting: loaded at 0x%p\n", &_start);
+
+ initrd_size = (char *)(&__ramdisk_end) - (char *)(&__ramdisk_begin);
+ if (initrd_size) {
+ initrd_start = (RAM_END - initrd_size) & ~0xFFF;
+ a1 = initrd_start;
+ a2 = initrd_size;
+ claim(initrd_start, RAM_END - initrd_start, 0);
+ printf("initial ramdisk moving 0x%x <- 0x%p (%x bytes)\n\r",
+ initrd_start, (char *)(&__ramdisk_begin), initrd_size);
+ memcpy((char *)initrd_start, (char *)(&__ramdisk_begin), initrd_size);
+ } else
+ a2 = 0xdeadbeef;
+
+ im = (char *)(&__image_begin);
+ len = (char *)(&__image_end) - (char *)(&__image_begin);
+ /* claim 3MB starting at PROG_START */
+ claim(PROG_START, PROG_SIZE, 0);
+ dst = (void *) PROG_START;
+ if (im[0] == 0x1f && im[1] == 0x8b) {
+ /* claim some memory for scratch space */
+ avail_ram = (char *) claim(0, SCRATCH_SIZE, 0x10);
+ begin_avail = avail_high = avail_ram;
+ end_avail = avail_ram + SCRATCH_SIZE;
+ printf("heap at 0x%p\n", avail_ram);
+ printf("gunzipping (0x%p <- 0x%p:0x%p)...", dst, im, im+len);
+ gunzip(dst, PROG_SIZE, im, &len);
+ printf("done %u bytes\n", len);
+ printf("%u bytes of heap consumed, max in use %u\n",
+ avail_high - begin_avail, heap_max);
+ release(begin_avail, SCRATCH_SIZE);
+ } else {
+ memmove(dst, im, len);
+ }
+
+ flush_cache(dst, len);
+ make_bi_recs(((unsigned long) dst + len), "chrpboot", _MACH_Pmac,
+ (PROG_START + PROG_SIZE));
+
+ sa = (unsigned long)PROG_START;
+ printf("start address = 0x%x\n", sa);
+
+ (*(kernel_start_t)sa)(a1, a2, prom);
+
+ printf("returned?\n");
+
+ pause();
+}
diff --git a/arch/ppc/boot/openfirmware/start.c b/arch/ppc/boot/openfirmware/start.c
new file mode 100644
index 0000000..1617a26
--- /dev/null
+++ b/arch/ppc/boot/openfirmware/start.c
@@ -0,0 +1,172 @@
+/*
+ * Copyright (C) Paul Mackerras 1997.
+ *
+ * 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.
+ */
+#include <stdarg.h>
+#include "of1275.h"
+
+extern int strlen(const char *s);
+extern void boot(int a1, int a2, void *prom);
+
+phandle stdin;
+phandle stdout;
+phandle stderr;
+
+void printk(char *fmt, ...);
+
+void
+start(int a1, int a2, void *promptr)
+{
+ ofinit(promptr);
+ if (ofstdio(&stdin, &stdout, &stderr))
+ exit();
+
+ boot(a1, a2, promptr);
+ for (;;)
+ exit();
+}
+
+int writestring(void *f, char *ptr, int nb)
+{
+ int w = 0, i;
+ char *ret = "\r";
+
+ for (i = 0; i < nb; ++i) {
+ if (ptr[i] == '\n') {
+ if (i > w) {
+ write(f, ptr + w, i - w);
+ w = i;
+ }
+ write(f, ret, 1);
+ }
+ }
+ if (w < nb)
+ write(f, ptr + w, nb - w);
+ return nb;
+}
+
+int
+putc(int c, void *f)
+{
+ char ch = c;
+
+ return writestring(f, &ch, 1) == 1? c: -1;
+}
+
+int
+putchar(int c)
+{
+ return putc(c, stdout);
+}
+
+int
+fputs(char *str, void *f)
+{
+ int n = strlen(str);
+
+ return writestring(f, str, n) == n? 0: -1;
+}
+
+int
+readchar(void)
+{
+ char ch;
+
+ for (;;) {
+ switch (read(stdin, &ch, 1)) {
+ case 1:
+ return ch;
+ case -1:
+ printk("read(stdin) returned -1\n");
+ return -1;
+ }
+ }
+}
+
+static char line[256];
+static char *lineptr;
+static int lineleft;
+
+int
+getchar(void)
+{
+ int c;
+
+ if (lineleft == 0) {
+ lineptr = line;
+ for (;;) {
+ c = readchar();
+ if (c == -1 || c == 4)
+ break;
+ if (c == '\r' || c == '\n') {
+ *lineptr++ = '\n';
+ putchar('\n');
+ break;
+ }
+ switch (c) {
+ case 0177:
+ case '\b':
+ if (lineptr > line) {
+ putchar('\b');
+ putchar(' ');
+ putchar('\b');
+ --lineptr;
+ }
+ break;
+ case 'U' & 0x1F:
+ while (lineptr > line) {
+ putchar('\b');
+ putchar(' ');
+ putchar('\b');
+ --lineptr;
+ }
+ break;
+ default:
+ if (lineptr >= &line[sizeof(line) - 1])
+ putchar('\a');
+ else {
+ putchar(c);
+ *lineptr++ = c;
+ }
+ }
+ }
+ lineleft = lineptr - line;
+ lineptr = line;
+ }
+ if (lineleft == 0)
+ return -1;
+ --lineleft;
+ return *lineptr++;
+}
+
+extern int vsprintf(char *buf, const char *fmt, va_list args);
+static char sprint_buf[1024];
+
+void
+printk(char *fmt, ...)
+{
+ va_list args;
+ int n;
+
+ va_start(args, fmt);
+ n = vsprintf(sprint_buf, fmt, args);
+ va_end(args);
+ writestring(stdout, sprint_buf, n);
+}
+
+int
+printf(char *fmt, ...)
+{
+ va_list args;
+ int n;
+
+ va_start(args, fmt);
+ n = vsprintf(sprint_buf, fmt, args);
+ va_end(args);
+ writestring(stdout, sprint_buf, n);
+ return n;
+}
diff --git a/arch/ppc/boot/simple/Makefile b/arch/ppc/boot/simple/Makefile
new file mode 100644
index 0000000..d8d801f
--- /dev/null
+++ b/arch/ppc/boot/simple/Makefile
@@ -0,0 +1,252 @@
+# This is far from simple, but I couldn't think of a good name. This is
+# for making the 'zImage' or 'zImage.initrd' on a number of targets.
+#
+# Author: Tom Rini <trini@mvista.com>
+#
+# Notes:
+# (1) For machines that do not want to use the ELF image directly (including
+# stripping just the ELF header off), they must set the variables
+# zimage-$(CONFIG_MACHINE) and zimagerd-$(CONFIG_MACHINE) to the target
+# that produces the desired image and they must set end-$(CONFIG_MACHINE)
+# to what will be suffixed to the image filename.
+# (2) Regardless of (1), to have the resulting image be something other
+# than 'zImage.elf', set end-$(CONFIG_MACHINE) to be the suffix used for
+# the zImage, znetboot, and znetbootrd targets.
+# (3) For machine targets which use the mktree program, you can optionally
+# set entrypoint-$(CONFIG_MACHINE) to the location which the image should be
+# loaded at. The optimal setting for entrypoint-$(CONFIG_MACHINE) is the link
+# address.
+# (4) It is advisable to pass in the memory size using BI_MEMSIZE and
+# get_mem_size(), which is memory controller dependent. Add in the correct
+# XXX_memory.o file for this to work, as well as editing the
+# misc-$(CONFIG_MACHINE) variable.
+
+boot := arch/ppc/boot
+common := $(boot)/common
+utils := $(boot)/utils
+bootlib := $(boot)/lib
+images := $(boot)/images
+of1275 := $(boot)/of1275
+tftpboot := /tftpboot
+
+# Normally, we use the 'misc.c' file for decompress_kernel and
+# whatnot. Sometimes we need to override this however.
+misc-y := misc.o
+
+# Normally, we have our images end in .elf, but something we want to
+# change this.
+end-y := elf
+
+# Additionally, we normally don't need to mess with the L2 / L3 caches
+# if present on 'classic' PPC.
+cacheflag-y := -DCLEAR_CACHES=""
+# This file will flush / disable the L2, and L3 if present.
+clear_L2_L3 := $(srctree)/$(boot)/simple/clear.S
+
+#
+# See arch/ppc/kconfig and arch/ppc/platforms/Kconfig
+# for definition of what platform each config option refer to.
+#----------------------------------------------------------------------------
+ zimage-$(CONFIG_CPCI690) := zImage-STRIPELF
+zimageinitrd-$(CONFIG_CPCI690) := zImage.initrd-STRIPELF
+ extra.o-$(CONFIG_CPCI690) := misc-cpci690.o
+ end-$(CONFIG_CPCI690) := cpci690
+ cacheflag-$(CONFIG_CPCI690) := -include $(clear_L2_L3)
+
+ zimage-$(CONFIG_IBM_OPENBIOS) := zImage-TREE
+zimageinitrd-$(CONFIG_IBM_OPENBIOS) := zImage.initrd-TREE
+ end-$(CONFIG_IBM_OPENBIOS) := treeboot
+ misc-$(CONFIG_IBM_OPENBIOS) := misc-embedded.o
+
+ end-$(CONFIG_EMBEDDEDBOOT) := embedded
+ misc-$(CONFIG_EMBEDDEDBOOT) := misc-embedded.o
+
+ zimage-$(CONFIG_EBONY) := zImage-TREE
+zimageinitrd-$(CONFIG_EBONY) := zImage.initrd-TREE
+ end-$(CONFIG_EBONY) := ebony
+ entrypoint-$(CONFIG_EBONY) := 0x01000000
+ extra.o-$(CONFIG_EBONY) := openbios.o
+
+ zimage-$(CONFIG_LUAN) := zImage-TREE
+zimageinitrd-$(CONFIG_LUAN) := zImage.initrd-TREE
+ end-$(CONFIG_LUAN) := luan
+ entrypoint-$(CONFIG_LUAN) := 0x01000000
+ extra.o-$(CONFIG_LUAN) := pibs.o
+
+ zimage-$(CONFIG_OCOTEA) := zImage-TREE
+zimageinitrd-$(CONFIG_OCOTEA) := zImage.initrd-TREE
+ end-$(CONFIG_OCOTEA) := ocotea
+ entrypoint-$(CONFIG_OCOTEA) := 0x01000000
+ extra.o-$(CONFIG_OCOTEA) := pibs.o
+
+ extra.o-$(CONFIG_EV64260) := misc-ev64260.o
+ end-$(CONFIG_EV64260) := ev64260
+ cacheflag-$(CONFIG_EV64260) := -include $(clear_L2_L3)
+
+ extra.o-$(CONFIG_CHESTNUT) := misc-chestnut.o
+ end-$(CONFIG_CHESTNUT) := chestnut
+
+ zimage-$(CONFIG_GEMINI) := zImage-STRIPELF
+zimageinitrd-$(CONFIG_GEMINI) := zImage.initrd-STRIPELF
+ end-$(CONFIG_GEMINI) := gemini
+
+ extra.o-$(CONFIG_K2) := prepmap.o
+ end-$(CONFIG_K2) := k2
+ cacheflag-$(CONFIG_K2) := -include $(clear_L2_L3)
+
+ extra.o-$(CONFIG_KATANA) := misc-katana.o
+ end-$(CONFIG_KATANA) := katana
+ cacheflag-$(CONFIG_KATANA) := -include $(clear_L2_L3)
+
+ extra.o-$(CONFIG_RADSTONE_PPC7D) := misc-radstone_ppc7d.o
+ end-$(CONFIG_RADSTONE_PPC7D) := radstone_ppc7d
+ cacheflag-$(CONFIG_RADSTONE_PPC7D) := -include $(clear_L2_L3)
+
+# kconfig 'feature', only one of these will ever be 'y' at a time.
+# The rest will be unset.
+motorola := $(CONFIG_MCPN765)$(CONFIG_MVME5100)$(CONFIG_PRPMC750) \
+$(CONFIG_PRPMC800)$(CONFIG_LOPEC)$(CONFIG_PPLUS)
+motorola := $(strip $(motorola))
+pcore := $(CONFIG_PCORE)$(CONFIG_POWERPMC250)
+
+ zimage-$(motorola) := zImage-PPLUS
+zimageinitrd-$(motorola) := zImage.initrd-PPLUS
+ end-$(motorola) := pplus
+
+# Overrides previous assingment
+ extra.o-$(CONFIG_PPLUS) := prepmap.o
+ extra.o-$(CONFIG_LOPEC) := mpc10x_memory.o
+
+ zimage-$(pcore) := zImage-STRIPELF
+zimageinitrd-$(pcore) := zImage.initrd-STRIPELF
+ extra.o-$(pcore) := chrpmap.o
+ end-$(pcore) := pcore
+ cacheflag-$(pcore) := -include $(clear_L2_L3)
+
+ zimage-$(CONFIG_PPC_PREP) := zImage-PPLUS
+zimageinitrd-$(CONFIG_PPC_PREP) := zImage.initrd-PPLUS
+ extra.o-$(CONFIG_PPC_PREP) := prepmap.o
+ misc-$(CONFIG_PPC_PREP) += misc-prep.o mpc10x_memory.o
+ end-$(CONFIG_PPC_PREP) := prep
+
+ end-$(CONFIG_SANDPOINT) := sandpoint
+ cacheflag-$(CONFIG_SANDPOINT) := -include $(clear_L2_L3)
+
+ zimage-$(CONFIG_SPRUCE) := zImage-TREE
+zimageinitrd-$(CONFIG_SPRUCE) := zImage.initrd-TREE
+ end-$(CONFIG_SPRUCE) := spruce
+ entrypoint-$(CONFIG_SPRUCE) := 0x00800000
+ misc-$(CONFIG_SPRUCE) += misc-spruce.o
+
+ zimage-$(CONFIG_LITE5200) := zImage-STRIPELF
+zimageinitrd-$(CONFIG_LITE5200) := zImage.initrd-STRIPELF
+ end-$(CONFIG_LITE5200) := lite5200
+ cacheflag-$(CONFIG_LITE5200) := -include $(clear_L2_L3)
+
+
+# SMP images should have a '.smp' suffix.
+ end-$(CONFIG_SMP) := $(end-y).smp
+
+# This is a treeboot that needs init functions until the
+# boot rom is sorted out (i.e. this is short lived)
+extra-aflags-$(CONFIG_REDWOOD_4) := -Wa,-m405
+extra.o-$(CONFIG_REDWOOD_4) := rw4/rw4_init.o rw4/rw4_init_brd.o
+EXTRA_AFLAGS := $(extra-aflags-y)
+# head.o needs to get the cacheflags defined.
+AFLAGS_head.o += $(cacheflag-y)
+
+# Linker args. This specifies where the image will be run at.
+LD_ARGS := -T $(srctree)/$(boot)/ld.script \
+ -Ttext $(CONFIG_BOOT_LOAD) -Bstatic
+OBJCOPY_ARGS := -O elf32-powerpc
+
+# head.o and relocate.o must be at the start.
+boot-y := head.o relocate.o $(extra.o-y) $(misc-y)
+boot-$(CONFIG_40x) += embed_config.o
+boot-$(CONFIG_8xx) += embed_config.o
+boot-$(CONFIG_8260) += embed_config.o
+boot-$(CONFIG_BSEIP) += iic.o
+boot-$(CONFIG_MBX) += iic.o pci.o qspan_pci.o
+boot-$(CONFIG_MV64X60) += misc-mv64x60.o
+boot-$(CONFIG_RPXCLASSIC) += iic.o pci.o qspan_pci.o
+boot-$(CONFIG_RPXLITE) += iic.o
+# Different boards need different serial implementations.
+ifeq ($(CONFIG_SERIAL_CPM_CONSOLE),y)
+boot-$(CONFIG_8xx) += m8xx_tty.o
+boot-$(CONFIG_8260) += m8260_tty.o
+endif
+boot-$(CONFIG_SERIAL_MPC52xx_CONSOLE) += mpc52xx_tty.o
+boot-$(CONFIG_SERIAL_MPSC_CONSOLE) += mv64x60_tty.o
+
+LIBS := $(common)/lib.a $(bootlib)/lib.a
+ifeq ($(CONFIG_PPC_PREP),y)
+LIBS += $(of1275)/lib.a
+endif
+
+OBJS := $(addprefix $(obj)/,$(boot-y))
+
+# Tools
+MKBUGBOOT := $(utils)/mkbugboot
+MKPREP := $(utils)/mkprep
+MKTREE := $(utils)/mktree
+
+targets := dummy.o
+
+$(obj)/zvmlinux: $(OBJS) $(LIBS) $(srctree)/$(boot)/ld.script \
+ $(images)/vmlinux.gz $(obj)/dummy.o
+ $(OBJCOPY) $(OBJCOPY_ARGS) \
+ --add-section=.image=$(images)/vmlinux.gz \
+ --set-section-flags=.image=contents,alloc,load,readonly,data \
+ $(obj)/dummy.o $(obj)/image.o
+ $(LD) $(LD_ARGS) -o $@ $(OBJS) $(obj)/image.o $(LIBS)
+ $(OBJCOPY) $(OBJCOPY_ARGS) $@ $@ -R .comment -R .stab \
+ -R .stabstr -R .ramdisk -R .sysmap
+
+$(obj)/zvmlinux.initrd: $(OBJS) $(LIBS) $(srctree)/$(boot)/ld.script \
+ $(images)/vmlinux.gz $(obj)/dummy.o
+ $(OBJCOPY) $(OBJCOPY_ARGS) \
+ --add-section=.ramdisk=$(images)/ramdisk.image.gz \
+ --set-section-flags=.ramdisk=contents,alloc,load,readonly,data \
+ --add-section=.image=$(images)/vmlinux.gz \
+ --set-section-flags=.image=contents,alloc,load,readonly,data \
+ $(obj)/dummy.o $(obj)/image.o
+ $(LD) $(LD_ARGS) -o $@ $(OBJS) $(obj)/image.o $(LIBS)
+ $(OBJCOPY) $(OBJCOPY_ARGS) $@ $@ -R .comment -R .stab \
+ -R .stabstr -R .sysmap
+
+# Sort-of dummy rules, that let us format the image we want.
+zImage: $(images)/$(zimage-y) $(obj)/zvmlinux
+ cp -f $(obj)/zvmlinux $(images)/zImage.elf
+ rm -f $(obj)/zvmlinux
+
+zImage.initrd: $(images)/$(zimageinitrd-y) $(obj)/zvmlinux.initrd
+ cp -f $(obj)/zvmlinux.initrd $(images)/zImage.initrd.elf
+ rm -f $(obj)/zvmlinux.initrd
+
+znetboot: zImage
+ cp $(images)/zImage.$(end-y) $(tftpboot)/zImage.$(end-y)
+
+znetboot.initrd: zImage.initrd
+ cp $(images)/zImage.initrd.$(end-y) $(tftpboot)/zImage.initrd.$(end-y)
+
+$(images)/zImage-STRIPELF: $(obj)/zvmlinux
+ dd if=$(obj)/zvmlinux of=$(images)/zImage.$(end-y) skip=64 bs=1k
+
+$(images)/zImage.initrd-STRIPELF: $(obj)/zvmlinux.initrd
+ dd if=$(obj)/zvmlinux.initrd of=$(images)/zImage.initrd.$(end-y) \
+ skip=64 bs=1k
+
+$(images)/zImage-TREE: $(obj)/zvmlinux $(MKTREE)
+ $(MKTREE) $(obj)/zvmlinux $(images)/zImage.$(end-y) $(ENTRYPOINT)
+
+$(images)/zImage.initrd-TREE: $(obj)/zvmlinux.initrd $(MKTREE)
+ $(MKTREE) $(obj)/zvmlinux.initrd $(images)/zImage.initrd.$(end-y) \
+ $(ENTRYPOINT)
+
+$(images)/zImage-PPLUS: $(obj)/zvmlinux $(MKPREP) $(MKBUGBOOT)
+ $(MKPREP) -pbp $(obj)/zvmlinux $(images)/zImage.$(end-y)
+ $(MKBUGBOOT) $(obj)/zvmlinux $(images)/zImage.bugboot
+
+$(images)/zImage.initrd-PPLUS: $(obj)/zvmlinux.initrd $(MKPREP) $(MKBUGBOOT)
+ $(MKPREP) -pbp $(obj)/zvmlinux.initrd $(images)/zImage.initrd.$(end-y)
+ $(MKBUGBOOT) $(obj)/zvmlinux.initrd $(images)/zImage.initrd.bugboot
diff --git a/arch/ppc/boot/simple/chrpmap.c b/arch/ppc/boot/simple/chrpmap.c
new file mode 100644
index 0000000..14d9e05
--- /dev/null
+++ b/arch/ppc/boot/simple/chrpmap.c
@@ -0,0 +1,12 @@
+/*
+ * 2004 (C) IBM. This file is licensed under the terms of the GNU General
+ * Public License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <nonstdio.h>
+
+void board_isa_init(void)
+{
+ ISA_init(0xFE000000);
+}
diff --git a/arch/ppc/boot/simple/clear.S b/arch/ppc/boot/simple/clear.S
new file mode 100644
index 0000000..95c5647
--- /dev/null
+++ b/arch/ppc/boot/simple/clear.S
@@ -0,0 +1,19 @@
+/*
+ * Code to call _setup_L2CR to flus, invalidate and disable the L2,
+ * and if present, do the same to the L3.
+ */
+
+#define CLEAR_CACHES \
+ bl _setup_L2CR; \
+ \
+ /* If 745x, turn off L3CR as well */ \
+ mfspr r8,SPRN_PVR; \
+ srwi r8,r8,16; \
+ \
+ cmpli cr0,r8,0x8000; /* 7450 */ \
+ cmpli cr1,r8,0x8001; /* 7455 */ \
+ cmpli cr2,r8,0x8002; /* 7457 */ \
+ /* Now test if any are true. */ \
+ cror 4*cr0+eq,4*cr0+eq,4*cr1+eq; \
+ cror 4*cr0+eq,4*cr0+eq,4*cr2+eq; \
+ beql _setup_L3CR
diff --git a/arch/ppc/boot/simple/cpc700_memory.c b/arch/ppc/boot/simple/cpc700_memory.c
new file mode 100644
index 0000000..8c75cf6
--- /dev/null
+++ b/arch/ppc/boot/simple/cpc700_memory.c
@@ -0,0 +1,36 @@
+/*
+ * arch/ppc/boot/common/cpc700_memory.c
+ *
+ * Find memory based upon settings in the CPC700 bridge
+ *
+ * Author: Dan Cox
+ *
+ * 2001-2002 (c) MontaVista, Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+
+#include <asm/types.h>
+#include <asm/io.h>
+#include "cpc700.h"
+
+unsigned long
+cpc700_get_mem_size(void)
+{
+ int i;
+ unsigned long len, amt;
+
+ /* Start at MB1EA, since MB0EA will most likely be the ending address
+ for ROM space. */
+ for(len = 0, i = CPC700_MB1EA; i <= CPC700_MB4EA; i+=4) {
+ amt = cpc700_read_memreg(i);
+ if (amt == 0)
+ break;
+ len = amt;
+ }
+
+ return len;
+}
+
+
diff --git a/arch/ppc/boot/simple/dummy.c b/arch/ppc/boot/simple/dummy.c
new file mode 100644
index 0000000..31dbf45
--- /dev/null
+++ b/arch/ppc/boot/simple/dummy.c
@@ -0,0 +1,4 @@
+int main(void)
+{
+ return 0;
+}
diff --git a/arch/ppc/boot/simple/embed_config.c b/arch/ppc/boot/simple/embed_config.c
new file mode 100644
index 0000000..c342b47
--- /dev/null
+++ b/arch/ppc/boot/simple/embed_config.c
@@ -0,0 +1,981 @@
+/* Board specific functions for those embedded 8xx boards that do
+ * not have boot monitor support for board information.
+ *
+ * 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.
+ */
+
+#include <linux/types.h>
+#include <linux/config.h>
+#include <linux/string.h>
+#include <asm/reg.h>
+#ifdef CONFIG_8xx
+#include <asm/mpc8xx.h>
+#endif
+#ifdef CONFIG_8260
+#include <asm/mpc8260.h>
+#include <asm/immap_cpm2.h>
+#endif
+#ifdef CONFIG_40x
+#include <asm/io.h>
+#endif
+extern unsigned long timebase_period_ns;
+
+/* For those boards that don't provide one.
+*/
+#if !defined(CONFIG_MBX)
+static bd_t bdinfo;
+#endif
+
+/* IIC functions.
+ * These are just the basic master read/write operations so we can
+ * examine serial EEPROM.
+ */
+extern void iic_read(uint devaddr, u_char *buf, uint offset, uint count);
+
+/* Supply a default Ethernet address for those eval boards that don't
+ * ship with one. This is an address from the MBX board I have, so
+ * it is unlikely you will find it on your network.
+ */
+static ushort def_enet_addr[] = { 0x0800, 0x3e26, 0x1559 };
+
+#if defined(CONFIG_MBX)
+
+/* The MBX hands us a pretty much ready to go board descriptor. This
+ * is where the idea started in the first place.
+ */
+void
+embed_config(bd_t **bdp)
+{
+ u_char *mp;
+ u_char eebuf[128];
+ int i = 8;
+ bd_t *bd;
+
+ bd = *bdp;
+
+ /* Read the first 128 bytes of the EEPROM. There is more,
+ * but this is all we need.
+ */
+ iic_read(0xa4, eebuf, 0, 128);
+
+ /* All we are looking for is the Ethernet MAC address. The
+ * first 8 bytes are 'MOTOROLA', so check for part of that.
+ * Next, the VPD describes a MAC 'packet' as being of type 08
+ * and size 06. So we look for that and the MAC must follow.
+ * If there are more than one, we still only care about the first.
+ * If it's there, assume we have a valid MAC address. If not,
+ * grab our default one.
+ */
+ if ((*(uint *)eebuf) == 0x4d4f544f) {
+ while (i < 127 && !(eebuf[i] == 0x08 && eebuf[i + 1] == 0x06))
+ i += eebuf[i + 1] + 2; /* skip this packet */
+
+ if (i == 127) /* Couldn't find. */
+ mp = (u_char *)def_enet_addr;
+ else
+ mp = &eebuf[i + 2];
+ }
+ else
+ mp = (u_char *)def_enet_addr;
+
+ for (i=0; i<6; i++)
+ bd->bi_enetaddr[i] = *mp++;
+
+ /* The boot rom passes these to us in MHz. Linux now expects
+ * them to be in Hz.
+ */
+ bd->bi_intfreq *= 1000000;
+ bd->bi_busfreq *= 1000000;
+
+ /* Stuff a baud rate here as well.
+ */
+ bd->bi_baudrate = 9600;
+}
+#endif /* CONFIG_MBX */
+
+#if defined(CONFIG_RPXLITE) || defined(CONFIG_RPXCLASSIC) || \
+ defined(CONFIG_RPX8260) || defined(CONFIG_EP405)
+/* Helper functions for Embedded Planet boards.
+*/
+/* Because I didn't find anything that would do this.......
+*/
+u_char
+aschex_to_byte(u_char *cp)
+{
+ u_char byte, c;
+
+ c = *cp++;
+
+ if ((c >= 'A') && (c <= 'F')) {
+ c -= 'A';
+ c += 10;
+ } else if ((c >= 'a') && (c <= 'f')) {
+ c -= 'a';
+ c += 10;
+ } else
+ c -= '0';
+
+ byte = c * 16;
+
+ c = *cp;
+
+ if ((c >= 'A') && (c <= 'F')) {
+ c -= 'A';
+ c += 10;
+ } else if ((c >= 'a') && (c <= 'f')) {
+ c -= 'a';
+ c += 10;
+ } else
+ c -= '0';
+
+ byte += c;
+
+ return(byte);
+}
+
+static void
+rpx_eth(bd_t *bd, u_char *cp)
+{
+ int i;
+
+ for (i=0; i<6; i++) {
+ bd->bi_enetaddr[i] = aschex_to_byte(cp);
+ cp += 2;
+ }
+}
+
+#ifdef CONFIG_RPX8260
+static uint
+rpx_baseten(u_char *cp)
+{
+ uint retval;
+
+ retval = 0;
+
+ while (*cp != '\n') {
+ retval *= 10;
+ retval += (*cp) - '0';
+ cp++;
+ }
+ return(retval);
+}
+#endif
+
+#if defined(CONFIG_RPXLITE) || defined(CONFIG_RPXCLASSIC)
+static void
+rpx_brate(bd_t *bd, u_char *cp)
+{
+ uint rate;
+
+ rate = 0;
+
+ while (*cp != '\n') {
+ rate *= 10;
+ rate += (*cp) - '0';
+ cp++;
+ }
+
+ bd->bi_baudrate = rate * 100;
+}
+
+static void
+rpx_cpuspeed(bd_t *bd, u_char *cp)
+{
+ uint num, den;
+
+ num = den = 0;
+
+ while (*cp != '\n') {
+ num *= 10;
+ num += (*cp) - '0';
+ cp++;
+ if (*cp == '/') {
+ cp++;
+ den = (*cp) - '0';
+ break;
+ }
+ }
+
+ /* I don't know why the RPX just can't state the actual
+ * CPU speed.....
+ */
+ if (den) {
+ num /= den;
+ num *= den;
+ }
+ bd->bi_intfreq = bd->bi_busfreq = num * 1000000;
+
+ /* The 8xx can only run a maximum 50 MHz bus speed (until
+ * Motorola changes this :-). Greater than 50 MHz parts
+ * run internal/2 for bus speed.
+ */
+ if (num > 50)
+ bd->bi_busfreq /= 2;
+}
+#endif
+
+#if defined(CONFIG_RPXLITE) || defined(CONFIG_RPXCLASSIC) || defined(CONFIG_EP405)
+static void
+rpx_memsize(bd_t *bd, u_char *cp)
+{
+ uint size;
+
+ size = 0;
+
+ while (*cp != '\n') {
+ size *= 10;
+ size += (*cp) - '0';
+ cp++;
+ }
+
+ bd->bi_memsize = size * 1024 * 1024;
+}
+#endif /* LITE || CLASSIC || EP405 */
+#if defined(CONFIG_EP405)
+static void
+rpx_nvramsize(bd_t *bd, u_char *cp)
+{
+ uint size;
+
+ size = 0;
+
+ while (*cp != '\n') {
+ size *= 10;
+ size += (*cp) - '0';
+ cp++;
+ }
+
+ bd->bi_nvramsize = size * 1024;
+}
+#endif /* CONFIG_EP405 */
+
+#endif /* Embedded Planet boards */
+
+#if defined(CONFIG_RPXLITE) || defined(CONFIG_RPXCLASSIC)
+
+/* Read the EEPROM on the RPX-Lite board.
+*/
+void
+embed_config(bd_t **bdp)
+{
+ u_char eebuf[256], *cp;
+ bd_t *bd;
+
+ /* Read the first 256 bytes of the EEPROM. I think this
+ * is really all there is, and I hope if it gets bigger the
+ * info we want is still up front.
+ */
+ bd = &bdinfo;
+ *bdp = bd;
+
+#if 1
+ iic_read(0xa8, eebuf, 0, 128);
+ iic_read(0xa8, &eebuf[128], 128, 128);
+
+ /* We look for two things, the Ethernet address and the
+ * serial baud rate. The records are separated by
+ * newlines.
+ */
+ cp = eebuf;
+ for (;;) {
+ if (*cp == 'E') {
+ cp++;
+ if (*cp == 'A') {
+ cp += 2;
+ rpx_eth(bd, cp);
+ }
+ }
+ if (*cp == 'S') {
+ cp++;
+ if (*cp == 'B') {
+ cp += 2;
+ rpx_brate(bd, cp);
+ }
+ }
+ if (*cp == 'D') {
+ cp++;
+ if (*cp == '1') {
+ cp += 2;
+ rpx_memsize(bd, cp);
+ }
+ }
+ if (*cp == 'H') {
+ cp++;
+ if (*cp == 'Z') {
+ cp += 2;
+ rpx_cpuspeed(bd, cp);
+ }
+ }
+
+ /* Scan to the end of the record.
+ */
+ while ((*cp != '\n') && (*cp != 0xff))
+ cp++;
+
+ /* If the next character is a 0 or ff, we are done.
+ */
+ cp++;
+ if ((*cp == 0) || (*cp == 0xff))
+ break;
+ }
+ bd->bi_memstart = 0;
+#else
+ /* For boards without initialized EEPROM.
+ */
+ bd->bi_memstart = 0;
+ bd->bi_memsize = (8 * 1024 * 1024);
+ bd->bi_intfreq = 48000000;
+ bd->bi_busfreq = 48000000;
+ bd->bi_baudrate = 9600;
+#endif
+}
+#endif /* RPXLITE || RPXCLASSIC */
+
+#ifdef CONFIG_BSEIP
+/* Build a board information structure for the BSE ip-Engine.
+ * There is more to come since we will add some environment
+ * variables and a function to read them.
+ */
+void
+embed_config(bd_t **bdp)
+{
+ u_char *cp;
+ int i;
+ bd_t *bd;
+
+ bd = &bdinfo;
+ *bdp = bd;
+
+ /* Baud rate and processor speed will eventually come
+ * from the environment variables.
+ */
+ bd->bi_baudrate = 9600;
+
+ /* Get the Ethernet station address from the Flash ROM.
+ */
+ cp = (u_char *)0xfe003ffa;
+ for (i=0; i<6; i++) {
+ bd->bi_enetaddr[i] = *cp++;
+ }
+
+ /* The rest of this should come from the environment as well.
+ */
+ bd->bi_memstart = 0;
+ bd->bi_memsize = (16 * 1024 * 1024);
+ bd->bi_intfreq = 48000000;
+ bd->bi_busfreq = 48000000;
+}
+#endif /* BSEIP */
+
+#ifdef CONFIG_FADS
+/* Build a board information structure for the FADS.
+ */
+void
+embed_config(bd_t **bdp)
+{
+ u_char *cp;
+ int i;
+ bd_t *bd;
+
+ bd = &bdinfo;
+ *bdp = bd;
+
+ /* Just fill in some known values.
+ */
+ bd->bi_baudrate = 9600;
+
+ /* Use default enet.
+ */
+ cp = (u_char *)def_enet_addr;
+ for (i=0; i<6; i++) {
+ bd->bi_enetaddr[i] = *cp++;
+ }
+
+ bd->bi_memstart = 0;
+ bd->bi_memsize = (8 * 1024 * 1024);
+ bd->bi_intfreq = 40000000;
+ bd->bi_busfreq = 40000000;
+}
+#endif /* FADS */
+
+#ifdef CONFIG_8260
+/* Compute 8260 clock values if the rom doesn't provide them.
+ */
+static unsigned char bus2core_8260[] = {
+/* 0 1 2 3 4 5 6 7 8 9 a b c d e f */
+ 3, 2, 2, 2, 4, 4, 5, 9, 6, 11, 8, 10, 3, 12, 7, 2,
+ 6, 5, 13, 2, 14, 4, 15, 2, 3, 11, 8, 10, 16, 12, 7, 2,
+};
+
+static void
+clk_8260(bd_t *bd)
+{
+ uint scmr, vco_out, clkin;
+ uint plldf, pllmf, corecnf;
+ volatile cpm2_map_t *ip;
+
+ ip = (cpm2_map_t *)CPM_MAP_ADDR;
+ scmr = ip->im_clkrst.car_scmr;
+
+ /* The clkin is always bus frequency.
+ */
+ clkin = bd->bi_busfreq;
+
+ /* Collect the bits from the scmr.
+ */
+ plldf = (scmr >> 12) & 1;
+ pllmf = scmr & 0xfff;
+ corecnf = (scmr >> 24) &0x1f;
+
+ /* This is arithmetic from the 8260 manual.
+ */
+ vco_out = clkin / (plldf + 1);
+ vco_out *= 2 * (pllmf + 1);
+ bd->bi_vco = vco_out; /* Save for later */
+
+ bd->bi_cpmfreq = vco_out / 2; /* CPM Freq, in MHz */
+ bd->bi_intfreq = bd->bi_busfreq * bus2core_8260[corecnf] / 2;
+
+ /* Set Baud rate divisor. The power up default is divide by 16,
+ * but we set it again here in case it was changed.
+ */
+ ip->im_clkrst.car_sccr = 1; /* DIV 16 BRG */
+ bd->bi_brgfreq = vco_out / 16;
+}
+
+static unsigned char bus2core_8280[] = {
+/* 0 1 2 3 4 5 6 7 8 9 a b c d e f */
+ 3, 2, 2, 2, 4, 4, 5, 9, 6, 11, 8, 10, 3, 12, 7, 2,
+ 6, 5, 13, 2, 14, 2, 15, 2, 3, 2, 2, 2, 16, 2, 2, 2,
+};
+
+static void
+clk_8280(bd_t *bd)
+{
+ uint scmr, main_clk, clkin;
+ uint pllmf, corecnf;
+ volatile cpm2_map_t *ip;
+
+ ip = (cpm2_map_t *)CPM_MAP_ADDR;
+ scmr = ip->im_clkrst.car_scmr;
+
+ /* The clkin is always bus frequency.
+ */
+ clkin = bd->bi_busfreq;
+
+ /* Collect the bits from the scmr.
+ */
+ pllmf = scmr & 0xf;
+ corecnf = (scmr >> 24) & 0x1f;
+
+ /* This is arithmetic from the 8280 manual.
+ */
+ main_clk = clkin * (pllmf + 1);
+
+ bd->bi_cpmfreq = main_clk / 2; /* CPM Freq, in MHz */
+ bd->bi_intfreq = bd->bi_busfreq * bus2core_8280[corecnf] / 2;
+
+ /* Set Baud rate divisor. The power up default is divide by 16,
+ * but we set it again here in case it was changed.
+ */
+ ip->im_clkrst.car_sccr = (ip->im_clkrst.car_sccr & 0x3) | 0x1;
+ bd->bi_brgfreq = main_clk / 16;
+}
+#endif
+
+#ifdef CONFIG_SBC82xx
+void
+embed_config(bd_t **bdp)
+{
+ u_char *cp;
+ int i;
+ bd_t *bd;
+ unsigned long pvr;
+
+ bd = *bdp;
+
+ bd = &bdinfo;
+ *bdp = bd;
+ bd->bi_baudrate = 9600;
+ bd->bi_memsize = 256 * 1024 * 1024; /* just a guess */
+
+ cp = (void*)SBC82xx_MACADDR_NVRAM_SCC1;
+ memcpy(bd->bi_enetaddr, cp, 6);
+
+ /* can busfreq be calculated? */
+ pvr = mfspr(SPRN_PVR);
+ if ((pvr & 0xffff0000) == 0x80820000) {
+ bd->bi_busfreq = 100000000;
+ clk_8280(bd);
+ } else {
+ bd->bi_busfreq = 66000000;
+ clk_8260(bd);
+ }
+
+}
+#endif /* SBC82xx */
+
+#if defined(CONFIG_EST8260) || defined(CONFIG_TQM8260)
+void
+embed_config(bd_t **bdp)
+{
+ u_char *cp;
+ int i;
+ bd_t *bd;
+
+ bd = *bdp;
+#if 0
+ /* This is actually provided by my boot rom. I have it
+ * here for those people that may load the kernel with
+ * a JTAG/COP tool and not the rom monitor.
+ */
+ bd->bi_baudrate = 115200;
+ bd->bi_intfreq = 200000000;
+ bd->bi_busfreq = 66666666;
+ bd->bi_cpmfreq = 66666666;
+ bd->bi_brgfreq = 33333333;
+ bd->bi_memsize = 16 * 1024 * 1024;
+#else
+ /* The boot rom passes these to us in MHz. Linux now expects
+ * them to be in Hz.
+ */
+ bd->bi_intfreq *= 1000000;
+ bd->bi_busfreq *= 1000000;
+ bd->bi_cpmfreq *= 1000000;
+ bd->bi_brgfreq *= 1000000;
+#endif
+
+ cp = (u_char *)def_enet_addr;
+ for (i=0; i<6; i++) {
+ bd->bi_enetaddr[i] = *cp++;
+ }
+}
+#endif /* EST8260 */
+
+#ifdef CONFIG_SBS8260
+void
+embed_config(bd_t **bdp)
+{
+ u_char *cp;
+ int i;
+ bd_t *bd;
+
+ /* This should provided by the boot rom.
+ */
+ bd = &bdinfo;
+ *bdp = bd;
+ bd->bi_baudrate = 9600;
+ bd->bi_memsize = 64 * 1024 * 1024;
+
+ /* Set all of the clocks. We have to know the speed of the
+ * external clock. The development board had 66 MHz.
+ */
+ bd->bi_busfreq = 66666666;
+ clk_8260(bd);
+
+ /* I don't know how to compute this yet.
+ */
+ bd->bi_intfreq = 133000000;
+
+
+ cp = (u_char *)def_enet_addr;
+ for (i=0; i<6; i++) {
+ bd->bi_enetaddr[i] = *cp++;
+ }
+}
+#endif /* SBS8260 */
+
+#ifdef CONFIG_RPX8260
+void
+embed_config(bd_t **bdp)
+{
+ u_char *cp, *keyvals;
+ int i;
+ bd_t *bd;
+
+ keyvals = (u_char *)*bdp;
+
+ bd = &bdinfo;
+ *bdp = bd;
+
+ /* This is almost identical to the RPX-Lite/Classic functions
+ * on the 8xx boards. It would be nice to have a key lookup
+ * function in a string, but the format of all of the fields
+ * is slightly different.
+ */
+ cp = keyvals;
+ for (;;) {
+ if (*cp == 'E') {
+ cp++;
+ if (*cp == 'A') {
+ cp += 2;
+ rpx_eth(bd, cp);
+ }
+ }
+ if (*cp == 'S') {
+ cp++;
+ if (*cp == 'B') {
+ cp += 2;
+ bd->bi_baudrate = rpx_baseten(cp);
+ }
+ }
+ if (*cp == 'D') {
+ cp++;
+ if (*cp == '1') {
+ cp += 2;
+ bd->bi_memsize = rpx_baseten(cp) * 1024 * 1024;
+ }
+ }
+ if (*cp == 'X') {
+ cp++;
+ if (*cp == 'T') {
+ cp += 2;
+ bd->bi_busfreq = rpx_baseten(cp);
+ }
+ }
+ if (*cp == 'N') {
+ cp++;
+ if (*cp == 'V') {
+ cp += 2;
+ bd->bi_nvsize = rpx_baseten(cp) * 1024 * 1024;
+ }
+ }
+
+ /* Scan to the end of the record.
+ */
+ while ((*cp != '\n') && (*cp != 0xff))
+ cp++;
+
+ /* If the next character is a 0 or ff, we are done.
+ */
+ cp++;
+ if ((*cp == 0) || (*cp == 0xff))
+ break;
+ }
+ bd->bi_memstart = 0;
+
+ /* The memory size includes both the 60x and local bus DRAM.
+ * I don't want to use the local bus DRAM for real memory,
+ * so subtract it out. It would be nice if they were separate
+ * keys.
+ */
+ bd->bi_memsize -= 32 * 1024 * 1024;
+
+ /* Set all of the clocks. We have to know the speed of the
+ * external clock.
+ */
+ clk_8260(bd);
+
+ /* I don't know how to compute this yet.
+ */
+ bd->bi_intfreq = 200000000;
+}
+#endif /* RPX6 for testing */
+
+#ifdef CONFIG_ADS8260
+void
+embed_config(bd_t **bdp)
+{
+ u_char *cp;
+ int i;
+ bd_t *bd;
+
+ /* This should provided by the boot rom.
+ */
+ bd = &bdinfo;
+ *bdp = bd;
+ bd->bi_baudrate = 9600;
+ bd->bi_memsize = 16 * 1024 * 1024;
+
+ /* Set all of the clocks. We have to know the speed of the
+ * external clock. The development board had 66 MHz.
+ */
+ bd->bi_busfreq = 66666666;
+ clk_8260(bd);
+
+ /* I don't know how to compute this yet.
+ */
+ bd->bi_intfreq = 200000000;
+
+
+ cp = (u_char *)def_enet_addr;
+ for (i=0; i<6; i++) {
+ bd->bi_enetaddr[i] = *cp++;
+ }
+}
+#endif /* ADS8260 */
+
+#ifdef CONFIG_WILLOW
+void
+embed_config(bd_t **bdp)
+{
+ u_char *cp;
+ int i;
+ bd_t *bd;
+
+ /* Willow has Open Firmware....I should learn how to get this
+ * information from it.
+ */
+ bd = &bdinfo;
+ *bdp = bd;
+ bd->bi_baudrate = 9600;
+ bd->bi_memsize = 32 * 1024 * 1024;
+
+ /* Set all of the clocks. We have to know the speed of the
+ * external clock. The development board had 66 MHz.
+ */
+ bd->bi_busfreq = 66666666;
+ clk_8260(bd);
+
+ /* I don't know how to compute this yet.
+ */
+ bd->bi_intfreq = 200000000;
+
+
+ cp = (u_char *)def_enet_addr;
+ for (i=0; i<6; i++) {
+ bd->bi_enetaddr[i] = *cp++;
+ }
+}
+#endif /* WILLOW */
+
+#ifdef CONFIG_XILINX_ML300
+void
+embed_config(bd_t ** bdp)
+{
+ static const unsigned long line_size = 32;
+ static const unsigned long congruence_classes = 256;
+ unsigned long addr;
+ unsigned long dccr;
+ bd_t *bd;
+
+ /*
+ * Invalidate the data cache if the data cache is turned off.
+ * - The 405 core does not invalidate the data cache on power-up
+ * or reset but does turn off the data cache. We cannot assume
+ * that the cache contents are valid.
+ * - If the data cache is turned on this must have been done by
+ * a bootloader and we assume that the cache contents are
+ * valid.
+ */
+ __asm__("mfdccr %0": "=r" (dccr));
+ if (dccr == 0) {
+ for (addr = 0;
+ addr < (congruence_classes * line_size);
+ addr += line_size) {
+ __asm__("dccci 0,%0": :"b"(addr));
+ }
+ }
+
+ bd = &bdinfo;
+ *bdp = bd;
+ bd->bi_memsize = XPAR_DDR_0_SIZE;
+ bd->bi_intfreq = XPAR_CORE_CLOCK_FREQ_HZ;
+ bd->bi_busfreq = XPAR_PLB_CLOCK_FREQ_HZ;
+ bd->bi_pci_busfreq = XPAR_PCI_0_CLOCK_FREQ_HZ;
+ timebase_period_ns = 1000000000 / bd->bi_tbfreq;
+ /* see bi_tbfreq definition in arch/ppc/platforms/4xx/xilinx_ml300.h */
+}
+#endif /* CONFIG_XILINX_ML300 */
+
+#ifdef CONFIG_IBM_OPENBIOS
+/* This could possibly work for all treeboot roms.
+*/
+#if defined(CONFIG_ASH) || defined(CONFIG_BEECH) || defined(CONFIG_BUBINGA)
+#define BOARD_INFO_VECTOR 0xFFF80B50 /* openbios 1.19 moved this vector down - armin */
+#else
+#define BOARD_INFO_VECTOR 0xFFFE0B50
+#endif
+
+#ifdef CONFIG_BEECH
+static void
+get_board_info(bd_t **bdp)
+{
+ typedef void (*PFV)(bd_t *bd);
+ ((PFV)(*(unsigned long *)BOARD_INFO_VECTOR))(*bdp);
+ return;
+}
+
+void
+embed_config(bd_t **bdp)
+{
+ *bdp = &bdinfo;
+ get_board_info(bdp);
+}
+#else /* !CONFIG_BEECH */
+void
+embed_config(bd_t **bdp)
+{
+ u_char *cp;
+ int i;
+ bd_t *bd, *treeboot_bd;
+ bd_t *(*get_board_info)(void) =
+ (bd_t *(*)(void))(*(unsigned long *)BOARD_INFO_VECTOR);
+#if !defined(CONFIG_STB03xxx)
+
+ /* shut down the Ethernet controller that the boot rom
+ * sometimes leaves running.
+ */
+ mtdcr(DCRN_MALCR(DCRN_MAL_BASE), MALCR_MMSR); /* 1st reset MAL */
+ while (mfdcr(DCRN_MALCR(DCRN_MAL_BASE)) & MALCR_MMSR) {}; /* wait for the reset */
+ out_be32((volatile u32*)EMAC0_BASE,0x20000000); /* then reset EMAC */
+#endif
+
+ bd = &bdinfo;
+ *bdp = bd;
+ if ((treeboot_bd = get_board_info()) != NULL) {
+ memcpy(bd, treeboot_bd, sizeof(bd_t));
+ }
+ else {
+ /* Hmmm...better try to stuff some defaults.
+ */
+ bd->bi_memsize = 16 * 1024 * 1024;
+ cp = (u_char *)def_enet_addr;
+ for (i=0; i<6; i++) {
+ /* I should probably put different ones here,
+ * hopefully only one is used.
+ */
+ bd->BD_EMAC_ADDR(0,i) = *cp;
+
+#ifdef CONFIG_PCI
+ bd->bi_pci_enetaddr[i] = *cp++;
+#endif
+ }
+ bd->bi_tbfreq = 200 * 1000 * 1000;
+ bd->bi_intfreq = 200000000;
+ bd->bi_busfreq = 100000000;
+#ifdef CONFIG_PCI
+ bd->bi_pci_busfreq = 66666666;
+#endif
+ }
+ /* Yeah, this look weird, but on Redwood 4 they are
+ * different object in the structure. Sincr Redwwood 5
+ * and Redwood 6 use OpenBIOS, it requires a special value.
+ */
+#if defined(CONFIG_REDWOOD_5) || defined (CONFIG_REDWOOD_6)
+ bd->bi_tbfreq = 27 * 1000 * 1000;
+#endif
+ timebase_period_ns = 1000000000 / bd->bi_tbfreq;
+}
+#endif /* CONFIG_BEECH */
+#endif /* CONFIG_IBM_OPENBIOS */
+
+#ifdef CONFIG_EP405
+#include <linux/serial_reg.h>
+
+void
+embed_config(bd_t **bdp)
+{
+ u32 chcr0;
+ u_char *cp;
+ bd_t *bd;
+
+ /* Different versions of the PlanetCore firmware vary in how
+ they set up the serial port - in particular whether they
+ use the internal or external serial clock for UART0. Make
+ sure the UART is in a known state. */
+ /* FIXME: We should use the board's 11.0592MHz external serial
+ clock - it will be more accurate for serial rates. For
+ now, however the baud rates in ep405.h are for the internal
+ clock. */
+ chcr0 = mfdcr(DCRN_CHCR0);
+ if ( (chcr0 & 0x1fff) != 0x103e ) {
+ mtdcr(DCRN_CHCR0, (chcr0 & 0xffffe000) | 0x103e);
+ /* The following tricks serial_init() into resetting the baud rate */
+ writeb(0, UART0_IO_BASE + UART_LCR);
+ }
+
+ /* We haven't seen actual problems with the EP405 leaving the
+ * EMAC running (as we have on Walnut). But the registers
+ * suggest it may not be left completely quiescent. Reset it
+ * just to be sure. */
+ mtdcr(DCRN_MALCR(DCRN_MAL_BASE), MALCR_MMSR); /* 1st reset MAL */
+ while (mfdcr(DCRN_MALCR(DCRN_MAL_BASE)) & MALCR_MMSR) {}; /* wait for the reset */
+ out_be32((unsigned *)EMAC0_BASE,0x20000000); /* then reset EMAC */
+
+ bd = &bdinfo;
+ *bdp = bd;
+#if 1
+ cp = (u_char *)0xF0000EE0;
+ for (;;) {
+ if (*cp == 'E') {
+ cp++;
+ if (*cp == 'A') {
+ cp += 2;
+ rpx_eth(bd, cp);
+ }
+ }
+
+ if (*cp == 'D') {
+ cp++;
+ if (*cp == '1') {
+ cp += 2;
+ rpx_memsize(bd, cp);
+ }
+ }
+
+ if (*cp == 'N') {
+ cp++;
+ if (*cp == 'V') {
+ cp += 2;
+ rpx_nvramsize(bd, cp);
+ }
+ }
+ while ((*cp != '\n') && (*cp != 0xff))
+ cp++;
+
+ cp++;
+ if ((*cp == 0) || (*cp == 0xff))
+ break;
+ }
+ bd->bi_intfreq = 200000000;
+ bd->bi_busfreq = 100000000;
+ bd->bi_pci_busfreq= 33000000 ;
+#else
+
+ bd->bi_memsize = 64000000;
+ bd->bi_intfreq = 200000000;
+ bd->bi_busfreq = 100000000;
+ bd->bi_pci_busfreq= 33000000 ;
+#endif
+}
+#endif
+
+#ifdef CONFIG_RAINIER
+/* Rainier uses vxworks bootrom */
+void
+embed_config(bd_t **bdp)
+{
+ u_char *cp;
+ int i;
+ bd_t *bd;
+
+ bd = &bdinfo;
+ *bdp = bd;
+
+ for(i=0;i<8192;i+=32) {
+ __asm__("dccci 0,%0" :: "r" (i));
+ }
+ __asm__("iccci 0,0");
+ __asm__("sync;isync");
+
+ /* init ram for parity */
+ memset(0, 0,0x400000); /* Lo memory */
+
+
+ bd->bi_memsize = (32 * 1024 * 1024) ;
+ bd->bi_intfreq = 133000000; //the internal clock is 133 MHz
+ bd->bi_busfreq = 100000000;
+ bd->bi_pci_busfreq= 33000000;
+
+ cp = (u_char *)def_enet_addr;
+ for (i=0; i<6; i++) {
+ bd->bi_enetaddr[i] = *cp++;
+ }
+
+}
+#endif
+
diff --git a/arch/ppc/boot/simple/head.S b/arch/ppc/boot/simple/head.S
new file mode 100644
index 0000000..5240532
--- /dev/null
+++ b/arch/ppc/boot/simple/head.S
@@ -0,0 +1,142 @@
+/*
+ * arch/ppc/boot/simple/head.S
+ *
+ * Initial board bringup code for many different boards.
+ *
+ * Author: Tom Rini
+ * trini@mvista.com
+ * Derived from arch/ppc/boot/prep/head.S (Cort Dougan, many others).
+ *
+ * 2001-2004 (c) MontaVista, Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+
+#include <linux/config.h>
+#include <asm/reg.h>
+#include <asm/cache.h>
+#include <asm/ppc_asm.h>
+
+ .text
+
+/*
+ * Begin at some arbitrary location in RAM or Flash
+ * Initialize core registers
+ * Configure memory controller (Not executing from RAM)
+ * Move the boot code to the link address (8M)
+ * Setup C stack
+ * Initialize UART
+ * Decompress the kernel to 0x0
+ * Jump to the kernel entry
+ *
+ */
+
+ .globl start
+start:
+ bl start_
+#ifdef CONFIG_IBM_OPENBIOS
+ /* The IBM "Tree" bootrom knows that the address of the bootrom
+ * read only structure is 4 bytes after _start.
+ */
+ .long 0x62726f6d # structure ID - "brom"
+ .long 0x5f726f00 # - "_ro\0"
+ .long 1 # structure version
+ .long bootrom_cmdline # address of *bootrom_cmdline
+#endif
+
+start_:
+#ifdef CONFIG_FORCE
+ /* We have some really bad firmware. We must disable the L1
+ * icache/dcache now or the board won't boot.
+ */
+ li r4,0x0000
+ isync
+ mtspr SPRN_HID0,r4
+ sync
+ isync
+#endif
+
+#if defined(CONFIG_MBX) || defined(CONFIG_RPX8260) || defined(CONFIG_PPC_PREP)
+ mr r29,r3 /* On the MBX860, r3 is the board info pointer.
+ * On the RPXSUPER, r3 points to the NVRAM
+ * configuration keys.
+ * On PReP, r3 is the pointer to the residual data.
+ */
+#endif
+
+ mflr r3 /* Save our actual starting address. */
+
+ /* The following functions we call must not modify r3 or r4.....
+ */
+#ifdef CONFIG_6xx
+ /* On PReP we must look at the OpenFirmware pointer and sanity
+ * test it. On other platforms, we disable the MMU right now
+ * and other bits.
+ */
+#ifdef CONFIG_PPC_PREP
+/*
+ * Save the OF pointer to r25, but only if the entry point is in a sane
+ * location; if not we store 0. If there is no entry point, or it is
+ * invalid, we establish the default MSR value immediately. Otherwise,
+ * we defer doing that, to allow OF functions to be called, until we
+ * begin uncompressing the kernel.
+ */
+ lis r8,0x0fff /* r8 = 0x0fffffff */
+ ori r8,r8,0xffff
+
+ subc r8,r8,r5 /* r8 = (r5 <= r8) ? ~0 : 0 */
+ subfe r8,r8,r8
+ nand r8,r8,r8
+
+ and. r5,r5,r8 /* r5 will be cleared if (r5 > r8) */
+ bne+ haveOF
+
+ li r8,MSR_IP|MSR_FP /* Not OF: set MSR immediately */
+ mtmsr r8
+ isync
+haveOF:
+ mr r25,r5
+#else
+ bl disable_6xx_mmu
+#endif
+ bl disable_6xx_l1cache
+
+ CLEAR_CACHES
+#endif
+
+#ifdef CONFIG_8xx
+ mfmsr r8 /* Turn off interrupts */
+ li r9,0
+ ori r9,r9,MSR_EE
+ andc r8,r8,r9
+ mtmsr r8
+
+ /* We do this because some boot roms don't initialize the
+ * processor correctly. Don't do this if you want to debug
+ * using a BDM device.
+ */
+ li r4,0 /* Zero DER to prevent FRZ */
+ mtspr SPRN_DER,r4
+#endif
+
+#ifdef CONFIG_REDWOOD_4
+ /* All of this Redwood 4 stuff will soon disappear when the
+ * boot rom is straightened out.
+ */
+ mr r29, r3 /* Easier than changing the other code */
+ bl HdwInit
+ mr r3, r29
+#endif
+
+#if defined(CONFIG_MBX) || defined(CONFIG_RPX8260) || defined(CONFIG_PPC_PREP)
+ mr r4,r29 /* put the board info pointer where the relocate
+ * routine will find it
+ */
+#endif
+
+ /* Get the load address.
+ */
+ subi r3, r3, 4 /* Get the actual IP, not NIP */
+ b relocate
+
diff --git a/arch/ppc/boot/simple/iic.c b/arch/ppc/boot/simple/iic.c
new file mode 100644
index 0000000..e4efd83
--- /dev/null
+++ b/arch/ppc/boot/simple/iic.c
@@ -0,0 +1,214 @@
+/* Minimal support functions to read configuration from IIC EEPROMS
+ * on MPC8xx boards. Originally written for RPGC RPX-Lite.
+ * Dan Malek (dmalek@jlc.net).
+ */
+#include <linux/types.h>
+#include <asm/uaccess.h>
+#include <asm/mpc8xx.h>
+#include <asm/commproc.h>
+
+
+/* IIC functions.
+ * These are just the basic master read/write operations so we can
+ * examine serial EEPROM.
+ */
+void iic_read(uint devaddr, u_char *buf, uint offset, uint count);
+
+static int iic_init_done;
+
+static void
+iic_init(void)
+{
+ volatile iic_t *iip;
+ volatile i2c8xx_t *i2c;
+ volatile cpm8xx_t *cp;
+ volatile immap_t *immap;
+ uint dpaddr;
+
+ immap = (immap_t *)IMAP_ADDR;
+ cp = (cpm8xx_t *)&(immap->im_cpm);
+
+ /* Reset the CPM. This is necessary on the 860 processors
+ * that may have started the SCC1 ethernet without relocating
+ * the IIC.
+ * This also stops the Ethernet in case we were loaded by a
+ * BOOTP rom monitor.
+ */
+ cp->cp_cpcr = (CPM_CR_RST | CPM_CR_FLG);
+
+ /* Wait for it.
+ */
+ while (cp->cp_cpcr & (CPM_CR_RST | CPM_CR_FLG));
+
+ /* Remove any microcode patches. We will install our own
+ * later.
+ */
+ cp->cp_cpmcr1 = 0;
+ cp->cp_cpmcr2 = 0;
+ cp->cp_cpmcr3 = 0;
+ cp->cp_cpmcr4 = 0;
+ cp->cp_rccr = 0;
+
+ iip = (iic_t *)&cp->cp_dparam[PROFF_IIC];
+ i2c = (i2c8xx_t *)&(immap->im_i2c);
+
+ /* Initialize Port B IIC pins.
+ */
+ cp->cp_pbpar |= 0x00000030;
+ cp->cp_pbdir |= 0x00000030;
+ cp->cp_pbodr |= 0x00000030;
+
+ /* Initialize the parameter ram.
+ */
+
+ /* Allocate space for a two transmit and one receive buffer
+ * descriptor in the DP ram.
+ * For now, this address seems OK, but it may have to
+ * change with newer versions of the firmware.
+ */
+ dpaddr = 0x0840;
+
+ /* Set up the IIC parameters in the parameter ram.
+ */
+ iip->iic_tbase = dpaddr;
+ iip->iic_rbase = dpaddr + (2 * sizeof(cbd_t));
+
+ iip->iic_tfcr = SMC_EB;
+ iip->iic_rfcr = SMC_EB;
+
+ /* This should really be done by the reader/writer.
+ */
+ iip->iic_mrblr = 128;
+
+ /* Initialize Tx/Rx parameters.
+ */
+ cp->cp_cpcr = mk_cr_cmd(CPM_CR_CH_I2C, CPM_CR_INIT_TRX) | CPM_CR_FLG;
+ while (cp->cp_cpcr & CPM_CR_FLG);
+
+ /* Select an arbitrary address. Just make sure it is unique.
+ */
+ i2c->i2c_i2add = 0x34;
+
+ /* Make clock run maximum slow.
+ */
+ i2c->i2c_i2brg = 7;
+
+ /* Disable interrupts.
+ */
+ i2c->i2c_i2cmr = 0;
+ i2c->i2c_i2cer = 0xff;
+
+ /* Enable SDMA.
+ */
+ immap->im_siu_conf.sc_sdcr = 1;
+
+ iic_init_done = 1;
+}
+
+/* Read from IIC.
+ * Caller provides device address, memory buffer, and byte count.
+ */
+static u_char iitemp[32];
+
+void
+iic_read(uint devaddr, u_char *buf, uint offset, uint count)
+{
+ volatile iic_t *iip;
+ volatile i2c8xx_t *i2c;
+ volatile cbd_t *tbdf, *rbdf;
+ volatile cpm8xx_t *cp;
+ volatile immap_t *immap;
+ u_char *tb;
+ uint temp;
+
+ /* If the interface has not been initialized, do that now.
+ */
+ if (!iic_init_done)
+ iic_init();
+
+ immap = (immap_t *)IMAP_ADDR;
+ cp = (cpm8xx_t *)&(immap->im_cpm);
+
+ iip = (iic_t *)&cp->cp_dparam[PROFF_IIC];
+ i2c = (i2c8xx_t *)&(immap->im_i2c);
+
+ tbdf = (cbd_t *)&cp->cp_dpmem[iip->iic_tbase];
+ rbdf = (cbd_t *)&cp->cp_dpmem[iip->iic_rbase];
+
+ /* Send a "dummy write" operation. This is a write request with
+ * only the offset sent, followed by another start condition.
+ * This will ensure we start reading from the first location
+ * of the EEPROM.
+ */
+ tb = iitemp;
+ tb = (u_char *)(((uint)tb + 15) & ~15);
+ tbdf->cbd_bufaddr = (int)tb;
+ *tb = devaddr & 0xfe; /* Device address */
+ *(tb+1) = offset; /* Offset */
+ tbdf->cbd_datlen = 2; /* Length */
+ tbdf->cbd_sc =
+ BD_SC_READY | BD_SC_LAST | BD_SC_WRAP | BD_IIC_START;
+
+ i2c->i2c_i2mod = 1; /* Enable */
+ i2c->i2c_i2cer = 0xff;
+ i2c->i2c_i2com = 0x81; /* Start master */
+
+ /* Wait for IIC transfer.
+ */
+#if 0
+ while ((i2c->i2c_i2cer & 3) == 0);
+
+ if (tbdf->cbd_sc & BD_SC_READY)
+ printf("IIC ra complete but tbuf ready\n");
+#else
+ temp = 10000000;
+ while ((tbdf->cbd_sc & BD_SC_READY) && (temp != 0))
+ temp--;
+#if 0
+ /* We can't do this...there is no serial port yet!
+ */
+ if (temp == 0) {
+ printf("Timeout reading EEPROM\n");
+ return;
+ }
+#endif
+#endif
+
+ /* Chip errata, clear enable.
+ */
+ i2c->i2c_i2mod = 0;
+
+ /* To read, we need an empty buffer of the proper length.
+ * All that is used is the first byte for address, the remainder
+ * is just used for timing (and doesn't really have to exist).
+ */
+ tbdf->cbd_bufaddr = (int)tb;
+ *tb = devaddr | 1; /* Device address */
+ rbdf->cbd_bufaddr = (uint)buf; /* Desination buffer */
+ tbdf->cbd_datlen = rbdf->cbd_datlen = count + 1; /* Length */
+ tbdf->cbd_sc = BD_SC_READY | BD_SC_LAST | BD_SC_WRAP | BD_IIC_START;
+ rbdf->cbd_sc = BD_SC_EMPTY | BD_SC_WRAP;
+
+ /* Chip bug, set enable here.
+ */
+ i2c->i2c_i2mod = 1; /* Enable */
+ i2c->i2c_i2cer = 0xff;
+ i2c->i2c_i2com = 0x81; /* Start master */
+
+ /* Wait for IIC transfer.
+ */
+#if 0
+ while ((i2c->i2c_i2cer & 1) == 0);
+
+ if (rbdf->cbd_sc & BD_SC_EMPTY)
+ printf("IIC read complete but rbuf empty\n");
+#else
+ temp = 10000000;
+ while ((tbdf->cbd_sc & BD_SC_READY) && (temp != 0))
+ temp--;
+#endif
+
+ /* Chip errata, clear enable.
+ */
+ i2c->i2c_i2mod = 0;
+}
diff --git a/arch/ppc/boot/simple/m8260_tty.c b/arch/ppc/boot/simple/m8260_tty.c
new file mode 100644
index 0000000..d770947
--- /dev/null
+++ b/arch/ppc/boot/simple/m8260_tty.c
@@ -0,0 +1,325 @@
+/* Minimal serial functions needed to send messages out the serial
+ * port on SMC1.
+ */
+#include <linux/types.h>
+#include <asm/mpc8260.h>
+#include <asm/cpm2.h>
+#include <asm/immap_cpm2.h>
+
+uint no_print;
+extern char *params[];
+extern int nparams;
+static u_char cons_hold[128], *sgptr;
+static int cons_hold_cnt;
+
+/* If defined, enables serial console. The value (1 through 4)
+ * should designate which SCC is used, but this isn't complete. Only
+ * SCC1 is known to work at this time.
+ * We're only linked if SERIAL_CPM_CONSOLE=y, so we only need to test
+ * SERIAL_CPM_SCC1.
+ */
+#ifdef CONFIG_SERIAL_CPM_SCC1
+#define SCC_CONSOLE 1
+#endif
+
+unsigned long
+serial_init(int ignored, bd_t *bd)
+{
+#ifdef SCC_CONSOLE
+ volatile scc_t *sccp;
+ volatile scc_uart_t *sup;
+#else
+ volatile smc_t *sp;
+ volatile smc_uart_t *up;
+#endif
+ volatile cbd_t *tbdf, *rbdf;
+ volatile cpm2_map_t *ip;
+ volatile iop_cpm2_t *io;
+ volatile cpm_cpm2_t *cp;
+ uint dpaddr, memaddr;
+
+ ip = (cpm2_map_t *)CPM_MAP_ADDR;
+ cp = &ip->im_cpm;
+ io = &ip->im_ioport;
+
+ /* Perform a reset.
+ */
+ cp->cp_cpcr = (CPM_CR_RST | CPM_CR_FLG);
+
+ /* Wait for it.
+ */
+ while (cp->cp_cpcr & CPM_CR_FLG);
+
+#ifdef CONFIG_ADS8260
+ /* Enable the RS-232 transceivers.
+ */
+ *(volatile uint *)(BCSR_ADDR + 4) &=
+ ~(BCSR1_RS232_EN1 | BCSR1_RS232_EN2);
+#endif
+
+#ifdef SCC_CONSOLE
+ sccp = (scc_t *)&(ip->im_scc[SCC_CONSOLE-1]);
+ sup = (scc_uart_t *)&ip->im_dprambase[PROFF_SCC1 + ((SCC_CONSOLE-1) << 8)];
+ sccp->scc_sccm &= ~(UART_SCCM_TX | UART_SCCM_RX);
+ sccp->scc_gsmrl &= ~(SCC_GSMRL_ENR | SCC_GSMRL_ENT);
+
+ /* Use Port D for SCC1 instead of other functions.
+ */
+ io->iop_ppard |= 0x00000003;
+ io->iop_psord &= ~0x00000001; /* Rx */
+ io->iop_psord |= 0x00000002; /* Tx */
+ io->iop_pdird &= ~0x00000001; /* Rx */
+ io->iop_pdird |= 0x00000002; /* Tx */
+
+#else
+ sp = (smc_t*)&(ip->im_smc[0]);
+ *(ushort *)(&ip->im_dprambase[PROFF_SMC1_BASE]) = PROFF_SMC1;
+ up = (smc_uart_t *)&ip->im_dprambase[PROFF_SMC1];
+
+ /* Disable transmitter/receiver.
+ */
+ sp->smc_smcmr &= ~(SMCMR_REN | SMCMR_TEN);
+
+ /* Use Port D for SMC1 instead of other functions.
+ */
+ io->iop_ppard |= 0x00c00000;
+ io->iop_pdird |= 0x00400000;
+ io->iop_pdird &= ~0x00800000;
+ io->iop_psord &= ~0x00c00000;
+#endif
+
+ /* Allocate space for two buffer descriptors in the DP ram.
+ * For now, this address seems OK, but it may have to
+ * change with newer versions of the firmware.
+ */
+ dpaddr = 0x0800;
+
+ /* Grab a few bytes from the top of memory.
+ */
+ memaddr = (bd->bi_memsize - 256) & ~15;
+
+ /* Set the physical address of the host memory buffers in
+ * the buffer descriptors.
+ */
+ rbdf = (cbd_t *)&ip->im_dprambase[dpaddr];
+ rbdf->cbd_bufaddr = memaddr;
+ rbdf->cbd_sc = 0;
+ tbdf = rbdf + 1;
+ tbdf->cbd_bufaddr = memaddr+128;
+ tbdf->cbd_sc = 0;
+
+ /* Set up the uart parameters in the parameter ram.
+ */
+#ifdef SCC_CONSOLE
+ sup->scc_genscc.scc_rbase = dpaddr;
+ sup->scc_genscc.scc_tbase = dpaddr + sizeof(cbd_t);
+
+ /* Set up the uart parameters in the
+ * parameter ram.
+ */
+ sup->scc_genscc.scc_rfcr = CPMFCR_GBL | CPMFCR_EB;
+ sup->scc_genscc.scc_tfcr = CPMFCR_GBL | CPMFCR_EB;
+
+ sup->scc_genscc.scc_mrblr = 128;
+ sup->scc_maxidl = 8;
+ sup->scc_brkcr = 1;
+ sup->scc_parec = 0;
+ sup->scc_frmec = 0;
+ sup->scc_nosec = 0;
+ sup->scc_brkec = 0;
+ sup->scc_uaddr1 = 0;
+ sup->scc_uaddr2 = 0;
+ sup->scc_toseq = 0;
+ sup->scc_char1 = 0x8000;
+ sup->scc_char2 = 0x8000;
+ sup->scc_char3 = 0x8000;
+ sup->scc_char4 = 0x8000;
+ sup->scc_char5 = 0x8000;
+ sup->scc_char6 = 0x8000;
+ sup->scc_char7 = 0x8000;
+ sup->scc_char8 = 0x8000;
+ sup->scc_rccm = 0xc0ff;
+
+ /* Send the CPM an initialize command.
+ */
+ cp->cp_cpcr = mk_cr_cmd(CPM_CR_SCC1_PAGE, CPM_CR_SCC1_SBLOCK, 0,
+ CPM_CR_INIT_TRX) | CPM_CR_FLG;
+ while (cp->cp_cpcr & CPM_CR_FLG);
+
+ /* Set UART mode, 8 bit, no parity, one stop.
+ * Enable receive and transmit.
+ */
+ sccp->scc_gsmrh = 0;
+ sccp->scc_gsmrl =
+ (SCC_GSMRL_MODE_UART | SCC_GSMRL_TDCR_16 | SCC_GSMRL_RDCR_16);
+
+ /* Disable all interrupts and clear all pending
+ * events.
+ */
+ sccp->scc_sccm = 0;
+ sccp->scc_scce = 0xffff;
+ sccp->scc_dsr = 0x7e7e;
+ sccp->scc_psmr = 0x3000;
+
+ /* Wire BRG1 to SCC1. The console driver will take care of
+ * others.
+ */
+ ip->im_cpmux.cmx_scr = 0;
+#else
+ up->smc_rbase = dpaddr;
+ up->smc_tbase = dpaddr+sizeof(cbd_t);
+ up->smc_rfcr = CPMFCR_EB;
+ up->smc_tfcr = CPMFCR_EB;
+ up->smc_brklen = 0;
+ up->smc_brkec = 0;
+ up->smc_brkcr = 0;
+ up->smc_mrblr = 128;
+ up->smc_maxidl = 8;
+
+ /* Set UART mode, 8 bit, no parity, one stop.
+ * Enable receive and transmit.
+ */
+ sp->smc_smcmr = smcr_mk_clen(9) | SMCMR_SM_UART;
+
+ /* Mask all interrupts and remove anything pending.
+ */
+ sp->smc_smcm = 0;
+ sp->smc_smce = 0xff;
+
+ /* Set up the baud rate generator.
+ */
+ ip->im_cpmux.cmx_smr = 0;
+#endif
+
+ /* The baud rate divisor needs to be coordinated with clk_8260().
+ */
+ ip->im_brgc1 =
+ (((bd->bi_brgfreq/16) / bd->bi_baudrate) << 1) |
+ CPM_BRG_EN;
+
+ /* Make the first buffer the only buffer.
+ */
+ tbdf->cbd_sc |= BD_SC_WRAP;
+ rbdf->cbd_sc |= BD_SC_EMPTY | BD_SC_WRAP;
+
+ /* Initialize Tx/Rx parameters.
+ */
+#ifdef SCC_CONSOLE
+ sccp->scc_gsmrl |= (SCC_GSMRL_ENR | SCC_GSMRL_ENT);
+#else
+ cp->cp_cpcr = mk_cr_cmd(CPM_CR_SMC1_PAGE, CPM_CR_SMC1_SBLOCK, 0, CPM_CR_INIT_TRX) | CPM_CR_FLG;
+ while (cp->cp_cpcr & CPM_CR_FLG);
+
+ /* Enable transmitter/receiver.
+ */
+ sp->smc_smcmr |= SMCMR_REN | SMCMR_TEN;
+#endif
+
+ /* This is ignored.
+ */
+ return 0;
+}
+
+int
+serial_readbuf(u_char *cbuf)
+{
+ volatile cbd_t *rbdf;
+ volatile char *buf;
+#ifdef SCC_CONSOLE
+ volatile scc_uart_t *sup;
+#else
+ volatile smc_uart_t *up;
+#endif
+ volatile cpm2_map_t *ip;
+ int i, nc;
+
+ ip = (cpm2_map_t *)CPM_MAP_ADDR;
+
+#ifdef SCC_CONSOLE
+ sup = (scc_uart_t *)&ip->im_dprambase[PROFF_SCC1 + ((SCC_CONSOLE-1) << 8)];
+ rbdf = (cbd_t *)&ip->im_dprambase[sup->scc_genscc.scc_rbase];
+#else
+ up = (smc_uart_t *)&(ip->im_dprambase[PROFF_SMC1]);
+ rbdf = (cbd_t *)&ip->im_dprambase[up->smc_rbase];
+#endif
+
+ /* Wait for character to show up.
+ */
+ buf = (char *)rbdf->cbd_bufaddr;
+ while (rbdf->cbd_sc & BD_SC_EMPTY);
+ nc = rbdf->cbd_datlen;
+ for (i=0; i<nc; i++)
+ *cbuf++ = *buf++;
+ rbdf->cbd_sc |= BD_SC_EMPTY;
+
+ return(nc);
+}
+
+void
+serial_putc(void *ignored, const char c)
+{
+ volatile cbd_t *tbdf;
+ volatile char *buf;
+#ifdef SCC_CONSOLE
+ volatile scc_uart_t *sup;
+#else
+ volatile smc_uart_t *up;
+#endif
+ volatile cpm2_map_t *ip;
+
+ ip = (cpm2_map_t *)CPM_MAP_ADDR;
+#ifdef SCC_CONSOLE
+ sup = (scc_uart_t *)&ip->im_dprambase[PROFF_SCC1 + ((SCC_CONSOLE-1) << 8)];
+ tbdf = (cbd_t *)&ip->im_dprambase[sup->scc_genscc.scc_tbase];
+#else
+ up = (smc_uart_t *)&(ip->im_dprambase[PROFF_SMC1]);
+ tbdf = (cbd_t *)&ip->im_dprambase[up->smc_tbase];
+#endif
+
+ /* Wait for last character to go.
+ */
+ buf = (char *)tbdf->cbd_bufaddr;
+ while (tbdf->cbd_sc & BD_SC_READY);
+
+ *buf = c;
+ tbdf->cbd_datlen = 1;
+ tbdf->cbd_sc |= BD_SC_READY;
+}
+
+char
+serial_getc(void *ignored)
+{
+ char c;
+
+ if (cons_hold_cnt <= 0) {
+ cons_hold_cnt = serial_readbuf(cons_hold);
+ sgptr = cons_hold;
+ }
+ c = *sgptr++;
+ cons_hold_cnt--;
+
+ return(c);
+}
+
+int
+serial_tstc(void *ignored)
+{
+ volatile cbd_t *rbdf;
+#ifdef SCC_CONSOLE
+ volatile scc_uart_t *sup;
+#else
+ volatile smc_uart_t *up;
+#endif
+ volatile cpm2_map_t *ip;
+
+ ip = (cpm2_map_t *)CPM_MAP_ADDR;
+#ifdef SCC_CONSOLE
+ sup = (scc_uart_t *)&ip->im_dprambase[PROFF_SCC1 + ((SCC_CONSOLE-1) << 8)];
+ rbdf = (cbd_t *)&ip->im_dprambase[sup->scc_genscc.scc_rbase];
+#else
+ up = (smc_uart_t *)&(ip->im_dprambase[PROFF_SMC1]);
+ rbdf = (cbd_t *)&ip->im_dprambase[up->smc_rbase];
+#endif
+
+ return(!(rbdf->cbd_sc & BD_SC_EMPTY));
+}
diff --git a/arch/ppc/boot/simple/m8xx_tty.c b/arch/ppc/boot/simple/m8xx_tty.c
new file mode 100644
index 0000000..1d2778e
--- /dev/null
+++ b/arch/ppc/boot/simple/m8xx_tty.c
@@ -0,0 +1,290 @@
+/* Minimal serial functions needed to send messages out the serial
+ * port on the MBX console.
+ *
+ * The MBX uxes SMC1 for the serial port. We reset the port and use
+ * only the first BD that EPPC-Bug set up as a character FIFO.
+ *
+ * Later versions (at least 1.4, maybe earlier) of the MBX EPPC-Bug
+ * use COM1 instead of SMC1 as the console port. This kinda sucks
+ * for the rest of the kernel, so here we force the use of SMC1 again.
+ */
+#include <linux/config.h>
+#include <linux/types.h>
+#include <asm/uaccess.h>
+#include <asm/mpc8xx.h>
+#include <asm/commproc.h>
+
+#ifdef CONFIG_MBX
+#define MBX_CSR1 ((volatile u_char *)0xfa100000)
+#define CSR1_COMEN (u_char)0x02
+#endif
+
+#ifdef TQM_SMC2_CONSOLE
+#define PROFF_CONS PROFF_SMC2
+#define CPM_CR_CH_CONS CPM_CR_CH_SMC2
+#define SMC_INDEX 1
+static volatile iop8xx_t *iopp = (iop8xx_t *)&(((immap_t *)IMAP_ADDR)->im_ioport);
+#else
+#define PROFF_CONS PROFF_SMC1
+#define CPM_CR_CH_CONS CPM_CR_CH_SMC1
+#define SMC_INDEX 0
+#endif
+
+static cpm8xx_t *cpmp = (cpm8xx_t *)&(((immap_t *)IMAP_ADDR)->im_cpm);
+
+unsigned long
+serial_init(int ignored, bd_t *bd)
+{
+ volatile smc_t *sp;
+ volatile smc_uart_t *up;
+ volatile cbd_t *tbdf, *rbdf;
+ volatile cpm8xx_t *cp;
+ uint dpaddr, memaddr;
+#ifndef CONFIG_MBX
+ uint ui;
+#endif
+
+ cp = cpmp;
+ sp = (smc_t*)&(cp->cp_smc[SMC_INDEX]);
+ up = (smc_uart_t *)&cp->cp_dparam[PROFF_CONS];
+
+ /* Disable transmitter/receiver.
+ */
+ sp->smc_smcmr &= ~(SMCMR_REN | SMCMR_TEN);
+
+#ifdef CONFIG_FADS
+ /* Enable SMC1/2 transceivers.
+ */
+ *((volatile uint *)BCSR1) &= ~(BCSR1_RS232EN_1|BCSR1_RS232EN_2);
+#endif
+
+#ifndef CONFIG_MBX
+ {
+ /* Initialize SMCx and use it for the console port.
+ */
+
+ /* Enable SDMA.
+ */
+ ((immap_t *)IMAP_ADDR)->im_siu_conf.sc_sdcr = 1;
+
+#ifdef TQM_SMC2_CONSOLE
+ /* Use Port A for SMC2 instead of other functions.
+ */
+ iopp->iop_papar |= 0x00c0;
+ iopp->iop_padir &= ~0x00c0;
+ iopp->iop_paodr &= ~0x00c0;
+#else
+ /* Use Port B for SMCs instead of other functions.
+ */
+ cp->cp_pbpar |= 0x00000cc0;
+ cp->cp_pbdir &= ~0x00000cc0;
+ cp->cp_pbodr &= ~0x00000cc0;
+#endif
+
+ /* Allocate space for two buffer descriptors in the DP ram.
+ * For now, this address seems OK, but it may have to
+ * change with newer versions of the firmware.
+ */
+ dpaddr = 0x0800;
+
+ /* Grab a few bytes from the top of memory for SMC FIFOs.
+ */
+ memaddr = (bd->bi_memsize - 32) & ~15;
+
+ /* Set the physical address of the host memory buffers in
+ * the buffer descriptors.
+ */
+ rbdf = (cbd_t *)&cp->cp_dpmem[dpaddr];
+ rbdf->cbd_bufaddr = memaddr;
+ rbdf->cbd_sc = 0;
+ tbdf = rbdf + 1;
+ tbdf->cbd_bufaddr = memaddr+4;
+ tbdf->cbd_sc = 0;
+
+ /* Set up the uart parameters in the parameter ram.
+ */
+ up->smc_rbase = dpaddr;
+ up->smc_tbase = dpaddr+sizeof(cbd_t);
+ up->smc_rfcr = SMC_EB;
+ up->smc_tfcr = SMC_EB;
+
+ /* Set UART mode, 8 bit, no parity, one stop.
+ * Enable receive and transmit.
+ */
+ sp->smc_smcmr = smcr_mk_clen(9) | SMCMR_SM_UART;
+
+ /* Mask all interrupts and remove anything pending.
+ */
+ sp->smc_smcm = 0;
+ sp->smc_smce = 0xff;
+
+ /* Set up the baud rate generator.
+ * See 8xx_io/commproc.c for details.
+ * This wires BRG1 to SMC1 and BRG2 to SMC2;
+ */
+ cp->cp_simode = 0x10000000;
+ ui = bd->bi_intfreq / 16 / bd->bi_baudrate;
+#ifdef TQM_SMC2_CONSOLE
+ cp->cp_brgc2 =
+#else
+ cp->cp_brgc1 =
+#endif
+ ((ui - 1) < 4096)
+ ? (((ui - 1) << 1) | CPM_BRG_EN)
+ : ((((ui / 16) - 1) << 1) | CPM_BRG_EN | CPM_BRG_DIV16);
+
+#else /* CONFIG_MBX */
+ if (*MBX_CSR1 & CSR1_COMEN) {
+ /* COM1 is enabled. Initialize SMC1 and use it for
+ * the console port.
+ */
+
+ /* Enable SDMA.
+ */
+ ((immap_t *)IMAP_ADDR)->im_siu_conf.sc_sdcr = 1;
+
+ /* Use Port B for SMCs instead of other functions.
+ */
+ cp->cp_pbpar |= 0x00000cc0;
+ cp->cp_pbdir &= ~0x00000cc0;
+ cp->cp_pbodr &= ~0x00000cc0;
+
+ /* Allocate space for two buffer descriptors in the DP ram.
+ * For now, this address seems OK, but it may have to
+ * change with newer versions of the firmware.
+ */
+ dpaddr = 0x0800;
+
+ /* Grab a few bytes from the top of memory. EPPC-Bug isn't
+ * running any more, so we can do this.
+ */
+ memaddr = (bd->bi_memsize - 32) & ~15;
+
+ /* Set the physical address of the host memory buffers in
+ * the buffer descriptors.
+ */
+ rbdf = (cbd_t *)&cp->cp_dpmem[dpaddr];
+ rbdf->cbd_bufaddr = memaddr;
+ rbdf->cbd_sc = 0;
+ tbdf = rbdf + 1;
+ tbdf->cbd_bufaddr = memaddr+4;
+ tbdf->cbd_sc = 0;
+
+ /* Set up the uart parameters in the parameter ram.
+ */
+ up->smc_rbase = dpaddr;
+ up->smc_tbase = dpaddr+sizeof(cbd_t);
+ up->smc_rfcr = SMC_EB;
+ up->smc_tfcr = SMC_EB;
+
+ /* Set UART mode, 8 bit, no parity, one stop.
+ * Enable receive and transmit.
+ */
+ sp->smc_smcmr = smcr_mk_clen(9) | SMCMR_SM_UART;
+
+ /* Mask all interrupts and remove anything pending.
+ */
+ sp->smc_smcm = 0;
+ sp->smc_smce = 0xff;
+
+ /* Set up the baud rate generator.
+ * See 8xx_io/commproc.c for details.
+ */
+ cp->cp_simode = 0x10000000;
+ cp->cp_brgc1 =
+ (((bd->bi_intfreq/16) / 9600) << 1) | CPM_BRG_EN;
+
+ /* Enable SMC1 for console output.
+ */
+ *MBX_CSR1 &= ~CSR1_COMEN;
+ }
+ else {
+#endif /* ndef CONFIG_MBX */
+ /* SMCx is used as console port.
+ */
+ tbdf = (cbd_t *)&cp->cp_dpmem[up->smc_tbase];
+ rbdf = (cbd_t *)&cp->cp_dpmem[up->smc_rbase];
+
+ /* Issue a stop transmit, and wait for it.
+ */
+ cp->cp_cpcr = mk_cr_cmd(CPM_CR_CH_CONS,
+ CPM_CR_STOP_TX) | CPM_CR_FLG;
+ while (cp->cp_cpcr & CPM_CR_FLG);
+ }
+
+ /* Make the first buffer the only buffer.
+ */
+ tbdf->cbd_sc |= BD_SC_WRAP;
+ rbdf->cbd_sc |= BD_SC_EMPTY | BD_SC_WRAP;
+
+ /* Single character receive.
+ */
+ up->smc_mrblr = 1;
+ up->smc_maxidl = 0;
+
+ /* Initialize Tx/Rx parameters.
+ */
+ cp->cp_cpcr = mk_cr_cmd(CPM_CR_CH_CONS, CPM_CR_INIT_TRX) | CPM_CR_FLG;
+ while (cp->cp_cpcr & CPM_CR_FLG);
+
+ /* Enable transmitter/receiver.
+ */
+ sp->smc_smcmr |= SMCMR_REN | SMCMR_TEN;
+
+ /* This is ignored.
+ */
+ return 0;
+}
+
+void
+serial_putc(void *ignored, const char c)
+{
+ volatile cbd_t *tbdf;
+ volatile char *buf;
+ volatile smc_uart_t *up;
+
+ up = (smc_uart_t *)&cpmp->cp_dparam[PROFF_CONS];
+ tbdf = (cbd_t *)&cpmp->cp_dpmem[up->smc_tbase];
+
+ /* Wait for last character to go.
+ */
+ buf = (char *)tbdf->cbd_bufaddr;
+ while (tbdf->cbd_sc & BD_SC_READY);
+
+ *buf = c;
+ tbdf->cbd_datlen = 1;
+ tbdf->cbd_sc |= BD_SC_READY;
+}
+
+char
+serial_getc(void *ignored)
+{
+ volatile cbd_t *rbdf;
+ volatile char *buf;
+ volatile smc_uart_t *up;
+ char c;
+
+ up = (smc_uart_t *)&cpmp->cp_dparam[PROFF_CONS];
+ rbdf = (cbd_t *)&cpmp->cp_dpmem[up->smc_rbase];
+
+ /* Wait for character to show up.
+ */
+ buf = (char *)rbdf->cbd_bufaddr;
+ while (rbdf->cbd_sc & BD_SC_EMPTY);
+ c = *buf;
+ rbdf->cbd_sc |= BD_SC_EMPTY;
+
+ return(c);
+}
+
+int
+serial_tstc(void *ignored)
+{
+ volatile cbd_t *rbdf;
+ volatile smc_uart_t *up;
+
+ up = (smc_uart_t *)&cpmp->cp_dparam[PROFF_CONS];
+ rbdf = (cbd_t *)&cpmp->cp_dpmem[up->smc_rbase];
+
+ return(!(rbdf->cbd_sc & BD_SC_EMPTY));
+}
diff --git a/arch/ppc/boot/simple/misc-chestnut.c b/arch/ppc/boot/simple/misc-chestnut.c
new file mode 100644
index 0000000..0dce7f3
--- /dev/null
+++ b/arch/ppc/boot/simple/misc-chestnut.c
@@ -0,0 +1,35 @@
+/*
+ * arch/ppc/boot/simple/misc-chestnut.c
+ *
+ * Setup for the IBM Chestnut (ibm-750fxgx_eval)
+ *
+ * Author: Mark A. Greer <mgreer@mvista.com>
+ *
+ * 2005 (c) MontaVista Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+
+#include <linux/config.h>
+#include <linux/types.h>
+#include <asm/io.h>
+#include <asm/mv64x60_defs.h>
+#include <platforms/chestnut.h>
+
+/* Not in the kernel so won't include kernel.h to get its 'max' definition */
+#define max(a,b) (((a) > (b)) ? (a) : (b))
+
+void
+mv64x60_board_init(void __iomem *old_base, void __iomem *new_base)
+{
+#ifdef CONFIG_SERIAL_8250_CONSOLE
+ /*
+ * Change device bus 2 window so that bootoader can do I/O thru
+ * 8250/16550 UART that's mapped in that window.
+ */
+ out_le32(new_base + MV64x60_CPU2DEV_2_BASE, CHESTNUT_UART_BASE >> 16);
+ out_le32(new_base + MV64x60_CPU2DEV_2_SIZE, CHESTNUT_UART_SIZE >> 16);
+ __asm__ __volatile__("sync");
+#endif
+}
diff --git a/arch/ppc/boot/simple/misc-cpci690.c b/arch/ppc/boot/simple/misc-cpci690.c
new file mode 100644
index 0000000..ef08e86
--- /dev/null
+++ b/arch/ppc/boot/simple/misc-cpci690.c
@@ -0,0 +1,27 @@
+/*
+ * arch/ppc/boot/simple/misc-cpci690.c
+ *
+ * Add birec data for Force CPCI690 board.
+ *
+ * Author: Mark A. Greer <source@mvista.com>
+ *
+ * 2003 (c) MontaVista Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+
+#include <linux/types.h>
+#include <platforms/cpci690.h>
+
+extern u32 mv64x60_console_baud;
+extern u32 mv64x60_mpsc_clk_src;
+extern u32 mv64x60_mpsc_clk_freq;
+
+void
+mv64x60_board_init(void __iomem *old_base, void __iomem *new_base)
+{
+ mv64x60_console_baud = CPCI690_MPSC_BAUD;
+ mv64x60_mpsc_clk_src = CPCI690_MPSC_CLK_SRC;
+ mv64x60_mpsc_clk_freq = CPCI690_BUS_FREQ;
+}
diff --git a/arch/ppc/boot/simple/misc-embedded.c b/arch/ppc/boot/simple/misc-embedded.c
new file mode 100644
index 0000000..3865f3f
--- /dev/null
+++ b/arch/ppc/boot/simple/misc-embedded.c
@@ -0,0 +1,275 @@
+/*
+ * Originally adapted by Gary Thomas. Much additional work by
+ * Cort Dougan <cort@fsmlabs.com>. On top of that still more work by
+ * Dan Malek <dmalek@jlc.net>.
+ *
+ * Currently maintained by: Tom Rini <trini@kernel.crashing.org>
+ */
+
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/string.h>
+#include <asm/bootinfo.h>
+#include <asm/mmu.h>
+#include <asm/page.h>
+#include <asm/residual.h>
+#if defined(CONFIG_4xx)
+#include <asm/ibm4xx.h>
+#elif defined(CONFIG_8xx)
+#include <asm/mpc8xx.h>
+#elif defined(CONFIG_8260)
+#include <asm/mpc8260.h>
+#endif
+
+#include "nonstdio.h"
+
+/* The linker tells us where the image is. */
+extern char __image_begin, __image_end;
+extern char __ramdisk_begin, __ramdisk_end;
+extern char _end[];
+
+/* Because of the limited amount of memory on embedded, it presents
+ * loading problems. The biggest is that we load this boot program
+ * into a relatively low memory address, and the Linux kernel Bss often
+ * extends into this space when it get loaded. When the kernel starts
+ * and zeros the BSS space, it also writes over the information we
+ * save here and pass to the kernel (usually board info).
+ * On these boards, we grab some known memory holes to hold this information.
+ */
+char cmd_buf[256];
+char *cmd_line = cmd_buf;
+char *avail_ram;
+char *end_avail;
+char *zimage_start;
+
+/* This is for 4xx treeboot. It provides a place for the bootrom
+ * give us a pointer to a rom environment command line.
+ */
+char *bootrom_cmdline = "";
+
+/* This is the default cmdline that will be given to the user at boot time..
+ * If none was specified at compile time, we'll give it one that should work.
+ * -- Tom */
+#ifdef CONFIG_CMDLINE_BOOL
+char compiled_string[] = CONFIG_CMDLINE;
+#endif
+char ramroot_string[] = "root=/dev/ram";
+char netroot_string[] = "root=/dev/nfs rw ip=on";
+
+/* Serial port to use. */
+unsigned long com_port;
+
+/* We need to make sure that this is before the images to ensure
+ * that it's in a mapped location. - Tom */
+bd_t hold_resid_buf __attribute__ ((__section__ (".data.boot")));
+bd_t *hold_residual = &hold_resid_buf;
+
+extern unsigned long serial_init(int chan, bd_t *bp);
+extern void serial_close(unsigned long com_port);
+extern unsigned long start;
+extern void flush_instruction_cache(void);
+extern void gunzip(void *, int, unsigned char *, int *);
+extern void embed_config(bd_t **bp);
+
+/* Weak function for boards which don't need to build the
+ * board info struct because they are using PPCBoot/U-Boot.
+ */
+void __attribute__ ((weak))
+embed_config(bd_t **bdp)
+{
+}
+
+unsigned long
+load_kernel(unsigned long load_addr, int num_words, unsigned long cksum, bd_t *bp)
+{
+ char *cp, ch;
+ int timer = 0, zimage_size;
+ unsigned long initrd_size;
+
+ /* First, capture the embedded board information. Then
+ * initialize the serial console port.
+ */
+ embed_config(&bp);
+#if defined(CONFIG_SERIAL_CPM_CONSOLE) || defined(CONFIG_SERIAL_8250_CONSOLE)
+ com_port = serial_init(0, bp);
+#endif
+
+ /* Grab some space for the command line and board info. Since
+ * we no longer use the ELF header, but it was loaded, grab
+ * that space.
+ */
+#ifdef CONFIG_MBX
+ /* Because of the way the MBX loads the ELF image, we can't
+ * tell where we started. We read a magic variable from the NVRAM
+ * that gives us the intermediate buffer load address.
+ */
+ load_addr = *(uint *)0xfa000020;
+ load_addr += 0x10000; /* Skip ELF header */
+#endif
+ /* copy board data */
+ if (bp)
+ memcpy(hold_residual,bp,sizeof(bd_t));
+
+ /* Set end of memory available to us. It is always the highest
+ * memory address provided by the board information.
+ */
+ end_avail = (char *)(bp->bi_memsize);
+
+ puts("\nloaded at: "); puthex(load_addr);
+ puts(" "); puthex((unsigned long)(load_addr + (4*num_words))); puts("\n");
+ if ( (unsigned long)load_addr != (unsigned long)&start ) {
+ puts("relocated to: "); puthex((unsigned long)&start);
+ puts(" ");
+ puthex((unsigned long)((unsigned long)&start + (4*num_words)));
+ puts("\n");
+ }
+
+ if ( bp ) {
+ puts("board data at: "); puthex((unsigned long)bp);
+ puts(" ");
+ puthex((unsigned long)((unsigned long)bp + sizeof(bd_t)));
+ puts("\nrelocated to: ");
+ puthex((unsigned long)hold_residual);
+ puts(" ");
+ puthex((unsigned long)((unsigned long)hold_residual + sizeof(bd_t)));
+ puts("\n");
+ }
+
+ /*
+ * We link ourself to an arbitrary low address. When we run, we
+ * relocate outself to that address. __image_being points to
+ * the part of the image where the zImage is. -- Tom
+ */
+ zimage_start = (char *)(unsigned long)(&__image_begin);
+ zimage_size = (unsigned long)(&__image_end) -
+ (unsigned long)(&__image_begin);
+
+ initrd_size = (unsigned long)(&__ramdisk_end) -
+ (unsigned long)(&__ramdisk_begin);
+
+ /*
+ * The zImage and initrd will be between start and _end, so they've
+ * already been moved once. We're good to go now. -- Tom
+ */
+ puts("zimage at: "); puthex((unsigned long)zimage_start);
+ puts(" "); puthex((unsigned long)(zimage_size+zimage_start));
+ puts("\n");
+
+ if ( initrd_size ) {
+ puts("initrd at: ");
+ puthex((unsigned long)(&__ramdisk_begin));
+ puts(" "); puthex((unsigned long)(&__ramdisk_end));puts("\n");
+ }
+
+ /*
+ * setup avail_ram - this is the first part of ram usable
+ * by the uncompress code. Anything after this program in RAM
+ * is now fair game. -- Tom
+ */
+ avail_ram = (char *)PAGE_ALIGN((unsigned long)_end);
+
+ puts("avail ram: "); puthex((unsigned long)avail_ram); puts(" ");
+ puthex((unsigned long)end_avail); puts("\n");
+ puts("\nLinux/PPC load: ");
+ cp = cmd_line;
+ /* This is where we try and pick the right command line for booting.
+ * If we were given one at compile time, use it. It Is Right.
+ * If we weren't, see if we have a ramdisk. If so, thats root.
+ * When in doubt, give them the netroot (root=/dev/nfs rw) -- Tom
+ */
+#ifdef CONFIG_CMDLINE_BOOL
+ memcpy (cmd_line, compiled_string, sizeof(compiled_string));
+#else
+ if ( initrd_size )
+ memcpy (cmd_line, ramroot_string, sizeof(ramroot_string));
+ else
+ memcpy (cmd_line, netroot_string, sizeof(netroot_string));
+#endif
+ while ( *cp )
+ putc(*cp++);
+ while (timer++ < 5*1000) {
+ if (tstc()) {
+ while ((ch = getc()) != '\n' && ch != '\r') {
+ if (ch == '\b' || ch == '\177') {
+ if (cp != cmd_line) {
+ cp--;
+ puts("\b \b");
+ }
+ } else if (ch == '\030' /* ^x */
+ || ch == '\025') { /* ^u */
+ while (cp != cmd_line) {
+ cp--;
+ puts("\b \b");
+ }
+ } else {
+ *cp++ = ch;
+ putc(ch);
+ }
+ }
+ break; /* Exit 'timer' loop */
+ }
+ udelay(1000); /* 1 msec */
+ }
+ *cp = 0;
+ puts("\nUncompressing Linux...");
+
+ gunzip(0, 0x400000, zimage_start, &zimage_size);
+ flush_instruction_cache();
+ puts("done.\n");
+ {
+ struct bi_record *rec;
+ unsigned long initrd_loc = 0;
+ unsigned long rec_loc = _ALIGN((unsigned long)(zimage_size) +
+ (1 << 20) - 1, (1 << 20));
+ rec = (struct bi_record *)rec_loc;
+
+ /* We need to make sure that the initrd and bi_recs do not
+ * overlap. */
+ if ( initrd_size ) {
+ initrd_loc = (unsigned long)(&__ramdisk_begin);
+ /* If the bi_recs are in the middle of the current
+ * initrd, move the initrd to the next MB
+ * boundary. */
+ if ((rec_loc > initrd_loc) &&
+ ((initrd_loc + initrd_size)
+ > rec_loc)) {
+ initrd_loc = _ALIGN((unsigned long)(zimage_size)
+ + (2 << 20) - 1, (2 << 20));
+ memmove((void *)initrd_loc, &__ramdisk_begin,
+ initrd_size);
+ puts("initrd moved: "); puthex(initrd_loc);
+ puts(" "); puthex(initrd_loc + initrd_size);
+ puts("\n");
+ }
+ }
+
+ rec->tag = BI_FIRST;
+ rec->size = sizeof(struct bi_record);
+ rec = (struct bi_record *)((unsigned long)rec + rec->size);
+
+ rec->tag = BI_CMD_LINE;
+ memcpy( (char *)rec->data, cmd_line, strlen(cmd_line)+1);
+ rec->size = sizeof(struct bi_record) + strlen(cmd_line) + 1;
+ rec = (struct bi_record *)((unsigned long)rec + rec->size);
+
+ if ( initrd_size ) {
+ rec->tag = BI_INITRD;
+ rec->data[0] = initrd_loc;
+ rec->data[1] = initrd_size;
+ rec->size = sizeof(struct bi_record) + 2 *
+ sizeof(unsigned long);
+ rec = (struct bi_record *)((unsigned long)rec +
+ rec->size);
+ }
+
+ rec->tag = BI_LAST;
+ rec->size = sizeof(struct bi_record);
+ rec = (struct bi_record *)((unsigned long)rec + rec->size);
+ }
+ puts("Now booting the kernel\n");
+#if defined(CONFIG_SERIAL_CPM_CONSOLE) || defined(CONFIG_SERIAL_8250_CONSOLE)
+ serial_close(com_port);
+#endif
+
+ return (unsigned long)hold_residual;
+}
diff --git a/arch/ppc/boot/simple/misc-ev64260.c b/arch/ppc/boot/simple/misc-ev64260.c
new file mode 100644
index 0000000..52ece69
--- /dev/null
+++ b/arch/ppc/boot/simple/misc-ev64260.c
@@ -0,0 +1,57 @@
+/*
+ * arch/ppc/boot/simple/misc-ev64260.c
+ *
+ * Host bridge init code for the Marvell/Galileo EV-64260-BP evaluation board
+ * with a GT64260 onboard.
+ *
+ * Author: Mark A. Greer <mgreer@mvista.com>
+ *
+ * 2001 (c) MontaVista Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+
+#include <linux/config.h>
+#include <linux/types.h>
+#include <asm/reg.h>
+#include <asm/io.h>
+#include <asm/mv64x60_defs.h>
+#include <platforms/ev64260.h>
+
+#ifdef CONFIG_SERIAL_MPSC_CONSOLE
+extern u32 mv64x60_console_baud;
+extern u32 mv64x60_mpsc_clk_src;
+extern u32 mv64x60_mpsc_clk_freq;
+#endif
+
+void
+mv64x60_board_init(void __iomem *old_base, void __iomem *new_base)
+{
+ u32 p, v;
+
+ /* DINK doesn't enable 745x timebase, so enable here (Adrian Cox) */
+ p = mfspr(SPRN_PVR);
+ p >>= 16;
+
+ /* Reasonable SWAG at a 745x PVR value */
+ if (((p & 0xfff0) == 0x8000) && (p != 0x800c)) {
+ v = mfspr(SPRN_HID0);
+ v |= HID0_TBEN;
+ mtspr(SPRN_HID0, v);
+ }
+
+#ifdef CONFIG_SERIAL_8250_CONSOLE
+ /*
+ * Change device bus 2 window so that bootoader can do I/O thru
+ * 8250/16550 UART that's mapped in that window.
+ */
+ out_le32(new_base + MV64x60_CPU2DEV_2_BASE, EV64260_UART_BASE >> 20);
+ out_le32(new_base + MV64x60_CPU2DEV_2_SIZE, EV64260_UART_END >> 20);
+ __asm__ __volatile__("sync");
+#elif defined(CONFIG_SERIAL_MPSC_CONSOLE)
+ mv64x60_console_baud = EV64260_DEFAULT_BAUD;
+ mv64x60_mpsc_clk_src = EV64260_MPSC_CLK_SRC;
+ mv64x60_mpsc_clk_freq = EV64260_MPSC_CLK_FREQ;
+#endif
+}
diff --git a/arch/ppc/boot/simple/misc-katana.c b/arch/ppc/boot/simple/misc-katana.c
new file mode 100644
index 0000000..b6e1bb8
--- /dev/null
+++ b/arch/ppc/boot/simple/misc-katana.c
@@ -0,0 +1,37 @@
+/*
+ * arch/ppc/boot/simple/misc-katana.c
+ *
+ * Set up MPSC values to bootwrapper can prompt user.
+ *
+ * Author: Mark A. Greer <source@mvista.com>
+ *
+ * 2004 (c) MontaVista Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+
+#include <linux/config.h>
+#include <linux/types.h>
+#include <asm/io.h>
+#include <asm/mv64x60_defs.h>
+#include <platforms/katana.h>
+
+extern u32 mv64x60_console_baud;
+extern u32 mv64x60_mpsc_clk_src;
+extern u32 mv64x60_mpsc_clk_freq;
+
+/* Not in the kernel so won't include kernel.h to get its 'min' definition */
+#ifndef min
+#define min(a,b) (((a) < (b)) ? (a) : (b))
+#endif
+
+void
+mv64x60_board_init(void __iomem *old_base, void __iomem *new_base)
+{
+ mv64x60_console_baud = KATANA_DEFAULT_BAUD;
+ mv64x60_mpsc_clk_src = KATANA_MPSC_CLK_SRC;
+ mv64x60_mpsc_clk_freq =
+ min(katana_bus_freq((void __iomem *)KATANA_CPLD_BASE),
+ MV64x60_TCLK_FREQ_MAX);
+}
diff --git a/arch/ppc/boot/simple/misc-mv64x60.c b/arch/ppc/boot/simple/misc-mv64x60.c
new file mode 100644
index 0000000..7e88fc6
--- /dev/null
+++ b/arch/ppc/boot/simple/misc-mv64x60.c
@@ -0,0 +1,61 @@
+/*
+ * arch/ppc/boot/simple/misc-mv64x60.c
+ *
+ * Relocate bridge's register base and call board specific routine.
+ *
+ * Author: Mark A. Greer <source@mvista.com>
+ *
+ * 2005 (c) MontaVista Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+
+#include <linux/config.h>
+#include <linux/types.h>
+#include <asm/io.h>
+#include <asm/mv64x60_defs.h>
+
+extern struct bi_record *decompress_kernel(unsigned long load_addr,
+ int num_words, unsigned long cksum);
+
+void
+mv64x60_move_base(void __iomem *old_base, void __iomem *new_base)
+{
+ u32 bits, mask, b;
+
+ if (old_base != new_base) {
+#ifdef CONFIG_GT64260
+ bits = 12;
+ mask = 0x07000000;
+#else /* Must be mv64[34]60 */
+ bits = 16;
+ mask = 0x03000000;
+#endif
+ b = in_le32(old_base + MV64x60_INTERNAL_SPACE_DECODE);
+ b &= mask;
+ b |= ((u32)new_base >> (32 - bits));
+ out_le32(old_base + MV64x60_INTERNAL_SPACE_DECODE, b);
+
+ __asm__ __volatile__("sync");
+
+ /* Wait for change to happen (in accordance with the manual) */
+ while (in_le32(new_base + MV64x60_INTERNAL_SPACE_DECODE) != b);
+ }
+}
+
+void __attribute__ ((weak))
+mv64x60_board_init(void __iomem *old_base, void __iomem *new_base)
+{
+}
+
+void *
+load_kernel(unsigned long load_addr, int num_words, unsigned long cksum,
+ void *ign1, void *ign2)
+{
+ mv64x60_move_base((void __iomem *)CONFIG_MV64X60_BASE,
+ (void __iomem *)CONFIG_MV64X60_NEW_BASE);
+ mv64x60_board_init((void __iomem *)CONFIG_MV64X60_BASE,
+ (void __iomem *)CONFIG_MV64X60_NEW_BASE);
+ return decompress_kernel(load_addr, num_words, cksum);
+}
diff --git a/arch/ppc/boot/simple/misc-prep.c b/arch/ppc/boot/simple/misc-prep.c
new file mode 100644
index 0000000..75380ac
--- /dev/null
+++ b/arch/ppc/boot/simple/misc-prep.c
@@ -0,0 +1,212 @@
+/*
+ * arch/ppc/boot/simple/misc-prep.c
+ *
+ * Maintainer: Tom Rini <trini@kernel.crashing.org>
+ *
+ * In the past: Gary Thomas, Cort Dougan <cort@cs.nmt.edu>
+ */
+
+#include <linux/config.h>
+#include <linux/pci_ids.h>
+#include <linux/types.h>
+#include <asm/residual.h>
+#include <asm/string.h>
+#include <asm/byteorder.h>
+#include "mpc10x.h"
+#include "of1275.h"
+#include "nonstdio.h"
+
+extern int keyb_present; /* keyboard controller is present by default */
+RESIDUAL hold_resid_buf;
+RESIDUAL *hold_residual = &hold_resid_buf;
+static void *OFW_interface; /* Pointer to OF, if available. */
+
+#ifdef CONFIG_VGA_CONSOLE
+char *vidmem = (char *)0xC00B8000;
+int lines = 25, cols = 80;
+int orig_x, orig_y = 24;
+#endif /* CONFIG_VGA_CONSOLE */
+
+extern int CRT_tstc(void);
+extern int vga_init(unsigned char *ISA_mem);
+extern void gunzip(void *, int, unsigned char *, int *);
+extern unsigned long serial_init(int chan, void *ignored);
+extern void serial_fixups(void);
+extern struct bi_record *decompress_kernel(unsigned long load_addr,
+ int num_words, unsigned long cksum);
+extern void disable_6xx_mmu(void);
+extern unsigned long mpc10x_get_mem_size(void);
+
+static void
+writel(unsigned int val, unsigned int address)
+{
+ /* Ensure I/O operations complete */
+ __asm__ volatile("eieio");
+ *(unsigned int *)address = cpu_to_le32(val);
+}
+
+#define PCI_CFG_ADDR(dev,off) ((0x80<<24) | (dev<<8) | (off&0xfc))
+#define PCI_CFG_DATA(off) (MPC10X_MAPA_CNFG_DATA+(off&3))
+
+static void
+pci_read_config_32(unsigned char devfn,
+ unsigned char offset,
+ unsigned int *val)
+{
+ /* Ensure I/O operations complete */
+ __asm__ volatile("eieio");
+ *(unsigned int *)PCI_CFG_ADDR(devfn,offset) =
+ cpu_to_le32(MPC10X_MAPA_CNFG_ADDR);
+ /* Ensure I/O operations complete */
+ __asm__ volatile("eieio");
+ *val = le32_to_cpu(*(unsigned int *)PCI_CFG_DATA(offset));
+ return;
+}
+
+#ifdef CONFIG_VGA_CONSOLE
+void
+scroll(void)
+{
+ int i;
+
+ memcpy ( vidmem, vidmem + cols * 2, ( lines - 1 ) * cols * 2 );
+ for ( i = ( lines - 1 ) * cols * 2; i < lines * cols * 2; i += 2 )
+ vidmem[i] = ' ';
+}
+#endif /* CONFIG_VGA_CONSOLE */
+
+unsigned long
+load_kernel(unsigned long load_addr, int num_words, unsigned long cksum,
+ RESIDUAL *residual, void *OFW)
+{
+ int start_multi = 0;
+ unsigned int pci_viddid, pci_did, tulip_pci_base, tulip_base;
+
+ /* If we have Open Firmware, initialise it immediately */
+ if (OFW) {
+ OFW_interface = OFW;
+ ofinit(OFW_interface);
+ }
+
+ board_isa_init();
+#if defined(CONFIG_VGA_CONSOLE)
+ vga_init((unsigned char *)0xC0000000);
+#endif /* CONFIG_VGA_CONSOLE */
+
+ if (residual) {
+ /* Is this Motorola PPCBug? */
+ if ((1 & residual->VitalProductData.FirmwareSupports) &&
+ (1 == residual->VitalProductData.FirmwareSupplier)) {
+ unsigned char base_mod;
+ unsigned char board_type = inb(0x801) & 0xF0;
+
+ /*
+ * Reset the onboard 21x4x Ethernet
+ * Motorola Ethernet is at IDSEL 14 (devfn 0x70)
+ */
+ pci_read_config_32(0x70, 0x00, &pci_viddid);
+ pci_did = (pci_viddid & 0xffff0000) >> 16;
+ /* Be sure we've really found a 21x4x chip */
+ if (((pci_viddid & 0xffff) == PCI_VENDOR_ID_DEC) &&
+ ((pci_did == PCI_DEVICE_ID_DEC_TULIP_FAST) ||
+ (pci_did == PCI_DEVICE_ID_DEC_TULIP) ||
+ (pci_did == PCI_DEVICE_ID_DEC_TULIP_PLUS) ||
+ (pci_did == PCI_DEVICE_ID_DEC_21142))) {
+ pci_read_config_32(0x70,
+ 0x10,
+ &tulip_pci_base);
+ /* Get the physical base address */
+ tulip_base =
+ (tulip_pci_base & ~0x03UL) + 0x80000000;
+ /* Strobe the 21x4x reset bit in CSR0 */
+ writel(0x1, tulip_base);
+ }
+
+ /* If this is genesis 2 board then check for no
+ * keyboard controller and more than one processor.
+ */
+ if (board_type == 0xe0) {
+ base_mod = inb(0x803);
+ /* if a MVME2300/2400 or a Sitka then no keyboard */
+ if((base_mod == 0xFA) || (base_mod == 0xF9) ||
+ (base_mod == 0xE1)) {
+ keyb_present = 0; /* no keyboard */
+ }
+ }
+ /* If this is a multiprocessor system then
+ * park the other processor so that the
+ * kernel knows where to find them.
+ */
+ if (residual->MaxNumCpus > 1)
+ start_multi = 1;
+ }
+ memcpy(hold_residual,residual,sizeof(RESIDUAL));
+ }
+
+ /* Call decompress_kernel */
+ decompress_kernel(load_addr, num_words, cksum);
+
+ if (start_multi) {
+ residual->VitalProductData.SmpIar = (unsigned long)0xc0;
+ residual->Cpus[1].CpuState = CPU_GOOD;
+ hold_residual->VitalProductData.Reserved5 = 0xdeadbeef;
+ }
+
+ /* Now go and clear out the BATs and ensure that our MSR is
+ * correct .*/
+ disable_6xx_mmu();
+
+ /* Make r3 be a pointer to the residual data. */
+ return (unsigned long)hold_residual;
+}
+
+unsigned long
+get_mem_size(void)
+{
+ unsigned int pci_viddid, pci_did;
+
+ /* First, figure out what kind of host bridge we are on. If it's
+ * an MPC10x, we can ask it directly how much memory it has.
+ * Otherwise, see if the residual data has anything. This isn't
+ * the best way, but it can be the only way. If there's nothing,
+ * assume 32MB. -- Tom.
+ */
+ /* See what our host bridge is. */
+ pci_read_config_32(0x00, 0x00, &pci_viddid);
+ pci_did = (pci_viddid & 0xffff0000) >> 16;
+ /* See if we are on an MPC10x. */
+ if (((pci_viddid & 0xffff) == PCI_VENDOR_ID_MOTOROLA)
+ && ((pci_did == PCI_DEVICE_ID_MOTOROLA_MPC105)
+ || (pci_did == PCI_DEVICE_ID_MOTOROLA_MPC106)
+ || (pci_did == PCI_DEVICE_ID_MOTOROLA_MPC107)))
+ return mpc10x_get_mem_size();
+ /* If it's not, see if we have anything in the residual data. */
+ else if (hold_residual && hold_residual->TotalMemory)
+ return hold_residual->TotalMemory;
+ else if (OFW_interface) {
+ /*
+ * This is a 'best guess' check. We want to make sure
+ * we don't try this on a PReP box without OF
+ * -- Cort
+ */
+ while (OFW_interface)
+ {
+ phandle dev_handle;
+ int mem_info[2];
+
+ /* get handle to memory description */
+ if (!(dev_handle = finddevice("/memory@0")))
+ break;
+
+ /* get the info */
+ if (getprop(dev_handle, "reg", mem_info,
+ sizeof(mem_info)) != 8)
+ break;
+
+ return mem_info[1];
+ }
+ }
+
+ /* Fall back to hard-coding 32MB. */
+ return 32*1024*1024;
+}
diff --git a/arch/ppc/boot/simple/misc-radstone_ppc7d.c b/arch/ppc/boot/simple/misc-radstone_ppc7d.c
new file mode 100644
index 0000000..569e0d4
--- /dev/null
+++ b/arch/ppc/boot/simple/misc-radstone_ppc7d.c
@@ -0,0 +1,26 @@
+/*
+ * arch/ppc/boot/simple/misc-radstone_ppc7d.c
+ *
+ * Misc data for Radstone PPC7D board.
+ *
+ * Author: James Chapman <jchapman@katalix.com>
+ */
+
+#include <linux/types.h>
+#include <platforms/radstone_ppc7d.h>
+
+#if defined(CONFIG_SERIAL_MPSC_CONSOLE)
+extern u32 mv64x60_console_baud;
+extern u32 mv64x60_mpsc_clk_src;
+extern u32 mv64x60_mpsc_clk_freq;
+#endif
+
+void
+mv64x60_board_init(void __iomem *old_base, void __iomem *new_base)
+{
+#if defined(CONFIG_SERIAL_MPSC_CONSOLE)
+ mv64x60_console_baud = PPC7D_DEFAULT_BAUD;
+ mv64x60_mpsc_clk_src = PPC7D_MPSC_CLK_SRC;
+ mv64x60_mpsc_clk_freq = PPC7D_MPSC_CLK_FREQ;
+#endif
+}
diff --git a/arch/ppc/boot/simple/misc-spruce.c b/arch/ppc/boot/simple/misc-spruce.c
new file mode 100644
index 0000000..d012c39
--- /dev/null
+++ b/arch/ppc/boot/simple/misc-spruce.c
@@ -0,0 +1,274 @@
+/*
+ * arch/ppc/boot/spruce/misc.c
+ *
+ * Misc. bootloader code for IBM Spruce reference platform
+ *
+ * Authors: Johnnie Peters <jpeters@mvista.com>
+ * Matt Porter <mporter@mvista.com>
+ *
+ * Derived from arch/ppc/boot/prep/misc.c
+ *
+ * 2000-2001 (c) MontaVista, Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+
+#include <linux/types.h>
+#include <linux/config.h>
+#include <linux/pci.h>
+
+#include <asm/bootinfo.h>
+
+extern unsigned long decompress_kernel(unsigned long load_addr, int num_words,
+ unsigned long cksum);
+
+/* Define some important locations of the Spruce. */
+#define SPRUCE_PCI_CONFIG_ADDR 0xfec00000
+#define SPRUCE_PCI_CONFIG_DATA 0xfec00004
+
+/* PCI configuration space access routines. */
+unsigned int *pci_config_address = (unsigned int *)SPRUCE_PCI_CONFIG_ADDR;
+unsigned char *pci_config_data = (unsigned char *)SPRUCE_PCI_CONFIG_DATA;
+
+void cpc700_pcibios_read_config_byte(unsigned char bus, unsigned char dev_fn,
+ unsigned char offset, unsigned char *val)
+{
+ out_le32(pci_config_address,
+ (((bus & 0xff)<<16) | (dev_fn<<8) | (offset&0xfc) | 0x80000000));
+
+ *val= (in_le32((unsigned *)pci_config_data) >> (8 * (offset & 3))) & 0xff;
+}
+
+void cpc700_pcibios_write_config_byte(unsigned char bus, unsigned char dev_fn,
+ unsigned char offset, unsigned char val)
+{
+ out_le32(pci_config_address,
+ (((bus & 0xff)<<16) | (dev_fn<<8) | (offset&0xfc) | 0x80000000));
+
+ out_8(pci_config_data + (offset&3), val);
+}
+
+void cpc700_pcibios_read_config_word(unsigned char bus, unsigned char dev_fn,
+ unsigned char offset, unsigned short *val)
+{
+ out_le32(pci_config_address,
+ (((bus & 0xff)<<16) | (dev_fn<<8) | (offset&0xfc) | 0x80000000));
+
+ *val= in_le16((unsigned short *)(pci_config_data + (offset&3)));
+}
+
+void cpc700_pcibios_write_config_word(unsigned char bus, unsigned char dev_fn,
+ unsigned char offset, unsigned short val)
+{
+ out_le32(pci_config_address,
+ (((bus & 0xff)<<16) | (dev_fn<<8) | (offset&0xfc) | 0x80000000));
+
+ out_le16((unsigned short *)(pci_config_data + (offset&3)), val);
+}
+
+void cpc700_pcibios_read_config_dword(unsigned char bus, unsigned char dev_fn,
+ unsigned char offset, unsigned int *val)
+{
+ out_le32(pci_config_address,
+ (((bus & 0xff)<<16) | (dev_fn<<8) | (offset&0xfc) | 0x80000000));
+
+ *val= in_le32((unsigned *)pci_config_data);
+}
+
+void cpc700_pcibios_write_config_dword(unsigned char bus, unsigned char dev_fn,
+ unsigned char offset, unsigned int val)
+{
+ out_le32(pci_config_address,
+ (((bus & 0xff)<<16) | (dev_fn<<8) | (offset&0xfc) | 0x80000000));
+
+ out_le32((unsigned *)pci_config_data, val);
+}
+
+#define PCNET32_WIO_RDP 0x10
+#define PCNET32_WIO_RAP 0x12
+#define PCNET32_WIO_RESET 0x14
+
+#define PCNET32_DWIO_RDP 0x10
+#define PCNET32_DWIO_RAP 0x14
+#define PCNET32_DWIO_RESET 0x18
+
+/* Processor interface config register access */
+#define PIFCFGADDR 0xff500000
+#define PIFCFGDATA 0xff500004
+
+#define PLBMIFOPT 0x18 /* PLB Master Interface Options */
+
+#define MEM_MBEN 0x24
+#define MEM_TYPE 0x28
+#define MEM_B1SA 0x3c
+#define MEM_B1EA 0x5c
+#define MEM_B2SA 0x40
+#define MEM_B2EA 0x60
+
+unsigned long
+get_mem_size(void)
+{
+ int loop;
+ unsigned long mem_size = 0;
+ unsigned long mem_mben;
+ unsigned long mem_type;
+ unsigned long mem_start;
+ unsigned long mem_end;
+ volatile int *mem_addr = (int *)0xff500008;
+ volatile int *mem_data = (int *)0xff50000c;
+
+ /* Get the size of memory from the memory controller. */
+ *mem_addr = MEM_MBEN;
+ asm("sync");
+ mem_mben = *mem_data;
+ asm("sync");
+ for(loop = 0; loop < 1000; loop++);
+
+ *mem_addr = MEM_TYPE;
+ asm("sync");
+ mem_type = *mem_data;
+ asm("sync");
+ for(loop = 0; loop < 1000; loop++);
+
+ *mem_addr = MEM_TYPE;
+ /* Confirm bank 1 has DRAM memory */
+ if ((mem_mben & 0x40000000) &&
+ ((mem_type & 0x30000000) == 0x10000000)) {
+ *mem_addr = MEM_B1SA;
+ asm("sync");
+ mem_start = *mem_data;
+ asm("sync");
+ for(loop = 0; loop < 1000; loop++);
+
+ *mem_addr = MEM_B1EA;
+ asm("sync");
+ mem_end = *mem_data;
+ asm("sync");
+ for(loop = 0; loop < 1000; loop++);
+
+ mem_size = mem_end - mem_start + 0x100000;
+ }
+
+ /* Confirm bank 2 has DRAM memory */
+ if ((mem_mben & 0x20000000) &&
+ ((mem_type & 0xc000000) == 0x4000000)) {
+ *mem_addr = MEM_B2SA;
+ asm("sync");
+ mem_start = *mem_data;
+ asm("sync");
+ for(loop = 0; loop < 1000; loop++);
+
+ *mem_addr = MEM_B2EA;
+ asm("sync");
+ mem_end = *mem_data;
+ asm("sync");
+ for(loop = 0; loop < 1000; loop++);
+
+ mem_size += mem_end - mem_start + 0x100000;
+ }
+ return mem_size;
+}
+
+unsigned long
+load_kernel(unsigned long load_addr, int num_words, unsigned long cksum,
+ void *ign1, void *ign2)
+{
+ int csr0;
+ int csr_id;
+ int pci_devfn;
+ int found_multi = 0;
+ unsigned short vendor;
+ unsigned short device;
+ unsigned short command;
+ unsigned char header_type;
+ unsigned int bar0;
+ volatile int *pif_addr = (int *)0xff500000;
+ volatile int *pif_data = (int *)0xff500004;
+
+ /*
+ * Gah, these firmware guys need to learn that hardware
+ * byte swapping is evil! Disable all hardware byte
+ * swapping so it doesn't hurt anyone.
+ */
+ *pif_addr = PLBMIFOPT;
+ asm("sync");
+ *pif_data = 0x00000000;
+ asm("sync");
+
+ /* Search out and turn off the PcNet ethernet boot device. */
+ for (pci_devfn = 1; pci_devfn < 0xff; pci_devfn++) {
+ if (PCI_FUNC(pci_devfn) && !found_multi)
+ continue;
+
+ cpc700_pcibios_read_config_byte(0, pci_devfn,
+ PCI_HEADER_TYPE, &header_type);
+
+ if (!PCI_FUNC(pci_devfn))
+ found_multi = header_type & 0x80;
+
+ cpc700_pcibios_read_config_word(0, pci_devfn, PCI_VENDOR_ID,
+ &vendor);
+
+ if (vendor != 0xffff) {
+ cpc700_pcibios_read_config_word(0, pci_devfn,
+ PCI_DEVICE_ID, &device);
+
+ /* If this PCI device is the Lance PCNet board then turn it off */
+ if ((vendor == PCI_VENDOR_ID_AMD) &&
+ (device == PCI_DEVICE_ID_AMD_LANCE)) {
+
+ /* Turn on I/O Space on the board. */
+ cpc700_pcibios_read_config_word(0, pci_devfn,
+ PCI_COMMAND, &command);
+ command |= 0x1;
+ cpc700_pcibios_write_config_word(0, pci_devfn,
+ PCI_COMMAND, command);
+
+ /* Get the I/O space address */
+ cpc700_pcibios_read_config_dword(0, pci_devfn,
+ PCI_BASE_ADDRESS_0, &bar0);
+ bar0 &= 0xfffffffe;
+
+ /* Reset the PCNet Board */
+ inl (bar0+PCNET32_DWIO_RESET);
+ inw (bar0+PCNET32_WIO_RESET);
+
+ /* First do a work oriented read of csr0. If the value is
+ * 4 then this is the correct mode to access the board.
+ * If not try a double word ortiented read.
+ */
+ outw(0, bar0 + PCNET32_WIO_RAP);
+ csr0 = inw(bar0 + PCNET32_WIO_RDP);
+
+ if (csr0 == 4) {
+ /* Check the Chip id register */
+ outw(88, bar0 + PCNET32_WIO_RAP);
+ csr_id = inw(bar0 + PCNET32_WIO_RDP);
+
+ if (csr_id) {
+ /* This is the valid mode - set the stop bit */
+ outw(0, bar0 + PCNET32_WIO_RAP);
+ outw(csr0, bar0 + PCNET32_WIO_RDP);
+ }
+ } else {
+ outl(0, bar0 + PCNET32_DWIO_RAP);
+ csr0 = inl(bar0 + PCNET32_DWIO_RDP);
+ if (csr0 == 4) {
+ /* Check the Chip id register */
+ outl(88, bar0 + PCNET32_WIO_RAP);
+ csr_id = inl(bar0 + PCNET32_WIO_RDP);
+
+ if (csr_id) {
+ /* This is the valid mode - set the stop bit*/
+ outl(0, bar0 + PCNET32_WIO_RAP);
+ outl(csr0, bar0 + PCNET32_WIO_RDP);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ return decompress_kernel(load_addr, num_words, cksum);
+}
diff --git a/arch/ppc/boot/simple/misc.c b/arch/ppc/boot/simple/misc.c
new file mode 100644
index 0000000..ab0f990
--- /dev/null
+++ b/arch/ppc/boot/simple/misc.c
@@ -0,0 +1,284 @@
+/*
+ * arch/ppc/simple/misc.c
+ *
+ * Misc. bootloader code for many machines. This assumes you have are using
+ * a 6xx/7xx/74xx CPU in your machine. This assumes the chunk of memory
+ * below 8MB is free. Finally, it assumes you have a NS16550-style uart for
+ * your serial console. If a machine meets these requirements, it can quite
+ * likely use this code during boot.
+ *
+ * Author: Matt Porter <mporter@mvista.com>
+ * Derived from arch/ppc/boot/prep/misc.c
+ *
+ * 2001 (c) MontaVista, Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+
+#include <linux/types.h>
+#include <linux/config.h>
+#include <linux/string.h>
+
+#include <asm/page.h>
+#include <asm/mmu.h>
+#include <asm/bootinfo.h>
+#ifdef CONFIG_44x
+#include <asm/ibm4xx.h>
+#endif
+#include <asm/reg.h>
+
+#include "nonstdio.h"
+
+/* Default cmdline */
+#ifdef CONFIG_CMDLINE
+#define CMDLINE CONFIG_CMDLINE
+#else
+#define CMDLINE ""
+#endif
+
+/* Keyboard (and VGA console)? */
+#ifdef CONFIG_VGA_CONSOLE
+#define HAS_KEYB 1
+#else
+#define HAS_KEYB 0
+#endif
+
+/* Will / Can the user give input?
+ * Val Henson has requested that Gemini doesn't wait for the
+ * user to edit the cmdline or not.
+ */
+#if (defined(CONFIG_SERIAL_8250_CONSOLE) \
+ || defined(CONFIG_VGA_CONSOLE) \
+ || defined(CONFIG_SERIAL_MPC52xx_CONSOLE) \
+ || defined(CONFIG_SERIAL_MPSC_CONSOLE)) \
+ && !defined(CONFIG_GEMINI)
+#define INTERACTIVE_CONSOLE 1
+#endif
+
+char *avail_ram;
+char *end_avail;
+char *zimage_start;
+char cmd_preset[] = CMDLINE;
+char cmd_buf[256];
+char *cmd_line = cmd_buf;
+int keyb_present = HAS_KEYB;
+int zimage_size;
+
+unsigned long com_port;
+unsigned long initrd_size = 0;
+
+/* The linker tells us various locations in the image */
+extern char __image_begin, __image_end;
+extern char __ramdisk_begin, __ramdisk_end;
+extern char _end[];
+/* Original location */
+extern unsigned long start;
+
+extern int CRT_tstc(void);
+extern unsigned long serial_init(int chan, void *ignored);
+extern void serial_close(unsigned long com_port);
+extern void gunzip(void *, int, unsigned char *, int *);
+extern void serial_fixups(void);
+
+/* Allow get_mem_size to be hooked into. This is the default. */
+unsigned long __attribute__ ((weak))
+get_mem_size(void)
+{
+ return 0;
+}
+
+struct bi_record *
+decompress_kernel(unsigned long load_addr, int num_words, unsigned long cksum)
+{
+#ifdef INTERACTIVE_CONSOLE
+ int timer = 0;
+ char ch;
+#endif
+ char *cp;
+ struct bi_record *rec;
+ unsigned long initrd_loc = 0, TotalMemory = 0;
+
+#if defined(CONFIG_SERIAL_8250_CONSOLE) || defined(CONFIG_SERIAL_MPSC_CONSOLE)
+ com_port = serial_init(0, NULL);
+#endif
+
+#if defined(CONFIG_44x) && defined(PPC44x_EMAC0_MR0)
+ /* Reset MAL */
+ mtdcr(DCRN_MALCR(DCRN_MAL_BASE), MALCR_MMSR);
+ /* Wait for reset */
+ while (mfdcr(DCRN_MALCR(DCRN_MAL_BASE)) & MALCR_MMSR) {};
+ /* Reset EMAC */
+ *(volatile unsigned long *)PPC44x_EMAC0_MR0 = 0x20000000;
+ __asm__ __volatile__("eieio");
+#endif
+
+ /*
+ * Call get_mem_size(), which is memory controller dependent,
+ * and we must have the correct file linked in here.
+ */
+ TotalMemory = get_mem_size();
+
+ /* assume the chunk below 8M is free */
+ end_avail = (char *)0x00800000;
+
+ /*
+ * Reveal where we were loaded at and where we
+ * were relocated to.
+ */
+ puts("loaded at: "); puthex(load_addr);
+ puts(" "); puthex((unsigned long)(load_addr + (4*num_words)));
+ puts("\n");
+ if ( (unsigned long)load_addr != (unsigned long)&start )
+ {
+ puts("relocated to: "); puthex((unsigned long)&start);
+ puts(" ");
+ puthex((unsigned long)((unsigned long)&start + (4*num_words)));
+ puts("\n");
+ }
+
+ /*
+ * We link ourself to 0x00800000. When we run, we relocate
+ * ourselves there. So we just need __image_begin for the
+ * start. -- Tom
+ */
+ zimage_start = (char *)(unsigned long)(&__image_begin);
+ zimage_size = (unsigned long)(&__image_end) -
+ (unsigned long)(&__image_begin);
+
+ initrd_size = (unsigned long)(&__ramdisk_end) -
+ (unsigned long)(&__ramdisk_begin);
+
+ /*
+ * The zImage and initrd will be between start and _end, so they've
+ * already been moved once. We're good to go now. -- Tom
+ */
+ avail_ram = (char *)PAGE_ALIGN((unsigned long)_end);
+ puts("zimage at: "); puthex((unsigned long)zimage_start);
+ puts(" "); puthex((unsigned long)(zimage_size+zimage_start));
+ puts("\n");
+
+ if ( initrd_size ) {
+ puts("initrd at: ");
+ puthex((unsigned long)(&__ramdisk_begin));
+ puts(" "); puthex((unsigned long)(&__ramdisk_end));puts("\n");
+ }
+
+ avail_ram = (char *)0x00400000;
+ end_avail = (char *)0x00800000;
+ puts("avail ram: "); puthex((unsigned long)avail_ram); puts(" ");
+ puthex((unsigned long)end_avail); puts("\n");
+
+ if (keyb_present)
+ CRT_tstc(); /* Forces keyboard to be initialized */
+#ifdef CONFIG_GEMINI
+ /*
+ * If cmd_line is empty and cmd_preset is not, copy cmd_preset
+ * to cmd_line. This way we can override cmd_preset with the
+ * command line from Smon.
+ */
+
+ if ( (cmd_line[0] == '\0') && (cmd_preset[0] != '\0'))
+ memcpy (cmd_line, cmd_preset, sizeof(cmd_preset));
+#endif
+
+ /* Display standard Linux/PPC boot prompt for kernel args */
+ puts("\nLinux/PPC load: ");
+ cp = cmd_line;
+ memcpy (cmd_line, cmd_preset, sizeof(cmd_preset));
+ while ( *cp ) putc(*cp++);
+
+#ifdef INTERACTIVE_CONSOLE
+ /*
+ * If they have a console, allow them to edit the command line.
+ * Otherwise, don't bother wasting the five seconds.
+ */
+ while (timer++ < 5*1000) {
+ if (tstc()) {
+ while ((ch = getc()) != '\n' && ch != '\r') {
+ /* Test for backspace/delete */
+ if (ch == '\b' || ch == '\177') {
+ if (cp != cmd_line) {
+ cp--;
+ puts("\b \b");
+ }
+ /* Test for ^x/^u (and wipe the line) */
+ } else if (ch == '\030' || ch == '\025') {
+ while (cp != cmd_line) {
+ cp--;
+ puts("\b \b");
+ }
+ } else {
+ *cp++ = ch;
+ putc(ch);
+ }
+ }
+ break; /* Exit 'timer' loop */
+ }
+ udelay(1000); /* 1 msec */
+ }
+ *cp = 0;
+#endif
+ puts("\n");
+
+ puts("Uncompressing Linux...");
+ gunzip(0x0, 0x400000, zimage_start, &zimage_size);
+ puts("done.\n");
+
+ /* get the bi_rec address */
+ rec = bootinfo_addr(zimage_size);
+
+ /* We need to make sure that the initrd and bi_recs do not
+ * overlap. */
+ if ( initrd_size ) {
+ unsigned long rec_loc = (unsigned long) rec;
+ initrd_loc = (unsigned long)(&__ramdisk_begin);
+ /* If the bi_recs are in the middle of the current
+ * initrd, move the initrd to the next MB
+ * boundary. */
+ if ((rec_loc > initrd_loc) &&
+ ((initrd_loc + initrd_size) > rec_loc)) {
+ initrd_loc = _ALIGN((unsigned long)(zimage_size)
+ + (2 << 20) - 1, (2 << 20));
+ memmove((void *)initrd_loc, &__ramdisk_begin,
+ initrd_size);
+ puts("initrd moved: "); puthex(initrd_loc);
+ puts(" "); puthex(initrd_loc + initrd_size);
+ puts("\n");
+ }
+ }
+
+ bootinfo_init(rec);
+ if ( TotalMemory )
+ bootinfo_append(BI_MEMSIZE, sizeof(int), (void*)&TotalMemory);
+
+ bootinfo_append(BI_CMD_LINE, strlen(cmd_line)+1, (void*)cmd_line);
+
+ /* add a bi_rec for the initrd if it exists */
+ if (initrd_size) {
+ unsigned long initrd[2];
+
+ initrd[0] = initrd_loc;
+ initrd[1] = initrd_size;
+
+ bootinfo_append(BI_INITRD, sizeof(initrd), &initrd);
+ }
+ puts("Now booting the kernel\n");
+ serial_close(com_port);
+
+ return rec;
+}
+
+void __attribute__ ((weak))
+board_isa_init(void)
+{
+}
+
+/* Allow decompress_kernel to be hooked into. This is the default. */
+void * __attribute__ ((weak))
+load_kernel(unsigned long load_addr, int num_words, unsigned long cksum,
+ void *ign1, void *ign2)
+{
+ board_isa_init();
+ return decompress_kernel(load_addr, num_words, cksum);
+}
diff --git a/arch/ppc/boot/simple/mpc10x_memory.c b/arch/ppc/boot/simple/mpc10x_memory.c
new file mode 100644
index 0000000..977daed
--- /dev/null
+++ b/arch/ppc/boot/simple/mpc10x_memory.c
@@ -0,0 +1,111 @@
+/*
+ * arch/ppc/boot/common/mpc10x_common.c
+ *
+ * A routine to find out how much memory the machine has.
+ *
+ * Based on:
+ * arch/ppc/kernel/mpc10x_common.c
+ *
+ * Author: Mark A. Greer
+ * mgreer@mvista.com
+ *
+ * 2001-2002 (c) MontaVista, Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+
+#include <linux/pci.h>
+#include <asm/types.h>
+#include <asm/io.h>
+#include "mpc10x.h"
+
+/*
+ * *** WARNING - A BAT MUST be set to access the PCI config addr/data regs ***
+ */
+
+/*
+ * PCI config space macros, similar to indirect_xxx and early_xxx macros.
+ * We assume bus 0.
+ */
+#define MPC10X_CFG_read(val, addr, type, op) *val = op((type)(addr))
+#define MPC10X_CFG_write(val, addr, type, op) op((type *)(addr), (val))
+
+#define MPC10X_PCI_OP(rw, size, type, op, mask) \
+static void \
+mpc10x_##rw##_config_##size(unsigned int *cfg_addr, \
+ unsigned int *cfg_data, int devfn, int offset, \
+ type val) \
+{ \
+ out_be32(cfg_addr, \
+ ((offset & 0xfc) << 24) | (devfn << 16) \
+ | (0 << 8) | 0x80); \
+ MPC10X_CFG_##rw(val, cfg_data + (offset & mask), type, op); \
+ return; \
+}
+
+MPC10X_PCI_OP(read, byte, u8 *, in_8, 3)
+MPC10X_PCI_OP(read, dword, u32 *, in_le32, 0)
+
+/*
+ * Read the memory controller registers to determine the amount of memory in
+ * the system. This assumes that the firmware has correctly set up the memory
+ * controller registers. On CONFIG_PPC_PREP, we know we are being called
+ * under a PReP memory map. On all other machines, we assume we are under
+ * a CHRP memory map. Further, on CONFIG_PPC_MULTIPLATFORM we must rename
+ * this function.
+ */
+#ifdef CONFIG_PPC_MULTIPLATFORM
+#define get_mem_size mpc10x_get_mem_size
+#endif
+unsigned long
+get_mem_size(void)
+{
+ unsigned int *config_addr, *config_data, val;
+ unsigned long start, end, total, offset;
+ int i;
+ unsigned char bank_enables;
+
+#ifdef CONFIG_PPC_PREP
+ config_addr = (unsigned int *)MPC10X_MAPA_CNFG_ADDR;
+ config_data = (unsigned int *)MPC10X_MAPA_CNFG_DATA;
+#else
+ config_addr = (unsigned int *)MPC10X_MAPB_CNFG_ADDR;
+ config_data = (unsigned int *)MPC10X_MAPB_CNFG_DATA;
+#endif
+
+ mpc10x_read_config_byte(config_addr, config_data, PCI_DEVFN(0,0),
+ MPC10X_MCTLR_MEM_BANK_ENABLES, &bank_enables);
+
+ total = 0;
+
+ for (i = 0; i < 8; i++) {
+ if (bank_enables & (1 << i)) {
+ offset = MPC10X_MCTLR_MEM_START_1 + ((i > 3) ? 4 : 0);
+ mpc10x_read_config_dword(config_addr, config_data,
+ PCI_DEVFN(0,0), offset, &val);
+ start = (val >> ((i & 3) << 3)) & 0xff;
+
+ offset = MPC10X_MCTLR_EXT_MEM_START_1 + ((i>3) ? 4 : 0);
+ mpc10x_read_config_dword(config_addr, config_data,
+ PCI_DEVFN(0,0), offset, &val);
+ val = (val >> ((i & 3) << 3)) & 0x03;
+ start = (val << 28) | (start << 20);
+
+ offset = MPC10X_MCTLR_MEM_END_1 + ((i > 3) ? 4 : 0);
+ mpc10x_read_config_dword(config_addr, config_data,
+ PCI_DEVFN(0,0), offset, &val);
+ end = (val >> ((i & 3) << 3)) & 0xff;
+
+ offset = MPC10X_MCTLR_EXT_MEM_END_1 + ((i > 3) ? 4 : 0);
+ mpc10x_read_config_dword(config_addr, config_data,
+ PCI_DEVFN(0,0), offset, &val);
+ val = (val >> ((i & 3) << 3)) & 0x03;
+ end = (val << 28) | (end << 20) | 0xfffff;
+
+ total += (end - start + 1);
+ }
+ }
+
+ return total;
+}
diff --git a/arch/ppc/boot/simple/mpc52xx_tty.c b/arch/ppc/boot/simple/mpc52xx_tty.c
new file mode 100644
index 0000000..3acc6b7
--- /dev/null
+++ b/arch/ppc/boot/simple/mpc52xx_tty.c
@@ -0,0 +1,140 @@
+/*
+ * arch/ppc/boot/simple/mpc52xx_tty.c
+ *
+ * Minimal serial functions needed to send messages out a MPC52xx
+ * Programmable Serial Controller (PSC).
+ *
+ * Author: Dale Farnsworth <dfarnsworth@mvista.com>
+ *
+ * 2003-2004 (c) MontaVista, Software, Inc. This file is licensed under the
+ * terms of the GNU General Public License version 2. This program is licensed
+ * "as is" without any warranty of any kind, whether express or implied.
+ */
+
+#include <linux/config.h>
+#include <linux/types.h>
+#include <asm/uaccess.h>
+#include <asm/mpc52xx.h>
+#include <asm/mpc52xx_psc.h>
+#include <asm/serial.h>
+#include <asm/io.h>
+#include <asm/time.h>
+
+
+#ifdef MPC52xx_PF_CONSOLE_PORT
+#define MPC52xx_CONSOLE MPC52xx_PSCx_OFFSET(MPC52xx_PF_CONSOLE_PORT)
+#define MPC52xx_PSC_CONFIG_SHIFT ((MPC52xx_PF_CONSOLE_PORT-1)<<2)
+#else
+#error "MPC52xx_PF_CONSOLE_PORT not defined"
+#endif
+
+static struct mpc52xx_psc __iomem *psc =
+ (struct mpc52xx_psc __iomem *) MPC52xx_PA(MPC52xx_CONSOLE);
+
+/* The decrementer counts at the system bus clock frequency
+ * divided by four. The most accurate time base is connected to the
+ * rtc. We read the decrementer change during one rtc tick
+ * and multiply by 4 to get the system bus clock frequency. Since a
+ * rtc tick is one seconds, and that's pretty long, we change the rtc
+ * dividers temporarly to set them 64x faster ;)
+ */
+static int
+mpc52xx_ipbfreq(void)
+{
+ struct mpc52xx_rtc __iomem *rtc =
+ (struct mpc52xx_rtc __iomem *) MPC52xx_PA(MPC52xx_RTC_OFFSET);
+ struct mpc52xx_cdm __iomem *cdm =
+ (struct mpc52xx_cdm __iomem *) MPC52xx_PA(MPC52xx_CDM_OFFSET);
+ int current_time, previous_time;
+ int tbl_start, tbl_end;
+ int xlbfreq, ipbfreq;
+
+ out_be32(&rtc->dividers, 0x8f1f0000); /* Set RTC 64x faster */
+ previous_time = in_be32(&rtc->time);
+ while ((current_time = in_be32(&rtc->time)) == previous_time) ;
+ tbl_start = get_tbl();
+ previous_time = current_time;
+ while ((current_time = in_be32(&rtc->time)) == previous_time) ;
+ tbl_end = get_tbl();
+ out_be32(&rtc->dividers, 0xffff0000); /* Restore RTC */
+
+ xlbfreq = (tbl_end - tbl_start) << 8;
+ ipbfreq = (in_8(&cdm->ipb_clk_sel) & 1) ? xlbfreq / 2 : xlbfreq;
+
+ return ipbfreq;
+}
+
+unsigned long
+serial_init(int ignored, void *ignored2)
+{
+ struct mpc52xx_gpio __iomem *gpio =
+ (struct mpc52xx_gpio __iomem *) MPC52xx_PA(MPC52xx_GPIO_OFFSET);
+ int divisor;
+ int mode1;
+ int mode2;
+ u32 val32;
+
+ static int been_here = 0;
+
+ if (been_here)
+ return 0;
+
+ been_here = 1;
+
+ val32 = in_be32(&gpio->port_config);
+ val32 &= ~(0x7 << MPC52xx_PSC_CONFIG_SHIFT);
+ val32 |= MPC52xx_GPIO_PSC_CONFIG_UART_WITHOUT_CD
+ << MPC52xx_PSC_CONFIG_SHIFT;
+ out_be32(&gpio->port_config, val32);
+
+ out_8(&psc->command, MPC52xx_PSC_RST_TX
+ | MPC52xx_PSC_RX_DISABLE | MPC52xx_PSC_TX_ENABLE);
+ out_8(&psc->command, MPC52xx_PSC_RST_RX);
+
+ out_be32(&psc->sicr, 0x0);
+ out_be16(&psc->mpc52xx_psc_clock_select, 0xdd00);
+ out_be16(&psc->tfalarm, 0xf8);
+
+ out_8(&psc->command, MPC52xx_PSC_SEL_MODE_REG_1
+ | MPC52xx_PSC_RX_ENABLE
+ | MPC52xx_PSC_TX_ENABLE);
+
+ divisor = ((mpc52xx_ipbfreq()
+ / (CONFIG_SERIAL_MPC52xx_CONSOLE_BAUD * 16)) + 1) >> 1;
+
+ mode1 = MPC52xx_PSC_MODE_8_BITS | MPC52xx_PSC_MODE_PARNONE
+ | MPC52xx_PSC_MODE_ERR;
+ mode2 = MPC52xx_PSC_MODE_ONE_STOP;
+
+ out_8(&psc->ctur, divisor>>8);
+ out_8(&psc->ctlr, divisor);
+ out_8(&psc->command, MPC52xx_PSC_SEL_MODE_REG_1);
+ out_8(&psc->mode, mode1);
+ out_8(&psc->mode, mode2);
+
+ return 0; /* ignored */
+}
+
+void
+serial_putc(void *ignored, const char c)
+{
+ serial_init(0, NULL);
+
+ while (!(in_be16(&psc->mpc52xx_psc_status) & MPC52xx_PSC_SR_TXEMP)) ;
+ out_8(&psc->mpc52xx_psc_buffer_8, c);
+ while (!(in_be16(&psc->mpc52xx_psc_status) & MPC52xx_PSC_SR_TXEMP)) ;
+}
+
+char
+serial_getc(void *ignored)
+{
+ while (!(in_be16(&psc->mpc52xx_psc_status) & MPC52xx_PSC_SR_RXRDY)) ;
+
+ return in_8(&psc->mpc52xx_psc_buffer_8);
+}
+
+int
+serial_tstc(void *ignored)
+{
+ return (in_be16(&psc->mpc52xx_psc_status) & MPC52xx_PSC_SR_RXRDY) != 0;
+}
diff --git a/arch/ppc/boot/simple/mv64x60_tty.c b/arch/ppc/boot/simple/mv64x60_tty.c
new file mode 100644
index 0000000..5b45eb4
--- /dev/null
+++ b/arch/ppc/boot/simple/mv64x60_tty.c
@@ -0,0 +1,360 @@
+/*
+ * arch/ppc/boot/simple/mv64x60_tty.c
+ *
+ * Bootloader version of the embedded MPSC/UART driver for the Marvell 64x60.
+ * Note: Due to a GT64260A erratum, DMA will be used for UART input (via SDMA).
+ *
+ * Author: Mark A. Greer <mgreer@mvista.com>
+ *
+ * 2001 (c) MontaVista Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+
+/* This code assumes that the data cache has been disabled (L1, L2, L3). */
+
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/serial_reg.h>
+#include <asm/serial.h>
+#include <asm/io.h>
+#include <asm/mv64x60_defs.h>
+#include <mpsc_defs.h>
+
+u32 mv64x60_console_baud = 9600;
+u32 mv64x60_mpsc_clk_src = 8; /* TCLK */
+u32 mv64x60_mpsc_clk_freq = 100000000;
+
+extern void udelay(long);
+static void stop_dma(int chan);
+
+static void __iomem *mv64x60_base = (void __iomem *)CONFIG_MV64X60_NEW_BASE;
+
+struct sdma_regs {
+ u32 sdc;
+ u32 sdcm;
+ u32 rx_desc;
+ u32 rx_buf_ptr;
+ u32 scrdp;
+ u32 tx_desc;
+ u32 sctdp;
+ u32 sftdp;
+};
+
+static struct sdma_regs sdma_regs[2];
+
+#define SDMA_REGS_INIT(s, reg_base) { \
+ (s)->sdc = (reg_base) + SDMA_SDC; \
+ (s)->sdcm = (reg_base) + SDMA_SDCM; \
+ (s)->rx_desc = (reg_base) + SDMA_RX_DESC; \
+ (s)->rx_buf_ptr = (reg_base) + SDMA_RX_BUF_PTR; \
+ (s)->scrdp = (reg_base) + SDMA_SCRDP; \
+ (s)->tx_desc = (reg_base) + SDMA_TX_DESC; \
+ (s)->sctdp = (reg_base) + SDMA_SCTDP; \
+ (s)->sftdp = (reg_base) + SDMA_SFTDP; \
+}
+
+static u32 mpsc_base[2] = { MV64x60_MPSC_0_OFFSET, MV64x60_MPSC_1_OFFSET };
+
+struct mv64x60_rx_desc {
+ u16 bufsize;
+ u16 bytecnt;
+ u32 cmd_stat;
+ u32 next_desc_ptr;
+ u32 buffer;
+};
+
+struct mv64x60_tx_desc {
+ u16 bytecnt;
+ u16 shadow;
+ u32 cmd_stat;
+ u32 next_desc_ptr;
+ u32 buffer;
+};
+
+#define MAX_RESET_WAIT 10000
+#define MAX_TX_WAIT 10000
+
+#define RX_NUM_DESC 2
+#define TX_NUM_DESC 2
+
+#define RX_BUF_SIZE 32
+#define TX_BUF_SIZE 32
+
+static struct mv64x60_rx_desc rd[2][RX_NUM_DESC] __attribute__ ((aligned(32)));
+static struct mv64x60_tx_desc td[2][TX_NUM_DESC] __attribute__ ((aligned(32)));
+
+static char rx_buf[2][RX_NUM_DESC * RX_BUF_SIZE] __attribute__ ((aligned(32)));
+static char tx_buf[2][TX_NUM_DESC * TX_BUF_SIZE] __attribute__ ((aligned(32)));
+
+static int cur_rd[2] = { 0, 0 };
+static int cur_td[2] = { 0, 0 };
+
+static char chan_initialized[2] = { 0, 0 };
+
+
+#define RX_INIT_RDP(rdp) { \
+ (rdp)->bufsize = 2; \
+ (rdp)->bytecnt = 0; \
+ (rdp)->cmd_stat = SDMA_DESC_CMDSTAT_L | SDMA_DESC_CMDSTAT_F | \
+ SDMA_DESC_CMDSTAT_O; \
+}
+
+#ifdef CONFIG_MV64360
+static u32 cpu2mem_tab[MV64x60_CPU2MEM_WINDOWS][2] = {
+ { MV64x60_CPU2MEM_0_BASE, MV64x60_CPU2MEM_0_SIZE },
+ { MV64x60_CPU2MEM_1_BASE, MV64x60_CPU2MEM_1_SIZE },
+ { MV64x60_CPU2MEM_2_BASE, MV64x60_CPU2MEM_2_SIZE },
+ { MV64x60_CPU2MEM_3_BASE, MV64x60_CPU2MEM_3_SIZE }
+};
+
+static u32 com2mem_tab[MV64x60_CPU2MEM_WINDOWS][2] = {
+ { MV64360_MPSC2MEM_0_BASE, MV64360_MPSC2MEM_0_SIZE },
+ { MV64360_MPSC2MEM_1_BASE, MV64360_MPSC2MEM_1_SIZE },
+ { MV64360_MPSC2MEM_2_BASE, MV64360_MPSC2MEM_2_SIZE },
+ { MV64360_MPSC2MEM_3_BASE, MV64360_MPSC2MEM_3_SIZE }
+};
+
+static u32 dram_selects[MV64x60_CPU2MEM_WINDOWS] = { 0xe, 0xd, 0xb, 0x7 };
+#endif
+
+unsigned long
+serial_init(int chan, void *ignored)
+{
+ u32 mpsc_routing_base, sdma_base, brg_bcr, cdv;
+ int i;
+
+ chan = (chan == 1); /* default to chan 0 if anything but 1 */
+
+ if (chan_initialized[chan])
+ return chan;
+
+ chan_initialized[chan] = 1;
+
+ if (chan == 0) {
+ sdma_base = MV64x60_SDMA_0_OFFSET;
+ brg_bcr = MV64x60_BRG_0_OFFSET + BRG_BCR;
+ SDMA_REGS_INIT(&sdma_regs[0], MV64x60_SDMA_0_OFFSET);
+ } else {
+ sdma_base = MV64x60_SDMA_1_OFFSET;
+ brg_bcr = MV64x60_BRG_1_OFFSET + BRG_BCR;
+ SDMA_REGS_INIT(&sdma_regs[0], MV64x60_SDMA_1_OFFSET);
+ }
+
+ mpsc_routing_base = MV64x60_MPSC_ROUTING_OFFSET;
+
+ stop_dma(chan);
+
+ /* Set up ring buffers */
+ for (i=0; i<RX_NUM_DESC; i++) {
+ RX_INIT_RDP(&rd[chan][i]);
+ rd[chan][i].buffer = (u32)&rx_buf[chan][i * RX_BUF_SIZE];
+ rd[chan][i].next_desc_ptr = (u32)&rd[chan][i+1];
+ }
+ rd[chan][RX_NUM_DESC - 1].next_desc_ptr = (u32)&rd[chan][0];
+
+ for (i=0; i<TX_NUM_DESC; i++) {
+ td[chan][i].bytecnt = 0;
+ td[chan][i].shadow = 0;
+ td[chan][i].buffer = (u32)&tx_buf[chan][i * TX_BUF_SIZE];
+ td[chan][i].cmd_stat = SDMA_DESC_CMDSTAT_F|SDMA_DESC_CMDSTAT_L;
+ td[chan][i].next_desc_ptr = (u32)&td[chan][i+1];
+ }
+ td[chan][TX_NUM_DESC - 1].next_desc_ptr = (u32)&td[chan][0];
+
+ /* Set MPSC Routing */
+ out_le32(mv64x60_base + mpsc_routing_base + MPSC_MRR, 0x3ffffe38);
+
+#ifdef CONFIG_GT64260
+ out_le32(mv64x60_base + GT64260_MPP_SERIAL_PORTS_MULTIPLEX, 0x00001102);
+#else /* Must be MV64360 or MV64460 */
+ {
+ u32 enables, prot_bits, v;
+
+ /* Set up comm unit to memory mapping windows */
+ /* Note: Assumes MV64x60_CPU2MEM_WINDOWS == 4 */
+
+ enables = in_le32(mv64x60_base + MV64360_CPU_BAR_ENABLE) & 0xf;
+ prot_bits = 0;
+
+ for (i=0; i<MV64x60_CPU2MEM_WINDOWS; i++) {
+ if (!(enables & (1 << i))) {
+ v = in_le32(mv64x60_base + cpu2mem_tab[i][0]);
+ v = ((v & 0xffff) << 16) | (dram_selects[i] << 8);
+ out_le32(mv64x60_base + com2mem_tab[i][0], v);
+
+ v = in_le32(mv64x60_base + cpu2mem_tab[i][1]);
+ v = (v & 0xffff) << 16;
+ out_le32(mv64x60_base + com2mem_tab[i][1], v);
+
+ prot_bits |= (0x3 << (i << 1)); /* r/w access */
+ }
+ }
+
+ out_le32(mv64x60_base + MV64360_MPSC_0_REMAP, 0);
+ out_le32(mv64x60_base + MV64360_MPSC_1_REMAP, 0);
+ out_le32(mv64x60_base + MV64360_MPSC2MEM_ACC_PROT_0, prot_bits);
+ out_le32(mv64x60_base + MV64360_MPSC2MEM_ACC_PROT_1, prot_bits);
+ out_le32(mv64x60_base + MV64360_MPSC2MEM_BAR_ENABLE, enables);
+ }
+#endif
+
+ /* MPSC 0/1 Rx & Tx get clocks BRG0/1 */
+ out_le32(mv64x60_base + mpsc_routing_base + MPSC_RCRR, 0x00000100);
+ out_le32(mv64x60_base + mpsc_routing_base + MPSC_TCRR, 0x00000100);
+
+ /* clear pending interrupts */
+ out_le32(mv64x60_base + MV64x60_SDMA_INTR_OFFSET + SDMA_INTR_MASK, 0);
+
+ out_le32(mv64x60_base + SDMA_SCRDP + sdma_base, (int)&rd[chan][0]);
+ out_le32(mv64x60_base + SDMA_SCTDP + sdma_base,
+ (int)&td[chan][TX_NUM_DESC - 1]);
+ out_le32(mv64x60_base + SDMA_SFTDP + sdma_base,
+ (int)&td[chan][TX_NUM_DESC - 1]);
+
+ out_le32(mv64x60_base + SDMA_SDC + sdma_base,
+ SDMA_SDC_RFT | SDMA_SDC_SFM | SDMA_SDC_BLMR | SDMA_SDC_BLMT |
+ (3 << 12));
+
+ cdv = ((mv64x60_mpsc_clk_freq/(32*mv64x60_console_baud))-1);
+ out_le32(mv64x60_base + brg_bcr,
+ ((mv64x60_mpsc_clk_src << 18) | (1 << 16) | cdv));
+
+ /* Put MPSC into UART mode, no null modem, 16x clock mode */
+ out_le32(mv64x60_base + MPSC_MMCRL + mpsc_base[chan], 0x000004c4);
+ out_le32(mv64x60_base + MPSC_MMCRH + mpsc_base[chan], 0x04400400);
+
+ out_le32(mv64x60_base + MPSC_CHR_1 + mpsc_base[chan], 0);
+ out_le32(mv64x60_base + MPSC_CHR_9 + mpsc_base[chan], 0);
+ out_le32(mv64x60_base + MPSC_CHR_10 + mpsc_base[chan], 0);
+ out_le32(mv64x60_base + MPSC_CHR_3 + mpsc_base[chan], 4);
+ out_le32(mv64x60_base + MPSC_CHR_4 + mpsc_base[chan], 0);
+ out_le32(mv64x60_base + MPSC_CHR_5 + mpsc_base[chan], 0);
+ out_le32(mv64x60_base + MPSC_CHR_6 + mpsc_base[chan], 0);
+ out_le32(mv64x60_base + MPSC_CHR_7 + mpsc_base[chan], 0);
+ out_le32(mv64x60_base + MPSC_CHR_8 + mpsc_base[chan], 0);
+
+ /* 8 data bits, 1 stop bit */
+ out_le32(mv64x60_base + MPSC_MPCR + mpsc_base[chan], (3 << 12));
+ out_le32(mv64x60_base + SDMA_SDCM + sdma_base, SDMA_SDCM_ERD);
+ out_le32(mv64x60_base + MPSC_CHR_2 + mpsc_base[chan], MPSC_CHR_2_EH);
+
+ udelay(100);
+
+ return chan;
+}
+
+static void
+stop_dma(int chan)
+{
+ int i;
+
+ /* Abort MPSC Rx (aborting Tx messes things up) */
+ out_le32(mv64x60_base + MPSC_CHR_2 + mpsc_base[chan], MPSC_CHR_2_RA);
+
+ /* Abort SDMA Rx, Tx */
+ out_le32(mv64x60_base + sdma_regs[chan].sdcm,
+ SDMA_SDCM_AR | SDMA_SDCM_STD);
+
+ for (i=0; i<MAX_RESET_WAIT; i++) {
+ if ((in_le32(mv64x60_base + sdma_regs[chan].sdcm) &
+ (SDMA_SDCM_AR | SDMA_SDCM_AT)) == 0)
+ break;
+
+ udelay(100);
+ }
+}
+
+static int
+wait_for_ownership(int chan)
+{
+ int i;
+
+ for (i=0; i<MAX_TX_WAIT; i++) {
+ if ((in_le32(mv64x60_base + sdma_regs[chan].sdcm) &
+ SDMA_SDCM_TXD) == 0)
+ break;
+
+ udelay(1000);
+ }
+
+ return (i < MAX_TX_WAIT);
+}
+
+void
+serial_putc(unsigned long com_port, unsigned char c)
+{
+ struct mv64x60_tx_desc *tdp;
+
+ if (wait_for_ownership(com_port) == 0)
+ return;
+
+ tdp = &td[com_port][cur_td[com_port]];
+ if (++cur_td[com_port] >= TX_NUM_DESC)
+ cur_td[com_port] = 0;
+
+ *(unchar *)(tdp->buffer ^ 7) = c;
+ tdp->bytecnt = 1;
+ tdp->shadow = 1;
+ tdp->cmd_stat = SDMA_DESC_CMDSTAT_L | SDMA_DESC_CMDSTAT_F |
+ SDMA_DESC_CMDSTAT_O;
+
+ out_le32(mv64x60_base + sdma_regs[com_port].sctdp, (int)tdp);
+ out_le32(mv64x60_base + sdma_regs[com_port].sftdp, (int)tdp);
+ out_le32(mv64x60_base + sdma_regs[com_port].sdcm,
+ in_le32(mv64x60_base + sdma_regs[com_port].sdcm) |
+ SDMA_SDCM_TXD);
+}
+
+unsigned char
+serial_getc(unsigned long com_port)
+{
+ struct mv64x60_rx_desc *rdp;
+ unchar c = '\0';
+
+ rdp = &rd[com_port][cur_rd[com_port]];
+
+ if ((rdp->cmd_stat & (SDMA_DESC_CMDSTAT_O|SDMA_DESC_CMDSTAT_ES)) == 0) {
+ c = *(unchar *)(rdp->buffer ^ 7);
+ RX_INIT_RDP(rdp);
+ if (++cur_rd[com_port] >= RX_NUM_DESC)
+ cur_rd[com_port] = 0;
+ }
+
+ return c;
+}
+
+int
+serial_tstc(unsigned long com_port)
+{
+ struct mv64x60_rx_desc *rdp;
+ int loop_count = 0;
+ int rc = 0;
+
+ rdp = &rd[com_port][cur_rd[com_port]];
+
+ /* Go thru rcv desc's until empty looking for one with data (no error)*/
+ while (((rdp->cmd_stat & SDMA_DESC_CMDSTAT_O) == 0) &&
+ (loop_count++ < RX_NUM_DESC)) {
+
+ /* If there was an error, reinit the desc & continue */
+ if ((rdp->cmd_stat & SDMA_DESC_CMDSTAT_ES) != 0) {
+ RX_INIT_RDP(rdp);
+ if (++cur_rd[com_port] >= RX_NUM_DESC)
+ cur_rd[com_port] = 0;
+ rdp = (struct mv64x60_rx_desc *)rdp->next_desc_ptr;
+ } else {
+ rc = 1;
+ break;
+ }
+ }
+
+ return rc;
+}
+
+void
+serial_close(unsigned long com_port)
+{
+ stop_dma(com_port);
+}
diff --git a/arch/ppc/boot/simple/openbios.c b/arch/ppc/boot/simple/openbios.c
new file mode 100644
index 0000000..c732b6d
--- /dev/null
+++ b/arch/ppc/boot/simple/openbios.c
@@ -0,0 +1,37 @@
+/*
+ * arch/ppc/boot/simple/openbios.c
+ *
+ * 2005 (c) SYSGO AG - g.jaeger@sysgo.com
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without
+ * any warranty of any kind, whether express or implied.
+ *
+ * Derived from arch/ppc/boot/simple/pibs.c (from MontaVista)
+ */
+
+#include <linux/types.h>
+#include <linux/config.h>
+#include <linux/string.h>
+#include <asm/ppcboot.h>
+#include <platforms/4xx/ebony.h>
+
+extern unsigned long decompress_kernel(unsigned long load_addr, int num_words,
+ unsigned long cksum);
+
+/* We need to make sure that this is before the images to ensure
+ * that it's in a mapped location. */
+bd_t hold_resid_buf __attribute__ ((__section__ (".data.boot")));
+bd_t *hold_residual = &hold_resid_buf;
+
+void *
+load_kernel(unsigned long load_addr, int num_words, unsigned long cksum,
+ void *ign1, void *ign2)
+{
+ decompress_kernel(load_addr, num_words, cksum);
+
+ /* simply copy the MAC addresses */
+ memcpy(hold_residual->bi_enetaddr, (char *)EBONY_OPENBIOS_MAC_BASE, 6);
+ memcpy(hold_residual->bi_enet1addr, (char *)(EBONY_OPENBIOS_MAC_BASE+EBONY_OPENBIOS_MAC_OFFSET), 6);
+
+ return (void *)hold_residual;
+}
diff --git a/arch/ppc/boot/simple/pci.c b/arch/ppc/boot/simple/pci.c
new file mode 100644
index 0000000..b0f673c
--- /dev/null
+++ b/arch/ppc/boot/simple/pci.c
@@ -0,0 +1,274 @@
+/* Stand alone funtions for QSpan Tundra support.
+ */
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <asm/mpc8xx.h>
+
+extern void puthex(unsigned long val);
+extern void puts(const char *);
+
+/* To map PCI devices, you first write 0xffffffff into the device
+ * base address registers. When the register is read back, the
+ * number of most significant '1' bits describes the amount of address
+ * space needed for mapping. If the most significant bit is not set,
+ * either the device does not use that address register, or it has
+ * a fixed address that we can't change. After the address is assigned,
+ * the command register has to be written to enable the card.
+ */
+typedef struct {
+ u_char pci_bus;
+ u_char pci_devfn;
+ ushort pci_command;
+ uint pci_addrs[6];
+} pci_map_t;
+
+/* We should probably dynamically allocate these structures.
+*/
+#define MAX_PCI_DEVS 32
+int pci_dev_cnt;
+pci_map_t pci_map[MAX_PCI_DEVS];
+
+void pci_conf_write(int bus, int device, int func, int reg, uint writeval);
+void pci_conf_read(int bus, int device, int func, int reg, void *readval);
+void probe_addresses(int bus, int devfn);
+void map_pci_addrs(void);
+
+extern int
+qs_pci_read_config_byte(unsigned char bus, unsigned char dev_fn,
+ unsigned char offset, unsigned char *val);
+extern int
+qs_pci_read_config_word(unsigned char bus, unsigned char dev_fn,
+ unsigned char offset, unsigned short *val);
+extern int
+qs_pci_read_config_dword(unsigned char bus, unsigned char dev_fn,
+ unsigned char offset, unsigned int *val);
+extern int
+qs_pci_write_config_byte(unsigned char bus, unsigned char dev_fn,
+ unsigned char offset, unsigned char val);
+extern int
+qs_pci_write_config_word(unsigned char bus, unsigned char dev_fn,
+ unsigned char offset, unsigned short val);
+extern int
+qs_pci_write_config_dword(unsigned char bus, unsigned char dev_fn,
+ unsigned char offset, unsigned int val);
+
+
+/* This is a really stripped version of PCI bus scan. All we are
+ * looking for are devices that exist.
+ */
+void
+pci_scanner(int addr_probe)
+{
+ unsigned int devfn, l, class, bus_number;
+ unsigned char hdr_type, is_multi;
+
+ is_multi = 0;
+ bus_number = 0;
+ for (devfn = 0; devfn < 0xff; ++devfn) {
+ /* The device numbers are comprised of upper 5 bits of
+ * device number and lower 3 bits of multi-function number.
+ */
+ if ((devfn & 7) && !is_multi) {
+ /* Don't scan multifunction addresses if this is
+ * not a multifunction device.
+ */
+ continue;
+ }
+
+ /* Read the header to determine card type.
+ */
+ qs_pci_read_config_byte(bus_number, devfn, PCI_HEADER_TYPE,
+ &hdr_type);
+
+ /* If this is a base device number, check the header to
+ * determine if it is mulifunction.
+ */
+ if ((devfn & 7) == 0)
+ is_multi = hdr_type & 0x80;
+
+ /* Check to see if the board is really in the slot.
+ */
+ qs_pci_read_config_dword(bus_number, devfn, PCI_VENDOR_ID, &l);
+ /* some broken boards return 0 if a slot is empty: */
+ if (l == 0xffffffff || l == 0x00000000 || l == 0x0000ffff ||
+ l == 0xffff0000) {
+ /* Nothing there.
+ */
+ is_multi = 0;
+ continue;
+ }
+
+ /* If we are not performing an address probe,
+ * just simply print out some information.
+ */
+ if (!addr_probe) {
+ qs_pci_read_config_dword(bus_number, devfn,
+ PCI_CLASS_REVISION, &class);
+
+ class >>= 8; /* upper 3 bytes */
+
+#if 0
+ printf("Found (%3d:%d): vendor 0x%04x, device 0x%04x, class 0x%06x\n",
+ (devfn >> 3), (devfn & 7),
+ (l & 0xffff), (l >> 16) & 0xffff, class);
+#else
+ puts("Found ("); puthex(devfn >> 3);
+ puts(":"); puthex(devfn & 7);
+ puts("): vendor "); puthex(l & 0xffff);
+ puts(", device "); puthex((l >> 16) & 0xffff);
+ puts(", class "); puthex(class); puts("\n");
+#endif
+ }
+ else {
+ /* If this is a "normal" device, build address list.
+ */
+ if ((hdr_type & 0x7f) == PCI_HEADER_TYPE_NORMAL)
+ probe_addresses(bus_number, devfn);
+ }
+ }
+
+ /* Now map the boards.
+ */
+ if (addr_probe)
+ map_pci_addrs();
+}
+
+/* Probe addresses for the specified device. This is a destructive
+ * operation because it writes the registers.
+ */
+void
+probe_addresses(bus, devfn)
+{
+ int i;
+ uint pciaddr;
+ ushort pcicmd;
+ pci_map_t *pm;
+
+ if (pci_dev_cnt >= MAX_PCI_DEVS) {
+ puts("Too many PCI devices\n");
+ return;
+ }
+
+ pm = &pci_map[pci_dev_cnt++];
+
+ pm->pci_bus = bus;
+ pm->pci_devfn = devfn;
+
+ for (i=0; i<6; i++) {
+ qs_pci_write_config_dword(bus, devfn, PCI_BASE_ADDRESS_0 + (i * 4), -1);
+ qs_pci_read_config_dword(bus, devfn, PCI_BASE_ADDRESS_0 + (i * 4),
+ &pciaddr);
+ pm->pci_addrs[i] = pciaddr;
+ qs_pci_read_config_word(bus, devfn, PCI_COMMAND, &pcicmd);
+ pm->pci_command = pcicmd;
+ }
+}
+
+/* Map the cards into the PCI space. The PCI has separate memory
+ * and I/O spaces. In addition, some memory devices require mapping
+ * below 1M. The least significant 4 bits of the address register
+ * provide information. If this is an I/O device, only the LS bit
+ * is used to indicate that, so I/O devices can be mapped to a two byte
+ * boundard. Memory addresses can be mapped to a 32 byte boundary.
+ * The QSpan implementations usually have a 1Gbyte space for each
+ * memory and I/O spaces.
+ *
+ * This isn't a terribly fancy algorithm. I just map the spaces from
+ * the top starting with the largest address space. When finished,
+ * the registers are written and the card enabled.
+ *
+ * While the Tundra can map a large address space on most boards, we
+ * need to be careful because it may overlap other devices (like IMMR).
+ */
+#define MEMORY_SPACE_SIZE 0x20000000
+#define IO_SPACE_SIZE 0x20000000
+
+void
+map_pci_addrs()
+{
+ uint pci_mem_top, pci_mem_low;
+ uint pci_io_top;
+ uint addr_mask, reg_addr, space;
+ int i, j;
+ pci_map_t *pm;
+
+ pci_mem_top = MEMORY_SPACE_SIZE;
+ pci_io_top = IO_SPACE_SIZE;
+ pci_mem_low = (1 * 1024 * 1024); /* Below one meg addresses */
+
+ /* We can't map anything more than the maximum space, but test
+ * for it anyway to catch devices out of range.
+ */
+ addr_mask = 0x80000000;
+
+ do {
+ space = (~addr_mask) + 1; /* Size of the space */
+ for (i=0; i<pci_dev_cnt; i++) {
+ pm = &pci_map[i];
+ for (j=0; j<6; j++) {
+ /* If the MS bit is not set, this has either
+ * already been mapped, or is not used.
+ */
+ reg_addr = pm->pci_addrs[j];
+ if ((reg_addr & 0x80000000) == 0)
+ continue;
+ if (reg_addr & PCI_BASE_ADDRESS_SPACE_IO) {
+ if ((reg_addr & PCI_BASE_ADDRESS_IO_MASK) != addr_mask)
+ continue;
+ if (pci_io_top < space) {
+ puts("Out of PCI I/O space\n");
+ }
+ else {
+ pci_io_top -= space;
+ pm->pci_addrs[j] = pci_io_top;
+ pm->pci_command |= PCI_COMMAND_IO;
+ }
+ }
+ else {
+ if ((reg_addr & PCI_BASE_ADDRESS_MEM_MASK) != addr_mask)
+ continue;
+
+ /* Memory space. Test if below 1M.
+ */
+ if (reg_addr & PCI_BASE_ADDRESS_MEM_TYPE_1M) {
+ if (pci_mem_low < space) {
+ puts("Out of PCI 1M space\n");
+ }
+ else {
+ pci_mem_low -= space;
+ pm->pci_addrs[j] = pci_mem_low;
+ }
+ }
+ else {
+ if (pci_mem_top < space) {
+ puts("Out of PCI Mem space\n");
+ }
+ else {
+ pci_mem_top -= space;
+ pm->pci_addrs[j] = pci_mem_top;
+ }
+ }
+ pm->pci_command |= PCI_COMMAND_MEMORY;
+ }
+ }
+ }
+ addr_mask >>= 1;
+ addr_mask |= 0x80000000;
+ } while (addr_mask != 0xfffffffe);
+
+ /* Now, run the list one more time and map everything.
+ */
+ for (i=0; i<pci_dev_cnt; i++) {
+ pm = &pci_map[i];
+ for (j=0; j<6; j++) {
+ qs_pci_write_config_dword(pm->pci_bus, pm->pci_devfn,
+ PCI_BASE_ADDRESS_0 + (j * 4), pm->pci_addrs[j]);
+ }
+
+ /* Enable memory or address mapping.
+ */
+ qs_pci_write_config_word(pm->pci_bus, pm->pci_devfn, PCI_COMMAND,
+ pm->pci_command);
+ }
+}
+
diff --git a/arch/ppc/boot/simple/pibs.c b/arch/ppc/boot/simple/pibs.c
new file mode 100644
index 0000000..1348740
--- /dev/null
+++ b/arch/ppc/boot/simple/pibs.c
@@ -0,0 +1,103 @@
+/*
+ * 2004-2005 (c) MontaVista, Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+
+#include <linux/types.h>
+#include <linux/config.h>
+#include <linux/string.h>
+#include <linux/ctype.h>
+#include <asm/ppcboot.h>
+#include <asm/ibm4xx.h>
+
+extern unsigned long decompress_kernel(unsigned long load_addr, int num_words,
+ unsigned long cksum);
+
+/* We need to make sure that this is before the images to ensure
+ * that it's in a mapped location. - Tom */
+bd_t hold_resid_buf __attribute__ ((__section__ (".data.boot")));
+bd_t *hold_residual = &hold_resid_buf;
+
+/* String functions lifted from lib/vsprintf.c and lib/ctype.c */
+unsigned char _ctype[] = {
+_C,_C,_C,_C,_C,_C,_C,_C, /* 0-7 */
+_C,_C|_S,_C|_S,_C|_S,_C|_S,_C|_S,_C,_C, /* 8-15 */
+_C,_C,_C,_C,_C,_C,_C,_C, /* 16-23 */
+_C,_C,_C,_C,_C,_C,_C,_C, /* 24-31 */
+_S|_SP,_P,_P,_P,_P,_P,_P,_P, /* 32-39 */
+_P,_P,_P,_P,_P,_P,_P,_P, /* 40-47 */
+_D,_D,_D,_D,_D,_D,_D,_D, /* 48-55 */
+_D,_D,_P,_P,_P,_P,_P,_P, /* 56-63 */
+_P,_U|_X,_U|_X,_U|_X,_U|_X,_U|_X,_U|_X,_U, /* 64-71 */
+_U,_U,_U,_U,_U,_U,_U,_U, /* 72-79 */
+_U,_U,_U,_U,_U,_U,_U,_U, /* 80-87 */
+_U,_U,_U,_P,_P,_P,_P,_P, /* 88-95 */
+_P,_L|_X,_L|_X,_L|_X,_L|_X,_L|_X,_L|_X,_L, /* 96-103 */
+_L,_L,_L,_L,_L,_L,_L,_L, /* 104-111 */
+_L,_L,_L,_L,_L,_L,_L,_L, /* 112-119 */
+_L,_L,_L,_P,_P,_P,_P,_C, /* 120-127 */
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 128-143 */
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 144-159 */
+_S|_SP,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P, /* 160-175 */
+_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P, /* 176-191 */
+_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U, /* 192-207 */
+_U,_U,_U,_U,_U,_U,_U,_P,_U,_U,_U,_U,_U,_U,_U,_L, /* 208-223 */
+_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L, /* 224-239 */
+_L,_L,_L,_L,_L,_L,_L,_P,_L,_L,_L,_L,_L,_L,_L,_L}; /* 240-255 */
+
+/**
+ * simple_strtoull - convert a string to an unsigned long long
+ * @cp: The start of the string
+ * @endp: A pointer to the end of the parsed string will be placed here
+ * @base: The number base to use
+ */
+unsigned long long simple_strtoull(const char *cp,char **endp,unsigned int base)
+{
+ unsigned long long result = 0,value;
+
+ if (!base) {
+ base = 10;
+ if (*cp == '0') {
+ base = 8;
+ cp++;
+ if ((toupper(*cp) == 'X') && isxdigit(cp[1])) {
+ cp++;
+ base = 16;
+ }
+ }
+ } else if (base == 16) {
+ if (cp[0] == '0' && toupper(cp[1]) == 'X')
+ cp += 2;
+ }
+ while (isxdigit(*cp) && (value = isdigit(*cp) ? *cp-'0' : (islower(*cp)
+ ? toupper(*cp) : *cp)-'A'+10) < base) {
+ result = result*base + value;
+ cp++;
+ }
+ if (endp)
+ *endp = (char *)cp;
+ return result;
+}
+
+void *
+load_kernel(unsigned long load_addr, int num_words, unsigned long cksum,
+ void *ign1, void *ign2)
+{
+ unsigned long long mac64;
+
+ decompress_kernel(load_addr, num_words, cksum);
+
+ mac64 = simple_strtoull((char *)PIBS_MAC_BASE, 0, 16);
+ memcpy(hold_residual->bi_enetaddr, (char *)&mac64+2, 6);
+#ifdef CONFIG_440GX
+ mac64 = simple_strtoull((char *)(PIBS_MAC_BASE+PIBS_MAC_OFFSET), 0, 16);
+ memcpy(hold_residual->bi_enet1addr, (char *)&mac64+2, 6);
+ mac64 = simple_strtoull((char *)(PIBS_MAC_BASE+PIBS_MAC_OFFSET*2), 0, 16);
+ memcpy(hold_residual->bi_enet2addr, (char *)&mac64+2, 6);
+ mac64 = simple_strtoull((char *)(PIBS_MAC_BASE+PIBS_MAC_OFFSET*3), 0, 16);
+ memcpy(hold_residual->bi_enet3addr, (char *)&mac64+2, 6);
+#endif
+ return (void *)hold_residual;
+}
diff --git a/arch/ppc/boot/simple/prepmap.c b/arch/ppc/boot/simple/prepmap.c
new file mode 100644
index 0000000..c871a4d
--- /dev/null
+++ b/arch/ppc/boot/simple/prepmap.c
@@ -0,0 +1,12 @@
+/*
+ * 2004 (C) IBM. This file is licensed under the terms of the GNU General
+ * Public License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <nonstdio.h>
+
+void board_isa_init(void)
+{
+ ISA_init(0x80000000);
+}
diff --git a/arch/ppc/boot/simple/qspan_pci.c b/arch/ppc/boot/simple/qspan_pci.c
new file mode 100644
index 0000000..d2966d0
--- /dev/null
+++ b/arch/ppc/boot/simple/qspan_pci.c
@@ -0,0 +1,269 @@
+/*
+ * LinuxPPC arch/ppc/kernel/qspan_pci.c Dan Malek (dmalek@jlc.net)
+ *
+ * QSpan Motorola bus to PCI bridge. The config address register
+ * is located 0x500 from the base of the bridge control/status registers.
+ * The data register is located at 0x504.
+ * This is a two step operation. First, the address register is written,
+ * then the data register is read/written as required.
+ * I don't know what to do about interrupts (yet).
+ */
+
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <asm/mpc8xx.h>
+
+/*
+ * When reading the configuration space, if something does not respond
+ * the bus times out and we get a machine check interrupt. So, the
+ * good ol' exception tables come to mind to trap it and return some
+ * value.
+ *
+ * On an error we just return a -1, since that is what the caller wants
+ * returned if nothing is present. I copied this from __get_user_asm,
+ * with the only difference of returning -1 instead of EFAULT.
+ * There is an associated hack in the machine check trap code.
+ *
+ * The QSPAN is also a big endian device, that is it makes the PCI
+ * look big endian to us. This presents a problem for the Linux PCI
+ * functions, which assume little endian. For example, we see the
+ * first 32-bit word like this:
+ * ------------------------
+ * | Device ID | Vendor ID |
+ * ------------------------
+ * If we read/write as a double word, that's OK. But in our world,
+ * when read as a word, device ID is at location 0, not location 2 as
+ * the little endian PCI would believe. We have to switch bits in
+ * the PCI addresses given to us to get the data to/from the correct
+ * byte lanes.
+ *
+ * The QSPAN only supports 4 bits of "slot" in the dev_fn instead of 5.
+ * It always forces the MS bit to zero. Therefore, dev_fn values
+ * greater than 128 are returned as "no device found" errors.
+ *
+ * The QSPAN can only perform long word (32-bit) configuration cycles.
+ * The "offset" must have the two LS bits set to zero. Read operations
+ * require we read the entire word and then sort out what should be
+ * returned. Write operations other than long word require that we
+ * read the long word, update the proper word or byte, then write the
+ * entire long word back.
+ *
+ * PCI Bridge hack. We assume (correctly) that bus 0 is the primary
+ * PCI bus from the QSPAN. If we are called with a bus number other
+ * than zero, we create a Type 1 configuration access that a downstream
+ * PCI bridge will interpret.
+ */
+
+#define __get_pci_config(x, addr, op) \
+ __asm__ __volatile__( \
+ "1: "op" %0,0(%1)\n" \
+ " eieio\n" \
+ "2:\n" \
+ ".section .fixup,\"ax\"\n" \
+ "3: li %0,-1\n" \
+ " b 2b\n" \
+ ".section __ex_table,\"a\"\n" \
+ " .align 2\n" \
+ " .long 1b,3b\n" \
+ ".text" \
+ : "=r"(x) : "r"(addr))
+
+#define QS_CONFIG_ADDR ((volatile uint *)(PCI_CSR_ADDR + 0x500))
+#define QS_CONFIG_DATA ((volatile uint *)(PCI_CSR_ADDR + 0x504))
+
+#define mk_config_addr(bus, dev, offset) \
+ (((bus)<<16) | ((dev)<<8) | (offset & 0xfc))
+
+#define mk_config_type1(bus, dev, offset) \
+ mk_config_addr(bus, dev, offset) | 1;
+
+/* Initialize the QSpan device registers after power up.
+*/
+void
+qspan_init(void)
+{
+ uint *qptr;
+
+
+
+ qptr = (uint *)PCI_CSR_ADDR;
+
+ /* PCI Configuration/status. Upper bits written to clear
+ * pending interrupt or status. Lower bits enable QSPAN as
+ * PCI master, enable memory and I/O cycles, and enable PCI
+ * parity error checking.
+ * IMPORTANT: The last two bits of this word enable PCI
+ * master cycles into the QBus. The QSpan is broken and can't
+ * meet the timing specs of the PQ bus for this to work. Therefore,
+ * if you don't have external bus arbitration, you can't use
+ * this function.
+ */
+#ifdef EXTERNAL_PQ_ARB
+ qptr[1] = 0xf9000147;
+#else
+ qptr[1] = 0xf9000144;
+#endif
+
+ /* PCI Misc configuration. Set PCI latency timer resolution
+ * of 8 cycles, set cache size to 4 x 32.
+ */
+ qptr[3] = 0;
+
+ /* Set up PCI Target address mapping. Enable, Posted writes,
+ * 2Gbyte space (processor memory controller determines actual size).
+ */
+ qptr[64] = 0x8f000080;
+
+ /* Map processor 0x80000000 to PCI 0x00000000.
+ * Processor address bit 1 determines I/O type access (0x80000000)
+ * or memory type access (0xc0000000).
+ */
+ qptr[65] = 0x80000000;
+
+ /* Enable error logging and clear any pending error status.
+ */
+ qptr[80] = 0x90000000;
+
+ qptr[512] = 0x000c0003;
+
+ /* Set up Qbus slave image.
+ */
+ qptr[960] = 0x01000000;
+ qptr[961] = 0x000000d1;
+ qptr[964] = 0x00000000;
+ qptr[965] = 0x000000d1;
+
+}
+
+/* Functions to support PCI bios-like features to read/write configuration
+ * space. If the function fails for any reason, a -1 (0xffffffff) value
+ * must be returned.
+ */
+#define DEVICE_NOT_FOUND (-1)
+#define SUCCESSFUL 0
+
+int qs_pci_read_config_byte(unsigned char bus, unsigned char dev_fn,
+ unsigned char offset, unsigned char *val)
+{
+ uint temp;
+ u_char *cp;
+
+ if ((bus > 7) || (dev_fn > 127)) {
+ *val = 0xff;
+ return DEVICE_NOT_FOUND;
+ }
+
+ if (bus == 0)
+ *QS_CONFIG_ADDR = mk_config_addr(bus, dev_fn, offset);
+ else
+ *QS_CONFIG_ADDR = mk_config_type1(bus, dev_fn, offset);
+ __get_pci_config(temp, QS_CONFIG_DATA, "lwz");
+
+ offset ^= 0x03;
+ cp = ((u_char *)&temp) + (offset & 0x03);
+ *val = *cp;
+ return SUCCESSFUL;
+}
+
+int qs_pci_read_config_word(unsigned char bus, unsigned char dev_fn,
+ unsigned char offset, unsigned short *val)
+{
+ uint temp;
+ ushort *sp;
+
+ if ((bus > 7) || (dev_fn > 127)) {
+ *val = 0xffff;
+ return DEVICE_NOT_FOUND;
+ }
+
+ if (bus == 0)
+ *QS_CONFIG_ADDR = mk_config_addr(bus, dev_fn, offset);
+ else
+ *QS_CONFIG_ADDR = mk_config_type1(bus, dev_fn, offset);
+ __get_pci_config(temp, QS_CONFIG_DATA, "lwz");
+ offset ^= 0x02;
+
+ sp = ((ushort *)&temp) + ((offset >> 1) & 1);
+ *val = *sp;
+ return SUCCESSFUL;
+}
+
+int qs_pci_read_config_dword(unsigned char bus, unsigned char dev_fn,
+ unsigned char offset, unsigned int *val)
+{
+ if ((bus > 7) || (dev_fn > 127)) {
+ *val = 0xffffffff;
+ return DEVICE_NOT_FOUND;
+ }
+ if (bus == 0)
+ *QS_CONFIG_ADDR = mk_config_addr(bus, dev_fn, offset);
+ else
+ *QS_CONFIG_ADDR = mk_config_type1(bus, dev_fn, offset);
+ __get_pci_config(*val, QS_CONFIG_DATA, "lwz");
+ return SUCCESSFUL;
+}
+
+int qs_pci_write_config_byte(unsigned char bus, unsigned char dev_fn,
+ unsigned char offset, unsigned char val)
+{
+ uint temp;
+ u_char *cp;
+
+ if ((bus > 7) || (dev_fn > 127))
+ return DEVICE_NOT_FOUND;
+
+ qs_pci_read_config_dword(bus, dev_fn, offset, &temp);
+
+ offset ^= 0x03;
+ cp = ((u_char *)&temp) + (offset & 0x03);
+ *cp = val;
+
+ if (bus == 0)
+ *QS_CONFIG_ADDR = mk_config_addr(bus, dev_fn, offset);
+ else
+ *QS_CONFIG_ADDR = mk_config_type1(bus, dev_fn, offset);
+ *QS_CONFIG_DATA = temp;
+
+ return SUCCESSFUL;
+}
+
+int qs_pci_write_config_word(unsigned char bus, unsigned char dev_fn,
+ unsigned char offset, unsigned short val)
+{
+ uint temp;
+ ushort *sp;
+
+ if ((bus > 7) || (dev_fn > 127))
+ return DEVICE_NOT_FOUND;
+
+ qs_pci_read_config_dword(bus, dev_fn, offset, &temp);
+
+ offset ^= 0x02;
+ sp = ((ushort *)&temp) + ((offset >> 1) & 1);
+ *sp = val;
+
+ if (bus == 0)
+ *QS_CONFIG_ADDR = mk_config_addr(bus, dev_fn, offset);
+ else
+ *QS_CONFIG_ADDR = mk_config_type1(bus, dev_fn, offset);
+ *QS_CONFIG_DATA = temp;
+
+ return SUCCESSFUL;
+}
+
+int qs_pci_write_config_dword(unsigned char bus, unsigned char dev_fn,
+ unsigned char offset, unsigned int val)
+{
+ if ((bus > 7) || (dev_fn > 127))
+ return DEVICE_NOT_FOUND;
+
+ if (bus == 0)
+ *QS_CONFIG_ADDR = mk_config_addr(bus, dev_fn, offset);
+ else
+ *QS_CONFIG_ADDR = mk_config_type1(bus, dev_fn, offset);
+ *(unsigned int *)QS_CONFIG_DATA = val;
+
+ return SUCCESSFUL;
+}
+
diff --git a/arch/ppc/boot/simple/relocate.S b/arch/ppc/boot/simple/relocate.S
new file mode 100644
index 0000000..555a216
--- /dev/null
+++ b/arch/ppc/boot/simple/relocate.S
@@ -0,0 +1,216 @@
+/*
+ * arch/ppc/boot/simple/relocate.S
+ *
+ * This is the common part of the loader relocation and initialization
+ * process. All of the board/processor specific initialization is
+ * done before we get here.
+ *
+ * Author: Tom Rini
+ * trini@mvista.com
+ * Derived from arch/ppc/boot/prep/head.S (Cort Dougan, many others).
+ *
+ * 2001-2004 (c) MontaVista, Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+
+#include <linux/config.h>
+#include <asm/cache.h>
+#include <asm/ppc_asm.h>
+
+#define GETSYM(reg, sym) \
+ lis reg, sym@h; ori reg, reg, sym@l
+
+ .text
+ /* We get called from the early initialization code.
+ * Register 3 has the address where we were loaded,
+ * Register 4 contains any residual data passed from the
+ * boot rom.
+ */
+ .globl relocate
+relocate:
+ /* Save r3, r4 for later.
+ * The r8/r11 are legacy registers so I don't have to
+ * rewrite the code below :-).
+ */
+ mr r8, r3
+ mr r11, r4
+
+ /* compute the size of the whole image in words. */
+ GETSYM(r4,start)
+ GETSYM(r5,end)
+
+ addi r5,r5,3 /* round up */
+ sub r5,r5,r4 /* end - start */
+ srwi r5,r5,2
+ mr r7,r5 /* Save for later use. */
+
+ /*
+ * Check if we need to relocate ourselves to the link addr or were
+ * we loaded there to begin with.
+ */
+ cmpw cr0,r3,r4
+ beq start_ldr /* If 0, we don't need to relocate */
+
+ /* Move this code somewhere safe. This is max(load + size, end)
+ * r8 == load address
+ */
+ GETSYM(r4, start)
+ GETSYM(r5, end)
+
+ sub r6,r5,r4
+ add r6,r8,r6 /* r6 == phys(load + size) */
+
+ cmpw r5,r6
+ bgt 1f
+ b 2f
+1:
+ mr r6, r5
+2:
+ /* dest is in r6 */
+ /* Ensure alignment --- this code is precautionary */
+ addi r6,r6,4
+ li r5,0x0003
+ andc r6,r6,r5
+
+ /* Find physical address and size of do_relocate */
+ GETSYM(r5, __relocate_start)
+ GETSYM(r4, __relocate_end)
+ GETSYM(r3, start)
+
+ /* Size to copy */
+ sub r4,r4,r5
+ srwi r4,r4,2
+
+ /* Src addr to copy (= __relocate_start - start + where_loaded) */
+ sub r3,r5,r3
+ add r5,r8,r3
+
+ /* Save dest */
+ mr r3, r6
+
+ /* Do the copy */
+ mtctr r4
+3: lwz r4,0(r5)
+ stw r4,0(r3)
+ addi r3,r3,4
+ addi r5,r5,4
+ bdnz 3b
+
+ GETSYM(r4, __relocate_start)
+ GETSYM(r5, do_relocate)
+
+ sub r4,r5,r4 /* Get entry point for do_relocate in */
+ add r6,r6,r4 /* relocated section */
+
+ /* This will return to the relocated do_relocate */
+ mtlr r6
+ b flush_instruction_cache
+
+ .section ".relocate_code","xa"
+
+do_relocate:
+ /* We have 2 cases --- start < load, or start > load
+ * This determines whether we copy from the end, or the start.
+ * Its easier to have 2 loops than to have paramaterised
+ * loops. Sigh.
+ */
+ li r6,0 /* Clear checksum */
+ mtctr r7 /* Setup for a loop */
+
+ GETSYM(r4, start)
+ mr r3,r8 /* Get the load addr */
+
+ cmpw cr0,r4,r3 /* If we need to copy from the end, do so */
+ bgt do_relocate_from_end
+
+do_relocate_from_start:
+1: lwz r5,0(r3) /* Load and decrement */
+ stw r5,0(r4) /* Store and decrement */
+ addi r3,r3,4
+ addi r4,r4,4
+ xor r6,r6,r5 /* Update checksum */
+ bdnz 1b /* Are we done? */
+ b do_relocate_out /* Finished */
+
+do_relocate_from_end:
+ GETSYM(r3, end)
+ slwi r4,r7,2
+ add r4,r8,r4 /* Get the physical end */
+1: lwzu r5,-4(r4)
+ stwu r5, -4(r3)
+ xor r6,r6,r5
+ bdnz 1b
+
+do_relocate_out:
+ GETSYM(r3,start_ldr)
+ mtlr r3 /* Easiest way to do an absolute jump */
+/* Some boards don't boot up with the I-cache enabled. Do that
+ * now because the decompress runs much faster that way.
+ * As a side effect, we have to ensure the data cache is not enabled
+ * so we can access the serial I/O without trouble.
+ */
+ b flush_instruction_cache
+
+ .previous
+
+start_ldr:
+/* Clear all of BSS and set up stack for C calls */
+ lis r3,edata@h
+ ori r3,r3,edata@l
+ lis r4,end@h
+ ori r4,r4,end@l
+ subi r3,r3,4
+ subi r4,r4,4
+ li r0,0
+50: stwu r0,4(r3)
+ cmpw cr0,r3,r4
+ bne 50b
+90: mr r9,r1 /* Save old stack pointer (in case it matters) */
+ lis r1,.stack@h
+ ori r1,r1,.stack@l
+ addi r1,r1,4096*2
+ subi r1,r1,256
+ li r2,0x000F /* Mask pointer to 16-byte boundary */
+ andc r1,r1,r2
+
+ /*
+ * Exec kernel loader
+ */
+ mr r3,r8 /* Load point */
+ mr r4,r7 /* Program length */
+ mr r5,r6 /* Checksum */
+ mr r6,r11 /* Residual data */
+ mr r7,r25 /* Validated OFW interface */
+ bl load_kernel
+
+ /*
+ * Make sure the kernel knows we don't have things set in
+ * registers. -- Tom
+ */
+ li r4,0
+ li r5,0
+ li r6,0
+
+ /*
+ * Start at the begining.
+ */
+#ifdef CONFIG_PPC_MULTIPLATFORM
+ li r9,0xc
+ mtlr r9
+ /* tell kernel we're prep, by putting 0xdeadc0de at KERNELLOAD,
+ * and tell the kernel to start on the 4th instruction since we
+ * overwrite the first 3 sometimes (which are 'nop').
+ */
+ lis r10,0xdeadc0de@h
+ ori r10,r10,0xdeadc0de@l
+ li r9,0
+ stw r10,0(r9)
+#else
+ li r9,0
+ mtlr r9
+#endif
+ blr
+
+ .comm .stack,4096*2,4
diff --git a/arch/ppc/boot/simple/rw4/ppc_40x.h b/arch/ppc/boot/simple/rw4/ppc_40x.h
new file mode 100644
index 0000000..561fb26
--- /dev/null
+++ b/arch/ppc/boot/simple/rw4/ppc_40x.h
@@ -0,0 +1,664 @@
+/*----------------------------------------------------------------------------+
+| This source code has been made available to you by IBM on an AS-IS
+| basis. Anyone receiving this source is licensed under IBM
+| copyrights to use it in any way he or she deems fit, including
+| copying it, modifying it, compiling it, and redistributing it either
+| with or without modifications. No license under IBM patents or
+| patent applications is to be implied by the copyright license.
+|
+| Any user of this software should understand that IBM cannot provide
+| technical support for this software and will not be responsible for
+| any consequences resulting from the use of this software.
+|
+| Any person who transfers this source code or any derivative work
+| must include the IBM copyright notice, this paragraph, and the
+| preceding two paragraphs in the transferred software.
+|
+| COPYRIGHT I B M CORPORATION 1997
+| LICENSED MATERIAL - PROGRAM PROPERTY OF I B M
++----------------------------------------------------------------------------*/
+/*----------------------------------------------------------------------------+
+| Author: Tony J. Cerreto
+| Component: Assembler include file.
+| File: ppc_40x.h
+| Purpose: Include file containing PPC DCR defines.
+|
+| Changes:
+| Date Author Comment
+| --------- ------ --------------------------------------------------------
+| 01-Mar-00 tjc Created
++----------------------------------------------------------------------------*/
+/* added by linguohui*/
+#define MW
+/*----------------------------------------------------------------------------+
+| PPC Special purpose registers Numbers
++----------------------------------------------------------------------------*/
+#define ccr0 0x3b3 /* core configuration reg */
+#define ctr 0x009 /* count register */
+#define ctrreg 0x009 /* count register */
+#define dbcr0 0x3f2 /* debug control register 0 */
+#define dbcr1 0x3bd /* debug control register 1 */
+#define dbsr 0x3f0 /* debug status register */
+#define dccr 0x3fa /* data cache control reg. */
+#define dcwr 0x3ba /* data cache write-thru reg */
+#define dear 0x3d5 /* data exception address reg */
+#define esr 0x3d4 /* exception syndrome register */
+#define evpr 0x3d6 /* exception vector prefix reg */
+#define iccr 0x3fb /* instruction cache cntrl re */
+#define icdbdr 0x3d3 /* instr cache dbug data reg */
+#define lrreg 0x008 /* link register */
+#define pid 0x3b1 /* process id reg */
+#define pit 0x3db /* programmable interval time */
+#define pvr 0x11f /* processor version register */
+#define sgr 0x3b9 /* storage guarded reg */
+#define sler 0x3bb /* storage little endian reg */
+#define sprg0 0x110 /* special general purpose 0 */
+#define sprg1 0x111 /* special general purpose 1 */
+#define sprg2 0x112 /* special general purpose 2 */
+#define sprg3 0x113 /* special general purpose 3 */
+#define sprg4 0x114 /* special general purpose 4 */
+#define sprg5 0x115 /* special general purpose 5 */
+#define sprg6 0x116 /* special general purpose 6 */
+#define sprg7 0x117 /* special general purpose 7 */
+#define srr0 0x01a /* save/restore register 0 */
+#define srr1 0x01b /* save/restore register 1 */
+#define srr2 0x3de /* save/restore register 2 */
+#define srr3 0x3df /* save/restore register 3 */
+#define tbhi 0x11D
+#define tblo 0x11C
+#define tcr 0x3da /* timer control register */
+#define tsr 0x3d8 /* timer status register */
+#define xerreg 0x001 /* fixed point exception */
+#define xer 0x001 /* fixed point exception */
+#define zpr 0x3b0 /* zone protection reg */
+
+/*----------------------------------------------------------------------------+
+| Decompression Controller
++----------------------------------------------------------------------------*/
+#define kiar 0x014 /* Decompression cntl addr reg */
+#define kidr 0x015 /* Decompression cntl data reg */
+#define kitor0 0x00 /* index table origin Reg 0 */
+#define kitor1 0x01 /* index table origin Reg 1 */
+#define kitor2 0x02 /* index table origin Reg 2 */
+#define kitor3 0x03 /* index table origin Reg 3 */
+#define kaddr0 0x04 /* addr decode Definition Reg 0 */
+#define kaddr1 0x05 /* addr decode Definition Reg 1 */
+#define kconf 0x40 /* Decompression cntl config reg */
+#define kid 0x41 /* Decompression cntl id reg */
+#define kver 0x42 /* Decompression cntl ver number */
+#define kpear 0x50 /* bus error addr reg (PLB) */
+#define kbear 0x51 /* bus error addr reg (DCP-EBC) */
+#define kesr0 0x52 /* bus error status reg 0 */
+
+/*----------------------------------------------------------------------------+
+| Romeo Specific Device Control Register Numbers.
++----------------------------------------------------------------------------*/
+#ifndef VESTA
+#define cdbcr 0x3d7 /* cache debug cntrl reg */
+
+#define a_latcnt 0x1a9 /* PLB Latency count */
+#define a_tgval 0x1ac /* tone generation value */
+#define a_plb_pr 0x1bf /* PLB priority */
+
+#define cic_sel1 0x031 /* select register 1 */
+#define cic_sel2 0x032 /* select register 2 */
+
+#define clkgcrst 0x122 /* chip reset register */
+
+#define cp_cpmsr 0x100 /*rstatus register */
+#define cp_cpmer 0x101 /* enable register */
+
+#define dcp_kiar 0x190 /* indirect address register */
+#define dcp_kidr 0x191 /* indirect data register */
+
+#define hsmc_mcgr 0x1c0 /* HSMC global register */
+#define hsmc_mcbesr 0x1c1 /* bus error status register */
+#define hsmc_mcbear 0x1c2 /* bus error address register*/
+#define hsmc_mcbr0 0x1c4 /* SDRAM sub-ctrl bank reg 0 */
+#define hsmc_mccr0 0x1c5 /* SDRAM sub-ctrl ctrl reg 0 */
+#define hsmc_mcbr1 0x1c7 /* SDRAM sub-ctrl bank reg 1 */
+#define hsmc_mccr1 0x1c8 /* SDRAM sub-ctrl ctrl reg 1 */
+#define hsmc_sysr 0x1d1 /* system register */
+#define hsmc_data 0x1d2 /* data register */
+#define hsmc_mccrr 0x1d3 /* refresh register */
+
+#define ocm_pbar 0x1E0 /* base address register */
+
+#define plb0_pacr0 0x057 /* PLB arbiter control reg */
+#define plb1_pacr1 0x067 /* PLB arbiter control reg */
+
+#define v_displb 0x157 /* set left border of display*/
+#define v_disptb 0x158 /* top border of display */
+#define v_osd_la 0x159 /* first link address for OSD*/
+#define v_ptsdlta 0x15E /* PTS delta register */
+#define v_v0base 0x16C /* base mem add for VBI-0 */
+#define v_v1base 0x16D /* base mem add for VBI-1 */
+#define v_osbase 0x16E /* base mem add for OSD data */
+#endif
+
+/*----------------------------------------------------------------------------+
+| Vesta Device Control Register Numbers.
++----------------------------------------------------------------------------*/
+/*----------------------------------------------------------------------------+
+| Cross bar switch.
++----------------------------------------------------------------------------*/
+#define cbs0_cr 0x010 /* CBS configuration register */
+
+/*----------------------------------------------------------------------------+
+| DCR external master (DCRX).
++----------------------------------------------------------------------------*/
+#define dcrx0_icr 0x020 /* internal control register */
+#define dcrx0_isr 0x021 /* internal status register */
+#define dcrx0_ecr 0x022 /* external control register */
+#define dcrx0_esr 0x023 /* external status register */
+#define dcrx0_tar 0x024 /* target address register */
+#define dcrx0_tdr 0x025 /* target data register */
+#define dcrx0_igr 0x026 /* interrupt generation register */
+#define dcrx0_bcr 0x027 /* buffer control register */
+
+/*----------------------------------------------------------------------------+
+| Chip interconnect configuration.
++----------------------------------------------------------------------------*/
+#define cic0_cr 0x030 /* CIC control register */
+#define cic0_vcr 0x033 /* video macro control reg */
+#define cic0_sel3 0x035 /* select register 3 */
+
+/*----------------------------------------------------------------------------+
+| Chip interconnect configuration.
++----------------------------------------------------------------------------*/
+#define sgpo0_sgpO 0x036 /* simplified GPIO output */
+#define sgpo0_gpod 0x037 /* simplified GPIO open drain */
+#define sgpo0_gptc 0x038 /* simplified GPIO tristate cntl */
+#define sgpo0_gpi 0x039 /* simplified GPIO input */
+
+/*----------------------------------------------------------------------------+
+| Universal interrupt controller.
++----------------------------------------------------------------------------*/
+#define uic0_sr 0x040 /* status register */
+#define uic0_srs 0x041 /* status register set */
+#define uic0_er 0x042 /* enable register */
+#define uic0_cr 0x043 /* critical register */
+#define uic0_pr 0x044 /* parity register */
+#define uic0_tr 0x045 /* triggering register */
+#define uic0_msr 0x046 /* masked status register */
+#define uic0_vr 0x047 /* vector register */
+#define uic0_vcr 0x048 /* enable config register */
+
+/*----------------------------------------------------------------------------+
+| PLB 0 and 1.
++----------------------------------------------------------------------------*/
+#define pb0_pesr 0x054 /* PLB error status reg 0 */
+#define pb0_pesrs 0x055 /* PLB error status reg 0 set */
+#define pb0_pear 0x056 /* PLB error address reg */
+
+#define pb1_pesr 0x064 /* PLB error status reg 1 */
+#define pb1_pesrs 0x065 /* PLB error status reg 1 set */
+#define pb1_pear 0x066 /* PLB error address reg */
+
+/*----------------------------------------------------------------------------+
+| EBIU DCR registers.
++----------------------------------------------------------------------------*/
+#define ebiu0_brcrh0 0x070 /* bus region register 0 high */
+#define ebiu0_brcrh1 0x071 /* bus region register 1 high */
+#define ebiu0_brcrh2 0x072 /* bus region register 2 high */
+#define ebiu0_brcrh3 0x073 /* bus region register 3 high */
+#define ebiu0_brcrh4 0x074 /* bus region register 4 high */
+#define ebiu0_brcrh5 0x075 /* bus region register 5 high */
+#define ebiu0_brcrh6 0x076 /* bus region register 6 high */
+#define ebiu0_brcrh7 0x077 /* bus region register 7 high */
+#define ebiu0_brcr0 0x080 /* bus region register 0 */
+#define ebiu0_brcr1 0x081 /* bus region register 1 */
+#define ebiu0_brcr2 0x082 /* bus region register 2 */
+#define ebiu0_brcr3 0x083 /* bus region register 3 */
+#define ebiu0_brcr4 0x084 /* bus region register 4 */
+#define ebiu0_brcr5 0x085 /* bus region register 5 */
+#define ebiu0_brcr6 0x086 /* bus region register 6 */
+#define ebiu0_brcr7 0x087 /* bus region register 7 */
+#define ebiu0_bear 0x090 /* bus error address register */
+#define ebiu0_besr 0x091 /* bus error syndrome reg */
+#define ebiu0_besr0s 0x093 /* bus error syndrome reg */
+#define ebiu0_biucr 0x09a /* bus interface control reg */
+
+/*----------------------------------------------------------------------------+
+| OPB bridge.
++----------------------------------------------------------------------------*/
+#define opbw0_gesr 0x0b0 /* error status reg */
+#define opbw0_gesrs 0x0b1 /* error status reg */
+#define opbw0_gear 0x0b2 /* error address reg */
+
+/*----------------------------------------------------------------------------+
+| DMA.
++----------------------------------------------------------------------------*/
+#define dma0_cr0 0x0c0 /* DMA channel control reg 0 */
+#define dma0_ct0 0x0c1 /* DMA count register 0 */
+#define dma0_da0 0x0c2 /* DMA destination addr reg 0 */
+#define dma0_sa0 0x0c3 /* DMA source addr register 0 */
+#define dma0_cc0 0x0c4 /* DMA chained count 0 */
+#define dma0_cr1 0x0c8 /* DMA channel control reg 1 */
+#define dma0_ct1 0x0c9 /* DMA count register 1 */
+#define dma0_da1 0x0ca /* DMA destination addr reg 1 */
+#define dma0_sa1 0x0cb /* DMA source addr register 1 */
+#define dma0_cc1 0x0cc /* DMA chained count 1 */
+#define dma0_cr2 0x0d0 /* DMA channel control reg 2 */
+#define dma0_ct2 0x0d1 /* DMA count register 2 */
+#define dma0_da2 0x0d2 /* DMA destination addr reg 2 */
+#define dma0_sa2 0x0d3 /* DMA source addr register 2 */
+#define dma0_cc2 0x0d4 /* DMA chained count 2 */
+#define dma0_cr3 0x0d8 /* DMA channel control reg 3 */
+#define dma0_ct3 0x0d9 /* DMA count register 3 */
+#define dma0_da3 0x0da /* DMA destination addr reg 3 */
+#define dma0_sa3 0x0db /* DMA source addr register 3 */
+#define dma0_cc3 0x0dc /* DMA chained count 3 */
+#define dma0_sr 0x0e0 /* DMA status register */
+#define dma0_srs 0x0e1 /* DMA status register */
+#define dma0_s1 0x031 /* DMA select1 register */
+#define dma0_s2 0x032 /* DMA select2 register */
+
+/*---------------------------------------------------------------------------+
+| Clock and power management.
++----------------------------------------------------------------------------*/
+#define cpm0_fr 0x102 /* force register */
+
+/*----------------------------------------------------------------------------+
+| Serial Clock Control.
++----------------------------------------------------------------------------*/
+#define ser0_ccr 0x120 /* serial clock control register */
+
+/*----------------------------------------------------------------------------+
+| Audio Clock Control.
++----------------------------------------------------------------------------*/
+#define aud0_apcr 0x121 /* audio clock ctrl register */
+
+/*----------------------------------------------------------------------------+
+| DENC.
++----------------------------------------------------------------------------*/
+#define denc0_idr 0x130 /* DENC ID register */
+#define denc0_cr1 0x131 /* control register 1 */
+#define denc0_rr1 0x132 /* microvision 1 (reserved 1) */
+#define denc0_cr2 0x133 /* control register 2 */
+#define denc0_rr2 0x134 /* microvision 2 (reserved 2) */
+#define denc0_rr3 0x135 /* microvision 3 (reserved 3) */
+#define denc0_rr4 0x136 /* microvision 4 (reserved 4) */
+#define denc0_rr5 0x137 /* microvision 5 (reserved 5) */
+#define denc0_ccdr 0x138 /* closed caption data */
+#define denc0_cccr 0x139 /* closed caption control */
+#define denc0_trr 0x13A /* teletext request register */
+#define denc0_tosr 0x13B /* teletext odd field line se */
+#define denc0_tesr 0x13C /* teletext even field line s */
+#define denc0_rlsr 0x13D /* RGB rhift left register */
+#define denc0_vlsr 0x13E /* video level shift register */
+#define denc0_vsr 0x13F /* video scaling register */
+
+/*----------------------------------------------------------------------------+
+| Video decoder. Suspect 0x179, 0x169, 0x16a, 0x152 (rc).
++----------------------------------------------------------------------------*/
+#define vid0_ccntl 0x140 /* control decoder operation */
+#define vid0_cmode 0x141 /* video operational mode */
+#define vid0_sstc0 0x142 /* STC high order bits 31:0 */
+#define vid0_sstc1 0x143 /* STC low order bit 32 */
+#define vid0_spts0 0x144 /* PTS high order bits 31:0 */
+#define vid0_spts1 0x145 /* PTS low order bit 32 */
+#define vid0_fifo 0x146 /* FIFO data port */
+#define vid0_fifos 0x147 /* FIFO status */
+#define vid0_cmd 0x148 /* send command to decoder */
+#define vid0_cmdd 0x149 /* port for command params */
+#define vid0_cmdst 0x14A /* command status */
+#define vid0_cmdad 0x14B /* command address */
+#define vid0_procia 0x14C /* instruction store */
+#define vid0_procid 0x14D /* data port for I_Store */
+#define vid0_osdm 0x151 /* OSD mode control */
+#define vid0_hosti 0x152 /* base interrupt register */
+#define vid0_mask 0x153 /* interrupt mask register */
+#define vid0_dispm 0x154 /* operational mode for Disp */
+#define vid0_dispd 0x155 /* setting for 'Sync' delay */
+#define vid0_vbctl 0x156 /* VBI */
+#define vid0_ttxctl 0x157 /* teletext control */
+#define vid0_disptb 0x158 /* display left/top border */
+#define vid0_osdgla 0x159 /* Graphics plane link addr */
+#define vid0_osdila 0x15A /* Image plane link addr */
+#define vid0_rbthr 0x15B /* rate buffer threshold */
+#define vid0_osdcla 0x15C /* Cursor link addr */
+#define vid0_stcca 0x15D /* STC common address */
+#define vid0_ptsctl 0x15F /* PTS Control */
+#define vid0_wprot 0x165 /* write protect for I_Store */
+#define vid0_vcqa 0x167 /* video clip queued block Ad */
+#define vid0_vcql 0x168 /* video clip queued block Le */
+#define vid0_blksz 0x169 /* block size bytes for copy op */
+#define vid0_srcad 0x16a /* copy source address bits 6-31 */
+#define vid0_udbas 0x16B /* base mem add for user data */
+#define vid0_vbibas 0x16C /* base mem add for VBI 0/1 */
+#define vid0_osdibas 0x16D /* Image plane base address */
+#define vid0_osdgbas 0x16E /* Graphic plane base address */
+#define vid0_rbbase 0x16F /* base mem add for video buf */
+#define vid0_dramad 0x170 /* DRAM address */
+#define vid0_dramdt 0x171 /* data port for DRAM access */
+#define vid0_dramcs 0x172 /* DRAM command and statusa */
+#define vid0_vcwa 0x173 /* v clip work address */
+#define vid0_vcwl 0x174 /* v clip work length */
+#define vid0_mseg0 0x175 /* segment address 0 */
+#define vid0_mseg1 0x176 /* segment address 1 */
+#define vid0_mseg2 0x177 /* segment address 2 */
+#define vid0_mseg3 0x178 /* segment address 3 */
+#define vid0_fbbase 0x179 /* frame buffer base memory */
+#define vid0_osdcbas 0x17A /* Cursor base addr */
+#define vid0_lboxtb 0x17B /* top left border */
+#define vid0_trdly 0x17C /* transparency gate delay */
+#define vid0_sbord 0x17D /* left/top small pict. bord. */
+#define vid0_zoffs 0x17E /* hor/ver zoom window */
+#define vid0_rbsz 0x17F /* rate buffer size read */
+
+/*----------------------------------------------------------------------------+
+| Transport demultiplexer.
++----------------------------------------------------------------------------*/
+#define xpt0_lr 0x180 /* demux location register */
+#define xpt0_data 0x181 /* demux data register */
+#define xpt0_ir 0x182 /* demux interrupt register */
+
+#define xpt0_config1 0x0000 /* configuration 1 */
+#define xpt0_control1 0x0001 /* control 1 */
+#define xpt0_festat 0x0002 /* Front-end status */
+#define xpt0_feimask 0x0003 /* Front_end interrupt Mask */
+#define xpt0_ocmcnfg 0x0004 /* OCM Address */
+#define xpt0_settapi 0x0005 /* Set TAP Interrupt */
+
+#define xpt0_pcrhi 0x0010 /* PCR High */
+#define xpt0_pcrlow 0x0011 /* PCR Low */
+#define xpt0_lstchi 0x0012 /* Latched STC High */
+#define xpt0_lstclow 0x0013 /* Latched STC Low */
+#define xpt0_stchi 0x0014 /* STC High */
+#define xpt0_stclow 0x0015 /* STC Low */
+#define xpt0_pwm 0x0016 /* PWM */
+#define xpt0_pcrstct 0x0017 /* PCR-STC Threshold */
+#define xpt0_pcrstcd 0x0018 /* PCR-STC Delta */
+#define xpt0_stccomp 0x0019 /* STC Compare */
+#define xpt0_stccmpd 0x001a /* STC Compare Disarm */
+
+#define xpt0_dsstat 0x0048 /* Descrambler Status */
+#define xpt0_dsimask 0x0049 /* Descrambler Interrupt Mask */
+
+#define xpt0_vcchng 0x01f0 /* Video Channel Change */
+#define xpt0_acchng 0x01f1 /* Audio Channel Change */
+#define xpt0_axenable 0x01fe /* Aux PID Enables */
+#define xpt0_pcrpid 0x01ff /* PCR PID */
+
+#define xpt0_config2 0x1000 /* Configuration 2 */
+#define xpt0_pbuflvl 0x1002 /* Packet Buffer Level */
+#define xpt0_intmask 0x1003 /* Interrupt Mask */
+#define xpt0_plbcnfg 0x1004 /* PLB Configuration */
+
+#define xpt0_qint 0x1010 /* Queues Interrupts */
+#define xpt0_qintmsk 0x1011 /* Queues Interrupts Mask */
+#define xpt0_astatus 0x1012 /* Audio Status */
+#define xpt0_aintmask 0x1013 /* Audio Interrupt Mask */
+#define xpt0_vstatus 0x1014 /* Video Status */
+#define xpt0_vintmask 0x1015 /* Video Interrupt Mask */
+
+#define xpt0_qbase 0x1020 /* Queue Base */
+#define xpt0_bucketq 0x1021 /* Bucket Queue */
+#define xpt0_qstops 0x1024 /* Queue Stops */
+#define xpt0_qresets 0x1025 /* Queue Resets */
+#define xpt0_sfchng 0x1026 /* Section Filter Change */
+
+/*----------------------------------------------------------------------------+
+| Audio decoder. Suspect 0x1ad, 0x1b4, 0x1a3, 0x1a5 (read/write status)
++----------------------------------------------------------------------------*/
+#define aud0_ctrl0 0x1a0 /* control 0 */
+#define aud0_ctrl1 0x1a1 /* control 1 */
+#define aud0_ctrl2 0x1a2 /* control 2 */
+#define aud0_cmd 0x1a3 /* command register */
+#define aud0_isr 0x1a4 /* interrupt status register */
+#define aud0_imr 0x1a5 /* interrupt mask register */
+#define aud0_dsr 0x1a6 /* decoder status register */
+#define aud0_stc 0x1a7 /* system time clock */
+#define aud0_csr 0x1a8 /* channel status register */
+#define aud0_lcnt 0x1a9 /* queued address register 2 */
+#define aud0_pts 0x1aa /* presentation time stamp */
+#define aud0_tgctrl 0x1ab /* tone generation control */
+#define aud0_qlr2 0x1ac /* queued length register 2 */
+#define aud0_auxd 0x1ad /* aux data */
+#define aud0_strmid 0x1ae /* stream ID */
+#define aud0_qar 0x1af /* queued address register */
+#define aud0_dsps 0x1b0 /* DSP status */
+#define aud0_qlr 0x1b1 /* queued len address */
+#define aud0_dspc 0x1b2 /* DSP control */
+#define aud0_wlr2 0x1b3 /* working length register 2 */
+#define aud0_instd 0x1b4 /* instruction download */
+#define aud0_war 0x1b5 /* working address register */
+#define aud0_seg1 0x1b6 /* segment 1 base register */
+#define aud0_seg2 0x1b7 /* segment 2 base register */
+#define aud0_avf 0x1b9 /* audio att value front */
+#define aud0_avr 0x1ba /* audio att value rear */
+#define aud0_avc 0x1bb /* audio att value center */
+#define aud0_seg3 0x1bc /* segment 3 base register */
+#define aud0_offset 0x1bd /* offset address */
+#define aud0_wrl 0x1be /* working length register */
+#define aud0_war2 0x1bf /* working address register 2 */
+
+/*----------------------------------------------------------------------------+
+| High speed memory controller 0 and 1.
++----------------------------------------------------------------------------*/
+#define hsmc0_gr 0x1e0 /* HSMC global register */
+#define hsmc0_besr 0x1e1 /* bus error status register */
+#define hsmc0_bear 0x1e2 /* bus error address register */
+#define hsmc0_br0 0x1e4 /* SDRAM sub-ctrl bank reg 0 */
+#define hsmc0_cr0 0x1e5 /* SDRAM sub-ctrl ctrl reg 0 */
+#define hsmc0_br1 0x1e7 /* SDRAM sub-ctrl bank reg 1 */
+#define hsmc0_cr1 0x1e8 /* SDRAM sub-ctrl ctrl reg 1 */
+#define hsmc0_sysr 0x1f1 /* system register */
+#define hsmc0_data 0x1f2 /* data register */
+#define hsmc0_crr 0x1f3 /* refresh register */
+
+#define hsmc1_gr 0x1c0 /* HSMC global register */
+#define hsmc1_besr 0x1c1 /* bus error status register */
+#define hsmc1_bear 0x1c2 /* bus error address register */
+#define hsmc1_br0 0x1c4 /* SDRAM sub-ctrl bank reg 0 */
+#define hsmc1_cr0 0x1c5 /* SDRAM sub-ctrl ctrl reg 0 */
+#define hsmc1_br1 0x1c7 /* SDRAM sub-ctrl bank reg 1 */
+#define hsmc1_cr1 0x1c8 /* SDRAM sub-ctrl ctrl reg 1 */
+#define hsmc1_sysr 0x1d1 /* system register */
+#define hsmc1_data 0x1d2 /* data register */
+#define hsmc1_crr 0x1d3 /* refresh register */
+
+/*----------------------------------------------------------------------------+
+| Machine State Register bit definitions.
++----------------------------------------------------------------------------*/
+#define msr_ape 0x00100000
+#define msr_apa 0x00080000
+#define msr_we 0x00040000
+#define msr_ce 0x00020000
+#define msr_ile 0x00010000
+#define msr_ee 0x00008000
+#define msr_pr 0x00004000
+#define msr_me 0x00001000
+#define msr_de 0x00000200
+#define msr_ir 0x00000020
+#define msr_dr 0x00000010
+#define msr_le 0x00000001
+
+/*----------------------------------------------------------------------------+
+| Used during interrupt processing.
++----------------------------------------------------------------------------*/
+#define stack_reg_image_size 160
+
+/*----------------------------------------------------------------------------+
+| Function prolog definition and other Metaware (EABI) defines.
++----------------------------------------------------------------------------*/
+#ifdef MW
+
+#define r0 0
+#define r1 1
+#define r2 2
+#define r3 3
+#define r4 4
+#define r5 5
+#define r6 6
+#define r7 7
+#define r8 8
+#define r9 9
+#define r10 10
+#define r11 11
+#define r12 12
+#define r13 13
+#define r14 14
+#define r15 15
+#define r16 16
+#define r17 17
+#define r18 18
+#define r19 19
+#define r20 20
+#define r21 21
+#define r22 22
+#define r23 23
+#define r24 24
+#define r25 25
+#define r26 26
+#define r27 27
+#define r28 28
+#define r29 29
+#define r30 30
+#define r31 31
+
+#define cr0 0
+#define cr1 1
+#define cr2 2
+#define cr3 3
+#define cr4 4
+#define cr5 5
+#define cr6 6
+#define cr7 7
+
+#define function_prolog(func_name) .text; \
+ .align 2; \
+ .globl func_name; \
+ func_name:
+#define function_epilog(func_name) .type func_name,@function; \
+ .size func_name,.-func_name
+
+#define function_call(func_name) bl func_name
+
+#define stack_frame_min 8
+#define stack_frame_bc 0
+#define stack_frame_lr 4
+#define stack_neg_off 0
+
+#endif
+
+/*----------------------------------------------------------------------------+
+| Function prolog definition and other DIAB (Elf) defines.
++----------------------------------------------------------------------------*/
+#ifdef ELF_DIAB
+
+fprolog: macro f_name
+ .text
+ .align 2
+ .globl f_name
+f_name:
+ endm
+
+fepilog: macro f_name
+ .type f_name,@function
+ .size f_name,.-f_name
+ endm
+
+#define function_prolog(func_name) fprolog func_name
+#define function_epilog(func_name) fepilog func_name
+#define function_call(func_name) bl func_name
+
+#define stack_frame_min 8
+#define stack_frame_bc 0
+#define stack_frame_lr 4
+#define stack_neg_off 0
+
+#endif
+
+/*----------------------------------------------------------------------------+
+| Function prolog definition and other Xlc (XCOFF) defines.
++----------------------------------------------------------------------------*/
+#ifdef XCOFF
+
+.machine "403ga"
+
+#define r0 0
+#define r1 1
+#define r2 2
+#define r3 3
+#define r4 4
+#define r5 5
+#define r6 6
+#define r7 7
+#define r8 8
+#define r9 9
+#define r10 10
+#define r11 11
+#define r12 12
+#define r13 13
+#define r14 14
+#define r15 15
+#define r16 16
+#define r17 17
+#define r18 18
+#define r19 19
+#define r20 20
+#define r21 21
+#define r22 22
+#define r23 23
+#define r24 24
+#define r25 25
+#define r26 26
+#define r27 27
+#define r28 28
+#define r29 29
+#define r30 30
+#define r31 31
+
+#define cr0 0
+#define cr1 1
+#define cr2 2
+#define cr3 3
+#define cr4 4
+#define cr5 5
+#define cr6 6
+#define cr7 7
+
+#define function_prolog(func_name) .csect .func_name[PR]; \
+ .globl .func_name[PR]; \
+ func_name:
+
+#define function_epilog(func_name) .toc; \
+ .csect func_name[DS]; \
+ .globl func_name[DS]; \
+ .long .func_name[PR]; \
+ .long TOC[tc0]
+
+#define function_call(func_name) .extern .func_name[PR]; \
+ stw r2,stack_frame_toc(r1); \
+ mfspr r2,sprg0; \
+ bl .func_name[PR]; \
+ lwz r2,stack_frame_toc(r1)
+
+#define stack_frame_min 56
+#define stack_frame_bc 0
+#define stack_frame_lr 8
+#define stack_frame_toc 20
+#define stack_neg_off 276
+
+#endif
+#define function_prolog(func_name) .text; \
+ .align 2; \
+ .globl func_name; \
+ func_name:
+#define function_epilog(func_name) .type func_name,@function; \
+ .size func_name,.-func_name
+
+#define function_call(func_name) bl func_name
+
+/*----------------------------------------------------------------------------+
+| Function prolog definition for GNU
++----------------------------------------------------------------------------*/
+#ifdef _GNU_TOOL
+
+#define function_prolog(func_name) .globl func_name; \
+ func_name:
+#define function_epilog(func_name)
+
+#endif
diff --git a/arch/ppc/boot/simple/rw4/rw4_init.S b/arch/ppc/boot/simple/rw4/rw4_init.S
new file mode 100644
index 0000000..b106196
--- /dev/null
+++ b/arch/ppc/boot/simple/rw4/rw4_init.S
@@ -0,0 +1,78 @@
+#define VESTA
+#include "ppc_40x.h"
+#
+ .align 2
+ .text
+#
+# added by linguohui
+ .extern initb_ebiu0, initb_config, hdw_init_finish
+ .extern initb_hsmc0, initb_hsmc1, initb_cache
+# end added
+ .globl HdwInit
+#
+HdwInit:
+#
+#-----------------------------------------------------------------------*
+# If we are not executing from the FLASH get out *
+#-----------------------------------------------------------------------*
+# SAW keep this or comment out a la Hawthorne?
+# r3 contains NIP when used with Linux
+# rlwinm r28, r3, 8, 24, 31 # if MSB == 0xFF -> FLASH address
+# cmpwi r28, 0xff
+# bne locn01
+#
+#
+#------------------------------------------------------------------------
+# Init_cpu. Bank registers are setup for the IBM STB.
+#------------------------------------------------------------------------
+#
+# Setup processor core clock to be driven off chip. This is GPI4 bit
+# twenty. Setup Open Drain, Output Select, Three-State Control, and
+# Three-State Select registers.
+#
+
+
+ pb0pesr = 0x054
+ pb0pear = 0x056
+
+ mflr r30
+
+#-----------------------------------------------------------------------------
+# Vectors will be at 0x1F000000
+# Dummy Machine check handler just does RFI before true handler gets installed
+#-----------------------------------------------------------------------------
+#if 1 /* xuwentao added*/
+#ifdef SDRAM16MB
+ lis r10,0x0000
+ addi r10,r10,0x0000
+#else
+ lis r10,0x1F00
+ addi r10,r10,0x0000
+#endif
+
+ mtspr evpr,r10 #EVPR: 0x0 or 0x1f000000 depending
+ isync # on SDRAM memory model used.
+
+ lis r10,0xFFFF # clear PB0_PESR because some
+ ori r10,r10,0xFFFF # transitions from flash,changed by linguohui
+ mtdcr pb0pesr,r10 # to load RAM image via RiscWatch
+ lis r10,0x0000 # cause PB0_PESR machine checks
+ mtdcr pb0pear,r10
+ addis r10,r10,0x0000 # clear the
+ mtxer r10 # XER just in case...
+#endif /* xuwentao*/
+
+ bl initb_ebiu0 # init EBIU
+
+ bl initb_config # config PPC and board
+
+
+
+
+#------------------------------------------------------------------------
+# EVPR setup moved to top of this function.
+#------------------------------------------------------------------------
+#
+ mtlr r30
+ blr
+ .end
diff --git a/arch/ppc/boot/simple/rw4/rw4_init_brd.S b/arch/ppc/boot/simple/rw4/rw4_init_brd.S
new file mode 100644
index 0000000..386afda
--- /dev/null
+++ b/arch/ppc/boot/simple/rw4/rw4_init_brd.S
@@ -0,0 +1,1125 @@
+/*----------------------------------------------------------------------------+
+| This source code has been made available to you by IBM on an AS-IS
+| basis. Anyone receiving this source is licensed under IBM
+| copyrights to use it in any way he or she deems fit, including
+| copying it, modifying it, compiling it, and redistributing it either
+| with or without modifications. No license under IBM patents or
+| patent applications is to be implied by the copyright license.
+|
+| Any user of this software should understand that IBM cannot provide
+| technical support for this software and will not be responsible for
+| any consequences resulting from the use of this software.
+|
+| Any person who transfers this source code or any derivative work
+| must include the IBM copyright notice, this paragraph, and the
+| preceding two paragraphs in the transferred software.
+|
+| COPYRIGHT I B M CORPORATION 1997
+| LICENSED MATERIAL - PROGRAM PROPERTY OF I B M
++----------------------------------------------------------------------------*/
+/*----------------------------------------------------------------------------+
+| Author: Tony J. Cerreto
+| Component: BSPS
+| File: init_brd.s
+| Purpose: Vesta Evaluation Board initialization subroutines. The following
+| routines are available:
+| 1. INITB_EBIU0: Initialize EBIU0.
+| 2. INITB_CONFIG: Configure board.
+| 3. INITB_HSMC0: Initialize HSMC0 (SDRAM).
+| 4. INITB_HSMC1: Initialize HSMC1 (SDRAM).
+| 5. INITB_CACHE: Initialize Data and Instruction Cache.
+| 6. INITB_DCACHE: Initialize Data Cache.
+| 7. INITB_ICACHE: Initialize Instruction Cache.
+| 8. INITB_GET_CSPD: Get CPU Speed (Bus Speed and Processor Speed)
+|
+| Changes:
+| Date: Author Comment:
+| --------- ------ --------
+| 01-Mar-00 tjc Created
+| 04-Mar-00 jfh Modified CIC_SEL3_VAL to support 1284 (Mux3 & GPIO 21-28)
+| 04-Mar-00 jfh Modified XILINIX Reg 0 to support 1284 (Mux3 & GPIO 21-28)
+| 04-Mar-00 jfh Modified XILINIX Reg 1 to support 1284 (Mux3 & GPIO 21-28)
+| 04-Mar-00 jfh Modified XILINIX Reg 4 to support 1284 (Mux3 & GPIO 21-28)
+| 19-May-00 rlb Relcoated HSMC0 to 0x1F000000 to support 32MB of contiguous
+| SDRAM space. Changed cache ctl regs to reflect this.
+| 22-May-00 tjc Changed initb_get_cspd interface and eliminated
+| initb_get_bspd routines.
+| 26-May-00 tjc Added two nop instructions after all mtxxx/mfxxx
+| instructions due to PPC405 bug.
++----------------------------------------------------------------------------*/
+#define VESTA
+#include "ppc_40x.h"
+#include "stb.h"
+
+/*----------------------------------------------------------------------------+
+| BOARD CONFIGURATION DEFINES
++----------------------------------------------------------------------------*/
+#define CBS0_CR_VAL 0x00000002 /* CBS control reg value */
+#define CIC0_CR_VAL 0xD0800448 /* CIC control reg value */
+#define CIC0_SEL3_VAL 0x11500000 /* CIC select 3 reg value */
+#define CIC0_VCR_VAL 0x00631700 /* CIC video cntl reg value */
+
+/*----------------------------------------------------------------------------+
+| EBIU0 BANK REGISTERS DEFINES
++----------------------------------------------------------------------------*/
+#define EBIU0_BRCRH0_VAL 0x00000000 /* BR High 0 (Extension Reg)*/
+#define EBIU0_BRCRH1_VAL 0x00000000 /* BR High 1 (Extension Reg)*/
+#define EBIU0_BRCRH2_VAL 0x40000000 /* BR High 2 (Extension Reg)*/
+#define EBIU0_BRCRH3_VAL 0x40000000 /* BR High 3 (Extension Reg)*/
+#define EBIU0_BRCRH4_VAL 0x00000000 /* BR High 4 (Extension Reg)*/
+#define EBIU0_BRCRH5_VAL 0x00000000 /* BR High 5 (Extension Reg)*/
+#define EBIU0_BRCRH6_VAL 0x00000000 /* BR High 6 (Extension Reg)*/
+#define EBIU0_BRCRH7_VAL 0x40000000 /* BR High 7 (Extension Reg)*/
+
+#define EBIU0_BRCR0_VAL 0xFC58BFFE /* BR 0: 16 bit Flash 4 MB */
+#define EBIU0_BRCR1_VAL 0xFF00BFFE /* BR 1: Ext Connector 1 MB */
+#if 1
+#define EBIU0_BRCR2_VAL 0x207CFFBE /* BR 2: Xilinx 8 MB */
+ /* twt == 0x3f */
+#else
+#define EBIU0_BRCR2_VAL 0x207CCFBE /* BR 2: Xilinx 8 MB */
+ /* twt == 0x0f */
+#endif
+#define EBIU0_BRCR3_VAL 0x407CBFBE /* BR 3: IDE Drive 8 MB */
+#define EBIU0_BRCR4_VAL 0xFF00BFFF /* BR 4: Disabled. 0 MB */
+#define EBIU0_BRCR5_VAL 0xFF00BFFF /* BR 5: Disabled. 0 MB */
+#define EBIU0_BRCR6_VAL 0xFF00BFFF /* BR 6: Disabled. 0 MB */
+#define EBIU0_BRCR7_VAL 0xCE3F0003 /* BR 7: Line Mode DMA 2 MB */
+
+/*----------------------------------------------------------------------------+
+| GPIO DEFINES
++----------------------------------------------------------------------------*/
+#define STB_GPIO0_OUTPUT (STB_GPIO0_BASE_ADDRESS+ 0x00)
+#define STB_GPIO0_TC (STB_GPIO0_BASE_ADDRESS+ 0x04)
+#define STB_GPIO0_OS_0_31 (STB_GPIO0_BASE_ADDRESS+ 0x08)
+#define STB_GPIO0_OS_32_63 (STB_GPIO0_BASE_ADDRESS+ 0x0C)
+#define STB_GPIO0_TS_0_31 (STB_GPIO0_BASE_ADDRESS+ 0x10)
+#define STB_GPIO0_TS_32_63 (STB_GPIO0_BASE_ADDRESS+ 0x14)
+#define STB_GPIO0_OD (STB_GPIO0_BASE_ADDRESS+ 0x18)
+#define STB_GPIO0_INPUT (STB_GPIO0_BASE_ADDRESS+ 0x1C)
+#define STB_GPIO0_R1 (STB_GPIO0_BASE_ADDRESS+ 0x20)
+#define STB_GPIO0_R2 (STB_GPIO0_BASE_ADDRESS+ 0x24)
+#define STB_GPIO0_R3 (STB_GPIO0_BASE_ADDRESS+ 0x28)
+#define STB_GPIO0_IS_1_0_31 (STB_GPIO0_BASE_ADDRESS+ 0x30)
+#define STB_GPIO0_IS_1_32_63 (STB_GPIO0_BASE_ADDRESS+ 0x34)
+#define STB_GPIO0_IS_2_0_31 (STB_GPIO0_BASE_ADDRESS+ 0x38)
+#define STB_GPIO0_IS_2_32_63 (STB_GPIO0_BASE_ADDRESS+ 0x3C)
+#define STB_GPIO0_IS_3_0_31 (STB_GPIO0_BASE_ADDRESS+ 0x40)
+#define STB_GPIO0_IS_3_32_63 (STB_GPIO0_BASE_ADDRESS+ 0x44)
+#define STB_GPIO0_SS_1 (STB_GPIO0_BASE_ADDRESS+ 0x50)
+#define STB_GPIO0_SS_2 (STB_GPIO0_BASE_ADDRESS+ 0x54)
+#define STB_GPIO0_SS_3 (STB_GPIO0_BASE_ADDRESS+ 0x58)
+
+#define GPIO0_TC_VAL 0x0C020004 /* three-state control val */
+#define GPIO0_OS_0_31_VAL 0x51A00004 /* output select 0-31 val */
+#define GPIO0_OS_32_63_VAL 0x0000002F /* output select 32-63 val */
+#define GPIO0_TS_0_31_VAL 0x51A00000 /* three-state sel 0-31 val*/
+#define GPIO0_TS_32_63_VAL 0x0000000F /* three-state sel 32-63 val*/
+#define GPIO0_OD_VAL 0xC0000004 /* open drain val */
+#define GPIO0_IS_1_0_31_VAL 0x50000151 /* input select 1 0-31 val */
+#define GPIO0_IS_1_32_63_VAL 0x00000000 /* input select 1 32-63 val */
+#define GPIO0_IS_2_0_31_VAL 0x00000000 /* input select 2 0-31 val */
+#define GPIO0_IS_2_32_63_VAL 0x00000000 /* input select 2 32-63 val */
+#define GPIO0_IS_3_0_31_VAL 0x00000440 /* input select 3 0-31 val */
+#define GPIO0_IS_3_32_63_VAL 0x00000000 /* input select 3 32-63 val */
+#define GPIO0_SS_1_VAL 0x00000000 /* sync select 1 val */
+#define GPIO0_SS_2_VAL 0x00000000 /* sync select 2 val */
+#define GPIO0_SS_3_VAL 0x00000000 /* sync select 3 val */
+
+/*----------------------------------------------------------------------------+
+| XILINX DEFINES
++----------------------------------------------------------------------------*/
+#define STB_XILINX_LED (STB_FPGA_BASE_ADDRESS+ 0x0100)
+#define STB_XILINX1_REG0 (STB_FPGA_BASE_ADDRESS+ 0x40000)
+#define STB_XILINX1_REG1 (STB_FPGA_BASE_ADDRESS+ 0x40002)
+#define STB_XILINX1_REG2 (STB_FPGA_BASE_ADDRESS+ 0x40004)
+#define STB_XILINX1_REG3 (STB_FPGA_BASE_ADDRESS+ 0x40006)
+#define STB_XILINX1_REG4 (STB_FPGA_BASE_ADDRESS+ 0x40008)
+#define STB_XILINX1_REG5 (STB_FPGA_BASE_ADDRESS+ 0x4000A)
+#define STB_XILINX1_REG6 (STB_FPGA_BASE_ADDRESS+ 0x4000C)
+#define STB_XILINX1_ID (STB_FPGA_BASE_ADDRESS+ 0x4000E)
+#define STB_XILINX1_FLUSH (STB_FPGA_BASE_ADDRESS+ 0x4000E)
+#define STB_XILINX2_REG0 (STB_FPGA_BASE_ADDRESS+ 0x80000)
+#define STB_XILINX2_REG1 (STB_FPGA_BASE_ADDRESS+ 0x80002)
+#define STB_XILINX2_REG2 (STB_FPGA_BASE_ADDRESS+ 0x80004)
+
+#define XILINX1_R0_VAL 0x2440 /* Xilinx 1 Register 0 Val */
+#define XILINX1_R1_VAL 0x0025 /* Xilinx 1 Register 1 Val */
+#define XILINX1_R2_VAL 0x0441 /* Xilinx 1 Register 2 Val */
+#define XILINX1_R3_VAL 0x0008 /* Xilinx 1 Register 3 Val */
+#define XILINX1_R4_VAL 0x0100 /* Xilinx 1 Register 4 Val */
+#define XILINX1_R5_VAL 0x6810 /* Xilinx 1 Register 5 Val */
+#define XILINX1_R6_VAL 0x0000 /* Xilinx 1 Register 6 Val */
+#if 0
+#define XILINX2_R0_VAL 0x0008 /* Xilinx 2 Register 0 Val */
+#define XILINX2_R1_VAL 0x0000 /* Xilinx 2 Register 1 Val */
+#else
+#define XILINX2_R0_VAL 0x0018 /* disable IBM IrDA RxD */
+#define XILINX2_R1_VAL 0x0008 /* enable SICC MAX chip */
+#endif
+#define XILINX2_R2_VAL 0x0000 /* Xilinx 2 Register 2 Val */
+
+/*----------------------------------------------------------------------------+
+| HSMC BANK REGISTERS DEFINES
++----------------------------------------------------------------------------*/
+#ifdef SDRAM16MB
+#define HSMC0_BR0_VAL 0x000D2D55 /* 0x1F000000-007FFFFF R/W */
+#define HSMC0_BR1_VAL 0x008D2D55 /* 0x1F800000-1FFFFFFF R/W */
+#else
+#define HSMC0_BR0_VAL 0x1F0D2D55 /* 0x1F000000-007FFFFF R/W */
+#define HSMC0_BR1_VAL 0x1F8D2D55 /* 0x1F800000-1FFFFFFF R/W */
+#endif
+#define HSMC1_BR0_VAL 0xA00D2D55 /* 0xA0000000-A07FFFFF R/W */
+#define HSMC1_BR1_VAL 0xA08D2D55 /* 0xA0800000-A0FFFFFF R/W */
+
+/*----------------------------------------------------------------------------+
+| CACHE DEFINES
++----------------------------------------------------------------------------*/
+#define DCACHE_NLINES 128 /* no. D-cache lines */
+#define DCACHE_NBYTES 32 /* no. bytes/ D-cache line */
+#define ICACHE_NLINES 256 /* no. I-cache lines */
+#define ICACHE_NBYTES 32 /* no. bytes/ I-cache line */
+#ifdef SDRAM16MB
+#define DCACHE_ENABLE 0x80000000 /* D-cache regions to enable*/
+#define ICACHE_ENABLE 0x80000001 /* I-cache regions to enable*/
+#else
+#define DCACHE_ENABLE 0x18000000 /* D-cache regions to enable*/
+#define ICACHE_ENABLE 0x18000001 /* I-cache regions to enable*/
+#endif
+
+/*----------------------------------------------------------------------------+
+| CPU CORE SPEED CALCULATION DEFINES
++----------------------------------------------------------------------------*/
+#define GCS_LCNT 500000 /* CPU speed loop count */
+#define GCS_TROW_BYTES 8 /* no. bytes in table row */
+#define GCS_CTICK_TOL 100 /* allowable clock tick tol */
+#define GCS_NMULT 4 /* no. of core speed mults */
+
+ /*--------------------------------------------------------------------+
+ | No. 13.5Mhz
+ | Clock Ticks
+ | based on a
+ | loop count Bus
+ | of 100,000 Speed
+ +--------------------------------------------------------------------*/
+gcs_lookup_table:
+ .int 50000, 54000000 /* 54.0 Mhz */
+ .int 66667, 40500000 /* 40.5 Mhz */
+ .int 54545, 49500000 /* 49.5 Mhz */
+ .int 46154, 58500000 /* 58.5 Mhz */
+ .int 0, 0 /* end of table flag */
+
+
+/*****************************************************************************+
+| XXXXXXX XXX XXX XXXXXX XXXXXXX XXXXXX XX XX XX XXXX
+| XX X XX XX X XX X XX X XX XX XXX XX XXXX XX
+| XX X XXX XX XX X XX XX XXXX XX XX XX XX
+| XXXX X XX XXXX XXXXX XX XXXX XX XX XX
+| XX X XXX XX XX X XX XX XX XXX XXXXXX XX
+| XX X XX XX XX XX X XX XX XX XX XX XX XX XX
+| XXXXXXX XXX XXX XXXX XXXXXXX XXX XX XX XX XX XX XXXXXXX
++*****************************************************************************/
+/******************************************************************************
+|
+| Routine: INITB_EBIU0.
+|
+| Purpose: Initialize all the EBIU0 Bank Registers
+| Parameters: None.
+| Returns: None.
+|
+******************************************************************************/
+ function_prolog(initb_ebiu0)
+ /*--------------------------------------------------------------------+
+ | Set EBIU0 Bank 0
+ +--------------------------------------------------------------------*/
+ lis r10,EBIU0_BRCR0_VAL@h
+ ori r10,r10,EBIU0_BRCR0_VAL@l
+ mtdcr ebiu0_brcr0,r10
+ lis r10,EBIU0_BRCRH0_VAL@h
+ ori r10,r10,EBIU0_BRCRH0_VAL@l
+ mtdcr ebiu0_brcrh0,r10
+
+ /*--------------------------------------------------------------------+
+ | Set EBIU0 Bank 1
+ +--------------------------------------------------------------------*/
+ lis r10,EBIU0_BRCR1_VAL@h
+ ori r10,r10,EBIU0_BRCR1_VAL@l
+ mtdcr ebiu0_brcr1,r10
+ lis r10,EBIU0_BRCRH1_VAL@h
+ ori r10,r10,EBIU0_BRCRH1_VAL@l
+ mtdcr ebiu0_brcrh1,r10
+
+ /*--------------------------------------------------------------------+
+ | Set EBIU0 Bank 2
+ +--------------------------------------------------------------------*/
+ lis r10,EBIU0_BRCR2_VAL@h
+ ori r10,r10,EBIU0_BRCR2_VAL@l
+ mtdcr ebiu0_brcr2,r10
+ lis r10,EBIU0_BRCRH2_VAL@h
+ ori r10,r10,EBIU0_BRCRH2_VAL@l
+ mtdcr ebiu0_brcrh2,r10
+
+ /*--------------------------------------------------------------------+
+ | Set EBIU0 Bank 3
+ +--------------------------------------------------------------------*/
+ lis r10,EBIU0_BRCR3_VAL@h
+ ori r10,r10,EBIU0_BRCR3_VAL@l
+ mtdcr ebiu0_brcr3,r10
+ lis r10,EBIU0_BRCRH3_VAL@h
+ ori r10,r10,EBIU0_BRCRH3_VAL@l
+ mtdcr ebiu0_brcrh3,r10
+
+ /*--------------------------------------------------------------------+
+ | Set EBIU0 Bank 4
+ +--------------------------------------------------------------------*/
+ lis r10,EBIU0_BRCR4_VAL@h
+ ori r10,r10,EBIU0_BRCR4_VAL@l
+ mtdcr ebiu0_brcr4,r10
+ lis r10,EBIU0_BRCRH4_VAL@h
+ ori r10,r10,EBIU0_BRCRH4_VAL@l
+ mtdcr ebiu0_brcrh4,r10
+
+ /*--------------------------------------------------------------------+
+ | Set EBIU0 Bank 5
+ +--------------------------------------------------------------------*/
+ lis r10,EBIU0_BRCR5_VAL@h
+ ori r10,r10,EBIU0_BRCR5_VAL@l
+ mtdcr ebiu0_brcr5,r10
+ lis r10,EBIU0_BRCRH5_VAL@h
+ ori r10,r10,EBIU0_BRCRH5_VAL@l
+ mtdcr ebiu0_brcrh5,r10
+
+ /*--------------------------------------------------------------------+
+ | Set EBIU0 Bank 6
+ +--------------------------------------------------------------------*/
+ lis r10,EBIU0_BRCR6_VAL@h
+ ori r10,r10,EBIU0_BRCR6_VAL@l
+ mtdcr ebiu0_brcr6,r10
+ lis r10,EBIU0_BRCRH6_VAL@h
+ ori r10,r10,EBIU0_BRCRH6_VAL@l
+ mtdcr ebiu0_brcrh6,r10
+
+ /*--------------------------------------------------------------------+
+ | Set EBIU0 Bank 7
+ +--------------------------------------------------------------------*/
+ lis r10,EBIU0_BRCR7_VAL@h
+ ori r10,r10,EBIU0_BRCR7_VAL@l
+ mtdcr ebiu0_brcr7,r10
+ lis r10,EBIU0_BRCRH7_VAL@h
+ ori r10,r10,EBIU0_BRCRH7_VAL@l
+ mtdcr ebiu0_brcrh7,r10
+
+ blr
+ function_epilog(initb_ebiu0)
+
+
+/******************************************************************************
+|
+| Routine: INITB_CONFIG
+|
+| Purpose: Configure the Vesta Evaluation Board. The following items
+| will be configured:
+| 1. Cross-Bar Switch.
+| 2. Chip Interconnect.
+| 3. Clear/reset key PPC registers.
+| 4. Xilinx and GPIO Registers.
+|
+| Returns: None.
+|
+******************************************************************************/
+ function_prolog(initb_config)
+ /*--------------------------------------------------------------------+
+ | Init CROSS-BAR SWITCH
+ +--------------------------------------------------------------------*/
+ lis r10,CBS0_CR_VAL@h /* r10 <- CBS Cntl Reg val */
+ ori r10,r10,CBS0_CR_VAL@l
+ mtdcr cbs0_cr,r10
+
+ /*--------------------------------------------------------------------+
+ | Init Chip-Interconnect (CIC) Registers
+ +--------------------------------------------------------------------*/
+ lis r10,CIC0_CR_VAL@h /* r10 <- CIC Cntl Reg val */
+ ori r10,r10,CIC0_CR_VAL@l
+ mtdcr cic0_cr,r10
+
+ lis r10,CIC0_SEL3_VAL@h /* r10 <- CIC SEL3 Reg val */
+ ori r10,r10,CIC0_SEL3_VAL@l
+ mtdcr cic0_sel3,r10
+
+ lis r10,CIC0_VCR_VAL@h /* r10 <- CIC Vid C-Reg val */
+ ori r10,r10,CIC0_VCR_VAL@l
+ mtdcr cic0_vcr,r10
+
+ /*--------------------------------------------------------------------+
+ | Clear SGR and DCWR
+ +--------------------------------------------------------------------*/
+ li r10,0x0000
+ mtspr sgr,r10
+ mtspr dcwr,r10
+
+ /*--------------------------------------------------------------------+
+ | Clear/set up some machine state registers.
+ +--------------------------------------------------------------------*/
+ li r10,0x0000 /* r10 <- 0 */
+ mtdcr ebiu0_besr,r10 /* clr Bus Err Syndrome Reg */
+ mtspr esr,r10 /* clr Exceptn Syndrome Reg */
+ mttcr r10 /* timer control register */
+
+ mtdcr uic0_er,r10 /* disable all interrupts */
+
+ /* UIC_IIC0 | UIC_IIC1 | UIC_U0 | UIC_IR_RCV | UIC_IR_XMIT */
+ lis r10, 0x00600e00@h
+ ori r10,r10,0x00600e00@l
+ mtdcr uic0_pr,r10
+
+ li r10,0x00000020 /* UIC_EIR1 */
+ mtdcr uic0_tr,r10
+
+ lis r10,0xFFFF /* r10 <- 0xFFFFFFFF */
+ ori r10,r10,0xFFFF /* */
+ mtdbsr r10 /* clear/reset the dbsr */
+ mtdcr uic0_sr,r10 /* clear pending interrupts */
+
+ li r10,0x1000 /* set Machine Exception bit*/
+ oris r10,r10,0x2 /* set Criticl Exception bit*/
+ mtmsr r10 /* change MSR */
+
+ /*--------------------------------------------------------------------+
+ | Clear XER.
+ +--------------------------------------------------------------------*/
+ li r10,0x0000
+ mtxer r10
+
+ /*--------------------------------------------------------------------+
+ | Init GPIO0 Registers
+ +--------------------------------------------------------------------*/
+ lis r10, STB_GPIO0_TC@h /* Three-state control */
+ ori r10,r10,STB_GPIO0_TC@l
+ lis r11, GPIO0_TC_VAL@h
+ ori r11,r11,GPIO0_TC_VAL@l
+ stw r11,0(r10)
+
+ lis r10, STB_GPIO0_OS_0_31@h /* output select 0-31 */
+ ori r10,r10,STB_GPIO0_OS_0_31@l
+ lis r11, GPIO0_OS_0_31_VAL@h
+ ori r11,r11,GPIO0_OS_0_31_VAL@l
+ stw r11,0(r10)
+
+ lis r10, STB_GPIO0_OS_32_63@h /* output select 32-63 */
+ ori r10,r10,STB_GPIO0_OS_32_63@l
+ lis r11, GPIO0_OS_32_63_VAL@h
+ ori r11,r11,GPIO0_OS_32_63_VAL@l
+ stw r11,0(r10)
+
+ lis r10, STB_GPIO0_TS_0_31@h /* three-state select 0-31 */
+ ori r10,r10,STB_GPIO0_TS_0_31@l
+ lis r11, GPIO0_TS_0_31_VAL@h
+ ori r11,r11,GPIO0_TS_0_31_VAL@l
+ stw r11,0(r10)
+
+ lis r10, STB_GPIO0_TS_32_63@h /* three-state select 32-63 */
+ ori r10,r10,STB_GPIO0_TS_32_63@l
+ lis r11, GPIO0_TS_32_63_VAL@h
+ ori r11,r11,GPIO0_TS_32_63_VAL@l
+ stw r11,0(r10)
+
+ lis r10, STB_GPIO0_OD@h /* open drain */
+ ori r10,r10,STB_GPIO0_OD@l
+ lis r11, GPIO0_OD_VAL@h
+ ori r11,r11,GPIO0_OD_VAL@l
+ stw r11,0(r10)
+
+ lis r10, STB_GPIO0_IS_1_0_31@h /* input select 1, 0-31 */
+ ori r10,r10,STB_GPIO0_IS_1_0_31@l
+ lis r11, GPIO0_IS_1_0_31_VAL@h
+ ori r11,r11,GPIO0_IS_1_0_31_VAL@l
+ stw r11,0(r10)
+
+ lis r10, STB_GPIO0_IS_1_32_63@h /* input select 1, 32-63 */
+ ori r10,r10,STB_GPIO0_IS_1_32_63@l
+ lis r11, GPIO0_IS_1_32_63_VAL@h
+ ori r11,r11,GPIO0_IS_1_32_63_VAL@l
+ stw r11,0(r10)
+
+ lis r10, STB_GPIO0_IS_2_0_31@h /* input select 2, 0-31 */
+ ori r10,r10,STB_GPIO0_IS_2_0_31@l
+ lis r11, GPIO0_IS_2_0_31_VAL@h
+ ori r11,r11,GPIO0_IS_2_0_31_VAL@l
+ stw r11,0(r10)
+
+ lis r10, STB_GPIO0_IS_2_32_63@h /* input select 2, 32-63 */
+ ori r10,r10,STB_GPIO0_IS_2_32_63@l
+ lis r11, GPIO0_IS_2_32_63_VAL@h
+ ori r11,r11,GPIO0_IS_2_32_63_VAL@l
+ stw r11,0(r10)
+
+ lis r10, STB_GPIO0_IS_3_0_31@h /* input select 3, 0-31 */
+ ori r10,r10,STB_GPIO0_IS_3_0_31@l
+ lis r11, GPIO0_IS_3_0_31_VAL@h
+ ori r11,r11,GPIO0_IS_3_0_31_VAL@l
+ stw r11,0(r10)
+
+ lis r10, STB_GPIO0_IS_3_32_63@h /* input select 3, 32-63 */
+ ori r10,r10,STB_GPIO0_IS_3_32_63@l
+ lis r11, GPIO0_IS_3_32_63_VAL@h
+ ori r11,r11,GPIO0_IS_3_32_63_VAL@l
+ stw r11,0(r10)
+
+ lis r10, STB_GPIO0_SS_1@h /* sync select 1 */
+ ori r10,r10,STB_GPIO0_SS_1@l
+ lis r11, GPIO0_SS_1_VAL@h
+ ori r11,r11,GPIO0_SS_1_VAL@l
+ stw r11,0(r10)
+
+ lis r10, STB_GPIO0_SS_2@h /* sync select 2 */
+ ori r10,r10,STB_GPIO0_SS_2@l
+ lis r11, GPIO0_SS_2_VAL@h
+ ori r11,r11,GPIO0_SS_2_VAL@l
+ stw r11,0(r10)
+
+ lis r10, STB_GPIO0_SS_3@h /* sync select 3 */
+ ori r10,r10,STB_GPIO0_SS_3@l
+ lis r11, GPIO0_SS_3_VAL@h
+ ori r11,r11,GPIO0_SS_3_VAL@l
+ stw r11,0(r10)
+
+ /*--------------------------------------------------------------------+
+ | Init Xilinx #1 Registers
+ +--------------------------------------------------------------------*/
+ lis r10, STB_XILINX1_REG0@h /* init Xilinx1 Reg 0 */
+ ori r10,r10,STB_XILINX1_REG0@l
+ li r11,XILINX1_R0_VAL
+ sth r11,0(r10)
+
+ lis r10, STB_XILINX1_REG1@h /* init Xilinx1 Reg 1 */
+ ori r10,r10,STB_XILINX1_REG1@l
+ li r11,XILINX1_R1_VAL
+ sth r11,0(r10)
+
+ lis r10, STB_XILINX1_REG2@h /* init Xilinx1 Reg 2 */
+ ori r10,r10,STB_XILINX1_REG2@l
+ li r11,XILINX1_R2_VAL
+ sth r11,0(r10)
+
+ lis r10, STB_XILINX1_REG3@h /* init Xilinx1 Reg 3 */
+ ori r10,r10,STB_XILINX1_REG3@l
+ li r11,XILINX1_R3_VAL
+ sth r11,0(r10)
+
+ lis r10, STB_XILINX1_REG4@h /* init Xilinx1 Reg 4 */
+ ori r10,r10,STB_XILINX1_REG4@l
+ li r11,XILINX1_R4_VAL
+ sth r11,0(r10)
+
+ lis r10, STB_XILINX1_REG5@h /* init Xilinx1 Reg 5 */
+ ori r10,r10,STB_XILINX1_REG5@l
+ li r11,XILINX1_R5_VAL
+ sth r11,0(r10)
+
+ lis r10, STB_XILINX1_REG6@h /* init Xilinx1 Reg 6 */
+ ori r10,r10,STB_XILINX1_REG6@l
+ li r11,XILINX1_R6_VAL
+ sth r11,0(r10)
+
+ lis r10, STB_XILINX1_FLUSH@h /* latch registers in Xilinx*/
+ ori r10,r10,STB_XILINX1_FLUSH@l
+ li r11,0x0000
+ sth r11,0(r10)
+
+ /*--------------------------------------------------------------------+
+ | Init Xilinx #2 Registers
+ +--------------------------------------------------------------------*/
+ lis r10, STB_XILINX2_REG0@h /* init Xilinx2 Reg 0 */
+ ori r10,r10,STB_XILINX2_REG0@l
+ li r11,XILINX2_R0_VAL
+ sth r11,0(r10)
+
+ lis r10, STB_XILINX2_REG1@h /* init Xilinx2 Reg 1 */
+ ori r10,r10,STB_XILINX2_REG1@l
+ li r11,XILINX2_R1_VAL
+ sth r11,0(r10)
+
+ lis r10, STB_XILINX2_REG2@h /* init Xilinx2 Reg 2 */
+ ori r10,r10,STB_XILINX2_REG2@l
+ li r11,XILINX2_R2_VAL
+ sth r11,0(r10)
+
+ blr
+ function_epilog(initb_config)
+
+
+/******************************************************************************
+|
+| Routine: INITB_HSMC0.
+|
+| Purpose: Initialize the HSMC0 Registers for SDRAM
+| Parameters: None.
+| Returns: R3 = 0: Successful
+| = -1: Unsuccessful, SDRAM did not reset properly.
+|
+******************************************************************************/
+ function_prolog(initb_hsmc0)
+ mflr r0 /* Save return addr */
+
+ /*--------------------------------------------------------------------+
+ | Set Global SDRAM Controller to recommended default
+ +--------------------------------------------------------------------*/
+ lis r10,0x6C00
+ ori r10,r10,0x0000
+ mtdcr hsmc0_gr,r10
+
+ /*--------------------------------------------------------------------+
+ | Set HSMC0 Data Register to recommended default
+ +--------------------------------------------------------------------*/
+ lis r10,0x0037
+ ori r10,r10,0x0000
+ mtdcr hsmc0_data,r10
+
+ /*--------------------------------------------------------------------+
+ | Init HSMC0 Bank Register 0
+ +--------------------------------------------------------------------*/
+ lis r10,HSMC0_BR0_VAL@h
+ ori r10,r10,HSMC0_BR0_VAL@l
+ mtdcr hsmc0_br0,r10
+
+ /*--------------------------------------------------------------------+
+ | Init HSMC0 Bank Register 1
+ +--------------------------------------------------------------------*/
+ lis r10,HSMC0_BR1_VAL@h
+ ori r10,r10,HSMC0_BR1_VAL@l
+ mtdcr hsmc0_br1,r10
+
+ /*--------------------------------------------------------------------+
+ | Set HSMC0 Control Reg 0
+ +--------------------------------------------------------------------*/
+ lis r10,0x8077 /* PRECHARGE ALL DEVICE BKS */
+ ori r10,r10,0x0000
+ mtdcr hsmc0_cr0,r10
+ li r3,0x0000
+ bl hsmc_cr_wait /* wait for op completion */
+ cmpwi cr0,r3,0x0000
+ bne cr0,hsmc0_err
+
+ lis r10,0x8078 /* AUTO-REFRESH */
+ ori r10,r10,0x0000
+ mtdcr hsmc0_cr0,r10
+ li r3,0x0000
+ bl hsmc_cr_wait /* wait for op completion */
+ cmpwi cr0,r3,0x0000
+ bne cr0,hsmc0_err
+
+ lis r10,0x8070 /* PROG MODE W/DATA REG VAL */
+ ori r10,r10,0x8000
+ mtdcr hsmc0_cr0,r10
+ li r3,0x0000
+ bl hsmc_cr_wait /* wait for op completion */
+ cmpwi cr0,r3,0x0000
+ bne hsmc0_err
+
+ /*--------------------------------------------------------------------+
+ | Set HSMC0 Control Reg 1
+ +--------------------------------------------------------------------*/
+ lis r10,0x8077 /* PRECHARGE ALL DEVICE BKS */
+ ori r10,r10,0x0000
+ mtdcr hsmc0_cr1,r10
+ li r3,0x0001
+ bl hsmc_cr_wait /* wait for op completion */
+ cmpwi cr0,r3,0x0000
+ bne cr0,hsmc0_err
+
+ lis r10,0x8078 /* AUTO-REFRESH */
+ ori r10,r10,0x0000
+ mtdcr hsmc0_cr1,r10
+ li r3,0x0001
+ bl hsmc_cr_wait /* wait for op completion */
+ cmpwi cr0,r3,0x0000
+ bne cr0,hsmc0_err
+
+ lis r10,0x8070 /* PROG MODE W/DATA REG VAL */
+ ori r10,r10,0x8000
+ mtdcr hsmc0_cr1,r10
+ li r3,0x0001
+ bl hsmc_cr_wait /* wait for op completion */
+ cmpwi cr0,r3,0x0000
+ bne cr0,hsmc0_err
+
+ /*--------------------------------------------------------------------+
+ | Set HSMC0 Refresh Register
+ +--------------------------------------------------------------------*/
+ lis r10,0x0FE1
+ ori r10,r10,0x0000
+ mtdcr hsmc0_crr,r10
+ li r3,0
+
+hsmc0_err:
+ mtlr r0
+ blr
+ function_epilog(initb_hsmc0)
+
+
+/******************************************************************************
+|
+| Routine: INITB_HSMC1.
+|
+| Purpose: Initialize the HSMC1 Registers for SDRAM
+| Parameters: None.
+| Returns: R3 = 0: Successful
+| = -1: Unsuccessful, SDRAM did not reset properly.
+|
+******************************************************************************/
+ function_prolog(initb_hsmc1)
+ mflr r0 /* Save return addr */
+
+ /*--------------------------------------------------------------------+
+ | Set Global SDRAM Controller to recommended default
+ +--------------------------------------------------------------------*/
+ lis r10,0x6C00
+ ori r10,r10,0x0000
+ mtdcr hsmc1_gr,r10
+
+ /*--------------------------------------------------------------------+
+ | Set HSMC1 Data Register to recommended default
+ +--------------------------------------------------------------------*/
+ lis r10,0x0037
+ ori r10,r10,0x0000
+ mtdcr hsmc1_data,r10
+
+ /*--------------------------------------------------------------------+
+ | Init HSMC1 Bank Register 0
+ +--------------------------------------------------------------------*/
+ lis r10,HSMC1_BR0_VAL@h
+ ori r10,r10,HSMC1_BR0_VAL@l
+ mtdcr hsmc1_br0,r10
+
+ /*--------------------------------------------------------------------+
+ | Init HSMC1 Bank Register 1
+ +--------------------------------------------------------------------*/
+ lis r10,HSMC1_BR1_VAL@h
+ ori r10,r10,HSMC1_BR1_VAL@l
+ mtdcr hsmc1_br1,r10
+
+ /*--------------------------------------------------------------------+
+ | Set HSMC1 Control Reg 0
+ +--------------------------------------------------------------------*/
+ lis r10,0x8077 /* PRECHARGE ALL DEVICE BANKS */
+ ori r10,r10,0x0000
+ mtdcr hsmc1_cr0,r10
+ li r3,0x0002
+ bl hsmc_cr_wait /* wait for operation completion */
+ cmpwi cr0,r3,0x0000
+ bne hsmc1_err
+
+ lis r10,0x8078 /* AUTO-REFRESH */
+ ori r10,r10,0x0000
+ mtdcr hsmc1_cr0,r10
+ li r3,0x0002
+ bl hsmc_cr_wait /* wait for operation completion */
+ cmpwi cr0,r3,0x0000
+ bne hsmc1_err
+
+ lis r10,0x8070 /* PROGRAM MODE W/DATA REG VALUE */
+ ori r10,r10,0x8000
+ mtdcr hsmc1_cr0,r10
+ li r3,0x0002
+ bl hsmc_cr_wait /* wait for operation completion */
+ cmpwi cr0,r3,0x0000
+ bne hsmc1_err
+
+ /*--------------------------------------------------------------------+
+ | Set HSMC1 Control Reg 1
+ +--------------------------------------------------------------------*/
+ lis r10,0x8077 /* PRECHARGE ALL DEVICE BKS */
+ ori r10,r10,0x0000
+ mtdcr hsmc1_cr1,r10
+ li r3,0x0003
+ bl hsmc_cr_wait /* wait for op completion */
+ cmpwi cr0,r3,0x0000
+ bne hsmc1_err
+
+ lis r10,0x8078 /* AUTO-REFRESH */
+ ori r10,r10,0x0000
+ mtdcr hsmc1_cr1,r10
+ li r3,0x0003
+ bl hsmc_cr_wait /* wait for op completion */
+ cmpwi cr0,r3,0x0000
+ bne hsmc1_err
+
+ lis r10,0x8070 /* PROG MODE W/DATA REG VAL */
+ ori r10,r10,0x8000
+ mtdcr hsmc1_cr1,r10
+ li r3,0x0003
+ bl hsmc_cr_wait /* wait for op completion */
+ cmpwi cr0,r3,0x0000
+ bne hsmc1_err
+
+ /*--------------------------------------------------------------------+
+ | Set HSMC1 Refresh Register
+ +--------------------------------------------------------------------*/
+ lis r10,0x0FE1
+ ori r10,r10,0x0000
+ mtdcr hsmc1_crr,r10
+ xor r3,r3,r3
+
+hsmc1_err:
+ mtlr r0
+ blr
+ function_epilog(initb_hsmc1)
+
+
+/******************************************************************************
+|
+| Routine: INITB_CACHE
+|
+| Purpose: This routine will enable Data and Instruction Cache.
+| The Data Cache is an 8K two-way set associative and the
+| Instruction Cache is an 16K two-way set associative cache.
+|
+| Parameters: None.
+|
+| Returns: None.
+|
+******************************************************************************/
+ function_prolog(initb_cache)
+ mflr r0 /* Save return addr */
+
+ bl initb_Dcache /* enable D-Cache */
+ bl initb_Icache /* enable I-Cache */
+
+ mtlr r0
+ blr
+ function_epilog(initb_cache)
+
+
+/******************************************************************************
+|
+| Routine: INITB_DCACHE
+|
+| Purpose: This routine will invalidate all data in the Data Cache and
+| then enable D-Cache. If cache is enabled already, the D-Cache
+| will be flushed before the data is invalidated.
+|
+| Parameters: None.
+|
+| Returns: None.
+|
+******************************************************************************/
+ function_prolog(initb_Dcache)
+ /*--------------------------------------------------------------------+
+ | Flush Data Cache if enabled
+ +--------------------------------------------------------------------*/
+ mfdccr r10 /* r10 <- DCCR */
+ isync /* ensure prev insts done */
+ cmpwi r10,0x00
+ beq ic_dcinv /* D-cache off, invalidate */
+
+ /*--------------------------------------------------------------------+
+ | Data Cache enabled, force known memory addresses to be Cached
+ +--------------------------------------------------------------------*/
+ lis r10,HSMC0_BR0_VAL@h /* r10 <- first memory loc */
+ andis. r10,r10,0xFFF0
+ li r11,DCACHE_NLINES /* r11 <- # A-way addresses */
+ addi r11,r11,DCACHE_NLINES /* r11 <- # B-way addresses */
+ mtctr r11 /* set loop counter */
+
+ic_dcload:
+ lwz r12,0(r10) /* force cache of address */
+ addi r10,r10,DCACHE_NBYTES /* r10 <- next memory loc */
+ bdnz ic_dcload
+ sync /* ensure prev insts done */
+ isync
+
+ /*--------------------------------------------------------------------+
+ | Flush the known memory addresses from Cache
+ +--------------------------------------------------------------------*/
+ lis r10,HSMC0_BR0_VAL@h /* r10 <- first memory loc */
+ andis. r10,r10,0xFFF0
+ mtctr r11 /* set loop counter */
+
+ic_dcflush:
+ dcbf 0,r10 /* flush D-cache line */
+ addi r10,r10,DCACHE_NBYTES /* r10 <- next memory loc */
+ bdnz ic_dcflush
+ sync /* ensure prev insts done */
+ isync
+
+ /*--------------------------------------------------------------------+
+ | Disable then invalidate Data Cache
+ +--------------------------------------------------------------------*/
+ li r10,0 /* r10 <- 0 */
+ mtdccr r10 /* disable the D-Cache */
+ isync /* ensure prev insts done */
+
+ic_dcinv:
+ li r10,0 /* r10 <- line address */
+ li r11,DCACHE_NLINES /* r11 <- # lines in cache */
+ mtctr r11 /* set loop counter */
+
+ic_dcloop:
+ dccci 0,r10 /* invalidate A/B cache lns */
+ addi r10,r10,DCACHE_NBYTES /* bump to next line */
+ bdnz ic_dcloop
+ sync /* ensure prev insts done */
+ isync
+
+ /*--------------------------------------------------------------------+
+ | Enable Data Cache
+ +--------------------------------------------------------------------*/
+ lis r10,DCACHE_ENABLE@h /* r10 <- D-cache enable msk*/
+ ori r10,r10,DCACHE_ENABLE@l
+ mtdccr r10
+ sync /* ensure prev insts done */
+ isync
+
+ blr
+ function_epilog(initb_Dcache)
+
+
+/******************************************************************************
+|
+| Routine: INITB_ICACHE
+|
+| Purpose: This routine will invalidate all data in the Instruction
+| Cache then enable I-Cache.
+|
+| Parameters: None.
+|
+| Returns: None.
+|
+******************************************************************************/
+ function_prolog(initb_Icache)
+ /*--------------------------------------------------------------------+
+ | Invalidate Instruction Cache
+ +--------------------------------------------------------------------*/
+ li r10,0 /* r10 <- lines address */
+ iccci 0,r10 /* invalidate all I-cache */
+ sync /* ensure prev insts done */
+ isync
+
+ /*--------------------------------------------------------------------+
+ | Enable Instruction Cache
+ +--------------------------------------------------------------------*/
+ lis r10,ICACHE_ENABLE@h /* r10 <- I-cache enable msk*/
+ ori r10,r10,ICACHE_ENABLE@l
+ mticcr r10
+ sync /* ensure prev insts done */
+ isync
+
+ blr
+ function_epilog(initb_Icache)
+
+#if 0
+/******************************************************************************
+|
+| Routine: INITB_GET_CSPD
+|
+| Purpose: Determine the CPU Core Speed. The 13.5 Mhz Time Base
+| Counter (TBC) is used to measure a conditional branch
+| instruction.
+|
+| Parameters: R3 = Address of Bus Speed
+| R4 = Address of Core Speed
+|
+| Returns: (R3) = >0: Bus Speed.
+| 0: Bus Speed not found in Look-Up Table.
+| (R4) = >0: Core Speed.
+| 0: Core Speed not found in Look-Up Table.
+|
+| Note: 1. This routine assumes the bdnz branch instruction takes
+| two instruction cycles to complete.
+| 2. This routine must be called before interrupts are enabled.
+|
+******************************************************************************/
+ function_prolog(initb_get_cspd)
+ mflr r0 /* Save return address */
+ /*--------------------------------------------------------------------+
+ | Set-up timed loop
+ +--------------------------------------------------------------------*/
+ lis r9,gcs_time_loop@h /* r9 <- addr loop instr */
+ ori r9,r9,gcs_time_loop@l
+ lis r10,GCS_LCNT@h /* r10 <- loop count */
+ ori r10,r10,GCS_LCNT@l
+ mtctr r10 /* ctr <- loop count */
+ lis r11,STB_TIMERS_TBC@h /* r11 <- TBC register addr */
+ ori r11,r11,STB_TIMERS_TBC@l
+ li r12,0 /* r12 <- 0 */
+
+ /*--------------------------------------------------------------------+
+ | Cache timed-loop instruction
+ +--------------------------------------------------------------------*/
+ icbt 0,r9
+ sync
+ isync
+
+ /*--------------------------------------------------------------------+
+ | Get number of 13.5 Mhz cycles to execute time-loop
+ +--------------------------------------------------------------------*/
+ stw r12,0(r11) /* reset TBC */
+gcs_time_loop:
+ bdnz+ gcs_time_loop /* force branch pred taken */
+ lwz r5,0(r11) /* r5 <- num 13.5 Mhz ticks */
+ li r6,5 /* LUT based on 1/5th the...*/
+ divw r5,r5,r6 /*..loop count used */
+ sync
+ isync
+
+ /*--------------------------------------------------------------------+
+ | Look-up core speed based on TBC value
+ +--------------------------------------------------------------------*/
+ lis r6,gcs_lookup_table@h /* r6 <- pts at core spd LUT*/
+ ori r6,r6,gcs_lookup_table@l
+ bl gcs_cspd_lookup /* find core speed in LUT */
+
+ mtlr r0 /* set return address */
+ blr
+ function_epilog(initb_get_cspd)
+
+#endif
+/*****************************************************************************+
+| XXXX XX XX XXXXXX XXXXXXX XXXXXX XX XX XX XXXX
+| XX XXX XX X XX X XX X XX XX XXX XX XXXX XX
+| XX XXXX XX XX XX X XX XX XXXX XX XX XX XX
+| XX XX XXXX XX XXXX XXXXX XX XXXX XX XX XX
+| XX XX XXX XX XX X XX XX XX XXX XXXXXX XX
+| XX XX XX XX XX X XX XX XX XX XX XX XX XX
+| XXXX XX XX XXXX XXXXXXX XXX XX XX XX XX XX XXXXXXX
++*****************************************************************************/
+/******************************************************************************
+|
+| Routine: HSMC_CR_WAIT
+|
+| Purpose: Wait for the HSMC Control Register (bits 12-16) to be reset
+| after an auto-refresh, pre-charge or program mode register
+| command execution.
+|
+| Parameters: R3 = HSMC Control Register ID.
+| 0: HSMC0 CR0
+| 1: HSMC0 CR1
+| 2: HSMC1 CR0
+| 3: HSMC1 CR1
+|
+| Returns: R3 = 0: Successful
+| -1: Unsuccessful
+|
+******************************************************************************/
+hsmc_cr_wait:
+
+ li r11,10 /* r11 <- retry counter */
+ mtctr r11 /* set retry counter */
+ mr r11,r3 /* r11 <- HSMC CR reg id */
+
+hsmc_cr_rep:
+ bdz hsmc_cr_err /* branch if max retries hit*/
+
+ /*--------------------------------------------------------------------+
+ | GET HSMCx_CRx value based on HSMC Control Register ID
+ +--------------------------------------------------------------------*/
+try_hsmc0_cr0: /* CHECK IF ID=HSMC0 CR0 REG*/
+ cmpwi cr0,r11,0x0000
+ bne cr0,try_hsmc0_cr1
+ mfdcr r10,hsmc0_cr0 /* r11 <- HSMC0 CR0 value */
+ b hsmc_cr_read
+
+try_hsmc0_cr1: /* CHECK IF ID=HSMC0 CR1 REG*/
+ cmpwi cr0,r11,0x0001
+ bne cr0,try_hsmc1_cr0
+ mfdcr r10,hsmc0_cr1 /* r10 <- HSMC0 CR1 value */
+ b hsmc_cr_read
+
+try_hsmc1_cr0: /* CHECK IF ID=HSMC1 CR0 REG*/
+ cmpwi cr0,r11,0x0002
+ bne cr0,try_hsmc1_cr1
+ mfdcr r10,hsmc1_cr0 /* r10 <- HSMC1 CR0 value */
+ b hsmc_cr_read
+
+try_hsmc1_cr1: /* CHECK IF ID=HSMC1 CR1 REG*/
+ cmpwi cr0,r11,0x0003
+ bne cr0,hsmc_cr_err
+ mfdcr r10,hsmc1_cr1 /* r10 <- HSMC1 CR1 value */
+
+ /*--------------------------------------------------------------------+
+ | Check if HSMC CR register was reset after command execution
+ +--------------------------------------------------------------------*/
+hsmc_cr_read:
+ lis r12,0x000F /* create "AND" mask */
+ ori r12,r12,0x8000
+ and. r10,r10,r12 /* r10 <- HSMC CR bits 12-16*/
+ bne cr0,hsmc_cr_rep /* wait for bits to reset */
+ li r3,0 /* set return code = success*/
+ b hsmc_cr_done
+
+hsmc_cr_err: /* ERROR: SDRAM didn't reset*/
+ li r3,-1 /* set RC=unsuccessful */
+
+hsmc_cr_done:
+ blr
+
+#if 0
+/******************************************************************************
+|
+| Routine: GCS_CSPD_LOOKUP
+|
+| Purpose: Uses the number of 13.5 Mhz clock ticks found after executing
+| the branch instruction time loop to look-up the CPU Core Speed
+| in the Core Speed Look-up Table.
+|
+| Parameters: R3 = Address of Bus Speed
+| R4 = Address of Core Speed
+| R5 = Number of 13.5 Mhz clock ticks found in time loop.
+| R6 = Pointer to Core-Speed Look-Up Table
+|
+| Returns: (R3) = >0: Bus Speed.
+| 0: Bus Speed not found in Look-Up Table.
+| (R4) = >0: Core Speed.
+| 0: Core Speed not found in Look-Up Table.
+|
+| Note: Core Speed = Bus Speed * Mult Factor (1-4x).
+|
+******************************************************************************/
+gcs_cspd_lookup:
+
+ li r9,1 /* r9 <- core speed mult */
+ /*--------------------------------------------------------------------+
+ | Get theoritical number 13.5 Mhz ticks for a given Bus Speed from
+ | Look-up Table. Check all mult factors to determine if calculated
+ | value matches theoretical value (within a tolerance).
+ +--------------------------------------------------------------------*/
+gcs_cspd_loop:
+ lwz r10,0(r6) /* r10 <- no. ticks from LUT*/
+ divw r10,r10,r9 /* r10 <- div mult (1-4x) */
+ subi r11,r10,GCS_CTICK_TOL /* r11 <- no. tks low range */
+ addi r12,r10,GCS_CTICK_TOL /* r12 <- no. tks high range*/
+
+ cmpw cr0,r5,r11 /* calc value within range? */
+ blt gcs_cspd_retry /* less than low range */
+ cmpw cr0,r5,r12
+ bgt gcs_cspd_retry /* greater than high range */
+ b gcs_cspd_fnd /* calc value within range */
+
+ /*--------------------------------------------------------------------+
+ | SO FAR CORE SPEED NOT FOUND: Check next mult factor
+ +--------------------------------------------------------------------*/
+gcs_cspd_retry:
+ addi r9,r9,1 /* bump mult factor (1-4x) */
+ cmpwi cr0,r9,GCS_NMULT
+ ble gcs_cspd_loop
+
+ /*--------------------------------------------------------------------+
+ | SO FAR CORE SPEED NOT FOUND: Point at next Bus Speed in LUT
+ +--------------------------------------------------------------------*/
+ li r9,1 /* reset mult factor */
+ addi r6,r6,GCS_TROW_BYTES /* point at next table entry*/
+ lwz r10,0(r6)
+ cmpwi cr0,r10,0 /* check for EOT flag */
+ bne gcs_cspd_loop
+
+ /*--------------------------------------------------------------------+
+ | COMPUTE CORE SPEED AND GET BUS SPEED FROM LOOK-UP TABLE
+ +--------------------------------------------------------------------*/
+gcs_cspd_fnd:
+ lwz r5,4(r6) /* r5 <- Bus Speed in LUT */
+ mullw r6,r5,r9 /* r6 <- Core speed */
+ stw r5,0(r3) /* (r3) <- Bus Speed */
+ stw r6,0(r4) /* (r4) <- Core Speed */
+
+ blr
+#endif
diff --git a/arch/ppc/boot/simple/rw4/stb.h b/arch/ppc/boot/simple/rw4/stb.h
new file mode 100644
index 0000000..fd98ee0
--- /dev/null
+++ b/arch/ppc/boot/simple/rw4/stb.h
@@ -0,0 +1,239 @@
+/*----------------------------------------------------------------------------+
+| This source code has been made available to you by IBM on an AS-IS
+| basis. Anyone receiving this source is licensed under IBM
+| copyrights to use it in any way he or she deems fit, including
+| copying it, modifying it, compiling it, and redistributing it either
+| with or without modifications. No license under IBM patents or
+| patent applications is to be implied by the copyright license.
+|
+| Any user of this software should understand that IBM cannot provide
+| technical support for this software and will not be responsible for
+| any consequences resulting from the use of this software.
+|
+| Any person who transfers this source code or any derivative work
+| must include the IBM copyright notice, this paragraph, and the
+| preceding two paragraphs in the transferred software.
+|
+| COPYRIGHT I B M CORPORATION 1999
+| LICENSED MATERIAL - PROGRAM PROPERTY OF I B M
++----------------------------------------------------------------------------*/
+/*----------------------------------------------------------------------------+
+| Author: Maciej P. Tyrlik
+| Component: Include file.
+| File: stb.h
+| Purpose: Common Set-tob-box definitions.
+| Changes:
+| Date: Comment:
+| ----- --------
+| 14-Jan-97 Created for ElPaso pass 1 MPT
+| 13-May-97 Added function prototype and global variables MPT
+| 08-Dec-98 Added RAW IR task information MPT
+| 19-Jan-99 Port to Romeo MPT
+| 19-May-00 Changed SDRAM to 32MB contiguous 0x1F000000 - 0x20FFFFFF RLB
++----------------------------------------------------------------------------*/
+
+#ifndef _stb_h_
+#define _stb_h_
+
+/*----------------------------------------------------------------------------+
+| Read/write from I/O macros.
++----------------------------------------------------------------------------*/
+#define inbyte(port) (*((unsigned char volatile *)(port)))
+#define outbyte(port,data) *(unsigned char volatile *)(port)=\
+ (unsigned char)(data)
+
+#define inshort(port) (*((unsigned short volatile *)(port)))
+#define outshort(port,data) *(unsigned short volatile *)(port)=\
+ (unsigned short)(data)
+
+#define inword(port) (*((unsigned long volatile *)(port)))
+#define outword(port,data) *(unsigned long volatile *)(port)=\
+ (unsigned long)(data)
+
+/*----------------------------------------------------------------------------+
+| STB interrupts.
++----------------------------------------------------------------------------*/
+#define STB_XP_TP_INT 0
+#define STB_XP_APP_INT 1
+#define STB_AUD_INT 2
+#define STB_VID_INT 3
+#define STB_DMA0_INT 4
+#define STB_DMA1_INT 5
+#define STB_DMA2_INT 6
+#define STB_DMA3_INT 7
+#define STB_SCI_INT 8
+#define STB_I2C1_INT 9
+#define STB_I2C2_INT 10
+#define STB_GPT_PWM0 11
+#define STB_GPT_PWM1 12
+#define STB_SCP_INT 13
+#define STB_SSP_INT 14
+#define STB_GPT_PWM2 15
+#define STB_EXT5_INT 16
+#define STB_EXT6_INT 17
+#define STB_EXT7_INT 18
+#define STB_EXT8_INT 19
+#define STB_SCC_INT 20
+#define STB_SICC_RECV_INT 21
+#define STB_SICC_TRAN_INT 22
+#define STB_PPU_INT 23
+#define STB_DCRX_INT 24
+#define STB_EXT0_INT 25
+#define STB_EXT1_INT 26
+#define STB_EXT2_INT 27
+#define STB_EXT3_INT 28
+#define STB_EXT4_INT 29
+#define STB_REDWOOD_ENET_INT STB_EXT1_INT
+
+/*----------------------------------------------------------------------------+
+| STB tasks, task stack sizes, and task priorities. The actual task priority
+| is 1 more than the specified number since priority 0 is reserved (system
+| internaly adds 1 to supplied priority number).
++----------------------------------------------------------------------------*/
+#define STB_IDLE_TASK_SS (5* 1024)
+#define STB_IDLE_TASK_PRIO 0
+#define STB_LEDTEST_SS (2* 1024)
+#define STB_LEDTEST_PRIO 0
+#define STB_CURSOR_TASK_SS (10* 1024)
+#define STB_CURSOR_TASK_PRIO 7
+#define STB_MPEG_TASK_SS (10* 1024)
+#define STB_MPEG_TASK_PRIO 9
+#define STB_DEMUX_TASK_SS (10* 1024)
+#define STB_DEMUX_TASK_PRIO 20
+#define RAW_STB_IR_TASK_SS (10* 1024)
+#define RAW_STB_IR_TASK_PRIO 20
+
+#define STB_SERIAL_ER_TASK_SS (10* 1024)
+#define STB_SERIAL_ER_TASK_PRIO 1
+#define STB_CA_TASK_SS (10* 1024)
+#define STB_CA_TASK_PRIO 8
+
+#define INIT_DEFAULT_VIDEO_SS (10* 1024)
+#define INIT_DEFAULT_VIDEO_PRIO 8
+#define INIT_DEFAULT_SERVI_SS (10* 1024)
+#define INIT_DEFAULT_SERVI_PRIO 8
+#define INIT_DEFAULT_POST_SS (10* 1024)
+#define INIT_DEFAULT_POST_PRIO 8
+#define INIT_DEFAULT_INTER_SS (10* 1024)
+#define INIT_DEFAULT_INTER_PRIO 8
+#define INIT_DEFAULT_BR_SS (10* 1024)
+#define INIT_DEFAULT_BR_PRIO 8
+#define INITIAL_TASK_STACK_SIZE (32* 1024)
+
+#ifdef VESTA
+/*----------------------------------------------------------------------------+
+| Vesta Overall Address Map (all addresses are double mapped, bit 0 of the
+| address is not decoded. Numbers below are dependent on board configuration.
+| FLASH, SDRAM, DRAM numbers can be affected by actual board setup.
+|
+| FFE0,0000 - FFFF,FFFF FLASH
+| F200,0000 - F210,FFFF FPGA logic
+| Ethernet = F200,0000
+| LED Display = F200,0100
+| Xilinx #1 Regs = F204,0000
+| Xilinx #2 Regs = F208,0000
+| Spare = F20C,0000
+| IDE CS0 = F210,0000
+| F410,0000 - F410,FFFF IDE CS1
+| C000,0000 - C7FF,FFFF OBP
+| C000,0000 - C000,0014 SICC (16550 + infra red)
+| C001,0000 - C001,0018 PPU (Parallel Port)
+| C002,0000 - C002,001B SC0 (Smart Card 0)
+| C003,0000 - C003,000F I2C0
+| C004,0000 - C004,0009 SCC (16550 UART)
+| C005,0000 - C005,0124 GPT (Timers)
+| C006,0000 - C006,0058 GPIO0
+| C007,0000 - C007,001b SC1 (Smart Card 1)
+| C008,0000 - C008,FFFF Unused
+| C009,0000 - C009,FFFF Unused
+| C00A,0000 - C00A,FFFF Unused
+| C00B,0000 - C00B,000F I2C1
+| C00C,0000 - C00C,0006 SCP
+| C00D,0000 - C00D,0010 SSP
+| A000,0000 - A0FF,FFFF SDRAM1 (16M)
+| 0000,0000 - 00FF,FFFF SDRAM0 (16M)
++----------------------------------------------------------------------------*/
+#define STB_FLASH_BASE_ADDRESS 0xFFE00000
+#define STB_FPGA_BASE_ADDRESS 0xF2000000
+#define STB_SICC_BASE_ADDRESS 0xC0000000
+#define STB_PPU_BASE_ADDR 0xC0010000
+#define STB_SC0_BASE_ADDRESS 0xC0020000
+#define STB_I2C1_BASE_ADDRESS 0xC0030000
+#define STB_SCC_BASE_ADDRESS 0xC0040000
+#define STB_TIMERS_BASE_ADDRESS 0xC0050000
+#define STB_GPIO0_BASE_ADDRESS 0xC0060000
+#define STB_SC1_BASE_ADDRESS 0xC0070000
+#define STB_I2C2_BASE_ADDRESS 0xC00B0000
+#define STB_SCP_BASE_ADDRESS 0xC00C0000
+#define STB_SSP_BASE_ADDRESS 0xC00D0000
+/*----------------------------------------------------------------------------+
+|The following are used by the IBM RTOS SW.
+|15-May-00 Changed these values to reflect movement of base addresses in
+|order to support 32MB of contiguous SDRAM space.
+|Points to the cacheable region since these values are used in IBM RTOS
+|to establish the vector address.
++----------------------------------------------------------------------------*/
+#define STB_SDRAM1_BASE_ADDRESS 0x20000000
+#define STB_SDRAM1_SIZE 0x01000000
+#define STB_SDRAM0_BASE_ADDRESS 0x1F000000
+#define STB_SDRAM0_SIZE 0x01000000
+
+#else
+/*----------------------------------------------------------------------------+
+| ElPaso Overall Address Map (all addresses are double mapped, bit 0 of the
+| address is not decoded. Numbers below are dependent on board configuration.
+| FLASH, SDRAM, DRAM numbers can be affected by actual board setup. OPB
+| devices are inside the ElPaso chip.
+| FFE0,0000 - FFFF,FFFF FLASH
+| F144,0000 - F104,FFFF FPGA logic
+| F140,0000 - F100,0000 ethernet (through FPGA logic)
+| C000,0000 - C7FF,FFFF OBP
+| C000,0000 - C000,0014 SICC (16550+ infra red)
+| C001,0000 - C001,0016 PPU (parallel port)
+| C002,0000 - C002,001B SC (smart card)
+| C003,0000 - C003,000F I2C 1
+| C004,0000 - C004,0009 SCC (16550 UART)
+| C005,0000 - C005,0124 Timers
+| C006,0000 - C006,0058 GPIO0
+| C007,0000 - C007,0058 GPIO1
+| C008,0000 - C008,0058 GPIO2
+| C009,0000 - C009,0058 GPIO3
+| C00A,0000 - C00A,0058 GPIO4
+| C00B,0000 - C00B,000F I2C 2
+| C00C,0000 - C00C,0006 SCP
+| C00D,0000 - C00D,0006 SSP
+| A000,0000 - A0FF,FFFF SDRAM 16M
+| 0000,0000 - 00FF,FFFF DRAM 16M
++----------------------------------------------------------------------------*/
+#define STB_FLASH_BASE_ADDRESS 0xFFE00000
+#define STB_FPGA_BASE_ADDRESS 0xF1440000
+#define STB_ENET_BASE_ADDRESS 0xF1400000
+#define STB_SICC_BASE_ADDRESS 0xC0000000
+#define STB_PPU_BASE_ADDR 0xC0010000
+#define STB_SC_BASE_ADDRESS 0xC0020000
+#define STB_I2C1_BASE_ADDRESS 0xC0030000
+#define STB_SCC_BASE_ADDRESS 0xC0040000
+#define STB_TIMERS_BASE_ADDRESS 0xC0050000
+#define STB_GPIO0_BASE_ADDRESS 0xC0060000
+#define STB_GPIO1_BASE_ADDRESS 0xC0070000
+#define STB_GPIO2_BASE_ADDRESS 0xC0080000
+#define STB_GPIO3_BASE_ADDRESS 0xC0090000
+#define STB_GPIO4_BASE_ADDRESS 0xC00A0000
+#define STB_I2C2_BASE_ADDRESS 0xC00B0000
+#define STB_SCP_BASE_ADDRESS 0xC00C0000
+#define STB_SSP_BASE_ADDRESS 0xC00D0000
+#define STB_SDRAM_BASE_ADDRESS 0xA0000000
+#endif
+
+/*----------------------------------------------------------------------------+
+| Other common defines.
++----------------------------------------------------------------------------*/
+#ifndef TRUE
+#define TRUE 1
+#endif
+
+#ifndef FALSE
+#define FALSE 0
+#endif
+
+#endif /* _stb_h_ */
diff --git a/arch/ppc/boot/utils/addRamDisk.c b/arch/ppc/boot/utils/addRamDisk.c
new file mode 100644
index 0000000..93400df
--- /dev/null
+++ b/arch/ppc/boot/utils/addRamDisk.c
@@ -0,0 +1,203 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <netinet/in.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <string.h>
+
+#define ElfHeaderSize (64 * 1024)
+#define ElfPages (ElfHeaderSize / 4096)
+#define KERNELBASE (0xc0000000)
+
+void get4k(FILE *file, char *buf )
+{
+ unsigned j;
+ unsigned num = fread(buf, 1, 4096, file);
+ for ( j=num; j<4096; ++j )
+ buf[j] = 0;
+}
+
+void put4k(FILE *file, char *buf )
+{
+ fwrite(buf, 1, 4096, file);
+}
+
+void death(const char *msg, FILE *fdesc, const char *fname)
+{
+ printf(msg);
+ fclose(fdesc);
+ unlink(fname);
+ exit(1);
+}
+
+int main(int argc, char **argv)
+{
+ char inbuf[4096];
+ FILE *ramDisk = NULL;
+ FILE *inputVmlinux = NULL;
+ FILE *outputVmlinux = NULL;
+ unsigned i = 0;
+ u_int32_t ramFileLen = 0;
+ u_int32_t ramLen = 0;
+ u_int32_t roundR = 0;
+ u_int32_t kernelLen = 0;
+ u_int32_t actualKernelLen = 0;
+ u_int32_t round = 0;
+ u_int32_t roundedKernelLen = 0;
+ u_int32_t ramStartOffs = 0;
+ u_int32_t ramPages = 0;
+ u_int32_t roundedKernelPages = 0;
+ u_int32_t hvReleaseData = 0;
+ u_int32_t eyeCatcher = 0xc8a5d9c4;
+ u_int32_t naca = 0;
+ u_int32_t xRamDisk = 0;
+ u_int32_t xRamDiskSize = 0;
+ if ( argc < 2 ) {
+ printf("Name of RAM disk file missing.\n");
+ exit(1);
+ }
+
+ if ( argc < 3 ) {
+ printf("Name of vmlinux file missing.\n");
+ exit(1);
+ }
+
+ if ( argc < 4 ) {
+ printf("Name of vmlinux output file missing.\n");
+ exit(1);
+ }
+
+ ramDisk = fopen(argv[1], "r");
+ if ( ! ramDisk ) {
+ printf("RAM disk file \"%s\" failed to open.\n", argv[1]);
+ exit(1);
+ }
+ inputVmlinux = fopen(argv[2], "r");
+ if ( ! inputVmlinux ) {
+ printf("vmlinux file \"%s\" failed to open.\n", argv[2]);
+ exit(1);
+ }
+ outputVmlinux = fopen(argv[3], "w+");
+ if ( ! outputVmlinux ) {
+ printf("output vmlinux file \"%s\" failed to open.\n", argv[3]);
+ exit(1);
+ }
+ fseek(ramDisk, 0, SEEK_END);
+ ramFileLen = ftell(ramDisk);
+ fseek(ramDisk, 0, SEEK_SET);
+ printf("%s file size = %d\n", argv[1], ramFileLen);
+
+ ramLen = ramFileLen;
+
+ roundR = 4096 - (ramLen % 4096);
+ if ( roundR ) {
+ printf("Rounding RAM disk file up to a multiple of 4096, adding %d\n", roundR);
+ ramLen += roundR;
+ }
+
+ printf("Rounded RAM disk size is %d\n", ramLen);
+ fseek(inputVmlinux, 0, SEEK_END);
+ kernelLen = ftell(inputVmlinux);
+ fseek(inputVmlinux, 0, SEEK_SET);
+ printf("kernel file size = %d\n", kernelLen);
+ if ( kernelLen == 0 ) {
+ printf("You must have a linux kernel specified as argv[2]\n");
+ exit(1);
+ }
+
+ actualKernelLen = kernelLen - ElfHeaderSize;
+
+ printf("actual kernel length (minus ELF header) = %d\n", actualKernelLen);
+
+ round = actualKernelLen % 4096;
+ roundedKernelLen = actualKernelLen;
+ if ( round )
+ roundedKernelLen += (4096 - round);
+
+ printf("actual kernel length rounded up to a 4k multiple = %d\n", roundedKernelLen);
+
+ ramStartOffs = roundedKernelLen;
+ ramPages = ramLen / 4096;
+
+ printf("RAM disk pages to copy = %d\n", ramPages);
+
+ // Copy 64K ELF header
+ for (i=0; i<(ElfPages); ++i) {
+ get4k( inputVmlinux, inbuf );
+ put4k( outputVmlinux, inbuf );
+ }
+
+ roundedKernelPages = roundedKernelLen / 4096;
+
+ fseek(inputVmlinux, ElfHeaderSize, SEEK_SET);
+
+ for ( i=0; i<roundedKernelPages; ++i ) {
+ get4k( inputVmlinux, inbuf );
+ put4k( outputVmlinux, inbuf );
+ }
+
+ for ( i=0; i<ramPages; ++i ) {
+ get4k( ramDisk, inbuf );
+ put4k( outputVmlinux, inbuf );
+ }
+
+ /* Close the input files */
+ fclose(ramDisk);
+ fclose(inputVmlinux);
+ /* And flush the written output file */
+ fflush(outputVmlinux);
+
+ /* fseek to the hvReleaseData pointer */
+ fseek(outputVmlinux, ElfHeaderSize + 0x24, SEEK_SET);
+ if (fread(&hvReleaseData, 4, 1, outputVmlinux) != 1) {
+ death("Could not read hvReleaseData pointer\n", outputVmlinux, argv[3]);
+ }
+ hvReleaseData = ntohl(hvReleaseData); /* Convert to native int */
+ printf("hvReleaseData is at %08x\n", hvReleaseData);
+
+ /* fseek to the hvReleaseData */
+ fseek(outputVmlinux, ElfHeaderSize + hvReleaseData, SEEK_SET);
+ if (fread(inbuf, 0x40, 1, outputVmlinux) != 1) {
+ death("Could not read hvReleaseData\n", outputVmlinux, argv[3]);
+ }
+ /* Check hvReleaseData sanity */
+ if (memcmp(inbuf, &eyeCatcher, 4) != 0) {
+ death("hvReleaseData is invalid\n", outputVmlinux, argv[3]);
+ }
+ /* Get the naca pointer */
+ naca = ntohl(*((u_int32_t *) &inbuf[0x0c])) - KERNELBASE;
+ printf("naca is at %08x\n", naca);
+
+ /* fseek to the naca */
+ fseek(outputVmlinux, ElfHeaderSize + naca, SEEK_SET);
+ if (fread(inbuf, 0x18, 1, outputVmlinux) != 1) {
+ death("Could not read naca\n", outputVmlinux, argv[3]);
+ }
+ xRamDisk = ntohl(*((u_int32_t *) &inbuf[0x0c]));
+ xRamDiskSize = ntohl(*((u_int32_t *) &inbuf[0x14]));
+ /* Make sure a RAM disk isn't already present */
+ if ((xRamDisk != 0) || (xRamDiskSize != 0)) {
+ death("RAM disk is already attached to this kernel\n", outputVmlinux, argv[3]);
+ }
+ /* Fill in the values */
+ *((u_int32_t *) &inbuf[0x0c]) = htonl(ramStartOffs);
+ *((u_int32_t *) &inbuf[0x14]) = htonl(ramPages);
+
+ /* Write out the new naca */
+ fflush(outputVmlinux);
+ fseek(outputVmlinux, ElfHeaderSize + naca, SEEK_SET);
+ if (fwrite(inbuf, 0x18, 1, outputVmlinux) != 1) {
+ death("Could not write naca\n", outputVmlinux, argv[3]);
+ }
+ printf("RAM Disk of 0x%x pages size is attached to the kernel at offset 0x%08x\n",
+ ramPages, ramStartOffs);
+
+ /* Done */
+ fclose(outputVmlinux);
+ /* Set permission to executable */
+ chmod(argv[3], S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH);
+
+ return 0;
+}
+
diff --git a/arch/ppc/boot/utils/addSystemMap.c b/arch/ppc/boot/utils/addSystemMap.c
new file mode 100644
index 0000000..4654f89
--- /dev/null
+++ b/arch/ppc/boot/utils/addSystemMap.c
@@ -0,0 +1,186 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <byteswap.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+void xlate( char * inb, char * trb, unsigned len )
+{
+ unsigned i;
+ for ( i=0; i<len; ++i ) {
+ char c = *inb++;
+ char c1 = c >> 4;
+ char c2 = c & 0xf;
+ if ( c1 > 9 )
+ c1 = c1 + 'A' - 10;
+ else
+ c1 = c1 + '0';
+ if ( c2 > 9 )
+ c2 = c2 + 'A' - 10;
+ else
+ c2 = c2 + '0';
+ *trb++ = c1;
+ *trb++ = c2;
+ }
+ *trb = 0;
+}
+
+#define ElfHeaderSize (64 * 1024)
+#define ElfPages (ElfHeaderSize / 4096)
+#define KERNELBASE (0xc0000000)
+
+void get4k( /*istream *inf*/FILE *file, char *buf )
+{
+ unsigned j;
+ unsigned num = fread(buf, 1, 4096, file);
+ for ( j=num; j<4096; ++j )
+ buf[j] = 0;
+}
+
+void put4k( /*ostream *outf*/FILE *file, char *buf )
+{
+ fwrite(buf, 1, 4096, file);
+}
+
+int main(int argc, char **argv)
+{
+ char inbuf[4096];
+ FILE *ramDisk = NULL;
+ FILE *inputVmlinux = NULL;
+ FILE *outputVmlinux = NULL;
+ unsigned i = 0;
+ unsigned long ramFileLen = 0;
+ unsigned long ramLen = 0;
+ unsigned long roundR = 0;
+ unsigned long kernelLen = 0;
+ unsigned long actualKernelLen = 0;
+ unsigned long round = 0;
+ unsigned long roundedKernelLen = 0;
+ unsigned long ramStartOffs = 0;
+ unsigned long ramPages = 0;
+ unsigned long roundedKernelPages = 0;
+ if ( argc < 2 ) {
+ printf("Name of System Map file missing.\n");
+ exit(1);
+ }
+
+ if ( argc < 3 ) {
+ printf("Name of vmlinux file missing.\n");
+ exit(1);
+ }
+
+ if ( argc < 4 ) {
+ printf("Name of vmlinux output file missing.\n");
+ exit(1);
+ }
+
+ ramDisk = fopen(argv[1], "r");
+ if ( ! ramDisk ) {
+ printf("System Map file \"%s\" failed to open.\n", argv[1]);
+ exit(1);
+ }
+ inputVmlinux = fopen(argv[2], "r");
+ if ( ! inputVmlinux ) {
+ printf("vmlinux file \"%s\" failed to open.\n", argv[2]);
+ exit(1);
+ }
+ outputVmlinux = fopen(argv[3], "w");
+ if ( ! outputVmlinux ) {
+ printf("output vmlinux file \"%s\" failed to open.\n", argv[3]);
+ exit(1);
+ }
+ fseek(ramDisk, 0, SEEK_END);
+ ramFileLen = ftell(ramDisk);
+ fseek(ramDisk, 0, SEEK_SET);
+ printf("%s file size = %ld\n", argv[1], ramFileLen);
+
+ ramLen = ramFileLen;
+
+ roundR = 4096 - (ramLen % 4096);
+ if ( roundR ) {
+ printf("Rounding System Map file up to a multiple of 4096, adding %ld\n", roundR);
+ ramLen += roundR;
+ }
+
+ printf("Rounded System Map size is %ld\n", ramLen);
+ fseek(inputVmlinux, 0, SEEK_END);
+ kernelLen = ftell(inputVmlinux);
+ fseek(inputVmlinux, 0, SEEK_SET);
+ printf("kernel file size = %ld\n", kernelLen);
+ if ( kernelLen == 0 ) {
+ printf("You must have a linux kernel specified as argv[2]\n");
+ exit(1);
+ }
+
+ actualKernelLen = kernelLen - ElfHeaderSize;
+
+ printf("actual kernel length (minus ELF header) = %ld\n", actualKernelLen);
+
+ round = actualKernelLen % 4096;
+ roundedKernelLen = actualKernelLen;
+ if ( round )
+ roundedKernelLen += (4096 - round);
+
+ printf("actual kernel length rounded up to a 4k multiple = %ld\n", roundedKernelLen);
+
+ ramStartOffs = roundedKernelLen;
+ ramPages = ramLen / 4096;
+
+ printf("System map pages to copy = %ld\n", ramPages);
+
+ // Copy 64K ELF header
+ for (i=0; i<(ElfPages); ++i) {
+ get4k( inputVmlinux, inbuf );
+ put4k( outputVmlinux, inbuf );
+ }
+
+
+
+ roundedKernelPages = roundedKernelLen / 4096;
+
+ fseek(inputVmlinux, ElfHeaderSize, SEEK_SET);
+
+ {
+ for ( i=0; i<roundedKernelPages; ++i ) {
+ get4k( inputVmlinux, inbuf );
+ if ( i == 0 ) {
+ unsigned long * p;
+ printf("Storing embedded_sysmap_start at 0x3c\n");
+ p = (unsigned long *)(inbuf + 0x3c);
+
+#if (BYTE_ORDER == __BIG_ENDIAN)
+ *p = ramStartOffs;
+#else
+ *p = bswap_32(ramStartOffs);
+#endif
+
+ printf("Storing embedded_sysmap_end at 0x44\n");
+ p = (unsigned long *)(inbuf + 0x44);
+#if (BYTE_ORDER == __BIG_ENDIAN)
+ *p = ramStartOffs + ramFileLen;
+#else
+ *p = bswap_32(ramStartOffs + ramFileLen);
+#endif
+ }
+ put4k( outputVmlinux, inbuf );
+ }
+ }
+
+ {
+ for ( i=0; i<ramPages; ++i ) {
+ get4k( ramDisk, inbuf );
+ put4k( outputVmlinux, inbuf );
+ }
+ }
+
+
+ fclose(ramDisk);
+ fclose(inputVmlinux);
+ fclose(outputVmlinux);
+ /* Set permission to executable */
+ chmod(argv[3], S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH);
+
+ return 0;
+
+}
+
diff --git a/arch/ppc/boot/utils/addnote.c b/arch/ppc/boot/utils/addnote.c
new file mode 100644
index 0000000..6c52b18
--- /dev/null
+++ b/arch/ppc/boot/utils/addnote.c
@@ -0,0 +1,175 @@
+/*
+ * Program to hack in a PT_NOTE program header entry in an ELF file.
+ * This is needed for OF on RS/6000s to load an image correctly.
+ * Note that OF needs a program header entry for the note, not an
+ * ELF section.
+ *
+ * Copyright 2000 Paul Mackerras.
+ *
+ * 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.
+ *
+ * Usage: addnote zImage
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <string.h>
+
+char arch[] = "PowerPC";
+
+#define N_DESCR 6
+unsigned int descr[N_DESCR] = {
+#if 1
+ /* values for IBM RS/6000 machines */
+ 0xffffffff, /* real-mode = true */
+ 0x00c00000, /* real-base, i.e. where we expect OF to be */
+ 0xffffffff, /* real-size */
+ 0xffffffff, /* virt-base */
+ 0xffffffff, /* virt-size */
+ 0x4000, /* load-base */
+#else
+ /* values for longtrail CHRP */
+ 0, /* real-mode = false */
+ 0xffffffff, /* real-base */
+ 0xffffffff, /* real-size */
+ 0xffffffff, /* virt-base */
+ 0xffffffff, /* virt-size */
+ 0x00600000, /* load-base */
+#endif
+};
+
+unsigned char buf[512];
+
+#define GET_16BE(off) ((buf[off] << 8) + (buf[(off)+1]))
+#define GET_32BE(off) ((GET_16BE(off) << 16) + GET_16BE((off)+2))
+
+#define PUT_16BE(off, v) (buf[off] = ((v) >> 8) & 0xff, \
+ buf[(off) + 1] = (v) & 0xff)
+#define PUT_32BE(off, v) (PUT_16BE((off), (v) >> 16), \
+ PUT_16BE((off) + 2, (v)))
+
+/* Structure of an ELF file */
+#define E_IDENT 0 /* ELF header */
+#define E_PHOFF 28
+#define E_PHENTSIZE 42
+#define E_PHNUM 44
+#define E_HSIZE 52 /* size of ELF header */
+
+#define EI_MAGIC 0 /* offsets in E_IDENT area */
+#define EI_CLASS 4
+#define EI_DATA 5
+
+#define PH_TYPE 0 /* ELF program header */
+#define PH_OFFSET 4
+#define PH_FILESZ 16
+#define PH_HSIZE 32 /* size of program header */
+
+#define PT_NOTE 4 /* Program header type = note */
+
+#define ELFCLASS32 1
+#define ELFDATA2MSB 2
+
+unsigned char elf_magic[4] = { 0x7f, 'E', 'L', 'F' };
+
+int main(int ac, char **av)
+{
+ int fd, n, i;
+ int ph, ps, np;
+ int nnote, ns;
+
+ if (ac != 2) {
+ fprintf(stderr, "Usage: %s elf-file\n", av[0]);
+ exit(1);
+ }
+ fd = open(av[1], O_RDWR);
+ if (fd < 0) {
+ perror(av[1]);
+ exit(1);
+ }
+
+ nnote = strlen(arch) + 1 + (N_DESCR + 3) * 4;
+
+ n = read(fd, buf, sizeof(buf));
+ if (n < 0) {
+ perror("read");
+ exit(1);
+ }
+
+ if (n < E_HSIZE || memcmp(&buf[E_IDENT+EI_MAGIC], elf_magic, 4) != 0)
+ goto notelf;
+
+ if (buf[E_IDENT+EI_CLASS] != ELFCLASS32
+ || buf[E_IDENT+EI_DATA] != ELFDATA2MSB) {
+ fprintf(stderr, "%s is not a big-endian 32-bit ELF image\n",
+ av[1]);
+ exit(1);
+ }
+
+ ph = GET_32BE(E_PHOFF);
+ ps = GET_16BE(E_PHENTSIZE);
+ np = GET_16BE(E_PHNUM);
+ if (ph < E_HSIZE || ps < PH_HSIZE || np < 1)
+ goto notelf;
+ if (ph + (np + 1) * ps + nnote > n)
+ goto nospace;
+
+ for (i = 0; i < np; ++i) {
+ if (GET_32BE(ph + PH_TYPE) == PT_NOTE) {
+ fprintf(stderr, "%s already has a note entry\n",
+ av[1]);
+ exit(0);
+ }
+ ph += ps;
+ }
+
+ /* XXX check that the area we want to use is all zeroes */
+ for (i = 0; i < ps + nnote; ++i)
+ if (buf[ph + i] != 0)
+ goto nospace;
+
+ /* fill in the program header entry */
+ ns = ph + ps;
+ PUT_32BE(ph + PH_TYPE, PT_NOTE);
+ PUT_32BE(ph + PH_OFFSET, ns);
+ PUT_32BE(ph + PH_FILESZ, nnote);
+
+ /* fill in the note area we point to */
+ /* XXX we should probably make this a proper section */
+ PUT_32BE(ns, strlen(arch) + 1);
+ PUT_32BE(ns + 4, N_DESCR * 4);
+ PUT_32BE(ns + 8, 0x1275);
+ strcpy(&buf[ns + 12], arch);
+ ns += 12 + strlen(arch) + 1;
+ for (i = 0; i < N_DESCR; ++i)
+ PUT_32BE(ns + i * 4, descr[i]);
+
+ /* Update the number of program headers */
+ PUT_16BE(E_PHNUM, np + 1);
+
+ /* write back */
+ lseek(fd, (long) 0, SEEK_SET);
+ i = write(fd, buf, n);
+ if (i < 0) {
+ perror("write");
+ exit(1);
+ }
+ if (i < n) {
+ fprintf(stderr, "%s: write truncated\n", av[1]);
+ exit(1);
+ }
+
+ exit(0);
+
+ notelf:
+ fprintf(stderr, "%s does not appear to be an ELF file\n", av[0]);
+ exit(1);
+
+ nospace:
+ fprintf(stderr, "sorry, I can't find space in %s to put the note\n",
+ av[0]);
+ exit(1);
+}
diff --git a/arch/ppc/boot/utils/elf.pl b/arch/ppc/boot/utils/elf.pl
new file mode 100644
index 0000000..d3e9d9d
--- /dev/null
+++ b/arch/ppc/boot/utils/elf.pl
@@ -0,0 +1,33 @@
+#
+# ELF header field numbers
+#
+
+$e_ident = 0; # Identification bytes / magic number
+$e_type = 1; # ELF file type
+$e_machine = 2; # Target machine type
+$e_version = 3; # File version
+$e_entry = 4; # Start address
+$e_phoff = 5; # Program header file offset
+$e_shoff = 6; # Section header file offset
+$e_flags = 7; # File flags
+$e_ehsize = 8; # Size of ELF header
+$e_phentsize = 9; # Size of program header
+$e_phnum = 10; # Number of program header entries
+$e_shentsize = 11; # Size of section header
+$e_shnum = 12; # Number of section header entries
+$e_shstrndx = 13; # Section header table string index
+
+#
+# Section header field numbers
+#
+
+$sh_name = 0; # Section name
+$sh_type = 1; # Section header type
+$sh_flags = 2; # Section header flags
+$sh_addr = 3; # Virtual address
+$sh_offset = 4; # File offset
+$sh_size = 5; # Section size
+$sh_link = 6; # Miscellaneous info
+$sh_info = 7; # More miscellaneous info
+$sh_addralign = 8; # Memory alignment
+$sh_entsize = 9; # Entry size if this is a table
diff --git a/arch/ppc/boot/utils/hack-coff.c b/arch/ppc/boot/utils/hack-coff.c
new file mode 100644
index 0000000..5e5a657
--- /dev/null
+++ b/arch/ppc/boot/utils/hack-coff.c
@@ -0,0 +1,84 @@
+/*
+ * hack-coff.c - hack the header of an xcoff file to fill in
+ * a few fields needed by the Open Firmware xcoff loader on
+ * Power Macs but not initialized by objcopy.
+ *
+ * Copyright (C) Paul Mackerras 1997.
+ *
+ * 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.
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+#include "rs6000.h"
+
+#define AOUT_MAGIC 0x010b
+
+#define get_16be(x) ((((unsigned char *)(x))[0] << 8) \
+ + ((unsigned char *)(x))[1])
+#define put_16be(x, v) (((unsigned char *)(x))[0] = (v) >> 8, \
+ ((unsigned char *)(x))[1] = (v) & 0xff)
+#define get_32be(x) ((((unsigned char *)(x))[0] << 24) \
+ + (((unsigned char *)(x))[1] << 16) \
+ + (((unsigned char *)(x))[2] << 8) \
+ + ((unsigned char *)(x))[3])
+
+int
+main(int ac, char **av)
+{
+ int fd;
+ int i, nsect;
+ int aoutsz;
+ struct external_filehdr fhdr;
+ AOUTHDR aout;
+ struct external_scnhdr shdr;
+
+ if (ac != 2) {
+ fprintf(stderr, "Usage: hack-coff coff-file\n");
+ exit(1);
+ }
+ if ((fd = open(av[1], 2)) == -1) {
+ perror(av[2]);
+ exit(1);
+ }
+ if (read(fd, &fhdr, sizeof(fhdr)) != sizeof(fhdr))
+ goto readerr;
+ i = get_16be(fhdr.f_magic);
+ if (i != U802TOCMAGIC && i != U802WRMAGIC && i != U802ROMAGIC) {
+ fprintf(stderr, "%s: not an xcoff file\n", av[1]);
+ exit(1);
+ }
+ aoutsz = get_16be(fhdr.f_opthdr);
+ if (read(fd, &aout, aoutsz) != aoutsz)
+ goto readerr;
+ nsect = get_16be(fhdr.f_nscns);
+ for (i = 0; i < nsect; ++i) {
+ if (read(fd, &shdr, sizeof(shdr)) != sizeof(shdr))
+ goto readerr;
+ if (strcmp(shdr.s_name, ".text") == 0) {
+ put_16be(aout.o_snentry, i+1);
+ put_16be(aout.o_sntext, i+1);
+ } else if (strcmp(shdr.s_name, ".data") == 0) {
+ put_16be(aout.o_sndata, i+1);
+ } else if (strcmp(shdr.s_name, ".bss") == 0) {
+ put_16be(aout.o_snbss, i+1);
+ }
+ }
+ put_16be(aout.magic, AOUT_MAGIC);
+ if (lseek(fd, (long) sizeof(struct external_filehdr), 0) == -1
+ || write(fd, &aout, aoutsz) != aoutsz) {
+ fprintf(stderr, "%s: write error\n", av[1]);
+ exit(1);
+ }
+ close(fd);
+ exit(0);
+
+readerr:
+ fprintf(stderr, "%s: read error or file too short\n", av[1]);
+ exit(1);
+}
diff --git a/arch/ppc/boot/utils/mkbugboot.c b/arch/ppc/boot/utils/mkbugboot.c
new file mode 100644
index 0000000..8861222
--- /dev/null
+++ b/arch/ppc/boot/utils/mkbugboot.c
@@ -0,0 +1,187 @@
+/*
+ * arch/ppc/boot/utils/mkbugboot.c
+ *
+ * Makes a Motorola PPCBUG ROM bootable image which can be flashed
+ * into one of the FLASH banks on a Motorola PowerPlus board.
+ *
+ * Author: Matt Porter <mporter@mvista.com>
+ *
+ * 2001 (c) MontaVista, Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+
+#define ELF_HEADER_SIZE 65536
+
+#include <unistd.h>
+#include <sys/stat.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <fcntl.h>
+#ifdef __sun__
+#include <inttypes.h>
+#else
+#include <stdint.h>
+#endif
+
+#ifdef __i386__
+#define cpu_to_be32(x) le32_to_cpu(x)
+#define cpu_to_be16(x) le16_to_cpu(x)
+#else
+#define cpu_to_be32(x) (x)
+#define cpu_to_be16(x) (x)
+#endif
+
+#define cpu_to_le32(x) le32_to_cpu((x))
+unsigned long le32_to_cpu(unsigned long x)
+{
+ return (((x & 0x000000ffU) << 24) |
+ ((x & 0x0000ff00U) << 8) |
+ ((x & 0x00ff0000U) >> 8) |
+ ((x & 0xff000000U) >> 24));
+}
+
+#define cpu_to_le16(x) le16_to_cpu((x))
+unsigned short le16_to_cpu(unsigned short x)
+{
+ return (((x & 0x00ff) << 8) |
+ ((x & 0xff00) >> 8));
+}
+
+/* size of read buffer */
+#define SIZE 0x1000
+
+/* PPCBUG ROM boot header */
+typedef struct bug_boot_header {
+ uint8_t magic_word[4]; /* "BOOT" */
+ uint32_t entry_offset; /* Offset from top of header to code */
+ uint32_t routine_length; /* Length of code */
+ uint8_t routine_name[8]; /* Name of the boot code */
+} bug_boot_header_t;
+
+#define HEADER_SIZE sizeof(bug_boot_header_t)
+
+uint32_t copy_image(int32_t in_fd, int32_t out_fd)
+{
+ uint8_t buf[SIZE];
+ int n;
+ uint32_t image_size = 0;
+ uint8_t zero = 0;
+
+ lseek(in_fd, ELF_HEADER_SIZE, SEEK_SET);
+
+ /* Copy an image while recording its size */
+ while ( (n = read(in_fd, buf, SIZE)) > 0 )
+ {
+ image_size = image_size + n;
+ write(out_fd, buf, n);
+ }
+
+ /* BUG romboot requires that our size is divisible by 2 */
+ /* align image to 2 byte boundary */
+ if (image_size % 2)
+ {
+ image_size++;
+ write(out_fd, &zero, 1);
+ }
+
+ return image_size;
+}
+
+void write_bugboot_header(int32_t out_fd, uint32_t boot_size)
+{
+ uint8_t header_block[HEADER_SIZE];
+ bug_boot_header_t *bbh = (bug_boot_header_t *)&header_block[0];
+
+ memset(header_block, 0, HEADER_SIZE);
+
+ /* Fill in the PPCBUG ROM boot header */
+ strncpy(bbh->magic_word, "BOOT", 4); /* PPCBUG magic word */
+ bbh->entry_offset = cpu_to_be32(HEADER_SIZE); /* Entry address */
+ bbh->routine_length= cpu_to_be32(HEADER_SIZE+boot_size+2); /* Routine length */
+ strncpy(bbh->routine_name, "LINUXROM", 8); /* Routine name */
+
+ /* Output the header and bootloader to the file */
+ write(out_fd, header_block, HEADER_SIZE);
+}
+
+uint16_t calc_checksum(int32_t bug_fd)
+{
+ uint32_t checksum_var = 0;
+ uint8_t buf[2];
+ int n;
+
+ /* Checksum loop */
+ while ( (n = read(bug_fd, buf, 2) ) )
+ {
+ checksum_var = checksum_var + *(uint16_t *)buf;
+
+ /* If we carry out, mask it and add one to the checksum */
+ if (checksum_var >> 16)
+ checksum_var = (checksum_var & 0x0000ffff) + 1;
+ }
+
+ return checksum_var;
+}
+
+int main(int argc, char *argv[])
+{
+ int32_t image_fd, bugboot_fd;
+ int argptr = 1;
+ uint32_t kernel_size = 0;
+ uint16_t checksum = 0;
+ uint8_t bugbootname[256];
+
+ if ( (argc != 3) )
+ {
+ fprintf(stderr, "usage: %s <kernel_image> <bugboot>\n",argv[0]);
+ exit(-1);
+ }
+
+ /* Get file args */
+
+ /* kernel image file */
+ if ((image_fd = open( argv[argptr] , 0)) < 0)
+ exit(-1);
+ argptr++;
+
+ /* bugboot file */
+ if ( !strcmp( argv[argptr], "-" ) )
+ bugboot_fd = 1; /* stdout */
+ else
+ if ((bugboot_fd = creat( argv[argptr] , 0755)) < 0)
+ exit(-1);
+ else
+ strcpy(bugbootname, argv[argptr]);
+ argptr++;
+
+ /* Set file position after ROM header block where zImage will be written */
+ lseek(bugboot_fd, HEADER_SIZE, SEEK_SET);
+
+ /* Copy kernel image into bugboot image */
+ kernel_size = copy_image(image_fd, bugboot_fd);
+ close(image_fd);
+
+ /* Set file position to beginning where header/romboot will be written */
+ lseek(bugboot_fd, 0, SEEK_SET);
+
+ /* Write out BUG header/romboot */
+ write_bugboot_header(bugboot_fd, kernel_size);
+
+ /* Close bugboot file */
+ close(bugboot_fd);
+
+ /* Reopen it as read/write */
+ bugboot_fd = open(bugbootname, O_RDWR);
+
+ /* Calculate checksum */
+ checksum = calc_checksum(bugboot_fd);
+
+ /* Write out the calculated checksum */
+ write(bugboot_fd, &checksum, 2);
+
+ return 0;
+}
diff --git a/arch/ppc/boot/utils/mknote.c b/arch/ppc/boot/utils/mknote.c
new file mode 100644
index 0000000..b9fbb2c
--- /dev/null
+++ b/arch/ppc/boot/utils/mknote.c
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) Cort Dougan 1999.
+ *
+ * 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.
+ *
+ * Generate a note section as per the CHRP specification.
+ *
+ */
+
+#include <stdio.h>
+#include <string.h>
+
+#define PL(x) printf("%c%c%c%c", ((x)>>24)&0xff, ((x)>>16)&0xff, ((x)>>8)&0xff, (x)&0xff );
+
+int main(void)
+{
+/* header */
+ /* namesz */
+ PL(strlen("PowerPC")+1);
+ /* descrsz */
+ PL(6*4);
+ /* type */
+ PL(0x1275);
+ /* name */
+ printf("PowerPC"); printf("%c", 0);
+
+/* descriptor */
+ /* real-mode */
+ PL(0xffffffff);
+ /* real-base */
+ PL(0x00c00000);
+ /* real-size */
+ PL(0xffffffff);
+ /* virt-base */
+ PL(0xffffffff);
+ /* virt-size */
+ PL(0xffffffff);
+ /* load-base */
+ PL(0x4000);
+ return 0;
+}
diff --git a/arch/ppc/boot/utils/mkprep.c b/arch/ppc/boot/utils/mkprep.c
new file mode 100644
index 0000000..f6d5a2f
--- /dev/null
+++ b/arch/ppc/boot/utils/mkprep.c
@@ -0,0 +1,293 @@
+/*
+ * Makes a prep bootable image which can be dd'd onto
+ * a disk device to make a bootdisk. Will take
+ * as input a elf executable, strip off the header
+ * and write out a boot image as:
+ * 1) default - strips elf header
+ * suitable as a network boot image
+ * 2) -pbp - strips elf header and writes out prep boot partition image
+ * cat or dd onto disk for booting
+ * 3) -asm - strips elf header and writes out as asm data
+ * useful for generating data for a compressed image
+ * -- Cort
+ *
+ * Modified for x86 hosted builds by Matt Porter <porter@neta.com>
+ * Modified for Sparc hosted builds by Peter Wahl <PeterWahl@web.de>
+ */
+
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <strings.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#define cpu_to_le32(x) le32_to_cpu((x))
+unsigned long le32_to_cpu(unsigned long x)
+{
+ return (((x & 0x000000ffU) << 24) |
+ ((x & 0x0000ff00U) << 8) |
+ ((x & 0x00ff0000U) >> 8) |
+ ((x & 0xff000000U) >> 24));
+}
+
+
+#define cpu_to_le16(x) le16_to_cpu((x))
+unsigned short le16_to_cpu(unsigned short x)
+{
+ return (((x & 0x00ff) << 8) |
+ ((x & 0xff00) >> 8));
+}
+
+#define cpu_to_be32(x) (x)
+#define be32_to_cpu(x) (x)
+#define cpu_to_be16(x) (x)
+#define be16_to_cpu(x) (x)
+
+/* size of read buffer */
+#define SIZE 0x1000
+
+
+typedef unsigned long dword_t;
+typedef unsigned short word_t;
+typedef unsigned char byte_t;
+typedef byte_t block_t[512];
+typedef byte_t page_t[4096];
+
+
+/*
+ * Partition table entry
+ * - from the PReP spec
+ */
+typedef struct partition_entry {
+ byte_t boot_indicator;
+ byte_t starting_head;
+ byte_t starting_sector;
+ byte_t starting_cylinder;
+
+ byte_t system_indicator;
+ byte_t ending_head;
+ byte_t ending_sector;
+ byte_t ending_cylinder;
+
+ dword_t beginning_sector;
+ dword_t number_of_sectors;
+} partition_entry_t;
+
+#define BootActive 0x80
+#define SystemPrep 0x41
+
+void copy_image(int , int);
+void write_prep_partition(int , int );
+void write_asm_data( int in, int out );
+
+unsigned int elfhdr_size = 65536;
+
+int main(int argc, char *argv[])
+{
+ int in_fd, out_fd;
+ int argptr = 1;
+ unsigned int prep = 0;
+ unsigned int asmoutput = 0;
+
+ if ( (argc < 3) || (argc > 4) )
+ {
+ fprintf(stderr, "usage: %s [-pbp] [-asm] <boot-file> <image>\n",argv[0]);
+ exit(-1);
+ }
+
+ /* needs to handle args more elegantly -- but this is a small/simple program */
+
+ /* check for -pbp */
+ if ( !strcmp( argv[argptr], "-pbp" ) )
+ {
+ prep = 1;
+ argptr++;
+ }
+
+ /* check for -asm */
+ if ( !strcmp( argv[argptr], "-asm" ) )
+ {
+ asmoutput = 1;
+ argptr++;
+ }
+
+ /* input file */
+ if ( !strcmp( argv[argptr], "-" ) )
+ in_fd = 0; /* stdin */
+ else
+ if ((in_fd = open( argv[argptr] , 0)) < 0)
+ exit(-1);
+ argptr++;
+
+ /* output file */
+ if ( !strcmp( argv[argptr], "-" ) )
+ out_fd = 1; /* stdout */
+ else
+ if ((out_fd = creat( argv[argptr] , 0755)) < 0)
+ exit(-1);
+ argptr++;
+
+ /* skip elf header in input file */
+ /*if ( !prep )*/
+ lseek(in_fd, elfhdr_size, SEEK_SET);
+
+ /* write prep partition if necessary */
+ if ( prep )
+ write_prep_partition( in_fd, out_fd );
+
+ /* write input image to bootimage */
+ if ( asmoutput )
+ write_asm_data( in_fd, out_fd );
+ else
+ copy_image(in_fd, out_fd);
+
+ return 0;
+}
+
+void write_prep_partition(int in, int out)
+{
+ unsigned char block[512];
+ partition_entry_t pe;
+ dword_t *entry = (dword_t *)&block[0];
+ dword_t *length = (dword_t *)&block[sizeof(long)];
+ struct stat info;
+
+ if (fstat(in, &info) < 0)
+ {
+ fprintf(stderr,"info failed\n");
+ exit(-1);
+ }
+
+ bzero( block, sizeof block );
+
+ /* set entry point and boot image size skipping over elf header */
+#ifdef __i386__
+ *entry = 0x400/*+65536*/;
+ *length = info.st_size-elfhdr_size+0x400;
+#else
+ *entry = cpu_to_le32(0x400/*+65536*/);
+ *length = cpu_to_le32(info.st_size-elfhdr_size+0x400);
+#endif /* __i386__ */
+
+ /* sets magic number for msdos partition (used by linux) */
+ block[510] = 0x55;
+ block[511] = 0xAA;
+
+ /*
+ * Build a "PReP" partition table entry in the boot record
+ * - "PReP" may only look at the system_indicator
+ */
+ pe.boot_indicator = BootActive;
+ pe.system_indicator = SystemPrep;
+ /*
+ * The first block of the diskette is used by this "boot record" which
+ * actually contains the partition table. (The first block of the
+ * partition contains the boot image, but I digress...) We'll set up
+ * one partition on the diskette and it shall contain the rest of the
+ * diskette.
+ */
+ pe.starting_head = 0; /* zero-based */
+ pe.starting_sector = 2; /* one-based */
+ pe.starting_cylinder = 0; /* zero-based */
+ pe.ending_head = 1; /* assumes two heads */
+ pe.ending_sector = 18; /* assumes 18 sectors/track */
+ pe.ending_cylinder = 79; /* assumes 80 cylinders/diskette */
+
+ /*
+ * The "PReP" software ignores the above fields and just looks at
+ * the next two.
+ * - size of the diskette is (assumed to be)
+ * (2 tracks/cylinder)(18 sectors/tracks)(80 cylinders/diskette)
+ * - unlike the above sector numbers, the beginning sector is zero-based!
+ */
+#if 0
+ pe.beginning_sector = cpu_to_le32(1);
+#else
+ /* This has to be 0 on the PowerStack? */
+#ifdef __i386__
+ pe.beginning_sector = 0;
+#else
+ pe.beginning_sector = cpu_to_le32(0);
+#endif /* __i386__ */
+#endif
+
+#ifdef __i386__
+ pe.number_of_sectors = 2*18*80-1;
+#else
+ pe.number_of_sectors = cpu_to_le32(2*18*80-1);
+#endif /* __i386__ */
+
+ memcpy(&block[0x1BE], &pe, sizeof(pe));
+
+ write( out, block, sizeof(block) );
+ write( out, entry, sizeof(*entry) );
+ write( out, length, sizeof(*length) );
+ /* set file position to 2nd sector where image will be written */
+ lseek( out, 0x400, SEEK_SET );
+}
+
+
+
+void
+copy_image(int in, int out)
+{
+ char buf[SIZE];
+ int n;
+
+ while ( (n = read(in, buf, SIZE)) > 0 )
+ write(out, buf, n);
+}
+
+
+void
+write_asm_data( int in, int out )
+{
+ int i, cnt, pos, len;
+ unsigned int cksum, val;
+ unsigned char *lp;
+ unsigned char buf[SIZE];
+ unsigned char str[256];
+
+ write( out, "\t.data\n\t.globl input_data\ninput_data:\n",
+ strlen( "\t.data\n\t.globl input_data\ninput_data:\n" ) );
+ pos = 0;
+ cksum = 0;
+ while ((len = read(in, buf, sizeof(buf))) > 0)
+ {
+ cnt = 0;
+ lp = (unsigned char *)buf;
+ len = (len + 3) & ~3; /* Round up to longwords */
+ for (i = 0; i < len; i += 4)
+ {
+ if (cnt == 0)
+ {
+ write( out, "\t.long\t", strlen( "\t.long\t" ) );
+ }
+ sprintf( str, "0x%02X%02X%02X%02X", lp[0], lp[1], lp[2], lp[3]);
+ write( out, str, strlen(str) );
+ val = *(unsigned long *)lp;
+ cksum ^= val;
+ lp += 4;
+ if (++cnt == 4)
+ {
+ cnt = 0;
+ sprintf( str, " # %x \n", pos+i-12);
+ write( out, str, strlen(str) );
+ } else
+ {
+ write( out, ",", 1 );
+ }
+ }
+ if (cnt)
+ {
+ write( out, "0\n", 2 );
+ }
+ pos += len;
+ }
+ sprintf(str, "\t.globl input_len\ninput_len:\t.long\t0x%x\n", pos);
+ write( out, str, strlen(str) );
+
+ fprintf(stderr, "cksum = %x\n", cksum);
+}
diff --git a/arch/ppc/boot/utils/mktree.c b/arch/ppc/boot/utils/mktree.c
new file mode 100644
index 0000000..2be22e2
--- /dev/null
+++ b/arch/ppc/boot/utils/mktree.c
@@ -0,0 +1,152 @@
+/*
+ * Makes a tree bootable image for IBM Evaluation boards.
+ * Basically, just take a zImage, skip the ELF header, and stuff
+ * a 32 byte header on the front.
+ *
+ * We use htonl, which is a network macro, to make sure we're doing
+ * The Right Thing on an LE machine. It's non-obvious, but it should
+ * work on anything BSD'ish.
+ */
+
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <netinet/in.h>
+#ifdef __sun__
+#include <inttypes.h>
+#else
+#include <stdint.h>
+#endif
+
+/* This gets tacked on the front of the image. There are also a few
+ * bytes allocated after the _start label used by the boot rom (see
+ * head.S for details).
+ */
+typedef struct boot_block {
+ uint32_t bb_magic; /* 0x0052504F */
+ uint32_t bb_dest; /* Target address of the image */
+ uint32_t bb_num_512blocks; /* Size, rounded-up, in 512 byte blks */
+ uint32_t bb_debug_flag; /* Run debugger or image after load */
+ uint32_t bb_entry_point; /* The image address to start */
+ uint32_t bb_checksum; /* 32 bit checksum including header */
+ uint32_t reserved[2];
+} boot_block_t;
+
+#define IMGBLK 512
+char tmpbuf[IMGBLK];
+
+int main(int argc, char *argv[])
+{
+ int in_fd, out_fd;
+ int nblks, i;
+ uint cksum, *cp;
+ struct stat st;
+ boot_block_t bt;
+
+ if (argc < 3) {
+ fprintf(stderr, "usage: %s <zImage-file> <boot-image> [entry-point]\n",argv[0]);
+ exit(1);
+ }
+
+ if (stat(argv[1], &st) < 0) {
+ perror("stat");
+ exit(2);
+ }
+
+ nblks = (st.st_size + IMGBLK) / IMGBLK;
+
+ bt.bb_magic = htonl(0x0052504F);
+
+ /* If we have the optional entry point parameter, use it */
+ if (argc == 4)
+ bt.bb_dest = bt.bb_entry_point = htonl(strtoul(argv[3], NULL, 0));
+ else
+ bt.bb_dest = bt.bb_entry_point = htonl(0x500000);
+
+ /* We know these from the linker command.
+ * ...and then move it up into memory a little more so the
+ * relocation can happen.
+ */
+ bt.bb_num_512blocks = htonl(nblks);
+ bt.bb_debug_flag = 0;
+
+ bt.bb_checksum = 0;
+
+ /* To be neat and tidy :-).
+ */
+ bt.reserved[0] = 0;
+ bt.reserved[1] = 0;
+
+ if ((in_fd = open(argv[1], O_RDONLY)) < 0) {
+ perror("zImage open");
+ exit(3);
+ }
+
+ if ((out_fd = open(argv[2], (O_RDWR | O_CREAT | O_TRUNC), 0666)) < 0) {
+ perror("bootfile open");
+ exit(3);
+ }
+
+ cksum = 0;
+ cp = (void *)&bt;
+ for (i=0; i<sizeof(bt)/sizeof(uint); i++)
+ cksum += *cp++;
+
+ /* Assume zImage is an ELF file, and skip the 64K header.
+ */
+ if (read(in_fd, tmpbuf, IMGBLK) != IMGBLK) {
+ fprintf(stderr, "%s is too small to be an ELF image\n",
+ argv[1]);
+ exit(4);
+ }
+
+ if ((*(uint *)tmpbuf) != htonl(0x7f454c46)) {
+ fprintf(stderr, "%s is not an ELF image\n", argv[1]);
+ exit(4);
+ }
+
+ if (lseek(in_fd, (64 * 1024), SEEK_SET) < 0) {
+ fprintf(stderr, "%s failed to seek in ELF image\n", argv[1]);
+ exit(4);
+ }
+
+ nblks -= (64 * 1024) / IMGBLK;
+
+ /* And away we go......
+ */
+ if (write(out_fd, &bt, sizeof(bt)) != sizeof(bt)) {
+ perror("boot-image write");
+ exit(5);
+ }
+
+ while (nblks-- > 0) {
+ if (read(in_fd, tmpbuf, IMGBLK) < 0) {
+ perror("zImage read");
+ exit(5);
+ }
+ cp = (uint *)tmpbuf;
+ for (i=0; i<sizeof(tmpbuf)/sizeof(uint); i++)
+ cksum += *cp++;
+ if (write(out_fd, tmpbuf, sizeof(tmpbuf)) != sizeof(tmpbuf)) {
+ perror("boot-image write");
+ exit(5);
+ }
+ }
+
+ /* rewrite the header with the computed checksum.
+ */
+ bt.bb_checksum = htonl(cksum);
+ if (lseek(out_fd, 0, SEEK_SET) < 0) {
+ perror("rewrite seek");
+ exit(1);
+ }
+ if (write(out_fd, &bt, sizeof(bt)) != sizeof(bt)) {
+ perror("boot-image rewrite");
+ exit(1);
+ }
+
+ exit(0);
+}
diff --git a/arch/ppc/configs/FADS_defconfig b/arch/ppc/configs/FADS_defconfig
new file mode 100644
index 0000000..c1934f8
--- /dev/null
+++ b/arch/ppc/configs/FADS_defconfig
@@ -0,0 +1,520 @@
+#
+# Automatically generated make config: don't edit
+#
+CONFIG_MMU=y
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_HAVE_DEC_LOCK=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+
+#
+# General setup
+#
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_EMBEDDED=y
+CONFIG_FUTEX=y
+# CONFIG_EPOLL is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_OBSOLETE_MODPARM=y
+# CONFIG_MODVERSIONS is not set
+CONFIG_KMOD=y
+
+#
+# Platform support
+#
+CONFIG_PPC=y
+CONFIG_PPC32=y
+# CONFIG_6xx is not set
+# CONFIG_40x is not set
+# CONFIG_POWER3 is not set
+CONFIG_8xx=y
+
+#
+# IBM 4xx options
+#
+CONFIG_EMBEDDEDBOOT=y
+CONFIG_SERIAL_CONSOLE=y
+CONFIG_NOT_COHERENT_CACHE=y
+# CONFIG_RPXLITE is not set
+# CONFIG_RPXCLASSIC is not set
+# CONFIG_BSEIP is not set
+CONFIG_FADS=y
+# CONFIG_TQM823L is not set
+# CONFIG_TQM850L is not set
+# CONFIG_TQM855L is not set
+# CONFIG_TQM860L is not set
+# CONFIG_FPS850L is not set
+# CONFIG_SPD823TS is not set
+# CONFIG_IVMS8 is not set
+# CONFIG_IVML24 is not set
+# CONFIG_SM850 is not set
+# CONFIG_HERMES_PRO is not set
+# CONFIG_IP860 is not set
+# CONFIG_LWMON is not set
+# CONFIG_PCU_E is not set
+# CONFIG_CCM is not set
+# CONFIG_LANTEC is not set
+# CONFIG_MBX is not set
+# CONFIG_WINCEPT is not set
+# CONFIG_SMP is not set
+# CONFIG_PREEMPT is not set
+CONFIG_MATH_EMULATION=y
+# CONFIG_CPU_FREQ is not set
+
+#
+# General setup
+#
+# CONFIG_HIGHMEM is not set
+# CONFIG_PCI is not set
+# CONFIG_PCI_DOMAINS is not set
+# CONFIG_PCI_QSPAN is not set
+CONFIG_KCORE_ELF=y
+CONFIG_BINFMT_ELF=y
+CONFIG_KERNEL_ELF=y
+# CONFIG_BINFMT_MISC is not set
+# CONFIG_HOTPLUG is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+# CONFIG_CMDLINE_BOOL is not set
+
+#
+# Advanced setup
+#
+# CONFIG_ADVANCED_OPTIONS is not set
+
+#
+# Default settings for advanced configuration options are used
+#
+CONFIG_HIGHMEM_START=0xfe000000
+CONFIG_LOWMEM_SIZE=0x30000000
+CONFIG_KERNEL_START=0xc0000000
+CONFIG_TASK_SIZE=0x80000000
+CONFIG_BOOT_LOAD=0x00400000
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Plug and Play support
+#
+# CONFIG_PNP is not set
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_RAM is not set
+# CONFIG_BLK_DEV_INITRD is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# ATA/IDE/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI support
+#
+# CONFIG_SCSI is not set
+
+#
+# Fusion MPT device support
+#
+
+#
+# I2O device support
+#
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+# CONFIG_NETLINK_DEV is not set
+# CONFIG_NETFILTER is not set
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+# CONFIG_INET_ECN is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_IPV6 is not set
+# CONFIG_XFRM_USER is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+CONFIG_IPV6_SCTP__=y
+# CONFIG_IP_SCTP is not set
+# CONFIG_ATM is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_LLC is not set
+# CONFIG_DECNET is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_HW_FLOWCONTROL is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_ETHERTAP is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+# CONFIG_MII is not set
+# CONFIG_OAKNET is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Token Ring devices (depends on LLC=y)
+#
+# CONFIG_SHAPER is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+
+#
+# Amateur Radio support
+#
+# CONFIG_HAMRADIO is not set
+
+#
+# IrDA (infrared) support
+#
+# CONFIG_IRDA is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN_BOOL is not set
+
+#
+# Graphics support
+#
+# CONFIG_FB is not set
+
+#
+# Old CD-ROM drivers (not SCSI, not IDE)
+#
+# CONFIG_CD_NO_IDESCSI is not set
+
+#
+# Input device support
+#
+# CONFIG_INPUT is not set
+
+#
+# Userland interfaces
+#
+
+#
+# Input I/O drivers
+#
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+# CONFIG_SERIO is not set
+
+#
+# Input Device Drivers
+#
+
+#
+# Macintosh device drivers
+#
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_SERIAL_CPM=y
+CONFIG_SERIAL_CPM_CONSOLE=y
+# CONFIG_SERIAL_CPM_SCC1 is not set
+# CONFIG_SERIAL_CPM_SCC2 is not set
+# CONFIG_SERIAL_CPM_SCC3 is not set
+# CONFIG_SERIAL_CPM_SCC4 is not set
+CONFIG_SERIAL_CPM_SMC1=y
+CONFIG_SERIAL_CPM_SMC2=y
+# CONFIG_SERIAL_CPM_ALT_SMC2 is not set
+CONFIG_UNIX98_PTYS=y
+# CONFIG_LEGACY_PTYS is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# I2C Hardware Sensors Mainboard support
+#
+
+#
+# I2C Hardware Sensors Chip support
+#
+# CONFIG_I2C_SENSOR is not set
+
+#
+# Mice
+#
+# CONFIG_BUSMOUSE is not set
+# CONFIG_QIC02_TAPE is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_NVRAM is not set
+CONFIG_GEN_RTC=y
+# CONFIG_GEN_RTC_X is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_FTAPE is not set
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_HANGCHECK_TIMER is not set
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# File systems
+#
+# CONFIG_EXT2_FS is not set
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_FS_XATTR=y
+# CONFIG_EXT3_FS_POSIX_ACL is not set
+# CONFIG_EXT3_FS_SECURITY is not set
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+CONFIG_FS_MBCACHE=y
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_FAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+# CONFIG_DEVFS_FS is not set
+CONFIG_DEVPTS_FS=y
+# CONFIG_DEVPTS_FS_XATTR is not set
+# CONFIG_TMPFS is not set
+CONFIG_RAMFS=y
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+# CONFIG_NFS_V3 is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFSD is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+# CONFIG_EXPORTFS is not set
+CONFIG_SUNRPC=y
+# CONFIG_SUNRPC_GSS is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_INTERMEZZO_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
+# CONFIG_MSDOS_PARTITION is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_NEC98_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_EFI_PARTITION is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# MPC8xx CPM Options
+#
+CONFIG_SCC_ENET=y
+CONFIG_SCC1_ENET=y
+# CONFIG_SCC2_ENET is not set
+# CONFIG_SCC3_ENET is not set
+# CONFIG_FEC_ENET is not set
+CONFIG_ENET_BIG_BUFFERS=y
+
+#
+# Generic MPC8xx Options
+#
+CONFIG_8xx_COPYBACK=y
+# CONFIG_8xx_CPU6 is not set
+# CONFIG_UCODE_PATCH is not set
+
+#
+# USB support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# Bluetooth support
+#
+# CONFIG_BT is not set
+
+#
+# Library routines
+#
+# CONFIG_CRC32 is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_DEBUG_KERNEL is not set
+# CONFIG_KALLSYMS is not set
+
+#
+# Security options
+#
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
diff --git a/arch/ppc/configs/IVMS8_defconfig b/arch/ppc/configs/IVMS8_defconfig
new file mode 100644
index 0000000..66bbefe
--- /dev/null
+++ b/arch/ppc/configs/IVMS8_defconfig
@@ -0,0 +1,548 @@
+#
+# Automatically generated make config: don't edit
+#
+CONFIG_MMU=y
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_HAVE_DEC_LOCK=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+
+#
+# General setup
+#
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_EMBEDDED=y
+CONFIG_FUTEX=y
+# CONFIG_EPOLL is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_OBSOLETE_MODPARM=y
+# CONFIG_MODVERSIONS is not set
+CONFIG_KMOD=y
+
+#
+# Platform support
+#
+CONFIG_PPC=y
+CONFIG_PPC32=y
+# CONFIG_6xx is not set
+# CONFIG_40x is not set
+# CONFIG_POWER3 is not set
+CONFIG_8xx=y
+
+#
+# IBM 4xx options
+#
+CONFIG_EMBEDDEDBOOT=y
+CONFIG_SERIAL_CONSOLE=y
+CONFIG_NOT_COHERENT_CACHE=y
+# CONFIG_RPXLITE is not set
+# CONFIG_RPXCLASSIC is not set
+# CONFIG_BSEIP is not set
+# CONFIG_FADS is not set
+# CONFIG_TQM823L is not set
+# CONFIG_TQM850L is not set
+# CONFIG_TQM855L is not set
+# CONFIG_TQM860L is not set
+# CONFIG_FPS850L is not set
+# CONFIG_SPD823TS is not set
+CONFIG_IVMS8=y
+# CONFIG_IVML24 is not set
+# CONFIG_SM850 is not set
+# CONFIG_HERMES_PRO is not set
+# CONFIG_IP860 is not set
+# CONFIG_LWMON is not set
+# CONFIG_PCU_E is not set
+# CONFIG_CCM is not set
+# CONFIG_LANTEC is not set
+# CONFIG_MBX is not set
+# CONFIG_WINCEPT is not set
+# CONFIG_SMP is not set
+# CONFIG_PREEMPT is not set
+CONFIG_MATH_EMULATION=y
+# CONFIG_CPU_FREQ is not set
+
+#
+# General setup
+#
+# CONFIG_HIGHMEM is not set
+# CONFIG_PCI is not set
+# CONFIG_PCI_DOMAINS is not set
+# CONFIG_PCI_QSPAN is not set
+CONFIG_KCORE_ELF=y
+CONFIG_BINFMT_ELF=y
+CONFIG_KERNEL_ELF=y
+# CONFIG_BINFMT_MISC is not set
+# CONFIG_HOTPLUG is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+# CONFIG_CMDLINE_BOOL is not set
+
+#
+# Advanced setup
+#
+# CONFIG_ADVANCED_OPTIONS is not set
+
+#
+# Default settings for advanced configuration options are used
+#
+CONFIG_HIGHMEM_START=0xfe000000
+CONFIG_LOWMEM_SIZE=0x30000000
+CONFIG_KERNEL_START=0xc0000000
+CONFIG_TASK_SIZE=0x80000000
+CONFIG_BOOT_LOAD=0x00400000
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Plug and Play support
+#
+# CONFIG_PNP is not set
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_RAM is not set
+# CONFIG_BLK_DEV_INITRD is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# ATA/IDE/MFM/RLL support
+#
+CONFIG_IDE=y
+
+#
+# IDE, ATA and ATAPI Block devices
+#
+CONFIG_BLK_DEV_IDE=y
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+# CONFIG_BLK_DEV_HD is not set
+CONFIG_BLK_DEV_IDEDISK=y
+CONFIG_IDEDISK_MULTI_MODE=y
+# CONFIG_IDEDISK_STROKE is not set
+CONFIG_BLK_DEV_IDECD=y
+# CONFIG_BLK_DEV_IDEFLOPPY is not set
+# CONFIG_IDE_TASK_IOCTL is not set
+
+#
+# IDE chipset support/bugfixes
+#
+CONFIG_BLK_DEV_MPC8xx_IDE=y
+CONFIG_IDE_8xx_PCCARD=y
+# CONFIG_IDE_8xx_DIRECT is not set
+# CONFIG_IDE_EXT_DIRECT is not set
+
+#
+# SCSI support
+#
+# CONFIG_SCSI is not set
+
+#
+# Fusion MPT device support
+#
+
+#
+# I2O device support
+#
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+# CONFIG_NETLINK_DEV is not set
+# CONFIG_NETFILTER is not set
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+# CONFIG_IP_PNP_BOOTP is not set
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+# CONFIG_INET_ECN is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_IPV6 is not set
+# CONFIG_XFRM_USER is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+CONFIG_IPV6_SCTP__=y
+# CONFIG_IP_SCTP is not set
+# CONFIG_ATM is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_LLC is not set
+# CONFIG_DECNET is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_HW_FLOWCONTROL is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_ETHERTAP is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+# CONFIG_MII is not set
+# CONFIG_OAKNET is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Token Ring devices (depends on LLC=y)
+#
+# CONFIG_SHAPER is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+
+#
+# Amateur Radio support
+#
+# CONFIG_HAMRADIO is not set
+
+#
+# IrDA (infrared) support
+#
+# CONFIG_IRDA is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN_BOOL is not set
+
+#
+# Graphics support
+#
+# CONFIG_FB is not set
+
+#
+# Old CD-ROM drivers (not SCSI, not IDE)
+#
+# CONFIG_CD_NO_IDESCSI is not set
+
+#
+# Input device support
+#
+# CONFIG_INPUT is not set
+
+#
+# Userland interfaces
+#
+
+#
+# Input I/O drivers
+#
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+# CONFIG_SERIO is not set
+
+#
+# Input Device Drivers
+#
+
+#
+# Macintosh device drivers
+#
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_SERIAL_CPM=y
+CONFIG_SERIAL_CPM_CONSOLE=y
+# CONFIG_SERIAL_CPM_SCC1 is not set
+# CONFIG_SERIAL_CPM_SCC2 is not set
+# CONFIG_SERIAL_CPM_SCC3 is not set
+# CONFIG_SERIAL_CPM_SCC4 is not set
+CONFIG_SERIAL_CPM_SMC1=y
+# CONFIG_SERIAL_CPM_SMC2 is not set
+CONFIG_UNIX98_PTYS=y
+# CONFIG_LEGACY_PTYS is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# I2C Hardware Sensors Mainboard support
+#
+
+#
+# I2C Hardware Sensors Chip support
+#
+# CONFIG_I2C_SENSOR is not set
+
+#
+# Mice
+#
+# CONFIG_BUSMOUSE is not set
+# CONFIG_QIC02_TAPE is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_NVRAM is not set
+CONFIG_GEN_RTC=y
+# CONFIG_GEN_RTC_X is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_FTAPE is not set
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_HANGCHECK_TIMER is not set
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_FS_XATTR=y
+# CONFIG_EXT3_FS_POSIX_ACL is not set
+# CONFIG_EXT3_FS_SECURITY is not set
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+CONFIG_FS_MBCACHE=y
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+CONFIG_ISO9660_FS=y
+# CONFIG_JOLIET is not set
+# CONFIG_ZISOFS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_FAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+# CONFIG_DEVFS_FS is not set
+CONFIG_DEVPTS_FS=y
+# CONFIG_DEVPTS_FS_XATTR is not set
+CONFIG_TMPFS=y
+CONFIG_RAMFS=y
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+# CONFIG_NFS_V3 is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFSD is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+# CONFIG_EXPORTFS is not set
+CONFIG_SUNRPC=y
+# CONFIG_SUNRPC_GSS is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_INTERMEZZO_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+CONFIG_MAC_PARTITION=y
+# CONFIG_MSDOS_PARTITION is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_NEC98_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_EFI_PARTITION is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# MPC8xx CPM Options
+#
+# CONFIG_SCC_ENET is not set
+CONFIG_FEC_ENET=y
+CONFIG_USE_MDIO=y
+CONFIG_FEC_AM79C874=y
+CONFIG_FEC_LXT970=y
+CONFIG_FEC_LXT971=y
+CONFIG_FEC_QS6612=y
+CONFIG_ENET_BIG_BUFFERS=y
+
+#
+# Generic MPC8xx Options
+#
+CONFIG_8xx_COPYBACK=y
+# CONFIG_8xx_CPU6 is not set
+# CONFIG_UCODE_PATCH is not set
+
+#
+# USB support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# Bluetooth support
+#
+# CONFIG_BT is not set
+
+#
+# Library routines
+#
+# CONFIG_CRC32 is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_DEBUG_KERNEL is not set
+# CONFIG_KALLSYMS is not set
+
+#
+# Security options
+#
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
diff --git a/arch/ppc/configs/SM850_defconfig b/arch/ppc/configs/SM850_defconfig
new file mode 100644
index 0000000..021884b
--- /dev/null
+++ b/arch/ppc/configs/SM850_defconfig
@@ -0,0 +1,522 @@
+#
+# Automatically generated make config: don't edit
+#
+CONFIG_MMU=y
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_HAVE_DEC_LOCK=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+
+#
+# General setup
+#
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_EMBEDDED=y
+CONFIG_FUTEX=y
+# CONFIG_EPOLL is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_OBSOLETE_MODPARM=y
+# CONFIG_MODVERSIONS is not set
+CONFIG_KMOD=y
+
+#
+# Platform support
+#
+CONFIG_PPC=y
+CONFIG_PPC32=y
+# CONFIG_6xx is not set
+# CONFIG_40x is not set
+# CONFIG_POWER3 is not set
+CONFIG_8xx=y
+
+#
+# IBM 4xx options
+#
+CONFIG_EMBEDDEDBOOT=y
+CONFIG_SERIAL_CONSOLE=y
+CONFIG_NOT_COHERENT_CACHE=y
+# CONFIG_RPXLITE is not set
+# CONFIG_RPXCLASSIC is not set
+# CONFIG_BSEIP is not set
+# CONFIG_FADS is not set
+# CONFIG_TQM823L is not set
+# CONFIG_TQM850L is not set
+# CONFIG_TQM855L is not set
+# CONFIG_TQM860L is not set
+# CONFIG_FPS850L is not set
+# CONFIG_SPD823TS is not set
+# CONFIG_IVMS8 is not set
+# CONFIG_IVML24 is not set
+CONFIG_SM850=y
+# CONFIG_HERMES_PRO is not set
+# CONFIG_IP860 is not set
+# CONFIG_LWMON is not set
+# CONFIG_PCU_E is not set
+# CONFIG_CCM is not set
+# CONFIG_LANTEC is not set
+# CONFIG_MBX is not set
+# CONFIG_WINCEPT is not set
+CONFIG_TQM8xxL=y
+# CONFIG_SMP is not set
+# CONFIG_PREEMPT is not set
+CONFIG_MATH_EMULATION=y
+# CONFIG_CPU_FREQ is not set
+
+#
+# General setup
+#
+# CONFIG_HIGHMEM is not set
+# CONFIG_PCI is not set
+# CONFIG_PCI_DOMAINS is not set
+# CONFIG_PCI_QSPAN is not set
+CONFIG_KCORE_ELF=y
+CONFIG_BINFMT_ELF=y
+CONFIG_KERNEL_ELF=y
+# CONFIG_BINFMT_MISC is not set
+# CONFIG_HOTPLUG is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+CONFIG_CMDLINE_BOOL=y
+CONFIG_CMDLINE="console=ttyCPM1"
+
+#
+# Advanced setup
+#
+# CONFIG_ADVANCED_OPTIONS is not set
+
+#
+# Default settings for advanced configuration options are used
+#
+CONFIG_HIGHMEM_START=0xfe000000
+CONFIG_LOWMEM_SIZE=0x30000000
+CONFIG_KERNEL_START=0xc0000000
+CONFIG_TASK_SIZE=0x80000000
+CONFIG_BOOT_LOAD=0x00400000
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Plug and Play support
+#
+# CONFIG_PNP is not set
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_RAM is not set
+# CONFIG_BLK_DEV_INITRD is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# ATA/IDE/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI support
+#
+# CONFIG_SCSI is not set
+
+#
+# Fusion MPT device support
+#
+
+#
+# I2O device support
+#
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+# CONFIG_NETLINK_DEV is not set
+# CONFIG_NETFILTER is not set
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+# CONFIG_IP_PNP_BOOTP is not set
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+# CONFIG_INET_ECN is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_IPV6 is not set
+# CONFIG_XFRM_USER is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+CONFIG_IPV6_SCTP__=y
+# CONFIG_IP_SCTP is not set
+# CONFIG_ATM is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_LLC is not set
+# CONFIG_DECNET is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_HW_FLOWCONTROL is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_ETHERTAP is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+# CONFIG_MII is not set
+# CONFIG_OAKNET is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Token Ring devices (depends on LLC=y)
+#
+# CONFIG_SHAPER is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+
+#
+# Amateur Radio support
+#
+# CONFIG_HAMRADIO is not set
+
+#
+# IrDA (infrared) support
+#
+# CONFIG_IRDA is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN_BOOL is not set
+
+#
+# Graphics support
+#
+# CONFIG_FB is not set
+
+#
+# Old CD-ROM drivers (not SCSI, not IDE)
+#
+# CONFIG_CD_NO_IDESCSI is not set
+
+#
+# Input device support
+#
+# CONFIG_INPUT is not set
+
+#
+# Userland interfaces
+#
+
+#
+# Input I/O drivers
+#
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+# CONFIG_SERIO is not set
+
+#
+# Input Device Drivers
+#
+
+#
+# Macintosh device drivers
+#
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_SERIAL_CPM=y
+CONFIG_SERIAL_CPM_CONSOLE=y
+# CONFIG_SERIAL_CPM_SCC1 is not set
+# CONFIG_SERIAL_CPM_SCC2 is not set
+# CONFIG_SERIAL_CPM_SCC3 is not set
+# CONFIG_SERIAL_CPM_SCC4 is not set
+CONFIG_SERIAL_CPM_SMC1=y
+CONFIG_SERIAL_CPM_SMC2=y
+CONFIG_SERIAL_CPM_ALT_SMC2=y
+CONFIG_UNIX98_PTYS=y
+# CONFIG_LEGACY_PTYS is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# I2C Hardware Sensors Mainboard support
+#
+
+#
+# I2C Hardware Sensors Chip support
+#
+# CONFIG_I2C_SENSOR is not set
+
+#
+# Mice
+#
+# CONFIG_BUSMOUSE is not set
+# CONFIG_QIC02_TAPE is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_NVRAM is not set
+CONFIG_GEN_RTC=y
+# CONFIG_GEN_RTC_X is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_FTAPE is not set
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_HANGCHECK_TIMER is not set
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# File systems
+#
+# CONFIG_EXT2_FS is not set
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_FS_XATTR=y
+# CONFIG_EXT3_FS_POSIX_ACL is not set
+# CONFIG_EXT3_FS_SECURITY is not set
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+CONFIG_FS_MBCACHE=y
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_FAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+# CONFIG_DEVFS_FS is not set
+CONFIG_DEVPTS_FS=y
+# CONFIG_DEVPTS_FS_XATTR is not set
+CONFIG_TMPFS=y
+CONFIG_RAMFS=y
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+# CONFIG_NFS_V3 is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFSD is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+# CONFIG_EXPORTFS is not set
+CONFIG_SUNRPC=y
+# CONFIG_SUNRPC_GSS is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_INTERMEZZO_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
+# CONFIG_MSDOS_PARTITION is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_NEC98_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_EFI_PARTITION is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# MPC8xx CPM Options
+#
+CONFIG_SCC_ENET=y
+# CONFIG_SCC1_ENET is not set
+# CONFIG_SCC2_ENET is not set
+CONFIG_SCC3_ENET=y
+# CONFIG_FEC_ENET is not set
+CONFIG_ENET_BIG_BUFFERS=y
+
+#
+# Generic MPC8xx Options
+#
+CONFIG_8xx_COPYBACK=y
+CONFIG_8xx_CPU6=y
+# CONFIG_UCODE_PATCH is not set
+
+#
+# USB support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# Bluetooth support
+#
+# CONFIG_BT is not set
+
+#
+# Library routines
+#
+# CONFIG_CRC32 is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_DEBUG_KERNEL is not set
+# CONFIG_KALLSYMS is not set
+
+#
+# Security options
+#
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
diff --git a/arch/ppc/configs/SPD823TS_defconfig b/arch/ppc/configs/SPD823TS_defconfig
new file mode 100644
index 0000000..ba60fea
--- /dev/null
+++ b/arch/ppc/configs/SPD823TS_defconfig
@@ -0,0 +1,520 @@
+#
+# Automatically generated make config: don't edit
+#
+CONFIG_MMU=y
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_HAVE_DEC_LOCK=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+
+#
+# General setup
+#
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_EMBEDDED=y
+CONFIG_FUTEX=y
+# CONFIG_EPOLL is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_OBSOLETE_MODPARM=y
+# CONFIG_MODVERSIONS is not set
+CONFIG_KMOD=y
+
+#
+# Platform support
+#
+CONFIG_PPC=y
+CONFIG_PPC32=y
+# CONFIG_6xx is not set
+# CONFIG_40x is not set
+# CONFIG_POWER3 is not set
+CONFIG_8xx=y
+
+#
+# IBM 4xx options
+#
+CONFIG_EMBEDDEDBOOT=y
+CONFIG_SERIAL_CONSOLE=y
+CONFIG_NOT_COHERENT_CACHE=y
+# CONFIG_RPXLITE is not set
+# CONFIG_RPXCLASSIC is not set
+# CONFIG_BSEIP is not set
+# CONFIG_FADS is not set
+# CONFIG_TQM823L is not set
+# CONFIG_TQM850L is not set
+# CONFIG_TQM855L is not set
+# CONFIG_TQM860L is not set
+# CONFIG_FPS850L is not set
+CONFIG_SPD823TS=y
+# CONFIG_IVMS8 is not set
+# CONFIG_IVML24 is not set
+# CONFIG_SM850 is not set
+# CONFIG_HERMES_PRO is not set
+# CONFIG_IP860 is not set
+# CONFIG_LWMON is not set
+# CONFIG_PCU_E is not set
+# CONFIG_CCM is not set
+# CONFIG_LANTEC is not set
+# CONFIG_MBX is not set
+# CONFIG_WINCEPT is not set
+# CONFIG_SMP is not set
+# CONFIG_PREEMPT is not set
+CONFIG_MATH_EMULATION=y
+# CONFIG_CPU_FREQ is not set
+
+#
+# General setup
+#
+# CONFIG_HIGHMEM is not set
+# CONFIG_PCI is not set
+# CONFIG_PCI_DOMAINS is not set
+# CONFIG_PCI_QSPAN is not set
+CONFIG_KCORE_ELF=y
+CONFIG_BINFMT_ELF=y
+CONFIG_KERNEL_ELF=y
+# CONFIG_BINFMT_MISC is not set
+# CONFIG_HOTPLUG is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+# CONFIG_CMDLINE_BOOL is not set
+
+#
+# Advanced setup
+#
+# CONFIG_ADVANCED_OPTIONS is not set
+
+#
+# Default settings for advanced configuration options are used
+#
+CONFIG_HIGHMEM_START=0xfe000000
+CONFIG_LOWMEM_SIZE=0x30000000
+CONFIG_KERNEL_START=0xc0000000
+CONFIG_TASK_SIZE=0x80000000
+CONFIG_BOOT_LOAD=0x00400000
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Plug and Play support
+#
+# CONFIG_PNP is not set
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_RAM is not set
+# CONFIG_BLK_DEV_INITRD is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# ATA/IDE/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI support
+#
+# CONFIG_SCSI is not set
+
+#
+# Fusion MPT device support
+#
+
+#
+# I2O device support
+#
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+# CONFIG_NETLINK_DEV is not set
+# CONFIG_NETFILTER is not set
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+# CONFIG_IP_PNP_BOOTP is not set
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+# CONFIG_INET_ECN is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_IPV6 is not set
+# CONFIG_XFRM_USER is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+CONFIG_IPV6_SCTP__=y
+# CONFIG_IP_SCTP is not set
+# CONFIG_ATM is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_LLC is not set
+# CONFIG_DECNET is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_HW_FLOWCONTROL is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_ETHERTAP is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+# CONFIG_MII is not set
+# CONFIG_OAKNET is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Token Ring devices (depends on LLC=y)
+#
+# CONFIG_SHAPER is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+
+#
+# Amateur Radio support
+#
+# CONFIG_HAMRADIO is not set
+
+#
+# IrDA (infrared) support
+#
+# CONFIG_IRDA is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN_BOOL is not set
+
+#
+# Graphics support
+#
+# CONFIG_FB is not set
+
+#
+# Old CD-ROM drivers (not SCSI, not IDE)
+#
+# CONFIG_CD_NO_IDESCSI is not set
+
+#
+# Input device support
+#
+# CONFIG_INPUT is not set
+
+#
+# Userland interfaces
+#
+
+#
+# Input I/O drivers
+#
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+# CONFIG_SERIO is not set
+
+#
+# Input Device Drivers
+#
+
+#
+# Macintosh device drivers
+#
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_SERIAL_CPM=y
+CONFIG_SERIAL_CPM_CONSOLE=y
+# CONFIG_SERIAL_CPM_SCC1 is not set
+# CONFIG_SERIAL_CPM_SCC2 is not set
+# CONFIG_SERIAL_CPM_SCC3 is not set
+# CONFIG_SERIAL_CPM_SCC4 is not set
+CONFIG_SERIAL_CPM_SMC1=y
+# CONFIG_SERIAL_CPM_SMC2 is not set
+CONFIG_SERIAL_CPM_ALT_SMC2=y
+CONFIG_UNIX98_PTYS=y
+# CONFIG_LEGACY_PTYS is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# I2C Hardware Sensors Mainboard support
+#
+
+#
+# I2C Hardware Sensors Chip support
+#
+# CONFIG_I2C_SENSOR is not set
+
+#
+# Mice
+#
+# CONFIG_BUSMOUSE is not set
+# CONFIG_QIC02_TAPE is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_NVRAM is not set
+CONFIG_GEN_RTC=y
+# CONFIG_GEN_RTC_X is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_FTAPE is not set
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_HANGCHECK_TIMER is not set
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# File systems
+#
+# CONFIG_EXT2_FS is not set
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_FS_XATTR=y
+# CONFIG_EXT3_FS_POSIX_ACL is not set
+# CONFIG_EXT3_FS_SECURITY is not set
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+CONFIG_FS_MBCACHE=y
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_FAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+# CONFIG_DEVFS_FS is not set
+CONFIG_DEVPTS_FS=y
+# CONFIG_DEVPTS_FS_XATTR is not set
+CONFIG_TMPFS=y
+CONFIG_RAMFS=y
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+# CONFIG_NFS_V3 is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFSD is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+# CONFIG_EXPORTFS is not set
+CONFIG_SUNRPC=y
+# CONFIG_SUNRPC_GSS is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_INTERMEZZO_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
+# CONFIG_MSDOS_PARTITION is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_NEC98_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_EFI_PARTITION is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# MPC8xx CPM Options
+#
+CONFIG_SCC_ENET=y
+# CONFIG_SCC1_ENET is not set
+CONFIG_SCC2_ENET=y
+# CONFIG_SCC3_ENET is not set
+# CONFIG_FEC_ENET is not set
+CONFIG_ENET_BIG_BUFFERS=y
+
+#
+# Generic MPC8xx Options
+#
+CONFIG_8xx_COPYBACK=y
+# CONFIG_8xx_CPU6 is not set
+# CONFIG_UCODE_PATCH is not set
+
+#
+# USB support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# Bluetooth support
+#
+# CONFIG_BT is not set
+
+#
+# Library routines
+#
+# CONFIG_CRC32 is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_DEBUG_KERNEL is not set
+# CONFIG_KALLSYMS is not set
+
+#
+# Security options
+#
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
diff --git a/arch/ppc/configs/TQM823L_defconfig b/arch/ppc/configs/TQM823L_defconfig
new file mode 100644
index 0000000..3b44f3d
--- /dev/null
+++ b/arch/ppc/configs/TQM823L_defconfig
@@ -0,0 +1,521 @@
+#
+# Automatically generated make config: don't edit
+#
+CONFIG_MMU=y
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_HAVE_DEC_LOCK=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+
+#
+# General setup
+#
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_EMBEDDED=y
+CONFIG_FUTEX=y
+# CONFIG_EPOLL is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_OBSOLETE_MODPARM=y
+# CONFIG_MODVERSIONS is not set
+CONFIG_KMOD=y
+
+#
+# Platform support
+#
+CONFIG_PPC=y
+CONFIG_PPC32=y
+# CONFIG_6xx is not set
+# CONFIG_40x is not set
+# CONFIG_POWER3 is not set
+CONFIG_8xx=y
+
+#
+# IBM 4xx options
+#
+CONFIG_EMBEDDEDBOOT=y
+CONFIG_SERIAL_CONSOLE=y
+CONFIG_NOT_COHERENT_CACHE=y
+# CONFIG_RPXLITE is not set
+# CONFIG_RPXCLASSIC is not set
+# CONFIG_BSEIP is not set
+# CONFIG_FADS is not set
+CONFIG_TQM823L=y
+# CONFIG_TQM850L is not set
+# CONFIG_TQM855L is not set
+# CONFIG_TQM860L is not set
+# CONFIG_FPS850L is not set
+# CONFIG_SPD823TS is not set
+# CONFIG_IVMS8 is not set
+# CONFIG_IVML24 is not set
+# CONFIG_SM850 is not set
+# CONFIG_HERMES_PRO is not set
+# CONFIG_IP860 is not set
+# CONFIG_LWMON is not set
+# CONFIG_PCU_E is not set
+# CONFIG_CCM is not set
+# CONFIG_LANTEC is not set
+# CONFIG_MBX is not set
+# CONFIG_WINCEPT is not set
+CONFIG_TQM8xxL=y
+# CONFIG_SMP is not set
+# CONFIG_PREEMPT is not set
+CONFIG_MATH_EMULATION=y
+# CONFIG_CPU_FREQ is not set
+
+#
+# General setup
+#
+# CONFIG_HIGHMEM is not set
+# CONFIG_PCI is not set
+# CONFIG_PCI_DOMAINS is not set
+# CONFIG_PCI_QSPAN is not set
+CONFIG_KCORE_ELF=y
+CONFIG_BINFMT_ELF=y
+CONFIG_KERNEL_ELF=y
+# CONFIG_BINFMT_MISC is not set
+# CONFIG_HOTPLUG is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+# CONFIG_CMDLINE_BOOL is not set
+
+#
+# Advanced setup
+#
+# CONFIG_ADVANCED_OPTIONS is not set
+
+#
+# Default settings for advanced configuration options are used
+#
+CONFIG_HIGHMEM_START=0xfe000000
+CONFIG_LOWMEM_SIZE=0x30000000
+CONFIG_KERNEL_START=0xc0000000
+CONFIG_TASK_SIZE=0x80000000
+CONFIG_BOOT_LOAD=0x00400000
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Plug and Play support
+#
+# CONFIG_PNP is not set
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_RAM is not set
+# CONFIG_BLK_DEV_INITRD is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# ATA/IDE/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI support
+#
+# CONFIG_SCSI is not set
+
+#
+# Fusion MPT device support
+#
+
+#
+# I2O device support
+#
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+# CONFIG_NETLINK_DEV is not set
+# CONFIG_NETFILTER is not set
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+# CONFIG_IP_PNP_BOOTP is not set
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+# CONFIG_INET_ECN is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_IPV6 is not set
+# CONFIG_XFRM_USER is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+CONFIG_IPV6_SCTP__=y
+# CONFIG_IP_SCTP is not set
+# CONFIG_ATM is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_LLC is not set
+# CONFIG_DECNET is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_HW_FLOWCONTROL is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_ETHERTAP is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+# CONFIG_MII is not set
+# CONFIG_OAKNET is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Token Ring devices (depends on LLC=y)
+#
+# CONFIG_SHAPER is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+
+#
+# Amateur Radio support
+#
+# CONFIG_HAMRADIO is not set
+
+#
+# IrDA (infrared) support
+#
+# CONFIG_IRDA is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN_BOOL is not set
+
+#
+# Graphics support
+#
+# CONFIG_FB is not set
+
+#
+# Old CD-ROM drivers (not SCSI, not IDE)
+#
+# CONFIG_CD_NO_IDESCSI is not set
+
+#
+# Input device support
+#
+# CONFIG_INPUT is not set
+
+#
+# Userland interfaces
+#
+
+#
+# Input I/O drivers
+#
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+# CONFIG_SERIO is not set
+
+#
+# Input Device Drivers
+#
+
+#
+# Macintosh device drivers
+#
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_SERIAL_CPM=y
+CONFIG_SERIAL_CPM_CONSOLE=y
+# CONFIG_SERIAL_CPM_SCC1 is not set
+# CONFIG_SERIAL_CPM_SCC2 is not set
+# CONFIG_SERIAL_CPM_SCC3 is not set
+# CONFIG_SERIAL_CPM_SCC4 is not set
+CONFIG_SERIAL_CPM_SMC1=y
+CONFIG_SERIAL_CPM_SMC2=y
+CONFIG_SERIAL_CPM_ALT_SMC2=y
+CONFIG_UNIX98_PTYS=y
+# CONFIG_LEGACY_PTYS is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# I2C Hardware Sensors Mainboard support
+#
+
+#
+# I2C Hardware Sensors Chip support
+#
+# CONFIG_I2C_SENSOR is not set
+
+#
+# Mice
+#
+# CONFIG_BUSMOUSE is not set
+# CONFIG_QIC02_TAPE is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_NVRAM is not set
+CONFIG_GEN_RTC=y
+# CONFIG_GEN_RTC_X is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_FTAPE is not set
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_HANGCHECK_TIMER is not set
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# File systems
+#
+# CONFIG_EXT2_FS is not set
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_FS_XATTR=y
+# CONFIG_EXT3_FS_POSIX_ACL is not set
+# CONFIG_EXT3_FS_SECURITY is not set
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+CONFIG_FS_MBCACHE=y
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_FAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+# CONFIG_DEVFS_FS is not set
+CONFIG_DEVPTS_FS=y
+# CONFIG_DEVPTS_FS_XATTR is not set
+CONFIG_TMPFS=y
+CONFIG_RAMFS=y
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+# CONFIG_NFS_V3 is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFSD is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+# CONFIG_EXPORTFS is not set
+CONFIG_SUNRPC=y
+# CONFIG_SUNRPC_GSS is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_INTERMEZZO_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
+# CONFIG_MSDOS_PARTITION is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_NEC98_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_EFI_PARTITION is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# MPC8xx CPM Options
+#
+CONFIG_SCC_ENET=y
+# CONFIG_SCC1_ENET is not set
+CONFIG_SCC2_ENET=y
+# CONFIG_SCC3_ENET is not set
+# CONFIG_FEC_ENET is not set
+CONFIG_ENET_BIG_BUFFERS=y
+
+#
+# Generic MPC8xx Options
+#
+CONFIG_8xx_COPYBACK=y
+# CONFIG_8xx_CPU6 is not set
+# CONFIG_UCODE_PATCH is not set
+
+#
+# USB support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# Bluetooth support
+#
+# CONFIG_BT is not set
+
+#
+# Library routines
+#
+# CONFIG_CRC32 is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_DEBUG_KERNEL is not set
+# CONFIG_KALLSYMS is not set
+
+#
+# Security options
+#
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
diff --git a/arch/ppc/configs/TQM8260_defconfig b/arch/ppc/configs/TQM8260_defconfig
new file mode 100644
index 0000000..57cfa83
--- /dev/null
+++ b/arch/ppc/configs/TQM8260_defconfig
@@ -0,0 +1,499 @@
+#
+# Automatically generated make config: don't edit
+#
+CONFIG_MMU=y
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_HAVE_DEC_LOCK=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+
+#
+# General setup
+#
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_EMBEDDED=y
+CONFIG_FUTEX=y
+# CONFIG_EPOLL is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_OBSOLETE_MODPARM=y
+# CONFIG_MODVERSIONS is not set
+CONFIG_KMOD=y
+
+#
+# Platform support
+#
+CONFIG_PPC=y
+CONFIG_PPC32=y
+CONFIG_6xx=y
+# CONFIG_40x is not set
+# CONFIG_POWER3 is not set
+# CONFIG_8xx is not set
+
+#
+# IBM 4xx options
+#
+CONFIG_EMBEDDEDBOOT=y
+CONFIG_8260=y
+CONFIG_PPC_STD_MMU=y
+CONFIG_SERIAL_CONSOLE=y
+# CONFIG_EST8260 is not set
+# CONFIG_SBS8260 is not set
+# CONFIG_RPX6 is not set
+CONFIG_TQM8260=y
+# CONFIG_WILLOW_1 is not set
+# CONFIG_SMP is not set
+# CONFIG_PREEMPT is not set
+# CONFIG_CPU_FREQ is not set
+
+#
+# General setup
+#
+# CONFIG_HIGHMEM is not set
+# CONFIG_PCI is not set
+# CONFIG_PCI_DOMAINS is not set
+# CONFIG_PC_KEYBOARD is not set
+CONFIG_KCORE_ELF=y
+CONFIG_BINFMT_ELF=y
+CONFIG_KERNEL_ELF=y
+# CONFIG_BINFMT_MISC is not set
+# CONFIG_HOTPLUG is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+# CONFIG_PPC601_SYNC_FIX is not set
+# CONFIG_CMDLINE_BOOL is not set
+
+#
+# Advanced setup
+#
+# CONFIG_ADVANCED_OPTIONS is not set
+
+#
+# Default settings for advanced configuration options are used
+#
+CONFIG_HIGHMEM_START=0xfe000000
+CONFIG_LOWMEM_SIZE=0x30000000
+CONFIG_KERNEL_START=0xc0000000
+CONFIG_TASK_SIZE=0x80000000
+CONFIG_BOOT_LOAD=0x00400000
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Plug and Play support
+#
+# CONFIG_PNP is not set
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=4096
+CONFIG_BLK_DEV_INITRD=y
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# ATA/IDE/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI support
+#
+# CONFIG_SCSI is not set
+
+#
+# Fusion MPT device support
+#
+
+#
+# I2O device support
+#
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+# CONFIG_NETLINK_DEV is not set
+# CONFIG_NETFILTER is not set
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+# CONFIG_IP_PNP_BOOTP is not set
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+# CONFIG_INET_ECN is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_IPV6 is not set
+# CONFIG_XFRM_USER is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+CONFIG_IPV6_SCTP__=y
+# CONFIG_IP_SCTP is not set
+# CONFIG_ATM is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_LLC is not set
+# CONFIG_DECNET is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_HW_FLOWCONTROL is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_ETHERTAP is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+# CONFIG_MII is not set
+# CONFIG_OAKNET is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Token Ring devices (depends on LLC=y)
+#
+# CONFIG_SHAPER is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+
+#
+# Amateur Radio support
+#
+# CONFIG_HAMRADIO is not set
+
+#
+# IrDA (infrared) support
+#
+# CONFIG_IRDA is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN_BOOL is not set
+
+#
+# Graphics support
+#
+# CONFIG_FB is not set
+
+#
+# Old CD-ROM drivers (not SCSI, not IDE)
+#
+# CONFIG_CD_NO_IDESCSI is not set
+
+#
+# Input device support
+#
+# CONFIG_INPUT is not set
+
+#
+# Userland interfaces
+#
+
+#
+# Input I/O drivers
+#
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+# CONFIG_SERIO is not set
+
+#
+# Input Device Drivers
+#
+
+#
+# Macintosh device drivers
+#
+
+#
+# Character devices
+#
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_UNIX98_PTY_COUNT=32
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# I2C Hardware Sensors Mainboard support
+#
+
+#
+# I2C Hardware Sensors Chip support
+#
+# CONFIG_I2C_SENSOR is not set
+
+#
+# Mice
+#
+# CONFIG_BUSMOUSE is not set
+# CONFIG_QIC02_TAPE is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_NVRAM is not set
+CONFIG_GEN_RTC=y
+# CONFIG_GEN_RTC_X is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_FTAPE is not set
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_HANGCHECK_TIMER is not set
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_FS_XATTR=y
+# CONFIG_EXT3_FS_POSIX_ACL is not set
+# CONFIG_EXT3_FS_SECURITY is not set
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+CONFIG_FS_MBCACHE=y
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_FAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+# CONFIG_DEVFS_FS is not set
+CONFIG_DEVPTS_FS=y
+# CONFIG_DEVPTS_FS_XATTR is not set
+# CONFIG_TMPFS is not set
+CONFIG_RAMFS=y
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+# CONFIG_NFS_V3 is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFSD is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+# CONFIG_EXPORTFS is not set
+CONFIG_SUNRPC=y
+# CONFIG_SUNRPC_GSS is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_INTERMEZZO_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
+# CONFIG_MSDOS_PARTITION is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_NEC98_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_EFI_PARTITION is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+# CONFIG_SCC_ENET is not set
+CONFIG_FEC_ENET=y
+# CONFIG_USE_MDIO is not set
+
+#
+# MPC8260 CPM Options
+#
+CONFIG_SCC_CONSOLE=y
+# CONFIG_FCC1_ENET is not set
+CONFIG_FCC2_ENET=y
+# CONFIG_FCC3_ENET is not set
+
+#
+# USB support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# Bluetooth support
+#
+# CONFIG_BT is not set
+
+#
+# Library routines
+#
+# CONFIG_CRC32 is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_DEBUG_KERNEL is not set
+# CONFIG_KALLSYMS is not set
+
+#
+# Security options
+#
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
diff --git a/arch/ppc/configs/TQM850L_defconfig b/arch/ppc/configs/TQM850L_defconfig
new file mode 100644
index 0000000..b02d196
--- /dev/null
+++ b/arch/ppc/configs/TQM850L_defconfig
@@ -0,0 +1,521 @@
+#
+# Automatically generated make config: don't edit
+#
+CONFIG_MMU=y
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_HAVE_DEC_LOCK=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+
+#
+# General setup
+#
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_EMBEDDED=y
+CONFIG_FUTEX=y
+# CONFIG_EPOLL is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_OBSOLETE_MODPARM=y
+# CONFIG_MODVERSIONS is not set
+CONFIG_KMOD=y
+
+#
+# Platform support
+#
+CONFIG_PPC=y
+CONFIG_PPC32=y
+# CONFIG_6xx is not set
+# CONFIG_40x is not set
+# CONFIG_POWER3 is not set
+CONFIG_8xx=y
+
+#
+# IBM 4xx options
+#
+CONFIG_EMBEDDEDBOOT=y
+CONFIG_SERIAL_CONSOLE=y
+CONFIG_NOT_COHERENT_CACHE=y
+# CONFIG_RPXLITE is not set
+# CONFIG_RPXCLASSIC is not set
+# CONFIG_BSEIP is not set
+# CONFIG_FADS is not set
+# CONFIG_TQM823L is not set
+CONFIG_TQM850L=y
+# CONFIG_TQM855L is not set
+# CONFIG_TQM860L is not set
+# CONFIG_FPS850L is not set
+# CONFIG_SPD823TS is not set
+# CONFIG_IVMS8 is not set
+# CONFIG_IVML24 is not set
+# CONFIG_SM850 is not set
+# CONFIG_HERMES_PRO is not set
+# CONFIG_IP860 is not set
+# CONFIG_LWMON is not set
+# CONFIG_PCU_E is not set
+# CONFIG_CCM is not set
+# CONFIG_LANTEC is not set
+# CONFIG_MBX is not set
+# CONFIG_WINCEPT is not set
+CONFIG_TQM8xxL=y
+# CONFIG_SMP is not set
+# CONFIG_PREEMPT is not set
+CONFIG_MATH_EMULATION=y
+# CONFIG_CPU_FREQ is not set
+
+#
+# General setup
+#
+# CONFIG_HIGHMEM is not set
+# CONFIG_PCI is not set
+# CONFIG_PCI_DOMAINS is not set
+# CONFIG_PCI_QSPAN is not set
+CONFIG_KCORE_ELF=y
+CONFIG_BINFMT_ELF=y
+CONFIG_KERNEL_ELF=y
+# CONFIG_BINFMT_MISC is not set
+# CONFIG_HOTPLUG is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+# CONFIG_CMDLINE_BOOL is not set
+
+#
+# Advanced setup
+#
+# CONFIG_ADVANCED_OPTIONS is not set
+
+#
+# Default settings for advanced configuration options are used
+#
+CONFIG_HIGHMEM_START=0xfe000000
+CONFIG_LOWMEM_SIZE=0x30000000
+CONFIG_KERNEL_START=0xc0000000
+CONFIG_TASK_SIZE=0x80000000
+CONFIG_BOOT_LOAD=0x00400000
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Plug and Play support
+#
+# CONFIG_PNP is not set
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_RAM is not set
+# CONFIG_BLK_DEV_INITRD is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# ATA/IDE/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI support
+#
+# CONFIG_SCSI is not set
+
+#
+# Fusion MPT device support
+#
+
+#
+# I2O device support
+#
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+# CONFIG_NETLINK_DEV is not set
+# CONFIG_NETFILTER is not set
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+# CONFIG_IP_PNP_BOOTP is not set
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+# CONFIG_INET_ECN is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_IPV6 is not set
+# CONFIG_XFRM_USER is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+CONFIG_IPV6_SCTP__=y
+# CONFIG_IP_SCTP is not set
+# CONFIG_ATM is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_LLC is not set
+# CONFIG_DECNET is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_HW_FLOWCONTROL is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_ETHERTAP is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+# CONFIG_MII is not set
+# CONFIG_OAKNET is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Token Ring devices (depends on LLC=y)
+#
+# CONFIG_SHAPER is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+
+#
+# Amateur Radio support
+#
+# CONFIG_HAMRADIO is not set
+
+#
+# IrDA (infrared) support
+#
+# CONFIG_IRDA is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN_BOOL is not set
+
+#
+# Graphics support
+#
+# CONFIG_FB is not set
+
+#
+# Old CD-ROM drivers (not SCSI, not IDE)
+#
+# CONFIG_CD_NO_IDESCSI is not set
+
+#
+# Input device support
+#
+# CONFIG_INPUT is not set
+
+#
+# Userland interfaces
+#
+
+#
+# Input I/O drivers
+#
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+# CONFIG_SERIO is not set
+
+#
+# Input Device Drivers
+#
+
+#
+# Macintosh device drivers
+#
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_SERIAL_CPM=y
+CONFIG_SERIAL_CPM_CONSOLE=y
+# CONFIG_SERIAL_CPM_SCC1 is not set
+# CONFIG_SERIAL_CPM_SCC2 is not set
+# CONFIG_SERIAL_CPM_SCC3 is not set
+# CONFIG_SERIAL_CPM_SCC4 is not set
+CONFIG_SERIAL_CPM_SMC1=y
+CONFIG_SERIAL_CPM_SMC2=y
+CONFIG_SERIAL_CPM_ALT_SMC2=y
+CONFIG_UNIX98_PTYS=y
+# CONFIG_LEGACY_PTYS is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# I2C Hardware Sensors Mainboard support
+#
+
+#
+# I2C Hardware Sensors Chip support
+#
+# CONFIG_I2C_SENSOR is not set
+
+#
+# Mice
+#
+# CONFIG_BUSMOUSE is not set
+# CONFIG_QIC02_TAPE is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_NVRAM is not set
+CONFIG_GEN_RTC=y
+# CONFIG_GEN_RTC_X is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_FTAPE is not set
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_HANGCHECK_TIMER is not set
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# File systems
+#
+# CONFIG_EXT2_FS is not set
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_FS_XATTR=y
+# CONFIG_EXT3_FS_POSIX_ACL is not set
+# CONFIG_EXT3_FS_SECURITY is not set
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+CONFIG_FS_MBCACHE=y
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_FAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+# CONFIG_DEVFS_FS is not set
+CONFIG_DEVPTS_FS=y
+# CONFIG_DEVPTS_FS_XATTR is not set
+CONFIG_TMPFS=y
+CONFIG_RAMFS=y
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+# CONFIG_NFS_V3 is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFSD is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+# CONFIG_EXPORTFS is not set
+CONFIG_SUNRPC=y
+# CONFIG_SUNRPC_GSS is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_INTERMEZZO_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
+# CONFIG_MSDOS_PARTITION is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_NEC98_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_EFI_PARTITION is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# MPC8xx CPM Options
+#
+CONFIG_SCC_ENET=y
+# CONFIG_SCC1_ENET is not set
+CONFIG_SCC2_ENET=y
+# CONFIG_SCC3_ENET is not set
+# CONFIG_FEC_ENET is not set
+CONFIG_ENET_BIG_BUFFERS=y
+
+#
+# Generic MPC8xx Options
+#
+CONFIG_8xx_COPYBACK=y
+CONFIG_8xx_CPU6=y
+# CONFIG_UCODE_PATCH is not set
+
+#
+# USB support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# Bluetooth support
+#
+# CONFIG_BT is not set
+
+#
+# Library routines
+#
+# CONFIG_CRC32 is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_DEBUG_KERNEL is not set
+# CONFIG_KALLSYMS is not set
+
+#
+# Security options
+#
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
diff --git a/arch/ppc/configs/TQM860L_defconfig b/arch/ppc/configs/TQM860L_defconfig
new file mode 100644
index 0000000..857e4ab
--- /dev/null
+++ b/arch/ppc/configs/TQM860L_defconfig
@@ -0,0 +1,549 @@
+#
+# Automatically generated make config: don't edit
+#
+CONFIG_MMU=y
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_HAVE_DEC_LOCK=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+
+#
+# General setup
+#
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_EMBEDDED=y
+CONFIG_FUTEX=y
+# CONFIG_EPOLL is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_OBSOLETE_MODPARM=y
+# CONFIG_MODVERSIONS is not set
+CONFIG_KMOD=y
+
+#
+# Platform support
+#
+CONFIG_PPC=y
+CONFIG_PPC32=y
+# CONFIG_6xx is not set
+# CONFIG_40x is not set
+# CONFIG_POWER3 is not set
+CONFIG_8xx=y
+
+#
+# IBM 4xx options
+#
+CONFIG_EMBEDDEDBOOT=y
+CONFIG_SERIAL_CONSOLE=y
+CONFIG_NOT_COHERENT_CACHE=y
+# CONFIG_RPXLITE is not set
+# CONFIG_RPXCLASSIC is not set
+# CONFIG_BSEIP is not set
+# CONFIG_FADS is not set
+# CONFIG_TQM823L is not set
+# CONFIG_TQM850L is not set
+# CONFIG_TQM855L is not set
+CONFIG_TQM860L=y
+# CONFIG_FPS850L is not set
+# CONFIG_SPD823TS is not set
+# CONFIG_IVMS8 is not set
+# CONFIG_IVML24 is not set
+# CONFIG_SM850 is not set
+# CONFIG_HERMES_PRO is not set
+# CONFIG_IP860 is not set
+# CONFIG_LWMON is not set
+# CONFIG_PCU_E is not set
+# CONFIG_CCM is not set
+# CONFIG_LANTEC is not set
+# CONFIG_MBX is not set
+# CONFIG_WINCEPT is not set
+CONFIG_TQM8xxL=y
+# CONFIG_SMP is not set
+# CONFIG_PREEMPT is not set
+CONFIG_MATH_EMULATION=y
+# CONFIG_CPU_FREQ is not set
+
+#
+# General setup
+#
+# CONFIG_HIGHMEM is not set
+# CONFIG_PCI is not set
+# CONFIG_PCI_DOMAINS is not set
+# CONFIG_PCI_QSPAN is not set
+CONFIG_KCORE_ELF=y
+CONFIG_BINFMT_ELF=y
+CONFIG_KERNEL_ELF=y
+# CONFIG_BINFMT_MISC is not set
+# CONFIG_HOTPLUG is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+# CONFIG_CMDLINE_BOOL is not set
+
+#
+# Advanced setup
+#
+# CONFIG_ADVANCED_OPTIONS is not set
+
+#
+# Default settings for advanced configuration options are used
+#
+CONFIG_HIGHMEM_START=0xfe000000
+CONFIG_LOWMEM_SIZE=0x30000000
+CONFIG_KERNEL_START=0xc0000000
+CONFIG_TASK_SIZE=0x80000000
+CONFIG_BOOT_LOAD=0x00400000
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Plug and Play support
+#
+# CONFIG_PNP is not set
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_RAM is not set
+# CONFIG_BLK_DEV_INITRD is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# ATA/IDE/MFM/RLL support
+#
+CONFIG_IDE=y
+
+#
+# IDE, ATA and ATAPI Block devices
+#
+CONFIG_BLK_DEV_IDE=y
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+# CONFIG_BLK_DEV_HD is not set
+CONFIG_BLK_DEV_IDEDISK=y
+# CONFIG_IDEDISK_MULTI_MODE is not set
+# CONFIG_IDEDISK_STROKE is not set
+# CONFIG_BLK_DEV_IDECD is not set
+# CONFIG_BLK_DEV_IDEFLOPPY is not set
+# CONFIG_IDE_TASK_IOCTL is not set
+
+#
+# IDE chipset support/bugfixes
+#
+CONFIG_BLK_DEV_MPC8xx_IDE=y
+CONFIG_IDE_8xx_PCCARD=y
+# CONFIG_IDE_8xx_DIRECT is not set
+# CONFIG_IDE_EXT_DIRECT is not set
+
+#
+# SCSI support
+#
+# CONFIG_SCSI is not set
+
+#
+# Fusion MPT device support
+#
+
+#
+# I2O device support
+#
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+# CONFIG_NETLINK_DEV is not set
+# CONFIG_NETFILTER is not set
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+# CONFIG_IP_PNP_BOOTP is not set
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+# CONFIG_INET_ECN is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_IPV6 is not set
+# CONFIG_XFRM_USER is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+CONFIG_IPV6_SCTP__=y
+# CONFIG_IP_SCTP is not set
+# CONFIG_ATM is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_LLC is not set
+# CONFIG_DECNET is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_HW_FLOWCONTROL is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_ETHERTAP is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+# CONFIG_MII is not set
+# CONFIG_OAKNET is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Token Ring devices (depends on LLC=y)
+#
+# CONFIG_SHAPER is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+
+#
+# Amateur Radio support
+#
+# CONFIG_HAMRADIO is not set
+
+#
+# IrDA (infrared) support
+#
+# CONFIG_IRDA is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN_BOOL is not set
+
+#
+# Graphics support
+#
+# CONFIG_FB is not set
+
+#
+# Old CD-ROM drivers (not SCSI, not IDE)
+#
+# CONFIG_CD_NO_IDESCSI is not set
+
+#
+# Input device support
+#
+# CONFIG_INPUT is not set
+
+#
+# Userland interfaces
+#
+
+#
+# Input I/O drivers
+#
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+# CONFIG_SERIO is not set
+
+#
+# Input Device Drivers
+#
+
+#
+# Macintosh device drivers
+#
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_SERIAL_CPM=y
+CONFIG_SERIAL_CPM_CONSOLE=y
+# CONFIG_SERIAL_CPM_SCC1 is not set
+# CONFIG_SERIAL_CPM_SCC2 is not set
+# CONFIG_SERIAL_CPM_SCC3 is not set
+# CONFIG_SERIAL_CPM_SCC4 is not set
+CONFIG_SERIAL_CPM_SMC1=y
+CONFIG_SERIAL_CPM_SMC2=y
+CONFIG_UNIX98_PTYS=y
+# CONFIG_LEGACY_PTYS is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# I2C Hardware Sensors Mainboard support
+#
+
+#
+# I2C Hardware Sensors Chip support
+#
+# CONFIG_I2C_SENSOR is not set
+
+#
+# Mice
+#
+# CONFIG_BUSMOUSE is not set
+# CONFIG_QIC02_TAPE is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_NVRAM is not set
+CONFIG_GEN_RTC=y
+# CONFIG_GEN_RTC_X is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_FTAPE is not set
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_HANGCHECK_TIMER is not set
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_FS_XATTR=y
+# CONFIG_EXT3_FS_POSIX_ACL is not set
+# CONFIG_EXT3_FS_SECURITY is not set
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+CONFIG_FS_MBCACHE=y
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_FAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+# CONFIG_DEVFS_FS is not set
+CONFIG_DEVPTS_FS=y
+# CONFIG_DEVPTS_FS_XATTR is not set
+CONFIG_TMPFS=y
+CONFIG_RAMFS=y
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+# CONFIG_NFS_V3 is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFSD is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+# CONFIG_EXPORTFS is not set
+CONFIG_SUNRPC=y
+# CONFIG_SUNRPC_GSS is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_INTERMEZZO_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+CONFIG_MAC_PARTITION=y
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_BSD_DISKLABEL is not set
+# CONFIG_MINIX_SUBPARTITION is not set
+# CONFIG_SOLARIS_X86_PARTITION is not set
+# CONFIG_UNIXWARE_DISKLABEL is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_NEC98_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_EFI_PARTITION is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# MPC8xx CPM Options
+#
+CONFIG_SCC_ENET=y
+CONFIG_SCC1_ENET=y
+# CONFIG_SCC2_ENET is not set
+# CONFIG_SCC3_ENET is not set
+# CONFIG_FEC_ENET is not set
+CONFIG_ENET_BIG_BUFFERS=y
+
+#
+# Generic MPC8xx Options
+#
+CONFIG_8xx_COPYBACK=y
+# CONFIG_8xx_CPU6 is not set
+# CONFIG_UCODE_PATCH is not set
+
+#
+# USB support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# Bluetooth support
+#
+# CONFIG_BT is not set
+
+#
+# Library routines
+#
+# CONFIG_CRC32 is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_DEBUG_KERNEL is not set
+# CONFIG_KALLSYMS is not set
+
+#
+# Security options
+#
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
diff --git a/arch/ppc/configs/adir_defconfig b/arch/ppc/configs/adir_defconfig
new file mode 100644
index 0000000..f20e653
--- /dev/null
+++ b/arch/ppc/configs/adir_defconfig
@@ -0,0 +1,805 @@
+#
+# Automatically generated make config: don't edit
+#
+CONFIG_MMU=y
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_HAVE_DEC_LOCK=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+
+#
+# General setup
+#
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_EMBEDDED is not set
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_OBSOLETE_MODPARM=y
+# CONFIG_MODVERSIONS is not set
+CONFIG_KMOD=y
+
+#
+# Platform support
+#
+CONFIG_PPC=y
+CONFIG_PPC32=y
+CONFIG_6xx=y
+# CONFIG_40x is not set
+# CONFIG_POWER3 is not set
+# CONFIG_8xx is not set
+
+#
+# IBM 4xx options
+#
+# CONFIG_8260 is not set
+CONFIG_GENERIC_ISA_DMA=y
+CONFIG_PPC_STD_MMU=y
+# CONFIG_PPC_MULTIPLATFORM is not set
+# CONFIG_APUS is not set
+# CONFIG_WILLOW_2 is not set
+# CONFIG_PCORE is not set
+# CONFIG_POWERPMC250 is not set
+# CONFIG_EV64260 is not set
+# CONFIG_SPRUCE is not set
+# CONFIG_LOPEC is not set
+# CONFIG_MCPN765 is not set
+# CONFIG_MVME5100 is not set
+# CONFIG_PPLUS is not set
+# CONFIG_PRPMC750 is not set
+# CONFIG_PRPMC800 is not set
+# CONFIG_SANDPOINT is not set
+CONFIG_ADIR=y
+# CONFIG_K2 is not set
+# CONFIG_PAL4 is not set
+# CONFIG_GEMINI is not set
+# CONFIG_SMP is not set
+# CONFIG_PREEMPT is not set
+# CONFIG_ALTIVEC is not set
+# CONFIG_TAU is not set
+# CONFIG_CPU_FREQ is not set
+
+#
+# General setup
+#
+# CONFIG_HIGHMEM is not set
+CONFIG_PCI=y
+CONFIG_PCI_DOMAINS=y
+CONFIG_KCORE_ELF=y
+CONFIG_BINFMT_ELF=y
+CONFIG_KERNEL_ELF=y
+# CONFIG_BINFMT_MISC is not set
+CONFIG_PCI_LEGACY_PROC=y
+# CONFIG_PCI_NAMES is not set
+# CONFIG_HOTPLUG is not set
+
+#
+# Parallel port support
+#
+CONFIG_PARPORT=y
+CONFIG_PARPORT_PC=y
+CONFIG_PARPORT_PC_CML1=y
+# CONFIG_PARPORT_SERIAL is not set
+CONFIG_PARPORT_PC_FIFO=y
+CONFIG_PARPORT_PC_SUPERIO=y
+# CONFIG_PARPORT_OTHER is not set
+CONFIG_PARPORT_1284=y
+# CONFIG_PPC601_SYNC_FIX is not set
+CONFIG_CMDLINE_BOOL=y
+CONFIG_CMDLINE="ip=on"
+
+#
+# Advanced setup
+#
+# CONFIG_ADVANCED_OPTIONS is not set
+
+#
+# Default settings for advanced configuration options are used
+#
+CONFIG_HIGHMEM_START=0xfe000000
+CONFIG_LOWMEM_SIZE=0x30000000
+CONFIG_KERNEL_START=0xc0000000
+CONFIG_TASK_SIZE=0x80000000
+CONFIG_BOOT_LOAD=0x00800000
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Plug and Play support
+#
+# CONFIG_PNP is not set
+
+#
+# Block devices
+#
+CONFIG_BLK_DEV_FD=y
+# CONFIG_PARIDE is not set
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_NBD is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=4096
+CONFIG_BLK_DEV_INITRD=y
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# ATA/IDE/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI support
+#
+CONFIG_SCSI=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+CONFIG_CHR_DEV_ST=y
+# CONFIG_CHR_DEV_OSST is not set
+CONFIG_BLK_DEV_SR=y
+CONFIG_BLK_DEV_SR_VENDOR=y
+CONFIG_CHR_DEV_SG=y
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+# CONFIG_SCSI_MULTI_LUN is not set
+# CONFIG_SCSI_REPORT_LUNS is not set
+CONFIG_SCSI_CONSTANTS=y
+# CONFIG_SCSI_LOGGING is not set
+
+#
+# SCSI low-level drivers
+#
+# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
+# CONFIG_SCSI_ACARD is not set
+# CONFIG_SCSI_AACRAID is not set
+# CONFIG_SCSI_AIC7XXX is not set
+# CONFIG_SCSI_AIC7XXX_OLD is not set
+# CONFIG_SCSI_AIC79XX is not set
+# CONFIG_SCSI_DPT_I2O is not set
+# CONFIG_SCSI_ADVANSYS is not set
+# CONFIG_SCSI_IN2000 is not set
+# CONFIG_SCSI_AM53C974 is not set
+# CONFIG_SCSI_MEGARAID is not set
+# CONFIG_SCSI_BUSLOGIC is not set
+# CONFIG_SCSI_CPQFCTS is not set
+# CONFIG_SCSI_DMX3191D is not set
+# CONFIG_SCSI_EATA is not set
+# CONFIG_SCSI_EATA_PIO is not set
+# CONFIG_SCSI_FUTURE_DOMAIN is not set
+# CONFIG_SCSI_GDTH is not set
+# CONFIG_SCSI_GENERIC_NCR5380 is not set
+# CONFIG_SCSI_GENERIC_NCR5380_MMIO is not set
+# CONFIG_SCSI_INITIO is not set
+# CONFIG_SCSI_INIA100 is not set
+# CONFIG_SCSI_PPA is not set
+# CONFIG_SCSI_IMM is not set
+# CONFIG_SCSI_NCR53C7xx is not set
+# CONFIG_SCSI_SYM53C8XX_2 is not set
+CONFIG_SCSI_NCR53C8XX=y
+CONFIG_SCSI_SYM53C8XX=y
+CONFIG_SCSI_NCR53C8XX_DEFAULT_TAGS=8
+CONFIG_SCSI_NCR53C8XX_MAX_TAGS=32
+CONFIG_SCSI_NCR53C8XX_SYNC=20
+# CONFIG_SCSI_NCR53C8XX_PROFILE is not set
+# CONFIG_SCSI_NCR53C8XX_IOMAPPED is not set
+# CONFIG_SCSI_NCR53C8XX_PQS_PDS is not set
+# CONFIG_SCSI_NCR53C8XX_SYMBIOS_COMPAT is not set
+# CONFIG_SCSI_PCI2000 is not set
+# CONFIG_SCSI_PCI2220I is not set
+# CONFIG_SCSI_QLOGIC_ISP is not set
+# CONFIG_SCSI_QLOGIC_FC is not set
+# CONFIG_SCSI_QLOGIC_1280 is not set
+# CONFIG_SCSI_DC395x is not set
+# CONFIG_SCSI_DC390T is not set
+# CONFIG_SCSI_U14_34F is not set
+# CONFIG_SCSI_NSP32 is not set
+# CONFIG_SCSI_DEBUG is not set
+
+#
+# Fusion MPT device support
+#
+# CONFIG_FUSION is not set
+
+#
+# IEEE 1394 (FireWire) support (EXPERIMENTAL)
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+# CONFIG_NETLINK_DEV is not set
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+# CONFIG_IP_PNP_BOOTP is not set
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+# CONFIG_INET_ECN is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+
+#
+# IP: Netfilter Configuration
+#
+CONFIG_IP_NF_CONNTRACK=m
+CONFIG_IP_NF_FTP=m
+CONFIG_IP_NF_IRC=m
+CONFIG_IP_NF_TFTP=m
+CONFIG_IP_NF_AMANDA=m
+# CONFIG_IP_NF_QUEUE is not set
+CONFIG_IP_NF_IPTABLES=m
+CONFIG_IP_NF_MATCH_LIMIT=m
+CONFIG_IP_NF_MATCH_MAC=m
+CONFIG_IP_NF_MATCH_PKTTYPE=m
+CONFIG_IP_NF_MATCH_MARK=m
+CONFIG_IP_NF_MATCH_MULTIPORT=m
+CONFIG_IP_NF_MATCH_TOS=m
+CONFIG_IP_NF_MATCH_ECN=m
+CONFIG_IP_NF_MATCH_DSCP=m
+CONFIG_IP_NF_MATCH_AH_ESP=m
+CONFIG_IP_NF_MATCH_LENGTH=m
+CONFIG_IP_NF_MATCH_TTL=m
+CONFIG_IP_NF_MATCH_TCPMSS=m
+CONFIG_IP_NF_MATCH_HELPER=m
+CONFIG_IP_NF_MATCH_STATE=m
+CONFIG_IP_NF_MATCH_CONNTRACK=m
+CONFIG_IP_NF_MATCH_UNCLEAN=m
+CONFIG_IP_NF_MATCH_OWNER=m
+CONFIG_IP_NF_FILTER=m
+CONFIG_IP_NF_TARGET_REJECT=m
+CONFIG_IP_NF_TARGET_MIRROR=m
+CONFIG_IP_NF_NAT=m
+CONFIG_IP_NF_NAT_NEEDED=y
+CONFIG_IP_NF_TARGET_MASQUERADE=m
+CONFIG_IP_NF_TARGET_REDIRECT=m
+CONFIG_IP_NF_NAT_SNMP_BASIC=m
+CONFIG_IP_NF_NAT_IRC=m
+CONFIG_IP_NF_NAT_FTP=m
+CONFIG_IP_NF_NAT_TFTP=m
+CONFIG_IP_NF_NAT_AMANDA=m
+# CONFIG_IP_NF_MANGLE is not set
+# CONFIG_IP_NF_TARGET_LOG is not set
+# CONFIG_IP_NF_TARGET_ULOG is not set
+CONFIG_IP_NF_TARGET_TCPMSS=m
+CONFIG_IP_NF_ARPTABLES=m
+CONFIG_IP_NF_ARPFILTER=m
+CONFIG_IP_NF_COMPAT_IPCHAINS=m
+# CONFIG_IP_NF_COMPAT_IPFWADM is not set
+# CONFIG_IPV6 is not set
+# CONFIG_XFRM_USER is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+CONFIG_IPV6_SCTP__=y
+# CONFIG_IP_SCTP is not set
+# CONFIG_ATM is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_LLC is not set
+# CONFIG_DECNET is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_HW_FLOWCONTROL is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+CONFIG_NETDEVICES=y
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_ETHERTAP is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_OAKNET is not set
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_NET_VENDOR_3COM is not set
+
+#
+# Tulip family network device support
+#
+# CONFIG_NET_TULIP is not set
+# CONFIG_HP100 is not set
+CONFIG_NET_PCI=y
+# CONFIG_PCNET32 is not set
+# CONFIG_AMD8111_ETH is not set
+# CONFIG_ADAPTEC_STARFIRE is not set
+# CONFIG_B44 is not set
+# CONFIG_DGRS is not set
+CONFIG_EEPRO100=y
+# CONFIG_EEPRO100_PIO is not set
+# CONFIG_E100 is not set
+# CONFIG_FEALNX is not set
+# CONFIG_NATSEMI is not set
+# CONFIG_NE2K_PCI is not set
+# CONFIG_8139CP is not set
+# CONFIG_8139TOO is not set
+# CONFIG_SIS900 is not set
+# CONFIG_EPIC100 is not set
+# CONFIG_SUNDANCE is not set
+# CONFIG_TLAN is not set
+# CONFIG_VIA_RHINE is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_E1000 is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_TIGON3 is not set
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_IXGB is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_PLIP is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Token Ring devices (depends on LLC=y)
+#
+# CONFIG_NET_FC is not set
+# CONFIG_RCPCI is not set
+# CONFIG_SHAPER is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+
+#
+# Amateur Radio support
+#
+# CONFIG_HAMRADIO is not set
+
+#
+# IrDA (infrared) support
+#
+# CONFIG_IRDA is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN_BOOL is not set
+
+#
+# Graphics support
+#
+# CONFIG_FB is not set
+
+#
+# Old CD-ROM drivers (not SCSI, not IDE)
+#
+# CONFIG_CD_NO_IDESCSI is not set
+
+#
+# Input device support
+#
+# CONFIG_INPUT is not set
+
+#
+# Userland interfaces
+#
+
+#
+# Input I/O drivers
+#
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+# CONFIG_SERIO is not set
+
+#
+# Input Device Drivers
+#
+
+#
+# Macintosh device drivers
+#
+
+#
+# Character devices
+#
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_UNIX98_PTY_COUNT=256
+# CONFIG_PRINTER is not set
+# CONFIG_PPDEV is not set
+# CONFIG_TIPAR is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# I2C Hardware Sensors Mainboard support
+#
+
+#
+# I2C Hardware Sensors Chip support
+#
+# CONFIG_I2C_SENSOR is not set
+
+#
+# Mice
+#
+# CONFIG_BUSMOUSE is not set
+# CONFIG_QIC02_TAPE is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_NVRAM is not set
+CONFIG_GEN_RTC=y
+# CONFIG_GEN_RTC_X is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_FTAPE is not set
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_HANGCHECK_TIMER is not set
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_FS_XATTR=y
+# CONFIG_EXT3_FS_POSIX_ACL is not set
+# CONFIG_EXT3_FS_SECURITY is not set
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+CONFIG_FS_MBCACHE=y
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_FAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+# CONFIG_DEVFS_FS is not set
+CONFIG_DEVPTS_FS=y
+# CONFIG_DEVPTS_FS_XATTR is not set
+CONFIG_TMPFS=y
+CONFIG_RAMFS=y
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+# CONFIG_NFS_V3 is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFSD is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+# CONFIG_EXPORTFS is not set
+CONFIG_SUNRPC=y
+# CONFIG_SUNRPC_GSS is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_INTERMEZZO_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+CONFIG_USB=y
+# CONFIG_USB_DEBUG is not set
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEVICEFS=y
+# CONFIG_USB_BANDWIDTH is not set
+CONFIG_USB_DYNAMIC_MINORS=y
+
+#
+# USB Host Controller Drivers
+#
+# CONFIG_USB_EHCI_HCD is not set
+CONFIG_USB_OHCI_HCD=y
+# CONFIG_USB_UHCI_HCD is not set
+
+#
+# USB Device Class drivers
+#
+# CONFIG_USB_BLUETOOTH_TTY is not set
+CONFIG_USB_ACM=m
+# CONFIG_USB_PRINTER is not set
+CONFIG_USB_STORAGE=m
+# CONFIG_USB_STORAGE_DEBUG is not set
+# CONFIG_USB_STORAGE_DATAFAB is not set
+CONFIG_USB_STORAGE_FREECOM=y
+# CONFIG_USB_STORAGE_ISD200 is not set
+CONFIG_USB_STORAGE_DPCM=y
+# CONFIG_USB_STORAGE_HP8200e is not set
+# CONFIG_USB_STORAGE_SDDR09 is not set
+# CONFIG_USB_STORAGE_SDDR55 is not set
+# CONFIG_USB_STORAGE_JUMPSHOT is not set
+
+#
+# USB Human Interface Devices (HID)
+#
+CONFIG_USB_HID=m
+
+#
+# Input core support is needed for USB HID input layer or HIDBP support
+#
+CONFIG_USB_HIDDEV=y
+
+#
+# USB HID Boot Protocol drivers
+#
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_SCANNER is not set
+# CONFIG_USB_MICROTEK is not set
+# CONFIG_USB_HPUSBSCSI is not set
+
+#
+# USB Multimedia devices
+#
+# CONFIG_USB_DABUSB is not set
+
+#
+# Video4Linux support is needed for USB Multimedia device support
+#
+
+#
+# USB Network adaptors
+#
+# CONFIG_USB_CATC is not set
+# CONFIG_USB_KAWETH is not set
+# CONFIG_USB_PEGASUS is not set
+# CONFIG_USB_RTL8150 is not set
+# CONFIG_USB_USBNET is not set
+
+#
+# USB port drivers
+#
+# CONFIG_USB_USS720 is not set
+
+#
+# USB Serial Converter support
+#
+CONFIG_USB_SERIAL=m
+# CONFIG_USB_SERIAL_GENERIC is not set
+# CONFIG_USB_SERIAL_BELKIN is not set
+# CONFIG_USB_SERIAL_WHITEHEAT is not set
+# CONFIG_USB_SERIAL_DIGI_ACCELEPORT is not set
+# CONFIG_USB_SERIAL_EMPEG is not set
+# CONFIG_USB_SERIAL_FTDI_SIO is not set
+CONFIG_USB_SERIAL_VISOR=m
+# CONFIG_USB_SERIAL_IPAQ is not set
+# CONFIG_USB_SERIAL_IR is not set
+# CONFIG_USB_SERIAL_EDGEPORT is not set
+# CONFIG_USB_SERIAL_EDGEPORT_TI is not set
+# CONFIG_USB_SERIAL_KEYSPAN_PDA is not set
+CONFIG_USB_SERIAL_KEYSPAN=m
+# CONFIG_USB_SERIAL_KEYSPAN_MPR is not set
+CONFIG_USB_SERIAL_KEYSPAN_USA28=y
+CONFIG_USB_SERIAL_KEYSPAN_USA28X=y
+# CONFIG_USB_SERIAL_KEYSPAN_USA28XA is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA28XB is not set
+CONFIG_USB_SERIAL_KEYSPAN_USA19=y
+CONFIG_USB_SERIAL_KEYSPAN_USA18X=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19W=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19QW=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19QI=y
+CONFIG_USB_SERIAL_KEYSPAN_USA49W=y
+# CONFIG_USB_SERIAL_KEYSPAN_USA49WLC is not set
+# CONFIG_USB_SERIAL_KLSI is not set
+# CONFIG_USB_SERIAL_KOBIL_SCT is not set
+# CONFIG_USB_SERIAL_MCT_U232 is not set
+# CONFIG_USB_SERIAL_PL2303 is not set
+# CONFIG_USB_SERIAL_SAFE is not set
+# CONFIG_USB_SERIAL_CYBERJACK is not set
+# CONFIG_USB_SERIAL_XIRCOM is not set
+# CONFIG_USB_SERIAL_OMNINET is not set
+CONFIG_USB_EZUSB=y
+
+#
+# USB Miscellaneous drivers
+#
+# CONFIG_USB_TIGL is not set
+# CONFIG_USB_AUERSWALD is not set
+# CONFIG_USB_RIO500 is not set
+# CONFIG_USB_LCD is not set
+# CONFIG_USB_TEST is not set
+# CONFIG_USB_GADGET is not set
+
+#
+# Bluetooth support
+#
+# CONFIG_BT is not set
+
+#
+# Library routines
+#
+# CONFIG_CRC32 is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_DEBUG_KERNEL is not set
+# CONFIG_KALLSYMS is not set
+
+#
+# Security options
+#
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
diff --git a/arch/ppc/configs/ads8272_defconfig b/arch/ppc/configs/ads8272_defconfig
new file mode 100644
index 0000000..d1db7d1
--- /dev/null
+++ b/arch/ppc/configs/ads8272_defconfig
@@ -0,0 +1,582 @@
+#
+# Automatically generated make config: don't edit
+#
+CONFIG_MMU=y
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_HAVE_DEC_LOCK=y
+CONFIG_PPC=y
+CONFIG_PPC32=y
+CONFIG_GENERIC_NVRAM=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=y
+CONFIG_STANDALONE=y
+CONFIG_BROKEN_ON_SMP=y
+
+#
+# General setup
+#
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_HOTPLUG is not set
+# CONFIG_IKCONFIG is not set
+CONFIG_EMBEDDED=y
+# CONFIG_KALLSYMS is not set
+CONFIG_FUTEX=y
+# CONFIG_EPOLL is not set
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+
+#
+# Loadable module support
+#
+# CONFIG_MODULES is not set
+
+#
+# Processor
+#
+CONFIG_6xx=y
+# CONFIG_40x is not set
+# CONFIG_44x is not set
+# CONFIG_POWER3 is not set
+# CONFIG_POWER4 is not set
+# CONFIG_8xx is not set
+# CONFIG_CPU_FREQ is not set
+CONFIG_EMBEDDEDBOOT=y
+CONFIG_PPC_STD_MMU=y
+
+#
+# Platform options
+#
+# CONFIG_PPC_MULTIPLATFORM is not set
+# CONFIG_APUS is not set
+# CONFIG_WILLOW is not set
+# CONFIG_PCORE is not set
+# CONFIG_POWERPMC250 is not set
+# CONFIG_EV64260 is not set
+# CONFIG_SPRUCE is not set
+# CONFIG_LOPEC is not set
+# CONFIG_MCPN765 is not set
+# CONFIG_MVME5100 is not set
+# CONFIG_PPLUS is not set
+# CONFIG_PRPMC750 is not set
+# CONFIG_PRPMC800 is not set
+# CONFIG_SANDPOINT is not set
+# CONFIG_ADIR is not set
+# CONFIG_K2 is not set
+# CONFIG_PAL4 is not set
+# CONFIG_GEMINI is not set
+# CONFIG_EST8260 is not set
+# CONFIG_SBC82xx is not set
+# CONFIG_SBS8260 is not set
+# CONFIG_RPX6 is not set
+# CONFIG_TQM8260 is not set
+CONFIG_ADS8272=y
+CONFIG_PQ2ADS=y
+CONFIG_8260=y
+CONFIG_8272=y
+CONFIG_CPM2=y
+# CONFIG_PC_KEYBOARD is not set
+CONFIG_SERIAL_CONSOLE=y
+# CONFIG_SMP is not set
+# CONFIG_PREEMPT is not set
+# CONFIG_HIGHMEM is not set
+CONFIG_KERNEL_ELF=y
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+# CONFIG_CMDLINE_BOOL is not set
+
+#
+# Bus options
+#
+CONFIG_PCI=y
+CONFIG_PCI_DOMAINS=y
+# CONFIG_PCI_LEGACY_PROC is not set
+# CONFIG_PCI_NAMES is not set
+
+#
+# Advanced setup
+#
+# CONFIG_ADVANCED_OPTIONS is not set
+
+#
+# Default settings for advanced configuration options are used
+#
+CONFIG_HIGHMEM_START=0xfe000000
+CONFIG_LOWMEM_SIZE=0x30000000
+CONFIG_KERNEL_START=0xc0000000
+CONFIG_TASK_SIZE=0x80000000
+CONFIG_BOOT_LOAD=0x00400000
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_CARMEL is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=32768
+CONFIG_BLK_DEV_INITRD=y
+# CONFIG_LBD is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_SCSI is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# Macintosh device drivers
+#
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+# CONFIG_NETLINK_DEV is not set
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_IP_MROUTE is not set
+# CONFIG_ARPD is not set
+CONFIG_SYN_COOKIES=y
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_IPV6 is not set
+# CONFIG_NETFILTER is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_HW_FLOWCONTROL is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+# CONFIG_MII is not set
+# CONFIG_OAKNET is not set
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_NET_VENDOR_3COM is not set
+
+#
+# Tulip family network device support
+#
+# CONFIG_NET_TULIP is not set
+# CONFIG_HP100 is not set
+# CONFIG_NET_PCI is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_E1000 is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_TIGON3 is not set
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_IXGB is not set
+# CONFIG_S2IO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input I/O drivers
+#
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+# CONFIG_SERIO is not set
+# CONFIG_SERIO_I8042 is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Character devices
+#
+# CONFIG_VT is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_QIC02_TAPE is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_NVRAM is not set
+CONFIG_GEN_RTC=y
+# CONFIG_GEN_RTC_X is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_FTAPE is not set
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# Misc devices
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+# CONFIG_FB is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+# CONFIG_USB is not set
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_FS_XATTR=y
+# CONFIG_EXT3_FS_POSIX_ACL is not set
+# CONFIG_EXT3_FS_SECURITY is not set
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+CONFIG_FS_MBCACHE=y
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_FAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_SYSFS=y
+# CONFIG_DEVFS_FS is not set
+# CONFIG_DEVPTS_FS_XATTR is not set
+CONFIG_TMPFS=y
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+# CONFIG_NFS_V3 is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+# CONFIG_NFSD is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+# CONFIG_EXPORTFS is not set
+CONFIG_SUNRPC=y
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
+# CONFIG_MSDOS_PARTITION is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_NEC98_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_EFI_PARTITION is not set
+
+#
+# Native Language Support
+#
+# CONFIG_NLS is not set
+# CONFIG_SCC_ENET is not set
+CONFIG_FEC_ENET=y
+# CONFIG_USE_MDIO is not set
+
+#
+# CPM2 Options
+#
+CONFIG_SCC_CONSOLE=y
+CONFIG_FCC1_ENET=y
+# CONFIG_FCC2_ENET is not set
+# CONFIG_FCC3_ENET is not set
+
+#
+# Library routines
+#
+# CONFIG_CRC32 is not set
+# CONFIG_LIBCRC32C is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_DEBUG_KERNEL is not set
+# CONFIG_KGDB_CONSOLE is not set
+
+#
+# Security options
+#
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
diff --git a/arch/ppc/configs/apus_defconfig b/arch/ppc/configs/apus_defconfig
new file mode 100644
index 0000000..e224525
--- /dev/null
+++ b/arch/ppc/configs/apus_defconfig
@@ -0,0 +1,920 @@
+#
+# Automatically generated make config: don't edit
+#
+CONFIG_MMU=y
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_HAVE_DEC_LOCK=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+
+#
+# General setup
+#
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_EMBEDDED is not set
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+CONFIG_OBSOLETE_MODPARM=y
+# CONFIG_MODVERSIONS is not set
+CONFIG_KMOD=y
+
+#
+# Platform support
+#
+CONFIG_PPC=y
+CONFIG_PPC32=y
+CONFIG_6xx=y
+# CONFIG_40x is not set
+# CONFIG_POWER3 is not set
+# CONFIG_8xx is not set
+
+#
+# IBM 4xx options
+#
+# CONFIG_8260 is not set
+CONFIG_GENERIC_ISA_DMA=y
+CONFIG_PPC_STD_MMU=y
+CONFIG_SERIAL_CONSOLE=y
+# CONFIG_PPC_MULTIPLATFORM is not set
+CONFIG_APUS=y
+# CONFIG_WILLOW_2 is not set
+# CONFIG_PCORE is not set
+# CONFIG_POWERPMC250 is not set
+# CONFIG_EV64260 is not set
+# CONFIG_SPRUCE is not set
+# CONFIG_LOPEC is not set
+# CONFIG_MCPN765 is not set
+# CONFIG_MVME5100 is not set
+# CONFIG_PPLUS is not set
+# CONFIG_PRPMC750 is not set
+# CONFIG_PRPMC800 is not set
+# CONFIG_SANDPOINT is not set
+# CONFIG_ADIR is not set
+# CONFIG_K2 is not set
+# CONFIG_PAL4 is not set
+# CONFIG_GEMINI is not set
+# CONFIG_SMP is not set
+# CONFIG_PREEMPT is not set
+# CONFIG_ALTIVEC is not set
+# CONFIG_TAU is not set
+# CONFIG_CPU_FREQ is not set
+
+#
+# General setup
+#
+# CONFIG_HIGHMEM is not set
+CONFIG_PCI=y
+CONFIG_PCI_DOMAINS=y
+CONFIG_PCI_PERMEDIA=y
+CONFIG_KCORE_ELF=y
+CONFIG_BINFMT_ELF=y
+CONFIG_KERNEL_ELF=y
+CONFIG_BINFMT_MISC=m
+CONFIG_PCI_LEGACY_PROC=y
+CONFIG_PCI_NAMES=y
+# CONFIG_HOTPLUG is not set
+
+#
+# Parallel port support
+#
+CONFIG_PARPORT=m
+# CONFIG_PARPORT_PC is not set
+CONFIG_PARPORT_AMIGA=m
+# CONFIG_PARPORT_MFC3 is not set
+# CONFIG_PARPORT_OTHER is not set
+# CONFIG_PARPORT_1284 is not set
+CONFIG_PPC601_SYNC_FIX=y
+# CONFIG_CMDLINE_BOOL is not set
+CONFIG_AMIGA=y
+CONFIG_ZORRO=y
+CONFIG_ABSTRACT_CONSOLE=y
+CONFIG_APUS_FAST_EXCEPT=y
+CONFIG_AMIGA_PCMCIA=y
+CONFIG_AMIGA_BUILTIN_SERIAL=y
+CONFIG_GVPIOEXT=y
+CONFIG_GVPIOEXT_LP=m
+CONFIG_GVPIOEXT_PLIP=m
+CONFIG_MULTIFACE_III_TTY=y
+CONFIG_A2232=y
+CONFIG_WHIPPET_SERIAL=y
+CONFIG_APNE=y
+CONFIG_HEARTBEAT=y
+CONFIG_PROC_HARDWARE=y
+CONFIG_ZORRO_NAMES=y
+
+#
+# Advanced setup
+#
+# CONFIG_ADVANCED_OPTIONS is not set
+
+#
+# Default settings for advanced configuration options are used
+#
+CONFIG_HIGHMEM_START=0xfe000000
+CONFIG_LOWMEM_SIZE=0x30000000
+CONFIG_KERNEL_START=0xc0000000
+CONFIG_TASK_SIZE=0x80000000
+CONFIG_BOOT_LOAD=0x00800000
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Plug and Play support
+#
+# CONFIG_PNP is not set
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+CONFIG_AMIGA_FLOPPY=y
+CONFIG_AMIGA_Z2RAM=m
+# CONFIG_PARIDE is not set
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_NBD=m
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=4096
+CONFIG_BLK_DEV_INITRD=y
+
+#
+# Multi-device support (RAID and LVM)
+#
+CONFIG_MD=y
+CONFIG_BLK_DEV_MD=m
+CONFIG_MD_LINEAR=m
+CONFIG_MD_RAID0=m
+CONFIG_MD_RAID1=m
+CONFIG_MD_RAID5=m
+# CONFIG_MD_MULTIPATH is not set
+CONFIG_BLK_DEV_DM=m
+
+#
+# ATA/IDE/MFM/RLL support
+#
+CONFIG_IDE=y
+
+#
+# IDE, ATA and ATAPI Block devices
+#
+CONFIG_BLK_DEV_IDE=y
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+# CONFIG_BLK_DEV_HD is not set
+CONFIG_BLK_DEV_IDEDISK=y
+# CONFIG_IDEDISK_MULTI_MODE is not set
+# CONFIG_IDEDISK_STROKE is not set
+CONFIG_BLK_DEV_IDECD=y
+CONFIG_BLK_DEV_IDEFLOPPY=y
+CONFIG_BLK_DEV_IDESCSI=m
+# CONFIG_IDE_TASK_IOCTL is not set
+
+#
+# IDE chipset support/bugfixes
+#
+# CONFIG_BLK_DEV_IDEPCI is not set
+CONFIG_BLK_DEV_GAYLE=y
+CONFIG_BLK_DEV_IDEDOUBLER=y
+CONFIG_BLK_DEV_BUDDHA=y
+
+#
+# SCSI support
+#
+CONFIG_SCSI=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+CONFIG_CHR_DEV_ST=m
+CONFIG_CHR_DEV_OSST=m
+CONFIG_BLK_DEV_SR=y
+CONFIG_BLK_DEV_SR_VENDOR=y
+CONFIG_CHR_DEV_SG=m
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+# CONFIG_SCSI_MULTI_LUN is not set
+# CONFIG_SCSI_REPORT_LUNS is not set
+CONFIG_SCSI_CONSTANTS=y
+CONFIG_SCSI_LOGGING=y
+
+#
+# SCSI low-level drivers
+#
+# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
+# CONFIG_SCSI_ACARD is not set
+# CONFIG_SCSI_AACRAID is not set
+# CONFIG_SCSI_AIC7XXX is not set
+# CONFIG_SCSI_AIC7XXX_OLD is not set
+# CONFIG_SCSI_AIC79XX is not set
+# CONFIG_SCSI_DPT_I2O is not set
+# CONFIG_SCSI_ADVANSYS is not set
+# CONFIG_SCSI_IN2000 is not set
+# CONFIG_SCSI_AM53C974 is not set
+# CONFIG_SCSI_MEGARAID is not set
+# CONFIG_SCSI_BUSLOGIC is not set
+# CONFIG_SCSI_CPQFCTS is not set
+# CONFIG_SCSI_DMX3191D is not set
+# CONFIG_SCSI_EATA is not set
+# CONFIG_SCSI_EATA_PIO is not set
+# CONFIG_SCSI_FUTURE_DOMAIN is not set
+# CONFIG_SCSI_GDTH is not set
+# CONFIG_SCSI_GENERIC_NCR5380 is not set
+# CONFIG_SCSI_GENERIC_NCR5380_MMIO is not set
+# CONFIG_SCSI_INITIO is not set
+# CONFIG_SCSI_INIA100 is not set
+# CONFIG_SCSI_PPA is not set
+# CONFIG_SCSI_IMM is not set
+# CONFIG_SCSI_NCR53C7xx is not set
+# CONFIG_SCSI_SYM53C8XX_2 is not set
+# CONFIG_SCSI_NCR53C8XX is not set
+# CONFIG_SCSI_SYM53C8XX is not set
+# CONFIG_SCSI_PCI2000 is not set
+# CONFIG_SCSI_PCI2220I is not set
+# CONFIG_SCSI_QLOGIC_ISP is not set
+# CONFIG_SCSI_QLOGIC_FC is not set
+# CONFIG_SCSI_QLOGIC_1280 is not set
+# CONFIG_SCSI_DC395x is not set
+# CONFIG_SCSI_DC390T is not set
+# CONFIG_SCSI_U14_34F is not set
+# CONFIG_SCSI_NSP32 is not set
+# CONFIG_SCSI_DEBUG is not set
+CONFIG_A3000_SCSI=y
+CONFIG_A4000T_SCSI=y
+CONFIG_A2091_SCSI=y
+CONFIG_GVP11_SCSI=y
+CONFIG_CYBERSTORM_SCSI=y
+CONFIG_CYBERSTORMII_SCSI=y
+CONFIG_BLZ2060_SCSI=y
+CONFIG_BLZ1230_SCSI=y
+CONFIG_FASTLANE_SCSI=y
+CONFIG_A4091_SCSI=y
+CONFIG_WARPENGINE_SCSI=y
+CONFIG_BLZ603EPLUS_SCSI=y
+CONFIG_OKTAGON_SCSI=y
+
+#
+# Fusion MPT device support
+#
+# CONFIG_FUSION is not set
+
+#
+# IEEE 1394 (FireWire) support (EXPERIMENTAL)
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=m
+CONFIG_PACKET_MMAP=y
+CONFIG_NETLINK_DEV=m
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+# CONFIG_IP_PNP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+# CONFIG_INET_ECN is not set
+CONFIG_SYN_COOKIES=y
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+
+#
+# IP: Netfilter Configuration
+#
+CONFIG_IP_NF_CONNTRACK=m
+CONFIG_IP_NF_FTP=m
+CONFIG_IP_NF_IRC=m
+CONFIG_IP_NF_TFTP=m
+CONFIG_IP_NF_AMANDA=m
+CONFIG_IP_NF_QUEUE=m
+CONFIG_IP_NF_IPTABLES=m
+CONFIG_IP_NF_MATCH_LIMIT=m
+CONFIG_IP_NF_MATCH_MAC=m
+# CONFIG_IP_NF_MATCH_PKTTYPE is not set
+CONFIG_IP_NF_MATCH_MARK=m
+CONFIG_IP_NF_MATCH_MULTIPORT=m
+CONFIG_IP_NF_MATCH_TOS=m
+# CONFIG_IP_NF_MATCH_ECN is not set
+# CONFIG_IP_NF_MATCH_DSCP is not set
+# CONFIG_IP_NF_MATCH_AH_ESP is not set
+CONFIG_IP_NF_MATCH_LENGTH=m
+CONFIG_IP_NF_MATCH_TTL=m
+CONFIG_IP_NF_MATCH_TCPMSS=m
+CONFIG_IP_NF_MATCH_HELPER=m
+CONFIG_IP_NF_MATCH_STATE=m
+CONFIG_IP_NF_MATCH_CONNTRACK=m
+CONFIG_IP_NF_MATCH_UNCLEAN=m
+CONFIG_IP_NF_MATCH_OWNER=m
+CONFIG_IP_NF_FILTER=m
+CONFIG_IP_NF_TARGET_REJECT=m
+CONFIG_IP_NF_TARGET_MIRROR=m
+CONFIG_IP_NF_NAT=m
+CONFIG_IP_NF_NAT_NEEDED=y
+CONFIG_IP_NF_TARGET_MASQUERADE=m
+CONFIG_IP_NF_TARGET_REDIRECT=m
+CONFIG_IP_NF_NAT_SNMP_BASIC=m
+CONFIG_IP_NF_NAT_IRC=m
+CONFIG_IP_NF_NAT_FTP=m
+CONFIG_IP_NF_NAT_TFTP=m
+CONFIG_IP_NF_NAT_AMANDA=m
+CONFIG_IP_NF_MANGLE=m
+CONFIG_IP_NF_TARGET_TOS=m
+CONFIG_IP_NF_TARGET_ECN=m
+CONFIG_IP_NF_TARGET_DSCP=m
+CONFIG_IP_NF_TARGET_MARK=m
+CONFIG_IP_NF_TARGET_LOG=m
+CONFIG_IP_NF_TARGET_ULOG=m
+CONFIG_IP_NF_TARGET_TCPMSS=m
+CONFIG_IP_NF_ARPTABLES=m
+CONFIG_IP_NF_ARPFILTER=m
+CONFIG_IP_NF_COMPAT_IPCHAINS=m
+# CONFIG_IP_NF_COMPAT_IPFWADM is not set
+# CONFIG_IPV6 is not set
+# CONFIG_XFRM_USER is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+CONFIG_IPV6_SCTP__=y
+# CONFIG_IP_SCTP is not set
+# CONFIG_ATM is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_LLC is not set
+# CONFIG_DECNET is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_HW_FLOWCONTROL is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+CONFIG_NETDEVICES=y
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+CONFIG_DUMMY=m
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+CONFIG_TUN=m
+# CONFIG_ETHERTAP is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+# CONFIG_MII is not set
+# CONFIG_OAKNET is not set
+CONFIG_ARIADNE=y
+# CONFIG_ZORRO8390 is not set
+CONFIG_A2065=y
+CONFIG_HYDRA=y
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_NET_VENDOR_3COM is not set
+
+#
+# Tulip family network device support
+#
+# CONFIG_NET_TULIP is not set
+# CONFIG_HP100 is not set
+# CONFIG_NET_PCI is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_E1000 is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_TIGON3 is not set
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_IXGB is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+CONFIG_PLIP=m
+CONFIG_PPP=y
+CONFIG_PPP_MULTILINK=y
+CONFIG_PPP_FILTER=y
+CONFIG_PPP_ASYNC=y
+CONFIG_PPP_SYNC_TTY=y
+CONFIG_PPP_DEFLATE=y
+CONFIG_PPP_BSDCOMP=y
+CONFIG_PPPOE=y
+CONFIG_SLIP=y
+CONFIG_SLIP_COMPRESSED=y
+CONFIG_SLIP_SMART=y
+CONFIG_SLIP_MODE_SLIP6=y
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Token Ring devices (depends on LLC=y)
+#
+# CONFIG_NET_FC is not set
+# CONFIG_RCPCI is not set
+# CONFIG_SHAPER is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+
+#
+# Amateur Radio support
+#
+# CONFIG_HAMRADIO is not set
+
+#
+# IrDA (infrared) support
+#
+# CONFIG_IRDA is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN_BOOL is not set
+
+#
+# Graphics support
+#
+CONFIG_FB=y
+# CONFIG_FB_CIRRUS is not set
+CONFIG_FB_PM2=y
+# CONFIG_FB_PM2_FIFO_DISCONNECT is not set
+# CONFIG_FB_PM2_PCI is not set
+CONFIG_FB_PM2_CVPPC=y
+CONFIG_FB_CYBER2000=y
+CONFIG_FB_AMIGA=y
+CONFIG_FB_AMIGA_OCS=y
+CONFIG_FB_AMIGA_ECS=y
+CONFIG_FB_AMIGA_AGA=y
+CONFIG_FB_CYBER=y
+CONFIG_FB_VIRGE=y
+CONFIG_FB_RETINAZ3=y
+CONFIG_FB_FM2=y
+# CONFIG_FB_CT65550 is not set
+# CONFIG_FB_IMSTT is not set
+# CONFIG_FB_S3TRIO is not set
+# CONFIG_FB_VGA16 is not set
+# CONFIG_FB_RIVA is not set
+# CONFIG_FB_MATROX is not set
+# CONFIG_FB_RADEON is not set
+# CONFIG_FB_ATY128 is not set
+# CONFIG_FB_ATY is not set
+# CONFIG_FB_SIS is not set
+# CONFIG_FB_NEOMAGIC is not set
+# CONFIG_FB_3DFX is not set
+# CONFIG_FB_VOODOO1 is not set
+# CONFIG_FB_TRIDENT is not set
+# CONFIG_FB_PM3 is not set
+# CONFIG_FB_VIRTUAL is not set
+
+#
+# Logo configuration
+#
+CONFIG_LOGO=y
+CONFIG_LOGO_LINUX_MONO=y
+CONFIG_LOGO_LINUX_VGA16=y
+CONFIG_LOGO_LINUX_CLUT224=y
+
+#
+# Old CD-ROM drivers (not SCSI, not IDE)
+#
+# CONFIG_CD_NO_IDESCSI is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=m
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=m
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+CONFIG_INPUT_JOYDEV=m
+# CONFIG_INPUT_TSDEV is not set
+CONFIG_INPUT_EVDEV=m
+CONFIG_INPUT_EVBUG=m
+
+#
+# Input I/O drivers
+#
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+CONFIG_SERIO=y
+# CONFIG_SERIO_I8042 is not set
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_CT82C710 is not set
+# CONFIG_SERIO_PARKBD is not set
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+CONFIG_KEYBOARD_ATKBD=m
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+CONFIG_KEYBOARD_AMIGA=m
+CONFIG_INPUT_MOUSE=y
+CONFIG_MOUSE_PS2=m
+CONFIG_MOUSE_SERIAL=m
+CONFIG_MOUSE_AMIGA=m
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+CONFIG_INPUT_MISC=y
+# CONFIG_INPUT_PCSPKR is not set
+CONFIG_INPUT_UINPUT=m
+
+#
+# Macintosh device drivers
+#
+
+#
+# Character devices
+#
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_UNIX98_PTYS=y
+CONFIG_UNIX98_PTY_COUNT=256
+CONFIG_PRINTER=m
+# CONFIG_LP_CONSOLE is not set
+# CONFIG_PPDEV is not set
+# CONFIG_TIPAR is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# I2C Hardware Sensors Mainboard support
+#
+
+#
+# I2C Hardware Sensors Chip support
+#
+# CONFIG_I2C_SENSOR is not set
+
+#
+# Mice
+#
+CONFIG_BUSMOUSE=y
+# CONFIG_QIC02_TAPE is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_NVRAM is not set
+CONFIG_GEN_RTC=y
+# CONFIG_GEN_RTC_X is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_FTAPE is not set
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_HANGCHECK_TIMER is not set
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_FS_XATTR=y
+# CONFIG_EXT3_FS_POSIX_ACL is not set
+# CONFIG_EXT3_FS_SECURITY is not set
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+CONFIG_FS_MBCACHE=y
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_XFS_FS is not set
+CONFIG_MINIX_FS=y
+CONFIG_ROMFS_FS=y
+# CONFIG_QUOTA is not set
+CONFIG_AUTOFS_FS=m
+CONFIG_AUTOFS4_FS=m
+
+#
+# CD-ROM/DVD Filesystems
+#
+CONFIG_ISO9660_FS=y
+CONFIG_JOLIET=y
+# CONFIG_ZISOFS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+# CONFIG_DEVFS_FS is not set
+CONFIG_DEVPTS_FS=y
+# CONFIG_DEVPTS_FS_XATTR is not set
+CONFIG_TMPFS=y
+CONFIG_RAMFS=y
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+CONFIG_AFFS_FS=y
+CONFIG_HFS_FS=y
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+CONFIG_CRAMFS=y
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V4 is not set
+CONFIG_NFSD=m
+CONFIG_NFSD_V3=y
+# CONFIG_NFSD_V4 is not set
+# CONFIG_NFSD_TCP is not set
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_EXPORTFS=m
+CONFIG_SUNRPC=y
+# CONFIG_SUNRPC_GSS is not set
+CONFIG_SMB_FS=m
+# CONFIG_SMB_NLS_DEFAULT is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+CONFIG_CODA_FS=m
+# CONFIG_INTERMEZZO_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+CONFIG_AMIGA_PARTITION=y
+CONFIG_ATARI_PARTITION=y
+# CONFIG_MAC_PARTITION is not set
+CONFIG_MSDOS_PARTITION=y
+CONFIG_BSD_DISKLABEL=y
+# CONFIG_MINIX_SUBPARTITION is not set
+CONFIG_SOLARIS_X86_PARTITION=y
+CONFIG_UNIXWARE_DISKLABEL=y
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_NEC98_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_EFI_PARTITION is not set
+CONFIG_SMB_NLS=y
+CONFIG_NLS=y
+
+#
+# Native Language Support
+#
+CONFIG_NLS_DEFAULT="iso8859-1"
+CONFIG_NLS_CODEPAGE_437=m
+CONFIG_NLS_CODEPAGE_737=m
+CONFIG_NLS_CODEPAGE_775=m
+CONFIG_NLS_CODEPAGE_850=m
+CONFIG_NLS_CODEPAGE_852=m
+CONFIG_NLS_CODEPAGE_855=m
+CONFIG_NLS_CODEPAGE_857=m
+CONFIG_NLS_CODEPAGE_860=m
+CONFIG_NLS_CODEPAGE_861=m
+CONFIG_NLS_CODEPAGE_862=m
+CONFIG_NLS_CODEPAGE_863=m
+CONFIG_NLS_CODEPAGE_864=m
+CONFIG_NLS_CODEPAGE_865=m
+CONFIG_NLS_CODEPAGE_866=m
+CONFIG_NLS_CODEPAGE_869=m
+CONFIG_NLS_CODEPAGE_936=m
+CONFIG_NLS_CODEPAGE_950=m
+CONFIG_NLS_CODEPAGE_932=m
+CONFIG_NLS_CODEPAGE_949=m
+CONFIG_NLS_CODEPAGE_874=m
+CONFIG_NLS_ISO8859_8=m
+# CONFIG_NLS_CODEPAGE_1250 is not set
+CONFIG_NLS_CODEPAGE_1251=m
+CONFIG_NLS_ISO8859_1=m
+CONFIG_NLS_ISO8859_2=m
+CONFIG_NLS_ISO8859_3=m
+CONFIG_NLS_ISO8859_4=m
+CONFIG_NLS_ISO8859_5=m
+CONFIG_NLS_ISO8859_6=m
+CONFIG_NLS_ISO8859_7=m
+CONFIG_NLS_ISO8859_9=m
+CONFIG_NLS_ISO8859_13=m
+CONFIG_NLS_ISO8859_14=m
+CONFIG_NLS_ISO8859_15=m
+CONFIG_NLS_KOI8_R=m
+CONFIG_NLS_KOI8_U=m
+CONFIG_NLS_UTF8=m
+
+#
+# Sound
+#
+CONFIG_SOUND=y
+CONFIG_DMASOUND_PAULA=m
+CONFIG_DMASOUND=m
+
+#
+# Advanced Linux Sound Architecture
+#
+# CONFIG_SND is not set
+
+#
+# Open Sound System
+#
+CONFIG_SOUND_PRIME=m
+# CONFIG_SOUND_BT878 is not set
+# CONFIG_SOUND_CMPCI is not set
+# CONFIG_SOUND_EMU10K1 is not set
+# CONFIG_SOUND_FUSION is not set
+# CONFIG_SOUND_CS4281 is not set
+# CONFIG_SOUND_ES1370 is not set
+# CONFIG_SOUND_ES1371 is not set
+# CONFIG_SOUND_ESSSOLO1 is not set
+# CONFIG_SOUND_MAESTRO is not set
+# CONFIG_SOUND_MAESTRO3 is not set
+# CONFIG_SOUND_ICH is not set
+# CONFIG_SOUND_RME96XX is not set
+# CONFIG_SOUND_SONICVIBES is not set
+# CONFIG_SOUND_TRIDENT is not set
+# CONFIG_SOUND_MSNDCLAS is not set
+# CONFIG_SOUND_MSNDPIN is not set
+# CONFIG_SOUND_VIA82CXXX is not set
+CONFIG_SOUND_OSS=m
+CONFIG_SOUND_TRACEINIT=y
+CONFIG_SOUND_DMAP=y
+# CONFIG_SOUND_AD1816 is not set
+# CONFIG_SOUND_SGALAXY is not set
+# CONFIG_SOUND_ADLIB is not set
+# CONFIG_SOUND_ACI_MIXER is not set
+# CONFIG_SOUND_CS4232 is not set
+# CONFIG_SOUND_SSCAPE is not set
+# CONFIG_SOUND_GUS is not set
+CONFIG_SOUND_VMIDI=m
+# CONFIG_SOUND_TRIX is not set
+# CONFIG_SOUND_MSS is not set
+# CONFIG_SOUND_MPU401 is not set
+# CONFIG_SOUND_NM256 is not set
+# CONFIG_SOUND_MAD16 is not set
+# CONFIG_SOUND_PAS is not set
+# CONFIG_SOUND_PSS is not set
+# CONFIG_SOUND_SB is not set
+# CONFIG_SOUND_AWE32_SYNTH is not set
+# CONFIG_SOUND_WAVEFRONT is not set
+# CONFIG_SOUND_MAUI is not set
+# CONFIG_SOUND_YM3812 is not set
+# CONFIG_SOUND_OPL3SA1 is not set
+# CONFIG_SOUND_OPL3SA2 is not set
+# CONFIG_SOUND_YMFPCI is not set
+# CONFIG_SOUND_UART6850 is not set
+# CONFIG_SOUND_AEDSP16 is not set
+
+#
+# USB support
+#
+# CONFIG_USB is not set
+# CONFIG_USB_GADGET is not set
+
+#
+# Bluetooth support
+#
+# CONFIG_BT is not set
+
+#
+# Library routines
+#
+# CONFIG_CRC32 is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
+
+#
+# Kernel hacking
+#
+# CONFIG_DEBUG_KERNEL is not set
+# CONFIG_KALLSYMS is not set
+
+#
+# Security options
+#
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
diff --git a/arch/ppc/configs/ash_defconfig b/arch/ppc/configs/ash_defconfig
new file mode 100644
index 0000000..c4a73cc
--- /dev/null
+++ b/arch/ppc/configs/ash_defconfig
@@ -0,0 +1,666 @@
+#
+# Automatically generated make config: don't edit
+#
+CONFIG_MMU=y
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_HAVE_DEC_LOCK=y
+CONFIG_PPC=y
+CONFIG_PPC32=y
+CONFIG_GENERIC_NVRAM=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=y
+CONFIG_STANDALONE=y
+CONFIG_BROKEN_ON_SMP=y
+
+#
+# General setup
+#
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_HOTPLUG is not set
+# CONFIG_IKCONFIG is not set
+CONFIG_EMBEDDED=y
+# CONFIG_KALLSYMS is not set
+CONFIG_FUTEX=y
+# CONFIG_EPOLL is not set
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_OBSOLETE_MODPARM=y
+# CONFIG_MODVERSIONS is not set
+CONFIG_KMOD=y
+
+#
+# Processor
+#
+# CONFIG_6xx is not set
+CONFIG_40x=y
+# CONFIG_44x is not set
+# CONFIG_POWER3 is not set
+# CONFIG_POWER4 is not set
+# CONFIG_8xx is not set
+# CONFIG_MATH_EMULATION is not set
+# CONFIG_CPU_FREQ is not set
+CONFIG_4xx=y
+
+#
+# IBM 4xx options
+#
+CONFIG_ASH=y
+# CONFIG_CPCI405 is not set
+# CONFIG_EP405 is not set
+# CONFIG_EVB405EP is not set
+# CONFIG_OAK is not set
+# CONFIG_REDWOOD_5 is not set
+# CONFIG_REDWOOD_6 is not set
+# CONFIG_SYCAMORE is not set
+# CONFIG_WALNUT is not set
+CONFIG_NP405H=y
+CONFIG_IBM405_ERR77=y
+CONFIG_IBM405_ERR51=y
+CONFIG_IBM_OCP=y
+CONFIG_PPC_OCP=y
+CONFIG_IBM_OPENBIOS=y
+# CONFIG_PM is not set
+CONFIG_UART0_TTYS0=y
+# CONFIG_UART0_TTYS1 is not set
+CONFIG_NOT_COHERENT_CACHE=y
+
+#
+# Platform options
+#
+# CONFIG_PC_KEYBOARD is not set
+# CONFIG_SMP is not set
+# CONFIG_PREEMPT is not set
+# CONFIG_HIGHMEM is not set
+CONFIG_KERNEL_ELF=y
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+CONFIG_CMDLINE_BOOL=y
+CONFIG_CMDLINE="ip=on"
+
+#
+# Bus options
+#
+CONFIG_PCI=y
+CONFIG_PCI_DOMAINS=y
+CONFIG_PCI_LEGACY_PROC=y
+# CONFIG_PCI_NAMES is not set
+
+#
+# Advanced setup
+#
+# CONFIG_ADVANCED_OPTIONS is not set
+
+#
+# Default settings for advanced configuration options are used
+#
+CONFIG_HIGHMEM_START=0xfe000000
+CONFIG_LOWMEM_SIZE=0x30000000
+CONFIG_KERNEL_START=0xc0000000
+CONFIG_TASK_SIZE=0x80000000
+CONFIG_BOOT_LOAD=0x00400000
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_CARMEL is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=4096
+CONFIG_BLK_DEV_INITRD=y
+# CONFIG_LBD is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_SCSI is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+# CONFIG_FUSION is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# Macintosh device drivers
+#
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+# CONFIG_PACKET is not set
+# CONFIG_NETLINK_DEV is not set
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_PNP=y
+# CONFIG_IP_PNP_DHCP is not set
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_IP_MROUTE is not set
+# CONFIG_ARPD is not set
+CONFIG_SYN_COOKIES=y
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_IPV6 is not set
+# CONFIG_DECNET is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_NETFILTER is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+# CONFIG_ATM is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_HW_FLOWCONTROL is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+CONFIG_NETDEVICES=y
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+# CONFIG_NET_ETHERNET is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_E1000 is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
+# CONFIG_SIS190 is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_TIGON3 is not set
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_IXGB is not set
+CONFIG_IBM_EMAC=y
+# CONFIG_IBM_EMAC_ERRMSG is not set
+CONFIG_IBM_EMAC_RXB=64
+CONFIG_IBM_EMAC_TXB=8
+CONFIG_IBM_EMAC_FGAP=8
+CONFIG_IBM_EMAC_SKBRES=0
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+# CONFIG_RCPCI is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+
+#
+# Amateur Radio support
+#
+# CONFIG_HAMRADIO is not set
+
+#
+# IrDA (infrared) support
+#
+# CONFIG_IRDA is not set
+
+#
+# Bluetooth support
+#
+# CONFIG_BT is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input I/O drivers
+#
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+CONFIG_SERIO=y
+CONFIG_SERIO_I8042=y
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_CT82C710 is not set
+# CONFIG_SERIO_PCIPS2 is not set
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+CONFIG_KEYBOARD_ATKBD=y
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+CONFIG_INPUT_MOUSE=y
+CONFIG_MOUSE_PS2=y
+# CONFIG_MOUSE_SERIAL is not set
+# CONFIG_MOUSE_VSXXXAA is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Character devices
+#
+# CONFIG_VT is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=4
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_QIC02_TAPE is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+CONFIG_WATCHDOG=y
+# CONFIG_WATCHDOG_NOWAYOUT is not set
+
+#
+# Watchdog Device Drivers
+#
+# CONFIG_SOFT_WATCHDOG is not set
+
+#
+# PCI-based Watchdog Cards
+#
+# CONFIG_PCIPCWATCHDOG is not set
+# CONFIG_WDTPCI is not set
+# CONFIG_NVRAM is not set
+CONFIG_GEN_RTC=y
+# CONFIG_GEN_RTC_X is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_FTAPE is not set
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# I2C support
+#
+CONFIG_I2C=y
+# CONFIG_I2C_CHARDEV is not set
+
+#
+# I2C Algorithms
+#
+# CONFIG_I2C_ALGOBIT is not set
+# CONFIG_I2C_ALGOPCF is not set
+
+#
+# I2C Hardware Bus support
+#
+# CONFIG_I2C_ALI1535 is not set
+# CONFIG_I2C_ALI15X3 is not set
+# CONFIG_I2C_AMD756 is not set
+# CONFIG_I2C_AMD8111 is not set
+# CONFIG_I2C_I801 is not set
+# CONFIG_I2C_I810 is not set
+# CONFIG_I2C_IBM_IIC is not set
+# CONFIG_I2C_ISA is not set
+# CONFIG_I2C_NFORCE2 is not set
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_PIIX4 is not set
+# CONFIG_I2C_PROSAVAGE is not set
+# CONFIG_I2C_SAVAGE4 is not set
+# CONFIG_SCx200_ACB is not set
+# CONFIG_I2C_SIS5595 is not set
+# CONFIG_I2C_SIS630 is not set
+# CONFIG_I2C_SIS96X is not set
+# CONFIG_I2C_VIA is not set
+# CONFIG_I2C_VIAPRO is not set
+# CONFIG_I2C_VOODOO3 is not set
+
+#
+# Hardware Sensors Chip support
+#
+# CONFIG_I2C_SENSOR is not set
+# CONFIG_SENSORS_ADM1021 is not set
+# CONFIG_SENSORS_ASB100 is not set
+# CONFIG_SENSORS_DS1621 is not set
+# CONFIG_SENSORS_FSCHER is not set
+# CONFIG_SENSORS_GL518SM is not set
+# CONFIG_SENSORS_IT87 is not set
+# CONFIG_SENSORS_LM75 is not set
+# CONFIG_SENSORS_LM78 is not set
+# CONFIG_SENSORS_LM80 is not set
+# CONFIG_SENSORS_LM83 is not set
+# CONFIG_SENSORS_LM85 is not set
+# CONFIG_SENSORS_LM90 is not set
+# CONFIG_SENSORS_VIA686A is not set
+# CONFIG_SENSORS_W83781D is not set
+# CONFIG_SENSORS_W83L785TS is not set
+# CONFIG_SENSORS_W83627HF is not set
+
+#
+# Other I2C Chip support
+#
+# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+
+#
+# Misc devices
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+# CONFIG_FB is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+# CONFIG_USB is not set
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_JBD is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_FAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+# CONFIG_DEVFS_FS is not set
+# CONFIG_DEVPTS_FS_XATTR is not set
+CONFIG_TMPFS=y
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+# CONFIG_NFS_V3 is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+# CONFIG_NFSD is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+# CONFIG_EXPORTFS is not set
+CONFIG_SUNRPC=y
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_INTERMEZZO_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
+# CONFIG_MSDOS_PARTITION is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_NEC98_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_EFI_PARTITION is not set
+
+#
+# Native Language Support
+#
+# CONFIG_NLS is not set
+
+#
+# IBM 40x options
+#
+
+#
+# Library routines
+#
+CONFIG_CRC32=y
+
+#
+# Kernel hacking
+#
+# CONFIG_DEBUG_KERNEL is not set
+# CONFIG_SERIAL_TEXT_DEBUG is not set
+CONFIG_OCP=y
+
+#
+# Security options
+#
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
diff --git a/arch/ppc/configs/beech_defconfig b/arch/ppc/configs/beech_defconfig
new file mode 100644
index 0000000..0bd671b
--- /dev/null
+++ b/arch/ppc/configs/beech_defconfig
@@ -0,0 +1,615 @@
+#
+# Automatically generated make config: don't edit
+#
+CONFIG_MMU=y
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_HAVE_DEC_LOCK=y
+CONFIG_PPC=y
+CONFIG_PPC32=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=y
+# CONFIG_STANDALONE is not set
+CONFIG_BROKEN_ON_SMP=y
+
+#
+# General setup
+#
+# CONFIG_SWAP is not set
+CONFIG_SYSVIPC=y
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_IKCONFIG is not set
+CONFIG_EMBEDDED=y
+# CONFIG_KALLSYMS is not set
+CONFIG_FUTEX=y
+# CONFIG_EPOLL is not set
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_OBSOLETE_MODPARM=y
+CONFIG_MODVERSIONS=y
+CONFIG_KMOD=y
+
+#
+# Processor
+#
+# CONFIG_6xx is not set
+CONFIG_40x=y
+# CONFIG_44x is not set
+# CONFIG_POWER3 is not set
+# CONFIG_POWER4 is not set
+# CONFIG_8xx is not set
+# CONFIG_MATH_EMULATION is not set
+# CONFIG_CPU_FREQ is not set
+CONFIG_4xx=y
+
+#
+# IBM 4xx options
+#
+# CONFIG_ASH is not set
+CONFIG_BEECH=y
+# CONFIG_CEDAR is not set
+# CONFIG_CPCI405 is not set
+# CONFIG_EP405 is not set
+# CONFIG_OAK is not set
+# CONFIG_REDWOOD_4 is not set
+# CONFIG_REDWOOD_5 is not set
+# CONFIG_REDWOOD_6 is not set
+# CONFIG_SYCAMORE is not set
+# CONFIG_TIVO is not set
+# CONFIG_WALNUT is not set
+CONFIG_IBM405_ERR77=y
+CONFIG_IBM405_ERR51=y
+CONFIG_IBM_OCP=y
+CONFIG_IBM_OPENBIOS=y
+CONFIG_405_DMA=y
+# CONFIG_PM is not set
+CONFIG_UART0_TTYS0=y
+# CONFIG_UART0_TTYS1 is not set
+CONFIG_NOT_COHERENT_CACHE=y
+
+#
+# Platform options
+#
+# CONFIG_PC_KEYBOARD is not set
+# CONFIG_SMP is not set
+# CONFIG_PREEMPT is not set
+# CONFIG_HIGHMEM is not set
+CONFIG_KERNEL_ELF=y
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+# CONFIG_CMDLINE_BOOL is not set
+
+#
+# Bus options
+#
+# CONFIG_PCI is not set
+# CONFIG_PCI_DOMAINS is not set
+# CONFIG_HOTPLUG is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Advanced setup
+#
+# CONFIG_ADVANCED_OPTIONS is not set
+
+#
+# Default settings for advanced configuration options are used
+#
+CONFIG_HIGHMEM_START=0xfe000000
+CONFIG_LOWMEM_SIZE=0x30000000
+CONFIG_KERNEL_START=0xc0000000
+CONFIG_TASK_SIZE=0x80000000
+CONFIG_BOOT_LOAD=0x00400000
+
+#
+# Generic Driver Options
+#
+
+#
+# Memory Technology Devices (MTD)
+#
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_CONCAT is not set
+# CONFIG_MTD_REDBOOT_PARTS is not set
+# CONFIG_MTD_CMDLINE_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=y
+CONFIG_MTD_JEDECPROBE=y
+CONFIG_MTD_GEN_PROBE=y
+# CONFIG_MTD_CFI_ADV_OPTIONS is not set
+# CONFIG_MTD_CFI_INTELEXT is not set
+CONFIG_MTD_CFI_AMDSTD=y
+# CONFIG_MTD_CFI_STAA is not set
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+# CONFIG_MTD_OBSOLETE_CHIPS is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+# CONFIG_MTD_PHYSMAP is not set
+CONFIG_MTD_BEECH=y
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLKMTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+
+#
+# NAND Flash Device Drivers
+#
+# CONFIG_MTD_NAND is not set
+
+#
+# Plug and Play support
+#
+# CONFIG_PNP is not set
+
+#
+# Block devices
+#
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=4096
+CONFIG_BLK_DEV_INITRD=y
+# CONFIG_LBD is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_SCSI is not set
+
+#
+# Fusion MPT device support
+#
+
+#
+# I2O device support
+#
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+# CONFIG_PACKET is not set
+# CONFIG_NETLINK_DEV is not set
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_PNP=y
+# CONFIG_IP_PNP_DHCP is not set
+CONFIG_IP_PNP_BOOTP=y
+CONFIG_IP_PNP_RARP=y
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_IP_MROUTE is not set
+# CONFIG_ARPD is not set
+# CONFIG_INET_ECN is not set
+CONFIG_SYN_COOKIES=y
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_IPV6 is not set
+# CONFIG_DECNET is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_NETFILTER is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+CONFIG_IPV6_SCTP__=y
+# CONFIG_IP_SCTP is not set
+# CONFIG_ATM is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_HW_FLOWCONTROL is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+# CONFIG_MII is not set
+# CONFIG_OAKNET is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_SHAPER is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+
+#
+# Amateur Radio support
+#
+# CONFIG_HAMRADIO is not set
+
+#
+# IrDA (infrared) support
+#
+# CONFIG_IRDA is not set
+
+#
+# Bluetooth support
+#
+# CONFIG_BT is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN_BOOL is not set
+
+#
+# Graphics support
+#
+CONFIG_FB=y
+# CONFIG_FB_CT65550 is not set
+# CONFIG_FB_S3TRIO is not set
+# CONFIG_FB_VGA16 is not set
+# CONFIG_FB_VIRTUAL is not set
+
+#
+# Logo configuration
+#
+# CONFIG_LOGO is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input I/O drivers
+#
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+CONFIG_SERIO=y
+# CONFIG_SERIO_I8042 is not set
+# CONFIG_SERIO_SERPORT is not set
+# CONFIG_SERIO_CT82C710 is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Macintosh device drivers
+#
+
+#
+# Character devices
+#
+# CONFIG_VT is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=4
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_UNIX98_PTY_COUNT=256
+
+#
+# I2C support
+#
+CONFIG_I2C=y
+# CONFIG_I2C_CHARDEV is not set
+
+#
+# I2C Algorithms
+#
+# CONFIG_I2C_ALGOBIT is not set
+# CONFIG_I2C_ALGOPCF is not set
+
+#
+# I2C Hardware Bus support
+#
+# CONFIG_I2C_AMD756 is not set
+# CONFIG_I2C_AMD8111 is not set
+CONFIG_I2C_IBM_IIC=y
+
+#
+# I2C Hardware Sensors Chip support
+#
+# CONFIG_I2C_SENSOR is not set
+# CONFIG_SENSORS_ADM1021 is not set
+# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_SENSORS_IT87 is not set
+# CONFIG_SENSORS_LM75 is not set
+# CONFIG_SENSORS_LM78 is not set
+# CONFIG_SENSORS_LM85 is not set
+# CONFIG_SENSORS_VIA686A is not set
+# CONFIG_SENSORS_W83781D is not set
+
+#
+# Mice
+#
+# CONFIG_BUSMOUSE is not set
+# CONFIG_QIC02_TAPE is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_NVRAM is not set
+CONFIG_GEN_RTC=y
+# CONFIG_GEN_RTC_X is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_FTAPE is not set
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_JBD is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_FAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_DEVFS_FS=y
+# CONFIG_DEVFS_MOUNT is not set
+# CONFIG_DEVFS_DEBUG is not set
+CONFIG_DEVPTS_FS=y
+# CONFIG_DEVPTS_FS_XATTR is not set
+CONFIG_TMPFS=y
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_JFFS_FS is not set
+# CONFIG_JFFS2_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+# CONFIG_NFS_V3 is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFSD is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+# CONFIG_EXPORTFS is not set
+CONFIG_SUNRPC=y
+# CONFIG_SUNRPC_GSS is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_INTERMEZZO_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Sound
+#
+CONFIG_SOUND=y
+
+#
+# Advanced Linux Sound Architecture
+#
+# CONFIG_SND is not set
+
+#
+# Open Sound System
+#
+# CONFIG_SOUND_PRIME is not set
+
+#
+# IBM 40x options
+#
+
+#
+# USB support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# Library routines
+#
+# CONFIG_CRC32 is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_DEBUG_KERNEL is not set
+# CONFIG_SERIAL_TEXT_DEBUG is not set
+CONFIG_OCP=y
+
+#
+# Security options
+#
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
diff --git a/arch/ppc/configs/bseip_defconfig b/arch/ppc/configs/bseip_defconfig
new file mode 100644
index 0000000..ce9f9f77
--- /dev/null
+++ b/arch/ppc/configs/bseip_defconfig
@@ -0,0 +1,517 @@
+#
+# Automatically generated make config: don't edit
+#
+CONFIG_MMU=y
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_HAVE_DEC_LOCK=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+
+#
+# General setup
+#
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_EMBEDDED=y
+CONFIG_FUTEX=y
+# CONFIG_EPOLL is not set
+
+#
+# Loadable module support
+#
+# CONFIG_MODULES is not set
+
+#
+# Platform support
+#
+CONFIG_PPC=y
+CONFIG_PPC32=y
+# CONFIG_6xx is not set
+# CONFIG_40x is not set
+# CONFIG_POWER3 is not set
+CONFIG_8xx=y
+
+#
+# IBM 4xx options
+#
+CONFIG_EMBEDDEDBOOT=y
+CONFIG_SERIAL_CONSOLE=y
+CONFIG_NOT_COHERENT_CACHE=y
+# CONFIG_RPXLITE is not set
+# CONFIG_RPXCLASSIC is not set
+CONFIG_BSEIP=y
+# CONFIG_FADS is not set
+# CONFIG_TQM823L is not set
+# CONFIG_TQM850L is not set
+# CONFIG_TQM855L is not set
+# CONFIG_TQM860L is not set
+# CONFIG_FPS850L is not set
+# CONFIG_SPD823TS is not set
+# CONFIG_IVMS8 is not set
+# CONFIG_IVML24 is not set
+# CONFIG_SM850 is not set
+# CONFIG_HERMES_PRO is not set
+# CONFIG_IP860 is not set
+# CONFIG_LWMON is not set
+# CONFIG_PCU_E is not set
+# CONFIG_CCM is not set
+# CONFIG_LANTEC is not set
+# CONFIG_MBX is not set
+# CONFIG_WINCEPT is not set
+# CONFIG_SMP is not set
+# CONFIG_PREEMPT is not set
+CONFIG_MATH_EMULATION=y
+# CONFIG_CPU_FREQ is not set
+
+#
+# General setup
+#
+# CONFIG_HIGHMEM is not set
+# CONFIG_PCI is not set
+# CONFIG_PCI_DOMAINS is not set
+# CONFIG_PCI_QSPAN is not set
+CONFIG_KCORE_ELF=y
+CONFIG_BINFMT_ELF=y
+CONFIG_KERNEL_ELF=y
+# CONFIG_BINFMT_MISC is not set
+# CONFIG_HOTPLUG is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+# CONFIG_CMDLINE_BOOL is not set
+
+#
+# Advanced setup
+#
+# CONFIG_ADVANCED_OPTIONS is not set
+
+#
+# Default settings for advanced configuration options are used
+#
+CONFIG_HIGHMEM_START=0xfe000000
+CONFIG_LOWMEM_SIZE=0x30000000
+CONFIG_KERNEL_START=0xc0000000
+CONFIG_TASK_SIZE=0x80000000
+CONFIG_BOOT_LOAD=0x00400000
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Plug and Play support
+#
+# CONFIG_PNP is not set
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_NBD is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=4096
+CONFIG_BLK_DEV_INITRD=y
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# ATA/IDE/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI support
+#
+# CONFIG_SCSI is not set
+
+#
+# Fusion MPT device support
+#
+
+#
+# I2O device support
+#
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+# CONFIG_NETLINK_DEV is not set
+# CONFIG_NETFILTER is not set
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_IP_MROUTE is not set
+# CONFIG_ARPD is not set
+# CONFIG_INET_ECN is not set
+CONFIG_SYN_COOKIES=y
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_IPV6 is not set
+# CONFIG_XFRM_USER is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+CONFIG_IPV6_SCTP__=y
+# CONFIG_IP_SCTP is not set
+# CONFIG_ATM is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_LLC is not set
+# CONFIG_DECNET is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_HW_FLOWCONTROL is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_ETHERTAP is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+# CONFIG_MII is not set
+# CONFIG_OAKNET is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Token Ring devices (depends on LLC=y)
+#
+# CONFIG_SHAPER is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+
+#
+# Amateur Radio support
+#
+# CONFIG_HAMRADIO is not set
+
+#
+# IrDA (infrared) support
+#
+# CONFIG_IRDA is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN_BOOL is not set
+
+#
+# Graphics support
+#
+# CONFIG_FB is not set
+
+#
+# Old CD-ROM drivers (not SCSI, not IDE)
+#
+# CONFIG_CD_NO_IDESCSI is not set
+
+#
+# Input device support
+#
+# CONFIG_INPUT is not set
+
+#
+# Userland interfaces
+#
+
+#
+# Input I/O drivers
+#
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+# CONFIG_SERIO is not set
+
+#
+# Input Device Drivers
+#
+
+#
+# Macintosh device drivers
+#
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_SERIAL_CPM=y
+CONFIG_SERIAL_CPM_CONSOLE=y
+# CONFIG_SERIAL_CPM_SCC1 is not set
+# CONFIG_SERIAL_CPM_SCC2 is not set
+# CONFIG_SERIAL_CPM_SCC3 is not set
+# CONFIG_SERIAL_CPM_SCC4 is not set
+CONFIG_SERIAL_CPM_SMC1=y
+CONFIG_SERIAL_CPM_SMC2=y
+CONFIG_UNIX98_PTYS=y
+# CONFIG_LEGACY_PTYS is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# I2C Hardware Sensors Mainboard support
+#
+
+#
+# I2C Hardware Sensors Chip support
+#
+# CONFIG_I2C_SENSOR is not set
+
+#
+# Mice
+#
+# CONFIG_BUSMOUSE is not set
+# CONFIG_QIC02_TAPE is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_NVRAM is not set
+CONFIG_GEN_RTC=y
+# CONFIG_GEN_RTC_X is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_FTAPE is not set
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_HANGCHECK_TIMER is not set
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_FS_XATTR=y
+# CONFIG_EXT3_FS_POSIX_ACL is not set
+# CONFIG_EXT3_FS_SECURITY is not set
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+CONFIG_FS_MBCACHE=y
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_FAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+# CONFIG_DEVFS_FS is not set
+CONFIG_DEVPTS_FS=y
+# CONFIG_DEVPTS_FS_XATTR is not set
+CONFIG_TMPFS=y
+CONFIG_RAMFS=y
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+# CONFIG_NFS_V3 is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFSD is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+# CONFIG_EXPORTFS is not set
+CONFIG_SUNRPC=y
+# CONFIG_SUNRPC_GSS is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_INTERMEZZO_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
+# CONFIG_MSDOS_PARTITION is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_NEC98_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_EFI_PARTITION is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# MPC8xx CPM Options
+#
+CONFIG_SCC_ENET=y
+# CONFIG_SCC1_ENET is not set
+CONFIG_SCC2_ENET=y
+# CONFIG_SCC3_ENET is not set
+# CONFIG_FEC_ENET is not set
+# CONFIG_ENET_BIG_BUFFERS is not set
+
+#
+# Generic MPC8xx Options
+#
+CONFIG_8xx_COPYBACK=y
+# CONFIG_8xx_CPU6 is not set
+# CONFIG_UCODE_PATCH is not set
+
+#
+# USB support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# Bluetooth support
+#
+# CONFIG_BT is not set
+
+#
+# Library routines
+#
+# CONFIG_CRC32 is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_DEBUG_KERNEL is not set
+# CONFIG_KALLSYMS is not set
+
+#
+# Security options
+#
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
diff --git a/arch/ppc/configs/bubinga_defconfig b/arch/ppc/configs/bubinga_defconfig
new file mode 100644
index 0000000..ebec801
--- /dev/null
+++ b/arch/ppc/configs/bubinga_defconfig
@@ -0,0 +1,592 @@
+#
+# Automatically generated make config: don't edit
+#
+CONFIG_MMU=y
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_HAVE_DEC_LOCK=y
+CONFIG_PPC=y
+CONFIG_PPC32=y
+CONFIG_GENERIC_NVRAM=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=y
+# CONFIG_STANDALONE is not set
+CONFIG_BROKEN_ON_SMP=y
+
+#
+# General setup
+#
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_HOTPLUG is not set
+# CONFIG_IKCONFIG is not set
+CONFIG_EMBEDDED=y
+# CONFIG_KALLSYMS is not set
+CONFIG_FUTEX=y
+# CONFIG_EPOLL is not set
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_OBSOLETE_MODPARM=y
+# CONFIG_MODVERSIONS is not set
+CONFIG_KMOD=y
+
+#
+# Processor
+#
+# CONFIG_6xx is not set
+CONFIG_40x=y
+# CONFIG_44x is not set
+# CONFIG_POWER3 is not set
+# CONFIG_POWER4 is not set
+# CONFIG_8xx is not set
+# CONFIG_MATH_EMULATION is not set
+# CONFIG_CPU_FREQ is not set
+CONFIG_4xx=y
+
+#
+# IBM 4xx options
+#
+# CONFIG_ASH is not set
+CONFIG_BUBINGA=y
+# CONFIG_CPCI405 is not set
+# CONFIG_EP405 is not set
+# CONFIG_OAK is not set
+# CONFIG_REDWOOD_5 is not set
+# CONFIG_REDWOOD_6 is not set
+# CONFIG_SYCAMORE is not set
+# CONFIG_WALNUT is not set
+CONFIG_IBM405_ERR77=y
+CONFIG_IBM405_ERR51=y
+CONFIG_IBM_OCP=y
+CONFIG_BIOS_FIXUP=y
+CONFIG_405EP=y
+CONFIG_IBM_OPENBIOS=y
+# CONFIG_PM is not set
+CONFIG_UART0_TTYS0=y
+# CONFIG_UART0_TTYS1 is not set
+CONFIG_NOT_COHERENT_CACHE=y
+
+#
+# Platform options
+#
+# CONFIG_PC_KEYBOARD is not set
+# CONFIG_SMP is not set
+# CONFIG_PREEMPT is not set
+# CONFIG_HIGHMEM is not set
+CONFIG_KERNEL_ELF=y
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+# CONFIG_CMDLINE_BOOL is not set
+
+#
+# Bus options
+#
+CONFIG_PCI=y
+CONFIG_PCI_DOMAINS=y
+CONFIG_PCI_LEGACY_PROC=y
+# CONFIG_PCI_NAMES is not set
+
+#
+# Advanced setup
+#
+# CONFIG_ADVANCED_OPTIONS is not set
+
+#
+# Default settings for advanced configuration options are used
+#
+CONFIG_HIGHMEM_START=0xfe000000
+CONFIG_LOWMEM_SIZE=0x30000000
+CONFIG_KERNEL_START=0xc0000000
+CONFIG_TASK_SIZE=0x80000000
+CONFIG_BOOT_LOAD=0x00400000
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_CARMEL is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=4096
+CONFIG_BLK_DEV_INITRD=y
+# CONFIG_LBD is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_SCSI is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+# CONFIG_FUSION is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# Macintosh device drivers
+#
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+# CONFIG_PACKET is not set
+# CONFIG_NETLINK_DEV is not set
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_PNP=y
+# CONFIG_IP_PNP_DHCP is not set
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_IP_MROUTE is not set
+# CONFIG_ARPD is not set
+CONFIG_SYN_COOKIES=y
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_IPV6 is not set
+# CONFIG_DECNET is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_NETFILTER is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+# CONFIG_ATM is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_HW_FLOWCONTROL is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+CONFIG_NETDEVICES=y
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_OAKNET is not set
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_NET_VENDOR_3COM is not set
+
+#
+# Tulip family network device support
+#
+# CONFIG_NET_TULIP is not set
+# CONFIG_HP100 is not set
+# CONFIG_NET_PCI is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_E1000 is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
+# CONFIG_SIS190 is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_TIGON3 is not set
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_IXGB is not set
+CONFIG_IBM_EMAC=y
+# CONFIG_IBM_EMAC_ERRMSG is not set
+CONFIG_IBM_EMAC_RXB=64
+CONFIG_IBM_EMAC_TXB=8
+CONFIG_IBM_EMAC_FGAP=8
+CONFIG_IBM_EMAC_SKBRES=0
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+# CONFIG_RCPCI is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+
+#
+# Amateur Radio support
+#
+# CONFIG_HAMRADIO is not set
+
+#
+# IrDA (infrared) support
+#
+# CONFIG_IRDA is not set
+
+#
+# Bluetooth support
+#
+# CONFIG_BT is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input I/O drivers
+#
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+CONFIG_SERIO=y
+# CONFIG_SERIO_I8042 is not set
+# CONFIG_SERIO_SERPORT is not set
+# CONFIG_SERIO_CT82C710 is not set
+# CONFIG_SERIO_PCIPS2 is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Character devices
+#
+# CONFIG_VT is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=4
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_QIC02_TAPE is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_NVRAM is not set
+# CONFIG_GEN_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_FTAPE is not set
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# Misc devices
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+# CONFIG_FB is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+# CONFIG_USB is not set
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_JBD is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_FAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+# CONFIG_DEVFS_FS is not set
+# CONFIG_DEVPTS_FS_XATTR is not set
+CONFIG_TMPFS=y
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+# CONFIG_NFS_V3 is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+# CONFIG_NFSD is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+# CONFIG_EXPORTFS is not set
+CONFIG_SUNRPC=y
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_INTERMEZZO_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
+# CONFIG_MSDOS_PARTITION is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_NEC98_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_EFI_PARTITION is not set
+
+#
+# Native Language Support
+#
+# CONFIG_NLS is not set
+
+#
+# IBM 40x options
+#
+
+#
+# Library routines
+#
+CONFIG_CRC32=y
+
+#
+# Kernel hacking
+#
+# CONFIG_DEBUG_KERNEL is not set
+# CONFIG_SERIAL_TEXT_DEBUG is not set
+CONFIG_PPC_OCP=y
+
+#
+# Security options
+#
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
diff --git a/arch/ppc/configs/cedar_defconfig b/arch/ppc/configs/cedar_defconfig
new file mode 100644
index 0000000..5de8288
--- /dev/null
+++ b/arch/ppc/configs/cedar_defconfig
@@ -0,0 +1,534 @@
+#
+# Automatically generated make config: don't edit
+#
+CONFIG_MMU=y
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_HAVE_DEC_LOCK=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+
+#
+# General setup
+#
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_EMBEDDED=y
+CONFIG_FUTEX=y
+# CONFIG_EPOLL is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_OBSOLETE_MODPARM=y
+# CONFIG_MODVERSIONS is not set
+CONFIG_KMOD=y
+
+#
+# Platform support
+#
+CONFIG_PPC=y
+CONFIG_PPC32=y
+# CONFIG_6xx is not set
+CONFIG_40x=y
+# CONFIG_POWER3 is not set
+# CONFIG_8xx is not set
+CONFIG_4xx=y
+
+#
+# IBM 4xx options
+#
+# CONFIG_ASH is not set
+# CONFIG_BEECH is not set
+CONFIG_CEDAR=y
+# CONFIG_CPCI405 is not set
+# CONFIG_EP405 is not set
+# CONFIG_OAK is not set
+# CONFIG_REDWOOD_4 is not set
+# CONFIG_REDWOOD_5 is not set
+# CONFIG_REDWOOD_6 is not set
+# CONFIG_SYCAMORE is not set
+# CONFIG_TIVO is not set
+# CONFIG_WALNUT is not set
+CONFIG_IBM405_ERR77=y
+CONFIG_IBM405_ERR51=y
+CONFIG_IBM_OCP=y
+CONFIG_NP405L=y
+CONFIG_BIOS_FIXUP=y
+CONFIG_IBM_OPENBIOS=y
+# CONFIG_405_DMA is not set
+# CONFIG_PM is not set
+CONFIG_UART0_TTYS0=y
+# CONFIG_UART0_TTYS1 is not set
+CONFIG_NOT_COHERENT_CACHE=y
+# CONFIG_SMP is not set
+# CONFIG_PREEMPT is not set
+# CONFIG_MATH_EMULATION is not set
+# CONFIG_CPU_FREQ is not set
+
+#
+# General setup
+#
+# CONFIG_HIGHMEM is not set
+# CONFIG_PCI is not set
+# CONFIG_PCI_DOMAINS is not set
+# CONFIG_PC_KEYBOARD is not set
+CONFIG_KCORE_ELF=y
+CONFIG_BINFMT_ELF=y
+CONFIG_KERNEL_ELF=y
+# CONFIG_BINFMT_MISC is not set
+# CONFIG_HOTPLUG is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+# CONFIG_CMDLINE_BOOL is not set
+
+#
+# Advanced setup
+#
+# CONFIG_ADVANCED_OPTIONS is not set
+
+#
+# Default settings for advanced configuration options are used
+#
+CONFIG_HIGHMEM_START=0xfe000000
+CONFIG_LOWMEM_SIZE=0x30000000
+CONFIG_KERNEL_START=0xc0000000
+CONFIG_TASK_SIZE=0x80000000
+CONFIG_BOOT_LOAD=0x00400000
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Plug and Play support
+#
+# CONFIG_PNP is not set
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_NBD is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=4096
+CONFIG_BLK_DEV_INITRD=y
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# ATA/IDE/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI support
+#
+# CONFIG_SCSI is not set
+
+#
+# Fusion MPT device support
+#
+
+#
+# I2O device support
+#
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+# CONFIG_PACKET is not set
+# CONFIG_NETLINK_DEV is not set
+# CONFIG_NETFILTER is not set
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+CONFIG_IP_PNP_RARP=y
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_IP_MROUTE is not set
+# CONFIG_ARPD is not set
+# CONFIG_INET_ECN is not set
+CONFIG_SYN_COOKIES=y
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_IPV6 is not set
+# CONFIG_XFRM_USER is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+CONFIG_IPV6_SCTP__=y
+# CONFIG_IP_SCTP is not set
+# CONFIG_ATM is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_LLC is not set
+# CONFIG_DECNET is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_HW_FLOWCONTROL is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_ETHERTAP is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+# CONFIG_NET_ETHERNET is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Token Ring devices (depends on LLC=y)
+#
+# CONFIG_SHAPER is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+
+#
+# Amateur Radio support
+#
+# CONFIG_HAMRADIO is not set
+
+#
+# IrDA (infrared) support
+#
+# CONFIG_IRDA is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN_BOOL is not set
+
+#
+# Graphics support
+#
+# CONFIG_FB is not set
+
+#
+# Old CD-ROM drivers (not SCSI, not IDE)
+#
+# CONFIG_CD_NO_IDESCSI is not set
+
+#
+# Input device support
+#
+# CONFIG_INPUT is not set
+
+#
+# Userland interfaces
+#
+
+#
+# Input I/O drivers
+#
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+# CONFIG_SERIO is not set
+
+#
+# Input Device Drivers
+#
+
+#
+# Macintosh device drivers
+#
+
+#
+# Character devices
+#
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_UNIX98_PTY_COUNT=256
+
+#
+# I2C support
+#
+CONFIG_I2C=y
+# CONFIG_I2C_ALGOBIT is not set
+# CONFIG_I2C_ALGOPCF is not set
+CONFIG_I2C_IBM_OCP_ALGO=y
+CONFIG_I2C_IBM_OCP_ADAP=y
+# CONFIG_I2C_CHARDEV is not set
+
+#
+# I2C Hardware Sensors Mainboard support
+#
+# CONFIG_I2C_AMD756 is not set
+# CONFIG_I2C_AMD8111 is not set
+
+#
+# I2C Hardware Sensors Chip support
+#
+# CONFIG_SENSORS_ADM1021 is not set
+# CONFIG_SENSORS_IT87 is not set
+# CONFIG_SENSORS_LM75 is not set
+# CONFIG_SENSORS_LM85 is not set
+# CONFIG_SENSORS_VIA686A is not set
+# CONFIG_SENSORS_W83781D is not set
+# CONFIG_I2C_SENSOR is not set
+
+#
+# Mice
+#
+# CONFIG_BUSMOUSE is not set
+# CONFIG_QIC02_TAPE is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+CONFIG_WATCHDOG=y
+# CONFIG_WATCHDOG_NOWAYOUT is not set
+# CONFIG_SOFT_WATCHDOG is not set
+# CONFIG_WDT is not set
+# CONFIG_WDTPCI is not set
+# CONFIG_PCWATCHDOG is not set
+# CONFIG_ACQUIRE_WDT is not set
+# CONFIG_ADVANTECH_WDT is not set
+# CONFIG_EUROTECH_WDT is not set
+# CONFIG_IB700_WDT is not set
+# CONFIG_MIXCOMWD is not set
+# CONFIG_SCx200_WDT is not set
+# CONFIG_60XX_WDT is not set
+# CONFIG_W83877F_WDT is not set
+# CONFIG_MACHZ_WDT is not set
+# CONFIG_SC520_WDT is not set
+# CONFIG_AMD7XX_TCO is not set
+# CONFIG_ALIM7101_WDT is not set
+# CONFIG_SC1200_WDT is not set
+# CONFIG_WAFER_WDT is not set
+# CONFIG_CPU5_WDT is not set
+# CONFIG_NVRAM is not set
+# CONFIG_GEN_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_FTAPE is not set
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_HANGCHECK_TIMER is not set
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_JBD is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_FAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+# CONFIG_DEVFS_FS is not set
+CONFIG_DEVPTS_FS=y
+# CONFIG_DEVPTS_FS_XATTR is not set
+CONFIG_TMPFS=y
+CONFIG_RAMFS=y
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+# CONFIG_NFS_V3 is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFSD is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+# CONFIG_EXPORTFS is not set
+CONFIG_SUNRPC=y
+# CONFIG_SUNRPC_GSS is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_INTERMEZZO_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
+# CONFIG_MSDOS_PARTITION is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_NEC98_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_EFI_PARTITION is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# IBM 40x options
+#
+
+#
+# USB support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# Bluetooth support
+#
+# CONFIG_BT is not set
+
+#
+# Library routines
+#
+CONFIG_CRC32=y
+
+#
+# Kernel hacking
+#
+# CONFIG_DEBUG_KERNEL is not set
+# CONFIG_KALLSYMS is not set
+# CONFIG_SERIAL_TEXT_DEBUG is not set
+CONFIG_OCP=y
+
+#
+# Security options
+#
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
diff --git a/arch/ppc/configs/chestnut_defconfig b/arch/ppc/configs/chestnut_defconfig
new file mode 100644
index 0000000..e219aad
--- /dev/null
+++ b/arch/ppc/configs/chestnut_defconfig
@@ -0,0 +1,794 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.11
+# Fri Mar 11 14:32:49 2005
+#
+CONFIG_MMU=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_HAVE_DEC_LOCK=y
+CONFIG_PPC=y
+CONFIG_PPC32=y
+CONFIG_GENERIC_NVRAM=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=y
+CONFIG_BROKEN_ON_SMP=y
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_HOTPLUG is not set
+CONFIG_KOBJECT_UEVENT=y
+# CONFIG_IKCONFIG is not set
+# CONFIG_EMBEDDED is not set
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SHMEM=y
+CONFIG_CC_ALIGN_FUNCTIONS=0
+CONFIG_CC_ALIGN_LABELS=0
+CONFIG_CC_ALIGN_LOOPS=0
+CONFIG_CC_ALIGN_JUMPS=0
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_OBSOLETE_MODPARM=y
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_KMOD=y
+
+#
+# Processor
+#
+CONFIG_6xx=y
+# CONFIG_40x is not set
+# CONFIG_44x is not set
+# CONFIG_POWER3 is not set
+# CONFIG_POWER4 is not set
+# CONFIG_8xx is not set
+# CONFIG_E500 is not set
+CONFIG_ALTIVEC=y
+# CONFIG_TAU is not set
+# CONFIG_CPU_FREQ is not set
+CONFIG_PPC_GEN550=y
+CONFIG_PPC_STD_MMU=y
+CONFIG_NOT_COHERENT_CACHE=y
+
+#
+# Platform options
+#
+# CONFIG_PPC_MULTIPLATFORM is not set
+# CONFIG_APUS is not set
+# CONFIG_KATANA is not set
+# CONFIG_WILLOW is not set
+# CONFIG_CPCI690 is not set
+# CONFIG_PCORE is not set
+# CONFIG_POWERPMC250 is not set
+CONFIG_CHESTNUT=y
+# CONFIG_SPRUCE is not set
+# CONFIG_EV64260 is not set
+# CONFIG_LOPEC is not set
+# CONFIG_MCPN765 is not set
+# CONFIG_MVME5100 is not set
+# CONFIG_PPLUS is not set
+# CONFIG_PRPMC750 is not set
+# CONFIG_PRPMC800 is not set
+# CONFIG_SANDPOINT is not set
+# CONFIG_RADSTONE_PPC7D is not set
+# CONFIG_ADIR is not set
+# CONFIG_K2 is not set
+# CONFIG_PAL4 is not set
+# CONFIG_GEMINI is not set
+# CONFIG_EST8260 is not set
+# CONFIG_SBC82xx is not set
+# CONFIG_SBS8260 is not set
+# CONFIG_RPX8260 is not set
+# CONFIG_TQM8260 is not set
+# CONFIG_ADS8272 is not set
+# CONFIG_PQ2FADS is not set
+# CONFIG_LITE5200 is not set
+# CONFIG_MPC834x_SYS is not set
+CONFIG_MV64360=y
+CONFIG_MV64X60=y
+
+#
+# Set bridge options
+#
+CONFIG_MV64X60_BASE=0xf1000000
+CONFIG_MV64X60_NEW_BASE=0xf1000000
+# CONFIG_SMP is not set
+# CONFIG_PREEMPT is not set
+# CONFIG_HIGHMEM is not set
+CONFIG_BINFMT_ELF=y
+CONFIG_BINFMT_MISC=y
+CONFIG_CMDLINE_BOOL=y
+CONFIG_CMDLINE="console=ttyS0,115200 ip=on"
+
+#
+# Bus options
+#
+CONFIG_GENERIC_ISA_DMA=y
+CONFIG_PCI=y
+CONFIG_PCI_DOMAINS=y
+CONFIG_PCI_LEGACY_PROC=y
+CONFIG_PCI_NAMES=y
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# PC-card bridges
+#
+
+#
+# Advanced setup
+#
+CONFIG_ADVANCED_OPTIONS=y
+CONFIG_HIGHMEM_START=0xfe000000
+# CONFIG_LOWMEM_SIZE_BOOL is not set
+CONFIG_LOWMEM_SIZE=0x30000000
+# CONFIG_KERNEL_START_BOOL is not set
+CONFIG_KERNEL_START=0xc0000000
+# CONFIG_TASK_SIZE_BOOL is not set
+CONFIG_TASK_SIZE=0x80000000
+# CONFIG_CONSISTENT_START_BOOL is not set
+CONFIG_CONSISTENT_START=0xff100000
+# CONFIG_CONSISTENT_SIZE_BOOL is not set
+CONFIG_CONSISTENT_SIZE=0x00200000
+# CONFIG_BOOT_LOAD_BOOL is not set
+CONFIG_BOOT_LOAD=0x00800000
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_CONCAT is not set
+# CONFIG_MTD_REDBOOT_PARTS is not set
+# CONFIG_MTD_CMDLINE_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=y
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_GEN_PROBE=y
+# CONFIG_MTD_CFI_ADV_OPTIONS is not set
+# CONFIG_MTD_CFI_NOSWAP is not set
+# CONFIG_MTD_CFI_BE_BYTE_SWAP is not set
+# CONFIG_MTD_CFI_LE_BYTE_SWAP is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+CONFIG_MTD_CFI_INTELEXT=y
+# CONFIG_MTD_CFI_AMDSTD is not set
+# CONFIG_MTD_CFI_STAA is not set
+CONFIG_MTD_CFI_UTIL=y
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+# CONFIG_MTD_XIP is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+CONFIG_MTD_PHYSMAP=y
+CONFIG_MTD_PHYSMAP_START=0xfc000000
+CONFIG_MTD_PHYSMAP_LEN=0x02000000
+CONFIG_MTD_PHYSMAP_BANKWIDTH=4
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_PMC551 is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLKMTD is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+
+#
+# NAND Flash Device Drivers
+#
+# CONFIG_MTD_NAND is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_SX8 is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=4096
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_LBD is not set
+# CONFIG_CDROM_PKTCDVD is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_SCSI is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# Macintosh device drivers
+#
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+# CONFIG_NETLINK_DEV is not set
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+# CONFIG_IP_PNP_BOOTP is not set
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_IP_MROUTE is not set
+# CONFIG_ARPD is not set
+CONFIG_SYN_COOKIES=y
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_IP_TCPDIAG=y
+# CONFIG_IP_TCPDIAG_IPV6 is not set
+# CONFIG_IPV6 is not set
+# CONFIG_NETFILTER is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_NET_VENDOR_3COM is not set
+
+#
+# Tulip family network device support
+#
+CONFIG_NET_TULIP=y
+# CONFIG_DE2104X is not set
+CONFIG_TULIP=y
+# CONFIG_TULIP_MWI is not set
+CONFIG_TULIP_MMIO=y
+# CONFIG_TULIP_NAPI is not set
+# CONFIG_DE4X5 is not set
+# CONFIG_WINBOND_840 is not set
+# CONFIG_DM9102 is not set
+# CONFIG_HP100 is not set
+CONFIG_NET_PCI=y
+# CONFIG_PCNET32 is not set
+# CONFIG_AMD8111_ETH is not set
+# CONFIG_ADAPTEC_STARFIRE is not set
+# CONFIG_B44 is not set
+# CONFIG_FORCEDETH is not set
+# CONFIG_DGRS is not set
+# CONFIG_EEPRO100 is not set
+CONFIG_E100=y
+# CONFIG_FEALNX is not set
+# CONFIG_NATSEMI is not set
+# CONFIG_NE2K_PCI is not set
+# CONFIG_8139CP is not set
+# CONFIG_8139TOO is not set
+# CONFIG_SIS900 is not set
+# CONFIG_EPIC100 is not set
+# CONFIG_SUNDANCE is not set
+# CONFIG_TLAN is not set
+# CONFIG_VIA_RHINE is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_E1000 is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_VIA_VELOCITY is not set
+# CONFIG_TIGON3 is not set
+CONFIG_MV643XX_ETH=y
+CONFIG_MV643XX_ETH_0=y
+CONFIG_MV643XX_ETH_1=y
+# CONFIG_MV643XX_ETH_2 is not set
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_IXGB is not set
+# CONFIG_S2IO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=2
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+# CONFIG_SERIAL_MPSC is not set
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_NVRAM is not set
+CONFIG_GEN_RTC=y
+# CONFIG_GEN_RTC_X is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
+# Misc devices
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+# CONFIG_FB is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+# CONFIG_USB is not set
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# InfiniBand support
+#
+# CONFIG_INFINIBAND is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_JBD is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+
+#
+# XFS support
+#
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_SYSFS=y
+CONFIG_DEVFS_FS=y
+CONFIG_DEVFS_MOUNT=y
+# CONFIG_DEVFS_DEBUG is not set
+# CONFIG_DEVPTS_FS_XATTR is not set
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_XATTR is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_JFFS_FS is not set
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+# CONFIG_JFFS2_FS_NAND is not set
+# CONFIG_JFFS2_FS_NOR_ECC is not set
+# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+CONFIG_JFFS2_ZLIB=y
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+# CONFIG_NFSD is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_SUNRPC=y
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+# CONFIG_NLS is not set
+
+#
+# Library routines
+#
+# CONFIG_CRC_CCITT is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_DEBUG_KERNEL is not set
+# CONFIG_PRINTK_TIME is not set
+# CONFIG_SERIAL_TEXT_DEBUG is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Hardware crypto devices
+#
diff --git a/arch/ppc/configs/common_defconfig b/arch/ppc/configs/common_defconfig
new file mode 100644
index 0000000..95ead3f
--- /dev/null
+++ b/arch/ppc/configs/common_defconfig
@@ -0,0 +1,1421 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.10-rc2
+# Thu Nov 18 08:22:35 2004
+#
+CONFIG_MMU=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_HAVE_DEC_LOCK=y
+CONFIG_PPC=y
+CONFIG_PPC32=y
+CONFIG_GENERIC_NVRAM=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=y
+CONFIG_BROKEN_ON_SMP=y
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_POSIX_MQUEUE=y
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_HOTPLUG=y
+CONFIG_KOBJECT_UEVENT=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+# CONFIG_EMBEDDED is not set
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SHMEM=y
+CONFIG_CC_ALIGN_FUNCTIONS=0
+CONFIG_CC_ALIGN_LABELS=0
+CONFIG_CC_ALIGN_LOOPS=0
+CONFIG_CC_ALIGN_JUMPS=0
+# CONFIG_TINY_SHMEM is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+CONFIG_OBSOLETE_MODPARM=y
+CONFIG_MODVERSIONS=y
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_KMOD=y
+
+#
+# Processor
+#
+CONFIG_6xx=y
+# CONFIG_40x is not set
+# CONFIG_44x is not set
+# CONFIG_POWER3 is not set
+# CONFIG_POWER4 is not set
+# CONFIG_8xx is not set
+# CONFIG_E500 is not set
+CONFIG_ALTIVEC=y
+CONFIG_TAU=y
+# CONFIG_TAU_INT is not set
+# CONFIG_TAU_AVERAGE is not set
+CONFIG_CPU_FREQ=y
+# CONFIG_CPU_FREQ_DEBUG is not set
+CONFIG_CPU_FREQ_PROC_INTF=y
+CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y
+# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set
+CONFIG_CPU_FREQ_GOV_PERFORMANCE=y
+# CONFIG_CPU_FREQ_GOV_POWERSAVE is not set
+# CONFIG_CPU_FREQ_GOV_USERSPACE is not set
+# CONFIG_CPU_FREQ_GOV_ONDEMAND is not set
+CONFIG_CPU_FREQ_PMAC=y
+CONFIG_CPU_FREQ_TABLE=y
+CONFIG_PPC601_SYNC_FIX=y
+CONFIG_PM=y
+CONFIG_PPC_STD_MMU=y
+
+#
+# Platform options
+#
+CONFIG_PPC_MULTIPLATFORM=y
+# CONFIG_APUS is not set
+# CONFIG_WILLOW is not set
+# CONFIG_PCORE is not set
+# CONFIG_POWERPMC250 is not set
+# CONFIG_EV64260 is not set
+# CONFIG_SPRUCE is not set
+# CONFIG_LOPEC is not set
+# CONFIG_MCPN765 is not set
+# CONFIG_MVME5100 is not set
+# CONFIG_PPLUS is not set
+# CONFIG_PRPMC750 is not set
+# CONFIG_PRPMC800 is not set
+# CONFIG_SANDPOINT is not set
+# CONFIG_ADIR is not set
+# CONFIG_K2 is not set
+# CONFIG_PAL4 is not set
+# CONFIG_GEMINI is not set
+# CONFIG_EST8260 is not set
+# CONFIG_SBC82xx is not set
+# CONFIG_SBS8260 is not set
+# CONFIG_RPX8260 is not set
+# CONFIG_TQM8260 is not set
+# CONFIG_ADS8272 is not set
+# CONFIG_LITE5200 is not set
+CONFIG_PPC_CHRP=y
+CONFIG_PPC_PMAC=y
+CONFIG_PPC_PREP=y
+CONFIG_PPC_OF=y
+CONFIG_PPCBUG_NVRAM=y
+# CONFIG_SMP is not set
+# CONFIG_PREEMPT is not set
+# CONFIG_HIGHMEM is not set
+CONFIG_BINFMT_ELF=y
+CONFIG_BINFMT_MISC=m
+CONFIG_PROC_DEVICETREE=y
+CONFIG_PREP_RESIDUAL=y
+CONFIG_PROC_PREPRESIDUAL=y
+CONFIG_CMDLINE_BOOL=y
+CONFIG_CMDLINE="console=ttyS0,9600 console=tty0 root=/dev/sda2"
+
+#
+# Bus options
+#
+CONFIG_ISA=y
+CONFIG_GENERIC_ISA_DMA=y
+CONFIG_PCI=y
+CONFIG_PCI_DOMAINS=y
+CONFIG_PCI_LEGACY_PROC=y
+CONFIG_PCI_NAMES=y
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# PC-card bridges
+#
+CONFIG_PCMCIA_PROBE=y
+
+#
+# Advanced setup
+#
+# CONFIG_ADVANCED_OPTIONS is not set
+
+#
+# Default settings for advanced configuration options are used
+#
+CONFIG_HIGHMEM_START=0xfe000000
+CONFIG_LOWMEM_SIZE=0x30000000
+CONFIG_KERNEL_START=0xc0000000
+CONFIG_TASK_SIZE=0x80000000
+CONFIG_BOOT_LOAD=0x00800000
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+# CONFIG_STANDALONE is not set
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+# CONFIG_PNP is not set
+
+#
+# Block devices
+#
+CONFIG_BLK_DEV_FD=m
+# CONFIG_MAC_FLOPPY is not set
+# CONFIG_BLK_DEV_XD is not set
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_SX8 is not set
+# CONFIG_BLK_DEV_UB is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=4096
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_LBD=y
+# CONFIG_CDROM_PKTCDVD is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+CONFIG_IDE=y
+CONFIG_BLK_DEV_IDE=y
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+# CONFIG_BLK_DEV_IDE_SATA is not set
+CONFIG_BLK_DEV_IDEDISK=y
+# CONFIG_IDEDISK_MULTI_MODE is not set
+CONFIG_BLK_DEV_IDECD=y
+# CONFIG_BLK_DEV_IDETAPE is not set
+CONFIG_BLK_DEV_IDEFLOPPY=y
+CONFIG_BLK_DEV_IDESCSI=y
+# CONFIG_IDE_TASK_IOCTL is not set
+
+#
+# IDE chipset support/bugfixes
+#
+CONFIG_IDE_GENERIC=y
+CONFIG_BLK_DEV_IDEPCI=y
+CONFIG_IDEPCI_SHARE_IRQ=y
+# CONFIG_BLK_DEV_OFFBOARD is not set
+CONFIG_BLK_DEV_GENERIC=y
+# CONFIG_BLK_DEV_OPTI621 is not set
+CONFIG_BLK_DEV_SL82C105=y
+CONFIG_BLK_DEV_IDEDMA_PCI=y
+# CONFIG_BLK_DEV_IDEDMA_FORCED is not set
+CONFIG_IDEDMA_PCI_AUTO=y
+# CONFIG_IDEDMA_ONLYDISK is not set
+# CONFIG_BLK_DEV_AEC62XX is not set
+# CONFIG_BLK_DEV_ALI15X3 is not set
+# CONFIG_BLK_DEV_AMD74XX is not set
+CONFIG_BLK_DEV_CMD64X=y
+# CONFIG_BLK_DEV_TRIFLEX is not set
+# CONFIG_BLK_DEV_CY82C693 is not set
+# CONFIG_BLK_DEV_CS5520 is not set
+# CONFIG_BLK_DEV_CS5530 is not set
+# CONFIG_BLK_DEV_HPT34X is not set
+# CONFIG_BLK_DEV_HPT366 is not set
+# CONFIG_BLK_DEV_SC1200 is not set
+# CONFIG_BLK_DEV_PIIX is not set
+# CONFIG_BLK_DEV_NS87415 is not set
+# CONFIG_BLK_DEV_PDC202XX_OLD is not set
+CONFIG_BLK_DEV_PDC202XX_NEW=y
+# CONFIG_PDC202XX_FORCE is not set
+# CONFIG_BLK_DEV_SVWKS is not set
+# CONFIG_BLK_DEV_SIIMAGE is not set
+# CONFIG_BLK_DEV_SLC90E66 is not set
+# CONFIG_BLK_DEV_TRM290 is not set
+# CONFIG_BLK_DEV_VIA82CXXX is not set
+CONFIG_BLK_DEV_IDE_PMAC=y
+CONFIG_BLK_DEV_IDE_PMAC_ATA100FIRST=y
+CONFIG_BLK_DEV_IDEDMA_PMAC=y
+CONFIG_BLK_DEV_IDE_PMAC_BLINK=y
+# CONFIG_IDE_ARM is not set
+# CONFIG_IDE_CHIPSETS is not set
+CONFIG_BLK_DEV_IDEDMA=y
+# CONFIG_IDEDMA_IVB is not set
+CONFIG_IDEDMA_AUTO=y
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# SCSI device support
+#
+CONFIG_SCSI=y
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+CONFIG_CHR_DEV_ST=y
+# CONFIG_CHR_DEV_OSST is not set
+CONFIG_BLK_DEV_SR=y
+CONFIG_BLK_DEV_SR_VENDOR=y
+CONFIG_CHR_DEV_SG=y
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+# CONFIG_SCSI_MULTI_LUN is not set
+CONFIG_SCSI_CONSTANTS=y
+# CONFIG_SCSI_LOGGING is not set
+
+#
+# SCSI Transport Attributes
+#
+CONFIG_SCSI_SPI_ATTRS=y
+# CONFIG_SCSI_FC_ATTRS is not set
+
+#
+# SCSI low-level drivers
+#
+# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
+# CONFIG_SCSI_3W_9XXX is not set
+# CONFIG_SCSI_7000FASST is not set
+# CONFIG_SCSI_ACARD is not set
+# CONFIG_SCSI_AHA152X is not set
+# CONFIG_SCSI_AHA1542 is not set
+# CONFIG_SCSI_AACRAID is not set
+CONFIG_SCSI_AIC7XXX=m
+CONFIG_AIC7XXX_CMDS_PER_DEVICE=253
+CONFIG_AIC7XXX_RESET_DELAY_MS=15000
+CONFIG_AIC7XXX_DEBUG_ENABLE=y
+CONFIG_AIC7XXX_DEBUG_MASK=0
+CONFIG_AIC7XXX_REG_PRETTY_PRINT=y
+CONFIG_SCSI_AIC7XXX_OLD=m
+# CONFIG_SCSI_AIC79XX is not set
+# CONFIG_SCSI_DPT_I2O is not set
+# CONFIG_SCSI_IN2000 is not set
+# CONFIG_MEGARAID_NEWGEN is not set
+# CONFIG_MEGARAID_LEGACY is not set
+# CONFIG_SCSI_SATA is not set
+# CONFIG_SCSI_BUSLOGIC is not set
+# CONFIG_SCSI_DMX3191D is not set
+# CONFIG_SCSI_DTC3280 is not set
+# CONFIG_SCSI_EATA is not set
+# CONFIG_SCSI_EATA_PIO is not set
+# CONFIG_SCSI_FUTURE_DOMAIN is not set
+# CONFIG_SCSI_GDTH is not set
+# CONFIG_SCSI_GENERIC_NCR5380 is not set
+# CONFIG_SCSI_GENERIC_NCR5380_MMIO is not set
+# CONFIG_SCSI_IPS is not set
+# CONFIG_SCSI_INITIO is not set
+# CONFIG_SCSI_INIA100 is not set
+# CONFIG_SCSI_NCR53C406A is not set
+CONFIG_SCSI_SYM53C8XX_2=y
+CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=0
+CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16
+CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64
+# CONFIG_SCSI_SYM53C8XX_IOMAPPED is not set
+# CONFIG_SCSI_IPR is not set
+# CONFIG_SCSI_PAS16 is not set
+# CONFIG_SCSI_PSI240I is not set
+# CONFIG_SCSI_QLOGIC_FAS is not set
+# CONFIG_SCSI_QLOGIC_ISP is not set
+# CONFIG_SCSI_QLOGIC_FC is not set
+# CONFIG_SCSI_QLOGIC_1280 is not set
+# CONFIG_SCSI_QLOGIC_1280_1040 is not set
+CONFIG_SCSI_QLA2XXX=y
+# CONFIG_SCSI_QLA21XX is not set
+# CONFIG_SCSI_QLA22XX is not set
+# CONFIG_SCSI_QLA2300 is not set
+# CONFIG_SCSI_QLA2322 is not set
+# CONFIG_SCSI_QLA6312 is not set
+# CONFIG_SCSI_QLA6322 is not set
+# CONFIG_SCSI_SYM53C416 is not set
+# CONFIG_SCSI_DC395x is not set
+# CONFIG_SCSI_DC390T is not set
+# CONFIG_SCSI_T128 is not set
+# CONFIG_SCSI_U14_34F is not set
+# CONFIG_SCSI_NSP32 is not set
+# CONFIG_SCSI_DEBUG is not set
+CONFIG_SCSI_MESH=y
+CONFIG_SCSI_MESH_SYNC_RATE=5
+CONFIG_SCSI_MESH_RESET_DELAY_MS=4000
+CONFIG_SCSI_MAC53C94=y
+
+#
+# Old CD-ROM drivers (not SCSI, not IDE)
+#
+# CONFIG_CD_NO_IDESCSI is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+# CONFIG_FUSION is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# Macintosh device drivers
+#
+CONFIG_ADB=y
+CONFIG_ADB_CUDA=y
+CONFIG_ADB_PMU=y
+CONFIG_PMAC_PBOOK=y
+CONFIG_PMAC_APM_EMU=y
+CONFIG_PMAC_BACKLIGHT=y
+CONFIG_ADB_MACIO=y
+CONFIG_INPUT_ADBHID=y
+CONFIG_MAC_EMUMOUSEBTN=y
+CONFIG_THERM_WINDTUNNEL=m
+CONFIG_THERM_ADT746X=m
+# CONFIG_ANSLCD is not set
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+# CONFIG_NETLINK_DEV is not set
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+# CONFIG_IP_PNP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_IP_MROUTE is not set
+# CONFIG_ARPD is not set
+CONFIG_SYN_COOKIES=y
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_IP_TCPDIAG=y
+# CONFIG_IP_TCPDIAG_IPV6 is not set
+
+#
+# IP: Virtual Server Configuration
+#
+# CONFIG_IP_VS is not set
+# CONFIG_IPV6 is not set
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+
+#
+# IP: Netfilter Configuration
+#
+CONFIG_IP_NF_CONNTRACK=m
+# CONFIG_IP_NF_CT_ACCT is not set
+# CONFIG_IP_NF_CONNTRACK_MARK is not set
+# CONFIG_IP_NF_CT_PROTO_SCTP is not set
+CONFIG_IP_NF_FTP=m
+CONFIG_IP_NF_IRC=m
+CONFIG_IP_NF_TFTP=m
+CONFIG_IP_NF_AMANDA=m
+# CONFIG_IP_NF_QUEUE is not set
+CONFIG_IP_NF_IPTABLES=m
+CONFIG_IP_NF_MATCH_LIMIT=m
+CONFIG_IP_NF_MATCH_IPRANGE=m
+CONFIG_IP_NF_MATCH_MAC=m
+CONFIG_IP_NF_MATCH_PKTTYPE=m
+CONFIG_IP_NF_MATCH_MARK=m
+CONFIG_IP_NF_MATCH_MULTIPORT=m
+CONFIG_IP_NF_MATCH_TOS=m
+CONFIG_IP_NF_MATCH_RECENT=m
+CONFIG_IP_NF_MATCH_ECN=m
+CONFIG_IP_NF_MATCH_DSCP=m
+CONFIG_IP_NF_MATCH_AH_ESP=m
+CONFIG_IP_NF_MATCH_LENGTH=m
+CONFIG_IP_NF_MATCH_TTL=m
+CONFIG_IP_NF_MATCH_TCPMSS=m
+CONFIG_IP_NF_MATCH_HELPER=m
+CONFIG_IP_NF_MATCH_STATE=m
+CONFIG_IP_NF_MATCH_CONNTRACK=m
+CONFIG_IP_NF_MATCH_OWNER=m
+# CONFIG_IP_NF_MATCH_ADDRTYPE is not set
+# CONFIG_IP_NF_MATCH_REALM is not set
+# CONFIG_IP_NF_MATCH_SCTP is not set
+# CONFIG_IP_NF_MATCH_COMMENT is not set
+# CONFIG_IP_NF_MATCH_HASHLIMIT is not set
+CONFIG_IP_NF_FILTER=m
+CONFIG_IP_NF_TARGET_REJECT=m
+# CONFIG_IP_NF_TARGET_LOG is not set
+CONFIG_IP_NF_TARGET_ULOG=m
+CONFIG_IP_NF_TARGET_TCPMSS=m
+CONFIG_IP_NF_NAT=m
+CONFIG_IP_NF_NAT_NEEDED=y
+CONFIG_IP_NF_TARGET_MASQUERADE=m
+CONFIG_IP_NF_TARGET_REDIRECT=m
+CONFIG_IP_NF_TARGET_NETMAP=m
+CONFIG_IP_NF_TARGET_SAME=m
+CONFIG_IP_NF_NAT_SNMP_BASIC=m
+CONFIG_IP_NF_NAT_IRC=m
+CONFIG_IP_NF_NAT_FTP=m
+CONFIG_IP_NF_NAT_TFTP=m
+CONFIG_IP_NF_NAT_AMANDA=m
+# CONFIG_IP_NF_MANGLE is not set
+CONFIG_IP_NF_RAW=m
+CONFIG_IP_NF_TARGET_NOTRACK=m
+# CONFIG_IP_NF_ARPTABLES is not set
+CONFIG_IP_NF_COMPAT_IPCHAINS=m
+# CONFIG_IP_NF_COMPAT_IPFWADM is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+CONFIG_MACE=y
+# CONFIG_MACE_AAUI_PORT is not set
+CONFIG_BMAC=y
+# CONFIG_HAPPYMEAL is not set
+CONFIG_SUNGEM=y
+# CONFIG_NET_VENDOR_3COM is not set
+# CONFIG_LANCE is not set
+# CONFIG_NET_VENDOR_SMC is not set
+# CONFIG_NET_VENDOR_RACAL is not set
+
+#
+# Tulip family network device support
+#
+CONFIG_NET_TULIP=y
+CONFIG_DE2104X=y
+CONFIG_TULIP=y
+# CONFIG_TULIP_MWI is not set
+CONFIG_TULIP_MMIO=y
+# CONFIG_TULIP_NAPI is not set
+CONFIG_DE4X5=m
+# CONFIG_WINBOND_840 is not set
+# CONFIG_DM9102 is not set
+# CONFIG_AT1700 is not set
+# CONFIG_DEPCA is not set
+# CONFIG_HP100 is not set
+# CONFIG_NET_ISA is not set
+CONFIG_NET_PCI=y
+CONFIG_PCNET32=y
+# CONFIG_AMD8111_ETH is not set
+# CONFIG_ADAPTEC_STARFIRE is not set
+# CONFIG_AC3200 is not set
+# CONFIG_APRICOT is not set
+# CONFIG_B44 is not set
+# CONFIG_FORCEDETH is not set
+# CONFIG_CS89x0 is not set
+# CONFIG_DGRS is not set
+# CONFIG_EEPRO100 is not set
+# CONFIG_E100 is not set
+# CONFIG_FEALNX is not set
+# CONFIG_NATSEMI is not set
+# CONFIG_NE2K_PCI is not set
+# CONFIG_8139CP is not set
+# CONFIG_8139TOO is not set
+# CONFIG_SIS900 is not set
+# CONFIG_EPIC100 is not set
+# CONFIG_SUNDANCE is not set
+# CONFIG_TLAN is not set
+# CONFIG_VIA_RHINE is not set
+# CONFIG_NET_POCKET is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_E1000 is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_VIA_VELOCITY is not set
+# CONFIG_TIGON3 is not set
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_IXGB is not set
+# CONFIG_S2IO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+CONFIG_NET_RADIO=y
+
+#
+# Obsolete Wireless cards support (pre-802.11)
+#
+# CONFIG_STRIP is not set
+# CONFIG_ARLAN is not set
+# CONFIG_WAVELAN is not set
+
+#
+# Wireless 802.11b ISA/PCI cards support
+#
+# CONFIG_AIRO is not set
+CONFIG_HERMES=m
+CONFIG_APPLE_AIRPORT=m
+# CONFIG_PLX_HERMES is not set
+# CONFIG_TMD_HERMES is not set
+# CONFIG_PCI_HERMES is not set
+# CONFIG_ATMEL is not set
+
+#
+# Prism GT/Duette 802.11(a/b/g) PCI/Cardbus support
+#
+# CONFIG_PRISM54 is not set
+CONFIG_NET_WIRELESS=y
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+CONFIG_PPP=y
+CONFIG_PPP_MULTILINK=y
+CONFIG_PPP_FILTER=y
+CONFIG_PPP_ASYNC=y
+# CONFIG_PPP_SYNC_TTY is not set
+CONFIG_PPP_DEFLATE=y
+# CONFIG_PPP_BSDCOMP is not set
+# CONFIG_PPPOE is not set
+# CONFIG_SLIP is not set
+# CONFIG_NET_FC is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+CONFIG_INPUT_EVDEV=y
+CONFIG_INPUT_EVBUG=m
+
+#
+# Input I/O drivers
+#
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+CONFIG_SERIO=y
+CONFIG_SERIO_I8042=y
+# CONFIG_SERIO_SERPORT is not set
+# CONFIG_SERIO_CT82C710 is not set
+# CONFIG_SERIO_PCIPS2 is not set
+# CONFIG_SERIO_RAW is not set
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+CONFIG_KEYBOARD_ATKBD=y
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+CONFIG_INPUT_MOUSE=y
+CONFIG_MOUSE_PS2=y
+# CONFIG_MOUSE_SERIAL is not set
+# CONFIG_MOUSE_INPORT is not set
+# CONFIG_MOUSE_LOGIBM is not set
+# CONFIG_MOUSE_PC110PAD is not set
+# CONFIG_MOUSE_VSXXXAA is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+CONFIG_INPUT_MISC=y
+# CONFIG_INPUT_PCSPKR is not set
+CONFIG_INPUT_UINPUT=m
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=m
+CONFIG_SERIAL_8250_NR_UARTS=4
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_PMACZILOG=y
+# CONFIG_SERIAL_PMACZILOG_CONSOLE is not set
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+CONFIG_NVRAM=y
+CONFIG_GEN_RTC=y
+# CONFIG_GEN_RTC_X is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# I2C support
+#
+CONFIG_I2C=y
+CONFIG_I2C_CHARDEV=m
+
+#
+# I2C Algorithms
+#
+CONFIG_I2C_ALGOBIT=y
+# CONFIG_I2C_ALGOPCF is not set
+# CONFIG_I2C_ALGOPCA is not set
+
+#
+# I2C Hardware Bus support
+#
+# CONFIG_I2C_ALI1535 is not set
+# CONFIG_I2C_ALI1563 is not set
+# CONFIG_I2C_ALI15X3 is not set
+# CONFIG_I2C_AMD756 is not set
+# CONFIG_I2C_AMD8111 is not set
+# CONFIG_I2C_ELEKTOR is not set
+CONFIG_I2C_HYDRA=y
+# CONFIG_I2C_I801 is not set
+# CONFIG_I2C_I810 is not set
+# CONFIG_I2C_ISA is not set
+CONFIG_I2C_KEYWEST=m
+# CONFIG_I2C_NFORCE2 is not set
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_PIIX4 is not set
+# CONFIG_I2C_PROSAVAGE is not set
+# CONFIG_I2C_SAVAGE4 is not set
+# CONFIG_SCx200_ACB is not set
+# CONFIG_I2C_SIS5595 is not set
+# CONFIG_I2C_SIS630 is not set
+# CONFIG_I2C_SIS96X is not set
+# CONFIG_I2C_STUB is not set
+# CONFIG_I2C_VIA is not set
+# CONFIG_I2C_VIAPRO is not set
+# CONFIG_I2C_VOODOO3 is not set
+# CONFIG_I2C_PCA_ISA is not set
+
+#
+# Hardware Sensors Chip support
+#
+# CONFIG_I2C_SENSOR is not set
+# CONFIG_SENSORS_ADM1021 is not set
+# CONFIG_SENSORS_ADM1025 is not set
+# CONFIG_SENSORS_ADM1031 is not set
+# CONFIG_SENSORS_ASB100 is not set
+# CONFIG_SENSORS_DS1621 is not set
+# CONFIG_SENSORS_FSCHER is not set
+# CONFIG_SENSORS_GL518SM is not set
+# CONFIG_SENSORS_IT87 is not set
+# CONFIG_SENSORS_LM63 is not set
+# CONFIG_SENSORS_LM75 is not set
+# CONFIG_SENSORS_LM77 is not set
+# CONFIG_SENSORS_LM78 is not set
+# CONFIG_SENSORS_LM80 is not set
+# CONFIG_SENSORS_LM83 is not set
+# CONFIG_SENSORS_LM85 is not set
+# CONFIG_SENSORS_LM87 is not set
+# CONFIG_SENSORS_LM90 is not set
+# CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_PC87360 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_VIA686A is not set
+# CONFIG_SENSORS_W83781D is not set
+# CONFIG_SENSORS_W83L785TS is not set
+# CONFIG_SENSORS_W83627HF is not set
+
+#
+# Other I2C Chip support
+#
+# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_SENSORS_RTC8564 is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
+# Misc devices
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+CONFIG_FB=y
+CONFIG_FB_MODE_HELPERS=y
+# CONFIG_FB_TILEBLITTING is not set
+# CONFIG_FB_CIRRUS is not set
+# CONFIG_FB_PM2 is not set
+# CONFIG_FB_CYBER2000 is not set
+CONFIG_FB_OF=y
+CONFIG_FB_CONTROL=y
+CONFIG_FB_PLATINUM=y
+CONFIG_FB_VALKYRIE=y
+CONFIG_FB_CT65550=y
+# CONFIG_FB_ASILIANT is not set
+CONFIG_FB_IMSTT=y
+# CONFIG_FB_VGA16 is not set
+# CONFIG_FB_RIVA is not set
+CONFIG_FB_MATROX=y
+CONFIG_FB_MATROX_MILLENIUM=y
+CONFIG_FB_MATROX_MYSTIQUE=y
+# CONFIG_FB_MATROX_G450 is not set
+# CONFIG_FB_MATROX_G100A is not set
+CONFIG_FB_MATROX_I2C=y
+# CONFIG_FB_MATROX_MULTIHEAD is not set
+# CONFIG_FB_RADEON_OLD is not set
+CONFIG_FB_RADEON=y
+CONFIG_FB_RADEON_I2C=y
+# CONFIG_FB_RADEON_DEBUG is not set
+CONFIG_FB_ATY128=y
+CONFIG_FB_ATY=y
+CONFIG_FB_ATY_CT=y
+# CONFIG_FB_ATY_GENERIC_LCD is not set
+# CONFIG_FB_ATY_XL_INIT is not set
+CONFIG_FB_ATY_GX=y
+# CONFIG_FB_SAVAGE is not set
+# CONFIG_FB_SIS is not set
+# CONFIG_FB_NEOMAGIC is not set
+# CONFIG_FB_KYRO is not set
+CONFIG_FB_3DFX=y
+# CONFIG_FB_3DFX_ACCEL is not set
+# CONFIG_FB_VOODOO1 is not set
+# CONFIG_FB_TRIDENT is not set
+# CONFIG_FB_VIRTUAL is not set
+
+#
+# Console display driver support
+#
+CONFIG_VGA_CONSOLE=y
+# CONFIG_MDA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+# CONFIG_FONTS is not set
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
+
+#
+# Logo configuration
+#
+CONFIG_LOGO=y
+CONFIG_LOGO_LINUX_MONO=y
+CONFIG_LOGO_LINUX_VGA16=y
+CONFIG_LOGO_LINUX_CLUT224=y
+
+#
+# Sound
+#
+CONFIG_SOUND=m
+CONFIG_DMASOUND_PMAC=m
+CONFIG_DMASOUND=m
+
+#
+# Advanced Linux Sound Architecture
+#
+CONFIG_SND=m
+CONFIG_SND_TIMER=m
+CONFIG_SND_PCM=m
+CONFIG_SND_HWDEP=m
+CONFIG_SND_RAWMIDI=m
+CONFIG_SND_SEQUENCER=m
+# CONFIG_SND_SEQ_DUMMY is not set
+CONFIG_SND_OSSEMUL=y
+CONFIG_SND_MIXER_OSS=m
+CONFIG_SND_PCM_OSS=m
+CONFIG_SND_SEQUENCER_OSS=y
+# CONFIG_SND_VERBOSE_PRINTK is not set
+# CONFIG_SND_DEBUG is not set
+
+#
+# Generic devices
+#
+CONFIG_SND_MPU401_UART=m
+CONFIG_SND_OPL3_LIB=m
+# CONFIG_SND_DUMMY is not set
+# CONFIG_SND_VIRMIDI is not set
+# CONFIG_SND_MTPAV is not set
+# CONFIG_SND_SERIAL_U16550 is not set
+# CONFIG_SND_MPU401 is not set
+
+#
+# ISA devices
+#
+# CONFIG_SND_AD1848 is not set
+# CONFIG_SND_CS4231 is not set
+CONFIG_SND_CS4232=m
+# CONFIG_SND_CS4236 is not set
+# CONFIG_SND_ES1688 is not set
+# CONFIG_SND_ES18XX is not set
+# CONFIG_SND_GUSCLASSIC is not set
+# CONFIG_SND_GUSEXTREME is not set
+# CONFIG_SND_GUSMAX is not set
+# CONFIG_SND_INTERWAVE is not set
+# CONFIG_SND_INTERWAVE_STB is not set
+# CONFIG_SND_OPTI92X_AD1848 is not set
+# CONFIG_SND_OPTI92X_CS4231 is not set
+# CONFIG_SND_OPTI93X is not set
+# CONFIG_SND_SB8 is not set
+# CONFIG_SND_SB16 is not set
+# CONFIG_SND_SBAWE is not set
+# CONFIG_SND_WAVEFRONT is not set
+# CONFIG_SND_CMI8330 is not set
+# CONFIG_SND_OPL3SA2 is not set
+# CONFIG_SND_SGALAXY is not set
+# CONFIG_SND_SSCAPE is not set
+
+#
+# PCI devices
+#
+# CONFIG_SND_ALI5451 is not set
+# CONFIG_SND_ATIIXP is not set
+# CONFIG_SND_ATIIXP_MODEM is not set
+# CONFIG_SND_AU8810 is not set
+# CONFIG_SND_AU8820 is not set
+# CONFIG_SND_AU8830 is not set
+# CONFIG_SND_AZT3328 is not set
+# CONFIG_SND_BT87X is not set
+# CONFIG_SND_CS46XX is not set
+# CONFIG_SND_CS4281 is not set
+# CONFIG_SND_EMU10K1 is not set
+# CONFIG_SND_KORG1212 is not set
+# CONFIG_SND_MIXART is not set
+# CONFIG_SND_NM256 is not set
+# CONFIG_SND_RME32 is not set
+# CONFIG_SND_RME96 is not set
+# CONFIG_SND_RME9652 is not set
+# CONFIG_SND_HDSP is not set
+# CONFIG_SND_TRIDENT is not set
+# CONFIG_SND_YMFPCI is not set
+# CONFIG_SND_ALS4000 is not set
+# CONFIG_SND_CMIPCI is not set
+# CONFIG_SND_ENS1370 is not set
+# CONFIG_SND_ENS1371 is not set
+# CONFIG_SND_ES1938 is not set
+# CONFIG_SND_ES1968 is not set
+# CONFIG_SND_MAESTRO3 is not set
+# CONFIG_SND_FM801 is not set
+# CONFIG_SND_ICE1712 is not set
+# CONFIG_SND_ICE1724 is not set
+# CONFIG_SND_INTEL8X0 is not set
+# CONFIG_SND_INTEL8X0M is not set
+# CONFIG_SND_SONICVIBES is not set
+# CONFIG_SND_VIA82XX is not set
+# CONFIG_SND_VX222 is not set
+
+#
+# ALSA PowerMac devices
+#
+CONFIG_SND_POWERMAC=m
+
+#
+# USB devices
+#
+CONFIG_SND_USB_AUDIO=m
+# CONFIG_SND_USB_USX2Y is not set
+
+#
+# Open Sound System
+#
+# CONFIG_SOUND_PRIME is not set
+
+#
+# USB support
+#
+CONFIG_USB=y
+# CONFIG_USB_DEBUG is not set
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEVICEFS=y
+# CONFIG_USB_BANDWIDTH is not set
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_SUSPEND is not set
+# CONFIG_USB_OTG is not set
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+
+#
+# USB Host Controller Drivers
+#
+# CONFIG_USB_EHCI_HCD is not set
+CONFIG_USB_OHCI_HCD=y
+# CONFIG_USB_UHCI_HCD is not set
+
+#
+# USB Device Class drivers
+#
+# CONFIG_USB_AUDIO is not set
+# CONFIG_USB_BLUETOOTH_TTY is not set
+# CONFIG_USB_MIDI is not set
+CONFIG_USB_ACM=m
+CONFIG_USB_PRINTER=m
+CONFIG_USB_STORAGE=m
+# CONFIG_USB_STORAGE_DEBUG is not set
+# CONFIG_USB_STORAGE_RW_DETECT is not set
+# CONFIG_USB_STORAGE_DATAFAB is not set
+CONFIG_USB_STORAGE_FREECOM=y
+# CONFIG_USB_STORAGE_ISD200 is not set
+CONFIG_USB_STORAGE_DPCM=y
+# CONFIG_USB_STORAGE_HP8200e is not set
+# CONFIG_USB_STORAGE_SDDR09 is not set
+# CONFIG_USB_STORAGE_SDDR55 is not set
+# CONFIG_USB_STORAGE_JUMPSHOT is not set
+
+#
+# USB Input Devices
+#
+CONFIG_USB_HID=y
+CONFIG_USB_HIDINPUT=y
+# CONFIG_HID_FF is not set
+# CONFIG_USB_HIDDEV is not set
+# CONFIG_USB_AIPTEK is not set
+# CONFIG_USB_WACOM is not set
+# CONFIG_USB_KBTAB is not set
+# CONFIG_USB_POWERMATE is not set
+# CONFIG_USB_MTOUCH is not set
+# CONFIG_USB_EGALAX is not set
+# CONFIG_USB_XPAD is not set
+# CONFIG_USB_ATI_REMOTE is not set
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_MICROTEK is not set
+# CONFIG_USB_HPUSBSCSI is not set
+
+#
+# USB Multimedia devices
+#
+# CONFIG_USB_DABUSB is not set
+
+#
+# Video4Linux support is needed for USB Multimedia device support
+#
+
+#
+# USB Network Adapters
+#
+# CONFIG_USB_CATC is not set
+# CONFIG_USB_KAWETH is not set
+# CONFIG_USB_PEGASUS is not set
+# CONFIG_USB_RTL8150 is not set
+# CONFIG_USB_USBNET is not set
+
+#
+# USB port drivers
+#
+
+#
+# USB Serial Converter support
+#
+CONFIG_USB_SERIAL=m
+# CONFIG_USB_SERIAL_GENERIC is not set
+# CONFIG_USB_SERIAL_BELKIN is not set
+# CONFIG_USB_SERIAL_WHITEHEAT is not set
+# CONFIG_USB_SERIAL_DIGI_ACCELEPORT is not set
+# CONFIG_USB_SERIAL_CYPRESS_M8 is not set
+# CONFIG_USB_SERIAL_EMPEG is not set
+# CONFIG_USB_SERIAL_FTDI_SIO is not set
+CONFIG_USB_SERIAL_VISOR=m
+# CONFIG_USB_SERIAL_IPAQ is not set
+# CONFIG_USB_SERIAL_IR is not set
+# CONFIG_USB_SERIAL_EDGEPORT is not set
+# CONFIG_USB_SERIAL_EDGEPORT_TI is not set
+# CONFIG_USB_SERIAL_IPW is not set
+# CONFIG_USB_SERIAL_KEYSPAN_PDA is not set
+CONFIG_USB_SERIAL_KEYSPAN=m
+# CONFIG_USB_SERIAL_KEYSPAN_MPR is not set
+CONFIG_USB_SERIAL_KEYSPAN_USA28=y
+CONFIG_USB_SERIAL_KEYSPAN_USA28X=y
+# CONFIG_USB_SERIAL_KEYSPAN_USA28XA is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA28XB is not set
+CONFIG_USB_SERIAL_KEYSPAN_USA19=y
+CONFIG_USB_SERIAL_KEYSPAN_USA18X=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19W=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19QW=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19QI=y
+CONFIG_USB_SERIAL_KEYSPAN_USA49W=y
+# CONFIG_USB_SERIAL_KEYSPAN_USA49WLC is not set
+# CONFIG_USB_SERIAL_KLSI is not set
+# CONFIG_USB_SERIAL_KOBIL_SCT is not set
+# CONFIG_USB_SERIAL_MCT_U232 is not set
+# CONFIG_USB_SERIAL_PL2303 is not set
+# CONFIG_USB_SERIAL_SAFE is not set
+# CONFIG_USB_SERIAL_CYBERJACK is not set
+# CONFIG_USB_SERIAL_XIRCOM is not set
+# CONFIG_USB_SERIAL_OMNINET is not set
+CONFIG_USB_EZUSB=y
+
+#
+# USB Miscellaneous drivers
+#
+# CONFIG_USB_EMI62 is not set
+# CONFIG_USB_EMI26 is not set
+# CONFIG_USB_TIGL is not set
+# CONFIG_USB_AUERSWALD is not set
+# CONFIG_USB_RIO500 is not set
+# CONFIG_USB_LEGOTOWER is not set
+# CONFIG_USB_LCD is not set
+# CONFIG_USB_LED is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_PHIDGETKIT is not set
+# CONFIG_USB_PHIDGETSERVO is not set
+# CONFIG_USB_TEST is not set
+
+#
+# USB ATM/DSL drivers
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_JBD is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+CONFIG_ISO9660_FS=y
+# CONFIG_JOLIET is not set
+# CONFIG_ZISOFS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=m
+CONFIG_MSDOS_FS=m
+CONFIG_VFAT_FS=m
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_SYSFS=y
+CONFIG_DEVFS_FS=y
+# CONFIG_DEVFS_MOUNT is not set
+# CONFIG_DEVFS_DEBUG is not set
+# CONFIG_DEVPTS_FS_XATTR is not set
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_XATTR is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+CONFIG_HFS_FS=m
+CONFIG_HFSPLUS_FS=m
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+CONFIG_NFSD=y
+CONFIG_NFSD_V3=y
+# CONFIG_NFSD_V4 is not set
+CONFIG_NFSD_TCP=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_EXPORTFS=y
+CONFIG_SUNRPC=y
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+CONFIG_MAC_PARTITION=y
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_BSD_DISKLABEL is not set
+# CONFIG_MINIX_SUBPARTITION is not set
+# CONFIG_SOLARIS_X86_PARTITION is not set
+# CONFIG_UNIXWARE_DISKLABEL is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_EFI_PARTITION is not set
+
+#
+# Native Language Support
+#
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+# CONFIG_NLS_CODEPAGE_437 is not set
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
+CONFIG_NLS_ISO8859_1=m
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_UTF8 is not set
+
+#
+# Library routines
+#
+CONFIG_CRC_CCITT=y
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_DEBUG_KERNEL is not set
+CONFIG_BOOTX_TEXT=y
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
diff --git a/arch/ppc/configs/cpci405_defconfig b/arch/ppc/configs/cpci405_defconfig
new file mode 100644
index 0000000..a336ffa
--- /dev/null
+++ b/arch/ppc/configs/cpci405_defconfig
@@ -0,0 +1,631 @@
+#
+# Automatically generated make config: don't edit
+#
+CONFIG_MMU=y
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_HAVE_DEC_LOCK=y
+CONFIG_PPC=y
+CONFIG_PPC32=y
+CONFIG_GENERIC_NVRAM=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=y
+# CONFIG_STANDALONE is not set
+CONFIG_BROKEN_ON_SMP=y
+
+#
+# General setup
+#
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_HOTPLUG is not set
+# CONFIG_IKCONFIG is not set
+CONFIG_EMBEDDED=y
+# CONFIG_KALLSYMS is not set
+CONFIG_FUTEX=y
+# CONFIG_EPOLL is not set
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_OBSOLETE_MODPARM=y
+# CONFIG_MODVERSIONS is not set
+CONFIG_KMOD=y
+
+#
+# Processor
+#
+# CONFIG_6xx is not set
+CONFIG_40x=y
+# CONFIG_44x is not set
+# CONFIG_POWER3 is not set
+# CONFIG_POWER4 is not set
+# CONFIG_8xx is not set
+# CONFIG_MATH_EMULATION is not set
+# CONFIG_CPU_FREQ is not set
+CONFIG_4xx=y
+
+#
+# IBM 4xx options
+#
+# CONFIG_ASH is not set
+CONFIG_CPCI405=y
+# CONFIG_EP405 is not set
+# CONFIG_EVB405EP is not set
+# CONFIG_OAK is not set
+# CONFIG_REDWOOD_5 is not set
+# CONFIG_REDWOOD_6 is not set
+# CONFIG_SYCAMORE is not set
+# CONFIG_WALNUT is not set
+CONFIG_IBM405_ERR77=y
+CONFIG_IBM405_ERR51=y
+CONFIG_IBM_OCP=y
+CONFIG_PPC_OCP=y
+CONFIG_405GP=y
+# CONFIG_PM is not set
+CONFIG_UART0_TTYS0=y
+# CONFIG_UART0_TTYS1 is not set
+CONFIG_NOT_COHERENT_CACHE=y
+
+#
+# Platform options
+#
+# CONFIG_PC_KEYBOARD is not set
+# CONFIG_SMP is not set
+# CONFIG_PREEMPT is not set
+# CONFIG_HIGHMEM is not set
+CONFIG_KERNEL_ELF=y
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+CONFIG_CMDLINE_BOOL=y
+CONFIG_CMDLINE="ip=on"
+
+#
+# Bus options
+#
+CONFIG_PCI=y
+CONFIG_PCI_DOMAINS=y
+CONFIG_PCI_LEGACY_PROC=y
+# CONFIG_PCI_NAMES is not set
+
+#
+# Advanced setup
+#
+# CONFIG_ADVANCED_OPTIONS is not set
+
+#
+# Default settings for advanced configuration options are used
+#
+CONFIG_HIGHMEM_START=0xfe000000
+CONFIG_LOWMEM_SIZE=0x30000000
+CONFIG_KERNEL_START=0xc0000000
+CONFIG_TASK_SIZE=0x80000000
+CONFIG_BOOT_LOAD=0x00400000
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_CARMEL is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=4096
+CONFIG_BLK_DEV_INITRD=y
+# CONFIG_LBD is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+CONFIG_IDE=y
+CONFIG_BLK_DEV_IDE=y
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+CONFIG_BLK_DEV_IDEDISK=y
+# CONFIG_IDEDISK_MULTI_MODE is not set
+# CONFIG_IDEDISK_STROKE is not set
+# CONFIG_BLK_DEV_IDECD is not set
+# CONFIG_BLK_DEV_IDETAPE is not set
+# CONFIG_BLK_DEV_IDEFLOPPY is not set
+# CONFIG_IDE_TASK_IOCTL is not set
+# CONFIG_IDE_TASKFILE_IO is not set
+
+#
+# IDE chipset support/bugfixes
+#
+CONFIG_IDE_GENERIC=y
+# CONFIG_BLK_DEV_IDEPCI is not set
+# CONFIG_BLK_DEV_IDEDMA is not set
+# CONFIG_IDEDMA_AUTO is not set
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# SCSI device support
+#
+# CONFIG_SCSI is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+# CONFIG_FUSION is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# Macintosh device drivers
+#
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+# CONFIG_PACKET is not set
+# CONFIG_NETLINK_DEV is not set
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_PNP=y
+# CONFIG_IP_PNP_DHCP is not set
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_IP_MROUTE is not set
+# CONFIG_ARPD is not set
+CONFIG_SYN_COOKIES=y
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_IPV6 is not set
+# CONFIG_DECNET is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_NETFILTER is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+# CONFIG_ATM is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_HW_FLOWCONTROL is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+CONFIG_NETDEVICES=y
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+# CONFIG_NET_ETHERNET is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_E1000 is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
+# CONFIG_SIS190 is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_TIGON3 is not set
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_IXGB is not set
+CONFIG_IBM_EMAC=y
+# CONFIG_IBM_EMAC_ERRMSG is not set
+CONFIG_IBM_EMAC_RXB=64
+CONFIG_IBM_EMAC_TXB=8
+CONFIG_IBM_EMAC_FGAP=8
+CONFIG_IBM_EMAC_SKBRES=0
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+# CONFIG_RCPCI is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+
+#
+# Amateur Radio support
+#
+# CONFIG_HAMRADIO is not set
+
+#
+# IrDA (infrared) support
+#
+# CONFIG_IRDA is not set
+
+#
+# Bluetooth support
+#
+# CONFIG_BT is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input I/O drivers
+#
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+CONFIG_SERIO=y
+# CONFIG_SERIO_I8042 is not set
+# CONFIG_SERIO_SERPORT is not set
+# CONFIG_SERIO_CT82C710 is not set
+# CONFIG_SERIO_PCIPS2 is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Character devices
+#
+# CONFIG_VT is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=4
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_UNIX98_PTYS is not set
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_QIC02_TAPE is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_NVRAM is not set
+CONFIG_GEN_RTC=y
+# CONFIG_GEN_RTC_X is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_FTAPE is not set
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# Misc devices
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+# CONFIG_FB is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+# CONFIG_USB is not set
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_JBD is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=y
+CONFIG_MSDOS_FS=y
+# CONFIG_VFAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+# CONFIG_DEVFS_FS is not set
+CONFIG_TMPFS=y
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+# CONFIG_NFSD is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+# CONFIG_EXPORTFS is not set
+CONFIG_SUNRPC=y
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_INTERMEZZO_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+# CONFIG_NLS_CODEPAGE_437 is not set
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+CONFIG_NLS_ISO8859_1=y
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_UTF8 is not set
+
+#
+# IBM 40x options
+#
+
+#
+# Library routines
+#
+CONFIG_CRC32=y
+
+#
+# Kernel hacking
+#
+# CONFIG_DEBUG_KERNEL is not set
+# CONFIG_SERIAL_TEXT_DEBUG is not set
+CONFIG_OCP=y
+
+#
+# Security options
+#
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
diff --git a/arch/ppc/configs/cpci690_defconfig b/arch/ppc/configs/cpci690_defconfig
new file mode 100644
index 0000000..5394879
--- /dev/null
+++ b/arch/ppc/configs/cpci690_defconfig
@@ -0,0 +1,686 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.10-rc2
+# Fri Dec 3 15:56:10 2004
+#
+CONFIG_MMU=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_HAVE_DEC_LOCK=y
+CONFIG_PPC=y
+CONFIG_PPC32=y
+CONFIG_GENERIC_NVRAM=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=y
+CONFIG_BROKEN_ON_SMP=y
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+# CONFIG_SWAP is not set
+CONFIG_SYSVIPC=y
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_HOTPLUG is not set
+CONFIG_KOBJECT_UEVENT=y
+# CONFIG_IKCONFIG is not set
+# CONFIG_EMBEDDED is not set
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SHMEM=y
+CONFIG_CC_ALIGN_FUNCTIONS=0
+CONFIG_CC_ALIGN_LABELS=0
+CONFIG_CC_ALIGN_LOOPS=0
+CONFIG_CC_ALIGN_JUMPS=0
+# CONFIG_TINY_SHMEM is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_OBSOLETE_MODPARM=y
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_KMOD=y
+
+#
+# Processor
+#
+CONFIG_6xx=y
+# CONFIG_40x is not set
+# CONFIG_44x is not set
+# CONFIG_POWER3 is not set
+# CONFIG_POWER4 is not set
+# CONFIG_8xx is not set
+# CONFIG_E500 is not set
+CONFIG_ALTIVEC=y
+# CONFIG_TAU is not set
+# CONFIG_CPU_FREQ is not set
+CONFIG_PPC_STD_MMU=y
+# CONFIG_NOT_COHERENT_CACHE is not set
+
+#
+# Platform options
+#
+# CONFIG_PPC_MULTIPLATFORM is not set
+# CONFIG_APUS is not set
+# CONFIG_KATANA is not set
+# CONFIG_DMV182 is not set
+# CONFIG_WILLOW is not set
+CONFIG_CPCI690=y
+# CONFIG_PCORE is not set
+# CONFIG_POWERPMC250 is not set
+# CONFIG_EV64260 is not set
+# CONFIG_DB64360 is not set
+# CONFIG_CHESTNUT is not set
+# CONFIG_SPRUCE is not set
+# CONFIG_LOPEC is not set
+# CONFIG_MCPN765 is not set
+# CONFIG_MVME5100 is not set
+# CONFIG_PPLUS is not set
+# CONFIG_PRPMC750 is not set
+# CONFIG_PRPMC800 is not set
+# CONFIG_PRPMC880 is not set
+# CONFIG_SANDPOINT is not set
+# CONFIG_ADIR is not set
+# CONFIG_K2 is not set
+# CONFIG_PAL4 is not set
+# CONFIG_GEMINI is not set
+# CONFIG_EST8260 is not set
+# CONFIG_SBC82xx is not set
+# CONFIG_SBS8260 is not set
+# CONFIG_RPX8260 is not set
+# CONFIG_TQM8260 is not set
+# CONFIG_ADS8272 is not set
+# CONFIG_LITE5200 is not set
+
+#
+# Set bridge options
+#
+CONFIG_MV64X60_BASE=0xf1000000
+CONFIG_MV64X60_NEW_BASE=0xf1000000
+CONFIG_GT64260=y
+CONFIG_MV64X60=y
+# CONFIG_SMP is not set
+# CONFIG_PREEMPT is not set
+# CONFIG_HIGHMEM is not set
+CONFIG_BINFMT_ELF=y
+CONFIG_BINFMT_MISC=y
+CONFIG_CMDLINE_BOOL=y
+CONFIG_CMDLINE="console=ttyMM0,9600 ip=on"
+
+#
+# Bus options
+#
+CONFIG_GENERIC_ISA_DMA=y
+CONFIG_PCI=y
+CONFIG_PCI_DOMAINS=y
+CONFIG_PCI_LEGACY_PROC=y
+CONFIG_PCI_NAMES=y
+
+#
+# Advanced setup
+#
+# CONFIG_ADVANCED_OPTIONS is not set
+
+#
+# Default settings for advanced configuration options are used
+#
+CONFIG_HIGHMEM_START=0xfe000000
+CONFIG_LOWMEM_SIZE=0x30000000
+CONFIG_KERNEL_START=0xc0000000
+CONFIG_TASK_SIZE=0x80000000
+CONFIG_BOOT_LOAD=0x00800000
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_SX8 is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=4096
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_LBD is not set
+# CONFIG_CDROM_PKTCDVD is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_SCSI is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# Macintosh device drivers
+#
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+# CONFIG_NETLINK_DEV is not set
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+# CONFIG_IP_PNP_BOOTP is not set
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_IP_MROUTE is not set
+# CONFIG_ARPD is not set
+CONFIG_SYN_COOKIES=y
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_IP_TCPDIAG=y
+# CONFIG_IP_TCPDIAG_IPV6 is not set
+# CONFIG_IPV6 is not set
+# CONFIG_NETFILTER is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_NET_VENDOR_3COM is not set
+
+#
+# Tulip family network device support
+#
+CONFIG_NET_TULIP=y
+# CONFIG_DE2104X is not set
+CONFIG_TULIP=y
+# CONFIG_TULIP_MWI is not set
+# CONFIG_TULIP_MMIO is not set
+# CONFIG_TULIP_NAPI is not set
+# CONFIG_DE4X5 is not set
+# CONFIG_WINBOND_840 is not set
+# CONFIG_DM9102 is not set
+# CONFIG_HP100 is not set
+CONFIG_NET_PCI=y
+# CONFIG_PCNET32 is not set
+# CONFIG_AMD8111_ETH is not set
+# CONFIG_ADAPTEC_STARFIRE is not set
+# CONFIG_B44 is not set
+# CONFIG_FORCEDETH is not set
+# CONFIG_DGRS is not set
+CONFIG_EEPRO100=y
+# CONFIG_EEPRO100_PIO is not set
+# CONFIG_E100 is not set
+# CONFIG_FEALNX is not set
+# CONFIG_NATSEMI is not set
+# CONFIG_NE2K_PCI is not set
+# CONFIG_8139CP is not set
+# CONFIG_8139TOO is not set
+# CONFIG_SIS900 is not set
+# CONFIG_EPIC100 is not set
+# CONFIG_SUNDANCE is not set
+# CONFIG_TLAN is not set
+# CONFIG_VIA_RHINE is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_E1000 is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_VIA_VELOCITY is not set
+# CONFIG_TIGON3 is not set
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_IXGB is not set
+# CONFIG_S2IO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input I/O drivers
+#
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+# CONFIG_SERIO is not set
+# CONFIG_SERIO_I8042 is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_MPSC=y
+CONFIG_SERIAL_MPSC_CONSOLE=y
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_NVRAM is not set
+CONFIG_GEN_RTC=y
+# CONFIG_GEN_RTC_X is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
+# Misc devices
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+# CONFIG_FB is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+# CONFIG_USB is not set
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_JBD is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_SYSFS=y
+CONFIG_DEVFS_FS=y
+# CONFIG_DEVFS_MOUNT is not set
+# CONFIG_DEVFS_DEBUG is not set
+# CONFIG_DEVPTS_FS_XATTR is not set
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_XATTR is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+CONFIG_NFS_V4=y
+# CONFIG_NFS_DIRECTIO is not set
+# CONFIG_NFSD is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+# CONFIG_EXPORTFS is not set
+CONFIG_SUNRPC=y
+CONFIG_SUNRPC_GSS=y
+CONFIG_RPCSEC_GSS_KRB5=y
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+# CONFIG_NLS is not set
+
+#
+# Library routines
+#
+# CONFIG_CRC_CCITT is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_DEBUG_KERNEL is not set
+# CONFIG_SERIAL_TEXT_DEBUG is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+CONFIG_CRYPTO=y
+# CONFIG_CRYPTO_HMAC is not set
+# CONFIG_CRYPTO_NULL is not set
+# CONFIG_CRYPTO_MD4 is not set
+CONFIG_CRYPTO_MD5=y
+# CONFIG_CRYPTO_SHA1 is not set
+# CONFIG_CRYPTO_SHA256 is not set
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_WP512 is not set
+CONFIG_CRYPTO_DES=y
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_AES is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_ARC4 is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_ANUBIS is not set
+# CONFIG_CRYPTO_DEFLATE is not set
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_TEST is not set
diff --git a/arch/ppc/configs/ebony_defconfig b/arch/ppc/configs/ebony_defconfig
new file mode 100644
index 0000000..c8deca3
--- /dev/null
+++ b/arch/ppc/configs/ebony_defconfig
@@ -0,0 +1,585 @@
+#
+# Automatically generated make config: don't edit
+#
+CONFIG_MMU=y
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_HAVE_DEC_LOCK=y
+CONFIG_PPC=y
+CONFIG_PPC32=y
+CONFIG_GENERIC_NVRAM=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=y
+# CONFIG_STANDALONE is not set
+CONFIG_BROKEN_ON_SMP=y
+
+#
+# General setup
+#
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_POSIX_MQUEUE=y
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_HOTPLUG is not set
+# CONFIG_IKCONFIG is not set
+CONFIG_EMBEDDED=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+# CONFIG_MODULE_UNLOAD is not set
+CONFIG_OBSOLETE_MODPARM=y
+# CONFIG_MODVERSIONS is not set
+CONFIG_KMOD=y
+
+#
+# Processor
+#
+# CONFIG_6xx is not set
+# CONFIG_40x is not set
+CONFIG_44x=y
+# CONFIG_POWER3 is not set
+# CONFIG_POWER4 is not set
+# CONFIG_8xx is not set
+# CONFIG_E500 is not set
+CONFIG_BOOKE=y
+CONFIG_PTE_64BIT=y
+# CONFIG_MATH_EMULATION is not set
+# CONFIG_CPU_FREQ is not set
+CONFIG_4xx=y
+
+#
+# IBM 4xx options
+#
+CONFIG_EBONY=y
+# CONFIG_OCOTEA is not set
+CONFIG_440GP=y
+CONFIG_440=y
+CONFIG_IBM_OCP=y
+# CONFIG_PM is not set
+CONFIG_NOT_COHERENT_CACHE=y
+
+#
+# Platform options
+#
+# CONFIG_PC_KEYBOARD is not set
+# CONFIG_SMP is not set
+# CONFIG_PREEMPT is not set
+# CONFIG_HIGHMEM is not set
+CONFIG_KERNEL_ELF=y
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+CONFIG_CMDLINE_BOOL=y
+CONFIG_CMDLINE="ip=on"
+
+#
+# Bus options
+#
+CONFIG_PCI=y
+CONFIG_PCI_DOMAINS=y
+# CONFIG_PCI_LEGACY_PROC is not set
+# CONFIG_PCI_NAMES is not set
+
+#
+# Advanced setup
+#
+# CONFIG_ADVANCED_OPTIONS is not set
+
+#
+# Default settings for advanced configuration options are used
+#
+CONFIG_HIGHMEM_START=0xfe000000
+CONFIG_LOWMEM_SIZE=0x30000000
+CONFIG_KERNEL_START=0xc0000000
+CONFIG_TASK_SIZE=0x80000000
+CONFIG_CONSISTENT_START=0xff100000
+CONFIG_CONSISTENT_SIZE=0x00200000
+CONFIG_BOOT_LOAD=0x01000000
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_DEBUG_DRIVER is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_SX8 is not set
+# CONFIG_BLK_DEV_RAM is not set
+CONFIG_LBD=y
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_SCSI is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# Macintosh device drivers
+#
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+# CONFIG_NETLINK_DEV is not set
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_PNP=y
+# CONFIG_IP_PNP_DHCP is not set
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+
+#
+# IP: Virtual Server Configuration
+#
+# CONFIG_IP_VS is not set
+# CONFIG_IPV6 is not set
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+
+#
+# IP: Netfilter Configuration
+#
+# CONFIG_IP_NF_CONNTRACK is not set
+# CONFIG_IP_NF_QUEUE is not set
+# CONFIG_IP_NF_IPTABLES is not set
+# CONFIG_IP_NF_ARPTABLES is not set
+# CONFIG_IP_NF_COMPAT_IPCHAINS is not set
+# CONFIG_IP_NF_COMPAT_IPFWADM is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_HW_FLOWCONTROL is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+# CONFIG_NET_ETHERNET is not set
+CONFIG_IBM_EMAC=y
+# CONFIG_IBM_EMAC_ERRMSG is not set
+CONFIG_IBM_EMAC_RXB=64
+CONFIG_IBM_EMAC_TXB=8
+CONFIG_IBM_EMAC_FGAP=8
+CONFIG_IBM_EMAC_SKBRES=0
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_E1000 is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_TIGON3 is not set
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_IXGB is not set
+# CONFIG_S2IO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input I/O drivers
+#
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+CONFIG_SERIO=y
+# CONFIG_SERIO_I8042 is not set
+# CONFIG_SERIO_SERPORT is not set
+# CONFIG_SERIO_CT82C710 is not set
+# CONFIG_SERIO_PCIPS2 is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Character devices
+#
+# CONFIG_VT is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=4
+CONFIG_SERIAL_8250_EXTENDED=y
+# CONFIG_SERIAL_8250_MANY_PORTS is not set
+CONFIG_SERIAL_8250_SHARE_IRQ=y
+# CONFIG_SERIAL_8250_DETECT_IRQ is not set
+# CONFIG_SERIAL_8250_MULTIPORT is not set
+# CONFIG_SERIAL_8250_RSA is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_QIC02_TAPE is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_NVRAM is not set
+# CONFIG_GEN_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_FTAPE is not set
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# Misc devices
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+# CONFIG_FB is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+# CONFIG_USB is not set
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# File systems
+#
+# CONFIG_EXT2_FS is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_JBD is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_FAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_SYSFS=y
+# CONFIG_DEVFS_FS is not set
+# CONFIG_DEVPTS_FS_XATTR is not set
+# CONFIG_TMPFS is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+# CONFIG_NFS_V3 is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+# CONFIG_NFSD is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+# CONFIG_EXPORTFS is not set
+CONFIG_SUNRPC=y
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+# CONFIG_NLS is not set
+
+#
+# Library routines
+#
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_DEBUG_SLAB is not set
+# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_KGDB is not set
+# CONFIG_XMON is not set
+CONFIG_BDI_SWITCH=y
+# CONFIG_DEBUG_INFO is not set
+# CONFIG_SERIAL_TEXT_DEBUG is not set
+CONFIG_PPC_OCP=y
+
+#
+# Security options
+#
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
diff --git a/arch/ppc/configs/ep405_defconfig b/arch/ppc/configs/ep405_defconfig
new file mode 100644
index 0000000..880b5f8
--- /dev/null
+++ b/arch/ppc/configs/ep405_defconfig
@@ -0,0 +1,572 @@
+#
+# Automatically generated make config: don't edit
+#
+CONFIG_MMU=y
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_HAVE_DEC_LOCK=y
+CONFIG_PPC=y
+CONFIG_PPC32=y
+CONFIG_GENERIC_NVRAM=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=y
+# CONFIG_STANDALONE is not set
+CONFIG_BROKEN_ON_SMP=y
+
+#
+# General setup
+#
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_POSIX_MQUEUE=y
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_HOTPLUG is not set
+# CONFIG_IKCONFIG is not set
+CONFIG_EMBEDDED=y
+CONFIG_KALLSYMS=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_OBSOLETE_MODPARM=y
+# CONFIG_MODVERSIONS is not set
+CONFIG_KMOD=y
+
+#
+# Processor
+#
+# CONFIG_6xx is not set
+CONFIG_40x=y
+# CONFIG_44x is not set
+# CONFIG_POWER3 is not set
+# CONFIG_POWER4 is not set
+# CONFIG_8xx is not set
+# CONFIG_MATH_EMULATION is not set
+# CONFIG_CPU_FREQ is not set
+CONFIG_4xx=y
+
+#
+# IBM 4xx options
+#
+# CONFIG_ASH is not set
+# CONFIG_BUBINGA is not set
+# CONFIG_CPCI405 is not set
+CONFIG_EP405=y
+# CONFIG_OAK is not set
+# CONFIG_REDWOOD_5 is not set
+# CONFIG_REDWOOD_6 is not set
+# CONFIG_SYCAMORE is not set
+# CONFIG_WALNUT is not set
+# CONFIG_EP405PC is not set
+CONFIG_IBM405_ERR77=y
+CONFIG_IBM405_ERR51=y
+CONFIG_IBM_OCP=y
+CONFIG_BIOS_FIXUP=y
+CONFIG_405GP=y
+CONFIG_EMBEDDEDBOOT=y
+# CONFIG_PM is not set
+CONFIG_UART0_TTYS0=y
+# CONFIG_UART0_TTYS1 is not set
+CONFIG_NOT_COHERENT_CACHE=y
+
+#
+# Platform options
+#
+# CONFIG_PC_KEYBOARD is not set
+# CONFIG_SMP is not set
+# CONFIG_PREEMPT is not set
+# CONFIG_HIGHMEM is not set
+CONFIG_KERNEL_ELF=y
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+CONFIG_CMDLINE_BOOL=y
+CONFIG_CMDLINE="ip=on"
+
+#
+# Bus options
+#
+CONFIG_PCI=y
+CONFIG_PCI_DOMAINS=y
+# CONFIG_PCI_LEGACY_PROC is not set
+# CONFIG_PCI_NAMES is not set
+
+#
+# Advanced setup
+#
+# CONFIG_ADVANCED_OPTIONS is not set
+
+#
+# Default settings for advanced configuration options are used
+#
+CONFIG_HIGHMEM_START=0xfe000000
+CONFIG_LOWMEM_SIZE=0x30000000
+CONFIG_KERNEL_START=0xc0000000
+CONFIG_TASK_SIZE=0x80000000
+CONFIG_BOOT_LOAD=0x00400000
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_CARMEL is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=4096
+CONFIG_BLK_DEV_INITRD=y
+# CONFIG_LBD is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_SCSI is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# Macintosh device drivers
+#
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+# CONFIG_PACKET is not set
+# CONFIG_NETLINK_DEV is not set
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_PNP=y
+# CONFIG_IP_PNP_DHCP is not set
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_IP_MROUTE is not set
+# CONFIG_ARPD is not set
+CONFIG_SYN_COOKIES=y
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_IPV6 is not set
+# CONFIG_NETFILTER is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_HW_FLOWCONTROL is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+# CONFIG_MII is not set
+# CONFIG_OAKNET is not set
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_NET_VENDOR_3COM is not set
+
+#
+# Tulip family network device support
+#
+# CONFIG_NET_TULIP is not set
+# CONFIG_HP100 is not set
+# CONFIG_NET_PCI is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_E1000 is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_TIGON3 is not set
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_IXGB is not set
+# CONFIG_S2IO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_RCPCI is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input I/O drivers
+#
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+CONFIG_SERIO=y
+# CONFIG_SERIO_I8042 is not set
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_CT82C710 is not set
+# CONFIG_SERIO_PCIPS2 is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Character devices
+#
+# CONFIG_VT is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=4
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_QIC02_TAPE is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_NVRAM is not set
+CONFIG_GEN_RTC=y
+# CONFIG_GEN_RTC_X is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_FTAPE is not set
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# Misc devices
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+# CONFIG_FB is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+# CONFIG_USB is not set
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_JBD is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_FAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_SYSFS=y
+# CONFIG_DEVFS_FS is not set
+# CONFIG_DEVPTS_FS_XATTR is not set
+CONFIG_TMPFS=y
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+# CONFIG_NFS_V3 is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+# CONFIG_NFSD is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+# CONFIG_EXPORTFS is not set
+CONFIG_SUNRPC=y
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+# CONFIG_NLS is not set
+
+#
+# IBM 40x options
+#
+
+#
+# Library routines
+#
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_DEBUG_KERNEL is not set
+# CONFIG_SERIAL_TEXT_DEBUG is not set
+CONFIG_PPC_OCP=y
+
+#
+# Security options
+#
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
diff --git a/arch/ppc/configs/est8260_defconfig b/arch/ppc/configs/est8260_defconfig
new file mode 100644
index 0000000..b3f6446
--- /dev/null
+++ b/arch/ppc/configs/est8260_defconfig
@@ -0,0 +1,491 @@
+#
+# Automatically generated make config: don't edit
+#
+CONFIG_MMU=y
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_HAVE_DEC_LOCK=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+
+#
+# General setup
+#
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_EMBEDDED=y
+CONFIG_FUTEX=y
+# CONFIG_EPOLL is not set
+
+#
+# Loadable module support
+#
+# CONFIG_MODULES is not set
+
+#
+# Platform support
+#
+CONFIG_PPC=y
+CONFIG_PPC32=y
+CONFIG_6xx=y
+# CONFIG_40x is not set
+# CONFIG_POWER3 is not set
+# CONFIG_8xx is not set
+
+#
+# IBM 4xx options
+#
+CONFIG_EMBEDDEDBOOT=y
+CONFIG_8260=y
+CONFIG_PPC_STD_MMU=y
+CONFIG_SERIAL_CONSOLE=y
+CONFIG_EST8260=y
+# CONFIG_SBS8260 is not set
+# CONFIG_RPX6 is not set
+# CONFIG_TQM8260 is not set
+# CONFIG_WILLOW_1 is not set
+# CONFIG_SMP is not set
+# CONFIG_PREEMPT is not set
+# CONFIG_CPU_FREQ is not set
+
+#
+# General setup
+#
+# CONFIG_HIGHMEM is not set
+# CONFIG_PCI is not set
+# CONFIG_PCI_DOMAINS is not set
+# CONFIG_PC_KEYBOARD is not set
+CONFIG_KCORE_ELF=y
+CONFIG_BINFMT_ELF=y
+CONFIG_KERNEL_ELF=y
+# CONFIG_BINFMT_MISC is not set
+# CONFIG_HOTPLUG is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+# CONFIG_PPC601_SYNC_FIX is not set
+# CONFIG_CMDLINE_BOOL is not set
+
+#
+# Advanced setup
+#
+# CONFIG_ADVANCED_OPTIONS is not set
+
+#
+# Default settings for advanced configuration options are used
+#
+CONFIG_HIGHMEM_START=0xfe000000
+CONFIG_LOWMEM_SIZE=0x30000000
+CONFIG_KERNEL_START=0xc0000000
+CONFIG_TASK_SIZE=0x80000000
+CONFIG_BOOT_LOAD=0x00400000
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Plug and Play support
+#
+# CONFIG_PNP is not set
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_NBD is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=4096
+CONFIG_BLK_DEV_INITRD=y
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# ATA/IDE/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI support
+#
+# CONFIG_SCSI is not set
+
+#
+# Fusion MPT device support
+#
+
+#
+# I2O device support
+#
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+# CONFIG_NETLINK_DEV is not set
+# CONFIG_NETFILTER is not set
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_IP_MROUTE is not set
+# CONFIG_ARPD is not set
+# CONFIG_INET_ECN is not set
+CONFIG_SYN_COOKIES=y
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_IPV6 is not set
+# CONFIG_XFRM_USER is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+CONFIG_IPV6_SCTP__=y
+# CONFIG_IP_SCTP is not set
+# CONFIG_ATM is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_LLC is not set
+# CONFIG_DECNET is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_HW_FLOWCONTROL is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_ETHERTAP is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+# CONFIG_MII is not set
+# CONFIG_OAKNET is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Token Ring devices (depends on LLC=y)
+#
+# CONFIG_SHAPER is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+
+#
+# Amateur Radio support
+#
+# CONFIG_HAMRADIO is not set
+
+#
+# IrDA (infrared) support
+#
+# CONFIG_IRDA is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN_BOOL is not set
+
+#
+# Graphics support
+#
+# CONFIG_FB is not set
+
+#
+# Old CD-ROM drivers (not SCSI, not IDE)
+#
+# CONFIG_CD_NO_IDESCSI is not set
+
+#
+# Input device support
+#
+# CONFIG_INPUT is not set
+
+#
+# Userland interfaces
+#
+
+#
+# Input I/O drivers
+#
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+# CONFIG_SERIO is not set
+
+#
+# Input Device Drivers
+#
+
+#
+# Macintosh device drivers
+#
+
+#
+# Character devices
+#
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_UNIX98_PTY_COUNT=256
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# I2C Hardware Sensors Mainboard support
+#
+
+#
+# I2C Hardware Sensors Chip support
+#
+# CONFIG_I2C_SENSOR is not set
+
+#
+# Mice
+#
+# CONFIG_BUSMOUSE is not set
+# CONFIG_QIC02_TAPE is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_NVRAM is not set
+CONFIG_GEN_RTC=y
+# CONFIG_GEN_RTC_X is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_FTAPE is not set
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_HANGCHECK_TIMER is not set
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_FS_XATTR=y
+# CONFIG_EXT3_FS_POSIX_ACL is not set
+# CONFIG_EXT3_FS_SECURITY is not set
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+CONFIG_FS_MBCACHE=y
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_FAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+# CONFIG_DEVFS_FS is not set
+CONFIG_DEVPTS_FS=y
+# CONFIG_DEVPTS_FS_XATTR is not set
+CONFIG_TMPFS=y
+CONFIG_RAMFS=y
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+# CONFIG_NFS_V3 is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFSD is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+# CONFIG_EXPORTFS is not set
+CONFIG_SUNRPC=y
+# CONFIG_SUNRPC_GSS is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_INTERMEZZO_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
+# CONFIG_MSDOS_PARTITION is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_NEC98_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_EFI_PARTITION is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+CONFIG_SCC_ENET=y
+# CONFIG_FEC_ENET is not set
+
+#
+# MPC8260 CPM Options
+#
+CONFIG_SCC_CONSOLE=y
+
+#
+# USB support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# Bluetooth support
+#
+# CONFIG_BT is not set
+
+#
+# Library routines
+#
+# CONFIG_CRC32 is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_DEBUG_KERNEL is not set
+# CONFIG_KALLSYMS is not set
+
+#
+# Security options
+#
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
diff --git a/arch/ppc/configs/ev64260_defconfig b/arch/ppc/configs/ev64260_defconfig
new file mode 100644
index 0000000..84cc142
--- /dev/null
+++ b/arch/ppc/configs/ev64260_defconfig
@@ -0,0 +1,759 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.10-rc2
+# Fri Nov 19 11:17:02 2004
+#
+CONFIG_MMU=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_HAVE_DEC_LOCK=y
+CONFIG_PPC=y
+CONFIG_PPC32=y
+CONFIG_GENERIC_NVRAM=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=y
+CONFIG_BROKEN_ON_SMP=y
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_HOTPLUG is not set
+CONFIG_KOBJECT_UEVENT=y
+# CONFIG_IKCONFIG is not set
+# CONFIG_EMBEDDED is not set
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SHMEM=y
+CONFIG_CC_ALIGN_FUNCTIONS=0
+CONFIG_CC_ALIGN_LABELS=0
+CONFIG_CC_ALIGN_LOOPS=0
+CONFIG_CC_ALIGN_JUMPS=0
+# CONFIG_TINY_SHMEM is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_OBSOLETE_MODPARM=y
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_KMOD=y
+
+#
+# Processor
+#
+CONFIG_6xx=y
+# CONFIG_40x is not set
+# CONFIG_44x is not set
+# CONFIG_POWER3 is not set
+# CONFIG_POWER4 is not set
+# CONFIG_8xx is not set
+# CONFIG_E500 is not set
+CONFIG_ALTIVEC=y
+CONFIG_TAU=y
+# CONFIG_TAU_INT is not set
+# CONFIG_TAU_AVERAGE is not set
+# CONFIG_CPU_FREQ is not set
+CONFIG_PPC_GEN550=y
+CONFIG_PPC_STD_MMU=y
+# CONFIG_NOT_COHERENT_CACHE is not set
+
+#
+# Platform options
+#
+# CONFIG_PPC_MULTIPLATFORM is not set
+# CONFIG_APUS is not set
+# CONFIG_WILLOW is not set
+# CONFIG_PCORE is not set
+# CONFIG_POWERPMC250 is not set
+# CONFIG_SPRUCE is not set
+CONFIG_EV64260=y
+# CONFIG_LOPEC is not set
+# CONFIG_MCPN765 is not set
+# CONFIG_MVME5100 is not set
+# CONFIG_PPLUS is not set
+# CONFIG_PRPMC750 is not set
+# CONFIG_PRPMC800 is not set
+# CONFIG_SANDPOINT is not set
+# CONFIG_ADIR is not set
+# CONFIG_K2 is not set
+# CONFIG_PAL4 is not set
+# CONFIG_GEMINI is not set
+# CONFIG_EST8260 is not set
+# CONFIG_SBC82xx is not set
+# CONFIG_SBS8260 is not set
+# CONFIG_RPX8260 is not set
+# CONFIG_TQM8260 is not set
+# CONFIG_ADS8272 is not set
+# CONFIG_LITE5200 is not set
+CONFIG_GT64260=y
+CONFIG_MV64X60=y
+
+#
+# Set bridge options
+#
+CONFIG_MV64X60_BASE=0xf1000000
+CONFIG_MV64X60_NEW_BASE=0xfbe00000
+# CONFIG_SMP is not set
+# CONFIG_PREEMPT is not set
+# CONFIG_HIGHMEM is not set
+CONFIG_BINFMT_ELF=y
+CONFIG_BINFMT_MISC=y
+CONFIG_CMDLINE_BOOL=y
+CONFIG_CMDLINE="console=ttyS0,115200 ip=on"
+
+#
+# Bus options
+#
+CONFIG_GENERIC_ISA_DMA=y
+CONFIG_PCI=y
+CONFIG_PCI_DOMAINS=y
+CONFIG_PCI_LEGACY_PROC=y
+CONFIG_PCI_NAMES=y
+
+#
+# Advanced setup
+#
+# CONFIG_ADVANCED_OPTIONS is not set
+
+#
+# Default settings for advanced configuration options are used
+#
+CONFIG_HIGHMEM_START=0xfe000000
+CONFIG_LOWMEM_SIZE=0x30000000
+CONFIG_KERNEL_START=0xc0000000
+CONFIG_TASK_SIZE=0x80000000
+CONFIG_BOOT_LOAD=0x00800000
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_SX8 is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=4096
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_LBD is not set
+# CONFIG_CDROM_PKTCDVD is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_SCSI is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# Macintosh device drivers
+#
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+# CONFIG_NETLINK_DEV is not set
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+# CONFIG_IP_PNP_BOOTP is not set
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_IP_MROUTE is not set
+# CONFIG_ARPD is not set
+CONFIG_SYN_COOKIES=y
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_IP_TCPDIAG=y
+# CONFIG_IP_TCPDIAG_IPV6 is not set
+
+#
+# IP: Virtual Server Configuration
+#
+# CONFIG_IP_VS is not set
+# CONFIG_IPV6 is not set
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+
+#
+# IP: Netfilter Configuration
+#
+# CONFIG_IP_NF_CONNTRACK is not set
+# CONFIG_IP_NF_CONNTRACK_MARK is not set
+# CONFIG_IP_NF_QUEUE is not set
+# CONFIG_IP_NF_IPTABLES is not set
+# CONFIG_IP_NF_ARPTABLES is not set
+# CONFIG_IP_NF_COMPAT_IPCHAINS is not set
+# CONFIG_IP_NF_COMPAT_IPFWADM is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_NET_VENDOR_3COM is not set
+
+#
+# Tulip family network device support
+#
+CONFIG_NET_TULIP=y
+# CONFIG_DE2104X is not set
+CONFIG_TULIP=y
+# CONFIG_TULIP_MWI is not set
+# CONFIG_TULIP_MMIO is not set
+# CONFIG_TULIP_NAPI is not set
+# CONFIG_DE4X5 is not set
+# CONFIG_WINBOND_840 is not set
+# CONFIG_DM9102 is not set
+# CONFIG_HP100 is not set
+CONFIG_NET_PCI=y
+# CONFIG_PCNET32 is not set
+# CONFIG_AMD8111_ETH is not set
+# CONFIG_ADAPTEC_STARFIRE is not set
+# CONFIG_B44 is not set
+# CONFIG_FORCEDETH is not set
+# CONFIG_DGRS is not set
+# CONFIG_EEPRO100 is not set
+CONFIG_E100=y
+# CONFIG_E100_NAPI is not set
+# CONFIG_FEALNX is not set
+# CONFIG_NATSEMI is not set
+# CONFIG_NE2K_PCI is not set
+# CONFIG_8139CP is not set
+# CONFIG_8139TOO is not set
+# CONFIG_SIS900 is not set
+# CONFIG_EPIC100 is not set
+# CONFIG_SUNDANCE is not set
+# CONFIG_TLAN is not set
+# CONFIG_VIA_RHINE is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_E1000 is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_VIA_VELOCITY is not set
+# CONFIG_TIGON3 is not set
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_IXGB is not set
+# CONFIG_S2IO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input I/O drivers
+#
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+CONFIG_SERIO=y
+CONFIG_SERIO_I8042=y
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_CT82C710 is not set
+# CONFIG_SERIO_PCIPS2 is not set
+# CONFIG_SERIO_RAW is not set
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+CONFIG_KEYBOARD_ATKBD=y
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+CONFIG_INPUT_MOUSE=y
+CONFIG_MOUSE_PS2=y
+# CONFIG_MOUSE_SERIAL is not set
+# CONFIG_MOUSE_VSXXXAA is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=4
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_NVRAM is not set
+CONFIG_GEN_RTC=y
+# CONFIG_GEN_RTC_X is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# I2C support
+#
+CONFIG_I2C=m
+CONFIG_I2C_CHARDEV=m
+
+#
+# I2C Algorithms
+#
+# CONFIG_I2C_ALGOBIT is not set
+# CONFIG_I2C_ALGOPCF is not set
+# CONFIG_I2C_ALGOPCA is not set
+
+#
+# I2C Hardware Bus support
+#
+# CONFIG_I2C_ALI1535 is not set
+# CONFIG_I2C_ALI1563 is not set
+# CONFIG_I2C_ALI15X3 is not set
+# CONFIG_I2C_AMD756 is not set
+# CONFIG_I2C_AMD8111 is not set
+# CONFIG_I2C_I801 is not set
+# CONFIG_I2C_I810 is not set
+# CONFIG_I2C_ISA is not set
+# CONFIG_I2C_NFORCE2 is not set
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_PIIX4 is not set
+# CONFIG_I2C_PROSAVAGE is not set
+# CONFIG_I2C_SAVAGE4 is not set
+# CONFIG_SCx200_ACB is not set
+# CONFIG_I2C_SIS5595 is not set
+# CONFIG_I2C_SIS630 is not set
+# CONFIG_I2C_SIS96X is not set
+# CONFIG_I2C_STUB is not set
+# CONFIG_I2C_VIA is not set
+# CONFIG_I2C_VIAPRO is not set
+# CONFIG_I2C_VOODOO3 is not set
+# CONFIG_I2C_PCA_ISA is not set
+
+#
+# Hardware Sensors Chip support
+#
+# CONFIG_I2C_SENSOR is not set
+# CONFIG_SENSORS_ADM1021 is not set
+# CONFIG_SENSORS_ADM1025 is not set
+# CONFIG_SENSORS_ADM1031 is not set
+# CONFIG_SENSORS_ASB100 is not set
+# CONFIG_SENSORS_DS1621 is not set
+# CONFIG_SENSORS_FSCHER is not set
+# CONFIG_SENSORS_GL518SM is not set
+# CONFIG_SENSORS_IT87 is not set
+# CONFIG_SENSORS_LM63 is not set
+# CONFIG_SENSORS_LM75 is not set
+# CONFIG_SENSORS_LM77 is not set
+# CONFIG_SENSORS_LM78 is not set
+# CONFIG_SENSORS_LM80 is not set
+# CONFIG_SENSORS_LM83 is not set
+# CONFIG_SENSORS_LM85 is not set
+# CONFIG_SENSORS_LM87 is not set
+# CONFIG_SENSORS_LM90 is not set
+# CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_PC87360 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_VIA686A is not set
+# CONFIG_SENSORS_W83781D is not set
+# CONFIG_SENSORS_W83L785TS is not set
+# CONFIG_SENSORS_W83627HF is not set
+
+#
+# Other I2C Chip support
+#
+# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_SENSORS_RTC8564 is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
+# Misc devices
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+# CONFIG_FB is not set
+
+#
+# Console display driver support
+#
+CONFIG_VGA_CONSOLE=y
+CONFIG_DUMMY_CONSOLE=y
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+# CONFIG_USB is not set
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_JBD is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+# CONFIG_PROC_KCORE is not set
+CONFIG_SYSFS=y
+CONFIG_DEVFS_FS=y
+# CONFIG_DEVFS_MOUNT is not set
+# CONFIG_DEVFS_DEBUG is not set
+# CONFIG_DEVPTS_FS_XATTR is not set
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_XATTR is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+# CONFIG_NFSD is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+# CONFIG_EXPORTFS is not set
+CONFIG_SUNRPC=y
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+# CONFIG_NLS is not set
+
+#
+# Library routines
+#
+# CONFIG_CRC_CCITT is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_DEBUG_KERNEL is not set
+# CONFIG_SERIAL_TEXT_DEBUG is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
diff --git a/arch/ppc/configs/gemini_defconfig b/arch/ppc/configs/gemini_defconfig
new file mode 100644
index 0000000..ebcd17b
--- /dev/null
+++ b/arch/ppc/configs/gemini_defconfig
@@ -0,0 +1,618 @@
+#
+# Automatically generated make config: don't edit
+#
+CONFIG_MMU=y
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_HAVE_DEC_LOCK=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+
+#
+# General setup
+#
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_EMBEDDED is not set
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_OBSOLETE_MODPARM=y
+# CONFIG_MODVERSIONS is not set
+CONFIG_KMOD=y
+
+#
+# Platform support
+#
+CONFIG_PPC=y
+CONFIG_PPC32=y
+CONFIG_6xx=y
+# CONFIG_40x is not set
+# CONFIG_POWER3 is not set
+# CONFIG_8xx is not set
+
+#
+# IBM 4xx options
+#
+# CONFIG_8260 is not set
+CONFIG_GENERIC_ISA_DMA=y
+CONFIG_PPC_STD_MMU=y
+# CONFIG_PPC_MULTIPLATFORM is not set
+# CONFIG_APUS is not set
+# CONFIG_WILLOW_2 is not set
+# CONFIG_PCORE is not set
+# CONFIG_POWERPMC250 is not set
+# CONFIG_EV64260 is not set
+# CONFIG_SPRUCE is not set
+# CONFIG_LOPEC is not set
+# CONFIG_MCPN765 is not set
+# CONFIG_MVME5100 is not set
+# CONFIG_PPLUS is not set
+# CONFIG_PRPMC750 is not set
+# CONFIG_PRPMC800 is not set
+# CONFIG_SANDPOINT is not set
+# CONFIG_ADIR is not set
+# CONFIG_K2 is not set
+# CONFIG_PAL4 is not set
+CONFIG_GEMINI=y
+# CONFIG_SMP is not set
+# CONFIG_PREEMPT is not set
+CONFIG_ALTIVEC=y
+CONFIG_TAU=y
+# CONFIG_TAU_INT is not set
+# CONFIG_TAU_AVERAGE is not set
+# CONFIG_CPU_FREQ is not set
+
+#
+# General setup
+#
+# CONFIG_HIGHMEM is not set
+CONFIG_PCI=y
+CONFIG_PCI_DOMAINS=y
+CONFIG_KCORE_ELF=y
+CONFIG_BINFMT_ELF=y
+CONFIG_KERNEL_ELF=y
+# CONFIG_BINFMT_MISC is not set
+CONFIG_PCI_LEGACY_PROC=y
+CONFIG_PCI_NAMES=y
+# CONFIG_HOTPLUG is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+# CONFIG_PPC601_SYNC_FIX is not set
+# CONFIG_CMDLINE_BOOL is not set
+
+#
+# Advanced setup
+#
+# CONFIG_ADVANCED_OPTIONS is not set
+
+#
+# Default settings for advanced configuration options are used
+#
+CONFIG_HIGHMEM_START=0xfe000000
+CONFIG_LOWMEM_SIZE=0x30000000
+CONFIG_KERNEL_START=0xc0000000
+CONFIG_TASK_SIZE=0x80000000
+CONFIG_BOOT_LOAD=0x00800000
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Plug and Play support
+#
+# CONFIG_PNP is not set
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=4096
+CONFIG_BLK_DEV_INITRD=y
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# ATA/IDE/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI support
+#
+CONFIG_SCSI=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+CONFIG_BLK_DEV_SR=y
+CONFIG_BLK_DEV_SR_VENDOR=y
+CONFIG_CHR_DEV_SG=y
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+# CONFIG_SCSI_MULTI_LUN is not set
+# CONFIG_SCSI_REPORT_LUNS is not set
+CONFIG_SCSI_CONSTANTS=y
+# CONFIG_SCSI_LOGGING is not set
+
+#
+# SCSI low-level drivers
+#
+# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
+# CONFIG_SCSI_ACARD is not set
+# CONFIG_SCSI_AACRAID is not set
+# CONFIG_SCSI_AIC7XXX is not set
+# CONFIG_SCSI_AIC7XXX_OLD is not set
+# CONFIG_SCSI_AIC79XX is not set
+# CONFIG_SCSI_DPT_I2O is not set
+# CONFIG_SCSI_ADVANSYS is not set
+# CONFIG_SCSI_IN2000 is not set
+# CONFIG_SCSI_AM53C974 is not set
+# CONFIG_SCSI_MEGARAID is not set
+# CONFIG_SCSI_BUSLOGIC is not set
+# CONFIG_SCSI_CPQFCTS is not set
+# CONFIG_SCSI_DMX3191D is not set
+# CONFIG_SCSI_EATA is not set
+# CONFIG_SCSI_EATA_PIO is not set
+# CONFIG_SCSI_FUTURE_DOMAIN is not set
+# CONFIG_SCSI_GDTH is not set
+# CONFIG_SCSI_GENERIC_NCR5380 is not set
+# CONFIG_SCSI_GENERIC_NCR5380_MMIO is not set
+# CONFIG_SCSI_INITIO is not set
+# CONFIG_SCSI_INIA100 is not set
+# CONFIG_SCSI_NCR53C7xx is not set
+CONFIG_SCSI_SYM53C8XX_2=y
+CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=0
+CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16
+CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64
+# CONFIG_SCSI_SYM53C8XX_IOMAPPED is not set
+# CONFIG_SCSI_PCI2000 is not set
+# CONFIG_SCSI_PCI2220I is not set
+# CONFIG_SCSI_QLOGIC_ISP is not set
+# CONFIG_SCSI_QLOGIC_FC is not set
+# CONFIG_SCSI_QLOGIC_1280 is not set
+# CONFIG_SCSI_DC395x is not set
+# CONFIG_SCSI_DC390T is not set
+# CONFIG_SCSI_U14_34F is not set
+# CONFIG_SCSI_NSP32 is not set
+# CONFIG_SCSI_DEBUG is not set
+
+#
+# Fusion MPT device support
+#
+# CONFIG_FUSION is not set
+
+#
+# IEEE 1394 (FireWire) support (EXPERIMENTAL)
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+# CONFIG_NETLINK_DEV is not set
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+# CONFIG_IP_PNP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+# CONFIG_INET_ECN is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+
+#
+# IP: Netfilter Configuration
+#
+# CONFIG_IP_NF_CONNTRACK is not set
+# CONFIG_IP_NF_QUEUE is not set
+# CONFIG_IP_NF_IPTABLES is not set
+# CONFIG_IP_NF_ARPTABLES is not set
+# CONFIG_IP_NF_COMPAT_IPCHAINS is not set
+# CONFIG_IP_NF_COMPAT_IPFWADM is not set
+# CONFIG_IPV6 is not set
+# CONFIG_XFRM_USER is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+CONFIG_IPV6_SCTP__=y
+# CONFIG_IP_SCTP is not set
+# CONFIG_ATM is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_LLC is not set
+# CONFIG_DECNET is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_HW_FLOWCONTROL is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+CONFIG_NETDEVICES=y
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_ETHERTAP is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+# CONFIG_MII is not set
+# CONFIG_OAKNET is not set
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_NET_VENDOR_3COM is not set
+
+#
+# Tulip family network device support
+#
+# CONFIG_NET_TULIP is not set
+# CONFIG_HP100 is not set
+# CONFIG_NET_PCI is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_E1000 is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_TIGON3 is not set
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_IXGB is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Token Ring devices (depends on LLC=y)
+#
+# CONFIG_NET_FC is not set
+# CONFIG_RCPCI is not set
+# CONFIG_SHAPER is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+
+#
+# Amateur Radio support
+#
+# CONFIG_HAMRADIO is not set
+
+#
+# IrDA (infrared) support
+#
+# CONFIG_IRDA is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN_BOOL is not set
+
+#
+# Graphics support
+#
+# CONFIG_FB is not set
+
+#
+# Old CD-ROM drivers (not SCSI, not IDE)
+#
+# CONFIG_CD_NO_IDESCSI is not set
+
+#
+# Input device support
+#
+# CONFIG_INPUT is not set
+
+#
+# Userland interfaces
+#
+
+#
+# Input I/O drivers
+#
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+# CONFIG_SERIO is not set
+
+#
+# Input Device Drivers
+#
+
+#
+# Macintosh device drivers
+#
+
+#
+# Character devices
+#
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_UNIX98_PTY_COUNT=256
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# I2C Hardware Sensors Mainboard support
+#
+
+#
+# I2C Hardware Sensors Chip support
+#
+# CONFIG_I2C_SENSOR is not set
+
+#
+# Mice
+#
+# CONFIG_BUSMOUSE is not set
+# CONFIG_QIC02_TAPE is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_NVRAM is not set
+CONFIG_GEN_RTC=y
+# CONFIG_GEN_RTC_X is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_FTAPE is not set
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_HANGCHECK_TIMER is not set
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_JBD is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+CONFIG_ISO9660_FS=y
+# CONFIG_JOLIET is not set
+# CONFIG_ZISOFS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_FAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_DEVFS_FS=y
+# CONFIG_DEVFS_MOUNT is not set
+# CONFIG_DEVFS_DEBUG is not set
+CONFIG_DEVPTS_FS=y
+# CONFIG_DEVPTS_FS_XATTR is not set
+CONFIG_TMPFS=y
+CONFIG_RAMFS=y
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+# CONFIG_NFS_V3 is not set
+# CONFIG_NFS_V4 is not set
+CONFIG_NFSD=y
+# CONFIG_NFSD_V3 is not set
+# CONFIG_NFSD_TCP is not set
+CONFIG_LOCKD=y
+CONFIG_EXPORTFS=y
+CONFIG_SUNRPC=y
+# CONFIG_SUNRPC_GSS is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_INTERMEZZO_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_BSD_DISKLABEL is not set
+# CONFIG_MINIX_SUBPARTITION is not set
+CONFIG_SOLARIS_X86_PARTITION=y
+# CONFIG_UNIXWARE_DISKLABEL is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_NEC98_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_EFI_PARTITION is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+# CONFIG_USB is not set
+# CONFIG_USB_GADGET is not set
+
+#
+# Bluetooth support
+#
+# CONFIG_BT is not set
+
+#
+# Library routines
+#
+# CONFIG_CRC32 is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_DEBUG_KERNEL is not set
+# CONFIG_KALLSYMS is not set
+
+#
+# Security options
+#
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
diff --git a/arch/ppc/configs/hdpu_defconfig b/arch/ppc/configs/hdpu_defconfig
new file mode 100644
index 0000000..956a178
--- /dev/null
+++ b/arch/ppc/configs/hdpu_defconfig
@@ -0,0 +1,890 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.11
+# Wed Mar 16 12:43:19 2005
+#
+CONFIG_MMU=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_HAVE_DEC_LOCK=y
+CONFIG_PPC=y
+CONFIG_PPC32=y
+CONFIG_GENERIC_NVRAM=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=y
+CONFIG_LOCK_KERNEL=y
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+CONFIG_HOTPLUG=y
+CONFIG_KOBJECT_UEVENT=y
+# CONFIG_IKCONFIG is not set
+# CONFIG_CPUSETS is not set
+CONFIG_EMBEDDED=y
+# CONFIG_KALLSYMS is not set
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SHMEM=y
+CONFIG_CC_ALIGN_FUNCTIONS=0
+CONFIG_CC_ALIGN_LABELS=0
+CONFIG_CC_ALIGN_LOOPS=0
+CONFIG_CC_ALIGN_JUMPS=0
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_OBSOLETE_MODPARM=y
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_KMOD=y
+CONFIG_STOP_MACHINE=y
+
+#
+# Processor
+#
+CONFIG_6xx=y
+# CONFIG_40x is not set
+# CONFIG_44x is not set
+# CONFIG_POWER3 is not set
+# CONFIG_POWER4 is not set
+# CONFIG_8xx is not set
+# CONFIG_E500 is not set
+CONFIG_ALTIVEC=y
+# CONFIG_TAU is not set
+# CONFIG_CPU_FREQ is not set
+# CONFIG_PM is not set
+CONFIG_PPC_STD_MMU=y
+# CONFIG_NOT_COHERENT_CACHE is not set
+
+#
+# Platform options
+#
+# CONFIG_PPC_MULTIPLATFORM is not set
+# CONFIG_APUS is not set
+# CONFIG_KATANA is not set
+# CONFIG_WILLOW is not set
+# CONFIG_CPCI690 is not set
+# CONFIG_PCORE is not set
+# CONFIG_POWERPMC250 is not set
+# CONFIG_CHESTNUT is not set
+# CONFIG_SPRUCE is not set
+CONFIG_HDPU=y
+# CONFIG_EV64260 is not set
+# CONFIG_LOPEC is not set
+# CONFIG_MCPN765 is not set
+# CONFIG_MVME5100 is not set
+# CONFIG_PPLUS is not set
+# CONFIG_PRPMC750 is not set
+# CONFIG_PRPMC800 is not set
+# CONFIG_SANDPOINT is not set
+# CONFIG_RADSTONE_PPC7D is not set
+# CONFIG_ADIR is not set
+# CONFIG_K2 is not set
+# CONFIG_PAL4 is not set
+# CONFIG_GEMINI is not set
+# CONFIG_EST8260 is not set
+# CONFIG_SBC82xx is not set
+# CONFIG_SBS8260 is not set
+# CONFIG_RPX8260 is not set
+# CONFIG_TQM8260 is not set
+# CONFIG_ADS8272 is not set
+# CONFIG_PQ2FADS is not set
+# CONFIG_LITE5200 is not set
+# CONFIG_MPC834x_SYS is not set
+CONFIG_MV64360=y
+CONFIG_MV64X60=y
+
+#
+# Set bridge options
+#
+CONFIG_MV64X60_BASE=0xf1000000
+CONFIG_MV64X60_NEW_BASE=0xf1000000
+# CONFIG_SMP is not set
+# CONFIG_IRQ_ALL_CPUS is not set
+# CONFIG_NR_CPUS is not set
+CONFIG_PREEMPT=y
+CONFIG_HIGHMEM=y
+CONFIG_BINFMT_ELF=y
+CONFIG_BINFMT_MISC=y
+CONFIG_CMDLINE_BOOL=y
+CONFIG_CMDLINE="root=/dev/nfs ip=auto"
+
+#
+# Bus options
+#
+CONFIG_GENERIC_ISA_DMA=y
+CONFIG_PCI=y
+CONFIG_PCI_DOMAINS=y
+CONFIG_PCI_LEGACY_PROC=y
+CONFIG_PCI_NAMES=y
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# Advanced setup
+#
+CONFIG_ADVANCED_OPTIONS=y
+# CONFIG_HIGHMEM_START_BOOL is not set
+CONFIG_HIGHMEM_START=0xfe000000
+# CONFIG_LOWMEM_SIZE_BOOL is not set
+CONFIG_LOWMEM_SIZE=0x30000000
+CONFIG_KERNEL_START_BOOL=y
+CONFIG_KERNEL_START=0x80000000
+# CONFIG_TASK_SIZE_BOOL is not set
+CONFIG_TASK_SIZE=0x80000000
+# CONFIG_BOOT_LOAD_BOOL is not set
+CONFIG_BOOT_LOAD=0x00800000
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=y
+
+#
+# Memory Technology Devices (MTD)
+#
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+# CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_REDBOOT_PARTS is not set
+# CONFIG_MTD_CMDLINE_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+# CONFIG_MTD_BLOCK is not set
+# CONFIG_MTD_BLOCK_RO is not set
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=y
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_GEN_PROBE=y
+# CONFIG_MTD_CFI_ADV_OPTIONS is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+CONFIG_MTD_CFI_INTELEXT=y
+# CONFIG_MTD_CFI_AMDSTD is not set
+# CONFIG_MTD_CFI_STAA is not set
+CONFIG_MTD_CFI_UTIL=y
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+CONFIG_MTD_PHYSMAP=y
+CONFIG_MTD_PHYSMAP_START=0xfc000000
+CONFIG_MTD_PHYSMAP_LEN=0x04000000
+CONFIG_MTD_PHYSMAP_BANKWIDTH=4
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_PMC551 is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLKMTD is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+
+#
+# NAND Flash Device Drivers
+#
+# CONFIG_MTD_NAND is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_SX8 is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=8192
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_LBD is not set
+# CONFIG_CDROM_PKTCDVD is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+CONFIG_SCSI=y
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+CONFIG_CHR_DEV_ST=y
+# CONFIG_CHR_DEV_OSST is not set
+CONFIG_BLK_DEV_SR=y
+# CONFIG_BLK_DEV_SR_VENDOR is not set
+CONFIG_CHR_DEV_SG=y
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+# CONFIG_SCSI_MULTI_LUN is not set
+CONFIG_SCSI_CONSTANTS=y
+# CONFIG_SCSI_LOGGING is not set
+
+#
+# SCSI Transport Attributes
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+
+#
+# SCSI low-level drivers
+#
+# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
+# CONFIG_SCSI_3W_9XXX is not set
+# CONFIG_SCSI_ACARD is not set
+# CONFIG_SCSI_AACRAID is not set
+CONFIG_SCSI_AIC7XXX=y
+CONFIG_AIC7XXX_CMDS_PER_DEVICE=32
+CONFIG_AIC7XXX_RESET_DELAY_MS=15000
+# CONFIG_AIC7XXX_DEBUG_ENABLE is not set
+CONFIG_AIC7XXX_DEBUG_MASK=0
+# CONFIG_AIC7XXX_REG_PRETTY_PRINT is not set
+# CONFIG_SCSI_AIC7XXX_OLD is not set
+# CONFIG_SCSI_AIC79XX is not set
+# CONFIG_SCSI_DPT_I2O is not set
+# CONFIG_MEGARAID_NEWGEN is not set
+# CONFIG_MEGARAID_LEGACY is not set
+# CONFIG_SCSI_SATA is not set
+# CONFIG_SCSI_BUSLOGIC is not set
+# CONFIG_SCSI_DMX3191D is not set
+# CONFIG_SCSI_EATA is not set
+# CONFIG_SCSI_EATA_PIO is not set
+# CONFIG_SCSI_FUTURE_DOMAIN is not set
+# CONFIG_SCSI_GDTH is not set
+# CONFIG_SCSI_IPS is not set
+# CONFIG_SCSI_INITIO is not set
+# CONFIG_SCSI_INIA100 is not set
+# CONFIG_SCSI_SYM53C8XX_2 is not set
+# CONFIG_SCSI_IPR is not set
+# CONFIG_SCSI_QLOGIC_ISP is not set
+# CONFIG_SCSI_QLOGIC_FC is not set
+# CONFIG_SCSI_QLOGIC_1280 is not set
+CONFIG_SCSI_QLA2XXX=y
+# CONFIG_SCSI_QLA21XX is not set
+# CONFIG_SCSI_QLA22XX is not set
+# CONFIG_SCSI_QLA2300 is not set
+# CONFIG_SCSI_QLA2322 is not set
+# CONFIG_SCSI_QLA6312 is not set
+# CONFIG_SCSI_DC395x is not set
+# CONFIG_SCSI_DC390T is not set
+# CONFIG_SCSI_NSP32 is not set
+# CONFIG_SCSI_DEBUG is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+# CONFIG_FUSION is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# Macintosh device drivers
+#
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+# CONFIG_NETLINK_DEV is not set
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_PNP=y
+# CONFIG_IP_PNP_DHCP is not set
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_IP_MROUTE is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_TUNNEL is not set
+# CONFIG_IP_TCPDIAG is not set
+# CONFIG_IP_TCPDIAG_IPV6 is not set
+# CONFIG_IPV6 is not set
+# CONFIG_NETFILTER is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_NET_VENDOR_3COM is not set
+
+#
+# Tulip family network device support
+#
+# CONFIG_NET_TULIP is not set
+# CONFIG_HP100 is not set
+# CONFIG_NET_PCI is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_E1000 is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_TIGON3 is not set
+CONFIG_MV643XX_ETH=y
+CONFIG_MV643XX_ETH_0=y
+# CONFIG_MV643XX_ETH_1 is not set
+# CONFIG_MV643XX_ETH_2 is not set
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_IXGB is not set
+# CONFIG_S2IO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_NET_FC is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+
+#
+# Character devices
+#
+# CONFIG_VT is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_MPSC=y
+CONFIG_SERIAL_MPSC_CONSOLE=y
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_NVRAM is not set
+CONFIG_GEN_RTC=y
+# CONFIG_GEN_RTC_X is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
+# Misc devices
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+# CONFIG_FB is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+# CONFIG_USB is not set
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# InfiniBand support
+#
+# CONFIG_INFINIBAND is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+CONFIG_EXT3_FS=y
+# CONFIG_EXT3_FS_XATTR is not set
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+CONFIG_FS_POSIX_ACL=y
+
+#
+# XFS support
+#
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+CONFIG_ISO9660_FS=y
+CONFIG_JOLIET=y
+# CONFIG_ZISOFS is not set
+CONFIG_UDF_FS=y
+CONFIG_UDF_NLS=y
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_SYSFS=y
+# CONFIG_DEVFS_FS is not set
+# CONFIG_DEVPTS_FS_XATTR is not set
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_XATTR is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_JFFS_FS is not set
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+# CONFIG_JFFS2_FS_NAND is not set
+# CONFIG_JFFS2_FS_NOR_ECC is not set
+# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+CONFIG_JFFS2_ZLIB=y
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+CONFIG_NFS_V4=y
+CONFIG_NFS_DIRECTIO=y
+CONFIG_NFSD=y
+CONFIG_NFSD_V3=y
+CONFIG_NFSD_V4=y
+CONFIG_NFSD_TCP=y
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_EXPORTFS=y
+CONFIG_SUNRPC=y
+CONFIG_SUNRPC_GSS=y
+CONFIG_RPCSEC_GSS_KRB5=y
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+# CONFIG_NLS_CODEPAGE_437 is not set
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
+# CONFIG_NLS_ISO8859_1 is not set
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_UTF8 is not set
+
+#
+# Library routines
+#
+# CONFIG_CRC_CCITT is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+# CONFIG_DEBUG_KERNEL is not set
+CONFIG_LOG_BUF_SHIFT=15
+# CONFIG_SERIAL_TEXT_DEBUG is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+CONFIG_CRYPTO=y
+# CONFIG_CRYPTO_HMAC is not set
+# CONFIG_CRYPTO_NULL is not set
+# CONFIG_CRYPTO_MD4 is not set
+CONFIG_CRYPTO_MD5=y
+# CONFIG_CRYPTO_SHA1 is not set
+# CONFIG_CRYPTO_SHA256 is not set
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_WP512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+CONFIG_CRYPTO_DES=y
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_AES is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_ARC4 is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_ANUBIS is not set
+# CONFIG_CRYPTO_DEFLATE is not set
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Hardware crypto devices
+#
diff --git a/arch/ppc/configs/ibmchrp_defconfig b/arch/ppc/configs/ibmchrp_defconfig
new file mode 100644
index 0000000..27f3e69
--- /dev/null
+++ b/arch/ppc/configs/ibmchrp_defconfig
@@ -0,0 +1,875 @@
+#
+# Automatically generated make config: don't edit
+#
+CONFIG_MMU=y
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_HAVE_DEC_LOCK=y
+CONFIG_PPC=y
+CONFIG_PPC32=y
+CONFIG_GENERIC_NVRAM=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=y
+# CONFIG_STANDALONE is not set
+CONFIG_BROKEN_ON_SMP=y
+
+#
+# General setup
+#
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_POSIX_MQUEUE=y
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_HOTPLUG is not set
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+# CONFIG_EMBEDDED is not set
+CONFIG_KALLSYMS=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+CONFIG_OBSOLETE_MODPARM=y
+# CONFIG_MODVERSIONS is not set
+CONFIG_KMOD=y
+
+#
+# Processor
+#
+CONFIG_6xx=y
+# CONFIG_40x is not set
+# CONFIG_44x is not set
+# CONFIG_POWER3 is not set
+# CONFIG_POWER4 is not set
+# CONFIG_8xx is not set
+# CONFIG_ALTIVEC is not set
+# CONFIG_TAU is not set
+# CONFIG_CPU_FREQ is not set
+# CONFIG_PPC601_SYNC_FIX is not set
+CONFIG_PPC_STD_MMU=y
+
+#
+# Platform options
+#
+CONFIG_PPC_MULTIPLATFORM=y
+# CONFIG_APUS is not set
+# CONFIG_WILLOW is not set
+# CONFIG_PCORE is not set
+# CONFIG_POWERPMC250 is not set
+# CONFIG_EV64260 is not set
+# CONFIG_SPRUCE is not set
+# CONFIG_LOPEC is not set
+# CONFIG_MCPN765 is not set
+# CONFIG_MVME5100 is not set
+# CONFIG_PPLUS is not set
+# CONFIG_PRPMC750 is not set
+# CONFIG_PRPMC800 is not set
+# CONFIG_SANDPOINT is not set
+# CONFIG_ADIR is not set
+# CONFIG_K2 is not set
+# CONFIG_PAL4 is not set
+# CONFIG_GEMINI is not set
+# CONFIG_EST8260 is not set
+# CONFIG_SBS8260 is not set
+# CONFIG_RPX6 is not set
+# CONFIG_TQM8260 is not set
+CONFIG_PPC_CHRP=y
+CONFIG_PPC_PMAC=y
+CONFIG_PPC_PREP=y
+CONFIG_PPC_OF=y
+CONFIG_PPCBUG_NVRAM=y
+# CONFIG_SMP is not set
+# CONFIG_PREEMPT is not set
+CONFIG_HIGHMEM=y
+CONFIG_KERNEL_ELF=y
+CONFIG_BINFMT_ELF=y
+CONFIG_BINFMT_MISC=y
+CONFIG_PROC_DEVICETREE=y
+CONFIG_PPC_RTAS=y
+# CONFIG_PREP_RESIDUAL is not set
+# CONFIG_CMDLINE_BOOL is not set
+
+#
+# Bus options
+#
+CONFIG_ISA=y
+CONFIG_GENERIC_ISA_DMA=y
+CONFIG_PCI=y
+CONFIG_PCI_DOMAINS=y
+CONFIG_PCI_LEGACY_PROC=y
+CONFIG_PCI_NAMES=y
+
+#
+# Advanced setup
+#
+# CONFIG_ADVANCED_OPTIONS is not set
+
+#
+# Default settings for advanced configuration options are used
+#
+CONFIG_HIGHMEM_START=0xfe000000
+CONFIG_LOWMEM_SIZE=0x30000000
+CONFIG_KERNEL_START=0xc0000000
+CONFIG_TASK_SIZE=0x80000000
+CONFIG_BOOT_LOAD=0x00800000
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+# CONFIG_PNP is not set
+
+#
+# Block devices
+#
+CONFIG_BLK_DEV_FD=y
+# CONFIG_BLK_DEV_XD is not set
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_CARMEL is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=4096
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_LBD=y
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+CONFIG_SCSI=y
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+CONFIG_CHR_DEV_ST=y
+# CONFIG_CHR_DEV_OSST is not set
+CONFIG_BLK_DEV_SR=y
+CONFIG_BLK_DEV_SR_VENDOR=y
+CONFIG_CHR_DEV_SG=y
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+# CONFIG_SCSI_MULTI_LUN is not set
+# CONFIG_SCSI_REPORT_LUNS is not set
+CONFIG_SCSI_CONSTANTS=y
+# CONFIG_SCSI_LOGGING is not set
+
+#
+# SCSI Transport Attributes
+#
+CONFIG_SCSI_SPI_ATTRS=y
+# CONFIG_SCSI_FC_ATTRS is not set
+
+#
+# SCSI low-level drivers
+#
+# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
+# CONFIG_SCSI_7000FASST is not set
+# CONFIG_SCSI_ACARD is not set
+# CONFIG_SCSI_AHA152X is not set
+# CONFIG_SCSI_AHA1542 is not set
+# CONFIG_SCSI_AACRAID is not set
+# CONFIG_SCSI_AIC7XXX is not set
+# CONFIG_SCSI_AIC7XXX_OLD is not set
+# CONFIG_SCSI_AIC79XX is not set
+# CONFIG_SCSI_ADVANSYS is not set
+# CONFIG_SCSI_IN2000 is not set
+# CONFIG_SCSI_MEGARAID is not set
+# CONFIG_SCSI_SATA is not set
+# CONFIG_SCSI_BUSLOGIC is not set
+# CONFIG_SCSI_CPQFCTS is not set
+# CONFIG_SCSI_DMX3191D is not set
+# CONFIG_SCSI_DTC3280 is not set
+# CONFIG_SCSI_EATA is not set
+# CONFIG_SCSI_EATA_PIO is not set
+# CONFIG_SCSI_FUTURE_DOMAIN is not set
+# CONFIG_SCSI_GDTH is not set
+# CONFIG_SCSI_GENERIC_NCR5380 is not set
+# CONFIG_SCSI_GENERIC_NCR5380_MMIO is not set
+# CONFIG_SCSI_IPS is not set
+# CONFIG_SCSI_INIA100 is not set
+# CONFIG_SCSI_NCR53C406A is not set
+CONFIG_SCSI_SYM53C8XX_2=y
+CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=0
+CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16
+CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64
+# CONFIG_SCSI_SYM53C8XX_IOMAPPED is not set
+# CONFIG_SCSI_IPR is not set
+# CONFIG_SCSI_PAS16 is not set
+# CONFIG_SCSI_PSI240I is not set
+# CONFIG_SCSI_QLOGIC_FAS is not set
+# CONFIG_SCSI_QLOGIC_ISP is not set
+# CONFIG_SCSI_QLOGIC_FC is not set
+# CONFIG_SCSI_QLOGIC_1280 is not set
+CONFIG_SCSI_QLA2XXX=y
+# CONFIG_SCSI_QLA21XX is not set
+# CONFIG_SCSI_QLA22XX is not set
+# CONFIG_SCSI_QLA2300 is not set
+# CONFIG_SCSI_QLA2322 is not set
+# CONFIG_SCSI_QLA6312 is not set
+# CONFIG_SCSI_QLA6322 is not set
+# CONFIG_SCSI_SYM53C416 is not set
+# CONFIG_SCSI_DC395x is not set
+# CONFIG_SCSI_DC390T is not set
+# CONFIG_SCSI_T128 is not set
+# CONFIG_SCSI_U14_34F is not set
+# CONFIG_SCSI_NSP32 is not set
+# CONFIG_SCSI_DEBUG is not set
+# CONFIG_SCSI_MESH is not set
+# CONFIG_SCSI_MAC53C94 is not set
+
+#
+# Old CD-ROM drivers (not SCSI, not IDE)
+#
+# CONFIG_CD_NO_IDESCSI is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+# CONFIG_FUSION is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# Macintosh device drivers
+#
+# CONFIG_ADB is not set
+# CONFIG_ADB_CUDA is not set
+# CONFIG_ADB_PMU is not set
+# CONFIG_MAC_FLOPPY is not set
+# CONFIG_MAC_SERIAL is not set
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+# CONFIG_NETLINK_DEV is not set
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+# CONFIG_IP_PNP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_IP_MROUTE is not set
+# CONFIG_ARPD is not set
+CONFIG_SYN_COOKIES=y
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+
+#
+# IP: Virtual Server Configuration
+#
+# CONFIG_IP_VS is not set
+# CONFIG_IPV6 is not set
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+
+#
+# IP: Netfilter Configuration
+#
+CONFIG_IP_NF_CONNTRACK=m
+CONFIG_IP_NF_FTP=m
+CONFIG_IP_NF_IRC=m
+CONFIG_IP_NF_TFTP=m
+CONFIG_IP_NF_AMANDA=m
+# CONFIG_IP_NF_QUEUE is not set
+CONFIG_IP_NF_IPTABLES=m
+CONFIG_IP_NF_MATCH_LIMIT=m
+CONFIG_IP_NF_MATCH_IPRANGE=m
+CONFIG_IP_NF_MATCH_MAC=m
+# CONFIG_IP_NF_MATCH_PKTTYPE is not set
+CONFIG_IP_NF_MATCH_MARK=m
+CONFIG_IP_NF_MATCH_MULTIPORT=m
+CONFIG_IP_NF_MATCH_TOS=m
+CONFIG_IP_NF_MATCH_RECENT=m
+CONFIG_IP_NF_MATCH_ECN=m
+CONFIG_IP_NF_MATCH_DSCP=m
+CONFIG_IP_NF_MATCH_AH_ESP=m
+CONFIG_IP_NF_MATCH_LENGTH=m
+CONFIG_IP_NF_MATCH_TTL=m
+CONFIG_IP_NF_MATCH_TCPMSS=m
+CONFIG_IP_NF_MATCH_HELPER=m
+CONFIG_IP_NF_MATCH_STATE=m
+CONFIG_IP_NF_MATCH_CONNTRACK=m
+CONFIG_IP_NF_MATCH_OWNER=m
+CONFIG_IP_NF_FILTER=m
+CONFIG_IP_NF_TARGET_REJECT=m
+CONFIG_IP_NF_NAT=m
+CONFIG_IP_NF_NAT_NEEDED=y
+CONFIG_IP_NF_TARGET_MASQUERADE=m
+CONFIG_IP_NF_TARGET_REDIRECT=m
+CONFIG_IP_NF_TARGET_NETMAP=m
+CONFIG_IP_NF_TARGET_SAME=m
+CONFIG_IP_NF_NAT_SNMP_BASIC=m
+CONFIG_IP_NF_NAT_IRC=m
+CONFIG_IP_NF_NAT_FTP=m
+CONFIG_IP_NF_NAT_TFTP=m
+CONFIG_IP_NF_NAT_AMANDA=m
+# CONFIG_IP_NF_MANGLE is not set
+# CONFIG_IP_NF_TARGET_LOG is not set
+CONFIG_IP_NF_TARGET_ULOG=m
+CONFIG_IP_NF_TARGET_TCPMSS=m
+CONFIG_IP_NF_ARPTABLES=m
+CONFIG_IP_NF_ARPFILTER=m
+CONFIG_IP_NF_ARP_MANGLE=m
+CONFIG_IP_NF_COMPAT_IPCHAINS=m
+# CONFIG_IP_NF_COMPAT_IPFWADM is not set
+CONFIG_IP_NF_TARGET_NOTRACK=m
+CONFIG_IP_NF_RAW=m
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_HW_FLOWCONTROL is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_MACE is not set
+# CONFIG_BMAC is not set
+# CONFIG_OAKNET is not set
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_NET_VENDOR_3COM is not set
+# CONFIG_LANCE is not set
+# CONFIG_NET_VENDOR_SMC is not set
+# CONFIG_NET_VENDOR_RACAL is not set
+
+#
+# Tulip family network device support
+#
+# CONFIG_NET_TULIP is not set
+# CONFIG_AT1700 is not set
+# CONFIG_DEPCA is not set
+# CONFIG_HP100 is not set
+# CONFIG_NET_ISA is not set
+CONFIG_NET_PCI=y
+CONFIG_PCNET32=y
+# CONFIG_AMD8111_ETH is not set
+# CONFIG_ADAPTEC_STARFIRE is not set
+# CONFIG_AC3200 is not set
+# CONFIG_APRICOT is not set
+# CONFIG_B44 is not set
+# CONFIG_FORCEDETH is not set
+# CONFIG_CS89x0 is not set
+# CONFIG_DGRS is not set
+# CONFIG_EEPRO100 is not set
+# CONFIG_E100 is not set
+# CONFIG_FEALNX is not set
+# CONFIG_NATSEMI is not set
+# CONFIG_NE2K_PCI is not set
+# CONFIG_8139CP is not set
+# CONFIG_8139TOO is not set
+# CONFIG_SIS900 is not set
+# CONFIG_EPIC100 is not set
+# CONFIG_SUNDANCE is not set
+# CONFIG_TLAN is not set
+# CONFIG_VIA_RHINE is not set
+# CONFIG_NET_POCKET is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_E1000 is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_TIGON3 is not set
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_IXGB is not set
+# CONFIG_S2IO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_NET_FC is not set
+# CONFIG_RCPCI is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input I/O drivers
+#
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+CONFIG_SERIO=y
+CONFIG_SERIO_I8042=y
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_CT82C710 is not set
+# CONFIG_SERIO_PCIPS2 is not set
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+CONFIG_KEYBOARD_ATKBD=y
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+CONFIG_INPUT_MOUSE=y
+CONFIG_MOUSE_PS2=y
+# CONFIG_MOUSE_SERIAL is not set
+# CONFIG_MOUSE_INPORT is not set
+# CONFIG_MOUSE_LOGIBM is not set
+# CONFIG_MOUSE_PC110PAD is not set
+# CONFIG_MOUSE_VSXXXAA is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+CONFIG_INPUT_MISC=y
+CONFIG_INPUT_UINPUT=y
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+# CONFIG_SERIAL_8250_CONSOLE is not set
+CONFIG_SERIAL_8250_NR_UARTS=4
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+# CONFIG_SERIAL_PMACZILOG is not set
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_QIC02_TAPE is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+CONFIG_NVRAM=y
+CONFIG_GEN_RTC=y
+# CONFIG_GEN_RTC_X is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_FTAPE is not set
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# Misc devices
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+CONFIG_FB=y
+# CONFIG_FB_PM2 is not set
+# CONFIG_FB_CYBER2000 is not set
+CONFIG_FB_OF=y
+# CONFIG_FB_CONTROL is not set
+# CONFIG_FB_PLATINUM is not set
+# CONFIG_FB_VALKYRIE is not set
+# CONFIG_FB_CT65550 is not set
+# CONFIG_FB_IMSTT is not set
+# CONFIG_FB_S3TRIO is not set
+# CONFIG_FB_VGA16 is not set
+# CONFIG_FB_RIVA is not set
+CONFIG_FB_MATROX=y
+CONFIG_FB_MATROX_MILLENIUM=y
+CONFIG_FB_MATROX_MYSTIQUE=y
+# CONFIG_FB_MATROX_G450 is not set
+CONFIG_FB_MATROX_G100A=y
+CONFIG_FB_MATROX_G100=y
+# CONFIG_FB_MATROX_MULTIHEAD is not set
+# CONFIG_FB_RADEON_OLD is not set
+# CONFIG_FB_RADEON is not set
+# CONFIG_FB_ATY128 is not set
+# CONFIG_FB_ATY is not set
+# CONFIG_FB_SIS is not set
+# CONFIG_FB_NEOMAGIC is not set
+# CONFIG_FB_KYRO is not set
+CONFIG_FB_3DFX=y
+# CONFIG_FB_VOODOO1 is not set
+# CONFIG_FB_TRIDENT is not set
+# CONFIG_FB_VIRTUAL is not set
+
+#
+# Console display driver support
+#
+CONFIG_VGA_CONSOLE=y
+# CONFIG_MDA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_PCI_CONSOLE=y
+# CONFIG_FONTS is not set
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
+
+#
+# Logo configuration
+#
+CONFIG_LOGO=y
+CONFIG_LOGO_LINUX_MONO=y
+CONFIG_LOGO_LINUX_VGA16=y
+CONFIG_LOGO_LINUX_CLUT224=y
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+# CONFIG_USB is not set
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_JBD is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+CONFIG_ISO9660_FS=y
+# CONFIG_JOLIET is not set
+# CONFIG_ZISOFS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=m
+CONFIG_MSDOS_FS=m
+CONFIG_VFAT_FS=m
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_SYSFS=y
+CONFIG_DEVFS_FS=y
+# CONFIG_DEVFS_MOUNT is not set
+# CONFIG_DEVFS_DEBUG is not set
+# CONFIG_DEVPTS_FS_XATTR is not set
+CONFIG_TMPFS=y
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+# CONFIG_NFS_FS is not set
+# CONFIG_NFSD is not set
+# CONFIG_EXPORTFS is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+CONFIG_MAC_PARTITION=y
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_BSD_DISKLABEL is not set
+# CONFIG_MINIX_SUBPARTITION is not set
+# CONFIG_SOLARIS_X86_PARTITION is not set
+# CONFIG_UNIXWARE_DISKLABEL is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_NEC98_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_EFI_PARTITION is not set
+
+#
+# Native Language Support
+#
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+# CONFIG_NLS_CODEPAGE_437 is not set
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+CONFIG_NLS_ISO8859_1=m
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_UTF8 is not set
+
+#
+# Library routines
+#
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_DEBUG_KERNEL is not set
+# CONFIG_BOOTX_TEXT is not set
+
+#
+# Security options
+#
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
diff --git a/arch/ppc/configs/k2_defconfig b/arch/ppc/configs/k2_defconfig
new file mode 100644
index 0000000..f10f5a6
--- /dev/null
+++ b/arch/ppc/configs/k2_defconfig
@@ -0,0 +1,680 @@
+#
+# Automatically generated make config: don't edit
+#
+CONFIG_MMU=y
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_HAVE_DEC_LOCK=y
+CONFIG_PPC=y
+CONFIG_PPC32=y
+CONFIG_GENERIC_NVRAM=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=y
+CONFIG_STANDALONE=y
+CONFIG_BROKEN_ON_SMP=y
+
+#
+# General setup
+#
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_HOTPLUG is not set
+# CONFIG_IKCONFIG is not set
+CONFIG_EMBEDDED=y
+CONFIG_KALLSYMS=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_OBSOLETE_MODPARM=y
+# CONFIG_MODVERSIONS is not set
+CONFIG_KMOD=y
+
+#
+# Processor
+#
+CONFIG_6xx=y
+# CONFIG_40x is not set
+# CONFIG_44x is not set
+# CONFIG_POWER3 is not set
+# CONFIG_POWER4 is not set
+# CONFIG_8xx is not set
+# CONFIG_ALTIVEC is not set
+# CONFIG_TAU is not set
+# CONFIG_CPU_FREQ is not set
+CONFIG_PPC_STD_MMU=y
+
+#
+# Platform options
+#
+# CONFIG_PPC_MULTIPLATFORM is not set
+# CONFIG_APUS is not set
+# CONFIG_WILLOW is not set
+# CONFIG_PCORE is not set
+# CONFIG_POWERPMC250 is not set
+# CONFIG_EV64260 is not set
+# CONFIG_SPRUCE is not set
+# CONFIG_LOPEC is not set
+# CONFIG_MCPN765 is not set
+# CONFIG_MVME5100 is not set
+# CONFIG_PPLUS is not set
+# CONFIG_PRPMC750 is not set
+# CONFIG_PRPMC800 is not set
+# CONFIG_SANDPOINT is not set
+# CONFIG_ADIR is not set
+CONFIG_K2=y
+# CONFIG_PAL4 is not set
+# CONFIG_GEMINI is not set
+# CONFIG_EST8260 is not set
+# CONFIG_SBS8260 is not set
+# CONFIG_RPX6 is not set
+# CONFIG_TQM8260 is not set
+CONFIG_PPC_GEN550=y
+# CONFIG_CPC710_DATA_GATHERING is not set
+# CONFIG_SMP is not set
+# CONFIG_PREEMPT is not set
+# CONFIG_HIGHMEM is not set
+CONFIG_KERNEL_ELF=y
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+CONFIG_CMDLINE_BOOL=y
+CONFIG_CMDLINE="ip=on"
+
+#
+# Bus options
+#
+CONFIG_GENERIC_ISA_DMA=y
+CONFIG_PCI=y
+CONFIG_PCI_DOMAINS=y
+# CONFIG_PCI_LEGACY_PROC is not set
+# CONFIG_PCI_NAMES is not set
+
+#
+# Advanced setup
+#
+# CONFIG_ADVANCED_OPTIONS is not set
+
+#
+# Default settings for advanced configuration options are used
+#
+CONFIG_HIGHMEM_START=0xfe000000
+CONFIG_LOWMEM_SIZE=0x30000000
+CONFIG_KERNEL_START=0xc0000000
+CONFIG_TASK_SIZE=0x80000000
+CONFIG_BOOT_LOAD=0x00800000
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_CARMEL is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=4096
+CONFIG_BLK_DEV_INITRD=y
+# CONFIG_LBD is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+CONFIG_IDE=y
+CONFIG_BLK_DEV_IDE=y
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+CONFIG_BLK_DEV_IDEDISK=y
+# CONFIG_IDEDISK_MULTI_MODE is not set
+# CONFIG_IDEDISK_STROKE is not set
+# CONFIG_BLK_DEV_IDECD is not set
+# CONFIG_BLK_DEV_IDETAPE is not set
+# CONFIG_BLK_DEV_IDEFLOPPY is not set
+# CONFIG_IDE_TASK_IOCTL is not set
+# CONFIG_IDE_TASKFILE_IO is not set
+
+#
+# IDE chipset support/bugfixes
+#
+# CONFIG_IDE_GENERIC is not set
+CONFIG_BLK_DEV_IDEPCI=y
+# CONFIG_IDEPCI_SHARE_IRQ is not set
+# CONFIG_BLK_DEV_OFFBOARD is not set
+# CONFIG_BLK_DEV_GENERIC is not set
+# CONFIG_BLK_DEV_OPTI621 is not set
+# CONFIG_BLK_DEV_SL82C105 is not set
+CONFIG_BLK_DEV_IDEDMA_PCI=y
+# CONFIG_BLK_DEV_IDEDMA_FORCED is not set
+# CONFIG_IDEDMA_PCI_AUTO is not set
+CONFIG_BLK_DEV_ADMA=y
+# CONFIG_BLK_DEV_AEC62XX is not set
+CONFIG_BLK_DEV_ALI15X3=y
+# CONFIG_WDC_ALI15X3 is not set
+# CONFIG_BLK_DEV_AMD74XX is not set
+# CONFIG_BLK_DEV_CMD64X is not set
+# CONFIG_BLK_DEV_TRIFLEX is not set
+# CONFIG_BLK_DEV_CY82C693 is not set
+# CONFIG_BLK_DEV_CS5520 is not set
+# CONFIG_BLK_DEV_CS5530 is not set
+# CONFIG_BLK_DEV_HPT34X is not set
+# CONFIG_BLK_DEV_HPT366 is not set
+# CONFIG_BLK_DEV_SC1200 is not set
+# CONFIG_BLK_DEV_PIIX is not set
+# CONFIG_BLK_DEV_NS87415 is not set
+# CONFIG_BLK_DEV_PDC202XX_OLD is not set
+# CONFIG_BLK_DEV_PDC202XX_NEW is not set
+# CONFIG_BLK_DEV_SVWKS is not set
+# CONFIG_BLK_DEV_SIIMAGE is not set
+# CONFIG_BLK_DEV_SLC90E66 is not set
+# CONFIG_BLK_DEV_TRM290 is not set
+# CONFIG_BLK_DEV_VIA82CXXX is not set
+CONFIG_BLK_DEV_IDEDMA=y
+# CONFIG_IDEDMA_IVB is not set
+# CONFIG_IDEDMA_AUTO is not set
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# SCSI device support
+#
+# CONFIG_SCSI is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+# CONFIG_FUSION is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# Macintosh device drivers
+#
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+# CONFIG_NETLINK_DEV is not set
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+# CONFIG_IP_PNP_BOOTP is not set
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+
+#
+# IP: Virtual Server Configuration
+#
+# CONFIG_IP_VS is not set
+# CONFIG_IPV6 is not set
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+
+#
+# IP: Netfilter Configuration
+#
+CONFIG_IP_NF_CONNTRACK=m
+CONFIG_IP_NF_FTP=m
+# CONFIG_IP_NF_IRC is not set
+# CONFIG_IP_NF_TFTP is not set
+# CONFIG_IP_NF_AMANDA is not set
+# CONFIG_IP_NF_QUEUE is not set
+CONFIG_IP_NF_IPTABLES=m
+CONFIG_IP_NF_MATCH_LIMIT=m
+# CONFIG_IP_NF_MATCH_IPRANGE is not set
+CONFIG_IP_NF_MATCH_MAC=m
+CONFIG_IP_NF_MATCH_PKTTYPE=m
+CONFIG_IP_NF_MATCH_MARK=m
+CONFIG_IP_NF_MATCH_MULTIPORT=m
+CONFIG_IP_NF_MATCH_TOS=m
+# CONFIG_IP_NF_MATCH_RECENT is not set
+CONFIG_IP_NF_MATCH_ECN=m
+CONFIG_IP_NF_MATCH_DSCP=m
+CONFIG_IP_NF_MATCH_AH_ESP=m
+# CONFIG_IP_NF_MATCH_LENGTH is not set
+# CONFIG_IP_NF_MATCH_TTL is not set
+CONFIG_IP_NF_MATCH_TCPMSS=m
+CONFIG_IP_NF_MATCH_HELPER=m
+CONFIG_IP_NF_MATCH_STATE=m
+CONFIG_IP_NF_MATCH_CONNTRACK=m
+CONFIG_IP_NF_MATCH_OWNER=m
+CONFIG_IP_NF_FILTER=m
+CONFIG_IP_NF_TARGET_REJECT=m
+CONFIG_IP_NF_NAT=m
+CONFIG_IP_NF_NAT_NEEDED=y
+CONFIG_IP_NF_TARGET_MASQUERADE=m
+CONFIG_IP_NF_TARGET_REDIRECT=m
+# CONFIG_IP_NF_TARGET_NETMAP is not set
+# CONFIG_IP_NF_TARGET_SAME is not set
+# CONFIG_IP_NF_NAT_SNMP_BASIC is not set
+CONFIG_IP_NF_NAT_FTP=m
+# CONFIG_IP_NF_MANGLE is not set
+# CONFIG_IP_NF_TARGET_LOG is not set
+CONFIG_IP_NF_TARGET_ULOG=m
+CONFIG_IP_NF_TARGET_TCPMSS=m
+CONFIG_IP_NF_ARPTABLES=m
+CONFIG_IP_NF_ARPFILTER=m
+# CONFIG_IP_NF_ARP_MANGLE is not set
+CONFIG_IP_NF_COMPAT_IPCHAINS=m
+# CONFIG_IP_NF_COMPAT_IPFWADM is not set
+# CONFIG_IP_NF_RAW is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_HW_FLOWCONTROL is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_OAKNET is not set
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_NET_VENDOR_3COM is not set
+
+#
+# Tulip family network device support
+#
+# CONFIG_NET_TULIP is not set
+# CONFIG_HP100 is not set
+CONFIG_NET_PCI=y
+# CONFIG_PCNET32 is not set
+# CONFIG_AMD8111_ETH is not set
+# CONFIG_ADAPTEC_STARFIRE is not set
+# CONFIG_B44 is not set
+# CONFIG_FORCEDETH is not set
+# CONFIG_DGRS is not set
+CONFIG_EEPRO100=y
+# CONFIG_EEPRO100_PIO is not set
+# CONFIG_E100 is not set
+# CONFIG_FEALNX is not set
+# CONFIG_NATSEMI is not set
+# CONFIG_NE2K_PCI is not set
+# CONFIG_8139CP is not set
+# CONFIG_8139TOO is not set
+# CONFIG_SIS900 is not set
+# CONFIG_EPIC100 is not set
+# CONFIG_SUNDANCE is not set
+# CONFIG_TLAN is not set
+# CONFIG_VIA_RHINE is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_E1000 is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_TIGON3 is not set
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_IXGB is not set
+# CONFIG_S2IO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_RCPCI is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+# CONFIG_INPUT is not set
+
+#
+# Userland interfaces
+#
+
+#
+# Input I/O drivers
+#
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+# CONFIG_SERIO is not set
+# CONFIG_SERIO_I8042 is not set
+
+#
+# Input Device Drivers
+#
+
+#
+# Character devices
+#
+# CONFIG_VT is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=2
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_QIC02_TAPE is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_NVRAM is not set
+CONFIG_GEN_RTC=y
+# CONFIG_GEN_RTC_X is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_FTAPE is not set
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# Misc devices
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+# CONFIG_FB is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+# CONFIG_USB is not set
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_JBD is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_FAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_SYSFS=y
+# CONFIG_DEVFS_FS is not set
+# CONFIG_DEVPTS_FS_XATTR is not set
+CONFIG_TMPFS=y
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+# CONFIG_NFS_V3 is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+# CONFIG_NFSD is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+# CONFIG_EXPORTFS is not set
+CONFIG_SUNRPC=y
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_INTERMEZZO_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+# CONFIG_NLS is not set
+
+#
+# Library routines
+#
+# CONFIG_CRC32 is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_DEBUG_KERNEL is not set
+# CONFIG_SERIAL_TEXT_DEBUG is not set
+
+#
+# Security options
+#
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
diff --git a/arch/ppc/configs/katana_defconfig b/arch/ppc/configs/katana_defconfig
new file mode 100644
index 0000000..f0b0d57
--- /dev/null
+++ b/arch/ppc/configs/katana_defconfig
@@ -0,0 +1,861 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.11
+# Tue Mar 8 17:31:00 2005
+#
+CONFIG_MMU=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_HAVE_DEC_LOCK=y
+CONFIG_PPC=y
+CONFIG_PPC32=y
+CONFIG_GENERIC_NVRAM=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=y
+CONFIG_BROKEN_ON_SMP=y
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_HOTPLUG is not set
+CONFIG_KOBJECT_UEVENT=y
+# CONFIG_IKCONFIG is not set
+# CONFIG_EMBEDDED is not set
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SHMEM=y
+CONFIG_CC_ALIGN_FUNCTIONS=0
+CONFIG_CC_ALIGN_LABELS=0
+CONFIG_CC_ALIGN_LOOPS=0
+CONFIG_CC_ALIGN_JUMPS=0
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_OBSOLETE_MODPARM=y
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_KMOD=y
+
+#
+# Processor
+#
+CONFIG_6xx=y
+# CONFIG_40x is not set
+# CONFIG_44x is not set
+# CONFIG_POWER3 is not set
+# CONFIG_POWER4 is not set
+# CONFIG_8xx is not set
+# CONFIG_E500 is not set
+CONFIG_ALTIVEC=y
+# CONFIG_TAU is not set
+# CONFIG_CPU_FREQ is not set
+# CONFIG_83xx is not set
+CONFIG_PPC_STD_MMU=y
+CONFIG_NOT_COHERENT_CACHE=y
+
+#
+# Platform options
+#
+# CONFIG_PPC_MULTIPLATFORM is not set
+# CONFIG_APUS is not set
+CONFIG_KATANA=y
+# CONFIG_WILLOW is not set
+# CONFIG_CPCI690 is not set
+# CONFIG_PCORE is not set
+# CONFIG_POWERPMC250 is not set
+# CONFIG_CHESTNUT is not set
+# CONFIG_SPRUCE is not set
+# CONFIG_EV64260 is not set
+# CONFIG_LOPEC is not set
+# CONFIG_MCPN765 is not set
+# CONFIG_MVME5100 is not set
+# CONFIG_PPLUS is not set
+# CONFIG_PRPMC750 is not set
+# CONFIG_PRPMC800 is not set
+# CONFIG_SANDPOINT is not set
+# CONFIG_RADSTONE_PPC7D is not set
+# CONFIG_ADIR is not set
+# CONFIG_K2 is not set
+# CONFIG_PAL4 is not set
+# CONFIG_GEMINI is not set
+# CONFIG_EST8260 is not set
+# CONFIG_SBC82xx is not set
+# CONFIG_SBS8260 is not set
+# CONFIG_RPX8260 is not set
+# CONFIG_TQM8260 is not set
+# CONFIG_ADS8272 is not set
+# CONFIG_PQ2FADS is not set
+# CONFIG_LITE5200 is not set
+CONFIG_MV64360=y
+CONFIG_MV64X60=y
+
+#
+# Set bridge options
+#
+CONFIG_MV64X60_BASE=0xf8100000
+CONFIG_MV64X60_NEW_BASE=0xf8100000
+# CONFIG_SMP is not set
+# CONFIG_PREEMPT is not set
+# CONFIG_HIGHMEM is not set
+CONFIG_BINFMT_ELF=y
+CONFIG_BINFMT_MISC=y
+CONFIG_CMDLINE_BOOL=y
+CONFIG_CMDLINE="console=ttyMM0,9600 ip=on"
+
+#
+# Bus options
+#
+CONFIG_GENERIC_ISA_DMA=y
+CONFIG_PCI=y
+CONFIG_PCI_DOMAINS=y
+CONFIG_PCI_LEGACY_PROC=y
+CONFIG_PCI_NAMES=y
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# PC-card bridges
+#
+
+#
+# Advanced setup
+#
+CONFIG_ADVANCED_OPTIONS=y
+CONFIG_HIGHMEM_START=0xfe000000
+# CONFIG_LOWMEM_SIZE_BOOL is not set
+CONFIG_LOWMEM_SIZE=0x30000000
+# CONFIG_KERNEL_START_BOOL is not set
+CONFIG_KERNEL_START=0xc0000000
+# CONFIG_TASK_SIZE_BOOL is not set
+CONFIG_TASK_SIZE=0x80000000
+CONFIG_CONSISTENT_START_BOOL=y
+CONFIG_CONSISTENT_START=0xf0000000
+CONFIG_CONSISTENT_SIZE_BOOL=y
+CONFIG_CONSISTENT_SIZE=0x00400000
+# CONFIG_BOOT_LOAD_BOOL is not set
+CONFIG_BOOT_LOAD=0x00800000
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+CONFIG_MTD_PARTITIONS=y
+CONFIG_MTD_CONCAT=y
+# CONFIG_MTD_REDBOOT_PARTS is not set
+# CONFIG_MTD_CMDLINE_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=y
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_GEN_PROBE=y
+CONFIG_MTD_CFI_ADV_OPTIONS=y
+CONFIG_MTD_CFI_NOSWAP=y
+# CONFIG_MTD_CFI_BE_BYTE_SWAP is not set
+# CONFIG_MTD_CFI_LE_BYTE_SWAP is not set
+CONFIG_MTD_CFI_GEOMETRY=y
+# CONFIG_MTD_MAP_BANK_WIDTH_1 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_2 is not set
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+# CONFIG_MTD_CFI_I1 is not set
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+CONFIG_MTD_CFI_INTELEXT=y
+# CONFIG_MTD_CFI_AMDSTD is not set
+# CONFIG_MTD_CFI_STAA is not set
+CONFIG_MTD_CFI_UTIL=y
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+# CONFIG_MTD_XIP is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+CONFIG_MTD_PHYSMAP=y
+CONFIG_MTD_PHYSMAP_START=0xe0000000
+CONFIG_MTD_PHYSMAP_LEN=0x0
+CONFIG_MTD_PHYSMAP_BANKWIDTH=4
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_PMC551 is not set
+# CONFIG_MTD_SLRAM is not set
+CONFIG_MTD_PHRAM=y
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLKMTD is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+
+#
+# NAND Flash Device Drivers
+#
+# CONFIG_MTD_NAND is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_SX8 is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=4096
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_LBD is not set
+# CONFIG_CDROM_PKTCDVD is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_SCSI is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# Macintosh device drivers
+#
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+# CONFIG_NETLINK_DEV is not set
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+# CONFIG_IP_PNP_BOOTP is not set
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_IP_MROUTE is not set
+# CONFIG_ARPD is not set
+CONFIG_SYN_COOKIES=y
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_IP_TCPDIAG=y
+# CONFIG_IP_TCPDIAG_IPV6 is not set
+# CONFIG_IPV6 is not set
+# CONFIG_NETFILTER is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_NET_VENDOR_3COM is not set
+
+#
+# Tulip family network device support
+#
+CONFIG_NET_TULIP=y
+# CONFIG_DE2104X is not set
+CONFIG_TULIP=y
+# CONFIG_TULIP_MWI is not set
+# CONFIG_TULIP_MMIO is not set
+# CONFIG_TULIP_NAPI is not set
+# CONFIG_DE4X5 is not set
+# CONFIG_WINBOND_840 is not set
+# CONFIG_DM9102 is not set
+# CONFIG_HP100 is not set
+CONFIG_NET_PCI=y
+# CONFIG_PCNET32 is not set
+# CONFIG_AMD8111_ETH is not set
+# CONFIG_ADAPTEC_STARFIRE is not set
+# CONFIG_B44 is not set
+# CONFIG_FORCEDETH is not set
+# CONFIG_DGRS is not set
+# CONFIG_EEPRO100 is not set
+CONFIG_E100=y
+# CONFIG_FEALNX is not set
+# CONFIG_NATSEMI is not set
+# CONFIG_NE2K_PCI is not set
+# CONFIG_8139CP is not set
+# CONFIG_8139TOO is not set
+# CONFIG_SIS900 is not set
+# CONFIG_EPIC100 is not set
+# CONFIG_SUNDANCE is not set
+# CONFIG_TLAN is not set
+# CONFIG_VIA_RHINE is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_E1000 is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_VIA_VELOCITY is not set
+# CONFIG_TIGON3 is not set
+CONFIG_MV643XX_ETH=y
+CONFIG_MV643XX_ETH_0=y
+CONFIG_MV643XX_ETH_1=y
+CONFIG_MV643XX_ETH_2=y
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_IXGB is not set
+# CONFIG_S2IO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input I/O drivers
+#
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+# CONFIG_SERIO is not set
+# CONFIG_SERIO_I8042 is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_MPSC=y
+CONFIG_SERIAL_MPSC_CONSOLE=y
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_NVRAM is not set
+CONFIG_GEN_RTC=y
+# CONFIG_GEN_RTC_X is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# I2C support
+#
+CONFIG_I2C=y
+CONFIG_I2C_CHARDEV=y
+
+#
+# I2C Algorithms
+#
+# CONFIG_I2C_ALGOBIT is not set
+# CONFIG_I2C_ALGOPCF is not set
+# CONFIG_I2C_ALGOPCA is not set
+
+#
+# I2C Hardware Bus support
+#
+# CONFIG_I2C_ALI1535 is not set
+# CONFIG_I2C_ALI1563 is not set
+# CONFIG_I2C_ALI15X3 is not set
+# CONFIG_I2C_AMD756 is not set
+# CONFIG_I2C_AMD8111 is not set
+# CONFIG_I2C_I801 is not set
+# CONFIG_I2C_I810 is not set
+# CONFIG_I2C_ISA is not set
+# CONFIG_I2C_MPC is not set
+# CONFIG_I2C_NFORCE2 is not set
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_PIIX4 is not set
+# CONFIG_I2C_PROSAVAGE is not set
+# CONFIG_I2C_SAVAGE4 is not set
+# CONFIG_SCx200_ACB is not set
+# CONFIG_I2C_SIS5595 is not set
+# CONFIG_I2C_SIS630 is not set
+# CONFIG_I2C_SIS96X is not set
+# CONFIG_I2C_STUB is not set
+# CONFIG_I2C_VIA is not set
+# CONFIG_I2C_VIAPRO is not set
+# CONFIG_I2C_VOODOO3 is not set
+# CONFIG_I2C_PCA_ISA is not set
+CONFIG_I2C_MV64XXX=y
+
+#
+# Hardware Sensors Chip support
+#
+# CONFIG_I2C_SENSOR is not set
+# CONFIG_SENSORS_ADM1021 is not set
+# CONFIG_SENSORS_ADM1025 is not set
+# CONFIG_SENSORS_ADM1026 is not set
+# CONFIG_SENSORS_ADM1031 is not set
+# CONFIG_SENSORS_ASB100 is not set
+# CONFIG_SENSORS_DS1621 is not set
+# CONFIG_SENSORS_FSCHER is not set
+# CONFIG_SENSORS_FSCPOS is not set
+# CONFIG_SENSORS_GL518SM is not set
+# CONFIG_SENSORS_GL520SM is not set
+# CONFIG_SENSORS_IT87 is not set
+# CONFIG_SENSORS_LM63 is not set
+# CONFIG_SENSORS_LM75 is not set
+# CONFIG_SENSORS_LM77 is not set
+# CONFIG_SENSORS_LM78 is not set
+# CONFIG_SENSORS_LM80 is not set
+# CONFIG_SENSORS_LM83 is not set
+# CONFIG_SENSORS_LM85 is not set
+# CONFIG_SENSORS_LM87 is not set
+# CONFIG_SENSORS_LM90 is not set
+# CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_PC87360 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
+# CONFIG_SENSORS_SIS5595 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_VIA686A is not set
+# CONFIG_SENSORS_W83781D is not set
+# CONFIG_SENSORS_W83L785TS is not set
+# CONFIG_SENSORS_W83627HF is not set
+
+#
+# Other I2C Chip support
+#
+# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_SENSORS_RTC8564 is not set
+CONFIG_SENSORS_M41T00=y
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
+# Misc devices
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+# CONFIG_FB is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+# CONFIG_USB is not set
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# InfiniBand support
+#
+# CONFIG_INFINIBAND is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_JBD is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+
+#
+# XFS support
+#
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_SYSFS=y
+CONFIG_DEVFS_FS=y
+# CONFIG_DEVFS_MOUNT is not set
+# CONFIG_DEVFS_DEBUG is not set
+# CONFIG_DEVPTS_FS_XATTR is not set
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_XATTR is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_JFFS_FS is not set
+# CONFIG_JFFS2_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+# CONFIG_NFSD is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_SUNRPC=y
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+# CONFIG_NLS is not set
+
+#
+# Library routines
+#
+# CONFIG_CRC_CCITT is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_DEBUG_KERNEL is not set
+# CONFIG_PRINTK_TIME is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Hardware crypto devices
+#
diff --git a/arch/ppc/configs/lite5200_defconfig b/arch/ppc/configs/lite5200_defconfig
new file mode 100644
index 0000000..7e7a943
--- /dev/null
+++ b/arch/ppc/configs/lite5200_defconfig
@@ -0,0 +1,436 @@
+#
+# Automatically generated make config: don't edit
+#
+CONFIG_MMU=y
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_HAVE_DEC_LOCK=y
+CONFIG_PPC=y
+CONFIG_PPC32=y
+CONFIG_GENERIC_NVRAM=y
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=y
+CONFIG_STANDALONE=y
+CONFIG_BROKEN_ON_SMP=y
+#
+# General setup
+#
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_HOTPLUG is not set
+# CONFIG_IKCONFIG is not set
+# CONFIG_EMBEDDED is not set
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_OBSOLETE_MODPARM=y
+CONFIG_MODVERSIONS=y
+CONFIG_KMOD=y
+#
+# Processor
+#
+CONFIG_6xx=y
+# CONFIG_40x is not set
+# CONFIG_44x is not set
+# CONFIG_POWER3 is not set
+# CONFIG_POWER4 is not set
+# CONFIG_8xx is not set
+# CONFIG_E500 is not set
+# CONFIG_ALTIVEC is not set
+# CONFIG_TAU is not set
+# CONFIG_CPU_FREQ is not set
+CONFIG_FSL_OCP=y
+CONFIG_PPC_STD_MMU=y
+#
+# Platform options
+#
+# CONFIG_PPC_MULTIPLATFORM is not set
+# CONFIG_APUS is not set
+# CONFIG_WILLOW is not set
+# CONFIG_PCORE is not set
+# CONFIG_POWERPMC250 is not set
+# CONFIG_EV64260 is not set
+# CONFIG_SPRUCE is not set
+# CONFIG_LOPEC is not set
+# CONFIG_MCPN765 is not set
+# CONFIG_MVME5100 is not set
+# CONFIG_PPLUS is not set
+# CONFIG_PRPMC750 is not set
+# CONFIG_PRPMC800 is not set
+# CONFIG_SANDPOINT is not set
+# CONFIG_ADIR is not set
+# CONFIG_K2 is not set
+# CONFIG_PAL4 is not set
+# CONFIG_GEMINI is not set
+# CONFIG_EST8260 is not set
+# CONFIG_SBC82xx is not set
+# CONFIG_SBS8260 is not set
+# CONFIG_RPX6 is not set
+# CONFIG_TQM8260 is not set
+# CONFIG_ADS8272 is not set
+CONFIG_LITE5200=y
+CONFIG_PPC_MPC52xx=y
+# CONFIG_SMP is not set
+# CONFIG_PREEMPT is not set
+# CONFIG_HIGHMEM is not set
+CONFIG_KERNEL_ELF=y
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+CONFIG_CMDLINE_BOOL=y
+CONFIG_CMDLINE="console=ttyS0 root=/dev/ram0 rw"
+#
+# Bus options
+#
+CONFIG_GENERIC_ISA_DMA=y
+CONFIG_PCI=y
+CONFIG_PCI_DOMAINS=y
+# CONFIG_PCI_LEGACY_PROC is not set
+# CONFIG_PCI_NAMES is not set
+#
+# Advanced setup
+#
+CONFIG_ADVANCED_OPTIONS=y
+CONFIG_HIGHMEM_START=0xfe000000
+# CONFIG_LOWMEM_SIZE_BOOL is not set
+CONFIG_LOWMEM_SIZE=0x30000000
+# CONFIG_KERNEL_START_BOOL is not set
+CONFIG_KERNEL_START=0xc0000000
+# CONFIG_TASK_SIZE_BOOL is not set
+CONFIG_TASK_SIZE=0x80000000
+# CONFIG_BOOT_LOAD_BOOL is not set
+CONFIG_BOOT_LOAD=0x00800000
+#
+# Device Drivers
+#
+#
+# Generic Driver Options
+#
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_DEBUG_DRIVER is not set
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+#
+# Plug and Play support
+#
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_SX8 is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=4096
+CONFIG_BLK_DEV_INITRD=y
+# CONFIG_LBD is not set
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+#
+# SCSI device support
+#
+# CONFIG_SCSI is not set
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+#
+# Fusion MPT device support
+#
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+#
+# Macintosh device drivers
+#
+#
+# Networking support
+#
+# CONFIG_NET is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+#
+# ISDN subsystem
+#
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+#
+# Input device support
+#
+CONFIG_INPUT=y
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+CONFIG_INPUT_EVDEV=y
+CONFIG_INPUT_EVBUG=y
+#
+# Input I/O drivers
+#
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+CONFIG_SERIO=y
+# CONFIG_SERIO_I8042 is not set
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_CT82C710 is not set
+# CONFIG_SERIO_PCIPS2 is not set
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_SERIAL_MPC52xx=y
+CONFIG_SERIAL_MPC52xx_CONSOLE=y
+CONFIG_SERIAL_MPC52xx_CONSOLE_BAUD=9600
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_QIC02_TAPE is not set
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_NVRAM is not set
+# CONFIG_GEN_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_FTAPE is not set
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+#
+# Misc devices
+#
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+#
+# Digital Video Broadcasting Devices
+#
+#
+# Graphics support
+#
+# CONFIG_FB is not set
+#
+# Console display driver support
+#
+CONFIG_VGA_CONSOLE=y
+# CONFIG_MDA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+#
+# USB support
+#
+# CONFIG_USB is not set
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_JBD is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_FAT_FS is not set
+# CONFIG_NTFS_FS is not set
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_SYSFS=y
+# CONFIG_DEVFS_FS is not set
+# CONFIG_DEVPTS_FS_XATTR is not set
+CONFIG_TMPFS=y
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+#
+# Native Language Support
+#
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+# CONFIG_NLS_CODEPAGE_437 is not set
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
+CONFIG_NLS_ISO8859_1=m
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_UTF8 is not set
+#
+# Library routines
+#
+# CONFIG_CRC16 is not set
+# CONFIG_CRC32 is not set
+# CONFIG_LIBCRC32C is not set
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+#
+# Kernel hacking
+#
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_DEBUG_SLAB is not set
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_DEBUG_SPINLOCK is not set
+CONFIG_DEBUG_SPINLOCK_SLEEP=y
+# CONFIG_KGDB is not set
+# CONFIG_XMON is not set
+# CONFIG_BDI_SWITCH is not set
+CONFIG_DEBUG_INFO=y
+CONFIG_SERIAL_TEXT_DEBUG=y
+CONFIG_PPC_OCP=y
+#
+# Security options
+#
+# CONFIG_SECURITY is not set
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
diff --git a/arch/ppc/configs/lopec_defconfig b/arch/ppc/configs/lopec_defconfig
new file mode 100644
index 0000000..85ea06b
--- /dev/null
+++ b/arch/ppc/configs/lopec_defconfig
@@ -0,0 +1,814 @@
+#
+# Automatically generated make config: don't edit
+#
+CONFIG_MMU=y
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_HAVE_DEC_LOCK=y
+CONFIG_PPC=y
+CONFIG_PPC32=y
+CONFIG_GENERIC_NVRAM=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=y
+CONFIG_STANDALONE=y
+CONFIG_BROKEN_ON_SMP=y
+
+#
+# General setup
+#
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_HOTPLUG=y
+# CONFIG_IKCONFIG is not set
+CONFIG_EMBEDDED=y
+CONFIG_KALLSYMS=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_OBSOLETE_MODPARM=y
+# CONFIG_MODVERSIONS is not set
+CONFIG_KMOD=y
+
+#
+# Processor
+#
+CONFIG_6xx=y
+# CONFIG_40x is not set
+# CONFIG_44x is not set
+# CONFIG_POWER3 is not set
+# CONFIG_POWER4 is not set
+# CONFIG_8xx is not set
+CONFIG_ALTIVEC=y
+# CONFIG_TAU is not set
+# CONFIG_CPU_FREQ is not set
+CONFIG_PPC_STD_MMU=y
+
+#
+# Platform options
+#
+# CONFIG_PPC_MULTIPLATFORM is not set
+# CONFIG_APUS is not set
+# CONFIG_WILLOW is not set
+# CONFIG_PCORE is not set
+# CONFIG_POWERPMC250 is not set
+# CONFIG_EV64260 is not set
+# CONFIG_SPRUCE is not set
+CONFIG_LOPEC=y
+# CONFIG_MCPN765 is not set
+# CONFIG_MVME5100 is not set
+# CONFIG_PPLUS is not set
+# CONFIG_PRPMC750 is not set
+# CONFIG_PRPMC800 is not set
+# CONFIG_SANDPOINT is not set
+# CONFIG_ADIR is not set
+# CONFIG_K2 is not set
+# CONFIG_PAL4 is not set
+# CONFIG_GEMINI is not set
+# CONFIG_EST8260 is not set
+# CONFIG_SBS8260 is not set
+# CONFIG_RPX6 is not set
+# CONFIG_TQM8260 is not set
+CONFIG_EPIC_SERIAL_MODE=y
+CONFIG_MPC10X_BRIDGE=y
+# CONFIG_MPC10X_STORE_GATHERING is not set
+CONFIG_PPCBUG_NVRAM=y
+# CONFIG_SMP is not set
+# CONFIG_PREEMPT is not set
+# CONFIG_HIGHMEM is not set
+CONFIG_KERNEL_ELF=y
+CONFIG_BINFMT_ELF=y
+CONFIG_BINFMT_MISC=m
+CONFIG_CMDLINE_BOOL=y
+CONFIG_CMDLINE="ip=on"
+
+#
+# Bus options
+#
+CONFIG_GENERIC_ISA_DMA=y
+CONFIG_PCI=y
+CONFIG_PCI_DOMAINS=y
+# CONFIG_PCI_LEGACY_PROC is not set
+CONFIG_PCI_NAMES=y
+
+#
+# PCMCIA/CardBus support
+#
+# CONFIG_PCMCIA is not set
+
+#
+# Advanced setup
+#
+# CONFIG_ADVANCED_OPTIONS is not set
+
+#
+# Default settings for advanced configuration options are used
+#
+CONFIG_HIGHMEM_START=0xfe000000
+CONFIG_LOWMEM_SIZE=0x30000000
+CONFIG_KERNEL_START=0xc0000000
+CONFIG_TASK_SIZE=0x80000000
+CONFIG_BOOT_LOAD=0x00800000
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+# CONFIG_FW_LOADER is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+CONFIG_BLK_DEV_LOOP=m
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_CARMEL is not set
+CONFIG_BLK_DEV_RAM=m
+CONFIG_BLK_DEV_RAM_SIZE=4096
+# CONFIG_LBD is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+CONFIG_IDE=y
+CONFIG_BLK_DEV_IDE=y
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+CONFIG_BLK_DEV_IDEDISK=y
+CONFIG_IDEDISK_MULTI_MODE=y
+# CONFIG_IDEDISK_STROKE is not set
+CONFIG_BLK_DEV_IDECD=y
+# CONFIG_BLK_DEV_IDETAPE is not set
+# CONFIG_BLK_DEV_IDEFLOPPY is not set
+# CONFIG_BLK_DEV_IDESCSI is not set
+# CONFIG_IDE_TASK_IOCTL is not set
+# CONFIG_IDE_TASKFILE_IO is not set
+
+#
+# IDE chipset support/bugfixes
+#
+CONFIG_IDE_GENERIC=y
+CONFIG_BLK_DEV_IDEPCI=y
+# CONFIG_IDEPCI_SHARE_IRQ is not set
+# CONFIG_BLK_DEV_OFFBOARD is not set
+CONFIG_BLK_DEV_GENERIC=y
+# CONFIG_BLK_DEV_OPTI621 is not set
+CONFIG_BLK_DEV_SL82C105=y
+CONFIG_BLK_DEV_IDEDMA_PCI=y
+# CONFIG_BLK_DEV_IDEDMA_FORCED is not set
+CONFIG_IDEDMA_PCI_AUTO=y
+# CONFIG_IDEDMA_ONLYDISK is not set
+CONFIG_BLK_DEV_ADMA=y
+# CONFIG_BLK_DEV_AEC62XX is not set
+# CONFIG_BLK_DEV_ALI15X3 is not set
+# CONFIG_BLK_DEV_AMD74XX is not set
+# CONFIG_BLK_DEV_CMD64X is not set
+# CONFIG_BLK_DEV_TRIFLEX is not set
+# CONFIG_BLK_DEV_CY82C693 is not set
+# CONFIG_BLK_DEV_CS5520 is not set
+# CONFIG_BLK_DEV_CS5530 is not set
+# CONFIG_BLK_DEV_HPT34X is not set
+# CONFIG_BLK_DEV_HPT366 is not set
+# CONFIG_BLK_DEV_SC1200 is not set
+# CONFIG_BLK_DEV_PIIX is not set
+# CONFIG_BLK_DEV_NS87415 is not set
+# CONFIG_BLK_DEV_PDC202XX_OLD is not set
+# CONFIG_BLK_DEV_PDC202XX_NEW is not set
+# CONFIG_BLK_DEV_SVWKS is not set
+# CONFIG_BLK_DEV_SIIMAGE is not set
+# CONFIG_BLK_DEV_SLC90E66 is not set
+# CONFIG_BLK_DEV_TRM290 is not set
+# CONFIG_BLK_DEV_VIA82CXXX is not set
+CONFIG_BLK_DEV_IDEDMA=y
+# CONFIG_IDEDMA_IVB is not set
+CONFIG_IDEDMA_AUTO=y
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# SCSI device support
+#
+CONFIG_SCSI=y
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+# CONFIG_BLK_DEV_SR is not set
+# CONFIG_CHR_DEV_SG is not set
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+# CONFIG_SCSI_MULTI_LUN is not set
+# CONFIG_SCSI_REPORT_LUNS is not set
+CONFIG_SCSI_CONSTANTS=y
+# CONFIG_SCSI_LOGGING is not set
+
+#
+# SCSI Transport Attributes
+#
+CONFIG_SCSI_SPI_ATTRS=y
+# CONFIG_SCSI_FC_ATTRS is not set
+
+#
+# SCSI low-level drivers
+#
+# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
+# CONFIG_SCSI_ACARD is not set
+# CONFIG_SCSI_AACRAID is not set
+# CONFIG_SCSI_AIC7XXX is not set
+# CONFIG_SCSI_AIC7XXX_OLD is not set
+# CONFIG_SCSI_AIC79XX is not set
+# CONFIG_SCSI_ADVANSYS is not set
+# CONFIG_SCSI_MEGARAID is not set
+# CONFIG_SCSI_SATA is not set
+# CONFIG_SCSI_BUSLOGIC is not set
+# CONFIG_SCSI_CPQFCTS is not set
+# CONFIG_SCSI_DMX3191D is not set
+# CONFIG_SCSI_EATA is not set
+# CONFIG_SCSI_EATA_PIO is not set
+# CONFIG_SCSI_FUTURE_DOMAIN is not set
+# CONFIG_SCSI_GDTH is not set
+# CONFIG_SCSI_IPS is not set
+# CONFIG_SCSI_INIA100 is not set
+CONFIG_SCSI_SYM53C8XX_2=y
+CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=0
+CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16
+CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64
+# CONFIG_SCSI_SYM53C8XX_IOMAPPED is not set
+# CONFIG_SCSI_IPR is not set
+# CONFIG_SCSI_QLOGIC_ISP is not set
+# CONFIG_SCSI_QLOGIC_FC is not set
+# CONFIG_SCSI_QLOGIC_1280 is not set
+CONFIG_SCSI_QLA2XXX=y
+# CONFIG_SCSI_QLA21XX is not set
+# CONFIG_SCSI_QLA22XX is not set
+# CONFIG_SCSI_QLA2300 is not set
+# CONFIG_SCSI_QLA2322 is not set
+# CONFIG_SCSI_QLA6312 is not set
+# CONFIG_SCSI_QLA6322 is not set
+# CONFIG_SCSI_DC395x is not set
+# CONFIG_SCSI_DC390T is not set
+# CONFIG_SCSI_NSP32 is not set
+# CONFIG_SCSI_DEBUG is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+# CONFIG_FUSION is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# Macintosh device drivers
+#
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+# CONFIG_NETLINK_DEV is not set
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_PNP=y
+# CONFIG_IP_PNP_DHCP is not set
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_IP_MROUTE is not set
+# CONFIG_ARPD is not set
+CONFIG_SYN_COOKIES=y
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_IPV6 is not set
+# CONFIG_NETFILTER is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_HW_FLOWCONTROL is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+CONFIG_NETDEVICES=y
+CONFIG_DUMMY=m
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_OAKNET is not set
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_NET_VENDOR_3COM is not set
+
+#
+# Tulip family network device support
+#
+# CONFIG_NET_TULIP is not set
+# CONFIG_HP100 is not set
+CONFIG_NET_PCI=y
+# CONFIG_PCNET32 is not set
+# CONFIG_AMD8111_ETH is not set
+# CONFIG_ADAPTEC_STARFIRE is not set
+# CONFIG_B44 is not set
+# CONFIG_FORCEDETH is not set
+# CONFIG_DGRS is not set
+# CONFIG_EEPRO100 is not set
+CONFIG_E100=y
+# CONFIG_E100_NAPI is not set
+# CONFIG_FEALNX is not set
+# CONFIG_NATSEMI is not set
+# CONFIG_NE2K_PCI is not set
+# CONFIG_8139CP is not set
+# CONFIG_8139TOO is not set
+# CONFIG_SIS900 is not set
+# CONFIG_EPIC100 is not set
+# CONFIG_SUNDANCE is not set
+# CONFIG_TLAN is not set
+# CONFIG_VIA_RHINE is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_E1000 is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_TIGON3 is not set
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_IXGB is not set
+# CONFIG_S2IO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_NET_FC is not set
+# CONFIG_RCPCI is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+# CONFIG_INPUT is not set
+
+#
+# Userland interfaces
+#
+
+#
+# Input I/O drivers
+#
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+# CONFIG_SERIO is not set
+# CONFIG_SERIO_I8042 is not set
+
+#
+# Input Device Drivers
+#
+
+#
+# Character devices
+#
+# CONFIG_VT is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=1
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_QIC02_TAPE is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_NVRAM is not set
+CONFIG_GEN_RTC=y
+# CONFIG_GEN_RTC_X is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_FTAPE is not set
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# Misc devices
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+# CONFIG_FB is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+CONFIG_USB=m
+# CONFIG_USB_DEBUG is not set
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEVICEFS=y
+# CONFIG_USB_BANDWIDTH is not set
+# CONFIG_USB_DYNAMIC_MINORS is not set
+
+#
+# USB Host Controller Drivers
+#
+# CONFIG_USB_EHCI_HCD is not set
+CONFIG_USB_OHCI_HCD=m
+# CONFIG_USB_UHCI_HCD is not set
+
+#
+# USB Device Class drivers
+#
+# CONFIG_USB_BLUETOOTH_TTY is not set
+CONFIG_USB_ACM=m
+# CONFIG_USB_PRINTER is not set
+# CONFIG_USB_STORAGE is not set
+
+#
+# USB Human Interface Devices (HID)
+#
+CONFIG_USB_HID=m
+
+#
+# Input core support is needed for USB HID input layer or HIDBP support
+#
+# CONFIG_USB_HIDDEV is not set
+
+#
+# USB HID Boot Protocol drivers
+#
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_MICROTEK is not set
+# CONFIG_USB_HPUSBSCSI is not set
+
+#
+# USB Multimedia devices
+#
+# CONFIG_USB_DABUSB is not set
+
+#
+# Video4Linux support is needed for USB Multimedia device support
+#
+
+#
+# USB Network adaptors
+#
+# CONFIG_USB_CATC is not set
+# CONFIG_USB_KAWETH is not set
+# CONFIG_USB_PEGASUS is not set
+# CONFIG_USB_RTL8150 is not set
+# CONFIG_USB_USBNET is not set
+
+#
+# USB port drivers
+#
+
+#
+# USB Serial Converter support
+#
+CONFIG_USB_SERIAL=m
+# CONFIG_USB_SERIAL_GENERIC is not set
+# CONFIG_USB_SERIAL_BELKIN is not set
+# CONFIG_USB_SERIAL_WHITEHEAT is not set
+# CONFIG_USB_SERIAL_DIGI_ACCELEPORT is not set
+# CONFIG_USB_SERIAL_EMPEG is not set
+# CONFIG_USB_SERIAL_FTDI_SIO is not set
+CONFIG_USB_SERIAL_VISOR=m
+# CONFIG_USB_SERIAL_IPAQ is not set
+# CONFIG_USB_SERIAL_IR is not set
+# CONFIG_USB_SERIAL_EDGEPORT is not set
+# CONFIG_USB_SERIAL_EDGEPORT_TI is not set
+# CONFIG_USB_SERIAL_KEYSPAN_PDA is not set
+# CONFIG_USB_SERIAL_KEYSPAN is not set
+# CONFIG_USB_SERIAL_KLSI is not set
+# CONFIG_USB_SERIAL_KOBIL_SCT is not set
+# CONFIG_USB_SERIAL_MCT_U232 is not set
+# CONFIG_USB_SERIAL_PL2303 is not set
+# CONFIG_USB_SERIAL_SAFE is not set
+# CONFIG_USB_SERIAL_CYBERJACK is not set
+# CONFIG_USB_SERIAL_XIRCOM is not set
+# CONFIG_USB_SERIAL_OMNINET is not set
+
+#
+# USB Miscellaneous drivers
+#
+# CONFIG_USB_EMI62 is not set
+# CONFIG_USB_EMI26 is not set
+# CONFIG_USB_TIGL is not set
+# CONFIG_USB_AUERSWALD is not set
+# CONFIG_USB_RIO500 is not set
+# CONFIG_USB_LEGOTOWER is not set
+# CONFIG_USB_LCD is not set
+# CONFIG_USB_LED is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_PHIDGETSERVO is not set
+# CONFIG_USB_TEST is not set
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_FS_XATTR=y
+# CONFIG_EXT3_FS_POSIX_ACL is not set
+# CONFIG_EXT3_FS_SECURITY is not set
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+CONFIG_FS_MBCACHE=y
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_FAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_SYSFS=y
+# CONFIG_DEVFS_FS is not set
+# CONFIG_DEVPTS_FS_XATTR is not set
+CONFIG_TMPFS=y
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+# CONFIG_NFSD is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+# CONFIG_EXPORTFS is not set
+CONFIG_SUNRPC=y
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+# CONFIG_NLS is not set
+
+#
+# Library routines
+#
+# CONFIG_CRC32 is not set
+# CONFIG_LIBCRC32C is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_DEBUG_KERNEL is not set
+# CONFIG_SERIAL_TEXT_DEBUG is not set
+
+#
+# Security options
+#
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
diff --git a/arch/ppc/configs/luan_defconfig b/arch/ppc/configs/luan_defconfig
new file mode 100644
index 0000000..71d7bf1
--- /dev/null
+++ b/arch/ppc/configs/luan_defconfig
@@ -0,0 +1,668 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.11-rc2
+# Mon Jan 31 16:26:31 2005
+#
+CONFIG_MMU=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_HAVE_DEC_LOCK=y
+CONFIG_PPC=y
+CONFIG_PPC32=y
+CONFIG_GENERIC_NVRAM=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=y
+CONFIG_BROKEN_ON_SMP=y
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_HOTPLUG is not set
+CONFIG_KOBJECT_UEVENT=y
+# CONFIG_IKCONFIG is not set
+CONFIG_EMBEDDED=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SHMEM=y
+CONFIG_CC_ALIGN_FUNCTIONS=0
+CONFIG_CC_ALIGN_LABELS=0
+CONFIG_CC_ALIGN_LOOPS=0
+CONFIG_CC_ALIGN_JUMPS=0
+# CONFIG_TINY_SHMEM is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_OBSOLETE_MODPARM=y
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_KMOD=y
+
+#
+# Processor
+#
+# CONFIG_6xx is not set
+# CONFIG_40x is not set
+CONFIG_44x=y
+# CONFIG_POWER3 is not set
+# CONFIG_POWER4 is not set
+# CONFIG_8xx is not set
+# CONFIG_E500 is not set
+CONFIG_BOOKE=y
+CONFIG_PTE_64BIT=y
+CONFIG_PHYS_64BIT=y
+# CONFIG_MATH_EMULATION is not set
+# CONFIG_CPU_FREQ is not set
+CONFIG_4xx=y
+
+#
+# IBM 4xx options
+#
+# CONFIG_EBONY is not set
+CONFIG_LUAN=y
+# CONFIG_OCOTEA is not set
+CONFIG_440SP=y
+CONFIG_440=y
+CONFIG_IBM_OCP=y
+CONFIG_IBM_EMAC4=y
+# CONFIG_PPC4xx_DMA is not set
+CONFIG_PPC_GEN550=y
+# CONFIG_PM is not set
+CONFIG_NOT_COHERENT_CACHE=y
+
+#
+# Platform options
+#
+# CONFIG_PC_KEYBOARD is not set
+# CONFIG_SMP is not set
+# CONFIG_PREEMPT is not set
+# CONFIG_HIGHMEM is not set
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+CONFIG_CMDLINE_BOOL=y
+CONFIG_CMDLINE="ip=on console=ttyS0,115200"
+
+#
+# Bus options
+#
+CONFIG_PCI=y
+CONFIG_PCI_DOMAINS=y
+# CONFIG_PCI_LEGACY_PROC is not set
+# CONFIG_PCI_NAMES is not set
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# PC-card bridges
+#
+
+#
+# Advanced setup
+#
+# CONFIG_ADVANCED_OPTIONS is not set
+
+#
+# Default settings for advanced configuration options are used
+#
+CONFIG_HIGHMEM_START=0xfe000000
+CONFIG_LOWMEM_SIZE=0x30000000
+CONFIG_KERNEL_START=0xc0000000
+CONFIG_TASK_SIZE=0x80000000
+CONFIG_CONSISTENT_START=0xff100000
+CONFIG_CONSISTENT_SIZE=0x00200000
+CONFIG_BOOT_LOAD=0x01000000
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+# CONFIG_STANDALONE is not set
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+# CONFIG_DEBUG_DRIVER is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_SX8 is not set
+# CONFIG_BLK_DEV_RAM is not set
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_LBD is not set
+# CONFIG_CDROM_PKTCDVD is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_SCSI is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# Macintosh device drivers
+#
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+# CONFIG_NETLINK_DEV is not set
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_PNP=y
+# CONFIG_IP_PNP_DHCP is not set
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_IP_TCPDIAG=y
+# CONFIG_IP_TCPDIAG_IPV6 is not set
+
+#
+# IP: Virtual Server Configuration
+#
+# CONFIG_IP_VS is not set
+# CONFIG_IPV6 is not set
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+
+#
+# IP: Netfilter Configuration
+#
+# CONFIG_IP_NF_CONNTRACK is not set
+# CONFIG_IP_NF_CONNTRACK_MARK is not set
+# CONFIG_IP_NF_QUEUE is not set
+# CONFIG_IP_NF_IPTABLES is not set
+# CONFIG_IP_NF_ARPTABLES is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+# CONFIG_MII is not set
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_NET_VENDOR_3COM is not set
+
+#
+# Tulip family network device support
+#
+# CONFIG_NET_TULIP is not set
+# CONFIG_HP100 is not set
+CONFIG_IBM_EMAC=y
+# CONFIG_IBM_EMAC_ERRMSG is not set
+CONFIG_IBM_EMAC_RXB=128
+CONFIG_IBM_EMAC_TXB=128
+CONFIG_IBM_EMAC_FGAP=8
+CONFIG_IBM_EMAC_SKBRES=0
+# CONFIG_NET_PCI is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_E1000 is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_TIGON3 is not set
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_IXGB is not set
+# CONFIG_S2IO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input I/O drivers
+#
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+CONFIG_SERIO=y
+# CONFIG_SERIO_I8042 is not set
+# CONFIG_SERIO_SERPORT is not set
+# CONFIG_SERIO_CT82C710 is not set
+# CONFIG_SERIO_PCIPS2 is not set
+# CONFIG_SERIO_LIBPS2 is not set
+# CONFIG_SERIO_RAW is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Character devices
+#
+# CONFIG_VT is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=4
+CONFIG_SERIAL_8250_EXTENDED=y
+# CONFIG_SERIAL_8250_MANY_PORTS is not set
+CONFIG_SERIAL_8250_SHARE_IRQ=y
+# CONFIG_SERIAL_8250_DETECT_IRQ is not set
+# CONFIG_SERIAL_8250_MULTIPORT is not set
+# CONFIG_SERIAL_8250_RSA is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_NVRAM is not set
+# CONFIG_GEN_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
+# Misc devices
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+# CONFIG_FB is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+# CONFIG_USB is not set
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# InfiniBand support
+#
+# CONFIG_INFINIBAND is not set
+
+#
+# File systems
+#
+# CONFIG_EXT2_FS is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_JBD is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_SYSFS=y
+# CONFIG_DEVFS_FS is not set
+# CONFIG_DEVPTS_FS_XATTR is not set
+# CONFIG_TMPFS is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+# CONFIG_NFS_V3 is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+# CONFIG_NFSD is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+# CONFIG_EXPORTFS is not set
+CONFIG_SUNRPC=y
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+# CONFIG_NLS is not set
+
+#
+# Library routines
+#
+# CONFIG_CRC_CCITT is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_DEBUG_SLAB is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_KOBJECT is not set
+CONFIG_DEBUG_INFO=y
+# CONFIG_DEBUG_FS is not set
+# CONFIG_KGDB is not set
+# CONFIG_XMON is not set
+CONFIG_BDI_SWITCH=y
+# CONFIG_SERIAL_TEXT_DEBUG is not set
+CONFIG_PPC_OCP=y
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Hardware crypto devices
+#
diff --git a/arch/ppc/configs/mbx_defconfig b/arch/ppc/configs/mbx_defconfig
new file mode 100644
index 0000000..52c3799
--- /dev/null
+++ b/arch/ppc/configs/mbx_defconfig
@@ -0,0 +1,512 @@
+#
+# Automatically generated make config: don't edit
+#
+CONFIG_MMU=y
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_HAVE_DEC_LOCK=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+
+#
+# General setup
+#
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+# CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_SYSCTL is not set
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_EMBEDDED=y
+CONFIG_FUTEX=y
+# CONFIG_EPOLL is not set
+
+#
+# Loadable module support
+#
+# CONFIG_MODULES is not set
+
+#
+# Platform support
+#
+CONFIG_PPC=y
+CONFIG_PPC32=y
+# CONFIG_6xx is not set
+# CONFIG_40x is not set
+# CONFIG_POWER3 is not set
+CONFIG_8xx=y
+
+#
+# IBM 4xx options
+#
+CONFIG_EMBEDDEDBOOT=y
+CONFIG_SERIAL_CONSOLE=y
+CONFIG_NOT_COHERENT_CACHE=y
+# CONFIG_RPXLITE is not set
+# CONFIG_RPXCLASSIC is not set
+# CONFIG_BSEIP is not set
+# CONFIG_FADS is not set
+# CONFIG_TQM823L is not set
+# CONFIG_TQM850L is not set
+# CONFIG_TQM855L is not set
+# CONFIG_TQM860L is not set
+# CONFIG_FPS850L is not set
+# CONFIG_SPD823TS is not set
+# CONFIG_IVMS8 is not set
+# CONFIG_IVML24 is not set
+# CONFIG_SM850 is not set
+# CONFIG_HERMES_PRO is not set
+# CONFIG_IP860 is not set
+# CONFIG_LWMON is not set
+# CONFIG_PCU_E is not set
+# CONFIG_CCM is not set
+# CONFIG_LANTEC is not set
+CONFIG_MBX=y
+# CONFIG_WINCEPT is not set
+# CONFIG_SMP is not set
+# CONFIG_PREEMPT is not set
+CONFIG_MATH_EMULATION=y
+# CONFIG_CPU_FREQ is not set
+
+#
+# General setup
+#
+# CONFIG_HIGHMEM is not set
+# CONFIG_PCI is not set
+# CONFIG_PCI_DOMAINS is not set
+# CONFIG_PCI_QSPAN is not set
+CONFIG_KCORE_ELF=y
+CONFIG_BINFMT_ELF=y
+CONFIG_KERNEL_ELF=y
+# CONFIG_BINFMT_MISC is not set
+# CONFIG_HOTPLUG is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+# CONFIG_CMDLINE_BOOL is not set
+
+#
+# Advanced setup
+#
+# CONFIG_ADVANCED_OPTIONS is not set
+
+#
+# Default settings for advanced configuration options are used
+#
+CONFIG_HIGHMEM_START=0xfe000000
+CONFIG_LOWMEM_SIZE=0x30000000
+CONFIG_KERNEL_START=0xc0000000
+CONFIG_TASK_SIZE=0x80000000
+CONFIG_BOOT_LOAD=0x00400000
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Plug and Play support
+#
+# CONFIG_PNP is not set
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_RAM is not set
+# CONFIG_BLK_DEV_INITRD is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# ATA/IDE/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI support
+#
+# CONFIG_SCSI is not set
+
+#
+# Fusion MPT device support
+#
+
+#
+# I2O device support
+#
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+# CONFIG_PACKET is not set
+# CONFIG_NETLINK_DEV is not set
+# CONFIG_NETFILTER is not set
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+# CONFIG_INET_ECN is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_IPV6 is not set
+# CONFIG_XFRM_USER is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+CONFIG_IPV6_SCTP__=y
+# CONFIG_IP_SCTP is not set
+# CONFIG_ATM is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_LLC is not set
+# CONFIG_DECNET is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_HW_FLOWCONTROL is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_ETHERTAP is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_OAKNET is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Token Ring devices (depends on LLC=y)
+#
+# CONFIG_SHAPER is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+
+#
+# Amateur Radio support
+#
+# CONFIG_HAMRADIO is not set
+
+#
+# IrDA (infrared) support
+#
+# CONFIG_IRDA is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN_BOOL is not set
+
+#
+# Graphics support
+#
+# CONFIG_FB is not set
+
+#
+# Old CD-ROM drivers (not SCSI, not IDE)
+#
+# CONFIG_CD_NO_IDESCSI is not set
+
+#
+# Input device support
+#
+# CONFIG_INPUT is not set
+
+#
+# Userland interfaces
+#
+
+#
+# Input I/O drivers
+#
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+# CONFIG_SERIO is not set
+
+#
+# Input Device Drivers
+#
+
+#
+# Macintosh device drivers
+#
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_SERIAL_CPM=y
+CONFIG_SERIAL_CPM_CONSOLE=y
+# CONFIG_SERIAL_CPM_SCC1 is not set
+CONFIG_SERIAL_CPM_SCC2=y
+CONFIG_SERIAL_CPM_SCC3=y
+# CONFIG_SERIAL_CPM_SCC4 is not set
+CONFIG_SERIAL_CPM_SMC1=y
+CONFIG_SERIAL_CPM_SMC2=y
+CONFIG_UNIX98_PTYS=y
+# CONFIG_LEGACY_PTYS is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# I2C Hardware Sensors Mainboard support
+#
+
+#
+# I2C Hardware Sensors Chip support
+#
+# CONFIG_I2C_SENSOR is not set
+
+#
+# Mice
+#
+# CONFIG_BUSMOUSE is not set
+# CONFIG_QIC02_TAPE is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_NVRAM is not set
+CONFIG_GEN_RTC=y
+# CONFIG_GEN_RTC_X is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_FTAPE is not set
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_HANGCHECK_TIMER is not set
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_FS_XATTR=y
+# CONFIG_EXT3_FS_POSIX_ACL is not set
+# CONFIG_EXT3_FS_SECURITY is not set
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+CONFIG_FS_MBCACHE=y
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_FAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+# CONFIG_DEVFS_FS is not set
+CONFIG_TMPFS=y
+CONFIG_RAMFS=y
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+# CONFIG_NFS_V3 is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFSD is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+# CONFIG_EXPORTFS is not set
+CONFIG_SUNRPC=y
+# CONFIG_SUNRPC_GSS is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_INTERMEZZO_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
+# CONFIG_MSDOS_PARTITION is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_NEC98_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_EFI_PARTITION is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# MPC8xx CPM Options
+#
+CONFIG_SCC_ENET=y
+CONFIG_SCC1_ENET=y
+# CONFIG_SCC2_ENET is not set
+# CONFIG_SCC3_ENET is not set
+# CONFIG_FEC_ENET is not set
+CONFIG_ENET_BIG_BUFFERS=y
+
+#
+# Generic MPC8xx Options
+#
+CONFIG_8xx_COPYBACK=y
+CONFIG_8xx_CPU6=y
+# CONFIG_UCODE_PATCH is not set
+
+#
+# USB support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# Bluetooth support
+#
+# CONFIG_BT is not set
+
+#
+# Library routines
+#
+# CONFIG_CRC32 is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_DEBUG_KERNEL is not set
+# CONFIG_KALLSYMS is not set
+
+#
+# Security options
+#
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
diff --git a/arch/ppc/configs/mcpn765_defconfig b/arch/ppc/configs/mcpn765_defconfig
new file mode 100644
index 0000000..899e89a
--- /dev/null
+++ b/arch/ppc/configs/mcpn765_defconfig
@@ -0,0 +1,579 @@
+#
+# Automatically generated make config: don't edit
+#
+CONFIG_MMU=y
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_HAVE_DEC_LOCK=y
+CONFIG_PPC=y
+CONFIG_PPC32=y
+CONFIG_GENERIC_NVRAM=y
+
+#
+# Code maturity level options
+#
+# CONFIG_EXPERIMENTAL is not set
+CONFIG_CLEAN_COMPILE=y
+CONFIG_STANDALONE=y
+CONFIG_BROKEN_ON_SMP=y
+
+#
+# General setup
+#
+# CONFIG_SWAP is not set
+CONFIG_SYSVIPC=y
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_HOTPLUG is not set
+# CONFIG_IKCONFIG is not set
+CONFIG_EMBEDDED=y
+CONFIG_KALLSYMS=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+# CONFIG_MODULE_UNLOAD is not set
+CONFIG_OBSOLETE_MODPARM=y
+# CONFIG_KMOD is not set
+
+#
+# Processor
+#
+CONFIG_6xx=y
+# CONFIG_40x is not set
+# CONFIG_44x is not set
+# CONFIG_POWER3 is not set
+# CONFIG_POWER4 is not set
+# CONFIG_8xx is not set
+CONFIG_ALTIVEC=y
+# CONFIG_TAU is not set
+# CONFIG_CPU_FREQ is not set
+CONFIG_PPC_STD_MMU=y
+
+#
+# Platform options
+#
+# CONFIG_PPC_MULTIPLATFORM is not set
+# CONFIG_APUS is not set
+# CONFIG_WILLOW is not set
+# CONFIG_PCORE is not set
+# CONFIG_POWERPMC250 is not set
+# CONFIG_EV64260 is not set
+# CONFIG_SPRUCE is not set
+# CONFIG_LOPEC is not set
+CONFIG_MCPN765=y
+# CONFIG_MVME5100 is not set
+# CONFIG_PPLUS is not set
+# CONFIG_PRPMC750 is not set
+# CONFIG_PRPMC800 is not set
+# CONFIG_SANDPOINT is not set
+# CONFIG_ADIR is not set
+# CONFIG_K2 is not set
+# CONFIG_PAL4 is not set
+# CONFIG_GEMINI is not set
+# CONFIG_EST8260 is not set
+# CONFIG_SBS8260 is not set
+# CONFIG_RPX6 is not set
+# CONFIG_TQM8260 is not set
+CONFIG_PPC_GEN550=y
+# CONFIG_SMP is not set
+# CONFIG_PREEMPT is not set
+CONFIG_HIGHMEM=y
+CONFIG_KERNEL_ELF=y
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+CONFIG_CMDLINE_BOOL=y
+CONFIG_CMDLINE="ip=on"
+
+#
+# Bus options
+#
+CONFIG_GENERIC_ISA_DMA=y
+CONFIG_PCI=y
+CONFIG_PCI_DOMAINS=y
+# CONFIG_PCI_LEGACY_PROC is not set
+# CONFIG_PCI_NAMES is not set
+
+#
+# Advanced setup
+#
+# CONFIG_ADVANCED_OPTIONS is not set
+
+#
+# Default settings for advanced configuration options are used
+#
+CONFIG_HIGHMEM_START=0xfe000000
+CONFIG_LOWMEM_SIZE=0x30000000
+CONFIG_KERNEL_START=0xc0000000
+CONFIG_TASK_SIZE=0x80000000
+CONFIG_BOOT_LOAD=0x00800000
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_CARMEL is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=4096
+CONFIG_BLK_DEV_INITRD=y
+# CONFIG_LBD is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+CONFIG_IDE=y
+CONFIG_BLK_DEV_IDE=y
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+CONFIG_BLK_DEV_IDEDISK=y
+# CONFIG_IDEDISK_MULTI_MODE is not set
+# CONFIG_IDEDISK_STROKE is not set
+# CONFIG_BLK_DEV_IDECD is not set
+# CONFIG_BLK_DEV_IDEFLOPPY is not set
+# CONFIG_IDE_TASK_IOCTL is not set
+
+#
+# IDE chipset support/bugfixes
+#
+# CONFIG_IDE_GENERIC is not set
+CONFIG_BLK_DEV_IDEPCI=y
+# CONFIG_IDEPCI_SHARE_IRQ is not set
+# CONFIG_BLK_DEV_OFFBOARD is not set
+# CONFIG_BLK_DEV_GENERIC is not set
+# CONFIG_BLK_DEV_SL82C105 is not set
+CONFIG_BLK_DEV_IDEDMA_PCI=y
+# CONFIG_BLK_DEV_IDEDMA_FORCED is not set
+# CONFIG_IDEDMA_PCI_AUTO is not set
+CONFIG_BLK_DEV_ADMA=y
+# CONFIG_BLK_DEV_AEC62XX is not set
+# CONFIG_BLK_DEV_ALI15X3 is not set
+# CONFIG_BLK_DEV_AMD74XX is not set
+# CONFIG_BLK_DEV_CMD64X is not set
+# CONFIG_BLK_DEV_TRIFLEX is not set
+# CONFIG_BLK_DEV_CY82C693 is not set
+# CONFIG_BLK_DEV_CS5530 is not set
+# CONFIG_BLK_DEV_HPT34X is not set
+# CONFIG_BLK_DEV_HPT366 is not set
+# CONFIG_BLK_DEV_SC1200 is not set
+# CONFIG_BLK_DEV_PIIX is not set
+# CONFIG_BLK_DEV_NS87415 is not set
+# CONFIG_BLK_DEV_PDC202XX_OLD is not set
+# CONFIG_BLK_DEV_PDC202XX_NEW is not set
+# CONFIG_BLK_DEV_SVWKS is not set
+# CONFIG_BLK_DEV_SIIMAGE is not set
+# CONFIG_BLK_DEV_SLC90E66 is not set
+# CONFIG_BLK_DEV_TRM290 is not set
+CONFIG_BLK_DEV_VIA82CXXX=y
+CONFIG_BLK_DEV_IDEDMA=y
+# CONFIG_IDEDMA_IVB is not set
+# CONFIG_IDEDMA_AUTO is not set
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# SCSI device support
+#
+# CONFIG_SCSI is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+# CONFIG_FUSION is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# Macintosh device drivers
+#
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+# CONFIG_NETLINK_DEV is not set
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+# CONFIG_IP_PNP_BOOTP is not set
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_DECNET is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_NETFILTER is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+CONFIG_NETDEVICES=y
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_OAKNET is not set
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_NET_VENDOR_3COM is not set
+
+#
+# Tulip family network device support
+#
+CONFIG_NET_TULIP=y
+CONFIG_TULIP=y
+# CONFIG_TULIP_MMIO is not set
+# CONFIG_TULIP_NAPI is not set
+# CONFIG_DE4X5 is not set
+# CONFIG_WINBOND_840 is not set
+# CONFIG_DM9102 is not set
+# CONFIG_HP100 is not set
+# CONFIG_NET_PCI is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_E1000 is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_R8169 is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_TIGON3 is not set
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_IXGB is not set
+# CONFIG_FDDI is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+
+#
+# Amateur Radio support
+#
+# CONFIG_HAMRADIO is not set
+
+#
+# IrDA (infrared) support
+#
+# CONFIG_IRDA is not set
+
+#
+# Bluetooth support
+#
+# CONFIG_BT is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+# CONFIG_INPUT is not set
+
+#
+# Userland interfaces
+#
+
+#
+# Input I/O drivers
+#
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+# CONFIG_SERIO is not set
+# CONFIG_SERIO_I8042 is not set
+
+#
+# Input Device Drivers
+#
+
+#
+# Character devices
+#
+# CONFIG_VT is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=4
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_QIC02_TAPE is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_NVRAM is not set
+CONFIG_GEN_RTC=y
+# CONFIG_GEN_RTC_X is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_FTAPE is not set
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# Misc devices
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+# CONFIG_FB is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+# CONFIG_USB is not set
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_JBD is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_FAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+# CONFIG_DEVPTS_FS_XATTR is not set
+CONFIG_TMPFS=y
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+# CONFIG_NFS_V3 is not set
+# CONFIG_NFSD is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+# CONFIG_EXPORTFS is not set
+CONFIG_SUNRPC=y
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+# CONFIG_NLS is not set
+
+#
+# Library routines
+#
+CONFIG_CRC32=y
+
+#
+# Kernel hacking
+#
+# CONFIG_DEBUG_KERNEL is not set
+# CONFIG_SERIAL_TEXT_DEBUG is not set
+
+#
+# Security options
+#
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
diff --git a/arch/ppc/configs/menf1_defconfig b/arch/ppc/configs/menf1_defconfig
new file mode 100644
index 0000000..321659b
--- /dev/null
+++ b/arch/ppc/configs/menf1_defconfig
@@ -0,0 +1,621 @@
+#
+# Automatically generated make config: don't edit
+#
+CONFIG_MMU=y
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_HAVE_DEC_LOCK=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+
+#
+# General setup
+#
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_EMBEDDED is not set
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_OBSOLETE_MODPARM=y
+# CONFIG_MODVERSIONS is not set
+CONFIG_KMOD=y
+
+#
+# Platform support
+#
+CONFIG_PPC=y
+CONFIG_PPC32=y
+CONFIG_6xx=y
+# CONFIG_40x is not set
+# CONFIG_POWER3 is not set
+# CONFIG_8xx is not set
+
+#
+# IBM 4xx options
+#
+# CONFIG_8260 is not set
+CONFIG_GENERIC_ISA_DMA=y
+CONFIG_PPC_STD_MMU=y
+# CONFIG_PPC_MULTIPLATFORM is not set
+# CONFIG_APUS is not set
+# CONFIG_WILLOW_2 is not set
+# CONFIG_PCORE is not set
+# CONFIG_POWERPMC250 is not set
+# CONFIG_EV64260 is not set
+# CONFIG_SPRUCE is not set
+CONFIG_MENF1=y
+# CONFIG_LOPEC is not set
+# CONFIG_MCPN765 is not set
+# CONFIG_MVME5100 is not set
+# CONFIG_PPLUS is not set
+# CONFIG_PRPMC750 is not set
+# CONFIG_PRPMC800 is not set
+# CONFIG_SANDPOINT is not set
+# CONFIG_ADIR is not set
+# CONFIG_K2 is not set
+# CONFIG_PAL4 is not set
+# CONFIG_GEMINI is not set
+CONFIG_MPC10X_STORE_GATHERING=y
+# CONFIG_SMP is not set
+# CONFIG_PREEMPT is not set
+# CONFIG_ALTIVEC is not set
+# CONFIG_TAU is not set
+# CONFIG_CPU_FREQ is not set
+
+#
+# General setup
+#
+# CONFIG_HIGHMEM is not set
+CONFIG_PCI=y
+CONFIG_PCI_DOMAINS=y
+CONFIG_KCORE_ELF=y
+CONFIG_BINFMT_ELF=y
+CONFIG_KERNEL_ELF=y
+# CONFIG_BINFMT_MISC is not set
+# CONFIG_PCI_LEGACY_PROC is not set
+# CONFIG_PCI_NAMES is not set
+# CONFIG_HOTPLUG is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+# CONFIG_PPC601_SYNC_FIX is not set
+CONFIG_CMDLINE_BOOL=y
+CONFIG_CMDLINE="ip=on"
+
+#
+# Advanced setup
+#
+# CONFIG_ADVANCED_OPTIONS is not set
+
+#
+# Default settings for advanced configuration options are used
+#
+CONFIG_HIGHMEM_START=0xfe000000
+CONFIG_LOWMEM_SIZE=0x30000000
+CONFIG_KERNEL_START=0xc0000000
+CONFIG_TASK_SIZE=0x80000000
+CONFIG_BOOT_LOAD=0x00800000
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Plug and Play support
+#
+# CONFIG_PNP is not set
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_RAM is not set
+# CONFIG_BLK_DEV_INITRD is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# ATA/IDE/MFM/RLL support
+#
+CONFIG_IDE=y
+
+#
+# IDE, ATA and ATAPI Block devices
+#
+CONFIG_BLK_DEV_IDE=y
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+# CONFIG_BLK_DEV_HD is not set
+CONFIG_BLK_DEV_IDEDISK=y
+# CONFIG_IDEDISK_MULTI_MODE is not set
+# CONFIG_IDEDISK_STROKE is not set
+CONFIG_BLK_DEV_IDECD=y
+# CONFIG_BLK_DEV_IDEFLOPPY is not set
+# CONFIG_IDE_TASK_IOCTL is not set
+
+#
+# IDE chipset support/bugfixes
+#
+# CONFIG_BLK_DEV_IDEPCI is not set
+
+#
+# SCSI support
+#
+# CONFIG_SCSI is not set
+
+#
+# Fusion MPT device support
+#
+
+#
+# IEEE 1394 (FireWire) support (EXPERIMENTAL)
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+# CONFIG_NETLINK_DEV is not set
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+# CONFIG_IP_PNP_BOOTP is not set
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_IP_MROUTE is not set
+# CONFIG_ARPD is not set
+# CONFIG_INET_ECN is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+
+#
+# IP: Netfilter Configuration
+#
+CONFIG_IP_NF_CONNTRACK=m
+CONFIG_IP_NF_FTP=m
+CONFIG_IP_NF_IRC=m
+# CONFIG_IP_NF_TFTP is not set
+# CONFIG_IP_NF_AMANDA is not set
+# CONFIG_IP_NF_QUEUE is not set
+CONFIG_IP_NF_IPTABLES=m
+CONFIG_IP_NF_MATCH_LIMIT=m
+CONFIG_IP_NF_MATCH_MAC=m
+CONFIG_IP_NF_MATCH_PKTTYPE=m
+CONFIG_IP_NF_MATCH_MARK=m
+CONFIG_IP_NF_MATCH_MULTIPORT=m
+CONFIG_IP_NF_MATCH_TOS=m
+CONFIG_IP_NF_MATCH_ECN=m
+CONFIG_IP_NF_MATCH_DSCP=m
+CONFIG_IP_NF_MATCH_AH_ESP=m
+CONFIG_IP_NF_MATCH_LENGTH=m
+CONFIG_IP_NF_MATCH_TTL=m
+CONFIG_IP_NF_MATCH_TCPMSS=m
+CONFIG_IP_NF_MATCH_HELPER=m
+CONFIG_IP_NF_MATCH_STATE=m
+CONFIG_IP_NF_MATCH_CONNTRACK=m
+CONFIG_IP_NF_MATCH_UNCLEAN=m
+CONFIG_IP_NF_MATCH_OWNER=m
+CONFIG_IP_NF_FILTER=m
+CONFIG_IP_NF_TARGET_REJECT=m
+CONFIG_IP_NF_TARGET_MIRROR=m
+CONFIG_IP_NF_NAT=m
+CONFIG_IP_NF_NAT_NEEDED=y
+CONFIG_IP_NF_TARGET_MASQUERADE=m
+CONFIG_IP_NF_TARGET_REDIRECT=m
+# CONFIG_IP_NF_NAT_SNMP_BASIC is not set
+CONFIG_IP_NF_NAT_IRC=m
+CONFIG_IP_NF_NAT_FTP=m
+# CONFIG_IP_NF_MANGLE is not set
+# CONFIG_IP_NF_TARGET_LOG is not set
+CONFIG_IP_NF_TARGET_ULOG=m
+CONFIG_IP_NF_TARGET_TCPMSS=m
+CONFIG_IP_NF_ARPTABLES=m
+CONFIG_IP_NF_ARPFILTER=m
+CONFIG_IP_NF_COMPAT_IPCHAINS=m
+# CONFIG_IP_NF_COMPAT_IPFWADM is not set
+# CONFIG_IPV6 is not set
+# CONFIG_XFRM_USER is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+CONFIG_IPV6_SCTP__=y
+# CONFIG_IP_SCTP is not set
+# CONFIG_ATM is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_LLC is not set
+# CONFIG_DECNET is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_HW_FLOWCONTROL is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+CONFIG_NETDEVICES=y
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_ETHERTAP is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_OAKNET is not set
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_NET_VENDOR_3COM is not set
+
+#
+# Tulip family network device support
+#
+# CONFIG_NET_TULIP is not set
+# CONFIG_HP100 is not set
+CONFIG_NET_PCI=y
+# CONFIG_PCNET32 is not set
+# CONFIG_AMD8111_ETH is not set
+# CONFIG_ADAPTEC_STARFIRE is not set
+# CONFIG_B44 is not set
+# CONFIG_DGRS is not set
+# CONFIG_EEPRO100 is not set
+# CONFIG_E100 is not set
+# CONFIG_FEALNX is not set
+# CONFIG_NATSEMI is not set
+# CONFIG_NE2K_PCI is not set
+# CONFIG_8139CP is not set
+# CONFIG_8139TOO is not set
+# CONFIG_SIS900 is not set
+# CONFIG_EPIC100 is not set
+# CONFIG_SUNDANCE is not set
+# CONFIG_TLAN is not set
+# CONFIG_VIA_RHINE is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_E1000 is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_TIGON3 is not set
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_IXGB is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Token Ring devices (depends on LLC=y)
+#
+# CONFIG_RCPCI is not set
+# CONFIG_SHAPER is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+
+#
+# Amateur Radio support
+#
+# CONFIG_HAMRADIO is not set
+
+#
+# IrDA (infrared) support
+#
+# CONFIG_IRDA is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN_BOOL is not set
+
+#
+# Graphics support
+#
+# CONFIG_FB is not set
+
+#
+# Old CD-ROM drivers (not SCSI, not IDE)
+#
+# CONFIG_CD_NO_IDESCSI is not set
+
+#
+# Input device support
+#
+# CONFIG_INPUT is not set
+
+#
+# Userland interfaces
+#
+
+#
+# Input I/O drivers
+#
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+# CONFIG_SERIO is not set
+
+#
+# Input Device Drivers
+#
+
+#
+# Macintosh device drivers
+#
+
+#
+# Character devices
+#
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_UNIX98_PTY_COUNT=256
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# I2C Hardware Sensors Mainboard support
+#
+
+#
+# I2C Hardware Sensors Chip support
+#
+# CONFIG_I2C_SENSOR is not set
+
+#
+# Mice
+#
+# CONFIG_BUSMOUSE is not set
+# CONFIG_QIC02_TAPE is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_NVRAM is not set
+CONFIG_GEN_RTC=y
+# CONFIG_GEN_RTC_X is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_FTAPE is not set
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_HANGCHECK_TIMER is not set
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_FS_XATTR=y
+# CONFIG_EXT3_FS_POSIX_ACL is not set
+# CONFIG_EXT3_FS_SECURITY is not set
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+CONFIG_FS_MBCACHE=y
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+CONFIG_ISO9660_FS=y
+# CONFIG_JOLIET is not set
+# CONFIG_ZISOFS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_FAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+# CONFIG_DEVFS_FS is not set
+CONFIG_DEVPTS_FS=y
+# CONFIG_DEVPTS_FS_XATTR is not set
+CONFIG_TMPFS=y
+CONFIG_RAMFS=y
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+# CONFIG_NFS_V3 is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFSD is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+# CONFIG_EXPORTFS is not set
+CONFIG_SUNRPC=y
+# CONFIG_SUNRPC_GSS is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_INTERMEZZO_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+# CONFIG_USB is not set
+# CONFIG_USB_GADGET is not set
+
+#
+# Bluetooth support
+#
+# CONFIG_BT is not set
+
+#
+# Library routines
+#
+# CONFIG_CRC32 is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_DEBUG_KERNEL is not set
+# CONFIG_KALLSYMS is not set
+
+#
+# Security options
+#
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
diff --git a/arch/ppc/configs/mpc834x_sys_defconfig b/arch/ppc/configs/mpc834x_sys_defconfig
new file mode 100644
index 0000000..4a5522c
--- /dev/null
+++ b/arch/ppc/configs/mpc834x_sys_defconfig
@@ -0,0 +1,644 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.11-rc4
+# Thu Feb 17 16:12:23 2005
+#
+CONFIG_MMU=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_HAVE_DEC_LOCK=y
+CONFIG_PPC=y
+CONFIG_PPC32=y
+CONFIG_GENERIC_NVRAM=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=y
+CONFIG_BROKEN_ON_SMP=y
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_HOTPLUG is not set
+CONFIG_KOBJECT_UEVENT=y
+# CONFIG_IKCONFIG is not set
+CONFIG_EMBEDDED=y
+# CONFIG_KALLSYMS is not set
+CONFIG_FUTEX=y
+# CONFIG_EPOLL is not set
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SHMEM=y
+CONFIG_CC_ALIGN_FUNCTIONS=0
+CONFIG_CC_ALIGN_LABELS=0
+CONFIG_CC_ALIGN_LOOPS=0
+CONFIG_CC_ALIGN_JUMPS=0
+# CONFIG_TINY_SHMEM is not set
+
+#
+# Loadable module support
+#
+# CONFIG_MODULES is not set
+
+#
+# Processor
+#
+CONFIG_6xx=y
+# CONFIG_40x is not set
+# CONFIG_44x is not set
+# CONFIG_POWER3 is not set
+# CONFIG_POWER4 is not set
+# CONFIG_8xx is not set
+# CONFIG_E500 is not set
+# CONFIG_CPU_FREQ is not set
+CONFIG_PPC_GEN550=y
+CONFIG_83xx=y
+
+#
+# Freescale 83xx options
+#
+CONFIG_MPC834x_SYS=y
+CONFIG_MPC834x=y
+CONFIG_PPC_STD_MMU=y
+
+#
+# Platform options
+#
+# CONFIG_SMP is not set
+# CONFIG_PREEMPT is not set
+# CONFIG_HIGHMEM is not set
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+# CONFIG_CMDLINE_BOOL is not set
+
+#
+# Bus options
+#
+CONFIG_GENERIC_ISA_DMA=y
+# CONFIG_PCI is not set
+# CONFIG_PCI_DOMAINS is not set
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# PC-card bridges
+#
+
+#
+# Advanced setup
+#
+# CONFIG_ADVANCED_OPTIONS is not set
+
+#
+# Default settings for advanced configuration options are used
+#
+CONFIG_HIGHMEM_START=0xfe000000
+CONFIG_LOWMEM_SIZE=0x30000000
+CONFIG_KERNEL_START=0xc0000000
+CONFIG_TASK_SIZE=0x80000000
+CONFIG_BOOT_LOAD=0x00800000
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=32768
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_LBD is not set
+# CONFIG_CDROM_PKTCDVD is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_SCSI is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+
+#
+# IEEE 1394 (FireWire) support
+#
+
+#
+# I2O device support
+#
+
+#
+# Macintosh device drivers
+#
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+# CONFIG_NETLINK_DEV is not set
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_IP_MROUTE is not set
+# CONFIG_ARPD is not set
+CONFIG_SYN_COOKIES=y
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_IP_TCPDIAG=y
+# CONFIG_IP_TCPDIAG_IPV6 is not set
+# CONFIG_IPV6 is not set
+# CONFIG_NETFILTER is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+
+#
+# Ethernet (1000 Mbit)
+#
+CONFIG_GIANFAR=y
+# CONFIG_GFAR_NAPI is not set
+
+#
+# Ethernet (10000 Mbit)
+#
+
+#
+# Token Ring devices
+#
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input I/O drivers
+#
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+# CONFIG_SERIO is not set
+# CONFIG_SERIO_I8042 is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Character devices
+#
+# CONFIG_VT is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=4
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_NVRAM is not set
+CONFIG_GEN_RTC=y
+# CONFIG_GEN_RTC_X is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# I2C support
+#
+CONFIG_I2C=y
+CONFIG_I2C_CHARDEV=y
+
+#
+# I2C Algorithms
+#
+# CONFIG_I2C_ALGOBIT is not set
+# CONFIG_I2C_ALGOPCF is not set
+# CONFIG_I2C_ALGOPCA is not set
+
+#
+# I2C Hardware Bus support
+#
+# CONFIG_I2C_ISA is not set
+CONFIG_I2C_MPC=y
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_PCA_ISA is not set
+
+#
+# Hardware Sensors Chip support
+#
+# CONFIG_I2C_SENSOR is not set
+# CONFIG_SENSORS_ADM1021 is not set
+# CONFIG_SENSORS_ADM1025 is not set
+# CONFIG_SENSORS_ADM1026 is not set
+# CONFIG_SENSORS_ADM1031 is not set
+# CONFIG_SENSORS_ASB100 is not set
+# CONFIG_SENSORS_DS1621 is not set
+# CONFIG_SENSORS_FSCHER is not set
+# CONFIG_SENSORS_GL518SM is not set
+# CONFIG_SENSORS_IT87 is not set
+# CONFIG_SENSORS_LM63 is not set
+# CONFIG_SENSORS_LM75 is not set
+# CONFIG_SENSORS_LM77 is not set
+# CONFIG_SENSORS_LM78 is not set
+# CONFIG_SENSORS_LM80 is not set
+# CONFIG_SENSORS_LM83 is not set
+# CONFIG_SENSORS_LM85 is not set
+# CONFIG_SENSORS_LM87 is not set
+# CONFIG_SENSORS_LM90 is not set
+# CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_PC87360 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_W83781D is not set
+# CONFIG_SENSORS_W83L785TS is not set
+# CONFIG_SENSORS_W83627HF is not set
+
+#
+# Other I2C Chip support
+#
+# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_SENSORS_RTC8564 is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
+# Misc devices
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+# CONFIG_FB is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+# CONFIG_USB_ARCH_HAS_HCD is not set
+# CONFIG_USB_ARCH_HAS_OHCI is not set
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# InfiniBand support
+#
+# CONFIG_INFINIBAND is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_FS_XATTR=y
+# CONFIG_EXT3_FS_POSIX_ACL is not set
+# CONFIG_EXT3_FS_SECURITY is not set
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+CONFIG_FS_MBCACHE=y
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+
+#
+# XFS support
+#
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_SYSFS=y
+# CONFIG_DEVFS_FS is not set
+# CONFIG_DEVPTS_FS_XATTR is not set
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_XATTR is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+# CONFIG_NFS_V3 is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+# CONFIG_NFSD is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_SUNRPC=y
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
+# CONFIG_MSDOS_PARTITION is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_EFI_PARTITION is not set
+
+#
+# Native Language Support
+#
+# CONFIG_NLS is not set
+
+#
+# Library routines
+#
+# CONFIG_CRC_CCITT is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_DEBUG_KERNEL is not set
+# CONFIG_SERIAL_TEXT_DEBUG is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Hardware crypto devices
+#
diff --git a/arch/ppc/configs/mpc8540_ads_defconfig b/arch/ppc/configs/mpc8540_ads_defconfig
new file mode 100644
index 0000000..c5c8602
--- /dev/null
+++ b/arch/ppc/configs/mpc8540_ads_defconfig
@@ -0,0 +1,707 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.11-rc1
+# Thu Jan 20 01:23:13 2005
+#
+CONFIG_MMU=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_HAVE_DEC_LOCK=y
+CONFIG_PPC=y
+CONFIG_PPC32=y
+CONFIG_GENERIC_NVRAM=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=y
+CONFIG_BROKEN_ON_SMP=y
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_HOTPLUG is not set
+CONFIG_KOBJECT_UEVENT=y
+# CONFIG_IKCONFIG is not set
+CONFIG_EMBEDDED=y
+# CONFIG_KALLSYMS is not set
+CONFIG_FUTEX=y
+# CONFIG_EPOLL is not set
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SHMEM=y
+CONFIG_CC_ALIGN_FUNCTIONS=0
+CONFIG_CC_ALIGN_LABELS=0
+CONFIG_CC_ALIGN_LOOPS=0
+CONFIG_CC_ALIGN_JUMPS=0
+# CONFIG_TINY_SHMEM is not set
+
+#
+# Loadable module support
+#
+# CONFIG_MODULES is not set
+
+#
+# Processor
+#
+# CONFIG_6xx is not set
+# CONFIG_40x is not set
+# CONFIG_44x is not set
+# CONFIG_POWER3 is not set
+# CONFIG_POWER4 is not set
+# CONFIG_8xx is not set
+CONFIG_E500=y
+CONFIG_BOOKE=y
+CONFIG_FSL_BOOKE=y
+CONFIG_SPE=y
+CONFIG_MATH_EMULATION=y
+# CONFIG_CPU_FREQ is not set
+CONFIG_PPC_GEN550=y
+CONFIG_85xx=y
+CONFIG_PPC_INDIRECT_PCI_BE=y
+
+#
+# Freescale 85xx options
+#
+CONFIG_MPC8540_ADS=y
+# CONFIG_MPC8555_CDS is not set
+# CONFIG_MPC8560_ADS is not set
+# CONFIG_SBC8560 is not set
+CONFIG_MPC8540=y
+
+#
+# Platform options
+#
+# CONFIG_SMP is not set
+# CONFIG_PREEMPT is not set
+# CONFIG_HIGHMEM is not set
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+# CONFIG_CMDLINE_BOOL is not set
+
+#
+# Bus options
+#
+CONFIG_PCI=y
+CONFIG_PCI_DOMAINS=y
+# CONFIG_PCI_LEGACY_PROC is not set
+CONFIG_PCI_NAMES=y
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# PC-card bridges
+#
+
+#
+# Advanced setup
+#
+# CONFIG_ADVANCED_OPTIONS is not set
+
+#
+# Default settings for advanced configuration options are used
+#
+CONFIG_HIGHMEM_START=0xfe000000
+CONFIG_LOWMEM_SIZE=0x30000000
+CONFIG_KERNEL_START=0xc0000000
+CONFIG_TASK_SIZE=0x80000000
+CONFIG_BOOT_LOAD=0x00800000
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_SX8 is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=32768
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_LBD is not set
+# CONFIG_CDROM_PKTCDVD is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_SCSI is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# Macintosh device drivers
+#
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+# CONFIG_NETLINK_DEV is not set
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_IP_MROUTE is not set
+# CONFIG_ARPD is not set
+CONFIG_SYN_COOKIES=y
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_IP_TCPDIAG=y
+# CONFIG_IP_TCPDIAG_IPV6 is not set
+# CONFIG_IPV6 is not set
+# CONFIG_NETFILTER is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_NET_VENDOR_3COM is not set
+
+#
+# Tulip family network device support
+#
+# CONFIG_NET_TULIP is not set
+# CONFIG_HP100 is not set
+# CONFIG_NET_PCI is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_E1000 is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_TIGON3 is not set
+CONFIG_GIANFAR=y
+CONFIG_GFAR_NAPI=y
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_IXGB is not set
+# CONFIG_S2IO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input I/O drivers
+#
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+# CONFIG_SERIO is not set
+# CONFIG_SERIO_I8042 is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Character devices
+#
+# CONFIG_VT is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=4
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_NVRAM is not set
+CONFIG_GEN_RTC=y
+# CONFIG_GEN_RTC_X is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# I2C support
+#
+CONFIG_I2C=y
+CONFIG_I2C_CHARDEV=y
+
+#
+# I2C Algorithms
+#
+# CONFIG_I2C_ALGOBIT is not set
+# CONFIG_I2C_ALGOPCF is not set
+# CONFIG_I2C_ALGOPCA is not set
+
+#
+# I2C Hardware Bus support
+#
+# CONFIG_I2C_ALI1535 is not set
+# CONFIG_I2C_ALI1563 is not set
+# CONFIG_I2C_ALI15X3 is not set
+# CONFIG_I2C_AMD756 is not set
+# CONFIG_I2C_AMD8111 is not set
+# CONFIG_I2C_I801 is not set
+# CONFIG_I2C_I810 is not set
+# CONFIG_I2C_ISA is not set
+CONFIG_I2C_MPC=y
+# CONFIG_I2C_NFORCE2 is not set
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_PIIX4 is not set
+# CONFIG_I2C_PROSAVAGE is not set
+# CONFIG_I2C_SAVAGE4 is not set
+# CONFIG_SCx200_ACB is not set
+# CONFIG_I2C_SIS5595 is not set
+# CONFIG_I2C_SIS630 is not set
+# CONFIG_I2C_SIS96X is not set
+# CONFIG_I2C_VIA is not set
+# CONFIG_I2C_VIAPRO is not set
+# CONFIG_I2C_VOODOO3 is not set
+# CONFIG_I2C_PCA_ISA is not set
+
+#
+# Hardware Sensors Chip support
+#
+# CONFIG_I2C_SENSOR is not set
+# CONFIG_SENSORS_ADM1021 is not set
+# CONFIG_SENSORS_ADM1025 is not set
+# CONFIG_SENSORS_ADM1026 is not set
+# CONFIG_SENSORS_ADM1031 is not set
+# CONFIG_SENSORS_ASB100 is not set
+# CONFIG_SENSORS_DS1621 is not set
+# CONFIG_SENSORS_FSCHER is not set
+# CONFIG_SENSORS_GL518SM is not set
+# CONFIG_SENSORS_IT87 is not set
+# CONFIG_SENSORS_LM63 is not set
+# CONFIG_SENSORS_LM75 is not set
+# CONFIG_SENSORS_LM77 is not set
+# CONFIG_SENSORS_LM78 is not set
+# CONFIG_SENSORS_LM80 is not set
+# CONFIG_SENSORS_LM83 is not set
+# CONFIG_SENSORS_LM85 is not set
+# CONFIG_SENSORS_LM87 is not set
+# CONFIG_SENSORS_LM90 is not set
+# CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_PC87360 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_VIA686A is not set
+# CONFIG_SENSORS_W83781D is not set
+# CONFIG_SENSORS_W83L785TS is not set
+# CONFIG_SENSORS_W83627HF is not set
+
+#
+# Other I2C Chip support
+#
+# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_SENSORS_RTC8564 is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
+# Misc devices
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+# CONFIG_FB is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+# CONFIG_USB is not set
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# InfiniBand support
+#
+# CONFIG_INFINIBAND is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_FS_XATTR=y
+# CONFIG_EXT3_FS_POSIX_ACL is not set
+# CONFIG_EXT3_FS_SECURITY is not set
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+CONFIG_FS_MBCACHE=y
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_SYSFS=y
+# CONFIG_DEVFS_FS is not set
+# CONFIG_DEVPTS_FS_XATTR is not set
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_XATTR is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+# CONFIG_NFS_V3 is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+# CONFIG_NFSD is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+# CONFIG_EXPORTFS is not set
+CONFIG_SUNRPC=y
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
+# CONFIG_MSDOS_PARTITION is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_EFI_PARTITION is not set
+
+#
+# Native Language Support
+#
+# CONFIG_NLS is not set
+
+#
+# Library routines
+#
+# CONFIG_CRC_CCITT is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_DEBUG_KERNEL is not set
+# CONFIG_SERIAL_TEXT_DEBUG is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Hardware crypto devices
+#
diff --git a/arch/ppc/configs/mpc8555_cds_defconfig b/arch/ppc/configs/mpc8555_cds_defconfig
new file mode 100644
index 0000000..728bd9e
--- /dev/null
+++ b/arch/ppc/configs/mpc8555_cds_defconfig
@@ -0,0 +1,718 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.11-rc1
+# Thu Jan 20 01:25:35 2005
+#
+CONFIG_MMU=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_HAVE_DEC_LOCK=y
+CONFIG_PPC=y
+CONFIG_PPC32=y
+CONFIG_GENERIC_NVRAM=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=y
+CONFIG_BROKEN_ON_SMP=y
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_HOTPLUG is not set
+CONFIG_KOBJECT_UEVENT=y
+# CONFIG_IKCONFIG is not set
+CONFIG_EMBEDDED=y
+# CONFIG_KALLSYMS is not set
+CONFIG_FUTEX=y
+# CONFIG_EPOLL is not set
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SHMEM=y
+CONFIG_CC_ALIGN_FUNCTIONS=0
+CONFIG_CC_ALIGN_LABELS=0
+CONFIG_CC_ALIGN_LOOPS=0
+CONFIG_CC_ALIGN_JUMPS=0
+# CONFIG_TINY_SHMEM is not set
+
+#
+# Loadable module support
+#
+# CONFIG_MODULES is not set
+
+#
+# Processor
+#
+# CONFIG_6xx is not set
+# CONFIG_40x is not set
+# CONFIG_44x is not set
+# CONFIG_POWER3 is not set
+# CONFIG_POWER4 is not set
+# CONFIG_8xx is not set
+CONFIG_E500=y
+CONFIG_BOOKE=y
+CONFIG_FSL_BOOKE=y
+CONFIG_SPE=y
+CONFIG_MATH_EMULATION=y
+# CONFIG_CPU_FREQ is not set
+CONFIG_PPC_GEN550=y
+CONFIG_85xx=y
+CONFIG_PPC_INDIRECT_PCI_BE=y
+
+#
+# Freescale 85xx options
+#
+# CONFIG_MPC8540_ADS is not set
+CONFIG_MPC8555_CDS=y
+# CONFIG_MPC8560_ADS is not set
+# CONFIG_SBC8560 is not set
+CONFIG_MPC8555=y
+CONFIG_85xx_PCI2=y
+
+#
+# Platform options
+#
+CONFIG_CPM2=y
+# CONFIG_PC_KEYBOARD is not set
+# CONFIG_SMP is not set
+# CONFIG_PREEMPT is not set
+# CONFIG_HIGHMEM is not set
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+# CONFIG_CMDLINE_BOOL is not set
+
+#
+# Bus options
+#
+CONFIG_PCI=y
+CONFIG_PCI_DOMAINS=y
+# CONFIG_PCI_LEGACY_PROC is not set
+CONFIG_PCI_NAMES=y
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# PC-card bridges
+#
+
+#
+# Advanced setup
+#
+# CONFIG_ADVANCED_OPTIONS is not set
+
+#
+# Default settings for advanced configuration options are used
+#
+CONFIG_HIGHMEM_START=0xfe000000
+CONFIG_LOWMEM_SIZE=0x30000000
+CONFIG_KERNEL_START=0xc0000000
+CONFIG_TASK_SIZE=0x80000000
+CONFIG_BOOT_LOAD=0x00800000
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_SX8 is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=32768
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_LBD is not set
+# CONFIG_CDROM_PKTCDVD is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_SCSI is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# Macintosh device drivers
+#
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+# CONFIG_NETLINK_DEV is not set
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_IP_MROUTE is not set
+# CONFIG_ARPD is not set
+CONFIG_SYN_COOKIES=y
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_IP_TCPDIAG=y
+# CONFIG_IP_TCPDIAG_IPV6 is not set
+# CONFIG_IPV6 is not set
+# CONFIG_NETFILTER is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_NET_VENDOR_3COM is not set
+
+#
+# Tulip family network device support
+#
+# CONFIG_NET_TULIP is not set
+# CONFIG_HP100 is not set
+# CONFIG_NET_PCI is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_E1000 is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_TIGON3 is not set
+CONFIG_GIANFAR=y
+CONFIG_GFAR_NAPI=y
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_IXGB is not set
+# CONFIG_S2IO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input I/O drivers
+#
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+# CONFIG_SERIO is not set
+# CONFIG_SERIO_I8042 is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Character devices
+#
+# CONFIG_VT is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=4
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_CPM is not set
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_NVRAM is not set
+CONFIG_GEN_RTC=y
+# CONFIG_GEN_RTC_X is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# I2C support
+#
+CONFIG_I2C=y
+CONFIG_I2C_CHARDEV=y
+
+#
+# I2C Algorithms
+#
+# CONFIG_I2C_ALGOBIT is not set
+# CONFIG_I2C_ALGOPCF is not set
+# CONFIG_I2C_ALGOPCA is not set
+
+#
+# I2C Hardware Bus support
+#
+# CONFIG_I2C_ALI1535 is not set
+# CONFIG_I2C_ALI1563 is not set
+# CONFIG_I2C_ALI15X3 is not set
+# CONFIG_I2C_AMD756 is not set
+# CONFIG_I2C_AMD8111 is not set
+# CONFIG_I2C_I801 is not set
+# CONFIG_I2C_I810 is not set
+# CONFIG_I2C_ISA is not set
+CONFIG_I2C_MPC=y
+# CONFIG_I2C_NFORCE2 is not set
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_PIIX4 is not set
+# CONFIG_I2C_PROSAVAGE is not set
+# CONFIG_I2C_SAVAGE4 is not set
+# CONFIG_SCx200_ACB is not set
+# CONFIG_I2C_SIS5595 is not set
+# CONFIG_I2C_SIS630 is not set
+# CONFIG_I2C_SIS96X is not set
+# CONFIG_I2C_VIA is not set
+# CONFIG_I2C_VIAPRO is not set
+# CONFIG_I2C_VOODOO3 is not set
+# CONFIG_I2C_PCA_ISA is not set
+
+#
+# Hardware Sensors Chip support
+#
+# CONFIG_I2C_SENSOR is not set
+# CONFIG_SENSORS_ADM1021 is not set
+# CONFIG_SENSORS_ADM1025 is not set
+# CONFIG_SENSORS_ADM1026 is not set
+# CONFIG_SENSORS_ADM1031 is not set
+# CONFIG_SENSORS_ASB100 is not set
+# CONFIG_SENSORS_DS1621 is not set
+# CONFIG_SENSORS_FSCHER is not set
+# CONFIG_SENSORS_GL518SM is not set
+# CONFIG_SENSORS_IT87 is not set
+# CONFIG_SENSORS_LM63 is not set
+# CONFIG_SENSORS_LM75 is not set
+# CONFIG_SENSORS_LM77 is not set
+# CONFIG_SENSORS_LM78 is not set
+# CONFIG_SENSORS_LM80 is not set
+# CONFIG_SENSORS_LM83 is not set
+# CONFIG_SENSORS_LM85 is not set
+# CONFIG_SENSORS_LM87 is not set
+# CONFIG_SENSORS_LM90 is not set
+# CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_PC87360 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_VIA686A is not set
+# CONFIG_SENSORS_W83781D is not set
+# CONFIG_SENSORS_W83L785TS is not set
+# CONFIG_SENSORS_W83627HF is not set
+
+#
+# Other I2C Chip support
+#
+# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_SENSORS_RTC8564 is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
+# Misc devices
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+# CONFIG_FB is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+# CONFIG_USB is not set
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# InfiniBand support
+#
+# CONFIG_INFINIBAND is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_FS_XATTR=y
+# CONFIG_EXT3_FS_POSIX_ACL is not set
+# CONFIG_EXT3_FS_SECURITY is not set
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+CONFIG_FS_MBCACHE=y
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_SYSFS=y
+# CONFIG_DEVFS_FS is not set
+# CONFIG_DEVPTS_FS_XATTR is not set
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_XATTR is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+# CONFIG_NFS_V3 is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+# CONFIG_NFSD is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+# CONFIG_EXPORTFS is not set
+CONFIG_SUNRPC=y
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
+# CONFIG_MSDOS_PARTITION is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_EFI_PARTITION is not set
+
+#
+# Native Language Support
+#
+# CONFIG_NLS is not set
+# CONFIG_SCC_ENET is not set
+# CONFIG_FEC_ENET is not set
+
+#
+# CPM2 Options
+#
+
+#
+# Library routines
+#
+# CONFIG_CRC_CCITT is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_DEBUG_KERNEL is not set
+# CONFIG_KGDB_CONSOLE is not set
+# CONFIG_SERIAL_TEXT_DEBUG is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Hardware crypto devices
+#
diff --git a/arch/ppc/configs/mpc8560_ads_defconfig b/arch/ppc/configs/mpc8560_ads_defconfig
new file mode 100644
index 0000000..38a343c
--- /dev/null
+++ b/arch/ppc/configs/mpc8560_ads_defconfig
@@ -0,0 +1,719 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.11-rc1
+# Thu Jan 20 01:24:56 2005
+#
+CONFIG_MMU=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_HAVE_DEC_LOCK=y
+CONFIG_PPC=y
+CONFIG_PPC32=y
+CONFIG_GENERIC_NVRAM=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=y
+CONFIG_BROKEN_ON_SMP=y
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_HOTPLUG is not set
+CONFIG_KOBJECT_UEVENT=y
+# CONFIG_IKCONFIG is not set
+CONFIG_EMBEDDED=y
+# CONFIG_KALLSYMS is not set
+CONFIG_FUTEX=y
+# CONFIG_EPOLL is not set
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SHMEM=y
+CONFIG_CC_ALIGN_FUNCTIONS=0
+CONFIG_CC_ALIGN_LABELS=0
+CONFIG_CC_ALIGN_LOOPS=0
+CONFIG_CC_ALIGN_JUMPS=0
+# CONFIG_TINY_SHMEM is not set
+
+#
+# Loadable module support
+#
+# CONFIG_MODULES is not set
+
+#
+# Processor
+#
+# CONFIG_6xx is not set
+# CONFIG_40x is not set
+# CONFIG_44x is not set
+# CONFIG_POWER3 is not set
+# CONFIG_POWER4 is not set
+# CONFIG_8xx is not set
+CONFIG_E500=y
+CONFIG_BOOKE=y
+CONFIG_FSL_BOOKE=y
+CONFIG_SPE=y
+CONFIG_MATH_EMULATION=y
+# CONFIG_CPU_FREQ is not set
+CONFIG_85xx=y
+CONFIG_PPC_INDIRECT_PCI_BE=y
+
+#
+# Freescale 85xx options
+#
+# CONFIG_MPC8540_ADS is not set
+# CONFIG_MPC8555_CDS is not set
+CONFIG_MPC8560_ADS=y
+# CONFIG_SBC8560 is not set
+CONFIG_MPC8560=y
+
+#
+# Platform options
+#
+CONFIG_CPM2=y
+# CONFIG_PC_KEYBOARD is not set
+# CONFIG_SMP is not set
+# CONFIG_PREEMPT is not set
+# CONFIG_HIGHMEM is not set
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+# CONFIG_CMDLINE_BOOL is not set
+
+#
+# Bus options
+#
+CONFIG_PCI=y
+CONFIG_PCI_DOMAINS=y
+# CONFIG_PCI_LEGACY_PROC is not set
+CONFIG_PCI_NAMES=y
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# PC-card bridges
+#
+
+#
+# Advanced setup
+#
+# CONFIG_ADVANCED_OPTIONS is not set
+
+#
+# Default settings for advanced configuration options are used
+#
+CONFIG_HIGHMEM_START=0xfe000000
+CONFIG_LOWMEM_SIZE=0x30000000
+CONFIG_KERNEL_START=0xc0000000
+CONFIG_TASK_SIZE=0x80000000
+CONFIG_BOOT_LOAD=0x00800000
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_SX8 is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=32768
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_LBD is not set
+# CONFIG_CDROM_PKTCDVD is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_SCSI is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# Macintosh device drivers
+#
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+# CONFIG_NETLINK_DEV is not set
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_IP_MROUTE is not set
+# CONFIG_ARPD is not set
+CONFIG_SYN_COOKIES=y
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_IP_TCPDIAG=y
+# CONFIG_IP_TCPDIAG_IPV6 is not set
+# CONFIG_IPV6 is not set
+# CONFIG_NETFILTER is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_NET_VENDOR_3COM is not set
+
+#
+# Tulip family network device support
+#
+# CONFIG_NET_TULIP is not set
+# CONFIG_HP100 is not set
+# CONFIG_NET_PCI is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_E1000 is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_TIGON3 is not set
+CONFIG_GIANFAR=y
+CONFIG_GFAR_NAPI=y
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_IXGB is not set
+# CONFIG_S2IO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input I/O drivers
+#
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+# CONFIG_SERIO is not set
+# CONFIG_SERIO_I8042 is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Character devices
+#
+# CONFIG_VT is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_SERIAL_CPM=y
+CONFIG_SERIAL_CPM_CONSOLE=y
+CONFIG_SERIAL_CPM_SCC1=y
+# CONFIG_SERIAL_CPM_SCC2 is not set
+# CONFIG_SERIAL_CPM_SCC3 is not set
+CONFIG_SERIAL_CPM_SCC4=y
+# CONFIG_SERIAL_CPM_SMC1 is not set
+# CONFIG_SERIAL_CPM_SMC2 is not set
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_NVRAM is not set
+CONFIG_GEN_RTC=y
+# CONFIG_GEN_RTC_X is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# I2C support
+#
+CONFIG_I2C=y
+CONFIG_I2C_CHARDEV=y
+
+#
+# I2C Algorithms
+#
+# CONFIG_I2C_ALGOBIT is not set
+# CONFIG_I2C_ALGOPCF is not set
+# CONFIG_I2C_ALGOPCA is not set
+
+#
+# I2C Hardware Bus support
+#
+# CONFIG_I2C_ALI1535 is not set
+# CONFIG_I2C_ALI1563 is not set
+# CONFIG_I2C_ALI15X3 is not set
+# CONFIG_I2C_AMD756 is not set
+# CONFIG_I2C_AMD8111 is not set
+# CONFIG_I2C_I801 is not set
+# CONFIG_I2C_I810 is not set
+# CONFIG_I2C_ISA is not set
+CONFIG_I2C_MPC=y
+# CONFIG_I2C_NFORCE2 is not set
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_PIIX4 is not set
+# CONFIG_I2C_PROSAVAGE is not set
+# CONFIG_I2C_SAVAGE4 is not set
+# CONFIG_SCx200_ACB is not set
+# CONFIG_I2C_SIS5595 is not set
+# CONFIG_I2C_SIS630 is not set
+# CONFIG_I2C_SIS96X is not set
+# CONFIG_I2C_VIA is not set
+# CONFIG_I2C_VIAPRO is not set
+# CONFIG_I2C_VOODOO3 is not set
+# CONFIG_I2C_PCA_ISA is not set
+
+#
+# Hardware Sensors Chip support
+#
+# CONFIG_I2C_SENSOR is not set
+# CONFIG_SENSORS_ADM1021 is not set
+# CONFIG_SENSORS_ADM1025 is not set
+# CONFIG_SENSORS_ADM1026 is not set
+# CONFIG_SENSORS_ADM1031 is not set
+# CONFIG_SENSORS_ASB100 is not set
+# CONFIG_SENSORS_DS1621 is not set
+# CONFIG_SENSORS_FSCHER is not set
+# CONFIG_SENSORS_GL518SM is not set
+# CONFIG_SENSORS_IT87 is not set
+# CONFIG_SENSORS_LM63 is not set
+# CONFIG_SENSORS_LM75 is not set
+# CONFIG_SENSORS_LM77 is not set
+# CONFIG_SENSORS_LM78 is not set
+# CONFIG_SENSORS_LM80 is not set
+# CONFIG_SENSORS_LM83 is not set
+# CONFIG_SENSORS_LM85 is not set
+# CONFIG_SENSORS_LM87 is not set
+# CONFIG_SENSORS_LM90 is not set
+# CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_PC87360 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_VIA686A is not set
+# CONFIG_SENSORS_W83781D is not set
+# CONFIG_SENSORS_W83L785TS is not set
+# CONFIG_SENSORS_W83627HF is not set
+
+#
+# Other I2C Chip support
+#
+# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_SENSORS_RTC8564 is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
+# Misc devices
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+# CONFIG_FB is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+# CONFIG_USB is not set
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# InfiniBand support
+#
+# CONFIG_INFINIBAND is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_FS_XATTR=y
+# CONFIG_EXT3_FS_POSIX_ACL is not set
+# CONFIG_EXT3_FS_SECURITY is not set
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+CONFIG_FS_MBCACHE=y
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_SYSFS=y
+# CONFIG_DEVFS_FS is not set
+# CONFIG_DEVPTS_FS_XATTR is not set
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_XATTR is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+# CONFIG_NFS_V3 is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+# CONFIG_NFSD is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+# CONFIG_EXPORTFS is not set
+CONFIG_SUNRPC=y
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
+# CONFIG_MSDOS_PARTITION is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_EFI_PARTITION is not set
+
+#
+# Native Language Support
+#
+# CONFIG_NLS is not set
+# CONFIG_SCC_ENET is not set
+# CONFIG_FEC_ENET is not set
+
+#
+# CPM2 Options
+#
+
+#
+# Library routines
+#
+# CONFIG_CRC_CCITT is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_DEBUG_KERNEL is not set
+# CONFIG_KGDB_CONSOLE is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Hardware crypto devices
+#
diff --git a/arch/ppc/configs/mvme5100_defconfig b/arch/ppc/configs/mvme5100_defconfig
new file mode 100644
index 0000000..46776b9
--- /dev/null
+++ b/arch/ppc/configs/mvme5100_defconfig
@@ -0,0 +1,746 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.9-rc2
+# Wed Sep 22 09:53:26 2004
+#
+CONFIG_MMU=y
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_HAVE_DEC_LOCK=y
+CONFIG_PPC=y
+CONFIG_PPC32=y
+CONFIG_GENERIC_NVRAM=y
+CONFIG_GENERIC_IOMAP=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=y
+CONFIG_BROKEN_ON_SMP=y
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_HOTPLUG is not set
+# CONFIG_IKCONFIG is not set
+CONFIG_EMBEDDED=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SHMEM=y
+# CONFIG_TINY_SHMEM is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_OBSOLETE_MODPARM=y
+# CONFIG_MODVERSIONS is not set
+CONFIG_KMOD=y
+
+#
+# Processor
+#
+CONFIG_6xx=y
+# CONFIG_40x is not set
+# CONFIG_44x is not set
+# CONFIG_POWER3 is not set
+# CONFIG_POWER4 is not set
+# CONFIG_8xx is not set
+# CONFIG_E500 is not set
+CONFIG_ALTIVEC=y
+# CONFIG_TAU is not set
+# CONFIG_CPU_FREQ is not set
+CONFIG_PPC_STD_MMU=y
+
+#
+# Platform options
+#
+# CONFIG_PPC_MULTIPLATFORM is not set
+# CONFIG_APUS is not set
+# CONFIG_WILLOW is not set
+# CONFIG_PCORE is not set
+# CONFIG_POWERPMC250 is not set
+# CONFIG_EV64260 is not set
+# CONFIG_SPRUCE is not set
+# CONFIG_LOPEC is not set
+# CONFIG_MCPN765 is not set
+CONFIG_MVME5100=y
+# CONFIG_PPLUS is not set
+# CONFIG_PRPMC750 is not set
+# CONFIG_PRPMC800 is not set
+# CONFIG_SANDPOINT is not set
+# CONFIG_ADIR is not set
+# CONFIG_K2 is not set
+# CONFIG_PAL4 is not set
+# CONFIG_GEMINI is not set
+# CONFIG_EST8260 is not set
+# CONFIG_SBC82xx is not set
+# CONFIG_SBS8260 is not set
+# CONFIG_RPX8260 is not set
+# CONFIG_TQM8260 is not set
+# CONFIG_ADS8272 is not set
+# CONFIG_LITE5200 is not set
+# CONFIG_MVME5100_IPMC761_PRESENT is not set
+# CONFIG_SMP is not set
+# CONFIG_PREEMPT is not set
+# CONFIG_HIGHMEM is not set
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+CONFIG_CMDLINE_BOOL=y
+CONFIG_CMDLINE="ip=on"
+
+#
+# Bus options
+#
+CONFIG_GENERIC_ISA_DMA=y
+CONFIG_PCI=y
+CONFIG_PCI_DOMAINS=y
+# CONFIG_PCI_LEGACY_PROC is not set
+# CONFIG_PCI_NAMES is not set
+
+#
+# Advanced setup
+#
+# CONFIG_ADVANCED_OPTIONS is not set
+
+#
+# Default settings for advanced configuration options are used
+#
+CONFIG_HIGHMEM_START=0xfe000000
+CONFIG_LOWMEM_SIZE=0x30000000
+CONFIG_KERNEL_START=0xc0000000
+CONFIG_TASK_SIZE=0x80000000
+CONFIG_BOOT_LOAD=0x00800000
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_SX8 is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=4096
+CONFIG_BLK_DEV_INITRD=y
+# CONFIG_LBD is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+CONFIG_IDE=y
+CONFIG_BLK_DEV_IDE=y
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+# CONFIG_BLK_DEV_IDE_SATA is not set
+CONFIG_BLK_DEV_IDEDISK=y
+# CONFIG_IDEDISK_MULTI_MODE is not set
+# CONFIG_BLK_DEV_IDECD is not set
+# CONFIG_BLK_DEV_IDETAPE is not set
+# CONFIG_BLK_DEV_IDEFLOPPY is not set
+# CONFIG_BLK_DEV_IDESCSI is not set
+# CONFIG_IDE_TASK_IOCTL is not set
+# CONFIG_IDE_TASKFILE_IO is not set
+
+#
+# IDE chipset support/bugfixes
+#
+CONFIG_IDE_GENERIC=y
+# CONFIG_BLK_DEV_IDEPCI is not set
+# CONFIG_IDE_ARM is not set
+# CONFIG_BLK_DEV_IDEDMA is not set
+# CONFIG_IDEDMA_AUTO is not set
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# SCSI device support
+#
+CONFIG_SCSI=y
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+CONFIG_BLK_DEV_SR=y
+# CONFIG_BLK_DEV_SR_VENDOR is not set
+# CONFIG_CHR_DEV_SG is not set
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+# CONFIG_SCSI_MULTI_LUN is not set
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+
+#
+# SCSI Transport Attributes
+#
+CONFIG_SCSI_SPI_ATTRS=y
+# CONFIG_SCSI_FC_ATTRS is not set
+
+#
+# SCSI low-level drivers
+#
+# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
+# CONFIG_SCSI_3W_9XXX is not set
+# CONFIG_SCSI_ACARD is not set
+# CONFIG_SCSI_AACRAID is not set
+# CONFIG_SCSI_AIC7XXX is not set
+# CONFIG_SCSI_AIC7XXX_OLD is not set
+# CONFIG_SCSI_AIC79XX is not set
+# CONFIG_SCSI_DPT_I2O is not set
+# CONFIG_MEGARAID_NEWGEN is not set
+# CONFIG_MEGARAID_LEGACY is not set
+# CONFIG_SCSI_SATA is not set
+# CONFIG_SCSI_BUSLOGIC is not set
+# CONFIG_SCSI_DMX3191D is not set
+# CONFIG_SCSI_EATA is not set
+# CONFIG_SCSI_EATA_PIO is not set
+# CONFIG_SCSI_FUTURE_DOMAIN is not set
+# CONFIG_SCSI_GDTH is not set
+# CONFIG_SCSI_IPS is not set
+# CONFIG_SCSI_INIA100 is not set
+CONFIG_SCSI_SYM53C8XX_2=y
+CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=0
+CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=8
+CONFIG_SCSI_SYM53C8XX_MAX_TAGS=32
+# CONFIG_SCSI_SYM53C8XX_IOMAPPED is not set
+# CONFIG_SCSI_IPR is not set
+# CONFIG_SCSI_QLOGIC_ISP is not set
+# CONFIG_SCSI_QLOGIC_FC is not set
+# CONFIG_SCSI_QLOGIC_1280 is not set
+CONFIG_SCSI_QLA2XXX=y
+# CONFIG_SCSI_QLA21XX is not set
+# CONFIG_SCSI_QLA22XX is not set
+# CONFIG_SCSI_QLA2300 is not set
+# CONFIG_SCSI_QLA2322 is not set
+# CONFIG_SCSI_QLA6312 is not set
+# CONFIG_SCSI_QLA6322 is not set
+# CONFIG_SCSI_DC395x is not set
+# CONFIG_SCSI_DC390T is not set
+# CONFIG_SCSI_NSP32 is not set
+# CONFIG_SCSI_DEBUG is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+# CONFIG_FUSION is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# Macintosh device drivers
+#
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+# CONFIG_NETLINK_DEV is not set
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_PNP=y
+# CONFIG_IP_PNP_DHCP is not set
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_IP_MROUTE is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+CONFIG_INET_TUNNEL=m
+
+#
+# IP: Virtual Server Configuration
+#
+# CONFIG_IP_VS is not set
+# CONFIG_IPV6 is not set
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+
+#
+# IP: Netfilter Configuration
+#
+CONFIG_IP_NF_CONNTRACK=m
+# CONFIG_IP_NF_CT_ACCT is not set
+# CONFIG_IP_NF_CT_PROTO_SCTP is not set
+CONFIG_IP_NF_FTP=m
+CONFIG_IP_NF_IRC=m
+CONFIG_IP_NF_TFTP=m
+CONFIG_IP_NF_AMANDA=m
+# CONFIG_IP_NF_QUEUE is not set
+CONFIG_IP_NF_IPTABLES=m
+# CONFIG_IP_NF_MATCH_LIMIT is not set
+# CONFIG_IP_NF_MATCH_IPRANGE is not set
+# CONFIG_IP_NF_MATCH_MAC is not set
+# CONFIG_IP_NF_MATCH_PKTTYPE is not set
+# CONFIG_IP_NF_MATCH_MARK is not set
+# CONFIG_IP_NF_MATCH_MULTIPORT is not set
+# CONFIG_IP_NF_MATCH_TOS is not set
+# CONFIG_IP_NF_MATCH_RECENT is not set
+# CONFIG_IP_NF_MATCH_ECN is not set
+# CONFIG_IP_NF_MATCH_DSCP is not set
+# CONFIG_IP_NF_MATCH_AH_ESP is not set
+# CONFIG_IP_NF_MATCH_LENGTH is not set
+# CONFIG_IP_NF_MATCH_TTL is not set
+# CONFIG_IP_NF_MATCH_TCPMSS is not set
+CONFIG_IP_NF_MATCH_HELPER=m
+# CONFIG_IP_NF_MATCH_STATE is not set
+# CONFIG_IP_NF_MATCH_CONNTRACK is not set
+# CONFIG_IP_NF_MATCH_OWNER is not set
+# CONFIG_IP_NF_MATCH_ADDRTYPE is not set
+# CONFIG_IP_NF_MATCH_REALM is not set
+# CONFIG_IP_NF_MATCH_SCTP is not set
+# CONFIG_IP_NF_FILTER is not set
+# CONFIG_IP_NF_TARGET_LOG is not set
+# CONFIG_IP_NF_TARGET_ULOG is not set
+# CONFIG_IP_NF_TARGET_TCPMSS is not set
+# CONFIG_IP_NF_NAT is not set
+# CONFIG_IP_NF_MANGLE is not set
+# CONFIG_IP_NF_RAW is not set
+# CONFIG_IP_NF_ARPTABLES is not set
+# CONFIG_IP_NF_COMPAT_IPCHAINS is not set
+# CONFIG_IP_NF_COMPAT_IPFWADM is not set
+CONFIG_XFRM=y
+CONFIG_XFRM_USER=y
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_HW_FLOWCONTROL is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_NET_VENDOR_3COM is not set
+
+#
+# Tulip family network device support
+#
+CONFIG_NET_TULIP=y
+# CONFIG_DE2104X is not set
+CONFIG_TULIP=y
+# CONFIG_TULIP_MWI is not set
+# CONFIG_TULIP_MMIO is not set
+# CONFIG_TULIP_NAPI is not set
+# CONFIG_DE4X5 is not set
+# CONFIG_WINBOND_840 is not set
+# CONFIG_DM9102 is not set
+# CONFIG_HP100 is not set
+CONFIG_NET_PCI=y
+# CONFIG_PCNET32 is not set
+# CONFIG_AMD8111_ETH is not set
+# CONFIG_ADAPTEC_STARFIRE is not set
+# CONFIG_B44 is not set
+# CONFIG_FORCEDETH is not set
+# CONFIG_DGRS is not set
+# CONFIG_EEPRO100 is not set
+CONFIG_E100=y
+# CONFIG_E100_NAPI is not set
+# CONFIG_FEALNX is not set
+# CONFIG_NATSEMI is not set
+# CONFIG_NE2K_PCI is not set
+# CONFIG_8139CP is not set
+# CONFIG_8139TOO is not set
+# CONFIG_SIS900 is not set
+# CONFIG_EPIC100 is not set
+# CONFIG_SUNDANCE is not set
+# CONFIG_TLAN is not set
+# CONFIG_VIA_RHINE is not set
+# CONFIG_VIA_VELOCITY is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_E1000 is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_TIGON3 is not set
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_IXGB is not set
+# CONFIG_S2IO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_NET_FC is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+# CONFIG_INPUT is not set
+
+#
+# Userland interfaces
+#
+
+#
+# Input I/O drivers
+#
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+# CONFIG_SERIO is not set
+# CONFIG_SERIO_I8042 is not set
+
+#
+# Input Device Drivers
+#
+
+#
+# Character devices
+#
+# CONFIG_VT is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=4
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_NVRAM is not set
+CONFIG_GEN_RTC=y
+# CONFIG_GEN_RTC_X is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
+# Misc devices
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+# CONFIG_FB is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+# CONFIG_USB is not set
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_JBD is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_SYSFS=y
+# CONFIG_DEVFS_FS is not set
+# CONFIG_DEVPTS_FS_XATTR is not set
+CONFIG_TMPFS=y
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+# CONFIG_NFSD is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+# CONFIG_EXPORTFS is not set
+CONFIG_SUNRPC=y
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+# CONFIG_NLS is not set
+
+#
+# Library routines
+#
+# CONFIG_CRC_CCITT is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_DEBUG_KERNEL is not set
+
+#
+# Security options
+#
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
diff --git a/arch/ppc/configs/oak_defconfig b/arch/ppc/configs/oak_defconfig
new file mode 100644
index 0000000..366cc48
--- /dev/null
+++ b/arch/ppc/configs/oak_defconfig
@@ -0,0 +1,485 @@
+#
+# Automatically generated make config: don't edit
+#
+CONFIG_MMU=y
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_HAVE_DEC_LOCK=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+
+#
+# General setup
+#
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_EMBEDDED=y
+CONFIG_FUTEX=y
+# CONFIG_EPOLL is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_OBSOLETE_MODPARM=y
+# CONFIG_MODVERSIONS is not set
+CONFIG_KMOD=y
+
+#
+# Platform support
+#
+CONFIG_PPC=y
+CONFIG_PPC32=y
+# CONFIG_6xx is not set
+CONFIG_40x=y
+# CONFIG_POWER3 is not set
+# CONFIG_8xx is not set
+CONFIG_4xx=y
+
+#
+# IBM 4xx options
+#
+# CONFIG_ASH is not set
+# CONFIG_BEECH is not set
+# CONFIG_CEDAR is not set
+# CONFIG_CPCI405 is not set
+# CONFIG_EP405 is not set
+CONFIG_OAK=y
+# CONFIG_REDWOOD_4 is not set
+# CONFIG_REDWOOD_5 is not set
+# CONFIG_REDWOOD_6 is not set
+# CONFIG_SYCAMORE is not set
+# CONFIG_TIVO is not set
+# CONFIG_WALNUT is not set
+CONFIG_IBM405_ERR51=y
+CONFIG_403GCX=y
+# CONFIG_405_DMA is not set
+# CONFIG_PM is not set
+CONFIG_UART0_TTYS0=y
+# CONFIG_UART0_TTYS1 is not set
+CONFIG_NOT_COHERENT_CACHE=y
+# CONFIG_SMP is not set
+# CONFIG_PREEMPT is not set
+# CONFIG_MATH_EMULATION is not set
+# CONFIG_CPU_FREQ is not set
+
+#
+# General setup
+#
+# CONFIG_HIGHMEM is not set
+# CONFIG_PCI is not set
+# CONFIG_PCI_DOMAINS is not set
+# CONFIG_PC_KEYBOARD is not set
+CONFIG_KCORE_ELF=y
+CONFIG_BINFMT_ELF=y
+CONFIG_KERNEL_ELF=y
+# CONFIG_BINFMT_MISC is not set
+# CONFIG_HOTPLUG is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+# CONFIG_CMDLINE_BOOL is not set
+
+#
+# Advanced setup
+#
+# CONFIG_ADVANCED_OPTIONS is not set
+
+#
+# Default settings for advanced configuration options are used
+#
+CONFIG_HIGHMEM_START=0xfe000000
+CONFIG_LOWMEM_SIZE=0x30000000
+CONFIG_KERNEL_START=0xc0000000
+CONFIG_TASK_SIZE=0x80000000
+CONFIG_BOOT_LOAD=0x00400000
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Plug and Play support
+#
+# CONFIG_PNP is not set
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_NBD is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=4096
+CONFIG_BLK_DEV_INITRD=y
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# ATA/IDE/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI support
+#
+# CONFIG_SCSI is not set
+
+#
+# Fusion MPT device support
+#
+
+#
+# I2O device support
+#
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+# CONFIG_PACKET is not set
+# CONFIG_NETLINK_DEV is not set
+# CONFIG_NETFILTER is not set
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_PNP=y
+# CONFIG_IP_PNP_DHCP is not set
+CONFIG_IP_PNP_BOOTP=y
+CONFIG_IP_PNP_RARP=y
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_IP_MROUTE is not set
+# CONFIG_ARPD is not set
+# CONFIG_INET_ECN is not set
+CONFIG_SYN_COOKIES=y
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_IPV6 is not set
+# CONFIG_XFRM_USER is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+CONFIG_IPV6_SCTP__=y
+# CONFIG_IP_SCTP is not set
+# CONFIG_ATM is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_LLC is not set
+# CONFIG_DECNET is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_HW_FLOWCONTROL is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_ETHERTAP is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+# CONFIG_MII is not set
+CONFIG_OAKNET=y
+
+#
+# Ethernet (1000 Mbit)
+#
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Token Ring devices (depends on LLC=y)
+#
+# CONFIG_SHAPER is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+
+#
+# Amateur Radio support
+#
+# CONFIG_HAMRADIO is not set
+
+#
+# IrDA (infrared) support
+#
+# CONFIG_IRDA is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN_BOOL is not set
+
+#
+# Graphics support
+#
+# CONFIG_FB is not set
+
+#
+# Old CD-ROM drivers (not SCSI, not IDE)
+#
+# CONFIG_CD_NO_IDESCSI is not set
+
+#
+# Input device support
+#
+# CONFIG_INPUT is not set
+
+#
+# Userland interfaces
+#
+
+#
+# Input I/O drivers
+#
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+# CONFIG_SERIO is not set
+
+#
+# Input Device Drivers
+#
+
+#
+# Macintosh device drivers
+#
+
+#
+# Character devices
+#
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_UNIX98_PTYS is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# I2C Hardware Sensors Mainboard support
+#
+
+#
+# I2C Hardware Sensors Chip support
+#
+# CONFIG_I2C_SENSOR is not set
+
+#
+# Mice
+#
+# CONFIG_BUSMOUSE is not set
+# CONFIG_QIC02_TAPE is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_NVRAM is not set
+CONFIG_GEN_RTC=y
+# CONFIG_GEN_RTC_X is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_FTAPE is not set
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_HANGCHECK_TIMER is not set
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_JBD is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_FAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+# CONFIG_DEVFS_FS is not set
+CONFIG_TMPFS=y
+CONFIG_RAMFS=y
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+# CONFIG_NFS_V3 is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFSD is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+# CONFIG_EXPORTFS is not set
+CONFIG_SUNRPC=y
+# CONFIG_SUNRPC_GSS is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_INTERMEZZO_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# IBM 40x options
+#
+
+#
+# USB support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# Bluetooth support
+#
+# CONFIG_BT is not set
+
+#
+# Library routines
+#
+# CONFIG_CRC32 is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_DEBUG_KERNEL is not set
+# CONFIG_KALLSYMS is not set
+# CONFIG_SERIAL_TEXT_DEBUG is not set
+
+#
+# Security options
+#
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
diff --git a/arch/ppc/configs/ocotea_defconfig b/arch/ppc/configs/ocotea_defconfig
new file mode 100644
index 0000000..9dcf575
--- /dev/null
+++ b/arch/ppc/configs/ocotea_defconfig
@@ -0,0 +1,599 @@
+#
+# Automatically generated make config: don't edit
+#
+CONFIG_MMU=y
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_HAVE_DEC_LOCK=y
+CONFIG_PPC=y
+CONFIG_PPC32=y
+CONFIG_GENERIC_NVRAM=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=y
+# CONFIG_STANDALONE is not set
+CONFIG_BROKEN_ON_SMP=y
+
+#
+# General setup
+#
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_HOTPLUG is not set
+# CONFIG_IKCONFIG is not set
+CONFIG_EMBEDDED=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_OBSOLETE_MODPARM=y
+# CONFIG_MODVERSIONS is not set
+CONFIG_KMOD=y
+
+#
+# Processor
+#
+# CONFIG_6xx is not set
+# CONFIG_40x is not set
+CONFIG_44x=y
+# CONFIG_POWER3 is not set
+# CONFIG_POWER4 is not set
+# CONFIG_8xx is not set
+# CONFIG_E500 is not set
+CONFIG_BOOKE=y
+CONFIG_PTE_64BIT=y
+# CONFIG_MATH_EMULATION is not set
+# CONFIG_CPU_FREQ is not set
+CONFIG_4xx=y
+
+#
+# IBM 4xx options
+#
+# CONFIG_EBONY is not set
+CONFIG_OCOTEA=y
+CONFIG_440GX=y
+CONFIG_440A=y
+CONFIG_IBM_OCP=y
+CONFIG_IBM_EMAC4=y
+# CONFIG_PM is not set
+CONFIG_NOT_COHERENT_CACHE=y
+
+#
+# Platform options
+#
+# CONFIG_PC_KEYBOARD is not set
+# CONFIG_SMP is not set
+# CONFIG_PREEMPT is not set
+# CONFIG_HIGHMEM is not set
+CONFIG_KERNEL_ELF=y
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+CONFIG_CMDLINE_BOOL=y
+CONFIG_CMDLINE="ip=on console=ttyS0,115200"
+
+#
+# Bus options
+#
+CONFIG_PCI=y
+CONFIG_PCI_DOMAINS=y
+# CONFIG_PCI_LEGACY_PROC is not set
+# CONFIG_PCI_NAMES is not set
+
+#
+# Advanced setup
+#
+# CONFIG_ADVANCED_OPTIONS is not set
+
+#
+# Default settings for advanced configuration options are used
+#
+CONFIG_HIGHMEM_START=0xfe000000
+CONFIG_LOWMEM_SIZE=0x30000000
+CONFIG_KERNEL_START=0xc0000000
+CONFIG_TASK_SIZE=0x80000000
+CONFIG_CONSISTENT_START=0xff100000
+CONFIG_CONSISTENT_SIZE=0x00200000
+CONFIG_BOOT_LOAD=0x01000000
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_DEBUG_DRIVER is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_SX8 is not set
+# CONFIG_BLK_DEV_RAM is not set
+# CONFIG_LBD is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_SCSI is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# Macintosh device drivers
+#
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+# CONFIG_NETLINK_DEV is not set
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_PNP=y
+# CONFIG_IP_PNP_DHCP is not set
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+
+#
+# IP: Virtual Server Configuration
+#
+# CONFIG_IP_VS is not set
+# CONFIG_IPV6 is not set
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+
+#
+# IP: Netfilter Configuration
+#
+# CONFIG_IP_NF_CONNTRACK is not set
+# CONFIG_IP_NF_QUEUE is not set
+# CONFIG_IP_NF_IPTABLES is not set
+# CONFIG_IP_NF_ARPTABLES is not set
+# CONFIG_IP_NF_COMPAT_IPCHAINS is not set
+# CONFIG_IP_NF_COMPAT_IPFWADM is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_HW_FLOWCONTROL is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+# CONFIG_MII is not set
+# CONFIG_OAKNET is not set
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_NET_VENDOR_3COM is not set
+
+#
+# Tulip family network device support
+#
+# CONFIG_NET_TULIP is not set
+# CONFIG_HP100 is not set
+CONFIG_IBM_EMAC=y
+# CONFIG_IBM_EMAC_ERRMSG is not set
+CONFIG_IBM_EMAC_RXB=128
+CONFIG_IBM_EMAC_TXB=128
+CONFIG_IBM_EMAC_FGAP=8
+CONFIG_IBM_EMAC_SKBRES=0
+# CONFIG_NET_PCI is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_E1000 is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_TIGON3 is not set
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_IXGB is not set
+# CONFIG_S2IO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input I/O drivers
+#
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+CONFIG_SERIO=y
+# CONFIG_SERIO_I8042 is not set
+# CONFIG_SERIO_SERPORT is not set
+# CONFIG_SERIO_CT82C710 is not set
+# CONFIG_SERIO_PCIPS2 is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Character devices
+#
+# CONFIG_VT is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=4
+CONFIG_SERIAL_8250_EXTENDED=y
+# CONFIG_SERIAL_8250_MANY_PORTS is not set
+CONFIG_SERIAL_8250_SHARE_IRQ=y
+# CONFIG_SERIAL_8250_DETECT_IRQ is not set
+# CONFIG_SERIAL_8250_MULTIPORT is not set
+# CONFIG_SERIAL_8250_RSA is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_QIC02_TAPE is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_NVRAM is not set
+# CONFIG_GEN_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_FTAPE is not set
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# Misc devices
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+# CONFIG_FB is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+# CONFIG_USB is not set
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# File systems
+#
+# CONFIG_EXT2_FS is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_JBD is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_FAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_SYSFS=y
+# CONFIG_DEVFS_FS is not set
+# CONFIG_DEVPTS_FS_XATTR is not set
+# CONFIG_TMPFS is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+# CONFIG_NFS_V3 is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+# CONFIG_NFSD is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+# CONFIG_EXPORTFS is not set
+CONFIG_SUNRPC=y
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+# CONFIG_NLS is not set
+
+#
+# Library routines
+#
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_DEBUG_SLAB is not set
+# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_KGDB is not set
+# CONFIG_XMON is not set
+CONFIG_BDI_SWITCH=y
+CONFIG_DEBUG_INFO=y
+# CONFIG_SERIAL_TEXT_DEBUG is not set
+CONFIG_PPC_OCP=y
+
+#
+# Security options
+#
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
diff --git a/arch/ppc/configs/pcore_defconfig b/arch/ppc/configs/pcore_defconfig
new file mode 100644
index 0000000..ed34405
--- /dev/null
+++ b/arch/ppc/configs/pcore_defconfig
@@ -0,0 +1,716 @@
+#
+# Automatically generated make config: don't edit
+#
+CONFIG_MMU=y
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_HAVE_DEC_LOCK=y
+CONFIG_PPC=y
+CONFIG_PPC32=y
+CONFIG_GENERIC_NVRAM=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=y
+CONFIG_STANDALONE=y
+CONFIG_BROKEN_ON_SMP=y
+
+#
+# General setup
+#
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_HOTPLUG is not set
+# CONFIG_IKCONFIG is not set
+CONFIG_EMBEDDED=y
+CONFIG_KALLSYMS=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_OBSOLETE_MODPARM=y
+# CONFIG_MODVERSIONS is not set
+CONFIG_KMOD=y
+
+#
+# Processor
+#
+CONFIG_6xx=y
+# CONFIG_40x is not set
+# CONFIG_44x is not set
+# CONFIG_POWER3 is not set
+# CONFIG_POWER4 is not set
+# CONFIG_8xx is not set
+CONFIG_ALTIVEC=y
+# CONFIG_TAU is not set
+# CONFIG_CPU_FREQ is not set
+CONFIG_PPC_STD_MMU=y
+
+#
+# Platform options
+#
+# CONFIG_PPC_MULTIPLATFORM is not set
+# CONFIG_APUS is not set
+# CONFIG_WILLOW is not set
+CONFIG_PCORE=y
+# CONFIG_POWERPMC250 is not set
+# CONFIG_EV64260 is not set
+# CONFIG_SPRUCE is not set
+# CONFIG_LOPEC is not set
+# CONFIG_MCPN765 is not set
+# CONFIG_MVME5100 is not set
+# CONFIG_PPLUS is not set
+# CONFIG_PRPMC750 is not set
+# CONFIG_PRPMC800 is not set
+# CONFIG_SANDPOINT is not set
+# CONFIG_ADIR is not set
+# CONFIG_K2 is not set
+# CONFIG_PAL4 is not set
+# CONFIG_GEMINI is not set
+# CONFIG_EST8260 is not set
+# CONFIG_SBS8260 is not set
+# CONFIG_RPX6 is not set
+# CONFIG_TQM8260 is not set
+CONFIG_PPC_GEN550=y
+CONFIG_FORCE=y
+# CONFIG_MPC10X_STORE_GATHERING is not set
+# CONFIG_SMP is not set
+# CONFIG_PREEMPT is not set
+# CONFIG_HIGHMEM is not set
+CONFIG_KERNEL_ELF=y
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+CONFIG_CMDLINE_BOOL=y
+CONFIG_CMDLINE="ip=on"
+
+#
+# Bus options
+#
+CONFIG_GENERIC_ISA_DMA=y
+CONFIG_PCI=y
+CONFIG_PCI_DOMAINS=y
+# CONFIG_PCI_LEGACY_PROC is not set
+# CONFIG_PCI_NAMES is not set
+
+#
+# Advanced setup
+#
+# CONFIG_ADVANCED_OPTIONS is not set
+
+#
+# Default settings for advanced configuration options are used
+#
+CONFIG_HIGHMEM_START=0xfe000000
+CONFIG_LOWMEM_SIZE=0x30000000
+CONFIG_KERNEL_START=0xc0000000
+CONFIG_TASK_SIZE=0x80000000
+CONFIG_BOOT_LOAD=0x00800000
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_CARMEL is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=4096
+CONFIG_BLK_DEV_INITRD=y
+# CONFIG_LBD is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+CONFIG_SCSI=y
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+CONFIG_BLK_DEV_SR=y
+# CONFIG_BLK_DEV_SR_VENDOR is not set
+# CONFIG_CHR_DEV_SG is not set
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+# CONFIG_SCSI_MULTI_LUN is not set
+# CONFIG_SCSI_REPORT_LUNS is not set
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+
+#
+# SCSI Transport Attributes
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+
+#
+# SCSI low-level drivers
+#
+# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
+# CONFIG_SCSI_ACARD is not set
+# CONFIG_SCSI_AACRAID is not set
+# CONFIG_SCSI_AIC7XXX is not set
+# CONFIG_SCSI_AIC7XXX_OLD is not set
+# CONFIG_SCSI_AIC79XX is not set
+# CONFIG_SCSI_ADVANSYS is not set
+# CONFIG_SCSI_MEGARAID is not set
+# CONFIG_SCSI_SATA is not set
+# CONFIG_SCSI_BUSLOGIC is not set
+# CONFIG_SCSI_CPQFCTS is not set
+# CONFIG_SCSI_DMX3191D is not set
+# CONFIG_SCSI_EATA is not set
+# CONFIG_SCSI_EATA_PIO is not set
+# CONFIG_SCSI_FUTURE_DOMAIN is not set
+# CONFIG_SCSI_GDTH is not set
+# CONFIG_SCSI_IPS is not set
+# CONFIG_SCSI_INIA100 is not set
+CONFIG_SCSI_SYM53C8XX_2=y
+CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=1
+CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16
+CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64
+# CONFIG_SCSI_SYM53C8XX_IOMAPPED is not set
+# CONFIG_SCSI_QLOGIC_ISP is not set
+# CONFIG_SCSI_QLOGIC_FC is not set
+# CONFIG_SCSI_QLOGIC_1280 is not set
+CONFIG_SCSI_QLA2XXX=y
+# CONFIG_SCSI_QLA21XX is not set
+# CONFIG_SCSI_QLA22XX is not set
+# CONFIG_SCSI_QLA2300 is not set
+# CONFIG_SCSI_QLA2322 is not set
+# CONFIG_SCSI_QLA6312 is not set
+# CONFIG_SCSI_QLA6322 is not set
+# CONFIG_SCSI_DC395x is not set
+# CONFIG_SCSI_DC390T is not set
+# CONFIG_SCSI_NSP32 is not set
+# CONFIG_SCSI_DEBUG is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+# CONFIG_FUSION is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# Macintosh device drivers
+#
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+# CONFIG_NETLINK_DEV is not set
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+# CONFIG_IP_PNP_BOOTP is not set
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_IP_MROUTE is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+
+#
+# IP: Virtual Server Configuration
+#
+# CONFIG_IP_VS is not set
+# CONFIG_IPV6 is not set
+# CONFIG_DECNET is not set
+# CONFIG_BRIDGE is not set
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+
+#
+# IP: Netfilter Configuration
+#
+CONFIG_IP_NF_CONNTRACK=m
+CONFIG_IP_NF_FTP=m
+CONFIG_IP_NF_IRC=m
+# CONFIG_IP_NF_TFTP is not set
+# CONFIG_IP_NF_AMANDA is not set
+# CONFIG_IP_NF_QUEUE is not set
+CONFIG_IP_NF_IPTABLES=m
+CONFIG_IP_NF_MATCH_LIMIT=m
+# CONFIG_IP_NF_MATCH_IPRANGE is not set
+CONFIG_IP_NF_MATCH_MAC=m
+CONFIG_IP_NF_MATCH_PKTTYPE=m
+CONFIG_IP_NF_MATCH_MARK=m
+CONFIG_IP_NF_MATCH_MULTIPORT=m
+CONFIG_IP_NF_MATCH_TOS=m
+# CONFIG_IP_NF_MATCH_RECENT is not set
+CONFIG_IP_NF_MATCH_ECN=m
+CONFIG_IP_NF_MATCH_DSCP=m
+CONFIG_IP_NF_MATCH_AH_ESP=m
+CONFIG_IP_NF_MATCH_LENGTH=m
+CONFIG_IP_NF_MATCH_TTL=m
+CONFIG_IP_NF_MATCH_TCPMSS=m
+CONFIG_IP_NF_MATCH_HELPER=m
+CONFIG_IP_NF_MATCH_STATE=m
+CONFIG_IP_NF_MATCH_CONNTRACK=m
+CONFIG_IP_NF_MATCH_OWNER=m
+CONFIG_IP_NF_FILTER=m
+CONFIG_IP_NF_TARGET_REJECT=m
+CONFIG_IP_NF_NAT=m
+CONFIG_IP_NF_NAT_NEEDED=y
+CONFIG_IP_NF_TARGET_MASQUERADE=m
+CONFIG_IP_NF_TARGET_REDIRECT=m
+# CONFIG_IP_NF_TARGET_NETMAP is not set
+# CONFIG_IP_NF_TARGET_SAME is not set
+# CONFIG_IP_NF_NAT_SNMP_BASIC is not set
+CONFIG_IP_NF_NAT_IRC=m
+CONFIG_IP_NF_NAT_FTP=m
+# CONFIG_IP_NF_MANGLE is not set
+# CONFIG_IP_NF_TARGET_LOG is not set
+CONFIG_IP_NF_TARGET_ULOG=m
+CONFIG_IP_NF_TARGET_TCPMSS=m
+CONFIG_IP_NF_ARPTABLES=m
+CONFIG_IP_NF_ARPFILTER=m
+# CONFIG_IP_NF_ARP_MANGLE is not set
+CONFIG_IP_NF_COMPAT_IPCHAINS=m
+# CONFIG_IP_NF_COMPAT_IPFWADM is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+# CONFIG_ATM is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_HW_FLOWCONTROL is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+CONFIG_NETDEVICES=y
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_OAKNET is not set
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_NET_VENDOR_3COM is not set
+
+#
+# Tulip family network device support
+#
+CONFIG_NET_TULIP=y
+# CONFIG_DE2104X is not set
+CONFIG_TULIP=y
+# CONFIG_TULIP_MWI is not set
+# CONFIG_TULIP_MMIO is not set
+# CONFIG_TULIP_NAPI is not set
+# CONFIG_DE4X5 is not set
+# CONFIG_WINBOND_840 is not set
+# CONFIG_DM9102 is not set
+# CONFIG_HP100 is not set
+CONFIG_NET_PCI=y
+# CONFIG_PCNET32 is not set
+# CONFIG_AMD8111_ETH is not set
+# CONFIG_ADAPTEC_STARFIRE is not set
+# CONFIG_B44 is not set
+# CONFIG_FORCEDETH is not set
+# CONFIG_DGRS is not set
+CONFIG_EEPRO100=y
+# CONFIG_EEPRO100_PIO is not set
+# CONFIG_E100 is not set
+# CONFIG_FEALNX is not set
+# CONFIG_NATSEMI is not set
+# CONFIG_NE2K_PCI is not set
+# CONFIG_8139CP is not set
+# CONFIG_8139TOO is not set
+# CONFIG_SIS900 is not set
+# CONFIG_EPIC100 is not set
+# CONFIG_SUNDANCE is not set
+# CONFIG_TLAN is not set
+# CONFIG_VIA_RHINE is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_E1000 is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
+# CONFIG_SIS190 is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_TIGON3 is not set
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_IXGB is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+# CONFIG_NET_FC is not set
+# CONFIG_RCPCI is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+
+#
+# Amateur Radio support
+#
+# CONFIG_HAMRADIO is not set
+
+#
+# IrDA (infrared) support
+#
+# CONFIG_IRDA is not set
+
+#
+# Bluetooth support
+#
+# CONFIG_BT is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+# CONFIG_INPUT is not set
+
+#
+# Userland interfaces
+#
+
+#
+# Input I/O drivers
+#
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+# CONFIG_SERIO is not set
+# CONFIG_SERIO_I8042 is not set
+
+#
+# Input Device Drivers
+#
+
+#
+# Character devices
+#
+# CONFIG_VT is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=2
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_QIC02_TAPE is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_NVRAM is not set
+CONFIG_GEN_RTC=y
+# CONFIG_GEN_RTC_X is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_FTAPE is not set
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# Misc devices
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+# CONFIG_FB is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+# CONFIG_USB is not set
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_FS_XATTR=y
+# CONFIG_EXT3_FS_POSIX_ACL is not set
+# CONFIG_EXT3_FS_SECURITY is not set
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+CONFIG_FS_MBCACHE=y
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_FAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+# CONFIG_DEVFS_FS is not set
+# CONFIG_DEVPTS_FS_XATTR is not set
+CONFIG_TMPFS=y
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+# CONFIG_NFS_V3 is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+# CONFIG_NFSD is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+# CONFIG_EXPORTFS is not set
+CONFIG_SUNRPC=y
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_INTERMEZZO_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+# CONFIG_NLS is not set
+
+#
+# Library routines
+#
+CONFIG_CRC32=y
+
+#
+# Kernel hacking
+#
+# CONFIG_DEBUG_KERNEL is not set
+# CONFIG_SERIAL_TEXT_DEBUG is not set
+
+#
+# Security options
+#
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
diff --git a/arch/ppc/configs/pmac_defconfig b/arch/ppc/configs/pmac_defconfig
new file mode 100644
index 0000000..8eebb04
--- /dev/null
+++ b/arch/ppc/configs/pmac_defconfig
@@ -0,0 +1,1523 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.11-rc4
+# Sun Feb 13 14:56:58 2005
+#
+CONFIG_MMU=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_HAVE_DEC_LOCK=y
+CONFIG_PPC=y
+CONFIG_PPC32=y
+CONFIG_GENERIC_NVRAM=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=y
+CONFIG_BROKEN_ON_SMP=y
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_POSIX_MQUEUE=y
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+CONFIG_LOG_BUF_SHIFT=16
+CONFIG_HOTPLUG=y
+CONFIG_KOBJECT_UEVENT=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+# CONFIG_EMBEDDED is not set
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SHMEM=y
+CONFIG_CC_ALIGN_FUNCTIONS=0
+CONFIG_CC_ALIGN_LABELS=0
+CONFIG_CC_ALIGN_LOOPS=0
+CONFIG_CC_ALIGN_JUMPS=0
+# CONFIG_TINY_SHMEM is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_OBSOLETE_MODPARM=y
+CONFIG_MODVERSIONS=y
+CONFIG_MODULE_SRCVERSION_ALL=y
+CONFIG_KMOD=y
+
+#
+# Processor
+#
+CONFIG_6xx=y
+# CONFIG_40x is not set
+# CONFIG_44x is not set
+# CONFIG_POWER3 is not set
+# CONFIG_POWER4 is not set
+# CONFIG_8xx is not set
+# CONFIG_E500 is not set
+CONFIG_ALTIVEC=y
+CONFIG_TAU=y
+# CONFIG_TAU_INT is not set
+# CONFIG_TAU_AVERAGE is not set
+CONFIG_CPU_FREQ=y
+# CONFIG_CPU_FREQ_DEBUG is not set
+CONFIG_CPU_FREQ_STAT=m
+CONFIG_CPU_FREQ_STAT_DETAILS=y
+CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y
+# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set
+CONFIG_CPU_FREQ_GOV_PERFORMANCE=y
+CONFIG_CPU_FREQ_GOV_POWERSAVE=m
+CONFIG_CPU_FREQ_GOV_USERSPACE=m
+CONFIG_CPU_FREQ_GOV_ONDEMAND=m
+CONFIG_CPU_FREQ_PMAC=y
+CONFIG_CPU_FREQ_TABLE=y
+CONFIG_PPC601_SYNC_FIX=y
+CONFIG_PM=y
+CONFIG_PPC_STD_MMU=y
+
+#
+# Platform options
+#
+CONFIG_PPC_MULTIPLATFORM=y
+# CONFIG_APUS is not set
+# CONFIG_KATANA is not set
+# CONFIG_WILLOW is not set
+# CONFIG_CPCI690 is not set
+# CONFIG_PCORE is not set
+# CONFIG_POWERPMC250 is not set
+# CONFIG_CHESTNUT is not set
+# CONFIG_SPRUCE is not set
+# CONFIG_EV64260 is not set
+# CONFIG_LOPEC is not set
+# CONFIG_MCPN765 is not set
+# CONFIG_MVME5100 is not set
+# CONFIG_PPLUS is not set
+# CONFIG_PRPMC750 is not set
+# CONFIG_PRPMC800 is not set
+# CONFIG_SANDPOINT is not set
+# CONFIG_ADIR is not set
+# CONFIG_K2 is not set
+# CONFIG_PAL4 is not set
+# CONFIG_GEMINI is not set
+# CONFIG_EST8260 is not set
+# CONFIG_SBC82xx is not set
+# CONFIG_SBS8260 is not set
+# CONFIG_RPX8260 is not set
+# CONFIG_TQM8260 is not set
+# CONFIG_ADS8272 is not set
+# CONFIG_PQ2FADS is not set
+# CONFIG_LITE5200 is not set
+CONFIG_PPC_CHRP=y
+CONFIG_PPC_PMAC=y
+CONFIG_PPC_PREP=y
+CONFIG_PPC_OF=y
+CONFIG_PPCBUG_NVRAM=y
+# CONFIG_SMP is not set
+# CONFIG_PREEMPT is not set
+# CONFIG_HIGHMEM is not set
+CONFIG_BINFMT_ELF=y
+CONFIG_BINFMT_MISC=m
+CONFIG_PROC_DEVICETREE=y
+# CONFIG_PREP_RESIDUAL is not set
+# CONFIG_CMDLINE_BOOL is not set
+
+#
+# Bus options
+#
+# CONFIG_ISA is not set
+CONFIG_GENERIC_ISA_DMA=y
+CONFIG_PCI=y
+CONFIG_PCI_DOMAINS=y
+CONFIG_PCI_LEGACY_PROC=y
+CONFIG_PCI_NAMES=y
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+CONFIG_PCCARD=m
+# CONFIG_PCMCIA_DEBUG is not set
+CONFIG_PCMCIA=m
+CONFIG_CARDBUS=y
+
+#
+# PC-card bridges
+#
+CONFIG_YENTA=m
+# CONFIG_PD6729 is not set
+# CONFIG_I82092 is not set
+# CONFIG_TCIC is not set
+CONFIG_PCCARD_NONSTATIC=m
+
+#
+# Advanced setup
+#
+CONFIG_ADVANCED_OPTIONS=y
+CONFIG_HIGHMEM_START=0xfe000000
+# CONFIG_LOWMEM_SIZE_BOOL is not set
+CONFIG_LOWMEM_SIZE=0x30000000
+# CONFIG_KERNEL_START_BOOL is not set
+CONFIG_KERNEL_START=0xc0000000
+CONFIG_TASK_SIZE_BOOL=y
+CONFIG_TASK_SIZE=0xc0000000
+CONFIG_BOOT_LOAD=0x00800000
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+# CONFIG_STANDALONE is not set
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+# CONFIG_DEBUG_DRIVER is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+CONFIG_MAC_FLOPPY=m
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_SX8 is not set
+# CONFIG_BLK_DEV_UB is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=4096
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_LBD=y
+CONFIG_CDROM_PKTCDVD=m
+CONFIG_CDROM_PKTCDVD_BUFFERS=8
+# CONFIG_CDROM_PKTCDVD_WCACHE is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+CONFIG_IDE=y
+CONFIG_BLK_DEV_IDE=y
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+# CONFIG_BLK_DEV_IDE_SATA is not set
+CONFIG_BLK_DEV_IDEDISK=y
+# CONFIG_IDEDISK_MULTI_MODE is not set
+# CONFIG_BLK_DEV_IDECS is not set
+CONFIG_BLK_DEV_IDECD=y
+# CONFIG_BLK_DEV_IDETAPE is not set
+CONFIG_BLK_DEV_IDEFLOPPY=y
+CONFIG_BLK_DEV_IDESCSI=y
+# CONFIG_IDE_TASK_IOCTL is not set
+
+#
+# IDE chipset support/bugfixes
+#
+# CONFIG_IDE_GENERIC is not set
+CONFIG_BLK_DEV_IDEPCI=y
+CONFIG_IDEPCI_SHARE_IRQ=y
+# CONFIG_BLK_DEV_OFFBOARD is not set
+CONFIG_BLK_DEV_GENERIC=y
+# CONFIG_BLK_DEV_OPTI621 is not set
+# CONFIG_BLK_DEV_SL82C105 is not set
+CONFIG_BLK_DEV_IDEDMA_PCI=y
+# CONFIG_BLK_DEV_IDEDMA_FORCED is not set
+CONFIG_IDEDMA_PCI_AUTO=y
+# CONFIG_IDEDMA_ONLYDISK is not set
+# CONFIG_BLK_DEV_AEC62XX is not set
+# CONFIG_BLK_DEV_ALI15X3 is not set
+# CONFIG_BLK_DEV_AMD74XX is not set
+CONFIG_BLK_DEV_CMD64X=y
+# CONFIG_BLK_DEV_TRIFLEX is not set
+# CONFIG_BLK_DEV_CY82C693 is not set
+# CONFIG_BLK_DEV_CS5520 is not set
+# CONFIG_BLK_DEV_CS5530 is not set
+# CONFIG_BLK_DEV_HPT34X is not set
+# CONFIG_BLK_DEV_HPT366 is not set
+# CONFIG_BLK_DEV_SC1200 is not set
+# CONFIG_BLK_DEV_PIIX is not set
+# CONFIG_BLK_DEV_NS87415 is not set
+# CONFIG_BLK_DEV_PDC202XX_OLD is not set
+CONFIG_BLK_DEV_PDC202XX_NEW=y
+# CONFIG_PDC202XX_FORCE is not set
+# CONFIG_BLK_DEV_SVWKS is not set
+# CONFIG_BLK_DEV_SIIMAGE is not set
+# CONFIG_BLK_DEV_SLC90E66 is not set
+# CONFIG_BLK_DEV_TRM290 is not set
+# CONFIG_BLK_DEV_VIA82CXXX is not set
+CONFIG_BLK_DEV_IDE_PMAC=y
+CONFIG_BLK_DEV_IDE_PMAC_ATA100FIRST=y
+CONFIG_BLK_DEV_IDEDMA_PMAC=y
+CONFIG_BLK_DEV_IDE_PMAC_BLINK=y
+# CONFIG_IDE_ARM is not set
+CONFIG_BLK_DEV_IDEDMA=y
+# CONFIG_IDEDMA_IVB is not set
+CONFIG_IDEDMA_AUTO=y
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# SCSI device support
+#
+CONFIG_SCSI=y
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+CONFIG_CHR_DEV_ST=y
+# CONFIG_CHR_DEV_OSST is not set
+CONFIG_BLK_DEV_SR=y
+CONFIG_BLK_DEV_SR_VENDOR=y
+CONFIG_CHR_DEV_SG=y
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+# CONFIG_SCSI_MULTI_LUN is not set
+CONFIG_SCSI_CONSTANTS=y
+# CONFIG_SCSI_LOGGING is not set
+
+#
+# SCSI Transport Attributes
+#
+CONFIG_SCSI_SPI_ATTRS=y
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+
+#
+# SCSI low-level drivers
+#
+# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
+# CONFIG_SCSI_3W_9XXX is not set
+# CONFIG_SCSI_ACARD is not set
+# CONFIG_SCSI_AACRAID is not set
+CONFIG_SCSI_AIC7XXX=m
+CONFIG_AIC7XXX_CMDS_PER_DEVICE=253
+CONFIG_AIC7XXX_RESET_DELAY_MS=15000
+CONFIG_AIC7XXX_DEBUG_ENABLE=y
+CONFIG_AIC7XXX_DEBUG_MASK=0
+CONFIG_AIC7XXX_REG_PRETTY_PRINT=y
+CONFIG_SCSI_AIC7XXX_OLD=m
+# CONFIG_SCSI_AIC79XX is not set
+# CONFIG_SCSI_DPT_I2O is not set
+# CONFIG_MEGARAID_NEWGEN is not set
+# CONFIG_MEGARAID_LEGACY is not set
+# CONFIG_SCSI_SATA is not set
+# CONFIG_SCSI_BUSLOGIC is not set
+# CONFIG_SCSI_DMX3191D is not set
+# CONFIG_SCSI_EATA is not set
+# CONFIG_SCSI_EATA_PIO is not set
+# CONFIG_SCSI_FUTURE_DOMAIN is not set
+# CONFIG_SCSI_GDTH is not set
+# CONFIG_SCSI_IPS is not set
+# CONFIG_SCSI_INITIO is not set
+# CONFIG_SCSI_INIA100 is not set
+CONFIG_SCSI_SYM53C8XX_2=y
+CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=0
+CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16
+CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64
+# CONFIG_SCSI_SYM53C8XX_IOMAPPED is not set
+# CONFIG_SCSI_IPR is not set
+# CONFIG_SCSI_QLOGIC_ISP is not set
+# CONFIG_SCSI_QLOGIC_FC is not set
+# CONFIG_SCSI_QLOGIC_1280 is not set
+CONFIG_SCSI_QLA2XXX=y
+# CONFIG_SCSI_QLA21XX is not set
+# CONFIG_SCSI_QLA22XX is not set
+# CONFIG_SCSI_QLA2300 is not set
+# CONFIG_SCSI_QLA2322 is not set
+# CONFIG_SCSI_QLA6312 is not set
+# CONFIG_SCSI_DC395x is not set
+# CONFIG_SCSI_DC390T is not set
+# CONFIG_SCSI_NSP32 is not set
+# CONFIG_SCSI_DEBUG is not set
+CONFIG_SCSI_MESH=y
+CONFIG_SCSI_MESH_SYNC_RATE=5
+CONFIG_SCSI_MESH_RESET_DELAY_MS=1000
+CONFIG_SCSI_MAC53C94=y
+
+#
+# PCMCIA SCSI adapter support
+#
+# CONFIG_PCMCIA_AHA152X is not set
+# CONFIG_PCMCIA_FDOMAIN is not set
+# CONFIG_PCMCIA_NINJA_SCSI is not set
+# CONFIG_PCMCIA_QLOGIC is not set
+# CONFIG_PCMCIA_SYM53C500 is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+# CONFIG_FUSION is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+CONFIG_IEEE1394=m
+
+#
+# Subsystem Options
+#
+# CONFIG_IEEE1394_VERBOSEDEBUG is not set
+# CONFIG_IEEE1394_OUI_DB is not set
+CONFIG_IEEE1394_EXTRA_CONFIG_ROMS=y
+CONFIG_IEEE1394_CONFIG_ROM_IP1394=y
+
+#
+# Device Drivers
+#
+# CONFIG_IEEE1394_PCILYNX is not set
+CONFIG_IEEE1394_OHCI1394=m
+
+#
+# Protocol Drivers
+#
+CONFIG_IEEE1394_VIDEO1394=m
+CONFIG_IEEE1394_SBP2=m
+# CONFIG_IEEE1394_SBP2_PHYS_DMA is not set
+CONFIG_IEEE1394_ETH1394=m
+CONFIG_IEEE1394_DV1394=m
+CONFIG_IEEE1394_RAWIO=m
+CONFIG_IEEE1394_CMP=m
+CONFIG_IEEE1394_AMDTP=m
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# Macintosh device drivers
+#
+CONFIG_ADB=y
+CONFIG_ADB_CUDA=y
+CONFIG_ADB_PMU=y
+CONFIG_PMAC_PBOOK=y
+CONFIG_PMAC_APM_EMU=y
+CONFIG_PMAC_BACKLIGHT=y
+CONFIG_ADB_MACIO=y
+CONFIG_INPUT_ADBHID=y
+CONFIG_MAC_EMUMOUSEBTN=y
+CONFIG_THERM_WINDTUNNEL=m
+CONFIG_THERM_ADT746X=m
+# CONFIG_ANSLCD is not set
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+# CONFIG_NETLINK_DEV is not set
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+# CONFIG_IP_PNP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_IP_MROUTE is not set
+# CONFIG_ARPD is not set
+CONFIG_SYN_COOKIES=y
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_IP_TCPDIAG=y
+# CONFIG_IP_TCPDIAG_IPV6 is not set
+
+#
+# IP: Virtual Server Configuration
+#
+# CONFIG_IP_VS is not set
+# CONFIG_IPV6 is not set
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+
+#
+# IP: Netfilter Configuration
+#
+CONFIG_IP_NF_CONNTRACK=m
+CONFIG_IP_NF_CT_ACCT=y
+CONFIG_IP_NF_CONNTRACK_MARK=y
+CONFIG_IP_NF_CT_PROTO_SCTP=m
+CONFIG_IP_NF_FTP=m
+CONFIG_IP_NF_IRC=m
+CONFIG_IP_NF_TFTP=m
+CONFIG_IP_NF_AMANDA=m
+CONFIG_IP_NF_QUEUE=m
+CONFIG_IP_NF_IPTABLES=m
+CONFIG_IP_NF_MATCH_LIMIT=m
+CONFIG_IP_NF_MATCH_IPRANGE=m
+CONFIG_IP_NF_MATCH_MAC=m
+CONFIG_IP_NF_MATCH_PKTTYPE=m
+CONFIG_IP_NF_MATCH_MARK=m
+CONFIG_IP_NF_MATCH_MULTIPORT=m
+CONFIG_IP_NF_MATCH_TOS=m
+CONFIG_IP_NF_MATCH_RECENT=m
+CONFIG_IP_NF_MATCH_ECN=m
+CONFIG_IP_NF_MATCH_DSCP=m
+CONFIG_IP_NF_MATCH_AH_ESP=m
+CONFIG_IP_NF_MATCH_LENGTH=m
+CONFIG_IP_NF_MATCH_TTL=m
+CONFIG_IP_NF_MATCH_TCPMSS=m
+CONFIG_IP_NF_MATCH_HELPER=m
+CONFIG_IP_NF_MATCH_STATE=m
+CONFIG_IP_NF_MATCH_CONNTRACK=m
+CONFIG_IP_NF_MATCH_OWNER=m
+CONFIG_IP_NF_MATCH_ADDRTYPE=m
+CONFIG_IP_NF_MATCH_REALM=m
+CONFIG_IP_NF_MATCH_SCTP=m
+CONFIG_IP_NF_MATCH_COMMENT=m
+CONFIG_IP_NF_MATCH_CONNMARK=m
+CONFIG_IP_NF_MATCH_HASHLIMIT=m
+CONFIG_IP_NF_FILTER=m
+CONFIG_IP_NF_TARGET_REJECT=m
+CONFIG_IP_NF_TARGET_LOG=m
+CONFIG_IP_NF_TARGET_ULOG=m
+CONFIG_IP_NF_TARGET_TCPMSS=m
+CONFIG_IP_NF_NAT=m
+CONFIG_IP_NF_NAT_NEEDED=y
+CONFIG_IP_NF_TARGET_MASQUERADE=m
+CONFIG_IP_NF_TARGET_REDIRECT=m
+CONFIG_IP_NF_TARGET_NETMAP=m
+CONFIG_IP_NF_TARGET_SAME=m
+CONFIG_IP_NF_NAT_SNMP_BASIC=m
+CONFIG_IP_NF_NAT_IRC=m
+CONFIG_IP_NF_NAT_FTP=m
+CONFIG_IP_NF_NAT_TFTP=m
+CONFIG_IP_NF_NAT_AMANDA=m
+CONFIG_IP_NF_MANGLE=m
+CONFIG_IP_NF_TARGET_TOS=m
+CONFIG_IP_NF_TARGET_ECN=m
+CONFIG_IP_NF_TARGET_DSCP=m
+CONFIG_IP_NF_TARGET_MARK=m
+CONFIG_IP_NF_TARGET_CLASSIFY=m
+CONFIG_IP_NF_TARGET_CONNMARK=m
+CONFIG_IP_NF_TARGET_CLUSTERIP=m
+CONFIG_IP_NF_RAW=m
+CONFIG_IP_NF_TARGET_NOTRACK=m
+CONFIG_IP_NF_ARPTABLES=m
+CONFIG_IP_NF_ARPFILTER=m
+CONFIG_IP_NF_ARP_MANGLE=m
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+CONFIG_NET_CLS_ROUTE=y
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_HAMRADIO is not set
+CONFIG_IRDA=m
+
+#
+# IrDA protocols
+#
+CONFIG_IRLAN=m
+CONFIG_IRNET=m
+CONFIG_IRCOMM=m
+# CONFIG_IRDA_ULTRA is not set
+
+#
+# IrDA options
+#
+CONFIG_IRDA_CACHE_LAST_LSAP=y
+CONFIG_IRDA_FAST_RR=y
+# CONFIG_IRDA_DEBUG is not set
+
+#
+# Infrared-port device drivers
+#
+
+#
+# SIR device drivers
+#
+CONFIG_IRTTY_SIR=m
+
+#
+# Dongle support
+#
+# CONFIG_DONGLE is not set
+
+#
+# Old SIR device drivers
+#
+# CONFIG_IRPORT_SIR is not set
+
+#
+# Old Serial dongle support
+#
+
+#
+# FIR device drivers
+#
+# CONFIG_USB_IRDA is not set
+# CONFIG_SIGMATEL_FIR is not set
+# CONFIG_TOSHIBA_FIR is not set
+# CONFIG_VLSI_FIR is not set
+# CONFIG_BT is not set
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+CONFIG_MACE=y
+# CONFIG_MACE_AAUI_PORT is not set
+CONFIG_BMAC=y
+# CONFIG_HAPPYMEAL is not set
+CONFIG_SUNGEM=y
+# CONFIG_NET_VENDOR_3COM is not set
+
+#
+# Tulip family network device support
+#
+# CONFIG_NET_TULIP is not set
+# CONFIG_HP100 is not set
+CONFIG_NET_PCI=y
+CONFIG_PCNET32=y
+# CONFIG_AMD8111_ETH is not set
+# CONFIG_ADAPTEC_STARFIRE is not set
+# CONFIG_B44 is not set
+# CONFIG_FORCEDETH is not set
+# CONFIG_DGRS is not set
+# CONFIG_EEPRO100 is not set
+# CONFIG_E100 is not set
+# CONFIG_FEALNX is not set
+# CONFIG_NATSEMI is not set
+# CONFIG_NE2K_PCI is not set
+# CONFIG_8139CP is not set
+# CONFIG_8139TOO is not set
+# CONFIG_SIS900 is not set
+# CONFIG_EPIC100 is not set
+# CONFIG_SUNDANCE is not set
+# CONFIG_TLAN is not set
+# CONFIG_VIA_RHINE is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_E1000 is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_VIA_VELOCITY is not set
+# CONFIG_TIGON3 is not set
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_IXGB is not set
+# CONFIG_S2IO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+CONFIG_NET_RADIO=y
+
+#
+# Obsolete Wireless cards support (pre-802.11)
+#
+# CONFIG_STRIP is not set
+# CONFIG_PCMCIA_WAVELAN is not set
+# CONFIG_PCMCIA_NETWAVE is not set
+
+#
+# Wireless 802.11 Frequency Hopping cards support
+#
+# CONFIG_PCMCIA_RAYCS is not set
+
+#
+# Wireless 802.11b ISA/PCI cards support
+#
+CONFIG_HERMES=m
+CONFIG_APPLE_AIRPORT=m
+# CONFIG_PLX_HERMES is not set
+# CONFIG_TMD_HERMES is not set
+# CONFIG_PCI_HERMES is not set
+# CONFIG_ATMEL is not set
+
+#
+# Wireless 802.11b Pcmcia/Cardbus cards support
+#
+CONFIG_PCMCIA_HERMES=m
+# CONFIG_AIRO_CS is not set
+# CONFIG_PCMCIA_WL3501 is not set
+
+#
+# Prism GT/Duette 802.11(a/b/g) PCI/Cardbus support
+#
+# CONFIG_PRISM54 is not set
+CONFIG_NET_WIRELESS=y
+
+#
+# PCMCIA network device support
+#
+# CONFIG_NET_PCMCIA is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+CONFIG_PPP=y
+CONFIG_PPP_MULTILINK=y
+# CONFIG_PPP_FILTER is not set
+CONFIG_PPP_ASYNC=y
+CONFIG_PPP_SYNC_TTY=m
+CONFIG_PPP_DEFLATE=y
+CONFIG_PPP_BSDCOMP=m
+CONFIG_PPPOE=m
+# CONFIG_SLIP is not set
+# CONFIG_NET_FC is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input I/O drivers
+#
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+# CONFIG_SERIO is not set
+# CONFIG_SERIO_I8042 is not set
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+# CONFIG_KEYBOARD_ATKBD is not set
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+CONFIG_INPUT_MOUSE=y
+# CONFIG_MOUSE_PS2 is not set
+# CONFIG_MOUSE_SERIAL is not set
+# CONFIG_MOUSE_VSXXXAA is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=m
+CONFIG_SERIAL_8250_CS=m
+CONFIG_SERIAL_8250_NR_UARTS=4
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_SERIAL_PMACZILOG=y
+CONFIG_SERIAL_PMACZILOG_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+CONFIG_NVRAM=y
+CONFIG_GEN_RTC=y
+# CONFIG_GEN_RTC_X is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+CONFIG_AGP=m
+CONFIG_AGP_UNINORTH=m
+CONFIG_DRM=m
+# CONFIG_DRM_TDFX is not set
+CONFIG_DRM_R128=m
+CONFIG_DRM_RADEON=m
+# CONFIG_DRM_MGA is not set
+# CONFIG_DRM_SIS is not set
+
+#
+# PCMCIA character devices
+#
+# CONFIG_SYNCLINK_CS is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# I2C support
+#
+CONFIG_I2C=y
+CONFIG_I2C_CHARDEV=m
+
+#
+# I2C Algorithms
+#
+CONFIG_I2C_ALGOBIT=y
+# CONFIG_I2C_ALGOPCF is not set
+# CONFIG_I2C_ALGOPCA is not set
+
+#
+# I2C Hardware Bus support
+#
+# CONFIG_I2C_ALI1535 is not set
+# CONFIG_I2C_ALI1563 is not set
+# CONFIG_I2C_ALI15X3 is not set
+# CONFIG_I2C_AMD756 is not set
+# CONFIG_I2C_AMD8111 is not set
+# CONFIG_I2C_HYDRA is not set
+# CONFIG_I2C_I801 is not set
+# CONFIG_I2C_I810 is not set
+# CONFIG_I2C_ISA is not set
+CONFIG_I2C_KEYWEST=m
+# CONFIG_I2C_MPC is not set
+# CONFIG_I2C_NFORCE2 is not set
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_PIIX4 is not set
+# CONFIG_I2C_PROSAVAGE is not set
+# CONFIG_I2C_SAVAGE4 is not set
+# CONFIG_SCx200_ACB is not set
+# CONFIG_I2C_SIS5595 is not set
+# CONFIG_I2C_SIS630 is not set
+# CONFIG_I2C_SIS96X is not set
+# CONFIG_I2C_STUB is not set
+# CONFIG_I2C_VIA is not set
+# CONFIG_I2C_VIAPRO is not set
+# CONFIG_I2C_VOODOO3 is not set
+# CONFIG_I2C_PCA_ISA is not set
+
+#
+# Hardware Sensors Chip support
+#
+# CONFIG_I2C_SENSOR is not set
+# CONFIG_SENSORS_ADM1021 is not set
+# CONFIG_SENSORS_ADM1025 is not set
+# CONFIG_SENSORS_ADM1026 is not set
+# CONFIG_SENSORS_ADM1031 is not set
+# CONFIG_SENSORS_ASB100 is not set
+# CONFIG_SENSORS_DS1621 is not set
+# CONFIG_SENSORS_FSCHER is not set
+# CONFIG_SENSORS_GL518SM is not set
+# CONFIG_SENSORS_IT87 is not set
+# CONFIG_SENSORS_LM63 is not set
+# CONFIG_SENSORS_LM75 is not set
+# CONFIG_SENSORS_LM77 is not set
+# CONFIG_SENSORS_LM78 is not set
+# CONFIG_SENSORS_LM80 is not set
+# CONFIG_SENSORS_LM83 is not set
+# CONFIG_SENSORS_LM85 is not set
+# CONFIG_SENSORS_LM87 is not set
+# CONFIG_SENSORS_LM90 is not set
+# CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_PC87360 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_VIA686A is not set
+# CONFIG_SENSORS_W83781D is not set
+# CONFIG_SENSORS_W83L785TS is not set
+# CONFIG_SENSORS_W83627HF is not set
+
+#
+# Other I2C Chip support
+#
+# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_SENSORS_RTC8564 is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
+# Misc devices
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+CONFIG_FB=y
+CONFIG_FB_MODE_HELPERS=y
+CONFIG_FB_TILEBLITTING=y
+# CONFIG_FB_CIRRUS is not set
+# CONFIG_FB_PM2 is not set
+# CONFIG_FB_CYBER2000 is not set
+CONFIG_FB_OF=y
+CONFIG_FB_CONTROL=y
+CONFIG_FB_PLATINUM=y
+CONFIG_FB_VALKYRIE=y
+CONFIG_FB_CT65550=y
+# CONFIG_FB_ASILIANT is not set
+CONFIG_FB_IMSTT=y
+# CONFIG_FB_VGA16 is not set
+# CONFIG_FB_RIVA is not set
+CONFIG_FB_MATROX=y
+CONFIG_FB_MATROX_MILLENIUM=y
+CONFIG_FB_MATROX_MYSTIQUE=y
+CONFIG_FB_MATROX_G=y
+# CONFIG_FB_MATROX_I2C is not set
+# CONFIG_FB_MATROX_MULTIHEAD is not set
+# CONFIG_FB_RADEON_OLD is not set
+CONFIG_FB_RADEON=y
+CONFIG_FB_RADEON_I2C=y
+# CONFIG_FB_RADEON_DEBUG is not set
+CONFIG_FB_ATY128=y
+CONFIG_FB_ATY=y
+CONFIG_FB_ATY_CT=y
+CONFIG_FB_ATY_GENERIC_LCD=y
+# CONFIG_FB_ATY_XL_INIT is not set
+CONFIG_FB_ATY_GX=y
+# CONFIG_FB_SAVAGE is not set
+# CONFIG_FB_SIS is not set
+# CONFIG_FB_NEOMAGIC is not set
+# CONFIG_FB_KYRO is not set
+CONFIG_FB_3DFX=y
+CONFIG_FB_3DFX_ACCEL=y
+# CONFIG_FB_VOODOO1 is not set
+# CONFIG_FB_TRIDENT is not set
+# CONFIG_FB_VIRTUAL is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+# CONFIG_FONTS is not set
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
+
+#
+# Logo configuration
+#
+CONFIG_LOGO=y
+CONFIG_LOGO_LINUX_MONO=y
+CONFIG_LOGO_LINUX_VGA16=y
+CONFIG_LOGO_LINUX_CLUT224=y
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+CONFIG_BACKLIGHT_CLASS_DEVICE=y
+CONFIG_BACKLIGHT_DEVICE=y
+CONFIG_LCD_CLASS_DEVICE=y
+CONFIG_LCD_DEVICE=y
+
+#
+# Sound
+#
+CONFIG_SOUND=m
+CONFIG_DMASOUND_PMAC=m
+CONFIG_DMASOUND=m
+
+#
+# Advanced Linux Sound Architecture
+#
+CONFIG_SND=m
+CONFIG_SND_TIMER=m
+CONFIG_SND_PCM=m
+CONFIG_SND_HWDEP=m
+CONFIG_SND_RAWMIDI=m
+CONFIG_SND_SEQUENCER=m
+CONFIG_SND_SEQ_DUMMY=m
+CONFIG_SND_OSSEMUL=y
+CONFIG_SND_MIXER_OSS=m
+CONFIG_SND_PCM_OSS=m
+CONFIG_SND_SEQUENCER_OSS=y
+# CONFIG_SND_VERBOSE_PRINTK is not set
+# CONFIG_SND_DEBUG is not set
+
+#
+# Generic devices
+#
+CONFIG_SND_DUMMY=m
+# CONFIG_SND_VIRMIDI is not set
+# CONFIG_SND_MTPAV is not set
+# CONFIG_SND_SERIAL_U16550 is not set
+# CONFIG_SND_MPU401 is not set
+
+#
+# PCI devices
+#
+# CONFIG_SND_ALI5451 is not set
+# CONFIG_SND_ATIIXP is not set
+# CONFIG_SND_ATIIXP_MODEM is not set
+# CONFIG_SND_AU8810 is not set
+# CONFIG_SND_AU8820 is not set
+# CONFIG_SND_AU8830 is not set
+# CONFIG_SND_AZT3328 is not set
+# CONFIG_SND_BT87X is not set
+# CONFIG_SND_CS46XX is not set
+# CONFIG_SND_CS4281 is not set
+# CONFIG_SND_EMU10K1 is not set
+# CONFIG_SND_EMU10K1X is not set
+# CONFIG_SND_CA0106 is not set
+# CONFIG_SND_KORG1212 is not set
+# CONFIG_SND_MIXART is not set
+# CONFIG_SND_NM256 is not set
+# CONFIG_SND_RME32 is not set
+# CONFIG_SND_RME96 is not set
+# CONFIG_SND_RME9652 is not set
+# CONFIG_SND_HDSP is not set
+# CONFIG_SND_TRIDENT is not set
+# CONFIG_SND_YMFPCI is not set
+# CONFIG_SND_ALS4000 is not set
+# CONFIG_SND_CMIPCI is not set
+# CONFIG_SND_ENS1370 is not set
+# CONFIG_SND_ENS1371 is not set
+# CONFIG_SND_ES1938 is not set
+# CONFIG_SND_ES1968 is not set
+# CONFIG_SND_MAESTRO3 is not set
+# CONFIG_SND_FM801 is not set
+# CONFIG_SND_ICE1712 is not set
+# CONFIG_SND_ICE1724 is not set
+# CONFIG_SND_INTEL8X0 is not set
+# CONFIG_SND_INTEL8X0M is not set
+# CONFIG_SND_SONICVIBES is not set
+# CONFIG_SND_VIA82XX is not set
+# CONFIG_SND_VIA82XX_MODEM is not set
+# CONFIG_SND_VX222 is not set
+
+#
+# ALSA PowerMac devices
+#
+CONFIG_SND_POWERMAC=m
+
+#
+# USB devices
+#
+CONFIG_SND_USB_AUDIO=m
+CONFIG_SND_USB_USX2Y=m
+
+#
+# PCMCIA devices
+#
+
+#
+# Open Sound System
+#
+# CONFIG_SOUND_PRIME is not set
+
+#
+# USB support
+#
+CONFIG_USB=y
+# CONFIG_USB_DEBUG is not set
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEVICEFS=y
+# CONFIG_USB_BANDWIDTH is not set
+CONFIG_USB_DYNAMIC_MINORS=y
+CONFIG_USB_SUSPEND=y
+# CONFIG_USB_OTG is not set
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+
+#
+# USB Host Controller Drivers
+#
+# CONFIG_USB_EHCI_HCD is not set
+CONFIG_USB_OHCI_HCD=y
+# CONFIG_USB_UHCI_HCD is not set
+# CONFIG_USB_SL811_HCD is not set
+
+#
+# USB Device Class drivers
+#
+# CONFIG_USB_AUDIO is not set
+# CONFIG_USB_BLUETOOTH_TTY is not set
+# CONFIG_USB_MIDI is not set
+CONFIG_USB_ACM=m
+CONFIG_USB_PRINTER=m
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
+#
+# CONFIG_USB_STORAGE is not set
+
+#
+# USB Input Devices
+#
+CONFIG_USB_HID=y
+CONFIG_USB_HIDINPUT=y
+# CONFIG_HID_FF is not set
+CONFIG_USB_HIDDEV=y
+# CONFIG_USB_AIPTEK is not set
+# CONFIG_USB_WACOM is not set
+# CONFIG_USB_KBTAB is not set
+# CONFIG_USB_POWERMATE is not set
+# CONFIG_USB_MTOUCH is not set
+# CONFIG_USB_EGALAX is not set
+# CONFIG_USB_XPAD is not set
+# CONFIG_USB_ATI_REMOTE is not set
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_MICROTEK is not set
+
+#
+# USB Multimedia devices
+#
+# CONFIG_USB_DABUSB is not set
+
+#
+# Video4Linux support is needed for USB Multimedia device support
+#
+
+#
+# USB Network Adapters
+#
+# CONFIG_USB_CATC is not set
+# CONFIG_USB_KAWETH is not set
+CONFIG_USB_PEGASUS=m
+# CONFIG_USB_RTL8150 is not set
+# CONFIG_USB_USBNET is not set
+
+#
+# USB port drivers
+#
+
+#
+# USB Serial Converter support
+#
+CONFIG_USB_SERIAL=m
+# CONFIG_USB_SERIAL_GENERIC is not set
+# CONFIG_USB_SERIAL_BELKIN is not set
+# CONFIG_USB_SERIAL_WHITEHEAT is not set
+# CONFIG_USB_SERIAL_DIGI_ACCELEPORT is not set
+# CONFIG_USB_SERIAL_CYPRESS_M8 is not set
+# CONFIG_USB_SERIAL_EMPEG is not set
+# CONFIG_USB_SERIAL_FTDI_SIO is not set
+CONFIG_USB_SERIAL_VISOR=m
+# CONFIG_USB_SERIAL_IPAQ is not set
+# CONFIG_USB_SERIAL_IR is not set
+# CONFIG_USB_SERIAL_EDGEPORT is not set
+# CONFIG_USB_SERIAL_EDGEPORT_TI is not set
+# CONFIG_USB_SERIAL_GARMIN is not set
+# CONFIG_USB_SERIAL_IPW is not set
+# CONFIG_USB_SERIAL_KEYSPAN_PDA is not set
+CONFIG_USB_SERIAL_KEYSPAN=m
+CONFIG_USB_SERIAL_KEYSPAN_MPR=y
+CONFIG_USB_SERIAL_KEYSPAN_USA28=y
+CONFIG_USB_SERIAL_KEYSPAN_USA28X=y
+CONFIG_USB_SERIAL_KEYSPAN_USA28XA=y
+CONFIG_USB_SERIAL_KEYSPAN_USA28XB=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19=y
+CONFIG_USB_SERIAL_KEYSPAN_USA18X=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19W=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19QW=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19QI=y
+CONFIG_USB_SERIAL_KEYSPAN_USA49W=y
+CONFIG_USB_SERIAL_KEYSPAN_USA49WLC=y
+# CONFIG_USB_SERIAL_KLSI is not set
+# CONFIG_USB_SERIAL_KOBIL_SCT is not set
+# CONFIG_USB_SERIAL_MCT_U232 is not set
+# CONFIG_USB_SERIAL_PL2303 is not set
+# CONFIG_USB_SERIAL_SAFE is not set
+# CONFIG_USB_SERIAL_TI is not set
+# CONFIG_USB_SERIAL_CYBERJACK is not set
+# CONFIG_USB_SERIAL_XIRCOM is not set
+# CONFIG_USB_SERIAL_OMNINET is not set
+CONFIG_USB_EZUSB=y
+
+#
+# USB Miscellaneous drivers
+#
+# CONFIG_USB_EMI62 is not set
+# CONFIG_USB_EMI26 is not set
+# CONFIG_USB_AUERSWALD is not set
+# CONFIG_USB_RIO500 is not set
+# CONFIG_USB_LEGOTOWER is not set
+# CONFIG_USB_LCD is not set
+# CONFIG_USB_LED is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_PHIDGETKIT is not set
+# CONFIG_USB_PHIDGETSERVO is not set
+# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_TEST is not set
+
+#
+# USB ATM/DSL drivers
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# InfiniBand support
+#
+# CONFIG_INFINIBAND is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+# CONFIG_EXT2_FS_POSIX_ACL is not set
+# CONFIG_EXT2_FS_SECURITY is not set
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_FS_XATTR=y
+# CONFIG_EXT3_FS_POSIX_ACL is not set
+# CONFIG_EXT3_FS_SECURITY is not set
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+CONFIG_FS_MBCACHE=y
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+
+#
+# XFS support
+#
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+CONFIG_ISO9660_FS=y
+# CONFIG_JOLIET is not set
+# CONFIG_ZISOFS is not set
+CONFIG_UDF_FS=m
+CONFIG_UDF_NLS=y
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=m
+CONFIG_MSDOS_FS=m
+CONFIG_VFAT_FS=m
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_SYSFS=y
+# CONFIG_DEVFS_FS is not set
+CONFIG_DEVPTS_FS_XATTR=y
+CONFIG_DEVPTS_FS_SECURITY=y
+CONFIG_TMPFS=y
+CONFIG_TMPFS_XATTR=y
+CONFIG_TMPFS_SECURITY=y
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+CONFIG_HFS_FS=m
+CONFIG_HFSPLUS_FS=m
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+CONFIG_CRAMFS=m
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+CONFIG_NFSD=y
+CONFIG_NFSD_V3=y
+# CONFIG_NFSD_V4 is not set
+CONFIG_NFSD_TCP=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_EXPORTFS=y
+CONFIG_SUNRPC=y
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+CONFIG_SMB_FS=m
+# CONFIG_SMB_NLS_DEFAULT is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+CONFIG_MAC_PARTITION=y
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_BSD_DISKLABEL is not set
+# CONFIG_MINIX_SUBPARTITION is not set
+# CONFIG_SOLARIS_X86_PARTITION is not set
+# CONFIG_UNIXWARE_DISKLABEL is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_EFI_PARTITION is not set
+
+#
+# Native Language Support
+#
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+# CONFIG_NLS_CODEPAGE_437 is not set
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+CONFIG_NLS_CODEPAGE_1250=m
+CONFIG_NLS_CODEPAGE_1251=m
+CONFIG_NLS_ASCII=m
+CONFIG_NLS_ISO8859_1=m
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+CONFIG_NLS_ISO8859_15=m
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+CONFIG_NLS_UTF8=m
+
+#
+# Library routines
+#
+CONFIG_CRC_CCITT=y
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+CONFIG_DEBUG_KERNEL=y
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_DEBUG_SLAB is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_KOBJECT is not set
+# CONFIG_DEBUG_INFO is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_XMON is not set
+# CONFIG_BDI_SWITCH is not set
+CONFIG_BOOTX_TEXT=y
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Hardware crypto devices
+#
diff --git a/arch/ppc/configs/power3_defconfig b/arch/ppc/configs/power3_defconfig
new file mode 100644
index 0000000..93da595
--- /dev/null
+++ b/arch/ppc/configs/power3_defconfig
@@ -0,0 +1,1034 @@
+#
+# Automatically generated make config: don't edit
+#
+CONFIG_MMU=y
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_HAVE_DEC_LOCK=y
+CONFIG_PPC=y
+CONFIG_PPC32=y
+CONFIG_GENERIC_NVRAM=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=y
+# CONFIG_STANDALONE is not set
+
+#
+# General setup
+#
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_POSIX_MQUEUE=y
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+CONFIG_LOG_BUF_SHIFT=15
+# CONFIG_HOTPLUG is not set
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+# CONFIG_EMBEDDED is not set
+CONFIG_KALLSYMS=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+CONFIG_OBSOLETE_MODPARM=y
+# CONFIG_MODVERSIONS is not set
+CONFIG_KMOD=y
+CONFIG_STOP_MACHINE=y
+
+#
+# Processor
+#
+# CONFIG_6xx is not set
+# CONFIG_40x is not set
+# CONFIG_44x is not set
+CONFIG_POWER3=y
+# CONFIG_POWER4 is not set
+# CONFIG_8xx is not set
+# CONFIG_CPU_FREQ is not set
+CONFIG_PPC64BRIDGE=y
+CONFIG_PPC_STD_MMU=y
+
+#
+# Platform options
+#
+CONFIG_PPC_MULTIPLATFORM=y
+# CONFIG_APUS is not set
+# CONFIG_WILLOW is not set
+# CONFIG_PCORE is not set
+# CONFIG_POWERPMC250 is not set
+# CONFIG_EV64260 is not set
+# CONFIG_SPRUCE is not set
+# CONFIG_LOPEC is not set
+# CONFIG_MCPN765 is not set
+# CONFIG_MVME5100 is not set
+# CONFIG_PPLUS is not set
+# CONFIG_PRPMC750 is not set
+# CONFIG_PRPMC800 is not set
+# CONFIG_SANDPOINT is not set
+# CONFIG_ADIR is not set
+# CONFIG_K2 is not set
+# CONFIG_PAL4 is not set
+# CONFIG_GEMINI is not set
+# CONFIG_EST8260 is not set
+# CONFIG_SBS8260 is not set
+# CONFIG_RPX6 is not set
+# CONFIG_TQM8260 is not set
+CONFIG_PPC_CHRP=y
+CONFIG_PPC_PMAC=y
+CONFIG_PPC_PREP=y
+CONFIG_PPC_OF=y
+CONFIG_PPCBUG_NVRAM=y
+CONFIG_SMP=y
+# CONFIG_IRQ_ALL_CPUS is not set
+CONFIG_NR_CPUS=32
+# CONFIG_PREEMPT is not set
+CONFIG_HIGHMEM=y
+CONFIG_KERNEL_ELF=y
+CONFIG_BINFMT_ELF=y
+CONFIG_BINFMT_MISC=y
+CONFIG_PROC_DEVICETREE=y
+CONFIG_PPC_RTAS=y
+# CONFIG_PREP_RESIDUAL is not set
+# CONFIG_CMDLINE_BOOL is not set
+
+#
+# Bus options
+#
+CONFIG_ISA=y
+CONFIG_GENERIC_ISA_DMA=y
+CONFIG_PCI=y
+CONFIG_PCI_DOMAINS=y
+CONFIG_PCI_LEGACY_PROC=y
+CONFIG_PCI_NAMES=y
+
+#
+# Advanced setup
+#
+CONFIG_ADVANCED_OPTIONS=y
+# CONFIG_HIGHMEM_START_BOOL is not set
+CONFIG_HIGHMEM_START=0xfe000000
+# CONFIG_LOWMEM_SIZE_BOOL is not set
+CONFIG_LOWMEM_SIZE=0x30000000
+# CONFIG_KERNEL_START_BOOL is not set
+CONFIG_KERNEL_START=0xc0000000
+CONFIG_TASK_SIZE_BOOL=y
+CONFIG_TASK_SIZE=0xc0000000
+CONFIG_BOOT_LOAD=0x00800000
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Parallel port support
+#
+CONFIG_PARPORT=m
+CONFIG_PARPORT_PC=m
+CONFIG_PARPORT_PC_CML1=m
+# CONFIG_PARPORT_SERIAL is not set
+CONFIG_PARPORT_PC_FIFO=y
+# CONFIG_PARPORT_PC_SUPERIO is not set
+# CONFIG_PARPORT_OTHER is not set
+# CONFIG_PARPORT_1284 is not set
+
+#
+# Plug and Play support
+#
+# CONFIG_PNP is not set
+
+#
+# Block devices
+#
+CONFIG_BLK_DEV_FD=y
+# CONFIG_BLK_DEV_XD is not set
+# CONFIG_PARIDE is not set
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_CARMEL is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=4096
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_LBD=y
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+CONFIG_SCSI=y
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+CONFIG_CHR_DEV_ST=y
+# CONFIG_CHR_DEV_OSST is not set
+CONFIG_BLK_DEV_SR=y
+CONFIG_BLK_DEV_SR_VENDOR=y
+CONFIG_CHR_DEV_SG=y
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+# CONFIG_SCSI_MULTI_LUN is not set
+# CONFIG_SCSI_REPORT_LUNS is not set
+CONFIG_SCSI_CONSTANTS=y
+CONFIG_SCSI_LOGGING=y
+
+#
+# SCSI Transport Attributes
+#
+CONFIG_SCSI_SPI_ATTRS=y
+# CONFIG_SCSI_FC_ATTRS is not set
+
+#
+# SCSI low-level drivers
+#
+# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
+# CONFIG_SCSI_7000FASST is not set
+# CONFIG_SCSI_ACARD is not set
+# CONFIG_SCSI_AHA152X is not set
+# CONFIG_SCSI_AHA1542 is not set
+# CONFIG_SCSI_AACRAID is not set
+# CONFIG_SCSI_AIC7XXX is not set
+# CONFIG_SCSI_AIC7XXX_OLD is not set
+# CONFIG_SCSI_AIC79XX is not set
+# CONFIG_SCSI_ADVANSYS is not set
+# CONFIG_SCSI_IN2000 is not set
+# CONFIG_SCSI_MEGARAID is not set
+# CONFIG_SCSI_SATA is not set
+# CONFIG_SCSI_BUSLOGIC is not set
+# CONFIG_SCSI_CPQFCTS is not set
+# CONFIG_SCSI_DMX3191D is not set
+# CONFIG_SCSI_DTC3280 is not set
+# CONFIG_SCSI_EATA is not set
+# CONFIG_SCSI_EATA_PIO is not set
+# CONFIG_SCSI_FUTURE_DOMAIN is not set
+# CONFIG_SCSI_GDTH is not set
+# CONFIG_SCSI_GENERIC_NCR5380 is not set
+# CONFIG_SCSI_GENERIC_NCR5380_MMIO is not set
+# CONFIG_SCSI_IPS is not set
+# CONFIG_SCSI_INIA100 is not set
+# CONFIG_SCSI_PPA is not set
+# CONFIG_SCSI_IMM is not set
+# CONFIG_SCSI_NCR53C406A is not set
+CONFIG_SCSI_SYM53C8XX_2=y
+CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=1
+CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16
+CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64
+# CONFIG_SCSI_SYM53C8XX_IOMAPPED is not set
+# CONFIG_SCSI_IPR is not set
+# CONFIG_SCSI_PAS16 is not set
+# CONFIG_SCSI_PSI240I is not set
+# CONFIG_SCSI_QLOGIC_FAS is not set
+# CONFIG_SCSI_QLOGIC_ISP is not set
+# CONFIG_SCSI_QLOGIC_FC is not set
+# CONFIG_SCSI_QLOGIC_1280 is not set
+CONFIG_SCSI_QLA2XXX=y
+# CONFIG_SCSI_QLA21XX is not set
+# CONFIG_SCSI_QLA22XX is not set
+# CONFIG_SCSI_QLA2300 is not set
+# CONFIG_SCSI_QLA2322 is not set
+# CONFIG_SCSI_QLA6312 is not set
+# CONFIG_SCSI_QLA6322 is not set
+# CONFIG_SCSI_SYM53C416 is not set
+# CONFIG_SCSI_DC395x is not set
+# CONFIG_SCSI_DC390T is not set
+# CONFIG_SCSI_T128 is not set
+# CONFIG_SCSI_U14_34F is not set
+# CONFIG_SCSI_NSP32 is not set
+# CONFIG_SCSI_DEBUG is not set
+# CONFIG_SCSI_MESH is not set
+# CONFIG_SCSI_MAC53C94 is not set
+
+#
+# Old CD-ROM drivers (not SCSI, not IDE)
+#
+# CONFIG_CD_NO_IDESCSI is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+CONFIG_MD=y
+CONFIG_BLK_DEV_MD=y
+CONFIG_MD_LINEAR=y
+CONFIG_MD_RAID0=y
+CONFIG_MD_RAID1=y
+CONFIG_MD_RAID5=y
+CONFIG_MD_RAID6=y
+# CONFIG_MD_MULTIPATH is not set
+CONFIG_BLK_DEV_DM=y
+CONFIG_DM_CRYPT=y
+
+#
+# Fusion MPT device support
+#
+# CONFIG_FUSION is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# Macintosh device drivers
+#
+# CONFIG_ADB is not set
+# CONFIG_ADB_CUDA is not set
+# CONFIG_ADB_PMU is not set
+# CONFIG_MAC_FLOPPY is not set
+# CONFIG_MAC_SERIAL is not set
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+# CONFIG_NETLINK_DEV is not set
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+# CONFIG_IP_PNP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_IP_MROUTE is not set
+# CONFIG_ARPD is not set
+CONFIG_SYN_COOKIES=y
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_IPV6 is not set
+# CONFIG_NETFILTER is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_HW_FLOWCONTROL is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_MACE is not set
+# CONFIG_BMAC is not set
+# CONFIG_OAKNET is not set
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_NET_VENDOR_3COM is not set
+# CONFIG_LANCE is not set
+# CONFIG_NET_VENDOR_SMC is not set
+# CONFIG_NET_VENDOR_RACAL is not set
+
+#
+# Tulip family network device support
+#
+# CONFIG_NET_TULIP is not set
+# CONFIG_AT1700 is not set
+# CONFIG_DEPCA is not set
+# CONFIG_HP100 is not set
+# CONFIG_NET_ISA is not set
+CONFIG_NET_PCI=y
+CONFIG_PCNET32=y
+# CONFIG_AMD8111_ETH is not set
+# CONFIG_ADAPTEC_STARFIRE is not set
+# CONFIG_AC3200 is not set
+# CONFIG_APRICOT is not set
+# CONFIG_B44 is not set
+# CONFIG_FORCEDETH is not set
+# CONFIG_CS89x0 is not set
+# CONFIG_DGRS is not set
+# CONFIG_EEPRO100 is not set
+CONFIG_E100=y
+# CONFIG_E100_NAPI is not set
+# CONFIG_FEALNX is not set
+# CONFIG_NATSEMI is not set
+# CONFIG_NE2K_PCI is not set
+# CONFIG_8139CP is not set
+# CONFIG_8139TOO is not set
+# CONFIG_SIS900 is not set
+# CONFIG_EPIC100 is not set
+# CONFIG_SUNDANCE is not set
+# CONFIG_TLAN is not set
+# CONFIG_VIA_RHINE is not set
+# CONFIG_NET_POCKET is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+CONFIG_E1000=y
+# CONFIG_E1000_NAPI is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_TIGON3 is not set
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_IXGB is not set
+# CONFIG_S2IO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_PLIP is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_NET_FC is not set
+# CONFIG_RCPCI is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input I/O drivers
+#
+CONFIG_GAMEPORT=m
+CONFIG_SOUND_GAMEPORT=m
+# CONFIG_GAMEPORT_NS558 is not set
+# CONFIG_GAMEPORT_L4 is not set
+# CONFIG_GAMEPORT_EMU10K1 is not set
+# CONFIG_GAMEPORT_VORTEX is not set
+# CONFIG_GAMEPORT_FM801 is not set
+# CONFIG_GAMEPORT_CS461x is not set
+CONFIG_SERIO=y
+CONFIG_SERIO_I8042=y
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_CT82C710 is not set
+# CONFIG_SERIO_PARKBD is not set
+# CONFIG_SERIO_PCIPS2 is not set
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+CONFIG_KEYBOARD_ATKBD=y
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+CONFIG_INPUT_MOUSE=y
+CONFIG_MOUSE_PS2=y
+# CONFIG_MOUSE_SERIAL is not set
+# CONFIG_MOUSE_INPORT is not set
+# CONFIG_MOUSE_LOGIBM is not set
+# CONFIG_MOUSE_PC110PAD is not set
+# CONFIG_MOUSE_VSXXXAA is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+CONFIG_INPUT_MISC=y
+CONFIG_INPUT_UINPUT=y
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=4
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_PMACZILOG is not set
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+CONFIG_PRINTER=m
+# CONFIG_LP_CONSOLE is not set
+# CONFIG_PPDEV is not set
+# CONFIG_TIPAR is not set
+# CONFIG_QIC02_TAPE is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+CONFIG_NVRAM=y
+CONFIG_GEN_RTC=y
+# CONFIG_GEN_RTC_X is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# I2C support
+#
+CONFIG_I2C=y
+CONFIG_I2C_CHARDEV=y
+
+#
+# I2C Algorithms
+#
+CONFIG_I2C_ALGOBIT=y
+CONFIG_I2C_ALGOPCF=y
+
+#
+# I2C Hardware Bus support
+#
+# CONFIG_I2C_ALI1535 is not set
+# CONFIG_I2C_ALI1563 is not set
+# CONFIG_I2C_ALI15X3 is not set
+# CONFIG_I2C_AMD756 is not set
+# CONFIG_I2C_AMD8111 is not set
+# CONFIG_I2C_HYDRA is not set
+# CONFIG_I2C_I801 is not set
+# CONFIG_I2C_I810 is not set
+# CONFIG_I2C_ISA is not set
+# CONFIG_I2C_KEYWEST is not set
+# CONFIG_I2C_NFORCE2 is not set
+# CONFIG_I2C_PARPORT is not set
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_PIIX4 is not set
+# CONFIG_I2C_PROSAVAGE is not set
+# CONFIG_I2C_SAVAGE4 is not set
+# CONFIG_SCx200_ACB is not set
+# CONFIG_I2C_SIS5595 is not set
+# CONFIG_I2C_SIS630 is not set
+# CONFIG_I2C_SIS96X is not set
+# CONFIG_I2C_VIA is not set
+# CONFIG_I2C_VIAPRO is not set
+# CONFIG_I2C_VOODOO3 is not set
+
+#
+# Hardware Sensors Chip support
+#
+# CONFIG_I2C_SENSOR is not set
+# CONFIG_SENSORS_ADM1021 is not set
+# CONFIG_SENSORS_ASB100 is not set
+# CONFIG_SENSORS_DS1621 is not set
+# CONFIG_SENSORS_FSCHER is not set
+# CONFIG_SENSORS_GL518SM is not set
+# CONFIG_SENSORS_IT87 is not set
+# CONFIG_SENSORS_LM75 is not set
+# CONFIG_SENSORS_LM78 is not set
+# CONFIG_SENSORS_LM80 is not set
+# CONFIG_SENSORS_LM83 is not set
+# CONFIG_SENSORS_LM85 is not set
+# CONFIG_SENSORS_LM90 is not set
+# CONFIG_SENSORS_VIA686A is not set
+# CONFIG_SENSORS_W83781D is not set
+# CONFIG_SENSORS_W83L785TS is not set
+# CONFIG_SENSORS_W83627HF is not set
+
+#
+# Other I2C Chip support
+#
+# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+
+#
+# Misc devices
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+CONFIG_FB=y
+# CONFIG_FB_PM2 is not set
+# CONFIG_FB_CYBER2000 is not set
+CONFIG_FB_OF=y
+# CONFIG_FB_CONTROL is not set
+# CONFIG_FB_PLATINUM is not set
+# CONFIG_FB_VALKYRIE is not set
+# CONFIG_FB_CT65550 is not set
+# CONFIG_FB_IMSTT is not set
+# CONFIG_FB_S3TRIO is not set
+# CONFIG_FB_VGA16 is not set
+# CONFIG_FB_RIVA is not set
+CONFIG_FB_MATROX=y
+CONFIG_FB_MATROX_MILLENIUM=y
+CONFIG_FB_MATROX_MYSTIQUE=y
+# CONFIG_FB_MATROX_G450 is not set
+CONFIG_FB_MATROX_G100A=y
+CONFIG_FB_MATROX_G100=y
+CONFIG_FB_MATROX_I2C=y
+# CONFIG_FB_MATROX_MAVEN is not set
+CONFIG_FB_MATROX_MULTIHEAD=y
+# CONFIG_FB_RADEON_OLD is not set
+# CONFIG_FB_RADEON is not set
+# CONFIG_FB_ATY128 is not set
+# CONFIG_FB_ATY is not set
+# CONFIG_FB_SIS is not set
+# CONFIG_FB_NEOMAGIC is not set
+# CONFIG_FB_KYRO is not set
+# CONFIG_FB_3DFX is not set
+# CONFIG_FB_VOODOO1 is not set
+# CONFIG_FB_TRIDENT is not set
+# CONFIG_FB_VIRTUAL is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+# CONFIG_MDA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_PCI_CONSOLE=y
+# CONFIG_FONTS is not set
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
+
+#
+# Logo configuration
+#
+CONFIG_LOGO=y
+CONFIG_LOGO_LINUX_MONO=y
+CONFIG_LOGO_LINUX_VGA16=y
+CONFIG_LOGO_LINUX_CLUT224=y
+
+#
+# Sound
+#
+CONFIG_SOUND=y
+# CONFIG_DMASOUND_PMAC is not set
+
+#
+# Advanced Linux Sound Architecture
+#
+CONFIG_SND=m
+CONFIG_SND_TIMER=m
+CONFIG_SND_PCM=m
+CONFIG_SND_HWDEP=m
+CONFIG_SND_RAWMIDI=m
+CONFIG_SND_SEQUENCER=m
+CONFIG_SND_SEQ_DUMMY=m
+CONFIG_SND_OSSEMUL=y
+CONFIG_SND_MIXER_OSS=m
+CONFIG_SND_PCM_OSS=m
+CONFIG_SND_SEQUENCER_OSS=y
+# CONFIG_SND_VERBOSE_PRINTK is not set
+# CONFIG_SND_DEBUG is not set
+
+#
+# Generic devices
+#
+CONFIG_SND_MPU401_UART=m
+CONFIG_SND_OPL3_LIB=m
+CONFIG_SND_DUMMY=m
+# CONFIG_SND_VIRMIDI is not set
+# CONFIG_SND_MTPAV is not set
+# CONFIG_SND_SERIAL_U16550 is not set
+# CONFIG_SND_MPU401 is not set
+
+#
+# ISA devices
+#
+# CONFIG_SND_AD1848 is not set
+# CONFIG_SND_CS4231 is not set
+CONFIG_SND_CS4232=m
+# CONFIG_SND_CS4236 is not set
+# CONFIG_SND_ES1688 is not set
+# CONFIG_SND_ES18XX is not set
+# CONFIG_SND_GUSCLASSIC is not set
+# CONFIG_SND_GUSEXTREME is not set
+# CONFIG_SND_GUSMAX is not set
+# CONFIG_SND_INTERWAVE is not set
+# CONFIG_SND_INTERWAVE_STB is not set
+# CONFIG_SND_OPTI92X_AD1848 is not set
+# CONFIG_SND_OPTI92X_CS4231 is not set
+# CONFIG_SND_OPTI93X is not set
+# CONFIG_SND_SB8 is not set
+# CONFIG_SND_SB16 is not set
+# CONFIG_SND_SBAWE is not set
+# CONFIG_SND_WAVEFRONT is not set
+# CONFIG_SND_CMI8330 is not set
+# CONFIG_SND_OPL3SA2 is not set
+# CONFIG_SND_SGALAXY is not set
+# CONFIG_SND_SSCAPE is not set
+
+#
+# PCI devices
+#
+CONFIG_SND_AC97_CODEC=m
+# CONFIG_SND_ALI5451 is not set
+# CONFIG_SND_ATIIXP is not set
+# CONFIG_SND_AU8810 is not set
+# CONFIG_SND_AU8820 is not set
+# CONFIG_SND_AU8830 is not set
+# CONFIG_SND_AZT3328 is not set
+# CONFIG_SND_BT87X is not set
+CONFIG_SND_CS46XX=m
+# CONFIG_SND_CS46XX_NEW_DSP is not set
+CONFIG_SND_CS4281=m
+# CONFIG_SND_EMU10K1 is not set
+# CONFIG_SND_KORG1212 is not set
+# CONFIG_SND_MIXART is not set
+# CONFIG_SND_NM256 is not set
+# CONFIG_SND_RME32 is not set
+# CONFIG_SND_RME96 is not set
+# CONFIG_SND_RME9652 is not set
+# CONFIG_SND_HDSP is not set
+# CONFIG_SND_TRIDENT is not set
+# CONFIG_SND_YMFPCI is not set
+# CONFIG_SND_ALS4000 is not set
+# CONFIG_SND_CMIPCI is not set
+# CONFIG_SND_ENS1370 is not set
+# CONFIG_SND_ENS1371 is not set
+# CONFIG_SND_ES1938 is not set
+# CONFIG_SND_ES1968 is not set
+# CONFIG_SND_MAESTRO3 is not set
+# CONFIG_SND_FM801 is not set
+# CONFIG_SND_ICE1712 is not set
+# CONFIG_SND_ICE1724 is not set
+# CONFIG_SND_INTEL8X0 is not set
+# CONFIG_SND_INTEL8X0M is not set
+# CONFIG_SND_SONICVIBES is not set
+# CONFIG_SND_VIA82XX is not set
+# CONFIG_SND_VX222 is not set
+
+#
+# ALSA PowerMac devices
+#
+# CONFIG_SND_POWERMAC is not set
+
+#
+# Open Sound System
+#
+# CONFIG_SOUND_PRIME is not set
+
+#
+# USB support
+#
+# CONFIG_USB is not set
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_JBD is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+CONFIG_ISO9660_FS=y
+CONFIG_JOLIET=y
+# CONFIG_ZISOFS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_SYSFS=y
+# CONFIG_DEVFS_FS is not set
+# CONFIG_DEVPTS_FS_XATTR is not set
+CONFIG_TMPFS=y
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+# CONFIG_NFS_V3 is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+CONFIG_NFSD=y
+# CONFIG_NFSD_V3 is not set
+# CONFIG_NFSD_TCP is not set
+CONFIG_LOCKD=y
+CONFIG_EXPORTFS=y
+CONFIG_SUNRPC=y
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+CONFIG_NLS_CODEPAGE_437=y
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+CONFIG_NLS_ISO8859_1=y
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_UTF8 is not set
+
+#
+# Library routines
+#
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=m
+CONFIG_ZLIB_DEFLATE=m
+
+#
+# Kernel hacking
+#
+# CONFIG_DEBUG_KERNEL is not set
+CONFIG_BOOTX_TEXT=y
+
+#
+# Security options
+#
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+CONFIG_CRYPTO=y
+CONFIG_CRYPTO_HMAC=y
+CONFIG_CRYPTO_NULL=y
+CONFIG_CRYPTO_MD4=m
+CONFIG_CRYPTO_MD5=m
+CONFIG_CRYPTO_SHA1=m
+CONFIG_CRYPTO_SHA256=m
+CONFIG_CRYPTO_SHA512=m
+CONFIG_CRYPTO_DES=m
+CONFIG_CRYPTO_BLOWFISH=m
+CONFIG_CRYPTO_TWOFISH=m
+# CONFIG_CRYPTO_SERPENT is not set
+CONFIG_CRYPTO_AES=m
+CONFIG_CRYPTO_CAST5=m
+CONFIG_CRYPTO_CAST6=m
+CONFIG_CRYPTO_ARC4=m
+CONFIG_CRYPTO_DEFLATE=m
+CONFIG_CRYPTO_MICHAEL_MIC=m
+# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_TEST is not set
diff --git a/arch/ppc/configs/pplus_defconfig b/arch/ppc/configs/pplus_defconfig
new file mode 100644
index 0000000..5e459bc
--- /dev/null
+++ b/arch/ppc/configs/pplus_defconfig
@@ -0,0 +1,720 @@
+#
+# Automatically generated make config: don't edit
+#
+CONFIG_MMU=y
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_HAVE_DEC_LOCK=y
+CONFIG_PPC=y
+CONFIG_PPC32=y
+CONFIG_GENERIC_NVRAM=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=y
+CONFIG_STANDALONE=y
+CONFIG_BROKEN_ON_SMP=y
+
+#
+# General setup
+#
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_HOTPLUG is not set
+# CONFIG_IKCONFIG is not set
+CONFIG_EMBEDDED=y
+CONFIG_KALLSYMS=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_OBSOLETE_MODPARM=y
+# CONFIG_MODVERSIONS is not set
+CONFIG_KMOD=y
+
+#
+# Processor
+#
+CONFIG_6xx=y
+# CONFIG_40x is not set
+# CONFIG_44x is not set
+# CONFIG_POWER3 is not set
+# CONFIG_POWER4 is not set
+# CONFIG_8xx is not set
+# CONFIG_ALTIVEC is not set
+# CONFIG_TAU is not set
+# CONFIG_CPU_FREQ is not set
+CONFIG_PPC_STD_MMU=y
+
+#
+# Platform options
+#
+# CONFIG_PPC_MULTIPLATFORM is not set
+# CONFIG_APUS is not set
+# CONFIG_WILLOW is not set
+# CONFIG_PCORE is not set
+# CONFIG_POWERPMC250 is not set
+# CONFIG_EV64260 is not set
+# CONFIG_SPRUCE is not set
+# CONFIG_LOPEC is not set
+# CONFIG_MCPN765 is not set
+# CONFIG_MVME5100 is not set
+CONFIG_PPLUS=y
+# CONFIG_PRPMC750 is not set
+# CONFIG_PRPMC800 is not set
+# CONFIG_SANDPOINT is not set
+# CONFIG_ADIR is not set
+# CONFIG_K2 is not set
+# CONFIG_PAL4 is not set
+# CONFIG_GEMINI is not set
+# CONFIG_EST8260 is not set
+# CONFIG_SBS8260 is not set
+# CONFIG_RPX6 is not set
+# CONFIG_TQM8260 is not set
+CONFIG_PPC_GEN550=y
+# CONFIG_PPCBUG_NVRAM is not set
+# CONFIG_SMP is not set
+# CONFIG_PREEMPT is not set
+# CONFIG_HIGHMEM is not set
+CONFIG_KERNEL_ELF=y
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+CONFIG_CMDLINE_BOOL=y
+CONFIG_CMDLINE="ip=on"
+
+#
+# Bus options
+#
+CONFIG_GENERIC_ISA_DMA=y
+CONFIG_PCI=y
+CONFIG_PCI_DOMAINS=y
+# CONFIG_PCI_LEGACY_PROC is not set
+# CONFIG_PCI_NAMES is not set
+
+#
+# Advanced setup
+#
+# CONFIG_ADVANCED_OPTIONS is not set
+
+#
+# Default settings for advanced configuration options are used
+#
+CONFIG_HIGHMEM_START=0xfe000000
+CONFIG_LOWMEM_SIZE=0x30000000
+CONFIG_KERNEL_START=0xc0000000
+CONFIG_TASK_SIZE=0x80000000
+CONFIG_BOOT_LOAD=0x00800000
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+CONFIG_BLK_DEV_FD=y
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_RAM is not set
+# CONFIG_BLK_DEV_INITRD is not set
+# CONFIG_LBD is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+CONFIG_IDE=y
+CONFIG_BLK_DEV_IDE=y
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+CONFIG_BLK_DEV_IDEDISK=y
+# CONFIG_IDEDISK_MULTI_MODE is not set
+# CONFIG_IDEDISK_STROKE is not set
+CONFIG_BLK_DEV_IDECD=y
+# CONFIG_BLK_DEV_IDETAPE is not set
+CONFIG_BLK_DEV_IDEFLOPPY=y
+CONFIG_BLK_DEV_IDESCSI=y
+# CONFIG_IDE_TASK_IOCTL is not set
+# CONFIG_IDE_TASKFILE_IO is not set
+
+#
+# IDE chipset support/bugfixes
+#
+CONFIG_IDE_GENERIC=y
+# CONFIG_BLK_DEV_IDEPCI is not set
+# CONFIG_BLK_DEV_IDEDMA is not set
+# CONFIG_IDEDMA_AUTO is not set
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# SCSI device support
+#
+CONFIG_SCSI=y
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+CONFIG_CHR_DEV_ST=y
+# CONFIG_CHR_DEV_OSST is not set
+CONFIG_BLK_DEV_SR=y
+CONFIG_BLK_DEV_SR_VENDOR=y
+CONFIG_CHR_DEV_SG=y
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+# CONFIG_SCSI_MULTI_LUN is not set
+# CONFIG_SCSI_REPORT_LUNS is not set
+CONFIG_SCSI_CONSTANTS=y
+# CONFIG_SCSI_LOGGING is not set
+
+#
+# SCSI low-level drivers
+#
+# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
+# CONFIG_SCSI_ACARD is not set
+# CONFIG_SCSI_AACRAID is not set
+# CONFIG_SCSI_AIC7XXX is not set
+# CONFIG_SCSI_AIC7XXX_OLD is not set
+# CONFIG_SCSI_AIC79XX is not set
+# CONFIG_SCSI_ADVANSYS is not set
+# CONFIG_SCSI_MEGARAID is not set
+# CONFIG_SCSI_SATA is not set
+# CONFIG_SCSI_BUSLOGIC is not set
+# CONFIG_SCSI_CPQFCTS is not set
+# CONFIG_SCSI_DMX3191D is not set
+# CONFIG_SCSI_EATA is not set
+# CONFIG_SCSI_EATA_PIO is not set
+# CONFIG_SCSI_FUTURE_DOMAIN is not set
+# CONFIG_SCSI_GDTH is not set
+# CONFIG_SCSI_IPS is not set
+# CONFIG_SCSI_INIA100 is not set
+# CONFIG_SCSI_SYM53C8XX_2 is not set
+# CONFIG_SCSI_QLOGIC_ISP is not set
+# CONFIG_SCSI_QLOGIC_FC is not set
+# CONFIG_SCSI_QLOGIC_1280 is not set
+CONFIG_SCSI_QLA2XXX=y
+# CONFIG_SCSI_QLA21XX is not set
+# CONFIG_SCSI_QLA22XX is not set
+# CONFIG_SCSI_QLA2300 is not set
+# CONFIG_SCSI_QLA2322 is not set
+# CONFIG_SCSI_QLA6312 is not set
+# CONFIG_SCSI_QLA6322 is not set
+# CONFIG_SCSI_DC395x is not set
+# CONFIG_SCSI_DC390T is not set
+# CONFIG_SCSI_NSP32 is not set
+# CONFIG_SCSI_DEBUG is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+# CONFIG_FUSION is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# Macintosh device drivers
+#
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+# CONFIG_NETLINK_DEV is not set
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+# CONFIG_IP_PNP_BOOTP is not set
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_IP_MROUTE is not set
+# CONFIG_ARPD is not set
+# CONFIG_INET_ECN is not set
+CONFIG_SYN_COOKIES=y
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+
+#
+# IP: Virtual Server Configuration
+#
+# CONFIG_IP_VS is not set
+# CONFIG_IPV6 is not set
+# CONFIG_DECNET is not set
+# CONFIG_BRIDGE is not set
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+
+#
+# IP: Netfilter Configuration
+#
+CONFIG_IP_NF_CONNTRACK=m
+CONFIG_IP_NF_FTP=m
+# CONFIG_IP_NF_IRC is not set
+# CONFIG_IP_NF_TFTP is not set
+# CONFIG_IP_NF_AMANDA is not set
+# CONFIG_IP_NF_QUEUE is not set
+CONFIG_IP_NF_IPTABLES=m
+CONFIG_IP_NF_MATCH_LIMIT=m
+# CONFIG_IP_NF_MATCH_IPRANGE is not set
+CONFIG_IP_NF_MATCH_MAC=m
+CONFIG_IP_NF_MATCH_PKTTYPE=m
+CONFIG_IP_NF_MATCH_MARK=m
+CONFIG_IP_NF_MATCH_MULTIPORT=m
+CONFIG_IP_NF_MATCH_TOS=m
+# CONFIG_IP_NF_MATCH_RECENT is not set
+CONFIG_IP_NF_MATCH_ECN=m
+CONFIG_IP_NF_MATCH_DSCP=m
+CONFIG_IP_NF_MATCH_AH_ESP=m
+# CONFIG_IP_NF_MATCH_LENGTH is not set
+# CONFIG_IP_NF_MATCH_TTL is not set
+# CONFIG_IP_NF_MATCH_TCPMSS is not set
+CONFIG_IP_NF_MATCH_HELPER=m
+CONFIG_IP_NF_MATCH_STATE=m
+CONFIG_IP_NF_MATCH_CONNTRACK=m
+CONFIG_IP_NF_MATCH_OWNER=m
+CONFIG_IP_NF_FILTER=m
+CONFIG_IP_NF_TARGET_REJECT=m
+CONFIG_IP_NF_NAT=m
+CONFIG_IP_NF_NAT_NEEDED=y
+CONFIG_IP_NF_TARGET_MASQUERADE=m
+CONFIG_IP_NF_TARGET_REDIRECT=m
+# CONFIG_IP_NF_TARGET_NETMAP is not set
+# CONFIG_IP_NF_TARGET_SAME is not set
+# CONFIG_IP_NF_NAT_SNMP_BASIC is not set
+CONFIG_IP_NF_NAT_FTP=m
+# CONFIG_IP_NF_MANGLE is not set
+# CONFIG_IP_NF_TARGET_LOG is not set
+CONFIG_IP_NF_TARGET_ULOG=m
+# CONFIG_IP_NF_TARGET_TCPMSS is not set
+CONFIG_IP_NF_ARPTABLES=m
+CONFIG_IP_NF_ARPFILTER=m
+# CONFIG_IP_NF_ARP_MANGLE is not set
+CONFIG_IP_NF_COMPAT_IPCHAINS=m
+# CONFIG_IP_NF_COMPAT_IPFWADM is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+CONFIG_IPV6_SCTP__=y
+# CONFIG_IP_SCTP is not set
+# CONFIG_ATM is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_HW_FLOWCONTROL is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+CONFIG_NETDEVICES=y
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+CONFIG_CRC32=y
+# CONFIG_OAKNET is not set
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_NET_VENDOR_3COM is not set
+
+#
+# Tulip family network device support
+#
+CONFIG_NET_TULIP=y
+# CONFIG_DE2104X is not set
+CONFIG_TULIP=y
+# CONFIG_TULIP_MWI is not set
+# CONFIG_TULIP_MMIO is not set
+# CONFIG_TULIP_NAPI is not set
+# CONFIG_DE4X5 is not set
+# CONFIG_WINBOND_840 is not set
+# CONFIG_DM9102 is not set
+# CONFIG_HP100 is not set
+CONFIG_NET_PCI=y
+# CONFIG_PCNET32 is not set
+# CONFIG_AMD8111_ETH is not set
+# CONFIG_ADAPTEC_STARFIRE is not set
+# CONFIG_B44 is not set
+# CONFIG_FORCEDETH is not set
+# CONFIG_DGRS is not set
+CONFIG_EEPRO100=y
+# CONFIG_EEPRO100_PIO is not set
+# CONFIG_E100 is not set
+# CONFIG_FEALNX is not set
+# CONFIG_NATSEMI is not set
+# CONFIG_NE2K_PCI is not set
+# CONFIG_8139CP is not set
+# CONFIG_8139TOO is not set
+# CONFIG_SIS900 is not set
+# CONFIG_EPIC100 is not set
+# CONFIG_SUNDANCE is not set
+# CONFIG_TLAN is not set
+# CONFIG_VIA_RHINE is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_E1000 is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
+# CONFIG_SIS190 is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_TIGON3 is not set
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_IXGB is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+# CONFIG_NET_FC is not set
+# CONFIG_RCPCI is not set
+# CONFIG_SHAPER is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+
+#
+# Amateur Radio support
+#
+# CONFIG_HAMRADIO is not set
+
+#
+# IrDA (infrared) support
+#
+# CONFIG_IRDA is not set
+
+#
+# Bluetooth support
+#
+# CONFIG_BT is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+# CONFIG_INPUT is not set
+
+#
+# Userland interfaces
+#
+
+#
+# Input I/O drivers
+#
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+# CONFIG_SERIO is not set
+# CONFIG_SERIO_I8042 is not set
+
+#
+# Input Device Drivers
+#
+
+#
+# Character devices
+#
+# CONFIG_VT is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=4
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+
+#
+# Mice
+#
+# CONFIG_BUSMOUSE is not set
+# CONFIG_QIC02_TAPE is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_NVRAM is not set
+CONFIG_GEN_RTC=y
+# CONFIG_GEN_RTC_X is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_FTAPE is not set
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+# CONFIG_FB is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+# CONFIG_USB is not set
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_JBD is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+CONFIG_ISO9660_FS=y
+# CONFIG_JOLIET is not set
+# CONFIG_ZISOFS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_FAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+# CONFIG_DEVFS_FS is not set
+# CONFIG_DEVPTS_FS_XATTR is not set
+# CONFIG_TMPFS is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+# CONFIG_NFS_V3 is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+# CONFIG_NFSD is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+# CONFIG_EXPORTFS is not set
+CONFIG_SUNRPC=y
+# CONFIG_SUNRPC_GSS is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+# CONFIG_NLS is not set
+
+#
+# Library routines
+#
+
+#
+# Kernel hacking
+#
+# CONFIG_DEBUG_KERNEL is not set
+# CONFIG_SERIAL_TEXT_DEBUG is not set
+
+#
+# Security options
+#
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
diff --git a/arch/ppc/configs/prpmc750_defconfig b/arch/ppc/configs/prpmc750_defconfig
new file mode 100644
index 0000000..82d52f6
--- /dev/null
+++ b/arch/ppc/configs/prpmc750_defconfig
@@ -0,0 +1,594 @@
+#
+# Automatically generated make config: don't edit
+#
+CONFIG_MMU=y
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_HAVE_DEC_LOCK=y
+CONFIG_PPC=y
+CONFIG_PPC32=y
+CONFIG_GENERIC_NVRAM=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=y
+CONFIG_STANDALONE=y
+CONFIG_BROKEN_ON_SMP=y
+
+#
+# General setup
+#
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_HOTPLUG is not set
+# CONFIG_IKCONFIG is not set
+CONFIG_EMBEDDED=y
+# CONFIG_KALLSYMS is not set
+CONFIG_FUTEX=y
+# CONFIG_EPOLL is not set
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_OBSOLETE_MODPARM=y
+# CONFIG_MODVERSIONS is not set
+CONFIG_KMOD=y
+
+#
+# Processor
+#
+CONFIG_6xx=y
+# CONFIG_40x is not set
+# CONFIG_44x is not set
+# CONFIG_POWER3 is not set
+# CONFIG_POWER4 is not set
+# CONFIG_8xx is not set
+# CONFIG_ALTIVEC is not set
+# CONFIG_TAU is not set
+# CONFIG_CPU_FREQ is not set
+CONFIG_PPC_STD_MMU=y
+
+#
+# Platform options
+#
+# CONFIG_PPC_MULTIPLATFORM is not set
+# CONFIG_APUS is not set
+# CONFIG_WILLOW is not set
+# CONFIG_PCORE is not set
+# CONFIG_POWERPMC250 is not set
+# CONFIG_EV64260 is not set
+# CONFIG_SPRUCE is not set
+# CONFIG_LOPEC is not set
+# CONFIG_MCPN765 is not set
+# CONFIG_MVME5100 is not set
+# CONFIG_PPLUS is not set
+CONFIG_PRPMC750=y
+# CONFIG_PRPMC800 is not set
+# CONFIG_SANDPOINT is not set
+# CONFIG_ADIR is not set
+# CONFIG_K2 is not set
+# CONFIG_PAL4 is not set
+# CONFIG_GEMINI is not set
+# CONFIG_EST8260 is not set
+# CONFIG_SBS8260 is not set
+# CONFIG_RPX6 is not set
+# CONFIG_TQM8260 is not set
+CONFIG_PPC_GEN550=y
+# CONFIG_SMP is not set
+# CONFIG_PREEMPT is not set
+# CONFIG_HIGHMEM is not set
+CONFIG_KERNEL_ELF=y
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+CONFIG_CMDLINE_BOOL=y
+CONFIG_CMDLINE="ip=on"
+
+#
+# Bus options
+#
+CONFIG_GENERIC_ISA_DMA=y
+CONFIG_PCI=y
+CONFIG_PCI_DOMAINS=y
+# CONFIG_PCI_LEGACY_PROC is not set
+# CONFIG_PCI_NAMES is not set
+
+#
+# Advanced setup
+#
+# CONFIG_ADVANCED_OPTIONS is not set
+
+#
+# Default settings for advanced configuration options are used
+#
+CONFIG_HIGHMEM_START=0xfe000000
+CONFIG_LOWMEM_SIZE=0x30000000
+CONFIG_KERNEL_START=0xc0000000
+CONFIG_TASK_SIZE=0x80000000
+CONFIG_BOOT_LOAD=0x00800000
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_CARMEL is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=4096
+CONFIG_BLK_DEV_INITRD=y
+# CONFIG_LBD is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_SCSI is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+# CONFIG_FUSION is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# Macintosh device drivers
+#
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+# CONFIG_NETLINK_DEV is not set
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+# CONFIG_IP_PNP_BOOTP is not set
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_IP_MROUTE is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_IPV6 is not set
+# CONFIG_NETFILTER is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_HW_FLOWCONTROL is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_OAKNET is not set
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_NET_VENDOR_3COM is not set
+
+#
+# Tulip family network device support
+#
+CONFIG_NET_TULIP=y
+# CONFIG_DE2104X is not set
+CONFIG_TULIP=y
+# CONFIG_TULIP_MWI is not set
+CONFIG_TULIP_MMIO=y
+# CONFIG_TULIP_NAPI is not set
+# CONFIG_DE4X5 is not set
+# CONFIG_WINBOND_840 is not set
+# CONFIG_DM9102 is not set
+# CONFIG_HP100 is not set
+CONFIG_NET_PCI=y
+# CONFIG_PCNET32 is not set
+# CONFIG_AMD8111_ETH is not set
+# CONFIG_ADAPTEC_STARFIRE is not set
+# CONFIG_B44 is not set
+# CONFIG_FORCEDETH is not set
+# CONFIG_DGRS is not set
+CONFIG_EEPRO100=y
+# CONFIG_EEPRO100_PIO is not set
+# CONFIG_E100 is not set
+# CONFIG_FEALNX is not set
+# CONFIG_NATSEMI is not set
+# CONFIG_NE2K_PCI is not set
+# CONFIG_8139CP is not set
+# CONFIG_8139TOO is not set
+# CONFIG_SIS900 is not set
+# CONFIG_EPIC100 is not set
+# CONFIG_SUNDANCE is not set
+# CONFIG_TLAN is not set
+# CONFIG_VIA_RHINE is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_E1000 is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_TIGON3 is not set
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_IXGB is not set
+# CONFIG_S2IO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_RCPCI is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input I/O drivers
+#
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+# CONFIG_SERIO is not set
+# CONFIG_SERIO_I8042 is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Character devices
+#
+# CONFIG_VT is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=4
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_QIC02_TAPE is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_NVRAM is not set
+CONFIG_GEN_RTC=y
+# CONFIG_GEN_RTC_X is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_FTAPE is not set
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# Misc devices
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+# CONFIG_FB is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+# CONFIG_USB is not set
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_FS_XATTR=y
+# CONFIG_EXT3_FS_POSIX_ACL is not set
+# CONFIG_EXT3_FS_SECURITY is not set
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+CONFIG_FS_MBCACHE=y
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_FAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_SYSFS=y
+# CONFIG_DEVFS_FS is not set
+# CONFIG_DEVPTS_FS_XATTR is not set
+CONFIG_TMPFS=y
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+# CONFIG_NFS_V3 is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+# CONFIG_NFSD is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+# CONFIG_EXPORTFS is not set
+CONFIG_SUNRPC=y
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_INTERMEZZO_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+# CONFIG_NLS is not set
+
+#
+# Library routines
+#
+CONFIG_CRC32=y
+
+#
+# Kernel hacking
+#
+# CONFIG_DEBUG_KERNEL is not set
+# CONFIG_SERIAL_TEXT_DEBUG is not set
+
+#
+# Security options
+#
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
diff --git a/arch/ppc/configs/prpmc800_defconfig b/arch/ppc/configs/prpmc800_defconfig
new file mode 100644
index 0000000..613c266
--- /dev/null
+++ b/arch/ppc/configs/prpmc800_defconfig
@@ -0,0 +1,656 @@
+#
+# Automatically generated make config: don't edit
+#
+CONFIG_MMU=y
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_HAVE_DEC_LOCK=y
+CONFIG_PPC=y
+CONFIG_PPC32=y
+CONFIG_GENERIC_NVRAM=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=y
+CONFIG_STANDALONE=y
+CONFIG_BROKEN_ON_SMP=y
+
+#
+# General setup
+#
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_HOTPLUG is not set
+# CONFIG_IKCONFIG is not set
+CONFIG_EMBEDDED=y
+# CONFIG_KALLSYMS is not set
+CONFIG_FUTEX=y
+# CONFIG_EPOLL is not set
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_OBSOLETE_MODPARM=y
+# CONFIG_MODVERSIONS is not set
+CONFIG_KMOD=y
+
+#
+# Processor
+#
+CONFIG_6xx=y
+# CONFIG_40x is not set
+# CONFIG_44x is not set
+# CONFIG_POWER3 is not set
+# CONFIG_POWER4 is not set
+# CONFIG_8xx is not set
+CONFIG_ALTIVEC=y
+# CONFIG_TAU is not set
+# CONFIG_CPU_FREQ is not set
+CONFIG_PPC_STD_MMU=y
+
+#
+# Platform options
+#
+# CONFIG_PPC_MULTIPLATFORM is not set
+# CONFIG_APUS is not set
+# CONFIG_WILLOW is not set
+# CONFIG_PCORE is not set
+# CONFIG_POWERPMC250 is not set
+# CONFIG_EV64260 is not set
+# CONFIG_SPRUCE is not set
+# CONFIG_LOPEC is not set
+# CONFIG_MCPN765 is not set
+# CONFIG_MVME5100 is not set
+# CONFIG_PPLUS is not set
+# CONFIG_PRPMC750 is not set
+CONFIG_PRPMC800=y
+# CONFIG_SANDPOINT is not set
+# CONFIG_ADIR is not set
+# CONFIG_K2 is not set
+# CONFIG_PAL4 is not set
+# CONFIG_GEMINI is not set
+# CONFIG_EST8260 is not set
+# CONFIG_SBS8260 is not set
+# CONFIG_RPX6 is not set
+# CONFIG_TQM8260 is not set
+CONFIG_PPC_GEN550=y
+# CONFIG_NONMONARCH_SUPPORT is not set
+CONFIG_HARRIER=y
+# CONFIG_HARRIER_STORE_GATHERING is not set
+# CONFIG_SMP is not set
+# CONFIG_PREEMPT is not set
+# CONFIG_HIGHMEM is not set
+CONFIG_KERNEL_ELF=y
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+CONFIG_CMDLINE_BOOL=y
+CONFIG_CMDLINE="ip=on"
+
+#
+# Bus options
+#
+CONFIG_GENERIC_ISA_DMA=y
+CONFIG_PCI=y
+CONFIG_PCI_DOMAINS=y
+# CONFIG_PCI_LEGACY_PROC is not set
+# CONFIG_PCI_NAMES is not set
+
+#
+# Advanced setup
+#
+# CONFIG_ADVANCED_OPTIONS is not set
+
+#
+# Default settings for advanced configuration options are used
+#
+CONFIG_HIGHMEM_START=0xfe000000
+CONFIG_LOWMEM_SIZE=0x30000000
+CONFIG_KERNEL_START=0xc0000000
+CONFIG_TASK_SIZE=0x80000000
+CONFIG_BOOT_LOAD=0x00800000
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_CARMEL is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=4096
+CONFIG_BLK_DEV_INITRD=y
+# CONFIG_LBD is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+CONFIG_SCSI=y
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+CONFIG_CHR_DEV_ST=y
+# CONFIG_CHR_DEV_OSST is not set
+CONFIG_BLK_DEV_SR=y
+# CONFIG_BLK_DEV_SR_VENDOR is not set
+# CONFIG_CHR_DEV_SG is not set
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+# CONFIG_SCSI_MULTI_LUN is not set
+# CONFIG_SCSI_REPORT_LUNS is not set
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+
+#
+# SCSI Transport Attributes
+#
+CONFIG_SCSI_SPI_ATTRS=y
+# CONFIG_SCSI_FC_ATTRS is not set
+
+#
+# SCSI low-level drivers
+#
+# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
+# CONFIG_SCSI_ACARD is not set
+# CONFIG_SCSI_AACRAID is not set
+# CONFIG_SCSI_AIC7XXX is not set
+# CONFIG_SCSI_AIC7XXX_OLD is not set
+# CONFIG_SCSI_AIC79XX is not set
+# CONFIG_SCSI_ADVANSYS is not set
+# CONFIG_SCSI_MEGARAID is not set
+# CONFIG_SCSI_SATA is not set
+# CONFIG_SCSI_BUSLOGIC is not set
+# CONFIG_SCSI_CPQFCTS is not set
+# CONFIG_SCSI_DMX3191D is not set
+# CONFIG_SCSI_EATA is not set
+# CONFIG_SCSI_EATA_PIO is not set
+# CONFIG_SCSI_FUTURE_DOMAIN is not set
+# CONFIG_SCSI_GDTH is not set
+# CONFIG_SCSI_IPS is not set
+# CONFIG_SCSI_INIA100 is not set
+CONFIG_SCSI_SYM53C8XX_2=y
+CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=1
+CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16
+CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64
+# CONFIG_SCSI_SYM53C8XX_IOMAPPED is not set
+# CONFIG_SCSI_QLOGIC_ISP is not set
+# CONFIG_SCSI_QLOGIC_FC is not set
+# CONFIG_SCSI_QLOGIC_1280 is not set
+CONFIG_SCSI_QLA2XXX=y
+# CONFIG_SCSI_QLA21XX is not set
+# CONFIG_SCSI_QLA22XX is not set
+# CONFIG_SCSI_QLA2300 is not set
+# CONFIG_SCSI_QLA2322 is not set
+# CONFIG_SCSI_QLA6312 is not set
+# CONFIG_SCSI_QLA6322 is not set
+# CONFIG_SCSI_DC395x is not set
+# CONFIG_SCSI_DC390T is not set
+# CONFIG_SCSI_NSP32 is not set
+# CONFIG_SCSI_DEBUG is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+# CONFIG_FUSION is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# Macintosh device drivers
+#
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+# CONFIG_NETLINK_DEV is not set
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+# CONFIG_IP_PNP_BOOTP is not set
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_IP_MROUTE is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_IPV6 is not set
+# CONFIG_NETFILTER is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_HW_FLOWCONTROL is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_OAKNET is not set
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_NET_VENDOR_3COM is not set
+
+#
+# Tulip family network device support
+#
+# CONFIG_NET_TULIP is not set
+# CONFIG_HP100 is not set
+CONFIG_NET_PCI=y
+# CONFIG_PCNET32 is not set
+# CONFIG_AMD8111_ETH is not set
+# CONFIG_ADAPTEC_STARFIRE is not set
+# CONFIG_B44 is not set
+# CONFIG_FORCEDETH is not set
+# CONFIG_DGRS is not set
+CONFIG_EEPRO100=y
+# CONFIG_EEPRO100_PIO is not set
+# CONFIG_E100 is not set
+# CONFIG_FEALNX is not set
+# CONFIG_NATSEMI is not set
+# CONFIG_NE2K_PCI is not set
+# CONFIG_8139CP is not set
+# CONFIG_8139TOO is not set
+# CONFIG_SIS900 is not set
+# CONFIG_EPIC100 is not set
+# CONFIG_SUNDANCE is not set
+# CONFIG_TLAN is not set
+# CONFIG_VIA_RHINE is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_E1000 is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_TIGON3 is not set
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_IXGB is not set
+# CONFIG_S2IO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_NET_FC is not set
+# CONFIG_RCPCI is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input I/O drivers
+#
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+# CONFIG_SERIO is not set
+# CONFIG_SERIO_I8042 is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Character devices
+#
+# CONFIG_VT is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=4
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_QIC02_TAPE is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_NVRAM is not set
+CONFIG_GEN_RTC=y
+# CONFIG_GEN_RTC_X is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_FTAPE is not set
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# Misc devices
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+# CONFIG_FB is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+# CONFIG_USB is not set
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_FS_XATTR=y
+# CONFIG_EXT3_FS_POSIX_ACL is not set
+# CONFIG_EXT3_FS_SECURITY is not set
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+CONFIG_FS_MBCACHE=y
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_FAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_SYSFS=y
+# CONFIG_DEVFS_FS is not set
+# CONFIG_DEVPTS_FS_XATTR is not set
+CONFIG_TMPFS=y
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+# CONFIG_NFS_V3 is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+# CONFIG_NFSD is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+# CONFIG_EXPORTFS is not set
+CONFIG_SUNRPC=y
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_INTERMEZZO_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+# CONFIG_NLS is not set
+
+#
+# Library routines
+#
+# CONFIG_CRC32 is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_DEBUG_KERNEL is not set
+# CONFIG_SERIAL_TEXT_DEBUG is not set
+
+#
+# Security options
+#
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
diff --git a/arch/ppc/configs/radstone_ppc7d_defconfig b/arch/ppc/configs/radstone_ppc7d_defconfig
new file mode 100644
index 0000000..7f6467e
--- /dev/null
+++ b/arch/ppc/configs/radstone_ppc7d_defconfig
@@ -0,0 +1,956 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.11
+# Tue Mar 15 14:31:19 2005
+#
+CONFIG_MMU=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_HAVE_DEC_LOCK=y
+CONFIG_PPC=y
+CONFIG_PPC32=y
+CONFIG_GENERIC_NVRAM=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=y
+CONFIG_BROKEN_ON_SMP=y
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+# CONFIG_HOTPLUG is not set
+CONFIG_KOBJECT_UEVENT=y
+# CONFIG_IKCONFIG is not set
+CONFIG_EMBEDDED=y
+CONFIG_KALLSYMS=y
+CONFIG_KALLSYMS_EXTRA_PASS=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SHMEM=y
+CONFIG_CC_ALIGN_FUNCTIONS=0
+CONFIG_CC_ALIGN_LABELS=0
+CONFIG_CC_ALIGN_LOOPS=0
+CONFIG_CC_ALIGN_JUMPS=0
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_OBSOLETE_MODPARM=y
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_KMOD=y
+
+#
+# Processor
+#
+CONFIG_6xx=y
+# CONFIG_40x is not set
+# CONFIG_44x is not set
+# CONFIG_POWER3 is not set
+# CONFIG_POWER4 is not set
+# CONFIG_8xx is not set
+# CONFIG_E500 is not set
+CONFIG_ALTIVEC=y
+# CONFIG_TAU is not set
+# CONFIG_CPU_FREQ is not set
+CONFIG_PPC_GEN550=y
+# CONFIG_PM is not set
+CONFIG_PPC_STD_MMU=y
+# CONFIG_NOT_COHERENT_CACHE is not set
+
+#
+# Platform options
+#
+# CONFIG_PPC_MULTIPLATFORM is not set
+# CONFIG_APUS is not set
+# CONFIG_KATANA is not set
+# CONFIG_WILLOW is not set
+# CONFIG_CPCI690 is not set
+# CONFIG_PCORE is not set
+# CONFIG_POWERPMC250 is not set
+# CONFIG_CHESTNUT is not set
+# CONFIG_SPRUCE is not set
+# CONFIG_EV64260 is not set
+# CONFIG_LOPEC is not set
+# CONFIG_MCPN765 is not set
+# CONFIG_MVME5100 is not set
+# CONFIG_PPLUS is not set
+# CONFIG_PRPMC750 is not set
+# CONFIG_PRPMC800 is not set
+# CONFIG_SANDPOINT is not set
+CONFIG_RADSTONE_PPC7D=y
+# CONFIG_ADIR is not set
+# CONFIG_K2 is not set
+# CONFIG_PAL4 is not set
+# CONFIG_GEMINI is not set
+# CONFIG_EST8260 is not set
+# CONFIG_SBC82xx is not set
+# CONFIG_SBS8260 is not set
+# CONFIG_RPX8260 is not set
+# CONFIG_TQM8260 is not set
+# CONFIG_ADS8272 is not set
+# CONFIG_PQ2FADS is not set
+# CONFIG_LITE5200 is not set
+# CONFIG_MPC834x_SYS is not set
+CONFIG_MV64360=y
+CONFIG_MV64X60=y
+
+#
+# Set bridge options
+#
+CONFIG_MV64X60_BASE=0xfef00000
+CONFIG_MV64X60_NEW_BASE=0xfef00000
+# CONFIG_SMP is not set
+# CONFIG_PREEMPT is not set
+# CONFIG_HIGHMEM is not set
+CONFIG_BINFMT_ELF=y
+CONFIG_BINFMT_MISC=y
+CONFIG_CMDLINE_BOOL=y
+CONFIG_CMDLINE="console=ttyS0,9600"
+
+#
+# Bus options
+#
+CONFIG_GENERIC_ISA_DMA=y
+CONFIG_PCI=y
+CONFIG_PCI_DOMAINS=y
+CONFIG_PCI_LEGACY_PROC=y
+CONFIG_PCI_NAMES=y
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# Advanced setup
+#
+CONFIG_ADVANCED_OPTIONS=y
+CONFIG_HIGHMEM_START=0xfe000000
+# CONFIG_LOWMEM_SIZE_BOOL is not set
+CONFIG_LOWMEM_SIZE=0x30000000
+# CONFIG_KERNEL_START_BOOL is not set
+CONFIG_KERNEL_START=0xc0000000
+# CONFIG_TASK_SIZE_BOOL is not set
+CONFIG_TASK_SIZE=0x80000000
+# CONFIG_BOOT_LOAD_BOOL is not set
+CONFIG_BOOT_LOAD=0x00800000
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+# CONFIG_MTD_CONCAT is not set
+# CONFIG_MTD_PARTITIONS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLOCK=y
+CONFIG_FTL=y
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=y
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_GEN_PROBE=y
+CONFIG_MTD_CFI_ADV_OPTIONS=y
+CONFIG_MTD_CFI_NOSWAP=y
+# CONFIG_MTD_CFI_BE_BYTE_SWAP is not set
+# CONFIG_MTD_CFI_LE_BYTE_SWAP is not set
+# CONFIG_MTD_CFI_GEOMETRY is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+CONFIG_MTD_CFI_INTELEXT=y
+# CONFIG_MTD_CFI_AMDSTD is not set
+# CONFIG_MTD_CFI_STAA is not set
+CONFIG_MTD_CFI_UTIL=y
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+# CONFIG_MTD_XIP is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+# CONFIG_MTD_PHYSMAP is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_PMC551 is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLKMTD is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+
+#
+# NAND Flash Device Drivers
+#
+# CONFIG_MTD_NAND is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_SX8 is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=8192
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_LBD is not set
+# CONFIG_CDROM_PKTCDVD is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+CONFIG_SCSI=y
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+CONFIG_BLK_DEV_SR=y
+CONFIG_BLK_DEV_SR_VENDOR=y
+CONFIG_CHR_DEV_SG=y
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+CONFIG_SCSI_MULTI_LUN=y
+CONFIG_SCSI_CONSTANTS=y
+CONFIG_SCSI_LOGGING=y
+
+#
+# SCSI Transport Attributes
+#
+CONFIG_SCSI_SPI_ATTRS=y
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+
+#
+# SCSI low-level drivers
+#
+# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
+# CONFIG_SCSI_3W_9XXX is not set
+# CONFIG_SCSI_ACARD is not set
+# CONFIG_SCSI_AACRAID is not set
+# CONFIG_SCSI_AIC7XXX is not set
+# CONFIG_SCSI_AIC7XXX_OLD is not set
+# CONFIG_SCSI_AIC79XX is not set
+# CONFIG_SCSI_DPT_I2O is not set
+# CONFIG_MEGARAID_NEWGEN is not set
+# CONFIG_MEGARAID_LEGACY is not set
+# CONFIG_SCSI_SATA is not set
+# CONFIG_SCSI_BUSLOGIC is not set
+# CONFIG_SCSI_DMX3191D is not set
+# CONFIG_SCSI_EATA is not set
+# CONFIG_SCSI_EATA_PIO is not set
+# CONFIG_SCSI_FUTURE_DOMAIN is not set
+# CONFIG_SCSI_GDTH is not set
+# CONFIG_SCSI_IPS is not set
+# CONFIG_SCSI_INITIO is not set
+# CONFIG_SCSI_INIA100 is not set
+CONFIG_SCSI_SYM53C8XX_2=y
+CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=1
+CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16
+CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64
+# CONFIG_SCSI_SYM53C8XX_IOMAPPED is not set
+# CONFIG_SCSI_IPR is not set
+# CONFIG_SCSI_QLOGIC_ISP is not set
+# CONFIG_SCSI_QLOGIC_FC is not set
+# CONFIG_SCSI_QLOGIC_1280 is not set
+CONFIG_SCSI_QLA2XXX=y
+# CONFIG_SCSI_QLA21XX is not set
+# CONFIG_SCSI_QLA22XX is not set
+# CONFIG_SCSI_QLA2300 is not set
+# CONFIG_SCSI_QLA2322 is not set
+# CONFIG_SCSI_QLA6312 is not set
+# CONFIG_SCSI_DC395x is not set
+# CONFIG_SCSI_DC390T is not set
+# CONFIG_SCSI_NSP32 is not set
+# CONFIG_SCSI_DEBUG is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+# CONFIG_FUSION is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# Macintosh device drivers
+#
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+# CONFIG_NETLINK_DEV is not set
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_IP_MROUTE is not set
+# CONFIG_ARPD is not set
+CONFIG_SYN_COOKIES=y
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_IP_TCPDIAG=y
+# CONFIG_IP_TCPDIAG_IPV6 is not set
+# CONFIG_IPV6 is not set
+# CONFIG_NETFILTER is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+# CONFIG_ATM is not set
+CONFIG_BRIDGE=y
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_NET_VENDOR_3COM is not set
+
+#
+# Tulip family network device support
+#
+CONFIG_NET_TULIP=y
+# CONFIG_DE2104X is not set
+CONFIG_TULIP=y
+# CONFIG_TULIP_MWI is not set
+# CONFIG_TULIP_MMIO is not set
+# CONFIG_TULIP_NAPI is not set
+# CONFIG_DE4X5 is not set
+# CONFIG_WINBOND_840 is not set
+# CONFIG_DM9102 is not set
+# CONFIG_HP100 is not set
+CONFIG_NET_PCI=y
+# CONFIG_PCNET32 is not set
+# CONFIG_AMD8111_ETH is not set
+# CONFIG_ADAPTEC_STARFIRE is not set
+# CONFIG_B44 is not set
+# CONFIG_FORCEDETH is not set
+# CONFIG_DGRS is not set
+# CONFIG_EEPRO100 is not set
+CONFIG_E100=y
+# CONFIG_FEALNX is not set
+# CONFIG_NATSEMI is not set
+# CONFIG_NE2K_PCI is not set
+# CONFIG_8139CP is not set
+# CONFIG_8139TOO is not set
+# CONFIG_SIS900 is not set
+# CONFIG_EPIC100 is not set
+# CONFIG_SUNDANCE is not set
+# CONFIG_TLAN is not set
+# CONFIG_VIA_RHINE is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_E1000 is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+CONFIG_R8169=y
+CONFIG_R8169_NAPI=y
+CONFIG_SK98LIN=y
+# CONFIG_VIA_VELOCITY is not set
+CONFIG_TIGON3=y
+CONFIG_MV643XX_ETH=y
+CONFIG_MV643XX_ETH_0=y
+CONFIG_MV643XX_ETH_1=y
+# CONFIG_MV643XX_ETH_2 is not set
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_IXGB is not set
+# CONFIG_S2IO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_NET_FC is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+CONFIG_KEYBOARD_ATKBD=y
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+CONFIG_KEYBOARD_XTKBD=y
+# CONFIG_KEYBOARD_NEWTON is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+CONFIG_SERIO_I8042=y
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_PCIPS2 is not set
+CONFIG_SERIO_LIBPS2=y
+# CONFIG_SERIO_RAW is not set
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+
+#
+# Character devices
+#
+CONFIG_VT=y
+# CONFIG_VT_CONSOLE is not set
+CONFIG_HW_CONSOLE=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=4
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_MPSC=y
+# CONFIG_SERIAL_MPSC_CONSOLE is not set
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+CONFIG_WATCHDOG=y
+CONFIG_WATCHDOG_NOWAYOUT=y
+
+#
+# Watchdog Device Drivers
+#
+# CONFIG_SOFT_WATCHDOG is not set
+
+#
+# PCI-based Watchdog Cards
+#
+# CONFIG_PCIPCWATCHDOG is not set
+# CONFIG_WDTPCI is not set
+# CONFIG_NVRAM is not set
+CONFIG_GEN_RTC=y
+# CONFIG_GEN_RTC_X is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+
+#
+# I2C support
+#
+CONFIG_I2C=y
+CONFIG_I2C_CHARDEV=y
+
+#
+# I2C Algorithms
+#
+# CONFIG_I2C_ALGOBIT is not set
+# CONFIG_I2C_ALGOPCF is not set
+# CONFIG_I2C_ALGOPCA is not set
+
+#
+# I2C Hardware Bus support
+#
+# CONFIG_I2C_ALI1535 is not set
+# CONFIG_I2C_ALI1563 is not set
+# CONFIG_I2C_ALI15X3 is not set
+# CONFIG_I2C_AMD756 is not set
+# CONFIG_I2C_AMD8111 is not set
+# CONFIG_I2C_I801 is not set
+# CONFIG_I2C_I810 is not set
+# CONFIG_I2C_ISA is not set
+# CONFIG_I2C_MPC is not set
+# CONFIG_I2C_NFORCE2 is not set
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_PIIX4 is not set
+# CONFIG_I2C_PROSAVAGE is not set
+# CONFIG_I2C_SAVAGE4 is not set
+# CONFIG_SCx200_ACB is not set
+# CONFIG_I2C_SIS5595 is not set
+# CONFIG_I2C_SIS630 is not set
+# CONFIG_I2C_SIS96X is not set
+# CONFIG_I2C_STUB is not set
+# CONFIG_I2C_VIA is not set
+# CONFIG_I2C_VIAPRO is not set
+# CONFIG_I2C_VOODOO3 is not set
+# CONFIG_I2C_PCA_ISA is not set
+CONFIG_I2C_MV64XXX=y
+
+#
+# Hardware Sensors Chip support
+#
+CONFIG_I2C_SENSOR=y
+# CONFIG_SENSORS_ADM1021 is not set
+# CONFIG_SENSORS_ADM1025 is not set
+# CONFIG_SENSORS_ADM1026 is not set
+# CONFIG_SENSORS_ADM1031 is not set
+# CONFIG_SENSORS_ASB100 is not set
+# CONFIG_SENSORS_DS1621 is not set
+# CONFIG_SENSORS_FSCHER is not set
+# CONFIG_SENSORS_FSCPOS is not set
+# CONFIG_SENSORS_GL518SM is not set
+# CONFIG_SENSORS_GL520SM is not set
+# CONFIG_SENSORS_IT87 is not set
+# CONFIG_SENSORS_LM63 is not set
+# CONFIG_SENSORS_LM75 is not set
+# CONFIG_SENSORS_LM77 is not set
+# CONFIG_SENSORS_LM78 is not set
+# CONFIG_SENSORS_LM80 is not set
+# CONFIG_SENSORS_LM83 is not set
+# CONFIG_SENSORS_LM85 is not set
+# CONFIG_SENSORS_LM87 is not set
+CONFIG_SENSORS_LM90=y
+# CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_PC87360 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
+# CONFIG_SENSORS_SIS5595 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_VIA686A is not set
+# CONFIG_SENSORS_W83781D is not set
+# CONFIG_SENSORS_W83L785TS is not set
+# CONFIG_SENSORS_W83627HF is not set
+
+#
+# Other I2C Chip support
+#
+# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_SENSORS_RTC8564 is not set
+# CONFIG_SENSORS_M41T00 is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
+# Misc devices
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+# CONFIG_FB is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+# CONFIG_USB is not set
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# InfiniBand support
+#
+# CONFIG_INFINIBAND is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_JBD is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+
+#
+# XFS support
+#
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+CONFIG_ISO9660_FS=y
+# CONFIG_JOLIET is not set
+# CONFIG_ZISOFS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_SYSFS=y
+# CONFIG_DEVFS_FS is not set
+# CONFIG_DEVPTS_FS_XATTR is not set
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_XATTR is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_JFFS_FS is not set
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+# CONFIG_JFFS2_FS_NAND is not set
+# CONFIG_JFFS2_FS_NOR_ECC is not set
+# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+CONFIG_JFFS2_ZLIB=y
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+# CONFIG_NFSD is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_SUNRPC=y
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+# CONFIG_NLS is not set
+
+#
+# Library routines
+#
+CONFIG_CRC_CCITT=y
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+# CONFIG_DEBUG_KERNEL is not set
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_SERIAL_TEXT_DEBUG is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Hardware crypto devices
+#
diff --git a/arch/ppc/configs/rainier_defconfig b/arch/ppc/configs/rainier_defconfig
new file mode 100644
index 0000000..4d4fcdc
--- /dev/null
+++ b/arch/ppc/configs/rainier_defconfig
@@ -0,0 +1,599 @@
+#
+# Automatically generated make config: don't edit
+#
+CONFIG_MMU=y
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_HAVE_DEC_LOCK=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+
+#
+# General setup
+#
+# CONFIG_SWAP is not set
+CONFIG_SYSVIPC=y
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_EMBEDDED=y
+CONFIG_FUTEX=y
+# CONFIG_EPOLL is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+# CONFIG_MODULE_UNLOAD is not set
+CONFIG_OBSOLETE_MODPARM=y
+CONFIG_MODVERSIONS=y
+CONFIG_KMOD=y
+
+#
+# Platform support
+#
+CONFIG_PPC=y
+CONFIG_PPC32=y
+# CONFIG_6xx is not set
+CONFIG_40x=y
+# CONFIG_POWER3 is not set
+# CONFIG_8xx is not set
+CONFIG_4xx=y
+
+#
+# IBM 4xx options
+#
+# CONFIG_ASH is not set
+# CONFIG_BEECH is not set
+# CONFIG_CEDAR is not set
+# CONFIG_CPCI405 is not set
+# CONFIG_EP405 is not set
+# CONFIG_OAK is not set
+# CONFIG_REDWOOD_4 is not set
+# CONFIG_REDWOOD_5 is not set
+# CONFIG_REDWOOD_6 is not set
+# CONFIG_SYCAMORE is not set
+# CONFIG_TIVO is not set
+CONFIG_WALNUT=y
+CONFIG_IBM405_ERR77=y
+CONFIG_IBM405_ERR51=y
+CONFIG_IBM_OCP=y
+CONFIG_BIOS_FIXUP=y
+CONFIG_405GP=y
+CONFIG_IBM_OPENBIOS=y
+CONFIG_405_DMA=y
+# CONFIG_PM is not set
+CONFIG_UART0_TTYS0=y
+# CONFIG_UART0_TTYS1 is not set
+CONFIG_NOT_COHERENT_CACHE=y
+# CONFIG_SMP is not set
+# CONFIG_PREEMPT is not set
+# CONFIG_MATH_EMULATION is not set
+# CONFIG_CPU_FREQ is not set
+
+#
+# General setup
+#
+# CONFIG_HIGHMEM is not set
+CONFIG_PCI=y
+CONFIG_PCI_DOMAINS=y
+# CONFIG_PC_KEYBOARD is not set
+CONFIG_KCORE_ELF=y
+CONFIG_BINFMT_ELF=y
+CONFIG_KERNEL_ELF=y
+# CONFIG_BINFMT_MISC is not set
+# CONFIG_PCI_LEGACY_PROC is not set
+CONFIG_PCI_NAMES=y
+# CONFIG_HOTPLUG is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+# CONFIG_CMDLINE_BOOL is not set
+
+#
+# Advanced setup
+#
+# CONFIG_ADVANCED_OPTIONS is not set
+
+#
+# Default settings for advanced configuration options are used
+#
+CONFIG_HIGHMEM_START=0xfe000000
+CONFIG_LOWMEM_SIZE=0x30000000
+CONFIG_KERNEL_START=0xc0000000
+CONFIG_TASK_SIZE=0x80000000
+CONFIG_BOOT_LOAD=0x00400000
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Plug and Play support
+#
+# CONFIG_PNP is not set
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_NBD=y
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=4096
+CONFIG_BLK_DEV_INITRD=y
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# ATA/IDE/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI support
+#
+# CONFIG_SCSI is not set
+
+#
+# Fusion MPT device support
+#
+
+#
+# IEEE 1394 (FireWire) support (EXPERIMENTAL)
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+# CONFIG_NETLINK_DEV is not set
+# CONFIG_NETFILTER is not set
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_PNP=y
+# CONFIG_IP_PNP_DHCP is not set
+CONFIG_IP_PNP_BOOTP=y
+CONFIG_IP_PNP_RARP=y
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_IP_MROUTE is not set
+# CONFIG_ARPD is not set
+# CONFIG_INET_ECN is not set
+CONFIG_SYN_COOKIES=y
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_IPV6 is not set
+# CONFIG_XFRM_USER is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+CONFIG_IPV6_SCTP__=y
+# CONFIG_IP_SCTP is not set
+# CONFIG_ATM is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_LLC is not set
+# CONFIG_DECNET is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_HW_FLOWCONTROL is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+CONFIG_NETDEVICES=y
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_ETHERTAP is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_OAKNET is not set
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_NET_VENDOR_3COM is not set
+
+#
+# Tulip family network device support
+#
+# CONFIG_NET_TULIP is not set
+# CONFIG_HP100 is not set
+CONFIG_NET_PCI=y
+CONFIG_PCNET32=y
+# CONFIG_AMD8111_ETH is not set
+# CONFIG_ADAPTEC_STARFIRE is not set
+# CONFIG_B44 is not set
+# CONFIG_DGRS is not set
+CONFIG_EEPRO100=y
+# CONFIG_EEPRO100_PIO is not set
+# CONFIG_E100 is not set
+# CONFIG_FEALNX is not set
+# CONFIG_NATSEMI is not set
+# CONFIG_NE2K_PCI is not set
+# CONFIG_8139CP is not set
+# CONFIG_8139TOO is not set
+# CONFIG_SIS900 is not set
+# CONFIG_EPIC100 is not set
+# CONFIG_SUNDANCE is not set
+# CONFIG_TLAN is not set
+# CONFIG_VIA_RHINE is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_E1000 is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_TIGON3 is not set
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_IXGB is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+CONFIG_PPP=y
+# CONFIG_PPP_MULTILINK is not set
+# CONFIG_PPP_FILTER is not set
+# CONFIG_PPP_ASYNC is not set
+# CONFIG_PPP_SYNC_TTY is not set
+# CONFIG_PPP_DEFLATE is not set
+# CONFIG_PPP_BSDCOMP is not set
+# CONFIG_PPPOE is not set
+# CONFIG_SLIP is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Token Ring devices (depends on LLC=y)
+#
+# CONFIG_RCPCI is not set
+# CONFIG_SHAPER is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+
+#
+# Amateur Radio support
+#
+# CONFIG_HAMRADIO is not set
+
+#
+# IrDA (infrared) support
+#
+# CONFIG_IRDA is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN_BOOL is not set
+
+#
+# Graphics support
+#
+# CONFIG_FB is not set
+
+#
+# Old CD-ROM drivers (not SCSI, not IDE)
+#
+# CONFIG_CD_NO_IDESCSI is not set
+
+#
+# Input device support
+#
+# CONFIG_INPUT is not set
+
+#
+# Userland interfaces
+#
+
+#
+# Input I/O drivers
+#
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+CONFIG_SERIO=y
+CONFIG_SERIO_I8042=y
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_CT82C710 is not set
+
+#
+# Input Device Drivers
+#
+
+#
+# Macintosh device drivers
+#
+
+#
+# Character devices
+#
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_UNIX98_PTYS=y
+CONFIG_UNIX98_PTY_COUNT=256
+
+#
+# I2C support
+#
+CONFIG_I2C=y
+# CONFIG_I2C_ALGOBIT is not set
+# CONFIG_I2C_ALGOPCF is not set
+# CONFIG_I2C_IBM_OCP_ALGO is not set
+CONFIG_I2C_CHARDEV=y
+
+#
+# I2C Hardware Sensors Mainboard support
+#
+# CONFIG_I2C_ALI15X3 is not set
+# CONFIG_I2C_AMD756 is not set
+# CONFIG_I2C_AMD8111 is not set
+# CONFIG_I2C_I801 is not set
+# CONFIG_I2C_PIIX4 is not set
+# CONFIG_I2C_SIS96X is not set
+# CONFIG_I2C_VIAPRO is not set
+
+#
+# I2C Hardware Sensors Chip support
+#
+# CONFIG_SENSORS_ADM1021 is not set
+# CONFIG_SENSORS_IT87 is not set
+# CONFIG_SENSORS_LM75 is not set
+# CONFIG_SENSORS_LM85 is not set
+# CONFIG_SENSORS_VIA686A is not set
+# CONFIG_SENSORS_W83781D is not set
+# CONFIG_I2C_SENSOR is not set
+
+#
+# Mice
+#
+CONFIG_BUSMOUSE=y
+# CONFIG_QIC02_TAPE is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+CONFIG_WATCHDOG=y
+# CONFIG_WATCHDOG_NOWAYOUT is not set
+# CONFIG_SOFT_WATCHDOG is not set
+# CONFIG_WDT is not set
+# CONFIG_WDTPCI is not set
+# CONFIG_PCWATCHDOG is not set
+# CONFIG_ACQUIRE_WDT is not set
+# CONFIG_ADVANTECH_WDT is not set
+# CONFIG_EUROTECH_WDT is not set
+# CONFIG_IB700_WDT is not set
+# CONFIG_MIXCOMWD is not set
+# CONFIG_SCx200_WDT is not set
+# CONFIG_60XX_WDT is not set
+# CONFIG_W83877F_WDT is not set
+# CONFIG_MACHZ_WDT is not set
+# CONFIG_SC520_WDT is not set
+# CONFIG_AMD7XX_TCO is not set
+# CONFIG_ALIM7101_WDT is not set
+# CONFIG_SC1200_WDT is not set
+# CONFIG_WAFER_WDT is not set
+# CONFIG_CPU5_WDT is not set
+# CONFIG_NVRAM is not set
+CONFIG_GEN_RTC=y
+# CONFIG_GEN_RTC_X is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_FTAPE is not set
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_HANGCHECK_TIMER is not set
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_JBD is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+CONFIG_AUTOFS_FS=y
+# CONFIG_AUTOFS4_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+CONFIG_ISO9660_FS=y
+# CONFIG_JOLIET is not set
+# CONFIG_ZISOFS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_FAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+# CONFIG_DEVFS_FS is not set
+CONFIG_DEVPTS_FS=y
+# CONFIG_DEVPTS_FS_XATTR is not set
+CONFIG_TMPFS=y
+CONFIG_RAMFS=y
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+# CONFIG_NFS_V3 is not set
+# CONFIG_NFS_V4 is not set
+CONFIG_NFSD=y
+# CONFIG_NFSD_V3 is not set
+# CONFIG_NFSD_TCP is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_EXPORTFS=y
+CONFIG_SUNRPC=y
+# CONFIG_SUNRPC_GSS is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_INTERMEZZO_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# IBM 40x options
+#
+
+#
+# USB support
+#
+# CONFIG_USB is not set
+# CONFIG_USB_GADGET is not set
+
+#
+# Bluetooth support
+#
+# CONFIG_BT is not set
+
+#
+# Library routines
+#
+# CONFIG_CRC32 is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_DEBUG_KERNEL is not set
+# CONFIG_KALLSYMS is not set
+# CONFIG_SERIAL_TEXT_DEBUG is not set
+CONFIG_OCP=y
+
+#
+# Security options
+#
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
diff --git a/arch/ppc/configs/redwood5_defconfig b/arch/ppc/configs/redwood5_defconfig
new file mode 100644
index 0000000..4c5486d
--- /dev/null
+++ b/arch/ppc/configs/redwood5_defconfig
@@ -0,0 +1,557 @@
+#
+# Automatically generated make config: don't edit
+#
+CONFIG_MMU=y
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_HAVE_DEC_LOCK=y
+CONFIG_PPC=y
+CONFIG_PPC32=y
+CONFIG_GENERIC_NVRAM=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=y
+# CONFIG_STANDALONE is not set
+CONFIG_BROKEN_ON_SMP=y
+
+#
+# General setup
+#
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_HOTPLUG is not set
+# CONFIG_IKCONFIG is not set
+CONFIG_EMBEDDED=y
+# CONFIG_KALLSYMS is not set
+CONFIG_FUTEX=y
+# CONFIG_EPOLL is not set
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_OBSOLETE_MODPARM=y
+# CONFIG_MODVERSIONS is not set
+CONFIG_KMOD=y
+
+#
+# Processor
+#
+# CONFIG_6xx is not set
+CONFIG_40x=y
+# CONFIG_44x is not set
+# CONFIG_POWER3 is not set
+# CONFIG_POWER4 is not set
+# CONFIG_8xx is not set
+# CONFIG_MATH_EMULATION is not set
+# CONFIG_CPU_FREQ is not set
+CONFIG_4xx=y
+
+#
+# IBM 4xx options
+#
+# CONFIG_ASH is not set
+# CONFIG_CPCI405 is not set
+# CONFIG_EP405 is not set
+# CONFIG_OAK is not set
+CONFIG_REDWOOD_5=y
+# CONFIG_REDWOOD_6 is not set
+# CONFIG_SYCAMORE is not set
+# CONFIG_WALNUT is not set
+CONFIG_IBM405_ERR77=y
+CONFIG_IBM405_ERR51=y
+CONFIG_IBM_OCP=y
+CONFIG_PPC_OCP=y
+CONFIG_STB03xxx=y
+CONFIG_IBM_OPENBIOS=y
+# CONFIG_PM is not set
+CONFIG_UART0_TTYS0=y
+# CONFIG_UART0_TTYS1 is not set
+# CONFIG_SERIAL_SICC is not set
+CONFIG_NOT_COHERENT_CACHE=y
+
+#
+# Platform options
+#
+# CONFIG_PC_KEYBOARD is not set
+# CONFIG_SMP is not set
+# CONFIG_PREEMPT is not set
+# CONFIG_HIGHMEM is not set
+CONFIG_KERNEL_ELF=y
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+CONFIG_CMDLINE_BOOL=y
+CONFIG_CMDLINE="ip=on"
+
+#
+# Bus options
+#
+# CONFIG_PCI is not set
+# CONFIG_PCI_DOMAINS is not set
+
+#
+# Advanced setup
+#
+# CONFIG_ADVANCED_OPTIONS is not set
+
+#
+# Default settings for advanced configuration options are used
+#
+CONFIG_HIGHMEM_START=0xfe000000
+CONFIG_LOWMEM_SIZE=0x30000000
+CONFIG_KERNEL_START=0xc0000000
+CONFIG_TASK_SIZE=0x80000000
+CONFIG_BOOT_LOAD=0x00400000
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=4096
+CONFIG_BLK_DEV_INITRD=y
+# CONFIG_LBD is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+CONFIG_IDE=y
+CONFIG_BLK_DEV_IDE=y
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+CONFIG_BLK_DEV_IDEDISK=y
+# CONFIG_IDEDISK_MULTI_MODE is not set
+# CONFIG_IDEDISK_STROKE is not set
+# CONFIG_BLK_DEV_IDECD is not set
+# CONFIG_BLK_DEV_IDETAPE is not set
+# CONFIG_BLK_DEV_IDEFLOPPY is not set
+# CONFIG_IDE_TASK_IOCTL is not set
+# CONFIG_IDE_TASKFILE_IO is not set
+
+#
+# IDE chipset support/bugfixes
+#
+CONFIG_IDE_GENERIC=y
+# CONFIG_BLK_DEV_IDEDMA is not set
+# CONFIG_IDEDMA_AUTO is not set
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# SCSI device support
+#
+# CONFIG_SCSI is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+
+#
+# Macintosh device drivers
+#
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+# CONFIG_PACKET is not set
+# CONFIG_NETLINK_DEV is not set
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+CONFIG_IP_PNP_RARP=y
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_IP_MROUTE is not set
+# CONFIG_ARPD is not set
+CONFIG_SYN_COOKIES=y
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_IPV6 is not set
+# CONFIG_DECNET is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_NETFILTER is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+# CONFIG_ATM is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_HW_FLOWCONTROL is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_OAKNET is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_IBM_EMAC is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+
+#
+# Amateur Radio support
+#
+# CONFIG_HAMRADIO is not set
+
+#
+# IrDA (infrared) support
+#
+# CONFIG_IRDA is not set
+
+#
+# Bluetooth support
+#
+# CONFIG_BT is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input I/O drivers
+#
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+CONFIG_SERIO=y
+# CONFIG_SERIO_I8042 is not set
+# CONFIG_SERIO_SERPORT is not set
+# CONFIG_SERIO_CT82C710 is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Character devices
+#
+# CONFIG_VT is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=4
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_UNIX98_PTYS is not set
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_QIC02_TAPE is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_NVRAM is not set
+CONFIG_GEN_RTC=y
+# CONFIG_GEN_RTC_X is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_FTAPE is not set
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# Misc devices
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+# CONFIG_FB is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_JBD is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_FAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+# CONFIG_DEVFS_FS is not set
+CONFIG_TMPFS=y
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+# CONFIG_NFS_V3 is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+# CONFIG_NFSD is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+# CONFIG_EXPORTFS is not set
+CONFIG_SUNRPC=y
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_INTERMEZZO_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+# CONFIG_NLS is not set
+
+#
+# IBM 40x options
+#
+
+#
+# Library routines
+#
+# CONFIG_CRC32 is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_DEBUG_KERNEL is not set
+# CONFIG_SERIAL_TEXT_DEBUG is not set
+CONFIG_OCP=y
+
+#
+# Security options
+#
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
diff --git a/arch/ppc/configs/redwood6_defconfig b/arch/ppc/configs/redwood6_defconfig
new file mode 100644
index 0000000..5752845
--- /dev/null
+++ b/arch/ppc/configs/redwood6_defconfig
@@ -0,0 +1,535 @@
+#
+# Automatically generated make config: don't edit
+#
+CONFIG_MMU=y
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_HAVE_DEC_LOCK=y
+CONFIG_PPC=y
+CONFIG_PPC32=y
+CONFIG_GENERIC_NVRAM=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=y
+# CONFIG_STANDALONE is not set
+CONFIG_BROKEN_ON_SMP=y
+
+#
+# General setup
+#
+# CONFIG_SWAP is not set
+CONFIG_SYSVIPC=y
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_HOTPLUG is not set
+# CONFIG_IKCONFIG is not set
+CONFIG_EMBEDDED=y
+# CONFIG_KALLSYMS is not set
+CONFIG_FUTEX=y
+# CONFIG_EPOLL is not set
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+# CONFIG_MODULE_UNLOAD is not set
+CONFIG_OBSOLETE_MODPARM=y
+# CONFIG_MODVERSIONS is not set
+CONFIG_KMOD=y
+
+#
+# Processor
+#
+# CONFIG_6xx is not set
+CONFIG_40x=y
+# CONFIG_44x is not set
+# CONFIG_POWER3 is not set
+# CONFIG_POWER4 is not set
+# CONFIG_8xx is not set
+# CONFIG_MATH_EMULATION is not set
+# CONFIG_CPU_FREQ is not set
+CONFIG_4xx=y
+
+#
+# IBM 4xx options
+#
+# CONFIG_ASH is not set
+# CONFIG_CPCI405 is not set
+# CONFIG_EP405 is not set
+# CONFIG_OAK is not set
+# CONFIG_REDWOOD_5 is not set
+CONFIG_REDWOOD_6=y
+# CONFIG_SYCAMORE is not set
+# CONFIG_WALNUT is not set
+CONFIG_IBM405_ERR77=y
+CONFIG_IBM405_ERR51=y
+CONFIG_IBM_OCP=y
+CONFIG_PPC_OCP=y
+CONFIG_STB03xxx=y
+CONFIG_IBM_OPENBIOS=y
+# CONFIG_PM is not set
+CONFIG_UART0_TTYS0=y
+# CONFIG_UART0_TTYS1 is not set
+# CONFIG_SERIAL_SICC is not set
+CONFIG_NOT_COHERENT_CACHE=y
+
+#
+# Platform options
+#
+# CONFIG_PC_KEYBOARD is not set
+# CONFIG_SMP is not set
+# CONFIG_PREEMPT is not set
+# CONFIG_HIGHMEM is not set
+CONFIG_KERNEL_ELF=y
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+CONFIG_CMDLINE_BOOL=y
+CONFIG_CMDLINE="ip=on"
+
+#
+# Bus options
+#
+# CONFIG_PCI is not set
+# CONFIG_PCI_DOMAINS is not set
+
+#
+# Advanced setup
+#
+# CONFIG_ADVANCED_OPTIONS is not set
+
+#
+# Default settings for advanced configuration options are used
+#
+CONFIG_HIGHMEM_START=0xfe000000
+CONFIG_LOWMEM_SIZE=0x30000000
+CONFIG_KERNEL_START=0xc0000000
+CONFIG_TASK_SIZE=0x80000000
+CONFIG_BOOT_LOAD=0x00400000
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=4096
+CONFIG_BLK_DEV_INITRD=y
+# CONFIG_LBD is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_SCSI is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+
+#
+# Macintosh device drivers
+#
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+# CONFIG_PACKET is not set
+# CONFIG_NETLINK_DEV is not set
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_PNP=y
+# CONFIG_IP_PNP_DHCP is not set
+CONFIG_IP_PNP_BOOTP=y
+CONFIG_IP_PNP_RARP=y
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_IP_MROUTE is not set
+# CONFIG_ARPD is not set
+CONFIG_SYN_COOKIES=y
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_IPV6 is not set
+# CONFIG_DECNET is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_NETFILTER is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+# CONFIG_ATM is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_HW_FLOWCONTROL is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_OAKNET is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_IBM_EMAC is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+
+#
+# Amateur Radio support
+#
+# CONFIG_HAMRADIO is not set
+
+#
+# IrDA (infrared) support
+#
+# CONFIG_IRDA is not set
+
+#
+# Bluetooth support
+#
+# CONFIG_BT is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input I/O drivers
+#
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+CONFIG_SERIO=y
+# CONFIG_SERIO_I8042 is not set
+# CONFIG_SERIO_SERPORT is not set
+# CONFIG_SERIO_CT82C710 is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Character devices
+#
+# CONFIG_VT is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=4
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_QIC02_TAPE is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_NVRAM is not set
+# CONFIG_GEN_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_FTAPE is not set
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# Misc devices
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+# CONFIG_FB is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_JBD is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_FAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+# CONFIG_DEVFS_FS is not set
+# CONFIG_DEVPTS_FS_XATTR is not set
+CONFIG_TMPFS=y
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+# CONFIG_NFS_V3 is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+# CONFIG_NFSD is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+# CONFIG_EXPORTFS is not set
+CONFIG_SUNRPC=y
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_INTERMEZZO_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+# CONFIG_NLS is not set
+
+#
+# IBM 40x options
+#
+
+#
+# Library routines
+#
+# CONFIG_CRC32 is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_DEBUG_KERNEL is not set
+# CONFIG_SERIAL_TEXT_DEBUG is not set
+CONFIG_OCP=y
+
+#
+# Security options
+#
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
diff --git a/arch/ppc/configs/redwood_defconfig b/arch/ppc/configs/redwood_defconfig
new file mode 100644
index 0000000..4aa348d
--- /dev/null
+++ b/arch/ppc/configs/redwood_defconfig
@@ -0,0 +1,540 @@
+#
+# Automatically generated make config: don't edit
+#
+CONFIG_MMU=y
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_HAVE_DEC_LOCK=y
+CONFIG_PPC=y
+CONFIG_PPC32=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=y
+# CONFIG_STANDALONE is not set
+CONFIG_BROKEN_ON_SMP=y
+
+#
+# General setup
+#
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_IKCONFIG is not set
+CONFIG_EMBEDDED=y
+# CONFIG_KALLSYMS is not set
+CONFIG_FUTEX=y
+# CONFIG_EPOLL is not set
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+# CONFIG_MODULE_UNLOAD is not set
+CONFIG_OBSOLETE_MODPARM=y
+# CONFIG_MODVERSIONS is not set
+CONFIG_KMOD=y
+
+#
+# Processor
+#
+# CONFIG_6xx is not set
+CONFIG_40x=y
+# CONFIG_44x is not set
+# CONFIG_POWER3 is not set
+# CONFIG_POWER4 is not set
+# CONFIG_8xx is not set
+# CONFIG_MATH_EMULATION is not set
+# CONFIG_CPU_FREQ is not set
+CONFIG_4xx=y
+
+#
+# IBM 4xx options
+#
+# CONFIG_ASH is not set
+# CONFIG_BEECH is not set
+# CONFIG_CEDAR is not set
+# CONFIG_CPCI405 is not set
+# CONFIG_EP405 is not set
+# CONFIG_OAK is not set
+CONFIG_REDWOOD_4=y
+# CONFIG_REDWOOD_5 is not set
+# CONFIG_REDWOOD_6 is not set
+# CONFIG_SYCAMORE is not set
+# CONFIG_TIVO is not set
+# CONFIG_WALNUT is not set
+CONFIG_IBM405_ERR77=y
+CONFIG_IBM405_ERR51=y
+CONFIG_IBM_OCP=y
+CONFIG_STB03xxx=y
+CONFIG_IBM_OPENBIOS=y
+# CONFIG_405_DMA is not set
+# CONFIG_PM is not set
+CONFIG_UART0_TTYS0=y
+# CONFIG_UART0_TTYS1 is not set
+# CONFIG_SERIAL_SICC is not set
+CONFIG_NOT_COHERENT_CACHE=y
+
+#
+# Platform options
+#
+# CONFIG_PC_KEYBOARD is not set
+# CONFIG_SMP is not set
+# CONFIG_PREEMPT is not set
+# CONFIG_HIGHMEM is not set
+CONFIG_KERNEL_ELF=y
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+# CONFIG_CMDLINE_BOOL is not set
+
+#
+# Bus options
+#
+# CONFIG_PCI is not set
+# CONFIG_PCI_DOMAINS is not set
+# CONFIG_HOTPLUG is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Advanced setup
+#
+# CONFIG_ADVANCED_OPTIONS is not set
+
+#
+# Default settings for advanced configuration options are used
+#
+CONFIG_HIGHMEM_START=0xfe000000
+CONFIG_LOWMEM_SIZE=0x30000000
+CONFIG_KERNEL_START=0xc0000000
+CONFIG_TASK_SIZE=0x80000000
+CONFIG_BOOT_LOAD=0x00400000
+
+#
+# Generic Driver Options
+#
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Plug and Play support
+#
+# CONFIG_PNP is not set
+
+#
+# Block devices
+#
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=4096
+CONFIG_BLK_DEV_INITRD=y
+# CONFIG_LBD is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_SCSI is not set
+
+#
+# Fusion MPT device support
+#
+
+#
+# I2O device support
+#
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+# CONFIG_PACKET is not set
+# CONFIG_NETLINK_DEV is not set
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+CONFIG_IP_PNP_RARP=y
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_IP_MROUTE is not set
+# CONFIG_ARPD is not set
+# CONFIG_INET_ECN is not set
+CONFIG_SYN_COOKIES=y
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_IPV6 is not set
+# CONFIG_DECNET is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_NETFILTER is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+CONFIG_IPV6_SCTP__=y
+# CONFIG_IP_SCTP is not set
+# CONFIG_ATM is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_HW_FLOWCONTROL is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+CONFIG_OAKNET=y
+
+#
+# Ethernet (1000 Mbit)
+#
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_SHAPER is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+
+#
+# Amateur Radio support
+#
+# CONFIG_HAMRADIO is not set
+
+#
+# IrDA (infrared) support
+#
+# CONFIG_IRDA is not set
+
+#
+# Bluetooth support
+#
+# CONFIG_BT is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN_BOOL is not set
+
+#
+# Graphics support
+#
+# CONFIG_FB is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input I/O drivers
+#
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+CONFIG_SERIO=y
+# CONFIG_SERIO_I8042 is not set
+# CONFIG_SERIO_SERPORT is not set
+# CONFIG_SERIO_CT82C710 is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Macintosh device drivers
+#
+
+#
+# Character devices
+#
+# CONFIG_VT is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=4
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_UNIX98_PTYS is not set
+
+#
+# I2C support
+#
+CONFIG_I2C=y
+# CONFIG_I2C_CHARDEV is not set
+
+#
+# I2C Algorithms
+#
+# CONFIG_I2C_ALGOBIT is not set
+# CONFIG_I2C_ALGOPCF is not set
+
+#
+# I2C Hardware Bus support
+#
+# CONFIG_I2C_AMD756 is not set
+# CONFIG_I2C_AMD8111 is not set
+CONFIG_I2C_IBM_IIC=y
+
+#
+# I2C Hardware Sensors Chip support
+#
+# CONFIG_I2C_SENSOR is not set
+# CONFIG_SENSORS_ADM1021 is not set
+# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_SENSORS_IT87 is not set
+# CONFIG_SENSORS_LM75 is not set
+# CONFIG_SENSORS_LM78 is not set
+# CONFIG_SENSORS_LM85 is not set
+# CONFIG_SENSORS_VIA686A is not set
+# CONFIG_SENSORS_W83781D is not set
+
+#
+# Mice
+#
+# CONFIG_BUSMOUSE is not set
+# CONFIG_QIC02_TAPE is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_NVRAM is not set
+CONFIG_GEN_RTC=y
+# CONFIG_GEN_RTC_X is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_FTAPE is not set
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_FS_XATTR=y
+# CONFIG_EXT3_FS_POSIX_ACL is not set
+# CONFIG_EXT3_FS_SECURITY is not set
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+CONFIG_FS_MBCACHE=y
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_FAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+# CONFIG_DEVFS_FS is not set
+CONFIG_TMPFS=y
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+# CONFIG_NFS_V3 is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFSD is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+# CONFIG_EXPORTFS is not set
+CONFIG_SUNRPC=y
+# CONFIG_SUNRPC_GSS is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_INTERMEZZO_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# IBM 40x options
+#
+
+#
+# USB support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# Library routines
+#
+CONFIG_CRC32=y
+
+#
+# Kernel hacking
+#
+# CONFIG_DEBUG_KERNEL is not set
+CONFIG_SERIAL_TEXT_DEBUG=y
+CONFIG_OCP=y
+
+#
+# Security options
+#
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
diff --git a/arch/ppc/configs/rpx8260_defconfig b/arch/ppc/configs/rpx8260_defconfig
new file mode 100644
index 0000000..a9c4544
--- /dev/null
+++ b/arch/ppc/configs/rpx8260_defconfig
@@ -0,0 +1,555 @@
+#
+# Automatically generated make config: don't edit
+#
+CONFIG_MMU=y
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_HAVE_DEC_LOCK=y
+CONFIG_PPC=y
+CONFIG_PPC32=y
+CONFIG_GENERIC_NVRAM=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=y
+CONFIG_STANDALONE=y
+CONFIG_BROKEN_ON_SMP=y
+
+#
+# General setup
+#
+# CONFIG_SWAP is not set
+CONFIG_SYSVIPC=y
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_HOTPLUG is not set
+# CONFIG_IKCONFIG is not set
+CONFIG_EMBEDDED=y
+# CONFIG_KALLSYMS is not set
+CONFIG_FUTEX=y
+# CONFIG_EPOLL is not set
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+
+#
+# Loadable module support
+#
+# CONFIG_MODULES is not set
+
+#
+# Processor
+#
+CONFIG_6xx=y
+# CONFIG_40x is not set
+# CONFIG_44x is not set
+# CONFIG_POWER3 is not set
+# CONFIG_POWER4 is not set
+# CONFIG_8xx is not set
+# CONFIG_E500 is not set
+# CONFIG_CPU_FREQ is not set
+CONFIG_EMBEDDEDBOOT=y
+CONFIG_PPC_STD_MMU=y
+
+#
+# Platform options
+#
+# CONFIG_PPC_MULTIPLATFORM is not set
+# CONFIG_APUS is not set
+# CONFIG_WILLOW is not set
+# CONFIG_PCORE is not set
+# CONFIG_POWERPMC250 is not set
+# CONFIG_EV64260 is not set
+# CONFIG_SPRUCE is not set
+# CONFIG_LOPEC is not set
+# CONFIG_MCPN765 is not set
+# CONFIG_MVME5100 is not set
+# CONFIG_PPLUS is not set
+# CONFIG_PRPMC750 is not set
+# CONFIG_PRPMC800 is not set
+# CONFIG_SANDPOINT is not set
+# CONFIG_ADIR is not set
+# CONFIG_K2 is not set
+# CONFIG_PAL4 is not set
+# CONFIG_GEMINI is not set
+# CONFIG_EST8260 is not set
+# CONFIG_SBC82xx is not set
+# CONFIG_SBS8260 is not set
+CONFIG_RPX8260=y
+# CONFIG_TQM8260 is not set
+# CONFIG_ADS8272 is not set
+CONFIG_8260=y
+CONFIG_CPM2=y
+# CONFIG_PC_KEYBOARD is not set
+# CONFIG_SMP is not set
+# CONFIG_PREEMPT is not set
+# CONFIG_HIGHMEM is not set
+CONFIG_KERNEL_ELF=y
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+# CONFIG_CMDLINE_BOOL is not set
+
+#
+# Bus options
+#
+# CONFIG_PCI is not set
+# CONFIG_PCI_DOMAINS is not set
+
+#
+# Advanced setup
+#
+# CONFIG_ADVANCED_OPTIONS is not set
+
+#
+# Default settings for advanced configuration options are used
+#
+CONFIG_HIGHMEM_START=0xfe000000
+CONFIG_LOWMEM_SIZE=0x30000000
+CONFIG_KERNEL_START=0xc0000000
+CONFIG_TASK_SIZE=0x80000000
+CONFIG_BOOT_LOAD=0x00400000
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=4096
+CONFIG_BLK_DEV_INITRD=y
+# CONFIG_LBD is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_SCSI is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+
+#
+# Macintosh device drivers
+#
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+# CONFIG_NETLINK_DEV is not set
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_PNP=y
+# CONFIG_IP_PNP_DHCP is not set
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_IP_MROUTE is not set
+# CONFIG_ARPD is not set
+CONFIG_SYN_COOKIES=y
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_IPV6 is not set
+# CONFIG_NETFILTER is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_HW_FLOWCONTROL is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+# CONFIG_MII is not set
+# CONFIG_OAKNET is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+
+#
+# Ethernet (10000 Mbit)
+#
+
+#
+# Token Ring devices
+#
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+# CONFIG_INPUT is not set
+
+#
+# Userland interfaces
+#
+
+#
+# Input I/O drivers
+#
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+# CONFIG_SERIO is not set
+# CONFIG_SERIO_I8042 is not set
+
+#
+# Input Device Drivers
+#
+
+#
+# Character devices
+#
+# CONFIG_VT is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_SERIAL_CPM=y
+CONFIG_SERIAL_CPM_CONSOLE=y
+# CONFIG_SERIAL_CPM_SCC1 is not set
+# CONFIG_SERIAL_CPM_SCC2 is not set
+# CONFIG_SERIAL_CPM_SCC3 is not set
+# CONFIG_SERIAL_CPM_SCC4 is not set
+CONFIG_SERIAL_CPM_SMC1=y
+# CONFIG_SERIAL_CPM_SMC2 is not set
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_QIC02_TAPE is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_NVRAM is not set
+# CONFIG_GEN_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_FTAPE is not set
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
+# Misc devices
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+# CONFIG_FB is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_FS_XATTR=y
+# CONFIG_EXT3_FS_POSIX_ACL is not set
+# CONFIG_EXT3_FS_SECURITY is not set
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+CONFIG_FS_MBCACHE=y
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_SYSFS=y
+# CONFIG_DEVFS_FS is not set
+# CONFIG_DEVPTS_FS_XATTR is not set
+CONFIG_TMPFS=y
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+# CONFIG_NFSD is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+# CONFIG_EXPORTFS is not set
+CONFIG_SUNRPC=y
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
+# CONFIG_MSDOS_PARTITION is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_EFI_PARTITION is not set
+
+#
+# Native Language Support
+#
+# CONFIG_NLS is not set
+# CONFIG_SCC_ENET is not set
+CONFIG_FEC_ENET=y
+# CONFIG_USE_MDIO is not set
+
+#
+# CPM2 Options
+#
+# CONFIG_FCC1_ENET is not set
+# CONFIG_FCC2_ENET is not set
+CONFIG_FCC3_ENET=y
+
+#
+# Library routines
+#
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC32 is not set
+# CONFIG_LIBCRC32C is not set
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_DEBUG_KERNEL is not set
+# CONFIG_KGDB_CONSOLE is not set
+
+#
+# Security options
+#
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
diff --git a/arch/ppc/configs/rpxcllf_defconfig b/arch/ppc/configs/rpxcllf_defconfig
new file mode 100644
index 0000000..cf932f1
--- /dev/null
+++ b/arch/ppc/configs/rpxcllf_defconfig
@@ -0,0 +1,582 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.10-rc1
+# Mon Nov 1 16:41:04 2004
+#
+CONFIG_MMU=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_HAVE_DEC_LOCK=y
+CONFIG_PPC=y
+CONFIG_PPC32=y
+CONFIG_GENERIC_NVRAM=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+# CONFIG_CLEAN_COMPILE is not set
+CONFIG_BROKEN=y
+CONFIG_BROKEN_ON_SMP=y
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+# CONFIG_SWAP is not set
+CONFIG_SYSVIPC=y
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_HOTPLUG is not set
+# CONFIG_KOBJECT_UEVENT is not set
+# CONFIG_IKCONFIG is not set
+CONFIG_EMBEDDED=y
+# CONFIG_KALLSYMS is not set
+# CONFIG_FUTEX is not set
+# CONFIG_EPOLL is not set
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+# CONFIG_SHMEM is not set
+CONFIG_CC_ALIGN_FUNCTIONS=0
+CONFIG_CC_ALIGN_LABELS=0
+CONFIG_CC_ALIGN_LOOPS=0
+CONFIG_CC_ALIGN_JUMPS=0
+CONFIG_TINY_SHMEM=y
+
+#
+# Loadable module support
+#
+# CONFIG_MODULES is not set
+
+#
+# Processor
+#
+# CONFIG_6xx is not set
+# CONFIG_40x is not set
+# CONFIG_44x is not set
+# CONFIG_POWER3 is not set
+# CONFIG_POWER4 is not set
+CONFIG_8xx=y
+# CONFIG_E500 is not set
+CONFIG_MATH_EMULATION=y
+# CONFIG_CPU_FREQ is not set
+CONFIG_EMBEDDEDBOOT=y
+CONFIG_NOT_COHERENT_CACHE=y
+
+#
+# Platform options
+#
+# CONFIG_RPXLITE is not set
+CONFIG_RPXCLASSIC=y
+# CONFIG_BSEIP is not set
+# CONFIG_FADS is not set
+# CONFIG_TQM823L is not set
+# CONFIG_TQM850L is not set
+# CONFIG_TQM855L is not set
+# CONFIG_TQM860L is not set
+# CONFIG_FPS850L is not set
+# CONFIG_SPD823TS is not set
+# CONFIG_IVMS8 is not set
+# CONFIG_IVML24 is not set
+# CONFIG_SM850 is not set
+# CONFIG_HERMES_PRO is not set
+# CONFIG_IP860 is not set
+# CONFIG_LWMON is not set
+# CONFIG_PCU_E is not set
+# CONFIG_CCM is not set
+# CONFIG_LANTEC is not set
+# CONFIG_MBX is not set
+# CONFIG_WINCEPT is not set
+# CONFIG_SMP is not set
+# CONFIG_PREEMPT is not set
+# CONFIG_HIGHMEM is not set
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+# CONFIG_CMDLINE_BOOL is not set
+
+#
+# Bus options
+#
+# CONFIG_PCI is not set
+# CONFIG_PCI_DOMAINS is not set
+# CONFIG_PCI_QSPAN is not set
+
+#
+# Advanced setup
+#
+# CONFIG_ADVANCED_OPTIONS is not set
+
+#
+# Default settings for advanced configuration options are used
+#
+CONFIG_HIGHMEM_START=0xfe000000
+CONFIG_LOWMEM_SIZE=0x30000000
+CONFIG_KERNEL_START=0xc0000000
+CONFIG_TASK_SIZE=0x80000000
+CONFIG_CONSISTENT_START=0xff100000
+CONFIG_CONSISTENT_SIZE=0x00200000
+CONFIG_BOOT_LOAD=0x00400000
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=4096
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_LBD is not set
+# CONFIG_CDROM_PKTCDVD is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_SCSI is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+
+#
+# Macintosh device drivers
+#
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+# CONFIG_NETLINK_DEV is not set
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_PNP=y
+# CONFIG_IP_PNP_DHCP is not set
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_IP_MROUTE is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_TUNNEL is not set
+# CONFIG_IPV6 is not set
+# CONFIG_NETFILTER is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+# CONFIG_MII is not set
+# CONFIG_OAKNET is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+
+#
+# Ethernet (10000 Mbit)
+#
+
+#
+# Token Ring devices
+#
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+# CONFIG_INPUT is not set
+
+#
+# Userland interfaces
+#
+
+#
+# Input I/O drivers
+#
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+# CONFIG_SERIO is not set
+# CONFIG_SERIO_I8042 is not set
+
+#
+# Input Device Drivers
+#
+
+#
+# Character devices
+#
+# CONFIG_VT is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_SERIAL_CPM=y
+CONFIG_SERIAL_CPM_CONSOLE=y
+# CONFIG_SERIAL_CPM_SCC1 is not set
+CONFIG_SERIAL_CPM_SCC2=y
+CONFIG_SERIAL_CPM_SCC3=y
+# CONFIG_SERIAL_CPM_SCC4 is not set
+CONFIG_SERIAL_CPM_SMC1=y
+CONFIG_SERIAL_CPM_SMC2=y
+CONFIG_UNIX98_PTYS=y
+# CONFIG_LEGACY_PTYS is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_NVRAM is not set
+CONFIG_GEN_RTC=y
+# CONFIG_GEN_RTC_X is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
+# Misc devices
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+# CONFIG_FB is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+# CONFIG_USB_ARCH_HAS_HCD is not set
+# CONFIG_USB_ARCH_HAS_OHCI is not set
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_FS_XATTR=y
+# CONFIG_EXT3_FS_POSIX_ACL is not set
+# CONFIG_EXT3_FS_SECURITY is not set
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+CONFIG_FS_MBCACHE=y
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_SYSFS=y
+# CONFIG_DEVFS_FS is not set
+# CONFIG_DEVPTS_FS_XATTR is not set
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_XATTR is not set
+# CONFIG_HUGETLBFS is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+# CONFIG_NFS_V3 is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+# CONFIG_NFSD is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+# CONFIG_EXPORTFS is not set
+CONFIG_SUNRPC=y
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
+# CONFIG_MSDOS_PARTITION is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_EFI_PARTITION is not set
+
+#
+# Native Language Support
+#
+# CONFIG_NLS is not set
+
+#
+# MPC8xx CPM Options
+#
+CONFIG_SCC_ENET=y
+CONFIG_SCC1_ENET=y
+# CONFIG_SCC2_ENET is not set
+# CONFIG_SCC3_ENET is not set
+CONFIG_FEC_ENET=y
+# CONFIG_USE_MDIO is not set
+CONFIG_ENET_BIG_BUFFERS=y
+
+#
+# Generic MPC8xx Options
+#
+CONFIG_8xx_COPYBACK=y
+# CONFIG_8xx_CPU6 is not set
+CONFIG_NO_UCODE_PATCH=y
+# CONFIG_USB_SOF_UCODE_PATCH is not set
+# CONFIG_I2C_SPI_UCODE_PATCH is not set
+# CONFIG_I2C_SPI_SMC1_UCODE_PATCH is not set
+
+#
+# Library routines
+#
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC32 is not set
+# CONFIG_LIBCRC32C is not set
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_DEBUG_KERNEL is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
diff --git a/arch/ppc/configs/rpxlite_defconfig b/arch/ppc/configs/rpxlite_defconfig
new file mode 100644
index 0000000..828dd6e
--- /dev/null
+++ b/arch/ppc/configs/rpxlite_defconfig
@@ -0,0 +1,581 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.10-rc1
+# Mon Nov 1 16:41:09 2004
+#
+CONFIG_MMU=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_HAVE_DEC_LOCK=y
+CONFIG_PPC=y
+CONFIG_PPC32=y
+CONFIG_GENERIC_NVRAM=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+# CONFIG_CLEAN_COMPILE is not set
+CONFIG_BROKEN=y
+CONFIG_BROKEN_ON_SMP=y
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+# CONFIG_SWAP is not set
+CONFIG_SYSVIPC=y
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_HOTPLUG is not set
+# CONFIG_KOBJECT_UEVENT is not set
+# CONFIG_IKCONFIG is not set
+CONFIG_EMBEDDED=y
+# CONFIG_KALLSYMS is not set
+# CONFIG_FUTEX is not set
+# CONFIG_EPOLL is not set
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+# CONFIG_SHMEM is not set
+CONFIG_CC_ALIGN_FUNCTIONS=0
+CONFIG_CC_ALIGN_LABELS=0
+CONFIG_CC_ALIGN_LOOPS=0
+CONFIG_CC_ALIGN_JUMPS=0
+CONFIG_TINY_SHMEM=y
+
+#
+# Loadable module support
+#
+# CONFIG_MODULES is not set
+
+#
+# Processor
+#
+# CONFIG_6xx is not set
+# CONFIG_40x is not set
+# CONFIG_44x is not set
+# CONFIG_POWER3 is not set
+# CONFIG_POWER4 is not set
+CONFIG_8xx=y
+# CONFIG_E500 is not set
+CONFIG_MATH_EMULATION=y
+# CONFIG_CPU_FREQ is not set
+CONFIG_EMBEDDEDBOOT=y
+CONFIG_NOT_COHERENT_CACHE=y
+
+#
+# Platform options
+#
+CONFIG_RPXLITE=y
+# CONFIG_RPXCLASSIC is not set
+# CONFIG_BSEIP is not set
+# CONFIG_FADS is not set
+# CONFIG_TQM823L is not set
+# CONFIG_TQM850L is not set
+# CONFIG_TQM855L is not set
+# CONFIG_TQM860L is not set
+# CONFIG_FPS850L is not set
+# CONFIG_SPD823TS is not set
+# CONFIG_IVMS8 is not set
+# CONFIG_IVML24 is not set
+# CONFIG_SM850 is not set
+# CONFIG_HERMES_PRO is not set
+# CONFIG_IP860 is not set
+# CONFIG_LWMON is not set
+# CONFIG_PCU_E is not set
+# CONFIG_CCM is not set
+# CONFIG_LANTEC is not set
+# CONFIG_MBX is not set
+# CONFIG_WINCEPT is not set
+# CONFIG_SMP is not set
+# CONFIG_PREEMPT is not set
+# CONFIG_HIGHMEM is not set
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+# CONFIG_CMDLINE_BOOL is not set
+
+#
+# Bus options
+#
+# CONFIG_PCI is not set
+# CONFIG_PCI_DOMAINS is not set
+# CONFIG_PCI_QSPAN is not set
+
+#
+# Advanced setup
+#
+# CONFIG_ADVANCED_OPTIONS is not set
+
+#
+# Default settings for advanced configuration options are used
+#
+CONFIG_HIGHMEM_START=0xfe000000
+CONFIG_LOWMEM_SIZE=0x30000000
+CONFIG_KERNEL_START=0xc0000000
+CONFIG_TASK_SIZE=0x80000000
+CONFIG_CONSISTENT_START=0xff100000
+CONFIG_CONSISTENT_SIZE=0x00200000
+CONFIG_BOOT_LOAD=0x00400000
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=4096
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_LBD is not set
+# CONFIG_CDROM_PKTCDVD is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_SCSI is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+
+#
+# Macintosh device drivers
+#
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+# CONFIG_NETLINK_DEV is not set
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_PNP=y
+# CONFIG_IP_PNP_DHCP is not set
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_IP_MROUTE is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_TUNNEL is not set
+# CONFIG_IPV6 is not set
+# CONFIG_NETFILTER is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+# CONFIG_MII is not set
+# CONFIG_OAKNET is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+
+#
+# Ethernet (10000 Mbit)
+#
+
+#
+# Token Ring devices
+#
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+# CONFIG_INPUT is not set
+
+#
+# Userland interfaces
+#
+
+#
+# Input I/O drivers
+#
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+# CONFIG_SERIO is not set
+# CONFIG_SERIO_I8042 is not set
+
+#
+# Input Device Drivers
+#
+
+#
+# Character devices
+#
+# CONFIG_VT is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_SERIAL_CPM=y
+CONFIG_SERIAL_CPM_CONSOLE=y
+# CONFIG_SERIAL_CPM_SCC1 is not set
+# CONFIG_SERIAL_CPM_SCC2 is not set
+# CONFIG_SERIAL_CPM_SCC3 is not set
+# CONFIG_SERIAL_CPM_SCC4 is not set
+CONFIG_SERIAL_CPM_SMC1=y
+# CONFIG_SERIAL_CPM_SMC2 is not set
+CONFIG_UNIX98_PTYS=y
+# CONFIG_LEGACY_PTYS is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_NVRAM is not set
+CONFIG_GEN_RTC=y
+# CONFIG_GEN_RTC_X is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
+# Misc devices
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+# CONFIG_FB is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+# CONFIG_USB_ARCH_HAS_HCD is not set
+# CONFIG_USB_ARCH_HAS_OHCI is not set
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_FS_XATTR=y
+# CONFIG_EXT3_FS_POSIX_ACL is not set
+# CONFIG_EXT3_FS_SECURITY is not set
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+CONFIG_FS_MBCACHE=y
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_SYSFS=y
+# CONFIG_DEVFS_FS is not set
+# CONFIG_DEVPTS_FS_XATTR is not set
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_XATTR is not set
+# CONFIG_HUGETLBFS is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+# CONFIG_NFS_V3 is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+# CONFIG_NFSD is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+# CONFIG_EXPORTFS is not set
+CONFIG_SUNRPC=y
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
+# CONFIG_MSDOS_PARTITION is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_EFI_PARTITION is not set
+
+#
+# Native Language Support
+#
+# CONFIG_NLS is not set
+
+#
+# MPC8xx CPM Options
+#
+CONFIG_SCC_ENET=y
+# CONFIG_SCC1_ENET is not set
+CONFIG_SCC2_ENET=y
+# CONFIG_SCC3_ENET is not set
+# CONFIG_FEC_ENET is not set
+# CONFIG_ENET_BIG_BUFFERS is not set
+
+#
+# Generic MPC8xx Options
+#
+CONFIG_8xx_COPYBACK=y
+# CONFIG_8xx_CPU6 is not set
+CONFIG_NO_UCODE_PATCH=y
+# CONFIG_USB_SOF_UCODE_PATCH is not set
+# CONFIG_I2C_SPI_UCODE_PATCH is not set
+# CONFIG_I2C_SPI_SMC1_UCODE_PATCH is not set
+
+#
+# Library routines
+#
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC32 is not set
+# CONFIG_LIBCRC32C is not set
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_DEBUG_KERNEL is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
diff --git a/arch/ppc/configs/sandpoint_defconfig b/arch/ppc/configs/sandpoint_defconfig
new file mode 100644
index 0000000..0f4393a
--- /dev/null
+++ b/arch/ppc/configs/sandpoint_defconfig
@@ -0,0 +1,737 @@
+#
+# Automatically generated make config: don't edit
+#
+CONFIG_MMU=y
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_HAVE_DEC_LOCK=y
+CONFIG_PPC=y
+CONFIG_PPC32=y
+CONFIG_GENERIC_NVRAM=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=y
+CONFIG_STANDALONE=y
+CONFIG_BROKEN_ON_SMP=y
+
+#
+# General setup
+#
+# CONFIG_SWAP is not set
+CONFIG_SYSVIPC=y
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_HOTPLUG=y
+# CONFIG_IKCONFIG is not set
+CONFIG_EMBEDDED=y
+CONFIG_KALLSYMS=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_OBSOLETE_MODPARM=y
+# CONFIG_MODVERSIONS is not set
+CONFIG_KMOD=y
+
+#
+# Processor
+#
+CONFIG_6xx=y
+# CONFIG_40x is not set
+# CONFIG_44x is not set
+# CONFIG_POWER3 is not set
+# CONFIG_POWER4 is not set
+# CONFIG_8xx is not set
+CONFIG_ALTIVEC=y
+# CONFIG_TAU is not set
+# CONFIG_CPU_FREQ is not set
+CONFIG_PPC_STD_MMU=y
+
+#
+# Platform options
+#
+# CONFIG_PPC_MULTIPLATFORM is not set
+# CONFIG_APUS is not set
+# CONFIG_WILLOW is not set
+# CONFIG_PCORE is not set
+# CONFIG_POWERPMC250 is not set
+# CONFIG_EV64260 is not set
+# CONFIG_SPRUCE is not set
+# CONFIG_LOPEC is not set
+# CONFIG_MCPN765 is not set
+# CONFIG_MVME5100 is not set
+# CONFIG_PPLUS is not set
+# CONFIG_PRPMC750 is not set
+# CONFIG_PRPMC800 is not set
+CONFIG_SANDPOINT=y
+# CONFIG_ADIR is not set
+# CONFIG_K2 is not set
+# CONFIG_PAL4 is not set
+# CONFIG_GEMINI is not set
+# CONFIG_EST8260 is not set
+# CONFIG_SBS8260 is not set
+# CONFIG_RPX6 is not set
+# CONFIG_TQM8260 is not set
+CONFIG_PPC_GEN550=y
+CONFIG_EPIC_SERIAL_MODE=y
+CONFIG_MPC10X_BRIDGE=y
+# CONFIG_MPC10X_STORE_GATHERING is not set
+# CONFIG_SMP is not set
+# CONFIG_PREEMPT is not set
+# CONFIG_HIGHMEM is not set
+CONFIG_KERNEL_ELF=y
+CONFIG_BINFMT_ELF=y
+CONFIG_BINFMT_MISC=m
+CONFIG_CMDLINE_BOOL=y
+CONFIG_CMDLINE="ip=on"
+
+#
+# Bus options
+#
+CONFIG_GENERIC_ISA_DMA=y
+CONFIG_PCI=y
+CONFIG_PCI_DOMAINS=y
+# CONFIG_PCI_LEGACY_PROC is not set
+# CONFIG_PCI_NAMES is not set
+
+#
+# PCMCIA/CardBus support
+#
+# CONFIG_PCMCIA is not set
+
+#
+# Advanced setup
+#
+# CONFIG_ADVANCED_OPTIONS is not set
+
+#
+# Default settings for advanced configuration options are used
+#
+CONFIG_HIGHMEM_START=0xfe000000
+CONFIG_LOWMEM_SIZE=0x30000000
+CONFIG_KERNEL_START=0xc0000000
+CONFIG_TASK_SIZE=0x80000000
+CONFIG_BOOT_LOAD=0x00800000
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+# CONFIG_FW_LOADER is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_CARMEL is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=4096
+CONFIG_BLK_DEV_INITRD=y
+# CONFIG_LBD is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+CONFIG_IDE=y
+CONFIG_BLK_DEV_IDE=y
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+CONFIG_BLK_DEV_IDEDISK=y
+# CONFIG_IDEDISK_MULTI_MODE is not set
+# CONFIG_IDEDISK_STROKE is not set
+CONFIG_BLK_DEV_IDECD=y
+# CONFIG_BLK_DEV_IDETAPE is not set
+# CONFIG_BLK_DEV_IDEFLOPPY is not set
+# CONFIG_IDE_TASK_IOCTL is not set
+CONFIG_IDE_TASKFILE_IO=y
+
+#
+# IDE chipset support/bugfixes
+#
+CONFIG_IDE_GENERIC=y
+# CONFIG_BLK_DEV_IDEPCI is not set
+# CONFIG_BLK_DEV_IDEDMA is not set
+# CONFIG_IDEDMA_AUTO is not set
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# SCSI device support
+#
+# CONFIG_SCSI is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# Macintosh device drivers
+#
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+# CONFIG_NETLINK_DEV is not set
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_PNP=y
+# CONFIG_IP_PNP_DHCP is not set
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_IP_MROUTE is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_IPV6 is not set
+# CONFIG_NETFILTER is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_HW_FLOWCONTROL is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+CONFIG_NETDEVICES=y
+CONFIG_DUMMY=m
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_OAKNET is not set
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+CONFIG_NET_VENDOR_3COM=y
+CONFIG_VORTEX=y
+# CONFIG_TYPHOON is not set
+
+#
+# Tulip family network device support
+#
+CONFIG_NET_TULIP=y
+# CONFIG_DE2104X is not set
+CONFIG_TULIP=y
+# CONFIG_TULIP_MWI is not set
+# CONFIG_TULIP_MMIO is not set
+# CONFIG_TULIP_NAPI is not set
+# CONFIG_DE4X5 is not set
+# CONFIG_WINBOND_840 is not set
+# CONFIG_DM9102 is not set
+# CONFIG_HP100 is not set
+CONFIG_NET_PCI=y
+# CONFIG_PCNET32 is not set
+# CONFIG_AMD8111_ETH is not set
+# CONFIG_ADAPTEC_STARFIRE is not set
+# CONFIG_B44 is not set
+# CONFIG_FORCEDETH is not set
+# CONFIG_DGRS is not set
+# CONFIG_EEPRO100 is not set
+CONFIG_E100=y
+# CONFIG_E100_NAPI is not set
+# CONFIG_FEALNX is not set
+# CONFIG_NATSEMI is not set
+# CONFIG_NE2K_PCI is not set
+# CONFIG_8139CP is not set
+CONFIG_8139TOO=y
+CONFIG_8139TOO_PIO=y
+# CONFIG_8139TOO_TUNE_TWISTER is not set
+# CONFIG_8139TOO_8129 is not set
+# CONFIG_8139_OLD_RX_RESET is not set
+# CONFIG_SIS900 is not set
+# CONFIG_EPIC100 is not set
+# CONFIG_SUNDANCE is not set
+# CONFIG_TLAN is not set
+# CONFIG_VIA_RHINE is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_E1000 is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_TIGON3 is not set
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_IXGB is not set
+# CONFIG_S2IO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+CONFIG_PPP=m
+# CONFIG_PPP_MULTILINK is not set
+# CONFIG_PPP_FILTER is not set
+CONFIG_PPP_ASYNC=m
+CONFIG_PPP_SYNC_TTY=m
+CONFIG_PPP_DEFLATE=m
+CONFIG_PPP_BSDCOMP=m
+# CONFIG_PPPOE is not set
+# CONFIG_SLIP is not set
+# CONFIG_RCPCI is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+# CONFIG_INPUT is not set
+
+#
+# Userland interfaces
+#
+
+#
+# Input I/O drivers
+#
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+# CONFIG_SERIO is not set
+# CONFIG_SERIO_I8042 is not set
+
+#
+# Input Device Drivers
+#
+
+#
+# Character devices
+#
+# CONFIG_VT is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=2
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_QIC02_TAPE is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_NVRAM is not set
+CONFIG_GEN_RTC=y
+# CONFIG_GEN_RTC_X is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_FTAPE is not set
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# Misc devices
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+# CONFIG_FB is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+CONFIG_USB=y
+# CONFIG_USB_DEBUG is not set
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEVICEFS=y
+# CONFIG_USB_BANDWIDTH is not set
+# CONFIG_USB_DYNAMIC_MINORS is not set
+
+#
+# USB Host Controller Drivers
+#
+# CONFIG_USB_EHCI_HCD is not set
+CONFIG_USB_OHCI_HCD=y
+# CONFIG_USB_UHCI_HCD is not set
+
+#
+# USB Device Class drivers
+#
+# CONFIG_USB_BLUETOOTH_TTY is not set
+CONFIG_USB_ACM=m
+# CONFIG_USB_PRINTER is not set
+# CONFIG_USB_STORAGE is not set
+
+#
+# USB Human Interface Devices (HID)
+#
+# CONFIG_USB_HID is not set
+
+#
+# Input core support is needed for USB HID input layer or HIDBP support
+#
+
+#
+# USB HID Boot Protocol drivers
+#
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+
+#
+# USB Multimedia devices
+#
+# CONFIG_USB_DABUSB is not set
+
+#
+# Video4Linux support is needed for USB Multimedia device support
+#
+
+#
+# USB Network adaptors
+#
+# CONFIG_USB_CATC is not set
+# CONFIG_USB_KAWETH is not set
+# CONFIG_USB_PEGASUS is not set
+# CONFIG_USB_RTL8150 is not set
+# CONFIG_USB_USBNET is not set
+
+#
+# USB port drivers
+#
+
+#
+# USB Serial Converter support
+#
+CONFIG_USB_SERIAL=m
+# CONFIG_USB_SERIAL_GENERIC is not set
+# CONFIG_USB_SERIAL_BELKIN is not set
+# CONFIG_USB_SERIAL_WHITEHEAT is not set
+# CONFIG_USB_SERIAL_DIGI_ACCELEPORT is not set
+# CONFIG_USB_SERIAL_EMPEG is not set
+# CONFIG_USB_SERIAL_FTDI_SIO is not set
+CONFIG_USB_SERIAL_VISOR=m
+# CONFIG_USB_SERIAL_IPAQ is not set
+# CONFIG_USB_SERIAL_IR is not set
+# CONFIG_USB_SERIAL_EDGEPORT is not set
+# CONFIG_USB_SERIAL_EDGEPORT_TI is not set
+# CONFIG_USB_SERIAL_KEYSPAN_PDA is not set
+# CONFIG_USB_SERIAL_KEYSPAN is not set
+# CONFIG_USB_SERIAL_KLSI is not set
+# CONFIG_USB_SERIAL_KOBIL_SCT is not set
+# CONFIG_USB_SERIAL_MCT_U232 is not set
+# CONFIG_USB_SERIAL_PL2303 is not set
+# CONFIG_USB_SERIAL_SAFE is not set
+# CONFIG_USB_SERIAL_CYBERJACK is not set
+# CONFIG_USB_SERIAL_XIRCOM is not set
+# CONFIG_USB_SERIAL_OMNINET is not set
+
+#
+# USB Miscellaneous drivers
+#
+# CONFIG_USB_EMI62 is not set
+# CONFIG_USB_EMI26 is not set
+# CONFIG_USB_TIGL is not set
+# CONFIG_USB_AUERSWALD is not set
+# CONFIG_USB_RIO500 is not set
+# CONFIG_USB_LEGOTOWER is not set
+# CONFIG_USB_LCD is not set
+# CONFIG_USB_LED is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_PHIDGETSERVO is not set
+# CONFIG_USB_TEST is not set
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_FS_XATTR=y
+# CONFIG_EXT3_FS_POSIX_ACL is not set
+# CONFIG_EXT3_FS_SECURITY is not set
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+CONFIG_FS_MBCACHE=y
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+CONFIG_ISO9660_FS=y
+# CONFIG_JOLIET is not set
+# CONFIG_ZISOFS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_FAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_SYSFS=y
+# CONFIG_DEVFS_FS is not set
+# CONFIG_DEVPTS_FS_XATTR is not set
+CONFIG_TMPFS=y
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+# CONFIG_NFSD is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+# CONFIG_EXPORTFS is not set
+CONFIG_SUNRPC=y
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+# CONFIG_NLS is not set
+
+#
+# Library routines
+#
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=m
+CONFIG_ZLIB_DEFLATE=m
+
+#
+# Kernel hacking
+#
+# CONFIG_DEBUG_KERNEL is not set
+# CONFIG_SERIAL_TEXT_DEBUG is not set
+
+#
+# Security options
+#
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
diff --git a/arch/ppc/configs/spruce_defconfig b/arch/ppc/configs/spruce_defconfig
new file mode 100644
index 0000000..430dd9c
--- /dev/null
+++ b/arch/ppc/configs/spruce_defconfig
@@ -0,0 +1,577 @@
+#
+# Automatically generated make config: don't edit
+#
+CONFIG_MMU=y
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_HAVE_DEC_LOCK=y
+CONFIG_PPC=y
+CONFIG_PPC32=y
+CONFIG_GENERIC_NVRAM=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=y
+CONFIG_STANDALONE=y
+CONFIG_BROKEN_ON_SMP=y
+
+#
+# General setup
+#
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_POSIX_MQUEUE=y
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_HOTPLUG is not set
+# CONFIG_IKCONFIG is not set
+CONFIG_EMBEDDED=y
+CONFIG_KALLSYMS=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_OBSOLETE_MODPARM=y
+# CONFIG_MODVERSIONS is not set
+CONFIG_KMOD=y
+
+#
+# Processor
+#
+CONFIG_6xx=y
+# CONFIG_40x is not set
+# CONFIG_44x is not set
+# CONFIG_POWER3 is not set
+# CONFIG_POWER4 is not set
+# CONFIG_8xx is not set
+# CONFIG_ALTIVEC is not set
+# CONFIG_TAU is not set
+# CONFIG_CPU_FREQ is not set
+CONFIG_PPC_STD_MMU=y
+
+#
+# Platform options
+#
+# CONFIG_PPC_MULTIPLATFORM is not set
+# CONFIG_APUS is not set
+# CONFIG_WILLOW is not set
+# CONFIG_PCORE is not set
+# CONFIG_POWERPMC250 is not set
+# CONFIG_EV64260 is not set
+CONFIG_SPRUCE=y
+# CONFIG_LOPEC is not set
+# CONFIG_MCPN765 is not set
+# CONFIG_MVME5100 is not set
+# CONFIG_PPLUS is not set
+# CONFIG_PRPMC750 is not set
+# CONFIG_PRPMC800 is not set
+# CONFIG_SANDPOINT is not set
+# CONFIG_ADIR is not set
+# CONFIG_K2 is not set
+# CONFIG_PAL4 is not set
+# CONFIG_GEMINI is not set
+# CONFIG_EST8260 is not set
+# CONFIG_SBS8260 is not set
+# CONFIG_RPX6 is not set
+# CONFIG_TQM8260 is not set
+CONFIG_PPC_GEN550=y
+CONFIG_SPRUCE_BAUD_33M=y
+# CONFIG_SMP is not set
+# CONFIG_PREEMPT is not set
+# CONFIG_HIGHMEM is not set
+CONFIG_KERNEL_ELF=y
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+CONFIG_CMDLINE_BOOL=y
+CONFIG_CMDLINE="ip=on"
+
+#
+# Bus options
+#
+CONFIG_GENERIC_ISA_DMA=y
+CONFIG_PCI=y
+CONFIG_PCI_DOMAINS=y
+CONFIG_PCI_LEGACY_PROC=y
+# CONFIG_PCI_NAMES is not set
+
+#
+# Advanced setup
+#
+# CONFIG_ADVANCED_OPTIONS is not set
+
+#
+# Default settings for advanced configuration options are used
+#
+CONFIG_HIGHMEM_START=0xfe000000
+CONFIG_LOWMEM_SIZE=0x30000000
+CONFIG_KERNEL_START=0xc0000000
+CONFIG_TASK_SIZE=0x80000000
+CONFIG_BOOT_LOAD=0x00800000
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_CARMEL is not set
+# CONFIG_BLK_DEV_RAM is not set
+# CONFIG_LBD is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_SCSI is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# Macintosh device drivers
+#
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+# CONFIG_NETLINK_DEV is not set
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+# CONFIG_IP_PNP_BOOTP is not set
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_IPV6 is not set
+# CONFIG_NETFILTER is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_HW_FLOWCONTROL is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_OAKNET is not set
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_NET_VENDOR_3COM is not set
+
+#
+# Tulip family network device support
+#
+# CONFIG_NET_TULIP is not set
+# CONFIG_HP100 is not set
+CONFIG_NET_PCI=y
+CONFIG_PCNET32=y
+# CONFIG_AMD8111_ETH is not set
+# CONFIG_ADAPTEC_STARFIRE is not set
+# CONFIG_B44 is not set
+# CONFIG_FORCEDETH is not set
+# CONFIG_DGRS is not set
+# CONFIG_EEPRO100 is not set
+# CONFIG_E100 is not set
+# CONFIG_FEALNX is not set
+# CONFIG_NATSEMI is not set
+# CONFIG_NE2K_PCI is not set
+# CONFIG_8139CP is not set
+# CONFIG_8139TOO is not set
+# CONFIG_SIS900 is not set
+# CONFIG_EPIC100 is not set
+# CONFIG_SUNDANCE is not set
+# CONFIG_TLAN is not set
+# CONFIG_VIA_RHINE is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_E1000 is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_TIGON3 is not set
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_IXGB is not set
+# CONFIG_S2IO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_RCPCI is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+# CONFIG_INPUT is not set
+
+#
+# Userland interfaces
+#
+
+#
+# Input I/O drivers
+#
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+CONFIG_SERIO=y
+CONFIG_SERIO_I8042=y
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_CT82C710 is not set
+CONFIG_SERIO_PCIPS2=y
+
+#
+# Input Device Drivers
+#
+
+#
+# Character devices
+#
+# CONFIG_VT is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=2
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_QIC02_TAPE is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_NVRAM is not set
+CONFIG_GEN_RTC=y
+# CONFIG_GEN_RTC_X is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_FTAPE is not set
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# Misc devices
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+# CONFIG_FB is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+# CONFIG_USB is not set
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_FS_XATTR=y
+# CONFIG_EXT3_FS_POSIX_ACL is not set
+# CONFIG_EXT3_FS_SECURITY is not set
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+CONFIG_FS_MBCACHE=y
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+CONFIG_ISO9660_FS=y
+# CONFIG_JOLIET is not set
+# CONFIG_ZISOFS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_FAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_SYSFS=y
+# CONFIG_DEVFS_FS is not set
+# CONFIG_DEVPTS_FS_XATTR is not set
+CONFIG_TMPFS=y
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+# CONFIG_NFS_V3 is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+# CONFIG_NFSD is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+# CONFIG_EXPORTFS is not set
+CONFIG_SUNRPC=y
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+# CONFIG_NLS is not set
+
+#
+# Library routines
+#
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_DEBUG_KERNEL is not set
+# CONFIG_SERIAL_TEXT_DEBUG is not set
+
+#
+# Security options
+#
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
diff --git a/arch/ppc/configs/stx_gp3_defconfig b/arch/ppc/configs/stx_gp3_defconfig
new file mode 100644
index 0000000..66dae83
--- /dev/null
+++ b/arch/ppc/configs/stx_gp3_defconfig
@@ -0,0 +1,972 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.11-rc2
+# Wed Jan 26 14:32:58 2005
+#
+CONFIG_MMU=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_HAVE_DEC_LOCK=y
+CONFIG_PPC=y
+CONFIG_PPC32=y
+CONFIG_GENERIC_NVRAM=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=y
+CONFIG_BROKEN_ON_SMP=y
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_HOTPLUG=y
+CONFIG_KOBJECT_UEVENT=y
+# CONFIG_IKCONFIG is not set
+CONFIG_EMBEDDED=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SHMEM=y
+CONFIG_CC_ALIGN_FUNCTIONS=0
+CONFIG_CC_ALIGN_LABELS=0
+CONFIG_CC_ALIGN_LOOPS=0
+CONFIG_CC_ALIGN_JUMPS=0
+# CONFIG_TINY_SHMEM is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+# CONFIG_MODULE_UNLOAD is not set
+CONFIG_OBSOLETE_MODPARM=y
+CONFIG_MODVERSIONS=y
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_KMOD=y
+
+#
+# Processor
+#
+# CONFIG_6xx is not set
+# CONFIG_40x is not set
+# CONFIG_44x is not set
+# CONFIG_POWER3 is not set
+# CONFIG_POWER4 is not set
+# CONFIG_8xx is not set
+CONFIG_E500=y
+CONFIG_BOOKE=y
+CONFIG_FSL_BOOKE=y
+# CONFIG_SPE is not set
+CONFIG_MATH_EMULATION=y
+# CONFIG_CPU_FREQ is not set
+CONFIG_85xx=y
+CONFIG_PPC_INDIRECT_PCI_BE=y
+
+#
+# Freescale 85xx options
+#
+# CONFIG_MPC8540_ADS is not set
+# CONFIG_MPC8555_CDS is not set
+# CONFIG_MPC8560_ADS is not set
+# CONFIG_SBC8560 is not set
+CONFIG_STX_GP3=y
+CONFIG_MPC8560=y
+
+#
+# Platform options
+#
+CONFIG_CPM2=y
+# CONFIG_PC_KEYBOARD is not set
+# CONFIG_SMP is not set
+# CONFIG_PREEMPT is not set
+CONFIG_HIGHMEM=y
+CONFIG_BINFMT_ELF=y
+CONFIG_BINFMT_MISC=m
+# CONFIG_CMDLINE_BOOL is not set
+
+#
+# Bus options
+#
+CONFIG_PCI=y
+CONFIG_PCI_DOMAINS=y
+# CONFIG_PCI_LEGACY_PROC is not set
+# CONFIG_PCI_NAMES is not set
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# PC-card bridges
+#
+
+#
+# Advanced setup
+#
+# CONFIG_ADVANCED_OPTIONS is not set
+
+#
+# Default settings for advanced configuration options are used
+#
+CONFIG_HIGHMEM_START=0xfe000000
+CONFIG_LOWMEM_SIZE=0x30000000
+CONFIG_KERNEL_START=0xc0000000
+CONFIG_TASK_SIZE=0x80000000
+CONFIG_BOOT_LOAD=0x00800000
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+# CONFIG_DEBUG_DRIVER is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Parallel port support
+#
+CONFIG_PARPORT=m
+CONFIG_PARPORT_PC=m
+# CONFIG_PARPORT_PC_FIFO is not set
+# CONFIG_PARPORT_PC_SUPERIO is not set
+# CONFIG_PARPORT_OTHER is not set
+# CONFIG_PARPORT_1284 is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_PARIDE is not set
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=m
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+CONFIG_BLK_DEV_NBD=m
+# CONFIG_BLK_DEV_SX8 is not set
+CONFIG_BLK_DEV_RAM=m
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=4096
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_LBD is not set
+# CONFIG_CDROM_PKTCDVD is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+CONFIG_IDE=y
+CONFIG_BLK_DEV_IDE=y
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+# CONFIG_BLK_DEV_IDE_SATA is not set
+CONFIG_BLK_DEV_IDEDISK=y
+# CONFIG_IDEDISK_MULTI_MODE is not set
+CONFIG_BLK_DEV_IDECD=m
+# CONFIG_BLK_DEV_IDETAPE is not set
+# CONFIG_BLK_DEV_IDEFLOPPY is not set
+# CONFIG_BLK_DEV_IDESCSI is not set
+# CONFIG_IDE_TASK_IOCTL is not set
+
+#
+# IDE chipset support/bugfixes
+#
+CONFIG_IDE_GENERIC=y
+# CONFIG_BLK_DEV_IDEPCI is not set
+# CONFIG_IDE_ARM is not set
+# CONFIG_BLK_DEV_IDEDMA is not set
+# CONFIG_IDEDMA_AUTO is not set
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# SCSI device support
+#
+CONFIG_SCSI=m
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=m
+CONFIG_CHR_DEV_ST=m
+# CONFIG_CHR_DEV_OSST is not set
+CONFIG_BLK_DEV_SR=m
+# CONFIG_BLK_DEV_SR_VENDOR is not set
+CONFIG_CHR_DEV_SG=m
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+CONFIG_SCSI_MULTI_LUN=y
+CONFIG_SCSI_CONSTANTS=y
+# CONFIG_SCSI_LOGGING is not set
+
+#
+# SCSI Transport Attributes
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+
+#
+# SCSI low-level drivers
+#
+# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
+# CONFIG_SCSI_3W_9XXX is not set
+# CONFIG_SCSI_ACARD is not set
+# CONFIG_SCSI_AACRAID is not set
+# CONFIG_SCSI_AIC7XXX is not set
+# CONFIG_SCSI_AIC7XXX_OLD is not set
+# CONFIG_SCSI_AIC79XX is not set
+# CONFIG_SCSI_DPT_I2O is not set
+# CONFIG_MEGARAID_NEWGEN is not set
+# CONFIG_MEGARAID_LEGACY is not set
+# CONFIG_SCSI_SATA is not set
+# CONFIG_SCSI_BUSLOGIC is not set
+# CONFIG_SCSI_DMX3191D is not set
+# CONFIG_SCSI_EATA is not set
+# CONFIG_SCSI_EATA_PIO is not set
+# CONFIG_SCSI_FUTURE_DOMAIN is not set
+# CONFIG_SCSI_GDTH is not set
+# CONFIG_SCSI_IPS is not set
+# CONFIG_SCSI_INITIO is not set
+# CONFIG_SCSI_INIA100 is not set
+# CONFIG_SCSI_PPA is not set
+# CONFIG_SCSI_IMM is not set
+# CONFIG_SCSI_SYM53C8XX_2 is not set
+# CONFIG_SCSI_IPR is not set
+# CONFIG_SCSI_QLOGIC_ISP is not set
+# CONFIG_SCSI_QLOGIC_FC is not set
+# CONFIG_SCSI_QLOGIC_1280 is not set
+CONFIG_SCSI_QLA2XXX=m
+# CONFIG_SCSI_QLA21XX is not set
+# CONFIG_SCSI_QLA22XX is not set
+# CONFIG_SCSI_QLA2300 is not set
+# CONFIG_SCSI_QLA2322 is not set
+# CONFIG_SCSI_QLA6312 is not set
+# CONFIG_SCSI_DC395x is not set
+# CONFIG_SCSI_DC390T is not set
+# CONFIG_SCSI_NSP32 is not set
+# CONFIG_SCSI_DEBUG is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+# CONFIG_FUSION is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# Macintosh device drivers
+#
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+# CONFIG_NETLINK_DEV is not set
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_PNP=y
+# CONFIG_IP_PNP_DHCP is not set
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_IP_TCPDIAG=y
+# CONFIG_IP_TCPDIAG_IPV6 is not set
+
+#
+# IP: Virtual Server Configuration
+#
+# CONFIG_IP_VS is not set
+# CONFIG_IPV6 is not set
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+
+#
+# IP: Netfilter Configuration
+#
+CONFIG_IP_NF_CONNTRACK=m
+# CONFIG_IP_NF_CT_ACCT is not set
+# CONFIG_IP_NF_CONNTRACK_MARK is not set
+# CONFIG_IP_NF_CT_PROTO_SCTP is not set
+CONFIG_IP_NF_FTP=m
+CONFIG_IP_NF_IRC=m
+# CONFIG_IP_NF_TFTP is not set
+# CONFIG_IP_NF_AMANDA is not set
+# CONFIG_IP_NF_QUEUE is not set
+CONFIG_IP_NF_IPTABLES=m
+# CONFIG_IP_NF_MATCH_LIMIT is not set
+# CONFIG_IP_NF_MATCH_IPRANGE is not set
+# CONFIG_IP_NF_MATCH_MAC is not set
+# CONFIG_IP_NF_MATCH_PKTTYPE is not set
+# CONFIG_IP_NF_MATCH_MARK is not set
+# CONFIG_IP_NF_MATCH_MULTIPORT is not set
+# CONFIG_IP_NF_MATCH_TOS is not set
+# CONFIG_IP_NF_MATCH_RECENT is not set
+# CONFIG_IP_NF_MATCH_ECN is not set
+# CONFIG_IP_NF_MATCH_DSCP is not set
+# CONFIG_IP_NF_MATCH_AH_ESP is not set
+# CONFIG_IP_NF_MATCH_LENGTH is not set
+# CONFIG_IP_NF_MATCH_TTL is not set
+# CONFIG_IP_NF_MATCH_TCPMSS is not set
+# CONFIG_IP_NF_MATCH_HELPER is not set
+# CONFIG_IP_NF_MATCH_STATE is not set
+# CONFIG_IP_NF_MATCH_CONNTRACK is not set
+# CONFIG_IP_NF_MATCH_OWNER is not set
+# CONFIG_IP_NF_MATCH_ADDRTYPE is not set
+# CONFIG_IP_NF_MATCH_REALM is not set
+# CONFIG_IP_NF_MATCH_SCTP is not set
+# CONFIG_IP_NF_MATCH_COMMENT is not set
+# CONFIG_IP_NF_MATCH_HASHLIMIT is not set
+CONFIG_IP_NF_FILTER=m
+# CONFIG_IP_NF_TARGET_REJECT is not set
+# CONFIG_IP_NF_TARGET_LOG is not set
+# CONFIG_IP_NF_TARGET_ULOG is not set
+# CONFIG_IP_NF_TARGET_TCPMSS is not set
+CONFIG_IP_NF_NAT=m
+CONFIG_IP_NF_NAT_NEEDED=y
+CONFIG_IP_NF_TARGET_MASQUERADE=m
+CONFIG_IP_NF_TARGET_REDIRECT=m
+# CONFIG_IP_NF_TARGET_NETMAP is not set
+# CONFIG_IP_NF_TARGET_SAME is not set
+CONFIG_IP_NF_NAT_SNMP_BASIC=m
+CONFIG_IP_NF_NAT_IRC=m
+CONFIG_IP_NF_NAT_FTP=m
+# CONFIG_IP_NF_MANGLE is not set
+# CONFIG_IP_NF_RAW is not set
+# CONFIG_IP_NF_ARPTABLES is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+# CONFIG_MII is not set
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_NET_VENDOR_3COM is not set
+
+#
+# Tulip family network device support
+#
+# CONFIG_NET_TULIP is not set
+# CONFIG_HP100 is not set
+# CONFIG_NET_PCI is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_E1000 is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_TIGON3 is not set
+CONFIG_GIANFAR=y
+CONFIG_GFAR_NAPI=y
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_IXGB is not set
+# CONFIG_S2IO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_PLIP is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_NET_FC is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1280
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=1024
+CONFIG_INPUT_JOYDEV=m
+# CONFIG_INPUT_TSDEV is not set
+CONFIG_INPUT_EVDEV=m
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input I/O drivers
+#
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+CONFIG_SERIO=y
+CONFIG_SERIO_I8042=y
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_CT82C710 is not set
+# CONFIG_SERIO_PARKBD is not set
+# CONFIG_SERIO_PCIPS2 is not set
+CONFIG_SERIO_LIBPS2=y
+# CONFIG_SERIO_RAW is not set
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+CONFIG_KEYBOARD_ATKBD=y
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+CONFIG_INPUT_MOUSE=y
+CONFIG_MOUSE_PS2=y
+# CONFIG_MOUSE_SERIAL is not set
+# CONFIG_MOUSE_VSXXXAA is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Character devices
+#
+# CONFIG_VT is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_SERIAL_CPM=y
+CONFIG_SERIAL_CPM_CONSOLE=y
+# CONFIG_SERIAL_CPM_SCC1 is not set
+CONFIG_SERIAL_CPM_SCC2=y
+# CONFIG_SERIAL_CPM_SCC3 is not set
+# CONFIG_SERIAL_CPM_SCC4 is not set
+# CONFIG_SERIAL_CPM_SMC1 is not set
+# CONFIG_SERIAL_CPM_SMC2 is not set
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+CONFIG_PRINTER=m
+# CONFIG_LP_CONSOLE is not set
+# CONFIG_PPDEV is not set
+# CONFIG_TIPAR is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_NVRAM is not set
+# CONFIG_GEN_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+CONFIG_AGP=m
+CONFIG_DRM=m
+# CONFIG_DRM_TDFX is not set
+# CONFIG_DRM_R128 is not set
+# CONFIG_DRM_RADEON is not set
+# CONFIG_DRM_MGA is not set
+# CONFIG_DRM_SIS is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# I2C support
+#
+CONFIG_I2C=m
+CONFIG_I2C_CHARDEV=m
+
+#
+# I2C Algorithms
+#
+CONFIG_I2C_ALGOBIT=m
+# CONFIG_I2C_ALGOPCF is not set
+# CONFIG_I2C_ALGOPCA is not set
+
+#
+# I2C Hardware Bus support
+#
+# CONFIG_I2C_ALI1535 is not set
+# CONFIG_I2C_ALI1563 is not set
+# CONFIG_I2C_ALI15X3 is not set
+# CONFIG_I2C_AMD756 is not set
+# CONFIG_I2C_AMD8111 is not set
+# CONFIG_I2C_I801 is not set
+# CONFIG_I2C_I810 is not set
+# CONFIG_I2C_ISA is not set
+# CONFIG_I2C_MPC is not set
+# CONFIG_I2C_NFORCE2 is not set
+# CONFIG_I2C_PARPORT is not set
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_PIIX4 is not set
+# CONFIG_I2C_PROSAVAGE is not set
+# CONFIG_I2C_SAVAGE4 is not set
+# CONFIG_SCx200_ACB is not set
+# CONFIG_I2C_SIS5595 is not set
+# CONFIG_I2C_SIS630 is not set
+# CONFIG_I2C_SIS96X is not set
+# CONFIG_I2C_STUB is not set
+# CONFIG_I2C_VIA is not set
+# CONFIG_I2C_VIAPRO is not set
+# CONFIG_I2C_VOODOO3 is not set
+# CONFIG_I2C_PCA_ISA is not set
+
+#
+# Hardware Sensors Chip support
+#
+# CONFIG_I2C_SENSOR is not set
+# CONFIG_SENSORS_ADM1021 is not set
+# CONFIG_SENSORS_ADM1025 is not set
+# CONFIG_SENSORS_ADM1026 is not set
+# CONFIG_SENSORS_ADM1031 is not set
+# CONFIG_SENSORS_ASB100 is not set
+# CONFIG_SENSORS_DS1621 is not set
+# CONFIG_SENSORS_FSCHER is not set
+# CONFIG_SENSORS_GL518SM is not set
+# CONFIG_SENSORS_IT87 is not set
+# CONFIG_SENSORS_LM63 is not set
+# CONFIG_SENSORS_LM75 is not set
+# CONFIG_SENSORS_LM77 is not set
+# CONFIG_SENSORS_LM78 is not set
+# CONFIG_SENSORS_LM80 is not set
+# CONFIG_SENSORS_LM83 is not set
+# CONFIG_SENSORS_LM85 is not set
+# CONFIG_SENSORS_LM87 is not set
+# CONFIG_SENSORS_LM90 is not set
+# CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_PC87360 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_VIA686A is not set
+# CONFIG_SENSORS_W83781D is not set
+# CONFIG_SENSORS_W83L785TS is not set
+# CONFIG_SENSORS_W83627HF is not set
+
+#
+# Other I2C Chip support
+#
+# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_SENSORS_RTC8564 is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
+# Misc devices
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+# CONFIG_FB is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Sound
+#
+CONFIG_SOUND=m
+
+#
+# Advanced Linux Sound Architecture
+#
+# CONFIG_SND is not set
+
+#
+# Open Sound System
+#
+# CONFIG_SOUND_PRIME is not set
+
+#
+# USB support
+#
+# CONFIG_USB is not set
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# InfiniBand support
+#
+# CONFIG_INFINIBAND is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_FS_XATTR=y
+# CONFIG_EXT3_FS_POSIX_ACL is not set
+# CONFIG_EXT3_FS_SECURITY is not set
+CONFIG_JBD=y
+CONFIG_JBD_DEBUG=y
+CONFIG_FS_MBCACHE=y
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+CONFIG_AUTOFS_FS=m
+CONFIG_AUTOFS4_FS=y
+
+#
+# CD-ROM/DVD Filesystems
+#
+CONFIG_ISO9660_FS=m
+# CONFIG_JOLIET is not set
+# CONFIG_ZISOFS is not set
+CONFIG_UDF_FS=m
+CONFIG_UDF_NLS=y
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=m
+CONFIG_MSDOS_FS=m
+CONFIG_VFAT_FS=m
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+# CONFIG_PROC_KCORE is not set
+CONFIG_SYSFS=y
+CONFIG_DEVFS_FS=y
+# CONFIG_DEVFS_MOUNT is not set
+# CONFIG_DEVFS_DEBUG is not set
+# CONFIG_DEVPTS_FS_XATTR is not set
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_XATTR is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+CONFIG_CRAMFS=m
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+# CONFIG_NFSD is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+# CONFIG_EXPORTFS is not set
+CONFIG_SUNRPC=y
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+CONFIG_SMB_FS=m
+# CONFIG_SMB_NLS_DEFAULT is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+# CONFIG_NLS_CODEPAGE_437 is not set
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
+# CONFIG_NLS_ISO8859_1 is not set
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_UTF8 is not set
+# CONFIG_SCC_ENET is not set
+# CONFIG_FEC_ENET is not set
+
+#
+# CPM2 Options
+#
+
+#
+# Library routines
+#
+CONFIG_CRC_CCITT=y
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=m
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_DEBUG_SLAB is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_KOBJECT is not set
+# CONFIG_DEBUG_HIGHMEM is not set
+# CONFIG_DEBUG_INFO is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_KGDB_CONSOLE is not set
+# CONFIG_XMON is not set
+CONFIG_BDI_SWITCH=y
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Hardware crypto devices
+#
diff --git a/arch/ppc/configs/sycamore_defconfig b/arch/ppc/configs/sycamore_defconfig
new file mode 100644
index 0000000..758114c
--- /dev/null
+++ b/arch/ppc/configs/sycamore_defconfig
@@ -0,0 +1,664 @@
+#
+# Automatically generated make config: don't edit
+#
+CONFIG_MMU=y
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_HAVE_DEC_LOCK=y
+CONFIG_PPC=y
+CONFIG_PPC32=y
+CONFIG_GENERIC_NVRAM=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=y
+CONFIG_STANDALONE=y
+CONFIG_BROKEN_ON_SMP=y
+
+#
+# General setup
+#
+# CONFIG_SWAP is not set
+CONFIG_SYSVIPC=y
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_HOTPLUG is not set
+# CONFIG_IKCONFIG is not set
+CONFIG_EMBEDDED=y
+# CONFIG_KALLSYMS is not set
+CONFIG_FUTEX=y
+# CONFIG_EPOLL is not set
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_OBSOLETE_MODPARM=y
+CONFIG_MODVERSIONS=y
+CONFIG_KMOD=y
+
+#
+# Processor
+#
+# CONFIG_6xx is not set
+CONFIG_40x=y
+# CONFIG_44x is not set
+# CONFIG_POWER3 is not set
+# CONFIG_POWER4 is not set
+# CONFIG_8xx is not set
+# CONFIG_MATH_EMULATION is not set
+# CONFIG_CPU_FREQ is not set
+CONFIG_4xx=y
+
+#
+# IBM 4xx options
+#
+# CONFIG_ASH is not set
+# CONFIG_CPCI405 is not set
+# CONFIG_EP405 is not set
+# CONFIG_EVB405EP is not set
+# CONFIG_OAK is not set
+# CONFIG_REDWOOD_5 is not set
+# CONFIG_REDWOOD_6 is not set
+CONFIG_SYCAMORE=y
+# CONFIG_WALNUT is not set
+CONFIG_IBM_OCP=y
+CONFIG_PPC_OCP=y
+CONFIG_BIOS_FIXUP=y
+CONFIG_405GPR=y
+CONFIG_IBM_OPENBIOS=y
+# CONFIG_PM is not set
+CONFIG_UART0_TTYS0=y
+# CONFIG_UART0_TTYS1 is not set
+CONFIG_NOT_COHERENT_CACHE=y
+
+#
+# Platform options
+#
+# CONFIG_PC_KEYBOARD is not set
+# CONFIG_SMP is not set
+# CONFIG_PREEMPT is not set
+# CONFIG_HIGHMEM is not set
+CONFIG_KERNEL_ELF=y
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+CONFIG_CMDLINE_BOOL=y
+CONFIG_CMDLINE="ip=on"
+
+#
+# Bus options
+#
+CONFIG_PCI=y
+CONFIG_PCI_DOMAINS=y
+# CONFIG_PCI_LEGACY_PROC is not set
+# CONFIG_PCI_NAMES is not set
+
+#
+# Advanced setup
+#
+# CONFIG_ADVANCED_OPTIONS is not set
+
+#
+# Default settings for advanced configuration options are used
+#
+CONFIG_HIGHMEM_START=0xfe000000
+CONFIG_LOWMEM_SIZE=0x30000000
+CONFIG_KERNEL_START=0xc0000000
+CONFIG_TASK_SIZE=0x80000000
+CONFIG_BOOT_LOAD=0x00400000
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_CARMEL is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=4096
+CONFIG_BLK_DEV_INITRD=y
+# CONFIG_LBD is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_SCSI is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+# CONFIG_FUSION is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# Macintosh device drivers
+#
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+# CONFIG_PACKET is not set
+# CONFIG_NETLINK_DEV is not set
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_PNP=y
+# CONFIG_IP_PNP_DHCP is not set
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_IP_MROUTE is not set
+# CONFIG_ARPD is not set
+CONFIG_SYN_COOKIES=y
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_IPV6 is not set
+# CONFIG_DECNET is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_NETFILTER is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+# CONFIG_ATM is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_HW_FLOWCONTROL is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+CONFIG_NETDEVICES=y
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_OAKNET is not set
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_NET_VENDOR_3COM is not set
+
+#
+# Tulip family network device support
+#
+# CONFIG_NET_TULIP is not set
+# CONFIG_HP100 is not set
+# CONFIG_NET_PCI is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_E1000 is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
+# CONFIG_SIS190 is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_TIGON3 is not set
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_IXGB is not set
+CONFIG_IBM_EMAC=y
+# CONFIG_IBM_EMAC_ERRMSG is not set
+CONFIG_IBM_EMAC_RXB=64
+CONFIG_IBM_EMAC_TXB=8
+CONFIG_IBM_EMAC_FGAP=8
+CONFIG_IBM_EMAC_SKBRES=0
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+# CONFIG_RCPCI is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+
+#
+# Amateur Radio support
+#
+# CONFIG_HAMRADIO is not set
+
+#
+# IrDA (infrared) support
+#
+# CONFIG_IRDA is not set
+
+#
+# Bluetooth support
+#
+# CONFIG_BT is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input I/O drivers
+#
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+CONFIG_SERIO=y
+CONFIG_SERIO_I8042=y
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_CT82C710 is not set
+# CONFIG_SERIO_PCIPS2 is not set
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+CONFIG_KEYBOARD_ATKBD=y
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+CONFIG_INPUT_MOUSE=y
+CONFIG_MOUSE_PS2=y
+# CONFIG_MOUSE_SERIAL is not set
+# CONFIG_MOUSE_VSXXXAA is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Character devices
+#
+# CONFIG_VT is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=4
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_QIC02_TAPE is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_NVRAM is not set
+# CONFIG_GEN_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_FTAPE is not set
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# I2C support
+#
+CONFIG_I2C=y
+CONFIG_I2C_CHARDEV=y
+
+#
+# I2C Algorithms
+#
+# CONFIG_I2C_ALGOBIT is not set
+# CONFIG_I2C_ALGOPCF is not set
+
+#
+# I2C Hardware Bus support
+#
+# CONFIG_I2C_ALI1535 is not set
+# CONFIG_I2C_ALI15X3 is not set
+# CONFIG_I2C_AMD756 is not set
+# CONFIG_I2C_AMD8111 is not set
+# CONFIG_I2C_I801 is not set
+# CONFIG_I2C_I810 is not set
+# CONFIG_I2C_IBM_IIC is not set
+# CONFIG_I2C_ISA is not set
+# CONFIG_I2C_NFORCE2 is not set
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_PIIX4 is not set
+# CONFIG_I2C_PROSAVAGE is not set
+# CONFIG_I2C_SAVAGE4 is not set
+# CONFIG_SCx200_ACB is not set
+# CONFIG_I2C_SIS5595 is not set
+# CONFIG_I2C_SIS630 is not set
+# CONFIG_I2C_SIS96X is not set
+# CONFIG_I2C_VIA is not set
+# CONFIG_I2C_VIAPRO is not set
+# CONFIG_I2C_VOODOO3 is not set
+
+#
+# Hardware Sensors Chip support
+#
+# CONFIG_I2C_SENSOR is not set
+# CONFIG_SENSORS_ADM1021 is not set
+# CONFIG_SENSORS_ASB100 is not set
+# CONFIG_SENSORS_DS1621 is not set
+# CONFIG_SENSORS_FSCHER is not set
+# CONFIG_SENSORS_GL518SM is not set
+# CONFIG_SENSORS_IT87 is not set
+# CONFIG_SENSORS_LM75 is not set
+# CONFIG_SENSORS_LM78 is not set
+# CONFIG_SENSORS_LM80 is not set
+# CONFIG_SENSORS_LM83 is not set
+# CONFIG_SENSORS_LM85 is not set
+# CONFIG_SENSORS_LM90 is not set
+# CONFIG_SENSORS_VIA686A is not set
+# CONFIG_SENSORS_W83781D is not set
+# CONFIG_SENSORS_W83L785TS is not set
+# CONFIG_SENSORS_W83627HF is not set
+
+#
+# Other I2C Chip support
+#
+# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+
+#
+# Misc devices
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+# CONFIG_FB is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+# CONFIG_USB is not set
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_JBD is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_FAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+# CONFIG_DEVFS_FS is not set
+# CONFIG_DEVPTS_FS_XATTR is not set
+CONFIG_TMPFS=y
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+# CONFIG_NFS_V3 is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+# CONFIG_NFSD is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+# CONFIG_EXPORTFS is not set
+CONFIG_SUNRPC=y
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_INTERMEZZO_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
+# CONFIG_MSDOS_PARTITION is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_NEC98_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_EFI_PARTITION is not set
+
+#
+# Native Language Support
+#
+# CONFIG_NLS is not set
+
+#
+# IBM 40x options
+#
+
+#
+# Library routines
+#
+CONFIG_CRC32=y
+
+#
+# Kernel hacking
+#
+# CONFIG_DEBUG_KERNEL is not set
+# CONFIG_SERIAL_TEXT_DEBUG is not set
+CONFIG_OCP=y
+
+#
+# Security options
+#
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
diff --git a/arch/ppc/configs/walnut_defconfig b/arch/ppc/configs/walnut_defconfig
new file mode 100644
index 0000000..bf9721a
--- /dev/null
+++ b/arch/ppc/configs/walnut_defconfig
@@ -0,0 +1,578 @@
+#
+# Automatically generated make config: don't edit
+#
+CONFIG_MMU=y
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_HAVE_DEC_LOCK=y
+CONFIG_PPC=y
+CONFIG_PPC32=y
+CONFIG_GENERIC_NVRAM=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=y
+# CONFIG_STANDALONE is not set
+CONFIG_BROKEN_ON_SMP=y
+
+#
+# General setup
+#
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_POSIX_MQUEUE=y
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_HOTPLUG is not set
+# CONFIG_IKCONFIG is not set
+CONFIG_EMBEDDED=y
+# CONFIG_KALLSYMS is not set
+CONFIG_FUTEX=y
+# CONFIG_EPOLL is not set
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_OBSOLETE_MODPARM=y
+# CONFIG_MODVERSIONS is not set
+CONFIG_KMOD=y
+
+#
+# Processor
+#
+# CONFIG_6xx is not set
+CONFIG_40x=y
+# CONFIG_44x is not set
+# CONFIG_POWER3 is not set
+# CONFIG_POWER4 is not set
+# CONFIG_8xx is not set
+# CONFIG_MATH_EMULATION is not set
+# CONFIG_CPU_FREQ is not set
+CONFIG_4xx=y
+
+#
+# IBM 4xx options
+#
+# CONFIG_ASH is not set
+# CONFIG_BUBINGA is not set
+# CONFIG_CPCI405 is not set
+# CONFIG_EP405 is not set
+# CONFIG_OAK is not set
+# CONFIG_REDWOOD_5 is not set
+# CONFIG_REDWOOD_6 is not set
+# CONFIG_SYCAMORE is not set
+CONFIG_WALNUT=y
+CONFIG_IBM405_ERR77=y
+CONFIG_IBM405_ERR51=y
+CONFIG_IBM_OCP=y
+CONFIG_BIOS_FIXUP=y
+CONFIG_405GP=y
+CONFIG_IBM_OPENBIOS=y
+# CONFIG_PM is not set
+CONFIG_UART0_TTYS0=y
+# CONFIG_UART0_TTYS1 is not set
+CONFIG_NOT_COHERENT_CACHE=y
+
+#
+# Platform options
+#
+# CONFIG_PC_KEYBOARD is not set
+# CONFIG_SMP is not set
+# CONFIG_PREEMPT is not set
+# CONFIG_HIGHMEM is not set
+CONFIG_KERNEL_ELF=y
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+CONFIG_CMDLINE_BOOL=y
+CONFIG_CMDLINE="ip=on"
+
+#
+# Bus options
+#
+CONFIG_PCI=y
+CONFIG_PCI_DOMAINS=y
+CONFIG_PCI_LEGACY_PROC=y
+# CONFIG_PCI_NAMES is not set
+
+#
+# Advanced setup
+#
+# CONFIG_ADVANCED_OPTIONS is not set
+
+#
+# Default settings for advanced configuration options are used
+#
+CONFIG_HIGHMEM_START=0xfe000000
+CONFIG_LOWMEM_SIZE=0x30000000
+CONFIG_KERNEL_START=0xc0000000
+CONFIG_TASK_SIZE=0x80000000
+CONFIG_BOOT_LOAD=0x00400000
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_CARMEL is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=4096
+CONFIG_BLK_DEV_INITRD=y
+# CONFIG_LBD is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_SCSI is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# Macintosh device drivers
+#
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+# CONFIG_PACKET is not set
+# CONFIG_NETLINK_DEV is not set
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_PNP=y
+# CONFIG_IP_PNP_DHCP is not set
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_IP_MROUTE is not set
+# CONFIG_ARPD is not set
+CONFIG_SYN_COOKIES=y
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_IPV6 is not set
+# CONFIG_NETFILTER is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_HW_FLOWCONTROL is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_OAKNET is not set
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_NET_VENDOR_3COM is not set
+
+#
+# Tulip family network device support
+#
+# CONFIG_NET_TULIP is not set
+# CONFIG_HP100 is not set
+# CONFIG_NET_PCI is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_E1000 is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_TIGON3 is not set
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_IXGB is not set
+# CONFIG_S2IO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_RCPCI is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input I/O drivers
+#
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+CONFIG_SERIO=y
+# CONFIG_SERIO_I8042 is not set
+# CONFIG_SERIO_SERPORT is not set
+# CONFIG_SERIO_CT82C710 is not set
+# CONFIG_SERIO_PCIPS2 is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Character devices
+#
+# CONFIG_VT is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=4
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_QIC02_TAPE is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_NVRAM is not set
+# CONFIG_GEN_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_FTAPE is not set
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# Misc devices
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+# CONFIG_FB is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+# CONFIG_USB is not set
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_JBD is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_FAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_SYSFS=y
+# CONFIG_DEVFS_FS is not set
+# CONFIG_DEVPTS_FS_XATTR is not set
+CONFIG_TMPFS=y
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+# CONFIG_NFS_V3 is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+# CONFIG_NFSD is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+# CONFIG_EXPORTFS is not set
+CONFIG_SUNRPC=y
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
+# CONFIG_MSDOS_PARTITION is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_NEC98_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_EFI_PARTITION is not set
+
+#
+# Native Language Support
+#
+# CONFIG_NLS is not set
+
+#
+# IBM 40x options
+#
+
+#
+# Library routines
+#
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_DEBUG_KERNEL is not set
+# CONFIG_SERIAL_TEXT_DEBUG is not set
+CONFIG_PPC_OCP=y
+
+#
+# Security options
+#
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
diff --git a/arch/ppc/kernel/Makefile b/arch/ppc/kernel/Makefile
new file mode 100644
index 0000000..86bc878
--- /dev/null
+++ b/arch/ppc/kernel/Makefile
@@ -0,0 +1,33 @@
+#
+# Makefile for the linux kernel.
+#
+
+extra-$(CONFIG_PPC_STD_MMU) := head.o
+extra-$(CONFIG_40x) := head_4xx.o
+extra-$(CONFIG_44x) := head_44x.o
+extra-$(CONFIG_FSL_BOOKE) := head_fsl_booke.o
+extra-$(CONFIG_8xx) := head_8xx.o
+extra-$(CONFIG_6xx) += idle_6xx.o
+extra-$(CONFIG_POWER4) += idle_power4.o
+extra-y += vmlinux.lds
+
+obj-y := entry.o traps.o irq.o idle.o time.o misc.o \
+ process.o signal.o ptrace.o align.o \
+ semaphore.o syscalls.o setup.o \
+ cputable.o ppc_htab.o perfmon.o
+obj-$(CONFIG_6xx) += l2cr.o cpu_setup_6xx.o
+obj-$(CONFIG_SOFTWARE_SUSPEND) += swsusp.o
+obj-$(CONFIG_POWER4) += cpu_setup_power4.o
+obj-$(CONFIG_MODULES) += module.o ppc_ksyms.o
+obj-$(CONFIG_NOT_COHERENT_CACHE) += dma-mapping.o
+obj-$(CONFIG_PCI) += pci.o
+obj-$(CONFIG_KGDB) += ppc-stub.o
+obj-$(CONFIG_SMP) += smp.o smp-tbsync.o
+obj-$(CONFIG_TAU) += temp.o
+obj-$(CONFIG_ALTIVEC) += vecemu.o vector.o
+obj-$(CONFIG_FSL_BOOKE) += perfmon_fsl_booke.o
+
+ifndef CONFIG_MATH_EMULATION
+obj-$(CONFIG_8xx) += softemu8xx.o
+endif
+
diff --git a/arch/ppc/kernel/align.c b/arch/ppc/kernel/align.c
new file mode 100644
index 0000000..79c9294
--- /dev/null
+++ b/arch/ppc/kernel/align.c
@@ -0,0 +1,398 @@
+/*
+ * align.c - handle alignment exceptions for the Power PC.
+ *
+ * Copyright (c) 1996 Paul Mackerras <paulus@cs.anu.edu.au>
+ * Copyright (c) 1998-1999 TiVo, Inc.
+ * PowerPC 403GCX modifications.
+ * Copyright (c) 1999 Grant Erickson <grant@lcse.umn.edu>
+ * PowerPC 403GCX/405GP modifications.
+ */
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <asm/ptrace.h>
+#include <asm/processor.h>
+#include <asm/uaccess.h>
+#include <asm/system.h>
+#include <asm/cache.h>
+
+struct aligninfo {
+ unsigned char len;
+ unsigned char flags;
+};
+
+#if defined(CONFIG_4xx) || defined(CONFIG_POWER4) || defined(CONFIG_BOOKE)
+#define OPCD(inst) (((inst) & 0xFC000000) >> 26)
+#define RS(inst) (((inst) & 0x03E00000) >> 21)
+#define RA(inst) (((inst) & 0x001F0000) >> 16)
+#define IS_XFORM(code) ((code) == 31)
+#endif
+
+#define INVALID { 0, 0 }
+
+#define LD 1 /* load */
+#define ST 2 /* store */
+#define SE 4 /* sign-extend value */
+#define F 8 /* to/from fp regs */
+#define U 0x10 /* update index register */
+#define M 0x20 /* multiple load/store */
+#define S 0x40 /* single-precision fp, or byte-swap value */
+#define SX 0x40 /* byte count in XER */
+#define HARD 0x80 /* string, stwcx. */
+
+#define DCBZ 0x5f /* 8xx/82xx dcbz faults when cache not enabled */
+
+/*
+ * The PowerPC stores certain bits of the instruction that caused the
+ * alignment exception in the DSISR register. This array maps those
+ * bits to information about the operand length and what the
+ * instruction would do.
+ */
+static struct aligninfo aligninfo[128] = {
+ { 4, LD }, /* 00 0 0000: lwz / lwarx */
+ INVALID, /* 00 0 0001 */
+ { 4, ST }, /* 00 0 0010: stw */
+ INVALID, /* 00 0 0011 */
+ { 2, LD }, /* 00 0 0100: lhz */
+ { 2, LD+SE }, /* 00 0 0101: lha */
+ { 2, ST }, /* 00 0 0110: sth */
+ { 4, LD+M }, /* 00 0 0111: lmw */
+ { 4, LD+F+S }, /* 00 0 1000: lfs */
+ { 8, LD+F }, /* 00 0 1001: lfd */
+ { 4, ST+F+S }, /* 00 0 1010: stfs */
+ { 8, ST+F }, /* 00 0 1011: stfd */
+ INVALID, /* 00 0 1100 */
+ INVALID, /* 00 0 1101: ld/ldu/lwa */
+ INVALID, /* 00 0 1110 */
+ INVALID, /* 00 0 1111: std/stdu */
+ { 4, LD+U }, /* 00 1 0000: lwzu */
+ INVALID, /* 00 1 0001 */
+ { 4, ST+U }, /* 00 1 0010: stwu */
+ INVALID, /* 00 1 0011 */
+ { 2, LD+U }, /* 00 1 0100: lhzu */
+ { 2, LD+SE+U }, /* 00 1 0101: lhau */
+ { 2, ST+U }, /* 00 1 0110: sthu */
+ { 4, ST+M }, /* 00 1 0111: stmw */
+ { 4, LD+F+S+U }, /* 00 1 1000: lfsu */
+ { 8, LD+F+U }, /* 00 1 1001: lfdu */
+ { 4, ST+F+S+U }, /* 00 1 1010: stfsu */
+ { 8, ST+F+U }, /* 00 1 1011: stfdu */
+ INVALID, /* 00 1 1100 */
+ INVALID, /* 00 1 1101 */
+ INVALID, /* 00 1 1110 */
+ INVALID, /* 00 1 1111 */
+ INVALID, /* 01 0 0000: ldx */
+ INVALID, /* 01 0 0001 */
+ INVALID, /* 01 0 0010: stdx */
+ INVALID, /* 01 0 0011 */
+ INVALID, /* 01 0 0100 */
+ INVALID, /* 01 0 0101: lwax */
+ INVALID, /* 01 0 0110 */
+ INVALID, /* 01 0 0111 */
+ { 4, LD+M+HARD+SX }, /* 01 0 1000: lswx */
+ { 4, LD+M+HARD }, /* 01 0 1001: lswi */
+ { 4, ST+M+HARD+SX }, /* 01 0 1010: stswx */
+ { 4, ST+M+HARD }, /* 01 0 1011: stswi */
+ INVALID, /* 01 0 1100 */
+ INVALID, /* 01 0 1101 */
+ INVALID, /* 01 0 1110 */
+ INVALID, /* 01 0 1111 */
+ INVALID, /* 01 1 0000: ldux */
+ INVALID, /* 01 1 0001 */
+ INVALID, /* 01 1 0010: stdux */
+ INVALID, /* 01 1 0011 */
+ INVALID, /* 01 1 0100 */
+ INVALID, /* 01 1 0101: lwaux */
+ INVALID, /* 01 1 0110 */
+ INVALID, /* 01 1 0111 */
+ INVALID, /* 01 1 1000 */
+ INVALID, /* 01 1 1001 */
+ INVALID, /* 01 1 1010 */
+ INVALID, /* 01 1 1011 */
+ INVALID, /* 01 1 1100 */
+ INVALID, /* 01 1 1101 */
+ INVALID, /* 01 1 1110 */
+ INVALID, /* 01 1 1111 */
+ INVALID, /* 10 0 0000 */
+ INVALID, /* 10 0 0001 */
+ { 0, ST+HARD }, /* 10 0 0010: stwcx. */
+ INVALID, /* 10 0 0011 */
+ INVALID, /* 10 0 0100 */
+ INVALID, /* 10 0 0101 */
+ INVALID, /* 10 0 0110 */
+ INVALID, /* 10 0 0111 */
+ { 4, LD+S }, /* 10 0 1000: lwbrx */
+ INVALID, /* 10 0 1001 */
+ { 4, ST+S }, /* 10 0 1010: stwbrx */
+ INVALID, /* 10 0 1011 */
+ { 2, LD+S }, /* 10 0 1100: lhbrx */
+ INVALID, /* 10 0 1101 */
+ { 2, ST+S }, /* 10 0 1110: sthbrx */
+ INVALID, /* 10 0 1111 */
+ INVALID, /* 10 1 0000 */
+ INVALID, /* 10 1 0001 */
+ INVALID, /* 10 1 0010 */
+ INVALID, /* 10 1 0011 */
+ INVALID, /* 10 1 0100 */
+ INVALID, /* 10 1 0101 */
+ INVALID, /* 10 1 0110 */
+ INVALID, /* 10 1 0111 */
+ INVALID, /* 10 1 1000 */
+ INVALID, /* 10 1 1001 */
+ INVALID, /* 10 1 1010 */
+ INVALID, /* 10 1 1011 */
+ INVALID, /* 10 1 1100 */
+ INVALID, /* 10 1 1101 */
+ INVALID, /* 10 1 1110 */
+ { 0, ST+HARD }, /* 10 1 1111: dcbz */
+ { 4, LD }, /* 11 0 0000: lwzx */
+ INVALID, /* 11 0 0001 */
+ { 4, ST }, /* 11 0 0010: stwx */
+ INVALID, /* 11 0 0011 */
+ { 2, LD }, /* 11 0 0100: lhzx */
+ { 2, LD+SE }, /* 11 0 0101: lhax */
+ { 2, ST }, /* 11 0 0110: sthx */
+ INVALID, /* 11 0 0111 */
+ { 4, LD+F+S }, /* 11 0 1000: lfsx */
+ { 8, LD+F }, /* 11 0 1001: lfdx */
+ { 4, ST+F+S }, /* 11 0 1010: stfsx */
+ { 8, ST+F }, /* 11 0 1011: stfdx */
+ INVALID, /* 11 0 1100 */
+ INVALID, /* 11 0 1101: lmd */
+ INVALID, /* 11 0 1110 */
+ INVALID, /* 11 0 1111: stmd */
+ { 4, LD+U }, /* 11 1 0000: lwzux */
+ INVALID, /* 11 1 0001 */
+ { 4, ST+U }, /* 11 1 0010: stwux */
+ INVALID, /* 11 1 0011 */
+ { 2, LD+U }, /* 11 1 0100: lhzux */
+ { 2, LD+SE+U }, /* 11 1 0101: lhaux */
+ { 2, ST+U }, /* 11 1 0110: sthux */
+ INVALID, /* 11 1 0111 */
+ { 4, LD+F+S+U }, /* 11 1 1000: lfsux */
+ { 8, LD+F+U }, /* 11 1 1001: lfdux */
+ { 4, ST+F+S+U }, /* 11 1 1010: stfsux */
+ { 8, ST+F+U }, /* 11 1 1011: stfdux */
+ INVALID, /* 11 1 1100 */
+ INVALID, /* 11 1 1101 */
+ INVALID, /* 11 1 1110 */
+ INVALID, /* 11 1 1111 */
+};
+
+#define SWAP(a, b) (t = (a), (a) = (b), (b) = t)
+
+int
+fix_alignment(struct pt_regs *regs)
+{
+ int instr, nb, flags;
+#if defined(CONFIG_4xx) || defined(CONFIG_POWER4) || defined(CONFIG_BOOKE)
+ int opcode, f1, f2, f3;
+#endif
+ int i, t;
+ int reg, areg;
+ int offset, nb0;
+ unsigned char __user *addr;
+ unsigned char *rptr;
+ union {
+ long l;
+ float f;
+ double d;
+ unsigned char v[8];
+ } data;
+
+ CHECK_FULL_REGS(regs);
+
+#if defined(CONFIG_4xx) || defined(CONFIG_POWER4) || defined(CONFIG_BOOKE)
+ /* The 4xx-family & Book-E processors have no DSISR register,
+ * so we emulate it.
+ * The POWER4 has a DSISR register but doesn't set it on
+ * an alignment fault. -- paulus
+ */
+
+ if (__get_user(instr, (unsigned int __user *) regs->nip))
+ return 0;
+ opcode = OPCD(instr);
+ reg = RS(instr);
+ areg = RA(instr);
+
+ if (!IS_XFORM(opcode)) {
+ f1 = 0;
+ f2 = (instr & 0x04000000) >> 26;
+ f3 = (instr & 0x78000000) >> 27;
+ } else {
+ f1 = (instr & 0x00000006) >> 1;
+ f2 = (instr & 0x00000040) >> 6;
+ f3 = (instr & 0x00000780) >> 7;
+ }
+
+ instr = ((f1 << 5) | (f2 << 4) | f3);
+#else
+ reg = (regs->dsisr >> 5) & 0x1f; /* source/dest register */
+ areg = regs->dsisr & 0x1f; /* register to update */
+ instr = (regs->dsisr >> 10) & 0x7f;
+#endif
+
+ nb = aligninfo[instr].len;
+ if (nb == 0) {
+ long __user *p;
+ int i;
+
+ if (instr != DCBZ)
+ return 0; /* too hard or invalid instruction */
+ /*
+ * The dcbz (data cache block zero) instruction
+ * gives an alignment fault if used on non-cacheable
+ * memory. We handle the fault mainly for the
+ * case when we are running with the cache disabled
+ * for debugging.
+ */
+ p = (long __user *) (regs->dar & -L1_CACHE_BYTES);
+ if (user_mode(regs)
+ && !access_ok(VERIFY_WRITE, p, L1_CACHE_BYTES))
+ return -EFAULT;
+ for (i = 0; i < L1_CACHE_BYTES / sizeof(long); ++i)
+ if (__put_user(0, p+i))
+ return -EFAULT;
+ return 1;
+ }
+
+ flags = aligninfo[instr].flags;
+ if ((flags & (LD|ST)) == 0)
+ return 0;
+
+ /* For the 4xx-family & Book-E processors, the 'dar' field of the
+ * pt_regs structure is overloaded and is really from the DEAR.
+ */
+
+ addr = (unsigned char __user *)regs->dar;
+
+ if (flags & M) {
+ /* lmw, stmw, lswi/x, stswi/x */
+ nb0 = 0;
+ if (flags & HARD) {
+ if (flags & SX) {
+ nb = regs->xer & 127;
+ if (nb == 0)
+ return 1;
+ } else {
+ if (__get_user(instr,
+ (unsigned int __user *)regs->nip))
+ return 0;
+ nb = (instr >> 11) & 0x1f;
+ if (nb == 0)
+ nb = 32;
+ }
+ if (nb + reg * 4 > 128) {
+ nb0 = nb + reg * 4 - 128;
+ nb = 128 - reg * 4;
+ }
+ } else {
+ /* lwm, stmw */
+ nb = (32 - reg) * 4;
+ }
+ rptr = (unsigned char *) ®s->gpr[reg];
+ if (flags & LD) {
+ for (i = 0; i < nb; ++i)
+ if (__get_user(rptr[i], addr+i))
+ return -EFAULT;
+ if (nb0 > 0) {
+ rptr = (unsigned char *) ®s->gpr[0];
+ addr += nb;
+ for (i = 0; i < nb0; ++i)
+ if (__get_user(rptr[i], addr+i))
+ return -EFAULT;
+ }
+ for (; (i & 3) != 0; ++i)
+ rptr[i] = 0;
+ } else {
+ for (i = 0; i < nb; ++i)
+ if (__put_user(rptr[i], addr+i))
+ return -EFAULT;
+ if (nb0 > 0) {
+ rptr = (unsigned char *) ®s->gpr[0];
+ addr += nb;
+ for (i = 0; i < nb0; ++i)
+ if (__put_user(rptr[i], addr+i))
+ return -EFAULT;
+ }
+ }
+ return 1;
+ }
+
+ offset = 0;
+ if (nb < 4) {
+ /* read/write the least significant bits */
+ data.l = 0;
+ offset = 4 - nb;
+ }
+
+ /* Verify the address of the operand */
+ if (user_mode(regs)) {
+ if (!access_ok((flags & ST? VERIFY_WRITE: VERIFY_READ), addr, nb))
+ return -EFAULT; /* bad address */
+ }
+
+ if (flags & F) {
+ preempt_disable();
+ if (regs->msr & MSR_FP)
+ giveup_fpu(current);
+ preempt_enable();
+ }
+
+ /* If we read the operand, copy it in, else get register values */
+ if (flags & LD) {
+ for (i = 0; i < nb; ++i)
+ if (__get_user(data.v[offset+i], addr+i))
+ return -EFAULT;
+ } else if (flags & F) {
+ data.d = current->thread.fpr[reg];
+ } else {
+ data.l = regs->gpr[reg];
+ }
+
+ switch (flags & ~U) {
+ case LD+SE: /* sign extend */
+ if (data.v[2] >= 0x80)
+ data.v[0] = data.v[1] = -1;
+ break;
+
+ case LD+S: /* byte-swap */
+ case ST+S:
+ if (nb == 2) {
+ SWAP(data.v[2], data.v[3]);
+ } else {
+ SWAP(data.v[0], data.v[3]);
+ SWAP(data.v[1], data.v[2]);
+ }
+ break;
+
+ /* Single-precision FP load and store require conversions... */
+ case LD+F+S:
+ preempt_disable();
+ enable_kernel_fp();
+ cvt_fd(&data.f, &data.d, ¤t->thread.fpscr);
+ preempt_enable();
+ break;
+ case ST+F+S:
+ preempt_disable();
+ enable_kernel_fp();
+ cvt_df(&data.d, &data.f, ¤t->thread.fpscr);
+ preempt_enable();
+ break;
+ }
+
+ if (flags & ST) {
+ for (i = 0; i < nb; ++i)
+ if (__put_user(data.v[offset+i], addr+i))
+ return -EFAULT;
+ } else if (flags & F) {
+ current->thread.fpr[reg] = data.d;
+ } else {
+ regs->gpr[reg] = data.l;
+ }
+
+ if (flags & U)
+ regs->gpr[areg] = regs->dar;
+
+ return 1;
+}
diff --git a/arch/ppc/kernel/asm-offsets.c b/arch/ppc/kernel/asm-offsets.c
new file mode 100644
index 0000000..d9ad1d7
--- /dev/null
+++ b/arch/ppc/kernel/asm-offsets.c
@@ -0,0 +1,146 @@
+/*
+ * This program is used to generate definitions needed by
+ * assembly language modules.
+ *
+ * We use the technique used in the OSF Mach kernel code:
+ * generate asm statements containing #defines,
+ * compile this file to assembler, and then extract the
+ * #defines from the assembly-language output.
+ */
+
+#include <linux/config.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/types.h>
+#include <linux/ptrace.h>
+#include <linux/suspend.h>
+#include <linux/mman.h>
+#include <linux/mm.h>
+#include <asm/io.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <asm/processor.h>
+#include <asm/cputable.h>
+#include <asm/thread_info.h>
+
+#define DEFINE(sym, val) \
+ asm volatile("\n->" #sym " %0 " #val : : "i" (val))
+
+#define BLANK() asm volatile("\n->" : : )
+
+int
+main(void)
+{
+ DEFINE(THREAD, offsetof(struct task_struct, thread));
+ DEFINE(THREAD_INFO, offsetof(struct task_struct, thread_info));
+ DEFINE(MM, offsetof(struct task_struct, mm));
+ DEFINE(PTRACE, offsetof(struct task_struct, ptrace));
+ DEFINE(KSP, offsetof(struct thread_struct, ksp));
+ DEFINE(PGDIR, offsetof(struct thread_struct, pgdir));
+ DEFINE(LAST_SYSCALL, offsetof(struct thread_struct, last_syscall));
+ DEFINE(PT_REGS, offsetof(struct thread_struct, regs));
+ DEFINE(THREAD_FPEXC_MODE, offsetof(struct thread_struct, fpexc_mode));
+ DEFINE(THREAD_FPR0, offsetof(struct thread_struct, fpr[0]));
+ DEFINE(THREAD_FPSCR, offsetof(struct thread_struct, fpscr));
+#if defined(CONFIG_4xx) || defined(CONFIG_BOOKE)
+ DEFINE(THREAD_DBCR0, offsetof(struct thread_struct, dbcr0));
+ DEFINE(PT_PTRACED, PT_PTRACED);
+#endif
+#ifdef CONFIG_ALTIVEC
+ DEFINE(THREAD_VR0, offsetof(struct thread_struct, vr[0]));
+ DEFINE(THREAD_VRSAVE, offsetof(struct thread_struct, vrsave));
+ DEFINE(THREAD_VSCR, offsetof(struct thread_struct, vscr));
+ DEFINE(THREAD_USED_VR, offsetof(struct thread_struct, used_vr));
+#endif /* CONFIG_ALTIVEC */
+#ifdef CONFIG_SPE
+ DEFINE(THREAD_EVR0, offsetof(struct thread_struct, evr[0]));
+ DEFINE(THREAD_ACC, offsetof(struct thread_struct, acc));
+ DEFINE(THREAD_SPEFSCR, offsetof(struct thread_struct, spefscr));
+ DEFINE(THREAD_USED_SPE, offsetof(struct thread_struct, used_spe));
+#endif /* CONFIG_SPE */
+ /* Interrupt register frame */
+ DEFINE(STACK_FRAME_OVERHEAD, STACK_FRAME_OVERHEAD);
+ DEFINE(INT_FRAME_SIZE, STACK_FRAME_OVERHEAD + sizeof(struct pt_regs));
+ /* in fact we only use gpr0 - gpr9 and gpr20 - gpr23 */
+ DEFINE(GPR0, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[0]));
+ DEFINE(GPR1, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[1]));
+ DEFINE(GPR2, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[2]));
+ DEFINE(GPR3, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[3]));
+ DEFINE(GPR4, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[4]));
+ DEFINE(GPR5, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[5]));
+ DEFINE(GPR6, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[6]));
+ DEFINE(GPR7, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[7]));
+ DEFINE(GPR8, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[8]));
+ DEFINE(GPR9, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[9]));
+ DEFINE(GPR10, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[10]));
+ DEFINE(GPR11, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[11]));
+ DEFINE(GPR12, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[12]));
+ DEFINE(GPR13, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[13]));
+ DEFINE(GPR14, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[14]));
+ DEFINE(GPR15, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[15]));
+ DEFINE(GPR16, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[16]));
+ DEFINE(GPR17, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[17]));
+ DEFINE(GPR18, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[18]));
+ DEFINE(GPR19, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[19]));
+ DEFINE(GPR20, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[20]));
+ DEFINE(GPR21, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[21]));
+ DEFINE(GPR22, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[22]));
+ DEFINE(GPR23, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[23]));
+ DEFINE(GPR24, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[24]));
+ DEFINE(GPR25, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[25]));
+ DEFINE(GPR26, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[26]));
+ DEFINE(GPR27, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[27]));
+ DEFINE(GPR28, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[28]));
+ DEFINE(GPR29, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[29]));
+ DEFINE(GPR30, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[30]));
+ DEFINE(GPR31, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[31]));
+ /* Note: these symbols include _ because they overlap with special
+ * register names
+ */
+ DEFINE(_NIP, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, nip));
+ DEFINE(_MSR, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, msr));
+ DEFINE(_CTR, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, ctr));
+ DEFINE(_LINK, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, link));
+ DEFINE(_CCR, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, ccr));
+ DEFINE(_MQ, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, mq));
+ DEFINE(_XER, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, xer));
+ DEFINE(_DAR, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, dar));
+ DEFINE(_DSISR, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, dsisr));
+ /* The PowerPC 400-class & Book-E processors have neither the DAR nor the DSISR
+ * SPRs. Hence, we overload them to hold the similar DEAR and ESR SPRs
+ * for such processors. For critical interrupts we use them to
+ * hold SRR0 and SRR1.
+ */
+ DEFINE(_DEAR, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, dar));
+ DEFINE(_ESR, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, dsisr));
+ DEFINE(ORIG_GPR3, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, orig_gpr3));
+ DEFINE(RESULT, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, result));
+ DEFINE(TRAP, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, trap));
+ DEFINE(CLONE_VM, CLONE_VM);
+ DEFINE(CLONE_UNTRACED, CLONE_UNTRACED);
+ DEFINE(MM_PGD, offsetof(struct mm_struct, pgd));
+
+ /* About the CPU features table */
+ DEFINE(CPU_SPEC_ENTRY_SIZE, sizeof(struct cpu_spec));
+ DEFINE(CPU_SPEC_PVR_MASK, offsetof(struct cpu_spec, pvr_mask));
+ DEFINE(CPU_SPEC_PVR_VALUE, offsetof(struct cpu_spec, pvr_value));
+ DEFINE(CPU_SPEC_FEATURES, offsetof(struct cpu_spec, cpu_features));
+ DEFINE(CPU_SPEC_SETUP, offsetof(struct cpu_spec, cpu_setup));
+
+ DEFINE(TI_TASK, offsetof(struct thread_info, task));
+ DEFINE(TI_EXECDOMAIN, offsetof(struct thread_info, exec_domain));
+ DEFINE(TI_FLAGS, offsetof(struct thread_info, flags));
+ DEFINE(TI_LOCAL_FLAGS, offsetof(struct thread_info, local_flags));
+ DEFINE(TI_CPU, offsetof(struct thread_info, cpu));
+ DEFINE(TI_PREEMPT, offsetof(struct thread_info, preempt_count));
+
+ DEFINE(pbe_address, offsetof(struct pbe, address));
+ DEFINE(pbe_orig_address, offsetof(struct pbe, orig_address));
+ DEFINE(pbe_next, offsetof(struct pbe, next));
+
+ DEFINE(NUM_USER_SEGMENTS, TASK_SIZE>>28);
+ return 0;
+}
diff --git a/arch/ppc/kernel/bitops.c b/arch/ppc/kernel/bitops.c
new file mode 100644
index 0000000..7f53d19
--- /dev/null
+++ b/arch/ppc/kernel/bitops.c
@@ -0,0 +1,126 @@
+/*
+ * Copyright (C) 1996 Paul Mackerras.
+ */
+
+#include <linux/kernel.h>
+#include <linux/bitops.h>
+
+/*
+ * If the bitops are not inlined in bitops.h, they are defined here.
+ * -- paulus
+ */
+#if !__INLINE_BITOPS
+void set_bit(int nr, volatile void * addr)
+{
+ unsigned long old;
+ unsigned long mask = 1 << (nr & 0x1f);
+ unsigned long *p = ((unsigned long *)addr) + (nr >> 5);
+
+ __asm__ __volatile__(SMP_WMB "\n\
+1: lwarx %0,0,%3 \n\
+ or %0,%0,%2 \n"
+ PPC405_ERR77(0,%3)
+" stwcx. %0,0,%3 \n\
+ bne 1b"
+ SMP_MB
+ : "=&r" (old), "=m" (*p)
+ : "r" (mask), "r" (p), "m" (*p)
+ : "cc" );
+}
+
+void clear_bit(int nr, volatile void *addr)
+{
+ unsigned long old;
+ unsigned long mask = 1 << (nr & 0x1f);
+ unsigned long *p = ((unsigned long *)addr) + (nr >> 5);
+
+ __asm__ __volatile__(SMP_WMB "\n\
+1: lwarx %0,0,%3 \n\
+ andc %0,%0,%2 \n"
+ PPC405_ERR77(0,%3)
+" stwcx. %0,0,%3 \n\
+ bne 1b"
+ SMP_MB
+ : "=&r" (old), "=m" (*p)
+ : "r" (mask), "r" (p), "m" (*p)
+ : "cc");
+}
+
+void change_bit(int nr, volatile void *addr)
+{
+ unsigned long old;
+ unsigned long mask = 1 << (nr & 0x1f);
+ unsigned long *p = ((unsigned long *)addr) + (nr >> 5);
+
+ __asm__ __volatile__(SMP_WMB "\n\
+1: lwarx %0,0,%3 \n\
+ xor %0,%0,%2 \n"
+ PPC405_ERR77(0,%3)
+" stwcx. %0,0,%3 \n\
+ bne 1b"
+ SMP_MB
+ : "=&r" (old), "=m" (*p)
+ : "r" (mask), "r" (p), "m" (*p)
+ : "cc");
+}
+
+int test_and_set_bit(int nr, volatile void *addr)
+{
+ unsigned int old, t;
+ unsigned int mask = 1 << (nr & 0x1f);
+ volatile unsigned int *p = ((volatile unsigned int *)addr) + (nr >> 5);
+
+ __asm__ __volatile__(SMP_WMB "\n\
+1: lwarx %0,0,%4 \n\
+ or %1,%0,%3 \n"
+ PPC405_ERR77(0,%4)
+" stwcx. %1,0,%4 \n\
+ bne 1b"
+ SMP_MB
+ : "=&r" (old), "=&r" (t), "=m" (*p)
+ : "r" (mask), "r" (p), "m" (*p)
+ : "cc");
+
+ return (old & mask) != 0;
+}
+
+int test_and_clear_bit(int nr, volatile void *addr)
+{
+ unsigned int old, t;
+ unsigned int mask = 1 << (nr & 0x1f);
+ volatile unsigned int *p = ((volatile unsigned int *)addr) + (nr >> 5);
+
+ __asm__ __volatile__(SMP_WMB "\n\
+1: lwarx %0,0,%4 \n\
+ andc %1,%0,%3 \n"
+ PPC405_ERR77(0,%4)
+" stwcx. %1,0,%4 \n\
+ bne 1b"
+ SMP_MB
+ : "=&r" (old), "=&r" (t), "=m" (*p)
+ : "r" (mask), "r" (p), "m" (*p)
+ : "cc");
+
+ return (old & mask) != 0;
+}
+
+int test_and_change_bit(int nr, volatile void *addr)
+{
+ unsigned int old, t;
+ unsigned int mask = 1 << (nr & 0x1f);
+ volatile unsigned int *p = ((volatile unsigned int *)addr) + (nr >> 5);
+
+ __asm__ __volatile__(SMP_WMB "\n\
+1: lwarx %0,0,%4 \n\
+ xor %1,%0,%3 \n"
+ PPC405_ERR77(0,%4)
+" stwcx. %1,0,%4 \n\
+ bne 1b"
+ SMP_MB
+ : "=&r" (old), "=&r" (t), "=m" (*p)
+ : "r" (mask), "r" (p), "m" (*p)
+ : "cc");
+
+ return (old & mask) != 0;
+}
+#endif /* !__INLINE_BITOPS */
diff --git a/arch/ppc/kernel/cpu_setup_6xx.S b/arch/ppc/kernel/cpu_setup_6xx.S
new file mode 100644
index 0000000..74f781b
--- /dev/null
+++ b/arch/ppc/kernel/cpu_setup_6xx.S
@@ -0,0 +1,440 @@
+/*
+ * This file contains low level CPU setup functions.
+ * Copyright (C) 2003 Benjamin Herrenschmidt (benh@kernel.crashing.org)
+ *
+ * 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.
+ *
+ */
+
+#include <linux/config.h>
+#include <asm/processor.h>
+#include <asm/page.h>
+#include <asm/ppc_asm.h>
+#include <asm/cputable.h>
+#include <asm/ppc_asm.h>
+#include <asm/offsets.h>
+#include <asm/cache.h>
+
+_GLOBAL(__setup_cpu_601)
+ blr
+_GLOBAL(__setup_cpu_603)
+ b setup_common_caches
+_GLOBAL(__setup_cpu_604)
+ mflr r4
+ bl setup_common_caches
+ bl setup_604_hid0
+ mtlr r4
+ blr
+_GLOBAL(__setup_cpu_750)
+ mflr r4
+ bl setup_common_caches
+ bl setup_750_7400_hid0
+ mtlr r4
+ blr
+_GLOBAL(__setup_cpu_750cx)
+ mflr r4
+ bl setup_common_caches
+ bl setup_750_7400_hid0
+ bl setup_750cx
+ mtlr r4
+ blr
+_GLOBAL(__setup_cpu_750fx)
+ mflr r4
+ bl setup_common_caches
+ bl setup_750_7400_hid0
+ bl setup_750fx
+ mtlr r4
+ blr
+_GLOBAL(__setup_cpu_7400)
+ mflr r4
+ bl setup_7400_workarounds
+ bl setup_common_caches
+ bl setup_750_7400_hid0
+ mtlr r4
+ blr
+_GLOBAL(__setup_cpu_7410)
+ mflr r4
+ bl setup_7410_workarounds
+ bl setup_common_caches
+ bl setup_750_7400_hid0
+ li r3,0
+ mtspr SPRN_L2CR2,r3
+ mtlr r4
+ blr
+_GLOBAL(__setup_cpu_745x)
+ mflr r4
+ bl setup_common_caches
+ bl setup_745x_specifics
+ mtlr r4
+ blr
+
+/* Enable caches for 603's, 604, 750 & 7400 */
+setup_common_caches:
+ mfspr r11,SPRN_HID0
+ andi. r0,r11,HID0_DCE
+ ori r11,r11,HID0_ICE|HID0_DCE
+ ori r8,r11,HID0_ICFI
+ bne 1f /* don't invalidate the D-cache */
+ ori r8,r8,HID0_DCI /* unless it wasn't enabled */
+1: sync
+ mtspr SPRN_HID0,r8 /* enable and invalidate caches */
+ sync
+ mtspr SPRN_HID0,r11 /* enable caches */
+ sync
+ isync
+ blr
+
+/* 604, 604e, 604ev, ...
+ * Enable superscalar execution & branch history table
+ */
+setup_604_hid0:
+ mfspr r11,SPRN_HID0
+ ori r11,r11,HID0_SIED|HID0_BHTE
+ ori r8,r11,HID0_BTCD
+ sync
+ mtspr SPRN_HID0,r8 /* flush branch target address cache */
+ sync /* on 604e/604r */
+ mtspr SPRN_HID0,r11
+ sync
+ isync
+ blr
+
+/* 7400 <= rev 2.7 and 7410 rev = 1.0 suffer from some
+ * erratas we work around here.
+ * Moto MPC710CE.pdf describes them, those are errata
+ * #3, #4 and #5
+ * Note that we assume the firmware didn't choose to
+ * apply other workarounds (there are other ones documented
+ * in the .pdf). It appear that Apple firmware only works
+ * around #3 and with the same fix we use. We may want to
+ * check if the CPU is using 60x bus mode in which case
+ * the workaround for errata #4 is useless. Also, we may
+ * want to explicitely clear HID0_NOPDST as this is not
+ * needed once we have applied workaround #5 (though it's
+ * not set by Apple's firmware at least).
+ */
+setup_7400_workarounds:
+ mfpvr r3
+ rlwinm r3,r3,0,20,31
+ cmpwi 0,r3,0x0207
+ ble 1f
+ blr
+setup_7410_workarounds:
+ mfpvr r3
+ rlwinm r3,r3,0,20,31
+ cmpwi 0,r3,0x0100
+ bnelr
+1:
+ mfspr r11,SPRN_MSSSR0
+ /* Errata #3: Set L1OPQ_SIZE to 0x10 */
+ rlwinm r11,r11,0,9,6
+ oris r11,r11,0x0100
+ /* Errata #4: Set L2MQ_SIZE to 1 (check for MPX mode first ?) */
+ oris r11,r11,0x0002
+ /* Errata #5: Set DRLT_SIZE to 0x01 */
+ rlwinm r11,r11,0,5,2
+ oris r11,r11,0x0800
+ sync
+ mtspr SPRN_MSSSR0,r11
+ sync
+ isync
+ blr
+
+/* 740/750/7400/7410
+ * Enable Store Gathering (SGE), Address Brodcast (ABE),
+ * Branch History Table (BHTE), Branch Target ICache (BTIC)
+ * Dynamic Power Management (DPM), Speculative (SPD)
+ * Clear Instruction cache throttling (ICTC)
+ */
+setup_750_7400_hid0:
+ mfspr r11,SPRN_HID0
+ ori r11,r11,HID0_SGE | HID0_ABE | HID0_BHTE | HID0_BTIC
+BEGIN_FTR_SECTION
+ oris r11,r11,HID0_DPM@h /* enable dynamic power mgmt */
+END_FTR_SECTION_IFCLR(CPU_FTR_NO_DPM)
+ li r3,HID0_SPD
+ andc r11,r11,r3 /* clear SPD: enable speculative */
+ li r3,0
+ mtspr SPRN_ICTC,r3 /* Instruction Cache Throttling off */
+ isync
+ mtspr SPRN_HID0,r11
+ sync
+ isync
+ blr
+
+/* 750cx specific
+ * Looks like we have to disable NAP feature for some PLL settings...
+ * (waiting for confirmation)
+ */
+setup_750cx:
+ mfspr r10, SPRN_HID1
+ rlwinm r10,r10,4,28,31
+ cmpwi cr0,r10,7
+ cmpwi cr1,r10,9
+ cmpwi cr2,r10,11
+ cror 4*cr0+eq,4*cr0+eq,4*cr1+eq
+ cror 4*cr0+eq,4*cr0+eq,4*cr2+eq
+ bnelr
+ lwz r6,CPU_SPEC_FEATURES(r5)
+ li r7,CPU_FTR_CAN_NAP
+ andc r6,r6,r7
+ stw r6,CPU_SPEC_FEATURES(r5)
+ blr
+
+/* 750fx specific
+ */
+setup_750fx:
+ blr
+
+/* MPC 745x
+ * Enable Store Gathering (SGE), Branch Folding (FOLD)
+ * Branch History Table (BHTE), Branch Target ICache (BTIC)
+ * Dynamic Power Management (DPM), Speculative (SPD)
+ * Ensure our data cache instructions really operate.
+ * Timebase has to be running or we wouldn't have made it here,
+ * just ensure we don't disable it.
+ * Clear Instruction cache throttling (ICTC)
+ * Enable L2 HW prefetch
+ */
+setup_745x_specifics:
+ /* We check for the presence of an L3 cache setup by
+ * the firmware. If any, we disable NAP capability as
+ * it's known to be bogus on rev 2.1 and earlier
+ */
+ mfspr r11,SPRN_L3CR
+ andis. r11,r11,L3CR_L3E@h
+ beq 1f
+ lwz r6,CPU_SPEC_FEATURES(r5)
+ andi. r0,r6,CPU_FTR_L3_DISABLE_NAP
+ beq 1f
+ li r7,CPU_FTR_CAN_NAP
+ andc r6,r6,r7
+ stw r6,CPU_SPEC_FEATURES(r5)
+1:
+ mfspr r11,SPRN_HID0
+
+ /* All of the bits we have to set.....
+ */
+ ori r11,r11,HID0_SGE | HID0_FOLD | HID0_BHTE | HID0_LRSTK | HID0_BTIC
+BEGIN_FTR_SECTION
+ xori r11,r11,HID0_BTIC
+END_FTR_SECTION_IFSET(CPU_FTR_NO_BTIC)
+BEGIN_FTR_SECTION
+ oris r11,r11,HID0_DPM@h /* enable dynamic power mgmt */
+END_FTR_SECTION_IFCLR(CPU_FTR_NO_DPM)
+
+ /* All of the bits we have to clear....
+ */
+ li r3,HID0_SPD | HID0_NOPDST | HID0_NOPTI
+ andc r11,r11,r3 /* clear SPD: enable speculative */
+ li r3,0
+
+ mtspr SPRN_ICTC,r3 /* Instruction Cache Throttling off */
+ isync
+ mtspr SPRN_HID0,r11
+ sync
+ isync
+
+ /* Enable L2 HW prefetch
+ */
+ mfspr r3,SPRN_MSSCR0
+ ori r3,r3,3
+ sync
+ mtspr SPRN_MSSCR0,r3
+ sync
+ isync
+ blr
+
+/* Definitions for the table use to save CPU states */
+#define CS_HID0 0
+#define CS_HID1 4
+#define CS_HID2 8
+#define CS_MSSCR0 12
+#define CS_MSSSR0 16
+#define CS_ICTRL 20
+#define CS_LDSTCR 24
+#define CS_LDSTDB 28
+#define CS_SIZE 32
+
+ .data
+ .balign L1_CACHE_LINE_SIZE
+cpu_state_storage:
+ .space CS_SIZE
+ .balign L1_CACHE_LINE_SIZE,0
+ .text
+
+/* Called in normal context to backup CPU 0 state. This
+ * does not include cache settings. This function is also
+ * called for machine sleep. This does not include the MMU
+ * setup, BATs, etc... but rather the "special" registers
+ * like HID0, HID1, MSSCR0, etc...
+ */
+_GLOBAL(__save_cpu_setup)
+ /* Some CR fields are volatile, we back it up all */
+ mfcr r7
+
+ /* Get storage ptr */
+ lis r5,cpu_state_storage@h
+ ori r5,r5,cpu_state_storage@l
+
+ /* Save HID0 (common to all CONFIG_6xx cpus) */
+ mfspr r3,SPRN_HID0
+ stw r3,CS_HID0(r5)
+
+ /* Now deal with CPU type dependent registers */
+ mfspr r3,SPRN_PVR
+ srwi r3,r3,16
+ cmplwi cr0,r3,0x8000 /* 7450 */
+ cmplwi cr1,r3,0x000c /* 7400 */
+ cmplwi cr2,r3,0x800c /* 7410 */
+ cmplwi cr3,r3,0x8001 /* 7455 */
+ cmplwi cr4,r3,0x8002 /* 7457 */
+ cmplwi cr5,r3,0x8003 /* 7447A */
+ cmplwi cr6,r3,0x7000 /* 750FX */
+ /* cr1 is 7400 || 7410 */
+ cror 4*cr1+eq,4*cr1+eq,4*cr2+eq
+ /* cr0 is 74xx */
+ cror 4*cr0+eq,4*cr0+eq,4*cr3+eq
+ cror 4*cr0+eq,4*cr0+eq,4*cr4+eq
+ cror 4*cr0+eq,4*cr0+eq,4*cr1+eq
+ cror 4*cr0+eq,4*cr0+eq,4*cr5+eq
+ bne 1f
+ /* Backup 74xx specific regs */
+ mfspr r4,SPRN_MSSCR0
+ stw r4,CS_MSSCR0(r5)
+ mfspr r4,SPRN_MSSSR0
+ stw r4,CS_MSSSR0(r5)
+ beq cr1,1f
+ /* Backup 745x specific registers */
+ mfspr r4,SPRN_HID1
+ stw r4,CS_HID1(r5)
+ mfspr r4,SPRN_ICTRL
+ stw r4,CS_ICTRL(r5)
+ mfspr r4,SPRN_LDSTCR
+ stw r4,CS_LDSTCR(r5)
+ mfspr r4,SPRN_LDSTDB
+ stw r4,CS_LDSTDB(r5)
+1:
+ bne cr6,1f
+ /* Backup 750FX specific registers */
+ mfspr r4,SPRN_HID1
+ stw r4,CS_HID1(r5)
+ /* If rev 2.x, backup HID2 */
+ mfspr r3,SPRN_PVR
+ andi. r3,r3,0xff00
+ cmpwi cr0,r3,0x0200
+ bne 1f
+ mfspr r4,SPRN_HID2
+ stw r4,CS_HID2(r5)
+1:
+ mtcr r7
+ blr
+
+/* Called with no MMU context (typically MSR:IR/DR off) to
+ * restore CPU state as backed up by the previous
+ * function. This does not include cache setting
+ */
+_GLOBAL(__restore_cpu_setup)
+ /* Some CR fields are volatile, we back it up all */
+ mfcr r7
+
+ /* Get storage ptr */
+ lis r5,(cpu_state_storage-KERNELBASE)@h
+ ori r5,r5,cpu_state_storage@l
+
+ /* Restore HID0 */
+ lwz r3,CS_HID0(r5)
+ sync
+ isync
+ mtspr SPRN_HID0,r3
+ sync
+ isync
+
+ /* Now deal with CPU type dependent registers */
+ mfspr r3,SPRN_PVR
+ srwi r3,r3,16
+ cmplwi cr0,r3,0x8000 /* 7450 */
+ cmplwi cr1,r3,0x000c /* 7400 */
+ cmplwi cr2,r3,0x800c /* 7410 */
+ cmplwi cr3,r3,0x8001 /* 7455 */
+ cmplwi cr4,r3,0x8002 /* 7457 */
+ cmplwi cr5,r3,0x8003 /* 7447A */
+ cmplwi cr6,r3,0x7000 /* 750FX */
+ /* cr1 is 7400 || 7410 */
+ cror 4*cr1+eq,4*cr1+eq,4*cr2+eq
+ /* cr0 is 74xx */
+ cror 4*cr0+eq,4*cr0+eq,4*cr3+eq
+ cror 4*cr0+eq,4*cr0+eq,4*cr4+eq
+ cror 4*cr0+eq,4*cr0+eq,4*cr1+eq
+ cror 4*cr0+eq,4*cr0+eq,4*cr5+eq
+ bne 2f
+ /* Restore 74xx specific regs */
+ lwz r4,CS_MSSCR0(r5)
+ sync
+ mtspr SPRN_MSSCR0,r4
+ sync
+ isync
+ lwz r4,CS_MSSSR0(r5)
+ sync
+ mtspr SPRN_MSSSR0,r4
+ sync
+ isync
+ bne cr2,1f
+ /* Clear 7410 L2CR2 */
+ li r4,0
+ mtspr SPRN_L2CR2,r4
+1: beq cr1,2f
+ /* Restore 745x specific registers */
+ lwz r4,CS_HID1(r5)
+ sync
+ mtspr SPRN_HID1,r4
+ isync
+ sync
+ lwz r4,CS_ICTRL(r5)
+ sync
+ mtspr SPRN_ICTRL,r4
+ isync
+ sync
+ lwz r4,CS_LDSTCR(r5)
+ sync
+ mtspr SPRN_LDSTCR,r4
+ isync
+ sync
+ lwz r4,CS_LDSTDB(r5)
+ sync
+ mtspr SPRN_LDSTDB,r4
+ isync
+ sync
+2: bne cr6,1f
+ /* Restore 750FX specific registers
+ * that is restore HID2 on rev 2.x and PLL config & switch
+ * to PLL 0 on all
+ */
+ /* If rev 2.x, restore HID2 with low voltage bit cleared */
+ mfspr r3,SPRN_PVR
+ andi. r3,r3,0xff00
+ cmpwi cr0,r3,0x0200
+ bne 4f
+ lwz r4,CS_HID2(r5)
+ rlwinm r4,r4,0,19,17
+ mtspr SPRN_HID2,r4
+ sync
+4:
+ lwz r4,CS_HID1(r5)
+ rlwinm r5,r4,0,16,14
+ mtspr SPRN_HID1,r5
+ /* Wait for PLL to stabilize */
+ mftbl r5
+3: mftbl r6
+ sub r6,r6,r5
+ cmplwi cr0,r6,10000
+ ble 3b
+ /* Setup final PLL */
+ mtspr SPRN_HID1,r4
+1:
+ mtcr r7
+ blr
+
diff --git a/arch/ppc/kernel/cpu_setup_power4.S b/arch/ppc/kernel/cpu_setup_power4.S
new file mode 100644
index 0000000..f2ea1a9
--- /dev/null
+++ b/arch/ppc/kernel/cpu_setup_power4.S
@@ -0,0 +1,201 @@
+/*
+ * This file contains low level CPU setup functions.
+ * Copyright (C) 2003 Benjamin Herrenschmidt (benh@kernel.crashing.org)
+ *
+ * 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.
+ *
+ */
+
+#include <linux/config.h>
+#include <asm/processor.h>
+#include <asm/page.h>
+#include <asm/ppc_asm.h>
+#include <asm/cputable.h>
+#include <asm/ppc_asm.h>
+#include <asm/offsets.h>
+#include <asm/cache.h>
+
+_GLOBAL(__970_cpu_preinit)
+ /*
+ * Deal only with PPC970 and PPC970FX.
+ */
+ mfspr r0,SPRN_PVR
+ srwi r0,r0,16
+ cmpwi cr0,r0,0x39
+ cmpwi cr1,r0,0x3c
+ cror 4*cr0+eq,4*cr0+eq,4*cr1+eq
+ bnelr
+
+ /* Make sure HID4:rm_ci is off before MMU is turned off, that large
+ * pages are enabled with HID4:61 and clear HID5:DCBZ_size and
+ * HID5:DCBZ32_ill
+ */
+ li r0,0
+ mfspr r11,SPRN_HID4
+ rldimi r11,r0,40,23 /* clear bit 23 (rm_ci) */
+ rldimi r11,r0,2,61 /* clear bit 61 (lg_pg_en) */
+ sync
+ mtspr SPRN_HID4,r11
+ isync
+ sync
+ mfspr r11,SPRN_HID5
+ rldimi r11,r0,6,56 /* clear bits 56 & 57 (DCBZ*) */
+ sync
+ mtspr SPRN_HID5,r11
+ isync
+ sync
+
+ /* Setup some basic HID1 features */
+ mfspr r0,SPRN_HID1
+ li r11,0x1200 /* enable i-fetch cacheability */
+ sldi r11,r11,44 /* and prefetch */
+ or r0,r0,r11
+ mtspr SPRN_HID1,r0
+ mtspr SPRN_HID1,r0
+ isync
+
+ /* Clear HIOR */
+ li r0,0
+ sync
+ mtspr SPRN_HIOR,0 /* Clear interrupt prefix */
+ isync
+ blr
+
+_GLOBAL(__setup_cpu_power4)
+ blr
+_GLOBAL(__setup_cpu_ppc970)
+ mfspr r0,SPRN_HID0
+ li r11,5 /* clear DOZE and SLEEP */
+ rldimi r0,r11,52,8 /* set NAP and DPM */
+ mtspr SPRN_HID0,r0
+ mfspr r0,SPRN_HID0
+ mfspr r0,SPRN_HID0
+ mfspr r0,SPRN_HID0
+ mfspr r0,SPRN_HID0
+ mfspr r0,SPRN_HID0
+ mfspr r0,SPRN_HID0
+ sync
+ isync
+ blr
+
+/* Definitions for the table use to save CPU states */
+#define CS_HID0 0
+#define CS_HID1 8
+#define CS_HID4 16
+#define CS_HID5 24
+#define CS_SIZE 32
+
+ .data
+ .balign L1_CACHE_LINE_SIZE
+cpu_state_storage:
+ .space CS_SIZE
+ .balign L1_CACHE_LINE_SIZE,0
+ .text
+
+/* Called in normal context to backup CPU 0 state. This
+ * does not include cache settings. This function is also
+ * called for machine sleep. This does not include the MMU
+ * setup, BATs, etc... but rather the "special" registers
+ * like HID0, HID1, HID4, etc...
+ */
+_GLOBAL(__save_cpu_setup)
+ /* Some CR fields are volatile, we back it up all */
+ mfcr r7
+
+ /* Get storage ptr */
+ lis r5,cpu_state_storage@h
+ ori r5,r5,cpu_state_storage@l
+
+ /* We only deal with 970 for now */
+ mfspr r0,SPRN_PVR
+ srwi r0,r0,16
+ cmpwi cr0,r0,0x39
+ cmpwi cr1,r0,0x3c
+ cror 4*cr0+eq,4*cr0+eq,4*cr1+eq
+ bne 1f
+
+ /* Save HID0,1,4 and 5 */
+ mfspr r3,SPRN_HID0
+ std r3,CS_HID0(r5)
+ mfspr r3,SPRN_HID1
+ std r3,CS_HID1(r5)
+ mfspr r3,SPRN_HID4
+ std r3,CS_HID4(r5)
+ mfspr r3,SPRN_HID5
+ std r3,CS_HID5(r5)
+
+1:
+ mtcr r7
+ blr
+
+/* Called with no MMU context (typically MSR:IR/DR off) to
+ * restore CPU state as backed up by the previous
+ * function. This does not include cache setting
+ */
+_GLOBAL(__restore_cpu_setup)
+ /* Some CR fields are volatile, we back it up all */
+ mfcr r7
+
+ /* Get storage ptr */
+ lis r5,(cpu_state_storage-KERNELBASE)@h
+ ori r5,r5,cpu_state_storage@l
+
+ /* We only deal with 970 for now */
+ mfspr r0,SPRN_PVR
+ srwi r0,r0,16
+ cmpwi cr0,r0,0x39
+ cmpwi cr1,r0,0x3c
+ cror 4*cr0+eq,4*cr0+eq,4*cr1+eq
+ bne 1f
+
+ /* Clear interrupt prefix */
+ li r0,0
+ sync
+ mtspr SPRN_HIOR,0
+ isync
+
+ /* Restore HID0 */
+ ld r3,CS_HID0(r5)
+ sync
+ isync
+ mtspr SPRN_HID0,r3
+ mfspr r3,SPRN_HID0
+ mfspr r3,SPRN_HID0
+ mfspr r3,SPRN_HID0
+ mfspr r3,SPRN_HID0
+ mfspr r3,SPRN_HID0
+ mfspr r3,SPRN_HID0
+ sync
+ isync
+
+ /* Restore HID1 */
+ ld r3,CS_HID1(r5)
+ sync
+ isync
+ mtspr SPRN_HID1,r3
+ mtspr SPRN_HID1,r3
+ sync
+ isync
+
+ /* Restore HID4 */
+ ld r3,CS_HID4(r5)
+ sync
+ isync
+ mtspr SPRN_HID4,r3
+ sync
+ isync
+
+ /* Restore HID5 */
+ ld r3,CS_HID5(r5)
+ sync
+ isync
+ mtspr SPRN_HID5,r3
+ sync
+ isync
+1:
+ mtcr r7
+ blr
+
diff --git a/arch/ppc/kernel/cputable.c b/arch/ppc/kernel/cputable.c
new file mode 100644
index 0000000..8aa5e8c
--- /dev/null
+++ b/arch/ppc/kernel/cputable.c
@@ -0,0 +1,922 @@
+/*
+ * arch/ppc/kernel/cputable.c
+ *
+ * Copyright (C) 2001 Ben. Herrenschmidt (benh@kernel.crashing.org)
+ *
+ * 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.
+ */
+
+#include <linux/config.h>
+#include <linux/string.h>
+#include <linux/sched.h>
+#include <linux/threads.h>
+#include <linux/init.h>
+#include <asm/cputable.h>
+
+struct cpu_spec* cur_cpu_spec[NR_CPUS];
+
+extern void __setup_cpu_601(unsigned long offset, int cpu_nr, struct cpu_spec* spec);
+extern void __setup_cpu_603(unsigned long offset, int cpu_nr, struct cpu_spec* spec);
+extern void __setup_cpu_604(unsigned long offset, int cpu_nr, struct cpu_spec* spec);
+extern void __setup_cpu_750(unsigned long offset, int cpu_nr, struct cpu_spec* spec);
+extern void __setup_cpu_750cx(unsigned long offset, int cpu_nr, struct cpu_spec* spec);
+extern void __setup_cpu_750fx(unsigned long offset, int cpu_nr, struct cpu_spec* spec);
+extern void __setup_cpu_7400(unsigned long offset, int cpu_nr, struct cpu_spec* spec);
+extern void __setup_cpu_7410(unsigned long offset, int cpu_nr, struct cpu_spec* spec);
+extern void __setup_cpu_745x(unsigned long offset, int cpu_nr, struct cpu_spec* spec);
+extern void __setup_cpu_power3(unsigned long offset, int cpu_nr, struct cpu_spec* spec);
+extern void __setup_cpu_power4(unsigned long offset, int cpu_nr, struct cpu_spec* spec);
+extern void __setup_cpu_ppc970(unsigned long offset, int cpu_nr, struct cpu_spec* spec);
+extern void __setup_cpu_generic(unsigned long offset, int cpu_nr, struct cpu_spec* spec);
+
+#define CLASSIC_PPC (!defined(CONFIG_8xx) && !defined(CONFIG_4xx) && \
+ !defined(CONFIG_POWER3) && !defined(CONFIG_POWER4) && \
+ !defined(CONFIG_BOOKE))
+
+/* This table only contains "desktop" CPUs, it need to be filled with embedded
+ * ones as well...
+ */
+#define COMMON_PPC (PPC_FEATURE_32 | PPC_FEATURE_HAS_FPU | \
+ PPC_FEATURE_HAS_MMU)
+
+/* We only set the altivec features if the kernel was compiled with altivec
+ * support
+ */
+#ifdef CONFIG_ALTIVEC
+#define CPU_FTR_ALTIVEC_COMP CPU_FTR_ALTIVEC
+#define PPC_FEATURE_ALTIVEC_COMP PPC_FEATURE_HAS_ALTIVEC
+#else
+#define CPU_FTR_ALTIVEC_COMP 0
+#define PPC_FEATURE_ALTIVEC_COMP 0
+#endif
+
+/* We only set the spe features if the kernel was compiled with
+ * spe support
+ */
+#ifdef CONFIG_SPE
+#define PPC_FEATURE_SPE_COMP PPC_FEATURE_HAS_SPE
+#else
+#define PPC_FEATURE_SPE_COMP 0
+#endif
+
+/* We need to mark all pages as being coherent if we're SMP or we
+ * have a 74[45]x and an MPC107 host bridge.
+ */
+#if defined(CONFIG_SMP) || defined(CONFIG_MPC10X_BRIDGE)
+#define CPU_FTR_COMMON CPU_FTR_NEED_COHERENT
+#else
+#define CPU_FTR_COMMON 0
+#endif
+
+/* The powersave features NAP & DOZE seems to confuse BDI when
+ debugging. So if a BDI is used, disable theses
+ */
+#ifndef CONFIG_BDI_SWITCH
+#define CPU_FTR_MAYBE_CAN_DOZE CPU_FTR_CAN_DOZE
+#define CPU_FTR_MAYBE_CAN_NAP CPU_FTR_CAN_NAP
+#else
+#define CPU_FTR_MAYBE_CAN_DOZE 0
+#define CPU_FTR_MAYBE_CAN_NAP 0
+#endif
+
+struct cpu_spec cpu_specs[] = {
+#if CLASSIC_PPC
+ { /* 601 */
+ .pvr_mask = 0xffff0000,
+ .pvr_value = 0x00010000,
+ .cpu_name = "601",
+ .cpu_features = CPU_FTR_COMMON | CPU_FTR_601 |
+ CPU_FTR_HPTE_TABLE,
+ .cpu_user_features = COMMON_PPC | PPC_FEATURE_601_INSTR |
+ PPC_FEATURE_UNIFIED_CACHE,
+ .icache_bsize = 32,
+ .dcache_bsize = 32,
+ .cpu_setup = __setup_cpu_601
+ },
+ { /* 603 */
+ .pvr_mask = 0xffff0000,
+ .pvr_value = 0x00030000,
+ .cpu_name = "603",
+ .cpu_features = CPU_FTR_COMMON |
+ CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_MAYBE_CAN_DOZE |
+ CPU_FTR_USE_TB | CPU_FTR_MAYBE_CAN_NAP,
+ .cpu_user_features = COMMON_PPC,
+ .icache_bsize = 32,
+ .dcache_bsize = 32,
+ .cpu_setup = __setup_cpu_603
+ },
+ { /* 603e */
+ .pvr_mask = 0xffff0000,
+ .pvr_value = 0x00060000,
+ .cpu_name = "603e",
+ .cpu_features = CPU_FTR_COMMON |
+ CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_MAYBE_CAN_DOZE |
+ CPU_FTR_USE_TB | CPU_FTR_MAYBE_CAN_NAP,
+ .cpu_user_features = COMMON_PPC,
+ .icache_bsize = 32,
+ .dcache_bsize = 32,
+ .cpu_setup = __setup_cpu_603
+ },
+ { /* 603ev */
+ .pvr_mask = 0xffff0000,
+ .pvr_value = 0x00070000,
+ .cpu_name = "603ev",
+ .cpu_features = CPU_FTR_COMMON |
+ CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_MAYBE_CAN_DOZE |
+ CPU_FTR_USE_TB | CPU_FTR_MAYBE_CAN_NAP,
+ .cpu_user_features = COMMON_PPC,
+ .icache_bsize = 32,
+ .dcache_bsize = 32,
+ .cpu_setup = __setup_cpu_603
+ },
+ { /* 604 */
+ .pvr_mask = 0xffff0000,
+ .pvr_value = 0x00040000,
+ .cpu_name = "604",
+ .cpu_features = CPU_FTR_COMMON |
+ CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB |
+ CPU_FTR_604_PERF_MON | CPU_FTR_HPTE_TABLE,
+ .cpu_user_features = COMMON_PPC,
+ .icache_bsize = 32,
+ .dcache_bsize = 32,
+ .num_pmcs = 2,
+ .cpu_setup = __setup_cpu_604
+ },
+ { /* 604e */
+ .pvr_mask = 0xfffff000,
+ .pvr_value = 0x00090000,
+ .cpu_name = "604e",
+ .cpu_features = CPU_FTR_COMMON |
+ CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB |
+ CPU_FTR_604_PERF_MON | CPU_FTR_HPTE_TABLE,
+ .cpu_user_features = COMMON_PPC,
+ .icache_bsize = 32,
+ .dcache_bsize = 32,
+ .num_pmcs = 4,
+ .cpu_setup = __setup_cpu_604
+ },
+ { /* 604r */
+ .pvr_mask = 0xffff0000,
+ .pvr_value = 0x00090000,
+ .cpu_name = "604r",
+ .cpu_features = CPU_FTR_COMMON |
+ CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB |
+ CPU_FTR_604_PERF_MON | CPU_FTR_HPTE_TABLE,
+ .cpu_user_features = COMMON_PPC,
+ .icache_bsize = 32,
+ .dcache_bsize = 32,
+ .num_pmcs = 4,
+ .cpu_setup = __setup_cpu_604
+ },
+ { /* 604ev */
+ .pvr_mask = 0xffff0000,
+ .pvr_value = 0x000a0000,
+ .cpu_name = "604ev",
+ .cpu_features = CPU_FTR_COMMON |
+ CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB |
+ CPU_FTR_604_PERF_MON | CPU_FTR_HPTE_TABLE,
+ .cpu_user_features = COMMON_PPC,
+ .icache_bsize = 32,
+ .dcache_bsize = 32,
+ .num_pmcs = 4,
+ .cpu_setup = __setup_cpu_604
+ },
+ { /* 740/750 (0x4202, don't support TAU ?) */
+ .pvr_mask = 0xffffffff,
+ .pvr_value = 0x00084202,
+ .cpu_name = "740/750",
+ .cpu_features = CPU_FTR_COMMON |
+ CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_MAYBE_CAN_DOZE |
+ CPU_FTR_USE_TB | CPU_FTR_L2CR | CPU_FTR_HPTE_TABLE |
+ CPU_FTR_MAYBE_CAN_NAP,
+ .cpu_user_features = COMMON_PPC,
+ .icache_bsize = 32,
+ .dcache_bsize = 32,
+ .num_pmcs = 4,
+ .cpu_setup = __setup_cpu_750
+ },
+ { /* 745/755 */
+ .pvr_mask = 0xfffff000,
+ .pvr_value = 0x00083000,
+ .cpu_name = "745/755",
+ .cpu_features = CPU_FTR_COMMON |
+ CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_MAYBE_CAN_DOZE |
+ CPU_FTR_USE_TB | CPU_FTR_L2CR | CPU_FTR_TAU |
+ CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP,
+ .cpu_user_features = COMMON_PPC,
+ .icache_bsize = 32,
+ .dcache_bsize = 32,
+ .num_pmcs = 4,
+ .cpu_setup = __setup_cpu_750
+ },
+ { /* 750CX (80100 and 8010x?) */
+ .pvr_mask = 0xfffffff0,
+ .pvr_value = 0x00080100,
+ .cpu_name = "750CX",
+ .cpu_features = CPU_FTR_COMMON |
+ CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_MAYBE_CAN_DOZE |
+ CPU_FTR_USE_TB | CPU_FTR_L2CR | CPU_FTR_TAU |
+ CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP,
+ .cpu_user_features = COMMON_PPC,
+ .icache_bsize = 32,
+ .dcache_bsize = 32,
+ .num_pmcs = 4,
+ .cpu_setup = __setup_cpu_750cx
+ },
+ { /* 750CX (82201 and 82202) */
+ .pvr_mask = 0xfffffff0,
+ .pvr_value = 0x00082200,
+ .cpu_name = "750CX",
+ .cpu_features = CPU_FTR_COMMON |
+ CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_MAYBE_CAN_DOZE |
+ CPU_FTR_USE_TB | CPU_FTR_L2CR | CPU_FTR_TAU |
+ CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP,
+ .cpu_user_features = COMMON_PPC,
+ .icache_bsize = 32,
+ .dcache_bsize = 32,
+ .num_pmcs = 4,
+ .cpu_setup = __setup_cpu_750cx
+ },
+ { /* 750CXe (82214) */
+ .pvr_mask = 0xfffffff0,
+ .pvr_value = 0x00082210,
+ .cpu_name = "750CXe",
+ .cpu_features = CPU_FTR_COMMON |
+ CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_MAYBE_CAN_DOZE |
+ CPU_FTR_USE_TB | CPU_FTR_L2CR | CPU_FTR_TAU |
+ CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP,
+ .cpu_user_features = COMMON_PPC,
+ .icache_bsize = 32,
+ .dcache_bsize = 32,
+ .num_pmcs = 4,
+ .cpu_setup = __setup_cpu_750cx
+ },
+ { /* 750FX rev 1.x */
+ .pvr_mask = 0xffffff00,
+ .pvr_value = 0x70000100,
+ .cpu_name = "750FX",
+ .cpu_features = CPU_FTR_COMMON |
+ CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_MAYBE_CAN_DOZE |
+ CPU_FTR_USE_TB | CPU_FTR_L2CR | CPU_FTR_TAU |
+ CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP |
+ CPU_FTR_DUAL_PLL_750FX | CPU_FTR_NO_DPM,
+ .cpu_user_features = COMMON_PPC,
+ .icache_bsize = 32,
+ .dcache_bsize = 32,
+ .num_pmcs = 4,
+ .cpu_setup = __setup_cpu_750
+ },
+ { /* 750FX rev 2.0 must disable HID0[DPM] */
+ .pvr_mask = 0xffffffff,
+ .pvr_value = 0x70000200,
+ .cpu_name = "750FX",
+ .cpu_features = CPU_FTR_COMMON |
+ CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_MAYBE_CAN_DOZE |
+ CPU_FTR_USE_TB | CPU_FTR_L2CR | CPU_FTR_TAU |
+ CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP |
+ CPU_FTR_NO_DPM,
+ .cpu_user_features = COMMON_PPC,
+ .icache_bsize = 32,
+ .dcache_bsize = 32,
+ .num_pmcs = 4,
+ .cpu_setup = __setup_cpu_750
+ },
+ { /* 750FX (All revs except 2.0) */
+ .pvr_mask = 0xffff0000,
+ .pvr_value = 0x70000000,
+ .cpu_name = "750FX",
+ .cpu_features = CPU_FTR_COMMON |
+ CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_MAYBE_CAN_DOZE |
+ CPU_FTR_USE_TB | CPU_FTR_L2CR | CPU_FTR_TAU |
+ CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP |
+ CPU_FTR_DUAL_PLL_750FX | CPU_FTR_HAS_HIGH_BATS,
+ .cpu_user_features = COMMON_PPC,
+ .icache_bsize = 32,
+ .dcache_bsize = 32,
+ .num_pmcs = 4,
+ .cpu_setup = __setup_cpu_750fx
+ },
+ { /* 750GX */
+ .pvr_mask = 0xffff0000,
+ .pvr_value = 0x70020000,
+ .cpu_name = "750GX",
+ .cpu_features = CPU_FTR_SPLIT_ID_CACHE |
+ CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB |
+ CPU_FTR_L2CR | CPU_FTR_TAU | CPU_FTR_HPTE_TABLE |
+ CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_DUAL_PLL_750FX |
+ CPU_FTR_HAS_HIGH_BATS,
+ .cpu_user_features = COMMON_PPC,
+ .icache_bsize = 32,
+ .dcache_bsize = 32,
+ .num_pmcs = 4,
+ .cpu_setup = __setup_cpu_750fx
+ },
+ { /* 740/750 (L2CR bit need fixup for 740) */
+ .pvr_mask = 0xffff0000,
+ .pvr_value = 0x00080000,
+ .cpu_name = "740/750",
+ .cpu_features = CPU_FTR_COMMON |
+ CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_MAYBE_CAN_DOZE |
+ CPU_FTR_USE_TB | CPU_FTR_L2CR | CPU_FTR_TAU |
+ CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP,
+ .cpu_user_features = COMMON_PPC,
+ .icache_bsize = 32,
+ .dcache_bsize = 32,
+ .num_pmcs = 4,
+ .cpu_setup = __setup_cpu_750
+ },
+ { /* 7400 rev 1.1 ? (no TAU) */
+ .pvr_mask = 0xffffffff,
+ .pvr_value = 0x000c1101,
+ .cpu_name = "7400 (1.1)",
+ .cpu_features = CPU_FTR_COMMON |
+ CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_MAYBE_CAN_DOZE |
+ CPU_FTR_USE_TB | CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP |
+ CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP,
+ .cpu_user_features = COMMON_PPC | PPC_FEATURE_ALTIVEC_COMP,
+ .icache_bsize = 32,
+ .dcache_bsize = 32,
+ .num_pmcs = 4,
+ .cpu_setup = __setup_cpu_7400
+ },
+ { /* 7400 */
+ .pvr_mask = 0xffff0000,
+ .pvr_value = 0x000c0000,
+ .cpu_name = "7400",
+ .cpu_features = CPU_FTR_COMMON |
+ CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_MAYBE_CAN_DOZE |
+ CPU_FTR_USE_TB | CPU_FTR_L2CR | CPU_FTR_TAU |
+ CPU_FTR_ALTIVEC_COMP | CPU_FTR_HPTE_TABLE |
+ CPU_FTR_MAYBE_CAN_NAP,
+ .cpu_user_features = COMMON_PPC | PPC_FEATURE_ALTIVEC_COMP,
+ .icache_bsize = 32,
+ .dcache_bsize = 32,
+ .num_pmcs = 4,
+ .cpu_setup = __setup_cpu_7400
+ },
+ { /* 7410 */
+ .pvr_mask = 0xffff0000,
+ .pvr_value = 0x800c0000,
+ .cpu_name = "7410",
+ .cpu_features = CPU_FTR_COMMON |
+ CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_MAYBE_CAN_DOZE |
+ CPU_FTR_USE_TB | CPU_FTR_L2CR | CPU_FTR_TAU |
+ CPU_FTR_ALTIVEC_COMP | CPU_FTR_HPTE_TABLE |
+ CPU_FTR_MAYBE_CAN_NAP,
+ .cpu_user_features = COMMON_PPC | PPC_FEATURE_ALTIVEC_COMP,
+ .icache_bsize = 32,
+ .dcache_bsize = 32,
+ .num_pmcs = 4,
+ .cpu_setup = __setup_cpu_7410
+ },
+ { /* 7450 2.0 - no doze/nap */
+ .pvr_mask = 0xffffffff,
+ .pvr_value = 0x80000200,
+ .cpu_name = "7450",
+ .cpu_features = CPU_FTR_COMMON |
+ CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB |
+ CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | CPU_FTR_L3CR |
+ CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 |
+ CPU_FTR_NEED_COHERENT,
+ .cpu_user_features = COMMON_PPC | PPC_FEATURE_ALTIVEC_COMP,
+ .icache_bsize = 32,
+ .dcache_bsize = 32,
+ .num_pmcs = 6,
+ .cpu_setup = __setup_cpu_745x
+ },
+ { /* 7450 2.1 */
+ .pvr_mask = 0xffffffff,
+ .pvr_value = 0x80000201,
+ .cpu_name = "7450",
+ .cpu_features = CPU_FTR_COMMON |
+ CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB |
+ CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR |
+ CPU_FTR_ALTIVEC_COMP | CPU_FTR_L3CR |
+ CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 |
+ CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_L3_DISABLE_NAP |
+ CPU_FTR_NEED_COHERENT,
+ .cpu_user_features = COMMON_PPC | PPC_FEATURE_ALTIVEC_COMP,
+ .icache_bsize = 32,
+ .dcache_bsize = 32,
+ .num_pmcs = 6,
+ .cpu_setup = __setup_cpu_745x
+ },
+ { /* 7450 2.3 and newer */
+ .pvr_mask = 0xffff0000,
+ .pvr_value = 0x80000000,
+ .cpu_name = "7450",
+ .cpu_features = CPU_FTR_COMMON |
+ CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB |
+ CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR |
+ CPU_FTR_ALTIVEC_COMP | CPU_FTR_L3CR |
+ CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 |
+ CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_NEED_COHERENT,
+ .cpu_user_features = COMMON_PPC | PPC_FEATURE_ALTIVEC_COMP,
+ .icache_bsize = 32,
+ .dcache_bsize = 32,
+ .num_pmcs = 6,
+ .cpu_setup = __setup_cpu_745x
+ },
+ { /* 7455 rev 1.x */
+ .pvr_mask = 0xffffff00,
+ .pvr_value = 0x80010100,
+ .cpu_name = "7455",
+ .cpu_features = CPU_FTR_COMMON |
+ CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB |
+ CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | CPU_FTR_L3CR |
+ CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 |
+ CPU_FTR_HAS_HIGH_BATS | CPU_FTR_NEED_COHERENT,
+ .cpu_user_features = COMMON_PPC | PPC_FEATURE_ALTIVEC_COMP,
+ .icache_bsize = 32,
+ .dcache_bsize = 32,
+ .num_pmcs = 6,
+ .cpu_setup = __setup_cpu_745x
+ },
+ { /* 7455 rev 2.0 */
+ .pvr_mask = 0xffffffff,
+ .pvr_value = 0x80010200,
+ .cpu_name = "7455",
+ .cpu_features = CPU_FTR_COMMON |
+ CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB |
+ CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR |
+ CPU_FTR_ALTIVEC_COMP | CPU_FTR_L3CR |
+ CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 |
+ CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_L3_DISABLE_NAP |
+ CPU_FTR_NEED_COHERENT | CPU_FTR_HAS_HIGH_BATS,
+ .cpu_user_features = COMMON_PPC | PPC_FEATURE_ALTIVEC_COMP,
+ .icache_bsize = 32,
+ .dcache_bsize = 32,
+ .num_pmcs = 6,
+ .cpu_setup = __setup_cpu_745x
+ },
+ { /* 7455 others */
+ .pvr_mask = 0xffff0000,
+ .pvr_value = 0x80010000,
+ .cpu_name = "7455",
+ .cpu_features = CPU_FTR_COMMON |
+ CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB |
+ CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR |
+ CPU_FTR_ALTIVEC_COMP | CPU_FTR_L3CR |
+ CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 |
+ CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_HAS_HIGH_BATS |
+ CPU_FTR_NEED_COHERENT,
+ .cpu_user_features = COMMON_PPC | PPC_FEATURE_ALTIVEC_COMP,
+ .icache_bsize = 32,
+ .dcache_bsize = 32,
+ .num_pmcs = 6,
+ .cpu_setup = __setup_cpu_745x
+ },
+ { /* 7447/7457 Rev 1.0 */
+ .pvr_mask = 0xffffffff,
+ .pvr_value = 0x80020100,
+ .cpu_name = "7447/7457",
+ .cpu_features = CPU_FTR_COMMON |
+ CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB |
+ CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR |
+ CPU_FTR_ALTIVEC_COMP | CPU_FTR_L3CR |
+ CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 |
+ CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_HAS_HIGH_BATS |
+ CPU_FTR_NEED_COHERENT | CPU_FTR_NO_BTIC,
+ .cpu_user_features = COMMON_PPC | PPC_FEATURE_ALTIVEC_COMP,
+ .icache_bsize = 32,
+ .dcache_bsize = 32,
+ .num_pmcs = 6,
+ .cpu_setup = __setup_cpu_745x
+ },
+ { /* 7447/7457 Rev 1.1 */
+ .pvr_mask = 0xffffffff,
+ .pvr_value = 0x80020101,
+ .cpu_name = "7447/7457",
+ .cpu_features = CPU_FTR_COMMON |
+ CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB |
+ CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR |
+ CPU_FTR_ALTIVEC_COMP | CPU_FTR_L3CR |
+ CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 |
+ CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_HAS_HIGH_BATS |
+ CPU_FTR_NEED_COHERENT | CPU_FTR_NO_BTIC,
+ .cpu_user_features = COMMON_PPC | PPC_FEATURE_ALTIVEC_COMP,
+ .icache_bsize = 32,
+ .dcache_bsize = 32,
+ .num_pmcs = 6,
+ .cpu_setup = __setup_cpu_745x
+ },
+ { /* 7447/7457 Rev 1.2 and later */
+ .pvr_mask = 0xffff0000,
+ .pvr_value = 0x80020000,
+ .cpu_name = "7447/7457",
+ .cpu_features = CPU_FTR_COMMON |
+ CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB |
+ CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR |
+ CPU_FTR_ALTIVEC_COMP | CPU_FTR_L3CR |
+ CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 |
+ CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_HAS_HIGH_BATS |
+ CPU_FTR_NEED_COHERENT,
+ .cpu_user_features = COMMON_PPC | PPC_FEATURE_ALTIVEC_COMP,
+ .icache_bsize = 32,
+ .dcache_bsize = 32,
+ .num_pmcs = 6,
+ .cpu_setup = __setup_cpu_745x
+ },
+ { /* 7447A */
+ .pvr_mask = 0xffff0000,
+ .pvr_value = 0x80030000,
+ .cpu_name = "7447A",
+ .cpu_features = CPU_FTR_COMMON |
+ CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB |
+ CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR |
+ CPU_FTR_ALTIVEC_COMP | CPU_FTR_HPTE_TABLE |
+ CPU_FTR_SPEC7450 | CPU_FTR_NAP_DISABLE_L2_PR |
+ CPU_FTR_HAS_HIGH_BATS | CPU_FTR_NEED_COHERENT,
+ .cpu_user_features = COMMON_PPC | PPC_FEATURE_ALTIVEC_COMP,
+ .icache_bsize = 32,
+ .dcache_bsize = 32,
+ .num_pmcs = 6,
+ .cpu_setup = __setup_cpu_745x
+ },
+ { /* 82xx (8240, 8245, 8260 are all 603e cores) */
+ .pvr_mask = 0x7fff0000,
+ .pvr_value = 0x00810000,
+ .cpu_name = "82xx",
+ .cpu_features = CPU_FTR_COMMON |
+ CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_MAYBE_CAN_DOZE |
+ CPU_FTR_USE_TB,
+ .cpu_user_features = COMMON_PPC,
+ .icache_bsize = 32,
+ .dcache_bsize = 32,
+ .cpu_setup = __setup_cpu_603
+ },
+ { /* All G2_LE (603e core, plus some) have the same pvr */
+ .pvr_mask = 0x7fff0000,
+ .pvr_value = 0x00820000,
+ .cpu_name = "G2_LE",
+ .cpu_features = CPU_FTR_SPLIT_ID_CACHE |
+ CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB |
+ CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_HAS_HIGH_BATS,
+ .cpu_user_features = COMMON_PPC,
+ .icache_bsize = 32,
+ .dcache_bsize = 32,
+ .cpu_setup = __setup_cpu_603
+ },
+ { /* e300 (a 603e core, plus some) on 83xx */
+ .pvr_mask = 0x7fff0000,
+ .pvr_value = 0x00830000,
+ .cpu_name = "e300",
+ .cpu_features = CPU_FTR_SPLIT_ID_CACHE |
+ CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB |
+ CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_HAS_HIGH_BATS,
+ .cpu_user_features = COMMON_PPC,
+ .icache_bsize = 32,
+ .dcache_bsize = 32,
+ .cpu_setup = __setup_cpu_603
+ },
+ { /* default match, we assume split I/D cache & TB (non-601)... */
+ .pvr_mask = 0x00000000,
+ .pvr_value = 0x00000000,
+ .cpu_name = "(generic PPC)",
+ .cpu_features = CPU_FTR_COMMON |
+ CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB |
+ CPU_FTR_HPTE_TABLE,
+ .cpu_user_features = COMMON_PPC,
+ .icache_bsize = 32,
+ .dcache_bsize = 32,
+ .cpu_setup = __setup_cpu_generic
+ },
+#endif /* CLASSIC_PPC */
+#ifdef CONFIG_PPC64BRIDGE
+ { /* Power3 */
+ .pvr_mask = 0xffff0000,
+ .pvr_value = 0x00400000,
+ .cpu_name = "Power3 (630)",
+ .cpu_features = CPU_FTR_COMMON |
+ CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB |
+ CPU_FTR_HPTE_TABLE,
+ .cpu_user_features = COMMON_PPC | PPC_FEATURE_64,
+ .icache_bsize = 128,
+ .dcache_bsize = 128,
+ .num_pmcs = 8,
+ .cpu_setup = __setup_cpu_power3
+ },
+ { /* Power3+ */
+ .pvr_mask = 0xffff0000,
+ .pvr_value = 0x00410000,
+ .cpu_name = "Power3 (630+)",
+ .cpu_features = CPU_FTR_COMMON |
+ CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB |
+ CPU_FTR_HPTE_TABLE,
+ .cpu_user_features = COMMON_PPC | PPC_FEATURE_64,
+ .icache_bsize = 128,
+ .dcache_bsize = 128,
+ .num_pmcs = 8,
+ .cpu_setup = __setup_cpu_power3
+ },
+ { /* I-star */
+ .pvr_mask = 0xffff0000,
+ .pvr_value = 0x00360000,
+ .cpu_name = "I-star",
+ .cpu_features = CPU_FTR_COMMON |
+ CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB |
+ CPU_FTR_HPTE_TABLE,
+ .cpu_user_features = COMMON_PPC | PPC_FEATURE_64,
+ .icache_bsize = 128,
+ .dcache_bsize = 128,
+ .num_pmcs = 8,
+ .cpu_setup = __setup_cpu_power3
+ },
+ { /* S-star */
+ .pvr_mask = 0xffff0000,
+ .pvr_value = 0x00370000,
+ .cpu_name = "S-star",
+ .cpu_features = CPU_FTR_COMMON |
+ CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB |
+ CPU_FTR_HPTE_TABLE,
+ .cpu_user_features = COMMON_PPC | PPC_FEATURE_64,
+ .icache_bsize = 128,
+ .dcache_bsize = 128,
+ .num_pmcs = 8,
+ .cpu_setup = __setup_cpu_power3
+ },
+#endif /* CONFIG_PPC64BRIDGE */
+#ifdef CONFIG_POWER4
+ { /* Power4 */
+ .pvr_mask = 0xffff0000,
+ .pvr_value = 0x00350000,
+ .cpu_name = "Power4",
+ .cpu_features = CPU_FTR_COMMON |
+ CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB |
+ CPU_FTR_HPTE_TABLE,
+ .cpu_user_features = COMMON_PPC | PPC_FEATURE_64,
+ .icache_bsize = 128,
+ .dcache_bsize = 128,
+ .num_pmcs = 8,
+ .cpu_setup = __setup_cpu_power4
+ },
+ { /* PPC970 */
+ .pvr_mask = 0xffff0000,
+ .pvr_value = 0x00390000,
+ .cpu_name = "PPC970",
+ .cpu_features = CPU_FTR_COMMON |
+ CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB |
+ CPU_FTR_HPTE_TABLE |
+ CPU_FTR_ALTIVEC_COMP | CPU_FTR_MAYBE_CAN_NAP,
+ .cpu_user_features = COMMON_PPC | PPC_FEATURE_64 |
+ PPC_FEATURE_ALTIVEC_COMP,
+ .icache_bsize = 128,
+ .dcache_bsize = 128,
+ .num_pmcs = 8,
+ .cpu_setup = __setup_cpu_ppc970
+ },
+ { /* PPC970FX */
+ .pvr_mask = 0xffff0000,
+ .pvr_value = 0x003c0000,
+ .cpu_name = "PPC970FX",
+ .cpu_features = CPU_FTR_COMMON |
+ CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB |
+ CPU_FTR_HPTE_TABLE |
+ CPU_FTR_ALTIVEC_COMP | CPU_FTR_MAYBE_CAN_NAP,
+ .cpu_user_features = COMMON_PPC | PPC_FEATURE_64 |
+ PPC_FEATURE_ALTIVEC_COMP,
+ .icache_bsize = 128,
+ .dcache_bsize = 128,
+ .num_pmcs = 8,
+ .cpu_setup = __setup_cpu_ppc970
+ },
+#endif /* CONFIG_POWER4 */
+#ifdef CONFIG_8xx
+ { /* 8xx */
+ .pvr_mask = 0xffff0000,
+ .pvr_value = 0x00500000,
+ .cpu_name = "8xx",
+ /* CPU_FTR_MAYBE_CAN_DOZE is possible,
+ * if the 8xx code is there.... */
+ .cpu_features = CPU_FTR_SPLIT_ID_CACHE |
+ CPU_FTR_USE_TB,
+ .cpu_user_features = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU,
+ .icache_bsize = 16,
+ .dcache_bsize = 16,
+ },
+#endif /* CONFIG_8xx */
+#ifdef CONFIG_40x
+ { /* 403GC */
+ .pvr_mask = 0xffffff00,
+ .pvr_value = 0x00200200,
+ .cpu_name = "403GC",
+ .cpu_features = CPU_FTR_SPLIT_ID_CACHE |
+ CPU_FTR_USE_TB,
+ .cpu_user_features = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU,
+ .icache_bsize = 16,
+ .dcache_bsize = 16,
+ },
+ { /* 403GCX */
+ .pvr_mask = 0xffffff00,
+ .pvr_value = 0x00201400,
+ .cpu_name = "403GCX",
+ .cpu_features = CPU_FTR_SPLIT_ID_CACHE |
+ CPU_FTR_USE_TB,
+ .cpu_user_features = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU,
+ .icache_bsize = 16,
+ .dcache_bsize = 16,
+ },
+ { /* 403G ?? */
+ .pvr_mask = 0xffff0000,
+ .pvr_value = 0x00200000,
+ .cpu_name = "403G ??",
+ .cpu_features = CPU_FTR_SPLIT_ID_CACHE |
+ CPU_FTR_USE_TB,
+ .cpu_user_features = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU,
+ .icache_bsize = 16,
+ .dcache_bsize = 16,
+ },
+ { /* 405GP */
+ .pvr_mask = 0xffff0000,
+ .pvr_value = 0x40110000,
+ .cpu_name = "405GP",
+ .cpu_features = CPU_FTR_SPLIT_ID_CACHE |
+ CPU_FTR_USE_TB,
+ .cpu_user_features = PPC_FEATURE_32 |
+ PPC_FEATURE_HAS_MMU | PPC_FEATURE_HAS_4xxMAC,
+ .icache_bsize = 32,
+ .dcache_bsize = 32,
+ },
+ { /* STB 03xxx */
+ .pvr_mask = 0xffff0000,
+ .pvr_value = 0x40130000,
+ .cpu_name = "STB03xxx",
+ .cpu_features = CPU_FTR_SPLIT_ID_CACHE |
+ CPU_FTR_USE_TB,
+ .cpu_user_features = PPC_FEATURE_32 |
+ PPC_FEATURE_HAS_MMU | PPC_FEATURE_HAS_4xxMAC,
+ .icache_bsize = 32,
+ .dcache_bsize = 32,
+ },
+ { /* STB 04xxx */
+ .pvr_mask = 0xffff0000,
+ .pvr_value = 0x41810000,
+ .cpu_name = "STB04xxx",
+ .cpu_features = CPU_FTR_SPLIT_ID_CACHE |
+ CPU_FTR_USE_TB,
+ .cpu_user_features = PPC_FEATURE_32 |
+ PPC_FEATURE_HAS_MMU | PPC_FEATURE_HAS_4xxMAC,
+ .icache_bsize = 32,
+ .dcache_bsize = 32,
+ },
+ { /* NP405L */
+ .pvr_mask = 0xffff0000,
+ .pvr_value = 0x41610000,
+ .cpu_name = "NP405L",
+ .cpu_features = CPU_FTR_SPLIT_ID_CACHE |
+ CPU_FTR_USE_TB,
+ .cpu_user_features = PPC_FEATURE_32 |
+ PPC_FEATURE_HAS_MMU | PPC_FEATURE_HAS_4xxMAC,
+ .icache_bsize = 32,
+ .dcache_bsize = 32,
+ },
+ { /* NP4GS3 */
+ .pvr_mask = 0xffff0000,
+ .pvr_value = 0x40B10000,
+ .cpu_name = "NP4GS3",
+ .cpu_features = CPU_FTR_SPLIT_ID_CACHE |
+ CPU_FTR_USE_TB,
+ .cpu_user_features = PPC_FEATURE_32 |
+ PPC_FEATURE_HAS_MMU | PPC_FEATURE_HAS_4xxMAC,
+ .icache_bsize = 32,
+ .dcache_bsize = 32,
+ },
+ { /* NP405H */
+ .pvr_mask = 0xffff0000,
+ .pvr_value = 0x41410000,
+ .cpu_name = "NP405H",
+ .cpu_features = CPU_FTR_SPLIT_ID_CACHE |
+ CPU_FTR_USE_TB,
+ .cpu_user_features = PPC_FEATURE_32 |
+ PPC_FEATURE_HAS_MMU | PPC_FEATURE_HAS_4xxMAC,
+ .icache_bsize = 32,
+ .dcache_bsize = 32,
+ },
+ { /* 405GPr */
+ .pvr_mask = 0xffff0000,
+ .pvr_value = 0x50910000,
+ .cpu_name = "405GPr",
+ .cpu_features = CPU_FTR_SPLIT_ID_CACHE |
+ CPU_FTR_USE_TB,
+ .cpu_user_features = PPC_FEATURE_32 |
+ PPC_FEATURE_HAS_MMU | PPC_FEATURE_HAS_4xxMAC,
+ .icache_bsize = 32,
+ .dcache_bsize = 32,
+ },
+ { /* STBx25xx */
+ .pvr_mask = 0xffff0000,
+ .pvr_value = 0x51510000,
+ .cpu_name = "STBx25xx",
+ .cpu_features = CPU_FTR_SPLIT_ID_CACHE |
+ CPU_FTR_USE_TB,
+ .cpu_user_features = PPC_FEATURE_32 |
+ PPC_FEATURE_HAS_MMU | PPC_FEATURE_HAS_4xxMAC,
+ .icache_bsize = 32,
+ .dcache_bsize = 32,
+ },
+ { /* 405LP */
+ .pvr_mask = 0xffff0000,
+ .pvr_value = 0x41F10000,
+ .cpu_name = "405LP",
+ .cpu_features = CPU_FTR_SPLIT_ID_CACHE |
+ CPU_FTR_USE_TB,
+ .cpu_user_features = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU,
+ .icache_bsize = 32,
+ .dcache_bsize = 32,
+ },
+ { /* Xilinx Virtex-II Pro */
+ .pvr_mask = 0xffff0000,
+ .pvr_value = 0x20010000,
+ .cpu_name = "Virtex-II Pro",
+ .cpu_features = CPU_FTR_SPLIT_ID_CACHE |
+ CPU_FTR_USE_TB,
+ .cpu_user_features = PPC_FEATURE_32 |
+ PPC_FEATURE_HAS_MMU | PPC_FEATURE_HAS_4xxMAC,
+ .icache_bsize = 32,
+ .dcache_bsize = 32,
+ },
+
+#endif /* CONFIG_40x */
+#ifdef CONFIG_44x
+ { /* 440GP Rev. B */
+ .pvr_mask = 0xf0000fff,
+ .pvr_value = 0x40000440,
+ .cpu_name = "440GP Rev. B",
+ .cpu_features = CPU_FTR_SPLIT_ID_CACHE |
+ CPU_FTR_USE_TB,
+ .cpu_user_features = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU,
+ .icache_bsize = 32,
+ .dcache_bsize = 32,
+ },
+ { /* 440GP Rev. C */
+ .pvr_mask = 0xf0000fff,
+ .pvr_value = 0x40000481,
+ .cpu_name = "440GP Rev. C",
+ .cpu_features = CPU_FTR_SPLIT_ID_CACHE |
+ CPU_FTR_USE_TB,
+ .cpu_user_features = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU,
+ .icache_bsize = 32,
+ .dcache_bsize = 32,
+ },
+ { /* 440GX Rev. A */
+ .pvr_mask = 0xf0000fff,
+ .pvr_value = 0x50000850,
+ .cpu_name = "440GX Rev. A",
+ .cpu_features = CPU_FTR_SPLIT_ID_CACHE |
+ CPU_FTR_USE_TB,
+ .cpu_user_features = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU,
+ .icache_bsize = 32,
+ .dcache_bsize = 32,
+ },
+ { /* 440GX Rev. B */
+ .pvr_mask = 0xf0000fff,
+ .pvr_value = 0x50000851,
+ .cpu_name = "440GX Rev. B",
+ .cpu_features = CPU_FTR_SPLIT_ID_CACHE |
+ CPU_FTR_USE_TB,
+ .cpu_user_features = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU,
+ .icache_bsize = 32,
+ .dcache_bsize = 32,
+ },
+ { /* 440GX Rev. C */
+ .pvr_mask = 0xf0000fff,
+ .pvr_value = 0x50000892,
+ .cpu_name = "440GX Rev. C",
+ .cpu_features = CPU_FTR_SPLIT_ID_CACHE |
+ CPU_FTR_USE_TB,
+ .cpu_user_features = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU,
+ .icache_bsize = 32,
+ .dcache_bsize = 32,
+ },
+#endif /* CONFIG_44x */
+#ifdef CONFIG_E500
+ { /* e500 */
+ .pvr_mask = 0xffff0000,
+ .pvr_value = 0x80200000,
+ .cpu_name = "e500",
+ /* xxx - galak: add CPU_FTR_MAYBE_CAN_DOZE */
+ .cpu_features = CPU_FTR_SPLIT_ID_CACHE |
+ CPU_FTR_USE_TB,
+ .cpu_user_features = PPC_FEATURE_32 |
+ PPC_FEATURE_HAS_MMU | PPC_FEATURE_SPE_COMP |
+ PPC_FEATURE_HAS_EFP_SINGLE,
+ .icache_bsize = 32,
+ .dcache_bsize = 32,
+ .num_pmcs = 4,
+ },
+#endif
+#if !CLASSIC_PPC
+ { /* default match */
+ .pvr_mask = 0x00000000,
+ .pvr_value = 0x00000000,
+ .cpu_name = "(generic PPC)",
+ .cpu_features = CPU_FTR_COMMON,
+ .cpu_user_features = PPC_FEATURE_32,
+ .icache_bsize = 32,
+ .dcache_bsize = 32,
+ }
+#endif /* !CLASSIC_PPC */
+};
diff --git a/arch/ppc/kernel/dma-mapping.c b/arch/ppc/kernel/dma-mapping.c
new file mode 100644
index 0000000..e0c631cf
--- /dev/null
+++ b/arch/ppc/kernel/dma-mapping.c
@@ -0,0 +1,447 @@
+/*
+ * PowerPC version derived from arch/arm/mm/consistent.c
+ * Copyright (C) 2001 Dan Malek (dmalek@jlc.net)
+ *
+ * Copyright (C) 2000 Russell King
+ *
+ * Consistent memory allocators. Used for DMA devices that want to
+ * share uncached memory with the processor core. The function return
+ * is the virtual address and 'dma_handle' is the physical address.
+ * Mostly stolen from the ARM port, with some changes for PowerPC.
+ * -- Dan
+ *
+ * Reorganized to get rid of the arch-specific consistent_* functions
+ * and provide non-coherent implementations for the DMA API. -Matt
+ *
+ * Added in_interrupt() safe dma_alloc_coherent()/dma_free_coherent()
+ * implementation. This is pulled straight from ARM and barely
+ * modified. -Matt
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/types.h>
+#include <linux/ptrace.h>
+#include <linux/mman.h>
+#include <linux/mm.h>
+#include <linux/swap.h>
+#include <linux/stddef.h>
+#include <linux/vmalloc.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/bootmem.h>
+#include <linux/highmem.h>
+#include <linux/dma-mapping.h>
+#include <linux/hardirq.h>
+
+#include <asm/pgalloc.h>
+#include <asm/prom.h>
+#include <asm/io.h>
+#include <asm/mmu_context.h>
+#include <asm/pgtable.h>
+#include <asm/mmu.h>
+#include <asm/uaccess.h>
+#include <asm/smp.h>
+#include <asm/machdep.h>
+
+int map_page(unsigned long va, phys_addr_t pa, int flags);
+
+#include <asm/tlbflush.h>
+
+/*
+ * This address range defaults to a value that is safe for all
+ * platforms which currently set CONFIG_NOT_COHERENT_CACHE. It
+ * can be further configured for specific applications under
+ * the "Advanced Setup" menu. -Matt
+ */
+#define CONSISTENT_BASE (CONFIG_CONSISTENT_START)
+#define CONSISTENT_END (CONFIG_CONSISTENT_START + CONFIG_CONSISTENT_SIZE)
+#define CONSISTENT_OFFSET(x) (((unsigned long)(x) - CONSISTENT_BASE) >> PAGE_SHIFT)
+
+/*
+ * This is the page table (2MB) covering uncached, DMA consistent allocations
+ */
+static pte_t *consistent_pte;
+static DEFINE_SPINLOCK(consistent_lock);
+
+/*
+ * VM region handling support.
+ *
+ * This should become something generic, handling VM region allocations for
+ * vmalloc and similar (ioremap, module space, etc).
+ *
+ * I envisage vmalloc()'s supporting vm_struct becoming:
+ *
+ * struct vm_struct {
+ * struct vm_region region;
+ * unsigned long flags;
+ * struct page **pages;
+ * unsigned int nr_pages;
+ * unsigned long phys_addr;
+ * };
+ *
+ * get_vm_area() would then call vm_region_alloc with an appropriate
+ * struct vm_region head (eg):
+ *
+ * struct vm_region vmalloc_head = {
+ * .vm_list = LIST_HEAD_INIT(vmalloc_head.vm_list),
+ * .vm_start = VMALLOC_START,
+ * .vm_end = VMALLOC_END,
+ * };
+ *
+ * However, vmalloc_head.vm_start is variable (typically, it is dependent on
+ * the amount of RAM found at boot time.) I would imagine that get_vm_area()
+ * would have to initialise this each time prior to calling vm_region_alloc().
+ */
+struct vm_region {
+ struct list_head vm_list;
+ unsigned long vm_start;
+ unsigned long vm_end;
+};
+
+static struct vm_region consistent_head = {
+ .vm_list = LIST_HEAD_INIT(consistent_head.vm_list),
+ .vm_start = CONSISTENT_BASE,
+ .vm_end = CONSISTENT_END,
+};
+
+static struct vm_region *
+vm_region_alloc(struct vm_region *head, size_t size, int gfp)
+{
+ unsigned long addr = head->vm_start, end = head->vm_end - size;
+ unsigned long flags;
+ struct vm_region *c, *new;
+
+ new = kmalloc(sizeof(struct vm_region), gfp);
+ if (!new)
+ goto out;
+
+ spin_lock_irqsave(&consistent_lock, flags);
+
+ list_for_each_entry(c, &head->vm_list, vm_list) {
+ if ((addr + size) < addr)
+ goto nospc;
+ if ((addr + size) <= c->vm_start)
+ goto found;
+ addr = c->vm_end;
+ if (addr > end)
+ goto nospc;
+ }
+
+ found:
+ /*
+ * Insert this entry _before_ the one we found.
+ */
+ list_add_tail(&new->vm_list, &c->vm_list);
+ new->vm_start = addr;
+ new->vm_end = addr + size;
+
+ spin_unlock_irqrestore(&consistent_lock, flags);
+ return new;
+
+ nospc:
+ spin_unlock_irqrestore(&consistent_lock, flags);
+ kfree(new);
+ out:
+ return NULL;
+}
+
+static struct vm_region *vm_region_find(struct vm_region *head, unsigned long addr)
+{
+ struct vm_region *c;
+
+ list_for_each_entry(c, &head->vm_list, vm_list) {
+ if (c->vm_start == addr)
+ goto out;
+ }
+ c = NULL;
+ out:
+ return c;
+}
+
+/*
+ * Allocate DMA-coherent memory space and return both the kernel remapped
+ * virtual and bus address for that space.
+ */
+void *
+__dma_alloc_coherent(size_t size, dma_addr_t *handle, int gfp)
+{
+ struct page *page;
+ struct vm_region *c;
+ unsigned long order;
+ u64 mask = 0x00ffffff, limit; /* ISA default */
+
+ if (!consistent_pte) {
+ printk(KERN_ERR "%s: not initialised\n", __func__);
+ dump_stack();
+ return NULL;
+ }
+
+ size = PAGE_ALIGN(size);
+ limit = (mask + 1) & ~mask;
+ if ((limit && size >= limit) || size >= (CONSISTENT_END - CONSISTENT_BASE)) {
+ printk(KERN_WARNING "coherent allocation too big (requested %#x mask %#Lx)\n",
+ size, mask);
+ return NULL;
+ }
+
+ order = get_order(size);
+
+ if (mask != 0xffffffff)
+ gfp |= GFP_DMA;
+
+ page = alloc_pages(gfp, order);
+ if (!page)
+ goto no_page;
+
+ /*
+ * Invalidate any data that might be lurking in the
+ * kernel direct-mapped region for device DMA.
+ */
+ {
+ unsigned long kaddr = (unsigned long)page_address(page);
+ memset(page_address(page), 0, size);
+ flush_dcache_range(kaddr, kaddr + size);
+ }
+
+ /*
+ * Allocate a virtual address in the consistent mapping region.
+ */
+ c = vm_region_alloc(&consistent_head, size,
+ gfp & ~(__GFP_DMA | __GFP_HIGHMEM));
+ if (c) {
+ unsigned long vaddr = c->vm_start;
+ pte_t *pte = consistent_pte + CONSISTENT_OFFSET(vaddr);
+ struct page *end = page + (1 << order);
+
+ /*
+ * Set the "dma handle"
+ */
+ *handle = page_to_bus(page);
+
+ do {
+ BUG_ON(!pte_none(*pte));
+
+ set_page_count(page, 1);
+ SetPageReserved(page);
+ set_pte_at(&init_mm, vaddr,
+ pte, mk_pte(page, pgprot_noncached(PAGE_KERNEL)));
+ page++;
+ pte++;
+ vaddr += PAGE_SIZE;
+ } while (size -= PAGE_SIZE);
+
+ /*
+ * Free the otherwise unused pages.
+ */
+ while (page < end) {
+ set_page_count(page, 1);
+ __free_page(page);
+ page++;
+ }
+
+ return (void *)c->vm_start;
+ }
+
+ if (page)
+ __free_pages(page, order);
+ no_page:
+ return NULL;
+}
+EXPORT_SYMBOL(__dma_alloc_coherent);
+
+/*
+ * free a page as defined by the above mapping.
+ */
+void __dma_free_coherent(size_t size, void *vaddr)
+{
+ struct vm_region *c;
+ unsigned long flags, addr;
+ pte_t *ptep;
+
+ size = PAGE_ALIGN(size);
+
+ spin_lock_irqsave(&consistent_lock, flags);
+
+ c = vm_region_find(&consistent_head, (unsigned long)vaddr);
+ if (!c)
+ goto no_area;
+
+ if ((c->vm_end - c->vm_start) != size) {
+ printk(KERN_ERR "%s: freeing wrong coherent size (%ld != %d)\n",
+ __func__, c->vm_end - c->vm_start, size);
+ dump_stack();
+ size = c->vm_end - c->vm_start;
+ }
+
+ ptep = consistent_pte + CONSISTENT_OFFSET(c->vm_start);
+ addr = c->vm_start;
+ do {
+ pte_t pte = ptep_get_and_clear(&init_mm, addr, ptep);
+ unsigned long pfn;
+
+ ptep++;
+ addr += PAGE_SIZE;
+
+ if (!pte_none(pte) && pte_present(pte)) {
+ pfn = pte_pfn(pte);
+
+ if (pfn_valid(pfn)) {
+ struct page *page = pfn_to_page(pfn);
+ ClearPageReserved(page);
+
+ __free_page(page);
+ continue;
+ }
+ }
+
+ printk(KERN_CRIT "%s: bad page in kernel page table\n",
+ __func__);
+ } while (size -= PAGE_SIZE);
+
+ flush_tlb_kernel_range(c->vm_start, c->vm_end);
+
+ list_del(&c->vm_list);
+
+ spin_unlock_irqrestore(&consistent_lock, flags);
+
+ kfree(c);
+ return;
+
+ no_area:
+ spin_unlock_irqrestore(&consistent_lock, flags);
+ printk(KERN_ERR "%s: trying to free invalid coherent area: %p\n",
+ __func__, vaddr);
+ dump_stack();
+}
+EXPORT_SYMBOL(__dma_free_coherent);
+
+/*
+ * Initialise the consistent memory allocation.
+ */
+static int __init dma_alloc_init(void)
+{
+ pgd_t *pgd;
+ pmd_t *pmd;
+ pte_t *pte;
+ int ret = 0;
+
+ spin_lock(&init_mm.page_table_lock);
+
+ do {
+ pgd = pgd_offset(&init_mm, CONSISTENT_BASE);
+ pmd = pmd_alloc(&init_mm, pgd, CONSISTENT_BASE);
+ if (!pmd) {
+ printk(KERN_ERR "%s: no pmd tables\n", __func__);
+ ret = -ENOMEM;
+ break;
+ }
+ WARN_ON(!pmd_none(*pmd));
+
+ pte = pte_alloc_kernel(&init_mm, pmd, CONSISTENT_BASE);
+ if (!pte) {
+ printk(KERN_ERR "%s: no pte tables\n", __func__);
+ ret = -ENOMEM;
+ break;
+ }
+
+ consistent_pte = pte;
+ } while (0);
+
+ spin_unlock(&init_mm.page_table_lock);
+
+ return ret;
+}
+
+core_initcall(dma_alloc_init);
+
+/*
+ * make an area consistent.
+ */
+void __dma_sync(void *vaddr, size_t size, int direction)
+{
+ unsigned long start = (unsigned long)vaddr;
+ unsigned long end = start + size;
+
+ switch (direction) {
+ case DMA_NONE:
+ BUG();
+ case DMA_FROM_DEVICE: /* invalidate only */
+ invalidate_dcache_range(start, end);
+ break;
+ case DMA_TO_DEVICE: /* writeback only */
+ clean_dcache_range(start, end);
+ break;
+ case DMA_BIDIRECTIONAL: /* writeback and invalidate */
+ flush_dcache_range(start, end);
+ break;
+ }
+}
+EXPORT_SYMBOL(__dma_sync);
+
+#ifdef CONFIG_HIGHMEM
+/*
+ * __dma_sync_page() implementation for systems using highmem.
+ * In this case, each page of a buffer must be kmapped/kunmapped
+ * in order to have a virtual address for __dma_sync(). This must
+ * not sleep so kmap_atmomic()/kunmap_atomic() are used.
+ *
+ * Note: yes, it is possible and correct to have a buffer extend
+ * beyond the first page.
+ */
+static inline void __dma_sync_page_highmem(struct page *page,
+ unsigned long offset, size_t size, int direction)
+{
+ size_t seg_size = min((size_t)PAGE_SIZE, size) - offset;
+ size_t cur_size = seg_size;
+ unsigned long flags, start, seg_offset = offset;
+ int nr_segs = PAGE_ALIGN(size + (PAGE_SIZE - offset))/PAGE_SIZE;
+ int seg_nr = 0;
+
+ local_irq_save(flags);
+
+ do {
+ start = (unsigned long)kmap_atomic(page + seg_nr,
+ KM_PPC_SYNC_PAGE) + seg_offset;
+
+ /* Sync this buffer segment */
+ __dma_sync((void *)start, seg_size, direction);
+ kunmap_atomic((void *)start, KM_PPC_SYNC_PAGE);
+ seg_nr++;
+
+ /* Calculate next buffer segment size */
+ seg_size = min((size_t)PAGE_SIZE, size - cur_size);
+
+ /* Add the segment size to our running total */
+ cur_size += seg_size;
+ seg_offset = 0;
+ } while (seg_nr < nr_segs);
+
+ local_irq_restore(flags);
+}
+#endif /* CONFIG_HIGHMEM */
+
+/*
+ * __dma_sync_page makes memory consistent. identical to __dma_sync, but
+ * takes a struct page instead of a virtual address
+ */
+void __dma_sync_page(struct page *page, unsigned long offset,
+ size_t size, int direction)
+{
+#ifdef CONFIG_HIGHMEM
+ __dma_sync_page_highmem(page, offset, size, direction);
+#else
+ unsigned long start = (unsigned long)page_address(page) + offset;
+ __dma_sync((void *)start, size, direction);
+#endif
+}
+EXPORT_SYMBOL(__dma_sync_page);
diff --git a/arch/ppc/kernel/entry.S b/arch/ppc/kernel/entry.S
new file mode 100644
index 0000000..035217d
--- /dev/null
+++ b/arch/ppc/kernel/entry.S
@@ -0,0 +1,969 @@
+/*
+ * PowerPC version
+ * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
+ * Rewritten by Cort Dougan (cort@fsmlabs.com) for PReP
+ * Copyright (C) 1996 Cort Dougan <cort@fsmlabs.com>
+ * Adapted for Power Macintosh by Paul Mackerras.
+ * Low-level exception handlers and MMU support
+ * rewritten by Paul Mackerras.
+ * Copyright (C) 1996 Paul Mackerras.
+ * MPC8xx modifications Copyright (C) 1997 Dan Malek (dmalek@jlc.net).
+ *
+ * This file contains the system call entry code, context switch
+ * code, and exception/interrupt return code for PowerPC.
+ *
+ * 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.
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/errno.h>
+#include <linux/sys.h>
+#include <linux/threads.h>
+#include <asm/processor.h>
+#include <asm/page.h>
+#include <asm/mmu.h>
+#include <asm/cputable.h>
+#include <asm/thread_info.h>
+#include <asm/ppc_asm.h>
+#include <asm/offsets.h>
+#include <asm/unistd.h>
+
+#undef SHOW_SYSCALLS
+#undef SHOW_SYSCALLS_TASK
+
+/*
+ * MSR_KERNEL is > 0x10000 on 4xx/Book-E since it include MSR_CE.
+ */
+#if MSR_KERNEL >= 0x10000
+#define LOAD_MSR_KERNEL(r, x) lis r,(x)@h; ori r,r,(x)@l
+#else
+#define LOAD_MSR_KERNEL(r, x) li r,(x)
+#endif
+
+#ifdef CONFIG_BOOKE
+#include "head_booke.h"
+ .globl mcheck_transfer_to_handler
+mcheck_transfer_to_handler:
+ mtspr MCHECK_SPRG,r8
+ BOOKE_LOAD_MCHECK_STACK
+ lwz r0,GPR10-INT_FRAME_SIZE(r8)
+ stw r0,GPR10(r11)
+ lwz r0,GPR11-INT_FRAME_SIZE(r8)
+ stw r0,GPR11(r11)
+ mfspr r8,MCHECK_SPRG
+ b transfer_to_handler_full
+
+ .globl crit_transfer_to_handler
+crit_transfer_to_handler:
+ mtspr CRIT_SPRG,r8
+ BOOKE_LOAD_CRIT_STACK
+ lwz r0,GPR10-INT_FRAME_SIZE(r8)
+ stw r0,GPR10(r11)
+ lwz r0,GPR11-INT_FRAME_SIZE(r8)
+ stw r0,GPR11(r11)
+ mfspr r8,CRIT_SPRG
+ /* fall through */
+#endif
+
+#ifdef CONFIG_40x
+ .globl crit_transfer_to_handler
+crit_transfer_to_handler:
+ lwz r0,crit_r10@l(0)
+ stw r0,GPR10(r11)
+ lwz r0,crit_r11@l(0)
+ stw r0,GPR11(r11)
+ /* fall through */
+#endif
+
+/*
+ * This code finishes saving the registers to the exception frame
+ * and jumps to the appropriate handler for the exception, turning
+ * on address translation.
+ * Note that we rely on the caller having set cr0.eq iff the exception
+ * occurred in kernel mode (i.e. MSR:PR = 0).
+ */
+ .globl transfer_to_handler_full
+transfer_to_handler_full:
+ SAVE_NVGPRS(r11)
+ /* fall through */
+
+ .globl transfer_to_handler
+transfer_to_handler:
+ stw r2,GPR2(r11)
+ stw r12,_NIP(r11)
+ stw r9,_MSR(r11)
+ andi. r2,r9,MSR_PR
+ mfctr r12
+ mfspr r2,SPRN_XER
+ stw r12,_CTR(r11)
+ stw r2,_XER(r11)
+ mfspr r12,SPRN_SPRG3
+ addi r2,r12,-THREAD
+ tovirt(r2,r2) /* set r2 to current */
+ beq 2f /* if from user, fix up THREAD.regs */
+ addi r11,r1,STACK_FRAME_OVERHEAD
+ stw r11,PT_REGS(r12)
+#if defined(CONFIG_40x) || defined(CONFIG_BOOKE)
+ /* Check to see if the dbcr0 register is set up to debug. Use the
+ single-step bit to do this. */
+ lwz r12,THREAD_DBCR0(r12)
+ andis. r12,r12,DBCR0_IC@h
+ beq+ 3f
+ /* From user and task is ptraced - load up global dbcr0 */
+ li r12,-1 /* clear all pending debug events */
+ mtspr SPRN_DBSR,r12
+ lis r11,global_dbcr0@ha
+ tophys(r11,r11)
+ addi r11,r11,global_dbcr0@l
+ lwz r12,0(r11)
+ mtspr SPRN_DBCR0,r12
+ lwz r12,4(r11)
+ addi r12,r12,-1
+ stw r12,4(r11)
+#endif
+ b 3f
+2: /* if from kernel, check interrupted DOZE/NAP mode and
+ * check for stack overflow
+ */
+#ifdef CONFIG_6xx
+ mfspr r11,SPRN_HID0
+ mtcr r11
+BEGIN_FTR_SECTION
+ bt- 8,power_save_6xx_restore /* Check DOZE */
+END_FTR_SECTION_IFSET(CPU_FTR_CAN_DOZE)
+BEGIN_FTR_SECTION
+ bt- 9,power_save_6xx_restore /* Check NAP */
+END_FTR_SECTION_IFSET(CPU_FTR_CAN_NAP)
+#endif /* CONFIG_6xx */
+ .globl transfer_to_handler_cont
+transfer_to_handler_cont:
+ lwz r11,THREAD_INFO-THREAD(r12)
+ cmplw r1,r11 /* if r1 <= current->thread_info */
+ ble- stack_ovf /* then the kernel stack overflowed */
+3:
+ mflr r9
+ lwz r11,0(r9) /* virtual address of handler */
+ lwz r9,4(r9) /* where to go when done */
+ FIX_SRR1(r10,r12)
+ mtspr SPRN_SRR0,r11
+ mtspr SPRN_SRR1,r10
+ mtlr r9
+ SYNC
+ RFI /* jump to handler, enable MMU */
+
+/*
+ * On kernel stack overflow, load up an initial stack pointer
+ * and call StackOverflow(regs), which should not return.
+ */
+stack_ovf:
+ /* sometimes we use a statically-allocated stack, which is OK. */
+ lis r11,_end@h
+ ori r11,r11,_end@l
+ cmplw r1,r11
+ ble 3b /* r1 <= &_end is OK */
+ SAVE_NVGPRS(r11)
+ addi r3,r1,STACK_FRAME_OVERHEAD
+ lis r1,init_thread_union@ha
+ addi r1,r1,init_thread_union@l
+ addi r1,r1,THREAD_SIZE-STACK_FRAME_OVERHEAD
+ lis r9,StackOverflow@ha
+ addi r9,r9,StackOverflow@l
+ LOAD_MSR_KERNEL(r10,MSR_KERNEL)
+ FIX_SRR1(r10,r12)
+ mtspr SPRN_SRR0,r9
+ mtspr SPRN_SRR1,r10
+ SYNC
+ RFI
+
+/*
+ * Handle a system call.
+ */
+ .stabs "arch/ppc/kernel/",N_SO,0,0,0f
+ .stabs "entry.S",N_SO,0,0,0f
+0:
+
+_GLOBAL(DoSyscall)
+ stw r0,THREAD+LAST_SYSCALL(r2)
+ stw r3,ORIG_GPR3(r1)
+ li r12,0
+ stw r12,RESULT(r1)
+ lwz r11,_CCR(r1) /* Clear SO bit in CR */
+ rlwinm r11,r11,0,4,2
+ stw r11,_CCR(r1)
+#ifdef SHOW_SYSCALLS
+ bl do_show_syscall
+#endif /* SHOW_SYSCALLS */
+ rlwinm r10,r1,0,0,18 /* current_thread_info() */
+ lwz r11,TI_LOCAL_FLAGS(r10)
+ rlwinm r11,r11,0,~_TIFL_FORCE_NOERROR
+ stw r11,TI_LOCAL_FLAGS(r10)
+ lwz r11,TI_FLAGS(r10)
+ andi. r11,r11,_TIF_SYSCALL_TRACE
+ bne- syscall_dotrace
+syscall_dotrace_cont:
+ cmplwi 0,r0,NR_syscalls
+ lis r10,sys_call_table@h
+ ori r10,r10,sys_call_table@l
+ slwi r0,r0,2
+ bge- 66f
+ lwzx r10,r10,r0 /* Fetch system call handler [ptr] */
+ mtlr r10
+ addi r9,r1,STACK_FRAME_OVERHEAD
+ blrl /* Call handler */
+ .globl ret_from_syscall
+ret_from_syscall:
+#ifdef SHOW_SYSCALLS
+ bl do_show_syscall_exit
+#endif
+ mr r6,r3
+ li r11,-_LAST_ERRNO
+ cmplw 0,r3,r11
+ rlwinm r12,r1,0,0,18 /* current_thread_info() */
+ blt+ 30f
+ lwz r11,TI_LOCAL_FLAGS(r12)
+ andi. r11,r11,_TIFL_FORCE_NOERROR
+ bne 30f
+ neg r3,r3
+ lwz r10,_CCR(r1) /* Set SO bit in CR */
+ oris r10,r10,0x1000
+ stw r10,_CCR(r1)
+
+ /* disable interrupts so current_thread_info()->flags can't change */
+30: LOAD_MSR_KERNEL(r10,MSR_KERNEL) /* doesn't include MSR_EE */
+ SYNC
+ MTMSRD(r10)
+ lwz r9,TI_FLAGS(r12)
+ andi. r0,r9,(_TIF_SYSCALL_TRACE|_TIF_SIGPENDING|_TIF_NEED_RESCHED)
+ bne- syscall_exit_work
+syscall_exit_cont:
+#if defined(CONFIG_4xx) || defined(CONFIG_BOOKE)
+ /* If the process has its own DBCR0 value, load it up. The single
+ step bit tells us that dbcr0 should be loaded. */
+ lwz r0,THREAD+THREAD_DBCR0(r2)
+ andis. r10,r0,DBCR0_IC@h
+ bnel- load_dbcr0
+#endif
+ stwcx. r0,0,r1 /* to clear the reservation */
+ lwz r4,_LINK(r1)
+ lwz r5,_CCR(r1)
+ mtlr r4
+ mtcr r5
+ lwz r7,_NIP(r1)
+ lwz r8,_MSR(r1)
+ FIX_SRR1(r8, r0)
+ lwz r2,GPR2(r1)
+ lwz r1,GPR1(r1)
+ mtspr SPRN_SRR0,r7
+ mtspr SPRN_SRR1,r8
+ SYNC
+ RFI
+
+66: li r3,-ENOSYS
+ b ret_from_syscall
+
+ .globl ret_from_fork
+ret_from_fork:
+ REST_NVGPRS(r1)
+ bl schedule_tail
+ li r3,0
+ b ret_from_syscall
+
+/* Traced system call support */
+syscall_dotrace:
+ SAVE_NVGPRS(r1)
+ li r0,0xc00
+ stw r0,TRAP(r1)
+ bl do_syscall_trace
+ lwz r0,GPR0(r1) /* Restore original registers */
+ lwz r3,GPR3(r1)
+ lwz r4,GPR4(r1)
+ lwz r5,GPR5(r1)
+ lwz r6,GPR6(r1)
+ lwz r7,GPR7(r1)
+ lwz r8,GPR8(r1)
+ REST_NVGPRS(r1)
+ b syscall_dotrace_cont
+
+syscall_exit_work:
+ stw r6,RESULT(r1) /* Save result */
+ stw r3,GPR3(r1) /* Update return value */
+ andi. r0,r9,_TIF_SYSCALL_TRACE
+ beq 5f
+ ori r10,r10,MSR_EE
+ SYNC
+ MTMSRD(r10) /* re-enable interrupts */
+ lwz r4,TRAP(r1)
+ andi. r4,r4,1
+ beq 4f
+ SAVE_NVGPRS(r1)
+ li r4,0xc00
+ stw r4,TRAP(r1)
+4:
+ bl do_syscall_trace
+ REST_NVGPRS(r1)
+2:
+ lwz r3,GPR3(r1)
+ LOAD_MSR_KERNEL(r10,MSR_KERNEL) /* doesn't include MSR_EE */
+ SYNC
+ MTMSRD(r10) /* disable interrupts again */
+ rlwinm r12,r1,0,0,18 /* current_thread_info() */
+ lwz r9,TI_FLAGS(r12)
+5:
+ andi. r0,r9,_TIF_NEED_RESCHED
+ bne 1f
+ lwz r5,_MSR(r1)
+ andi. r5,r5,MSR_PR
+ beq syscall_exit_cont
+ andi. r0,r9,_TIF_SIGPENDING
+ beq syscall_exit_cont
+ b do_user_signal
+1:
+ ori r10,r10,MSR_EE
+ SYNC
+ MTMSRD(r10) /* re-enable interrupts */
+ bl schedule
+ b 2b
+
+#ifdef SHOW_SYSCALLS
+do_show_syscall:
+#ifdef SHOW_SYSCALLS_TASK
+ lis r11,show_syscalls_task@ha
+ lwz r11,show_syscalls_task@l(r11)
+ cmp 0,r2,r11
+ bnelr
+#endif
+ stw r31,GPR31(r1)
+ mflr r31
+ lis r3,7f@ha
+ addi r3,r3,7f@l
+ lwz r4,GPR0(r1)
+ lwz r5,GPR3(r1)
+ lwz r6,GPR4(r1)
+ lwz r7,GPR5(r1)
+ lwz r8,GPR6(r1)
+ lwz r9,GPR7(r1)
+ bl printk
+ lis r3,77f@ha
+ addi r3,r3,77f@l
+ lwz r4,GPR8(r1)
+ mr r5,r2
+ bl printk
+ lwz r0,GPR0(r1)
+ lwz r3,GPR3(r1)
+ lwz r4,GPR4(r1)
+ lwz r5,GPR5(r1)
+ lwz r6,GPR6(r1)
+ lwz r7,GPR7(r1)
+ lwz r8,GPR8(r1)
+ mtlr r31
+ lwz r31,GPR31(r1)
+ blr
+
+do_show_syscall_exit:
+#ifdef SHOW_SYSCALLS_TASK
+ lis r11,show_syscalls_task@ha
+ lwz r11,show_syscalls_task@l(r11)
+ cmp 0,r2,r11
+ bnelr
+#endif
+ stw r31,GPR31(r1)
+ mflr r31
+ stw r3,RESULT(r1) /* Save result */
+ mr r4,r3
+ lis r3,79f@ha
+ addi r3,r3,79f@l
+ bl printk
+ lwz r3,RESULT(r1)
+ mtlr r31
+ lwz r31,GPR31(r1)
+ blr
+
+7: .string "syscall %d(%x, %x, %x, %x, %x, "
+77: .string "%x), current=%p\n"
+79: .string " -> %x\n"
+ .align 2,0
+
+#ifdef SHOW_SYSCALLS_TASK
+ .data
+ .globl show_syscalls_task
+show_syscalls_task:
+ .long -1
+ .text
+#endif
+#endif /* SHOW_SYSCALLS */
+
+/*
+ * The sigsuspend and rt_sigsuspend system calls can call do_signal
+ * and thus put the process into the stopped state where we might
+ * want to examine its user state with ptrace. Therefore we need
+ * to save all the nonvolatile registers (r13 - r31) before calling
+ * the C code.
+ */
+ .globl ppc_sigsuspend
+ppc_sigsuspend:
+ SAVE_NVGPRS(r1)
+ lwz r0,TRAP(r1)
+ rlwinm r0,r0,0,0,30 /* clear LSB to indicate full */
+ stw r0,TRAP(r1) /* register set saved */
+ b sys_sigsuspend
+
+ .globl ppc_rt_sigsuspend
+ppc_rt_sigsuspend:
+ SAVE_NVGPRS(r1)
+ lwz r0,TRAP(r1)
+ rlwinm r0,r0,0,0,30
+ stw r0,TRAP(r1)
+ b sys_rt_sigsuspend
+
+ .globl ppc_fork
+ppc_fork:
+ SAVE_NVGPRS(r1)
+ lwz r0,TRAP(r1)
+ rlwinm r0,r0,0,0,30 /* clear LSB to indicate full */
+ stw r0,TRAP(r1) /* register set saved */
+ b sys_fork
+
+ .globl ppc_vfork
+ppc_vfork:
+ SAVE_NVGPRS(r1)
+ lwz r0,TRAP(r1)
+ rlwinm r0,r0,0,0,30 /* clear LSB to indicate full */
+ stw r0,TRAP(r1) /* register set saved */
+ b sys_vfork
+
+ .globl ppc_clone
+ppc_clone:
+ SAVE_NVGPRS(r1)
+ lwz r0,TRAP(r1)
+ rlwinm r0,r0,0,0,30 /* clear LSB to indicate full */
+ stw r0,TRAP(r1) /* register set saved */
+ b sys_clone
+
+ .globl ppc_swapcontext
+ppc_swapcontext:
+ SAVE_NVGPRS(r1)
+ lwz r0,TRAP(r1)
+ rlwinm r0,r0,0,0,30 /* clear LSB to indicate full */
+ stw r0,TRAP(r1) /* register set saved */
+ b sys_swapcontext
+
+/*
+ * Top-level page fault handling.
+ * This is in assembler because if do_page_fault tells us that
+ * it is a bad kernel page fault, we want to save the non-volatile
+ * registers before calling bad_page_fault.
+ */
+ .globl handle_page_fault
+handle_page_fault:
+ stw r4,_DAR(r1)
+ addi r3,r1,STACK_FRAME_OVERHEAD
+ bl do_page_fault
+ cmpwi r3,0
+ beq+ ret_from_except
+ SAVE_NVGPRS(r1)
+ lwz r0,TRAP(r1)
+ clrrwi r0,r0,1
+ stw r0,TRAP(r1)
+ mr r5,r3
+ addi r3,r1,STACK_FRAME_OVERHEAD
+ lwz r4,_DAR(r1)
+ bl bad_page_fault
+ b ret_from_except_full
+
+/*
+ * This routine switches between two different tasks. The process
+ * state of one is saved on its kernel stack. Then the state
+ * of the other is restored from its kernel stack. The memory
+ * management hardware is updated to the second process's state.
+ * Finally, we can return to the second process.
+ * On entry, r3 points to the THREAD for the current task, r4
+ * points to the THREAD for the new task.
+ *
+ * This routine is always called with interrupts disabled.
+ *
+ * Note: there are two ways to get to the "going out" portion
+ * of this code; either by coming in via the entry (_switch)
+ * or via "fork" which must set up an environment equivalent
+ * to the "_switch" path. If you change this , you'll have to
+ * change the fork code also.
+ *
+ * The code which creates the new task context is in 'copy_thread'
+ * in arch/ppc/kernel/process.c
+ */
+_GLOBAL(_switch)
+ stwu r1,-INT_FRAME_SIZE(r1)
+ mflr r0
+ stw r0,INT_FRAME_SIZE+4(r1)
+ /* r3-r12 are caller saved -- Cort */
+ SAVE_NVGPRS(r1)
+ stw r0,_NIP(r1) /* Return to switch caller */
+ mfmsr r11
+ li r0,MSR_FP /* Disable floating-point */
+#ifdef CONFIG_ALTIVEC
+BEGIN_FTR_SECTION
+ oris r0,r0,MSR_VEC@h /* Disable altivec */
+ mfspr r12,SPRN_VRSAVE /* save vrsave register value */
+ stw r12,THREAD+THREAD_VRSAVE(r2)
+END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
+#endif /* CONFIG_ALTIVEC */
+#ifdef CONFIG_SPE
+ oris r0,r0,MSR_SPE@h /* Disable SPE */
+ mfspr r12,SPRN_SPEFSCR /* save spefscr register value */
+ stw r12,THREAD+THREAD_SPEFSCR(r2)
+#endif /* CONFIG_SPE */
+ and. r0,r0,r11 /* FP or altivec or SPE enabled? */
+ beq+ 1f
+ andc r11,r11,r0
+ MTMSRD(r11)
+ isync
+1: stw r11,_MSR(r1)
+ mfcr r10
+ stw r10,_CCR(r1)
+ stw r1,KSP(r3) /* Set old stack pointer */
+
+#ifdef CONFIG_SMP
+ /* We need a sync somewhere here to make sure that if the
+ * previous task gets rescheduled on another CPU, it sees all
+ * stores it has performed on this one.
+ */
+ sync
+#endif /* CONFIG_SMP */
+
+ tophys(r0,r4)
+ CLR_TOP32(r0)
+ mtspr SPRN_SPRG3,r0 /* Update current THREAD phys addr */
+ lwz r1,KSP(r4) /* Load new stack pointer */
+
+ /* save the old current 'last' for return value */
+ mr r3,r2
+ addi r2,r4,-THREAD /* Update current */
+
+#ifdef CONFIG_ALTIVEC
+BEGIN_FTR_SECTION
+ lwz r0,THREAD+THREAD_VRSAVE(r2)
+ mtspr SPRN_VRSAVE,r0 /* if G4, restore VRSAVE reg */
+END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
+#endif /* CONFIG_ALTIVEC */
+#ifdef CONFIG_SPE
+ lwz r0,THREAD+THREAD_SPEFSCR(r2)
+ mtspr SPRN_SPEFSCR,r0 /* restore SPEFSCR reg */
+#endif /* CONFIG_SPE */
+
+ lwz r0,_CCR(r1)
+ mtcrf 0xFF,r0
+ /* r3-r12 are destroyed -- Cort */
+ REST_NVGPRS(r1)
+
+ lwz r4,_NIP(r1) /* Return to _switch caller in new task */
+ mtlr r4
+ addi r1,r1,INT_FRAME_SIZE
+ blr
+
+ .globl sigreturn_exit
+sigreturn_exit:
+ subi r1,r3,STACK_FRAME_OVERHEAD
+ rlwinm r12,r1,0,0,18 /* current_thread_info() */
+ lwz r9,TI_FLAGS(r12)
+ andi. r0,r9,_TIF_SYSCALL_TRACE
+ bnel- do_syscall_trace
+ /* fall through */
+
+ .globl ret_from_except_full
+ret_from_except_full:
+ REST_NVGPRS(r1)
+ /* fall through */
+
+ .globl ret_from_except
+ret_from_except:
+ /* Hard-disable interrupts so that current_thread_info()->flags
+ * can't change between when we test it and when we return
+ * from the interrupt. */
+ LOAD_MSR_KERNEL(r10,MSR_KERNEL)
+ SYNC /* Some chip revs have problems here... */
+ MTMSRD(r10) /* disable interrupts */
+
+ lwz r3,_MSR(r1) /* Returning to user mode? */
+ andi. r0,r3,MSR_PR
+ beq resume_kernel
+
+user_exc_return: /* r10 contains MSR_KERNEL here */
+ /* Check current_thread_info()->flags */
+ rlwinm r9,r1,0,0,18
+ lwz r9,TI_FLAGS(r9)
+ andi. r0,r9,(_TIF_SIGPENDING|_TIF_NEED_RESCHED)
+ bne do_work
+
+restore_user:
+#if defined(CONFIG_4xx) || defined(CONFIG_BOOKE)
+ /* Check whether this process has its own DBCR0 value. The single
+ step bit tells us that dbcr0 should be loaded. */
+ lwz r0,THREAD+THREAD_DBCR0(r2)
+ andis. r10,r0,DBCR0_IC@h
+ bnel- load_dbcr0
+#endif
+
+#ifdef CONFIG_PREEMPT
+ b restore
+
+/* N.B. the only way to get here is from the beq following ret_from_except. */
+resume_kernel:
+ /* check current_thread_info->preempt_count */
+ rlwinm r9,r1,0,0,18
+ lwz r0,TI_PREEMPT(r9)
+ cmpwi 0,r0,0 /* if non-zero, just restore regs and return */
+ bne restore
+ lwz r0,TI_FLAGS(r9)
+ andi. r0,r0,_TIF_NEED_RESCHED
+ beq+ restore
+ andi. r0,r3,MSR_EE /* interrupts off? */
+ beq restore /* don't schedule if so */
+1: bl preempt_schedule_irq
+ rlwinm r9,r1,0,0,18
+ lwz r3,TI_FLAGS(r9)
+ andi. r0,r3,_TIF_NEED_RESCHED
+ bne- 1b
+#else
+resume_kernel:
+#endif /* CONFIG_PREEMPT */
+
+ /* interrupts are hard-disabled at this point */
+restore:
+ lwz r0,GPR0(r1)
+ lwz r2,GPR2(r1)
+ REST_4GPRS(3, r1)
+ REST_2GPRS(7, r1)
+
+ lwz r10,_XER(r1)
+ lwz r11,_CTR(r1)
+ mtspr SPRN_XER,r10
+ mtctr r11
+
+ PPC405_ERR77(0,r1)
+ stwcx. r0,0,r1 /* to clear the reservation */
+
+#if !(defined(CONFIG_4xx) || defined(CONFIG_BOOKE))
+ lwz r9,_MSR(r1)
+ andi. r10,r9,MSR_RI /* check if this exception occurred */
+ beql nonrecoverable /* at a bad place (MSR:RI = 0) */
+
+ lwz r10,_CCR(r1)
+ lwz r11,_LINK(r1)
+ mtcrf 0xFF,r10
+ mtlr r11
+
+ /*
+ * Once we put values in SRR0 and SRR1, we are in a state
+ * where exceptions are not recoverable, since taking an
+ * exception will trash SRR0 and SRR1. Therefore we clear the
+ * MSR:RI bit to indicate this. If we do take an exception,
+ * we can't return to the point of the exception but we
+ * can restart the exception exit path at the label
+ * exc_exit_restart below. -- paulus
+ */
+ LOAD_MSR_KERNEL(r10,MSR_KERNEL & ~MSR_RI)
+ SYNC
+ MTMSRD(r10) /* clear the RI bit */
+ .globl exc_exit_restart
+exc_exit_restart:
+ lwz r9,_MSR(r1)
+ lwz r12,_NIP(r1)
+ FIX_SRR1(r9,r10)
+ mtspr SPRN_SRR0,r12
+ mtspr SPRN_SRR1,r9
+ REST_4GPRS(9, r1)
+ lwz r1,GPR1(r1)
+ .globl exc_exit_restart_end
+exc_exit_restart_end:
+ SYNC
+ RFI
+
+#else /* !(CONFIG_4xx || CONFIG_BOOKE) */
+ /*
+ * This is a bit different on 4xx/Book-E because it doesn't have
+ * the RI bit in the MSR.
+ * The TLB miss handler checks if we have interrupted
+ * the exception exit path and restarts it if so
+ * (well maybe one day it will... :).
+ */
+ lwz r11,_LINK(r1)
+ mtlr r11
+ lwz r10,_CCR(r1)
+ mtcrf 0xff,r10
+ REST_2GPRS(9, r1)
+ .globl exc_exit_restart
+exc_exit_restart:
+ lwz r11,_NIP(r1)
+ lwz r12,_MSR(r1)
+exc_exit_start:
+ mtspr SPRN_SRR0,r11
+ mtspr SPRN_SRR1,r12
+ REST_2GPRS(11, r1)
+ lwz r1,GPR1(r1)
+ .globl exc_exit_restart_end
+exc_exit_restart_end:
+ PPC405_ERR77_SYNC
+ rfi
+ b . /* prevent prefetch past rfi */
+
+/*
+ * Returning from a critical interrupt in user mode doesn't need
+ * to be any different from a normal exception. For a critical
+ * interrupt in the kernel, we just return (without checking for
+ * preemption) since the interrupt may have happened at some crucial
+ * place (e.g. inside the TLB miss handler), and because we will be
+ * running with r1 pointing into critical_stack, not the current
+ * process's kernel stack (and therefore current_thread_info() will
+ * give the wrong answer).
+ * We have to restore various SPRs that may have been in use at the
+ * time of the critical interrupt.
+ *
+ */
+ .globl ret_from_crit_exc
+ret_from_crit_exc:
+ REST_NVGPRS(r1)
+ lwz r3,_MSR(r1)
+ andi. r3,r3,MSR_PR
+ LOAD_MSR_KERNEL(r10,MSR_KERNEL)
+ bne user_exc_return
+
+ lwz r0,GPR0(r1)
+ lwz r2,GPR2(r1)
+ REST_4GPRS(3, r1)
+ REST_2GPRS(7, r1)
+
+ lwz r10,_XER(r1)
+ lwz r11,_CTR(r1)
+ mtspr SPRN_XER,r10
+ mtctr r11
+
+ PPC405_ERR77(0,r1)
+ stwcx. r0,0,r1 /* to clear the reservation */
+
+ lwz r11,_LINK(r1)
+ mtlr r11
+ lwz r10,_CCR(r1)
+ mtcrf 0xff,r10
+#ifdef CONFIG_40x
+ /* avoid any possible TLB misses here by turning off MSR.DR, we
+ * assume the instructions here are mapped by a pinned TLB entry */
+ li r10,MSR_IR
+ mtmsr r10
+ isync
+ tophys(r1, r1)
+#endif
+ lwz r9,_DEAR(r1)
+ lwz r10,_ESR(r1)
+ mtspr SPRN_DEAR,r9
+ mtspr SPRN_ESR,r10
+ lwz r11,_NIP(r1)
+ lwz r12,_MSR(r1)
+ mtspr SPRN_CSRR0,r11
+ mtspr SPRN_CSRR1,r12
+ lwz r9,GPR9(r1)
+ lwz r12,GPR12(r1)
+ lwz r10,GPR10(r1)
+ lwz r11,GPR11(r1)
+ lwz r1,GPR1(r1)
+ PPC405_ERR77_SYNC
+ rfci
+ b . /* prevent prefetch past rfci */
+
+#ifdef CONFIG_BOOKE
+/*
+ * Return from a machine check interrupt, similar to a critical
+ * interrupt.
+ */
+ .globl ret_from_mcheck_exc
+ret_from_mcheck_exc:
+ REST_NVGPRS(r1)
+ lwz r3,_MSR(r1)
+ andi. r3,r3,MSR_PR
+ LOAD_MSR_KERNEL(r10,MSR_KERNEL)
+ bne user_exc_return
+
+ lwz r0,GPR0(r1)
+ lwz r2,GPR2(r1)
+ REST_4GPRS(3, r1)
+ REST_2GPRS(7, r1)
+
+ lwz r10,_XER(r1)
+ lwz r11,_CTR(r1)
+ mtspr SPRN_XER,r10
+ mtctr r11
+
+ stwcx. r0,0,r1 /* to clear the reservation */
+
+ lwz r11,_LINK(r1)
+ mtlr r11
+ lwz r10,_CCR(r1)
+ mtcrf 0xff,r10
+ lwz r9,_DEAR(r1)
+ lwz r10,_ESR(r1)
+ mtspr SPRN_DEAR,r9
+ mtspr SPRN_ESR,r10
+ lwz r11,_NIP(r1)
+ lwz r12,_MSR(r1)
+ mtspr SPRN_MCSRR0,r11
+ mtspr SPRN_MCSRR1,r12
+ lwz r9,GPR9(r1)
+ lwz r12,GPR12(r1)
+ lwz r10,GPR10(r1)
+ lwz r11,GPR11(r1)
+ lwz r1,GPR1(r1)
+ RFMCI
+#endif /* CONFIG_BOOKE */
+
+/*
+ * Load the DBCR0 value for a task that is being ptraced,
+ * having first saved away the global DBCR0. Note that r0
+ * has the dbcr0 value to set upon entry to this.
+ */
+load_dbcr0:
+ mfmsr r10 /* first disable debug exceptions */
+ rlwinm r10,r10,0,~MSR_DE
+ mtmsr r10
+ isync
+ mfspr r10,SPRN_DBCR0
+ lis r11,global_dbcr0@ha
+ addi r11,r11,global_dbcr0@l
+ stw r10,0(r11)
+ mtspr SPRN_DBCR0,r0
+ lwz r10,4(r11)
+ addi r10,r10,1
+ stw r10,4(r11)
+ li r11,-1
+ mtspr SPRN_DBSR,r11 /* clear all pending debug events */
+ blr
+
+ .comm global_dbcr0,8
+#endif /* !(CONFIG_4xx || CONFIG_BOOKE) */
+
+do_work: /* r10 contains MSR_KERNEL here */
+ andi. r0,r9,_TIF_NEED_RESCHED
+ beq do_user_signal
+
+do_resched: /* r10 contains MSR_KERNEL here */
+ ori r10,r10,MSR_EE
+ SYNC
+ MTMSRD(r10) /* hard-enable interrupts */
+ bl schedule
+recheck:
+ LOAD_MSR_KERNEL(r10,MSR_KERNEL)
+ SYNC
+ MTMSRD(r10) /* disable interrupts */
+ rlwinm r9,r1,0,0,18
+ lwz r9,TI_FLAGS(r9)
+ andi. r0,r9,_TIF_NEED_RESCHED
+ bne- do_resched
+ andi. r0,r9,_TIF_SIGPENDING
+ beq restore_user
+do_user_signal: /* r10 contains MSR_KERNEL here */
+ ori r10,r10,MSR_EE
+ SYNC
+ MTMSRD(r10) /* hard-enable interrupts */
+ /* save r13-r31 in the exception frame, if not already done */
+ lwz r3,TRAP(r1)
+ andi. r0,r3,1
+ beq 2f
+ SAVE_NVGPRS(r1)
+ rlwinm r3,r3,0,0,30
+ stw r3,TRAP(r1)
+2: li r3,0
+ addi r4,r1,STACK_FRAME_OVERHEAD
+ bl do_signal
+ REST_NVGPRS(r1)
+ b recheck
+
+/*
+ * We come here when we are at the end of handling an exception
+ * that occurred at a place where taking an exception will lose
+ * state information, such as the contents of SRR0 and SRR1.
+ */
+nonrecoverable:
+ lis r10,exc_exit_restart_end@ha
+ addi r10,r10,exc_exit_restart_end@l
+ cmplw r12,r10
+ bge 3f
+ lis r11,exc_exit_restart@ha
+ addi r11,r11,exc_exit_restart@l
+ cmplw r12,r11
+ blt 3f
+ lis r10,ee_restarts@ha
+ lwz r12,ee_restarts@l(r10)
+ addi r12,r12,1
+ stw r12,ee_restarts@l(r10)
+ mr r12,r11 /* restart at exc_exit_restart */
+ blr
+3: /* OK, we can't recover, kill this process */
+ /* but the 601 doesn't implement the RI bit, so assume it's OK */
+BEGIN_FTR_SECTION
+ blr
+END_FTR_SECTION_IFSET(CPU_FTR_601)
+ lwz r3,TRAP(r1)
+ andi. r0,r3,1
+ beq 4f
+ SAVE_NVGPRS(r1)
+ rlwinm r3,r3,0,0,30
+ stw r3,TRAP(r1)
+4: addi r3,r1,STACK_FRAME_OVERHEAD
+ bl nonrecoverable_exception
+ /* shouldn't return */
+ b 4b
+
+ .comm ee_restarts,4
+
+/*
+ * PROM code for specific machines follows. Put it
+ * here so it's easy to add arch-specific sections later.
+ * -- Cort
+ */
+#ifdef CONFIG_PPC_OF
+/*
+ * On CHRP, the Run-Time Abstraction Services (RTAS) have to be
+ * called with the MMU off.
+ */
+_GLOBAL(enter_rtas)
+ stwu r1,-INT_FRAME_SIZE(r1)
+ mflr r0
+ stw r0,INT_FRAME_SIZE+4(r1)
+ lis r4,rtas_data@ha
+ lwz r4,rtas_data@l(r4)
+ lis r6,1f@ha /* physical return address for rtas */
+ addi r6,r6,1f@l
+ tophys(r6,r6)
+ tophys(r7,r1)
+ lis r8,rtas_entry@ha
+ lwz r8,rtas_entry@l(r8)
+ mfmsr r9
+ stw r9,8(r1)
+ LOAD_MSR_KERNEL(r0,MSR_KERNEL)
+ SYNC /* disable interrupts so SRR0/1 */
+ MTMSRD(r0) /* don't get trashed */
+ li r9,MSR_KERNEL & ~(MSR_IR|MSR_DR)
+ mtlr r6
+ CLR_TOP32(r7)
+ mtspr SPRN_SPRG2,r7
+ mtspr SPRN_SRR0,r8
+ mtspr SPRN_SRR1,r9
+ RFI
+1: tophys(r9,r1)
+ lwz r8,INT_FRAME_SIZE+4(r9) /* get return address */
+ lwz r9,8(r9) /* original msr value */
+ FIX_SRR1(r9,r0)
+ addi r1,r1,INT_FRAME_SIZE
+ li r0,0
+ mtspr SPRN_SPRG2,r0
+ mtspr SPRN_SRR0,r8
+ mtspr SPRN_SRR1,r9
+ RFI /* return to caller */
+
+ .globl machine_check_in_rtas
+machine_check_in_rtas:
+ twi 31,0,0
+ /* XXX load up BATs and panic */
+
+#endif /* CONFIG_PPC_OF */
diff --git a/arch/ppc/kernel/find_name.c b/arch/ppc/kernel/find_name.c
new file mode 100644
index 0000000..3c0fa8e
--- /dev/null
+++ b/arch/ppc/kernel/find_name.c
@@ -0,0 +1,48 @@
+#include <stdio.h>
+#include <asm/page.h>
+#include <sys/mman.h>
+#include <strings.h>
+/*
+ * Finds a given address in the System.map and prints it out
+ * with its neighbors. -- Cort
+ */
+
+int main(int argc, char **argv)
+{
+ unsigned long addr, cmp, i;
+ FILE *f;
+ char s[256], last[256];
+
+ if ( argc < 2 )
+ {
+ fprintf(stderr, "Usage: %s <address>\n", argv[0]);
+ return -1;
+ }
+
+ for ( i = 1 ; argv[i] ; i++ )
+ {
+ sscanf( argv[i], "%0lx", &addr );
+ /* adjust if addr is relative to kernelbase */
+ if ( addr < PAGE_OFFSET )
+ addr += PAGE_OFFSET;
+
+ if ( (f = fopen( "System.map", "r" )) == NULL )
+ {
+ perror("fopen()\n");
+ exit(-1);
+ }
+
+ while ( !feof(f) )
+ {
+ fgets(s, 255 , f);
+ sscanf( s, "%0lx", &cmp );
+ if ( addr < cmp )
+ break;
+ strcpy( last, s);
+ }
+
+ printf( "%s%s", last, s );
+ }
+ fclose(f);
+ return 0;
+}
diff --git a/arch/ppc/kernel/head.S b/arch/ppc/kernel/head.S
new file mode 100644
index 0000000..1a89a71
--- /dev/null
+++ b/arch/ppc/kernel/head.S
@@ -0,0 +1,1710 @@
+/*
+ * PowerPC version
+ * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
+ *
+ * Rewritten by Cort Dougan (cort@cs.nmt.edu) for PReP
+ * Copyright (C) 1996 Cort Dougan <cort@cs.nmt.edu>
+ * Adapted for Power Macintosh by Paul Mackerras.
+ * Low-level exception handlers and MMU support
+ * rewritten by Paul Mackerras.
+ * Copyright (C) 1996 Paul Mackerras.
+ * MPC8xx modifications Copyright (C) 1997 Dan Malek (dmalek@jlc.net).
+ * Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk).
+ *
+ * This file contains the low-level support and setup for the
+ * PowerPC platform, including trap and interrupt dispatch.
+ * (The PPC 8xx embedded CPUs use head_8xx.S instead.)
+ *
+ * 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.
+ *
+ */
+
+#include <linux/config.h>
+#include <asm/processor.h>
+#include <asm/page.h>
+#include <asm/mmu.h>
+#include <asm/pgtable.h>
+#include <asm/cputable.h>
+#include <asm/cache.h>
+#include <asm/thread_info.h>
+#include <asm/ppc_asm.h>
+#include <asm/offsets.h>
+
+#ifdef CONFIG_APUS
+#include <asm/amigappc.h>
+#endif
+
+#ifdef CONFIG_PPC64BRIDGE
+#define LOAD_BAT(n, reg, RA, RB) \
+ ld RA,(n*32)+0(reg); \
+ ld RB,(n*32)+8(reg); \
+ mtspr SPRN_IBAT##n##U,RA; \
+ mtspr SPRN_IBAT##n##L,RB; \
+ ld RA,(n*32)+16(reg); \
+ ld RB,(n*32)+24(reg); \
+ mtspr SPRN_DBAT##n##U,RA; \
+ mtspr SPRN_DBAT##n##L,RB; \
+
+#else /* CONFIG_PPC64BRIDGE */
+
+/* 601 only have IBAT; cr0.eq is set on 601 when using this macro */
+#define LOAD_BAT(n, reg, RA, RB) \
+ /* see the comment for clear_bats() -- Cort */ \
+ li RA,0; \
+ mtspr SPRN_IBAT##n##U,RA; \
+ mtspr SPRN_DBAT##n##U,RA; \
+ lwz RA,(n*16)+0(reg); \
+ lwz RB,(n*16)+4(reg); \
+ mtspr SPRN_IBAT##n##U,RA; \
+ mtspr SPRN_IBAT##n##L,RB; \
+ beq 1f; \
+ lwz RA,(n*16)+8(reg); \
+ lwz RB,(n*16)+12(reg); \
+ mtspr SPRN_DBAT##n##U,RA; \
+ mtspr SPRN_DBAT##n##L,RB; \
+1:
+#endif /* CONFIG_PPC64BRIDGE */
+
+ .text
+ .stabs "arch/ppc/kernel/",N_SO,0,0,0f
+ .stabs "head.S",N_SO,0,0,0f
+0:
+ .globl _stext
+_stext:
+
+/*
+ * _start is defined this way because the XCOFF loader in the OpenFirmware
+ * on the powermac expects the entry point to be a procedure descriptor.
+ */
+ .text
+ .globl _start
+_start:
+ /*
+ * These are here for legacy reasons, the kernel used to
+ * need to look like a coff function entry for the pmac
+ * but we're always started by some kind of bootloader now.
+ * -- Cort
+ */
+ nop /* used by __secondary_hold on prep (mtx) and chrp smp */
+ nop /* used by __secondary_hold on prep (mtx) and chrp smp */
+ nop
+
+/* PMAC
+ * Enter here with the kernel text, data and bss loaded starting at
+ * 0, running with virtual == physical mapping.
+ * r5 points to the prom entry point (the client interface handler
+ * address). Address translation is turned on, with the prom
+ * managing the hash table. Interrupts are disabled. The stack
+ * pointer (r1) points to just below the end of the half-meg region
+ * from 0x380000 - 0x400000, which is mapped in already.
+ *
+ * If we are booted from MacOS via BootX, we enter with the kernel
+ * image loaded somewhere, and the following values in registers:
+ * r3: 'BooX' (0x426f6f58)
+ * r4: virtual address of boot_infos_t
+ * r5: 0
+ *
+ * APUS
+ * r3: 'APUS'
+ * r4: physical address of memory base
+ * Linux/m68k style BootInfo structure at &_end.
+ *
+ * PREP
+ * This is jumped to on prep systems right after the kernel is relocated
+ * to its proper place in memory by the boot loader. The expected layout
+ * of the regs is:
+ * r3: ptr to residual data
+ * r4: initrd_start or if no initrd then 0
+ * r5: initrd_end - unused if r4 is 0
+ * r6: Start of command line string
+ * r7: End of command line string
+ *
+ * This just gets a minimal mmu environment setup so we can call
+ * start_here() to do the real work.
+ * -- Cort
+ */
+
+ .globl __start
+__start:
+/*
+ * We have to do any OF calls before we map ourselves to KERNELBASE,
+ * because OF may have I/O devices mapped into that area
+ * (particularly on CHRP).
+ */
+ mr r31,r3 /* save parameters */
+ mr r30,r4
+ mr r29,r5
+ mr r28,r6
+ mr r27,r7
+ li r24,0 /* cpu # */
+
+/*
+ * early_init() does the early machine identification and does
+ * the necessary low-level setup and clears the BSS
+ * -- Cort <cort@fsmlabs.com>
+ */
+ bl early_init
+
+/*
+ * On POWER4, we first need to tweak some CPU configuration registers
+ * like real mode cache inhibit or exception base
+ */
+#ifdef CONFIG_POWER4
+ bl __970_cpu_preinit
+#endif /* CONFIG_POWER4 */
+
+#ifdef CONFIG_APUS
+/* On APUS the __va/__pa constants need to be set to the correct
+ * values before continuing.
+ */
+ mr r4,r30
+ bl fix_mem_constants
+#endif /* CONFIG_APUS */
+
+/* Switch MMU off, clear BATs and flush TLB. At this point, r3 contains
+ * the physical address we are running at, returned by early_init()
+ */
+ bl mmu_off
+__after_mmu_off:
+#ifndef CONFIG_POWER4
+ bl clear_bats
+ bl flush_tlbs
+
+ bl initial_bats
+#if !defined(CONFIG_APUS) && defined(CONFIG_BOOTX_TEXT)
+ bl setup_disp_bat
+#endif
+#else /* CONFIG_POWER4 */
+ bl reloc_offset
+ bl initial_mm_power4
+#endif /* CONFIG_POWER4 */
+
+/*
+ * Call setup_cpu for CPU 0 and initialize 6xx Idle
+ */
+ bl reloc_offset
+ li r24,0 /* cpu# */
+ bl call_setup_cpu /* Call setup_cpu for this CPU */
+#ifdef CONFIG_6xx
+ bl reloc_offset
+ bl init_idle_6xx
+#endif /* CONFIG_6xx */
+#ifdef CONFIG_POWER4
+ bl reloc_offset
+ bl init_idle_power4
+#endif /* CONFIG_POWER4 */
+
+
+#ifndef CONFIG_APUS
+/*
+ * We need to run with _start at physical address 0.
+ * On CHRP, we are loaded at 0x10000 since OF on CHRP uses
+ * the exception vectors at 0 (and therefore this copy
+ * overwrites OF's exception vectors with our own).
+ * If the MMU is already turned on, we copy stuff to KERNELBASE,
+ * otherwise we copy it to 0.
+ */
+ bl reloc_offset
+ mr r26,r3
+ addis r4,r3,KERNELBASE@h /* current address of _start */
+ cmpwi 0,r4,0 /* are we already running at 0? */
+ bne relocate_kernel
+#endif /* CONFIG_APUS */
+/*
+ * we now have the 1st 16M of ram mapped with the bats.
+ * prep needs the mmu to be turned on here, but pmac already has it on.
+ * this shouldn't bother the pmac since it just gets turned on again
+ * as we jump to our code at KERNELBASE. -- Cort
+ * Actually no, pmac doesn't have it on any more. BootX enters with MMU
+ * off, and in other cases, we now turn it off before changing BATs above.
+ */
+turn_on_mmu:
+ mfmsr r0
+ ori r0,r0,MSR_DR|MSR_IR
+ mtspr SPRN_SRR1,r0
+ lis r0,start_here@h
+ ori r0,r0,start_here@l
+ mtspr SPRN_SRR0,r0
+ SYNC
+ RFI /* enables MMU */
+
+/*
+ * We need __secondary_hold as a place to hold the other cpus on
+ * an SMP machine, even when we are running a UP kernel.
+ */
+ . = 0xc0 /* for prep bootloader */
+ li r3,1 /* MTX only has 1 cpu */
+ .globl __secondary_hold
+__secondary_hold:
+ /* tell the master we're here */
+ stw r3,4(0)
+#ifdef CONFIG_SMP
+100: lwz r4,0(0)
+ /* wait until we're told to start */
+ cmpw 0,r4,r3
+ bne 100b
+ /* our cpu # was at addr 0 - go */
+ mr r24,r3 /* cpu # */
+ b __secondary_start
+#else
+ b .
+#endif /* CONFIG_SMP */
+
+/*
+ * Exception entry code. This code runs with address translation
+ * turned off, i.e. using physical addresses.
+ * We assume sprg3 has the physical address of the current
+ * task's thread_struct.
+ */
+#define EXCEPTION_PROLOG \
+ mtspr SPRN_SPRG0,r10; \
+ mtspr SPRN_SPRG1,r11; \
+ mfcr r10; \
+ EXCEPTION_PROLOG_1; \
+ EXCEPTION_PROLOG_2
+
+#define EXCEPTION_PROLOG_1 \
+ mfspr r11,SPRN_SRR1; /* check whether user or kernel */ \
+ andi. r11,r11,MSR_PR; \
+ tophys(r11,r1); /* use tophys(r1) if kernel */ \
+ beq 1f; \
+ mfspr r11,SPRN_SPRG3; \
+ lwz r11,THREAD_INFO-THREAD(r11); \
+ addi r11,r11,THREAD_SIZE; \
+ tophys(r11,r11); \
+1: subi r11,r11,INT_FRAME_SIZE /* alloc exc. frame */
+
+
+#define EXCEPTION_PROLOG_2 \
+ CLR_TOP32(r11); \
+ stw r10,_CCR(r11); /* save registers */ \
+ stw r12,GPR12(r11); \
+ stw r9,GPR9(r11); \
+ mfspr r10,SPRN_SPRG0; \
+ stw r10,GPR10(r11); \
+ mfspr r12,SPRN_SPRG1; \
+ stw r12,GPR11(r11); \
+ mflr r10; \
+ stw r10,_LINK(r11); \
+ mfspr r12,SPRN_SRR0; \
+ mfspr r9,SPRN_SRR1; \
+ stw r1,GPR1(r11); \
+ stw r1,0(r11); \
+ tovirt(r1,r11); /* set new kernel sp */ \
+ li r10,MSR_KERNEL & ~(MSR_IR|MSR_DR); /* can take exceptions */ \
+ MTMSRD(r10); /* (except for mach check in rtas) */ \
+ stw r0,GPR0(r11); \
+ SAVE_4GPRS(3, r11); \
+ SAVE_2GPRS(7, r11)
+
+/*
+ * Note: code which follows this uses cr0.eq (set if from kernel),
+ * r11, r12 (SRR0), and r9 (SRR1).
+ *
+ * Note2: once we have set r1 we are in a position to take exceptions
+ * again, and we could thus set MSR:RI at that point.
+ */
+
+/*
+ * Exception vectors.
+ */
+#define EXCEPTION(n, label, hdlr, xfer) \
+ . = n; \
+label: \
+ EXCEPTION_PROLOG; \
+ addi r3,r1,STACK_FRAME_OVERHEAD; \
+ xfer(n, hdlr)
+
+#define EXC_XFER_TEMPLATE(n, hdlr, trap, copyee, tfer, ret) \
+ li r10,trap; \
+ stw r10,TRAP(r11); \
+ li r10,MSR_KERNEL; \
+ copyee(r10, r9); \
+ bl tfer; \
+i##n: \
+ .long hdlr; \
+ .long ret
+
+#define COPY_EE(d, s) rlwimi d,s,0,16,16
+#define NOCOPY(d, s)
+
+#define EXC_XFER_STD(n, hdlr) \
+ EXC_XFER_TEMPLATE(n, hdlr, n, NOCOPY, transfer_to_handler_full, \
+ ret_from_except_full)
+
+#define EXC_XFER_LITE(n, hdlr) \
+ EXC_XFER_TEMPLATE(n, hdlr, n+1, NOCOPY, transfer_to_handler, \
+ ret_from_except)
+
+#define EXC_XFER_EE(n, hdlr) \
+ EXC_XFER_TEMPLATE(n, hdlr, n, COPY_EE, transfer_to_handler_full, \
+ ret_from_except_full)
+
+#define EXC_XFER_EE_LITE(n, hdlr) \
+ EXC_XFER_TEMPLATE(n, hdlr, n+1, COPY_EE, transfer_to_handler, \
+ ret_from_except)
+
+/* System reset */
+/* core99 pmac starts the seconary here by changing the vector, and
+ putting it back to what it was (UnknownException) when done. */
+#if defined(CONFIG_GEMINI) && defined(CONFIG_SMP)
+ . = 0x100
+ b __secondary_start_gemini
+#else
+ EXCEPTION(0x100, Reset, UnknownException, EXC_XFER_STD)
+#endif
+
+/* Machine check */
+/*
+ * On CHRP, this is complicated by the fact that we could get a
+ * machine check inside RTAS, and we have no guarantee that certain
+ * critical registers will have the values we expect. The set of
+ * registers that might have bad values includes all the GPRs
+ * and all the BATs. We indicate that we are in RTAS by putting
+ * a non-zero value, the address of the exception frame to use,
+ * in SPRG2. The machine check handler checks SPRG2 and uses its
+ * value if it is non-zero. If we ever needed to free up SPRG2,
+ * we could use a field in the thread_info or thread_struct instead.
+ * (Other exception handlers assume that r1 is a valid kernel stack
+ * pointer when we take an exception from supervisor mode.)
+ * -- paulus.
+ */
+ . = 0x200
+ mtspr SPRN_SPRG0,r10
+ mtspr SPRN_SPRG1,r11
+ mfcr r10
+#ifdef CONFIG_PPC_CHRP
+ mfspr r11,SPRN_SPRG2
+ cmpwi 0,r11,0
+ bne 7f
+#endif /* CONFIG_PPC_CHRP */
+ EXCEPTION_PROLOG_1
+7: EXCEPTION_PROLOG_2
+ addi r3,r1,STACK_FRAME_OVERHEAD
+#ifdef CONFIG_PPC_CHRP
+ mfspr r4,SPRN_SPRG2
+ cmpwi cr1,r4,0
+ bne cr1,1f
+#endif
+ EXC_XFER_STD(0x200, MachineCheckException)
+#ifdef CONFIG_PPC_CHRP
+1: b machine_check_in_rtas
+#endif
+
+/* Data access exception. */
+ . = 0x300
+#ifdef CONFIG_PPC64BRIDGE
+ b DataAccess
+DataAccessCont:
+#else
+DataAccess:
+ EXCEPTION_PROLOG
+#endif /* CONFIG_PPC64BRIDGE */
+ mfspr r10,SPRN_DSISR
+ andis. r0,r10,0xa470 /* weird error? */
+ bne 1f /* if not, try to put a PTE */
+ mfspr r4,SPRN_DAR /* into the hash table */
+ rlwinm r3,r10,32-15,21,21 /* DSISR_STORE -> _PAGE_RW */
+ bl hash_page
+1: stw r10,_DSISR(r11)
+ mr r5,r10
+ mfspr r4,SPRN_DAR
+ EXC_XFER_EE_LITE(0x300, handle_page_fault)
+
+#ifdef CONFIG_PPC64BRIDGE
+/* SLB fault on data access. */
+ . = 0x380
+ b DataSegment
+#endif /* CONFIG_PPC64BRIDGE */
+
+/* Instruction access exception. */
+ . = 0x400
+#ifdef CONFIG_PPC64BRIDGE
+ b InstructionAccess
+InstructionAccessCont:
+#else
+InstructionAccess:
+ EXCEPTION_PROLOG
+#endif /* CONFIG_PPC64BRIDGE */
+ andis. r0,r9,0x4000 /* no pte found? */
+ beq 1f /* if so, try to put a PTE */
+ li r3,0 /* into the hash table */
+ mr r4,r12 /* SRR0 is fault address */
+ bl hash_page
+1: mr r4,r12
+ mr r5,r9
+ EXC_XFER_EE_LITE(0x400, handle_page_fault)
+
+#ifdef CONFIG_PPC64BRIDGE
+/* SLB fault on instruction access. */
+ . = 0x480
+ b InstructionSegment
+#endif /* CONFIG_PPC64BRIDGE */
+
+/* External interrupt */
+ EXCEPTION(0x500, HardwareInterrupt, do_IRQ, EXC_XFER_LITE)
+
+/* Alignment exception */
+ . = 0x600
+Alignment:
+ EXCEPTION_PROLOG
+ mfspr r4,SPRN_DAR
+ stw r4,_DAR(r11)
+ mfspr r5,SPRN_DSISR
+ stw r5,_DSISR(r11)
+ addi r3,r1,STACK_FRAME_OVERHEAD
+ EXC_XFER_EE(0x600, AlignmentException)
+
+/* Program check exception */
+ EXCEPTION(0x700, ProgramCheck, ProgramCheckException, EXC_XFER_STD)
+
+/* Floating-point unavailable */
+ . = 0x800
+FPUnavailable:
+ EXCEPTION_PROLOG
+ bne load_up_fpu /* if from user, just load it up */
+ addi r3,r1,STACK_FRAME_OVERHEAD
+ EXC_XFER_EE_LITE(0x800, KernelFP)
+
+/* Decrementer */
+ EXCEPTION(0x900, Decrementer, timer_interrupt, EXC_XFER_LITE)
+
+ EXCEPTION(0xa00, Trap_0a, UnknownException, EXC_XFER_EE)
+ EXCEPTION(0xb00, Trap_0b, UnknownException, EXC_XFER_EE)
+
+/* System call */
+ . = 0xc00
+SystemCall:
+ EXCEPTION_PROLOG
+ EXC_XFER_EE_LITE(0xc00, DoSyscall)
+
+/* Single step - not used on 601 */
+ EXCEPTION(0xd00, SingleStep, SingleStepException, EXC_XFER_STD)
+ EXCEPTION(0xe00, Trap_0e, UnknownException, EXC_XFER_EE)
+
+/*
+ * The Altivec unavailable trap is at 0x0f20. Foo.
+ * We effectively remap it to 0x3000.
+ * We include an altivec unavailable exception vector even if
+ * not configured for Altivec, so that you can't panic a
+ * non-altivec kernel running on a machine with altivec just
+ * by executing an altivec instruction.
+ */
+ . = 0xf00
+ b Trap_0f
+
+ . = 0xf20
+ b AltiVecUnavailable
+
+Trap_0f:
+ EXCEPTION_PROLOG
+ addi r3,r1,STACK_FRAME_OVERHEAD
+ EXC_XFER_EE(0xf00, UnknownException)
+
+/*
+ * Handle TLB miss for instruction on 603/603e.
+ * Note: we get an alternate set of r0 - r3 to use automatically.
+ */
+ . = 0x1000
+InstructionTLBMiss:
+/*
+ * r0: stored ctr
+ * r1: linux style pte ( later becomes ppc hardware pte )
+ * r2: ptr to linux-style pte
+ * r3: scratch
+ */
+ mfctr r0
+ /* Get PTE (linux-style) and check access */
+ mfspr r3,SPRN_IMISS
+ lis r1,KERNELBASE@h /* check if kernel address */
+ cmplw 0,r3,r1
+ mfspr r2,SPRN_SPRG3
+ li r1,_PAGE_USER|_PAGE_PRESENT /* low addresses tested as user */
+ lwz r2,PGDIR(r2)
+ blt+ 112f
+ lis r2,swapper_pg_dir@ha /* if kernel address, use */
+ addi r2,r2,swapper_pg_dir@l /* kernel page table */
+ mfspr r1,SPRN_SRR1 /* and MSR_PR bit from SRR1 */
+ rlwinm r1,r1,32-12,29,29 /* shift MSR_PR to _PAGE_USER posn */
+112: tophys(r2,r2)
+ rlwimi r2,r3,12,20,29 /* insert top 10 bits of address */
+ lwz r2,0(r2) /* get pmd entry */
+ rlwinm. r2,r2,0,0,19 /* extract address of pte page */
+ beq- InstructionAddressInvalid /* return if no mapping */
+ rlwimi r2,r3,22,20,29 /* insert next 10 bits of address */
+ lwz r3,0(r2) /* get linux-style pte */
+ andc. r1,r1,r3 /* check access & ~permission */
+ bne- InstructionAddressInvalid /* return if access not permitted */
+ ori r3,r3,_PAGE_ACCESSED /* set _PAGE_ACCESSED in pte */
+ /*
+ * NOTE! We are assuming this is not an SMP system, otherwise
+ * we would need to update the pte atomically with lwarx/stwcx.
+ */
+ stw r3,0(r2) /* update PTE (accessed bit) */
+ /* Convert linux-style PTE to low word of PPC-style PTE */
+ rlwinm r1,r3,32-10,31,31 /* _PAGE_RW -> PP lsb */
+ rlwinm r2,r3,32-7,31,31 /* _PAGE_DIRTY -> PP lsb */
+ and r1,r1,r2 /* writable if _RW and _DIRTY */
+ rlwimi r3,r3,32-1,30,30 /* _PAGE_USER -> PP msb */
+ rlwimi r3,r3,32-1,31,31 /* _PAGE_USER -> PP lsb */
+ ori r1,r1,0xe14 /* clear out reserved bits and M */
+ andc r1,r3,r1 /* PP = user? (rw&dirty? 2: 3): 0 */
+ mtspr SPRN_RPA,r1
+ mfspr r3,SPRN_IMISS
+ tlbli r3
+ mfspr r3,SPRN_SRR1 /* Need to restore CR0 */
+ mtcrf 0x80,r3
+ rfi
+InstructionAddressInvalid:
+ mfspr r3,SPRN_SRR1
+ rlwinm r1,r3,9,6,6 /* Get load/store bit */
+
+ addis r1,r1,0x2000
+ mtspr SPRN_DSISR,r1 /* (shouldn't be needed) */
+ mtctr r0 /* Restore CTR */
+ andi. r2,r3,0xFFFF /* Clear upper bits of SRR1 */
+ or r2,r2,r1
+ mtspr SPRN_SRR1,r2
+ mfspr r1,SPRN_IMISS /* Get failing address */
+ rlwinm. r2,r2,0,31,31 /* Check for little endian access */
+ rlwimi r2,r2,1,30,30 /* change 1 -> 3 */
+ xor r1,r1,r2
+ mtspr SPRN_DAR,r1 /* Set fault address */
+ mfmsr r0 /* Restore "normal" registers */
+ xoris r0,r0,MSR_TGPR>>16
+ mtcrf 0x80,r3 /* Restore CR0 */
+ mtmsr r0
+ b InstructionAccess
+
+/*
+ * Handle TLB miss for DATA Load operation on 603/603e
+ */
+ . = 0x1100
+DataLoadTLBMiss:
+/*
+ * r0: stored ctr
+ * r1: linux style pte ( later becomes ppc hardware pte )
+ * r2: ptr to linux-style pte
+ * r3: scratch
+ */
+ mfctr r0
+ /* Get PTE (linux-style) and check access */
+ mfspr r3,SPRN_DMISS
+ lis r1,KERNELBASE@h /* check if kernel address */
+ cmplw 0,r3,r1
+ mfspr r2,SPRN_SPRG3
+ li r1,_PAGE_USER|_PAGE_PRESENT /* low addresses tested as user */
+ lwz r2,PGDIR(r2)
+ blt+ 112f
+ lis r2,swapper_pg_dir@ha /* if kernel address, use */
+ addi r2,r2,swapper_pg_dir@l /* kernel page table */
+ mfspr r1,SPRN_SRR1 /* and MSR_PR bit from SRR1 */
+ rlwinm r1,r1,32-12,29,29 /* shift MSR_PR to _PAGE_USER posn */
+112: tophys(r2,r2)
+ rlwimi r2,r3,12,20,29 /* insert top 10 bits of address */
+ lwz r2,0(r2) /* get pmd entry */
+ rlwinm. r2,r2,0,0,19 /* extract address of pte page */
+ beq- DataAddressInvalid /* return if no mapping */
+ rlwimi r2,r3,22,20,29 /* insert next 10 bits of address */
+ lwz r3,0(r2) /* get linux-style pte */
+ andc. r1,r1,r3 /* check access & ~permission */
+ bne- DataAddressInvalid /* return if access not permitted */
+ ori r3,r3,_PAGE_ACCESSED /* set _PAGE_ACCESSED in pte */
+ /*
+ * NOTE! We are assuming this is not an SMP system, otherwise
+ * we would need to update the pte atomically with lwarx/stwcx.
+ */
+ stw r3,0(r2) /* update PTE (accessed bit) */
+ /* Convert linux-style PTE to low word of PPC-style PTE */
+ rlwinm r1,r3,32-10,31,31 /* _PAGE_RW -> PP lsb */
+ rlwinm r2,r3,32-7,31,31 /* _PAGE_DIRTY -> PP lsb */
+ and r1,r1,r2 /* writable if _RW and _DIRTY */
+ rlwimi r3,r3,32-1,30,30 /* _PAGE_USER -> PP msb */
+ rlwimi r3,r3,32-1,31,31 /* _PAGE_USER -> PP lsb */
+ ori r1,r1,0xe14 /* clear out reserved bits and M */
+ andc r1,r3,r1 /* PP = user? (rw&dirty? 2: 3): 0 */
+ mtspr SPRN_RPA,r1
+ mfspr r3,SPRN_DMISS
+ tlbld r3
+ mfspr r3,SPRN_SRR1 /* Need to restore CR0 */
+ mtcrf 0x80,r3
+ rfi
+DataAddressInvalid:
+ mfspr r3,SPRN_SRR1
+ rlwinm r1,r3,9,6,6 /* Get load/store bit */
+ addis r1,r1,0x2000
+ mtspr SPRN_DSISR,r1
+ mtctr r0 /* Restore CTR */
+ andi. r2,r3,0xFFFF /* Clear upper bits of SRR1 */
+ mtspr SPRN_SRR1,r2
+ mfspr r1,SPRN_DMISS /* Get failing address */
+ rlwinm. r2,r2,0,31,31 /* Check for little endian access */
+ beq 20f /* Jump if big endian */
+ xori r1,r1,3
+20: mtspr SPRN_DAR,r1 /* Set fault address */
+ mfmsr r0 /* Restore "normal" registers */
+ xoris r0,r0,MSR_TGPR>>16
+ mtcrf 0x80,r3 /* Restore CR0 */
+ mtmsr r0
+ b DataAccess
+
+/*
+ * Handle TLB miss for DATA Store on 603/603e
+ */
+ . = 0x1200
+DataStoreTLBMiss:
+/*
+ * r0: stored ctr
+ * r1: linux style pte ( later becomes ppc hardware pte )
+ * r2: ptr to linux-style pte
+ * r3: scratch
+ */
+ mfctr r0
+ /* Get PTE (linux-style) and check access */
+ mfspr r3,SPRN_DMISS
+ lis r1,KERNELBASE@h /* check if kernel address */
+ cmplw 0,r3,r1
+ mfspr r2,SPRN_SPRG3
+ li r1,_PAGE_RW|_PAGE_USER|_PAGE_PRESENT /* access flags */
+ lwz r2,PGDIR(r2)
+ blt+ 112f
+ lis r2,swapper_pg_dir@ha /* if kernel address, use */
+ addi r2,r2,swapper_pg_dir@l /* kernel page table */
+ mfspr r1,SPRN_SRR1 /* and MSR_PR bit from SRR1 */
+ rlwinm r1,r1,32-12,29,29 /* shift MSR_PR to _PAGE_USER posn */
+112: tophys(r2,r2)
+ rlwimi r2,r3,12,20,29 /* insert top 10 bits of address */
+ lwz r2,0(r2) /* get pmd entry */
+ rlwinm. r2,r2,0,0,19 /* extract address of pte page */
+ beq- DataAddressInvalid /* return if no mapping */
+ rlwimi r2,r3,22,20,29 /* insert next 10 bits of address */
+ lwz r3,0(r2) /* get linux-style pte */
+ andc. r1,r1,r3 /* check access & ~permission */
+ bne- DataAddressInvalid /* return if access not permitted */
+ ori r3,r3,_PAGE_ACCESSED|_PAGE_DIRTY
+ /*
+ * NOTE! We are assuming this is not an SMP system, otherwise
+ * we would need to update the pte atomically with lwarx/stwcx.
+ */
+ stw r3,0(r2) /* update PTE (accessed/dirty bits) */
+ /* Convert linux-style PTE to low word of PPC-style PTE */
+ rlwimi r3,r3,32-1,30,30 /* _PAGE_USER -> PP msb */
+ li r1,0xe15 /* clear out reserved bits and M */
+ andc r1,r3,r1 /* PP = user? 2: 0 */
+ mtspr SPRN_RPA,r1
+ mfspr r3,SPRN_DMISS
+ tlbld r3
+ mfspr r3,SPRN_SRR1 /* Need to restore CR0 */
+ mtcrf 0x80,r3
+ rfi
+
+#ifndef CONFIG_ALTIVEC
+#define AltivecAssistException UnknownException
+#endif
+
+ EXCEPTION(0x1300, Trap_13, InstructionBreakpoint, EXC_XFER_EE)
+ EXCEPTION(0x1400, SMI, SMIException, EXC_XFER_EE)
+ EXCEPTION(0x1500, Trap_15, UnknownException, EXC_XFER_EE)
+#ifdef CONFIG_POWER4
+ EXCEPTION(0x1600, Trap_16, UnknownException, EXC_XFER_EE)
+ EXCEPTION(0x1700, Trap_17, AltivecAssistException, EXC_XFER_EE)
+ EXCEPTION(0x1800, Trap_18, TAUException, EXC_XFER_STD)
+#else /* !CONFIG_POWER4 */
+ EXCEPTION(0x1600, Trap_16, AltivecAssistException, EXC_XFER_EE)
+ EXCEPTION(0x1700, Trap_17, TAUException, EXC_XFER_STD)
+ EXCEPTION(0x1800, Trap_18, UnknownException, EXC_XFER_EE)
+#endif /* CONFIG_POWER4 */
+ EXCEPTION(0x1900, Trap_19, UnknownException, EXC_XFER_EE)
+ EXCEPTION(0x1a00, Trap_1a, UnknownException, EXC_XFER_EE)
+ EXCEPTION(0x1b00, Trap_1b, UnknownException, EXC_XFER_EE)
+ EXCEPTION(0x1c00, Trap_1c, UnknownException, EXC_XFER_EE)
+ EXCEPTION(0x1d00, Trap_1d, UnknownException, EXC_XFER_EE)
+ EXCEPTION(0x1e00, Trap_1e, UnknownException, EXC_XFER_EE)
+ EXCEPTION(0x1f00, Trap_1f, UnknownException, EXC_XFER_EE)
+ EXCEPTION(0x2000, RunMode, RunModeException, EXC_XFER_EE)
+ EXCEPTION(0x2100, Trap_21, UnknownException, EXC_XFER_EE)
+ EXCEPTION(0x2200, Trap_22, UnknownException, EXC_XFER_EE)
+ EXCEPTION(0x2300, Trap_23, UnknownException, EXC_XFER_EE)
+ EXCEPTION(0x2400, Trap_24, UnknownException, EXC_XFER_EE)
+ EXCEPTION(0x2500, Trap_25, UnknownException, EXC_XFER_EE)
+ EXCEPTION(0x2600, Trap_26, UnknownException, EXC_XFER_EE)
+ EXCEPTION(0x2700, Trap_27, UnknownException, EXC_XFER_EE)
+ EXCEPTION(0x2800, Trap_28, UnknownException, EXC_XFER_EE)
+ EXCEPTION(0x2900, Trap_29, UnknownException, EXC_XFER_EE)
+ EXCEPTION(0x2a00, Trap_2a, UnknownException, EXC_XFER_EE)
+ EXCEPTION(0x2b00, Trap_2b, UnknownException, EXC_XFER_EE)
+ EXCEPTION(0x2c00, Trap_2c, UnknownException, EXC_XFER_EE)
+ EXCEPTION(0x2d00, Trap_2d, UnknownException, EXC_XFER_EE)
+ EXCEPTION(0x2e00, Trap_2e, UnknownException, EXC_XFER_EE)
+ EXCEPTION(0x2f00, MOLTrampoline, UnknownException, EXC_XFER_EE_LITE)
+
+ .globl mol_trampoline
+ .set mol_trampoline, i0x2f00
+
+ . = 0x3000
+
+AltiVecUnavailable:
+ EXCEPTION_PROLOG
+#ifdef CONFIG_ALTIVEC
+ bne load_up_altivec /* if from user, just load it up */
+#endif /* CONFIG_ALTIVEC */
+ EXC_XFER_EE_LITE(0xf20, AltivecUnavailException)
+
+#ifdef CONFIG_PPC64BRIDGE
+DataAccess:
+ EXCEPTION_PROLOG
+ b DataAccessCont
+
+InstructionAccess:
+ EXCEPTION_PROLOG
+ b InstructionAccessCont
+
+DataSegment:
+ EXCEPTION_PROLOG
+ addi r3,r1,STACK_FRAME_OVERHEAD
+ mfspr r4,SPRN_DAR
+ stw r4,_DAR(r11)
+ EXC_XFER_STD(0x380, UnknownException)
+
+InstructionSegment:
+ EXCEPTION_PROLOG
+ addi r3,r1,STACK_FRAME_OVERHEAD
+ EXC_XFER_STD(0x480, UnknownException)
+#endif /* CONFIG_PPC64BRIDGE */
+
+/*
+ * This task wants to use the FPU now.
+ * On UP, disable FP for the task which had the FPU previously,
+ * and save its floating-point registers in its thread_struct.
+ * Load up this task's FP registers from its thread_struct,
+ * enable the FPU for the current task and return to the task.
+ */
+load_up_fpu:
+ mfmsr r5
+ ori r5,r5,MSR_FP
+#ifdef CONFIG_PPC64BRIDGE
+ clrldi r5,r5,1 /* turn off 64-bit mode */
+#endif /* CONFIG_PPC64BRIDGE */
+ SYNC
+ MTMSRD(r5) /* enable use of fpu now */
+ isync
+/*
+ * For SMP, we don't do lazy FPU switching because it just gets too
+ * horrendously complex, especially when a task switches from one CPU
+ * to another. Instead we call giveup_fpu in switch_to.
+ */
+#ifndef CONFIG_SMP
+ tophys(r6,0) /* get __pa constant */
+ addis r3,r6,last_task_used_math@ha
+ lwz r4,last_task_used_math@l(r3)
+ cmpwi 0,r4,0
+ beq 1f
+ add r4,r4,r6
+ addi r4,r4,THREAD /* want last_task_used_math->thread */
+ SAVE_32FPRS(0, r4)
+ mffs fr0
+ stfd fr0,THREAD_FPSCR-4(r4)
+ lwz r5,PT_REGS(r4)
+ add r5,r5,r6
+ lwz r4,_MSR-STACK_FRAME_OVERHEAD(r5)
+ li r10,MSR_FP|MSR_FE0|MSR_FE1
+ andc r4,r4,r10 /* disable FP for previous task */
+ stw r4,_MSR-STACK_FRAME_OVERHEAD(r5)
+1:
+#endif /* CONFIG_SMP */
+ /* enable use of FP after return */
+ mfspr r5,SPRN_SPRG3 /* current task's THREAD (phys) */
+ lwz r4,THREAD_FPEXC_MODE(r5)
+ ori r9,r9,MSR_FP /* enable FP for current */
+ or r9,r9,r4
+ lfd fr0,THREAD_FPSCR-4(r5)
+ mtfsf 0xff,fr0
+ REST_32FPRS(0, r5)
+#ifndef CONFIG_SMP
+ subi r4,r5,THREAD
+ sub r4,r4,r6
+ stw r4,last_task_used_math@l(r3)
+#endif /* CONFIG_SMP */
+ /* restore registers and return */
+ /* we haven't used ctr or xer or lr */
+ /* fall through to fast_exception_return */
+
+ .globl fast_exception_return
+fast_exception_return:
+ andi. r10,r9,MSR_RI /* check for recoverable interrupt */
+ beq 1f /* if not, we've got problems */
+2: REST_4GPRS(3, r11)
+ lwz r10,_CCR(r11)
+ REST_GPR(1, r11)
+ mtcr r10
+ lwz r10,_LINK(r11)
+ mtlr r10
+ REST_GPR(10, r11)
+ mtspr SPRN_SRR1,r9
+ mtspr SPRN_SRR0,r12
+ REST_GPR(9, r11)
+ REST_GPR(12, r11)
+ lwz r11,GPR11(r11)
+ SYNC
+ RFI
+
+/* check if the exception happened in a restartable section */
+1: lis r3,exc_exit_restart_end@ha
+ addi r3,r3,exc_exit_restart_end@l
+ cmplw r12,r3
+ bge 3f
+ lis r4,exc_exit_restart@ha
+ addi r4,r4,exc_exit_restart@l
+ cmplw r12,r4
+ blt 3f
+ lis r3,fee_restarts@ha
+ tophys(r3,r3)
+ lwz r5,fee_restarts@l(r3)
+ addi r5,r5,1
+ stw r5,fee_restarts@l(r3)
+ mr r12,r4 /* restart at exc_exit_restart */
+ b 2b
+
+ .comm fee_restarts,4
+
+/* aargh, a nonrecoverable interrupt, panic */
+/* aargh, we don't know which trap this is */
+/* but the 601 doesn't implement the RI bit, so assume it's OK */
+3:
+BEGIN_FTR_SECTION
+ b 2b
+END_FTR_SECTION_IFSET(CPU_FTR_601)
+ li r10,-1
+ stw r10,TRAP(r11)
+ addi r3,r1,STACK_FRAME_OVERHEAD
+ li r10,MSR_KERNEL
+ bl transfer_to_handler_full
+ .long nonrecoverable_exception
+ .long ret_from_except
+
+/*
+ * FP unavailable trap from kernel - print a message, but let
+ * the task use FP in the kernel until it returns to user mode.
+ */
+KernelFP:
+ lwz r3,_MSR(r1)
+ ori r3,r3,MSR_FP
+ stw r3,_MSR(r1) /* enable use of FP after return */
+ lis r3,86f@h
+ ori r3,r3,86f@l
+ mr r4,r2 /* current */
+ lwz r5,_NIP(r1)
+ bl printk
+ b ret_from_except
+86: .string "floating point used in kernel (task=%p, pc=%x)\n"
+ .align 4,0
+
+#ifdef CONFIG_ALTIVEC
+/* Note that the AltiVec support is closely modeled after the FP
+ * support. Changes to one are likely to be applicable to the
+ * other! */
+load_up_altivec:
+/*
+ * Disable AltiVec for the task which had AltiVec previously,
+ * and save its AltiVec registers in its thread_struct.
+ * Enables AltiVec for use in the kernel on return.
+ * On SMP we know the AltiVec units are free, since we give it up every
+ * switch. -- Kumar
+ */
+ mfmsr r5
+ oris r5,r5,MSR_VEC@h
+ MTMSRD(r5) /* enable use of AltiVec now */
+ isync
+/*
+ * For SMP, we don't do lazy AltiVec switching because it just gets too
+ * horrendously complex, especially when a task switches from one CPU
+ * to another. Instead we call giveup_altivec in switch_to.
+ */
+#ifndef CONFIG_SMP
+ tophys(r6,0)
+ addis r3,r6,last_task_used_altivec@ha
+ lwz r4,last_task_used_altivec@l(r3)
+ cmpwi 0,r4,0
+ beq 1f
+ add r4,r4,r6
+ addi r4,r4,THREAD /* want THREAD of last_task_used_altivec */
+ SAVE_32VR(0,r10,r4)
+ mfvscr vr0
+ li r10,THREAD_VSCR
+ stvx vr0,r10,r4
+ lwz r5,PT_REGS(r4)
+ add r5,r5,r6
+ lwz r4,_MSR-STACK_FRAME_OVERHEAD(r5)
+ lis r10,MSR_VEC@h
+ andc r4,r4,r10 /* disable altivec for previous task */
+ stw r4,_MSR-STACK_FRAME_OVERHEAD(r5)
+1:
+#endif /* CONFIG_SMP */
+ /* enable use of AltiVec after return */
+ oris r9,r9,MSR_VEC@h
+ mfspr r5,SPRN_SPRG3 /* current task's THREAD (phys) */
+ li r4,1
+ li r10,THREAD_VSCR
+ stw r4,THREAD_USED_VR(r5)
+ lvx vr0,r10,r5
+ mtvscr vr0
+ REST_32VR(0,r10,r5)
+#ifndef CONFIG_SMP
+ subi r4,r5,THREAD
+ sub r4,r4,r6
+ stw r4,last_task_used_altivec@l(r3)
+#endif /* CONFIG_SMP */
+ /* restore registers and return */
+ /* we haven't used ctr or xer or lr */
+ b fast_exception_return
+
+/*
+ * AltiVec unavailable trap from kernel - print a message, but let
+ * the task use AltiVec in the kernel until it returns to user mode.
+ */
+KernelAltiVec:
+ lwz r3,_MSR(r1)
+ oris r3,r3,MSR_VEC@h
+ stw r3,_MSR(r1) /* enable use of AltiVec after return */
+ lis r3,87f@h
+ ori r3,r3,87f@l
+ mr r4,r2 /* current */
+ lwz r5,_NIP(r1)
+ bl printk
+ b ret_from_except
+87: .string "AltiVec used in kernel (task=%p, pc=%x) \n"
+ .align 4,0
+
+/*
+ * giveup_altivec(tsk)
+ * Disable AltiVec for the task given as the argument,
+ * and save the AltiVec registers in its thread_struct.
+ * Enables AltiVec for use in the kernel on return.
+ */
+
+ .globl giveup_altivec
+giveup_altivec:
+ mfmsr r5
+ oris r5,r5,MSR_VEC@h
+ SYNC
+ MTMSRD(r5) /* enable use of AltiVec now */
+ isync
+ cmpwi 0,r3,0
+ beqlr- /* if no previous owner, done */
+ addi r3,r3,THREAD /* want THREAD of task */
+ lwz r5,PT_REGS(r3)
+ cmpwi 0,r5,0
+ SAVE_32VR(0, r4, r3)
+ mfvscr vr0
+ li r4,THREAD_VSCR
+ stvx vr0,r4,r3
+ beq 1f
+ lwz r4,_MSR-STACK_FRAME_OVERHEAD(r5)
+ lis r3,MSR_VEC@h
+ andc r4,r4,r3 /* disable AltiVec for previous task */
+ stw r4,_MSR-STACK_FRAME_OVERHEAD(r5)
+1:
+#ifndef CONFIG_SMP
+ li r5,0
+ lis r4,last_task_used_altivec@ha
+ stw r5,last_task_used_altivec@l(r4)
+#endif /* CONFIG_SMP */
+ blr
+#endif /* CONFIG_ALTIVEC */
+
+/*
+ * giveup_fpu(tsk)
+ * Disable FP for the task given as the argument,
+ * and save the floating-point registers in its thread_struct.
+ * Enables the FPU for use in the kernel on return.
+ */
+ .globl giveup_fpu
+giveup_fpu:
+ mfmsr r5
+ ori r5,r5,MSR_FP
+ SYNC_601
+ ISYNC_601
+ MTMSRD(r5) /* enable use of fpu now */
+ SYNC_601
+ isync
+ cmpwi 0,r3,0
+ beqlr- /* if no previous owner, done */
+ addi r3,r3,THREAD /* want THREAD of task */
+ lwz r5,PT_REGS(r3)
+ cmpwi 0,r5,0
+ SAVE_32FPRS(0, r3)
+ mffs fr0
+ stfd fr0,THREAD_FPSCR-4(r3)
+ beq 1f
+ lwz r4,_MSR-STACK_FRAME_OVERHEAD(r5)
+ li r3,MSR_FP|MSR_FE0|MSR_FE1
+ andc r4,r4,r3 /* disable FP for previous task */
+ stw r4,_MSR-STACK_FRAME_OVERHEAD(r5)
+1:
+#ifndef CONFIG_SMP
+ li r5,0
+ lis r4,last_task_used_math@ha
+ stw r5,last_task_used_math@l(r4)
+#endif /* CONFIG_SMP */
+ blr
+
+/*
+ * This code is jumped to from the startup code to copy
+ * the kernel image to physical address 0.
+ */
+relocate_kernel:
+ addis r9,r26,klimit@ha /* fetch klimit */
+ lwz r25,klimit@l(r9)
+ addis r25,r25,-KERNELBASE@h
+ li r3,0 /* Destination base address */
+ li r6,0 /* Destination offset */
+ li r5,0x4000 /* # bytes of memory to copy */
+ bl copy_and_flush /* copy the first 0x4000 bytes */
+ addi r0,r3,4f@l /* jump to the address of 4f */
+ mtctr r0 /* in copy and do the rest. */
+ bctr /* jump to the copy */
+4: mr r5,r25
+ bl copy_and_flush /* copy the rest */
+ b turn_on_mmu
+
+/*
+ * Copy routine used to copy the kernel to start at physical address 0
+ * and flush and invalidate the caches as needed.
+ * r3 = dest addr, r4 = source addr, r5 = copy limit, r6 = start offset
+ * on exit, r3, r4, r5 are unchanged, r6 is updated to be >= r5.
+ */
+copy_and_flush:
+ addi r5,r5,-4
+ addi r6,r6,-4
+4: li r0,L1_CACHE_LINE_SIZE/4
+ mtctr r0
+3: addi r6,r6,4 /* copy a cache line */
+ lwzx r0,r6,r4
+ stwx r0,r6,r3
+ bdnz 3b
+ dcbst r6,r3 /* write it to memory */
+ sync
+ icbi r6,r3 /* flush the icache line */
+ cmplw 0,r6,r5
+ blt 4b
+ sync /* additional sync needed on g4 */
+ isync
+ addi r5,r5,4
+ addi r6,r6,4
+ blr
+
+#ifdef CONFIG_APUS
+/*
+ * On APUS the physical base address of the kernel is not known at compile
+ * time, which means the __pa/__va constants used are incorrect. In the
+ * __init section is recorded the virtual addresses of instructions using
+ * these constants, so all that has to be done is fix these before
+ * continuing the kernel boot.
+ *
+ * r4 = The physical address of the kernel base.
+ */
+fix_mem_constants:
+ mr r10,r4
+ addis r10,r10,-KERNELBASE@h /* virt_to_phys constant */
+ neg r11,r10 /* phys_to_virt constant */
+
+ lis r12,__vtop_table_begin@h
+ ori r12,r12,__vtop_table_begin@l
+ add r12,r12,r10 /* table begin phys address */
+ lis r13,__vtop_table_end@h
+ ori r13,r13,__vtop_table_end@l
+ add r13,r13,r10 /* table end phys address */
+ subi r12,r12,4
+ subi r13,r13,4
+1: lwzu r14,4(r12) /* virt address of instruction */
+ add r14,r14,r10 /* phys address of instruction */
+ lwz r15,0(r14) /* instruction, now insert top */
+ rlwimi r15,r10,16,16,31 /* half of vp const in low half */
+ stw r15,0(r14) /* of instruction and restore. */
+ dcbst r0,r14 /* write it to memory */
+ sync
+ icbi r0,r14 /* flush the icache line */
+ cmpw r12,r13
+ bne 1b
+ sync /* additional sync needed on g4 */
+ isync
+
+/*
+ * Map the memory where the exception handlers will
+ * be copied to when hash constants have been patched.
+ */
+#ifdef CONFIG_APUS_FAST_EXCEPT
+ lis r8,0xfff0
+#else
+ lis r8,0
+#endif
+ ori r8,r8,0x2 /* 128KB, supervisor */
+ mtspr SPRN_DBAT3U,r8
+ mtspr SPRN_DBAT3L,r8
+
+ lis r12,__ptov_table_begin@h
+ ori r12,r12,__ptov_table_begin@l
+ add r12,r12,r10 /* table begin phys address */
+ lis r13,__ptov_table_end@h
+ ori r13,r13,__ptov_table_end@l
+ add r13,r13,r10 /* table end phys address */
+ subi r12,r12,4
+ subi r13,r13,4
+1: lwzu r14,4(r12) /* virt address of instruction */
+ add r14,r14,r10 /* phys address of instruction */
+ lwz r15,0(r14) /* instruction, now insert top */
+ rlwimi r15,r11,16,16,31 /* half of pv const in low half*/
+ stw r15,0(r14) /* of instruction and restore. */
+ dcbst r0,r14 /* write it to memory */
+ sync
+ icbi r0,r14 /* flush the icache line */
+ cmpw r12,r13
+ bne 1b
+
+ sync /* additional sync needed on g4 */
+ isync /* No speculative loading until now */
+ blr
+
+/***********************************************************************
+ * Please note that on APUS the exception handlers are located at the
+ * physical address 0xfff0000. For this reason, the exception handlers
+ * cannot use relative branches to access the code below.
+ ***********************************************************************/
+#endif /* CONFIG_APUS */
+
+#ifdef CONFIG_SMP
+#ifdef CONFIG_GEMINI
+ .globl __secondary_start_gemini
+__secondary_start_gemini:
+ mfspr r4,SPRN_HID0
+ ori r4,r4,HID0_ICFI
+ li r3,0
+ ori r3,r3,HID0_ICE
+ andc r4,r4,r3
+ mtspr SPRN_HID0,r4
+ sync
+ bl gemini_prom_init
+ b __secondary_start
+#endif /* CONFIG_GEMINI */
+ .globl __secondary_start_psurge
+__secondary_start_psurge:
+ li r24,1 /* cpu # */
+ b __secondary_start_psurge99
+ .globl __secondary_start_psurge2
+__secondary_start_psurge2:
+ li r24,2 /* cpu # */
+ b __secondary_start_psurge99
+ .globl __secondary_start_psurge3
+__secondary_start_psurge3:
+ li r24,3 /* cpu # */
+ b __secondary_start_psurge99
+__secondary_start_psurge99:
+ /* we come in here with IR=0 and DR=1, and DBAT 0
+ set to map the 0xf0000000 - 0xffffffff region */
+ mfmsr r0
+ rlwinm r0,r0,0,28,26 /* clear DR (0x10) */
+ SYNC
+ mtmsr r0
+ isync
+
+ .globl __secondary_start
+__secondary_start:
+#ifdef CONFIG_PPC64BRIDGE
+ mfmsr r0
+ clrldi r0,r0,1 /* make sure it's in 32-bit mode */
+ SYNC
+ MTMSRD(r0)
+ isync
+#endif
+ /* Copy some CPU settings from CPU 0 */
+ bl __restore_cpu_setup
+
+ lis r3,-KERNELBASE@h
+ mr r4,r24
+ bl identify_cpu
+ bl call_setup_cpu /* Call setup_cpu for this CPU */
+#ifdef CONFIG_6xx
+ lis r3,-KERNELBASE@h
+ bl init_idle_6xx
+#endif /* CONFIG_6xx */
+#ifdef CONFIG_POWER4
+ lis r3,-KERNELBASE@h
+ bl init_idle_power4
+#endif /* CONFIG_POWER4 */
+
+ /* get current_thread_info and current */
+ lis r1,secondary_ti@ha
+ tophys(r1,r1)
+ lwz r1,secondary_ti@l(r1)
+ tophys(r2,r1)
+ lwz r2,TI_TASK(r2)
+
+ /* stack */
+ addi r1,r1,THREAD_SIZE-STACK_FRAME_OVERHEAD
+ li r0,0
+ tophys(r3,r1)
+ stw r0,0(r3)
+
+ /* load up the MMU */
+ bl load_up_mmu
+
+ /* ptr to phys current thread */
+ tophys(r4,r2)
+ addi r4,r4,THREAD /* phys address of our thread_struct */
+ CLR_TOP32(r4)
+ mtspr SPRN_SPRG3,r4
+ li r3,0
+ mtspr SPRN_SPRG2,r3 /* 0 => not in RTAS */
+
+ /* enable MMU and jump to start_secondary */
+ li r4,MSR_KERNEL
+ FIX_SRR1(r4,r5)
+ lis r3,start_secondary@h
+ ori r3,r3,start_secondary@l
+ mtspr SPRN_SRR0,r3
+ mtspr SPRN_SRR1,r4
+ SYNC
+ RFI
+#endif /* CONFIG_SMP */
+
+/*
+ * Those generic dummy functions are kept for CPUs not
+ * included in CONFIG_6xx
+ */
+_GLOBAL(__setup_cpu_power3)
+ blr
+_GLOBAL(__setup_cpu_generic)
+ blr
+
+#if !defined(CONFIG_6xx) && !defined(CONFIG_POWER4)
+_GLOBAL(__save_cpu_setup)
+ blr
+_GLOBAL(__restore_cpu_setup)
+ blr
+#endif /* !defined(CONFIG_6xx) && !defined(CONFIG_POWER4) */
+
+
+/*
+ * Load stuff into the MMU. Intended to be called with
+ * IR=0 and DR=0.
+ */
+load_up_mmu:
+ sync /* Force all PTE updates to finish */
+ isync
+ tlbia /* Clear all TLB entries */
+ sync /* wait for tlbia/tlbie to finish */
+ TLBSYNC /* ... on all CPUs */
+ /* Load the SDR1 register (hash table base & size) */
+ lis r6,_SDR1@ha
+ tophys(r6,r6)
+ lwz r6,_SDR1@l(r6)
+ mtspr SPRN_SDR1,r6
+#ifdef CONFIG_PPC64BRIDGE
+ /* clear the ASR so we only use the pseudo-segment registers. */
+ li r6,0
+ mtasr r6
+#endif /* CONFIG_PPC64BRIDGE */
+ li r0,16 /* load up segment register values */
+ mtctr r0 /* for context 0 */
+ lis r3,0x2000 /* Ku = 1, VSID = 0 */
+ li r4,0
+3: mtsrin r3,r4
+ addi r3,r3,0x111 /* increment VSID */
+ addis r4,r4,0x1000 /* address of next segment */
+ bdnz 3b
+#ifndef CONFIG_POWER4
+/* Load the BAT registers with the values set up by MMU_init.
+ MMU_init takes care of whether we're on a 601 or not. */
+ mfpvr r3
+ srwi r3,r3,16
+ cmpwi r3,1
+ lis r3,BATS@ha
+ addi r3,r3,BATS@l
+ tophys(r3,r3)
+ LOAD_BAT(0,r3,r4,r5)
+ LOAD_BAT(1,r3,r4,r5)
+ LOAD_BAT(2,r3,r4,r5)
+ LOAD_BAT(3,r3,r4,r5)
+#endif /* CONFIG_POWER4 */
+ blr
+
+/*
+ * This is where the main kernel code starts.
+ */
+start_here:
+ /* ptr to current */
+ lis r2,init_task@h
+ ori r2,r2,init_task@l
+ /* Set up for using our exception vectors */
+ /* ptr to phys current thread */
+ tophys(r4,r2)
+ addi r4,r4,THREAD /* init task's THREAD */
+ CLR_TOP32(r4)
+ mtspr SPRN_SPRG3,r4
+ li r3,0
+ mtspr SPRN_SPRG2,r3 /* 0 => not in RTAS */
+
+ /* stack */
+ lis r1,init_thread_union@ha
+ addi r1,r1,init_thread_union@l
+ li r0,0
+ stwu r0,THREAD_SIZE-STACK_FRAME_OVERHEAD(r1)
+/*
+ * Do early bootinfo parsing, platform-specific initialization,
+ * and set up the MMU.
+ */
+ mr r3,r31
+ mr r4,r30
+ mr r5,r29
+ mr r6,r28
+ mr r7,r27
+ bl machine_init
+ bl MMU_init
+
+#ifdef CONFIG_APUS
+ /* Copy exception code to exception vector base on APUS. */
+ lis r4,KERNELBASE@h
+#ifdef CONFIG_APUS_FAST_EXCEPT
+ lis r3,0xfff0 /* Copy to 0xfff00000 */
+#else
+ lis r3,0 /* Copy to 0x00000000 */
+#endif
+ li r5,0x4000 /* # bytes of memory to copy */
+ li r6,0
+ bl copy_and_flush /* copy the first 0x4000 bytes */
+#endif /* CONFIG_APUS */
+
+/*
+ * Go back to running unmapped so we can load up new values
+ * for SDR1 (hash table pointer) and the segment registers
+ * and change to using our exception vectors.
+ */
+ lis r4,2f@h
+ ori r4,r4,2f@l
+ tophys(r4,r4)
+ li r3,MSR_KERNEL & ~(MSR_IR|MSR_DR)
+ FIX_SRR1(r3,r5)
+ mtspr SPRN_SRR0,r4
+ mtspr SPRN_SRR1,r3
+ SYNC
+ RFI
+/* Load up the kernel context */
+2: bl load_up_mmu
+
+#ifdef CONFIG_BDI_SWITCH
+ /* Add helper information for the Abatron bdiGDB debugger.
+ * We do this here because we know the mmu is disabled, and
+ * will be enabled for real in just a few instructions.
+ */
+ lis r5, abatron_pteptrs@h
+ ori r5, r5, abatron_pteptrs@l
+ stw r5, 0xf0(r0) /* This much match your Abatron config */
+ lis r6, swapper_pg_dir@h
+ ori r6, r6, swapper_pg_dir@l
+ tophys(r5, r5)
+ stw r6, 0(r5)
+#endif /* CONFIG_BDI_SWITCH */
+
+/* Now turn on the MMU for real! */
+ li r4,MSR_KERNEL
+ FIX_SRR1(r4,r5)
+ lis r3,start_kernel@h
+ ori r3,r3,start_kernel@l
+ mtspr SPRN_SRR0,r3
+ mtspr SPRN_SRR1,r4
+ SYNC
+ RFI
+
+/*
+ * Set up the segment registers for a new context.
+ */
+_GLOBAL(set_context)
+ mulli r3,r3,897 /* multiply context by skew factor */
+ rlwinm r3,r3,4,8,27 /* VSID = (context & 0xfffff) << 4 */
+ addis r3,r3,0x6000 /* Set Ks, Ku bits */
+ li r0,NUM_USER_SEGMENTS
+ mtctr r0
+
+#ifdef CONFIG_BDI_SWITCH
+ /* Context switch the PTE pointer for the Abatron BDI2000.
+ * The PGDIR is passed as second argument.
+ */
+ lis r5, KERNELBASE@h
+ lwz r5, 0xf0(r5)
+ stw r4, 0x4(r5)
+#endif
+ li r4,0
+ isync
+3:
+#ifdef CONFIG_PPC64BRIDGE
+ slbie r4
+#endif /* CONFIG_PPC64BRIDGE */
+ mtsrin r3,r4
+ addi r3,r3,0x111 /* next VSID */
+ rlwinm r3,r3,0,8,3 /* clear out any overflow from VSID field */
+ addis r4,r4,0x1000 /* address of next segment */
+ bdnz 3b
+ sync
+ isync
+ blr
+
+/*
+ * An undocumented "feature" of 604e requires that the v bit
+ * be cleared before changing BAT values.
+ *
+ * Also, newer IBM firmware does not clear bat3 and 4 so
+ * this makes sure it's done.
+ * -- Cort
+ */
+clear_bats:
+ li r10,0
+ mfspr r9,SPRN_PVR
+ rlwinm r9,r9,16,16,31 /* r9 = 1 for 601, 4 for 604 */
+ cmpwi r9, 1
+ beq 1f
+
+ mtspr SPRN_DBAT0U,r10
+ mtspr SPRN_DBAT0L,r10
+ mtspr SPRN_DBAT1U,r10
+ mtspr SPRN_DBAT1L,r10
+ mtspr SPRN_DBAT2U,r10
+ mtspr SPRN_DBAT2L,r10
+ mtspr SPRN_DBAT3U,r10
+ mtspr SPRN_DBAT3L,r10
+1:
+ mtspr SPRN_IBAT0U,r10
+ mtspr SPRN_IBAT0L,r10
+ mtspr SPRN_IBAT1U,r10
+ mtspr SPRN_IBAT1L,r10
+ mtspr SPRN_IBAT2U,r10
+ mtspr SPRN_IBAT2L,r10
+ mtspr SPRN_IBAT3U,r10
+ mtspr SPRN_IBAT3L,r10
+BEGIN_FTR_SECTION
+ /* Here's a tweak: at this point, CPU setup have
+ * not been called yet, so HIGH_BAT_EN may not be
+ * set in HID0 for the 745x processors. However, it
+ * seems that doesn't affect our ability to actually
+ * write to these SPRs.
+ */
+ mtspr SPRN_DBAT4U,r10
+ mtspr SPRN_DBAT4L,r10
+ mtspr SPRN_DBAT5U,r10
+ mtspr SPRN_DBAT5L,r10
+ mtspr SPRN_DBAT6U,r10
+ mtspr SPRN_DBAT6L,r10
+ mtspr SPRN_DBAT7U,r10
+ mtspr SPRN_DBAT7L,r10
+ mtspr SPRN_IBAT4U,r10
+ mtspr SPRN_IBAT4L,r10
+ mtspr SPRN_IBAT5U,r10
+ mtspr SPRN_IBAT5L,r10
+ mtspr SPRN_IBAT6U,r10
+ mtspr SPRN_IBAT6L,r10
+ mtspr SPRN_IBAT7U,r10
+ mtspr SPRN_IBAT7L,r10
+END_FTR_SECTION_IFSET(CPU_FTR_HAS_HIGH_BATS)
+ blr
+
+flush_tlbs:
+ lis r10, 0x40
+1: addic. r10, r10, -0x1000
+ tlbie r10
+ blt 1b
+ sync
+ blr
+
+mmu_off:
+ addi r4, r3, __after_mmu_off - _start
+ mfmsr r3
+ andi. r0,r3,MSR_DR|MSR_IR /* MMU enabled? */
+ beqlr
+ andc r3,r3,r0
+ mtspr SPRN_SRR0,r4
+ mtspr SPRN_SRR1,r3
+ sync
+ RFI
+
+#ifndef CONFIG_POWER4
+/*
+ * Use the first pair of BAT registers to map the 1st 16MB
+ * of RAM to KERNELBASE. From this point on we can't safely
+ * call OF any more.
+ */
+initial_bats:
+ lis r11,KERNELBASE@h
+#ifndef CONFIG_PPC64BRIDGE
+ mfspr r9,SPRN_PVR
+ rlwinm r9,r9,16,16,31 /* r9 = 1 for 601, 4 for 604 */
+ cmpwi 0,r9,1
+ bne 4f
+ ori r11,r11,4 /* set up BAT registers for 601 */
+ li r8,0x7f /* valid, block length = 8MB */
+ oris r9,r11,0x800000@h /* set up BAT reg for 2nd 8M */
+ oris r10,r8,0x800000@h /* set up BAT reg for 2nd 8M */
+ mtspr SPRN_IBAT0U,r11 /* N.B. 601 has valid bit in */
+ mtspr SPRN_IBAT0L,r8 /* lower BAT register */
+ mtspr SPRN_IBAT1U,r9
+ mtspr SPRN_IBAT1L,r10
+ isync
+ blr
+#endif /* CONFIG_PPC64BRIDGE */
+
+4: tophys(r8,r11)
+#ifdef CONFIG_SMP
+ ori r8,r8,0x12 /* R/W access, M=1 */
+#else
+ ori r8,r8,2 /* R/W access */
+#endif /* CONFIG_SMP */
+#ifdef CONFIG_APUS
+ ori r11,r11,BL_8M<<2|0x2 /* set up 8MB BAT registers for 604 */
+#else
+ ori r11,r11,BL_256M<<2|0x2 /* set up BAT registers for 604 */
+#endif /* CONFIG_APUS */
+
+#ifdef CONFIG_PPC64BRIDGE
+ /* clear out the high 32 bits in the BAT */
+ clrldi r11,r11,32
+ clrldi r8,r8,32
+#endif /* CONFIG_PPC64BRIDGE */
+ mtspr SPRN_DBAT0L,r8 /* N.B. 6xx (not 601) have valid */
+ mtspr SPRN_DBAT0U,r11 /* bit in upper BAT register */
+ mtspr SPRN_IBAT0L,r8
+ mtspr SPRN_IBAT0U,r11
+ isync
+ blr
+
+#if !defined(CONFIG_APUS) && defined(CONFIG_BOOTX_TEXT)
+setup_disp_bat:
+ /*
+ * setup the display bat prepared for us in prom.c
+ */
+ mflr r8
+ bl reloc_offset
+ mtlr r8
+ addis r8,r3,disp_BAT@ha
+ addi r8,r8,disp_BAT@l
+ lwz r11,0(r8)
+ lwz r8,4(r8)
+ mfspr r9,SPRN_PVR
+ rlwinm r9,r9,16,16,31 /* r9 = 1 for 601, 4 for 604 */
+ cmpwi 0,r9,1
+ beq 1f
+ mtspr SPRN_DBAT3L,r8
+ mtspr SPRN_DBAT3U,r11
+ blr
+1: mtspr SPRN_IBAT3L,r8
+ mtspr SPRN_IBAT3U,r11
+ blr
+
+#endif /* !defined(CONFIG_APUS) && defined(CONFIG_BOOTX_TEXT) */
+
+#else /* CONFIG_POWER4 */
+/*
+ * Load up the SDR1 and segment register values now
+ * since we don't have the BATs.
+ * Also make sure we are running in 32-bit mode.
+ */
+
+initial_mm_power4:
+ addis r14,r3,_SDR1@ha /* get the value from _SDR1 */
+ lwz r14,_SDR1@l(r14) /* assume hash table below 4GB */
+ mtspr SPRN_SDR1,r14
+ slbia
+ lis r4,0x2000 /* set pseudo-segment reg 12 */
+ ori r5,r4,0x0ccc
+ mtsr 12,r5
+#if 0
+ ori r5,r4,0x0888 /* set pseudo-segment reg 8 */
+ mtsr 8,r5 /* (for access to serial port) */
+#endif
+#ifdef CONFIG_BOOTX_TEXT
+ ori r5,r4,0x0999 /* set pseudo-segment reg 9 */
+ mtsr 9,r5 /* (for access to screen) */
+#endif
+ mfmsr r0
+ clrldi r0,r0,1
+ sync
+ mtmsr r0
+ isync
+ blr
+
+#endif /* CONFIG_POWER4 */
+
+#ifdef CONFIG_8260
+/* Jump into the system reset for the rom.
+ * We first disable the MMU, and then jump to the ROM reset address.
+ *
+ * r3 is the board info structure, r4 is the location for starting.
+ * I use this for building a small kernel that can load other kernels,
+ * rather than trying to write or rely on a rom monitor that can tftp load.
+ */
+ .globl m8260_gorom
+m8260_gorom:
+ mfmsr r0
+ rlwinm r0,r0,0,17,15 /* clear MSR_EE in r0 */
+ sync
+ mtmsr r0
+ sync
+ mfspr r11, SPRN_HID0
+ lis r10, 0
+ ori r10,r10,HID0_ICE|HID0_DCE
+ andc r11, r11, r10
+ mtspr SPRN_HID0, r11
+ isync
+ li r5, MSR_ME|MSR_RI
+ lis r6,2f@h
+ addis r6,r6,-KERNELBASE@h
+ ori r6,r6,2f@l
+ mtspr SPRN_SRR0,r6
+ mtspr SPRN_SRR1,r5
+ isync
+ sync
+ rfi
+2:
+ mtlr r4
+ blr
+#endif
+
+
+/*
+ * We put a few things here that have to be page-aligned.
+ * This stuff goes at the beginning of the data segment,
+ * which is page-aligned.
+ */
+ .data
+ .globl sdata
+sdata:
+ .globl empty_zero_page
+empty_zero_page:
+ .space 4096
+
+ .globl swapper_pg_dir
+swapper_pg_dir:
+ .space 4096
+
+/*
+ * This space gets a copy of optional info passed to us by the bootstrap
+ * Used to pass parameters into the kernel like root=/dev/sda1, etc.
+ */
+ .globl cmd_line
+cmd_line:
+ .space 512
+
+ .globl intercept_table
+intercept_table:
+ .long 0, 0, i0x200, i0x300, i0x400, 0, i0x600, i0x700
+ .long i0x800, 0, 0, 0, 0, i0xd00, 0, 0
+ .long 0, 0, 0, i0x1300, 0, 0, 0, 0
+ .long 0, 0, 0, 0, 0, 0, 0, 0
+ .long 0, 0, 0, 0, 0, 0, 0, 0
+ .long 0, 0, 0, 0, 0, 0, 0, 0
+
+/* Room for two PTE pointers, usually the kernel and current user pointers
+ * to their respective root page table.
+ */
+abatron_pteptrs:
+ .space 8
diff --git a/arch/ppc/kernel/head_44x.S b/arch/ppc/kernel/head_44x.S
new file mode 100644
index 0000000..9ed8165
--- /dev/null
+++ b/arch/ppc/kernel/head_44x.S
@@ -0,0 +1,753 @@
+/*
+ * arch/ppc/kernel/head_44x.S
+ *
+ * Kernel execution entry point code.
+ *
+ * Copyright (c) 1995-1996 Gary Thomas <gdt@linuxppc.org>
+ * Initial PowerPC version.
+ * Copyright (c) 1996 Cort Dougan <cort@cs.nmt.edu>
+ * Rewritten for PReP
+ * Copyright (c) 1996 Paul Mackerras <paulus@cs.anu.edu.au>
+ * Low-level exception handers, MMU support, and rewrite.
+ * Copyright (c) 1997 Dan Malek <dmalek@jlc.net>
+ * PowerPC 8xx modifications.
+ * Copyright (c) 1998-1999 TiVo, Inc.
+ * PowerPC 403GCX modifications.
+ * Copyright (c) 1999 Grant Erickson <grant@lcse.umn.edu>
+ * PowerPC 403GCX/405GP modifications.
+ * Copyright 2000 MontaVista Software Inc.
+ * PPC405 modifications
+ * PowerPC 403GCX/405GP modifications.
+ * Author: MontaVista Software, Inc.
+ * frank_rowand@mvista.com or source@mvista.com
+ * debbie_chu@mvista.com
+ * Copyright 2002-2005 MontaVista Software, Inc.
+ * PowerPC 44x support, Matt Porter <mporter@kernel.crashing.org>
+ *
+ * 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.
+ */
+
+#include <linux/config.h>
+#include <asm/processor.h>
+#include <asm/page.h>
+#include <asm/mmu.h>
+#include <asm/pgtable.h>
+#include <asm/ibm4xx.h>
+#include <asm/ibm44x.h>
+#include <asm/cputable.h>
+#include <asm/thread_info.h>
+#include <asm/ppc_asm.h>
+#include <asm/offsets.h>
+#include "head_booke.h"
+
+
+/* As with the other PowerPC ports, it is expected that when code
+ * execution begins here, the following registers contain valid, yet
+ * optional, information:
+ *
+ * r3 - Board info structure pointer (DRAM, frequency, MAC address, etc.)
+ * r4 - Starting address of the init RAM disk
+ * r5 - Ending address of the init RAM disk
+ * r6 - Start of kernel command line string (e.g. "mem=128")
+ * r7 - End of kernel command line string
+ *
+ */
+ .text
+_GLOBAL(_stext)
+_GLOBAL(_start)
+ /*
+ * Reserve a word at a fixed location to store the address
+ * of abatron_pteptrs
+ */
+ nop
+/*
+ * Save parameters we are passed
+ */
+ mr r31,r3
+ mr r30,r4
+ mr r29,r5
+ mr r28,r6
+ mr r27,r7
+ li r24,0 /* CPU number */
+
+/*
+ * Set up the initial MMU state
+ *
+ * We are still executing code at the virtual address
+ * mappings set by the firmware for the base of RAM.
+ *
+ * We first invalidate all TLB entries but the one
+ * we are running from. We then load the KERNELBASE
+ * mappings so we can begin to use kernel addresses
+ * natively and so the interrupt vector locations are
+ * permanently pinned (necessary since Book E
+ * implementations always have translation enabled).
+ *
+ * TODO: Use the known TLB entry we are running from to
+ * determine which physical region we are located
+ * in. This can be used to determine where in RAM
+ * (on a shared CPU system) or PCI memory space
+ * (on a DRAMless system) we are located.
+ * For now, we assume a perfect world which means
+ * we are located at the base of DRAM (physical 0).
+ */
+
+/*
+ * Search TLB for entry that we are currently using.
+ * Invalidate all entries but the one we are using.
+ */
+ /* Load our current PID->MMUCR TID and MSR IS->MMUCR STS */
+ mfspr r3,SPRN_PID /* Get PID */
+ mfmsr r4 /* Get MSR */
+ andi. r4,r4,MSR_IS@l /* TS=1? */
+ beq wmmucr /* If not, leave STS=0 */
+ oris r3,r3,PPC44x_MMUCR_STS@h /* Set STS=1 */
+wmmucr: mtspr SPRN_MMUCR,r3 /* Put MMUCR */
+ sync
+
+ bl invstr /* Find our address */
+invstr: mflr r5 /* Make it accessible */
+ tlbsx r23,0,r5 /* Find entry we are in */
+ li r4,0 /* Start at TLB entry 0 */
+ li r3,0 /* Set PAGEID inval value */
+1: cmpw r23,r4 /* Is this our entry? */
+ beq skpinv /* If so, skip the inval */
+ tlbwe r3,r4,PPC44x_TLB_PAGEID /* If not, inval the entry */
+skpinv: addi r4,r4,1 /* Increment */
+ cmpwi r4,64 /* Are we done? */
+ bne 1b /* If not, repeat */
+ isync /* If so, context change */
+
+/*
+ * Configure and load pinned entry into TLB slot 63.
+ */
+
+ lis r3,KERNELBASE@h /* Load the kernel virtual address */
+ ori r3,r3,KERNELBASE@l
+
+ /* Kernel is at the base of RAM */
+ li r4, 0 /* Load the kernel physical address */
+
+ /* Load the kernel PID = 0 */
+ li r0,0
+ mtspr SPRN_PID,r0
+ sync
+
+ /* Initialize MMUCR */
+ li r5,0
+ mtspr SPRN_MMUCR,r5
+ sync
+
+ /* pageid fields */
+ clrrwi r3,r3,10 /* Mask off the effective page number */
+ ori r3,r3,PPC44x_TLB_VALID | PPC44x_TLB_256M
+
+ /* xlat fields */
+ clrrwi r4,r4,10 /* Mask off the real page number */
+ /* ERPN is 0 for first 4GB page */
+
+ /* attrib fields */
+ /* Added guarded bit to protect against speculative loads/stores */
+ li r5,0
+ ori r5,r5,(PPC44x_TLB_SW | PPC44x_TLB_SR | PPC44x_TLB_SX | PPC44x_TLB_G)
+
+ li r0,63 /* TLB slot 63 */
+
+ tlbwe r3,r0,PPC44x_TLB_PAGEID /* Load the pageid fields */
+ tlbwe r4,r0,PPC44x_TLB_XLAT /* Load the translation fields */
+ tlbwe r5,r0,PPC44x_TLB_ATTRIB /* Load the attrib/access fields */
+
+ /* Force context change */
+ mfmsr r0
+ mtspr SPRN_SRR1, r0
+ lis r0,3f@h
+ ori r0,r0,3f@l
+ mtspr SPRN_SRR0,r0
+ sync
+ rfi
+
+ /* If necessary, invalidate original entry we used */
+3: cmpwi r23,63
+ beq 4f
+ li r6,0
+ tlbwe r6,r23,PPC44x_TLB_PAGEID
+ isync
+
+4:
+#ifdef CONFIG_SERIAL_TEXT_DEBUG
+ /*
+ * Add temporary UART mapping for early debug. This
+ * mapping must be identical to that used by the early
+ * bootloader code since the same asm/serial.h parameters
+ * are used for polled operation.
+ */
+ /* pageid fields */
+ lis r3,UART0_IO_BASE@h
+ ori r3,r3,PPC44x_TLB_VALID | PPC44x_TLB_256M
+
+ /* xlat fields */
+ lis r4,UART0_PHYS_IO_BASE@h /* RPN depends on SoC */
+ ori r4,r4,0x0001 /* ERPN is 1 for second 4GB page */
+
+ /* attrib fields */
+ li r5,0
+ ori r5,r5,(PPC44x_TLB_SW | PPC44x_TLB_SR | PPC44x_TLB_I | PPC44x_TLB_G)
+
+ li r0,1 /* TLB slot 1 */
+
+ tlbwe r3,r0,PPC44x_TLB_PAGEID /* Load the pageid fields */
+ tlbwe r4,r0,PPC44x_TLB_XLAT /* Load the translation fields */
+ tlbwe r5,r0,PPC44x_TLB_ATTRIB /* Load the attrib/access fields */
+
+ /* Force context change */
+ isync
+#endif /* CONFIG_SERIAL_TEXT_DEBUG */
+
+ /* Establish the interrupt vector offsets */
+ SET_IVOR(0, CriticalInput);
+ SET_IVOR(1, MachineCheck);
+ SET_IVOR(2, DataStorage);
+ SET_IVOR(3, InstructionStorage);
+ SET_IVOR(4, ExternalInput);
+ SET_IVOR(5, Alignment);
+ SET_IVOR(6, Program);
+ SET_IVOR(7, FloatingPointUnavailable);
+ SET_IVOR(8, SystemCall);
+ SET_IVOR(9, AuxillaryProcessorUnavailable);
+ SET_IVOR(10, Decrementer);
+ SET_IVOR(11, FixedIntervalTimer);
+ SET_IVOR(12, WatchdogTimer);
+ SET_IVOR(13, DataTLBError);
+ SET_IVOR(14, InstructionTLBError);
+ SET_IVOR(15, Debug);
+
+ /* Establish the interrupt vector base */
+ lis r4,interrupt_base@h /* IVPR only uses the high 16-bits */
+ mtspr SPRN_IVPR,r4
+
+ /*
+ * This is where the main kernel code starts.
+ */
+
+ /* ptr to current */
+ lis r2,init_task@h
+ ori r2,r2,init_task@l
+
+ /* ptr to current thread */
+ addi r4,r2,THREAD /* init task's THREAD */
+ mtspr SPRN_SPRG3,r4
+
+ /* stack */
+ lis r1,init_thread_union@h
+ ori r1,r1,init_thread_union@l
+ li r0,0
+ stwu r0,THREAD_SIZE-STACK_FRAME_OVERHEAD(r1)
+
+ bl early_init
+
+/*
+ * Decide what sort of machine this is and initialize the MMU.
+ */
+ mr r3,r31
+ mr r4,r30
+ mr r5,r29
+ mr r6,r28
+ mr r7,r27
+ bl machine_init
+ bl MMU_init
+
+ /* Setup PTE pointers for the Abatron bdiGDB */
+ lis r6, swapper_pg_dir@h
+ ori r6, r6, swapper_pg_dir@l
+ lis r5, abatron_pteptrs@h
+ ori r5, r5, abatron_pteptrs@l
+ lis r4, KERNELBASE@h
+ ori r4, r4, KERNELBASE@l
+ stw r5, 0(r4) /* Save abatron_pteptrs at a fixed location */
+ stw r6, 0(r5)
+
+ /* Let's move on */
+ lis r4,start_kernel@h
+ ori r4,r4,start_kernel@l
+ lis r3,MSR_KERNEL@h
+ ori r3,r3,MSR_KERNEL@l
+ mtspr SPRN_SRR0,r4
+ mtspr SPRN_SRR1,r3
+ rfi /* change context and jump to start_kernel */
+
+/*
+ * Interrupt vector entry code
+ *
+ * The Book E MMUs are always on so we don't need to handle
+ * interrupts in real mode as with previous PPC processors. In
+ * this case we handle interrupts in the kernel virtual address
+ * space.
+ *
+ * Interrupt vectors are dynamically placed relative to the
+ * interrupt prefix as determined by the address of interrupt_base.
+ * The interrupt vectors offsets are programmed using the labels
+ * for each interrupt vector entry.
+ *
+ * Interrupt vectors must be aligned on a 16 byte boundary.
+ * We align on a 32 byte cache line boundary for good measure.
+ */
+
+interrupt_base:
+ /* Critical Input Interrupt */
+ CRITICAL_EXCEPTION(0x0100, CriticalInput, UnknownException)
+
+ /* Machine Check Interrupt */
+#ifdef CONFIG_440A
+ MCHECK_EXCEPTION(0x0200, MachineCheck, MachineCheckException)
+#else
+ CRITICAL_EXCEPTION(0x0200, MachineCheck, MachineCheckException)
+#endif
+
+ /* Data Storage Interrupt */
+ START_EXCEPTION(DataStorage)
+ mtspr SPRN_SPRG0, r10 /* Save some working registers */
+ mtspr SPRN_SPRG1, r11
+ mtspr SPRN_SPRG4W, r12
+ mtspr SPRN_SPRG5W, r13
+ mfcr r11
+ mtspr SPRN_SPRG7W, r11
+
+ /*
+ * Check if it was a store fault, if not then bail
+ * because a user tried to access a kernel or
+ * read-protected page. Otherwise, get the
+ * offending address and handle it.
+ */
+ mfspr r10, SPRN_ESR
+ andis. r10, r10, ESR_ST@h
+ beq 2f
+
+ mfspr r10, SPRN_DEAR /* Get faulting address */
+
+ /* If we are faulting a kernel address, we have to use the
+ * kernel page tables.
+ */
+ andis. r11, r10, 0x8000
+ beq 3f
+ lis r11, swapper_pg_dir@h
+ ori r11, r11, swapper_pg_dir@l
+
+ mfspr r12,SPRN_MMUCR
+ rlwinm r12,r12,0,0,23 /* Clear TID */
+
+ b 4f
+
+ /* Get the PGD for the current thread */
+3:
+ mfspr r11,SPRN_SPRG3
+ lwz r11,PGDIR(r11)
+
+ /* Load PID into MMUCR TID */
+ mfspr r12,SPRN_MMUCR /* Get MMUCR */
+ mfspr r13,SPRN_PID /* Get PID */
+ rlwimi r12,r13,0,24,31 /* Set TID */
+
+4:
+ mtspr SPRN_MMUCR,r12
+
+ rlwinm r12, r10, 13, 19, 29 /* Compute pgdir/pmd offset */
+ lwzx r11, r12, r11 /* Get pgd/pmd entry */
+ rlwinm. r12, r11, 0, 0, 20 /* Extract pt base address */
+ beq 2f /* Bail if no table */
+
+ rlwimi r12, r10, 23, 20, 28 /* Compute pte address */
+ lwz r11, 4(r12) /* Get pte entry */
+
+ andi. r13, r11, _PAGE_RW /* Is it writeable? */
+ beq 2f /* Bail if not */
+
+ /* Update 'changed'.
+ */
+ ori r11, r11, _PAGE_DIRTY|_PAGE_ACCESSED|_PAGE_HWWRITE
+ stw r11, 4(r12) /* Update Linux page table */
+
+ li r13, PPC44x_TLB_SR@l /* Set SR */
+ rlwimi r13, r11, 29, 29, 29 /* SX = _PAGE_HWEXEC */
+ rlwimi r13, r11, 0, 30, 30 /* SW = _PAGE_RW */
+ rlwimi r13, r11, 29, 28, 28 /* UR = _PAGE_USER */
+ rlwimi r12, r11, 31, 26, 26 /* (_PAGE_USER>>1)->r12 */
+ rlwimi r12, r11, 29, 30, 30 /* (_PAGE_USER>>3)->r12 */
+ and r12, r12, r11 /* HWEXEC/RW & USER */
+ rlwimi r13, r12, 0, 26, 26 /* UX = HWEXEC & USER */
+ rlwimi r13, r12, 3, 27, 27 /* UW = RW & USER */
+
+ rlwimi r11,r13,0,26,31 /* Insert static perms */
+
+ rlwinm r11,r11,0,20,15 /* Clear U0-U3 */
+
+ /* find the TLB index that caused the fault. It has to be here. */
+ tlbsx r10, 0, r10
+
+ tlbwe r11, r10, PPC44x_TLB_ATTRIB /* Write ATTRIB */
+
+ /* Done...restore registers and get out of here.
+ */
+ mfspr r11, SPRN_SPRG7R
+ mtcr r11
+ mfspr r13, SPRN_SPRG5R
+ mfspr r12, SPRN_SPRG4R
+
+ mfspr r11, SPRN_SPRG1
+ mfspr r10, SPRN_SPRG0
+ rfi /* Force context change */
+
+2:
+ /*
+ * The bailout. Restore registers to pre-exception conditions
+ * and call the heavyweights to help us out.
+ */
+ mfspr r11, SPRN_SPRG7R
+ mtcr r11
+ mfspr r13, SPRN_SPRG5R
+ mfspr r12, SPRN_SPRG4R
+
+ mfspr r11, SPRN_SPRG1
+ mfspr r10, SPRN_SPRG0
+ b data_access
+
+ /* Instruction Storage Interrupt */
+ INSTRUCTION_STORAGE_EXCEPTION
+
+ /* External Input Interrupt */
+ EXCEPTION(0x0500, ExternalInput, do_IRQ, EXC_XFER_LITE)
+
+ /* Alignment Interrupt */
+ ALIGNMENT_EXCEPTION
+
+ /* Program Interrupt */
+ PROGRAM_EXCEPTION
+
+ /* Floating Point Unavailable Interrupt */
+ EXCEPTION(0x2010, FloatingPointUnavailable, UnknownException, EXC_XFER_EE)
+
+ /* System Call Interrupt */
+ START_EXCEPTION(SystemCall)
+ NORMAL_EXCEPTION_PROLOG
+ EXC_XFER_EE_LITE(0x0c00, DoSyscall)
+
+ /* Auxillary Processor Unavailable Interrupt */
+ EXCEPTION(0x2020, AuxillaryProcessorUnavailable, UnknownException, EXC_XFER_EE)
+
+ /* Decrementer Interrupt */
+ DECREMENTER_EXCEPTION
+
+ /* Fixed Internal Timer Interrupt */
+ /* TODO: Add FIT support */
+ EXCEPTION(0x1010, FixedIntervalTimer, UnknownException, EXC_XFER_EE)
+
+ /* Watchdog Timer Interrupt */
+ /* TODO: Add watchdog support */
+ CRITICAL_EXCEPTION(0x1020, WatchdogTimer, UnknownException)
+
+ /* Data TLB Error Interrupt */
+ START_EXCEPTION(DataTLBError)
+ mtspr SPRN_SPRG0, r10 /* Save some working registers */
+ mtspr SPRN_SPRG1, r11
+ mtspr SPRN_SPRG4W, r12
+ mtspr SPRN_SPRG5W, r13
+ mfcr r11
+ mtspr SPRN_SPRG7W, r11
+ mfspr r10, SPRN_DEAR /* Get faulting address */
+
+ /* If we are faulting a kernel address, we have to use the
+ * kernel page tables.
+ */
+ andis. r11, r10, 0x8000
+ beq 3f
+ lis r11, swapper_pg_dir@h
+ ori r11, r11, swapper_pg_dir@l
+
+ mfspr r12,SPRN_MMUCR
+ rlwinm r12,r12,0,0,23 /* Clear TID */
+
+ b 4f
+
+ /* Get the PGD for the current thread */
+3:
+ mfspr r11,SPRN_SPRG3
+ lwz r11,PGDIR(r11)
+
+ /* Load PID into MMUCR TID */
+ mfspr r12,SPRN_MMUCR
+ mfspr r13,SPRN_PID /* Get PID */
+ rlwimi r12,r13,0,24,31 /* Set TID */
+
+4:
+ mtspr SPRN_MMUCR,r12
+
+ rlwinm r12, r10, 13, 19, 29 /* Compute pgdir/pmd offset */
+ lwzx r11, r12, r11 /* Get pgd/pmd entry */
+ rlwinm. r12, r11, 0, 0, 20 /* Extract pt base address */
+ beq 2f /* Bail if no table */
+
+ rlwimi r12, r10, 23, 20, 28 /* Compute pte address */
+ lwz r11, 4(r12) /* Get pte entry */
+ andi. r13, r11, _PAGE_PRESENT /* Is the page present? */
+ beq 2f /* Bail if not present */
+
+ ori r11, r11, _PAGE_ACCESSED
+ stw r11, 4(r12)
+
+ /* Jump to common tlb load */
+ b finish_tlb_load
+
+2:
+ /* The bailout. Restore registers to pre-exception conditions
+ * and call the heavyweights to help us out.
+ */
+ mfspr r11, SPRN_SPRG7R
+ mtcr r11
+ mfspr r13, SPRN_SPRG5R
+ mfspr r12, SPRN_SPRG4R
+ mfspr r11, SPRN_SPRG1
+ mfspr r10, SPRN_SPRG0
+ b data_access
+
+ /* Instruction TLB Error Interrupt */
+ /*
+ * Nearly the same as above, except we get our
+ * information from different registers and bailout
+ * to a different point.
+ */
+ START_EXCEPTION(InstructionTLBError)
+ mtspr SPRN_SPRG0, r10 /* Save some working registers */
+ mtspr SPRN_SPRG1, r11
+ mtspr SPRN_SPRG4W, r12
+ mtspr SPRN_SPRG5W, r13
+ mfcr r11
+ mtspr SPRN_SPRG7W, r11
+ mfspr r10, SPRN_SRR0 /* Get faulting address */
+
+ /* If we are faulting a kernel address, we have to use the
+ * kernel page tables.
+ */
+ andis. r11, r10, 0x8000
+ beq 3f
+ lis r11, swapper_pg_dir@h
+ ori r11, r11, swapper_pg_dir@l
+
+ mfspr r12,SPRN_MMUCR
+ rlwinm r12,r12,0,0,23 /* Clear TID */
+
+ b 4f
+
+ /* Get the PGD for the current thread */
+3:
+ mfspr r11,SPRN_SPRG3
+ lwz r11,PGDIR(r11)
+
+ /* Load PID into MMUCR TID */
+ mfspr r12,SPRN_MMUCR
+ mfspr r13,SPRN_PID /* Get PID */
+ rlwimi r12,r13,0,24,31 /* Set TID */
+
+4:
+ mtspr SPRN_MMUCR,r12
+
+ rlwinm r12, r10, 13, 19, 29 /* Compute pgdir/pmd offset */
+ lwzx r11, r12, r11 /* Get pgd/pmd entry */
+ rlwinm. r12, r11, 0, 0, 20 /* Extract pt base address */
+ beq 2f /* Bail if no table */
+
+ rlwimi r12, r10, 23, 20, 28 /* Compute pte address */
+ lwz r11, 4(r12) /* Get pte entry */
+ andi. r13, r11, _PAGE_PRESENT /* Is the page present? */
+ beq 2f /* Bail if not present */
+
+ ori r11, r11, _PAGE_ACCESSED
+ stw r11, 4(r12)
+
+ /* Jump to common TLB load point */
+ b finish_tlb_load
+
+2:
+ /* The bailout. Restore registers to pre-exception conditions
+ * and call the heavyweights to help us out.
+ */
+ mfspr r11, SPRN_SPRG7R
+ mtcr r11
+ mfspr r13, SPRN_SPRG5R
+ mfspr r12, SPRN_SPRG4R
+ mfspr r11, SPRN_SPRG1
+ mfspr r10, SPRN_SPRG0
+ b InstructionStorage
+
+ /* Debug Interrupt */
+ DEBUG_EXCEPTION
+
+/*
+ * Local functions
+ */
+ /*
+ * Data TLB exceptions will bail out to this point
+ * if they can't resolve the lightweight TLB fault.
+ */
+data_access:
+ NORMAL_EXCEPTION_PROLOG
+ mfspr r5,SPRN_ESR /* Grab the ESR, save it, pass arg3 */
+ stw r5,_ESR(r11)
+ mfspr r4,SPRN_DEAR /* Grab the DEAR, save it, pass arg2 */
+ EXC_XFER_EE_LITE(0x0300, handle_page_fault)
+
+/*
+
+ * Both the instruction and data TLB miss get to this
+ * point to load the TLB.
+ * r10 - EA of fault
+ * r11 - available to use
+ * r12 - Pointer to the 64-bit PTE
+ * r13 - available to use
+ * MMUCR - loaded with proper value when we get here
+ * Upon exit, we reload everything and RFI.
+ */
+finish_tlb_load:
+ /*
+ * We set execute, because we don't have the granularity to
+ * properly set this at the page level (Linux problem).
+ * If shared is set, we cause a zero PID->TID load.
+ * Many of these bits are software only. Bits we don't set
+ * here we (properly should) assume have the appropriate value.
+ */
+
+ /* Load the next available TLB index */
+ lis r13, tlb_44x_index@ha
+ lwz r13, tlb_44x_index@l(r13)
+ /* Load the TLB high watermark */
+ lis r11, tlb_44x_hwater@ha
+ lwz r11, tlb_44x_hwater@l(r11)
+
+ /* Increment, rollover, and store TLB index */
+ addi r13, r13, 1
+ cmpw 0, r13, r11 /* reserve entries */
+ ble 7f
+ li r13, 0
+7:
+ /* Store the next available TLB index */
+ lis r11, tlb_44x_index@ha
+ stw r13, tlb_44x_index@l(r11)
+
+ lwz r11, 0(r12) /* Get MS word of PTE */
+ lwz r12, 4(r12) /* Get LS word of PTE */
+ rlwimi r11, r12, 0, 0 , 19 /* Insert RPN */
+ tlbwe r11, r13, PPC44x_TLB_XLAT /* Write XLAT */
+
+ /*
+ * Create PAGEID. This is the faulting address,
+ * page size, and valid flag.
+ */
+ li r11, PPC44x_TLB_VALID | PPC44x_TLB_4K
+ rlwimi r10, r11, 0, 20, 31 /* Insert valid and page size */
+ tlbwe r10, r13, PPC44x_TLB_PAGEID /* Write PAGEID */
+
+ li r10, PPC44x_TLB_SR@l /* Set SR */
+ rlwimi r10, r12, 0, 30, 30 /* Set SW = _PAGE_RW */
+ rlwimi r10, r12, 29, 29, 29 /* SX = _PAGE_HWEXEC */
+ rlwimi r10, r12, 29, 28, 28 /* UR = _PAGE_USER */
+ rlwimi r11, r12, 31, 26, 26 /* (_PAGE_USER>>1)->r12 */
+ and r11, r12, r11 /* HWEXEC & USER */
+ rlwimi r10, r11, 0, 26, 26 /* UX = HWEXEC & USER */
+
+ rlwimi r12, r10, 0, 26, 31 /* Insert static perms */
+ rlwinm r12, r12, 0, 20, 15 /* Clear U0-U3 */
+ tlbwe r12, r13, PPC44x_TLB_ATTRIB /* Write ATTRIB */
+
+ /* Done...restore registers and get out of here.
+ */
+ mfspr r11, SPRN_SPRG7R
+ mtcr r11
+ mfspr r13, SPRN_SPRG5R
+ mfspr r12, SPRN_SPRG4R
+ mfspr r11, SPRN_SPRG1
+ mfspr r10, SPRN_SPRG0
+ rfi /* Force context change */
+
+/*
+ * Global functions
+ */
+
+/*
+ * extern void giveup_altivec(struct task_struct *prev)
+ *
+ * The 44x core does not have an AltiVec unit.
+ */
+_GLOBAL(giveup_altivec)
+ blr
+
+/*
+ * extern void giveup_fpu(struct task_struct *prev)
+ *
+ * The 44x core does not have an FPU.
+ */
+_GLOBAL(giveup_fpu)
+ blr
+
+/*
+ * extern void abort(void)
+ *
+ * At present, this routine just applies a system reset.
+ */
+_GLOBAL(abort)
+ mfspr r13,SPRN_DBCR0
+ oris r13,r13,DBCR0_RST_SYSTEM@h
+ mtspr SPRN_DBCR0,r13
+
+_GLOBAL(set_context)
+
+#ifdef CONFIG_BDI_SWITCH
+ /* Context switch the PTE pointer for the Abatron BDI2000.
+ * The PGDIR is the second parameter.
+ */
+ lis r5, abatron_pteptrs@h
+ ori r5, r5, abatron_pteptrs@l
+ stw r4, 0x4(r5)
+#endif
+ mtspr SPRN_PID,r3
+ isync /* Force context change */
+ blr
+
+/*
+ * We put a few things here that have to be page-aligned. This stuff
+ * goes at the beginning of the data segment, which is page-aligned.
+ */
+ .data
+_GLOBAL(sdata)
+_GLOBAL(empty_zero_page)
+ .space 4096
+
+/*
+ * To support >32-bit physical addresses, we use an 8KB pgdir.
+ */
+_GLOBAL(swapper_pg_dir)
+ .space 8192
+
+/* Reserved 4k for the critical exception stack & 4k for the machine
+ * check stack per CPU for kernel mode exceptions */
+ .section .bss
+ .align 12
+exception_stack_bottom:
+ .space BOOKE_EXCEPTION_STACK_SIZE
+_GLOBAL(exception_stack_top)
+
+/*
+ * This space gets a copy of optional info passed to us by the bootstrap
+ * which is used to pass parameters into the kernel like root=/dev/sda1, etc.
+ */
+_GLOBAL(cmd_line)
+ .space 512
+
+/*
+ * Room for two PTE pointers, usually the kernel and current user pointers
+ * to their respective root page table.
+ */
+abatron_pteptrs:
+ .space 8
+
+
diff --git a/arch/ppc/kernel/head_4xx.S b/arch/ppc/kernel/head_4xx.S
new file mode 100644
index 0000000..6f5d380
--- /dev/null
+++ b/arch/ppc/kernel/head_4xx.S
@@ -0,0 +1,1010 @@
+/*
+ * Copyright (c) 1995-1996 Gary Thomas <gdt@linuxppc.org>
+ * Initial PowerPC version.
+ * Copyright (c) 1996 Cort Dougan <cort@cs.nmt.edu>
+ * Rewritten for PReP
+ * Copyright (c) 1996 Paul Mackerras <paulus@cs.anu.edu.au>
+ * Low-level exception handers, MMU support, and rewrite.
+ * Copyright (c) 1997 Dan Malek <dmalek@jlc.net>
+ * PowerPC 8xx modifications.
+ * Copyright (c) 1998-1999 TiVo, Inc.
+ * PowerPC 403GCX modifications.
+ * Copyright (c) 1999 Grant Erickson <grant@lcse.umn.edu>
+ * PowerPC 403GCX/405GP modifications.
+ * Copyright 2000 MontaVista Software Inc.
+ * PPC405 modifications
+ * PowerPC 403GCX/405GP modifications.
+ * Author: MontaVista Software, Inc.
+ * frank_rowand@mvista.com or source@mvista.com
+ * debbie_chu@mvista.com
+ *
+ *
+ * Module name: head_4xx.S
+ *
+ * Description:
+ * Kernel execution entry point code.
+ *
+ * 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.
+ *
+ */
+
+#include <linux/config.h>
+#include <asm/processor.h>
+#include <asm/page.h>
+#include <asm/mmu.h>
+#include <asm/pgtable.h>
+#include <asm/ibm4xx.h>
+#include <asm/cputable.h>
+#include <asm/thread_info.h>
+#include <asm/ppc_asm.h>
+#include <asm/offsets.h>
+
+/* As with the other PowerPC ports, it is expected that when code
+ * execution begins here, the following registers contain valid, yet
+ * optional, information:
+ *
+ * r3 - Board info structure pointer (DRAM, frequency, MAC address, etc.)
+ * r4 - Starting address of the init RAM disk
+ * r5 - Ending address of the init RAM disk
+ * r6 - Start of kernel command line string (e.g. "mem=96m")
+ * r7 - End of kernel command line string
+ *
+ * This is all going to change RSN when we add bi_recs....... -- Dan
+ */
+ .text
+_GLOBAL(_stext)
+_GLOBAL(_start)
+
+ /* Save parameters we are passed.
+ */
+ mr r31,r3
+ mr r30,r4
+ mr r29,r5
+ mr r28,r6
+ mr r27,r7
+
+ /* We have to turn on the MMU right away so we get cache modes
+ * set correctly.
+ */
+ bl initial_mmu
+
+/* We now have the lower 16 Meg mapped into TLB entries, and the caches
+ * ready to work.
+ */
+turn_on_mmu:
+ lis r0,MSR_KERNEL@h
+ ori r0,r0,MSR_KERNEL@l
+ mtspr SPRN_SRR1,r0
+ lis r0,start_here@h
+ ori r0,r0,start_here@l
+ mtspr SPRN_SRR0,r0
+ SYNC
+ rfi /* enables MMU */
+ b . /* prevent prefetch past rfi */
+
+/*
+ * This area is used for temporarily saving registers during the
+ * critical exception prolog.
+ */
+ . = 0xc0
+crit_save:
+_GLOBAL(crit_r10)
+ .space 4
+_GLOBAL(crit_r11)
+ .space 4
+
+/*
+ * Exception vector entry code. This code runs with address translation
+ * turned off (i.e. using physical addresses). We assume SPRG3 has the
+ * physical address of the current task thread_struct.
+ * Note that we have to have decremented r1 before we write to any fields
+ * of the exception frame, since a critical interrupt could occur at any
+ * time, and it will write to the area immediately below the current r1.
+ */
+#define NORMAL_EXCEPTION_PROLOG \
+ mtspr SPRN_SPRG0,r10; /* save two registers to work with */\
+ mtspr SPRN_SPRG1,r11; \
+ mtspr SPRN_SPRG2,r1; \
+ mfcr r10; /* save CR in r10 for now */\
+ mfspr r11,SPRN_SRR1; /* check whether user or kernel */\
+ andi. r11,r11,MSR_PR; \
+ beq 1f; \
+ mfspr r1,SPRN_SPRG3; /* if from user, start at top of */\
+ lwz r1,THREAD_INFO-THREAD(r1); /* this thread's kernel stack */\
+ addi r1,r1,THREAD_SIZE; \
+1: subi r1,r1,INT_FRAME_SIZE; /* Allocate an exception frame */\
+ tophys(r11,r1); \
+ stw r10,_CCR(r11); /* save various registers */\
+ stw r12,GPR12(r11); \
+ stw r9,GPR9(r11); \
+ mfspr r10,SPRN_SPRG0; \
+ stw r10,GPR10(r11); \
+ mfspr r12,SPRN_SPRG1; \
+ stw r12,GPR11(r11); \
+ mflr r10; \
+ stw r10,_LINK(r11); \
+ mfspr r10,SPRN_SPRG2; \
+ mfspr r12,SPRN_SRR0; \
+ stw r10,GPR1(r11); \
+ mfspr r9,SPRN_SRR1; \
+ stw r10,0(r11); \
+ rlwinm r9,r9,0,14,12; /* clear MSR_WE (necessary?) */\
+ stw r0,GPR0(r11); \
+ SAVE_4GPRS(3, r11); \
+ SAVE_2GPRS(7, r11)
+
+/*
+ * Exception prolog for critical exceptions. This is a little different
+ * from the normal exception prolog above since a critical exception
+ * can potentially occur at any point during normal exception processing.
+ * Thus we cannot use the same SPRG registers as the normal prolog above.
+ * Instead we use a couple of words of memory at low physical addresses.
+ * This is OK since we don't support SMP on these processors.
+ */
+#define CRITICAL_EXCEPTION_PROLOG \
+ stw r10,crit_r10@l(0); /* save two registers to work with */\
+ stw r11,crit_r11@l(0); \
+ mfcr r10; /* save CR in r10 for now */\
+ mfspr r11,SPRN_SRR3; /* check whether user or kernel */\
+ andi. r11,r11,MSR_PR; \
+ lis r11,critical_stack_top@h; \
+ ori r11,r11,critical_stack_top@l; \
+ beq 1f; \
+ /* COMING FROM USER MODE */ \
+ mfspr r11,SPRN_SPRG3; /* if from user, start at top of */\
+ lwz r11,THREAD_INFO-THREAD(r11); /* this thread's kernel stack */\
+ addi r11,r11,THREAD_SIZE; \
+1: subi r11,r11,INT_FRAME_SIZE; /* Allocate an exception frame */\
+ tophys(r11,r11); \
+ stw r10,_CCR(r11); /* save various registers */\
+ stw r12,GPR12(r11); \
+ stw r9,GPR9(r11); \
+ mflr r10; \
+ stw r10,_LINK(r11); \
+ mfspr r12,SPRN_DEAR; /* save DEAR and ESR in the frame */\
+ stw r12,_DEAR(r11); /* since they may have had stuff */\
+ mfspr r9,SPRN_ESR; /* in them at the point where the */\
+ stw r9,_ESR(r11); /* exception was taken */\
+ mfspr r12,SPRN_SRR2; \
+ stw r1,GPR1(r11); \
+ mfspr r9,SPRN_SRR3; \
+ stw r1,0(r11); \
+ tovirt(r1,r11); \
+ rlwinm r9,r9,0,14,12; /* clear MSR_WE (necessary?) */\
+ stw r0,GPR0(r11); \
+ SAVE_4GPRS(3, r11); \
+ SAVE_2GPRS(7, r11)
+
+ /*
+ * State at this point:
+ * r9 saved in stack frame, now saved SRR3 & ~MSR_WE
+ * r10 saved in crit_r10 and in stack frame, trashed
+ * r11 saved in crit_r11 and in stack frame,
+ * now phys stack/exception frame pointer
+ * r12 saved in stack frame, now saved SRR2
+ * CR saved in stack frame, CR0.EQ = !SRR3.PR
+ * LR, DEAR, ESR in stack frame
+ * r1 saved in stack frame, now virt stack/excframe pointer
+ * r0, r3-r8 saved in stack frame
+ */
+
+/*
+ * Exception vectors.
+ */
+#define START_EXCEPTION(n, label) \
+ . = n; \
+label:
+
+#define EXCEPTION(n, label, hdlr, xfer) \
+ START_EXCEPTION(n, label); \
+ NORMAL_EXCEPTION_PROLOG; \
+ addi r3,r1,STACK_FRAME_OVERHEAD; \
+ xfer(n, hdlr)
+
+#define CRITICAL_EXCEPTION(n, label, hdlr) \
+ START_EXCEPTION(n, label); \
+ CRITICAL_EXCEPTION_PROLOG; \
+ addi r3,r1,STACK_FRAME_OVERHEAD; \
+ EXC_XFER_TEMPLATE(hdlr, n+2, (MSR_KERNEL & ~(MSR_ME|MSR_DE|MSR_CE)), \
+ NOCOPY, crit_transfer_to_handler, \
+ ret_from_crit_exc)
+
+#define EXC_XFER_TEMPLATE(hdlr, trap, msr, copyee, tfer, ret) \
+ li r10,trap; \
+ stw r10,TRAP(r11); \
+ lis r10,msr@h; \
+ ori r10,r10,msr@l; \
+ copyee(r10, r9); \
+ bl tfer; \
+ .long hdlr; \
+ .long ret
+
+#define COPY_EE(d, s) rlwimi d,s,0,16,16
+#define NOCOPY(d, s)
+
+#define EXC_XFER_STD(n, hdlr) \
+ EXC_XFER_TEMPLATE(hdlr, n, MSR_KERNEL, NOCOPY, transfer_to_handler_full, \
+ ret_from_except_full)
+
+#define EXC_XFER_LITE(n, hdlr) \
+ EXC_XFER_TEMPLATE(hdlr, n+1, MSR_KERNEL, NOCOPY, transfer_to_handler, \
+ ret_from_except)
+
+#define EXC_XFER_EE(n, hdlr) \
+ EXC_XFER_TEMPLATE(hdlr, n, MSR_KERNEL, COPY_EE, transfer_to_handler_full, \
+ ret_from_except_full)
+
+#define EXC_XFER_EE_LITE(n, hdlr) \
+ EXC_XFER_TEMPLATE(hdlr, n+1, MSR_KERNEL, COPY_EE, transfer_to_handler, \
+ ret_from_except)
+
+
+/*
+ * 0x0100 - Critical Interrupt Exception
+ */
+ CRITICAL_EXCEPTION(0x0100, CriticalInterrupt, UnknownException)
+
+/*
+ * 0x0200 - Machine Check Exception
+ */
+ CRITICAL_EXCEPTION(0x0200, MachineCheck, MachineCheckException)
+
+/*
+ * 0x0300 - Data Storage Exception
+ * This happens for just a few reasons. U0 set (but we don't do that),
+ * or zone protection fault (user violation, write to protected page).
+ * If this is just an update of modified status, we do that quickly
+ * and exit. Otherwise, we call heavywight functions to do the work.
+ */
+ START_EXCEPTION(0x0300, DataStorage)
+ mtspr SPRN_SPRG0, r10 /* Save some working registers */
+ mtspr SPRN_SPRG1, r11
+#ifdef CONFIG_403GCX
+ stw r12, 0(r0)
+ stw r9, 4(r0)
+ mfcr r11
+ mfspr r12, SPRN_PID
+ stw r11, 8(r0)
+ stw r12, 12(r0)
+#else
+ mtspr SPRN_SPRG4, r12
+ mtspr SPRN_SPRG5, r9
+ mfcr r11
+ mfspr r12, SPRN_PID
+ mtspr SPRN_SPRG7, r11
+ mtspr SPRN_SPRG6, r12
+#endif
+
+ /* First, check if it was a zone fault (which means a user
+ * tried to access a kernel or read-protected page - always
+ * a SEGV). All other faults here must be stores, so no
+ * need to check ESR_DST as well. */
+ mfspr r10, SPRN_ESR
+ andis. r10, r10, ESR_DIZ@h
+ bne 2f
+
+ mfspr r10, SPRN_DEAR /* Get faulting address */
+
+ /* If we are faulting a kernel address, we have to use the
+ * kernel page tables.
+ */
+ andis. r11, r10, 0x8000
+ beq 3f
+ lis r11, swapper_pg_dir@h
+ ori r11, r11, swapper_pg_dir@l
+ li r9, 0
+ mtspr SPRN_PID, r9 /* TLB will have 0 TID */
+ b 4f
+
+ /* Get the PGD for the current thread.
+ */
+3:
+ mfspr r11,SPRN_SPRG3
+ lwz r11,PGDIR(r11)
+4:
+ tophys(r11, r11)
+ rlwimi r11, r10, 12, 20, 29 /* Create L1 (pgdir/pmd) address */
+ lwz r11, 0(r11) /* Get L1 entry */
+ rlwinm. r12, r11, 0, 0, 19 /* Extract L2 (pte) base address */
+ beq 2f /* Bail if no table */
+
+ rlwimi r12, r10, 22, 20, 29 /* Compute PTE address */
+ lwz r11, 0(r12) /* Get Linux PTE */
+
+ andi. r9, r11, _PAGE_RW /* Is it writeable? */
+ beq 2f /* Bail if not */
+
+ /* Update 'changed'.
+ */
+ ori r11, r11, _PAGE_DIRTY|_PAGE_ACCESSED|_PAGE_HWWRITE
+ stw r11, 0(r12) /* Update Linux page table */
+
+ /* Most of the Linux PTE is ready to load into the TLB LO.
+ * We set ZSEL, where only the LS-bit determines user access.
+ * We set execute, because we don't have the granularity to
+ * properly set this at the page level (Linux problem).
+ * If shared is set, we cause a zero PID->TID load.
+ * Many of these bits are software only. Bits we don't set
+ * here we (properly should) assume have the appropriate value.
+ */
+ li r12, 0x0ce2
+ andc r11, r11, r12 /* Make sure 20, 21 are zero */
+
+ /* find the TLB index that caused the fault. It has to be here.
+ */
+ tlbsx r9, 0, r10
+
+ tlbwe r11, r9, TLB_DATA /* Load TLB LO */
+
+ /* Done...restore registers and get out of here.
+ */
+#ifdef CONFIG_403GCX
+ lwz r12, 12(r0)
+ lwz r11, 8(r0)
+ mtspr SPRN_PID, r12
+ mtcr r11
+ lwz r9, 4(r0)
+ lwz r12, 0(r0)
+#else
+ mfspr r12, SPRN_SPRG6
+ mfspr r11, SPRN_SPRG7
+ mtspr SPRN_PID, r12
+ mtcr r11
+ mfspr r9, SPRN_SPRG5
+ mfspr r12, SPRN_SPRG4
+#endif
+ mfspr r11, SPRN_SPRG1
+ mfspr r10, SPRN_SPRG0
+ PPC405_ERR77_SYNC
+ rfi /* Should sync shadow TLBs */
+ b . /* prevent prefetch past rfi */
+
+2:
+ /* The bailout. Restore registers to pre-exception conditions
+ * and call the heavyweights to help us out.
+ */
+#ifdef CONFIG_403GCX
+ lwz r12, 12(r0)
+ lwz r11, 8(r0)
+ mtspr SPRN_PID, r12
+ mtcr r11
+ lwz r9, 4(r0)
+ lwz r12, 0(r0)
+#else
+ mfspr r12, SPRN_SPRG6
+ mfspr r11, SPRN_SPRG7
+ mtspr SPRN_PID, r12
+ mtcr r11
+ mfspr r9, SPRN_SPRG5
+ mfspr r12, SPRN_SPRG4
+#endif
+ mfspr r11, SPRN_SPRG1
+ mfspr r10, SPRN_SPRG0
+ b DataAccess
+
+/*
+ * 0x0400 - Instruction Storage Exception
+ * This is caused by a fetch from non-execute or guarded pages.
+ */
+ START_EXCEPTION(0x0400, InstructionAccess)
+ NORMAL_EXCEPTION_PROLOG
+ mr r4,r12 /* Pass SRR0 as arg2 */
+ li r5,0 /* Pass zero as arg3 */
+ EXC_XFER_EE_LITE(0x400, handle_page_fault)
+
+/* 0x0500 - External Interrupt Exception */
+ EXCEPTION(0x0500, HardwareInterrupt, do_IRQ, EXC_XFER_LITE)
+
+/* 0x0600 - Alignment Exception */
+ START_EXCEPTION(0x0600, Alignment)
+ NORMAL_EXCEPTION_PROLOG
+ mfspr r4,SPRN_DEAR /* Grab the DEAR and save it */
+ stw r4,_DEAR(r11)
+ addi r3,r1,STACK_FRAME_OVERHEAD
+ EXC_XFER_EE(0x600, AlignmentException)
+
+/* 0x0700 - Program Exception */
+ START_EXCEPTION(0x0700, ProgramCheck)
+ NORMAL_EXCEPTION_PROLOG
+ mfspr r4,SPRN_ESR /* Grab the ESR and save it */
+ stw r4,_ESR(r11)
+ addi r3,r1,STACK_FRAME_OVERHEAD
+ EXC_XFER_STD(0x700, ProgramCheckException)
+
+ EXCEPTION(0x0800, Trap_08, UnknownException, EXC_XFER_EE)
+ EXCEPTION(0x0900, Trap_09, UnknownException, EXC_XFER_EE)
+ EXCEPTION(0x0A00, Trap_0A, UnknownException, EXC_XFER_EE)
+ EXCEPTION(0x0B00, Trap_0B, UnknownException, EXC_XFER_EE)
+
+/* 0x0C00 - System Call Exception */
+ START_EXCEPTION(0x0C00, SystemCall)
+ NORMAL_EXCEPTION_PROLOG
+ EXC_XFER_EE_LITE(0xc00, DoSyscall)
+
+ EXCEPTION(0x0D00, Trap_0D, UnknownException, EXC_XFER_EE)
+ EXCEPTION(0x0E00, Trap_0E, UnknownException, EXC_XFER_EE)
+ EXCEPTION(0x0F00, Trap_0F, UnknownException, EXC_XFER_EE)
+
+/* 0x1000 - Programmable Interval Timer (PIT) Exception */
+ START_EXCEPTION(0x1000, Decrementer)
+ NORMAL_EXCEPTION_PROLOG
+ lis r0,TSR_PIS@h
+ mtspr SPRN_TSR,r0 /* Clear the PIT exception */
+ addi r3,r1,STACK_FRAME_OVERHEAD
+ EXC_XFER_LITE(0x1000, timer_interrupt)
+
+#if 0
+/* NOTE:
+ * FIT and WDT handlers are not implemented yet.
+ */
+
+/* 0x1010 - Fixed Interval Timer (FIT) Exception
+*/
+ STND_EXCEPTION(0x1010, FITException, UnknownException)
+
+/* 0x1020 - Watchdog Timer (WDT) Exception
+*/
+
+ CRITICAL_EXCEPTION(0x1020, WDTException, UnknownException)
+#endif
+
+/* 0x1100 - Data TLB Miss Exception
+ * As the name implies, translation is not in the MMU, so search the
+ * page tables and fix it. The only purpose of this function is to
+ * load TLB entries from the page table if they exist.
+ */
+ START_EXCEPTION(0x1100, DTLBMiss)
+ mtspr SPRN_SPRG0, r10 /* Save some working registers */
+ mtspr SPRN_SPRG1, r11
+#ifdef CONFIG_403GCX
+ stw r12, 0(r0)
+ stw r9, 4(r0)
+ mfcr r11
+ mfspr r12, SPRN_PID
+ stw r11, 8(r0)
+ stw r12, 12(r0)
+#else
+ mtspr SPRN_SPRG4, r12
+ mtspr SPRN_SPRG5, r9
+ mfcr r11
+ mfspr r12, SPRN_PID
+ mtspr SPRN_SPRG7, r11
+ mtspr SPRN_SPRG6, r12
+#endif
+ mfspr r10, SPRN_DEAR /* Get faulting address */
+
+ /* If we are faulting a kernel address, we have to use the
+ * kernel page tables.
+ */
+ andis. r11, r10, 0x8000
+ beq 3f
+ lis r11, swapper_pg_dir@h
+ ori r11, r11, swapper_pg_dir@l
+ li r9, 0
+ mtspr SPRN_PID, r9 /* TLB will have 0 TID */
+ b 4f
+
+ /* Get the PGD for the current thread.
+ */
+3:
+ mfspr r11,SPRN_SPRG3
+ lwz r11,PGDIR(r11)
+4:
+ tophys(r11, r11)
+ rlwimi r11, r10, 12, 20, 29 /* Create L1 (pgdir/pmd) address */
+ lwz r12, 0(r11) /* Get L1 entry */
+ andi. r9, r12, _PMD_PRESENT /* Check if it points to a PTE page */
+ beq 2f /* Bail if no table */
+
+ rlwimi r12, r10, 22, 20, 29 /* Compute PTE address */
+ lwz r11, 0(r12) /* Get Linux PTE */
+ andi. r9, r11, _PAGE_PRESENT
+ beq 5f
+
+ ori r11, r11, _PAGE_ACCESSED
+ stw r11, 0(r12)
+
+ /* Create TLB tag. This is the faulting address plus a static
+ * set of bits. These are size, valid, E, U0.
+ */
+ li r12, 0x00c0
+ rlwimi r10, r12, 0, 20, 31
+
+ b finish_tlb_load
+
+2: /* Check for possible large-page pmd entry */
+ rlwinm. r9, r12, 2, 22, 24
+ beq 5f
+
+ /* Create TLB tag. This is the faulting address, plus a static
+ * set of bits (valid, E, U0) plus the size from the PMD.
+ */
+ ori r9, r9, 0x40
+ rlwimi r10, r9, 0, 20, 31
+ mr r11, r12
+
+ b finish_tlb_load
+
+5:
+ /* The bailout. Restore registers to pre-exception conditions
+ * and call the heavyweights to help us out.
+ */
+#ifdef CONFIG_403GCX
+ lwz r12, 12(r0)
+ lwz r11, 8(r0)
+ mtspr SPRN_PID, r12
+ mtcr r11
+ lwz r9, 4(r0)
+ lwz r12, 0(r0)
+#else
+ mfspr r12, SPRN_SPRG6
+ mfspr r11, SPRN_SPRG7
+ mtspr SPRN_PID, r12
+ mtcr r11
+ mfspr r9, SPRN_SPRG5
+ mfspr r12, SPRN_SPRG4
+#endif
+ mfspr r11, SPRN_SPRG1
+ mfspr r10, SPRN_SPRG0
+ b DataAccess
+
+/* 0x1200 - Instruction TLB Miss Exception
+ * Nearly the same as above, except we get our information from different
+ * registers and bailout to a different point.
+ */
+ START_EXCEPTION(0x1200, ITLBMiss)
+ mtspr SPRN_SPRG0, r10 /* Save some working registers */
+ mtspr SPRN_SPRG1, r11
+#ifdef CONFIG_403GCX
+ stw r12, 0(r0)
+ stw r9, 4(r0)
+ mfcr r11
+ mfspr r12, SPRN_PID
+ stw r11, 8(r0)
+ stw r12, 12(r0)
+#else
+ mtspr SPRN_SPRG4, r12
+ mtspr SPRN_SPRG5, r9
+ mfcr r11
+ mfspr r12, SPRN_PID
+ mtspr SPRN_SPRG7, r11
+ mtspr SPRN_SPRG6, r12
+#endif
+ mfspr r10, SPRN_SRR0 /* Get faulting address */
+
+ /* If we are faulting a kernel address, we have to use the
+ * kernel page tables.
+ */
+ andis. r11, r10, 0x8000
+ beq 3f
+ lis r11, swapper_pg_dir@h
+ ori r11, r11, swapper_pg_dir@l
+ li r9, 0
+ mtspr SPRN_PID, r9 /* TLB will have 0 TID */
+ b 4f
+
+ /* Get the PGD for the current thread.
+ */
+3:
+ mfspr r11,SPRN_SPRG3
+ lwz r11,PGDIR(r11)
+4:
+ tophys(r11, r11)
+ rlwimi r11, r10, 12, 20, 29 /* Create L1 (pgdir/pmd) address */
+ lwz r12, 0(r11) /* Get L1 entry */
+ andi. r9, r12, _PMD_PRESENT /* Check if it points to a PTE page */
+ beq 2f /* Bail if no table */
+
+ rlwimi r12, r10, 22, 20, 29 /* Compute PTE address */
+ lwz r11, 0(r12) /* Get Linux PTE */
+ andi. r9, r11, _PAGE_PRESENT
+ beq 5f
+
+ ori r11, r11, _PAGE_ACCESSED
+ stw r11, 0(r12)
+
+ /* Create TLB tag. This is the faulting address plus a static
+ * set of bits. These are size, valid, E, U0.
+ */
+ li r12, 0x00c0
+ rlwimi r10, r12, 0, 20, 31
+
+ b finish_tlb_load
+
+2: /* Check for possible large-page pmd entry */
+ rlwinm. r9, r12, 2, 22, 24
+ beq 5f
+
+ /* Create TLB tag. This is the faulting address, plus a static
+ * set of bits (valid, E, U0) plus the size from the PMD.
+ */
+ ori r9, r9, 0x40
+ rlwimi r10, r9, 0, 20, 31
+ mr r11, r12
+
+ b finish_tlb_load
+
+5:
+ /* The bailout. Restore registers to pre-exception conditions
+ * and call the heavyweights to help us out.
+ */
+#ifdef CONFIG_403GCX
+ lwz r12, 12(r0)
+ lwz r11, 8(r0)
+ mtspr SPRN_PID, r12
+ mtcr r11
+ lwz r9, 4(r0)
+ lwz r12, 0(r0)
+#else
+ mfspr r12, SPRN_SPRG6
+ mfspr r11, SPRN_SPRG7
+ mtspr SPRN_PID, r12
+ mtcr r11
+ mfspr r9, SPRN_SPRG5
+ mfspr r12, SPRN_SPRG4
+#endif
+ mfspr r11, SPRN_SPRG1
+ mfspr r10, SPRN_SPRG0
+ b InstructionAccess
+
+ EXCEPTION(0x1300, Trap_13, UnknownException, EXC_XFER_EE)
+ EXCEPTION(0x1400, Trap_14, UnknownException, EXC_XFER_EE)
+ EXCEPTION(0x1500, Trap_15, UnknownException, EXC_XFER_EE)
+ EXCEPTION(0x1600, Trap_16, UnknownException, EXC_XFER_EE)
+#ifdef CONFIG_IBM405_ERR51
+ /* 405GP errata 51 */
+ START_EXCEPTION(0x1700, Trap_17)
+ b DTLBMiss
+#else
+ EXCEPTION(0x1700, Trap_17, UnknownException, EXC_XFER_EE)
+#endif
+ EXCEPTION(0x1800, Trap_18, UnknownException, EXC_XFER_EE)
+ EXCEPTION(0x1900, Trap_19, UnknownException, EXC_XFER_EE)
+ EXCEPTION(0x1A00, Trap_1A, UnknownException, EXC_XFER_EE)
+ EXCEPTION(0x1B00, Trap_1B, UnknownException, EXC_XFER_EE)
+ EXCEPTION(0x1C00, Trap_1C, UnknownException, EXC_XFER_EE)
+ EXCEPTION(0x1D00, Trap_1D, UnknownException, EXC_XFER_EE)
+ EXCEPTION(0x1E00, Trap_1E, UnknownException, EXC_XFER_EE)
+ EXCEPTION(0x1F00, Trap_1F, UnknownException, EXC_XFER_EE)
+
+/* Check for a single step debug exception while in an exception
+ * handler before state has been saved. This is to catch the case
+ * where an instruction that we are trying to single step causes
+ * an exception (eg ITLB/DTLB miss) and thus the first instruction of
+ * the exception handler generates a single step debug exception.
+ *
+ * If we get a debug trap on the first instruction of an exception handler,
+ * we reset the MSR_DE in the _exception handler's_ MSR (the debug trap is
+ * a critical exception, so we are using SPRN_CSRR1 to manipulate the MSR).
+ * The exception handler was handling a non-critical interrupt, so it will
+ * save (and later restore) the MSR via SPRN_SRR1, which will still have
+ * the MSR_DE bit set.
+ */
+ /* 0x2000 - Debug Exception */
+ START_EXCEPTION(0x2000, DebugTrap)
+ CRITICAL_EXCEPTION_PROLOG
+
+ /*
+ * If this is a single step or branch-taken exception in an
+ * exception entry sequence, it was probably meant to apply to
+ * the code where the exception occurred (since exception entry
+ * doesn't turn off DE automatically). We simulate the effect
+ * of turning off DE on entry to an exception handler by turning
+ * off DE in the SRR3 value and clearing the debug status.
+ */
+ mfspr r10,SPRN_DBSR /* check single-step/branch taken */
+ andis. r10,r10,DBSR_IC@h
+ beq+ 2f
+
+ andi. r10,r9,MSR_IR|MSR_PR /* check supervisor + MMU off */
+ beq 1f /* branch and fix it up */
+
+ mfspr r10,SPRN_SRR2 /* Faulting instruction address */
+ cmplwi r10,0x2100
+ bgt+ 2f /* address above exception vectors */
+
+ /* here it looks like we got an inappropriate debug exception. */
+1: rlwinm r9,r9,0,~MSR_DE /* clear DE in the SRR3 value */
+ lis r10,DBSR_IC@h /* clear the IC event */
+ mtspr SPRN_DBSR,r10
+ /* restore state and get out */
+ lwz r10,_CCR(r11)
+ lwz r0,GPR0(r11)
+ lwz r1,GPR1(r11)
+ mtcrf 0x80,r10
+ mtspr SPRN_SRR2,r12
+ mtspr SPRN_SRR3,r9
+ lwz r9,GPR9(r11)
+ lwz r12,GPR12(r11)
+ lwz r10,crit_r10@l(0)
+ lwz r11,crit_r11@l(0)
+ PPC405_ERR77_SYNC
+ rfci
+ b .
+
+ /* continue normal handling for a critical exception... */
+2: mfspr r4,SPRN_DBSR
+ addi r3,r1,STACK_FRAME_OVERHEAD
+ EXC_XFER_TEMPLATE(DebugException, 0x2002, \
+ (MSR_KERNEL & ~(MSR_ME|MSR_DE|MSR_CE)), \
+ NOCOPY, crit_transfer_to_handler, ret_from_crit_exc)
+
+/*
+ * The other Data TLB exceptions bail out to this point
+ * if they can't resolve the lightweight TLB fault.
+ */
+DataAccess:
+ NORMAL_EXCEPTION_PROLOG
+ mfspr r5,SPRN_ESR /* Grab the ESR, save it, pass arg3 */
+ stw r5,_ESR(r11)
+ mfspr r4,SPRN_DEAR /* Grab the DEAR, save it, pass arg2 */
+ EXC_XFER_EE_LITE(0x300, handle_page_fault)
+
+/* Other PowerPC processors, namely those derived from the 6xx-series
+ * have vectors from 0x2100 through 0x2F00 defined, but marked as reserved.
+ * However, for the 4xx-series processors these are neither defined nor
+ * reserved.
+ */
+
+ /* Damn, I came up one instruction too many to fit into the
+ * exception space :-). Both the instruction and data TLB
+ * miss get to this point to load the TLB.
+ * r10 - TLB_TAG value
+ * r11 - Linux PTE
+ * r12, r9 - avilable to use
+ * PID - loaded with proper value when we get here
+ * Upon exit, we reload everything and RFI.
+ * Actually, it will fit now, but oh well.....a common place
+ * to load the TLB.
+ */
+tlb_4xx_index:
+ .long 0
+finish_tlb_load:
+ /* load the next available TLB index.
+ */
+ lwz r9, tlb_4xx_index@l(0)
+ addi r9, r9, 1
+ andi. r9, r9, (PPC4XX_TLB_SIZE-1)
+ stw r9, tlb_4xx_index@l(0)
+
+6:
+ /*
+ * Clear out the software-only bits in the PTE to generate the
+ * TLB_DATA value. These are the bottom 2 bits of the RPM, the
+ * top 3 bits of the zone field, and M.
+ */
+ li r12, 0x0ce2
+ andc r11, r11, r12
+
+ tlbwe r11, r9, TLB_DATA /* Load TLB LO */
+ tlbwe r10, r9, TLB_TAG /* Load TLB HI */
+
+ /* Done...restore registers and get out of here.
+ */
+#ifdef CONFIG_403GCX
+ lwz r12, 12(r0)
+ lwz r11, 8(r0)
+ mtspr SPRN_PID, r12
+ mtcr r11
+ lwz r9, 4(r0)
+ lwz r12, 0(r0)
+#else
+ mfspr r12, SPRN_SPRG6
+ mfspr r11, SPRN_SPRG7
+ mtspr SPRN_PID, r12
+ mtcr r11
+ mfspr r9, SPRN_SPRG5
+ mfspr r12, SPRN_SPRG4
+#endif
+ mfspr r11, SPRN_SPRG1
+ mfspr r10, SPRN_SPRG0
+ PPC405_ERR77_SYNC
+ rfi /* Should sync shadow TLBs */
+ b . /* prevent prefetch past rfi */
+
+/* extern void giveup_fpu(struct task_struct *prev)
+ *
+ * The PowerPC 4xx family of processors do not have an FPU, so this just
+ * returns.
+ */
+_GLOBAL(giveup_fpu)
+ blr
+
+/* This is where the main kernel code starts.
+ */
+start_here:
+
+ /* ptr to current */
+ lis r2,init_task@h
+ ori r2,r2,init_task@l
+
+ /* ptr to phys current thread */
+ tophys(r4,r2)
+ addi r4,r4,THREAD /* init task's THREAD */
+ mtspr SPRN_SPRG3,r4
+
+ /* stack */
+ lis r1,init_thread_union@ha
+ addi r1,r1,init_thread_union@l
+ li r0,0
+ stwu r0,THREAD_SIZE-STACK_FRAME_OVERHEAD(r1)
+
+ bl early_init /* We have to do this with MMU on */
+
+/*
+ * Decide what sort of machine this is and initialize the MMU.
+ */
+ mr r3,r31
+ mr r4,r30
+ mr r5,r29
+ mr r6,r28
+ mr r7,r27
+ bl machine_init
+ bl MMU_init
+
+/* Go back to running unmapped so we can load up new values
+ * and change to using our exception vectors.
+ * On the 4xx, all we have to do is invalidate the TLB to clear
+ * the old 16M byte TLB mappings.
+ */
+ lis r4,2f@h
+ ori r4,r4,2f@l
+ tophys(r4,r4)
+ lis r3,(MSR_KERNEL & ~(MSR_IR|MSR_DR))@h
+ ori r3,r3,(MSR_KERNEL & ~(MSR_IR|MSR_DR))@l
+ mtspr SPRN_SRR0,r4
+ mtspr SPRN_SRR1,r3
+ rfi
+ b . /* prevent prefetch past rfi */
+
+/* Load up the kernel context */
+2:
+ sync /* Flush to memory before changing TLB */
+ tlbia
+ isync /* Flush shadow TLBs */
+
+ /* set up the PTE pointers for the Abatron bdiGDB.
+ */
+ lis r6, swapper_pg_dir@h
+ ori r6, r6, swapper_pg_dir@l
+ lis r5, abatron_pteptrs@h
+ ori r5, r5, abatron_pteptrs@l
+ stw r5, 0xf0(r0) /* Must match your Abatron config file */
+ tophys(r5,r5)
+ stw r6, 0(r5)
+
+/* Now turn on the MMU for real! */
+ lis r4,MSR_KERNEL@h
+ ori r4,r4,MSR_KERNEL@l
+ lis r3,start_kernel@h
+ ori r3,r3,start_kernel@l
+ mtspr SPRN_SRR0,r3
+ mtspr SPRN_SRR1,r4
+ rfi /* enable MMU and jump to start_kernel */
+ b . /* prevent prefetch past rfi */
+
+/* Set up the initial MMU state so we can do the first level of
+ * kernel initialization. This maps the first 16 MBytes of memory 1:1
+ * virtual to physical and more importantly sets the cache mode.
+ */
+initial_mmu:
+ tlbia /* Invalidate all TLB entries */
+ isync
+
+ /* We should still be executing code at physical address 0x0000xxxx
+ * at this point. However, start_here is at virtual address
+ * 0xC000xxxx. So, set up a TLB mapping to cover this once
+ * translation is enabled.
+ */
+
+ lis r3,KERNELBASE@h /* Load the kernel virtual address */
+ ori r3,r3,KERNELBASE@l
+ tophys(r4,r3) /* Load the kernel physical address */
+
+ iccci r0,r3 /* Invalidate the i-cache before use */
+
+ /* Load the kernel PID.
+ */
+ li r0,0
+ mtspr SPRN_PID,r0
+ sync
+
+ /* Configure and load two entries into TLB slots 62 and 63.
+ * In case we are pinning TLBs, these are reserved in by the
+ * other TLB functions. If not reserving, then it doesn't
+ * matter where they are loaded.
+ */
+ clrrwi r4,r4,10 /* Mask off the real page number */
+ ori r4,r4,(TLB_WR | TLB_EX) /* Set the write and execute bits */
+
+ clrrwi r3,r3,10 /* Mask off the effective page number */
+ ori r3,r3,(TLB_VALID | TLB_PAGESZ(PAGESZ_16M))
+
+ li r0,63 /* TLB slot 63 */
+
+ tlbwe r4,r0,TLB_DATA /* Load the data portion of the entry */
+ tlbwe r3,r0,TLB_TAG /* Load the tag portion of the entry */
+
+#if defined(CONFIG_SERIAL_TEXT_DEBUG) && defined(SERIAL_DEBUG_IO_BASE)
+
+ /* Load a TLB entry for the UART, so that ppc4xx_progress() can use
+ * the UARTs nice and early. We use a 4k real==virtual mapping. */
+
+ lis r3,SERIAL_DEBUG_IO_BASE@h
+ ori r3,r3,SERIAL_DEBUG_IO_BASE@l
+ mr r4,r3
+ clrrwi r4,r4,12
+ ori r4,r4,(TLB_WR|TLB_I|TLB_M|TLB_G)
+
+ clrrwi r3,r3,12
+ ori r3,r3,(TLB_VALID | TLB_PAGESZ(PAGESZ_4K))
+
+ li r0,0 /* TLB slot 0 */
+ tlbwe r4,r0,TLB_DATA
+ tlbwe r3,r0,TLB_TAG
+#endif /* CONFIG_SERIAL_DEBUG_TEXT && SERIAL_DEBUG_IO_BASE */
+
+ isync
+
+ /* Establish the exception vector base
+ */
+ lis r4,KERNELBASE@h /* EVPR only uses the high 16-bits */
+ tophys(r0,r4) /* Use the physical address */
+ mtspr SPRN_EVPR,r0
+
+ blr
+
+_GLOBAL(abort)
+ mfspr r13,SPRN_DBCR0
+ oris r13,r13,DBCR0_RST_SYSTEM@h
+ mtspr SPRN_DBCR0,r13
+
+_GLOBAL(set_context)
+
+#ifdef CONFIG_BDI_SWITCH
+ /* Context switch the PTE pointer for the Abatron BDI2000.
+ * The PGDIR is the second parameter.
+ */
+ lis r5, KERNELBASE@h
+ lwz r5, 0xf0(r5)
+ stw r4, 0x4(r5)
+#endif
+ sync
+ mtspr SPRN_PID,r3
+ isync /* Need an isync to flush shadow */
+ /* TLBs after changing PID */
+ blr
+
+/* We put a few things here that have to be page-aligned. This stuff
+ * goes at the beginning of the data segment, which is page-aligned.
+ */
+ .data
+_GLOBAL(sdata)
+_GLOBAL(empty_zero_page)
+ .space 4096
+_GLOBAL(swapper_pg_dir)
+ .space 4096
+
+
+/* Stack for handling critical exceptions from kernel mode */
+ .section .bss
+ .align 12
+exception_stack_bottom:
+ .space 4096
+critical_stack_top:
+_GLOBAL(exception_stack_top)
+
+/* This space gets a copy of optional info passed to us by the bootstrap
+ * which is used to pass parameters into the kernel like root=/dev/sda1, etc.
+ */
+_GLOBAL(cmd_line)
+ .space 512
+
+/* Room for two PTE pointers, usually the kernel and current user pointers
+ * to their respective root page table.
+ */
+abatron_pteptrs:
+ .space 8
diff --git a/arch/ppc/kernel/head_8xx.S b/arch/ppc/kernel/head_8xx.S
new file mode 100644
index 0000000..5a7a64e
--- /dev/null
+++ b/arch/ppc/kernel/head_8xx.S
@@ -0,0 +1,862 @@
+/*
+ * arch/ppc/kernel/except_8xx.S
+ *
+ * PowerPC version
+ * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
+ * Rewritten by Cort Dougan (cort@cs.nmt.edu) for PReP
+ * Copyright (C) 1996 Cort Dougan <cort@cs.nmt.edu>
+ * Low-level exception handlers and MMU support
+ * rewritten by Paul Mackerras.
+ * Copyright (C) 1996 Paul Mackerras.
+ * MPC8xx modifications by Dan Malek
+ * Copyright (C) 1997 Dan Malek (dmalek@jlc.net).
+ *
+ * This file contains low-level support and setup for PowerPC 8xx
+ * embedded processors, including trap and interrupt dispatch.
+ *
+ * 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.
+ *
+ */
+
+#include <linux/config.h>
+#include <asm/processor.h>
+#include <asm/page.h>
+#include <asm/mmu.h>
+#include <asm/cache.h>
+#include <asm/pgtable.h>
+#include <asm/cputable.h>
+#include <asm/thread_info.h>
+#include <asm/ppc_asm.h>
+#include <asm/offsets.h>
+
+/* Macro to make the code more readable. */
+#ifdef CONFIG_8xx_CPU6
+#define DO_8xx_CPU6(val, reg) \
+ li reg, val; \
+ stw reg, 12(r0); \
+ lwz reg, 12(r0);
+#else
+#define DO_8xx_CPU6(val, reg)
+#endif
+ .text
+ .globl _stext
+_stext:
+ .text
+ .globl _start
+_start:
+
+/* MPC8xx
+ * This port was done on an MBX board with an 860. Right now I only
+ * support an ELF compressed (zImage) boot from EPPC-Bug because the
+ * code there loads up some registers before calling us:
+ * r3: ptr to board info data
+ * r4: initrd_start or if no initrd then 0
+ * r5: initrd_end - unused if r4 is 0
+ * r6: Start of command line string
+ * r7: End of command line string
+ *
+ * I decided to use conditional compilation instead of checking PVR and
+ * adding more processor specific branches around code I don't need.
+ * Since this is an embedded processor, I also appreciate any memory
+ * savings I can get.
+ *
+ * The MPC8xx does not have any BATs, but it supports large page sizes.
+ * We first initialize the MMU to support 8M byte pages, then load one
+ * entry into each of the instruction and data TLBs to map the first
+ * 8M 1:1. I also mapped an additional I/O space 1:1 so we can get to
+ * the "internal" processor registers before MMU_init is called.
+ *
+ * The TLB code currently contains a major hack. Since I use the condition
+ * code register, I have to save and restore it. I am out of registers, so
+ * I just store it in memory location 0 (the TLB handlers are not reentrant).
+ * To avoid making any decisions, I need to use the "segment" valid bit
+ * in the first level table, but that would require many changes to the
+ * Linux page directory/table functions that I don't want to do right now.
+ *
+ * I used to use SPRG2 for a temporary register in the TLB handler, but it
+ * has since been put to other uses. I now use a hack to save a register
+ * and the CCR at memory location 0.....Someday I'll fix this.....
+ * -- Dan
+ */
+ .globl __start
+__start:
+ mr r31,r3 /* save parameters */
+ mr r30,r4
+ mr r29,r5
+ mr r28,r6
+ mr r27,r7
+
+ /* We have to turn on the MMU right away so we get cache modes
+ * set correctly.
+ */
+ bl initial_mmu
+
+/* We now have the lower 8 Meg mapped into TLB entries, and the caches
+ * ready to work.
+ */
+
+turn_on_mmu:
+ mfmsr r0
+ ori r0,r0,MSR_DR|MSR_IR
+ mtspr SPRN_SRR1,r0
+ lis r0,start_here@h
+ ori r0,r0,start_here@l
+ mtspr SPRN_SRR0,r0
+ SYNC
+ rfi /* enables MMU */
+
+/*
+ * Exception entry code. This code runs with address translation
+ * turned off, i.e. using physical addresses.
+ * We assume sprg3 has the physical address of the current
+ * task's thread_struct.
+ */
+#define EXCEPTION_PROLOG \
+ mtspr SPRN_SPRG0,r10; \
+ mtspr SPRN_SPRG1,r11; \
+ mfcr r10; \
+ EXCEPTION_PROLOG_1; \
+ EXCEPTION_PROLOG_2
+
+#define EXCEPTION_PROLOG_1 \
+ mfspr r11,SPRN_SRR1; /* check whether user or kernel */ \
+ andi. r11,r11,MSR_PR; \
+ tophys(r11,r1); /* use tophys(r1) if kernel */ \
+ beq 1f; \
+ mfspr r11,SPRN_SPRG3; \
+ lwz r11,THREAD_INFO-THREAD(r11); \
+ addi r11,r11,THREAD_SIZE; \
+ tophys(r11,r11); \
+1: subi r11,r11,INT_FRAME_SIZE /* alloc exc. frame */
+
+
+#define EXCEPTION_PROLOG_2 \
+ CLR_TOP32(r11); \
+ stw r10,_CCR(r11); /* save registers */ \
+ stw r12,GPR12(r11); \
+ stw r9,GPR9(r11); \
+ mfspr r10,SPRN_SPRG0; \
+ stw r10,GPR10(r11); \
+ mfspr r12,SPRN_SPRG1; \
+ stw r12,GPR11(r11); \
+ mflr r10; \
+ stw r10,_LINK(r11); \
+ mfspr r12,SPRN_SRR0; \
+ mfspr r9,SPRN_SRR1; \
+ stw r1,GPR1(r11); \
+ stw r1,0(r11); \
+ tovirt(r1,r11); /* set new kernel sp */ \
+ li r10,MSR_KERNEL & ~(MSR_IR|MSR_DR); /* can take exceptions */ \
+ MTMSRD(r10); /* (except for mach check in rtas) */ \
+ stw r0,GPR0(r11); \
+ SAVE_4GPRS(3, r11); \
+ SAVE_2GPRS(7, r11)
+
+/*
+ * Note: code which follows this uses cr0.eq (set if from kernel),
+ * r11, r12 (SRR0), and r9 (SRR1).
+ *
+ * Note2: once we have set r1 we are in a position to take exceptions
+ * again, and we could thus set MSR:RI at that point.
+ */
+
+/*
+ * Exception vectors.
+ */
+#define EXCEPTION(n, label, hdlr, xfer) \
+ . = n; \
+label: \
+ EXCEPTION_PROLOG; \
+ addi r3,r1,STACK_FRAME_OVERHEAD; \
+ xfer(n, hdlr)
+
+#define EXC_XFER_TEMPLATE(n, hdlr, trap, copyee, tfer, ret) \
+ li r10,trap; \
+ stw r10,TRAP(r11); \
+ li r10,MSR_KERNEL; \
+ copyee(r10, r9); \
+ bl tfer; \
+i##n: \
+ .long hdlr; \
+ .long ret
+
+#define COPY_EE(d, s) rlwimi d,s,0,16,16
+#define NOCOPY(d, s)
+
+#define EXC_XFER_STD(n, hdlr) \
+ EXC_XFER_TEMPLATE(n, hdlr, n, NOCOPY, transfer_to_handler_full, \
+ ret_from_except_full)
+
+#define EXC_XFER_LITE(n, hdlr) \
+ EXC_XFER_TEMPLATE(n, hdlr, n+1, NOCOPY, transfer_to_handler, \
+ ret_from_except)
+
+#define EXC_XFER_EE(n, hdlr) \
+ EXC_XFER_TEMPLATE(n, hdlr, n, COPY_EE, transfer_to_handler_full, \
+ ret_from_except_full)
+
+#define EXC_XFER_EE_LITE(n, hdlr) \
+ EXC_XFER_TEMPLATE(n, hdlr, n+1, COPY_EE, transfer_to_handler, \
+ ret_from_except)
+
+/* System reset */
+ EXCEPTION(0x100, Reset, UnknownException, EXC_XFER_STD)
+
+/* Machine check */
+ . = 0x200
+MachineCheck:
+ EXCEPTION_PROLOG
+ mfspr r4,SPRN_DAR
+ stw r4,_DAR(r11)
+ mfspr r5,SPRN_DSISR
+ stw r5,_DSISR(r11)
+ addi r3,r1,STACK_FRAME_OVERHEAD
+ EXC_XFER_STD(0x200, MachineCheckException)
+
+/* Data access exception.
+ * This is "never generated" by the MPC8xx. We jump to it for other
+ * translation errors.
+ */
+ . = 0x300
+DataAccess:
+ EXCEPTION_PROLOG
+ mfspr r10,SPRN_DSISR
+ stw r10,_DSISR(r11)
+ mr r5,r10
+ mfspr r4,SPRN_DAR
+ EXC_XFER_EE_LITE(0x300, handle_page_fault)
+
+/* Instruction access exception.
+ * This is "never generated" by the MPC8xx. We jump to it for other
+ * translation errors.
+ */
+ . = 0x400
+InstructionAccess:
+ EXCEPTION_PROLOG
+ mr r4,r12
+ mr r5,r9
+ EXC_XFER_EE_LITE(0x400, handle_page_fault)
+
+/* External interrupt */
+ EXCEPTION(0x500, HardwareInterrupt, do_IRQ, EXC_XFER_LITE)
+
+/* Alignment exception */
+ . = 0x600
+Alignment:
+ EXCEPTION_PROLOG
+ mfspr r4,SPRN_DAR
+ stw r4,_DAR(r11)
+ mfspr r5,SPRN_DSISR
+ stw r5,_DSISR(r11)
+ addi r3,r1,STACK_FRAME_OVERHEAD
+ EXC_XFER_EE(0x600, AlignmentException)
+
+/* Program check exception */
+ EXCEPTION(0x700, ProgramCheck, ProgramCheckException, EXC_XFER_STD)
+
+/* No FPU on MPC8xx. This exception is not supposed to happen.
+*/
+ EXCEPTION(0x800, FPUnavailable, UnknownException, EXC_XFER_STD)
+
+/* Decrementer */
+ EXCEPTION(0x900, Decrementer, timer_interrupt, EXC_XFER_LITE)
+
+ EXCEPTION(0xa00, Trap_0a, UnknownException, EXC_XFER_EE)
+ EXCEPTION(0xb00, Trap_0b, UnknownException, EXC_XFER_EE)
+
+/* System call */
+ . = 0xc00
+SystemCall:
+ EXCEPTION_PROLOG
+ EXC_XFER_EE_LITE(0xc00, DoSyscall)
+
+/* Single step - not used on 601 */
+ EXCEPTION(0xd00, SingleStep, SingleStepException, EXC_XFER_STD)
+ EXCEPTION(0xe00, Trap_0e, UnknownException, EXC_XFER_EE)
+ EXCEPTION(0xf00, Trap_0f, UnknownException, EXC_XFER_EE)
+
+/* On the MPC8xx, this is a software emulation interrupt. It occurs
+ * for all unimplemented and illegal instructions.
+ */
+ EXCEPTION(0x1000, SoftEmu, SoftwareEmulation, EXC_XFER_STD)
+
+ . = 0x1100
+/*
+ * For the MPC8xx, this is a software tablewalk to load the instruction
+ * TLB. It is modelled after the example in the Motorola manual. The task
+ * switch loads the M_TWB register with the pointer to the first level table.
+ * If we discover there is no second level table (the value is zero), the
+ * plan was to load that into the TLB, which causes another fault into the
+ * TLB Error interrupt where we can handle such problems. However, that did
+ * not work, so if we discover there is no second level table, we restore
+ * registers and branch to the error exception. We have to use the MD_xxx
+ * registers for the tablewalk because the equivalent MI_xxx registers
+ * only perform the attribute functions.
+ */
+InstructionTLBMiss:
+#ifdef CONFIG_8xx_CPU6
+ stw r3, 8(r0)
+#endif
+ DO_8xx_CPU6(0x3f80, r3)
+ mtspr SPRN_M_TW, r10 /* Save a couple of working registers */
+ mfcr r10
+ stw r10, 0(r0)
+ stw r11, 4(r0)
+ mfspr r10, SPRN_SRR0 /* Get effective address of fault */
+ DO_8xx_CPU6(0x3780, r3)
+ mtspr SPRN_MD_EPN, r10 /* Have to use MD_EPN for walk, MI_EPN can't */
+ mfspr r10, SPRN_M_TWB /* Get level 1 table entry address */
+
+ /* If we are faulting a kernel address, we have to use the
+ * kernel page tables.
+ */
+ andi. r11, r10, 0x0800 /* Address >= 0x80000000 */
+ beq 3f
+ lis r11, swapper_pg_dir@h
+ ori r11, r11, swapper_pg_dir@l
+ rlwimi r10, r11, 0, 2, 19
+3:
+ lwz r11, 0(r10) /* Get the level 1 entry */
+ rlwinm. r10, r11,0,0,19 /* Extract page descriptor page address */
+ beq 2f /* If zero, don't try to find a pte */
+
+ /* We have a pte table, so load the MI_TWC with the attributes
+ * for this "segment."
+ */
+ ori r11,r11,1 /* Set valid bit */
+ DO_8xx_CPU6(0x2b80, r3)
+ mtspr SPRN_MI_TWC, r11 /* Set segment attributes */
+ DO_8xx_CPU6(0x3b80, r3)
+ mtspr SPRN_MD_TWC, r11 /* Load pte table base address */
+ mfspr r11, SPRN_MD_TWC /* ....and get the pte address */
+ lwz r10, 0(r11) /* Get the pte */
+
+ ori r10, r10, _PAGE_ACCESSED
+ stw r10, 0(r11)
+
+ /* The Linux PTE won't go exactly into the MMU TLB.
+ * Software indicator bits 21, 22 and 28 must be clear.
+ * Software indicator bits 24, 25, 26, and 27 must be
+ * set. All other Linux PTE bits control the behavior
+ * of the MMU.
+ */
+2: li r11, 0x00f0
+ rlwimi r10, r11, 0, 24, 28 /* Set 24-27, clear 28 */
+ DO_8xx_CPU6(0x2d80, r3)
+ mtspr SPRN_MI_RPN, r10 /* Update TLB entry */
+
+ mfspr r10, SPRN_M_TW /* Restore registers */
+ lwz r11, 0(r0)
+ mtcr r11
+ lwz r11, 4(r0)
+#ifdef CONFIG_8xx_CPU6
+ lwz r3, 8(r0)
+#endif
+ rfi
+
+ . = 0x1200
+DataStoreTLBMiss:
+#ifdef CONFIG_8xx_CPU6
+ stw r3, 8(r0)
+#endif
+ DO_8xx_CPU6(0x3f80, r3)
+ mtspr SPRN_M_TW, r10 /* Save a couple of working registers */
+ mfcr r10
+ stw r10, 0(r0)
+ stw r11, 4(r0)
+ mfspr r10, SPRN_M_TWB /* Get level 1 table entry address */
+
+ /* If we are faulting a kernel address, we have to use the
+ * kernel page tables.
+ */
+ andi. r11, r10, 0x0800
+ beq 3f
+ lis r11, swapper_pg_dir@h
+ ori r11, r11, swapper_pg_dir@l
+ rlwimi r10, r11, 0, 2, 19
+3:
+ lwz r11, 0(r10) /* Get the level 1 entry */
+ rlwinm. r10, r11,0,0,19 /* Extract page descriptor page address */
+ beq 2f /* If zero, don't try to find a pte */
+
+ /* We have a pte table, so load fetch the pte from the table.
+ */
+ ori r11, r11, 1 /* Set valid bit in physical L2 page */
+ DO_8xx_CPU6(0x3b80, r3)
+ mtspr SPRN_MD_TWC, r11 /* Load pte table base address */
+ mfspr r10, SPRN_MD_TWC /* ....and get the pte address */
+ lwz r10, 0(r10) /* Get the pte */
+
+ /* Insert the Guarded flag into the TWC from the Linux PTE.
+ * It is bit 27 of both the Linux PTE and the TWC (at least
+ * I got that right :-). It will be better when we can put
+ * this into the Linux pgd/pmd and load it in the operation
+ * above.
+ */
+ rlwimi r11, r10, 0, 27, 27
+ DO_8xx_CPU6(0x3b80, r3)
+ mtspr SPRN_MD_TWC, r11
+
+ mfspr r11, SPRN_MD_TWC /* get the pte address again */
+ ori r10, r10, _PAGE_ACCESSED
+ stw r10, 0(r11)
+
+ /* The Linux PTE won't go exactly into the MMU TLB.
+ * Software indicator bits 21, 22 and 28 must be clear.
+ * Software indicator bits 24, 25, 26, and 27 must be
+ * set. All other Linux PTE bits control the behavior
+ * of the MMU.
+ */
+2: li r11, 0x00f0
+ rlwimi r10, r11, 0, 24, 28 /* Set 24-27, clear 28 */
+ DO_8xx_CPU6(0x3d80, r3)
+ mtspr SPRN_MD_RPN, r10 /* Update TLB entry */
+
+ mfspr r10, SPRN_M_TW /* Restore registers */
+ lwz r11, 0(r0)
+ mtcr r11
+ lwz r11, 4(r0)
+#ifdef CONFIG_8xx_CPU6
+ lwz r3, 8(r0)
+#endif
+ rfi
+
+/* This is an instruction TLB error on the MPC8xx. This could be due
+ * to many reasons, such as executing guarded memory or illegal instruction
+ * addresses. There is nothing to do but handle a big time error fault.
+ */
+ . = 0x1300
+InstructionTLBError:
+ b InstructionAccess
+
+/* This is the data TLB error on the MPC8xx. This could be due to
+ * many reasons, including a dirty update to a pte. We can catch that
+ * one here, but anything else is an error. First, we track down the
+ * Linux pte. If it is valid, write access is allowed, but the
+ * page dirty bit is not set, we will set it and reload the TLB. For
+ * any other case, we bail out to a higher level function that can
+ * handle it.
+ */
+ . = 0x1400
+DataTLBError:
+#ifdef CONFIG_8xx_CPU6
+ stw r3, 8(r0)
+#endif
+ DO_8xx_CPU6(0x3f80, r3)
+ mtspr SPRN_M_TW, r10 /* Save a couple of working registers */
+ mfcr r10
+ stw r10, 0(r0)
+ stw r11, 4(r0)
+
+ /* First, make sure this was a store operation.
+ */
+ mfspr r10, SPRN_DSISR
+ andis. r11, r10, 0x0200 /* If set, indicates store op */
+ beq 2f
+
+ /* The EA of a data TLB miss is automatically stored in the MD_EPN
+ * register. The EA of a data TLB error is automatically stored in
+ * the DAR, but not the MD_EPN register. We must copy the 20 most
+ * significant bits of the EA from the DAR to MD_EPN before we
+ * start walking the page tables. We also need to copy the CASID
+ * value from the M_CASID register.
+ * Addendum: The EA of a data TLB error is _supposed_ to be stored
+ * in DAR, but it seems that this doesn't happen in some cases, such
+ * as when the error is due to a dcbi instruction to a page with a
+ * TLB that doesn't have the changed bit set. In such cases, there
+ * does not appear to be any way to recover the EA of the error
+ * since it is neither in DAR nor MD_EPN. As a workaround, the
+ * _PAGE_HWWRITE bit is set for all kernel data pages when the PTEs
+ * are initialized in mapin_ram(). This will avoid the problem,
+ * assuming we only use the dcbi instruction on kernel addresses.
+ */
+ mfspr r10, SPRN_DAR
+ rlwinm r11, r10, 0, 0, 19
+ ori r11, r11, MD_EVALID
+ mfspr r10, SPRN_M_CASID
+ rlwimi r11, r10, 0, 28, 31
+ DO_8xx_CPU6(0x3780, r3)
+ mtspr SPRN_MD_EPN, r11
+
+ mfspr r10, SPRN_M_TWB /* Get level 1 table entry address */
+
+ /* If we are faulting a kernel address, we have to use the
+ * kernel page tables.
+ */
+ andi. r11, r10, 0x0800
+ beq 3f
+ lis r11, swapper_pg_dir@h
+ ori r11, r11, swapper_pg_dir@l
+ rlwimi r10, r11, 0, 2, 19
+3:
+ lwz r11, 0(r10) /* Get the level 1 entry */
+ rlwinm. r10, r11,0,0,19 /* Extract page descriptor page address */
+ beq 2f /* If zero, bail */
+
+ /* We have a pte table, so fetch the pte from the table.
+ */
+ ori r11, r11, 1 /* Set valid bit in physical L2 page */
+ DO_8xx_CPU6(0x3b80, r3)
+ mtspr SPRN_MD_TWC, r11 /* Load pte table base address */
+ mfspr r11, SPRN_MD_TWC /* ....and get the pte address */
+ lwz r10, 0(r11) /* Get the pte */
+
+ andi. r11, r10, _PAGE_RW /* Is it writeable? */
+ beq 2f /* Bail out if not */
+
+ /* Update 'changed', among others.
+ */
+ ori r10, r10, _PAGE_DIRTY|_PAGE_ACCESSED|_PAGE_HWWRITE
+ mfspr r11, SPRN_MD_TWC /* Get pte address again */
+ stw r10, 0(r11) /* and update pte in table */
+
+ /* The Linux PTE won't go exactly into the MMU TLB.
+ * Software indicator bits 21, 22 and 28 must be clear.
+ * Software indicator bits 24, 25, 26, and 27 must be
+ * set. All other Linux PTE bits control the behavior
+ * of the MMU.
+ */
+ li r11, 0x00f0
+ rlwimi r10, r11, 0, 24, 28 /* Set 24-27, clear 28 */
+ DO_8xx_CPU6(0x3d80, r3)
+ mtspr SPRN_MD_RPN, r10 /* Update TLB entry */
+
+ mfspr r10, SPRN_M_TW /* Restore registers */
+ lwz r11, 0(r0)
+ mtcr r11
+ lwz r11, 4(r0)
+#ifdef CONFIG_8xx_CPU6
+ lwz r3, 8(r0)
+#endif
+ rfi
+2:
+ mfspr r10, SPRN_M_TW /* Restore registers */
+ lwz r11, 0(r0)
+ mtcr r11
+ lwz r11, 4(r0)
+#ifdef CONFIG_8xx_CPU6
+ lwz r3, 8(r0)
+#endif
+ b DataAccess
+
+ EXCEPTION(0x1500, Trap_15, UnknownException, EXC_XFER_EE)
+ EXCEPTION(0x1600, Trap_16, UnknownException, EXC_XFER_EE)
+ EXCEPTION(0x1700, Trap_17, UnknownException, EXC_XFER_EE)
+ EXCEPTION(0x1800, Trap_18, UnknownException, EXC_XFER_EE)
+ EXCEPTION(0x1900, Trap_19, UnknownException, EXC_XFER_EE)
+ EXCEPTION(0x1a00, Trap_1a, UnknownException, EXC_XFER_EE)
+ EXCEPTION(0x1b00, Trap_1b, UnknownException, EXC_XFER_EE)
+
+/* On the MPC8xx, these next four traps are used for development
+ * support of breakpoints and such. Someday I will get around to
+ * using them.
+ */
+ EXCEPTION(0x1c00, Trap_1c, UnknownException, EXC_XFER_EE)
+ EXCEPTION(0x1d00, Trap_1d, UnknownException, EXC_XFER_EE)
+ EXCEPTION(0x1e00, Trap_1e, UnknownException, EXC_XFER_EE)
+ EXCEPTION(0x1f00, Trap_1f, UnknownException, EXC_XFER_EE)
+
+ . = 0x2000
+
+ .globl giveup_fpu
+giveup_fpu:
+ blr
+
+/*
+ * This is where the main kernel code starts.
+ */
+start_here:
+ /* ptr to current */
+ lis r2,init_task@h
+ ori r2,r2,init_task@l
+
+ /* ptr to phys current thread */
+ tophys(r4,r2)
+ addi r4,r4,THREAD /* init task's THREAD */
+ mtspr SPRN_SPRG3,r4
+ li r3,0
+ mtspr SPRN_SPRG2,r3 /* 0 => r1 has kernel sp */
+
+ /* stack */
+ lis r1,init_thread_union@ha
+ addi r1,r1,init_thread_union@l
+ li r0,0
+ stwu r0,THREAD_SIZE-STACK_FRAME_OVERHEAD(r1)
+
+ bl early_init /* We have to do this with MMU on */
+
+/*
+ * Decide what sort of machine this is and initialize the MMU.
+ */
+ mr r3,r31
+ mr r4,r30
+ mr r5,r29
+ mr r6,r28
+ mr r7,r27
+ bl machine_init
+ bl MMU_init
+
+/*
+ * Go back to running unmapped so we can load up new values
+ * and change to using our exception vectors.
+ * On the 8xx, all we have to do is invalidate the TLB to clear
+ * the old 8M byte TLB mappings and load the page table base register.
+ */
+ /* The right way to do this would be to track it down through
+ * init's THREAD like the context switch code does, but this is
+ * easier......until someone changes init's static structures.
+ */
+ lis r6, swapper_pg_dir@h
+ ori r6, r6, swapper_pg_dir@l
+ tophys(r6,r6)
+#ifdef CONFIG_8xx_CPU6
+ lis r4, cpu6_errata_word@h
+ ori r4, r4, cpu6_errata_word@l
+ li r3, 0x3980
+ stw r3, 12(r4)
+ lwz r3, 12(r4)
+#endif
+ mtspr SPRN_M_TWB, r6
+ lis r4,2f@h
+ ori r4,r4,2f@l
+ tophys(r4,r4)
+ li r3,MSR_KERNEL & ~(MSR_IR|MSR_DR)
+ mtspr SPRN_SRR0,r4
+ mtspr SPRN_SRR1,r3
+ rfi
+/* Load up the kernel context */
+2:
+ SYNC /* Force all PTE updates to finish */
+ tlbia /* Clear all TLB entries */
+ sync /* wait for tlbia/tlbie to finish */
+ TLBSYNC /* ... on all CPUs */
+
+ /* set up the PTE pointers for the Abatron bdiGDB.
+ */
+ tovirt(r6,r6)
+ lis r5, abatron_pteptrs@h
+ ori r5, r5, abatron_pteptrs@l
+ stw r5, 0xf0(r0) /* Must match your Abatron config file */
+ tophys(r5,r5)
+ stw r6, 0(r5)
+
+/* Now turn on the MMU for real! */
+ li r4,MSR_KERNEL
+ lis r3,start_kernel@h
+ ori r3,r3,start_kernel@l
+ mtspr SPRN_SRR0,r3
+ mtspr SPRN_SRR1,r4
+ rfi /* enable MMU and jump to start_kernel */
+
+/* Set up the initial MMU state so we can do the first level of
+ * kernel initialization. This maps the first 8 MBytes of memory 1:1
+ * virtual to physical. Also, set the cache mode since that is defined
+ * by TLB entries and perform any additional mapping (like of the IMMR).
+ * If configured to pin some TLBs, we pin the first 8 Mbytes of kernel,
+ * 24 Mbytes of data, and the 8M IMMR space. Anything not covered by
+ * these mappings is mapped by page tables.
+ */
+initial_mmu:
+ tlbia /* Invalidate all TLB entries */
+#ifdef CONFIG_PIN_TLB
+ lis r8, MI_RSV4I@h
+ ori r8, r8, 0x1c00
+#else
+ li r8, 0
+#endif
+ mtspr SPRN_MI_CTR, r8 /* Set instruction MMU control */
+
+#ifdef CONFIG_PIN_TLB
+ lis r10, (MD_RSV4I | MD_RESETVAL)@h
+ ori r10, r10, 0x1c00
+ mr r8, r10
+#else
+ lis r10, MD_RESETVAL@h
+#endif
+#ifndef CONFIG_8xx_COPYBACK
+ oris r10, r10, MD_WTDEF@h
+#endif
+ mtspr SPRN_MD_CTR, r10 /* Set data TLB control */
+
+ /* Now map the lower 8 Meg into the TLBs. For this quick hack,
+ * we can load the instruction and data TLB registers with the
+ * same values.
+ */
+ lis r8, KERNELBASE@h /* Create vaddr for TLB */
+ ori r8, r8, MI_EVALID /* Mark it valid */
+ mtspr SPRN_MI_EPN, r8
+ mtspr SPRN_MD_EPN, r8
+ li r8, MI_PS8MEG /* Set 8M byte page */
+ ori r8, r8, MI_SVALID /* Make it valid */
+ mtspr SPRN_MI_TWC, r8
+ mtspr SPRN_MD_TWC, r8
+ li r8, MI_BOOTINIT /* Create RPN for address 0 */
+ mtspr SPRN_MI_RPN, r8 /* Store TLB entry */
+ mtspr SPRN_MD_RPN, r8
+ lis r8, MI_Kp@h /* Set the protection mode */
+ mtspr SPRN_MI_AP, r8
+ mtspr SPRN_MD_AP, r8
+
+ /* Map another 8 MByte at the IMMR to get the processor
+ * internal registers (among other things).
+ */
+#ifdef CONFIG_PIN_TLB
+ addi r10, r10, 0x0100
+ mtspr SPRN_MD_CTR, r10
+#endif
+ mfspr r9, 638 /* Get current IMMR */
+ andis. r9, r9, 0xff80 /* Get 8Mbyte boundary */
+
+ mr r8, r9 /* Create vaddr for TLB */
+ ori r8, r8, MD_EVALID /* Mark it valid */
+ mtspr SPRN_MD_EPN, r8
+ li r8, MD_PS8MEG /* Set 8M byte page */
+ ori r8, r8, MD_SVALID /* Make it valid */
+ mtspr SPRN_MD_TWC, r8
+ mr r8, r9 /* Create paddr for TLB */
+ ori r8, r8, MI_BOOTINIT|0x2 /* Inhibit cache -- Cort */
+ mtspr SPRN_MD_RPN, r8
+
+#ifdef CONFIG_PIN_TLB
+ /* Map two more 8M kernel data pages.
+ */
+ addi r10, r10, 0x0100
+ mtspr SPRN_MD_CTR, r10
+
+ lis r8, KERNELBASE@h /* Create vaddr for TLB */
+ addis r8, r8, 0x0080 /* Add 8M */
+ ori r8, r8, MI_EVALID /* Mark it valid */
+ mtspr SPRN_MD_EPN, r8
+ li r9, MI_PS8MEG /* Set 8M byte page */
+ ori r9, r9, MI_SVALID /* Make it valid */
+ mtspr SPRN_MD_TWC, r9
+ li r11, MI_BOOTINIT /* Create RPN for address 0 */
+ addis r11, r11, 0x0080 /* Add 8M */
+ mtspr SPRN_MD_RPN, r8
+
+ addis r8, r8, 0x0080 /* Add 8M */
+ mtspr SPRN_MD_EPN, r8
+ mtspr SPRN_MD_TWC, r9
+ addis r11, r11, 0x0080 /* Add 8M */
+ mtspr SPRN_MD_RPN, r8
+#endif
+
+ /* Since the cache is enabled according to the information we
+ * just loaded into the TLB, invalidate and enable the caches here.
+ * We should probably check/set other modes....later.
+ */
+ lis r8, IDC_INVALL@h
+ mtspr SPRN_IC_CST, r8
+ mtspr SPRN_DC_CST, r8
+ lis r8, IDC_ENABLE@h
+ mtspr SPRN_IC_CST, r8
+#ifdef CONFIG_8xx_COPYBACK
+ mtspr SPRN_DC_CST, r8
+#else
+ /* For a debug option, I left this here to easily enable
+ * the write through cache mode
+ */
+ lis r8, DC_SFWT@h
+ mtspr SPRN_DC_CST, r8
+ lis r8, IDC_ENABLE@h
+ mtspr SPRN_DC_CST, r8
+#endif
+ blr
+
+
+/*
+ * Set up to use a given MMU context.
+ * r3 is context number, r4 is PGD pointer.
+ *
+ * We place the physical address of the new task page directory loaded
+ * into the MMU base register, and set the ASID compare register with
+ * the new "context."
+ */
+_GLOBAL(set_context)
+
+#ifdef CONFIG_BDI_SWITCH
+ /* Context switch the PTE pointer for the Abatron BDI2000.
+ * The PGDIR is passed as second argument.
+ */
+ lis r5, KERNELBASE@h
+ lwz r5, 0xf0(r5)
+ stw r4, 0x4(r5)
+#endif
+
+#ifdef CONFIG_8xx_CPU6
+ lis r6, cpu6_errata_word@h
+ ori r6, r6, cpu6_errata_word@l
+ tophys (r4, r4)
+ li r7, 0x3980
+ stw r7, 12(r6)
+ lwz r7, 12(r6)
+ mtspr SPRN_M_TWB, r4 /* Update MMU base address */
+ li r7, 0x3380
+ stw r7, 12(r6)
+ lwz r7, 12(r6)
+ mtspr SPRN_M_CASID, r3 /* Update context */
+#else
+ mtspr SPRN_M_CASID,r3 /* Update context */
+ tophys (r4, r4)
+ mtspr SPRN_M_TWB, r4 /* and pgd */
+#endif
+ SYNC
+ blr
+
+#ifdef CONFIG_8xx_CPU6
+/* It's here because it is unique to the 8xx.
+ * It is important we get called with interrupts disabled. I used to
+ * do that, but it appears that all code that calls this already had
+ * interrupt disabled.
+ */
+ .globl set_dec_cpu6
+set_dec_cpu6:
+ lis r7, cpu6_errata_word@h
+ ori r7, r7, cpu6_errata_word@l
+ li r4, 0x2c00
+ stw r4, 8(r7)
+ lwz r4, 8(r7)
+ mtspr 22, r3 /* Update Decrementer */
+ SYNC
+ blr
+#endif
+
+/*
+ * We put a few things here that have to be page-aligned.
+ * This stuff goes at the beginning of the data segment,
+ * which is page-aligned.
+ */
+ .data
+ .globl sdata
+sdata:
+ .globl empty_zero_page
+empty_zero_page:
+ .space 4096
+
+ .globl swapper_pg_dir
+swapper_pg_dir:
+ .space 4096
+
+/*
+ * This space gets a copy of optional info passed to us by the bootstrap
+ * Used to pass parameters into the kernel like root=/dev/sda1, etc.
+ */
+ .globl cmd_line
+cmd_line:
+ .space 512
+
+/* Room for two PTE table poiners, usually the kernel and current user
+ * pointer to their respective root page table (pgdir).
+ */
+abatron_pteptrs:
+ .space 8
+
+#ifdef CONFIG_8xx_CPU6
+ .globl cpu6_errata_word
+cpu6_errata_word:
+ .space 16
+#endif
+
diff --git a/arch/ppc/kernel/head_booke.h b/arch/ppc/kernel/head_booke.h
new file mode 100644
index 0000000..884dac9
--- /dev/null
+++ b/arch/ppc/kernel/head_booke.h
@@ -0,0 +1,340 @@
+#ifndef __HEAD_BOOKE_H__
+#define __HEAD_BOOKE_H__
+
+/*
+ * Macros used for common Book-e exception handling
+ */
+
+#define SET_IVOR(vector_number, vector_label) \
+ li r26,vector_label@l; \
+ mtspr SPRN_IVOR##vector_number,r26; \
+ sync
+
+#define NORMAL_EXCEPTION_PROLOG \
+ mtspr SPRN_SPRG0,r10; /* save two registers to work with */\
+ mtspr SPRN_SPRG1,r11; \
+ mtspr SPRN_SPRG4W,r1; \
+ mfcr r10; /* save CR in r10 for now */\
+ mfspr r11,SPRN_SRR1; /* check whether user or kernel */\
+ andi. r11,r11,MSR_PR; \
+ beq 1f; \
+ mfspr r1,SPRN_SPRG3; /* if from user, start at top of */\
+ lwz r1,THREAD_INFO-THREAD(r1); /* this thread's kernel stack */\
+ addi r1,r1,THREAD_SIZE; \
+1: subi r1,r1,INT_FRAME_SIZE; /* Allocate an exception frame */\
+ mr r11,r1; \
+ stw r10,_CCR(r11); /* save various registers */\
+ stw r12,GPR12(r11); \
+ stw r9,GPR9(r11); \
+ mfspr r10,SPRN_SPRG0; \
+ stw r10,GPR10(r11); \
+ mfspr r12,SPRN_SPRG1; \
+ stw r12,GPR11(r11); \
+ mflr r10; \
+ stw r10,_LINK(r11); \
+ mfspr r10,SPRN_SPRG4R; \
+ mfspr r12,SPRN_SRR0; \
+ stw r10,GPR1(r11); \
+ mfspr r9,SPRN_SRR1; \
+ stw r10,0(r11); \
+ rlwinm r9,r9,0,14,12; /* clear MSR_WE (necessary?) */\
+ stw r0,GPR0(r11); \
+ SAVE_4GPRS(3, r11); \
+ SAVE_2GPRS(7, r11)
+
+/* To handle the additional exception priority levels on 40x and Book-E
+ * processors we allocate a 4k stack per additional priority level. The various
+ * head_xxx.S files allocate space (exception_stack_top) for each priority's
+ * stack times the number of CPUs
+ *
+ * On 40x critical is the only additional level
+ * On 44x/e500 we have critical and machine check
+ *
+ * Additionally we reserve a SPRG for each priority level so we can free up a
+ * GPR to use as the base for indirect access to the exception stacks. This
+ * is necessary since the MMU is always on, for Book-E parts, and the stacks
+ * are offset from KERNELBASE.
+ *
+ */
+#define BOOKE_EXCEPTION_STACK_SIZE (8192)
+
+/* CRIT_SPRG only used in critical exception handling */
+#define CRIT_SPRG SPRN_SPRG2
+/* MCHECK_SPRG only used in critical exception handling */
+#define MCHECK_SPRG SPRN_SPRG6W
+
+#define MCHECK_STACK_TOP (exception_stack_top - 4096)
+#define CRIT_STACK_TOP (exception_stack_top)
+
+#ifdef CONFIG_SMP
+#define BOOKE_LOAD_CRIT_STACK \
+ mfspr r8,SPRN_PIR; \
+ mulli r8,r8,BOOKE_EXCEPTION_STACK_SIZE; \
+ neg r8,r8; \
+ addis r8,r8,CRIT_STACK_TOP@ha; \
+ addi r8,r8,CRIT_STACK_TOP@l
+#define BOOKE_LOAD_MCHECK_STACK \
+ mfspr r8,SPRN_PIR; \
+ mulli r8,r8,BOOKE_EXCEPTION_STACK_SIZE; \
+ neg r8,r8; \
+ addis r8,r8,MCHECK_STACK_TOP@ha; \
+ addi r8,r8,MCHECK_STACK_TOP@l
+#else
+#define BOOKE_LOAD_CRIT_STACK \
+ lis r8,CRIT_STACK_TOP@h; \
+ ori r8,r8,CRIT_STACK_TOP@l
+#define BOOKE_LOAD_MCHECK_STACK \
+ lis r8,MCHECK_STACK_TOP@h; \
+ ori r8,r8,MCHECK_STACK_TOP@l
+#endif
+
+/*
+ * Exception prolog for critical exceptions. This is a little different
+ * from the normal exception prolog above since a critical exception
+ * can potentially occur at any point during normal exception processing.
+ * Thus we cannot use the same SPRG registers as the normal prolog above.
+ * Instead we use a portion of the critical exception stack at low physical
+ * addresses.
+ */
+
+#define CRITICAL_EXCEPTION_PROLOG \
+ mtspr CRIT_SPRG,r8; \
+ BOOKE_LOAD_CRIT_STACK; /* r8 points to the crit stack */ \
+ stw r10,GPR10-INT_FRAME_SIZE(r8); \
+ stw r11,GPR11-INT_FRAME_SIZE(r8); \
+ mfcr r10; /* save CR in r10 for now */\
+ mfspr r11,SPRN_CSRR1; /* check whether user or kernel */\
+ andi. r11,r11,MSR_PR; \
+ mr r11,r8; \
+ mfspr r8,CRIT_SPRG; \
+ beq 1f; \
+ /* COMING FROM USER MODE */ \
+ mfspr r11,SPRN_SPRG3; /* if from user, start at top of */\
+ lwz r11,THREAD_INFO-THREAD(r11); /* this thread's kernel stack */\
+ addi r11,r11,THREAD_SIZE; \
+1: subi r11,r11,INT_FRAME_SIZE; /* Allocate an exception frame */\
+ stw r10,_CCR(r11); /* save various registers */\
+ stw r12,GPR12(r11); \
+ stw r9,GPR9(r11); \
+ mflr r10; \
+ stw r10,_LINK(r11); \
+ mfspr r12,SPRN_DEAR; /* save DEAR and ESR in the frame */\
+ stw r12,_DEAR(r11); /* since they may have had stuff */\
+ mfspr r9,SPRN_ESR; /* in them at the point where the */\
+ stw r9,_ESR(r11); /* exception was taken */\
+ mfspr r12,SPRN_CSRR0; \
+ stw r1,GPR1(r11); \
+ mfspr r9,SPRN_CSRR1; \
+ stw r1,0(r11); \
+ mr r1,r11; \
+ rlwinm r9,r9,0,14,12; /* clear MSR_WE (necessary?) */\
+ stw r0,GPR0(r11); \
+ SAVE_4GPRS(3, r11); \
+ SAVE_2GPRS(7, r11)
+
+/*
+ * Exception prolog for machine check exceptions. This is similar to
+ * the critical exception prolog, except that machine check exceptions
+ * have their stack.
+ */
+#define MCHECK_EXCEPTION_PROLOG \
+ mtspr MCHECK_SPRG,r8; \
+ BOOKE_LOAD_MCHECK_STACK; /* r8 points to the mcheck stack */\
+ stw r10,GPR10-INT_FRAME_SIZE(r8); \
+ stw r11,GPR11-INT_FRAME_SIZE(r8); \
+ mfcr r10; /* save CR in r10 for now */\
+ mfspr r11,SPRN_MCSRR1; /* check whether user or kernel */\
+ andi. r11,r11,MSR_PR; \
+ mr r11,r8; \
+ mfspr r8,MCHECK_SPRG; \
+ beq 1f; \
+ /* COMING FROM USER MODE */ \
+ mfspr r11,SPRN_SPRG3; /* if from user, start at top of */\
+ lwz r11,THREAD_INFO-THREAD(r11); /* this thread's kernel stack */\
+ addi r11,r11,THREAD_SIZE; \
+1: subi r11,r11,INT_FRAME_SIZE; /* Allocate an exception frame */\
+ stw r10,_CCR(r11); /* save various registers */\
+ stw r12,GPR12(r11); \
+ stw r9,GPR9(r11); \
+ mflr r10; \
+ stw r10,_LINK(r11); \
+ mfspr r12,SPRN_DEAR; /* save DEAR and ESR in the frame */\
+ stw r12,_DEAR(r11); /* since they may have had stuff */\
+ mfspr r9,SPRN_ESR; /* in them at the point where the */\
+ stw r9,_ESR(r11); /* exception was taken */\
+ mfspr r12,SPRN_MCSRR0; \
+ stw r1,GPR1(r11); \
+ mfspr r9,SPRN_MCSRR1; \
+ stw r1,0(r11); \
+ mr r1,r11; \
+ rlwinm r9,r9,0,14,12; /* clear MSR_WE (necessary?) */\
+ stw r0,GPR0(r11); \
+ SAVE_4GPRS(3, r11); \
+ SAVE_2GPRS(7, r11)
+
+/*
+ * Exception vectors.
+ */
+#define START_EXCEPTION(label) \
+ .align 5; \
+label:
+
+#define FINISH_EXCEPTION(func) \
+ bl transfer_to_handler_full; \
+ .long func; \
+ .long ret_from_except_full
+
+#define EXCEPTION(n, label, hdlr, xfer) \
+ START_EXCEPTION(label); \
+ NORMAL_EXCEPTION_PROLOG; \
+ addi r3,r1,STACK_FRAME_OVERHEAD; \
+ xfer(n, hdlr)
+
+#define CRITICAL_EXCEPTION(n, label, hdlr) \
+ START_EXCEPTION(label); \
+ CRITICAL_EXCEPTION_PROLOG; \
+ addi r3,r1,STACK_FRAME_OVERHEAD; \
+ EXC_XFER_TEMPLATE(hdlr, n+2, (MSR_KERNEL & ~(MSR_ME|MSR_DE|MSR_CE)), \
+ NOCOPY, crit_transfer_to_handler, \
+ ret_from_crit_exc)
+
+#define MCHECK_EXCEPTION(n, label, hdlr) \
+ START_EXCEPTION(label); \
+ MCHECK_EXCEPTION_PROLOG; \
+ mfspr r5,SPRN_ESR; \
+ stw r5,_ESR(r11); \
+ addi r3,r1,STACK_FRAME_OVERHEAD; \
+ EXC_XFER_TEMPLATE(hdlr, n+2, (MSR_KERNEL & ~(MSR_ME|MSR_DE|MSR_CE)), \
+ NOCOPY, mcheck_transfer_to_handler, \
+ ret_from_mcheck_exc)
+
+#define EXC_XFER_TEMPLATE(hdlr, trap, msr, copyee, tfer, ret) \
+ li r10,trap; \
+ stw r10,TRAP(r11); \
+ lis r10,msr@h; \
+ ori r10,r10,msr@l; \
+ copyee(r10, r9); \
+ bl tfer; \
+ .long hdlr; \
+ .long ret
+
+#define COPY_EE(d, s) rlwimi d,s,0,16,16
+#define NOCOPY(d, s)
+
+#define EXC_XFER_STD(n, hdlr) \
+ EXC_XFER_TEMPLATE(hdlr, n, MSR_KERNEL, NOCOPY, transfer_to_handler_full, \
+ ret_from_except_full)
+
+#define EXC_XFER_LITE(n, hdlr) \
+ EXC_XFER_TEMPLATE(hdlr, n+1, MSR_KERNEL, NOCOPY, transfer_to_handler, \
+ ret_from_except)
+
+#define EXC_XFER_EE(n, hdlr) \
+ EXC_XFER_TEMPLATE(hdlr, n, MSR_KERNEL, COPY_EE, transfer_to_handler_full, \
+ ret_from_except_full)
+
+#define EXC_XFER_EE_LITE(n, hdlr) \
+ EXC_XFER_TEMPLATE(hdlr, n+1, MSR_KERNEL, COPY_EE, transfer_to_handler, \
+ ret_from_except)
+
+
+/* Check for a single step debug exception while in an exception
+ * handler before state has been saved. This is to catch the case
+ * where an instruction that we are trying to single step causes
+ * an exception (eg ITLB/DTLB miss) and thus the first instruction of
+ * the exception handler generates a single step debug exception.
+ *
+ * If we get a debug trap on the first instruction of an exception handler,
+ * we reset the MSR_DE in the _exception handler's_ MSR (the debug trap is
+ * a critical exception, so we are using SPRN_CSRR1 to manipulate the MSR).
+ * The exception handler was handling a non-critical interrupt, so it will
+ * save (and later restore) the MSR via SPRN_CSRR1, which will still have
+ * the MSR_DE bit set.
+ */
+#define DEBUG_EXCEPTION \
+ START_EXCEPTION(Debug); \
+ CRITICAL_EXCEPTION_PROLOG; \
+ \
+ /* \
+ * If there is a single step or branch-taken exception in an \
+ * exception entry sequence, it was probably meant to apply to \
+ * the code where the exception occurred (since exception entry \
+ * doesn't turn off DE automatically). We simulate the effect \
+ * of turning off DE on entry to an exception handler by turning \
+ * off DE in the CSRR1 value and clearing the debug status. \
+ */ \
+ mfspr r10,SPRN_DBSR; /* check single-step/branch taken */ \
+ andis. r10,r10,DBSR_IC@h; \
+ beq+ 2f; \
+ \
+ lis r10,KERNELBASE@h; /* check if exception in vectors */ \
+ ori r10,r10,KERNELBASE@l; \
+ cmplw r12,r10; \
+ blt+ 2f; /* addr below exception vectors */ \
+ \
+ lis r10,Debug@h; \
+ ori r10,r10,Debug@l; \
+ cmplw r12,r10; \
+ bgt+ 2f; /* addr above exception vectors */ \
+ \
+ /* here it looks like we got an inappropriate debug exception. */ \
+1: rlwinm r9,r9,0,~MSR_DE; /* clear DE in the CSRR1 value */ \
+ lis r10,DBSR_IC@h; /* clear the IC event */ \
+ mtspr SPRN_DBSR,r10; \
+ /* restore state and get out */ \
+ lwz r10,_CCR(r11); \
+ lwz r0,GPR0(r11); \
+ lwz r1,GPR1(r11); \
+ mtcrf 0x80,r10; \
+ mtspr SPRN_CSRR0,r12; \
+ mtspr SPRN_CSRR1,r9; \
+ lwz r9,GPR9(r11); \
+ lwz r12,GPR12(r11); \
+ mtspr CRIT_SPRG,r8; \
+ BOOKE_LOAD_CRIT_STACK; /* r8 points to the crit stack */ \
+ lwz r10,GPR10-INT_FRAME_SIZE(r8); \
+ lwz r11,GPR11-INT_FRAME_SIZE(r8); \
+ mfspr r8,CRIT_SPRG; \
+ \
+ rfci; \
+ b .; \
+ \
+ /* continue normal handling for a critical exception... */ \
+2: mfspr r4,SPRN_DBSR; \
+ addi r3,r1,STACK_FRAME_OVERHEAD; \
+ EXC_XFER_TEMPLATE(DebugException, 0x2002, (MSR_KERNEL & ~(MSR_ME|MSR_DE|MSR_CE)), NOCOPY, crit_transfer_to_handler, ret_from_crit_exc)
+
+#define INSTRUCTION_STORAGE_EXCEPTION \
+ START_EXCEPTION(InstructionStorage) \
+ NORMAL_EXCEPTION_PROLOG; \
+ mfspr r5,SPRN_ESR; /* Grab the ESR and save it */ \
+ stw r5,_ESR(r11); \
+ mr r4,r12; /* Pass SRR0 as arg2 */ \
+ li r5,0; /* Pass zero as arg3 */ \
+ EXC_XFER_EE_LITE(0x0400, handle_page_fault)
+
+#define ALIGNMENT_EXCEPTION \
+ START_EXCEPTION(Alignment) \
+ NORMAL_EXCEPTION_PROLOG; \
+ mfspr r4,SPRN_DEAR; /* Grab the DEAR and save it */ \
+ stw r4,_DEAR(r11); \
+ addi r3,r1,STACK_FRAME_OVERHEAD; \
+ EXC_XFER_EE(0x0600, AlignmentException)
+
+#define PROGRAM_EXCEPTION \
+ START_EXCEPTION(Program) \
+ NORMAL_EXCEPTION_PROLOG; \
+ mfspr r4,SPRN_ESR; /* Grab the ESR and save it */ \
+ stw r4,_ESR(r11); \
+ addi r3,r1,STACK_FRAME_OVERHEAD; \
+ EXC_XFER_STD(0x0700, ProgramCheckException)
+
+#define DECREMENTER_EXCEPTION \
+ START_EXCEPTION(Decrementer) \
+ NORMAL_EXCEPTION_PROLOG; \
+ lis r0,TSR_DIS@h; /* Setup the DEC interrupt mask */ \
+ mtspr SPRN_TSR,r0; /* Clear the DEC interrupt */ \
+ addi r3,r1,STACK_FRAME_OVERHEAD; \
+ EXC_XFER_LITE(0x0900, timer_interrupt)
+
+#endif /* __HEAD_BOOKE_H__ */
diff --git a/arch/ppc/kernel/head_fsl_booke.S b/arch/ppc/kernel/head_fsl_booke.S
new file mode 100644
index 0000000..dea19c2
--- /dev/null
+++ b/arch/ppc/kernel/head_fsl_booke.S
@@ -0,0 +1,952 @@
+/*
+ * arch/ppc/kernel/head_fsl_booke.S
+ *
+ * Kernel execution entry point code.
+ *
+ * Copyright (c) 1995-1996 Gary Thomas <gdt@linuxppc.org>
+ * Initial PowerPC version.
+ * Copyright (c) 1996 Cort Dougan <cort@cs.nmt.edu>
+ * Rewritten for PReP
+ * Copyright (c) 1996 Paul Mackerras <paulus@cs.anu.edu.au>
+ * Low-level exception handers, MMU support, and rewrite.
+ * Copyright (c) 1997 Dan Malek <dmalek@jlc.net>
+ * PowerPC 8xx modifications.
+ * Copyright (c) 1998-1999 TiVo, Inc.
+ * PowerPC 403GCX modifications.
+ * Copyright (c) 1999 Grant Erickson <grant@lcse.umn.edu>
+ * PowerPC 403GCX/405GP modifications.
+ * Copyright 2000 MontaVista Software Inc.
+ * PPC405 modifications
+ * PowerPC 403GCX/405GP modifications.
+ * Author: MontaVista Software, Inc.
+ * frank_rowand@mvista.com or source@mvista.com
+ * debbie_chu@mvista.com
+ * Copyright 2002-2004 MontaVista Software, Inc.
+ * PowerPC 44x support, Matt Porter <mporter@kernel.crashing.org>
+ * Copyright 2004 Freescale Semiconductor, Inc
+ * PowerPC e500 modifications, Kumar Gala <kumar.gala@freescale.com>
+ *
+ * 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.
+ */
+
+#include <linux/config.h>
+#include <linux/threads.h>
+#include <asm/processor.h>
+#include <asm/page.h>
+#include <asm/mmu.h>
+#include <asm/pgtable.h>
+#include <asm/cputable.h>
+#include <asm/thread_info.h>
+#include <asm/ppc_asm.h>
+#include <asm/offsets.h>
+#include "head_booke.h"
+
+/* As with the other PowerPC ports, it is expected that when code
+ * execution begins here, the following registers contain valid, yet
+ * optional, information:
+ *
+ * r3 - Board info structure pointer (DRAM, frequency, MAC address, etc.)
+ * r4 - Starting address of the init RAM disk
+ * r5 - Ending address of the init RAM disk
+ * r6 - Start of kernel command line string (e.g. "mem=128")
+ * r7 - End of kernel command line string
+ *
+ */
+ .text
+_GLOBAL(_stext)
+_GLOBAL(_start)
+ /*
+ * Reserve a word at a fixed location to store the address
+ * of abatron_pteptrs
+ */
+ nop
+/*
+ * Save parameters we are passed
+ */
+ mr r31,r3
+ mr r30,r4
+ mr r29,r5
+ mr r28,r6
+ mr r27,r7
+ li r24,0 /* CPU number */
+
+/* We try to not make any assumptions about how the boot loader
+ * setup or used the TLBs. We invalidate all mappings from the
+ * boot loader and load a single entry in TLB1[0] to map the
+ * first 16M of kernel memory. Any boot info passed from the
+ * bootloader needs to live in this first 16M.
+ *
+ * Requirement on bootloader:
+ * - The page we're executing in needs to reside in TLB1 and
+ * have IPROT=1. If not an invalidate broadcast could
+ * evict the entry we're currently executing in.
+ *
+ * r3 = Index of TLB1 were executing in
+ * r4 = Current MSR[IS]
+ * r5 = Index of TLB1 temp mapping
+ *
+ * Later in mapin_ram we will correctly map lowmem, and resize TLB1[0]
+ * if needed
+ */
+
+/* 1. Find the index of the entry we're executing in */
+ bl invstr /* Find our address */
+invstr: mflr r6 /* Make it accessible */
+ mfmsr r7
+ rlwinm r4,r7,27,31,31 /* extract MSR[IS] */
+ mfspr r7, SPRN_PID0
+ slwi r7,r7,16
+ or r7,r7,r4
+ mtspr SPRN_MAS6,r7
+ tlbsx 0,r6 /* search MSR[IS], SPID=PID0 */
+ mfspr r7,SPRN_MAS1
+ andis. r7,r7,MAS1_VALID@h
+ bne match_TLB
+ mfspr r7,SPRN_PID1
+ slwi r7,r7,16
+ or r7,r7,r4
+ mtspr SPRN_MAS6,r7
+ tlbsx 0,r6 /* search MSR[IS], SPID=PID1 */
+ mfspr r7,SPRN_MAS1
+ andis. r7,r7,MAS1_VALID@h
+ bne match_TLB
+ mfspr r7, SPRN_PID2
+ slwi r7,r7,16
+ or r7,r7,r4
+ mtspr SPRN_MAS6,r7
+ tlbsx 0,r6 /* Fall through, we had to match */
+match_TLB:
+ mfspr r7,SPRN_MAS0
+ rlwinm r3,r7,16,20,31 /* Extract MAS0(Entry) */
+
+ mfspr r7,SPRN_MAS1 /* Insure IPROT set */
+ oris r7,r7,MAS1_IPROT@h
+ mtspr SPRN_MAS1,r7
+ tlbwe
+
+/* 2. Invalidate all entries except the entry we're executing in */
+ mfspr r9,SPRN_TLB1CFG
+ andi. r9,r9,0xfff
+ li r6,0 /* Set Entry counter to 0 */
+1: lis r7,0x1000 /* Set MAS0(TLBSEL) = 1 */
+ rlwimi r7,r6,16,4,15 /* Setup MAS0 = TLBSEL | ESEL(r6) */
+ mtspr SPRN_MAS0,r7
+ tlbre
+ mfspr r7,SPRN_MAS1
+ rlwinm r7,r7,0,2,31 /* Clear MAS1 Valid and IPROT */
+ cmpw r3,r6
+ beq skpinv /* Dont update the current execution TLB */
+ mtspr SPRN_MAS1,r7
+ tlbwe
+ isync
+skpinv: addi r6,r6,1 /* Increment */
+ cmpw r6,r9 /* Are we done? */
+ bne 1b /* If not, repeat */
+
+ /* Invalidate TLB0 */
+ li r6,0x04
+ tlbivax 0,r6
+#ifdef CONFIG_SMP
+ tlbsync
+#endif
+ /* Invalidate TLB1 */
+ li r6,0x0c
+ tlbivax 0,r6
+#ifdef CONFIG_SMP
+ tlbsync
+#endif
+ msync
+
+/* 3. Setup a temp mapping and jump to it */
+ andi. r5, r3, 0x1 /* Find an entry not used and is non-zero */
+ addi r5, r5, 0x1
+ lis r7,0x1000 /* Set MAS0(TLBSEL) = 1 */
+ rlwimi r7,r3,16,4,15 /* Setup MAS0 = TLBSEL | ESEL(r3) */
+ mtspr SPRN_MAS0,r7
+ tlbre
+
+ /* Just modify the entry ID and EPN for the temp mapping */
+ lis r7,0x1000 /* Set MAS0(TLBSEL) = 1 */
+ rlwimi r7,r5,16,4,15 /* Setup MAS0 = TLBSEL | ESEL(r5) */
+ mtspr SPRN_MAS0,r7
+ xori r6,r4,1 /* Setup TMP mapping in the other Address space */
+ slwi r6,r6,12
+ oris r6,r6,(MAS1_VALID|MAS1_IPROT)@h
+ ori r6,r6,(MAS1_TSIZE(BOOKE_PAGESZ_4K))@l
+ mtspr SPRN_MAS1,r6
+ mfspr r6,SPRN_MAS2
+ li r7,0 /* temp EPN = 0 */
+ rlwimi r7,r6,0,20,31
+ mtspr SPRN_MAS2,r7
+ tlbwe
+
+ xori r6,r4,1
+ slwi r6,r6,5 /* setup new context with other address space */
+ bl 1f /* Find our address */
+1: mflr r9
+ rlwimi r7,r9,0,20,31
+ addi r7,r7,24
+ mtspr SPRN_SRR0,r7
+ mtspr SPRN_SRR1,r6
+ rfi
+
+/* 4. Clear out PIDs & Search info */
+ li r6,0
+ mtspr SPRN_PID0,r6
+ mtspr SPRN_PID1,r6
+ mtspr SPRN_PID2,r6
+ mtspr SPRN_MAS6,r6
+
+/* 5. Invalidate mapping we started in */
+ lis r7,0x1000 /* Set MAS0(TLBSEL) = 1 */
+ rlwimi r7,r3,16,4,15 /* Setup MAS0 = TLBSEL | ESEL(r3) */
+ mtspr SPRN_MAS0,r7
+ tlbre
+ li r6,0
+ mtspr SPRN_MAS1,r6
+ tlbwe
+ /* Invalidate TLB1 */
+ li r9,0x0c
+ tlbivax 0,r9
+#ifdef CONFIG_SMP
+ tlbsync
+#endif
+ msync
+
+/* 6. Setup KERNELBASE mapping in TLB1[0] */
+ lis r6,0x1000 /* Set MAS0(TLBSEL) = TLB1(1), ESEL = 0 */
+ mtspr SPRN_MAS0,r6
+ lis r6,(MAS1_VALID|MAS1_IPROT)@h
+ ori r6,r6,(MAS1_TSIZE(BOOKE_PAGESZ_16M))@l
+ mtspr SPRN_MAS1,r6
+ li r7,0
+ lis r6,KERNELBASE@h
+ ori r6,r6,KERNELBASE@l
+ rlwimi r6,r7,0,20,31
+ mtspr SPRN_MAS2,r6
+ li r7,(MAS3_SX|MAS3_SW|MAS3_SR)
+ mtspr SPRN_MAS3,r7
+ tlbwe
+
+/* 7. Jump to KERNELBASE mapping */
+ li r7,0
+ bl 1f /* Find our address */
+1: mflr r9
+ rlwimi r6,r9,0,20,31
+ addi r6,r6,24
+ mtspr SPRN_SRR0,r6
+ mtspr SPRN_SRR1,r7
+ rfi /* start execution out of TLB1[0] entry */
+
+/* 8. Clear out the temp mapping */
+ lis r7,0x1000 /* Set MAS0(TLBSEL) = 1 */
+ rlwimi r7,r5,16,4,15 /* Setup MAS0 = TLBSEL | ESEL(r5) */
+ mtspr SPRN_MAS0,r7
+ tlbre
+ mtspr SPRN_MAS1,r8
+ tlbwe
+ /* Invalidate TLB1 */
+ li r9,0x0c
+ tlbivax 0,r9
+#ifdef CONFIG_SMP
+ tlbsync
+#endif
+ msync
+
+ /* Establish the interrupt vector offsets */
+ SET_IVOR(0, CriticalInput);
+ SET_IVOR(1, MachineCheck);
+ SET_IVOR(2, DataStorage);
+ SET_IVOR(3, InstructionStorage);
+ SET_IVOR(4, ExternalInput);
+ SET_IVOR(5, Alignment);
+ SET_IVOR(6, Program);
+ SET_IVOR(7, FloatingPointUnavailable);
+ SET_IVOR(8, SystemCall);
+ SET_IVOR(9, AuxillaryProcessorUnavailable);
+ SET_IVOR(10, Decrementer);
+ SET_IVOR(11, FixedIntervalTimer);
+ SET_IVOR(12, WatchdogTimer);
+ SET_IVOR(13, DataTLBError);
+ SET_IVOR(14, InstructionTLBError);
+ SET_IVOR(15, Debug);
+ SET_IVOR(32, SPEUnavailable);
+ SET_IVOR(33, SPEFloatingPointData);
+ SET_IVOR(34, SPEFloatingPointRound);
+ SET_IVOR(35, PerformanceMonitor);
+
+ /* Establish the interrupt vector base */
+ lis r4,interrupt_base@h /* IVPR only uses the high 16-bits */
+ mtspr SPRN_IVPR,r4
+
+ /* Setup the defaults for TLB entries */
+ li r2,(MAS4_TSIZED(BOOKE_PAGESZ_4K))@l
+ mtspr SPRN_MAS4, r2
+
+#if 0
+ /* Enable DOZE */
+ mfspr r2,SPRN_HID0
+ oris r2,r2,HID0_DOZE@h
+ mtspr SPRN_HID0, r2
+#endif
+
+ /*
+ * This is where the main kernel code starts.
+ */
+
+ /* ptr to current */
+ lis r2,init_task@h
+ ori r2,r2,init_task@l
+
+ /* ptr to current thread */
+ addi r4,r2,THREAD /* init task's THREAD */
+ mtspr SPRN_SPRG3,r4
+
+ /* stack */
+ lis r1,init_thread_union@h
+ ori r1,r1,init_thread_union@l
+ li r0,0
+ stwu r0,THREAD_SIZE-STACK_FRAME_OVERHEAD(r1)
+
+ bl early_init
+
+ mfspr r3,SPRN_TLB1CFG
+ andi. r3,r3,0xfff
+ lis r4,num_tlbcam_entries@ha
+ stw r3,num_tlbcam_entries@l(r4)
+/*
+ * Decide what sort of machine this is and initialize the MMU.
+ */
+ mr r3,r31
+ mr r4,r30
+ mr r5,r29
+ mr r6,r28
+ mr r7,r27
+ bl machine_init
+ bl MMU_init
+
+ /* Setup PTE pointers for the Abatron bdiGDB */
+ lis r6, swapper_pg_dir@h
+ ori r6, r6, swapper_pg_dir@l
+ lis r5, abatron_pteptrs@h
+ ori r5, r5, abatron_pteptrs@l
+ lis r4, KERNELBASE@h
+ ori r4, r4, KERNELBASE@l
+ stw r5, 0(r4) /* Save abatron_pteptrs at a fixed location */
+ stw r6, 0(r5)
+
+ /* Let's move on */
+ lis r4,start_kernel@h
+ ori r4,r4,start_kernel@l
+ lis r3,MSR_KERNEL@h
+ ori r3,r3,MSR_KERNEL@l
+ mtspr SPRN_SRR0,r4
+ mtspr SPRN_SRR1,r3
+ rfi /* change context and jump to start_kernel */
+
+/*
+ * Interrupt vector entry code
+ *
+ * The Book E MMUs are always on so we don't need to handle
+ * interrupts in real mode as with previous PPC processors. In
+ * this case we handle interrupts in the kernel virtual address
+ * space.
+ *
+ * Interrupt vectors are dynamically placed relative to the
+ * interrupt prefix as determined by the address of interrupt_base.
+ * The interrupt vectors offsets are programmed using the labels
+ * for each interrupt vector entry.
+ *
+ * Interrupt vectors must be aligned on a 16 byte boundary.
+ * We align on a 32 byte cache line boundary for good measure.
+ */
+
+interrupt_base:
+ /* Critical Input Interrupt */
+ CRITICAL_EXCEPTION(0x0100, CriticalInput, UnknownException)
+
+ /* Machine Check Interrupt */
+ MCHECK_EXCEPTION(0x0200, MachineCheck, MachineCheckException)
+
+ /* Data Storage Interrupt */
+ START_EXCEPTION(DataStorage)
+ mtspr SPRN_SPRG0, r10 /* Save some working registers */
+ mtspr SPRN_SPRG1, r11
+ mtspr SPRN_SPRG4W, r12
+ mtspr SPRN_SPRG5W, r13
+ mfcr r11
+ mtspr SPRN_SPRG7W, r11
+
+ /*
+ * Check if it was a store fault, if not then bail
+ * because a user tried to access a kernel or
+ * read-protected page. Otherwise, get the
+ * offending address and handle it.
+ */
+ mfspr r10, SPRN_ESR
+ andis. r10, r10, ESR_ST@h
+ beq 2f
+
+ mfspr r10, SPRN_DEAR /* Get faulting address */
+
+ /* If we are faulting a kernel address, we have to use the
+ * kernel page tables.
+ */
+ lis r11, TASK_SIZE@h
+ ori r11, r11, TASK_SIZE@l
+ cmplw 0, r10, r11
+ bge 2f
+
+ /* Get the PGD for the current thread */
+3:
+ mfspr r11,SPRN_SPRG3
+ lwz r11,PGDIR(r11)
+4:
+ rlwimi r11, r10, 12, 20, 29 /* Create L1 (pgdir/pmd) address */
+ lwz r11, 0(r11) /* Get L1 entry */
+ rlwinm. r12, r11, 0, 0, 19 /* Extract L2 (pte) base address */
+ beq 2f /* Bail if no table */
+
+ rlwimi r12, r10, 22, 20, 29 /* Compute PTE address */
+ lwz r11, 0(r12) /* Get Linux PTE */
+
+ /* Are _PAGE_USER & _PAGE_RW set & _PAGE_HWWRITE not? */
+ andi. r13, r11, _PAGE_RW|_PAGE_USER|_PAGE_HWWRITE
+ cmpwi 0, r13, _PAGE_RW|_PAGE_USER
+ bne 2f /* Bail if not */
+
+ /* Update 'changed'. */
+ ori r11, r11, _PAGE_DIRTY|_PAGE_ACCESSED|_PAGE_HWWRITE
+ stw r11, 0(r12) /* Update Linux page table */
+
+ /* MAS2 not updated as the entry does exist in the tlb, this
+ fault taken to detect state transition (eg: COW -> DIRTY)
+ */
+ lis r12, MAS3_RPN@h
+ ori r12, r12, _PAGE_HWEXEC | MAS3_RPN@l
+ and r11, r11, r12
+ rlwimi r11, r11, 31, 27, 27 /* SX <- _PAGE_HWEXEC */
+ ori r11, r11, (MAS3_UW|MAS3_SW|MAS3_UR|MAS3_SR)@l /* set static perms */
+
+ /* update search PID in MAS6, AS = 0 */
+ mfspr r12, SPRN_PID0
+ slwi r12, r12, 16
+ mtspr SPRN_MAS6, r12
+
+ /* find the TLB index that caused the fault. It has to be here. */
+ tlbsx 0, r10
+
+ mtspr SPRN_MAS3,r11
+ tlbwe
+
+ /* Done...restore registers and get out of here. */
+ mfspr r11, SPRN_SPRG7R
+ mtcr r11
+ mfspr r13, SPRN_SPRG5R
+ mfspr r12, SPRN_SPRG4R
+ mfspr r11, SPRN_SPRG1
+ mfspr r10, SPRN_SPRG0
+ rfi /* Force context change */
+
+2:
+ /*
+ * The bailout. Restore registers to pre-exception conditions
+ * and call the heavyweights to help us out.
+ */
+ mfspr r11, SPRN_SPRG7R
+ mtcr r11
+ mfspr r13, SPRN_SPRG5R
+ mfspr r12, SPRN_SPRG4R
+ mfspr r11, SPRN_SPRG1
+ mfspr r10, SPRN_SPRG0
+ b data_access
+
+ /* Instruction Storage Interrupt */
+ INSTRUCTION_STORAGE_EXCEPTION
+
+ /* External Input Interrupt */
+ EXCEPTION(0x0500, ExternalInput, do_IRQ, EXC_XFER_LITE)
+
+ /* Alignment Interrupt */
+ ALIGNMENT_EXCEPTION
+
+ /* Program Interrupt */
+ PROGRAM_EXCEPTION
+
+ /* Floating Point Unavailable Interrupt */
+ EXCEPTION(0x0800, FloatingPointUnavailable, UnknownException, EXC_XFER_EE)
+
+ /* System Call Interrupt */
+ START_EXCEPTION(SystemCall)
+ NORMAL_EXCEPTION_PROLOG
+ EXC_XFER_EE_LITE(0x0c00, DoSyscall)
+
+ /* Auxillary Processor Unavailable Interrupt */
+ EXCEPTION(0x2900, AuxillaryProcessorUnavailable, UnknownException, EXC_XFER_EE)
+
+ /* Decrementer Interrupt */
+ DECREMENTER_EXCEPTION
+
+ /* Fixed Internal Timer Interrupt */
+ /* TODO: Add FIT support */
+ EXCEPTION(0x3100, FixedIntervalTimer, UnknownException, EXC_XFER_EE)
+
+ /* Watchdog Timer Interrupt */
+ /* TODO: Add watchdog support */
+ CRITICAL_EXCEPTION(0x3200, WatchdogTimer, UnknownException)
+
+ /* Data TLB Error Interrupt */
+ START_EXCEPTION(DataTLBError)
+ mtspr SPRN_SPRG0, r10 /* Save some working registers */
+ mtspr SPRN_SPRG1, r11
+ mtspr SPRN_SPRG4W, r12
+ mtspr SPRN_SPRG5W, r13
+ mfcr r11
+ mtspr SPRN_SPRG7W, r11
+ mfspr r10, SPRN_DEAR /* Get faulting address */
+
+ /* If we are faulting a kernel address, we have to use the
+ * kernel page tables.
+ */
+ lis r11, TASK_SIZE@h
+ ori r11, r11, TASK_SIZE@l
+ cmplw 5, r10, r11
+ blt 5, 3f
+ lis r11, swapper_pg_dir@h
+ ori r11, r11, swapper_pg_dir@l
+
+ mfspr r12,SPRN_MAS1 /* Set TID to 0 */
+ rlwinm r12,r12,0,16,1
+ mtspr SPRN_MAS1,r12
+
+ b 4f
+
+ /* Get the PGD for the current thread */
+3:
+ mfspr r11,SPRN_SPRG3
+ lwz r11,PGDIR(r11)
+
+4:
+ rlwimi r11, r10, 12, 20, 29 /* Create L1 (pgdir/pmd) address */
+ lwz r11, 0(r11) /* Get L1 entry */
+ rlwinm. r12, r11, 0, 0, 19 /* Extract L2 (pte) base address */
+ beq 2f /* Bail if no table */
+
+ rlwimi r12, r10, 22, 20, 29 /* Compute PTE address */
+ lwz r11, 0(r12) /* Get Linux PTE */
+ andi. r13, r11, _PAGE_PRESENT
+ beq 2f
+
+ ori r11, r11, _PAGE_ACCESSED
+ stw r11, 0(r12)
+
+ /* Jump to common tlb load */
+ b finish_tlb_load
+2:
+ /* The bailout. Restore registers to pre-exception conditions
+ * and call the heavyweights to help us out.
+ */
+ mfspr r11, SPRN_SPRG7R
+ mtcr r11
+ mfspr r13, SPRN_SPRG5R
+ mfspr r12, SPRN_SPRG4R
+ mfspr r11, SPRN_SPRG1
+ mfspr r10, SPRN_SPRG0
+ b data_access
+
+ /* Instruction TLB Error Interrupt */
+ /*
+ * Nearly the same as above, except we get our
+ * information from different registers and bailout
+ * to a different point.
+ */
+ START_EXCEPTION(InstructionTLBError)
+ mtspr SPRN_SPRG0, r10 /* Save some working registers */
+ mtspr SPRN_SPRG1, r11
+ mtspr SPRN_SPRG4W, r12
+ mtspr SPRN_SPRG5W, r13
+ mfcr r11
+ mtspr SPRN_SPRG7W, r11
+ mfspr r10, SPRN_SRR0 /* Get faulting address */
+
+ /* If we are faulting a kernel address, we have to use the
+ * kernel page tables.
+ */
+ lis r11, TASK_SIZE@h
+ ori r11, r11, TASK_SIZE@l
+ cmplw 5, r10, r11
+ blt 5, 3f
+ lis r11, swapper_pg_dir@h
+ ori r11, r11, swapper_pg_dir@l
+
+ mfspr r12,SPRN_MAS1 /* Set TID to 0 */
+ rlwinm r12,r12,0,16,1
+ mtspr SPRN_MAS1,r12
+
+ b 4f
+
+ /* Get the PGD for the current thread */
+3:
+ mfspr r11,SPRN_SPRG3
+ lwz r11,PGDIR(r11)
+
+4:
+ rlwimi r11, r10, 12, 20, 29 /* Create L1 (pgdir/pmd) address */
+ lwz r11, 0(r11) /* Get L1 entry */
+ rlwinm. r12, r11, 0, 0, 19 /* Extract L2 (pte) base address */
+ beq 2f /* Bail if no table */
+
+ rlwimi r12, r10, 22, 20, 29 /* Compute PTE address */
+ lwz r11, 0(r12) /* Get Linux PTE */
+ andi. r13, r11, _PAGE_PRESENT
+ beq 2f
+
+ ori r11, r11, _PAGE_ACCESSED
+ stw r11, 0(r12)
+
+ /* Jump to common TLB load point */
+ b finish_tlb_load
+
+2:
+ /* The bailout. Restore registers to pre-exception conditions
+ * and call the heavyweights to help us out.
+ */
+ mfspr r11, SPRN_SPRG7R
+ mtcr r11
+ mfspr r13, SPRN_SPRG5R
+ mfspr r12, SPRN_SPRG4R
+ mfspr r11, SPRN_SPRG1
+ mfspr r10, SPRN_SPRG0
+ b InstructionStorage
+
+#ifdef CONFIG_SPE
+ /* SPE Unavailable */
+ START_EXCEPTION(SPEUnavailable)
+ NORMAL_EXCEPTION_PROLOG
+ bne load_up_spe
+ addi r3,r1,STACK_FRAME_OVERHEAD
+ EXC_XFER_EE_LITE(0x2010, KernelSPE)
+#else
+ EXCEPTION(0x2020, SPEUnavailable, UnknownException, EXC_XFER_EE)
+#endif /* CONFIG_SPE */
+
+ /* SPE Floating Point Data */
+#ifdef CONFIG_SPE
+ EXCEPTION(0x2030, SPEFloatingPointData, SPEFloatingPointException, EXC_XFER_EE);
+#else
+ EXCEPTION(0x2040, SPEFloatingPointData, UnknownException, EXC_XFER_EE)
+#endif /* CONFIG_SPE */
+
+ /* SPE Floating Point Round */
+ EXCEPTION(0x2050, SPEFloatingPointRound, UnknownException, EXC_XFER_EE)
+
+ /* Performance Monitor */
+ EXCEPTION(0x2060, PerformanceMonitor, PerformanceMonitorException, EXC_XFER_STD)
+
+
+ /* Debug Interrupt */
+ DEBUG_EXCEPTION
+
+/*
+ * Local functions
+ */
+ /*
+ * Data TLB exceptions will bail out to this point
+ * if they can't resolve the lightweight TLB fault.
+ */
+data_access:
+ NORMAL_EXCEPTION_PROLOG
+ mfspr r5,SPRN_ESR /* Grab the ESR, save it, pass arg3 */
+ stw r5,_ESR(r11)
+ mfspr r4,SPRN_DEAR /* Grab the DEAR, save it, pass arg2 */
+ andis. r10,r5,(ESR_ILK|ESR_DLK)@h
+ bne 1f
+ EXC_XFER_EE_LITE(0x0300, handle_page_fault)
+1:
+ addi r3,r1,STACK_FRAME_OVERHEAD
+ EXC_XFER_EE_LITE(0x0300, CacheLockingException)
+
+/*
+
+ * Both the instruction and data TLB miss get to this
+ * point to load the TLB.
+ * r10 - EA of fault
+ * r11 - TLB (info from Linux PTE)
+ * r12, r13 - available to use
+ * CR5 - results of addr < TASK_SIZE
+ * MAS0, MAS1 - loaded with proper value when we get here
+ * MAS2, MAS3 - will need additional info from Linux PTE
+ * Upon exit, we reload everything and RFI.
+ */
+finish_tlb_load:
+ /*
+ * We set execute, because we don't have the granularity to
+ * properly set this at the page level (Linux problem).
+ * Many of these bits are software only. Bits we don't set
+ * here we (properly should) assume have the appropriate value.
+ */
+
+ mfspr r12, SPRN_MAS2
+ rlwimi r12, r11, 26, 27, 31 /* extract WIMGE from pte */
+ mtspr SPRN_MAS2, r12
+
+ bge 5, 1f
+
+ /* addr > TASK_SIZE */
+ li r10, (MAS3_UX | MAS3_UW | MAS3_UR)
+ andi. r13, r11, (_PAGE_USER | _PAGE_HWWRITE | _PAGE_HWEXEC)
+ andi. r12, r11, _PAGE_USER /* Test for _PAGE_USER */
+ iseleq r12, 0, r10
+ and r10, r12, r13
+ srwi r12, r10, 1
+ or r12, r12, r10 /* Copy user perms into supervisor */
+ b 2f
+
+ /* addr <= TASK_SIZE */
+1: rlwinm r12, r11, 31, 29, 29 /* Extract _PAGE_HWWRITE into SW */
+ ori r12, r12, (MAS3_SX | MAS3_SR)
+
+2: rlwimi r11, r12, 0, 20, 31 /* Extract RPN from PTE and merge with perms */
+ mtspr SPRN_MAS3, r11
+ tlbwe
+
+ /* Done...restore registers and get out of here. */
+ mfspr r11, SPRN_SPRG7R
+ mtcr r11
+ mfspr r13, SPRN_SPRG5R
+ mfspr r12, SPRN_SPRG4R
+ mfspr r11, SPRN_SPRG1
+ mfspr r10, SPRN_SPRG0
+ rfi /* Force context change */
+
+#ifdef CONFIG_SPE
+/* Note that the SPE support is closely modeled after the AltiVec
+ * support. Changes to one are likely to be applicable to the
+ * other! */
+load_up_spe:
+/*
+ * Disable SPE for the task which had SPE previously,
+ * and save its SPE registers in its thread_struct.
+ * Enables SPE for use in the kernel on return.
+ * On SMP we know the SPE units are free, since we give it up every
+ * switch. -- Kumar
+ */
+ mfmsr r5
+ oris r5,r5,MSR_SPE@h
+ mtmsr r5 /* enable use of SPE now */
+ isync
+/*
+ * For SMP, we don't do lazy SPE switching because it just gets too
+ * horrendously complex, especially when a task switches from one CPU
+ * to another. Instead we call giveup_spe in switch_to.
+ */
+#ifndef CONFIG_SMP
+ lis r3,last_task_used_spe@ha
+ lwz r4,last_task_used_spe@l(r3)
+ cmpi 0,r4,0
+ beq 1f
+ addi r4,r4,THREAD /* want THREAD of last_task_used_spe */
+ SAVE_32EVR(0,r10,r4)
+ evxor evr10, evr10, evr10 /* clear out evr10 */
+ evmwumiaa evr10, evr10, evr10 /* evr10 <- ACC = 0 * 0 + ACC */
+ li r5,THREAD_ACC
+ evstddx evr10, r4, r5 /* save off accumulator */
+ lwz r5,PT_REGS(r4)
+ lwz r4,_MSR-STACK_FRAME_OVERHEAD(r5)
+ lis r10,MSR_SPE@h
+ andc r4,r4,r10 /* disable SPE for previous task */
+ stw r4,_MSR-STACK_FRAME_OVERHEAD(r5)
+1:
+#endif /* CONFIG_SMP */
+ /* enable use of SPE after return */
+ oris r9,r9,MSR_SPE@h
+ mfspr r5,SPRN_SPRG3 /* current task's THREAD (phys) */
+ li r4,1
+ li r10,THREAD_ACC
+ stw r4,THREAD_USED_SPE(r5)
+ evlddx evr4,r10,r5
+ evmra evr4,evr4
+ REST_32EVR(0,r10,r5)
+#ifndef CONFIG_SMP
+ subi r4,r5,THREAD
+ stw r4,last_task_used_spe@l(r3)
+#endif /* CONFIG_SMP */
+ /* restore registers and return */
+2: REST_4GPRS(3, r11)
+ lwz r10,_CCR(r11)
+ REST_GPR(1, r11)
+ mtcr r10
+ lwz r10,_LINK(r11)
+ mtlr r10
+ REST_GPR(10, r11)
+ mtspr SPRN_SRR1,r9
+ mtspr SPRN_SRR0,r12
+ REST_GPR(9, r11)
+ REST_GPR(12, r11)
+ lwz r11,GPR11(r11)
+ SYNC
+ rfi
+
+/*
+ * SPE unavailable trap from kernel - print a message, but let
+ * the task use SPE in the kernel until it returns to user mode.
+ */
+KernelSPE:
+ lwz r3,_MSR(r1)
+ oris r3,r3,MSR_SPE@h
+ stw r3,_MSR(r1) /* enable use of SPE after return */
+ lis r3,87f@h
+ ori r3,r3,87f@l
+ mr r4,r2 /* current */
+ lwz r5,_NIP(r1)
+ bl printk
+ b ret_from_except
+87: .string "SPE used in kernel (task=%p, pc=%x) \n"
+ .align 4,0
+
+#endif /* CONFIG_SPE */
+
+/*
+ * Global functions
+ */
+
+/*
+ * extern void loadcam_entry(unsigned int index)
+ *
+ * Load TLBCAM[index] entry in to the L2 CAM MMU
+ */
+_GLOBAL(loadcam_entry)
+ lis r4,TLBCAM@ha
+ addi r4,r4,TLBCAM@l
+ mulli r5,r3,20
+ add r3,r5,r4
+ lwz r4,0(r3)
+ mtspr SPRN_MAS0,r4
+ lwz r4,4(r3)
+ mtspr SPRN_MAS1,r4
+ lwz r4,8(r3)
+ mtspr SPRN_MAS2,r4
+ lwz r4,12(r3)
+ mtspr SPRN_MAS3,r4
+ tlbwe
+ isync
+ blr
+
+/*
+ * extern void giveup_altivec(struct task_struct *prev)
+ *
+ * The e500 core does not have an AltiVec unit.
+ */
+_GLOBAL(giveup_altivec)
+ blr
+
+#ifdef CONFIG_SPE
+/*
+ * extern void giveup_spe(struct task_struct *prev)
+ *
+ */
+_GLOBAL(giveup_spe)
+ mfmsr r5
+ oris r5,r5,MSR_SPE@h
+ SYNC
+ mtmsr r5 /* enable use of SPE now */
+ isync
+ cmpi 0,r3,0
+ beqlr- /* if no previous owner, done */
+ addi r3,r3,THREAD /* want THREAD of task */
+ lwz r5,PT_REGS(r3)
+ cmpi 0,r5,0
+ SAVE_32EVR(0, r4, r3)
+ evxor evr6, evr6, evr6 /* clear out evr6 */
+ evmwumiaa evr6, evr6, evr6 /* evr6 <- ACC = 0 * 0 + ACC */
+ li r4,THREAD_ACC
+ evstddx evr6, r4, r3 /* save off accumulator */
+ mfspr r6,SPRN_SPEFSCR
+ stw r6,THREAD_SPEFSCR(r3) /* save spefscr register value */
+ beq 1f
+ lwz r4,_MSR-STACK_FRAME_OVERHEAD(r5)
+ lis r3,MSR_SPE@h
+ andc r4,r4,r3 /* disable SPE for previous task */
+ stw r4,_MSR-STACK_FRAME_OVERHEAD(r5)
+1:
+#ifndef CONFIG_SMP
+ li r5,0
+ lis r4,last_task_used_spe@ha
+ stw r5,last_task_used_spe@l(r4)
+#endif /* CONFIG_SMP */
+ blr
+#endif /* CONFIG_SPE */
+
+/*
+ * extern void giveup_fpu(struct task_struct *prev)
+ *
+ * The e500 core does not have an FPU.
+ */
+_GLOBAL(giveup_fpu)
+ blr
+
+/*
+ * extern void abort(void)
+ *
+ * At present, this routine just applies a system reset.
+ */
+_GLOBAL(abort)
+ li r13,0
+ mtspr SPRN_DBCR0,r13 /* disable all debug events */
+ mfmsr r13
+ ori r13,r13,MSR_DE@l /* Enable Debug Events */
+ mtmsr r13
+ mfspr r13,SPRN_DBCR0
+ lis r13,(DBCR0_IDM|DBCR0_RST_CHIP)@h
+ mtspr SPRN_DBCR0,r13
+
+_GLOBAL(set_context)
+
+#ifdef CONFIG_BDI_SWITCH
+ /* Context switch the PTE pointer for the Abatron BDI2000.
+ * The PGDIR is the second parameter.
+ */
+ lis r5, abatron_pteptrs@h
+ ori r5, r5, abatron_pteptrs@l
+ stw r4, 0x4(r5)
+#endif
+ mtspr SPRN_PID,r3
+ isync /* Force context change */
+ blr
+
+/*
+ * We put a few things here that have to be page-aligned. This stuff
+ * goes at the beginning of the data segment, which is page-aligned.
+ */
+ .data
+_GLOBAL(sdata)
+_GLOBAL(empty_zero_page)
+ .space 4096
+_GLOBAL(swapper_pg_dir)
+ .space 4096
+
+/* Reserved 4k for the critical exception stack & 4k for the machine
+ * check stack per CPU for kernel mode exceptions */
+ .section .bss
+ .align 12
+exception_stack_bottom:
+ .space BOOKE_EXCEPTION_STACK_SIZE * NR_CPUS
+_GLOBAL(exception_stack_top)
+
+/*
+ * This space gets a copy of optional info passed to us by the bootstrap
+ * which is used to pass parameters into the kernel like root=/dev/sda1, etc.
+ */
+_GLOBAL(cmd_line)
+ .space 512
+
+/*
+ * Room for two PTE pointers, usually the kernel and current user pointers
+ * to their respective root page table.
+ */
+abatron_pteptrs:
+ .space 8
+
diff --git a/arch/ppc/kernel/idle.c b/arch/ppc/kernel/idle.c
new file mode 100644
index 0000000..53547b6
--- /dev/null
+++ b/arch/ppc/kernel/idle.c
@@ -0,0 +1,100 @@
+/*
+ * Idle daemon for PowerPC. Idle daemon will handle any action
+ * that needs to be taken when the system becomes idle.
+ *
+ * Written by Cort Dougan (cort@cs.nmt.edu). Subsequently hacked
+ * on by Tom Rini, Armin Kuster, Paul Mackerras and others.
+ *
+ * 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.
+ */
+#include <linux/config.h>
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/smp.h>
+#include <linux/smp_lock.h>
+#include <linux/stddef.h>
+#include <linux/unistd.h>
+#include <linux/ptrace.h>
+#include <linux/slab.h>
+#include <linux/sysctl.h>
+
+#include <asm/pgtable.h>
+#include <asm/uaccess.h>
+#include <asm/system.h>
+#include <asm/io.h>
+#include <asm/mmu.h>
+#include <asm/cache.h>
+#include <asm/cputable.h>
+#include <asm/machdep.h>
+
+void default_idle(void)
+{
+ void (*powersave)(void);
+
+ powersave = ppc_md.power_save;
+
+ if (!need_resched()) {
+ if (powersave != NULL)
+ powersave();
+#ifdef CONFIG_SMP
+ else {
+ set_thread_flag(TIF_POLLING_NRFLAG);
+ while (!need_resched())
+ barrier();
+ clear_thread_flag(TIF_POLLING_NRFLAG);
+ }
+#endif
+ }
+ if (need_resched())
+ schedule();
+}
+
+/*
+ * The body of the idle task.
+ */
+void cpu_idle(void)
+{
+ for (;;)
+ if (ppc_md.idle != NULL)
+ ppc_md.idle();
+ else
+ default_idle();
+}
+
+#if defined(CONFIG_SYSCTL) && defined(CONFIG_6xx)
+/*
+ * Register the sysctl to set/clear powersave_nap.
+ */
+extern unsigned long powersave_nap;
+
+static ctl_table powersave_nap_ctl_table[]={
+ {
+ .ctl_name = KERN_PPC_POWERSAVE_NAP,
+ .procname = "powersave-nap",
+ .data = &powersave_nap,
+ .maxlen = sizeof(int),
+ .mode = 0644,
+ .proc_handler = &proc_dointvec,
+ },
+ { 0, },
+};
+static ctl_table powersave_nap_sysctl_root[] = {
+ { 1, "kernel", NULL, 0, 0755, powersave_nap_ctl_table, },
+ { 0,},
+};
+
+static int __init
+register_powersave_nap_sysctl(void)
+{
+ register_sysctl_table(powersave_nap_sysctl_root, 0);
+
+ return 0;
+}
+
+__initcall(register_powersave_nap_sysctl);
+#endif
diff --git a/arch/ppc/kernel/idle_6xx.S b/arch/ppc/kernel/idle_6xx.S
new file mode 100644
index 0000000..25d009c
--- /dev/null
+++ b/arch/ppc/kernel/idle_6xx.S
@@ -0,0 +1,233 @@
+/*
+ * This file contains the power_save function for 6xx & 7xxx CPUs
+ * rewritten in assembler
+ *
+ * Warning ! This code assumes that if your machine has a 750fx
+ * it will have PLL 1 set to low speed mode (used during NAP/DOZE).
+ * if this is not the case some additional changes will have to
+ * be done to check a runtime var (a bit like powersave-nap)
+ *
+ * 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.
+ */
+
+#include <linux/config.h>
+#include <linux/threads.h>
+#include <asm/processor.h>
+#include <asm/page.h>
+#include <asm/cputable.h>
+#include <asm/thread_info.h>
+#include <asm/ppc_asm.h>
+#include <asm/offsets.h>
+
+#undef DEBUG
+
+ .text
+
+/*
+ * Init idle, called at early CPU setup time from head.S for each CPU
+ * Make sure no rest of NAP mode remains in HID0, save default
+ * values for some CPU specific registers. Called with r24
+ * containing CPU number and r3 reloc offset
+ */
+_GLOBAL(init_idle_6xx)
+BEGIN_FTR_SECTION
+ mfspr r4,SPRN_HID0
+ rlwinm r4,r4,0,10,8 /* Clear NAP */
+ mtspr SPRN_HID0, r4
+ b 1f
+END_FTR_SECTION_IFSET(CPU_FTR_CAN_NAP)
+ blr
+1:
+ slwi r5,r24,2
+ add r5,r5,r3
+BEGIN_FTR_SECTION
+ mfspr r4,SPRN_MSSCR0
+ addis r6,r5, nap_save_msscr0@ha
+ stw r4,nap_save_msscr0@l(r6)
+END_FTR_SECTION_IFSET(CPU_FTR_NAP_DISABLE_L2_PR)
+BEGIN_FTR_SECTION
+ mfspr r4,SPRN_HID1
+ addis r6,r5,nap_save_hid1@ha
+ stw r4,nap_save_hid1@l(r6)
+END_FTR_SECTION_IFSET(CPU_FTR_DUAL_PLL_750FX)
+ blr
+
+/*
+ * Here is the power_save_6xx function. This could eventually be
+ * split into several functions & changing the function pointer
+ * depending on the various features.
+ */
+_GLOBAL(ppc6xx_idle)
+ /* Check if we can nap or doze, put HID0 mask in r3
+ */
+ lis r3, 0
+BEGIN_FTR_SECTION
+ lis r3,HID0_DOZE@h
+END_FTR_SECTION_IFSET(CPU_FTR_CAN_DOZE)
+BEGIN_FTR_SECTION
+ /* We must dynamically check for the NAP feature as it
+ * can be cleared by CPU init after the fixups are done
+ */
+ lis r4,cur_cpu_spec@ha
+ lwz r4,cur_cpu_spec@l(r4)
+ lwz r4,CPU_SPEC_FEATURES(r4)
+ andi. r0,r4,CPU_FTR_CAN_NAP
+ beq 1f
+ /* Now check if user or arch enabled NAP mode */
+ lis r4,powersave_nap@ha
+ lwz r4,powersave_nap@l(r4)
+ cmpwi 0,r4,0
+ beq 1f
+ lis r3,HID0_NAP@h
+1:
+END_FTR_SECTION_IFSET(CPU_FTR_CAN_NAP)
+ cmpwi 0,r3,0
+ beqlr
+
+ /* Clear MSR:EE */
+ mfmsr r7
+ rlwinm r0,r7,0,17,15
+ mtmsr r0
+
+ /* Check current_thread_info()->flags */
+ rlwinm r4,r1,0,0,18
+ lwz r4,TI_FLAGS(r4)
+ andi. r0,r4,_TIF_NEED_RESCHED
+ beq 1f
+ mtmsr r7 /* out of line this ? */
+ blr
+1:
+ /* Some pre-nap cleanups needed on some CPUs */
+ andis. r0,r3,HID0_NAP@h
+ beq 2f
+BEGIN_FTR_SECTION
+ /* Disable L2 prefetch on some 745x and try to ensure
+ * L2 prefetch engines are idle. As explained by errata
+ * text, we can't be sure they are, we just hope very hard
+ * that well be enough (sic !). At least I noticed Apple
+ * doesn't even bother doing the dcbf's here...
+ */
+ mfspr r4,SPRN_MSSCR0
+ rlwinm r4,r4,0,0,29
+ sync
+ mtspr SPRN_MSSCR0,r4
+ sync
+ isync
+ lis r4,KERNELBASE@h
+ dcbf 0,r4
+ dcbf 0,r4
+ dcbf 0,r4
+ dcbf 0,r4
+END_FTR_SECTION_IFSET(CPU_FTR_NAP_DISABLE_L2_PR)
+#ifdef DEBUG
+ lis r6,nap_enter_count@ha
+ lwz r4,nap_enter_count@l(r6)
+ addi r4,r4,1
+ stw r4,nap_enter_count@l(r6)
+#endif
+2:
+BEGIN_FTR_SECTION
+ /* Go to low speed mode on some 750FX */
+ lis r4,powersave_lowspeed@ha
+ lwz r4,powersave_lowspeed@l(r4)
+ cmpwi 0,r4,0
+ beq 1f
+ mfspr r4,SPRN_HID1
+ oris r4,r4,0x0001
+ mtspr SPRN_HID1,r4
+1:
+END_FTR_SECTION_IFSET(CPU_FTR_DUAL_PLL_750FX)
+
+ /* Go to NAP or DOZE now */
+ mfspr r4,SPRN_HID0
+ lis r5,(HID0_NAP|HID0_SLEEP)@h
+BEGIN_FTR_SECTION
+ oris r5,r5,HID0_DOZE@h
+END_FTR_SECTION_IFSET(CPU_FTR_CAN_DOZE)
+ andc r4,r4,r5
+ or r4,r4,r3
+BEGIN_FTR_SECTION
+ oris r4,r4,HID0_DPM@h /* that should be done once for all */
+END_FTR_SECTION_IFCLR(CPU_FTR_NO_DPM)
+ mtspr SPRN_HID0,r4
+BEGIN_FTR_SECTION
+ DSSALL
+ sync
+END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
+ ori r7,r7,MSR_EE /* Could be ommited (already set) */
+ oris r7,r7,MSR_POW@h
+ sync
+ isync
+ mtmsr r7
+ isync
+ sync
+ blr
+
+/*
+ * Return from NAP/DOZE mode, restore some CPU specific registers,
+ * we are called with DR/IR still off and r2 containing physical
+ * address of current.
+ */
+_GLOBAL(power_save_6xx_restore)
+ mfspr r11,SPRN_HID0
+ rlwinm. r11,r11,0,10,8 /* Clear NAP & copy NAP bit !state to cr1 EQ */
+ cror 4*cr1+eq,4*cr0+eq,4*cr0+eq
+BEGIN_FTR_SECTION
+ rlwinm r11,r11,0,9,7 /* Clear DOZE */
+END_FTR_SECTION_IFSET(CPU_FTR_CAN_DOZE)
+ mtspr SPRN_HID0, r11
+
+#ifdef DEBUG
+ beq cr1,1f
+ lis r11,(nap_return_count-KERNELBASE)@ha
+ lwz r9,nap_return_count@l(r11)
+ addi r9,r9,1
+ stw r9,nap_return_count@l(r11)
+1:
+#endif
+
+ rlwinm r9,r1,0,0,18
+ tophys(r9,r9)
+ lwz r11,TI_CPU(r9)
+ slwi r11,r11,2
+ /* Todo make sure all these are in the same page
+ * and load r22 (@ha part + CPU offset) only once
+ */
+BEGIN_FTR_SECTION
+ beq cr1,1f
+ addis r9,r11,(nap_save_msscr0-KERNELBASE)@ha
+ lwz r9,nap_save_msscr0@l(r9)
+ mtspr SPRN_MSSCR0, r9
+ sync
+ isync
+1:
+END_FTR_SECTION_IFSET(CPU_FTR_NAP_DISABLE_L2_PR)
+BEGIN_FTR_SECTION
+ addis r9,r11,(nap_save_hid1-KERNELBASE)@ha
+ lwz r9,nap_save_hid1@l(r9)
+ mtspr SPRN_HID1, r9
+END_FTR_SECTION_IFSET(CPU_FTR_DUAL_PLL_750FX)
+ b transfer_to_handler_cont
+
+ .data
+
+_GLOBAL(nap_save_msscr0)
+ .space 4*NR_CPUS
+
+_GLOBAL(nap_save_hid1)
+ .space 4*NR_CPUS
+
+_GLOBAL(powersave_nap)
+ .long 0
+_GLOBAL(powersave_lowspeed)
+ .long 0
+
+#ifdef DEBUG
+_GLOBAL(nap_enter_count)
+ .space 4
+_GLOBAL(nap_return_count)
+ .space 4
+#endif
diff --git a/arch/ppc/kernel/idle_power4.S b/arch/ppc/kernel/idle_power4.S
new file mode 100644
index 0000000..73a58ff
--- /dev/null
+++ b/arch/ppc/kernel/idle_power4.S
@@ -0,0 +1,91 @@
+/*
+ * This file contains the power_save function for 6xx & 7xxx CPUs
+ * rewritten in assembler
+ *
+ * Warning ! This code assumes that if your machine has a 750fx
+ * it will have PLL 1 set to low speed mode (used during NAP/DOZE).
+ * if this is not the case some additional changes will have to
+ * be done to check a runtime var (a bit like powersave-nap)
+ *
+ * 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.
+ */
+
+#include <linux/config.h>
+#include <linux/threads.h>
+#include <asm/processor.h>
+#include <asm/page.h>
+#include <asm/cputable.h>
+#include <asm/thread_info.h>
+#include <asm/ppc_asm.h>
+#include <asm/offsets.h>
+
+#undef DEBUG
+
+ .text
+
+/*
+ * Init idle, called at early CPU setup time from head.S for each CPU
+ * So nothing for now. Called with r24 containing CPU number and r3
+ * reloc offset
+ */
+ .globl init_idle_power4
+init_idle_power4:
+ blr
+
+/*
+ * Here is the power_save_6xx function. This could eventually be
+ * split into several functions & changing the function pointer
+ * depending on the various features.
+ */
+ .globl power4_idle
+power4_idle:
+BEGIN_FTR_SECTION
+ blr
+END_FTR_SECTION_IFCLR(CPU_FTR_CAN_NAP)
+ /* We must dynamically check for the NAP feature as it
+ * can be cleared by CPU init after the fixups are done
+ */
+ lis r4,cur_cpu_spec@ha
+ lwz r4,cur_cpu_spec@l(r4)
+ lwz r4,CPU_SPEC_FEATURES(r4)
+ andi. r0,r4,CPU_FTR_CAN_NAP
+ beqlr
+ /* Now check if user or arch enabled NAP mode */
+ lis r4,powersave_nap@ha
+ lwz r4,powersave_nap@l(r4)
+ cmpwi 0,r4,0
+ beqlr
+
+ /* Clear MSR:EE */
+ mfmsr r7
+ rlwinm r0,r7,0,17,15
+ mtmsr r0
+
+ /* Check current_thread_info()->flags */
+ rlwinm r4,r1,0,0,18
+ lwz r4,TI_FLAGS(r4)
+ andi. r0,r4,_TIF_NEED_RESCHED
+ beq 1f
+ mtmsr r7 /* out of line this ? */
+ blr
+1:
+ /* Go to NAP now */
+BEGIN_FTR_SECTION
+ DSSALL
+ sync
+END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
+ ori r7,r7,MSR_EE /* Could be ommited (already set) */
+ oris r7,r7,MSR_POW@h
+ sync
+ isync
+ mtmsr r7
+ isync
+ sync
+ blr
+
+ .globl powersave_nap
+powersave_nap:
+ .long 0
diff --git a/arch/ppc/kernel/irq.c b/arch/ppc/kernel/irq.c
new file mode 100644
index 0000000..8843f3a
--- /dev/null
+++ b/arch/ppc/kernel/irq.c
@@ -0,0 +1,164 @@
+/*
+ * arch/ppc/kernel/irq.c
+ *
+ * Derived from arch/i386/kernel/irq.c
+ * Copyright (C) 1992 Linus Torvalds
+ * Adapted from arch/i386 by Gary Thomas
+ * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
+ * Updated and modified by Cort Dougan <cort@fsmlabs.com>
+ * Copyright (C) 1996-2001 Cort Dougan
+ * Adapted for Power Macintosh by Paul Mackerras
+ * Copyright (C) 1996 Paul Mackerras (paulus@cs.anu.edu.au)
+ * Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk).
+ *
+ * This file contains the code used by various IRQ handling routines:
+ * asking for different IRQ's should be done through these routines
+ * instead of just grabbing them. Thus setups with different IRQ numbers
+ * shouldn't result in any weird surprises, and installing new handlers
+ * should be easier.
+ *
+ * The MPC8xx has an interrupt mask in the SIU. If a bit is set, the
+ * interrupt is _enabled_. As expected, IRQ0 is bit 0 in the 32-bit
+ * mask register (of which only 16 are defined), hence the weird shifting
+ * and complement of the cached_irq_mask. I want to be able to stuff
+ * this right into the SIU SMASK register.
+ * Many of the prep/chrp functions are conditional compiled on CONFIG_8xx
+ * to reduce code space and undefined function references.
+ */
+
+#include <linux/errno.h>
+#include <linux/module.h>
+#include <linux/threads.h>
+#include <linux/kernel_stat.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/ptrace.h>
+#include <linux/ioport.h>
+#include <linux/interrupt.h>
+#include <linux/timex.h>
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/pci.h>
+#include <linux/delay.h>
+#include <linux/irq.h>
+#include <linux/proc_fs.h>
+#include <linux/random.h>
+#include <linux/seq_file.h>
+#include <linux/cpumask.h>
+#include <linux/profile.h>
+#include <linux/bitops.h>
+
+#include <asm/uaccess.h>
+#include <asm/system.h>
+#include <asm/io.h>
+#include <asm/pgtable.h>
+#include <asm/irq.h>
+#include <asm/cache.h>
+#include <asm/prom.h>
+#include <asm/ptrace.h>
+
+#define NR_MASK_WORDS ((NR_IRQS + 31) / 32)
+
+extern atomic_t ipi_recv;
+extern atomic_t ipi_sent;
+
+#define MAXCOUNT 10000000
+
+int ppc_spurious_interrupts = 0;
+struct irqaction *ppc_irq_action[NR_IRQS];
+unsigned long ppc_cached_irq_mask[NR_MASK_WORDS];
+unsigned long ppc_lost_interrupts[NR_MASK_WORDS];
+atomic_t ppc_n_lost_interrupts;
+
+#ifdef CONFIG_TAU_INT
+extern int tau_initialized;
+extern int tau_interrupts(int);
+#endif
+
+int show_interrupts(struct seq_file *p, void *v)
+{
+ int i = *(loff_t *) v, j;
+ struct irqaction * action;
+ unsigned long flags;
+
+ if (i == 0) {
+ seq_puts(p, " ");
+ for (j=0; j<NR_CPUS; j++)
+ if (cpu_online(j))
+ seq_printf(p, "CPU%d ", j);
+ seq_putc(p, '\n');
+ }
+
+ if (i < NR_IRQS) {
+ spin_lock_irqsave(&irq_desc[i].lock, flags);
+ action = irq_desc[i].action;
+ if ( !action || !action->handler )
+ goto skip;
+ seq_printf(p, "%3d: ", i);
+#ifdef CONFIG_SMP
+ for (j = 0; j < NR_CPUS; j++)
+ if (cpu_online(j))
+ seq_printf(p, "%10u ",
+ kstat_cpu(j).irqs[i]);
+#else
+ seq_printf(p, "%10u ", kstat_irqs(i));
+#endif /* CONFIG_SMP */
+ if (irq_desc[i].handler)
+ seq_printf(p, " %s ", irq_desc[i].handler->typename);
+ else
+ seq_puts(p, " None ");
+ seq_printf(p, "%s", (irq_desc[i].status & IRQ_LEVEL) ? "Level " : "Edge ");
+ seq_printf(p, " %s", action->name);
+ for (action = action->next; action; action = action->next)
+ seq_printf(p, ", %s", action->name);
+ seq_putc(p, '\n');
+skip:
+ spin_unlock_irqrestore(&irq_desc[i].lock, flags);
+ } else if (i == NR_IRQS) {
+#ifdef CONFIG_TAU_INT
+ if (tau_initialized){
+ seq_puts(p, "TAU: ");
+ for (j = 0; j < NR_CPUS; j++)
+ if (cpu_online(j))
+ seq_printf(p, "%10u ", tau_interrupts(j));
+ seq_puts(p, " PowerPC Thermal Assist (cpu temp)\n");
+ }
+#endif
+#ifdef CONFIG_SMP
+ /* should this be per processor send/receive? */
+ seq_printf(p, "IPI (recv/sent): %10u/%u\n",
+ atomic_read(&ipi_recv), atomic_read(&ipi_sent));
+#endif
+ seq_printf(p, "BAD: %10u\n", ppc_spurious_interrupts);
+ }
+ return 0;
+}
+
+void do_IRQ(struct pt_regs *regs)
+{
+ int irq, first = 1;
+ irq_enter();
+
+ /*
+ * Every platform is required to implement ppc_md.get_irq.
+ * This function will either return an irq number or -1 to
+ * indicate there are no more pending. But the first time
+ * through the loop this means there wasn't and IRQ pending.
+ * The value -2 is for buggy hardware and means that this IRQ
+ * has already been handled. -- Tom
+ */
+ while ((irq = ppc_md.get_irq(regs)) >= 0) {
+ __do_IRQ(irq, regs);
+ first = 0;
+ }
+ if (irq != -2 && first)
+ /* That's not SMP safe ... but who cares ? */
+ ppc_spurious_interrupts++;
+ irq_exit();
+}
+
+void __init init_IRQ(void)
+{
+ ppc_md.init_IRQ();
+}
diff --git a/arch/ppc/kernel/l2cr.S b/arch/ppc/kernel/l2cr.S
new file mode 100644
index 0000000..c394410
--- /dev/null
+++ b/arch/ppc/kernel/l2cr.S
@@ -0,0 +1,442 @@
+/*
+ L2CR functions
+ Copyright © 1997-1998 by PowerLogix R & D, Inc.
+
+ 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+/*
+ Thur, Dec. 12, 1998.
+ - First public release, contributed by PowerLogix.
+ ***********
+ Sat, Aug. 7, 1999.
+ - Terry: Made sure code disabled interrupts before running. (Previously
+ it was assumed interrupts were already disabled).
+ - Terry: Updated for tentative G4 support. 4MB of memory is now flushed
+ instead of 2MB. (Prob. only 3 is necessary).
+ - Terry: Updated for workaround to HID0[DPM] processor bug
+ during global invalidates.
+ ***********
+ Thu, July 13, 2000.
+ - Terry: Added isync to correct for an errata.
+
+ 22 August 2001.
+ - DanM: Finally added the 7450 patch I've had for the past
+ several months. The L2CR is similar, but I'm going
+ to assume the user of this functions knows what they
+ are doing.
+
+ Author: Terry Greeniaus (tgree@phys.ualberta.ca)
+ Please e-mail updates to this file to me, thanks!
+*/
+#include <linux/config.h>
+#include <asm/processor.h>
+#include <asm/cputable.h>
+#include <asm/ppc_asm.h>
+#include <asm/cache.h>
+#include <asm/page.h>
+
+/* Usage:
+
+ When setting the L2CR register, you must do a few special
+ things. If you are enabling the cache, you must perform a
+ global invalidate. If you are disabling the cache, you must
+ flush the cache contents first. This routine takes care of
+ doing these things. When first enabling the cache, make sure
+ you pass in the L2CR you want, as well as passing in the
+ global invalidate bit set. A global invalidate will only be
+ performed if the L2I bit is set in applyThis. When enabling
+ the cache, you should also set the L2E bit in applyThis. If
+ you want to modify the L2CR contents after the cache has been
+ enabled, the recommended procedure is to first call
+ __setL2CR(0) to disable the cache and then call it again with
+ the new values for L2CR. Examples:
+
+ _setL2CR(0) - disables the cache
+ _setL2CR(0xB3A04000) - enables my G3 upgrade card:
+ - L2E set to turn on the cache
+ - L2SIZ set to 1MB
+ - L2CLK set to 1:1
+ - L2RAM set to pipelined synchronous late-write
+ - L2I set to perform a global invalidation
+ - L2OH set to 0.5 nS
+ - L2DF set because this upgrade card
+ requires it
+
+ A similar call should work for your card. You need to know
+ the correct setting for your card and then place them in the
+ fields I have outlined above. Other fields support optional
+ features, such as L2DO which caches only data, or L2TS which
+ causes cache pushes from the L1 cache to go to the L2 cache
+ instead of to main memory.
+
+IMPORTANT:
+ Starting with the 7450, the bits in this register have moved
+ or behave differently. The Enable, Parity Enable, Size,
+ and L2 Invalidate are the only bits that have not moved.
+ The size is read-only for these processors with internal L2
+ cache, and the invalidate is a control as well as status.
+ -- Dan
+
+*/
+/*
+ * Summary: this procedure ignores the L2I bit in the value passed in,
+ * flushes the cache if it was already enabled, always invalidates the
+ * cache, then enables the cache if the L2E bit is set in the value
+ * passed in.
+ * -- paulus.
+ */
+_GLOBAL(_set_L2CR)
+ /* Make sure this is a 750 or 7400 chip */
+BEGIN_FTR_SECTION
+ li r3,-1
+ blr
+END_FTR_SECTION_IFCLR(CPU_FTR_L2CR)
+
+ mflr r9
+
+ /* Stop DST streams */
+BEGIN_FTR_SECTION
+ DSSALL
+ sync
+END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
+
+ /* Turn off interrupts and data relocation. */
+ mfmsr r7 /* Save MSR in r7 */
+ rlwinm r4,r7,0,17,15
+ rlwinm r4,r4,0,28,26 /* Turn off DR bit */
+ sync
+ mtmsr r4
+ isync
+
+ /* Before we perform the global invalidation, we must disable dynamic
+ * power management via HID0[DPM] to work around a processor bug where
+ * DPM can possibly interfere with the state machine in the processor
+ * that invalidates the L2 cache tags.
+ */
+ mfspr r8,SPRN_HID0 /* Save HID0 in r8 */
+ rlwinm r4,r8,0,12,10 /* Turn off HID0[DPM] */
+ sync
+ mtspr SPRN_HID0,r4 /* Disable DPM */
+ sync
+
+ /* Get the current enable bit of the L2CR into r4 */
+ mfspr r4,SPRN_L2CR
+
+ /* Tweak some bits */
+ rlwinm r5,r3,0,0,0 /* r5 contains the new enable bit */
+ rlwinm r3,r3,0,11,9 /* Turn off the invalidate bit */
+ rlwinm r3,r3,0,1,31 /* Turn off the enable bit */
+
+ /* Check to see if we need to flush */
+ rlwinm. r4,r4,0,0,0
+ beq 2f
+
+ /* Flush the cache. First, read the first 4MB of memory (physical) to
+ * put new data in the cache. (Actually we only need
+ * the size of the L2 cache plus the size of the L1 cache, but 4MB will
+ * cover everything just to be safe).
+ */
+
+ /**** Might be a good idea to set L2DO here - to prevent instructions
+ from getting into the cache. But since we invalidate
+ the next time we enable the cache it doesn't really matter.
+ Don't do this unless you accomodate all processor variations.
+ The bit moved on the 7450.....
+ ****/
+
+ /* TODO: use HW flush assist when available */
+
+ lis r4,0x0002
+ mtctr r4
+ li r4,0
+1:
+ lwzx r0,r0,r4
+ addi r4,r4,32 /* Go to start of next cache line */
+ bdnz 1b
+ isync
+
+ /* Now, flush the first 4MB of memory */
+ lis r4,0x0002
+ mtctr r4
+ li r4,0
+ sync
+1:
+ dcbf 0,r4
+ addi r4,r4,32 /* Go to start of next cache line */
+ bdnz 1b
+
+2:
+ /* Set up the L2CR configuration bits (and switch L2 off) */
+ /* CPU errata: Make sure the mtspr below is already in the
+ * L1 icache
+ */
+ b 20f
+ .balign L1_CACHE_LINE_SIZE
+22:
+ sync
+ mtspr SPRN_L2CR,r3
+ sync
+ b 23f
+20:
+ b 21f
+21: sync
+ isync
+ b 22b
+
+23:
+ /* Perform a global invalidation */
+ oris r3,r3,0x0020
+ sync
+ mtspr SPRN_L2CR,r3
+ sync
+ isync /* For errata */
+
+BEGIN_FTR_SECTION
+ /* On the 7450, we wait for the L2I bit to clear......
+ */
+10: mfspr r3,SPRN_L2CR
+ andis. r4,r3,0x0020
+ bne 10b
+ b 11f
+END_FTR_SECTION_IFSET(CPU_FTR_SPEC7450)
+
+ /* Wait for the invalidation to complete */
+3: mfspr r3,SPRN_L2CR
+ rlwinm. r4,r3,0,31,31
+ bne 3b
+
+11: rlwinm r3,r3,0,11,9 /* Turn off the L2I bit */
+ sync
+ mtspr SPRN_L2CR,r3
+ sync
+
+ /* See if we need to enable the cache */
+ cmplwi r5,0
+ beq 4f
+
+ /* Enable the cache */
+ oris r3,r3,0x8000
+ mtspr SPRN_L2CR,r3
+ sync
+
+4:
+
+ /* Restore HID0[DPM] to whatever it was before */
+ sync
+ mtspr 1008,r8
+ sync
+
+ /* Restore MSR (restores EE and DR bits to original state) */
+ SYNC
+ mtmsr r7
+ isync
+
+ mtlr r9
+ blr
+
+_GLOBAL(_get_L2CR)
+ /* Return the L2CR contents */
+ li r3,0
+BEGIN_FTR_SECTION
+ mfspr r3,SPRN_L2CR
+END_FTR_SECTION_IFSET(CPU_FTR_L2CR)
+ blr
+
+
+/*
+ * Here is a similar routine for dealing with the L3 cache
+ * on the 745x family of chips
+ */
+
+_GLOBAL(_set_L3CR)
+ /* Make sure this is a 745x chip */
+BEGIN_FTR_SECTION
+ li r3,-1
+ blr
+END_FTR_SECTION_IFCLR(CPU_FTR_L3CR)
+
+ /* Turn off interrupts and data relocation. */
+ mfmsr r7 /* Save MSR in r7 */
+ rlwinm r4,r7,0,17,15
+ rlwinm r4,r4,0,28,26 /* Turn off DR bit */
+ sync
+ mtmsr r4
+ isync
+
+ /* Stop DST streams */
+ DSSALL
+ sync
+
+ /* Get the current enable bit of the L3CR into r4 */
+ mfspr r4,SPRN_L3CR
+
+ /* Tweak some bits */
+ rlwinm r5,r3,0,0,0 /* r5 contains the new enable bit */
+ rlwinm r3,r3,0,22,20 /* Turn off the invalidate bit */
+ rlwinm r3,r3,0,2,31 /* Turn off the enable & PE bits */
+ rlwinm r3,r3,0,5,3 /* Turn off the clken bit */
+ /* Check to see if we need to flush */
+ rlwinm. r4,r4,0,0,0
+ beq 2f
+
+ /* Flush the cache.
+ */
+
+ /* TODO: use HW flush assist */
+
+ lis r4,0x0008
+ mtctr r4
+ li r4,0
+1:
+ lwzx r0,r0,r4
+ dcbf 0,r4
+ addi r4,r4,32 /* Go to start of next cache line */
+ bdnz 1b
+
+2:
+ /* Set up the L3CR configuration bits (and switch L3 off) */
+ sync
+ mtspr SPRN_L3CR,r3
+ sync
+
+ oris r3,r3,L3CR_L3RES@h /* Set reserved bit 5 */
+ mtspr SPRN_L3CR,r3
+ sync
+ oris r3,r3,L3CR_L3CLKEN@h /* Set clken */
+ mtspr SPRN_L3CR,r3
+ sync
+
+ /* Wait for stabilize */
+ li r0,256
+ mtctr r0
+1: bdnz 1b
+
+ /* Perform a global invalidation */
+ ori r3,r3,0x0400
+ sync
+ mtspr SPRN_L3CR,r3
+ sync
+ isync
+
+ /* We wait for the L3I bit to clear...... */
+10: mfspr r3,SPRN_L3CR
+ andi. r4,r3,0x0400
+ bne 10b
+
+ /* Clear CLKEN */
+ rlwinm r3,r3,0,5,3 /* Turn off the clken bit */
+ mtspr SPRN_L3CR,r3
+ sync
+
+ /* Wait for stabilize */
+ li r0,256
+ mtctr r0
+1: bdnz 1b
+
+ /* See if we need to enable the cache */
+ cmplwi r5,0
+ beq 4f
+
+ /* Enable the cache */
+ oris r3,r3,(L3CR_L3E | L3CR_L3CLKEN)@h
+ mtspr SPRN_L3CR,r3
+ sync
+
+ /* Wait for stabilize */
+ li r0,256
+ mtctr r0
+1: bdnz 1b
+
+ /* Restore MSR (restores EE and DR bits to original state) */
+4: SYNC
+ mtmsr r7
+ isync
+ blr
+
+_GLOBAL(_get_L3CR)
+ /* Return the L3CR contents */
+ li r3,0
+BEGIN_FTR_SECTION
+ mfspr r3,SPRN_L3CR
+END_FTR_SECTION_IFSET(CPU_FTR_L3CR)
+ blr
+
+/* --- End of PowerLogix code ---
+ */
+
+
+/* flush_disable_L1() - Flush and disable L1 cache
+ *
+ * clobbers r0, r3, ctr, cr0
+ * Must be called with interrupts disabled and MMU enabled.
+ */
+_GLOBAL(__flush_disable_L1)
+ /* Stop pending alitvec streams and memory accesses */
+BEGIN_FTR_SECTION
+ DSSALL
+END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
+ sync
+
+ /* Load counter to 0x4000 cache lines (512k) and
+ * load cache with datas
+ */
+ li r3,0x4000 /* 512kB / 32B */
+ mtctr r3
+ lis r3,KERNELBASE@h
+1:
+ lwz r0,0(r3)
+ addi r3,r3,0x0020 /* Go to start of next cache line */
+ bdnz 1b
+ isync
+ sync
+
+ /* Now flush those cache lines */
+ li r3,0x4000 /* 512kB / 32B */
+ mtctr r3
+ lis r3,KERNELBASE@h
+1:
+ dcbf 0,r3
+ addi r3,r3,0x0020 /* Go to start of next cache line */
+ bdnz 1b
+ sync
+
+ /* We can now disable the L1 cache (HID0:DCE, HID0:ICE) */
+ mfspr r3,SPRN_HID0
+ rlwinm r3,r3,0,18,15
+ mtspr SPRN_HID0,r3
+ sync
+ isync
+ blr
+
+/* inval_enable_L1 - Invalidate and enable L1 cache
+ *
+ * Assumes L1 is already disabled and MSR:EE is off
+ *
+ * clobbers r3
+ */
+_GLOBAL(__inval_enable_L1)
+ /* Enable and then Flash inval the instruction & data cache */
+ mfspr r3,SPRN_HID0
+ ori r3,r3, HID0_ICE|HID0_ICFI|HID0_DCE|HID0_DCI
+ sync
+ isync
+ mtspr SPRN_HID0,r3
+ xori r3,r3, HID0_ICFI|HID0_DCI
+ mtspr SPRN_HID0,r3
+ sync
+
+ blr
+
+
diff --git a/arch/ppc/kernel/misc.S b/arch/ppc/kernel/misc.S
new file mode 100644
index 0000000..73f7c23
--- /dev/null
+++ b/arch/ppc/kernel/misc.S
@@ -0,0 +1,1453 @@
+/*
+ * This file contains miscellaneous low-level functions.
+ * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
+ *
+ * Largely rewritten by Cort Dougan (cort@cs.nmt.edu)
+ * and Paul Mackerras.
+ *
+ * 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.
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/sys.h>
+#include <asm/unistd.h>
+#include <asm/errno.h>
+#include <asm/processor.h>
+#include <asm/page.h>
+#include <asm/cache.h>
+#include <asm/cputable.h>
+#include <asm/mmu.h>
+#include <asm/ppc_asm.h>
+#include <asm/thread_info.h>
+#include <asm/offsets.h>
+
+ .text
+
+ .align 5
+_GLOBAL(__delay)
+ cmpwi 0,r3,0
+ mtctr r3
+ beqlr
+1: bdnz 1b
+ blr
+
+/*
+ * Returns (address we're running at) - (address we were linked at)
+ * for use before the text and data are mapped to KERNELBASE.
+ */
+_GLOBAL(reloc_offset)
+ mflr r0
+ bl 1f
+1: mflr r3
+ lis r4,1b@ha
+ addi r4,r4,1b@l
+ subf r3,r4,r3
+ mtlr r0
+ blr
+
+/*
+ * add_reloc_offset(x) returns x + reloc_offset().
+ */
+_GLOBAL(add_reloc_offset)
+ mflr r0
+ bl 1f
+1: mflr r5
+ lis r4,1b@ha
+ addi r4,r4,1b@l
+ subf r5,r4,r5
+ add r3,r3,r5
+ mtlr r0
+ blr
+
+/*
+ * sub_reloc_offset(x) returns x - reloc_offset().
+ */
+_GLOBAL(sub_reloc_offset)
+ mflr r0
+ bl 1f
+1: mflr r5
+ lis r4,1b@ha
+ addi r4,r4,1b@l
+ subf r5,r4,r5
+ subf r3,r5,r3
+ mtlr r0
+ blr
+
+/*
+ * reloc_got2 runs through the .got2 section adding an offset
+ * to each entry.
+ */
+_GLOBAL(reloc_got2)
+ mflr r11
+ lis r7,__got2_start@ha
+ addi r7,r7,__got2_start@l
+ lis r8,__got2_end@ha
+ addi r8,r8,__got2_end@l
+ subf r8,r7,r8
+ srwi. r8,r8,2
+ beqlr
+ mtctr r8
+ bl 1f
+1: mflr r0
+ lis r4,1b@ha
+ addi r4,r4,1b@l
+ subf r0,r4,r0
+ add r7,r0,r7
+2: lwz r0,0(r7)
+ add r0,r0,r3
+ stw r0,0(r7)
+ addi r7,r7,4
+ bdnz 2b
+ mtlr r11
+ blr
+
+/*
+ * identify_cpu,
+ * called with r3 = data offset and r4 = CPU number
+ * doesn't change r3
+ */
+_GLOBAL(identify_cpu)
+ addis r8,r3,cpu_specs@ha
+ addi r8,r8,cpu_specs@l
+ mfpvr r7
+1:
+ lwz r5,CPU_SPEC_PVR_MASK(r8)
+ and r5,r5,r7
+ lwz r6,CPU_SPEC_PVR_VALUE(r8)
+ cmplw 0,r6,r5
+ beq 1f
+ addi r8,r8,CPU_SPEC_ENTRY_SIZE
+ b 1b
+1:
+ addis r6,r3,cur_cpu_spec@ha
+ addi r6,r6,cur_cpu_spec@l
+ slwi r4,r4,2
+ sub r8,r8,r3
+ stwx r8,r4,r6
+ blr
+
+/*
+ * do_cpu_ftr_fixups - goes through the list of CPU feature fixups
+ * and writes nop's over sections of code that don't apply for this cpu.
+ * r3 = data offset (not changed)
+ */
+_GLOBAL(do_cpu_ftr_fixups)
+ /* Get CPU 0 features */
+ addis r6,r3,cur_cpu_spec@ha
+ addi r6,r6,cur_cpu_spec@l
+ lwz r4,0(r6)
+ add r4,r4,r3
+ lwz r4,CPU_SPEC_FEATURES(r4)
+
+ /* Get the fixup table */
+ addis r6,r3,__start___ftr_fixup@ha
+ addi r6,r6,__start___ftr_fixup@l
+ addis r7,r3,__stop___ftr_fixup@ha
+ addi r7,r7,__stop___ftr_fixup@l
+
+ /* Do the fixup */
+1: cmplw 0,r6,r7
+ bgelr
+ addi r6,r6,16
+ lwz r8,-16(r6) /* mask */
+ and r8,r8,r4
+ lwz r9,-12(r6) /* value */
+ cmplw 0,r8,r9
+ beq 1b
+ lwz r8,-8(r6) /* section begin */
+ lwz r9,-4(r6) /* section end */
+ subf. r9,r8,r9
+ beq 1b
+ /* write nops over the section of code */
+ /* todo: if large section, add a branch at the start of it */
+ srwi r9,r9,2
+ mtctr r9
+ add r8,r8,r3
+ lis r0,0x60000000@h /* nop */
+3: stw r0,0(r8)
+ andi. r10,r4,CPU_FTR_SPLIT_ID_CACHE@l
+ beq 2f
+ dcbst 0,r8 /* suboptimal, but simpler */
+ sync
+ icbi 0,r8
+2: addi r8,r8,4
+ bdnz 3b
+ sync /* additional sync needed on g4 */
+ isync
+ b 1b
+
+/*
+ * call_setup_cpu - call the setup_cpu function for this cpu
+ * r3 = data offset, r24 = cpu number
+ *
+ * Setup function is called with:
+ * r3 = data offset
+ * r4 = CPU number
+ * r5 = ptr to CPU spec (relocated)
+ */
+_GLOBAL(call_setup_cpu)
+ addis r5,r3,cur_cpu_spec@ha
+ addi r5,r5,cur_cpu_spec@l
+ slwi r4,r24,2
+ lwzx r5,r4,r5
+ add r5,r5,r3
+ lwz r6,CPU_SPEC_SETUP(r5)
+ add r6,r6,r3
+ mtctr r6
+ mr r4,r24
+ bctr
+
+#if defined(CONFIG_CPU_FREQ_PMAC) && defined(CONFIG_6xx)
+
+/* This gets called by via-pmu.c to switch the PLL selection
+ * on 750fx CPU. This function should really be moved to some
+ * other place (as most of the cpufreq code in via-pmu
+ */
+_GLOBAL(low_choose_750fx_pll)
+ /* Clear MSR:EE */
+ mfmsr r7
+ rlwinm r0,r7,0,17,15
+ mtmsr r0
+
+ /* If switching to PLL1, disable HID0:BTIC */
+ cmplwi cr0,r3,0
+ beq 1f
+ mfspr r5,SPRN_HID0
+ rlwinm r5,r5,0,27,25
+ sync
+ mtspr SPRN_HID0,r5
+ isync
+ sync
+
+1:
+ /* Calc new HID1 value */
+ mfspr r4,SPRN_HID1 /* Build a HID1:PS bit from parameter */
+ rlwinm r5,r3,16,15,15 /* Clear out HID1:PS from value read */
+ rlwinm r4,r4,0,16,14 /* Could have I used rlwimi here ? */
+ or r4,r4,r5
+ mtspr SPRN_HID1,r4
+
+ /* Store new HID1 image */
+ rlwinm r6,r1,0,0,18
+ lwz r6,TI_CPU(r6)
+ slwi r6,r6,2
+ addis r6,r6,nap_save_hid1@ha
+ stw r4,nap_save_hid1@l(r6)
+
+ /* If switching to PLL0, enable HID0:BTIC */
+ cmplwi cr0,r3,0
+ bne 1f
+ mfspr r5,SPRN_HID0
+ ori r5,r5,HID0_BTIC
+ sync
+ mtspr SPRN_HID0,r5
+ isync
+ sync
+
+1:
+ /* Return */
+ mtmsr r7
+ blr
+
+_GLOBAL(low_choose_7447a_dfs)
+ /* Clear MSR:EE */
+ mfmsr r7
+ rlwinm r0,r7,0,17,15
+ mtmsr r0
+
+ /* Calc new HID1 value */
+ mfspr r4,SPRN_HID1
+ insrwi r4,r3,1,9 /* insert parameter into bit 9 */
+ sync
+ mtspr SPRN_HID1,r4
+ sync
+ isync
+
+ /* Return */
+ mtmsr r7
+ blr
+
+#endif /* CONFIG_CPU_FREQ_PMAC && CONFIG_6xx */
+
+/* void local_save_flags_ptr(unsigned long *flags) */
+_GLOBAL(local_save_flags_ptr)
+ mfmsr r4
+ stw r4,0(r3)
+ blr
+ /*
+ * Need these nops here for taking over save/restore to
+ * handle lost intrs
+ * -- Cort
+ */
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+_GLOBAL(local_save_flags_ptr_end)
+
+/* void local_irq_restore(unsigned long flags) */
+_GLOBAL(local_irq_restore)
+/*
+ * Just set/clear the MSR_EE bit through restore/flags but do not
+ * change anything else. This is needed by the RT system and makes
+ * sense anyway.
+ * -- Cort
+ */
+ mfmsr r4
+ /* Copy all except the MSR_EE bit from r4 (current MSR value)
+ to r3. This is the sort of thing the rlwimi instruction is
+ designed for. -- paulus. */
+ rlwimi r3,r4,0,17,15
+ /* Check if things are setup the way we want _already_. */
+ cmpw 0,r3,r4
+ beqlr
+1: SYNC
+ mtmsr r3
+ SYNC
+ blr
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+_GLOBAL(local_irq_restore_end)
+
+_GLOBAL(local_irq_disable)
+ mfmsr r0 /* Get current interrupt state */
+ rlwinm r3,r0,16+1,32-1,31 /* Extract old value of 'EE' */
+ rlwinm r0,r0,0,17,15 /* clear MSR_EE in r0 */
+ SYNC /* Some chip revs have problems here... */
+ mtmsr r0 /* Update machine state */
+ blr /* Done */
+ /*
+ * Need these nops here for taking over save/restore to
+ * handle lost intrs
+ * -- Cort
+ */
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+_GLOBAL(local_irq_disable_end)
+
+_GLOBAL(local_irq_enable)
+ mfmsr r3 /* Get current state */
+ ori r3,r3,MSR_EE /* Turn on 'EE' bit */
+ SYNC /* Some chip revs have problems here... */
+ mtmsr r3 /* Update machine state */
+ blr
+ /*
+ * Need these nops here for taking over save/restore to
+ * handle lost intrs
+ * -- Cort
+ */
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+_GLOBAL(local_irq_enable_end)
+
+/*
+ * complement mask on the msr then "or" some values on.
+ * _nmask_and_or_msr(nmask, value_to_or)
+ */
+_GLOBAL(_nmask_and_or_msr)
+ mfmsr r0 /* Get current msr */
+ andc r0,r0,r3 /* And off the bits set in r3 (first parm) */
+ or r0,r0,r4 /* Or on the bits in r4 (second parm) */
+ SYNC /* Some chip revs have problems here... */
+ mtmsr r0 /* Update machine state */
+ isync
+ blr /* Done */
+
+
+/*
+ * Flush MMU TLB
+ */
+_GLOBAL(_tlbia)
+#if defined(CONFIG_40x)
+ sync /* Flush to memory before changing mapping */
+ tlbia
+ isync /* Flush shadow TLB */
+#elif defined(CONFIG_44x)
+ li r3,0
+ sync
+
+ /* Load high watermark */
+ lis r4,tlb_44x_hwater@ha
+ lwz r5,tlb_44x_hwater@l(r4)
+
+1: tlbwe r3,r3,PPC44x_TLB_PAGEID
+ addi r3,r3,1
+ cmpw 0,r3,r5
+ ble 1b
+
+ isync
+#elif defined(CONFIG_FSL_BOOKE)
+ /* Invalidate all entries in TLB0 */
+ li r3, 0x04
+ tlbivax 0,3
+ /* Invalidate all entries in TLB1 */
+ li r3, 0x0c
+ tlbivax 0,3
+ /* Invalidate all entries in TLB2 */
+ li r3, 0x14
+ tlbivax 0,3
+ /* Invalidate all entries in TLB3 */
+ li r3, 0x1c
+ tlbivax 0,3
+ msync
+#ifdef CONFIG_SMP
+ tlbsync
+#endif /* CONFIG_SMP */
+#else /* !(CONFIG_40x || CONFIG_44x || CONFIG_FSL_BOOKE) */
+#if defined(CONFIG_SMP)
+ rlwinm r8,r1,0,0,18
+ lwz r8,TI_CPU(r8)
+ oris r8,r8,10
+ mfmsr r10
+ SYNC
+ rlwinm r0,r10,0,17,15 /* clear bit 16 (MSR_EE) */
+ rlwinm r0,r0,0,28,26 /* clear DR */
+ mtmsr r0
+ SYNC_601
+ isync
+ lis r9,mmu_hash_lock@h
+ ori r9,r9,mmu_hash_lock@l
+ tophys(r9,r9)
+10: lwarx r7,0,r9
+ cmpwi 0,r7,0
+ bne- 10b
+ stwcx. r8,0,r9
+ bne- 10b
+ sync
+ tlbia
+ sync
+ TLBSYNC
+ li r0,0
+ stw r0,0(r9) /* clear mmu_hash_lock */
+ mtmsr r10
+ SYNC_601
+ isync
+#else /* CONFIG_SMP */
+ sync
+ tlbia
+ sync
+#endif /* CONFIG_SMP */
+#endif /* ! defined(CONFIG_40x) */
+ blr
+
+/*
+ * Flush MMU TLB for a particular address
+ */
+_GLOBAL(_tlbie)
+#if defined(CONFIG_40x)
+ tlbsx. r3, 0, r3
+ bne 10f
+ sync
+ /* There are only 64 TLB entries, so r3 < 64, which means bit 25 is clear.
+ * Since 25 is the V bit in the TLB_TAG, loading this value will invalidate
+ * the TLB entry. */
+ tlbwe r3, r3, TLB_TAG
+ isync
+10:
+#elif defined(CONFIG_44x)
+ mfspr r4,SPRN_MMUCR
+ mfspr r5,SPRN_PID /* Get PID */
+ rlwimi r4,r5,0,24,31 /* Set TID */
+ mtspr SPRN_MMUCR,r4
+
+ tlbsx. r3, 0, r3
+ bne 10f
+ sync
+ /* There are only 64 TLB entries, so r3 < 64,
+ * which means bit 22, is clear. Since 22 is
+ * the V bit in the TLB_PAGEID, loading this
+ * value will invalidate the TLB entry.
+ */
+ tlbwe r3, r3, PPC44x_TLB_PAGEID
+ isync
+10:
+#elif defined(CONFIG_FSL_BOOKE)
+ rlwinm r4, r3, 0, 0, 19
+ ori r5, r4, 0x08 /* TLBSEL = 1 */
+ ori r6, r4, 0x10 /* TLBSEL = 2 */
+ ori r7, r4, 0x18 /* TLBSEL = 3 */
+ tlbivax 0, r4
+ tlbivax 0, r5
+ tlbivax 0, r6
+ tlbivax 0, r7
+ msync
+#if defined(CONFIG_SMP)
+ tlbsync
+#endif /* CONFIG_SMP */
+#else /* !(CONFIG_40x || CONFIG_44x || CONFIG_FSL_BOOKE) */
+#if defined(CONFIG_SMP)
+ rlwinm r8,r1,0,0,18
+ lwz r8,TI_CPU(r8)
+ oris r8,r8,11
+ mfmsr r10
+ SYNC
+ rlwinm r0,r10,0,17,15 /* clear bit 16 (MSR_EE) */
+ rlwinm r0,r0,0,28,26 /* clear DR */
+ mtmsr r0
+ SYNC_601
+ isync
+ lis r9,mmu_hash_lock@h
+ ori r9,r9,mmu_hash_lock@l
+ tophys(r9,r9)
+10: lwarx r7,0,r9
+ cmpwi 0,r7,0
+ bne- 10b
+ stwcx. r8,0,r9
+ bne- 10b
+ eieio
+ tlbie r3
+ sync
+ TLBSYNC
+ li r0,0
+ stw r0,0(r9) /* clear mmu_hash_lock */
+ mtmsr r10
+ SYNC_601
+ isync
+#else /* CONFIG_SMP */
+ tlbie r3
+ sync
+#endif /* CONFIG_SMP */
+#endif /* ! CONFIG_40x */
+ blr
+
+/*
+ * Flush instruction cache.
+ * This is a no-op on the 601.
+ */
+_GLOBAL(flush_instruction_cache)
+#if defined(CONFIG_8xx)
+ isync
+ lis r5, IDC_INVALL@h
+ mtspr SPRN_IC_CST, r5
+#elif defined(CONFIG_4xx)
+#ifdef CONFIG_403GCX
+ li r3, 512
+ mtctr r3
+ lis r4, KERNELBASE@h
+1: iccci 0, r4
+ addi r4, r4, 16
+ bdnz 1b
+#else
+ lis r3, KERNELBASE@h
+ iccci 0,r3
+#endif
+#elif CONFIG_FSL_BOOKE
+ mfspr r3,SPRN_L1CSR1
+ ori r3,r3,L1CSR1_ICFI|L1CSR1_ICLFR
+ mtspr SPRN_L1CSR1,r3
+#else
+ mfspr r3,SPRN_PVR
+ rlwinm r3,r3,16,16,31
+ cmpwi 0,r3,1
+ beqlr /* for 601, do nothing */
+ /* 603/604 processor - use invalidate-all bit in HID0 */
+ mfspr r3,SPRN_HID0
+ ori r3,r3,HID0_ICFI
+ mtspr SPRN_HID0,r3
+#endif /* CONFIG_8xx/4xx */
+ isync
+ blr
+
+/*
+ * Write any modified data cache blocks out to memory
+ * and invalidate the corresponding instruction cache blocks.
+ * This is a no-op on the 601.
+ *
+ * flush_icache_range(unsigned long start, unsigned long stop)
+ */
+_GLOBAL(flush_icache_range)
+BEGIN_FTR_SECTION
+ blr /* for 601, do nothing */
+END_FTR_SECTION_IFSET(PPC_FEATURE_UNIFIED_CACHE)
+ li r5,L1_CACHE_LINE_SIZE-1
+ andc r3,r3,r5
+ subf r4,r3,r4
+ add r4,r4,r5
+ srwi. r4,r4,LG_L1_CACHE_LINE_SIZE
+ beqlr
+ mtctr r4
+ mr r6,r3
+1: dcbst 0,r3
+ addi r3,r3,L1_CACHE_LINE_SIZE
+ bdnz 1b
+ sync /* wait for dcbst's to get to ram */
+ mtctr r4
+2: icbi 0,r6
+ addi r6,r6,L1_CACHE_LINE_SIZE
+ bdnz 2b
+ sync /* additional sync needed on g4 */
+ isync
+ blr
+/*
+ * Write any modified data cache blocks out to memory.
+ * Does not invalidate the corresponding cache lines (especially for
+ * any corresponding instruction cache).
+ *
+ * clean_dcache_range(unsigned long start, unsigned long stop)
+ */
+_GLOBAL(clean_dcache_range)
+ li r5,L1_CACHE_LINE_SIZE-1
+ andc r3,r3,r5
+ subf r4,r3,r4
+ add r4,r4,r5
+ srwi. r4,r4,LG_L1_CACHE_LINE_SIZE
+ beqlr
+ mtctr r4
+
+1: dcbst 0,r3
+ addi r3,r3,L1_CACHE_LINE_SIZE
+ bdnz 1b
+ sync /* wait for dcbst's to get to ram */
+ blr
+
+/*
+ * Write any modified data cache blocks out to memory and invalidate them.
+ * Does not invalidate the corresponding instruction cache blocks.
+ *
+ * flush_dcache_range(unsigned long start, unsigned long stop)
+ */
+_GLOBAL(flush_dcache_range)
+ li r5,L1_CACHE_LINE_SIZE-1
+ andc r3,r3,r5
+ subf r4,r3,r4
+ add r4,r4,r5
+ srwi. r4,r4,LG_L1_CACHE_LINE_SIZE
+ beqlr
+ mtctr r4
+
+1: dcbf 0,r3
+ addi r3,r3,L1_CACHE_LINE_SIZE
+ bdnz 1b
+ sync /* wait for dcbst's to get to ram */
+ blr
+
+/*
+ * Like above, but invalidate the D-cache. This is used by the 8xx
+ * to invalidate the cache so the PPC core doesn't get stale data
+ * from the CPM (no cache snooping here :-).
+ *
+ * invalidate_dcache_range(unsigned long start, unsigned long stop)
+ */
+_GLOBAL(invalidate_dcache_range)
+ li r5,L1_CACHE_LINE_SIZE-1
+ andc r3,r3,r5
+ subf r4,r3,r4
+ add r4,r4,r5
+ srwi. r4,r4,LG_L1_CACHE_LINE_SIZE
+ beqlr
+ mtctr r4
+
+1: dcbi 0,r3
+ addi r3,r3,L1_CACHE_LINE_SIZE
+ bdnz 1b
+ sync /* wait for dcbi's to get to ram */
+ blr
+
+#ifdef CONFIG_NOT_COHERENT_CACHE
+/*
+ * 40x cores have 8K or 16K dcache and 32 byte line size.
+ * 44x has a 32K dcache and 32 byte line size.
+ * 8xx has 1, 2, 4, 8K variants.
+ * For now, cover the worst case of the 44x.
+ * Must be called with external interrupts disabled.
+ */
+#define CACHE_NWAYS 64
+#define CACHE_NLINES 16
+
+_GLOBAL(flush_dcache_all)
+ li r4, (2 * CACHE_NWAYS * CACHE_NLINES)
+ mtctr r4
+ lis r5, KERNELBASE@h
+1: lwz r3, 0(r5) /* Load one word from every line */
+ addi r5, r5, L1_CACHE_LINE_SIZE
+ bdnz 1b
+ blr
+#endif /* CONFIG_NOT_COHERENT_CACHE */
+
+/*
+ * Flush a particular page from the data cache to RAM.
+ * Note: this is necessary because the instruction cache does *not*
+ * snoop from the data cache.
+ * This is a no-op on the 601 which has a unified cache.
+ *
+ * void __flush_dcache_icache(void *page)
+ */
+_GLOBAL(__flush_dcache_icache)
+BEGIN_FTR_SECTION
+ blr /* for 601, do nothing */
+END_FTR_SECTION_IFSET(PPC_FEATURE_UNIFIED_CACHE)
+ rlwinm r3,r3,0,0,19 /* Get page base address */
+ li r4,4096/L1_CACHE_LINE_SIZE /* Number of lines in a page */
+ mtctr r4
+ mr r6,r3
+0: dcbst 0,r3 /* Write line to ram */
+ addi r3,r3,L1_CACHE_LINE_SIZE
+ bdnz 0b
+ sync
+ mtctr r4
+1: icbi 0,r6
+ addi r6,r6,L1_CACHE_LINE_SIZE
+ bdnz 1b
+ sync
+ isync
+ blr
+
+/*
+ * Flush a particular page from the data cache to RAM, identified
+ * by its physical address. We turn off the MMU so we can just use
+ * the physical address (this may be a highmem page without a kernel
+ * mapping).
+ *
+ * void __flush_dcache_icache_phys(unsigned long physaddr)
+ */
+_GLOBAL(__flush_dcache_icache_phys)
+BEGIN_FTR_SECTION
+ blr /* for 601, do nothing */
+END_FTR_SECTION_IFSET(PPC_FEATURE_UNIFIED_CACHE)
+ mfmsr r10
+ rlwinm r0,r10,0,28,26 /* clear DR */
+ mtmsr r0
+ isync
+ rlwinm r3,r3,0,0,19 /* Get page base address */
+ li r4,4096/L1_CACHE_LINE_SIZE /* Number of lines in a page */
+ mtctr r4
+ mr r6,r3
+0: dcbst 0,r3 /* Write line to ram */
+ addi r3,r3,L1_CACHE_LINE_SIZE
+ bdnz 0b
+ sync
+ mtctr r4
+1: icbi 0,r6
+ addi r6,r6,L1_CACHE_LINE_SIZE
+ bdnz 1b
+ sync
+ mtmsr r10 /* restore DR */
+ isync
+ blr
+
+/*
+ * Clear pages using the dcbz instruction, which doesn't cause any
+ * memory traffic (except to write out any cache lines which get
+ * displaced). This only works on cacheable memory.
+ *
+ * void clear_pages(void *page, int order) ;
+ */
+_GLOBAL(clear_pages)
+ li r0,4096/L1_CACHE_LINE_SIZE
+ slw r0,r0,r4
+ mtctr r0
+#ifdef CONFIG_8xx
+ li r4, 0
+1: stw r4, 0(r3)
+ stw r4, 4(r3)
+ stw r4, 8(r3)
+ stw r4, 12(r3)
+#else
+1: dcbz 0,r3
+#endif
+ addi r3,r3,L1_CACHE_LINE_SIZE
+ bdnz 1b
+ blr
+
+/*
+ * Copy a whole page. We use the dcbz instruction on the destination
+ * to reduce memory traffic (it eliminates the unnecessary reads of
+ * the destination into cache). This requires that the destination
+ * is cacheable.
+ */
+#define COPY_16_BYTES \
+ lwz r6,4(r4); \
+ lwz r7,8(r4); \
+ lwz r8,12(r4); \
+ lwzu r9,16(r4); \
+ stw r6,4(r3); \
+ stw r7,8(r3); \
+ stw r8,12(r3); \
+ stwu r9,16(r3)
+
+_GLOBAL(copy_page)
+ addi r3,r3,-4
+ addi r4,r4,-4
+
+#ifdef CONFIG_8xx
+ /* don't use prefetch on 8xx */
+ li r0,4096/L1_CACHE_LINE_SIZE
+ mtctr r0
+1: COPY_16_BYTES
+ bdnz 1b
+ blr
+
+#else /* not 8xx, we can prefetch */
+ li r5,4
+
+#if MAX_COPY_PREFETCH > 1
+ li r0,MAX_COPY_PREFETCH
+ li r11,4
+ mtctr r0
+11: dcbt r11,r4
+ addi r11,r11,L1_CACHE_LINE_SIZE
+ bdnz 11b
+#else /* MAX_COPY_PREFETCH == 1 */
+ dcbt r5,r4
+ li r11,L1_CACHE_LINE_SIZE+4
+#endif /* MAX_COPY_PREFETCH */
+ li r0,4096/L1_CACHE_LINE_SIZE - MAX_COPY_PREFETCH
+ crclr 4*cr0+eq
+2:
+ mtctr r0
+1:
+ dcbt r11,r4
+ dcbz r5,r3
+ COPY_16_BYTES
+#if L1_CACHE_LINE_SIZE >= 32
+ COPY_16_BYTES
+#if L1_CACHE_LINE_SIZE >= 64
+ COPY_16_BYTES
+ COPY_16_BYTES
+#if L1_CACHE_LINE_SIZE >= 128
+ COPY_16_BYTES
+ COPY_16_BYTES
+ COPY_16_BYTES
+ COPY_16_BYTES
+#endif
+#endif
+#endif
+ bdnz 1b
+ beqlr
+ crnot 4*cr0+eq,4*cr0+eq
+ li r0,MAX_COPY_PREFETCH
+ li r11,4
+ b 2b
+#endif /* CONFIG_8xx */
+
+/*
+ * void atomic_clear_mask(atomic_t mask, atomic_t *addr)
+ * void atomic_set_mask(atomic_t mask, atomic_t *addr);
+ */
+_GLOBAL(atomic_clear_mask)
+10: lwarx r5,0,r4
+ andc r5,r5,r3
+ PPC405_ERR77(0,r4)
+ stwcx. r5,0,r4
+ bne- 10b
+ blr
+_GLOBAL(atomic_set_mask)
+10: lwarx r5,0,r4
+ or r5,r5,r3
+ PPC405_ERR77(0,r4)
+ stwcx. r5,0,r4
+ bne- 10b
+ blr
+
+/*
+ * I/O string operations
+ *
+ * insb(port, buf, len)
+ * outsb(port, buf, len)
+ * insw(port, buf, len)
+ * outsw(port, buf, len)
+ * insl(port, buf, len)
+ * outsl(port, buf, len)
+ * insw_ns(port, buf, len)
+ * outsw_ns(port, buf, len)
+ * insl_ns(port, buf, len)
+ * outsl_ns(port, buf, len)
+ *
+ * The *_ns versions don't do byte-swapping.
+ */
+_GLOBAL(_insb)
+ cmpwi 0,r5,0
+ mtctr r5
+ subi r4,r4,1
+ blelr-
+00: lbz r5,0(r3)
+ eieio
+ stbu r5,1(r4)
+ bdnz 00b
+ blr
+
+_GLOBAL(_outsb)
+ cmpwi 0,r5,0
+ mtctr r5
+ subi r4,r4,1
+ blelr-
+00: lbzu r5,1(r4)
+ stb r5,0(r3)
+ eieio
+ bdnz 00b
+ blr
+
+_GLOBAL(_insw)
+ cmpwi 0,r5,0
+ mtctr r5
+ subi r4,r4,2
+ blelr-
+00: lhbrx r5,0,r3
+ eieio
+ sthu r5,2(r4)
+ bdnz 00b
+ blr
+
+_GLOBAL(_outsw)
+ cmpwi 0,r5,0
+ mtctr r5
+ subi r4,r4,2
+ blelr-
+00: lhzu r5,2(r4)
+ eieio
+ sthbrx r5,0,r3
+ bdnz 00b
+ blr
+
+_GLOBAL(_insl)
+ cmpwi 0,r5,0
+ mtctr r5
+ subi r4,r4,4
+ blelr-
+00: lwbrx r5,0,r3
+ eieio
+ stwu r5,4(r4)
+ bdnz 00b
+ blr
+
+_GLOBAL(_outsl)
+ cmpwi 0,r5,0
+ mtctr r5
+ subi r4,r4,4
+ blelr-
+00: lwzu r5,4(r4)
+ stwbrx r5,0,r3
+ eieio
+ bdnz 00b
+ blr
+
+_GLOBAL(__ide_mm_insw)
+_GLOBAL(_insw_ns)
+ cmpwi 0,r5,0
+ mtctr r5
+ subi r4,r4,2
+ blelr-
+00: lhz r5,0(r3)
+ eieio
+ sthu r5,2(r4)
+ bdnz 00b
+ blr
+
+_GLOBAL(__ide_mm_outsw)
+_GLOBAL(_outsw_ns)
+ cmpwi 0,r5,0
+ mtctr r5
+ subi r4,r4,2
+ blelr-
+00: lhzu r5,2(r4)
+ sth r5,0(r3)
+ eieio
+ bdnz 00b
+ blr
+
+_GLOBAL(__ide_mm_insl)
+_GLOBAL(_insl_ns)
+ cmpwi 0,r5,0
+ mtctr r5
+ subi r4,r4,4
+ blelr-
+00: lwz r5,0(r3)
+ eieio
+ stwu r5,4(r4)
+ bdnz 00b
+ blr
+
+_GLOBAL(__ide_mm_outsl)
+_GLOBAL(_outsl_ns)
+ cmpwi 0,r5,0
+ mtctr r5
+ subi r4,r4,4
+ blelr-
+00: lwzu r5,4(r4)
+ stw r5,0(r3)
+ eieio
+ bdnz 00b
+ blr
+
+/*
+ * Extended precision shifts.
+ *
+ * Updated to be valid for shift counts from 0 to 63 inclusive.
+ * -- Gabriel
+ *
+ * R3/R4 has 64 bit value
+ * R5 has shift count
+ * result in R3/R4
+ *
+ * ashrdi3: arithmetic right shift (sign propagation)
+ * lshrdi3: logical right shift
+ * ashldi3: left shift
+ */
+_GLOBAL(__ashrdi3)
+ subfic r6,r5,32
+ srw r4,r4,r5 # LSW = count > 31 ? 0 : LSW >> count
+ addi r7,r5,32 # could be xori, or addi with -32
+ slw r6,r3,r6 # t1 = count > 31 ? 0 : MSW << (32-count)
+ rlwinm r8,r7,0,32 # t3 = (count < 32) ? 32 : 0
+ sraw r7,r3,r7 # t2 = MSW >> (count-32)
+ or r4,r4,r6 # LSW |= t1
+ slw r7,r7,r8 # t2 = (count < 32) ? 0 : t2
+ sraw r3,r3,r5 # MSW = MSW >> count
+ or r4,r4,r7 # LSW |= t2
+ blr
+
+_GLOBAL(__ashldi3)
+ subfic r6,r5,32
+ slw r3,r3,r5 # MSW = count > 31 ? 0 : MSW << count
+ addi r7,r5,32 # could be xori, or addi with -32
+ srw r6,r4,r6 # t1 = count > 31 ? 0 : LSW >> (32-count)
+ slw r7,r4,r7 # t2 = count < 32 ? 0 : LSW << (count-32)
+ or r3,r3,r6 # MSW |= t1
+ slw r4,r4,r5 # LSW = LSW << count
+ or r3,r3,r7 # MSW |= t2
+ blr
+
+_GLOBAL(__lshrdi3)
+ subfic r6,r5,32
+ srw r4,r4,r5 # LSW = count > 31 ? 0 : LSW >> count
+ addi r7,r5,32 # could be xori, or addi with -32
+ slw r6,r3,r6 # t1 = count > 31 ? 0 : MSW << (32-count)
+ srw r7,r3,r7 # t2 = count < 32 ? 0 : MSW >> (count-32)
+ or r4,r4,r6 # LSW |= t1
+ srw r3,r3,r5 # MSW = MSW >> count
+ or r4,r4,r7 # LSW |= t2
+ blr
+
+_GLOBAL(abs)
+ srawi r4,r3,31
+ xor r3,r3,r4
+ sub r3,r3,r4
+ blr
+
+_GLOBAL(_get_SP)
+ mr r3,r1 /* Close enough */
+ blr
+
+/*
+ * These are used in the alignment trap handler when emulating
+ * single-precision loads and stores.
+ * We restore and save the fpscr so the task gets the same result
+ * and exceptions as if the cpu had performed the load or store.
+ */
+
+#if defined(CONFIG_4xx) || defined(CONFIG_E500)
+_GLOBAL(cvt_fd)
+ lfs 0,0(r3)
+ stfd 0,0(r4)
+ blr
+
+_GLOBAL(cvt_df)
+ lfd 0,0(r3)
+ stfs 0,0(r4)
+ blr
+#else
+_GLOBAL(cvt_fd)
+ lfd 0,-4(r5) /* load up fpscr value */
+ mtfsf 0xff,0
+ lfs 0,0(r3)
+ stfd 0,0(r4)
+ mffs 0 /* save new fpscr value */
+ stfd 0,-4(r5)
+ blr
+
+_GLOBAL(cvt_df)
+ lfd 0,-4(r5) /* load up fpscr value */
+ mtfsf 0xff,0
+ lfd 0,0(r3)
+ stfs 0,0(r4)
+ mffs 0 /* save new fpscr value */
+ stfd 0,-4(r5)
+ blr
+#endif
+
+/*
+ * Create a kernel thread
+ * kernel_thread(fn, arg, flags)
+ */
+_GLOBAL(kernel_thread)
+ stwu r1,-16(r1)
+ stw r30,8(r1)
+ stw r31,12(r1)
+ mr r30,r3 /* function */
+ mr r31,r4 /* argument */
+ ori r3,r5,CLONE_VM /* flags */
+ oris r3,r3,CLONE_UNTRACED>>16
+ li r4,0 /* new sp (unused) */
+ li r0,__NR_clone
+ sc
+ cmpwi 0,r3,0 /* parent or child? */
+ bne 1f /* return if parent */
+ li r0,0 /* make top-level stack frame */
+ stwu r0,-16(r1)
+ mtlr r30 /* fn addr in lr */
+ mr r3,r31 /* load arg and call fn */
+ blrl
+ li r0,__NR_exit /* exit if function returns */
+ li r3,0
+ sc
+1: lwz r30,8(r1)
+ lwz r31,12(r1)
+ addi r1,r1,16
+ blr
+
+/*
+ * This routine is just here to keep GCC happy - sigh...
+ */
+_GLOBAL(__main)
+ blr
+
+#define SYSCALL(name) \
+_GLOBAL(name) \
+ li r0,__NR_##name; \
+ sc; \
+ bnslr; \
+ lis r4,errno@ha; \
+ stw r3,errno@l(r4); \
+ li r3,-1; \
+ blr
+
+SYSCALL(execve)
+
+/* Why isn't this a) automatic, b) written in 'C'? */
+ .data
+ .align 4
+_GLOBAL(sys_call_table)
+ .long sys_restart_syscall /* 0 */
+ .long sys_exit
+ .long ppc_fork
+ .long sys_read
+ .long sys_write
+ .long sys_open /* 5 */
+ .long sys_close
+ .long sys_waitpid
+ .long sys_creat
+ .long sys_link
+ .long sys_unlink /* 10 */
+ .long sys_execve
+ .long sys_chdir
+ .long sys_time
+ .long sys_mknod
+ .long sys_chmod /* 15 */
+ .long sys_lchown
+ .long sys_ni_syscall /* old break syscall holder */
+ .long sys_stat
+ .long sys_lseek
+ .long sys_getpid /* 20 */
+ .long sys_mount
+ .long sys_oldumount
+ .long sys_setuid
+ .long sys_getuid
+ .long sys_stime /* 25 */
+ .long sys_ptrace
+ .long sys_alarm
+ .long sys_fstat
+ .long sys_pause
+ .long sys_utime /* 30 */
+ .long sys_ni_syscall /* old stty syscall holder */
+ .long sys_ni_syscall /* old gtty syscall holder */
+ .long sys_access
+ .long sys_nice
+ .long sys_ni_syscall /* 35 */ /* old ftime syscall holder */
+ .long sys_sync
+ .long sys_kill
+ .long sys_rename
+ .long sys_mkdir
+ .long sys_rmdir /* 40 */
+ .long sys_dup
+ .long sys_pipe
+ .long sys_times
+ .long sys_ni_syscall /* old prof syscall holder */
+ .long sys_brk /* 45 */
+ .long sys_setgid
+ .long sys_getgid
+ .long sys_signal
+ .long sys_geteuid
+ .long sys_getegid /* 50 */
+ .long sys_acct
+ .long sys_umount /* recycled never used phys() */
+ .long sys_ni_syscall /* old lock syscall holder */
+ .long sys_ioctl
+ .long sys_fcntl /* 55 */
+ .long sys_ni_syscall /* old mpx syscall holder */
+ .long sys_setpgid
+ .long sys_ni_syscall /* old ulimit syscall holder */
+ .long sys_olduname
+ .long sys_umask /* 60 */
+ .long sys_chroot
+ .long sys_ustat
+ .long sys_dup2
+ .long sys_getppid
+ .long sys_getpgrp /* 65 */
+ .long sys_setsid
+ .long sys_sigaction
+ .long sys_sgetmask
+ .long sys_ssetmask
+ .long sys_setreuid /* 70 */
+ .long sys_setregid
+ .long ppc_sigsuspend
+ .long sys_sigpending
+ .long sys_sethostname
+ .long sys_setrlimit /* 75 */
+ .long sys_old_getrlimit
+ .long sys_getrusage
+ .long sys_gettimeofday
+ .long sys_settimeofday
+ .long sys_getgroups /* 80 */
+ .long sys_setgroups
+ .long ppc_select
+ .long sys_symlink
+ .long sys_lstat
+ .long sys_readlink /* 85 */
+ .long sys_uselib
+ .long sys_swapon
+ .long sys_reboot
+ .long old_readdir
+ .long sys_mmap /* 90 */
+ .long sys_munmap
+ .long sys_truncate
+ .long sys_ftruncate
+ .long sys_fchmod
+ .long sys_fchown /* 95 */
+ .long sys_getpriority
+ .long sys_setpriority
+ .long sys_ni_syscall /* old profil syscall holder */
+ .long sys_statfs
+ .long sys_fstatfs /* 100 */
+ .long sys_ni_syscall
+ .long sys_socketcall
+ .long sys_syslog
+ .long sys_setitimer
+ .long sys_getitimer /* 105 */
+ .long sys_newstat
+ .long sys_newlstat
+ .long sys_newfstat
+ .long sys_uname
+ .long sys_ni_syscall /* 110 */
+ .long sys_vhangup
+ .long sys_ni_syscall /* old 'idle' syscall */
+ .long sys_ni_syscall
+ .long sys_wait4
+ .long sys_swapoff /* 115 */
+ .long sys_sysinfo
+ .long sys_ipc
+ .long sys_fsync
+ .long sys_sigreturn
+ .long ppc_clone /* 120 */
+ .long sys_setdomainname
+ .long sys_newuname
+ .long sys_ni_syscall
+ .long sys_adjtimex
+ .long sys_mprotect /* 125 */
+ .long sys_sigprocmask
+ .long sys_ni_syscall /* old sys_create_module */
+ .long sys_init_module
+ .long sys_delete_module
+ .long sys_ni_syscall /* old sys_get_kernel_syms */ /* 130 */
+ .long sys_quotactl
+ .long sys_getpgid
+ .long sys_fchdir
+ .long sys_bdflush
+ .long sys_sysfs /* 135 */
+ .long sys_personality
+ .long sys_ni_syscall /* for afs_syscall */
+ .long sys_setfsuid
+ .long sys_setfsgid
+ .long sys_llseek /* 140 */
+ .long sys_getdents
+ .long ppc_select
+ .long sys_flock
+ .long sys_msync
+ .long sys_readv /* 145 */
+ .long sys_writev
+ .long sys_getsid
+ .long sys_fdatasync
+ .long sys_sysctl
+ .long sys_mlock /* 150 */
+ .long sys_munlock
+ .long sys_mlockall
+ .long sys_munlockall
+ .long sys_sched_setparam
+ .long sys_sched_getparam /* 155 */
+ .long sys_sched_setscheduler
+ .long sys_sched_getscheduler
+ .long sys_sched_yield
+ .long sys_sched_get_priority_max
+ .long sys_sched_get_priority_min /* 160 */
+ .long sys_sched_rr_get_interval
+ .long sys_nanosleep
+ .long sys_mremap
+ .long sys_setresuid
+ .long sys_getresuid /* 165 */
+ .long sys_ni_syscall /* old sys_query_module */
+ .long sys_poll
+ .long sys_nfsservctl
+ .long sys_setresgid
+ .long sys_getresgid /* 170 */
+ .long sys_prctl
+ .long sys_rt_sigreturn
+ .long sys_rt_sigaction
+ .long sys_rt_sigprocmask
+ .long sys_rt_sigpending /* 175 */
+ .long sys_rt_sigtimedwait
+ .long sys_rt_sigqueueinfo
+ .long ppc_rt_sigsuspend
+ .long sys_pread64
+ .long sys_pwrite64 /* 180 */
+ .long sys_chown
+ .long sys_getcwd
+ .long sys_capget
+ .long sys_capset
+ .long sys_sigaltstack /* 185 */
+ .long sys_sendfile
+ .long sys_ni_syscall /* streams1 */
+ .long sys_ni_syscall /* streams2 */
+ .long ppc_vfork
+ .long sys_getrlimit /* 190 */
+ .long sys_readahead
+ .long sys_mmap2
+ .long sys_truncate64
+ .long sys_ftruncate64
+ .long sys_stat64 /* 195 */
+ .long sys_lstat64
+ .long sys_fstat64
+ .long sys_pciconfig_read
+ .long sys_pciconfig_write
+ .long sys_pciconfig_iobase /* 200 */
+ .long sys_ni_syscall /* 201 - reserved - MacOnLinux - new */
+ .long sys_getdents64
+ .long sys_pivot_root
+ .long sys_fcntl64
+ .long sys_madvise /* 205 */
+ .long sys_mincore
+ .long sys_gettid
+ .long sys_tkill
+ .long sys_setxattr
+ .long sys_lsetxattr /* 210 */
+ .long sys_fsetxattr
+ .long sys_getxattr
+ .long sys_lgetxattr
+ .long sys_fgetxattr
+ .long sys_listxattr /* 215 */
+ .long sys_llistxattr
+ .long sys_flistxattr
+ .long sys_removexattr
+ .long sys_lremovexattr
+ .long sys_fremovexattr /* 220 */
+ .long sys_futex
+ .long sys_sched_setaffinity
+ .long sys_sched_getaffinity
+ .long sys_ni_syscall
+ .long sys_ni_syscall /* 225 - reserved for Tux */
+ .long sys_sendfile64
+ .long sys_io_setup
+ .long sys_io_destroy
+ .long sys_io_getevents
+ .long sys_io_submit /* 230 */
+ .long sys_io_cancel
+ .long sys_set_tid_address
+ .long sys_fadvise64
+ .long sys_exit_group
+ .long sys_lookup_dcookie /* 235 */
+ .long sys_epoll_create
+ .long sys_epoll_ctl
+ .long sys_epoll_wait
+ .long sys_remap_file_pages
+ .long sys_timer_create /* 240 */
+ .long sys_timer_settime
+ .long sys_timer_gettime
+ .long sys_timer_getoverrun
+ .long sys_timer_delete
+ .long sys_clock_settime /* 245 */
+ .long sys_clock_gettime
+ .long sys_clock_getres
+ .long sys_clock_nanosleep
+ .long ppc_swapcontext
+ .long sys_tgkill /* 250 */
+ .long sys_utimes
+ .long sys_statfs64
+ .long sys_fstatfs64
+ .long ppc_fadvise64_64
+ .long sys_ni_syscall /* 255 - rtas (used on ppc64) */
+ .long sys_debug_setcontext
+ .long sys_ni_syscall /* 257 reserved for vserver */
+ .long sys_ni_syscall /* 258 reserved for new sys_remap_file_pages */
+ .long sys_ni_syscall /* 259 reserved for new sys_mbind */
+ .long sys_ni_syscall /* 260 reserved for new sys_get_mempolicy */
+ .long sys_ni_syscall /* 261 reserved for new sys_set_mempolicy */
+ .long sys_mq_open
+ .long sys_mq_unlink
+ .long sys_mq_timedsend
+ .long sys_mq_timedreceive /* 265 */
+ .long sys_mq_notify
+ .long sys_mq_getsetattr
+ .long sys_ni_syscall /* 268 reserved for sys_kexec_load */
+ .long sys_add_key
+ .long sys_request_key /* 270 */
+ .long sys_keyctl
+ .long sys_waitid
diff --git a/arch/ppc/kernel/module.c b/arch/ppc/kernel/module.c
new file mode 100644
index 0000000..92f4e5f
--- /dev/null
+++ b/arch/ppc/kernel/module.c
@@ -0,0 +1,320 @@
+/* Kernel module help for PPC.
+ Copyright (C) 2001 Rusty Russell.
+
+ 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 <linux/module.h>
+#include <linux/moduleloader.h>
+#include <linux/elf.h>
+#include <linux/vmalloc.h>
+#include <linux/fs.h>
+#include <linux/string.h>
+#include <linux/kernel.h>
+#include <linux/cache.h>
+
+#if 0
+#define DEBUGP printk
+#else
+#define DEBUGP(fmt , ...)
+#endif
+
+LIST_HEAD(module_bug_list);
+
+void *module_alloc(unsigned long size)
+{
+ if (size == 0)
+ return NULL;
+ return vmalloc(size);
+}
+
+/* Free memory returned from module_alloc */
+void module_free(struct module *mod, void *module_region)
+{
+ vfree(module_region);
+ /* FIXME: If module_region == mod->init_region, trim exception
+ table entries. */
+}
+
+/* Count how many different relocations (different symbol, different
+ addend) */
+static unsigned int count_relocs(const Elf32_Rela *rela, unsigned int num)
+{
+ unsigned int i, j, ret = 0;
+
+ /* Sure, this is order(n^2), but it's usually short, and not
+ time critical */
+ for (i = 0; i < num; i++) {
+ for (j = 0; j < i; j++) {
+ /* If this addend appeared before, it's
+ already been counted */
+ if (ELF32_R_SYM(rela[i].r_info)
+ == ELF32_R_SYM(rela[j].r_info)
+ && rela[i].r_addend == rela[j].r_addend)
+ break;
+ }
+ if (j == i) ret++;
+ }
+ return ret;
+}
+
+/* Get the potential trampolines size required of the init and
+ non-init sections */
+static unsigned long get_plt_size(const Elf32_Ehdr *hdr,
+ const Elf32_Shdr *sechdrs,
+ const char *secstrings,
+ int is_init)
+{
+ unsigned long ret = 0;
+ unsigned i;
+
+ /* Everything marked ALLOC (this includes the exported
+ symbols) */
+ for (i = 1; i < hdr->e_shnum; i++) {
+ /* If it's called *.init*, and we're not init, we're
+ not interested */
+ if ((strstr(secstrings + sechdrs[i].sh_name, ".init") != 0)
+ != is_init)
+ continue;
+
+ /* We don't want to look at debug sections. */
+ if (strstr(secstrings + sechdrs[i].sh_name, ".debug") != 0)
+ continue;
+
+ if (sechdrs[i].sh_type == SHT_RELA) {
+ DEBUGP("Found relocations in section %u\n", i);
+ DEBUGP("Ptr: %p. Number: %u\n",
+ (void *)hdr + sechdrs[i].sh_offset,
+ sechdrs[i].sh_size / sizeof(Elf32_Rela));
+ ret += count_relocs((void *)hdr
+ + sechdrs[i].sh_offset,
+ sechdrs[i].sh_size
+ / sizeof(Elf32_Rela))
+ * sizeof(struct ppc_plt_entry);
+ }
+ }
+
+ return ret;
+}
+
+int module_frob_arch_sections(Elf32_Ehdr *hdr,
+ Elf32_Shdr *sechdrs,
+ char *secstrings,
+ struct module *me)
+{
+ unsigned int i;
+
+ /* Find .plt and .init.plt sections */
+ for (i = 0; i < hdr->e_shnum; i++) {
+ if (strcmp(secstrings + sechdrs[i].sh_name, ".init.plt") == 0)
+ me->arch.init_plt_section = i;
+ else if (strcmp(secstrings + sechdrs[i].sh_name, ".plt") == 0)
+ me->arch.core_plt_section = i;
+ }
+ if (!me->arch.core_plt_section || !me->arch.init_plt_section) {
+ printk("Module doesn't contain .plt or .init.plt sections.\n");
+ return -ENOEXEC;
+ }
+
+ /* Override their sizes */
+ sechdrs[me->arch.core_plt_section].sh_size
+ = get_plt_size(hdr, sechdrs, secstrings, 0);
+ sechdrs[me->arch.init_plt_section].sh_size
+ = get_plt_size(hdr, sechdrs, secstrings, 1);
+ return 0;
+}
+
+int apply_relocate(Elf32_Shdr *sechdrs,
+ const char *strtab,
+ unsigned int symindex,
+ unsigned int relsec,
+ struct module *module)
+{
+ printk(KERN_ERR "%s: Non-ADD RELOCATION unsupported\n",
+ module->name);
+ return -ENOEXEC;
+}
+
+static inline int entry_matches(struct ppc_plt_entry *entry, Elf32_Addr val)
+{
+ if (entry->jump[0] == 0x3d600000 + ((val + 0x8000) >> 16)
+ && entry->jump[1] == 0x396b0000 + (val & 0xffff))
+ return 1;
+ return 0;
+}
+
+/* Set up a trampoline in the PLT to bounce us to the distant function */
+static uint32_t do_plt_call(void *location,
+ Elf32_Addr val,
+ Elf32_Shdr *sechdrs,
+ struct module *mod)
+{
+ struct ppc_plt_entry *entry;
+
+ DEBUGP("Doing plt for call to 0x%x at 0x%x\n", val, (unsigned int)location);
+ /* Init, or core PLT? */
+ if (location >= mod->module_core
+ && location < mod->module_core + mod->core_size)
+ entry = (void *)sechdrs[mod->arch.core_plt_section].sh_addr;
+ else
+ entry = (void *)sechdrs[mod->arch.init_plt_section].sh_addr;
+
+ /* Find this entry, or if that fails, the next avail. entry */
+ while (entry->jump[0]) {
+ if (entry_matches(entry, val)) return (uint32_t)entry;
+ entry++;
+ }
+
+ /* Stolen from Paul Mackerras as well... */
+ entry->jump[0] = 0x3d600000+((val+0x8000)>>16); /* lis r11,sym@ha */
+ entry->jump[1] = 0x396b0000 + (val&0xffff); /* addi r11,r11,sym@l*/
+ entry->jump[2] = 0x7d6903a6; /* mtctr r11 */
+ entry->jump[3] = 0x4e800420; /* bctr */
+
+ DEBUGP("Initialized plt for 0x%x at %p\n", val, entry);
+ return (uint32_t)entry;
+}
+
+int apply_relocate_add(Elf32_Shdr *sechdrs,
+ const char *strtab,
+ unsigned int symindex,
+ unsigned int relsec,
+ struct module *module)
+{
+ unsigned int i;
+ Elf32_Rela *rela = (void *)sechdrs[relsec].sh_addr;
+ Elf32_Sym *sym;
+ uint32_t *location;
+ uint32_t value;
+
+ DEBUGP("Applying ADD relocate section %u to %u\n", relsec,
+ sechdrs[relsec].sh_info);
+ for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rela); i++) {
+ /* This is where to make the change */
+ location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr
+ + rela[i].r_offset;
+ /* This is the symbol it is referring to. Note that all
+ undefined symbols have been resolved. */
+ sym = (Elf32_Sym *)sechdrs[symindex].sh_addr
+ + ELF32_R_SYM(rela[i].r_info);
+ /* `Everything is relative'. */
+ value = sym->st_value + rela[i].r_addend;
+
+ switch (ELF32_R_TYPE(rela[i].r_info)) {
+ case R_PPC_ADDR32:
+ /* Simply set it */
+ *(uint32_t *)location = value;
+ break;
+
+ case R_PPC_ADDR16_LO:
+ /* Low half of the symbol */
+ *(uint16_t *)location = value;
+ break;
+
+ case R_PPC_ADDR16_HA:
+ /* Sign-adjusted lower 16 bits: PPC ELF ABI says:
+ (((x >> 16) + ((x & 0x8000) ? 1 : 0))) & 0xFFFF.
+ This is the same, only sane.
+ */
+ *(uint16_t *)location = (value + 0x8000) >> 16;
+ break;
+
+ case R_PPC_REL24:
+ if ((int)(value - (uint32_t)location) < -0x02000000
+ || (int)(value - (uint32_t)location) >= 0x02000000)
+ value = do_plt_call(location, value,
+ sechdrs, module);
+
+ /* Only replace bits 2 through 26 */
+ DEBUGP("REL24 value = %08X. location = %08X\n",
+ value, (uint32_t)location);
+ DEBUGP("Location before: %08X.\n",
+ *(uint32_t *)location);
+ *(uint32_t *)location
+ = (*(uint32_t *)location & ~0x03fffffc)
+ | ((value - (uint32_t)location)
+ & 0x03fffffc);
+ DEBUGP("Location after: %08X.\n",
+ *(uint32_t *)location);
+ DEBUGP("ie. jump to %08X+%08X = %08X\n",
+ *(uint32_t *)location & 0x03fffffc,
+ (uint32_t)location,
+ (*(uint32_t *)location & 0x03fffffc)
+ + (uint32_t)location);
+ break;
+
+ case R_PPC_REL32:
+ /* 32-bit relative jump. */
+ *(uint32_t *)location = value - (uint32_t)location;
+ break;
+
+ default:
+ printk("%s: unknown ADD relocation: %u\n",
+ module->name,
+ ELF32_R_TYPE(rela[i].r_info));
+ return -ENOEXEC;
+ }
+ }
+ return 0;
+}
+
+int module_finalize(const Elf_Ehdr *hdr,
+ const Elf_Shdr *sechdrs,
+ struct module *me)
+{
+ char *secstrings;
+ unsigned int i;
+
+ me->arch.bug_table = NULL;
+ me->arch.num_bugs = 0;
+
+ /* Find the __bug_table section, if present */
+ secstrings = (char *)hdr + sechdrs[hdr->e_shstrndx].sh_offset;
+ for (i = 1; i < hdr->e_shnum; i++) {
+ if (strcmp(secstrings+sechdrs[i].sh_name, "__bug_table"))
+ continue;
+ me->arch.bug_table = (void *) sechdrs[i].sh_addr;
+ me->arch.num_bugs = sechdrs[i].sh_size / sizeof(struct bug_entry);
+ break;
+ }
+
+ /*
+ * Strictly speaking this should have a spinlock to protect against
+ * traversals, but since we only traverse on BUG()s, a spinlock
+ * could potentially lead to deadlock and thus be counter-productive.
+ */
+ list_add(&me->arch.bug_list, &module_bug_list);
+
+ return 0;
+}
+
+void module_arch_cleanup(struct module *mod)
+{
+ list_del(&mod->arch.bug_list);
+}
+
+struct bug_entry *module_find_bug(unsigned long bugaddr)
+{
+ struct mod_arch_specific *mod;
+ unsigned int i;
+ struct bug_entry *bug;
+
+ list_for_each_entry(mod, &module_bug_list, bug_list) {
+ bug = mod->bug_table;
+ for (i = 0; i < mod->num_bugs; ++i, ++bug)
+ if (bugaddr == bug->bug_addr)
+ return bug;
+ }
+ return NULL;
+}
diff --git a/arch/ppc/kernel/pci.c b/arch/ppc/kernel/pci.c
new file mode 100644
index 0000000..98f94b6
--- /dev/null
+++ b/arch/ppc/kernel/pci.c
@@ -0,0 +1,1849 @@
+/*
+ * Common pmac/prep/chrp pci routines. -- Cort
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/delay.h>
+#include <linux/string.h>
+#include <linux/init.h>
+#include <linux/capability.h>
+#include <linux/sched.h>
+#include <linux/errno.h>
+#include <linux/bootmem.h>
+
+#include <asm/processor.h>
+#include <asm/io.h>
+#include <asm/prom.h>
+#include <asm/sections.h>
+#include <asm/pci-bridge.h>
+#include <asm/byteorder.h>
+#include <asm/irq.h>
+#include <asm/uaccess.h>
+
+#undef DEBUG
+
+#ifdef DEBUG
+#define DBG(x...) printk(x)
+#else
+#define DBG(x...)
+#endif
+
+unsigned long isa_io_base = 0;
+unsigned long isa_mem_base = 0;
+unsigned long pci_dram_offset = 0;
+int pcibios_assign_bus_offset = 1;
+
+void pcibios_make_OF_bus_map(void);
+
+static int pci_relocate_bridge_resource(struct pci_bus *bus, int i);
+static int probe_resource(struct pci_bus *parent, struct resource *pr,
+ struct resource *res, struct resource **conflict);
+static void update_bridge_base(struct pci_bus *bus, int i);
+static void pcibios_fixup_resources(struct pci_dev* dev);
+static void fixup_broken_pcnet32(struct pci_dev* dev);
+static int reparent_resources(struct resource *parent, struct resource *res);
+static void fixup_rev1_53c810(struct pci_dev* dev);
+static void fixup_cpc710_pci64(struct pci_dev* dev);
+#ifdef CONFIG_PPC_OF
+static u8* pci_to_OF_bus_map;
+#endif
+
+/* By default, we don't re-assign bus numbers. We do this only on
+ * some pmacs
+ */
+int pci_assign_all_busses;
+
+struct pci_controller* hose_head;
+struct pci_controller** hose_tail = &hose_head;
+
+static int pci_bus_count;
+
+static void
+fixup_rev1_53c810(struct pci_dev* dev)
+{
+ /* rev 1 ncr53c810 chips don't set the class at all which means
+ * they don't get their resources remapped. Fix that here.
+ */
+
+ if ((dev->class == PCI_CLASS_NOT_DEFINED)) {
+ printk("NCR 53c810 rev 1 detected, setting PCI class.\n");
+ dev->class = PCI_CLASS_STORAGE_SCSI;
+ }
+}
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NCR, PCI_DEVICE_ID_NCR_53C810, fixup_rev1_53c810);
+
+static void
+fixup_broken_pcnet32(struct pci_dev* dev)
+{
+ if ((dev->class>>8 == PCI_CLASS_NETWORK_ETHERNET)) {
+ dev->vendor = PCI_VENDOR_ID_AMD;
+ pci_write_config_word(dev, PCI_VENDOR_ID, PCI_VENDOR_ID_AMD);
+ pci_name_device(dev);
+ }
+}
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_TRIDENT, PCI_ANY_ID, fixup_broken_pcnet32);
+
+static void
+fixup_cpc710_pci64(struct pci_dev* dev)
+{
+ /* Hide the PCI64 BARs from the kernel as their content doesn't
+ * fit well in the resource management
+ */
+ dev->resource[0].start = dev->resource[0].end = 0;
+ dev->resource[0].flags = 0;
+ dev->resource[1].start = dev->resource[1].end = 0;
+ dev->resource[1].flags = 0;
+}
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_CPC710_PCI64, fixup_cpc710_pci64);
+
+static void
+pcibios_fixup_resources(struct pci_dev *dev)
+{
+ struct pci_controller* hose = (struct pci_controller *)dev->sysdata;
+ int i;
+ unsigned long offset;
+
+ if (!hose) {
+ printk(KERN_ERR "No hose for PCI dev %s!\n", pci_name(dev));
+ return;
+ }
+ for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {
+ struct resource *res = dev->resource + i;
+ if (!res->flags)
+ continue;
+ if (res->end == 0xffffffff) {
+ DBG("PCI:%s Resource %d [%08lx-%08lx] is unassigned\n",
+ pci_name(dev), i, res->start, res->end);
+ res->end -= res->start;
+ res->start = 0;
+ res->flags |= IORESOURCE_UNSET;
+ continue;
+ }
+ offset = 0;
+ if (res->flags & IORESOURCE_MEM) {
+ offset = hose->pci_mem_offset;
+ } else if (res->flags & IORESOURCE_IO) {
+ offset = (unsigned long) hose->io_base_virt
+ - isa_io_base;
+ }
+ if (offset != 0) {
+ res->start += offset;
+ res->end += offset;
+#ifdef DEBUG
+ printk("Fixup res %d (%lx) of dev %s: %lx -> %lx\n",
+ i, res->flags, pci_name(dev),
+ res->start - offset, res->start);
+#endif
+ }
+ }
+
+ /* Call machine specific resource fixup */
+ if (ppc_md.pcibios_fixup_resources)
+ ppc_md.pcibios_fixup_resources(dev);
+}
+DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, pcibios_fixup_resources);
+
+void pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region,
+ struct resource *res)
+{
+ unsigned long offset = 0;
+ struct pci_controller *hose = dev->sysdata;
+
+ if (hose && res->flags & IORESOURCE_IO)
+ offset = (unsigned long)hose->io_base_virt - isa_io_base;
+ else if (hose && res->flags & IORESOURCE_MEM)
+ offset = hose->pci_mem_offset;
+ region->start = res->start - offset;
+ region->end = res->end - offset;
+}
+EXPORT_SYMBOL(pcibios_resource_to_bus);
+
+/*
+ * We need to avoid collisions with `mirrored' VGA ports
+ * and other strange ISA hardware, so we always want the
+ * addresses to be allocated in the 0x000-0x0ff region
+ * modulo 0x400.
+ *
+ * Why? Because some silly external IO cards only decode
+ * the low 10 bits of the IO address. The 0x00-0xff region
+ * is reserved for motherboard devices that decode all 16
+ * bits, so it's ok to allocate at, say, 0x2800-0x28ff,
+ * but we want to try to avoid allocating at 0x2900-0x2bff
+ * which might have be mirrored at 0x0100-0x03ff..
+ */
+void pcibios_align_resource(void *data, struct resource *res, unsigned long size,
+ unsigned long align)
+{
+ struct pci_dev *dev = data;
+
+ if (res->flags & IORESOURCE_IO) {
+ unsigned long start = res->start;
+
+ if (size > 0x100) {
+ printk(KERN_ERR "PCI: I/O Region %s/%d too large"
+ " (%ld bytes)\n", pci_name(dev),
+ dev->resource - res, size);
+ }
+
+ if (start & 0x300) {
+ start = (start + 0x3ff) & ~0x3ff;
+ res->start = start;
+ }
+ }
+}
+EXPORT_SYMBOL(pcibios_align_resource);
+
+/*
+ * Handle resources of PCI devices. If the world were perfect, we could
+ * just allocate all the resource regions and do nothing more. It isn't.
+ * On the other hand, we cannot just re-allocate all devices, as it would
+ * require us to know lots of host bridge internals. So we attempt to
+ * keep as much of the original configuration as possible, but tweak it
+ * when it's found to be wrong.
+ *
+ * Known BIOS problems we have to work around:
+ * - I/O or memory regions not configured
+ * - regions configured, but not enabled in the command register
+ * - bogus I/O addresses above 64K used
+ * - expansion ROMs left enabled (this may sound harmless, but given
+ * the fact the PCI specs explicitly allow address decoders to be
+ * shared between expansion ROMs and other resource regions, it's
+ * at least dangerous)
+ *
+ * Our solution:
+ * (1) Allocate resources for all buses behind PCI-to-PCI bridges.
+ * This gives us fixed barriers on where we can allocate.
+ * (2) Allocate resources for all enabled devices. If there is
+ * a collision, just mark the resource as unallocated. Also
+ * disable expansion ROMs during this step.
+ * (3) Try to allocate resources for disabled devices. If the
+ * resources were assigned correctly, everything goes well,
+ * if they weren't, they won't disturb allocation of other
+ * resources.
+ * (4) Assign new addresses to resources which were either
+ * not configured at all or misconfigured. If explicitly
+ * requested by the user, configure expansion ROM address
+ * as well.
+ */
+
+static void __init
+pcibios_allocate_bus_resources(struct list_head *bus_list)
+{
+ struct pci_bus *bus;
+ int i;
+ struct resource *res, *pr;
+
+ /* Depth-First Search on bus tree */
+ list_for_each_entry(bus, bus_list, node) {
+ for (i = 0; i < 4; ++i) {
+ if ((res = bus->resource[i]) == NULL || !res->flags
+ || res->start > res->end)
+ continue;
+ if (bus->parent == NULL)
+ pr = (res->flags & IORESOURCE_IO)?
+ &ioport_resource: &iomem_resource;
+ else {
+ pr = pci_find_parent_resource(bus->self, res);
+ if (pr == res) {
+ /* this happens when the generic PCI
+ * code (wrongly) decides that this
+ * bridge is transparent -- paulus
+ */
+ continue;
+ }
+ }
+
+ DBG("PCI: bridge rsrc %lx..%lx (%lx), parent %p\n",
+ res->start, res->end, res->flags, pr);
+ if (pr) {
+ if (request_resource(pr, res) == 0)
+ continue;
+ /*
+ * Must be a conflict with an existing entry.
+ * Move that entry (or entries) under the
+ * bridge resource and try again.
+ */
+ if (reparent_resources(pr, res) == 0)
+ continue;
+ }
+ printk(KERN_ERR "PCI: Cannot allocate resource region "
+ "%d of PCI bridge %d\n", i, bus->number);
+ if (pci_relocate_bridge_resource(bus, i))
+ bus->resource[i] = NULL;
+ }
+ pcibios_allocate_bus_resources(&bus->children);
+ }
+}
+
+/*
+ * Reparent resource children of pr that conflict with res
+ * under res, and make res replace those children.
+ */
+static int __init
+reparent_resources(struct resource *parent, struct resource *res)
+{
+ struct resource *p, **pp;
+ struct resource **firstpp = NULL;
+
+ for (pp = &parent->child; (p = *pp) != NULL; pp = &p->sibling) {
+ if (p->end < res->start)
+ continue;
+ if (res->end < p->start)
+ break;
+ if (p->start < res->start || p->end > res->end)
+ return -1; /* not completely contained */
+ if (firstpp == NULL)
+ firstpp = pp;
+ }
+ if (firstpp == NULL)
+ return -1; /* didn't find any conflicting entries? */
+ res->parent = parent;
+ res->child = *firstpp;
+ res->sibling = *pp;
+ *firstpp = res;
+ *pp = NULL;
+ for (p = res->child; p != NULL; p = p->sibling) {
+ p->parent = res;
+ DBG(KERN_INFO "PCI: reparented %s [%lx..%lx] under %s\n",
+ p->name, p->start, p->end, res->name);
+ }
+ return 0;
+}
+
+/*
+ * A bridge has been allocated a range which is outside the range
+ * of its parent bridge, so it needs to be moved.
+ */
+static int __init
+pci_relocate_bridge_resource(struct pci_bus *bus, int i)
+{
+ struct resource *res, *pr, *conflict;
+ unsigned long try, size;
+ int j;
+ struct pci_bus *parent = bus->parent;
+
+ if (parent == NULL) {
+ /* shouldn't ever happen */
+ printk(KERN_ERR "PCI: can't move host bridge resource\n");
+ return -1;
+ }
+ res = bus->resource[i];
+ if (res == NULL)
+ return -1;
+ pr = NULL;
+ for (j = 0; j < 4; j++) {
+ struct resource *r = parent->resource[j];
+ if (!r)
+ continue;
+ if ((res->flags ^ r->flags) & (IORESOURCE_IO | IORESOURCE_MEM))
+ continue;
+ if (!((res->flags ^ r->flags) & IORESOURCE_PREFETCH)) {
+ pr = r;
+ break;
+ }
+ if (res->flags & IORESOURCE_PREFETCH)
+ pr = r;
+ }
+ if (pr == NULL)
+ return -1;
+ size = res->end - res->start;
+ if (pr->start > pr->end || size > pr->end - pr->start)
+ return -1;
+ try = pr->end;
+ for (;;) {
+ res->start = try - size;
+ res->end = try;
+ if (probe_resource(bus->parent, pr, res, &conflict) == 0)
+ break;
+ if (conflict->start <= pr->start + size)
+ return -1;
+ try = conflict->start - 1;
+ }
+ if (request_resource(pr, res)) {
+ DBG(KERN_ERR "PCI: huh? couldn't move to %lx..%lx\n",
+ res->start, res->end);
+ return -1; /* "can't happen" */
+ }
+ update_bridge_base(bus, i);
+ printk(KERN_INFO "PCI: bridge %d resource %d moved to %lx..%lx\n",
+ bus->number, i, res->start, res->end);
+ return 0;
+}
+
+static int __init
+probe_resource(struct pci_bus *parent, struct resource *pr,
+ struct resource *res, struct resource **conflict)
+{
+ struct pci_bus *bus;
+ struct pci_dev *dev;
+ struct resource *r;
+ int i;
+
+ for (r = pr->child; r != NULL; r = r->sibling) {
+ if (r->end >= res->start && res->end >= r->start) {
+ *conflict = r;
+ return 1;
+ }
+ }
+ list_for_each_entry(bus, &parent->children, node) {
+ for (i = 0; i < 4; ++i) {
+ if ((r = bus->resource[i]) == NULL)
+ continue;
+ if (!r->flags || r->start > r->end || r == res)
+ continue;
+ if (pci_find_parent_resource(bus->self, r) != pr)
+ continue;
+ if (r->end >= res->start && res->end >= r->start) {
+ *conflict = r;
+ return 1;
+ }
+ }
+ }
+ list_for_each_entry(dev, &parent->devices, bus_list) {
+ for (i = 0; i < 6; ++i) {
+ r = &dev->resource[i];
+ if (!r->flags || (r->flags & IORESOURCE_UNSET))
+ continue;
+ if (pci_find_parent_resource(dev, r) != pr)
+ continue;
+ if (r->end >= res->start && res->end >= r->start) {
+ *conflict = r;
+ return 1;
+ }
+ }
+ }
+ return 0;
+}
+
+static void __init
+update_bridge_base(struct pci_bus *bus, int i)
+{
+ struct resource *res = bus->resource[i];
+ u8 io_base_lo, io_limit_lo;
+ u16 mem_base, mem_limit;
+ u16 cmd;
+ unsigned long start, end, off;
+ struct pci_dev *dev = bus->self;
+ struct pci_controller *hose = dev->sysdata;
+
+ if (!hose) {
+ printk("update_bridge_base: no hose?\n");
+ return;
+ }
+ pci_read_config_word(dev, PCI_COMMAND, &cmd);
+ pci_write_config_word(dev, PCI_COMMAND,
+ cmd & ~(PCI_COMMAND_IO | PCI_COMMAND_MEMORY));
+ if (res->flags & IORESOURCE_IO) {
+ off = (unsigned long) hose->io_base_virt - isa_io_base;
+ start = res->start - off;
+ end = res->end - off;
+ io_base_lo = (start >> 8) & PCI_IO_RANGE_MASK;
+ io_limit_lo = (end >> 8) & PCI_IO_RANGE_MASK;
+ if (end > 0xffff) {
+ pci_write_config_word(dev, PCI_IO_BASE_UPPER16,
+ start >> 16);
+ pci_write_config_word(dev, PCI_IO_LIMIT_UPPER16,
+ end >> 16);
+ io_base_lo |= PCI_IO_RANGE_TYPE_32;
+ } else
+ io_base_lo |= PCI_IO_RANGE_TYPE_16;
+ pci_write_config_byte(dev, PCI_IO_BASE, io_base_lo);
+ pci_write_config_byte(dev, PCI_IO_LIMIT, io_limit_lo);
+
+ } else if ((res->flags & (IORESOURCE_MEM | IORESOURCE_PREFETCH))
+ == IORESOURCE_MEM) {
+ off = hose->pci_mem_offset;
+ mem_base = ((res->start - off) >> 16) & PCI_MEMORY_RANGE_MASK;
+ mem_limit = ((res->end - off) >> 16) & PCI_MEMORY_RANGE_MASK;
+ pci_write_config_word(dev, PCI_MEMORY_BASE, mem_base);
+ pci_write_config_word(dev, PCI_MEMORY_LIMIT, mem_limit);
+
+ } else if ((res->flags & (IORESOURCE_MEM | IORESOURCE_PREFETCH))
+ == (IORESOURCE_MEM | IORESOURCE_PREFETCH)) {
+ off = hose->pci_mem_offset;
+ mem_base = ((res->start - off) >> 16) & PCI_PREF_RANGE_MASK;
+ mem_limit = ((res->end - off) >> 16) & PCI_PREF_RANGE_MASK;
+ pci_write_config_word(dev, PCI_PREF_MEMORY_BASE, mem_base);
+ pci_write_config_word(dev, PCI_PREF_MEMORY_LIMIT, mem_limit);
+
+ } else {
+ DBG(KERN_ERR "PCI: ugh, bridge %s res %d has flags=%lx\n",
+ pci_name(dev), i, res->flags);
+ }
+ pci_write_config_word(dev, PCI_COMMAND, cmd);
+}
+
+static inline void alloc_resource(struct pci_dev *dev, int idx)
+{
+ struct resource *pr, *r = &dev->resource[idx];
+
+ DBG("PCI:%s: Resource %d: %08lx-%08lx (f=%lx)\n",
+ pci_name(dev), idx, r->start, r->end, r->flags);
+ pr = pci_find_parent_resource(dev, r);
+ if (!pr || request_resource(pr, r) < 0) {
+ printk(KERN_ERR "PCI: Cannot allocate resource region %d"
+ " of device %s\n", idx, pci_name(dev));
+ if (pr)
+ DBG("PCI: parent is %p: %08lx-%08lx (f=%lx)\n",
+ pr, pr->start, pr->end, pr->flags);
+ /* We'll assign a new address later */
+ r->flags |= IORESOURCE_UNSET;
+ r->end -= r->start;
+ r->start = 0;
+ }
+}
+
+static void __init
+pcibios_allocate_resources(int pass)
+{
+ struct pci_dev *dev = NULL;
+ int idx, disabled;
+ u16 command;
+ struct resource *r;
+
+ while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
+ pci_read_config_word(dev, PCI_COMMAND, &command);
+ for (idx = 0; idx < 6; idx++) {
+ r = &dev->resource[idx];
+ if (r->parent) /* Already allocated */
+ continue;
+ if (!r->flags || (r->flags & IORESOURCE_UNSET))
+ continue; /* Not assigned at all */
+ if (r->flags & IORESOURCE_IO)
+ disabled = !(command & PCI_COMMAND_IO);
+ else
+ disabled = !(command & PCI_COMMAND_MEMORY);
+ if (pass == disabled)
+ alloc_resource(dev, idx);
+ }
+ if (pass)
+ continue;
+ r = &dev->resource[PCI_ROM_RESOURCE];
+ if (r->flags & IORESOURCE_ROM_ENABLE) {
+ /* Turn the ROM off, leave the resource region, but keep it unregistered. */
+ u32 reg;
+ DBG("PCI: Switching off ROM of %s\n", pci_name(dev));
+ r->flags &= ~IORESOURCE_ROM_ENABLE;
+ pci_read_config_dword(dev, dev->rom_base_reg, ®);
+ pci_write_config_dword(dev, dev->rom_base_reg,
+ reg & ~PCI_ROM_ADDRESS_ENABLE);
+ }
+ }
+}
+
+static void __init
+pcibios_assign_resources(void)
+{
+ struct pci_dev *dev = NULL;
+ int idx;
+ struct resource *r;
+
+ while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
+ int class = dev->class >> 8;
+
+ /* Don't touch classless devices and host bridges */
+ if (!class || class == PCI_CLASS_BRIDGE_HOST)
+ continue;
+
+ for (idx = 0; idx < 6; idx++) {
+ r = &dev->resource[idx];
+
+ /*
+ * We shall assign a new address to this resource,
+ * either because the BIOS (sic) forgot to do so
+ * or because we have decided the old address was
+ * unusable for some reason.
+ */
+ if ((r->flags & IORESOURCE_UNSET) && r->end &&
+ (!ppc_md.pcibios_enable_device_hook ||
+ !ppc_md.pcibios_enable_device_hook(dev, 1))) {
+ r->flags &= ~IORESOURCE_UNSET;
+ pci_assign_resource(dev, idx);
+ }
+ }
+
+#if 0 /* don't assign ROMs */
+ r = &dev->resource[PCI_ROM_RESOURCE];
+ r->end -= r->start;
+ r->start = 0;
+ if (r->end)
+ pci_assign_resource(dev, PCI_ROM_RESOURCE);
+#endif
+ }
+}
+
+
+int
+pcibios_enable_resources(struct pci_dev *dev, int mask)
+{
+ u16 cmd, old_cmd;
+ int idx;
+ struct resource *r;
+
+ pci_read_config_word(dev, PCI_COMMAND, &cmd);
+ old_cmd = cmd;
+ for (idx=0; idx<6; idx++) {
+ /* Only set up the requested stuff */
+ if (!(mask & (1<<idx)))
+ continue;
+
+ r = &dev->resource[idx];
+ if (r->flags & IORESOURCE_UNSET) {
+ printk(KERN_ERR "PCI: Device %s not available because of resource collisions\n", pci_name(dev));
+ return -EINVAL;
+ }
+ if (r->flags & IORESOURCE_IO)
+ cmd |= PCI_COMMAND_IO;
+ if (r->flags & IORESOURCE_MEM)
+ cmd |= PCI_COMMAND_MEMORY;
+ }
+ if (dev->resource[PCI_ROM_RESOURCE].start)
+ cmd |= PCI_COMMAND_MEMORY;
+ if (cmd != old_cmd) {
+ printk("PCI: Enabling device %s (%04x -> %04x)\n", pci_name(dev), old_cmd, cmd);
+ pci_write_config_word(dev, PCI_COMMAND, cmd);
+ }
+ return 0;
+}
+
+static int next_controller_index;
+
+struct pci_controller * __init
+pcibios_alloc_controller(void)
+{
+ struct pci_controller *hose;
+
+ hose = (struct pci_controller *)alloc_bootmem(sizeof(*hose));
+ memset(hose, 0, sizeof(struct pci_controller));
+
+ *hose_tail = hose;
+ hose_tail = &hose->next;
+
+ hose->index = next_controller_index++;
+
+ return hose;
+}
+
+#ifdef CONFIG_PPC_OF
+/*
+ * Functions below are used on OpenFirmware machines.
+ */
+static void __openfirmware
+make_one_node_map(struct device_node* node, u8 pci_bus)
+{
+ int *bus_range;
+ int len;
+
+ if (pci_bus >= pci_bus_count)
+ return;
+ bus_range = (int *) get_property(node, "bus-range", &len);
+ if (bus_range == NULL || len < 2 * sizeof(int)) {
+ printk(KERN_WARNING "Can't get bus-range for %s, "
+ "assuming it starts at 0\n", node->full_name);
+ pci_to_OF_bus_map[pci_bus] = 0;
+ } else
+ pci_to_OF_bus_map[pci_bus] = bus_range[0];
+
+ for (node=node->child; node != 0;node = node->sibling) {
+ struct pci_dev* dev;
+ unsigned int *class_code, *reg;
+
+ class_code = (unsigned int *) get_property(node, "class-code", NULL);
+ if (!class_code || ((*class_code >> 8) != PCI_CLASS_BRIDGE_PCI &&
+ (*class_code >> 8) != PCI_CLASS_BRIDGE_CARDBUS))
+ continue;
+ reg = (unsigned int *)get_property(node, "reg", NULL);
+ if (!reg)
+ continue;
+ dev = pci_find_slot(pci_bus, ((reg[0] >> 8) & 0xff));
+ if (!dev || !dev->subordinate)
+ continue;
+ make_one_node_map(node, dev->subordinate->number);
+ }
+}
+
+void __openfirmware
+pcibios_make_OF_bus_map(void)
+{
+ int i;
+ struct pci_controller* hose;
+ u8* of_prop_map;
+
+ pci_to_OF_bus_map = (u8*)kmalloc(pci_bus_count, GFP_KERNEL);
+ if (!pci_to_OF_bus_map) {
+ printk(KERN_ERR "Can't allocate OF bus map !\n");
+ return;
+ }
+
+ /* We fill the bus map with invalid values, that helps
+ * debugging.
+ */
+ for (i=0; i<pci_bus_count; i++)
+ pci_to_OF_bus_map[i] = 0xff;
+
+ /* For each hose, we begin searching bridges */
+ for(hose=hose_head; hose; hose=hose->next) {
+ struct device_node* node;
+ node = (struct device_node *)hose->arch_data;
+ if (!node)
+ continue;
+ make_one_node_map(node, hose->first_busno);
+ }
+ of_prop_map = get_property(find_path_device("/"), "pci-OF-bus-map", NULL);
+ if (of_prop_map)
+ memcpy(of_prop_map, pci_to_OF_bus_map, pci_bus_count);
+#ifdef DEBUG
+ printk("PCI->OF bus map:\n");
+ for (i=0; i<pci_bus_count; i++) {
+ if (pci_to_OF_bus_map[i] == 0xff)
+ continue;
+ printk("%d -> %d\n", i, pci_to_OF_bus_map[i]);
+ }
+#endif
+}
+
+typedef int (*pci_OF_scan_iterator)(struct device_node* node, void* data);
+
+static struct device_node* __openfirmware
+scan_OF_pci_childs(struct device_node* node, pci_OF_scan_iterator filter, void* data)
+{
+ struct device_node* sub_node;
+
+ for (; node != 0;node = node->sibling) {
+ unsigned int *class_code;
+
+ if (filter(node, data))
+ return node;
+
+ /* For PCI<->PCI bridges or CardBus bridges, we go down
+ * Note: some OFs create a parent node "multifunc-device" as
+ * a fake root for all functions of a multi-function device,
+ * we go down them as well.
+ */
+ class_code = (unsigned int *) get_property(node, "class-code", NULL);
+ if ((!class_code || ((*class_code >> 8) != PCI_CLASS_BRIDGE_PCI &&
+ (*class_code >> 8) != PCI_CLASS_BRIDGE_CARDBUS)) &&
+ strcmp(node->name, "multifunc-device"))
+ continue;
+ sub_node = scan_OF_pci_childs(node->child, filter, data);
+ if (sub_node)
+ return sub_node;
+ }
+ return NULL;
+}
+
+static int
+scan_OF_pci_childs_iterator(struct device_node* node, void* data)
+{
+ unsigned int *reg;
+ u8* fdata = (u8*)data;
+
+ reg = (unsigned int *) get_property(node, "reg", NULL);
+ if (reg && ((reg[0] >> 8) & 0xff) == fdata[1]
+ && ((reg[0] >> 16) & 0xff) == fdata[0])
+ return 1;
+ return 0;
+}
+
+static struct device_node* __openfirmware
+scan_OF_childs_for_device(struct device_node* node, u8 bus, u8 dev_fn)
+{
+ u8 filter_data[2] = {bus, dev_fn};
+
+ return scan_OF_pci_childs(node, scan_OF_pci_childs_iterator, filter_data);
+}
+
+/*
+ * Scans the OF tree for a device node matching a PCI device
+ */
+struct device_node *
+pci_busdev_to_OF_node(struct pci_bus *bus, int devfn)
+{
+ struct pci_controller *hose;
+ struct device_node *node;
+ int busnr;
+
+ if (!have_of)
+ return NULL;
+
+ /* Lookup the hose */
+ busnr = bus->number;
+ hose = pci_bus_to_hose(busnr);
+ if (!hose)
+ return NULL;
+
+ /* Check it has an OF node associated */
+ node = (struct device_node *) hose->arch_data;
+ if (!node)
+ return NULL;
+
+ /* Fixup bus number according to what OF think it is. */
+#ifdef CONFIG_PPC_PMAC
+ /* The G5 need a special case here. Basically, we don't remap all
+ * busses on it so we don't create the pci-OF-map. However, we do
+ * remap the AGP bus and so have to deal with it. A future better
+ * fix has to be done by making the remapping per-host and always
+ * filling the pci_to_OF map. --BenH
+ */
+ if (_machine == _MACH_Pmac && busnr >= 0xf0)
+ busnr -= 0xf0;
+ else
+#endif
+ if (pci_to_OF_bus_map)
+ busnr = pci_to_OF_bus_map[busnr];
+ if (busnr == 0xff)
+ return NULL;
+
+ /* Now, lookup childs of the hose */
+ return scan_OF_childs_for_device(node->child, busnr, devfn);
+}
+
+struct device_node*
+pci_device_to_OF_node(struct pci_dev *dev)
+{
+ return pci_busdev_to_OF_node(dev->bus, dev->devfn);
+}
+
+/* This routine is meant to be used early during boot, when the
+ * PCI bus numbers have not yet been assigned, and you need to
+ * issue PCI config cycles to an OF device.
+ * It could also be used to "fix" RTAS config cycles if you want
+ * to set pci_assign_all_busses to 1 and still use RTAS for PCI
+ * config cycles.
+ */
+struct pci_controller*
+pci_find_hose_for_OF_device(struct device_node* node)
+{
+ if (!have_of)
+ return NULL;
+ while(node) {
+ struct pci_controller* hose;
+ for (hose=hose_head;hose;hose=hose->next)
+ if (hose->arch_data == node)
+ return hose;
+ node=node->parent;
+ }
+ return NULL;
+}
+
+static int __openfirmware
+find_OF_pci_device_filter(struct device_node* node, void* data)
+{
+ return ((void *)node == data);
+}
+
+/*
+ * Returns the PCI device matching a given OF node
+ */
+int
+pci_device_from_OF_node(struct device_node* node, u8* bus, u8* devfn)
+{
+ unsigned int *reg;
+ struct pci_controller* hose;
+ struct pci_dev* dev = NULL;
+
+ if (!have_of)
+ return -ENODEV;
+ /* Make sure it's really a PCI device */
+ hose = pci_find_hose_for_OF_device(node);
+ if (!hose || !hose->arch_data)
+ return -ENODEV;
+ if (!scan_OF_pci_childs(((struct device_node*)hose->arch_data)->child,
+ find_OF_pci_device_filter, (void *)node))
+ return -ENODEV;
+ reg = (unsigned int *) get_property(node, "reg", NULL);
+ if (!reg)
+ return -ENODEV;
+ *bus = (reg[0] >> 16) & 0xff;
+ *devfn = ((reg[0] >> 8) & 0xff);
+
+ /* Ok, here we need some tweak. If we have already renumbered
+ * all busses, we can't rely on the OF bus number any more.
+ * the pci_to_OF_bus_map is not enough as several PCI busses
+ * may match the same OF bus number.
+ */
+ if (!pci_to_OF_bus_map)
+ return 0;
+ while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
+ if (pci_to_OF_bus_map[dev->bus->number] != *bus)
+ continue;
+ if (dev->devfn != *devfn)
+ continue;
+ *bus = dev->bus->number;
+ return 0;
+ }
+ return -ENODEV;
+}
+
+void __init
+pci_process_bridge_OF_ranges(struct pci_controller *hose,
+ struct device_node *dev, int primary)
+{
+ static unsigned int static_lc_ranges[256] __initdata;
+ unsigned int *dt_ranges, *lc_ranges, *ranges, *prev;
+ unsigned int size;
+ int rlen = 0, orig_rlen;
+ int memno = 0;
+ struct resource *res;
+ int np, na = prom_n_addr_cells(dev);
+ np = na + 5;
+
+ /* First we try to merge ranges to fix a problem with some pmacs
+ * that can have more than 3 ranges, fortunately using contiguous
+ * addresses -- BenH
+ */
+ dt_ranges = (unsigned int *) get_property(dev, "ranges", &rlen);
+ if (!dt_ranges)
+ return;
+ /* Sanity check, though hopefully that never happens */
+ if (rlen > sizeof(static_lc_ranges)) {
+ printk(KERN_WARNING "OF ranges property too large !\n");
+ rlen = sizeof(static_lc_ranges);
+ }
+ lc_ranges = static_lc_ranges;
+ memcpy(lc_ranges, dt_ranges, rlen);
+ orig_rlen = rlen;
+
+ /* Let's work on a copy of the "ranges" property instead of damaging
+ * the device-tree image in memory
+ */
+ ranges = lc_ranges;
+ prev = NULL;
+ while ((rlen -= np * sizeof(unsigned int)) >= 0) {
+ if (prev) {
+ if (prev[0] == ranges[0] && prev[1] == ranges[1] &&
+ (prev[2] + prev[na+4]) == ranges[2] &&
+ (prev[na+2] + prev[na+4]) == ranges[na+2]) {
+ prev[na+4] += ranges[na+4];
+ ranges[0] = 0;
+ ranges += np;
+ continue;
+ }
+ }
+ prev = ranges;
+ ranges += np;
+ }
+
+ /*
+ * The ranges property is laid out as an array of elements,
+ * each of which comprises:
+ * cells 0 - 2: a PCI address
+ * cells 3 or 3+4: a CPU physical address
+ * (size depending on dev->n_addr_cells)
+ * cells 4+5 or 5+6: the size of the range
+ */
+ ranges = lc_ranges;
+ rlen = orig_rlen;
+ while (ranges && (rlen -= np * sizeof(unsigned int)) >= 0) {
+ res = NULL;
+ size = ranges[na+4];
+ switch (ranges[0] >> 24) {
+ case 1: /* I/O space */
+ if (ranges[2] != 0)
+ break;
+ hose->io_base_phys = ranges[na+2];
+ /* limit I/O space to 16MB */
+ if (size > 0x01000000)
+ size = 0x01000000;
+ hose->io_base_virt = ioremap(ranges[na+2], size);
+ if (primary)
+ isa_io_base = (unsigned long) hose->io_base_virt;
+ res = &hose->io_resource;
+ res->flags = IORESOURCE_IO;
+ res->start = ranges[2];
+ break;
+ case 2: /* memory space */
+ memno = 0;
+ if (ranges[1] == 0 && ranges[2] == 0
+ && ranges[na+4] <= (16 << 20)) {
+ /* 1st 16MB, i.e. ISA memory area */
+ if (primary)
+ isa_mem_base = ranges[na+2];
+ memno = 1;
+ }
+ while (memno < 3 && hose->mem_resources[memno].flags)
+ ++memno;
+ if (memno == 0)
+ hose->pci_mem_offset = ranges[na+2] - ranges[2];
+ if (memno < 3) {
+ res = &hose->mem_resources[memno];
+ res->flags = IORESOURCE_MEM;
+ res->start = ranges[na+2];
+ }
+ break;
+ }
+ if (res != NULL) {
+ res->name = dev->full_name;
+ res->end = res->start + size - 1;
+ res->parent = NULL;
+ res->sibling = NULL;
+ res->child = NULL;
+ }
+ ranges += np;
+ }
+}
+
+/* We create the "pci-OF-bus-map" property now so it appears in the
+ * /proc device tree
+ */
+void __init
+pci_create_OF_bus_map(void)
+{
+ struct property* of_prop;
+
+ of_prop = (struct property*) alloc_bootmem(sizeof(struct property) + 256);
+ if (of_prop && find_path_device("/")) {
+ memset(of_prop, -1, sizeof(struct property) + 256);
+ of_prop->name = "pci-OF-bus-map";
+ of_prop->length = 256;
+ of_prop->value = (unsigned char *)&of_prop[1];
+ prom_add_property(find_path_device("/"), of_prop);
+ }
+}
+
+static ssize_t pci_show_devspec(struct device *dev, char *buf)
+{
+ struct pci_dev *pdev;
+ struct device_node *np;
+
+ pdev = to_pci_dev (dev);
+ np = pci_device_to_OF_node(pdev);
+ if (np == NULL || np->full_name == NULL)
+ return 0;
+ return sprintf(buf, "%s", np->full_name);
+}
+static DEVICE_ATTR(devspec, S_IRUGO, pci_show_devspec, NULL);
+
+#endif /* CONFIG_PPC_OF */
+
+/* Add sysfs properties */
+void pcibios_add_platform_entries(struct pci_dev *pdev)
+{
+#ifdef CONFIG_PPC_OF
+ device_create_file(&pdev->dev, &dev_attr_devspec);
+#endif /* CONFIG_PPC_OF */
+}
+
+
+#ifdef CONFIG_PPC_PMAC
+/*
+ * This set of routines checks for PCI<->PCI bridges that have closed
+ * IO resources and have child devices. It tries to re-open an IO
+ * window on them.
+ *
+ * This is a _temporary_ fix to workaround a problem with Apple's OF
+ * closing IO windows on P2P bridges when the OF drivers of cards
+ * below this bridge don't claim any IO range (typically ATI or
+ * Adaptec).
+ *
+ * A more complete fix would be to use drivers/pci/setup-bus.c, which
+ * involves a working pcibios_fixup_pbus_ranges(), some more care about
+ * ordering when creating the host bus resources, and maybe a few more
+ * minor tweaks
+ */
+
+/* Initialize bridges with base/limit values we have collected */
+static void __init
+do_update_p2p_io_resource(struct pci_bus *bus, int enable_vga)
+{
+ struct pci_dev *bridge = bus->self;
+ struct pci_controller* hose = (struct pci_controller *)bridge->sysdata;
+ u32 l;
+ u16 w;
+ struct resource res;
+
+ if (bus->resource[0] == NULL)
+ return;
+ res = *(bus->resource[0]);
+
+ DBG("Remapping Bus %d, bridge: %s\n", bus->number, pci_name(bridge));
+ res.start -= ((unsigned long) hose->io_base_virt - isa_io_base);
+ res.end -= ((unsigned long) hose->io_base_virt - isa_io_base);
+ DBG(" IO window: %08lx-%08lx\n", res.start, res.end);
+
+ /* Set up the top and bottom of the PCI I/O segment for this bus. */
+ pci_read_config_dword(bridge, PCI_IO_BASE, &l);
+ l &= 0xffff000f;
+ l |= (res.start >> 8) & 0x00f0;
+ l |= res.end & 0xf000;
+ pci_write_config_dword(bridge, PCI_IO_BASE, l);
+
+ if ((l & PCI_IO_RANGE_TYPE_MASK) == PCI_IO_RANGE_TYPE_32) {
+ l = (res.start >> 16) | (res.end & 0xffff0000);
+ pci_write_config_dword(bridge, PCI_IO_BASE_UPPER16, l);
+ }
+
+ pci_read_config_word(bridge, PCI_COMMAND, &w);
+ w |= PCI_COMMAND_IO;
+ pci_write_config_word(bridge, PCI_COMMAND, w);
+
+#if 0 /* Enabling this causes XFree 4.2.0 to hang during PCI probe */
+ if (enable_vga) {
+ pci_read_config_word(bridge, PCI_BRIDGE_CONTROL, &w);
+ w |= PCI_BRIDGE_CTL_VGA;
+ pci_write_config_word(bridge, PCI_BRIDGE_CONTROL, w);
+ }
+#endif
+}
+
+/* This function is pretty basic and actually quite broken for the
+ * general case, it's enough for us right now though. It's supposed
+ * to tell us if we need to open an IO range at all or not and what
+ * size.
+ */
+static int __init
+check_for_io_childs(struct pci_bus *bus, struct resource* res, int *found_vga)
+{
+ struct pci_dev *dev;
+ int i;
+ int rc = 0;
+
+#define push_end(res, size) do { unsigned long __sz = (size) ; \
+ res->end = ((res->end + __sz) / (__sz + 1)) * (__sz + 1) + __sz; \
+ } while (0)
+
+ list_for_each_entry(dev, &bus->devices, bus_list) {
+ u16 class = dev->class >> 8;
+
+ if (class == PCI_CLASS_DISPLAY_VGA ||
+ class == PCI_CLASS_NOT_DEFINED_VGA)
+ *found_vga = 1;
+ if (class >> 8 == PCI_BASE_CLASS_BRIDGE && dev->subordinate)
+ rc |= check_for_io_childs(dev->subordinate, res, found_vga);
+ if (class == PCI_CLASS_BRIDGE_CARDBUS)
+ push_end(res, 0xfff);
+
+ for (i=0; i<PCI_NUM_RESOURCES; i++) {
+ struct resource *r;
+ unsigned long r_size;
+
+ if (dev->class >> 8 == PCI_CLASS_BRIDGE_PCI
+ && i >= PCI_BRIDGE_RESOURCES)
+ continue;
+ r = &dev->resource[i];
+ r_size = r->end - r->start;
+ if (r_size < 0xfff)
+ r_size = 0xfff;
+ if (r->flags & IORESOURCE_IO && (r_size) != 0) {
+ rc = 1;
+ push_end(res, r_size);
+ }
+ }
+ }
+
+ return rc;
+}
+
+/* Here we scan all P2P bridges of a given level that have a closed
+ * IO window. Note that the test for the presence of a VGA card should
+ * be improved to take into account already configured P2P bridges,
+ * currently, we don't see them and might end up configuring 2 bridges
+ * with VGA pass through enabled
+ */
+static void __init
+do_fixup_p2p_level(struct pci_bus *bus)
+{
+ struct pci_bus *b;
+ int i, parent_io;
+ int has_vga = 0;
+
+ for (parent_io=0; parent_io<4; parent_io++)
+ if (bus->resource[parent_io]
+ && bus->resource[parent_io]->flags & IORESOURCE_IO)
+ break;
+ if (parent_io >= 4)
+ return;
+
+ list_for_each_entry(b, &bus->children, node) {
+ struct pci_dev *d = b->self;
+ struct pci_controller* hose = (struct pci_controller *)d->sysdata;
+ struct resource *res = b->resource[0];
+ struct resource tmp_res;
+ unsigned long max;
+ int found_vga = 0;
+
+ memset(&tmp_res, 0, sizeof(tmp_res));
+ tmp_res.start = bus->resource[parent_io]->start;
+
+ /* We don't let low addresses go through that closed P2P bridge, well,
+ * that may not be necessary but I feel safer that way
+ */
+ if (tmp_res.start == 0)
+ tmp_res.start = 0x1000;
+
+ if (!list_empty(&b->devices) && res && res->flags == 0 &&
+ res != bus->resource[parent_io] &&
+ (d->class >> 8) == PCI_CLASS_BRIDGE_PCI &&
+ check_for_io_childs(b, &tmp_res, &found_vga)) {
+ u8 io_base_lo;
+
+ printk(KERN_INFO "Fixing up IO bus %s\n", b->name);
+
+ if (found_vga) {
+ if (has_vga) {
+ printk(KERN_WARNING "Skipping VGA, already active"
+ " on bus segment\n");
+ found_vga = 0;
+ } else
+ has_vga = 1;
+ }
+ pci_read_config_byte(d, PCI_IO_BASE, &io_base_lo);
+
+ if ((io_base_lo & PCI_IO_RANGE_TYPE_MASK) == PCI_IO_RANGE_TYPE_32)
+ max = ((unsigned long) hose->io_base_virt
+ - isa_io_base) + 0xffffffff;
+ else
+ max = ((unsigned long) hose->io_base_virt
+ - isa_io_base) + 0xffff;
+
+ *res = tmp_res;
+ res->flags = IORESOURCE_IO;
+ res->name = b->name;
+
+ /* Find a resource in the parent where we can allocate */
+ for (i = 0 ; i < 4; i++) {
+ struct resource *r = bus->resource[i];
+ if (!r)
+ continue;
+ if ((r->flags & IORESOURCE_IO) == 0)
+ continue;
+ DBG("Trying to allocate from %08lx, size %08lx from parent"
+ " res %d: %08lx -> %08lx\n",
+ res->start, res->end, i, r->start, r->end);
+
+ if (allocate_resource(r, res, res->end + 1, res->start, max,
+ res->end + 1, NULL, NULL) < 0) {
+ DBG("Failed !\n");
+ continue;
+ }
+ do_update_p2p_io_resource(b, found_vga);
+ break;
+ }
+ }
+ do_fixup_p2p_level(b);
+ }
+}
+
+static void
+pcibios_fixup_p2p_bridges(void)
+{
+ struct pci_bus *b;
+
+ list_for_each_entry(b, &pci_root_buses, node)
+ do_fixup_p2p_level(b);
+}
+
+#endif /* CONFIG_PPC_PMAC */
+
+static int __init
+pcibios_init(void)
+{
+ struct pci_controller *hose;
+ struct pci_bus *bus;
+ int next_busno;
+
+ printk(KERN_INFO "PCI: Probing PCI hardware\n");
+
+ /* Scan all of the recorded PCI controllers. */
+ for (next_busno = 0, hose = hose_head; hose; hose = hose->next) {
+ if (pci_assign_all_busses)
+ hose->first_busno = next_busno;
+ hose->last_busno = 0xff;
+ bus = pci_scan_bus(hose->first_busno, hose->ops, hose);
+ hose->last_busno = bus->subordinate;
+ if (pci_assign_all_busses || next_busno <= hose->last_busno)
+ next_busno = hose->last_busno + pcibios_assign_bus_offset;
+ }
+ pci_bus_count = next_busno;
+
+ /* OpenFirmware based machines need a map of OF bus
+ * numbers vs. kernel bus numbers since we may have to
+ * remap them.
+ */
+ if (pci_assign_all_busses && have_of)
+ pcibios_make_OF_bus_map();
+
+ /* Do machine dependent PCI interrupt routing */
+ if (ppc_md.pci_swizzle && ppc_md.pci_map_irq)
+ pci_fixup_irqs(ppc_md.pci_swizzle, ppc_md.pci_map_irq);
+
+ /* Call machine dependent fixup */
+ if (ppc_md.pcibios_fixup)
+ ppc_md.pcibios_fixup();
+
+ /* Allocate and assign resources */
+ pcibios_allocate_bus_resources(&pci_root_buses);
+ pcibios_allocate_resources(0);
+ pcibios_allocate_resources(1);
+#ifdef CONFIG_PPC_PMAC
+ pcibios_fixup_p2p_bridges();
+#endif /* CONFIG_PPC_PMAC */
+ pcibios_assign_resources();
+
+ /* Call machine dependent post-init code */
+ if (ppc_md.pcibios_after_init)
+ ppc_md.pcibios_after_init();
+
+ return 0;
+}
+
+subsys_initcall(pcibios_init);
+
+unsigned char __init
+common_swizzle(struct pci_dev *dev, unsigned char *pinp)
+{
+ struct pci_controller *hose = dev->sysdata;
+
+ if (dev->bus->number != hose->first_busno) {
+ u8 pin = *pinp;
+ do {
+ pin = bridge_swizzle(pin, PCI_SLOT(dev->devfn));
+ /* Move up the chain of bridges. */
+ dev = dev->bus->self;
+ } while (dev->bus->self);
+ *pinp = pin;
+
+ /* The slot is the idsel of the last bridge. */
+ }
+ return PCI_SLOT(dev->devfn);
+}
+
+unsigned long resource_fixup(struct pci_dev * dev, struct resource * res,
+ unsigned long start, unsigned long size)
+{
+ return start;
+}
+
+void __init pcibios_fixup_bus(struct pci_bus *bus)
+{
+ struct pci_controller *hose = (struct pci_controller *) bus->sysdata;
+ unsigned long io_offset;
+ struct resource *res;
+ int i;
+
+ io_offset = (unsigned long)hose->io_base_virt - isa_io_base;
+ if (bus->parent == NULL) {
+ /* This is a host bridge - fill in its resources */
+ hose->bus = bus;
+
+ bus->resource[0] = res = &hose->io_resource;
+ if (!res->flags) {
+ if (io_offset)
+ printk(KERN_ERR "I/O resource not set for host"
+ " bridge %d\n", hose->index);
+ res->start = 0;
+ res->end = IO_SPACE_LIMIT;
+ res->flags = IORESOURCE_IO;
+ }
+ res->start += io_offset;
+ res->end += io_offset;
+
+ for (i = 0; i < 3; ++i) {
+ res = &hose->mem_resources[i];
+ if (!res->flags) {
+ if (i > 0)
+ continue;
+ printk(KERN_ERR "Memory resource not set for "
+ "host bridge %d\n", hose->index);
+ res->start = hose->pci_mem_offset;
+ res->end = ~0U;
+ res->flags = IORESOURCE_MEM;
+ }
+ bus->resource[i+1] = res;
+ }
+ } else {
+ /* This is a subordinate bridge */
+ pci_read_bridge_bases(bus);
+
+ for (i = 0; i < 4; ++i) {
+ if ((res = bus->resource[i]) == NULL)
+ continue;
+ if (!res->flags)
+ continue;
+ if (io_offset && (res->flags & IORESOURCE_IO)) {
+ res->start += io_offset;
+ res->end += io_offset;
+ } else if (hose->pci_mem_offset
+ && (res->flags & IORESOURCE_MEM)) {
+ res->start += hose->pci_mem_offset;
+ res->end += hose->pci_mem_offset;
+ }
+ }
+ }
+
+ if (ppc_md.pcibios_fixup_bus)
+ ppc_md.pcibios_fixup_bus(bus);
+}
+
+char __init *pcibios_setup(char *str)
+{
+ return str;
+}
+
+/* the next one is stolen from the alpha port... */
+void __init
+pcibios_update_irq(struct pci_dev *dev, int irq)
+{
+ pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq);
+ /* XXX FIXME - update OF device tree node interrupt property */
+}
+
+int pcibios_enable_device(struct pci_dev *dev, int mask)
+{
+ u16 cmd, old_cmd;
+ int idx;
+ struct resource *r;
+
+ if (ppc_md.pcibios_enable_device_hook)
+ if (ppc_md.pcibios_enable_device_hook(dev, 0))
+ return -EINVAL;
+
+ pci_read_config_word(dev, PCI_COMMAND, &cmd);
+ old_cmd = cmd;
+ for (idx=0; idx<6; idx++) {
+ r = &dev->resource[idx];
+ if (r->flags & IORESOURCE_UNSET) {
+ printk(KERN_ERR "PCI: Device %s not available because of resource collisions\n", pci_name(dev));
+ return -EINVAL;
+ }
+ if (r->flags & IORESOURCE_IO)
+ cmd |= PCI_COMMAND_IO;
+ if (r->flags & IORESOURCE_MEM)
+ cmd |= PCI_COMMAND_MEMORY;
+ }
+ if (cmd != old_cmd) {
+ printk("PCI: Enabling device %s (%04x -> %04x)\n",
+ pci_name(dev), old_cmd, cmd);
+ pci_write_config_word(dev, PCI_COMMAND, cmd);
+ }
+ return 0;
+}
+
+struct pci_controller*
+pci_bus_to_hose(int bus)
+{
+ struct pci_controller* hose = hose_head;
+
+ for (; hose; hose = hose->next)
+ if (bus >= hose->first_busno && bus <= hose->last_busno)
+ return hose;
+ return NULL;
+}
+
+void*
+pci_bus_io_base(unsigned int bus)
+{
+ struct pci_controller *hose;
+
+ hose = pci_bus_to_hose(bus);
+ if (!hose)
+ return NULL;
+ return hose->io_base_virt;
+}
+
+unsigned long
+pci_bus_io_base_phys(unsigned int bus)
+{
+ struct pci_controller *hose;
+
+ hose = pci_bus_to_hose(bus);
+ if (!hose)
+ return 0;
+ return hose->io_base_phys;
+}
+
+unsigned long
+pci_bus_mem_base_phys(unsigned int bus)
+{
+ struct pci_controller *hose;
+
+ hose = pci_bus_to_hose(bus);
+ if (!hose)
+ return 0;
+ return hose->pci_mem_offset;
+}
+
+unsigned long
+pci_resource_to_bus(struct pci_dev *pdev, struct resource *res)
+{
+ /* Hack alert again ! See comments in chrp_pci.c
+ */
+ struct pci_controller* hose =
+ (struct pci_controller *)pdev->sysdata;
+ if (hose && res->flags & IORESOURCE_MEM)
+ return res->start - hose->pci_mem_offset;
+ /* We may want to do something with IOs here... */
+ return res->start;
+}
+
+
+static struct resource *__pci_mmap_make_offset(struct pci_dev *dev,
+ unsigned long *offset,
+ enum pci_mmap_state mmap_state)
+{
+ struct pci_controller *hose = pci_bus_to_hose(dev->bus->number);
+ unsigned long io_offset = 0;
+ int i, res_bit;
+
+ if (hose == 0)
+ return NULL; /* should never happen */
+
+ /* If memory, add on the PCI bridge address offset */
+ if (mmap_state == pci_mmap_mem) {
+ *offset += hose->pci_mem_offset;
+ res_bit = IORESOURCE_MEM;
+ } else {
+ io_offset = (unsigned long)hose->io_base_virt;
+ *offset += io_offset;
+ res_bit = IORESOURCE_IO;
+ }
+
+ /*
+ * Check that the offset requested corresponds to one of the
+ * resources of the device.
+ */
+ for (i = 0; i <= PCI_ROM_RESOURCE; i++) {
+ struct resource *rp = &dev->resource[i];
+ int flags = rp->flags;
+
+ /* treat ROM as memory (should be already) */
+ if (i == PCI_ROM_RESOURCE)
+ flags |= IORESOURCE_MEM;
+
+ /* Active and same type? */
+ if ((flags & res_bit) == 0)
+ continue;
+
+ /* In the range of this resource? */
+ if (*offset < (rp->start & PAGE_MASK) || *offset > rp->end)
+ continue;
+
+ /* found it! construct the final physical address */
+ if (mmap_state == pci_mmap_io)
+ *offset += hose->io_base_phys - _IO_BASE;
+ return rp;
+ }
+
+ return NULL;
+}
+
+/*
+ * Set vm_page_prot of VMA, as appropriate for this architecture, for a pci
+ * device mapping.
+ */
+static pgprot_t __pci_mmap_set_pgprot(struct pci_dev *dev, struct resource *rp,
+ pgprot_t protection,
+ enum pci_mmap_state mmap_state,
+ int write_combine)
+{
+ unsigned long prot = pgprot_val(protection);
+
+ /* Write combine is always 0 on non-memory space mappings. On
+ * memory space, if the user didn't pass 1, we check for a
+ * "prefetchable" resource. This is a bit hackish, but we use
+ * this to workaround the inability of /sysfs to provide a write
+ * combine bit
+ */
+ if (mmap_state != pci_mmap_mem)
+ write_combine = 0;
+ else if (write_combine == 0) {
+ if (rp->flags & IORESOURCE_PREFETCH)
+ write_combine = 1;
+ }
+
+ /* XXX would be nice to have a way to ask for write-through */
+ prot |= _PAGE_NO_CACHE;
+ if (write_combine)
+ prot &= ~_PAGE_GUARDED;
+ else
+ prot |= _PAGE_GUARDED;
+
+ printk("PCI map for %s:%lx, prot: %lx\n", pci_name(dev), rp->start,
+ prot);
+
+ return __pgprot(prot);
+}
+
+/*
+ * This one is used by /dev/mem and fbdev who have no clue about the
+ * PCI device, it tries to find the PCI device first and calls the
+ * above routine
+ */
+pgprot_t pci_phys_mem_access_prot(struct file *file,
+ unsigned long offset,
+ unsigned long size,
+ pgprot_t protection)
+{
+ struct pci_dev *pdev = NULL;
+ struct resource *found = NULL;
+ unsigned long prot = pgprot_val(protection);
+ int i;
+
+ if (page_is_ram(offset >> PAGE_SHIFT))
+ return prot;
+
+ prot |= _PAGE_NO_CACHE | _PAGE_GUARDED;
+
+ for_each_pci_dev(pdev) {
+ for (i = 0; i <= PCI_ROM_RESOURCE; i++) {
+ struct resource *rp = &pdev->resource[i];
+ int flags = rp->flags;
+
+ /* Active and same type? */
+ if ((flags & IORESOURCE_MEM) == 0)
+ continue;
+ /* In the range of this resource? */
+ if (offset < (rp->start & PAGE_MASK) ||
+ offset > rp->end)
+ continue;
+ found = rp;
+ break;
+ }
+ if (found)
+ break;
+ }
+ if (found) {
+ if (found->flags & IORESOURCE_PREFETCH)
+ prot &= ~_PAGE_GUARDED;
+ pci_dev_put(pdev);
+ }
+
+ DBG("non-PCI map for %lx, prot: %lx\n", offset, prot);
+
+ return __pgprot(prot);
+}
+
+
+/*
+ * Perform the actual remap of the pages for a PCI device mapping, as
+ * appropriate for this architecture. The region in the process to map
+ * is described by vm_start and vm_end members of VMA, the base physical
+ * address is found in vm_pgoff.
+ * The pci device structure is provided so that architectures may make mapping
+ * decisions on a per-device or per-bus basis.
+ *
+ * Returns a negative error code on failure, zero on success.
+ */
+int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
+ enum pci_mmap_state mmap_state,
+ int write_combine)
+{
+ unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
+ struct resource *rp;
+ int ret;
+
+ rp = __pci_mmap_make_offset(dev, &offset, mmap_state);
+ if (rp == NULL)
+ return -EINVAL;
+
+ vma->vm_pgoff = offset >> PAGE_SHIFT;
+ vma->vm_flags |= VM_SHM | VM_LOCKED | VM_IO;
+ vma->vm_page_prot = __pci_mmap_set_pgprot(dev, rp,
+ vma->vm_page_prot,
+ mmap_state, write_combine);
+
+ ret = remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff,
+ vma->vm_end - vma->vm_start, vma->vm_page_prot);
+
+ return ret;
+}
+
+/* Obsolete functions. Should be removed once the symbios driver
+ * is fixed
+ */
+unsigned long
+phys_to_bus(unsigned long pa)
+{
+ struct pci_controller *hose;
+ int i;
+
+ for (hose = hose_head; hose; hose = hose->next) {
+ for (i = 0; i < 3; ++i) {
+ if (pa >= hose->mem_resources[i].start
+ && pa <= hose->mem_resources[i].end) {
+ /*
+ * XXX the hose->pci_mem_offset really
+ * only applies to mem_resources[0].
+ * We need a way to store an offset for
+ * the others. -- paulus
+ */
+ if (i == 0)
+ pa -= hose->pci_mem_offset;
+ return pa;
+ }
+ }
+ }
+ /* hmmm, didn't find it */
+ return 0;
+}
+
+unsigned long
+pci_phys_to_bus(unsigned long pa, int busnr)
+{
+ struct pci_controller* hose = pci_bus_to_hose(busnr);
+ if (!hose)
+ return pa;
+ return pa - hose->pci_mem_offset;
+}
+
+unsigned long
+pci_bus_to_phys(unsigned int ba, int busnr)
+{
+ struct pci_controller* hose = pci_bus_to_hose(busnr);
+ if (!hose)
+ return ba;
+ return ba + hose->pci_mem_offset;
+}
+
+/* Provide information on locations of various I/O regions in physical
+ * memory. Do this on a per-card basis so that we choose the right
+ * root bridge.
+ * Note that the returned IO or memory base is a physical address
+ */
+
+long sys_pciconfig_iobase(long which, unsigned long bus, unsigned long devfn)
+{
+ struct pci_controller* hose;
+ long result = -EOPNOTSUPP;
+
+ /* Argh ! Please forgive me for that hack, but that's the
+ * simplest way to get existing XFree to not lockup on some
+ * G5 machines... So when something asks for bus 0 io base
+ * (bus 0 is HT root), we return the AGP one instead.
+ */
+#ifdef CONFIG_PPC_PMAC
+ if (_machine == _MACH_Pmac && machine_is_compatible("MacRISC4"))
+ if (bus == 0)
+ bus = 0xf0;
+#endif /* CONFIG_PPC_PMAC */
+
+ hose = pci_bus_to_hose(bus);
+ if (!hose)
+ return -ENODEV;
+
+ switch (which) {
+ case IOBASE_BRIDGE_NUMBER:
+ return (long)hose->first_busno;
+ case IOBASE_MEMORY:
+ return (long)hose->pci_mem_offset;
+ case IOBASE_IO:
+ return (long)hose->io_base_phys;
+ case IOBASE_ISA_IO:
+ return (long)isa_io_base;
+ case IOBASE_ISA_MEM:
+ return (long)isa_mem_base;
+ }
+
+ return result;
+}
+
+void __init
+pci_init_resource(struct resource *res, unsigned long start, unsigned long end,
+ int flags, char *name)
+{
+ res->start = start;
+ res->end = end;
+ res->flags = flags;
+ res->name = name;
+ res->parent = NULL;
+ res->sibling = NULL;
+ res->child = NULL;
+}
+
+void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long max)
+{
+ unsigned long start = pci_resource_start(dev, bar);
+ unsigned long len = pci_resource_len(dev, bar);
+ unsigned long flags = pci_resource_flags(dev, bar);
+
+ if (!len)
+ return NULL;
+ if (max && len > max)
+ len = max;
+ if (flags & IORESOURCE_IO)
+ return ioport_map(start, len);
+ if (flags & IORESOURCE_MEM)
+ /* Not checking IORESOURCE_CACHEABLE because PPC does
+ * not currently distinguish between ioremap and
+ * ioremap_nocache.
+ */
+ return ioremap(start, len);
+ /* What? */
+ return NULL;
+}
+
+void pci_iounmap(struct pci_dev *dev, void __iomem *addr)
+{
+ /* Nothing to do */
+}
+EXPORT_SYMBOL(pci_iomap);
+EXPORT_SYMBOL(pci_iounmap);
+
+
+/*
+ * Null PCI config access functions, for the case when we can't
+ * find a hose.
+ */
+#define NULL_PCI_OP(rw, size, type) \
+static int \
+null_##rw##_config_##size(struct pci_dev *dev, int offset, type val) \
+{ \
+ return PCIBIOS_DEVICE_NOT_FOUND; \
+}
+
+static int
+null_read_config(struct pci_bus *bus, unsigned int devfn, int offset,
+ int len, u32 *val)
+{
+ return PCIBIOS_DEVICE_NOT_FOUND;
+}
+
+static int
+null_write_config(struct pci_bus *bus, unsigned int devfn, int offset,
+ int len, u32 val)
+{
+ return PCIBIOS_DEVICE_NOT_FOUND;
+}
+
+static struct pci_ops null_pci_ops =
+{
+ null_read_config,
+ null_write_config
+};
+
+/*
+ * These functions are used early on before PCI scanning is done
+ * and all of the pci_dev and pci_bus structures have been created.
+ */
+static struct pci_bus *
+fake_pci_bus(struct pci_controller *hose, int busnr)
+{
+ static struct pci_bus bus;
+
+ if (hose == 0) {
+ hose = pci_bus_to_hose(busnr);
+ if (hose == 0)
+ printk(KERN_ERR "Can't find hose for PCI bus %d!\n", busnr);
+ }
+ bus.number = busnr;
+ bus.sysdata = hose;
+ bus.ops = hose? hose->ops: &null_pci_ops;
+ return &bus;
+}
+
+#define EARLY_PCI_OP(rw, size, type) \
+int early_##rw##_config_##size(struct pci_controller *hose, int bus, \
+ int devfn, int offset, type value) \
+{ \
+ return pci_bus_##rw##_config_##size(fake_pci_bus(hose, bus), \
+ devfn, offset, value); \
+}
+
+EARLY_PCI_OP(read, byte, u8 *)
+EARLY_PCI_OP(read, word, u16 *)
+EARLY_PCI_OP(read, dword, u32 *)
+EARLY_PCI_OP(write, byte, u8)
+EARLY_PCI_OP(write, word, u16)
+EARLY_PCI_OP(write, dword, u32)
diff --git a/arch/ppc/kernel/perfmon.c b/arch/ppc/kernel/perfmon.c
new file mode 100644
index 0000000..918f6b2
--- /dev/null
+++ b/arch/ppc/kernel/perfmon.c
@@ -0,0 +1,93 @@
+/* kernel/perfmon.c
+ * PPC 32 Performance Monitor Infrastructure
+ *
+ * Author: Andy Fleming
+ * Copyright (c) 2004 Freescale Semiconductor, Inc
+ *
+ * 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.
+ */
+
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/stddef.h>
+#include <linux/unistd.h>
+#include <linux/ptrace.h>
+#include <linux/slab.h>
+#include <linux/user.h>
+#include <linux/a.out.h>
+#include <linux/interrupt.h>
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/prctl.h>
+
+#include <asm/pgtable.h>
+#include <asm/uaccess.h>
+#include <asm/system.h>
+#include <asm/io.h>
+#include <asm/reg.h>
+#include <asm/xmon.h>
+
+/* A lock to regulate grabbing the interrupt */
+DEFINE_SPINLOCK(perfmon_lock);
+
+#ifdef CONFIG_FSL_BOOKE
+static void dummy_perf(struct pt_regs *regs)
+{
+ unsigned int pmgc0 = mfpmr(PMRN_PMGC0);
+
+ pmgc0 &= ~PMGC0_PMIE;
+ mtpmr(PMRN_PMGC0, pmgc0);
+}
+
+#else
+/* Ensure exceptions are disabled */
+
+static void dummy_perf(struct pt_regs *regs)
+{
+ unsigned int mmcr0 = mfspr(SPRN_MMCR0);
+
+ mmcr0 &= ~MMCR0_PMXE;
+ mtspr(SPRN_MMCR0, mmcr0);
+}
+#endif
+
+void (*perf_irq)(struct pt_regs *) = dummy_perf;
+
+/* Grab the interrupt, if it's free.
+ * Returns 0 on success, -1 if the interrupt is taken already */
+int request_perfmon_irq(void (*handler)(struct pt_regs *))
+{
+ int err = 0;
+
+ spin_lock(&perfmon_lock);
+
+ if (perf_irq == dummy_perf)
+ perf_irq = handler;
+ else {
+ pr_info("perfmon irq already handled by %p\n", perf_irq);
+ err = -1;
+ }
+
+ spin_unlock(&perfmon_lock);
+
+ return err;
+}
+
+void free_perfmon_irq(void)
+{
+ spin_lock(&perfmon_lock);
+
+ perf_irq = dummy_perf;
+
+ spin_unlock(&perfmon_lock);
+}
+
+EXPORT_SYMBOL(perf_irq);
+EXPORT_SYMBOL(request_perfmon_irq);
+EXPORT_SYMBOL(free_perfmon_irq);
diff --git a/arch/ppc/kernel/perfmon_fsl_booke.c b/arch/ppc/kernel/perfmon_fsl_booke.c
new file mode 100644
index 0000000..03526bf
--- /dev/null
+++ b/arch/ppc/kernel/perfmon_fsl_booke.c
@@ -0,0 +1,222 @@
+/* kernel/perfmon_fsl_booke.c
+ * Freescale Book-E Performance Monitor code
+ *
+ * Author: Andy Fleming
+ * Copyright (c) 2004 Freescale Semiconductor, Inc
+ *
+ * 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.
+ */
+
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/stddef.h>
+#include <linux/unistd.h>
+#include <linux/ptrace.h>
+#include <linux/slab.h>
+#include <linux/user.h>
+#include <linux/a.out.h>
+#include <linux/interrupt.h>
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/prctl.h>
+
+#include <asm/pgtable.h>
+#include <asm/uaccess.h>
+#include <asm/system.h>
+#include <asm/io.h>
+#include <asm/reg.h>
+#include <asm/xmon.h>
+#include <asm/perfmon.h>
+
+static inline u32 get_pmlca(int ctr);
+static inline void set_pmlca(int ctr, u32 pmlca);
+
+static inline u32 get_pmlca(int ctr)
+{
+ u32 pmlca;
+
+ switch (ctr) {
+ case 0:
+ pmlca = mfpmr(PMRN_PMLCA0);
+ break;
+ case 1:
+ pmlca = mfpmr(PMRN_PMLCA1);
+ break;
+ case 2:
+ pmlca = mfpmr(PMRN_PMLCA2);
+ break;
+ case 3:
+ pmlca = mfpmr(PMRN_PMLCA3);
+ break;
+ default:
+ panic("Bad ctr number\n");
+ }
+
+ return pmlca;
+}
+
+static inline void set_pmlca(int ctr, u32 pmlca)
+{
+ switch (ctr) {
+ case 0:
+ mtpmr(PMRN_PMLCA0, pmlca);
+ break;
+ case 1:
+ mtpmr(PMRN_PMLCA1, pmlca);
+ break;
+ case 2:
+ mtpmr(PMRN_PMLCA2, pmlca);
+ break;
+ case 3:
+ mtpmr(PMRN_PMLCA3, pmlca);
+ break;
+ default:
+ panic("Bad ctr number\n");
+ }
+}
+
+void init_pmc_stop(int ctr)
+{
+ u32 pmlca = (PMLCA_FC | PMLCA_FCS | PMLCA_FCU |
+ PMLCA_FCM1 | PMLCA_FCM0);
+ u32 pmlcb = 0;
+
+ switch (ctr) {
+ case 0:
+ mtpmr(PMRN_PMLCA0, pmlca);
+ mtpmr(PMRN_PMLCB0, pmlcb);
+ break;
+ case 1:
+ mtpmr(PMRN_PMLCA1, pmlca);
+ mtpmr(PMRN_PMLCB1, pmlcb);
+ break;
+ case 2:
+ mtpmr(PMRN_PMLCA2, pmlca);
+ mtpmr(PMRN_PMLCB2, pmlcb);
+ break;
+ case 3:
+ mtpmr(PMRN_PMLCA3, pmlca);
+ mtpmr(PMRN_PMLCB3, pmlcb);
+ break;
+ default:
+ panic("Bad ctr number!\n");
+ }
+}
+
+void set_pmc_event(int ctr, int event)
+{
+ u32 pmlca;
+
+ pmlca = get_pmlca(ctr);
+
+ pmlca = (pmlca & ~PMLCA_EVENT_MASK) |
+ ((event << PMLCA_EVENT_SHIFT) &
+ PMLCA_EVENT_MASK);
+
+ set_pmlca(ctr, pmlca);
+}
+
+void set_pmc_user_kernel(int ctr, int user, int kernel)
+{
+ u32 pmlca;
+
+ pmlca = get_pmlca(ctr);
+
+ if(user)
+ pmlca &= ~PMLCA_FCU;
+ else
+ pmlca |= PMLCA_FCU;
+
+ if(kernel)
+ pmlca &= ~PMLCA_FCS;
+ else
+ pmlca |= PMLCA_FCS;
+
+ set_pmlca(ctr, pmlca);
+}
+
+void set_pmc_marked(int ctr, int mark0, int mark1)
+{
+ u32 pmlca = get_pmlca(ctr);
+
+ if(mark0)
+ pmlca &= ~PMLCA_FCM0;
+ else
+ pmlca |= PMLCA_FCM0;
+
+ if(mark1)
+ pmlca &= ~PMLCA_FCM1;
+ else
+ pmlca |= PMLCA_FCM1;
+
+ set_pmlca(ctr, pmlca);
+}
+
+void pmc_start_ctr(int ctr, int enable)
+{
+ u32 pmlca = get_pmlca(ctr);
+
+ pmlca &= ~PMLCA_FC;
+
+ if (enable)
+ pmlca |= PMLCA_CE;
+ else
+ pmlca &= ~PMLCA_CE;
+
+ set_pmlca(ctr, pmlca);
+}
+
+void pmc_start_ctrs(int enable)
+{
+ u32 pmgc0 = mfpmr(PMRN_PMGC0);
+
+ pmgc0 &= ~PMGC0_FAC;
+ pmgc0 |= PMGC0_FCECE;
+
+ if (enable)
+ pmgc0 |= PMGC0_PMIE;
+ else
+ pmgc0 &= ~PMGC0_PMIE;
+
+ mtpmr(PMRN_PMGC0, pmgc0);
+}
+
+void pmc_stop_ctrs(void)
+{
+ u32 pmgc0 = mfpmr(PMRN_PMGC0);
+
+ pmgc0 |= PMGC0_FAC;
+
+ pmgc0 &= ~(PMGC0_PMIE | PMGC0_FCECE);
+
+ mtpmr(PMRN_PMGC0, pmgc0);
+}
+
+void dump_pmcs(void)
+{
+ printk("pmgc0: %x\n", mfpmr(PMRN_PMGC0));
+ printk("pmc\t\tpmlca\t\tpmlcb\n");
+ printk("%8x\t%8x\t%8x\n", mfpmr(PMRN_PMC0),
+ mfpmr(PMRN_PMLCA0), mfpmr(PMRN_PMLCB0));
+ printk("%8x\t%8x\t%8x\n", mfpmr(PMRN_PMC1),
+ mfpmr(PMRN_PMLCA1), mfpmr(PMRN_PMLCB1));
+ printk("%8x\t%8x\t%8x\n", mfpmr(PMRN_PMC2),
+ mfpmr(PMRN_PMLCA2), mfpmr(PMRN_PMLCB2));
+ printk("%8x\t%8x\t%8x\n", mfpmr(PMRN_PMC3),
+ mfpmr(PMRN_PMLCA3), mfpmr(PMRN_PMLCB3));
+}
+
+EXPORT_SYMBOL(init_pmc_stop);
+EXPORT_SYMBOL(set_pmc_event);
+EXPORT_SYMBOL(set_pmc_user_kernel);
+EXPORT_SYMBOL(set_pmc_marked);
+EXPORT_SYMBOL(pmc_start_ctr);
+EXPORT_SYMBOL(pmc_start_ctrs);
+EXPORT_SYMBOL(pmc_stop_ctrs);
+EXPORT_SYMBOL(dump_pmcs);
diff --git a/arch/ppc/kernel/ppc-stub.c b/arch/ppc/kernel/ppc-stub.c
new file mode 100644
index 0000000..d61889c
--- /dev/null
+++ b/arch/ppc/kernel/ppc-stub.c
@@ -0,0 +1,867 @@
+/*
+ * ppc-stub.c: KGDB support for the Linux kernel.
+ *
+ * adapted from arch/sparc/kernel/sparc-stub.c for the PowerPC
+ * some stuff borrowed from Paul Mackerras' xmon
+ * Copyright (C) 1998 Michael AK Tesch (tesch@cs.wisc.edu)
+ *
+ * Modifications to run under Linux
+ * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
+ *
+ * This file originally came from the gdb sources, and the
+ * copyright notices have been retained below.
+ */
+
+/****************************************************************************
+
+ THIS SOFTWARE IS NOT COPYRIGHTED
+
+ HP offers the following for use in the public domain. HP makes no
+ warranty with regard to the software or its performance and the
+ user accepts the software "AS IS" with all faults.
+
+ HP DISCLAIMS ANY WARRANTIES, EXPRESS OR IMPLIED, WITH REGARD
+ TO THIS SOFTWARE INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+
+****************************************************************************/
+
+/****************************************************************************
+ * Header: remcom.c,v 1.34 91/03/09 12:29:49 glenne Exp $
+ *
+ * Module name: remcom.c $
+ * Revision: 1.34 $
+ * Date: 91/03/09 12:29:49 $
+ * Contributor: Lake Stevens Instrument Division$
+ *
+ * Description: low level support for gdb debugger. $
+ *
+ * Considerations: only works on target hardware $
+ *
+ * Written by: Glenn Engel $
+ * ModuleState: Experimental $
+ *
+ * NOTES: See Below $
+ *
+ * Modified for SPARC by Stu Grossman, Cygnus Support.
+ *
+ * This code has been extensively tested on the Fujitsu SPARClite demo board.
+ *
+ * To enable debugger support, two things need to happen. One, a
+ * call to set_debug_traps() is necessary in order to allow any breakpoints
+ * or error conditions to be properly intercepted and reported to gdb.
+ * Two, a breakpoint needs to be generated to begin communication. This
+ * is most easily accomplished by a call to breakpoint(). Breakpoint()
+ * simulates a breakpoint by executing a trap #1.
+ *
+ *************
+ *
+ * The following gdb commands are supported:
+ *
+ * command function Return value
+ *
+ * g return the value of the CPU registers hex data or ENN
+ * G set the value of the CPU registers OK or ENN
+ * qOffsets Get section offsets. Reply is Text=xxx;Data=yyy;Bss=zzz
+ *
+ * mAA..AA,LLLL Read LLLL bytes at address AA..AA hex data or ENN
+ * MAA..AA,LLLL: Write LLLL bytes at address AA.AA OK or ENN
+ *
+ * c Resume at current address SNN ( signal NN)
+ * cAA..AA Continue at address AA..AA SNN
+ *
+ * s Step one instruction SNN
+ * sAA..AA Step one instruction from AA..AA SNN
+ *
+ * k kill
+ *
+ * ? What was the last sigval ? SNN (signal NN)
+ *
+ * bBB..BB Set baud rate to BB..BB OK or BNN, then sets
+ * baud rate
+ *
+ * All commands and responses are sent with a packet which includes a
+ * checksum. A packet consists of
+ *
+ * $<packet info>#<checksum>.
+ *
+ * where
+ * <packet info> :: <characters representing the command or response>
+ * <checksum> :: <two hex digits computed as modulo 256 sum of <packetinfo>>
+ *
+ * When a packet is received, it is first acknowledged with either '+' or '-'.
+ * '+' indicates a successful transfer. '-' indicates a failed transfer.
+ *
+ * Example:
+ *
+ * Host: Reply:
+ * $m0,10#2a +$00010203040506070809101112131415#42
+ *
+ ****************************************************************************/
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/smp.h>
+#include <linux/smp_lock.h>
+#include <linux/init.h>
+#include <linux/sysrq.h>
+
+#include <asm/cacheflush.h>
+#include <asm/system.h>
+#include <asm/signal.h>
+#include <asm/kgdb.h>
+#include <asm/pgtable.h>
+#include <asm/ptrace.h>
+
+void breakinst(void);
+
+/*
+ * BUFMAX defines the maximum number of characters in inbound/outbound buffers
+ * at least NUMREGBYTES*2 are needed for register packets
+ */
+#define BUFMAX 2048
+static char remcomInBuffer[BUFMAX];
+static char remcomOutBuffer[BUFMAX];
+
+static int initialized;
+static int kgdb_active;
+static int kgdb_started;
+static u_int fault_jmp_buf[100];
+static int kdebug;
+
+
+static const char hexchars[]="0123456789abcdef";
+
+/* Place where we save old trap entries for restoration - sparc*/
+/* struct tt_entry kgdb_savettable[256]; */
+/* typedef void (*trapfunc_t)(void); */
+
+static void kgdb_fault_handler(struct pt_regs *regs);
+static int handle_exception (struct pt_regs *regs);
+
+#if 0
+/* Install an exception handler for kgdb */
+static void exceptionHandler(int tnum, unsigned int *tfunc)
+{
+ /* We are dorking with a live trap table, all irqs off */
+}
+#endif
+
+int
+kgdb_setjmp(long *buf)
+{
+ asm ("mflr 0; stw 0,0(%0);"
+ "stw 1,4(%0); stw 2,8(%0);"
+ "mfcr 0; stw 0,12(%0);"
+ "stmw 13,16(%0)"
+ : : "r" (buf));
+ /* XXX should save fp regs as well */
+ return 0;
+}
+void
+kgdb_longjmp(long *buf, int val)
+{
+ if (val == 0)
+ val = 1;
+ asm ("lmw 13,16(%0);"
+ "lwz 0,12(%0); mtcrf 0x38,0;"
+ "lwz 0,0(%0); lwz 1,4(%0); lwz 2,8(%0);"
+ "mtlr 0; mr 3,%1"
+ : : "r" (buf), "r" (val));
+}
+/* Convert ch from a hex digit to an int */
+static int
+hex(unsigned char ch)
+{
+ if (ch >= 'a' && ch <= 'f')
+ return ch-'a'+10;
+ if (ch >= '0' && ch <= '9')
+ return ch-'0';
+ if (ch >= 'A' && ch <= 'F')
+ return ch-'A'+10;
+ return -1;
+}
+
+/* Convert the memory pointed to by mem into hex, placing result in buf.
+ * Return a pointer to the last char put in buf (null), in case of mem fault,
+ * return 0.
+ */
+static unsigned char *
+mem2hex(const char *mem, char *buf, int count)
+{
+ unsigned char ch;
+ unsigned short tmp_s;
+ unsigned long tmp_l;
+
+ if (kgdb_setjmp((long*)fault_jmp_buf) == 0) {
+ debugger_fault_handler = kgdb_fault_handler;
+
+ /* Accessing 16 bit and 32 bit objects in a single
+ ** load instruction is required to avoid bad side
+ ** effects for some IO registers.
+ */
+
+ if ((count == 2) && (((long)mem & 1) == 0)) {
+ tmp_s = *(unsigned short *)mem;
+ mem += 2;
+ *buf++ = hexchars[(tmp_s >> 12) & 0xf];
+ *buf++ = hexchars[(tmp_s >> 8) & 0xf];
+ *buf++ = hexchars[(tmp_s >> 4) & 0xf];
+ *buf++ = hexchars[tmp_s & 0xf];
+
+ } else if ((count == 4) && (((long)mem & 3) == 0)) {
+ tmp_l = *(unsigned int *)mem;
+ mem += 4;
+ *buf++ = hexchars[(tmp_l >> 28) & 0xf];
+ *buf++ = hexchars[(tmp_l >> 24) & 0xf];
+ *buf++ = hexchars[(tmp_l >> 20) & 0xf];
+ *buf++ = hexchars[(tmp_l >> 16) & 0xf];
+ *buf++ = hexchars[(tmp_l >> 12) & 0xf];
+ *buf++ = hexchars[(tmp_l >> 8) & 0xf];
+ *buf++ = hexchars[(tmp_l >> 4) & 0xf];
+ *buf++ = hexchars[tmp_l & 0xf];
+
+ } else {
+ while (count-- > 0) {
+ ch = *mem++;
+ *buf++ = hexchars[ch >> 4];
+ *buf++ = hexchars[ch & 0xf];
+ }
+ }
+
+ } else {
+ /* error condition */
+ }
+ debugger_fault_handler = NULL;
+ *buf = 0;
+ return buf;
+}
+
+/* convert the hex array pointed to by buf into binary to be placed in mem
+ * return a pointer to the character AFTER the last byte written.
+*/
+static char *
+hex2mem(char *buf, char *mem, int count)
+{
+ unsigned char ch;
+ int i;
+ char *orig_mem;
+ unsigned short tmp_s;
+ unsigned long tmp_l;
+
+ orig_mem = mem;
+
+ if (kgdb_setjmp((long*)fault_jmp_buf) == 0) {
+ debugger_fault_handler = kgdb_fault_handler;
+
+ /* Accessing 16 bit and 32 bit objects in a single
+ ** store instruction is required to avoid bad side
+ ** effects for some IO registers.
+ */
+
+ if ((count == 2) && (((long)mem & 1) == 0)) {
+ tmp_s = hex(*buf++) << 12;
+ tmp_s |= hex(*buf++) << 8;
+ tmp_s |= hex(*buf++) << 4;
+ tmp_s |= hex(*buf++);
+
+ *(unsigned short *)mem = tmp_s;
+ mem += 2;
+
+ } else if ((count == 4) && (((long)mem & 3) == 0)) {
+ tmp_l = hex(*buf++) << 28;
+ tmp_l |= hex(*buf++) << 24;
+ tmp_l |= hex(*buf++) << 20;
+ tmp_l |= hex(*buf++) << 16;
+ tmp_l |= hex(*buf++) << 12;
+ tmp_l |= hex(*buf++) << 8;
+ tmp_l |= hex(*buf++) << 4;
+ tmp_l |= hex(*buf++);
+
+ *(unsigned long *)mem = tmp_l;
+ mem += 4;
+
+ } else {
+ for (i=0; i<count; i++) {
+ ch = hex(*buf++) << 4;
+ ch |= hex(*buf++);
+ *mem++ = ch;
+ }
+ }
+
+
+ /*
+ ** Flush the data cache, invalidate the instruction cache.
+ */
+ flush_icache_range((int)orig_mem, (int)orig_mem + count - 1);
+
+ } else {
+ /* error condition */
+ }
+ debugger_fault_handler = NULL;
+ return mem;
+}
+
+/*
+ * While we find nice hex chars, build an int.
+ * Return number of chars processed.
+ */
+static int
+hexToInt(char **ptr, int *intValue)
+{
+ int numChars = 0;
+ int hexValue;
+
+ *intValue = 0;
+
+ if (kgdb_setjmp((long*)fault_jmp_buf) == 0) {
+ debugger_fault_handler = kgdb_fault_handler;
+ while (**ptr) {
+ hexValue = hex(**ptr);
+ if (hexValue < 0)
+ break;
+
+ *intValue = (*intValue << 4) | hexValue;
+ numChars ++;
+
+ (*ptr)++;
+ }
+ } else {
+ /* error condition */
+ }
+ debugger_fault_handler = NULL;
+
+ return (numChars);
+}
+
+/* scan for the sequence $<data>#<checksum> */
+static void
+getpacket(char *buffer)
+{
+ unsigned char checksum;
+ unsigned char xmitcsum;
+ int i;
+ int count;
+ unsigned char ch;
+
+ do {
+ /* wait around for the start character, ignore all other
+ * characters */
+ while ((ch = (getDebugChar() & 0x7f)) != '$') ;
+
+ checksum = 0;
+ xmitcsum = -1;
+
+ count = 0;
+
+ /* now, read until a # or end of buffer is found */
+ while (count < BUFMAX) {
+ ch = getDebugChar() & 0x7f;
+ if (ch == '#')
+ break;
+ checksum = checksum + ch;
+ buffer[count] = ch;
+ count = count + 1;
+ }
+
+ if (count >= BUFMAX)
+ continue;
+
+ buffer[count] = 0;
+
+ if (ch == '#') {
+ xmitcsum = hex(getDebugChar() & 0x7f) << 4;
+ xmitcsum |= hex(getDebugChar() & 0x7f);
+ if (checksum != xmitcsum)
+ putDebugChar('-'); /* failed checksum */
+ else {
+ putDebugChar('+'); /* successful transfer */
+ /* if a sequence char is present, reply the ID */
+ if (buffer[2] == ':') {
+ putDebugChar(buffer[0]);
+ putDebugChar(buffer[1]);
+ /* remove sequence chars from buffer */
+ count = strlen(buffer);
+ for (i=3; i <= count; i++)
+ buffer[i-3] = buffer[i];
+ }
+ }
+ }
+ } while (checksum != xmitcsum);
+}
+
+/* send the packet in buffer. */
+static void putpacket(unsigned char *buffer)
+{
+ unsigned char checksum;
+ int count;
+ unsigned char ch, recv;
+
+ /* $<packet info>#<checksum>. */
+ do {
+ putDebugChar('$');
+ checksum = 0;
+ count = 0;
+
+ while ((ch = buffer[count])) {
+ putDebugChar(ch);
+ checksum += ch;
+ count += 1;
+ }
+
+ putDebugChar('#');
+ putDebugChar(hexchars[checksum >> 4]);
+ putDebugChar(hexchars[checksum & 0xf]);
+ recv = getDebugChar();
+ } while ((recv & 0x7f) != '+');
+}
+
+static void kgdb_flush_cache_all(void)
+{
+ flush_instruction_cache();
+}
+
+/* Set up exception handlers for tracing and breakpoints
+ * [could be called kgdb_init()]
+ */
+void set_debug_traps(void)
+{
+#if 0
+ unsigned char c;
+
+ save_and_cli(flags);
+
+ /* In case GDB is started before us, ack any packets (presumably
+ * "$?#xx") sitting there.
+ *
+ * I've found this code causes more problems than it solves,
+ * so that's why it's commented out. GDB seems to work fine
+ * now starting either before or after the kernel -bwb
+ */
+
+ while((c = getDebugChar()) != '$');
+ while((c = getDebugChar()) != '#');
+ c = getDebugChar(); /* eat first csum byte */
+ c = getDebugChar(); /* eat second csum byte */
+ putDebugChar('+'); /* ack it */
+#endif
+ debugger = kgdb;
+ debugger_bpt = kgdb_bpt;
+ debugger_sstep = kgdb_sstep;
+ debugger_iabr_match = kgdb_iabr_match;
+ debugger_dabr_match = kgdb_dabr_match;
+
+ initialized = 1;
+}
+
+static void kgdb_fault_handler(struct pt_regs *regs)
+{
+ kgdb_longjmp((long*)fault_jmp_buf, 1);
+}
+
+int kgdb_bpt(struct pt_regs *regs)
+{
+ return handle_exception(regs);
+}
+
+int kgdb_sstep(struct pt_regs *regs)
+{
+ return handle_exception(regs);
+}
+
+void kgdb(struct pt_regs *regs)
+{
+ handle_exception(regs);
+}
+
+int kgdb_iabr_match(struct pt_regs *regs)
+{
+ printk(KERN_ERR "kgdb doesn't support iabr, what?!?\n");
+ return handle_exception(regs);
+}
+
+int kgdb_dabr_match(struct pt_regs *regs)
+{
+ printk(KERN_ERR "kgdb doesn't support dabr, what?!?\n");
+ return handle_exception(regs);
+}
+
+/* Convert the hardware trap type code to a unix signal number. */
+/*
+ * This table contains the mapping between PowerPC hardware trap types, and
+ * signals, which are primarily what GDB understands.
+ */
+static struct hard_trap_info
+{
+ unsigned int tt; /* Trap type code for powerpc */
+ unsigned char signo; /* Signal that we map this trap into */
+} hard_trap_info[] = {
+#if defined(CONFIG_40x) || defined(CONFIG_BOOKE)
+ { 0x100, SIGINT }, /* critical input interrupt */
+ { 0x200, SIGSEGV }, /* machine check */
+ { 0x300, SIGSEGV }, /* data storage */
+ { 0x400, SIGBUS }, /* instruction storage */
+ { 0x500, SIGINT }, /* interrupt */
+ { 0x600, SIGBUS }, /* alignment */
+ { 0x700, SIGILL }, /* program */
+ { 0x800, SIGILL }, /* reserved */
+ { 0x900, SIGILL }, /* reserved */
+ { 0xa00, SIGILL }, /* reserved */
+ { 0xb00, SIGILL }, /* reserved */
+ { 0xc00, SIGCHLD }, /* syscall */
+ { 0xd00, SIGILL }, /* reserved */
+ { 0xe00, SIGILL }, /* reserved */
+ { 0xf00, SIGILL }, /* reserved */
+ /*
+ ** 0x1000 PIT
+ ** 0x1010 FIT
+ ** 0x1020 watchdog
+ ** 0x1100 data TLB miss
+ ** 0x1200 instruction TLB miss
+ */
+ { 0x2002, SIGTRAP}, /* debug */
+#else
+ { 0x200, SIGSEGV }, /* machine check */
+ { 0x300, SIGSEGV }, /* address error (store) */
+ { 0x400, SIGBUS }, /* instruction bus error */
+ { 0x500, SIGINT }, /* interrupt */
+ { 0x600, SIGBUS }, /* alingment */
+ { 0x700, SIGTRAP }, /* breakpoint trap */
+ { 0x800, SIGFPE }, /* fpu unavail */
+ { 0x900, SIGALRM }, /* decrementer */
+ { 0xa00, SIGILL }, /* reserved */
+ { 0xb00, SIGILL }, /* reserved */
+ { 0xc00, SIGCHLD }, /* syscall */
+ { 0xd00, SIGTRAP }, /* single-step/watch */
+ { 0xe00, SIGFPE }, /* fp assist */
+#endif
+ { 0, 0} /* Must be last */
+
+};
+
+static int computeSignal(unsigned int tt)
+{
+ struct hard_trap_info *ht;
+
+ for (ht = hard_trap_info; ht->tt && ht->signo; ht++)
+ if (ht->tt == tt)
+ return ht->signo;
+
+ return SIGHUP; /* default for things we don't know about */
+}
+
+#define PC_REGNUM 64
+#define SP_REGNUM 1
+
+/*
+ * This function does all command processing for interfacing to gdb.
+ */
+static int
+handle_exception (struct pt_regs *regs)
+{
+ int sigval;
+ int addr;
+ int length;
+ char *ptr;
+ unsigned int msr;
+
+ /* We don't handle user-mode breakpoints. */
+ if (user_mode(regs))
+ return 0;
+
+ if (debugger_fault_handler) {
+ debugger_fault_handler(regs);
+ panic("kgdb longjump failed!\n");
+ }
+ if (kgdb_active) {
+ printk(KERN_ERR "interrupt while in kgdb, returning\n");
+ return 0;
+ }
+
+ kgdb_active = 1;
+ kgdb_started = 1;
+
+#ifdef KGDB_DEBUG
+ printk("kgdb: entering handle_exception; trap [0x%x]\n",
+ (unsigned int)regs->trap);
+#endif
+
+ kgdb_interruptible(0);
+ lock_kernel();
+ msr = mfmsr();
+ mtmsr(msr & ~MSR_EE); /* disable interrupts */
+
+ if (regs->nip == (unsigned long)breakinst) {
+ /* Skip over breakpoint trap insn */
+ regs->nip += 4;
+ }
+
+ /* reply to host that an exception has occurred */
+ sigval = computeSignal(regs->trap);
+ ptr = remcomOutBuffer;
+
+ *ptr++ = 'T';
+ *ptr++ = hexchars[sigval >> 4];
+ *ptr++ = hexchars[sigval & 0xf];
+ *ptr++ = hexchars[PC_REGNUM >> 4];
+ *ptr++ = hexchars[PC_REGNUM & 0xf];
+ *ptr++ = ':';
+ ptr = mem2hex((char *)®s->nip, ptr, 4);
+ *ptr++ = ';';
+ *ptr++ = hexchars[SP_REGNUM >> 4];
+ *ptr++ = hexchars[SP_REGNUM & 0xf];
+ *ptr++ = ':';
+ ptr = mem2hex(((char *)regs) + SP_REGNUM*4, ptr, 4);
+ *ptr++ = ';';
+ *ptr++ = 0;
+
+ putpacket(remcomOutBuffer);
+ if (kdebug)
+ printk("remcomOutBuffer: %s\n", remcomOutBuffer);
+
+ /* XXX We may want to add some features dealing with poking the
+ * XXX page tables, ... (look at sparc-stub.c for more info)
+ * XXX also required hacking to the gdb sources directly...
+ */
+
+ while (1) {
+ remcomOutBuffer[0] = 0;
+
+ getpacket(remcomInBuffer);
+ switch (remcomInBuffer[0]) {
+ case '?': /* report most recent signal */
+ remcomOutBuffer[0] = 'S';
+ remcomOutBuffer[1] = hexchars[sigval >> 4];
+ remcomOutBuffer[2] = hexchars[sigval & 0xf];
+ remcomOutBuffer[3] = 0;
+ break;
+#if 0
+ case 'q': /* this screws up gdb for some reason...*/
+ {
+ extern long _start, sdata, __bss_start;
+
+ ptr = &remcomInBuffer[1];
+ if (strncmp(ptr, "Offsets", 7) != 0)
+ break;
+
+ ptr = remcomOutBuffer;
+ sprintf(ptr, "Text=%8.8x;Data=%8.8x;Bss=%8.8x",
+ &_start, &sdata, &__bss_start);
+ break;
+ }
+#endif
+ case 'd':
+ /* toggle debug flag */
+ kdebug ^= 1;
+ break;
+
+ case 'g': /* return the value of the CPU registers.
+ * some of them are non-PowerPC names :(
+ * they are stored in gdb like:
+ * struct {
+ * u32 gpr[32];
+ * f64 fpr[32];
+ * u32 pc, ps, cnd, lr; (ps=msr)
+ * u32 cnt, xer, mq;
+ * }
+ */
+ {
+ int i;
+ ptr = remcomOutBuffer;
+ /* General Purpose Regs */
+ ptr = mem2hex((char *)regs, ptr, 32 * 4);
+ /* Floating Point Regs - FIXME */
+ /*ptr = mem2hex((char *), ptr, 32 * 8);*/
+ for(i=0; i<(32*8*2); i++) { /* 2chars/byte */
+ ptr[i] = '0';
+ }
+ ptr += 32*8*2;
+ /* pc, msr, cr, lr, ctr, xer, (mq is unused) */
+ ptr = mem2hex((char *)®s->nip, ptr, 4);
+ ptr = mem2hex((char *)®s->msr, ptr, 4);
+ ptr = mem2hex((char *)®s->ccr, ptr, 4);
+ ptr = mem2hex((char *)®s->link, ptr, 4);
+ ptr = mem2hex((char *)®s->ctr, ptr, 4);
+ ptr = mem2hex((char *)®s->xer, ptr, 4);
+ }
+ break;
+
+ case 'G': /* set the value of the CPU registers */
+ {
+ ptr = &remcomInBuffer[1];
+
+ /*
+ * If the stack pointer has moved, you should pray.
+ * (cause only god can help you).
+ */
+
+ /* General Purpose Regs */
+ hex2mem(ptr, (char *)regs, 32 * 4);
+
+ /* Floating Point Regs - FIXME?? */
+ /*ptr = hex2mem(ptr, ??, 32 * 8);*/
+ ptr += 32*8*2;
+
+ /* pc, msr, cr, lr, ctr, xer, (mq is unused) */
+ ptr = hex2mem(ptr, (char *)®s->nip, 4);
+ ptr = hex2mem(ptr, (char *)®s->msr, 4);
+ ptr = hex2mem(ptr, (char *)®s->ccr, 4);
+ ptr = hex2mem(ptr, (char *)®s->link, 4);
+ ptr = hex2mem(ptr, (char *)®s->ctr, 4);
+ ptr = hex2mem(ptr, (char *)®s->xer, 4);
+
+ strcpy(remcomOutBuffer,"OK");
+ }
+ break;
+ case 'H':
+ /* don't do anything, yet, just acknowledge */
+ hexToInt(&ptr, &addr);
+ strcpy(remcomOutBuffer,"OK");
+ break;
+
+ case 'm': /* mAA..AA,LLLL Read LLLL bytes at address AA..AA */
+ /* Try to read %x,%x. */
+
+ ptr = &remcomInBuffer[1];
+
+ if (hexToInt(&ptr, &addr) && *ptr++ == ','
+ && hexToInt(&ptr, &length)) {
+ if (mem2hex((char *)addr, remcomOutBuffer,
+ length))
+ break;
+ strcpy(remcomOutBuffer, "E03");
+ } else
+ strcpy(remcomOutBuffer, "E01");
+ break;
+
+ case 'M': /* MAA..AA,LLLL: Write LLLL bytes at address AA.AA return OK */
+ /* Try to read '%x,%x:'. */
+
+ ptr = &remcomInBuffer[1];
+
+ if (hexToInt(&ptr, &addr) && *ptr++ == ','
+ && hexToInt(&ptr, &length)
+ && *ptr++ == ':') {
+ if (hex2mem(ptr, (char *)addr, length))
+ strcpy(remcomOutBuffer, "OK");
+ else
+ strcpy(remcomOutBuffer, "E03");
+ flush_icache_range(addr, addr+length);
+ } else
+ strcpy(remcomOutBuffer, "E02");
+ break;
+
+
+ case 'k': /* kill the program, actually just continue */
+ case 'c': /* cAA..AA Continue; address AA..AA optional */
+ /* try to read optional parameter, pc unchanged if no parm */
+
+ ptr = &remcomInBuffer[1];
+ if (hexToInt(&ptr, &addr))
+ regs->nip = addr;
+
+/* Need to flush the instruction cache here, as we may have deposited a
+ * breakpoint, and the icache probably has no way of knowing that a data ref to
+ * some location may have changed something that is in the instruction cache.
+ */
+ kgdb_flush_cache_all();
+ mtmsr(msr);
+
+ kgdb_interruptible(1);
+ unlock_kernel();
+ kgdb_active = 0;
+ if (kdebug) {
+ printk("remcomInBuffer: %s\n", remcomInBuffer);
+ printk("remcomOutBuffer: %s\n", remcomOutBuffer);
+ }
+ return 1;
+
+ case 's':
+ kgdb_flush_cache_all();
+#if defined(CONFIG_40x) || defined(CONFIG_BOOKE)
+ mtspr(SPRN_DBCR0, mfspr(SPRN_DBCR0) | DBCR0_IC);
+ regs->msr |= MSR_DE;
+#else
+ regs->msr |= MSR_SE;
+#endif
+ unlock_kernel();
+ kgdb_active = 0;
+ if (kdebug) {
+ printk("remcomInBuffer: %s\n", remcomInBuffer);
+ printk("remcomOutBuffer: %s\n", remcomOutBuffer);
+ }
+ return 1;
+
+ case 'r': /* Reset (if user process..exit ???)*/
+ panic("kgdb reset.");
+ break;
+ } /* switch */
+ if (remcomOutBuffer[0] && kdebug) {
+ printk("remcomInBuffer: %s\n", remcomInBuffer);
+ printk("remcomOutBuffer: %s\n", remcomOutBuffer);
+ }
+ /* reply to the request */
+ putpacket(remcomOutBuffer);
+ } /* while(1) */
+}
+
+/* This function will generate a breakpoint exception. It is used at the
+ beginning of a program to sync up with a debugger and can be used
+ otherwise as a quick means to stop program execution and "break" into
+ the debugger. */
+
+void
+breakpoint(void)
+{
+ if (!initialized) {
+ printk("breakpoint() called b4 kgdb init\n");
+ return;
+ }
+
+ asm(" .globl breakinst \n\
+ breakinst: .long 0x7d821008");
+}
+
+#ifdef CONFIG_KGDB_CONSOLE
+/* Output string in GDB O-packet format if GDB has connected. If nothing
+ output, returns 0 (caller must then handle output). */
+int
+kgdb_output_string (const char* s, unsigned int count)
+{
+ char buffer[512];
+
+ if (!kgdb_started)
+ return 0;
+
+ count = (count <= (sizeof(buffer) / 2 - 2))
+ ? count : (sizeof(buffer) / 2 - 2);
+
+ buffer[0] = 'O';
+ mem2hex (s, &buffer[1], count);
+ putpacket(buffer);
+
+ return 1;
+}
+#endif
+
+static void sysrq_handle_gdb(int key, struct pt_regs *pt_regs,
+ struct tty_struct *tty)
+{
+ printk("Entering GDB stub\n");
+ breakpoint();
+}
+static struct sysrq_key_op sysrq_gdb_op = {
+ .handler = sysrq_handle_gdb,
+ .help_msg = "Gdb",
+ .action_msg = "GDB",
+};
+
+static int gdb_register_sysrq(void)
+{
+ printk("Registering GDB sysrq handler\n");
+ register_sysrq_key('g', &sysrq_gdb_op);
+ return 0;
+}
+module_init(gdb_register_sysrq);
diff --git a/arch/ppc/kernel/ppc_htab.c b/arch/ppc/kernel/ppc_htab.c
new file mode 100644
index 0000000..ca81002
--- /dev/null
+++ b/arch/ppc/kernel/ppc_htab.c
@@ -0,0 +1,467 @@
+/*
+ * PowerPC hash table management proc entry. Will show information
+ * about the current hash table and will allow changes to it.
+ *
+ * Written by Cort Dougan (cort@cs.nmt.edu)
+ *
+ * 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.
+ */
+
+#include <linux/config.h>
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/proc_fs.h>
+#include <linux/stat.h>
+#include <linux/sysctl.h>
+#include <linux/ctype.h>
+#include <linux/threads.h>
+#include <linux/smp_lock.h>
+#include <linux/seq_file.h>
+#include <linux/init.h>
+#include <linux/bitops.h>
+
+#include <asm/uaccess.h>
+#include <asm/mmu.h>
+#include <asm/residual.h>
+#include <asm/io.h>
+#include <asm/pgtable.h>
+#include <asm/cputable.h>
+#include <asm/system.h>
+#include <asm/reg.h>
+
+static int ppc_htab_show(struct seq_file *m, void *v);
+static ssize_t ppc_htab_write(struct file * file, const char __user * buffer,
+ size_t count, loff_t *ppos);
+extern PTE *Hash, *Hash_end;
+extern unsigned long Hash_size, Hash_mask;
+extern unsigned long _SDR1;
+extern unsigned long htab_reloads;
+extern unsigned long htab_preloads;
+extern unsigned long htab_evicts;
+extern unsigned long pte_misses;
+extern unsigned long pte_errors;
+extern unsigned int primary_pteg_full;
+extern unsigned int htab_hash_searches;
+
+static int ppc_htab_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, ppc_htab_show, NULL);
+}
+
+struct file_operations ppc_htab_operations = {
+ .open = ppc_htab_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .write = ppc_htab_write,
+ .release = single_release,
+};
+
+static char *pmc1_lookup(unsigned long mmcr0)
+{
+ switch ( mmcr0 & (0x7f<<7) )
+ {
+ case 0x0:
+ return "none";
+ case MMCR0_PMC1_CYCLES:
+ return "cycles";
+ case MMCR0_PMC1_ICACHEMISS:
+ return "ic miss";
+ case MMCR0_PMC1_DTLB:
+ return "dtlb miss";
+ default:
+ return "unknown";
+ }
+}
+
+static char *pmc2_lookup(unsigned long mmcr0)
+{
+ switch ( mmcr0 & 0x3f )
+ {
+ case 0x0:
+ return "none";
+ case MMCR0_PMC2_CYCLES:
+ return "cycles";
+ case MMCR0_PMC2_DCACHEMISS:
+ return "dc miss";
+ case MMCR0_PMC2_ITLB:
+ return "itlb miss";
+ case MMCR0_PMC2_LOADMISSTIME:
+ return "load miss time";
+ default:
+ return "unknown";
+ }
+}
+
+/*
+ * print some useful info about the hash table. This function
+ * is _REALLY_ slow (see the nested for loops below) but nothing
+ * in here should be really timing critical. -- Cort
+ */
+static int ppc_htab_show(struct seq_file *m, void *v)
+{
+ unsigned long mmcr0 = 0, pmc1 = 0, pmc2 = 0;
+#if defined(CONFIG_PPC_STD_MMU) && !defined(CONFIG_PPC64BRIDGE)
+ unsigned int kptes = 0, uptes = 0;
+ PTE *ptr;
+#endif /* CONFIG_PPC_STD_MMU */
+
+ if (cpu_has_feature(CPU_FTR_604_PERF_MON)) {
+ mmcr0 = mfspr(SPRN_MMCR0);
+ pmc1 = mfspr(SPRN_PMC1);
+ pmc2 = mfspr(SPRN_PMC2);
+ seq_printf(m,
+ "604 Performance Monitoring\n"
+ "MMCR0\t\t: %08lx %s%s ",
+ mmcr0,
+ ( mmcr0>>28 & 0x2 ) ? "(user mode counted)" : "",
+ ( mmcr0>>28 & 0x4 ) ? "(kernel mode counted)" : "");
+ seq_printf(m,
+ "\nPMC1\t\t: %08lx (%s)\n"
+ "PMC2\t\t: %08lx (%s)\n",
+ pmc1, pmc1_lookup(mmcr0),
+ pmc2, pmc2_lookup(mmcr0));
+ }
+
+#ifdef CONFIG_PPC_STD_MMU
+ /* if we don't have a htab */
+ if ( Hash_size == 0 ) {
+ seq_printf(m, "No Hash Table used\n");
+ return 0;
+ }
+
+#ifndef CONFIG_PPC64BRIDGE
+ for (ptr = Hash; ptr < Hash_end; ptr++) {
+ unsigned int mctx, vsid;
+
+ if (!ptr->v)
+ continue;
+ /* undo the esid skew */
+ vsid = ptr->vsid;
+ mctx = ((vsid - (vsid & 0xf) * 0x111) >> 4) & 0xfffff;
+ if (mctx == 0)
+ kptes++;
+ else
+ uptes++;
+ }
+#endif
+
+ seq_printf(m,
+ "PTE Hash Table Information\n"
+ "Size\t\t: %luKb\n"
+ "Buckets\t\t: %lu\n"
+ "Address\t\t: %08lx\n"
+ "Entries\t\t: %lu\n"
+#ifndef CONFIG_PPC64BRIDGE
+ "User ptes\t: %u\n"
+ "Kernel ptes\t: %u\n"
+ "Percent full\t: %lu%%\n"
+#endif
+ , (unsigned long)(Hash_size>>10),
+ (Hash_size/(sizeof(PTE)*8)),
+ (unsigned long)Hash,
+ Hash_size/sizeof(PTE)
+#ifndef CONFIG_PPC64BRIDGE
+ , uptes,
+ kptes,
+ ((kptes+uptes)*100) / (Hash_size/sizeof(PTE))
+#endif
+ );
+
+ seq_printf(m,
+ "Reloads\t\t: %lu\n"
+ "Preloads\t: %lu\n"
+ "Searches\t: %u\n"
+ "Overflows\t: %u\n"
+ "Evicts\t\t: %lu\n",
+ htab_reloads, htab_preloads, htab_hash_searches,
+ primary_pteg_full, htab_evicts);
+#endif /* CONFIG_PPC_STD_MMU */
+
+ seq_printf(m,
+ "Non-error misses: %lu\n"
+ "Error misses\t: %lu\n",
+ pte_misses, pte_errors);
+ return 0;
+}
+
+/*
+ * Allow user to define performance counters and resize the hash table
+ */
+static ssize_t ppc_htab_write(struct file * file, const char __user * ubuffer,
+ size_t count, loff_t *ppos)
+{
+#ifdef CONFIG_PPC_STD_MMU
+ unsigned long tmp;
+ char buffer[16];
+
+ if (!capable(CAP_SYS_ADMIN))
+ return -EACCES;
+ if (strncpy_from_user(buffer, ubuffer, 15))
+ return -EFAULT;
+ buffer[15] = 0;
+
+ /* don't set the htab size for now */
+ if ( !strncmp( buffer, "size ", 5) )
+ return -EBUSY;
+
+ if ( !strncmp( buffer, "reset", 5) )
+ {
+ if (cpu_has_feature(CPU_FTR_604_PERF_MON)) {
+ /* reset PMC1 and PMC2 */
+ mtspr(SPRN_PMC1, 0);
+ mtspr(SPRN_PMC2, 0);
+ }
+ htab_reloads = 0;
+ htab_evicts = 0;
+ pte_misses = 0;
+ pte_errors = 0;
+ }
+
+ /* Everything below here requires the performance monitor feature. */
+ if (!cpu_has_feature(CPU_FTR_604_PERF_MON))
+ return count;
+
+ /* turn off performance monitoring */
+ if ( !strncmp( buffer, "off", 3) )
+ {
+ mtspr(SPRN_MMCR0, 0);
+ mtspr(SPRN_PMC1, 0);
+ mtspr(SPRN_PMC2, 0);
+ }
+
+ if ( !strncmp( buffer, "user", 4) )
+ {
+ /* setup mmcr0 and clear the correct pmc */
+ tmp = (mfspr(SPRN_MMCR0) & ~(0x60000000)) | 0x20000000;
+ mtspr(SPRN_MMCR0, tmp);
+ mtspr(SPRN_PMC1, 0);
+ mtspr(SPRN_PMC2, 0);
+ }
+
+ if ( !strncmp( buffer, "kernel", 6) )
+ {
+ /* setup mmcr0 and clear the correct pmc */
+ tmp = (mfspr(SPRN_MMCR0) & ~(0x60000000)) | 0x40000000;
+ mtspr(SPRN_MMCR0, tmp);
+ mtspr(SPRN_PMC1, 0);
+ mtspr(SPRN_PMC2, 0);
+ }
+
+ /* PMC1 values */
+ if ( !strncmp( buffer, "dtlb", 4) )
+ {
+ /* setup mmcr0 and clear the correct pmc */
+ tmp = (mfspr(SPRN_MMCR0) & ~(0x7F << 7)) | MMCR0_PMC1_DTLB;
+ mtspr(SPRN_MMCR0, tmp);
+ mtspr(SPRN_PMC1, 0);
+ }
+
+ if ( !strncmp( buffer, "ic miss", 7) )
+ {
+ /* setup mmcr0 and clear the correct pmc */
+ tmp = (mfspr(SPRN_MMCR0) & ~(0x7F<<7)) | MMCR0_PMC1_ICACHEMISS;
+ mtspr(SPRN_MMCR0, tmp);
+ mtspr(SPRN_PMC1, 0);
+ }
+
+ /* PMC2 values */
+ if ( !strncmp( buffer, "load miss time", 14) )
+ {
+ /* setup mmcr0 and clear the correct pmc */
+ asm volatile(
+ "mfspr %0,%1\n\t" /* get current mccr0 */
+ "rlwinm %0,%0,0,0,31-6\n\t" /* clear bits [26-31] */
+ "ori %0,%0,%2 \n\t" /* or in mmcr0 settings */
+ "mtspr %1,%0 \n\t" /* set new mccr0 */
+ "mtspr %3,%4 \n\t" /* reset the pmc */
+ : "=r" (tmp)
+ : "i" (SPRN_MMCR0),
+ "i" (MMCR0_PMC2_LOADMISSTIME),
+ "i" (SPRN_PMC2), "r" (0) );
+ }
+
+ if ( !strncmp( buffer, "itlb", 4) )
+ {
+ /* setup mmcr0 and clear the correct pmc */
+ asm volatile(
+ "mfspr %0,%1\n\t" /* get current mccr0 */
+ "rlwinm %0,%0,0,0,31-6\n\t" /* clear bits [26-31] */
+ "ori %0,%0,%2 \n\t" /* or in mmcr0 settings */
+ "mtspr %1,%0 \n\t" /* set new mccr0 */
+ "mtspr %3,%4 \n\t" /* reset the pmc */
+ : "=r" (tmp)
+ : "i" (SPRN_MMCR0), "i" (MMCR0_PMC2_ITLB),
+ "i" (SPRN_PMC2), "r" (0) );
+ }
+
+ if ( !strncmp( buffer, "dc miss", 7) )
+ {
+ /* setup mmcr0 and clear the correct pmc */
+ asm volatile(
+ "mfspr %0,%1\n\t" /* get current mccr0 */
+ "rlwinm %0,%0,0,0,31-6\n\t" /* clear bits [26-31] */
+ "ori %0,%0,%2 \n\t" /* or in mmcr0 settings */
+ "mtspr %1,%0 \n\t" /* set new mccr0 */
+ "mtspr %3,%4 \n\t" /* reset the pmc */
+ : "=r" (tmp)
+ : "i" (SPRN_MMCR0), "i" (MMCR0_PMC2_DCACHEMISS),
+ "i" (SPRN_PMC2), "r" (0) );
+ }
+
+ return count;
+#else /* CONFIG_PPC_STD_MMU */
+ return 0;
+#endif /* CONFIG_PPC_STD_MMU */
+}
+
+int proc_dol2crvec(ctl_table *table, int write, struct file *filp,
+ void __user *buffer_arg, size_t *lenp, loff_t *ppos)
+{
+ int vleft, first=1, len, left, val;
+ char __user *buffer = (char __user *) buffer_arg;
+ #define TMPBUFLEN 256
+ char buf[TMPBUFLEN], *p;
+ static const char *sizestrings[4] = {
+ "2MB", "256KB", "512KB", "1MB"
+ };
+ static const char *clockstrings[8] = {
+ "clock disabled", "+1 clock", "+1.5 clock", "reserved(3)",
+ "+2 clock", "+2.5 clock", "+3 clock", "reserved(7)"
+ };
+ static const char *typestrings[4] = {
+ "flow-through burst SRAM", "reserved SRAM",
+ "pipelined burst SRAM", "pipelined late-write SRAM"
+ };
+ static const char *holdstrings[4] = {
+ "0.5", "1.0", "(reserved2)", "(reserved3)"
+ };
+
+ if (!cpu_has_feature(CPU_FTR_L2CR))
+ return -EFAULT;
+
+ if ( /*!table->maxlen ||*/ (*ppos && !write)) {
+ *lenp = 0;
+ return 0;
+ }
+
+ vleft = table->maxlen / sizeof(int);
+ left = *lenp;
+
+ for (; left /*&& vleft--*/; first=0) {
+ if (write) {
+ while (left) {
+ char c;
+ if(get_user(c, buffer))
+ return -EFAULT;
+ if (!isspace(c))
+ break;
+ left--;
+ buffer++;
+ }
+ if (!left)
+ break;
+ len = left;
+ if (len > TMPBUFLEN-1)
+ len = TMPBUFLEN-1;
+ if(copy_from_user(buf, buffer, len))
+ return -EFAULT;
+ buf[len] = 0;
+ p = buf;
+ if (*p < '0' || *p > '9')
+ break;
+ val = simple_strtoul(p, &p, 0);
+ len = p-buf;
+ if ((len < left) && *p && !isspace(*p))
+ break;
+ buffer += len;
+ left -= len;
+ _set_L2CR(val);
+ } else {
+ p = buf;
+ if (!first)
+ *p++ = '\t';
+ val = _get_L2CR();
+ p += sprintf(p, "0x%08x: ", val);
+ p += sprintf(p, " %s", (val >> 31) & 1 ? "enabled" :
+ "disabled");
+ p += sprintf(p, ", %sparity", (val>>30)&1 ? "" : "no ");
+ p += sprintf(p, ", %s", sizestrings[(val >> 28) & 3]);
+ p += sprintf(p, ", %s", clockstrings[(val >> 25) & 7]);
+ p += sprintf(p, ", %s", typestrings[(val >> 23) & 2]);
+ p += sprintf(p, "%s", (val>>22)&1 ? ", data only" : "");
+ p += sprintf(p, "%s", (val>>20)&1 ? ", ZZ enabled": "");
+ p += sprintf(p, ", %s", (val>>19)&1 ? "write-through" :
+ "copy-back");
+ p += sprintf(p, "%s", (val>>18)&1 ? ", testing" : "");
+ p += sprintf(p, ", %sns hold",holdstrings[(val>>16)&3]);
+ p += sprintf(p, "%s", (val>>15)&1 ? ", DLL slow" : "");
+ p += sprintf(p, "%s", (val>>14)&1 ? ", diff clock" :"");
+ p += sprintf(p, "%s", (val>>13)&1 ? ", DLL bypass" :"");
+
+ p += sprintf(p,"\n");
+
+ len = strlen(buf);
+ if (len > left)
+ len = left;
+ if (copy_to_user(buffer, buf, len))
+ return -EFAULT;
+ left -= len;
+ buffer += len;
+ break;
+ }
+ }
+
+ if (!write && !first && left) {
+ if(put_user('\n', (char __user *) buffer))
+ return -EFAULT;
+ left--, buffer++;
+ }
+ if (write) {
+ char __user *s = (char __user *) buffer;
+ while (left) {
+ char c;
+ if(get_user(c, s++))
+ return -EFAULT;
+ if (!isspace(c))
+ break;
+ left--;
+ }
+ }
+ if (write && first)
+ return -EINVAL;
+ *lenp -= left;
+ *ppos += *lenp;
+ return 0;
+}
+
+#ifdef CONFIG_SYSCTL
+/*
+ * Register our sysctl.
+ */
+static ctl_table htab_ctl_table[]={
+ {
+ .ctl_name = KERN_PPC_L2CR,
+ .procname = "l2cr",
+ .mode = 0644,
+ .proc_handler = &proc_dol2crvec,
+ },
+ { 0, },
+};
+static ctl_table htab_sysctl_root[] = {
+ { 1, "kernel", NULL, 0, 0755, htab_ctl_table, },
+ { 0,},
+};
+
+static int __init
+register_ppc_htab_sysctl(void)
+{
+ register_sysctl_table(htab_sysctl_root, 0);
+
+ return 0;
+}
+
+__initcall(register_ppc_htab_sysctl);
+#endif
diff --git a/arch/ppc/kernel/ppc_ksyms.c b/arch/ppc/kernel/ppc_ksyms.c
new file mode 100644
index 0000000..2ccb58f
--- /dev/null
+++ b/arch/ppc/kernel/ppc_ksyms.c
@@ -0,0 +1,350 @@
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/threads.h>
+#include <linux/smp.h>
+#include <linux/sched.h>
+#include <linux/elfcore.h>
+#include <linux/string.h>
+#include <linux/interrupt.h>
+#include <linux/tty.h>
+#include <linux/vt_kern.h>
+#include <linux/nvram.h>
+#include <linux/console.h>
+#include <linux/irq.h>
+#include <linux/pci.h>
+#include <linux/delay.h>
+#include <linux/ide.h>
+#include <linux/pm.h>
+#include <linux/bitops.h>
+
+#include <asm/page.h>
+#include <asm/semaphore.h>
+#include <asm/processor.h>
+#include <asm/uaccess.h>
+#include <asm/io.h>
+#include <asm/ide.h>
+#include <asm/atomic.h>
+#include <asm/checksum.h>
+#include <asm/pgtable.h>
+#include <asm/tlbflush.h>
+#include <linux/adb.h>
+#include <linux/cuda.h>
+#include <linux/pmu.h>
+#include <asm/prom.h>
+#include <asm/system.h>
+#include <asm/pci-bridge.h>
+#include <asm/irq.h>
+#include <asm/pmac_feature.h>
+#include <asm/dma.h>
+#include <asm/machdep.h>
+#include <asm/hw_irq.h>
+#include <asm/nvram.h>
+#include <asm/mmu_context.h>
+#include <asm/backlight.h>
+#include <asm/time.h>
+#include <asm/cputable.h>
+#include <asm/btext.h>
+#include <asm/div64.h>
+#include <asm/xmon.h>
+
+#ifdef CONFIG_8xx
+#include <asm/commproc.h>
+#endif
+
+/* Tell string.h we don't want memcpy etc. as cpp defines */
+#define EXPORT_SYMTAB_STROPS
+
+extern void transfer_to_handler(void);
+extern void do_syscall_trace(void);
+extern void do_IRQ(struct pt_regs *regs);
+extern void MachineCheckException(struct pt_regs *regs);
+extern void AlignmentException(struct pt_regs *regs);
+extern void ProgramCheckException(struct pt_regs *regs);
+extern void SingleStepException(struct pt_regs *regs);
+extern int do_signal(sigset_t *, struct pt_regs *);
+extern int pmac_newworld;
+extern int sys_sigreturn(struct pt_regs *regs);
+
+long long __ashrdi3(long long, int);
+long long __ashldi3(long long, int);
+long long __lshrdi3(long long, int);
+
+extern unsigned long mm_ptov (unsigned long paddr);
+
+EXPORT_SYMBOL(clear_pages);
+EXPORT_SYMBOL(clear_user_page);
+EXPORT_SYMBOL(do_signal);
+EXPORT_SYMBOL(do_syscall_trace);
+EXPORT_SYMBOL(transfer_to_handler);
+EXPORT_SYMBOL(do_IRQ);
+EXPORT_SYMBOL(MachineCheckException);
+EXPORT_SYMBOL(AlignmentException);
+EXPORT_SYMBOL(ProgramCheckException);
+EXPORT_SYMBOL(SingleStepException);
+EXPORT_SYMBOL(sys_sigreturn);
+EXPORT_SYMBOL(ppc_n_lost_interrupts);
+EXPORT_SYMBOL(ppc_lost_interrupts);
+
+EXPORT_SYMBOL(ISA_DMA_THRESHOLD);
+EXPORT_SYMBOL(DMA_MODE_READ);
+EXPORT_SYMBOL(DMA_MODE_WRITE);
+#if defined(CONFIG_PPC_PREP)
+EXPORT_SYMBOL(_prep_type);
+EXPORT_SYMBOL(ucSystemType);
+#endif
+
+#if !defined(__INLINE_BITOPS)
+EXPORT_SYMBOL(set_bit);
+EXPORT_SYMBOL(clear_bit);
+EXPORT_SYMBOL(change_bit);
+EXPORT_SYMBOL(test_and_set_bit);
+EXPORT_SYMBOL(test_and_clear_bit);
+EXPORT_SYMBOL(test_and_change_bit);
+#endif /* __INLINE_BITOPS */
+
+EXPORT_SYMBOL(strcpy);
+EXPORT_SYMBOL(strncpy);
+EXPORT_SYMBOL(strcat);
+EXPORT_SYMBOL(strncat);
+EXPORT_SYMBOL(strchr);
+EXPORT_SYMBOL(strrchr);
+EXPORT_SYMBOL(strpbrk);
+EXPORT_SYMBOL(strstr);
+EXPORT_SYMBOL(strlen);
+EXPORT_SYMBOL(strnlen);
+EXPORT_SYMBOL(strcmp);
+EXPORT_SYMBOL(strncmp);
+EXPORT_SYMBOL(strcasecmp);
+EXPORT_SYMBOL(__div64_32);
+
+EXPORT_SYMBOL(csum_partial);
+EXPORT_SYMBOL(csum_partial_copy_generic);
+EXPORT_SYMBOL(ip_fast_csum);
+EXPORT_SYMBOL(csum_tcpudp_magic);
+
+EXPORT_SYMBOL(__copy_tofrom_user);
+EXPORT_SYMBOL(__clear_user);
+EXPORT_SYMBOL(__strncpy_from_user);
+EXPORT_SYMBOL(__strnlen_user);
+
+/*
+EXPORT_SYMBOL(inb);
+EXPORT_SYMBOL(inw);
+EXPORT_SYMBOL(inl);
+EXPORT_SYMBOL(outb);
+EXPORT_SYMBOL(outw);
+EXPORT_SYMBOL(outl);
+EXPORT_SYMBOL(outsl);*/
+
+EXPORT_SYMBOL(_insb);
+EXPORT_SYMBOL(_outsb);
+EXPORT_SYMBOL(_insw);
+EXPORT_SYMBOL(_outsw);
+EXPORT_SYMBOL(_insl);
+EXPORT_SYMBOL(_outsl);
+EXPORT_SYMBOL(_insw_ns);
+EXPORT_SYMBOL(_outsw_ns);
+EXPORT_SYMBOL(_insl_ns);
+EXPORT_SYMBOL(_outsl_ns);
+EXPORT_SYMBOL(iopa);
+EXPORT_SYMBOL(mm_ptov);
+EXPORT_SYMBOL(ioremap);
+#ifdef CONFIG_44x
+EXPORT_SYMBOL(ioremap64);
+#endif
+EXPORT_SYMBOL(__ioremap);
+EXPORT_SYMBOL(iounmap);
+EXPORT_SYMBOL(ioremap_bot); /* aka VMALLOC_END */
+
+#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
+EXPORT_SYMBOL(ppc_ide_md);
+#endif
+
+#ifdef CONFIG_PCI
+EXPORT_SYMBOL(isa_io_base);
+EXPORT_SYMBOL(isa_mem_base);
+EXPORT_SYMBOL(pci_dram_offset);
+EXPORT_SYMBOL(pci_alloc_consistent);
+EXPORT_SYMBOL(pci_free_consistent);
+EXPORT_SYMBOL(pci_bus_io_base);
+EXPORT_SYMBOL(pci_bus_io_base_phys);
+EXPORT_SYMBOL(pci_bus_mem_base_phys);
+EXPORT_SYMBOL(pci_bus_to_hose);
+EXPORT_SYMBOL(pci_resource_to_bus);
+EXPORT_SYMBOL(pci_phys_to_bus);
+EXPORT_SYMBOL(pci_bus_to_phys);
+#endif /* CONFIG_PCI */
+
+#ifdef CONFIG_NOT_COHERENT_CACHE
+EXPORT_SYMBOL(flush_dcache_all);
+#endif
+
+EXPORT_SYMBOL(start_thread);
+EXPORT_SYMBOL(kernel_thread);
+
+EXPORT_SYMBOL(flush_instruction_cache);
+EXPORT_SYMBOL(giveup_fpu);
+EXPORT_SYMBOL(flush_icache_range);
+EXPORT_SYMBOL(flush_dcache_range);
+EXPORT_SYMBOL(flush_icache_user_range);
+EXPORT_SYMBOL(flush_dcache_page);
+EXPORT_SYMBOL(flush_tlb_kernel_range);
+EXPORT_SYMBOL(flush_tlb_page);
+EXPORT_SYMBOL(_tlbie);
+#ifdef CONFIG_ALTIVEC
+EXPORT_SYMBOL(last_task_used_altivec);
+EXPORT_SYMBOL(giveup_altivec);
+#endif /* CONFIG_ALTIVEC */
+#ifdef CONFIG_SPE
+EXPORT_SYMBOL(last_task_used_spe);
+EXPORT_SYMBOL(giveup_spe);
+#endif /* CONFIG_SPE */
+#ifdef CONFIG_SMP
+EXPORT_SYMBOL(smp_call_function);
+EXPORT_SYMBOL(smp_hw_index);
+#endif
+
+EXPORT_SYMBOL(ppc_md);
+
+#ifdef CONFIG_ADB
+EXPORT_SYMBOL(adb_request);
+EXPORT_SYMBOL(adb_register);
+EXPORT_SYMBOL(adb_unregister);
+EXPORT_SYMBOL(adb_poll);
+EXPORT_SYMBOL(adb_try_handler_change);
+#endif /* CONFIG_ADB */
+#ifdef CONFIG_ADB_CUDA
+EXPORT_SYMBOL(cuda_request);
+EXPORT_SYMBOL(cuda_poll);
+#endif /* CONFIG_ADB_CUDA */
+#ifdef CONFIG_PPC_MULTIPLATFORM
+EXPORT_SYMBOL(_machine);
+#endif
+#ifdef CONFIG_PPC_PMAC
+EXPORT_SYMBOL(sys_ctrler);
+EXPORT_SYMBOL(pmac_newworld);
+#endif
+#ifdef CONFIG_PPC_OF
+EXPORT_SYMBOL(find_devices);
+EXPORT_SYMBOL(find_type_devices);
+EXPORT_SYMBOL(find_compatible_devices);
+EXPORT_SYMBOL(find_path_device);
+EXPORT_SYMBOL(device_is_compatible);
+EXPORT_SYMBOL(machine_is_compatible);
+EXPORT_SYMBOL(find_all_nodes);
+EXPORT_SYMBOL(get_property);
+EXPORT_SYMBOL(request_OF_resource);
+EXPORT_SYMBOL(release_OF_resource);
+EXPORT_SYMBOL(pci_busdev_to_OF_node);
+EXPORT_SYMBOL(pci_device_to_OF_node);
+EXPORT_SYMBOL(pci_device_from_OF_node);
+EXPORT_SYMBOL(of_find_node_by_name);
+EXPORT_SYMBOL(of_find_node_by_type);
+EXPORT_SYMBOL(of_find_compatible_node);
+EXPORT_SYMBOL(of_find_node_by_path);
+EXPORT_SYMBOL(of_find_all_nodes);
+EXPORT_SYMBOL(of_get_parent);
+EXPORT_SYMBOL(of_get_next_child);
+EXPORT_SYMBOL(of_node_get);
+EXPORT_SYMBOL(of_node_put);
+#endif /* CONFIG_PPC_OF */
+#if defined(CONFIG_BOOTX_TEXT)
+EXPORT_SYMBOL(btext_update_display);
+#endif
+#if defined(CONFIG_SCSI) && defined(CONFIG_PPC_PMAC)
+EXPORT_SYMBOL(note_scsi_host);
+#endif
+#ifdef CONFIG_VT
+EXPORT_SYMBOL(kd_mksound);
+#endif
+EXPORT_SYMBOL(to_tm);
+
+EXPORT_SYMBOL(pm_power_off);
+
+EXPORT_SYMBOL(__ashrdi3);
+EXPORT_SYMBOL(__ashldi3);
+EXPORT_SYMBOL(__lshrdi3);
+EXPORT_SYMBOL(memcpy);
+EXPORT_SYMBOL(memset);
+EXPORT_SYMBOL(memmove);
+EXPORT_SYMBOL(memscan);
+EXPORT_SYMBOL(memcmp);
+EXPORT_SYMBOL(memchr);
+
+#if defined(CONFIG_FB_VGA16_MODULE)
+EXPORT_SYMBOL(screen_info);
+#endif
+
+EXPORT_SYMBOL(__delay);
+#ifndef INLINE_IRQS
+EXPORT_SYMBOL(local_irq_enable);
+EXPORT_SYMBOL(local_irq_enable_end);
+EXPORT_SYMBOL(local_irq_disable);
+EXPORT_SYMBOL(local_irq_disable_end);
+EXPORT_SYMBOL(local_save_flags_ptr);
+EXPORT_SYMBOL(local_save_flags_ptr_end);
+EXPORT_SYMBOL(local_irq_restore);
+EXPORT_SYMBOL(local_irq_restore_end);
+#endif
+EXPORT_SYMBOL(timer_interrupt);
+EXPORT_SYMBOL(irq_desc);
+EXPORT_SYMBOL(tb_ticks_per_jiffy);
+EXPORT_SYMBOL(get_wchan);
+EXPORT_SYMBOL(console_drivers);
+#ifdef CONFIG_XMON
+EXPORT_SYMBOL(xmon);
+EXPORT_SYMBOL(xmon_printf);
+#endif
+EXPORT_SYMBOL(__up);
+EXPORT_SYMBOL(__down);
+EXPORT_SYMBOL(__down_interruptible);
+
+#if defined(CONFIG_KGDB) || defined(CONFIG_XMON)
+extern void (*debugger)(struct pt_regs *regs);
+extern int (*debugger_bpt)(struct pt_regs *regs);
+extern int (*debugger_sstep)(struct pt_regs *regs);
+extern int (*debugger_iabr_match)(struct pt_regs *regs);
+extern int (*debugger_dabr_match)(struct pt_regs *regs);
+extern void (*debugger_fault_handler)(struct pt_regs *regs);
+
+EXPORT_SYMBOL(debugger);
+EXPORT_SYMBOL(debugger_bpt);
+EXPORT_SYMBOL(debugger_sstep);
+EXPORT_SYMBOL(debugger_iabr_match);
+EXPORT_SYMBOL(debugger_dabr_match);
+EXPORT_SYMBOL(debugger_fault_handler);
+#endif
+
+#ifdef CONFIG_8xx
+EXPORT_SYMBOL(cpm_install_handler);
+EXPORT_SYMBOL(cpm_free_handler);
+#endif /* CONFIG_8xx */
+#if defined(CONFIG_8xx) || defined(CONFIG_40x) || defined(CONFIG_85xx) ||\
+ defined(CONFIG_83xx)
+EXPORT_SYMBOL(__res);
+#endif
+
+EXPORT_SYMBOL(next_mmu_context);
+EXPORT_SYMBOL(set_context);
+EXPORT_SYMBOL(handle_mm_fault); /* For MOL */
+EXPORT_SYMBOL(disarm_decr);
+#ifdef CONFIG_PPC_STD_MMU
+extern long mol_trampoline;
+EXPORT_SYMBOL(mol_trampoline); /* For MOL */
+EXPORT_SYMBOL(flush_hash_pages); /* For MOL */
+#ifdef CONFIG_SMP
+extern int mmu_hash_lock;
+EXPORT_SYMBOL(mmu_hash_lock); /* For MOL */
+#endif /* CONFIG_SMP */
+extern long *intercept_table;
+EXPORT_SYMBOL(intercept_table);
+#endif /* CONFIG_PPC_STD_MMU */
+EXPORT_SYMBOL(cur_cpu_spec);
+#ifdef CONFIG_PPC_PMAC
+extern unsigned long agp_special_page;
+EXPORT_SYMBOL(agp_special_page);
+#endif
+#if defined(CONFIG_40x) || defined(CONFIG_BOOKE)
+EXPORT_SYMBOL(__mtdcr);
+EXPORT_SYMBOL(__mfdcr);
+#endif
diff --git a/arch/ppc/kernel/process.c b/arch/ppc/kernel/process.c
new file mode 100644
index 0000000..82de66e
--- /dev/null
+++ b/arch/ppc/kernel/process.c
@@ -0,0 +1,781 @@
+/*
+ * arch/ppc/kernel/process.c
+ *
+ * Derived from "arch/i386/kernel/process.c"
+ * Copyright (C) 1995 Linus Torvalds
+ *
+ * Updated and modified by Cort Dougan (cort@cs.nmt.edu) and
+ * Paul Mackerras (paulus@cs.anu.edu.au)
+ *
+ * PowerPC version
+ * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
+ *
+ * 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.
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/smp.h>
+#include <linux/smp_lock.h>
+#include <linux/stddef.h>
+#include <linux/unistd.h>
+#include <linux/ptrace.h>
+#include <linux/slab.h>
+#include <linux/user.h>
+#include <linux/elf.h>
+#include <linux/init.h>
+#include <linux/prctl.h>
+#include <linux/init_task.h>
+#include <linux/module.h>
+#include <linux/kallsyms.h>
+#include <linux/mqueue.h>
+#include <linux/hardirq.h>
+
+#include <asm/pgtable.h>
+#include <asm/uaccess.h>
+#include <asm/system.h>
+#include <asm/io.h>
+#include <asm/processor.h>
+#include <asm/mmu.h>
+#include <asm/prom.h>
+
+extern unsigned long _get_SP(void);
+
+struct task_struct *last_task_used_math = NULL;
+struct task_struct *last_task_used_altivec = NULL;
+struct task_struct *last_task_used_spe = NULL;
+
+static struct fs_struct init_fs = INIT_FS;
+static struct files_struct init_files = INIT_FILES;
+static struct signal_struct init_signals = INIT_SIGNALS(init_signals);
+static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand);
+struct mm_struct init_mm = INIT_MM(init_mm);
+EXPORT_SYMBOL(init_mm);
+
+/* this is 8kB-aligned so we can get to the thread_info struct
+ at the base of it from the stack pointer with 1 integer instruction. */
+union thread_union init_thread_union
+ __attribute__((__section__(".data.init_task"))) =
+{ INIT_THREAD_INFO(init_task) };
+
+/* initial task structure */
+struct task_struct init_task = INIT_TASK(init_task);
+EXPORT_SYMBOL(init_task);
+
+/* only used to get secondary processor up */
+struct task_struct *current_set[NR_CPUS] = {&init_task, };
+
+#undef SHOW_TASK_SWITCHES
+#undef CHECK_STACK
+
+#if defined(CHECK_STACK)
+unsigned long
+kernel_stack_top(struct task_struct *tsk)
+{
+ return ((unsigned long)tsk) + sizeof(union task_union);
+}
+
+unsigned long
+task_top(struct task_struct *tsk)
+{
+ return ((unsigned long)tsk) + sizeof(struct thread_info);
+}
+
+/* check to make sure the kernel stack is healthy */
+int check_stack(struct task_struct *tsk)
+{
+ unsigned long stack_top = kernel_stack_top(tsk);
+ unsigned long tsk_top = task_top(tsk);
+ int ret = 0;
+
+#if 0
+ /* check thread magic */
+ if ( tsk->thread.magic != THREAD_MAGIC )
+ {
+ ret |= 1;
+ printk("thread.magic bad: %08x\n", tsk->thread.magic);
+ }
+#endif
+
+ if ( !tsk )
+ printk("check_stack(): tsk bad tsk %p\n",tsk);
+
+ /* check if stored ksp is bad */
+ if ( (tsk->thread.ksp > stack_top) || (tsk->thread.ksp < tsk_top) )
+ {
+ printk("stack out of bounds: %s/%d\n"
+ " tsk_top %08lx ksp %08lx stack_top %08lx\n",
+ tsk->comm,tsk->pid,
+ tsk_top, tsk->thread.ksp, stack_top);
+ ret |= 2;
+ }
+
+ /* check if stack ptr RIGHT NOW is bad */
+ if ( (tsk == current) && ((_get_SP() > stack_top ) || (_get_SP() < tsk_top)) )
+ {
+ printk("current stack ptr out of bounds: %s/%d\n"
+ " tsk_top %08lx sp %08lx stack_top %08lx\n",
+ current->comm,current->pid,
+ tsk_top, _get_SP(), stack_top);
+ ret |= 4;
+ }
+
+#if 0
+ /* check amount of free stack */
+ for ( i = (unsigned long *)task_top(tsk) ; i < kernel_stack_top(tsk) ; i++ )
+ {
+ if ( !i )
+ printk("check_stack(): i = %p\n", i);
+ if ( *i != 0 )
+ {
+ /* only notify if it's less than 900 bytes */
+ if ( (i - (unsigned long *)task_top(tsk)) < 900 )
+ printk("%d bytes free on stack\n",
+ i - task_top(tsk));
+ break;
+ }
+ }
+#endif
+
+ if (ret)
+ {
+ panic("bad kernel stack");
+ }
+ return(ret);
+}
+#endif /* defined(CHECK_STACK) */
+
+#ifdef CONFIG_ALTIVEC
+int
+dump_altivec(struct pt_regs *regs, elf_vrregset_t *vrregs)
+{
+ if (regs->msr & MSR_VEC)
+ giveup_altivec(current);
+ memcpy(vrregs, ¤t->thread.vr[0], sizeof(*vrregs));
+ return 1;
+}
+
+void
+enable_kernel_altivec(void)
+{
+ WARN_ON(preemptible());
+
+#ifdef CONFIG_SMP
+ if (current->thread.regs && (current->thread.regs->msr & MSR_VEC))
+ giveup_altivec(current);
+ else
+ giveup_altivec(NULL); /* just enable AltiVec for kernel - force */
+#else
+ giveup_altivec(last_task_used_altivec);
+#endif /* __SMP __ */
+}
+EXPORT_SYMBOL(enable_kernel_altivec);
+#endif /* CONFIG_ALTIVEC */
+
+#ifdef CONFIG_SPE
+int
+dump_spe(struct pt_regs *regs, elf_vrregset_t *evrregs)
+{
+ if (regs->msr & MSR_SPE)
+ giveup_spe(current);
+ /* We copy u32 evr[32] + u64 acc + u32 spefscr -> 35 */
+ memcpy(evrregs, ¤t->thread.evr[0], sizeof(u32) * 35);
+ return 1;
+}
+
+void
+enable_kernel_spe(void)
+{
+ WARN_ON(preemptible());
+
+#ifdef CONFIG_SMP
+ if (current->thread.regs && (current->thread.regs->msr & MSR_SPE))
+ giveup_spe(current);
+ else
+ giveup_spe(NULL); /* just enable SPE for kernel - force */
+#else
+ giveup_spe(last_task_used_spe);
+#endif /* __SMP __ */
+}
+EXPORT_SYMBOL(enable_kernel_spe);
+#endif /* CONFIG_SPE */
+
+void
+enable_kernel_fp(void)
+{
+ WARN_ON(preemptible());
+
+#ifdef CONFIG_SMP
+ if (current->thread.regs && (current->thread.regs->msr & MSR_FP))
+ giveup_fpu(current);
+ else
+ giveup_fpu(NULL); /* just enables FP for kernel */
+#else
+ giveup_fpu(last_task_used_math);
+#endif /* CONFIG_SMP */
+}
+EXPORT_SYMBOL(enable_kernel_fp);
+
+int
+dump_task_fpu(struct task_struct *tsk, elf_fpregset_t *fpregs)
+{
+ preempt_disable();
+ if (tsk->thread.regs && (tsk->thread.regs->msr & MSR_FP))
+ giveup_fpu(tsk);
+ preempt_enable();
+ memcpy(fpregs, &tsk->thread.fpr[0], sizeof(*fpregs));
+ return 1;
+}
+
+struct task_struct *__switch_to(struct task_struct *prev,
+ struct task_struct *new)
+{
+ struct thread_struct *new_thread, *old_thread;
+ unsigned long s;
+ struct task_struct *last;
+
+ local_irq_save(s);
+#ifdef CHECK_STACK
+ check_stack(prev);
+ check_stack(new);
+#endif
+
+#ifdef CONFIG_SMP
+ /* avoid complexity of lazy save/restore of fpu
+ * by just saving it every time we switch out if
+ * this task used the fpu during the last quantum.
+ *
+ * If it tries to use the fpu again, it'll trap and
+ * reload its fp regs. So we don't have to do a restore
+ * every switch, just a save.
+ * -- Cort
+ */
+ if (prev->thread.regs && (prev->thread.regs->msr & MSR_FP))
+ giveup_fpu(prev);
+#ifdef CONFIG_ALTIVEC
+ /*
+ * If the previous thread used altivec in the last quantum
+ * (thus changing altivec regs) then save them.
+ * We used to check the VRSAVE register but not all apps
+ * set it, so we don't rely on it now (and in fact we need
+ * to save & restore VSCR even if VRSAVE == 0). -- paulus
+ *
+ * On SMP we always save/restore altivec regs just to avoid the
+ * complexity of changing processors.
+ * -- Cort
+ */
+ if ((prev->thread.regs && (prev->thread.regs->msr & MSR_VEC)))
+ giveup_altivec(prev);
+#endif /* CONFIG_ALTIVEC */
+#ifdef CONFIG_SPE
+ /*
+ * If the previous thread used spe in the last quantum
+ * (thus changing spe regs) then save them.
+ *
+ * On SMP we always save/restore spe regs just to avoid the
+ * complexity of changing processors.
+ */
+ if ((prev->thread.regs && (prev->thread.regs->msr & MSR_SPE)))
+ giveup_spe(prev);
+#endif /* CONFIG_SPE */
+#endif /* CONFIG_SMP */
+
+ /* Avoid the trap. On smp this this never happens since
+ * we don't set last_task_used_altivec -- Cort
+ */
+ if (new->thread.regs && last_task_used_altivec == new)
+ new->thread.regs->msr |= MSR_VEC;
+#ifdef CONFIG_SPE
+ /* Avoid the trap. On smp this this never happens since
+ * we don't set last_task_used_spe
+ */
+ if (new->thread.regs && last_task_used_spe == new)
+ new->thread.regs->msr |= MSR_SPE;
+#endif /* CONFIG_SPE */
+ new_thread = &new->thread;
+ old_thread = ¤t->thread;
+ last = _switch(old_thread, new_thread);
+ local_irq_restore(s);
+ return last;
+}
+
+void show_regs(struct pt_regs * regs)
+{
+ int i, trap;
+
+ printk("NIP: %08lX LR: %08lX SP: %08lX REGS: %p TRAP: %04lx %s\n",
+ regs->nip, regs->link, regs->gpr[1], regs, regs->trap,
+ print_tainted());
+ printk("MSR: %08lx EE: %01x PR: %01x FP: %01x ME: %01x IR/DR: %01x%01x\n",
+ regs->msr, regs->msr&MSR_EE ? 1 : 0, regs->msr&MSR_PR ? 1 : 0,
+ regs->msr & MSR_FP ? 1 : 0,regs->msr&MSR_ME ? 1 : 0,
+ regs->msr&MSR_IR ? 1 : 0,
+ regs->msr&MSR_DR ? 1 : 0);
+ trap = TRAP(regs);
+ if (trap == 0x300 || trap == 0x600)
+ printk("DAR: %08lX, DSISR: %08lX\n", regs->dar, regs->dsisr);
+ printk("TASK = %p[%d] '%s' THREAD: %p\n",
+ current, current->pid, current->comm, current->thread_info);
+ printk("Last syscall: %ld ", current->thread.last_syscall);
+
+#ifdef CONFIG_SMP
+ printk(" CPU: %d", smp_processor_id());
+#endif /* CONFIG_SMP */
+
+ for (i = 0; i < 32; i++) {
+ long r;
+ if ((i % 8) == 0)
+ printk("\n" KERN_INFO "GPR%02d: ", i);
+ if (__get_user(r, ®s->gpr[i]))
+ break;
+ printk("%08lX ", r);
+ if (i == 12 && !FULL_REGS(regs))
+ break;
+ }
+ printk("\n");
+#ifdef CONFIG_KALLSYMS
+ /*
+ * Lookup NIP late so we have the best change of getting the
+ * above info out without failing
+ */
+ printk("NIP [%08lx] ", regs->nip);
+ print_symbol("%s\n", regs->nip);
+ printk("LR [%08lx] ", regs->link);
+ print_symbol("%s\n", regs->link);
+#endif
+ show_stack(current, (unsigned long *) regs->gpr[1]);
+}
+
+void exit_thread(void)
+{
+ if (last_task_used_math == current)
+ last_task_used_math = NULL;
+ if (last_task_used_altivec == current)
+ last_task_used_altivec = NULL;
+#ifdef CONFIG_SPE
+ if (last_task_used_spe == current)
+ last_task_used_spe = NULL;
+#endif
+}
+
+void flush_thread(void)
+{
+ if (last_task_used_math == current)
+ last_task_used_math = NULL;
+ if (last_task_used_altivec == current)
+ last_task_used_altivec = NULL;
+#ifdef CONFIG_SPE
+ if (last_task_used_spe == current)
+ last_task_used_spe = NULL;
+#endif
+}
+
+void
+release_thread(struct task_struct *t)
+{
+}
+
+/*
+ * This gets called before we allocate a new thread and copy
+ * the current task into it.
+ */
+void prepare_to_copy(struct task_struct *tsk)
+{
+ struct pt_regs *regs = tsk->thread.regs;
+
+ if (regs == NULL)
+ return;
+ preempt_disable();
+ if (regs->msr & MSR_FP)
+ giveup_fpu(current);
+#ifdef CONFIG_ALTIVEC
+ if (regs->msr & MSR_VEC)
+ giveup_altivec(current);
+#endif /* CONFIG_ALTIVEC */
+#ifdef CONFIG_SPE
+ if (regs->msr & MSR_SPE)
+ giveup_spe(current);
+#endif /* CONFIG_SPE */
+ preempt_enable();
+}
+
+/*
+ * Copy a thread..
+ */
+int
+copy_thread(int nr, unsigned long clone_flags, unsigned long usp,
+ unsigned long unused,
+ struct task_struct *p, struct pt_regs *regs)
+{
+ struct pt_regs *childregs, *kregs;
+ extern void ret_from_fork(void);
+ unsigned long sp = (unsigned long)p->thread_info + THREAD_SIZE;
+ unsigned long childframe;
+
+ CHECK_FULL_REGS(regs);
+ /* Copy registers */
+ sp -= sizeof(struct pt_regs);
+ childregs = (struct pt_regs *) sp;
+ *childregs = *regs;
+ if ((childregs->msr & MSR_PR) == 0) {
+ /* for kernel thread, set `current' and stackptr in new task */
+ childregs->gpr[1] = sp + sizeof(struct pt_regs);
+ childregs->gpr[2] = (unsigned long) p;
+ p->thread.regs = NULL; /* no user register state */
+ } else {
+ childregs->gpr[1] = usp;
+ p->thread.regs = childregs;
+ if (clone_flags & CLONE_SETTLS)
+ childregs->gpr[2] = childregs->gpr[6];
+ }
+ childregs->gpr[3] = 0; /* Result from fork() */
+ sp -= STACK_FRAME_OVERHEAD;
+ childframe = sp;
+
+ /*
+ * The way this works is that at some point in the future
+ * some task will call _switch to switch to the new task.
+ * That will pop off the stack frame created below and start
+ * the new task running at ret_from_fork. The new task will
+ * do some house keeping and then return from the fork or clone
+ * system call, using the stack frame created above.
+ */
+ sp -= sizeof(struct pt_regs);
+ kregs = (struct pt_regs *) sp;
+ sp -= STACK_FRAME_OVERHEAD;
+ p->thread.ksp = sp;
+ kregs->nip = (unsigned long)ret_from_fork;
+
+ p->thread.last_syscall = -1;
+
+ return 0;
+}
+
+/*
+ * Set up a thread for executing a new program
+ */
+void start_thread(struct pt_regs *regs, unsigned long nip, unsigned long sp)
+{
+ set_fs(USER_DS);
+ memset(regs->gpr, 0, sizeof(regs->gpr));
+ regs->ctr = 0;
+ regs->link = 0;
+ regs->xer = 0;
+ regs->ccr = 0;
+ regs->mq = 0;
+ regs->nip = nip;
+ regs->gpr[1] = sp;
+ regs->msr = MSR_USER;
+ if (last_task_used_math == current)
+ last_task_used_math = NULL;
+ if (last_task_used_altivec == current)
+ last_task_used_altivec = NULL;
+#ifdef CONFIG_SPE
+ if (last_task_used_spe == current)
+ last_task_used_spe = NULL;
+#endif
+ memset(current->thread.fpr, 0, sizeof(current->thread.fpr));
+ current->thread.fpscr = 0;
+#ifdef CONFIG_ALTIVEC
+ memset(current->thread.vr, 0, sizeof(current->thread.vr));
+ memset(¤t->thread.vscr, 0, sizeof(current->thread.vscr));
+ current->thread.vrsave = 0;
+ current->thread.used_vr = 0;
+#endif /* CONFIG_ALTIVEC */
+#ifdef CONFIG_SPE
+ memset(current->thread.evr, 0, sizeof(current->thread.evr));
+ current->thread.acc = 0;
+ current->thread.spefscr = 0;
+ current->thread.used_spe = 0;
+#endif /* CONFIG_SPE */
+}
+
+#define PR_FP_ALL_EXCEPT (PR_FP_EXC_DIV | PR_FP_EXC_OVF | PR_FP_EXC_UND \
+ | PR_FP_EXC_RES | PR_FP_EXC_INV)
+
+int set_fpexc_mode(struct task_struct *tsk, unsigned int val)
+{
+ struct pt_regs *regs = tsk->thread.regs;
+
+ /* This is a bit hairy. If we are an SPE enabled processor
+ * (have embedded fp) we store the IEEE exception enable flags in
+ * fpexc_mode. fpexc_mode is also used for setting FP exception
+ * mode (asyn, precise, disabled) for 'Classic' FP. */
+ if (val & PR_FP_EXC_SW_ENABLE) {
+#ifdef CONFIG_SPE
+ tsk->thread.fpexc_mode = val &
+ (PR_FP_EXC_SW_ENABLE | PR_FP_ALL_EXCEPT);
+#else
+ return -EINVAL;
+#endif
+ } else {
+ /* on a CONFIG_SPE this does not hurt us. The bits that
+ * __pack_fe01 use do not overlap with bits used for
+ * PR_FP_EXC_SW_ENABLE. Additionally, the MSR[FE0,FE1] bits
+ * on CONFIG_SPE implementations are reserved so writing to
+ * them does not change anything */
+ if (val > PR_FP_EXC_PRECISE)
+ return -EINVAL;
+ tsk->thread.fpexc_mode = __pack_fe01(val);
+ if (regs != NULL && (regs->msr & MSR_FP) != 0)
+ regs->msr = (regs->msr & ~(MSR_FE0|MSR_FE1))
+ | tsk->thread.fpexc_mode;
+ }
+ return 0;
+}
+
+int get_fpexc_mode(struct task_struct *tsk, unsigned long adr)
+{
+ unsigned int val;
+
+ if (tsk->thread.fpexc_mode & PR_FP_EXC_SW_ENABLE)
+#ifdef CONFIG_SPE
+ val = tsk->thread.fpexc_mode;
+#else
+ return -EINVAL;
+#endif
+ else
+ val = __unpack_fe01(tsk->thread.fpexc_mode);
+ return put_user(val, (unsigned int __user *) adr);
+}
+
+int sys_clone(unsigned long clone_flags, unsigned long usp,
+ int __user *parent_tidp, void __user *child_threadptr,
+ int __user *child_tidp, int p6,
+ struct pt_regs *regs)
+{
+ CHECK_FULL_REGS(regs);
+ if (usp == 0)
+ usp = regs->gpr[1]; /* stack pointer for child */
+ return do_fork(clone_flags, usp, regs, 0, parent_tidp, child_tidp);
+}
+
+int sys_fork(int p1, int p2, int p3, int p4, int p5, int p6,
+ struct pt_regs *regs)
+{
+ CHECK_FULL_REGS(regs);
+ return do_fork(SIGCHLD, regs->gpr[1], regs, 0, NULL, NULL);
+}
+
+int sys_vfork(int p1, int p2, int p3, int p4, int p5, int p6,
+ struct pt_regs *regs)
+{
+ CHECK_FULL_REGS(regs);
+ return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs->gpr[1],
+ regs, 0, NULL, NULL);
+}
+
+int sys_execve(unsigned long a0, unsigned long a1, unsigned long a2,
+ unsigned long a3, unsigned long a4, unsigned long a5,
+ struct pt_regs *regs)
+{
+ int error;
+ char * filename;
+
+ filename = getname((char __user *) a0);
+ error = PTR_ERR(filename);
+ if (IS_ERR(filename))
+ goto out;
+ preempt_disable();
+ if (regs->msr & MSR_FP)
+ giveup_fpu(current);
+#ifdef CONFIG_ALTIVEC
+ if (regs->msr & MSR_VEC)
+ giveup_altivec(current);
+#endif /* CONFIG_ALTIVEC */
+#ifdef CONFIG_SPE
+ if (regs->msr & MSR_SPE)
+ giveup_spe(current);
+#endif /* CONFIG_SPE */
+ preempt_enable();
+ error = do_execve(filename, (char __user *__user *) a1,
+ (char __user *__user *) a2, regs);
+ if (error == 0) {
+ task_lock(current);
+ current->ptrace &= ~PT_DTRACE;
+ task_unlock(current);
+ }
+ putname(filename);
+out:
+ return error;
+}
+
+void dump_stack(void)
+{
+ show_stack(current, NULL);
+}
+
+EXPORT_SYMBOL(dump_stack);
+
+void show_stack(struct task_struct *tsk, unsigned long *stack)
+{
+ unsigned long sp, stack_top, prev_sp, ret;
+ int count = 0;
+ unsigned long next_exc = 0;
+ struct pt_regs *regs;
+ extern char ret_from_except, ret_from_except_full, ret_from_syscall;
+
+ sp = (unsigned long) stack;
+ if (tsk == NULL)
+ tsk = current;
+ if (sp == 0) {
+ if (tsk == current)
+ asm("mr %0,1" : "=r" (sp));
+ else
+ sp = tsk->thread.ksp;
+ }
+
+ prev_sp = (unsigned long) (tsk->thread_info + 1);
+ stack_top = (unsigned long) tsk->thread_info + THREAD_SIZE;
+ while (count < 16 && sp > prev_sp && sp < stack_top && (sp & 3) == 0) {
+ if (count == 0) {
+ printk("Call trace:");
+#ifdef CONFIG_KALLSYMS
+ printk("\n");
+#endif
+ } else {
+ if (next_exc) {
+ ret = next_exc;
+ next_exc = 0;
+ } else
+ ret = *(unsigned long *)(sp + 4);
+ printk(" [%08lx] ", ret);
+#ifdef CONFIG_KALLSYMS
+ print_symbol("%s", ret);
+ printk("\n");
+#endif
+ if (ret == (unsigned long) &ret_from_except
+ || ret == (unsigned long) &ret_from_except_full
+ || ret == (unsigned long) &ret_from_syscall) {
+ /* sp + 16 points to an exception frame */
+ regs = (struct pt_regs *) (sp + 16);
+ if (sp + 16 + sizeof(*regs) <= stack_top)
+ next_exc = regs->nip;
+ }
+ }
+ ++count;
+ sp = *(unsigned long *)sp;
+ }
+#ifndef CONFIG_KALLSYMS
+ if (count > 0)
+ printk("\n");
+#endif
+}
+
+#if 0
+/*
+ * Low level print for debugging - Cort
+ */
+int __init ll_printk(const char *fmt, ...)
+{
+ va_list args;
+ char buf[256];
+ int i;
+
+ va_start(args, fmt);
+ i=vsprintf(buf,fmt,args);
+ ll_puts(buf);
+ va_end(args);
+ return i;
+}
+
+int lines = 24, cols = 80;
+int orig_x = 0, orig_y = 0;
+
+void puthex(unsigned long val)
+{
+ unsigned char buf[10];
+ int i;
+ for (i = 7; i >= 0; i--)
+ {
+ buf[i] = "0123456789ABCDEF"[val & 0x0F];
+ val >>= 4;
+ }
+ buf[8] = '\0';
+ prom_print(buf);
+}
+
+void __init ll_puts(const char *s)
+{
+ int x,y;
+ char *vidmem = (char *)/*(_ISA_MEM_BASE + 0xB8000) */0xD00B8000;
+ char c;
+ extern int mem_init_done;
+
+ if ( mem_init_done ) /* assume this means we can printk */
+ {
+ printk(s);
+ return;
+ }
+
+#if 0
+ if ( have_of )
+ {
+ prom_print(s);
+ return;
+ }
+#endif
+
+ /*
+ * can't ll_puts on chrp without openfirmware yet.
+ * vidmem just needs to be setup for it.
+ * -- Cort
+ */
+ if ( _machine != _MACH_prep )
+ return;
+ x = orig_x;
+ y = orig_y;
+
+ while ( ( c = *s++ ) != '\0' ) {
+ if ( c == '\n' ) {
+ x = 0;
+ if ( ++y >= lines ) {
+ /*scroll();*/
+ /*y--;*/
+ y = 0;
+ }
+ } else {
+ vidmem [ ( x + cols * y ) * 2 ] = c;
+ if ( ++x >= cols ) {
+ x = 0;
+ if ( ++y >= lines ) {
+ /*scroll();*/
+ /*y--;*/
+ y = 0;
+ }
+ }
+ }
+ }
+
+ orig_x = x;
+ orig_y = y;
+}
+#endif
+
+unsigned long get_wchan(struct task_struct *p)
+{
+ unsigned long ip, sp;
+ unsigned long stack_page = (unsigned long) p->thread_info;
+ int count = 0;
+ if (!p || p == current || p->state == TASK_RUNNING)
+ return 0;
+ sp = p->thread.ksp;
+ do {
+ sp = *(unsigned long *)sp;
+ if (sp < stack_page || sp >= stack_page + 8188)
+ return 0;
+ if (count > 0) {
+ ip = *(unsigned long *)(sp + 4);
+ if (!in_sched_functions(ip))
+ return ip;
+ }
+ } while (count++ < 16);
+ return 0;
+}
diff --git a/arch/ppc/kernel/ptrace.c b/arch/ppc/kernel/ptrace.c
new file mode 100644
index 0000000..426b6f7
--- /dev/null
+++ b/arch/ppc/kernel/ptrace.c
@@ -0,0 +1,474 @@
+/*
+ * arch/ppc/kernel/ptrace.c
+ *
+ * PowerPC version
+ * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
+ *
+ * Derived from "arch/m68k/kernel/ptrace.c"
+ * Copyright (C) 1994 by Hamish Macdonald
+ * Taken from linux/kernel/ptrace.c and modified for M680x0.
+ * linux/kernel/ptrace.c is by Ross Biro 1/23/92, edited by Linus Torvalds
+ *
+ * Modified by Cort Dougan (cort@hq.fsmlabs.com)
+ * and Paul Mackerras (paulus@linuxcare.com.au).
+ *
+ * This file is subject to the terms and conditions of the GNU General
+ * Public License. See the file README.legal in the main directory of
+ * this archive for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/smp.h>
+#include <linux/smp_lock.h>
+#include <linux/errno.h>
+#include <linux/ptrace.h>
+#include <linux/user.h>
+#include <linux/security.h>
+
+#include <asm/uaccess.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <asm/system.h>
+
+/*
+ * Set of msr bits that gdb can change on behalf of a process.
+ */
+#if defined(CONFIG_40x) || defined(CONFIG_BOOKE)
+#define MSR_DEBUGCHANGE 0
+#else
+#define MSR_DEBUGCHANGE (MSR_SE | MSR_BE)
+#endif
+
+/*
+ * does not yet catch signals sent when the child dies.
+ * in exit.c or in signal.c.
+ */
+
+/*
+ * Get contents of register REGNO in task TASK.
+ */
+static inline unsigned long get_reg(struct task_struct *task, int regno)
+{
+ if (regno < sizeof(struct pt_regs) / sizeof(unsigned long)
+ && task->thread.regs != NULL)
+ return ((unsigned long *)task->thread.regs)[regno];
+ return (0);
+}
+
+/*
+ * Write contents of register REGNO in task TASK.
+ */
+static inline int put_reg(struct task_struct *task, int regno,
+ unsigned long data)
+{
+ if (regno <= PT_MQ && task->thread.regs != NULL) {
+ if (regno == PT_MSR)
+ data = (data & MSR_DEBUGCHANGE)
+ | (task->thread.regs->msr & ~MSR_DEBUGCHANGE);
+ ((unsigned long *)task->thread.regs)[regno] = data;
+ return 0;
+ }
+ return -EIO;
+}
+
+#ifdef CONFIG_ALTIVEC
+/*
+ * Get contents of AltiVec register state in task TASK
+ */
+static inline int get_vrregs(unsigned long __user *data, struct task_struct *task)
+{
+ int i, j;
+
+ if (!access_ok(VERIFY_WRITE, data, 133 * sizeof(unsigned long)))
+ return -EFAULT;
+
+ /* copy AltiVec registers VR[0] .. VR[31] */
+ for (i = 0; i < 32; i++)
+ for (j = 0; j < 4; j++, data++)
+ if (__put_user(task->thread.vr[i].u[j], data))
+ return -EFAULT;
+
+ /* copy VSCR */
+ for (i = 0; i < 4; i++, data++)
+ if (__put_user(task->thread.vscr.u[i], data))
+ return -EFAULT;
+
+ /* copy VRSAVE */
+ if (__put_user(task->thread.vrsave, data))
+ return -EFAULT;
+
+ return 0;
+}
+
+/*
+ * Write contents of AltiVec register state into task TASK.
+ */
+static inline int set_vrregs(struct task_struct *task, unsigned long __user *data)
+{
+ int i, j;
+
+ if (!access_ok(VERIFY_READ, data, 133 * sizeof(unsigned long)))
+ return -EFAULT;
+
+ /* copy AltiVec registers VR[0] .. VR[31] */
+ for (i = 0; i < 32; i++)
+ for (j = 0; j < 4; j++, data++)
+ if (__get_user(task->thread.vr[i].u[j], data))
+ return -EFAULT;
+
+ /* copy VSCR */
+ for (i = 0; i < 4; i++, data++)
+ if (__get_user(task->thread.vscr.u[i], data))
+ return -EFAULT;
+
+ /* copy VRSAVE */
+ if (__get_user(task->thread.vrsave, data))
+ return -EFAULT;
+
+ return 0;
+}
+#endif
+
+#ifdef CONFIG_SPE
+
+/*
+ * For get_evrregs/set_evrregs functions 'data' has the following layout:
+ *
+ * struct {
+ * u32 evr[32];
+ * u64 acc;
+ * u32 spefscr;
+ * }
+ */
+
+/*
+ * Get contents of SPE register state in task TASK.
+ */
+static inline int get_evrregs(unsigned long *data, struct task_struct *task)
+{
+ int i;
+
+ if (!access_ok(VERIFY_WRITE, data, 35 * sizeof(unsigned long)))
+ return -EFAULT;
+
+ /* copy SPEFSCR */
+ if (__put_user(task->thread.spefscr, &data[34]))
+ return -EFAULT;
+
+ /* copy SPE registers EVR[0] .. EVR[31] */
+ for (i = 0; i < 32; i++, data++)
+ if (__put_user(task->thread.evr[i], data))
+ return -EFAULT;
+
+ /* copy ACC */
+ if (__put_user64(task->thread.acc, (unsigned long long *)data))
+ return -EFAULT;
+
+ return 0;
+}
+
+/*
+ * Write contents of SPE register state into task TASK.
+ */
+static inline int set_evrregs(struct task_struct *task, unsigned long *data)
+{
+ int i;
+
+ if (!access_ok(VERIFY_READ, data, 35 * sizeof(unsigned long)))
+ return -EFAULT;
+
+ /* copy SPEFSCR */
+ if (__get_user(task->thread.spefscr, &data[34]))
+ return -EFAULT;
+
+ /* copy SPE registers EVR[0] .. EVR[31] */
+ for (i = 0; i < 32; i++, data++)
+ if (__get_user(task->thread.evr[i], data))
+ return -EFAULT;
+ /* copy ACC */
+ if (__get_user64(task->thread.acc, (unsigned long long*)data))
+ return -EFAULT;
+
+ return 0;
+}
+#endif /* CONFIG_SPE */
+
+static inline void
+set_single_step(struct task_struct *task)
+{
+ struct pt_regs *regs = task->thread.regs;
+
+ if (regs != NULL) {
+#if defined(CONFIG_40x) || defined(CONFIG_BOOKE)
+ task->thread.dbcr0 = DBCR0_IDM | DBCR0_IC;
+ regs->msr |= MSR_DE;
+#else
+ regs->msr |= MSR_SE;
+#endif
+ }
+}
+
+static inline void
+clear_single_step(struct task_struct *task)
+{
+ struct pt_regs *regs = task->thread.regs;
+
+ if (regs != NULL) {
+#if defined(CONFIG_40x) || defined(CONFIG_BOOKE)
+ task->thread.dbcr0 = 0;
+ regs->msr &= ~MSR_DE;
+#else
+ regs->msr &= ~MSR_SE;
+#endif
+ }
+}
+
+/*
+ * Called by kernel/ptrace.c when detaching..
+ *
+ * Make sure single step bits etc are not set.
+ */
+void ptrace_disable(struct task_struct *child)
+{
+ /* make sure the single step bit is not set. */
+ clear_single_step(child);
+}
+
+int sys_ptrace(long request, long pid, long addr, long data)
+{
+ struct task_struct *child;
+ int ret = -EPERM;
+
+ lock_kernel();
+ if (request == PTRACE_TRACEME) {
+ /* are we already being traced? */
+ if (current->ptrace & PT_PTRACED)
+ goto out;
+ ret = security_ptrace(current->parent, current);
+ if (ret)
+ goto out;
+ /* set the ptrace bit in the process flags. */
+ current->ptrace |= PT_PTRACED;
+ ret = 0;
+ goto out;
+ }
+ ret = -ESRCH;
+ read_lock(&tasklist_lock);
+ child = find_task_by_pid(pid);
+ if (child)
+ get_task_struct(child);
+ read_unlock(&tasklist_lock);
+ if (!child)
+ goto out;
+
+ ret = -EPERM;
+ if (pid == 1) /* you may not mess with init */
+ goto out_tsk;
+
+ if (request == PTRACE_ATTACH) {
+ ret = ptrace_attach(child);
+ goto out_tsk;
+ }
+
+ ret = ptrace_check_attach(child, request == PTRACE_KILL);
+ if (ret < 0)
+ goto out_tsk;
+
+ switch (request) {
+ /* when I and D space are separate, these will need to be fixed. */
+ case PTRACE_PEEKTEXT: /* read word at location addr. */
+ case PTRACE_PEEKDATA: {
+ unsigned long tmp;
+ int copied;
+
+ copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 0);
+ ret = -EIO;
+ if (copied != sizeof(tmp))
+ break;
+ ret = put_user(tmp,(unsigned long __user *) data);
+ break;
+ }
+
+ /* read the word at location addr in the USER area. */
+ /* XXX this will need fixing for 64-bit */
+ case PTRACE_PEEKUSR: {
+ unsigned long index, tmp;
+
+ ret = -EIO;
+ /* convert to index and check */
+ index = (unsigned long) addr >> 2;
+ if ((addr & 3) || index > PT_FPSCR
+ || child->thread.regs == NULL)
+ break;
+
+ CHECK_FULL_REGS(child->thread.regs);
+ if (index < PT_FPR0) {
+ tmp = get_reg(child, (int) index);
+ } else {
+ preempt_disable();
+ if (child->thread.regs->msr & MSR_FP)
+ giveup_fpu(child);
+ preempt_enable();
+ tmp = ((unsigned long *)child->thread.fpr)[index - PT_FPR0];
+ }
+ ret = put_user(tmp,(unsigned long __user *) data);
+ break;
+ }
+
+ /* If I and D space are separate, this will have to be fixed. */
+ case PTRACE_POKETEXT: /* write the word at location addr. */
+ case PTRACE_POKEDATA:
+ ret = 0;
+ if (access_process_vm(child, addr, &data, sizeof(data), 1) == sizeof(data))
+ break;
+ ret = -EIO;
+ break;
+
+ /* write the word at location addr in the USER area */
+ case PTRACE_POKEUSR: {
+ unsigned long index;
+
+ ret = -EIO;
+ /* convert to index and check */
+ index = (unsigned long) addr >> 2;
+ if ((addr & 3) || index > PT_FPSCR
+ || child->thread.regs == NULL)
+ break;
+
+ CHECK_FULL_REGS(child->thread.regs);
+ if (index == PT_ORIG_R3)
+ break;
+ if (index < PT_FPR0) {
+ ret = put_reg(child, index, data);
+ } else {
+ preempt_disable();
+ if (child->thread.regs->msr & MSR_FP)
+ giveup_fpu(child);
+ preempt_enable();
+ ((unsigned long *)child->thread.fpr)[index - PT_FPR0] = data;
+ ret = 0;
+ }
+ break;
+ }
+
+ case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */
+ case PTRACE_CONT: { /* restart after signal. */
+ ret = -EIO;
+ if ((unsigned long) data > _NSIG)
+ break;
+ if (request == PTRACE_SYSCALL) {
+ set_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
+ } else {
+ clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
+ }
+ child->exit_code = data;
+ /* make sure the single step bit is not set. */
+ clear_single_step(child);
+ wake_up_process(child);
+ ret = 0;
+ break;
+ }
+
+/*
+ * make the child exit. Best I can do is send it a sigkill.
+ * perhaps it should be put in the status that it wants to
+ * exit.
+ */
+ case PTRACE_KILL: {
+ ret = 0;
+ if (child->exit_state == EXIT_ZOMBIE) /* already dead */
+ break;
+ child->exit_code = SIGKILL;
+ /* make sure the single step bit is not set. */
+ clear_single_step(child);
+ wake_up_process(child);
+ break;
+ }
+
+ case PTRACE_SINGLESTEP: { /* set the trap flag. */
+ ret = -EIO;
+ if ((unsigned long) data > _NSIG)
+ break;
+ clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
+ set_single_step(child);
+ child->exit_code = data;
+ /* give it a chance to run. */
+ wake_up_process(child);
+ ret = 0;
+ break;
+ }
+
+ case PTRACE_DETACH:
+ ret = ptrace_detach(child, data);
+ break;
+
+#ifdef CONFIG_ALTIVEC
+ case PTRACE_GETVRREGS:
+ /* Get the child altivec register state. */
+ preempt_disable();
+ if (child->thread.regs->msr & MSR_VEC)
+ giveup_altivec(child);
+ preempt_enable();
+ ret = get_vrregs((unsigned long __user *)data, child);
+ break;
+
+ case PTRACE_SETVRREGS:
+ /* Set the child altivec register state. */
+ /* this is to clear the MSR_VEC bit to force a reload
+ * of register state from memory */
+ preempt_disable();
+ if (child->thread.regs->msr & MSR_VEC)
+ giveup_altivec(child);
+ preempt_enable();
+ ret = set_vrregs(child, (unsigned long __user *)data);
+ break;
+#endif
+#ifdef CONFIG_SPE
+ case PTRACE_GETEVRREGS:
+ /* Get the child spe register state. */
+ if (child->thread.regs->msr & MSR_SPE)
+ giveup_spe(child);
+ ret = get_evrregs((unsigned long __user *)data, child);
+ break;
+
+ case PTRACE_SETEVRREGS:
+ /* Set the child spe register state. */
+ /* this is to clear the MSR_SPE bit to force a reload
+ * of register state from memory */
+ if (child->thread.regs->msr & MSR_SPE)
+ giveup_spe(child);
+ ret = set_evrregs(child, (unsigned long __user *)data);
+ break;
+#endif
+
+ default:
+ ret = ptrace_request(child, request, addr, data);
+ break;
+ }
+out_tsk:
+ put_task_struct(child);
+out:
+ unlock_kernel();
+ return ret;
+}
+
+void do_syscall_trace(void)
+{
+ if (!test_thread_flag(TIF_SYSCALL_TRACE)
+ || !(current->ptrace & PT_PTRACED))
+ return;
+ ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD)
+ ? 0x80 : 0));
+
+ /*
+ * this isn't the same as continuing with a signal, but it will do
+ * for normal use. strace only continues with a signal if the
+ * stopping signal is not SIGTRAP. -brl
+ */
+ if (current->exit_code) {
+ send_sig(current->exit_code, current, 1);
+ current->exit_code = 0;
+ }
+}
diff --git a/arch/ppc/kernel/semaphore.c b/arch/ppc/kernel/semaphore.c
new file mode 100644
index 0000000..2fe429b
--- /dev/null
+++ b/arch/ppc/kernel/semaphore.c
@@ -0,0 +1,131 @@
+/*
+ * PowerPC-specific semaphore code.
+ *
+ * Copyright (C) 1999 Cort Dougan <cort@cs.nmt.edu>
+ *
+ * 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.
+ *
+ * April 2001 - Reworked by Paul Mackerras <paulus@samba.org>
+ * to eliminate the SMP races in the old version between the updates
+ * of `count' and `waking'. Now we use negative `count' values to
+ * indicate that some process(es) are waiting for the semaphore.
+ */
+
+#include <linux/sched.h>
+#include <linux/init.h>
+#include <asm/atomic.h>
+#include <asm/semaphore.h>
+#include <asm/errno.h>
+
+/*
+ * Atomically update sem->count.
+ * This does the equivalent of the following:
+ *
+ * old_count = sem->count;
+ * tmp = MAX(old_count, 0) + incr;
+ * sem->count = tmp;
+ * return old_count;
+ */
+static inline int __sem_update_count(struct semaphore *sem, int incr)
+{
+ int old_count, tmp;
+
+ __asm__ __volatile__("\n"
+"1: lwarx %0,0,%3\n"
+" srawi %1,%0,31\n"
+" andc %1,%0,%1\n"
+" add %1,%1,%4\n"
+ PPC405_ERR77(0,%3)
+" stwcx. %1,0,%3\n"
+" bne 1b"
+ : "=&r" (old_count), "=&r" (tmp), "=m" (sem->count)
+ : "r" (&sem->count), "r" (incr), "m" (sem->count)
+ : "cc");
+
+ return old_count;
+}
+
+void __up(struct semaphore *sem)
+{
+ /*
+ * Note that we incremented count in up() before we came here,
+ * but that was ineffective since the result was <= 0, and
+ * any negative value of count is equivalent to 0.
+ * This ends up setting count to 1, unless count is now > 0
+ * (i.e. because some other cpu has called up() in the meantime),
+ * in which case we just increment count.
+ */
+ __sem_update_count(sem, 1);
+ wake_up(&sem->wait);
+}
+
+/*
+ * Note that when we come in to __down or __down_interruptible,
+ * we have already decremented count, but that decrement was
+ * ineffective since the result was < 0, and any negative value
+ * of count is equivalent to 0.
+ * Thus it is only when we decrement count from some value > 0
+ * that we have actually got the semaphore.
+ */
+void __sched __down(struct semaphore *sem)
+{
+ struct task_struct *tsk = current;
+ DECLARE_WAITQUEUE(wait, tsk);
+
+ tsk->state = TASK_UNINTERRUPTIBLE;
+ add_wait_queue_exclusive(&sem->wait, &wait);
+ smp_wmb();
+
+ /*
+ * Try to get the semaphore. If the count is > 0, then we've
+ * got the semaphore; we decrement count and exit the loop.
+ * If the count is 0 or negative, we set it to -1, indicating
+ * that we are asleep, and then sleep.
+ */
+ while (__sem_update_count(sem, -1) <= 0) {
+ schedule();
+ tsk->state = TASK_UNINTERRUPTIBLE;
+ }
+ remove_wait_queue(&sem->wait, &wait);
+ tsk->state = TASK_RUNNING;
+
+ /*
+ * If there are any more sleepers, wake one of them up so
+ * that it can either get the semaphore, or set count to -1
+ * indicating that there are still processes sleeping.
+ */
+ wake_up(&sem->wait);
+}
+
+int __sched __down_interruptible(struct semaphore * sem)
+{
+ int retval = 0;
+ struct task_struct *tsk = current;
+ DECLARE_WAITQUEUE(wait, tsk);
+
+ tsk->state = TASK_INTERRUPTIBLE;
+ add_wait_queue_exclusive(&sem->wait, &wait);
+ smp_wmb();
+
+ while (__sem_update_count(sem, -1) <= 0) {
+ if (signal_pending(current)) {
+ /*
+ * A signal is pending - give up trying.
+ * Set sem->count to 0 if it is negative,
+ * since we are no longer sleeping.
+ */
+ __sem_update_count(sem, 0);
+ retval = -EINTR;
+ break;
+ }
+ schedule();
+ tsk->state = TASK_INTERRUPTIBLE;
+ }
+ tsk->state = TASK_RUNNING;
+ remove_wait_queue(&sem->wait, &wait);
+ wake_up(&sem->wait);
+ return retval;
+}
diff --git a/arch/ppc/kernel/setup.c b/arch/ppc/kernel/setup.c
new file mode 100644
index 0000000..e97ce63
--- /dev/null
+++ b/arch/ppc/kernel/setup.c
@@ -0,0 +1,778 @@
+/*
+ * Common prep/pmac/chrp boot and setup code.
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/sched.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/reboot.h>
+#include <linux/delay.h>
+#include <linux/initrd.h>
+#include <linux/ide.h>
+#include <linux/tty.h>
+#include <linux/bootmem.h>
+#include <linux/seq_file.h>
+#include <linux/root_dev.h>
+#include <linux/cpu.h>
+#include <linux/console.h>
+
+#include <asm/residual.h>
+#include <asm/io.h>
+#include <asm/prom.h>
+#include <asm/processor.h>
+#include <asm/pgtable.h>
+#include <asm/bootinfo.h>
+#include <asm/setup.h>
+#include <asm/amigappc.h>
+#include <asm/smp.h>
+#include <asm/elf.h>
+#include <asm/cputable.h>
+#include <asm/bootx.h>
+#include <asm/btext.h>
+#include <asm/machdep.h>
+#include <asm/uaccess.h>
+#include <asm/system.h>
+#include <asm/pmac_feature.h>
+#include <asm/sections.h>
+#include <asm/nvram.h>
+#include <asm/xmon.h>
+#include <asm/ocp.h>
+
+#if defined(CONFIG_85xx) || defined(CONFIG_83xx)
+#include <asm/ppc_sys.h>
+#endif
+
+#if defined CONFIG_KGDB
+#include <asm/kgdb.h>
+#endif
+
+extern void platform_init(unsigned long r3, unsigned long r4,
+ unsigned long r5, unsigned long r6, unsigned long r7);
+extern void bootx_init(unsigned long r4, unsigned long phys);
+extern void identify_cpu(unsigned long offset, unsigned long cpu);
+extern void do_cpu_ftr_fixups(unsigned long offset);
+extern void reloc_got2(unsigned long offset);
+
+extern void ppc6xx_idle(void);
+extern void power4_idle(void);
+
+extern boot_infos_t *boot_infos;
+struct ide_machdep_calls ppc_ide_md;
+char *sysmap;
+unsigned long sysmap_size;
+
+/* Used with the BI_MEMSIZE bootinfo parameter to store the memory
+ size value reported by the boot loader. */
+unsigned long boot_mem_size;
+
+unsigned long ISA_DMA_THRESHOLD;
+unsigned long DMA_MODE_READ, DMA_MODE_WRITE;
+
+#ifdef CONFIG_PPC_MULTIPLATFORM
+int _machine = 0;
+
+extern void prep_init(unsigned long r3, unsigned long r4,
+ unsigned long r5, unsigned long r6, unsigned long r7);
+extern void pmac_init(unsigned long r3, unsigned long r4,
+ unsigned long r5, unsigned long r6, unsigned long r7);
+extern void chrp_init(unsigned long r3, unsigned long r4,
+ unsigned long r5, unsigned long r6, unsigned long r7);
+#endif /* CONFIG_PPC_MULTIPLATFORM */
+
+#ifdef CONFIG_MAGIC_SYSRQ
+unsigned long SYSRQ_KEY = 0x54;
+#endif /* CONFIG_MAGIC_SYSRQ */
+
+#ifdef CONFIG_VGA_CONSOLE
+unsigned long vgacon_remap_base;
+#endif
+
+struct machdep_calls ppc_md;
+
+/*
+ * These are used in binfmt_elf.c to put aux entries on the stack
+ * for each elf executable being started.
+ */
+int dcache_bsize;
+int icache_bsize;
+int ucache_bsize;
+
+#if defined(CONFIG_VGA_CONSOLE) || defined(CONFIG_FB_VGA16) || \
+ defined(CONFIG_FB_VGA16_MODULE) || defined(CONFIG_FB_VESA)
+struct screen_info screen_info = {
+ 0, 25, /* orig-x, orig-y */
+ 0, /* unused */
+ 0, /* orig-video-page */
+ 0, /* orig-video-mode */
+ 80, /* orig-video-cols */
+ 0,0,0, /* ega_ax, ega_bx, ega_cx */
+ 25, /* orig-video-lines */
+ 1, /* orig-video-isVGA */
+ 16 /* orig-video-points */
+};
+#endif /* CONFIG_VGA_CONSOLE || CONFIG_FB_VGA16 || CONFIG_FB_VESA */
+
+void machine_restart(char *cmd)
+{
+#ifdef CONFIG_NVRAM
+ nvram_sync();
+#endif
+ ppc_md.restart(cmd);
+}
+
+EXPORT_SYMBOL(machine_restart);
+
+void machine_power_off(void)
+{
+#ifdef CONFIG_NVRAM
+ nvram_sync();
+#endif
+ ppc_md.power_off();
+}
+
+EXPORT_SYMBOL(machine_power_off);
+
+void machine_halt(void)
+{
+#ifdef CONFIG_NVRAM
+ nvram_sync();
+#endif
+ ppc_md.halt();
+}
+
+EXPORT_SYMBOL(machine_halt);
+
+void (*pm_power_off)(void) = machine_power_off;
+
+#ifdef CONFIG_TAU
+extern u32 cpu_temp(unsigned long cpu);
+extern u32 cpu_temp_both(unsigned long cpu);
+#endif /* CONFIG_TAU */
+
+int show_cpuinfo(struct seq_file *m, void *v)
+{
+ int i = (int) v - 1;
+ int err = 0;
+ unsigned int pvr;
+ unsigned short maj, min;
+ unsigned long lpj;
+
+ if (i >= NR_CPUS) {
+ /* Show summary information */
+#ifdef CONFIG_SMP
+ unsigned long bogosum = 0;
+ for (i = 0; i < NR_CPUS; ++i)
+ if (cpu_online(i))
+ bogosum += cpu_data[i].loops_per_jiffy;
+ seq_printf(m, "total bogomips\t: %lu.%02lu\n",
+ bogosum/(500000/HZ), bogosum/(5000/HZ) % 100);
+#endif /* CONFIG_SMP */
+
+ if (ppc_md.show_cpuinfo != NULL)
+ err = ppc_md.show_cpuinfo(m);
+ return err;
+ }
+
+#ifdef CONFIG_SMP
+ if (!cpu_online(i))
+ return 0;
+ pvr = cpu_data[i].pvr;
+ lpj = cpu_data[i].loops_per_jiffy;
+#else
+ pvr = mfspr(SPRN_PVR);
+ lpj = loops_per_jiffy;
+#endif
+
+ seq_printf(m, "processor\t: %d\n", i);
+ seq_printf(m, "cpu\t\t: ");
+
+ if (cur_cpu_spec[i]->pvr_mask)
+ seq_printf(m, "%s", cur_cpu_spec[i]->cpu_name);
+ else
+ seq_printf(m, "unknown (%08x)", pvr);
+#ifdef CONFIG_ALTIVEC
+ if (cur_cpu_spec[i]->cpu_features & CPU_FTR_ALTIVEC)
+ seq_printf(m, ", altivec supported");
+#endif
+ seq_printf(m, "\n");
+
+#ifdef CONFIG_TAU
+ if (cur_cpu_spec[i]->cpu_features & CPU_FTR_TAU) {
+#ifdef CONFIG_TAU_AVERAGE
+ /* more straightforward, but potentially misleading */
+ seq_printf(m, "temperature \t: %u C (uncalibrated)\n",
+ cpu_temp(i));
+#else
+ /* show the actual temp sensor range */
+ u32 temp;
+ temp = cpu_temp_both(i);
+ seq_printf(m, "temperature \t: %u-%u C (uncalibrated)\n",
+ temp & 0xff, temp >> 16);
+#endif
+ }
+#endif /* CONFIG_TAU */
+
+ if (ppc_md.show_percpuinfo != NULL) {
+ err = ppc_md.show_percpuinfo(m, i);
+ if (err)
+ return err;
+ }
+
+ switch (PVR_VER(pvr)) {
+ case 0x0020: /* 403 family */
+ maj = PVR_MAJ(pvr) + 1;
+ min = PVR_MIN(pvr);
+ break;
+ case 0x1008: /* 740P/750P ?? */
+ maj = ((pvr >> 8) & 0xFF) - 1;
+ min = pvr & 0xFF;
+ break;
+ case 0x8083: /* e300 */
+ maj = PVR_MAJ(pvr);
+ min = PVR_MIN(pvr);
+ break;
+ case 0x8020: /* e500 */
+ maj = PVR_MAJ(pvr);
+ min = PVR_MIN(pvr);
+ break;
+ default:
+ maj = (pvr >> 8) & 0xFF;
+ min = pvr & 0xFF;
+ break;
+ }
+
+ seq_printf(m, "revision\t: %hd.%hd (pvr %04x %04x)\n",
+ maj, min, PVR_VER(pvr), PVR_REV(pvr));
+
+ seq_printf(m, "bogomips\t: %lu.%02lu\n",
+ lpj / (500000/HZ), (lpj / (5000/HZ)) % 100);
+
+#if defined(CONFIG_85xx) || defined(CONFIG_83xx)
+ if (cur_ppc_sys_spec->ppc_sys_name)
+ seq_printf(m, "chipset\t\t: %s\n",
+ cur_ppc_sys_spec->ppc_sys_name);
+#endif
+
+#ifdef CONFIG_SMP
+ seq_printf(m, "\n");
+#endif
+
+ return 0;
+}
+
+static void *c_start(struct seq_file *m, loff_t *pos)
+{
+ int i = *pos;
+
+ return i <= NR_CPUS? (void *) (i + 1): NULL;
+}
+
+static void *c_next(struct seq_file *m, void *v, loff_t *pos)
+{
+ ++*pos;
+ return c_start(m, pos);
+}
+
+static void c_stop(struct seq_file *m, void *v)
+{
+}
+
+struct seq_operations cpuinfo_op = {
+ .start =c_start,
+ .next = c_next,
+ .stop = c_stop,
+ .show = show_cpuinfo,
+};
+
+/*
+ * We're called here very early in the boot. We determine the machine
+ * type and call the appropriate low-level setup functions.
+ * -- Cort <cort@fsmlabs.com>
+ *
+ * Note that the kernel may be running at an address which is different
+ * from the address that it was linked at, so we must use RELOC/PTRRELOC
+ * to access static data (including strings). -- paulus
+ */
+__init
+unsigned long
+early_init(int r3, int r4, int r5)
+{
+ unsigned long phys;
+ unsigned long offset = reloc_offset();
+
+ /* Default */
+ phys = offset + KERNELBASE;
+
+ /* First zero the BSS -- use memset, some arches don't have
+ * caches on yet */
+ memset_io(PTRRELOC(&__bss_start), 0, _end - __bss_start);
+
+ /*
+ * Identify the CPU type and fix up code sections
+ * that depend on which cpu we have.
+ */
+ identify_cpu(offset, 0);
+ do_cpu_ftr_fixups(offset);
+
+#if defined(CONFIG_PPC_MULTIPLATFORM)
+ reloc_got2(offset);
+
+ /* If we came here from BootX, clear the screen,
+ * set up some pointers and return. */
+ if ((r3 == 0x426f6f58) && (r5 == 0))
+ bootx_init(r4, phys);
+
+ /*
+ * don't do anything on prep
+ * for now, don't use bootinfo because it breaks yaboot 0.5
+ * and assume that if we didn't find a magic number, we have OF
+ */
+ else if (*(unsigned long *)(0) != 0xdeadc0de)
+ phys = prom_init(r3, r4, (prom_entry)r5);
+
+ reloc_got2(-offset);
+#endif
+
+ return phys;
+}
+
+#ifdef CONFIG_PPC_OF
+/*
+ * Assume here that all clock rates are the same in a
+ * smp system. -- Cort
+ */
+int __openfirmware
+of_show_percpuinfo(struct seq_file *m, int i)
+{
+ struct device_node *cpu_node;
+ u32 *fp;
+ int s;
+
+ cpu_node = find_type_devices("cpu");
+ if (!cpu_node)
+ return 0;
+ for (s = 0; s < i && cpu_node->next; s++)
+ cpu_node = cpu_node->next;
+ fp = (u32 *)get_property(cpu_node, "clock-frequency", NULL);
+ if (fp)
+ seq_printf(m, "clock\t\t: %dMHz\n", *fp / 1000000);
+ return 0;
+}
+
+void __init
+intuit_machine_type(void)
+{
+ char *model;
+ struct device_node *root;
+
+ /* ask the OF info if we're a chrp or pmac */
+ root = find_path_device("/");
+ if (root != 0) {
+ /* assume pmac unless proven to be chrp -- Cort */
+ _machine = _MACH_Pmac;
+ model = get_property(root, "device_type", NULL);
+ if (model && !strncmp("chrp", model, 4))
+ _machine = _MACH_chrp;
+ else {
+ model = get_property(root, "model", NULL);
+ if (model && !strncmp(model, "IBM", 3))
+ _machine = _MACH_chrp;
+ }
+ }
+}
+#endif
+
+#ifdef CONFIG_PPC_MULTIPLATFORM
+/*
+ * The PPC_MULTIPLATFORM version of platform_init...
+ */
+void __init
+platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
+ unsigned long r6, unsigned long r7)
+{
+#ifdef CONFIG_BOOTX_TEXT
+ if (boot_text_mapped) {
+ btext_clearscreen();
+ btext_welcome();
+ }
+#endif
+
+ parse_bootinfo(find_bootinfo());
+
+ /* if we didn't get any bootinfo telling us what we are... */
+ if (_machine == 0) {
+ /* prep boot loader tells us if we're prep or not */
+ if ( *(unsigned long *)(KERNELBASE) == (0xdeadc0de) )
+ _machine = _MACH_prep;
+ }
+
+ /* not much more to do here, if prep */
+ if (_machine == _MACH_prep) {
+ prep_init(r3, r4, r5, r6, r7);
+ return;
+ }
+
+ /* prom_init has already been called from __start */
+ if (boot_infos)
+ relocate_nodes();
+
+ /* If we aren't PReP, we can find out if we're Pmac
+ * or CHRP with this. */
+ if (_machine == 0)
+ intuit_machine_type();
+
+ /* finish_device_tree may need _machine defined. */
+ finish_device_tree();
+
+ /*
+ * If we were booted via quik, r3 points to the physical
+ * address of the command-line parameters.
+ * If we were booted from an xcoff image (i.e. netbooted or
+ * booted from floppy), we get the command line from the
+ * bootargs property of the /chosen node.
+ * If an initial ramdisk is present, r3 and r4
+ * are used for initrd_start and initrd_size,
+ * otherwise they contain 0xdeadbeef.
+ */
+ if (r3 >= 0x4000 && r3 < 0x800000 && r4 == 0) {
+ strlcpy(cmd_line, (char *)r3 + KERNELBASE,
+ sizeof(cmd_line));
+ } else if (boot_infos != 0) {
+ /* booted by BootX - check for ramdisk */
+ if (boot_infos->kernelParamsOffset != 0)
+ strlcpy(cmd_line, (char *) boot_infos
+ + boot_infos->kernelParamsOffset,
+ sizeof(cmd_line));
+#ifdef CONFIG_BLK_DEV_INITRD
+ if (boot_infos->ramDisk) {
+ initrd_start = (unsigned long) boot_infos
+ + boot_infos->ramDisk;
+ initrd_end = initrd_start + boot_infos->ramDiskSize;
+ initrd_below_start_ok = 1;
+ }
+#endif
+ } else {
+ struct device_node *chosen;
+ char *p;
+
+#ifdef CONFIG_BLK_DEV_INITRD
+ if (r3 && r4 && r4 != 0xdeadbeef) {
+ if (r3 < KERNELBASE)
+ r3 += KERNELBASE;
+ initrd_start = r3;
+ initrd_end = r3 + r4;
+ ROOT_DEV = Root_RAM0;
+ initrd_below_start_ok = 1;
+ }
+#endif
+ chosen = find_devices("chosen");
+ if (chosen != NULL) {
+ p = get_property(chosen, "bootargs", NULL);
+ if (p && *p) {
+ strlcpy(cmd_line, p, sizeof(cmd_line));
+ }
+ }
+ }
+#ifdef CONFIG_ADB
+ if (strstr(cmd_line, "adb_sync")) {
+ extern int __adb_probe_sync;
+ __adb_probe_sync = 1;
+ }
+#endif /* CONFIG_ADB */
+
+ switch (_machine) {
+ case _MACH_Pmac:
+ pmac_init(r3, r4, r5, r6, r7);
+ break;
+ case _MACH_chrp:
+ chrp_init(r3, r4, r5, r6, r7);
+ break;
+ }
+}
+
+#ifdef CONFIG_SERIAL_CORE_CONSOLE
+extern char *of_stdout_device;
+
+static int __init set_preferred_console(void)
+{
+ struct device_node *prom_stdout;
+ char *name;
+ int offset;
+
+ if (of_stdout_device == NULL)
+ return -ENODEV;
+
+ /* The user has requested a console so this is already set up. */
+ if (strstr(saved_command_line, "console="))
+ return -EBUSY;
+
+ prom_stdout = find_path_device(of_stdout_device);
+ if (!prom_stdout)
+ return -ENODEV;
+
+ name = (char *)get_property(prom_stdout, "name", NULL);
+ if (!name)
+ return -ENODEV;
+
+ if (strcmp(name, "serial") == 0) {
+ int i;
+ u32 *reg = (u32 *)get_property(prom_stdout, "reg", &i);
+ if (i > 8) {
+ switch (reg[1]) {
+ case 0x3f8:
+ offset = 0;
+ break;
+ case 0x2f8:
+ offset = 1;
+ break;
+ case 0x898:
+ offset = 2;
+ break;
+ case 0x890:
+ offset = 3;
+ break;
+ default:
+ /* We dont recognise the serial port */
+ return -ENODEV;
+ }
+ }
+ } else if (strcmp(name, "ch-a") == 0)
+ offset = 0;
+ else if (strcmp(name, "ch-b") == 0)
+ offset = 1;
+ else
+ return -ENODEV;
+ return add_preferred_console("ttyS", offset, NULL);
+}
+console_initcall(set_preferred_console);
+#endif /* CONFIG_SERIAL_CORE_CONSOLE */
+#endif /* CONFIG_PPC_MULTIPLATFORM */
+
+struct bi_record *find_bootinfo(void)
+{
+ struct bi_record *rec;
+
+ rec = (struct bi_record *)_ALIGN((ulong)__bss_start+(1<<20)-1,(1<<20));
+ if ( rec->tag != BI_FIRST ) {
+ /*
+ * This 0x10000 offset is a terrible hack but it will go away when
+ * we have the bootloader handle all the relocation and
+ * prom calls -- Cort
+ */
+ rec = (struct bi_record *)_ALIGN((ulong)__bss_start+0x10000+(1<<20)-1,(1<<20));
+ if ( rec->tag != BI_FIRST )
+ return NULL;
+ }
+ return rec;
+}
+
+void parse_bootinfo(struct bi_record *rec)
+{
+ if (rec == NULL || rec->tag != BI_FIRST)
+ return;
+ while (rec->tag != BI_LAST) {
+ ulong *data = rec->data;
+ switch (rec->tag) {
+ case BI_CMD_LINE:
+ strlcpy(cmd_line, (void *)data, sizeof(cmd_line));
+ break;
+ case BI_SYSMAP:
+ sysmap = (char *)((data[0] >= (KERNELBASE)) ? data[0] :
+ (data[0]+KERNELBASE));
+ sysmap_size = data[1];
+ break;
+#ifdef CONFIG_BLK_DEV_INITRD
+ case BI_INITRD:
+ initrd_start = data[0] + KERNELBASE;
+ initrd_end = data[0] + data[1] + KERNELBASE;
+ break;
+#endif /* CONFIG_BLK_DEV_INITRD */
+#ifdef CONFIG_PPC_MULTIPLATFORM
+ case BI_MACHTYPE:
+ _machine = data[0];
+ break;
+#endif
+ case BI_MEMSIZE:
+ boot_mem_size = data[0];
+ break;
+ }
+ rec = (struct bi_record *)((ulong)rec + rec->size);
+ }
+}
+
+/*
+ * Find out what kind of machine we're on and save any data we need
+ * from the early boot process (devtree is copied on pmac by prom_init()).
+ * This is called very early on the boot process, after a minimal
+ * MMU environment has been set up but before MMU_init is called.
+ */
+void __init
+machine_init(unsigned long r3, unsigned long r4, unsigned long r5,
+ unsigned long r6, unsigned long r7)
+{
+#ifdef CONFIG_CMDLINE
+ strlcpy(cmd_line, CONFIG_CMDLINE, sizeof(cmd_line));
+#endif /* CONFIG_CMDLINE */
+
+#ifdef CONFIG_6xx
+ ppc_md.power_save = ppc6xx_idle;
+#endif
+#ifdef CONFIG_POWER4
+ ppc_md.power_save = power4_idle;
+#endif
+
+ platform_init(r3, r4, r5, r6, r7);
+
+ if (ppc_md.progress)
+ ppc_md.progress("id mach(): done", 0x200);
+}
+
+/* Checks "l2cr=xxxx" command-line option */
+int __init ppc_setup_l2cr(char *str)
+{
+ if (cpu_has_feature(CPU_FTR_L2CR)) {
+ unsigned long val = simple_strtoul(str, NULL, 0);
+ printk(KERN_INFO "l2cr set to %lx\n", val);
+ _set_L2CR(0); /* force invalidate by disable cache */
+ _set_L2CR(val); /* and enable it */
+ }
+ return 1;
+}
+__setup("l2cr=", ppc_setup_l2cr);
+
+#ifdef CONFIG_GENERIC_NVRAM
+
+/* Generic nvram hooks used by drivers/char/gen_nvram.c */
+unsigned char nvram_read_byte(int addr)
+{
+ if (ppc_md.nvram_read_val)
+ return ppc_md.nvram_read_val(addr);
+ return 0xff;
+}
+EXPORT_SYMBOL(nvram_read_byte);
+
+void nvram_write_byte(unsigned char val, int addr)
+{
+ if (ppc_md.nvram_write_val)
+ ppc_md.nvram_write_val(addr, val);
+}
+EXPORT_SYMBOL(nvram_write_byte);
+
+void nvram_sync(void)
+{
+ if (ppc_md.nvram_sync)
+ ppc_md.nvram_sync();
+}
+EXPORT_SYMBOL(nvram_sync);
+
+#endif /* CONFIG_NVRAM */
+
+static struct cpu cpu_devices[NR_CPUS];
+
+int __init ppc_init(void)
+{
+ int i;
+
+ /* clear the progress line */
+ if ( ppc_md.progress ) ppc_md.progress(" ", 0xffff);
+
+ /* register CPU devices */
+ for (i = 0; i < NR_CPUS; i++)
+ if (cpu_possible(i))
+ register_cpu(&cpu_devices[i], i, NULL);
+
+ /* call platform init */
+ if (ppc_md.init != NULL) {
+ ppc_md.init();
+ }
+ return 0;
+}
+
+arch_initcall(ppc_init);
+
+/* Warning, IO base is not yet inited */
+void __init setup_arch(char **cmdline_p)
+{
+ extern char *klimit;
+ extern void do_init_bootmem(void);
+
+ /* so udelay does something sensible, assume <= 1000 bogomips */
+ loops_per_jiffy = 500000000 / HZ;
+
+#ifdef CONFIG_PPC_MULTIPLATFORM
+ /* This could be called "early setup arch", it must be done
+ * now because xmon need it
+ */
+ if (_machine == _MACH_Pmac)
+ pmac_feature_init(); /* New cool way */
+#endif
+
+#ifdef CONFIG_XMON
+ xmon_map_scc();
+ if (strstr(cmd_line, "xmon"))
+ xmon(NULL);
+#endif /* CONFIG_XMON */
+ if ( ppc_md.progress ) ppc_md.progress("setup_arch: enter", 0x3eab);
+
+#if defined(CONFIG_KGDB)
+ if (ppc_md.kgdb_map_scc)
+ ppc_md.kgdb_map_scc();
+ set_debug_traps();
+ if (strstr(cmd_line, "gdb")) {
+ if (ppc_md.progress)
+ ppc_md.progress("setup_arch: kgdb breakpoint", 0x4000);
+ printk("kgdb breakpoint activated\n");
+ breakpoint();
+ }
+#endif
+
+ /*
+ * Set cache line size based on type of cpu as a default.
+ * Systems with OF can look in the properties on the cpu node(s)
+ * for a possibly more accurate value.
+ */
+ if (cpu_has_feature(CPU_FTR_SPLIT_ID_CACHE)) {
+ dcache_bsize = cur_cpu_spec[0]->dcache_bsize;
+ icache_bsize = cur_cpu_spec[0]->icache_bsize;
+ ucache_bsize = 0;
+ } else
+ ucache_bsize = dcache_bsize = icache_bsize
+ = cur_cpu_spec[0]->dcache_bsize;
+
+ /* reboot on panic */
+ panic_timeout = 180;
+
+ init_mm.start_code = PAGE_OFFSET;
+ init_mm.end_code = (unsigned long) _etext;
+ init_mm.end_data = (unsigned long) _edata;
+ init_mm.brk = (unsigned long) klimit;
+
+ /* Save unparsed command line copy for /proc/cmdline */
+ strlcpy(saved_command_line, cmd_line, COMMAND_LINE_SIZE);
+ *cmdline_p = cmd_line;
+
+ /* set up the bootmem stuff with available memory */
+ do_init_bootmem();
+ if ( ppc_md.progress ) ppc_md.progress("setup_arch: bootmem", 0x3eab);
+
+#ifdef CONFIG_PPC_OCP
+ /* Initialize OCP device list */
+ ocp_early_init();
+ if ( ppc_md.progress ) ppc_md.progress("ocp: exit", 0x3eab);
+#endif
+
+#ifdef CONFIG_DUMMY_CONSOLE
+ conswitchp = &dummy_con;
+#endif
+
+ ppc_md.setup_arch();
+ if ( ppc_md.progress ) ppc_md.progress("arch: exit", 0x3eab);
+
+ paging_init();
+
+ /* this is for modules since _machine can be a define -- Cort */
+ ppc_md.ppc_machine = _machine;
+}
diff --git a/arch/ppc/kernel/signal.c b/arch/ppc/kernel/signal.c
new file mode 100644
index 0000000..9567d30
--- /dev/null
+++ b/arch/ppc/kernel/signal.c
@@ -0,0 +1,775 @@
+/*
+ * arch/ppc/kernel/signal.c
+ *
+ * PowerPC version
+ * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
+ *
+ * Derived from "arch/i386/kernel/signal.c"
+ * Copyright (C) 1991, 1992 Linus Torvalds
+ * 1997-11-28 Modified for POSIX.1b signals by Richard Henderson
+ *
+ * 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.
+ */
+
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/smp.h>
+#include <linux/smp_lock.h>
+#include <linux/kernel.h>
+#include <linux/signal.h>
+#include <linux/errno.h>
+#include <linux/wait.h>
+#include <linux/ptrace.h>
+#include <linux/unistd.h>
+#include <linux/stddef.h>
+#include <linux/elf.h>
+#include <linux/tty.h>
+#include <linux/binfmts.h>
+#include <linux/suspend.h>
+#include <asm/ucontext.h>
+#include <asm/uaccess.h>
+#include <asm/pgtable.h>
+#include <asm/cacheflush.h>
+
+#undef DEBUG_SIG
+
+#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
+
+extern void sigreturn_exit(struct pt_regs *);
+
+#define GP_REGS_SIZE min(sizeof(elf_gregset_t), sizeof(struct pt_regs))
+
+int do_signal(sigset_t *oldset, struct pt_regs *regs);
+
+/*
+ * Atomically swap in the new signal mask, and wait for a signal.
+ */
+int
+sys_sigsuspend(old_sigset_t mask, int p2, int p3, int p4, int p6, int p7,
+ struct pt_regs *regs)
+{
+ sigset_t saveset;
+
+ mask &= _BLOCKABLE;
+ spin_lock_irq(¤t->sighand->siglock);
+ saveset = current->blocked;
+ siginitset(¤t->blocked, mask);
+ recalc_sigpending();
+ spin_unlock_irq(¤t->sighand->siglock);
+
+ regs->result = -EINTR;
+ regs->gpr[3] = EINTR;
+ regs->ccr |= 0x10000000;
+ while (1) {
+ current->state = TASK_INTERRUPTIBLE;
+ schedule();
+ if (do_signal(&saveset, regs))
+ sigreturn_exit(regs);
+ }
+}
+
+int
+sys_rt_sigsuspend(sigset_t __user *unewset, size_t sigsetsize, int p3, int p4,
+ int p6, int p7, struct pt_regs *regs)
+{
+ sigset_t saveset, newset;
+
+ /* XXX: Don't preclude handling different sized sigset_t's. */
+ if (sigsetsize != sizeof(sigset_t))
+ return -EINVAL;
+
+ if (copy_from_user(&newset, unewset, sizeof(newset)))
+ return -EFAULT;
+ sigdelsetmask(&newset, ~_BLOCKABLE);
+
+ spin_lock_irq(¤t->sighand->siglock);
+ saveset = current->blocked;
+ current->blocked = newset;
+ recalc_sigpending();
+ spin_unlock_irq(¤t->sighand->siglock);
+
+ regs->result = -EINTR;
+ regs->gpr[3] = EINTR;
+ regs->ccr |= 0x10000000;
+ while (1) {
+ current->state = TASK_INTERRUPTIBLE;
+ schedule();
+ if (do_signal(&saveset, regs))
+ sigreturn_exit(regs);
+ }
+}
+
+
+int
+sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss, int r5,
+ int r6, int r7, int r8, struct pt_regs *regs)
+{
+ return do_sigaltstack(uss, uoss, regs->gpr[1]);
+}
+
+int
+sys_sigaction(int sig, const struct old_sigaction __user *act,
+ struct old_sigaction __user *oact)
+{
+ struct k_sigaction new_ka, old_ka;
+ int ret;
+
+ if (act) {
+ old_sigset_t mask;
+ if (!access_ok(VERIFY_READ, act, sizeof(*act)) ||
+ __get_user(new_ka.sa.sa_handler, &act->sa_handler) ||
+ __get_user(new_ka.sa.sa_restorer, &act->sa_restorer))
+ return -EFAULT;
+ __get_user(new_ka.sa.sa_flags, &act->sa_flags);
+ __get_user(mask, &act->sa_mask);
+ siginitset(&new_ka.sa.sa_mask, mask);
+ }
+
+ ret = do_sigaction(sig, (act? &new_ka: NULL), (oact? &old_ka: NULL));
+
+ if (!ret && oact) {
+ if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) ||
+ __put_user(old_ka.sa.sa_handler, &oact->sa_handler) ||
+ __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer))
+ return -EFAULT;
+ __put_user(old_ka.sa.sa_flags, &oact->sa_flags);
+ __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask);
+ }
+
+ return ret;
+}
+
+/*
+ * When we have signals to deliver, we set up on the
+ * user stack, going down from the original stack pointer:
+ * a sigregs struct
+ * a sigcontext struct
+ * a gap of __SIGNAL_FRAMESIZE bytes
+ *
+ * Each of these things must be a multiple of 16 bytes in size.
+ *
+ */
+struct sigregs {
+ struct mcontext mctx; /* all the register values */
+ /* Programs using the rs6000/xcoff abi can save up to 19 gp regs
+ and 18 fp regs below sp before decrementing it. */
+ int abigap[56];
+};
+
+/* We use the mc_pad field for the signal return trampoline. */
+#define tramp mc_pad
+
+/*
+ * When we have rt signals to deliver, we set up on the
+ * user stack, going down from the original stack pointer:
+ * one rt_sigframe struct (siginfo + ucontext + ABI gap)
+ * a gap of __SIGNAL_FRAMESIZE+16 bytes
+ * (the +16 is to get the siginfo and ucontext in the same
+ * positions as in older kernels).
+ *
+ * Each of these things must be a multiple of 16 bytes in size.
+ *
+ */
+struct rt_sigframe
+{
+ struct siginfo info;
+ struct ucontext uc;
+ /* Programs using the rs6000/xcoff abi can save up to 19 gp regs
+ and 18 fp regs below sp before decrementing it. */
+ int abigap[56];
+};
+
+/*
+ * Save the current user registers on the user stack.
+ * We only save the altivec/spe registers if the process has used
+ * altivec/spe instructions at some point.
+ */
+static int
+save_user_regs(struct pt_regs *regs, struct mcontext __user *frame, int sigret)
+{
+ /* save general and floating-point registers */
+ CHECK_FULL_REGS(regs);
+ preempt_disable();
+ if (regs->msr & MSR_FP)
+ giveup_fpu(current);
+#ifdef CONFIG_ALTIVEC
+ if (current->thread.used_vr && (regs->msr & MSR_VEC))
+ giveup_altivec(current);
+#endif /* CONFIG_ALTIVEC */
+#ifdef CONFIG_SPE
+ if (current->thread.used_spe && (regs->msr & MSR_SPE))
+ giveup_spe(current);
+#endif /* CONFIG_ALTIVEC */
+ preempt_enable();
+
+ if (__copy_to_user(&frame->mc_gregs, regs, GP_REGS_SIZE)
+ || __copy_to_user(&frame->mc_fregs, current->thread.fpr,
+ ELF_NFPREG * sizeof(double)))
+ return 1;
+
+ current->thread.fpscr = 0; /* turn off all fp exceptions */
+
+#ifdef CONFIG_ALTIVEC
+ /* save altivec registers */
+ if (current->thread.used_vr) {
+ if (__copy_to_user(&frame->mc_vregs, current->thread.vr,
+ ELF_NVRREG * sizeof(vector128)))
+ return 1;
+ /* set MSR_VEC in the saved MSR value to indicate that
+ frame->mc_vregs contains valid data */
+ if (__put_user(regs->msr | MSR_VEC, &frame->mc_gregs[PT_MSR]))
+ return 1;
+ }
+ /* else assert((regs->msr & MSR_VEC) == 0) */
+
+ /* We always copy to/from vrsave, it's 0 if we don't have or don't
+ * use altivec. Since VSCR only contains 32 bits saved in the least
+ * significant bits of a vector, we "cheat" and stuff VRSAVE in the
+ * most significant bits of that same vector. --BenH
+ */
+ if (__put_user(current->thread.vrsave, (u32 __user *)&frame->mc_vregs[32]))
+ return 1;
+#endif /* CONFIG_ALTIVEC */
+
+#ifdef CONFIG_SPE
+ /* save spe registers */
+ if (current->thread.used_spe) {
+ if (__copy_to_user(&frame->mc_vregs, current->thread.evr,
+ ELF_NEVRREG * sizeof(u32)))
+ return 1;
+ /* set MSR_SPE in the saved MSR value to indicate that
+ frame->mc_vregs contains valid data */
+ if (__put_user(regs->msr | MSR_SPE, &frame->mc_gregs[PT_MSR]))
+ return 1;
+ }
+ /* else assert((regs->msr & MSR_SPE) == 0) */
+
+ /* We always copy to/from spefscr */
+ if (__put_user(current->thread.spefscr, (u32 *)&frame->mc_vregs + ELF_NEVRREG))
+ return 1;
+#endif /* CONFIG_SPE */
+
+ if (sigret) {
+ /* Set up the sigreturn trampoline: li r0,sigret; sc */
+ if (__put_user(0x38000000UL + sigret, &frame->tramp[0])
+ || __put_user(0x44000002UL, &frame->tramp[1]))
+ return 1;
+ flush_icache_range((unsigned long) &frame->tramp[0],
+ (unsigned long) &frame->tramp[2]);
+ }
+
+ return 0;
+}
+
+/*
+ * Restore the current user register values from the user stack,
+ * (except for MSR).
+ */
+static int
+restore_user_regs(struct pt_regs *regs, struct mcontext __user *sr, int sig)
+{
+ unsigned long save_r2 = 0;
+#if defined(CONFIG_ALTIVEC) || defined(CONFIG_SPE)
+ unsigned long msr;
+#endif
+
+ /* backup/restore the TLS as we don't want it to be modified */
+ if (!sig)
+ save_r2 = regs->gpr[2];
+ /* copy up to but not including MSR */
+ if (__copy_from_user(regs, &sr->mc_gregs, PT_MSR * sizeof(elf_greg_t)))
+ return 1;
+ /* copy from orig_r3 (the word after the MSR) up to the end */
+ if (__copy_from_user(®s->orig_gpr3, &sr->mc_gregs[PT_ORIG_R3],
+ GP_REGS_SIZE - PT_ORIG_R3 * sizeof(elf_greg_t)))
+ return 1;
+ if (!sig)
+ regs->gpr[2] = save_r2;
+
+ /* force the process to reload the FP registers from
+ current->thread when it next does FP instructions */
+ regs->msr &= ~(MSR_FP | MSR_FE0 | MSR_FE1);
+ if (__copy_from_user(current->thread.fpr, &sr->mc_fregs,
+ sizeof(sr->mc_fregs)))
+ return 1;
+
+#ifdef CONFIG_ALTIVEC
+ /* force the process to reload the altivec registers from
+ current->thread when it next does altivec instructions */
+ regs->msr &= ~MSR_VEC;
+ if (!__get_user(msr, &sr->mc_gregs[PT_MSR]) && (msr & MSR_VEC) != 0) {
+ /* restore altivec registers from the stack */
+ if (__copy_from_user(current->thread.vr, &sr->mc_vregs,
+ sizeof(sr->mc_vregs)))
+ return 1;
+ } else if (current->thread.used_vr)
+ memset(¤t->thread.vr, 0, ELF_NVRREG * sizeof(vector128));
+
+ /* Always get VRSAVE back */
+ if (__get_user(current->thread.vrsave, (u32 __user *)&sr->mc_vregs[32]))
+ return 1;
+#endif /* CONFIG_ALTIVEC */
+
+#ifdef CONFIG_SPE
+ /* force the process to reload the spe registers from
+ current->thread when it next does spe instructions */
+ regs->msr &= ~MSR_SPE;
+ if (!__get_user(msr, &sr->mc_gregs[PT_MSR]) && (msr & MSR_SPE) != 0) {
+ /* restore spe registers from the stack */
+ if (__copy_from_user(current->thread.evr, &sr->mc_vregs,
+ ELF_NEVRREG * sizeof(u32)))
+ return 1;
+ } else if (current->thread.used_spe)
+ memset(¤t->thread.evr, 0, ELF_NEVRREG * sizeof(u32));
+
+ /* Always get SPEFSCR back */
+ if (__get_user(current->thread.spefscr, (u32 *)&sr->mc_vregs + ELF_NEVRREG))
+ return 1;
+#endif /* CONFIG_SPE */
+
+#ifndef CONFIG_SMP
+ preempt_disable();
+ if (last_task_used_math == current)
+ last_task_used_math = NULL;
+ if (last_task_used_altivec == current)
+ last_task_used_altivec = NULL;
+ if (last_task_used_spe == current)
+ last_task_used_spe = NULL;
+ preempt_enable();
+#endif
+ return 0;
+}
+
+/*
+ * Restore the user process's signal mask
+ */
+static void
+restore_sigmask(sigset_t *set)
+{
+ sigdelsetmask(set, ~_BLOCKABLE);
+ spin_lock_irq(¤t->sighand->siglock);
+ current->blocked = *set;
+ recalc_sigpending();
+ spin_unlock_irq(¤t->sighand->siglock);
+}
+
+/*
+ * Set up a signal frame for a "real-time" signal handler
+ * (one which gets siginfo).
+ */
+static void
+handle_rt_signal(unsigned long sig, struct k_sigaction *ka,
+ siginfo_t *info, sigset_t *oldset, struct pt_regs * regs,
+ unsigned long newsp)
+{
+ struct rt_sigframe __user *rt_sf;
+ struct mcontext __user *frame;
+ unsigned long origsp = newsp;
+
+ /* Set up Signal Frame */
+ /* Put a Real Time Context onto stack */
+ newsp -= sizeof(*rt_sf);
+ rt_sf = (struct rt_sigframe __user *) newsp;
+
+ /* create a stack frame for the caller of the handler */
+ newsp -= __SIGNAL_FRAMESIZE + 16;
+
+ if (!access_ok(VERIFY_WRITE, (void __user *) newsp, origsp - newsp))
+ goto badframe;
+
+ /* Put the siginfo & fill in most of the ucontext */
+ if (copy_siginfo_to_user(&rt_sf->info, info)
+ || __put_user(0, &rt_sf->uc.uc_flags)
+ || __put_user(0, &rt_sf->uc.uc_link)
+ || __put_user(current->sas_ss_sp, &rt_sf->uc.uc_stack.ss_sp)
+ || __put_user(sas_ss_flags(regs->gpr[1]),
+ &rt_sf->uc.uc_stack.ss_flags)
+ || __put_user(current->sas_ss_size, &rt_sf->uc.uc_stack.ss_size)
+ || __put_user(&rt_sf->uc.uc_mcontext, &rt_sf->uc.uc_regs)
+ || __copy_to_user(&rt_sf->uc.uc_sigmask, oldset, sizeof(*oldset)))
+ goto badframe;
+
+ /* Save user registers on the stack */
+ frame = &rt_sf->uc.uc_mcontext;
+ if (save_user_regs(regs, frame, __NR_rt_sigreturn))
+ goto badframe;
+
+ if (put_user(regs->gpr[1], (unsigned long __user *)newsp))
+ goto badframe;
+ regs->gpr[1] = newsp;
+ regs->gpr[3] = sig;
+ regs->gpr[4] = (unsigned long) &rt_sf->info;
+ regs->gpr[5] = (unsigned long) &rt_sf->uc;
+ regs->gpr[6] = (unsigned long) rt_sf;
+ regs->nip = (unsigned long) ka->sa.sa_handler;
+ regs->link = (unsigned long) frame->tramp;
+ regs->trap = 0;
+
+ return;
+
+badframe:
+#ifdef DEBUG_SIG
+ printk("badframe in handle_rt_signal, regs=%p frame=%p newsp=%lx\n",
+ regs, frame, newsp);
+#endif
+ force_sigsegv(sig, current);
+}
+
+static int do_setcontext(struct ucontext __user *ucp, struct pt_regs *regs, int sig)
+{
+ sigset_t set;
+ struct mcontext __user *mcp;
+
+ if (__copy_from_user(&set, &ucp->uc_sigmask, sizeof(set))
+ || __get_user(mcp, &ucp->uc_regs))
+ return -EFAULT;
+ restore_sigmask(&set);
+ if (restore_user_regs(regs, mcp, sig))
+ return -EFAULT;
+
+ return 0;
+}
+
+int sys_swapcontext(struct ucontext __user *old_ctx,
+ struct ucontext __user *new_ctx,
+ int ctx_size, int r6, int r7, int r8, struct pt_regs *regs)
+{
+ unsigned char tmp;
+
+ /* Context size is for future use. Right now, we only make sure
+ * we are passed something we understand
+ */
+ if (ctx_size < sizeof(struct ucontext))
+ return -EINVAL;
+
+ if (old_ctx != NULL) {
+ if (!access_ok(VERIFY_WRITE, old_ctx, sizeof(*old_ctx))
+ || save_user_regs(regs, &old_ctx->uc_mcontext, 0)
+ || __copy_to_user(&old_ctx->uc_sigmask,
+ ¤t->blocked, sizeof(sigset_t))
+ || __put_user(&old_ctx->uc_mcontext, &old_ctx->uc_regs))
+ return -EFAULT;
+ }
+ if (new_ctx == NULL)
+ return 0;
+ if (!access_ok(VERIFY_READ, new_ctx, sizeof(*new_ctx))
+ || __get_user(tmp, (u8 __user *) new_ctx)
+ || __get_user(tmp, (u8 __user *) (new_ctx + 1) - 1))
+ return -EFAULT;
+
+ /*
+ * If we get a fault copying the context into the kernel's
+ * image of the user's registers, we can't just return -EFAULT
+ * because the user's registers will be corrupted. For instance
+ * the NIP value may have been updated but not some of the
+ * other registers. Given that we have done the access_ok
+ * and successfully read the first and last bytes of the region
+ * above, this should only happen in an out-of-memory situation
+ * or if another thread unmaps the region containing the context.
+ * We kill the task with a SIGSEGV in this situation.
+ */
+ if (do_setcontext(new_ctx, regs, 0))
+ do_exit(SIGSEGV);
+ sigreturn_exit(regs);
+ /* doesn't actually return back to here */
+ return 0;
+}
+
+int sys_rt_sigreturn(int r3, int r4, int r5, int r6, int r7, int r8,
+ struct pt_regs *regs)
+{
+ struct rt_sigframe __user *rt_sf;
+
+ /* Always make any pending restarted system calls return -EINTR */
+ current_thread_info()->restart_block.fn = do_no_restart_syscall;
+
+ rt_sf = (struct rt_sigframe __user *)
+ (regs->gpr[1] + __SIGNAL_FRAMESIZE + 16);
+ if (!access_ok(VERIFY_READ, rt_sf, sizeof(struct rt_sigframe)))
+ goto bad;
+ if (do_setcontext(&rt_sf->uc, regs, 1))
+ goto bad;
+
+ /*
+ * It's not clear whether or why it is desirable to save the
+ * sigaltstack setting on signal delivery and restore it on
+ * signal return. But other architectures do this and we have
+ * always done it up until now so it is probably better not to
+ * change it. -- paulus
+ */
+ do_sigaltstack(&rt_sf->uc.uc_stack, NULL, regs->gpr[1]);
+
+ sigreturn_exit(regs); /* doesn't return here */
+ return 0;
+
+ bad:
+ force_sig(SIGSEGV, current);
+ return 0;
+}
+
+int sys_debug_setcontext(struct ucontext __user *ctx,
+ int ndbg, struct sig_dbg_op *dbg,
+ int r6, int r7, int r8,
+ struct pt_regs *regs)
+{
+ struct sig_dbg_op op;
+ int i;
+ unsigned long new_msr = regs->msr;
+#if defined(CONFIG_4xx) || defined(CONFIG_BOOKE)
+ unsigned long new_dbcr0 = current->thread.dbcr0;
+#endif
+
+ for (i=0; i<ndbg; i++) {
+ if (__copy_from_user(&op, dbg, sizeof(op)))
+ return -EFAULT;
+ switch (op.dbg_type) {
+ case SIG_DBG_SINGLE_STEPPING:
+#if defined(CONFIG_4xx) || defined(CONFIG_BOOKE)
+ if (op.dbg_value) {
+ new_msr |= MSR_DE;
+ new_dbcr0 |= (DBCR0_IDM | DBCR0_IC);
+ } else {
+ new_msr &= ~MSR_DE;
+ new_dbcr0 &= ~(DBCR0_IDM | DBCR0_IC);
+ }
+#else
+ if (op.dbg_value)
+ new_msr |= MSR_SE;
+ else
+ new_msr &= ~MSR_SE;
+#endif
+ break;
+ case SIG_DBG_BRANCH_TRACING:
+#if defined(CONFIG_4xx) || defined(CONFIG_BOOKE)
+ return -EINVAL;
+#else
+ if (op.dbg_value)
+ new_msr |= MSR_BE;
+ else
+ new_msr &= ~MSR_BE;
+#endif
+ break;
+
+ default:
+ return -EINVAL;
+ }
+ }
+
+ /* We wait until here to actually install the values in the
+ registers so if we fail in the above loop, it will not
+ affect the contents of these registers. After this point,
+ failure is a problem, anyway, and it's very unlikely unless
+ the user is really doing something wrong. */
+ regs->msr = new_msr;
+#if defined(CONFIG_4xx) || defined(CONFIG_BOOKE)
+ current->thread.dbcr0 = new_dbcr0;
+#endif
+
+ /*
+ * If we get a fault copying the context into the kernel's
+ * image of the user's registers, we can't just return -EFAULT
+ * because the user's registers will be corrupted. For instance
+ * the NIP value may have been updated but not some of the
+ * other registers. Given that we have done the access_ok
+ * and successfully read the first and last bytes of the region
+ * above, this should only happen in an out-of-memory situation
+ * or if another thread unmaps the region containing the context.
+ * We kill the task with a SIGSEGV in this situation.
+ */
+ if (do_setcontext(ctx, regs, 1)) {
+ force_sig(SIGSEGV, current);
+ goto out;
+ }
+
+ /*
+ * It's not clear whether or why it is desirable to save the
+ * sigaltstack setting on signal delivery and restore it on
+ * signal return. But other architectures do this and we have
+ * always done it up until now so it is probably better not to
+ * change it. -- paulus
+ */
+ do_sigaltstack(&ctx->uc_stack, NULL, regs->gpr[1]);
+
+ sigreturn_exit(regs);
+ /* doesn't actually return back to here */
+
+ out:
+ return 0;
+}
+
+/*
+ * OK, we're invoking a handler
+ */
+static void
+handle_signal(unsigned long sig, struct k_sigaction *ka,
+ siginfo_t *info, sigset_t *oldset, struct pt_regs * regs,
+ unsigned long newsp)
+{
+ struct sigcontext __user *sc;
+ struct sigregs __user *frame;
+ unsigned long origsp = newsp;
+
+ /* Set up Signal Frame */
+ newsp -= sizeof(struct sigregs);
+ frame = (struct sigregs __user *) newsp;
+
+ /* Put a sigcontext on the stack */
+ newsp -= sizeof(*sc);
+ sc = (struct sigcontext __user *) newsp;
+
+ /* create a stack frame for the caller of the handler */
+ newsp -= __SIGNAL_FRAMESIZE;
+
+ if (!access_ok(VERIFY_WRITE, (void __user *) newsp, origsp - newsp))
+ goto badframe;
+
+#if _NSIG != 64
+#error "Please adjust handle_signal()"
+#endif
+ if (__put_user((unsigned long) ka->sa.sa_handler, &sc->handler)
+ || __put_user(oldset->sig[0], &sc->oldmask)
+ || __put_user(oldset->sig[1], &sc->_unused[3])
+ || __put_user((struct pt_regs *)frame, &sc->regs)
+ || __put_user(sig, &sc->signal))
+ goto badframe;
+
+ if (save_user_regs(regs, &frame->mctx, __NR_sigreturn))
+ goto badframe;
+
+ if (put_user(regs->gpr[1], (unsigned long __user *)newsp))
+ goto badframe;
+ regs->gpr[1] = newsp;
+ regs->gpr[3] = sig;
+ regs->gpr[4] = (unsigned long) sc;
+ regs->nip = (unsigned long) ka->sa.sa_handler;
+ regs->link = (unsigned long) frame->mctx.tramp;
+ regs->trap = 0;
+
+ return;
+
+badframe:
+#ifdef DEBUG_SIG
+ printk("badframe in handle_signal, regs=%p frame=%p newsp=%lx\n",
+ regs, frame, newsp);
+#endif
+ force_sigsegv(sig, current);
+}
+
+/*
+ * Do a signal return; undo the signal stack.
+ */
+int sys_sigreturn(int r3, int r4, int r5, int r6, int r7, int r8,
+ struct pt_regs *regs)
+{
+ struct sigcontext __user *sc;
+ struct sigcontext sigctx;
+ struct mcontext __user *sr;
+ sigset_t set;
+
+ /* Always make any pending restarted system calls return -EINTR */
+ current_thread_info()->restart_block.fn = do_no_restart_syscall;
+
+ sc = (struct sigcontext __user *)(regs->gpr[1] + __SIGNAL_FRAMESIZE);
+ if (copy_from_user(&sigctx, sc, sizeof(sigctx)))
+ goto badframe;
+
+ set.sig[0] = sigctx.oldmask;
+ set.sig[1] = sigctx._unused[3];
+ restore_sigmask(&set);
+
+ sr = (struct mcontext __user *) sigctx.regs;
+ if (!access_ok(VERIFY_READ, sr, sizeof(*sr))
+ || restore_user_regs(regs, sr, 1))
+ goto badframe;
+
+ sigreturn_exit(regs); /* doesn't return */
+ return 0;
+
+badframe:
+ force_sig(SIGSEGV, current);
+ return 0;
+}
+
+/*
+ * Note that 'init' is a special process: it doesn't get signals it doesn't
+ * want to handle. Thus you cannot kill init even with a SIGKILL even by
+ * mistake.
+ */
+int do_signal(sigset_t *oldset, struct pt_regs *regs)
+{
+ siginfo_t info;
+ struct k_sigaction ka;
+ unsigned long frame, newsp;
+ int signr, ret;
+
+ if (current->flags & PF_FREEZE) {
+ refrigerator(PF_FREEZE);
+ signr = 0;
+ ret = regs->gpr[3];
+ if (!signal_pending(current))
+ goto no_signal;
+ }
+
+ if (!oldset)
+ oldset = ¤t->blocked;
+
+ newsp = frame = 0;
+
+ signr = get_signal_to_deliver(&info, &ka, regs, NULL);
+
+ if (TRAP(regs) == 0x0C00 /* System Call! */
+ && regs->ccr & 0x10000000 /* error signalled */
+ && ((ret = regs->gpr[3]) == ERESTARTSYS
+ || ret == ERESTARTNOHAND || ret == ERESTARTNOINTR
+ || ret == ERESTART_RESTARTBLOCK)) {
+
+ if (signr > 0
+ && (ret == ERESTARTNOHAND || ret == ERESTART_RESTARTBLOCK
+ || (ret == ERESTARTSYS
+ && !(ka.sa.sa_flags & SA_RESTART)))) {
+ /* make the system call return an EINTR error */
+ regs->result = -EINTR;
+ regs->gpr[3] = EINTR;
+ /* note that the cr0.SO bit is already set */
+ } else {
+no_signal:
+ regs->nip -= 4; /* Back up & retry system call */
+ regs->result = 0;
+ regs->trap = 0;
+ if (ret == ERESTART_RESTARTBLOCK)
+ regs->gpr[0] = __NR_restart_syscall;
+ else
+ regs->gpr[3] = regs->orig_gpr3;
+ }
+ }
+
+ if (signr == 0)
+ return 0; /* no signals delivered */
+
+ if ((ka.sa.sa_flags & SA_ONSTACK) && current->sas_ss_size
+ && !on_sig_stack(regs->gpr[1]))
+ newsp = current->sas_ss_sp + current->sas_ss_size;
+ else
+ newsp = regs->gpr[1];
+ newsp &= ~0xfUL;
+
+ /* Whee! Actually deliver the signal. */
+ if (ka.sa.sa_flags & SA_SIGINFO)
+ handle_rt_signal(signr, &ka, &info, oldset, regs, newsp);
+ else
+ handle_signal(signr, &ka, &info, oldset, regs, newsp);
+
+ if (!(ka.sa.sa_flags & SA_NODEFER)) {
+ spin_lock_irq(¤t->sighand->siglock);
+ sigorsets(¤t->blocked,¤t->blocked,&ka.sa.sa_mask);
+ sigaddset(¤t->blocked, signr);
+ recalc_sigpending();
+ spin_unlock_irq(¤t->sighand->siglock);
+ }
+
+ return 1;
+}
+
diff --git a/arch/ppc/kernel/smp-tbsync.c b/arch/ppc/kernel/smp-tbsync.c
new file mode 100644
index 0000000..2c9cd95
--- /dev/null
+++ b/arch/ppc/kernel/smp-tbsync.c
@@ -0,0 +1,181 @@
+/*
+ * Smp timebase synchronization for ppc.
+ *
+ * Copyright (C) 2003 Samuel Rydh (samuel@ibrium.se)
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/smp.h>
+#include <linux/unistd.h>
+#include <linux/init.h>
+#include <asm/atomic.h>
+#include <asm/smp.h>
+#include <asm/time.h>
+
+#define NUM_ITER 300
+
+enum {
+ kExit=0, kSetAndTest, kTest
+};
+
+static struct {
+ volatile int tbu;
+ volatile int tbl;
+ volatile int mark;
+ volatile int cmd;
+ volatile int handshake;
+ int filler[3];
+
+ volatile int ack;
+ int filler2[7];
+
+ volatile int race_result;
+} *tbsync;
+
+static volatile int running;
+
+static void __devinit
+enter_contest( int mark, int add )
+{
+ while( (int)(get_tbl() - mark) < 0 )
+ tbsync->race_result = add;
+}
+
+void __devinit
+smp_generic_take_timebase( void )
+{
+ int cmd, tbl, tbu;
+
+ local_irq_disable();
+ while( !running )
+ ;
+ rmb();
+
+ for( ;; ) {
+ tbsync->ack = 1;
+ while( !tbsync->handshake )
+ ;
+ rmb();
+
+ cmd = tbsync->cmd;
+ tbl = tbsync->tbl;
+ tbu = tbsync->tbu;
+ tbsync->ack = 0;
+ if( cmd == kExit )
+ return;
+
+ if( cmd == kSetAndTest ) {
+ while( tbsync->handshake )
+ ;
+ asm volatile ("mttbl %0" :: "r" (tbl) );
+ asm volatile ("mttbu %0" :: "r" (tbu) );
+ } else {
+ while( tbsync->handshake )
+ ;
+ }
+ enter_contest( tbsync->mark, -1 );
+ }
+ local_irq_enable();
+}
+
+static int __devinit
+start_contest( int cmd, int offset, int num )
+{
+ int i, tbu, tbl, mark, score=0;
+
+ tbsync->cmd = cmd;
+
+ local_irq_disable();
+ for( i=-3; i<num; ) {
+ tbl = get_tbl() + 400;
+ tbsync->tbu = tbu = get_tbu();
+ tbsync->tbl = tbl + offset;
+ tbsync->mark = mark = tbl + 400;
+
+ wmb();
+
+ tbsync->handshake = 1;
+ while( tbsync->ack )
+ ;
+
+ while( (int)(get_tbl() - tbl) <= 0 )
+ ;
+ tbsync->handshake = 0;
+ enter_contest( mark, 1 );
+
+ while( !tbsync->ack )
+ ;
+
+ if( tbsync->tbu != get_tbu() || ((tbsync->tbl ^ get_tbl()) & 0x80000000) )
+ continue;
+ if( i++ > 0 )
+ score += tbsync->race_result;
+ }
+ local_irq_enable();
+ return score;
+}
+
+void __devinit
+smp_generic_give_timebase( void )
+{
+ int i, score, score2, old, min=0, max=5000, offset=1000;
+
+ printk("Synchronizing timebase\n");
+
+ /* if this fails then this kernel won't work anyway... */
+ tbsync = kmalloc( sizeof(*tbsync), GFP_KERNEL );
+ memset( tbsync, 0, sizeof(*tbsync) );
+ mb();
+ running = 1;
+
+ while( !tbsync->ack )
+ ;
+
+ /* binary search */
+ for( old=-1 ; old != offset ; offset=(min+max)/2 ) {
+ score = start_contest( kSetAndTest, offset, NUM_ITER );
+
+ printk("score %d, offset %d\n", score, offset );
+
+ if( score > 0 )
+ max = offset;
+ else
+ min = offset;
+ old = offset;
+ }
+ score = start_contest( kSetAndTest, min, NUM_ITER );
+ score2 = start_contest( kSetAndTest, max, NUM_ITER );
+
+ printk( "Min %d (score %d), Max %d (score %d)\n", min, score, max, score2 );
+ score = abs( score );
+ score2 = abs( score2 );
+ offset = (score < score2) ? min : max;
+
+ /* guard against inaccurate mttb */
+ for( i=0; i<10; i++ ) {
+ start_contest( kSetAndTest, offset, NUM_ITER/10 );
+
+ if( (score2=start_contest(kTest, offset, NUM_ITER)) < 0 )
+ score2 = -score2;
+ if( score2 <= score || score2 < 20 )
+ break;
+ }
+ printk("Final offset: %d (%d/%d)\n", offset, score2, NUM_ITER );
+
+ /* exiting */
+ tbsync->cmd = kExit;
+ wmb();
+ tbsync->handshake = 1;
+ while( tbsync->ack )
+ ;
+ tbsync->handshake = 0;
+ kfree( tbsync );
+ tbsync = NULL;
+ running = 0;
+
+ /* all done */
+ smp_tb_synchronized = 1;
+}
diff --git a/arch/ppc/kernel/smp.c b/arch/ppc/kernel/smp.c
new file mode 100644
index 0000000..e70b587
--- /dev/null
+++ b/arch/ppc/kernel/smp.c
@@ -0,0 +1,399 @@
+/*
+ * Smp support for ppc.
+ *
+ * Written by Cort Dougan (cort@cs.nmt.edu) borrowing a great
+ * deal of code from the sparc and intel versions.
+ *
+ * Copyright (C) 1999 Cort Dougan <cort@cs.nmt.edu>
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/smp.h>
+#include <linux/smp_lock.h>
+#include <linux/interrupt.h>
+#include <linux/kernel_stat.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/spinlock.h>
+#include <linux/cache.h>
+
+#include <asm/ptrace.h>
+#include <asm/atomic.h>
+#include <asm/irq.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <asm/io.h>
+#include <asm/prom.h>
+#include <asm/smp.h>
+#include <asm/residual.h>
+#include <asm/time.h>
+#include <asm/thread_info.h>
+#include <asm/tlbflush.h>
+#include <asm/xmon.h>
+
+volatile int smp_commenced;
+int smp_tb_synchronized;
+struct cpuinfo_PPC cpu_data[NR_CPUS];
+struct klock_info_struct klock_info = { KLOCK_CLEAR, 0 };
+atomic_t ipi_recv;
+atomic_t ipi_sent;
+cpumask_t cpu_online_map;
+cpumask_t cpu_possible_map;
+int smp_hw_index[NR_CPUS];
+struct thread_info *secondary_ti;
+
+EXPORT_SYMBOL(cpu_online_map);
+EXPORT_SYMBOL(cpu_possible_map);
+
+/* SMP operations for this machine */
+static struct smp_ops_t *smp_ops;
+
+/* all cpu mappings are 1-1 -- Cort */
+volatile unsigned long cpu_callin_map[NR_CPUS];
+
+int start_secondary(void *);
+void smp_call_function_interrupt(void);
+static int __smp_call_function(void (*func) (void *info), void *info,
+ int wait, int target);
+
+/* Low level assembly function used to backup CPU 0 state */
+extern void __save_cpu_setup(void);
+
+/* Since OpenPIC has only 4 IPIs, we use slightly different message numbers.
+ *
+ * Make sure this matches openpic_request_IPIs in open_pic.c, or what shows up
+ * in /proc/interrupts will be wrong!!! --Troy */
+#define PPC_MSG_CALL_FUNCTION 0
+#define PPC_MSG_RESCHEDULE 1
+#define PPC_MSG_INVALIDATE_TLB 2
+#define PPC_MSG_XMON_BREAK 3
+
+static inline void
+smp_message_pass(int target, int msg, unsigned long data, int wait)
+{
+ if (smp_ops){
+ atomic_inc(&ipi_sent);
+ smp_ops->message_pass(target,msg,data,wait);
+ }
+}
+
+/*
+ * Common functions
+ */
+void smp_message_recv(int msg, struct pt_regs *regs)
+{
+ atomic_inc(&ipi_recv);
+
+ switch( msg ) {
+ case PPC_MSG_CALL_FUNCTION:
+ smp_call_function_interrupt();
+ break;
+ case PPC_MSG_RESCHEDULE:
+ set_need_resched();
+ break;
+ case PPC_MSG_INVALIDATE_TLB:
+ _tlbia();
+ break;
+#ifdef CONFIG_XMON
+ case PPC_MSG_XMON_BREAK:
+ xmon(regs);
+ break;
+#endif /* CONFIG_XMON */
+ default:
+ printk("SMP %d: smp_message_recv(): unknown msg %d\n",
+ smp_processor_id(), msg);
+ break;
+ }
+}
+
+/*
+ * 750's don't broadcast tlb invalidates so
+ * we have to emulate that behavior.
+ * -- Cort
+ */
+void smp_send_tlb_invalidate(int cpu)
+{
+ if ( PVR_VER(mfspr(SPRN_PVR)) == 8 )
+ smp_message_pass(MSG_ALL_BUT_SELF, PPC_MSG_INVALIDATE_TLB, 0, 0);
+}
+
+void smp_send_reschedule(int cpu)
+{
+ /*
+ * This is only used if `cpu' is running an idle task,
+ * so it will reschedule itself anyway...
+ *
+ * This isn't the case anymore since the other CPU could be
+ * sleeping and won't reschedule until the next interrupt (such
+ * as the timer).
+ * -- Cort
+ */
+ /* This is only used if `cpu' is running an idle task,
+ so it will reschedule itself anyway... */
+ smp_message_pass(cpu, PPC_MSG_RESCHEDULE, 0, 0);
+}
+
+#ifdef CONFIG_XMON
+void smp_send_xmon_break(int cpu)
+{
+ smp_message_pass(cpu, PPC_MSG_XMON_BREAK, 0, 0);
+}
+#endif /* CONFIG_XMON */
+
+static void stop_this_cpu(void *dummy)
+{
+ local_irq_disable();
+ while (1)
+ ;
+}
+
+void smp_send_stop(void)
+{
+ smp_call_function(stop_this_cpu, NULL, 1, 0);
+}
+
+/*
+ * Structure and data for smp_call_function(). This is designed to minimise
+ * static memory requirements. It also looks cleaner.
+ * Stolen from the i386 version.
+ */
+static DEFINE_SPINLOCK(call_lock);
+
+static struct call_data_struct {
+ void (*func) (void *info);
+ void *info;
+ atomic_t started;
+ atomic_t finished;
+ int wait;
+} *call_data;
+
+/*
+ * this function sends a 'generic call function' IPI to all other CPUs
+ * in the system.
+ */
+
+int smp_call_function(void (*func) (void *info), void *info, int nonatomic,
+ int wait)
+/*
+ * [SUMMARY] Run a function on all other CPUs.
+ * <func> The function to run. This must be fast and non-blocking.
+ * <info> An arbitrary pointer to pass to the function.
+ * <nonatomic> currently unused.
+ * <wait> If true, wait (atomically) until function has completed on other CPUs.
+ * [RETURNS] 0 on success, else a negative status code. Does not return until
+ * remote CPUs are nearly ready to execute <<func>> or are or have executed.
+ *
+ * You must not call this function with disabled interrupts or from a
+ * hardware interrupt handler or from a bottom half handler.
+ */
+{
+ /* FIXME: get cpu lock with hotplug cpus, or change this to
+ bitmask. --RR */
+ if (num_online_cpus() <= 1)
+ return 0;
+ /* Can deadlock when called with interrupts disabled */
+ WARN_ON(irqs_disabled());
+ return __smp_call_function(func, info, wait, MSG_ALL_BUT_SELF);
+}
+
+static int __smp_call_function(void (*func) (void *info), void *info,
+ int wait, int target)
+{
+ struct call_data_struct data;
+ int ret = -1;
+ int timeout;
+ int ncpus = 1;
+
+ if (target == MSG_ALL_BUT_SELF)
+ ncpus = num_online_cpus() - 1;
+ else if (target == MSG_ALL)
+ ncpus = num_online_cpus();
+
+ data.func = func;
+ data.info = info;
+ atomic_set(&data.started, 0);
+ data.wait = wait;
+ if (wait)
+ atomic_set(&data.finished, 0);
+
+ spin_lock(&call_lock);
+ call_data = &data;
+ /* Send a message to all other CPUs and wait for them to respond */
+ smp_message_pass(target, PPC_MSG_CALL_FUNCTION, 0, 0);
+
+ /* Wait for response */
+ timeout = 1000000;
+ while (atomic_read(&data.started) != ncpus) {
+ if (--timeout == 0) {
+ printk("smp_call_function on cpu %d: other cpus not responding (%d)\n",
+ smp_processor_id(), atomic_read(&data.started));
+ goto out;
+ }
+ barrier();
+ udelay(1);
+ }
+
+ if (wait) {
+ timeout = 1000000;
+ while (atomic_read(&data.finished) != ncpus) {
+ if (--timeout == 0) {
+ printk("smp_call_function on cpu %d: other cpus not finishing (%d/%d)\n",
+ smp_processor_id(), atomic_read(&data.finished), atomic_read(&data.started));
+ goto out;
+ }
+ barrier();
+ udelay(1);
+ }
+ }
+ ret = 0;
+
+ out:
+ spin_unlock(&call_lock);
+ return ret;
+}
+
+void smp_call_function_interrupt(void)
+{
+ void (*func) (void *info) = call_data->func;
+ void *info = call_data->info;
+ int wait = call_data->wait;
+
+ /*
+ * Notify initiating CPU that I've grabbed the data and am
+ * about to execute the function
+ */
+ atomic_inc(&call_data->started);
+ /*
+ * At this point the info structure may be out of scope unless wait==1
+ */
+ (*func)(info);
+ if (wait)
+ atomic_inc(&call_data->finished);
+}
+
+static void __devinit smp_store_cpu_info(int id)
+{
+ struct cpuinfo_PPC *c = &cpu_data[id];
+
+ /* assume bogomips are same for everything */
+ c->loops_per_jiffy = loops_per_jiffy;
+ c->pvr = mfspr(SPRN_PVR);
+}
+
+void __init smp_prepare_cpus(unsigned int max_cpus)
+{
+ int num_cpus, i;
+
+ /* Fixup boot cpu */
+ smp_store_cpu_info(smp_processor_id());
+ cpu_callin_map[smp_processor_id()] = 1;
+
+ smp_ops = ppc_md.smp_ops;
+ if (smp_ops == NULL) {
+ printk("SMP not supported on this machine.\n");
+ return;
+ }
+
+ /* Probe platform for CPUs: always linear. */
+ num_cpus = smp_ops->probe();
+ for (i = 0; i < num_cpus; ++i)
+ cpu_set(i, cpu_possible_map);
+
+ /* Backup CPU 0 state */
+ __save_cpu_setup();
+
+ if (smp_ops->space_timers)
+ smp_ops->space_timers(num_cpus);
+}
+
+void __devinit smp_prepare_boot_cpu(void)
+{
+ cpu_set(smp_processor_id(), cpu_online_map);
+ cpu_set(smp_processor_id(), cpu_possible_map);
+}
+
+int __init setup_profiling_timer(unsigned int multiplier)
+{
+ return 0;
+}
+
+/* Processor coming up starts here */
+int __devinit start_secondary(void *unused)
+{
+ int cpu;
+
+ atomic_inc(&init_mm.mm_count);
+ current->active_mm = &init_mm;
+
+ cpu = smp_processor_id();
+ smp_store_cpu_info(cpu);
+ set_dec(tb_ticks_per_jiffy);
+ cpu_callin_map[cpu] = 1;
+
+ printk("CPU %i done callin...\n", cpu);
+ smp_ops->setup_cpu(cpu);
+ printk("CPU %i done setup...\n", cpu);
+ local_irq_enable();
+ smp_ops->take_timebase();
+ printk("CPU %i done timebase take...\n", cpu);
+
+ cpu_idle();
+ return 0;
+}
+
+int __cpu_up(unsigned int cpu)
+{
+ struct task_struct *p;
+ char buf[32];
+ int c;
+
+ /* create a process for the processor */
+ /* only regs.msr is actually used, and 0 is OK for it */
+ p = fork_idle(cpu);
+ if (IS_ERR(p))
+ panic("failed fork for CPU %u: %li", cpu, PTR_ERR(p));
+ secondary_ti = p->thread_info;
+ p->thread_info->cpu = cpu;
+
+ /*
+ * There was a cache flush loop here to flush the cache
+ * to memory for the first 8MB of RAM. The cache flush
+ * has been pushed into the kick_cpu function for those
+ * platforms that need it.
+ */
+
+ /* wake up cpu */
+ smp_ops->kick_cpu(cpu);
+
+ /*
+ * wait to see if the cpu made a callin (is actually up).
+ * use this value that I found through experimentation.
+ * -- Cort
+ */
+ for (c = 1000; c && !cpu_callin_map[cpu]; c--)
+ udelay(100);
+
+ if (!cpu_callin_map[cpu]) {
+ sprintf(buf, "didn't find cpu %u", cpu);
+ if (ppc_md.progress) ppc_md.progress(buf, 0x360+cpu);
+ printk("Processor %u is stuck.\n", cpu);
+ return -ENOENT;
+ }
+
+ sprintf(buf, "found cpu %u", cpu);
+ if (ppc_md.progress) ppc_md.progress(buf, 0x350+cpu);
+ printk("Processor %d found.\n", cpu);
+
+ smp_ops->give_timebase();
+ cpu_set(cpu, cpu_online_map);
+ return 0;
+}
+
+void smp_cpus_done(unsigned int max_cpus)
+{
+ smp_ops->setup_cpu(0);
+}
diff --git a/arch/ppc/kernel/softemu8xx.c b/arch/ppc/kernel/softemu8xx.c
new file mode 100644
index 0000000..9bbb6bf
--- /dev/null
+++ b/arch/ppc/kernel/softemu8xx.c
@@ -0,0 +1,147 @@
+/*
+ * Software emulation of some PPC instructions for the 8xx core.
+ *
+ * Copyright (C) 1998 Dan Malek (dmalek@jlc.net)
+ *
+ * Software floating emuation for the MPC8xx processor. I did this mostly
+ * because it was easier than trying to get the libraries compiled for
+ * software floating point. The goal is still to get the libraries done,
+ * but I lost patience and needed some hacks to at least get init and
+ * shells running. The first problem is the setjmp/longjmp that save
+ * and restore the floating point registers.
+ *
+ * For this emulation, our working registers are found on the register
+ * save area.
+ */
+
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/stddef.h>
+#include <linux/unistd.h>
+#include <linux/ptrace.h>
+#include <linux/slab.h>
+#include <linux/user.h>
+#include <linux/a.out.h>
+#include <linux/interrupt.h>
+
+#include <asm/pgtable.h>
+#include <asm/uaccess.h>
+#include <asm/system.h>
+#include <asm/io.h>
+
+extern void
+print_8xx_pte(struct mm_struct *mm, unsigned long addr);
+extern int
+get_8xx_pte(struct mm_struct *mm, unsigned long addr);
+
+/* Eventually we may need a look-up table, but this works for now.
+*/
+#define LFS 48
+#define LFD 50
+#define LFDU 51
+#define STFD 54
+#define STFDU 55
+#define FMR 63
+
+/*
+ * We return 0 on success, 1 on unimplemented instruction, and EFAULT
+ * if a load/store faulted.
+ */
+int
+Soft_emulate_8xx(struct pt_regs *regs)
+{
+ uint inst, instword;
+ uint flreg, idxreg, disp;
+ uint retval;
+ signed short sdisp;
+ uint *ea, *ip;
+
+ retval = 0;
+
+ instword = *((uint *)regs->nip);
+ inst = instword >> 26;
+
+ flreg = (instword >> 21) & 0x1f;
+ idxreg = (instword >> 16) & 0x1f;
+ disp = instword & 0xffff;
+
+ ea = (uint *)(regs->gpr[idxreg] + disp);
+ ip = (uint *)¤t->thread.fpr[flreg];
+
+ switch ( inst )
+ {
+ case LFD:
+ /* this is a 16 bit quantity that is sign extended
+ * so use a signed short here -- Cort
+ */
+ sdisp = (instword & 0xffff);
+ ea = (uint *)(regs->gpr[idxreg] + sdisp);
+ if (copy_from_user(ip, ea, sizeof(double)))
+ retval = -EFAULT;
+ break;
+
+ case LFDU:
+ if (copy_from_user(ip, ea, sizeof(double)))
+ retval = -EFAULT;
+ else
+ regs->gpr[idxreg] = (uint)ea;
+ break;
+ case LFS:
+ sdisp = (instword & 0xffff);
+ ea = (uint *)(regs->gpr[idxreg] + sdisp);
+ if (copy_from_user(ip, ea, sizeof(float)))
+ retval = -EFAULT;
+ break;
+ case STFD:
+ /* this is a 16 bit quantity that is sign extended
+ * so use a signed short here -- Cort
+ */
+ sdisp = (instword & 0xffff);
+ ea = (uint *)(regs->gpr[idxreg] + sdisp);
+ if (copy_to_user(ea, ip, sizeof(double)))
+ retval = -EFAULT;
+ break;
+
+ case STFDU:
+ if (copy_to_user(ea, ip, sizeof(double)))
+ retval = -EFAULT;
+ else
+ regs->gpr[idxreg] = (uint)ea;
+ break;
+ case FMR:
+ /* assume this is a fp move -- Cort */
+ memcpy( ip, ¤t->thread.fpr[(instword>>11)&0x1f],
+ sizeof(double) );
+ break;
+ default:
+ retval = 1;
+ printk("Bad emulation %s/%d\n"
+ " NIP: %08lx instruction: %08x opcode: %x "
+ "A: %x B: %x C: %x code: %x rc: %x\n",
+ current->comm,current->pid,
+ regs->nip,
+ instword,inst,
+ (instword>>16)&0x1f,
+ (instword>>11)&0x1f,
+ (instword>>6)&0x1f,
+ (instword>>1)&0x3ff,
+ instword&1);
+ {
+ int pa;
+ print_8xx_pte(current->mm,regs->nip);
+ pa = get_8xx_pte(current->mm,regs->nip) & PAGE_MASK;
+ pa |= (regs->nip & ~PAGE_MASK);
+ pa = (unsigned long)__va(pa);
+ printk("Kernel VA for NIP %x ", pa);
+ print_8xx_pte(current->mm,pa);
+ }
+
+ }
+
+ if (retval == 0)
+ regs->nip += 4;
+ return(retval);
+}
+
diff --git a/arch/ppc/kernel/swsusp.S b/arch/ppc/kernel/swsusp.S
new file mode 100644
index 0000000..55148bb
--- /dev/null
+++ b/arch/ppc/kernel/swsusp.S
@@ -0,0 +1,349 @@
+#include <linux/config.h>
+#include <linux/threads.h>
+#include <asm/processor.h>
+#include <asm/page.h>
+#include <asm/cputable.h>
+#include <asm/thread_info.h>
+#include <asm/ppc_asm.h>
+#include <asm/offsets.h>
+
+
+/*
+ * Structure for storing CPU registers on the save area.
+ */
+#define SL_SP 0
+#define SL_PC 4
+#define SL_MSR 8
+#define SL_SDR1 0xc
+#define SL_SPRG0 0x10 /* 4 sprg's */
+#define SL_DBAT0 0x20
+#define SL_IBAT0 0x28
+#define SL_DBAT1 0x30
+#define SL_IBAT1 0x38
+#define SL_DBAT2 0x40
+#define SL_IBAT2 0x48
+#define SL_DBAT3 0x50
+#define SL_IBAT3 0x58
+#define SL_TB 0x60
+#define SL_R2 0x68
+#define SL_CR 0x6c
+#define SL_LR 0x70
+#define SL_R12 0x74 /* r12 to r31 */
+#define SL_SIZE (SL_R12 + 80)
+
+ .section .data
+ .align 5
+
+_GLOBAL(swsusp_save_area)
+ .space SL_SIZE
+
+
+ .section .text
+ .align 5
+
+_GLOBAL(swsusp_arch_suspend)
+
+ lis r11,swsusp_save_area@h
+ ori r11,r11,swsusp_save_area@l
+
+ mflr r0
+ stw r0,SL_LR(r11)
+ mfcr r0
+ stw r0,SL_CR(r11)
+ stw r1,SL_SP(r11)
+ stw r2,SL_R2(r11)
+ stmw r12,SL_R12(r11)
+
+ /* Save MSR & SDR1 */
+ mfmsr r4
+ stw r4,SL_MSR(r11)
+ mfsdr1 r4
+ stw r4,SL_SDR1(r11)
+
+ /* Get a stable timebase and save it */
+1: mftbu r4
+ stw r4,SL_TB(r11)
+ mftb r5
+ stw r5,SL_TB+4(r11)
+ mftbu r3
+ cmpw r3,r4
+ bne 1b
+
+ /* Save SPRGs */
+ mfsprg r4,0
+ stw r4,SL_SPRG0(r11)
+ mfsprg r4,1
+ stw r4,SL_SPRG0+4(r11)
+ mfsprg r4,2
+ stw r4,SL_SPRG0+8(r11)
+ mfsprg r4,3
+ stw r4,SL_SPRG0+12(r11)
+
+ /* Save BATs */
+ mfdbatu r4,0
+ stw r4,SL_DBAT0(r11)
+ mfdbatl r4,0
+ stw r4,SL_DBAT0+4(r11)
+ mfdbatu r4,1
+ stw r4,SL_DBAT1(r11)
+ mfdbatl r4,1
+ stw r4,SL_DBAT1+4(r11)
+ mfdbatu r4,2
+ stw r4,SL_DBAT2(r11)
+ mfdbatl r4,2
+ stw r4,SL_DBAT2+4(r11)
+ mfdbatu r4,3
+ stw r4,SL_DBAT3(r11)
+ mfdbatl r4,3
+ stw r4,SL_DBAT3+4(r11)
+ mfibatu r4,0
+ stw r4,SL_IBAT0(r11)
+ mfibatl r4,0
+ stw r4,SL_IBAT0+4(r11)
+ mfibatu r4,1
+ stw r4,SL_IBAT1(r11)
+ mfibatl r4,1
+ stw r4,SL_IBAT1+4(r11)
+ mfibatu r4,2
+ stw r4,SL_IBAT2(r11)
+ mfibatl r4,2
+ stw r4,SL_IBAT2+4(r11)
+ mfibatu r4,3
+ stw r4,SL_IBAT3(r11)
+ mfibatl r4,3
+ stw r4,SL_IBAT3+4(r11)
+
+#if 0
+ /* Backup various CPU config stuffs */
+ bl __save_cpu_setup
+#endif
+ /* Call the low level suspend stuff (we should probably have made
+ * a stackframe...
+ */
+ bl swsusp_save
+
+ /* Restore LR from the save area */
+ lis r11,swsusp_save_area@h
+ ori r11,r11,swsusp_save_area@l
+ lwz r0,SL_LR(r11)
+ mtlr r0
+
+ blr
+
+
+/* Resume code */
+_GLOBAL(swsusp_arch_resume)
+
+ /* Stop pending alitvec streams and memory accesses */
+BEGIN_FTR_SECTION
+ DSSALL
+END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
+ sync
+
+ /* Disable MSR:DR to make sure we don't take a TLB or
+ * hash miss during the copy, as our hash table will
+ * for a while be unuseable. For .text, we assume we are
+ * covered by a BAT. This works only for non-G5 at this
+ * point. G5 will need a better approach, possibly using
+ * a small temporary hash table filled with large mappings,
+ * disabling the MMU completely isn't a good option for
+ * performance reasons.
+ * (Note that 750's may have the same performance issue as
+ * the G5 in this case, we should investigate using moving
+ * BATs for these CPUs)
+ */
+ mfmsr r0
+ sync
+ rlwinm r0,r0,0,28,26 /* clear MSR_DR */
+ mtmsr r0
+ sync
+ isync
+
+ /* Load ptr the list of pages to copy in r3 */
+ lis r11,(pagedir_nosave - KERNELBASE)@h
+ ori r11,r11,pagedir_nosave@l
+ lwz r10,0(r11)
+
+ /* Copy the pages. This is a very basic implementation, to
+ * be replaced by something more cache efficient */
+1:
+ tophys(r3,r10)
+ li r0,256
+ mtctr r0
+ lwz r11,pbe_address(r3) /* source */
+ tophys(r5,r11)
+ lwz r10,pbe_orig_address(r3) /* destination */
+ tophys(r6,r10)
+2:
+ lwz r8,0(r5)
+ lwz r9,4(r5)
+ lwz r10,8(r5)
+ lwz r11,12(r5)
+ addi r5,r5,16
+ stw r8,0(r6)
+ stw r9,4(r6)
+ stw r10,8(r6)
+ stw r11,12(r6)
+ addi r6,r6,16
+ bdnz 2b
+ lwz r10,pbe_next(r3)
+ cmpwi 0,r10,0
+ bne 1b
+
+ /* Do a very simple cache flush/inval of the L1 to ensure
+ * coherency of the icache
+ */
+ lis r3,0x0002
+ mtctr r3
+ li r3, 0
+1:
+ lwz r0,0(r3)
+ addi r3,r3,0x0020
+ bdnz 1b
+ isync
+ sync
+
+ /* Now flush those cache lines */
+ lis r3,0x0002
+ mtctr r3
+ li r3, 0
+1:
+ dcbf 0,r3
+ addi r3,r3,0x0020
+ bdnz 1b
+ sync
+
+ /* Ok, we are now running with the kernel data of the old
+ * kernel fully restored. We can get to the save area
+ * easily now. As for the rest of the code, it assumes the
+ * loader kernel and the booted one are exactly identical
+ */
+ lis r11,swsusp_save_area@h
+ ori r11,r11,swsusp_save_area@l
+ tophys(r11,r11)
+
+#if 0
+ /* Restore various CPU config stuffs */
+ bl __restore_cpu_setup
+#endif
+ /* Restore the BATs, and SDR1. Then we can turn on the MMU.
+ * This is a bit hairy as we are running out of those BATs,
+ * but first, our code is probably in the icache, and we are
+ * writing the same value to the BAT, so that should be fine,
+ * though a better solution will have to be found long-term
+ */
+ lwz r4,SL_SDR1(r11)
+ mtsdr1 r4
+ lwz r4,SL_SPRG0(r11)
+ mtsprg 0,r4
+ lwz r4,SL_SPRG0+4(r11)
+ mtsprg 1,r4
+ lwz r4,SL_SPRG0+8(r11)
+ mtsprg 2,r4
+ lwz r4,SL_SPRG0+12(r11)
+ mtsprg 3,r4
+
+#if 0
+ lwz r4,SL_DBAT0(r11)
+ mtdbatu 0,r4
+ lwz r4,SL_DBAT0+4(r11)
+ mtdbatl 0,r4
+ lwz r4,SL_DBAT1(r11)
+ mtdbatu 1,r4
+ lwz r4,SL_DBAT1+4(r11)
+ mtdbatl 1,r4
+ lwz r4,SL_DBAT2(r11)
+ mtdbatu 2,r4
+ lwz r4,SL_DBAT2+4(r11)
+ mtdbatl 2,r4
+ lwz r4,SL_DBAT3(r11)
+ mtdbatu 3,r4
+ lwz r4,SL_DBAT3+4(r11)
+ mtdbatl 3,r4
+ lwz r4,SL_IBAT0(r11)
+ mtibatu 0,r4
+ lwz r4,SL_IBAT0+4(r11)
+ mtibatl 0,r4
+ lwz r4,SL_IBAT1(r11)
+ mtibatu 1,r4
+ lwz r4,SL_IBAT1+4(r11)
+ mtibatl 1,r4
+ lwz r4,SL_IBAT2(r11)
+ mtibatu 2,r4
+ lwz r4,SL_IBAT2+4(r11)
+ mtibatl 2,r4
+ lwz r4,SL_IBAT3(r11)
+ mtibatu 3,r4
+ lwz r4,SL_IBAT3+4(r11)
+ mtibatl 3,r4
+#endif
+
+BEGIN_FTR_SECTION
+ li r4,0
+ mtspr SPRN_DBAT4U,r4
+ mtspr SPRN_DBAT4L,r4
+ mtspr SPRN_DBAT5U,r4
+ mtspr SPRN_DBAT5L,r4
+ mtspr SPRN_DBAT6U,r4
+ mtspr SPRN_DBAT6L,r4
+ mtspr SPRN_DBAT7U,r4
+ mtspr SPRN_DBAT7L,r4
+ mtspr SPRN_IBAT4U,r4
+ mtspr SPRN_IBAT4L,r4
+ mtspr SPRN_IBAT5U,r4
+ mtspr SPRN_IBAT5L,r4
+ mtspr SPRN_IBAT6U,r4
+ mtspr SPRN_IBAT6L,r4
+ mtspr SPRN_IBAT7U,r4
+ mtspr SPRN_IBAT7L,r4
+END_FTR_SECTION_IFSET(CPU_FTR_HAS_HIGH_BATS)
+
+ /* Flush all TLBs */
+ lis r4,0x1000
+1: addic. r4,r4,-0x1000
+ tlbie r4
+ blt 1b
+ sync
+
+ /* restore the MSR and turn on the MMU */
+ lwz r3,SL_MSR(r11)
+ bl turn_on_mmu
+ tovirt(r11,r11)
+
+ /* Restore TB */
+ li r3,0
+ mttbl r3
+ lwz r3,SL_TB(r11)
+ lwz r4,SL_TB+4(r11)
+ mttbu r3
+ mttbl r4
+
+ /* Kick decrementer */
+ li r0,1
+ mtdec r0
+
+ /* Restore the callee-saved registers and return */
+ lwz r0,SL_CR(r11)
+ mtcr r0
+ lwz r2,SL_R2(r11)
+ lmw r12,SL_R12(r11)
+ lwz r1,SL_SP(r11)
+ lwz r0,SL_LR(r11)
+ mtlr r0
+
+ // XXX Note: we don't really need to call swsusp_resume
+
+ li r3,0
+ blr
+
+/* FIXME:This construct is actually not useful since we don't shut
+ * down the instruction MMU, we could just flip back MSR-DR on.
+ */
+turn_on_mmu:
+ mflr r4
+ mtsrr0 r4
+ mtsrr1 r3
+ sync
+ isync
+ rfi
+
diff --git a/arch/ppc/kernel/syscalls.c b/arch/ppc/kernel/syscalls.c
new file mode 100644
index 0000000..124313c
--- /dev/null
+++ b/arch/ppc/kernel/syscalls.c
@@ -0,0 +1,272 @@
+/*
+ * arch/ppc/kernel/sys_ppc.c
+ *
+ * PowerPC version
+ * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
+ *
+ * Derived from "arch/i386/kernel/sys_i386.c"
+ * Adapted from the i386 version by Gary Thomas
+ * Modified by Cort Dougan (cort@cs.nmt.edu)
+ * and Paul Mackerras (paulus@cs.anu.edu.au).
+ *
+ * This file contains various random system calls that
+ * have a non-standard calling sequence on the Linux/PPC
+ * platform.
+ *
+ * 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.
+ *
+ */
+
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/smp.h>
+#include <linux/smp_lock.h>
+#include <linux/sem.h>
+#include <linux/msg.h>
+#include <linux/shm.h>
+#include <linux/stat.h>
+#include <linux/syscalls.h>
+#include <linux/mman.h>
+#include <linux/sys.h>
+#include <linux/ipc.h>
+#include <linux/utsname.h>
+#include <linux/file.h>
+#include <linux/unistd.h>
+
+#include <asm/uaccess.h>
+#include <asm/ipc.h>
+#include <asm/semaphore.h>
+
+void
+check_bugs(void)
+{
+}
+
+/*
+ * sys_ipc() is the de-multiplexer for the SysV IPC calls..
+ *
+ * This is really horribly ugly.
+ */
+int
+sys_ipc (uint call, int first, int second, int third, void __user *ptr, long fifth)
+{
+ int version, ret;
+
+ version = call >> 16; /* hack for backward compatibility */
+ call &= 0xffff;
+
+ ret = -ENOSYS;
+ switch (call) {
+ case SEMOP:
+ ret = sys_semtimedop (first, (struct sembuf __user *)ptr,
+ second, NULL);
+ break;
+ case SEMTIMEDOP:
+ ret = sys_semtimedop (first, (struct sembuf __user *)ptr,
+ second, (const struct timespec __user *) fifth);
+ break;
+ case SEMGET:
+ ret = sys_semget (first, second, third);
+ break;
+ case SEMCTL: {
+ union semun fourth;
+
+ if (!ptr)
+ break;
+ if ((ret = access_ok(VERIFY_READ, ptr, sizeof(long)) ? 0 : -EFAULT)
+ || (ret = get_user(fourth.__pad, (void __user *__user *)ptr)))
+ break;
+ ret = sys_semctl (first, second, third, fourth);
+ break;
+ }
+ case MSGSND:
+ ret = sys_msgsnd (first, (struct msgbuf __user *) ptr, second, third);
+ break;
+ case MSGRCV:
+ switch (version) {
+ case 0: {
+ struct ipc_kludge tmp;
+
+ if (!ptr)
+ break;
+ if ((ret = access_ok(VERIFY_READ, ptr, sizeof(tmp)) ? 0 : -EFAULT)
+ || (ret = copy_from_user(&tmp,
+ (struct ipc_kludge __user *) ptr,
+ sizeof (tmp)) ? -EFAULT : 0))
+ break;
+ ret = sys_msgrcv (first, tmp.msgp, second, tmp.msgtyp,
+ third);
+ break;
+ }
+ default:
+ ret = sys_msgrcv (first, (struct msgbuf __user *) ptr,
+ second, fifth, third);
+ break;
+ }
+ break;
+ case MSGGET:
+ ret = sys_msgget ((key_t) first, second);
+ break;
+ case MSGCTL:
+ ret = sys_msgctl (first, second, (struct msqid_ds __user *) ptr);
+ break;
+ case SHMAT: {
+ ulong raddr;
+
+ if ((ret = access_ok(VERIFY_WRITE, (ulong __user *) third,
+ sizeof(ulong)) ? 0 : -EFAULT))
+ break;
+ ret = do_shmat (first, (char __user *) ptr, second, &raddr);
+ if (ret)
+ break;
+ ret = put_user (raddr, (ulong __user *) third);
+ break;
+ }
+ case SHMDT:
+ ret = sys_shmdt ((char __user *)ptr);
+ break;
+ case SHMGET:
+ ret = sys_shmget (first, second, third);
+ break;
+ case SHMCTL:
+ ret = sys_shmctl (first, second, (struct shmid_ds __user *) ptr);
+ break;
+ }
+
+ return ret;
+}
+
+/*
+ * sys_pipe() is the normal C calling standard for creating
+ * a pipe. It's not the way unix traditionally does this, though.
+ */
+int sys_pipe(int __user *fildes)
+{
+ int fd[2];
+ int error;
+
+ error = do_pipe(fd);
+ if (!error) {
+ if (copy_to_user(fildes, fd, 2*sizeof(int)))
+ error = -EFAULT;
+ }
+ return error;
+}
+
+static inline unsigned long
+do_mmap2(unsigned long addr, size_t len,
+ unsigned long prot, unsigned long flags,
+ unsigned long fd, unsigned long pgoff)
+{
+ struct file * file = NULL;
+ int ret = -EBADF;
+
+ flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
+ if (!(flags & MAP_ANONYMOUS)) {
+ if (!(file = fget(fd)))
+ goto out;
+ }
+
+ down_write(¤t->mm->mmap_sem);
+ ret = do_mmap_pgoff(file, addr, len, prot, flags, pgoff);
+ up_write(¤t->mm->mmap_sem);
+ if (file)
+ fput(file);
+out:
+ return ret;
+}
+
+unsigned long sys_mmap2(unsigned long addr, size_t len,
+ unsigned long prot, unsigned long flags,
+ unsigned long fd, unsigned long pgoff)
+{
+ return do_mmap2(addr, len, prot, flags, fd, pgoff);
+}
+
+unsigned long sys_mmap(unsigned long addr, size_t len,
+ unsigned long prot, unsigned long flags,
+ unsigned long fd, off_t offset)
+{
+ int err = -EINVAL;
+
+ if (offset & ~PAGE_MASK)
+ goto out;
+
+ err = do_mmap2(addr, len, prot, flags, fd, offset >> PAGE_SHIFT);
+out:
+ return err;
+}
+
+/*
+ * Due to some executables calling the wrong select we sometimes
+ * get wrong args. This determines how the args are being passed
+ * (a single ptr to them all args passed) then calls
+ * sys_select() with the appropriate args. -- Cort
+ */
+int
+ppc_select(int n, fd_set __user *inp, fd_set __user *outp, fd_set __user *exp, struct timeval __user *tvp)
+{
+ if ( (unsigned long)n >= 4096 )
+ {
+ unsigned long __user *buffer = (unsigned long __user *)n;
+ if (!access_ok(VERIFY_READ, buffer, 5*sizeof(unsigned long))
+ || __get_user(n, buffer)
+ || __get_user(inp, ((fd_set __user * __user *)(buffer+1)))
+ || __get_user(outp, ((fd_set __user * __user *)(buffer+2)))
+ || __get_user(exp, ((fd_set __user * __user *)(buffer+3)))
+ || __get_user(tvp, ((struct timeval __user * __user *)(buffer+4))))
+ return -EFAULT;
+ }
+ return sys_select(n, inp, outp, exp, tvp);
+}
+
+int sys_uname(struct old_utsname __user * name)
+{
+ int err = -EFAULT;
+
+ down_read(&uts_sem);
+ if (name && !copy_to_user(name, &system_utsname, sizeof (*name)))
+ err = 0;
+ up_read(&uts_sem);
+ return err;
+}
+
+int sys_olduname(struct oldold_utsname __user * name)
+{
+ int error;
+
+ if (!name)
+ return -EFAULT;
+ if (!access_ok(VERIFY_WRITE,name,sizeof(struct oldold_utsname)))
+ return -EFAULT;
+
+ down_read(&uts_sem);
+ error = __copy_to_user(&name->sysname,&system_utsname.sysname,__OLD_UTS_LEN);
+ error -= __put_user(0,name->sysname+__OLD_UTS_LEN);
+ error -= __copy_to_user(&name->nodename,&system_utsname.nodename,__OLD_UTS_LEN);
+ error -= __put_user(0,name->nodename+__OLD_UTS_LEN);
+ error -= __copy_to_user(&name->release,&system_utsname.release,__OLD_UTS_LEN);
+ error -= __put_user(0,name->release+__OLD_UTS_LEN);
+ error -= __copy_to_user(&name->version,&system_utsname.version,__OLD_UTS_LEN);
+ error -= __put_user(0,name->version+__OLD_UTS_LEN);
+ error -= __copy_to_user(&name->machine,&system_utsname.machine,__OLD_UTS_LEN);
+ error = __put_user(0,name->machine+__OLD_UTS_LEN);
+ up_read(&uts_sem);
+
+ error = error ? -EFAULT : 0;
+ return error;
+}
+
+/*
+ * We put the arguments in a different order so we only use 6
+ * registers for arguments, rather than 7 as sys_fadvise64_64 needs
+ * (because `offset' goes in r5/r6).
+ */
+long ppc_fadvise64_64(int fd, int advice, loff_t offset, loff_t len)
+{
+ return sys_fadvise64_64(fd, offset, len, advice);
+}
diff --git a/arch/ppc/kernel/temp.c b/arch/ppc/kernel/temp.c
new file mode 100644
index 0000000..fe8bb63
--- /dev/null
+++ b/arch/ppc/kernel/temp.c
@@ -0,0 +1,272 @@
+/*
+ * temp.c Thermal management for cpu's with Thermal Assist Units
+ *
+ * Written by Troy Benjegerdes <hozer@drgw.net>
+ *
+ * TODO:
+ * dynamic power management to limit peak CPU temp (using ICTC)
+ * calibration???
+ *
+ * Silly, crazy ideas: use cpu load (from scheduler) and ICTC to extend battery
+ * life in portables, and add a 'performance/watt' metric somewhere in /proc
+ */
+
+#include <linux/config.h>
+#include <linux/errno.h>
+#include <linux/jiffies.h>
+#include <linux/kernel.h>
+#include <linux/param.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/interrupt.h>
+#include <linux/init.h>
+
+#include <asm/segment.h>
+#include <asm/io.h>
+#include <asm/reg.h>
+#include <asm/nvram.h>
+#include <asm/cache.h>
+#include <asm/8xx_immap.h>
+#include <asm/machdep.h>
+
+static struct tau_temp
+{
+ int interrupts;
+ unsigned char low;
+ unsigned char high;
+ unsigned char grew;
+} tau[NR_CPUS];
+
+struct timer_list tau_timer;
+
+#undef DEBUG
+
+/* TODO: put these in a /proc interface, with some sanity checks, and maybe
+ * dynamic adjustment to minimize # of interrupts */
+/* configurable values for step size and how much to expand the window when
+ * we get an interrupt. These are based on the limit that was out of range */
+#define step_size 2 /* step size when temp goes out of range */
+#define window_expand 1 /* expand the window by this much */
+/* configurable values for shrinking the window */
+#define shrink_timer 2*HZ /* period between shrinking the window */
+#define min_window 2 /* minimum window size, degrees C */
+
+void set_thresholds(unsigned long cpu)
+{
+#ifdef CONFIG_TAU_INT
+ /*
+ * setup THRM1,
+ * threshold, valid bit, enable interrupts, interrupt when below threshold
+ */
+ mtspr(SPRN_THRM1, THRM1_THRES(tau[cpu].low) | THRM1_V | THRM1_TIE | THRM1_TID);
+
+ /* setup THRM2,
+ * threshold, valid bit, enable interrupts, interrupt when above threshhold
+ */
+ mtspr (SPRN_THRM2, THRM1_THRES(tau[cpu].high) | THRM1_V | THRM1_TIE);
+#else
+ /* same thing but don't enable interrupts */
+ mtspr(SPRN_THRM1, THRM1_THRES(tau[cpu].low) | THRM1_V | THRM1_TID);
+ mtspr(SPRN_THRM2, THRM1_THRES(tau[cpu].high) | THRM1_V);
+#endif
+}
+
+void TAUupdate(int cpu)
+{
+ unsigned thrm;
+
+#ifdef DEBUG
+ printk("TAUupdate ");
+#endif
+
+ /* if both thresholds are crossed, the step_sizes cancel out
+ * and the window winds up getting expanded twice. */
+ if((thrm = mfspr(SPRN_THRM1)) & THRM1_TIV){ /* is valid? */
+ if(thrm & THRM1_TIN){ /* crossed low threshold */
+ if (tau[cpu].low >= step_size){
+ tau[cpu].low -= step_size;
+ tau[cpu].high -= (step_size - window_expand);
+ }
+ tau[cpu].grew = 1;
+#ifdef DEBUG
+ printk("low threshold crossed ");
+#endif
+ }
+ }
+ if((thrm = mfspr(SPRN_THRM2)) & THRM1_TIV){ /* is valid? */
+ if(thrm & THRM1_TIN){ /* crossed high threshold */
+ if (tau[cpu].high <= 127-step_size){
+ tau[cpu].low += (step_size - window_expand);
+ tau[cpu].high += step_size;
+ }
+ tau[cpu].grew = 1;
+#ifdef DEBUG
+ printk("high threshold crossed ");
+#endif
+ }
+ }
+
+#ifdef DEBUG
+ printk("grew = %d\n", tau[cpu].grew);
+#endif
+
+#ifndef CONFIG_TAU_INT /* tau_timeout will do this if not using interrupts */
+ set_thresholds(cpu);
+#endif
+
+}
+
+#ifdef CONFIG_TAU_INT
+/*
+ * TAU interrupts - called when we have a thermal assist unit interrupt
+ * with interrupts disabled
+ */
+
+void TAUException(struct pt_regs * regs)
+{
+ int cpu = smp_processor_id();
+
+ irq_enter();
+ tau[cpu].interrupts++;
+
+ TAUupdate(cpu);
+
+ irq_exit();
+}
+#endif /* CONFIG_TAU_INT */
+
+static void tau_timeout(void * info)
+{
+ int cpu;
+ unsigned long flags;
+ int size;
+ int shrink;
+
+ /* disabling interrupts *should* be okay */
+ local_irq_save(flags);
+ cpu = smp_processor_id();
+
+#ifndef CONFIG_TAU_INT
+ TAUupdate(cpu);
+#endif
+
+ size = tau[cpu].high - tau[cpu].low;
+ if (size > min_window && ! tau[cpu].grew) {
+ /* do an exponential shrink of half the amount currently over size */
+ shrink = (2 + size - min_window) / 4;
+ if (shrink) {
+ tau[cpu].low += shrink;
+ tau[cpu].high -= shrink;
+ } else { /* size must have been min_window + 1 */
+ tau[cpu].low += 1;
+#if 1 /* debug */
+ if ((tau[cpu].high - tau[cpu].low) != min_window){
+ printk(KERN_ERR "temp.c: line %d, logic error\n", __LINE__);
+ }
+#endif
+ }
+ }
+
+ tau[cpu].grew = 0;
+
+ set_thresholds(cpu);
+
+ /*
+ * Do the enable every time, since otherwise a bunch of (relatively)
+ * complex sleep code needs to be added. One mtspr every time
+ * tau_timeout is called is probably not a big deal.
+ *
+ * Enable thermal sensor and set up sample interval timer
+ * need 20 us to do the compare.. until a nice 'cpu_speed' function
+ * call is implemented, just assume a 500 mhz clock. It doesn't really
+ * matter if we take too long for a compare since it's all interrupt
+ * driven anyway.
+ *
+ * use a extra long time.. (60 us @ 500 mhz)
+ */
+ mtspr(SPRN_THRM3, THRM3_SITV(500*60) | THRM3_E);
+
+ local_irq_restore(flags);
+}
+
+static void tau_timeout_smp(unsigned long unused)
+{
+
+ /* schedule ourselves to be run again */
+ mod_timer(&tau_timer, jiffies + shrink_timer) ;
+ on_each_cpu(tau_timeout, NULL, 1, 0);
+}
+
+/*
+ * setup the TAU
+ *
+ * Set things up to use THRM1 as a temperature lower bound, and THRM2 as an upper bound.
+ * Start off at zero
+ */
+
+int tau_initialized = 0;
+
+void __init TAU_init_smp(void * info)
+{
+ unsigned long cpu = smp_processor_id();
+
+ /* set these to a reasonable value and let the timer shrink the
+ * window */
+ tau[cpu].low = 5;
+ tau[cpu].high = 120;
+
+ set_thresholds(cpu);
+}
+
+int __init TAU_init(void)
+{
+ /* We assume in SMP that if one CPU has TAU support, they
+ * all have it --BenH
+ */
+ if (!cpu_has_feature(CPU_FTR_TAU)) {
+ printk("Thermal assist unit not available\n");
+ tau_initialized = 0;
+ return 1;
+ }
+
+
+ /* first, set up the window shrinking timer */
+ init_timer(&tau_timer);
+ tau_timer.function = tau_timeout_smp;
+ tau_timer.expires = jiffies + shrink_timer;
+ add_timer(&tau_timer);
+
+ on_each_cpu(TAU_init_smp, NULL, 1, 0);
+
+ printk("Thermal assist unit ");
+#ifdef CONFIG_TAU_INT
+ printk("using interrupts, ");
+#else
+ printk("using timers, ");
+#endif
+ printk("shrink_timer: %d jiffies\n", shrink_timer);
+ tau_initialized = 1;
+
+ return 0;
+}
+
+__initcall(TAU_init);
+
+/*
+ * return current temp
+ */
+
+u32 cpu_temp_both(unsigned long cpu)
+{
+ return ((tau[cpu].high << 16) | tau[cpu].low);
+}
+
+int cpu_temp(unsigned long cpu)
+{
+ return ((tau[cpu].high + tau[cpu].low) / 2);
+}
+
+int tau_interrupts(unsigned long cpu)
+{
+ return (tau[cpu].interrupts);
+}
diff --git a/arch/ppc/kernel/time.c b/arch/ppc/kernel/time.c
new file mode 100644
index 0000000..5072413
--- /dev/null
+++ b/arch/ppc/kernel/time.c
@@ -0,0 +1,447 @@
+/*
+ * Common time routines among all ppc machines.
+ *
+ * Written by Cort Dougan (cort@cs.nmt.edu) to merge
+ * Paul Mackerras' version and mine for PReP and Pmac.
+ * MPC8xx/MBX changes by Dan Malek (dmalek@jlc.net).
+ *
+ * First round of bugfixes by Gabriel Paubert (paubert@iram.es)
+ * to make clock more stable (2.4.0-test5). The only thing
+ * that this code assumes is that the timebases have been synchronized
+ * by firmware on SMP and are never stopped (never do sleep
+ * on SMP then, nap and doze are OK).
+ *
+ * TODO (not necessarily in this file):
+ * - improve precision and reproducibility of timebase frequency
+ * measurement at boot time.
+ * - get rid of xtime_lock for gettimeofday (generic kernel problem
+ * to be implemented on all architectures for SMP scalability and
+ * eventually implementing gettimeofday without entering the kernel).
+ * - put all time/clock related variables in a single structure
+ * to minimize number of cache lines touched by gettimeofday()
+ * - for astronomical applications: add a new function to get
+ * non ambiguous timestamps even around leap seconds. This needs
+ * a new timestamp format and a good name.
+ *
+ *
+ * The following comment is partially obsolete (at least the long wait
+ * is no more a valid reason):
+ * Since the MPC8xx has a programmable interrupt timer, I decided to
+ * use that rather than the decrementer. Two reasons: 1.) the clock
+ * frequency is low, causing 2.) a long wait in the timer interrupt
+ * while ((d = get_dec()) == dval)
+ * loop. The MPC8xx can be driven from a variety of input clocks,
+ * so a number of assumptions have been made here because the kernel
+ * parameter HZ is a constant. We assume (correctly, today :-) that
+ * the MPC8xx on the MBX board is driven from a 32.768 kHz crystal.
+ * This is then divided by 4, providing a 8192 Hz clock into the PIT.
+ * Since it is not possible to get a nice 100 Hz clock out of this, without
+ * creating a software PLL, I have set HZ to 128. -- Dan
+ *
+ * 1997-09-10 Updated NTP code according to technical memorandum Jan '96
+ * "A Kernel Model for Precision Timekeeping" by Dave Mills
+ */
+
+#include <linux/config.h>
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/param.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/timex.h>
+#include <linux/kernel_stat.h>
+#include <linux/mc146818rtc.h>
+#include <linux/time.h>
+#include <linux/init.h>
+#include <linux/profile.h>
+
+#include <asm/segment.h>
+#include <asm/io.h>
+#include <asm/nvram.h>
+#include <asm/cache.h>
+#include <asm/8xx_immap.h>
+#include <asm/machdep.h>
+
+#include <asm/time.h>
+
+/* XXX false sharing with below? */
+u64 jiffies_64 = INITIAL_JIFFIES;
+
+EXPORT_SYMBOL(jiffies_64);
+
+unsigned long disarm_decr[NR_CPUS];
+
+extern struct timezone sys_tz;
+
+/* keep track of when we need to update the rtc */
+time_t last_rtc_update;
+
+/* The decrementer counts down by 128 every 128ns on a 601. */
+#define DECREMENTER_COUNT_601 (1000000000 / HZ)
+
+unsigned tb_ticks_per_jiffy;
+unsigned tb_to_us;
+unsigned tb_last_stamp;
+unsigned long tb_to_ns_scale;
+
+extern unsigned long wall_jiffies;
+
+static long time_offset;
+
+DEFINE_SPINLOCK(rtc_lock);
+
+EXPORT_SYMBOL(rtc_lock);
+
+/* Timer interrupt helper function */
+static inline int tb_delta(unsigned *jiffy_stamp) {
+ int delta;
+ if (__USE_RTC()) {
+ delta = get_rtcl();
+ if (delta < *jiffy_stamp) *jiffy_stamp -= 1000000000;
+ delta -= *jiffy_stamp;
+ } else {
+ delta = get_tbl() - *jiffy_stamp;
+ }
+ return delta;
+}
+
+#ifdef CONFIG_SMP
+unsigned long profile_pc(struct pt_regs *regs)
+{
+ unsigned long pc = instruction_pointer(regs);
+
+ if (in_lock_functions(pc))
+ return regs->link;
+
+ return pc;
+}
+EXPORT_SYMBOL(profile_pc);
+#endif
+
+/*
+ * timer_interrupt - gets called when the decrementer overflows,
+ * with interrupts disabled.
+ * We set it up to overflow again in 1/HZ seconds.
+ */
+void timer_interrupt(struct pt_regs * regs)
+{
+ int next_dec;
+ unsigned long cpu = smp_processor_id();
+ unsigned jiffy_stamp = last_jiffy_stamp(cpu);
+ extern void do_IRQ(struct pt_regs *);
+
+ if (atomic_read(&ppc_n_lost_interrupts) != 0)
+ do_IRQ(regs);
+
+ irq_enter();
+
+ while ((next_dec = tb_ticks_per_jiffy - tb_delta(&jiffy_stamp)) <= 0) {
+ jiffy_stamp += tb_ticks_per_jiffy;
+
+ profile_tick(CPU_PROFILING, regs);
+ update_process_times(user_mode(regs));
+
+ if (smp_processor_id())
+ continue;
+
+ /* We are in an interrupt, no need to save/restore flags */
+ write_seqlock(&xtime_lock);
+ tb_last_stamp = jiffy_stamp;
+ do_timer(regs);
+
+ /*
+ * update the rtc when needed, this should be performed on the
+ * right fraction of a second. Half or full second ?
+ * Full second works on mk48t59 clocks, others need testing.
+ * Note that this update is basically only used through
+ * the adjtimex system calls. Setting the HW clock in
+ * any other way is a /dev/rtc and userland business.
+ * This is still wrong by -0.5/+1.5 jiffies because of the
+ * timer interrupt resolution and possible delay, but here we
+ * hit a quantization limit which can only be solved by higher
+ * resolution timers and decoupling time management from timer
+ * interrupts. This is also wrong on the clocks
+ * which require being written at the half second boundary.
+ * We should have an rtc call that only sets the minutes and
+ * seconds like on Intel to avoid problems with non UTC clocks.
+ */
+ if ( ppc_md.set_rtc_time && (time_status & STA_UNSYNC) == 0 &&
+ xtime.tv_sec - last_rtc_update >= 659 &&
+ abs((xtime.tv_nsec / 1000) - (1000000-1000000/HZ)) < 500000/HZ &&
+ jiffies - wall_jiffies == 1) {
+ if (ppc_md.set_rtc_time(xtime.tv_sec+1 + time_offset) == 0)
+ last_rtc_update = xtime.tv_sec+1;
+ else
+ /* Try again one minute later */
+ last_rtc_update += 60;
+ }
+ write_sequnlock(&xtime_lock);
+ }
+ if ( !disarm_decr[smp_processor_id()] )
+ set_dec(next_dec);
+ last_jiffy_stamp(cpu) = jiffy_stamp;
+
+ if (ppc_md.heartbeat && !ppc_md.heartbeat_count--)
+ ppc_md.heartbeat();
+
+ irq_exit();
+}
+
+/*
+ * This version of gettimeofday has microsecond resolution.
+ */
+void do_gettimeofday(struct timeval *tv)
+{
+ unsigned long flags;
+ unsigned long seq;
+ unsigned delta, lost_ticks, usec, sec;
+
+ do {
+ seq = read_seqbegin_irqsave(&xtime_lock, flags);
+ sec = xtime.tv_sec;
+ usec = (xtime.tv_nsec / 1000);
+ delta = tb_ticks_since(tb_last_stamp);
+#ifdef CONFIG_SMP
+ /* As long as timebases are not in sync, gettimeofday can only
+ * have jiffy resolution on SMP.
+ */
+ if (!smp_tb_synchronized)
+ delta = 0;
+#endif /* CONFIG_SMP */
+ lost_ticks = jiffies - wall_jiffies;
+ } while (read_seqretry_irqrestore(&xtime_lock, seq, flags));
+
+ usec += mulhwu(tb_to_us, tb_ticks_per_jiffy * lost_ticks + delta);
+ while (usec >= 1000000) {
+ sec++;
+ usec -= 1000000;
+ }
+ tv->tv_sec = sec;
+ tv->tv_usec = usec;
+}
+
+EXPORT_SYMBOL(do_gettimeofday);
+
+int do_settimeofday(struct timespec *tv)
+{
+ time_t wtm_sec, new_sec = tv->tv_sec;
+ long wtm_nsec, new_nsec = tv->tv_nsec;
+ unsigned long flags;
+ int tb_delta;
+
+ if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC)
+ return -EINVAL;
+
+ write_seqlock_irqsave(&xtime_lock, flags);
+ /* Updating the RTC is not the job of this code. If the time is
+ * stepped under NTP, the RTC will be update after STA_UNSYNC
+ * is cleared. Tool like clock/hwclock either copy the RTC
+ * to the system time, in which case there is no point in writing
+ * to the RTC again, or write to the RTC but then they don't call
+ * settimeofday to perform this operation. Note also that
+ * we don't touch the decrementer since:
+ * a) it would lose timer interrupt synchronization on SMP
+ * (if it is working one day)
+ * b) it could make one jiffy spuriously shorter or longer
+ * which would introduce another source of uncertainty potentially
+ * harmful to relatively short timers.
+ */
+
+ /* This works perfectly on SMP only if the tb are in sync but
+ * guarantees an error < 1 jiffy even if they are off by eons,
+ * still reasonable when gettimeofday resolution is 1 jiffy.
+ */
+ tb_delta = tb_ticks_since(last_jiffy_stamp(smp_processor_id()));
+ tb_delta += (jiffies - wall_jiffies) * tb_ticks_per_jiffy;
+
+ new_nsec -= 1000 * mulhwu(tb_to_us, tb_delta);
+
+ wtm_sec = wall_to_monotonic.tv_sec + (xtime.tv_sec - new_sec);
+ wtm_nsec = wall_to_monotonic.tv_nsec + (xtime.tv_nsec - new_nsec);
+
+ set_normalized_timespec(&xtime, new_sec, new_nsec);
+ set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec);
+
+ /* In case of a large backwards jump in time with NTP, we want the
+ * clock to be updated as soon as the PLL is again in lock.
+ */
+ last_rtc_update = new_sec - 658;
+
+ time_adjust = 0; /* stop active adjtime() */
+ time_status |= STA_UNSYNC;
+ time_state = TIME_ERROR; /* p. 24, (a) */
+ time_maxerror = NTP_PHASE_LIMIT;
+ time_esterror = NTP_PHASE_LIMIT;
+ write_sequnlock_irqrestore(&xtime_lock, flags);
+ clock_was_set();
+ return 0;
+}
+
+EXPORT_SYMBOL(do_settimeofday);
+
+/* This function is only called on the boot processor */
+void __init time_init(void)
+{
+ time_t sec, old_sec;
+ unsigned old_stamp, stamp, elapsed;
+
+ if (ppc_md.time_init != NULL)
+ time_offset = ppc_md.time_init();
+
+ if (__USE_RTC()) {
+ /* 601 processor: dec counts down by 128 every 128ns */
+ tb_ticks_per_jiffy = DECREMENTER_COUNT_601;
+ /* mulhwu_scale_factor(1000000000, 1000000) is 0x418937 */
+ tb_to_us = 0x418937;
+ } else {
+ ppc_md.calibrate_decr();
+ tb_to_ns_scale = mulhwu(tb_to_us, 1000 << 10);
+ }
+
+ /* Now that the decrementer is calibrated, it can be used in case the
+ * clock is stuck, but the fact that we have to handle the 601
+ * makes things more complex. Repeatedly read the RTC until the
+ * next second boundary to try to achieve some precision. If there
+ * is no RTC, we still need to set tb_last_stamp and
+ * last_jiffy_stamp(cpu 0) to the current stamp.
+ */
+ stamp = get_native_tbl();
+ if (ppc_md.get_rtc_time) {
+ sec = ppc_md.get_rtc_time();
+ elapsed = 0;
+ do {
+ old_stamp = stamp;
+ old_sec = sec;
+ stamp = get_native_tbl();
+ if (__USE_RTC() && stamp < old_stamp)
+ old_stamp -= 1000000000;
+ elapsed += stamp - old_stamp;
+ sec = ppc_md.get_rtc_time();
+ } while ( sec == old_sec && elapsed < 2*HZ*tb_ticks_per_jiffy);
+ if (sec==old_sec)
+ printk("Warning: real time clock seems stuck!\n");
+ xtime.tv_sec = sec;
+ xtime.tv_nsec = 0;
+ /* No update now, we just read the time from the RTC ! */
+ last_rtc_update = xtime.tv_sec;
+ }
+ last_jiffy_stamp(0) = tb_last_stamp = stamp;
+
+ /* Not exact, but the timer interrupt takes care of this */
+ set_dec(tb_ticks_per_jiffy);
+
+ /* If platform provided a timezone (pmac), we correct the time */
+ if (time_offset) {
+ sys_tz.tz_minuteswest = -time_offset / 60;
+ sys_tz.tz_dsttime = 0;
+ xtime.tv_sec -= time_offset;
+ }
+ set_normalized_timespec(&wall_to_monotonic,
+ -xtime.tv_sec, -xtime.tv_nsec);
+}
+
+#define FEBRUARY 2
+#define STARTOFTIME 1970
+#define SECDAY 86400L
+#define SECYR (SECDAY * 365)
+
+/*
+ * Note: this is wrong for 2100, but our signed 32-bit time_t will
+ * have overflowed long before that, so who cares. -- paulus
+ */
+#define leapyear(year) ((year) % 4 == 0)
+#define days_in_year(a) (leapyear(a) ? 366 : 365)
+#define days_in_month(a) (month_days[(a) - 1])
+
+static int month_days[12] = {
+ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
+};
+
+void to_tm(int tim, struct rtc_time * tm)
+{
+ register int i;
+ register long hms, day, gday;
+
+ gday = day = tim / SECDAY;
+ hms = tim % SECDAY;
+
+ /* Hours, minutes, seconds are easy */
+ tm->tm_hour = hms / 3600;
+ tm->tm_min = (hms % 3600) / 60;
+ tm->tm_sec = (hms % 3600) % 60;
+
+ /* Number of years in days */
+ for (i = STARTOFTIME; day >= days_in_year(i); i++)
+ day -= days_in_year(i);
+ tm->tm_year = i;
+
+ /* Number of months in days left */
+ if (leapyear(tm->tm_year))
+ days_in_month(FEBRUARY) = 29;
+ for (i = 1; day >= days_in_month(i); i++)
+ day -= days_in_month(i);
+ days_in_month(FEBRUARY) = 28;
+ tm->tm_mon = i;
+
+ /* Days are what is left over (+1) from all that. */
+ tm->tm_mday = day + 1;
+
+ /*
+ * Determine the day of week. Jan. 1, 1970 was a Thursday.
+ */
+ tm->tm_wday = (gday + 4) % 7;
+}
+
+/* Auxiliary function to compute scaling factors */
+/* Actually the choice of a timebase running at 1/4 the of the bus
+ * frequency giving resolution of a few tens of nanoseconds is quite nice.
+ * It makes this computation very precise (27-28 bits typically) which
+ * is optimistic considering the stability of most processor clock
+ * oscillators and the precision with which the timebase frequency
+ * is measured but does not harm.
+ */
+unsigned mulhwu_scale_factor(unsigned inscale, unsigned outscale) {
+ unsigned mlt=0, tmp, err;
+ /* No concern for performance, it's done once: use a stupid
+ * but safe and compact method to find the multiplier.
+ */
+ for (tmp = 1U<<31; tmp != 0; tmp >>= 1) {
+ if (mulhwu(inscale, mlt|tmp) < outscale) mlt|=tmp;
+ }
+ /* We might still be off by 1 for the best approximation.
+ * A side effect of this is that if outscale is too large
+ * the returned value will be zero.
+ * Many corner cases have been checked and seem to work,
+ * some might have been forgotten in the test however.
+ */
+ err = inscale*(mlt+1);
+ if (err <= inscale/2) mlt++;
+ return mlt;
+}
+
+unsigned long long sched_clock(void)
+{
+ unsigned long lo, hi, hi2;
+ unsigned long long tb;
+
+ if (!__USE_RTC()) {
+ do {
+ hi = get_tbu();
+ lo = get_tbl();
+ hi2 = get_tbu();
+ } while (hi2 != hi);
+ tb = ((unsigned long long) hi << 32) | lo;
+ tb = (tb * tb_to_ns_scale) >> 10;
+ } else {
+ do {
+ hi = get_rtcu();
+ lo = get_rtcl();
+ hi2 = get_rtcu();
+ } while (hi2 != hi);
+ tb = ((unsigned long long) hi) * 1000000000 + lo;
+ }
+ return tb;
+}
diff --git a/arch/ppc/kernel/traps.c b/arch/ppc/kernel/traps.c
new file mode 100644
index 0000000..ed5c7ac
--- /dev/null
+++ b/arch/ppc/kernel/traps.c
@@ -0,0 +1,886 @@
+/*
+ * arch/ppc/kernel/traps.c
+ *
+ * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
+ *
+ * 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.
+ *
+ * Modified by Cort Dougan (cort@cs.nmt.edu)
+ * and Paul Mackerras (paulus@cs.anu.edu.au)
+ */
+
+/*
+ * This file handles the architecture-dependent parts of hardware exceptions
+ */
+
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/stddef.h>
+#include <linux/unistd.h>
+#include <linux/ptrace.h>
+#include <linux/slab.h>
+#include <linux/user.h>
+#include <linux/a.out.h>
+#include <linux/interrupt.h>
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/prctl.h>
+
+#include <asm/pgtable.h>
+#include <asm/uaccess.h>
+#include <asm/system.h>
+#include <asm/io.h>
+#include <asm/reg.h>
+#include <asm/xmon.h>
+#ifdef CONFIG_PMAC_BACKLIGHT
+#include <asm/backlight.h>
+#endif
+#include <asm/perfmon.h>
+
+#ifdef CONFIG_XMON
+void (*debugger)(struct pt_regs *regs) = xmon;
+int (*debugger_bpt)(struct pt_regs *regs) = xmon_bpt;
+int (*debugger_sstep)(struct pt_regs *regs) = xmon_sstep;
+int (*debugger_iabr_match)(struct pt_regs *regs) = xmon_iabr_match;
+int (*debugger_dabr_match)(struct pt_regs *regs) = xmon_dabr_match;
+void (*debugger_fault_handler)(struct pt_regs *regs);
+#else
+#ifdef CONFIG_KGDB
+void (*debugger)(struct pt_regs *regs);
+int (*debugger_bpt)(struct pt_regs *regs);
+int (*debugger_sstep)(struct pt_regs *regs);
+int (*debugger_iabr_match)(struct pt_regs *regs);
+int (*debugger_dabr_match)(struct pt_regs *regs);
+void (*debugger_fault_handler)(struct pt_regs *regs);
+#else
+#define debugger(regs) do { } while (0)
+#define debugger_bpt(regs) 0
+#define debugger_sstep(regs) 0
+#define debugger_iabr_match(regs) 0
+#define debugger_dabr_match(regs) 0
+#define debugger_fault_handler ((void (*)(struct pt_regs *))0)
+#endif
+#endif
+
+/*
+ * Trap & Exception support
+ */
+
+DEFINE_SPINLOCK(die_lock);
+
+void die(const char * str, struct pt_regs * fp, long err)
+{
+ static int die_counter;
+ int nl = 0;
+ console_verbose();
+ spin_lock_irq(&die_lock);
+#ifdef CONFIG_PMAC_BACKLIGHT
+ set_backlight_enable(1);
+ set_backlight_level(BACKLIGHT_MAX);
+#endif
+ printk("Oops: %s, sig: %ld [#%d]\n", str, err, ++die_counter);
+#ifdef CONFIG_PREEMPT
+ printk("PREEMPT ");
+ nl = 1;
+#endif
+#ifdef CONFIG_SMP
+ printk("SMP NR_CPUS=%d ", NR_CPUS);
+ nl = 1;
+#endif
+ if (nl)
+ printk("\n");
+ show_regs(fp);
+ spin_unlock_irq(&die_lock);
+ /* do_exit() should take care of panic'ing from an interrupt
+ * context so we don't handle it here
+ */
+ do_exit(err);
+}
+
+void _exception(int signr, struct pt_regs *regs, int code, unsigned long addr)
+{
+ siginfo_t info;
+
+ if (!user_mode(regs)) {
+ debugger(regs);
+ die("Exception in kernel mode", regs, signr);
+ }
+ info.si_signo = signr;
+ info.si_errno = 0;
+ info.si_code = code;
+ info.si_addr = (void __user *) addr;
+ force_sig_info(signr, &info, current);
+}
+
+/*
+ * I/O accesses can cause machine checks on powermacs.
+ * Check if the NIP corresponds to the address of a sync
+ * instruction for which there is an entry in the exception
+ * table.
+ * Note that the 601 only takes a machine check on TEA
+ * (transfer error ack) signal assertion, and does not
+ * set any of the top 16 bits of SRR1.
+ * -- paulus.
+ */
+static inline int check_io_access(struct pt_regs *regs)
+{
+#ifdef CONFIG_PPC_PMAC
+ unsigned long msr = regs->msr;
+ const struct exception_table_entry *entry;
+ unsigned int *nip = (unsigned int *)regs->nip;
+
+ if (((msr & 0xffff0000) == 0 || (msr & (0x80000 | 0x40000)))
+ && (entry = search_exception_tables(regs->nip)) != NULL) {
+ /*
+ * Check that it's a sync instruction, or somewhere
+ * in the twi; isync; nop sequence that inb/inw/inl uses.
+ * As the address is in the exception table
+ * we should be able to read the instr there.
+ * For the debug message, we look at the preceding
+ * load or store.
+ */
+ if (*nip == 0x60000000) /* nop */
+ nip -= 2;
+ else if (*nip == 0x4c00012c) /* isync */
+ --nip;
+ if (*nip == 0x7c0004ac || (*nip >> 26) == 3) {
+ /* sync or twi */
+ unsigned int rb;
+
+ --nip;
+ rb = (*nip >> 11) & 0x1f;
+ printk(KERN_DEBUG "%s bad port %lx at %p\n",
+ (*nip & 0x100)? "OUT to": "IN from",
+ regs->gpr[rb] - _IO_BASE, nip);
+ regs->msr |= MSR_RI;
+ regs->nip = entry->fixup;
+ return 1;
+ }
+ }
+#endif /* CONFIG_PPC_PMAC */
+ return 0;
+}
+
+#if defined(CONFIG_4xx) || defined(CONFIG_BOOKE)
+/* On 4xx, the reason for the machine check or program exception
+ is in the ESR. */
+#define get_reason(regs) ((regs)->dsisr)
+#ifndef CONFIG_E500
+#define get_mc_reason(regs) ((regs)->dsisr)
+#else
+#define get_mc_reason(regs) (mfspr(SPRN_MCSR))
+#endif
+#define REASON_FP 0
+#define REASON_ILLEGAL ESR_PIL
+#define REASON_PRIVILEGED ESR_PPR
+#define REASON_TRAP ESR_PTR
+
+/* single-step stuff */
+#define single_stepping(regs) (current->thread.dbcr0 & DBCR0_IC)
+#define clear_single_step(regs) (current->thread.dbcr0 &= ~DBCR0_IC)
+
+#else
+/* On non-4xx, the reason for the machine check or program
+ exception is in the MSR. */
+#define get_reason(regs) ((regs)->msr)
+#define get_mc_reason(regs) ((regs)->msr)
+#define REASON_FP 0x100000
+#define REASON_ILLEGAL 0x80000
+#define REASON_PRIVILEGED 0x40000
+#define REASON_TRAP 0x20000
+
+#define single_stepping(regs) ((regs)->msr & MSR_SE)
+#define clear_single_step(regs) ((regs)->msr &= ~MSR_SE)
+#endif
+
+/*
+ * This is "fall-back" implementation for configurations
+ * which don't provide platform-specific machine check info
+ */
+void __attribute__ ((weak))
+platform_machine_check(struct pt_regs *regs)
+{
+}
+
+void MachineCheckException(struct pt_regs *regs)
+{
+ unsigned long reason = get_mc_reason(regs);
+
+ if (user_mode(regs)) {
+ regs->msr |= MSR_RI;
+ _exception(SIGBUS, regs, BUS_ADRERR, regs->nip);
+ return;
+ }
+
+#if defined(CONFIG_8xx) && defined(CONFIG_PCI)
+ /* the qspan pci read routines can cause machine checks -- Cort */
+ bad_page_fault(regs, regs->dar, SIGBUS);
+ return;
+#endif
+
+ if (debugger_fault_handler) {
+ debugger_fault_handler(regs);
+ regs->msr |= MSR_RI;
+ return;
+ }
+
+ if (check_io_access(regs))
+ return;
+
+#if defined(CONFIG_4xx) && !defined(CONFIG_440A)
+ if (reason & ESR_IMCP) {
+ printk("Instruction");
+ mtspr(SPRN_ESR, reason & ~ESR_IMCP);
+ } else
+ printk("Data");
+ printk(" machine check in kernel mode.\n");
+#elif defined(CONFIG_440A)
+ printk("Machine check in kernel mode.\n");
+ if (reason & ESR_IMCP){
+ printk("Instruction Synchronous Machine Check exception\n");
+ mtspr(SPRN_ESR, reason & ~ESR_IMCP);
+ }
+ else {
+ u32 mcsr = mfspr(SPRN_MCSR);
+ if (mcsr & MCSR_IB)
+ printk("Instruction Read PLB Error\n");
+ if (mcsr & MCSR_DRB)
+ printk("Data Read PLB Error\n");
+ if (mcsr & MCSR_DWB)
+ printk("Data Write PLB Error\n");
+ if (mcsr & MCSR_TLBP)
+ printk("TLB Parity Error\n");
+ if (mcsr & MCSR_ICP){
+ flush_instruction_cache();
+ printk("I-Cache Parity Error\n");
+ }
+ if (mcsr & MCSR_DCSP)
+ printk("D-Cache Search Parity Error\n");
+ if (mcsr & MCSR_DCFP)
+ printk("D-Cache Flush Parity Error\n");
+ if (mcsr & MCSR_IMPE)
+ printk("Machine Check exception is imprecise\n");
+
+ /* Clear MCSR */
+ mtspr(SPRN_MCSR, mcsr);
+ }
+#elif defined (CONFIG_E500)
+ printk("Machine check in kernel mode.\n");
+ printk("Caused by (from MCSR=%lx): ", reason);
+
+ if (reason & MCSR_MCP)
+ printk("Machine Check Signal\n");
+ if (reason & MCSR_ICPERR)
+ printk("Instruction Cache Parity Error\n");
+ if (reason & MCSR_DCP_PERR)
+ printk("Data Cache Push Parity Error\n");
+ if (reason & MCSR_DCPERR)
+ printk("Data Cache Parity Error\n");
+ if (reason & MCSR_GL_CI)
+ printk("Guarded Load or Cache-Inhibited stwcx.\n");
+ if (reason & MCSR_BUS_IAERR)
+ printk("Bus - Instruction Address Error\n");
+ if (reason & MCSR_BUS_RAERR)
+ printk("Bus - Read Address Error\n");
+ if (reason & MCSR_BUS_WAERR)
+ printk("Bus - Write Address Error\n");
+ if (reason & MCSR_BUS_IBERR)
+ printk("Bus - Instruction Data Error\n");
+ if (reason & MCSR_BUS_RBERR)
+ printk("Bus - Read Data Bus Error\n");
+ if (reason & MCSR_BUS_WBERR)
+ printk("Bus - Read Data Bus Error\n");
+ if (reason & MCSR_BUS_IPERR)
+ printk("Bus - Instruction Parity Error\n");
+ if (reason & MCSR_BUS_RPERR)
+ printk("Bus - Read Parity Error\n");
+#else /* !CONFIG_4xx && !CONFIG_E500 */
+ printk("Machine check in kernel mode.\n");
+ printk("Caused by (from SRR1=%lx): ", reason);
+ switch (reason & 0x601F0000) {
+ case 0x80000:
+ printk("Machine check signal\n");
+ break;
+ case 0: /* for 601 */
+ case 0x40000:
+ case 0x140000: /* 7450 MSS error and TEA */
+ printk("Transfer error ack signal\n");
+ break;
+ case 0x20000:
+ printk("Data parity error signal\n");
+ break;
+ case 0x10000:
+ printk("Address parity error signal\n");
+ break;
+ case 0x20000000:
+ printk("L1 Data Cache error\n");
+ break;
+ case 0x40000000:
+ printk("L1 Instruction Cache error\n");
+ break;
+ case 0x00100000:
+ printk("L2 data cache parity error\n");
+ break;
+ default:
+ printk("Unknown values in msr\n");
+ }
+#endif /* CONFIG_4xx */
+
+ /*
+ * Optional platform-provided routine to print out
+ * additional info, e.g. bus error registers.
+ */
+ platform_machine_check(regs);
+
+ debugger(regs);
+ die("machine check", regs, SIGBUS);
+}
+
+void SMIException(struct pt_regs *regs)
+{
+ debugger(regs);
+#if !(defined(CONFIG_XMON) || defined(CONFIG_KGDB))
+ show_regs(regs);
+ panic("System Management Interrupt");
+#endif
+}
+
+void UnknownException(struct pt_regs *regs)
+{
+ printk("Bad trap at PC: %lx, MSR: %lx, vector=%lx %s\n",
+ regs->nip, regs->msr, regs->trap, print_tainted());
+ _exception(SIGTRAP, regs, 0, 0);
+}
+
+void InstructionBreakpoint(struct pt_regs *regs)
+{
+ if (debugger_iabr_match(regs))
+ return;
+ _exception(SIGTRAP, regs, TRAP_BRKPT, 0);
+}
+
+void RunModeException(struct pt_regs *regs)
+{
+ _exception(SIGTRAP, regs, 0, 0);
+}
+
+/* Illegal instruction emulation support. Originally written to
+ * provide the PVR to user applications using the mfspr rd, PVR.
+ * Return non-zero if we can't emulate, or -EFAULT if the associated
+ * memory access caused an access fault. Return zero on success.
+ *
+ * There are a couple of ways to do this, either "decode" the instruction
+ * or directly match lots of bits. In this case, matching lots of
+ * bits is faster and easier.
+ *
+ */
+#define INST_MFSPR_PVR 0x7c1f42a6
+#define INST_MFSPR_PVR_MASK 0xfc1fffff
+
+#define INST_DCBA 0x7c0005ec
+#define INST_DCBA_MASK 0x7c0007fe
+
+#define INST_MCRXR 0x7c000400
+#define INST_MCRXR_MASK 0x7c0007fe
+
+#define INST_STRING 0x7c00042a
+#define INST_STRING_MASK 0x7c0007fe
+#define INST_STRING_GEN_MASK 0x7c00067e
+#define INST_LSWI 0x7c0004aa
+#define INST_LSWX 0x7c00042a
+#define INST_STSWI 0x7c0005aa
+#define INST_STSWX 0x7c00052a
+
+static int emulate_string_inst(struct pt_regs *regs, u32 instword)
+{
+ u8 rT = (instword >> 21) & 0x1f;
+ u8 rA = (instword >> 16) & 0x1f;
+ u8 NB_RB = (instword >> 11) & 0x1f;
+ u32 num_bytes;
+ u32 EA;
+ int pos = 0;
+
+ /* Early out if we are an invalid form of lswx */
+ if ((instword & INST_STRING_MASK) == INST_LSWX)
+ if ((rA >= rT) || (NB_RB >= rT) || (rT == rA) || (rT == NB_RB))
+ return -EINVAL;
+
+ /* Early out if we are an invalid form of lswi */
+ if ((instword & INST_STRING_MASK) == INST_LSWI)
+ if ((rA >= rT) || (rT == rA))
+ return -EINVAL;
+
+ EA = (rA == 0) ? 0 : regs->gpr[rA];
+
+ switch (instword & INST_STRING_MASK) {
+ case INST_LSWX:
+ case INST_STSWX:
+ EA += NB_RB;
+ num_bytes = regs->xer & 0x7f;
+ break;
+ case INST_LSWI:
+ case INST_STSWI:
+ num_bytes = (NB_RB == 0) ? 32 : NB_RB;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ while (num_bytes != 0)
+ {
+ u8 val;
+ u32 shift = 8 * (3 - (pos & 0x3));
+
+ switch ((instword & INST_STRING_MASK)) {
+ case INST_LSWX:
+ case INST_LSWI:
+ if (get_user(val, (u8 __user *)EA))
+ return -EFAULT;
+ /* first time updating this reg,
+ * zero it out */
+ if (pos == 0)
+ regs->gpr[rT] = 0;
+ regs->gpr[rT] |= val << shift;
+ break;
+ case INST_STSWI:
+ case INST_STSWX:
+ val = regs->gpr[rT] >> shift;
+ if (put_user(val, (u8 __user *)EA))
+ return -EFAULT;
+ break;
+ }
+ /* move EA to next address */
+ EA += 1;
+ num_bytes--;
+
+ /* manage our position within the register */
+ if (++pos == 4) {
+ pos = 0;
+ if (++rT == 32)
+ rT = 0;
+ }
+ }
+
+ return 0;
+}
+
+static int emulate_instruction(struct pt_regs *regs)
+{
+ u32 instword;
+ u32 rd;
+
+ if (!user_mode(regs))
+ return -EINVAL;
+ CHECK_FULL_REGS(regs);
+
+ if (get_user(instword, (u32 __user *)(regs->nip)))
+ return -EFAULT;
+
+ /* Emulate the mfspr rD, PVR.
+ */
+ if ((instword & INST_MFSPR_PVR_MASK) == INST_MFSPR_PVR) {
+ rd = (instword >> 21) & 0x1f;
+ regs->gpr[rd] = mfspr(SPRN_PVR);
+ return 0;
+ }
+
+ /* Emulating the dcba insn is just a no-op. */
+ if ((instword & INST_DCBA_MASK) == INST_DCBA)
+ return 0;
+
+ /* Emulate the mcrxr insn. */
+ if ((instword & INST_MCRXR_MASK) == INST_MCRXR) {
+ int shift = (instword >> 21) & 0x1c;
+ unsigned long msk = 0xf0000000UL >> shift;
+
+ regs->ccr = (regs->ccr & ~msk) | ((regs->xer >> shift) & msk);
+ regs->xer &= ~0xf0000000UL;
+ return 0;
+ }
+
+ /* Emulate load/store string insn. */
+ if ((instword & INST_STRING_GEN_MASK) == INST_STRING)
+ return emulate_string_inst(regs, instword);
+
+ return -EINVAL;
+}
+
+/*
+ * After we have successfully emulated an instruction, we have to
+ * check if the instruction was being single-stepped, and if so,
+ * pretend we got a single-step exception. This was pointed out
+ * by Kumar Gala. -- paulus
+ */
+static void emulate_single_step(struct pt_regs *regs)
+{
+ if (single_stepping(regs)) {
+ clear_single_step(regs);
+ _exception(SIGTRAP, regs, TRAP_TRACE, 0);
+ }
+}
+
+/*
+ * Look through the list of trap instructions that are used for BUG(),
+ * BUG_ON() and WARN_ON() and see if we hit one. At this point we know
+ * that the exception was caused by a trap instruction of some kind.
+ * Returns 1 if we should continue (i.e. it was a WARN_ON) or 0
+ * otherwise.
+ */
+extern struct bug_entry __start___bug_table[], __stop___bug_table[];
+
+#ifndef CONFIG_MODULES
+#define module_find_bug(x) NULL
+#endif
+
+static struct bug_entry *find_bug(unsigned long bugaddr)
+{
+ struct bug_entry *bug;
+
+ for (bug = __start___bug_table; bug < __stop___bug_table; ++bug)
+ if (bugaddr == bug->bug_addr)
+ return bug;
+ return module_find_bug(bugaddr);
+}
+
+int check_bug_trap(struct pt_regs *regs)
+{
+ struct bug_entry *bug;
+ unsigned long addr;
+
+ if (regs->msr & MSR_PR)
+ return 0; /* not in kernel */
+ addr = regs->nip; /* address of trap instruction */
+ if (addr < PAGE_OFFSET)
+ return 0;
+ bug = find_bug(regs->nip);
+ if (bug == NULL)
+ return 0;
+ if (bug->line & BUG_WARNING_TRAP) {
+ /* this is a WARN_ON rather than BUG/BUG_ON */
+#ifdef CONFIG_XMON
+ xmon_printf(KERN_ERR "Badness in %s at %s:%d\n",
+ bug->function, bug->file,
+ bug->line & ~BUG_WARNING_TRAP);
+#endif /* CONFIG_XMON */
+ printk(KERN_ERR "Badness in %s at %s:%d\n",
+ bug->function, bug->file,
+ bug->line & ~BUG_WARNING_TRAP);
+ dump_stack();
+ return 1;
+ }
+#ifdef CONFIG_XMON
+ xmon_printf(KERN_CRIT "kernel BUG in %s at %s:%d!\n",
+ bug->function, bug->file, bug->line);
+ xmon(regs);
+#endif /* CONFIG_XMON */
+ printk(KERN_CRIT "kernel BUG in %s at %s:%d!\n",
+ bug->function, bug->file, bug->line);
+
+ return 0;
+}
+
+void ProgramCheckException(struct pt_regs *regs)
+{
+ unsigned int reason = get_reason(regs);
+ extern int do_mathemu(struct pt_regs *regs);
+
+#ifdef CONFIG_MATH_EMULATION
+ /* (reason & REASON_ILLEGAL) would be the obvious thing here,
+ * but there seems to be a hardware bug on the 405GP (RevD)
+ * that means ESR is sometimes set incorrectly - either to
+ * ESR_DST (!?) or 0. In the process of chasing this with the
+ * hardware people - not sure if it can happen on any illegal
+ * instruction or only on FP instructions, whether there is a
+ * pattern to occurences etc. -dgibson 31/Mar/2003 */
+ if (!(reason & REASON_TRAP) && do_mathemu(regs) == 0) {
+ emulate_single_step(regs);
+ return;
+ }
+#endif /* CONFIG_MATH_EMULATION */
+
+ if (reason & REASON_FP) {
+ /* IEEE FP exception */
+ int code = 0;
+ u32 fpscr;
+
+ /* We must make sure the FP state is consistent with
+ * our MSR_FP in regs
+ */
+ preempt_disable();
+ if (regs->msr & MSR_FP)
+ giveup_fpu(current);
+ preempt_enable();
+
+ fpscr = current->thread.fpscr;
+ fpscr &= fpscr << 22; /* mask summary bits with enables */
+ if (fpscr & FPSCR_VX)
+ code = FPE_FLTINV;
+ else if (fpscr & FPSCR_OX)
+ code = FPE_FLTOVF;
+ else if (fpscr & FPSCR_UX)
+ code = FPE_FLTUND;
+ else if (fpscr & FPSCR_ZX)
+ code = FPE_FLTDIV;
+ else if (fpscr & FPSCR_XX)
+ code = FPE_FLTRES;
+ _exception(SIGFPE, regs, code, regs->nip);
+ return;
+ }
+
+ if (reason & REASON_TRAP) {
+ /* trap exception */
+ if (debugger_bpt(regs))
+ return;
+ if (check_bug_trap(regs)) {
+ regs->nip += 4;
+ return;
+ }
+ _exception(SIGTRAP, regs, TRAP_BRKPT, 0);
+ return;
+ }
+
+ /* Try to emulate it if we should. */
+ if (reason & (REASON_ILLEGAL | REASON_PRIVILEGED)) {
+ switch (emulate_instruction(regs)) {
+ case 0:
+ regs->nip += 4;
+ emulate_single_step(regs);
+ return;
+ case -EFAULT:
+ _exception(SIGSEGV, regs, SEGV_MAPERR, regs->nip);
+ return;
+ }
+ }
+
+ if (reason & REASON_PRIVILEGED)
+ _exception(SIGILL, regs, ILL_PRVOPC, regs->nip);
+ else
+ _exception(SIGILL, regs, ILL_ILLOPC, regs->nip);
+}
+
+void SingleStepException(struct pt_regs *regs)
+{
+ regs->msr &= ~(MSR_SE | MSR_BE); /* Turn off 'trace' bits */
+ if (debugger_sstep(regs))
+ return;
+ _exception(SIGTRAP, regs, TRAP_TRACE, 0);
+}
+
+void AlignmentException(struct pt_regs *regs)
+{
+ int fixed;
+
+ fixed = fix_alignment(regs);
+ if (fixed == 1) {
+ regs->nip += 4; /* skip over emulated instruction */
+ return;
+ }
+ if (fixed == -EFAULT) {
+ /* fixed == -EFAULT means the operand address was bad */
+ if (user_mode(regs))
+ _exception(SIGSEGV, regs, SEGV_ACCERR, regs->dar);
+ else
+ bad_page_fault(regs, regs->dar, SIGSEGV);
+ return;
+ }
+ _exception(SIGBUS, regs, BUS_ADRALN, regs->dar);
+}
+
+void StackOverflow(struct pt_regs *regs)
+{
+ printk(KERN_CRIT "Kernel stack overflow in process %p, r1=%lx\n",
+ current, regs->gpr[1]);
+ debugger(regs);
+ show_regs(regs);
+ panic("kernel stack overflow");
+}
+
+void nonrecoverable_exception(struct pt_regs *regs)
+{
+ printk(KERN_ERR "Non-recoverable exception at PC=%lx MSR=%lx\n",
+ regs->nip, regs->msr);
+ debugger(regs);
+ die("nonrecoverable exception", regs, SIGKILL);
+}
+
+void trace_syscall(struct pt_regs *regs)
+{
+ printk("Task: %p(%d), PC: %08lX/%08lX, Syscall: %3ld, Result: %s%ld %s\n",
+ current, current->pid, regs->nip, regs->link, regs->gpr[0],
+ regs->ccr&0x10000000?"Error=":"", regs->gpr[3], print_tainted());
+}
+
+#ifdef CONFIG_8xx
+void SoftwareEmulation(struct pt_regs *regs)
+{
+ extern int do_mathemu(struct pt_regs *);
+ extern int Soft_emulate_8xx(struct pt_regs *);
+ int errcode;
+
+ CHECK_FULL_REGS(regs);
+
+ if (!user_mode(regs)) {
+ debugger(regs);
+ die("Kernel Mode Software FPU Emulation", regs, SIGFPE);
+ }
+
+#ifdef CONFIG_MATH_EMULATION
+ errcode = do_mathemu(regs);
+#else
+ errcode = Soft_emulate_8xx(regs);
+#endif
+ if (errcode) {
+ if (errcode > 0)
+ _exception(SIGFPE, regs, 0, 0);
+ else if (errcode == -EFAULT)
+ _exception(SIGSEGV, regs, 0, 0);
+ else
+ _exception(SIGILL, regs, ILL_ILLOPC, regs->nip);
+ } else
+ emulate_single_step(regs);
+}
+#endif /* CONFIG_8xx */
+
+#if defined(CONFIG_40x) || defined(CONFIG_BOOKE)
+
+void DebugException(struct pt_regs *regs, unsigned long debug_status)
+{
+ if (debug_status & DBSR_IC) { /* instruction completion */
+ regs->msr &= ~MSR_DE;
+ if (user_mode(regs)) {
+ current->thread.dbcr0 &= ~DBCR0_IC;
+ } else {
+ /* Disable instruction completion */
+ mtspr(SPRN_DBCR0, mfspr(SPRN_DBCR0) & ~DBCR0_IC);
+ /* Clear the instruction completion event */
+ mtspr(SPRN_DBSR, DBSR_IC);
+ if (debugger_sstep(regs))
+ return;
+ }
+ _exception(SIGTRAP, regs, TRAP_TRACE, 0);
+ }
+}
+#endif /* CONFIG_4xx || CONFIG_BOOKE */
+
+#if !defined(CONFIG_TAU_INT)
+void TAUException(struct pt_regs *regs)
+{
+ printk("TAU trap at PC: %lx, MSR: %lx, vector=%lx %s\n",
+ regs->nip, regs->msr, regs->trap, print_tainted());
+}
+#endif /* CONFIG_INT_TAU */
+
+void AltivecUnavailException(struct pt_regs *regs)
+{
+ static int kernel_altivec_count;
+
+#ifndef CONFIG_ALTIVEC
+ if (user_mode(regs)) {
+ /* A user program has executed an altivec instruction,
+ but this kernel doesn't support altivec. */
+ _exception(SIGILL, regs, ILL_ILLOPC, regs->nip);
+ return;
+ }
+#endif
+ /* The kernel has executed an altivec instruction without
+ first enabling altivec. Whinge but let it do it. */
+ if (++kernel_altivec_count < 10)
+ printk(KERN_ERR "AltiVec used in kernel (task=%p, pc=%lx)\n",
+ current, regs->nip);
+ regs->msr |= MSR_VEC;
+}
+
+#ifdef CONFIG_ALTIVEC
+void AltivecAssistException(struct pt_regs *regs)
+{
+ int err;
+
+ preempt_disable();
+ if (regs->msr & MSR_VEC)
+ giveup_altivec(current);
+ preempt_enable();
+
+ err = emulate_altivec(regs);
+ if (err == 0) {
+ regs->nip += 4; /* skip emulated instruction */
+ emulate_single_step(regs);
+ return;
+ }
+
+ if (err == -EFAULT) {
+ /* got an error reading the instruction */
+ _exception(SIGSEGV, regs, SEGV_ACCERR, regs->nip);
+ } else {
+ /* didn't recognize the instruction */
+ /* XXX quick hack for now: set the non-Java bit in the VSCR */
+ printk(KERN_ERR "unrecognized altivec instruction "
+ "in %s at %lx\n", current->comm, regs->nip);
+ current->thread.vscr.u[3] |= 0x10000;
+ }
+}
+#endif /* CONFIG_ALTIVEC */
+
+void PerformanceMonitorException(struct pt_regs *regs)
+{
+ perf_irq(regs);
+}
+
+#ifdef CONFIG_FSL_BOOKE
+void CacheLockingException(struct pt_regs *regs, unsigned long address,
+ unsigned long error_code)
+{
+ /* We treat cache locking instructions from the user
+ * as priv ops, in the future we could try to do
+ * something smarter
+ */
+ if (error_code & (ESR_DLK|ESR_ILK))
+ _exception(SIGILL, regs, ILL_PRVOPC, regs->nip);
+ return;
+}
+#endif /* CONFIG_FSL_BOOKE */
+
+#ifdef CONFIG_SPE
+void SPEFloatingPointException(struct pt_regs *regs)
+{
+ unsigned long spefscr;
+ int fpexc_mode;
+ int code = 0;
+
+ spefscr = current->thread.spefscr;
+ fpexc_mode = current->thread.fpexc_mode;
+
+ /* Hardware does not neccessarily set sticky
+ * underflow/overflow/invalid flags */
+ if ((spefscr & SPEFSCR_FOVF) && (fpexc_mode & PR_FP_EXC_OVF)) {
+ code = FPE_FLTOVF;
+ spefscr |= SPEFSCR_FOVFS;
+ }
+ else if ((spefscr & SPEFSCR_FUNF) && (fpexc_mode & PR_FP_EXC_UND)) {
+ code = FPE_FLTUND;
+ spefscr |= SPEFSCR_FUNFS;
+ }
+ else if ((spefscr & SPEFSCR_FDBZ) && (fpexc_mode & PR_FP_EXC_DIV))
+ code = FPE_FLTDIV;
+ else if ((spefscr & SPEFSCR_FINV) && (fpexc_mode & PR_FP_EXC_INV)) {
+ code = FPE_FLTINV;
+ spefscr |= SPEFSCR_FINVS;
+ }
+ else if ((spefscr & (SPEFSCR_FG | SPEFSCR_FX)) && (fpexc_mode & PR_FP_EXC_RES))
+ code = FPE_FLTRES;
+
+ current->thread.spefscr = spefscr;
+
+ _exception(SIGFPE, regs, code, regs->nip);
+ return;
+}
+#endif
+
+void __init trap_init(void)
+{
+}
diff --git a/arch/ppc/kernel/vecemu.c b/arch/ppc/kernel/vecemu.c
new file mode 100644
index 0000000..604d094
--- /dev/null
+++ b/arch/ppc/kernel/vecemu.c
@@ -0,0 +1,345 @@
+/*
+ * Routines to emulate some Altivec/VMX instructions, specifically
+ * those that can trap when given denormalized operands in Java mode.
+ */
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <asm/ptrace.h>
+#include <asm/processor.h>
+#include <asm/uaccess.h>
+
+/* Functions in vector.S */
+extern void vaddfp(vector128 *dst, vector128 *a, vector128 *b);
+extern void vsubfp(vector128 *dst, vector128 *a, vector128 *b);
+extern void vmaddfp(vector128 *dst, vector128 *a, vector128 *b, vector128 *c);
+extern void vnmsubfp(vector128 *dst, vector128 *a, vector128 *b, vector128 *c);
+extern void vrefp(vector128 *dst, vector128 *src);
+extern void vrsqrtefp(vector128 *dst, vector128 *src);
+extern void vexptep(vector128 *dst, vector128 *src);
+
+static unsigned int exp2s[8] = {
+ 0x800000,
+ 0x8b95c2,
+ 0x9837f0,
+ 0xa5fed7,
+ 0xb504f3,
+ 0xc5672a,
+ 0xd744fd,
+ 0xeac0c7
+};
+
+/*
+ * Computes an estimate of 2^x. The `s' argument is the 32-bit
+ * single-precision floating-point representation of x.
+ */
+static unsigned int eexp2(unsigned int s)
+{
+ int exp, pwr;
+ unsigned int mant, frac;
+
+ /* extract exponent field from input */
+ exp = ((s >> 23) & 0xff) - 127;
+ if (exp > 7) {
+ /* check for NaN input */
+ if (exp == 128 && (s & 0x7fffff) != 0)
+ return s | 0x400000; /* return QNaN */
+ /* 2^-big = 0, 2^+big = +Inf */
+ return (s & 0x80000000)? 0: 0x7f800000; /* 0 or +Inf */
+ }
+ if (exp < -23)
+ return 0x3f800000; /* 1.0 */
+
+ /* convert to fixed point integer in 9.23 representation */
+ pwr = (s & 0x7fffff) | 0x800000;
+ if (exp > 0)
+ pwr <<= exp;
+ else
+ pwr >>= -exp;
+ if (s & 0x80000000)
+ pwr = -pwr;
+
+ /* extract integer part, which becomes exponent part of result */
+ exp = (pwr >> 23) + 126;
+ if (exp >= 254)
+ return 0x7f800000;
+ if (exp < -23)
+ return 0;
+
+ /* table lookup on top 3 bits of fraction to get mantissa */
+ mant = exp2s[(pwr >> 20) & 7];
+
+ /* linear interpolation using remaining 20 bits of fraction */
+ asm("mulhwu %0,%1,%2" : "=r" (frac)
+ : "r" (pwr << 12), "r" (0x172b83ff));
+ asm("mulhwu %0,%1,%2" : "=r" (frac) : "r" (frac), "r" (mant));
+ mant += frac;
+
+ if (exp >= 0)
+ return mant + (exp << 23);
+
+ /* denormalized result */
+ exp = -exp;
+ mant += 1 << (exp - 1);
+ return mant >> exp;
+}
+
+/*
+ * Computes an estimate of log_2(x). The `s' argument is the 32-bit
+ * single-precision floating-point representation of x.
+ */
+static unsigned int elog2(unsigned int s)
+{
+ int exp, mant, lz, frac;
+
+ exp = s & 0x7f800000;
+ mant = s & 0x7fffff;
+ if (exp == 0x7f800000) { /* Inf or NaN */
+ if (mant != 0)
+ s |= 0x400000; /* turn NaN into QNaN */
+ return s;
+ }
+ if ((exp | mant) == 0) /* +0 or -0 */
+ return 0xff800000; /* return -Inf */
+
+ if (exp == 0) {
+ /* denormalized */
+ asm("cntlzw %0,%1" : "=r" (lz) : "r" (mant));
+ mant <<= lz - 8;
+ exp = (-118 - lz) << 23;
+ } else {
+ mant |= 0x800000;
+ exp -= 127 << 23;
+ }
+
+ if (mant >= 0xb504f3) { /* 2^0.5 * 2^23 */
+ exp |= 0x400000; /* 0.5 * 2^23 */
+ asm("mulhwu %0,%1,%2" : "=r" (mant)
+ : "r" (mant), "r" (0xb504f334)); /* 2^-0.5 * 2^32 */
+ }
+ if (mant >= 0x9837f0) { /* 2^0.25 * 2^23 */
+ exp |= 0x200000; /* 0.25 * 2^23 */
+ asm("mulhwu %0,%1,%2" : "=r" (mant)
+ : "r" (mant), "r" (0xd744fccb)); /* 2^-0.25 * 2^32 */
+ }
+ if (mant >= 0x8b95c2) { /* 2^0.125 * 2^23 */
+ exp |= 0x100000; /* 0.125 * 2^23 */
+ asm("mulhwu %0,%1,%2" : "=r" (mant)
+ : "r" (mant), "r" (0xeac0c6e8)); /* 2^-0.125 * 2^32 */
+ }
+ if (mant > 0x800000) { /* 1.0 * 2^23 */
+ /* calculate (mant - 1) * 1.381097463 */
+ /* 1.381097463 == 0.125 / (2^0.125 - 1) */
+ asm("mulhwu %0,%1,%2" : "=r" (frac)
+ : "r" ((mant - 0x800000) << 1), "r" (0xb0c7cd3a));
+ exp += frac;
+ }
+ s = exp & 0x80000000;
+ if (exp != 0) {
+ if (s)
+ exp = -exp;
+ asm("cntlzw %0,%1" : "=r" (lz) : "r" (exp));
+ lz = 8 - lz;
+ if (lz > 0)
+ exp >>= lz;
+ else if (lz < 0)
+ exp <<= -lz;
+ s += ((lz + 126) << 23) + exp;
+ }
+ return s;
+}
+
+#define VSCR_SAT 1
+
+static int ctsxs(unsigned int x, int scale, unsigned int *vscrp)
+{
+ int exp, mant;
+
+ exp = (x >> 23) & 0xff;
+ mant = x & 0x7fffff;
+ if (exp == 255 && mant != 0)
+ return 0; /* NaN -> 0 */
+ exp = exp - 127 + scale;
+ if (exp < 0)
+ return 0; /* round towards zero */
+ if (exp >= 31) {
+ /* saturate, unless the result would be -2^31 */
+ if (x + (scale << 23) != 0xcf000000)
+ *vscrp |= VSCR_SAT;
+ return (x & 0x80000000)? 0x80000000: 0x7fffffff;
+ }
+ mant |= 0x800000;
+ mant = (mant << 7) >> (30 - exp);
+ return (x & 0x80000000)? -mant: mant;
+}
+
+static unsigned int ctuxs(unsigned int x, int scale, unsigned int *vscrp)
+{
+ int exp;
+ unsigned int mant;
+
+ exp = (x >> 23) & 0xff;
+ mant = x & 0x7fffff;
+ if (exp == 255 && mant != 0)
+ return 0; /* NaN -> 0 */
+ exp = exp - 127 + scale;
+ if (exp < 0)
+ return 0; /* round towards zero */
+ if (x & 0x80000000) {
+ /* negative => saturate to 0 */
+ *vscrp |= VSCR_SAT;
+ return 0;
+ }
+ if (exp >= 32) {
+ /* saturate */
+ *vscrp |= VSCR_SAT;
+ return 0xffffffff;
+ }
+ mant |= 0x800000;
+ mant = (mant << 8) >> (31 - exp);
+ return mant;
+}
+
+/* Round to floating integer, towards 0 */
+static unsigned int rfiz(unsigned int x)
+{
+ int exp;
+
+ exp = ((x >> 23) & 0xff) - 127;
+ if (exp == 128 && (x & 0x7fffff) != 0)
+ return x | 0x400000; /* NaN -> make it a QNaN */
+ if (exp >= 23)
+ return x; /* it's an integer already (or Inf) */
+ if (exp < 0)
+ return x & 0x80000000; /* |x| < 1.0 rounds to 0 */
+ return x & ~(0x7fffff >> exp);
+}
+
+/* Round to floating integer, towards +/- Inf */
+static unsigned int rfii(unsigned int x)
+{
+ int exp, mask;
+
+ exp = ((x >> 23) & 0xff) - 127;
+ if (exp == 128 && (x & 0x7fffff) != 0)
+ return x | 0x400000; /* NaN -> make it a QNaN */
+ if (exp >= 23)
+ return x; /* it's an integer already (or Inf) */
+ if ((x & 0x7fffffff) == 0)
+ return x; /* +/-0 -> +/-0 */
+ if (exp < 0)
+ /* 0 < |x| < 1.0 rounds to +/- 1.0 */
+ return (x & 0x80000000) | 0x3f800000;
+ mask = 0x7fffff >> exp;
+ /* mantissa overflows into exponent - that's OK,
+ it can't overflow into the sign bit */
+ return (x + mask) & ~mask;
+}
+
+/* Round to floating integer, to nearest */
+static unsigned int rfin(unsigned int x)
+{
+ int exp, half;
+
+ exp = ((x >> 23) & 0xff) - 127;
+ if (exp == 128 && (x & 0x7fffff) != 0)
+ return x | 0x400000; /* NaN -> make it a QNaN */
+ if (exp >= 23)
+ return x; /* it's an integer already (or Inf) */
+ if (exp < -1)
+ return x & 0x80000000; /* |x| < 0.5 -> +/-0 */
+ if (exp == -1)
+ /* 0.5 <= |x| < 1.0 rounds to +/- 1.0 */
+ return (x & 0x80000000) | 0x3f800000;
+ half = 0x400000 >> exp;
+ /* add 0.5 to the magnitude and chop off the fraction bits */
+ return (x + half) & ~(0x7fffff >> exp);
+}
+
+int emulate_altivec(struct pt_regs *regs)
+{
+ unsigned int instr, i;
+ unsigned int va, vb, vc, vd;
+ vector128 *vrs;
+
+ if (get_user(instr, (unsigned int __user *) regs->nip))
+ return -EFAULT;
+ if ((instr >> 26) != 4)
+ return -EINVAL; /* not an altivec instruction */
+ vd = (instr >> 21) & 0x1f;
+ va = (instr >> 16) & 0x1f;
+ vb = (instr >> 11) & 0x1f;
+ vc = (instr >> 6) & 0x1f;
+
+ vrs = current->thread.vr;
+ switch (instr & 0x3f) {
+ case 10:
+ switch (vc) {
+ case 0: /* vaddfp */
+ vaddfp(&vrs[vd], &vrs[va], &vrs[vb]);
+ break;
+ case 1: /* vsubfp */
+ vsubfp(&vrs[vd], &vrs[va], &vrs[vb]);
+ break;
+ case 4: /* vrefp */
+ vrefp(&vrs[vd], &vrs[vb]);
+ break;
+ case 5: /* vrsqrtefp */
+ vrsqrtefp(&vrs[vd], &vrs[vb]);
+ break;
+ case 6: /* vexptefp */
+ for (i = 0; i < 4; ++i)
+ vrs[vd].u[i] = eexp2(vrs[vb].u[i]);
+ break;
+ case 7: /* vlogefp */
+ for (i = 0; i < 4; ++i)
+ vrs[vd].u[i] = elog2(vrs[vb].u[i]);
+ break;
+ case 8: /* vrfin */
+ for (i = 0; i < 4; ++i)
+ vrs[vd].u[i] = rfin(vrs[vb].u[i]);
+ break;
+ case 9: /* vrfiz */
+ for (i = 0; i < 4; ++i)
+ vrs[vd].u[i] = rfiz(vrs[vb].u[i]);
+ break;
+ case 10: /* vrfip */
+ for (i = 0; i < 4; ++i) {
+ u32 x = vrs[vb].u[i];
+ x = (x & 0x80000000)? rfiz(x): rfii(x);
+ vrs[vd].u[i] = x;
+ }
+ break;
+ case 11: /* vrfim */
+ for (i = 0; i < 4; ++i) {
+ u32 x = vrs[vb].u[i];
+ x = (x & 0x80000000)? rfii(x): rfiz(x);
+ vrs[vd].u[i] = x;
+ }
+ break;
+ case 14: /* vctuxs */
+ for (i = 0; i < 4; ++i)
+ vrs[vd].u[i] = ctuxs(vrs[vb].u[i], va,
+ ¤t->thread.vscr.u[3]);
+ break;
+ case 15: /* vctsxs */
+ for (i = 0; i < 4; ++i)
+ vrs[vd].u[i] = ctsxs(vrs[vb].u[i], va,
+ ¤t->thread.vscr.u[3]);
+ break;
+ default:
+ return -EINVAL;
+ }
+ break;
+ case 46: /* vmaddfp */
+ vmaddfp(&vrs[vd], &vrs[va], &vrs[vb], &vrs[vc]);
+ break;
+ case 47: /* vnmsubfp */
+ vnmsubfp(&vrs[vd], &vrs[va], &vrs[vb], &vrs[vc]);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
diff --git a/arch/ppc/kernel/vector.S b/arch/ppc/kernel/vector.S
new file mode 100644
index 0000000..82a2134
--- /dev/null
+++ b/arch/ppc/kernel/vector.S
@@ -0,0 +1,217 @@
+#include <asm/ppc_asm.h>
+#include <asm/processor.h>
+
+/*
+ * The routines below are in assembler so we can closely control the
+ * usage of floating-point registers. These routines must be called
+ * with preempt disabled.
+ */
+ .data
+fpzero:
+ .long 0
+fpone:
+ .long 0x3f800000 /* 1.0 in single-precision FP */
+fphalf:
+ .long 0x3f000000 /* 0.5 in single-precision FP */
+
+ .text
+/*
+ * Internal routine to enable floating point and set FPSCR to 0.
+ * Don't call it from C; it doesn't use the normal calling convention.
+ */
+fpenable:
+ mfmsr r10
+ ori r11,r10,MSR_FP
+ mtmsr r11
+ isync
+ stfd fr0,24(r1)
+ stfd fr1,16(r1)
+ stfd fr31,8(r1)
+ lis r11,fpzero@ha
+ mffs fr31
+ lfs fr1,fpzero@l(r11)
+ mtfsf 0xff,fr1
+ blr
+
+fpdisable:
+ mtfsf 0xff,fr31
+ lfd fr31,8(r1)
+ lfd fr1,16(r1)
+ lfd fr0,24(r1)
+ mtmsr r10
+ isync
+ blr
+
+/*
+ * Vector add, floating point.
+ */
+ .globl vaddfp
+vaddfp:
+ stwu r1,-32(r1)
+ mflr r0
+ stw r0,36(r1)
+ bl fpenable
+ li r0,4
+ mtctr r0
+ li r6,0
+1: lfsx fr0,r4,r6
+ lfsx fr1,r5,r6
+ fadds fr0,fr0,fr1
+ stfsx fr0,r3,r6
+ addi r6,r6,4
+ bdnz 1b
+ bl fpdisable
+ lwz r0,36(r1)
+ mtlr r0
+ addi r1,r1,32
+ blr
+
+/*
+ * Vector subtract, floating point.
+ */
+ .globl vsubfp
+vsubfp:
+ stwu r1,-32(r1)
+ mflr r0
+ stw r0,36(r1)
+ bl fpenable
+ li r0,4
+ mtctr r0
+ li r6,0
+1: lfsx fr0,r4,r6
+ lfsx fr1,r5,r6
+ fsubs fr0,fr0,fr1
+ stfsx fr0,r3,r6
+ addi r6,r6,4
+ bdnz 1b
+ bl fpdisable
+ lwz r0,36(r1)
+ mtlr r0
+ addi r1,r1,32
+ blr
+
+/*
+ * Vector multiply and add, floating point.
+ */
+ .globl vmaddfp
+vmaddfp:
+ stwu r1,-48(r1)
+ mflr r0
+ stw r0,52(r1)
+ bl fpenable
+ stfd fr2,32(r1)
+ li r0,4
+ mtctr r0
+ li r7,0
+1: lfsx fr0,r4,r7
+ lfsx fr1,r5,r7
+ lfsx fr2,r6,r7
+ fmadds fr0,fr0,fr2,fr1
+ stfsx fr0,r3,r7
+ addi r7,r7,4
+ bdnz 1b
+ lfd fr2,32(r1)
+ bl fpdisable
+ lwz r0,52(r1)
+ mtlr r0
+ addi r1,r1,48
+ blr
+
+/*
+ * Vector negative multiply and subtract, floating point.
+ */
+ .globl vnmsubfp
+vnmsubfp:
+ stwu r1,-48(r1)
+ mflr r0
+ stw r0,52(r1)
+ bl fpenable
+ stfd fr2,32(r1)
+ li r0,4
+ mtctr r0
+ li r7,0
+1: lfsx fr0,r4,r7
+ lfsx fr1,r5,r7
+ lfsx fr2,r6,r7
+ fnmsubs fr0,fr0,fr2,fr1
+ stfsx fr0,r3,r7
+ addi r7,r7,4
+ bdnz 1b
+ lfd fr2,32(r1)
+ bl fpdisable
+ lwz r0,52(r1)
+ mtlr r0
+ addi r1,r1,48
+ blr
+
+/*
+ * Vector reciprocal estimate. We just compute 1.0/x.
+ * r3 -> destination, r4 -> source.
+ */
+ .globl vrefp
+vrefp:
+ stwu r1,-32(r1)
+ mflr r0
+ stw r0,36(r1)
+ bl fpenable
+ lis r9,fpone@ha
+ li r0,4
+ lfs fr1,fpone@l(r9)
+ mtctr r0
+ li r6,0
+1: lfsx fr0,r4,r6
+ fdivs fr0,fr1,fr0
+ stfsx fr0,r3,r6
+ addi r6,r6,4
+ bdnz 1b
+ bl fpdisable
+ lwz r0,36(r1)
+ mtlr r0
+ addi r1,r1,32
+ blr
+
+/*
+ * Vector reciprocal square-root estimate, floating point.
+ * We use the frsqrte instruction for the initial estimate followed
+ * by 2 iterations of Newton-Raphson to get sufficient accuracy.
+ * r3 -> destination, r4 -> source.
+ */
+ .globl vrsqrtefp
+vrsqrtefp:
+ stwu r1,-48(r1)
+ mflr r0
+ stw r0,52(r1)
+ bl fpenable
+ stfd fr2,32(r1)
+ stfd fr3,40(r1)
+ stfd fr4,48(r1)
+ stfd fr5,56(r1)
+ lis r9,fpone@ha
+ lis r8,fphalf@ha
+ li r0,4
+ lfs fr4,fpone@l(r9)
+ lfs fr5,fphalf@l(r8)
+ mtctr r0
+ li r6,0
+1: lfsx fr0,r4,r6
+ frsqrte fr1,fr0 /* r = frsqrte(s) */
+ fmuls fr3,fr1,fr0 /* r * s */
+ fmuls fr2,fr1,fr5 /* r * 0.5 */
+ fnmsubs fr3,fr1,fr3,fr4 /* 1 - s * r * r */
+ fmadds fr1,fr2,fr3,fr1 /* r = r + 0.5 * r * (1 - s * r * r) */
+ fmuls fr3,fr1,fr0 /* r * s */
+ fmuls fr2,fr1,fr5 /* r * 0.5 */
+ fnmsubs fr3,fr1,fr3,fr4 /* 1 - s * r * r */
+ fmadds fr1,fr2,fr3,fr1 /* r = r + 0.5 * r * (1 - s * r * r) */
+ stfsx fr1,r3,r6
+ addi r6,r6,4
+ bdnz 1b
+ lfd fr5,56(r1)
+ lfd fr4,48(r1)
+ lfd fr3,40(r1)
+ lfd fr2,32(r1)
+ bl fpdisable
+ lwz r0,36(r1)
+ mtlr r0
+ addi r1,r1,32
+ blr
diff --git a/arch/ppc/kernel/vmlinux.lds.S b/arch/ppc/kernel/vmlinux.lds.S
new file mode 100644
index 0000000..0c0e714
--- /dev/null
+++ b/arch/ppc/kernel/vmlinux.lds.S
@@ -0,0 +1,192 @@
+#include <asm-generic/vmlinux.lds.h>
+
+OUTPUT_ARCH(powerpc:common)
+jiffies = jiffies_64 + 4;
+SECTIONS
+{
+ /* Read-only sections, merged into text segment: */
+ . = + SIZEOF_HEADERS;
+ .interp : { *(.interp) }
+ .hash : { *(.hash) }
+ .dynsym : { *(.dynsym) }
+ .dynstr : { *(.dynstr) }
+ .rel.text : { *(.rel.text) }
+ .rela.text : { *(.rela.text) }
+ .rel.data : { *(.rel.data) }
+ .rela.data : { *(.rela.data) }
+ .rel.rodata : { *(.rel.rodata) }
+ .rela.rodata : { *(.rela.rodata) }
+ .rel.got : { *(.rel.got) }
+ .rela.got : { *(.rela.got) }
+ .rel.ctors : { *(.rel.ctors) }
+ .rela.ctors : { *(.rela.ctors) }
+ .rel.dtors : { *(.rel.dtors) }
+ .rela.dtors : { *(.rela.dtors) }
+ .rel.bss : { *(.rel.bss) }
+ .rela.bss : { *(.rela.bss) }
+ .rel.plt : { *(.rel.plt) }
+ .rela.plt : { *(.rela.plt) }
+/* .init : { *(.init) } =0*/
+ .plt : { *(.plt) }
+ .text :
+ {
+ *(.text)
+ SCHED_TEXT
+ LOCK_TEXT
+ *(.fixup)
+ *(.got1)
+ __got2_start = .;
+ *(.got2)
+ __got2_end = .;
+ }
+ _etext = .;
+ PROVIDE (etext = .);
+
+ RODATA
+ .fini : { *(.fini) } =0
+ .ctors : { *(.ctors) }
+ .dtors : { *(.dtors) }
+
+ .fixup : { *(.fixup) }
+
+ __ex_table : {
+ __start___ex_table = .;
+ *(__ex_table)
+ __stop___ex_table = .;
+ }
+
+ __bug_table : {
+ __start___bug_table = .;
+ *(__bug_table)
+ __stop___bug_table = .;
+ }
+
+ /* Read-write section, merged into data segment: */
+ . = ALIGN(4096);
+ .data :
+ {
+ *(.data)
+ *(.data1)
+ *(.sdata)
+ *(.sdata2)
+ *(.got.plt) *(.got)
+ *(.dynamic)
+ CONSTRUCTORS
+ }
+
+ . = ALIGN(4096);
+ __nosave_begin = .;
+ .data_nosave : { *(.data.nosave) }
+ . = ALIGN(4096);
+ __nosave_end = .;
+
+ . = ALIGN(32);
+ .data.cacheline_aligned : { *(.data.cacheline_aligned) }
+
+ _edata = .;
+ PROVIDE (edata = .);
+
+ . = ALIGN(8192);
+ .data.init_task : { *(.data.init_task) }
+
+ . = ALIGN(4096);
+ __init_begin = .;
+ .init.text : {
+ _sinittext = .;
+ *(.init.text)
+ _einittext = .;
+ }
+ .init.data : {
+ *(.init.data);
+ __vtop_table_begin = .;
+ *(.vtop_fixup);
+ __vtop_table_end = .;
+ __ptov_table_begin = .;
+ *(.ptov_fixup);
+ __ptov_table_end = .;
+ }
+ . = ALIGN(16);
+ __setup_start = .;
+ .init.setup : { *(.init.setup) }
+ __setup_end = .;
+ __initcall_start = .;
+ .initcall.init : {
+ *(.initcall1.init)
+ *(.initcall2.init)
+ *(.initcall3.init)
+ *(.initcall4.init)
+ *(.initcall5.init)
+ *(.initcall6.init)
+ *(.initcall7.init)
+ }
+ __initcall_end = .;
+
+ __con_initcall_start = .;
+ .con_initcall.init : { *(.con_initcall.init) }
+ __con_initcall_end = .;
+
+ SECURITY_INIT
+
+ __start___ftr_fixup = .;
+ __ftr_fixup : { *(__ftr_fixup) }
+ __stop___ftr_fixup = .;
+
+ . = ALIGN(32);
+ __per_cpu_start = .;
+ .data.percpu : { *(.data.percpu) }
+ __per_cpu_end = .;
+
+ . = ALIGN(4096);
+ __initramfs_start = .;
+ .init.ramfs : { *(.init.ramfs) }
+ __initramfs_end = .;
+
+ . = ALIGN(4096);
+ __init_end = .;
+
+ . = ALIGN(4096);
+ __pmac_begin = .;
+ .pmac.text : { *(.pmac.text) }
+ .pmac.data : { *(.pmac.data) }
+ . = ALIGN(4096);
+ __pmac_end = .;
+
+ . = ALIGN(4096);
+ __prep_begin = .;
+ .prep.text : { *(.prep.text) }
+ .prep.data : { *(.prep.data) }
+ . = ALIGN(4096);
+ __prep_end = .;
+
+ . = ALIGN(4096);
+ __chrp_begin = .;
+ .chrp.text : { *(.chrp.text) }
+ .chrp.data : { *(.chrp.data) }
+ . = ALIGN(4096);
+ __chrp_end = .;
+
+ . = ALIGN(4096);
+ __openfirmware_begin = .;
+ .openfirmware.text : { *(.openfirmware.text) }
+ .openfirmware.data : { *(.openfirmware.data) }
+ . = ALIGN(4096);
+ __openfirmware_end = .;
+
+ __bss_start = .;
+ .bss :
+ {
+ *(.sbss) *(.scommon)
+ *(.dynbss)
+ *(.bss)
+ *(COMMON)
+ }
+ __bss_stop = .;
+
+ _end = . ;
+ PROVIDE (end = .);
+
+ /* Sections to be discarded. */
+ /DISCARD/ : {
+ *(.exitcall.exit)
+ }
+}
diff --git a/arch/ppc/lib/Makefile b/arch/ppc/lib/Makefile
new file mode 100644
index 0000000..1c380e6
--- /dev/null
+++ b/arch/ppc/lib/Makefile
@@ -0,0 +1,9 @@
+#
+# Makefile for ppc-specific library files..
+#
+
+obj-y := checksum.o string.o strcase.o dec_and_lock.o div64.o
+
+obj-$(CONFIG_SMP) += locks.o
+obj-$(CONFIG_8xx) += rheap.o
+obj-$(CONFIG_CPM2) += rheap.o
diff --git a/arch/ppc/lib/checksum.S b/arch/ppc/lib/checksum.S
new file mode 100644
index 0000000..7874e8a
--- /dev/null
+++ b/arch/ppc/lib/checksum.S
@@ -0,0 +1,225 @@
+/*
+ * This file contains assembly-language implementations
+ * of IP-style 1's complement checksum routines.
+ *
+ * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
+ *
+ * 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.
+ *
+ * Severely hacked about by Paul Mackerras (paulus@cs.anu.edu.au).
+ */
+
+#include <linux/sys.h>
+#include <asm/processor.h>
+#include <asm/errno.h>
+#include <asm/ppc_asm.h>
+
+ .text
+
+/*
+ * ip_fast_csum(buf, len) -- Optimized for IP header
+ * len is in words and is always >= 5.
+ */
+_GLOBAL(ip_fast_csum)
+ lwz r0,0(r3)
+ lwzu r5,4(r3)
+ addic. r4,r4,-2
+ addc r0,r0,r5
+ mtctr r4
+ blelr-
+1: lwzu r4,4(r3)
+ adde r0,r0,r4
+ bdnz 1b
+ addze r0,r0 /* add in final carry */
+ rlwinm r3,r0,16,0,31 /* fold two halves together */
+ add r3,r0,r3
+ not r3,r3
+ srwi r3,r3,16
+ blr
+
+/*
+ * Compute checksum of TCP or UDP pseudo-header:
+ * csum_tcpudp_magic(saddr, daddr, len, proto, sum)
+ */
+_GLOBAL(csum_tcpudp_magic)
+ rlwimi r5,r6,16,0,15 /* put proto in upper half of len */
+ addc r0,r3,r4 /* add 4 32-bit words together */
+ adde r0,r0,r5
+ adde r0,r0,r7
+ addze r0,r0 /* add in final carry */
+ rlwinm r3,r0,16,0,31 /* fold two halves together */
+ add r3,r0,r3
+ not r3,r3
+ srwi r3,r3,16
+ blr
+
+/*
+ * computes the checksum of a memory block at buff, length len,
+ * and adds in "sum" (32-bit)
+ *
+ * csum_partial(buff, len, sum)
+ */
+_GLOBAL(csum_partial)
+ addic r0,r5,0
+ subi r3,r3,4
+ srwi. r6,r4,2
+ beq 3f /* if we're doing < 4 bytes */
+ andi. r5,r3,2 /* Align buffer to longword boundary */
+ beq+ 1f
+ lhz r5,4(r3) /* do 2 bytes to get aligned */
+ addi r3,r3,2
+ subi r4,r4,2
+ addc r0,r0,r5
+ srwi. r6,r4,2 /* # words to do */
+ beq 3f
+1: mtctr r6
+2: lwzu r5,4(r3) /* the bdnz has zero overhead, so it should */
+ adde r0,r0,r5 /* be unnecessary to unroll this loop */
+ bdnz 2b
+ andi. r4,r4,3
+3: cmpwi 0,r4,2
+ blt+ 4f
+ lhz r5,4(r3)
+ addi r3,r3,2
+ subi r4,r4,2
+ adde r0,r0,r5
+4: cmpwi 0,r4,1
+ bne+ 5f
+ lbz r5,4(r3)
+ slwi r5,r5,8 /* Upper byte of word */
+ adde r0,r0,r5
+5: addze r3,r0 /* add in final carry */
+ blr
+
+/*
+ * Computes the checksum of a memory block at src, length len,
+ * and adds in "sum" (32-bit), while copying the block to dst.
+ * If an access exception occurs on src or dst, it stores -EFAULT
+ * to *src_err or *dst_err respectively, and (for an error on
+ * src) zeroes the rest of dst.
+ *
+ * csum_partial_copy_generic(src, dst, len, sum, src_err, dst_err)
+ */
+_GLOBAL(csum_partial_copy_generic)
+ addic r0,r6,0
+ subi r3,r3,4
+ subi r4,r4,4
+ srwi. r6,r5,2
+ beq 3f /* if we're doing < 4 bytes */
+ andi. r9,r4,2 /* Align dst to longword boundary */
+ beq+ 1f
+81: lhz r6,4(r3) /* do 2 bytes to get aligned */
+ addi r3,r3,2
+ subi r5,r5,2
+91: sth r6,4(r4)
+ addi r4,r4,2
+ addc r0,r0,r6
+ srwi. r6,r5,2 /* # words to do */
+ beq 3f
+1: srwi. r6,r5,4 /* # groups of 4 words to do */
+ beq 10f
+ mtctr r6
+71: lwz r6,4(r3)
+72: lwz r9,8(r3)
+73: lwz r10,12(r3)
+74: lwzu r11,16(r3)
+ adde r0,r0,r6
+75: stw r6,4(r4)
+ adde r0,r0,r9
+76: stw r9,8(r4)
+ adde r0,r0,r10
+77: stw r10,12(r4)
+ adde r0,r0,r11
+78: stwu r11,16(r4)
+ bdnz 71b
+10: rlwinm. r6,r5,30,30,31 /* # words left to do */
+ beq 13f
+ mtctr r6
+82: lwzu r9,4(r3)
+92: stwu r9,4(r4)
+ adde r0,r0,r9
+ bdnz 82b
+13: andi. r5,r5,3
+3: cmpwi 0,r5,2
+ blt+ 4f
+83: lhz r6,4(r3)
+ addi r3,r3,2
+ subi r5,r5,2
+93: sth r6,4(r4)
+ addi r4,r4,2
+ adde r0,r0,r6
+4: cmpwi 0,r5,1
+ bne+ 5f
+84: lbz r6,4(r3)
+94: stb r6,4(r4)
+ slwi r6,r6,8 /* Upper byte of word */
+ adde r0,r0,r6
+5: addze r3,r0 /* add in final carry */
+ blr
+
+/* These shouldn't go in the fixup section, since that would
+ cause the ex_table addresses to get out of order. */
+
+src_error_4:
+ mfctr r6 /* update # bytes remaining from ctr */
+ rlwimi r5,r6,4,0,27
+ b 79f
+src_error_1:
+ li r6,0
+ subi r5,r5,2
+95: sth r6,4(r4)
+ addi r4,r4,2
+79: srwi. r6,r5,2
+ beq 3f
+ mtctr r6
+src_error_2:
+ li r6,0
+96: stwu r6,4(r4)
+ bdnz 96b
+3: andi. r5,r5,3
+ beq src_error
+src_error_3:
+ li r6,0
+ mtctr r5
+ addi r4,r4,3
+97: stbu r6,1(r4)
+ bdnz 97b
+src_error:
+ cmpwi 0,r7,0
+ beq 1f
+ li r6,-EFAULT
+ stw r6,0(r7)
+1: addze r3,r0
+ blr
+
+dst_error:
+ cmpwi 0,r8,0
+ beq 1f
+ li r6,-EFAULT
+ stw r6,0(r8)
+1: addze r3,r0
+ blr
+
+.section __ex_table,"a"
+ .long 81b,src_error_1
+ .long 91b,dst_error
+ .long 71b,src_error_4
+ .long 72b,src_error_4
+ .long 73b,src_error_4
+ .long 74b,src_error_4
+ .long 75b,dst_error
+ .long 76b,dst_error
+ .long 77b,dst_error
+ .long 78b,dst_error
+ .long 82b,src_error_2
+ .long 92b,dst_error
+ .long 83b,src_error_3
+ .long 93b,dst_error
+ .long 84b,src_error_3
+ .long 94b,dst_error
+ .long 95b,dst_error
+ .long 96b,dst_error
+ .long 97b,dst_error
diff --git a/arch/ppc/lib/dec_and_lock.c b/arch/ppc/lib/dec_and_lock.c
new file mode 100644
index 0000000..4ee8880
--- /dev/null
+++ b/arch/ppc/lib/dec_and_lock.c
@@ -0,0 +1,46 @@
+#include <linux/module.h>
+#include <linux/spinlock.h>
+#include <asm/atomic.h>
+#include <asm/system.h>
+
+/*
+ * This is an implementation of the notion of "decrement a
+ * reference count, and return locked if it decremented to zero".
+ *
+ * This implementation can be used on any architecture that
+ * has a cmpxchg, and where atomic->value is an int holding
+ * the value of the atomic (i.e. the high bits aren't used
+ * for a lock or anything like that).
+ *
+ * N.B. ATOMIC_DEC_AND_LOCK gets defined in include/linux/spinlock.h
+ * if spinlocks are empty and thus atomic_dec_and_lock is defined
+ * to be atomic_dec_and_test - in that case we don't need it
+ * defined here as well.
+ */
+
+#ifndef ATOMIC_DEC_AND_LOCK
+int _atomic_dec_and_lock(atomic_t *atomic, spinlock_t *lock)
+{
+ int counter;
+ int newcount;
+
+ for (;;) {
+ counter = atomic_read(atomic);
+ newcount = counter - 1;
+ if (!newcount)
+ break; /* do it the slow way */
+
+ newcount = cmpxchg(&atomic->counter, counter, newcount);
+ if (newcount == counter)
+ return 0;
+ }
+
+ spin_lock(lock);
+ if (atomic_dec_and_test(atomic))
+ return 1;
+ spin_unlock(lock);
+ return 0;
+}
+
+EXPORT_SYMBOL(_atomic_dec_and_lock);
+#endif /* ATOMIC_DEC_AND_LOCK */
diff --git a/arch/ppc/lib/div64.S b/arch/ppc/lib/div64.S
new file mode 100644
index 0000000..3527569
--- /dev/null
+++ b/arch/ppc/lib/div64.S
@@ -0,0 +1,58 @@
+/*
+ * Divide a 64-bit unsigned number by a 32-bit unsigned number.
+ * This routine assumes that the top 32 bits of the dividend are
+ * non-zero to start with.
+ * On entry, r3 points to the dividend, which get overwritten with
+ * the 64-bit quotient, and r4 contains the divisor.
+ * On exit, r3 contains the remainder.
+ *
+ * Copyright (C) 2002 Paul Mackerras, IBM Corp.
+ *
+ * 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.
+ */
+#include <asm/ppc_asm.h>
+#include <asm/processor.h>
+
+_GLOBAL(__div64_32)
+ lwz r5,0(r3) # get the dividend into r5/r6
+ lwz r6,4(r3)
+ cmplw r5,r4
+ li r7,0
+ li r8,0
+ blt 1f
+ divwu r7,r5,r4 # if dividend.hi >= divisor,
+ mullw r0,r7,r4 # quotient.hi = dividend.hi / divisor
+ subf. r5,r0,r5 # dividend.hi %= divisor
+ beq 3f
+1: mr r11,r5 # here dividend.hi != 0
+ andis. r0,r5,0xc000
+ bne 2f
+ cntlzw r0,r5 # we are shifting the dividend right
+ li r10,-1 # to make it < 2^32, and shifting
+ srw r10,r10,r0 # the divisor right the same amount,
+ add r9,r4,r10 # rounding up (so the estimate cannot
+ andc r11,r6,r10 # ever be too large, only too small)
+ andc r9,r9,r10
+ or r11,r5,r11
+ rotlw r9,r9,r0
+ rotlw r11,r11,r0
+ divwu r11,r11,r9 # then we divide the shifted quantities
+2: mullw r10,r11,r4 # to get an estimate of the quotient,
+ mulhwu r9,r11,r4 # multiply the estimate by the divisor,
+ subfc r6,r10,r6 # take the product from the divisor,
+ add r8,r8,r11 # and add the estimate to the accumulated
+ subfe. r5,r9,r5 # quotient
+ bne 1b
+3: cmplw r6,r4
+ blt 4f
+ divwu r0,r6,r4 # perform the remaining 32-bit division
+ mullw r10,r0,r4 # and get the remainder
+ add r8,r8,r0
+ subf r6,r10,r6
+4: stw r7,0(r3) # return the quotient in *r3
+ stw r8,4(r3)
+ mr r3,r6 # return the remainder in r3
+ blr
diff --git a/arch/ppc/lib/locks.c b/arch/ppc/lib/locks.c
new file mode 100644
index 0000000..694163d
--- /dev/null
+++ b/arch/ppc/lib/locks.c
@@ -0,0 +1,190 @@
+/*
+ * Locks for smp ppc
+ *
+ * Written by Cort Dougan (cort@cs.nmt.edu)
+ */
+
+#include <linux/config.h>
+#include <linux/sched.h>
+#include <linux/spinlock.h>
+#include <linux/module.h>
+#include <asm/ppc_asm.h>
+#include <asm/smp.h>
+
+#ifdef CONFIG_DEBUG_SPINLOCK
+
+#undef INIT_STUCK
+#define INIT_STUCK 200000000 /*0xffffffff*/
+
+/*
+ * Try to acquire a spinlock.
+ * Only does the stwcx. if the load returned 0 - the Programming
+ * Environments Manual suggests not doing unnecessary stcwx.'s
+ * since they may inhibit forward progress by other CPUs in getting
+ * a lock.
+ */
+static inline unsigned long __spin_trylock(volatile unsigned long *lock)
+{
+ unsigned long ret;
+
+ __asm__ __volatile__ ("\n\
+1: lwarx %0,0,%1\n\
+ cmpwi 0,%0,0\n\
+ bne 2f\n"
+ PPC405_ERR77(0,%1)
+" stwcx. %2,0,%1\n\
+ bne- 1b\n\
+ isync\n\
+2:"
+ : "=&r"(ret)
+ : "r"(lock), "r"(1)
+ : "cr0", "memory");
+
+ return ret;
+}
+
+void _raw_spin_lock(spinlock_t *lock)
+{
+ int cpu = smp_processor_id();
+ unsigned int stuck = INIT_STUCK;
+ while (__spin_trylock(&lock->lock)) {
+ while ((unsigned volatile long)lock->lock != 0) {
+ if (!--stuck) {
+ printk("_spin_lock(%p) CPU#%d NIP %p"
+ " holder: cpu %ld pc %08lX\n",
+ lock, cpu, __builtin_return_address(0),
+ lock->owner_cpu,lock->owner_pc);
+ stuck = INIT_STUCK;
+ /* steal the lock */
+ /*xchg_u32((void *)&lock->lock,0);*/
+ }
+ }
+ }
+ lock->owner_pc = (unsigned long)__builtin_return_address(0);
+ lock->owner_cpu = cpu;
+}
+EXPORT_SYMBOL(_raw_spin_lock);
+
+int _raw_spin_trylock(spinlock_t *lock)
+{
+ if (__spin_trylock(&lock->lock))
+ return 0;
+ lock->owner_cpu = smp_processor_id();
+ lock->owner_pc = (unsigned long)__builtin_return_address(0);
+ return 1;
+}
+EXPORT_SYMBOL(_raw_spin_trylock);
+
+void _raw_spin_unlock(spinlock_t *lp)
+{
+ if ( !lp->lock )
+ printk("_spin_unlock(%p): no lock cpu %d curr PC %p %s/%d\n",
+ lp, smp_processor_id(), __builtin_return_address(0),
+ current->comm, current->pid);
+ if ( lp->owner_cpu != smp_processor_id() )
+ printk("_spin_unlock(%p): cpu %d trying clear of cpu %d pc %lx val %lx\n",
+ lp, smp_processor_id(), (int)lp->owner_cpu,
+ lp->owner_pc,lp->lock);
+ lp->owner_pc = lp->owner_cpu = 0;
+ wmb();
+ lp->lock = 0;
+}
+EXPORT_SYMBOL(_raw_spin_unlock);
+
+/*
+ * For rwlocks, zero is unlocked, -1 is write-locked,
+ * positive is read-locked.
+ */
+static __inline__ int __read_trylock(rwlock_t *rw)
+{
+ signed int tmp;
+
+ __asm__ __volatile__(
+"2: lwarx %0,0,%1 # __read_trylock\n\
+ addic. %0,%0,1\n\
+ ble- 1f\n"
+ PPC405_ERR77(0,%1)
+" stwcx. %0,0,%1\n\
+ bne- 2b\n\
+ isync\n\
+1:"
+ : "=&r"(tmp)
+ : "r"(&rw->lock)
+ : "cr0", "memory");
+
+ return tmp;
+}
+
+int _raw_read_trylock(rwlock_t *rw)
+{
+ return __read_trylock(rw) > 0;
+}
+EXPORT_SYMBOL(_raw_read_trylock);
+
+void _raw_read_lock(rwlock_t *rw)
+{
+ unsigned int stuck;
+
+ while (__read_trylock(rw) <= 0) {
+ stuck = INIT_STUCK;
+ while (!read_can_lock(rw)) {
+ if (--stuck == 0) {
+ printk("_read_lock(%p) CPU#%d lock %d\n",
+ rw, _smp_processor_id(), rw->lock);
+ stuck = INIT_STUCK;
+ }
+ }
+ }
+}
+EXPORT_SYMBOL(_raw_read_lock);
+
+void _raw_read_unlock(rwlock_t *rw)
+{
+ if ( rw->lock == 0 )
+ printk("_read_unlock(): %s/%d (nip %08lX) lock %d\n",
+ current->comm,current->pid,current->thread.regs->nip,
+ rw->lock);
+ wmb();
+ atomic_dec((atomic_t *) &(rw)->lock);
+}
+EXPORT_SYMBOL(_raw_read_unlock);
+
+void _raw_write_lock(rwlock_t *rw)
+{
+ unsigned int stuck;
+
+ while (cmpxchg(&rw->lock, 0, -1) != 0) {
+ stuck = INIT_STUCK;
+ while (!write_can_lock(rw)) {
+ if (--stuck == 0) {
+ printk("write_lock(%p) CPU#%d lock %d)\n",
+ rw, _smp_processor_id(), rw->lock);
+ stuck = INIT_STUCK;
+ }
+ }
+ }
+ wmb();
+}
+EXPORT_SYMBOL(_raw_write_lock);
+
+int _raw_write_trylock(rwlock_t *rw)
+{
+ if (cmpxchg(&rw->lock, 0, -1) != 0)
+ return 0;
+ wmb();
+ return 1;
+}
+EXPORT_SYMBOL(_raw_write_trylock);
+
+void _raw_write_unlock(rwlock_t *rw)
+{
+ if (rw->lock >= 0)
+ printk("_write_lock(): %s/%d (nip %08lX) lock %d\n",
+ current->comm,current->pid,current->thread.regs->nip,
+ rw->lock);
+ wmb();
+ rw->lock = 0;
+}
+EXPORT_SYMBOL(_raw_write_unlock);
+
+#endif
diff --git a/arch/ppc/lib/rheap.c b/arch/ppc/lib/rheap.c
new file mode 100644
index 0000000..42c5de2
--- /dev/null
+++ b/arch/ppc/lib/rheap.c
@@ -0,0 +1,693 @@
+/*
+ * arch/ppc/syslib/rheap.c
+ *
+ * A Remote Heap. Remote means that we don't touch the memory that the
+ * heap points to. Normal heap implementations use the memory they manage
+ * to place their list. We cannot do that because the memory we manage may
+ * have special properties, for example it is uncachable or of different
+ * endianess.
+ *
+ * Author: Pantelis Antoniou <panto@intracom.gr>
+ *
+ * 2004 (c) INTRACOM S.A. Greece. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+
+#include <asm/rheap.h>
+
+/*
+ * Fixup a list_head, needed when copying lists. If the pointers fall
+ * between s and e, apply the delta. This assumes that
+ * sizeof(struct list_head *) == sizeof(unsigned long *).
+ */
+static inline void fixup(unsigned long s, unsigned long e, int d,
+ struct list_head *l)
+{
+ unsigned long *pp;
+
+ pp = (unsigned long *)&l->next;
+ if (*pp >= s && *pp < e)
+ *pp += d;
+
+ pp = (unsigned long *)&l->prev;
+ if (*pp >= s && *pp < e)
+ *pp += d;
+}
+
+/* Grow the allocated blocks */
+static int grow(rh_info_t * info, int max_blocks)
+{
+ rh_block_t *block, *blk;
+ int i, new_blocks;
+ int delta;
+ unsigned long blks, blke;
+
+ if (max_blocks <= info->max_blocks)
+ return -EINVAL;
+
+ new_blocks = max_blocks - info->max_blocks;
+
+ block = kmalloc(sizeof(rh_block_t) * max_blocks, GFP_KERNEL);
+ if (block == NULL)
+ return -ENOMEM;
+
+ if (info->max_blocks > 0) {
+
+ /* copy old block area */
+ memcpy(block, info->block,
+ sizeof(rh_block_t) * info->max_blocks);
+
+ delta = (char *)block - (char *)info->block;
+
+ /* and fixup list pointers */
+ blks = (unsigned long)info->block;
+ blke = (unsigned long)(info->block + info->max_blocks);
+
+ for (i = 0, blk = block; i < info->max_blocks; i++, blk++)
+ fixup(blks, blke, delta, &blk->list);
+
+ fixup(blks, blke, delta, &info->empty_list);
+ fixup(blks, blke, delta, &info->free_list);
+ fixup(blks, blke, delta, &info->taken_list);
+
+ /* free the old allocated memory */
+ if ((info->flags & RHIF_STATIC_BLOCK) == 0)
+ kfree(info->block);
+ }
+
+ info->block = block;
+ info->empty_slots += new_blocks;
+ info->max_blocks = max_blocks;
+ info->flags &= ~RHIF_STATIC_BLOCK;
+
+ /* add all new blocks to the free list */
+ for (i = 0, blk = block + info->max_blocks; i < new_blocks; i++, blk++)
+ list_add(&blk->list, &info->empty_list);
+
+ return 0;
+}
+
+/*
+ * Assure at least the required amount of empty slots. If this function
+ * causes a grow in the block area then all pointers kept to the block
+ * area are invalid!
+ */
+static int assure_empty(rh_info_t * info, int slots)
+{
+ int max_blocks;
+
+ /* This function is not meant to be used to grow uncontrollably */
+ if (slots >= 4)
+ return -EINVAL;
+
+ /* Enough space */
+ if (info->empty_slots >= slots)
+ return 0;
+
+ /* Next 16 sized block */
+ max_blocks = ((info->max_blocks + slots) + 15) & ~15;
+
+ return grow(info, max_blocks);
+}
+
+static rh_block_t *get_slot(rh_info_t * info)
+{
+ rh_block_t *blk;
+
+ /* If no more free slots, and failure to extend. */
+ /* XXX: You should have called assure_empty before */
+ if (info->empty_slots == 0) {
+ printk(KERN_ERR "rh: out of slots; crash is imminent.\n");
+ return NULL;
+ }
+
+ /* Get empty slot to use */
+ blk = list_entry(info->empty_list.next, rh_block_t, list);
+ list_del_init(&blk->list);
+ info->empty_slots--;
+
+ /* Initialize */
+ blk->start = NULL;
+ blk->size = 0;
+ blk->owner = NULL;
+
+ return blk;
+}
+
+static inline void release_slot(rh_info_t * info, rh_block_t * blk)
+{
+ list_add(&blk->list, &info->empty_list);
+ info->empty_slots++;
+}
+
+static void attach_free_block(rh_info_t * info, rh_block_t * blkn)
+{
+ rh_block_t *blk;
+ rh_block_t *before;
+ rh_block_t *after;
+ rh_block_t *next;
+ int size;
+ unsigned long s, e, bs, be;
+ struct list_head *l;
+
+ /* We assume that they are aligned properly */
+ size = blkn->size;
+ s = (unsigned long)blkn->start;
+ e = s + size;
+
+ /* Find the blocks immediately before and after the given one
+ * (if any) */
+ before = NULL;
+ after = NULL;
+ next = NULL;
+
+ list_for_each(l, &info->free_list) {
+ blk = list_entry(l, rh_block_t, list);
+
+ bs = (unsigned long)blk->start;
+ be = bs + blk->size;
+
+ if (next == NULL && s >= bs)
+ next = blk;
+
+ if (be == s)
+ before = blk;
+
+ if (e == bs)
+ after = blk;
+
+ /* If both are not null, break now */
+ if (before != NULL && after != NULL)
+ break;
+ }
+
+ /* Now check if they are really adjacent */
+ if (before != NULL && s != (unsigned long)before->start + before->size)
+ before = NULL;
+
+ if (after != NULL && e != (unsigned long)after->start)
+ after = NULL;
+
+ /* No coalescing; list insert and return */
+ if (before == NULL && after == NULL) {
+
+ if (next != NULL)
+ list_add(&blkn->list, &next->list);
+ else
+ list_add(&blkn->list, &info->free_list);
+
+ return;
+ }
+
+ /* We don't need it anymore */
+ release_slot(info, blkn);
+
+ /* Grow the before block */
+ if (before != NULL && after == NULL) {
+ before->size += size;
+ return;
+ }
+
+ /* Grow the after block backwards */
+ if (before == NULL && after != NULL) {
+ after->start = (int8_t *)after->start - size;
+ after->size += size;
+ return;
+ }
+
+ /* Grow the before block, and release the after block */
+ before->size += size + after->size;
+ list_del(&after->list);
+ release_slot(info, after);
+}
+
+static void attach_taken_block(rh_info_t * info, rh_block_t * blkn)
+{
+ rh_block_t *blk;
+ struct list_head *l;
+
+ /* Find the block immediately before the given one (if any) */
+ list_for_each(l, &info->taken_list) {
+ blk = list_entry(l, rh_block_t, list);
+ if (blk->start > blkn->start) {
+ list_add_tail(&blkn->list, &blk->list);
+ return;
+ }
+ }
+
+ list_add_tail(&blkn->list, &info->taken_list);
+}
+
+/*
+ * Create a remote heap dynamically. Note that no memory for the blocks
+ * are allocated. It will upon the first allocation
+ */
+rh_info_t *rh_create(unsigned int alignment)
+{
+ rh_info_t *info;
+
+ /* Alignment must be a power of two */
+ if ((alignment & (alignment - 1)) != 0)
+ return ERR_PTR(-EINVAL);
+
+ info = kmalloc(sizeof(*info), GFP_KERNEL);
+ if (info == NULL)
+ return ERR_PTR(-ENOMEM);
+
+ info->alignment = alignment;
+
+ /* Initially everything as empty */
+ info->block = NULL;
+ info->max_blocks = 0;
+ info->empty_slots = 0;
+ info->flags = 0;
+
+ INIT_LIST_HEAD(&info->empty_list);
+ INIT_LIST_HEAD(&info->free_list);
+ INIT_LIST_HEAD(&info->taken_list);
+
+ return info;
+}
+
+/*
+ * Destroy a dynamically created remote heap. Deallocate only if the areas
+ * are not static
+ */
+void rh_destroy(rh_info_t * info)
+{
+ if ((info->flags & RHIF_STATIC_BLOCK) == 0 && info->block != NULL)
+ kfree(info->block);
+
+ if ((info->flags & RHIF_STATIC_INFO) == 0)
+ kfree(info);
+}
+
+/*
+ * Initialize in place a remote heap info block. This is needed to support
+ * operation very early in the startup of the kernel, when it is not yet safe
+ * to call kmalloc.
+ */
+void rh_init(rh_info_t * info, unsigned int alignment, int max_blocks,
+ rh_block_t * block)
+{
+ int i;
+ rh_block_t *blk;
+
+ /* Alignment must be a power of two */
+ if ((alignment & (alignment - 1)) != 0)
+ return;
+
+ info->alignment = alignment;
+
+ /* Initially everything as empty */
+ info->block = block;
+ info->max_blocks = max_blocks;
+ info->empty_slots = max_blocks;
+ info->flags = RHIF_STATIC_INFO | RHIF_STATIC_BLOCK;
+
+ INIT_LIST_HEAD(&info->empty_list);
+ INIT_LIST_HEAD(&info->free_list);
+ INIT_LIST_HEAD(&info->taken_list);
+
+ /* Add all new blocks to the free list */
+ for (i = 0, blk = block; i < max_blocks; i++, blk++)
+ list_add(&blk->list, &info->empty_list);
+}
+
+/* Attach a free memory region, coalesces regions if adjuscent */
+int rh_attach_region(rh_info_t * info, void *start, int size)
+{
+ rh_block_t *blk;
+ unsigned long s, e, m;
+ int r;
+
+ /* The region must be aligned */
+ s = (unsigned long)start;
+ e = s + size;
+ m = info->alignment - 1;
+
+ /* Round start up */
+ s = (s + m) & ~m;
+
+ /* Round end down */
+ e = e & ~m;
+
+ /* Take final values */
+ start = (void *)s;
+ size = (int)(e - s);
+
+ /* Grow the blocks, if needed */
+ r = assure_empty(info, 1);
+ if (r < 0)
+ return r;
+
+ blk = get_slot(info);
+ blk->start = start;
+ blk->size = size;
+ blk->owner = NULL;
+
+ attach_free_block(info, blk);
+
+ return 0;
+}
+
+/* Detatch given address range, splits free block if needed. */
+void *rh_detach_region(rh_info_t * info, void *start, int size)
+{
+ struct list_head *l;
+ rh_block_t *blk, *newblk;
+ unsigned long s, e, m, bs, be;
+
+ /* Validate size */
+ if (size <= 0)
+ return ERR_PTR(-EINVAL);
+
+ /* The region must be aligned */
+ s = (unsigned long)start;
+ e = s + size;
+ m = info->alignment - 1;
+
+ /* Round start up */
+ s = (s + m) & ~m;
+
+ /* Round end down */
+ e = e & ~m;
+
+ if (assure_empty(info, 1) < 0)
+ return ERR_PTR(-ENOMEM);
+
+ blk = NULL;
+ list_for_each(l, &info->free_list) {
+ blk = list_entry(l, rh_block_t, list);
+ /* The range must lie entirely inside one free block */
+ bs = (unsigned long)blk->start;
+ be = (unsigned long)blk->start + blk->size;
+ if (s >= bs && e <= be)
+ break;
+ blk = NULL;
+ }
+
+ if (blk == NULL)
+ return ERR_PTR(-ENOMEM);
+
+ /* Perfect fit */
+ if (bs == s && be == e) {
+ /* Delete from free list, release slot */
+ list_del(&blk->list);
+ release_slot(info, blk);
+ return (void *)s;
+ }
+
+ /* blk still in free list, with updated start and/or size */
+ if (bs == s || be == e) {
+ if (bs == s)
+ blk->start = (int8_t *)blk->start + size;
+ blk->size -= size;
+
+ } else {
+ /* The front free fragment */
+ blk->size = s - bs;
+
+ /* the back free fragment */
+ newblk = get_slot(info);
+ newblk->start = (void *)e;
+ newblk->size = be - e;
+
+ list_add(&newblk->list, &blk->list);
+ }
+
+ return (void *)s;
+}
+
+void *rh_alloc(rh_info_t * info, int size, const char *owner)
+{
+ struct list_head *l;
+ rh_block_t *blk;
+ rh_block_t *newblk;
+ void *start;
+
+ /* Validate size */
+ if (size <= 0)
+ return ERR_PTR(-EINVAL);
+
+ /* Align to configured alignment */
+ size = (size + (info->alignment - 1)) & ~(info->alignment - 1);
+
+ if (assure_empty(info, 1) < 0)
+ return ERR_PTR(-ENOMEM);
+
+ blk = NULL;
+ list_for_each(l, &info->free_list) {
+ blk = list_entry(l, rh_block_t, list);
+ if (size <= blk->size)
+ break;
+ blk = NULL;
+ }
+
+ if (blk == NULL)
+ return ERR_PTR(-ENOMEM);
+
+ /* Just fits */
+ if (blk->size == size) {
+ /* Move from free list to taken list */
+ list_del(&blk->list);
+ blk->owner = owner;
+ start = blk->start;
+
+ attach_taken_block(info, blk);
+
+ return start;
+ }
+
+ newblk = get_slot(info);
+ newblk->start = blk->start;
+ newblk->size = size;
+ newblk->owner = owner;
+
+ /* blk still in free list, with updated start, size */
+ blk->start = (int8_t *)blk->start + size;
+ blk->size -= size;
+
+ start = newblk->start;
+
+ attach_taken_block(info, newblk);
+
+ return start;
+}
+
+/* allocate at precisely the given address */
+void *rh_alloc_fixed(rh_info_t * info, void *start, int size, const char *owner)
+{
+ struct list_head *l;
+ rh_block_t *blk, *newblk1, *newblk2;
+ unsigned long s, e, m, bs, be;
+
+ /* Validate size */
+ if (size <= 0)
+ return ERR_PTR(-EINVAL);
+
+ /* The region must be aligned */
+ s = (unsigned long)start;
+ e = s + size;
+ m = info->alignment - 1;
+
+ /* Round start up */
+ s = (s + m) & ~m;
+
+ /* Round end down */
+ e = e & ~m;
+
+ if (assure_empty(info, 2) < 0)
+ return ERR_PTR(-ENOMEM);
+
+ blk = NULL;
+ list_for_each(l, &info->free_list) {
+ blk = list_entry(l, rh_block_t, list);
+ /* The range must lie entirely inside one free block */
+ bs = (unsigned long)blk->start;
+ be = (unsigned long)blk->start + blk->size;
+ if (s >= bs && e <= be)
+ break;
+ }
+
+ if (blk == NULL)
+ return ERR_PTR(-ENOMEM);
+
+ /* Perfect fit */
+ if (bs == s && be == e) {
+ /* Move from free list to taken list */
+ list_del(&blk->list);
+ blk->owner = owner;
+
+ start = blk->start;
+ attach_taken_block(info, blk);
+
+ return start;
+
+ }
+
+ /* blk still in free list, with updated start and/or size */
+ if (bs == s || be == e) {
+ if (bs == s)
+ blk->start = (int8_t *)blk->start + size;
+ blk->size -= size;
+
+ } else {
+ /* The front free fragment */
+ blk->size = s - bs;
+
+ /* The back free fragment */
+ newblk2 = get_slot(info);
+ newblk2->start = (void *)e;
+ newblk2->size = be - e;
+
+ list_add(&newblk2->list, &blk->list);
+ }
+
+ newblk1 = get_slot(info);
+ newblk1->start = (void *)s;
+ newblk1->size = e - s;
+ newblk1->owner = owner;
+
+ start = newblk1->start;
+ attach_taken_block(info, newblk1);
+
+ return start;
+}
+
+int rh_free(rh_info_t * info, void *start)
+{
+ rh_block_t *blk, *blk2;
+ struct list_head *l;
+ int size;
+
+ /* Linear search for block */
+ blk = NULL;
+ list_for_each(l, &info->taken_list) {
+ blk2 = list_entry(l, rh_block_t, list);
+ if (start < blk2->start)
+ break;
+ blk = blk2;
+ }
+
+ if (blk == NULL || start > (blk->start + blk->size))
+ return -EINVAL;
+
+ /* Remove from taken list */
+ list_del(&blk->list);
+
+ /* Get size of freed block */
+ size = blk->size;
+ attach_free_block(info, blk);
+
+ return size;
+}
+
+int rh_get_stats(rh_info_t * info, int what, int max_stats, rh_stats_t * stats)
+{
+ rh_block_t *blk;
+ struct list_head *l;
+ struct list_head *h;
+ int nr;
+
+ switch (what) {
+
+ case RHGS_FREE:
+ h = &info->free_list;
+ break;
+
+ case RHGS_TAKEN:
+ h = &info->taken_list;
+ break;
+
+ default:
+ return -EINVAL;
+ }
+
+ /* Linear search for block */
+ nr = 0;
+ list_for_each(l, h) {
+ blk = list_entry(l, rh_block_t, list);
+ if (stats != NULL && nr < max_stats) {
+ stats->start = blk->start;
+ stats->size = blk->size;
+ stats->owner = blk->owner;
+ stats++;
+ }
+ nr++;
+ }
+
+ return nr;
+}
+
+int rh_set_owner(rh_info_t * info, void *start, const char *owner)
+{
+ rh_block_t *blk, *blk2;
+ struct list_head *l;
+ int size;
+
+ /* Linear search for block */
+ blk = NULL;
+ list_for_each(l, &info->taken_list) {
+ blk2 = list_entry(l, rh_block_t, list);
+ if (start < blk2->start)
+ break;
+ blk = blk2;
+ }
+
+ if (blk == NULL || start > (blk->start + blk->size))
+ return -EINVAL;
+
+ blk->owner = owner;
+ size = blk->size;
+
+ return size;
+}
+
+void rh_dump(rh_info_t * info)
+{
+ static rh_stats_t st[32]; /* XXX maximum 32 blocks */
+ int maxnr;
+ int i, nr;
+
+ maxnr = sizeof(st) / sizeof(st[0]);
+
+ printk(KERN_INFO
+ "info @0x%p (%d slots empty / %d max)\n",
+ info, info->empty_slots, info->max_blocks);
+
+ printk(KERN_INFO " Free:\n");
+ nr = rh_get_stats(info, RHGS_FREE, maxnr, st);
+ if (nr > maxnr)
+ nr = maxnr;
+ for (i = 0; i < nr; i++)
+ printk(KERN_INFO
+ " 0x%p-0x%p (%u)\n",
+ st[i].start, (int8_t *) st[i].start + st[i].size,
+ st[i].size);
+ printk(KERN_INFO "\n");
+
+ printk(KERN_INFO " Taken:\n");
+ nr = rh_get_stats(info, RHGS_TAKEN, maxnr, st);
+ if (nr > maxnr)
+ nr = maxnr;
+ for (i = 0; i < nr; i++)
+ printk(KERN_INFO
+ " 0x%p-0x%p (%u) %s\n",
+ st[i].start, (int8_t *) st[i].start + st[i].size,
+ st[i].size, st[i].owner != NULL ? st[i].owner : "");
+ printk(KERN_INFO "\n");
+}
+
+void rh_dump_blk(rh_info_t * info, rh_block_t * blk)
+{
+ printk(KERN_INFO
+ "blk @0x%p: 0x%p-0x%p (%u)\n",
+ blk, blk->start, (int8_t *) blk->start + blk->size, blk->size);
+}
diff --git a/arch/ppc/lib/strcase.c b/arch/ppc/lib/strcase.c
new file mode 100644
index 0000000..36b5210
--- /dev/null
+++ b/arch/ppc/lib/strcase.c
@@ -0,0 +1,23 @@
+#include <linux/ctype.h>
+
+int strcasecmp(const char *s1, const char *s2)
+{
+ int c1, c2;
+
+ do {
+ c1 = tolower(*s1++);
+ c2 = tolower(*s2++);
+ } while (c1 == c2 && c1 != 0);
+ return c1 - c2;
+}
+
+int strncasecmp(const char *s1, const char *s2, int n)
+{
+ int c1, c2;
+
+ do {
+ c1 = tolower(*s1++);
+ c2 = tolower(*s2++);
+ } while ((--n > 0) && c1 == c2 && c1 != 0);
+ return c1 - c2;
+}
diff --git a/arch/ppc/lib/string.S b/arch/ppc/lib/string.S
new file mode 100644
index 0000000..8d08a2e
--- /dev/null
+++ b/arch/ppc/lib/string.S
@@ -0,0 +1,716 @@
+/*
+ * String handling functions for PowerPC.
+ *
+ * Copyright (C) 1996 Paul Mackerras.
+ *
+ * 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.
+ */
+#include <linux/config.h>
+#include <asm/processor.h>
+#include <asm/cache.h>
+#include <asm/errno.h>
+#include <asm/ppc_asm.h>
+
+#define COPY_16_BYTES \
+ lwz r7,4(r4); \
+ lwz r8,8(r4); \
+ lwz r9,12(r4); \
+ lwzu r10,16(r4); \
+ stw r7,4(r6); \
+ stw r8,8(r6); \
+ stw r9,12(r6); \
+ stwu r10,16(r6)
+
+#define COPY_16_BYTES_WITHEX(n) \
+8 ## n ## 0: \
+ lwz r7,4(r4); \
+8 ## n ## 1: \
+ lwz r8,8(r4); \
+8 ## n ## 2: \
+ lwz r9,12(r4); \
+8 ## n ## 3: \
+ lwzu r10,16(r4); \
+8 ## n ## 4: \
+ stw r7,4(r6); \
+8 ## n ## 5: \
+ stw r8,8(r6); \
+8 ## n ## 6: \
+ stw r9,12(r6); \
+8 ## n ## 7: \
+ stwu r10,16(r6)
+
+#define COPY_16_BYTES_EXCODE(n) \
+9 ## n ## 0: \
+ addi r5,r5,-(16 * n); \
+ b 104f; \
+9 ## n ## 1: \
+ addi r5,r5,-(16 * n); \
+ b 105f; \
+.section __ex_table,"a"; \
+ .align 2; \
+ .long 8 ## n ## 0b,9 ## n ## 0b; \
+ .long 8 ## n ## 1b,9 ## n ## 0b; \
+ .long 8 ## n ## 2b,9 ## n ## 0b; \
+ .long 8 ## n ## 3b,9 ## n ## 0b; \
+ .long 8 ## n ## 4b,9 ## n ## 1b; \
+ .long 8 ## n ## 5b,9 ## n ## 1b; \
+ .long 8 ## n ## 6b,9 ## n ## 1b; \
+ .long 8 ## n ## 7b,9 ## n ## 1b; \
+ .text
+
+ .text
+ .stabs "arch/ppc/lib/",N_SO,0,0,0f
+ .stabs "string.S",N_SO,0,0,0f
+
+CACHELINE_BYTES = L1_CACHE_LINE_SIZE
+LG_CACHELINE_BYTES = LG_L1_CACHE_LINE_SIZE
+CACHELINE_MASK = (L1_CACHE_LINE_SIZE-1)
+
+_GLOBAL(strcpy)
+ addi r5,r3,-1
+ addi r4,r4,-1
+1: lbzu r0,1(r4)
+ cmpwi 0,r0,0
+ stbu r0,1(r5)
+ bne 1b
+ blr
+
+/* This clears out any unused part of the destination buffer,
+ just as the libc version does. -- paulus */
+_GLOBAL(strncpy)
+ cmpwi 0,r5,0
+ beqlr
+ mtctr r5
+ addi r6,r3,-1
+ addi r4,r4,-1
+1: lbzu r0,1(r4)
+ cmpwi 0,r0,0
+ stbu r0,1(r6)
+ bdnzf 2,1b /* dec ctr, branch if ctr != 0 && !cr0.eq */
+ bnelr /* if we didn't hit a null char, we're done */
+ mfctr r5
+ cmpwi 0,r5,0 /* any space left in destination buffer? */
+ beqlr /* we know r0 == 0 here */
+2: stbu r0,1(r6) /* clear it out if so */
+ bdnz 2b
+ blr
+
+_GLOBAL(strcat)
+ addi r5,r3,-1
+ addi r4,r4,-1
+1: lbzu r0,1(r5)
+ cmpwi 0,r0,0
+ bne 1b
+ addi r5,r5,-1
+1: lbzu r0,1(r4)
+ cmpwi 0,r0,0
+ stbu r0,1(r5)
+ bne 1b
+ blr
+
+_GLOBAL(strcmp)
+ addi r5,r3,-1
+ addi r4,r4,-1
+1: lbzu r3,1(r5)
+ cmpwi 1,r3,0
+ lbzu r0,1(r4)
+ subf. r3,r0,r3
+ beqlr 1
+ beq 1b
+ blr
+
+_GLOBAL(strlen)
+ addi r4,r3,-1
+1: lbzu r0,1(r4)
+ cmpwi 0,r0,0
+ bne 1b
+ subf r3,r3,r4
+ blr
+
+/*
+ * Use dcbz on the complete cache lines in the destination
+ * to set them to zero. This requires that the destination
+ * area is cacheable. -- paulus
+ */
+_GLOBAL(cacheable_memzero)
+ mr r5,r4
+ li r4,0
+ addi r6,r3,-4
+ cmplwi 0,r5,4
+ blt 7f
+ stwu r4,4(r6)
+ beqlr
+ andi. r0,r6,3
+ add r5,r0,r5
+ subf r6,r0,r6
+ clrlwi r7,r6,32-LG_CACHELINE_BYTES
+ add r8,r7,r5
+ srwi r9,r8,LG_CACHELINE_BYTES
+ addic. r9,r9,-1 /* total number of complete cachelines */
+ ble 2f
+ xori r0,r7,CACHELINE_MASK & ~3
+ srwi. r0,r0,2
+ beq 3f
+ mtctr r0
+4: stwu r4,4(r6)
+ bdnz 4b
+3: mtctr r9
+ li r7,4
+#if !defined(CONFIG_8xx)
+10: dcbz r7,r6
+#else
+10: stw r4, 4(r6)
+ stw r4, 8(r6)
+ stw r4, 12(r6)
+ stw r4, 16(r6)
+#if CACHE_LINE_SIZE >= 32
+ stw r4, 20(r6)
+ stw r4, 24(r6)
+ stw r4, 28(r6)
+ stw r4, 32(r6)
+#endif /* CACHE_LINE_SIZE */
+#endif
+ addi r6,r6,CACHELINE_BYTES
+ bdnz 10b
+ clrlwi r5,r8,32-LG_CACHELINE_BYTES
+ addi r5,r5,4
+2: srwi r0,r5,2
+ mtctr r0
+ bdz 6f
+1: stwu r4,4(r6)
+ bdnz 1b
+6: andi. r5,r5,3
+7: cmpwi 0,r5,0
+ beqlr
+ mtctr r5
+ addi r6,r6,3
+8: stbu r4,1(r6)
+ bdnz 8b
+ blr
+
+_GLOBAL(memset)
+ rlwimi r4,r4,8,16,23
+ rlwimi r4,r4,16,0,15
+ addi r6,r3,-4
+ cmplwi 0,r5,4
+ blt 7f
+ stwu r4,4(r6)
+ beqlr
+ andi. r0,r6,3
+ add r5,r0,r5
+ subf r6,r0,r6
+ srwi r0,r5,2
+ mtctr r0
+ bdz 6f
+1: stwu r4,4(r6)
+ bdnz 1b
+6: andi. r5,r5,3
+7: cmpwi 0,r5,0
+ beqlr
+ mtctr r5
+ addi r6,r6,3
+8: stbu r4,1(r6)
+ bdnz 8b
+ blr
+
+/*
+ * This version uses dcbz on the complete cache lines in the
+ * destination area to reduce memory traffic. This requires that
+ * the destination area is cacheable.
+ * We only use this version if the source and dest don't overlap.
+ * -- paulus.
+ */
+_GLOBAL(cacheable_memcpy)
+ add r7,r3,r5 /* test if the src & dst overlap */
+ add r8,r4,r5
+ cmplw 0,r4,r7
+ cmplw 1,r3,r8
+ crand 0,0,4 /* cr0.lt &= cr1.lt */
+ blt memcpy /* if regions overlap */
+
+ addi r4,r4,-4
+ addi r6,r3,-4
+ neg r0,r3
+ andi. r0,r0,CACHELINE_MASK /* # bytes to start of cache line */
+ beq 58f
+
+ cmplw 0,r5,r0 /* is this more than total to do? */
+ blt 63f /* if not much to do */
+ andi. r8,r0,3 /* get it word-aligned first */
+ subf r5,r0,r5
+ mtctr r8
+ beq+ 61f
+70: lbz r9,4(r4) /* do some bytes */
+ stb r9,4(r6)
+ addi r4,r4,1
+ addi r6,r6,1
+ bdnz 70b
+61: srwi. r0,r0,2
+ mtctr r0
+ beq 58f
+72: lwzu r9,4(r4) /* do some words */
+ stwu r9,4(r6)
+ bdnz 72b
+
+58: srwi. r0,r5,LG_CACHELINE_BYTES /* # complete cachelines */
+ clrlwi r5,r5,32-LG_CACHELINE_BYTES
+ li r11,4
+ mtctr r0
+ beq 63f
+53:
+#if !defined(CONFIG_8xx)
+ dcbz r11,r6
+#endif
+ COPY_16_BYTES
+#if L1_CACHE_LINE_SIZE >= 32
+ COPY_16_BYTES
+#if L1_CACHE_LINE_SIZE >= 64
+ COPY_16_BYTES
+ COPY_16_BYTES
+#if L1_CACHE_LINE_SIZE >= 128
+ COPY_16_BYTES
+ COPY_16_BYTES
+ COPY_16_BYTES
+ COPY_16_BYTES
+#endif
+#endif
+#endif
+ bdnz 53b
+
+63: srwi. r0,r5,2
+ mtctr r0
+ beq 64f
+30: lwzu r0,4(r4)
+ stwu r0,4(r6)
+ bdnz 30b
+
+64: andi. r0,r5,3
+ mtctr r0
+ beq+ 65f
+40: lbz r0,4(r4)
+ stb r0,4(r6)
+ addi r4,r4,1
+ addi r6,r6,1
+ bdnz 40b
+65: blr
+
+_GLOBAL(memmove)
+ cmplw 0,r3,r4
+ bgt backwards_memcpy
+ /* fall through */
+
+_GLOBAL(memcpy)
+ srwi. r7,r5,3
+ addi r6,r3,-4
+ addi r4,r4,-4
+ beq 2f /* if less than 8 bytes to do */
+ andi. r0,r6,3 /* get dest word aligned */
+ mtctr r7
+ bne 5f
+1: lwz r7,4(r4)
+ lwzu r8,8(r4)
+ stw r7,4(r6)
+ stwu r8,8(r6)
+ bdnz 1b
+ andi. r5,r5,7
+2: cmplwi 0,r5,4
+ blt 3f
+ lwzu r0,4(r4)
+ addi r5,r5,-4
+ stwu r0,4(r6)
+3: cmpwi 0,r5,0
+ beqlr
+ mtctr r5
+ addi r4,r4,3
+ addi r6,r6,3
+4: lbzu r0,1(r4)
+ stbu r0,1(r6)
+ bdnz 4b
+ blr
+5: subfic r0,r0,4
+ mtctr r0
+6: lbz r7,4(r4)
+ addi r4,r4,1
+ stb r7,4(r6)
+ addi r6,r6,1
+ bdnz 6b
+ subf r5,r0,r5
+ rlwinm. r7,r5,32-3,3,31
+ beq 2b
+ mtctr r7
+ b 1b
+
+_GLOBAL(backwards_memcpy)
+ rlwinm. r7,r5,32-3,3,31 /* r0 = r5 >> 3 */
+ add r6,r3,r5
+ add r4,r4,r5
+ beq 2f
+ andi. r0,r6,3
+ mtctr r7
+ bne 5f
+1: lwz r7,-4(r4)
+ lwzu r8,-8(r4)
+ stw r7,-4(r6)
+ stwu r8,-8(r6)
+ bdnz 1b
+ andi. r5,r5,7
+2: cmplwi 0,r5,4
+ blt 3f
+ lwzu r0,-4(r4)
+ subi r5,r5,4
+ stwu r0,-4(r6)
+3: cmpwi 0,r5,0
+ beqlr
+ mtctr r5
+4: lbzu r0,-1(r4)
+ stbu r0,-1(r6)
+ bdnz 4b
+ blr
+5: mtctr r0
+6: lbzu r7,-1(r4)
+ stbu r7,-1(r6)
+ bdnz 6b
+ subf r5,r0,r5
+ rlwinm. r7,r5,32-3,3,31
+ beq 2b
+ mtctr r7
+ b 1b
+
+_GLOBAL(memcmp)
+ cmpwi 0,r5,0
+ ble- 2f
+ mtctr r5
+ addi r6,r3,-1
+ addi r4,r4,-1
+1: lbzu r3,1(r6)
+ lbzu r0,1(r4)
+ subf. r3,r0,r3
+ bdnzt 2,1b
+ blr
+2: li r3,0
+ blr
+
+_GLOBAL(memchr)
+ cmpwi 0,r5,0
+ ble- 2f
+ mtctr r5
+ addi r3,r3,-1
+1: lbzu r0,1(r3)
+ cmpw 0,r0,r4
+ bdnzf 2,1b
+ beqlr
+2: li r3,0
+ blr
+
+_GLOBAL(__copy_tofrom_user)
+ addi r4,r4,-4
+ addi r6,r3,-4
+ neg r0,r3
+ andi. r0,r0,CACHELINE_MASK /* # bytes to start of cache line */
+ beq 58f
+
+ cmplw 0,r5,r0 /* is this more than total to do? */
+ blt 63f /* if not much to do */
+ andi. r8,r0,3 /* get it word-aligned first */
+ mtctr r8
+ beq+ 61f
+70: lbz r9,4(r4) /* do some bytes */
+71: stb r9,4(r6)
+ addi r4,r4,1
+ addi r6,r6,1
+ bdnz 70b
+61: subf r5,r0,r5
+ srwi. r0,r0,2
+ mtctr r0
+ beq 58f
+72: lwzu r9,4(r4) /* do some words */
+73: stwu r9,4(r6)
+ bdnz 72b
+
+ .section __ex_table,"a"
+ .align 2
+ .long 70b,100f
+ .long 71b,101f
+ .long 72b,102f
+ .long 73b,103f
+ .text
+
+58: srwi. r0,r5,LG_CACHELINE_BYTES /* # complete cachelines */
+ clrlwi r5,r5,32-LG_CACHELINE_BYTES
+ li r11,4
+ beq 63f
+
+#ifdef CONFIG_8xx
+ /* Don't use prefetch on 8xx */
+ mtctr r0
+53: COPY_16_BYTES_WITHEX(0)
+ bdnz 53b
+
+#else /* not CONFIG_8xx */
+ /* Here we decide how far ahead to prefetch the source */
+ li r3,4
+ cmpwi r0,1
+ li r7,0
+ ble 114f
+ li r7,1
+#if MAX_COPY_PREFETCH > 1
+ /* Heuristically, for large transfers we prefetch
+ MAX_COPY_PREFETCH cachelines ahead. For small transfers
+ we prefetch 1 cacheline ahead. */
+ cmpwi r0,MAX_COPY_PREFETCH
+ ble 112f
+ li r7,MAX_COPY_PREFETCH
+112: mtctr r7
+111: dcbt r3,r4
+ addi r3,r3,CACHELINE_BYTES
+ bdnz 111b
+#else
+ dcbt r3,r4
+ addi r3,r3,CACHELINE_BYTES
+#endif /* MAX_COPY_PREFETCH > 1 */
+
+114: subf r8,r7,r0
+ mr r0,r7
+ mtctr r8
+
+53: dcbt r3,r4
+54: dcbz r11,r6
+ .section __ex_table,"a"
+ .align 2
+ .long 54b,105f
+ .text
+/* the main body of the cacheline loop */
+ COPY_16_BYTES_WITHEX(0)
+#if L1_CACHE_LINE_SIZE >= 32
+ COPY_16_BYTES_WITHEX(1)
+#if L1_CACHE_LINE_SIZE >= 64
+ COPY_16_BYTES_WITHEX(2)
+ COPY_16_BYTES_WITHEX(3)
+#if L1_CACHE_LINE_SIZE >= 128
+ COPY_16_BYTES_WITHEX(4)
+ COPY_16_BYTES_WITHEX(5)
+ COPY_16_BYTES_WITHEX(6)
+ COPY_16_BYTES_WITHEX(7)
+#endif
+#endif
+#endif
+ bdnz 53b
+ cmpwi r0,0
+ li r3,4
+ li r7,0
+ bne 114b
+#endif /* CONFIG_8xx */
+
+63: srwi. r0,r5,2
+ mtctr r0
+ beq 64f
+30: lwzu r0,4(r4)
+31: stwu r0,4(r6)
+ bdnz 30b
+
+64: andi. r0,r5,3
+ mtctr r0
+ beq+ 65f
+40: lbz r0,4(r4)
+41: stb r0,4(r6)
+ addi r4,r4,1
+ addi r6,r6,1
+ bdnz 40b
+65: li r3,0
+ blr
+
+/* read fault, initial single-byte copy */
+100: li r9,0
+ b 90f
+/* write fault, initial single-byte copy */
+101: li r9,1
+90: subf r5,r8,r5
+ li r3,0
+ b 99f
+/* read fault, initial word copy */
+102: li r9,0
+ b 91f
+/* write fault, initial word copy */
+103: li r9,1
+91: li r3,2
+ b 99f
+
+/*
+ * this stuff handles faults in the cacheline loop and branches to either
+ * 104f (if in read part) or 105f (if in write part), after updating r5
+ */
+ COPY_16_BYTES_EXCODE(0)
+#if L1_CACHE_LINE_SIZE >= 32
+ COPY_16_BYTES_EXCODE(1)
+#if L1_CACHE_LINE_SIZE >= 64
+ COPY_16_BYTES_EXCODE(2)
+ COPY_16_BYTES_EXCODE(3)
+#if L1_CACHE_LINE_SIZE >= 128
+ COPY_16_BYTES_EXCODE(4)
+ COPY_16_BYTES_EXCODE(5)
+ COPY_16_BYTES_EXCODE(6)
+ COPY_16_BYTES_EXCODE(7)
+#endif
+#endif
+#endif
+
+/* read fault in cacheline loop */
+104: li r9,0
+ b 92f
+/* fault on dcbz (effectively a write fault) */
+/* or write fault in cacheline loop */
+105: li r9,1
+92: li r3,LG_CACHELINE_BYTES
+ b 99f
+/* read fault in final word loop */
+108: li r9,0
+ b 93f
+/* write fault in final word loop */
+109: li r9,1
+93: andi. r5,r5,3
+ li r3,2
+ b 99f
+/* read fault in final byte loop */
+110: li r9,0
+ b 94f
+/* write fault in final byte loop */
+111: li r9,1
+94: li r5,0
+ li r3,0
+/*
+ * At this stage the number of bytes not copied is
+ * r5 + (ctr << r3), and r9 is 0 for read or 1 for write.
+ */
+99: mfctr r0
+ slw r3,r0,r3
+ add. r3,r3,r5
+ beq 120f /* shouldn't happen */
+ cmpwi 0,r9,0
+ bne 120f
+/* for a read fault, first try to continue the copy one byte at a time */
+ mtctr r3
+130: lbz r0,4(r4)
+131: stb r0,4(r6)
+ addi r4,r4,1
+ addi r6,r6,1
+ bdnz 130b
+/* then clear out the destination: r3 bytes starting at 4(r6) */
+132: mfctr r3
+ srwi. r0,r3,2
+ li r9,0
+ mtctr r0
+ beq 113f
+112: stwu r9,4(r6)
+ bdnz 112b
+113: andi. r0,r3,3
+ mtctr r0
+ beq 120f
+114: stb r9,4(r6)
+ addi r6,r6,1
+ bdnz 114b
+120: blr
+
+ .section __ex_table,"a"
+ .align 2
+ .long 30b,108b
+ .long 31b,109b
+ .long 40b,110b
+ .long 41b,111b
+ .long 130b,132b
+ .long 131b,120b
+ .long 112b,120b
+ .long 114b,120b
+ .text
+
+_GLOBAL(__clear_user)
+ addi r6,r3,-4
+ li r3,0
+ li r5,0
+ cmplwi 0,r4,4
+ blt 7f
+ /* clear a single word */
+11: stwu r5,4(r6)
+ beqlr
+ /* clear word sized chunks */
+ andi. r0,r6,3
+ add r4,r0,r4
+ subf r6,r0,r6
+ srwi r0,r4,2
+ andi. r4,r4,3
+ mtctr r0
+ bdz 7f
+1: stwu r5,4(r6)
+ bdnz 1b
+ /* clear byte sized chunks */
+7: cmpwi 0,r4,0
+ beqlr
+ mtctr r4
+ addi r6,r6,3
+8: stbu r5,1(r6)
+ bdnz 8b
+ blr
+90: mr r3,r4
+ blr
+91: mfctr r3
+ slwi r3,r3,2
+ add r3,r3,r4
+ blr
+92: mfctr r3
+ blr
+
+ .section __ex_table,"a"
+ .align 2
+ .long 11b,90b
+ .long 1b,91b
+ .long 8b,92b
+ .text
+
+_GLOBAL(__strncpy_from_user)
+ addi r6,r3,-1
+ addi r4,r4,-1
+ cmpwi 0,r5,0
+ beq 2f
+ mtctr r5
+1: lbzu r0,1(r4)
+ cmpwi 0,r0,0
+ stbu r0,1(r6)
+ bdnzf 2,1b /* dec ctr, branch if ctr != 0 && !cr0.eq */
+ beq 3f
+2: addi r6,r6,1
+3: subf r3,r3,r6
+ blr
+99: li r3,-EFAULT
+ blr
+
+ .section __ex_table,"a"
+ .align 2
+ .long 1b,99b
+ .text
+
+/* r3 = str, r4 = len (> 0), r5 = top (highest addr) */
+_GLOBAL(__strnlen_user)
+ addi r7,r3,-1
+ subf r6,r7,r5 /* top+1 - str */
+ cmplw 0,r4,r6
+ bge 0f
+ mr r6,r4
+0: mtctr r6 /* ctr = min(len, top - str) */
+1: lbzu r0,1(r7) /* get next byte */
+ cmpwi 0,r0,0
+ bdnzf 2,1b /* loop if --ctr != 0 && byte != 0 */
+ addi r7,r7,1
+ subf r3,r3,r7 /* number of bytes we have looked at */
+ beqlr /* return if we found a 0 byte */
+ cmpw 0,r3,r4 /* did we look at all len bytes? */
+ blt 99f /* if not, must have hit top */
+ addi r3,r4,1 /* return len + 1 to indicate no null found */
+ blr
+99: li r3,0 /* bad address, return 0 */
+ blr
+
+ .section __ex_table,"a"
+ .align 2
+ .long 1b,99b
diff --git a/arch/ppc/math-emu/Makefile b/arch/ppc/math-emu/Makefile
new file mode 100644
index 0000000..754143e
--- /dev/null
+++ b/arch/ppc/math-emu/Makefile
@@ -0,0 +1,13 @@
+
+obj-y := math.o fmr.o lfd.o stfd.o
+
+obj-$(CONFIG_MATH_EMULATION) += fabs.o fadd.o fadds.o fcmpo.o fcmpu.o \
+ fctiw.o fctiwz.o fdiv.o fdivs.o \
+ fmadd.o fmadds.o fmsub.o fmsubs.o \
+ fmul.o fmuls.o fnabs.o fneg.o types.o \
+ fnmadd.o fnmadds.o fnmsub.o fnmsubs.o \
+ fres.o frsp.o frsqrte.o fsel.o lfs.o \
+ fsqrt.o fsqrts.o fsub.o fsubs.o \
+ mcrfs.o mffs.o mtfsb0.o mtfsb1.o \
+ mtfsf.o mtfsfi.o stfiwx.o stfs.o \
+ udivmodti4.o
diff --git a/arch/ppc/math-emu/double.h b/arch/ppc/math-emu/double.h
new file mode 100644
index 0000000..ffba8b6
--- /dev/null
+++ b/arch/ppc/math-emu/double.h
@@ -0,0 +1,129 @@
+/*
+ * Definitions for IEEE Double Precision
+ */
+
+#if _FP_W_TYPE_SIZE < 32
+#error "Here's a nickel kid. Go buy yourself a real computer."
+#endif
+
+#if _FP_W_TYPE_SIZE < 64
+#define _FP_FRACTBITS_D (2 * _FP_W_TYPE_SIZE)
+#else
+#define _FP_FRACTBITS_D _FP_W_TYPE_SIZE
+#endif
+
+#define _FP_FRACBITS_D 53
+#define _FP_FRACXBITS_D (_FP_FRACTBITS_D - _FP_FRACBITS_D)
+#define _FP_WFRACBITS_D (_FP_WORKBITS + _FP_FRACBITS_D)
+#define _FP_WFRACXBITS_D (_FP_FRACTBITS_D - _FP_WFRACBITS_D)
+#define _FP_EXPBITS_D 11
+#define _FP_EXPBIAS_D 1023
+#define _FP_EXPMAX_D 2047
+
+#define _FP_QNANBIT_D \
+ ((_FP_W_TYPE)1 << ((_FP_FRACBITS_D-2) % _FP_W_TYPE_SIZE))
+#define _FP_IMPLBIT_D \
+ ((_FP_W_TYPE)1 << ((_FP_FRACBITS_D-1) % _FP_W_TYPE_SIZE))
+#define _FP_OVERFLOW_D \
+ ((_FP_W_TYPE)1 << (_FP_WFRACBITS_D % _FP_W_TYPE_SIZE))
+
+#if _FP_W_TYPE_SIZE < 64
+
+union _FP_UNION_D
+{
+ double flt;
+ struct {
+#if __BYTE_ORDER == __BIG_ENDIAN
+ unsigned sign : 1;
+ unsigned exp : _FP_EXPBITS_D;
+ unsigned frac1 : _FP_FRACBITS_D - (_FP_IMPLBIT_D != 0) - _FP_W_TYPE_SIZE;
+ unsigned frac0 : _FP_W_TYPE_SIZE;
+#else
+ unsigned frac0 : _FP_W_TYPE_SIZE;
+ unsigned frac1 : _FP_FRACBITS_D - (_FP_IMPLBIT_D != 0) - _FP_W_TYPE_SIZE;
+ unsigned exp : _FP_EXPBITS_D;
+ unsigned sign : 1;
+#endif
+ } bits __attribute__((packed));
+};
+
+#define FP_DECL_D(X) _FP_DECL(2,X)
+#define FP_UNPACK_RAW_D(X,val) _FP_UNPACK_RAW_2(D,X,val)
+#define FP_PACK_RAW_D(val,X) _FP_PACK_RAW_2(D,val,X)
+
+#define FP_UNPACK_D(X,val) \
+ do { \
+ _FP_UNPACK_RAW_2(D,X,val); \
+ _FP_UNPACK_CANONICAL(D,2,X); \
+ } while (0)
+
+#define FP_PACK_D(val,X) \
+ do { \
+ _FP_PACK_CANONICAL(D,2,X); \
+ _FP_PACK_RAW_2(D,val,X); \
+ } while (0)
+
+#define FP_NEG_D(R,X) _FP_NEG(D,2,R,X)
+#define FP_ADD_D(R,X,Y) _FP_ADD(D,2,R,X,Y)
+#define FP_SUB_D(R,X,Y) _FP_SUB(D,2,R,X,Y)
+#define FP_MUL_D(R,X,Y) _FP_MUL(D,2,R,X,Y)
+#define FP_DIV_D(R,X,Y) _FP_DIV(D,2,R,X,Y)
+#define FP_SQRT_D(R,X) _FP_SQRT(D,2,R,X)
+
+#define FP_CMP_D(r,X,Y,un) _FP_CMP(D,2,r,X,Y,un)
+#define FP_CMP_EQ_D(r,X,Y) _FP_CMP_EQ(D,2,r,X,Y)
+
+#define FP_TO_INT_D(r,X,rsz,rsg) _FP_TO_INT(D,2,r,X,rsz,rsg)
+#define FP_FROM_INT_D(X,r,rs,rt) _FP_FROM_INT(D,2,X,r,rs,rt)
+
+#else
+
+union _FP_UNION_D
+{
+ double flt;
+ struct {
+#if __BYTE_ORDER == __BIG_ENDIAN
+ unsigned sign : 1;
+ unsigned exp : _FP_EXPBITS_D;
+ unsigned long frac : _FP_FRACBITS_D - (_FP_IMPLBIT_D != 0);
+#else
+ unsigned long frac : _FP_FRACBITS_D - (_FP_IMPLBIT_D != 0);
+ unsigned exp : _FP_EXPBITS_D;
+ unsigned sign : 1;
+#endif
+ } bits __attribute__((packed));
+};
+
+#define FP_DECL_D(X) _FP_DECL(1,X)
+#define FP_UNPACK_RAW_D(X,val) _FP_UNPACK_RAW_1(D,X,val)
+#define FP_PACK_RAW_D(val,X) _FP_PACK_RAW_1(D,val,X)
+
+#define FP_UNPACK_D(X,val) \
+ do { \
+ _FP_UNPACK_RAW_1(D,X,val); \
+ _FP_UNPACK_CANONICAL(D,1,X); \
+ } while (0)
+
+#define FP_PACK_D(val,X) \
+ do { \
+ _FP_PACK_CANONICAL(D,1,X); \
+ _FP_PACK_RAW_1(D,val,X); \
+ } while (0)
+
+#define FP_NEG_D(R,X) _FP_NEG(D,1,R,X)
+#define FP_ADD_D(R,X,Y) _FP_ADD(D,1,R,X,Y)
+#define FP_SUB_D(R,X,Y) _FP_SUB(D,1,R,X,Y)
+#define FP_MUL_D(R,X,Y) _FP_MUL(D,1,R,X,Y)
+#define FP_DIV_D(R,X,Y) _FP_DIV(D,1,R,X,Y)
+#define FP_SQRT_D(R,X) _FP_SQRT(D,1,R,X)
+
+/* The implementation of _FP_MUL_D and _FP_DIV_D should be chosen by
+ the target machine. */
+
+#define FP_CMP_D(r,X,Y,un) _FP_CMP(D,1,r,X,Y,un)
+#define FP_CMP_EQ_D(r,X,Y) _FP_CMP_EQ(D,1,r,X,Y)
+
+#define FP_TO_INT_D(r,X,rsz,rsg) _FP_TO_INT(D,1,r,X,rsz,rsg)
+#define FP_FROM_INT_D(X,r,rs,rt) _FP_FROM_INT(D,1,X,r,rs,rt)
+
+#endif /* W_TYPE_SIZE < 64 */
diff --git a/arch/ppc/math-emu/fabs.c b/arch/ppc/math-emu/fabs.c
new file mode 100644
index 0000000..41f0617
--- /dev/null
+++ b/arch/ppc/math-emu/fabs.c
@@ -0,0 +1,18 @@
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <asm/uaccess.h>
+
+int
+fabs(u32 *frD, u32 *frB)
+{
+ frD[0] = frB[0] & 0x7fffffff;
+ frD[1] = frB[1];
+
+#ifdef DEBUG
+ printk("%s: D %p, B %p: ", __FUNCTION__, frD, frB);
+ dump_double(frD);
+ printk("\n");
+#endif
+
+ return 0;
+}
diff --git a/arch/ppc/math-emu/fadd.c b/arch/ppc/math-emu/fadd.c
new file mode 100644
index 0000000..fc88364
--- /dev/null
+++ b/arch/ppc/math-emu/fadd.c
@@ -0,0 +1,38 @@
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <asm/uaccess.h>
+
+#include "soft-fp.h"
+#include "double.h"
+
+int
+fadd(void *frD, void *frA, void *frB)
+{
+ FP_DECL_D(A);
+ FP_DECL_D(B);
+ FP_DECL_D(R);
+ int ret = 0;
+
+#ifdef DEBUG
+ printk("%s: %p %p %p\n", __FUNCTION__, frD, frA, frB);
+#endif
+
+ __FP_UNPACK_D(A, frA);
+ __FP_UNPACK_D(B, frB);
+
+#ifdef DEBUG
+ printk("A: %ld %lu %lu %ld (%ld)\n", A_s, A_f1, A_f0, A_e, A_c);
+ printk("B: %ld %lu %lu %ld (%ld)\n", B_s, B_f1, B_f0, B_e, B_c);
+#endif
+
+ if (A_s != B_s && A_c == FP_CLS_INF && B_c == FP_CLS_INF)
+ ret |= EFLAG_VXISI;
+
+ FP_ADD_D(R, A, B);
+
+#ifdef DEBUG
+ printk("D: %ld %lu %lu %ld (%ld)\n", R_s, R_f1, R_f0, R_e, R_c);
+#endif
+
+ return (ret | __FP_PACK_D(frD, R));
+}
diff --git a/arch/ppc/math-emu/fadds.c b/arch/ppc/math-emu/fadds.c
new file mode 100644
index 0000000..93025b6
--- /dev/null
+++ b/arch/ppc/math-emu/fadds.c
@@ -0,0 +1,39 @@
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <asm/uaccess.h>
+
+#include "soft-fp.h"
+#include "double.h"
+#include "single.h"
+
+int
+fadds(void *frD, void *frA, void *frB)
+{
+ FP_DECL_D(A);
+ FP_DECL_D(B);
+ FP_DECL_D(R);
+ int ret = 0;
+
+#ifdef DEBUG
+ printk("%s: %p %p %p\n", __FUNCTION__, frD, frA, frB);
+#endif
+
+ __FP_UNPACK_D(A, frA);
+ __FP_UNPACK_D(B, frB);
+
+#ifdef DEBUG
+ printk("A: %ld %lu %lu %ld (%ld)\n", A_s, A_f1, A_f0, A_e, A_c);
+ printk("B: %ld %lu %lu %ld (%ld)\n", B_s, B_f1, B_f0, B_e, B_c);
+#endif
+
+ if (A_s != B_s && A_c == FP_CLS_INF && B_c == FP_CLS_INF)
+ ret |= EFLAG_VXISI;
+
+ FP_ADD_D(R, A, B);
+
+#ifdef DEBUG
+ printk("D: %ld %lu %lu %ld (%ld)\n", R_s, R_f1, R_f0, R_e, R_c);
+#endif
+
+ return (ret | __FP_PACK_DS(frD, R));
+}
diff --git a/arch/ppc/math-emu/fcmpo.c b/arch/ppc/math-emu/fcmpo.c
new file mode 100644
index 0000000..4efac39
--- /dev/null
+++ b/arch/ppc/math-emu/fcmpo.c
@@ -0,0 +1,46 @@
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <asm/uaccess.h>
+
+#include "soft-fp.h"
+#include "double.h"
+
+int
+fcmpo(u32 *ccr, int crfD, void *frA, void *frB)
+{
+ FP_DECL_D(A);
+ FP_DECL_D(B);
+ int code[4] = { (1 << 3), (1 << 1), (1 << 2), (1 << 0) };
+ long cmp;
+ int ret = 0;
+
+#ifdef DEBUG
+ printk("%s: %p (%08x) %d %p %p\n", __FUNCTION__, ccr, *ccr, crfD, frA, frB);
+#endif
+
+ __FP_UNPACK_D(A, frA);
+ __FP_UNPACK_D(B, frB);
+
+#ifdef DEBUG
+ printk("A: %ld %lu %lu %ld (%ld)\n", A_s, A_f1, A_f0, A_e, A_c);
+ printk("B: %ld %lu %lu %ld (%ld)\n", B_s, B_f1, B_f0, B_e, B_c);
+#endif
+
+ if (A_c == FP_CLS_NAN || B_c == FP_CLS_NAN)
+ ret |= EFLAG_VXVC;
+
+ FP_CMP_D(cmp, A, B, 2);
+ cmp = code[(cmp + 1) & 3];
+
+ __FPU_FPSCR &= ~(0x1f000);
+ __FPU_FPSCR |= (cmp << 12);
+
+ *ccr &= ~(15 << ((7 - crfD) << 2));
+ *ccr |= (cmp << ((7 - crfD) << 2));
+
+#ifdef DEBUG
+ printk("CR: %08x\n", *ccr);
+#endif
+
+ return ret;
+}
diff --git a/arch/ppc/math-emu/fcmpu.c b/arch/ppc/math-emu/fcmpu.c
new file mode 100644
index 0000000..b7e3317
--- /dev/null
+++ b/arch/ppc/math-emu/fcmpu.c
@@ -0,0 +1,42 @@
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <asm/uaccess.h>
+
+#include "soft-fp.h"
+#include "double.h"
+
+int
+fcmpu(u32 *ccr, int crfD, void *frA, void *frB)
+{
+ FP_DECL_D(A);
+ FP_DECL_D(B);
+ int code[4] = { (1 << 3), (1 << 1), (1 << 2), (1 << 0) };
+ long cmp;
+
+#ifdef DEBUG
+ printk("%s: %p (%08x) %d %p %p\n", __FUNCTION__, ccr, *ccr, crfD, frA, frB);
+#endif
+
+ __FP_UNPACK_D(A, frA);
+ __FP_UNPACK_D(B, frB);
+
+#ifdef DEBUG
+ printk("A: %ld %lu %lu %ld (%ld)\n", A_s, A_f1, A_f0, A_e, A_c);
+ printk("B: %ld %lu %lu %ld (%ld)\n", B_s, B_f1, B_f0, B_e, B_c);
+#endif
+
+ FP_CMP_D(cmp, A, B, 2);
+ cmp = code[(cmp + 1) & 3];
+
+ __FPU_FPSCR &= ~(0x1f000);
+ __FPU_FPSCR |= (cmp << 12);
+
+ *ccr &= ~(15 << ((7 - crfD) << 2));
+ *ccr |= (cmp << ((7 - crfD) << 2));
+
+#ifdef DEBUG
+ printk("CR: %08x\n", *ccr);
+#endif
+
+ return 0;
+}
diff --git a/arch/ppc/math-emu/fctiw.c b/arch/ppc/math-emu/fctiw.c
new file mode 100644
index 0000000..3b3c98b
--- /dev/null
+++ b/arch/ppc/math-emu/fctiw.c
@@ -0,0 +1,25 @@
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <asm/uaccess.h>
+
+#include "soft-fp.h"
+#include "double.h"
+
+int
+fctiw(u32 *frD, void *frB)
+{
+ FP_DECL_D(B);
+ unsigned int r;
+
+ __FP_UNPACK_D(B, frB);
+ FP_TO_INT_D(r, B, 32, 1);
+ frD[1] = r;
+
+#ifdef DEBUG
+ printk("%s: D %p, B %p: ", __FUNCTION__, frD, frB);
+ dump_double(frD);
+ printk("\n");
+#endif
+
+ return 0;
+}
diff --git a/arch/ppc/math-emu/fctiwz.c b/arch/ppc/math-emu/fctiwz.c
new file mode 100644
index 0000000..7717eb6
--- /dev/null
+++ b/arch/ppc/math-emu/fctiwz.c
@@ -0,0 +1,32 @@
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <asm/uaccess.h>
+
+#include "soft-fp.h"
+#include "double.h"
+
+int
+fctiwz(u32 *frD, void *frB)
+{
+ FP_DECL_D(B);
+ u32 fpscr;
+ unsigned int r;
+
+ fpscr = __FPU_FPSCR;
+ __FPU_FPSCR &= ~(3);
+ __FPU_FPSCR |= FP_RND_ZERO;
+
+ __FP_UNPACK_D(B, frB);
+ FP_TO_INT_D(r, B, 32, 1);
+ frD[1] = r;
+
+ __FPU_FPSCR = fpscr;
+
+#ifdef DEBUG
+ printk("%s: D %p, B %p: ", __FUNCTION__, frD, frB);
+ dump_double(frD);
+ printk("\n");
+#endif
+
+ return 0;
+}
diff --git a/arch/ppc/math-emu/fdiv.c b/arch/ppc/math-emu/fdiv.c
new file mode 100644
index 0000000..f2fba82
--- /dev/null
+++ b/arch/ppc/math-emu/fdiv.c
@@ -0,0 +1,53 @@
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <asm/uaccess.h>
+
+#include "soft-fp.h"
+#include "double.h"
+
+int
+fdiv(void *frD, void *frA, void *frB)
+{
+ FP_DECL_D(A);
+ FP_DECL_D(B);
+ FP_DECL_D(R);
+ int ret = 0;
+
+#ifdef DEBUG
+ printk("%s: %p %p %p\n", __FUNCTION__, frD, frA, frB);
+#endif
+
+ __FP_UNPACK_D(A, frA);
+ __FP_UNPACK_D(B, frB);
+
+#ifdef DEBUG
+ printk("A: %ld %lu %lu %ld (%ld)\n", A_s, A_f1, A_f0, A_e, A_c);
+ printk("B: %ld %lu %lu %ld (%ld)\n", B_s, B_f1, B_f0, B_e, B_c);
+#endif
+
+ if (A_c == FP_CLS_ZERO && B_c == FP_CLS_ZERO) {
+ ret |= EFLAG_VXZDZ;
+#ifdef DEBUG
+ printk("%s: FPSCR_VXZDZ raised\n", __FUNCTION__);
+#endif
+ }
+ if (A_c == FP_CLS_INF && B_c == FP_CLS_INF) {
+ ret |= EFLAG_VXIDI;
+#ifdef DEBUG
+ printk("%s: FPSCR_VXIDI raised\n", __FUNCTION__);
+#endif
+ }
+
+ if (B_c == FP_CLS_ZERO && A_c != FP_CLS_ZERO) {
+ ret |= EFLAG_DIVZERO;
+ if (__FPU_TRAP_P(EFLAG_DIVZERO))
+ return ret;
+ }
+ FP_DIV_D(R, A, B);
+
+#ifdef DEBUG
+ printk("D: %ld %lu %lu %ld (%ld)\n", R_s, R_f1, R_f0, R_e, R_c);
+#endif
+
+ return (ret | __FP_PACK_D(frD, R));
+}
diff --git a/arch/ppc/math-emu/fdivs.c b/arch/ppc/math-emu/fdivs.c
new file mode 100644
index 0000000..b971196
--- /dev/null
+++ b/arch/ppc/math-emu/fdivs.c
@@ -0,0 +1,55 @@
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <asm/uaccess.h>
+
+#include "soft-fp.h"
+#include "double.h"
+#include "single.h"
+
+int
+fdivs(void *frD, void *frA, void *frB)
+{
+ FP_DECL_D(A);
+ FP_DECL_D(B);
+ FP_DECL_D(R);
+ int ret = 0;
+
+#ifdef DEBUG
+ printk("%s: %p %p %p\n", __FUNCTION__, frD, frA, frB);
+#endif
+
+ __FP_UNPACK_D(A, frA);
+ __FP_UNPACK_D(B, frB);
+
+#ifdef DEBUG
+ printk("A: %ld %lu %lu %ld (%ld)\n", A_s, A_f1, A_f0, A_e, A_c);
+ printk("B: %ld %lu %lu %ld (%ld)\n", B_s, B_f1, B_f0, B_e, B_c);
+#endif
+
+ if (A_c == FP_CLS_ZERO && B_c == FP_CLS_ZERO) {
+ ret |= EFLAG_VXZDZ;
+#ifdef DEBUG
+ printk("%s: FPSCR_VXZDZ raised\n", __FUNCTION__);
+#endif
+ }
+ if (A_c == FP_CLS_INF && B_c == FP_CLS_INF) {
+ ret |= EFLAG_VXIDI;
+#ifdef DEBUG
+ printk("%s: FPSCR_VXIDI raised\n", __FUNCTION__);
+#endif
+ }
+
+ if (B_c == FP_CLS_ZERO && A_c != FP_CLS_ZERO) {
+ ret |= EFLAG_DIVZERO;
+ if (__FPU_TRAP_P(EFLAG_DIVZERO))
+ return ret;
+ }
+
+ FP_DIV_D(R, A, B);
+
+#ifdef DEBUG
+ printk("D: %ld %lu %lu %ld (%ld)\n", R_s, R_f1, R_f0, R_e, R_c);
+#endif
+
+ return (ret | __FP_PACK_DS(frD, R));
+}
diff --git a/arch/ppc/math-emu/fmadd.c b/arch/ppc/math-emu/fmadd.c
new file mode 100644
index 0000000..0a1dbce
--- /dev/null
+++ b/arch/ppc/math-emu/fmadd.c
@@ -0,0 +1,48 @@
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <asm/uaccess.h>
+
+#include "soft-fp.h"
+#include "double.h"
+
+int
+fmadd(void *frD, void *frA, void *frB, void *frC)
+{
+ FP_DECL_D(R);
+ FP_DECL_D(A);
+ FP_DECL_D(B);
+ FP_DECL_D(C);
+ FP_DECL_D(T);
+ int ret = 0;
+
+#ifdef DEBUG
+ printk("%s: %p %p %p %p\n", __FUNCTION__, frD, frA, frB, frC);
+#endif
+
+ __FP_UNPACK_D(A, frA);
+ __FP_UNPACK_D(B, frB);
+ __FP_UNPACK_D(C, frC);
+
+#ifdef DEBUG
+ printk("A: %ld %lu %lu %ld (%ld)\n", A_s, A_f1, A_f0, A_e, A_c);
+ printk("B: %ld %lu %lu %ld (%ld)\n", B_s, B_f1, B_f0, B_e, B_c);
+ printk("C: %ld %lu %lu %ld (%ld)\n", C_s, C_f1, C_f0, C_e, C_c);
+#endif
+
+ if ((A_c == FP_CLS_INF && C_c == FP_CLS_ZERO) ||
+ (A_c == FP_CLS_ZERO && C_c == FP_CLS_INF))
+ ret |= EFLAG_VXIMZ;
+
+ FP_MUL_D(T, A, C);
+
+ if (T_s != B_s && T_c == FP_CLS_INF && B_c == FP_CLS_INF)
+ ret |= EFLAG_VXISI;
+
+ FP_ADD_D(R, T, B);
+
+#ifdef DEBUG
+ printk("D: %ld %lu %lu %ld (%ld)\n", R_s, R_f1, R_f0, R_e, R_c);
+#endif
+
+ return (ret | __FP_PACK_D(frD, R));
+}
diff --git a/arch/ppc/math-emu/fmadds.c b/arch/ppc/math-emu/fmadds.c
new file mode 100644
index 0000000..0f70bba
--- /dev/null
+++ b/arch/ppc/math-emu/fmadds.c
@@ -0,0 +1,49 @@
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <asm/uaccess.h>
+
+#include "soft-fp.h"
+#include "double.h"
+#include "single.h"
+
+int
+fmadds(void *frD, void *frA, void *frB, void *frC)
+{
+ FP_DECL_D(R);
+ FP_DECL_D(A);
+ FP_DECL_D(B);
+ FP_DECL_D(C);
+ FP_DECL_D(T);
+ int ret = 0;
+
+#ifdef DEBUG
+ printk("%s: %p %p %p %p\n", __FUNCTION__, frD, frA, frB, frC);
+#endif
+
+ __FP_UNPACK_D(A, frA);
+ __FP_UNPACK_D(B, frB);
+ __FP_UNPACK_D(C, frC);
+
+#ifdef DEBUG
+ printk("A: %ld %lu %lu %ld (%ld)\n", A_s, A_f1, A_f0, A_e, A_c);
+ printk("B: %ld %lu %lu %ld (%ld)\n", B_s, B_f1, B_f0, B_e, B_c);
+ printk("C: %ld %lu %lu %ld (%ld)\n", C_s, C_f1, C_f0, C_e, C_c);
+#endif
+
+ if ((A_c == FP_CLS_INF && C_c == FP_CLS_ZERO) ||
+ (A_c == FP_CLS_ZERO && C_c == FP_CLS_INF))
+ ret |= EFLAG_VXIMZ;
+
+ FP_MUL_D(T, A, C);
+
+ if (T_s != B_s && T_c == FP_CLS_INF && B_c == FP_CLS_INF)
+ ret |= EFLAG_VXISI;
+
+ FP_ADD_D(R, T, B);
+
+#ifdef DEBUG
+ printk("D: %ld %lu %lu %ld (%ld)\n", R_s, R_f1, R_f0, R_e, R_c);
+#endif
+
+ return (ret | __FP_PACK_DS(frD, R));
+}
diff --git a/arch/ppc/math-emu/fmr.c b/arch/ppc/math-emu/fmr.c
new file mode 100644
index 0000000..28df700
--- /dev/null
+++ b/arch/ppc/math-emu/fmr.c
@@ -0,0 +1,18 @@
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <asm/uaccess.h>
+
+int
+fmr(u32 *frD, u32 *frB)
+{
+ frD[0] = frB[0];
+ frD[1] = frB[1];
+
+#ifdef DEBUG
+ printk("%s: D %p, B %p: ", __FUNCTION__, frD, frB);
+ dump_double(frD);
+ printk("\n");
+#endif
+
+ return 0;
+}
diff --git a/arch/ppc/math-emu/fmsub.c b/arch/ppc/math-emu/fmsub.c
new file mode 100644
index 0000000..203fd48
--- /dev/null
+++ b/arch/ppc/math-emu/fmsub.c
@@ -0,0 +1,51 @@
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <asm/uaccess.h>
+
+#include "soft-fp.h"
+#include "double.h"
+
+int
+fmsub(void *frD, void *frA, void *frB, void *frC)
+{
+ FP_DECL_D(R);
+ FP_DECL_D(A);
+ FP_DECL_D(B);
+ FP_DECL_D(C);
+ FP_DECL_D(T);
+ int ret = 0;
+
+#ifdef DEBUG
+ printk("%s: %p %p %p %p\n", __FUNCTION__, frD, frA, frB, frC);
+#endif
+
+ __FP_UNPACK_D(A, frA);
+ __FP_UNPACK_D(B, frB);
+ __FP_UNPACK_D(C, frC);
+
+#ifdef DEBUG
+ printk("A: %ld %lu %lu %ld (%ld)\n", A_s, A_f1, A_f0, A_e, A_c);
+ printk("B: %ld %lu %lu %ld (%ld)\n", B_s, B_f1, B_f0, B_e, B_c);
+ printk("C: %ld %lu %lu %ld (%ld)\n", C_s, C_f1, C_f0, C_e, C_c);
+#endif
+
+ if ((A_c == FP_CLS_INF && C_c == FP_CLS_ZERO) ||
+ (A_c == FP_CLS_ZERO && C_c == FP_CLS_INF))
+ ret |= EFLAG_VXIMZ;
+
+ FP_MUL_D(T, A, C);
+
+ if (B_c != FP_CLS_NAN)
+ B_s ^= 1;
+
+ if (T_s != B_s && T_c == FP_CLS_INF && B_c == FP_CLS_INF)
+ ret |= EFLAG_VXISI;
+
+ FP_ADD_D(R, T, B);
+
+#ifdef DEBUG
+ printk("D: %ld %lu %lu %ld (%ld)\n", R_s, R_f1, R_f0, R_e, R_c);
+#endif
+
+ return (ret | __FP_PACK_D(frD, R));
+}
diff --git a/arch/ppc/math-emu/fmsubs.c b/arch/ppc/math-emu/fmsubs.c
new file mode 100644
index 0000000..8ce6862
--- /dev/null
+++ b/arch/ppc/math-emu/fmsubs.c
@@ -0,0 +1,52 @@
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <asm/uaccess.h>
+
+#include "soft-fp.h"
+#include "double.h"
+#include "single.h"
+
+int
+fmsubs(void *frD, void *frA, void *frB, void *frC)
+{
+ FP_DECL_D(R);
+ FP_DECL_D(A);
+ FP_DECL_D(B);
+ FP_DECL_D(C);
+ FP_DECL_D(T);
+ int ret = 0;
+
+#ifdef DEBUG
+ printk("%s: %p %p %p %p\n", __FUNCTION__, frD, frA, frB, frC);
+#endif
+
+ __FP_UNPACK_D(A, frA);
+ __FP_UNPACK_D(B, frB);
+ __FP_UNPACK_D(C, frC);
+
+#ifdef DEBUG
+ printk("A: %ld %lu %lu %ld (%ld)\n", A_s, A_f1, A_f0, A_e, A_c);
+ printk("B: %ld %lu %lu %ld (%ld)\n", B_s, B_f1, B_f0, B_e, B_c);
+ printk("C: %ld %lu %lu %ld (%ld)\n", C_s, C_f1, C_f0, C_e, C_c);
+#endif
+
+ if ((A_c == FP_CLS_INF && C_c == FP_CLS_ZERO) ||
+ (A_c == FP_CLS_ZERO && C_c == FP_CLS_INF))
+ ret |= EFLAG_VXIMZ;
+
+ FP_MUL_D(T, A, C);
+
+ if (B_c != FP_CLS_NAN)
+ B_s ^= 1;
+
+ if (T_s != B_s && T_c == FP_CLS_INF && B_c == FP_CLS_INF)
+ ret |= EFLAG_VXISI;
+
+ FP_ADD_D(R, T, B);
+
+#ifdef DEBUG
+ printk("D: %ld %lu %lu %ld (%ld)\n", R_s, R_f1, R_f0, R_e, R_c);
+#endif
+
+ return (ret | __FP_PACK_DS(frD, R));
+}
diff --git a/arch/ppc/math-emu/fmul.c b/arch/ppc/math-emu/fmul.c
new file mode 100644
index 0000000..66c7e79
--- /dev/null
+++ b/arch/ppc/math-emu/fmul.c
@@ -0,0 +1,42 @@
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <asm/uaccess.h>
+
+#include "soft-fp.h"
+#include "double.h"
+
+int
+fmul(void *frD, void *frA, void *frB)
+{
+ FP_DECL_D(A);
+ FP_DECL_D(B);
+ FP_DECL_D(R);
+ int ret = 0;
+
+#ifdef DEBUG
+ printk("%s: %p %p %p\n", __FUNCTION__, frD, frA, frB);
+#endif
+
+ __FP_UNPACK_D(A, frA);
+ __FP_UNPACK_D(B, frB);
+
+#ifdef DEBUG
+ printk("A: %ld %lu %lu %ld (%ld) [%08lx.%08lx %lx]\n",
+ A_s, A_f1, A_f0, A_e, A_c, A_f1, A_f0, A_e + 1023);
+ printk("B: %ld %lu %lu %ld (%ld) [%08lx.%08lx %lx]\n",
+ B_s, B_f1, B_f0, B_e, B_c, B_f1, B_f0, B_e + 1023);
+#endif
+
+ if ((A_c == FP_CLS_INF && B_c == FP_CLS_ZERO) ||
+ (A_c == FP_CLS_ZERO && B_c == FP_CLS_INF))
+ ret |= EFLAG_VXIMZ;
+
+ FP_MUL_D(R, A, B);
+
+#ifdef DEBUG
+ printk("D: %ld %lu %lu %ld (%ld) [%08lx.%08lx %lx]\n",
+ R_s, R_f1, R_f0, R_e, R_c, R_f1, R_f0, R_e + 1023);
+#endif
+
+ return (ret | __FP_PACK_D(frD, R));
+}
diff --git a/arch/ppc/math-emu/fmuls.c b/arch/ppc/math-emu/fmuls.c
new file mode 100644
index 0000000..26bc427
--- /dev/null
+++ b/arch/ppc/math-emu/fmuls.c
@@ -0,0 +1,43 @@
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <asm/uaccess.h>
+
+#include "soft-fp.h"
+#include "double.h"
+#include "single.h"
+
+int
+fmuls(void *frD, void *frA, void *frB)
+{
+ FP_DECL_D(A);
+ FP_DECL_D(B);
+ FP_DECL_D(R);
+ int ret = 0;
+
+#ifdef DEBUG
+ printk("%s: %p %p %p\n", __FUNCTION__, frD, frA, frB);
+#endif
+
+ __FP_UNPACK_D(A, frA);
+ __FP_UNPACK_D(B, frB);
+
+#ifdef DEBUG
+ printk("A: %ld %lu %lu %ld (%ld) [%08lx.%08lx %lx]\n",
+ A_s, A_f1, A_f0, A_e, A_c, A_f1, A_f0, A_e + 1023);
+ printk("B: %ld %lu %lu %ld (%ld) [%08lx.%08lx %lx]\n",
+ B_s, B_f1, B_f0, B_e, B_c, B_f1, B_f0, B_e + 1023);
+#endif
+
+ if ((A_c == FP_CLS_INF && B_c == FP_CLS_ZERO) ||
+ (A_c == FP_CLS_ZERO && B_c == FP_CLS_INF))
+ ret |= EFLAG_VXIMZ;
+
+ FP_MUL_D(R, A, B);
+
+#ifdef DEBUG
+ printk("D: %ld %lu %lu %ld (%ld) [%08lx.%08lx %lx]\n",
+ R_s, R_f1, R_f0, R_e, R_c, R_f1, R_f0, R_e + 1023);
+#endif
+
+ return (ret | __FP_PACK_DS(frD, R));
+}
diff --git a/arch/ppc/math-emu/fnabs.c b/arch/ppc/math-emu/fnabs.c
new file mode 100644
index 0000000..c6b913d
--- /dev/null
+++ b/arch/ppc/math-emu/fnabs.c
@@ -0,0 +1,18 @@
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <asm/uaccess.h>
+
+int
+fnabs(u32 *frD, u32 *frB)
+{
+ frD[0] = frB[0] | 0x80000000;
+ frD[1] = frB[1];
+
+#ifdef DEBUG
+ printk("%s: D %p, B %p: ", __FUNCTION__, frD, frB);
+ dump_double(frD);
+ printk("\n");
+#endif
+
+ return 0;
+}
diff --git a/arch/ppc/math-emu/fneg.c b/arch/ppc/math-emu/fneg.c
new file mode 100644
index 0000000..fe9a98d
--- /dev/null
+++ b/arch/ppc/math-emu/fneg.c
@@ -0,0 +1,18 @@
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <asm/uaccess.h>
+
+int
+fneg(u32 *frD, u32 *frB)
+{
+ frD[0] = frB[0] ^ 0x80000000;
+ frD[1] = frB[1];
+
+#ifdef DEBUG
+ printk("%s: D %p, B %p: ", __FUNCTION__, frD, frB);
+ dump_double(frD);
+ printk("\n");
+#endif
+
+ return 0;
+}
diff --git a/arch/ppc/math-emu/fnmadd.c b/arch/ppc/math-emu/fnmadd.c
new file mode 100644
index 0000000..7f31227
--- /dev/null
+++ b/arch/ppc/math-emu/fnmadd.c
@@ -0,0 +1,51 @@
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <asm/uaccess.h>
+
+#include "soft-fp.h"
+#include "double.h"
+
+int
+fnmadd(void *frD, void *frA, void *frB, void *frC)
+{
+ FP_DECL_D(R);
+ FP_DECL_D(A);
+ FP_DECL_D(B);
+ FP_DECL_D(C);
+ FP_DECL_D(T);
+ int ret = 0;
+
+#ifdef DEBUG
+ printk("%s: %p %p %p %p\n", __FUNCTION__, frD, frA, frB, frC);
+#endif
+
+ __FP_UNPACK_D(A, frA);
+ __FP_UNPACK_D(B, frB);
+ __FP_UNPACK_D(C, frC);
+
+#ifdef DEBUG
+ printk("A: %ld %lu %lu %ld (%ld)\n", A_s, A_f1, A_f0, A_e, A_c);
+ printk("B: %ld %lu %lu %ld (%ld)\n", B_s, B_f1, B_f0, B_e, B_c);
+ printk("C: %ld %lu %lu %ld (%ld)\n", C_s, C_f1, C_f0, C_e, C_c);
+#endif
+
+ if ((A_c == FP_CLS_INF && C_c == FP_CLS_ZERO) ||
+ (A_c == FP_CLS_ZERO && C_c == FP_CLS_INF))
+ ret |= EFLAG_VXIMZ;
+
+ FP_MUL_D(T, A, C);
+
+ if (T_s != B_s && T_c == FP_CLS_INF && B_c == FP_CLS_INF)
+ ret |= EFLAG_VXISI;
+
+ FP_ADD_D(R, T, B);
+
+ if (R_c != FP_CLS_NAN)
+ R_s ^= 1;
+
+#ifdef DEBUG
+ printk("D: %ld %lu %lu %ld (%ld)\n", R_s, R_f1, R_f0, R_e, R_c);
+#endif
+
+ return (ret | __FP_PACK_D(frD, R));
+}
diff --git a/arch/ppc/math-emu/fnmadds.c b/arch/ppc/math-emu/fnmadds.c
new file mode 100644
index 0000000..65454c9
--- /dev/null
+++ b/arch/ppc/math-emu/fnmadds.c
@@ -0,0 +1,52 @@
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <asm/uaccess.h>
+
+#include "soft-fp.h"
+#include "double.h"
+#include "single.h"
+
+int
+fnmadds(void *frD, void *frA, void *frB, void *frC)
+{
+ FP_DECL_D(R);
+ FP_DECL_D(A);
+ FP_DECL_D(B);
+ FP_DECL_D(C);
+ FP_DECL_D(T);
+ int ret = 0;
+
+#ifdef DEBUG
+ printk("%s: %p %p %p %p\n", __FUNCTION__, frD, frA, frB, frC);
+#endif
+
+ __FP_UNPACK_D(A, frA);
+ __FP_UNPACK_D(B, frB);
+ __FP_UNPACK_D(C, frC);
+
+#ifdef DEBUG
+ printk("A: %ld %lu %lu %ld (%ld)\n", A_s, A_f1, A_f0, A_e, A_c);
+ printk("B: %ld %lu %lu %ld (%ld)\n", B_s, B_f1, B_f0, B_e, B_c);
+ printk("C: %ld %lu %lu %ld (%ld)\n", C_s, C_f1, C_f0, C_e, C_c);
+#endif
+
+ if ((A_c == FP_CLS_INF && C_c == FP_CLS_ZERO) ||
+ (A_c == FP_CLS_ZERO && C_c == FP_CLS_INF))
+ ret |= EFLAG_VXIMZ;
+
+ FP_MUL_D(T, A, C);
+
+ if (T_s != B_s && T_c == FP_CLS_INF && B_c == FP_CLS_INF)
+ ret |= EFLAG_VXISI;
+
+ FP_ADD_D(R, T, B);
+
+ if (R_c != FP_CLS_NAN)
+ R_s ^= 1;
+
+#ifdef DEBUG
+ printk("D: %ld %lu %lu %ld (%ld)\n", R_s, R_f1, R_f0, R_e, R_c);
+#endif
+
+ return (ret | __FP_PACK_DS(frD, R));
+}
diff --git a/arch/ppc/math-emu/fnmsub.c b/arch/ppc/math-emu/fnmsub.c
new file mode 100644
index 0000000..f1ca748
--- /dev/null
+++ b/arch/ppc/math-emu/fnmsub.c
@@ -0,0 +1,54 @@
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <asm/uaccess.h>
+
+#include "soft-fp.h"
+#include "double.h"
+
+int
+fnmsub(void *frD, void *frA, void *frB, void *frC)
+{
+ FP_DECL_D(R);
+ FP_DECL_D(A);
+ FP_DECL_D(B);
+ FP_DECL_D(C);
+ FP_DECL_D(T);
+ int ret = 0;
+
+#ifdef DEBUG
+ printk("%s: %p %p %p %p\n", __FUNCTION__, frD, frA, frB, frC);
+#endif
+
+ __FP_UNPACK_D(A, frA);
+ __FP_UNPACK_D(B, frB);
+ __FP_UNPACK_D(C, frC);
+
+#ifdef DEBUG
+ printk("A: %ld %lu %lu %ld (%ld)\n", A_s, A_f1, A_f0, A_e, A_c);
+ printk("B: %ld %lu %lu %ld (%ld)\n", B_s, B_f1, B_f0, B_e, B_c);
+ printk("C: %ld %lu %lu %ld (%ld)\n", C_s, C_f1, C_f0, C_e, C_c);
+#endif
+
+ if ((A_c == FP_CLS_INF && C_c == FP_CLS_ZERO) ||
+ (A_c == FP_CLS_ZERO && C_c == FP_CLS_INF))
+ ret |= EFLAG_VXIMZ;
+
+ FP_MUL_D(T, A, C);
+
+ if (B_c != FP_CLS_NAN)
+ B_s ^= 1;
+
+ if (T_s != B_s && T_c == FP_CLS_INF && B_c == FP_CLS_INF)
+ ret |= EFLAG_VXISI;
+
+ FP_ADD_D(R, T, B);
+
+ if (R_c != FP_CLS_NAN)
+ R_s ^= 1;
+
+#ifdef DEBUG
+ printk("D: %ld %lu %lu %ld (%ld)\n", R_s, R_f1, R_f0, R_e, R_c);
+#endif
+
+ return (ret | __FP_PACK_D(frD, R));
+}
diff --git a/arch/ppc/math-emu/fnmsubs.c b/arch/ppc/math-emu/fnmsubs.c
new file mode 100644
index 0000000..5c9a09a
--- /dev/null
+++ b/arch/ppc/math-emu/fnmsubs.c
@@ -0,0 +1,55 @@
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <asm/uaccess.h>
+
+#include "soft-fp.h"
+#include "double.h"
+#include "single.h"
+
+int
+fnmsubs(void *frD, void *frA, void *frB, void *frC)
+{
+ FP_DECL_D(R);
+ FP_DECL_D(A);
+ FP_DECL_D(B);
+ FP_DECL_D(C);
+ FP_DECL_D(T);
+ int ret = 0;
+
+#ifdef DEBUG
+ printk("%s: %p %p %p %p\n", __FUNCTION__, frD, frA, frB, frC);
+#endif
+
+ __FP_UNPACK_D(A, frA);
+ __FP_UNPACK_D(B, frB);
+ __FP_UNPACK_D(C, frC);
+
+#ifdef DEBUG
+ printk("A: %ld %lu %lu %ld (%ld)\n", A_s, A_f1, A_f0, A_e, A_c);
+ printk("B: %ld %lu %lu %ld (%ld)\n", B_s, B_f1, B_f0, B_e, B_c);
+ printk("C: %ld %lu %lu %ld (%ld)\n", C_s, C_f1, C_f0, C_e, C_c);
+#endif
+
+ if ((A_c == FP_CLS_INF && C_c == FP_CLS_ZERO) ||
+ (A_c == FP_CLS_ZERO && C_c == FP_CLS_INF))
+ ret |= EFLAG_VXIMZ;
+
+ FP_MUL_D(T, A, C);
+
+ if (B_c != FP_CLS_NAN)
+ B_s ^= 1;
+
+ if (T_s != B_s && T_c == FP_CLS_INF && B_c == FP_CLS_INF)
+ ret |= EFLAG_VXISI;
+
+ FP_ADD_D(R, T, B);
+
+ if (R_c != FP_CLS_NAN)
+ R_s ^= 1;
+
+#ifdef DEBUG
+ printk("D: %ld %lu %lu %ld (%ld)\n", R_s, R_f1, R_f0, R_e, R_c);
+#endif
+
+ return (ret | __FP_PACK_DS(frD, R));
+}
diff --git a/arch/ppc/math-emu/fres.c b/arch/ppc/math-emu/fres.c
new file mode 100644
index 0000000..ec11e46
--- /dev/null
+++ b/arch/ppc/math-emu/fres.c
@@ -0,0 +1,12 @@
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <asm/uaccess.h>
+
+int
+fres(void *frD, void *frB)
+{
+#ifdef DEBUG
+ printk("%s: %p %p\n", __FUNCTION__, frD, frB);
+#endif
+ return -ENOSYS;
+}
diff --git a/arch/ppc/math-emu/frsp.c b/arch/ppc/math-emu/frsp.c
new file mode 100644
index 0000000..d879b2a
--- /dev/null
+++ b/arch/ppc/math-emu/frsp.c
@@ -0,0 +1,25 @@
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <asm/uaccess.h>
+
+#include "soft-fp.h"
+#include "double.h"
+#include "single.h"
+
+int
+frsp(void *frD, void *frB)
+{
+ FP_DECL_D(B);
+
+#ifdef DEBUG
+ printk("%s: D %p, B %p\n", __FUNCTION__, frD, frB);
+#endif
+
+ __FP_UNPACK_D(B, frB);
+
+#ifdef DEBUG
+ printk("B: %ld %lu %lu %ld (%ld)\n", B_s, B_f1, B_f0, B_e, B_c);
+#endif
+
+ return __FP_PACK_DS(frD, B);
+}
diff --git a/arch/ppc/math-emu/frsqrte.c b/arch/ppc/math-emu/frsqrte.c
new file mode 100644
index 0000000..a11ae18
--- /dev/null
+++ b/arch/ppc/math-emu/frsqrte.c
@@ -0,0 +1,12 @@
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <asm/uaccess.h>
+
+int
+frsqrte(void *frD, void *frB)
+{
+#ifdef DEBUG
+ printk("%s: %p %p\n", __FUNCTION__, frD, frB);
+#endif
+ return 0;
+}
diff --git a/arch/ppc/math-emu/fsel.c b/arch/ppc/math-emu/fsel.c
new file mode 100644
index 0000000..e36e6e7
--- /dev/null
+++ b/arch/ppc/math-emu/fsel.c
@@ -0,0 +1,38 @@
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <asm/uaccess.h>
+
+#include "soft-fp.h"
+#include "double.h"
+
+int
+fsel(u32 *frD, void *frA, u32 *frB, u32 *frC)
+{
+ FP_DECL_D(A);
+
+#ifdef DEBUG
+ printk("%s: %p %p %p %p\n", __FUNCTION__, frD, frA, frB, frC);
+#endif
+
+ __FP_UNPACK_D(A, frA);
+
+#ifdef DEBUG
+ printk("A: %ld %lu %lu %ld (%ld)\n", A_s, A_f1, A_f0, A_e, A_c);
+ printk("B: %08x %08x\n", frB[0], frB[1]);
+ printk("C: %08x %08x\n", frC[0], frC[1]);
+#endif
+
+ if (A_c == FP_CLS_NAN || (A_c != FP_CLS_ZERO && A_s)) {
+ frD[0] = frB[0];
+ frD[1] = frB[1];
+ } else {
+ frD[0] = frC[0];
+ frD[1] = frC[1];
+ }
+
+#ifdef DEBUG
+ printk("D: %08x.%08x\n", frD[0], frD[1]);
+#endif
+
+ return 0;
+}
diff --git a/arch/ppc/math-emu/fsqrt.c b/arch/ppc/math-emu/fsqrt.c
new file mode 100644
index 0000000..6f8319f
--- /dev/null
+++ b/arch/ppc/math-emu/fsqrt.c
@@ -0,0 +1,37 @@
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <asm/uaccess.h>
+
+#include "soft-fp.h"
+#include "double.h"
+
+int
+fsqrt(void *frD, void *frB)
+{
+ FP_DECL_D(B);
+ FP_DECL_D(R);
+ int ret = 0;
+
+#ifdef DEBUG
+ printk("%s: %p %p %p %p\n", __FUNCTION__, frD, frB);
+#endif
+
+ __FP_UNPACK_D(B, frB);
+
+#ifdef DEBUG
+ printk("B: %ld %lu %lu %ld (%ld)\n", B_s, B_f1, B_f0, B_e, B_c);
+#endif
+
+ if (B_s && B_c != FP_CLS_ZERO)
+ ret |= EFLAG_VXSQRT;
+ if (B_c == FP_CLS_NAN)
+ ret |= EFLAG_VXSNAN;
+
+ FP_SQRT_D(R, B);
+
+#ifdef DEBUG
+ printk("R: %ld %lu %lu %ld (%ld)\n", R_s, R_f1, R_f0, R_e, R_c);
+#endif
+
+ return (ret | __FP_PACK_D(frD, R));
+}
diff --git a/arch/ppc/math-emu/fsqrts.c b/arch/ppc/math-emu/fsqrts.c
new file mode 100644
index 0000000..3b2b1cf
--- /dev/null
+++ b/arch/ppc/math-emu/fsqrts.c
@@ -0,0 +1,38 @@
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <asm/uaccess.h>
+
+#include "soft-fp.h"
+#include "double.h"
+#include "single.h"
+
+int
+fsqrts(void *frD, void *frB)
+{
+ FP_DECL_D(B);
+ FP_DECL_D(R);
+ int ret = 0;
+
+#ifdef DEBUG
+ printk("%s: %p %p %p %p\n", __FUNCTION__, frD, frB);
+#endif
+
+ __FP_UNPACK_D(B, frB);
+
+#ifdef DEBUG
+ printk("B: %ld %lu %lu %ld (%ld)\n", B_s, B_f1, B_f0, B_e, B_c);
+#endif
+
+ if (B_s && B_c != FP_CLS_ZERO)
+ ret |= EFLAG_VXSQRT;
+ if (B_c == FP_CLS_NAN)
+ ret |= EFLAG_VXSNAN;
+
+ FP_SQRT_D(R, B);
+
+#ifdef DEBUG
+ printk("R: %ld %lu %lu %ld (%ld)\n", R_s, R_f1, R_f0, R_e, R_c);
+#endif
+
+ return (ret | __FP_PACK_DS(frD, R));
+}
diff --git a/arch/ppc/math-emu/fsub.c b/arch/ppc/math-emu/fsub.c
new file mode 100644
index 0000000..9566790
--- /dev/null
+++ b/arch/ppc/math-emu/fsub.c
@@ -0,0 +1,41 @@
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <asm/uaccess.h>
+
+#include "soft-fp.h"
+#include "double.h"
+
+int
+fsub(void *frD, void *frA, void *frB)
+{
+ FP_DECL_D(A);
+ FP_DECL_D(B);
+ FP_DECL_D(R);
+ int ret = 0;
+
+#ifdef DEBUG
+ printk("%s: %p %p %p\n", __FUNCTION__, frD, frA, frB);
+#endif
+
+ __FP_UNPACK_D(A, frA);
+ __FP_UNPACK_D(B, frB);
+
+#ifdef DEBUG
+ printk("A: %ld %lu %lu %ld (%ld)\n", A_s, A_f1, A_f0, A_e, A_c);
+ printk("B: %ld %lu %lu %ld (%ld)\n", B_s, B_f1, B_f0, B_e, B_c);
+#endif
+
+ if (B_c != FP_CLS_NAN)
+ B_s ^= 1;
+
+ if (A_s != B_s && A_c == FP_CLS_INF && B_c == FP_CLS_INF)
+ ret |= EFLAG_VXISI;
+
+ FP_ADD_D(R, A, B);
+
+#ifdef DEBUG
+ printk("D: %ld %lu %lu %ld (%ld)\n", R_s, R_f1, R_f0, R_e, R_c);
+#endif
+
+ return (ret | __FP_PACK_D(frD, R));
+}
diff --git a/arch/ppc/math-emu/fsubs.c b/arch/ppc/math-emu/fsubs.c
new file mode 100644
index 0000000..3428117
--- /dev/null
+++ b/arch/ppc/math-emu/fsubs.c
@@ -0,0 +1,42 @@
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <asm/uaccess.h>
+
+#include "soft-fp.h"
+#include "double.h"
+#include "single.h"
+
+int
+fsubs(void *frD, void *frA, void *frB)
+{
+ FP_DECL_D(A);
+ FP_DECL_D(B);
+ FP_DECL_D(R);
+ int ret = 0;
+
+#ifdef DEBUG
+ printk("%s: %p %p %p\n", __FUNCTION__, frD, frA, frB);
+#endif
+
+ __FP_UNPACK_D(A, frA);
+ __FP_UNPACK_D(B, frB);
+
+#ifdef DEBUG
+ printk("A: %ld %lu %lu %ld (%ld)\n", A_s, A_f1, A_f0, A_e, A_c);
+ printk("B: %ld %lu %lu %ld (%ld)\n", B_s, B_f1, B_f0, B_e, B_c);
+#endif
+
+ if (B_c != FP_CLS_NAN)
+ B_s ^= 1;
+
+ if (A_s != B_s && A_c == FP_CLS_INF && B_c == FP_CLS_INF)
+ ret |= EFLAG_VXISI;
+
+ FP_ADD_D(R, A, B);
+
+#ifdef DEBUG
+ printk("D: %ld %lu %lu %ld (%ld)\n", R_s, R_f1, R_f0, R_e, R_c);
+#endif
+
+ return (ret | __FP_PACK_DS(frD, R));
+}
diff --git a/arch/ppc/math-emu/lfd.c b/arch/ppc/math-emu/lfd.c
new file mode 100644
index 0000000..7d38101
--- /dev/null
+++ b/arch/ppc/math-emu/lfd.c
@@ -0,0 +1,19 @@
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <asm/uaccess.h>
+
+#include "sfp-machine.h"
+#include "double.h"
+
+int
+lfd(void *frD, void *ea)
+{
+ if (copy_from_user(frD, ea, sizeof(double)))
+ return -EFAULT;
+#ifdef DEBUG
+ printk("%s: D %p, ea %p: ", __FUNCTION__, frD, ea);
+ dump_double(frD);
+ printk("\n");
+#endif
+ return 0;
+}
diff --git a/arch/ppc/math-emu/lfs.c b/arch/ppc/math-emu/lfs.c
new file mode 100644
index 0000000..c86dee3
--- /dev/null
+++ b/arch/ppc/math-emu/lfs.c
@@ -0,0 +1,37 @@
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <asm/uaccess.h>
+
+#include "soft-fp.h"
+#include "double.h"
+#include "single.h"
+
+int
+lfs(void *frD, void *ea)
+{
+ FP_DECL_D(R);
+ FP_DECL_S(A);
+ float f;
+
+#ifdef DEBUG
+ printk("%s: D %p, ea %p\n", __FUNCTION__, frD, ea);
+#endif
+
+ if (copy_from_user(&f, ea, sizeof(float)))
+ return -EFAULT;
+
+ __FP_UNPACK_S(A, &f);
+
+#ifdef DEBUG
+ printk("A: %ld %lu %ld (%ld) [%08lx]\n", A_s, A_f, A_e, A_c,
+ *(unsigned long *)&f);
+#endif
+
+ FP_CONV(D, S, 2, 1, R, A);
+
+#ifdef DEBUG
+ printk("R: %ld %lu %lu %ld (%ld)\n", R_s, R_f1, R_f0, R_e, R_c);
+#endif
+
+ return __FP_PACK_D(frD, R);
+}
diff --git a/arch/ppc/math-emu/math.c b/arch/ppc/math-emu/math.c
new file mode 100644
index 0000000..b7dff53
--- /dev/null
+++ b/arch/ppc/math-emu/math.c
@@ -0,0 +1,485 @@
+/*
+ * arch/ppc/math-emu/math.c
+ *
+ * Copyright (C) 1999 Eddie C. Dost (ecd@atecom.com)
+ */
+
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/sched.h>
+
+#include <asm/uaccess.h>
+#include <asm/reg.h>
+
+#include "sfp-machine.h"
+#include "double.h"
+
+#define FLOATFUNC(x) extern int x(void *, void *, void *, void *)
+
+FLOATFUNC(fadd);
+FLOATFUNC(fadds);
+FLOATFUNC(fdiv);
+FLOATFUNC(fdivs);
+FLOATFUNC(fmul);
+FLOATFUNC(fmuls);
+FLOATFUNC(fsub);
+FLOATFUNC(fsubs);
+
+FLOATFUNC(fmadd);
+FLOATFUNC(fmadds);
+FLOATFUNC(fmsub);
+FLOATFUNC(fmsubs);
+FLOATFUNC(fnmadd);
+FLOATFUNC(fnmadds);
+FLOATFUNC(fnmsub);
+FLOATFUNC(fnmsubs);
+
+FLOATFUNC(fctiw);
+FLOATFUNC(fctiwz);
+FLOATFUNC(frsp);
+
+FLOATFUNC(fcmpo);
+FLOATFUNC(fcmpu);
+
+FLOATFUNC(mcrfs);
+FLOATFUNC(mffs);
+FLOATFUNC(mtfsb0);
+FLOATFUNC(mtfsb1);
+FLOATFUNC(mtfsf);
+FLOATFUNC(mtfsfi);
+
+FLOATFUNC(lfd);
+FLOATFUNC(lfs);
+
+FLOATFUNC(stfd);
+FLOATFUNC(stfs);
+FLOATFUNC(stfiwx);
+
+FLOATFUNC(fabs);
+FLOATFUNC(fmr);
+FLOATFUNC(fnabs);
+FLOATFUNC(fneg);
+
+/* Optional */
+FLOATFUNC(fres);
+FLOATFUNC(frsqrte);
+FLOATFUNC(fsel);
+FLOATFUNC(fsqrt);
+FLOATFUNC(fsqrts);
+
+
+#define OP31 0x1f /* 31 */
+#define LFS 0x30 /* 48 */
+#define LFSU 0x31 /* 49 */
+#define LFD 0x32 /* 50 */
+#define LFDU 0x33 /* 51 */
+#define STFS 0x34 /* 52 */
+#define STFSU 0x35 /* 53 */
+#define STFD 0x36 /* 54 */
+#define STFDU 0x37 /* 55 */
+#define OP59 0x3b /* 59 */
+#define OP63 0x3f /* 63 */
+
+/* Opcode 31: */
+/* X-Form: */
+#define LFSX 0x217 /* 535 */
+#define LFSUX 0x237 /* 567 */
+#define LFDX 0x257 /* 599 */
+#define LFDUX 0x277 /* 631 */
+#define STFSX 0x297 /* 663 */
+#define STFSUX 0x2b7 /* 695 */
+#define STFDX 0x2d7 /* 727 */
+#define STFDUX 0x2f7 /* 759 */
+#define STFIWX 0x3d7 /* 983 */
+
+/* Opcode 59: */
+/* A-Form: */
+#define FDIVS 0x012 /* 18 */
+#define FSUBS 0x014 /* 20 */
+#define FADDS 0x015 /* 21 */
+#define FSQRTS 0x016 /* 22 */
+#define FRES 0x018 /* 24 */
+#define FMULS 0x019 /* 25 */
+#define FMSUBS 0x01c /* 28 */
+#define FMADDS 0x01d /* 29 */
+#define FNMSUBS 0x01e /* 30 */
+#define FNMADDS 0x01f /* 31 */
+
+/* Opcode 63: */
+/* A-Form: */
+#define FDIV 0x012 /* 18 */
+#define FSUB 0x014 /* 20 */
+#define FADD 0x015 /* 21 */
+#define FSQRT 0x016 /* 22 */
+#define FSEL 0x017 /* 23 */
+#define FMUL 0x019 /* 25 */
+#define FRSQRTE 0x01a /* 26 */
+#define FMSUB 0x01c /* 28 */
+#define FMADD 0x01d /* 29 */
+#define FNMSUB 0x01e /* 30 */
+#define FNMADD 0x01f /* 31 */
+
+/* X-Form: */
+#define FCMPU 0x000 /* 0 */
+#define FRSP 0x00c /* 12 */
+#define FCTIW 0x00e /* 14 */
+#define FCTIWZ 0x00f /* 15 */
+#define FCMPO 0x020 /* 32 */
+#define MTFSB1 0x026 /* 38 */
+#define FNEG 0x028 /* 40 */
+#define MCRFS 0x040 /* 64 */
+#define MTFSB0 0x046 /* 70 */
+#define FMR 0x048 /* 72 */
+#define MTFSFI 0x086 /* 134 */
+#define FNABS 0x088 /* 136 */
+#define FABS 0x108 /* 264 */
+#define MFFS 0x247 /* 583 */
+#define MTFSF 0x2c7 /* 711 */
+
+
+#define AB 2
+#define AC 3
+#define ABC 4
+#define D 5
+#define DU 6
+#define X 7
+#define XA 8
+#define XB 9
+#define XCR 11
+#define XCRB 12
+#define XCRI 13
+#define XCRL 16
+#define XE 14
+#define XEU 15
+#define XFLB 10
+
+#ifdef CONFIG_MATH_EMULATION
+static int
+record_exception(struct pt_regs *regs, int eflag)
+{
+ u32 fpscr;
+
+ fpscr = __FPU_FPSCR;
+
+ if (eflag) {
+ fpscr |= FPSCR_FX;
+ if (eflag & EFLAG_OVERFLOW)
+ fpscr |= FPSCR_OX;
+ if (eflag & EFLAG_UNDERFLOW)
+ fpscr |= FPSCR_UX;
+ if (eflag & EFLAG_DIVZERO)
+ fpscr |= FPSCR_ZX;
+ if (eflag & EFLAG_INEXACT)
+ fpscr |= FPSCR_XX;
+ if (eflag & EFLAG_VXSNAN)
+ fpscr |= FPSCR_VXSNAN;
+ if (eflag & EFLAG_VXISI)
+ fpscr |= FPSCR_VXISI;
+ if (eflag & EFLAG_VXIDI)
+ fpscr |= FPSCR_VXIDI;
+ if (eflag & EFLAG_VXZDZ)
+ fpscr |= FPSCR_VXZDZ;
+ if (eflag & EFLAG_VXIMZ)
+ fpscr |= FPSCR_VXIMZ;
+ if (eflag & EFLAG_VXVC)
+ fpscr |= FPSCR_VXVC;
+ if (eflag & EFLAG_VXSOFT)
+ fpscr |= FPSCR_VXSOFT;
+ if (eflag & EFLAG_VXSQRT)
+ fpscr |= FPSCR_VXSQRT;
+ if (eflag & EFLAG_VXCVI)
+ fpscr |= FPSCR_VXCVI;
+ }
+
+ fpscr &= ~(FPSCR_VX);
+ if (fpscr & (FPSCR_VXSNAN | FPSCR_VXISI | FPSCR_VXIDI |
+ FPSCR_VXZDZ | FPSCR_VXIMZ | FPSCR_VXVC |
+ FPSCR_VXSOFT | FPSCR_VXSQRT | FPSCR_VXCVI))
+ fpscr |= FPSCR_VX;
+
+ fpscr &= ~(FPSCR_FEX);
+ if (((fpscr & FPSCR_VX) && (fpscr & FPSCR_VE)) ||
+ ((fpscr & FPSCR_OX) && (fpscr & FPSCR_OE)) ||
+ ((fpscr & FPSCR_UX) && (fpscr & FPSCR_UE)) ||
+ ((fpscr & FPSCR_ZX) && (fpscr & FPSCR_ZE)) ||
+ ((fpscr & FPSCR_XX) && (fpscr & FPSCR_XE)))
+ fpscr |= FPSCR_FEX;
+
+ __FPU_FPSCR = fpscr;
+
+ return (fpscr & FPSCR_FEX) ? 1 : 0;
+}
+#endif /* CONFIG_MATH_EMULATION */
+
+int
+do_mathemu(struct pt_regs *regs)
+{
+ void *op0 = 0, *op1 = 0, *op2 = 0, *op3 = 0;
+ unsigned long pc = regs->nip;
+ signed short sdisp;
+ u32 insn = 0;
+ int idx = 0;
+#ifdef CONFIG_MATH_EMULATION
+ int (*func)(void *, void *, void *, void *);
+ int type = 0;
+ int eflag, trap;
+#endif
+
+ if (get_user(insn, (u32 *)pc))
+ return -EFAULT;
+
+#ifndef CONFIG_MATH_EMULATION
+ switch (insn >> 26) {
+ case LFD:
+ idx = (insn >> 16) & 0x1f;
+ sdisp = (insn & 0xffff);
+ op0 = (void *)¤t->thread.fpr[(insn >> 21) & 0x1f];
+ op1 = (void *)((idx ? regs->gpr[idx] : 0) + sdisp);
+ lfd(op0, op1, op2, op3);
+ break;
+ case LFDU:
+ idx = (insn >> 16) & 0x1f;
+ sdisp = (insn & 0xffff);
+ op0 = (void *)¤t->thread.fpr[(insn >> 21) & 0x1f];
+ op1 = (void *)((idx ? regs->gpr[idx] : 0) + sdisp);
+ lfd(op0, op1, op2, op3);
+ regs->gpr[idx] = (unsigned long)op1;
+ break;
+ case STFD:
+ idx = (insn >> 16) & 0x1f;
+ sdisp = (insn & 0xffff);
+ op0 = (void *)¤t->thread.fpr[(insn >> 21) & 0x1f];
+ op1 = (void *)((idx ? regs->gpr[idx] : 0) + sdisp);
+ stfd(op0, op1, op2, op3);
+ break;
+ case STFDU:
+ idx = (insn >> 16) & 0x1f;
+ sdisp = (insn & 0xffff);
+ op0 = (void *)¤t->thread.fpr[(insn >> 21) & 0x1f];
+ op1 = (void *)((idx ? regs->gpr[idx] : 0) + sdisp);
+ stfd(op0, op1, op2, op3);
+ regs->gpr[idx] = (unsigned long)op1;
+ break;
+ case OP63:
+ op0 = (void *)¤t->thread.fpr[(insn >> 21) & 0x1f];
+ op1 = (void *)¤t->thread.fpr[(insn >> 11) & 0x1f];
+ fmr(op0, op1, op2, op3);
+ break;
+ default:
+ goto illegal;
+ }
+#else /* CONFIG_MATH_EMULATION */
+ switch (insn >> 26) {
+ case LFS: func = lfs; type = D; break;
+ case LFSU: func = lfs; type = DU; break;
+ case LFD: func = lfd; type = D; break;
+ case LFDU: func = lfd; type = DU; break;
+ case STFS: func = stfs; type = D; break;
+ case STFSU: func = stfs; type = DU; break;
+ case STFD: func = stfd; type = D; break;
+ case STFDU: func = stfd; type = DU; break;
+
+ case OP31:
+ switch ((insn >> 1) & 0x3ff) {
+ case LFSX: func = lfs; type = XE; break;
+ case LFSUX: func = lfs; type = XEU; break;
+ case LFDX: func = lfd; type = XE; break;
+ case LFDUX: func = lfd; type = XEU; break;
+ case STFSX: func = stfs; type = XE; break;
+ case STFSUX: func = stfs; type = XEU; break;
+ case STFDX: func = stfd; type = XE; break;
+ case STFDUX: func = stfd; type = XEU; break;
+ case STFIWX: func = stfiwx; type = XE; break;
+ default:
+ goto illegal;
+ }
+ break;
+
+ case OP59:
+ switch ((insn >> 1) & 0x1f) {
+ case FDIVS: func = fdivs; type = AB; break;
+ case FSUBS: func = fsubs; type = AB; break;
+ case FADDS: func = fadds; type = AB; break;
+ case FSQRTS: func = fsqrts; type = AB; break;
+ case FRES: func = fres; type = AB; break;
+ case FMULS: func = fmuls; type = AC; break;
+ case FMSUBS: func = fmsubs; type = ABC; break;
+ case FMADDS: func = fmadds; type = ABC; break;
+ case FNMSUBS: func = fnmsubs; type = ABC; break;
+ case FNMADDS: func = fnmadds; type = ABC; break;
+ default:
+ goto illegal;
+ }
+ break;
+
+ case OP63:
+ if (insn & 0x20) {
+ switch ((insn >> 1) & 0x1f) {
+ case FDIV: func = fdiv; type = AB; break;
+ case FSUB: func = fsub; type = AB; break;
+ case FADD: func = fadd; type = AB; break;
+ case FSQRT: func = fsqrt; type = AB; break;
+ case FSEL: func = fsel; type = ABC; break;
+ case FMUL: func = fmul; type = AC; break;
+ case FRSQRTE: func = frsqrte; type = AB; break;
+ case FMSUB: func = fmsub; type = ABC; break;
+ case FMADD: func = fmadd; type = ABC; break;
+ case FNMSUB: func = fnmsub; type = ABC; break;
+ case FNMADD: func = fnmadd; type = ABC; break;
+ default:
+ goto illegal;
+ }
+ break;
+ }
+
+ switch ((insn >> 1) & 0x3ff) {
+ case FCMPU: func = fcmpu; type = XCR; break;
+ case FRSP: func = frsp; type = XB; break;
+ case FCTIW: func = fctiw; type = XB; break;
+ case FCTIWZ: func = fctiwz; type = XB; break;
+ case FCMPO: func = fcmpo; type = XCR; break;
+ case MTFSB1: func = mtfsb1; type = XCRB; break;
+ case FNEG: func = fneg; type = XB; break;
+ case MCRFS: func = mcrfs; type = XCRL; break;
+ case MTFSB0: func = mtfsb0; type = XCRB; break;
+ case FMR: func = fmr; type = XB; break;
+ case MTFSFI: func = mtfsfi; type = XCRI; break;
+ case FNABS: func = fnabs; type = XB; break;
+ case FABS: func = fabs; type = XB; break;
+ case MFFS: func = mffs; type = X; break;
+ case MTFSF: func = mtfsf; type = XFLB; break;
+ default:
+ goto illegal;
+ }
+ break;
+
+ default:
+ goto illegal;
+ }
+
+ switch (type) {
+ case AB:
+ op0 = (void *)¤t->thread.fpr[(insn >> 21) & 0x1f];
+ op1 = (void *)¤t->thread.fpr[(insn >> 16) & 0x1f];
+ op2 = (void *)¤t->thread.fpr[(insn >> 11) & 0x1f];
+ break;
+
+ case AC:
+ op0 = (void *)¤t->thread.fpr[(insn >> 21) & 0x1f];
+ op1 = (void *)¤t->thread.fpr[(insn >> 16) & 0x1f];
+ op2 = (void *)¤t->thread.fpr[(insn >> 6) & 0x1f];
+ break;
+
+ case ABC:
+ op0 = (void *)¤t->thread.fpr[(insn >> 21) & 0x1f];
+ op1 = (void *)¤t->thread.fpr[(insn >> 16) & 0x1f];
+ op2 = (void *)¤t->thread.fpr[(insn >> 11) & 0x1f];
+ op3 = (void *)¤t->thread.fpr[(insn >> 6) & 0x1f];
+ break;
+
+ case D:
+ idx = (insn >> 16) & 0x1f;
+ sdisp = (insn & 0xffff);
+ op0 = (void *)¤t->thread.fpr[(insn >> 21) & 0x1f];
+ op1 = (void *)((idx ? regs->gpr[idx] : 0) + sdisp);
+ break;
+
+ case DU:
+ idx = (insn >> 16) & 0x1f;
+ if (!idx)
+ goto illegal;
+
+ sdisp = (insn & 0xffff);
+ op0 = (void *)¤t->thread.fpr[(insn >> 21) & 0x1f];
+ op1 = (void *)(regs->gpr[idx] + sdisp);
+ break;
+
+ case X:
+ op0 = (void *)¤t->thread.fpr[(insn >> 21) & 0x1f];
+ break;
+
+ case XA:
+ op0 = (void *)¤t->thread.fpr[(insn >> 21) & 0x1f];
+ op1 = (void *)¤t->thread.fpr[(insn >> 16) & 0x1f];
+ break;
+
+ case XB:
+ op0 = (void *)¤t->thread.fpr[(insn >> 21) & 0x1f];
+ op1 = (void *)¤t->thread.fpr[(insn >> 11) & 0x1f];
+ break;
+
+ case XE:
+ idx = (insn >> 16) & 0x1f;
+ if (!idx)
+ goto illegal;
+
+ op0 = (void *)¤t->thread.fpr[(insn >> 21) & 0x1f];
+ op1 = (void *)(regs->gpr[idx] + regs->gpr[(insn >> 11) & 0x1f]);
+ break;
+
+ case XEU:
+ idx = (insn >> 16) & 0x1f;
+ op0 = (void *)¤t->thread.fpr[(insn >> 21) & 0x1f];
+ op1 = (void *)((idx ? regs->gpr[idx] : 0)
+ + regs->gpr[(insn >> 11) & 0x1f]);
+ break;
+
+ case XCR:
+ op0 = (void *)®s->ccr;
+ op1 = (void *)((insn >> 23) & 0x7);
+ op2 = (void *)¤t->thread.fpr[(insn >> 16) & 0x1f];
+ op3 = (void *)¤t->thread.fpr[(insn >> 11) & 0x1f];
+ break;
+
+ case XCRL:
+ op0 = (void *)®s->ccr;
+ op1 = (void *)((insn >> 23) & 0x7);
+ op2 = (void *)((insn >> 18) & 0x7);
+ break;
+
+ case XCRB:
+ op0 = (void *)((insn >> 21) & 0x1f);
+ break;
+
+ case XCRI:
+ op0 = (void *)((insn >> 23) & 0x7);
+ op1 = (void *)((insn >> 12) & 0xf);
+ break;
+
+ case XFLB:
+ op0 = (void *)((insn >> 17) & 0xff);
+ op1 = (void *)¤t->thread.fpr[(insn >> 11) & 0x1f];
+ break;
+
+ default:
+ goto illegal;
+ }
+
+ eflag = func(op0, op1, op2, op3);
+
+ if (insn & 1) {
+ regs->ccr &= ~(0x0f000000);
+ regs->ccr |= (__FPU_FPSCR >> 4) & 0x0f000000;
+ }
+
+ trap = record_exception(regs, eflag);
+ if (trap)
+ return 1;
+
+ switch (type) {
+ case DU:
+ case XEU:
+ regs->gpr[idx] = (unsigned long)op1;
+ break;
+
+ default:
+ break;
+ }
+#endif /* CONFIG_MATH_EMULATION */
+
+ regs->nip += 4;
+ return 0;
+
+illegal:
+ return -ENOSYS;
+}
diff --git a/arch/ppc/math-emu/mcrfs.c b/arch/ppc/math-emu/mcrfs.c
new file mode 100644
index 0000000..106dd91
--- /dev/null
+++ b/arch/ppc/math-emu/mcrfs.c
@@ -0,0 +1,31 @@
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <asm/uaccess.h>
+
+#include "soft-fp.h"
+
+int
+mcrfs(u32 *ccr, u32 crfD, u32 crfS)
+{
+ u32 value, clear;
+
+#ifdef DEBUG
+ printk("%s: %p (%08x) %d %d\n", __FUNCTION__, ccr, *ccr, crfD, crfS);
+#endif
+
+ clear = 15 << ((7 - crfS) << 2);
+ if (!crfS)
+ clear = 0x90000000;
+
+ value = (__FPU_FPSCR >> ((7 - crfS) << 2)) & 15;
+ __FPU_FPSCR &= ~(clear);
+
+ *ccr &= ~(15 << ((7 - crfD) << 2));
+ *ccr |= (value << ((7 - crfD) << 2));
+
+#ifdef DEBUG
+ printk("CR: %08x\n", __FUNCTION__, *ccr);
+#endif
+
+ return 0;
+}
diff --git a/arch/ppc/math-emu/mffs.c b/arch/ppc/math-emu/mffs.c
new file mode 100644
index 0000000..f477c91
--- /dev/null
+++ b/arch/ppc/math-emu/mffs.c
@@ -0,0 +1,17 @@
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <asm/uaccess.h>
+
+#include "soft-fp.h"
+
+int
+mffs(u32 *frD)
+{
+ frD[1] = __FPU_FPSCR;
+
+#ifdef DEBUG
+ printk("%s: frD %p: %08x.%08x\n", __FUNCTION__, frD, frD[0], frD[1]);
+#endif
+
+ return 0;
+}
diff --git a/arch/ppc/math-emu/mtfsb0.c b/arch/ppc/math-emu/mtfsb0.c
new file mode 100644
index 0000000..99bfd80
--- /dev/null
+++ b/arch/ppc/math-emu/mtfsb0.c
@@ -0,0 +1,18 @@
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <asm/uaccess.h>
+
+#include "soft-fp.h"
+
+int
+mtfsb0(int crbD)
+{
+ if ((crbD != 1) && (crbD != 2))
+ __FPU_FPSCR &= ~(1 << (31 - crbD));
+
+#ifdef DEBUG
+ printk("%s: %d %08lx\n", __FUNCTION__, crbD, __FPU_FPSCR);
+#endif
+
+ return 0;
+}
diff --git a/arch/ppc/math-emu/mtfsb1.c b/arch/ppc/math-emu/mtfsb1.c
new file mode 100644
index 0000000..3d9e7ed
--- /dev/null
+++ b/arch/ppc/math-emu/mtfsb1.c
@@ -0,0 +1,18 @@
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <asm/uaccess.h>
+
+#include "soft-fp.h"
+
+int
+mtfsb1(int crbD)
+{
+ if ((crbD != 1) && (crbD != 2))
+ __FPU_FPSCR |= (1 << (31 - crbD));
+
+#ifdef DEBUG
+ printk("%s: %d %08lx\n", __FUNCTION__, crbD, __FPU_FPSCR);
+#endif
+
+ return 0;
+}
diff --git a/arch/ppc/math-emu/mtfsf.c b/arch/ppc/math-emu/mtfsf.c
new file mode 100644
index 0000000..d70cf71
--- /dev/null
+++ b/arch/ppc/math-emu/mtfsf.c
@@ -0,0 +1,45 @@
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <asm/uaccess.h>
+
+#include "soft-fp.h"
+
+int
+mtfsf(unsigned int FM, u32 *frB)
+{
+ u32 mask;
+
+ if (FM == 0)
+ return 0;
+
+ if (FM == 0xff)
+ mask = 0x9fffffff;
+ else {
+ mask = 0;
+ if (FM & (1 << 0))
+ mask |= 0x90000000;
+ if (FM & (1 << 1))
+ mask |= 0x0f000000;
+ if (FM & (1 << 2))
+ mask |= 0x00f00000;
+ if (FM & (1 << 3))
+ mask |= 0x000f0000;
+ if (FM & (1 << 4))
+ mask |= 0x0000f000;
+ if (FM & (1 << 5))
+ mask |= 0x00000f00;
+ if (FM & (1 << 6))
+ mask |= 0x000000f0;
+ if (FM & (1 << 7))
+ mask |= 0x0000000f;
+ }
+
+ __FPU_FPSCR &= ~(mask);
+ __FPU_FPSCR |= (frB[1] & mask);
+
+#ifdef DEBUG
+ printk("%s: %02x %p: %08lx\n", __FUNCTION__, FM, frB, __FPU_FPSCR);
+#endif
+
+ return 0;
+}
diff --git a/arch/ppc/math-emu/mtfsfi.c b/arch/ppc/math-emu/mtfsfi.c
new file mode 100644
index 0000000..71df854
--- /dev/null
+++ b/arch/ppc/math-emu/mtfsfi.c
@@ -0,0 +1,23 @@
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <asm/uaccess.h>
+
+#include "soft-fp.h"
+
+int
+mtfsfi(unsigned int crfD, unsigned int IMM)
+{
+ u32 mask = 0xf;
+
+ if (!crfD)
+ mask = 9;
+
+ __FPU_FPSCR &= ~(mask << ((7 - crfD) << 2));
+ __FPU_FPSCR |= (IMM & 0xf) << ((7 - crfD) << 2);
+
+#ifdef DEBUG
+ printk("%s: %d %x: %08lx\n", __FUNCTION__, crfD, IMM, __FPU_FPSCR);
+#endif
+
+ return 0;
+}
diff --git a/arch/ppc/math-emu/op-1.h b/arch/ppc/math-emu/op-1.h
new file mode 100644
index 0000000..c92fa95
--- /dev/null
+++ b/arch/ppc/math-emu/op-1.h
@@ -0,0 +1,245 @@
+/*
+ * Basic one-word fraction declaration and manipulation.
+ */
+
+#define _FP_FRAC_DECL_1(X) _FP_W_TYPE X##_f
+#define _FP_FRAC_COPY_1(D,S) (D##_f = S##_f)
+#define _FP_FRAC_SET_1(X,I) (X##_f = I)
+#define _FP_FRAC_HIGH_1(X) (X##_f)
+#define _FP_FRAC_LOW_1(X) (X##_f)
+#define _FP_FRAC_WORD_1(X,w) (X##_f)
+
+#define _FP_FRAC_ADDI_1(X,I) (X##_f += I)
+#define _FP_FRAC_SLL_1(X,N) \
+ do { \
+ if (__builtin_constant_p(N) && (N) == 1) \
+ X##_f += X##_f; \
+ else \
+ X##_f <<= (N); \
+ } while (0)
+#define _FP_FRAC_SRL_1(X,N) (X##_f >>= N)
+
+/* Right shift with sticky-lsb. */
+#define _FP_FRAC_SRS_1(X,N,sz) __FP_FRAC_SRS_1(X##_f, N, sz)
+
+#define __FP_FRAC_SRS_1(X,N,sz) \
+ (X = (X >> (N) | (__builtin_constant_p(N) && (N) == 1 \
+ ? X & 1 : (X << (_FP_W_TYPE_SIZE - (N))) != 0)))
+
+#define _FP_FRAC_ADD_1(R,X,Y) (R##_f = X##_f + Y##_f)
+#define _FP_FRAC_SUB_1(R,X,Y) (R##_f = X##_f - Y##_f)
+#define _FP_FRAC_CLZ_1(z, X) __FP_CLZ(z, X##_f)
+
+/* Predicates */
+#define _FP_FRAC_NEGP_1(X) ((_FP_WS_TYPE)X##_f < 0)
+#define _FP_FRAC_ZEROP_1(X) (X##_f == 0)
+#define _FP_FRAC_OVERP_1(fs,X) (X##_f & _FP_OVERFLOW_##fs)
+#define _FP_FRAC_EQ_1(X, Y) (X##_f == Y##_f)
+#define _FP_FRAC_GE_1(X, Y) (X##_f >= Y##_f)
+#define _FP_FRAC_GT_1(X, Y) (X##_f > Y##_f)
+
+#define _FP_ZEROFRAC_1 0
+#define _FP_MINFRAC_1 1
+
+/*
+ * Unpack the raw bits of a native fp value. Do not classify or
+ * normalize the data.
+ */
+
+#define _FP_UNPACK_RAW_1(fs, X, val) \
+ do { \
+ union _FP_UNION_##fs _flo; _flo.flt = (val); \
+ \
+ X##_f = _flo.bits.frac; \
+ X##_e = _flo.bits.exp; \
+ X##_s = _flo.bits.sign; \
+ } while (0)
+
+
+/*
+ * Repack the raw bits of a native fp value.
+ */
+
+#define _FP_PACK_RAW_1(fs, val, X) \
+ do { \
+ union _FP_UNION_##fs _flo; \
+ \
+ _flo.bits.frac = X##_f; \
+ _flo.bits.exp = X##_e; \
+ _flo.bits.sign = X##_s; \
+ \
+ (val) = _flo.flt; \
+ } while (0)
+
+
+/*
+ * Multiplication algorithms:
+ */
+
+/* Basic. Assuming the host word size is >= 2*FRACBITS, we can do the
+ multiplication immediately. */
+
+#define _FP_MUL_MEAT_1_imm(fs, R, X, Y) \
+ do { \
+ R##_f = X##_f * Y##_f; \
+ /* Normalize since we know where the msb of the multiplicands \
+ were (bit B), we know that the msb of the of the product is \
+ at either 2B or 2B-1. */ \
+ _FP_FRAC_SRS_1(R, _FP_WFRACBITS_##fs-1, 2*_FP_WFRACBITS_##fs); \
+ } while (0)
+
+/* Given a 1W * 1W => 2W primitive, do the extended multiplication. */
+
+#define _FP_MUL_MEAT_1_wide(fs, R, X, Y, doit) \
+ do { \
+ _FP_W_TYPE _Z_f0, _Z_f1; \
+ doit(_Z_f1, _Z_f0, X##_f, Y##_f); \
+ /* Normalize since we know where the msb of the multiplicands \
+ were (bit B), we know that the msb of the of the product is \
+ at either 2B or 2B-1. */ \
+ _FP_FRAC_SRS_2(_Z, _FP_WFRACBITS_##fs-1, 2*_FP_WFRACBITS_##fs); \
+ R##_f = _Z_f0; \
+ } while (0)
+
+/* Finally, a simple widening multiply algorithm. What fun! */
+
+#define _FP_MUL_MEAT_1_hard(fs, R, X, Y) \
+ do { \
+ _FP_W_TYPE _xh, _xl, _yh, _yl, _z_f0, _z_f1, _a_f0, _a_f1; \
+ \
+ /* split the words in half */ \
+ _xh = X##_f >> (_FP_W_TYPE_SIZE/2); \
+ _xl = X##_f & (((_FP_W_TYPE)1 << (_FP_W_TYPE_SIZE/2)) - 1); \
+ _yh = Y##_f >> (_FP_W_TYPE_SIZE/2); \
+ _yl = Y##_f & (((_FP_W_TYPE)1 << (_FP_W_TYPE_SIZE/2)) - 1); \
+ \
+ /* multiply the pieces */ \
+ _z_f0 = _xl * _yl; \
+ _a_f0 = _xh * _yl; \
+ _a_f1 = _xl * _yh; \
+ _z_f1 = _xh * _yh; \
+ \
+ /* reassemble into two full words */ \
+ if ((_a_f0 += _a_f1) < _a_f1) \
+ _z_f1 += (_FP_W_TYPE)1 << (_FP_W_TYPE_SIZE/2); \
+ _a_f1 = _a_f0 >> (_FP_W_TYPE_SIZE/2); \
+ _a_f0 = _a_f0 << (_FP_W_TYPE_SIZE/2); \
+ _FP_FRAC_ADD_2(_z, _z, _a); \
+ \
+ /* normalize */ \
+ _FP_FRAC_SRS_2(_z, _FP_WFRACBITS_##fs - 1, 2*_FP_WFRACBITS_##fs); \
+ R##_f = _z_f0; \
+ } while (0)
+
+
+/*
+ * Division algorithms:
+ */
+
+/* Basic. Assuming the host word size is >= 2*FRACBITS, we can do the
+ division immediately. Give this macro either _FP_DIV_HELP_imm for
+ C primitives or _FP_DIV_HELP_ldiv for the ISO function. Which you
+ choose will depend on what the compiler does with divrem4. */
+
+#define _FP_DIV_MEAT_1_imm(fs, R, X, Y, doit) \
+ do { \
+ _FP_W_TYPE _q, _r; \
+ X##_f <<= (X##_f < Y##_f \
+ ? R##_e--, _FP_WFRACBITS_##fs \
+ : _FP_WFRACBITS_##fs - 1); \
+ doit(_q, _r, X##_f, Y##_f); \
+ R##_f = _q | (_r != 0); \
+ } while (0)
+
+/* GCC's longlong.h defines a 2W / 1W => (1W,1W) primitive udiv_qrnnd
+ that may be useful in this situation. This first is for a primitive
+ that requires normalization, the second for one that does not. Look
+ for UDIV_NEEDS_NORMALIZATION to tell which your machine needs. */
+
+#define _FP_DIV_MEAT_1_udiv_norm(fs, R, X, Y) \
+ do { \
+ _FP_W_TYPE _nh, _nl, _q, _r; \
+ \
+ /* Normalize Y -- i.e. make the most significant bit set. */ \
+ Y##_f <<= _FP_WFRACXBITS_##fs - 1; \
+ \
+ /* Shift X op correspondingly high, that is, up one full word. */ \
+ if (X##_f <= Y##_f) \
+ { \
+ _nl = 0; \
+ _nh = X##_f; \
+ } \
+ else \
+ { \
+ R##_e++; \
+ _nl = X##_f << (_FP_W_TYPE_SIZE-1); \
+ _nh = X##_f >> 1; \
+ } \
+ \
+ udiv_qrnnd(_q, _r, _nh, _nl, Y##_f); \
+ R##_f = _q | (_r != 0); \
+ } while (0)
+
+#define _FP_DIV_MEAT_1_udiv(fs, R, X, Y) \
+ do { \
+ _FP_W_TYPE _nh, _nl, _q, _r; \
+ if (X##_f < Y##_f) \
+ { \
+ R##_e--; \
+ _nl = X##_f << _FP_WFRACBITS_##fs; \
+ _nh = X##_f >> _FP_WFRACXBITS_##fs; \
+ } \
+ else \
+ { \
+ _nl = X##_f << (_FP_WFRACBITS_##fs - 1); \
+ _nh = X##_f >> (_FP_WFRACXBITS_##fs + 1); \
+ } \
+ udiv_qrnnd(_q, _r, _nh, _nl, Y##_f); \
+ R##_f = _q | (_r != 0); \
+ } while (0)
+
+
+/*
+ * Square root algorithms:
+ * We have just one right now, maybe Newton approximation
+ * should be added for those machines where division is fast.
+ */
+
+#define _FP_SQRT_MEAT_1(R, S, T, X, q) \
+ do { \
+ while (q) \
+ { \
+ T##_f = S##_f + q; \
+ if (T##_f <= X##_f) \
+ { \
+ S##_f = T##_f + q; \
+ X##_f -= T##_f; \
+ R##_f += q; \
+ } \
+ _FP_FRAC_SLL_1(X, 1); \
+ q >>= 1; \
+ } \
+ } while (0)
+
+/*
+ * Assembly/disassembly for converting to/from integral types.
+ * No shifting or overflow handled here.
+ */
+
+#define _FP_FRAC_ASSEMBLE_1(r, X, rsize) (r = X##_f)
+#define _FP_FRAC_DISASSEMBLE_1(X, r, rsize) (X##_f = r)
+
+
+/*
+ * Convert FP values between word sizes
+ */
+
+#define _FP_FRAC_CONV_1_1(dfs, sfs, D, S) \
+ do { \
+ D##_f = S##_f; \
+ if (_FP_WFRACBITS_##sfs > _FP_WFRACBITS_##dfs) \
+ _FP_FRAC_SRS_1(D, (_FP_WFRACBITS_##sfs-_FP_WFRACBITS_##dfs), \
+ _FP_WFRACBITS_##sfs); \
+ else \
+ D##_f <<= _FP_WFRACBITS_##dfs - _FP_WFRACBITS_##sfs; \
+ } while (0)
diff --git a/arch/ppc/math-emu/op-2.h b/arch/ppc/math-emu/op-2.h
new file mode 100644
index 0000000..b9b06b4
--- /dev/null
+++ b/arch/ppc/math-emu/op-2.h
@@ -0,0 +1,433 @@
+/*
+ * Basic two-word fraction declaration and manipulation.
+ */
+
+#define _FP_FRAC_DECL_2(X) _FP_W_TYPE X##_f0, X##_f1
+#define _FP_FRAC_COPY_2(D,S) (D##_f0 = S##_f0, D##_f1 = S##_f1)
+#define _FP_FRAC_SET_2(X,I) __FP_FRAC_SET_2(X, I)
+#define _FP_FRAC_HIGH_2(X) (X##_f1)
+#define _FP_FRAC_LOW_2(X) (X##_f0)
+#define _FP_FRAC_WORD_2(X,w) (X##_f##w)
+
+#define _FP_FRAC_SLL_2(X,N) \
+ do { \
+ if ((N) < _FP_W_TYPE_SIZE) \
+ { \
+ if (__builtin_constant_p(N) && (N) == 1) \
+ { \
+ X##_f1 = X##_f1 + X##_f1 + (((_FP_WS_TYPE)(X##_f0)) < 0); \
+ X##_f0 += X##_f0; \
+ } \
+ else \
+ { \
+ X##_f1 = X##_f1 << (N) | X##_f0 >> (_FP_W_TYPE_SIZE - (N)); \
+ X##_f0 <<= (N); \
+ } \
+ } \
+ else \
+ { \
+ X##_f1 = X##_f0 << ((N) - _FP_W_TYPE_SIZE); \
+ X##_f0 = 0; \
+ } \
+ } while (0)
+
+#define _FP_FRAC_SRL_2(X,N) \
+ do { \
+ if ((N) < _FP_W_TYPE_SIZE) \
+ { \
+ X##_f0 = X##_f0 >> (N) | X##_f1 << (_FP_W_TYPE_SIZE - (N)); \
+ X##_f1 >>= (N); \
+ } \
+ else \
+ { \
+ X##_f0 = X##_f1 >> ((N) - _FP_W_TYPE_SIZE); \
+ X##_f1 = 0; \
+ } \
+ } while (0)
+
+/* Right shift with sticky-lsb. */
+#define _FP_FRAC_SRS_2(X,N,sz) \
+ do { \
+ if ((N) < _FP_W_TYPE_SIZE) \
+ { \
+ X##_f0 = (X##_f1 << (_FP_W_TYPE_SIZE - (N)) | X##_f0 >> (N) | \
+ (__builtin_constant_p(N) && (N) == 1 \
+ ? X##_f0 & 1 \
+ : (X##_f0 << (_FP_W_TYPE_SIZE - (N))) != 0)); \
+ X##_f1 >>= (N); \
+ } \
+ else \
+ { \
+ X##_f0 = (X##_f1 >> ((N) - _FP_W_TYPE_SIZE) | \
+ (((X##_f1 << (sz - (N))) | X##_f0) != 0)); \
+ X##_f1 = 0; \
+ } \
+ } while (0)
+
+#define _FP_FRAC_ADDI_2(X,I) \
+ __FP_FRAC_ADDI_2(X##_f1, X##_f0, I)
+
+#define _FP_FRAC_ADD_2(R,X,Y) \
+ __FP_FRAC_ADD_2(R##_f1, R##_f0, X##_f1, X##_f0, Y##_f1, Y##_f0)
+
+#define _FP_FRAC_SUB_2(R,X,Y) \
+ __FP_FRAC_SUB_2(R##_f1, R##_f0, X##_f1, X##_f0, Y##_f1, Y##_f0)
+
+#define _FP_FRAC_CLZ_2(R,X) \
+ do { \
+ if (X##_f1) \
+ __FP_CLZ(R,X##_f1); \
+ else \
+ { \
+ __FP_CLZ(R,X##_f0); \
+ R += _FP_W_TYPE_SIZE; \
+ } \
+ } while(0)
+
+/* Predicates */
+#define _FP_FRAC_NEGP_2(X) ((_FP_WS_TYPE)X##_f1 < 0)
+#define _FP_FRAC_ZEROP_2(X) ((X##_f1 | X##_f0) == 0)
+#define _FP_FRAC_OVERP_2(fs,X) (X##_f1 & _FP_OVERFLOW_##fs)
+#define _FP_FRAC_EQ_2(X, Y) (X##_f1 == Y##_f1 && X##_f0 == Y##_f0)
+#define _FP_FRAC_GT_2(X, Y) \
+ ((X##_f1 > Y##_f1) || (X##_f1 == Y##_f1 && X##_f0 > Y##_f0))
+#define _FP_FRAC_GE_2(X, Y) \
+ ((X##_f1 > Y##_f1) || (X##_f1 == Y##_f1 && X##_f0 >= Y##_f0))
+
+#define _FP_ZEROFRAC_2 0, 0
+#define _FP_MINFRAC_2 0, 1
+
+/*
+ * Internals
+ */
+
+#define __FP_FRAC_SET_2(X,I1,I0) (X##_f0 = I0, X##_f1 = I1)
+
+#define __FP_CLZ_2(R, xh, xl) \
+ do { \
+ if (xh) \
+ __FP_CLZ(R,xl); \
+ else \
+ { \
+ __FP_CLZ(R,xl); \
+ R += _FP_W_TYPE_SIZE; \
+ } \
+ } while(0)
+
+#if 0
+
+#ifndef __FP_FRAC_ADDI_2
+#define __FP_FRAC_ADDI_2(xh, xl, i) \
+ (xh += ((xl += i) < i))
+#endif
+#ifndef __FP_FRAC_ADD_2
+#define __FP_FRAC_ADD_2(rh, rl, xh, xl, yh, yl) \
+ (rh = xh + yh + ((rl = xl + yl) < xl))
+#endif
+#ifndef __FP_FRAC_SUB_2
+#define __FP_FRAC_SUB_2(rh, rl, xh, xl, yh, yl) \
+ (rh = xh - yh - ((rl = xl - yl) > xl))
+#endif
+
+#else
+
+#undef __FP_FRAC_ADDI_2
+#define __FP_FRAC_ADDI_2(xh, xl, i) add_ssaaaa(xh, xl, xh, xl, 0, i)
+#undef __FP_FRAC_ADD_2
+#define __FP_FRAC_ADD_2 add_ssaaaa
+#undef __FP_FRAC_SUB_2
+#define __FP_FRAC_SUB_2 sub_ddmmss
+
+#endif
+
+/*
+ * Unpack the raw bits of a native fp value. Do not classify or
+ * normalize the data.
+ */
+
+#define _FP_UNPACK_RAW_2(fs, X, val) \
+ do { \
+ union _FP_UNION_##fs _flo; _flo.flt = (val); \
+ \
+ X##_f0 = _flo.bits.frac0; \
+ X##_f1 = _flo.bits.frac1; \
+ X##_e = _flo.bits.exp; \
+ X##_s = _flo.bits.sign; \
+ } while (0)
+
+
+/*
+ * Repack the raw bits of a native fp value.
+ */
+
+#define _FP_PACK_RAW_2(fs, val, X) \
+ do { \
+ union _FP_UNION_##fs _flo; \
+ \
+ _flo.bits.frac0 = X##_f0; \
+ _flo.bits.frac1 = X##_f1; \
+ _flo.bits.exp = X##_e; \
+ _flo.bits.sign = X##_s; \
+ \
+ (val) = _flo.flt; \
+ } while (0)
+
+
+/*
+ * Multiplication algorithms:
+ */
+
+/* Given a 1W * 1W => 2W primitive, do the extended multiplication. */
+
+#define _FP_MUL_MEAT_2_wide(fs, R, X, Y, doit) \
+ do { \
+ _FP_FRAC_DECL_4(_z); _FP_FRAC_DECL_2(_b); _FP_FRAC_DECL_2(_c); \
+ \
+ doit(_FP_FRAC_WORD_4(_z,1), _FP_FRAC_WORD_4(_z,0), X##_f0, Y##_f0); \
+ doit(_b_f1, _b_f0, X##_f0, Y##_f1); \
+ doit(_c_f1, _c_f0, X##_f1, Y##_f0); \
+ doit(_FP_FRAC_WORD_4(_z,3), _FP_FRAC_WORD_4(_z,2), X##_f1, Y##_f1); \
+ \
+ __FP_FRAC_ADD_4(_FP_FRAC_WORD_4(_z,3),_FP_FRAC_WORD_4(_z,2), \
+ _FP_FRAC_WORD_4(_z,1),_FP_FRAC_WORD_4(_z,0), \
+ 0, _b_f1, _b_f0, 0, \
+ _FP_FRAC_WORD_4(_z,3),_FP_FRAC_WORD_4(_z,2), \
+ _FP_FRAC_WORD_4(_z,1),_FP_FRAC_WORD_4(_z,0)); \
+ __FP_FRAC_ADD_4(_FP_FRAC_WORD_4(_z,3),_FP_FRAC_WORD_4(_z,2), \
+ _FP_FRAC_WORD_4(_z,1),_FP_FRAC_WORD_4(_z,0), \
+ 0, _c_f1, _c_f0, 0, \
+ _FP_FRAC_WORD_4(_z,3),_FP_FRAC_WORD_4(_z,2), \
+ _FP_FRAC_WORD_4(_z,1),_FP_FRAC_WORD_4(_z,0)); \
+ \
+ /* Normalize since we know where the msb of the multiplicands \
+ were (bit B), we know that the msb of the of the product is \
+ at either 2B or 2B-1. */ \
+ _FP_FRAC_SRS_4(_z, _FP_WFRACBITS_##fs-1, 2*_FP_WFRACBITS_##fs); \
+ R##_f0 = _FP_FRAC_WORD_4(_z,0); \
+ R##_f1 = _FP_FRAC_WORD_4(_z,1); \
+ } while (0)
+
+/* This next macro appears to be totally broken. Fortunately nowhere
+ * seems to use it :-> The problem is that we define _z[4] but
+ * then use it in _FP_FRAC_SRS_4, which will attempt to access
+ * _z_f[n] which will cause an error. The fix probably involves
+ * declaring it with _FP_FRAC_DECL_4, see previous macro. -- PMM 02/1998
+ */
+#define _FP_MUL_MEAT_2_gmp(fs, R, X, Y) \
+ do { \
+ _FP_W_TYPE _x[2], _y[2], _z[4]; \
+ _x[0] = X##_f0; _x[1] = X##_f1; \
+ _y[0] = Y##_f0; _y[1] = Y##_f1; \
+ \
+ mpn_mul_n(_z, _x, _y, 2); \
+ \
+ /* Normalize since we know where the msb of the multiplicands \
+ were (bit B), we know that the msb of the of the product is \
+ at either 2B or 2B-1. */ \
+ _FP_FRAC_SRS_4(_z, _FP_WFRACBITS##_fs-1, 2*_FP_WFRACBITS_##fs); \
+ R##_f0 = _z[0]; \
+ R##_f1 = _z[1]; \
+ } while (0)
+
+
+/*
+ * Division algorithms:
+ * This seems to be giving me difficulties -- PMM
+ * Look, NetBSD seems to be able to comment algorithms. Can't you?
+ * I've thrown printks at the problem.
+ * This now appears to work, but I still don't really know why.
+ * Also, I don't think the result is properly normalised...
+ */
+
+#define _FP_DIV_MEAT_2_udiv_64(fs, R, X, Y) \
+ do { \
+ extern void _fp_udivmodti4(_FP_W_TYPE q[2], _FP_W_TYPE r[2], \
+ _FP_W_TYPE n1, _FP_W_TYPE n0, \
+ _FP_W_TYPE d1, _FP_W_TYPE d0); \
+ _FP_W_TYPE _n_f3, _n_f2, _n_f1, _n_f0, _r_f1, _r_f0; \
+ _FP_W_TYPE _q_f1, _q_f0, _m_f1, _m_f0; \
+ _FP_W_TYPE _rmem[2], _qmem[2]; \
+ /* I think this check is to ensure that the result is normalised. \
+ * Assuming X,Y normalised (ie in [1.0,2.0)) X/Y will be in \
+ * [0.5,2.0). Furthermore, it will be less than 1.0 iff X < Y. \
+ * In this case we tweak things. (this is based on comments in \
+ * the NetBSD FPU emulation code. ) \
+ * We know X,Y are normalised because we ensure this as part of \
+ * the unpacking process. -- PMM \
+ */ \
+ if (_FP_FRAC_GT_2(X, Y)) \
+ { \
+/* R##_e++; */ \
+ _n_f3 = X##_f1 >> 1; \
+ _n_f2 = X##_f1 << (_FP_W_TYPE_SIZE - 1) | X##_f0 >> 1; \
+ _n_f1 = X##_f0 << (_FP_W_TYPE_SIZE - 1); \
+ _n_f0 = 0; \
+ } \
+ else \
+ { \
+ R##_e--; \
+ _n_f3 = X##_f1; \
+ _n_f2 = X##_f0; \
+ _n_f1 = _n_f0 = 0; \
+ } \
+ \
+ /* Normalize, i.e. make the most significant bit of the \
+ denominator set. CHANGED: - 1 to nothing -- PMM */ \
+ _FP_FRAC_SLL_2(Y, _FP_WFRACXBITS_##fs /* -1 */); \
+ \
+ /* Do the 256/128 bit division given the 128-bit _fp_udivmodtf4 \
+ primitive snagged from libgcc2.c. */ \
+ \
+ _fp_udivmodti4(_qmem, _rmem, _n_f3, _n_f2, 0, Y##_f1); \
+ _q_f1 = _qmem[0]; \
+ umul_ppmm(_m_f1, _m_f0, _q_f1, Y##_f0); \
+ _r_f1 = _rmem[0]; \
+ _r_f0 = _n_f1; \
+ if (_FP_FRAC_GT_2(_m, _r)) \
+ { \
+ _q_f1--; \
+ _FP_FRAC_ADD_2(_r, _r, Y); \
+ if (_FP_FRAC_GE_2(_r, Y) && _FP_FRAC_GT_2(_m, _r)) \
+ { \
+ _q_f1--; \
+ _FP_FRAC_ADD_2(_r, _r, Y); \
+ } \
+ } \
+ _FP_FRAC_SUB_2(_r, _r, _m); \
+ \
+ _fp_udivmodti4(_qmem, _rmem, _r_f1, _r_f0, 0, Y##_f1); \
+ _q_f0 = _qmem[0]; \
+ umul_ppmm(_m_f1, _m_f0, _q_f0, Y##_f0); \
+ _r_f1 = _rmem[0]; \
+ _r_f0 = _n_f0; \
+ if (_FP_FRAC_GT_2(_m, _r)) \
+ { \
+ _q_f0--; \
+ _FP_FRAC_ADD_2(_r, _r, Y); \
+ if (_FP_FRAC_GE_2(_r, Y) && _FP_FRAC_GT_2(_m, _r)) \
+ { \
+ _q_f0--; \
+ _FP_FRAC_ADD_2(_r, _r, Y); \
+ } \
+ } \
+ _FP_FRAC_SUB_2(_r, _r, _m); \
+ \
+ R##_f1 = _q_f1; \
+ R##_f0 = _q_f0 | ((_r_f1 | _r_f0) != 0); \
+ /* adjust so answer is normalized again. I'm not sure what the \
+ * final sz param should be. In practice it's never used since \
+ * N is 1 which is always going to be < _FP_W_TYPE_SIZE... \
+ */ \
+ /* _FP_FRAC_SRS_2(R,1,_FP_WFRACBITS_##fs); */ \
+ } while (0)
+
+
+#define _FP_DIV_MEAT_2_gmp(fs, R, X, Y) \
+ do { \
+ _FP_W_TYPE _x[4], _y[2], _z[4]; \
+ _y[0] = Y##_f0; _y[1] = Y##_f1; \
+ _x[0] = _x[3] = 0; \
+ if (_FP_FRAC_GT_2(X, Y)) \
+ { \
+ R##_e++; \
+ _x[1] = (X##_f0 << (_FP_WFRACBITS-1 - _FP_W_TYPE_SIZE) | \
+ X##_f1 >> (_FP_W_TYPE_SIZE - \
+ (_FP_WFRACBITS-1 - _FP_W_TYPE_SIZE))); \
+ _x[2] = X##_f1 << (_FP_WFRACBITS-1 - _FP_W_TYPE_SIZE); \
+ } \
+ else \
+ { \
+ _x[1] = (X##_f0 << (_FP_WFRACBITS - _FP_W_TYPE_SIZE) | \
+ X##_f1 >> (_FP_W_TYPE_SIZE - \
+ (_FP_WFRACBITS - _FP_W_TYPE_SIZE))); \
+ _x[2] = X##_f1 << (_FP_WFRACBITS - _FP_W_TYPE_SIZE); \
+ } \
+ \
+ (void) mpn_divrem (_z, 0, _x, 4, _y, 2); \
+ R##_f1 = _z[1]; \
+ R##_f0 = _z[0] | ((_x[0] | _x[1]) != 0); \
+ } while (0)
+
+
+/*
+ * Square root algorithms:
+ * We have just one right now, maybe Newton approximation
+ * should be added for those machines where division is fast.
+ */
+
+#define _FP_SQRT_MEAT_2(R, S, T, X, q) \
+ do { \
+ while (q) \
+ { \
+ T##_f1 = S##_f1 + q; \
+ if (T##_f1 <= X##_f1) \
+ { \
+ S##_f1 = T##_f1 + q; \
+ X##_f1 -= T##_f1; \
+ R##_f1 += q; \
+ } \
+ _FP_FRAC_SLL_2(X, 1); \
+ q >>= 1; \
+ } \
+ q = (_FP_W_TYPE)1 << (_FP_W_TYPE_SIZE - 1); \
+ while (q) \
+ { \
+ T##_f0 = S##_f0 + q; \
+ T##_f1 = S##_f1; \
+ if (T##_f1 < X##_f1 || \
+ (T##_f1 == X##_f1 && T##_f0 < X##_f0)) \
+ { \
+ S##_f0 = T##_f0 + q; \
+ if (((_FP_WS_TYPE)T##_f0) < 0 && \
+ ((_FP_WS_TYPE)S##_f0) >= 0) \
+ S##_f1++; \
+ _FP_FRAC_SUB_2(X, X, T); \
+ R##_f0 += q; \
+ } \
+ _FP_FRAC_SLL_2(X, 1); \
+ q >>= 1; \
+ } \
+ } while (0)
+
+
+/*
+ * Assembly/disassembly for converting to/from integral types.
+ * No shifting or overflow handled here.
+ */
+
+#define _FP_FRAC_ASSEMBLE_2(r, X, rsize) \
+ do { \
+ if (rsize <= _FP_W_TYPE_SIZE) \
+ r = X##_f0; \
+ else \
+ { \
+ r = X##_f1; \
+ r <<= _FP_W_TYPE_SIZE; \
+ r += X##_f0; \
+ } \
+ } while (0)
+
+#define _FP_FRAC_DISASSEMBLE_2(X, r, rsize) \
+ do { \
+ X##_f0 = r; \
+ X##_f1 = (rsize <= _FP_W_TYPE_SIZE ? 0 : r >> _FP_W_TYPE_SIZE); \
+ } while (0)
+
+/*
+ * Convert FP values between word sizes
+ */
+
+#define _FP_FRAC_CONV_1_2(dfs, sfs, D, S) \
+ do { \
+ _FP_FRAC_SRS_2(S, (_FP_WFRACBITS_##sfs - _FP_WFRACBITS_##dfs), \
+ _FP_WFRACBITS_##sfs); \
+ D##_f = S##_f0; \
+ } while (0)
+
+#define _FP_FRAC_CONV_2_1(dfs, sfs, D, S) \
+ do { \
+ D##_f0 = S##_f; \
+ D##_f1 = 0; \
+ _FP_FRAC_SLL_2(D, (_FP_WFRACBITS_##dfs - _FP_WFRACBITS_##sfs)); \
+ } while (0)
+
diff --git a/arch/ppc/math-emu/op-4.h b/arch/ppc/math-emu/op-4.h
new file mode 100644
index 0000000..fcdd6d0
--- /dev/null
+++ b/arch/ppc/math-emu/op-4.h
@@ -0,0 +1,297 @@
+/*
+ * Basic four-word fraction declaration and manipulation.
+ *
+ * When adding quadword support for 32 bit machines, we need
+ * to be a little careful as double multiply uses some of these
+ * macros: (in op-2.h)
+ * _FP_MUL_MEAT_2_wide() uses _FP_FRAC_DECL_4, _FP_FRAC_WORD_4,
+ * _FP_FRAC_ADD_4, _FP_FRAC_SRS_4
+ * _FP_MUL_MEAT_2_gmp() uses _FP_FRAC_SRS_4 (and should use
+ * _FP_FRAC_DECL_4: it appears to be broken and is not used
+ * anywhere anyway. )
+ *
+ * I've now fixed all the macros that were here from the sparc64 code.
+ * [*none* of the shift macros were correct!] -- PMM 02/1998
+ *
+ * The only quadword stuff that remains to be coded is:
+ * 1) the conversion to/from ints, which requires
+ * that we check (in op-common.h) that the following do the right thing
+ * for quadwords: _FP_TO_INT(Q,4,r,X,rsz,rsg), _FP_FROM_INT(Q,4,X,r,rs,rt)
+ * 2) multiply, divide and sqrt, which require:
+ * _FP_MUL_MEAT_4_*(R,X,Y), _FP_DIV_MEAT_4_*(R,X,Y), _FP_SQRT_MEAT_4(R,S,T,X,q),
+ * This also needs _FP_MUL_MEAT_Q and _FP_DIV_MEAT_Q to be defined to
+ * some suitable _FP_MUL_MEAT_4_* macros in sfp-machine.h.
+ * [we're free to choose whatever FP_MUL_MEAT_4_* macros we need for
+ * these; they are used nowhere else. ]
+ */
+
+#define _FP_FRAC_DECL_4(X) _FP_W_TYPE X##_f[4]
+#define _FP_FRAC_COPY_4(D,S) \
+ (D##_f[0] = S##_f[0], D##_f[1] = S##_f[1], \
+ D##_f[2] = S##_f[2], D##_f[3] = S##_f[3])
+/* The _FP_FRAC_SET_n(X,I) macro is intended for use with another
+ * macro such as _FP_ZEROFRAC_n which returns n comma separated values.
+ * The result is that we get an expansion of __FP_FRAC_SET_n(X,I0,I1,I2,I3)
+ * which just assigns the In values to the array X##_f[].
+ * This is why the number of parameters doesn't appear to match
+ * at first glance... -- PMM
+ */
+#define _FP_FRAC_SET_4(X,I) __FP_FRAC_SET_4(X, I)
+#define _FP_FRAC_HIGH_4(X) (X##_f[3])
+#define _FP_FRAC_LOW_4(X) (X##_f[0])
+#define _FP_FRAC_WORD_4(X,w) (X##_f[w])
+
+#define _FP_FRAC_SLL_4(X,N) \
+ do { \
+ _FP_I_TYPE _up, _down, _skip, _i; \
+ _skip = (N) / _FP_W_TYPE_SIZE; \
+ _up = (N) % _FP_W_TYPE_SIZE; \
+ _down = _FP_W_TYPE_SIZE - _up; \
+ for (_i = 3; _i > _skip; --_i) \
+ X##_f[_i] = X##_f[_i-_skip] << _up | X##_f[_i-_skip-1] >> _down; \
+/* bugfixed: was X##_f[_i] <<= _up; -- PMM 02/1998 */ \
+ X##_f[_i] = X##_f[0] << _up; \
+ for (--_i; _i >= 0; --_i) \
+ X##_f[_i] = 0; \
+ } while (0)
+
+/* This one was broken too */
+#define _FP_FRAC_SRL_4(X,N) \
+ do { \
+ _FP_I_TYPE _up, _down, _skip, _i; \
+ _skip = (N) / _FP_W_TYPE_SIZE; \
+ _down = (N) % _FP_W_TYPE_SIZE; \
+ _up = _FP_W_TYPE_SIZE - _down; \
+ for (_i = 0; _i < 3-_skip; ++_i) \
+ X##_f[_i] = X##_f[_i+_skip] >> _down | X##_f[_i+_skip+1] << _up; \
+ X##_f[_i] = X##_f[3] >> _down; \
+ for (++_i; _i < 4; ++_i) \
+ X##_f[_i] = 0; \
+ } while (0)
+
+
+/* Right shift with sticky-lsb.
+ * What this actually means is that we do a standard right-shift,
+ * but that if any of the bits that fall off the right hand side
+ * were one then we always set the LSbit.
+ */
+#define _FP_FRAC_SRS_4(X,N,size) \
+ do { \
+ _FP_I_TYPE _up, _down, _skip, _i; \
+ _FP_W_TYPE _s; \
+ _skip = (N) / _FP_W_TYPE_SIZE; \
+ _down = (N) % _FP_W_TYPE_SIZE; \
+ _up = _FP_W_TYPE_SIZE - _down; \
+ for (_s = _i = 0; _i < _skip; ++_i) \
+ _s |= X##_f[_i]; \
+ _s |= X##_f[_i] << _up; \
+/* s is now != 0 if we want to set the LSbit */ \
+ for (_i = 0; _i < 3-_skip; ++_i) \
+ X##_f[_i] = X##_f[_i+_skip] >> _down | X##_f[_i+_skip+1] << _up; \
+ X##_f[_i] = X##_f[3] >> _down; \
+ for (++_i; _i < 4; ++_i) \
+ X##_f[_i] = 0; \
+ /* don't fix the LSB until the very end when we're sure f[0] is stable */ \
+ X##_f[0] |= (_s != 0); \
+ } while (0)
+
+#define _FP_FRAC_ADD_4(R,X,Y) \
+ __FP_FRAC_ADD_4(R##_f[3], R##_f[2], R##_f[1], R##_f[0], \
+ X##_f[3], X##_f[2], X##_f[1], X##_f[0], \
+ Y##_f[3], Y##_f[2], Y##_f[1], Y##_f[0])
+
+#define _FP_FRAC_SUB_4(R,X,Y) \
+ __FP_FRAC_SUB_4(R##_f[3], R##_f[2], R##_f[1], R##_f[0], \
+ X##_f[3], X##_f[2], X##_f[1], X##_f[0], \
+ Y##_f[3], Y##_f[2], Y##_f[1], Y##_f[0])
+
+#define _FP_FRAC_ADDI_4(X,I) \
+ __FP_FRAC_ADDI_4(X##_f[3], X##_f[2], X##_f[1], X##_f[0], I)
+
+#define _FP_ZEROFRAC_4 0,0,0,0
+#define _FP_MINFRAC_4 0,0,0,1
+
+#define _FP_FRAC_ZEROP_4(X) ((X##_f[0] | X##_f[1] | X##_f[2] | X##_f[3]) == 0)
+#define _FP_FRAC_NEGP_4(X) ((_FP_WS_TYPE)X##_f[3] < 0)
+#define _FP_FRAC_OVERP_4(fs,X) (X##_f[0] & _FP_OVERFLOW_##fs)
+
+#define _FP_FRAC_EQ_4(X,Y) \
+ (X##_f[0] == Y##_f[0] && X##_f[1] == Y##_f[1] \
+ && X##_f[2] == Y##_f[2] && X##_f[3] == Y##_f[3])
+
+#define _FP_FRAC_GT_4(X,Y) \
+ (X##_f[3] > Y##_f[3] || \
+ (X##_f[3] == Y##_f[3] && (X##_f[2] > Y##_f[2] || \
+ (X##_f[2] == Y##_f[2] && (X##_f[1] > Y##_f[1] || \
+ (X##_f[1] == Y##_f[1] && X##_f[0] > Y##_f[0]) \
+ )) \
+ )) \
+ )
+
+#define _FP_FRAC_GE_4(X,Y) \
+ (X##_f[3] > Y##_f[3] || \
+ (X##_f[3] == Y##_f[3] && (X##_f[2] > Y##_f[2] || \
+ (X##_f[2] == Y##_f[2] && (X##_f[1] > Y##_f[1] || \
+ (X##_f[1] == Y##_f[1] && X##_f[0] >= Y##_f[0]) \
+ )) \
+ )) \
+ )
+
+
+#define _FP_FRAC_CLZ_4(R,X) \
+ do { \
+ if (X##_f[3]) \
+ { \
+ __FP_CLZ(R,X##_f[3]); \
+ } \
+ else if (X##_f[2]) \
+ { \
+ __FP_CLZ(R,X##_f[2]); \
+ R += _FP_W_TYPE_SIZE; \
+ } \
+ else if (X##_f[1]) \
+ { \
+ __FP_CLZ(R,X##_f[2]); \
+ R += _FP_W_TYPE_SIZE*2; \
+ } \
+ else \
+ { \
+ __FP_CLZ(R,X##_f[0]); \
+ R += _FP_W_TYPE_SIZE*3; \
+ } \
+ } while(0)
+
+
+#define _FP_UNPACK_RAW_4(fs, X, val) \
+ do { \
+ union _FP_UNION_##fs _flo; _flo.flt = (val); \
+ X##_f[0] = _flo.bits.frac0; \
+ X##_f[1] = _flo.bits.frac1; \
+ X##_f[2] = _flo.bits.frac2; \
+ X##_f[3] = _flo.bits.frac3; \
+ X##_e = _flo.bits.exp; \
+ X##_s = _flo.bits.sign; \
+ } while (0)
+
+#define _FP_PACK_RAW_4(fs, val, X) \
+ do { \
+ union _FP_UNION_##fs _flo; \
+ _flo.bits.frac0 = X##_f[0]; \
+ _flo.bits.frac1 = X##_f[1]; \
+ _flo.bits.frac2 = X##_f[2]; \
+ _flo.bits.frac3 = X##_f[3]; \
+ _flo.bits.exp = X##_e; \
+ _flo.bits.sign = X##_s; \
+ (val) = _flo.flt; \
+ } while (0)
+
+
+/*
+ * Internals
+ */
+
+#define __FP_FRAC_SET_4(X,I3,I2,I1,I0) \
+ (X##_f[3] = I3, X##_f[2] = I2, X##_f[1] = I1, X##_f[0] = I0)
+
+#ifndef __FP_FRAC_ADD_4
+#define __FP_FRAC_ADD_4(r3,r2,r1,r0,x3,x2,x1,x0,y3,y2,y1,y0) \
+ (r0 = x0 + y0, \
+ r1 = x1 + y1 + (r0 < x0), \
+ r2 = x2 + y2 + (r1 < x1), \
+ r3 = x3 + y3 + (r2 < x2))
+#endif
+
+#ifndef __FP_FRAC_SUB_4
+#define __FP_FRAC_SUB_4(r3,r2,r1,r0,x3,x2,x1,x0,y3,y2,y1,y0) \
+ (r0 = x0 - y0, \
+ r1 = x1 - y1 - (r0 > x0), \
+ r2 = x2 - y2 - (r1 > x1), \
+ r3 = x3 - y3 - (r2 > x2))
+#endif
+
+#ifndef __FP_FRAC_ADDI_4
+/* I always wanted to be a lisp programmer :-> */
+#define __FP_FRAC_ADDI_4(x3,x2,x1,x0,i) \
+ (x3 += ((x2 += ((x1 += ((x0 += i) < x0)) < x1) < x2)))
+#endif
+
+/* Convert FP values between word sizes. This appears to be more
+ * complicated than I'd have expected it to be, so these might be
+ * wrong... These macros are in any case somewhat bogus because they
+ * use information about what various FRAC_n variables look like
+ * internally [eg, that 2 word vars are X_f0 and x_f1]. But so do
+ * the ones in op-2.h and op-1.h.
+ */
+#define _FP_FRAC_CONV_1_4(dfs, sfs, D, S) \
+ do { \
+ _FP_FRAC_SRS_4(S, (_FP_WFRACBITS_##sfs - _FP_WFRACBITS_##dfs), \
+ _FP_WFRACBITS_##sfs); \
+ D##_f = S##_f[0]; \
+ } while (0)
+
+#define _FP_FRAC_CONV_2_4(dfs, sfs, D, S) \
+ do { \
+ _FP_FRAC_SRS_4(S, (_FP_WFRACBITS_##sfs - _FP_WFRACBITS_##dfs), \
+ _FP_WFRACBITS_##sfs); \
+ D##_f0 = S##_f[0]; \
+ D##_f1 = S##_f[1]; \
+ } while (0)
+
+/* Assembly/disassembly for converting to/from integral types.
+ * No shifting or overflow handled here.
+ */
+/* Put the FP value X into r, which is an integer of size rsize. */
+#define _FP_FRAC_ASSEMBLE_4(r, X, rsize) \
+ do { \
+ if (rsize <= _FP_W_TYPE_SIZE) \
+ r = X##_f[0]; \
+ else if (rsize <= 2*_FP_W_TYPE_SIZE) \
+ { \
+ r = X##_f[1]; \
+ r <<= _FP_W_TYPE_SIZE; \
+ r += X##_f[0]; \
+ } \
+ else \
+ { \
+ /* I'm feeling lazy so we deal with int == 3words (implausible)*/ \
+ /* and int == 4words as a single case. */ \
+ r = X##_f[3]; \
+ r <<= _FP_W_TYPE_SIZE; \
+ r += X##_f[2]; \
+ r <<= _FP_W_TYPE_SIZE; \
+ r += X##_f[1]; \
+ r <<= _FP_W_TYPE_SIZE; \
+ r += X##_f[0]; \
+ } \
+ } while (0)
+
+/* "No disassemble Number Five!" */
+/* move an integer of size rsize into X's fractional part. We rely on
+ * the _f[] array consisting of words of size _FP_W_TYPE_SIZE to avoid
+ * having to mask the values we store into it.
+ */
+#define _FP_FRAC_DISASSEMBLE_4(X, r, rsize) \
+ do { \
+ X##_f[0] = r; \
+ X##_f[1] = (rsize <= _FP_W_TYPE_SIZE ? 0 : r >> _FP_W_TYPE_SIZE); \
+ X##_f[2] = (rsize <= 2*_FP_W_TYPE_SIZE ? 0 : r >> 2*_FP_W_TYPE_SIZE); \
+ X##_f[3] = (rsize <= 3*_FP_W_TYPE_SIZE ? 0 : r >> 3*_FP_W_TYPE_SIZE); \
+ } while (0)
+
+#define _FP_FRAC_CONV_4_1(dfs, sfs, D, S) \
+ do { \
+ D##_f[0] = S##_f; \
+ D##_f[1] = D##_f[2] = D##_f[3] = 0; \
+ _FP_FRAC_SLL_4(D, (_FP_WFRACBITS_##dfs - _FP_WFRACBITS_##sfs)); \
+ } while (0)
+
+#define _FP_FRAC_CONV_4_2(dfs, sfs, D, S) \
+ do { \
+ D##_f[0] = S##_f0; \
+ D##_f[1] = S##_f1; \
+ D##_f[2] = D##_f[3] = 0; \
+ _FP_FRAC_SLL_4(D, (_FP_WFRACBITS_##dfs - _FP_WFRACBITS_##sfs)); \
+ } while (0)
+
+/* FIXME! This has to be written */
+#define _FP_SQRT_MEAT_4(R, S, T, X, q)
diff --git a/arch/ppc/math-emu/op-common.h b/arch/ppc/math-emu/op-common.h
new file mode 100644
index 0000000..afb82b6
--- /dev/null
+++ b/arch/ppc/math-emu/op-common.h
@@ -0,0 +1,688 @@
+#define _FP_DECL(wc, X) \
+ _FP_I_TYPE X##_c, X##_s, X##_e; \
+ _FP_FRAC_DECL_##wc(X)
+
+/*
+ * Finish truely unpacking a native fp value by classifying the kind
+ * of fp value and normalizing both the exponent and the fraction.
+ */
+
+#define _FP_UNPACK_CANONICAL(fs, wc, X) \
+do { \
+ switch (X##_e) \
+ { \
+ default: \
+ _FP_FRAC_HIGH_##wc(X) |= _FP_IMPLBIT_##fs; \
+ _FP_FRAC_SLL_##wc(X, _FP_WORKBITS); \
+ X##_e -= _FP_EXPBIAS_##fs; \
+ X##_c = FP_CLS_NORMAL; \
+ break; \
+ \
+ case 0: \
+ if (_FP_FRAC_ZEROP_##wc(X)) \
+ X##_c = FP_CLS_ZERO; \
+ else \
+ { \
+ /* a denormalized number */ \
+ _FP_I_TYPE _shift; \
+ _FP_FRAC_CLZ_##wc(_shift, X); \
+ _shift -= _FP_FRACXBITS_##fs; \
+ _FP_FRAC_SLL_##wc(X, (_shift+_FP_WORKBITS)); \
+ X##_e -= _FP_EXPBIAS_##fs - 1 + _shift; \
+ X##_c = FP_CLS_NORMAL; \
+ } \
+ break; \
+ \
+ case _FP_EXPMAX_##fs: \
+ if (_FP_FRAC_ZEROP_##wc(X)) \
+ X##_c = FP_CLS_INF; \
+ else \
+ /* we don't differentiate between signaling and quiet nans */ \
+ X##_c = FP_CLS_NAN; \
+ break; \
+ } \
+} while (0)
+
+
+/*
+ * Before packing the bits back into the native fp result, take care
+ * of such mundane things as rounding and overflow. Also, for some
+ * kinds of fp values, the original parts may not have been fully
+ * extracted -- but that is ok, we can regenerate them now.
+ */
+
+#define _FP_PACK_CANONICAL(fs, wc, X) \
+({int __ret = 0; \
+ switch (X##_c) \
+ { \
+ case FP_CLS_NORMAL: \
+ X##_e += _FP_EXPBIAS_##fs; \
+ if (X##_e > 0) \
+ { \
+ __ret |= _FP_ROUND(wc, X); \
+ if (_FP_FRAC_OVERP_##wc(fs, X)) \
+ { \
+ _FP_FRAC_SRL_##wc(X, (_FP_WORKBITS+1)); \
+ X##_e++; \
+ } \
+ else \
+ _FP_FRAC_SRL_##wc(X, _FP_WORKBITS); \
+ if (X##_e >= _FP_EXPMAX_##fs) \
+ { \
+ /* overflow to infinity */ \
+ X##_e = _FP_EXPMAX_##fs; \
+ _FP_FRAC_SET_##wc(X, _FP_ZEROFRAC_##wc); \
+ __ret |= EFLAG_OVERFLOW; \
+ } \
+ } \
+ else \
+ { \
+ /* we've got a denormalized number */ \
+ X##_e = -X##_e + 1; \
+ if (X##_e <= _FP_WFRACBITS_##fs) \
+ { \
+ _FP_FRAC_SRS_##wc(X, X##_e, _FP_WFRACBITS_##fs); \
+ _FP_FRAC_SLL_##wc(X, 1); \
+ if (_FP_FRAC_OVERP_##wc(fs, X)) \
+ { \
+ X##_e = 1; \
+ _FP_FRAC_SET_##wc(X, _FP_ZEROFRAC_##wc); \
+ } \
+ else \
+ { \
+ X##_e = 0; \
+ _FP_FRAC_SRL_##wc(X, _FP_WORKBITS+1); \
+ __ret |= EFLAG_UNDERFLOW; \
+ } \
+ } \
+ else \
+ { \
+ /* underflow to zero */ \
+ X##_e = 0; \
+ _FP_FRAC_SET_##wc(X, _FP_ZEROFRAC_##wc); \
+ __ret |= EFLAG_UNDERFLOW; \
+ } \
+ } \
+ break; \
+ \
+ case FP_CLS_ZERO: \
+ X##_e = 0; \
+ _FP_FRAC_SET_##wc(X, _FP_ZEROFRAC_##wc); \
+ break; \
+ \
+ case FP_CLS_INF: \
+ X##_e = _FP_EXPMAX_##fs; \
+ _FP_FRAC_SET_##wc(X, _FP_ZEROFRAC_##wc); \
+ break; \
+ \
+ case FP_CLS_NAN: \
+ X##_e = _FP_EXPMAX_##fs; \
+ if (!_FP_KEEPNANFRACP) \
+ { \
+ _FP_FRAC_SET_##wc(X, _FP_NANFRAC_##fs); \
+ X##_s = 0; \
+ } \
+ else \
+ _FP_FRAC_HIGH_##wc(X) |= _FP_QNANBIT_##fs; \
+ break; \
+ } \
+ __ret; \
+})
+
+
+/*
+ * Main addition routine. The input values should be cooked.
+ */
+
+#define _FP_ADD(fs, wc, R, X, Y) \
+do { \
+ switch (_FP_CLS_COMBINE(X##_c, Y##_c)) \
+ { \
+ case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_NORMAL): \
+ { \
+ /* shift the smaller number so that its exponent matches the larger */ \
+ _FP_I_TYPE diff = X##_e - Y##_e; \
+ \
+ if (diff < 0) \
+ { \
+ diff = -diff; \
+ if (diff <= _FP_WFRACBITS_##fs) \
+ _FP_FRAC_SRS_##wc(X, diff, _FP_WFRACBITS_##fs); \
+ else if (!_FP_FRAC_ZEROP_##wc(X)) \
+ _FP_FRAC_SET_##wc(X, _FP_MINFRAC_##wc); \
+ else \
+ _FP_FRAC_SET_##wc(X, _FP_ZEROFRAC_##wc); \
+ R##_e = Y##_e; \
+ } \
+ else \
+ { \
+ if (diff > 0) \
+ { \
+ if (diff <= _FP_WFRACBITS_##fs) \
+ _FP_FRAC_SRS_##wc(Y, diff, _FP_WFRACBITS_##fs); \
+ else if (!_FP_FRAC_ZEROP_##wc(Y)) \
+ _FP_FRAC_SET_##wc(Y, _FP_MINFRAC_##wc); \
+ else \
+ _FP_FRAC_SET_##wc(Y, _FP_ZEROFRAC_##wc); \
+ } \
+ R##_e = X##_e; \
+ } \
+ \
+ R##_c = FP_CLS_NORMAL; \
+ \
+ if (X##_s == Y##_s) \
+ { \
+ R##_s = X##_s; \
+ _FP_FRAC_ADD_##wc(R, X, Y); \
+ if (_FP_FRAC_OVERP_##wc(fs, R)) \
+ { \
+ _FP_FRAC_SRS_##wc(R, 1, _FP_WFRACBITS_##fs); \
+ R##_e++; \
+ } \
+ } \
+ else \
+ { \
+ R##_s = X##_s; \
+ _FP_FRAC_SUB_##wc(R, X, Y); \
+ if (_FP_FRAC_ZEROP_##wc(R)) \
+ { \
+ /* return an exact zero */ \
+ if (FP_ROUNDMODE == FP_RND_MINF) \
+ R##_s |= Y##_s; \
+ else \
+ R##_s &= Y##_s; \
+ R##_c = FP_CLS_ZERO; \
+ } \
+ else \
+ { \
+ if (_FP_FRAC_NEGP_##wc(R)) \
+ { \
+ _FP_FRAC_SUB_##wc(R, Y, X); \
+ R##_s = Y##_s; \
+ } \
+ \
+ /* renormalize after subtraction */ \
+ _FP_FRAC_CLZ_##wc(diff, R); \
+ diff -= _FP_WFRACXBITS_##fs; \
+ if (diff) \
+ { \
+ R##_e -= diff; \
+ _FP_FRAC_SLL_##wc(R, diff); \
+ } \
+ } \
+ } \
+ break; \
+ } \
+ \
+ case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_NAN): \
+ _FP_CHOOSENAN(fs, wc, R, X, Y); \
+ break; \
+ \
+ case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_ZERO): \
+ R##_e = X##_e; \
+ case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_NORMAL): \
+ case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_INF): \
+ case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_ZERO): \
+ _FP_FRAC_COPY_##wc(R, X); \
+ R##_s = X##_s; \
+ R##_c = X##_c; \
+ break; \
+ \
+ case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_NORMAL): \
+ R##_e = Y##_e; \
+ case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_NAN): \
+ case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_NAN): \
+ case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_NAN): \
+ _FP_FRAC_COPY_##wc(R, Y); \
+ R##_s = Y##_s; \
+ R##_c = Y##_c; \
+ break; \
+ \
+ case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_INF): \
+ if (X##_s != Y##_s) \
+ { \
+ /* +INF + -INF => NAN */ \
+ _FP_FRAC_SET_##wc(R, _FP_NANFRAC_##fs); \
+ R##_s = X##_s ^ Y##_s; \
+ R##_c = FP_CLS_NAN; \
+ break; \
+ } \
+ /* FALLTHRU */ \
+ \
+ case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_NORMAL): \
+ case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_ZERO): \
+ R##_s = X##_s; \
+ R##_c = FP_CLS_INF; \
+ break; \
+ \
+ case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_INF): \
+ case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_INF): \
+ R##_s = Y##_s; \
+ R##_c = FP_CLS_INF; \
+ break; \
+ \
+ case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_ZERO): \
+ /* make sure the sign is correct */ \
+ if (FP_ROUNDMODE == FP_RND_MINF) \
+ R##_s = X##_s | Y##_s; \
+ else \
+ R##_s = X##_s & Y##_s; \
+ R##_c = FP_CLS_ZERO; \
+ break; \
+ \
+ default: \
+ abort(); \
+ } \
+} while (0)
+
+
+/*
+ * Main negation routine. FIXME -- when we care about setting exception
+ * bits reliably, this will not do. We should examine all of the fp classes.
+ */
+
+#define _FP_NEG(fs, wc, R, X) \
+ do { \
+ _FP_FRAC_COPY_##wc(R, X); \
+ R##_c = X##_c; \
+ R##_e = X##_e; \
+ R##_s = 1 ^ X##_s; \
+ } while (0)
+
+
+/*
+ * Main multiplication routine. The input values should be cooked.
+ */
+
+#define _FP_MUL(fs, wc, R, X, Y) \
+do { \
+ R##_s = X##_s ^ Y##_s; \
+ switch (_FP_CLS_COMBINE(X##_c, Y##_c)) \
+ { \
+ case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_NORMAL): \
+ R##_c = FP_CLS_NORMAL; \
+ R##_e = X##_e + Y##_e + 1; \
+ \
+ _FP_MUL_MEAT_##fs(R,X,Y); \
+ \
+ if (_FP_FRAC_OVERP_##wc(fs, R)) \
+ _FP_FRAC_SRS_##wc(R, 1, _FP_WFRACBITS_##fs); \
+ else \
+ R##_e--; \
+ break; \
+ \
+ case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_NAN): \
+ _FP_CHOOSENAN(fs, wc, R, X, Y); \
+ break; \
+ \
+ case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_NORMAL): \
+ case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_INF): \
+ case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_ZERO): \
+ R##_s = X##_s; \
+ \
+ case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_INF): \
+ case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_NORMAL): \
+ case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_NORMAL): \
+ case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_ZERO): \
+ _FP_FRAC_COPY_##wc(R, X); \
+ R##_c = X##_c; \
+ break; \
+ \
+ case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_NAN): \
+ case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_NAN): \
+ case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_NAN): \
+ R##_s = Y##_s; \
+ \
+ case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_INF): \
+ case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_ZERO): \
+ _FP_FRAC_COPY_##wc(R, Y); \
+ R##_c = Y##_c; \
+ break; \
+ \
+ case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_ZERO): \
+ case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_INF): \
+ R##_c = FP_CLS_NAN; \
+ _FP_FRAC_SET_##wc(R, _FP_NANFRAC_##fs); \
+ break; \
+ \
+ default: \
+ abort(); \
+ } \
+} while (0)
+
+
+/*
+ * Main division routine. The input values should be cooked.
+ */
+
+#define _FP_DIV(fs, wc, R, X, Y) \
+do { \
+ R##_s = X##_s ^ Y##_s; \
+ switch (_FP_CLS_COMBINE(X##_c, Y##_c)) \
+ { \
+ case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_NORMAL): \
+ R##_c = FP_CLS_NORMAL; \
+ R##_e = X##_e - Y##_e; \
+ \
+ _FP_DIV_MEAT_##fs(R,X,Y); \
+ break; \
+ \
+ case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_NAN): \
+ _FP_CHOOSENAN(fs, wc, R, X, Y); \
+ break; \
+ \
+ case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_NORMAL): \
+ case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_INF): \
+ case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_ZERO): \
+ R##_s = X##_s; \
+ _FP_FRAC_COPY_##wc(R, X); \
+ R##_c = X##_c; \
+ break; \
+ \
+ case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_NAN): \
+ case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_NAN): \
+ case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_NAN): \
+ R##_s = Y##_s; \
+ _FP_FRAC_COPY_##wc(R, Y); \
+ R##_c = Y##_c; \
+ break; \
+ \
+ case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_INF): \
+ case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_INF): \
+ case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_NORMAL): \
+ R##_c = FP_CLS_ZERO; \
+ break; \
+ \
+ case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_ZERO): \
+ case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_ZERO): \
+ case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_NORMAL): \
+ R##_c = FP_CLS_INF; \
+ break; \
+ \
+ case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_INF): \
+ case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_ZERO): \
+ R##_c = FP_CLS_NAN; \
+ _FP_FRAC_SET_##wc(R, _FP_NANFRAC_##fs); \
+ break; \
+ \
+ default: \
+ abort(); \
+ } \
+} while (0)
+
+
+/*
+ * Main differential comparison routine. The inputs should be raw not
+ * cooked. The return is -1,0,1 for normal values, 2 otherwise.
+ */
+
+#define _FP_CMP(fs, wc, ret, X, Y, un) \
+ do { \
+ /* NANs are unordered */ \
+ if ((X##_e == _FP_EXPMAX_##fs && !_FP_FRAC_ZEROP_##wc(X)) \
+ || (Y##_e == _FP_EXPMAX_##fs && !_FP_FRAC_ZEROP_##wc(Y))) \
+ { \
+ ret = un; \
+ } \
+ else \
+ { \
+ int __x_zero = (!X##_e && _FP_FRAC_ZEROP_##wc(X)) ? 1 : 0; \
+ int __y_zero = (!Y##_e && _FP_FRAC_ZEROP_##wc(Y)) ? 1 : 0; \
+ \
+ if (__x_zero && __y_zero) \
+ ret = 0; \
+ else if (__x_zero) \
+ ret = Y##_s ? 1 : -1; \
+ else if (__y_zero) \
+ ret = X##_s ? -1 : 1; \
+ else if (X##_s != Y##_s) \
+ ret = X##_s ? -1 : 1; \
+ else if (X##_e > Y##_e) \
+ ret = X##_s ? -1 : 1; \
+ else if (X##_e < Y##_e) \
+ ret = X##_s ? 1 : -1; \
+ else if (_FP_FRAC_GT_##wc(X, Y)) \
+ ret = X##_s ? -1 : 1; \
+ else if (_FP_FRAC_GT_##wc(Y, X)) \
+ ret = X##_s ? 1 : -1; \
+ else \
+ ret = 0; \
+ } \
+ } while (0)
+
+
+/* Simplification for strict equality. */
+
+#define _FP_CMP_EQ(fs, wc, ret, X, Y) \
+ do { \
+ /* NANs are unordered */ \
+ if ((X##_e == _FP_EXPMAX_##fs && !_FP_FRAC_ZEROP_##wc(X)) \
+ || (Y##_e == _FP_EXPMAX_##fs && !_FP_FRAC_ZEROP_##wc(Y))) \
+ { \
+ ret = 1; \
+ } \
+ else \
+ { \
+ ret = !(X##_e == Y##_e \
+ && _FP_FRAC_EQ_##wc(X, Y) \
+ && (X##_s == Y##_s || !X##_e && _FP_FRAC_ZEROP_##wc(X))); \
+ } \
+ } while (0)
+
+/*
+ * Main square root routine. The input value should be cooked.
+ */
+
+#define _FP_SQRT(fs, wc, R, X) \
+do { \
+ _FP_FRAC_DECL_##wc(T); _FP_FRAC_DECL_##wc(S); \
+ _FP_W_TYPE q; \
+ switch (X##_c) \
+ { \
+ case FP_CLS_NAN: \
+ R##_s = 0; \
+ R##_c = FP_CLS_NAN; \
+ _FP_FRAC_SET_##wc(X, _FP_ZEROFRAC_##wc); \
+ break; \
+ case FP_CLS_INF: \
+ if (X##_s) \
+ { \
+ R##_s = 0; \
+ R##_c = FP_CLS_NAN; /* sNAN */ \
+ } \
+ else \
+ { \
+ R##_s = 0; \
+ R##_c = FP_CLS_INF; /* sqrt(+inf) = +inf */ \
+ } \
+ break; \
+ case FP_CLS_ZERO: \
+ R##_s = X##_s; \
+ R##_c = FP_CLS_ZERO; /* sqrt(+-0) = +-0 */ \
+ break; \
+ case FP_CLS_NORMAL: \
+ R##_s = 0; \
+ if (X##_s) \
+ { \
+ R##_c = FP_CLS_NAN; /* sNAN */ \
+ break; \
+ } \
+ R##_c = FP_CLS_NORMAL; \
+ if (X##_e & 1) \
+ _FP_FRAC_SLL_##wc(X, 1); \
+ R##_e = X##_e >> 1; \
+ _FP_FRAC_SET_##wc(S, _FP_ZEROFRAC_##wc); \
+ _FP_FRAC_SET_##wc(R, _FP_ZEROFRAC_##wc); \
+ q = _FP_OVERFLOW_##fs; \
+ _FP_FRAC_SLL_##wc(X, 1); \
+ _FP_SQRT_MEAT_##wc(R, S, T, X, q); \
+ _FP_FRAC_SRL_##wc(R, 1); \
+ } \
+ } while (0)
+
+/*
+ * Convert from FP to integer
+ */
+
+/* "When a NaN, infinity, large positive argument >= 2147483648.0, or
+ * large negative argument <= -2147483649.0 is converted to an integer,
+ * the invalid_current bit...should be set and fp_exception_IEEE_754 should
+ * be raised. If the floating point invalid trap is disabled, no trap occurs
+ * and a numerical result is generated: if the sign bit of the operand
+ * is 0, the result is 2147483647; if the sign bit of the operand is 1,
+ * the result is -2147483648."
+ * Similarly for conversion to extended ints, except that the boundaries
+ * are >= 2^63, <= -(2^63 + 1), and the results are 2^63 + 1 for s=0 and
+ * -2^63 for s=1.
+ * -- SPARC Architecture Manual V9, Appendix B, which specifies how
+ * SPARCs resolve implementation dependencies in the IEEE-754 spec.
+ * I don't believe that the code below follows this. I'm not even sure
+ * it's right!
+ * It doesn't cope with needing to convert to an n bit integer when there
+ * is no n bit integer type. Fortunately gcc provides long long so this
+ * isn't a problem for sparc32.
+ * I have, however, fixed its NaN handling to conform as above.
+ * -- PMM 02/1998
+ * NB: rsigned is not 'is r declared signed?' but 'should the value stored
+ * in r be signed or unsigned?'. r is always(?) declared unsigned.
+ * Comments below are mine, BTW -- PMM
+ */
+#define _FP_TO_INT(fs, wc, r, X, rsize, rsigned) \
+ do { \
+ switch (X##_c) \
+ { \
+ case FP_CLS_NORMAL: \
+ if (X##_e < 0) \
+ { \
+ /* case FP_CLS_NAN: see above! */ \
+ case FP_CLS_ZERO: \
+ r = 0; \
+ } \
+ else if (X##_e >= rsize - (rsigned != 0)) \
+ { /* overflow */ \
+ case FP_CLS_NAN: \
+ case FP_CLS_INF: \
+ if (rsigned) \
+ { \
+ r = 1; \
+ r <<= rsize - 1; \
+ r -= 1 - X##_s; \
+ } \
+ else \
+ { \
+ r = 0; \
+ if (!X##_s) \
+ r = ~r; \
+ } \
+ } \
+ else \
+ { \
+ if (_FP_W_TYPE_SIZE*wc < rsize) \
+ { \
+ _FP_FRAC_ASSEMBLE_##wc(r, X, rsize); \
+ r <<= X##_e - _FP_WFRACBITS_##fs; \
+ } \
+ else \
+ { \
+ if (X##_e >= _FP_WFRACBITS_##fs) \
+ _FP_FRAC_SLL_##wc(X, (X##_e - _FP_WFRACBITS_##fs + 1));\
+ else \
+ _FP_FRAC_SRL_##wc(X, (_FP_WFRACBITS_##fs - X##_e - 1));\
+ _FP_FRAC_ASSEMBLE_##wc(r, X, rsize); \
+ } \
+ if (rsigned && X##_s) \
+ r = -r; \
+ } \
+ break; \
+ } \
+ } while (0)
+
+#define _FP_FROM_INT(fs, wc, X, r, rsize, rtype) \
+ do { \
+ if (r) \
+ { \
+ X##_c = FP_CLS_NORMAL; \
+ \
+ if ((X##_s = (r < 0))) \
+ r = -r; \
+ /* Note that `r' is now considered unsigned, so we don't have \
+ to worry about the single signed overflow case. */ \
+ \
+ if (rsize <= _FP_W_TYPE_SIZE) \
+ __FP_CLZ(X##_e, r); \
+ else \
+ __FP_CLZ_2(X##_e, (_FP_W_TYPE)(r >> _FP_W_TYPE_SIZE), \
+ (_FP_W_TYPE)r); \
+ if (rsize < _FP_W_TYPE_SIZE) \
+ X##_e -= (_FP_W_TYPE_SIZE - rsize); \
+ X##_e = rsize - X##_e - 1; \
+ \
+ if (_FP_FRACBITS_##fs < rsize && _FP_WFRACBITS_##fs < X##_e) \
+ __FP_FRAC_SRS_1(r, (X##_e - _FP_WFRACBITS_##fs), rsize); \
+ r &= ~((_FP_W_TYPE)1 << X##_e); \
+ _FP_FRAC_DISASSEMBLE_##wc(X, ((unsigned rtype)r), rsize); \
+ _FP_FRAC_SLL_##wc(X, (_FP_WFRACBITS_##fs - X##_e - 1)); \
+ } \
+ else \
+ { \
+ X##_c = FP_CLS_ZERO, X##_s = 0; \
+ } \
+ } while (0)
+
+
+#define FP_CONV(dfs,sfs,dwc,swc,D,S) \
+ do { \
+ _FP_FRAC_CONV_##dwc##_##swc(dfs, sfs, D, S); \
+ D##_e = S##_e; \
+ D##_c = S##_c; \
+ D##_s = S##_s; \
+ } while (0)
+
+/*
+ * Helper primitives.
+ */
+
+/* Count leading zeros in a word. */
+
+#ifndef __FP_CLZ
+#if _FP_W_TYPE_SIZE < 64
+/* this is just to shut the compiler up about shifts > word length -- PMM 02/1998 */
+#define __FP_CLZ(r, x) \
+ do { \
+ _FP_W_TYPE _t = (x); \
+ r = _FP_W_TYPE_SIZE - 1; \
+ if (_t > 0xffff) r -= 16; \
+ if (_t > 0xffff) _t >>= 16; \
+ if (_t > 0xff) r -= 8; \
+ if (_t > 0xff) _t >>= 8; \
+ if (_t & 0xf0) r -= 4; \
+ if (_t & 0xf0) _t >>= 4; \
+ if (_t & 0xc) r -= 2; \
+ if (_t & 0xc) _t >>= 2; \
+ if (_t & 0x2) r -= 1; \
+ } while (0)
+#else /* not _FP_W_TYPE_SIZE < 64 */
+#define __FP_CLZ(r, x) \
+ do { \
+ _FP_W_TYPE _t = (x); \
+ r = _FP_W_TYPE_SIZE - 1; \
+ if (_t > 0xffffffff) r -= 32; \
+ if (_t > 0xffffffff) _t >>= 32; \
+ if (_t > 0xffff) r -= 16; \
+ if (_t > 0xffff) _t >>= 16; \
+ if (_t > 0xff) r -= 8; \
+ if (_t > 0xff) _t >>= 8; \
+ if (_t & 0xf0) r -= 4; \
+ if (_t & 0xf0) _t >>= 4; \
+ if (_t & 0xc) r -= 2; \
+ if (_t & 0xc) _t >>= 2; \
+ if (_t & 0x2) r -= 1; \
+ } while (0)
+#endif /* not _FP_W_TYPE_SIZE < 64 */
+#endif /* ndef __FP_CLZ */
+
+#define _FP_DIV_HELP_imm(q, r, n, d) \
+ do { \
+ q = n / d, r = n % d; \
+ } while (0)
+
diff --git a/arch/ppc/math-emu/sfp-machine.h b/arch/ppc/math-emu/sfp-machine.h
new file mode 100644
index 0000000..686e06d
--- /dev/null
+++ b/arch/ppc/math-emu/sfp-machine.h
@@ -0,0 +1,377 @@
+/* Machine-dependent software floating-point definitions. PPC version.
+ Copyright (C) 1997 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ The GNU C Library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with the GNU C Library; see the file COPYING.LIB. If
+ not, write to the Free Software Foundation, Inc.,
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ Actually, this is a PPC (32bit) version, written based on the
+ i386, sparc, and sparc64 versions, by me,
+ Peter Maydell (pmaydell@chiark.greenend.org.uk).
+ Comments are by and large also mine, although they may be inaccurate.
+
+ In picking out asm fragments I've gone with the lowest common
+ denominator, which also happens to be the hardware I have :->
+ That is, a SPARC without hardware multiply and divide.
+ */
+
+/* basic word size definitions */
+#define _FP_W_TYPE_SIZE 32
+#define _FP_W_TYPE unsigned long
+#define _FP_WS_TYPE signed long
+#define _FP_I_TYPE long
+
+#define __ll_B ((UWtype) 1 << (W_TYPE_SIZE / 2))
+#define __ll_lowpart(t) ((UWtype) (t) & (__ll_B - 1))
+#define __ll_highpart(t) ((UWtype) (t) >> (W_TYPE_SIZE / 2))
+
+/* You can optionally code some things like addition in asm. For
+ * example, i386 defines __FP_FRAC_ADD_2 as asm. If you don't
+ * then you get a fragment of C code [if you change an #ifdef 0
+ * in op-2.h] or a call to add_ssaaaa (see below).
+ * Good places to look for asm fragments to use are gcc and glibc.
+ * gcc's longlong.h is useful.
+ */
+
+/* We need to know how to multiply and divide. If the host word size
+ * is >= 2*fracbits you can use FP_MUL_MEAT_n_imm(t,R,X,Y) which
+ * codes the multiply with whatever gcc does to 'a * b'.
+ * _FP_MUL_MEAT_n_wide(t,R,X,Y,f) is used when you have an asm
+ * function that can multiply two 1W values and get a 2W result.
+ * Otherwise you're stuck with _FP_MUL_MEAT_n_hard(t,R,X,Y) which
+ * does bitshifting to avoid overflow.
+ * For division there is FP_DIV_MEAT_n_imm(t,R,X,Y,f) for word size
+ * >= 2*fracbits, where f is either _FP_DIV_HELP_imm or
+ * _FP_DIV_HELP_ldiv (see op-1.h).
+ * _FP_DIV_MEAT_udiv() is if you have asm to do 2W/1W => (1W, 1W).
+ * [GCC and glibc have longlong.h which has the asm macro udiv_qrnnd
+ * to do this.]
+ * In general, 'n' is the number of words required to hold the type,
+ * and 't' is either S, D or Q for single/double/quad.
+ * -- PMM
+ */
+/* Example: SPARC64:
+ * #define _FP_MUL_MEAT_S(R,X,Y) _FP_MUL_MEAT_1_imm(S,R,X,Y)
+ * #define _FP_MUL_MEAT_D(R,X,Y) _FP_MUL_MEAT_1_wide(D,R,X,Y,umul_ppmm)
+ * #define _FP_MUL_MEAT_Q(R,X,Y) _FP_MUL_MEAT_2_wide(Q,R,X,Y,umul_ppmm)
+ *
+ * #define _FP_DIV_MEAT_S(R,X,Y) _FP_DIV_MEAT_1_imm(S,R,X,Y,_FP_DIV_HELP_imm)
+ * #define _FP_DIV_MEAT_D(R,X,Y) _FP_DIV_MEAT_1_udiv(D,R,X,Y)
+ * #define _FP_DIV_MEAT_Q(R,X,Y) _FP_DIV_MEAT_2_udiv_64(Q,R,X,Y)
+ *
+ * Example: i386:
+ * #define _FP_MUL_MEAT_S(R,X,Y) _FP_MUL_MEAT_1_wide(S,R,X,Y,_i386_mul_32_64)
+ * #define _FP_MUL_MEAT_D(R,X,Y) _FP_MUL_MEAT_2_wide(D,R,X,Y,_i386_mul_32_64)
+ *
+ * #define _FP_DIV_MEAT_S(R,X,Y) _FP_DIV_MEAT_1_udiv(S,R,X,Y,_i386_div_64_32)
+ * #define _FP_DIV_MEAT_D(R,X,Y) _FP_DIV_MEAT_2_udiv_64(D,R,X,Y)
+ */
+
+#define _FP_MUL_MEAT_S(R,X,Y) _FP_MUL_MEAT_1_wide(S,R,X,Y,umul_ppmm)
+#define _FP_MUL_MEAT_D(R,X,Y) _FP_MUL_MEAT_2_wide(D,R,X,Y,umul_ppmm)
+
+#define _FP_DIV_MEAT_S(R,X,Y) _FP_DIV_MEAT_1_udiv(S,R,X,Y)
+#define _FP_DIV_MEAT_D(R,X,Y) _FP_DIV_MEAT_2_udiv_64(D,R,X,Y)
+
+/* These macros define what NaN looks like. They're supposed to expand to
+ * a comma-separated set of 32bit unsigned ints that encode NaN.
+ */
+#define _FP_NANFRAC_S _FP_QNANBIT_S
+#define _FP_NANFRAC_D _FP_QNANBIT_D, 0
+#define _FP_NANFRAC_Q _FP_QNANBIT_Q, 0, 0, 0
+
+#define _FP_KEEPNANFRACP 1
+
+/* This macro appears to be called when both X and Y are NaNs, and
+ * has to choose one and copy it to R. i386 goes for the larger of the
+ * two, sparc64 just picks Y. I don't understand this at all so I'll
+ * go with sparc64 because it's shorter :-> -- PMM
+ */
+#define _FP_CHOOSENAN(fs, wc, R, X, Y) \
+ do { \
+ R##_s = Y##_s; \
+ _FP_FRAC_COPY_##wc(R,Y); \
+ R##_c = FP_CLS_NAN; \
+ } while (0)
+
+
+extern void fp_unpack_d(long *, unsigned long *, unsigned long *,
+ long *, long *, void *);
+extern int fp_pack_d(void *, long, unsigned long, unsigned long, long, long);
+extern int fp_pack_ds(void *, long, unsigned long, unsigned long, long, long);
+
+#define __FP_UNPACK_RAW_1(fs, X, val) \
+ do { \
+ union _FP_UNION_##fs *_flo = \
+ (union _FP_UNION_##fs *)val; \
+ \
+ X##_f = _flo->bits.frac; \
+ X##_e = _flo->bits.exp; \
+ X##_s = _flo->bits.sign; \
+ } while (0)
+
+#define __FP_UNPACK_RAW_2(fs, X, val) \
+ do { \
+ union _FP_UNION_##fs *_flo = \
+ (union _FP_UNION_##fs *)val; \
+ \
+ X##_f0 = _flo->bits.frac0; \
+ X##_f1 = _flo->bits.frac1; \
+ X##_e = _flo->bits.exp; \
+ X##_s = _flo->bits.sign; \
+ } while (0)
+
+#define __FP_UNPACK_S(X,val) \
+ do { \
+ __FP_UNPACK_RAW_1(S,X,val); \
+ _FP_UNPACK_CANONICAL(S,1,X); \
+ } while (0)
+
+#define __FP_UNPACK_D(X,val) \
+ fp_unpack_d(&X##_s, &X##_f1, &X##_f0, &X##_e, &X##_c, val)
+
+#define __FP_PACK_RAW_1(fs, val, X) \
+ do { \
+ union _FP_UNION_##fs *_flo = \
+ (union _FP_UNION_##fs *)val; \
+ \
+ _flo->bits.frac = X##_f; \
+ _flo->bits.exp = X##_e; \
+ _flo->bits.sign = X##_s; \
+ } while (0)
+
+#define __FP_PACK_RAW_2(fs, val, X) \
+ do { \
+ union _FP_UNION_##fs *_flo = \
+ (union _FP_UNION_##fs *)val; \
+ \
+ _flo->bits.frac0 = X##_f0; \
+ _flo->bits.frac1 = X##_f1; \
+ _flo->bits.exp = X##_e; \
+ _flo->bits.sign = X##_s; \
+ } while (0)
+
+#include <linux/kernel.h>
+#include <linux/sched.h>
+
+#define __FPU_FPSCR (current->thread.fpscr)
+
+/* We only actually write to the destination register
+ * if exceptions signalled (if any) will not trap.
+ */
+#define __FPU_ENABLED_EXC \
+({ \
+ (__FPU_FPSCR >> 3) & 0x1f; \
+})
+
+#define __FPU_TRAP_P(bits) \
+ ((__FPU_ENABLED_EXC & (bits)) != 0)
+
+#define __FP_PACK_S(val,X) \
+({ int __exc = _FP_PACK_CANONICAL(S,1,X); \
+ if(!__exc || !__FPU_TRAP_P(__exc)) \
+ __FP_PACK_RAW_1(S,val,X); \
+ __exc; \
+})
+
+#define __FP_PACK_D(val,X) \
+ fp_pack_d(val, X##_s, X##_f1, X##_f0, X##_e, X##_c)
+
+#define __FP_PACK_DS(val,X) \
+ fp_pack_ds(val, X##_s, X##_f1, X##_f0, X##_e, X##_c)
+
+/* Obtain the current rounding mode. */
+#define FP_ROUNDMODE \
+({ \
+ __FPU_FPSCR & 0x3; \
+})
+
+/* the asm fragments go here: all these are taken from glibc-2.0.5's
+ * stdlib/longlong.h
+ */
+
+#include <linux/types.h>
+#include <asm/byteorder.h>
+
+/* add_ssaaaa is used in op-2.h and should be equivalent to
+ * #define add_ssaaaa(sh,sl,ah,al,bh,bl) (sh = ah+bh+ (( sl = al+bl) < al))
+ * add_ssaaaa(high_sum, low_sum, high_addend_1, low_addend_1,
+ * high_addend_2, low_addend_2) adds two UWtype integers, composed by
+ * HIGH_ADDEND_1 and LOW_ADDEND_1, and HIGH_ADDEND_2 and LOW_ADDEND_2
+ * respectively. The result is placed in HIGH_SUM and LOW_SUM. Overflow
+ * (i.e. carry out) is not stored anywhere, and is lost.
+ */
+#define add_ssaaaa(sh, sl, ah, al, bh, bl) \
+ do { \
+ if (__builtin_constant_p (bh) && (bh) == 0) \
+ __asm__ ("{a%I4|add%I4c} %1,%3,%4\n\t{aze|addze} %0,%2" \
+ : "=r" ((USItype)(sh)), \
+ "=&r" ((USItype)(sl)) \
+ : "%r" ((USItype)(ah)), \
+ "%r" ((USItype)(al)), \
+ "rI" ((USItype)(bl))); \
+ else if (__builtin_constant_p (bh) && (bh) ==~(USItype) 0) \
+ __asm__ ("{a%I4|add%I4c} %1,%3,%4\n\t{ame|addme} %0,%2" \
+ : "=r" ((USItype)(sh)), \
+ "=&r" ((USItype)(sl)) \
+ : "%r" ((USItype)(ah)), \
+ "%r" ((USItype)(al)), \
+ "rI" ((USItype)(bl))); \
+ else \
+ __asm__ ("{a%I5|add%I5c} %1,%4,%5\n\t{ae|adde} %0,%2,%3" \
+ : "=r" ((USItype)(sh)), \
+ "=&r" ((USItype)(sl)) \
+ : "%r" ((USItype)(ah)), \
+ "r" ((USItype)(bh)), \
+ "%r" ((USItype)(al)), \
+ "rI" ((USItype)(bl))); \
+ } while (0)
+
+/* sub_ddmmss is used in op-2.h and udivmodti4.c and should be equivalent to
+ * #define sub_ddmmss(sh, sl, ah, al, bh, bl) (sh = ah-bh - ((sl = al-bl) > al))
+ * sub_ddmmss(high_difference, low_difference, high_minuend, low_minuend,
+ * high_subtrahend, low_subtrahend) subtracts two two-word UWtype integers,
+ * composed by HIGH_MINUEND_1 and LOW_MINUEND_1, and HIGH_SUBTRAHEND_2 and
+ * LOW_SUBTRAHEND_2 respectively. The result is placed in HIGH_DIFFERENCE
+ * and LOW_DIFFERENCE. Overflow (i.e. carry out) is not stored anywhere,
+ * and is lost.
+ */
+#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
+ do { \
+ if (__builtin_constant_p (ah) && (ah) == 0) \
+ __asm__ ("{sf%I3|subf%I3c} %1,%4,%3\n\t{sfze|subfze} %0,%2" \
+ : "=r" ((USItype)(sh)), \
+ "=&r" ((USItype)(sl)) \
+ : "r" ((USItype)(bh)), \
+ "rI" ((USItype)(al)), \
+ "r" ((USItype)(bl))); \
+ else if (__builtin_constant_p (ah) && (ah) ==~(USItype) 0) \
+ __asm__ ("{sf%I3|subf%I3c} %1,%4,%3\n\t{sfme|subfme} %0,%2" \
+ : "=r" ((USItype)(sh)), \
+ "=&r" ((USItype)(sl)) \
+ : "r" ((USItype)(bh)), \
+ "rI" ((USItype)(al)), \
+ "r" ((USItype)(bl))); \
+ else if (__builtin_constant_p (bh) && (bh) == 0) \
+ __asm__ ("{sf%I3|subf%I3c} %1,%4,%3\n\t{ame|addme} %0,%2" \
+ : "=r" ((USItype)(sh)), \
+ "=&r" ((USItype)(sl)) \
+ : "r" ((USItype)(ah)), \
+ "rI" ((USItype)(al)), \
+ "r" ((USItype)(bl))); \
+ else if (__builtin_constant_p (bh) && (bh) ==~(USItype) 0) \
+ __asm__ ("{sf%I3|subf%I3c} %1,%4,%3\n\t{aze|addze} %0,%2" \
+ : "=r" ((USItype)(sh)), \
+ "=&r" ((USItype)(sl)) \
+ : "r" ((USItype)(ah)), \
+ "rI" ((USItype)(al)), \
+ "r" ((USItype)(bl))); \
+ else \
+ __asm__ ("{sf%I4|subf%I4c} %1,%5,%4\n\t{sfe|subfe} %0,%3,%2" \
+ : "=r" ((USItype)(sh)), \
+ "=&r" ((USItype)(sl)) \
+ : "r" ((USItype)(ah)), \
+ "r" ((USItype)(bh)), \
+ "rI" ((USItype)(al)), \
+ "r" ((USItype)(bl))); \
+ } while (0)
+
+/* asm fragments for mul and div */
+
+/* umul_ppmm(high_prod, low_prod, multipler, multiplicand) multiplies two
+ * UWtype integers MULTIPLER and MULTIPLICAND, and generates a two UWtype
+ * word product in HIGH_PROD and LOW_PROD.
+ */
+#define umul_ppmm(ph, pl, m0, m1) \
+ do { \
+ USItype __m0 = (m0), __m1 = (m1); \
+ __asm__ ("mulhwu %0,%1,%2" \
+ : "=r" ((USItype)(ph)) \
+ : "%r" (__m0), \
+ "r" (__m1)); \
+ (pl) = __m0 * __m1; \
+ } while (0)
+
+/* udiv_qrnnd(quotient, remainder, high_numerator, low_numerator,
+ * denominator) divides a UDWtype, composed by the UWtype integers
+ * HIGH_NUMERATOR and LOW_NUMERATOR, by DENOMINATOR and places the quotient
+ * in QUOTIENT and the remainder in REMAINDER. HIGH_NUMERATOR must be less
+ * than DENOMINATOR for correct operation. If, in addition, the most
+ * significant bit of DENOMINATOR must be 1, then the pre-processor symbol
+ * UDIV_NEEDS_NORMALIZATION is defined to 1.
+ */
+#define udiv_qrnnd(q, r, n1, n0, d) \
+ do { \
+ UWtype __d1, __d0, __q1, __q0, __r1, __r0, __m; \
+ __d1 = __ll_highpart (d); \
+ __d0 = __ll_lowpart (d); \
+ \
+ __r1 = (n1) % __d1; \
+ __q1 = (n1) / __d1; \
+ __m = (UWtype) __q1 * __d0; \
+ __r1 = __r1 * __ll_B | __ll_highpart (n0); \
+ if (__r1 < __m) \
+ { \
+ __q1--, __r1 += (d); \
+ if (__r1 >= (d)) /* we didn't get carry when adding to __r1 */ \
+ if (__r1 < __m) \
+ __q1--, __r1 += (d); \
+ } \
+ __r1 -= __m; \
+ \
+ __r0 = __r1 % __d1; \
+ __q0 = __r1 / __d1; \
+ __m = (UWtype) __q0 * __d0; \
+ __r0 = __r0 * __ll_B | __ll_lowpart (n0); \
+ if (__r0 < __m) \
+ { \
+ __q0--, __r0 += (d); \
+ if (__r0 >= (d)) \
+ if (__r0 < __m) \
+ __q0--, __r0 += (d); \
+ } \
+ __r0 -= __m; \
+ \
+ (q) = (UWtype) __q1 * __ll_B | __q0; \
+ (r) = __r0; \
+ } while (0)
+
+#define UDIV_NEEDS_NORMALIZATION 1
+
+#define abort() \
+ return 0
+
+#ifdef __BIG_ENDIAN
+#define __BYTE_ORDER __BIG_ENDIAN
+#else
+#define __BYTE_ORDER __LITTLE_ENDIAN
+#endif
+
+/* Exception flags. */
+#define EFLAG_INVALID (1 << (31 - 2))
+#define EFLAG_OVERFLOW (1 << (31 - 3))
+#define EFLAG_UNDERFLOW (1 << (31 - 4))
+#define EFLAG_DIVZERO (1 << (31 - 5))
+#define EFLAG_INEXACT (1 << (31 - 6))
+
+#define EFLAG_VXSNAN (1 << (31 - 7))
+#define EFLAG_VXISI (1 << (31 - 8))
+#define EFLAG_VXIDI (1 << (31 - 9))
+#define EFLAG_VXZDZ (1 << (31 - 10))
+#define EFLAG_VXIMZ (1 << (31 - 11))
+#define EFLAG_VXVC (1 << (31 - 12))
+#define EFLAG_VXSOFT (1 << (31 - 21))
+#define EFLAG_VXSQRT (1 << (31 - 22))
+#define EFLAG_VXCVI (1 << (31 - 23))
diff --git a/arch/ppc/math-emu/single.h b/arch/ppc/math-emu/single.h
new file mode 100644
index 0000000..f19d994
--- /dev/null
+++ b/arch/ppc/math-emu/single.h
@@ -0,0 +1,66 @@
+/*
+ * Definitions for IEEE Single Precision
+ */
+
+#if _FP_W_TYPE_SIZE < 32
+#error "Here's a nickel kid. Go buy yourself a real computer."
+#endif
+
+#define _FP_FRACBITS_S 24
+#define _FP_FRACXBITS_S (_FP_W_TYPE_SIZE - _FP_FRACBITS_S)
+#define _FP_WFRACBITS_S (_FP_WORKBITS + _FP_FRACBITS_S)
+#define _FP_WFRACXBITS_S (_FP_W_TYPE_SIZE - _FP_WFRACBITS_S)
+#define _FP_EXPBITS_S 8
+#define _FP_EXPBIAS_S 127
+#define _FP_EXPMAX_S 255
+#define _FP_QNANBIT_S ((_FP_W_TYPE)1 << (_FP_FRACBITS_S-2))
+#define _FP_IMPLBIT_S ((_FP_W_TYPE)1 << (_FP_FRACBITS_S-1))
+#define _FP_OVERFLOW_S ((_FP_W_TYPE)1 << (_FP_WFRACBITS_S))
+
+/* The implementation of _FP_MUL_MEAT_S and _FP_DIV_MEAT_S should be
+ chosen by the target machine. */
+
+union _FP_UNION_S
+{
+ float flt;
+ struct {
+#if __BYTE_ORDER == __BIG_ENDIAN
+ unsigned sign : 1;
+ unsigned exp : _FP_EXPBITS_S;
+ unsigned frac : _FP_FRACBITS_S - (_FP_IMPLBIT_S != 0);
+#else
+ unsigned frac : _FP_FRACBITS_S - (_FP_IMPLBIT_S != 0);
+ unsigned exp : _FP_EXPBITS_S;
+ unsigned sign : 1;
+#endif
+ } bits __attribute__((packed));
+};
+
+#define FP_DECL_S(X) _FP_DECL(1,X)
+#define FP_UNPACK_RAW_S(X,val) _FP_UNPACK_RAW_1(S,X,val)
+#define FP_PACK_RAW_S(val,X) _FP_PACK_RAW_1(S,val,X)
+
+#define FP_UNPACK_S(X,val) \
+ do { \
+ _FP_UNPACK_RAW_1(S,X,val); \
+ _FP_UNPACK_CANONICAL(S,1,X); \
+ } while (0)
+
+#define FP_PACK_S(val,X) \
+ do { \
+ _FP_PACK_CANONICAL(S,1,X); \
+ _FP_PACK_RAW_1(S,val,X); \
+ } while (0)
+
+#define FP_NEG_S(R,X) _FP_NEG(S,1,R,X)
+#define FP_ADD_S(R,X,Y) _FP_ADD(S,1,R,X,Y)
+#define FP_SUB_S(R,X,Y) _FP_SUB(S,1,R,X,Y)
+#define FP_MUL_S(R,X,Y) _FP_MUL(S,1,R,X,Y)
+#define FP_DIV_S(R,X,Y) _FP_DIV(S,1,R,X,Y)
+#define FP_SQRT_S(R,X) _FP_SQRT(S,1,R,X)
+
+#define FP_CMP_S(r,X,Y,un) _FP_CMP(S,1,r,X,Y,un)
+#define FP_CMP_EQ_S(r,X,Y) _FP_CMP_EQ(S,1,r,X,Y)
+
+#define FP_TO_INT_S(r,X,rsz,rsg) _FP_TO_INT(S,1,r,X,rsz,rsg)
+#define FP_FROM_INT_S(X,r,rs,rt) _FP_FROM_INT(S,1,X,r,rs,rt)
diff --git a/arch/ppc/math-emu/soft-fp.h b/arch/ppc/math-emu/soft-fp.h
new file mode 100644
index 0000000..cca3959
--- /dev/null
+++ b/arch/ppc/math-emu/soft-fp.h
@@ -0,0 +1,104 @@
+#ifndef SOFT_FP_H
+#define SOFT_FP_H
+
+#include "sfp-machine.h"
+
+#define _FP_WORKBITS 3
+#define _FP_WORK_LSB ((_FP_W_TYPE)1 << 3)
+#define _FP_WORK_ROUND ((_FP_W_TYPE)1 << 2)
+#define _FP_WORK_GUARD ((_FP_W_TYPE)1 << 1)
+#define _FP_WORK_STICKY ((_FP_W_TYPE)1 << 0)
+
+#ifndef FP_RND_NEAREST
+# define FP_RND_NEAREST 0
+# define FP_RND_ZERO 1
+# define FP_RND_PINF 2
+# define FP_RND_MINF 3
+#ifndef FP_ROUNDMODE
+# define FP_ROUNDMODE FP_RND_NEAREST
+#endif
+#endif
+
+#define _FP_ROUND_NEAREST(wc, X) \
+({ int __ret = 0; \
+ int __frac = _FP_FRAC_LOW_##wc(X) & 15; \
+ if (__frac & 7) { \
+ __ret = EFLAG_INEXACT; \
+ if ((__frac & 7) != _FP_WORK_ROUND) \
+ _FP_FRAC_ADDI_##wc(X, _FP_WORK_ROUND); \
+ else if (__frac & _FP_WORK_LSB) \
+ _FP_FRAC_ADDI_##wc(X, _FP_WORK_ROUND); \
+ } \
+ __ret; \
+})
+
+#define _FP_ROUND_ZERO(wc, X) \
+({ int __ret = 0; \
+ if (_FP_FRAC_LOW_##wc(X) & 7) \
+ __ret = EFLAG_INEXACT; \
+ __ret; \
+})
+
+#define _FP_ROUND_PINF(wc, X) \
+({ int __ret = EFLAG_INEXACT; \
+ if (!X##_s && (_FP_FRAC_LOW_##wc(X) & 7)) \
+ _FP_FRAC_ADDI_##wc(X, _FP_WORK_LSB); \
+ else __ret = 0; \
+ __ret; \
+})
+
+#define _FP_ROUND_MINF(wc, X) \
+({ int __ret = EFLAG_INEXACT; \
+ if (X##_s && (_FP_FRAC_LOW_##wc(X) & 7)) \
+ _FP_FRAC_ADDI_##wc(X, _FP_WORK_LSB); \
+ else __ret = 0; \
+ __ret; \
+})
+
+#define _FP_ROUND(wc, X) \
+({ int __ret = 0; \
+ switch (FP_ROUNDMODE) \
+ { \
+ case FP_RND_NEAREST: \
+ __ret |= _FP_ROUND_NEAREST(wc,X); \
+ break; \
+ case FP_RND_ZERO: \
+ __ret |= _FP_ROUND_ZERO(wc,X); \
+ break; \
+ case FP_RND_PINF: \
+ __ret |= _FP_ROUND_PINF(wc,X); \
+ break; \
+ case FP_RND_MINF: \
+ __ret |= _FP_ROUND_MINF(wc,X); \
+ break; \
+ }; \
+ __ret; \
+})
+
+#define FP_CLS_NORMAL 0
+#define FP_CLS_ZERO 1
+#define FP_CLS_INF 2
+#define FP_CLS_NAN 3
+
+#define _FP_CLS_COMBINE(x,y) (((x) << 2) | (y))
+
+#include "op-1.h"
+#include "op-2.h"
+#include "op-4.h"
+#include "op-common.h"
+
+/* Sigh. Silly things longlong.h needs. */
+#define UWtype _FP_W_TYPE
+#define W_TYPE_SIZE _FP_W_TYPE_SIZE
+
+typedef int SItype __attribute__((mode(SI)));
+typedef int DItype __attribute__((mode(DI)));
+typedef unsigned int USItype __attribute__((mode(SI)));
+typedef unsigned int UDItype __attribute__((mode(DI)));
+#if _FP_W_TYPE_SIZE == 32
+typedef unsigned int UHWtype __attribute__((mode(HI)));
+#elif _FP_W_TYPE_SIZE == 64
+typedef USItype UHWtype;
+#endif
+
+#endif
diff --git a/arch/ppc/math-emu/stfd.c b/arch/ppc/math-emu/stfd.c
new file mode 100644
index 0000000..3f8c255
--- /dev/null
+++ b/arch/ppc/math-emu/stfd.c
@@ -0,0 +1,20 @@
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <asm/uaccess.h>
+
+int
+stfd(void *frS, void *ea)
+{
+#if 0
+#ifdef DEBUG
+ printk("%s: S %p, ea %p: ", __FUNCTION__, frS, ea);
+ dump_double(frS);
+ printk("\n");
+#endif
+#endif
+
+ if (copy_to_user(ea, frS, sizeof(double)))
+ return -EFAULT;
+
+ return 0;
+}
diff --git a/arch/ppc/math-emu/stfiwx.c b/arch/ppc/math-emu/stfiwx.c
new file mode 100644
index 0000000..95caaee
--- /dev/null
+++ b/arch/ppc/math-emu/stfiwx.c
@@ -0,0 +1,16 @@
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <asm/uaccess.h>
+
+int
+stfiwx(u32 *frS, void *ea)
+{
+#ifdef DEBUG
+ printk("%s: %p %p\n", __FUNCTION__, frS, ea);
+#endif
+
+ if (copy_to_user(ea, &frS[1], sizeof(frS[1])))
+ return -EFAULT;
+
+ return 0;
+}
diff --git a/arch/ppc/math-emu/stfs.c b/arch/ppc/math-emu/stfs.c
new file mode 100644
index 0000000..e87ca23
--- /dev/null
+++ b/arch/ppc/math-emu/stfs.c
@@ -0,0 +1,41 @@
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <asm/uaccess.h>
+
+#include "soft-fp.h"
+#include "double.h"
+#include "single.h"
+
+int
+stfs(void *frS, void *ea)
+{
+ FP_DECL_D(A);
+ FP_DECL_S(R);
+ float f;
+ int err;
+
+#ifdef DEBUG
+ printk("%s: S %p, ea %p\n", __FUNCTION__, frS, ea);
+#endif
+
+ __FP_UNPACK_D(A, frS);
+
+#ifdef DEBUG
+ printk("A: %ld %lu %lu %ld (%ld)\n", A_s, A_f1, A_f0, A_e, A_c);
+#endif
+
+ FP_CONV(S, D, 1, 2, R, A);
+
+#ifdef DEBUG
+ printk("R: %ld %lu %ld (%ld)\n", R_s, R_f, R_e, R_c);
+#endif
+
+ err = _FP_PACK_CANONICAL(S, 1, R);
+ if (!err || !__FPU_TRAP_P(err)) {
+ __FP_PACK_RAW_1(S, &f, R);
+ if (copy_to_user(ea, &f, sizeof(float)))
+ return -EFAULT;
+ }
+
+ return err;
+}
diff --git a/arch/ppc/math-emu/types.c b/arch/ppc/math-emu/types.c
new file mode 100644
index 0000000..e1ed15d
--- /dev/null
+++ b/arch/ppc/math-emu/types.c
@@ -0,0 +1,51 @@
+#include "soft-fp.h"
+#include "double.h"
+#include "single.h"
+
+void
+fp_unpack_d(long *_s, unsigned long *_f1, unsigned long *_f0,
+ long *_e, long *_c, void *val)
+{
+ FP_DECL_D(X);
+
+ __FP_UNPACK_RAW_2(D, X, val);
+
+ _FP_UNPACK_CANONICAL(D, 2, X);
+
+ *_s = X_s;
+ *_f1 = X_f1;
+ *_f0 = X_f0;
+ *_e = X_e;
+ *_c = X_c;
+}
+
+int
+fp_pack_d(void *val, long X_s, unsigned long X_f1,
+ unsigned long X_f0, long X_e, long X_c)
+{
+ int exc;
+
+ exc = _FP_PACK_CANONICAL(D, 2, X);
+ if (!exc || !__FPU_TRAP_P(exc))
+ __FP_PACK_RAW_2(D, val, X);
+ return exc;
+}
+
+int
+fp_pack_ds(void *val, long X_s, unsigned long X_f1,
+ unsigned long X_f0, long X_e, long X_c)
+{
+ FP_DECL_S(__X);
+ int exc;
+
+ FP_CONV(S, D, 1, 2, __X, X);
+ exc = _FP_PACK_CANONICAL(S, 1, __X);
+ if (!exc || !__FPU_TRAP_P(exc)) {
+ _FP_UNPACK_CANONICAL(S, 1, __X);
+ FP_CONV(D, S, 2, 1, X, __X);
+ exc |= _FP_PACK_CANONICAL(D, 2, X);
+ if (!exc || !__FPU_TRAP_P(exc))
+ __FP_PACK_RAW_2(D, val, X);
+ }
+ return exc;
+}
diff --git a/arch/ppc/math-emu/udivmodti4.c b/arch/ppc/math-emu/udivmodti4.c
new file mode 100644
index 0000000..7e112dc
--- /dev/null
+++ b/arch/ppc/math-emu/udivmodti4.c
@@ -0,0 +1,191 @@
+/* This has so very few changes over libgcc2's __udivmoddi4 it isn't funny. */
+
+#include "soft-fp.h"
+
+#undef count_leading_zeros
+#define count_leading_zeros __FP_CLZ
+
+void
+_fp_udivmodti4(_FP_W_TYPE q[2], _FP_W_TYPE r[2],
+ _FP_W_TYPE n1, _FP_W_TYPE n0,
+ _FP_W_TYPE d1, _FP_W_TYPE d0)
+{
+ _FP_W_TYPE q0, q1, r0, r1;
+ _FP_I_TYPE b, bm;
+
+ if (d1 == 0)
+ {
+#if !UDIV_NEEDS_NORMALIZATION
+ if (d0 > n1)
+ {
+ /* 0q = nn / 0D */
+
+ udiv_qrnnd (q0, n0, n1, n0, d0);
+ q1 = 0;
+
+ /* Remainder in n0. */
+ }
+ else
+ {
+ /* qq = NN / 0d */
+
+ if (d0 == 0)
+ d0 = 1 / d0; /* Divide intentionally by zero. */
+
+ udiv_qrnnd (q1, n1, 0, n1, d0);
+ udiv_qrnnd (q0, n0, n1, n0, d0);
+
+ /* Remainder in n0. */
+ }
+
+ r0 = n0;
+ r1 = 0;
+
+#else /* UDIV_NEEDS_NORMALIZATION */
+
+ if (d0 > n1)
+ {
+ /* 0q = nn / 0D */
+
+ count_leading_zeros (bm, d0);
+
+ if (bm != 0)
+ {
+ /* Normalize, i.e. make the most significant bit of the
+ denominator set. */
+
+ d0 = d0 << bm;
+ n1 = (n1 << bm) | (n0 >> (_FP_W_TYPE_SIZE - bm));
+ n0 = n0 << bm;
+ }
+
+ udiv_qrnnd (q0, n0, n1, n0, d0);
+ q1 = 0;
+
+ /* Remainder in n0 >> bm. */
+ }
+ else
+ {
+ /* qq = NN / 0d */
+
+ if (d0 == 0)
+ d0 = 1 / d0; /* Divide intentionally by zero. */
+
+ count_leading_zeros (bm, d0);
+
+ if (bm == 0)
+ {
+ /* From (n1 >= d0) /\ (the most significant bit of d0 is set),
+ conclude (the most significant bit of n1 is set) /\ (the
+ leading quotient digit q1 = 1).
+
+ This special case is necessary, not an optimization.
+ (Shifts counts of SI_TYPE_SIZE are undefined.) */
+
+ n1 -= d0;
+ q1 = 1;
+ }
+ else
+ {
+ _FP_W_TYPE n2;
+
+ /* Normalize. */
+
+ b = _FP_W_TYPE_SIZE - bm;
+
+ d0 = d0 << bm;
+ n2 = n1 >> b;
+ n1 = (n1 << bm) | (n0 >> b);
+ n0 = n0 << bm;
+
+ udiv_qrnnd (q1, n1, n2, n1, d0);
+ }
+
+ /* n1 != d0... */
+
+ udiv_qrnnd (q0, n0, n1, n0, d0);
+
+ /* Remainder in n0 >> bm. */
+ }
+
+ r0 = n0 >> bm;
+ r1 = 0;
+#endif /* UDIV_NEEDS_NORMALIZATION */
+ }
+ else
+ {
+ if (d1 > n1)
+ {
+ /* 00 = nn / DD */
+
+ q0 = 0;
+ q1 = 0;
+
+ /* Remainder in n1n0. */
+ r0 = n0;
+ r1 = n1;
+ }
+ else
+ {
+ /* 0q = NN / dd */
+
+ count_leading_zeros (bm, d1);
+ if (bm == 0)
+ {
+ /* From (n1 >= d1) /\ (the most significant bit of d1 is set),
+ conclude (the most significant bit of n1 is set) /\ (the
+ quotient digit q0 = 0 or 1).
+
+ This special case is necessary, not an optimization. */
+
+ /* The condition on the next line takes advantage of that
+ n1 >= d1 (true due to program flow). */
+ if (n1 > d1 || n0 >= d0)
+ {
+ q0 = 1;
+ sub_ddmmss (n1, n0, n1, n0, d1, d0);
+ }
+ else
+ q0 = 0;
+
+ q1 = 0;
+
+ r0 = n0;
+ r1 = n1;
+ }
+ else
+ {
+ _FP_W_TYPE m1, m0, n2;
+
+ /* Normalize. */
+
+ b = _FP_W_TYPE_SIZE - bm;
+
+ d1 = (d1 << bm) | (d0 >> b);
+ d0 = d0 << bm;
+ n2 = n1 >> b;
+ n1 = (n1 << bm) | (n0 >> b);
+ n0 = n0 << bm;
+
+ udiv_qrnnd (q0, n1, n2, n1, d1);
+ umul_ppmm (m1, m0, q0, d0);
+
+ if (m1 > n1 || (m1 == n1 && m0 > n0))
+ {
+ q0--;
+ sub_ddmmss (m1, m0, m1, m0, d1, d0);
+ }
+
+ q1 = 0;
+
+ /* Remainder in (n1n0 - m1m0) >> bm. */
+ sub_ddmmss (n1, n0, n1, n0, m1, m0);
+ r0 = (n1 << b) | (n0 >> bm);
+ r1 = n1 >> bm;
+ }
+ }
+ }
+
+ q[0] = q0; q[1] = q1;
+ r[0] = r0, r[1] = r1;
+}
diff --git a/arch/ppc/mm/44x_mmu.c b/arch/ppc/mm/44x_mmu.c
new file mode 100644
index 0000000..72f7c0d
--- /dev/null
+++ b/arch/ppc/mm/44x_mmu.c
@@ -0,0 +1,121 @@
+/*
+ * Modifications by Matt Porter (mporter@mvista.com) to support
+ * PPC44x Book E processors.
+ *
+ * This file contains the routines for initializing the MMU
+ * on the 4xx series of chips.
+ * -- paulus
+ *
+ * Derived from arch/ppc/mm/init.c:
+ * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
+ *
+ * Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au)
+ * and Cort Dougan (PReP) (cort@cs.nmt.edu)
+ * Copyright (C) 1996 Paul Mackerras
+ * Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk).
+ *
+ * Derived from "arch/i386/mm/init.c"
+ * Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds
+ *
+ * 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.
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/types.h>
+#include <linux/ptrace.h>
+#include <linux/mman.h>
+#include <linux/mm.h>
+#include <linux/swap.h>
+#include <linux/stddef.h>
+#include <linux/vmalloc.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/bootmem.h>
+#include <linux/highmem.h>
+
+#include <asm/pgalloc.h>
+#include <asm/prom.h>
+#include <asm/io.h>
+#include <asm/mmu_context.h>
+#include <asm/pgtable.h>
+#include <asm/mmu.h>
+#include <asm/uaccess.h>
+#include <asm/smp.h>
+#include <asm/bootx.h>
+#include <asm/machdep.h>
+#include <asm/setup.h>
+
+#include "mmu_decl.h"
+
+extern char etext[], _stext[];
+
+/* Used by the 44x TLB replacement exception handler.
+ * Just needed it declared someplace.
+ */
+unsigned int tlb_44x_index = 0;
+unsigned int tlb_44x_hwater = 62;
+
+/*
+ * "Pins" a 256MB TLB entry in AS0 for kernel lowmem
+ */
+static void __init
+ppc44x_pin_tlb(int slot, unsigned int virt, unsigned int phys)
+{
+ unsigned long attrib = 0;
+
+ __asm__ __volatile__("\
+ clrrwi %2,%2,10\n\
+ ori %2,%2,%4\n\
+ clrrwi %1,%1,10\n\
+ li %0,0\n\
+ ori %0,%0,%5\n\
+ tlbwe %2,%3,%6\n\
+ tlbwe %1,%3,%7\n\
+ tlbwe %0,%3,%8"
+ :
+ : "r" (attrib), "r" (phys), "r" (virt), "r" (slot),
+ "i" (PPC44x_TLB_VALID | PPC44x_TLB_256M),
+ "i" (PPC44x_TLB_SW | PPC44x_TLB_SR | PPC44x_TLB_SX | PPC44x_TLB_G),
+ "i" (PPC44x_TLB_PAGEID),
+ "i" (PPC44x_TLB_XLAT),
+ "i" (PPC44x_TLB_ATTRIB));
+}
+
+/*
+ * MMU_init_hw does the chip-specific initialization of the MMU hardware.
+ */
+void __init MMU_init_hw(void)
+{
+ flush_instruction_cache();
+}
+
+unsigned long __init mmu_mapin_ram(void)
+{
+ unsigned int pinned_tlbs = 1;
+ int i;
+
+ /* Determine number of entries necessary to cover lowmem */
+ pinned_tlbs = (unsigned int)
+ (_ALIGN(total_lowmem, PPC44x_PIN_SIZE) >> PPC44x_PIN_SHIFT);
+
+ /* Write upper watermark to save location */
+ tlb_44x_hwater = PPC44x_LOW_SLOT - pinned_tlbs;
+
+ /* If necessary, set additional pinned TLBs */
+ if (pinned_tlbs > 1)
+ for (i = (PPC44x_LOW_SLOT-(pinned_tlbs-1)); i < PPC44x_LOW_SLOT; i++) {
+ unsigned int phys_addr = (PPC44x_LOW_SLOT-i) * PPC44x_PIN_SIZE;
+ ppc44x_pin_tlb(i, phys_addr+PAGE_OFFSET, phys_addr);
+ }
+
+ return total_lowmem;
+}
diff --git a/arch/ppc/mm/4xx_mmu.c b/arch/ppc/mm/4xx_mmu.c
new file mode 100644
index 0000000..a7f6161
--- /dev/null
+++ b/arch/ppc/mm/4xx_mmu.c
@@ -0,0 +1,142 @@
+/*
+ * This file contains the routines for initializing the MMU
+ * on the 4xx series of chips.
+ * -- paulus
+ *
+ * Derived from arch/ppc/mm/init.c:
+ * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
+ *
+ * Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au)
+ * and Cort Dougan (PReP) (cort@cs.nmt.edu)
+ * Copyright (C) 1996 Paul Mackerras
+ * Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk).
+ *
+ * Derived from "arch/i386/mm/init.c"
+ * Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds
+ *
+ * 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.
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/types.h>
+#include <linux/ptrace.h>
+#include <linux/mman.h>
+#include <linux/mm.h>
+#include <linux/swap.h>
+#include <linux/stddef.h>
+#include <linux/vmalloc.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/bootmem.h>
+#include <linux/highmem.h>
+
+#include <asm/pgalloc.h>
+#include <asm/prom.h>
+#include <asm/io.h>
+#include <asm/mmu_context.h>
+#include <asm/pgtable.h>
+#include <asm/mmu.h>
+#include <asm/uaccess.h>
+#include <asm/smp.h>
+#include <asm/bootx.h>
+#include <asm/machdep.h>
+#include <asm/setup.h>
+#include "mmu_decl.h"
+
+extern int __map_without_ltlbs;
+/*
+ * MMU_init_hw does the chip-specific initialization of the MMU hardware.
+ */
+void __init MMU_init_hw(void)
+{
+ /*
+ * The Zone Protection Register (ZPR) defines how protection will
+ * be applied to every page which is a member of a given zone. At
+ * present, we utilize only two of the 4xx's zones.
+ * The zone index bits (of ZSEL) in the PTE are used for software
+ * indicators, except the LSB. For user access, zone 1 is used,
+ * for kernel access, zone 0 is used. We set all but zone 1
+ * to zero, allowing only kernel access as indicated in the PTE.
+ * For zone 1, we set a 01 binary (a value of 10 will not work)
+ * to allow user access as indicated in the PTE. This also allows
+ * kernel access as indicated in the PTE.
+ */
+
+ mtspr(SPRN_ZPR, 0x10000000);
+
+ flush_instruction_cache();
+
+ /*
+ * Set up the real-mode cache parameters for the exception vector
+ * handlers (which are run in real-mode).
+ */
+
+ mtspr(SPRN_DCWR, 0x00000000); /* All caching is write-back */
+
+ /*
+ * Cache instruction and data space where the exception
+ * vectors and the kernel live in real-mode.
+ */
+
+ mtspr(SPRN_DCCR, 0xF0000000); /* 512 MB of data space at 0x0. */
+ mtspr(SPRN_ICCR, 0xF0000000); /* 512 MB of instr. space at 0x0. */
+}
+
+#define LARGE_PAGE_SIZE_16M (1<<24)
+#define LARGE_PAGE_SIZE_4M (1<<22)
+
+unsigned long __init mmu_mapin_ram(void)
+{
+ unsigned long v, s;
+ phys_addr_t p;
+
+ v = KERNELBASE;
+ p = PPC_MEMSTART;
+ s = 0;
+
+ if (__map_without_ltlbs) {
+ return s;
+ }
+
+ while (s <= (total_lowmem - LARGE_PAGE_SIZE_16M)) {
+ pmd_t *pmdp;
+ unsigned long val = p | _PMD_SIZE_16M | _PAGE_HWEXEC | _PAGE_HWWRITE;
+
+ spin_lock(&init_mm.page_table_lock);
+ pmdp = pmd_offset(pgd_offset_k(v), v);
+ pmd_val(*pmdp++) = val;
+ pmd_val(*pmdp++) = val;
+ pmd_val(*pmdp++) = val;
+ pmd_val(*pmdp++) = val;
+ spin_unlock(&init_mm.page_table_lock);
+
+ v += LARGE_PAGE_SIZE_16M;
+ p += LARGE_PAGE_SIZE_16M;
+ s += LARGE_PAGE_SIZE_16M;
+ }
+
+ while (s <= (total_lowmem - LARGE_PAGE_SIZE_4M)) {
+ pmd_t *pmdp;
+ unsigned long val = p | _PMD_SIZE_4M | _PAGE_HWEXEC | _PAGE_HWWRITE;
+
+ spin_lock(&init_mm.page_table_lock);
+ pmdp = pmd_offset(pgd_offset_k(v), v);
+ pmd_val(*pmdp) = val;
+ spin_unlock(&init_mm.page_table_lock);
+
+ v += LARGE_PAGE_SIZE_4M;
+ p += LARGE_PAGE_SIZE_4M;
+ s += LARGE_PAGE_SIZE_4M;
+ }
+
+ return s;
+}
diff --git a/arch/ppc/mm/Makefile b/arch/ppc/mm/Makefile
new file mode 100644
index 0000000..cd3eae1
--- /dev/null
+++ b/arch/ppc/mm/Makefile
@@ -0,0 +1,11 @@
+#
+# Makefile for the linux ppc-specific parts of the memory manager.
+#
+
+obj-y := fault.o init.o mem_pieces.o \
+ mmu_context.o pgtable.o
+
+obj-$(CONFIG_PPC_STD_MMU) += hashtable.o ppc_mmu.o tlb.o
+obj-$(CONFIG_40x) += 4xx_mmu.o
+obj-$(CONFIG_44x) += 44x_mmu.o
+obj-$(CONFIG_FSL_BOOKE) += fsl_booke_mmu.o
diff --git a/arch/ppc/mm/fault.c b/arch/ppc/mm/fault.c
new file mode 100644
index 0000000..57d9930
--- /dev/null
+++ b/arch/ppc/mm/fault.c
@@ -0,0 +1,440 @@
+/*
+ * arch/ppc/mm/fault.c
+ *
+ * PowerPC version
+ * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
+ *
+ * Derived from "arch/i386/mm/fault.c"
+ * Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds
+ *
+ * Modified by Cort Dougan and Paul Mackerras.
+ *
+ * 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.
+ */
+
+#include <linux/config.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/types.h>
+#include <linux/ptrace.h>
+#include <linux/mman.h>
+#include <linux/mm.h>
+#include <linux/interrupt.h>
+#include <linux/highmem.h>
+#include <linux/module.h>
+
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <asm/mmu.h>
+#include <asm/mmu_context.h>
+#include <asm/system.h>
+#include <asm/uaccess.h>
+#include <asm/tlbflush.h>
+
+#if defined(CONFIG_XMON) || defined(CONFIG_KGDB)
+extern void (*debugger)(struct pt_regs *);
+extern void (*debugger_fault_handler)(struct pt_regs *);
+extern int (*debugger_dabr_match)(struct pt_regs *);
+int debugger_kernel_faults = 1;
+#endif
+
+unsigned long htab_reloads; /* updated by hashtable.S:hash_page() */
+unsigned long htab_evicts; /* updated by hashtable.S:hash_page() */
+unsigned long htab_preloads; /* updated by hashtable.S:add_hash_page() */
+unsigned long pte_misses; /* updated by do_page_fault() */
+unsigned long pte_errors; /* updated by do_page_fault() */
+unsigned int probingmem;
+
+/*
+ * Check whether the instruction at regs->nip is a store using
+ * an update addressing form which will update r1.
+ */
+static int store_updates_sp(struct pt_regs *regs)
+{
+ unsigned int inst;
+
+ if (get_user(inst, (unsigned int __user *)regs->nip))
+ return 0;
+ /* check for 1 in the rA field */
+ if (((inst >> 16) & 0x1f) != 1)
+ return 0;
+ /* check major opcode */
+ switch (inst >> 26) {
+ case 37: /* stwu */
+ case 39: /* stbu */
+ case 45: /* sthu */
+ case 53: /* stfsu */
+ case 55: /* stfdu */
+ return 1;
+ case 31:
+ /* check minor opcode */
+ switch ((inst >> 1) & 0x3ff) {
+ case 183: /* stwux */
+ case 247: /* stbux */
+ case 439: /* sthux */
+ case 695: /* stfsux */
+ case 759: /* stfdux */
+ return 1;
+ }
+ }
+ return 0;
+}
+
+/*
+ * For 600- and 800-family processors, the error_code parameter is DSISR
+ * for a data fault, SRR1 for an instruction fault. For 400-family processors
+ * the error_code parameter is ESR for a data fault, 0 for an instruction
+ * fault.
+ */
+int do_page_fault(struct pt_regs *regs, unsigned long address,
+ unsigned long error_code)
+{
+ struct vm_area_struct * vma;
+ struct mm_struct *mm = current->mm;
+ siginfo_t info;
+ int code = SEGV_MAPERR;
+#if defined(CONFIG_4xx) || defined (CONFIG_BOOKE)
+ int is_write = error_code & ESR_DST;
+#else
+ int is_write = 0;
+
+ /*
+ * Fortunately the bit assignments in SRR1 for an instruction
+ * fault and DSISR for a data fault are mostly the same for the
+ * bits we are interested in. But there are some bits which
+ * indicate errors in DSISR but can validly be set in SRR1.
+ */
+ if (TRAP(regs) == 0x400)
+ error_code &= 0x48200000;
+ else
+ is_write = error_code & 0x02000000;
+#endif /* CONFIG_4xx || CONFIG_BOOKE */
+
+#if defined(CONFIG_XMON) || defined(CONFIG_KGDB)
+ if (debugger_fault_handler && TRAP(regs) == 0x300) {
+ debugger_fault_handler(regs);
+ return 0;
+ }
+#if !(defined(CONFIG_4xx) || defined(CONFIG_BOOKE))
+ if (error_code & 0x00400000) {
+ /* DABR match */
+ if (debugger_dabr_match(regs))
+ return 0;
+ }
+#endif /* !(CONFIG_4xx || CONFIG_BOOKE)*/
+#endif /* CONFIG_XMON || CONFIG_KGDB */
+
+ if (in_atomic() || mm == NULL)
+ return SIGSEGV;
+
+ down_read(&mm->mmap_sem);
+ vma = find_vma(mm, address);
+ if (!vma)
+ goto bad_area;
+ if (vma->vm_start <= address)
+ goto good_area;
+ if (!(vma->vm_flags & VM_GROWSDOWN))
+ goto bad_area;
+ if (!is_write)
+ goto bad_area;
+
+ /*
+ * N.B. The rs6000/xcoff ABI allows programs to access up to
+ * a few hundred bytes below the stack pointer.
+ * The kernel signal delivery code writes up to about 1.5kB
+ * below the stack pointer (r1) before decrementing it.
+ * The exec code can write slightly over 640kB to the stack
+ * before setting the user r1. Thus we allow the stack to
+ * expand to 1MB without further checks.
+ */
+ if (address + 0x100000 < vma->vm_end) {
+ /* get user regs even if this fault is in kernel mode */
+ struct pt_regs *uregs = current->thread.regs;
+ if (uregs == NULL)
+ goto bad_area;
+
+ /*
+ * A user-mode access to an address a long way below
+ * the stack pointer is only valid if the instruction
+ * is one which would update the stack pointer to the
+ * address accessed if the instruction completed,
+ * i.e. either stwu rs,n(r1) or stwux rs,r1,rb
+ * (or the byte, halfword, float or double forms).
+ *
+ * If we don't check this then any write to the area
+ * between the last mapped region and the stack will
+ * expand the stack rather than segfaulting.
+ */
+ if (address + 2048 < uregs->gpr[1]
+ && (!user_mode(regs) || !store_updates_sp(regs)))
+ goto bad_area;
+ }
+ if (expand_stack(vma, address))
+ goto bad_area;
+
+good_area:
+ code = SEGV_ACCERR;
+#if defined(CONFIG_6xx)
+ if (error_code & 0x95700000)
+ /* an error such as lwarx to I/O controller space,
+ address matching DABR, eciwx, etc. */
+ goto bad_area;
+#endif /* CONFIG_6xx */
+#if defined(CONFIG_8xx)
+ /* The MPC8xx seems to always set 0x80000000, which is
+ * "undefined". Of those that can be set, this is the only
+ * one which seems bad.
+ */
+ if (error_code & 0x10000000)
+ /* Guarded storage error. */
+ goto bad_area;
+#endif /* CONFIG_8xx */
+
+ /* a write */
+ if (is_write) {
+ if (!(vma->vm_flags & VM_WRITE))
+ goto bad_area;
+#if defined(CONFIG_4xx) || defined(CONFIG_BOOKE)
+ /* an exec - 4xx/Book-E allows for per-page execute permission */
+ } else if (TRAP(regs) == 0x400) {
+ pte_t *ptep;
+
+#if 0
+ /* It would be nice to actually enforce the VM execute
+ permission on CPUs which can do so, but far too
+ much stuff in userspace doesn't get the permissions
+ right, so we let any page be executed for now. */
+ if (! (vma->vm_flags & VM_EXEC))
+ goto bad_area;
+#endif
+
+ /* Since 4xx/Book-E supports per-page execute permission,
+ * we lazily flush dcache to icache. */
+ ptep = NULL;
+ if (get_pteptr(mm, address, &ptep) && pte_present(*ptep)) {
+ struct page *page = pte_page(*ptep);
+
+ if (! test_bit(PG_arch_1, &page->flags)) {
+ flush_dcache_icache_page(page);
+ set_bit(PG_arch_1, &page->flags);
+ }
+ pte_update(ptep, 0, _PAGE_HWEXEC);
+ _tlbie(address);
+ pte_unmap(ptep);
+ up_read(&mm->mmap_sem);
+ return 0;
+ }
+ if (ptep != NULL)
+ pte_unmap(ptep);
+#endif
+ /* a read */
+ } else {
+ /* protection fault */
+ if (error_code & 0x08000000)
+ goto bad_area;
+ if (!(vma->vm_flags & (VM_READ | VM_EXEC)))
+ goto bad_area;
+ }
+
+ /*
+ * If for any reason at all we couldn't handle the fault,
+ * make sure we exit gracefully rather than endlessly redo
+ * the fault.
+ */
+ survive:
+ switch (handle_mm_fault(mm, vma, address, is_write)) {
+ case VM_FAULT_MINOR:
+ current->min_flt++;
+ break;
+ case VM_FAULT_MAJOR:
+ current->maj_flt++;
+ break;
+ case VM_FAULT_SIGBUS:
+ goto do_sigbus;
+ case VM_FAULT_OOM:
+ goto out_of_memory;
+ default:
+ BUG();
+ }
+
+ up_read(&mm->mmap_sem);
+ /*
+ * keep track of tlb+htab misses that are good addrs but
+ * just need pte's created via handle_mm_fault()
+ * -- Cort
+ */
+ pte_misses++;
+ return 0;
+
+bad_area:
+ up_read(&mm->mmap_sem);
+ pte_errors++;
+
+ /* User mode accesses cause a SIGSEGV */
+ if (user_mode(regs)) {
+ info.si_signo = SIGSEGV;
+ info.si_errno = 0;
+ info.si_code = code;
+ info.si_addr = (void __user *) address;
+ force_sig_info(SIGSEGV, &info, current);
+ return 0;
+ }
+
+ return SIGSEGV;
+
+/*
+ * We ran out of memory, or some other thing happened to us that made
+ * us unable to handle the page fault gracefully.
+ */
+out_of_memory:
+ up_read(&mm->mmap_sem);
+ if (current->pid == 1) {
+ yield();
+ down_read(&mm->mmap_sem);
+ goto survive;
+ }
+ printk("VM: killing process %s\n", current->comm);
+ if (user_mode(regs))
+ do_exit(SIGKILL);
+ return SIGKILL;
+
+do_sigbus:
+ up_read(&mm->mmap_sem);
+ info.si_signo = SIGBUS;
+ info.si_errno = 0;
+ info.si_code = BUS_ADRERR;
+ info.si_addr = (void __user *)address;
+ force_sig_info (SIGBUS, &info, current);
+ if (!user_mode(regs))
+ return SIGBUS;
+ return 0;
+}
+
+/*
+ * bad_page_fault is called when we have a bad access from the kernel.
+ * It is called from the DSI and ISI handlers in head.S and from some
+ * of the procedures in traps.c.
+ */
+void
+bad_page_fault(struct pt_regs *regs, unsigned long address, int sig)
+{
+ const struct exception_table_entry *entry;
+
+ /* Are we prepared to handle this fault? */
+ if ((entry = search_exception_tables(regs->nip)) != NULL) {
+ regs->nip = entry->fixup;
+ return;
+ }
+
+ /* kernel has accessed a bad area */
+#if defined(CONFIG_XMON) || defined(CONFIG_KGDB)
+ if (debugger_kernel_faults)
+ debugger(regs);
+#endif
+ die("kernel access of bad area", regs, sig);
+}
+
+#ifdef CONFIG_8xx
+
+/* The pgtable.h claims some functions generically exist, but I
+ * can't find them......
+ */
+pte_t *va_to_pte(unsigned long address)
+{
+ pgd_t *dir;
+ pmd_t *pmd;
+ pte_t *pte;
+
+ if (address < TASK_SIZE)
+ return NULL;
+
+ dir = pgd_offset(&init_mm, address);
+ if (dir) {
+ pmd = pmd_offset(dir, address & PAGE_MASK);
+ if (pmd && pmd_present(*pmd)) {
+ pte = pte_offset_kernel(pmd, address & PAGE_MASK);
+ if (pte && pte_present(*pte))
+ return(pte);
+ }
+ }
+ return NULL;
+}
+
+unsigned long va_to_phys(unsigned long address)
+{
+ pte_t *pte;
+
+ pte = va_to_pte(address);
+ if (pte)
+ return(((unsigned long)(pte_val(*pte)) & PAGE_MASK) | (address & ~(PAGE_MASK)));
+ return (0);
+}
+
+void
+print_8xx_pte(struct mm_struct *mm, unsigned long addr)
+{
+ pgd_t * pgd;
+ pmd_t * pmd;
+ pte_t * pte;
+
+ printk(" pte @ 0x%8lx: ", addr);
+ pgd = pgd_offset(mm, addr & PAGE_MASK);
+ if (pgd) {
+ pmd = pmd_offset(pgd, addr & PAGE_MASK);
+ if (pmd && pmd_present(*pmd)) {
+ pte = pte_offset_kernel(pmd, addr & PAGE_MASK);
+ if (pte) {
+ printk(" (0x%08lx)->(0x%08lx)->0x%08lx\n",
+ (long)pgd, (long)pte, (long)pte_val(*pte));
+#define pp ((long)pte_val(*pte))
+ printk(" RPN: %05lx PP: %lx SPS: %lx SH: %lx "
+ "CI: %lx v: %lx\n",
+ pp>>12, /* rpn */
+ (pp>>10)&3, /* pp */
+ (pp>>3)&1, /* small */
+ (pp>>2)&1, /* shared */
+ (pp>>1)&1, /* cache inhibit */
+ pp&1 /* valid */
+ );
+#undef pp
+ }
+ else {
+ printk("no pte\n");
+ }
+ }
+ else {
+ printk("no pmd\n");
+ }
+ }
+ else {
+ printk("no pgd\n");
+ }
+}
+
+int
+get_8xx_pte(struct mm_struct *mm, unsigned long addr)
+{
+ pgd_t * pgd;
+ pmd_t * pmd;
+ pte_t * pte;
+ int retval = 0;
+
+ pgd = pgd_offset(mm, addr & PAGE_MASK);
+ if (pgd) {
+ pmd = pmd_offset(pgd, addr & PAGE_MASK);
+ if (pmd && pmd_present(*pmd)) {
+ pte = pte_offset_kernel(pmd, addr & PAGE_MASK);
+ if (pte) {
+ retval = (int)pte_val(*pte);
+ }
+ }
+ }
+ return(retval);
+}
+#endif /* CONFIG_8xx */
diff --git a/arch/ppc/mm/fsl_booke_mmu.c b/arch/ppc/mm/fsl_booke_mmu.c
new file mode 100644
index 0000000..36233bd
--- /dev/null
+++ b/arch/ppc/mm/fsl_booke_mmu.c
@@ -0,0 +1,236 @@
+/*
+ * Modifications by Kumar Gala (kumar.gala@freescale.com) to support
+ * E500 Book E processors.
+ *
+ * Copyright 2004 Freescale Semiconductor, Inc
+ *
+ * This file contains the routines for initializing the MMU
+ * on the 4xx series of chips.
+ * -- paulus
+ *
+ * Derived from arch/ppc/mm/init.c:
+ * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
+ *
+ * Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au)
+ * and Cort Dougan (PReP) (cort@cs.nmt.edu)
+ * Copyright (C) 1996 Paul Mackerras
+ * Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk).
+ *
+ * Derived from "arch/i386/mm/init.c"
+ * Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds
+ *
+ * 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.
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/types.h>
+#include <linux/ptrace.h>
+#include <linux/mman.h>
+#include <linux/mm.h>
+#include <linux/swap.h>
+#include <linux/stddef.h>
+#include <linux/vmalloc.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/bootmem.h>
+#include <linux/highmem.h>
+
+#include <asm/pgalloc.h>
+#include <asm/prom.h>
+#include <asm/io.h>
+#include <asm/mmu_context.h>
+#include <asm/pgtable.h>
+#include <asm/mmu.h>
+#include <asm/uaccess.h>
+#include <asm/smp.h>
+#include <asm/bootx.h>
+#include <asm/machdep.h>
+#include <asm/setup.h>
+
+extern void loadcam_entry(unsigned int index);
+unsigned int tlbcam_index;
+unsigned int num_tlbcam_entries;
+static unsigned long __cam0, __cam1, __cam2;
+extern unsigned long total_lowmem;
+extern unsigned long __max_low_memory;
+#define MAX_LOW_MEM CONFIG_LOWMEM_SIZE
+
+struct tlbcam {
+ u32 MAS0;
+ u32 MAS1;
+ u32 MAS2;
+ u32 MAS3;
+ u32 MAS7;
+} TLBCAM[NUM_TLBCAMS];
+
+struct tlbcamrange {
+ unsigned long start;
+ unsigned long limit;
+ phys_addr_t phys;
+} tlbcam_addrs[NUM_TLBCAMS];
+
+extern unsigned int tlbcam_index;
+
+/*
+ * Return PA for this VA if it is mapped by a CAM, or 0
+ */
+unsigned long v_mapped_by_tlbcam(unsigned long va)
+{
+ int b;
+ for (b = 0; b < tlbcam_index; ++b)
+ if (va >= tlbcam_addrs[b].start && va < tlbcam_addrs[b].limit)
+ return tlbcam_addrs[b].phys + (va - tlbcam_addrs[b].start);
+ return 0;
+}
+
+/*
+ * Return VA for a given PA or 0 if not mapped
+ */
+unsigned long p_mapped_by_tlbcam(unsigned long pa)
+{
+ int b;
+ for (b = 0; b < tlbcam_index; ++b)
+ if (pa >= tlbcam_addrs[b].phys
+ && pa < (tlbcam_addrs[b].limit-tlbcam_addrs[b].start)
+ +tlbcam_addrs[b].phys)
+ return tlbcam_addrs[b].start+(pa-tlbcam_addrs[b].phys);
+ return 0;
+}
+
+/*
+ * Set up one of the I/D BAT (block address translation) register pairs.
+ * The parameters are not checked; in particular size must be a power
+ * of 4 between 4k and 256M.
+ */
+void settlbcam(int index, unsigned long virt, phys_addr_t phys,
+ unsigned int size, int flags, unsigned int pid)
+{
+ unsigned int tsize, lz;
+
+ asm ("cntlzw %0,%1" : "=r" (lz) : "r" (size));
+ tsize = (21 - lz) / 2;
+
+#ifdef CONFIG_SMP
+ if ((flags & _PAGE_NO_CACHE) == 0)
+ flags |= _PAGE_COHERENT;
+#endif
+
+ TLBCAM[index].MAS0 = MAS0_TLBSEL(1) | MAS0_ESEL(index);
+ TLBCAM[index].MAS1 = MAS1_VALID | MAS1_IPROT | MAS1_TSIZE(tsize) | MAS1_TID(pid);
+ TLBCAM[index].MAS2 = virt & PAGE_MASK;
+
+ TLBCAM[index].MAS2 |= (flags & _PAGE_WRITETHRU) ? MAS2_W : 0;
+ TLBCAM[index].MAS2 |= (flags & _PAGE_NO_CACHE) ? MAS2_I : 0;
+ TLBCAM[index].MAS2 |= (flags & _PAGE_COHERENT) ? MAS2_M : 0;
+ TLBCAM[index].MAS2 |= (flags & _PAGE_GUARDED) ? MAS2_G : 0;
+ TLBCAM[index].MAS2 |= (flags & _PAGE_ENDIAN) ? MAS2_E : 0;
+
+ TLBCAM[index].MAS3 = (phys & PAGE_MASK) | MAS3_SX | MAS3_SR;
+ TLBCAM[index].MAS3 |= ((flags & _PAGE_RW) ? MAS3_SW : 0);
+
+#ifndef CONFIG_KGDB /* want user access for breakpoints */
+ if (flags & _PAGE_USER) {
+ TLBCAM[index].MAS3 |= MAS3_UX | MAS3_UR;
+ TLBCAM[index].MAS3 |= ((flags & _PAGE_RW) ? MAS3_UW : 0);
+ }
+#else
+ TLBCAM[index].MAS3 |= MAS3_UX | MAS3_UR;
+ TLBCAM[index].MAS3 |= ((flags & _PAGE_RW) ? MAS3_UW : 0);
+#endif
+
+ tlbcam_addrs[index].start = virt;
+ tlbcam_addrs[index].limit = virt + size - 1;
+ tlbcam_addrs[index].phys = phys;
+
+ loadcam_entry(index);
+}
+
+void invalidate_tlbcam_entry(int index)
+{
+ TLBCAM[index].MAS0 = MAS0_TLBSEL(1) | MAS0_ESEL(index);
+ TLBCAM[index].MAS1 = ~MAS1_VALID;
+
+ loadcam_entry(index);
+}
+
+void __init cam_mapin_ram(unsigned long cam0, unsigned long cam1,
+ unsigned long cam2)
+{
+ settlbcam(0, KERNELBASE, PPC_MEMSTART, cam0, _PAGE_KERNEL, 0);
+ tlbcam_index++;
+ if (cam1) {
+ tlbcam_index++;
+ settlbcam(1, KERNELBASE+cam0, PPC_MEMSTART+cam0, cam1, _PAGE_KERNEL, 0);
+ }
+ if (cam2) {
+ tlbcam_index++;
+ settlbcam(2, KERNELBASE+cam0+cam1, PPC_MEMSTART+cam0+cam1, cam2, _PAGE_KERNEL, 0);
+ }
+}
+
+/*
+ * MMU_init_hw does the chip-specific initialization of the MMU hardware.
+ */
+void __init MMU_init_hw(void)
+{
+ flush_instruction_cache();
+}
+
+unsigned long __init mmu_mapin_ram(void)
+{
+ cam_mapin_ram(__cam0, __cam1, __cam2);
+
+ return __cam0 + __cam1 + __cam2;
+}
+
+
+void __init
+adjust_total_lowmem(void)
+{
+ unsigned long max_low_mem = MAX_LOW_MEM;
+ unsigned long cam_max = 0x10000000;
+ unsigned long ram;
+
+ /* adjust CAM size to max_low_mem */
+ if (max_low_mem < cam_max)
+ cam_max = max_low_mem;
+
+ /* adjust lowmem size to max_low_mem */
+ if (max_low_mem < total_lowmem)
+ ram = max_low_mem;
+ else
+ ram = total_lowmem;
+
+ /* Calculate CAM values */
+ __cam0 = 1UL << 2 * (__ilog2(ram) / 2);
+ if (__cam0 > cam_max)
+ __cam0 = cam_max;
+ ram -= __cam0;
+ if (ram) {
+ __cam1 = 1UL << 2 * (__ilog2(ram) / 2);
+ if (__cam1 > cam_max)
+ __cam1 = cam_max;
+ ram -= __cam1;
+ }
+ if (ram) {
+ __cam2 = 1UL << 2 * (__ilog2(ram) / 2);
+ if (__cam2 > cam_max)
+ __cam2 = cam_max;
+ ram -= __cam2;
+ }
+
+ printk(KERN_INFO "Memory CAM mapping: CAM0=%ldMb, CAM1=%ldMb,"
+ " CAM2=%ldMb residual: %ldMb\n",
+ __cam0 >> 20, __cam1 >> 20, __cam2 >> 20,
+ (total_lowmem - __cam0 - __cam1 - __cam2) >> 20);
+ __max_low_memory = max_low_mem = __cam0 + __cam1 + __cam2;
+}
diff --git a/arch/ppc/mm/hashtable.S b/arch/ppc/mm/hashtable.S
new file mode 100644
index 0000000..ab83132
--- /dev/null
+++ b/arch/ppc/mm/hashtable.S
@@ -0,0 +1,642 @@
+/*
+ * arch/ppc/kernel/hashtable.S
+ *
+ * $Id: hashtable.S,v 1.6 1999/10/08 01:56:15 paulus Exp $
+ *
+ * PowerPC version
+ * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
+ * Rewritten by Cort Dougan (cort@cs.nmt.edu) for PReP
+ * Copyright (C) 1996 Cort Dougan <cort@cs.nmt.edu>
+ * Adapted for Power Macintosh by Paul Mackerras.
+ * Low-level exception handlers and MMU support
+ * rewritten by Paul Mackerras.
+ * Copyright (C) 1996 Paul Mackerras.
+ *
+ * This file contains low-level assembler routines for managing
+ * the PowerPC MMU hash table. (PPC 8xx processors don't use a
+ * hash table, so this file is not used on them.)
+ *
+ * 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.
+ *
+ */
+
+#include <linux/config.h>
+#include <asm/processor.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <asm/cputable.h>
+#include <asm/ppc_asm.h>
+#include <asm/thread_info.h>
+#include <asm/offsets.h>
+
+#ifdef CONFIG_SMP
+ .comm mmu_hash_lock,4
+#endif /* CONFIG_SMP */
+
+/*
+ * Sync CPUs with hash_page taking & releasing the hash
+ * table lock
+ */
+#ifdef CONFIG_SMP
+ .text
+_GLOBAL(hash_page_sync)
+ lis r8,mmu_hash_lock@h
+ ori r8,r8,mmu_hash_lock@l
+ lis r0,0x0fff
+ b 10f
+11: lwz r6,0(r8)
+ cmpwi 0,r6,0
+ bne 11b
+10: lwarx r6,0,r8
+ cmpwi 0,r6,0
+ bne- 11b
+ stwcx. r0,0,r8
+ bne- 10b
+ isync
+ eieio
+ li r0,0
+ stw r0,0(r8)
+ blr
+#endif
+
+/*
+ * Load a PTE into the hash table, if possible.
+ * The address is in r4, and r3 contains an access flag:
+ * _PAGE_RW (0x400) if a write.
+ * r9 contains the SRR1 value, from which we use the MSR_PR bit.
+ * SPRG3 contains the physical address of the current task's thread.
+ *
+ * Returns to the caller if the access is illegal or there is no
+ * mapping for the address. Otherwise it places an appropriate PTE
+ * in the hash table and returns from the exception.
+ * Uses r0, r3 - r8, ctr, lr.
+ */
+ .text
+_GLOBAL(hash_page)
+#ifdef CONFIG_PPC64BRIDGE
+ mfmsr r0
+ clrldi r0,r0,1 /* make sure it's in 32-bit mode */
+ MTMSRD(r0)
+ isync
+#endif
+ tophys(r7,0) /* gets -KERNELBASE into r7 */
+#ifdef CONFIG_SMP
+ addis r8,r7,mmu_hash_lock@h
+ ori r8,r8,mmu_hash_lock@l
+ lis r0,0x0fff
+ b 10f
+11: lwz r6,0(r8)
+ cmpwi 0,r6,0
+ bne 11b
+10: lwarx r6,0,r8
+ cmpwi 0,r6,0
+ bne- 11b
+ stwcx. r0,0,r8
+ bne- 10b
+ isync
+#endif
+ /* Get PTE (linux-style) and check access */
+ lis r0,KERNELBASE@h /* check if kernel address */
+ cmplw 0,r4,r0
+ mfspr r8,SPRN_SPRG3 /* current task's THREAD (phys) */
+ ori r3,r3,_PAGE_USER|_PAGE_PRESENT /* test low addresses as user */
+ lwz r5,PGDIR(r8) /* virt page-table root */
+ blt+ 112f /* assume user more likely */
+ lis r5,swapper_pg_dir@ha /* if kernel address, use */
+ addi r5,r5,swapper_pg_dir@l /* kernel page table */
+ rlwimi r3,r9,32-12,29,29 /* MSR_PR -> _PAGE_USER */
+112: add r5,r5,r7 /* convert to phys addr */
+ rlwimi r5,r4,12,20,29 /* insert top 10 bits of address */
+ lwz r8,0(r5) /* get pmd entry */
+ rlwinm. r8,r8,0,0,19 /* extract address of pte page */
+#ifdef CONFIG_SMP
+ beq- hash_page_out /* return if no mapping */
+#else
+ /* XXX it seems like the 601 will give a machine fault on the
+ rfi if its alignment is wrong (bottom 4 bits of address are
+ 8 or 0xc) and we have had a not-taken conditional branch
+ to the address following the rfi. */
+ beqlr-
+#endif
+ rlwimi r8,r4,22,20,29 /* insert next 10 bits of address */
+ rlwinm r0,r3,32-3,24,24 /* _PAGE_RW access -> _PAGE_DIRTY */
+ ori r0,r0,_PAGE_ACCESSED|_PAGE_HASHPTE
+
+ /*
+ * Update the linux PTE atomically. We do the lwarx up-front
+ * because almost always, there won't be a permission violation
+ * and there won't already be an HPTE, and thus we will have
+ * to update the PTE to set _PAGE_HASHPTE. -- paulus.
+ */
+retry:
+ lwarx r6,0,r8 /* get linux-style pte */
+ andc. r5,r3,r6 /* check access & ~permission */
+#ifdef CONFIG_SMP
+ bne- hash_page_out /* return if access not permitted */
+#else
+ bnelr-
+#endif
+ or r5,r0,r6 /* set accessed/dirty bits */
+ stwcx. r5,0,r8 /* attempt to update PTE */
+ bne- retry /* retry if someone got there first */
+
+ mfsrin r3,r4 /* get segment reg for segment */
+ mfctr r0
+ stw r0,_CTR(r11)
+ bl create_hpte /* add the hash table entry */
+
+/*
+ * htab_reloads counts the number of times we have to fault an
+ * HPTE into the hash table. This should only happen after a
+ * fork (because fork does a flush_tlb_mm) or a vmalloc or ioremap.
+ * Where a page is faulted into a process's address space,
+ * update_mmu_cache gets called to put the HPTE into the hash table
+ * and those are counted as preloads rather than reloads.
+ */
+ addis r8,r7,htab_reloads@ha
+ lwz r3,htab_reloads@l(r8)
+ addi r3,r3,1
+ stw r3,htab_reloads@l(r8)
+
+#ifdef CONFIG_SMP
+ eieio
+ addis r8,r7,mmu_hash_lock@ha
+ li r0,0
+ stw r0,mmu_hash_lock@l(r8)
+#endif
+
+ /* Return from the exception */
+ lwz r5,_CTR(r11)
+ mtctr r5
+ lwz r0,GPR0(r11)
+ lwz r7,GPR7(r11)
+ lwz r8,GPR8(r11)
+ b fast_exception_return
+
+#ifdef CONFIG_SMP
+hash_page_out:
+ eieio
+ addis r8,r7,mmu_hash_lock@ha
+ li r0,0
+ stw r0,mmu_hash_lock@l(r8)
+ blr
+#endif /* CONFIG_SMP */
+
+/*
+ * Add an entry for a particular page to the hash table.
+ *
+ * add_hash_page(unsigned context, unsigned long va, unsigned long pmdval)
+ *
+ * We assume any necessary modifications to the pte (e.g. setting
+ * the accessed bit) have already been done and that there is actually
+ * a hash table in use (i.e. we're not on a 603).
+ */
+_GLOBAL(add_hash_page)
+ mflr r0
+ stw r0,4(r1)
+
+ /* Convert context and va to VSID */
+ mulli r3,r3,897*16 /* multiply context by context skew */
+ rlwinm r0,r4,4,28,31 /* get ESID (top 4 bits of va) */
+ mulli r0,r0,0x111 /* multiply by ESID skew */
+ add r3,r3,r0 /* note create_hpte trims to 24 bits */
+
+#ifdef CONFIG_SMP
+ rlwinm r8,r1,0,0,18 /* use cpu number to make tag */
+ lwz r8,TI_CPU(r8) /* to go in mmu_hash_lock */
+ oris r8,r8,12
+#endif /* CONFIG_SMP */
+
+ /*
+ * We disable interrupts here, even on UP, because we don't
+ * want to race with hash_page, and because we want the
+ * _PAGE_HASHPTE bit to be a reliable indication of whether
+ * the HPTE exists (or at least whether one did once).
+ * We also turn off the MMU for data accesses so that we
+ * we can't take a hash table miss (assuming the code is
+ * covered by a BAT). -- paulus
+ */
+ mfmsr r10
+ SYNC
+ rlwinm r0,r10,0,17,15 /* clear bit 16 (MSR_EE) */
+ rlwinm r0,r0,0,28,26 /* clear MSR_DR */
+ mtmsr r0
+ SYNC_601
+ isync
+
+ tophys(r7,0)
+
+#ifdef CONFIG_SMP
+ addis r9,r7,mmu_hash_lock@ha
+ addi r9,r9,mmu_hash_lock@l
+10: lwarx r0,0,r9 /* take the mmu_hash_lock */
+ cmpi 0,r0,0
+ bne- 11f
+ stwcx. r8,0,r9
+ beq+ 12f
+11: lwz r0,0(r9)
+ cmpi 0,r0,0
+ beq 10b
+ b 11b
+12: isync
+#endif
+
+ /*
+ * Fetch the linux pte and test and set _PAGE_HASHPTE atomically.
+ * If _PAGE_HASHPTE was already set, we don't replace the existing
+ * HPTE, so we just unlock and return.
+ */
+ mr r8,r5
+ rlwimi r8,r4,22,20,29
+1: lwarx r6,0,r8
+ andi. r0,r6,_PAGE_HASHPTE
+ bne 9f /* if HASHPTE already set, done */
+ ori r5,r6,_PAGE_HASHPTE
+ stwcx. r5,0,r8
+ bne- 1b
+
+ bl create_hpte
+
+ addis r8,r7,htab_preloads@ha
+ lwz r3,htab_preloads@l(r8)
+ addi r3,r3,1
+ stw r3,htab_preloads@l(r8)
+
+9:
+#ifdef CONFIG_SMP
+ eieio
+ li r0,0
+ stw r0,0(r9) /* clear mmu_hash_lock */
+#endif
+
+ /* reenable interrupts and DR */
+ mtmsr r10
+ SYNC_601
+ isync
+
+ lwz r0,4(r1)
+ mtlr r0
+ blr
+
+/*
+ * This routine adds a hardware PTE to the hash table.
+ * It is designed to be called with the MMU either on or off.
+ * r3 contains the VSID, r4 contains the virtual address,
+ * r5 contains the linux PTE, r6 contains the old value of the
+ * linux PTE (before setting _PAGE_HASHPTE) and r7 contains the
+ * offset to be added to addresses (0 if the MMU is on,
+ * -KERNELBASE if it is off).
+ * On SMP, the caller should have the mmu_hash_lock held.
+ * We assume that the caller has (or will) set the _PAGE_HASHPTE
+ * bit in the linux PTE in memory. The value passed in r6 should
+ * be the old linux PTE value; if it doesn't have _PAGE_HASHPTE set
+ * this routine will skip the search for an existing HPTE.
+ * This procedure modifies r0, r3 - r6, r8, cr0.
+ * -- paulus.
+ *
+ * For speed, 4 of the instructions get patched once the size and
+ * physical address of the hash table are known. These definitions
+ * of Hash_base and Hash_bits below are just an example.
+ */
+Hash_base = 0xc0180000
+Hash_bits = 12 /* e.g. 256kB hash table */
+Hash_msk = (((1 << Hash_bits) - 1) * 64)
+
+#ifndef CONFIG_PPC64BRIDGE
+/* defines for the PTE format for 32-bit PPCs */
+#define PTE_SIZE 8
+#define PTEG_SIZE 64
+#define LG_PTEG_SIZE 6
+#define LDPTEu lwzu
+#define STPTE stw
+#define CMPPTE cmpw
+#define PTE_H 0x40
+#define PTE_V 0x80000000
+#define TST_V(r) rlwinm. r,r,0,0,0
+#define SET_V(r) oris r,r,PTE_V@h
+#define CLR_V(r,t) rlwinm r,r,0,1,31
+
+#else
+/* defines for the PTE format for 64-bit PPCs */
+#define PTE_SIZE 16
+#define PTEG_SIZE 128
+#define LG_PTEG_SIZE 7
+#define LDPTEu ldu
+#define STPTE std
+#define CMPPTE cmpd
+#define PTE_H 2
+#define PTE_V 1
+#define TST_V(r) andi. r,r,PTE_V
+#define SET_V(r) ori r,r,PTE_V
+#define CLR_V(r,t) li t,PTE_V; andc r,r,t
+#endif /* CONFIG_PPC64BRIDGE */
+
+#define HASH_LEFT 31-(LG_PTEG_SIZE+Hash_bits-1)
+#define HASH_RIGHT 31-LG_PTEG_SIZE
+
+_GLOBAL(create_hpte)
+ /* Convert linux-style PTE (r5) to low word of PPC-style PTE (r8) */
+ rlwinm r8,r5,32-10,31,31 /* _PAGE_RW -> PP lsb */
+ rlwinm r0,r5,32-7,31,31 /* _PAGE_DIRTY -> PP lsb */
+ and r8,r8,r0 /* writable if _RW & _DIRTY */
+ rlwimi r5,r5,32-1,30,30 /* _PAGE_USER -> PP msb */
+ rlwimi r5,r5,32-2,31,31 /* _PAGE_USER -> PP lsb */
+ ori r8,r8,0xe14 /* clear out reserved bits and M */
+ andc r8,r5,r8 /* PP = user? (rw&dirty? 2: 3): 0 */
+BEGIN_FTR_SECTION
+ ori r8,r8,_PAGE_COHERENT /* set M (coherence required) */
+END_FTR_SECTION_IFSET(CPU_FTR_NEED_COHERENT)
+
+ /* Construct the high word of the PPC-style PTE (r5) */
+#ifndef CONFIG_PPC64BRIDGE
+ rlwinm r5,r3,7,1,24 /* put VSID in 0x7fffff80 bits */
+ rlwimi r5,r4,10,26,31 /* put in API (abbrev page index) */
+#else /* CONFIG_PPC64BRIDGE */
+ clrlwi r3,r3,8 /* reduce vsid to 24 bits */
+ sldi r5,r3,12 /* shift vsid into position */
+ rlwimi r5,r4,16,20,24 /* put in API (abbrev page index) */
+#endif /* CONFIG_PPC64BRIDGE */
+ SET_V(r5) /* set V (valid) bit */
+
+ /* Get the address of the primary PTE group in the hash table (r3) */
+_GLOBAL(hash_page_patch_A)
+ addis r0,r7,Hash_base@h /* base address of hash table */
+ rlwimi r0,r3,LG_PTEG_SIZE,HASH_LEFT,HASH_RIGHT /* VSID -> hash */
+ rlwinm r3,r4,20+LG_PTEG_SIZE,HASH_LEFT,HASH_RIGHT /* PI -> hash */
+ xor r3,r3,r0 /* make primary hash */
+ li r0,8 /* PTEs/group */
+
+ /*
+ * Test the _PAGE_HASHPTE bit in the old linux PTE, and skip the search
+ * if it is clear, meaning that the HPTE isn't there already...
+ */
+ andi. r6,r6,_PAGE_HASHPTE
+ beq+ 10f /* no PTE: go look for an empty slot */
+ tlbie r4
+
+ addis r4,r7,htab_hash_searches@ha
+ lwz r6,htab_hash_searches@l(r4)
+ addi r6,r6,1 /* count how many searches we do */
+ stw r6,htab_hash_searches@l(r4)
+
+ /* Search the primary PTEG for a PTE whose 1st (d)word matches r5 */
+ mtctr r0
+ addi r4,r3,-PTE_SIZE
+1: LDPTEu r6,PTE_SIZE(r4) /* get next PTE */
+ CMPPTE 0,r6,r5
+ bdnzf 2,1b /* loop while ctr != 0 && !cr0.eq */
+ beq+ found_slot
+
+ /* Search the secondary PTEG for a matching PTE */
+ ori r5,r5,PTE_H /* set H (secondary hash) bit */
+_GLOBAL(hash_page_patch_B)
+ xoris r4,r3,Hash_msk>>16 /* compute secondary hash */
+ xori r4,r4,(-PTEG_SIZE & 0xffff)
+ addi r4,r4,-PTE_SIZE
+ mtctr r0
+2: LDPTEu r6,PTE_SIZE(r4)
+ CMPPTE 0,r6,r5
+ bdnzf 2,2b
+ beq+ found_slot
+ xori r5,r5,PTE_H /* clear H bit again */
+
+ /* Search the primary PTEG for an empty slot */
+10: mtctr r0
+ addi r4,r3,-PTE_SIZE /* search primary PTEG */
+1: LDPTEu r6,PTE_SIZE(r4) /* get next PTE */
+ TST_V(r6) /* test valid bit */
+ bdnzf 2,1b /* loop while ctr != 0 && !cr0.eq */
+ beq+ found_empty
+
+ /* update counter of times that the primary PTEG is full */
+ addis r4,r7,primary_pteg_full@ha
+ lwz r6,primary_pteg_full@l(r4)
+ addi r6,r6,1
+ stw r6,primary_pteg_full@l(r4)
+
+ /* Search the secondary PTEG for an empty slot */
+ ori r5,r5,PTE_H /* set H (secondary hash) bit */
+_GLOBAL(hash_page_patch_C)
+ xoris r4,r3,Hash_msk>>16 /* compute secondary hash */
+ xori r4,r4,(-PTEG_SIZE & 0xffff)
+ addi r4,r4,-PTE_SIZE
+ mtctr r0
+2: LDPTEu r6,PTE_SIZE(r4)
+ TST_V(r6)
+ bdnzf 2,2b
+ beq+ found_empty
+ xori r5,r5,PTE_H /* clear H bit again */
+
+ /*
+ * Choose an arbitrary slot in the primary PTEG to overwrite.
+ * Since both the primary and secondary PTEGs are full, and we
+ * have no information that the PTEs in the primary PTEG are
+ * more important or useful than those in the secondary PTEG,
+ * and we know there is a definite (although small) speed
+ * advantage to putting the PTE in the primary PTEG, we always
+ * put the PTE in the primary PTEG.
+ */
+ addis r4,r7,next_slot@ha
+ lwz r6,next_slot@l(r4)
+ addi r6,r6,PTE_SIZE
+ andi. r6,r6,7*PTE_SIZE
+ stw r6,next_slot@l(r4)
+ add r4,r3,r6
+
+ /* update counter of evicted pages */
+ addis r6,r7,htab_evicts@ha
+ lwz r3,htab_evicts@l(r6)
+ addi r3,r3,1
+ stw r3,htab_evicts@l(r6)
+
+#ifndef CONFIG_SMP
+ /* Store PTE in PTEG */
+found_empty:
+ STPTE r5,0(r4)
+found_slot:
+ STPTE r8,PTE_SIZE/2(r4)
+
+#else /* CONFIG_SMP */
+/*
+ * Between the tlbie above and updating the hash table entry below,
+ * another CPU could read the hash table entry and put it in its TLB.
+ * There are 3 cases:
+ * 1. using an empty slot
+ * 2. updating an earlier entry to change permissions (i.e. enable write)
+ * 3. taking over the PTE for an unrelated address
+ *
+ * In each case it doesn't really matter if the other CPUs have the old
+ * PTE in their TLB. So we don't need to bother with another tlbie here,
+ * which is convenient as we've overwritten the register that had the
+ * address. :-) The tlbie above is mainly to make sure that this CPU comes
+ * and gets the new PTE from the hash table.
+ *
+ * We do however have to make sure that the PTE is never in an invalid
+ * state with the V bit set.
+ */
+found_empty:
+found_slot:
+ CLR_V(r5,r0) /* clear V (valid) bit in PTE */
+ STPTE r5,0(r4)
+ sync
+ TLBSYNC
+ STPTE r8,PTE_SIZE/2(r4) /* put in correct RPN, WIMG, PP bits */
+ sync
+ SET_V(r5)
+ STPTE r5,0(r4) /* finally set V bit in PTE */
+#endif /* CONFIG_SMP */
+
+ sync /* make sure pte updates get to memory */
+ blr
+
+ .comm next_slot,4
+ .comm primary_pteg_full,4
+ .comm htab_hash_searches,4
+
+/*
+ * Flush the entry for a particular page from the hash table.
+ *
+ * flush_hash_pages(unsigned context, unsigned long va, unsigned long pmdval,
+ * int count)
+ *
+ * We assume that there is a hash table in use (Hash != 0).
+ */
+_GLOBAL(flush_hash_pages)
+ tophys(r7,0)
+
+ /*
+ * We disable interrupts here, even on UP, because we want
+ * the _PAGE_HASHPTE bit to be a reliable indication of
+ * whether the HPTE exists (or at least whether one did once).
+ * We also turn off the MMU for data accesses so that we
+ * we can't take a hash table miss (assuming the code is
+ * covered by a BAT). -- paulus
+ */
+ mfmsr r10
+ SYNC
+ rlwinm r0,r10,0,17,15 /* clear bit 16 (MSR_EE) */
+ rlwinm r0,r0,0,28,26 /* clear MSR_DR */
+ mtmsr r0
+ SYNC_601
+ isync
+
+ /* First find a PTE in the range that has _PAGE_HASHPTE set */
+ rlwimi r5,r4,22,20,29
+1: lwz r0,0(r5)
+ cmpwi cr1,r6,1
+ andi. r0,r0,_PAGE_HASHPTE
+ bne 2f
+ ble cr1,19f
+ addi r4,r4,0x1000
+ addi r5,r5,4
+ addi r6,r6,-1
+ b 1b
+
+ /* Convert context and va to VSID */
+2: mulli r3,r3,897*16 /* multiply context by context skew */
+ rlwinm r0,r4,4,28,31 /* get ESID (top 4 bits of va) */
+ mulli r0,r0,0x111 /* multiply by ESID skew */
+ add r3,r3,r0 /* note code below trims to 24 bits */
+
+ /* Construct the high word of the PPC-style PTE (r11) */
+#ifndef CONFIG_PPC64BRIDGE
+ rlwinm r11,r3,7,1,24 /* put VSID in 0x7fffff80 bits */
+ rlwimi r11,r4,10,26,31 /* put in API (abbrev page index) */
+#else /* CONFIG_PPC64BRIDGE */
+ clrlwi r3,r3,8 /* reduce vsid to 24 bits */
+ sldi r11,r3,12 /* shift vsid into position */
+ rlwimi r11,r4,16,20,24 /* put in API (abbrev page index) */
+#endif /* CONFIG_PPC64BRIDGE */
+ SET_V(r11) /* set V (valid) bit */
+
+#ifdef CONFIG_SMP
+ addis r9,r7,mmu_hash_lock@ha
+ addi r9,r9,mmu_hash_lock@l
+ rlwinm r8,r1,0,0,18
+ add r8,r8,r7
+ lwz r8,TI_CPU(r8)
+ oris r8,r8,9
+10: lwarx r0,0,r9
+ cmpi 0,r0,0
+ bne- 11f
+ stwcx. r8,0,r9
+ beq+ 12f
+11: lwz r0,0(r9)
+ cmpi 0,r0,0
+ beq 10b
+ b 11b
+12: isync
+#endif
+
+ /*
+ * Check the _PAGE_HASHPTE bit in the linux PTE. If it is
+ * already clear, we're done (for this pte). If not,
+ * clear it (atomically) and proceed. -- paulus.
+ */
+33: lwarx r8,0,r5 /* fetch the pte */
+ andi. r0,r8,_PAGE_HASHPTE
+ beq 8f /* done if HASHPTE is already clear */
+ rlwinm r8,r8,0,31,29 /* clear HASHPTE bit */
+ stwcx. r8,0,r5 /* update the pte */
+ bne- 33b
+
+ /* Get the address of the primary PTE group in the hash table (r3) */
+_GLOBAL(flush_hash_patch_A)
+ addis r8,r7,Hash_base@h /* base address of hash table */
+ rlwimi r8,r3,LG_PTEG_SIZE,HASH_LEFT,HASH_RIGHT /* VSID -> hash */
+ rlwinm r0,r4,20+LG_PTEG_SIZE,HASH_LEFT,HASH_RIGHT /* PI -> hash */
+ xor r8,r0,r8 /* make primary hash */
+
+ /* Search the primary PTEG for a PTE whose 1st (d)word matches r5 */
+ li r0,8 /* PTEs/group */
+ mtctr r0
+ addi r12,r8,-PTE_SIZE
+1: LDPTEu r0,PTE_SIZE(r12) /* get next PTE */
+ CMPPTE 0,r0,r11
+ bdnzf 2,1b /* loop while ctr != 0 && !cr0.eq */
+ beq+ 3f
+
+ /* Search the secondary PTEG for a matching PTE */
+ ori r11,r11,PTE_H /* set H (secondary hash) bit */
+ li r0,8 /* PTEs/group */
+_GLOBAL(flush_hash_patch_B)
+ xoris r12,r8,Hash_msk>>16 /* compute secondary hash */
+ xori r12,r12,(-PTEG_SIZE & 0xffff)
+ addi r12,r12,-PTE_SIZE
+ mtctr r0
+2: LDPTEu r0,PTE_SIZE(r12)
+ CMPPTE 0,r0,r11
+ bdnzf 2,2b
+ xori r11,r11,PTE_H /* clear H again */
+ bne- 4f /* should rarely fail to find it */
+
+3: li r0,0
+ STPTE r0,0(r12) /* invalidate entry */
+4: sync
+ tlbie r4 /* in hw tlb too */
+ sync
+
+8: ble cr1,9f /* if all ptes checked */
+81: addi r6,r6,-1
+ addi r5,r5,4 /* advance to next pte */
+ addi r4,r4,0x1000
+ lwz r0,0(r5) /* check next pte */
+ cmpwi cr1,r6,1
+ andi. r0,r0,_PAGE_HASHPTE
+ bne 33b
+ bgt cr1,81b
+
+9:
+#ifdef CONFIG_SMP
+ TLBSYNC
+ li r0,0
+ stw r0,0(r9) /* clear mmu_hash_lock */
+#endif
+
+19: mtmsr r10
+ SYNC_601
+ isync
+ blr
diff --git a/arch/ppc/mm/init.c b/arch/ppc/mm/init.c
new file mode 100644
index 0000000..be02a7f
--- /dev/null
+++ b/arch/ppc/mm/init.c
@@ -0,0 +1,667 @@
+/*
+ * PowerPC version
+ * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
+ *
+ * Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au)
+ * and Cort Dougan (PReP) (cort@cs.nmt.edu)
+ * Copyright (C) 1996 Paul Mackerras
+ * Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk).
+ * PPC44x/36-bit changes by Matt Porter (mporter@mvista.com)
+ *
+ * Derived from "arch/i386/mm/init.c"
+ * Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds
+ *
+ * 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.
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/types.h>
+#include <linux/mm.h>
+#include <linux/stddef.h>
+#include <linux/init.h>
+#include <linux/bootmem.h>
+#include <linux/highmem.h>
+#include <linux/initrd.h>
+#include <linux/pagemap.h>
+
+#include <asm/pgalloc.h>
+#include <asm/prom.h>
+#include <asm/io.h>
+#include <asm/mmu_context.h>
+#include <asm/pgtable.h>
+#include <asm/mmu.h>
+#include <asm/smp.h>
+#include <asm/machdep.h>
+#include <asm/btext.h>
+#include <asm/tlb.h>
+#include <asm/bootinfo.h>
+
+#include "mem_pieces.h"
+#include "mmu_decl.h"
+
+#if defined(CONFIG_KERNEL_START_BOOL) || defined(CONFIG_LOWMEM_SIZE_BOOL)
+/* The ammount of lowmem must be within 0xF0000000 - KERNELBASE. */
+#if (CONFIG_LOWMEM_SIZE > (0xF0000000 - KERNELBASE))
+#error "You must adjust CONFIG_LOWMEM_SIZE or CONFIG_START_KERNEL"
+#endif
+#endif
+#define MAX_LOW_MEM CONFIG_LOWMEM_SIZE
+
+DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
+
+unsigned long total_memory;
+unsigned long total_lowmem;
+
+unsigned long ppc_memstart;
+unsigned long ppc_memoffset = PAGE_OFFSET;
+
+int mem_init_done;
+int init_bootmem_done;
+int boot_mapsize;
+#ifdef CONFIG_PPC_PMAC
+unsigned long agp_special_page;
+#endif
+
+extern char _end[];
+extern char etext[], _stext[];
+extern char __init_begin, __init_end;
+extern char __prep_begin, __prep_end;
+extern char __chrp_begin, __chrp_end;
+extern char __pmac_begin, __pmac_end;
+extern char __openfirmware_begin, __openfirmware_end;
+
+#ifdef CONFIG_HIGHMEM
+pte_t *kmap_pte;
+pgprot_t kmap_prot;
+
+EXPORT_SYMBOL(kmap_prot);
+EXPORT_SYMBOL(kmap_pte);
+#endif
+
+void MMU_init(void);
+void set_phys_avail(unsigned long total_ram);
+
+/* XXX should be in current.h -- paulus */
+extern struct task_struct *current_set[NR_CPUS];
+
+char *klimit = _end;
+struct mem_pieces phys_avail;
+
+extern char *sysmap;
+extern unsigned long sysmap_size;
+
+/*
+ * this tells the system to map all of ram with the segregs
+ * (i.e. page tables) instead of the bats.
+ * -- Cort
+ */
+int __map_without_bats;
+int __map_without_ltlbs;
+
+/* max amount of RAM to use */
+unsigned long __max_memory;
+/* max amount of low RAM to map in */
+unsigned long __max_low_memory = MAX_LOW_MEM;
+
+void show_mem(void)
+{
+ int i,free = 0,total = 0,reserved = 0;
+ int shared = 0, cached = 0;
+ int highmem = 0;
+
+ printk("Mem-info:\n");
+ show_free_areas();
+ printk("Free swap: %6ldkB\n", nr_swap_pages<<(PAGE_SHIFT-10));
+ i = max_mapnr;
+ while (i-- > 0) {
+ total++;
+ if (PageHighMem(mem_map+i))
+ highmem++;
+ if (PageReserved(mem_map+i))
+ reserved++;
+ else if (PageSwapCache(mem_map+i))
+ cached++;
+ else if (!page_count(mem_map+i))
+ free++;
+ else
+ shared += page_count(mem_map+i) - 1;
+ }
+ printk("%d pages of RAM\n",total);
+ printk("%d pages of HIGHMEM\n", highmem);
+ printk("%d free pages\n",free);
+ printk("%d reserved pages\n",reserved);
+ printk("%d pages shared\n",shared);
+ printk("%d pages swap cached\n",cached);
+}
+
+/* Free up now-unused memory */
+static void free_sec(unsigned long start, unsigned long end, const char *name)
+{
+ unsigned long cnt = 0;
+
+ while (start < end) {
+ ClearPageReserved(virt_to_page(start));
+ set_page_count(virt_to_page(start), 1);
+ free_page(start);
+ cnt++;
+ start += PAGE_SIZE;
+ }
+ if (cnt) {
+ printk(" %ldk %s", cnt << (PAGE_SHIFT - 10), name);
+ totalram_pages += cnt;
+ }
+}
+
+void free_initmem(void)
+{
+#define FREESEC(TYPE) \
+ free_sec((unsigned long)(&__ ## TYPE ## _begin), \
+ (unsigned long)(&__ ## TYPE ## _end), \
+ #TYPE);
+
+ printk ("Freeing unused kernel memory:");
+ FREESEC(init);
+ if (_machine != _MACH_Pmac)
+ FREESEC(pmac);
+ if (_machine != _MACH_chrp)
+ FREESEC(chrp);
+ if (_machine != _MACH_prep)
+ FREESEC(prep);
+ if (!have_of)
+ FREESEC(openfirmware);
+ printk("\n");
+#undef FREESEC
+}
+
+#ifdef CONFIG_BLK_DEV_INITRD
+void free_initrd_mem(unsigned long start, unsigned long end)
+{
+ printk ("Freeing initrd memory: %ldk freed\n", (end - start) >> 10);
+
+ for (; start < end; start += PAGE_SIZE) {
+ ClearPageReserved(virt_to_page(start));
+ set_page_count(virt_to_page(start), 1);
+ free_page(start);
+ totalram_pages++;
+ }
+}
+#endif
+
+/*
+ * Check for command-line options that affect what MMU_init will do.
+ */
+void MMU_setup(void)
+{
+ /* Check for nobats option (used in mapin_ram). */
+ if (strstr(cmd_line, "nobats")) {
+ __map_without_bats = 1;
+ }
+
+ if (strstr(cmd_line, "noltlbs")) {
+ __map_without_ltlbs = 1;
+ }
+
+ /* Look for mem= option on command line */
+ if (strstr(cmd_line, "mem=")) {
+ char *p, *q;
+ unsigned long maxmem = 0;
+
+ for (q = cmd_line; (p = strstr(q, "mem=")) != 0; ) {
+ q = p + 4;
+ if (p > cmd_line && p[-1] != ' ')
+ continue;
+ maxmem = simple_strtoul(q, &q, 0);
+ if (*q == 'k' || *q == 'K') {
+ maxmem <<= 10;
+ ++q;
+ } else if (*q == 'm' || *q == 'M') {
+ maxmem <<= 20;
+ ++q;
+ }
+ }
+ __max_memory = maxmem;
+ }
+}
+
+/*
+ * MMU_init sets up the basic memory mappings for the kernel,
+ * including both RAM and possibly some I/O regions,
+ * and sets up the page tables and the MMU hardware ready to go.
+ */
+void __init MMU_init(void)
+{
+ if (ppc_md.progress)
+ ppc_md.progress("MMU:enter", 0x111);
+
+ /* parse args from command line */
+ MMU_setup();
+
+ /*
+ * Figure out how much memory we have, how much
+ * is lowmem, and how much is highmem. If we were
+ * passed the total memory size from the bootloader,
+ * just use it.
+ */
+ if (boot_mem_size)
+ total_memory = boot_mem_size;
+ else
+ total_memory = ppc_md.find_end_of_memory();
+
+ if (__max_memory && total_memory > __max_memory)
+ total_memory = __max_memory;
+ total_lowmem = total_memory;
+#ifdef CONFIG_FSL_BOOKE
+ /* Freescale Book-E parts expect lowmem to be mapped by fixed TLB
+ * entries, so we need to adjust lowmem to match the amount we can map
+ * in the fixed entries */
+ adjust_total_lowmem();
+#endif /* CONFIG_FSL_BOOKE */
+ if (total_lowmem > __max_low_memory) {
+ total_lowmem = __max_low_memory;
+#ifndef CONFIG_HIGHMEM
+ total_memory = total_lowmem;
+#endif /* CONFIG_HIGHMEM */
+ }
+ set_phys_avail(total_lowmem);
+
+ /* Initialize the MMU hardware */
+ if (ppc_md.progress)
+ ppc_md.progress("MMU:hw init", 0x300);
+ MMU_init_hw();
+
+ /* Map in all of RAM starting at KERNELBASE */
+ if (ppc_md.progress)
+ ppc_md.progress("MMU:mapin", 0x301);
+ mapin_ram();
+
+#ifdef CONFIG_HIGHMEM
+ ioremap_base = PKMAP_BASE;
+#else
+ ioremap_base = 0xfe000000UL; /* for now, could be 0xfffff000 */
+#endif /* CONFIG_HIGHMEM */
+ ioremap_bot = ioremap_base;
+
+ /* Map in I/O resources */
+ if (ppc_md.progress)
+ ppc_md.progress("MMU:setio", 0x302);
+ if (ppc_md.setup_io_mappings)
+ ppc_md.setup_io_mappings();
+
+ /* Initialize the context management stuff */
+ mmu_context_init();
+
+ if (ppc_md.progress)
+ ppc_md.progress("MMU:exit", 0x211);
+
+#ifdef CONFIG_BOOTX_TEXT
+ /* By default, we are no longer mapped */
+ boot_text_mapped = 0;
+ /* Must be done last, or ppc_md.progress will die. */
+ map_boot_text();
+#endif
+}
+
+/* This is only called until mem_init is done. */
+void __init *early_get_page(void)
+{
+ void *p;
+
+ if (init_bootmem_done) {
+ p = alloc_bootmem_pages(PAGE_SIZE);
+ } else {
+ p = mem_pieces_find(PAGE_SIZE, PAGE_SIZE);
+ }
+ return p;
+}
+
+/*
+ * Initialize the bootmem system and give it all the memory we
+ * have available.
+ */
+void __init do_init_bootmem(void)
+{
+ unsigned long start, size;
+ int i;
+
+ /*
+ * Find an area to use for the bootmem bitmap.
+ * We look for the first area which is at least
+ * 128kB in length (128kB is enough for a bitmap
+ * for 4GB of memory, using 4kB pages), plus 1 page
+ * (in case the address isn't page-aligned).
+ */
+ start = 0;
+ size = 0;
+ for (i = 0; i < phys_avail.n_regions; ++i) {
+ unsigned long a = phys_avail.regions[i].address;
+ unsigned long s = phys_avail.regions[i].size;
+ if (s <= size)
+ continue;
+ start = a;
+ size = s;
+ if (s >= 33 * PAGE_SIZE)
+ break;
+ }
+ start = PAGE_ALIGN(start);
+
+ min_low_pfn = start >> PAGE_SHIFT;
+ max_low_pfn = (PPC_MEMSTART + total_lowmem) >> PAGE_SHIFT;
+ max_pfn = (PPC_MEMSTART + total_memory) >> PAGE_SHIFT;
+ boot_mapsize = init_bootmem_node(&contig_page_data, min_low_pfn,
+ PPC_MEMSTART >> PAGE_SHIFT,
+ max_low_pfn);
+
+ /* remove the bootmem bitmap from the available memory */
+ mem_pieces_remove(&phys_avail, start, boot_mapsize, 1);
+
+ /* add everything in phys_avail into the bootmem map */
+ for (i = 0; i < phys_avail.n_regions; ++i)
+ free_bootmem(phys_avail.regions[i].address,
+ phys_avail.regions[i].size);
+
+ init_bootmem_done = 1;
+}
+
+/*
+ * paging_init() sets up the page tables - in fact we've already done this.
+ */
+void __init paging_init(void)
+{
+ unsigned long zones_size[MAX_NR_ZONES], i;
+
+#ifdef CONFIG_HIGHMEM
+ map_page(PKMAP_BASE, 0, 0); /* XXX gross */
+ pkmap_page_table = pte_offset_kernel(pmd_offset(pgd_offset_k
+ (PKMAP_BASE), PKMAP_BASE), PKMAP_BASE);
+ map_page(KMAP_FIX_BEGIN, 0, 0); /* XXX gross */
+ kmap_pte = pte_offset_kernel(pmd_offset(pgd_offset_k
+ (KMAP_FIX_BEGIN), KMAP_FIX_BEGIN), KMAP_FIX_BEGIN);
+ kmap_prot = PAGE_KERNEL;
+#endif /* CONFIG_HIGHMEM */
+
+ /*
+ * All pages are DMA-able so we put them all in the DMA zone.
+ */
+ zones_size[ZONE_DMA] = total_lowmem >> PAGE_SHIFT;
+ for (i = 1; i < MAX_NR_ZONES; i++)
+ zones_size[i] = 0;
+
+#ifdef CONFIG_HIGHMEM
+ zones_size[ZONE_HIGHMEM] = (total_memory - total_lowmem) >> PAGE_SHIFT;
+#endif /* CONFIG_HIGHMEM */
+
+ free_area_init(zones_size);
+}
+
+void __init mem_init(void)
+{
+ unsigned long addr;
+ int codepages = 0;
+ int datapages = 0;
+ int initpages = 0;
+#ifdef CONFIG_HIGHMEM
+ unsigned long highmem_mapnr;
+
+ highmem_mapnr = total_lowmem >> PAGE_SHIFT;
+#endif /* CONFIG_HIGHMEM */
+ max_mapnr = total_memory >> PAGE_SHIFT;
+
+ high_memory = (void *) __va(PPC_MEMSTART + total_lowmem);
+ num_physpages = max_mapnr; /* RAM is assumed contiguous */
+
+ totalram_pages += free_all_bootmem();
+
+#ifdef CONFIG_BLK_DEV_INITRD
+ /* if we are booted from BootX with an initial ramdisk,
+ make sure the ramdisk pages aren't reserved. */
+ if (initrd_start) {
+ for (addr = initrd_start; addr < initrd_end; addr += PAGE_SIZE)
+ ClearPageReserved(virt_to_page(addr));
+ }
+#endif /* CONFIG_BLK_DEV_INITRD */
+
+#ifdef CONFIG_PPC_OF
+ /* mark the RTAS pages as reserved */
+ if ( rtas_data )
+ for (addr = (ulong)__va(rtas_data);
+ addr < PAGE_ALIGN((ulong)__va(rtas_data)+rtas_size) ;
+ addr += PAGE_SIZE)
+ SetPageReserved(virt_to_page(addr));
+#endif
+#ifdef CONFIG_PPC_PMAC
+ if (agp_special_page)
+ SetPageReserved(virt_to_page(agp_special_page));
+#endif
+ if ( sysmap )
+ for (addr = (unsigned long)sysmap;
+ addr < PAGE_ALIGN((unsigned long)sysmap+sysmap_size) ;
+ addr += PAGE_SIZE)
+ SetPageReserved(virt_to_page(addr));
+
+ for (addr = PAGE_OFFSET; addr < (unsigned long)high_memory;
+ addr += PAGE_SIZE) {
+ if (!PageReserved(virt_to_page(addr)))
+ continue;
+ if (addr < (ulong) etext)
+ codepages++;
+ else if (addr >= (unsigned long)&__init_begin
+ && addr < (unsigned long)&__init_end)
+ initpages++;
+ else if (addr < (ulong) klimit)
+ datapages++;
+ }
+
+#ifdef CONFIG_HIGHMEM
+ {
+ unsigned long pfn;
+
+ for (pfn = highmem_mapnr; pfn < max_mapnr; ++pfn) {
+ struct page *page = mem_map + pfn;
+
+ ClearPageReserved(page);
+ set_bit(PG_highmem, &page->flags);
+ set_page_count(page, 1);
+ __free_page(page);
+ totalhigh_pages++;
+ }
+ totalram_pages += totalhigh_pages;
+ }
+#endif /* CONFIG_HIGHMEM */
+
+ printk("Memory: %luk available (%dk kernel code, %dk data, %dk init, %ldk highmem)\n",
+ (unsigned long)nr_free_pages()<< (PAGE_SHIFT-10),
+ codepages<< (PAGE_SHIFT-10), datapages<< (PAGE_SHIFT-10),
+ initpages<< (PAGE_SHIFT-10),
+ (unsigned long) (totalhigh_pages << (PAGE_SHIFT-10)));
+ if (sysmap)
+ printk("System.map loaded at 0x%08x for debugger, size: %ld bytes\n",
+ (unsigned int)sysmap, sysmap_size);
+#ifdef CONFIG_PPC_PMAC
+ if (agp_special_page)
+ printk(KERN_INFO "AGP special page: 0x%08lx\n", agp_special_page);
+#endif
+
+ mem_init_done = 1;
+}
+
+/*
+ * Set phys_avail to the amount of physical memory,
+ * less the kernel text/data/bss.
+ */
+void __init
+set_phys_avail(unsigned long total_memory)
+{
+ unsigned long kstart, ksize;
+
+ /*
+ * Initially, available physical memory is equivalent to all
+ * physical memory.
+ */
+
+ phys_avail.regions[0].address = PPC_MEMSTART;
+ phys_avail.regions[0].size = total_memory;
+ phys_avail.n_regions = 1;
+
+ /*
+ * Map out the kernel text/data/bss from the available physical
+ * memory.
+ */
+
+ kstart = __pa(_stext); /* should be 0 */
+ ksize = PAGE_ALIGN(klimit - _stext);
+
+ mem_pieces_remove(&phys_avail, kstart, ksize, 0);
+ mem_pieces_remove(&phys_avail, 0, 0x4000, 0);
+
+#if defined(CONFIG_BLK_DEV_INITRD)
+ /* Remove the init RAM disk from the available memory. */
+ if (initrd_start) {
+ mem_pieces_remove(&phys_avail, __pa(initrd_start),
+ initrd_end - initrd_start, 1);
+ }
+#endif /* CONFIG_BLK_DEV_INITRD */
+#ifdef CONFIG_PPC_OF
+ /* remove the RTAS pages from the available memory */
+ if (rtas_data)
+ mem_pieces_remove(&phys_avail, rtas_data, rtas_size, 1);
+#endif
+ /* remove the sysmap pages from the available memory */
+ if (sysmap)
+ mem_pieces_remove(&phys_avail, __pa(sysmap), sysmap_size, 1);
+#ifdef CONFIG_PPC_PMAC
+ /* Because of some uninorth weirdness, we need a page of
+ * memory as high as possible (it must be outside of the
+ * bus address seen as the AGP aperture). It will be used
+ * by the r128 DRM driver
+ *
+ * FIXME: We need to make sure that page doesn't overlap any of the\
+ * above. This could be done by improving mem_pieces_find to be able
+ * to do a backward search from the end of the list.
+ */
+ if (_machine == _MACH_Pmac && find_devices("uni-north-agp")) {
+ agp_special_page = (total_memory - PAGE_SIZE);
+ mem_pieces_remove(&phys_avail, agp_special_page, PAGE_SIZE, 0);
+ agp_special_page = (unsigned long)__va(agp_special_page);
+ }
+#endif /* CONFIG_PPC_PMAC */
+}
+
+/* Mark some memory as reserved by removing it from phys_avail. */
+void __init reserve_phys_mem(unsigned long start, unsigned long size)
+{
+ mem_pieces_remove(&phys_avail, start, size, 1);
+}
+
+/*
+ * This is called when a page has been modified by the kernel.
+ * It just marks the page as not i-cache clean. We do the i-cache
+ * flush later when the page is given to a user process, if necessary.
+ */
+void flush_dcache_page(struct page *page)
+{
+ clear_bit(PG_arch_1, &page->flags);
+}
+
+void flush_dcache_icache_page(struct page *page)
+{
+#ifdef CONFIG_BOOKE
+ __flush_dcache_icache(kmap(page));
+ kunmap(page);
+#else
+ __flush_dcache_icache_phys(page_to_pfn(page) << PAGE_SHIFT);
+#endif
+
+}
+void clear_user_page(void *page, unsigned long vaddr, struct page *pg)
+{
+ clear_page(page);
+ clear_bit(PG_arch_1, &pg->flags);
+}
+
+void copy_user_page(void *vto, void *vfrom, unsigned long vaddr,
+ struct page *pg)
+{
+ copy_page(vto, vfrom);
+ clear_bit(PG_arch_1, &pg->flags);
+}
+
+void flush_icache_user_range(struct vm_area_struct *vma, struct page *page,
+ unsigned long addr, int len)
+{
+ unsigned long maddr;
+
+ maddr = (unsigned long) kmap(page) + (addr & ~PAGE_MASK);
+ flush_icache_range(maddr, maddr + len);
+ kunmap(page);
+}
+
+/*
+ * This is called at the end of handling a user page fault, when the
+ * fault has been handled by updating a PTE in the linux page tables.
+ * We use it to preload an HPTE into the hash table corresponding to
+ * the updated linux PTE.
+ */
+void update_mmu_cache(struct vm_area_struct *vma, unsigned long address,
+ pte_t pte)
+{
+ /* handle i-cache coherency */
+ unsigned long pfn = pte_pfn(pte);
+
+ if (pfn_valid(pfn)) {
+ struct page *page = pfn_to_page(pfn);
+ if (!PageReserved(page)
+ && !test_bit(PG_arch_1, &page->flags)) {
+ if (vma->vm_mm == current->active_mm)
+ __flush_dcache_icache((void *) address);
+ else
+ flush_dcache_icache_page(page);
+ set_bit(PG_arch_1, &page->flags);
+ }
+ }
+
+#ifdef CONFIG_PPC_STD_MMU
+ /* We only want HPTEs for linux PTEs that have _PAGE_ACCESSED set */
+ if (Hash != 0 && pte_young(pte)) {
+ struct mm_struct *mm;
+ pmd_t *pmd;
+
+ mm = (address < TASK_SIZE)? vma->vm_mm: &init_mm;
+ pmd = pmd_offset(pgd_offset(mm, address), address);
+ if (!pmd_none(*pmd))
+ add_hash_page(mm->context, address, pmd_val(*pmd));
+ }
+#endif
+}
+
+/*
+ * This is called by /dev/mem to know if a given address has to
+ * be mapped non-cacheable or not
+ */
+int page_is_ram(unsigned long pfn)
+{
+ unsigned long paddr = (pfn << PAGE_SHIFT);
+
+ return paddr < __pa(high_memory);
+}
+
+pgprot_t phys_mem_access_prot(struct file *file, unsigned long addr,
+ unsigned long size, pgprot_t vma_prot)
+{
+ if (ppc_md.phys_mem_access_prot)
+ return ppc_md.phys_mem_access_prot(file, addr, size, vma_prot);
+
+ if (!page_is_ram(addr >> PAGE_SHIFT))
+ vma_prot = __pgprot(pgprot_val(vma_prot)
+ | _PAGE_GUARDED | _PAGE_NO_CACHE);
+ return vma_prot;
+}
+EXPORT_SYMBOL(phys_mem_access_prot);
diff --git a/arch/ppc/mm/mem_pieces.c b/arch/ppc/mm/mem_pieces.c
new file mode 100644
index 0000000..3d63905
--- /dev/null
+++ b/arch/ppc/mm/mem_pieces.c
@@ -0,0 +1,163 @@
+/*
+ * Copyright (c) 1996 Paul Mackerras <paulus@cs.anu.edu.au>
+ * Changes to accommodate Power Macintoshes.
+ * Cort Dougan <cort@cs.nmt.edu>
+ * Rewrites.
+ * Grant Erickson <grant@lcse.umn.edu>
+ * General rework and split from mm/init.c.
+ *
+ * Module name: mem_pieces.c
+ *
+ * Description:
+ * Routines and data structures for manipulating and representing
+ * phyiscal memory extents (i.e. address/length pairs).
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/stddef.h>
+#include <linux/init.h>
+#include <asm/page.h>
+
+#include "mem_pieces.h"
+
+extern struct mem_pieces phys_avail;
+
+static void mem_pieces_print(struct mem_pieces *);
+
+/*
+ * Scan a region for a piece of a given size with the required alignment.
+ */
+void __init *
+mem_pieces_find(unsigned int size, unsigned int align)
+{
+ int i;
+ unsigned a, e;
+ struct mem_pieces *mp = &phys_avail;
+
+ for (i = 0; i < mp->n_regions; ++i) {
+ a = mp->regions[i].address;
+ e = a + mp->regions[i].size;
+ a = (a + align - 1) & -align;
+ if (a + size <= e) {
+ mem_pieces_remove(mp, a, size, 1);
+ return (void *) __va(a);
+ }
+ }
+ panic("Couldn't find %u bytes at %u alignment\n", size, align);
+
+ return NULL;
+}
+
+/*
+ * Remove some memory from an array of pieces
+ */
+void __init
+mem_pieces_remove(struct mem_pieces *mp, unsigned int start, unsigned int size,
+ int must_exist)
+{
+ int i, j;
+ unsigned int end, rs, re;
+ struct reg_property *rp;
+
+ end = start + size;
+ for (i = 0, rp = mp->regions; i < mp->n_regions; ++i, ++rp) {
+ if (end > rp->address && start < rp->address + rp->size)
+ break;
+ }
+ if (i >= mp->n_regions) {
+ if (must_exist)
+ printk("mem_pieces_remove: [%x,%x) not in any region\n",
+ start, end);
+ return;
+ }
+ for (; i < mp->n_regions && end > rp->address; ++i, ++rp) {
+ rs = rp->address;
+ re = rs + rp->size;
+ if (must_exist && (start < rs || end > re)) {
+ printk("mem_pieces_remove: bad overlap [%x,%x) with",
+ start, end);
+ mem_pieces_print(mp);
+ must_exist = 0;
+ }
+ if (start > rs) {
+ rp->size = start - rs;
+ if (end < re) {
+ /* need to split this entry */
+ if (mp->n_regions >= MEM_PIECES_MAX)
+ panic("eek... mem_pieces overflow");
+ for (j = mp->n_regions; j > i + 1; --j)
+ mp->regions[j] = mp->regions[j-1];
+ ++mp->n_regions;
+ rp[1].address = end;
+ rp[1].size = re - end;
+ }
+ } else {
+ if (end < re) {
+ rp->address = end;
+ rp->size = re - end;
+ } else {
+ /* need to delete this entry */
+ for (j = i; j < mp->n_regions - 1; ++j)
+ mp->regions[j] = mp->regions[j+1];
+ --mp->n_regions;
+ --i;
+ --rp;
+ }
+ }
+ }
+}
+
+static void __init
+mem_pieces_print(struct mem_pieces *mp)
+{
+ int i;
+
+ for (i = 0; i < mp->n_regions; ++i)
+ printk(" [%x, %x)", mp->regions[i].address,
+ mp->regions[i].address + mp->regions[i].size);
+ printk("\n");
+}
+
+void __init
+mem_pieces_sort(struct mem_pieces *mp)
+{
+ unsigned long a, s;
+ int i, j;
+
+ for (i = 1; i < mp->n_regions; ++i) {
+ a = mp->regions[i].address;
+ s = mp->regions[i].size;
+ for (j = i - 1; j >= 0; --j) {
+ if (a >= mp->regions[j].address)
+ break;
+ mp->regions[j+1] = mp->regions[j];
+ }
+ mp->regions[j+1].address = a;
+ mp->regions[j+1].size = s;
+ }
+}
+
+void __init
+mem_pieces_coalesce(struct mem_pieces *mp)
+{
+ unsigned long a, s, ns;
+ int i, j, d;
+
+ d = 0;
+ for (i = 0; i < mp->n_regions; i = j) {
+ a = mp->regions[i].address;
+ s = mp->regions[i].size;
+ for (j = i + 1; j < mp->n_regions
+ && mp->regions[j].address - a <= s; ++j) {
+ ns = mp->regions[j].address + mp->regions[j].size - a;
+ if (ns > s)
+ s = ns;
+ }
+ mp->regions[d].address = a;
+ mp->regions[d].size = s;
+ ++d;
+ }
+ mp->n_regions = d;
+}
diff --git a/arch/ppc/mm/mem_pieces.h b/arch/ppc/mm/mem_pieces.h
new file mode 100644
index 0000000..e2b700d
--- /dev/null
+++ b/arch/ppc/mm/mem_pieces.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 1996 Paul Mackerras <paulus@cs.anu.edu.au>
+ * Changes to accommodate Power Macintoshes.
+ * Cort Dougan <cort@cs.nmt.edu>
+ * Rewrites.
+ * Grant Erickson <grant@lcse.umn.edu>
+ * General rework and split from mm/init.c.
+ *
+ * Module name: mem_pieces.h
+ *
+ * Description:
+ * Routines and data structures for manipulating and representing
+ * phyiscal memory extents (i.e. address/length pairs).
+ *
+ */
+
+#ifndef __MEM_PIECES_H__
+#define __MEM_PIECES_H__
+
+#include <asm/prom.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/* Type Definitions */
+
+#define MEM_PIECES_MAX 32
+
+struct mem_pieces {
+ int n_regions;
+ struct reg_property regions[MEM_PIECES_MAX];
+};
+
+/* Function Prototypes */
+
+extern void *mem_pieces_find(unsigned int size, unsigned int align);
+extern void mem_pieces_remove(struct mem_pieces *mp, unsigned int start,
+ unsigned int size, int must_exist);
+extern void mem_pieces_coalesce(struct mem_pieces *mp);
+extern void mem_pieces_sort(struct mem_pieces *mp);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __MEM_PIECES_H__ */
diff --git a/arch/ppc/mm/mmu_context.c b/arch/ppc/mm/mmu_context.c
new file mode 100644
index 0000000..a8816e0
--- /dev/null
+++ b/arch/ppc/mm/mmu_context.c
@@ -0,0 +1,86 @@
+/*
+ * This file contains the routines for handling the MMU on those
+ * PowerPC implementations where the MMU substantially follows the
+ * architecture specification. This includes the 6xx, 7xx, 7xxx,
+ * 8260, and POWER3 implementations but excludes the 8xx and 4xx.
+ * -- paulus
+ *
+ * Derived from arch/ppc/mm/init.c:
+ * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
+ *
+ * Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au)
+ * and Cort Dougan (PReP) (cort@cs.nmt.edu)
+ * Copyright (C) 1996 Paul Mackerras
+ * Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk).
+ *
+ * Derived from "arch/i386/mm/init.c"
+ * Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds
+ *
+ * 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.
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/mm.h>
+#include <linux/init.h>
+
+#include <asm/mmu_context.h>
+#include <asm/tlbflush.h>
+
+mm_context_t next_mmu_context;
+unsigned long context_map[LAST_CONTEXT / BITS_PER_LONG + 1];
+#ifdef FEW_CONTEXTS
+atomic_t nr_free_contexts;
+struct mm_struct *context_mm[LAST_CONTEXT+1];
+void steal_context(void);
+#endif /* FEW_CONTEXTS */
+
+/*
+ * Initialize the context management stuff.
+ */
+void __init
+mmu_context_init(void)
+{
+ /*
+ * Some processors have too few contexts to reserve one for
+ * init_mm, and require using context 0 for a normal task.
+ * Other processors reserve the use of context zero for the kernel.
+ * This code assumes FIRST_CONTEXT < 32.
+ */
+ context_map[0] = (1 << FIRST_CONTEXT) - 1;
+ next_mmu_context = FIRST_CONTEXT;
+#ifdef FEW_CONTEXTS
+ atomic_set(&nr_free_contexts, LAST_CONTEXT - FIRST_CONTEXT + 1);
+#endif /* FEW_CONTEXTS */
+}
+
+#ifdef FEW_CONTEXTS
+/*
+ * Steal a context from a task that has one at the moment.
+ * This is only used on 8xx and 4xx and we presently assume that
+ * they don't do SMP. If they do then this will have to check
+ * whether the MM we steal is in use.
+ * We also assume that this is only used on systems that don't
+ * use an MMU hash table - this is true for 8xx and 4xx.
+ * This isn't an LRU system, it just frees up each context in
+ * turn (sort-of pseudo-random replacement :). This would be the
+ * place to implement an LRU scheme if anyone was motivated to do it.
+ * -- paulus
+ */
+void
+steal_context(void)
+{
+ struct mm_struct *mm;
+
+ /* free up context `next_mmu_context' */
+ /* if we shouldn't free context 0, don't... */
+ if (next_mmu_context < FIRST_CONTEXT)
+ next_mmu_context = FIRST_CONTEXT;
+ mm = context_mm[next_mmu_context];
+ flush_tlb_mm(mm);
+ destroy_context(mm);
+}
+#endif /* FEW_CONTEXTS */
diff --git a/arch/ppc/mm/mmu_decl.h b/arch/ppc/mm/mmu_decl.h
new file mode 100644
index 0000000..ffcdb46
--- /dev/null
+++ b/arch/ppc/mm/mmu_decl.h
@@ -0,0 +1,83 @@
+/*
+ * Declarations of procedures and variables shared between files
+ * in arch/ppc/mm/.
+ *
+ * Derived from arch/ppc/mm/init.c:
+ * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
+ *
+ * Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au)
+ * and Cort Dougan (PReP) (cort@cs.nmt.edu)
+ * Copyright (C) 1996 Paul Mackerras
+ * Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk).
+ *
+ * Derived from "arch/i386/mm/init.c"
+ * Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds
+ *
+ * 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.
+ *
+ */
+#include <asm/tlbflush.h>
+#include <asm/mmu.h>
+
+extern void mapin_ram(void);
+extern int map_page(unsigned long va, phys_addr_t pa, int flags);
+extern void setbat(int index, unsigned long virt, unsigned long phys,
+ unsigned int size, int flags);
+extern void reserve_phys_mem(unsigned long start, unsigned long size);
+extern void settlbcam(int index, unsigned long virt, phys_addr_t phys,
+ unsigned int size, int flags, unsigned int pid);
+extern void invalidate_tlbcam_entry(int index);
+
+extern int __map_without_bats;
+extern unsigned long ioremap_base;
+extern unsigned long ioremap_bot;
+extern unsigned int rtas_data, rtas_size;
+
+extern unsigned long total_memory;
+extern unsigned long total_lowmem;
+extern int mem_init_done;
+
+extern PTE *Hash, *Hash_end;
+extern unsigned long Hash_size, Hash_mask;
+
+/* ...and now those things that may be slightly different between processor
+ * architectures. -- Dan
+ */
+#if defined(CONFIG_8xx)
+#define flush_HPTE(X, va, pg) _tlbie(va)
+#define MMU_init_hw() do { } while(0)
+#define mmu_mapin_ram() (0UL)
+
+#elif defined(CONFIG_4xx)
+#define flush_HPTE(X, va, pg) _tlbie(va)
+extern void MMU_init_hw(void);
+extern unsigned long mmu_mapin_ram(void);
+
+#elif defined(CONFIG_FSL_BOOKE)
+#define flush_HPTE(X, va, pg) _tlbie(va)
+extern void MMU_init_hw(void);
+extern unsigned long mmu_mapin_ram(void);
+extern void adjust_total_lowmem(void);
+
+#else
+/* anything except 4xx or 8xx */
+extern void MMU_init_hw(void);
+extern unsigned long mmu_mapin_ram(void);
+
+/* Be careful....this needs to be updated if we ever encounter 603 SMPs,
+ * which includes all new 82xx processors. We need tlbie/tlbsync here
+ * in that case (I think). -- Dan.
+ */
+static inline void flush_HPTE(unsigned context, unsigned long va,
+ unsigned long pdval)
+{
+ if ((Hash != 0) &&
+ cpu_has_feature(CPU_FTR_HPTE_TABLE))
+ flush_hash_pages(0, va, pdval, 1);
+ else
+ _tlbie(va);
+}
+#endif
diff --git a/arch/ppc/mm/pgtable.c b/arch/ppc/mm/pgtable.c
new file mode 100644
index 0000000..0a5cd20
--- /dev/null
+++ b/arch/ppc/mm/pgtable.c
@@ -0,0 +1,471 @@
+/*
+ * This file contains the routines setting up the linux page tables.
+ * -- paulus
+ *
+ * Derived from arch/ppc/mm/init.c:
+ * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
+ *
+ * Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au)
+ * and Cort Dougan (PReP) (cort@cs.nmt.edu)
+ * Copyright (C) 1996 Paul Mackerras
+ * Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk).
+ *
+ * Derived from "arch/i386/mm/init.c"
+ * Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds
+ *
+ * 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.
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/mm.h>
+#include <linux/vmalloc.h>
+#include <linux/init.h>
+#include <linux/highmem.h>
+
+#include <asm/pgtable.h>
+#include <asm/pgalloc.h>
+#include <asm/io.h>
+
+#include "mmu_decl.h"
+
+unsigned long ioremap_base;
+unsigned long ioremap_bot;
+int io_bat_index;
+
+#if defined(CONFIG_6xx) || defined(CONFIG_POWER3)
+#define HAVE_BATS 1
+#endif
+
+#if defined(CONFIG_FSL_BOOKE)
+#define HAVE_TLBCAM 1
+#endif
+
+extern char etext[], _stext[];
+
+#ifdef CONFIG_SMP
+extern void hash_page_sync(void);
+#endif
+
+#ifdef HAVE_BATS
+extern unsigned long v_mapped_by_bats(unsigned long va);
+extern unsigned long p_mapped_by_bats(unsigned long pa);
+void setbat(int index, unsigned long virt, unsigned long phys,
+ unsigned int size, int flags);
+
+#else /* !HAVE_BATS */
+#define v_mapped_by_bats(x) (0UL)
+#define p_mapped_by_bats(x) (0UL)
+#endif /* HAVE_BATS */
+
+#ifdef HAVE_TLBCAM
+extern unsigned int tlbcam_index;
+extern unsigned int num_tlbcam_entries;
+extern unsigned long v_mapped_by_tlbcam(unsigned long va);
+extern unsigned long p_mapped_by_tlbcam(unsigned long pa);
+#else /* !HAVE_TLBCAM */
+#define v_mapped_by_tlbcam(x) (0UL)
+#define p_mapped_by_tlbcam(x) (0UL)
+#endif /* HAVE_TLBCAM */
+
+#ifdef CONFIG_44x
+/* 44x uses an 8kB pgdir because it has 8-byte Linux PTEs. */
+#define PGDIR_ORDER 1
+#else
+#define PGDIR_ORDER 0
+#endif
+
+pgd_t *pgd_alloc(struct mm_struct *mm)
+{
+ pgd_t *ret;
+
+ ret = (pgd_t *)__get_free_pages(GFP_KERNEL|__GFP_ZERO, PGDIR_ORDER);
+ return ret;
+}
+
+void pgd_free(pgd_t *pgd)
+{
+ free_pages((unsigned long)pgd, PGDIR_ORDER);
+}
+
+pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address)
+{
+ pte_t *pte;
+ extern int mem_init_done;
+ extern void *early_get_page(void);
+
+ if (mem_init_done) {
+ pte = (pte_t *)__get_free_page(GFP_KERNEL|__GFP_REPEAT|__GFP_ZERO);
+ } else {
+ pte = (pte_t *)early_get_page();
+ if (pte)
+ clear_page(pte);
+ }
+ return pte;
+}
+
+struct page *pte_alloc_one(struct mm_struct *mm, unsigned long address)
+{
+ struct page *ptepage;
+
+#ifdef CONFIG_HIGHPTE
+ int flags = GFP_KERNEL | __GFP_HIGHMEM | __GFP_REPEAT;
+#else
+ int flags = GFP_KERNEL | __GFP_REPEAT;
+#endif
+
+ ptepage = alloc_pages(flags, 0);
+ if (ptepage)
+ clear_highpage(ptepage);
+ return ptepage;
+}
+
+void pte_free_kernel(pte_t *pte)
+{
+#ifdef CONFIG_SMP
+ hash_page_sync();
+#endif
+ free_page((unsigned long)pte);
+}
+
+void pte_free(struct page *ptepage)
+{
+#ifdef CONFIG_SMP
+ hash_page_sync();
+#endif
+ __free_page(ptepage);
+}
+
+#ifndef CONFIG_44x
+void __iomem *
+ioremap(phys_addr_t addr, unsigned long size)
+{
+ return __ioremap(addr, size, _PAGE_NO_CACHE);
+}
+#else /* CONFIG_44x */
+void __iomem *
+ioremap64(unsigned long long addr, unsigned long size)
+{
+ return __ioremap(addr, size, _PAGE_NO_CACHE);
+}
+
+void __iomem *
+ioremap(phys_addr_t addr, unsigned long size)
+{
+ phys_addr_t addr64 = fixup_bigphys_addr(addr, size);
+
+ return ioremap64(addr64, size);
+}
+#endif /* CONFIG_44x */
+
+void __iomem *
+__ioremap(phys_addr_t addr, unsigned long size, unsigned long flags)
+{
+ unsigned long v, i;
+ phys_addr_t p;
+ int err;
+
+ /*
+ * Choose an address to map it to.
+ * Once the vmalloc system is running, we use it.
+ * Before then, we use space going down from ioremap_base
+ * (ioremap_bot records where we're up to).
+ */
+ p = addr & PAGE_MASK;
+ size = PAGE_ALIGN(addr + size) - p;
+
+ /*
+ * If the address lies within the first 16 MB, assume it's in ISA
+ * memory space
+ */
+ if (p < 16*1024*1024)
+ p += _ISA_MEM_BASE;
+
+ /*
+ * Don't allow anybody to remap normal RAM that we're using.
+ * mem_init() sets high_memory so only do the check after that.
+ */
+ if ( mem_init_done && (p < virt_to_phys(high_memory)) )
+ {
+ printk("__ioremap(): phys addr "PTE_FMT" is RAM lr %p\n", p,
+ __builtin_return_address(0));
+ return NULL;
+ }
+
+ if (size == 0)
+ return NULL;
+
+ /*
+ * Is it already mapped? Perhaps overlapped by a previous
+ * BAT mapping. If the whole area is mapped then we're done,
+ * otherwise remap it since we want to keep the virt addrs for
+ * each request contiguous.
+ *
+ * We make the assumption here that if the bottom and top
+ * of the range we want are mapped then it's mapped to the
+ * same virt address (and this is contiguous).
+ * -- Cort
+ */
+ if ((v = p_mapped_by_bats(p)) /*&& p_mapped_by_bats(p+size-1)*/ )
+ goto out;
+
+ if ((v = p_mapped_by_tlbcam(p)))
+ goto out;
+
+ if (mem_init_done) {
+ struct vm_struct *area;
+ area = get_vm_area(size, VM_IOREMAP);
+ if (area == 0)
+ return NULL;
+ v = (unsigned long) area->addr;
+ } else {
+ v = (ioremap_bot -= size);
+ }
+
+ if ((flags & _PAGE_PRESENT) == 0)
+ flags |= _PAGE_KERNEL;
+ if (flags & _PAGE_NO_CACHE)
+ flags |= _PAGE_GUARDED;
+
+ /*
+ * Should check if it is a candidate for a BAT mapping
+ */
+
+ err = 0;
+ for (i = 0; i < size && err == 0; i += PAGE_SIZE)
+ err = map_page(v+i, p+i, flags);
+ if (err) {
+ if (mem_init_done)
+ vunmap((void *)v);
+ return NULL;
+ }
+
+out:
+ return (void __iomem *) (v + ((unsigned long)addr & ~PAGE_MASK));
+}
+
+void iounmap(volatile void __iomem *addr)
+{
+ /*
+ * If mapped by BATs then there is nothing to do.
+ * Calling vfree() generates a benign warning.
+ */
+ if (v_mapped_by_bats((unsigned long)addr)) return;
+
+ if (addr > high_memory && (unsigned long) addr < ioremap_bot)
+ vunmap((void *) (PAGE_MASK & (unsigned long)addr));
+}
+
+void __iomem *ioport_map(unsigned long port, unsigned int len)
+{
+ return (void __iomem *) (port + _IO_BASE);
+}
+
+void ioport_unmap(void __iomem *addr)
+{
+ /* Nothing to do */
+}
+EXPORT_SYMBOL(ioport_map);
+EXPORT_SYMBOL(ioport_unmap);
+
+int
+map_page(unsigned long va, phys_addr_t pa, int flags)
+{
+ pmd_t *pd;
+ pte_t *pg;
+ int err = -ENOMEM;
+
+ spin_lock(&init_mm.page_table_lock);
+ /* Use upper 10 bits of VA to index the first level map */
+ pd = pmd_offset(pgd_offset_k(va), va);
+ /* Use middle 10 bits of VA to index the second-level map */
+ pg = pte_alloc_kernel(&init_mm, pd, va);
+ if (pg != 0) {
+ err = 0;
+ set_pte_at(&init_mm, va, pg, pfn_pte(pa >> PAGE_SHIFT, __pgprot(flags)));
+ if (mem_init_done)
+ flush_HPTE(0, va, pmd_val(*pd));
+ }
+ spin_unlock(&init_mm.page_table_lock);
+ return err;
+}
+
+/*
+ * Map in all of physical memory starting at KERNELBASE.
+ */
+void __init mapin_ram(void)
+{
+ unsigned long v, p, s, f;
+
+ s = mmu_mapin_ram();
+ v = KERNELBASE + s;
+ p = PPC_MEMSTART + s;
+ for (; s < total_lowmem; s += PAGE_SIZE) {
+ if ((char *) v >= _stext && (char *) v < etext)
+ f = _PAGE_RAM_TEXT;
+ else
+ f = _PAGE_RAM;
+ map_page(v, p, f);
+ v += PAGE_SIZE;
+ p += PAGE_SIZE;
+ }
+}
+
+/* is x a power of 2? */
+#define is_power_of_2(x) ((x) != 0 && (((x) & ((x) - 1)) == 0))
+
+/* is x a power of 4? */
+#define is_power_of_4(x) ((x) != 0 && (((x) & (x-1)) == 0) && (ffs(x) & 1))
+
+/*
+ * Set up a mapping for a block of I/O.
+ * virt, phys, size must all be page-aligned.
+ * This should only be called before ioremap is called.
+ */
+void __init io_block_mapping(unsigned long virt, phys_addr_t phys,
+ unsigned int size, int flags)
+{
+ int i;
+
+ if (virt > KERNELBASE && virt < ioremap_bot)
+ ioremap_bot = ioremap_base = virt;
+
+#ifdef HAVE_BATS
+ /*
+ * Use a BAT for this if possible...
+ */
+ if (io_bat_index < 2 && is_power_of_2(size)
+ && (virt & (size - 1)) == 0 && (phys & (size - 1)) == 0) {
+ setbat(io_bat_index, virt, phys, size, flags);
+ ++io_bat_index;
+ return;
+ }
+#endif /* HAVE_BATS */
+
+#ifdef HAVE_TLBCAM
+ /*
+ * Use a CAM for this if possible...
+ */
+ if (tlbcam_index < num_tlbcam_entries && is_power_of_4(size)
+ && (virt & (size - 1)) == 0 && (phys & (size - 1)) == 0) {
+ settlbcam(tlbcam_index, virt, phys, size, flags, 0);
+ ++tlbcam_index;
+ return;
+ }
+#endif /* HAVE_TLBCAM */
+
+ /* No BATs available, put it in the page tables. */
+ for (i = 0; i < size; i += PAGE_SIZE)
+ map_page(virt + i, phys + i, flags);
+}
+
+/* Scan the real Linux page tables and return a PTE pointer for
+ * a virtual address in a context.
+ * Returns true (1) if PTE was found, zero otherwise. The pointer to
+ * the PTE pointer is unmodified if PTE is not found.
+ */
+int
+get_pteptr(struct mm_struct *mm, unsigned long addr, pte_t **ptep)
+{
+ pgd_t *pgd;
+ pmd_t *pmd;
+ pte_t *pte;
+ int retval = 0;
+
+ pgd = pgd_offset(mm, addr & PAGE_MASK);
+ if (pgd) {
+ pmd = pmd_offset(pgd, addr & PAGE_MASK);
+ if (pmd_present(*pmd)) {
+ pte = pte_offset_map(pmd, addr & PAGE_MASK);
+ if (pte) {
+ retval = 1;
+ *ptep = pte;
+ /* XXX caller needs to do pte_unmap, yuck */
+ }
+ }
+ }
+ return(retval);
+}
+
+/* Find physical address for this virtual address. Normally used by
+ * I/O functions, but anyone can call it.
+ */
+unsigned long iopa(unsigned long addr)
+{
+ unsigned long pa;
+
+ /* I don't know why this won't work on PMacs or CHRP. It
+ * appears there is some bug, or there is some implicit
+ * mapping done not properly represented by BATs or in page
+ * tables.......I am actively working on resolving this, but
+ * can't hold up other stuff. -- Dan
+ */
+ pte_t *pte;
+ struct mm_struct *mm;
+
+ /* Check the BATs */
+ pa = v_mapped_by_bats(addr);
+ if (pa)
+ return pa;
+
+ /* Allow mapping of user addresses (within the thread)
+ * for DMA if necessary.
+ */
+ if (addr < TASK_SIZE)
+ mm = current->mm;
+ else
+ mm = &init_mm;
+
+ pa = 0;
+ if (get_pteptr(mm, addr, &pte)) {
+ pa = (pte_val(*pte) & PAGE_MASK) | (addr & ~PAGE_MASK);
+ pte_unmap(pte);
+ }
+
+ return(pa);
+}
+
+/* This is will find the virtual address for a physical one....
+ * Swiped from APUS, could be dangerous :-).
+ * This is only a placeholder until I really find a way to make this
+ * work. -- Dan
+ */
+unsigned long
+mm_ptov (unsigned long paddr)
+{
+ unsigned long ret;
+#if 0
+ if (paddr < 16*1024*1024)
+ ret = ZTWO_VADDR(paddr);
+ else {
+ int i;
+
+ for (i = 0; i < kmap_chunk_count;){
+ unsigned long phys = kmap_chunks[i++];
+ unsigned long size = kmap_chunks[i++];
+ unsigned long virt = kmap_chunks[i++];
+ if (paddr >= phys
+ && paddr < (phys + size)){
+ ret = virt + paddr - phys;
+ goto exit;
+ }
+ }
+
+ ret = (unsigned long) __va(paddr);
+ }
+exit:
+#ifdef DEBUGPV
+ printk ("PTOV(%lx)=%lx\n", paddr, ret);
+#endif
+#else
+ ret = (unsigned long)paddr + KERNELBASE;
+#endif
+ return ret;
+}
+
diff --git a/arch/ppc/mm/ppc_mmu.c b/arch/ppc/mm/ppc_mmu.c
new file mode 100644
index 0000000..9a381ed5
--- /dev/null
+++ b/arch/ppc/mm/ppc_mmu.c
@@ -0,0 +1,296 @@
+/*
+ * This file contains the routines for handling the MMU on those
+ * PowerPC implementations where the MMU substantially follows the
+ * architecture specification. This includes the 6xx, 7xx, 7xxx,
+ * 8260, and POWER3 implementations but excludes the 8xx and 4xx.
+ * -- paulus
+ *
+ * Derived from arch/ppc/mm/init.c:
+ * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
+ *
+ * Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au)
+ * and Cort Dougan (PReP) (cort@cs.nmt.edu)
+ * Copyright (C) 1996 Paul Mackerras
+ * Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk).
+ *
+ * Derived from "arch/i386/mm/init.c"
+ * Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds
+ *
+ * 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.
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/init.h>
+#include <linux/highmem.h>
+
+#include <asm/prom.h>
+#include <asm/mmu.h>
+#include <asm/machdep.h>
+
+#include "mmu_decl.h"
+#include "mem_pieces.h"
+
+PTE *Hash, *Hash_end;
+unsigned long Hash_size, Hash_mask;
+unsigned long _SDR1;
+
+union ubat { /* BAT register values to be loaded */
+ BAT bat;
+#ifdef CONFIG_PPC64BRIDGE
+ u64 word[2];
+#else
+ u32 word[2];
+#endif
+} BATS[4][2]; /* 4 pairs of IBAT, DBAT */
+
+struct batrange { /* stores address ranges mapped by BATs */
+ unsigned long start;
+ unsigned long limit;
+ unsigned long phys;
+} bat_addrs[4];
+
+/*
+ * Return PA for this VA if it is mapped by a BAT, or 0
+ */
+unsigned long v_mapped_by_bats(unsigned long va)
+{
+ int b;
+ for (b = 0; b < 4; ++b)
+ if (va >= bat_addrs[b].start && va < bat_addrs[b].limit)
+ return bat_addrs[b].phys + (va - bat_addrs[b].start);
+ return 0;
+}
+
+/*
+ * Return VA for a given PA or 0 if not mapped
+ */
+unsigned long p_mapped_by_bats(unsigned long pa)
+{
+ int b;
+ for (b = 0; b < 4; ++b)
+ if (pa >= bat_addrs[b].phys
+ && pa < (bat_addrs[b].limit-bat_addrs[b].start)
+ +bat_addrs[b].phys)
+ return bat_addrs[b].start+(pa-bat_addrs[b].phys);
+ return 0;
+}
+
+unsigned long __init mmu_mapin_ram(void)
+{
+#ifdef CONFIG_POWER4
+ return 0;
+#else
+ unsigned long tot, bl, done;
+ unsigned long max_size = (256<<20);
+ unsigned long align;
+
+ if (__map_without_bats)
+ return 0;
+
+ /* Set up BAT2 and if necessary BAT3 to cover RAM. */
+
+ /* Make sure we don't map a block larger than the
+ smallest alignment of the physical address. */
+ /* alignment of PPC_MEMSTART */
+ align = ~(PPC_MEMSTART-1) & PPC_MEMSTART;
+ /* set BAT block size to MIN(max_size, align) */
+ if (align && align < max_size)
+ max_size = align;
+
+ tot = total_lowmem;
+ for (bl = 128<<10; bl < max_size; bl <<= 1) {
+ if (bl * 2 > tot)
+ break;
+ }
+
+ setbat(2, KERNELBASE, PPC_MEMSTART, bl, _PAGE_RAM);
+ done = (unsigned long)bat_addrs[2].limit - KERNELBASE + 1;
+ if ((done < tot) && !bat_addrs[3].limit) {
+ /* use BAT3 to cover a bit more */
+ tot -= done;
+ for (bl = 128<<10; bl < max_size; bl <<= 1)
+ if (bl * 2 > tot)
+ break;
+ setbat(3, KERNELBASE+done, PPC_MEMSTART+done, bl, _PAGE_RAM);
+ done = (unsigned long)bat_addrs[3].limit - KERNELBASE + 1;
+ }
+
+ return done;
+#endif
+}
+
+/*
+ * Set up one of the I/D BAT (block address translation) register pairs.
+ * The parameters are not checked; in particular size must be a power
+ * of 2 between 128k and 256M.
+ */
+void __init setbat(int index, unsigned long virt, unsigned long phys,
+ unsigned int size, int flags)
+{
+ unsigned int bl;
+ int wimgxpp;
+ union ubat *bat = BATS[index];
+
+ if (((flags & _PAGE_NO_CACHE) == 0) &&
+ cpu_has_feature(CPU_FTR_NEED_COHERENT))
+ flags |= _PAGE_COHERENT;
+
+ bl = (size >> 17) - 1;
+ if (PVR_VER(mfspr(SPRN_PVR)) != 1) {
+ /* 603, 604, etc. */
+ /* Do DBAT first */
+ wimgxpp = flags & (_PAGE_WRITETHRU | _PAGE_NO_CACHE
+ | _PAGE_COHERENT | _PAGE_GUARDED);
+ wimgxpp |= (flags & _PAGE_RW)? BPP_RW: BPP_RX;
+ bat[1].word[0] = virt | (bl << 2) | 2; /* Vs=1, Vp=0 */
+ bat[1].word[1] = phys | wimgxpp;
+#ifndef CONFIG_KGDB /* want user access for breakpoints */
+ if (flags & _PAGE_USER)
+#endif
+ bat[1].bat.batu.vp = 1;
+ if (flags & _PAGE_GUARDED) {
+ /* G bit must be zero in IBATs */
+ bat[0].word[0] = bat[0].word[1] = 0;
+ } else {
+ /* make IBAT same as DBAT */
+ bat[0] = bat[1];
+ }
+ } else {
+ /* 601 cpu */
+ if (bl > BL_8M)
+ bl = BL_8M;
+ wimgxpp = flags & (_PAGE_WRITETHRU | _PAGE_NO_CACHE
+ | _PAGE_COHERENT);
+ wimgxpp |= (flags & _PAGE_RW)?
+ ((flags & _PAGE_USER)? PP_RWRW: PP_RWXX): PP_RXRX;
+ bat->word[0] = virt | wimgxpp | 4; /* Ks=0, Ku=1 */
+ bat->word[1] = phys | bl | 0x40; /* V=1 */
+ }
+
+ bat_addrs[index].start = virt;
+ bat_addrs[index].limit = virt + ((bl + 1) << 17) - 1;
+ bat_addrs[index].phys = phys;
+}
+
+/*
+ * Initialize the hash table and patch the instructions in hashtable.S.
+ */
+void __init MMU_init_hw(void)
+{
+ unsigned int hmask, mb, mb2;
+ unsigned int n_hpteg, lg_n_hpteg;
+
+ extern unsigned int hash_page_patch_A[];
+ extern unsigned int hash_page_patch_B[], hash_page_patch_C[];
+ extern unsigned int hash_page[];
+ extern unsigned int flush_hash_patch_A[], flush_hash_patch_B[];
+
+ if (!cpu_has_feature(CPU_FTR_HPTE_TABLE)) {
+ /*
+ * Put a blr (procedure return) instruction at the
+ * start of hash_page, since we can still get DSI
+ * exceptions on a 603.
+ */
+ hash_page[0] = 0x4e800020;
+ flush_icache_range((unsigned long) &hash_page[0],
+ (unsigned long) &hash_page[1]);
+ return;
+ }
+
+ if ( ppc_md.progress ) ppc_md.progress("hash:enter", 0x105);
+
+#ifdef CONFIG_PPC64BRIDGE
+#define LG_HPTEG_SIZE 7 /* 128 bytes per HPTEG */
+#define SDR1_LOW_BITS (lg_n_hpteg - 11)
+#define MIN_N_HPTEG 2048 /* min 256kB hash table */
+#else
+#define LG_HPTEG_SIZE 6 /* 64 bytes per HPTEG */
+#define SDR1_LOW_BITS ((n_hpteg - 1) >> 10)
+#define MIN_N_HPTEG 1024 /* min 64kB hash table */
+#endif
+
+#ifdef CONFIG_POWER4
+ /* The hash table has already been allocated and initialized
+ in prom.c */
+ n_hpteg = Hash_size >> LG_HPTEG_SIZE;
+ lg_n_hpteg = __ilog2(n_hpteg);
+
+ /* Remove the hash table from the available memory */
+ if (Hash)
+ reserve_phys_mem(__pa(Hash), Hash_size);
+
+#else /* CONFIG_POWER4 */
+ /*
+ * Allow 1 HPTE (1/8 HPTEG) for each page of memory.
+ * This is less than the recommended amount, but then
+ * Linux ain't AIX.
+ */
+ n_hpteg = total_memory / (PAGE_SIZE * 8);
+ if (n_hpteg < MIN_N_HPTEG)
+ n_hpteg = MIN_N_HPTEG;
+ lg_n_hpteg = __ilog2(n_hpteg);
+ if (n_hpteg & (n_hpteg - 1)) {
+ ++lg_n_hpteg; /* round up if not power of 2 */
+ n_hpteg = 1 << lg_n_hpteg;
+ }
+ Hash_size = n_hpteg << LG_HPTEG_SIZE;
+
+ /*
+ * Find some memory for the hash table.
+ */
+ if ( ppc_md.progress ) ppc_md.progress("hash:find piece", 0x322);
+ Hash = mem_pieces_find(Hash_size, Hash_size);
+ cacheable_memzero(Hash, Hash_size);
+ _SDR1 = __pa(Hash) | SDR1_LOW_BITS;
+#endif /* CONFIG_POWER4 */
+
+ Hash_end = (PTE *) ((unsigned long)Hash + Hash_size);
+
+ printk("Total memory = %ldMB; using %ldkB for hash table (at %p)\n",
+ total_memory >> 20, Hash_size >> 10, Hash);
+
+
+ /*
+ * Patch up the instructions in hashtable.S:create_hpte
+ */
+ if ( ppc_md.progress ) ppc_md.progress("hash:patch", 0x345);
+ Hash_mask = n_hpteg - 1;
+ hmask = Hash_mask >> (16 - LG_HPTEG_SIZE);
+ mb2 = mb = 32 - LG_HPTEG_SIZE - lg_n_hpteg;
+ if (lg_n_hpteg > 16)
+ mb2 = 16 - LG_HPTEG_SIZE;
+
+ hash_page_patch_A[0] = (hash_page_patch_A[0] & ~0xffff)
+ | ((unsigned int)(Hash) >> 16);
+ hash_page_patch_A[1] = (hash_page_patch_A[1] & ~0x7c0) | (mb << 6);
+ hash_page_patch_A[2] = (hash_page_patch_A[2] & ~0x7c0) | (mb2 << 6);
+ hash_page_patch_B[0] = (hash_page_patch_B[0] & ~0xffff) | hmask;
+ hash_page_patch_C[0] = (hash_page_patch_C[0] & ~0xffff) | hmask;
+
+ /*
+ * Ensure that the locations we've patched have been written
+ * out from the data cache and invalidated in the instruction
+ * cache, on those machines with split caches.
+ */
+ flush_icache_range((unsigned long) &hash_page_patch_A[0],
+ (unsigned long) &hash_page_patch_C[1]);
+
+ /*
+ * Patch up the instructions in hashtable.S:flush_hash_page
+ */
+ flush_hash_patch_A[0] = (flush_hash_patch_A[0] & ~0xffff)
+ | ((unsigned int)(Hash) >> 16);
+ flush_hash_patch_A[1] = (flush_hash_patch_A[1] & ~0x7c0) | (mb << 6);
+ flush_hash_patch_A[2] = (flush_hash_patch_A[2] & ~0x7c0) | (mb2 << 6);
+ flush_hash_patch_B[0] = (flush_hash_patch_B[0] & ~0xffff) | hmask;
+ flush_icache_range((unsigned long) &flush_hash_patch_A[0],
+ (unsigned long) &flush_hash_patch_B[1]);
+
+ if ( ppc_md.progress ) ppc_md.progress("hash:done", 0x205);
+}
diff --git a/arch/ppc/mm/tlb.c b/arch/ppc/mm/tlb.c
new file mode 100644
index 0000000..6c3dc3c
--- /dev/null
+++ b/arch/ppc/mm/tlb.c
@@ -0,0 +1,183 @@
+/*
+ * This file contains the routines for TLB flushing.
+ * On machines where the MMU uses a hash table to store virtual to
+ * physical translations, these routines flush entries from the
+ * hash table also.
+ * -- paulus
+ *
+ * Derived from arch/ppc/mm/init.c:
+ * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
+ *
+ * Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au)
+ * and Cort Dougan (PReP) (cort@cs.nmt.edu)
+ * Copyright (C) 1996 Paul Mackerras
+ * Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk).
+ *
+ * Derived from "arch/i386/mm/init.c"
+ * Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds
+ *
+ * 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.
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/init.h>
+#include <linux/highmem.h>
+#include <asm/tlbflush.h>
+#include <asm/tlb.h>
+
+#include "mmu_decl.h"
+
+/*
+ * Called when unmapping pages to flush entries from the TLB/hash table.
+ */
+void flush_hash_entry(struct mm_struct *mm, pte_t *ptep, unsigned long addr)
+{
+ unsigned long ptephys;
+
+ if (Hash != 0) {
+ ptephys = __pa(ptep) & PAGE_MASK;
+ flush_hash_pages(mm->context, addr, ptephys, 1);
+ }
+}
+
+/*
+ * Called by ptep_set_access_flags, must flush on CPUs for which the
+ * DSI handler can't just "fixup" the TLB on a write fault
+ */
+void flush_tlb_page_nohash(struct vm_area_struct *vma, unsigned long addr)
+{
+ if (Hash != 0)
+ return;
+ _tlbie(addr);
+}
+
+/*
+ * Called at the end of a mmu_gather operation to make sure the
+ * TLB flush is completely done.
+ */
+void tlb_flush(struct mmu_gather *tlb)
+{
+ if (Hash == 0) {
+ /*
+ * 603 needs to flush the whole TLB here since
+ * it doesn't use a hash table.
+ */
+ _tlbia();
+ }
+}
+
+/*
+ * TLB flushing:
+ *
+ * - flush_tlb_mm(mm) flushes the specified mm context TLB's
+ * - flush_tlb_page(vma, vmaddr) flushes one page
+ * - flush_tlb_range(vma, start, end) flushes a range of pages
+ * - flush_tlb_kernel_range(start, end) flushes kernel pages
+ *
+ * since the hardware hash table functions as an extension of the
+ * tlb as far as the linux tables are concerned, flush it too.
+ * -- Cort
+ */
+
+/*
+ * 750 SMP is a Bad Idea because the 750 doesn't broadcast all
+ * the cache operations on the bus. Hence we need to use an IPI
+ * to get the other CPU(s) to invalidate their TLBs.
+ */
+#ifdef CONFIG_SMP_750
+#define FINISH_FLUSH smp_send_tlb_invalidate(0)
+#else
+#define FINISH_FLUSH do { } while (0)
+#endif
+
+static void flush_range(struct mm_struct *mm, unsigned long start,
+ unsigned long end)
+{
+ pmd_t *pmd;
+ unsigned long pmd_end;
+ int count;
+ unsigned int ctx = mm->context;
+
+ if (Hash == 0) {
+ _tlbia();
+ return;
+ }
+ start &= PAGE_MASK;
+ if (start >= end)
+ return;
+ end = (end - 1) | ~PAGE_MASK;
+ pmd = pmd_offset(pgd_offset(mm, start), start);
+ for (;;) {
+ pmd_end = ((start + PGDIR_SIZE) & PGDIR_MASK) - 1;
+ if (pmd_end > end)
+ pmd_end = end;
+ if (!pmd_none(*pmd)) {
+ count = ((pmd_end - start) >> PAGE_SHIFT) + 1;
+ flush_hash_pages(ctx, start, pmd_val(*pmd), count);
+ }
+ if (pmd_end == end)
+ break;
+ start = pmd_end + 1;
+ ++pmd;
+ }
+}
+
+/*
+ * Flush kernel TLB entries in the given range
+ */
+void flush_tlb_kernel_range(unsigned long start, unsigned long end)
+{
+ flush_range(&init_mm, start, end);
+ FINISH_FLUSH;
+}
+
+/*
+ * Flush all the (user) entries for the address space described by mm.
+ */
+void flush_tlb_mm(struct mm_struct *mm)
+{
+ struct vm_area_struct *mp;
+
+ if (Hash == 0) {
+ _tlbia();
+ return;
+ }
+
+ for (mp = mm->mmap; mp != NULL; mp = mp->vm_next)
+ flush_range(mp->vm_mm, mp->vm_start, mp->vm_end);
+ FINISH_FLUSH;
+}
+
+void flush_tlb_page(struct vm_area_struct *vma, unsigned long vmaddr)
+{
+ struct mm_struct *mm;
+ pmd_t *pmd;
+
+ if (Hash == 0) {
+ _tlbie(vmaddr);
+ return;
+ }
+ mm = (vmaddr < TASK_SIZE)? vma->vm_mm: &init_mm;
+ pmd = pmd_offset(pgd_offset(mm, vmaddr), vmaddr);
+ if (!pmd_none(*pmd))
+ flush_hash_pages(mm->context, vmaddr, pmd_val(*pmd), 1);
+ FINISH_FLUSH;
+}
+
+/*
+ * For each address in the range, find the pte for the address
+ * and check _PAGE_HASHPTE bit; if it is set, find and destroy
+ * the corresponding HPTE.
+ */
+void flush_tlb_range(struct vm_area_struct *vma, unsigned long start,
+ unsigned long end)
+{
+ flush_range(vma->vm_mm, start, end);
+ FINISH_FLUSH;
+}
diff --git a/arch/ppc/oprofile/Kconfig b/arch/ppc/oprofile/Kconfig
new file mode 100644
index 0000000..19d3773
--- /dev/null
+++ b/arch/ppc/oprofile/Kconfig
@@ -0,0 +1,23 @@
+
+menu "Profiling support"
+ depends on EXPERIMENTAL
+
+config PROFILING
+ bool "Profiling support (EXPERIMENTAL)"
+ help
+ Say Y here to enable the extended profiling support mechanisms used
+ by profilers such as OProfile.
+
+
+config OPROFILE
+ tristate "OProfile system profiling (EXPERIMENTAL)"
+ depends on PROFILING
+ help
+ OProfile is a profiling system capable of profiling the
+ whole system, include the kernel, kernel modules, libraries,
+ and applications.
+
+ If unsure, say N.
+
+endmenu
+
diff --git a/arch/ppc/oprofile/Makefile b/arch/ppc/oprofile/Makefile
new file mode 100644
index 0000000..e2218d3
--- /dev/null
+++ b/arch/ppc/oprofile/Makefile
@@ -0,0 +1,14 @@
+obj-$(CONFIG_OPROFILE) += oprofile.o
+
+DRIVER_OBJS := $(addprefix ../../../drivers/oprofile/, \
+ oprof.o cpu_buffer.o buffer_sync.o \
+ event_buffer.o oprofile_files.o \
+ oprofilefs.o oprofile_stats.o \
+ timer_int.o )
+
+oprofile-y := $(DRIVER_OBJS) common.o
+
+ifeq ($(CONFIG_FSL_BOOKE),y)
+ oprofile-y += op_model_fsl_booke.o
+endif
+
diff --git a/arch/ppc/oprofile/common.c b/arch/ppc/oprofile/common.c
new file mode 100644
index 0000000..3169c67
--- /dev/null
+++ b/arch/ppc/oprofile/common.c
@@ -0,0 +1,161 @@
+/*
+ * PPC 32 oprofile support
+ * Based on PPC64 oprofile support
+ * Copyright (C) 2004 Anton Blanchard <anton@au.ibm.com>, IBM
+ *
+ * Copyright (C) Freescale Semiconductor, Inc 2004
+ *
+ * Author: Andy Fleming
+ *
+ * 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.
+ */
+
+#include <linux/oprofile.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <linux/smp.h>
+#include <linux/errno.h>
+#include <asm/ptrace.h>
+#include <asm/system.h>
+#include <asm/perfmon.h>
+#include <asm/cputable.h>
+
+#include "op_impl.h"
+
+static struct op_ppc32_model *model;
+
+static struct op_counter_config ctr[OP_MAX_COUNTER];
+static struct op_system_config sys;
+
+static void op_handle_interrupt(struct pt_regs *regs)
+{
+ model->handle_interrupt(regs, ctr);
+}
+
+static int op_ppc32_setup(void)
+{
+ /* Install our interrupt handler into the existing hook. */
+ if(request_perfmon_irq(&op_handle_interrupt))
+ return -EBUSY;
+
+ mb();
+
+ /* Pre-compute the values to stuff in the hardware registers. */
+ model->reg_setup(ctr, &sys, model->num_counters);
+
+#if 0
+ /* FIXME: Make multi-cpu work */
+ /* Configure the registers on all cpus. */
+ on_each_cpu(model->reg_setup, NULL, 0, 1);
+#endif
+
+ return 0;
+}
+
+static void op_ppc32_shutdown(void)
+{
+ mb();
+
+ /* Remove our interrupt handler. We may be removing this module. */
+ free_perfmon_irq();
+}
+
+static void op_ppc32_cpu_start(void *dummy)
+{
+ model->start(ctr);
+}
+
+static int op_ppc32_start(void)
+{
+ on_each_cpu(op_ppc32_cpu_start, NULL, 0, 1);
+ return 0;
+}
+
+static inline void op_ppc32_cpu_stop(void *dummy)
+{
+ model->stop();
+}
+
+static void op_ppc32_stop(void)
+{
+ on_each_cpu(op_ppc32_cpu_stop, NULL, 0, 1);
+}
+
+static int op_ppc32_create_files(struct super_block *sb, struct dentry *root)
+{
+ int i;
+
+ for (i = 0; i < model->num_counters; ++i) {
+ struct dentry *dir;
+ char buf[3];
+
+ snprintf(buf, sizeof buf, "%d", i);
+ dir = oprofilefs_mkdir(sb, root, buf);
+
+ oprofilefs_create_ulong(sb, dir, "enabled", &ctr[i].enabled);
+ oprofilefs_create_ulong(sb, dir, "event", &ctr[i].event);
+ oprofilefs_create_ulong(sb, dir, "count", &ctr[i].count);
+ oprofilefs_create_ulong(sb, dir, "kernel", &ctr[i].kernel);
+ oprofilefs_create_ulong(sb, dir, "user", &ctr[i].user);
+
+ /* FIXME: Not sure if this is used */
+ oprofilefs_create_ulong(sb, dir, "unit_mask", &ctr[i].unit_mask);
+ }
+
+ oprofilefs_create_ulong(sb, root, "enable_kernel", &sys.enable_kernel);
+ oprofilefs_create_ulong(sb, root, "enable_user", &sys.enable_user);
+
+ /* Default to tracing both kernel and user */
+ sys.enable_kernel = 1;
+ sys.enable_user = 1;
+
+ return 0;
+}
+
+static struct oprofile_operations oprof_ppc32_ops = {
+ .create_files = op_ppc32_create_files,
+ .setup = op_ppc32_setup,
+ .shutdown = op_ppc32_shutdown,
+ .start = op_ppc32_start,
+ .stop = op_ppc32_stop,
+ .cpu_type = NULL /* To be filled in below. */
+};
+
+int __init oprofile_arch_init(struct oprofile_operations *ops)
+{
+ char *name;
+ int cpu_id = smp_processor_id();
+
+#ifdef CONFIG_FSL_BOOKE
+ model = &op_model_fsl_booke;
+#else
+ return -ENODEV;
+#endif
+
+ name = kmalloc(32, GFP_KERNEL);
+
+ if (NULL == name)
+ return -ENOMEM;
+
+ sprintf(name, "ppc/%s", cur_cpu_spec[cpu_id]->cpu_name);
+
+ oprof_ppc32_ops.cpu_type = name;
+
+ model->num_counters = cur_cpu_spec[cpu_id]->num_pmcs;
+
+ *ops = oprof_ppc32_ops;
+
+ printk(KERN_INFO "oprofile: using %s performance monitoring.\n",
+ oprof_ppc32_ops.cpu_type);
+
+ return 0;
+}
+
+void oprofile_arch_exit(void)
+{
+ kfree(oprof_ppc32_ops.cpu_type);
+ oprof_ppc32_ops.cpu_type = NULL;
+}
diff --git a/arch/ppc/oprofile/op_impl.h b/arch/ppc/oprofile/op_impl.h
new file mode 100644
index 0000000..bc336dc
--- /dev/null
+++ b/arch/ppc/oprofile/op_impl.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2004 Anton Blanchard <anton@au.ibm.com>, IBM
+ *
+ * Based on alpha version.
+ *
+ * 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.
+ */
+
+#ifndef OP_IMPL_H
+#define OP_IMPL_H 1
+
+#define OP_MAX_COUNTER 8
+
+/* Per-counter configuration as set via oprofilefs. */
+struct op_counter_config {
+ unsigned long enabled;
+ unsigned long event;
+ unsigned long count;
+ unsigned long kernel;
+ unsigned long user;
+ unsigned long unit_mask;
+};
+
+/* System-wide configuration as set via oprofilefs. */
+struct op_system_config {
+ unsigned long enable_kernel;
+ unsigned long enable_user;
+};
+
+/* Per-arch configuration */
+struct op_ppc32_model {
+ void (*reg_setup) (struct op_counter_config *,
+ struct op_system_config *,
+ int num_counters);
+ void (*start) (struct op_counter_config *);
+ void (*stop) (void);
+ void (*handle_interrupt) (struct pt_regs *,
+ struct op_counter_config *);
+ int num_counters;
+};
+
+#endif /* OP_IMPL_H */
diff --git a/arch/ppc/oprofile/op_model_fsl_booke.c b/arch/ppc/oprofile/op_model_fsl_booke.c
new file mode 100644
index 0000000..fc9c859
--- /dev/null
+++ b/arch/ppc/oprofile/op_model_fsl_booke.c
@@ -0,0 +1,184 @@
+/*
+ * oprofile/op_model_e500.c
+ *
+ * Freescale Book-E oprofile support, based on ppc64 oprofile support
+ * Copyright (C) 2004 Anton Blanchard <anton@au.ibm.com>, IBM
+ *
+ * Copyright (c) 2004 Freescale Semiconductor, Inc
+ *
+ * Author: Andy Fleming
+ * Maintainer: Kumar Gala <Kumar.Gala@freescale.com>
+ *
+ * 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.
+ */
+
+#include <linux/oprofile.h>
+#include <linux/init.h>
+#include <linux/smp.h>
+#include <asm/ptrace.h>
+#include <asm/system.h>
+#include <asm/processor.h>
+#include <asm/cputable.h>
+#include <asm/reg_booke.h>
+#include <asm/page.h>
+#include <asm/perfmon.h>
+
+#include "op_impl.h"
+
+static unsigned long reset_value[OP_MAX_COUNTER];
+
+static int num_counters;
+static int oprofile_running;
+
+static inline unsigned int ctr_read(unsigned int i)
+{
+ switch(i) {
+ case 0:
+ return mfpmr(PMRN_PMC0);
+ case 1:
+ return mfpmr(PMRN_PMC1);
+ case 2:
+ return mfpmr(PMRN_PMC2);
+ case 3:
+ return mfpmr(PMRN_PMC3);
+ default:
+ return 0;
+ }
+}
+
+static inline void ctr_write(unsigned int i, unsigned int val)
+{
+ switch(i) {
+ case 0:
+ mtpmr(PMRN_PMC0, val);
+ break;
+ case 1:
+ mtpmr(PMRN_PMC1, val);
+ break;
+ case 2:
+ mtpmr(PMRN_PMC2, val);
+ break;
+ case 3:
+ mtpmr(PMRN_PMC3, val);
+ break;
+ default:
+ break;
+ }
+}
+
+
+static void fsl_booke_reg_setup(struct op_counter_config *ctr,
+ struct op_system_config *sys,
+ int num_ctrs)
+{
+ int i;
+
+ num_counters = num_ctrs;
+
+ /* freeze all counters */
+ pmc_stop_ctrs();
+
+ /* Our counters count up, and "count" refers to
+ * how much before the next interrupt, and we interrupt
+ * on overflow. So we calculate the starting value
+ * which will give us "count" until overflow.
+ * Then we set the events on the enabled counters */
+ for (i = 0; i < num_counters; ++i) {
+ reset_value[i] = 0x80000000UL - ctr[i].count;
+
+ init_pmc_stop(i);
+
+ set_pmc_event(i, ctr[i].event);
+
+ set_pmc_user_kernel(i, ctr[i].user, ctr[i].kernel);
+ }
+}
+
+static void fsl_booke_start(struct op_counter_config *ctr)
+{
+ int i;
+
+ mtmsr(mfmsr() | MSR_PMM);
+
+ for (i = 0; i < num_counters; ++i) {
+ if (ctr[i].enabled) {
+ ctr_write(i, reset_value[i]);
+ /* Set Each enabled counterd to only
+ * count when the Mark bit is not set */
+ set_pmc_marked(i, 1, 0);
+ pmc_start_ctr(i, 1);
+ } else {
+ ctr_write(i, 0);
+
+ /* Set the ctr to be stopped */
+ pmc_start_ctr(i, 0);
+ }
+ }
+
+ /* Clear the freeze bit, and enable the interrupt.
+ * The counters won't actually start until the rfi clears
+ * the PMM bit */
+ pmc_start_ctrs(1);
+
+ oprofile_running = 1;
+
+ pr_debug("start on cpu %d, pmgc0 %x\n", smp_processor_id(),
+ mfpmr(PMRN_PMGC0));
+}
+
+static void fsl_booke_stop(void)
+{
+ /* freeze counters */
+ pmc_stop_ctrs();
+
+ oprofile_running = 0;
+
+ pr_debug("stop on cpu %d, pmgc0 %x\n", smp_processor_id(),
+ mfpmr(PMRN_PMGC0));
+
+ mb();
+}
+
+
+static void fsl_booke_handle_interrupt(struct pt_regs *regs,
+ struct op_counter_config *ctr)
+{
+ unsigned long pc;
+ int is_kernel;
+ int val;
+ int i;
+
+ /* set the PMM bit (see comment below) */
+ mtmsr(mfmsr() | MSR_PMM);
+
+ pc = regs->nip;
+ is_kernel = (pc >= KERNELBASE);
+
+ for (i = 0; i < num_counters; ++i) {
+ val = ctr_read(i);
+ if (val < 0) {
+ if (oprofile_running && ctr[i].enabled) {
+ oprofile_add_pc(pc, is_kernel, i);
+ ctr_write(i, reset_value[i]);
+ } else {
+ ctr_write(i, 0);
+ }
+ }
+ }
+
+ /* The freeze bit was set by the interrupt. */
+ /* Clear the freeze bit, and reenable the interrupt.
+ * The counters won't actually start until the rfi clears
+ * the PMM bit */
+ pmc_start_ctrs(1);
+}
+
+struct op_ppc32_model op_model_fsl_booke = {
+ .reg_setup = fsl_booke_reg_setup,
+ .start = fsl_booke_start,
+ .stop = fsl_booke_stop,
+ .handle_interrupt = fsl_booke_handle_interrupt,
+};
diff --git a/arch/ppc/platforms/4xx/Kconfig b/arch/ppc/platforms/4xx/Kconfig
new file mode 100644
index 0000000..a0612a8
--- /dev/null
+++ b/arch/ppc/platforms/4xx/Kconfig
@@ -0,0 +1,247 @@
+config 4xx
+ bool
+ depends on 40x || 44x
+ default y
+
+menu "IBM 4xx options"
+ depends on 4xx
+
+choice
+ prompt "Machine Type"
+ depends on 40x
+ default WALNUT
+
+config ASH
+ bool "Ash"
+ help
+ This option enables support for the IBM NP405H evaluation board.
+
+config BUBINGA
+ bool "Bubinga"
+ help
+ This option enables support for the IBM 405EP evaluation board.
+
+config CPCI405
+ bool "CPCI405"
+ help
+ This option enables support for the CPCI405 board.
+
+config EP405
+ bool "EP405/EP405PC"
+ help
+ This option enables support for the EP405/EP405PC boards.
+
+config OAK
+ bool "Oak"
+ help
+ This option enables support for the IBM 403GCX evaluation board.
+
+config REDWOOD_5
+ bool "Redwood-5"
+ help
+ This option enables support for the IBM STB04 evaluation board.
+
+config REDWOOD_6
+ bool "Redwood-6"
+ help
+ This option enables support for the IBM STBx25xx evaluation board.
+
+config SYCAMORE
+ bool "Sycamore"
+ help
+ This option enables support for the IBM PPC405GPr evaluation board.
+
+config WALNUT
+ bool "Walnut"
+ help
+ This option enables support for the IBM PPC405GP evaluation board.
+
+config XILINX_ML300
+ bool "Xilinx-ML300"
+ help
+ This option enables support for the Xilinx ML300 evaluation board.
+
+endchoice
+
+choice
+ prompt "Machine Type"
+ depends on 44x
+ default EBONY
+
+config EBONY
+ bool "Ebony"
+ help
+ This option enables support for the IBM PPC440GP evaluation board.
+
+config LUAN
+ bool "Luan"
+ help
+ This option enables support for the IBM PPC440SP evaluation board.
+
+config OCOTEA
+ bool "Ocotea"
+ help
+ This option enables support for the IBM PPC440GX evaluation board.
+
+endchoice
+
+config EP405PC
+ bool "EP405PC Support"
+ depends on EP405
+
+
+# It's often necessary to know the specific 4xx processor type.
+# Fortunately, it is impled (so far) from the board type, so we
+# don't need to ask more redundant questions.
+config NP405H
+ bool
+ depends on ASH
+ default y
+
+config 440GP
+ bool
+ depends on EBONY
+ default y
+
+config 440GX
+ bool
+ depends on OCOTEA
+ default y
+
+config 440SP
+ bool
+ depends on LUAN
+ default y
+
+config 440
+ bool
+ depends on 440GP || 440SP
+ default y
+
+config 440A
+ bool
+ depends on 440GX
+ default y
+
+# All 405-based cores up until the 405GPR and 405EP have this errata.
+config IBM405_ERR77
+ bool
+ depends on 40x && !403GCX && !405GPR
+ default y
+
+# All 40x-based cores, up until the 405GPR and 405EP have this errata.
+config IBM405_ERR51
+ bool
+ depends on 40x && !405GPR
+ default y
+
+config BOOKE
+ bool
+ depends on 44x
+ default y
+
+config IBM_OCP
+ bool
+ depends on ASH || BUBINGA || CPCI405 || EBONY || EP405 || LUAN || OCOTEA || REDWOOD_5 || REDWOOD_6 || SYCAMORE || WALNUT
+ default y
+
+config XILINX_OCP
+ bool
+ depends on XILINX_ML300
+ default y
+
+config IBM_EMAC4
+ bool
+ depends on 440GX || 440SP
+ default y
+
+config BIOS_FIXUP
+ bool
+ depends on BUBINGA || EP405 || SYCAMORE || WALNUT
+ default y
+
+config 403GCX
+ bool
+ depends OAK
+ default y
+
+config 405EP
+ bool
+ depends on BUBINGA
+ default y
+
+config 405GP
+ bool
+ depends on CPCI405 || EP405 || WALNUT
+ default y
+
+config 405GPR
+ bool
+ depends on SYCAMORE
+ default y
+
+config VIRTEX_II_PRO
+ bool
+ depends on XILINX_ML300
+ default y
+
+config STB03xxx
+ bool
+ depends on REDWOOD_5 || REDWOOD_6
+ default y
+
+config EMBEDDEDBOOT
+ bool
+ depends on EP405 || XILINX_ML300
+ default y
+
+config IBM_OPENBIOS
+ bool
+ depends on ASH || BUBINGA || REDWOOD_5 || REDWOOD_6 || SYCAMORE || WALNUT
+ default y
+
+config PPC4xx_DMA
+ bool "PPC4xx DMA controller support"
+ depends on 4xx
+
+config PPC4xx_EDMA
+ bool
+ depends on !STB03xxx && PPC4xx_DMA
+ default y
+
+config PPC_GEN550
+ bool
+ depends on 4xx
+ default y
+
+config PM
+ bool "Power Management support (EXPERIMENTAL)"
+ depends on 4xx && EXPERIMENTAL
+
+choice
+ prompt "TTYS0 device and default console"
+ depends on 40x
+ default UART0_TTYS0
+
+config UART0_TTYS0
+ bool "UART0"
+
+config UART0_TTYS1
+ bool "UART1"
+
+endchoice
+
+config SERIAL_SICC
+ bool "SICC Serial port support"
+ depends on STB03xxx
+
+config UART1_DFLT_CONSOLE
+ bool
+ depends on SERIAL_SICC && UART0_TTYS1
+ default y
+
+config SERIAL_SICC_CONSOLE
+ bool
+ depends on SERIAL_SICC && UART0_TTYS1
+ default y
+endmenu
diff --git a/arch/ppc/platforms/4xx/Makefile b/arch/ppc/platforms/4xx/Makefile
new file mode 100644
index 0000000..ea470c6
--- /dev/null
+++ b/arch/ppc/platforms/4xx/Makefile
@@ -0,0 +1,27 @@
+#
+# Makefile for the PowerPC 4xx linux kernel.
+
+obj-$(CONFIG_ASH) += ash.o
+obj-$(CONFIG_CPCI405) += cpci405.o
+obj-$(CONFIG_EBONY) += ebony.o
+obj-$(CONFIG_EP405) += ep405.o
+obj-$(CONFIG_BUBINGA) += bubinga.o
+obj-$(CONFIG_LUAN) += luan.o
+obj-$(CONFIG_OAK) += oak.o
+obj-$(CONFIG_OCOTEA) += ocotea.o
+obj-$(CONFIG_REDWOOD_5) += redwood5.o
+obj-$(CONFIG_REDWOOD_6) += redwood6.o
+obj-$(CONFIG_SYCAMORE) += sycamore.o
+obj-$(CONFIG_WALNUT) += walnut.o
+obj-$(CONFIG_XILINX_ML300) += xilinx_ml300.o
+
+obj-$(CONFIG_405GP) += ibm405gp.o
+obj-$(CONFIG_REDWOOD_5) += ibmstb4.o
+obj-$(CONFIG_NP405H) += ibmnp405h.o
+obj-$(CONFIG_REDWOOD_6) += ibmstbx25.o
+obj-$(CONFIG_440GP) += ibm440gp.o
+obj-$(CONFIG_440GX) += ibm440gx.o
+obj-$(CONFIG_440SP) += ibm440sp.o
+obj-$(CONFIG_405EP) += ibm405ep.o
+obj-$(CONFIG_405GPR) += ibm405gpr.o
+obj-$(CONFIG_VIRTEX_II_PRO) += virtex-ii_pro.o
diff --git a/arch/ppc/platforms/4xx/ash.c b/arch/ppc/platforms/4xx/ash.c
new file mode 100644
index 0000000..ce29117
--- /dev/null
+++ b/arch/ppc/platforms/4xx/ash.c
@@ -0,0 +1,250 @@
+/*
+ * arch/ppc/platforms/4xx/ash.c
+ *
+ * Support for the IBM NP405H ash eval board
+ *
+ * Author: Armin Kuster <akuster@mvista.com>
+ *
+ * 2001-2002 (c) MontaVista, Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/pagemap.h>
+#include <linux/pci.h>
+
+#include <asm/machdep.h>
+#include <asm/pci-bridge.h>
+#include <asm/io.h>
+#include <asm/ocp.h>
+#include <asm/ibm_ocp_pci.h>
+#include <asm/todc.h>
+
+#ifdef DEBUG
+#define DBG(x...) printk(x)
+#else
+#define DBG(x...)
+#endif
+
+void *ash_rtc_base;
+
+/* Some IRQs unique to Walnut.
+ * Used by the generic 405 PCI setup functions in ppc4xx_pci.c
+ */
+int __init
+ppc405_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin)
+{
+ static char pci_irq_table[][4] =
+ /*
+ * PCI IDSEL/INTPIN->INTLINE
+ * A B C D
+ */
+ {
+ {24, 24, 24, 24}, /* IDSEL 1 - PCI slot 1 */
+ {25, 25, 25, 25}, /* IDSEL 2 - PCI slot 2 */
+ {26, 26, 26, 26}, /* IDSEL 3 - PCI slot 3 */
+ {27, 27, 27, 27}, /* IDSEL 4 - PCI slot 4 */
+ };
+
+ const long min_idsel = 1, max_idsel = 4, irqs_per_slot = 4;
+ return PCI_IRQ_TABLE_LOOKUP;
+}
+
+void __init
+ash_setup_arch(void)
+{
+ ppc4xx_setup_arch();
+
+ ibm_ocp_set_emac(0, 3);
+
+#ifdef CONFIG_DEBUG_BRINGUP
+ int i;
+ printk("\n");
+ printk("machine\t: %s\n", PPC4xx_MACHINE_NAME);
+ printk("\n");
+ printk("bi_s_version\t %s\n", bip->bi_s_version);
+ printk("bi_r_version\t %s\n", bip->bi_r_version);
+ printk("bi_memsize\t 0x%8.8x\t %dMBytes\n", bip->bi_memsize,
+ bip->bi_memsize / (1024 * 1000));
+ for (i = 0; i < EMAC_NUMS; i++) {
+ printk("bi_enetaddr %d\t %2.2x%2.2x%2.2x-%2.2x%2.2x%2.2x\n", i,
+ bip->bi_enetaddr[i][0], bip->bi_enetaddr[i][1],
+ bip->bi_enetaddr[i][2], bip->bi_enetaddr[i][3],
+ bip->bi_enetaddr[i][4], bip->bi_enetaddr[i][5]);
+ }
+ printk("bi_pci_enetaddr %d\t %2.2x%2.2x%2.2x-%2.2x%2.2x%2.2x\n", 0,
+ bip->bi_pci_enetaddr[0], bip->bi_pci_enetaddr[1],
+ bip->bi_pci_enetaddr[2], bip->bi_pci_enetaddr[3],
+ bip->bi_pci_enetaddr[4], bip->bi_pci_enetaddr[5]);
+
+ printk("bi_intfreq\t 0x%8.8x\t clock:\t %dMhz\n",
+ bip->bi_intfreq, bip->bi_intfreq / 1000000);
+
+ printk("bi_busfreq\t 0x%8.8x\t plb bus clock:\t %dMHz\n",
+ bip->bi_busfreq, bip->bi_busfreq / 1000000);
+ printk("bi_pci_busfreq\t 0x%8.8x\t pci bus clock:\t %dMHz\n",
+ bip->bi_pci_busfreq, bip->bi_pci_busfreq / 1000000);
+
+ printk("\n");
+#endif
+ /* RTC step for ash */
+ ash_rtc_base = (void *) ASH_RTC_VADDR;
+ TODC_INIT(TODC_TYPE_DS1743, ash_rtc_base, ash_rtc_base, ash_rtc_base,
+ 8);
+}
+
+void __init
+bios_fixup(struct pci_controller *hose, struct pcil0_regs *pcip)
+{
+ /*
+ * Expected PCI mapping:
+ *
+ * PLB addr PCI memory addr
+ * --------------------- ---------------------
+ * 0000'0000 - 7fff'ffff <--- 0000'0000 - 7fff'ffff
+ * 8000'0000 - Bfff'ffff ---> 8000'0000 - Bfff'ffff
+ *
+ * PLB addr PCI io addr
+ * --------------------- ---------------------
+ * e800'0000 - e800'ffff ---> 0000'0000 - 0001'0000
+ *
+ * The following code is simplified by assuming that the bootrom
+ * has been well behaved in following this mapping.
+ */
+
+#ifdef DEBUG
+ int i;
+
+ printk("ioremap PCLIO_BASE = 0x%x\n", pcip);
+ printk("PCI bridge regs before fixup \n");
+ for (i = 0; i <= 2; i++) {
+ printk(" pmm%dma\t0x%x\n", i, in_le32(&(pcip->pmm[i].ma)));
+ printk(" pmm%dla\t0x%x\n", i, in_le32(&(pcip->pmm[i].la)));
+ printk(" pmm%dpcila\t0x%x\n", i,
+ in_le32(&(pcip->pmm[i].pcila)));
+ printk(" pmm%dpciha\t0x%x\n", i,
+ in_le32(&(pcip->pmm[i].pciha)));
+ }
+ printk(" ptm1ms\t0x%x\n", in_le32(&(pcip->ptm1ms)));
+ printk(" ptm1la\t0x%x\n", in_le32(&(pcip->ptm1la)));
+ printk(" ptm2ms\t0x%x\n", in_le32(&(pcip->ptm2ms)));
+ printk(" ptm2la\t0x%x\n", in_le32(&(pcip->ptm2la)));
+ for (bar = PCI_BASE_ADDRESS_1; bar <= PCI_BASE_ADDRESS_2; bar += 4) {
+ early_read_config_dword(hose, hose->first_busno,
+ PCI_FUNC(hose->first_busno), bar,
+ &bar_response);
+ DBG("BUS %d, device %d, Function %d bar 0x%8.8x is 0x%8.8x\n",
+ hose->first_busno, PCI_SLOT(hose->first_busno),
+ PCI_FUNC(hose->first_busno), bar, bar_response);
+ }
+
+#endif
+ if (ppc_md.progress)
+ ppc_md.progress("bios_fixup(): enter", 0x800);
+
+ /* added for IBM boot rom version 1.15 bios bar changes -AK */
+
+ /* Disable region first */
+ out_le32((void *) &(pcip->pmm[0].ma), 0x00000000);
+ /* PLB starting addr, PCI: 0x80000000 */
+ out_le32((void *) &(pcip->pmm[0].la), 0x80000000);
+ /* PCI start addr, 0x80000000 */
+ out_le32((void *) &(pcip->pmm[0].pcila), PPC405_PCI_MEM_BASE);
+ /* 512MB range of PLB to PCI */
+ out_le32((void *) &(pcip->pmm[0].pciha), 0x00000000);
+ /* Enable no pre-fetch, enable region */
+ out_le32((void *) &(pcip->pmm[0].ma), ((0xffffffff -
+ (PPC405_PCI_UPPER_MEM -
+ PPC405_PCI_MEM_BASE)) | 0x01));
+
+ /* Disable region one */
+ out_le32((void *) &(pcip->pmm[1].ma), 0x00000000);
+ out_le32((void *) &(pcip->pmm[1].la), 0x00000000);
+ out_le32((void *) &(pcip->pmm[1].pcila), 0x00000000);
+ out_le32((void *) &(pcip->pmm[1].pciha), 0x00000000);
+ out_le32((void *) &(pcip->pmm[1].ma), 0x00000000);
+
+ /* Disable region two */
+ out_le32((void *) &(pcip->pmm[2].ma), 0x00000000);
+ out_le32((void *) &(pcip->pmm[2].la), 0x00000000);
+ out_le32((void *) &(pcip->pmm[2].pcila), 0x00000000);
+ out_le32((void *) &(pcip->pmm[2].pciha), 0x00000000);
+ out_le32((void *) &(pcip->pmm[2].ma), 0x00000000);
+
+ /* Enable PTM1 and PTM2, mapped to PLB address 0. */
+
+ out_le32((void *) &(pcip->ptm1la), 0x00000000);
+ out_le32((void *) &(pcip->ptm1ms), 0x00000001);
+ out_le32((void *) &(pcip->ptm2la), 0x00000000);
+ out_le32((void *) &(pcip->ptm2ms), 0x00000001);
+
+ /* Write zero to PTM1 BAR. */
+
+ early_write_config_dword(hose, hose->first_busno,
+ PCI_FUNC(hose->first_busno),
+ PCI_BASE_ADDRESS_1,
+ 0x00000000);
+
+ /* Disable PTM2 (unused) */
+
+ out_le32((void *) &(pcip->ptm2la), 0x00000000);
+ out_le32((void *) &(pcip->ptm2ms), 0x00000000);
+
+ /* end work arround */
+ if (ppc_md.progress)
+ ppc_md.progress("bios_fixup(): done", 0x800);
+
+#ifdef DEBUG
+ printk("PCI bridge regs after fixup \n");
+ for (i = 0; i <= 2; i++) {
+ printk(" pmm%dma\t0x%x\n", i, in_le32(&(pcip->pmm[i].ma)));
+ printk(" pmm%dla\t0x%x\n", i, in_le32(&(pcip->pmm[i].la)));
+ printk(" pmm%dpcila\t0x%x\n", i,
+ in_le32(&(pcip->pmm[i].pcila)));
+ printk(" pmm%dpciha\t0x%x\n", i,
+ in_le32(&(pcip->pmm[i].pciha)));
+ }
+ printk(" ptm1ms\t0x%x\n", in_le32(&(pcip->ptm1ms)));
+ printk(" ptm1la\t0x%x\n", in_le32(&(pcip->ptm1la)));
+ printk(" ptm2ms\t0x%x\n", in_le32(&(pcip->ptm2ms)));
+ printk(" ptm2la\t0x%x\n", in_le32(&(pcip->ptm2la)));
+
+ for (bar = PCI_BASE_ADDRESS_1; bar <= PCI_BASE_ADDRESS_2; bar += 4) {
+ early_read_config_dword(hose, hose->first_busno,
+ PCI_FUNC(hose->first_busno), bar,
+ &bar_response);
+ DBG("BUS %d, device %d, Function %d bar 0x%8.8x is 0x%8.8x\n",
+ hose->first_busno, PCI_SLOT(hose->first_busno),
+ PCI_FUNC(hose->first_busno), bar, bar_response);
+ }
+
+
+#endif
+}
+
+void __init
+ash_map_io(void)
+{
+ ppc4xx_map_io();
+ io_block_mapping(ASH_RTC_VADDR, ASH_RTC_PADDR, ASH_RTC_SIZE, _PAGE_IO);
+}
+
+void __init
+platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
+ unsigned long r6, unsigned long r7)
+{
+ ppc4xx_init(r3, r4, r5, r6, r7);
+
+ ppc_md.setup_arch = ash_setup_arch;
+ ppc_md.setup_io_mappings = ash_map_io;
+
+#ifdef CONFIG_PPC_RTC
+ ppc_md.time_init = todc_time_init;
+ ppc_md.set_rtc_time = todc_set_rtc_time;
+ ppc_md.get_rtc_time = todc_get_rtc_time;
+ ppc_md.nvram_read_val = todc_direct_read_val;
+ ppc_md.nvram_write_val = todc_direct_write_val;
+#endif
+}
diff --git a/arch/ppc/platforms/4xx/ash.h b/arch/ppc/platforms/4xx/ash.h
new file mode 100644
index 0000000..5f7448e
--- /dev/null
+++ b/arch/ppc/platforms/4xx/ash.h
@@ -0,0 +1,83 @@
+/*
+ * arch/ppc/platforms/4xx/ash.h
+ *
+ * Macros, definitions, and data structures specific to the IBM PowerPC
+ * Ash eval board.
+ *
+ * Author: Armin Kuster <akuster@mvista.com>
+ *
+ * 2000-2002 (c) MontaVista, Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+
+#ifdef __KERNEL__
+#ifndef __ASM_ASH_H__
+#define __ASM_ASH_H__
+#include <platforms/4xx/ibmnp405h.h>
+
+#ifndef __ASSEMBLY__
+/*
+ * Data structure defining board information maintained by the boot
+ * ROM on IBM's "Ash" evaluation board. An effort has been made to
+ * keep the field names consistent with the 8xx 'bd_t' board info
+ * structures.
+ */
+
+typedef struct board_info {
+ unsigned char bi_s_version[4]; /* Version of this structure */
+ unsigned char bi_r_version[30]; /* Version of the IBM ROM */
+ unsigned int bi_memsize; /* DRAM installed, in bytes */
+ unsigned char bi_enetaddr[4][6]; /* Local Ethernet MAC address */
+ unsigned char bi_pci_enetaddr[6];
+ unsigned int bi_intfreq; /* Processor speed, in Hz */
+ unsigned int bi_busfreq; /* PLB Bus speed, in Hz */
+ unsigned int bi_pci_busfreq; /* PCI speed in Hz */
+} bd_t;
+
+/* Some 4xx parts use a different timebase frequency from the internal clock.
+*/
+#define bi_tbfreq bi_intfreq
+
+/* Memory map for the IBM "Ash" NP405H evaluation board.
+ */
+
+extern void *ash_rtc_base;
+#define ASH_RTC_PADDR ((uint)0xf0000000)
+#define ASH_RTC_VADDR ASH_RTC_PADDR
+#define ASH_RTC_SIZE ((uint)8*1024)
+
+
+/* Early initialization address mapping for block_io.
+ * Standard 405GP map.
+ */
+#define PPC4xx_PCI_IO_PADDR ((uint)PPC405_PCI_PHY_IO_BASE)
+#define PPC4xx_PCI_IO_VADDR PPC4xx_PCI_IO_PADDR
+#define PPC4xx_PCI_IO_SIZE ((uint)64*1024)
+#define PPC4xx_PCI_CFG_PADDR ((uint)PPC405_PCI_CONFIG_ADDR)
+#define PPC4xx_PCI_CFG_VADDR PPC4xx_PCI_CFG_PADDR
+#define PPC4xx_PCI_CFG_SIZE ((uint)4*1024)
+#define PPC4xx_PCI_LCFG_PADDR ((uint)0xef400000)
+#define PPC4xx_PCI_LCFG_VADDR PPC4xx_PCI_LCFG_PADDR
+#define PPC4xx_PCI_LCFG_SIZE ((uint)4*1024)
+#define PPC4xx_ONB_IO_PADDR ((uint)0xef600000)
+#define PPC4xx_ONB_IO_VADDR PPC4xx_ONB_IO_PADDR
+#define PPC4xx_ONB_IO_SIZE ((uint)4*1024)
+
+#define NR_BOARD_IRQS 32
+
+#ifdef CONFIG_PPC405GP_INTERNAL_CLOCK
+#define BASE_BAUD 201600
+#else
+#define BASE_BAUD 691200
+#endif
+
+#define PPC4xx_MACHINE_NAME "IBM NP405H Ash"
+
+extern char pci_irq_table[][4];
+
+
+#endif /* !__ASSEMBLY__ */
+#endif /* __ASM_ASH_H__ */
+#endif /* __KERNEL__ */
diff --git a/arch/ppc/platforms/4xx/bubinga.c b/arch/ppc/platforms/4xx/bubinga.c
new file mode 100644
index 0000000..3678abf
--- /dev/null
+++ b/arch/ppc/platforms/4xx/bubinga.c
@@ -0,0 +1,263 @@
+/*
+ * Support for IBM PPC 405EP evaluation board (Bubinga).
+ *
+ * Author: SAW (IBM), derived from walnut.c.
+ * Maintained by MontaVista Software <source@mvista.com>
+ *
+ * 2003 (c) MontaVista Softare Inc. This file is licensed under the
+ * terms of the GNU General Public License version 2. This program is
+ * licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/smp.h>
+#include <linux/threads.h>
+#include <linux/param.h>
+#include <linux/string.h>
+#include <linux/blkdev.h>
+#include <linux/pci.h>
+#include <linux/rtc.h>
+#include <linux/tty.h>
+#include <linux/serial.h>
+#include <linux/serial_core.h>
+
+#include <asm/system.h>
+#include <asm/pci-bridge.h>
+#include <asm/processor.h>
+#include <asm/machdep.h>
+#include <asm/page.h>
+#include <asm/time.h>
+#include <asm/io.h>
+#include <asm/todc.h>
+#include <asm/kgdb.h>
+#include <asm/ocp.h>
+#include <asm/ibm_ocp_pci.h>
+
+#include <platforms/4xx/ibm405ep.h>
+
+#undef DEBUG
+
+#ifdef DEBUG
+#define DBG(x...) printk(x)
+#else
+#define DBG(x...)
+#endif
+
+extern bd_t __res;
+
+void *bubinga_rtc_base;
+
+/* Some IRQs unique to the board
+ * Used by the generic 405 PCI setup functions in ppc4xx_pci.c
+ */
+int __init
+ppc405_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin)
+{
+ static char pci_irq_table[][4] =
+ /*
+ * PCI IDSEL/INTPIN->INTLINE
+ * A B C D
+ */
+ {
+ {28, 28, 28, 28}, /* IDSEL 1 - PCI slot 1 */
+ {29, 29, 29, 29}, /* IDSEL 2 - PCI slot 2 */
+ {30, 30, 30, 30}, /* IDSEL 3 - PCI slot 3 */
+ {31, 31, 31, 31}, /* IDSEL 4 - PCI slot 4 */
+ };
+
+ const long min_idsel = 1, max_idsel = 4, irqs_per_slot = 4;
+ return PCI_IRQ_TABLE_LOOKUP;
+};
+
+/* The serial clock for the chip is an internal clock determined by
+ * different clock speeds/dividers.
+ * Calculate the proper input baud rate and setup the serial driver.
+ */
+static void __init
+bubinga_early_serial_map(void)
+{
+ u32 uart_div;
+ int uart_clock;
+ struct uart_port port;
+
+ /* Calculate the serial clock input frequency
+ *
+ * The base baud is the PLL OUTA (provided in the board info
+ * structure) divided by the external UART Divisor, divided
+ * by 16.
+ */
+ uart_div = (mfdcr(DCRN_CPC0_UCR_BASE) & DCRN_CPC0_UCR_U0DIV);
+ uart_clock = __res.bi_pllouta_freq / uart_div;
+
+ /* Setup serial port access */
+ memset(&port, 0, sizeof(port));
+ port.membase = (void*)ACTING_UART0_IO_BASE;
+ port.irq = ACTING_UART0_INT;
+ port.uartclk = uart_clock;
+ port.regshift = 0;
+ port.iotype = SERIAL_IO_MEM;
+ port.flags = ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST;
+ port.line = 0;
+
+ if (early_serial_setup(&port) != 0) {
+ printk("Early serial init of port 0 failed\n");
+ }
+
+ port.membase = (void*)ACTING_UART1_IO_BASE;
+ port.irq = ACTING_UART1_INT;
+ port.line = 1;
+
+ if (early_serial_setup(&port) != 0) {
+ printk("Early serial init of port 1 failed\n");
+ }
+}
+
+void __init
+bios_fixup(struct pci_controller *hose, struct pcil0_regs *pcip)
+{
+
+ unsigned int bar_response, bar;
+ /*
+ * Expected PCI mapping:
+ *
+ * PLB addr PCI memory addr
+ * --------------------- ---------------------
+ * 0000'0000 - 7fff'ffff <--- 0000'0000 - 7fff'ffff
+ * 8000'0000 - Bfff'ffff ---> 8000'0000 - Bfff'ffff
+ *
+ * PLB addr PCI io addr
+ * --------------------- ---------------------
+ * e800'0000 - e800'ffff ---> 0000'0000 - 0001'0000
+ *
+ * The following code is simplified by assuming that the bootrom
+ * has been well behaved in following this mapping.
+ */
+
+#ifdef DEBUG
+ int i;
+
+ printk("ioremap PCLIO_BASE = 0x%x\n", pcip);
+ printk("PCI bridge regs before fixup \n");
+ for (i = 0; i <= 3; i++) {
+ printk(" pmm%dma\t0x%x\n", i, in_le32(&(pcip->pmm[i].ma)));
+ printk(" pmm%dma\t0x%x\n", i, in_le32(&(pcip->pmm[i].la)));
+ printk(" pmm%dma\t0x%x\n", i, in_le32(&(pcip->pmm[i].pcila)));
+ printk(" pmm%dma\t0x%x\n", i, in_le32(&(pcip->pmm[i].pciha)));
+ }
+ printk(" ptm1ms\t0x%x\n", in_le32(&(pcip->ptm1ms)));
+ printk(" ptm1la\t0x%x\n", in_le32(&(pcip->ptm1la)));
+ printk(" ptm2ms\t0x%x\n", in_le32(&(pcip->ptm2ms)));
+ printk(" ptm2la\t0x%x\n", in_le32(&(pcip->ptm2la)));
+
+#endif
+
+ /* added for IBM boot rom version 1.15 bios bar changes -AK */
+
+ /* Disable region first */
+ out_le32((void *) &(pcip->pmm[0].ma), 0x00000000);
+ /* PLB starting addr, PCI: 0x80000000 */
+ out_le32((void *) &(pcip->pmm[0].la), 0x80000000);
+ /* PCI start addr, 0x80000000 */
+ out_le32((void *) &(pcip->pmm[0].pcila), PPC405_PCI_MEM_BASE);
+ /* 512MB range of PLB to PCI */
+ out_le32((void *) &(pcip->pmm[0].pciha), 0x00000000);
+ /* Enable no pre-fetch, enable region */
+ out_le32((void *) &(pcip->pmm[0].ma), ((0xffffffff -
+ (PPC405_PCI_UPPER_MEM -
+ PPC405_PCI_MEM_BASE)) | 0x01));
+
+ /* Disable region one */
+ out_le32((void *) &(pcip->pmm[1].ma), 0x00000000);
+ out_le32((void *) &(pcip->pmm[1].la), 0x00000000);
+ out_le32((void *) &(pcip->pmm[1].pcila), 0x00000000);
+ out_le32((void *) &(pcip->pmm[1].pciha), 0x00000000);
+ out_le32((void *) &(pcip->pmm[1].ma), 0x00000000);
+ out_le32((void *) &(pcip->ptm1ms), 0x00000001);
+
+ /* Disable region two */
+ out_le32((void *) &(pcip->pmm[2].ma), 0x00000000);
+ out_le32((void *) &(pcip->pmm[2].la), 0x00000000);
+ out_le32((void *) &(pcip->pmm[2].pcila), 0x00000000);
+ out_le32((void *) &(pcip->pmm[2].pciha), 0x00000000);
+ out_le32((void *) &(pcip->pmm[2].ma), 0x00000000);
+ out_le32((void *) &(pcip->ptm2ms), 0x00000000);
+ out_le32((void *) &(pcip->ptm2la), 0x00000000);
+
+ /* Zero config bars */
+ for (bar = PCI_BASE_ADDRESS_1; bar <= PCI_BASE_ADDRESS_2; bar += 4) {
+ early_write_config_dword(hose, hose->first_busno,
+ PCI_FUNC(hose->first_busno), bar,
+ 0x00000000);
+ early_read_config_dword(hose, hose->first_busno,
+ PCI_FUNC(hose->first_busno), bar,
+ &bar_response);
+ DBG("BUS %d, device %d, Function %d bar 0x%8.8x is 0x%8.8x\n",
+ hose->first_busno, PCI_SLOT(hose->first_busno),
+ PCI_FUNC(hose->first_busno), bar, bar_response);
+ }
+ /* end work arround */
+
+#ifdef DEBUG
+ printk("PCI bridge regs after fixup \n");
+ for (i = 0; i <= 3; i++) {
+ printk(" pmm%dma\t0x%x\n", i, in_le32(&(pcip->pmm[i].ma)));
+ printk(" pmm%dma\t0x%x\n", i, in_le32(&(pcip->pmm[i].la)));
+ printk(" pmm%dma\t0x%x\n", i, in_le32(&(pcip->pmm[i].pcila)));
+ printk(" pmm%dma\t0x%x\n", i, in_le32(&(pcip->pmm[i].pciha)));
+ }
+ printk(" ptm1ms\t0x%x\n", in_le32(&(pcip->ptm1ms)));
+ printk(" ptm1la\t0x%x\n", in_le32(&(pcip->ptm1la)));
+ printk(" ptm2ms\t0x%x\n", in_le32(&(pcip->ptm2ms)));
+ printk(" ptm2la\t0x%x\n", in_le32(&(pcip->ptm2la)));
+
+#endif
+}
+
+void __init
+bubinga_setup_arch(void)
+{
+ ppc4xx_setup_arch();
+
+ ibm_ocp_set_emac(0, 1);
+
+ bubinga_early_serial_map();
+
+ /* RTC step for the evb405ep */
+ bubinga_rtc_base = (void *) BUBINGA_RTC_VADDR;
+ TODC_INIT(TODC_TYPE_DS1743, bubinga_rtc_base, bubinga_rtc_base,
+ bubinga_rtc_base, 8);
+ /* Identify the system */
+ printk("IBM Bubinga port (MontaVista Software, Inc. <source@mvista.com>)\n");
+}
+
+void __init
+bubinga_map_io(void)
+{
+ ppc4xx_map_io();
+ io_block_mapping(BUBINGA_RTC_VADDR,
+ BUBINGA_RTC_PADDR, BUBINGA_RTC_SIZE, _PAGE_IO);
+}
+
+void __init
+platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
+ unsigned long r6, unsigned long r7)
+{
+ ppc4xx_init(r3, r4, r5, r6, r7);
+
+ ppc_md.setup_arch = bubinga_setup_arch;
+ ppc_md.setup_io_mappings = bubinga_map_io;
+
+#ifdef CONFIG_GEN_RTC
+ ppc_md.time_init = todc_time_init;
+ ppc_md.set_rtc_time = todc_set_rtc_time;
+ ppc_md.get_rtc_time = todc_get_rtc_time;
+ ppc_md.nvram_read_val = todc_direct_read_val;
+ ppc_md.nvram_write_val = todc_direct_write_val;
+#endif
+#ifdef CONFIG_KGDB
+ ppc_md.early_serial_map = bubinga_early_serial_map;
+#endif
+}
+
diff --git a/arch/ppc/platforms/4xx/bubinga.h b/arch/ppc/platforms/4xx/bubinga.h
new file mode 100644
index 0000000..b1df856
--- /dev/null
+++ b/arch/ppc/platforms/4xx/bubinga.h
@@ -0,0 +1,69 @@
+/*
+ * Support for IBM PPC 405EP evaluation board (Bubinga).
+ *
+ * Author: SAW (IBM), derived from walnut.h.
+ * Maintained by MontaVista Software <source@mvista.com>
+ *
+ * 2003 (c) MontaVista Softare Inc. This file is licensed under the
+ * terms of the GNU General Public License version 2. This program is
+ * licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+
+#ifdef __KERNEL__
+#ifndef __BUBINGA_H__
+#define __BUBINGA_H__
+
+/* 405EP */
+#include <platforms/4xx/ibm405ep.h>
+
+#ifndef __ASSEMBLY__
+/*
+ * Data structure defining board information maintained by the boot
+ * ROM on IBM's evaluation board. An effort has been made to
+ * keep the field names consistent with the 8xx 'bd_t' board info
+ * structures.
+ */
+
+typedef struct board_info {
+ unsigned char bi_s_version[4]; /* Version of this structure */
+ unsigned char bi_r_version[30]; /* Version of the IBM ROM */
+ unsigned int bi_memsize; /* DRAM installed, in bytes */
+ unsigned char bi_enetaddr[2][6]; /* Local Ethernet MAC address */ unsigned char bi_pci_enetaddr[6]; /* PCI Ethernet MAC address */
+ unsigned int bi_intfreq; /* Processor speed, in Hz */
+ unsigned int bi_busfreq; /* PLB Bus speed, in Hz */
+ unsigned int bi_pci_busfreq; /* PCI Bus speed, in Hz */
+ unsigned int bi_opb_busfreq; /* OPB Bus speed, in Hz */
+ unsigned int bi_pllouta_freq; /* PLL OUTA speed, in Hz */
+} bd_t;
+
+/* Some 4xx parts use a different timebase frequency from the internal clock.
+*/
+#define bi_tbfreq bi_intfreq
+
+
+/* Memory map for the Bubinga board.
+ * Generic 4xx plus RTC.
+ */
+
+extern void *bubinga_rtc_base;
+#define BUBINGA_RTC_PADDR ((uint)0xf0000000)
+#define BUBINGA_RTC_VADDR BUBINGA_RTC_PADDR
+#define BUBINGA_RTC_SIZE ((uint)8*1024)
+
+/* The UART clock is based off an internal clock -
+ * define BASE_BAUD based on the internal clock and divider(s).
+ * Since BASE_BAUD must be a constant, we will initialize it
+ * using clock/divider values which OpenBIOS initializes
+ * for typical configurations at various CPU speeds.
+ * The base baud is calculated as (FWDA / EXT UART DIV / 16)
+ */
+#define BASE_BAUD 0
+
+#define BUBINGA_FPGA_BASE 0xF0300000
+
+#define PPC4xx_MACHINE_NAME "IBM Bubinga"
+
+#endif /* !__ASSEMBLY__ */
+#endif /* __BUBINGA_H__ */
+#endif /* __KERNEL__ */
diff --git a/arch/ppc/platforms/4xx/cpci405.c b/arch/ppc/platforms/4xx/cpci405.c
new file mode 100644
index 0000000..ff96677
--- /dev/null
+++ b/arch/ppc/platforms/4xx/cpci405.c
@@ -0,0 +1,84 @@
+/*
+ * arch/ppc/platforms/cpci405.c
+ *
+ * Board setup routines for the esd CPCI-405 cPCI Board.
+ *
+ * Author: Stefan Roese
+ * stefan.roese@esd-electronics.com
+ *
+ * Copyright 2001 esd electronic system design - hannover germany
+ *
+ * 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.
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <asm/system.h>
+#include <asm/pci-bridge.h>
+#include <asm/machdep.h>
+#include <asm/todc.h>
+#include <asm/ocp.h>
+
+void *cpci405_nvram;
+
+/*
+ * Some IRQs unique to CPCI-405.
+ */
+int __init
+ppc405_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin)
+{
+ static char pci_irq_table[][4] =
+ /*
+ * PCI IDSEL/INTPIN->INTLINE
+ * A B C D
+ */
+ {
+ {28, 28, 28, 28}, /* IDSEL 15 - cPCI slot 8 */
+ {29, 29, 29, 29}, /* IDSEL 16 - cPCI slot 7 */
+ {30, 30, 30, 30}, /* IDSEL 17 - cPCI slot 6 */
+ {27, 27, 27, 27}, /* IDSEL 18 - cPCI slot 5 */
+ {28, 28, 28, 28}, /* IDSEL 19 - cPCI slot 4 */
+ {29, 29, 29, 29}, /* IDSEL 20 - cPCI slot 3 */
+ {30, 30, 30, 30}, /* IDSEL 21 - cPCI slot 2 */
+ };
+ const long min_idsel = 15, max_idsel = 21, irqs_per_slot = 4;
+ return PCI_IRQ_TABLE_LOOKUP;
+};
+
+void __init
+cpci405_setup_arch(void)
+{
+ ppc4xx_setup_arch();
+
+ ibm_ocp_set_emac(0, 0);
+
+ TODC_INIT(TODC_TYPE_MK48T35, cpci405_nvram, cpci405_nvram, cpci405_nvram, 8);
+}
+
+void __init
+cpci405_map_io(void)
+{
+ ppc4xx_map_io();
+ cpci405_nvram = ioremap(CPCI405_NVRAM_PADDR, CPCI405_NVRAM_SIZE);
+}
+
+void __init
+platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
+ unsigned long r6, unsigned long r7)
+{
+ ppc4xx_init(r3, r4, r5, r6, r7);
+
+ ppc_md.setup_arch = cpci405_setup_arch;
+ ppc_md.setup_io_mappings = cpci405_map_io;
+
+ ppc_md.time_init = todc_time_init;
+ ppc_md.set_rtc_time = todc_set_rtc_time;
+ ppc_md.get_rtc_time = todc_get_rtc_time;
+ ppc_md.nvram_read_val = todc_direct_read_val;
+ ppc_md.nvram_write_val = todc_direct_write_val;
+}
diff --git a/arch/ppc/platforms/4xx/cpci405.h b/arch/ppc/platforms/4xx/cpci405.h
new file mode 100644
index 0000000..e27f7cb
--- /dev/null
+++ b/arch/ppc/platforms/4xx/cpci405.h
@@ -0,0 +1,37 @@
+/*
+ * CPCI-405 board specific definitions
+ *
+ * Copyright (c) 2001 Stefan Roese (stefan.roese@esd-electronics.com)
+ */
+
+#ifdef __KERNEL__
+#ifndef __ASM_CPCI405_H__
+#define __ASM_CPCI405_H__
+
+#include <linux/config.h>
+
+/* We have a 405GP core */
+#include <platforms/4xx/ibm405gp.h>
+
+#include <asm/ppcboot.h>
+
+#ifndef __ASSEMBLY__
+/* Some 4xx parts use a different timebase frequency from the internal clock.
+*/
+#define bi_tbfreq bi_intfreq
+
+/* Map for the NVRAM space */
+#define CPCI405_NVRAM_PADDR ((uint)0xf0200000)
+#define CPCI405_NVRAM_SIZE ((uint)32*1024)
+
+#ifdef CONFIG_PPC405GP_INTERNAL_CLOCK
+#define BASE_BAUD 201600
+#else
+#define BASE_BAUD 691200
+#endif
+
+#define PPC4xx_MACHINE_NAME "esd CPCI-405"
+
+#endif /* !__ASSEMBLY__ */
+#endif /* __ASM_CPCI405_H__ */
+#endif /* __KERNEL__ */
diff --git a/arch/ppc/platforms/4xx/ebony.c b/arch/ppc/platforms/4xx/ebony.c
new file mode 100644
index 0000000..f63bca8
--- /dev/null
+++ b/arch/ppc/platforms/4xx/ebony.c
@@ -0,0 +1,356 @@
+/*
+ * arch/ppc/platforms/4xx/ebony.c
+ *
+ * Ebony board specific routines
+ *
+ * Matt Porter <mporter@kernel.crashing.org>
+ * Copyright 2002-2005 MontaVista Software Inc.
+ *
+ * Eugene Surovegin <eugene.surovegin@zultys.com> or <ebs@ebshome.net>
+ * Copyright (c) 2003, 2004 Zultys Technologies
+ *
+ * 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.
+ */
+
+#include <linux/config.h>
+#include <linux/stddef.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/reboot.h>
+#include <linux/pci.h>
+#include <linux/kdev_t.h>
+#include <linux/types.h>
+#include <linux/major.h>
+#include <linux/blkdev.h>
+#include <linux/console.h>
+#include <linux/delay.h>
+#include <linux/ide.h>
+#include <linux/initrd.h>
+#include <linux/irq.h>
+#include <linux/seq_file.h>
+#include <linux/root_dev.h>
+#include <linux/tty.h>
+#include <linux/serial.h>
+#include <linux/serial_core.h>
+
+#include <asm/system.h>
+#include <asm/pgtable.h>
+#include <asm/page.h>
+#include <asm/dma.h>
+#include <asm/io.h>
+#include <asm/machdep.h>
+#include <asm/ocp.h>
+#include <asm/pci-bridge.h>
+#include <asm/time.h>
+#include <asm/todc.h>
+#include <asm/bootinfo.h>
+#include <asm/ppc4xx_pic.h>
+#include <asm/ppcboot.h>
+
+#include <syslib/gen550.h>
+#include <syslib/ibm440gp_common.h>
+
+/*
+ * This is a horrible kludge, we eventually need to abstract this
+ * generic PHY stuff, so the standard phy mode defines can be
+ * easily used from arch code.
+ */
+#include "../../../../drivers/net/ibm_emac/ibm_emac_phy.h"
+
+bd_t __res;
+
+static struct ibm44x_clocks clocks __initdata;
+
+/*
+ * Ebony external IRQ triggering/polarity settings
+ */
+unsigned char ppc4xx_uic_ext_irq_cfg[] __initdata = {
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* IRQ0: PCI slot 0 */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* IRQ1: PCI slot 1 */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* IRQ2: PCI slot 2 */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* IRQ3: PCI slot 3 */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* IRQ4: IRDA */
+ (IRQ_SENSE_EDGE | IRQ_POLARITY_NEGATIVE), /* IRQ5: SMI pushbutton */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* IRQ6: PHYs */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* IRQ7: AUX */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* IRQ8: EXT */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* IRQ9: EXT */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* IRQ10: EXT */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* IRQ11: EXT */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* IRQ12: EXT */
+};
+
+static void __init
+ebony_calibrate_decr(void)
+{
+ unsigned int freq;
+
+ /*
+ * Determine system clock speed
+ *
+ * If we are on Rev. B silicon, then use
+ * default external system clock. If we are
+ * on Rev. C silicon then errata forces us to
+ * use the internal clock.
+ */
+ switch (PVR_REV(mfspr(SPRN_PVR))) {
+ case PVR_REV(PVR_440GP_RB):
+ freq = EBONY_440GP_RB_SYSCLK;
+ break;
+ case PVR_REV(PVR_440GP_RC1):
+ default:
+ freq = EBONY_440GP_RC_SYSCLK;
+ break;
+ }
+
+ ibm44x_calibrate_decr(freq);
+}
+
+static int
+ebony_show_cpuinfo(struct seq_file *m)
+{
+ seq_printf(m, "vendor\t\t: IBM\n");
+ seq_printf(m, "machine\t\t: Ebony\n");
+
+ return 0;
+}
+
+static inline int
+ebony_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin)
+{
+ static char pci_irq_table[][4] =
+ /*
+ * PCI IDSEL/INTPIN->INTLINE
+ * A B C D
+ */
+ {
+ { 23, 23, 23, 23 }, /* IDSEL 1 - PCI Slot 0 */
+ { 24, 24, 24, 24 }, /* IDSEL 2 - PCI Slot 1 */
+ { 25, 25, 25, 25 }, /* IDSEL 3 - PCI Slot 2 */
+ { 26, 26, 26, 26 }, /* IDSEL 4 - PCI Slot 3 */
+ };
+
+ const long min_idsel = 1, max_idsel = 4, irqs_per_slot = 4;
+ return PCI_IRQ_TABLE_LOOKUP;
+}
+
+#define PCIX_WRITEL(value, offset) \
+ (writel(value, pcix_reg_base + offset))
+
+/*
+ * FIXME: This is only here to "make it work". This will move
+ * to a ibm_pcix.c which will contain a generic IBM PCIX bridge
+ * configuration library. -Matt
+ */
+static void __init
+ebony_setup_pcix(void)
+{
+ void *pcix_reg_base;
+
+ pcix_reg_base = ioremap64(PCIX0_REG_BASE, PCIX_REG_SIZE);
+
+ /* Disable all windows */
+ PCIX_WRITEL(0, PCIX0_POM0SA);
+ PCIX_WRITEL(0, PCIX0_POM1SA);
+ PCIX_WRITEL(0, PCIX0_POM2SA);
+ PCIX_WRITEL(0, PCIX0_PIM0SA);
+ PCIX_WRITEL(0, PCIX0_PIM1SA);
+ PCIX_WRITEL(0, PCIX0_PIM2SA);
+
+ /* Setup 2GB PLB->PCI outbound mem window (3_8000_0000->0_8000_0000) */
+ PCIX_WRITEL(0x00000003, PCIX0_POM0LAH);
+ PCIX_WRITEL(0x80000000, PCIX0_POM0LAL);
+ PCIX_WRITEL(0x00000000, PCIX0_POM0PCIAH);
+ PCIX_WRITEL(0x80000000, PCIX0_POM0PCIAL);
+ PCIX_WRITEL(0x80000001, PCIX0_POM0SA);
+
+ /* Setup 2GB PCI->PLB inbound memory window at 0, enable MSIs */
+ PCIX_WRITEL(0x00000000, PCIX0_PIM0LAH);
+ PCIX_WRITEL(0x00000000, PCIX0_PIM0LAL);
+ PCIX_WRITEL(0x80000007, PCIX0_PIM0SA);
+
+ eieio();
+}
+
+static void __init
+ebony_setup_hose(void)
+{
+ struct pci_controller *hose;
+
+ /* Configure windows on the PCI-X host bridge */
+ ebony_setup_pcix();
+
+ hose = pcibios_alloc_controller();
+
+ if (!hose)
+ return;
+
+ hose->first_busno = 0;
+ hose->last_busno = 0xff;
+
+ hose->pci_mem_offset = EBONY_PCI_MEM_OFFSET;
+
+ pci_init_resource(&hose->io_resource,
+ EBONY_PCI_LOWER_IO,
+ EBONY_PCI_UPPER_IO,
+ IORESOURCE_IO,
+ "PCI host bridge");
+
+ pci_init_resource(&hose->mem_resources[0],
+ EBONY_PCI_LOWER_MEM,
+ EBONY_PCI_UPPER_MEM,
+ IORESOURCE_MEM,
+ "PCI host bridge");
+
+ hose->io_space.start = EBONY_PCI_LOWER_IO;
+ hose->io_space.end = EBONY_PCI_UPPER_IO;
+ hose->mem_space.start = EBONY_PCI_LOWER_MEM;
+ hose->mem_space.end = EBONY_PCI_UPPER_MEM;
+ isa_io_base =
+ (unsigned long)ioremap64(EBONY_PCI_IO_BASE, EBONY_PCI_IO_SIZE);
+ hose->io_base_virt = (void *)isa_io_base;
+
+ setup_indirect_pci(hose,
+ EBONY_PCI_CFGA_PLB32,
+ EBONY_PCI_CFGD_PLB32);
+ hose->set_cfg_type = 1;
+
+ hose->last_busno = pciauto_bus_scan(hose, hose->first_busno);
+
+ ppc_md.pci_swizzle = common_swizzle;
+ ppc_md.pci_map_irq = ebony_map_irq;
+}
+
+TODC_ALLOC();
+
+static void __init
+ebony_early_serial_map(void)
+{
+ struct uart_port port;
+
+ /* Setup ioremapped serial port access */
+ memset(&port, 0, sizeof(port));
+ port.membase = ioremap64(PPC440GP_UART0_ADDR, 8);
+ port.irq = 0;
+ port.uartclk = clocks.uart0;
+ port.regshift = 0;
+ port.iotype = SERIAL_IO_MEM;
+ port.flags = ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST;
+ port.line = 0;
+
+ if (early_serial_setup(&port) != 0) {
+ printk("Early serial init of port 0 failed\n");
+ }
+
+#if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB)
+ /* Configure debug serial access */
+ gen550_init(0, &port);
+#endif
+
+ port.membase = ioremap64(PPC440GP_UART1_ADDR, 8);
+ port.irq = 1;
+ port.uartclk = clocks.uart1;
+ port.line = 1;
+
+ if (early_serial_setup(&port) != 0) {
+ printk("Early serial init of port 1 failed\n");
+ }
+
+#if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB)
+ /* Configure debug serial access */
+ gen550_init(1, &port);
+#endif
+}
+
+static void __init
+ebony_setup_arch(void)
+{
+ struct ocp_def *def;
+ struct ocp_func_emac_data *emacdata;
+
+ /* Set mac_addr for each EMAC */
+ def = ocp_get_one_device(OCP_VENDOR_IBM, OCP_FUNC_EMAC, 0);
+ emacdata = def->additions;
+ emacdata->phy_map = 0x00000001; /* Skip 0x00 */
+ emacdata->phy_mode = PHY_MODE_RMII;
+ memcpy(emacdata->mac_addr, __res.bi_enetaddr, 6);
+
+ def = ocp_get_one_device(OCP_VENDOR_IBM, OCP_FUNC_EMAC, 1);
+ emacdata = def->additions;
+ emacdata->phy_map = 0x00000001; /* Skip 0x00 */
+ emacdata->phy_mode = PHY_MODE_RMII;
+ memcpy(emacdata->mac_addr, __res.bi_enet1addr, 6);
+
+ /*
+ * Determine various clocks.
+ * To be completely correct we should get SysClk
+ * from FPGA, because it can be changed by on-board switches
+ * --ebs
+ */
+ ibm440gp_get_clocks(&clocks, 33333333, 6 * 1843200);
+ ocp_sys_info.opb_bus_freq = clocks.opb;
+
+ /* Setup TODC access */
+ TODC_INIT(TODC_TYPE_DS1743,
+ 0,
+ 0,
+ ioremap64(EBONY_RTC_ADDR, EBONY_RTC_SIZE),
+ 8);
+
+ /* init to some ~sane value until calibrate_delay() runs */
+ loops_per_jiffy = 50000000/HZ;
+
+ /* Setup PCI host bridge */
+ ebony_setup_hose();
+
+#ifdef CONFIG_BLK_DEV_INITRD
+ if (initrd_start)
+ ROOT_DEV = Root_RAM0;
+ else
+#endif
+#ifdef CONFIG_ROOT_NFS
+ ROOT_DEV = Root_NFS;
+#else
+ ROOT_DEV = Root_HDA1;
+#endif
+
+ ebony_early_serial_map();
+
+ /* Identify the system */
+ printk("IBM Ebony port (MontaVista Software, Inc. (source@mvista.com))\n");
+}
+
+void __init platform_init(unsigned long r3, unsigned long r4,
+ unsigned long r5, unsigned long r6, unsigned long r7)
+{
+ parse_bootinfo(find_bootinfo());
+
+ /*
+ * If we were passed in a board information, copy it into the
+ * residual data area.
+ */
+ if (r3)
+ __res = *(bd_t *)(r3 + KERNELBASE);
+
+ ibm44x_platform_init();
+
+ ppc_md.setup_arch = ebony_setup_arch;
+ ppc_md.show_cpuinfo = ebony_show_cpuinfo;
+ ppc_md.get_irq = NULL; /* Set in ppc4xx_pic_init() */
+
+ ppc_md.calibrate_decr = ebony_calibrate_decr;
+ ppc_md.time_init = todc_time_init;
+ ppc_md.set_rtc_time = todc_set_rtc_time;
+ ppc_md.get_rtc_time = todc_get_rtc_time;
+
+ ppc_md.nvram_read_val = todc_direct_read_val;
+ ppc_md.nvram_write_val = todc_direct_write_val;
+#ifdef CONFIG_KGDB
+ ppc_md.early_serial_map = ebony_early_serial_map;
+#endif
+}
+
diff --git a/arch/ppc/platforms/4xx/ebony.h b/arch/ppc/platforms/4xx/ebony.h
new file mode 100644
index 0000000..47c391c
--- /dev/null
+++ b/arch/ppc/platforms/4xx/ebony.h
@@ -0,0 +1,91 @@
+/*
+ * arch/ppc/platforms/ebony.h
+ *
+ * Ebony board definitions
+ *
+ * Matt Porter <mporter@mvista.com>
+ *
+ * Copyright 2002 MontaVista Software Inc.
+ *
+ * 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.
+ */
+
+#ifdef __KERNEL__
+#ifndef __ASM_EBONY_H__
+#define __ASM_EBONY_H__
+
+#include <linux/config.h>
+#include <platforms/4xx/ibm440gp.h>
+
+/* F/W TLB mapping used in bootloader glue to reset EMAC */
+#define PPC44x_EMAC0_MR0 0xE0000800
+
+/* Where to find the MAC info */
+#define EBONY_OPENBIOS_MAC_BASE 0xfffffe0c
+#define EBONY_OPENBIOS_MAC_OFFSET 0x0c
+
+/* Default clock rates for Rev. B and Rev. C silicon */
+#define EBONY_440GP_RB_SYSCLK 33000000
+#define EBONY_440GP_RC_SYSCLK 400000000
+
+/* RTC/NVRAM location */
+#define EBONY_RTC_ADDR 0x0000000148000000ULL
+#define EBONY_RTC_SIZE 0x2000
+
+/* Flash */
+#define EBONY_FPGA_ADDR 0x0000000148300000ULL
+#define EBONY_BOOT_SMALL_FLASH(x) (x & 0x20)
+#define EBONY_ONBRD_FLASH_EN(x) (x & 0x02)
+#define EBONY_FLASH_SEL(x) (x & 0x01)
+#define EBONY_SMALL_FLASH_LOW1 0x00000001ff800000ULL
+#define EBONY_SMALL_FLASH_LOW2 0x00000001ff880000ULL
+#define EBONY_SMALL_FLASH_HIGH1 0x00000001fff00000ULL
+#define EBONY_SMALL_FLASH_HIGH2 0x00000001fff80000ULL
+#define EBONY_SMALL_FLASH_SIZE 0x80000
+#define EBONY_LARGE_FLASH_LOW 0x00000001ff800000ULL
+#define EBONY_LARGE_FLASH_HIGH 0x00000001ffc00000ULL
+#define EBONY_LARGE_FLASH_SIZE 0x400000
+
+#define EBONY_SMALL_FLASH_BASE 0x00000001fff80000ULL
+#define EBONY_LARGE_FLASH_BASE 0x00000001ff800000ULL
+
+/*
+ * Serial port defines
+ */
+
+/* OpenBIOS defined UART mappings, used before early_serial_setup */
+#define UART0_IO_BASE 0xE0000200
+#define UART1_IO_BASE 0xE0000300
+
+/* external Epson SG-615P */
+#define BASE_BAUD 691200
+
+#define STD_UART_OP(num) \
+ { 0, BASE_BAUD, 0, UART##num##_INT, \
+ (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST), \
+ iomem_base: UART##num##_IO_BASE, \
+ io_type: SERIAL_IO_MEM},
+
+#define SERIAL_PORT_DFNS \
+ STD_UART_OP(0) \
+ STD_UART_OP(1)
+
+/* PCI support */
+#define EBONY_PCI_LOWER_IO 0x00000000
+#define EBONY_PCI_UPPER_IO 0x0000ffff
+#define EBONY_PCI_LOWER_MEM 0x80002000
+#define EBONY_PCI_UPPER_MEM 0xffffefff
+
+#define EBONY_PCI_CFGREGS_BASE 0x000000020ec00000
+#define EBONY_PCI_CFGA_PLB32 0x0ec00000
+#define EBONY_PCI_CFGD_PLB32 0x0ec00004
+
+#define EBONY_PCI_IO_BASE 0x0000000208000000ULL
+#define EBONY_PCI_IO_SIZE 0x00010000
+#define EBONY_PCI_MEM_OFFSET 0x00000000
+
+#endif /* __ASM_EBONY_H__ */
+#endif /* __KERNEL__ */
diff --git a/arch/ppc/platforms/4xx/ep405.c b/arch/ppc/platforms/4xx/ep405.c
new file mode 100644
index 0000000..26a07cd
--- /dev/null
+++ b/arch/ppc/platforms/4xx/ep405.c
@@ -0,0 +1,197 @@
+/*
+ * arch/ppc/platforms/4xx/ep405.c
+ *
+ * Embedded Planet 405GP board
+ * http://www.embeddedplanet.com
+ *
+ * Author: Matthew Locke <mlocke@mvista.com>
+ *
+ * 2001 (c) MontaVista, Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <asm/system.h>
+#include <asm/pci-bridge.h>
+#include <asm/machdep.h>
+#include <asm/todc.h>
+#include <asm/ocp.h>
+#include <asm/ibm_ocp_pci.h>
+
+#undef DEBUG
+#ifdef DEBUG
+#define DBG(x...) printk(x)
+#else
+#define DBG(x...)
+#endif
+
+u8 *ep405_bcsr;
+u8 *ep405_nvram;
+
+static struct {
+ u8 cpld_xirq_select;
+ int pci_idsel;
+ int irq;
+} ep405_devtable[] = {
+#ifdef CONFIG_EP405PC
+ {0x07, 0x0E, 25}, /* EP405PC: USB */
+#endif
+};
+
+int __init
+ppc405_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin)
+{
+ int i;
+
+ /* AFAICT this is only called a few times during PCI setup, so
+ performance is not critical */
+ for (i = 0; i < ARRAY_SIZE(ep405_devtable); i++) {
+ if (idsel == ep405_devtable[i].pci_idsel)
+ return ep405_devtable[i].irq;
+ }
+ return -1;
+};
+
+void __init
+ep405_setup_arch(void)
+{
+ ppc4xx_setup_arch();
+
+ ibm_ocp_set_emac(0, 0);
+
+ if (__res.bi_nvramsize == 512*1024) {
+ /* FIXME: we should properly handle NVRTCs of different sizes */
+ TODC_INIT(TODC_TYPE_DS1557, ep405_nvram, ep405_nvram, ep405_nvram, 8);
+ }
+}
+
+void __init
+bios_fixup(struct pci_controller *hose, struct pcil0_regs *pcip)
+{
+ unsigned int bar_response, bar;
+ /*
+ * Expected PCI mapping:
+ *
+ * PLB addr PCI memory addr
+ * --------------------- ---------------------
+ * 0000'0000 - 7fff'ffff <--- 0000'0000 - 7fff'ffff
+ * 8000'0000 - Bfff'ffff ---> 8000'0000 - Bfff'ffff
+ *
+ * PLB addr PCI io addr
+ * --------------------- ---------------------
+ * e800'0000 - e800'ffff ---> 0000'0000 - 0001'0000
+ *
+ */
+
+ /* Disable region zero first */
+ out_le32((void *) &(pcip->pmm[0].ma), 0x00000000);
+ /* PLB starting addr, PCI: 0x80000000 */
+ out_le32((void *) &(pcip->pmm[0].la), 0x80000000);
+ /* PCI start addr, 0x80000000 */
+ out_le32((void *) &(pcip->pmm[0].pcila), PPC405_PCI_MEM_BASE);
+ /* 512MB range of PLB to PCI */
+ out_le32((void *) &(pcip->pmm[0].pciha), 0x00000000);
+ /* Enable no pre-fetch, enable region */
+ out_le32((void *) &(pcip->pmm[0].ma), ((0xffffffff -
+ (PPC405_PCI_UPPER_MEM -
+ PPC405_PCI_MEM_BASE)) | 0x01));
+
+ /* Disable region one */
+ out_le32((void *) &(pcip->pmm[1].ma), 0x00000000);
+ out_le32((void *) &(pcip->pmm[1].la), 0x00000000);
+ out_le32((void *) &(pcip->pmm[1].pcila), 0x00000000);
+ out_le32((void *) &(pcip->pmm[1].pciha), 0x00000000);
+ out_le32((void *) &(pcip->pmm[1].ma), 0x00000000);
+ out_le32((void *) &(pcip->ptm1ms), 0x00000000);
+
+ /* Disable region two */
+ out_le32((void *) &(pcip->pmm[2].ma), 0x00000000);
+ out_le32((void *) &(pcip->pmm[2].la), 0x00000000);
+ out_le32((void *) &(pcip->pmm[2].pcila), 0x00000000);
+ out_le32((void *) &(pcip->pmm[2].pciha), 0x00000000);
+ out_le32((void *) &(pcip->pmm[2].ma), 0x00000000);
+ out_le32((void *) &(pcip->ptm2ms), 0x00000000);
+
+ /* Configure PTM (PCI->PLB) region 1 */
+ out_le32((void *) &(pcip->ptm1la), 0x00000000); /* PLB base address */
+ /* Disable PTM region 2 */
+ out_le32((void *) &(pcip->ptm2ms), 0x00000000);
+
+ /* Zero config bars */
+ for (bar = PCI_BASE_ADDRESS_1; bar <= PCI_BASE_ADDRESS_2; bar += 4) {
+ early_write_config_dword(hose, hose->first_busno,
+ PCI_FUNC(hose->first_busno), bar,
+ 0x00000000);
+ early_read_config_dword(hose, hose->first_busno,
+ PCI_FUNC(hose->first_busno), bar,
+ &bar_response);
+ DBG("BUS %d, device %d, Function %d bar 0x%8.8x is 0x%8.8x\n",
+ hose->first_busno, PCI_SLOT(hose->first_busno),
+ PCI_FUNC(hose->first_busno), bar, bar_response);
+ }
+ /* end work arround */
+}
+
+void __init
+ep405_map_io(void)
+{
+ bd_t *bip = &__res;
+
+ ppc4xx_map_io();
+
+ ep405_bcsr = ioremap(EP405_BCSR_PADDR, EP405_BCSR_SIZE);
+
+ if (bip->bi_nvramsize > 0) {
+ ep405_nvram = ioremap(EP405_NVRAM_PADDR, bip->bi_nvramsize);
+ }
+}
+
+void __init
+ep405_init_IRQ(void)
+{
+ int i;
+
+ ppc4xx_init_IRQ();
+
+ /* Workaround for a bug in the firmware it incorrectly sets
+ the IRQ polarities for XIRQ0 and XIRQ1 */
+ mtdcr(DCRN_UIC_PR(DCRN_UIC0_BASE), 0xffffff80); /* set the polarity */
+ mtdcr(DCRN_UIC_SR(DCRN_UIC0_BASE), 0x00000060); /* clear bogus interrupts */
+
+ /* Activate the XIRQs from the CPLD */
+ writeb(0xf0, ep405_bcsr+10);
+
+ /* Set up IRQ routing */
+ for (i = 0; i < ARRAY_SIZE(ep405_devtable); i++) {
+ if ( (ep405_devtable[i].irq >= 25)
+ && (ep405_devtable[i].irq) <= 31) {
+ writeb(ep405_devtable[i].cpld_xirq_select, ep405_bcsr+5);
+ writeb(ep405_devtable[i].irq - 25, ep405_bcsr+6);
+ }
+ }
+}
+
+void __init
+platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
+ unsigned long r6, unsigned long r7)
+{
+ ppc4xx_init(r3, r4, r5, r6, r7);
+
+ ppc_md.setup_arch = ep405_setup_arch;
+ ppc_md.setup_io_mappings = ep405_map_io;
+ ppc_md.init_IRQ = ep405_init_IRQ;
+
+ ppc_md.nvram_read_val = todc_direct_read_val;
+ ppc_md.nvram_write_val = todc_direct_write_val;
+
+ if (__res.bi_nvramsize == 512*1024) {
+ ppc_md.time_init = todc_time_init;
+ ppc_md.set_rtc_time = todc_set_rtc_time;
+ ppc_md.get_rtc_time = todc_get_rtc_time;
+ } else {
+ printk("EP405: NVRTC size is not 512k (not a DS1557). Not sure what to do with it\n");
+ }
+}
diff --git a/arch/ppc/platforms/4xx/ep405.h b/arch/ppc/platforms/4xx/ep405.h
new file mode 100644
index 0000000..ea3eb21
--- /dev/null
+++ b/arch/ppc/platforms/4xx/ep405.h
@@ -0,0 +1,54 @@
+/*
+ * arch/ppc/platforms/4xx/ep405.h
+ *
+ * Embedded Planet 405GP board
+ * http://www.embeddedplanet.com
+ *
+ * Author: Matthew Locke <mlocke@mvista.com>
+ *
+ * 2000 (c) MontaVista, Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+
+#ifdef __KERNEL__
+#ifndef __ASM_EP405_H__
+#define __ASM_EP405_H__
+
+/* We have a 405GP core */
+#include <platforms/4xx/ibm405gp.h>
+
+#ifndef __ASSEMBLY__
+
+#include <linux/types.h>
+
+typedef struct board_info {
+ unsigned int bi_memsize; /* DRAM installed, in bytes */
+ unsigned char bi_enetaddr[6]; /* Local Ethernet MAC address */
+ unsigned int bi_intfreq; /* Processor speed, in Hz */
+ unsigned int bi_busfreq; /* PLB Bus speed, in Hz */
+ unsigned int bi_pci_busfreq; /* PCI Bus speed, in Hz */
+ unsigned int bi_nvramsize; /* Size of the NVRAM/RTC */
+} bd_t;
+
+/* Some 4xx parts use a different timebase frequency from the internal clock.
+*/
+#define bi_tbfreq bi_intfreq
+
+extern u8 *ep405_bcsr;
+extern u8 *ep405_nvram;
+
+/* Map for the BCSR and NVRAM space */
+#define EP405_BCSR_PADDR ((uint)0xf4000000)
+#define EP405_BCSR_SIZE ((uint)16)
+#define EP405_NVRAM_PADDR ((uint)0xf4200000)
+
+/* serial defines */
+#define BASE_BAUD 399193
+
+#define PPC4xx_MACHINE_NAME "Embedded Planet 405GP"
+
+#endif /* !__ASSEMBLY__ */
+#endif /* __ASM_EP405_H__ */
+#endif /* __KERNEL__ */
diff --git a/arch/ppc/platforms/4xx/ibm405ep.c b/arch/ppc/platforms/4xx/ibm405ep.c
new file mode 100644
index 0000000..6d44567
--- /dev/null
+++ b/arch/ppc/platforms/4xx/ibm405ep.c
@@ -0,0 +1,143 @@
+/*
+ * arch/ppc/platforms/ibm405ep.c
+ *
+ * Support for IBM PPC 405EP processors.
+ *
+ * Author: SAW (IBM), derived from ibmnp405l.c.
+ * Maintained by MontaVista Software <source@mvista.com>
+ *
+ * 2003 (c) MontaVista Softare Inc. This file is licensed under the
+ * terms of the GNU General Public License version 2. This program is
+ * licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/smp.h>
+#include <linux/threads.h>
+#include <linux/param.h>
+#include <linux/string.h>
+
+#include <asm/ibm4xx.h>
+#include <asm/ocp.h>
+#include <asm/ppc4xx_pic.h>
+
+#include <platforms/4xx/ibm405ep.h>
+
+static struct ocp_func_mal_data ibm405ep_mal0_def = {
+ .num_tx_chans = 4, /* Number of TX channels */
+ .num_rx_chans = 2, /* Number of RX channels */
+ .txeob_irq = 11, /* TX End Of Buffer IRQ */
+ .rxeob_irq = 12, /* RX End Of Buffer IRQ */
+ .txde_irq = 13, /* TX Descriptor Error IRQ */
+ .rxde_irq = 14, /* RX Descriptor Error IRQ */
+ .serr_irq = 10, /* MAL System Error IRQ */
+};
+OCP_SYSFS_MAL_DATA()
+
+static struct ocp_func_emac_data ibm405ep_emac0_def = {
+ .rgmii_idx = -1, /* No RGMII */
+ .rgmii_mux = -1, /* No RGMII */
+ .zmii_idx = -1, /* ZMII device index */
+ .zmii_mux = 0, /* ZMII input of this EMAC */
+ .mal_idx = 0, /* MAL device index */
+ .mal_rx_chan = 0, /* MAL rx channel number */
+ .mal_tx_chan = 0, /* MAL tx channel number */
+ .wol_irq = 9, /* WOL interrupt number */
+ .mdio_idx = 0, /* MDIO via EMAC0 */
+ .tah_idx = -1, /* No TAH */
+};
+
+static struct ocp_func_emac_data ibm405ep_emac1_def = {
+ .rgmii_idx = -1, /* No RGMII */
+ .rgmii_mux = -1, /* No RGMII */
+ .zmii_idx = -1, /* ZMII device index */
+ .zmii_mux = 0, /* ZMII input of this EMAC */
+ .mal_idx = 0, /* MAL device index */
+ .mal_rx_chan = 1, /* MAL rx channel number */
+ .mal_tx_chan = 2, /* MAL tx channel number */
+ .wol_irq = 9, /* WOL interrupt number */
+ .mdio_idx = 0, /* MDIO via EMAC0 */
+ .tah_idx = -1, /* No TAH */
+};
+OCP_SYSFS_EMAC_DATA()
+
+static struct ocp_func_iic_data ibm405ep_iic0_def = {
+ .fast_mode = 0, /* Use standad mode (100Khz) */
+};
+OCP_SYSFS_IIC_DATA()
+
+struct ocp_def core_ocp[] = {
+ { .vendor = OCP_VENDOR_IBM,
+ .function = OCP_FUNC_OPB,
+ .index = 0,
+ .paddr = 0xEF600000,
+ .irq = OCP_IRQ_NA,
+ .pm = OCP_CPM_NA,
+ },
+ { .vendor = OCP_VENDOR_IBM,
+ .function = OCP_FUNC_16550,
+ .index = 0,
+ .paddr = UART0_IO_BASE,
+ .irq = UART0_INT,
+ .pm = IBM_CPM_UART0
+ },
+ { .vendor = OCP_VENDOR_IBM,
+ .function = OCP_FUNC_16550,
+ .index = 1,
+ .paddr = UART1_IO_BASE,
+ .irq = UART1_INT,
+ .pm = IBM_CPM_UART1
+ },
+ { .vendor = OCP_VENDOR_IBM,
+ .function = OCP_FUNC_IIC,
+ .paddr = 0xEF600500,
+ .irq = 2,
+ .pm = IBM_CPM_IIC0,
+ .additions = &ibm405ep_iic0_def,
+ .show = &ocp_show_iic_data
+ },
+ { .vendor = OCP_VENDOR_IBM,
+ .function = OCP_FUNC_GPIO,
+ .paddr = 0xEF600700,
+ .irq = OCP_IRQ_NA,
+ .pm = IBM_CPM_GPIO0
+ },
+ { .vendor = OCP_VENDOR_IBM,
+ .function = OCP_FUNC_MAL,
+ .paddr = OCP_PADDR_NA,
+ .irq = OCP_IRQ_NA,
+ .pm = OCP_CPM_NA,
+ .additions = &ibm405ep_mal0_def,
+ .show = &ocp_show_mal_data
+ },
+ { .vendor = OCP_VENDOR_IBM,
+ .function = OCP_FUNC_EMAC,
+ .index = 0,
+ .paddr = EMAC0_BASE,
+ .irq = 15,
+ .pm = OCP_CPM_NA,
+ .additions = &ibm405ep_emac0_def,
+ .show = &ocp_show_emac_data
+ },
+ { .vendor = OCP_VENDOR_IBM,
+ .function = OCP_FUNC_EMAC,
+ .index = 1,
+ .paddr = 0xEF600900,
+ .irq = 17,
+ .pm = OCP_CPM_NA,
+ .additions = &ibm405ep_emac1_def,
+ .show = &ocp_show_emac_data
+ },
+ { .vendor = OCP_VENDOR_INVALID
+ }
+};
+
+/* Polarity and triggering settings for internal interrupt sources */
+struct ppc4xx_uic_settings ppc4xx_core_uic_cfg[] __initdata = {
+ { .polarity = 0xffff7f80,
+ .triggering = 0x00000000,
+ .ext_irq_mask = 0x0000007f, /* IRQ0 - IRQ6 */
+ }
+};
diff --git a/arch/ppc/platforms/4xx/ibm405ep.h b/arch/ppc/platforms/4xx/ibm405ep.h
new file mode 100644
index 0000000..e051e3f
--- /dev/null
+++ b/arch/ppc/platforms/4xx/ibm405ep.h
@@ -0,0 +1,148 @@
+/*
+ * arch/ppc/platforms/4xx/ibm405ep.h
+ *
+ * IBM PPC 405EP processor defines.
+ *
+ * Author: SAW (IBM), derived from ibm405gp.h.
+ * Maintained by MontaVista Software <source@mvista.com>
+ *
+ * 2003 (c) MontaVista Softare Inc. This file is licensed under the
+ * terms of the GNU General Public License version 2. This program is
+ * licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+
+#ifdef __KERNEL__
+#ifndef __ASM_IBM405EP_H__
+#define __ASM_IBM405EP_H__
+
+#include <linux/config.h>
+
+/* ibm405.h at bottom of this file */
+
+/* PCI
+ * PCI Bridge config reg definitions
+ * see 17-19 of manual
+ */
+
+#define PPC405_PCI_CONFIG_ADDR 0xeec00000
+#define PPC405_PCI_CONFIG_DATA 0xeec00004
+
+#define PPC405_PCI_PHY_MEM_BASE 0x80000000 /* hose_a->pci_mem_offset */
+ /* setbat */
+#define PPC405_PCI_MEM_BASE PPC405_PCI_PHY_MEM_BASE /* setbat */
+#define PPC405_PCI_PHY_IO_BASE 0xe8000000 /* setbat */
+#define PPC405_PCI_IO_BASE PPC405_PCI_PHY_IO_BASE /* setbat */
+
+#define PPC405_PCI_LOWER_MEM 0x80000000 /* hose_a->mem_space.start */
+#define PPC405_PCI_UPPER_MEM 0xBfffffff /* hose_a->mem_space.end */
+#define PPC405_PCI_LOWER_IO 0x00000000 /* hose_a->io_space.start */
+#define PPC405_PCI_UPPER_IO 0x0000ffff /* hose_a->io_space.end */
+
+#define PPC405_ISA_IO_BASE PPC405_PCI_IO_BASE
+
+#define PPC4xx_PCI_IO_PADDR ((uint)PPC405_PCI_PHY_IO_BASE)
+#define PPC4xx_PCI_IO_VADDR PPC4xx_PCI_IO_PADDR
+#define PPC4xx_PCI_IO_SIZE ((uint)64*1024)
+#define PPC4xx_PCI_CFG_PADDR ((uint)PPC405_PCI_CONFIG_ADDR)
+#define PPC4xx_PCI_CFG_VADDR PPC4xx_PCI_CFG_PADDR
+#define PPC4xx_PCI_CFG_SIZE ((uint)4*1024)
+#define PPC4xx_PCI_LCFG_PADDR ((uint)0xef400000)
+#define PPC4xx_PCI_LCFG_VADDR PPC4xx_PCI_LCFG_PADDR
+#define PPC4xx_PCI_LCFG_SIZE ((uint)4*1024)
+#define PPC4xx_ONB_IO_PADDR ((uint)0xef600000)
+#define PPC4xx_ONB_IO_VADDR PPC4xx_ONB_IO_PADDR
+#define PPC4xx_ONB_IO_SIZE ((uint)4*1024)
+
+/* serial port defines */
+#define RS_TABLE_SIZE 2
+
+#define UART0_INT 0
+#define UART1_INT 1
+
+#define PCIL0_BASE 0xEF400000
+#define UART0_IO_BASE 0xEF600300
+#define UART1_IO_BASE 0xEF600400
+#define EMAC0_BASE 0xEF600800
+
+#define BD_EMAC_ADDR(e,i) bi_enetaddr[e][i]
+
+#if defined(CONFIG_UART0_TTYS0)
+#define ACTING_UART0_IO_BASE UART0_IO_BASE
+#define ACTING_UART1_IO_BASE UART1_IO_BASE
+#define ACTING_UART0_INT UART0_INT
+#define ACTING_UART1_INT UART1_INT
+#else
+#define ACTING_UART0_IO_BASE UART1_IO_BASE
+#define ACTING_UART1_IO_BASE UART0_IO_BASE
+#define ACTING_UART0_INT UART1_INT
+#define ACTING_UART1_INT UART0_INT
+#endif
+
+#define STD_UART_OP(num) \
+ { 0, BASE_BAUD, 0, ACTING_UART##num##_INT, \
+ (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST), \
+ iomem_base: (u8 *)ACTING_UART##num##_IO_BASE, \
+ io_type: SERIAL_IO_MEM},
+
+#define SERIAL_DEBUG_IO_BASE ACTING_UART0_IO_BASE
+#define SERIAL_PORT_DFNS \
+ STD_UART_OP(0) \
+ STD_UART_OP(1)
+
+/* DCR defines */
+#define DCRN_CPMSR_BASE 0x0BA
+#define DCRN_CPMFR_BASE 0x0B9
+
+#define DCRN_CPC0_PLLMR0_BASE 0x0F0
+#define DCRN_CPC0_BOOT_BASE 0x0F1
+#define DCRN_CPC0_CR1_BASE 0x0F2
+#define DCRN_CPC0_EPRCSR_BASE 0x0F3
+#define DCRN_CPC0_PLLMR1_BASE 0x0F4
+#define DCRN_CPC0_UCR_BASE 0x0F5
+#define DCRN_CPC0_UCR_U0DIV 0x07F
+#define DCRN_CPC0_SRR_BASE 0x0F6
+#define DCRN_CPC0_JTAGID_BASE 0x0F7
+#define DCRN_CPC0_SPARE_BASE 0x0F8
+#define DCRN_CPC0_PCI_BASE 0x0F9
+
+
+#define IBM_CPM_GPT 0x80000000 /* GPT interface */
+#define IBM_CPM_PCI 0x40000000 /* PCI bridge */
+#define IBM_CPM_UIC 0x00010000 /* Universal Int Controller */
+#define IBM_CPM_CPU 0x00008000 /* processor core */
+#define IBM_CPM_EBC 0x00002000 /* EBC controller */
+#define IBM_CPM_SDRAM0 0x00004000 /* SDRAM memory controller */
+#define IBM_CPM_GPIO0 0x00001000 /* General Purpose IO */
+#define IBM_CPM_TMRCLK 0x00000400 /* CPU timers */
+#define IBM_CPM_PLB 0x00000100 /* PLB bus arbiter */
+#define IBM_CPM_OPB 0x00000080 /* PLB to OPB bridge */
+#define IBM_CPM_DMA 0x00000040 /* DMA controller */
+#define IBM_CPM_IIC0 0x00000010 /* IIC interface */
+#define IBM_CPM_UART1 0x00000002 /* serial port 0 */
+#define IBM_CPM_UART0 0x00000001 /* serial port 1 */
+#define DFLT_IBM4xx_PM ~(IBM_CPM_PCI | IBM_CPM_CPU | IBM_CPM_DMA \
+ | IBM_CPM_OPB | IBM_CPM_EBC \
+ | IBM_CPM_SDRAM0 | IBM_CPM_PLB \
+ | IBM_CPM_UIC | IBM_CPM_TMRCLK)
+#define DCRN_DMA0_BASE 0x100
+#define DCRN_DMA1_BASE 0x108
+#define DCRN_DMA2_BASE 0x110
+#define DCRN_DMA3_BASE 0x118
+#define DCRNCAP_DMA_SG 1 /* have DMA scatter/gather capability */
+#define DCRN_DMASR_BASE 0x120
+#define DCRN_EBC_BASE 0x012
+#define DCRN_DCP0_BASE 0x014
+#define DCRN_MAL_BASE 0x180
+#define DCRN_OCM0_BASE 0x018
+#define DCRN_PLB0_BASE 0x084
+#define DCRN_PLLMR_BASE 0x0B0
+#define DCRN_POB0_BASE 0x0A0
+#define DCRN_SDRAM0_BASE 0x010
+#define DCRN_UIC0_BASE 0x0C0
+#define UIC0 DCRN_UIC0_BASE
+
+#include <asm/ibm405.h>
+
+#endif /* __ASM_IBM405EP_H__ */
+#endif /* __KERNEL__ */
diff --git a/arch/ppc/platforms/4xx/ibm405gp.c b/arch/ppc/platforms/4xx/ibm405gp.c
new file mode 100644
index 0000000..dfd7ef3
--- /dev/null
+++ b/arch/ppc/platforms/4xx/ibm405gp.c
@@ -0,0 +1,120 @@
+/*
+ *
+ * Copyright 2000-2001 MontaVista Software Inc.
+ * Original author: Armin Kuster akuster@mvista.com
+ *
+ * Module name: ibm405gp.c
+ *
+ *
+ * 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.
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/smp.h>
+#include <linux/threads.h>
+#include <linux/param.h>
+#include <linux/string.h>
+#include <platforms/4xx/ibm405gp.h>
+#include <asm/ibm4xx.h>
+#include <asm/ocp.h>
+#include <asm/ppc4xx_pic.h>
+
+static struct ocp_func_emac_data ibm405gp_emac0_def = {
+ .rgmii_idx = -1, /* No RGMII */
+ .rgmii_mux = -1, /* No RGMII */
+ .zmii_idx = -1, /* ZMII device index */
+ .zmii_mux = 0, /* ZMII input of this EMAC */
+ .mal_idx = 0, /* MAL device index */
+ .mal_rx_chan = 0, /* MAL rx channel number */
+ .mal_tx_chan = 0, /* MAL tx channel number */
+ .wol_irq = 9, /* WOL interrupt number */
+ .mdio_idx = -1, /* No shared MDIO */
+ .tah_idx = -1, /* No TAH */
+};
+OCP_SYSFS_EMAC_DATA()
+
+static struct ocp_func_mal_data ibm405gp_mal0_def = {
+ .num_tx_chans = 1, /* Number of TX channels */
+ .num_rx_chans = 1, /* Number of RX channels */
+ .txeob_irq = 11, /* TX End Of Buffer IRQ */
+ .rxeob_irq = 12, /* RX End Of Buffer IRQ */
+ .txde_irq = 13, /* TX Descriptor Error IRQ */
+ .rxde_irq = 14, /* RX Descriptor Error IRQ */
+ .serr_irq = 10, /* MAL System Error IRQ */
+};
+OCP_SYSFS_MAL_DATA()
+
+static struct ocp_func_iic_data ibm405gp_iic0_def = {
+ .fast_mode = 0, /* Use standad mode (100Khz) */
+};
+OCP_SYSFS_IIC_DATA()
+
+struct ocp_def core_ocp[] = {
+ { .vendor = OCP_VENDOR_IBM,
+ .function = OCP_FUNC_OPB,
+ .index = 0,
+ .paddr = 0xEF600000,
+ .irq = OCP_IRQ_NA,
+ .pm = OCP_CPM_NA,
+ },
+ { .vendor = OCP_VENDOR_IBM,
+ .function = OCP_FUNC_16550,
+ .index = 0,
+ .paddr = UART0_IO_BASE,
+ .irq = UART0_INT,
+ .pm = IBM_CPM_UART0
+ },
+ { .vendor = OCP_VENDOR_IBM,
+ .function = OCP_FUNC_16550,
+ .index = 1,
+ .paddr = UART1_IO_BASE,
+ .irq = UART1_INT,
+ .pm = IBM_CPM_UART1
+ },
+ { .vendor = OCP_VENDOR_IBM,
+ .function = OCP_FUNC_IIC,
+ .paddr = 0xEF600500,
+ .irq = 2,
+ .pm = IBM_CPM_IIC0,
+ .additions = &ibm405gp_iic0_def,
+ .show = &ocp_show_iic_data,
+ },
+ { .vendor = OCP_VENDOR_IBM,
+ .function = OCP_FUNC_GPIO,
+ .paddr = 0xEF600700,
+ .irq = OCP_IRQ_NA,
+ .pm = IBM_CPM_GPIO0
+ },
+ { .vendor = OCP_VENDOR_IBM,
+ .function = OCP_FUNC_MAL,
+ .paddr = OCP_PADDR_NA,
+ .irq = OCP_IRQ_NA,
+ .pm = OCP_CPM_NA,
+ .additions = &ibm405gp_mal0_def,
+ .show = &ocp_show_mal_data,
+ },
+ { .vendor = OCP_VENDOR_IBM,
+ .function = OCP_FUNC_EMAC,
+ .index = 0,
+ .paddr = EMAC0_BASE,
+ .irq = 15,
+ .pm = IBM_CPM_EMAC0,
+ .additions = &ibm405gp_emac0_def,
+ .show = &ocp_show_emac_data,
+ },
+ { .vendor = OCP_VENDOR_INVALID
+ }
+};
+
+/* Polarity and triggering settings for internal interrupt sources */
+struct ppc4xx_uic_settings ppc4xx_core_uic_cfg[] __initdata = {
+ { .polarity = 0xffffff80,
+ .triggering = 0x10000000,
+ .ext_irq_mask = 0x0000007f, /* IRQ0 - IRQ6 */
+ }
+};
diff --git a/arch/ppc/platforms/4xx/ibm405gp.h b/arch/ppc/platforms/4xx/ibm405gp.h
new file mode 100644
index 0000000..b2b642e
--- /dev/null
+++ b/arch/ppc/platforms/4xx/ibm405gp.h
@@ -0,0 +1,151 @@
+/*
+ * arch/ppc/platforms/4xx/ibm405gp.h
+ *
+ * Author: Armin Kuster akuster@mvista.com
+ *
+ * 2001 (c) MontaVista, Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+
+#ifdef __KERNEL__
+#ifndef __ASM_IBM405GP_H__
+#define __ASM_IBM405GP_H__
+
+#include <linux/config.h>
+
+/* ibm405.h at bottom of this file */
+
+/* PCI
+ * PCI Bridge config reg definitions
+ * see 17-19 of manual
+ */
+
+#define PPC405_PCI_CONFIG_ADDR 0xeec00000
+#define PPC405_PCI_CONFIG_DATA 0xeec00004
+
+#define PPC405_PCI_PHY_MEM_BASE 0x80000000 /* hose_a->pci_mem_offset */
+ /* setbat */
+#define PPC405_PCI_MEM_BASE PPC405_PCI_PHY_MEM_BASE /* setbat */
+#define PPC405_PCI_PHY_IO_BASE 0xe8000000 /* setbat */
+#define PPC405_PCI_IO_BASE PPC405_PCI_PHY_IO_BASE /* setbat */
+
+#define PPC405_PCI_LOWER_MEM 0x80000000 /* hose_a->mem_space.start */
+#define PPC405_PCI_UPPER_MEM 0xBfffffff /* hose_a->mem_space.end */
+#define PPC405_PCI_LOWER_IO 0x00000000 /* hose_a->io_space.start */
+#define PPC405_PCI_UPPER_IO 0x0000ffff /* hose_a->io_space.end */
+
+#define PPC405_ISA_IO_BASE PPC405_PCI_IO_BASE
+
+#define PPC4xx_PCI_IO_PADDR ((uint)PPC405_PCI_PHY_IO_BASE)
+#define PPC4xx_PCI_IO_VADDR PPC4xx_PCI_IO_PADDR
+#define PPC4xx_PCI_IO_SIZE ((uint)64*1024)
+#define PPC4xx_PCI_CFG_PADDR ((uint)PPC405_PCI_CONFIG_ADDR)
+#define PPC4xx_PCI_CFG_VADDR PPC4xx_PCI_CFG_PADDR
+#define PPC4xx_PCI_CFG_SIZE ((uint)4*1024)
+#define PPC4xx_PCI_LCFG_PADDR ((uint)0xef400000)
+#define PPC4xx_PCI_LCFG_VADDR PPC4xx_PCI_LCFG_PADDR
+#define PPC4xx_PCI_LCFG_SIZE ((uint)4*1024)
+#define PPC4xx_ONB_IO_PADDR ((uint)0xef600000)
+#define PPC4xx_ONB_IO_VADDR PPC4xx_ONB_IO_PADDR
+#define PPC4xx_ONB_IO_SIZE ((uint)4*1024)
+
+/* serial port defines */
+#define RS_TABLE_SIZE 2
+
+#define UART0_INT 0
+#define UART1_INT 1
+
+#define PCIL0_BASE 0xEF400000
+#define UART0_IO_BASE 0xEF600300
+#define UART1_IO_BASE 0xEF600400
+#define EMAC0_BASE 0xEF600800
+
+#define BD_EMAC_ADDR(e,i) bi_enetaddr[i]
+
+#define STD_UART_OP(num) \
+ { 0, BASE_BAUD, 0, UART##num##_INT, \
+ (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST), \
+ iomem_base: (u8 *)UART##num##_IO_BASE, \
+ io_type: SERIAL_IO_MEM},
+
+#if defined(CONFIG_UART0_TTYS0)
+#define SERIAL_DEBUG_IO_BASE UART0_IO_BASE
+#define SERIAL_PORT_DFNS \
+ STD_UART_OP(0) \
+ STD_UART_OP(1)
+#endif
+
+#if defined(CONFIG_UART0_TTYS1)
+#define SERIAL_DEBUG_IO_BASE UART1_IO_BASE
+#define SERIAL_PORT_DFNS \
+ STD_UART_OP(1) \
+ STD_UART_OP(0)
+#endif
+
+/* DCR defines */
+#define DCRN_CHCR_BASE 0x0B1
+#define DCRN_CHPSR_BASE 0x0B4
+#define DCRN_CPMSR_BASE 0x0B8
+#define DCRN_CPMFR_BASE 0x0BA
+
+#define CHR0_U0EC 0x00000080 /* Select external clock for UART0 */
+#define CHR0_U1EC 0x00000040 /* Select external clock for UART1 */
+#define CHR0_UDIV 0x0000003E /* UART internal clock divisor */
+#define CHR1_CETE 0x00800000 /* CPU external timer enable */
+
+#define DCRN_CHPSR_BASE 0x0B4
+#define PSR_PLL_FWD_MASK 0xC0000000
+#define PSR_PLL_FDBACK_MASK 0x30000000
+#define PSR_PLL_TUNING_MASK 0x0E000000
+#define PSR_PLB_CPU_MASK 0x01800000
+#define PSR_OPB_PLB_MASK 0x00600000
+#define PSR_PCI_PLB_MASK 0x00180000
+#define PSR_EB_PLB_MASK 0x00060000
+#define PSR_ROM_WIDTH_MASK 0x00018000
+#define PSR_ROM_LOC 0x00004000
+#define PSR_PCI_ASYNC_EN 0x00001000
+#define PSR_PCI_ARBIT_EN 0x00000400
+
+#define IBM_CPM_IIC0 0x80000000 /* IIC interface */
+#define IBM_CPM_PCI 0x40000000 /* PCI bridge */
+#define IBM_CPM_CPU 0x20000000 /* processor core */
+#define IBM_CPM_DMA 0x10000000 /* DMA controller */
+#define IBM_CPM_OPB 0x08000000 /* PLB to OPB bridge */
+#define IBM_CPM_DCP 0x04000000 /* CodePack */
+#define IBM_CPM_EBC 0x02000000 /* ROM/SRAM peripheral controller */
+#define IBM_CPM_SDRAM0 0x01000000 /* SDRAM memory controller */
+#define IBM_CPM_PLB 0x00800000 /* PLB bus arbiter */
+#define IBM_CPM_GPIO0 0x00400000 /* General Purpose IO (??) */
+#define IBM_CPM_UART0 0x00200000 /* serial port 0 */
+#define IBM_CPM_UART1 0x00100000 /* serial port 1 */
+#define IBM_CPM_UIC 0x00080000 /* Universal Interrupt Controller */
+#define IBM_CPM_TMRCLK 0x00040000 /* CPU timers */
+#define IBM_CPM_EMAC0 0x00020000 /* on-chip ethernet MM unit */
+#define DFLT_IBM4xx_PM ~(IBM_CPM_PCI | IBM_CPM_CPU | IBM_CPM_DMA \
+ | IBM_CPM_OPB | IBM_CPM_EBC \
+ | IBM_CPM_SDRAM0 | IBM_CPM_PLB \
+ | IBM_CPM_UIC | IBM_CPM_TMRCLK)
+
+#define DCRN_DMA0_BASE 0x100
+#define DCRN_DMA1_BASE 0x108
+#define DCRN_DMA2_BASE 0x110
+#define DCRN_DMA3_BASE 0x118
+#define DCRNCAP_DMA_SG 1 /* have DMA scatter/gather capability */
+#define DCRN_DMASR_BASE 0x120
+#define DCRN_EBC_BASE 0x012
+#define DCRN_DCP0_BASE 0x014
+#define DCRN_MAL_BASE 0x180
+#define DCRN_OCM0_BASE 0x018
+#define DCRN_PLB0_BASE 0x084
+#define DCRN_PLLMR_BASE 0x0B0
+#define DCRN_POB0_BASE 0x0A0
+#define DCRN_SDRAM0_BASE 0x010
+#define DCRN_UIC0_BASE 0x0C0
+#define UIC0 DCRN_UIC0_BASE
+
+#include <asm/ibm405.h>
+
+#endif /* __ASM_IBM405GP_H__ */
+#endif /* __KERNEL__ */
diff --git a/arch/ppc/platforms/4xx/ibm405gpr.c b/arch/ppc/platforms/4xx/ibm405gpr.c
new file mode 100644
index 0000000..01c8ccb
--- /dev/null
+++ b/arch/ppc/platforms/4xx/ibm405gpr.c
@@ -0,0 +1,117 @@
+/*
+ * arch/ppc/platforms/4xx/ibm405gpr.c
+ *
+ * Author: Armin Kuster <akuster@mvista.com>
+ *
+ * 2002 (c) MontaVista, Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/smp.h>
+#include <linux/threads.h>
+#include <linux/param.h>
+#include <linux/string.h>
+#include <platforms/4xx/ibm405gpr.h>
+#include <asm/ibm4xx.h>
+#include <asm/ocp.h>
+#include <asm/ppc4xx_pic.h>
+
+static struct ocp_func_emac_data ibm405gpr_emac0_def = {
+ .rgmii_idx = -1, /* No RGMII */
+ .rgmii_mux = -1, /* No RGMII */
+ .zmii_idx = -1, /* ZMII device index */
+ .zmii_mux = 0, /* ZMII input of this EMAC */
+ .mal_idx = 0, /* MAL device index */
+ .mal_rx_chan = 0, /* MAL rx channel number */
+ .mal_tx_chan = 0, /* MAL tx channel number */
+ .wol_irq = 9, /* WOL interrupt number */
+ .mdio_idx = -1, /* No shared MDIO */
+ .tah_idx = -1, /* No TAH */
+};
+OCP_SYSFS_EMAC_DATA()
+
+static struct ocp_func_mal_data ibm405gpr_mal0_def = {
+ .num_tx_chans = 1, /* Number of TX channels */
+ .num_rx_chans = 1, /* Number of RX channels */
+ .txeob_irq = 11, /* TX End Of Buffer IRQ */
+ .rxeob_irq = 12, /* RX End Of Buffer IRQ */
+ .txde_irq = 13, /* TX Descriptor Error IRQ */
+ .rxde_irq = 14, /* RX Descriptor Error IRQ */
+ .serr_irq = 10, /* MAL System Error IRQ */
+};
+OCP_SYSFS_MAL_DATA()
+
+static struct ocp_func_iic_data ibm405gpr_iic0_def = {
+ .fast_mode = 0, /* Use standad mode (100Khz) */
+};
+
+OCP_SYSFS_IIC_DATA()
+
+struct ocp_def core_ocp[] = {
+ { .vendor = OCP_VENDOR_IBM,
+ .function = OCP_FUNC_OPB,
+ .index = 0,
+ .paddr = 0xEF600000,
+ .irq = OCP_IRQ_NA,
+ .pm = OCP_CPM_NA,
+ },
+ { .vendor = OCP_VENDOR_IBM,
+ .function = OCP_FUNC_16550,
+ .index = 0,
+ .paddr = UART0_IO_BASE,
+ .irq = UART0_INT,
+ .pm = IBM_CPM_UART0
+ },
+ { .vendor = OCP_VENDOR_IBM,
+ .function = OCP_FUNC_16550,
+ .index = 1,
+ .paddr = UART1_IO_BASE,
+ .irq = UART1_INT,
+ .pm = IBM_CPM_UART1
+ },
+ { .vendor = OCP_VENDOR_IBM,
+ .function = OCP_FUNC_IIC,
+ .paddr = 0xEF600500,
+ .irq = 2,
+ .pm = IBM_CPM_IIC0,
+ .additions = &ibm405gpr_iic0_def,
+ .show = &ocp_show_iic_data,
+ },
+ { .vendor = OCP_VENDOR_IBM,
+ .function = OCP_FUNC_GPIO,
+ .paddr = 0xEF600700,
+ .irq = OCP_IRQ_NA,
+ .pm = IBM_CPM_GPIO0
+ },
+ { .vendor = OCP_VENDOR_IBM,
+ .function = OCP_FUNC_MAL,
+ .paddr = OCP_PADDR_NA,
+ .irq = OCP_IRQ_NA,
+ .pm = OCP_CPM_NA,
+ .additions = &ibm405gpr_mal0_def,
+ .show = &ocp_show_mal_data,
+ },
+ { .vendor = OCP_VENDOR_IBM,
+ .function = OCP_FUNC_EMAC,
+ .index = 0,
+ .paddr = EMAC0_BASE,
+ .irq = 15,
+ .pm = IBM_CPM_EMAC0,
+ .additions = &ibm405gpr_emac0_def,
+ .show = &ocp_show_emac_data,
+ },
+ { .vendor = OCP_VENDOR_INVALID
+ }
+};
+
+/* Polarity and triggering settings for internal interrupt sources */
+struct ppc4xx_uic_settings ppc4xx_core_uic_cfg[] __initdata = {
+ { .polarity = 0xffffe000,
+ .triggering = 0x10000000,
+ .ext_irq_mask = 0x00001fff, /* IRQ7 - IRQ12, IRQ0 - IRQ6 */
+ }
+};
diff --git a/arch/ppc/platforms/4xx/ibm405gpr.h b/arch/ppc/platforms/4xx/ibm405gpr.h
new file mode 100644
index 0000000..45412fb
--- /dev/null
+++ b/arch/ppc/platforms/4xx/ibm405gpr.h
@@ -0,0 +1,151 @@
+/*
+ * arch/ppc/platforms/4xx/ibm405gpr.h
+ *
+ * Author: Armin Kuster <akuster@mvista.com>
+ *
+ * 2002 (c) MontaVista, Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+
+#ifdef __KERNEL__
+#ifndef __ASM_IBM405GPR_H__
+#define __ASM_IBM405GPR_H__
+
+#include <linux/config.h>
+
+/* ibm405.h at bottom of this file */
+
+/* PCI
+ * PCI Bridge config reg definitions
+ * see 17-19 of manual
+ */
+
+#define PPC405_PCI_CONFIG_ADDR 0xeec00000
+#define PPC405_PCI_CONFIG_DATA 0xeec00004
+
+#define PPC405_PCI_PHY_MEM_BASE 0x80000000 /* hose_a->pci_mem_offset */
+ /* setbat */
+#define PPC405_PCI_MEM_BASE PPC405_PCI_PHY_MEM_BASE /* setbat */
+#define PPC405_PCI_PHY_IO_BASE 0xe8000000 /* setbat */
+#define PPC405_PCI_IO_BASE PPC405_PCI_PHY_IO_BASE /* setbat */
+
+#define PPC405_PCI_LOWER_MEM 0x80000000 /* hose_a->mem_space.start */
+#define PPC405_PCI_UPPER_MEM 0xBfffffff /* hose_a->mem_space.end */
+#define PPC405_PCI_LOWER_IO 0x00000000 /* hose_a->io_space.start */
+#define PPC405_PCI_UPPER_IO 0x0000ffff /* hose_a->io_space.end */
+
+#define PPC405_ISA_IO_BASE PPC405_PCI_IO_BASE
+
+#define PPC4xx_PCI_IO_PADDR ((uint)PPC405_PCI_PHY_IO_BASE)
+#define PPC4xx_PCI_IO_VADDR PPC4xx_PCI_IO_PADDR
+#define PPC4xx_PCI_IO_SIZE ((uint)64*1024)
+#define PPC4xx_PCI_CFG_PADDR ((uint)PPC405_PCI_CONFIG_ADDR)
+#define PPC4xx_PCI_CFG_VADDR PPC4xx_PCI_CFG_PADDR
+#define PPC4xx_PCI_CFG_SIZE ((uint)4*1024)
+#define PPC4xx_PCI_LCFG_PADDR ((uint)0xef400000)
+#define PPC4xx_PCI_LCFG_VADDR PPC4xx_PCI_LCFG_PADDR
+#define PPC4xx_PCI_LCFG_SIZE ((uint)4*1024)
+#define PPC4xx_ONB_IO_PADDR ((uint)0xef600000)
+#define PPC4xx_ONB_IO_VADDR PPC4xx_ONB_IO_PADDR
+#define PPC4xx_ONB_IO_SIZE ((uint)4*1024)
+
+/* serial port defines */
+#define RS_TABLE_SIZE 2
+
+#define UART0_INT 0
+#define UART1_INT 1
+
+#define PCIL0_BASE 0xEF400000
+#define UART0_IO_BASE 0xEF600300
+#define UART1_IO_BASE 0xEF600400
+#define EMAC0_BASE 0xEF600800
+
+#define BD_EMAC_ADDR(e,i) bi_enetaddr[i]
+
+#define STD_UART_OP(num) \
+ { 0, BASE_BAUD, 0, UART##num##_INT, \
+ (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST), \
+ iomem_base: (u8 *)UART##num##_IO_BASE, \
+ io_type: SERIAL_IO_MEM},
+
+#if defined(CONFIG_UART0_TTYS0)
+#define SERIAL_DEBUG_IO_BASE UART0_IO_BASE
+#define SERIAL_PORT_DFNS \
+ STD_UART_OP(0) \
+ STD_UART_OP(1)
+#endif
+
+#if defined(CONFIG_UART0_TTYS1)
+#define SERIAL_DEBUG_IO_BASE UART1_IO_BASE
+#define SERIAL_PORT_DFNS \
+ STD_UART_OP(1) \
+ STD_UART_OP(0)
+#endif
+
+/* DCR defines */
+#define DCRN_CHCR_BASE 0x0B1
+#define DCRN_CHPSR_BASE 0x0B4
+#define DCRN_CPMSR_BASE 0x0B8
+#define DCRN_CPMFR_BASE 0x0BA
+
+#define CHR0_U0EC 0x00000080 /* Select external clock for UART0 */
+#define CHR0_U1EC 0x00000040 /* Select external clock for UART1 */
+#define CHR0_UDIV 0x0000003E /* UART internal clock divisor */
+#define CHR1_CETE 0x00800000 /* CPU external timer enable */
+
+#define DCRN_CHPSR_BASE 0x0B4
+#define PSR_PLL_FWD_MASK 0xC0000000
+#define PSR_PLL_FDBACK_MASK 0x30000000
+#define PSR_PLL_TUNING_MASK 0x0E000000
+#define PSR_PLB_CPU_MASK 0x01800000
+#define PSR_OPB_PLB_MASK 0x00600000
+#define PSR_PCI_PLB_MASK 0x00180000
+#define PSR_EB_PLB_MASK 0x00060000
+#define PSR_ROM_WIDTH_MASK 0x00018000
+#define PSR_ROM_LOC 0x00004000
+#define PSR_PCI_ASYNC_EN 0x00001000
+#define PSR_PCI_ARBIT_EN 0x00000400
+
+#define IBM_CPM_IIC0 0x80000000 /* IIC interface */
+#define IBM_CPM_PCI 0x40000000 /* PCI bridge */
+#define IBM_CPM_CPU 0x20000000 /* processor core */
+#define IBM_CPM_DMA 0x10000000 /* DMA controller */
+#define IBM_CPM_OPB 0x08000000 /* PLB to OPB bridge */
+#define IBM_CPM_DCP 0x04000000 /* CodePack */
+#define IBM_CPM_EBC 0x02000000 /* ROM/SRAM peripheral controller */
+#define IBM_CPM_SDRAM0 0x01000000 /* SDRAM memory controller */
+#define IBM_CPM_PLB 0x00800000 /* PLB bus arbiter */
+#define IBM_CPM_GPIO0 0x00400000 /* General Purpose IO (??) */
+#define IBM_CPM_UART0 0x00200000 /* serial port 0 */
+#define IBM_CPM_UART1 0x00100000 /* serial port 1 */
+#define IBM_CPM_UIC 0x00080000 /* Universal Interrupt Controller */
+#define IBM_CPM_TMRCLK 0x00040000 /* CPU timers */
+#define IBM_CPM_EMAC0 0x00020000 /* on-chip ethernet MM unit */
+#define DFLT_IBM4xx_PM ~(IBM_CPM_PCI | IBM_CPM_CPU | IBM_CPM_DMA \
+ | IBM_CPM_OPB | IBM_CPM_EBC \
+ | IBM_CPM_SDRAM0 | IBM_CPM_PLB \
+ | IBM_CPM_UIC | IBM_CPM_TMRCLK)
+
+#define DCRN_DMA0_BASE 0x100
+#define DCRN_DMA1_BASE 0x108
+#define DCRN_DMA2_BASE 0x110
+#define DCRN_DMA3_BASE 0x118
+#define DCRNCAP_DMA_SG 1 /* have DMA scatter/gather capability */
+#define DCRN_DMASR_BASE 0x120
+#define DCRN_EBC_BASE 0x012
+#define DCRN_DCP0_BASE 0x014
+#define DCRN_MAL_BASE 0x180
+#define DCRN_OCM0_BASE 0x018
+#define DCRN_PLB0_BASE 0x084
+#define DCRN_PLLMR_BASE 0x0B0
+#define DCRN_POB0_BASE 0x0A0
+#define DCRN_SDRAM0_BASE 0x010
+#define DCRN_UIC0_BASE 0x0C0
+#define UIC0 DCRN_UIC0_BASE
+
+#include <asm/ibm405.h>
+
+#endif /* __ASM_IBM405GPR_H__ */
+#endif /* __KERNEL__ */
diff --git a/arch/ppc/platforms/4xx/ibm440gp.c b/arch/ppc/platforms/4xx/ibm440gp.c
new file mode 100644
index 0000000..27615ef
--- /dev/null
+++ b/arch/ppc/platforms/4xx/ibm440gp.c
@@ -0,0 +1,164 @@
+/*
+ * arch/ppc/platforms/4xx/ibm440gp.c
+ *
+ * PPC440GP I/O descriptions
+ *
+ * Matt Porter <mporter@mvista.com>
+ * Copyright 2002-2004 MontaVista Software Inc.
+ *
+ * Eugene Surovegin <eugene.surovegin@zultys.com> or <ebs@ebshome.net>
+ * Copyright (c) 2003, 2004 Zultys Technologies
+ *
+ * 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.
+ *
+ */
+#include <linux/init.h>
+#include <linux/module.h>
+#include <platforms/4xx/ibm440gp.h>
+#include <asm/ocp.h>
+#include <asm/ppc4xx_pic.h>
+
+static struct ocp_func_emac_data ibm440gp_emac0_def = {
+ .rgmii_idx = -1, /* No RGMII */
+ .rgmii_mux = -1, /* No RGMII */
+ .zmii_idx = 0, /* ZMII device index */
+ .zmii_mux = 0, /* ZMII input of this EMAC */
+ .mal_idx = 0, /* MAL device index */
+ .mal_rx_chan = 0, /* MAL rx channel number */
+ .mal_tx_chan = 0, /* MAL tx channel number */
+ .wol_irq = 61, /* WOL interrupt number */
+ .mdio_idx = -1, /* No shared MDIO */
+ .tah_idx = -1, /* No TAH */
+};
+
+static struct ocp_func_emac_data ibm440gp_emac1_def = {
+ .rgmii_idx = -1, /* No RGMII */
+ .rgmii_mux = -1, /* No RGMII */
+ .zmii_idx = 0, /* ZMII device index */
+ .zmii_mux = 1, /* ZMII input of this EMAC */
+ .mal_idx = 0, /* MAL device index */
+ .mal_rx_chan = 1, /* MAL rx channel number */
+ .mal_tx_chan = 2, /* MAL tx channel number */
+ .wol_irq = 63, /* WOL interrupt number */
+ .mdio_idx = -1, /* No shared MDIO */
+ .tah_idx = -1, /* No TAH */
+};
+OCP_SYSFS_EMAC_DATA()
+
+static struct ocp_func_mal_data ibm440gp_mal0_def = {
+ .num_tx_chans = 4, /* Number of TX channels */
+ .num_rx_chans = 2, /* Number of RX channels */
+ .txeob_irq = 10, /* TX End Of Buffer IRQ */
+ .rxeob_irq = 11, /* RX End Of Buffer IRQ */
+ .txde_irq = 33, /* TX Descriptor Error IRQ */
+ .rxde_irq = 34, /* RX Descriptor Error IRQ */
+ .serr_irq = 32, /* MAL System Error IRQ */
+};
+OCP_SYSFS_MAL_DATA()
+
+static struct ocp_func_iic_data ibm440gp_iic0_def = {
+ .fast_mode = 0, /* Use standad mode (100Khz) */
+};
+
+static struct ocp_func_iic_data ibm440gp_iic1_def = {
+ .fast_mode = 0, /* Use standad mode (100Khz) */
+};
+OCP_SYSFS_IIC_DATA()
+
+struct ocp_def core_ocp[] = {
+ { .vendor = OCP_VENDOR_IBM,
+ .function = OCP_FUNC_OPB,
+ .index = 0,
+ .paddr = 0x0000000140000000ULL,
+ .irq = OCP_IRQ_NA,
+ .pm = OCP_CPM_NA,
+ },
+ { .vendor = OCP_VENDOR_IBM,
+ .function = OCP_FUNC_16550,
+ .index = 0,
+ .paddr = PPC440GP_UART0_ADDR,
+ .irq = UART0_INT,
+ .pm = IBM_CPM_UART0,
+ },
+ { .vendor = OCP_VENDOR_IBM,
+ .function = OCP_FUNC_16550,
+ .index = 1,
+ .paddr = PPC440GP_UART1_ADDR,
+ .irq = UART1_INT,
+ .pm = IBM_CPM_UART1,
+ },
+ { .vendor = OCP_VENDOR_IBM,
+ .function = OCP_FUNC_IIC,
+ .index = 0,
+ .paddr = 0x0000000140000400ULL,
+ .irq = 2,
+ .pm = IBM_CPM_IIC0,
+ .additions = &ibm440gp_iic0_def,
+ .show = &ocp_show_iic_data
+ },
+ { .vendor = OCP_VENDOR_IBM,
+ .function = OCP_FUNC_IIC,
+ .index = 1,
+ .paddr = 0x0000000140000500ULL,
+ .irq = 3,
+ .pm = IBM_CPM_IIC1,
+ .additions = &ibm440gp_iic1_def,
+ .show = &ocp_show_iic_data
+ },
+ { .vendor = OCP_VENDOR_IBM,
+ .function = OCP_FUNC_GPIO,
+ .index = 0,
+ .paddr = 0x0000000140000700ULL,
+ .irq = OCP_IRQ_NA,
+ .pm = IBM_CPM_GPIO0,
+ },
+ { .vendor = OCP_VENDOR_IBM,
+ .function = OCP_FUNC_MAL,
+ .paddr = OCP_PADDR_NA,
+ .irq = OCP_IRQ_NA,
+ .pm = OCP_CPM_NA,
+ .additions = &ibm440gp_mal0_def,
+ .show = &ocp_show_mal_data,
+ },
+ { .vendor = OCP_VENDOR_IBM,
+ .function = OCP_FUNC_EMAC,
+ .index = 0,
+ .paddr = 0x0000000140000800ULL,
+ .irq = 60,
+ .pm = OCP_CPM_NA,
+ .additions = &ibm440gp_emac0_def,
+ .show = &ocp_show_emac_data,
+ },
+ { .vendor = OCP_VENDOR_IBM,
+ .function = OCP_FUNC_EMAC,
+ .index = 1,
+ .paddr = 0x0000000140000900ULL,
+ .irq = 62,
+ .pm = OCP_CPM_NA,
+ .additions = &ibm440gp_emac1_def,
+ .show = &ocp_show_emac_data,
+ },
+ { .vendor = OCP_VENDOR_IBM,
+ .function = OCP_FUNC_ZMII,
+ .paddr = 0x0000000140000780ULL,
+ .irq = OCP_IRQ_NA,
+ .pm = OCP_CPM_NA,
+ },
+ { .vendor = OCP_VENDOR_INVALID
+ }
+};
+
+/* Polarity and triggering settings for internal interrupt sources */
+struct ppc4xx_uic_settings ppc4xx_core_uic_cfg[] __initdata = {
+ { .polarity = 0xfffffe03,
+ .triggering = 0x01c00000,
+ .ext_irq_mask = 0x000001fc, /* IRQ0 - IRQ6 */
+ },
+ { .polarity = 0xffffc0ff,
+ .triggering = 0x00ff8000,
+ .ext_irq_mask = 0x00003f00, /* IRQ7 - IRQ12 */
+ },
+};
diff --git a/arch/ppc/platforms/4xx/ibm440gp.h b/arch/ppc/platforms/4xx/ibm440gp.h
new file mode 100644
index 0000000..ae1efc0
--- /dev/null
+++ b/arch/ppc/platforms/4xx/ibm440gp.h
@@ -0,0 +1,66 @@
+/*
+ * arch/ppc/platforms/4xx/ibm440gp.h
+ *
+ * PPC440GP definitions
+ *
+ * Roland Dreier <roland@digitalvampire.org>
+ *
+ * Copyright 2002 Roland Dreier
+ *
+ * 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 file contains code that was originally in the files ibm44x.h
+ * and ebony.h, which were written by Matt Porter of MontaVista Software Inc.
+ */
+
+#ifdef __KERNEL__
+#ifndef __PPC_PLATFORMS_IBM440GP_H
+#define __PPC_PLATFORMS_IBM440GP_H
+
+#include <linux/config.h>
+
+/* UART */
+#define PPC440GP_UART0_ADDR 0x0000000140000200ULL
+#define PPC440GP_UART1_ADDR 0x0000000140000300ULL
+#define UART0_INT 0
+#define UART1_INT 1
+
+/* Clock and Power Management */
+#define IBM_CPM_IIC0 0x80000000 /* IIC interface */
+#define IBM_CPM_IIC1 0x40000000 /* IIC interface */
+#define IBM_CPM_PCI 0x20000000 /* PCI bridge */
+#define IBM_CPM_CPU 0x02000000 /* processor core */
+#define IBM_CPM_DMA 0x01000000 /* DMA controller */
+#define IBM_CPM_BGO 0x00800000 /* PLB to OPB bus arbiter */
+#define IBM_CPM_BGI 0x00400000 /* OPB to PLB bridge */
+#define IBM_CPM_EBC 0x00200000 /* External Bux Controller */
+#define IBM_CPM_EBM 0x00100000 /* Ext Bus Master Interface */
+#define IBM_CPM_DMC 0x00080000 /* SDRAM peripheral controller */
+#define IBM_CPM_PLB 0x00040000 /* PLB bus arbiter */
+#define IBM_CPM_SRAM 0x00020000 /* SRAM memory controller */
+#define IBM_CPM_PPM 0x00002000 /* PLB Performance Monitor */
+#define IBM_CPM_UIC1 0x00001000 /* Universal Interrupt Controller */
+#define IBM_CPM_GPIO0 0x00000800 /* General Purpose IO (??) */
+#define IBM_CPM_GPT 0x00000400 /* General Purpose Timers */
+#define IBM_CPM_UART0 0x00000200 /* serial port 0 */
+#define IBM_CPM_UART1 0x00000100 /* serial port 1 */
+#define IBM_CPM_UIC0 0x00000080 /* Universal Interrupt Controller */
+#define IBM_CPM_TMRCLK 0x00000040 /* CPU timers */
+
+#define DFLT_IBM4xx_PM ~(IBM_CPM_UIC | IBM_CPM_UIC1 | IBM_CPM_CPU \
+ | IBM_CPM_EBC | IBM_CPM_SRAM | IBM_CPM_BGO \
+ | IBM_CPM_EBM | IBM_CPM_PLB | IBM_CPM_OPB \
+ | IBM_CPM_TMRCLK | IBM_CPM_DMA | IBM_CPM_PCI)
+/*
+ * Serial port defines
+ */
+#define RS_TABLE_SIZE 2
+
+#include <asm/ibm44x.h>
+#include <syslib/ibm440gp_common.h>
+
+#endif /* __PPC_PLATFORMS_IBM440GP_H */
+#endif /* __KERNEL__ */
diff --git a/arch/ppc/platforms/4xx/ibm440gx.c b/arch/ppc/platforms/4xx/ibm440gx.c
new file mode 100644
index 0000000..1f38f42
--- /dev/null
+++ b/arch/ppc/platforms/4xx/ibm440gx.c
@@ -0,0 +1,234 @@
+/*
+ * arch/ppc/platforms/4xx/ibm440gx.c
+ *
+ * PPC440GX I/O descriptions
+ *
+ * Matt Porter <mporter@mvista.com>
+ * Copyright 2002-2004 MontaVista Software Inc.
+ *
+ * Eugene Surovegin <eugene.surovegin@zultys.com> or <ebs@ebshome.net>
+ * Copyright (c) 2003, 2004 Zultys Technologies
+ *
+ * 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.
+ *
+ */
+#include <linux/init.h>
+#include <linux/module.h>
+#include <platforms/4xx/ibm440gx.h>
+#include <asm/ocp.h>
+#include <asm/ppc4xx_pic.h>
+
+static struct ocp_func_emac_data ibm440gx_emac0_def = {
+ .rgmii_idx = -1, /* No RGMII */
+ .rgmii_mux = -1, /* No RGMII */
+ .zmii_idx = 0, /* ZMII device index */
+ .zmii_mux = 0, /* ZMII input of this EMAC */
+ .mal_idx = 0, /* MAL device index */
+ .mal_rx_chan = 0, /* MAL rx channel number */
+ .mal_tx_chan = 0, /* MAL tx channel number */
+ .wol_irq = 61, /* WOL interrupt number */
+ .mdio_idx = -1, /* No shared MDIO */
+ .tah_idx = -1, /* No TAH */
+};
+
+static struct ocp_func_emac_data ibm440gx_emac1_def = {
+ .rgmii_idx = -1, /* No RGMII */
+ .rgmii_mux = -1, /* No RGMII */
+ .zmii_idx = 0, /* ZMII device index */
+ .zmii_mux = 1, /* ZMII input of this EMAC */
+ .mal_idx = 0, /* MAL device index */
+ .mal_rx_chan = 1, /* MAL rx channel number */
+ .mal_tx_chan = 1, /* MAL tx channel number */
+ .wol_irq = 63, /* WOL interrupt number */
+ .mdio_idx = -1, /* No shared MDIO */
+ .tah_idx = -1, /* No TAH */
+};
+
+static struct ocp_func_emac_data ibm440gx_emac2_def = {
+ .rgmii_idx = 0, /* RGMII device index */
+ .rgmii_mux = 0, /* RGMII input of this EMAC */
+ .zmii_idx = 0, /* ZMII device index */
+ .zmii_mux = 2, /* ZMII input of this EMAC */
+ .mal_idx = 0, /* MAL device index */
+ .mal_rx_chan = 2, /* MAL rx channel number */
+ .mal_tx_chan = 2, /* MAL tx channel number */
+ .wol_irq = 65, /* WOL interrupt number */
+ .mdio_idx = -1, /* No shared MDIO */
+ .tah_idx = 0, /* TAH device index */
+ .jumbo = 1, /* Jumbo frames supported */
+};
+
+static struct ocp_func_emac_data ibm440gx_emac3_def = {
+ .rgmii_idx = 0, /* RGMII device index */
+ .rgmii_mux = 1, /* RGMII input of this EMAC */
+ .zmii_idx = 0, /* ZMII device index */
+ .zmii_mux = 3, /* ZMII input of this EMAC */
+ .mal_idx = 0, /* MAL device index */
+ .mal_rx_chan = 3, /* MAL rx channel number */
+ .mal_tx_chan = 3, /* MAL tx channel number */
+ .wol_irq = 67, /* WOL interrupt number */
+ .mdio_idx = -1, /* No shared MDIO */
+ .tah_idx = 1, /* TAH device index */
+ .jumbo = 1, /* Jumbo frames supported */
+};
+OCP_SYSFS_EMAC_DATA()
+
+static struct ocp_func_mal_data ibm440gx_mal0_def = {
+ .num_tx_chans = 4, /* Number of TX channels */
+ .num_rx_chans = 4, /* Number of RX channels */
+ .txeob_irq = 10, /* TX End Of Buffer IRQ */
+ .rxeob_irq = 11, /* RX End Of Buffer IRQ */
+ .txde_irq = 33, /* TX Descriptor Error IRQ */
+ .rxde_irq = 34, /* RX Descriptor Error IRQ */
+ .serr_irq = 32, /* MAL System Error IRQ */
+};
+OCP_SYSFS_MAL_DATA()
+
+static struct ocp_func_iic_data ibm440gx_iic0_def = {
+ .fast_mode = 0, /* Use standad mode (100Khz) */
+};
+
+static struct ocp_func_iic_data ibm440gx_iic1_def = {
+ .fast_mode = 0, /* Use standad mode (100Khz) */
+};
+OCP_SYSFS_IIC_DATA()
+
+struct ocp_def core_ocp[] = {
+ { .vendor = OCP_VENDOR_IBM,
+ .function = OCP_FUNC_OPB,
+ .index = 0,
+ .paddr = 0x0000000140000000ULL,
+ .irq = OCP_IRQ_NA,
+ .pm = OCP_CPM_NA,
+ },
+ { .vendor = OCP_VENDOR_IBM,
+ .function = OCP_FUNC_16550,
+ .index = 0,
+ .paddr = PPC440GX_UART0_ADDR,
+ .irq = UART0_INT,
+ .pm = IBM_CPM_UART0,
+ },
+ { .vendor = OCP_VENDOR_IBM,
+ .function = OCP_FUNC_16550,
+ .index = 1,
+ .paddr = PPC440GX_UART1_ADDR,
+ .irq = UART1_INT,
+ .pm = IBM_CPM_UART1,
+ },
+ { .vendor = OCP_VENDOR_IBM,
+ .function = OCP_FUNC_IIC,
+ .index = 0,
+ .paddr = 0x0000000140000400ULL,
+ .irq = 2,
+ .pm = IBM_CPM_IIC0,
+ .additions = &ibm440gx_iic0_def,
+ .show = &ocp_show_iic_data
+ },
+ { .vendor = OCP_VENDOR_IBM,
+ .function = OCP_FUNC_IIC,
+ .index = 1,
+ .paddr = 0x0000000140000500ULL,
+ .irq = 3,
+ .pm = IBM_CPM_IIC1,
+ .additions = &ibm440gx_iic1_def,
+ .show = &ocp_show_iic_data
+ },
+ { .vendor = OCP_VENDOR_IBM,
+ .function = OCP_FUNC_GPIO,
+ .index = 0,
+ .paddr = 0x0000000140000700ULL,
+ .irq = OCP_IRQ_NA,
+ .pm = IBM_CPM_GPIO0,
+ },
+ { .vendor = OCP_VENDOR_IBM,
+ .function = OCP_FUNC_MAL,
+ .paddr = OCP_PADDR_NA,
+ .irq = OCP_IRQ_NA,
+ .pm = OCP_CPM_NA,
+ .additions = &ibm440gx_mal0_def,
+ .show = &ocp_show_mal_data,
+ },
+ { .vendor = OCP_VENDOR_IBM,
+ .function = OCP_FUNC_EMAC,
+ .index = 0,
+ .paddr = 0x0000000140000800ULL,
+ .irq = 60,
+ .pm = OCP_CPM_NA,
+ .additions = &ibm440gx_emac0_def,
+ .show = &ocp_show_emac_data,
+ },
+ { .vendor = OCP_VENDOR_IBM,
+ .function = OCP_FUNC_EMAC,
+ .index = 1,
+ .paddr = 0x0000000140000900ULL,
+ .irq = 62,
+ .pm = OCP_CPM_NA,
+ .additions = &ibm440gx_emac1_def,
+ .show = &ocp_show_emac_data,
+ },
+ { .vendor = OCP_VENDOR_IBM,
+ .function = OCP_FUNC_EMAC,
+ .index = 2,
+ .paddr = 0x0000000140000C00ULL,
+ .irq = 64,
+ .pm = OCP_CPM_NA,
+ .additions = &ibm440gx_emac2_def,
+ .show = &ocp_show_emac_data,
+ },
+ { .vendor = OCP_VENDOR_IBM,
+ .function = OCP_FUNC_EMAC,
+ .index = 3,
+ .paddr = 0x0000000140000E00ULL,
+ .irq = 66,
+ .pm = OCP_CPM_NA,
+ .additions = &ibm440gx_emac3_def,
+ .show = &ocp_show_emac_data,
+ },
+ { .vendor = OCP_VENDOR_IBM,
+ .function = OCP_FUNC_RGMII,
+ .paddr = 0x0000000140000790ULL,
+ .irq = OCP_IRQ_NA,
+ .pm = OCP_CPM_NA,
+ },
+ { .vendor = OCP_VENDOR_IBM,
+ .function = OCP_FUNC_ZMII,
+ .paddr = 0x0000000140000780ULL,
+ .irq = OCP_IRQ_NA,
+ .pm = OCP_CPM_NA,
+ },
+ { .vendor = OCP_VENDOR_IBM,
+ .function = OCP_FUNC_TAH,
+ .index = 0,
+ .paddr = 0x0000000140000b50ULL,
+ .irq = 68,
+ .pm = OCP_CPM_NA,
+ },
+ { .vendor = OCP_VENDOR_IBM,
+ .function = OCP_FUNC_TAH,
+ .index = 1,
+ .paddr = 0x0000000140000d50ULL,
+ .irq = 69,
+ .pm = OCP_CPM_NA,
+ },
+ { .vendor = OCP_VENDOR_INVALID
+ }
+};
+
+/* Polarity and triggering settings for internal interrupt sources */
+struct ppc4xx_uic_settings ppc4xx_core_uic_cfg[] __initdata = {
+ { .polarity = 0xfffffe03,
+ .triggering = 0x01c00000,
+ .ext_irq_mask = 0x000001fc, /* IRQ0 - IRQ6 */
+ },
+ { .polarity = 0xffffc0ff,
+ .triggering = 0x00ff8000,
+ .ext_irq_mask = 0x00003f00, /* IRQ7 - IRQ12 */
+ },
+ { .polarity = 0xffff83ff,
+ .triggering = 0x000f83c0,
+ .ext_irq_mask = 0x00007c00, /* IRQ13 - IRQ17 */
+ },
+};
diff --git a/arch/ppc/platforms/4xx/ibm440gx.h b/arch/ppc/platforms/4xx/ibm440gx.h
new file mode 100644
index 0000000..0b59d8d
--- /dev/null
+++ b/arch/ppc/platforms/4xx/ibm440gx.h
@@ -0,0 +1,74 @@
+/*
+ * arch/ppc/platforms/ibm440gx.h
+ *
+ * PPC440GX definitions
+ *
+ * Matt Porter <mporter@mvista.com>
+ *
+ * Copyright 2002 Roland Dreier
+ * Copyright 2003 MontaVista Software, Inc.
+ *
+ * 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.
+ *
+ */
+
+#ifdef __KERNEL__
+#ifndef __PPC_PLATFORMS_IBM440GX_H
+#define __PPC_PLATFORMS_IBM440GX_H
+
+#include <linux/config.h>
+
+#include <asm/ibm44x.h>
+
+/* UART */
+#define PPC440GX_UART0_ADDR 0x0000000140000200ULL
+#define PPC440GX_UART1_ADDR 0x0000000140000300ULL
+#define UART0_INT 0
+#define UART1_INT 1
+
+/* Clock and Power Management */
+#define IBM_CPM_IIC0 0x80000000 /* IIC interface */
+#define IBM_CPM_IIC1 0x40000000 /* IIC interface */
+#define IBM_CPM_PCI 0x20000000 /* PCI bridge */
+#define IBM_CPM_RGMII 0x10000000 /* RGMII */
+#define IBM_CPM_TAHOE0 0x08000000 /* TAHOE 0 */
+#define IBM_CPM_TAHOE1 0x04000000 /* TAHOE 1 */
+#define IBM_CPM_CPU 0x02000000 /* processor core */
+#define IBM_CPM_DMA 0x01000000 /* DMA controller */
+#define IBM_CPM_BGO 0x00800000 /* PLB to OPB bus arbiter */
+#define IBM_CPM_BGI 0x00400000 /* OPB to PLB bridge */
+#define IBM_CPM_EBC 0x00200000 /* External Bux Controller */
+#define IBM_CPM_EBM 0x00100000 /* Ext Bus Master Interface */
+#define IBM_CPM_DMC 0x00080000 /* SDRAM peripheral controller */
+#define IBM_CPM_PLB 0x00040000 /* PLB bus arbiter */
+#define IBM_CPM_SRAM 0x00020000 /* SRAM memory controller */
+#define IBM_CPM_PPM 0x00002000 /* PLB Performance Monitor */
+#define IBM_CPM_UIC1 0x00001000 /* Universal Interrupt Controller */
+#define IBM_CPM_GPIO0 0x00000800 /* General Purpose IO (??) */
+#define IBM_CPM_GPT 0x00000400 /* General Purpose Timers */
+#define IBM_CPM_UART0 0x00000200 /* serial port 0 */
+#define IBM_CPM_UART1 0x00000100 /* serial port 1 */
+#define IBM_CPM_UIC0 0x00000080 /* Universal Interrupt Controller */
+#define IBM_CPM_TMRCLK 0x00000040 /* CPU timers */
+#define IBM_CPM_EMAC0 0x00000020 /* EMAC 0 */
+#define IBM_CPM_EMAC1 0x00000010 /* EMAC 1 */
+#define IBM_CPM_EMAC2 0x00000008 /* EMAC 2 */
+#define IBM_CPM_EMAC3 0x00000004 /* EMAC 3 */
+
+#define DFLT_IBM4xx_PM ~(IBM_CPM_UIC | IBM_CPM_UIC1 | IBM_CPM_CPU \
+ | IBM_CPM_EBC | IBM_CPM_SRAM | IBM_CPM_BGO \
+ | IBM_CPM_EBM | IBM_CPM_PLB | IBM_CPM_OPB \
+ | IBM_CPM_TMRCLK | IBM_CPM_DMA | IBM_CPM_PCI \
+ | IBM_CPM_TAHOE0 | IBM_CPM_TAHOE1 \
+ | IBM_CPM_EMAC0 | IBM_CPM_EMAC1 \
+ | IBM_CPM_EMAC2 | IBM_CPM_EMAC3 )
+/*
+ * Serial port defines
+ */
+#define RS_TABLE_SIZE 2
+
+#endif /* __PPC_PLATFORMS_IBM440GX_H */
+#endif /* __KERNEL__ */
diff --git a/arch/ppc/platforms/4xx/ibm440sp.c b/arch/ppc/platforms/4xx/ibm440sp.c
new file mode 100644
index 0000000..a203efb
--- /dev/null
+++ b/arch/ppc/platforms/4xx/ibm440sp.c
@@ -0,0 +1,131 @@
+/*
+ * arch/ppc/platforms/4xx/ibm440sp.c
+ *
+ * PPC440SP I/O descriptions
+ *
+ * Matt Porter <mporter@kernel.crashing.org>
+ * Copyright 2002-2005 MontaVista Software Inc.
+ *
+ * Eugene Surovegin <eugene.surovegin@zultys.com> or <ebs@ebshome.net>
+ * Copyright (c) 2003, 2004 Zultys Technologies
+ *
+ * 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.
+ *
+ */
+#include <linux/init.h>
+#include <linux/module.h>
+#include <platforms/4xx/ibm440sp.h>
+#include <asm/ocp.h>
+
+static struct ocp_func_emac_data ibm440sp_emac0_def = {
+ .rgmii_idx = -1, /* No RGMII */
+ .rgmii_mux = -1, /* No RGMII */
+ .zmii_idx = -1, /* No ZMII */
+ .zmii_mux = -1, /* No ZMII */
+ .mal_idx = 0, /* MAL device index */
+ .mal_rx_chan = 0, /* MAL rx channel number */
+ .mal_tx_chan = 0, /* MAL tx channel number */
+ .wol_irq = 61, /* WOL interrupt number */
+ .mdio_idx = -1, /* No shared MDIO */
+ .tah_idx = -1, /* No TAH */
+ .jumbo = 1, /* Jumbo frames supported */
+};
+OCP_SYSFS_EMAC_DATA()
+
+static struct ocp_func_mal_data ibm440sp_mal0_def = {
+ .num_tx_chans = 4, /* Number of TX channels */
+ .num_rx_chans = 4, /* Number of RX channels */
+ .txeob_irq = 38, /* TX End Of Buffer IRQ */
+ .rxeob_irq = 39, /* RX End Of Buffer IRQ */
+ .txde_irq = 34, /* TX Descriptor Error IRQ */
+ .rxde_irq = 35, /* RX Descriptor Error IRQ */
+ .serr_irq = 33, /* MAL System Error IRQ */
+};
+OCP_SYSFS_MAL_DATA()
+
+static struct ocp_func_iic_data ibm440sp_iic0_def = {
+ .fast_mode = 0, /* Use standad mode (100Khz) */
+};
+
+static struct ocp_func_iic_data ibm440sp_iic1_def = {
+ .fast_mode = 0, /* Use standad mode (100Khz) */
+};
+OCP_SYSFS_IIC_DATA()
+
+struct ocp_def core_ocp[] = {
+ { .vendor = OCP_VENDOR_IBM,
+ .function = OCP_FUNC_OPB,
+ .index = 0,
+ .paddr = 0x0000000140000000ULL,
+ .irq = OCP_IRQ_NA,
+ .pm = OCP_CPM_NA,
+ },
+ { .vendor = OCP_VENDOR_IBM,
+ .function = OCP_FUNC_16550,
+ .index = 0,
+ .paddr = PPC440SP_UART0_ADDR,
+ .irq = UART0_INT,
+ .pm = IBM_CPM_UART0,
+ },
+ { .vendor = OCP_VENDOR_IBM,
+ .function = OCP_FUNC_16550,
+ .index = 1,
+ .paddr = PPC440SP_UART1_ADDR,
+ .irq = UART1_INT,
+ .pm = IBM_CPM_UART1,
+ },
+ { .vendor = OCP_VENDOR_IBM,
+ .function = OCP_FUNC_16550,
+ .index = 2,
+ .paddr = PPC440SP_UART2_ADDR,
+ .irq = UART2_INT,
+ .pm = IBM_CPM_UART2,
+ },
+ { .vendor = OCP_VENDOR_IBM,
+ .function = OCP_FUNC_IIC,
+ .index = 0,
+ .paddr = 0x00000001f0000400ULL,
+ .irq = 2,
+ .pm = IBM_CPM_IIC0,
+ .additions = &ibm440sp_iic0_def,
+ .show = &ocp_show_iic_data
+ },
+ { .vendor = OCP_VENDOR_IBM,
+ .function = OCP_FUNC_IIC,
+ .index = 1,
+ .paddr = 0x00000001f0000500ULL,
+ .irq = 3,
+ .pm = IBM_CPM_IIC1,
+ .additions = &ibm440sp_iic1_def,
+ .show = &ocp_show_iic_data
+ },
+ { .vendor = OCP_VENDOR_IBM,
+ .function = OCP_FUNC_GPIO,
+ .index = 0,
+ .paddr = 0x00000001f0000700ULL,
+ .irq = OCP_IRQ_NA,
+ .pm = IBM_CPM_GPIO0,
+ },
+ { .vendor = OCP_VENDOR_IBM,
+ .function = OCP_FUNC_MAL,
+ .paddr = OCP_PADDR_NA,
+ .irq = OCP_IRQ_NA,
+ .pm = OCP_CPM_NA,
+ .additions = &ibm440sp_mal0_def,
+ .show = &ocp_show_mal_data,
+ },
+ { .vendor = OCP_VENDOR_IBM,
+ .function = OCP_FUNC_EMAC,
+ .index = 0,
+ .paddr = 0x00000001f0000800ULL,
+ .irq = 60,
+ .pm = OCP_CPM_NA,
+ .additions = &ibm440sp_emac0_def,
+ .show = &ocp_show_emac_data,
+ },
+ { .vendor = OCP_VENDOR_INVALID
+ }
+};
diff --git a/arch/ppc/platforms/4xx/ibm440sp.h b/arch/ppc/platforms/4xx/ibm440sp.h
new file mode 100644
index 0000000..c71e46a
--- /dev/null
+++ b/arch/ppc/platforms/4xx/ibm440sp.h
@@ -0,0 +1,64 @@
+/*
+ * arch/ppc/platforms/4xx/ibm440sp.h
+ *
+ * PPC440SP definitions
+ *
+ * Matt Porter <mporter@kernel.crashing.org>
+ *
+ * Copyright 2004-2005 MontaVista Software, Inc.
+ *
+ * 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.
+ */
+
+#ifdef __KERNEL__
+#ifndef __PPC_PLATFORMS_IBM440SP_H
+#define __PPC_PLATFORMS_IBM440SP_H
+
+#include <linux/config.h>
+
+#include <asm/ibm44x.h>
+
+/* UART */
+#define PPC440SP_UART0_ADDR 0x00000001f0000200ULL
+#define PPC440SP_UART1_ADDR 0x00000001f0000300ULL
+#define PPC440SP_UART2_ADDR 0x00000001f0000600ULL
+#define UART0_INT 0
+#define UART1_INT 1
+#define UART2_INT 2
+
+/* Clock and Power Management */
+#define IBM_CPM_IIC0 0x80000000 /* IIC interface */
+#define IBM_CPM_IIC1 0x40000000 /* IIC interface */
+#define IBM_CPM_PCI 0x20000000 /* PCI bridge */
+#define IBM_CPM_CPU 0x02000000 /* processor core */
+#define IBM_CPM_DMA 0x01000000 /* DMA controller */
+#define IBM_CPM_BGO 0x00800000 /* PLB to OPB bus arbiter */
+#define IBM_CPM_BGI 0x00400000 /* OPB to PLB bridge */
+#define IBM_CPM_EBC 0x00200000 /* External Bux Controller */
+#define IBM_CPM_EBM 0x00100000 /* Ext Bus Master Interface */
+#define IBM_CPM_DMC 0x00080000 /* SDRAM peripheral controller */
+#define IBM_CPM_PLB 0x00040000 /* PLB bus arbiter */
+#define IBM_CPM_SRAM 0x00020000 /* SRAM memory controller */
+#define IBM_CPM_PPM 0x00002000 /* PLB Performance Monitor */
+#define IBM_CPM_UIC1 0x00001000 /* Universal Interrupt Controller */
+#define IBM_CPM_GPIO0 0x00000800 /* General Purpose IO (??) */
+#define IBM_CPM_GPT 0x00000400 /* General Purpose Timers */
+#define IBM_CPM_UART0 0x00000200 /* serial port 0 */
+#define IBM_CPM_UART1 0x00000100 /* serial port 1 */
+#define IBM_CPM_UART2 0x00000100 /* serial port 1 */
+#define IBM_CPM_UIC0 0x00000080 /* Universal Interrupt Controller */
+#define IBM_CPM_TMRCLK 0x00000040 /* CPU timers */
+#define IBM_CPM_EMAC0 0x00000020 /* EMAC 0 */
+
+#define DFLT_IBM4xx_PM ~(IBM_CPM_UIC | IBM_CPM_UIC1 | IBM_CPM_CPU \
+ | IBM_CPM_EBC | IBM_CPM_SRAM | IBM_CPM_BGO \
+ | IBM_CPM_EBM | IBM_CPM_PLB | IBM_CPM_OPB \
+ | IBM_CPM_TMRCLK | IBM_CPM_DMA | IBM_CPM_PCI \
+ | IBM_CPM_TAHOE0 | IBM_CPM_TAHOE1 \
+ | IBM_CPM_EMAC0 | IBM_CPM_EMAC1 \
+ | IBM_CPM_EMAC2 | IBM_CPM_EMAC3 )
+#endif /* __PPC_PLATFORMS_IBM440SP_H */
+#endif /* __KERNEL__ */
diff --git a/arch/ppc/platforms/4xx/ibmnp405h.c b/arch/ppc/platforms/4xx/ibmnp405h.c
new file mode 100644
index 0000000..ecdc5be
--- /dev/null
+++ b/arch/ppc/platforms/4xx/ibmnp405h.c
@@ -0,0 +1,172 @@
+/*
+ * arch/ppc/platforms/4xx/ibmnp405h.c
+ *
+ * Author: Armin Kuster <akuster@mvista.com>
+ *
+ * 2000-2002 (c) MontaVista, Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+
+#include <linux/config.h>
+#include <linux/init.h>
+#include <asm/ocp.h>
+#include <platforms/4xx/ibmnp405h.h>
+
+static struct ocp_func_emac_data ibmnp405h_emac0_def = {
+ .rgmii_idx = -1, /* No RGMII */
+ .rgmii_mux = -1, /* No RGMII */
+ .zmii_idx = 0, /* ZMII device index */
+ .zmii_mux = 0, /* ZMII input of this EMAC */
+ .mal_idx = 0, /* MAL device index */
+ .mal_rx_chan = 0, /* MAL rx channel number */
+ .mal_tx_chan = 0, /* MAL tx channel number */
+ .wol_irq = 41, /* WOL interrupt number */
+ .mdio_idx = -1, /* No shared MDIO */
+ .tah_idx = -1, /* No TAH */
+};
+
+static struct ocp_func_emac_data ibmnp405h_emac1_def = {
+ .rgmii_idx = -1, /* No RGMII */
+ .rgmii_mux = -1, /* No RGMII */
+ .zmii_idx = 0, /* ZMII device index */
+ .zmii_mux = 1, /* ZMII input of this EMAC */
+ .mal_idx = 0, /* MAL device index */
+ .mal_rx_chan = 1, /* MAL rx channel number */
+ .mal_tx_chan = 1, /* MAL tx channel number */
+ .wol_irq = 41, /* WOL interrupt number */
+ .mdio_idx = -1, /* No shared MDIO */
+ .tah_idx = -1, /* No TAH */
+};
+static struct ocp_func_emac_data ibmnp405h_emac2_def = {
+ .rgmii_idx = -1, /* No RGMII */
+ .rgmii_mux = -1, /* No RGMII */
+ .zmii_idx = 0, /* ZMII device index */
+ .zmii_mux = 2, /* ZMII input of this EMAC */
+ .mal_idx = 0, /* MAL device index */
+ .mal_rx_chan = 2, /* MAL rx channel number */
+ .mal_tx_chan = 2, /* MAL tx channel number */
+ .wol_irq = 41, /* WOL interrupt number */
+ .mdio_idx = -1, /* No shared MDIO */
+ .tah_idx = -1, /* No TAH */
+};
+static struct ocp_func_emac_data ibmnp405h_emac3_def = {
+ .rgmii_idx = -1, /* No RGMII */
+ .rgmii_mux = -1, /* No RGMII */
+ .zmii_idx = 0, /* ZMII device index */
+ .zmii_mux = 3, /* ZMII input of this EMAC */
+ .mal_idx = 0, /* MAL device index */
+ .mal_rx_chan = 3, /* MAL rx channel number */
+ .mal_tx_chan = 3, /* MAL tx channel number */
+ .wol_irq = 41, /* WOL interrupt number */
+ .mdio_idx = -1, /* No shared MDIO */
+ .tah_idx = -1, /* No TAH */
+};
+OCP_SYSFS_EMAC_DATA()
+
+static struct ocp_func_mal_data ibmnp405h_mal0_def = {
+ .num_tx_chans = 8, /* Number of TX channels */
+ .num_rx_chans = 4, /* Number of RX channels */
+ .txeob_irq = 17, /* TX End Of Buffer IRQ */
+ .rxeob_irq = 18, /* RX End Of Buffer IRQ */
+ .txde_irq = 46, /* TX Descriptor Error IRQ */
+ .rxde_irq = 47, /* RX Descriptor Error IRQ */
+ .serr_irq = 45, /* MAL System Error IRQ */
+};
+OCP_SYSFS_MAL_DATA()
+
+static struct ocp_func_iic_data ibmnp405h_iic0_def = {
+ .fast_mode = 0, /* Use standad mode (100Khz) */
+};
+OCP_SYSFS_IIC_DATA()
+
+struct ocp_def core_ocp[] = {
+ { .vendor = OCP_VENDOR_IBM,
+ .function = OCP_FUNC_OPB,
+ .index = 0,
+ .paddr = 0xEF600000,
+ .irq = OCP_IRQ_NA,
+ .pm = OCP_CPM_NA,
+ },
+ { .vendor = OCP_VENDOR_IBM,
+ .function = OCP_FUNC_16550,
+ .index = 0,
+ .paddr = UART0_IO_BASE,
+ .irq = UART0_INT,
+ .pm = IBM_CPM_UART0
+ },
+ { .vendor = OCP_VENDOR_IBM,
+ .function = OCP_FUNC_16550,
+ .index = 1,
+ .paddr = UART1_IO_BASE,
+ .irq = UART1_INT,
+ .pm = IBM_CPM_UART1
+ },
+ { .vendor = OCP_VENDOR_IBM,
+ .function = OCP_FUNC_IIC,
+ .paddr = 0xEF600500,
+ .irq = 2,
+ .pm = IBM_CPM_IIC0,
+ .additions = &ibmnp405h_iic0_def,
+ .show = &ocp_show_iic_data
+ },
+ { .vendor = OCP_VENDOR_IBM,
+ .function = OCP_FUNC_GPIO,
+ .paddr = 0xEF600700,
+ .irq = OCP_IRQ_NA,
+ .pm = IBM_CPM_GPIO0
+ },
+ { .vendor = OCP_VENDOR_IBM,
+ .function = OCP_FUNC_MAL,
+ .paddr = OCP_PADDR_NA,
+ .irq = OCP_IRQ_NA,
+ .pm = OCP_CPM_NA,
+ .additions = &ibmnp405h_mal0_def,
+ .show = &ocp_show_mal_data,
+ },
+ { .vendor = OCP_VENDOR_IBM,
+ .function = OCP_FUNC_EMAC,
+ .index = 0,
+ .paddr = EMAC0_BASE,
+ .irq = 37,
+ .pm = IBM_CPM_EMAC0,
+ .additions = &ibmnp405h_emac0_def,
+ .show = &ocp_show_emac_data,
+ },
+ { .vendor = OCP_VENDOR_IBM,
+ .function = OCP_FUNC_EMAC,
+ .index = 1,
+ .paddr = 0xEF600900,
+ .irq = 38,
+ .pm = IBM_CPM_EMAC1,
+ .additions = &ibmnp405h_emac1_def,
+ .show = &ocp_show_emac_data,
+ },
+ { .vendor = OCP_VENDOR_IBM,
+ .function = OCP_FUNC_EMAC,
+ .index = 2,
+ .paddr = 0xEF600a00,
+ .irq = 39,
+ .pm = IBM_CPM_EMAC2,
+ .additions = &ibmnp405h_emac2_def,
+ .show = &ocp_show_emac_data,
+ },
+ { .vendor = OCP_VENDOR_IBM,
+ .function = OCP_FUNC_EMAC,
+ .index = 3,
+ .paddr = 0xEF600b00,
+ .irq = 40,
+ .pm = IBM_CPM_EMAC3,
+ .additions = &ibmnp405h_emac3_def,
+ .show = &ocp_show_emac_data,
+ },
+ { .vendor = OCP_VENDOR_IBM,
+ .function = OCP_FUNC_ZMII,
+ .paddr = 0xEF600C10,
+ .irq = OCP_IRQ_NA,
+ .pm = OCP_CPM_NA,
+ },
+ { .vendor = OCP_VENDOR_INVALID
+ }
+};
diff --git a/arch/ppc/platforms/4xx/ibmnp405h.h b/arch/ppc/platforms/4xx/ibmnp405h.h
new file mode 100644
index 0000000..e2c2b06
--- /dev/null
+++ b/arch/ppc/platforms/4xx/ibmnp405h.h
@@ -0,0 +1,157 @@
+/*
+ * arch/ppc/platforms/4xx/ibmnp405h.h
+ *
+ * Author: Armin Kuster <akuster@mvista.com>
+ *
+ * 2002 (c) MontaVista, Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+
+#ifdef __KERNEL__
+#ifndef __ASM_IBMNP405H_H__
+#define __ASM_IBMNP405H_H__
+
+#include <linux/config.h>
+
+/* ibm405.h at bottom of this file */
+
+#define PPC405_PCI_CONFIG_ADDR 0xeec00000
+#define PPC405_PCI_CONFIG_DATA 0xeec00004
+#define PPC405_PCI_PHY_MEM_BASE 0x80000000 /* hose_a->pci_mem_offset */
+ /* setbat */
+#define PPC405_PCI_MEM_BASE PPC405_PCI_PHY_MEM_BASE /* setbat */
+#define PPC405_PCI_PHY_IO_BASE 0xe8000000 /* setbat */
+#define PPC405_PCI_IO_BASE PPC405_PCI_PHY_IO_BASE /* setbat */
+
+#define PPC405_PCI_LOWER_MEM 0x00000000 /* hose_a->mem_space.start */
+#define PPC405_PCI_UPPER_MEM 0xBfffffff /* hose_a->mem_space.end */
+#define PPC405_PCI_LOWER_IO 0x00000000 /* hose_a->io_space.start */
+#define PPC405_PCI_UPPER_IO 0x0000ffff /* hose_a->io_space.end */
+
+#define PPC405_ISA_IO_BASE PPC405_PCI_IO_BASE
+
+#define PPC4xx_PCI_IO_ADDR ((uint)PPC405_PCI_PHY_IO_BASE)
+#define PPC4xx_PCI_IO_SIZE ((uint)64*1024)
+#define PPC4xx_PCI_CFG_ADDR ((uint)PPC405_PCI_CONFIG_ADDR)
+#define PPC4xx_PCI_CFG_SIZE ((uint)4*1024)
+#define PPC4xx_PCI_LCFG_ADDR ((uint)0xef400000)
+#define PPC4xx_PCI_LCFG_SIZE ((uint)4*1024)
+#define PPC4xx_ONB_IO_ADDR ((uint)0xef600000)
+#define PPC4xx_ONB_IO_SIZE ((uint)4*1024)
+
+/* serial port defines */
+#define RS_TABLE_SIZE 4
+
+#define UART0_INT 0
+#define UART1_INT 1
+#define PCIL0_BASE 0xEF400000
+#define UART0_IO_BASE 0xEF600300
+#define UART1_IO_BASE 0xEF600400
+#define OPB0_BASE 0xEF600600
+#define EMAC0_BASE 0xEF600800
+
+#define BD_EMAC_ADDR(e,i) bi_enetaddr[e][i]
+
+#define STD_UART_OP(num) \
+ { 0, BASE_BAUD, 0, UART##num##_INT, \
+ (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST), \
+ iomem_base:(u8 *) UART##num##_IO_BASE, \
+ io_type: SERIAL_IO_MEM},
+
+#if defined(CONFIG_UART0_TTYS0)
+#define SERIAL_DEBUG_IO_BASE UART0_IO_BASE
+#define SERIAL_PORT_DFNS \
+ STD_UART_OP(0) \
+ STD_UART_OP(1)
+#endif
+
+#if defined(CONFIG_UART0_TTYS1)
+#define SERIAL_DEBUG_IO_BASE UART0_IO_BASE
+#define SERIAL_PORT_DFNS \
+ STD_UART_OP(1) \
+ STD_UART_OP(0)
+#endif
+
+/* DCR defines */
+/* ------------------------------------------------------------------------- */
+
+#define DCRN_CHCR_BASE 0x0F1
+#define DCRN_CHPSR_BASE 0x0B4
+#define DCRN_CPMSR_BASE 0x0BA
+#define DCRN_CPMFR_BASE 0x0B9
+#define DCRN_CPMER_BASE 0x0B8
+
+/* CPM Clocking & Power Mangement defines */
+#define IBM_CPM_PCI 0x40000000 /* PCI */
+#define IBM_CPM_EMAC2 0x20000000 /* EMAC 2 MII */
+#define IBM_CPM_EMAC3 0x04000000 /* EMAC 3 MII */
+#define IBM_CPM_EMAC0 0x00800000 /* EMAC 0 MII */
+#define IBM_CPM_EMAC1 0x00100000 /* EMAC 1 MII */
+#define IBM_CPM_EMMII 0 /* Shift value for MII */
+#define IBM_CPM_EMRX 1 /* Shift value for recv */
+#define IBM_CPM_EMTX 2 /* Shift value for MAC */
+#define IBM_CPM_UIC1 0x00020000 /* Universal Interrupt Controller */
+#define IBM_CPM_UIC0 0x00010000 /* Universal Interrupt Controller */
+#define IBM_CPM_CPU 0x00008000 /* processor core */
+#define IBM_CPM_EBC 0x00004000 /* ROM/SRAM peripheral controller */
+#define IBM_CPM_SDRAM0 0x00002000 /* SDRAM memory controller */
+#define IBM_CPM_GPIO0 0x00001000 /* General Purpose IO (??) */
+#define IBM_CPM_HDLC 0x00000800 /* HDCL */
+#define IBM_CPM_TMRCLK 0x00000400 /* CPU timers */
+#define IBM_CPM_PLB 0x00000100 /* PLB bus arbiter */
+#define IBM_CPM_OPB 0x00000080 /* PLB to OPB bridge */
+#define IBM_CPM_DMA 0x00000040 /* DMA controller */
+#define IBM_CPM_IIC0 0x00000010 /* IIC interface */
+#define IBM_CPM_UART0 0x00000002 /* serial port 0 */
+#define IBM_CPM_UART1 0x00000001 /* serial port 1 */
+/* this is the default setting for devices put to sleep when booting */
+
+#define DFLT_IBM4xx_PM ~(IBM_CPM_UIC0 | IBM_CPM_UIC1 | IBM_CPM_CPU \
+ | IBM_CPM_EBC | IBM_CPM_SDRAM0 | IBM_CPM_PLB \
+ | IBM_CPM_OPB | IBM_CPM_TMRCLK | IBM_CPM_DMA \
+ | IBM_CPM_EMAC0 | IBM_CPM_EMAC1 | IBM_CPM_EMAC2 \
+ | IBM_CPM_EMAC3 | IBM_CPM_PCI)
+
+#define DCRN_DMA0_BASE 0x100
+#define DCRN_DMA1_BASE 0x108
+#define DCRN_DMA2_BASE 0x110
+#define DCRN_DMA3_BASE 0x118
+#define DCRNCAP_DMA_SG 1 /* have DMA scatter/gather capability */
+#define DCRN_DMASR_BASE 0x120
+#define DCRN_EBC_BASE 0x012
+#define DCRN_DCP0_BASE 0x014
+#define DCRN_MAL_BASE 0x180
+#define DCRN_OCM0_BASE 0x018
+#define DCRN_PLB0_BASE 0x084
+#define DCRN_PLLMR_BASE 0x0B0
+#define DCRN_POB0_BASE 0x0A0
+#define DCRN_SDRAM0_BASE 0x010
+#define DCRN_UIC0_BASE 0x0C0
+#define DCRN_UIC1_BASE 0x0D0
+#define DCRN_CPC0_EPRCSR 0x0F3
+
+#define UIC0_UIC1NC 0x00000002
+
+#define CHR1_CETE 0x00000004 /* CPU external timer enable */
+#define UIC0 DCRN_UIC0_BASE
+#define UIC1 DCRN_UIC1_BASE
+
+#undef NR_UICS
+#define NR_UICS 2
+
+/* EMAC DCRN's FIXME: armin */
+#define DCRN_MALRXCTP2R(base) ((base) + 0x42) /* Channel Rx 2 Channel Table Pointer */
+#define DCRN_MALRXCTP3R(base) ((base) + 0x43) /* Channel Rx 3 Channel Table Pointer */
+#define DCRN_MALTXCTP4R(base) ((base) + 0x24) /* Channel Tx 4 Channel Table Pointer */
+#define DCRN_MALTXCTP5R(base) ((base) + 0x25) /* Channel Tx 5 Channel Table Pointer */
+#define DCRN_MALTXCTP6R(base) ((base) + 0x26) /* Channel Tx 6 Channel Table Pointer */
+#define DCRN_MALTXCTP7R(base) ((base) + 0x27) /* Channel Tx 7 Channel Table Pointer */
+#define DCRN_MALRCBS2(base) ((base) + 0x62) /* Channel Rx 2 Channel Buffer Size */
+#define DCRN_MALRCBS3(base) ((base) + 0x63) /* Channel Rx 3 Channel Buffer Size */
+
+#include <asm/ibm405.h>
+
+#endif /* __ASM_IBMNP405H_H__ */
+#endif /* __KERNEL__ */
diff --git a/arch/ppc/platforms/4xx/ibmstb4.c b/arch/ppc/platforms/4xx/ibmstb4.c
new file mode 100644
index 0000000..874d16b
--- /dev/null
+++ b/arch/ppc/platforms/4xx/ibmstb4.c
@@ -0,0 +1,83 @@
+/*
+ * arch/ppc/platforms/4xx/ibmstb4.c
+ *
+ * Author: Armin Kuster <akuster@mvista.com>
+ *
+ * 2000-2001 (c) MontaVista, Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+
+#include <linux/init.h>
+#include <asm/ocp.h>
+#include <platforms/4xx/ibmstb4.h>
+
+static struct ocp_func_iic_data ibmstb4_iic0_def = {
+ .fast_mode = 0, /* Use standad mode (100Khz) */
+};
+
+static struct ocp_func_iic_data ibmstb4_iic1_def = {
+ .fast_mode = 0, /* Use standad mode (100Khz) */
+};
+OCP_SYSFS_IIC_DATA()
+
+struct ocp_def core_ocp[] __initdata = {
+ { .vendor = OCP_VENDOR_IBM,
+ .function = OCP_FUNC_16550,
+ .index = 0,
+ .paddr = UART0_IO_BASE,
+ .irq = UART0_INT,
+ .pm = IBM_CPM_UART0,
+ },
+ { .vendor = OCP_VENDOR_IBM,
+ .function = OCP_FUNC_16550,
+ .index = 1,
+ .paddr = UART1_IO_BASE,
+ .irq = UART1_INT,
+ .pm = IBM_CPM_UART1,
+ },
+ { .vendor = OCP_VENDOR_IBM,
+ .function = OCP_FUNC_16550,
+ .index = 2,
+ .paddr = UART2_IO_BASE,
+ .irq = UART2_INT,
+ .pm = IBM_CPM_UART2,
+ },
+ { .vendor = OCP_VENDOR_IBM,
+ .function = OCP_FUNC_IIC,
+ .paddr = IIC0_BASE,
+ .irq = IIC0_IRQ,
+ .pm = IBM_CPM_IIC0,
+ .additions = &ibmstb4_iic0_def,
+ .show = &ocp_show_iic_data
+ },
+ { .vendor = OCP_VENDOR_IBM,
+ .function = OCP_FUNC_IIC,
+ .paddr = IIC1_BASE,
+ .irq = IIC1_IRQ,
+ .pm = IBM_CPM_IIC1,
+ .additions = &ibmstb4_iic1_def,
+ .show = &ocp_show_iic_data
+ },
+ { .vendor = OCP_VENDOR_IBM,
+ .function = OCP_FUNC_GPIO,
+ .paddr = GPIO0_BASE,
+ .irq = OCP_IRQ_NA,
+ .pm = IBM_CPM_GPIO0,
+ },
+ { .vendor = OCP_VENDOR_IBM,
+ .function = OCP_FUNC_IDE,
+ .paddr = IDE0_BASE,
+ .irq = IDE0_IRQ,
+ .pm = OCP_CPM_NA,
+ },
+ { .vendor = OCP_VENDOR_IBM,
+ .function = OCP_FUNC_USB,
+ .paddr = USB0_BASE,
+ .irq = USB0_IRQ,
+ .pm = OCP_CPM_NA,
+ },
+ { .vendor = OCP_VENDOR_INVALID,
+ }
+};
diff --git a/arch/ppc/platforms/4xx/ibmstb4.h b/arch/ppc/platforms/4xx/ibmstb4.h
new file mode 100644
index 0000000..bcb4b1e
--- /dev/null
+++ b/arch/ppc/platforms/4xx/ibmstb4.h
@@ -0,0 +1,238 @@
+/*
+ * arch/ppc/platforms/4xx/ibmstb4.h
+ *
+ * Author: Armin Kuster <akuster@mvista.com>
+ *
+ * 2001 (c) MontaVista, Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+
+#ifdef __KERNEL__
+#ifndef __ASM_IBMSTB4_H__
+#define __ASM_IBMSTB4_H__
+
+#include <linux/config.h>
+
+/* serial port defines */
+#define STB04xxx_IO_BASE ((uint)0xe0000000)
+#define PPC4xx_PCI_IO_ADDR STB04xxx_IO_BASE
+#define PPC4xx_ONB_IO_PADDR STB04xxx_IO_BASE
+#define PPC4xx_ONB_IO_VADDR ((uint)0xe0000000)
+#define PPC4xx_ONB_IO_SIZE ((uint)14*64*1024)
+
+/*
+ * map STB04xxx internal i/o address (0x400x00xx) to an address
+ * which is below the 2GB limit...
+ *
+ * 4000 000x uart1 -> 0xe000 000x
+ * 4001 00xx ppu
+ * 4002 00xx smart card
+ * 4003 000x iic
+ * 4004 000x uart0
+ * 4005 0xxx timer
+ * 4006 00xx gpio
+ * 4007 00xx smart card
+ * 400b 000x iic
+ * 400c 000x scp
+ * 400d 000x modem
+ * 400e 000x uart2
+*/
+#define STB04xxx_MAP_IO_ADDR(a) (((uint)(a)) + (STB04xxx_IO_BASE - 0x40000000))
+
+#define RS_TABLE_SIZE 3
+#define UART0_INT 20
+
+#ifdef __BOOTER__
+#define UART0_IO_BASE 0x40040000
+#else
+#define UART0_IO_BASE 0xe0040000
+#endif
+
+#define UART1_INT 21
+
+#ifdef __BOOTER__
+#define UART1_IO_BASE 0x40000000
+#else
+#define UART1_IO_BASE 0xe0000000
+#endif
+
+#define UART2_INT 31
+#ifdef __BOOTER__
+#define UART2_IO_BASE 0x400e0000
+#else
+#define UART2_IO_BASE 0xe00e0000
+#endif
+
+#define IDE0_BASE 0x400F0000
+#define IDE0_SIZE 0x200
+#define IDE0_IRQ 25
+#define IIC0_BASE 0x40030000
+#define IIC1_BASE 0x400b0000
+#define OPB0_BASE 0x40000000
+#define GPIO0_BASE 0x40060000
+
+#define USB0_IRQ 18
+#define USB0_BASE STB04xxx_MAP_IO_ADDR(0x40010000)
+#define USB0_EXTENT 4096
+
+#define IIC_NUMS 2
+#define UART_NUMS 3
+#define IIC0_IRQ 9
+#define IIC1_IRQ 10
+#define IIC_OWN 0x55
+#define IIC_CLOCK 50
+
+#define BD_EMAC_ADDR(e,i) bi_enetaddr[i]
+
+#define STD_UART_OP(num) \
+ { 0, BASE_BAUD, 0, UART##num##_INT, \
+ (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST), \
+ iomem_base: (u8 *)UART##num##_IO_BASE, \
+ io_type: SERIAL_IO_MEM},
+
+#if defined(CONFIG_UART0_TTYS0)
+#define SERIAL_DEBUG_IO_BASE UART0_IO_BASE
+#define SERIAL_PORT_DFNS \
+ STD_UART_OP(0) \
+ STD_UART_OP(1) \
+ STD_UART_OP(2)
+#endif
+
+#if defined(CONFIG_UART0_TTYS1)
+#define SERIAL_DEBUG_IO_BASE UART2_IO_BASE
+#define SERIAL_PORT_DFNS \
+ STD_UART_OP(1) \
+ STD_UART_OP(0) \
+ STD_UART_OP(2)
+#endif
+
+#if defined(CONFIG_UART0_TTYS2)
+#define SERIAL_DEBUG_IO_BASE UART2_IO_BASE
+#define SERIAL_PORT_DFNS \
+ STD_UART_OP(2) \
+ STD_UART_OP(0) \
+ STD_UART_OP(1)
+#endif
+
+#define DCRN_BE_BASE 0x090
+#define DCRN_DMA0_BASE 0x0C0
+#define DCRN_DMA1_BASE 0x0C8
+#define DCRN_DMA2_BASE 0x0D0
+#define DCRN_DMA3_BASE 0x0D8
+#define DCRNCAP_DMA_CC 1 /* have DMA chained count capability */
+#define DCRN_DMASR_BASE 0x0E0
+#define DCRN_PLB0_BASE 0x054
+#define DCRN_PLB1_BASE 0x064
+#define DCRN_POB0_BASE 0x0B0
+#define DCRN_SCCR_BASE 0x120
+#define DCRN_UIC0_BASE 0x040
+#define DCRN_BE_BASE 0x090
+#define DCRN_DMA0_BASE 0x0C0
+#define DCRN_DMA1_BASE 0x0C8
+#define DCRN_DMA2_BASE 0x0D0
+#define DCRN_DMA3_BASE 0x0D8
+#define DCRN_CIC_BASE 0x030
+#define DCRN_DMASR_BASE 0x0E0
+#define DCRN_EBIMC_BASE 0x070
+#define DCRN_DCRX_BASE 0x020
+#define DCRN_CPMFR_BASE 0x102
+#define DCRN_SCCR_BASE 0x120
+#define UIC0 DCRN_UIC0_BASE
+
+#define IBM_CPM_IIC0 0x80000000 /* IIC 0 interface */
+#define IBM_CPM_USB0 0x40000000 /* IEEE-1284 */
+#define IBM_CPM_IIC1 0x20000000 /* IIC 1 interface */
+#define IBM_CPM_CPU 0x10000000 /* PPC405B3 clock control */
+#define IBM_CPM_AUD 0x08000000 /* Audio Decoder */
+#define IBM_CPM_EBIU 0x04000000 /* External Bus Interface Unit */
+#define IBM_CPM_SDRAM1 0x02000000 /* SDRAM 1 memory controller */
+#define IBM_CPM_DMA 0x01000000 /* DMA controller */
+#define IBM_CPM_DMA1 0x00800000 /* reserved */
+#define IBM_CPM_XPT1 0x00400000 /* reserved */
+#define IBM_CPM_XPT2 0x00200000 /* reserved */
+#define IBM_CPM_UART1 0x00100000 /* Serial 1 / Infrared */
+#define IBM_CPM_UART0 0x00080000 /* Serial 0 / 16550 */
+#define IBM_CPM_EPI 0x00040000 /* DCR Extension */
+#define IBM_CPM_SC0 0x00020000 /* Smart Card 0 */
+#define IBM_CPM_VID 0x00010000 /* reserved */
+#define IBM_CPM_SC1 0x00008000 /* Smart Card 1 */
+#define IBM_CPM_USBSDRA 0x00004000 /* SDRAM 0 memory controller */
+#define IBM_CPM_XPT0 0x00002000 /* Transport - 54 Mhz */
+#define IBM_CPM_CBS 0x00001000 /* Cross Bar Switch */
+#define IBM_CPM_GPT 0x00000800 /* GPTPWM */
+#define IBM_CPM_GPIO0 0x00000400 /* General Purpose IO 0 */
+#define IBM_CPM_DENC 0x00000200 /* Digital video Encoder */
+#define IBM_CPM_TMRCLK 0x00000100 /* CPU timers */
+#define IBM_CPM_XPT27 0x00000080 /* Transport - 27 Mhz */
+#define IBM_CPM_UIC 0x00000040 /* Universal Interrupt Controller */
+#define IBM_CPM_SSP 0x00000010 /* Modem Serial Interface (SSP) */
+#define IBM_CPM_UART2 0x00000008 /* Serial Control Port */
+#define IBM_CPM_DDIO 0x00000004 /* Descrambler */
+#define IBM_CPM_VID2 0x00000002 /* Video Decoder clock domain 2 */
+
+#define DFLT_IBM4xx_PM ~(IBM_CPM_CPU | IBM_CPM_EBIU | IBM_CPM_SDRAM1 \
+ | IBM_CPM_DMA | IBM_CPM_DMA1 | IBM_CPM_CBS \
+ | IBM_CPM_USBSDRA | IBM_CPM_XPT0 | IBM_CPM_TMRCLK \
+ | IBM_CPM_XPT27 | IBM_CPM_UIC )
+
+#define DCRN_BEAR (DCRN_BE_BASE + 0x0) /* Bus Error Address Register */
+#define DCRN_BESR (DCRN_BE_BASE + 0x1) /* Bus Error Syndrome Register */
+/* DCRN_BESR */
+#define BESR_DSES 0x80000000 /* Data-Side Error Status */
+#define BESR_DMES 0x40000000 /* DMA Error Status */
+#define BESR_RWS 0x20000000 /* Read/Write Status */
+#define BESR_ETMASK 0x1C000000 /* Error Type */
+#define ET_PROT 0
+#define ET_PARITY 1
+#define ET_NCFG 2
+#define ET_BUSERR 4
+#define ET_BUSTO 6
+
+#define CHR1_CETE 0x00800000 /* CPU external timer enable */
+#define CHR1_PCIPW 0x00008000 /* PCI Int enable/Peripheral Write enable */
+
+#define DCRN_CICCR (DCRN_CIC_BASE + 0x0) /* CIC Control Register */
+#define DCRN_DMAS1 (DCRN_CIC_BASE + 0x1) /* DMA Select1 Register */
+#define DCRN_DMAS2 (DCRN_CIC_BASE + 0x2) /* DMA Select2 Register */
+#define DCRN_CICVCR (DCRN_CIC_BASE + 0x3) /* CIC Video COntro Register */
+#define DCRN_CICSEL3 (DCRN_CIC_BASE + 0x5) /* CIC Select 3 Register */
+#define DCRN_SGPO (DCRN_CIC_BASE + 0x6) /* CIC GPIO Output Register */
+#define DCRN_SGPOD (DCRN_CIC_BASE + 0x7) /* CIC GPIO OD Register */
+#define DCRN_SGPTC (DCRN_CIC_BASE + 0x8) /* CIC GPIO Tristate Ctrl Reg */
+#define DCRN_SGPI (DCRN_CIC_BASE + 0x9) /* CIC GPIO Input Reg */
+
+#define DCRN_DCRXICR (DCRN_DCRX_BASE + 0x0) /* Internal Control Register */
+#define DCRN_DCRXISR (DCRN_DCRX_BASE + 0x1) /* Internal Status Register */
+#define DCRN_DCRXECR (DCRN_DCRX_BASE + 0x2) /* External Control Register */
+#define DCRN_DCRXESR (DCRN_DCRX_BASE + 0x3) /* External Status Register */
+#define DCRN_DCRXTAR (DCRN_DCRX_BASE + 0x4) /* Target Address Register */
+#define DCRN_DCRXTDR (DCRN_DCRX_BASE + 0x5) /* Target Data Register */
+#define DCRN_DCRXIGR (DCRN_DCRX_BASE + 0x6) /* Interrupt Generation Register */
+#define DCRN_DCRXBCR (DCRN_DCRX_BASE + 0x7) /* Line Buffer Control Register */
+
+#define DCRN_BRCRH0 (DCRN_EBIMC_BASE + 0x0) /* Bus Region Config High 0 */
+#define DCRN_BRCRH1 (DCRN_EBIMC_BASE + 0x1) /* Bus Region Config High 1 */
+#define DCRN_BRCRH2 (DCRN_EBIMC_BASE + 0x2) /* Bus Region Config High 2 */
+#define DCRN_BRCRH3 (DCRN_EBIMC_BASE + 0x3) /* Bus Region Config High 3 */
+#define DCRN_BRCRH4 (DCRN_EBIMC_BASE + 0x4) /* Bus Region Config High 4 */
+#define DCRN_BRCRH5 (DCRN_EBIMC_BASE + 0x5) /* Bus Region Config High 5 */
+#define DCRN_BRCRH6 (DCRN_EBIMC_BASE + 0x6) /* Bus Region Config High 6 */
+#define DCRN_BRCRH7 (DCRN_EBIMC_BASE + 0x7) /* Bus Region Config High 7 */
+#define DCRN_BRCR0 (DCRN_EBIMC_BASE + 0x10) /* BRC 0 */
+#define DCRN_BRCR1 (DCRN_EBIMC_BASE + 0x11) /* BRC 1 */
+#define DCRN_BRCR2 (DCRN_EBIMC_BASE + 0x12) /* BRC 2 */
+#define DCRN_BRCR3 (DCRN_EBIMC_BASE + 0x13) /* BRC 3 */
+#define DCRN_BRCR4 (DCRN_EBIMC_BASE + 0x14) /* BRC 4 */
+#define DCRN_BRCR5 (DCRN_EBIMC_BASE + 0x15) /* BRC 5 */
+#define DCRN_BRCR6 (DCRN_EBIMC_BASE + 0x16) /* BRC 6 */
+#define DCRN_BRCR7 (DCRN_EBIMC_BASE + 0x17) /* BRC 7 */
+#define DCRN_BEAR0 (DCRN_EBIMC_BASE + 0x20) /* Bus Error Address Register */
+#define DCRN_BESR0 (DCRN_EBIMC_BASE + 0x21) /* Bus Error Status Register */
+#define DCRN_BIUCR (DCRN_EBIMC_BASE + 0x2A) /* Bus Interfac Unit Ctrl Reg */
+
+#include <asm/ibm405.h>
+
+#endif /* __ASM_IBMSTB4_H__ */
+#endif /* __KERNEL__ */
diff --git a/arch/ppc/platforms/4xx/ibmstbx25.c b/arch/ppc/platforms/4xx/ibmstbx25.c
new file mode 100644
index 0000000..b895b9c
--- /dev/null
+++ b/arch/ppc/platforms/4xx/ibmstbx25.c
@@ -0,0 +1,68 @@
+/*
+ * arch/ppc/platforms/4xx/ibmstbx25.c
+ *
+ * Author: Armin Kuster <akuster@mvista.com>
+ *
+ * 2000-2002 (c) MontaVista, Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+
+#include <linux/init.h>
+#include <asm/ocp.h>
+#include <platforms/4xx/ibmstbx25.h>
+#include <asm/ppc4xx_pic.h>
+
+static struct ocp_func_iic_data ibmstbx25_iic0_def = {
+ .fast_mode = 0, /* Use standad mode (100Khz) */
+};
+OCP_SYSFS_IIC_DATA()
+
+struct ocp_def core_ocp[] __initdata = {
+ { .vendor = OCP_VENDOR_IBM,
+ .function = OCP_FUNC_16550,
+ .index = 0,
+ .paddr = UART0_IO_BASE,
+ .irq = UART0_INT,
+ .pm = IBM_CPM_UART0,
+ },
+ { .vendor = OCP_VENDOR_IBM,
+ .function = OCP_FUNC_16550,
+ .index = 1,
+ .paddr = UART1_IO_BASE,
+ .irq = UART1_INT,
+ .pm = IBM_CPM_UART1,
+ },
+ { .vendor = OCP_VENDOR_IBM,
+ .function = OCP_FUNC_16550,
+ .index = 2,
+ .paddr = UART2_IO_BASE,
+ .irq = UART2_INT,
+ .pm = IBM_CPM_UART2,
+ },
+ { .vendor = OCP_VENDOR_IBM,
+ .function = OCP_FUNC_IIC,
+ .paddr = IIC0_BASE,
+ .irq = IIC0_IRQ,
+ .pm = IBM_CPM_IIC0,
+ .additions = &ibmstbx25_iic0_def,
+ .show = &ocp_show_iic_data
+ },
+ { .vendor = OCP_VENDOR_IBM,
+ .function = OCP_FUNC_GPIO,
+ .paddr = GPIO0_BASE,
+ .irq = OCP_IRQ_NA,
+ .pm = IBM_CPM_GPIO0,
+ },
+ { .vendor = OCP_VENDOR_INVALID
+ }
+};
+
+/* Polarity and triggering settings for internal interrupt sources */
+struct ppc4xx_uic_settings ppc4xx_core_uic_cfg[] __initdata = {
+ { .polarity = 0xffff8f80,
+ .triggering = 0x00000000,
+ .ext_irq_mask = 0x0000707f, /* IRQ7 - IRQ9, IRQ0 - IRQ6 */
+ }
+};
diff --git a/arch/ppc/platforms/4xx/ibmstbx25.h b/arch/ppc/platforms/4xx/ibmstbx25.h
new file mode 100644
index 0000000..9a2efc3
--- /dev/null
+++ b/arch/ppc/platforms/4xx/ibmstbx25.h
@@ -0,0 +1,261 @@
+/*
+ * arch/ppc/platforms/4xx/ibmstbx25.h
+ *
+ * Author: Armin Kuster <akuster@mvista.com>
+ *
+ * 2002 (c) MontaVista, Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+
+#ifdef __KERNEL__
+#ifndef __ASM_IBMSTBX25_H__
+#define __ASM_IBMSTBX25_H__
+
+#include <linux/config.h>
+
+/* serial port defines */
+#define STBx25xx_IO_BASE ((uint)0xe0000000)
+#define PPC4xx_ONB_IO_PADDR STBx25xx_IO_BASE
+#define PPC4xx_ONB_IO_VADDR ((uint)0xe0000000)
+#define PPC4xx_ONB_IO_SIZE ((uint)14*64*1024)
+
+/*
+ * map STBxxxx internal i/o address (0x400x00xx) to an address
+ * which is below the 2GB limit...
+ *
+ * 4000 000x uart1 -> 0xe000 000x
+ * 4001 00xx uart2
+ * 4002 00xx smart card
+ * 4003 000x iic
+ * 4004 000x uart0
+ * 4005 0xxx timer
+ * 4006 00xx gpio
+ * 4007 00xx smart card
+ * 400b 000x iic
+ * 400c 000x scp
+ * 400d 000x modem
+ * 400e 000x uart2
+*/
+#define STBx25xx_MAP_IO_ADDR(a) (((uint)(a)) + (STBx25xx_IO_BASE - 0x40000000))
+
+#define RS_TABLE_SIZE 3
+
+#define OPB_BASE_START 0x40000000
+#define EBIU_BASE_START 0xF0100000
+#define DCR_BASE_START 0x0000
+
+#ifdef __BOOTER__
+#define UART1_IO_BASE 0x40000000
+#define UART2_IO_BASE 0x40010000
+#else
+#define UART1_IO_BASE 0xe0000000
+#define UART2_IO_BASE 0xe0010000
+#endif
+#define SC0_BASE 0x40020000 /* smart card #0 */
+#define IIC0_BASE 0x40030000
+#ifdef __BOOTER__
+#define UART0_IO_BASE 0x40040000
+#else
+#define UART0_IO_BASE 0xe0040000
+#endif
+#define SCC0_BASE 0x40040000 /* Serial 0 controller IrdA */
+#define GPT0_BASE 0x40050000 /* General purpose timers */
+#define GPIO0_BASE 0x40060000
+#define SC1_BASE 0x40070000 /* smart card #1 */
+#define SCP0_BASE 0x400C0000 /* Serial Controller Port */
+#define SSP0_BASE 0x400D0000 /* Sync serial port */
+
+#define IDE0_BASE 0xf0100000
+#define REDWOOD_IDE_CTRL 0xf1100000
+
+#define RTCFPC_IRQ 0
+#define XPORT_IRQ 1
+#define AUD_IRQ 2
+#define AID_IRQ 3
+#define DMA0 4
+#define DMA1_IRQ 5
+#define DMA2_IRQ 6
+#define DMA3_IRQ 7
+#define SC0_IRQ 8
+#define IIC0_IRQ 9
+#define IIR0_IRQ 10
+#define GPT0_IRQ 11
+#define GPT1_IRQ 12
+#define SCP0_IRQ 13
+#define SSP0_IRQ 14
+#define GPT2_IRQ 15 /* count down timer */
+#define SC1_IRQ 16
+/* IRQ 17 - 19 external */
+#define UART0_INT 20
+#define UART1_INT 21
+#define UART2_INT 22
+#define XPTDMA_IRQ 23
+#define DCRIDE_IRQ 24
+/* IRQ 25 - 30 external */
+#define IDE0_IRQ 26
+
+#define IIC_NUMS 1
+#define UART_NUMS 3
+#define IIC_OWN 0x55
+#define IIC_CLOCK 50
+
+#define BD_EMAC_ADDR(e,i) bi_enetaddr[i]
+
+#define STD_UART_OP(num) \
+ { 0, BASE_BAUD, 0, UART##num##_INT, \
+ (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST), \
+ iomem_base: (u8 *)UART##num##_IO_BASE, \
+ io_type: SERIAL_IO_MEM},
+
+#if defined(CONFIG_UART0_TTYS0)
+#define SERIAL_DEBUG_IO_BASE UART0_IO_BASE
+#define SERIAL_PORT_DFNS \
+ STD_UART_OP(0) \
+ STD_UART_OP(1) \
+ STD_UART_OP(2)
+#endif
+
+#if defined(CONFIG_UART0_TTYS1)
+#define SERIAL_DEBUG_IO_BASE UART2_IO_BASE
+#define SERIAL_PORT_DFNS \
+ STD_UART_OP(1) \
+ STD_UART_OP(0) \
+ STD_UART_OP(2)
+#endif
+
+#if defined(CONFIG_UART0_TTYS2)
+#define SERIAL_DEBUG_IO_BASE UART2_IO_BASE
+#define SERIAL_PORT_DFNS \
+ STD_UART_OP(2) \
+ STD_UART_OP(0) \
+ STD_UART_OP(1)
+#endif
+
+#define DCRN_BE_BASE 0x090
+#define DCRN_DMA0_BASE 0x0C0
+#define DCRN_DMA1_BASE 0x0C8
+#define DCRN_DMA2_BASE 0x0D0
+#define DCRN_DMA3_BASE 0x0D8
+#define DCRNCAP_DMA_CC 1 /* have DMA chained count capability */
+#define DCRN_DMASR_BASE 0x0E0
+#define DCRN_PLB0_BASE 0x054
+#define DCRN_PLB1_BASE 0x064
+#define DCRN_POB0_BASE 0x0B0
+#define DCRN_SCCR_BASE 0x120
+#define DCRN_UIC0_BASE 0x040
+#define DCRN_BE_BASE 0x090
+#define DCRN_DMA0_BASE 0x0C0
+#define DCRN_DMA1_BASE 0x0C8
+#define DCRN_DMA2_BASE 0x0D0
+#define DCRN_DMA3_BASE 0x0D8
+#define DCRN_CIC_BASE 0x030
+#define DCRN_DMASR_BASE 0x0E0
+#define DCRN_EBIMC_BASE 0x070
+#define DCRN_DCRX_BASE 0x020
+#define DCRN_CPMFR_BASE 0x102
+#define DCRN_SCCR_BASE 0x120
+#define DCRN_RTCFP_BASE 0x310
+
+#define UIC0 DCRN_UIC0_BASE
+
+#define IBM_CPM_IIC0 0x80000000 /* IIC 0 interface */
+#define IBM_CPM_CPU 0x10000000 /* PPC405B3 clock control */
+#define IBM_CPM_AUD 0x08000000 /* Audio Decoder */
+#define IBM_CPM_EBIU 0x04000000 /* External Bus Interface Unit */
+#define IBM_CPM_IRR 0x02000000 /* Infrared receiver */
+#define IBM_CPM_DMA 0x01000000 /* DMA controller */
+#define IBM_CPM_UART2 0x00200000 /* Serial Control Port */
+#define IBM_CPM_UART1 0x00100000 /* Serial 1 / Infrared */
+#define IBM_CPM_UART0 0x00080000 /* Serial 0 / 16550 */
+#define IBM_PM_DCRIDE 0x00040000 /* DCR timeout & IDE line Mode clock */
+#define IBM_CPM_SC0 0x00020000 /* Smart Card 0 */
+#define IBM_CPM_VID 0x00010000 /* reserved */
+#define IBM_CPM_SC1 0x00008000 /* Smart Card 0 */
+#define IBM_CPM_XPT0 0x00002000 /* Transport - 54 Mhz */
+#define IBM_CPM_CBS 0x00001000 /* Cross Bar Switch */
+#define IBM_CPM_GPT 0x00000800 /* GPTPWM */
+#define IBM_CPM_GPIO0 0x00000400 /* General Purpose IO 0 */
+#define IBM_CPM_DENC 0x00000200 /* Digital video Encoder */
+#define IBM_CPM_C405T 0x00000100 /* CPU timers */
+#define IBM_CPM_XPT27 0x00000080 /* Transport - 27 Mhz */
+#define IBM_CPM_UIC 0x00000040 /* Universal Interrupt Controller */
+#define IBM_CPM_RTCFPC 0x00000020 /* Realtime clock and front panel */
+#define IBM_CPM_SSP 0x00000010 /* Modem Serial Interface (SSP) */
+#define IBM_CPM_VID2 0x00000002 /* Video Decoder clock domain 2 */
+#define DFLT_IBM4xx_PM ~(IBM_CPM_CPU | IBM_CPM_EBIU | IBM_CPM_DMA \
+ | IBM_CPM_CBS | IBM_CPM_XPT0 | IBM_CPM_C405T \
+ | IBM_CPM_XPT27 | IBM_CPM_UIC)
+
+#define DCRN_BEAR (DCRN_BE_BASE + 0x0) /* Bus Error Address Register */
+#define DCRN_BESR (DCRN_BE_BASE + 0x1) /* Bus Error Syndrome Register */
+/* DCRN_BESR */
+#define BESR_DSES 0x80000000 /* Data-Side Error Status */
+#define BESR_DMES 0x40000000 /* DMA Error Status */
+#define BESR_RWS 0x20000000 /* Read/Write Status */
+#define BESR_ETMASK 0x1C000000 /* Error Type */
+#define ET_PROT 0
+#define ET_PARITY 1
+#define ET_NCFG 2
+#define ET_BUSERR 4
+#define ET_BUSTO 6
+
+#define CHR1_CETE 0x00800000 /* CPU external timer enable */
+#define CHR1_PCIPW 0x00008000 /* PCI Int enable/Peripheral Write enable */
+
+#define DCRN_CICCR (DCRN_CIC_BASE + 0x0) /* CIC Control Register */
+#define DCRN_DMAS1 (DCRN_CIC_BASE + 0x1) /* DMA Select1 Register */
+#define DCRN_DMAS2 (DCRN_CIC_BASE + 0x2) /* DMA Select2 Register */
+#define DCRN_CICVCR (DCRN_CIC_BASE + 0x3) /* CIC Video COntro Register */
+#define DCRN_CICSEL3 (DCRN_CIC_BASE + 0x5) /* CIC Select 3 Register */
+#define DCRN_SGPO (DCRN_CIC_BASE + 0x6) /* CIC GPIO Output Register */
+#define DCRN_SGPOD (DCRN_CIC_BASE + 0x7) /* CIC GPIO OD Register */
+#define DCRN_SGPTC (DCRN_CIC_BASE + 0x8) /* CIC GPIO Tristate Ctrl Reg */
+#define DCRN_SGPI (DCRN_CIC_BASE + 0x9) /* CIC GPIO Input Reg */
+
+#define DCRN_DCRXICR (DCRN_DCRX_BASE + 0x0) /* Internal Control Register */
+#define DCRN_DCRXISR (DCRN_DCRX_BASE + 0x1) /* Internal Status Register */
+#define DCRN_DCRXECR (DCRN_DCRX_BASE + 0x2) /* External Control Register */
+#define DCRN_DCRXESR (DCRN_DCRX_BASE + 0x3) /* External Status Register */
+#define DCRN_DCRXTAR (DCRN_DCRX_BASE + 0x4) /* Target Address Register */
+#define DCRN_DCRXTDR (DCRN_DCRX_BASE + 0x5) /* Target Data Register */
+#define DCRN_DCRXIGR (DCRN_DCRX_BASE + 0x6) /* Interrupt Generation Register */
+#define DCRN_DCRXBCR (DCRN_DCRX_BASE + 0x7) /* Line Buffer Control Register */
+
+#define DCRN_BRCRH0 (DCRN_EBIMC_BASE + 0x0) /* Bus Region Config High 0 */
+#define DCRN_BRCRH1 (DCRN_EBIMC_BASE + 0x1) /* Bus Region Config High 1 */
+#define DCRN_BRCRH2 (DCRN_EBIMC_BASE + 0x2) /* Bus Region Config High 2 */
+#define DCRN_BRCRH3 (DCRN_EBIMC_BASE + 0x3) /* Bus Region Config High 3 */
+#define DCRN_BRCRH4 (DCRN_EBIMC_BASE + 0x4) /* Bus Region Config High 4 */
+#define DCRN_BRCRH5 (DCRN_EBIMC_BASE + 0x5) /* Bus Region Config High 5 */
+#define DCRN_BRCRH6 (DCRN_EBIMC_BASE + 0x6) /* Bus Region Config High 6 */
+#define DCRN_BRCRH7 (DCRN_EBIMC_BASE + 0x7) /* Bus Region Config High 7 */
+#define DCRN_BRCR0 (DCRN_EBIMC_BASE + 0x10) /* BRC 0 */
+#define DCRN_BRCR1 (DCRN_EBIMC_BASE + 0x11) /* BRC 1 */
+#define DCRN_BRCR2 (DCRN_EBIMC_BASE + 0x12) /* BRC 2 */
+#define DCRN_BRCR3 (DCRN_EBIMC_BASE + 0x13) /* BRC 3 */
+#define DCRN_BRCR4 (DCRN_EBIMC_BASE + 0x14) /* BRC 4 */
+#define DCRN_BRCR5 (DCRN_EBIMC_BASE + 0x15) /* BRC 5 */
+#define DCRN_BRCR6 (DCRN_EBIMC_BASE + 0x16) /* BRC 6 */
+#define DCRN_BRCR7 (DCRN_EBIMC_BASE + 0x17) /* BRC 7 */
+#define DCRN_BEAR0 (DCRN_EBIMC_BASE + 0x20) /* Bus Error Address Register */
+#define DCRN_BESR0 (DCRN_EBIMC_BASE + 0x21) /* Bus Error Status Register */
+#define DCRN_BIUCR (DCRN_EBIMC_BASE + 0x2A) /* Bus Interfac Unit Ctrl Reg */
+
+#define DCRN_RTC_FPC0_CNTL (DCRN_RTCFP_BASE + 0x00) /* RTC cntl */
+#define DCRN_RTC_FPC0_INT (DCRN_RTCFP_BASE + 0x01) /* RTC Interrupt */
+#define DCRN_RTC_FPC0_TIME (DCRN_RTCFP_BASE + 0x02) /* RTC time reg */
+#define DCRN_RTC_FPC0_ALRM (DCRN_RTCFP_BASE + 0x03) /* RTC Alarm reg */
+#define DCRN_RTC_FPC0_D1 (DCRN_RTCFP_BASE + 0x04) /* LED Data 1 */
+#define DCRN_RTC_FPC0_D2 (DCRN_RTCFP_BASE + 0x05) /* LED Data 2 */
+#define DCRN_RTC_FPC0_D3 (DCRN_RTCFP_BASE + 0x06) /* LED Data 3 */
+#define DCRN_RTC_FPC0_D4 (DCRN_RTCFP_BASE + 0x07) /* LED Data 4 */
+#define DCRN_RTC_FPC0_D5 (DCRN_RTCFP_BASE + 0x08) /* LED Data 5 */
+#define DCRN_RTC_FPC0_FCNTL (DCRN_RTCFP_BASE + 0x09) /* LED control */
+#define DCRN_RTC_FPC0_BRT (DCRN_RTCFP_BASE + 0x0A) /* Brightness cntl */
+
+#include <asm/ibm405.h>
+
+#endif /* __ASM_IBMSTBX25_H__ */
+#endif /* __KERNEL__ */
diff --git a/arch/ppc/platforms/4xx/luan.c b/arch/ppc/platforms/4xx/luan.c
new file mode 100644
index 0000000..1df2339
--- /dev/null
+++ b/arch/ppc/platforms/4xx/luan.c
@@ -0,0 +1,387 @@
+/*
+ * arch/ppc/platforms/4xx/luan.c
+ *
+ * Luan board specific routines
+ *
+ * Matt Porter <mporter@kernel.crashing.org>
+ *
+ * Copyright 2004-2005 MontaVista Software Inc.
+ *
+ * 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.
+ */
+
+#include <linux/config.h>
+#include <linux/stddef.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/reboot.h>
+#include <linux/pci.h>
+#include <linux/kdev_t.h>
+#include <linux/types.h>
+#include <linux/major.h>
+#include <linux/blkdev.h>
+#include <linux/console.h>
+#include <linux/delay.h>
+#include <linux/ide.h>
+#include <linux/initrd.h>
+#include <linux/irq.h>
+#include <linux/seq_file.h>
+#include <linux/root_dev.h>
+#include <linux/tty.h>
+#include <linux/serial.h>
+#include <linux/serial_core.h>
+
+#include <asm/system.h>
+#include <asm/pgtable.h>
+#include <asm/page.h>
+#include <asm/dma.h>
+#include <asm/io.h>
+#include <asm/machdep.h>
+#include <asm/ocp.h>
+#include <asm/pci-bridge.h>
+#include <asm/time.h>
+#include <asm/todc.h>
+#include <asm/bootinfo.h>
+#include <asm/ppc4xx_pic.h>
+#include <asm/ppcboot.h>
+
+#include <syslib/ibm44x_common.h>
+#include <syslib/ibm440gx_common.h>
+#include <syslib/ibm440sp_common.h>
+
+/*
+ * This is a horrible kludge, we eventually need to abstract this
+ * generic PHY stuff, so the standard phy mode defines can be
+ * easily used from arch code.
+ */
+#include "../../../../drivers/net/ibm_emac/ibm_emac_phy.h"
+
+bd_t __res;
+
+static struct ibm44x_clocks clocks __initdata;
+
+static void __init
+luan_calibrate_decr(void)
+{
+ unsigned int freq;
+
+ if (mfspr(SPRN_CCR1) & CCR1_TCS)
+ freq = LUAN_TMR_CLK;
+ else
+ freq = clocks.cpu;
+
+ ibm44x_calibrate_decr(freq);
+}
+
+static int
+luan_show_cpuinfo(struct seq_file *m)
+{
+ seq_printf(m, "vendor\t\t: IBM\n");
+ seq_printf(m, "machine\t\t: PPC440SP EVB (Luan)\n");
+
+ return 0;
+}
+
+static inline int
+luan_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin)
+{
+ struct pci_controller *hose = pci_bus_to_hose(dev->bus->number);
+
+ /* PCIX0 in adapter mode, no host interrupt routing */
+
+ /* PCIX1 */
+ if (hose->index == 0) {
+ static char pci_irq_table[][4] =
+ /*
+ * PCI IDSEL/INTPIN->INTLINE
+ * A B C D
+ */
+ {
+ { 49, 49, 49, 49 }, /* IDSEL 1 - PCIX1 Slot 0 */
+ { 49, 49, 49, 49 }, /* IDSEL 2 - PCIX1 Slot 1 */
+ { 49, 49, 49, 49 }, /* IDSEL 3 - PCIX1 Slot 2 */
+ { 49, 49, 49, 49 }, /* IDSEL 4 - PCIX1 Slot 3 */
+ };
+ const long min_idsel = 1, max_idsel = 4, irqs_per_slot = 4;
+ return PCI_IRQ_TABLE_LOOKUP;
+ /* PCIX2 */
+ } else if (hose->index == 1) {
+ static char pci_irq_table[][4] =
+ /*
+ * PCI IDSEL/INTPIN->INTLINE
+ * A B C D
+ */
+ {
+ { 50, 50, 50, 50 }, /* IDSEL 1 - PCIX2 Slot 0 */
+ { 50, 50, 50, 50 }, /* IDSEL 2 - PCIX2 Slot 1 */
+ { 50, 50, 50, 50 }, /* IDSEL 3 - PCIX2 Slot 2 */
+ { 50, 50, 50, 50 }, /* IDSEL 4 - PCIX2 Slot 3 */
+ };
+ const long min_idsel = 1, max_idsel = 4, irqs_per_slot = 4;
+ return PCI_IRQ_TABLE_LOOKUP;
+ }
+ return -1;
+}
+
+static void __init luan_set_emacdata(void)
+{
+ struct ocp_def *def;
+ struct ocp_func_emac_data *emacdata;
+
+ /* Set phy_map, phy_mode, and mac_addr for the EMAC */
+ def = ocp_get_one_device(OCP_VENDOR_IBM, OCP_FUNC_EMAC, 0);
+ emacdata = def->additions;
+ emacdata->phy_map = 0x00000001; /* Skip 0x00 */
+ emacdata->phy_mode = PHY_MODE_GMII;
+ memcpy(emacdata->mac_addr, __res.bi_enetaddr, 6);
+}
+
+#define PCIX_READW(offset) \
+ (readw((void *)((u32)pcix_reg_base+offset)))
+
+#define PCIX_WRITEW(value, offset) \
+ (writew(value, (void *)((u32)pcix_reg_base+offset)))
+
+#define PCIX_WRITEL(value, offset) \
+ (writel(value, (void *)((u32)pcix_reg_base+offset)))
+
+static void __init
+luan_setup_pcix(void)
+{
+ int i;
+ void *pcix_reg_base;
+
+ for (i=0;i<3;i++) {
+ pcix_reg_base = ioremap64(PCIX0_REG_BASE + i*PCIX_REG_OFFSET, PCIX_REG_SIZE);
+
+ /* Enable PCIX0 I/O, Mem, and Busmaster cycles */
+ PCIX_WRITEW(PCIX_READW(PCIX0_COMMAND) | PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER, PCIX0_COMMAND);
+
+ /* Disable all windows */
+ PCIX_WRITEL(0, PCIX0_POM0SA);
+ PCIX_WRITEL(0, PCIX0_POM1SA);
+ PCIX_WRITEL(0, PCIX0_POM2SA);
+ PCIX_WRITEL(0, PCIX0_PIM0SA);
+ PCIX_WRITEL(0, PCIX0_PIM0SAH);
+ PCIX_WRITEL(0, PCIX0_PIM1SA);
+ PCIX_WRITEL(0, PCIX0_PIM2SA);
+ PCIX_WRITEL(0, PCIX0_PIM2SAH);
+
+ /*
+ * Setup 512MB PLB->PCI outbound mem window
+ * (a_n000_0000->0_n000_0000)
+ * */
+ PCIX_WRITEL(0x0000000a, PCIX0_POM0LAH);
+ PCIX_WRITEL(0x80000000 | i*LUAN_PCIX_MEM_SIZE, PCIX0_POM0LAL);
+ PCIX_WRITEL(0x00000000, PCIX0_POM0PCIAH);
+ PCIX_WRITEL(0x80000000 | i*LUAN_PCIX_MEM_SIZE, PCIX0_POM0PCIAL);
+ PCIX_WRITEL(0xe0000001, PCIX0_POM0SA);
+
+ /* Setup 2GB PCI->PLB inbound memory window at 0, enable MSIs */
+ PCIX_WRITEL(0x00000000, PCIX0_PIM0LAH);
+ PCIX_WRITEL(0x00000000, PCIX0_PIM0LAL);
+ PCIX_WRITEL(0xe0000007, PCIX0_PIM0SA);
+ PCIX_WRITEL(0xffffffff, PCIX0_PIM0SAH);
+
+ iounmap(pcix_reg_base);
+ }
+
+ eieio();
+}
+
+static void __init
+luan_setup_hose(struct pci_controller *hose,
+ int lower_mem,
+ int upper_mem,
+ int cfga,
+ int cfgd,
+ u64 pcix_io_base)
+{
+ char name[20];
+
+ sprintf(name, "PCIX%d host bridge", hose->index);
+
+ hose->pci_mem_offset = LUAN_PCIX_MEM_OFFSET;
+
+ pci_init_resource(&hose->io_resource,
+ LUAN_PCIX_LOWER_IO,
+ LUAN_PCIX_UPPER_IO,
+ IORESOURCE_IO,
+ name);
+
+ pci_init_resource(&hose->mem_resources[0],
+ lower_mem,
+ upper_mem,
+ IORESOURCE_MEM,
+ name);
+
+ hose->io_space.start = LUAN_PCIX_LOWER_IO;
+ hose->io_space.end = LUAN_PCIX_UPPER_IO;
+ hose->mem_space.start = lower_mem;
+ hose->mem_space.end = upper_mem;
+ isa_io_base =
+ (unsigned long)ioremap64(pcix_io_base, PCIX_IO_SIZE);
+ hose->io_base_virt = (void *)isa_io_base;
+
+ setup_indirect_pci(hose, cfga, cfgd);
+ hose->set_cfg_type = 1;
+}
+
+static void __init
+luan_setup_hoses(void)
+{
+ struct pci_controller *hose1, *hose2;
+
+ /* Configure windows on the PCI-X host bridge */
+ luan_setup_pcix();
+
+ /* Allocate hoses for PCIX1 and PCIX2 */
+ hose1 = pcibios_alloc_controller();
+ hose2 = pcibios_alloc_controller();
+ if (!hose1 || !hose2)
+ return;
+
+ /* Setup PCIX1 */
+ hose1->first_busno = 0;
+ hose1->last_busno = 0xff;
+
+ luan_setup_hose(hose1,
+ LUAN_PCIX1_LOWER_MEM,
+ LUAN_PCIX1_UPPER_MEM,
+ PCIX1_CFGA,
+ PCIX1_CFGD,
+ PCIX1_IO_BASE);
+
+ hose1->last_busno = pciauto_bus_scan(hose1, hose1->first_busno);
+
+ /* Setup PCIX2 */
+ hose2->first_busno = hose1->last_busno + 1;
+ hose2->last_busno = 0xff;
+
+ luan_setup_hose(hose2,
+ LUAN_PCIX2_LOWER_MEM,
+ LUAN_PCIX2_UPPER_MEM,
+ PCIX2_CFGA,
+ PCIX2_CFGD,
+ PCIX2_IO_BASE);
+
+ hose2->last_busno = pciauto_bus_scan(hose2, hose2->first_busno);
+
+ ppc_md.pci_swizzle = common_swizzle;
+ ppc_md.pci_map_irq = luan_map_irq;
+}
+
+TODC_ALLOC();
+
+static void __init
+luan_early_serial_map(void)
+{
+ struct uart_port port;
+
+ /* Setup ioremapped serial port access */
+ memset(&port, 0, sizeof(port));
+ port.membase = ioremap64(PPC440SP_UART0_ADDR, 8);
+ port.irq = UART0_INT;
+ port.uartclk = clocks.uart0;
+ port.regshift = 0;
+ port.iotype = SERIAL_IO_MEM;
+ port.flags = ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST;
+ port.line = 0;
+
+ if (early_serial_setup(&port) != 0) {
+ printk("Early serial init of port 0 failed\n");
+ }
+
+ port.membase = ioremap64(PPC440SP_UART1_ADDR, 8);
+ port.irq = UART1_INT;
+ port.uartclk = clocks.uart1;
+ port.line = 1;
+
+ if (early_serial_setup(&port) != 0) {
+ printk("Early serial init of port 1 failed\n");
+ }
+
+ port.membase = ioremap64(PPC440SP_UART2_ADDR, 8);
+ port.irq = UART2_INT;
+ port.uartclk = BASE_BAUD;
+ port.line = 2;
+
+ if (early_serial_setup(&port) != 0) {
+ printk("Early serial init of port 2 failed\n");
+ }
+}
+
+static void __init
+luan_setup_arch(void)
+{
+ luan_set_emacdata();
+
+#if !defined(CONFIG_BDI_SWITCH)
+ /*
+ * The Abatron BDI JTAG debugger does not tolerate others
+ * mucking with the debug registers.
+ */
+ mtspr(SPRN_DBCR0, (DBCR0_TDE | DBCR0_IDM));
+#endif
+
+ /*
+ * Determine various clocks.
+ * To be completely correct we should get SysClk
+ * from FPGA, because it can be changed by on-board switches
+ * --ebs
+ */
+ /* 440GX and 440SP clocking is the same -mdp */
+ ibm440gx_get_clocks(&clocks, 33333333, 6 * 1843200);
+ ocp_sys_info.opb_bus_freq = clocks.opb;
+
+ /* init to some ~sane value until calibrate_delay() runs */
+ loops_per_jiffy = 50000000/HZ;
+
+ /* Setup PCIXn host bridges */
+ luan_setup_hoses();
+
+#ifdef CONFIG_BLK_DEV_INITRD
+ if (initrd_start)
+ ROOT_DEV = Root_RAM0;
+ else
+#endif
+#ifdef CONFIG_ROOT_NFS
+ ROOT_DEV = Root_NFS;
+#else
+ ROOT_DEV = Root_HDA1;
+#endif
+
+ luan_early_serial_map();
+
+ /* Identify the system */
+ printk("Luan port (MontaVista Software, Inc. <source@mvista.com>)\n");
+}
+
+void __init platform_init(unsigned long r3, unsigned long r4,
+ unsigned long r5, unsigned long r6, unsigned long r7)
+{
+ parse_bootinfo(find_bootinfo());
+
+ /*
+ * If we were passed in a board information, copy it into the
+ * residual data area.
+ */
+ if (r3)
+ __res = *(bd_t *)(r3 + KERNELBASE);
+
+ ibm44x_platform_init();
+
+ ppc_md.setup_arch = luan_setup_arch;
+ ppc_md.show_cpuinfo = luan_show_cpuinfo;
+ ppc_md.find_end_of_memory = ibm440sp_find_end_of_memory;
+ ppc_md.get_irq = NULL; /* Set in ppc4xx_pic_init() */
+
+ ppc_md.calibrate_decr = luan_calibrate_decr;
+#ifdef CONFIG_KGDB
+ ppc_md.early_serial_map = luan_early_serial_map;
+#endif
+}
diff --git a/arch/ppc/platforms/4xx/luan.h b/arch/ppc/platforms/4xx/luan.h
new file mode 100644
index 0000000..09b444c
--- /dev/null
+++ b/arch/ppc/platforms/4xx/luan.h
@@ -0,0 +1,80 @@
+/*
+ * arch/ppc/platforms/4xx/luan.h
+ *
+ * Luan board definitions
+ *
+ * Matt Porter <mporter@kernel.crashing.org>
+ *
+ * Copyright 2004-2005 MontaVista Software Inc.
+ *
+ * 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.
+ *
+ */
+
+#ifdef __KERNEL__
+#ifndef __ASM_LUAN_H__
+#define __ASM_LUAN_H__
+
+#include <linux/config.h>
+#include <platforms/4xx/ibm440sp.h>
+
+/* F/W TLB mapping used in bootloader glue to reset EMAC */
+#define PPC44x_EMAC0_MR0 0xa0000800
+
+/* Location of MAC addresses in PIBS image */
+#define PIBS_FLASH_BASE 0xffe00000
+#define PIBS_MAC_BASE (PIBS_FLASH_BASE+0x1b0400)
+
+/* External timer clock frequency */
+#define LUAN_TMR_CLK 25000000
+
+/* Flash */
+#define LUAN_FPGA_REG_0 0x0000000148300000ULL
+#define LUAN_BOOT_LARGE_FLASH(x) (x & 0x40)
+#define LUAN_SMALL_FLASH_LOW 0x00000001ff900000ULL
+#define LUAN_SMALL_FLASH_HIGH 0x00000001ffe00000ULL
+#define LUAN_SMALL_FLASH_SIZE 0x100000
+#define LUAN_LARGE_FLASH_LOW 0x00000001ff800000ULL
+#define LUAN_LARGE_FLASH_HIGH 0x00000001ffc00000ULL
+#define LUAN_LARGE_FLASH_SIZE 0x400000
+
+/*
+ * Serial port defines
+ */
+#define RS_TABLE_SIZE 3
+
+/* PIBS defined UART mappings, used before early_serial_setup */
+#define UART0_IO_BASE 0xa0000200
+#define UART1_IO_BASE 0xa0000300
+#define UART2_IO_BASE 0xa0000600
+
+#define BASE_BAUD 11059200
+#define STD_UART_OP(num) \
+ { 0, BASE_BAUD, 0, UART##num##_INT, \
+ (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST), \
+ iomem_base: UART##num##_IO_BASE, \
+ io_type: SERIAL_IO_MEM},
+
+#define SERIAL_PORT_DFNS \
+ STD_UART_OP(0) \
+ STD_UART_OP(1) \
+ STD_UART_OP(2)
+
+/* PCI support */
+#define LUAN_PCIX_LOWER_IO 0x00000000
+#define LUAN_PCIX_UPPER_IO 0x0000ffff
+#define LUAN_PCIX0_LOWER_MEM 0x80000000
+#define LUAN_PCIX0_UPPER_MEM 0x9fffffff
+#define LUAN_PCIX1_LOWER_MEM 0xa0000000
+#define LUAN_PCIX1_UPPER_MEM 0xbfffffff
+#define LUAN_PCIX2_LOWER_MEM 0xc0000000
+#define LUAN_PCIX2_UPPER_MEM 0xdfffffff
+
+#define LUAN_PCIX_MEM_SIZE 0x20000000
+#define LUAN_PCIX_MEM_OFFSET 0x00000000
+
+#endif /* __ASM_LUAN_H__ */
+#endif /* __KERNEL__ */
diff --git a/arch/ppc/platforms/4xx/oak.c b/arch/ppc/platforms/4xx/oak.c
new file mode 100644
index 0000000..fa25ee1
--- /dev/null
+++ b/arch/ppc/platforms/4xx/oak.c
@@ -0,0 +1,255 @@
+/*
+ *
+ * Copyright (c) 1999-2000 Grant Erickson <grant@lcse.umn.edu>
+ *
+ * Module name: oak.c
+ *
+ * Description:
+ * Architecture- / platform-specific boot-time initialization code for
+ * the IBM PowerPC 403GCX "Oak" evaluation board. Adapted from original
+ * code by Gary Thomas, Cort Dougan <cort@fsmlabs.com>, and Dan Malek
+ * <dan@net4x.com>.
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/smp.h>
+#include <linux/threads.h>
+#include <linux/param.h>
+#include <linux/string.h>
+#include <linux/initrd.h>
+#include <linux/irq.h>
+#include <linux/seq_file.h>
+
+#include <asm/board.h>
+#include <asm/machdep.h>
+#include <asm/page.h>
+#include <asm/bootinfo.h>
+#include <asm/ppc4xx_pic.h>
+#include <asm/time.h>
+
+#include "oak.h"
+
+/* Function Prototypes */
+
+extern void abort(void);
+
+/* Global Variables */
+
+unsigned char __res[sizeof(bd_t)];
+
+
+/*
+ * void __init oak_init()
+ *
+ * Description:
+ * This routine...
+ *
+ * Input(s):
+ * r3 - Optional pointer to a board information structure.
+ * r4 - Optional pointer to the physical starting address of the init RAM
+ * disk.
+ * r5 - Optional pointer to the physical ending address of the init RAM
+ * disk.
+ * r6 - Optional pointer to the physical starting address of any kernel
+ * command-line parameters.
+ * r7 - Optional pointer to the physical ending address of any kernel
+ * command-line parameters.
+ *
+ * Output(s):
+ * N/A
+ *
+ * Returns:
+ * N/A
+ *
+ */
+void __init
+platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
+ unsigned long r6, unsigned long r7)
+{
+ parse_bootinfo(find_bootinfo());
+
+ /*
+ * If we were passed in a board information, copy it into the
+ * residual data area.
+ */
+ if (r3) {
+ memcpy((void *)__res, (void *)(r3 + KERNELBASE), sizeof(bd_t));
+ }
+
+#if defined(CONFIG_BLK_DEV_INITRD)
+ /*
+ * If the init RAM disk has been configured in, and there's a valid
+ * starting address for it, set it up.
+ */
+ if (r4) {
+ initrd_start = r4 + KERNELBASE;
+ initrd_end = r5 + KERNELBASE;
+ }
+#endif /* CONFIG_BLK_DEV_INITRD */
+
+ /* Copy the kernel command line arguments to a safe place. */
+
+ if (r6) {
+ *(char *)(r7 + KERNELBASE) = 0;
+ strcpy(cmd_line, (char *)(r6 + KERNELBASE));
+ }
+
+ /* Initialize machine-dependency vectors */
+
+ ppc_md.setup_arch = oak_setup_arch;
+ ppc_md.show_percpuinfo = oak_show_percpuinfo;
+ ppc_md.irq_canonicalize = NULL;
+ ppc_md.init_IRQ = ppc4xx_pic_init;
+ ppc_md.get_irq = NULL; /* Set in ppc4xx_pic_init() */
+ ppc_md.init = NULL;
+
+ ppc_md.restart = oak_restart;
+ ppc_md.power_off = oak_power_off;
+ ppc_md.halt = oak_halt;
+
+ ppc_md.time_init = oak_time_init;
+ ppc_md.set_rtc_time = oak_set_rtc_time;
+ ppc_md.get_rtc_time = oak_get_rtc_time;
+ ppc_md.calibrate_decr = oak_calibrate_decr;
+}
+
+/*
+ * Document me.
+ */
+void __init
+oak_setup_arch(void)
+{
+ /* XXX - Implement me */
+}
+
+/*
+ * int oak_show_percpuinfo()
+ *
+ * Description:
+ * This routine pretty-prints the platform's internal CPU and bus clock
+ * frequencies into the buffer for usage in /proc/cpuinfo.
+ *
+ * Input(s):
+ * *buffer - Buffer into which CPU and bus clock frequencies are to be
+ * printed.
+ *
+ * Output(s):
+ * *buffer - Buffer with the CPU and bus clock frequencies.
+ *
+ * Returns:
+ * The number of bytes copied into 'buffer' if OK, otherwise zero or less
+ * on error.
+ */
+int
+oak_show_percpuinfo(struct seq_file *m, int i)
+{
+ bd_t *bp = (bd_t *)__res;
+
+ seq_printf(m, "clock\t\t: %dMHz\n"
+ "bus clock\t\t: %dMHz\n",
+ bp->bi_intfreq / 1000000,
+ bp->bi_busfreq / 1000000);
+
+ return 0;
+}
+
+/*
+ * Document me.
+ */
+void
+oak_restart(char *cmd)
+{
+ abort();
+}
+
+/*
+ * Document me.
+ */
+void
+oak_power_off(void)
+{
+ oak_restart(NULL);
+}
+
+/*
+ * Document me.
+ */
+void
+oak_halt(void)
+{
+ oak_restart(NULL);
+}
+
+/*
+ * Document me.
+ */
+long __init
+oak_time_init(void)
+{
+ /* XXX - Implement me */
+ return 0;
+}
+
+/*
+ * Document me.
+ */
+int __init
+oak_set_rtc_time(unsigned long time)
+{
+ /* XXX - Implement me */
+
+ return (0);
+}
+
+/*
+ * Document me.
+ */
+unsigned long __init
+oak_get_rtc_time(void)
+{
+ /* XXX - Implement me */
+
+ return (0);
+}
+
+/*
+ * void __init oak_calibrate_decr()
+ *
+ * Description:
+ * This routine retrieves the internal processor frequency from the board
+ * information structure, sets up the kernel timer decrementer based on
+ * that value, enables the 403 programmable interval timer (PIT) and sets
+ * it up for auto-reload.
+ *
+ * Input(s):
+ * N/A
+ *
+ * Output(s):
+ * N/A
+ *
+ * Returns:
+ * N/A
+ *
+ */
+void __init
+oak_calibrate_decr(void)
+{
+ unsigned int freq;
+ bd_t *bip = (bd_t *)__res;
+
+ freq = bip->bi_intfreq;
+
+ decrementer_count = freq / HZ;
+ count_period_num = 1;
+ count_period_den = freq;
+
+ /* Enable the PIT and set auto-reload of its value */
+
+ mtspr(SPRN_TCR, TCR_PIE | TCR_ARE);
+
+ /* Clear any pending timer interrupts */
+
+ mtspr(SPRN_TSR, TSR_ENW | TSR_WIS | TSR_PIS | TSR_FIS);
+}
diff --git a/arch/ppc/platforms/4xx/oak.h b/arch/ppc/platforms/4xx/oak.h
new file mode 100644
index 0000000..1b86a4c
--- /dev/null
+++ b/arch/ppc/platforms/4xx/oak.h
@@ -0,0 +1,96 @@
+/*
+ *
+ * Copyright (c) 1999 Grant Erickson <grant@lcse.umn.edu>
+ *
+ * Module name: oak.h
+ *
+ * Description:
+ * Macros, definitions, and data structures specific to the IBM PowerPC
+ * 403G{A,B,C,CX} "Oak" evaluation board. Anything specific to the pro-
+ * cessor itself is defined elsewhere.
+ *
+ */
+
+#ifdef __KERNEL__
+#ifndef __ASM_OAK_H__
+#define __ASM_OAK_H__
+
+/* We have an IBM 403G{A,B,C,CX} core */
+#include <asm/ibm403.h>
+
+#define _IO_BASE 0
+#define _ISA_MEM_BASE 0
+#define PCI_DRAM_OFFSET 0
+
+/* Memory map for the "Oak" evaluation board */
+
+#define PPC403SPU_IO_BASE 0x40000000 /* 403 On-chip serial port */
+#define PPC403SPU_IO_SIZE 0x00000008
+#define OAKSERIAL_IO_BASE 0x7E000000 /* NS16550DV serial port */
+#define OAKSERIAL_IO_SIZE 0x00000008
+#define OAKNET_IO_BASE 0xF4000000 /* NS83902AV Ethernet */
+#define OAKNET_IO_SIZE 0x00000040
+#define OAKPROM_IO_BASE 0xFFFE0000 /* AMD 29F010 Flash ROM */
+#define OAKPROM_IO_SIZE 0x00020000
+
+
+/* Interrupt assignments fixed by the hardware implementation */
+
+/* This is annoying kbuild-2.4 problem. -- Tom */
+
+#define PPC403SPU_RX_INT 4 /* AIC_INT4 */
+#define PPC403SPU_TX_INT 5 /* AIC_INT5 */
+#define OAKNET_INT 27 /* AIC_INT27 */
+#define OAKSERIAL_INT 28 /* AIC_INT28 */
+
+#ifndef __ASSEMBLY__
+/*
+ * Data structure defining board information maintained by the boot
+ * ROM on IBM's "Oak" evaluation board. An effort has been made to
+ * keep the field names consistent with the 8xx 'bd_t' board info
+ * structures.
+ */
+
+typedef struct board_info {
+ unsigned char bi_s_version[4]; /* Version of this structure */
+ unsigned char bi_r_version[30]; /* Version of the IBM ROM */
+ unsigned int bi_memsize; /* DRAM installed, in bytes */
+ unsigned char bi_enetaddr[6]; /* Ethernet MAC address */
+ unsigned int bi_intfreq; /* Processor speed, in Hz */
+ unsigned int bi_busfreq; /* Bus speed, in Hz */
+} bd_t;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern void oak_init(unsigned long r3,
+ unsigned long ird_start,
+ unsigned long ird_end,
+ unsigned long cline_start,
+ unsigned long cline_end);
+extern void oak_setup_arch(void);
+extern int oak_setup_residual(char *buffer);
+extern void oak_init_IRQ(void);
+extern int oak_get_irq(struct pt_regs *regs);
+extern void oak_restart(char *cmd);
+extern void oak_power_off(void);
+extern void oak_halt(void);
+extern void oak_time_init(void);
+extern int oak_set_rtc_time(unsigned long now);
+extern unsigned long oak_get_rtc_time(void);
+extern void oak_calibrate_decr(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+/* Some 4xx parts use a different timebase frequency from the internal clock.
+*/
+#define bi_tbfreq bi_intfreq
+
+#define PPC4xx_MACHINE_NAME "IBM Oak"
+
+#endif /* !__ASSEMBLY__ */
+#endif /* __ASM_OAK_H__ */
+#endif /* __KERNEL__ */
diff --git a/arch/ppc/platforms/4xx/oak_setup.h b/arch/ppc/platforms/4xx/oak_setup.h
new file mode 100644
index 0000000..8648bd0
--- /dev/null
+++ b/arch/ppc/platforms/4xx/oak_setup.h
@@ -0,0 +1,50 @@
+/*
+ *
+ * Copyright (c) 1999-2000 Grant Erickson <grant@lcse.umn.edu>
+ *
+ * Module name: oak_setup.h
+ *
+ * Description:
+ * Architecture- / platform-specific boot-time initialization code for
+ * the IBM PowerPC 403GCX "Oak" evaluation board. Adapted from original
+ * code by Gary Thomas, Cort Dougan <cort@cs.nmt.edu>, and Dan Malek
+ * <dan@netx4.com>.
+ *
+ */
+
+#ifndef __OAK_SETUP_H__
+#define __OAK_SETUP_H__
+
+#include <asm/ptrace.h>
+#include <asm/board.h>
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern unsigned char __res[sizeof(bd_t)];
+
+extern void oak_init(unsigned long r3,
+ unsigned long ird_start,
+ unsigned long ird_end,
+ unsigned long cline_start,
+ unsigned long cline_end);
+extern void oak_setup_arch(void);
+extern int oak_setup_residual(char *buffer);
+extern void oak_init_IRQ(void);
+extern int oak_get_irq(struct pt_regs *regs);
+extern void oak_restart(char *cmd);
+extern void oak_power_off(void);
+extern void oak_halt(void);
+extern void oak_time_init(void);
+extern int oak_set_rtc_time(unsigned long now);
+extern unsigned long oak_get_rtc_time(void);
+extern void oak_calibrate_decr(void);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __OAK_SETUP_H__ */
diff --git a/arch/ppc/platforms/4xx/ocotea.c b/arch/ppc/platforms/4xx/ocotea.c
new file mode 100644
index 0000000..28de707
--- /dev/null
+++ b/arch/ppc/platforms/4xx/ocotea.c
@@ -0,0 +1,367 @@
+/*
+ * arch/ppc/platforms/4xx/ocotea.c
+ *
+ * Ocotea board specific routines
+ *
+ * Matt Porter <mporter@kernel.crashing.org>
+ *
+ * Copyright 2003-2005 MontaVista Software Inc.
+ *
+ * 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.
+ */
+
+#include <linux/config.h>
+#include <linux/stddef.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/reboot.h>
+#include <linux/pci.h>
+#include <linux/kdev_t.h>
+#include <linux/types.h>
+#include <linux/major.h>
+#include <linux/blkdev.h>
+#include <linux/console.h>
+#include <linux/delay.h>
+#include <linux/ide.h>
+#include <linux/initrd.h>
+#include <linux/irq.h>
+#include <linux/seq_file.h>
+#include <linux/root_dev.h>
+#include <linux/tty.h>
+#include <linux/serial.h>
+#include <linux/serial_core.h>
+
+#include <asm/system.h>
+#include <asm/pgtable.h>
+#include <asm/page.h>
+#include <asm/dma.h>
+#include <asm/io.h>
+#include <asm/machdep.h>
+#include <asm/ocp.h>
+#include <asm/pci-bridge.h>
+#include <asm/time.h>
+#include <asm/todc.h>
+#include <asm/bootinfo.h>
+#include <asm/ppc4xx_pic.h>
+#include <asm/ppcboot.h>
+
+#include <syslib/gen550.h>
+#include <syslib/ibm440gx_common.h>
+
+/*
+ * This is a horrible kludge, we eventually need to abstract this
+ * generic PHY stuff, so the standard phy mode defines can be
+ * easily used from arch code.
+ */
+#include "../../../../drivers/net/ibm_emac/ibm_emac_phy.h"
+
+bd_t __res;
+
+static struct ibm44x_clocks clocks __initdata;
+
+static void __init
+ocotea_calibrate_decr(void)
+{
+ unsigned int freq;
+
+ if (mfspr(SPRN_CCR1) & CCR1_TCS)
+ freq = OCOTEA_TMR_CLK;
+ else
+ freq = clocks.cpu;
+
+ ibm44x_calibrate_decr(freq);
+}
+
+static int
+ocotea_show_cpuinfo(struct seq_file *m)
+{
+ seq_printf(m, "vendor\t\t: IBM\n");
+ seq_printf(m, "machine\t\t: PPC440GX EVB (Ocotea)\n");
+ ibm440gx_show_cpuinfo(m);
+ return 0;
+}
+
+static inline int
+ocotea_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin)
+{
+ static char pci_irq_table[][4] =
+ /*
+ * PCI IDSEL/INTPIN->INTLINE
+ * A B C D
+ */
+ {
+ { 23, 23, 23, 23 }, /* IDSEL 1 - PCI Slot 0 */
+ { 24, 24, 24, 24 }, /* IDSEL 2 - PCI Slot 1 */
+ { 25, 25, 25, 25 }, /* IDSEL 3 - PCI Slot 2 */
+ { 26, 26, 26, 26 }, /* IDSEL 4 - PCI Slot 3 */
+ };
+
+ const long min_idsel = 1, max_idsel = 4, irqs_per_slot = 4;
+ return PCI_IRQ_TABLE_LOOKUP;
+}
+
+static void __init ocotea_set_emacdata(void)
+{
+ struct ocp_def *def;
+ struct ocp_func_emac_data *emacdata;
+ int i;
+
+ /*
+ * Note: Current rev. board only operates in Group 4a
+ * mode, so we always set EMAC0-1 for SMII and EMAC2-3
+ * for RGMII (though these could run in RTBI just the same).
+ *
+ * The FPGA reg 3 information isn't even suitable for
+ * determining the phy_mode, so if the board becomes
+ * usable in !4a, it will be necessary to parse an environment
+ * variable from the firmware or similar to properly configure
+ * the phy_map/phy_mode.
+ */
+ /* Set phy_map, phy_mode, and mac_addr for each EMAC */
+ for (i=0; i<4; i++) {
+ def = ocp_get_one_device(OCP_VENDOR_IBM, OCP_FUNC_EMAC, i);
+ emacdata = def->additions;
+ if (i < 2) {
+ emacdata->phy_map = 0x00000001; /* Skip 0x00 */
+ emacdata->phy_mode = PHY_MODE_SMII;
+ }
+ else {
+ emacdata->phy_map = 0x0000ffff; /* Skip 0x00-0x0f */
+ emacdata->phy_mode = PHY_MODE_RGMII;
+ }
+ if (i == 0)
+ memcpy(emacdata->mac_addr, __res.bi_enetaddr, 6);
+ else if (i == 1)
+ memcpy(emacdata->mac_addr, __res.bi_enet1addr, 6);
+ else if (i == 2)
+ memcpy(emacdata->mac_addr, __res.bi_enet2addr, 6);
+ else if (i == 3)
+ memcpy(emacdata->mac_addr, __res.bi_enet3addr, 6);
+ }
+}
+
+#define PCIX_READW(offset) \
+ (readw(pcix_reg_base+offset))
+
+#define PCIX_WRITEW(value, offset) \
+ (writew(value, pcix_reg_base+offset))
+
+#define PCIX_WRITEL(value, offset) \
+ (writel(value, pcix_reg_base+offset))
+
+/*
+ * FIXME: This is only here to "make it work". This will move
+ * to a ibm_pcix.c which will contain a generic IBM PCIX bridge
+ * configuration library. -Matt
+ */
+static void __init
+ocotea_setup_pcix(void)
+{
+ void *pcix_reg_base;
+
+ pcix_reg_base = ioremap64(PCIX0_REG_BASE, PCIX_REG_SIZE);
+
+ /* Enable PCIX0 I/O, Mem, and Busmaster cycles */
+ PCIX_WRITEW(PCIX_READW(PCIX0_COMMAND) | PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER, PCIX0_COMMAND);
+
+ /* Disable all windows */
+ PCIX_WRITEL(0, PCIX0_POM0SA);
+ PCIX_WRITEL(0, PCIX0_POM1SA);
+ PCIX_WRITEL(0, PCIX0_POM2SA);
+ PCIX_WRITEL(0, PCIX0_PIM0SA);
+ PCIX_WRITEL(0, PCIX0_PIM0SAH);
+ PCIX_WRITEL(0, PCIX0_PIM1SA);
+ PCIX_WRITEL(0, PCIX0_PIM2SA);
+ PCIX_WRITEL(0, PCIX0_PIM2SAH);
+
+ /* Setup 2GB PLB->PCI outbound mem window (3_8000_0000->0_8000_0000) */
+ PCIX_WRITEL(0x00000003, PCIX0_POM0LAH);
+ PCIX_WRITEL(0x80000000, PCIX0_POM0LAL);
+ PCIX_WRITEL(0x00000000, PCIX0_POM0PCIAH);
+ PCIX_WRITEL(0x80000000, PCIX0_POM0PCIAL);
+ PCIX_WRITEL(0x80000001, PCIX0_POM0SA);
+
+ /* Setup 2GB PCI->PLB inbound memory window at 0, enable MSIs */
+ PCIX_WRITEL(0x00000000, PCIX0_PIM0LAH);
+ PCIX_WRITEL(0x00000000, PCIX0_PIM0LAL);
+ PCIX_WRITEL(0xe0000007, PCIX0_PIM0SA);
+
+ eieio();
+}
+
+static void __init
+ocotea_setup_hose(void)
+{
+ struct pci_controller *hose;
+
+ /* Configure windows on the PCI-X host bridge */
+ ocotea_setup_pcix();
+
+ hose = pcibios_alloc_controller();
+
+ if (!hose)
+ return;
+
+ hose->first_busno = 0;
+ hose->last_busno = 0xff;
+
+ hose->pci_mem_offset = OCOTEA_PCI_MEM_OFFSET;
+
+ pci_init_resource(&hose->io_resource,
+ OCOTEA_PCI_LOWER_IO,
+ OCOTEA_PCI_UPPER_IO,
+ IORESOURCE_IO,
+ "PCI host bridge");
+
+ pci_init_resource(&hose->mem_resources[0],
+ OCOTEA_PCI_LOWER_MEM,
+ OCOTEA_PCI_UPPER_MEM,
+ IORESOURCE_MEM,
+ "PCI host bridge");
+
+ hose->io_space.start = OCOTEA_PCI_LOWER_IO;
+ hose->io_space.end = OCOTEA_PCI_UPPER_IO;
+ hose->mem_space.start = OCOTEA_PCI_LOWER_MEM;
+ hose->mem_space.end = OCOTEA_PCI_UPPER_MEM;
+ isa_io_base =
+ (unsigned long)ioremap64(OCOTEA_PCI_IO_BASE, OCOTEA_PCI_IO_SIZE);
+ hose->io_base_virt = (void *)isa_io_base;
+
+ setup_indirect_pci(hose,
+ OCOTEA_PCI_CFGA_PLB32,
+ OCOTEA_PCI_CFGD_PLB32);
+ hose->set_cfg_type = 1;
+
+ hose->last_busno = pciauto_bus_scan(hose, hose->first_busno);
+
+ ppc_md.pci_swizzle = common_swizzle;
+ ppc_md.pci_map_irq = ocotea_map_irq;
+}
+
+
+TODC_ALLOC();
+
+static void __init
+ocotea_early_serial_map(void)
+{
+ struct uart_port port;
+
+ /* Setup ioremapped serial port access */
+ memset(&port, 0, sizeof(port));
+ port.membase = ioremap64(PPC440GX_UART0_ADDR, 8);
+ port.irq = UART0_INT;
+ port.uartclk = clocks.uart0;
+ port.regshift = 0;
+ port.iotype = SERIAL_IO_MEM;
+ port.flags = ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST;
+ port.line = 0;
+
+ if (early_serial_setup(&port) != 0) {
+ printk("Early serial init of port 0 failed\n");
+ }
+
+#if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB)
+ /* Configure debug serial access */
+ gen550_init(0, &port);
+#endif
+
+ port.membase = ioremap64(PPC440GX_UART1_ADDR, 8);
+ port.irq = UART1_INT;
+ port.uartclk = clocks.uart1;
+ port.line = 1;
+
+ if (early_serial_setup(&port) != 0) {
+ printk("Early serial init of port 1 failed\n");
+ }
+
+#if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB)
+ /* Configure debug serial access */
+ gen550_init(1, &port);
+#endif
+}
+
+static void __init
+ocotea_setup_arch(void)
+{
+ ocotea_set_emacdata();
+
+ ibm440gx_tah_enable();
+
+ /* Setup TODC access */
+ TODC_INIT(TODC_TYPE_DS1743,
+ 0,
+ 0,
+ ioremap64(OCOTEA_RTC_ADDR, OCOTEA_RTC_SIZE),
+ 8);
+
+ /* init to some ~sane value until calibrate_delay() runs */
+ loops_per_jiffy = 50000000/HZ;
+
+ /* Setup PCI host bridge */
+ ocotea_setup_hose();
+
+#ifdef CONFIG_BLK_DEV_INITRD
+ if (initrd_start)
+ ROOT_DEV = Root_RAM0;
+ else
+#endif
+#ifdef CONFIG_ROOT_NFS
+ ROOT_DEV = Root_NFS;
+#else
+ ROOT_DEV = Root_HDA1;
+#endif
+
+ ocotea_early_serial_map();
+
+ /* Identify the system */
+ printk("IBM Ocotea port (MontaVista Software, Inc. <source@mvista.com>)\n");
+}
+
+static void __init ocotea_init(void)
+{
+ ibm440gx_l2c_setup(&clocks);
+}
+
+void __init platform_init(unsigned long r3, unsigned long r4,
+ unsigned long r5, unsigned long r6, unsigned long r7)
+{
+ parse_bootinfo(find_bootinfo());
+
+ /*
+ * If we were passed in a board information, copy it into the
+ * residual data area.
+ */
+ if (r3)
+ __res = *(bd_t *)(r3 + KERNELBASE);
+
+ /*
+ * Determine various clocks.
+ * To be completely correct we should get SysClk
+ * from FPGA, because it can be changed by on-board switches
+ * --ebs
+ */
+ ibm440gx_get_clocks(&clocks, 33333333, 6 * 1843200);
+ ocp_sys_info.opb_bus_freq = clocks.opb;
+
+ ibm44x_platform_init();
+
+ ppc_md.setup_arch = ocotea_setup_arch;
+ ppc_md.show_cpuinfo = ocotea_show_cpuinfo;
+ ppc_md.get_irq = NULL; /* Set in ppc4xx_pic_init() */
+
+ ppc_md.calibrate_decr = ocotea_calibrate_decr;
+ ppc_md.time_init = todc_time_init;
+ ppc_md.set_rtc_time = todc_set_rtc_time;
+ ppc_md.get_rtc_time = todc_get_rtc_time;
+
+ ppc_md.nvram_read_val = todc_direct_read_val;
+ ppc_md.nvram_write_val = todc_direct_write_val;
+#ifdef CONFIG_KGDB
+ ppc_md.early_serial_map = ocotea_early_serial_map;
+#endif
+ ppc_md.init = ocotea_init;
+}
diff --git a/arch/ppc/platforms/4xx/ocotea.h b/arch/ppc/platforms/4xx/ocotea.h
new file mode 100644
index 0000000..202dc82
--- /dev/null
+++ b/arch/ppc/platforms/4xx/ocotea.h
@@ -0,0 +1,88 @@
+/*
+ * arch/ppc/platforms/ocotea.h
+ *
+ * Ocotea board definitions
+ *
+ * Matt Porter <mporter@kernel.crashing.org>
+ *
+ * Copyright 2003-2005 MontaVista Software Inc.
+ *
+ * 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.
+ *
+ */
+
+#ifdef __KERNEL__
+#ifndef __ASM_OCOTEA_H__
+#define __ASM_OCOTEA_H__
+
+#include <linux/config.h>
+#include <platforms/4xx/ibm440gx.h>
+
+/* F/W TLB mapping used in bootloader glue to reset EMAC */
+#define PPC44x_EMAC0_MR0 0xe0000800
+
+/* Location of MAC addresses in PIBS image */
+#define PIBS_FLASH_BASE 0xfff00000
+#define PIBS_MAC_BASE (PIBS_FLASH_BASE+0xb0500)
+#define PIBS_MAC_SIZE 0x200
+#define PIBS_MAC_OFFSET 0x100
+
+/* External timer clock frequency */
+#define OCOTEA_TMR_CLK 25000000
+
+/* RTC/NVRAM location */
+#define OCOTEA_RTC_ADDR 0x0000000148000000ULL
+#define OCOTEA_RTC_SIZE 0x2000
+
+/* Flash */
+#define OCOTEA_FPGA_REG_0 0x0000000148300000ULL
+#define OCOTEA_BOOT_LARGE_FLASH(x) (x & 0x40)
+#define OCOTEA_SMALL_FLASH_LOW 0x00000001ff900000ULL
+#define OCOTEA_SMALL_FLASH_HIGH 0x00000001fff00000ULL
+#define OCOTEA_SMALL_FLASH_SIZE 0x100000
+#define OCOTEA_LARGE_FLASH_LOW 0x00000001ff800000ULL
+#define OCOTEA_LARGE_FLASH_HIGH 0x00000001ffc00000ULL
+#define OCOTEA_LARGE_FLASH_SIZE 0x400000
+
+/* FPGA_REG_3 (Ethernet Groups) */
+#define OCOTEA_FPGA_REG_3 0x0000000148300003ULL
+
+/*
+ * Serial port defines
+ */
+#define RS_TABLE_SIZE 2
+
+/* OpenBIOS defined UART mappings, used before early_serial_setup */
+#define UART0_IO_BASE 0xE0000200
+#define UART1_IO_BASE 0xE0000300
+
+#define BASE_BAUD 11059200/16
+#define STD_UART_OP(num) \
+ { 0, BASE_BAUD, 0, UART##num##_INT, \
+ (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST), \
+ iomem_base: UART##num##_IO_BASE, \
+ io_type: SERIAL_IO_MEM},
+
+#define SERIAL_PORT_DFNS \
+ STD_UART_OP(0) \
+ STD_UART_OP(1)
+
+/* PCI support */
+#define OCOTEA_PCI_LOWER_IO 0x00000000
+#define OCOTEA_PCI_UPPER_IO 0x0000ffff
+#define OCOTEA_PCI_LOWER_MEM 0x80000000
+#define OCOTEA_PCI_UPPER_MEM 0xffffefff
+
+#define OCOTEA_PCI_CFGREGS_BASE 0x000000020ec00000ULL
+#define OCOTEA_PCI_CFGA_PLB32 0x0ec00000
+#define OCOTEA_PCI_CFGD_PLB32 0x0ec00004
+
+#define OCOTEA_PCI_IO_BASE 0x0000000208000000ULL
+#define OCOTEA_PCI_IO_SIZE 0x00010000
+#define OCOTEA_PCI_MEM_OFFSET 0x00000000
+
+#endif /* __ASM_OCOTEA_H__ */
+#endif /* __KERNEL__ */
diff --git a/arch/ppc/platforms/4xx/redwood5.c b/arch/ppc/platforms/4xx/redwood5.c
new file mode 100644
index 0000000..2f5e410
--- /dev/null
+++ b/arch/ppc/platforms/4xx/redwood5.c
@@ -0,0 +1,110 @@
+/*
+ * arch/ppc/platforms/4xx/redwood5.c
+ *
+ * Support for the IBM redwood5 eval board file
+ *
+ * Author: Armin Kuster <akuster@mvista.com>
+ *
+ * 2000-2001 (c) MontaVista, Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/pagemap.h>
+#include <linux/device.h>
+#include <linux/ioport.h>
+#include <asm/io.h>
+#include <asm/machdep.h>
+
+static struct resource smc91x_resources[] = {
+ [0] = {
+ .start = SMC91111_BASE_ADDR,
+ .end = SMC91111_BASE_ADDR + SMC91111_REG_SIZE - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = SMC91111_IRQ,
+ .end = SMC91111_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device smc91x_device = {
+ .name = "smc91x",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(smc91x_resources),
+ .resource = smc91x_resources,
+};
+
+static struct platform_device *redwood5_devs[] __initdata = {
+ &smc91x_device,
+};
+
+static int __init
+redwood5_platform_add_devices(void)
+{
+ return platform_add_devices(redwood5_devs, ARRAY_SIZE(redwood5_devs));
+}
+
+void __init
+redwood5_setup_arch(void)
+{
+ ppc4xx_setup_arch();
+
+#ifdef CONFIG_DEBUG_BRINGUP
+ printk("\n");
+ printk("machine\t: %s\n", PPC4xx_MACHINE_NAME);
+ printk("\n");
+ printk("bi_s_version\t %s\n", bip->bi_s_version);
+ printk("bi_r_version\t %s\n", bip->bi_r_version);
+ printk("bi_memsize\t 0x%8.8x\t %dMBytes\n", bip->bi_memsize,bip->bi_memsize/(1024*1000));
+ printk("bi_enetaddr %d\t %2.2x%2.2x%2.2x-%2.2x%2.2x%2.2x\n", 0,
+ bip->bi_enetaddr[0], bip->bi_enetaddr[1],
+ bip->bi_enetaddr[2], bip->bi_enetaddr[3],
+ bip->bi_enetaddr[4], bip->bi_enetaddr[5]);
+
+ printk("bi_intfreq\t 0x%8.8x\t clock:\t %dMhz\n",
+ bip->bi_intfreq, bip->bi_intfreq/ 1000000);
+
+ printk("bi_busfreq\t 0x%8.8x\t plb bus clock:\t %dMHz\n",
+ bip->bi_busfreq, bip->bi_busfreq / 1000000 );
+ printk("bi_tbfreq\t 0x%8.8x\t TB freq:\t %dMHz\n",
+ bip->bi_tbfreq, bip->bi_tbfreq/1000000);
+
+ printk("\n");
+#endif
+ device_initcall(redwood5_platform_add_devices);
+}
+
+void __init
+redwood5_map_io(void)
+{
+ int i;
+
+ ppc4xx_map_io();
+ for (i = 0; i < 16; i++) {
+ unsigned long v, p;
+
+ /* 0x400x0000 -> 0xe00x0000 */
+ p = 0x40000000 | (i << 16);
+ v = STB04xxx_IO_BASE | (i << 16);
+
+ io_block_mapping(v, p, PAGE_SIZE,
+ _PAGE_NO_CACHE | pgprot_val(PAGE_KERNEL) | _PAGE_GUARDED);
+ }
+
+
+}
+
+void __init
+platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
+ unsigned long r6, unsigned long r7)
+{
+ ppc4xx_init(r3, r4, r5, r6, r7);
+
+ ppc_md.setup_arch = redwood5_setup_arch;
+ ppc_md.setup_io_mappings = redwood5_map_io;
+}
diff --git a/arch/ppc/platforms/4xx/redwood5.h b/arch/ppc/platforms/4xx/redwood5.h
new file mode 100644
index 0000000..264e34f
--- /dev/null
+++ b/arch/ppc/platforms/4xx/redwood5.h
@@ -0,0 +1,54 @@
+/*
+ * arch/ppc/platforms/4xx/redwood5.h
+ *
+ * Macros, definitions, and data structures specific to the IBM PowerPC
+ * STB03xxx "Redwood" evaluation board.
+ *
+ * Author: Armin Kuster <akuster@mvista.com>
+ *
+ * 2001 (c) MontaVista, Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+
+#ifdef __KERNEL__
+#ifndef __ASM_REDWOOD5_H__
+#define __ASM_REDWOOD5_H__
+
+/* Redwood5 has an STB04xxx core */
+#include <platforms/4xx/ibmstb4.h>
+
+#ifndef __ASSEMBLY__
+typedef struct board_info {
+ unsigned char bi_s_version[4]; /* Version of this structure */
+ unsigned char bi_r_version[30]; /* Version of the IBM ROM */
+ unsigned int bi_memsize; /* DRAM installed, in bytes */
+ unsigned int bi_dummy; /* field shouldn't exist */
+ unsigned char bi_enetaddr[6]; /* Ethernet MAC address */
+ unsigned int bi_intfreq; /* Processor speed, in Hz */
+ unsigned int bi_busfreq; /* Bus speed, in Hz */
+ unsigned int bi_tbfreq; /* Software timebase freq */
+} bd_t;
+#endif /* !__ASSEMBLY__ */
+
+
+#define SMC91111_BASE_ADDR 0xf2000300
+#define SMC91111_REG_SIZE 16
+#define SMC91111_IRQ 28
+
+#ifdef MAX_HWIFS
+#undef MAX_HWIFS
+#endif
+#define MAX_HWIFS 1
+
+#define _IO_BASE 0
+#define _ISA_MEM_BASE 0
+#define PCI_DRAM_OFFSET 0
+
+#define BASE_BAUD (378000000 / 18 / 16)
+
+#define PPC4xx_MACHINE_NAME "IBM Redwood5"
+
+#endif /* __ASM_REDWOOD5_H__ */
+#endif /* __KERNEL__ */
diff --git a/arch/ppc/platforms/4xx/redwood6.c b/arch/ppc/platforms/4xx/redwood6.c
new file mode 100644
index 0000000..8b10129
--- /dev/null
+++ b/arch/ppc/platforms/4xx/redwood6.c
@@ -0,0 +1,159 @@
+/*
+ * arch/ppc/platforms/4xx/redwood6.c
+ *
+ * Author: Armin Kuster <akuster@mvista.com>
+ *
+ * 2002 (c) MontaVista, Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/pagemap.h>
+#include <linux/device.h>
+#include <linux/ioport.h>
+#include <asm/io.h>
+#include <asm/ppc4xx_pic.h>
+#include <linux/delay.h>
+#include <asm/machdep.h>
+
+/*
+ * Define external IRQ senses and polarities.
+ */
+unsigned char ppc4xx_uic_ext_irq_cfg[] __initdata = {
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* Ext Int 7 */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* Ext Int 8 */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* Ext Int 9 */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* Ext Int 0 */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* Ext Int 1 */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* Ext Int 2 */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* Ext Int 3 */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* Ext Int 4 */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* Ext Int 5 */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* Ext Int 6 */
+};
+
+static struct resource smc91x_resources[] = {
+ [0] = {
+ .start = SMC91111_BASE_ADDR,
+ .end = SMC91111_BASE_ADDR + SMC91111_REG_SIZE - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = SMC91111_IRQ,
+ .end = SMC91111_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device smc91x_device = {
+ .name = "smc91x",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(smc91x_resources),
+ .resource = smc91x_resources,
+};
+
+static struct platform_device *redwood6_devs[] __initdata = {
+ &smc91x_device,
+};
+
+static int __init
+redwood6_platform_add_devices(void)
+{
+ return platform_add_devices(redwood6_devs, ARRAY_SIZE(redwood6_devs));
+}
+
+
+void __init
+redwood6_setup_arch(void)
+{
+#ifdef CONFIG_IDE
+ void *xilinx, *xilinx_1, *xilinx_2;
+ unsigned short us_reg5;
+#endif
+
+ ppc4xx_setup_arch();
+
+#ifdef CONFIG_IDE
+ xilinx = (unsigned long) ioremap(IDE_XLINUX_MUX_BASE, 0x10);
+ /* init xilinx control registers - enable ide mux, clear reset bit */
+ if (!xilinx) {
+ printk(KERN_CRIT
+ "redwood6_setup_arch() xilinxi ioremap failed\n");
+ return;
+ }
+ xilinx_1 = xilinx + 0xa;
+ xilinx_2 = xilinx + 0xe;
+
+ us_reg5 = readb(xilinx_1);
+ writeb(0x01d1, xilinx_1);
+ writeb(0x0008, xilinx_2);
+
+ udelay(10 * 1000);
+
+ writeb(0x01d1, xilinx_1);
+ writeb(0x0008, xilinx_2);
+#endif
+
+#ifdef DEBUG_BRINGUP
+ bd_t *bip = (bd_t *) __res;
+ printk("\n");
+ printk("machine\t: %s\n", PPC4xx_MACHINE_NAME);
+ printk("\n");
+ printk("bi_s_version\t %s\n", bip->bi_s_version);
+ printk("bi_r_version\t %s\n", bip->bi_r_version);
+ printk("bi_memsize\t 0x%8.8x\t %dMBytes\n", bip->bi_memsize,
+ bip->bi_memsize / (1024 * 1000));
+ printk("bi_enetaddr %d\t %2.2x%2.2x%2.2x-%2.2x%2.2x%2.2x\n", 0,
+ bip->bi_enetaddr[0], bip->bi_enetaddr[1], bip->bi_enetaddr[2],
+ bip->bi_enetaddr[3], bip->bi_enetaddr[4], bip->bi_enetaddr[5]);
+
+ printk("bi_intfreq\t 0x%8.8x\t clock:\t %dMhz\n",
+ bip->bi_intfreq, bip->bi_intfreq / 1000000);
+
+ printk("bi_busfreq\t 0x%8.8x\t plb bus clock:\t %dMHz\n",
+ bip->bi_busfreq, bip->bi_busfreq / 1000000);
+ printk("bi_tbfreq\t 0x%8.8x\t TB freq:\t %dMHz\n",
+ bip->bi_tbfreq, bip->bi_tbfreq / 1000000);
+
+ printk("\n");
+#endif
+
+ /* Identify the system */
+ printk(KERN_INFO "IBM Redwood6 (STBx25XX) Platform\n");
+ printk(KERN_INFO
+ "Port by MontaVista Software, Inc. (source@mvista.com)\n");
+
+ device_initcall(redwood6_platform_add_devices);
+}
+
+void __init
+redwood6_map_io(void)
+{
+ int i;
+
+ ppc4xx_map_io();
+ for (i = 0; i < 16; i++) {
+ unsigned long v, p;
+
+ /* 0x400x0000 -> 0xe00x0000 */
+ p = 0x40000000 | (i << 16);
+ v = STBx25xx_IO_BASE | (i << 16);
+
+ io_block_mapping(v, p, PAGE_SIZE,
+ _PAGE_NO_CACHE | pgprot_val(PAGE_KERNEL) |
+ _PAGE_GUARDED);
+ }
+}
+
+void __init
+platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
+ unsigned long r6, unsigned long r7)
+{
+ ppc4xx_init(r3, r4, r5, r6, r7);
+
+ ppc_md.setup_arch = redwood6_setup_arch;
+ ppc_md.setup_io_mappings = redwood6_map_io;
+}
diff --git a/arch/ppc/platforms/4xx/redwood6.h b/arch/ppc/platforms/4xx/redwood6.h
new file mode 100644
index 0000000..1814b9f
--- /dev/null
+++ b/arch/ppc/platforms/4xx/redwood6.h
@@ -0,0 +1,55 @@
+/*
+ * arch/ppc/platforms/4xx/redwood6.h
+ *
+ * Macros, definitions, and data structures specific to the IBM PowerPC
+ * STBx25xx "Redwood6" evaluation board.
+ *
+ * Author: Armin Kuster <akuster@mvista.com>
+ *
+ * 2002 (c) MontaVista, Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+
+#ifdef __KERNEL__
+#ifndef __ASM_REDWOOD5_H__
+#define __ASM_REDWOOD5_H__
+
+/* Redwood6 has an STBx25xx core */
+#include <platforms/4xx/ibmstbx25.h>
+
+#ifndef __ASSEMBLY__
+typedef struct board_info {
+ unsigned char bi_s_version[4]; /* Version of this structure */
+ unsigned char bi_r_version[30]; /* Version of the IBM ROM */
+ unsigned int bi_memsize; /* DRAM installed, in bytes */
+ unsigned int bi_dummy; /* field shouldn't exist */
+ unsigned char bi_enetaddr[6]; /* Ethernet MAC address */
+ unsigned int bi_intfreq; /* Processor speed, in Hz */
+ unsigned int bi_busfreq; /* Bus speed, in Hz */
+ unsigned int bi_tbfreq; /* Software timebase freq */
+} bd_t;
+#endif /* !__ASSEMBLY__ */
+
+#define SMC91111_BASE_ADDR 0xf2030300
+#define SMC91111_REG_SIZE 16
+#define SMC91111_IRQ 27
+#define IDE_XLINUX_MUX_BASE 0xf2040000
+#define IDE_DMA_ADDR 0xfce00000
+
+#ifdef MAX_HWIFS
+#undef MAX_HWIFS
+#endif
+#define MAX_HWIFS 1
+
+#define _IO_BASE 0
+#define _ISA_MEM_BASE 0
+#define PCI_DRAM_OFFSET 0
+
+#define BASE_BAUD (378000000 / 18 / 16)
+
+#define PPC4xx_MACHINE_NAME "IBM Redwood6"
+
+#endif /* __ASM_REDWOOD5_H__ */
+#endif /* __KERNEL__ */
diff --git a/arch/ppc/platforms/4xx/sycamore.c b/arch/ppc/platforms/4xx/sycamore.c
new file mode 100644
index 0000000..d8019ee
--- /dev/null
+++ b/arch/ppc/platforms/4xx/sycamore.c
@@ -0,0 +1,278 @@
+/*
+ * arch/ppc/platforms/4xx/sycamore.c
+ *
+ * Architecture- / platform-specific boot-time initialization code for
+ * IBM PowerPC 4xx based boards.
+ *
+ * Author: Armin Kuster <akuster@mvista.com>
+ *
+ * 2000-2002 (c) MontaVista, Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/smp.h>
+#include <linux/threads.h>
+#include <linux/param.h>
+#include <linux/string.h>
+#include <linux/pci.h>
+#include <linux/rtc.h>
+
+#include <asm/ocp.h>
+#include <asm/ppc4xx_pic.h>
+#include <asm/system.h>
+#include <asm/pci-bridge.h>
+#include <asm/machdep.h>
+#include <asm/page.h>
+#include <asm/time.h>
+#include <asm/io.h>
+#include <asm/ibm_ocp_pci.h>
+#include <asm/todc.h>
+
+#undef DEBUG
+
+#ifdef DEBUG
+#define DBG(x...) printk(x)
+#else
+#define DBG(x...)
+#endif
+
+void *kb_cs;
+void *kb_data;
+void *sycamore_rtc_base;
+
+/*
+ * Define external IRQ senses and polarities.
+ */
+unsigned char ppc4xx_uic_ext_irq_cfg[] __initdata = {
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* Ext Int 7 */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* Ext Int 8 */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* Ext Int 9 */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* Ext Int 10 */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* Ext Int 11 */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* Ext Int 12 */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* Ext Int 0 */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* Ext Int 1 */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* Ext Int 2 */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* Ext Int 3 */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* Ext Int 4 */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* Ext Int 5 */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* Ext Int 6 */
+};
+
+
+/* Some IRQs unique to Sycamore.
+ * Used by the generic 405 PCI setup functions in ppc4xx_pci.c
+ */
+int __init
+ppc405_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin)
+{
+ static char pci_irq_table[][4] =
+ /*
+ * PCI IDSEL/INTPIN->INTLINE
+ * A B C D
+ */
+ {
+ {28, 28, 28, 28}, /* IDSEL 1 - PCI slot 1 */
+ {29, 29, 29, 29}, /* IDSEL 2 - PCI slot 2 */
+ {30, 30, 30, 30}, /* IDSEL 3 - PCI slot 3 */
+ {31, 31, 31, 31}, /* IDSEL 4 - PCI slot 4 */
+ };
+
+ const long min_idsel = 1, max_idsel = 4, irqs_per_slot = 4;
+ return PCI_IRQ_TABLE_LOOKUP;
+};
+
+void __init
+sycamore_setup_arch(void)
+{
+#define SYCAMORE_PS2_BASE 0xF0100000
+#define SYCAMORE_FPGA_BASE 0xF0300000
+
+ void *fpga_brdc;
+ unsigned char fpga_brdc_data;
+ void *fpga_enable;
+ void *fpga_polarity;
+ void *fpga_status;
+ void *fpga_trigger;
+
+ ppc4xx_setup_arch();
+
+ ibm_ocp_set_emac(0, 1);
+
+ kb_data = ioremap(SYCAMORE_PS2_BASE, 8);
+ if (!kb_data) {
+ printk(KERN_CRIT
+ "sycamore_setup_arch() kb_data ioremap failed\n");
+ return;
+ }
+
+ kb_cs = kb_data + 1;
+
+ fpga_status = ioremap(SYCAMORE_FPGA_BASE, 8);
+ if (!fpga_status) {
+ printk(KERN_CRIT
+ "sycamore_setup_arch() fpga_status ioremap failed\n");
+ return;
+ }
+
+ fpga_enable = fpga_status + 1;
+ fpga_polarity = fpga_status + 2;
+ fpga_trigger = fpga_status + 3;
+ fpga_brdc = fpga_status + 4;
+
+ /* split the keyboard and mouse interrupts */
+ fpga_brdc_data = readb(fpga_brdc);
+ fpga_brdc_data |= 0x80;
+ writeb(fpga_brdc_data, fpga_brdc);
+
+ writeb(0x3, fpga_enable);
+
+ writeb(0x3, fpga_polarity);
+
+ writeb(0x3, fpga_trigger);
+
+ /* RTC step for the sycamore */
+ sycamore_rtc_base = (void *) SYCAMORE_RTC_VADDR;
+ TODC_INIT(TODC_TYPE_DS1743, sycamore_rtc_base, sycamore_rtc_base,
+ sycamore_rtc_base, 8);
+
+ /* Identify the system */
+ printk(KERN_INFO "IBM Sycamore (IBM405GPr) Platform\n");
+ printk(KERN_INFO
+ "Port by MontaVista Software, Inc. (source@mvista.com)\n");
+}
+
+void __init
+bios_fixup(struct pci_controller *hose, struct pcil0_regs *pcip)
+{
+#ifdef CONFIG_PCI
+ unsigned int bar_response, bar;
+ /*
+ * Expected PCI mapping:
+ *
+ * PLB addr PCI memory addr
+ * --------------------- ---------------------
+ * 0000'0000 - 7fff'ffff <--- 0000'0000 - 7fff'ffff
+ * 8000'0000 - Bfff'ffff ---> 8000'0000 - Bfff'ffff
+ *
+ * PLB addr PCI io addr
+ * --------------------- ---------------------
+ * e800'0000 - e800'ffff ---> 0000'0000 - 0001'0000
+ *
+ * The following code is simplified by assuming that the bootrom
+ * has been well behaved in following this mapping.
+ */
+
+#ifdef DEBUG
+ int i;
+
+ printk("ioremap PCLIO_BASE = 0x%x\n", pcip);
+ printk("PCI bridge regs before fixup \n");
+ for (i = 0; i <= 3; i++) {
+ printk(" pmm%dma\t0x%x\n", i, in_le32(&(pcip->pmm[i].ma)));
+ printk(" pmm%dma\t0x%x\n", i, in_le32(&(pcip->pmm[i].la)));
+ printk(" pmm%dma\t0x%x\n", i, in_le32(&(pcip->pmm[i].pcila)));
+ printk(" pmm%dma\t0x%x\n", i, in_le32(&(pcip->pmm[i].pciha)));
+ }
+ printk(" ptm1ms\t0x%x\n", in_le32(&(pcip->ptm1ms)));
+ printk(" ptm1la\t0x%x\n", in_le32(&(pcip->ptm1la)));
+ printk(" ptm2ms\t0x%x\n", in_le32(&(pcip->ptm2ms)));
+ printk(" ptm2la\t0x%x\n", in_le32(&(pcip->ptm2la)));
+
+#endif
+
+ /* added for IBM boot rom version 1.15 bios bar changes -AK */
+
+ /* Disable region first */
+ out_le32((void *) &(pcip->pmm[0].ma), 0x00000000);
+ /* PLB starting addr, PCI: 0x80000000 */
+ out_le32((void *) &(pcip->pmm[0].la), 0x80000000);
+ /* PCI start addr, 0x80000000 */
+ out_le32((void *) &(pcip->pmm[0].pcila), PPC405_PCI_MEM_BASE);
+ /* 512MB range of PLB to PCI */
+ out_le32((void *) &(pcip->pmm[0].pciha), 0x00000000);
+ /* Enable no pre-fetch, enable region */
+ out_le32((void *) &(pcip->pmm[0].ma), ((0xffffffff -
+ (PPC405_PCI_UPPER_MEM -
+ PPC405_PCI_MEM_BASE)) | 0x01));
+
+ /* Enable inbound region one - 1GB size */
+ out_le32((void *) &(pcip->ptm1ms), 0xc0000001);
+
+ /* Disable outbound region one */
+ out_le32((void *) &(pcip->pmm[1].ma), 0x00000000);
+ out_le32((void *) &(pcip->pmm[1].la), 0x00000000);
+ out_le32((void *) &(pcip->pmm[1].pcila), 0x00000000);
+ out_le32((void *) &(pcip->pmm[1].pciha), 0x00000000);
+ out_le32((void *) &(pcip->pmm[1].ma), 0x00000000);
+
+ /* Disable inbound region two */
+ out_le32((void *) &(pcip->ptm2ms), 0x00000000);
+
+ /* Disable outbound region two */
+ out_le32((void *) &(pcip->pmm[2].ma), 0x00000000);
+ out_le32((void *) &(pcip->pmm[2].la), 0x00000000);
+ out_le32((void *) &(pcip->pmm[2].pcila), 0x00000000);
+ out_le32((void *) &(pcip->pmm[2].pciha), 0x00000000);
+ out_le32((void *) &(pcip->pmm[2].ma), 0x00000000);
+
+ /* Zero config bars */
+ for (bar = PCI_BASE_ADDRESS_1; bar <= PCI_BASE_ADDRESS_2; bar += 4) {
+ early_write_config_dword(hose, hose->first_busno,
+ PCI_FUNC(hose->first_busno), bar,
+ 0x00000000);
+ early_read_config_dword(hose, hose->first_busno,
+ PCI_FUNC(hose->first_busno), bar,
+ &bar_response);
+ DBG("BUS %d, device %d, Function %d bar 0x%8.8x is 0x%8.8x\n",
+ hose->first_busno, PCI_SLOT(hose->first_busno),
+ PCI_FUNC(hose->first_busno), bar, bar_response);
+ }
+ /* end work arround */
+
+#ifdef DEBUG
+ printk("PCI bridge regs after fixup \n");
+ for (i = 0; i <= 3; i++) {
+ printk(" pmm%dma\t0x%x\n", i, in_le32(&(pcip->pmm[i].ma)));
+ printk(" pmm%dma\t0x%x\n", i, in_le32(&(pcip->pmm[i].la)));
+ printk(" pmm%dma\t0x%x\n", i, in_le32(&(pcip->pmm[i].pcila)));
+ printk(" pmm%dma\t0x%x\n", i, in_le32(&(pcip->pmm[i].pciha)));
+ }
+ printk(" ptm1ms\t0x%x\n", in_le32(&(pcip->ptm1ms)));
+ printk(" ptm1la\t0x%x\n", in_le32(&(pcip->ptm1la)));
+ printk(" ptm2ms\t0x%x\n", in_le32(&(pcip->ptm2ms)));
+ printk(" ptm2la\t0x%x\n", in_le32(&(pcip->ptm2la)));
+
+#endif
+#endif
+
+}
+
+void __init
+sycamore_map_io(void)
+{
+ ppc4xx_map_io();
+ io_block_mapping(SYCAMORE_RTC_VADDR,
+ SYCAMORE_RTC_PADDR, SYCAMORE_RTC_SIZE, _PAGE_IO);
+}
+
+void __init
+platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
+ unsigned long r6, unsigned long r7)
+{
+ ppc4xx_init(r3, r4, r5, r6, r7);
+
+ ppc_md.setup_arch = sycamore_setup_arch;
+ ppc_md.setup_io_mappings = sycamore_map_io;
+
+#ifdef CONFIG_GEN_RTC
+ ppc_md.time_init = todc_time_init;
+ ppc_md.set_rtc_time = todc_set_rtc_time;
+ ppc_md.get_rtc_time = todc_get_rtc_time;
+ ppc_md.nvram_read_val = todc_direct_read_val;
+ ppc_md.nvram_write_val = todc_direct_write_val;
+#endif
+}
diff --git a/arch/ppc/platforms/4xx/sycamore.h b/arch/ppc/platforms/4xx/sycamore.h
new file mode 100644
index 0000000..3e7b4e2
--- /dev/null
+++ b/arch/ppc/platforms/4xx/sycamore.h
@@ -0,0 +1,67 @@
+/*
+ * arch/ppc/platforms/4xx/sycamore.h
+ *
+ * Macros, definitions, and data structures specific to the IBM PowerPC
+ * 405GPr "Sycamore" evaluation board.
+ *
+ * Author: Armin Kuster <akuster@mvista.com>
+ *
+ * 2000 (c) MontaVista, Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+
+#ifdef __KERNEL__
+#ifndef __ASM_SYCAMORE_H__
+#define __ASM_SYCAMORE_H__
+
+#include <platforms/4xx/ibm405gpr.h>
+
+#ifndef __ASSEMBLY__
+/*
+ * Data structure defining board information maintained by the boot
+ * ROM on IBM's "Sycamore" evaluation board. An effort has been made to
+ * keep the field names consistent with the 8xx 'bd_t' board info
+ * structures.
+ */
+
+typedef struct board_info {
+ unsigned char bi_s_version[4]; /* Version of this structure */
+ unsigned char bi_r_version[30]; /* Version of the IBM ROM */
+ unsigned int bi_memsize; /* DRAM installed, in bytes */
+ unsigned char bi_enetaddr[6]; /* Local Ethernet MAC address */
+ unsigned char bi_pci_enetaddr[6]; /* PCI Ethernet MAC address */
+ unsigned int bi_intfreq; /* Processor speed, in Hz */
+ unsigned int bi_busfreq; /* PLB Bus speed, in Hz */
+ unsigned int bi_pci_busfreq; /* PCI Bus speed, in Hz */
+} bd_t;
+
+/* Some 4xx parts use a different timebase frequency from the internal clock.
+*/
+#define bi_tbfreq bi_intfreq
+
+
+/* Memory map for the IBM "Sycamore" 405GP evaluation board.
+ * Generic 4xx plus RTC.
+ */
+
+extern void *sycamore_rtc_base;
+#define SYCAMORE_RTC_PADDR ((uint)0xf0000000)
+#define SYCAMORE_RTC_VADDR SYCAMORE_RTC_PADDR
+#define SYCAMORE_RTC_SIZE ((uint)8*1024)
+
+#ifdef CONFIG_PPC405GP_INTERNAL_CLOCK
+#define BASE_BAUD 201600
+#else
+#define BASE_BAUD 691200
+#endif
+
+#define SYCAMORE_PS2_BASE 0xF0100000
+#define SYCAMORE_FPGA_BASE 0xF0300000
+
+#define PPC4xx_MACHINE_NAME "IBM Sycamore"
+
+#endif /* !__ASSEMBLY__ */
+#endif /* __ASM_SYCAMORE_H__ */
+#endif /* __KERNEL__ */
diff --git a/arch/ppc/platforms/4xx/virtex-ii_pro.c b/arch/ppc/platforms/4xx/virtex-ii_pro.c
new file mode 100644
index 0000000..097cc9d5
--- /dev/null
+++ b/arch/ppc/platforms/4xx/virtex-ii_pro.c
@@ -0,0 +1,60 @@
+/*
+ * arch/ppc/platforms/4xx/virtex-ii_pro.c
+ *
+ * Author: MontaVista Software, Inc.
+ * source@mvista.com
+ *
+ * 2002-2004 (c) MontaVista Software, Inc. This file is licensed under the
+ * terms of the GNU General Public License version 2. This program is licensed
+ * "as is" without any warranty of any kind, whether express or implied.
+ */
+
+#include <linux/config.h>
+#include <linux/init.h>
+#include <asm/ocp.h>
+#include "virtex-ii_pro.h"
+
+/* Have OCP take care of the serial ports. */
+struct ocp_def core_ocp[] = {
+#ifdef XPAR_UARTNS550_0_BASEADDR
+ { .vendor = OCP_VENDOR_XILINX,
+ .function = OCP_FUNC_16550,
+ .index = 0,
+ .paddr = XPAR_UARTNS550_0_BASEADDR,
+ .irq = XPAR_INTC_0_UARTNS550_0_VEC_ID,
+ .pm = OCP_CPM_NA
+ },
+#ifdef XPAR_UARTNS550_1_BASEADDR
+ { .vendor = OCP_VENDOR_XILINX,
+ .function = OCP_FUNC_16550,
+ .index = 1,
+ .paddr = XPAR_UARTNS550_1_BASEADDR,
+ .irq = XPAR_INTC_0_UARTNS550_1_VEC_ID,
+ .pm = OCP_CPM_NA
+ },
+#ifdef XPAR_UARTNS550_2_BASEADDR
+ { .vendor = OCP_VENDOR_XILINX,
+ .function = OCP_FUNC_16550,
+ .index = 2,
+ .paddr = XPAR_UARTNS550_2_BASEADDR,
+ .irq = XPAR_INTC_0_UARTNS550_2_VEC_ID,
+ .pm = OCP_CPM_NA
+ },
+#ifdef XPAR_UARTNS550_3_BASEADDR
+ { .vendor = OCP_VENDOR_XILINX,
+ .function = OCP_FUNC_16550,
+ .index = 3,
+ .paddr = XPAR_UARTNS550_3_BASEADDR,
+ .irq = XPAR_INTC_0_UARTNS550_3_VEC_ID,
+ .pm = OCP_CPM_NA
+ },
+#ifdef XPAR_UARTNS550_4_BASEADDR
+#error Edit this file to add more devices.
+#endif /* 4 */
+#endif /* 3 */
+#endif /* 2 */
+#endif /* 1 */
+#endif /* 0 */
+ { .vendor = OCP_VENDOR_INVALID
+ }
+};
diff --git a/arch/ppc/platforms/4xx/virtex-ii_pro.h b/arch/ppc/platforms/4xx/virtex-ii_pro.h
new file mode 100644
index 0000000..9014c48
--- /dev/null
+++ b/arch/ppc/platforms/4xx/virtex-ii_pro.h
@@ -0,0 +1,99 @@
+/*
+ * arch/ppc/platforms/4xx/virtex-ii_pro.h
+ *
+ * Include file that defines the Xilinx Virtex-II Pro processor
+ *
+ * Author: MontaVista Software, Inc.
+ * source@mvista.com
+ *
+ * 2002-2004 (c) MontaVista Software, Inc. This file is licensed under the
+ * terms of the GNU General Public License version 2. This program is licensed
+ * "as is" without any warranty of any kind, whether express or implied.
+ */
+
+#ifdef __KERNEL__
+#ifndef __ASM_VIRTEXIIPRO_H__
+#define __ASM_VIRTEXIIPRO_H__
+
+#include <linux/config.h>
+#include <asm/xparameters.h>
+
+/* serial defines */
+
+#define RS_TABLE_SIZE 4 /* change this and add more devices below
+ if you have more then 4 16x50 UARTs */
+
+#define BASE_BAUD (XPAR_UARTNS550_0_CLOCK_FREQ_HZ/16)
+
+/* The serial ports in the Virtex-II Pro have each I/O byte in the
+ * LSByte of a word. This means that iomem_reg_shift needs to be 2 to
+ * change the byte offsets into word offsets. In addition the base
+ * addresses need to have 3 added to them to get to the LSByte.
+ */
+#define STD_UART_OP(num) \
+ { 0, BASE_BAUD, 0, XPAR_INTC_0_UARTNS550_##num##_VEC_ID, \
+ ASYNC_BOOT_AUTOCONF, \
+ .iomem_base = (u8 *)XPAR_UARTNS550_##num##_BASEADDR + 3, \
+ .iomem_reg_shift = 2, \
+ .io_type = SERIAL_IO_MEM},
+
+#if defined(XPAR_INTC_0_UARTNS550_0_VEC_ID)
+#define ML300_UART0 STD_UART_OP(0)
+#else
+#define ML300_UART0
+#endif
+
+#if defined(XPAR_INTC_0_UARTNS550_1_VEC_ID)
+#define ML300_UART1 STD_UART_OP(1)
+#else
+#define ML300_UART1
+#endif
+
+#if defined(XPAR_INTC_0_UARTNS550_2_VEC_ID)
+#define ML300_UART2 STD_UART_OP(2)
+#else
+#define ML300_UART2
+#endif
+
+#if defined(XPAR_INTC_0_UARTNS550_3_VEC_ID)
+#define ML300_UART3 STD_UART_OP(3)
+#else
+#define ML300_UART3
+#endif
+
+#if defined(XPAR_INTC_0_UARTNS550_4_VEC_ID)
+#error Edit this file to add more devices.
+#elif defined(XPAR_INTC_0_UARTNS550_3_VEC_ID)
+#define NR_SER_PORTS 4
+#elif defined(XPAR_INTC_0_UARTNS550_2_VEC_ID)
+#define NR_SER_PORTS 3
+#elif defined(XPAR_INTC_0_UARTNS550_1_VEC_ID)
+#define NR_SER_PORTS 2
+#elif defined(XPAR_INTC_0_UARTNS550_0_VEC_ID)
+#define NR_SER_PORTS 1
+#else
+#define NR_SER_PORTS 0
+#endif
+
+#if defined(CONFIG_UART0_TTYS0)
+#define SERIAL_PORT_DFNS \
+ ML300_UART0 \
+ ML300_UART1 \
+ ML300_UART2 \
+ ML300_UART3
+#endif
+
+#if defined(CONFIG_UART0_TTYS1)
+#define SERIAL_PORT_DFNS \
+ ML300_UART1 \
+ ML300_UART0 \
+ ML300_UART2 \
+ ML300_UART3
+#endif
+
+#define DCRN_CPMFR_BASE 0
+
+#include <asm/ibm405.h>
+
+#endif /* __ASM_VIRTEXIIPRO_H__ */
+#endif /* __KERNEL__ */
diff --git a/arch/ppc/platforms/4xx/walnut.c b/arch/ppc/platforms/4xx/walnut.c
new file mode 100644
index 0000000..a33eda4
--- /dev/null
+++ b/arch/ppc/platforms/4xx/walnut.c
@@ -0,0 +1,249 @@
+/*
+ * arch/ppc/platforms/4xx/walnut.c
+ *
+ * Architecture- / platform-specific boot-time initialization code for
+ * IBM PowerPC 4xx based boards. Adapted from original
+ * code by Gary Thomas, Cort Dougan <cort@fsmlabs.com>, and Dan Malek
+ * <dan@net4x.com>.
+ *
+ * Copyright(c) 1999-2000 Grant Erickson <grant@lcse.umn.edu>
+ *
+ * 2002 (c) MontaVista, Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/smp.h>
+#include <linux/threads.h>
+#include <linux/param.h>
+#include <linux/string.h>
+#include <linux/pci.h>
+#include <linux/rtc.h>
+
+#include <asm/system.h>
+#include <asm/pci-bridge.h>
+#include <asm/machdep.h>
+#include <asm/page.h>
+#include <asm/time.h>
+#include <asm/io.h>
+#include <asm/ocp.h>
+#include <asm/ibm_ocp_pci.h>
+#include <asm/todc.h>
+
+#undef DEBUG
+
+#ifdef DEBUG
+#define DBG(x...) printk(x)
+#else
+#define DBG(x...)
+#endif
+
+void *kb_cs;
+void *kb_data;
+void *walnut_rtc_base;
+
+/* Some IRQs unique to Walnut.
+ * Used by the generic 405 PCI setup functions in ppc4xx_pci.c
+ */
+int __init
+ppc405_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin)
+{
+ static char pci_irq_table[][4] =
+ /*
+ * PCI IDSEL/INTPIN->INTLINE
+ * A B C D
+ */
+ {
+ {28, 28, 28, 28}, /* IDSEL 1 - PCI slot 1 */
+ {29, 29, 29, 29}, /* IDSEL 2 - PCI slot 2 */
+ {30, 30, 30, 30}, /* IDSEL 3 - PCI slot 3 */
+ {31, 31, 31, 31}, /* IDSEL 4 - PCI slot 4 */
+ };
+
+ const long min_idsel = 1, max_idsel = 4, irqs_per_slot = 4;
+ return PCI_IRQ_TABLE_LOOKUP;
+};
+
+void __init
+walnut_setup_arch(void)
+{
+
+ void *fpga_brdc;
+ unsigned char fpga_brdc_data;
+ void *fpga_enable;
+ void *fpga_polarity;
+ void *fpga_status;
+ void *fpga_trigger;
+
+ ppc4xx_setup_arch();
+
+ ibm_ocp_set_emac(0, 0);
+
+ kb_data = ioremap(WALNUT_PS2_BASE, 8);
+ if (!kb_data) {
+ printk(KERN_CRIT
+ "walnut_setup_arch() kb_data ioremap failed\n");
+ return;
+ }
+
+ kb_cs = kb_data + 1;
+
+ fpga_status = ioremap(WALNUT_FPGA_BASE, 8);
+ if (!fpga_status) {
+ printk(KERN_CRIT
+ "walnut_setup_arch() fpga_status ioremap failed\n");
+ return;
+ }
+
+ fpga_enable = fpga_status + 1;
+ fpga_polarity = fpga_status + 2;
+ fpga_trigger = fpga_status + 3;
+ fpga_brdc = fpga_status + 4;
+
+ /* split the keyboard and mouse interrupts */
+ fpga_brdc_data = readb(fpga_brdc);
+ fpga_brdc_data |= 0x80;
+ writeb(fpga_brdc_data, fpga_brdc);
+
+ writeb(0x3, fpga_enable);
+
+ writeb(0x3, fpga_polarity);
+
+ writeb(0x3, fpga_trigger);
+
+ /* RTC step for the walnut */
+ walnut_rtc_base = (void *) WALNUT_RTC_VADDR;
+ TODC_INIT(TODC_TYPE_DS1743, walnut_rtc_base, walnut_rtc_base,
+ walnut_rtc_base, 8);
+ /* Identify the system */
+ printk("IBM Walnut port (C) 2000-2002 MontaVista Software, Inc. (source@mvista.com)\n");
+}
+
+void __init
+bios_fixup(struct pci_controller *hose, struct pcil0_regs *pcip)
+{
+#ifdef CONFIG_PCI
+ unsigned int bar_response, bar;
+ /*
+ * Expected PCI mapping:
+ *
+ * PLB addr PCI memory addr
+ * --------------------- ---------------------
+ * 0000'0000 - 7fff'ffff <--- 0000'0000 - 7fff'ffff
+ * 8000'0000 - Bfff'ffff ---> 8000'0000 - Bfff'ffff
+ *
+ * PLB addr PCI io addr
+ * --------------------- ---------------------
+ * e800'0000 - e800'ffff ---> 0000'0000 - 0001'0000
+ *
+ * The following code is simplified by assuming that the bootrom
+ * has been well behaved in following this mapping.
+ */
+
+#ifdef DEBUG
+ int i;
+
+ printk("ioremap PCLIO_BASE = 0x%x\n", pcip);
+ printk("PCI bridge regs before fixup \n");
+ for (i = 0; i <= 3; i++) {
+ printk(" pmm%dma\t0x%x\n", i, in_le32(&(pcip->pmm[i].ma)));
+ printk(" pmm%dma\t0x%x\n", i, in_le32(&(pcip->pmm[i].la)));
+ printk(" pmm%dma\t0x%x\n", i, in_le32(&(pcip->pmm[i].pcila)));
+ printk(" pmm%dma\t0x%x\n", i, in_le32(&(pcip->pmm[i].pciha)));
+ }
+ printk(" ptm1ms\t0x%x\n", in_le32(&(pcip->ptm1ms)));
+ printk(" ptm1la\t0x%x\n", in_le32(&(pcip->ptm1la)));
+ printk(" ptm2ms\t0x%x\n", in_le32(&(pcip->ptm2ms)));
+ printk(" ptm2la\t0x%x\n", in_le32(&(pcip->ptm2la)));
+
+#endif
+
+ /* added for IBM boot rom version 1.15 bios bar changes -AK */
+
+ /* Disable region first */
+ out_le32((void *) &(pcip->pmm[0].ma), 0x00000000);
+ /* PLB starting addr, PCI: 0x80000000 */
+ out_le32((void *) &(pcip->pmm[0].la), 0x80000000);
+ /* PCI start addr, 0x80000000 */
+ out_le32((void *) &(pcip->pmm[0].pcila), PPC405_PCI_MEM_BASE);
+ /* 512MB range of PLB to PCI */
+ out_le32((void *) &(pcip->pmm[0].pciha), 0x00000000);
+ /* Enable no pre-fetch, enable region */
+ out_le32((void *) &(pcip->pmm[0].ma), ((0xffffffff -
+ (PPC405_PCI_UPPER_MEM -
+ PPC405_PCI_MEM_BASE)) | 0x01));
+
+ /* Disable region one */
+ out_le32((void *) &(pcip->pmm[1].ma), 0x00000000);
+ out_le32((void *) &(pcip->pmm[1].la), 0x00000000);
+ out_le32((void *) &(pcip->pmm[1].pcila), 0x00000000);
+ out_le32((void *) &(pcip->pmm[1].pciha), 0x00000000);
+ out_le32((void *) &(pcip->pmm[1].ma), 0x00000000);
+ out_le32((void *) &(pcip->ptm1ms), 0x00000000);
+
+ /* Disable region two */
+ out_le32((void *) &(pcip->pmm[2].ma), 0x00000000);
+ out_le32((void *) &(pcip->pmm[2].la), 0x00000000);
+ out_le32((void *) &(pcip->pmm[2].pcila), 0x00000000);
+ out_le32((void *) &(pcip->pmm[2].pciha), 0x00000000);
+ out_le32((void *) &(pcip->pmm[2].ma), 0x00000000);
+ out_le32((void *) &(pcip->ptm2ms), 0x00000000);
+
+ /* Zero config bars */
+ for (bar = PCI_BASE_ADDRESS_1; bar <= PCI_BASE_ADDRESS_2; bar += 4) {
+ early_write_config_dword(hose, hose->first_busno,
+ PCI_FUNC(hose->first_busno), bar,
+ 0x00000000);
+ early_read_config_dword(hose, hose->first_busno,
+ PCI_FUNC(hose->first_busno), bar,
+ &bar_response);
+ DBG("BUS %d, device %d, Function %d bar 0x%8.8x is 0x%8.8x\n",
+ hose->first_busno, PCI_SLOT(hose->first_busno),
+ PCI_FUNC(hose->first_busno), bar, bar_response);
+ }
+ /* end work arround */
+
+#ifdef DEBUG
+ printk("PCI bridge regs after fixup \n");
+ for (i = 0; i <= 3; i++) {
+ printk(" pmm%dma\t0x%x\n", i, in_le32(&(pcip->pmm[i].ma)));
+ printk(" pmm%dma\t0x%x\n", i, in_le32(&(pcip->pmm[i].la)));
+ printk(" pmm%dma\t0x%x\n", i, in_le32(&(pcip->pmm[i].pcila)));
+ printk(" pmm%dma\t0x%x\n", i, in_le32(&(pcip->pmm[i].pciha)));
+ }
+ printk(" ptm1ms\t0x%x\n", in_le32(&(pcip->ptm1ms)));
+ printk(" ptm1la\t0x%x\n", in_le32(&(pcip->ptm1la)));
+ printk(" ptm2ms\t0x%x\n", in_le32(&(pcip->ptm2ms)));
+ printk(" ptm2la\t0x%x\n", in_le32(&(pcip->ptm2la)));
+
+#endif
+#endif
+}
+
+void __init
+walnut_map_io(void)
+{
+ ppc4xx_map_io();
+ io_block_mapping(WALNUT_RTC_VADDR,
+ WALNUT_RTC_PADDR, WALNUT_RTC_SIZE, _PAGE_IO);
+}
+
+void __init
+platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
+ unsigned long r6, unsigned long r7)
+{
+ ppc4xx_init(r3, r4, r5, r6, r7);
+
+ ppc_md.setup_arch = walnut_setup_arch;
+ ppc_md.setup_io_mappings = walnut_map_io;
+
+#ifdef CONFIG_GEN_RTC
+ ppc_md.time_init = todc_time_init;
+ ppc_md.set_rtc_time = todc_set_rtc_time;
+ ppc_md.get_rtc_time = todc_get_rtc_time;
+ ppc_md.nvram_read_val = todc_direct_read_val;
+ ppc_md.nvram_write_val = todc_direct_write_val;
+#endif
+}
diff --git a/arch/ppc/platforms/4xx/walnut.h b/arch/ppc/platforms/4xx/walnut.h
new file mode 100644
index 0000000..04cfbf3
--- /dev/null
+++ b/arch/ppc/platforms/4xx/walnut.h
@@ -0,0 +1,72 @@
+/*
+ * arch/ppc/platforms/4xx/walnut.h
+ *
+ * Macros, definitions, and data structures specific to the IBM PowerPC
+ * 405GP "Walnut" evaluation board.
+ *
+ * Authors: Grant Erickson <grant@lcse.umn.edu>, Frank Rowand
+ * <frank_rowand@mvista.com>, Debbie Chu <debbie_chu@mvista.com> or
+ * source@mvista.com
+ *
+ * Copyright (c) 1999 Grant Erickson <grant@lcse.umn.edu>
+ *
+ * 2000 (c) MontaVista, Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+
+#ifdef __KERNEL__
+#ifndef __ASM_WALNUT_H__
+#define __ASM_WALNUT_H__
+
+/* We have a 405GP core */
+#include <platforms/4xx/ibm405gp.h>
+
+#ifndef __ASSEMBLY__
+/*
+ * Data structure defining board information maintained by the boot
+ * ROM on IBM's "Walnut" evaluation board. An effort has been made to
+ * keep the field names consistent with the 8xx 'bd_t' board info
+ * structures.
+ */
+
+typedef struct board_info {
+ unsigned char bi_s_version[4]; /* Version of this structure */
+ unsigned char bi_r_version[30]; /* Version of the IBM ROM */
+ unsigned int bi_memsize; /* DRAM installed, in bytes */
+ unsigned char bi_enetaddr[6]; /* Local Ethernet MAC address */
+ unsigned char bi_pci_enetaddr[6]; /* PCI Ethernet MAC address */
+ unsigned int bi_intfreq; /* Processor speed, in Hz */
+ unsigned int bi_busfreq; /* PLB Bus speed, in Hz */
+ unsigned int bi_pci_busfreq; /* PCI Bus speed, in Hz */
+} bd_t;
+
+/* Some 4xx parts use a different timebase frequency from the internal clock.
+*/
+#define bi_tbfreq bi_intfreq
+
+
+/* Memory map for the IBM "Walnut" 405GP evaluation board.
+ * Generic 4xx plus RTC.
+ */
+
+extern void *walnut_rtc_base;
+#define WALNUT_RTC_PADDR ((uint)0xf0000000)
+#define WALNUT_RTC_VADDR WALNUT_RTC_PADDR
+#define WALNUT_RTC_SIZE ((uint)8*1024)
+
+#ifdef CONFIG_PPC405GP_INTERNAL_CLOCK
+#define BASE_BAUD 201600
+#else
+#define BASE_BAUD 691200
+#endif
+
+#define WALNUT_PS2_BASE 0xF0100000
+#define WALNUT_FPGA_BASE 0xF0300000
+
+#define PPC4xx_MACHINE_NAME "IBM Walnut"
+
+#endif /* !__ASSEMBLY__ */
+#endif /* __ASM_WALNUT_H__ */
+#endif /* __KERNEL__ */
diff --git a/arch/ppc/platforms/4xx/xilinx_ml300.c b/arch/ppc/platforms/4xx/xilinx_ml300.c
new file mode 100644
index 0000000..0b1b77d
--- /dev/null
+++ b/arch/ppc/platforms/4xx/xilinx_ml300.c
@@ -0,0 +1,146 @@
+/*
+ * arch/ppc/platforms/4xx/xilinx_ml300.c
+ *
+ * Xilinx ML300 evaluation board initialization
+ *
+ * Author: MontaVista Software, Inc.
+ * source@mvista.com
+ *
+ * 2002-2004 (c) MontaVista Software, Inc. This file is licensed under the
+ * terms of the GNU General Public License version 2. This program is licensed
+ * "as is" without any warranty of any kind, whether express or implied.
+ */
+
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+#include <linux/tty.h>
+#include <linux/serial.h>
+#include <linux/serial_core.h>
+#include <linux/serialP.h>
+#include <asm/io.h>
+#include <asm/machdep.h>
+#include <asm/ocp.h>
+
+#include <platforms/4xx/virtex-ii_pro.h> /* for NR_SER_PORTS */
+
+/*
+ * As an overview of how the following functions (platform_init,
+ * ml300_map_io, ml300_setup_arch and ml300_init_IRQ) fit into the
+ * kernel startup procedure, here's a call tree:
+ *
+ * start_here arch/ppc/kernel/head_4xx.S
+ * early_init arch/ppc/kernel/setup.c
+ * machine_init arch/ppc/kernel/setup.c
+ * platform_init this file
+ * ppc4xx_init arch/ppc/syslib/ppc4xx_setup.c
+ * parse_bootinfo
+ * find_bootinfo
+ * "setup some default ppc_md pointers"
+ * MMU_init arch/ppc/mm/init.c
+ * *ppc_md.setup_io_mappings == ml300_map_io this file
+ * ppc4xx_map_io arch/ppc/syslib/ppc4xx_setup.c
+ * start_kernel init/main.c
+ * setup_arch arch/ppc/kernel/setup.c
+ * #if defined(CONFIG_KGDB)
+ * *ppc_md.kgdb_map_scc() == gen550_kgdb_map_scc
+ * #endif
+ * *ppc_md.setup_arch == ml300_setup_arch this file
+ * ppc4xx_setup_arch arch/ppc/syslib/ppc4xx_setup.c
+ * ppc4xx_find_bridges arch/ppc/syslib/ppc405_pci.c
+ * init_IRQ arch/ppc/kernel/irq.c
+ * *ppc_md.init_IRQ == ml300_init_IRQ this file
+ * ppc4xx_init_IRQ arch/ppc/syslib/ppc4xx_setup.c
+ * ppc4xx_pic_init arch/ppc/syslib/xilinx_pic.c
+ */
+
+#if defined(XPAR_POWER_0_POWERDOWN_BASEADDR)
+
+static volatile unsigned *powerdown_base =
+ (volatile unsigned *) XPAR_POWER_0_POWERDOWN_BASEADDR;
+
+static void
+xilinx_power_off(void)
+{
+ local_irq_disable();
+ out_be32(powerdown_base, XPAR_POWER_0_POWERDOWN_VALUE);
+ while (1) ;
+}
+#endif
+
+void __init
+ml300_map_io(void)
+{
+ ppc4xx_map_io();
+
+#if defined(XPAR_POWER_0_POWERDOWN_BASEADDR)
+ powerdown_base = ioremap((unsigned long) powerdown_base,
+ XPAR_POWER_0_POWERDOWN_HIGHADDR -
+ XPAR_POWER_0_POWERDOWN_BASEADDR + 1);
+#endif
+}
+
+static void __init
+ml300_early_serial_map(void)
+{
+#ifdef CONFIG_SERIAL_8250
+ struct serial_state old_ports[] = { SERIAL_PORT_DFNS };
+ struct uart_port port;
+ int i;
+
+ /* Setup ioremapped serial port access */
+ for (i = 0; i < ARRAY_SIZE(old_ports); i++ ) {
+ memset(&port, 0, sizeof(port));
+ port.membase = ioremap((phys_addr_t)(old_ports[i].iomem_base), 16);
+ port.irq = old_ports[i].irq;
+ port.uartclk = old_ports[i].baud_base * 16;
+ port.regshift = old_ports[i].iomem_reg_shift;
+ port.iotype = SERIAL_IO_MEM;
+ port.flags = ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST;
+ port.line = i;
+
+ if (early_serial_setup(&port) != 0) {
+ printk("Early serial init of port %d failed\n", i);
+ }
+ }
+#endif /* CONFIG_SERIAL_8250 */
+}
+
+void __init
+ml300_setup_arch(void)
+{
+ ppc4xx_setup_arch(); /* calls ppc4xx_find_bridges() */
+
+ ml300_early_serial_map();
+
+ /* Identify the system */
+ printk(KERN_INFO "Xilinx Virtex-II Pro port\n");
+ printk(KERN_INFO "Port by MontaVista Software, Inc. (source@mvista.com)\n");
+}
+
+/* Called after board_setup_irq from ppc4xx_init_IRQ(). */
+void __init
+ml300_init_irq(void)
+{
+ ppc4xx_init_IRQ();
+}
+
+void __init
+platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
+ unsigned long r6, unsigned long r7)
+{
+ ppc4xx_init(r3, r4, r5, r6, r7);
+
+ ppc_md.setup_arch = ml300_setup_arch;
+ ppc_md.setup_io_mappings = ml300_map_io;
+ ppc_md.init_IRQ = ml300_init_irq;
+
+#if defined(XPAR_POWER_0_POWERDOWN_BASEADDR)
+ ppc_md.power_off = xilinx_power_off;
+#endif
+
+#ifdef CONFIG_KGDB
+ ppc_md.early_serial_map = ml300_early_serial_map;
+#endif
+}
+
diff --git a/arch/ppc/platforms/4xx/xilinx_ml300.h b/arch/ppc/platforms/4xx/xilinx_ml300.h
new file mode 100644
index 0000000..f8c5884
--- /dev/null
+++ b/arch/ppc/platforms/4xx/xilinx_ml300.h
@@ -0,0 +1,47 @@
+/*
+ * arch/ppc/platforms/4xx/xilinx_ml300.h
+ *
+ * Include file that defines the Xilinx ML300 evaluation board
+ *
+ * Author: MontaVista Software, Inc.
+ * source@mvista.com
+ *
+ * 2002-2004 (c) MontaVista Software, Inc. This file is licensed under the
+ * terms of the GNU General Public License version 2. This program is licensed
+ * "as is" without any warranty of any kind, whether express or implied.
+ */
+
+#ifdef __KERNEL__
+#ifndef __ASM_XILINX_ML300_H__
+#define __ASM_XILINX_ML300_H__
+
+/* ML300 has a Xilinx Virtex-II Pro processor */
+#include <platforms/4xx/virtex-ii_pro.h>
+
+#ifndef __ASSEMBLY__
+
+#include <linux/types.h>
+
+typedef struct board_info {
+ unsigned int bi_memsize; /* DRAM installed, in bytes */
+ unsigned char bi_enetaddr[6]; /* Local Ethernet MAC address */
+ unsigned int bi_intfreq; /* Processor speed, in Hz */
+ unsigned int bi_busfreq; /* PLB Bus speed, in Hz */
+ unsigned int bi_pci_busfreq; /* PCI Bus speed, in Hz */
+} bd_t;
+
+/* Some 4xx parts use a different timebase frequency from the internal clock.
+*/
+#define bi_tbfreq bi_intfreq
+
+#endif /* !__ASSEMBLY__ */
+
+/* We don't need anything mapped. Size of zero will accomplish that. */
+#define PPC4xx_ONB_IO_PADDR 0u
+#define PPC4xx_ONB_IO_VADDR 0u
+#define PPC4xx_ONB_IO_SIZE 0u
+
+#define PPC4xx_MACHINE_NAME "Xilinx ML300"
+
+#endif /* __ASM_XILINX_ML300_H__ */
+#endif /* __KERNEL__ */
diff --git a/arch/ppc/platforms/4xx/xparameters/xparameters_ml300.h b/arch/ppc/platforms/4xx/xparameters/xparameters_ml300.h
new file mode 100644
index 0000000..97e3f4d
--- /dev/null
+++ b/arch/ppc/platforms/4xx/xparameters/xparameters_ml300.h
@@ -0,0 +1,310 @@
+/*******************************************************************
+*
+* Author: Xilinx, Inc.
+*
+*
+* 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.
+*
+*
+* XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" AS A
+* COURTESY TO YOU. BY PROVIDING THIS DESIGN, CODE, OR INFORMATION AS
+* ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE, APPLICATION OR STANDARD,
+* XILINX IS MAKING NO REPRESENTATION THAT THIS IMPLEMENTATION IS FREE
+* FROM ANY CLAIMS OF INFRINGEMENT, AND YOU ARE RESPONSIBLE FOR OBTAINING
+* ANY THIRD PARTY RIGHTS YOU MAY REQUIRE FOR YOUR IMPLEMENTATION.
+* XILINX EXPRESSLY DISCLAIMS ANY WARRANTY WHATSOEVER WITH RESPECT TO
+* THE ADEQUACY OF THE IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO ANY
+* WARRANTIES OR REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE FROM
+* CLAIMS OF INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY AND
+* FITNESS FOR A PARTICULAR PURPOSE.
+*
+*
+* Xilinx hardware products are not intended for use in life support
+* appliances, devices, or systems. Use in such applications is
+* expressly prohibited.
+*
+*
+* (c) Copyright 2002-2004 Xilinx Inc.
+* All rights reserved.
+*
+*
+* 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.,
+* 675 Mass Ave, Cambridge, MA 02139, USA.
+*
+* Description: Driver parameters
+*
+*******************************************************************/
+
+#define XPAR_XPCI_NUM_INSTANCES 1
+#define XPAR_XPCI_CLOCK_HZ 33333333
+#define XPAR_OPB_PCI_REF_0_DEVICE_ID 0
+#define XPAR_OPB_PCI_REF_0_BASEADDR 0x20000000
+#define XPAR_OPB_PCI_REF_0_HIGHADDR 0x3FFFFFFF
+#define XPAR_OPB_PCI_REF_0_CONFIG_ADDR 0x3C000000
+#define XPAR_OPB_PCI_REF_0_CONFIG_DATA 0x3C000004
+#define XPAR_OPB_PCI_REF_0_LCONFIG_ADDR 0x3E000000
+#define XPAR_OPB_PCI_REF_0_MEM_BASEADDR 0x20000000
+#define XPAR_OPB_PCI_REF_0_MEM_HIGHADDR 0x37FFFFFF
+#define XPAR_OPB_PCI_REF_0_IO_BASEADDR 0x38000000
+#define XPAR_OPB_PCI_REF_0_IO_HIGHADDR 0x3BFFFFFF
+
+/******************************************************************/
+
+#define XPAR_XEMAC_NUM_INSTANCES 1
+#define XPAR_OPB_ETHERNET_0_BASEADDR 0x60000000
+#define XPAR_OPB_ETHERNET_0_HIGHADDR 0x60003FFF
+#define XPAR_OPB_ETHERNET_0_DEVICE_ID 0
+#define XPAR_OPB_ETHERNET_0_ERR_COUNT_EXIST 1
+#define XPAR_OPB_ETHERNET_0_DMA_PRESENT 1
+#define XPAR_OPB_ETHERNET_0_MII_EXIST 1
+
+/******************************************************************/
+
+#define XPAR_MY_OPB_GPIO_0_DEVICE_ID_0 0
+#define XPAR_MY_OPB_GPIO_0_BASEADDR_0 0x90000000
+#define XPAR_MY_OPB_GPIO_0_HIGHADDR_0 (0x90000000+0x7)
+#define XPAR_MY_OPB_GPIO_0_DEVICE_ID_1 1
+#define XPAR_MY_OPB_GPIO_0_BASEADDR_1 (0x90000000+0x8)
+#define XPAR_MY_OPB_GPIO_0_HIGHADDR_1 (0x90000000+0x1F)
+#define XPAR_XGPIO_NUM_INSTANCES 2
+
+/******************************************************************/
+
+#define XPAR_XIIC_NUM_INSTANCES 1
+#define XPAR_OPB_IIC_0_BASEADDR 0xA8000000
+#define XPAR_OPB_IIC_0_HIGHADDR 0xA80001FF
+#define XPAR_OPB_IIC_0_DEVICE_ID 0
+#define XPAR_OPB_IIC_0_TEN_BIT_ADR 0
+
+/******************************************************************/
+
+#define XPAR_XUARTNS550_NUM_INSTANCES 2
+#define XPAR_XUARTNS550_CLOCK_HZ 100000000
+#define XPAR_OPB_UART16550_0_BASEADDR 0xA0000000
+#define XPAR_OPB_UART16550_0_HIGHADDR 0xA0001FFF
+#define XPAR_OPB_UART16550_0_DEVICE_ID 0
+#define XPAR_OPB_UART16550_1_BASEADDR 0xA0010000
+#define XPAR_OPB_UART16550_1_HIGHADDR 0xA0011FFF
+#define XPAR_OPB_UART16550_1_DEVICE_ID 1
+
+/******************************************************************/
+
+#define XPAR_XSPI_NUM_INSTANCES 1
+#define XPAR_OPB_SPI_0_BASEADDR 0xA4000000
+#define XPAR_OPB_SPI_0_HIGHADDR 0xA400007F
+#define XPAR_OPB_SPI_0_DEVICE_ID 0
+#define XPAR_OPB_SPI_0_FIFO_EXIST 1
+#define XPAR_OPB_SPI_0_SPI_SLAVE_ONLY 0
+#define XPAR_OPB_SPI_0_NUM_SS_BITS 1
+
+/******************************************************************/
+
+#define XPAR_XPS2_NUM_INSTANCES 2
+#define XPAR_OPB_PS2_DUAL_REF_0_DEVICE_ID_0 0
+#define XPAR_OPB_PS2_DUAL_REF_0_BASEADDR_0 0xA9000000
+#define XPAR_OPB_PS2_DUAL_REF_0_HIGHADDR_0 (0xA9000000+0x3F)
+#define XPAR_OPB_PS2_DUAL_REF_0_DEVICE_ID_1 1
+#define XPAR_OPB_PS2_DUAL_REF_0_BASEADDR_1 (0xA9000000+0x1000)
+#define XPAR_OPB_PS2_DUAL_REF_0_HIGHADDR_1 (0xA9000000+0x103F)
+
+/******************************************************************/
+
+#define XPAR_XTOUCHSCREEN_NUM_INSTANCES 1
+#define XPAR_OPB_TSD_REF_0_BASEADDR 0xAA000000
+#define XPAR_OPB_TSD_REF_0_HIGHADDR 0xAA000007
+#define XPAR_OPB_TSD_REF_0_DEVICE_ID 0
+
+/******************************************************************/
+
+#define XPAR_OPB_AC97_CONTROLLER_REF_0_BASEADDR 0xA6000000
+#define XPAR_OPB_AC97_CONTROLLER_REF_0_HIGHADDR 0xA60000FF
+#define XPAR_OPB_PAR_PORT_REF_0_BASEADDR 0x90010000
+#define XPAR_OPB_PAR_PORT_REF_0_HIGHADDR 0x900100FF
+#define XPAR_PLB_DDR_0_BASEADDR 0x00000000
+#define XPAR_PLB_DDR_0_HIGHADDR 0x0FFFFFFF
+
+/******************************************************************/
+
+#define XPAR_XINTC_HAS_IPR 1
+#define XPAR_INTC_MAX_NUM_INTR_INPUTS 18
+#define XPAR_XINTC_USE_DCR 0
+#define XPAR_XINTC_NUM_INSTANCES 1
+#define XPAR_DCR_INTC_0_BASEADDR 0xD0000FC0
+#define XPAR_DCR_INTC_0_HIGHADDR 0xD0000FDF
+#define XPAR_DCR_INTC_0_DEVICE_ID 0
+#define XPAR_DCR_INTC_0_KIND_OF_INTR 0x00038000
+
+/******************************************************************/
+
+#define XPAR_DCR_INTC_0_MISC_LOGIC_0_PHY_MII_INT_INTR 0
+#define XPAR_DCR_INTC_0_OPB_ETHERNET_0_IP2INTC_IRPT_INTR 1
+#define XPAR_DCR_INTC_0_MISC_LOGIC_0_IIC_TEMP_CRIT_INTR 2
+#define XPAR_DCR_INTC_0_MISC_LOGIC_0_IIC_IRQ_INTR 3
+#define XPAR_DCR_INTC_0_OPB_IIC_0_IP2INTC_IRPT_INTR 4
+#define XPAR_DCR_INTC_0_OPB_SYSACE_0_SYSACE_IRQ_INTR 5
+#define XPAR_DCR_INTC_0_OPB_UART16550_0_IP2INTC_IRPT_INTR 6
+#define XPAR_DCR_INTC_0_OPB_UART16550_1_IP2INTC_IRPT_INTR 7
+#define XPAR_DCR_INTC_0_OPB_PS2_DUAL_REF_0_SYS_INTR1_INTR 8
+#define XPAR_DCR_INTC_0_OPB_PS2_DUAL_REF_0_SYS_INTR2_INTR 9
+#define XPAR_DCR_INTC_0_OPB_SPI_0_IP2INTC_IRPT_INTR 10
+#define XPAR_DCR_INTC_0_OPB_TSD_REF_0_INTR_INTR 11
+#define XPAR_DCR_INTC_0_OPB_AC97_CONTROLLER_REF_0_PLAYBACK_INTERRUPT_INTR 12
+#define XPAR_DCR_INTC_0_OPB_AC97_CONTROLLER_REF_0_RECORD_INTERRUPT_INTR 13
+#define XPAR_DCR_INTC_0_OPB_PCI_REF_0_INTR_OUT_INTR 14
+#define XPAR_DCR_INTC_0_PLB2OPB_BRIDGE_0_BUS_ERROR_DET_INTR 15
+#define XPAR_DCR_INTC_0_PLB_V34_0_BUS_ERROR_DET_INTR 16
+#define XPAR_DCR_INTC_0_OPB2PLB_BRIDGE_0_BUS_ERROR_DET_INTR 17
+
+/******************************************************************/
+
+#define XPAR_XTFT_NUM_INSTANCES 1
+#define XPAR_PLB_TFT_CNTLR_REF_0_DCR_BASEADDR 0xD0000200
+#define XPAR_PLB_TFT_CNTLR_REF_0_DCR_HIGHADDR 0xD0000207
+#define XPAR_PLB_TFT_CNTLR_REF_0_DEVICE_ID 0
+
+/******************************************************************/
+
+#define XPAR_XSYSACE_MEM_WIDTH 8
+#define XPAR_XSYSACE_NUM_INSTANCES 1
+#define XPAR_OPB_SYSACE_0_BASEADDR 0xCF000000
+#define XPAR_OPB_SYSACE_0_HIGHADDR 0xCF0001FF
+#define XPAR_OPB_SYSACE_0_DEVICE_ID 0
+#define XPAR_OPB_SYSACE_0_MEM_WIDTH 8
+
+/******************************************************************/
+
+#define XPAR_CPU_PPC405_CORE_CLOCK_FREQ_HZ 300000000
+
+/******************************************************************/
+
+/******************************************************************/
+
+/* Linux Redefines */
+
+/******************************************************************/
+
+#define XPAR_UARTNS550_0_BASEADDR (XPAR_OPB_UART16550_0_BASEADDR+0x1000)
+#define XPAR_UARTNS550_0_HIGHADDR XPAR_OPB_UART16550_0_HIGHADDR
+#define XPAR_UARTNS550_0_CLOCK_FREQ_HZ XPAR_XUARTNS550_CLOCK_HZ
+#define XPAR_UARTNS550_0_DEVICE_ID XPAR_OPB_UART16550_0_DEVICE_ID
+#define XPAR_UARTNS550_1_BASEADDR (XPAR_OPB_UART16550_1_BASEADDR+0x1000)
+#define XPAR_UARTNS550_1_HIGHADDR XPAR_OPB_UART16550_1_HIGHADDR
+#define XPAR_UARTNS550_1_CLOCK_FREQ_HZ XPAR_XUARTNS550_CLOCK_HZ
+#define XPAR_UARTNS550_1_DEVICE_ID XPAR_OPB_UART16550_1_DEVICE_ID
+
+/******************************************************************/
+
+#define XPAR_GPIO_0_BASEADDR XPAR_MY_OPB_GPIO_0_BASEADDR_0
+#define XPAR_GPIO_0_HIGHADDR XPAR_MY_OPB_GPIO_0_HIGHADDR_0
+#define XPAR_GPIO_0_DEVICE_ID XPAR_MY_OPB_GPIO_0_DEVICE_ID_0
+#define XPAR_GPIO_1_BASEADDR XPAR_MY_OPB_GPIO_0_BASEADDR_1
+#define XPAR_GPIO_1_HIGHADDR XPAR_MY_OPB_GPIO_0_HIGHADDR_1
+#define XPAR_GPIO_1_DEVICE_ID XPAR_MY_OPB_GPIO_0_DEVICE_ID_1
+
+/******************************************************************/
+
+#define XPAR_IIC_0_BASEADDR XPAR_OPB_IIC_0_BASEADDR
+#define XPAR_IIC_0_HIGHADDR XPAR_OPB_IIC_0_HIGHADDR
+#define XPAR_IIC_0_TEN_BIT_ADR XPAR_OPB_IIC_0_TEN_BIT_ADR
+#define XPAR_IIC_0_DEVICE_ID XPAR_OPB_IIC_0_DEVICE_ID
+
+/******************************************************************/
+
+#define XPAR_SYSACE_0_BASEADDR XPAR_OPB_SYSACE_0_BASEADDR
+#define XPAR_SYSACE_0_HIGHADDR XPAR_OPB_SYSACE_0_HIGHADDR
+#define XPAR_SYSACE_0_DEVICE_ID XPAR_OPB_SYSACE_0_DEVICE_ID
+
+/******************************************************************/
+
+#define XPAR_INTC_0_BASEADDR XPAR_DCR_INTC_0_BASEADDR
+#define XPAR_INTC_0_HIGHADDR XPAR_DCR_INTC_0_HIGHADDR
+#define XPAR_INTC_0_KIND_OF_INTR XPAR_DCR_INTC_0_KIND_OF_INTR
+#define XPAR_INTC_0_DEVICE_ID XPAR_DCR_INTC_0_DEVICE_ID
+
+/******************************************************************/
+
+#define XPAR_INTC_0_EMAC_0_VEC_ID XPAR_DCR_INTC_0_OPB_ETHERNET_0_IP2INTC_IRPT_INTR
+#define XPAR_INTC_0_IIC_0_VEC_ID XPAR_DCR_INTC_0_OPB_IIC_0_IP2INTC_IRPT_INTR
+#define XPAR_INTC_0_SYSACE_0_VEC_ID XPAR_DCR_INTC_0_OPB_SYSACE_0_SYSACE_IRQ_INTR
+#define XPAR_INTC_0_UARTNS550_0_VEC_ID XPAR_DCR_INTC_0_OPB_UART16550_0_IP2INTC_IRPT_INTR
+#define XPAR_INTC_0_UARTNS550_1_VEC_ID XPAR_DCR_INTC_0_OPB_UART16550_1_IP2INTC_IRPT_INTR
+#define XPAR_INTC_0_PS2_0_VEC_ID XPAR_DCR_INTC_0_OPB_PS2_DUAL_REF_0_SYS_INTR1_INTR
+#define XPAR_INTC_0_PS2_1_VEC_ID XPAR_DCR_INTC_0_OPB_PS2_DUAL_REF_0_SYS_INTR2_INTR
+#define XPAR_INTC_0_SPI_0_VEC_ID XPAR_DCR_INTC_0_OPB_SPI_0_IP2INTC_IRPT_INTR
+#define XPAR_INTC_0_TOUCHSCREEN_0_VEC_ID XPAR_DCR_INTC_0_OPB_TSD_REF_0_INTR_INTR
+#define XPAR_INTC_0_PCI_0_VEC_ID_A XPAR_DCR_INTC_0_OPB_PCI_REF_0_INTR_OUT_INTR
+#define XPAR_INTC_0_PCI_0_VEC_ID_B XPAR_DCR_INTC_0_OPB_PCI_REF_0_INTR_OUT_INTR
+#define XPAR_INTC_0_PCI_0_VEC_ID_C XPAR_DCR_INTC_0_OPB_PCI_REF_0_INTR_OUT_INTR
+#define XPAR_INTC_0_PCI_0_VEC_ID_D XPAR_DCR_INTC_0_OPB_PCI_REF_0_INTR_OUT_INTR
+
+/******************************************************************/
+
+#define XPAR_EMAC_0_BASEADDR XPAR_OPB_ETHERNET_0_BASEADDR
+#define XPAR_EMAC_0_HIGHADDR XPAR_OPB_ETHERNET_0_HIGHADDR
+#define XPAR_EMAC_0_DMA_PRESENT XPAR_OPB_ETHERNET_0_DMA_PRESENT
+#define XPAR_EMAC_0_MII_EXIST XPAR_OPB_ETHERNET_0_MII_EXIST
+#define XPAR_EMAC_0_ERR_COUNT_EXIST XPAR_OPB_ETHERNET_0_ERR_COUNT_EXIST
+#define XPAR_EMAC_0_DEVICE_ID XPAR_OPB_ETHERNET_0_DEVICE_ID
+
+/******************************************************************/
+
+#define XPAR_SPI_0_BASEADDR XPAR_OPB_SPI_0_BASEADDR
+#define XPAR_SPI_0_HIGHADDR XPAR_OPB_SPI_0_HIGHADDR
+#define XPAR_SPI_0_DEVICE_ID XPAR_OPB_SPI_0_DEVICE_ID
+
+/******************************************************************/
+
+#define XPAR_TOUCHSCREEN_0_BASEADDR XPAR_OPB_TSD_REF_0_BASEADDR
+#define XPAR_TOUCHSCREEN_0_HIGHADDR XPAR_OPB_TSD_REF_0_HIGHADDR
+#define XPAR_TOUCHSCREEN_0_DEVICE_ID XPAR_OPB_TSD_REF_0_DEVICE_ID
+
+/******************************************************************/
+
+#define XPAR_TFT_0_BASEADDR XPAR_PLB_TFT_CNTLR_REF_0_DCR_BASEADDR
+
+/******************************************************************/
+
+#define XPAR_PCI_0_BASEADDR XPAR_OPB_PCI_REF_0_BASEADDR
+#define XPAR_PCI_0_HIGHADDR XPAR_OPB_PCI_REF_0_HIGHADDR
+#define XPAR_PCI_0_CONFIG_ADDR XPAR_OPB_PCI_REF_0_CONFIG_ADDR
+#define XPAR_PCI_0_CONFIG_DATA XPAR_OPB_PCI_REF_0_CONFIG_DATA
+#define XPAR_PCI_0_LCONFIG_ADDR XPAR_OPB_PCI_REF_0_LCONFIG_ADDR
+#define XPAR_PCI_0_MEM_BASEADDR XPAR_OPB_PCI_REF_0_MEM_BASEADDR
+#define XPAR_PCI_0_MEM_HIGHADDR XPAR_OPB_PCI_REF_0_MEM_HIGHADDR
+#define XPAR_PCI_0_IO_BASEADDR XPAR_OPB_PCI_REF_0_IO_BASEADDR
+#define XPAR_PCI_0_IO_HIGHADDR XPAR_OPB_PCI_REF_0_IO_HIGHADDR
+#define XPAR_PCI_0_CLOCK_FREQ_HZ XPAR_XPCI_CLOCK_HZ
+#define XPAR_PCI_0_DEVICE_ID XPAR_OPB_PCI_REF_0_DEVICE_ID
+
+/******************************************************************/
+
+#define XPAR_PS2_0_BASEADDR XPAR_OPB_PS2_DUAL_REF_0_BASEADDR_0
+#define XPAR_PS2_0_HIGHADDR XPAR_OPB_PS2_DUAL_REF_0_HIGHADDR_0
+#define XPAR_PS2_0_DEVICE_ID XPAR_OPB_PS2_DUAL_REF_0_DEVICE_ID_0
+#define XPAR_PS2_1_BASEADDR XPAR_OPB_PS2_DUAL_REF_0_BASEADDR_1
+#define XPAR_PS2_1_HIGHADDR XPAR_OPB_PS2_DUAL_REF_0_HIGHADDR_1
+#define XPAR_PS2_1_DEVICE_ID XPAR_OPB_PS2_DUAL_REF_0_DEVICE_ID_1
+
+/******************************************************************/
+
+#define XPAR_PLB_CLOCK_FREQ_HZ 100000000
+#define XPAR_CORE_CLOCK_FREQ_HZ XPAR_CPU_PPC405_CORE_CLOCK_FREQ_HZ
+#define XPAR_DDR_0_SIZE 0x08000000
+
+/******************************************************************/
+
+#define XPAR_PERSISTENT_0_IIC_0_BASEADDR 0x00000400
+#define XPAR_PERSISTENT_0_IIC_0_HIGHADDR 0x000007FF
+#define XPAR_PERSISTENT_0_IIC_0_EEPROMADDR 0xA0
+
+/******************************************************************/
+
+#define XPAR_POWER_0_POWERDOWN_BASEADDR 0x90000004
+#define XPAR_POWER_0_POWERDOWN_HIGHADDR 0x90000007
+#define XPAR_POWER_0_POWERDOWN_VALUE 0xFF
+
+/******************************************************************/
diff --git a/arch/ppc/platforms/83xx/Makefile b/arch/ppc/platforms/83xx/Makefile
new file mode 100644
index 0000000..eb55341
--- /dev/null
+++ b/arch/ppc/platforms/83xx/Makefile
@@ -0,0 +1,4 @@
+#
+# Makefile for the PowerPC 83xx linux kernel.
+#
+obj-$(CONFIG_MPC834x_SYS) += mpc834x_sys.o
diff --git a/arch/ppc/platforms/83xx/mpc834x_sys.c b/arch/ppc/platforms/83xx/mpc834x_sys.c
new file mode 100644
index 0000000..b3b0f51
--- /dev/null
+++ b/arch/ppc/platforms/83xx/mpc834x_sys.c
@@ -0,0 +1,289 @@
+/*
+ * arch/ppc/platforms/83xx/mpc834x_sys.c
+ *
+ * MPC834x SYS board specific routines
+ *
+ * Maintainer: Kumar Gala <kumar.gala@freescale.com>
+ *
+ * Copyright 2005 Freescale Semiconductor Inc.
+ *
+ * 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.
+ */
+
+#include <linux/config.h>
+#include <linux/stddef.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/reboot.h>
+#include <linux/pci.h>
+#include <linux/kdev_t.h>
+#include <linux/major.h>
+#include <linux/console.h>
+#include <linux/delay.h>
+#include <linux/irq.h>
+#include <linux/seq_file.h>
+#include <linux/root_dev.h>
+#include <linux/serial.h>
+#include <linux/tty.h> /* for linux/serial_core.h */
+#include <linux/serial_core.h>
+#include <linux/initrd.h>
+#include <linux/module.h>
+#include <linux/fsl_devices.h>
+
+#include <asm/system.h>
+#include <asm/pgtable.h>
+#include <asm/page.h>
+#include <asm/atomic.h>
+#include <asm/time.h>
+#include <asm/io.h>
+#include <asm/machdep.h>
+#include <asm/prom.h>
+#include <asm/ipic.h>
+#include <asm/bootinfo.h>
+#include <asm/pci-bridge.h>
+#include <asm/mpc83xx.h>
+#include <asm/irq.h>
+#include <asm/kgdb.h>
+#include <asm/ppc_sys.h>
+#include <mm/mmu_decl.h>
+
+#include <syslib/ppc83xx_setup.h>
+
+#ifndef CONFIG_PCI
+unsigned long isa_io_base = 0;
+unsigned long isa_mem_base = 0;
+#endif
+
+extern unsigned long total_memory; /* in mm/init */
+
+unsigned char __res[sizeof (bd_t)];
+
+#ifdef CONFIG_PCI
+#error "PCI is not supported"
+/* NEED mpc83xx_map_irq & mpc83xx_exclude_device
+ see platforms/85xx/mpc85xx_ads_common.c */
+#endif /* CONFIG_PCI */
+
+/* ************************************************************************
+ *
+ * Setup the architecture
+ *
+ */
+static void __init
+mpc834x_sys_setup_arch(void)
+{
+ bd_t *binfo = (bd_t *) __res;
+ unsigned int freq;
+ struct gianfar_platform_data *pdata;
+
+ /* get the core frequency */
+ freq = binfo->bi_intfreq;
+
+ /* Set loops_per_jiffy to a half-way reasonable value,
+ for use until calibrate_delay gets called. */
+ loops_per_jiffy = freq / HZ;
+
+#ifdef CONFIG_PCI
+ /* setup PCI host bridges */
+ mpc83xx_sys_setup_hose();
+#endif
+ mpc83xx_early_serial_map();
+
+ /* setup the board related information for the enet controllers */
+ pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC83xx_TSEC1);
+ pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR;
+ pdata->interruptPHY = MPC83xx_IRQ_EXT1;
+ pdata->phyid = 0;
+ /* fixup phy address */
+ pdata->phy_reg_addr += binfo->bi_immr_base;
+ memcpy(pdata->mac_addr, binfo->bi_enetaddr, 6);
+
+ pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC83xx_TSEC2);
+ pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR;
+ pdata->interruptPHY = MPC83xx_IRQ_EXT2;
+ pdata->phyid = 1;
+ /* fixup phy address */
+ pdata->phy_reg_addr += binfo->bi_immr_base;
+ memcpy(pdata->mac_addr, binfo->bi_enet1addr, 6);
+
+#ifdef CONFIG_BLK_DEV_INITRD
+ if (initrd_start)
+ ROOT_DEV = Root_RAM0;
+ else
+#endif
+#ifdef CONFIG_ROOT_NFS
+ ROOT_DEV = Root_NFS;
+#else
+ ROOT_DEV = Root_HDA1;
+#endif
+}
+
+static void __init
+mpc834x_sys_map_io(void)
+{
+ /* we steal the lowest ioremap addr for virt space */
+ io_block_mapping(VIRT_IMMRBAR, immrbar, 1024*1024, _PAGE_IO);
+ io_block_mapping(BCSR_VIRT_ADDR, BCSR_PHYS_ADDR, BCSR_SIZE, _PAGE_IO);
+}
+
+int
+mpc834x_sys_show_cpuinfo(struct seq_file *m)
+{
+ uint pvid, svid, phid1;
+ bd_t *binfo = (bd_t *) __res;
+ unsigned int freq;
+
+ /* get the core frequency */
+ freq = binfo->bi_intfreq;
+
+ pvid = mfspr(SPRN_PVR);
+ svid = mfspr(SPRN_SVR);
+
+ seq_printf(m, "Vendor\t\t: Freescale Inc.\n");
+ seq_printf(m, "Machine\t\t: mpc%s sys\n", cur_ppc_sys_spec->ppc_sys_name);
+ seq_printf(m, "core clock\t: %d MHz\n"
+ "bus clock\t: %d MHz\n",
+ (int)(binfo->bi_intfreq / 1000000),
+ (int)(binfo->bi_busfreq / 1000000));
+ seq_printf(m, "PVR\t\t: 0x%x\n", pvid);
+ seq_printf(m, "SVR\t\t: 0x%x\n", svid);
+
+ /* Display cpu Pll setting */
+ phid1 = mfspr(SPRN_HID1);
+ seq_printf(m, "PLL setting\t: 0x%x\n", ((phid1 >> 24) & 0x3f));
+
+ /* Display the amount of memory */
+ seq_printf(m, "Memory\t\t: %d MB\n", (int)(binfo->bi_memsize / (1024 * 1024)));
+
+ return 0;
+}
+
+
+void __init
+mpc834x_sys_init_IRQ(void)
+{
+ bd_t *binfo = (bd_t *) __res;
+
+ u8 senses[8] = {
+ 0, /* EXT 0 */
+ IRQ_SENSE_LEVEL, /* EXT 1 */
+ IRQ_SENSE_LEVEL, /* EXT 2 */
+ 0, /* EXT 3 */
+ 0, /* EXT 4 */
+ 0, /* EXT 5 */
+ 0, /* EXT 6 */
+ 0, /* EXT 7 */
+ };
+
+ ipic_init(binfo->bi_immr_base + 0x00700, 0, MPC83xx_IPIC_IRQ_OFFSET, senses, 8);
+
+ /* Initialize the default interrupt mapping priorities,
+ * in case the boot rom changed something on us.
+ */
+ ipic_set_default_priority();
+}
+
+static __inline__ void
+mpc834x_sys_set_bat(void)
+{
+ /* we steal the lowest ioremap addr for virt space */
+ mb();
+ mtspr(SPRN_DBAT1U, VIRT_IMMRBAR | 0x1e);
+ mtspr(SPRN_DBAT1L, immrbar | 0x2a);
+ mb();
+}
+
+void __init
+platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
+ unsigned long r6, unsigned long r7)
+{
+ bd_t *binfo = (bd_t *) __res;
+
+ /* parse_bootinfo must always be called first */
+ parse_bootinfo(find_bootinfo());
+
+ /*
+ * If we were passed in a board information, copy it into the
+ * residual data area.
+ */
+ if (r3) {
+ memcpy((void *) __res, (void *) (r3 + KERNELBASE),
+ sizeof (bd_t));
+ }
+
+#if defined(CONFIG_BLK_DEV_INITRD)
+ /*
+ * If the init RAM disk has been configured in, and there's a valid
+ * starting address for it, set it up.
+ */
+ if (r4) {
+ initrd_start = r4 + KERNELBASE;
+ initrd_end = r5 + KERNELBASE;
+ }
+#endif /* CONFIG_BLK_DEV_INITRD */
+
+ /* Copy the kernel command line arguments to a safe place. */
+ if (r6) {
+ *(char *) (r7 + KERNELBASE) = 0;
+ strcpy(cmd_line, (char *) (r6 + KERNELBASE));
+ }
+
+ immrbar = binfo->bi_immr_base;
+
+ mpc834x_sys_set_bat();
+
+#if defined(CONFIG_SERIAL_8250) && defined(CONFIG_SERIAL_TEXT_DEBUG)
+ {
+ struct uart_port p;
+
+ memset(&p, 0, sizeof (p));
+ p.iotype = SERIAL_IO_MEM;
+ p.membase = (unsigned char __iomem *)(VIRT_IMMRBAR + 0x4500);
+ p.uartclk = binfo->bi_busfreq;
+
+ gen550_init(0, &p);
+
+ memset(&p, 0, sizeof (p));
+ p.iotype = SERIAL_IO_MEM;
+ p.membase = (unsigned char __iomem *)(VIRT_IMMRBAR + 0x4600);
+ p.uartclk = binfo->bi_busfreq;
+
+ gen550_init(1, &p);
+ }
+#endif
+
+ identify_ppc_sys_by_id(mfspr(SPRN_SVR));
+
+ /* setup the PowerPC module struct */
+ ppc_md.setup_arch = mpc834x_sys_setup_arch;
+ ppc_md.show_cpuinfo = mpc834x_sys_show_cpuinfo;
+
+ ppc_md.init_IRQ = mpc834x_sys_init_IRQ;
+ ppc_md.get_irq = ipic_get_irq;
+
+ ppc_md.restart = mpc83xx_restart;
+ ppc_md.power_off = mpc83xx_power_off;
+ ppc_md.halt = mpc83xx_halt;
+
+ ppc_md.find_end_of_memory = mpc83xx_find_end_of_memory;
+ ppc_md.setup_io_mappings = mpc834x_sys_map_io;
+
+ ppc_md.time_init = mpc83xx_time_init;
+ ppc_md.set_rtc_time = NULL;
+ ppc_md.get_rtc_time = NULL;
+ ppc_md.calibrate_decr = mpc83xx_calibrate_decr;
+
+ ppc_md.early_serial_map = mpc83xx_early_serial_map;
+#if defined(CONFIG_SERIAL_8250) && defined(CONFIG_SERIAL_TEXT_DEBUG)
+ ppc_md.progress = gen550_progress;
+#endif /* CONFIG_SERIAL_8250 && CONFIG_SERIAL_TEXT_DEBUG */
+
+ if (ppc_md.progress)
+ ppc_md.progress("mpc834x_sys_init(): exit", 0);
+
+ return;
+}
diff --git a/arch/ppc/platforms/83xx/mpc834x_sys.h b/arch/ppc/platforms/83xx/mpc834x_sys.h
new file mode 100644
index 0000000..f4d055a
--- /dev/null
+++ b/arch/ppc/platforms/83xx/mpc834x_sys.h
@@ -0,0 +1,51 @@
+/*
+ * arch/ppc/platforms/83xx/mpc834x_sys.h
+ *
+ * MPC834X SYS common board definitions
+ *
+ * Maintainer: Kumar Gala <kumar.gala@freescale.com>
+ *
+ * Copyright 2005 Freescale Semiconductor, Inc.
+ *
+ * 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.
+ *
+ */
+
+#ifndef __MACH_MPC83XX_SYS_H__
+#define __MACH_MPC83XX_SYS_H__
+
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/seq_file.h>
+#include <syslib/ppc83xx_setup.h>
+#include <asm/ppcboot.h>
+
+#define VIRT_IMMRBAR ((uint)0xfe000000)
+
+#define BCSR_PHYS_ADDR ((uint)0xf8000000)
+#define BCSR_VIRT_ADDR ((uint)0xfe100000)
+#define BCSR_SIZE ((uint)(32 * 1024))
+
+#ifdef CONFIG_PCI
+/* PCI interrupt controller */
+#define PIRQA MPC83xx_IRQ_IRQ4
+#define PIRQB MPC83xx_IRQ_IRQ5
+#define PIRQC MPC83xx_IRQ_IRQ6
+#define PIRQD MPC83xx_IRQ_IRQ7
+
+#define MPC834x_SYS_PCI1_LOWER_IO 0x00000000
+#define MPC834x_SYS_PCI1_UPPER_IO 0x00ffffff
+
+#define MPC834x_SYS_PCI1_LOWER_MEM 0x80000000
+#define MPC834x_SYS_PCI1_UPPER_MEM 0x9fffffff
+
+#define MPC834x_SYS_PCI1_IO_BASE 0xe2000000
+#define MPC834x_SYS_PCI1_MEM_OFFSET 0x00000000
+
+#define MPC834x_SYS_PCI1_IO_SIZE 0x01000000
+#endif /* CONFIG_PCI */
+
+#endif /* __MACH_MPC83XX_SYS_H__ */
diff --git a/arch/ppc/platforms/85xx/Kconfig b/arch/ppc/platforms/85xx/Kconfig
new file mode 100644
index 0000000..ff92e38
--- /dev/null
+++ b/arch/ppc/platforms/85xx/Kconfig
@@ -0,0 +1,76 @@
+config 85xx
+ bool
+ depends on E500
+ default y
+
+config PPC_INDIRECT_PCI_BE
+ bool
+ depends on 85xx
+ default y
+
+menu "Freescale 85xx options"
+ depends on E500
+
+choice
+ prompt "Machine Type"
+ depends on 85xx
+ default MPC8540_ADS
+
+config MPC8540_ADS
+ bool "Freescale MPC8540 ADS"
+ help
+ This option enables support for the MPC 8540 ADS evaluation board.
+
+config MPC8555_CDS
+ bool "Freescale MPC8555 CDS"
+ help
+ This option enablese support for the MPC8555 CDS evaluation board.
+
+config MPC8560_ADS
+ bool "Freescale MPC8560 ADS"
+ help
+ This option enables support for the MPC 8560 ADS evaluation board.
+
+config SBC8560
+ bool "WindRiver PowerQUICC III SBC8560"
+ help
+ This option enables support for the WindRiver PowerQUICC III
+ SBC8560 board.
+
+config STX_GP3
+ bool "Silicon Turnkey Express GP3"
+ help
+ This option enables support for the Silicon Turnkey Express GP3
+ board.
+
+endchoice
+
+# It's often necessary to know the specific 85xx processor type.
+# Fortunately, it is implied (so far) from the board type, so we
+# don't need to ask more redundant questions.
+config MPC8540
+ bool
+ depends on MPC8540_ADS
+ default y
+
+config MPC8555
+ bool
+ depends on MPC8555_CDS
+ default y
+
+config MPC8560
+ bool
+ depends on SBC8560 || MPC8560_ADS || STX_GP3
+ default y
+
+config 85xx_PCI2
+ bool "Supprt for 2nd PCI host controller"
+ depends on MPC8555_CDS
+ default y
+
+config PPC_GEN550
+ bool
+ depends on MPC8540 || SBC8560 || MPC8555
+ default y
+
+endmenu
diff --git a/arch/ppc/platforms/85xx/Makefile b/arch/ppc/platforms/85xx/Makefile
new file mode 100644
index 0000000..854fbd2
--- /dev/null
+++ b/arch/ppc/platforms/85xx/Makefile
@@ -0,0 +1,8 @@
+#
+# Makefile for the PowerPC 85xx linux kernel.
+#
+obj-$(CONFIG_MPC8540_ADS) += mpc85xx_ads_common.o mpc8540_ads.o
+obj-$(CONFIG_MPC8555_CDS) += mpc85xx_cds_common.o
+obj-$(CONFIG_MPC8560_ADS) += mpc85xx_ads_common.o mpc8560_ads.o
+obj-$(CONFIG_SBC8560) += sbc85xx.o sbc8560.o
+obj-$(CONFIG_STX_GP3) += stx_gp3.o
diff --git a/arch/ppc/platforms/85xx/mpc8540_ads.c b/arch/ppc/platforms/85xx/mpc8540_ads.c
new file mode 100644
index 0000000..4d857d6
--- /dev/null
+++ b/arch/ppc/platforms/85xx/mpc8540_ads.c
@@ -0,0 +1,218 @@
+/*
+ * arch/ppc/platforms/85xx/mpc8540_ads.c
+ *
+ * MPC8540ADS board specific routines
+ *
+ * Maintainer: Kumar Gala <kumar.gala@freescale.com>
+ *
+ * Copyright 2004 Freescale Semiconductor Inc.
+ *
+ * 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.
+ */
+
+#include <linux/config.h>
+#include <linux/stddef.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/reboot.h>
+#include <linux/pci.h>
+#include <linux/kdev_t.h>
+#include <linux/major.h>
+#include <linux/console.h>
+#include <linux/delay.h>
+#include <linux/irq.h>
+#include <linux/seq_file.h>
+#include <linux/root_dev.h>
+#include <linux/serial.h>
+#include <linux/tty.h> /* for linux/serial_core.h */
+#include <linux/serial_core.h>
+#include <linux/initrd.h>
+#include <linux/module.h>
+#include <linux/fsl_devices.h>
+
+#include <asm/system.h>
+#include <asm/pgtable.h>
+#include <asm/page.h>
+#include <asm/atomic.h>
+#include <asm/time.h>
+#include <asm/io.h>
+#include <asm/machdep.h>
+#include <asm/prom.h>
+#include <asm/open_pic.h>
+#include <asm/bootinfo.h>
+#include <asm/pci-bridge.h>
+#include <asm/mpc85xx.h>
+#include <asm/irq.h>
+#include <asm/immap_85xx.h>
+#include <asm/kgdb.h>
+#include <asm/ppc_sys.h>
+#include <mm/mmu_decl.h>
+
+#include <syslib/ppc85xx_setup.h>
+
+/* ************************************************************************
+ *
+ * Setup the architecture
+ *
+ */
+static void __init
+mpc8540ads_setup_arch(void)
+{
+ bd_t *binfo = (bd_t *) __res;
+ unsigned int freq;
+ struct gianfar_platform_data *pdata;
+
+ /* get the core frequency */
+ freq = binfo->bi_intfreq;
+
+ if (ppc_md.progress)
+ ppc_md.progress("mpc8540ads_setup_arch()", 0);
+
+ /* Set loops_per_jiffy to a half-way reasonable value,
+ for use until calibrate_delay gets called. */
+ loops_per_jiffy = freq / HZ;
+
+#ifdef CONFIG_PCI
+ /* setup PCI host bridges */
+ mpc85xx_setup_hose();
+#endif
+
+#ifdef CONFIG_SERIAL_8250
+ mpc85xx_early_serial_map();
+#endif
+
+#ifdef CONFIG_SERIAL_TEXT_DEBUG
+ /* Invalidate the entry we stole earlier the serial ports
+ * should be properly mapped */
+ invalidate_tlbcam_entry(NUM_TLBCAMS - 1);
+#endif
+
+ /* setup the board related information for the enet controllers */
+ pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_TSEC1);
+ pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR;
+ pdata->interruptPHY = MPC85xx_IRQ_EXT5;
+ pdata->phyid = 0;
+ /* fixup phy address */
+ pdata->phy_reg_addr += binfo->bi_immr_base;
+ memcpy(pdata->mac_addr, binfo->bi_enetaddr, 6);
+
+ pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_TSEC2);
+ pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR;
+ pdata->interruptPHY = MPC85xx_IRQ_EXT5;
+ pdata->phyid = 1;
+ /* fixup phy address */
+ pdata->phy_reg_addr += binfo->bi_immr_base;
+ memcpy(pdata->mac_addr, binfo->bi_enet1addr, 6);
+
+ pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_FEC);
+ pdata->board_flags = 0;
+ pdata->interruptPHY = MPC85xx_IRQ_EXT5;
+ pdata->phyid = 3;
+ /* fixup phy address */
+ pdata->phy_reg_addr += binfo->bi_immr_base;
+ memcpy(pdata->mac_addr, binfo->bi_enet2addr, 6);
+
+#ifdef CONFIG_BLK_DEV_INITRD
+ if (initrd_start)
+ ROOT_DEV = Root_RAM0;
+ else
+#endif
+#ifdef CONFIG_ROOT_NFS
+ ROOT_DEV = Root_NFS;
+#else
+ ROOT_DEV = Root_HDA1;
+#endif
+}
+
+/* ************************************************************************ */
+void __init
+platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
+ unsigned long r6, unsigned long r7)
+{
+ /* parse_bootinfo must always be called first */
+ parse_bootinfo(find_bootinfo());
+
+ /*
+ * If we were passed in a board information, copy it into the
+ * residual data area.
+ */
+ if (r3) {
+ memcpy((void *) __res, (void *) (r3 + KERNELBASE),
+ sizeof (bd_t));
+ }
+#ifdef CONFIG_SERIAL_TEXT_DEBUG
+ {
+ bd_t *binfo = (bd_t *) __res;
+ struct uart_port p;
+
+ /* Use the last TLB entry to map CCSRBAR to allow access to DUART regs */
+ settlbcam(NUM_TLBCAMS - 1, binfo->bi_immr_base,
+ binfo->bi_immr_base, MPC85xx_CCSRBAR_SIZE, _PAGE_IO, 0);
+
+ memset(&p, 0, sizeof (p));
+ p.iotype = SERIAL_IO_MEM;
+ p.membase = (void *) binfo->bi_immr_base + MPC85xx_UART0_OFFSET;
+ p.uartclk = binfo->bi_busfreq;
+
+ gen550_init(0, &p);
+
+ memset(&p, 0, sizeof (p));
+ p.iotype = SERIAL_IO_MEM;
+ p.membase = (void *) binfo->bi_immr_base + MPC85xx_UART1_OFFSET;
+ p.uartclk = binfo->bi_busfreq;
+
+ gen550_init(1, &p);
+ }
+#endif
+
+#if defined(CONFIG_BLK_DEV_INITRD)
+ /*
+ * If the init RAM disk has been configured in, and there's a valid
+ * starting address for it, set it up.
+ */
+ if (r4) {
+ initrd_start = r4 + KERNELBASE;
+ initrd_end = r5 + KERNELBASE;
+ }
+#endif /* CONFIG_BLK_DEV_INITRD */
+
+ /* Copy the kernel command line arguments to a safe place. */
+
+ if (r6) {
+ *(char *) (r7 + KERNELBASE) = 0;
+ strcpy(cmd_line, (char *) (r6 + KERNELBASE));
+ }
+
+ identify_ppc_sys_by_id(mfspr(SPRN_SVR));
+
+ /* setup the PowerPC module struct */
+ ppc_md.setup_arch = mpc8540ads_setup_arch;
+ ppc_md.show_cpuinfo = mpc85xx_ads_show_cpuinfo;
+
+ ppc_md.init_IRQ = mpc85xx_ads_init_IRQ;
+ ppc_md.get_irq = openpic_get_irq;
+
+ ppc_md.restart = mpc85xx_restart;
+ ppc_md.power_off = mpc85xx_power_off;
+ ppc_md.halt = mpc85xx_halt;
+
+ ppc_md.find_end_of_memory = mpc85xx_find_end_of_memory;
+
+ ppc_md.time_init = NULL;
+ ppc_md.set_rtc_time = NULL;
+ ppc_md.get_rtc_time = NULL;
+ ppc_md.calibrate_decr = mpc85xx_calibrate_decr;
+
+#if defined(CONFIG_SERIAL_8250) && defined(CONFIG_SERIAL_TEXT_DEBUG)
+ ppc_md.progress = gen550_progress;
+#endif /* CONFIG_SERIAL_8250 && CONFIG_SERIAL_TEXT_DEBUG */
+
+ if (ppc_md.progress)
+ ppc_md.progress("mpc8540ads_init(): exit", 0);
+
+ return;
+}
diff --git a/arch/ppc/platforms/85xx/mpc8540_ads.h b/arch/ppc/platforms/85xx/mpc8540_ads.h
new file mode 100644
index 0000000..3d05d7c
--- /dev/null
+++ b/arch/ppc/platforms/85xx/mpc8540_ads.h
@@ -0,0 +1,25 @@
+/*
+ * arch/ppc/platforms/85xx/mpc8540_ads.h
+ *
+ * MPC8540ADS board definitions
+ *
+ * Maintainer: Kumar Gala <kumar.gala@freescale.com>
+ *
+ * Copyright 2004 Freescale Semiconductor Inc.
+ *
+ * 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.
+ *
+ */
+
+#ifndef __MACH_MPC8540ADS_H__
+#define __MACH_MPC8540ADS_H__
+
+#include <linux/config.h>
+#include <linux/initrd.h>
+#include <syslib/ppc85xx_setup.h>
+#include <platforms/85xx/mpc85xx_ads_common.h>
+
+#endif /* __MACH_MPC8540ADS_H__ */
diff --git a/arch/ppc/platforms/85xx/mpc8555_cds.h b/arch/ppc/platforms/85xx/mpc8555_cds.h
new file mode 100644
index 0000000..e0e7556
--- /dev/null
+++ b/arch/ppc/platforms/85xx/mpc8555_cds.h
@@ -0,0 +1,26 @@
+/*
+ * arch/ppc/platforms/mpc8555_cds.h
+ *
+ * MPC8555CDS board definitions
+ *
+ * Maintainer: Kumar Gala <kumar.gala@freescale.com>
+ *
+ * Copyright 2004 Freescale Semiconductor Inc.
+ *
+ * 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.
+ *
+ */
+
+#ifndef __MACH_MPC8555CDS_H__
+#define __MACH_MPC8555CDS_H__
+
+#include <linux/config.h>
+#include <syslib/ppc85xx_setup.h>
+#include <platforms/85xx/mpc85xx_cds_common.h>
+
+#define CPM_MAP_ADDR (CCSRBAR + MPC85xx_CPM_OFFSET)
+
+#endif /* __MACH_MPC8555CDS_H__ */
diff --git a/arch/ppc/platforms/85xx/mpc8560_ads.c b/arch/ppc/platforms/85xx/mpc8560_ads.c
new file mode 100644
index 0000000..761b8c7
--- /dev/null
+++ b/arch/ppc/platforms/85xx/mpc8560_ads.c
@@ -0,0 +1,210 @@
+/*
+ * arch/ppc/platforms/85xx/mpc8560_ads.c
+ *
+ * MPC8560ADS board specific routines
+ *
+ * Maintainer: Kumar Gala <kumar.gala@freescale.com>
+ *
+ * Copyright 2004 Freescale Semiconductor Inc.
+ *
+ * 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.
+ */
+
+#include <linux/config.h>
+#include <linux/stddef.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/reboot.h>
+#include <linux/pci.h>
+#include <linux/kdev_t.h>
+#include <linux/major.h>
+#include <linux/console.h>
+#include <linux/delay.h>
+#include <linux/irq.h>
+#include <linux/seq_file.h>
+#include <linux/root_dev.h>
+#include <linux/serial.h>
+#include <linux/tty.h> /* for linux/serial_core.h */
+#include <linux/serial_core.h>
+#include <linux/initrd.h>
+#include <linux/module.h>
+#include <linux/fsl_devices.h>
+
+#include <asm/system.h>
+#include <asm/pgtable.h>
+#include <asm/page.h>
+#include <asm/atomic.h>
+#include <asm/time.h>
+#include <asm/io.h>
+#include <asm/machdep.h>
+#include <asm/prom.h>
+#include <asm/open_pic.h>
+#include <asm/bootinfo.h>
+#include <asm/pci-bridge.h>
+#include <asm/mpc85xx.h>
+#include <asm/irq.h>
+#include <asm/immap_85xx.h>
+#include <asm/kgdb.h>
+#include <asm/ppc_sys.h>
+#include <asm/cpm2.h>
+#include <mm/mmu_decl.h>
+
+#include <syslib/cpm2_pic.h>
+#include <syslib/ppc85xx_common.h>
+#include <syslib/ppc85xx_setup.h>
+
+extern void cpm2_reset(void);
+
+/* ************************************************************************
+ *
+ * Setup the architecture
+ *
+ */
+
+static void __init
+mpc8560ads_setup_arch(void)
+{
+ bd_t *binfo = (bd_t *) __res;
+ unsigned int freq;
+ struct gianfar_platform_data *pdata;
+
+ cpm2_reset();
+
+ /* get the core frequency */
+ freq = binfo->bi_intfreq;
+
+ if (ppc_md.progress)
+ ppc_md.progress("mpc8560ads_setup_arch()", 0);
+
+ /* Set loops_per_jiffy to a half-way reasonable value,
+ for use until calibrate_delay gets called. */
+ loops_per_jiffy = freq / HZ;
+
+#ifdef CONFIG_PCI
+ /* setup PCI host bridges */
+ mpc85xx_setup_hose();
+#endif
+
+ /* setup the board related information for the enet controllers */
+ pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_TSEC1);
+ pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR;
+ pdata->interruptPHY = MPC85xx_IRQ_EXT5;
+ pdata->phyid = 0;
+ /* fixup phy address */
+ pdata->phy_reg_addr += binfo->bi_immr_base;
+ memcpy(pdata->mac_addr, binfo->bi_enetaddr, 6);
+
+ pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_TSEC2);
+ pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR;
+ pdata->interruptPHY = MPC85xx_IRQ_EXT5;
+ pdata->phyid = 1;
+ /* fixup phy address */
+ pdata->phy_reg_addr += binfo->bi_immr_base;
+ memcpy(pdata->mac_addr, binfo->bi_enet1addr, 6);
+
+#ifdef CONFIG_BLK_DEV_INITRD
+ if (initrd_start)
+ ROOT_DEV = Root_RAM0;
+ else
+#endif
+#ifdef CONFIG_ROOT_NFS
+ ROOT_DEV = Root_NFS;
+#else
+ ROOT_DEV = Root_HDA1;
+#endif
+}
+
+static irqreturn_t cpm2_cascade(int irq, void *dev_id, struct pt_regs *regs)
+{
+ while ((irq = cpm2_get_irq(regs)) >= 0)
+ __do_IRQ(irq, regs);
+ return IRQ_HANDLED;
+}
+
+static struct irqaction cpm2_irqaction = {
+ .handler = cpm2_cascade,
+ .flags = SA_INTERRUPT,
+ .mask = CPU_MASK_NONE,
+ .name = "cpm2_cascade",
+};
+
+static void __init
+mpc8560_ads_init_IRQ(void)
+{
+ /* Setup OpenPIC */
+ mpc85xx_ads_init_IRQ();
+
+ /* Setup CPM2 PIC */
+ cpm2_init_IRQ();
+
+ setup_irq(MPC85xx_IRQ_CPM, &cpm2_irqaction);
+
+ return;
+}
+
+
+
+/* ************************************************************************ */
+void __init
+platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
+ unsigned long r6, unsigned long r7)
+{
+ /* parse_bootinfo must always be called first */
+ parse_bootinfo(find_bootinfo());
+
+ /*
+ * If we were passed in a board information, copy it into the
+ * residual data area.
+ */
+ if (r3) {
+ memcpy((void *) __res, (void *) (r3 + KERNELBASE),
+ sizeof (bd_t));
+
+ }
+#if defined(CONFIG_BLK_DEV_INITRD)
+ /*
+ * If the init RAM disk has been configured in, and there's a valid
+ * starting address for it, set it up.
+ */
+ if (r4) {
+ initrd_start = r4 + KERNELBASE;
+ initrd_end = r5 + KERNELBASE;
+ }
+#endif /* CONFIG_BLK_DEV_INITRD */
+
+ /* Copy the kernel command line arguments to a safe place. */
+
+ if (r6) {
+ *(char *) (r7 + KERNELBASE) = 0;
+ strcpy(cmd_line, (char *) (r6 + KERNELBASE));
+ }
+
+ identify_ppc_sys_by_id(mfspr(SPRN_SVR));
+
+ /* setup the PowerPC module struct */
+ ppc_md.setup_arch = mpc8560ads_setup_arch;
+ ppc_md.show_cpuinfo = mpc85xx_ads_show_cpuinfo;
+
+ ppc_md.init_IRQ = mpc8560_ads_init_IRQ;
+ ppc_md.get_irq = openpic_get_irq;
+
+ ppc_md.restart = mpc85xx_restart;
+ ppc_md.power_off = mpc85xx_power_off;
+ ppc_md.halt = mpc85xx_halt;
+
+ ppc_md.find_end_of_memory = mpc85xx_find_end_of_memory;
+
+ ppc_md.time_init = NULL;
+ ppc_md.set_rtc_time = NULL;
+ ppc_md.get_rtc_time = NULL;
+ ppc_md.calibrate_decr = mpc85xx_calibrate_decr;
+
+ if (ppc_md.progress)
+ ppc_md.progress("mpc8560ads_init(): exit", 0);
+
+ return;
+}
diff --git a/arch/ppc/platforms/85xx/mpc8560_ads.h b/arch/ppc/platforms/85xx/mpc8560_ads.h
new file mode 100644
index 0000000..7df885d
--- /dev/null
+++ b/arch/ppc/platforms/85xx/mpc8560_ads.h
@@ -0,0 +1,27 @@
+/*
+ * arch/ppc/platforms/mpc8560_ads.h
+ *
+ * MPC8540ADS board definitions
+ *
+ * Maintainer: Kumar Gala <kumar.gala@freescale.com>
+ *
+ * Copyright 2004 Freescale Semiconductor Inc.
+ *
+ * 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.
+ *
+ */
+
+#ifndef __MACH_MPC8560ADS_H
+#define __MACH_MPC8560ADS_H
+
+#include <linux/config.h>
+#include <syslib/ppc85xx_setup.h>
+#include <platforms/85xx/mpc85xx_ads_common.h>
+
+#define CPM_MAP_ADDR (CCSRBAR + MPC85xx_CPM_OFFSET)
+#define PHY_INTERRUPT MPC85xx_IRQ_EXT7
+
+#endif /* __MACH_MPC8560ADS_H */
diff --git a/arch/ppc/platforms/85xx/mpc85xx_ads_common.c b/arch/ppc/platforms/85xx/mpc85xx_ads_common.c
new file mode 100644
index 0000000..ba9f9f5
--- /dev/null
+++ b/arch/ppc/platforms/85xx/mpc85xx_ads_common.c
@@ -0,0 +1,225 @@
+/*
+ * arch/ppc/platforms/85xx/mpc85xx_ads_common.c
+ *
+ * MPC85xx ADS board common routines
+ *
+ * Maintainer: Kumar Gala <kumar.gala@freescale.com>
+ *
+ * Copyright 2004 Freescale Semiconductor Inc.
+ *
+ * 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.
+ */
+
+#include <linux/config.h>
+#include <linux/stddef.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/reboot.h>
+#include <linux/pci.h>
+#include <linux/kdev_t.h>
+#include <linux/major.h>
+#include <linux/console.h>
+#include <linux/delay.h>
+#include <linux/irq.h>
+#include <linux/seq_file.h>
+#include <linux/serial.h>
+#include <linux/module.h>
+
+#include <asm/system.h>
+#include <asm/pgtable.h>
+#include <asm/page.h>
+#include <asm/atomic.h>
+#include <asm/time.h>
+#include <asm/io.h>
+#include <asm/machdep.h>
+#include <asm/prom.h>
+#include <asm/open_pic.h>
+#include <asm/bootinfo.h>
+#include <asm/pci-bridge.h>
+#include <asm/mpc85xx.h>
+#include <asm/irq.h>
+#include <asm/immap_85xx.h>
+#include <asm/ppc_sys.h>
+
+#include <mm/mmu_decl.h>
+
+#include <platforms/85xx/mpc85xx_ads_common.h>
+
+#ifndef CONFIG_PCI
+unsigned long isa_io_base = 0;
+unsigned long isa_mem_base = 0;
+#endif
+
+extern unsigned long total_memory; /* in mm/init */
+
+unsigned char __res[sizeof (bd_t)];
+
+/* Internal interrupts are all Level Sensitive, and Positive Polarity */
+
+static u_char mpc85xx_ads_openpic_initsenses[] __initdata = {
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 0: L2 Cache */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 1: ECM */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 2: DDR DRAM */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 3: LBIU */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 4: DMA 0 */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 5: DMA 1 */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 6: DMA 2 */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 7: DMA 3 */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 8: PCI/PCI-X */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 9: RIO Inbound Port Write Error */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 10: RIO Doorbell Inbound */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 11: RIO Outbound Message */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 12: RIO Inbound Message */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 13: TSEC 0 Transmit */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 14: TSEC 0 Receive */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 15: Unused */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 16: Unused */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 17: Unused */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 18: TSEC 0 Receive/Transmit Error */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 19: TSEC 1 Transmit */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 20: TSEC 1 Receive */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 21: Unused */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 22: Unused */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 23: Unused */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 24: TSEC 1 Receive/Transmit Error */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 25: Fast Ethernet */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 26: DUART */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 27: I2C */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 28: Performance Monitor */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 29: Unused */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 30: CPM */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 31: Unused */
+ 0x0, /* External 0: */
+#if defined(CONFIG_PCI)
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* External 1: PCI slot 0 */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* External 2: PCI slot 1 */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* External 3: PCI slot 2 */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* External 4: PCI slot 3 */
+#else
+ 0x0, /* External 1: */
+ 0x0, /* External 2: */
+ 0x0, /* External 3: */
+ 0x0, /* External 4: */
+#endif
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* External 5: PHY */
+ 0x0, /* External 6: */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* External 7: PHY */
+ 0x0, /* External 8: */
+ 0x0, /* External 9: */
+ 0x0, /* External 10: */
+ 0x0, /* External 11: */
+};
+
+/* ************************************************************************ */
+int
+mpc85xx_ads_show_cpuinfo(struct seq_file *m)
+{
+ uint pvid, svid, phid1;
+ uint memsize = total_memory;
+ bd_t *binfo = (bd_t *) __res;
+ unsigned int freq;
+
+ /* get the core frequency */
+ freq = binfo->bi_intfreq;
+
+ pvid = mfspr(SPRN_PVR);
+ svid = mfspr(SPRN_SVR);
+
+ seq_printf(m, "Vendor\t\t: Freescale Semiconductor\n");
+ seq_printf(m, "Machine\t\t: mpc%sads\n", cur_ppc_sys_spec->ppc_sys_name);
+ seq_printf(m, "clock\t\t: %dMHz\n", freq / 1000000);
+ seq_printf(m, "PVR\t\t: 0x%x\n", pvid);
+ seq_printf(m, "SVR\t\t: 0x%x\n", svid);
+
+ /* Display cpu Pll setting */
+ phid1 = mfspr(SPRN_HID1);
+ seq_printf(m, "PLL setting\t: 0x%x\n", ((phid1 >> 24) & 0x3f));
+
+ /* Display the amount of memory */
+ seq_printf(m, "Memory\t\t: %d MB\n", memsize / (1024 * 1024));
+
+ return 0;
+}
+
+void __init
+mpc85xx_ads_init_IRQ(void)
+{
+ bd_t *binfo = (bd_t *) __res;
+ /* Determine the Physical Address of the OpenPIC regs */
+ phys_addr_t OpenPIC_PAddr =
+ binfo->bi_immr_base + MPC85xx_OPENPIC_OFFSET;
+ OpenPIC_Addr = ioremap(OpenPIC_PAddr, MPC85xx_OPENPIC_SIZE);
+ OpenPIC_InitSenses = mpc85xx_ads_openpic_initsenses;
+ OpenPIC_NumInitSenses = sizeof (mpc85xx_ads_openpic_initsenses);
+
+ /* Skip reserved space and internal sources */
+ openpic_set_sources(0, 32, OpenPIC_Addr + 0x10200);
+ /* Map PIC IRQs 0-11 */
+ openpic_set_sources(32, 12, OpenPIC_Addr + 0x10000);
+
+ /* we let openpic interrupts starting from an offset, to
+ * leave space for cascading interrupts underneath.
+ */
+ openpic_init(MPC85xx_OPENPIC_IRQ_OFFSET);
+
+ return;
+}
+
+#ifdef CONFIG_PCI
+/*
+ * interrupt routing
+ */
+
+int
+mpc85xx_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin)
+{
+ static char pci_irq_table[][4] =
+ /*
+ * This is little evil, but works around the fact
+ * that revA boards have IDSEL starting at 18
+ * and others boards (older) start at 12
+ *
+ * PCI IDSEL/INTPIN->INTLINE
+ * A B C D
+ */
+ {
+ {PIRQA, PIRQB, PIRQC, PIRQD}, /* IDSEL 2 */
+ {PIRQD, PIRQA, PIRQB, PIRQC},
+ {PIRQC, PIRQD, PIRQA, PIRQB},
+ {PIRQB, PIRQC, PIRQD, PIRQA}, /* IDSEL 5 */
+ {0, 0, 0, 0}, /* -- */
+ {0, 0, 0, 0}, /* -- */
+ {0, 0, 0, 0}, /* -- */
+ {0, 0, 0, 0}, /* -- */
+ {0, 0, 0, 0}, /* -- */
+ {0, 0, 0, 0}, /* -- */
+ {PIRQA, PIRQB, PIRQC, PIRQD}, /* IDSEL 12 */
+ {PIRQD, PIRQA, PIRQB, PIRQC},
+ {PIRQC, PIRQD, PIRQA, PIRQB},
+ {PIRQB, PIRQC, PIRQD, PIRQA}, /* IDSEL 15 */
+ {0, 0, 0, 0}, /* -- */
+ {0, 0, 0, 0}, /* -- */
+ {PIRQA, PIRQB, PIRQC, PIRQD}, /* IDSEL 18 */
+ {PIRQD, PIRQA, PIRQB, PIRQC},
+ {PIRQC, PIRQD, PIRQA, PIRQB},
+ {PIRQB, PIRQC, PIRQD, PIRQA}, /* IDSEL 21 */
+ };
+
+ const long min_idsel = 2, max_idsel = 21, irqs_per_slot = 4;
+ return PCI_IRQ_TABLE_LOOKUP;
+}
+
+int
+mpc85xx_exclude_device(u_char bus, u_char devfn)
+{
+ if (bus == 0 && PCI_SLOT(devfn) == 0)
+ return PCIBIOS_DEVICE_NOT_FOUND;
+ else
+ return PCIBIOS_SUCCESSFUL;
+}
+
+#endif /* CONFIG_PCI */
diff --git a/arch/ppc/platforms/85xx/mpc85xx_ads_common.h b/arch/ppc/platforms/85xx/mpc85xx_ads_common.h
new file mode 100644
index 0000000..3875e83
--- /dev/null
+++ b/arch/ppc/platforms/85xx/mpc85xx_ads_common.h
@@ -0,0 +1,50 @@
+/*
+ * arch/ppc/platforms/85xx/mpc85xx_ads_common.h
+ *
+ * MPC85XX ADS common board definitions
+ *
+ * Maintainer: Kumar Gala <kumar.gala@freescale.com>
+ *
+ * Copyright 2004 Freescale Semiconductor Inc.
+ *
+ * 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.
+ *
+ */
+
+#ifndef __MACH_MPC85XX_ADS_H__
+#define __MACH_MPC85XX_ADS_H__
+
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/seq_file.h>
+#include <asm/ppcboot.h>
+
+#define BOARD_CCSRBAR ((uint)0xe0000000)
+#define BCSR_ADDR ((uint)0xf8000000)
+#define BCSR_SIZE ((uint)(32 * 1024))
+
+extern int mpc85xx_ads_show_cpuinfo(struct seq_file *m);
+extern void mpc85xx_ads_init_IRQ(void) __init;
+extern void mpc85xx_ads_map_io(void) __init;
+
+/* PCI interrupt controller */
+#define PIRQA MPC85xx_IRQ_EXT1
+#define PIRQB MPC85xx_IRQ_EXT2
+#define PIRQC MPC85xx_IRQ_EXT3
+#define PIRQD MPC85xx_IRQ_EXT4
+
+#define MPC85XX_PCI1_LOWER_IO 0x00000000
+#define MPC85XX_PCI1_UPPER_IO 0x00ffffff
+
+#define MPC85XX_PCI1_LOWER_MEM 0x80000000
+#define MPC85XX_PCI1_UPPER_MEM 0x9fffffff
+
+#define MPC85XX_PCI1_IO_BASE 0xe2000000
+#define MPC85XX_PCI1_MEM_OFFSET 0x00000000
+
+#define MPC85XX_PCI1_IO_SIZE 0x01000000
+
+#endif /* __MACH_MPC85XX_ADS_H__ */
diff --git a/arch/ppc/platforms/85xx/mpc85xx_cds_common.c b/arch/ppc/platforms/85xx/mpc85xx_cds_common.c
new file mode 100644
index 0000000..6c020d6
--- /dev/null
+++ b/arch/ppc/platforms/85xx/mpc85xx_cds_common.c
@@ -0,0 +1,467 @@
+/*
+ * arch/ppc/platform/85xx/mpc85xx_cds_common.c
+ *
+ * MPC85xx CDS board specific routines
+ *
+ * Maintainer: Kumar Gala <kumar.gala@freescale.com>
+ *
+ * Copyright 2004 Freescale Semiconductor, Inc
+ *
+ * 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.
+ */
+
+#include <linux/config.h>
+#include <linux/stddef.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/reboot.h>
+#include <linux/pci.h>
+#include <linux/kdev_t.h>
+#include <linux/major.h>
+#include <linux/console.h>
+#include <linux/delay.h>
+#include <linux/irq.h>
+#include <linux/seq_file.h>
+#include <linux/serial.h>
+#include <linux/module.h>
+#include <linux/root_dev.h>
+#include <linux/initrd.h>
+#include <linux/tty.h>
+#include <linux/serial_core.h>
+#include <linux/fsl_devices.h>
+
+#include <asm/system.h>
+#include <asm/pgtable.h>
+#include <asm/page.h>
+#include <asm/atomic.h>
+#include <asm/time.h>
+#include <asm/todc.h>
+#include <asm/io.h>
+#include <asm/machdep.h>
+#include <asm/prom.h>
+#include <asm/open_pic.h>
+#include <asm/bootinfo.h>
+#include <asm/pci-bridge.h>
+#include <asm/mpc85xx.h>
+#include <asm/irq.h>
+#include <asm/immap_85xx.h>
+#include <asm/immap_cpm2.h>
+#include <asm/ppc_sys.h>
+#include <asm/kgdb.h>
+
+#include <mm/mmu_decl.h>
+#include <syslib/cpm2_pic.h>
+#include <syslib/ppc85xx_common.h>
+#include <syslib/ppc85xx_setup.h>
+
+
+#ifndef CONFIG_PCI
+unsigned long isa_io_base = 0;
+unsigned long isa_mem_base = 0;
+#endif
+
+extern unsigned long total_memory; /* in mm/init */
+
+unsigned char __res[sizeof (bd_t)];
+
+static int cds_pci_slot = 2;
+static volatile u8 * cadmus;
+
+/* Internal interrupts are all Level Sensitive, and Positive Polarity */
+
+static u_char mpc85xx_cds_openpic_initsenses[] __initdata = {
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 0: L2 Cache */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 1: ECM */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 2: DDR DRAM */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 3: LBIU */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 4: DMA 0 */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 5: DMA 1 */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 6: DMA 2 */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 7: DMA 3 */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 8: PCI/PCI-X */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 9: RIO Inbound Port Write Error */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 10: RIO Doorbell Inbound */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 11: RIO Outbound Message */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 12: RIO Inbound Message */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 13: TSEC 0 Transmit */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 14: TSEC 0 Receive */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 15: Unused */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 16: Unused */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 17: Unused */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 18: TSEC 0 Receive/Transmit Error */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 19: TSEC 1 Transmit */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 20: TSEC 1 Receive */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 21: Unused */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 22: Unused */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 23: Unused */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 24: TSEC 1 Receive/Transmit Error */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 25: Fast Ethernet */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 26: DUART */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 27: I2C */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 28: Performance Monitor */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 29: Unused */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 30: CPM */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 31: Unused */
+#if defined(CONFIG_PCI)
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* External 0: PCI1 slot */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* External 1: PCI1 slot */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* External 2: PCI1 slot */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* External 3: PCI1 slot */
+#else
+ 0x0, /* External 0: */
+ 0x0, /* External 1: */
+ 0x0, /* External 2: */
+ 0x0, /* External 3: */
+#endif
+ 0x0, /* External 4: */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* External 5: PHY */
+ 0x0, /* External 6: */
+ 0x0, /* External 7: */
+ 0x0, /* External 8: */
+ 0x0, /* External 9: */
+ 0x0, /* External 10: */
+#if defined(CONFIG_85xx_PCI2) && defined(CONFIG_PCI)
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* External 11: PCI2 slot 0 */
+#else
+ 0x0, /* External 11: */
+#endif
+};
+
+/* ************************************************************************ */
+int
+mpc85xx_cds_show_cpuinfo(struct seq_file *m)
+{
+ uint pvid, svid, phid1;
+ uint memsize = total_memory;
+ bd_t *binfo = (bd_t *) __res;
+ unsigned int freq;
+
+ /* get the core frequency */
+ freq = binfo->bi_intfreq;
+
+ pvid = mfspr(SPRN_PVR);
+ svid = mfspr(SPRN_SVR);
+
+ seq_printf(m, "Vendor\t\t: Freescale Semiconductor\n");
+ seq_printf(m, "Machine\t\t: CDS - MPC%s (%x)\n", cur_ppc_sys_spec->ppc_sys_name, cadmus[CM_VER]);
+ seq_printf(m, "clock\t\t: %dMHz\n", freq / 1000000);
+ seq_printf(m, "PVR\t\t: 0x%x\n", pvid);
+ seq_printf(m, "SVR\t\t: 0x%x\n", svid);
+
+ /* Display cpu Pll setting */
+ phid1 = mfspr(SPRN_HID1);
+ seq_printf(m, "PLL setting\t: 0x%x\n", ((phid1 >> 24) & 0x3f));
+
+ /* Display the amount of memory */
+ seq_printf(m, "Memory\t\t: %d MB\n", memsize / (1024 * 1024));
+
+ return 0;
+}
+
+#ifdef CONFIG_CPM2
+static void cpm2_cascade(int irq, void *dev_id, struct pt_regs *regs)
+{
+ while((irq = cpm2_get_irq(regs)) >= 0)
+ __do_IRQ(irq, regs);
+}
+
+static struct irqaction cpm2_irqaction = {
+ .handler = cpm2_cascade,
+ .flags = SA_INTERRUPT,
+ .mask = CPU_MASK_NONE,
+ .name = "cpm2_cascade",
+};
+#endif /* CONFIG_CPM2 */
+
+void __init
+mpc85xx_cds_init_IRQ(void)
+{
+ bd_t *binfo = (bd_t *) __res;
+
+ /* Determine the Physical Address of the OpenPIC regs */
+ phys_addr_t OpenPIC_PAddr = binfo->bi_immr_base + MPC85xx_OPENPIC_OFFSET;
+ OpenPIC_Addr = ioremap(OpenPIC_PAddr, MPC85xx_OPENPIC_SIZE);
+ OpenPIC_InitSenses = mpc85xx_cds_openpic_initsenses;
+ OpenPIC_NumInitSenses = sizeof (mpc85xx_cds_openpic_initsenses);
+
+ /* Skip reserved space and internal sources */
+ openpic_set_sources(0, 32, OpenPIC_Addr + 0x10200);
+ /* Map PIC IRQs 0-11 */
+ openpic_set_sources(32, 12, OpenPIC_Addr + 0x10000);
+
+ /* we let openpic interrupts starting from an offset, to
+ * leave space for cascading interrupts underneath.
+ */
+ openpic_init(MPC85xx_OPENPIC_IRQ_OFFSET);
+
+#ifdef CONFIG_CPM2
+ /* Setup CPM2 PIC */
+ cpm2_init_IRQ();
+
+ setup_irq(MPC85xx_IRQ_CPM, &cpm2_irqaction);
+#endif
+
+ return;
+}
+
+#ifdef CONFIG_PCI
+/*
+ * interrupt routing
+ */
+int
+mpc85xx_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin)
+{
+ struct pci_controller *hose = pci_bus_to_hose(dev->bus->number);
+
+ if (!hose->index)
+ {
+ /* Handle PCI1 interrupts */
+ char pci_irq_table[][4] =
+ /*
+ * PCI IDSEL/INTPIN->INTLINE
+ * A B C D
+ */
+
+ /* Note IRQ assignment for slots is based on which slot the elysium is
+ * in -- in this setup elysium is in slot #2 (this PIRQA as first
+ * interrupt on slot */
+ {
+ { 0, 1, 2, 3 }, /* 16 - PMC */
+ { 3, 0, 0, 0 }, /* 17 P2P (Tsi320) */
+ { 0, 1, 2, 3 }, /* 18 - Slot 1 */
+ { 1, 2, 3, 0 }, /* 19 - Slot 2 */
+ { 2, 3, 0, 1 }, /* 20 - Slot 3 */
+ { 3, 0, 1, 2 }, /* 21 - Slot 4 */
+ };
+
+ const long min_idsel = 16, max_idsel = 21, irqs_per_slot = 4;
+ int i, j;
+
+ for (i = 0; i < 6; i++)
+ for (j = 0; j < 4; j++)
+ pci_irq_table[i][j] =
+ ((pci_irq_table[i][j] + 5 -
+ cds_pci_slot) & 0x3) + PIRQ0A;
+
+ return PCI_IRQ_TABLE_LOOKUP;
+ } else {
+ /* Handle PCI2 interrupts (if we have one) */
+ char pci_irq_table[][4] =
+ {
+ /*
+ * We only have one slot and one interrupt
+ * going to PIRQA - PIRQD */
+ { PIRQ1A, PIRQ1A, PIRQ1A, PIRQ1A }, /* 21 - slot 0 */
+ };
+
+ const long min_idsel = 21, max_idsel = 21, irqs_per_slot = 4;
+
+ return PCI_IRQ_TABLE_LOOKUP;
+ }
+}
+
+#define ARCADIA_HOST_BRIDGE_IDSEL 17
+#define ARCADIA_2ND_BRIDGE_IDSEL 3
+
+extern int mpc85xx_pci1_last_busno;
+
+int
+mpc85xx_exclude_device(u_char bus, u_char devfn)
+{
+ if (bus == 0 && PCI_SLOT(devfn) == 0)
+ return PCIBIOS_DEVICE_NOT_FOUND;
+#ifdef CONFIG_85xx_PCI2
+ if (mpc85xx_pci1_last_busno)
+ if (bus == (mpc85xx_pci1_last_busno + 1) && PCI_SLOT(devfn) == 0)
+ return PCIBIOS_DEVICE_NOT_FOUND;
+#endif
+ /* We explicitly do not go past the Tundra 320 Bridge */
+ if (bus == 1)
+ return PCIBIOS_DEVICE_NOT_FOUND;
+ if ((bus == 0) && (PCI_SLOT(devfn) == ARCADIA_2ND_BRIDGE_IDSEL))
+ return PCIBIOS_DEVICE_NOT_FOUND;
+ else
+ return PCIBIOS_SUCCESSFUL;
+}
+#endif /* CONFIG_PCI */
+
+TODC_ALLOC();
+
+/* ************************************************************************
+ *
+ * Setup the architecture
+ *
+ */
+static void __init
+mpc85xx_cds_setup_arch(void)
+{
+ bd_t *binfo = (bd_t *) __res;
+ unsigned int freq;
+ struct gianfar_platform_data *pdata;
+
+ /* get the core frequency */
+ freq = binfo->bi_intfreq;
+
+ printk("mpc85xx_cds_setup_arch\n");
+
+#ifdef CONFIG_CPM2
+ cpm2_reset();
+#endif
+
+ cadmus = ioremap(CADMUS_BASE, CADMUS_SIZE);
+ cds_pci_slot = ((cadmus[CM_CSR] >> 6) & 0x3) + 1;
+ printk("CDS Version = %x in PCI slot %d\n", cadmus[CM_VER], cds_pci_slot);
+
+ /* Setup TODC access */
+ TODC_INIT(TODC_TYPE_DS1743,
+ 0,
+ 0,
+ ioremap(CDS_RTC_ADDR, CDS_RTC_SIZE),
+ 8);
+
+ /* Set loops_per_jiffy to a half-way reasonable value,
+ for use until calibrate_delay gets called. */
+ loops_per_jiffy = freq / HZ;
+
+#ifdef CONFIG_PCI
+ /* setup PCI host bridges */
+ mpc85xx_setup_hose();
+#endif
+
+#ifdef CONFIG_SERIAL_8250
+ mpc85xx_early_serial_map();
+#endif
+
+#ifdef CONFIG_SERIAL_TEXT_DEBUG
+ /* Invalidate the entry we stole earlier the serial ports
+ * should be properly mapped */
+ invalidate_tlbcam_entry(NUM_TLBCAMS - 1);
+#endif
+
+ /* setup the board related information for the enet controllers */
+ pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_TSEC1);
+ pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR;
+ pdata->interruptPHY = MPC85xx_IRQ_EXT5;
+ pdata->phyid = 0;
+ /* fixup phy address */
+ pdata->phy_reg_addr += binfo->bi_immr_base;
+ memcpy(pdata->mac_addr, binfo->bi_enetaddr, 6);
+
+ pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_TSEC2);
+ pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR;
+ pdata->interruptPHY = MPC85xx_IRQ_EXT5;
+ pdata->phyid = 1;
+ /* fixup phy address */
+ pdata->phy_reg_addr += binfo->bi_immr_base;
+ memcpy(pdata->mac_addr, binfo->bi_enet1addr, 6);
+
+
+#ifdef CONFIG_BLK_DEV_INITRD
+ if (initrd_start)
+ ROOT_DEV = Root_RAM0;
+ else
+#endif
+#ifdef CONFIG_ROOT_NFS
+ ROOT_DEV = Root_NFS;
+#else
+ ROOT_DEV = Root_HDA1;
+#endif
+}
+
+/* ************************************************************************ */
+void __init
+platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
+ unsigned long r6, unsigned long r7)
+{
+ /* parse_bootinfo must always be called first */
+ parse_bootinfo(find_bootinfo());
+
+ /*
+ * If we were passed in a board information, copy it into the
+ * residual data area.
+ */
+ if (r3) {
+ memcpy((void *) __res, (void *) (r3 + KERNELBASE),
+ sizeof (bd_t));
+
+ }
+#ifdef CONFIG_SERIAL_TEXT_DEBUG
+ {
+ bd_t *binfo = (bd_t *) __res;
+ struct uart_port p;
+
+ /* Use the last TLB entry to map CCSRBAR to allow access to DUART regs */
+ settlbcam(NUM_TLBCAMS - 1, binfo->bi_immr_base,
+ binfo->bi_immr_base, MPC85xx_CCSRBAR_SIZE, _PAGE_IO, 0);
+
+ memset(&p, 0, sizeof (p));
+ p.iotype = SERIAL_IO_MEM;
+ p.membase = (void *) binfo->bi_immr_base + MPC85xx_UART0_OFFSET;
+ p.uartclk = binfo->bi_busfreq;
+
+ gen550_init(0, &p);
+
+ memset(&p, 0, sizeof (p));
+ p.iotype = SERIAL_IO_MEM;
+ p.membase = (void *) binfo->bi_immr_base + MPC85xx_UART1_OFFSET;
+ p.uartclk = binfo->bi_busfreq;
+
+ gen550_init(1, &p);
+ }
+#endif
+
+#if defined(CONFIG_BLK_DEV_INITRD)
+ /*
+ * If the init RAM disk has been configured in, and there's a valid
+ * starting address for it, set it up.
+ */
+ if (r4) {
+ initrd_start = r4 + KERNELBASE;
+ initrd_end = r5 + KERNELBASE;
+ }
+#endif /* CONFIG_BLK_DEV_INITRD */
+
+ /* Copy the kernel command line arguments to a safe place. */
+
+ if (r6) {
+ *(char *) (r7 + KERNELBASE) = 0;
+ strcpy(cmd_line, (char *) (r6 + KERNELBASE));
+ }
+
+ identify_ppc_sys_by_id(mfspr(SPRN_SVR));
+
+ /* setup the PowerPC module struct */
+ ppc_md.setup_arch = mpc85xx_cds_setup_arch;
+ ppc_md.show_cpuinfo = mpc85xx_cds_show_cpuinfo;
+
+ ppc_md.init_IRQ = mpc85xx_cds_init_IRQ;
+ ppc_md.get_irq = openpic_get_irq;
+
+ ppc_md.restart = mpc85xx_restart;
+ ppc_md.power_off = mpc85xx_power_off;
+ ppc_md.halt = mpc85xx_halt;
+
+ ppc_md.find_end_of_memory = mpc85xx_find_end_of_memory;
+
+ ppc_md.calibrate_decr = mpc85xx_calibrate_decr;
+
+ ppc_md.time_init = todc_time_init;
+ ppc_md.set_rtc_time = todc_set_rtc_time;
+ ppc_md.get_rtc_time = todc_get_rtc_time;
+
+ ppc_md.nvram_read_val = todc_direct_read_val;
+ ppc_md.nvram_write_val = todc_direct_write_val;
+
+#if defined(CONFIG_SERIAL_8250) && defined(CONFIG_SERIAL_TEXT_DEBUG)
+ ppc_md.progress = gen550_progress;
+#endif /* CONFIG_SERIAL_8250 && CONFIG_SERIAL_TEXT_DEBUG */
+
+ if (ppc_md.progress)
+ ppc_md.progress("mpc85xx_cds_init(): exit", 0);
+
+ return;
+}
diff --git a/arch/ppc/platforms/85xx/mpc85xx_cds_common.h b/arch/ppc/platforms/85xx/mpc85xx_cds_common.h
new file mode 100644
index 0000000..7627d77
--- /dev/null
+++ b/arch/ppc/platforms/85xx/mpc85xx_cds_common.h
@@ -0,0 +1,80 @@
+/*
+ * arch/ppc/platforms/85xx/mpc85xx_cds_common.h
+ *
+ * MPC85xx CDS board definitions
+ *
+ * Maintainer: Kumar Gala <kumar.gala@freescale.com>
+ *
+ * Copyright 2004 Freescale Semiconductor, Inc
+ *
+ * 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.
+ *
+ */
+
+#ifndef __MACH_MPC85XX_CDS_H__
+#define __MACH_MPC85XX_CDS_H__
+
+#include <linux/config.h>
+#include <linux/serial.h>
+#include <asm/ppcboot.h>
+#include <linux/initrd.h>
+#include <syslib/ppc85xx_setup.h>
+
+#define BOARD_CCSRBAR ((uint)0xe0000000)
+#define CCSRBAR_SIZE ((uint)1024*1024)
+
+/* CADMUS info */
+#define CADMUS_BASE (0xf8004000)
+#define CADMUS_SIZE (256)
+#define CM_VER (0)
+#define CM_CSR (1)
+#define CM_RST (2)
+
+/* CDS NVRAM/RTC */
+#define CDS_RTC_ADDR (0xf8000000)
+#define CDS_RTC_SIZE (8 * 1024)
+
+/* PCI config */
+#define PCI1_CFG_ADDR_OFFSET (0x8000)
+#define PCI1_CFG_DATA_OFFSET (0x8004)
+
+#define PCI2_CFG_ADDR_OFFSET (0x9000)
+#define PCI2_CFG_DATA_OFFSET (0x9004)
+
+/* PCI interrupt controller */
+#define PIRQ0A MPC85xx_IRQ_EXT0
+#define PIRQ0B MPC85xx_IRQ_EXT1
+#define PIRQ0C MPC85xx_IRQ_EXT2
+#define PIRQ0D MPC85xx_IRQ_EXT3
+#define PIRQ1A MPC85xx_IRQ_EXT11
+
+/* PCI 1 memory map */
+#define MPC85XX_PCI1_LOWER_IO 0x00000000
+#define MPC85XX_PCI1_UPPER_IO 0x00ffffff
+
+#define MPC85XX_PCI1_LOWER_MEM 0x80000000
+#define MPC85XX_PCI1_UPPER_MEM 0x9fffffff
+
+#define MPC85XX_PCI1_IO_BASE 0xe2000000
+#define MPC85XX_PCI1_MEM_OFFSET 0x00000000
+
+#define MPC85XX_PCI1_IO_SIZE 0x01000000
+
+/* PCI 2 memory map */
+/* Note: the standard PPC fixups will cause IO space to get bumped by
+ * hose->io_base_virt - isa_io_base => MPC85XX_PCI1_IO_SIZE */
+#define MPC85XX_PCI2_LOWER_IO 0x00000000
+#define MPC85XX_PCI2_UPPER_IO 0x00ffffff
+
+#define MPC85XX_PCI2_LOWER_MEM 0xa0000000
+#define MPC85XX_PCI2_UPPER_MEM 0xbfffffff
+
+#define MPC85XX_PCI2_IO_BASE 0xe3000000
+#define MPC85XX_PCI2_MEM_OFFSET 0x00000000
+
+#define MPC85XX_PCI2_IO_SIZE 0x01000000
+
+#endif /* __MACH_MPC85XX_CDS_H__ */
diff --git a/arch/ppc/platforms/85xx/sbc8560.c b/arch/ppc/platforms/85xx/sbc8560.c
new file mode 100644
index 0000000..9ab05e5
--- /dev/null
+++ b/arch/ppc/platforms/85xx/sbc8560.c
@@ -0,0 +1,227 @@
+/*
+ * arch/ppc/platforms/85xx/sbc8560.c
+ *
+ * Wind River SBC8560 board specific routines
+ *
+ * Maintainer: Kumar Gala <kumar.gala@freescale.com>
+ *
+ * Copyright 2004 Freescale Semiconductor Inc.
+ *
+ * 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.
+ */
+
+#include <linux/config.h>
+#include <linux/stddef.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/reboot.h>
+#include <linux/pci.h>
+#include <linux/kdev_t.h>
+#include <linux/major.h>
+#include <linux/console.h>
+#include <linux/delay.h>
+#include <linux/irq.h>
+#include <linux/seq_file.h>
+#include <linux/root_dev.h>
+#include <linux/serial.h>
+#include <linux/tty.h> /* for linux/serial_core.h */
+#include <linux/serial_core.h>
+#include <linux/initrd.h>
+#include <linux/module.h>
+#include <linux/fsl_devices.h>
+
+#include <asm/system.h>
+#include <asm/pgtable.h>
+#include <asm/page.h>
+#include <asm/atomic.h>
+#include <asm/time.h>
+#include <asm/io.h>
+#include <asm/machdep.h>
+#include <asm/prom.h>
+#include <asm/open_pic.h>
+#include <asm/bootinfo.h>
+#include <asm/pci-bridge.h>
+#include <asm/mpc85xx.h>
+#include <asm/irq.h>
+#include <asm/immap_85xx.h>
+#include <asm/kgdb.h>
+#include <asm/ppc_sys.h>
+#include <mm/mmu_decl.h>
+
+#include <syslib/ppc85xx_common.h>
+#include <syslib/ppc85xx_setup.h>
+
+#ifdef CONFIG_SERIAL_8250
+static void __init
+sbc8560_early_serial_map(void)
+{
+ struct uart_port uart_req;
+
+ /* Setup serial port access */
+ memset(&uart_req, 0, sizeof (uart_req));
+ uart_req.irq = MPC85xx_IRQ_EXT9;
+ uart_req.flags = STD_COM_FLAGS;
+ uart_req.uartclk = BASE_BAUD * 16;
+ uart_req.iotype = SERIAL_IO_MEM;
+ uart_req.mapbase = UARTA_ADDR;
+ uart_req.membase = ioremap(uart_req.mapbase, MPC85xx_UART0_SIZE);
+ uart_req.type = PORT_16650;
+
+#if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB)
+ gen550_init(0, &uart_req);
+#endif
+
+ if (early_serial_setup(&uart_req) != 0)
+ printk("Early serial init of port 0 failed\n");
+
+ /* Assume early_serial_setup() doesn't modify uart_req */
+ uart_req.line = 1;
+ uart_req.mapbase = UARTB_ADDR;
+ uart_req.membase = ioremap(uart_req.mapbase, MPC85xx_UART1_SIZE);
+ uart_req.irq = MPC85xx_IRQ_EXT10;
+
+#if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB)
+ gen550_init(1, &uart_req);
+#endif
+
+ if (early_serial_setup(&uart_req) != 0)
+ printk("Early serial init of port 1 failed\n");
+}
+#endif
+
+/* ************************************************************************
+ *
+ * Setup the architecture
+ *
+ */
+static void __init
+sbc8560_setup_arch(void)
+{
+ bd_t *binfo = (bd_t *) __res;
+ unsigned int freq;
+ struct gianfar_platform_data *pdata;
+
+ /* get the core frequency */
+ freq = binfo->bi_intfreq;
+
+ if (ppc_md.progress)
+ ppc_md.progress("sbc8560_setup_arch()", 0);
+
+ /* Set loops_per_jiffy to a half-way reasonable value,
+ for use until calibrate_delay gets called. */
+ loops_per_jiffy = freq / HZ;
+
+#ifdef CONFIG_PCI
+ /* setup PCI host bridges */
+ mpc85xx_setup_hose();
+#endif
+#ifdef CONFIG_SERIAL_8250
+ sbc8560_early_serial_map();
+#endif
+#ifdef CONFIG_SERIAL_TEXT_DEBUG
+ /* Invalidate the entry we stole earlier the serial ports
+ * should be properly mapped */
+ invalidate_tlbcam_entry(NUM_TLBCAMS - 1);
+#endif
+
+ /* setup the board related information for the enet controllers */
+ pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_TSEC1);
+ pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR;
+ pdata->interruptPHY = MPC85xx_IRQ_EXT6;
+ pdata->phyid = 25;
+ /* fixup phy address */
+ pdata->phy_reg_addr += binfo->bi_immr_base;
+ memcpy(pdata->mac_addr, binfo->bi_enetaddr, 6);
+
+ pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_TSEC2);
+ pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR;
+ pdata->interruptPHY = MPC85xx_IRQ_EXT7;
+ pdata->phyid = 26;
+ /* fixup phy address */
+ pdata->phy_reg_addr += binfo->bi_immr_base;
+ memcpy(pdata->mac_addr, binfo->bi_enet1addr, 6);
+
+#ifdef CONFIG_BLK_DEV_INITRD
+ if (initrd_start)
+ ROOT_DEV = Root_RAM0;
+ else
+#endif
+#ifdef CONFIG_ROOT_NFS
+ ROOT_DEV = Root_NFS;
+#else
+ ROOT_DEV = Root_HDA1;
+#endif
+}
+
+/* ************************************************************************ */
+void __init
+platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
+ unsigned long r6, unsigned long r7)
+{
+ /* parse_bootinfo must always be called first */
+ parse_bootinfo(find_bootinfo());
+
+ /*
+ * If we were passed in a board information, copy it into the
+ * residual data area.
+ */
+ if (r3) {
+ memcpy((void *) __res, (void *) (r3 + KERNELBASE),
+ sizeof (bd_t));
+ }
+
+#ifdef CONFIG_SERIAL_TEXT_DEBUG
+ /* Use the last TLB entry to map CCSRBAR to allow access to DUART regs */
+ settlbcam(NUM_TLBCAMS - 1, UARTA_ADDR,
+ UARTA_ADDR, 0x1000, _PAGE_IO, 0);
+#endif
+
+#if defined(CONFIG_BLK_DEV_INITRD)
+ /*
+ * If the init RAM disk has been configured in, and there's a valid
+ * starting address for it, set it up.
+ */
+ if (r4) {
+ initrd_start = r4 + KERNELBASE;
+ initrd_end = r5 + KERNELBASE;
+ }
+#endif /* CONFIG_BLK_DEV_INITRD */
+
+ /* Copy the kernel command line arguments to a safe place. */
+
+ if (r6) {
+ *(char *) (r7 + KERNELBASE) = 0;
+ strcpy(cmd_line, (char *) (r6 + KERNELBASE));
+ }
+
+ identify_ppc_sys_by_id(mfspr(SPRN_SVR));
+
+ /* setup the PowerPC module struct */
+ ppc_md.setup_arch = sbc8560_setup_arch;
+ ppc_md.show_cpuinfo = sbc8560_show_cpuinfo;
+
+ ppc_md.init_IRQ = sbc8560_init_IRQ;
+ ppc_md.get_irq = openpic_get_irq;
+
+ ppc_md.restart = mpc85xx_restart;
+ ppc_md.power_off = mpc85xx_power_off;
+ ppc_md.halt = mpc85xx_halt;
+
+ ppc_md.find_end_of_memory = mpc85xx_find_end_of_memory;
+
+ ppc_md.time_init = NULL;
+ ppc_md.set_rtc_time = NULL;
+ ppc_md.get_rtc_time = NULL;
+ ppc_md.calibrate_decr = mpc85xx_calibrate_decr;
+
+#if defined(CONFIG_SERIAL_8250) && defined(CONFIG_SERIAL_TEXT_DEBUG)
+ ppc_md.progress = gen550_progress;
+#endif /* CONFIG_SERIAL_8250 && CONFIG_SERIAL_TEXT_DEBUG */
+
+ if (ppc_md.progress)
+ ppc_md.progress("sbc8560_init(): exit", 0);
+}
diff --git a/arch/ppc/platforms/85xx/sbc8560.h b/arch/ppc/platforms/85xx/sbc8560.h
new file mode 100644
index 0000000..5e1b00c
--- /dev/null
+++ b/arch/ppc/platforms/85xx/sbc8560.h
@@ -0,0 +1,49 @@
+/*
+ * arch/ppc/platforms/85xx/sbc8560.h
+ *
+ * Wind River SBC8560 board definitions
+ *
+ * Copyright 2003 Motorola Inc.
+ *
+ * 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.
+ *
+ */
+
+#ifndef __MACH_SBC8560_H__
+#define __MACH_SBC8560_H__
+
+#include <linux/config.h>
+#include <platforms/85xx/sbc85xx.h>
+
+#define CPM_MAP_ADDR (CCSRBAR + MPC85xx_CPM_OFFSET)
+
+#ifdef CONFIG_SERIAL_MANY_PORTS
+#define RS_TABLE_SIZE 64
+#else
+#define RS_TABLE_SIZE 2
+#endif
+
+/* Rate for the 1.8432 Mhz clock for the onboard serial chip */
+#define BASE_BAUD ( 1843200 / 16 )
+
+#ifdef CONFIG_SERIAL_DETECT_IRQ
+#define STD_COM_FLAGS (ASYNC_SKIP_TEST|ASYNC_AUTO_IRQ)
+#else
+#define STD_COM_FLAGS (ASYNC_SKIP_TEST)
+#endif
+
+#define STD_SERIAL_PORT_DFNS \
+ { 0, BASE_BAUD, UARTA_ADDR, MPC85xx_IRQ_EXT9, STD_COM_FLAGS, /* ttyS0 */ \
+ iomem_base: (u8 *)UARTA_ADDR, \
+ io_type: SERIAL_IO_MEM }, \
+ { 0, BASE_BAUD, UARTB_ADDR, MPC85xx_IRQ_EXT10, STD_COM_FLAGS, /* ttyS1 */ \
+ iomem_base: (u8 *)UARTB_ADDR, \
+ io_type: SERIAL_IO_MEM },
+
+#define SERIAL_PORT_DFNS \
+ STD_SERIAL_PORT_DFNS
+
+#endif /* __MACH_SBC8560_H__ */
diff --git a/arch/ppc/platforms/85xx/sbc85xx.c b/arch/ppc/platforms/85xx/sbc85xx.c
new file mode 100644
index 0000000..2d638c1
--- /dev/null
+++ b/arch/ppc/platforms/85xx/sbc85xx.c
@@ -0,0 +1,203 @@
+/*
+ * arch/ppc/platform/85xx/sbc85xx.c
+ *
+ * WindRiver PowerQUICC III SBC85xx board common routines
+ *
+ * Copyright 2002, 2003 Motorola Inc.
+ * Copyright 2004 Red Hat, Inc.
+ *
+ * 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.
+ */
+
+#include <linux/config.h>
+#include <linux/stddef.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/reboot.h>
+#include <linux/pci.h>
+#include <linux/kdev_t.h>
+#include <linux/major.h>
+#include <linux/console.h>
+#include <linux/delay.h>
+#include <linux/irq.h>
+#include <linux/seq_file.h>
+#include <linux/serial.h>
+#include <linux/module.h>
+
+#include <asm/system.h>
+#include <asm/pgtable.h>
+#include <asm/page.h>
+#include <asm/atomic.h>
+#include <asm/time.h>
+#include <asm/io.h>
+#include <asm/machdep.h>
+#include <asm/prom.h>
+#include <asm/open_pic.h>
+#include <asm/bootinfo.h>
+#include <asm/pci-bridge.h>
+#include <asm/mpc85xx.h>
+#include <asm/irq.h>
+#include <asm/immap_85xx.h>
+#include <asm/ppc_sys.h>
+
+#include <mm/mmu_decl.h>
+
+#include <platforms/85xx/sbc85xx.h>
+
+unsigned char __res[sizeof (bd_t)];
+
+#ifndef CONFIG_PCI
+unsigned long isa_io_base = 0;
+unsigned long isa_mem_base = 0;
+unsigned long pci_dram_offset = 0;
+#endif
+
+extern unsigned long total_memory; /* in mm/init */
+
+/* Internal interrupts are all Level Sensitive, and Positive Polarity */
+
+static u_char sbc8560_openpic_initsenses[] __initdata = {
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 0: L2 Cache */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 1: ECM */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 2: DDR DRAM */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 3: LBIU */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 4: DMA 0 */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 5: DMA 1 */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 6: DMA 2 */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 7: DMA 3 */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 8: PCI/PCI-X */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 9: RIO Inbound Port Write Error */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 10: RIO Doorbell Inbound */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 11: RIO Outbound Message */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 12: RIO Inbound Message */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 13: TSEC 0 Transmit */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 14: TSEC 0 Receive */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 15: Unused */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 16: Unused */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 17: Unused */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 18: TSEC 0 Receive/Transmit Error */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 19: TSEC 1 Transmit */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 20: TSEC 1 Receive */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 21: Unused */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 22: Unused */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 23: Unused */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 24: TSEC 1 Receive/Transmit Error */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 25: Fast Ethernet */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 26: DUART */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 27: I2C */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 28: Performance Monitor */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 29: Unused */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 30: CPM */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 31: Unused */
+ 0x0, /* External 0: */
+ 0x0, /* External 1: */
+#if defined(CONFIG_PCI)
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* External 2: PCI slot 0 */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* External 3: PCI slot 1 */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* External 4: PCI slot 2 */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* External 5: PCI slot 3 */
+#else
+ 0x0, /* External 2: */
+ 0x0, /* External 3: */
+ 0x0, /* External 4: */
+ 0x0, /* External 5: */
+#endif
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* External 6: PHY */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* External 7: PHY */
+ 0x0, /* External 8: */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* External 9: PHY */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* External 10: PHY */
+ 0x0, /* External 11: */
+};
+
+/* ************************************************************************ */
+int
+sbc8560_show_cpuinfo(struct seq_file *m)
+{
+ uint pvid, svid, phid1;
+ uint memsize = total_memory;
+ bd_t *binfo = (bd_t *) __res;
+ unsigned int freq;
+
+ /* get the core frequency */
+ freq = binfo->bi_intfreq;
+
+ pvid = mfspr(SPRN_PVR);
+ svid = mfspr(SPRN_SVR);
+
+ seq_printf(m, "Vendor\t\t: Wind River\n");
+ seq_printf(m, "Machine\t\t: SBC%s\n", cur_ppc_sys_spec->ppc_sys_name);
+ seq_printf(m, "clock\t\t: %dMHz\n", freq / 1000000);
+ seq_printf(m, "PVR\t\t: 0x%x\n", pvid);
+ seq_printf(m, "SVR\t\t: 0x%x\n", svid);
+
+ /* Display cpu Pll setting */
+ phid1 = mfspr(SPRN_HID1);
+ seq_printf(m, "PLL setting\t: 0x%x\n", ((phid1 >> 24) & 0x3f));
+
+ /* Display the amount of memory */
+ seq_printf(m, "Memory\t\t: %d MB\n", memsize / (1024 * 1024));
+
+ return 0;
+}
+
+void __init
+sbc8560_init_IRQ(void)
+{
+ bd_t *binfo = (bd_t *) __res;
+ /* Determine the Physical Address of the OpenPIC regs */
+ phys_addr_t OpenPIC_PAddr =
+ binfo->bi_immr_base + MPC85xx_OPENPIC_OFFSET;
+ OpenPIC_Addr = ioremap(OpenPIC_PAddr, MPC85xx_OPENPIC_SIZE);
+ OpenPIC_InitSenses = sbc8560_openpic_initsenses;
+ OpenPIC_NumInitSenses = sizeof (sbc8560_openpic_initsenses);
+
+ /* Skip reserved space and internal sources */
+ openpic_set_sources(0, 32, OpenPIC_Addr + 0x10200);
+ /* Map PIC IRQs 0-11 */
+ openpic_set_sources(32, 12, OpenPIC_Addr + 0x10000);
+
+ /* we let openpic interrupts starting from an offset, to
+ * leave space for cascading interrupts underneath.
+ */
+ openpic_init(MPC85xx_OPENPIC_IRQ_OFFSET);
+
+ return;
+}
+
+/*
+ * interrupt routing
+ */
+
+#ifdef CONFIG_PCI
+int mpc85xx_map_irq(struct pci_dev *dev, unsigned char idsel,
+ unsigned char pin)
+{
+ static char pci_irq_table[][4] =
+ /*
+ * PCI IDSEL/INTPIN->INTLINE
+ * A B C D
+ */
+ {
+ {PIRQA, PIRQB, PIRQC, PIRQD},
+ {PIRQD, PIRQA, PIRQB, PIRQC},
+ {PIRQC, PIRQD, PIRQA, PIRQB},
+ {PIRQB, PIRQC, PIRQD, PIRQA},
+ };
+
+ const long min_idsel = 12, max_idsel = 15, irqs_per_slot = 4;
+ return PCI_IRQ_TABLE_LOOKUP;
+}
+
+int mpc85xx_exclude_device(u_char bus, u_char devfn)
+{
+ if (bus == 0 && PCI_SLOT(devfn) == 0)
+ return PCIBIOS_DEVICE_NOT_FOUND;
+ else
+ return PCIBIOS_SUCCESSFUL;
+}
+#endif /* CONFIG_PCI */
diff --git a/arch/ppc/platforms/85xx/sbc85xx.h b/arch/ppc/platforms/85xx/sbc85xx.h
new file mode 100644
index 0000000..7af93c6
--- /dev/null
+++ b/arch/ppc/platforms/85xx/sbc85xx.h
@@ -0,0 +1,55 @@
+/*
+ * arch/ppc/platforms/85xx/sbc85xx.h
+ *
+ * WindRiver PowerQUICC III SBC85xx common board definitions
+ *
+ * Copyright 2003 Motorola Inc.
+ * Copyright 2004 Red Hat, Inc.
+ *
+ * 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.
+ *
+ */
+
+#ifndef __PLATFORMS_85XX_SBC85XX_H__
+#define __PLATFORMS_85XX_SBC85XX_H__
+
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/seq_file.h>
+#include <asm/ppcboot.h>
+
+#define BOARD_CCSRBAR ((uint)0xff700000)
+#define CCSRBAR_SIZE ((uint)1024*1024)
+
+#define BCSR_ADDR ((uint)0xfc000000)
+#define BCSR_SIZE ((uint)(16 * 1024 * 1024))
+
+#define UARTA_ADDR (BCSR_ADDR + 0x00700000)
+#define UARTB_ADDR (BCSR_ADDR + 0x00800000)
+#define RTC_DEVICE_ADDR (BCSR_ADDR + 0x00900000)
+#define EEPROM_ADDR (BCSR_ADDR + 0x00b00000)
+
+extern int sbc8560_show_cpuinfo(struct seq_file *m);
+extern void sbc8560_init_IRQ(void) __init;
+
+/* PCI interrupt controller */
+#define PIRQA MPC85xx_IRQ_EXT1
+#define PIRQB MPC85xx_IRQ_EXT2
+#define PIRQC MPC85xx_IRQ_EXT3
+#define PIRQD MPC85xx_IRQ_EXT4
+
+#define MPC85XX_PCI1_LOWER_IO 0x00000000
+#define MPC85XX_PCI1_UPPER_IO 0x00ffffff
+
+#define MPC85XX_PCI1_LOWER_MEM 0x80000000
+#define MPC85XX_PCI1_UPPER_MEM 0x9fffffff
+
+#define MPC85XX_PCI1_IO_BASE 0xe2000000
+#define MPC85XX_PCI1_MEM_OFFSET 0x00000000
+
+#define MPC85XX_PCI1_IO_SIZE 0x01000000
+
+#endif /* __PLATFORMS_85XX_SBC85XX_H__ */
diff --git a/arch/ppc/platforms/85xx/stx_gp3.c b/arch/ppc/platforms/85xx/stx_gp3.c
new file mode 100644
index 0000000..bc95836
--- /dev/null
+++ b/arch/ppc/platforms/85xx/stx_gp3.c
@@ -0,0 +1,355 @@
+/*
+ * arch/ppc/platforms/85xx/stx_gp3.c
+ *
+ * STx GP3 board specific routines
+ *
+ * Dan Malek <dan@embeddededge.com>
+ * Copyright 2004 Embedded Edge, LLC
+ *
+ * Copied from mpc8560_ads.c
+ * Copyright 2002, 2003 Motorola Inc.
+ *
+ * Ported to 2.6, Matt Porter <mporter@kernel.crashing.org>
+ * Copyright 2004-2005 MontaVista Software, Inc.
+ *
+ * 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.
+ */
+
+#include <linux/config.h>
+#include <linux/stddef.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/reboot.h>
+#include <linux/pci.h>
+#include <linux/kdev_t.h>
+#include <linux/major.h>
+#include <linux/blkdev.h>
+#include <linux/console.h>
+#include <linux/delay.h>
+#include <linux/irq.h>
+#include <linux/root_dev.h>
+#include <linux/seq_file.h>
+#include <linux/serial.h>
+#include <linux/initrd.h>
+#include <linux/module.h>
+#include <linux/fsl_devices.h>
+#include <linux/interrupt.h>
+
+#include <asm/system.h>
+#include <asm/pgtable.h>
+#include <asm/page.h>
+#include <asm/atomic.h>
+#include <asm/time.h>
+#include <asm/io.h>
+#include <asm/machdep.h>
+#include <asm/prom.h>
+#include <asm/open_pic.h>
+#include <asm/bootinfo.h>
+#include <asm/pci-bridge.h>
+#include <asm/mpc85xx.h>
+#include <asm/irq.h>
+#include <asm/immap_85xx.h>
+#include <asm/immap_cpm2.h>
+#include <asm/mpc85xx.h>
+#include <asm/ppc_sys.h>
+
+#include <syslib/cpm2_pic.h>
+#include <syslib/ppc85xx_common.h>
+
+extern void cpm2_reset(void);
+
+unsigned char __res[sizeof(bd_t)];
+
+#ifndef CONFIG_PCI
+unsigned long isa_io_base = 0;
+unsigned long isa_mem_base = 0;
+unsigned long pci_dram_offset = 0;
+#endif
+
+/* Internal interrupts are all Level Sensitive, and Positive Polarity */
+static u8 gp3_openpic_initsenses[] __initdata = {
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 0: L2 Cache */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 1: ECM */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 2: DDR DRAM */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 3: LBIU */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 4: DMA 0 */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 5: DMA 1 */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 6: DMA 2 */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 7: DMA 3 */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 8: PCI/PCI-X */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 9: RIO Inbound Port Write Error */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 10: RIO Doorbell Inbound */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 11: RIO Outbound Message */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 12: RIO Inbound Message */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 13: TSEC 0 Transmit */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 14: TSEC 0 Receive */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 15: Unused */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 16: Unused */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 17: Unused */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 18: TSEC 0 Receive/Transmit Error */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 19: TSEC 1 Transmit */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 20: TSEC 1 Receive */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 21: Unused */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 22: Unused */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 23: Unused */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 24: TSEC 1 Receive/Transmit Error */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 25: Fast Ethernet */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 26: DUART */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 27: I2C */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 28: Performance Monitor */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 29: Unused */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 30: CPM */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 31: Unused */
+ 0x0, /* External 0: */
+#if defined(CONFIG_PCI)
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* External 1: PCI slot 0 */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* External 2: PCI slot 1 */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* External 3: PCI slot 2 */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* External 4: PCI slot 3 */
+#else
+ 0x0, /* External 1: */
+ 0x0, /* External 2: */
+ 0x0, /* External 3: */
+ 0x0, /* External 4: */
+#endif
+ 0x0, /* External 5: */
+ 0x0, /* External 6: */
+ 0x0, /* External 7: */
+ 0x0, /* External 8: */
+ 0x0, /* External 9: */
+ 0x0, /* External 10: */
+ 0x0, /* External 11: */
+};
+
+/*
+ * Setup the architecture
+ */
+static void __init
+gp3_setup_arch(void)
+{
+ bd_t *binfo = (bd_t *) __res;
+ unsigned int freq;
+ struct gianfar_platform_data *pdata;
+
+ cpm2_reset();
+
+ /* get the core frequency */
+ freq = binfo->bi_intfreq;
+
+ if (ppc_md.progress)
+ ppc_md.progress("gp3_setup_arch()", 0);
+
+ /* Set loops_per_jiffy to a half-way reasonable value,
+ for use until calibrate_delay gets called. */
+ loops_per_jiffy = freq / HZ;
+
+#ifdef CONFIG_PCI
+ /* setup PCI host bridges */
+ mpc85xx_setup_hose();
+#endif
+
+ /* setup the board related information for the enet controllers */
+ pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_TSEC1);
+/* pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR; */
+ pdata->interruptPHY = MPC85xx_IRQ_EXT5;
+ pdata->phyid = 2;
+ pdata->phy_reg_addr += binfo->bi_immr_base;
+ memcpy(pdata->mac_addr, binfo->bi_enetaddr, 6);
+
+ pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_TSEC2);
+/* pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR; */
+ pdata->interruptPHY = MPC85xx_IRQ_EXT5;
+ pdata->phyid = 4;
+ /* fixup phy address */
+ pdata->phy_reg_addr += binfo->bi_immr_base;
+ memcpy(pdata->mac_addr, binfo->bi_enet1addr, 6);
+
+#ifdef CONFIG_BLK_DEV_INITRD
+ if (initrd_start)
+ ROOT_DEV = Root_RAM0;
+ else
+#endif
+#ifdef CONFIG_ROOT_NFS
+ ROOT_DEV = Root_NFS;
+#else
+ ROOT_DEV = Root_HDA1;
+#endif
+
+ printk ("bi_immr_base = %8.8lx\n", binfo->bi_immr_base);
+}
+
+static irqreturn_t cpm2_cascade(int irq, void *dev_id, struct pt_regs *regs)
+{
+ while ((irq = cpm2_get_irq(regs)) >= 0)
+ __do_IRQ(irq, regs);
+
+ return IRQ_HANDLED;
+}
+
+static struct irqaction cpm2_irqaction = {
+ .handler = cpm2_cascade,
+ .flags = SA_INTERRUPT,
+ .mask = CPU_MASK_NONE,
+ .name = "cpm2_cascade",
+};
+
+static void __init
+gp3_init_IRQ(void)
+{
+ int i;
+ bd_t *binfo = (bd_t *) __res;
+
+ /*
+ * Setup OpenPIC
+ */
+
+ /* Determine the Physical Address of the OpenPIC regs */
+ phys_addr_t OpenPIC_PAddr =
+ binfo->bi_immr_base + MPC85xx_OPENPIC_OFFSET;
+ OpenPIC_Addr = ioremap(OpenPIC_PAddr, MPC85xx_OPENPIC_SIZE);
+ OpenPIC_InitSenses = gp3_openpic_initsenses;
+ OpenPIC_NumInitSenses = sizeof (gp3_openpic_initsenses);
+
+ /* Skip reserved space and internal sources */
+ openpic_set_sources(0, 32, OpenPIC_Addr + 0x10200);
+
+ /* Map PIC IRQs 0-11 */
+ openpic_set_sources(32, 12, OpenPIC_Addr + 0x10000);
+
+ /*
+ * Let openpic interrupts starting from an offset, to
+ * leave space for cascading interrupts underneath.
+ */
+ openpic_init(MPC85xx_OPENPIC_IRQ_OFFSET);
+
+ /* Setup CPM2 PIC */
+ cpm2_init_IRQ();
+
+ setup_irq(MPC85xx_IRQ_CPM, &cpm2_irqaction);
+
+ return;
+}
+
+static int
+gp3_show_cpuinfo(struct seq_file *m)
+{
+ uint pvid, svid, phid1;
+ bd_t *binfo = (bd_t *) __res;
+ uint memsize;
+ unsigned int freq;
+ extern unsigned long total_memory; /* in mm/init */
+
+ /* get the core frequency */
+ freq = binfo->bi_intfreq;
+
+ pvid = mfspr(SPRN_PVR);
+ svid = mfspr(SPRN_SVR);
+
+ memsize = total_memory;
+
+ seq_printf(m, "Vendor\t\t: RPC Electronics STx \n");
+ seq_printf(m, "Machine\t\t: GP3 - MPC%s\n", cur_ppc_sys_spec->ppc_sys_name);
+ seq_printf(m, "bus freq\t: %u.%.6u MHz\n", freq / 1000000,
+ freq % 1000000);
+ seq_printf(m, "PVR\t\t: 0x%x\n", pvid);
+ seq_printf(m, "SVR\t\t: 0x%x\n", svid);
+
+ /* Display cpu Pll setting */
+ phid1 = mfspr(SPRN_HID1);
+ seq_printf(m, "PLL setting\t: 0x%x\n", ((phid1 >> 24) & 0x3f));
+
+ /* Display the amount of memory */
+ seq_printf(m, "Memory\t\t: %d MB\n", memsize / (1024 * 1024));
+
+ return 0;
+}
+
+#ifdef CONFIG_PCI
+int mpc85xx_map_irq(struct pci_dev *dev, unsigned char idsel,
+ unsigned char pin)
+{
+ static char pci_irq_table[][4] =
+ /*
+ * PCI IDSEL/INTPIN->INTLINE
+ * A B C D
+ */
+ {
+ {PIRQA, PIRQB, PIRQC, PIRQD},
+ {PIRQD, PIRQA, PIRQB, PIRQC},
+ {PIRQC, PIRQD, PIRQA, PIRQB},
+ {PIRQB, PIRQC, PIRQD, PIRQA},
+ };
+
+ const long min_idsel = 12, max_idsel = 15, irqs_per_slot = 4;
+ return PCI_IRQ_TABLE_LOOKUP;
+}
+
+int mpc85xx_exclude_device(u_char bus, u_char devfn)
+{
+ if (bus == 0 && PCI_SLOT(devfn) == 0)
+ return PCIBIOS_DEVICE_NOT_FOUND;
+ else
+ return PCIBIOS_SUCCESSFUL;
+}
+#endif /* CONFIG_PCI */
+
+void __init
+platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
+ unsigned long r6, unsigned long r7)
+{
+ /* parse_bootinfo must always be called first */
+ parse_bootinfo(find_bootinfo());
+
+ /*
+ * If we were passed in a board information, copy it into the
+ * residual data area.
+ */
+ if (r3) {
+ memcpy((void *) __res, (void *) (r3 + KERNELBASE),
+ sizeof (bd_t));
+
+ }
+#if defined(CONFIG_BLK_DEV_INITRD)
+ /*
+ * If the init RAM disk has been configured in, and there's a valid
+ * starting address for it, set it up.
+ */
+ if (r4) {
+ initrd_start = r4 + KERNELBASE;
+ initrd_end = r5 + KERNELBASE;
+ }
+#endif /* CONFIG_BLK_DEV_INITRD */
+
+ /* Copy the kernel command line arguments to a safe place. */
+
+ if (r6) {
+ *(char *) (r7 + KERNELBASE) = 0;
+ strcpy(cmd_line, (char *) (r6 + KERNELBASE));
+ }
+
+ identify_ppc_sys_by_id(mfspr(SPRN_SVR));
+
+ /* setup the PowerPC module struct */
+ ppc_md.setup_arch = gp3_setup_arch;
+ ppc_md.show_cpuinfo = gp3_show_cpuinfo;
+
+ ppc_md.init_IRQ = gp3_init_IRQ;
+ ppc_md.get_irq = openpic_get_irq;
+
+ ppc_md.restart = mpc85xx_restart;
+ ppc_md.power_off = mpc85xx_power_off;
+ ppc_md.halt = mpc85xx_halt;
+
+ ppc_md.find_end_of_memory = mpc85xx_find_end_of_memory;
+
+ ppc_md.calibrate_decr = mpc85xx_calibrate_decr;
+
+ if (ppc_md.progress)
+ ppc_md.progress("platform_init(): exit", 0);
+
+ return;
+}
diff --git a/arch/ppc/platforms/85xx/stx_gp3.h b/arch/ppc/platforms/85xx/stx_gp3.h
new file mode 100644
index 0000000..7bcc6c3
--- /dev/null
+++ b/arch/ppc/platforms/85xx/stx_gp3.h
@@ -0,0 +1,74 @@
+/*
+ * arch/ppc/platforms/stx8560_gp3.h
+ *
+ * STx GP3 board definitions
+ *
+ * Dan Malek (dan@embeddededge.com)
+ * Copyright 2004 Embedded Edge, LLC
+ *
+ * Ported to 2.6, Matt Porter <mporter@kernel.crashing.org>
+ * Copyright 2004-2005 MontaVista Software, Inc.
+ *
+ * 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.
+ *
+ */
+
+#ifndef __MACH_STX_GP3_H
+#define __MACH_STX_GP3_H
+
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/seq_file.h>
+#include <asm/ppcboot.h>
+
+#define BOARD_CCSRBAR ((uint)0xe0000000)
+#define CCSRBAR_SIZE ((uint)1024*1024)
+
+#define CPM_MAP_ADDR (CCSRBAR + MPC85xx_CPM_OFFSET)
+
+#define BCSR_ADDR ((uint)0xfc000000)
+#define BCSR_SIZE ((uint)(16 * 1024))
+
+#define BCSR_TSEC1_RESET 0x00000080
+#define BCSR_TSEC2_RESET 0x00000040
+#define BCSR_LED1 0x00000008
+#define BCSR_LED2 0x00000004
+#define BCSR_LED3 0x00000002
+#define BCSR_LED4 0x00000001
+
+extern void mpc85xx_setup_hose(void) __init;
+extern void mpc85xx_restart(char *cmd);
+extern void mpc85xx_power_off(void);
+extern void mpc85xx_halt(void);
+extern int mpc85xx_show_cpuinfo(struct seq_file *m);
+extern void mpc85xx_init_IRQ(void) __init;
+extern unsigned long mpc85xx_find_end_of_memory(void) __init;
+extern void mpc85xx_calibrate_decr(void) __init;
+
+#define PCI_CFG_ADDR_OFFSET (0x8000)
+#define PCI_CFG_DATA_OFFSET (0x8004)
+
+/* PCI interrupt controller */
+#define PIRQA MPC85xx_IRQ_EXT1
+#define PIRQB MPC85xx_IRQ_EXT2
+#define PIRQC MPC85xx_IRQ_EXT3
+#define PIRQD MPC85xx_IRQ_EXT4
+#define PCI_MIN_IDSEL 16
+#define PCI_MAX_IDSEL 19
+#define PCI_IRQ_SLOT 4
+
+#define MPC85XX_PCI1_LOWER_IO 0x00000000
+#define MPC85XX_PCI1_UPPER_IO 0x00ffffff
+
+#define MPC85XX_PCI1_LOWER_MEM 0x80000000
+#define MPC85XX_PCI1_UPPER_MEM 0x9fffffff
+
+#define MPC85XX_PCI1_IO_BASE 0xe2000000
+#define MPC85XX_PCI1_MEM_OFFSET 0x00000000
+
+#define MPC85XX_PCI1_IO_SIZE 0x01000000
+
+#endif /* __MACH_STX_GP3_H */
diff --git a/arch/ppc/platforms/Makefile b/arch/ppc/platforms/Makefile
new file mode 100644
index 0000000..5488a05
--- /dev/null
+++ b/arch/ppc/platforms/Makefile
@@ -0,0 +1,53 @@
+#
+# Makefile for the linux kernel.
+#
+
+# Extra CFLAGS so we don't have to do relative includes
+CFLAGS_pmac_setup.o += -Iarch/$(ARCH)/mm
+
+obj-$(CONFIG_APUS) += apus_setup.o
+ifeq ($(CONFIG_APUS),y)
+obj-$(CONFIG_PCI) += apus_pci.o
+endif
+obj-$(CONFIG_PPC_PMAC) += pmac_pic.o pmac_setup.o pmac_time.o \
+ pmac_feature.o pmac_pci.o pmac_sleep.o \
+ pmac_low_i2c.o pmac_cache.o
+obj-$(CONFIG_PPC_CHRP) += chrp_setup.o chrp_time.o chrp_pci.o \
+ chrp_pegasos_eth.o
+obj-$(CONFIG_PPC_PREP) += prep_pci.o prep_setup.o
+ifeq ($(CONFIG_PPC_PMAC),y)
+obj-$(CONFIG_NVRAM) += pmac_nvram.o
+obj-$(CONFIG_CPU_FREQ_PMAC) += pmac_cpufreq.o
+endif
+obj-$(CONFIG_PMAC_BACKLIGHT) += pmac_backlight.o
+obj-$(CONFIG_PREP_RESIDUAL) += residual.o
+obj-$(CONFIG_ADIR) += adir_setup.o adir_pic.o adir_pci.o
+obj-$(CONFIG_PQ2ADS) += pq2ads.o
+obj-$(CONFIG_TQM8260) += tqm8260_setup.o
+obj-$(CONFIG_CPCI690) += cpci690.o
+obj-$(CONFIG_EV64260) += ev64260.o
+obj-$(CONFIG_CHESTNUT) += chestnut.o
+obj-$(CONFIG_GEMINI) += gemini_pci.o gemini_setup.o gemini_prom.o
+obj-$(CONFIG_K2) += k2.o
+obj-$(CONFIG_LOPEC) += lopec.o
+obj-$(CONFIG_KATANA) += katana.o
+obj-$(CONFIG_HDPU) += hdpu.o
+obj-$(CONFIG_MCPN765) += mcpn765.o
+obj-$(CONFIG_MENF1) += menf1_setup.o menf1_pci.o
+obj-$(CONFIG_MVME5100) += mvme5100.o
+obj-$(CONFIG_PAL4) += pal4_setup.o pal4_pci.o
+obj-$(CONFIG_PCORE) += pcore.o
+obj-$(CONFIG_POWERPMC250) += powerpmc250.o
+obj-$(CONFIG_PPLUS) += pplus.o
+obj-$(CONFIG_PRPMC750) += prpmc750.o
+obj-$(CONFIG_PRPMC800) += prpmc800.o
+obj-$(CONFIG_RADSTONE_PPC7D) += radstone_ppc7d.o
+obj-$(CONFIG_SANDPOINT) += sandpoint.o
+obj-$(CONFIG_SBC82xx) += sbc82xx.o
+obj-$(CONFIG_SPRUCE) += spruce.o
+obj-$(CONFIG_LITE5200) += lite5200.o
+
+ifeq ($(CONFIG_SMP),y)
+obj-$(CONFIG_PPC_PMAC) += pmac_smp.o
+obj-$(CONFIG_PPC_CHRP) += chrp_smp.o
+endif
diff --git a/arch/ppc/platforms/adir.h b/arch/ppc/platforms/adir.h
new file mode 100644
index 0000000..13a748b
--- /dev/null
+++ b/arch/ppc/platforms/adir.h
@@ -0,0 +1,95 @@
+/*
+ * arch/ppc/platforms/adir.h
+ *
+ * Definitions for SBS Adirondack board support
+ *
+ * By Michael Sokolov <msokolov@ivan.Harhan.ORG>
+ */
+
+#ifndef __PPC_PLATFORMS_ADIR_H
+#define __PPC_PLATFORMS_ADIR_H
+
+/*
+ * SBS Adirondack definitions
+ */
+
+/* PPC physical address space layout. We use the one set up by the firmware. */
+#define ADIR_PCI32_MEM_BASE 0x80000000
+#define ADIR_PCI32_MEM_SIZE 0x20000000
+#define ADIR_PCI64_MEM_BASE 0xA0000000
+#define ADIR_PCI64_MEM_SIZE 0x20000000
+#define ADIR_PCI32_IO_BASE 0xC0000000
+#define ADIR_PCI32_IO_SIZE 0x10000000
+#define ADIR_PCI64_IO_BASE 0xD0000000
+#define ADIR_PCI64_IO_SIZE 0x10000000
+#define ADIR_PCI64_PHB 0xFF400000
+#define ADIR_PCI32_PHB 0xFF500000
+
+#define ADIR_PCI64_CONFIG_ADDR (ADIR_PCI64_PHB + 0x000f8000)
+#define ADIR_PCI64_CONFIG_DATA (ADIR_PCI64_PHB + 0x000f8010)
+
+#define ADIR_PCI32_CONFIG_ADDR (ADIR_PCI32_PHB + 0x000f8000)
+#define ADIR_PCI32_CONFIG_DATA (ADIR_PCI32_PHB + 0x000f8010)
+
+/* System memory as seen from PCI */
+#define ADIR_PCI_SYS_MEM_BASE 0x80000000
+
+/* Static virtual mapping of PCI I/O */
+#define ADIR_PCI32_VIRT_IO_BASE 0xFE000000
+#define ADIR_PCI32_VIRT_IO_SIZE 0x01000000
+#define ADIR_PCI64_VIRT_IO_BASE 0xFF000000
+#define ADIR_PCI64_VIRT_IO_SIZE 0x01000000
+
+/* Registers */
+#define ADIR_NVRAM_RTC_ADDR 0x74
+#define ADIR_NVRAM_RTC_DATA 0x75
+
+#define ADIR_BOARD_ID_REG (ADIR_PCI32_VIRT_IO_BASE + 0x08FFF0)
+#define ADIR_CPLD1REV_REG (ADIR_PCI32_VIRT_IO_BASE + 0x08FFF1)
+#define ADIR_CPLD2REV_REG (ADIR_PCI32_VIRT_IO_BASE + 0x08FFF2)
+#define ADIR_FLASHCTL_REG (ADIR_PCI32_VIRT_IO_BASE + 0x08FFF3)
+#define ADIR_CPC710_STAT_REG (ADIR_PCI32_VIRT_IO_BASE + 0x08FFF4)
+#define ADIR_CLOCK_REG (ADIR_PCI32_VIRT_IO_BASE + 0x08FFF5)
+#define ADIR_GPIO_REG (ADIR_PCI32_VIRT_IO_BASE + 0x08FFF8)
+#define ADIR_MISC_REG (ADIR_PCI32_VIRT_IO_BASE + 0x08FFF9)
+#define ADIR_LED_REG (ADIR_PCI32_VIRT_IO_BASE + 0x08FFFA)
+
+#define ADIR_CLOCK_REG_PD 0x10
+#define ADIR_CLOCK_REG_SPREAD 0x08
+#define ADIR_CLOCK_REG_SEL133 0x04
+#define ADIR_CLOCK_REG_SEL1 0x02
+#define ADIR_CLOCK_REG_SEL0 0x01
+
+#define ADIR_PROCA_INT_MASK (ADIR_PCI32_VIRT_IO_BASE + 0x0EFFF0)
+#define ADIR_PROCB_INT_MASK (ADIR_PCI32_VIRT_IO_BASE + 0x0EFFF2)
+#define ADIR_PROCA_INT_STAT (ADIR_PCI32_VIRT_IO_BASE + 0x0EFFF4)
+#define ADIR_PROCB_INT_STAT (ADIR_PCI32_VIRT_IO_BASE + 0x0EFFF6)
+
+/* Linux IRQ numbers */
+#define ADIR_IRQ_NONE -1
+#define ADIR_IRQ_SERIAL2 3
+#define ADIR_IRQ_SERIAL1 4
+#define ADIR_IRQ_FDC 6
+#define ADIR_IRQ_PARALLEL 7
+#define ADIR_IRQ_VIA_AUDIO 10
+#define ADIR_IRQ_VIA_USB 11
+#define ADIR_IRQ_IDE0 14
+#define ADIR_IRQ_IDE1 15
+#define ADIR_IRQ_PCI0_INTA 16
+#define ADIR_IRQ_PCI0_INTB 17
+#define ADIR_IRQ_PCI0_INTC 18
+#define ADIR_IRQ_PCI0_INTD 19
+#define ADIR_IRQ_PCI1_INTA 20
+#define ADIR_IRQ_PCI1_INTB 21
+#define ADIR_IRQ_PCI1_INTC 22
+#define ADIR_IRQ_PCI1_INTD 23
+#define ADIR_IRQ_MBSCSI 24 /* motherboard SCSI */
+#define ADIR_IRQ_MBETH1 25 /* motherboard Ethernet 1 */
+#define ADIR_IRQ_MBETH0 26 /* motherboard Ethernet 0 */
+#define ADIR_IRQ_CPC710_INT1 27
+#define ADIR_IRQ_CPC710_INT2 28
+#define ADIR_IRQ_VT82C686_NMI 29
+#define ADIR_IRQ_VT82C686_INTR 30
+#define ADIR_IRQ_INTERPROC 31
+
+#endif /* __PPC_PLATFORMS_ADIR_H */
diff --git a/arch/ppc/platforms/adir_pci.c b/arch/ppc/platforms/adir_pci.c
new file mode 100644
index 0000000..f94ac53
--- /dev/null
+++ b/arch/ppc/platforms/adir_pci.c
@@ -0,0 +1,247 @@
+/*
+ * arch/ppc/platforms/adir_pci.c
+ *
+ * PCI support for SBS Adirondack
+ *
+ * By Michael Sokolov <msokolov@ivan.Harhan.ORG>
+ * based on the K2 version by Matt Porter <mporter@mvista.com>
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/slab.h>
+
+#include <asm/byteorder.h>
+#include <asm/io.h>
+#include <asm/uaccess.h>
+#include <asm/machdep.h>
+#include <asm/pci-bridge.h>
+
+#include <syslib/cpc710.h>
+#include "adir.h"
+
+#undef DEBUG
+#ifdef DEBUG
+#define DBG(x...) printk(x)
+#else
+#define DBG(x...)
+#endif /* DEBUG */
+
+static inline int __init
+adir_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin)
+{
+#define PCIIRQ(a,b,c,d) {ADIR_IRQ_##a,ADIR_IRQ_##b,ADIR_IRQ_##c,ADIR_IRQ_##d},
+ struct pci_controller *hose = pci_bus_to_hose(dev->bus->number);
+ /*
+ * The three PCI devices on the motherboard have dedicated lines to the
+ * CPLD interrupt controller, bypassing the standard PCI INTA-D and the
+ * PC interrupt controller. All other PCI devices (slots) have usual
+ * staggered INTA-D lines, resulting in 8 lines total (PCI0 INTA-D and
+ * PCI1 INTA-D). All 8 go to the CPLD interrupt controller. PCI0 INTA-D
+ * also go to the south bridge, so we have the option of taking them
+ * via the CPLD interrupt controller or via the south bridge 8259
+ * 8258 thingy. PCI1 INTA-D can only be taken via the CPLD interrupt
+ * controller. We take all PCI interrupts via the CPLD interrupt
+ * controller as recommended by SBS.
+ *
+ * We also have some monkey business with the PCI devices within the
+ * VT82C686B south bridge itself. This chip actually has 7 functions on
+ * its IDSEL. Function 0 is the actual south bridge, function 1 is IDE,
+ * and function 4 is some special stuff. The other 4 functions are just
+ * regular PCI devices bundled in the chip. 2 and 3 are USB UHCIs and 5
+ * and 6 are audio (not supported on the Adirondack).
+ *
+ * This is where the monkey business begins. PCI devices are supposed
+ * to signal normal PCI interrupts. But the 4 functions in question are
+ * located in the south bridge chip, which is designed with the
+ * assumption that it will be fielding PCI INTA-D interrupts rather
+ * than generating them. Here's what it does. Each of the functions in
+ * question routes its interrupt to one of the IRQs on the 8259 thingy.
+ * Which one? It looks at the Interrupt Line register in the PCI config
+ * space, even though the PCI spec says it's for BIOS/OS interaction
+ * only.
+ *
+ * How do we deal with this? We take these interrupts via 8259 IRQs as
+ * we have to. We return the desired IRQ numbers from this routine when
+ * called for the functions in question. The PCI scan code will then
+ * stick our return value into the Interrupt Line register in the PCI
+ * config space, and the interrupt will actually go there. We identify
+ * these functions within the south bridge IDSEL by their interrupt pin
+ * numbers, as the VT82C686B has 04 in the Interrupt Pin register for
+ * USB and 03 for audio.
+ */
+ if (!hose->index) {
+ static char pci_irq_table[][4] =
+ /*
+ * PCI IDSEL/INTPIN->INTLINE
+ * A B C D
+ */
+ {
+ /* south bridge */ PCIIRQ(IDE0, NONE, VIA_AUDIO, VIA_USB)
+ /* Ethernet 0 */ PCIIRQ(MBETH0, MBETH0, MBETH0, MBETH0)
+ /* PCI0 slot 1 */ PCIIRQ(PCI0_INTB, PCI0_INTC, PCI0_INTD, PCI0_INTA)
+ /* PCI0 slot 2 */ PCIIRQ(PCI0_INTC, PCI0_INTD, PCI0_INTA, PCI0_INTB)
+ /* PCI0 slot 3 */ PCIIRQ(PCI0_INTD, PCI0_INTA, PCI0_INTB, PCI0_INTC)
+ };
+ const long min_idsel = 3, max_idsel = 7, irqs_per_slot = 4;
+ return PCI_IRQ_TABLE_LOOKUP;
+ } else {
+ static char pci_irq_table[][4] =
+ /*
+ * PCI IDSEL/INTPIN->INTLINE
+ * A B C D
+ */
+ {
+ /* Ethernet 1 */ PCIIRQ(MBETH1, MBETH1, MBETH1, MBETH1)
+ /* SCSI */ PCIIRQ(MBSCSI, MBSCSI, MBSCSI, MBSCSI)
+ /* PCI1 slot 1 */ PCIIRQ(PCI1_INTB, PCI1_INTC, PCI1_INTD, PCI1_INTA)
+ /* PCI1 slot 2 */ PCIIRQ(PCI1_INTC, PCI1_INTD, PCI1_INTA, PCI1_INTB)
+ /* PCI1 slot 3 */ PCIIRQ(PCI1_INTD, PCI1_INTA, PCI1_INTB, PCI1_INTC)
+ };
+ const long min_idsel = 3, max_idsel = 7, irqs_per_slot = 4;
+ return PCI_IRQ_TABLE_LOOKUP;
+ }
+#undef PCIIRQ
+}
+
+static void
+adir_pcibios_fixup_resources(struct pci_dev *dev)
+{
+ int i;
+
+ if ((dev->vendor == PCI_VENDOR_ID_IBM) &&
+ (dev->device == PCI_DEVICE_ID_IBM_CPC710_PCI64))
+ {
+ DBG("Fixup CPC710 resources\n");
+ for (i=0; i<DEVICE_COUNT_RESOURCE; i++)
+ {
+ dev->resource[i].start = 0;
+ dev->resource[i].end = 0;
+ }
+ }
+}
+
+/*
+ * CPC710 DD3 has an errata causing it to hang the system if a type 0 config
+ * cycle is attempted on its PCI32 interface with a device number > 21.
+ * CPC710's PCI bridges map device numbers 1 through 21 to AD11 through AD31.
+ * Per the PCI spec it MUST accept all other device numbers and do nothing, and
+ * software MUST scan all device numbers without assuming how IDSELs are
+ * mapped. However, as the CPC710 DD3's errata causes such correct scanning
+ * procedure to hang the system, we have no choice but to introduce this hack
+ * of knowingly avoiding device numbers > 21 on PCI0,
+ */
+static int
+adir_exclude_device(u_char bus, u_char devfn)
+{
+ if ((bus == 0) && (PCI_SLOT(devfn) > 21))
+ return PCIBIOS_DEVICE_NOT_FOUND;
+ else
+ return PCIBIOS_SUCCESSFUL;
+}
+
+void adir_find_bridges(void)
+{
+ struct pci_controller *hose_a, *hose_b;
+
+ /* Setup PCI32 hose */
+ hose_a = pcibios_alloc_controller();
+ if (!hose_a)
+ return;
+
+ hose_a->first_busno = 0;
+ hose_a->last_busno = 0xff;
+ hose_a->pci_mem_offset = ADIR_PCI32_MEM_BASE;
+ hose_a->io_space.start = 0;
+ hose_a->io_space.end = ADIR_PCI32_VIRT_IO_SIZE - 1;
+ hose_a->mem_space.start = 0;
+ hose_a->mem_space.end = ADIR_PCI32_MEM_SIZE - 1;
+ hose_a->io_resource.start = 0;
+ hose_a->io_resource.end = ADIR_PCI32_VIRT_IO_SIZE - 1;
+ hose_a->io_resource.flags = IORESOURCE_IO;
+ hose_a->mem_resources[0].start = ADIR_PCI32_MEM_BASE;
+ hose_a->mem_resources[0].end = ADIR_PCI32_MEM_BASE +
+ ADIR_PCI32_MEM_SIZE - 1;
+ hose_a->mem_resources[0].flags = IORESOURCE_MEM;
+ hose_a->io_base_phys = ADIR_PCI32_IO_BASE;
+ hose_a->io_base_virt = (void *) ADIR_PCI32_VIRT_IO_BASE;
+
+ ppc_md.pci_exclude_device = adir_exclude_device;
+ setup_indirect_pci(hose_a, ADIR_PCI32_CONFIG_ADDR,
+ ADIR_PCI32_CONFIG_DATA);
+
+ /* Initialize PCI32 bus registers */
+ early_write_config_byte(hose_a,
+ hose_a->first_busno,
+ PCI_DEVFN(0, 0),
+ CPC710_BUS_NUMBER,
+ hose_a->first_busno);
+ early_write_config_byte(hose_a,
+ hose_a->first_busno,
+ PCI_DEVFN(0, 0),
+ CPC710_SUB_BUS_NUMBER,
+ hose_a->last_busno);
+
+ hose_a->last_busno = pciauto_bus_scan(hose_a, hose_a->first_busno);
+
+ /* Write out correct max subordinate bus number for hose A */
+ early_write_config_byte(hose_a,
+ hose_a->first_busno,
+ PCI_DEVFN(0, 0),
+ CPC710_SUB_BUS_NUMBER,
+ hose_a->last_busno);
+
+ /* Setup PCI64 hose */
+ hose_b = pcibios_alloc_controller();
+ if (!hose_b)
+ return;
+
+ hose_b->first_busno = hose_a->last_busno + 1;
+ hose_b->last_busno = 0xff;
+ hose_b->pci_mem_offset = ADIR_PCI64_MEM_BASE;
+ hose_b->io_space.start = 0;
+ hose_b->io_space.end = ADIR_PCI64_VIRT_IO_SIZE - 1;
+ hose_b->mem_space.start = 0;
+ hose_b->mem_space.end = ADIR_PCI64_MEM_SIZE - 1;
+ hose_b->io_resource.start = 0;
+ hose_b->io_resource.end = ADIR_PCI64_VIRT_IO_SIZE - 1;
+ hose_b->io_resource.flags = IORESOURCE_IO;
+ hose_b->mem_resources[0].start = ADIR_PCI64_MEM_BASE;
+ hose_b->mem_resources[0].end = ADIR_PCI64_MEM_BASE +
+ ADIR_PCI64_MEM_SIZE - 1;
+ hose_b->mem_resources[0].flags = IORESOURCE_MEM;
+ hose_b->io_base_phys = ADIR_PCI64_IO_BASE;
+ hose_b->io_base_virt = (void *) ADIR_PCI64_VIRT_IO_BASE;
+
+ setup_indirect_pci(hose_b, ADIR_PCI64_CONFIG_ADDR,
+ ADIR_PCI64_CONFIG_DATA);
+
+ /* Initialize PCI64 bus registers */
+ early_write_config_byte(hose_b,
+ 0,
+ PCI_DEVFN(0, 0),
+ CPC710_SUB_BUS_NUMBER,
+ 0xff);
+
+ early_write_config_byte(hose_b,
+ 0,
+ PCI_DEVFN(0, 0),
+ CPC710_BUS_NUMBER,
+ hose_b->first_busno);
+
+ hose_b->last_busno = pciauto_bus_scan(hose_b,
+ hose_b->first_busno);
+
+ /* Write out correct max subordinate bus number for hose B */
+ early_write_config_byte(hose_b,
+ hose_b->first_busno,
+ PCI_DEVFN(0, 0),
+ CPC710_SUB_BUS_NUMBER,
+ hose_b->last_busno);
+
+ ppc_md.pcibios_fixup = NULL;
+ ppc_md.pcibios_fixup_resources = adir_pcibios_fixup_resources;
+ ppc_md.pci_swizzle = common_swizzle;
+ ppc_md.pci_map_irq = adir_map_irq;
+}
diff --git a/arch/ppc/platforms/adir_pic.c b/arch/ppc/platforms/adir_pic.c
new file mode 100644
index 0000000..9947cba
--- /dev/null
+++ b/arch/ppc/platforms/adir_pic.c
@@ -0,0 +1,130 @@
+/*
+ * arch/ppc/platforms/adir_pic.c
+ *
+ * Interrupt controller support for SBS Adirondack
+ *
+ * By Michael Sokolov <msokolov@ivan.Harhan.ORG>
+ * based on the K2 and SCM versions by Matt Porter <mporter@mvista.com>
+ */
+
+#include <linux/stddef.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/pci.h>
+#include <linux/interrupt.h>
+
+#include <asm/io.h>
+#include <asm/i8259.h>
+#include "adir.h"
+
+static void adir_onboard_pic_enable(unsigned int irq);
+static void adir_onboard_pic_disable(unsigned int irq);
+
+__init static void
+adir_onboard_pic_init(void)
+{
+ volatile u_short *maskreg = (volatile u_short *) ADIR_PROCA_INT_MASK;
+
+ /* Disable all Adirondack onboard interrupts */
+ out_be16(maskreg, 0xFFFF);
+}
+
+static int
+adir_onboard_pic_get_irq(void)
+{
+ volatile u_short *statreg = (volatile u_short *) ADIR_PROCA_INT_STAT;
+ int irq;
+ u_short int_status, int_test;
+
+ int_status = in_be16(statreg);
+ for (irq = 0, int_test = 1; irq < 16; irq++, int_test <<= 1) {
+ if (int_status & int_test)
+ break;
+ }
+
+ if (irq == 16)
+ return -1;
+
+ return (irq+16);
+}
+
+static void
+adir_onboard_pic_enable(unsigned int irq)
+{
+ volatile u_short *maskreg = (volatile u_short *) ADIR_PROCA_INT_MASK;
+
+ /* Change irq to Adirondack onboard native value */
+ irq -= 16;
+
+ /* Enable requested irq number */
+ out_be16(maskreg, in_be16(maskreg) & ~(1 << irq));
+}
+
+static void
+adir_onboard_pic_disable(unsigned int irq)
+{
+ volatile u_short *maskreg = (volatile u_short *) ADIR_PROCA_INT_MASK;
+
+ /* Change irq to Adirondack onboard native value */
+ irq -= 16;
+
+ /* Disable requested irq number */
+ out_be16(maskreg, in_be16(maskreg) | (1 << irq));
+}
+
+static struct hw_interrupt_type adir_onboard_pic = {
+ " ADIR PIC ",
+ NULL,
+ NULL,
+ adir_onboard_pic_enable, /* unmask */
+ adir_onboard_pic_disable, /* mask */
+ adir_onboard_pic_disable, /* mask and ack */
+ NULL,
+ NULL
+};
+
+static struct irqaction noop_action = {
+ .handler = no_action,
+ .flags = SA_INTERRUPT,
+ .mask = CPU_MASK_NONE,
+ .name = "82c59 primary cascade",
+};
+
+/*
+ * Linux interrupt values are assigned as follows:
+ *
+ * 0-15 VT82C686 8259 interrupts
+ * 16-31 Adirondack CPLD interrupts
+ */
+__init void
+adir_init_IRQ(void)
+{
+ int i;
+
+ /* Initialize the cascaded 8259's on the VT82C686 */
+ for (i=0; i<16; i++)
+ irq_desc[i].handler = &i8259_pic;
+ i8259_init(NULL);
+
+ /* Initialize Adirondack CPLD PIC and enable 8259 interrupt cascade */
+ for (i=16; i<32; i++)
+ irq_desc[i].handler = &adir_onboard_pic;
+ adir_onboard_pic_init();
+
+ /* Enable 8259 interrupt cascade */
+ setup_irq(ADIR_IRQ_VT82C686_INTR, &noop_action);
+}
+
+int
+adir_get_irq(struct pt_regs *regs)
+{
+ int irq;
+
+ if ((irq = adir_onboard_pic_get_irq()) < 0)
+ return irq;
+
+ if (irq == ADIR_IRQ_VT82C686_INTR)
+ irq = i8259_irq(regs);
+
+ return irq;
+}
diff --git a/arch/ppc/platforms/adir_setup.c b/arch/ppc/platforms/adir_setup.c
new file mode 100644
index 0000000..6a6754e
--- /dev/null
+++ b/arch/ppc/platforms/adir_setup.c
@@ -0,0 +1,210 @@
+/*
+ * arch/ppc/platforms/adir_setup.c
+ *
+ * Board setup routines for SBS Adirondack
+ *
+ * By Michael Sokolov <msokolov@ivan.Harhan.ORG>
+ * based on the K2 version by Matt Porter <mporter@mvista.com>
+ */
+
+#include <linux/config.h>
+#include <linux/stddef.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/reboot.h>
+#include <linux/pci.h>
+#include <linux/kdev_t.h>
+#include <linux/types.h>
+#include <linux/major.h>
+#include <linux/initrd.h>
+#include <linux/console.h>
+#include <linux/delay.h>
+#include <linux/ide.h>
+#include <linux/seq_file.h>
+#include <linux/root_dev.h>
+
+#include <asm/system.h>
+#include <asm/pgtable.h>
+#include <asm/page.h>
+#include <asm/dma.h>
+#include <asm/io.h>
+#include <asm/machdep.h>
+#include <asm/time.h>
+#include <asm/todc.h>
+#include <asm/bootinfo.h>
+
+#include "adir.h"
+
+extern void adir_init_IRQ(void);
+extern int adir_get_irq(struct pt_regs *);
+extern void adir_find_bridges(void);
+extern unsigned long loops_per_jiffy;
+
+static unsigned int cpu_750cx[16] = {
+ 5, 15, 14, 0, 4, 13, 0, 9, 6, 11, 8, 10, 16, 12, 7, 0
+};
+
+static int
+adir_get_bus_speed(void)
+{
+ if (!(*((u_char *) ADIR_CLOCK_REG) & ADIR_CLOCK_REG_SEL133))
+ return 100000000;
+ else
+ return 133333333;
+}
+
+static int
+adir_get_cpu_speed(void)
+{
+ unsigned long hid1;
+ int cpu_speed;
+
+ hid1 = mfspr(SPRN_HID1) >> 28;
+
+ hid1 = cpu_750cx[hid1];
+
+ cpu_speed = adir_get_bus_speed()*hid1/2;
+ return cpu_speed;
+}
+
+static void __init
+adir_calibrate_decr(void)
+{
+ int freq, divisor = 4;
+
+ /* determine processor bus speed */
+ freq = adir_get_bus_speed();
+ tb_ticks_per_jiffy = freq / HZ / divisor;
+ tb_to_us = mulhwu_scale_factor(freq/divisor, 1000000);
+}
+
+static int
+adir_show_cpuinfo(struct seq_file *m)
+{
+ seq_printf(m, "vendor\t\t: SBS\n");
+ seq_printf(m, "machine\t\t: Adirondack\n");
+ seq_printf(m, "cpu speed\t: %dMhz\n", adir_get_cpu_speed()/1000000);
+ seq_printf(m, "bus speed\t: %dMhz\n", adir_get_bus_speed()/1000000);
+ seq_printf(m, "memory type\t: SDRAM\n");
+
+ return 0;
+}
+
+extern char cmd_line[];
+
+TODC_ALLOC();
+
+static void __init
+adir_setup_arch(void)
+{
+ unsigned int cpu;
+
+ /* Setup TODC access */
+ TODC_INIT(TODC_TYPE_MC146818, ADIR_NVRAM_RTC_ADDR, 0,
+ ADIR_NVRAM_RTC_DATA, 8);
+
+ /* init to some ~sane value until calibrate_delay() runs */
+ loops_per_jiffy = 50000000/HZ;
+
+ /* Setup PCI host bridges */
+ adir_find_bridges();
+
+#ifdef CONFIG_BLK_DEV_INITRD
+ if (initrd_start)
+ ROOT_DEV = Root_RAM0;
+ else
+#endif
+#ifdef CONFIG_ROOT_NFS
+ ROOT_DEV = Root_NFS;
+#else
+ ROOT_DEV = Root_SDA1;
+#endif
+
+ /* Identify the system */
+ printk("System Identification: SBS Adirondack - PowerPC 750CXe @ %d Mhz\n", adir_get_cpu_speed()/1000000);
+ printk("SBS Adirondack port (C) 2001 SBS Technologies, Inc.\n");
+
+ /* Identify the CPU manufacturer */
+ cpu = mfspr(SPRN_PVR);
+ printk("CPU manufacturer: IBM [rev=%04x]\n", (cpu & 0xffff));
+}
+
+static void
+adir_restart(char *cmd)
+{
+ local_irq_disable();
+ /* SRR0 has system reset vector, SRR1 has default MSR value */
+ /* rfi restores MSR from SRR1 and sets the PC to the SRR0 value */
+ __asm__ __volatile__
+ ("lis 3,0xfff0\n\t"
+ "ori 3,3,0x0100\n\t"
+ "mtspr 26,3\n\t"
+ "li 3,0\n\t"
+ "mtspr 27,3\n\t"
+ "rfi\n\t");
+ for(;;);
+}
+
+static void
+adir_power_off(void)
+{
+ for(;;);
+}
+
+static void
+adir_halt(void)
+{
+ adir_restart(NULL);
+}
+
+static unsigned long __init
+adir_find_end_of_memory(void)
+{
+ return boot_mem_size;
+}
+
+static void __init
+adir_map_io(void)
+{
+ io_block_mapping(ADIR_PCI32_VIRT_IO_BASE, ADIR_PCI32_IO_BASE,
+ ADIR_PCI32_VIRT_IO_SIZE, _PAGE_IO);
+ io_block_mapping(ADIR_PCI64_VIRT_IO_BASE, ADIR_PCI64_IO_BASE,
+ ADIR_PCI64_VIRT_IO_SIZE, _PAGE_IO);
+}
+
+void __init
+platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
+ unsigned long r6, unsigned long r7)
+{
+ /*
+ * On the Adirondack we use bi_recs and pass the pointer to them in R3.
+ */
+ parse_bootinfo((struct bi_record *) (r3 + KERNELBASE));
+
+ /* Remember, isa_io_base is virtual but isa_mem_base is physical! */
+ isa_io_base = ADIR_PCI32_VIRT_IO_BASE;
+ isa_mem_base = ADIR_PCI32_MEM_BASE;
+ pci_dram_offset = ADIR_PCI_SYS_MEM_BASE;
+
+ ppc_md.setup_arch = adir_setup_arch;
+ ppc_md.show_cpuinfo = adir_show_cpuinfo;
+ ppc_md.irq_canonicalize = NULL;
+ ppc_md.init_IRQ = adir_init_IRQ;
+ ppc_md.get_irq = adir_get_irq;
+ ppc_md.init = NULL;
+
+ ppc_md.find_end_of_memory = adir_find_end_of_memory;
+ ppc_md.setup_io_mappings = adir_map_io;
+
+ ppc_md.restart = adir_restart;
+ ppc_md.power_off = adir_power_off;
+ ppc_md.halt = adir_halt;
+
+ ppc_md.time_init = todc_time_init;
+ ppc_md.set_rtc_time = todc_set_rtc_time;
+ ppc_md.get_rtc_time = todc_get_rtc_time;
+ ppc_md.nvram_read_val = todc_mc146818_read_val;
+ ppc_md.nvram_write_val = todc_mc146818_write_val;
+ ppc_md.calibrate_decr = adir_calibrate_decr;
+}
diff --git a/arch/ppc/platforms/apus_pci.c b/arch/ppc/platforms/apus_pci.c
new file mode 100644
index 0000000..33dad6d
--- /dev/null
+++ b/arch/ppc/platforms/apus_pci.c
@@ -0,0 +1,208 @@
+/*
+ * Copyright (C) Michel Dänzer <michdaen@iiic.ethz.ch>
+ *
+ * APUS PCI routines.
+ *
+ * Currently, only B/CVisionPPC cards (Permedia2) are supported.
+ *
+ * Thanks to Geert Uytterhoeven for the idea:
+ * Read values from given config space(s) for the first devices, -1 otherwise
+ *
+ */
+
+#include <linux/config.h>
+#ifdef CONFIG_AMIGA
+
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/delay.h>
+#include <linux/string.h>
+#include <linux/init.h>
+
+#include <asm/io.h>
+#include <asm/pci-bridge.h>
+#include <asm/machdep.h>
+
+#include "apus_pci.h"
+
+
+/* These definitions are mostly adapted from pm2fb.c */
+
+#undef APUS_PCI_MASTER_DEBUG
+#ifdef APUS_PCI_MASTER_DEBUG
+#define DPRINTK(a,b...) printk(KERN_DEBUG "apus_pci: %s: " a, __FUNCTION__ , ## b)
+#else
+#define DPRINTK(a,b...)
+#endif
+
+/*
+ * The _DEFINITIVE_ memory mapping/unmapping functions.
+ * This is due to the fact that they're changing soooo often...
+ */
+#define DEFW() wmb()
+#define DEFR() rmb()
+#define DEFRW() mb()
+
+#define DEVNO(d) ((d)>>3)
+#define FNNO(d) ((d)&7)
+
+
+extern unsigned long powerup_PCI_present;
+
+static struct pci_controller *apus_hose;
+
+
+void *pci_io_base(unsigned int bus)
+{
+ return 0;
+}
+
+
+int
+apus_pcibios_read_config(struct pci_bus *bus, int devfn, int offset,
+ int len, u32 *val)
+{
+ int fnno = FNNO(devfn);
+ int devno = DEVNO(devfn);
+ volatile unsigned char *cfg_data;
+
+ if (bus->number > 0 || devno != 1) {
+ *val = ~0;
+ return PCIBIOS_DEVICE_NOT_FOUND;
+ }
+ /* base address + function offset + offset ^ endianness conversion */
+ /* XXX the fnno<<5 bit seems wacky -- paulus */
+ cfg_data = apus_hose->cfg_data + (fnno<<5) + (offset ^ (len - 1));
+ switch (len) {
+ case 1:
+ *val = readb(cfg_data);
+ break;
+ case 2:
+ *val = readw(cfg_data);
+ break;
+ default:
+ *val = readl(cfg_data);
+ break;
+ }
+
+ DPRINTK("read b: 0x%x, d: 0x%x, f: 0x%x, o: 0x%x, l: %d, v: 0x%x\n",
+ bus->number, devfn>>3, devfn&7, offset, len, *val);
+ return PCIBIOS_SUCCESSFUL;
+}
+
+int
+apus_pcibios_write_config(struct pci_bus *bus, int devfn, int offset,
+ int len, u32 *val)
+{
+ int fnno = FNNO(devfn);
+ int devno = DEVNO(devfn);
+ volatile unsigned char *cfg_data;
+
+ if (bus->number > 0 || devno != 1) {
+ return PCIBIOS_DEVICE_NOT_FOUND;
+ }
+ /* base address + function offset + offset ^ endianness conversion */
+ /* XXX the fnno<<5 bit seems wacky -- paulus */
+ cfg_data = apus_hose->cfg_data + (fnno<<5) + (offset ^ (len - 1));
+ switch (len) {
+ case 1:
+ writeb(val, cfg_data); DEFW();
+ break;
+ case 2:
+ writew(val, cfg_data); DEFW();
+ break;
+ default:
+ writel(val, cfg_data); DEFW();
+ break;
+ }
+
+ DPRINTK("write b: 0x%x, d: 0x%x, f: 0x%x, o: 0x%x, l: %d, v: 0x%x\n",
+ bus->number, devfn>>3, devfn&7, offset, len, val);
+ return PCIBIOS_SUCCESSFUL;
+}
+
+static struct pci_ops apus_pci_ops = {
+ apus_pcibios_read_config,
+ apus_pcibios_write_config
+};
+
+static struct resource pci_mem = { "B/CVisionPPC PCI mem", CVPPC_FB_APERTURE_ONE, CVPPC_PCI_CONFIG, IORESOURCE_MEM };
+
+void __init
+apus_pcibios_fixup(void)
+{
+/* struct pci_dev *dev = pci_find_slot(0, 1<<3);
+ unsigned int reg, val, offset;*/
+
+ /* FIXME: interrupt? */
+ /*dev->interrupt = xxx;*/
+
+ request_resource(&iomem_resource, &pci_mem);
+ printk("%s: PCI mem resource requested\n", __FUNCTION__);
+}
+
+static void __init apus_pcibios_fixup_bus(struct pci_bus *bus)
+{
+ bus->resource[1] = &pci_mem;
+}
+
+
+/*
+ * This is from pm2fb.c again
+ *
+ * Check if PCI (B/CVisionPPC) is available, initialize it and set up
+ * the pcibios_* pointers
+ */
+
+
+void __init
+apus_setup_pci_ptrs(void)
+{
+ if (!powerup_PCI_present) {
+ DPRINTK("no PCI bridge detected\n");
+ return;
+ }
+ DPRINTK("Phase5 B/CVisionPPC PCI bridge detected.\n");
+
+ apus_hose = pcibios_alloc_controller();
+ if (!apus_hose) {
+ printk("apus_pci: Can't allocate PCI controller structure\n");
+ return;
+ }
+
+ if (!(apus_hose->cfg_data = ioremap(CVPPC_PCI_CONFIG, 256))) {
+ printk("apus_pci: unable to map PCI config region\n");
+ return;
+ }
+
+ if (!(apus_hose->cfg_addr = ioremap(CSPPC_PCI_BRIDGE, 256))) {
+ printk("apus_pci: unable to map PCI bridge\n");
+ return;
+ }
+
+ writel(CSPPCF_BRIDGE_BIG_ENDIAN, apus_hose->cfg_addr + CSPPC_BRIDGE_ENDIAN);
+ DEFW();
+
+ writel(CVPPC_REGS_REGION, apus_hose->cfg_data+ PCI_BASE_ADDRESS_0);
+ DEFW();
+ writel(CVPPC_FB_APERTURE_ONE, apus_hose->cfg_data + PCI_BASE_ADDRESS_1);
+ DEFW();
+ writel(CVPPC_FB_APERTURE_TWO, apus_hose->cfg_data + PCI_BASE_ADDRESS_2);
+ DEFW();
+ writel(CVPPC_ROM_ADDRESS, apus_hose->cfg_data + PCI_ROM_ADDRESS);
+ DEFW();
+
+ writel(0xef000000 | PCI_COMMAND_IO | PCI_COMMAND_MEMORY |
+ PCI_COMMAND_MASTER, apus_hose->cfg_data + PCI_COMMAND);
+ DEFW();
+
+ apus_hose->first_busno = 0;
+ apus_hose->last_busno = 0;
+ apus_hose->ops = &apus_pci_ops;
+ ppc_md.pcibios_fixup = apus_pcibios_fixup;
+ ppc_md.pcibios_fixup_bus = apus_pcibios_fixup_bus;
+
+ return;
+}
+
+#endif /* CONFIG_AMIGA */
diff --git a/arch/ppc/platforms/apus_pci.h b/arch/ppc/platforms/apus_pci.h
new file mode 100644
index 0000000..f15974a
--- /dev/null
+++ b/arch/ppc/platforms/apus_pci.h
@@ -0,0 +1,34 @@
+/*
+ * Phase5 CybervisionPPC (TVP4020) definitions for the Permedia2 framebuffer
+ * driver.
+ *
+ * Copyright (c) 1998-1999 Ilario Nardinocchi (nardinoc@CS.UniBO.IT)
+ * --------------------------------------------------------------------------
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file README.legal in the main directory of this archive
+ * for more details.
+ */
+
+#ifndef APUS_PCI_H
+#define APUS_PCI_H
+
+
+#define CSPPC_PCI_BRIDGE 0xfffe0000
+#define CSPPC_BRIDGE_ENDIAN 0x0000
+#define CSPPC_BRIDGE_INT 0x0010
+
+#define CVPPC_PCI_CONFIG 0xfffc0000
+#define CVPPC_ROM_ADDRESS 0xe2000001
+#define CVPPC_REGS_REGION 0xef000000
+#define CVPPC_FB_APERTURE_ONE 0xe0000000
+#define CVPPC_FB_APERTURE_TWO 0xe1000000
+#define CVPPC_FB_SIZE 0x00800000
+
+/* CVPPC_BRIDGE_ENDIAN */
+#define CSPPCF_BRIDGE_BIG_ENDIAN 0x02
+
+/* CVPPC_BRIDGE_INT */
+#define CSPPCF_BRIDGE_ACTIVE_INT2 0x01
+
+
+#endif /* APUS_PCI_H */
diff --git a/arch/ppc/platforms/apus_setup.c b/arch/ppc/platforms/apus_setup.c
new file mode 100644
index 0000000..2f74fde
--- /dev/null
+++ b/arch/ppc/platforms/apus_setup.c
@@ -0,0 +1,815 @@
+/*
+ * arch/ppc/platforms/apus_setup.c
+ *
+ * Copyright (C) 1998, 1999 Jesper Skov
+ *
+ * Basically what is needed to replace functionality found in
+ * arch/m68k allowing Amiga drivers to work under APUS.
+ * Bits of code and/or ideas from arch/m68k and arch/ppc files.
+ *
+ * TODO:
+ * This file needs a *really* good cleanup. Restructure and optimize.
+ * Make sure it can be compiled for non-APUS configs. Begin to move
+ * Amiga specific stuff into mach/amiga.
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/init.h>
+#include <linux/initrd.h>
+#include <linux/seq_file.h>
+
+/* Needs INITSERIAL call in head.S! */
+#undef APUS_DEBUG
+
+#include <asm/bootinfo.h>
+#include <asm/setup.h>
+#include <asm/amigahw.h>
+#include <asm/amigaints.h>
+#include <asm/amigappc.h>
+#include <asm/pgtable.h>
+#include <asm/dma.h>
+#include <asm/machdep.h>
+#include <asm/time.h>
+
+unsigned long m68k_machtype;
+char debug_device[6] = "";
+
+extern void amiga_init_IRQ(void);
+
+extern void apus_setup_pci_ptrs(void);
+
+void (*mach_sched_init) (void (*handler)(int, void *, struct pt_regs *)) __initdata = NULL;
+/* machine dependent irq functions */
+void (*mach_init_IRQ) (void) __initdata = NULL;
+void (*(*mach_default_handler)[]) (int, void *, struct pt_regs *) = NULL;
+void (*mach_get_model) (char *model) = NULL;
+int (*mach_get_hardware_list) (char *buffer) = NULL;
+int (*mach_get_irq_list) (struct seq_file *, void *) = NULL;
+void (*mach_process_int) (int, struct pt_regs *) = NULL;
+/* machine dependent timer functions */
+unsigned long (*mach_gettimeoffset) (void);
+void (*mach_gettod) (int*, int*, int*, int*, int*, int*);
+int (*mach_hwclk) (int, struct hwclk_time*) = NULL;
+int (*mach_set_clock_mmss) (unsigned long) = NULL;
+void (*mach_reset)( void );
+long mach_max_dma_address = 0x00ffffff; /* default set to the lower 16MB */
+#if defined(CONFIG_AMIGA_FLOPPY)
+void (*mach_floppy_setup) (char *, int *) __initdata = NULL;
+#endif
+#ifdef CONFIG_HEARTBEAT
+void (*mach_heartbeat) (int) = NULL;
+extern void apus_heartbeat (void);
+#endif
+
+extern unsigned long amiga_model;
+extern unsigned decrementer_count;/* count value for 1e6/HZ microseconds */
+extern unsigned count_period_num; /* 1 decrementer count equals */
+extern unsigned count_period_den; /* count_period_num / count_period_den us */
+
+int num_memory = 0;
+struct mem_info memory[NUM_MEMINFO];/* memory description */
+/* FIXME: Duplicate memory data to avoid conflicts with m68k shared code. */
+int m68k_realnum_memory = 0;
+struct mem_info m68k_memory[NUM_MEMINFO];/* memory description */
+
+struct mem_info ramdisk;
+
+extern void amiga_floppy_setup(char *, int *);
+extern void config_amiga(void);
+
+static int __60nsram = 0;
+
+/* for cpuinfo */
+static int __bus_speed = 0;
+static int __speed_test_failed = 0;
+
+/********************************************** COMPILE PROTECTION */
+/* Provide some stubs that links to Amiga specific functions.
+ * This allows CONFIG_APUS to be removed from generic PPC files while
+ * preventing link errors for other PPC targets.
+ */
+unsigned long apus_get_rtc_time(void)
+{
+#ifdef CONFIG_APUS
+ extern unsigned long m68k_get_rtc_time(void);
+
+ return m68k_get_rtc_time ();
+#else
+ return 0;
+#endif
+}
+
+int apus_set_rtc_time(unsigned long nowtime)
+{
+#ifdef CONFIG_APUS
+ extern int m68k_set_rtc_time(unsigned long nowtime);
+
+ return m68k_set_rtc_time (nowtime);
+#else
+ return 0;
+#endif
+}
+
+/*********************************************************** SETUP */
+/* From arch/m68k/kernel/setup.c. */
+void __init apus_setup_arch(void)
+{
+#ifdef CONFIG_APUS
+ extern char cmd_line[];
+ int i;
+ char *p, *q;
+
+ /* Let m68k-shared code know it should do the Amiga thing. */
+ m68k_machtype = MACH_AMIGA;
+
+ /* Parse the command line for arch-specific options.
+ * For the m68k, this is currently only "debug=xxx" to enable printing
+ * certain kernel messages to some machine-specific device. */
+ for( p = cmd_line; p && *p; ) {
+ i = 0;
+ if (!strncmp( p, "debug=", 6 )) {
+ strlcpy( debug_device, p+6, sizeof(debug_device) );
+ if ((q = strchr( debug_device, ' ' ))) *q = 0;
+ i = 1;
+ } else if (!strncmp( p, "60nsram", 7 )) {
+ APUS_WRITE (APUS_REG_WAITSTATE,
+ REGWAITSTATE_SETRESET
+ |REGWAITSTATE_PPCR
+ |REGWAITSTATE_PPCW);
+ __60nsram = 1;
+ i = 1;
+ }
+
+ if (i) {
+ /* option processed, delete it */
+ if ((q = strchr( p, ' ' )))
+ strcpy( p, q+1 );
+ else
+ *p = 0;
+ } else {
+ if ((p = strchr( p, ' ' ))) ++p;
+ }
+ }
+
+ config_amiga();
+
+#if 0 /* Enable for logging - also include logging.o in Makefile rule */
+ {
+#define LOG_SIZE 4096
+ void* base;
+
+ /* Throw away some memory - the P5 firmare stomps on top
+ * of CHIP memory during bootup.
+ */
+ amiga_chip_alloc(0x1000);
+
+ base = amiga_chip_alloc(LOG_SIZE+sizeof(klog_data_t));
+ LOG_INIT(base, base+sizeof(klog_data_t), LOG_SIZE);
+ }
+#endif
+#endif
+}
+
+int
+apus_show_cpuinfo(struct seq_file *m)
+{
+ extern int __map_without_bats;
+ extern unsigned long powerup_PCI_present;
+
+ seq_printf(m, "machine\t\t: Amiga\n");
+ seq_printf(m, "bus speed\t: %d%s", __bus_speed,
+ (__speed_test_failed) ? " [failed]\n" : "\n");
+ seq_printf(m, "using BATs\t: %s\n",
+ (__map_without_bats) ? "No" : "Yes");
+ seq_printf(m, "ram speed\t: %dns\n", (__60nsram) ? 60 : 70);
+ seq_printf(m, "PCI bridge\t: %s\n",
+ (powerup_PCI_present) ? "Yes" : "No");
+ return 0;
+}
+
+static void get_current_tb(unsigned long long *time)
+{
+ __asm __volatile ("1:mftbu 4 \n\t"
+ " mftb 5 \n\t"
+ " mftbu 6 \n\t"
+ " cmpw 4,6 \n\t"
+ " bne 1b \n\t"
+ " stw 4,0(%0)\n\t"
+ " stw 5,4(%0)\n\t"
+ :
+ : "r" (time)
+ : "r4", "r5", "r6");
+}
+
+
+void apus_calibrate_decr(void)
+{
+#ifdef CONFIG_APUS
+ unsigned long freq;
+
+ /* This algorithm for determining the bus speed was
+ contributed by Ralph Schmidt. */
+ unsigned long long start, stop;
+ int bus_speed;
+ int speed_test_failed = 0;
+
+ {
+ unsigned long loop = amiga_eclock / 10;
+
+ get_current_tb (&start);
+ while (loop--) {
+ unsigned char tmp;
+
+ tmp = ciaa.pra;
+ }
+ get_current_tb (&stop);
+ }
+
+ bus_speed = (((unsigned long)(stop-start))*10*4) / 1000000;
+ if (AMI_1200 == amiga_model)
+ bus_speed /= 2;
+
+ if ((bus_speed >= 47) && (bus_speed < 53)) {
+ bus_speed = 50;
+ freq = 12500000;
+ } else if ((bus_speed >= 57) && (bus_speed < 63)) {
+ bus_speed = 60;
+ freq = 15000000;
+ } else if ((bus_speed >= 63) && (bus_speed < 69)) {
+ bus_speed = 67;
+ freq = 16666667;
+ } else {
+ printk ("APUS: Unable to determine bus speed (%d). "
+ "Defaulting to 50MHz", bus_speed);
+ bus_speed = 50;
+ freq = 12500000;
+ speed_test_failed = 1;
+ }
+
+ /* Ease diagnostics... */
+ {
+ extern int __map_without_bats;
+ extern unsigned long powerup_PCI_present;
+
+ printk ("APUS: BATs=%d, BUS=%dMHz",
+ (__map_without_bats) ? 0 : 1,
+ bus_speed);
+ if (speed_test_failed)
+ printk ("[FAILED - please report]");
+
+ printk (", RAM=%dns, PCI bridge=%d\n",
+ (__60nsram) ? 60 : 70,
+ (powerup_PCI_present) ? 1 : 0);
+
+ /* print a bit more if asked politely... */
+ if (!(ciaa.pra & 0x40)){
+ extern unsigned int bat_addrs[4][3];
+ int b;
+ for (b = 0; b < 4; ++b) {
+ printk ("APUS: BAT%d ", b);
+ printk ("%08x-%08x -> %08x\n",
+ bat_addrs[b][0],
+ bat_addrs[b][1],
+ bat_addrs[b][2]);
+ }
+ }
+
+ }
+
+ printk("time_init: decrementer frequency = %lu.%.6lu MHz\n",
+ freq/1000000, freq%1000000);
+ tb_ticks_per_jiffy = freq / HZ;
+ tb_to_us = mulhwu_scale_factor(freq, 1000000);
+
+ __bus_speed = bus_speed;
+ __speed_test_failed = speed_test_failed;
+#endif
+}
+
+void arch_gettod(int *year, int *mon, int *day, int *hour,
+ int *min, int *sec)
+{
+#ifdef CONFIG_APUS
+ if (mach_gettod)
+ mach_gettod(year, mon, day, hour, min, sec);
+ else
+ *year = *mon = *day = *hour = *min = *sec = 0;
+#endif
+}
+
+/* for "kbd-reset" cmdline param */
+__init
+void kbd_reset_setup(char *str, int *ints)
+{
+}
+
+/*********************************************************** FLOPPY */
+#if defined(CONFIG_AMIGA_FLOPPY)
+__init
+void floppy_setup(char *str, int *ints)
+{
+ if (mach_floppy_setup)
+ mach_floppy_setup (str, ints);
+}
+#endif
+
+/*********************************************************** MEMORY */
+#define KMAP_MAX 32
+unsigned long kmap_chunks[KMAP_MAX*3];
+int kmap_chunk_count = 0;
+
+/* From pgtable.h */
+static __inline__ pte_t *my_find_pte(struct mm_struct *mm,unsigned long va)
+{
+ pgd_t *dir = 0;
+ pmd_t *pmd = 0;
+ pte_t *pte = 0;
+
+ va &= PAGE_MASK;
+
+ dir = pgd_offset( mm, va );
+ if (dir)
+ {
+ pmd = pmd_offset(dir, va & PAGE_MASK);
+ if (pmd && pmd_present(*pmd))
+ {
+ pte = pte_offset(pmd, va);
+ }
+ }
+ return pte;
+}
+
+
+/* Again simulating an m68k/mm/kmap.c function. */
+void kernel_set_cachemode( unsigned long address, unsigned long size,
+ unsigned int cmode )
+{
+ unsigned long mask, flags;
+
+ switch (cmode)
+ {
+ case IOMAP_FULL_CACHING:
+ mask = ~(_PAGE_NO_CACHE | _PAGE_GUARDED);
+ flags = 0;
+ break;
+ case IOMAP_NOCACHE_SER:
+ mask = ~0;
+ flags = (_PAGE_NO_CACHE | _PAGE_GUARDED);
+ break;
+ default:
+ panic ("kernel_set_cachemode() doesn't support mode %d\n",
+ cmode);
+ break;
+ }
+
+ size /= PAGE_SIZE;
+ address &= PAGE_MASK;
+ while (size--)
+ {
+ pte_t *pte;
+
+ pte = my_find_pte(&init_mm, address);
+ if ( !pte )
+ {
+ printk("pte NULL in kernel_set_cachemode()\n");
+ return;
+ }
+
+ pte_val (*pte) &= mask;
+ pte_val (*pte) |= flags;
+ flush_tlb_page(find_vma(&init_mm,address),address);
+
+ address += PAGE_SIZE;
+ }
+}
+
+unsigned long mm_ptov (unsigned long paddr)
+{
+ unsigned long ret;
+ if (paddr < 16*1024*1024)
+ ret = ZTWO_VADDR(paddr);
+ else {
+ int i;
+
+ for (i = 0; i < kmap_chunk_count;){
+ unsigned long phys = kmap_chunks[i++];
+ unsigned long size = kmap_chunks[i++];
+ unsigned long virt = kmap_chunks[i++];
+ if (paddr >= phys
+ && paddr < (phys + size)){
+ ret = virt + paddr - phys;
+ goto exit;
+ }
+ }
+
+ ret = (unsigned long) __va(paddr);
+ }
+exit:
+#ifdef DEBUGPV
+ printk ("PTOV(%lx)=%lx\n", paddr, ret);
+#endif
+ return ret;
+}
+
+int mm_end_of_chunk (unsigned long addr, int len)
+{
+ if (memory[0].addr + memory[0].size == addr + len)
+ return 1;
+ return 0;
+}
+
+/*********************************************************** CACHE */
+
+#define L1_CACHE_BYTES 32
+#define MAX_CACHE_SIZE 8192
+void cache_push(__u32 addr, int length)
+{
+ addr = mm_ptov(addr);
+
+ if (MAX_CACHE_SIZE < length)
+ length = MAX_CACHE_SIZE;
+
+ while(length > 0){
+ __asm ("dcbf 0,%0\n\t"
+ : : "r" (addr));
+ addr += L1_CACHE_BYTES;
+ length -= L1_CACHE_BYTES;
+ }
+ /* Also flush trailing block */
+ __asm ("dcbf 0,%0\n\t"
+ "sync \n\t"
+ : : "r" (addr));
+}
+
+void cache_clear(__u32 addr, int length)
+{
+ if (MAX_CACHE_SIZE < length)
+ length = MAX_CACHE_SIZE;
+
+ addr = mm_ptov(addr);
+
+ __asm ("dcbf 0,%0\n\t"
+ "sync \n\t"
+ "icbi 0,%0 \n\t"
+ "isync \n\t"
+ : : "r" (addr));
+
+ addr += L1_CACHE_BYTES;
+ length -= L1_CACHE_BYTES;
+
+ while(length > 0){
+ __asm ("dcbf 0,%0\n\t"
+ "sync \n\t"
+ "icbi 0,%0 \n\t"
+ "isync \n\t"
+ : : "r" (addr));
+ addr += L1_CACHE_BYTES;
+ length -= L1_CACHE_BYTES;
+ }
+
+ __asm ("dcbf 0,%0\n\t"
+ "sync \n\t"
+ "icbi 0,%0 \n\t"
+ "isync \n\t"
+ : : "r" (addr));
+}
+
+/****************************************************** from setup.c */
+void
+apus_restart(char *cmd)
+{
+ local_irq_disable();
+
+ APUS_WRITE(APUS_REG_LOCK,
+ REGLOCK_BLACKMAGICK1|REGLOCK_BLACKMAGICK2);
+ APUS_WRITE(APUS_REG_LOCK,
+ REGLOCK_BLACKMAGICK1|REGLOCK_BLACKMAGICK3);
+ APUS_WRITE(APUS_REG_LOCK,
+ REGLOCK_BLACKMAGICK2|REGLOCK_BLACKMAGICK3);
+ APUS_WRITE(APUS_REG_SHADOW, REGSHADOW_SELFRESET);
+ APUS_WRITE(APUS_REG_RESET, REGRESET_AMIGARESET);
+ for(;;);
+}
+
+void
+apus_power_off(void)
+{
+ for (;;);
+}
+
+void
+apus_halt(void)
+{
+ apus_restart(NULL);
+}
+
+/****************************************************** IRQ stuff */
+
+static unsigned char last_ipl[8];
+
+int apus_get_irq(struct pt_regs* regs)
+{
+ unsigned char ipl_emu, mask;
+ unsigned int level;
+
+ APUS_READ(APUS_IPL_EMU, ipl_emu);
+ level = (ipl_emu >> 3) & IPLEMU_IPLMASK;
+ mask = IPLEMU_SETRESET|IPLEMU_DISABLEINT|level;
+ level ^= 7;
+
+ /* Save previous IPL value */
+ if (last_ipl[level])
+ return -2;
+ last_ipl[level] = ipl_emu;
+
+ /* Set to current IPL value */
+ APUS_WRITE(APUS_IPL_EMU, mask);
+ APUS_WRITE(APUS_IPL_EMU, IPLEMU_DISABLEINT|level);
+
+
+#ifdef __INTERRUPT_DEBUG
+ printk("<%d:%d>", level, ~ipl_emu & IPLEMU_IPLMASK);
+#endif
+ return level + IRQ_AMIGA_AUTO;
+}
+
+void apus_end_irq(unsigned int irq)
+{
+ unsigned char ipl_emu;
+ unsigned int level = irq - IRQ_AMIGA_AUTO;
+#ifdef __INTERRUPT_DEBUG
+ printk("{%d}", ~last_ipl[level] & IPLEMU_IPLMASK);
+#endif
+ /* Restore IPL to the previous value */
+ ipl_emu = last_ipl[level] & IPLEMU_IPLMASK;
+ APUS_WRITE(APUS_IPL_EMU, IPLEMU_SETRESET|IPLEMU_DISABLEINT|ipl_emu);
+ last_ipl[level] = 0;
+ ipl_emu ^= 7;
+ APUS_WRITE(APUS_IPL_EMU, IPLEMU_DISABLEINT|ipl_emu);
+}
+
+/****************************************************** debugging */
+
+/* some serial hardware definitions */
+#define SDR_OVRUN (1<<15)
+#define SDR_RBF (1<<14)
+#define SDR_TBE (1<<13)
+#define SDR_TSRE (1<<12)
+
+#define AC_SETCLR (1<<15)
+#define AC_UARTBRK (1<<11)
+
+#define SER_DTR (1<<7)
+#define SER_RTS (1<<6)
+#define SER_DCD (1<<5)
+#define SER_CTS (1<<4)
+#define SER_DSR (1<<3)
+
+static __inline__ void ser_RTSon(void)
+{
+ ciab.pra &= ~SER_RTS; /* active low */
+}
+
+int __debug_ser_out( unsigned char c )
+{
+ custom.serdat = c | 0x100;
+ mb();
+ while (!(custom.serdatr & 0x2000))
+ barrier();
+ return 1;
+}
+
+unsigned char __debug_ser_in( void )
+{
+ unsigned char c;
+
+ /* XXX: is that ok?? derived from amiga_ser.c... */
+ while( !(custom.intreqr & IF_RBF) )
+ barrier();
+ c = custom.serdatr;
+ /* clear the interrupt, so that another character can be read */
+ custom.intreq = IF_RBF;
+ return c;
+}
+
+int __debug_serinit( void )
+{
+ unsigned long flags;
+
+ local_irq_save(flags);
+
+ /* turn off Rx and Tx interrupts */
+ custom.intena = IF_RBF | IF_TBE;
+
+ /* clear any pending interrupt */
+ custom.intreq = IF_RBF | IF_TBE;
+
+ local_irq_restore(flags);
+
+ /*
+ * set the appropriate directions for the modem control flags,
+ * and clear RTS and DTR
+ */
+ ciab.ddra |= (SER_DTR | SER_RTS); /* outputs */
+ ciab.ddra &= ~(SER_DCD | SER_CTS | SER_DSR); /* inputs */
+
+#ifdef CONFIG_KGDB
+ /* turn Rx interrupts on for GDB */
+ custom.intena = IF_SETCLR | IF_RBF;
+ ser_RTSon();
+#endif
+
+ return 0;
+}
+
+void __debug_print_hex(unsigned long x)
+{
+ int i;
+ char hexchars[] = "0123456789ABCDEF";
+
+ for (i = 0; i < 8; i++) {
+ __debug_ser_out(hexchars[(x >> 28) & 15]);
+ x <<= 4;
+ }
+ __debug_ser_out('\n');
+ __debug_ser_out('\r');
+}
+
+void __debug_print_string(char* s)
+{
+ unsigned char c;
+ while((c = *s++))
+ __debug_ser_out(c);
+ __debug_ser_out('\n');
+ __debug_ser_out('\r');
+}
+
+static void apus_progress(char *s, unsigned short value)
+{
+ __debug_print_string(s);
+}
+
+/****************************************************** init */
+
+/* The number of spurious interrupts */
+volatile unsigned int num_spurious;
+
+extern struct irqaction amiga_sys_irqaction[AUTO_IRQS];
+
+
+extern void amiga_enable_irq(unsigned int irq);
+extern void amiga_disable_irq(unsigned int irq);
+
+struct hw_interrupt_type amiga_sys_irqctrl = {
+ .typename = "Amiga IPL",
+ .end = apus_end_irq,
+};
+
+struct hw_interrupt_type amiga_irqctrl = {
+ .typename = "Amiga ",
+ .enable = amiga_enable_irq,
+ .disable = amiga_disable_irq,
+};
+
+#define HARDWARE_MAPPED_SIZE (512*1024)
+unsigned long __init apus_find_end_of_memory(void)
+{
+ int shadow = 0;
+ unsigned long total;
+
+ /* The memory size reported by ADOS excludes the 512KB
+ reserved for PPC exception registers and possibly 512KB
+ containing a shadow of the ADOS ROM. */
+ {
+ unsigned long size = memory[0].size;
+
+ /* If 2MB aligned, size was probably user
+ specified. We can't tell anything about shadowing
+ in this case so skip shadow assignment. */
+ if (0 != (size & 0x1fffff)){
+ /* Align to 512KB to ensure correct handling
+ of both memfile and system specified
+ sizes. */
+ size = ((size+0x0007ffff) & 0xfff80000);
+ /* If memory is 1MB aligned, assume
+ shadowing. */
+ shadow = !(size & 0x80000);
+ }
+
+ /* Add the chunk that ADOS does not see. by aligning
+ the size to the nearest 2MB limit upwards. */
+ memory[0].size = ((size+0x001fffff) & 0xffe00000);
+ }
+
+ ppc_memstart = memory[0].addr;
+ ppc_memoffset = PAGE_OFFSET - PPC_MEMSTART;
+ total = memory[0].size;
+
+ /* Remove the memory chunks that are controlled by special
+ Phase5 hardware. */
+
+ /* Remove the upper 512KB if it contains a shadow of
+ the ADOS ROM. FIXME: It might be possible to
+ disable this shadow HW. Check the booter
+ (ppc_boot.c) */
+ if (shadow)
+ total -= HARDWARE_MAPPED_SIZE;
+
+ /* Remove the upper 512KB where the PPC exception
+ vectors are mapped. */
+ total -= HARDWARE_MAPPED_SIZE;
+
+ /* Linux/APUS only handles one block of memory -- the one on
+ the PowerUP board. Other system memory is horrible slow in
+ comparison. The user can use other memory for swapping
+ using the z2ram device. */
+ return total;
+}
+
+static void __init
+apus_map_io(void)
+{
+ /* Map PPC exception vectors. */
+ io_block_mapping(0xfff00000, 0xfff00000, 0x00020000, _PAGE_KERNEL);
+ /* Map chip and ZorroII memory */
+ io_block_mapping(zTwoBase, 0x00000000, 0x01000000, _PAGE_IO);
+}
+
+__init
+void apus_init_IRQ(void)
+{
+ struct irqaction *action;
+ int i;
+
+#ifdef CONFIG_PCI
+ apus_setup_pci_ptrs();
+#endif
+
+ for ( i = 0 ; i < AMI_IRQS; i++ ) {
+ irq_desc[i].status = IRQ_LEVEL;
+ if (i < IRQ_AMIGA_AUTO) {
+ irq_desc[i].handler = &amiga_irqctrl;
+ } else {
+ irq_desc[i].handler = &amiga_sys_irqctrl;
+ action = &amiga_sys_irqaction[i-IRQ_AMIGA_AUTO];
+ if (action->name)
+ setup_irq(i, action);
+ }
+ }
+
+ amiga_init_IRQ();
+
+}
+
+__init
+void platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
+ unsigned long r6, unsigned long r7)
+{
+ extern int parse_bootinfo(const struct bi_record *);
+ extern char _end[];
+
+ /* Parse bootinfo. The bootinfo is located right after
+ the kernel bss */
+ parse_bootinfo((const struct bi_record *)&_end);
+#ifdef CONFIG_BLK_DEV_INITRD
+ /* Take care of initrd if we have one. Use data from
+ bootinfo to avoid the need to initialize PPC
+ registers when kernel is booted via a PPC reset. */
+ if ( ramdisk.addr ) {
+ initrd_start = (unsigned long) __va(ramdisk.addr);
+ initrd_end = (unsigned long)
+ __va(ramdisk.size + ramdisk.addr);
+ }
+#endif /* CONFIG_BLK_DEV_INITRD */
+
+ ISA_DMA_THRESHOLD = 0x00ffffff;
+
+ ppc_md.setup_arch = apus_setup_arch;
+ ppc_md.show_cpuinfo = apus_show_cpuinfo;
+ ppc_md.init_IRQ = apus_init_IRQ;
+ ppc_md.get_irq = apus_get_irq;
+
+#ifdef CONFIG_HEARTBEAT
+ ppc_md.heartbeat = apus_heartbeat;
+ ppc_md.heartbeat_count = 1;
+#endif
+#ifdef APUS_DEBUG
+ __debug_serinit();
+ ppc_md.progress = apus_progress;
+#endif
+ ppc_md.init = NULL;
+
+ ppc_md.restart = apus_restart;
+ ppc_md.power_off = apus_power_off;
+ ppc_md.halt = apus_halt;
+
+ ppc_md.time_init = NULL;
+ ppc_md.set_rtc_time = apus_set_rtc_time;
+ ppc_md.get_rtc_time = apus_get_rtc_time;
+ ppc_md.calibrate_decr = apus_calibrate_decr;
+
+ ppc_md.find_end_of_memory = apus_find_end_of_memory;
+ ppc_md.setup_io_mappings = apus_map_io;
+}
diff --git a/arch/ppc/platforms/bseip.h b/arch/ppc/platforms/bseip.h
new file mode 100644
index 0000000..691f4a5
--- /dev/null
+++ b/arch/ppc/platforms/bseip.h
@@ -0,0 +1,38 @@
+/*
+ * A collection of structures, addresses, and values associated with
+ * the Bright Star Engineering ip-Engine board. Copied from the MBX stuff.
+ *
+ * Copyright (c) 1998 Dan Malek (dmalek@jlc.net)
+ */
+#ifndef __MACH_BSEIP_DEFS
+#define __MACH_BSEIP_DEFS
+
+#ifndef __ASSEMBLY__
+/* A Board Information structure that is given to a program when
+ * prom starts it up.
+ */
+typedef struct bd_info {
+ unsigned int bi_memstart; /* Memory start address */
+ unsigned int bi_memsize; /* Memory (end) size in bytes */
+ unsigned int bi_intfreq; /* Internal Freq, in Hz */
+ unsigned int bi_busfreq; /* Bus Freq, in Hz */
+ unsigned char bi_enetaddr[6];
+ unsigned int bi_baudrate;
+} bd_t;
+
+extern bd_t m8xx_board_info;
+
+/* Memory map is configured by the PROM startup.
+ * All we need to get started is the IMMR.
+ */
+#define IMAP_ADDR ((uint)0xff000000)
+#define IMAP_SIZE ((uint)(64 * 1024))
+#define PCMCIA_MEM_ADDR ((uint)0x04000000)
+#define PCMCIA_MEM_SIZE ((uint)(64 * 1024))
+#endif /* !__ASSEMBLY__ */
+
+/* We don't use the 8259.
+*/
+#define NR_8259_INTS 0
+
+#endif
diff --git a/arch/ppc/platforms/ccm.h b/arch/ppc/platforms/ccm.h
new file mode 100644
index 0000000..edb87b5
--- /dev/null
+++ b/arch/ppc/platforms/ccm.h
@@ -0,0 +1,28 @@
+/*
+ * Siemens Card Controller Module specific definitions
+ *
+ * Copyright (C) 2001-2002 Wolfgang Denk (wd@denx.de)
+ */
+
+#ifndef __MACH_CCM_H
+#define __MACH_CCM_H
+
+#include <linux/config.h>
+
+#include <asm/ppcboot.h>
+
+#define CCM_IMMR_BASE 0xF0000000 /* phys. addr of IMMR */
+#define CCM_IMAP_SIZE (64 * 1024) /* size of mapped area */
+
+#define IMAP_ADDR CCM_IMMR_BASE /* physical base address of IMMR area */
+#define IMAP_SIZE CCM_IMAP_SIZE /* mapped size of IMMR area */
+
+#define FEC_INTERRUPT 13 /* = SIU_LEVEL6 */
+#define DEC_INTERRUPT 11 /* = SIU_LEVEL5 */
+#define CPM_INTERRUPT 9 /* = SIU_LEVEL4 */
+
+/* We don't use the 8259.
+*/
+#define NR_8259_INTS 0
+
+#endif /* __MACH_CCM_H */
diff --git a/arch/ppc/platforms/chestnut.c b/arch/ppc/platforms/chestnut.c
new file mode 100644
index 0000000..7786818
--- /dev/null
+++ b/arch/ppc/platforms/chestnut.c
@@ -0,0 +1,580 @@
+/*
+ * arch/ppc/platforms/chestnut.c
+ *
+ * Board setup routines for IBM Chestnut
+ *
+ * Author: <source@mvista.com>
+ *
+ * <2004> (c) MontaVista Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+
+#include <linux/config.h>
+#include <linux/stddef.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/reboot.h>
+#include <linux/kdev_t.h>
+#include <linux/major.h>
+#include <linux/blkdev.h>
+#include <linux/console.h>
+#include <linux/root_dev.h>
+#include <linux/initrd.h>
+#include <linux/delay.h>
+#include <linux/seq_file.h>
+#include <linux/ide.h>
+#include <linux/serial.h>
+#include <linux/serial_core.h>
+#include <linux/mtd/physmap.h>
+#include <asm/system.h>
+#include <asm/pgtable.h>
+#include <asm/page.h>
+#include <asm/time.h>
+#include <asm/dma.h>
+#include <asm/io.h>
+#include <linux/irq.h>
+#include <asm/hw_irq.h>
+#include <asm/machdep.h>
+#include <asm/kgdb.h>
+#include <asm/bootinfo.h>
+#include <asm/mv64x60.h>
+#include <platforms/chestnut.h>
+
+static void __iomem *sram_base; /* Virtual addr of Internal SRAM */
+static void __iomem *cpld_base; /* Virtual addr of CPLD Regs */
+
+static mv64x60_handle_t bh;
+
+extern void gen550_progress(char *, unsigned short);
+extern void gen550_init(int, struct uart_port *);
+extern void mv64360_pcibios_fixup(mv64x60_handle_t *bh);
+
+#define BIT(x) (1<<x)
+#define CHESTNUT_PRESERVE_MASK (BIT(MV64x60_CPU2DEV_0_WIN) | \
+ BIT(MV64x60_CPU2DEV_1_WIN) | \
+ BIT(MV64x60_CPU2DEV_2_WIN) | \
+ BIT(MV64x60_CPU2DEV_3_WIN) | \
+ BIT(MV64x60_CPU2BOOT_WIN))
+/**************************************************************************
+ * FUNCTION: chestnut_calibrate_decr
+ *
+ * DESCRIPTION: initialize decrementer interrupt frequency (used as system
+ * timer)
+ *
+ ****/
+static void __init
+chestnut_calibrate_decr(void)
+{
+ ulong freq;
+
+ freq = CHESTNUT_BUS_SPEED / 4;
+
+ printk("time_init: decrementer frequency = %lu.%.6lu MHz\n",
+ freq/1000000, freq%1000000);
+
+ tb_ticks_per_jiffy = freq / HZ;
+ tb_to_us = mulhwu_scale_factor(freq, 1000000);
+}
+
+static int
+chestnut_show_cpuinfo(struct seq_file *m)
+{
+ seq_printf(m, "vendor\t\t: IBM\n");
+ seq_printf(m, "machine\t\t: 750FX/GX Eval Board (Chestnut/Buckeye)\n");
+
+ return 0;
+}
+
+/**************************************************************************
+ * FUNCTION: chestnut_find_end_of_memory
+ *
+ * DESCRIPTION: ppc_md memory size callback
+ *
+ ****/
+unsigned long __init
+chestnut_find_end_of_memory(void)
+{
+ static int mem_size = 0;
+
+ if (mem_size == 0) {
+ mem_size = mv64x60_get_mem_size(CONFIG_MV64X60_NEW_BASE,
+ MV64x60_TYPE_MV64460);
+ }
+ return mem_size;
+}
+
+#if defined(CONFIG_SERIAL_8250)
+static void __init
+chestnut_early_serial_map(void)
+{
+ struct uart_port port;
+
+ /* Setup serial port access */
+ memset(&port, 0, sizeof(port));
+ port.uartclk = BASE_BAUD * 16;
+ port.irq = UART0_INT;
+ port.flags = STD_COM_FLAGS | UPF_IOREMAP;
+ port.iotype = SERIAL_IO_MEM;
+ port.mapbase = CHESTNUT_UART0_IO_BASE;
+ port.regshift = 0;
+
+ if (early_serial_setup(&port) != 0)
+ printk("Early serial init of port 0 failed\n");
+
+ /* Assume early_serial_setup() doesn't modify serial_req */
+ port.line = 1;
+ port.irq = UART1_INT;
+ port.mapbase = CHESTNUT_UART1_IO_BASE;
+
+ if (early_serial_setup(&port) != 0)
+ printk("Early serial init of port 1 failed\n");
+}
+#endif
+
+/**************************************************************************
+ * FUNCTION: chestnut_map_irq
+ *
+ * DESCRIPTION: 0 return since PCI IRQs not needed
+ *
+ ****/
+static int __init
+chestnut_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin)
+{
+ static char pci_irq_table[][4] = {
+ {CHESTNUT_PCI_SLOT0_IRQ, CHESTNUT_PCI_SLOT0_IRQ,
+ CHESTNUT_PCI_SLOT0_IRQ, CHESTNUT_PCI_SLOT0_IRQ},
+ {CHESTNUT_PCI_SLOT1_IRQ, CHESTNUT_PCI_SLOT1_IRQ,
+ CHESTNUT_PCI_SLOT1_IRQ, CHESTNUT_PCI_SLOT1_IRQ},
+ {CHESTNUT_PCI_SLOT2_IRQ, CHESTNUT_PCI_SLOT2_IRQ,
+ CHESTNUT_PCI_SLOT2_IRQ, CHESTNUT_PCI_SLOT2_IRQ},
+ {CHESTNUT_PCI_SLOT3_IRQ, CHESTNUT_PCI_SLOT3_IRQ,
+ CHESTNUT_PCI_SLOT3_IRQ, CHESTNUT_PCI_SLOT3_IRQ},
+ };
+ const long min_idsel = 1, max_idsel = 4, irqs_per_slot = 4;
+
+ return PCI_IRQ_TABLE_LOOKUP;
+}
+
+
+/**************************************************************************
+ * FUNCTION: chestnut_setup_bridge
+ *
+ * DESCRIPTION: initalize board-specific settings on the MV64360
+ *
+ ****/
+static void __init
+chestnut_setup_bridge(void)
+{
+ struct mv64x60_setup_info si;
+ int i;
+
+ if ( ppc_md.progress )
+ ppc_md.progress("chestnut_setup_bridge: enter", 0);
+
+ memset(&si, 0, sizeof(si));
+
+ si.phys_reg_base = CONFIG_MV64X60_NEW_BASE;
+
+ /* setup only PCI bus 0 (bus 1 not used) */
+ si.pci_0.enable_bus = 1;
+ si.pci_0.pci_io.cpu_base = CHESTNUT_PCI0_IO_PROC_ADDR;
+ si.pci_0.pci_io.pci_base_hi = 0;
+ si.pci_0.pci_io.pci_base_lo = CHESTNUT_PCI0_IO_PCI_ADDR;
+ si.pci_0.pci_io.size = CHESTNUT_PCI0_IO_SIZE;
+ si.pci_0.pci_io.swap = MV64x60_CPU2PCI_SWAP_NONE; /* no swapping */
+ si.pci_0.pci_mem[0].cpu_base = CHESTNUT_PCI0_MEM_PROC_ADDR;
+ si.pci_0.pci_mem[0].pci_base_hi = CHESTNUT_PCI0_MEM_PCI_HI_ADDR;
+ si.pci_0.pci_mem[0].pci_base_lo = CHESTNUT_PCI0_MEM_PCI_LO_ADDR;
+ si.pci_0.pci_mem[0].size = CHESTNUT_PCI0_MEM_SIZE;
+ si.pci_0.pci_mem[0].swap = MV64x60_CPU2PCI_SWAP_NONE; /* no swapping */
+ si.pci_0.pci_cmd_bits = 0;
+ si.pci_0.latency_timer = 0x80;
+
+ for (i=0; i<MV64x60_CPU2MEM_WINDOWS; i++) {
+#if defined(CONFIG_NOT_COHERENT_CACHE)
+ si.cpu_prot_options[i] = 0;
+ si.enet_options[i] = MV64360_ENET2MEM_SNOOP_NONE;
+ si.mpsc_options[i] = MV64360_MPSC2MEM_SNOOP_NONE;
+ si.idma_options[i] = MV64360_IDMA2MEM_SNOOP_NONE;
+
+ si.pci_1.acc_cntl_options[i] =
+ MV64360_PCI_ACC_CNTL_SNOOP_NONE |
+ MV64360_PCI_ACC_CNTL_SWAP_NONE |
+ MV64360_PCI_ACC_CNTL_MBURST_128_BYTES |
+ MV64360_PCI_ACC_CNTL_RDSIZE_256_BYTES;
+#else
+ si.cpu_prot_options[i] = 0;
+ si.enet_options[i] = MV64360_ENET2MEM_SNOOP_NONE; /* errata */
+ si.mpsc_options[i] = MV64360_MPSC2MEM_SNOOP_NONE; /* errata */
+ si.idma_options[i] = MV64360_IDMA2MEM_SNOOP_NONE; /* errata */
+
+ si.pci_1.acc_cntl_options[i] =
+ MV64360_PCI_ACC_CNTL_SNOOP_WB |
+ MV64360_PCI_ACC_CNTL_SWAP_NONE |
+ MV64360_PCI_ACC_CNTL_MBURST_32_BYTES |
+ MV64360_PCI_ACC_CNTL_RDSIZE_32_BYTES;
+#endif
+ }
+
+ /* Lookup host bridge - on CPU 0 - no SMP support */
+ if (mv64x60_init(&bh, &si)) {
+ printk("\n\nPCI Bridge initialization failed!\n");
+ }
+
+ pci_dram_offset = 0;
+ ppc_md.pci_swizzle = common_swizzle;
+ ppc_md.pci_map_irq = chestnut_map_irq;
+ ppc_md.pci_exclude_device = mv64x60_pci_exclude_device;
+
+ mv64x60_set_bus(&bh, 0, 0);
+ bh.hose_a->first_busno = 0;
+ bh.hose_a->last_busno = 0xff;
+ bh.hose_a->last_busno = pciauto_bus_scan(bh.hose_a, 0);
+}
+
+void __init
+chestnut_setup_peripherals(void)
+{
+ mv64x60_set_32bit_window(&bh, MV64x60_CPU2BOOT_WIN,
+ CHESTNUT_BOOT_8BIT_BASE, CHESTNUT_BOOT_8BIT_SIZE, 0);
+ bh.ci->enable_window_32bit(&bh, MV64x60_CPU2BOOT_WIN);
+
+ mv64x60_set_32bit_window(&bh, MV64x60_CPU2DEV_0_WIN,
+ CHESTNUT_32BIT_BASE, CHESTNUT_32BIT_SIZE, 0);
+ bh.ci->enable_window_32bit(&bh, MV64x60_CPU2DEV_0_WIN);
+
+ mv64x60_set_32bit_window(&bh, MV64x60_CPU2DEV_1_WIN,
+ CHESTNUT_CPLD_BASE, CHESTNUT_CPLD_SIZE, 0);
+ bh.ci->enable_window_32bit(&bh, MV64x60_CPU2DEV_1_WIN);
+ cpld_base = ioremap(CHESTNUT_CPLD_BASE, CHESTNUT_CPLD_SIZE);
+
+ mv64x60_set_32bit_window(&bh, MV64x60_CPU2DEV_2_WIN,
+ CHESTNUT_UART_BASE, CHESTNUT_UART_SIZE, 0);
+ bh.ci->enable_window_32bit(&bh, MV64x60_CPU2DEV_2_WIN);
+
+ mv64x60_set_32bit_window(&bh, MV64x60_CPU2DEV_3_WIN,
+ CHESTNUT_FRAM_BASE, CHESTNUT_FRAM_SIZE, 0);
+ bh.ci->enable_window_32bit(&bh, MV64x60_CPU2DEV_3_WIN);
+
+ mv64x60_set_32bit_window(&bh, MV64x60_CPU2SRAM_WIN,
+ CHESTNUT_INTERNAL_SRAM_BASE, MV64360_SRAM_SIZE, 0);
+ bh.ci->enable_window_32bit(&bh, MV64x60_CPU2SRAM_WIN);
+
+#ifdef CONFIG_NOT_COHERENT_CACHE
+ mv64x60_write(&bh, MV64360_SRAM_CONFIG, 0x001600b0);
+#else
+ mv64x60_write(&bh, MV64360_SRAM_CONFIG, 0x001600b2);
+#endif
+ sram_base = ioremap(CHESTNUT_INTERNAL_SRAM_BASE, MV64360_SRAM_SIZE);
+ memset(sram_base, 0, MV64360_SRAM_SIZE);
+
+ /*
+ * Configure MPP pins for PCI DMA
+ *
+ * PCI Slot GNT pin REQ pin
+ * 0 MPP16 MPP17
+ * 1 MPP18 MPP19
+ * 2 MPP20 MPP21
+ * 3 MPP22 MPP23
+ */
+ mv64x60_write(&bh, MV64x60_MPP_CNTL_2,
+ (0x1 << 0) | /* MPPSel16 PCI0_GNT[0] */
+ (0x1 << 4) | /* MPPSel17 PCI0_REQ[0] */
+ (0x1 << 8) | /* MPPSel18 PCI0_GNT[1] */
+ (0x1 << 12) | /* MPPSel19 PCI0_REQ[1] */
+ (0x1 << 16) | /* MPPSel20 PCI0_GNT[2] */
+ (0x1 << 20) | /* MPPSel21 PCI0_REQ[2] */
+ (0x1 << 24) | /* MPPSel22 PCI0_GNT[3] */
+ (0x1 << 28)); /* MPPSel23 PCI0_REQ[3] */
+ /*
+ * Set unused MPP pins for output, as per schematic note
+ *
+ * Unused Pins: MPP01, MPP02, MPP04, MPP05, MPP06
+ * MPP09, MPP10, MPP13, MPP14, MPP15
+ */
+ mv64x60_clr_bits(&bh, MV64x60_MPP_CNTL_0,
+ (0xf << 4) | /* MPPSel01 GPIO[1] */
+ (0xf << 8) | /* MPPSel02 GPIO[2] */
+ (0xf << 16) | /* MPPSel04 GPIO[4] */
+ (0xf << 20) | /* MPPSel05 GPIO[5] */
+ (0xf << 24)); /* MPPSel06 GPIO[6] */
+ mv64x60_clr_bits(&bh, MV64x60_MPP_CNTL_1,
+ (0xf << 4) | /* MPPSel09 GPIO[9] */
+ (0xf << 8) | /* MPPSel10 GPIO[10] */
+ (0xf << 20) | /* MPPSel13 GPIO[13] */
+ (0xf << 24) | /* MPPSel14 GPIO[14] */
+ (0xf << 28)); /* MPPSel15 GPIO[15] */
+ mv64x60_set_bits(&bh, MV64x60_GPP_IO_CNTL, /* Output */
+ BIT(1) | BIT(2) | BIT(4) | BIT(5) | BIT(6) |
+ BIT(9) | BIT(10) | BIT(13) | BIT(14) | BIT(15));
+
+ /*
+ * Configure the following MPP pins to indicate a level
+ * triggered interrupt
+ *
+ * MPP24 - Board Reset (just map the MPP & GPP for chestnut_reset)
+ * MPP25 - UART A (high)
+ * MPP26 - UART B (high)
+ * MPP28 - PCI Slot 3 (low)
+ * MPP29 - PCI Slot 2 (low)
+ * MPP30 - PCI Slot 1 (low)
+ * MPP31 - PCI Slot 0 (low)
+ */
+ mv64x60_clr_bits(&bh, MV64x60_MPP_CNTL_3,
+ BIT(3) | BIT(2) | BIT(1) | BIT(0) | /* MPP 24 */
+ BIT(7) | BIT(6) | BIT(5) | BIT(4) | /* MPP 25 */
+ BIT(11) | BIT(10) | BIT(9) | BIT(8) | /* MPP 26 */
+ BIT(19) | BIT(18) | BIT(17) | BIT(16) | /* MPP 28 */
+ BIT(23) | BIT(22) | BIT(21) | BIT(20) | /* MPP 29 */
+ BIT(27) | BIT(26) | BIT(25) | BIT(24) | /* MPP 30 */
+ BIT(31) | BIT(30) | BIT(29) | BIT(28)); /* MPP 31 */
+
+ /*
+ * Define GPP 25 (high), 26 (high), 28 (low), 29 (low), 30 (low),
+ * 31 (low) interrupt polarity input signal and level triggered
+ */
+ mv64x60_clr_bits(&bh, MV64x60_GPP_LEVEL_CNTL, BIT(25) | BIT(26));
+ mv64x60_set_bits(&bh, MV64x60_GPP_LEVEL_CNTL,
+ BIT(28) | BIT(29) | BIT(30) | BIT(31));
+ mv64x60_clr_bits(&bh, MV64x60_GPP_IO_CNTL,
+ BIT(25) | BIT(26) | BIT(28) | BIT(29) | BIT(30) |
+ BIT(31));
+
+ /* Config GPP interrupt controller to respond to level trigger */
+ mv64x60_set_bits(&bh, MV64360_COMM_ARBITER_CNTL, BIT(10));
+
+ /*
+ * Dismiss and then enable interrupt on GPP interrupt cause for CPU #0
+ */
+ mv64x60_write(&bh, MV64x60_GPP_INTR_CAUSE,
+ ~(BIT(25) | BIT(26) | BIT(28) | BIT(29) | BIT(30) |
+ BIT(31)));
+ mv64x60_set_bits(&bh, MV64x60_GPP_INTR_MASK,
+ BIT(25) | BIT(26) | BIT(28) | BIT(29) | BIT(30) |
+ BIT(31));
+
+ /*
+ * Dismiss and then enable interrupt on CPU #0 high cause register
+ * BIT27 summarizes GPP interrupts 24-31
+ */
+ mv64x60_set_bits(&bh, MV64360_IC_CPU0_INTR_MASK_HI, BIT(27));
+
+ if (ppc_md.progress)
+ ppc_md.progress("chestnut_setup_bridge: exit", 0);
+}
+
+/**************************************************************************
+ * FUNCTION: chestnut_setup_arch
+ *
+ * DESCRIPTION: ppc_md machine configuration callback
+ *
+ ****/
+static void __init
+chestnut_setup_arch(void)
+{
+ if (ppc_md.progress)
+ ppc_md.progress("chestnut_setup_arch: enter", 0);
+
+ /* init to some ~sane value until calibrate_delay() runs */
+ loops_per_jiffy = 50000000 / HZ;
+
+ /* if the time base value is greater than bus freq/4 (the TB and
+ * decrementer tick rate) + signed integer rollover value, we
+ * can spend a fair amount of time waiting for the rollover to
+ * happen. To get around this, initialize the time base register
+ * to a "safe" value.
+ */
+ set_tb(0, 0);
+
+#ifdef CONFIG_BLK_DEV_INITRD
+ if (initrd_start)
+ ROOT_DEV = Root_RAM0;
+ else
+#endif
+#ifdef CONFIG_ROOT_NFS
+ ROOT_DEV = Root_NFS;
+#else
+ ROOT_DEV = Root_SDA2;
+#endif
+
+ /*
+ * Set up the L2CR register.
+ */
+ _set_L2CR(_get_L2CR() | L2CR_L2E);
+
+ chestnut_setup_bridge();
+ chestnut_setup_peripherals();
+
+#ifdef CONFIG_DUMMY_CONSOLE
+ conswitchp = &dummy_con;
+#endif
+
+#if defined(CONFIG_SERIAL_8250)
+ chestnut_early_serial_map();
+#endif
+
+ /* Identify the system */
+ printk(KERN_INFO "System Identification: IBM 750FX/GX Eval Board\n");
+ printk(KERN_INFO "IBM 750FX/GX port (C) 2004 MontaVista Software, Inc."
+ " (source@mvista.com)\n");
+
+ if (ppc_md.progress)
+ ppc_md.progress("chestnut_setup_arch: exit", 0);
+}
+
+#ifdef CONFIG_MTD_PHYSMAP
+static struct mtd_partition ptbl;
+
+static int __init
+chestnut_setup_mtd(void)
+{
+ memset(&ptbl, 0, sizeof(ptbl));
+
+ ptbl.name = "User FS";
+ ptbl.size = CHESTNUT_32BIT_SIZE;
+
+ physmap_map.size = CHESTNUT_32BIT_SIZE;
+ physmap_set_partitions(&ptbl, 1);
+ return 0;
+}
+
+arch_initcall(chestnut_setup_mtd);
+#endif
+
+/**************************************************************************
+ * FUNCTION: chestnut_restart
+ *
+ * DESCRIPTION: ppc_md machine reset callback
+ * reset the board via the CPLD command register
+ *
+ ****/
+static void
+chestnut_restart(char *cmd)
+{
+ volatile ulong i = 10000000;
+
+ local_irq_disable();
+
+ /*
+ * Set CPLD Reg 3 bit 0 to 1 to allow MPP signals on reset to work
+ *
+ * MPP24 - board reset
+ */
+ writeb(0x1, cpld_base + 3);
+
+ /* GPP pin tied to MPP earlier */
+ mv64x60_set_bits(&bh, MV64x60_GPP_VALUE_SET, BIT(24));
+
+ while (i-- > 0);
+ panic("restart failed\n");
+}
+
+static void
+chestnut_halt(void)
+{
+ local_irq_disable();
+ for (;;);
+ /* NOTREACHED */
+}
+
+static void
+chestnut_power_off(void)
+{
+ chestnut_halt();
+ /* NOTREACHED */
+}
+
+/**************************************************************************
+ * FUNCTION: chestnut_map_io
+ *
+ * DESCRIPTION: configure fixed memory-mapped IO
+ *
+ ****/
+static void __init
+chestnut_map_io(void)
+{
+#if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB)
+ io_block_mapping(CHESTNUT_UART_BASE, CHESTNUT_UART_BASE, 0x100000,
+ _PAGE_IO);
+#endif
+}
+
+/**************************************************************************
+ * FUNCTION: chestnut_set_bat
+ *
+ * DESCRIPTION: configures a (temporary) bat mapping for early access to
+ * device I/O
+ *
+ ****/
+static __inline__ void
+chestnut_set_bat(void)
+{
+ mb();
+ mtspr(SPRN_DBAT3U, 0xf0001ffe);
+ mtspr(SPRN_DBAT3L, 0xf000002a);
+ mb();
+}
+
+/**************************************************************************
+ * FUNCTION: platform_init
+ *
+ * DESCRIPTION: main entry point for configuring board-specific machine
+ * callbacks
+ *
+ ****/
+void __init
+platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
+ unsigned long r6, unsigned long r7)
+{
+ parse_bootinfo(find_bootinfo());
+
+ /* Copy the kernel command line arguments to a safe place. */
+
+ if (r6) {
+ *(char *) (r7 + KERNELBASE) = 0;
+ strcpy(cmd_line, (char *) (r6 + KERNELBASE));
+ }
+
+ isa_mem_base = 0;
+
+ ppc_md.setup_arch = chestnut_setup_arch;
+ ppc_md.show_cpuinfo = chestnut_show_cpuinfo;
+ ppc_md.irq_canonicalize = NULL;
+ ppc_md.init_IRQ = mv64360_init_irq;
+ ppc_md.get_irq = mv64360_get_irq;
+ ppc_md.init = NULL;
+
+ ppc_md.find_end_of_memory = chestnut_find_end_of_memory;
+ ppc_md.setup_io_mappings = chestnut_map_io;
+
+ ppc_md.restart = chestnut_restart;
+ ppc_md.power_off = chestnut_power_off;
+ ppc_md.halt = chestnut_halt;
+
+ ppc_md.time_init = NULL;
+ ppc_md.set_rtc_time = NULL;
+ ppc_md.get_rtc_time = NULL;
+ ppc_md.calibrate_decr = chestnut_calibrate_decr;
+
+ ppc_md.nvram_read_val = NULL;
+ ppc_md.nvram_write_val = NULL;
+
+ ppc_md.heartbeat = NULL;
+
+ bh.p_base = CONFIG_MV64X60_NEW_BASE;
+
+ chestnut_set_bat();
+
+#if defined(CONFIG_SERIAL_TEXT_DEBUG)
+ ppc_md.progress = gen550_progress;
+#endif
+#if defined(CONFIG_KGDB)
+ ppc_md.kgdb_map_scc = gen550_kgdb_map_scc;
+#endif
+
+ if (ppc_md.progress)
+ ppc_md.progress("chestnut_init(): exit", 0);
+}
diff --git a/arch/ppc/platforms/chestnut.h b/arch/ppc/platforms/chestnut.h
new file mode 100644
index 0000000..0400b2b
--- /dev/null
+++ b/arch/ppc/platforms/chestnut.h
@@ -0,0 +1,129 @@
+/*
+ * arch/ppc/platforms/chestnut.h
+ *
+ * Definitions for IBM 750FXGX Eval (Chestnut)
+ *
+ * Author: <source@mvista.com>
+ *
+ * Based on Artesyn Katana code done by Tim Montgomery <timm@artesyncp.com>
+ * Based on code done by Rabeeh Khoury - rabeeh@galileo.co.il
+ * Based on code done by Mark A. Greer <mgreer@mvista.com>
+ *
+ * <2004> (c) MontaVista Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+
+/*
+ * This is the CPU physical memory map (windows must be at least 1MB and start
+ * on a boundary that is a multiple of the window size):
+ *
+ * Seems on the IBM 750FXGX Eval board, the MV64460 Registers can be in
+ * only 2 places per switch U17 0x14000000 or 0xf1000000 easily - chose to
+ * implement at 0xf1000000 only at this time
+ *
+ * 0xfff00000-0xffffffff - 8 Flash
+ * 0xffe00000-0xffefffff - BOOT SRAM
+ * 0xffd00000-0xffd00004 - CPLD
+ * 0xffc00000-0xffc0000f - UART
+ * 0xffb00000-0xffb07fff - FRAM
+ * 0xff840000-0xffafffff - *** HOLE ***
+ * 0xff800000-0xff83ffff - MV64460 Integrated SRAM
+ * 0xfe000000-0xff8fffff - *** HOLE ***
+ * 0xfc000000-0xfdffffff - 32bit Flash
+ * 0xf1010000-0xfbffffff - *** HOLE ***
+ * 0xf1000000-0xf100ffff - MV64460 Registers
+ */
+
+#ifndef __PPC_PLATFORMS_CHESTNUT_H__
+#define __PPC_PLATFORMS_CHESTNUT_H__
+
+#define CHESTNUT_BOOT_8BIT_BASE 0xfff00000
+#define CHESTNUT_BOOT_8BIT_SIZE_ACTUAL (1024*1024)
+#define CHESTNUT_BOOT_SRAM_BASE 0xffe00000
+#define CHESTNUT_BOOT_SRAM_SIZE_ACTUAL (1024*1024)
+#define CHESTNUT_CPLD_BASE 0xffd00000
+#define CHESTNUT_CPLD_SIZE_ACTUAL 5
+#define CHESTNUT_CPLD_REG3 (CHESTNUT_CPLD_BASE+3)
+#define CHESTNUT_UART_BASE 0xffc00000
+#define CHESTNUT_UART_SIZE_ACTUAL 16
+#define CHESTNUT_FRAM_BASE 0xffb00000
+#define CHESTNUT_FRAM_SIZE_ACTUAL (32*1024)
+#define CHESTNUT_INTERNAL_SRAM_BASE 0xff800000
+#define CHESTNUT_32BIT_BASE 0xfc000000
+#define CHESTNUT_32BIT_SIZE (32*1024*1024)
+
+#define CHESTNUT_BOOT_8BIT_SIZE max(MV64360_WINDOW_SIZE_MIN, \
+ CHESTNUT_BOOT_8BIT_SIZE_ACTUAL)
+#define CHESTNUT_BOOT_SRAM_SIZE max(MV64360_WINDOW_SIZE_MIN, \
+ CHESTNUT_BOOT_SRAM_SIZE_ACTUAL)
+#define CHESTNUT_CPLD_SIZE max(MV64360_WINDOW_SIZE_MIN, \
+ CHESTNUT_CPLD_SIZE_ACTUAL)
+#define CHESTNUT_UART_SIZE max(MV64360_WINDOW_SIZE_MIN, \
+ CHESTNUT_UART_SIZE_ACTUAL)
+#define CHESTNUT_FRAM_SIZE max(MV64360_WINDOW_SIZE_MIN, \
+ CHESTNUT_FRAM_SIZE_ACTUAL)
+
+#define CHESTNUT_BUS_SPEED 200000000
+#define CHESTNUT_PIBS_DATABASE 0xf0000 /* from PIBS src code */
+
+#define KATANA_ETH0_PHY_ADDR 12
+#define KATANA_ETH1_PHY_ADDR 11
+#define KATANA_ETH2_PHY_ADDR 4
+
+#define CHESTNUT_ETH_TX_QUEUE_SIZE 800
+#define CHESTNUT_ETH_RX_QUEUE_SIZE 400
+
+/*
+ * PCI windows
+ */
+
+#define CHESTNUT_PCI0_MEM_PROC_ADDR 0x80000000
+#define CHESTNUT_PCI0_MEM_PCI_HI_ADDR 0x00000000
+#define CHESTNUT_PCI0_MEM_PCI_LO_ADDR 0x80000000
+#define CHESTNUT_PCI0_MEM_SIZE 0x10000000
+#define CHESTNUT_PCI0_IO_PROC_ADDR 0xa0000000
+#define CHESTNUT_PCI0_IO_PCI_ADDR 0x00000000
+#define CHESTNUT_PCI0_IO_SIZE 0x01000000
+
+/*
+ * Board-specific IRQ info
+ */
+#define CHESTNUT_PCI_SLOT0_IRQ (64 + 31)
+#define CHESTNUT_PCI_SLOT1_IRQ (64 + 30)
+#define CHESTNUT_PCI_SLOT2_IRQ (64 + 29)
+#define CHESTNUT_PCI_SLOT3_IRQ (64 + 28)
+
+/* serial port definitions */
+#define CHESTNUT_UART0_IO_BASE (CHESTNUT_UART_BASE + 8)
+#define CHESTNUT_UART1_IO_BASE CHESTNUT_UART_BASE
+
+#define UART0_INT (64 + 25)
+#define UART1_INT (64 + 26)
+
+#ifdef CONFIG_SERIAL_MANY_PORTS
+#define RS_TABLE_SIZE 64
+#else
+#define RS_TABLE_SIZE 2
+#endif
+
+/* Rate for the 3.6864 Mhz clock for the onboard serial chip */
+#define BASE_BAUD (3686400 / 16)
+
+#ifdef CONFIG_SERIAL_DETECT_IRQ
+#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF|ASYNC_SKIP_TEST|ASYNC_AUTO_IRQ)
+#else
+#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF|ASYNC_SKIP_TEST)
+#endif
+
+#define STD_UART_OP(num) \
+ { 0, BASE_BAUD, 0, UART##num##_INT, STD_COM_FLAGS, \
+ iomem_base: (u8 *)CHESTNUT_UART##num##_IO_BASE, \
+ io_type: SERIAL_IO_MEM},
+
+#define SERIAL_PORT_DFNS \
+ STD_UART_OP(0) \
+ STD_UART_OP(1)
+
+#endif /* __PPC_PLATFORMS_CHESTNUT_H__ */
diff --git a/arch/ppc/platforms/chrp_pci.c b/arch/ppc/platforms/chrp_pci.c
new file mode 100644
index 0000000..5bb6492
--- /dev/null
+++ b/arch/ppc/platforms/chrp_pci.c
@@ -0,0 +1,309 @@
+/*
+ * CHRP pci routines.
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/delay.h>
+#include <linux/string.h>
+#include <linux/init.h>
+#include <linux/ide.h>
+#include <linux/bootmem.h>
+
+#include <asm/io.h>
+#include <asm/pgtable.h>
+#include <asm/irq.h>
+#include <asm/hydra.h>
+#include <asm/prom.h>
+#include <asm/gg2.h>
+#include <asm/machdep.h>
+#include <asm/sections.h>
+#include <asm/pci-bridge.h>
+#include <asm/open_pic.h>
+
+/* LongTrail */
+void __iomem *gg2_pci_config_base;
+
+/*
+ * The VLSI Golden Gate II has only 512K of PCI configuration space, so we
+ * limit the bus number to 3 bits
+ */
+
+int __chrp gg2_read_config(struct pci_bus *bus, unsigned int devfn, int off,
+ int len, u32 *val)
+{
+ volatile void __iomem *cfg_data;
+ struct pci_controller *hose = bus->sysdata;
+
+ if (bus->number > 7)
+ return PCIBIOS_DEVICE_NOT_FOUND;
+ /*
+ * Note: the caller has already checked that off is
+ * suitably aligned and that len is 1, 2 or 4.
+ */
+ cfg_data = hose->cfg_data + ((bus->number<<16) | (devfn<<8) | off);
+ switch (len) {
+ case 1:
+ *val = in_8(cfg_data);
+ break;
+ case 2:
+ *val = in_le16(cfg_data);
+ break;
+ default:
+ *val = in_le32(cfg_data);
+ break;
+ }
+ return PCIBIOS_SUCCESSFUL;
+}
+
+int __chrp gg2_write_config(struct pci_bus *bus, unsigned int devfn, int off,
+ int len, u32 val)
+{
+ volatile void __iomem *cfg_data;
+ struct pci_controller *hose = bus->sysdata;
+
+ if (bus->number > 7)
+ return PCIBIOS_DEVICE_NOT_FOUND;
+ /*
+ * Note: the caller has already checked that off is
+ * suitably aligned and that len is 1, 2 or 4.
+ */
+ cfg_data = hose->cfg_data + ((bus->number<<16) | (devfn<<8) | off);
+ switch (len) {
+ case 1:
+ out_8(cfg_data, val);
+ break;
+ case 2:
+ out_le16(cfg_data, val);
+ break;
+ default:
+ out_le32(cfg_data, val);
+ break;
+ }
+ return PCIBIOS_SUCCESSFUL;
+}
+
+static struct pci_ops gg2_pci_ops =
+{
+ gg2_read_config,
+ gg2_write_config
+};
+
+/*
+ * Access functions for PCI config space using RTAS calls.
+ */
+int __chrp
+rtas_read_config(struct pci_bus *bus, unsigned int devfn, int offset,
+ int len, u32 *val)
+{
+ struct pci_controller *hose = bus->sysdata;
+ unsigned long addr = (offset & 0xff) | ((devfn & 0xff) << 8)
+ | (((bus->number - hose->first_busno) & 0xff) << 16)
+ | (hose->index << 24);
+ unsigned long ret = ~0UL;
+ int rval;
+
+ rval = call_rtas("read-pci-config", 2, 2, &ret, addr, len);
+ *val = ret;
+ return rval? PCIBIOS_DEVICE_NOT_FOUND: PCIBIOS_SUCCESSFUL;
+}
+
+int __chrp
+rtas_write_config(struct pci_bus *bus, unsigned int devfn, int offset,
+ int len, u32 val)
+{
+ struct pci_controller *hose = bus->sysdata;
+ unsigned long addr = (offset & 0xff) | ((devfn & 0xff) << 8)
+ | (((bus->number - hose->first_busno) & 0xff) << 16)
+ | (hose->index << 24);
+ int rval;
+
+ rval = call_rtas("write-pci-config", 3, 1, NULL, addr, len, val);
+ return rval? PCIBIOS_DEVICE_NOT_FOUND: PCIBIOS_SUCCESSFUL;
+}
+
+static struct pci_ops rtas_pci_ops =
+{
+ rtas_read_config,
+ rtas_write_config
+};
+
+volatile struct Hydra *Hydra = NULL;
+
+int __init
+hydra_init(void)
+{
+ struct device_node *np;
+
+ np = find_devices("mac-io");
+ if (np == NULL || np->n_addrs == 0)
+ return 0;
+ Hydra = ioremap(np->addrs[0].address, np->addrs[0].size);
+ printk("Hydra Mac I/O at %x\n", np->addrs[0].address);
+ printk("Hydra Feature_Control was %x",
+ in_le32(&Hydra->Feature_Control));
+ out_le32(&Hydra->Feature_Control, (HYDRA_FC_SCC_CELL_EN |
+ HYDRA_FC_SCSI_CELL_EN |
+ HYDRA_FC_SCCA_ENABLE |
+ HYDRA_FC_SCCB_ENABLE |
+ HYDRA_FC_ARB_BYPASS |
+ HYDRA_FC_MPIC_ENABLE |
+ HYDRA_FC_SLOW_SCC_PCLK |
+ HYDRA_FC_MPIC_IS_MASTER));
+ printk(", now %x\n", in_le32(&Hydra->Feature_Control));
+ return 1;
+}
+
+void __init
+chrp_pcibios_fixup(void)
+{
+ struct pci_dev *dev = NULL;
+ struct device_node *np;
+
+ /* PCI interrupts are controlled by the OpenPIC */
+ for_each_pci_dev(dev) {
+ np = pci_device_to_OF_node(dev);
+ if ((np != 0) && (np->n_intrs > 0) && (np->intrs[0].line != 0))
+ dev->irq = np->intrs[0].line;
+ pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq);
+ }
+}
+
+#define PRG_CL_RESET_VALID 0x00010000
+
+static void __init
+setup_python(struct pci_controller *hose, struct device_node *dev)
+{
+ u32 *reg, val;
+ unsigned long addr = dev->addrs[0].address;
+
+ setup_indirect_pci(hose, addr + 0xf8000, addr + 0xf8010);
+
+ /* Clear the magic go-slow bit */
+ reg = (u32 *) ioremap(dev->addrs[0].address + 0xf6000, 0x40);
+ val = in_be32(®[12]);
+ if (val & PRG_CL_RESET_VALID) {
+ out_be32(®[12], val & ~PRG_CL_RESET_VALID);
+ in_be32(®[12]);
+ }
+ iounmap(reg);
+}
+
+/* Marvell Discovery II based Pegasos 2 */
+static void __init setup_peg2(struct pci_controller *hose, struct device_node *dev)
+{
+ struct device_node *root = find_path_device("/");
+ struct device_node *rtas;
+
+ rtas = of_find_node_by_name (root, "rtas");
+ if (rtas) {
+ hose->ops = &rtas_pci_ops;
+ } else {
+ printk ("RTAS supporting Pegasos OF not found, please upgrade"
+ " your firmware\n");
+ }
+ pci_assign_all_busses = 1;
+}
+
+void __init
+chrp_find_bridges(void)
+{
+ struct device_node *dev;
+ int *bus_range;
+ int len, index = -1;
+ struct pci_controller *hose;
+ unsigned int *dma;
+ char *model, *machine;
+ int is_longtrail = 0, is_mot = 0, is_pegasos = 0;
+ struct device_node *root = find_path_device("/");
+
+ /*
+ * The PCI host bridge nodes on some machines don't have
+ * properties to adequately identify them, so we have to
+ * look at what sort of machine this is as well.
+ */
+ machine = get_property(root, "model", NULL);
+ if (machine != NULL) {
+ is_longtrail = strncmp(machine, "IBM,LongTrail", 13) == 0;
+ is_mot = strncmp(machine, "MOT", 3) == 0;
+ if (strncmp(machine, "Pegasos2", 8) == 0)
+ is_pegasos = 2;
+ else if (strncmp(machine, "Pegasos", 7) == 0)
+ is_pegasos = 1;
+ }
+ for (dev = root->child; dev != NULL; dev = dev->sibling) {
+ if (dev->type == NULL || strcmp(dev->type, "pci") != 0)
+ continue;
+ ++index;
+ /* The GG2 bridge on the LongTrail doesn't have an address */
+ if (dev->n_addrs < 1 && !is_longtrail) {
+ printk(KERN_WARNING "Can't use %s: no address\n",
+ dev->full_name);
+ continue;
+ }
+ bus_range = (int *) get_property(dev, "bus-range", &len);
+ if (bus_range == NULL || len < 2 * sizeof(int)) {
+ printk(KERN_WARNING "Can't get bus-range for %s\n",
+ dev->full_name);
+ continue;
+ }
+ if (bus_range[1] == bus_range[0])
+ printk(KERN_INFO "PCI bus %d", bus_range[0]);
+ else
+ printk(KERN_INFO "PCI buses %d..%d",
+ bus_range[0], bus_range[1]);
+ printk(" controlled by %s", dev->type);
+ if (dev->n_addrs > 0)
+ printk(" at %x", dev->addrs[0].address);
+ printk("\n");
+
+ hose = pcibios_alloc_controller();
+ if (!hose) {
+ printk("Can't allocate PCI controller structure for %s\n",
+ dev->full_name);
+ continue;
+ }
+ hose->arch_data = dev;
+ hose->first_busno = bus_range[0];
+ hose->last_busno = bus_range[1];
+
+ model = get_property(dev, "model", NULL);
+ if (model == NULL)
+ model = "<none>";
+ if (device_is_compatible(dev, "IBM,python")) {
+ setup_python(hose, dev);
+ } else if (is_mot
+ || strncmp(model, "Motorola, Grackle", 17) == 0) {
+ setup_grackle(hose);
+ } else if (is_longtrail) {
+ void __iomem *p = ioremap(GG2_PCI_CONFIG_BASE, 0x80000);
+ hose->ops = &gg2_pci_ops;
+ hose->cfg_data = p;
+ gg2_pci_config_base = p;
+ } else if (is_pegasos == 1) {
+ setup_indirect_pci(hose, 0xfec00cf8, 0xfee00cfc);
+ } else if (is_pegasos == 2) {
+ setup_peg2(hose, dev);
+ } else {
+ printk("No methods for %s (model %s), using RTAS\n",
+ dev->full_name, model);
+ hose->ops = &rtas_pci_ops;
+ }
+
+ pci_process_bridge_OF_ranges(hose, dev, index == 0);
+
+ /* check the first bridge for a property that we can
+ use to set pci_dram_offset */
+ dma = (unsigned int *)
+ get_property(dev, "ibm,dma-ranges", &len);
+ if (index == 0 && dma != NULL && len >= 6 * sizeof(*dma)) {
+ pci_dram_offset = dma[2] - dma[3];
+ printk("pci_dram_offset = %lx\n", pci_dram_offset);
+ }
+ }
+
+ /* Do not fixup interrupts from OF tree on pegasos */
+ if (is_pegasos == 0)
+ ppc_md.pcibios_fixup = chrp_pcibios_fixup;
+}
diff --git a/arch/ppc/platforms/chrp_pegasos_eth.c b/arch/ppc/platforms/chrp_pegasos_eth.c
new file mode 100644
index 0000000..cad5bfa
--- /dev/null
+++ b/arch/ppc/platforms/chrp_pegasos_eth.c
@@ -0,0 +1,101 @@
+/*
+ * arch/ppc/platforms/chrp_pegasos_eth.c
+ *
+ * Copyright (C) 2005 Sven Luther <sl@bplan-gmbh.de>
+ * Thanks to :
+ * Dale Farnsworth <dale@farnsworth.org>
+ * Mark A. Greer <mgreer@mvista.com>
+ * Nicolas DET <nd@bplan-gmbh.de>
+ * Benjamin Herrenschmidt <benh@kernel.crashing.org>
+ * And anyone else who helped me on this.
+ */
+
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/device.h>
+#include <linux/mv643xx.h>
+#include <linux/pci.h>
+
+/* Pegasos 2 specific Marvell MV 64361 gigabit ethernet port setup */
+static struct resource mv643xx_eth_shared_resources[] = {
+ [0] = {
+ .name = "ethernet shared base",
+ .start = 0xf1000000 + MV643XX_ETH_SHARED_REGS,
+ .end = 0xf1000000 + MV643XX_ETH_SHARED_REGS +
+ MV643XX_ETH_SHARED_REGS_SIZE - 1,
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+static struct platform_device mv643xx_eth_shared_device = {
+ .name = MV643XX_ETH_SHARED_NAME,
+ .id = 0,
+ .num_resources = ARRAY_SIZE(mv643xx_eth_shared_resources),
+ .resource = mv643xx_eth_shared_resources,
+};
+
+static struct resource mv643xx_eth0_resources[] = {
+ [0] = {
+ .name = "eth0 irq",
+ .start = 9,
+ .end = 9,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct mv643xx_eth_platform_data eth0_pd;
+
+static struct platform_device eth0_device = {
+ .name = MV643XX_ETH_NAME,
+ .id = 0,
+ .num_resources = ARRAY_SIZE(mv643xx_eth0_resources),
+ .resource = mv643xx_eth0_resources,
+ .dev = {
+ .platform_data = ð0_pd,
+ },
+};
+
+static struct resource mv643xx_eth1_resources[] = {
+ [0] = {
+ .name = "eth1 irq",
+ .start = 9,
+ .end = 9,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct mv643xx_eth_platform_data eth1_pd;
+
+static struct platform_device eth1_device = {
+ .name = MV643XX_ETH_NAME,
+ .id = 1,
+ .num_resources = ARRAY_SIZE(mv643xx_eth1_resources),
+ .resource = mv643xx_eth1_resources,
+ .dev = {
+ .platform_data = ð1_pd,
+ },
+};
+
+static struct platform_device *mv643xx_eth_pd_devs[] __initdata = {
+ &mv643xx_eth_shared_device,
+ ð0_device,
+ ð1_device,
+};
+
+
+int
+mv643xx_eth_add_pds(void)
+{
+ int ret = 0;
+ static struct pci_device_id pci_marvell_mv64360[] = {
+ { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, PCI_DEVICE_ID_MARVELL_MV64360) },
+ { }
+ };
+
+ if (pci_dev_present(pci_marvell_mv64360)) {
+ ret = platform_add_devices(mv643xx_eth_pd_devs, ARRAY_SIZE(mv643xx_eth_pd_devs));
+ }
+ return ret;
+}
+device_initcall(mv643xx_eth_add_pds);
diff --git a/arch/ppc/platforms/chrp_setup.c b/arch/ppc/platforms/chrp_setup.c
new file mode 100644
index 0000000..f23c4f3
--- /dev/null
+++ b/arch/ppc/platforms/chrp_setup.c
@@ -0,0 +1,615 @@
+/*
+ * arch/ppc/platforms/setup.c
+ *
+ * Copyright (C) 1995 Linus Torvalds
+ * Adapted from 'alpha' version by Gary Thomas
+ * Modified by Cort Dougan (cort@cs.nmt.edu)
+ */
+
+/*
+ * bootup setup stuff..
+ */
+
+#include <linux/config.h>
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/stddef.h>
+#include <linux/unistd.h>
+#include <linux/ptrace.h>
+#include <linux/slab.h>
+#include <linux/user.h>
+#include <linux/a.out.h>
+#include <linux/tty.h>
+#include <linux/major.h>
+#include <linux/interrupt.h>
+#include <linux/reboot.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/version.h>
+#include <linux/adb.h>
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/ide.h>
+#include <linux/irq.h>
+#include <linux/console.h>
+#include <linux/seq_file.h>
+#include <linux/root_dev.h>
+#include <linux/initrd.h>
+#include <linux/module.h>
+
+#include <asm/io.h>
+#include <asm/pgtable.h>
+#include <asm/prom.h>
+#include <asm/gg2.h>
+#include <asm/pci-bridge.h>
+#include <asm/dma.h>
+#include <asm/machdep.h>
+#include <asm/irq.h>
+#include <asm/hydra.h>
+#include <asm/sections.h>
+#include <asm/time.h>
+#include <asm/btext.h>
+#include <asm/i8259.h>
+#include <asm/open_pic.h>
+#include <asm/xmon.h>
+
+unsigned long chrp_get_rtc_time(void);
+int chrp_set_rtc_time(unsigned long nowtime);
+void chrp_calibrate_decr(void);
+long chrp_time_init(void);
+
+void chrp_find_bridges(void);
+void chrp_event_scan(void);
+void rtas_display_progress(char *, unsigned short);
+void rtas_indicator_progress(char *, unsigned short);
+void btext_progress(char *, unsigned short);
+
+extern unsigned long pmac_find_end_of_memory(void);
+extern int of_show_percpuinfo(struct seq_file *, int);
+
+int _chrp_type;
+EXPORT_SYMBOL(_chrp_type);
+
+/*
+ * XXX this should be in xmon.h, but putting it there means xmon.h
+ * has to include <linux/interrupt.h> (to get irqreturn_t), which
+ * causes all sorts of problems. -- paulus
+ */
+extern irqreturn_t xmon_irq(int, void *, struct pt_regs *);
+
+extern dev_t boot_dev;
+
+extern PTE *Hash, *Hash_end;
+extern unsigned long Hash_size, Hash_mask;
+extern int probingmem;
+extern unsigned long loops_per_jiffy;
+static int max_width;
+
+#ifdef CONFIG_SMP
+extern struct smp_ops_t chrp_smp_ops;
+#endif
+
+static const char *gg2_memtypes[4] = {
+ "FPM", "SDRAM", "EDO", "BEDO"
+};
+static const char *gg2_cachesizes[4] = {
+ "256 KB", "512 KB", "1 MB", "Reserved"
+};
+static const char *gg2_cachetypes[4] = {
+ "Asynchronous", "Reserved", "Flow-Through Synchronous",
+ "Pipelined Synchronous"
+};
+static const char *gg2_cachemodes[4] = {
+ "Disabled", "Write-Through", "Copy-Back", "Transparent Mode"
+};
+
+int __chrp
+chrp_show_cpuinfo(struct seq_file *m)
+{
+ int i, sdramen;
+ unsigned int t;
+ struct device_node *root;
+ const char *model = "";
+
+ root = find_path_device("/");
+ if (root)
+ model = get_property(root, "model", NULL);
+ seq_printf(m, "machine\t\t: CHRP %s\n", model);
+
+ /* longtrail (goldengate) stuff */
+ if (!strncmp(model, "IBM,LongTrail", 13)) {
+ /* VLSI VAS96011/12 `Golden Gate 2' */
+ /* Memory banks */
+ sdramen = (in_le32(gg2_pci_config_base + GG2_PCI_DRAM_CTRL)
+ >>31) & 1;
+ for (i = 0; i < (sdramen ? 4 : 6); i++) {
+ t = in_le32(gg2_pci_config_base+
+ GG2_PCI_DRAM_BANK0+
+ i*4);
+ if (!(t & 1))
+ continue;
+ switch ((t>>8) & 0x1f) {
+ case 0x1f:
+ model = "4 MB";
+ break;
+ case 0x1e:
+ model = "8 MB";
+ break;
+ case 0x1c:
+ model = "16 MB";
+ break;
+ case 0x18:
+ model = "32 MB";
+ break;
+ case 0x10:
+ model = "64 MB";
+ break;
+ case 0x00:
+ model = "128 MB";
+ break;
+ default:
+ model = "Reserved";
+ break;
+ }
+ seq_printf(m, "memory bank %d\t: %s %s\n", i, model,
+ gg2_memtypes[sdramen ? 1 : ((t>>1) & 3)]);
+ }
+ /* L2 cache */
+ t = in_le32(gg2_pci_config_base+GG2_PCI_CC_CTRL);
+ seq_printf(m, "board l2\t: %s %s (%s)\n",
+ gg2_cachesizes[(t>>7) & 3],
+ gg2_cachetypes[(t>>2) & 3],
+ gg2_cachemodes[t & 3]);
+ }
+ return 0;
+}
+
+/*
+ * Fixes for the National Semiconductor PC78308VUL SuperI/O
+ *
+ * Some versions of Open Firmware incorrectly initialize the IRQ settings
+ * for keyboard and mouse
+ */
+static inline void __init sio_write(u8 val, u8 index)
+{
+ outb(index, 0x15c);
+ outb(val, 0x15d);
+}
+
+static inline u8 __init sio_read(u8 index)
+{
+ outb(index, 0x15c);
+ return inb(0x15d);
+}
+
+static void __init sio_fixup_irq(const char *name, u8 device, u8 level,
+ u8 type)
+{
+ u8 level0, type0, active;
+
+ /* select logical device */
+ sio_write(device, 0x07);
+ active = sio_read(0x30);
+ level0 = sio_read(0x70);
+ type0 = sio_read(0x71);
+ if (level0 != level || type0 != type || !active) {
+ printk(KERN_WARNING "sio: %s irq level %d, type %d, %sactive: "
+ "remapping to level %d, type %d, active\n",
+ name, level0, type0, !active ? "in" : "", level, type);
+ sio_write(0x01, 0x30);
+ sio_write(level, 0x70);
+ sio_write(type, 0x71);
+ }
+}
+
+static void __init sio_init(void)
+{
+ struct device_node *root;
+
+ if ((root = find_path_device("/")) &&
+ !strncmp(get_property(root, "model", NULL), "IBM,LongTrail", 13)) {
+ /* logical device 0 (KBC/Keyboard) */
+ sio_fixup_irq("keyboard", 0, 1, 2);
+ /* select logical device 1 (KBC/Mouse) */
+ sio_fixup_irq("mouse", 1, 12, 2);
+ }
+}
+
+
+static void __init pegasos_set_l2cr(void)
+{
+ struct device_node *np;
+
+ /* On Pegasos, enable the l2 cache if needed, as the OF forgets it */
+ if (_chrp_type != _CHRP_Pegasos)
+ return;
+
+ /* Enable L2 cache if needed */
+ np = find_type_devices("cpu");
+ if (np != NULL) {
+ unsigned int *l2cr = (unsigned int *)
+ get_property (np, "l2cr", NULL);
+ if (l2cr == NULL) {
+ printk ("Pegasos l2cr : no cpu l2cr property found\n");
+ return;
+ }
+ if (!((*l2cr) & 0x80000000)) {
+ printk ("Pegasos l2cr : L2 cache was not active, "
+ "activating\n");
+ _set_L2CR(0);
+ _set_L2CR((*l2cr) | 0x80000000);
+ }
+ }
+}
+
+void __init chrp_setup_arch(void)
+{
+ struct device_node *device;
+
+ /* init to some ~sane value until calibrate_delay() runs */
+ loops_per_jiffy = 50000000/HZ;
+
+#ifdef CONFIG_BLK_DEV_INITRD
+ /* this is fine for chrp */
+ initrd_below_start_ok = 1;
+
+ if (initrd_start)
+ ROOT_DEV = Root_RAM0;
+ else
+#endif
+ ROOT_DEV = Root_SDA2; /* sda2 (sda1 is for the kernel) */
+
+ /* On pegasos, enable the L2 cache if not already done by OF */
+ pegasos_set_l2cr();
+
+ /* Lookup PCI host bridges */
+ chrp_find_bridges();
+
+#ifndef CONFIG_PPC64BRIDGE
+ /*
+ * Temporary fixes for PCI devices.
+ * -- Geert
+ */
+ hydra_init(); /* Mac I/O */
+
+#endif /* CONFIG_PPC64BRIDGE */
+
+ /*
+ * Fix the Super I/O configuration
+ */
+ sio_init();
+
+ /* Get the event scan rate for the rtas so we know how
+ * often it expects a heartbeat. -- Cort
+ */
+ if ( rtas_data ) {
+ struct property *p;
+ device = find_devices("rtas");
+ for ( p = device->properties;
+ p && strncmp(p->name, "rtas-event-scan-rate", 20);
+ p = p->next )
+ /* nothing */ ;
+ if ( p && *(unsigned long *)p->value ) {
+ ppc_md.heartbeat = chrp_event_scan;
+ ppc_md.heartbeat_reset = (HZ/(*(unsigned long *)p->value)*30)-1;
+ ppc_md.heartbeat_count = 1;
+ printk("RTAS Event Scan Rate: %lu (%lu jiffies)\n",
+ *(unsigned long *)p->value, ppc_md.heartbeat_reset );
+ }
+ }
+
+ pci_create_OF_bus_map();
+}
+
+void __chrp
+chrp_event_scan(void)
+{
+ unsigned char log[1024];
+ unsigned long ret = 0;
+ /* XXX: we should loop until the hardware says no more error logs -- Cort */
+ call_rtas( "event-scan", 4, 1, &ret, 0xffffffff, 0,
+ __pa(log), 1024 );
+ ppc_md.heartbeat_count = ppc_md.heartbeat_reset;
+}
+
+void __chrp
+chrp_restart(char *cmd)
+{
+ printk("RTAS system-reboot returned %d\n",
+ call_rtas("system-reboot", 0, 1, NULL));
+ for (;;);
+}
+
+void __chrp
+chrp_power_off(void)
+{
+ /* allow power on only with power button press */
+ printk("RTAS power-off returned %d\n",
+ call_rtas("power-off", 2, 1, NULL,0xffffffff,0xffffffff));
+ for (;;);
+}
+
+void __chrp
+chrp_halt(void)
+{
+ chrp_power_off();
+}
+
+u_int __chrp
+chrp_irq_canonicalize(u_int irq)
+{
+ if (irq == 2)
+ return 9;
+ return irq;
+}
+
+/*
+ * Finds the open-pic node and sets OpenPIC_Addr based on its reg property.
+ * Then checks if it has an interrupt-ranges property. If it does then
+ * we have a distributed open-pic, so call openpic_set_sources to tell
+ * the openpic code where to find the interrupt source registers.
+ */
+static void __init chrp_find_openpic(void)
+{
+ struct device_node *np;
+ int len, i;
+ unsigned int *iranges;
+ void *isu;
+
+ np = find_type_devices("open-pic");
+ if (np == NULL || np->n_addrs == 0)
+ return;
+ printk(KERN_INFO "OpenPIC at %x (size %x)\n",
+ np->addrs[0].address, np->addrs[0].size);
+ OpenPIC_Addr = ioremap(np->addrs[0].address, 0x40000);
+ if (OpenPIC_Addr == NULL) {
+ printk(KERN_ERR "Failed to map OpenPIC!\n");
+ return;
+ }
+
+ iranges = (unsigned int *) get_property(np, "interrupt-ranges", &len);
+ if (iranges == NULL || len < 2 * sizeof(unsigned int))
+ return; /* not distributed */
+
+ /*
+ * The first pair of cells in interrupt-ranges refers to the
+ * IDU; subsequent pairs refer to the ISUs.
+ */
+ len /= 2 * sizeof(unsigned int);
+ if (np->n_addrs < len) {
+ printk(KERN_ERR "Insufficient addresses for distributed"
+ " OpenPIC (%d < %d)\n", np->n_addrs, len);
+ return;
+ }
+ if (iranges[1] != 0) {
+ printk(KERN_INFO "OpenPIC irqs %d..%d in IDU\n",
+ iranges[0], iranges[0] + iranges[1] - 1);
+ openpic_set_sources(iranges[0], iranges[1], NULL);
+ }
+ for (i = 1; i < len; ++i) {
+ iranges += 2;
+ printk(KERN_INFO "OpenPIC irqs %d..%d in ISU at %x (%x)\n",
+ iranges[0], iranges[0] + iranges[1] - 1,
+ np->addrs[i].address, np->addrs[i].size);
+ isu = ioremap(np->addrs[i].address, np->addrs[i].size);
+ if (isu != NULL)
+ openpic_set_sources(iranges[0], iranges[1], isu);
+ else
+ printk(KERN_ERR "Failed to map OpenPIC ISU at %x!\n",
+ np->addrs[i].address);
+ }
+}
+
+#if defined(CONFIG_VT) && defined(CONFIG_INPUT_ADBHID) && defined(XMON)
+static struct irqaction xmon_irqaction = {
+ .handler = xmon_irq,
+ .mask = CPU_MASK_NONE,
+ .name = "XMON break",
+};
+#endif
+
+void __init chrp_init_IRQ(void)
+{
+ struct device_node *np;
+ int i;
+ unsigned long chrp_int_ack = 0;
+ unsigned char init_senses[NR_IRQS - NUM_8259_INTERRUPTS];
+#if defined(CONFIG_VT) && defined(CONFIG_INPUT_ADBHID) && defined(XMON)
+ struct device_node *kbd;
+#endif
+
+ for (np = find_devices("pci"); np != NULL; np = np->next) {
+ unsigned int *addrp = (unsigned int *)
+ get_property(np, "8259-interrupt-acknowledge", NULL);
+
+ if (addrp == NULL)
+ continue;
+ chrp_int_ack = addrp[prom_n_addr_cells(np)-1];
+ break;
+ }
+ if (np == NULL)
+ printk(KERN_ERR "Cannot find PCI interrupt acknowledge address\n");
+
+ chrp_find_openpic();
+
+ if (OpenPIC_Addr) {
+ prom_get_irq_senses(init_senses, NUM_8259_INTERRUPTS, NR_IRQS);
+ OpenPIC_InitSenses = init_senses;
+ OpenPIC_NumInitSenses = NR_IRQS - NUM_8259_INTERRUPTS;
+
+ openpic_init(NUM_8259_INTERRUPTS);
+ /* We have a cascade on OpenPIC IRQ 0, Linux IRQ 16 */
+ openpic_hookup_cascade(NUM_8259_INTERRUPTS, "82c59 cascade",
+ i8259_irq);
+
+ }
+ for (i = 0; i < NUM_8259_INTERRUPTS; i++)
+ irq_desc[i].handler = &i8259_pic;
+ i8259_init(chrp_int_ack);
+
+#if defined(CONFIG_VT) && defined(CONFIG_INPUT_ADBHID) && defined(XMON)
+ /* see if there is a keyboard in the device tree
+ with a parent of type "adb" */
+ for (kbd = find_devices("keyboard"); kbd; kbd = kbd->next)
+ if (kbd->parent && kbd->parent->type
+ && strcmp(kbd->parent->type, "adb") == 0)
+ break;
+ if (kbd)
+ setup_irq(HYDRA_INT_ADB_NMI, &xmon_irqaction);
+#endif
+}
+
+void __init
+chrp_init2(void)
+{
+#ifdef CONFIG_NVRAM
+// XX replace this in a more saner way
+// pmac_nvram_init();
+#endif
+
+ request_region(0x20,0x20,"pic1");
+ request_region(0xa0,0x20,"pic2");
+ request_region(0x00,0x20,"dma1");
+ request_region(0x40,0x20,"timer");
+ request_region(0x80,0x10,"dma page reg");
+ request_region(0xc0,0x20,"dma2");
+
+ if (ppc_md.progress)
+ ppc_md.progress(" Have fun! ", 0x7777);
+}
+
+void __init
+chrp_init(unsigned long r3, unsigned long r4, unsigned long r5,
+ unsigned long r6, unsigned long r7)
+{
+ struct device_node *root = find_path_device ("/");
+ char *machine = NULL;
+
+#ifdef CONFIG_BLK_DEV_INITRD
+ /* take care of initrd if we have one */
+ if ( r6 )
+ {
+ initrd_start = r6 + KERNELBASE;
+ initrd_end = r6 + r7 + KERNELBASE;
+ }
+#endif /* CONFIG_BLK_DEV_INITRD */
+
+ ISA_DMA_THRESHOLD = ~0L;
+ DMA_MODE_READ = 0x44;
+ DMA_MODE_WRITE = 0x48;
+ isa_io_base = CHRP_ISA_IO_BASE; /* default value */
+
+ if (root)
+ machine = get_property(root, "model", NULL);
+ if (machine && strncmp(machine, "Pegasos", 7) == 0) {
+ _chrp_type = _CHRP_Pegasos;
+ } else if (machine && strncmp(machine, "IBM", 3) == 0) {
+ _chrp_type = _CHRP_IBM;
+ } else if (machine && strncmp(machine, "MOT", 3) == 0) {
+ _chrp_type = _CHRP_Motorola;
+ } else {
+ /* Let's assume it is an IBM chrp if all else fails */
+ _chrp_type = _CHRP_IBM;
+ }
+
+ ppc_md.setup_arch = chrp_setup_arch;
+ ppc_md.show_percpuinfo = of_show_percpuinfo;
+ ppc_md.show_cpuinfo = chrp_show_cpuinfo;
+
+ ppc_md.irq_canonicalize = chrp_irq_canonicalize;
+ ppc_md.init_IRQ = chrp_init_IRQ;
+ if (_chrp_type == _CHRP_Pegasos)
+ ppc_md.get_irq = i8259_irq;
+ else
+ ppc_md.get_irq = openpic_get_irq;
+
+ ppc_md.init = chrp_init2;
+
+ ppc_md.phys_mem_access_prot = pci_phys_mem_access_prot;
+
+ ppc_md.restart = chrp_restart;
+ ppc_md.power_off = chrp_power_off;
+ ppc_md.halt = chrp_halt;
+
+ ppc_md.time_init = chrp_time_init;
+ ppc_md.set_rtc_time = chrp_set_rtc_time;
+ ppc_md.get_rtc_time = chrp_get_rtc_time;
+ ppc_md.calibrate_decr = chrp_calibrate_decr;
+
+ ppc_md.find_end_of_memory = pmac_find_end_of_memory;
+
+ if (rtas_data) {
+ struct device_node *rtas;
+ unsigned int *p;
+
+ rtas = find_devices("rtas");
+ if (rtas != NULL) {
+ if (get_property(rtas, "display-character", NULL)) {
+ ppc_md.progress = rtas_display_progress;
+ p = (unsigned int *) get_property
+ (rtas, "ibm,display-line-length", NULL);
+ if (p)
+ max_width = *p;
+ } else if (get_property(rtas, "set-indicator", NULL))
+ ppc_md.progress = rtas_indicator_progress;
+ }
+ }
+#ifdef CONFIG_BOOTX_TEXT
+ if (ppc_md.progress == NULL && boot_text_mapped)
+ ppc_md.progress = btext_progress;
+#endif
+
+#ifdef CONFIG_SMP
+ ppc_md.smp_ops = &chrp_smp_ops;
+#endif /* CONFIG_SMP */
+
+ /*
+ * Print the banner, then scroll down so boot progress
+ * can be printed. -- Cort
+ */
+ if (ppc_md.progress) ppc_md.progress("Linux/PPC "UTS_RELEASE"\n", 0x0);
+}
+
+void __chrp
+rtas_display_progress(char *s, unsigned short hex)
+{
+ int width;
+ char *os = s;
+
+ if ( call_rtas( "display-character", 1, 1, NULL, '\r' ) )
+ return;
+
+ width = max_width;
+ while ( *os )
+ {
+ if ( (*os == '\n') || (*os == '\r') )
+ width = max_width;
+ else
+ width--;
+ call_rtas( "display-character", 1, 1, NULL, *os++ );
+ /* if we overwrite the screen length */
+ if ( width == 0 )
+ while ( (*os != 0) && (*os != '\n') && (*os != '\r') )
+ os++;
+ }
+
+ /*while ( width-- > 0 )*/
+ call_rtas( "display-character", 1, 1, NULL, ' ' );
+}
+
+void __chrp
+rtas_indicator_progress(char *s, unsigned short hex)
+{
+ call_rtas("set-indicator", 3, 1, NULL, 6, 0, hex);
+}
+
+#ifdef CONFIG_BOOTX_TEXT
+void
+btext_progress(char *s, unsigned short hex)
+{
+ prom_print(s);
+ prom_print("\n");
+}
+#endif /* CONFIG_BOOTX_TEXT */
diff --git a/arch/ppc/platforms/chrp_smp.c b/arch/ppc/platforms/chrp_smp.c
new file mode 100644
index 0000000..0ea1f7d
--- /dev/null
+++ b/arch/ppc/platforms/chrp_smp.c
@@ -0,0 +1,98 @@
+/*
+ * Smp support for CHRP machines.
+ *
+ * Written by Cort Dougan (cort@cs.nmt.edu) borrowing a great
+ * deal of code from the sparc and intel versions.
+ *
+ * Copyright (C) 1999 Cort Dougan <cort@cs.nmt.edu>
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/smp.h>
+#include <linux/smp_lock.h>
+#include <linux/interrupt.h>
+#include <linux/kernel_stat.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/spinlock.h>
+
+#include <asm/ptrace.h>
+#include <asm/atomic.h>
+#include <asm/irq.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <asm/sections.h>
+#include <asm/io.h>
+#include <asm/prom.h>
+#include <asm/smp.h>
+#include <asm/residual.h>
+#include <asm/time.h>
+#include <asm/open_pic.h>
+
+extern unsigned long smp_chrp_cpu_nr;
+
+static int __init
+smp_chrp_probe(void)
+{
+ if (smp_chrp_cpu_nr > 1)
+ openpic_request_IPIs();
+
+ return smp_chrp_cpu_nr;
+}
+
+static void __devinit
+smp_chrp_kick_cpu(int nr)
+{
+ *(unsigned long *)KERNELBASE = nr;
+ asm volatile("dcbf 0,%0"::"r"(KERNELBASE):"memory");
+}
+
+static void __devinit
+smp_chrp_setup_cpu(int cpu_nr)
+{
+ if (OpenPIC_Addr)
+ do_openpic_setup_cpu();
+}
+
+static DEFINE_SPINLOCK(timebase_lock);
+static unsigned int timebase_upper = 0, timebase_lower = 0;
+
+void __devinit
+smp_chrp_give_timebase(void)
+{
+ spin_lock(&timebase_lock);
+ call_rtas("freeze-time-base", 0, 1, NULL);
+ timebase_upper = get_tbu();
+ timebase_lower = get_tbl();
+ spin_unlock(&timebase_lock);
+
+ while (timebase_upper || timebase_lower)
+ barrier();
+ call_rtas("thaw-time-base", 0, 1, NULL);
+}
+
+void __devinit
+smp_chrp_take_timebase(void)
+{
+ while (!(timebase_upper || timebase_lower))
+ barrier();
+ spin_lock(&timebase_lock);
+ set_tb(timebase_upper, timebase_lower);
+ timebase_upper = 0;
+ timebase_lower = 0;
+ spin_unlock(&timebase_lock);
+ printk("CPU %i taken timebase\n", smp_processor_id());
+}
+
+/* CHRP with openpic */
+struct smp_ops_t chrp_smp_ops __chrpdata = {
+ .message_pass = smp_openpic_message_pass,
+ .probe = smp_chrp_probe,
+ .kick_cpu = smp_chrp_kick_cpu,
+ .setup_cpu = smp_chrp_setup_cpu,
+ .give_timebase = smp_chrp_give_timebase,
+ .take_timebase = smp_chrp_take_timebase,
+};
diff --git a/arch/ppc/platforms/chrp_time.c b/arch/ppc/platforms/chrp_time.c
new file mode 100644
index 0000000..e2be0c8
--- /dev/null
+++ b/arch/ppc/platforms/chrp_time.c
@@ -0,0 +1,194 @@
+/*
+ * arch/ppc/platforms/chrp_time.c
+ *
+ * Copyright (C) 1991, 1992, 1995 Linus Torvalds
+ *
+ * Adapted for PowerPC (PReP) by Gary Thomas
+ * Modified by Cort Dougan (cort@cs.nmt.edu).
+ * Copied and modified from arch/i386/kernel/time.c
+ *
+ */
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/param.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/interrupt.h>
+#include <linux/time.h>
+#include <linux/timex.h>
+#include <linux/kernel_stat.h>
+#include <linux/mc146818rtc.h>
+#include <linux/init.h>
+#include <linux/bcd.h>
+
+#include <asm/segment.h>
+#include <asm/io.h>
+#include <asm/nvram.h>
+#include <asm/prom.h>
+#include <asm/sections.h>
+#include <asm/time.h>
+
+extern spinlock_t rtc_lock;
+
+static int nvram_as1 = NVRAM_AS1;
+static int nvram_as0 = NVRAM_AS0;
+static int nvram_data = NVRAM_DATA;
+
+long __init chrp_time_init(void)
+{
+ struct device_node *rtcs;
+ int base;
+
+ rtcs = find_compatible_devices("rtc", "pnpPNP,b00");
+ if (rtcs == NULL)
+ rtcs = find_compatible_devices("rtc", "ds1385-rtc");
+ if (rtcs == NULL || rtcs->addrs == NULL)
+ return 0;
+ base = rtcs->addrs[0].address;
+ nvram_as1 = 0;
+ nvram_as0 = base;
+ nvram_data = base + 1;
+
+ return 0;
+}
+
+int __chrp chrp_cmos_clock_read(int addr)
+{
+ if (nvram_as1 != 0)
+ outb(addr>>8, nvram_as1);
+ outb(addr, nvram_as0);
+ return (inb(nvram_data));
+}
+
+void __chrp chrp_cmos_clock_write(unsigned long val, int addr)
+{
+ if (nvram_as1 != 0)
+ outb(addr>>8, nvram_as1);
+ outb(addr, nvram_as0);
+ outb(val, nvram_data);
+ return;
+}
+
+/*
+ * Set the hardware clock. -- Cort
+ */
+int __chrp chrp_set_rtc_time(unsigned long nowtime)
+{
+ unsigned char save_control, save_freq_select;
+ struct rtc_time tm;
+
+ spin_lock(&rtc_lock);
+ to_tm(nowtime, &tm);
+
+ save_control = chrp_cmos_clock_read(RTC_CONTROL); /* tell the clock it's being set */
+
+ chrp_cmos_clock_write((save_control|RTC_SET), RTC_CONTROL);
+
+ save_freq_select = chrp_cmos_clock_read(RTC_FREQ_SELECT); /* stop and reset prescaler */
+
+ chrp_cmos_clock_write((save_freq_select|RTC_DIV_RESET2), RTC_FREQ_SELECT);
+
+ tm.tm_year -= 1900;
+ if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) {
+ BIN_TO_BCD(tm.tm_sec);
+ BIN_TO_BCD(tm.tm_min);
+ BIN_TO_BCD(tm.tm_hour);
+ BIN_TO_BCD(tm.tm_mon);
+ BIN_TO_BCD(tm.tm_mday);
+ BIN_TO_BCD(tm.tm_year);
+ }
+ chrp_cmos_clock_write(tm.tm_sec,RTC_SECONDS);
+ chrp_cmos_clock_write(tm.tm_min,RTC_MINUTES);
+ chrp_cmos_clock_write(tm.tm_hour,RTC_HOURS);
+ chrp_cmos_clock_write(tm.tm_mon,RTC_MONTH);
+ chrp_cmos_clock_write(tm.tm_mday,RTC_DAY_OF_MONTH);
+ chrp_cmos_clock_write(tm.tm_year,RTC_YEAR);
+
+ /* The following flags have to be released exactly in this order,
+ * otherwise the DS12887 (popular MC146818A clone with integrated
+ * battery and quartz) will not reset the oscillator and will not
+ * update precisely 500 ms later. You won't find this mentioned in
+ * the Dallas Semiconductor data sheets, but who believes data
+ * sheets anyway ... -- Markus Kuhn
+ */
+ chrp_cmos_clock_write(save_control, RTC_CONTROL);
+ chrp_cmos_clock_write(save_freq_select, RTC_FREQ_SELECT);
+
+ if ( (time_state == TIME_ERROR) || (time_state == TIME_BAD) )
+ time_state = TIME_OK;
+ spin_unlock(&rtc_lock);
+ return 0;
+}
+
+unsigned long __chrp chrp_get_rtc_time(void)
+{
+ unsigned int year, mon, day, hour, min, sec;
+ int uip, i;
+
+ /* The Linux interpretation of the CMOS clock register contents:
+ * When the Update-In-Progress (UIP) flag goes from 1 to 0, the
+ * RTC registers show the second which has precisely just started.
+ * Let's hope other operating systems interpret the RTC the same way.
+ */
+
+ /* Since the UIP flag is set for about 2.2 ms and the clock
+ * is typically written with a precision of 1 jiffy, trying
+ * to obtain a precision better than a few milliseconds is
+ * an illusion. Only consistency is interesting, this also
+ * allows to use the routine for /dev/rtc without a potential
+ * 1 second kernel busy loop triggered by any reader of /dev/rtc.
+ */
+
+ for ( i = 0; i<1000000; i++) {
+ uip = chrp_cmos_clock_read(RTC_FREQ_SELECT);
+ sec = chrp_cmos_clock_read(RTC_SECONDS);
+ min = chrp_cmos_clock_read(RTC_MINUTES);
+ hour = chrp_cmos_clock_read(RTC_HOURS);
+ day = chrp_cmos_clock_read(RTC_DAY_OF_MONTH);
+ mon = chrp_cmos_clock_read(RTC_MONTH);
+ year = chrp_cmos_clock_read(RTC_YEAR);
+ uip |= chrp_cmos_clock_read(RTC_FREQ_SELECT);
+ if ((uip & RTC_UIP)==0) break;
+ }
+
+ if (!(chrp_cmos_clock_read(RTC_CONTROL) & RTC_DM_BINARY) || RTC_ALWAYS_BCD)
+ {
+ BCD_TO_BIN(sec);
+ BCD_TO_BIN(min);
+ BCD_TO_BIN(hour);
+ BCD_TO_BIN(day);
+ BCD_TO_BIN(mon);
+ BCD_TO_BIN(year);
+ }
+ if ((year += 1900) < 1970)
+ year += 100;
+ return mktime(year, mon, day, hour, min, sec);
+}
+
+
+void __init chrp_calibrate_decr(void)
+{
+ struct device_node *cpu;
+ unsigned int freq, *fp;
+
+ if (via_calibrate_decr())
+ return;
+
+ /*
+ * The cpu node should have a timebase-frequency property
+ * to tell us the rate at which the decrementer counts.
+ */
+ freq = 16666000; /* hardcoded default */
+ cpu = find_type_devices("cpu");
+ if (cpu != 0) {
+ fp = (unsigned int *)
+ get_property(cpu, "timebase-frequency", NULL);
+ if (fp != 0)
+ freq = *fp;
+ }
+ printk("time_init: decrementer frequency = %u.%.6u MHz\n",
+ freq/1000000, freq%1000000);
+ tb_ticks_per_jiffy = freq / HZ;
+ tb_to_us = mulhwu_scale_factor(freq, 1000000);
+}
diff --git a/arch/ppc/platforms/cpci690.c b/arch/ppc/platforms/cpci690.c
new file mode 100644
index 0000000..507870c
--- /dev/null
+++ b/arch/ppc/platforms/cpci690.c
@@ -0,0 +1,491 @@
+/*
+ * arch/ppc/platforms/cpci690.c
+ *
+ * Board setup routines for the Force CPCI690 board.
+ *
+ * Author: Mark A. Greer <mgreer@mvista.com>
+ *
+ * 2003 (c) MontaVista Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This programr
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+#include <linux/config.h>
+#include <linux/delay.h>
+#include <linux/pci.h>
+#include <linux/ide.h>
+#include <linux/irq.h>
+#include <linux/fs.h>
+#include <linux/seq_file.h>
+#include <linux/console.h>
+#include <linux/initrd.h>
+#include <linux/root_dev.h>
+#include <linux/mv643xx.h>
+#include <asm/bootinfo.h>
+#include <asm/machdep.h>
+#include <asm/todc.h>
+#include <asm/time.h>
+#include <asm/mv64x60.h>
+#include <platforms/cpci690.h>
+
+#define BOARD_VENDOR "Force"
+#define BOARD_MACHINE "CPCI690"
+
+/* Set IDE controllers into Native mode? */
+#define SET_PCI_IDE_NATIVE
+
+static struct mv64x60_handle bh;
+static u32 cpci690_br_base;
+
+static const unsigned int cpu_7xx[16] = { /* 7xx & 74xx (but not 745x) */
+ 18, 15, 14, 2, 4, 13, 5, 9, 6, 11, 8, 10, 16, 12, 7, 0
+};
+
+TODC_ALLOC();
+
+static int __init
+cpci690_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin)
+{
+ struct pci_controller *hose = pci_bus_to_hose(dev->bus->number);
+
+ if (hose->index == 0) {
+ static char pci_irq_table[][4] =
+ /*
+ * PCI IDSEL/INTPIN->INTLINE
+ * A B C D
+ */
+ {
+ { 90, 91, 88, 89}, /* IDSEL 30/20 - Sentinel */
+ };
+
+ const long min_idsel = 20, max_idsel = 20, irqs_per_slot = 4;
+ return PCI_IRQ_TABLE_LOOKUP;
+ } else {
+ static char pci_irq_table[][4] =
+ /*
+ * PCI IDSEL/INTPIN->INTLINE
+ * A B C D
+ */
+ {
+ { 93, 94, 95, 92}, /* IDSEL 28/18 - PMC slot 2 */
+ { 0, 0, 0, 0}, /* IDSEL 29/19 - Not used */
+ { 94, 95, 92, 93}, /* IDSEL 30/20 - PMC slot 1 */
+ };
+
+ const long min_idsel = 18, max_idsel = 20, irqs_per_slot = 4;
+ return PCI_IRQ_TABLE_LOOKUP;
+ }
+}
+
+static int
+cpci690_get_cpu_speed(void)
+{
+ unsigned long hid1;
+
+ hid1 = mfspr(SPRN_HID1) >> 28;
+ return CPCI690_BUS_FREQ * cpu_7xx[hid1]/2;
+}
+
+#define KB (1024UL)
+#define MB (1024UL * KB)
+#define GB (1024UL * MB)
+
+unsigned long __init
+cpci690_find_end_of_memory(void)
+{
+ u32 mem_ctlr_size;
+ static u32 board_size;
+ static u8 first_time = 1;
+
+ if (first_time) {
+ /* Using cpci690_set_bat() mapping ==> virt addr == phys addr */
+ switch (in_8((u8 *) (cpci690_br_base +
+ CPCI690_BR_MEM_CTLR)) & 0x07) {
+ case 0x01:
+ board_size = 256*MB;
+ break;
+ case 0x02:
+ board_size = 512*MB;
+ break;
+ case 0x03:
+ board_size = 768*MB;
+ break;
+ case 0x04:
+ board_size = 1*GB;
+ break;
+ case 0x05:
+ board_size = 1*GB + 512*MB;
+ break;
+ case 0x06:
+ board_size = 2*GB;
+ break;
+ default:
+ board_size = 0xffffffff; /* use mem ctlr size */
+ } /* switch */
+
+ mem_ctlr_size = mv64x60_get_mem_size(CONFIG_MV64X60_NEW_BASE,
+ MV64x60_TYPE_GT64260A);
+
+ /* Check that mem ctlr & board reg agree. If not, pick MIN. */
+ if (board_size != mem_ctlr_size) {
+ printk(KERN_WARNING "Board register & memory controller"
+ "mem size disagree (board reg: 0x%lx, "
+ "mem ctlr: 0x%lx)\n",
+ (ulong)board_size, (ulong)mem_ctlr_size);
+ board_size = min(board_size, mem_ctlr_size);
+ }
+
+ first_time = 0;
+ } /* if */
+
+ return board_size;
+}
+
+static void __init
+cpci690_setup_bridge(void)
+{
+ struct mv64x60_setup_info si;
+ int i;
+
+ memset(&si, 0, sizeof(si));
+
+ si.phys_reg_base = CONFIG_MV64X60_NEW_BASE;
+
+ si.pci_0.enable_bus = 1;
+ si.pci_0.pci_io.cpu_base = CPCI690_PCI0_IO_START_PROC_ADDR;
+ si.pci_0.pci_io.pci_base_hi = 0;
+ si.pci_0.pci_io.pci_base_lo = CPCI690_PCI0_IO_START_PCI_ADDR;
+ si.pci_0.pci_io.size = CPCI690_PCI0_IO_SIZE;
+ si.pci_0.pci_io.swap = MV64x60_CPU2PCI_SWAP_NONE;
+ si.pci_0.pci_mem[0].cpu_base = CPCI690_PCI0_MEM_START_PROC_ADDR;
+ si.pci_0.pci_mem[0].pci_base_hi = CPCI690_PCI0_MEM_START_PCI_HI_ADDR;
+ si.pci_0.pci_mem[0].pci_base_lo = CPCI690_PCI0_MEM_START_PCI_LO_ADDR;
+ si.pci_0.pci_mem[0].size = CPCI690_PCI0_MEM_SIZE;
+ si.pci_0.pci_mem[0].swap = MV64x60_CPU2PCI_SWAP_NONE;
+ si.pci_0.pci_cmd_bits = 0;
+ si.pci_0.latency_timer = 0x80;
+
+ si.pci_1.enable_bus = 1;
+ si.pci_1.pci_io.cpu_base = CPCI690_PCI1_IO_START_PROC_ADDR;
+ si.pci_1.pci_io.pci_base_hi = 0;
+ si.pci_1.pci_io.pci_base_lo = CPCI690_PCI1_IO_START_PCI_ADDR;
+ si.pci_1.pci_io.size = CPCI690_PCI1_IO_SIZE;
+ si.pci_1.pci_io.swap = MV64x60_CPU2PCI_SWAP_NONE;
+ si.pci_1.pci_mem[0].cpu_base = CPCI690_PCI1_MEM_START_PROC_ADDR;
+ si.pci_1.pci_mem[0].pci_base_hi = CPCI690_PCI1_MEM_START_PCI_HI_ADDR;
+ si.pci_1.pci_mem[0].pci_base_lo = CPCI690_PCI1_MEM_START_PCI_LO_ADDR;
+ si.pci_1.pci_mem[0].size = CPCI690_PCI1_MEM_SIZE;
+ si.pci_1.pci_mem[0].swap = MV64x60_CPU2PCI_SWAP_NONE;
+ si.pci_1.pci_cmd_bits = 0;
+ si.pci_1.latency_timer = 0x80;
+
+ for (i=0; i<MV64x60_CPU2MEM_WINDOWS; i++) {
+ si.cpu_prot_options[i] = 0;
+ si.cpu_snoop_options[i] = GT64260_CPU_SNOOP_WB;
+ si.pci_0.acc_cntl_options[i] =
+ GT64260_PCI_ACC_CNTL_DREADEN |
+ GT64260_PCI_ACC_CNTL_RDPREFETCH |
+ GT64260_PCI_ACC_CNTL_RDLINEPREFETCH |
+ GT64260_PCI_ACC_CNTL_RDMULPREFETCH |
+ GT64260_PCI_ACC_CNTL_SWAP_NONE |
+ GT64260_PCI_ACC_CNTL_MBURST_32_BTYES;
+ si.pci_0.snoop_options[i] = GT64260_PCI_SNOOP_WB;
+ si.pci_1.acc_cntl_options[i] =
+ GT64260_PCI_ACC_CNTL_DREADEN |
+ GT64260_PCI_ACC_CNTL_RDPREFETCH |
+ GT64260_PCI_ACC_CNTL_RDLINEPREFETCH |
+ GT64260_PCI_ACC_CNTL_RDMULPREFETCH |
+ GT64260_PCI_ACC_CNTL_SWAP_NONE |
+ GT64260_PCI_ACC_CNTL_MBURST_32_BTYES;
+ si.pci_1.snoop_options[i] = GT64260_PCI_SNOOP_WB;
+ }
+
+ /* Lookup PCI host bridges */
+ if (mv64x60_init(&bh, &si))
+ printk(KERN_ERR "Bridge initialization failed.\n");
+
+ pci_dram_offset = 0; /* System mem at same addr on PCI & cpu bus */
+ ppc_md.pci_swizzle = common_swizzle;
+ ppc_md.pci_map_irq = cpci690_map_irq;
+ ppc_md.pci_exclude_device = mv64x60_pci_exclude_device;
+
+ mv64x60_set_bus(&bh, 0, 0);
+ bh.hose_a->first_busno = 0;
+ bh.hose_a->last_busno = 0xff;
+ bh.hose_a->last_busno = pciauto_bus_scan(bh.hose_a, 0);
+
+ bh.hose_b->first_busno = bh.hose_a->last_busno + 1;
+ mv64x60_set_bus(&bh, 1, bh.hose_b->first_busno);
+ bh.hose_b->last_busno = 0xff;
+ bh.hose_b->last_busno = pciauto_bus_scan(bh.hose_b,
+ bh.hose_b->first_busno);
+}
+
+static void __init
+cpci690_setup_peripherals(void)
+{
+ /* Set up windows to CPLD, RTC/TODC, IPMI. */
+ mv64x60_set_32bit_window(&bh, MV64x60_CPU2DEV_0_WIN, CPCI690_BR_BASE,
+ CPCI690_BR_SIZE, 0);
+ bh.ci->enable_window_32bit(&bh, MV64x60_CPU2DEV_0_WIN);
+ cpci690_br_base = (u32)ioremap(CPCI690_BR_BASE, CPCI690_BR_SIZE);
+
+ mv64x60_set_32bit_window(&bh, MV64x60_CPU2DEV_1_WIN, CPCI690_TODC_BASE,
+ CPCI690_TODC_SIZE, 0);
+ bh.ci->enable_window_32bit(&bh, MV64x60_CPU2DEV_1_WIN);
+ TODC_INIT(TODC_TYPE_MK48T35, 0, 0,
+ ioremap(CPCI690_TODC_BASE, CPCI690_TODC_SIZE), 8);
+
+ mv64x60_set_32bit_window(&bh, MV64x60_CPU2DEV_2_WIN, CPCI690_IPMI_BASE,
+ CPCI690_IPMI_SIZE, 0);
+ bh.ci->enable_window_32bit(&bh, MV64x60_CPU2DEV_2_WIN);
+
+ mv64x60_set_bits(&bh, MV64x60_PCI0_ARBITER_CNTL, (1<<31));
+ mv64x60_set_bits(&bh, MV64x60_PCI1_ARBITER_CNTL, (1<<31));
+
+ mv64x60_set_bits(&bh, MV64x60_CPU_MASTER_CNTL, (1<<9)); /* Only 1 cpu */
+
+ /*
+ * Turn off timer/counters. Not turning off watchdog timer because
+ * can't read its reg on the 64260A so don't know if we'll be enabling
+ * or disabling.
+ */
+ mv64x60_clr_bits(&bh, MV64x60_TIMR_CNTR_0_3_CNTL,
+ ((1<<0) | (1<<8) | (1<<16) | (1<<24)));
+ mv64x60_clr_bits(&bh, GT64260_TIMR_CNTR_4_7_CNTL,
+ ((1<<0) | (1<<8) | (1<<16) | (1<<24)));
+
+ /*
+ * Set MPSC Multiplex RMII
+ * NOTE: ethernet driver modifies bit 0 and 1
+ */
+ mv64x60_write(&bh, GT64260_MPP_SERIAL_PORTS_MULTIPLEX, 0x00001102);
+
+#define GPP_EXTERNAL_INTERRUPTS \
+ ((1<<24) | (1<<25) | (1<<26) | (1<<27) | \
+ (1<<28) | (1<<29) | (1<<30) | (1<<31))
+ /* PCI interrupts are inputs */
+ mv64x60_clr_bits(&bh, MV64x60_GPP_IO_CNTL, GPP_EXTERNAL_INTERRUPTS);
+ /* PCI interrupts are active low */
+ mv64x60_set_bits(&bh, MV64x60_GPP_LEVEL_CNTL, GPP_EXTERNAL_INTERRUPTS);
+
+ /* Clear any pending interrupts for these inputs and enable them. */
+ mv64x60_write(&bh, MV64x60_GPP_INTR_CAUSE, ~GPP_EXTERNAL_INTERRUPTS);
+ mv64x60_set_bits(&bh, MV64x60_GPP_INTR_MASK, GPP_EXTERNAL_INTERRUPTS);
+
+ /* Route MPP interrupt inputs to GPP */
+ mv64x60_write(&bh, MV64x60_MPP_CNTL_2, 0x00000000);
+ mv64x60_write(&bh, MV64x60_MPP_CNTL_3, 0x00000000);
+}
+
+static void __init
+cpci690_setup_arch(void)
+{
+ if (ppc_md.progress)
+ ppc_md.progress("cpci690_setup_arch: enter", 0);
+#ifdef CONFIG_BLK_DEV_INITRD
+ if (initrd_start)
+ ROOT_DEV = Root_RAM0;
+ else
+#endif
+#ifdef CONFIG_ROOT_NFS
+ ROOT_DEV = Root_NFS;
+#else
+ ROOT_DEV = Root_SDA2;
+#endif
+
+ if (ppc_md.progress)
+ ppc_md.progress("cpci690_setup_arch: Enabling L2 cache", 0);
+
+ /* Enable L2 and L3 caches (if 745x) */
+ _set_L2CR(_get_L2CR() | L2CR_L2E);
+ _set_L3CR(_get_L3CR() | L3CR_L3E);
+
+ if (ppc_md.progress)
+ ppc_md.progress("cpci690_setup_arch: Initializing bridge", 0);
+
+ cpci690_setup_bridge(); /* set up PCI bridge(s) */
+ cpci690_setup_peripherals(); /* set up chip selects/GPP/MPP etc */
+
+ if (ppc_md.progress)
+ ppc_md.progress("cpci690_setup_arch: bridge init complete", 0);
+
+ printk(KERN_INFO "%s %s port (C) 2003 MontaVista Software, Inc. "
+ "(source@mvista.com)\n", BOARD_VENDOR, BOARD_MACHINE);
+
+ if (ppc_md.progress)
+ ppc_md.progress("cpci690_setup_arch: exit", 0);
+}
+
+/* Platform device data fixup routines. */
+#if defined(CONFIG_SERIAL_MPSC)
+static void __init
+cpci690_fixup_mpsc_pdata(struct platform_device *pdev)
+{
+ struct mpsc_pdata *pdata;
+
+ pdata = (struct mpsc_pdata *)pdev->dev.platform_data;
+
+ pdata->max_idle = 40;
+ pdata->default_baud = CPCI690_MPSC_BAUD;
+ pdata->brg_clk_src = CPCI690_MPSC_CLK_SRC;
+ pdata->brg_clk_freq = CPCI690_BUS_FREQ;
+}
+
+static int __init
+cpci690_platform_notify(struct device *dev)
+{
+ static struct {
+ char *bus_id;
+ void ((*rtn)(struct platform_device *pdev));
+ } dev_map[] = {
+ { MPSC_CTLR_NAME ".0", cpci690_fixup_mpsc_pdata },
+ { MPSC_CTLR_NAME ".1", cpci690_fixup_mpsc_pdata },
+ };
+ struct platform_device *pdev;
+ int i;
+
+ if (dev && dev->bus_id)
+ for (i=0; i<ARRAY_SIZE(dev_map); i++)
+ if (!strncmp(dev->bus_id, dev_map[i].bus_id,
+ BUS_ID_SIZE)) {
+
+ pdev = container_of(dev,
+ struct platform_device, dev);
+ dev_map[i].rtn(pdev);
+ }
+
+ return 0;
+}
+#endif
+
+static void
+cpci690_reset_board(void)
+{
+ u32 i = 10000;
+
+ local_irq_disable();
+ out_8((u8 *)(cpci690_br_base + CPCI690_BR_SW_RESET), 0x11);
+
+ while (i != 0) i++;
+ panic("restart failed\n");
+}
+
+static void
+cpci690_restart(char *cmd)
+{
+ cpci690_reset_board();
+}
+
+static void
+cpci690_halt(void)
+{
+ while (1);
+ /* NOTREACHED */
+}
+
+static void
+cpci690_power_off(void)
+{
+ cpci690_halt();
+ /* NOTREACHED */
+}
+
+static int
+cpci690_show_cpuinfo(struct seq_file *m)
+{
+ seq_printf(m, "vendor\t\t: " BOARD_VENDOR "\n");
+ seq_printf(m, "machine\t\t: " BOARD_MACHINE "\n");
+ seq_printf(m, "cpu MHz\t\t: %d\n", cpci690_get_cpu_speed()/1000/1000);
+ seq_printf(m, "bus MHz\t\t: %d\n", CPCI690_BUS_FREQ/1000/1000);
+
+ return 0;
+}
+
+static void __init
+cpci690_calibrate_decr(void)
+{
+ ulong freq;
+
+ freq = CPCI690_BUS_FREQ / 4;
+
+ printk(KERN_INFO "time_init: decrementer frequency = %lu.%.6lu MHz\n",
+ freq/1000000, freq%1000000);
+
+ tb_ticks_per_jiffy = freq / HZ;
+ tb_to_us = mulhwu_scale_factor(freq, 1000000);
+}
+
+static __inline__ void
+cpci690_set_bat(u32 addr, u32 size)
+{
+ addr &= 0xfffe0000;
+ size &= 0x1ffe0000;
+ size = ((size >> 17) - 1) << 2;
+
+ mb();
+ mtspr(SPRN_DBAT1U, addr | size | 0x2); /* Vs == 1; Vp == 0 */
+ mtspr(SPRN_DBAT1L, addr | 0x2a); /* WIMG bits == 0101; PP == r/w access */
+ mb();
+}
+
+#if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB)
+static void __init
+cpci690_map_io(void)
+{
+ io_block_mapping(CONFIG_MV64X60_NEW_BASE, CONFIG_MV64X60_NEW_BASE,
+ 128 * KB, _PAGE_IO);
+}
+#endif
+
+void __init
+platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
+ unsigned long r6, unsigned long r7)
+{
+#ifdef CONFIG_BLK_DEV_INITRD
+ initrd_start=initrd_end=0;
+ initrd_below_start_ok=0;
+#endif /* CONFIG_BLK_DEV_INITRD */
+
+ parse_bootinfo(find_bootinfo());
+
+ loops_per_jiffy = cpci690_get_cpu_speed() / HZ;
+
+ isa_mem_base = 0;
+
+ ppc_md.setup_arch = cpci690_setup_arch;
+ ppc_md.show_cpuinfo = cpci690_show_cpuinfo;
+ ppc_md.init_IRQ = gt64260_init_irq;
+ ppc_md.get_irq = gt64260_get_irq;
+ ppc_md.restart = cpci690_restart;
+ ppc_md.power_off = cpci690_power_off;
+ ppc_md.halt = cpci690_halt;
+ ppc_md.find_end_of_memory = cpci690_find_end_of_memory;
+ ppc_md.time_init = todc_time_init;
+ ppc_md.set_rtc_time = todc_set_rtc_time;
+ ppc_md.get_rtc_time = todc_get_rtc_time;
+ ppc_md.nvram_read_val = todc_direct_read_val;
+ ppc_md.nvram_write_val = todc_direct_write_val;
+ ppc_md.calibrate_decr = cpci690_calibrate_decr;
+
+ /*
+ * Need to map in board regs (used by cpci690_find_end_of_memory())
+ * and the bridge's regs (used by progress);
+ */
+ cpci690_set_bat(CPCI690_BR_BASE, 32 * MB);
+ cpci690_br_base = CPCI690_BR_BASE;
+
+#ifdef CONFIG_SERIAL_TEXT_DEBUG
+ ppc_md.setup_io_mappings = cpci690_map_io;
+ ppc_md.progress = mv64x60_mpsc_progress;
+ mv64x60_progress_init(CONFIG_MV64X60_NEW_BASE);
+#endif /* CONFIG_SERIAL_TEXT_DEBUG */
+#ifdef CONFIG_KGDB
+ ppc_md.setup_io_mappings = cpci690_map_io;
+ ppc_md.early_serial_map = cpci690_early_serial_map;
+#endif /* CONFIG_KGDB */
+
+#if defined(CONFIG_SERIAL_MPSC)
+ platform_notify = cpci690_platform_notify;
+#endif
+}
diff --git a/arch/ppc/platforms/cpci690.h b/arch/ppc/platforms/cpci690.h
new file mode 100644
index 0000000..36cd267
--- /dev/null
+++ b/arch/ppc/platforms/cpci690.h
@@ -0,0 +1,78 @@
+/*
+ * arch/ppc/platforms/cpci690.h
+ *
+ * Definitions for Force CPCI690
+ *
+ * Author: Mark A. Greer <mgreer@mvista.com>
+ *
+ * 2003 (c) MontaVista, Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+
+/*
+ * The GT64260 has 2 PCI buses each with 1 window from the CPU bus to
+ * PCI I/O space and 4 windows from the CPU bus to PCI MEM space.
+ */
+
+#ifndef __PPC_PLATFORMS_CPCI690_H
+#define __PPC_PLATFORMS_CPCI690_H
+
+/*
+ * Define bd_t to pass in the MAC addresses used by the GT64260's enet ctlrs.
+ */
+#define CPCI690_BI_MAGIC 0xFE8765DC
+
+typedef struct board_info {
+ u32 bi_magic;
+ u8 bi_enetaddr[3][6];
+} bd_t;
+
+/* PCI bus Resource setup */
+#define CPCI690_PCI0_MEM_START_PROC_ADDR 0x80000000
+#define CPCI690_PCI0_MEM_START_PCI_HI_ADDR 0x00000000
+#define CPCI690_PCI0_MEM_START_PCI_LO_ADDR 0x80000000
+#define CPCI690_PCI0_MEM_SIZE 0x10000000
+#define CPCI690_PCI0_IO_START_PROC_ADDR 0xa0000000
+#define CPCI690_PCI0_IO_START_PCI_ADDR 0x00000000
+#define CPCI690_PCI0_IO_SIZE 0x01000000
+
+#define CPCI690_PCI1_MEM_START_PROC_ADDR 0x90000000
+#define CPCI690_PCI1_MEM_START_PCI_HI_ADDR 0x00000000
+#define CPCI690_PCI1_MEM_START_PCI_LO_ADDR 0x90000000
+#define CPCI690_PCI1_MEM_SIZE 0x10000000
+#define CPCI690_PCI1_IO_START_PROC_ADDR 0xa1000000
+#define CPCI690_PCI1_IO_START_PCI_ADDR 0x01000000
+#define CPCI690_PCI1_IO_SIZE 0x01000000
+
+/* Board Registers */
+#define CPCI690_BR_BASE 0xf0000000
+#define CPCI690_BR_SIZE_ACTUAL 0x8
+#define CPCI690_BR_SIZE max(GT64260_WINDOW_SIZE_MIN, \
+ CPCI690_BR_SIZE_ACTUAL)
+#define CPCI690_BR_LED_CNTL 0x00
+#define CPCI690_BR_SW_RESET 0x01
+#define CPCI690_BR_MISC_STATUS 0x02
+#define CPCI690_BR_SWITCH_STATUS 0x03
+#define CPCI690_BR_MEM_CTLR 0x04
+#define CPCI690_BR_LAST_RESET_1 0x05
+#define CPCI690_BR_LAST_RESET_2 0x06
+
+#define CPCI690_TODC_BASE 0xf0100000
+#define CPCI690_TODC_SIZE_ACTUAL 0x8000 /* Size or NVRAM + RTC */
+#define CPCI690_TODC_SIZE max(GT64260_WINDOW_SIZE_MIN, \
+ CPCI690_TODC_SIZE_ACTUAL)
+#define CPCI690_MAC_OFFSET 0x7c10 /* MAC in RTC NVRAM */
+
+#define CPCI690_IPMI_BASE 0xf0200000
+#define CPCI690_IPMI_SIZE_ACTUAL 0x10 /* 16 bytes of IPMI */
+#define CPCI690_IPMI_SIZE max(GT64260_WINDOW_SIZE_MIN, \
+ CPCI690_IPMI_SIZE_ACTUAL)
+
+#define CPCI690_MPSC_BAUD 9600
+#define CPCI690_MPSC_CLK_SRC 8 /* TCLK */
+
+#define CPCI690_BUS_FREQ 133333333
+
+#endif /* __PPC_PLATFORMS_CPCI690_H */
diff --git a/arch/ppc/platforms/est8260.h b/arch/ppc/platforms/est8260.h
new file mode 100644
index 0000000..adba68e
--- /dev/null
+++ b/arch/ppc/platforms/est8260.h
@@ -0,0 +1,35 @@
+/* Board information for the EST8260, which should be generic for
+ * all 8260 boards. The IMMR is now given to us so the hard define
+ * will soon be removed. All of the clock values are computed from
+ * the configuration SCMR and the Power-On-Reset word.
+ */
+#ifndef __EST8260_PLATFORM
+#define __EST8260_PLATFORM
+
+#define CPM_MAP_ADDR ((uint)0xf0000000)
+
+#define BOOTROM_RESTART_ADDR ((uint)0xff000104)
+
+/* For our show_cpuinfo hooks. */
+#define CPUINFO_VENDOR "EST Corporation"
+#define CPUINFO_MACHINE "SBC8260 PowerPC"
+
+/* A Board Information structure that is given to a program when
+ * prom starts it up.
+ */
+typedef struct bd_info {
+ unsigned int bi_memstart; /* Memory start address */
+ unsigned int bi_memsize; /* Memory (end) size in bytes */
+ unsigned int bi_intfreq; /* Internal Freq, in Hz */
+ unsigned int bi_busfreq; /* Bus Freq, in MHz */
+ unsigned int bi_cpmfreq; /* CPM Freq, in MHz */
+ unsigned int bi_brgfreq; /* BRG Freq, in MHz */
+ unsigned int bi_vco; /* VCO Out from PLL */
+ unsigned int bi_baudrate; /* Default console baud rate */
+ unsigned int bi_immr; /* IMMR when called from boot rom */
+ unsigned char bi_enetaddr[6];
+} bd_t;
+
+extern bd_t m8xx_board_info;
+
+#endif /* __EST8260_PLATFORM */
diff --git a/arch/ppc/platforms/ev64260.c b/arch/ppc/platforms/ev64260.c
new file mode 100644
index 0000000..aa50637
--- /dev/null
+++ b/arch/ppc/platforms/ev64260.c
@@ -0,0 +1,651 @@
+/*
+ * arch/ppc/platforms/ev64260.c
+ *
+ * Board setup routines for the Marvell/Galileo EV-64260-BP Evaluation Board.
+ *
+ * Author: Mark A. Greer <mgreer@mvista.com>
+ *
+ * 2001-2003 (c) MontaVista, Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+
+/*
+ * The EV-64260-BP port is the result of hard work from many people from
+ * many companies. In particular, employees of Marvell/Galileo, Mission
+ * Critical Linux, Xyterra, and MontaVista Software were heavily involved.
+ *
+ * Note: I have not been able to get *all* PCI slots to work reliably
+ * at 66 MHz. I recommend setting jumpers J15 & J16 to short pins 1&2
+ * so that 33 MHz is used. --MAG
+ * Note: The 750CXe and 7450 are not stable with a 125MHz or 133MHz TCLK/SYSCLK.
+ * At 100MHz, they are solid.
+ */
+#include <linux/config.h>
+
+#include <linux/delay.h>
+#include <linux/pci.h>
+#include <linux/ide.h>
+#include <linux/irq.h>
+#include <linux/fs.h>
+#include <linux/seq_file.h>
+#include <linux/console.h>
+#include <linux/initrd.h>
+#include <linux/root_dev.h>
+#if !defined(CONFIG_SERIAL_MPSC_CONSOLE)
+#include <linux/serial.h>
+#include <linux/tty.h>
+#include <linux/serial_core.h>
+#else
+#include <linux/mv643xx.h>
+#endif
+#include <asm/bootinfo.h>
+#include <asm/machdep.h>
+#include <asm/mv64x60.h>
+#include <asm/todc.h>
+#include <asm/time.h>
+
+#include <platforms/ev64260.h>
+
+#define BOARD_VENDOR "Marvell/Galileo"
+#define BOARD_MACHINE "EV-64260-BP"
+
+static struct mv64x60_handle bh;
+
+#if !defined(CONFIG_SERIAL_MPSC_CONSOLE)
+extern void gen550_progress(char *, unsigned short);
+extern void gen550_init(int, struct uart_port *);
+#endif
+
+static const unsigned int cpu_7xx[16] = { /* 7xx & 74xx (but not 745x) */
+ 18, 15, 14, 2, 4, 13, 5, 9, 6, 11, 8, 10, 16, 12, 7, 0
+};
+static const unsigned int cpu_745x[2][16] = { /* PLL_EXT 0 & 1 */
+ { 1, 15, 14, 2, 4, 13, 5, 9, 6, 11, 8, 10, 16, 12, 7, 0 },
+ { 0, 30, 0, 2, 0, 26, 0, 18, 0, 22, 20, 24, 28, 32, 0, 0 }
+};
+
+
+TODC_ALLOC();
+
+static int
+ev64260_get_bus_speed(void)
+{
+ return 100000000;
+}
+
+static int
+ev64260_get_cpu_speed(void)
+{
+ unsigned long pvr, hid1, pll_ext;
+
+ pvr = PVR_VER(mfspr(SPRN_PVR));
+
+ if (pvr != PVR_VER(PVR_7450)) {
+ hid1 = mfspr(SPRN_HID1) >> 28;
+ return ev64260_get_bus_speed() * cpu_7xx[hid1]/2;
+ }
+ else {
+ hid1 = (mfspr(SPRN_HID1) & 0x0001e000) >> 13;
+ pll_ext = 0; /* No way to read; must get from schematic */
+ return ev64260_get_bus_speed() * cpu_745x[pll_ext][hid1]/2;
+ }
+}
+
+unsigned long __init
+ev64260_find_end_of_memory(void)
+{
+ return mv64x60_get_mem_size(CONFIG_MV64X60_NEW_BASE,
+ MV64x60_TYPE_GT64260A);
+}
+
+/*
+ * Marvell/Galileo EV-64260-BP Evaluation Board PCI interrupt routing.
+ * Note: By playing with J8 and JP1-4, you can get 2 IRQ's from the first
+ * PCI bus (in which cast, INTPIN B would be EV64260_PCI_1_IRQ).
+ * This is the most IRQs you can get from one bus with this board, though.
+ */
+static int __init
+ev64260_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin)
+{
+ struct pci_controller *hose = pci_bus_to_hose(dev->bus->number);
+
+ if (hose->index == 0) {
+ static char pci_irq_table[][4] =
+ /*
+ * PCI IDSEL/INTPIN->INTLINE
+ * A B C D
+ */
+ {
+ {EV64260_PCI_0_IRQ,0,0,0}, /* IDSEL 7 - PCI bus 0 */
+ {EV64260_PCI_0_IRQ,0,0,0}, /* IDSEL 8 - PCI bus 0 */
+ };
+
+ const long min_idsel = 7, max_idsel = 8, irqs_per_slot = 4;
+ return PCI_IRQ_TABLE_LOOKUP;
+ }
+ else {
+ static char pci_irq_table[][4] =
+ /*
+ * PCI IDSEL/INTPIN->INTLINE
+ * A B C D
+ */
+ {
+ { EV64260_PCI_1_IRQ,0,0,0}, /* IDSEL 7 - PCI bus 1 */
+ { EV64260_PCI_1_IRQ,0,0,0}, /* IDSEL 8 - PCI bus 1 */
+ };
+
+ const long min_idsel = 7, max_idsel = 8, irqs_per_slot = 4;
+ return PCI_IRQ_TABLE_LOOKUP;
+ }
+}
+
+static void __init
+ev64260_setup_peripherals(void)
+{
+ mv64x60_set_32bit_window(&bh, MV64x60_CPU2BOOT_WIN,
+ EV64260_EMB_FLASH_BASE, EV64260_EMB_FLASH_SIZE, 0);
+ bh.ci->enable_window_32bit(&bh, MV64x60_CPU2BOOT_WIN);
+ mv64x60_set_32bit_window(&bh, MV64x60_CPU2DEV_0_WIN,
+ EV64260_EXT_SRAM_BASE, EV64260_EXT_SRAM_SIZE, 0);
+ bh.ci->enable_window_32bit(&bh, MV64x60_CPU2DEV_0_WIN);
+ mv64x60_set_32bit_window(&bh, MV64x60_CPU2DEV_1_WIN,
+ EV64260_TODC_BASE, EV64260_TODC_SIZE, 0);
+ bh.ci->enable_window_32bit(&bh, MV64x60_CPU2DEV_1_WIN);
+ mv64x60_set_32bit_window(&bh, MV64x60_CPU2DEV_2_WIN,
+ EV64260_UART_BASE, EV64260_UART_SIZE, 0);
+ bh.ci->enable_window_32bit(&bh, MV64x60_CPU2DEV_2_WIN);
+ mv64x60_set_32bit_window(&bh, MV64x60_CPU2DEV_3_WIN,
+ EV64260_EXT_FLASH_BASE, EV64260_EXT_FLASH_SIZE, 0);
+ bh.ci->enable_window_32bit(&bh, MV64x60_CPU2DEV_3_WIN);
+
+ TODC_INIT(TODC_TYPE_DS1501, 0, 0,
+ ioremap(EV64260_TODC_BASE, EV64260_TODC_SIZE), 8);
+
+ mv64x60_clr_bits(&bh, MV64x60_CPU_CONFIG,((1<<12) | (1<<28) | (1<<29)));
+ mv64x60_set_bits(&bh, MV64x60_CPU_CONFIG, (1<<27));
+
+ if (ev64260_get_bus_speed() > 100000000)
+ mv64x60_set_bits(&bh, MV64x60_CPU_CONFIG, (1<<23));
+
+ mv64x60_set_bits(&bh, MV64x60_PCI0_PCI_DECODE_CNTL, ((1<<0) | (1<<3)));
+ mv64x60_set_bits(&bh, MV64x60_PCI1_PCI_DECODE_CNTL, ((1<<0) | (1<<3)));
+
+ /*
+ * Enabling of PCI internal-vs-external arbitration
+ * is a platform- and errata-dependent decision.
+ */
+ if (bh.type == MV64x60_TYPE_GT64260A ) {
+ mv64x60_set_bits(&bh, MV64x60_PCI0_ARBITER_CNTL, (1<<31));
+ mv64x60_set_bits(&bh, MV64x60_PCI1_ARBITER_CNTL, (1<<31));
+ }
+
+ mv64x60_set_bits(&bh, MV64x60_CPU_MASTER_CNTL, (1<<9)); /* Only 1 cpu */
+
+ /*
+ * Turn off timer/counters. Not turning off watchdog timer because
+ * can't read its reg on the 64260A so don't know if we'll be enabling
+ * or disabling.
+ */
+ mv64x60_clr_bits(&bh, MV64x60_TIMR_CNTR_0_3_CNTL,
+ ((1<<0) | (1<<8) | (1<<16) | (1<<24)));
+ mv64x60_clr_bits(&bh, GT64260_TIMR_CNTR_4_7_CNTL,
+ ((1<<0) | (1<<8) | (1<<16) | (1<<24)));
+
+ /*
+ * Set MPSC Multiplex RMII
+ * NOTE: ethernet driver modifies bit 0 and 1
+ */
+ mv64x60_write(&bh, GT64260_MPP_SERIAL_PORTS_MULTIPLEX, 0x00001102);
+
+ /*
+ * The EV-64260-BP uses several Multi-Purpose Pins (MPP) on the 64260
+ * bridge as interrupt inputs (via the General Purpose Ports (GPP)
+ * register). Need to route the MPP inputs to the GPP and set the
+ * polarity correctly.
+ *
+ * In MPP Control 2 Register
+ * MPP 21 -> GPP 21 (DUART channel A intr) bits 20-23 -> 0
+ * MPP 22 -> GPP 22 (DUART channel B intr) bits 24-27 -> 0
+ */
+ mv64x60_clr_bits(&bh, MV64x60_MPP_CNTL_2, (0xf<<20) | (0xf<<24) );
+
+ /*
+ * In MPP Control 3 Register
+ * MPP 26 -> GPP 26 (RTC INT) bits 8-11 -> 0
+ * MPP 27 -> GPP 27 (PCI 0 INTA) bits 12-15 -> 0
+ * MPP 29 -> GPP 29 (PCI 1 INTA) bits 20-23 -> 0
+ */
+ mv64x60_clr_bits(&bh, MV64x60_MPP_CNTL_3, (0xf<<8)|(0xf<<12)|(0xf<<20));
+
+#define GPP_EXTERNAL_INTERRUPTS \
+ ((1<<21) | (1<<22) | (1<<26) | (1<<27) | (1<<29))
+ /* DUART & PCI interrupts are inputs */
+ mv64x60_clr_bits(&bh, MV64x60_GPP_IO_CNTL, GPP_EXTERNAL_INTERRUPTS);
+ /* DUART & PCI interrupts are active low */
+ mv64x60_set_bits(&bh, MV64x60_GPP_LEVEL_CNTL, GPP_EXTERNAL_INTERRUPTS);
+
+ /* Clear any pending interrupts for these inputs and enable them. */
+ mv64x60_write(&bh, MV64x60_GPP_INTR_CAUSE, ~GPP_EXTERNAL_INTERRUPTS);
+ mv64x60_set_bits(&bh, MV64x60_GPP_INTR_MASK, GPP_EXTERNAL_INTERRUPTS);
+
+ return;
+}
+
+static void __init
+ev64260_setup_bridge(void)
+{
+ struct mv64x60_setup_info si;
+ int i;
+
+ memset(&si, 0, sizeof(si));
+
+ si.phys_reg_base = CONFIG_MV64X60_NEW_BASE;
+
+ si.pci_0.enable_bus = 1;
+ si.pci_0.pci_io.cpu_base = EV64260_PCI0_IO_CPU_BASE;
+ si.pci_0.pci_io.pci_base_hi = 0;
+ si.pci_0.pci_io.pci_base_lo = EV64260_PCI0_IO_PCI_BASE;
+ si.pci_0.pci_io.size = EV64260_PCI0_IO_SIZE;
+ si.pci_0.pci_io.swap = MV64x60_CPU2PCI_SWAP_NONE;
+ si.pci_0.pci_mem[0].cpu_base = EV64260_PCI0_MEM_CPU_BASE;
+ si.pci_0.pci_mem[0].pci_base_hi = 0;
+ si.pci_0.pci_mem[0].pci_base_lo = EV64260_PCI0_MEM_PCI_BASE;
+ si.pci_0.pci_mem[0].size = EV64260_PCI0_MEM_SIZE;
+ si.pci_0.pci_mem[0].swap = MV64x60_CPU2PCI_SWAP_NONE;
+ si.pci_0.pci_cmd_bits = 0;
+ si.pci_0.latency_timer = 0x8;
+
+ si.pci_1.enable_bus = 1;
+ si.pci_1.pci_io.cpu_base = EV64260_PCI1_IO_CPU_BASE;
+ si.pci_1.pci_io.pci_base_hi = 0;
+ si.pci_1.pci_io.pci_base_lo = EV64260_PCI1_IO_PCI_BASE;
+ si.pci_1.pci_io.size = EV64260_PCI1_IO_SIZE;
+ si.pci_1.pci_io.swap = MV64x60_CPU2PCI_SWAP_NONE;
+ si.pci_1.pci_mem[0].cpu_base = EV64260_PCI1_MEM_CPU_BASE;
+ si.pci_1.pci_mem[0].pci_base_hi = 0;
+ si.pci_1.pci_mem[0].pci_base_lo = EV64260_PCI1_MEM_PCI_BASE;
+ si.pci_1.pci_mem[0].size = EV64260_PCI1_MEM_SIZE;
+ si.pci_1.pci_mem[0].swap = MV64x60_CPU2PCI_SWAP_NONE;
+ si.pci_1.pci_cmd_bits = 0;
+ si.pci_1.latency_timer = 0x8;
+
+ for (i=0; i<MV64x60_CPU2MEM_WINDOWS; i++) {
+ si.cpu_prot_options[i] = 0;
+ si.cpu_snoop_options[i] = GT64260_CPU_SNOOP_WB;
+ si.pci_0.acc_cntl_options[i] =
+ GT64260_PCI_ACC_CNTL_DREADEN |
+ GT64260_PCI_ACC_CNTL_RDPREFETCH |
+ GT64260_PCI_ACC_CNTL_RDLINEPREFETCH |
+ GT64260_PCI_ACC_CNTL_RDMULPREFETCH |
+ GT64260_PCI_ACC_CNTL_SWAP_NONE |
+ GT64260_PCI_ACC_CNTL_MBURST_32_BTYES;
+ si.pci_0.snoop_options[i] = GT64260_PCI_SNOOP_WB;
+ si.pci_1.acc_cntl_options[i] =
+ GT64260_PCI_ACC_CNTL_DREADEN |
+ GT64260_PCI_ACC_CNTL_RDPREFETCH |
+ GT64260_PCI_ACC_CNTL_RDLINEPREFETCH |
+ GT64260_PCI_ACC_CNTL_RDMULPREFETCH |
+ GT64260_PCI_ACC_CNTL_SWAP_NONE |
+ GT64260_PCI_ACC_CNTL_MBURST_32_BTYES;
+ si.pci_1.snoop_options[i] = GT64260_PCI_SNOOP_WB;
+ }
+
+ /* Lookup PCI host bridges */
+ if (mv64x60_init(&bh, &si))
+ printk(KERN_ERR "Bridge initialization failed.\n");
+
+ pci_dram_offset = 0; /* System mem at same addr on PCI & cpu bus */
+ ppc_md.pci_swizzle = common_swizzle;
+ ppc_md.pci_map_irq = ev64260_map_irq;
+ ppc_md.pci_exclude_device = mv64x60_pci_exclude_device;
+
+ mv64x60_set_bus(&bh, 0, 0);
+ bh.hose_a->first_busno = 0;
+ bh.hose_a->last_busno = 0xff;
+ bh.hose_a->last_busno = pciauto_bus_scan(bh.hose_a, 0);
+
+ bh.hose_b->first_busno = bh.hose_a->last_busno + 1;
+ mv64x60_set_bus(&bh, 1, bh.hose_b->first_busno);
+ bh.hose_b->last_busno = 0xff;
+ bh.hose_b->last_busno = pciauto_bus_scan(bh.hose_b,
+ bh.hose_b->first_busno);
+
+ return;
+}
+
+#if defined(CONFIG_SERIAL_8250) && !defined(CONFIG_SERIAL_MPSC_CONSOLE)
+static void __init
+ev64260_early_serial_map(void)
+{
+ struct uart_port port;
+ static char first_time = 1;
+
+ if (first_time) {
+ memset(&port, 0, sizeof(port));
+
+ port.membase = ioremap(EV64260_SERIAL_0, EV64260_UART_SIZE);
+ port.irq = EV64260_UART_0_IRQ;
+ port.uartclk = BASE_BAUD * 16;
+ port.regshift = 2;
+ port.iotype = SERIAL_IO_MEM;
+ port.flags = STD_COM_FLAGS;
+
+#if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB)
+ gen550_init(0, &port);
+#endif
+
+ if (early_serial_setup(&port) != 0)
+ printk(KERN_WARNING "Early serial init of port 0"
+ "failed\n");
+
+ first_time = 0;
+ }
+
+ return;
+}
+#elif defined(CONFIG_SERIAL_MPSC_CONSOLE)
+static void __init
+ev64260_early_serial_map(void)
+{
+}
+#endif
+
+static void __init
+ev64260_setup_arch(void)
+{
+ if (ppc_md.progress)
+ ppc_md.progress("ev64260_setup_arch: enter", 0);
+
+#ifdef CONFIG_BLK_DEV_INITRD
+ if (initrd_start)
+ ROOT_DEV = Root_RAM0;
+ else
+#endif
+#ifdef CONFIG_ROOT_NFS
+ ROOT_DEV = Root_NFS;
+#else
+ ROOT_DEV = Root_SDA2;
+#endif
+
+ if (ppc_md.progress)
+ ppc_md.progress("ev64260_setup_arch: Enabling L2 cache", 0);
+
+ /* Enable L2 and L3 caches (if 745x) */
+ _set_L2CR(_get_L2CR() | L2CR_L2E);
+ _set_L3CR(_get_L3CR() | L3CR_L3E);
+
+ if (ppc_md.progress)
+ ppc_md.progress("ev64260_setup_arch: Initializing bridge", 0);
+
+ ev64260_setup_bridge(); /* set up PCI bridge(s) */
+ ev64260_setup_peripherals(); /* set up chip selects/GPP/MPP etc */
+
+ if (ppc_md.progress)
+ ppc_md.progress("ev64260_setup_arch: bridge init complete", 0);
+
+#if defined(CONFIG_SERIAL_8250) || defined(CONFIG_SERIAL_MPSC_CONSOLE)
+ ev64260_early_serial_map();
+#endif
+
+ printk(KERN_INFO "%s %s port (C) 2001 MontaVista Software, Inc."
+ "(source@mvista.com)\n", BOARD_VENDOR, BOARD_MACHINE);
+
+ if (ppc_md.progress)
+ ppc_md.progress("ev64260_setup_arch: exit", 0);
+
+ return;
+}
+
+/* Platform device data fixup routines. */
+#if defined(CONFIG_SERIAL_MPSC)
+static void __init
+ev64260_fixup_mpsc_pdata(struct platform_device *pdev)
+{
+ struct mpsc_pdata *pdata;
+
+ pdata = (struct mpsc_pdata *)pdev->dev.platform_data;
+
+ pdata->max_idle = 40;
+ pdata->default_baud = EV64260_DEFAULT_BAUD;
+ pdata->brg_clk_src = EV64260_MPSC_CLK_SRC;
+ pdata->brg_clk_freq = EV64260_MPSC_CLK_FREQ;
+
+ return;
+}
+
+static int __init
+ev64260_platform_notify(struct device *dev)
+{
+ static struct {
+ char *bus_id;
+ void ((*rtn)(struct platform_device *pdev));
+ } dev_map[] = {
+ { MPSC_CTLR_NAME ".0", ev64260_fixup_mpsc_pdata },
+ { MPSC_CTLR_NAME ".1", ev64260_fixup_mpsc_pdata },
+ };
+ struct platform_device *pdev;
+ int i;
+
+ if (dev && dev->bus_id)
+ for (i=0; i<ARRAY_SIZE(dev_map); i++)
+ if (!strncmp(dev->bus_id, dev_map[i].bus_id,
+ BUS_ID_SIZE)) {
+
+ pdev = container_of(dev,
+ struct platform_device, dev);
+ dev_map[i].rtn(pdev);
+ }
+
+ return 0;
+}
+#endif
+
+static void
+ev64260_reset_board(void *addr)
+{
+ local_irq_disable();
+
+ /* disable and invalidate the L2 cache */
+ _set_L2CR(0);
+ _set_L2CR(0x200000);
+
+ /* flush and disable L1 I/D cache */
+ __asm__ __volatile__
+ ("mfspr 3,1008\n\t"
+ "ori 5,5,0xcc00\n\t"
+ "ori 4,3,0xc00\n\t"
+ "andc 5,3,5\n\t"
+ "sync\n\t"
+ "mtspr 1008,4\n\t"
+ "isync\n\t"
+ "sync\n\t"
+ "mtspr 1008,5\n\t"
+ "isync\n\t"
+ "sync\n\t");
+
+ /* unmap any other random cs's that might overlap with bootcs */
+ mv64x60_set_32bit_window(&bh, MV64x60_CPU2DEV_0_WIN, 0, 0, 0);
+ bh.ci->disable_window_32bit(&bh, MV64x60_CPU2DEV_0_WIN);
+ mv64x60_set_32bit_window(&bh, MV64x60_CPU2DEV_1_WIN, 0, 0, 0);
+ bh.ci->disable_window_32bit(&bh, MV64x60_CPU2DEV_1_WIN);
+ mv64x60_set_32bit_window(&bh, MV64x60_CPU2DEV_2_WIN, 0, 0, 0);
+ bh.ci->disable_window_32bit(&bh, MV64x60_CPU2DEV_2_WIN);
+ mv64x60_set_32bit_window(&bh, MV64x60_CPU2DEV_3_WIN, 0, 0, 0);
+ bh.ci->disable_window_32bit(&bh, MV64x60_CPU2DEV_3_WIN);
+
+ /* map bootrom back in to gt @ reset defaults */
+ mv64x60_set_32bit_window(&bh, MV64x60_CPU2BOOT_WIN,
+ 0xff800000, 8*1024*1024, 0);
+ bh.ci->enable_window_32bit(&bh, MV64x60_CPU2BOOT_WIN);
+
+ /* move reg base back to default, setup default pci0 */
+ mv64x60_write(&bh, MV64x60_INTERNAL_SPACE_DECODE,
+ (1<<24) | CONFIG_MV64X60_BASE >> 20);
+
+ /* NOTE: FROM NOW ON no more GT_REGS accesses.. 0x1 is not mapped
+ * via BAT or MMU, and MSR IR/DR is ON */
+ /* SRR0 has system reset vector, SRR1 has default MSR value */
+ /* rfi restores MSR from SRR1 and sets the PC to the SRR0 value */
+ /* NOTE: assumes reset vector is at 0xfff00100 */
+ __asm__ __volatile__
+ ("mtspr 26, %0\n\t"
+ "li 4,(1<<6)\n\t"
+ "mtspr 27,4\n\t"
+ "rfi\n\t"
+ :: "r" (addr):"r4");
+
+ return;
+}
+
+static void
+ev64260_restart(char *cmd)
+{
+ volatile ulong i = 10000000;
+
+ ev64260_reset_board((void *)0xfff00100);
+
+ while (i-- > 0);
+ panic("restart failed\n");
+}
+
+static void
+ev64260_halt(void)
+{
+ local_irq_disable();
+ while (1);
+ /* NOTREACHED */
+}
+
+static void
+ev64260_power_off(void)
+{
+ ev64260_halt();
+ /* NOTREACHED */
+}
+
+static int
+ev64260_show_cpuinfo(struct seq_file *m)
+{
+ uint pvid;
+
+ pvid = mfspr(SPRN_PVR);
+ seq_printf(m, "vendor\t\t: " BOARD_VENDOR "\n");
+ seq_printf(m, "machine\t\t: " BOARD_MACHINE "\n");
+ seq_printf(m, "cpu MHz\t\t: %d\n", ev64260_get_cpu_speed()/1000/1000);
+ seq_printf(m, "bus MHz\t\t: %d\n", ev64260_get_bus_speed()/1000/1000);
+
+ return 0;
+}
+
+/* DS1501 RTC has too much variation to use RTC for calibration */
+static void __init
+ev64260_calibrate_decr(void)
+{
+ ulong freq;
+
+ freq = ev64260_get_bus_speed()/4;
+
+ printk(KERN_INFO "time_init: decrementer frequency = %lu.%.6lu MHz\n",
+ freq/1000000, freq%1000000);
+
+ tb_ticks_per_jiffy = freq / HZ;
+ tb_to_us = mulhwu_scale_factor(freq, 1000000);
+
+ return;
+}
+
+/*
+ * Set BAT 3 to map 0xfb000000 to 0xfc000000 of physical memory space.
+ */
+static __inline__ void
+ev64260_set_bat(void)
+{
+ mb();
+ mtspr(SPRN_DBAT1U, 0xfb0001fe);
+ mtspr(SPRN_DBAT1L, 0xfb00002a);
+ mb();
+
+ return;
+}
+
+#if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB)
+static void __init
+ev64260_map_io(void)
+{
+ io_block_mapping(0xfb000000, 0xfb000000, 0x01000000, _PAGE_IO);
+}
+#endif
+
+void __init
+platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
+ unsigned long r6, unsigned long r7)
+{
+#ifdef CONFIG_BLK_DEV_INITRD
+ extern int initrd_below_start_ok;
+
+ initrd_start=initrd_end=0;
+ initrd_below_start_ok=0;
+#endif /* CONFIG_BLK_DEV_INITRD */
+
+ parse_bootinfo(find_bootinfo());
+
+ isa_mem_base = 0;
+ isa_io_base = EV64260_PCI0_IO_CPU_BASE;
+ pci_dram_offset = EV64260_PCI0_MEM_CPU_BASE;
+
+ loops_per_jiffy = ev64260_get_cpu_speed() / HZ;
+
+ ppc_md.setup_arch = ev64260_setup_arch;
+ ppc_md.show_cpuinfo = ev64260_show_cpuinfo;
+ ppc_md.init_IRQ = gt64260_init_irq;
+ ppc_md.get_irq = gt64260_get_irq;
+
+ ppc_md.restart = ev64260_restart;
+ ppc_md.power_off = ev64260_power_off;
+ ppc_md.halt = ev64260_halt;
+
+ ppc_md.find_end_of_memory = ev64260_find_end_of_memory;
+
+ ppc_md.init = NULL;
+
+ ppc_md.time_init = todc_time_init;
+ ppc_md.set_rtc_time = todc_set_rtc_time;
+ ppc_md.get_rtc_time = todc_get_rtc_time;
+ ppc_md.nvram_read_val = todc_direct_read_val;
+ ppc_md.nvram_write_val = todc_direct_write_val;
+ ppc_md.calibrate_decr = ev64260_calibrate_decr;
+
+ bh.p_base = CONFIG_MV64X60_NEW_BASE;
+
+ ev64260_set_bat();
+
+#ifdef CONFIG_SERIAL_8250
+#if defined(CONFIG_SERIAL_TEXT_DEBUG)
+ ppc_md.setup_io_mappings = ev64260_map_io;
+ ppc_md.progress = gen550_progress;
+#endif
+#if defined(CONFIG_KGDB)
+ ppc_md.setup_io_mappings = ev64260_map_io;
+ ppc_md.early_serial_map = ev64260_early_serial_map;
+#endif
+#elif defined(CONFIG_SERIAL_MPSC_CONSOLE)
+#ifdef CONFIG_SERIAL_TEXT_DEBUG
+ ppc_md.setup_io_mappings = ev64260_map_io;
+ ppc_md.progress = mv64x60_mpsc_progress;
+ mv64x60_progress_init(CONFIG_MV64X60_NEW_BASE);
+#endif /* CONFIG_SERIAL_TEXT_DEBUG */
+#ifdef CONFIG_KGDB
+ ppc_md.setup_io_mappings = ev64260_map_io;
+ ppc_md.early_serial_map = ev64260_early_serial_map;
+#endif /* CONFIG_KGDB */
+
+#endif
+
+#if defined(CONFIG_SERIAL_MPSC)
+ platform_notify = ev64260_platform_notify;
+#endif
+
+ return;
+}
diff --git a/arch/ppc/platforms/ev64260.h b/arch/ppc/platforms/ev64260.h
new file mode 100644
index 0000000..bedffce
--- /dev/null
+++ b/arch/ppc/platforms/ev64260.h
@@ -0,0 +1,128 @@
+/*
+ * arch/ppc/platforms/ev64260.h
+ *
+ * Definitions for Marvell/Galileo EV-64260-BP Evaluation Board.
+ *
+ * Author: Mark A. Greer <mgreer@mvista.com>
+ *
+ * 2001-2002 (c) MontaVista, Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+
+/*
+ * The MV64x60 has 2 PCI buses each with 1 window from the CPU bus to
+ * PCI I/O space and 4 windows from the CPU bus to PCI MEM space.
+ * We'll only use one PCI MEM window on each PCI bus.
+ *
+ * This is the CPU physical memory map (windows must be at least 1MB and start
+ * on a boundary that is a multiple of the window size):
+ *
+ * 0xfc000000-0xffffffff - External FLASH on device module
+ * 0xfbf00000-0xfbffffff - Embedded (on board) FLASH
+ * 0xfbe00000-0xfbefffff - GT64260 Registers (preferably)
+ * but really a config option
+ * 0xfbd00000-0xfbdfffff - External SRAM on device module
+ * 0xfbc00000-0xfbcfffff - TODC chip on device module
+ * 0xfbb00000-0xfbbfffff - External UART on device module
+ * 0xa2000000-0xfbafffff - <hole>
+ * 0xa1000000-0xa1ffffff - PCI 1 I/O (defined in gt64260.h)
+ * 0xa0000000-0xa0ffffff - PCI 0 I/O (defined in gt64260.h)
+ * 0x90000000-0x9fffffff - PCI 1 MEM (defined in gt64260.h)
+ * 0x80000000-0x8fffffff - PCI 0 MEM (defined in gt64260.h)
+ */
+
+#ifndef __PPC_PLATFORMS_EV64260_H
+#define __PPC_PLATFORMS_EV64260_H
+
+/* PCI mappings */
+#define EV64260_PCI0_IO_CPU_BASE 0xa0000000
+#define EV64260_PCI0_IO_PCI_BASE 0x00000000
+#define EV64260_PCI0_IO_SIZE 0x01000000
+
+#define EV64260_PCI0_MEM_CPU_BASE 0x80000000
+#define EV64260_PCI0_MEM_PCI_BASE 0x80000000
+#define EV64260_PCI0_MEM_SIZE 0x10000000
+
+#define EV64260_PCI1_IO_CPU_BASE (EV64260_PCI0_IO_CPU_BASE + \
+ EV64260_PCI0_IO_SIZE)
+#define EV64260_PCI1_IO_PCI_BASE (EV64260_PCI0_IO_PCI_BASE + \
+ EV64260_PCI0_IO_SIZE)
+#define EV64260_PCI1_IO_SIZE 0x01000000
+
+#define EV64260_PCI1_MEM_CPU_BASE (EV64260_PCI0_MEM_CPU_BASE + \
+ EV64260_PCI0_MEM_SIZE)
+#define EV64260_PCI1_MEM_PCI_BASE (EV64260_PCI0_MEM_PCI_BASE + \
+ EV64260_PCI0_MEM_SIZE)
+#define EV64260_PCI1_MEM_SIZE 0x10000000
+
+/* CPU Physical Memory Map setup (other than PCI) */
+#define EV64260_EXT_FLASH_BASE 0xfc000000
+#define EV64260_EMB_FLASH_BASE 0xfbf00000
+#define EV64260_EXT_SRAM_BASE 0xfbd00000
+#define EV64260_TODC_BASE 0xfbc00000
+#define EV64260_UART_BASE 0xfbb00000
+
+#define EV64260_EXT_FLASH_SIZE_ACTUAL 0x04000000 /* <= 64MB Extern FLASH */
+#define EV64260_EMB_FLASH_SIZE_ACTUAL 0x00080000 /* 512KB of Embed FLASH */
+#define EV64260_EXT_SRAM_SIZE_ACTUAL 0x00100000 /* 1MB SDRAM */
+#define EV64260_TODC_SIZE_ACTUAL 0x00000020 /* 32 bytes for TODC */
+#define EV64260_UART_SIZE_ACTUAL 0x00000040 /* 64 bytes for DUART */
+
+#define EV64260_EXT_FLASH_SIZE max(GT64260_WINDOW_SIZE_MIN, \
+ EV64260_EXT_FLASH_SIZE_ACTUAL)
+#define EV64260_EMB_FLASH_SIZE max(GT64260_WINDOW_SIZE_MIN, \
+ EV64260_EMB_FLASH_SIZE_ACTUAL)
+#define EV64260_EXT_SRAM_SIZE max(GT64260_WINDOW_SIZE_MIN, \
+ EV64260_EXT_SRAM_SIZE_ACTUAL)
+#define EV64260_TODC_SIZE max(GT64260_WINDOW_SIZE_MIN, \
+ EV64260_TODC_SIZE_ACTUAL)
+/* Assembler in bootwrapper blows up if 'max' is used */
+#define EV64260_UART_SIZE GT64260_WINDOW_SIZE_MIN
+#define EV64260_UART_END ((EV64260_UART_BASE + \
+ EV64260_UART_SIZE - 1) & 0xfff00000)
+
+/* Board-specific IRQ info */
+#define EV64260_UART_0_IRQ 85
+#define EV64260_UART_1_IRQ 86
+#define EV64260_PCI_0_IRQ 91
+#define EV64260_PCI_1_IRQ 93
+
+/* Serial port setup */
+#define EV64260_DEFAULT_BAUD 115200
+
+#if defined(CONFIG_SERIAL_MPSC_CONSOLE)
+#define SERIAL_PORT_DFNS
+
+#define EV64260_MPSC_CLK_SRC 8 /* TCLK */
+#define EV64260_MPSC_CLK_FREQ 100000000 /* 100MHz clk */
+#else
+#define EV64260_SERIAL_0 (EV64260_UART_BASE + 0x20)
+#define EV64260_SERIAL_1 EV64260_UART_BASE
+
+#define BASE_BAUD (EV64260_DEFAULT_BAUD * 2)
+
+#ifdef CONFIG_SERIAL_MANY_PORTS
+#define RS_TABLE_SIZE 64
+#else
+#define RS_TABLE_SIZE 2
+#endif
+
+#ifdef CONFIG_SERIAL_DETECT_IRQ
+#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF|ASYNC_SKIP_TEST|ASYNC_AUTO_IRQ)
+#else
+#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF|ASYNC_SKIP_TEST)
+#endif
+
+/* Required for bootloader's ns16550.c code */
+#define STD_SERIAL_PORT_DFNS \
+ { 0, BASE_BAUD, EV64260_SERIAL_0, EV64260_UART_0_IRQ, STD_COM_FLAGS, \
+ iomem_base: (u8 *)EV64260_SERIAL_0, /* ttyS0 */ \
+ iomem_reg_shift: 2, \
+ io_type: SERIAL_IO_MEM },
+
+#define SERIAL_PORT_DFNS \
+ STD_SERIAL_PORT_DFNS
+#endif
+#endif /* __PPC_PLATFORMS_EV64260_H */
diff --git a/arch/ppc/platforms/fads.h b/arch/ppc/platforms/fads.h
new file mode 100644
index 0000000..632b817
--- /dev/null
+++ b/arch/ppc/platforms/fads.h
@@ -0,0 +1,57 @@
+/*
+ * A collection of structures, addresses, and values associated with
+ * the Motorola 860T FADS board. Copied from the MBX stuff.
+ *
+ * Copyright (c) 1998 Dan Malek (dmalek@jlc.net)
+ */
+#ifdef __KERNEL__
+#ifndef __ASM_FADS_H__
+#define __ASM_FADS_H__
+
+#include <linux/config.h>
+
+#include <asm/ppcboot.h>
+
+/* Memory map is configured by the PROM startup.
+ * I tried to follow the FADS manual, although the startup PROM
+ * dictates this and we simply have to move some of the physical
+ * addresses for Linux.
+ */
+#define BCSR_ADDR ((uint)0xff010000)
+#define BCSR_SIZE ((uint)(64 * 1024))
+#define BCSR0 ((uint)0xff010000)
+#define BCSR1 ((uint)0xff010004)
+#define BCSR2 ((uint)0xff010008)
+#define BCSR3 ((uint)0xff01000c)
+#define BCSR4 ((uint)0xff010010)
+
+#define IMAP_ADDR ((uint)0xff000000)
+#define IMAP_SIZE ((uint)(64 * 1024))
+
+#define PCMCIA_MEM_ADDR ((uint)0xff020000)
+#define PCMCIA_MEM_SIZE ((uint)(64 * 1024))
+
+/* Bits of interest in the BCSRs.
+ */
+#define BCSR1_ETHEN ((uint)0x20000000)
+#define BCSR1_RS232EN_1 ((uint)0x01000000)
+#define BCSR1_RS232EN_2 ((uint)0x00040000)
+#define BCSR4_ETHLOOP ((uint)0x80000000) /* EEST Loopback */
+#define BCSR4_EEFDX ((uint)0x40000000) /* EEST FDX enable */
+#define BCSR4_FETH_EN ((uint)0x08000000) /* PHY enable */
+#define BCSR4_FETHCFG0 ((uint)0x04000000) /* PHY autoneg mode */
+#define BCSR4_FETHCFG1 ((uint)0x00400000) /* PHY autoneg mode */
+#define BCSR4_FETHFDE ((uint)0x02000000) /* PHY FDX advertise */
+#define BCSR4_FETHRST ((uint)0x00200000) /* PHY Reset */
+
+/* Interrupt level assignments.
+ */
+#define FEC_INTERRUPT SIU_LEVEL1 /* FEC interrupt */
+#define PHY_INTERRUPT SIU_IRQ2 /* PHY link change interrupt */
+
+/* We don't use the 8259.
+ */
+#define NR_8259_INTS 0
+
+#endif /* __ASM_FADS_H__ */
+#endif /* __KERNEL__ */
diff --git a/arch/ppc/platforms/gemini.h b/arch/ppc/platforms/gemini.h
new file mode 100644
index 0000000..06de592
--- /dev/null
+++ b/arch/ppc/platforms/gemini.h
@@ -0,0 +1,168 @@
+/*
+ * arch/ppc/platforms/gemini.h
+ *
+ *
+ * Onboard registers and descriptions for Synergy Microsystems'
+ * "Gemini" boards.
+ *
+ */
+#ifdef __KERNEL__
+#ifndef __PPC_GEMINI_H
+#define __PPC_GEMINI_H
+
+/* Registers */
+
+#define GEMINI_SERIAL_B (0xffeffb00)
+#define GEMINI_SERIAL_A (0xffeffb08)
+#define GEMINI_USWITCH (0xffeffd00)
+#define GEMINI_BREV (0xffeffe00)
+#define GEMINI_BECO (0xffeffe08)
+#define GEMINI_FEAT (0xffeffe10)
+#define GEMINI_BSTAT (0xffeffe18)
+#define GEMINI_CPUSTAT (0xffeffe20)
+#define GEMINI_L2CFG (0xffeffe30)
+#define GEMINI_MEMCFG (0xffeffe38)
+#define GEMINI_FLROM (0xffeffe40)
+#define GEMINI_P0PCI (0xffeffe48)
+#define GEMINI_FLWIN (0xffeffe50)
+#define GEMINI_P0INTMASK (0xffeffe60)
+#define GEMINI_P0INTAP (0xffeffe68)
+#define GEMINI_PCIERR (0xffeffe70)
+#define GEMINI_LEDBASE (0xffeffe80)
+#define GEMINI_RTC (0xffe9fff8)
+#define GEMINI_LEDS 8
+#define GEMINI_SWITCHES 8
+
+
+/* Flash ROM bit definitions */
+#define GEMINI_FLS_WEN (1<<0)
+#define GEMINI_FLS_JMP (1<<6)
+#define GEMINI_FLS_BOOT (1<<7)
+
+/* Memory bit definitions */
+#define GEMINI_MEM_TYPE_MASK 0xc0
+#define GEMINI_MEM_SIZE_MASK 0x38
+#define GEMINI_MEM_BANK_MASK 0x07
+
+/* L2 cache bit definitions */
+#define GEMINI_L2_SIZE_MASK 0xc0
+#define GEMINI_L2_RATIO_MASK 0x03
+
+/* Timebase register bit definitons */
+#define GEMINI_TIMEB0_EN (1<<0)
+#define GEMINI_TIMEB1_EN (1<<1)
+#define GEMINI_TIMEB2_EN (1<<2)
+#define GEMINI_TIMEB3_EN (1<<3)
+
+/* CPU status bit definitions */
+#define GEMINI_CPU_ID_MASK 0x03
+#define GEMINI_CPU_COUNT_MASK 0x0c
+#define GEMINI_CPU0_HALTED (1<<4)
+#define GEMINI_CPU1_HALTED (1<<5)
+#define GEMINI_CPU2_HALTED (1<<6)
+#define GEMINI_CPU3_HALTED (1<<7)
+
+/* Board status bit definitions */
+#define GEMINI_BRD_FAIL (1<<0) /* FAIL led is lit */
+#define GEMINI_BRD_BUS_MASK 0x0c /* PowerPC bus speed */
+
+/* Board family/feature bit descriptions */
+#define GEMINI_FEAT_HAS_FLASH (1<<0)
+#define GEMINI_FEAT_HAS_ETH (1<<1)
+#define GEMINI_FEAT_HAS_SCSI (1<<2)
+#define GEMINI_FEAT_HAS_P0 (1<<3)
+#define GEMINI_FEAT_FAM_MASK 0xf0
+
+/* Mod/ECO bit definitions */
+#define GEMINI_ECO_LEVEL_MASK 0x0f
+#define GEMINI_MOD_MASK 0xf0
+
+/* Type/revision bit definitions */
+#define GEMINI_REV_MASK 0x0f
+#define GEMINI_TYPE_MASK 0xf0
+
+/* User switch definitions */
+#define GEMINI_SWITCH_VERBOSE 1 /* adds "debug" to boot cmd line */
+#define GEMINI_SWITCH_SINGLE_USER 7 /* boots into "single-user" mode */
+
+#define SGS_RTC_CONTROL 0
+#define SGS_RTC_SECONDS 1
+#define SGS_RTC_MINUTES 2
+#define SGS_RTC_HOURS 3
+#define SGS_RTC_DAY 4
+#define SGS_RTC_DAY_OF_MONTH 5
+#define SGS_RTC_MONTH 6
+#define SGS_RTC_YEAR 7
+
+#define SGS_RTC_SET 0x80
+#define SGS_RTC_IS_STOPPED 0x80
+
+#define GRACKLE_CONFIG_ADDR_ADDR (0xfec00000)
+#define GRACKLE_CONFIG_DATA_ADDR (0xfee00000)
+
+#define GEMINI_BOOT_INIT (0xfff00100)
+
+#ifndef __ASSEMBLY__
+
+static inline void grackle_write( unsigned long addr, unsigned long data )
+{
+ __asm__ __volatile__(
+ " stwbrx %1, 0, %0\n \
+ sync\n \
+ stwbrx %3, 0, %2\n \
+ sync "
+ : /* no output */
+ : "r" (GRACKLE_CONFIG_ADDR_ADDR), "r" (addr),
+ "r" (GRACKLE_CONFIG_DATA_ADDR), "r" (data));
+}
+
+static inline unsigned long grackle_read( unsigned long addr )
+{
+ unsigned long val;
+
+ __asm__ __volatile__(
+ " stwbrx %1, 0, %2\n \
+ sync\n \
+ lwbrx %0, 0, %3\n \
+ sync "
+ : "=r" (val)
+ : "r" (addr), "r" (GRACKLE_CONFIG_ADDR_ADDR),
+ "r" (GRACKLE_CONFIG_DATA_ADDR));
+
+ return val;
+}
+
+static inline void gemini_led_on( int led )
+{
+ if (led >= 0 && led < GEMINI_LEDS)
+ *(unsigned char *)(GEMINI_LEDBASE + (led<<3)) = 1;
+}
+
+static inline void gemini_led_off(int led)
+{
+ if (led >= 0 && led < GEMINI_LEDS)
+ *(unsigned char *)(GEMINI_LEDBASE + (led<<3)) = 0;
+}
+
+static inline int gemini_led_val(int led)
+{
+ int val = 0;
+ if (led >= 0 && led < GEMINI_LEDS)
+ val = *(unsigned char *)(GEMINI_LEDBASE + (led<<3));
+ return (val & 0x1);
+}
+
+/* returns processor id from the board */
+static inline int gemini_processor(void)
+{
+ unsigned char cpu = *(unsigned char *)(GEMINI_CPUSTAT);
+ return (int) ((cpu == 0) ? 4 : (cpu & GEMINI_CPU_ID_MASK));
+}
+
+
+extern void _gemini_reboot(void);
+extern void gemini_prom_init(void);
+extern void gemini_init_l2(void);
+#endif /* __ASSEMBLY__ */
+#endif
+#endif /* __KERNEL__ */
diff --git a/arch/ppc/platforms/gemini_pci.c b/arch/ppc/platforms/gemini_pci.c
new file mode 100644
index 0000000..9565609
--- /dev/null
+++ b/arch/ppc/platforms/gemini_pci.c
@@ -0,0 +1,41 @@
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/slab.h>
+
+#include <asm/machdep.h>
+#include <platforms/gemini.h>
+#include <asm/byteorder.h>
+#include <asm/io.h>
+#include <asm/uaccess.h>
+#include <asm/pci-bridge.h>
+
+void __init gemini_pcibios_fixup(void)
+{
+ int i;
+ struct pci_dev *dev = NULL;
+
+ for_each_pci_dev(dev) {
+ for(i = 0; i < 6; i++) {
+ if (dev->resource[i].flags & IORESOURCE_IO) {
+ dev->resource[i].start |= (0xfe << 24);
+ dev->resource[i].end |= (0xfe << 24);
+ }
+ }
+ }
+}
+
+
+/* The "bootloader" for Synergy boards does none of this for us, so we need to
+ lay it all out ourselves... --Dan */
+void __init gemini_find_bridges(void)
+{
+ struct pci_controller* hose;
+
+ ppc_md.pcibios_fixup = gemini_pcibios_fixup;
+
+ hose = pcibios_alloc_controller();
+ if (!hose)
+ return;
+ setup_indirect_pci(hose, 0xfec00000, 0xfee00000);
+}
diff --git a/arch/ppc/platforms/gemini_prom.S b/arch/ppc/platforms/gemini_prom.S
new file mode 100644
index 0000000..8c5065d
--- /dev/null
+++ b/arch/ppc/platforms/gemini_prom.S
@@ -0,0 +1,93 @@
+/*
+ * arch/ppc/platforms/gemini_prom.S
+ *
+ * Not really prom support code (yet), but sort of anti-prom code. The current
+ * bootloader does a number of things it shouldn't and doesn't do things that it
+ * should. The stuff in here is mainly a hodge-podge collection of setup code
+ * to get the board up and running.
+ * ---Dan
+ */
+
+#include <linux/config.h>
+#include <asm/reg.h>
+#include <asm/page.h>
+#include <platforms/gemini.h>
+#include <asm/ppc_asm.h>
+
+/*
+ * On 750's the MMU is on when Linux is booted, so we need to clear out the
+ * bootloader's BAT settings, make sure we're in supervisor state (gotcha!),
+ * and turn off the MMU.
+ *
+ */
+
+_GLOBAL(gemini_prom_init)
+#ifdef CONFIG_SMP
+ /* Since the MMU's on, get stuff in rom space that we'll need */
+ lis r4,GEMINI_CPUSTAT@h
+ ori r4,r4,GEMINI_CPUSTAT@l
+ lbz r5,0(r4)
+ andi. r5,r5,3
+ mr r24,r5 /* cpu # used later on */
+#endif
+ mfmsr r4
+ li r3,MSR_PR /* ensure supervisor! */
+ ori r3,r3,MSR_IR|MSR_DR
+ andc r4,r4,r3
+ mtmsr r4
+ isync
+#if 0
+ /* zero out the bats now that the MMU is off */
+prom_no_mmu:
+ li r3,0
+ mtspr SPRN_IBAT0U,r3
+ mtspr SPRN_IBAT0L,r3
+ mtspr SPRN_IBAT1U,r3
+ mtspr SPRN_IBAT1L,r3
+ mtspr SPRN_IBAT2U,r3
+ mtspr SPRN_IBAT2L,r3
+ mtspr SPRN_IBAT3U,r3
+ mtspr SPRN_IBAT3L,r3
+
+ mtspr SPRN_DBAT0U,r3
+ mtspr SPRN_DBAT0L,r3
+ mtspr SPRN_DBAT1U,r3
+ mtspr SPRN_DBAT1L,r3
+ mtspr SPRN_DBAT2U,r3
+ mtspr SPRN_DBAT2L,r3
+ mtspr SPRN_DBAT3U,r3
+ mtspr SPRN_DBAT3L,r3
+#endif
+
+ /* the bootloader (as far as I'm currently aware) doesn't mess with page
+ tables, but since we're already here, might as well zap these, too */
+ li r4,0
+ mtspr SPRN_SDR1,r4
+
+ li r4,16
+ mtctr r4
+ li r3,0
+ li r4,0
+3: mtsrin r3,r4
+ addi r3,r3,1
+ bdnz 3b
+
+#ifdef CONFIG_SMP
+ /* The 750 book (and Mot/IBM support) says that this will "assist" snooping
+ when in SMP. Not sure yet whether this should stay or leave... */
+ mfspr r4,SPRN_HID0
+ ori r4,r4,HID0_ABE
+ mtspr SPRN_HID0,r4
+ sync
+#endif /* CONFIG_SMP */
+ blr
+
+/* apparently, SMon doesn't pay attention to HID0[SRST]. Disable the MMU and
+ branch to 0xfff00100 */
+_GLOBAL(_gemini_reboot)
+ lis r5,GEMINI_BOOT_INIT@h
+ ori r5,r5,GEMINI_BOOT_INIT@l
+ li r6,MSR_IP
+ mtspr SPRN_SRR0,r5
+ mtspr SPRN_SRR1,r6
+ rfi
diff --git a/arch/ppc/platforms/gemini_serial.h b/arch/ppc/platforms/gemini_serial.h
new file mode 100644
index 0000000..69855ae
--- /dev/null
+++ b/arch/ppc/platforms/gemini_serial.h
@@ -0,0 +1,41 @@
+#ifdef __KERNEL__
+#ifndef __ASMPPC_GEMINI_SERIAL_H
+#define __ASMPPC_GEMINI_SERIAL_H
+
+#include <linux/config.h>
+#include <platforms/gemini.h>
+
+#ifdef CONFIG_SERIAL_MANY_PORTS
+#define RS_TABLE_SIZE 64
+#else
+#define RS_TABLE_SIZE 4
+#endif
+
+/* Rate for the 24.576 Mhz clock for the onboard serial chip */
+#define BASE_BAUD (24576000 / 16)
+
+#ifdef CONFIG_SERIAL_DETECT_IRQ
+#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF|ASYNC_SKIP_TEST|ASYNC_AUTO_IRQ)
+#define STD_COM4_FLAGS (ASYNC_BOOT_AUTOCONF|ASYNC_AUTO_IRQ)
+#else
+#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF|ASYNC_SKIP_TEST)
+#define STD_COM4_FLAGS (ASYNC_BOOT_AUTOCONF)
+#endif
+
+#define STD_SERIAL_PORT_DEFNS \
+ { 0, BASE_BAUD, GEMINI_SERIAL_A, 15, STD_COM_FLAGS }, /* ttyS0 */ \
+ { 0, BASE_BAUD, GEMINI_SERIAL_B, 14, STD_COM_FLAGS }, /* ttyS1 */ \
+
+#ifdef CONFIG_GEMINI_PU32
+#define PU32_SERIAL_PORT_DEFNS \
+ { 0, BASE_BAUD, NULL, 0, STD_COM_FLAGS },
+#else
+#define PU32_SERIAL_PORT_DEFNS
+#endif
+
+#define SERIAL_PORT_DFNS \
+ STD_SERIAL_PORT_DEFNS \
+ PU32_SERIAL_PORT_DEFNS
+
+#endif
+#endif /* __KERNEL__ */
diff --git a/arch/ppc/platforms/gemini_setup.c b/arch/ppc/platforms/gemini_setup.c
new file mode 100644
index 0000000..1a42cb9
--- /dev/null
+++ b/arch/ppc/platforms/gemini_setup.c
@@ -0,0 +1,584 @@
+/*
+ * arch/ppc/platforms/gemini_setup.c
+ *
+ * Copyright (C) 1995 Linus Torvalds
+ * Adapted from 'alpha' version by Gary Thomas
+ * Modified by Cort Dougan (cort@cs.nmt.edu)
+ * Synergy Microsystems board support by Dan Cox (dan@synergymicro.com)
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/stddef.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/reboot.h>
+#include <linux/pci.h>
+#include <linux/time.h>
+#include <linux/kdev_t.h>
+#include <linux/types.h>
+#include <linux/major.h>
+#include <linux/initrd.h>
+#include <linux/console.h>
+#include <linux/irq.h>
+#include <linux/seq_file.h>
+#include <linux/root_dev.h>
+#include <linux/bcd.h>
+
+#include <asm/system.h>
+#include <asm/pgtable.h>
+#include <asm/page.h>
+#include <asm/dma.h>
+#include <asm/io.h>
+#include <asm/m48t35.h>
+#include <platforms/gemini.h>
+#include <asm/time.h>
+#include <asm/open_pic.h>
+#include <asm/bootinfo.h>
+
+void gemini_find_bridges(void);
+static int gemini_get_clock_speed(void);
+extern void gemini_pcibios_fixup(void);
+
+static char *gemini_board_families[] = {
+ "VGM", "VSS", "KGM", "VGR", "VCM", "VCS", "KCM", "VCR"
+};
+static int gemini_board_count = sizeof(gemini_board_families) /
+ sizeof(gemini_board_families[0]);
+
+static unsigned int cpu_7xx[16] = {
+ 0, 15, 14, 0, 0, 13, 5, 9, 6, 11, 8, 10, 16, 12, 7, 0
+};
+static unsigned int cpu_6xx[16] = {
+ 0, 0, 14, 0, 0, 13, 5, 9, 6, 11, 8, 10, 0, 12, 7, 0
+};
+
+/*
+ * prom_init is the Gemini version of prom.c:prom_init. We only need
+ * the BSS clearing code, so I copied that out of prom.c. This is a
+ * lot simpler than hacking prom.c so it will build with Gemini. -VAL
+ */
+
+#define PTRRELOC(x) ((typeof(x))((unsigned long)(x) + offset))
+
+unsigned long
+prom_init(void)
+{
+ unsigned long offset = reloc_offset();
+ unsigned long phys;
+ extern char __bss_start, _end;
+
+ /* First zero the BSS -- use memset, some arches don't have
+ * caches on yet */
+ memset_io(PTRRELOC(&__bss_start),0 , &_end - &__bss_start);
+
+ /* Default */
+ phys = offset + KERNELBASE;
+
+ gemini_prom_init();
+
+ return phys;
+}
+
+int
+gemini_show_cpuinfo(struct seq_file *m)
+{
+ unsigned char reg, rev;
+ char *family;
+ unsigned int type;
+
+ reg = readb(GEMINI_FEAT);
+ family = gemini_board_families[((reg>>4) & 0xf)];
+ if (((reg>>4) & 0xf) > gemini_board_count)
+ printk(KERN_ERR "cpuinfo(): unable to determine board family\n");
+
+ reg = readb(GEMINI_BREV);
+ type = (reg>>4) & 0xf;
+ rev = reg & 0xf;
+
+ reg = readb(GEMINI_BECO);
+
+ seq_printf(m, "machine\t\t: Gemini %s%d, rev %c, eco %d\n",
+ family, type, (rev + 'A'), (reg & 0xf));
+
+ seq_printf(m, "board\t\t: Gemini %s", family);
+ if (type > 9)
+ seq_printf(m, "%c", (type - 10) + 'A');
+ else
+ seq_printf(m, "%d", type);
+
+ seq_printf(m, ", rev %c, eco %d\n", (rev + 'A'), (reg & 0xf));
+
+ seq_printf(m, "clock\t\t: %dMhz\n", gemini_get_clock_speed());
+
+ return 0;
+}
+
+static u_char gemini_openpic_initsenses[] = {
+ 1,
+ 1,
+ 1,
+ 1,
+ 0,
+ 0,
+ 1, /* remainder are level-triggered */
+};
+
+#define GEMINI_MPIC_ADDR (0xfcfc0000)
+#define GEMINI_MPIC_PCI_CFG (0x80005800)
+
+void __init gemini_openpic_init(void)
+{
+
+ OpenPIC_Addr = (volatile struct OpenPIC *)
+ grackle_read(GEMINI_MPIC_PCI_CFG + 0x10);
+ OpenPIC_InitSenses = gemini_openpic_initsenses;
+ OpenPIC_NumInitSenses = sizeof( gemini_openpic_initsenses );
+
+ ioremap( GEMINI_MPIC_ADDR, OPENPIC_SIZE);
+}
+
+
+extern unsigned long loops_per_jiffy;
+extern int root_mountflags;
+extern char cmd_line[];
+
+void
+gemini_heartbeat(void)
+{
+ static unsigned long led = GEMINI_LEDBASE+(4*8);
+ static char direction = 8;
+
+
+ /* We only want to do this on 1 CPU */
+ if (smp_processor_id())
+ return;
+ *(char *)led = 0;
+ if ( (led + direction) > (GEMINI_LEDBASE+(7*8)) ||
+ (led + direction) < (GEMINI_LEDBASE+(4*8)) )
+ direction *= -1;
+ led += direction;
+ *(char *)led = 0xff;
+ ppc_md.heartbeat_count = ppc_md.heartbeat_reset;
+}
+
+void __init gemini_setup_arch(void)
+{
+ extern char cmd_line[];
+
+
+ loops_per_jiffy = 50000000/HZ;
+
+#ifdef CONFIG_BLK_DEV_INITRD
+ /* bootable off CDROM */
+ if (initrd_start)
+ ROOT_DEV = Root_SR0;
+ else
+#endif
+ ROOT_DEV = Root_SDA1;
+
+ /* nothing but serial consoles... */
+ sprintf(cmd_line, "%s console=ttyS0", cmd_line);
+
+ printk("Boot arguments: %s\n", cmd_line);
+
+ ppc_md.heartbeat = gemini_heartbeat;
+ ppc_md.heartbeat_reset = HZ/8;
+ ppc_md.heartbeat_count = 1;
+
+ /* Lookup PCI hosts */
+ gemini_find_bridges();
+ /* take special pains to map the MPIC, since it isn't mapped yet */
+ gemini_openpic_init();
+ /* start the L2 */
+ gemini_init_l2();
+}
+
+
+int
+gemini_get_clock_speed(void)
+{
+ unsigned long hid1, pvr;
+ int clock;
+
+ pvr = mfspr(SPRN_PVR);
+ hid1 = (mfspr(SPRN_HID1) >> 28) & 0xf;
+ if (PVR_VER(pvr) == 8 ||
+ PVR_VER(pvr) == 12)
+ hid1 = cpu_7xx[hid1];
+ else
+ hid1 = cpu_6xx[hid1];
+
+ switch((readb(GEMINI_BSTAT) & 0xc) >> 2) {
+
+ case 0:
+ default:
+ clock = (hid1*100)/3;
+ break;
+
+ case 1:
+ clock = (hid1*125)/3;
+ break;
+
+ case 2:
+ clock = (hid1*50);
+ break;
+ }
+
+ return clock;
+}
+
+void __init gemini_init_l2(void)
+{
+ unsigned char reg, brev, fam, creg;
+ unsigned long cache;
+ unsigned long pvr;
+
+ reg = readb(GEMINI_L2CFG);
+ brev = readb(GEMINI_BREV);
+ fam = readb(GEMINI_FEAT);
+ pvr = mfspr(SPRN_PVR);
+
+ switch(PVR_VER(pvr)) {
+
+ case 8:
+ if (reg & 0xc0)
+ cache = (((reg >> 6) & 0x3) << 28);
+ else
+ cache = 0x3 << 28;
+
+#ifdef CONFIG_SMP
+ /* Pre-3.0 processor revs had snooping errata. Leave
+ their L2's disabled with SMP. -- Dan */
+ if (PVR_CFG(pvr) < 3) {
+ printk("Pre-3.0 750; L2 left disabled!\n");
+ return;
+ }
+#endif /* CONFIG_SMP */
+
+ /* Special case: VGM5-B's came before L2 ratios were set on
+ the board. Processor speed shouldn't be too high, so
+ set L2 ratio to 1:1.5. */
+ if ((brev == 0x51) && ((fam & 0xa0) >> 4) == 0)
+ reg |= 1;
+
+ /* determine best cache ratio based upon what the board
+ tells us (which sometimes _may_ not be true) and
+ the processor speed. */
+ else {
+ if (gemini_get_clock_speed() > 250)
+ reg = 2;
+ }
+ break;
+ case 12:
+ {
+ static unsigned long l2_size_val = 0;
+
+ if (!l2_size_val)
+ l2_size_val = _get_L2CR();
+ cache = l2_size_val;
+ break;
+ }
+ case 4:
+ case 9:
+ creg = readb(GEMINI_CPUSTAT);
+ if (((creg & 0xc) >> 2) != 1)
+ printk("Dual-604 boards don't support the use of L2\n");
+ else
+ writeb(1, GEMINI_L2CFG);
+ return;
+ default:
+ printk("Unknown processor; L2 left disabled\n");
+ return;
+ }
+
+ cache |= ((1<<reg) << 25);
+ cache |= (L2CR_L2RAM_MASK|L2CR_L2CTL|L2CR_L2DO);
+ _set_L2CR(0);
+ _set_L2CR(cache | L2CR_L2E);
+
+}
+
+void
+gemini_restart(char *cmd)
+{
+ local_irq_disable();
+ /* make a clean restart, not via the MPIC */
+ _gemini_reboot();
+ for(;;);
+}
+
+void
+gemini_power_off(void)
+{
+ for(;;);
+}
+
+void
+gemini_halt(void)
+{
+ gemini_restart(NULL);
+}
+
+void __init gemini_init_IRQ(void)
+{
+ /* gemini has no 8259 */
+ openpic_init(1, 0, 0, -1);
+}
+
+#define gemini_rtc_read(x) (readb(GEMINI_RTC+(x)))
+#define gemini_rtc_write(val,x) (writeb((val),(GEMINI_RTC+(x))))
+
+/* ensure that the RTC is up and running */
+long __init gemini_time_init(void)
+{
+ unsigned char reg;
+
+ reg = gemini_rtc_read(M48T35_RTC_CONTROL);
+
+ if ( reg & M48T35_RTC_STOPPED ) {
+ printk(KERN_INFO "M48T35 real-time-clock was stopped. Now starting...\n");
+ gemini_rtc_write((reg & ~(M48T35_RTC_STOPPED)), M48T35_RTC_CONTROL);
+ gemini_rtc_write((reg | M48T35_RTC_SET), M48T35_RTC_CONTROL);
+ }
+ return 0;
+}
+
+#undef DEBUG_RTC
+
+unsigned long
+gemini_get_rtc_time(void)
+{
+ unsigned int year, mon, day, hour, min, sec;
+ unsigned char reg;
+
+ reg = gemini_rtc_read(M48T35_RTC_CONTROL);
+ gemini_rtc_write((reg|M48T35_RTC_READ), M48T35_RTC_CONTROL);
+#ifdef DEBUG_RTC
+ printk("get rtc: reg = %x\n", reg);
+#endif
+
+ do {
+ sec = gemini_rtc_read(M48T35_RTC_SECONDS);
+ min = gemini_rtc_read(M48T35_RTC_MINUTES);
+ hour = gemini_rtc_read(M48T35_RTC_HOURS);
+ day = gemini_rtc_read(M48T35_RTC_DOM);
+ mon = gemini_rtc_read(M48T35_RTC_MONTH);
+ year = gemini_rtc_read(M48T35_RTC_YEAR);
+ } while( sec != gemini_rtc_read(M48T35_RTC_SECONDS));
+#ifdef DEBUG_RTC
+ printk("get rtc: sec=%x, min=%x, hour=%x, day=%x, mon=%x, year=%x\n",
+ sec, min, hour, day, mon, year);
+#endif
+
+ gemini_rtc_write(reg, M48T35_RTC_CONTROL);
+
+ BCD_TO_BIN(sec);
+ BCD_TO_BIN(min);
+ BCD_TO_BIN(hour);
+ BCD_TO_BIN(day);
+ BCD_TO_BIN(mon);
+ BCD_TO_BIN(year);
+
+ if ((year += 1900) < 1970)
+ year += 100;
+#ifdef DEBUG_RTC
+ printk("get rtc: sec=%x, min=%x, hour=%x, day=%x, mon=%x, year=%x\n",
+ sec, min, hour, day, mon, year);
+#endif
+
+ return mktime( year, mon, day, hour, min, sec );
+}
+
+
+int
+gemini_set_rtc_time( unsigned long now )
+{
+ unsigned char reg;
+ struct rtc_time tm;
+
+ to_tm( now, &tm );
+
+ reg = gemini_rtc_read(M48T35_RTC_CONTROL);
+#ifdef DEBUG_RTC
+ printk("set rtc: reg = %x\n", reg);
+#endif
+
+ gemini_rtc_write((reg|M48T35_RTC_SET), M48T35_RTC_CONTROL);
+#ifdef DEBUG_RTC
+ printk("set rtc: tm vals - sec=%x, min=%x, hour=%x, mon=%x, mday=%x, year=%x\n",
+ tm.tm_sec, tm.tm_min, tm.tm_hour, tm.tm_mon, tm.tm_mday, tm.tm_year);
+#endif
+
+ tm.tm_year -= 1900;
+ BIN_TO_BCD(tm.tm_sec);
+ BIN_TO_BCD(tm.tm_min);
+ BIN_TO_BCD(tm.tm_hour);
+ BIN_TO_BCD(tm.tm_mon);
+ BIN_TO_BCD(tm.tm_mday);
+ BIN_TO_BCD(tm.tm_year);
+#ifdef DEBUG_RTC
+ printk("set rtc: tm vals - sec=%x, min=%x, hour=%x, mon=%x, mday=%x, year=%x\n",
+ tm.tm_sec, tm.tm_min, tm.tm_hour, tm.tm_mon, tm.tm_mday, tm.tm_year);
+#endif
+
+ gemini_rtc_write(tm.tm_sec, M48T35_RTC_SECONDS);
+ gemini_rtc_write(tm.tm_min, M48T35_RTC_MINUTES);
+ gemini_rtc_write(tm.tm_hour, M48T35_RTC_HOURS);
+ gemini_rtc_write(tm.tm_mday, M48T35_RTC_DOM);
+ gemini_rtc_write(tm.tm_mon, M48T35_RTC_MONTH);
+ gemini_rtc_write(tm.tm_year, M48T35_RTC_YEAR);
+
+ /* done writing */
+ gemini_rtc_write(reg, M48T35_RTC_CONTROL);
+
+ if ((time_state == TIME_ERROR) || (time_state == TIME_BAD))
+ time_state = TIME_OK;
+
+ return 0;
+}
+
+/* use the RTC to determine the decrementer count */
+void __init gemini_calibrate_decr(void)
+{
+ int freq, divisor;
+ unsigned char reg;
+
+ /* determine processor bus speed */
+ reg = readb(GEMINI_BSTAT);
+
+ switch(((reg & 0x0c)>>2)&0x3) {
+ case 0:
+ default:
+ freq = 66667;
+ break;
+ case 1:
+ freq = 83000;
+ break;
+ case 2:
+ freq = 100000;
+ break;
+ }
+
+ freq *= 1000;
+ divisor = 4;
+ tb_ticks_per_jiffy = freq / HZ / divisor;
+ tb_to_us = mulhwu_scale_factor(freq/divisor, 1000000);
+}
+
+unsigned long __init gemini_find_end_of_memory(void)
+{
+ unsigned long total;
+ unsigned char reg;
+
+ reg = readb(GEMINI_MEMCFG);
+ total = ((1<<((reg & 0x7) - 1)) *
+ (8<<((reg >> 3) & 0x7)));
+ total *= (1024*1024);
+ return total;
+}
+
+static void __init
+gemini_map_io(void)
+{
+ io_block_mapping(0xf0000000, 0xf0000000, 0x10000000, _PAGE_IO);
+ io_block_mapping(0x80000000, 0x80000000, 0x10000000, _PAGE_IO);
+}
+
+#ifdef CONFIG_SMP
+static int
+smp_gemini_probe(void)
+{
+ int i, nr;
+
+ nr = (readb(GEMINI_CPUSTAT) & GEMINI_CPU_COUNT_MASK) >> 2;
+ if (nr == 0)
+ nr = 4;
+
+ if (nr > 1) {
+ openpic_request_IPIs();
+ for (i = 1; i < nr; ++i)
+ smp_hw_index[i] = i;
+ }
+
+ return nr;
+}
+
+static void
+smp_gemini_kick_cpu(int nr)
+{
+ openpic_reset_processor_phys(1 << nr);
+ openpic_reset_processor_phys(0);
+}
+
+static void
+smp_gemini_setup_cpu(int cpu_nr)
+{
+ if (OpenPIC_Addr)
+ do_openpic_setup_cpu();
+ if (cpu_nr > 0)
+ gemini_init_l2();
+}
+
+static struct smp_ops_t gemini_smp_ops = {
+ smp_openpic_message_pass,
+ smp_gemini_probe,
+ smp_gemini_kick_cpu,
+ smp_gemini_setup_cpu,
+ .give_timebase = smp_generic_give_timebase,
+ .take_timebase = smp_generic_take_timebase,
+};
+#endif /* CONFIG_SMP */
+
+void __init platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
+ unsigned long r6, unsigned long r7)
+{
+ int i;
+
+ /* Restore BATs for now */
+ mtspr(SPRN_DBAT3U, 0xf0001fff);
+ mtspr(SPRN_DBAT3L, 0xf000002a);
+
+ parse_bootinfo(find_bootinfo());
+
+ for(i = 0; i < GEMINI_LEDS; i++)
+ gemini_led_off(i);
+
+ ISA_DMA_THRESHOLD = 0;
+ DMA_MODE_READ = 0;
+ DMA_MODE_WRITE = 0;
+
+#ifdef CONFIG_BLK_DEV_INITRD
+ if ( r4 )
+ {
+ initrd_start = r4 + KERNELBASE;
+ initrd_end = r5 + KERNELBASE;
+ }
+#endif
+
+ ppc_md.setup_arch = gemini_setup_arch;
+ ppc_md.show_cpuinfo = gemini_show_cpuinfo;
+ ppc_md.irq_canonicalize = NULL;
+ ppc_md.init_IRQ = gemini_init_IRQ;
+ ppc_md.get_irq = openpic_get_irq;
+ ppc_md.init = NULL;
+
+ ppc_md.restart = gemini_restart;
+ ppc_md.power_off = gemini_power_off;
+ ppc_md.halt = gemini_halt;
+
+ ppc_md.time_init = gemini_time_init;
+ ppc_md.set_rtc_time = gemini_set_rtc_time;
+ ppc_md.get_rtc_time = gemini_get_rtc_time;
+ ppc_md.calibrate_decr = gemini_calibrate_decr;
+
+ ppc_md.find_end_of_memory = gemini_find_end_of_memory;
+ ppc_md.setup_io_mappings = gemini_map_io;
+
+ ppc_md.pcibios_fixup_bus = gemini_pcibios_fixup;
+
+#ifdef CONFIG_SMP
+ ppc_md.smp_ops = &gemini_smp_ops;
+#endif /* CONFIG_SMP */
+}
diff --git a/arch/ppc/platforms/hdpu.c b/arch/ppc/platforms/hdpu.c
new file mode 100644
index 0000000..b659d7b
--- /dev/null
+++ b/arch/ppc/platforms/hdpu.c
@@ -0,0 +1,1062 @@
+
+/*
+ * arch/ppc/platforms/hdpu_setup.c
+ *
+ * Board setup routines for the Sky Computers HDPU Compute Blade.
+ *
+ * Written by Brian Waite <waite@skycomputers.com>
+ *
+ * Based on code done by - Mark A. Greer <mgreer@mvista.com>
+ * Rabeeh Khoury - rabeeh@galileo.co.il
+ *
+ * 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.
+ */
+
+#include <linux/config.h>
+
+#include <linux/pci.h>
+#include <linux/delay.h>
+#include <linux/irq.h>
+#include <linux/ide.h>
+#include <linux/seq_file.h>
+
+#include <linux/initrd.h>
+#include <linux/root_dev.h>
+#include <linux/smp.h>
+
+#include <asm/time.h>
+#include <asm/machdep.h>
+#include <asm/todc.h>
+#include <asm/mv64x60.h>
+#include <asm/ppcboot.h>
+#include <platforms/hdpu.h>
+#include <linux/mv643xx.h>
+#include <linux/hdpu_features.h>
+#include <linux/device.h>
+#include <linux/mtd/physmap.h>
+
+#define BOARD_VENDOR "Sky Computers"
+#define BOARD_MACHINE "HDPU-CB-A"
+
+bd_t ppcboot_bd;
+int ppcboot_bd_valid = 0;
+
+static mv64x60_handle_t bh;
+
+extern char cmd_line[];
+
+unsigned long hdpu_find_end_of_memory(void);
+void hdpu_mpsc_progress(char *s, unsigned short hex);
+void hdpu_heartbeat(void);
+
+static void parse_bootinfo(unsigned long r3,
+ unsigned long r4, unsigned long r5,
+ unsigned long r6, unsigned long r7);
+static void hdpu_set_l1pe(void);
+static void hdpu_cpustate_set(unsigned char new_state);
+#ifdef CONFIG_SMP
+static spinlock_t timebase_lock = SPIN_LOCK_UNLOCKED;
+static unsigned int timebase_upper = 0, timebase_lower = 0;
+extern int smp_tb_synchronized;
+
+void __devinit hdpu_tben_give(void);
+void __devinit hdpu_tben_take(void);
+#endif
+
+static int __init
+hdpu_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin)
+{
+ struct pci_controller *hose = pci_bus_to_hose(dev->bus->number);
+
+ if (hose->index == 0) {
+ static char pci_irq_table[][4] = {
+ {HDPU_PCI_0_IRQ, 0, 0, 0},
+ {HDPU_PCI_0_IRQ, 0, 0, 0},
+ };
+
+ const long min_idsel = 1, max_idsel = 2, irqs_per_slot = 4;
+ return PCI_IRQ_TABLE_LOOKUP;
+ } else {
+ static char pci_irq_table[][4] = {
+ {HDPU_PCI_1_IRQ, 0, 0, 0},
+ };
+
+ const long min_idsel = 1, max_idsel = 1, irqs_per_slot = 4;
+ return PCI_IRQ_TABLE_LOOKUP;
+ }
+}
+
+static void __init hdpu_intr_setup(void)
+{
+ mv64x60_write(&bh, MV64x60_GPP_IO_CNTL,
+ (1 | (1 << 2) | (1 << 3) | (1 << 4) | (1 << 5) |
+ (1 << 6) | (1 << 7) | (1 << 12) | (1 << 16) |
+ (1 << 18) | (1 << 19) | (1 << 20) | (1 << 21) |
+ (1 << 22) | (1 << 23) | (1 << 24) | (1 << 25) |
+ (1 << 26) | (1 << 27) | (1 << 28) | (1 << 29)));
+
+ /* XXXX Erranum FEr PCI-#8 */
+ mv64x60_clr_bits(&bh, MV64x60_PCI0_CMD, (1 << 5) | (1 << 9));
+ mv64x60_clr_bits(&bh, MV64x60_PCI1_CMD, (1 << 5) | (1 << 9));
+
+ /*
+ * Dismiss and then enable interrupt on GPP interrupt cause
+ * for CPU #0
+ */
+ mv64x60_write(&bh, MV64x60_GPP_INTR_CAUSE, ~((1 << 8) | (1 << 13)));
+ mv64x60_set_bits(&bh, MV64x60_GPP_INTR_MASK, (1 << 8) | (1 << 13));
+
+ /*
+ * Dismiss and then enable interrupt on CPU #0 high cause reg
+ * BIT25 summarizes GPP interrupts 8-15
+ */
+ mv64x60_set_bits(&bh, MV64360_IC_CPU0_INTR_MASK_HI, (1 << 25));
+}
+
+static void __init hdpu_setup_peripherals(void)
+{
+ unsigned int val;
+
+ mv64x60_set_32bit_window(&bh, MV64x60_CPU2BOOT_WIN,
+ HDPU_EMB_FLASH_BASE, HDPU_EMB_FLASH_SIZE, 0);
+ bh.ci->enable_window_32bit(&bh, MV64x60_CPU2BOOT_WIN);
+
+ mv64x60_set_32bit_window(&bh, MV64x60_CPU2DEV_0_WIN,
+ HDPU_TBEN_BASE, HDPU_TBEN_SIZE, 0);
+ bh.ci->enable_window_32bit(&bh, MV64x60_CPU2DEV_0_WIN);
+
+ mv64x60_set_32bit_window(&bh, MV64x60_CPU2DEV_1_WIN,
+ HDPU_NEXUS_ID_BASE, HDPU_NEXUS_ID_SIZE, 0);
+ bh.ci->enable_window_32bit(&bh, MV64x60_CPU2DEV_1_WIN);
+
+ mv64x60_set_32bit_window(&bh, MV64x60_CPU2SRAM_WIN,
+ HDPU_INTERNAL_SRAM_BASE,
+ HDPU_INTERNAL_SRAM_SIZE, 0);
+ bh.ci->enable_window_32bit(&bh, MV64x60_CPU2SRAM_WIN);
+
+ bh.ci->disable_window_32bit(&bh, MV64x60_ENET2MEM_4_WIN);
+ mv64x60_set_32bit_window(&bh, MV64x60_ENET2MEM_4_WIN, 0, 0, 0);
+
+ mv64x60_clr_bits(&bh, MV64x60_PCI0_PCI_DECODE_CNTL, (1 << 3));
+ mv64x60_clr_bits(&bh, MV64x60_PCI1_PCI_DECODE_CNTL, (1 << 3));
+ mv64x60_clr_bits(&bh, MV64x60_TIMR_CNTR_0_3_CNTL,
+ ((1 << 0) | (1 << 8) | (1 << 16) | (1 << 24)));
+
+ /* Enable pipelining */
+ mv64x60_set_bits(&bh, MV64x60_CPU_CONFIG, (1 << 13));
+ /* Enable Snoop Pipelineing */
+ mv64x60_set_bits(&bh, MV64360_D_UNIT_CONTROL_HIGH, (1 << 24));
+
+ /*
+ * Change DRAM read buffer assignment.
+ * Assign read buffer 0 dedicated only for CPU,
+ * and the rest read buffer 1.
+ */
+ val = mv64x60_read(&bh, MV64360_SDRAM_CONFIG);
+ val = val & 0x03ffffff;
+ val = val | 0xf8000000;
+ mv64x60_write(&bh, MV64360_SDRAM_CONFIG, val);
+
+ /*
+ * Configure internal SRAM -
+ * Cache coherent write back, if CONFIG_MV64360_SRAM_CACHE_COHERENT set
+ * Parity enabled.
+ * Parity error propagation
+ * Arbitration not parked for CPU only
+ * Other bits are reserved.
+ */
+#ifdef CONFIG_MV64360_SRAM_CACHE_COHERENT
+ mv64x60_write(&bh, MV64360_SRAM_CONFIG, 0x001600b2);
+#else
+ mv64x60_write(&bh, MV64360_SRAM_CONFIG, 0x001600b0);
+#endif
+
+ hdpu_intr_setup();
+}
+
+static void __init hdpu_setup_bridge(void)
+{
+ struct mv64x60_setup_info si;
+ int i;
+
+ memset(&si, 0, sizeof(si));
+
+ si.phys_reg_base = HDPU_BRIDGE_REG_BASE;
+ si.pci_0.enable_bus = 1;
+ si.pci_0.pci_io.cpu_base = HDPU_PCI0_IO_START_PROC_ADDR;
+ si.pci_0.pci_io.pci_base_hi = 0;
+ si.pci_0.pci_io.pci_base_lo = HDPU_PCI0_IO_START_PCI_ADDR;
+ si.pci_0.pci_io.size = HDPU_PCI0_IO_SIZE;
+ si.pci_0.pci_io.swap = MV64x60_CPU2PCI_SWAP_NONE;
+ si.pci_0.pci_mem[0].cpu_base = HDPU_PCI0_MEM_START_PROC_ADDR;
+ si.pci_0.pci_mem[0].pci_base_hi = HDPU_PCI0_MEM_START_PCI_HI_ADDR;
+ si.pci_0.pci_mem[0].pci_base_lo = HDPU_PCI0_MEM_START_PCI_LO_ADDR;
+ si.pci_0.pci_mem[0].size = HDPU_PCI0_MEM_SIZE;
+ si.pci_0.pci_mem[0].swap = MV64x60_CPU2PCI_SWAP_NONE;
+ si.pci_0.pci_cmd_bits = 0;
+ si.pci_0.latency_timer = 0x80;
+
+ si.pci_1.enable_bus = 1;
+ si.pci_1.pci_io.cpu_base = HDPU_PCI1_IO_START_PROC_ADDR;
+ si.pci_1.pci_io.pci_base_hi = 0;
+ si.pci_1.pci_io.pci_base_lo = HDPU_PCI1_IO_START_PCI_ADDR;
+ si.pci_1.pci_io.size = HDPU_PCI1_IO_SIZE;
+ si.pci_1.pci_io.swap = MV64x60_CPU2PCI_SWAP_NONE;
+ si.pci_1.pci_mem[0].cpu_base = HDPU_PCI1_MEM_START_PROC_ADDR;
+ si.pci_1.pci_mem[0].pci_base_hi = HDPU_PCI1_MEM_START_PCI_HI_ADDR;
+ si.pci_1.pci_mem[0].pci_base_lo = HDPU_PCI1_MEM_START_PCI_LO_ADDR;
+ si.pci_1.pci_mem[0].size = HDPU_PCI1_MEM_SIZE;
+ si.pci_1.pci_mem[0].swap = MV64x60_CPU2PCI_SWAP_NONE;
+ si.pci_1.pci_cmd_bits = 0;
+ si.pci_1.latency_timer = 0x80;
+
+ for (i = 0; i < MV64x60_CPU2MEM_WINDOWS; i++) {
+#if defined(CONFIG_NOT_COHERENT_CACHE)
+ si.cpu_prot_options[i] = 0;
+ si.enet_options[i] = MV64360_ENET2MEM_SNOOP_NONE;
+ si.mpsc_options[i] = MV64360_MPSC2MEM_SNOOP_NONE;
+ si.idma_options[i] = MV64360_IDMA2MEM_SNOOP_NONE;
+
+ si.pci_1.acc_cntl_options[i] =
+ MV64360_PCI_ACC_CNTL_SNOOP_NONE |
+ MV64360_PCI_ACC_CNTL_SWAP_NONE |
+ MV64360_PCI_ACC_CNTL_MBURST_128_BYTES |
+ MV64360_PCI_ACC_CNTL_RDSIZE_256_BYTES;
+
+ si.pci_0.acc_cntl_options[i] =
+ MV64360_PCI_ACC_CNTL_SNOOP_NONE |
+ MV64360_PCI_ACC_CNTL_SWAP_NONE |
+ MV64360_PCI_ACC_CNTL_MBURST_128_BYTES |
+ MV64360_PCI_ACC_CNTL_RDSIZE_256_BYTES;
+
+#else
+ si.cpu_prot_options[i] = 0;
+ si.enet_options[i] = MV64360_ENET2MEM_SNOOP_WB; /* errata */
+ si.mpsc_options[i] = MV64360_MPSC2MEM_SNOOP_WB; /* errata */
+ si.idma_options[i] = MV64360_IDMA2MEM_SNOOP_WB; /* errata */
+
+ si.pci_0.acc_cntl_options[i] =
+ MV64360_PCI_ACC_CNTL_SNOOP_WB |
+ MV64360_PCI_ACC_CNTL_SWAP_NONE |
+ MV64360_PCI_ACC_CNTL_MBURST_32_BYTES |
+ MV64360_PCI_ACC_CNTL_RDSIZE_256_BYTES;
+
+ si.pci_1.acc_cntl_options[i] =
+ MV64360_PCI_ACC_CNTL_SNOOP_WB |
+ MV64360_PCI_ACC_CNTL_SWAP_NONE |
+ MV64360_PCI_ACC_CNTL_MBURST_32_BYTES |
+ MV64360_PCI_ACC_CNTL_RDSIZE_256_BYTES;
+#endif
+ }
+
+ hdpu_cpustate_set(CPUSTATE_KERNEL_MAJOR | CPUSTATE_KERNEL_INIT_PCI);
+
+ /* Lookup PCI host bridges */
+ mv64x60_init(&bh, &si);
+ pci_dram_offset = 0; /* System mem at same addr on PCI & cpu bus */
+ ppc_md.pci_swizzle = common_swizzle;
+ ppc_md.pci_map_irq = hdpu_map_irq;
+
+ mv64x60_set_bus(&bh, 0, 0);
+ bh.hose_a->first_busno = 0;
+ bh.hose_a->last_busno = 0xff;
+ bh.hose_a->last_busno = pciauto_bus_scan(bh.hose_a, 0);
+
+ bh.hose_b->first_busno = bh.hose_a->last_busno + 1;
+ mv64x60_set_bus(&bh, 1, bh.hose_b->first_busno);
+ bh.hose_b->last_busno = 0xff;
+ bh.hose_b->last_busno = pciauto_bus_scan(bh.hose_b,
+ bh.hose_b->first_busno);
+
+ ppc_md.pci_exclude_device = mv64x60_pci_exclude_device;
+
+ hdpu_cpustate_set(CPUSTATE_KERNEL_MAJOR | CPUSTATE_KERNEL_INIT_REG);
+ /*
+ * Enabling of PCI internal-vs-external arbitration
+ * is a platform- and errata-dependent decision.
+ */
+ return;
+}
+
+#if defined(CONFIG_SERIAL_MPSC_CONSOLE)
+static void __init hdpu_early_serial_map(void)
+{
+#ifdef CONFIG_KGDB
+ static char first_time = 1;
+
+#if defined(CONFIG_KGDB_TTYS0)
+#define KGDB_PORT 0
+#elif defined(CONFIG_KGDB_TTYS1)
+#define KGDB_PORT 1
+#else
+#error "Invalid kgdb_tty port"
+#endif
+
+ if (first_time) {
+ gt_early_mpsc_init(KGDB_PORT,
+ B9600 | CS8 | CREAD | HUPCL | CLOCAL);
+ first_time = 0;
+ }
+
+ return;
+#endif
+}
+#endif
+
+static void hdpu_init2(void)
+{
+ return;
+}
+
+#if defined(CONFIG_MV643XX_ETH)
+static void __init hdpu_fixup_eth_pdata(struct platform_device *pd)
+{
+
+ struct mv643xx_eth_platform_data *eth_pd;
+ eth_pd = pd->dev.platform_data;
+
+ eth_pd->port_serial_control =
+ mv64x60_read(&bh, MV643XX_ETH_PORT_SERIAL_CONTROL_REG(pd->id) & ~1);
+
+ eth_pd->force_phy_addr = 1;
+ eth_pd->phy_addr = pd->id;
+ eth_pd->tx_queue_size = 400;
+ eth_pd->rx_queue_size = 800;
+}
+#endif
+
+static void __init hdpu_fixup_mpsc_pdata(struct platform_device *pd)
+{
+
+ struct mpsc_pdata *pdata;
+
+ pdata = (struct mpsc_pdata *)pd->dev.platform_data;
+
+ pdata->max_idle = 40;
+ if (ppcboot_bd_valid)
+ pdata->default_baud = ppcboot_bd.bi_baudrate;
+ else
+ pdata->default_baud = HDPU_DEFAULT_BAUD;
+ pdata->brg_clk_src = HDPU_MPSC_CLK_SRC;
+ pdata->brg_clk_freq = HDPU_MPSC_CLK_FREQ;
+}
+
+#if defined(CONFIG_HDPU_FEATURES)
+static void __init hdpu_fixup_cpustate_pdata(struct platform_device *pd)
+{
+ struct platform_device *pds[1];
+ pds[0] = pd;
+ mv64x60_pd_fixup(&bh, pds, 1);
+}
+#endif
+
+static int __init hdpu_platform_notify(struct device *dev)
+{
+ static struct {
+ char *bus_id;
+ void ((*rtn) (struct platform_device * pdev));
+ } dev_map[] = {
+ {
+ MPSC_CTLR_NAME ".0", hdpu_fixup_mpsc_pdata},
+#if defined(CONFIG_MV643XX_ETH)
+ {
+ MV643XX_ETH_NAME ".0", hdpu_fixup_eth_pdata},
+#endif
+#if defined(CONFIG_HDPU_FEATURES)
+ {
+ HDPU_CPUSTATE_NAME ".0", hdpu_fixup_cpustate_pdata},
+#endif
+ };
+ struct platform_device *pdev;
+ int i;
+
+ if (dev && dev->bus_id)
+ for (i = 0; i < ARRAY_SIZE(dev_map); i++)
+ if (!strncmp(dev->bus_id, dev_map[i].bus_id,
+ BUS_ID_SIZE)) {
+
+ pdev = container_of(dev,
+ struct platform_device,
+ dev);
+ dev_map[i].rtn(pdev);
+ }
+
+ return 0;
+}
+
+static void __init hdpu_setup_arch(void)
+{
+ if (ppc_md.progress)
+ ppc_md.progress("hdpu_setup_arch: enter", 0);
+#ifdef CONFIG_BLK_DEV_INITRD
+ if (initrd_start)
+ ROOT_DEV = Root_RAM0;
+ else
+#endif
+#ifdef CONFIG_ROOT_NFS
+ ROOT_DEV = Root_NFS;
+#else
+ ROOT_DEV = Root_SDA2;
+#endif
+
+ ppc_md.heartbeat = hdpu_heartbeat;
+
+ ppc_md.heartbeat_reset = HZ;
+ ppc_md.heartbeat_count = 1;
+
+ if (ppc_md.progress)
+ ppc_md.progress("hdpu_setup_arch: Enabling L2 cache", 0);
+
+ /* Enable L1 Parity Bits */
+ hdpu_set_l1pe();
+
+ /* Enable L2 and L3 caches (if 745x) */
+ _set_L2CR(0x80080000);
+
+ if (ppc_md.progress)
+ ppc_md.progress("hdpu_setup_arch: enter", 0);
+
+ hdpu_setup_bridge();
+
+ hdpu_setup_peripherals();
+
+#ifdef CONFIG_SERIAL_MPSC_CONSOLE
+ hdpu_early_serial_map();
+#endif
+
+ printk("SKY HDPU Compute Blade \n");
+
+ if (ppc_md.progress)
+ ppc_md.progress("hdpu_setup_arch: exit", 0);
+
+ hdpu_cpustate_set(CPUSTATE_KERNEL_MAJOR | CPUSTATE_KERNEL_OK);
+ return;
+}
+static void __init hdpu_init_irq(void)
+{
+ mv64360_init_irq();
+}
+
+static void __init hdpu_set_l1pe()
+{
+ unsigned long ictrl;
+ asm volatile ("mfspr %0, 1011":"=r" (ictrl):);
+ ictrl |= ICTRL_EICE | ICTRL_EDC | ICTRL_EICP;
+ asm volatile ("mtspr 1011, %0"::"r" (ictrl));
+}
+
+/*
+ * Set BAT 1 to map 0xf1000000 to end of physical memory space.
+ */
+static __inline__ void hdpu_set_bat(void)
+{
+ mb();
+ mtspr(SPRN_DBAT1U, 0xf10001fe);
+ mtspr(SPRN_DBAT1L, 0xf100002a);
+ mb();
+
+ return;
+}
+
+unsigned long __init hdpu_find_end_of_memory(void)
+{
+ return mv64x60_get_mem_size(CONFIG_MV64X60_NEW_BASE,
+ MV64x60_TYPE_MV64360);
+}
+
+static void hdpu_reset_board(void)
+{
+ volatile int infinite = 1;
+
+ hdpu_cpustate_set(CPUSTATE_KERNEL_MAJOR | CPUSTATE_KERNEL_RESET);
+
+ local_irq_disable();
+
+ /* Clear all the LEDs */
+ mv64x60_write(&bh, MV64x60_GPP_VALUE_CLR, ((1 << 4) |
+ (1 << 5) | (1 << 6)));
+
+ /* disable and invalidate the L2 cache */
+ _set_L2CR(0);
+ _set_L2CR(0x200000);
+
+ /* flush and disable L1 I/D cache */
+ __asm__ __volatile__
+ ("\n"
+ "mfspr 3,1008\n"
+ "ori 5,5,0xcc00\n"
+ "ori 4,3,0xc00\n"
+ "andc 5,3,5\n"
+ "sync\n"
+ "mtspr 1008,4\n"
+ "isync\n" "sync\n" "mtspr 1008,5\n" "isync\n" "sync\n");
+
+ /* Hit the reset bit */
+ mv64x60_write(&bh, MV64x60_GPP_VALUE_CLR, (1 << 3));
+
+ while (infinite)
+ infinite = infinite;
+
+ return;
+}
+
+static void hdpu_restart(char *cmd)
+{
+ volatile ulong i = 10000000;
+
+ hdpu_reset_board();
+
+ while (i-- > 0) ;
+ panic("restart failed\n");
+}
+
+static void hdpu_halt(void)
+{
+ local_irq_disable();
+
+ hdpu_cpustate_set(CPUSTATE_KERNEL_MAJOR | CPUSTATE_KERNEL_HALT);
+
+ /* Clear all the LEDs */
+ mv64x60_write(&bh, MV64x60_GPP_VALUE_CLR, ((1 << 4) | (1 << 5) |
+ (1 << 6)));
+ while (1) ;
+ /* NOTREACHED */
+}
+
+static void hdpu_power_off(void)
+{
+ hdpu_halt();
+ /* NOTREACHED */
+}
+
+static int hdpu_show_cpuinfo(struct seq_file *m)
+{
+ uint pvid;
+
+ pvid = mfspr(SPRN_PVR);
+ seq_printf(m, "vendor\t\t: Sky Computers\n");
+ seq_printf(m, "machine\t\t: HDPU Compute Blade\n");
+ seq_printf(m, "PVID\t\t: 0x%x, vendor: %s\n",
+ pvid, (pvid & (1 << 15) ? "IBM" : "Motorola"));
+
+ return 0;
+}
+
+static void __init hdpu_calibrate_decr(void)
+{
+ ulong freq;
+
+ if (ppcboot_bd_valid)
+ freq = ppcboot_bd.bi_busfreq / 4;
+ else
+ freq = 133000000;
+
+ printk("time_init: decrementer frequency = %lu.%.6lu MHz\n",
+ freq / 1000000, freq % 1000000);
+
+ tb_ticks_per_jiffy = freq / HZ;
+ tb_to_us = mulhwu_scale_factor(freq, 1000000);
+
+ return;
+}
+
+static void parse_bootinfo(unsigned long r3,
+ unsigned long r4, unsigned long r5,
+ unsigned long r6, unsigned long r7)
+{
+ bd_t *bd = NULL;
+ char *cmdline_start = NULL;
+ int cmdline_len = 0;
+
+ if (r3) {
+ if ((r3 & 0xf0000000) == 0)
+ r3 += KERNELBASE;
+ if ((r3 & 0xf0000000) == KERNELBASE) {
+ bd = (void *)r3;
+
+ memcpy(&ppcboot_bd, bd, sizeof(ppcboot_bd));
+ ppcboot_bd_valid = 1;
+ }
+ }
+#ifdef CONFIG_BLK_DEV_INITRD
+ if (r4 && r5 && r5 > r4) {
+ if ((r4 & 0xf0000000) == 0)
+ r4 += KERNELBASE;
+ if ((r5 & 0xf0000000) == 0)
+ r5 += KERNELBASE;
+ if ((r4 & 0xf0000000) == KERNELBASE) {
+ initrd_start = r4;
+ initrd_end = r5;
+ initrd_below_start_ok = 1;
+ }
+ }
+#endif /* CONFIG_BLK_DEV_INITRD */
+
+ if (r6 && r7 && r7 > r6) {
+ if ((r6 & 0xf0000000) == 0)
+ r6 += KERNELBASE;
+ if ((r7 & 0xf0000000) == 0)
+ r7 += KERNELBASE;
+ if ((r6 & 0xf0000000) == KERNELBASE) {
+ cmdline_start = (void *)r6;
+ cmdline_len = (r7 - r6);
+ strncpy(cmd_line, cmdline_start, cmdline_len);
+ }
+ }
+}
+
+#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
+static int hdpu_ide_check_region(ide_ioreg_t from, unsigned int extent)
+{
+ return check_region(from, extent);
+}
+
+static void
+hdpu_ide_request_region(ide_ioreg_t from, unsigned int extent, const char *name)
+{
+ request_region(from, extent, name);
+ return;
+}
+
+static void hdpu_ide_release_region(ide_ioreg_t from, unsigned int extent)
+{
+ release_region(from, extent);
+ return;
+}
+
+static void __init
+hdpu_ide_pci_init_hwif_ports(hw_regs_t * hw, ide_ioreg_t data_port,
+ ide_ioreg_t ctrl_port, int *irq)
+{
+ struct pci_dev *dev;
+
+ pci_for_each_dev(dev) {
+ if (((dev->class >> 8) == PCI_CLASS_STORAGE_IDE) ||
+ ((dev->class >> 8) == PCI_CLASS_STORAGE_RAID)) {
+ hw->irq = dev->irq;
+
+ if (irq != NULL) {
+ *irq = dev->irq;
+ }
+ }
+ }
+
+ return;
+}
+#endif
+
+void hdpu_heartbeat(void)
+{
+ if (mv64x60_read(&bh, MV64x60_GPP_VALUE) & (1 << 5))
+ mv64x60_write(&bh, MV64x60_GPP_VALUE_CLR, (1 << 5));
+ else
+ mv64x60_write(&bh, MV64x60_GPP_VALUE_SET, (1 << 5));
+
+ ppc_md.heartbeat_count = ppc_md.heartbeat_reset;
+
+}
+
+static void __init hdpu_map_io(void)
+{
+ io_block_mapping(0xf1000000, 0xf1000000, 0x20000, _PAGE_IO);
+}
+
+#ifdef CONFIG_SMP
+char hdpu_smp0[] = "SMP Cpu #0";
+char hdpu_smp1[] = "SMP Cpu #1";
+
+static irqreturn_t hdpu_smp_cpu0_int_handler(int irq, void *dev_id,
+ struct pt_regs *regs)
+{
+ volatile unsigned int doorbell;
+
+ doorbell = mv64x60_read(&bh, MV64360_CPU0_DOORBELL);
+
+ /* Ack the doorbell interrupts */
+ mv64x60_write(&bh, MV64360_CPU0_DOORBELL_CLR, doorbell);
+
+ if (doorbell & 1) {
+ smp_message_recv(0, regs);
+ }
+ if (doorbell & 2) {
+ smp_message_recv(1, regs);
+ }
+ if (doorbell & 4) {
+ smp_message_recv(2, regs);
+ }
+ if (doorbell & 8) {
+ smp_message_recv(3, regs);
+ }
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t hdpu_smp_cpu1_int_handler(int irq, void *dev_id,
+ struct pt_regs *regs)
+{
+ volatile unsigned int doorbell;
+
+ doorbell = mv64x60_read(&bh, MV64360_CPU1_DOORBELL);
+
+ /* Ack the doorbell interrupts */
+ mv64x60_write(&bh, MV64360_CPU1_DOORBELL_CLR, doorbell);
+
+ if (doorbell & 1) {
+ smp_message_recv(0, regs);
+ }
+ if (doorbell & 2) {
+ smp_message_recv(1, regs);
+ }
+ if (doorbell & 4) {
+ smp_message_recv(2, regs);
+ }
+ if (doorbell & 8) {
+ smp_message_recv(3, regs);
+ }
+ return IRQ_HANDLED;
+}
+
+static void smp_hdpu_CPU_two(void)
+{
+ __asm__ __volatile__
+ ("\n"
+ "lis 3,0x0000\n"
+ "ori 3,3,0x00c0\n"
+ "mtspr 26, 3\n" "li 4,0\n" "mtspr 27,4\n" "rfi");
+
+}
+
+static int smp_hdpu_probe(void)
+{
+ int *cpu_count_reg;
+ int num_cpus = 0;
+
+ cpu_count_reg = ioremap(HDPU_NEXUS_ID_BASE, HDPU_NEXUS_ID_SIZE);
+ if (cpu_count_reg) {
+ num_cpus = (*cpu_count_reg >> 20) & 0x3;
+ iounmap(cpu_count_reg);
+ }
+
+ /* Validate the bits in the CPLD. If we could not map the reg, return 2.
+ * If the register reported 0 or 3, return 2.
+ * Older CPLD revisions set these bits to all ones (val = 3).
+ */
+ if ((num_cpus < 1) || (num_cpus > 2)) {
+ printk
+ ("Unable to determine the number of processors %d . deafulting to 2.\n",
+ num_cpus);
+ num_cpus = 2;
+ }
+ return num_cpus;
+}
+
+static void
+smp_hdpu_message_pass(int target, int msg, unsigned long data, int wait)
+{
+ if (msg > 0x3) {
+ printk("SMP %d: smp_message_pass: unknown msg %d\n",
+ smp_processor_id(), msg);
+ return;
+ }
+ switch (target) {
+ case MSG_ALL:
+ mv64x60_write(&bh, MV64360_CPU0_DOORBELL, 1 << msg);
+ mv64x60_write(&bh, MV64360_CPU1_DOORBELL, 1 << msg);
+ break;
+ case MSG_ALL_BUT_SELF:
+ if (smp_processor_id())
+ mv64x60_write(&bh, MV64360_CPU0_DOORBELL, 1 << msg);
+ else
+ mv64x60_write(&bh, MV64360_CPU1_DOORBELL, 1 << msg);
+ break;
+ default:
+ if (target == 0)
+ mv64x60_write(&bh, MV64360_CPU0_DOORBELL, 1 << msg);
+ else
+ mv64x60_write(&bh, MV64360_CPU1_DOORBELL, 1 << msg);
+ break;
+ }
+}
+
+static void smp_hdpu_kick_cpu(int nr)
+{
+ volatile unsigned int *bootaddr;
+
+ if (ppc_md.progress)
+ ppc_md.progress("smp_hdpu_kick_cpu", 0);
+
+ hdpu_cpustate_set(CPUSTATE_KERNEL_MAJOR | CPUSTATE_KERNEL_CPU1_KICK);
+
+ /* Disable BootCS. Must also reduce the windows size to zero. */
+ bh.ci->disable_window_32bit(&bh, MV64x60_CPU2BOOT_WIN);
+ mv64x60_set_32bit_window(&bh, MV64x60_CPU2BOOT_WIN, 0, 0, 0);
+
+ bootaddr = ioremap(HDPU_INTERNAL_SRAM_BASE, HDPU_INTERNAL_SRAM_SIZE);
+ if (!bootaddr) {
+ if (ppc_md.progress)
+ ppc_md.progress("smp_hdpu_kick_cpu: ioremap failed", 0);
+ return;
+ }
+
+ memcpy((void *)(bootaddr + 0x40), (void *)&smp_hdpu_CPU_two, 0x20);
+
+ /* map SRAM to 0xfff00000 */
+ bh.ci->disable_window_32bit(&bh, MV64x60_CPU2SRAM_WIN);
+
+ mv64x60_set_32bit_window(&bh, MV64x60_CPU2SRAM_WIN,
+ 0xfff00000, HDPU_INTERNAL_SRAM_SIZE, 0);
+ bh.ci->enable_window_32bit(&bh, MV64x60_CPU2SRAM_WIN);
+
+ /* Enable CPU1 arbitration */
+ mv64x60_clr_bits(&bh, MV64x60_CPU_MASTER_CNTL, (1 << 9));
+
+ /*
+ * Wait 100mSecond until other CPU has reached __secondary_start.
+ * When it reaches, it is permittable to rever the SRAM mapping etc...
+ */
+ mdelay(100);
+ *(unsigned long *)KERNELBASE = nr;
+ asm volatile ("dcbf 0,%0"::"r" (KERNELBASE):"memory");
+
+ iounmap(bootaddr);
+
+ /* Set up window for internal sram (256KByte insize) */
+ bh.ci->disable_window_32bit(&bh, MV64x60_CPU2SRAM_WIN);
+ mv64x60_set_32bit_window(&bh, MV64x60_CPU2SRAM_WIN,
+ HDPU_INTERNAL_SRAM_BASE,
+ HDPU_INTERNAL_SRAM_SIZE, 0);
+ bh.ci->enable_window_32bit(&bh, MV64x60_CPU2SRAM_WIN);
+ /*
+ * Set up windows for embedded FLASH (using boot CS window).
+ */
+
+ bh.ci->disable_window_32bit(&bh, MV64x60_CPU2BOOT_WIN);
+ mv64x60_set_32bit_window(&bh, MV64x60_CPU2BOOT_WIN,
+ HDPU_EMB_FLASH_BASE, HDPU_EMB_FLASH_SIZE, 0);
+ bh.ci->enable_window_32bit(&bh, MV64x60_CPU2BOOT_WIN);
+}
+
+static void smp_hdpu_setup_cpu(int cpu_nr)
+{
+ if (cpu_nr == 0) {
+ if (ppc_md.progress)
+ ppc_md.progress("smp_hdpu_setup_cpu 0", 0);
+ mv64x60_write(&bh, MV64360_CPU0_DOORBELL_CLR, 0xff);
+ mv64x60_write(&bh, MV64360_CPU0_DOORBELL_MASK, 0xff);
+ request_irq(60, hdpu_smp_cpu0_int_handler,
+ SA_INTERRUPT, hdpu_smp0, 0);
+ }
+
+ if (cpu_nr == 1) {
+ if (ppc_md.progress)
+ ppc_md.progress("smp_hdpu_setup_cpu 1", 0);
+
+ hdpu_cpustate_set(CPUSTATE_KERNEL_MAJOR |
+ CPUSTATE_KERNEL_CPU1_OK);
+
+ /* Enable L1 Parity Bits */
+ hdpu_set_l1pe();
+
+ /* Enable L2 cache */
+ _set_L2CR(0);
+ _set_L2CR(0x80080000);
+
+ mv64x60_write(&bh, MV64360_CPU1_DOORBELL_CLR, 0x0);
+ mv64x60_write(&bh, MV64360_CPU1_DOORBELL_MASK, 0xff);
+ request_irq(28, hdpu_smp_cpu1_int_handler,
+ SA_INTERRUPT, hdpu_smp1, 0);
+ }
+
+}
+
+void __devinit hdpu_tben_give()
+{
+ volatile unsigned long *val = 0;
+
+ /* By writing 0 to the TBEN_BASE, the timebases is frozen */
+ val = ioremap(HDPU_TBEN_BASE, 4);
+ *val = 0;
+ mb();
+
+ spin_lock(&timebase_lock);
+ timebase_upper = get_tbu();
+ timebase_lower = get_tbl();
+ spin_unlock(&timebase_lock);
+
+ while (timebase_upper || timebase_lower)
+ barrier();
+
+ /* By writing 1 to the TBEN_BASE, the timebases is thawed */
+ *val = 1;
+ mb();
+
+ iounmap(val);
+
+}
+
+void __devinit hdpu_tben_take()
+{
+ while (!(timebase_upper || timebase_lower))
+ barrier();
+
+ spin_lock(&timebase_lock);
+ set_tb(timebase_upper, timebase_lower);
+ timebase_upper = 0;
+ timebase_lower = 0;
+ spin_unlock(&timebase_lock);
+}
+
+static struct smp_ops_t hdpu_smp_ops = {
+ .message_pass = smp_hdpu_message_pass,
+ .probe = smp_hdpu_probe,
+ .kick_cpu = smp_hdpu_kick_cpu,
+ .setup_cpu = smp_hdpu_setup_cpu,
+ .give_timebase = hdpu_tben_give,
+ .take_timebase = hdpu_tben_take,
+};
+#endif /* CONFIG_SMP */
+
+void __init
+platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
+ unsigned long r6, unsigned long r7)
+{
+ parse_bootinfo(r3, r4, r5, r6, r7);
+
+ isa_mem_base = 0;
+
+ ppc_md.setup_arch = hdpu_setup_arch;
+ ppc_md.init = hdpu_init2;
+ ppc_md.show_cpuinfo = hdpu_show_cpuinfo;
+ ppc_md.init_IRQ = hdpu_init_irq;
+ ppc_md.get_irq = mv64360_get_irq;
+ ppc_md.restart = hdpu_restart;
+ ppc_md.power_off = hdpu_power_off;
+ ppc_md.halt = hdpu_halt;
+ ppc_md.find_end_of_memory = hdpu_find_end_of_memory;
+ ppc_md.calibrate_decr = hdpu_calibrate_decr;
+ ppc_md.setup_io_mappings = hdpu_map_io;
+
+ bh.p_base = CONFIG_MV64X60_NEW_BASE;
+ bh.v_base = (unsigned long *)bh.p_base;
+
+ hdpu_set_bat();
+
+#if defined(CONFIG_SERIAL_TEXT_DEBUG)
+ ppc_md.progress = hdpu_mpsc_progress; /* embedded UART */
+ mv64x60_progress_init(bh.p_base);
+#endif /* CONFIG_SERIAL_TEXT_DEBUG */
+
+#ifdef CONFIG_SMP
+ ppc_md.smp_ops = &hdpu_smp_ops;
+#endif /* CONFIG_SMP */
+
+#if defined(CONFIG_SERIAL_MPSC) || defined(CONFIG_MV643XX_ETH)
+ platform_notify = hdpu_platform_notify;
+#endif
+ return;
+}
+
+#if defined(CONFIG_SERIAL_TEXT_DEBUG) && defined(CONFIG_SERIAL_MPSC_CONSOLE)
+/* SMP safe version of the serial text debug routine. Uses Semaphore 0 */
+void hdpu_mpsc_progress(char *s, unsigned short hex)
+{
+ while (mv64x60_read(&bh, MV64360_WHO_AM_I) !=
+ mv64x60_read(&bh, MV64360_SEMAPHORE_0)) {
+ }
+ mv64x60_mpsc_progress(s, hex);
+ mv64x60_write(&bh, MV64360_SEMAPHORE_0, 0xff);
+}
+#endif
+
+static void hdpu_cpustate_set(unsigned char new_state)
+{
+ unsigned int state = (new_state << 21);
+ mv64x60_write(&bh, MV64x60_GPP_VALUE_CLR, (0xff << 21));
+ mv64x60_write(&bh, MV64x60_GPP_VALUE_CLR, state);
+}
+
+#ifdef CONFIG_MTD_PHYSMAP
+static struct mtd_partition hdpu_partitions[] = {
+ {
+ .name = "Root FS",
+ .size = 0x03400000,
+ .offset = 0,
+ .mask_flags = 0,
+ },{
+ .name = "User FS",
+ .size = 0x00800000,
+ .offset = 0x03400000,
+ .mask_flags = 0,
+ },{
+ .name = "Kernel Image",
+ .size = 0x002C0000,
+ .offset = 0x03C00000,
+ .mask_flags = 0,
+ },{
+ .name = "bootEnv",
+ .size = 0x00040000,
+ .offset = 0x03EC0000,
+ .mask_flags = 0,
+ },{
+ .name = "bootROM",
+ .size = 0x00100000,
+ .offset = 0x03F00000,
+ .mask_flags = 0,
+ }
+};
+
+static int __init hdpu_setup_mtd(void)
+{
+
+ physmap_set_partitions(hdpu_partitions, 5);
+ return 0;
+}
+
+arch_initcall(hdpu_setup_mtd);
+#endif
+
+#ifdef CONFIG_HDPU_FEATURES
+
+static struct resource hdpu_cpustate_resources[] = {
+ [0] = {
+ .name = "addr base",
+ .start = MV64x60_GPP_VALUE_SET,
+ .end = MV64x60_GPP_VALUE_CLR + 1,
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+static struct resource hdpu_nexus_resources[] = {
+ [0] = {
+ .name = "nexus register",
+ .start = HDPU_NEXUS_ID_BASE,
+ .end = HDPU_NEXUS_ID_BASE + HDPU_NEXUS_ID_SIZE,
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+static struct platform_device hdpu_cpustate_device = {
+ .name = HDPU_CPUSTATE_NAME,
+ .id = 0,
+ .num_resources = ARRAY_SIZE(hdpu_cpustate_resources),
+ .resource = hdpu_cpustate_resources,
+};
+
+static struct platform_device hdpu_nexus_device = {
+ .name = HDPU_NEXUS_NAME,
+ .id = 0,
+ .num_resources = ARRAY_SIZE(hdpu_nexus_resources),
+ .resource = hdpu_nexus_resources,
+};
+
+static int __init hdpu_add_pds(void)
+{
+ platform_device_register(&hdpu_cpustate_device);
+ platform_device_register(&hdpu_nexus_device);
+ return 0;
+}
+
+arch_initcall(hdpu_add_pds);
+#endif
diff --git a/arch/ppc/platforms/hdpu.h b/arch/ppc/platforms/hdpu.h
new file mode 100644
index 0000000..07c3cff
--- /dev/null
+++ b/arch/ppc/platforms/hdpu.h
@@ -0,0 +1,82 @@
+/*
+ * arch/ppc/platforms/hdpu.h
+ *
+ * Definitions for Sky Computers HDPU board.
+ *
+ * Brian Waite <waite@skycomputers.com>
+ *
+ * Based on code done by Rabeeh Khoury - rabeeh@galileo.co.il
+ * Based on code done by Mark A. Greer <mgreer@mvista.com>
+ * Based on code done by Tim Montgomery <timm@artesyncp.com>
+ *
+ *
+ * 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.
+ */
+
+/*
+ * The MV64360 has 2 PCI buses each with 1 window from the CPU bus to
+ * PCI I/O space and 4 windows from the CPU bus to PCI MEM space.
+ * We'll only use one PCI MEM window on each PCI bus.
+ *
+ * This is the CPU physical memory map (windows must be at least 64K and start
+ * on a boundary that is a multiple of the window size):
+ *
+ * 0x80000000-0x8fffffff - PCI 0 MEM
+ * 0xa0000000-0xafffffff - PCI 1 MEM
+ * 0xc0000000-0xc0ffffff - PCI 0 I/O
+ * 0xc1000000-0xc1ffffff - PCI 1 I/O
+
+ * 0xf1000000-0xf100ffff - MV64360 Registers
+ * 0xf1010000-0xfb9fffff - HOLE
+ * 0xfbfa0000-0xfbfaffff - TBEN
+ * 0xfbf00000-0xfbfbffff - NEXUS
+ * 0xfbfc0000-0xfbffffff - Internal SRAM
+ * 0xfc000000-0xffffffff - Boot window
+ */
+
+#ifndef __PPC_PLATFORMS_HDPU_H
+#define __PPC_PLATFORMS_HDPU_H
+
+/* CPU Physical Memory Map setup. */
+#define HDPU_BRIDGE_REG_BASE 0xf1000000
+
+#define HDPU_TBEN_BASE 0xfbfa0000
+#define HDPU_TBEN_SIZE 0x00010000
+#define HDPU_NEXUS_ID_BASE 0xfbfb0000
+#define HDPU_NEXUS_ID_SIZE 0x00010000
+#define HDPU_INTERNAL_SRAM_BASE 0xfbfc0000
+#define HDPU_INTERNAL_SRAM_SIZE 0x00040000
+#define HDPU_EMB_FLASH_BASE 0xfc000000
+#define HDPU_EMB_FLASH_SIZE 0x04000000
+
+/* PCI Mappings */
+
+#define HDPU_PCI0_MEM_START_PROC_ADDR 0x80000000
+#define HDPU_PCI0_MEM_START_PCI_HI_ADDR 0x00000000
+#define HDPU_PCI0_MEM_START_PCI_LO_ADDR HDPU_PCI0_MEM_START_PROC_ADDR
+#define HDPU_PCI0_MEM_SIZE 0x10000000
+
+#define HDPU_PCI1_MEM_START_PROC_ADDR 0xc0000000
+#define HDPU_PCI1_MEM_START_PCI_HI_ADDR 0x00000000
+#define HDPU_PCI1_MEM_START_PCI_LO_ADDR HDPU_PCI1_MEM_START_PROC_ADDR
+#define HDPU_PCI1_MEM_SIZE 0x20000000
+
+#define HDPU_PCI0_IO_START_PROC_ADDR 0xc0000000
+#define HDPU_PCI0_IO_START_PCI_ADDR 0x00000000
+#define HDPU_PCI0_IO_SIZE 0x01000000
+
+#define HDPU_PCI1_IO_START_PROC_ADDR 0xc1000000
+#define HDPU_PCI1_IO_START_PCI_ADDR 0x01000000
+#define HDPU_PCI1_IO_SIZE 0x01000000
+
+#define HDPU_DEFAULT_BAUD 115200
+#define HDPU_MPSC_CLK_SRC 8 /* TCLK */
+#define HDPU_MPSC_CLK_FREQ 133000000 /* 133 Mhz */
+
+#define HDPU_PCI_0_IRQ (8+64)
+#define HDPU_PCI_1_IRQ (13+64)
+
+#endif /* __PPC_PLATFORMS_HDPU_H */
diff --git a/arch/ppc/platforms/hermes.h b/arch/ppc/platforms/hermes.h
new file mode 100644
index 0000000..198fc59
--- /dev/null
+++ b/arch/ppc/platforms/hermes.h
@@ -0,0 +1,27 @@
+/*
+ * Multidata HERMES-PRO ( / SL ) board specific definitions
+ *
+ * Copyright (c) 2000, 2001 Wolfgang Denk (wd@denx.de)
+ */
+
+#ifndef __MACH_HERMES_H
+#define __MACH_HERMES_H
+
+#include <linux/config.h>
+
+#include <asm/ppcboot.h>
+
+#define HERMES_IMMR_BASE 0xFF000000 /* phys. addr of IMMR */
+#define HERMES_IMAP_SIZE (64 * 1024) /* size of mapped area */
+
+#define IMAP_ADDR HERMES_IMMR_BASE /* physical base address of IMMR area */
+#define IMAP_SIZE HERMES_IMAP_SIZE /* mapped size of IMMR area */
+
+#define FEC_INTERRUPT 9 /* = SIU_LEVEL4 */
+#define CPM_INTERRUPT 11 /* = SIU_LEVEL5 (was: SIU_LEVEL2) */
+
+/* We don't use the 8259.
+*/
+#define NR_8259_INTS 0
+
+#endif /* __MACH_HERMES_H */
diff --git a/arch/ppc/platforms/ip860.h b/arch/ppc/platforms/ip860.h
new file mode 100644
index 0000000..8c3836c
--- /dev/null
+++ b/arch/ppc/platforms/ip860.h
@@ -0,0 +1,36 @@
+/*
+ * MicroSys IP860 VMEBus board specific definitions
+ *
+ * Copyright (c) 2000, 2001 Wolfgang Denk (wd@denx.de)
+ */
+
+#ifndef __MACH_IP860_H
+#define __MACH_IP860_H
+
+#include <linux/config.h>
+
+#include <asm/ppcboot.h>
+
+#define IP860_IMMR_BASE 0xF1000000 /* phys. addr of IMMR */
+#define IP860_IMAP_SIZE (64 * 1024) /* size of mapped area */
+
+#define IMAP_ADDR IP860_IMMR_BASE /* physical base address of IMMR area */
+#define IMAP_SIZE IP860_IMAP_SIZE /* mapped size of IMMR area */
+
+/*
+ * MPC8xx Chip Select Usage
+ */
+#define IP860_BOOT_CS 0 /* Boot (VMEBus or Flash) Chip Select 0 */
+#define IP860_FLASH_CS 1 /* Flash is on Chip Select 1 */
+#define IP860_SDRAM_CS 2 /* SDRAM is on Chip Select 2 */
+#define IP860_SRAM_CS 3 /* SRAM is on Chip Select 3 */
+#define IP860_BCSR_CS 4 /* BCSR is on Chip Select 4 */
+#define IP860_IP_CS 5 /* IP Slots are on Chip Select 5 */
+#define IP860_VME_STD_CS 6 /* VME Standard I/O is on Chip Select 6 */
+#define IP860_VME_SHORT_CS 7 /* VME Short I/O is on Chip Select 7 */
+
+/* We don't use the 8259.
+*/
+#define NR_8259_INTS 0
+
+#endif /* __MACH_IP860_H */
diff --git a/arch/ppc/platforms/ivms8.h b/arch/ppc/platforms/ivms8.h
new file mode 100644
index 0000000..d4be310
--- /dev/null
+++ b/arch/ppc/platforms/ivms8.h
@@ -0,0 +1,56 @@
+/*
+ * Speech Design Integrated Voicemail board specific definitions
+ * - IVMS8 (small, 8 channels)
+ * - IVML24 (large, 24 channels)
+ *
+ * In 2.5 when we force a new bootloader, we can merge these two, and add
+ * in _MACH_'s for them. -- Tom
+ *
+ * Copyright (c) 2000, 2001 Wolfgang Denk (wd@denx.de)
+ */
+
+#ifdef __KERNEL__
+#ifndef __ASM_IVMS8_H__
+#define __ASM_IVMS8_H__
+
+#include <linux/config.h>
+
+#include <asm/ppcboot.h>
+
+#define IVMS_IMMR_BASE 0xFFF00000 /* phys. addr of IMMR */
+#define IVMS_IMAP_SIZE (64 * 1024) /* size of mapped area */
+
+#define IMAP_ADDR IVMS_IMMR_BASE /* phys. base address of IMMR area */
+#define IMAP_SIZE IVMS_IMAP_SIZE /* mapped size of IMMR area */
+
+#define PCMCIA_MEM_ADDR ((uint)0xFE100000)
+#define PCMCIA_MEM_SIZE ((uint)(64 * 1024))
+
+#define FEC_INTERRUPT 9 /* = SIU_LEVEL4 */
+#define IDE0_INTERRUPT 10 /* = IRQ5 */
+#define CPM_INTERRUPT 11 /* = SIU_LEVEL5 (was: SIU_LEVEL2) */
+#define PHY_INTERRUPT 12 /* = IRQ6 */
+
+/* override the default number of IDE hardware interfaces */
+#define MAX_HWIFS 1
+
+/*
+ * Definitions for IDE0 Interface
+ */
+#define IDE0_BASE_OFFSET 0x0000 /* Offset in PCMCIA memory */
+#define IDE0_DATA_REG_OFFSET 0x0000
+#define IDE0_ERROR_REG_OFFSET 0x0081
+#define IDE0_NSECTOR_REG_OFFSET 0x0082
+#define IDE0_SECTOR_REG_OFFSET 0x0083
+#define IDE0_LCYL_REG_OFFSET 0x0084
+#define IDE0_HCYL_REG_OFFSET 0x0085
+#define IDE0_SELECT_REG_OFFSET 0x0086
+#define IDE0_STATUS_REG_OFFSET 0x0087
+#define IDE0_CONTROL_REG_OFFSET 0x0106
+#define IDE0_IRQ_REG_OFFSET 0x000A /* not used */
+
+/* We don't use the 8259. */
+#define NR_8259_INTS 0
+
+#endif /* __ASM_IVMS8_H__ */
+#endif /* __KERNEL__ */
diff --git a/arch/ppc/platforms/k2.c b/arch/ppc/platforms/k2.c
new file mode 100644
index 0000000..aacb438
--- /dev/null
+++ b/arch/ppc/platforms/k2.c
@@ -0,0 +1,613 @@
+/*
+ * arch/ppc/platforms/k2.c
+ *
+ * Board setup routines for SBS K2
+ *
+ * Author: Matt Porter <mporter@mvista.com>
+ *
+ * Updated by: Randy Vinson <rvinson@mvista.com.
+ *
+ * 2001-2004 (c) MontaVista, Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+
+#include <linux/config.h>
+#include <linux/stddef.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/reboot.h>
+#include <linux/pci.h>
+#include <linux/kdev_t.h>
+#include <linux/types.h>
+#include <linux/major.h>
+#include <linux/initrd.h>
+#include <linux/console.h>
+#include <linux/delay.h>
+#include <linux/ide.h>
+#include <linux/irq.h>
+#include <linux/seq_file.h>
+#include <linux/root_dev.h>
+
+#include <asm/system.h>
+#include <asm/pgtable.h>
+#include <asm/page.h>
+#include <asm/dma.h>
+#include <asm/io.h>
+#include <asm/machdep.h>
+#include <asm/time.h>
+#include <asm/i8259.h>
+#include <asm/todc.h>
+#include <asm/bootinfo.h>
+
+#include <syslib/cpc710.h>
+#include "k2.h"
+
+extern unsigned long loops_per_jiffy;
+extern void gen550_progress(char *, unsigned short);
+
+static unsigned int cpu_7xx[16] = {
+ 0, 15, 14, 0, 0, 13, 5, 9, 6, 11, 8, 10, 16, 12, 7, 0
+};
+static unsigned int cpu_6xx[16] = {
+ 0, 0, 14, 0, 0, 13, 5, 9, 6, 11, 8, 10, 0, 12, 7, 0
+};
+
+static inline int __init
+k2_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin)
+{
+ struct pci_controller *hose = pci_bus_to_hose(dev->bus->number);
+ /*
+ * Check our hose index. If we are zero then we are on the
+ * local PCI hose, otherwise we are on the cPCI hose.
+ */
+ if (!hose->index) {
+ static char pci_irq_table[][4] =
+ /*
+ * PCI IDSEL/INTPIN->INTLINE
+ * A B C D
+ */
+ {
+ {1, 0, 0, 0}, /* Ethernet */
+ {5, 5, 5, 5}, /* PMC Site 1 */
+ {6, 6, 6, 6}, /* PMC Site 2 */
+ {0, 0, 0, 0}, /* unused */
+ {0, 0, 0, 0}, /* unused */
+ {0, 0, 0, 0}, /* PCI-ISA Bridge */
+ {0, 0, 0, 0}, /* unused */
+ {0, 0, 0, 0}, /* unused */
+ {0, 0, 0, 0}, /* unused */
+ {0, 0, 0, 0}, /* unused */
+ {0, 0, 0, 0}, /* unused */
+ {0, 0, 0, 0}, /* unused */
+ {0, 0, 0, 0}, /* unused */
+ {0, 0, 0, 0}, /* unused */
+ {15, 0, 0, 0}, /* M5229 IDE */
+ };
+ const long min_idsel = 3, max_idsel = 17, irqs_per_slot = 4;
+ return PCI_IRQ_TABLE_LOOKUP;
+ } else {
+ static char pci_irq_table[][4] =
+ /*
+ * PCI IDSEL/INTPIN->INTLINE
+ * A B C D
+ */
+ {
+ {10, 11, 12, 9}, /* cPCI slot 8 */
+ {11, 12, 9, 10}, /* cPCI slot 7 */
+ {12, 9, 10, 11}, /* cPCI slot 6 */
+ {9, 10, 11, 12}, /* cPCI slot 5 */
+ {10, 11, 12, 9}, /* cPCI slot 4 */
+ {11, 12, 9, 10}, /* cPCI slot 3 */
+ {12, 9, 10, 11}, /* cPCI slot 2 */
+ };
+ const long min_idsel = 15, max_idsel = 21, irqs_per_slot = 4;
+ return PCI_IRQ_TABLE_LOOKUP;
+ }
+}
+
+void k2_pcibios_fixup(void)
+{
+#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
+ struct pci_dev *ide_dev;
+
+ /*
+ * Enable DMA support on hdc
+ */
+ ide_dev = pci_get_device(PCI_VENDOR_ID_AL,
+ PCI_DEVICE_ID_AL_M5229, NULL);
+
+ if (ide_dev) {
+
+ unsigned long ide_dma_base;
+
+ ide_dma_base = pci_resource_start(ide_dev, 4);
+ outb(0x00, ide_dma_base + 0x2);
+ outb(0x20, ide_dma_base + 0xa);
+ pci_dev_put(ide_dev);
+ }
+#endif
+}
+
+void k2_pcibios_fixup_resources(struct pci_dev *dev)
+{
+ int i;
+
+ if ((dev->vendor == PCI_VENDOR_ID_IBM) &&
+ (dev->device == PCI_DEVICE_ID_IBM_CPC710_PCI64)) {
+ pr_debug("Fixup CPC710 resources\n");
+ for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {
+ dev->resource[i].start = 0;
+ dev->resource[i].end = 0;
+ }
+ }
+}
+
+void k2_setup_hoses(void)
+{
+ struct pci_controller *hose_a, *hose_b;
+
+ /*
+ * Reconfigure CPC710 memory map so
+ * we have some more PCI memory space.
+ */
+
+ /* Set FPHB mode */
+ __raw_writel(0x808000e0, PGCHP); /* Set FPHB mode */
+
+ /* PCI32 mappings */
+ __raw_writel(0x00000000, K2_PCI32_BAR + PIBAR); /* PCI I/O base */
+ __raw_writel(0x00000000, K2_PCI32_BAR + PMBAR); /* PCI Mem base */
+ __raw_writel(0xf0000000, K2_PCI32_BAR + MSIZE); /* 256MB */
+ __raw_writel(0xfff00000, K2_PCI32_BAR + IOSIZE); /* 1MB */
+ __raw_writel(0xc0000000, K2_PCI32_BAR + SMBAR); /* Base@0xc0000000 */
+ __raw_writel(0x80000000, K2_PCI32_BAR + SIBAR); /* Base@0x80000000 */
+ __raw_writel(0x000000c0, K2_PCI32_BAR + PSSIZE); /* 1GB space */
+ __raw_writel(0x000000c0, K2_PCI32_BAR + PPSIZE); /* 1GB space */
+ __raw_writel(0x00000000, K2_PCI32_BAR + BARPS); /* Base@0x00000000 */
+ __raw_writel(0x00000000, K2_PCI32_BAR + BARPP); /* Base@0x00000000 */
+ __raw_writel(0x00000080, K2_PCI32_BAR + PSBAR); /* Base@0x80 */
+ __raw_writel(0x00000000, K2_PCI32_BAR + PPBAR);
+
+ __raw_writel(0xc0000000, K2_PCI32_BAR + BPMDLK);
+ __raw_writel(0xd0000000, K2_PCI32_BAR + TPMDLK);
+ __raw_writel(0x80000000, K2_PCI32_BAR + BIODLK);
+ __raw_writel(0x80100000, K2_PCI32_BAR + TIODLK);
+ __raw_writel(0xe0008000, K2_PCI32_BAR + DLKCTRL);
+ __raw_writel(0xffffffff, K2_PCI32_BAR + DLKDEV);
+
+ /* PCI64 mappings */
+ __raw_writel(0x00100000, K2_PCI64_BAR + PIBAR); /* PCI I/O base */
+ __raw_writel(0x10000000, K2_PCI64_BAR + PMBAR); /* PCI Mem base */
+ __raw_writel(0xf0000000, K2_PCI64_BAR + MSIZE); /* 256MB */
+ __raw_writel(0xfff00000, K2_PCI64_BAR + IOSIZE); /* 1MB */
+ __raw_writel(0xd0000000, K2_PCI64_BAR + SMBAR); /* Base@0xd0000000 */
+ __raw_writel(0x80100000, K2_PCI64_BAR + SIBAR); /* Base@0x80100000 */
+ __raw_writel(0x000000c0, K2_PCI64_BAR + PSSIZE); /* 1GB space */
+ __raw_writel(0x000000c0, K2_PCI64_BAR + PPSIZE); /* 1GB space */
+ __raw_writel(0x00000000, K2_PCI64_BAR + BARPS); /* Base@0x00000000 */
+ __raw_writel(0x00000000, K2_PCI64_BAR + BARPP); /* Base@0x00000000 */
+
+ /* Setup PCI32 hose */
+ hose_a = pcibios_alloc_controller();
+ if (!hose_a)
+ return;
+
+ hose_a->first_busno = 0;
+ hose_a->last_busno = 0xff;
+ hose_a->pci_mem_offset = K2_PCI32_MEM_BASE;
+
+ pci_init_resource(&hose_a->io_resource,
+ K2_PCI32_LOWER_IO,
+ K2_PCI32_UPPER_IO,
+ IORESOURCE_IO, "PCI32 host bridge");
+
+ pci_init_resource(&hose_a->mem_resources[0],
+ K2_PCI32_LOWER_MEM + K2_PCI32_MEM_BASE,
+ K2_PCI32_UPPER_MEM + K2_PCI32_MEM_BASE,
+ IORESOURCE_MEM, "PCI32 host bridge");
+
+ hose_a->io_space.start = K2_PCI32_LOWER_IO;
+ hose_a->io_space.end = K2_PCI32_UPPER_IO;
+ hose_a->mem_space.start = K2_PCI32_LOWER_MEM;
+ hose_a->mem_space.end = K2_PCI32_UPPER_MEM;
+ hose_a->io_base_virt = (void *)K2_ISA_IO_BASE;
+
+ setup_indirect_pci(hose_a, K2_PCI32_CONFIG_ADDR, K2_PCI32_CONFIG_DATA);
+
+ /* Initialize PCI32 bus registers */
+ early_write_config_byte(hose_a,
+ hose_a->first_busno,
+ PCI_DEVFN(0, 0),
+ CPC710_BUS_NUMBER, hose_a->first_busno);
+
+ early_write_config_byte(hose_a,
+ hose_a->first_busno,
+ PCI_DEVFN(0, 0),
+ CPC710_SUB_BUS_NUMBER, hose_a->last_busno);
+
+ /* Enable PCI interrupt polling */
+ early_write_config_byte(hose_a,
+ hose_a->first_busno,
+ PCI_DEVFN(8, 0), 0x45, 0x80);
+
+ /* Route polled PCI interrupts */
+ early_write_config_byte(hose_a,
+ hose_a->first_busno,
+ PCI_DEVFN(8, 0), 0x48, 0x58);
+
+ early_write_config_byte(hose_a,
+ hose_a->first_busno,
+ PCI_DEVFN(8, 0), 0x49, 0x07);
+
+ early_write_config_byte(hose_a,
+ hose_a->first_busno,
+ PCI_DEVFN(8, 0), 0x4a, 0x31);
+
+ early_write_config_byte(hose_a,
+ hose_a->first_busno,
+ PCI_DEVFN(8, 0), 0x4b, 0xb9);
+
+ /* route secondary IDE channel interrupt to IRQ 15 */
+ early_write_config_byte(hose_a,
+ hose_a->first_busno,
+ PCI_DEVFN(8, 0), 0x75, 0x0f);
+
+ /* enable IDE controller IDSEL */
+ early_write_config_byte(hose_a,
+ hose_a->first_busno,
+ PCI_DEVFN(8, 0), 0x58, 0x48);
+
+ /* Enable IDE function */
+ early_write_config_byte(hose_a,
+ hose_a->first_busno,
+ PCI_DEVFN(17, 0), 0x50, 0x03);
+
+ /* Set M5229 IDE controller to native mode */
+ early_write_config_byte(hose_a,
+ hose_a->first_busno,
+ PCI_DEVFN(17, 0), PCI_CLASS_PROG, 0xdf);
+
+ hose_a->last_busno = pciauto_bus_scan(hose_a, hose_a->first_busno);
+
+ /* Write out correct max subordinate bus number for hose A */
+ early_write_config_byte(hose_a,
+ hose_a->first_busno,
+ PCI_DEVFN(0, 0),
+ CPC710_SUB_BUS_NUMBER, hose_a->last_busno);
+
+ /* Only setup PCI64 hose if we are in the system slot */
+ if (!(readb(K2_MISC_REG) & K2_SYS_SLOT_MASK)) {
+ /* Setup PCI64 hose */
+ hose_b = pcibios_alloc_controller();
+ if (!hose_b)
+ return;
+
+ hose_b->first_busno = hose_a->last_busno + 1;
+ hose_b->last_busno = 0xff;
+
+ /* Reminder: quit changing the following, it is correct. */
+ hose_b->pci_mem_offset = K2_PCI32_MEM_BASE;
+
+ pci_init_resource(&hose_b->io_resource,
+ K2_PCI64_LOWER_IO,
+ K2_PCI64_UPPER_IO,
+ IORESOURCE_IO, "PCI64 host bridge");
+
+ pci_init_resource(&hose_b->mem_resources[0],
+ K2_PCI64_LOWER_MEM + K2_PCI32_MEM_BASE,
+ K2_PCI64_UPPER_MEM + K2_PCI32_MEM_BASE,
+ IORESOURCE_MEM, "PCI64 host bridge");
+
+ hose_b->io_space.start = K2_PCI64_LOWER_IO;
+ hose_b->io_space.end = K2_PCI64_UPPER_IO;
+ hose_b->mem_space.start = K2_PCI64_LOWER_MEM;
+ hose_b->mem_space.end = K2_PCI64_UPPER_MEM;
+ hose_b->io_base_virt = (void *)K2_ISA_IO_BASE;
+
+ setup_indirect_pci(hose_b,
+ K2_PCI64_CONFIG_ADDR, K2_PCI64_CONFIG_DATA);
+
+ /* Initialize PCI64 bus registers */
+ early_write_config_byte(hose_b,
+ 0,
+ PCI_DEVFN(0, 0),
+ CPC710_SUB_BUS_NUMBER, 0xff);
+
+ early_write_config_byte(hose_b,
+ 0,
+ PCI_DEVFN(0, 0),
+ CPC710_BUS_NUMBER, hose_b->first_busno);
+
+ hose_b->last_busno = pciauto_bus_scan(hose_b,
+ hose_b->first_busno);
+
+ /* Write out correct max subordinate bus number for hose B */
+ early_write_config_byte(hose_b,
+ hose_b->first_busno,
+ PCI_DEVFN(0, 0),
+ CPC710_SUB_BUS_NUMBER,
+ hose_b->last_busno);
+
+ /* Configure PCI64 PSBAR */
+ early_write_config_dword(hose_b,
+ hose_b->first_busno,
+ PCI_DEVFN(0, 0),
+ PCI_BASE_ADDRESS_0,
+ K2_PCI64_SYS_MEM_BASE);
+ }
+
+ /* Configure i8259 level/edge settings */
+ outb(0x62, 0x4d0);
+ outb(0xde, 0x4d1);
+
+#ifdef CONFIG_CPC710_DATA_GATHERING
+ {
+ unsigned int tmp;
+ tmp = __raw_readl(ABCNTL);
+ /* Enable data gathering on both PCI interfaces */
+ __raw_writel(tmp | 0x05000000, ABCNTL);
+ }
+#endif
+
+ ppc_md.pcibios_fixup = k2_pcibios_fixup;
+ ppc_md.pcibios_fixup_resources = k2_pcibios_fixup_resources;
+ ppc_md.pci_swizzle = common_swizzle;
+ ppc_md.pci_map_irq = k2_map_irq;
+}
+
+static int k2_get_bus_speed(void)
+{
+ int bus_speed;
+ unsigned char board_id;
+
+ board_id = *(unsigned char *)K2_BOARD_ID_REG;
+
+ switch (K2_BUS_SPD(board_id)) {
+
+ case 0:
+ default:
+ bus_speed = 100000000;
+ break;
+
+ case 1:
+ bus_speed = 83333333;
+ break;
+
+ case 2:
+ bus_speed = 75000000;
+ break;
+
+ case 3:
+ bus_speed = 66666666;
+ break;
+ }
+ return bus_speed;
+}
+
+static int k2_get_cpu_speed(void)
+{
+ unsigned long hid1;
+ int cpu_speed;
+
+ hid1 = mfspr(SPRN_HID1) >> 28;
+
+ if ((mfspr(SPRN_PVR) >> 16) == 8)
+ hid1 = cpu_7xx[hid1];
+ else
+ hid1 = cpu_6xx[hid1];
+
+ cpu_speed = k2_get_bus_speed() * hid1 / 2;
+ return cpu_speed;
+}
+
+static void __init k2_calibrate_decr(void)
+{
+ int freq, divisor = 4;
+
+ /* determine processor bus speed */
+ freq = k2_get_bus_speed();
+ tb_ticks_per_jiffy = freq / HZ / divisor;
+ tb_to_us = mulhwu_scale_factor(freq / divisor, 1000000);
+}
+
+static int k2_show_cpuinfo(struct seq_file *m)
+{
+ unsigned char k2_geo_bits, k2_system_slot;
+
+ seq_printf(m, "vendor\t\t: SBS\n");
+ seq_printf(m, "machine\t\t: K2\n");
+ seq_printf(m, "cpu speed\t: %dMhz\n", k2_get_cpu_speed() / 1000000);
+ seq_printf(m, "bus speed\t: %dMhz\n", k2_get_bus_speed() / 1000000);
+ seq_printf(m, "memory type\t: SDRAM\n");
+
+ k2_geo_bits = readb(K2_MSIZ_GEO_REG) & K2_GEO_ADR_MASK;
+ k2_system_slot = !(readb(K2_MISC_REG) & K2_SYS_SLOT_MASK);
+ seq_printf(m, "backplane\t: %s slot board",
+ k2_system_slot ? "System" : "Non system");
+ seq_printf(m, "with geographical address %x\n", k2_geo_bits);
+
+ return 0;
+}
+
+TODC_ALLOC();
+
+static void __init k2_setup_arch(void)
+{
+ unsigned int cpu;
+
+ /* Setup TODC access */
+ TODC_INIT(TODC_TYPE_MK48T37, 0, 0,
+ ioremap(K2_RTC_BASE_ADDRESS, K2_RTC_SIZE), 8);
+
+ /* init to some ~sane value until calibrate_delay() runs */
+ loops_per_jiffy = 50000000 / HZ;
+
+ /* make FLASH transactions higher priority than PCI to avoid deadlock */
+ __raw_writel(__raw_readl(SIOC1) | 0x80000000, SIOC1);
+
+ /* Set hardware to access FLASH page 2 */
+ __raw_writel(1 << 29, GPOUT);
+
+ /* Setup PCI host bridges */
+ k2_setup_hoses();
+
+#ifdef CONFIG_BLK_DEV_INITRD
+ if (initrd_start)
+ ROOT_DEV = Root_RAM0;
+ else
+#endif
+#ifdef CONFIG_ROOT_NFS
+ ROOT_DEV = Root_NFS;
+#else
+ ROOT_DEV = Root_HDC1;
+#endif
+
+ /* Identify the system */
+ printk(KERN_INFO "System Identification: SBS K2 - PowerPC 750 @ "
+ "%d Mhz\n", k2_get_cpu_speed() / 1000000);
+ printk(KERN_INFO "Port by MontaVista Software, Inc. "
+ "(source@mvista.com)\n");
+
+ /* Identify the CPU manufacturer */
+ cpu = PVR_REV(mfspr(SPRN_PVR));
+ printk(KERN_INFO "CPU manufacturer: %s [rev=%04x]\n",
+ (cpu & (1 << 15)) ? "IBM" : "Motorola", cpu);
+}
+
+static void k2_restart(char *cmd)
+{
+ local_irq_disable();
+
+ /* Flip FLASH back to page 1 to access firmware image */
+ __raw_writel(0, GPOUT);
+
+ /* SRR0 has system reset vector, SRR1 has default MSR value */
+ /* rfi restores MSR from SRR1 and sets the PC to the SRR0 value */
+ mtspr(SPRN_SRR0, 0xfff00100);
+ mtspr(SPRN_SRR1, 0);
+ __asm__ __volatile__("rfi\n\t");
+
+ /* not reached */
+ for (;;) ;
+}
+
+static void k2_power_off(void)
+{
+ for (;;) ;
+}
+
+static void k2_halt(void)
+{
+ k2_restart(NULL);
+}
+
+/*
+ * Set BAT 3 to map PCI32 I/O space.
+ */
+static __inline__ void k2_set_bat(void)
+{
+ /* wait for all outstanding memory accesses to complete */
+ mb();
+
+ /* setup DBATs */
+ mtspr(SPRN_DBAT2U, 0x80001ffe);
+ mtspr(SPRN_DBAT2L, 0x8000002a);
+ mtspr(SPRN_DBAT3U, 0xf0001ffe);
+ mtspr(SPRN_DBAT3L, 0xf000002a);
+
+ /* wait for updates */
+ mb();
+}
+
+static unsigned long __init k2_find_end_of_memory(void)
+{
+ unsigned long total;
+ unsigned char msize = 7; /* Default to 128MB */
+
+ msize = K2_MEM_SIZE(readb(K2_MSIZ_GEO_REG));
+
+ switch (msize) {
+ case 2:
+ /*
+ * This will break without a lowered
+ * KERNELBASE or CONFIG_HIGHMEM on.
+ * It seems non 1GB builds exist yet,
+ * though.
+ */
+ total = K2_MEM_SIZE_1GB;
+ break;
+ case 3:
+ case 4:
+ total = K2_MEM_SIZE_512MB;
+ break;
+ case 5:
+ case 6:
+ total = K2_MEM_SIZE_256MB;
+ break;
+ case 7:
+ total = K2_MEM_SIZE_128MB;
+ break;
+ default:
+ printk
+ ("K2: Invalid memory size detected, defaulting to 128MB\n");
+ total = K2_MEM_SIZE_128MB;
+ break;
+ }
+ return total;
+}
+
+static void __init k2_map_io(void)
+{
+ io_block_mapping(K2_PCI32_IO_BASE,
+ K2_PCI32_IO_BASE, 0x00200000, _PAGE_IO);
+ io_block_mapping(0xff000000, 0xff000000, 0x01000000, _PAGE_IO);
+}
+
+static void __init k2_init_irq(void)
+{
+ int i;
+
+ for (i = 0; i < 16; i++)
+ irq_desc[i].handler = &i8259_pic;
+
+ i8259_init(0);
+}
+
+void __init platform_init(unsigned long r3, unsigned long r4,
+ unsigned long r5, unsigned long r6, unsigned long r7)
+{
+ parse_bootinfo((struct bi_record *)(r3 + KERNELBASE));
+
+ k2_set_bat();
+
+ isa_io_base = K2_ISA_IO_BASE;
+ isa_mem_base = K2_ISA_MEM_BASE;
+ pci_dram_offset = K2_PCI32_SYS_MEM_BASE;
+
+ ppc_md.setup_arch = k2_setup_arch;
+ ppc_md.show_cpuinfo = k2_show_cpuinfo;
+ ppc_md.init_IRQ = k2_init_irq;
+ ppc_md.get_irq = i8259_irq;
+
+ ppc_md.find_end_of_memory = k2_find_end_of_memory;
+ ppc_md.setup_io_mappings = k2_map_io;
+
+ ppc_md.restart = k2_restart;
+ ppc_md.power_off = k2_power_off;
+ ppc_md.halt = k2_halt;
+
+ ppc_md.time_init = todc_time_init;
+ ppc_md.set_rtc_time = todc_set_rtc_time;
+ ppc_md.get_rtc_time = todc_get_rtc_time;
+ ppc_md.calibrate_decr = k2_calibrate_decr;
+
+ ppc_md.nvram_read_val = todc_direct_read_val;
+ ppc_md.nvram_write_val = todc_direct_write_val;
+
+#ifdef CONFIG_SERIAL_TEXT_DEBUG
+ ppc_md.progress = gen550_progress;
+#endif
+}
diff --git a/arch/ppc/platforms/k2.h b/arch/ppc/platforms/k2.h
new file mode 100644
index 0000000..78326ab
--- /dev/null
+++ b/arch/ppc/platforms/k2.h
@@ -0,0 +1,82 @@
+/*
+ * arch/ppc/platforms/k2.h
+ *
+ * Definitions for SBS K2 board support
+ *
+ * Author: Matt Porter <mporter@mvista.com>
+ *
+ * 2001 (c) MontaVista, Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+
+#ifndef __PPC_PLATFORMS_K2_H
+#define __PPC_PLATFORMS_K2_H
+
+/*
+ * SBS K2 definitions
+ */
+
+#define K2_PCI64_BAR 0xff400000
+#define K2_PCI32_BAR 0xff500000
+
+#define K2_PCI64_CONFIG_ADDR (K2_PCI64_BAR + 0x000f8000)
+#define K2_PCI64_CONFIG_DATA (K2_PCI64_BAR + 0x000f8010)
+
+#define K2_PCI32_CONFIG_ADDR (K2_PCI32_BAR + 0x000f8000)
+#define K2_PCI32_CONFIG_DATA (K2_PCI32_BAR + 0x000f8010)
+
+#define K2_PCI64_MEM_BASE 0xd0000000
+#define K2_PCI64_IO_BASE 0x80100000
+
+#define K2_PCI32_MEM_BASE 0xc0000000
+#define K2_PCI32_IO_BASE 0x80000000
+
+#define K2_PCI32_SYS_MEM_BASE 0x80000000
+#define K2_PCI64_SYS_MEM_BASE K2_PCI32_SYS_MEM_BASE
+
+#define K2_PCI32_LOWER_MEM 0x00000000
+#define K2_PCI32_UPPER_MEM 0x0fffffff
+#define K2_PCI32_LOWER_IO 0x00000000
+#define K2_PCI32_UPPER_IO 0x000fffff
+
+#define K2_PCI64_LOWER_MEM 0x10000000
+#define K2_PCI64_UPPER_MEM 0x1fffffff
+#define K2_PCI64_LOWER_IO 0x00100000
+#define K2_PCI64_UPPER_IO 0x001fffff
+
+#define K2_ISA_IO_BASE K2_PCI32_IO_BASE
+#define K2_ISA_MEM_BASE K2_PCI32_MEM_BASE
+
+#define K2_BOARD_ID_REG (K2_ISA_IO_BASE + 0x800)
+#define K2_MISC_REG (K2_ISA_IO_BASE + 0x804)
+#define K2_MSIZ_GEO_REG (K2_ISA_IO_BASE + 0x808)
+#define K2_HOT_SWAP_REG (K2_ISA_IO_BASE + 0x80c)
+#define K2_PLD2_REG (K2_ISA_IO_BASE + 0x80e)
+#define K2_PLD3_REG (K2_ISA_IO_BASE + 0x80f)
+
+#define K2_BUS_SPD(board_id) (board_id >> 2) & 3
+
+#define K2_RTC_BASE_OFFSET 0x90000
+#define K2_RTC_BASE_ADDRESS (K2_PCI32_MEM_BASE + K2_RTC_BASE_OFFSET)
+#define K2_RTC_SIZE 0x8000
+
+#define K2_MEM_SIZE_MASK 0xe0
+#define K2_MEM_SIZE(size_reg) (size_reg & K2_MEM_SIZE_MASK) >> 5
+#define K2_MEM_SIZE_1GB 0x40000000
+#define K2_MEM_SIZE_512MB 0x20000000
+#define K2_MEM_SIZE_256MB 0x10000000
+#define K2_MEM_SIZE_128MB 0x08000000
+
+#define K2_L2CACHE_MASK 0x03 /* Mask for 2 L2 Cache bits */
+#define K2_L2CACHE_512KB 0x00 /* 512KB */
+#define K2_L2CACHE_256KB 0x01 /* 256KB */
+#define K2_L2CACHE_1MB 0x02 /* 1MB */
+#define K2_L2CACHE_NONE 0x03 /* None */
+
+#define K2_GEO_ADR_MASK 0x1f
+
+#define K2_SYS_SLOT_MASK 0x08
+
+#endif /* __PPC_PLATFORMS_K2_H */
diff --git a/arch/ppc/platforms/katana.c b/arch/ppc/platforms/katana.c
new file mode 100644
index 0000000..eda922a
--- /dev/null
+++ b/arch/ppc/platforms/katana.c
@@ -0,0 +1,795 @@
+/*
+ * arch/ppc/platforms/katana.c
+ *
+ * Board setup routines for the Artesyn Katana cPCI boards.
+ *
+ * Author: Tim Montgomery <timm@artesyncp.com>
+ * Maintained by: Mark A. Greer <mgreer@mvista.com>
+ *
+ * Based on code done by Rabeeh Khoury - rabeeh@galileo.co.il
+ * Based on code done by - Mark A. Greer <mgreer@mvista.com>
+ *
+ * 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.
+ */
+/*
+ * Supports the Artesyn 750i, 752i, and 3750. The 752i is virtually identical
+ * to the 750i except that it has an mv64460 bridge.
+ */
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/kdev_t.h>
+#include <linux/console.h>
+#include <linux/initrd.h>
+#include <linux/root_dev.h>
+#include <linux/delay.h>
+#include <linux/seq_file.h>
+#include <linux/bootmem.h>
+#include <linux/mtd/physmap.h>
+#include <linux/mv643xx.h>
+#ifdef CONFIG_BOOTIMG
+#include <linux/bootimg.h>
+#endif
+#include <asm/page.h>
+#include <asm/time.h>
+#include <asm/smp.h>
+#include <asm/todc.h>
+#include <asm/bootinfo.h>
+#include <asm/ppcboot.h>
+#include <asm/mv64x60.h>
+#include <platforms/katana.h>
+
+static struct mv64x60_handle bh;
+static katana_id_t katana_id;
+static void __iomem *cpld_base;
+static void __iomem *sram_base;
+
+static u32 katana_flash_size_0;
+static u32 katana_flash_size_1;
+
+static u32 katana_bus_frequency;
+
+unsigned char __res[sizeof(bd_t)];
+
+/* PCI Interrupt routing */
+static int __init
+katana_irq_lookup_750i(unsigned char idsel, unsigned char pin)
+{
+ static char pci_irq_table[][4] = {
+ /*
+ * PCI IDSEL/INTPIN->INTLINE
+ * A B C D
+ */
+ /* IDSEL 4 (PMC 1) */
+ { KATANA_PCI_INTB_IRQ_750i, KATANA_PCI_INTC_IRQ_750i,
+ KATANA_PCI_INTD_IRQ_750i, KATANA_PCI_INTA_IRQ_750i },
+ /* IDSEL 5 (PMC 2) */
+ { KATANA_PCI_INTC_IRQ_750i, KATANA_PCI_INTD_IRQ_750i,
+ KATANA_PCI_INTA_IRQ_750i, KATANA_PCI_INTB_IRQ_750i },
+ /* IDSEL 6 (T8110) */
+ {KATANA_PCI_INTD_IRQ_750i, 0, 0, 0 },
+ };
+ const long min_idsel = 4, max_idsel = 6, irqs_per_slot = 4;
+
+ return PCI_IRQ_TABLE_LOOKUP;
+}
+
+static int __init
+katana_irq_lookup_3750(unsigned char idsel, unsigned char pin)
+{
+ static char pci_irq_table[][4] = {
+ /*
+ * PCI IDSEL/INTPIN->INTLINE
+ * A B C D
+ */
+ { KATANA_PCI_INTA_IRQ_3750, 0, 0, 0 }, /* IDSEL 3 (BCM5691) */
+ { KATANA_PCI_INTB_IRQ_3750, 0, 0, 0 }, /* IDSEL 4 (MV64360 #2)*/
+ { KATANA_PCI_INTC_IRQ_3750, 0, 0, 0 }, /* IDSEL 5 (MV64360 #3)*/
+ };
+ const long min_idsel = 3, max_idsel = 5, irqs_per_slot = 4;
+
+ return PCI_IRQ_TABLE_LOOKUP;
+}
+
+static int __init
+katana_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin)
+{
+ switch (katana_id) {
+ case KATANA_ID_750I:
+ case KATANA_ID_752I:
+ return katana_irq_lookup_750i(idsel, pin);
+
+ case KATANA_ID_3750:
+ return katana_irq_lookup_3750(idsel, pin);
+
+ default:
+ printk(KERN_ERR "Bogus board ID\n");
+ return 0;
+ }
+}
+
+/* Board info retrieval routines */
+void __init
+katana_get_board_id(void)
+{
+ switch (in_8(cpld_base + KATANA_CPLD_PRODUCT_ID)) {
+ case KATANA_PRODUCT_ID_3750:
+ katana_id = KATANA_ID_3750;
+ break;
+
+ case KATANA_PRODUCT_ID_750i:
+ katana_id = KATANA_ID_750I;
+ break;
+
+ case KATANA_PRODUCT_ID_752i:
+ katana_id = KATANA_ID_752I;
+ break;
+
+ default:
+ printk(KERN_ERR "Unsupported board\n");
+ }
+}
+
+int __init
+katana_get_proc_num(void)
+{
+ u16 val;
+ u8 save_exclude;
+ static int proc = -1;
+ static u8 first_time = 1;
+
+ if (first_time) {
+ if (katana_id != KATANA_ID_3750)
+ proc = 0;
+ else {
+ save_exclude = mv64x60_pci_exclude_bridge;
+ mv64x60_pci_exclude_bridge = 0;
+
+ early_read_config_word(bh.hose_a, 0,
+ PCI_DEVFN(0,0), PCI_DEVICE_ID, &val);
+
+ mv64x60_pci_exclude_bridge = save_exclude;
+
+ switch(val) {
+ case PCI_DEVICE_ID_KATANA_3750_PROC0:
+ proc = 0;
+ break;
+
+ case PCI_DEVICE_ID_KATANA_3750_PROC1:
+ proc = 1;
+ break;
+
+ case PCI_DEVICE_ID_KATANA_3750_PROC2:
+ proc = 2;
+ break;
+
+ default:
+ printk(KERN_ERR "Bogus Device ID\n");
+ }
+ }
+
+ first_time = 0;
+ }
+
+ return proc;
+}
+
+static inline int
+katana_is_monarch(void)
+{
+ return in_8(cpld_base + KATANA_CPLD_BD_CFG_3) &
+ KATANA_CPLD_BD_CFG_3_MONARCH;
+}
+
+static void __init
+katana_setup_bridge(void)
+{
+ struct pci_controller hose;
+ struct mv64x60_setup_info si;
+ void __iomem *vaddr;
+ int i;
+ u16 val;
+ u8 save_exclude;
+
+ /*
+ * Some versions of the Katana firmware mistakenly change the vendor
+ * & device id fields in the bridge's pci device (visible via pci
+ * config accesses). This breaks mv64x60_init() because those values
+ * are used to identify the type of bridge that's there. Artesyn
+ * claims that the subsystem vendor/device id's will have the correct
+ * Marvell values so this code puts back the correct values from there.
+ */
+ memset(&hose, 0, sizeof(hose));
+ vaddr = ioremap(CONFIG_MV64X60_NEW_BASE, MV64x60_INTERNAL_SPACE_SIZE);
+ setup_indirect_pci_nomap(&hose, vaddr + MV64x60_PCI0_CONFIG_ADDR,
+ vaddr + MV64x60_PCI0_CONFIG_DATA);
+ save_exclude = mv64x60_pci_exclude_bridge;
+ mv64x60_pci_exclude_bridge = 0;
+
+ early_read_config_word(&hose, 0, PCI_DEVFN(0, 0), PCI_VENDOR_ID, &val);
+
+ if (val != PCI_VENDOR_ID_MARVELL) {
+ early_read_config_word(&hose, 0, PCI_DEVFN(0, 0),
+ PCI_SUBSYSTEM_VENDOR_ID, &val);
+ early_write_config_word(&hose, 0, PCI_DEVFN(0, 0),
+ PCI_VENDOR_ID, val);
+ early_read_config_word(&hose, 0, PCI_DEVFN(0, 0),
+ PCI_SUBSYSTEM_ID, &val);
+ early_write_config_word(&hose, 0, PCI_DEVFN(0, 0),
+ PCI_DEVICE_ID, val);
+ }
+
+ mv64x60_pci_exclude_bridge = save_exclude;
+ iounmap(vaddr);
+
+ memset(&si, 0, sizeof(si));
+
+ si.phys_reg_base = CONFIG_MV64X60_NEW_BASE;
+
+ si.pci_1.enable_bus = 1;
+ si.pci_1.pci_io.cpu_base = KATANA_PCI1_IO_START_PROC_ADDR;
+ si.pci_1.pci_io.pci_base_hi = 0;
+ si.pci_1.pci_io.pci_base_lo = KATANA_PCI1_IO_START_PCI_ADDR;
+ si.pci_1.pci_io.size = KATANA_PCI1_IO_SIZE;
+ si.pci_1.pci_io.swap = MV64x60_CPU2PCI_SWAP_NONE;
+ si.pci_1.pci_mem[0].cpu_base = KATANA_PCI1_MEM_START_PROC_ADDR;
+ si.pci_1.pci_mem[0].pci_base_hi = KATANA_PCI1_MEM_START_PCI_HI_ADDR;
+ si.pci_1.pci_mem[0].pci_base_lo = KATANA_PCI1_MEM_START_PCI_LO_ADDR;
+ si.pci_1.pci_mem[0].size = KATANA_PCI1_MEM_SIZE;
+ si.pci_1.pci_mem[0].swap = MV64x60_CPU2PCI_SWAP_NONE;
+ si.pci_1.pci_cmd_bits = 0;
+ si.pci_1.latency_timer = 0x80;
+
+ for (i = 0; i < MV64x60_CPU2MEM_WINDOWS; i++) {
+#if defined(CONFIG_NOT_COHERENT_CACHE)
+ si.cpu_prot_options[i] = 0;
+ si.enet_options[i] = MV64360_ENET2MEM_SNOOP_NONE;
+ si.mpsc_options[i] = MV64360_MPSC2MEM_SNOOP_NONE;
+ si.idma_options[i] = MV64360_IDMA2MEM_SNOOP_NONE;
+
+ si.pci_1.acc_cntl_options[i] =
+ MV64360_PCI_ACC_CNTL_SNOOP_NONE |
+ MV64360_PCI_ACC_CNTL_SWAP_NONE |
+ MV64360_PCI_ACC_CNTL_MBURST_128_BYTES |
+ MV64360_PCI_ACC_CNTL_RDSIZE_256_BYTES;
+#else
+ si.cpu_prot_options[i] = 0;
+ si.enet_options[i] = MV64360_ENET2MEM_SNOOP_NONE; /* errata */
+ si.mpsc_options[i] = MV64360_MPSC2MEM_SNOOP_NONE; /* errata */
+ si.idma_options[i] = MV64360_IDMA2MEM_SNOOP_NONE; /* errata */
+
+ si.pci_1.acc_cntl_options[i] =
+ MV64360_PCI_ACC_CNTL_SNOOP_WB |
+ MV64360_PCI_ACC_CNTL_SWAP_NONE |
+ MV64360_PCI_ACC_CNTL_MBURST_32_BYTES |
+ MV64360_PCI_ACC_CNTL_RDSIZE_32_BYTES;
+#endif
+ }
+
+ /* Lookup PCI host bridges */
+ if (mv64x60_init(&bh, &si))
+ printk(KERN_WARNING "Bridge initialization failed.\n");
+
+ pci_dram_offset = 0; /* sys mem at same addr on PCI & cpu bus */
+ ppc_md.pci_swizzle = common_swizzle;
+ ppc_md.pci_map_irq = katana_map_irq;
+ ppc_md.pci_exclude_device = mv64x60_pci_exclude_device;
+
+ mv64x60_set_bus(&bh, 1, 0);
+ bh.hose_b->first_busno = 0;
+ bh.hose_b->last_busno = 0xff;
+}
+
+/* Bridge & platform setup routines */
+void __init
+katana_intr_setup(void)
+{
+ /* MPP 8, 9, and 10 */
+ mv64x60_clr_bits(&bh, MV64x60_MPP_CNTL_1, 0xfff);
+
+ /* MPP 14 */
+ if ((katana_id == KATANA_ID_750I) || (katana_id == KATANA_ID_752I))
+ mv64x60_clr_bits(&bh, MV64x60_MPP_CNTL_1, 0x0f000000);
+
+ /*
+ * Define GPP 8,9,and 10 interrupt polarity as active low
+ * input signal and level triggered
+ */
+ mv64x60_set_bits(&bh, MV64x60_GPP_LEVEL_CNTL, 0x700);
+ mv64x60_clr_bits(&bh, MV64x60_GPP_IO_CNTL, 0x700);
+
+ if ((katana_id == KATANA_ID_750I) || (katana_id == KATANA_ID_752I)) {
+ mv64x60_set_bits(&bh, MV64x60_GPP_LEVEL_CNTL, (1<<14));
+ mv64x60_clr_bits(&bh, MV64x60_GPP_IO_CNTL, (1<<14));
+ }
+
+ /* Config GPP intr ctlr to respond to level trigger */
+ mv64x60_set_bits(&bh, MV64x60_COMM_ARBITER_CNTL, (1<<10));
+
+ /* Erranum FEr PCI-#8 */
+ mv64x60_clr_bits(&bh, MV64x60_PCI0_CMD, (1<<5) | (1<<9));
+ mv64x60_clr_bits(&bh, MV64x60_PCI1_CMD, (1<<5) | (1<<9));
+
+ /*
+ * Dismiss and then enable interrupt on GPP interrupt cause
+ * for CPU #0
+ */
+ mv64x60_write(&bh, MV64x60_GPP_INTR_CAUSE, ~0x700);
+ mv64x60_set_bits(&bh, MV64x60_GPP_INTR_MASK, 0x700);
+
+ if ((katana_id == KATANA_ID_750I) || (katana_id == KATANA_ID_752I)) {
+ mv64x60_write(&bh, MV64x60_GPP_INTR_CAUSE, ~(1<<14));
+ mv64x60_set_bits(&bh, MV64x60_GPP_INTR_MASK, (1<<14));
+ }
+
+ /*
+ * Dismiss and then enable interrupt on CPU #0 high cause reg
+ * BIT25 summarizes GPP interrupts 8-15
+ */
+ mv64x60_set_bits(&bh, MV64360_IC_CPU0_INTR_MASK_HI, (1<<25));
+}
+
+void __init
+katana_setup_peripherals(void)
+{
+ u32 base;
+
+ /* Set up windows for boot CS, soldered & socketed flash, and CPLD */
+ mv64x60_set_32bit_window(&bh, MV64x60_CPU2BOOT_WIN,
+ KATANA_BOOT_WINDOW_BASE, KATANA_BOOT_WINDOW_SIZE, 0);
+ bh.ci->enable_window_32bit(&bh, MV64x60_CPU2BOOT_WIN);
+
+ /* Assume firmware set up window sizes correctly for dev 0 & 1 */
+ mv64x60_get_32bit_window(&bh, MV64x60_CPU2DEV_0_WIN, &base,
+ &katana_flash_size_0);
+
+ if (katana_flash_size_0 > 0) {
+ mv64x60_set_32bit_window(&bh, MV64x60_CPU2DEV_0_WIN,
+ KATANA_SOLDERED_FLASH_BASE, katana_flash_size_0, 0);
+ bh.ci->enable_window_32bit(&bh, MV64x60_CPU2DEV_0_WIN);
+ }
+
+ mv64x60_get_32bit_window(&bh, MV64x60_CPU2DEV_1_WIN, &base,
+ &katana_flash_size_1);
+
+ if (katana_flash_size_1 > 0) {
+ mv64x60_set_32bit_window(&bh, MV64x60_CPU2DEV_1_WIN,
+ (KATANA_SOLDERED_FLASH_BASE + katana_flash_size_0),
+ katana_flash_size_1, 0);
+ bh.ci->enable_window_32bit(&bh, MV64x60_CPU2DEV_1_WIN);
+ }
+
+ mv64x60_set_32bit_window(&bh, MV64x60_CPU2DEV_2_WIN,
+ KATANA_SOCKET_BASE, KATANA_SOCKETED_FLASH_SIZE, 0);
+ bh.ci->enable_window_32bit(&bh, MV64x60_CPU2DEV_2_WIN);
+
+ mv64x60_set_32bit_window(&bh, MV64x60_CPU2DEV_3_WIN,
+ KATANA_CPLD_BASE, KATANA_CPLD_SIZE, 0);
+ bh.ci->enable_window_32bit(&bh, MV64x60_CPU2DEV_3_WIN);
+ cpld_base = ioremap(KATANA_CPLD_BASE, KATANA_CPLD_SIZE);
+
+ mv64x60_set_32bit_window(&bh, MV64x60_CPU2SRAM_WIN,
+ KATANA_INTERNAL_SRAM_BASE, MV64360_SRAM_SIZE, 0);
+ bh.ci->enable_window_32bit(&bh, MV64x60_CPU2SRAM_WIN);
+ sram_base = ioremap(KATANA_INTERNAL_SRAM_BASE, MV64360_SRAM_SIZE);
+
+ /* Set up Enet->SRAM window */
+ mv64x60_set_32bit_window(&bh, MV64x60_ENET2MEM_4_WIN,
+ KATANA_INTERNAL_SRAM_BASE, MV64360_SRAM_SIZE, 0x2);
+ bh.ci->enable_window_32bit(&bh, MV64x60_ENET2MEM_4_WIN);
+
+ /* Give enet r/w access to memory region */
+ mv64x60_set_bits(&bh, MV64360_ENET2MEM_ACC_PROT_0, (0x3 << (4 << 1)));
+ mv64x60_set_bits(&bh, MV64360_ENET2MEM_ACC_PROT_1, (0x3 << (4 << 1)));
+ mv64x60_set_bits(&bh, MV64360_ENET2MEM_ACC_PROT_2, (0x3 << (4 << 1)));
+
+ mv64x60_clr_bits(&bh, MV64x60_PCI1_PCI_DECODE_CNTL, (1 << 3));
+ mv64x60_clr_bits(&bh, MV64x60_TIMR_CNTR_0_3_CNTL,
+ ((1 << 0) | (1 << 8) | (1 << 16) | (1 << 24)));
+
+ /* Must wait until window set up before retrieving board id */
+ katana_get_board_id();
+
+ /* Enumerate pci bus (must know board id before getting proc number) */
+ if (katana_get_proc_num() == 0)
+ bh.hose_b->last_busno = pciauto_bus_scan(bh.hose_b, 0);
+
+#if defined(CONFIG_NOT_COHERENT_CACHE)
+ mv64x60_write(&bh, MV64360_SRAM_CONFIG, 0x00160000);
+#else
+ mv64x60_write(&bh, MV64360_SRAM_CONFIG, 0x001600b2);
+#endif
+
+ /*
+ * Setting the SRAM to 0. Note that this generates parity errors on
+ * internal data path in SRAM since it's first time accessing it
+ * while after reset it's not configured.
+ */
+ memset(sram_base, 0, MV64360_SRAM_SIZE);
+
+ /* Only processor zero [on 3750] is an PCI interrupt controller */
+ if (katana_get_proc_num() == 0)
+ katana_intr_setup();
+}
+
+static void __init
+katana_enable_ipmi(void)
+{
+ u8 reset_out;
+
+ /* Enable access to IPMI ctlr by clearing IPMI PORTSEL bit in CPLD */
+ reset_out = in_8(cpld_base + KATANA_CPLD_RESET_OUT);
+ reset_out &= ~KATANA_CPLD_RESET_OUT_PORTSEL;
+ out_8(cpld_base + KATANA_CPLD_RESET_OUT, reset_out);
+}
+
+static void __init
+katana_setup_arch(void)
+{
+ if (ppc_md.progress)
+ ppc_md.progress("katana_setup_arch: enter", 0);
+
+ set_tb(0, 0);
+
+#ifdef CONFIG_BLK_DEV_INITRD
+ if (initrd_start)
+ ROOT_DEV = Root_RAM0;
+ else
+#endif
+#ifdef CONFIG_ROOT_NFS
+ ROOT_DEV = Root_NFS;
+#else
+ ROOT_DEV = Root_SDA2;
+#endif
+
+ /*
+ * Set up the L2CR register.
+ *
+ * 750FX has only L2E, L2PE (bits 2-8 are reserved)
+ * DD2.0 has bug that requires the L2 to be in WRT mode
+ * avoid dirty data in cache
+ */
+ if (PVR_REV(mfspr(SPRN_PVR)) == 0x0200) {
+ printk(KERN_INFO "DD2.0 detected. Setting L2 cache"
+ "to Writethrough mode\n");
+ _set_L2CR(L2CR_L2E | L2CR_L2PE | L2CR_L2WT);
+ } else
+ _set_L2CR(L2CR_L2E | L2CR_L2PE);
+
+ if (ppc_md.progress)
+ ppc_md.progress("katana_setup_arch: calling setup_bridge", 0);
+
+ katana_setup_bridge();
+ katana_setup_peripherals();
+ katana_enable_ipmi();
+
+ katana_bus_frequency = katana_bus_freq(cpld_base);
+
+ printk(KERN_INFO "Artesyn Communication Products, LLC - Katana(TM)\n");
+ if (ppc_md.progress)
+ ppc_md.progress("katana_setup_arch: exit", 0);
+}
+
+/* Platform device data fixup routines. */
+#if defined(CONFIG_SERIAL_MPSC)
+static void __init
+katana_fixup_mpsc_pdata(struct platform_device *pdev)
+{
+ struct mpsc_pdata *pdata;
+
+ pdata = (struct mpsc_pdata *)pdev->dev.platform_data;
+
+ pdata->max_idle = 40;
+ pdata->default_baud = KATANA_DEFAULT_BAUD;
+ pdata->brg_clk_src = KATANA_MPSC_CLK_SRC;
+ /*
+ * TCLK (not SysCLk) is routed to BRG, then to the MPSC. On most parts,
+ * TCLK == SysCLK but on 64460, they are separate pins.
+ * SysCLK can go up to 200 MHz but TCLK can only go up to 133 MHz.
+ */
+ pdata->brg_clk_freq = min(katana_bus_frequency, MV64x60_TCLK_FREQ_MAX);
+}
+#endif
+
+#if defined(CONFIG_MV643XX_ETH)
+static void __init
+katana_fixup_eth_pdata(struct platform_device *pdev)
+{
+ struct mv643xx_eth_platform_data *eth_pd;
+ static u16 phy_addr[] = {
+ KATANA_ETH0_PHY_ADDR,
+ KATANA_ETH1_PHY_ADDR,
+ KATANA_ETH2_PHY_ADDR,
+ };
+
+ eth_pd = pdev->dev.platform_data;
+ eth_pd->force_phy_addr = 1;
+ eth_pd->phy_addr = phy_addr[pdev->id];
+ eth_pd->tx_queue_size = KATANA_ETH_TX_QUEUE_SIZE;
+ eth_pd->rx_queue_size = KATANA_ETH_RX_QUEUE_SIZE;
+}
+#endif
+
+static int __init
+katana_platform_notify(struct device *dev)
+{
+ static struct {
+ char *bus_id;
+ void ((*rtn)(struct platform_device *pdev));
+ } dev_map[] = {
+#if defined(CONFIG_SERIAL_MPSC)
+ { MPSC_CTLR_NAME ".0", katana_fixup_mpsc_pdata },
+ { MPSC_CTLR_NAME ".1", katana_fixup_mpsc_pdata },
+#endif
+#if defined(CONFIG_MV643XX_ETH)
+ { MV643XX_ETH_NAME ".0", katana_fixup_eth_pdata },
+ { MV643XX_ETH_NAME ".1", katana_fixup_eth_pdata },
+ { MV643XX_ETH_NAME ".2", katana_fixup_eth_pdata },
+#endif
+ };
+ struct platform_device *pdev;
+ int i;
+
+ if (dev && dev->bus_id)
+ for (i=0; i<ARRAY_SIZE(dev_map); i++)
+ if (!strncmp(dev->bus_id, dev_map[i].bus_id,
+ BUS_ID_SIZE)) {
+
+ pdev = container_of(dev,
+ struct platform_device, dev);
+ dev_map[i].rtn(pdev);
+ }
+
+ return 0;
+}
+
+#ifdef CONFIG_MTD_PHYSMAP
+
+#ifndef MB
+#define MB (1 << 20)
+#endif
+
+/*
+ * MTD Layout depends on amount of soldered FLASH in system. Sizes in MB.
+ *
+ * FLASH Amount: 128 64 32 16
+ * ------------- --- -- -- --
+ * Monitor: 1 1 1 1
+ * Primary Kernel: 1.5 1.5 1.5 1.5
+ * Primary fs: 30 30 <end> <end>
+ * Secondary Kernel: 1.5 1.5 N/A N/A
+ * Secondary fs: <end> <end> N/A N/A
+ * User: <overlays entire FLASH except for "Monitor" section>
+ */
+static int __init
+katana_setup_mtd(void)
+{
+ u32 size;
+ int ptbl_entries;
+ static struct mtd_partition *ptbl;
+
+ size = katana_flash_size_0 + katana_flash_size_1;
+ if (!size)
+ return -ENOMEM;
+
+ ptbl_entries = (size >= (64*MB)) ? 6 : 4;
+
+ if ((ptbl = kmalloc(ptbl_entries * sizeof(struct mtd_partition),
+ GFP_KERNEL)) == NULL) {
+
+ printk(KERN_WARNING "Can't alloc MTD partition table\n");
+ return -ENOMEM;
+ }
+ memset(ptbl, 0, ptbl_entries * sizeof(struct mtd_partition));
+
+ ptbl[0].name = "Monitor";
+ ptbl[0].size = KATANA_MTD_MONITOR_SIZE;
+ ptbl[1].name = "Primary Kernel";
+ ptbl[1].offset = MTDPART_OFS_NXTBLK;
+ ptbl[1].size = 0x00180000; /* 1.5 MB */
+ ptbl[2].name = "Primary Filesystem";
+ ptbl[2].offset = MTDPART_OFS_APPEND;
+ ptbl[2].size = MTDPART_SIZ_FULL; /* Correct for 16 & 32 MB */
+ ptbl[ptbl_entries-1].name = "User FLASH";
+ ptbl[ptbl_entries-1].offset = KATANA_MTD_MONITOR_SIZE;
+ ptbl[ptbl_entries-1].size = MTDPART_SIZ_FULL;
+
+ if (size >= (64*MB)) {
+ ptbl[2].size = 30*MB;
+ ptbl[3].name = "Secondary Kernel";
+ ptbl[3].offset = MTDPART_OFS_NXTBLK;
+ ptbl[3].size = 0x00180000; /* 1.5 MB */
+ ptbl[4].name = "Secondary Filesystem";
+ ptbl[4].offset = MTDPART_OFS_APPEND;
+ ptbl[4].size = MTDPART_SIZ_FULL;
+ }
+
+ physmap_map.size = size;
+ physmap_set_partitions(ptbl, ptbl_entries);
+ return 0;
+}
+
+arch_initcall(katana_setup_mtd);
+#endif
+
+static void
+katana_restart(char *cmd)
+{
+ ulong i = 10000000;
+
+ /* issue hard reset to the reset command register */
+ out_8(cpld_base + KATANA_CPLD_RST_CMD, KATANA_CPLD_RST_CMD_HR);
+
+ while (i-- > 0) ;
+ panic("restart failed\n");
+}
+
+static void
+katana_halt(void)
+{
+ u8 v;
+
+ if (katana_id == KATANA_ID_752I) {
+ v = in_8(cpld_base + HSL_PLD_BASE + HSL_PLD_HOT_SWAP_OFF);
+ v |= HSL_PLD_HOT_SWAP_LED_BIT;
+ out_8(cpld_base + HSL_PLD_BASE + HSL_PLD_HOT_SWAP_OFF, v);
+ }
+
+ while (1) ;
+ /* NOTREACHED */
+}
+
+static void
+katana_power_off(void)
+{
+ katana_halt();
+ /* NOTREACHED */
+}
+
+static int
+katana_show_cpuinfo(struct seq_file *m)
+{
+ seq_printf(m, "vendor\t\t: Artesyn Communication Products, LLC\n");
+
+ seq_printf(m, "board\t\t: ");
+
+ switch (katana_id) {
+ case KATANA_ID_3750:
+ seq_printf(m, "Katana 3750\n");
+ break;
+
+ case KATANA_ID_750I:
+ seq_printf(m, "Katana 750i\n");
+ break;
+
+ case KATANA_ID_752I:
+ seq_printf(m, "Katana 752i\n");
+ break;
+
+ default:
+ seq_printf(m, "Unknown\n");
+ break;
+ }
+
+ seq_printf(m, "product ID\t: 0x%x\n",
+ in_8(cpld_base + KATANA_CPLD_PRODUCT_ID));
+ seq_printf(m, "hardware rev\t: 0x%x\n",
+ in_8(cpld_base+KATANA_CPLD_HARDWARE_VER));
+ seq_printf(m, "PLD rev\t\t: 0x%x\n",
+ in_8(cpld_base + KATANA_CPLD_PLD_VER));
+ seq_printf(m, "PLB freq\t: %ldMhz\n",
+ (long)katana_bus_frequency / 1000000);
+ seq_printf(m, "PCI\t\t: %sMonarch\n", katana_is_monarch()? "" : "Non-");
+
+ return 0;
+}
+
+static void __init
+katana_calibrate_decr(void)
+{
+ u32 freq;
+
+ freq = katana_bus_frequency / 4;
+
+ printk(KERN_INFO "time_init: decrementer frequency = %lu.%.6lu MHz\n",
+ (long)freq / 1000000, (long)freq % 1000000);
+
+ tb_ticks_per_jiffy = freq / HZ;
+ tb_to_us = mulhwu_scale_factor(freq, 1000000);
+}
+
+unsigned long __init
+katana_find_end_of_memory(void)
+{
+ return mv64x60_get_mem_size(CONFIG_MV64X60_NEW_BASE,
+ MV64x60_TYPE_MV64360);
+}
+
+#if defined(CONFIG_I2C_MV64XXX) && defined(CONFIG_SENSORS_M41T00)
+extern ulong m41t00_get_rtc_time(void);
+extern int m41t00_set_rtc_time(ulong);
+
+static int __init
+katana_rtc_hookup(void)
+{
+ struct timespec tv;
+
+ ppc_md.get_rtc_time = m41t00_get_rtc_time;
+ ppc_md.set_rtc_time = m41t00_set_rtc_time;
+
+ tv.tv_nsec = 0;
+ tv.tv_sec = (ppc_md.get_rtc_time)();
+ do_settimeofday(&tv);
+
+ return 0;
+}
+late_initcall(katana_rtc_hookup);
+#endif
+
+static inline void
+katana_set_bat(void)
+{
+ mb();
+ mtspr(SPRN_DBAT2U, 0xf0001ffe);
+ mtspr(SPRN_DBAT2L, 0xf000002a);
+ mb();
+}
+
+#if defined(CONFIG_SERIAL_TEXT_DEBUG) && defined(CONFIG_SERIAL_MPSC_CONSOLE)
+static void __init
+katana_map_io(void)
+{
+ io_block_mapping(0xf8100000, 0xf8100000, 0x00020000, _PAGE_IO);
+}
+#endif
+
+void __init
+platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
+ unsigned long r6, unsigned long r7)
+{
+ parse_bootinfo(find_bootinfo());
+
+ /* ASSUMPTION: If both r3 (bd_t pointer) and r6 (cmdline pointer)
+ * are non-zero, then we should use the board info from the bd_t
+ * structure and the cmdline pointed to by r6 instead of the
+ * information from birecs, if any. Otherwise, use the information
+ * from birecs as discovered by the preceeding call to
+ * parse_bootinfo(). This rule should work with both PPCBoot, which
+ * uses a bd_t board info structure, and the kernel boot wrapper,
+ * which uses birecs.
+ */
+ if (r3 && r6) {
+ /* copy board info structure */
+ memcpy( (void *)__res,(void *)(r3+KERNELBASE), sizeof(bd_t) );
+ /* copy command line */
+ *(char *)(r7+KERNELBASE) = 0;
+ strcpy(cmd_line, (char *)(r6+KERNELBASE));
+ }
+
+ isa_mem_base = 0;
+
+ ppc_md.setup_arch = katana_setup_arch;
+ ppc_md.show_cpuinfo = katana_show_cpuinfo;
+ ppc_md.init_IRQ = mv64360_init_irq;
+ ppc_md.get_irq = mv64360_get_irq;
+ ppc_md.restart = katana_restart;
+ ppc_md.power_off = katana_power_off;
+ ppc_md.halt = katana_halt;
+ ppc_md.find_end_of_memory = katana_find_end_of_memory;
+ ppc_md.calibrate_decr = katana_calibrate_decr;
+
+#if defined(CONFIG_SERIAL_TEXT_DEBUG) && defined(CONFIG_SERIAL_MPSC_CONSOLE)
+ ppc_md.setup_io_mappings = katana_map_io;
+ ppc_md.progress = mv64x60_mpsc_progress;
+ mv64x60_progress_init(CONFIG_MV64X60_NEW_BASE);
+#endif
+
+#if defined(CONFIG_SERIAL_MPSC) || defined(CONFIG_MV643XX_ETH)
+ platform_notify = katana_platform_notify;
+#endif
+
+ katana_set_bat(); /* Need for katana_find_end_of_memory and progress */
+}
diff --git a/arch/ppc/platforms/katana.h b/arch/ppc/platforms/katana.h
new file mode 100644
index 0000000..b82ed81
--- /dev/null
+++ b/arch/ppc/platforms/katana.h
@@ -0,0 +1,255 @@
+/*
+ * arch/ppc/platforms/katana.h
+ *
+ * Definitions for Artesyn Katana750i/3750 board.
+ *
+ * Author: Tim Montgomery <timm@artesyncp.com>
+ * Maintained by: Mark A. Greer <mgreer@mvista.com>
+ *
+ * Based on code done by Rabeeh Khoury - rabeeh@galileo.co.il
+ * Based on code done by Mark A. Greer <mgreer@mvista.com>
+ *
+ * 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.
+ */
+
+/*
+ * The MV64360 has 2 PCI buses each with 1 window from the CPU bus to
+ * PCI I/O space and 4 windows from the CPU bus to PCI MEM space.
+ * We'll only use one PCI MEM window on each PCI bus.
+ *
+ * This is the CPU physical memory map (windows must be at least 64 KB and start
+ * on a boundary that is a multiple of the window size):
+ *
+ * 0xff800000-0xffffffff - Boot window
+ * 0xf8400000-0xf843ffff - Internal SRAM
+ * 0xf8200000-0xf83fffff - CPLD
+ * 0xf8100000-0xf810ffff - MV64360 Registers (CONFIG_MV64X60_NEW_BASE)
+ * 0xf8000000-0xf80fffff - Socketed FLASH
+ * 0xe0000000-0xefffffff - Soldered FLASH
+ * 0xc0000000-0xc3ffffff - PCI I/O (second hose)
+ * 0x80000000-0xbfffffff - PCI MEM (second hose)
+ */
+
+#ifndef __PPC_PLATFORMS_KATANA_H
+#define __PPC_PLATFORMS_KATANA_H
+
+/* CPU Physical Memory Map setup. */
+#define KATANA_BOOT_WINDOW_BASE 0xff800000
+#define KATANA_BOOT_WINDOW_SIZE 0x00800000 /* 8 MB */
+#define KATANA_INTERNAL_SRAM_BASE 0xf8400000
+#define KATANA_CPLD_BASE 0xf8200000
+#define KATANA_CPLD_SIZE 0x00200000 /* 2 MB */
+#define KATANA_SOCKET_BASE 0xf8000000
+#define KATANA_SOCKETED_FLASH_SIZE 0x00100000 /* 1 MB */
+#define KATANA_SOLDERED_FLASH_BASE 0xe0000000
+#define KATANA_SOLDERED_FLASH_SIZE 0x10000000 /* 256 MB */
+
+#define KATANA_PCI1_MEM_START_PROC_ADDR 0x80000000
+#define KATANA_PCI1_MEM_START_PCI_HI_ADDR 0x00000000
+#define KATANA_PCI1_MEM_START_PCI_LO_ADDR 0x80000000
+#define KATANA_PCI1_MEM_SIZE 0x40000000 /* 1 GB */
+#define KATANA_PCI1_IO_START_PROC_ADDR 0xc0000000
+#define KATANA_PCI1_IO_START_PCI_ADDR 0x00000000
+#define KATANA_PCI1_IO_SIZE 0x04000000 /* 64 MB */
+
+/* Board-specific IRQ info */
+#define KATANA_PCI_INTA_IRQ_3750 64+8
+#define KATANA_PCI_INTB_IRQ_3750 64+9
+#define KATANA_PCI_INTC_IRQ_3750 64+10
+
+#define KATANA_PCI_INTA_IRQ_750i 64+8
+#define KATANA_PCI_INTB_IRQ_750i 64+9
+#define KATANA_PCI_INTC_IRQ_750i 64+10
+#define KATANA_PCI_INTD_IRQ_750i 64+14
+
+#define KATANA_CPLD_RST_EVENT 0x00000000
+#define KATANA_CPLD_RST_CMD 0x00001000
+#define KATANA_CPLD_PCI_ERR_INT_EN 0x00002000
+#define KATANA_CPLD_PCI_ERR_INT_PEND 0x00003000
+#define KATANA_CPLD_PRODUCT_ID 0x00004000
+#define KATANA_CPLD_EREADY 0x00005000
+
+#define KATANA_CPLD_HARDWARE_VER 0x00007000
+#define KATANA_CPLD_PLD_VER 0x00008000
+#define KATANA_CPLD_BD_CFG_0 0x00009000
+#define KATANA_CPLD_BD_CFG_1 0x0000a000
+#define KATANA_CPLD_BD_CFG_3 0x0000c000
+#define KATANA_CPLD_LED 0x0000d000
+#define KATANA_CPLD_RESET_OUT 0x0000e000
+
+#define KATANA_CPLD_RST_EVENT_INITACT 0x80
+#define KATANA_CPLD_RST_EVENT_SW 0x40
+#define KATANA_CPLD_RST_EVENT_WD 0x20
+#define KATANA_CPLD_RST_EVENT_COPS 0x10
+#define KATANA_CPLD_RST_EVENT_COPH 0x08
+#define KATANA_CPLD_RST_EVENT_CPCI 0x02
+#define KATANA_CPLD_RST_EVENT_FP 0x01
+
+#define KATANA_CPLD_RST_CMD_SCL 0x80
+#define KATANA_CPLD_RST_CMD_SDA 0x40
+#define KATANA_CPLD_RST_CMD_I2C 0x10
+#define KATANA_CPLD_RST_CMD_FR 0x08
+#define KATANA_CPLD_RST_CMD_SR 0x04
+#define KATANA_CPLD_RST_CMD_HR 0x01
+
+#define KATANA_CPLD_BD_CFG_0_SYSCLK_MASK 0xc0
+#define KATANA_CPLD_BD_CFG_0_SYSCLK_200 0x00
+#define KATANA_CPLD_BD_CFG_0_SYSCLK_166 0x80
+#define KATANA_CPLD_BD_CFG_0_SYSCLK_133 0xc0
+#define KATANA_CPLD_BD_CFG_0_SYSCLK_100 0x40
+
+#define KATANA_CPLD_BD_CFG_1_FL_BANK_MASK 0x03
+#define KATANA_CPLD_BD_CFG_1_FL_BANK_16MB 0x00
+#define KATANA_CPLD_BD_CFG_1_FL_BANK_32MB 0x01
+#define KATANA_CPLD_BD_CFG_1_FL_BANK_64MB 0x02
+#define KATANA_CPLD_BD_CFG_1_FL_BANK_128MB 0x03
+
+#define KATANA_CPLD_BD_CFG_1_FL_NUM_BANKS_MASK 0x04
+#define KATANA_CPLD_BD_CFG_1_FL_NUM_BANKS_ONE 0x00
+#define KATANA_CPLD_BD_CFG_1_FL_NUM_BANKS_TWO 0x04
+
+#define KATANA_CPLD_BD_CFG_3_MONARCH 0x04
+
+#define KATANA_CPLD_RESET_OUT_PORTSEL 0x80
+#define KATANA_CPLD_RESET_OUT_WD 0x20
+#define KATANA_CPLD_RESET_OUT_COPH 0x08
+#define KATANA_CPLD_RESET_OUT_PCI_RST_PCI 0x02
+#define KATANA_CPLD_RESET_OUT_PCI_RST_FP 0x01
+
+#define KATANA_MBOX_RESET_REQUEST 0xC83A
+#define KATANA_MBOX_RESET_ACK 0xE430
+#define KATANA_MBOX_RESET_DONE 0x32E5
+
+#define HSL_PLD_BASE 0x00010000
+#define HSL_PLD_J4SGA_REG_OFF 0
+#define HSL_PLD_J4GA_REG_OFF 1
+#define HSL_PLD_J2GA_REG_OFF 2
+#define HSL_PLD_HOT_SWAP_OFF 6
+#define HSL_PLD_HOT_SWAP_LED_BIT 0x1
+#define GA_MASK 0x1f
+#define HSL_PLD_SIZE 0x1000
+#define K3750_GPP_GEO_ADDR_PINS 0xf8000000
+#define K3750_GPP_GEO_ADDR_SHIFT 27
+
+#define K3750_GPP_EVENT_PROC_0 (1 << 21)
+#define K3750_GPP_EVENT_PROC_1_2 (1 << 2)
+
+#define PCI_VENDOR_ID_ARTESYN 0x1223
+#define PCI_DEVICE_ID_KATANA_3750_PROC0 0x0041
+#define PCI_DEVICE_ID_KATANA_3750_PROC1 0x0042
+#define PCI_DEVICE_ID_KATANA_3750_PROC2 0x0043
+
+#define COPROC_MEM_FUNCTION 0
+#define COPROC_MEM_BAR 0
+#define COPROC_REGS_FUNCTION 0
+#define COPROC_REGS_BAR 4
+#define COPROC_FLASH_FUNCTION 2
+#define COPROC_FLASH_BAR 4
+
+#define KATANA_IPMB_LOCAL_I2C_ADDR 0x08
+
+#define KATANA_DEFAULT_BAUD 9600
+#define KATANA_MPSC_CLK_SRC 8 /* TCLK */
+
+#define KATANA_MTD_MONITOR_SIZE (1 << 20) /* 1 MB */
+
+#define KATANA_ETH0_PHY_ADDR 12
+#define KATANA_ETH1_PHY_ADDR 11
+#define KATANA_ETH2_PHY_ADDR 4
+
+#define KATANA_PRODUCT_ID_3750 0x01
+#define KATANA_PRODUCT_ID_750i 0x02
+#define KATANA_PRODUCT_ID_752i 0x04
+
+#define KATANA_ETH_TX_QUEUE_SIZE 800
+#define KATANA_ETH_RX_QUEUE_SIZE 400
+
+#define KATANA_ETH_PORT_CONFIG_VALUE \
+ ETH_UNICAST_NORMAL_MODE | \
+ ETH_DEFAULT_RX_QUEUE_0 | \
+ ETH_DEFAULT_RX_ARP_QUEUE_0 | \
+ ETH_RECEIVE_BC_IF_NOT_IP_OR_ARP | \
+ ETH_RECEIVE_BC_IF_IP | \
+ ETH_RECEIVE_BC_IF_ARP | \
+ ETH_CAPTURE_TCP_FRAMES_DIS | \
+ ETH_CAPTURE_UDP_FRAMES_DIS | \
+ ETH_DEFAULT_RX_TCP_QUEUE_0 | \
+ ETH_DEFAULT_RX_UDP_QUEUE_0 | \
+ ETH_DEFAULT_RX_BPDU_QUEUE_0
+
+#define KATANA_ETH_PORT_CONFIG_EXTEND_VALUE \
+ ETH_SPAN_BPDU_PACKETS_AS_NORMAL | \
+ ETH_PARTITION_DISABLE
+
+#define GT_ETH_IPG_INT_RX(value) \
+ ((value & 0x3fff) << 8)
+
+#define KATANA_ETH_PORT_SDMA_CONFIG_VALUE \
+ ETH_RX_BURST_SIZE_4_64BIT | \
+ GT_ETH_IPG_INT_RX(0) | \
+ ETH_TX_BURST_SIZE_4_64BIT
+
+#define KATANA_ETH_PORT_SERIAL_CONTROL_VALUE \
+ ETH_FORCE_LINK_PASS | \
+ ETH_ENABLE_AUTO_NEG_FOR_DUPLX | \
+ ETH_DISABLE_AUTO_NEG_FOR_FLOW_CTRL | \
+ ETH_ADV_SYMMETRIC_FLOW_CTRL | \
+ ETH_FORCE_FC_MODE_NO_PAUSE_DIS_TX | \
+ ETH_FORCE_BP_MODE_NO_JAM | \
+ BIT9 | \
+ ETH_DO_NOT_FORCE_LINK_FAIL | \
+ ETH_RETRANSMIT_16_ATTEMPTS | \
+ ETH_ENABLE_AUTO_NEG_SPEED_GMII | \
+ ETH_DTE_ADV_0 | \
+ ETH_DISABLE_AUTO_NEG_BYPASS | \
+ ETH_AUTO_NEG_NO_CHANGE | \
+ ETH_MAX_RX_PACKET_9700BYTE | \
+ ETH_CLR_EXT_LOOPBACK | \
+ ETH_SET_FULL_DUPLEX_MODE | \
+ ETH_ENABLE_FLOW_CTRL_TX_RX_IN_FULL_DUPLEX
+
+#ifndef __ASSEMBLY__
+
+typedef enum {
+ KATANA_ID_3750,
+ KATANA_ID_750I,
+ KATANA_ID_752I,
+ KATANA_ID_MAX
+} katana_id_t;
+
+#endif
+
+static inline u32
+katana_bus_freq(void __iomem *cpld_base)
+{
+ u8 bd_cfg_0;
+
+ bd_cfg_0 = in_8(cpld_base + KATANA_CPLD_BD_CFG_0);
+
+ switch (bd_cfg_0 & KATANA_CPLD_BD_CFG_0_SYSCLK_MASK) {
+ case KATANA_CPLD_BD_CFG_0_SYSCLK_200:
+ return 200000000;
+ break;
+
+ case KATANA_CPLD_BD_CFG_0_SYSCLK_166:
+ return 166666666;
+ break;
+
+ case KATANA_CPLD_BD_CFG_0_SYSCLK_133:
+ return 133333333;
+ break;
+
+ case KATANA_CPLD_BD_CFG_0_SYSCLK_100:
+ return 100000000;
+ break;
+
+ default:
+ return 133333333;
+ break;
+ }
+}
+
+#endif /* __PPC_PLATFORMS_KATANA_H */
diff --git a/arch/ppc/platforms/lantec.h b/arch/ppc/platforms/lantec.h
new file mode 100644
index 0000000..8c87642
--- /dev/null
+++ b/arch/ppc/platforms/lantec.h
@@ -0,0 +1,21 @@
+/*
+ * LANTEC board specific definitions
+ *
+ * Copyright (c) 2001 Wolfgang Denk (wd@denx.de)
+ */
+
+#ifndef __MACH_LANTEC_H
+#define __MACH_LANTEC_H
+
+#include <linux/config.h>
+
+#include <asm/ppcboot.h>
+
+#define IMAP_ADDR 0xFFF00000 /* physical base address of IMMR area */
+#define IMAP_SIZE (64 * 1024) /* mapped size of IMMR area */
+
+/* We don't use the 8259.
+*/
+#define NR_8259_INTS 0
+
+#endif /* __MACH_LANTEC_H */
diff --git a/arch/ppc/platforms/lite5200.c b/arch/ppc/platforms/lite5200.c
new file mode 100644
index 0000000..b604cf8
--- /dev/null
+++ b/arch/ppc/platforms/lite5200.c
@@ -0,0 +1,236 @@
+/*
+ * arch/ppc/platforms/lite5200.c
+ *
+ * Platform support file for the Freescale LITE5200 based on MPC52xx.
+ * A maximum of this file should be moved to syslib/mpc52xx_?????
+ * so that new platform based on MPC52xx need a minimal platform file
+ * ( avoid code duplication )
+ *
+ *
+ * Maintainer : Sylvain Munaut <tnt@246tNt.com>
+ *
+ * Based on the 2.4 code written by Kent Borg,
+ * Dale Farnsworth <dale.farnsworth@mvista.com> and
+ * Wolfgang Denk <wd@denx.de>
+ *
+ * Copyright 2004-2005 Sylvain Munaut <tnt@246tNt.com>
+ * Copyright 2003 Motorola Inc.
+ * Copyright 2003 MontaVista Software Inc.
+ * Copyright 2003 DENX Software Engineering (wd@denx.de)
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2. This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ */
+
+#include <linux/config.h>
+#include <linux/initrd.h>
+#include <linux/seq_file.h>
+#include <linux/kdev_t.h>
+#include <linux/root_dev.h>
+#include <linux/console.h>
+#include <linux/module.h>
+
+#include <asm/bootinfo.h>
+#include <asm/io.h>
+#include <asm/mpc52xx.h>
+#include <asm/ppc_sys.h>
+
+#include <syslib/mpc52xx_pci.h>
+
+
+extern int powersave_nap;
+
+/* Board data given by U-Boot */
+bd_t __res;
+EXPORT_SYMBOL(__res); /* For modules */
+
+
+/* ======================================================================== */
+/* Platform specific code */
+/* ======================================================================== */
+
+/* Supported PSC function in "preference" order */
+struct mpc52xx_psc_func mpc52xx_psc_functions[] = {
+ { .id = 0,
+ .func = "uart",
+ },
+ { .id = -1, /* End entry */
+ .func = NULL,
+ }
+ };
+
+
+static int
+lite5200_show_cpuinfo(struct seq_file *m)
+{
+ seq_printf(m, "machine\t\t: Freescale LITE5200\n");
+ return 0;
+}
+
+#ifdef CONFIG_PCI
+static int
+lite5200_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin)
+{
+ return (pin == 1) && (idsel==24) ? MPC52xx_IRQ0 : -1;
+}
+#endif
+
+static void __init
+lite5200_setup_cpu(void)
+{
+ struct mpc52xx_cdm __iomem *cdm;
+ struct mpc52xx_gpio __iomem *gpio;
+ struct mpc52xx_intr __iomem *intr;
+ struct mpc52xx_xlb __iomem *xlb;
+
+ u32 port_config;
+ u32 intr_ctrl;
+
+ /* Map zones */
+ cdm = ioremap(MPC52xx_PA(MPC52xx_CDM_OFFSET), MPC52xx_CDM_SIZE);
+ gpio = ioremap(MPC52xx_PA(MPC52xx_GPIO_OFFSET), MPC52xx_GPIO_SIZE);
+ xlb = ioremap(MPC52xx_PA(MPC52xx_XLB_OFFSET), MPC52xx_XLB_SIZE);
+ intr = ioremap(MPC52xx_PA(MPC52xx_INTR_OFFSET), MPC52xx_INTR_SIZE);
+
+ if (!cdm || !gpio || !xlb || !intr) {
+ printk("lite5200.c: Error while mapping CDM/GPIO/XLB/INTR during"
+ "lite5200_setup_cpu\n");
+ goto unmap_regs;
+ }
+
+ /* Use internal 48 Mhz */
+ out_8(&cdm->ext_48mhz_en, 0x00);
+ out_8(&cdm->fd_enable, 0x01);
+ if (in_be32(&cdm->rstcfg) & 0x40) /* Assumes 33Mhz clock */
+ out_be16(&cdm->fd_counters, 0x0001);
+ else
+ out_be16(&cdm->fd_counters, 0x5555);
+
+ /* Get port mux config */
+ port_config = in_be32(&gpio->port_config);
+
+ /* 48Mhz internal, pin is GPIO */
+ port_config &= ~0x00800000;
+
+ /* USB port */
+ port_config &= ~0x00007000; /* Differential mode - USB1 only */
+ port_config |= 0x00001000;
+
+ /* Commit port config */
+ out_be32(&gpio->port_config, port_config);
+
+ /* Configure the XLB Arbiter */
+ out_be32(&xlb->master_pri_enable, 0xff);
+ out_be32(&xlb->master_priority, 0x11111111);
+
+ /* Enable ram snooping for 1GB window */
+ out_be32(&xlb->config, in_be32(&xlb->config) | MPC52xx_XLB_CFG_SNOOP);
+ out_be32(&xlb->snoop_window, MPC52xx_PCI_TARGET_MEM | 0x1d);
+
+ /* IRQ[0-3] setup : IRQ0 - Level Active Low */
+ /* IRQ[1-3] - Level Active High */
+ intr_ctrl = in_be32(&intr->ctrl);
+ intr_ctrl &= ~0x00ff0000;
+ intr_ctrl |= 0x00c00000;
+ out_be32(&intr->ctrl, intr_ctrl);
+
+ /* Unmap reg zone */
+unmap_regs:
+ if (cdm) iounmap(cdm);
+ if (gpio) iounmap(gpio);
+ if (xlb) iounmap(xlb);
+ if (intr) iounmap(intr);
+}
+
+static void __init
+lite5200_setup_arch(void)
+{
+ /* CPU & Port mux setup */
+ lite5200_setup_cpu();
+
+#ifdef CONFIG_PCI
+ /* PCI Bridge setup */
+ mpc52xx_find_bridges();
+#endif
+}
+
+void __init
+platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
+ unsigned long r6, unsigned long r7)
+{
+ /* Generic MPC52xx platform initialization */
+ /* TODO Create one and move a max of stuff in it.
+ Put this init in the syslib */
+
+ struct bi_record *bootinfo = find_bootinfo();
+
+ if (bootinfo)
+ parse_bootinfo(bootinfo);
+ else {
+ /* Load the bd_t board info structure */
+ if (r3)
+ memcpy((void*)&__res,(void*)(r3+KERNELBASE),
+ sizeof(bd_t));
+
+#ifdef CONFIG_BLK_DEV_INITRD
+ /* Load the initrd */
+ if (r4) {
+ initrd_start = r4 + KERNELBASE;
+ initrd_end = r5 + KERNELBASE;
+ }
+#endif
+
+ /* Load the command line */
+ if (r6) {
+ *(char *)(r7+KERNELBASE) = 0;
+ strcpy(cmd_line, (char *)(r6+KERNELBASE));
+ }
+ }
+
+ /* PPC Sys identification */
+ identify_ppc_sys_by_id(mfspr(SPRN_SVR));
+
+ /* BAT setup */
+ mpc52xx_set_bat();
+
+ /* No ISA bus by default */
+ isa_io_base = 0;
+ isa_mem_base = 0;
+
+ /* Powersave */
+ /* This is provided as an example on how to do it. But you
+ need to be aware that NAP disable bus snoop and that may
+ be required for some devices to work properly, like USB ... */
+ /* powersave_nap = 1; */
+
+
+ /* Setup the ppc_md struct */
+ ppc_md.setup_arch = lite5200_setup_arch;
+ ppc_md.show_cpuinfo = lite5200_show_cpuinfo;
+ ppc_md.show_percpuinfo = NULL;
+ ppc_md.init_IRQ = mpc52xx_init_irq;
+ ppc_md.get_irq = mpc52xx_get_irq;
+
+#ifdef CONFIG_PCI
+ ppc_md.pci_map_irq = lite5200_map_irq;
+#endif
+
+ ppc_md.find_end_of_memory = mpc52xx_find_end_of_memory;
+ ppc_md.setup_io_mappings = mpc52xx_map_io;
+
+ ppc_md.restart = mpc52xx_restart;
+ ppc_md.power_off = mpc52xx_power_off;
+ ppc_md.halt = mpc52xx_halt;
+
+ /* No time keeper on the LITE5200 */
+ ppc_md.time_init = NULL;
+ ppc_md.get_rtc_time = NULL;
+ ppc_md.set_rtc_time = NULL;
+
+ ppc_md.calibrate_decr = mpc52xx_calibrate_decr;
+#ifdef CONFIG_SERIAL_TEXT_DEBUG
+ ppc_md.progress = mpc52xx_progress;
+#endif
+}
+
diff --git a/arch/ppc/platforms/lite5200.h b/arch/ppc/platforms/lite5200.h
new file mode 100644
index 0000000..c1de2aa
--- /dev/null
+++ b/arch/ppc/platforms/lite5200.h
@@ -0,0 +1,23 @@
+/*
+ * arch/ppc/platforms/lite5200.h
+ *
+ * Definitions for Freescale LITE5200 : MPC52xx Standard Development
+ * Platform board support
+ *
+ * Maintainer : Sylvain Munaut <tnt@246tNt.com>
+ *
+ * Copyright (C) 2004 Sylvain Munaut <tnt@246tNt.com>
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2. This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ */
+
+#ifndef __PLATFORMS_LITE5200_H__
+#define __PLATFORMS_LITE5200_H__
+
+/* Serial port used for low-level debug */
+#define MPC52xx_PF_CONSOLE_PORT 1 /* PSC1 */
+
+
+#endif /* __PLATFORMS_LITE5200_H__ */
diff --git a/arch/ppc/platforms/lopec.c b/arch/ppc/platforms/lopec.c
new file mode 100644
index 0000000..a556952
--- /dev/null
+++ b/arch/ppc/platforms/lopec.c
@@ -0,0 +1,411 @@
+/*
+ * arch/ppc/platforms/lopec.c
+ *
+ * Setup routines for the Motorola LoPEC.
+ *
+ * Author: Dan Cox
+ * Maintainer: Tom Rini <trini@kernel.crashing.org>
+ *
+ * 2001-2004 (c) MontaVista, Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/delay.h>
+#include <linux/pci_ids.h>
+#include <linux/ioport.h>
+#include <linux/init.h>
+#include <linux/ide.h>
+#include <linux/seq_file.h>
+#include <linux/initrd.h>
+#include <linux/console.h>
+#include <linux/root_dev.h>
+#include <linux/pci.h>
+
+#include <asm/machdep.h>
+#include <asm/pci-bridge.h>
+#include <asm/io.h>
+#include <asm/open_pic.h>
+#include <asm/i8259.h>
+#include <asm/todc.h>
+#include <asm/bootinfo.h>
+#include <asm/mpc10x.h>
+#include <asm/hw_irq.h>
+#include <asm/prep_nvram.h>
+#include <asm/kgdb.h>
+
+/*
+ * Define all of the IRQ senses and polarities. Taken from the
+ * LoPEC Programmer's Reference Guide.
+ */
+static u_char lopec_openpic_initsenses[16] __initdata = {
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* IRQ 0 */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* IRQ 1 */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* IRQ 2 */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* IRQ 3 */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* IRQ 4 */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* IRQ 5 */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* IRQ 6 */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* IRQ 7 */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* IRQ 8 */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* IRQ 9 */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* IRQ 10 */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* IRQ 11 */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* IRQ 12 */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* IRQ 13 */
+ (IRQ_SENSE_EDGE | IRQ_POLARITY_NEGATIVE), /* IRQ 14 */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE) /* IRQ 15 */
+};
+
+static inline int __init
+lopec_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin)
+{
+ int irq;
+ static char pci_irq_table[][4] = {
+ {16, 0, 0, 0}, /* ID 11 - Winbond */
+ {22, 0, 0, 0}, /* ID 12 - SCSI */
+ {0, 0, 0, 0}, /* ID 13 - nothing */
+ {17, 0, 0, 0}, /* ID 14 - 82559 Ethernet */
+ {27, 0, 0, 0}, /* ID 15 - USB */
+ {23, 0, 0, 0}, /* ID 16 - PMC slot 1 */
+ {24, 0, 0, 0}, /* ID 17 - PMC slot 2 */
+ {25, 0, 0, 0}, /* ID 18 - PCI slot */
+ {0, 0, 0, 0}, /* ID 19 - nothing */
+ {0, 0, 0, 0}, /* ID 20 - nothing */
+ {0, 0, 0, 0}, /* ID 21 - nothing */
+ {0, 0, 0, 0}, /* ID 22 - nothing */
+ {0, 0, 0, 0}, /* ID 23 - nothing */
+ {0, 0, 0, 0}, /* ID 24 - PMC slot 1b */
+ {0, 0, 0, 0}, /* ID 25 - nothing */
+ {0, 0, 0, 0} /* ID 26 - PMC Slot 2b */
+ };
+ const long min_idsel = 11, max_idsel = 26, irqs_per_slot = 4;
+
+ irq = PCI_IRQ_TABLE_LOOKUP;
+ if (!irq)
+ return 0;
+
+ return irq;
+}
+
+static void __init
+lopec_setup_winbond_83553(struct pci_controller *hose)
+{
+ int devfn;
+
+ devfn = PCI_DEVFN(11,0);
+
+ /* IDE interrupt routing (primary 14, secondary 15) */
+ early_write_config_byte(hose, 0, devfn, 0x43, 0xef);
+ /* PCI interrupt routing */
+ early_write_config_word(hose, 0, devfn, 0x44, 0x0000);
+
+ /* ISA-PCI address decoder */
+ early_write_config_byte(hose, 0, devfn, 0x48, 0xf0);
+
+ /* RTC, kb, not used in PPC */
+ early_write_config_byte(hose, 0, devfn, 0x4d, 0x00);
+ early_write_config_byte(hose, 0, devfn, 0x4e, 0x04);
+ devfn = PCI_DEVFN(11, 1);
+ early_write_config_byte(hose, 0, devfn, 0x09, 0x8f);
+ early_write_config_dword(hose, 0, devfn, 0x40, 0x00ff0011);
+}
+
+static void __init
+lopec_find_bridges(void)
+{
+ struct pci_controller *hose;
+
+ hose = pcibios_alloc_controller();
+ if (!hose)
+ return;
+
+ hose->first_busno = 0;
+ hose->last_busno = 0xff;
+
+ if (mpc10x_bridge_init(hose, MPC10X_MEM_MAP_B, MPC10X_MEM_MAP_B,
+ MPC10X_MAPB_EUMB_BASE) == 0) {
+
+ hose->mem_resources[0].end = 0xffffffff;
+ lopec_setup_winbond_83553(hose);
+ hose->last_busno = pciauto_bus_scan(hose, hose->first_busno);
+ ppc_md.pci_swizzle = common_swizzle;
+ ppc_md.pci_map_irq = lopec_map_irq;
+ }
+}
+
+static int
+lopec_show_cpuinfo(struct seq_file *m)
+{
+ seq_printf(m, "machine\t\t: Motorola LoPEC\n");
+ return 0;
+}
+
+static u32
+lopec_irq_canonicalize(u32 irq)
+{
+ if (irq == 2)
+ return 9;
+ else
+ return irq;
+}
+
+static void
+lopec_restart(char *cmd)
+{
+#define LOPEC_SYSSTAT1 0xffe00000
+ /* force a hard reset, if possible */
+ unsigned char reg = *((unsigned char *) LOPEC_SYSSTAT1);
+ reg |= 0x80;
+ *((unsigned char *) LOPEC_SYSSTAT1) = reg;
+
+ local_irq_disable();
+ while(1);
+#undef LOPEC_SYSSTAT1
+}
+
+static void
+lopec_halt(void)
+{
+ local_irq_disable();
+ while(1);
+}
+
+static void
+lopec_power_off(void)
+{
+ lopec_halt();
+}
+
+#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
+int lopec_ide_ports_known = 0;
+static unsigned long lopec_ide_regbase[MAX_HWIFS];
+static unsigned long lopec_ide_ctl_regbase[MAX_HWIFS];
+static unsigned long lopec_idedma_regbase;
+
+static void
+lopec_ide_probe(void)
+{
+ struct pci_dev *dev = pci_get_device(PCI_VENDOR_ID_WINBOND,
+ PCI_DEVICE_ID_WINBOND_82C105,
+ NULL);
+ lopec_ide_ports_known = 1;
+
+ if (dev) {
+ lopec_ide_regbase[0] = dev->resource[0].start;
+ lopec_ide_regbase[1] = dev->resource[2].start;
+ lopec_ide_ctl_regbase[0] = dev->resource[1].start;
+ lopec_ide_ctl_regbase[1] = dev->resource[3].start;
+ lopec_idedma_regbase = dev->resource[4].start;
+ pci_dev_put(dev);
+ }
+}
+
+static int
+lopec_ide_default_irq(unsigned long base)
+{
+ if (lopec_ide_ports_known == 0)
+ lopec_ide_probe();
+
+ if (base == lopec_ide_regbase[0])
+ return 14;
+ else if (base == lopec_ide_regbase[1])
+ return 15;
+ else
+ return 0;
+}
+
+static unsigned long
+lopec_ide_default_io_base(int index)
+{
+ if (lopec_ide_ports_known == 0)
+ lopec_ide_probe();
+ return lopec_ide_regbase[index];
+}
+
+static void __init
+lopec_ide_init_hwif_ports(hw_regs_t *hw, unsigned long data,
+ unsigned long ctl, int *irq)
+{
+ unsigned long reg = data;
+ uint alt_status_base;
+ int i;
+
+ for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++)
+ hw->io_ports[i] = reg++;
+
+ if (data == lopec_ide_regbase[0]) {
+ alt_status_base = lopec_ide_ctl_regbase[0] + 2;
+ hw->irq = 14;
+ } else if (data == lopec_ide_regbase[1]) {
+ alt_status_base = lopec_ide_ctl_regbase[1] + 2;
+ hw->irq = 15;
+ } else {
+ alt_status_base = 0;
+ hw->irq = 0;
+ }
+
+ if (ctl)
+ hw->io_ports[IDE_CONTROL_OFFSET] = ctl;
+ else
+ hw->io_ports[IDE_CONTROL_OFFSET] = alt_status_base;
+
+ if (irq != NULL)
+ *irq = hw->irq;
+
+}
+#endif /* BLK_DEV_IDE */
+
+static void __init
+lopec_init_IRQ(void)
+{
+ int i;
+
+ /*
+ * Provide the open_pic code with the correct table of interrupts.
+ */
+ OpenPIC_InitSenses = lopec_openpic_initsenses;
+ OpenPIC_NumInitSenses = sizeof(lopec_openpic_initsenses);
+
+ mpc10x_set_openpic();
+
+ /* We have a cascade on OpenPIC IRQ 0, Linux IRQ 16 */
+ openpic_hookup_cascade(NUM_8259_INTERRUPTS, "82c59 cascade",
+ &i8259_irq);
+
+ /* Map i8259 interrupts */
+ for(i = 0; i < NUM_8259_INTERRUPTS; i++)
+ irq_desc[i].handler = &i8259_pic;
+
+ /*
+ * The EPIC allows for a read in the range of 0xFEF00000 ->
+ * 0xFEFFFFFF to generate a PCI interrupt-acknowledge transaction.
+ */
+ i8259_init(0xfef00000);
+}
+
+static int __init
+lopec_request_io(void)
+{
+ outb(0x00, 0x4d0);
+ outb(0xc0, 0x4d1);
+
+ request_region(0x00, 0x20, "dma1");
+ request_region(0x20, 0x20, "pic1");
+ request_region(0x40, 0x20, "timer");
+ request_region(0x80, 0x10, "dma page reg");
+ request_region(0xa0, 0x20, "pic2");
+ request_region(0xc0, 0x20, "dma2");
+
+ return 0;
+}
+
+device_initcall(lopec_request_io);
+
+static void __init
+lopec_map_io(void)
+{
+ io_block_mapping(0xf0000000, 0xf0000000, 0x10000000, _PAGE_IO);
+ io_block_mapping(0xb0000000, 0xb0000000, 0x10000000, _PAGE_IO);
+}
+
+/*
+ * Set BAT 3 to map 0xf8000000 to end of physical memory space 1-to-1.
+ */
+static __inline__ void
+lopec_set_bat(void)
+{
+ mb();
+ mtspr(SPRN_DBAT1U, 0xf8000ffe);
+ mtspr(SPRN_DBAT1L, 0xf800002a);
+ mb();
+}
+
+TODC_ALLOC();
+
+static void __init
+lopec_setup_arch(void)
+{
+
+ TODC_INIT(TODC_TYPE_MK48T37, 0, 0,
+ ioremap(0xffe80000, 0x8000), 8);
+
+ loops_per_jiffy = 100000000/HZ;
+
+ lopec_find_bridges();
+
+#ifdef CONFIG_BLK_DEV_INITRD
+ if (initrd_start)
+ ROOT_DEV = Root_RAM0;
+ else
+#elif defined(CONFIG_ROOT_NFS)
+ ROOT_DEV = Root_NFS;
+#elif defined(CONFIG_BLK_DEV_IDEDISK)
+ ROOT_DEV = Root_HDA1;
+#else
+ ROOT_DEV = Root_SDA1;
+#endif
+
+#ifdef CONFIG_PPCBUG_NVRAM
+ /* Read in NVRAM data */
+ init_prep_nvram();
+
+ /* if no bootargs, look in NVRAM */
+ if ( cmd_line[0] == '\0' ) {
+ char *bootargs;
+ bootargs = prep_nvram_get_var("bootargs");
+ if (bootargs != NULL) {
+ strcpy(cmd_line, bootargs);
+ /* again.. */
+ strcpy(saved_command_line, cmd_line);
+ }
+ }
+#endif
+}
+
+void __init
+platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
+ unsigned long r6, unsigned long r7)
+{
+ parse_bootinfo(find_bootinfo());
+ lopec_set_bat();
+
+ isa_io_base = MPC10X_MAPB_ISA_IO_BASE;
+ isa_mem_base = MPC10X_MAPB_ISA_MEM_BASE;
+ pci_dram_offset = MPC10X_MAPB_DRAM_OFFSET;
+ ISA_DMA_THRESHOLD = 0x00ffffff;
+ DMA_MODE_READ = 0x44;
+ DMA_MODE_WRITE = 0x48;
+
+ ppc_md.setup_arch = lopec_setup_arch;
+ ppc_md.show_cpuinfo = lopec_show_cpuinfo;
+ ppc_md.irq_canonicalize = lopec_irq_canonicalize;
+ ppc_md.init_IRQ = lopec_init_IRQ;
+ ppc_md.get_irq = openpic_get_irq;
+
+ ppc_md.restart = lopec_restart;
+ ppc_md.power_off = lopec_power_off;
+ ppc_md.halt = lopec_halt;
+
+ ppc_md.setup_io_mappings = lopec_map_io;
+
+ ppc_md.time_init = todc_time_init;
+ ppc_md.set_rtc_time = todc_set_rtc_time;
+ ppc_md.get_rtc_time = todc_get_rtc_time;
+ ppc_md.calibrate_decr = todc_calibrate_decr;
+
+ ppc_md.nvram_read_val = todc_direct_read_val;
+ ppc_md.nvram_write_val = todc_direct_write_val;
+
+#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
+ ppc_ide_md.default_irq = lopec_ide_default_irq;
+ ppc_ide_md.default_io_base = lopec_ide_default_io_base;
+ ppc_ide_md.ide_init_hwif = lopec_ide_init_hwif_ports;
+#endif
+#ifdef CONFIG_SERIAL_TEXT_DEBUG
+ ppc_md.progress = gen550_progress;
+#endif
+}
diff --git a/arch/ppc/platforms/lopec.h b/arch/ppc/platforms/lopec.h
new file mode 100644
index 0000000..5490edb
--- /dev/null
+++ b/arch/ppc/platforms/lopec.h
@@ -0,0 +1,39 @@
+/*
+ * include/asm-ppc/lopec_serial.h
+ *
+ * Definitions for Motorola LoPEC board.
+ *
+ * Author: Dan Cox
+ * danc@mvista.com (or, alternately, source@mvista.com)
+ *
+ * 2001 (c) MontaVista, Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+
+#ifndef __H_LOPEC_SERIAL
+#define __H_LOPEC_SERIAL
+
+#define RS_TABLE_SIZE 3
+
+#define BASE_BAUD (1843200 / 16)
+
+#ifdef CONFIG_SERIAL_DETECT_IRQ
+#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF|ASYNC_SKIP_TEST|ASYNC_AUTO_IRQ)
+#else
+#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF|ASYNC_SKIP_TEST)
+#endif
+
+#define SERIAL_PORT_DFNS \
+ { 0, BASE_BAUD, 0xffe10000, 29, STD_COM_FLAGS, \
+ iomem_base: (u8 *) 0xffe10000, \
+ io_type: SERIAL_IO_MEM }, \
+ { 0, BASE_BAUD, 0xffe11000, 20, STD_COM_FLAGS, \
+ iomem_base: (u8 *) 0xffe11000, \
+ io_type: SERIAL_IO_MEM }, \
+ { 0, BASE_BAUD, 0xffe12000, 21, STD_COM_FLAGS, \
+ iomem_base: (u8 *) 0xffe12000, \
+ io_type: SERIAL_IO_MEM }
+
+#endif
diff --git a/arch/ppc/platforms/lwmon.h b/arch/ppc/platforms/lwmon.h
new file mode 100644
index 0000000..995bf51
--- /dev/null
+++ b/arch/ppc/platforms/lwmon.h
@@ -0,0 +1,60 @@
+/*
+ * Liebherr LWMON board specific definitions
+ *
+ * Copyright (c) 2001 Wolfgang Denk (wd@denx.de)
+ */
+
+#ifndef __MACH_LWMON_H
+#define __MACH_LWMON_H
+
+#include <linux/config.h>
+
+#include <asm/ppcboot.h>
+
+#define IMAP_ADDR 0xFFF00000 /* physical base address of IMMR area */
+#define IMAP_SIZE (64 * 1024) /* mapped size of IMMR area */
+
+/*-----------------------------------------------------------------------
+ * PCMCIA stuff
+ *-----------------------------------------------------------------------
+ *
+ */
+#define PCMCIA_MEM_SIZE ( 64 << 20 )
+
+#define MAX_HWIFS 1 /* overwrite default in include/asm-ppc/ide.h */
+
+/*
+ * Definitions for IDE0 Interface
+ */
+#define IDE0_BASE_OFFSET 0
+#define IDE0_DATA_REG_OFFSET (PCMCIA_MEM_SIZE + 0x320)
+#define IDE0_ERROR_REG_OFFSET (2 * PCMCIA_MEM_SIZE + 0x320 + 1)
+#define IDE0_NSECTOR_REG_OFFSET (2 * PCMCIA_MEM_SIZE + 0x320 + 2)
+#define IDE0_SECTOR_REG_OFFSET (2 * PCMCIA_MEM_SIZE + 0x320 + 3)
+#define IDE0_LCYL_REG_OFFSET (2 * PCMCIA_MEM_SIZE + 0x320 + 4)
+#define IDE0_HCYL_REG_OFFSET (2 * PCMCIA_MEM_SIZE + 0x320 + 5)
+#define IDE0_SELECT_REG_OFFSET (2 * PCMCIA_MEM_SIZE + 0x320 + 6)
+#define IDE0_STATUS_REG_OFFSET (2 * PCMCIA_MEM_SIZE + 0x320 + 7)
+#define IDE0_CONTROL_REG_OFFSET 0x0106
+#define IDE0_IRQ_REG_OFFSET 0x000A /* not used */
+
+#define IDE0_INTERRUPT 13
+
+/*
+ * Definitions for I2C devices
+ */
+#define I2C_ADDR_AUDIO 0x28 /* Audio volume control */
+#define I2C_ADDR_SYSMON 0x2E /* LM87 System Monitor */
+#define I2C_ADDR_RTC 0x51 /* PCF8563 RTC */
+#define I2C_ADDR_POWER_A 0x52 /* PCMCIA/USB power switch, channel A */
+#define I2C_ADDR_POWER_B 0x53 /* PCMCIA/USB power switch, channel B */
+#define I2C_ADDR_KEYBD 0x56 /* PIC LWE keyboard */
+#define I2C_ADDR_PICIO 0x57 /* PIC IO Expander */
+#define I2C_ADDR_EEPROM 0x58 /* EEPROM AT24C164 */
+
+
+/* We don't use the 8259.
+*/
+#define NR_8259_INTS 0
+
+#endif /* __MACH_LWMON_H */
diff --git a/arch/ppc/platforms/mbx.h b/arch/ppc/platforms/mbx.h
new file mode 100644
index 0000000..fe81ca4
--- /dev/null
+++ b/arch/ppc/platforms/mbx.h
@@ -0,0 +1,117 @@
+/*
+ * A collection of structures, addresses, and values associated with
+ * the Motorola MBX boards. This was originally created for the
+ * MBX860, and probably needs revisions for other boards (like the 821).
+ * When this file gets out of control, we can split it up into more
+ * meaningful pieces.
+ *
+ * Copyright (c) 1997 Dan Malek (dmalek@jlc.net)
+ */
+#ifdef __KERNEL__
+#ifndef __MACH_MBX_DEFS
+#define __MACH_MBX_DEFS
+
+#ifndef __ASSEMBLY__
+/* A Board Information structure that is given to a program when
+ * EPPC-Bug starts it up.
+ */
+typedef struct bd_info {
+ unsigned int bi_tag; /* Should be 0x42444944 "BDID" */
+ unsigned int bi_size; /* Size of this structure */
+ unsigned int bi_revision; /* revision of this structure */
+ unsigned int bi_bdate; /* EPPCbug date, i.e. 0x11061997 */
+ unsigned int bi_memstart; /* Memory start address */
+ unsigned int bi_memsize; /* Memory (end) size in bytes */
+ unsigned int bi_intfreq; /* Internal Freq, in Hz */
+ unsigned int bi_busfreq; /* Bus Freq, in Hz */
+ unsigned int bi_clun; /* Boot device controller */
+ unsigned int bi_dlun; /* Boot device logical dev */
+
+ /* These fields are not part of the board information structure
+ * provided by the boot rom. They are filled in by embed_config.c
+ * so we have the information consistent with other platforms.
+ */
+ unsigned char bi_enetaddr[6];
+ unsigned int bi_baudrate;
+} bd_t;
+
+/* Memory map for the MBX as configured by EPPC-Bug. We could reprogram
+ * The SIU and PCI bridge, and try to use larger MMU pages, but the
+ * performance gain is not measureable and it certainly complicates the
+ * generic MMU model.
+ *
+ * In a effort to minimize memory usage for embedded applications, any
+ * PCI driver or ISA driver must request or map the region required by
+ * the device. For convenience (and since we can map up to 4 Mbytes with
+ * a single page table page), the MMU initialization will map the
+ * NVRAM, Status/Control registers, CPM Dual Port RAM, and the PCI
+ * Bridge CSRs 1:1 into the kernel address space.
+ */
+#define PCI_ISA_IO_ADDR ((unsigned)0x80000000)
+#define PCI_ISA_IO_SIZE ((uint)(512 * 1024 * 1024))
+#define PCI_IDE_ADDR ((unsigned)0x81000000)
+#define PCI_ISA_MEM_ADDR ((unsigned)0xc0000000)
+#define PCI_ISA_MEM_SIZE ((uint)(512 * 1024 * 1024))
+#define PCMCIA_MEM_ADDR ((uint)0xe0000000)
+#define PCMCIA_MEM_SIZE ((uint)(64 * 1024 * 1024))
+#define PCMCIA_DMA_ADDR ((uint)0xe4000000)
+#define PCMCIA_DMA_SIZE ((uint)(64 * 1024 * 1024))
+#define PCMCIA_ATTRB_ADDR ((uint)0xe8000000)
+#define PCMCIA_ATTRB_SIZE ((uint)(64 * 1024 * 1024))
+#define PCMCIA_IO_ADDR ((uint)0xec000000)
+#define PCMCIA_IO_SIZE ((uint)(64 * 1024 * 1024))
+#define NVRAM_ADDR ((uint)0xfa000000)
+#define NVRAM_SIZE ((uint)(1 * 1024 * 1024))
+#define MBX_CSR_ADDR ((uint)0xfa100000)
+#define MBX_CSR_SIZE ((uint)(1 * 1024 * 1024))
+#define IMAP_ADDR ((uint)0xfa200000)
+#define IMAP_SIZE ((uint)(64 * 1024))
+#define PCI_CSR_ADDR ((uint)0xfa210000)
+#define PCI_CSR_SIZE ((uint)(64 * 1024))
+
+/* Map additional physical space into well known virtual addresses. Due
+ * to virtual address mapping, these physical addresses are not accessible
+ * in a 1:1 virtual to physical mapping.
+ */
+#define ISA_IO_VIRT_ADDR ((uint)0xfa220000)
+#define ISA_IO_VIRT_SIZE ((uint)64 * 1024)
+
+/* Interrupt assignments.
+ * These are defined (and fixed) by the MBX hardware implementation.
+ */
+#define POWER_FAIL_INT SIU_IRQ0 /* Power fail */
+#define TEMP_HILO_INT SIU_IRQ1 /* Temperature sensor */
+#define QSPAN_INT SIU_IRQ2 /* PCI Bridge (DMA CTLR?) */
+#define ISA_BRIDGE_INT SIU_IRQ3 /* All those PC things */
+#define COMM_L_INT SIU_IRQ6 /* MBX Comm expansion connector pin */
+#define STOP_ABRT_INT SIU_IRQ7 /* Stop/Abort header pin */
+
+/* CPM Ethernet through SCCx.
+ *
+ * Bits in parallel I/O port registers that have to be set/cleared
+ * to configure the pins for SCC1 use. The TCLK and RCLK seem unique
+ * to the MBX860 board. Any two of the four available clocks could be
+ * used, and the MPC860 cookbook manual has an example using different
+ * clock pins.
+ */
+#define PA_ENET_RXD ((ushort)0x0001)
+#define PA_ENET_TXD ((ushort)0x0002)
+#define PA_ENET_TCLK ((ushort)0x0200)
+#define PA_ENET_RCLK ((ushort)0x0800)
+#define PC_ENET_TENA ((ushort)0x0001)
+#define PC_ENET_CLSN ((ushort)0x0010)
+#define PC_ENET_RENA ((ushort)0x0020)
+
+/* Control bits in the SICR to route TCLK (CLK2) and RCLK (CLK4) to
+ * SCC1. Also, make sure GR1 (bit 24) and SC1 (bit 25) are zero.
+ */
+#define SICR_ENET_MASK ((uint)0x000000ff)
+#define SICR_ENET_CLKRT ((uint)0x0000003d)
+
+/* The MBX uses the 8259.
+*/
+#define NR_8259_INTS 16
+
+#endif /* !__ASSEMBLY__ */
+#endif /* __MACH_MBX_DEFS */
+#endif /* __KERNEL__ */
diff --git a/arch/ppc/platforms/mcpn765.c b/arch/ppc/platforms/mcpn765.c
new file mode 100644
index 0000000..e88d294
--- /dev/null
+++ b/arch/ppc/platforms/mcpn765.c
@@ -0,0 +1,527 @@
+/*
+ * arch/ppc/platforms/mcpn765.c
+ *
+ * Board setup routines for the Motorola MCG MCPN765 cPCI Board.
+ *
+ * Author: Mark A. Greer
+ * mgreer@mvista.com
+ *
+ * Modified by Randy Vinson (rvinson@mvista.com)
+ *
+ * 2001-2002 (c) MontaVista, Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+
+/*
+ * This file adds support for the Motorola MCG MCPN765.
+ */
+#include <linux/config.h>
+#include <linux/stddef.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/reboot.h>
+#include <linux/pci.h>
+#include <linux/kdev_t.h>
+#include <linux/major.h>
+#include <linux/initrd.h>
+#include <linux/console.h>
+#include <linux/delay.h>
+#include <linux/irq.h>
+#include <linux/seq_file.h>
+#include <linux/root_dev.h>
+#include <linux/serial.h>
+#include <linux/tty.h> /* for linux/serial_core.h */
+#include <linux/serial_core.h>
+#include <linux/slab.h>
+
+#include <asm/system.h>
+#include <asm/pgtable.h>
+#include <asm/page.h>
+#include <asm/time.h>
+#include <asm/dma.h>
+#include <asm/byteorder.h>
+#include <asm/io.h>
+#include <asm/machdep.h>
+#include <asm/prom.h>
+#include <asm/smp.h>
+#include <asm/open_pic.h>
+#include <asm/i8259.h>
+#include <asm/todc.h>
+#include <asm/pci-bridge.h>
+#include <asm/irq.h>
+#include <asm/uaccess.h>
+#include <asm/bootinfo.h>
+#include <asm/hawk.h>
+#include <asm/kgdb.h>
+
+#include "mcpn765.h"
+
+static u_char mcpn765_openpic_initsenses[] __initdata = {
+ (IRQ_SENSE_EDGE | IRQ_POLARITY_POSITIVE),/* 16: i8259 cascade */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),/* 17: COM1,2,3,4 */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),/* 18: Enet 1 (front) */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),/* 19: HAWK WDT XXXX */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),/* 20: 21554 bridge */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),/* 21: cPCI INTA# */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),/* 22: cPCI INTB# */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),/* 23: cPCI INTC# */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),/* 24: cPCI INTD# */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),/* 25: PMC1 INTA#,PMC2 INTB#*/
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),/* 26: PMC1 INTB#,PMC2 INTC#*/
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),/* 27: PMC1 INTC#,PMC2 INTD#*/
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),/* 28: PMC1 INTD#,PMC2 INTA#*/
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),/* 29: Enet 2 (J3) */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),/* 30: Abort Switch */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),/* 31: RTC Alarm */
+};
+
+extern void mcpn765_set_VIA_IDE_native(void);
+
+extern u_int openpic_irq(void);
+extern char cmd_line[];
+
+extern void gen550_progress(char *, unsigned short);
+extern void gen550_init(int, struct uart_port *);
+
+int use_of_interrupt_tree = 0;
+
+static void mcpn765_halt(void);
+
+TODC_ALLOC();
+
+/*
+ * Motorola MCG MCPN765 interrupt routing.
+ */
+static inline int
+mcpn765_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin)
+{
+ static char pci_irq_table[][4] =
+ /*
+ * PCI IDSEL/INTPIN->INTLINE
+ * A B C D
+ */
+ {
+ { 14, 0, 0, 0 }, /* IDSEL 11 - have to manually set */
+ { 0, 0, 0, 0 }, /* IDSEL 12 - unused */
+ { 0, 0, 0, 0 }, /* IDSEL 13 - unused */
+ { 18, 0, 0, 0 }, /* IDSEL 14 - Enet 0 */
+ { 0, 0, 0, 0 }, /* IDSEL 15 - unused */
+ { 25, 26, 27, 28 }, /* IDSEL 16 - PMC Slot 1 */
+ { 28, 25, 26, 27 }, /* IDSEL 17 - PMC Slot 2 */
+ { 0, 0, 0, 0 }, /* IDSEL 18 - PMC 2B Connector XXXX */
+ { 29, 0, 0, 0 }, /* IDSEL 19 - Enet 1 */
+ { 20, 0, 0, 0 }, /* IDSEL 20 - 21554 cPCI bridge */
+ };
+
+ const long min_idsel = 11, max_idsel = 20, irqs_per_slot = 4;
+ return PCI_IRQ_TABLE_LOOKUP;
+}
+
+void __init
+mcpn765_set_VIA_IDE_legacy(void)
+{
+ unsigned short vend, dev;
+
+ early_read_config_word(0, 0, PCI_DEVFN(0xb, 1), PCI_VENDOR_ID, &vend);
+ early_read_config_word(0, 0, PCI_DEVFN(0xb, 1), PCI_DEVICE_ID, &dev);
+
+ if ((vend == PCI_VENDOR_ID_VIA) &&
+ (dev == PCI_DEVICE_ID_VIA_82C586_1)) {
+
+ unsigned char temp;
+
+ /* put back original "standard" port base addresses */
+ early_write_config_dword(0, 0, PCI_DEVFN(0xb, 1),
+ PCI_BASE_ADDRESS_0, 0x1f1);
+ early_write_config_dword(0, 0, PCI_DEVFN(0xb, 1),
+ PCI_BASE_ADDRESS_1, 0x3f5);
+ early_write_config_dword(0, 0, PCI_DEVFN(0xb, 1),
+ PCI_BASE_ADDRESS_2, 0x171);
+ early_write_config_dword(0, 0, PCI_DEVFN(0xb, 1),
+ PCI_BASE_ADDRESS_3, 0x375);
+ early_write_config_dword(0, 0, PCI_DEVFN(0xb, 1),
+ PCI_BASE_ADDRESS_4, 0xcc01);
+
+ /* put into legacy mode */
+ early_read_config_byte(0, 0, PCI_DEVFN(0xb, 1), PCI_CLASS_PROG,
+ &temp);
+ temp &= ~0x05;
+ early_write_config_byte(0, 0, PCI_DEVFN(0xb, 1), PCI_CLASS_PROG,
+ temp);
+ }
+}
+
+void
+mcpn765_set_VIA_IDE_native(void)
+{
+ unsigned short vend, dev;
+
+ early_read_config_word(0, 0, PCI_DEVFN(0xb, 1), PCI_VENDOR_ID, &vend);
+ early_read_config_word(0, 0, PCI_DEVFN(0xb, 1), PCI_DEVICE_ID, &dev);
+
+ if ((vend == PCI_VENDOR_ID_VIA) &&
+ (dev == PCI_DEVICE_ID_VIA_82C586_1)) {
+
+ unsigned char temp;
+
+ /* put into native mode */
+ early_read_config_byte(0, 0, PCI_DEVFN(0xb, 1), PCI_CLASS_PROG,
+ &temp);
+ temp |= 0x05;
+ early_write_config_byte(0, 0, PCI_DEVFN(0xb, 1), PCI_CLASS_PROG,
+ temp);
+ }
+}
+
+/*
+ * Initialize the VIA 82c586b.
+ */
+static void __init
+mcpn765_setup_via_82c586b(void)
+{
+ struct pci_dev *dev;
+ u_char c;
+
+ if ((dev = pci_get_device(PCI_VENDOR_ID_VIA,
+ PCI_DEVICE_ID_VIA_82C586_0,
+ NULL)) == NULL) {
+ printk("No VIA ISA bridge found\n");
+ mcpn765_halt();
+ /* NOTREACHED */
+ }
+
+ /*
+ * If the firmware left the EISA 4d0/4d1 ports enabled, make sure
+ * IRQ 14 is set for edge.
+ */
+ pci_read_config_byte(dev, 0x47, &c);
+
+ if (c & (1<<5)) {
+ c = inb(0x4d1);
+ c &= ~(1<<6);
+ outb(c, 0x4d1);
+ }
+
+ /* Disable PNP IRQ routing since we use the Hawk's MPIC */
+ pci_write_config_dword(dev, 0x54, 0);
+ pci_write_config_byte(dev, 0x58, 0);
+
+ pci_dev_put(dev);
+ if ((dev = pci_get_device(PCI_VENDOR_ID_VIA,
+ PCI_DEVICE_ID_VIA_82C586_1,
+ NULL)) == NULL) {
+ printk("No VIA ISA bridge found\n");
+ mcpn765_halt();
+ /* NOTREACHED */
+ }
+
+ /*
+ * PPCBug doesn't set the enable bits for the IDE device.
+ * Turn them on now.
+ */
+ pci_read_config_byte(dev, 0x40, &c);
+ c |= 0x03;
+ pci_write_config_byte(dev, 0x40, c);
+ pci_dev_put(dev);
+
+ return;
+}
+
+void __init
+mcpn765_pcibios_fixup(void)
+{
+ /* Do MCPN765 board specific initialization. */
+ mcpn765_setup_via_82c586b();
+}
+
+void __init
+mcpn765_find_bridges(void)
+{
+ struct pci_controller *hose;
+
+ hose = pcibios_alloc_controller();
+
+ if (!hose)
+ return;
+
+ hose->first_busno = 0;
+ hose->last_busno = 0xff;
+ hose->pci_mem_offset = MCPN765_PCI_PHY_MEM_OFFSET;
+
+ pci_init_resource(&hose->io_resource,
+ MCPN765_PCI_IO_START,
+ MCPN765_PCI_IO_END,
+ IORESOURCE_IO,
+ "PCI host bridge");
+
+ pci_init_resource(&hose->mem_resources[0],
+ MCPN765_PCI_MEM_START,
+ MCPN765_PCI_MEM_END,
+ IORESOURCE_MEM,
+ "PCI host bridge");
+
+ hose->io_space.start = MCPN765_PCI_IO_START;
+ hose->io_space.end = MCPN765_PCI_IO_END;
+ hose->mem_space.start = MCPN765_PCI_MEM_START;
+ hose->mem_space.end = MCPN765_PCI_MEM_END - HAWK_MPIC_SIZE;
+
+ if (hawk_init(hose,
+ MCPN765_HAWK_PPC_REG_BASE,
+ MCPN765_PROC_PCI_MEM_START,
+ MCPN765_PROC_PCI_MEM_END - HAWK_MPIC_SIZE,
+ MCPN765_PROC_PCI_IO_START,
+ MCPN765_PROC_PCI_IO_END,
+ MCPN765_PCI_MEM_END - HAWK_MPIC_SIZE + 1) != 0) {
+ printk("Could not initialize HAWK bridge\n");
+ }
+
+ /* VIA IDE BAR decoders are only 16-bits wide. PCI Auto Config
+ * will reassign the bars outside of 16-bit I/O space, which will
+ * "break" things. To prevent this, we'll set the IDE chip into
+ * legacy mode and seed the bars with their legacy addresses (in 16-bit
+ * I/O space). The Auto Config code will skip the IDE contoller in
+ * legacy mode, so our bar values will stick.
+ */
+ mcpn765_set_VIA_IDE_legacy();
+
+ hose->last_busno = pciauto_bus_scan(hose, hose->first_busno);
+
+ /* Now that we've got 16-bit addresses in the bars, we can switch the
+ * IDE controller back into native mode so we can do "modern" resource
+ * and interrupt management.
+ */
+ mcpn765_set_VIA_IDE_native();
+
+ ppc_md.pcibios_fixup = mcpn765_pcibios_fixup;
+ ppc_md.pcibios_fixup_bus = NULL;
+ ppc_md.pci_swizzle = common_swizzle;
+ ppc_md.pci_map_irq = mcpn765_map_irq;
+
+ return;
+}
+static void __init
+mcpn765_setup_arch(void)
+{
+ struct pci_controller *hose;
+
+ if ( ppc_md.progress )
+ ppc_md.progress("mcpn765_setup_arch: enter", 0);
+
+ loops_per_jiffy = 50000000 / HZ;
+
+#ifdef CONFIG_BLK_DEV_INITRD
+ if (initrd_start)
+ ROOT_DEV = Root_RAM0;
+ else
+#endif
+#ifdef CONFIG_ROOT_NFS
+ ROOT_DEV = Root_NFS;
+#else
+ ROOT_DEV = Root_SDA2;
+#endif
+
+ if ( ppc_md.progress )
+ ppc_md.progress("mcpn765_setup_arch: find_bridges", 0);
+
+ /* Lookup PCI host bridges */
+ mcpn765_find_bridges();
+
+ hose = pci_bus_to_hose(0);
+ isa_io_base = (ulong)hose->io_base_virt;
+
+ TODC_INIT(TODC_TYPE_MK48T37,
+ (MCPN765_PHYS_NVRAM_AS0 - isa_io_base),
+ (MCPN765_PHYS_NVRAM_AS1 - isa_io_base),
+ (MCPN765_PHYS_NVRAM_DATA - isa_io_base),
+ 8);
+
+ OpenPIC_InitSenses = mcpn765_openpic_initsenses;
+ OpenPIC_NumInitSenses = sizeof(mcpn765_openpic_initsenses);
+
+ printk("Motorola MCG MCPN765 cPCI Non-System Board\n");
+ printk("MCPN765 port (MontaVista Software, Inc. (source@mvista.com))\n");
+
+ if ( ppc_md.progress )
+ ppc_md.progress("mcpn765_setup_arch: exit", 0);
+
+ return;
+}
+
+static void __init
+mcpn765_init2(void)
+{
+
+ request_region(0x00,0x20,"dma1");
+ request_region(0x20,0x20,"pic1");
+ request_region(0x40,0x20,"timer");
+ request_region(0x80,0x10,"dma page reg");
+ request_region(0xa0,0x20,"pic2");
+ request_region(0xc0,0x20,"dma2");
+
+ return;
+}
+
+/*
+ * Interrupt setup and service.
+ * Have MPIC on HAWK and cascaded 8259s on VIA 82586 cascaded to MPIC.
+ */
+static void __init
+mcpn765_init_IRQ(void)
+{
+ int i;
+
+ if ( ppc_md.progress )
+ ppc_md.progress("init_irq: enter", 0);
+
+ openpic_init(NUM_8259_INTERRUPTS);
+ openpic_hookup_cascade(NUM_8259_INTERRUPTS, "82c59 cascade",
+ i8259_irq);
+
+ for(i=0; i < NUM_8259_INTERRUPTS; i++)
+ irq_desc[i].handler = &i8259_pic;
+
+ i8259_init(0);
+
+ if ( ppc_md.progress )
+ ppc_md.progress("init_irq: exit", 0);
+
+ return;
+}
+
+static u32
+mcpn765_irq_canonicalize(u32 irq)
+{
+ if (irq == 2)
+ return 9;
+ else
+ return irq;
+}
+
+static unsigned long __init
+mcpn765_find_end_of_memory(void)
+{
+ return hawk_get_mem_size(MCPN765_HAWK_SMC_BASE);
+}
+
+static void __init
+mcpn765_map_io(void)
+{
+ io_block_mapping(0xfe800000, 0xfe800000, 0x00800000, _PAGE_IO);
+}
+
+static void
+mcpn765_reset_board(void)
+{
+ local_irq_disable();
+
+ /* set VIA IDE controller into native mode */
+ mcpn765_set_VIA_IDE_native();
+
+ /* Set exception prefix high - to the firmware */
+ _nmask_and_or_msr(0, MSR_IP);
+
+ out_8((u_char *)MCPN765_BOARD_MODRST_REG, 0x01);
+
+ return;
+}
+
+static void
+mcpn765_restart(char *cmd)
+{
+ volatile ulong i = 10000000;
+
+ mcpn765_reset_board();
+
+ while (i-- > 0);
+ panic("restart failed\n");
+}
+
+static void
+mcpn765_power_off(void)
+{
+ mcpn765_halt();
+ /* NOTREACHED */
+}
+
+static void
+mcpn765_halt(void)
+{
+ local_irq_disable();
+ while (1);
+ /* NOTREACHED */
+}
+
+static int
+mcpn765_show_cpuinfo(struct seq_file *m)
+{
+ seq_printf(m, "vendor\t\t: Motorola MCG\n");
+ seq_printf(m, "machine\t\t: MCPN765\n");
+
+ return 0;
+}
+
+/*
+ * Set BAT 3 to map 0xf0000000 to end of physical memory space.
+ */
+static __inline__ void
+mcpn765_set_bat(void)
+{
+ mb();
+ mtspr(SPRN_DBAT1U, 0xfe8000fe);
+ mtspr(SPRN_DBAT1L, 0xfe80002a);
+ mb();
+}
+
+void __init
+platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
+ unsigned long r6, unsigned long r7)
+{
+ parse_bootinfo(find_bootinfo());
+
+ /* Map in board regs, etc. */
+ mcpn765_set_bat();
+
+ isa_mem_base = MCPN765_ISA_MEM_BASE;
+ pci_dram_offset = MCPN765_PCI_DRAM_OFFSET;
+ ISA_DMA_THRESHOLD = 0x00ffffff;
+ DMA_MODE_READ = 0x44;
+ DMA_MODE_WRITE = 0x48;
+
+ ppc_md.setup_arch = mcpn765_setup_arch;
+ ppc_md.show_cpuinfo = mcpn765_show_cpuinfo;
+ ppc_md.irq_canonicalize = mcpn765_irq_canonicalize;
+ ppc_md.init_IRQ = mcpn765_init_IRQ;
+ ppc_md.get_irq = openpic_get_irq;
+ ppc_md.init = mcpn765_init2;
+
+ ppc_md.restart = mcpn765_restart;
+ ppc_md.power_off = mcpn765_power_off;
+ ppc_md.halt = mcpn765_halt;
+
+ ppc_md.find_end_of_memory = mcpn765_find_end_of_memory;
+ ppc_md.setup_io_mappings = mcpn765_map_io;
+
+ ppc_md.time_init = todc_time_init;
+ ppc_md.set_rtc_time = todc_set_rtc_time;
+ ppc_md.get_rtc_time = todc_get_rtc_time;
+ ppc_md.calibrate_decr = todc_calibrate_decr;
+
+ ppc_md.nvram_read_val = todc_m48txx_read_val;
+ ppc_md.nvram_write_val = todc_m48txx_write_val;
+
+ ppc_md.heartbeat = NULL;
+ ppc_md.heartbeat_reset = 0;
+ ppc_md.heartbeat_count = 0;
+
+#ifdef CONFIG_SERIAL_TEXT_DEBUG
+ ppc_md.progress = gen550_progress;
+#endif
+#ifdef CONFIG_KGDB
+ ppc_md.kgdb_map_scc = gen550_kgdb_map_scc;
+#endif
+
+ return;
+}
diff --git a/arch/ppc/platforms/mcpn765.h b/arch/ppc/platforms/mcpn765.h
new file mode 100644
index 0000000..4d35eca
--- /dev/null
+++ b/arch/ppc/platforms/mcpn765.h
@@ -0,0 +1,122 @@
+/*
+ * arch/ppc/platforms/mcpn765.h
+ *
+ * Definitions for Motorola MCG MCPN765 cPCI Board.
+ *
+ * Author: Mark A. Greer
+ * mgreer@mvista.com
+ *
+ * 2001-2004 (c) MontaVista, Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+
+/*
+ * From Processor to PCI:
+ * PCI Mem Space: 0x80000000 - 0xc0000000 -> 0x80000000 - 0xc0000000 (1 GB)
+ * PCI I/O Space: 0xfd800000 - 0xfe000000 -> 0x00000000 - 0x00800000 (8 MB)
+ * Note: Must skip 0xfe000000-0xfe400000 for CONFIG_HIGHMEM/PKMAP area
+ * MPIC in PCI Mem Space: 0xfe800000 - 0xfe830000 (not all used by MPIC)
+ *
+ * From PCI to Processor:
+ * System Memory: 0x00000000 -> 0x00000000
+ */
+
+#ifndef __PPC_PLATFORMS_MCPN765_H
+#define __PPC_PLATFORMS_MCPN765_H
+#include <linux/config.h>
+
+/* PCI Memory space mapping info */
+#define MCPN765_PCI_MEM_SIZE 0x40000000U
+#define MCPN765_PROC_PCI_MEM_START 0x80000000U
+#define MCPN765_PROC_PCI_MEM_END (MCPN765_PROC_PCI_MEM_START + \
+ MCPN765_PCI_MEM_SIZE - 1)
+#define MCPN765_PCI_MEM_START 0x80000000U
+#define MCPN765_PCI_MEM_END (MCPN765_PCI_MEM_START + \
+ MCPN765_PCI_MEM_SIZE - 1)
+
+/* PCI I/O space mapping info */
+#define MCPN765_PCI_IO_SIZE 0x00800000U
+#define MCPN765_PROC_PCI_IO_START 0xfd800000U
+#define MCPN765_PROC_PCI_IO_END (MCPN765_PROC_PCI_IO_START + \
+ MCPN765_PCI_IO_SIZE - 1)
+#define MCPN765_PCI_IO_START 0x00000000U
+#define MCPN765_PCI_IO_END (MCPN765_PCI_IO_START + \
+ MCPN765_PCI_IO_SIZE - 1)
+
+/* System memory mapping info */
+#define MCPN765_PCI_DRAM_OFFSET 0x00000000U
+#define MCPN765_PCI_PHY_MEM_OFFSET 0x00000000U
+
+#define MCPN765_ISA_MEM_BASE 0x00000000U
+#define MCPN765_ISA_IO_BASE MCPN765_PROC_PCI_IO_START
+
+/* Define base addresses for important sets of registers */
+#define MCPN765_HAWK_MPIC_BASE 0xfe800000U
+#define MCPN765_HAWK_SMC_BASE 0xfef80000U
+#define MCPN765_HAWK_PPC_REG_BASE 0xfeff0000U
+
+/* Define MCPN765 board register addresses. */
+#define MCPN765_BOARD_STATUS_REG 0xfef88080U
+#define MCPN765_BOARD_MODFAIL_REG 0xfef88090U
+#define MCPN765_BOARD_MODRST_REG 0xfef880a0U
+#define MCPN765_BOARD_TBEN_REG 0xfef880c0U
+#define MCPN765_BOARD_GEOGRAPHICAL_REG 0xfef880e8U
+#define MCPN765_BOARD_EXT_FEATURE_REG 0xfef880f0U
+#define MCPN765_BOARD_LAST_RESET_REG 0xfef880f8U
+
+/* Defines for UART */
+
+/* Define the UART base addresses */
+#define MCPN765_SERIAL_1 0xfef88000
+#define MCPN765_SERIAL_2 0xfef88200
+#define MCPN765_SERIAL_3 0xfef88400
+#define MCPN765_SERIAL_4 0xfef88600
+
+#ifdef CONFIG_SERIAL_MANY_PORTS
+#define RS_TABLE_SIZE 64
+#else
+#define RS_TABLE_SIZE 4
+#endif
+
+/* Rate for the 1.8432 Mhz clock for the onboard serial chip */
+#define BASE_BAUD ( 1843200 / 16 )
+#define UART_CLK 1843200
+
+#ifdef CONFIG_SERIAL_DETECT_IRQ
+#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF|ASYNC_SKIP_TEST|ASYNC_AUTO_IRQ)
+#else
+#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF|ASYNC_SKIP_TEST)
+#endif
+
+/* All UART IRQ's are wire-OR'd to IRQ 17 */
+#define STD_SERIAL_PORT_DFNS \
+ { 0, BASE_BAUD, MCPN765_SERIAL_1, 17, STD_COM_FLAGS, /* ttyS0 */\
+ iomem_base: (u8 *)MCPN765_SERIAL_1, \
+ iomem_reg_shift: 4, \
+ io_type: SERIAL_IO_MEM }, \
+ { 0, BASE_BAUD, MCPN765_SERIAL_2, 17, STD_COM_FLAGS, /* ttyS1 */\
+ iomem_base: (u8 *)MCPN765_SERIAL_2, \
+ iomem_reg_shift: 4, \
+ io_type: SERIAL_IO_MEM }, \
+ { 0, BASE_BAUD, MCPN765_SERIAL_3, 17, STD_COM_FLAGS, /* ttyS2 */\
+ iomem_base: (u8 *)MCPN765_SERIAL_3, \
+ iomem_reg_shift: 4, \
+ io_type: SERIAL_IO_MEM }, \
+ { 0, BASE_BAUD, MCPN765_SERIAL_4, 17, STD_COM_FLAGS, /* ttyS3 */\
+ iomem_base: (u8 *)MCPN765_SERIAL_4, \
+ iomem_reg_shift: 4, \
+ io_type: SERIAL_IO_MEM },
+
+#define SERIAL_PORT_DFNS \
+ STD_SERIAL_PORT_DFNS
+
+/* Define the NVRAM/RTC address strobe & data registers */
+#define MCPN765_PHYS_NVRAM_AS0 0xfef880c8U
+#define MCPN765_PHYS_NVRAM_AS1 0xfef880d0U
+#define MCPN765_PHYS_NVRAM_DATA 0xfef880d8U
+
+extern void mcpn765_find_bridges(void);
+
+#endif /* __PPC_PLATFORMS_MCPN765_H */
diff --git a/arch/ppc/platforms/mpc5200.c b/arch/ppc/platforms/mpc5200.c
new file mode 100644
index 0000000..a58db43
--- /dev/null
+++ b/arch/ppc/platforms/mpc5200.c
@@ -0,0 +1,53 @@
+/*
+ * arch/ppc/platforms/mpc5200.c
+ *
+ * OCP Definitions for the boards based on MPC5200 processor. Contains
+ * definitions for every common peripherals. (Mostly all but PSCs)
+ *
+ * Maintainer : Sylvain Munaut <tnt@246tNt.com>
+ *
+ * Copyright 2004 Sylvain Munaut <tnt@246tNt.com>
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2. This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ */
+
+#include <asm/ocp.h>
+#include <asm/mpc52xx.h>
+
+
+static struct ocp_fs_i2c_data mpc5200_i2c_def = {
+ .flags = FS_I2C_CLOCK_5200,
+};
+
+
+/* Here is the core_ocp struct.
+ * With all the devices common to all board. Even if port multiplexing is
+ * not setup for them (if the user don't want them, just don't select the
+ * config option). The potentially conflicting devices (like PSCs) goes in
+ * board specific file.
+ */
+struct ocp_def core_ocp[] = {
+ {
+ .vendor = OCP_VENDOR_FREESCALE,
+ .function = OCP_FUNC_IIC,
+ .index = 0,
+ .paddr = MPC52xx_I2C1,
+ .irq = OCP_IRQ_NA, /* MPC52xx_IRQ_I2C1 - Buggy */
+ .pm = OCP_CPM_NA,
+ .additions = &mpc5200_i2c_def,
+ },
+ {
+ .vendor = OCP_VENDOR_FREESCALE,
+ .function = OCP_FUNC_IIC,
+ .index = 1,
+ .paddr = MPC52xx_I2C2,
+ .irq = OCP_IRQ_NA, /* MPC52xx_IRQ_I2C2 - Buggy */
+ .pm = OCP_CPM_NA,
+ .additions = &mpc5200_i2c_def,
+ },
+ { /* Terminating entry */
+ .vendor = OCP_VENDOR_INVALID
+ }
+};
diff --git a/arch/ppc/platforms/mvme5100.c b/arch/ppc/platforms/mvme5100.c
new file mode 100644
index 0000000..b292b44
--- /dev/null
+++ b/arch/ppc/platforms/mvme5100.c
@@ -0,0 +1,349 @@
+/*
+ * arch/ppc/platforms/mvme5100.c
+ *
+ * Board setup routines for the Motorola MVME5100.
+ *
+ * Author: Matt Porter <mporter@mvista.com>
+ *
+ * 2001-2004 (c) MontaVista, Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+
+#include <linux/config.h>
+#include <linux/stddef.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/pci.h>
+#include <linux/initrd.h>
+#include <linux/console.h>
+#include <linux/delay.h>
+#include <linux/irq.h>
+#include <linux/ide.h>
+#include <linux/seq_file.h>
+#include <linux/kdev_t.h>
+#include <linux/root_dev.h>
+
+#include <asm/system.h>
+#include <asm/pgtable.h>
+#include <asm/page.h>
+#include <asm/dma.h>
+#include <asm/io.h>
+#include <asm/machdep.h>
+#include <asm/open_pic.h>
+#include <asm/i8259.h>
+#include <asm/todc.h>
+#include <asm/pci-bridge.h>
+#include <asm/bootinfo.h>
+#include <asm/hawk.h>
+
+#include <platforms/pplus.h>
+#include <platforms/mvme5100.h>
+
+static u_char mvme5100_openpic_initsenses[16] __initdata = {
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* i8259 cascade */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* TL16C550 UART 1,2 */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* Enet1 front panel or P2 */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* Hawk Watchdog 1,2 */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* DS1621 thermal alarm */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* Universe II LINT0# */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* Universe II LINT1# */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* Universe II LINT2# */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* Universe II LINT3# */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* PMC1 INTA#, PMC2 INTB# */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* PMC1 INTB#, PMC2 INTC# */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* PMC1 INTC#, PMC2 INTD# */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* PMC1 INTD#, PMC2 INTA# */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* Enet 2 (front panel) */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* Abort Switch */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* RTC Alarm */
+};
+
+static inline int
+mvme5100_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin)
+{
+ int irq;
+
+ static char pci_irq_table[][4] =
+ /*
+ * PCI IDSEL/INTPIN->INTLINE
+ * A B C D
+ */
+ {
+ { 0, 0, 0, 0 }, /* IDSEL 11 - Winbond */
+ { 0, 0, 0, 0 }, /* IDSEL 12 - unused */
+ { 21, 22, 23, 24 }, /* IDSEL 13 - Universe II */
+ { 18, 0, 0, 0 }, /* IDSEL 14 - Enet 1 */
+ { 0, 0, 0, 0 }, /* IDSEL 15 - unused */
+ { 25, 26, 27, 28 }, /* IDSEL 16 - PMC Slot 1 */
+ { 28, 25, 26, 27 }, /* IDSEL 17 - PMC Slot 2 */
+ { 0, 0, 0, 0 }, /* IDSEL 18 - unused */
+ { 29, 0, 0, 0 }, /* IDSEL 19 - Enet 2 */
+ { 0, 0, 0, 0 }, /* IDSEL 20 - PMCSPAN */
+ };
+
+ const long min_idsel = 11, max_idsel = 20, irqs_per_slot = 4;
+ irq = PCI_IRQ_TABLE_LOOKUP;
+ /* If lookup is zero, always return 0 */
+ if (!irq)
+ return 0;
+ else
+#ifdef CONFIG_MVME5100_IPMC761_PRESENT
+ /* If IPMC761 present, return table value */
+ return irq;
+#else
+ /* If IPMC761 not present, we don't have an i8259 so adjust */
+ return (irq - NUM_8259_INTERRUPTS);
+#endif
+}
+
+static void
+mvme5100_pcibios_fixup_resources(struct pci_dev *dev)
+{
+ int i;
+
+ if ((dev->vendor == PCI_VENDOR_ID_MOTOROLA) &&
+ (dev->device == PCI_DEVICE_ID_MOTOROLA_HAWK))
+ for (i=0; i<DEVICE_COUNT_RESOURCE; i++)
+ {
+ dev->resource[i].start = 0;
+ dev->resource[i].end = 0;
+ }
+}
+
+static void __init
+mvme5100_setup_bridge(void)
+{
+ struct pci_controller* hose;
+
+ hose = pcibios_alloc_controller();
+
+ if (!hose)
+ return;
+
+ hose->first_busno = 0;
+ hose->last_busno = 0xff;
+ hose->pci_mem_offset = MVME5100_PCI_MEM_OFFSET;
+
+ pci_init_resource(&hose->io_resource, MVME5100_PCI_LOWER_IO,
+ MVME5100_PCI_UPPER_IO, IORESOURCE_IO,
+ "PCI host bridge");
+
+ pci_init_resource(&hose->mem_resources[0], MVME5100_PCI_LOWER_MEM,
+ MVME5100_PCI_UPPER_MEM, IORESOURCE_MEM,
+ "PCI host bridge");
+
+ hose->io_space.start = MVME5100_PCI_LOWER_IO;
+ hose->io_space.end = MVME5100_PCI_UPPER_IO;
+ hose->mem_space.start = MVME5100_PCI_LOWER_MEM;
+ hose->mem_space.end = MVME5100_PCI_UPPER_MEM;
+ hose->io_base_virt = (void *)MVME5100_ISA_IO_BASE;
+
+ /* Use indirect method of Hawk */
+ setup_indirect_pci(hose, MVME5100_PCI_CONFIG_ADDR,
+ MVME5100_PCI_CONFIG_DATA);
+
+ hose->last_busno = pciauto_bus_scan(hose, hose->first_busno);
+
+ ppc_md.pcibios_fixup_resources = mvme5100_pcibios_fixup_resources;
+ ppc_md.pci_swizzle = common_swizzle;
+ ppc_md.pci_map_irq = mvme5100_map_irq;
+}
+
+static void __init
+mvme5100_setup_arch(void)
+{
+ if ( ppc_md.progress )
+ ppc_md.progress("mvme5100_setup_arch: enter", 0);
+
+ loops_per_jiffy = 50000000 / HZ;
+
+#ifdef CONFIG_BLK_DEV_INITRD
+ if (initrd_start)
+ ROOT_DEV = Root_RAM0;
+ else
+#endif
+#ifdef CONFIG_ROOT_NFS
+ ROOT_DEV = Root_NFS;
+#else
+ ROOT_DEV = Root_SDA2;
+#endif
+
+ if ( ppc_md.progress )
+ ppc_md.progress("mvme5100_setup_arch: find_bridges", 0);
+
+ /* Setup PCI host bridge */
+ mvme5100_setup_bridge();
+
+ /* Find and map our OpenPIC */
+ hawk_mpic_init(MVME5100_PCI_MEM_OFFSET);
+ OpenPIC_InitSenses = mvme5100_openpic_initsenses;
+ OpenPIC_NumInitSenses = sizeof(mvme5100_openpic_initsenses);
+
+ printk("MVME5100 port (C) 2001 MontaVista Software, Inc. (source@mvista.com)\n");
+
+ if ( ppc_md.progress )
+ ppc_md.progress("mvme5100_setup_arch: exit", 0);
+
+ return;
+}
+
+static void __init
+mvme5100_init2(void)
+{
+#ifdef CONFIG_MVME5100_IPMC761_PRESENT
+ request_region(0x00,0x20,"dma1");
+ request_region(0x20,0x20,"pic1");
+ request_region(0x40,0x20,"timer");
+ request_region(0x80,0x10,"dma page reg");
+ request_region(0xa0,0x20,"pic2");
+ request_region(0xc0,0x20,"dma2");
+#endif
+ return;
+}
+
+/*
+ * Interrupt setup and service.
+ * Have MPIC on HAWK and cascaded 8259s on Winbond cascaded to MPIC.
+ */
+static void __init
+mvme5100_init_IRQ(void)
+{
+#ifdef CONFIG_MVME5100_IPMC761_PRESENT
+ int i;
+#endif
+
+ if ( ppc_md.progress )
+ ppc_md.progress("init_irq: enter", 0);
+
+ openpic_set_sources(0, 16, OpenPIC_Addr + 0x10000);
+#ifdef CONFIG_MVME5100_IPMC761_PRESENT
+ openpic_init(NUM_8259_INTERRUPTS);
+ openpic_hookup_cascade(NUM_8259_INTERRUPTS, "82c59 cascade",
+ &i8259_irq);
+
+ /* Map i8259 interrupts. */
+ for (i = 0; i < NUM_8259_INTERRUPTS; i++)
+ irq_desc[i].handler = &i8259_pic;
+
+ i8259_init(0);
+#else
+ openpic_init(0);
+#endif
+
+ if ( ppc_md.progress )
+ ppc_md.progress("init_irq: exit", 0);
+
+ return;
+}
+
+/*
+ * Set BAT 3 to map 0xf0000000 to end of physical memory space.
+ */
+static __inline__ void
+mvme5100_set_bat(void)
+{
+ mb();
+ mtspr(SPRN_DBAT1U, 0xf0001ffe);
+ mtspr(SPRN_DBAT1L, 0xf000002a);
+ mb();
+}
+
+static unsigned long __init
+mvme5100_find_end_of_memory(void)
+{
+ return hawk_get_mem_size(MVME5100_HAWK_SMC_BASE);
+}
+
+static void __init
+mvme5100_map_io(void)
+{
+ io_block_mapping(0xfe000000, 0xfe000000, 0x02000000, _PAGE_IO);
+ ioremap_base = 0xfe000000;
+}
+
+static void
+mvme5100_reset_board(void)
+{
+ local_irq_disable();
+
+ /* Set exception prefix high - to the firmware */
+ _nmask_and_or_msr(0, MSR_IP);
+
+ out_8((u_char *)MVME5100_BOARD_MODRST_REG, 0x01);
+
+ return;
+}
+
+static void
+mvme5100_restart(char *cmd)
+{
+ volatile ulong i = 10000000;
+
+ mvme5100_reset_board();
+
+ while (i-- > 0);
+ panic("restart failed\n");
+}
+
+static void
+mvme5100_halt(void)
+{
+ local_irq_disable();
+ while (1);
+}
+
+static void
+mvme5100_power_off(void)
+{
+ mvme5100_halt();
+}
+
+static int
+mvme5100_show_cpuinfo(struct seq_file *m)
+{
+ seq_printf(m, "vendor\t\t: Motorola\n");
+ seq_printf(m, "machine\t\t: MVME5100\n");
+
+ return 0;
+}
+
+TODC_ALLOC();
+
+void __init
+platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
+ unsigned long r6, unsigned long r7)
+{
+ parse_bootinfo(find_bootinfo());
+ mvme5100_set_bat();
+
+ isa_io_base = MVME5100_ISA_IO_BASE;
+ isa_mem_base = MVME5100_ISA_MEM_BASE;
+ pci_dram_offset = MVME5100_PCI_DRAM_OFFSET;
+
+ ppc_md.setup_arch = mvme5100_setup_arch;
+ ppc_md.show_cpuinfo = mvme5100_show_cpuinfo;
+ ppc_md.init_IRQ = mvme5100_init_IRQ;
+ ppc_md.get_irq = openpic_get_irq;
+ ppc_md.init = mvme5100_init2;
+
+ ppc_md.restart = mvme5100_restart;
+ ppc_md.power_off = mvme5100_power_off;
+ ppc_md.halt = mvme5100_halt;
+
+ ppc_md.find_end_of_memory = mvme5100_find_end_of_memory;
+ ppc_md.setup_io_mappings = mvme5100_map_io;
+
+ TODC_INIT(TODC_TYPE_MK48T37, MVME5100_NVRAM_AS0, MVME5100_NVRAM_AS1,
+ MVME5100_NVRAM_DATA, 8);
+
+ ppc_md.time_init = todc_time_init;
+ ppc_md.set_rtc_time = todc_set_rtc_time;
+ ppc_md.get_rtc_time = todc_get_rtc_time;
+ ppc_md.calibrate_decr = todc_calibrate_decr;
+
+ ppc_md.nvram_read_val = todc_m48txx_read_val;
+ ppc_md.nvram_write_val = todc_m48txx_write_val;
+}
diff --git a/arch/ppc/platforms/mvme5100.h b/arch/ppc/platforms/mvme5100.h
new file mode 100644
index 0000000..edd4794
--- /dev/null
+++ b/arch/ppc/platforms/mvme5100.h
@@ -0,0 +1,91 @@
+/*
+ * include/asm-ppc/platforms/mvme5100.h
+ *
+ * Definitions for Motorola MVME5100.
+ *
+ * Author: Matt Porter <mporter@mvista.com>
+ *
+ * 2001 (c) MontaVista, Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+
+#ifdef __KERNEL__
+#ifndef __ASM_MVME5100_H__
+#define __ASM_MVME5100_H__
+
+#define MVME5100_HAWK_SMC_BASE 0xfef80000
+
+#define MVME5100_PCI_CONFIG_ADDR 0xfe000cf8
+#define MVME5100_PCI_CONFIG_DATA 0xfe000cfc
+
+#define MVME5100_PCI_IO_BASE 0xfe000000
+#define MVME5100_PCI_MEM_BASE 0x80000000
+
+#define MVME5100_PCI_MEM_OFFSET 0x00000000
+
+#define MVME5100_PCI_DRAM_OFFSET 0x00000000
+#define MVME5100_ISA_MEM_BASE 0x00000000
+#define MVME5100_ISA_IO_BASE MVME5100_PCI_IO_BASE
+
+#define MVME5100_PCI_LOWER_MEM 0x80000000
+#define MVME5100_PCI_UPPER_MEM 0xf3f7ffff
+#define MVME5100_PCI_LOWER_IO 0x00000000
+#define MVME5100_PCI_UPPER_IO 0x0077ffff
+
+/* MVME5100 board register addresses. */
+#define MVME5100_BOARD_STATUS_REG 0xfef88080
+#define MVME5100_BOARD_MODFAIL_REG 0xfef88090
+#define MVME5100_BOARD_MODRST_REG 0xfef880a0
+#define MVME5100_BOARD_TBEN_REG 0xfef880c0
+#define MVME5100_BOARD_SW_READ_REG 0xfef880e0
+#define MVME5100_BOARD_GEO_ADDR_REG 0xfef880e8
+#define MVME5100_BOARD_EXT_FEATURE1_REG 0xfef880f0
+#define MVME5100_BOARD_EXT_FEATURE2_REG 0xfef88100
+
+/* Define the NVRAM/RTC address strobe & data registers */
+#define MVME5100_PHYS_NVRAM_AS0 0xfef880c8
+#define MVME5100_PHYS_NVRAM_AS1 0xfef880d0
+#define MVME5100_PHYS_NVRAM_DATA 0xfef880d8
+
+#define MVME5100_NVRAM_AS0 (MVME5100_PHYS_NVRAM_AS0 - MVME5100_ISA_IO_BASE)
+#define MVME5100_NVRAM_AS1 (MVME5100_PHYS_NVRAM_AS1 - MVME5100_ISA_IO_BASE)
+#define MVME5100_NVRAM_DATA (MVME5100_PHYS_NVRAM_DATA - MVME5100_ISA_IO_BASE)
+
+/* UART clock, addresses, and irq */
+#define MVME5100_BASE_BAUD 1843200
+#define MVME5100_SERIAL_1 0xfef88000
+#define MVME5100_SERIAL_2 0xfef88200
+#ifdef CONFIG_MVME5100_IPMC761_PRESENT
+#define MVME5100_SERIAL_IRQ 17
+#else
+#define MVME5100_SERIAL_IRQ 1
+#endif
+
+#define RS_TABLE_SIZE 4
+
+#define BASE_BAUD ( MVME5100_BASE_BAUD / 16 )
+
+#define STD_COM_FLAGS ASYNC_BOOT_AUTOCONF
+
+/* All UART IRQ's are wire-OR'd to one MPIC IRQ */
+#define STD_SERIAL_PORT_DFNS \
+ { 0, BASE_BAUD, MVME5100_SERIAL_1, \
+ MVME5100_SERIAL_IRQ, \
+ STD_COM_FLAGS, /* ttyS0 */ \
+ iomem_base: (unsigned char *)MVME5100_SERIAL_1, \
+ iomem_reg_shift: 4, \
+ io_type: SERIAL_IO_MEM }, \
+ { 0, BASE_BAUD, MVME5100_SERIAL_2, \
+ MVME5100_SERIAL_IRQ, \
+ STD_COM_FLAGS, /* ttyS1 */ \
+ iomem_base: (unsigned char *)MVME5100_SERIAL_2, \
+ iomem_reg_shift: 4, \
+ io_type: SERIAL_IO_MEM },
+
+#define SERIAL_PORT_DFNS \
+ STD_SERIAL_PORT_DFNS
+
+#endif /* __ASM_MVME5100_H__ */
+#endif /* __KERNEL__ */
diff --git a/arch/ppc/platforms/pal4.h b/arch/ppc/platforms/pal4.h
new file mode 100644
index 0000000..641a11a
--- /dev/null
+++ b/arch/ppc/platforms/pal4.h
@@ -0,0 +1,42 @@
+/*
+ * arch/ppc/platforms/pal4.h
+ *
+ * Definitions for SBS Palomar IV board
+ *
+ * Author: Dan Cox
+ *
+ * 2002 (c) MontaVista, Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+
+#ifndef __PPC_PLATFORMS_PAL4_H
+#define __PPC_PLATFORMS_PAL4_H
+
+#define PAL4_NVRAM 0xfffc0000
+#define PAL4_NVRAM_SIZE 0x8000
+
+#define PAL4_DRAM 0xfff80000
+#define PAL4_DRAM_BR_MASK 0xc0
+#define PAL4_DRAM_BR_SHIFT 6
+#define PAL4_DRAM_RESET 0x10
+#define PAL4_DRAM_EREADY 0x40
+
+#define PAL4_MISC 0xfff80004
+#define PAL4_MISC_FB_MASK 0xc0
+#define PAL4_MISC_FLASH 0x20 /* StratFlash mapping: 1->0xff80, 0->0xfff0 */
+#define PAL4_MISC_MISC 0x08
+#define PAL4_MISC_BITF 0x02
+#define PAL4_MISC_NVKS 0x01
+
+#define PAL4_L2 0xfff80008
+#define PAL4_L2_MASK 0x07
+
+#define PAL4_PLDR 0xfff8000c
+
+/* Only two Ethernet devices on the board... */
+#define PAL4_ETH 31
+#define PAL4_INTA 20
+
+#endif /* __PPC_PLATFORMS_PAL4_H */
diff --git a/arch/ppc/platforms/pal4_pci.c b/arch/ppc/platforms/pal4_pci.c
new file mode 100644
index 0000000..c3b1b75
--- /dev/null
+++ b/arch/ppc/platforms/pal4_pci.c
@@ -0,0 +1,77 @@
+/*
+ * arch/ppc/platforms/pal4_pci.c
+ *
+ * PCI support for SBS Palomar IV
+ *
+ * Author: Dan Cox
+ *
+ * 2002 (c) MontaVista, Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+
+#include <asm/byteorder.h>
+#include <asm/machdep.h>
+#include <asm/io.h>
+#include <asm/pci-bridge.h>
+#include <asm/uaccess.h>
+
+#include <syslib/cpc700.h>
+
+#include "pal4.h"
+
+/* not much to this.... */
+static inline int __init
+pal4_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin)
+{
+ if (idsel == 9)
+ return PAL4_ETH;
+ else
+ return PAL4_INTA + (idsel - 3);
+}
+
+void __init
+pal4_find_bridges(void)
+{
+ struct pci_controller *hose;
+
+ hose = pcibios_alloc_controller();
+ if (!hose)
+ return;
+
+ hose->first_busno = 0;
+ hose->last_busno = 0xff;
+ hose->pci_mem_offset = 0;
+
+ /* Could snatch these from the CPC700.... */
+ pci_init_resource(&hose->io_resource,
+ 0x0,
+ 0x03ffffff,
+ IORESOURCE_IO,
+ "PCI host bridge");
+
+ pci_init_resource(&hose->mem_resources[0],
+ 0x90000000,
+ 0x9fffffff,
+ IORESOURCE_MEM,
+ "PCI host bridge");
+
+ hose->io_space.start = 0x00800000;
+ hose->io_space.end = 0x03ffffff;
+ hose->mem_space.start = 0x90000000;
+ hose->mem_space.end = 0x9fffffff;
+ hose->io_base_virt = (void *) 0xf8000000;
+
+ setup_indirect_pci(hose, CPC700_PCI_CONFIG_ADDR,
+ CPC700_PCI_CONFIG_DATA);
+
+ hose->last_busno = pciauto_bus_scan(hose, hose->first_busno);
+
+ ppc_md.pci_swizzle = common_swizzle;
+ ppc_md.pci_map_irq = pal4_map_irq;
+}
diff --git a/arch/ppc/platforms/pal4_serial.h b/arch/ppc/platforms/pal4_serial.h
new file mode 100644
index 0000000..a715c66
--- /dev/null
+++ b/arch/ppc/platforms/pal4_serial.h
@@ -0,0 +1,39 @@
+/*
+ * arch/ppc/platforms/pal4_serial.h
+ *
+ * Definitions for SBS PalomarIV serial support
+ *
+ * Author: Dan Cox
+ *
+ * 2002 (c) MontaVista, Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+
+#ifndef __PPC_PAL4_SERIAL_H
+#define __PPC_PAL4_SERIAL_H
+
+#define CPC700_SERIAL_1 0xff600300
+#define CPC700_SERIAL_2 0xff600400
+
+#define RS_TABLE_SIZE 2
+#define BASE_BAUD (33333333 / 4 / 16)
+
+#ifdef CONFIG_SERIAL_DETECT_IRQ
+#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF|ASYNC_SKIP_TEST|ASYNC_AUTO_IRQ)
+#define STD_COM4_FLAGS (ASYNC_BOOT_AUTOCONF|ASYNC_AUTO_IRQ)
+#else
+#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF|ASYNC_SKIP_TEST)
+#define STD_COM4_FLAGS (ASYNC_BOOT_AUTOCONF)
+#endif
+
+#define SERIAL_PORT_DFNS \
+ {0, BASE_BAUD, CPC700_SERIAL_1, 3, STD_COM_FLAGS, \
+ iomem_base: (unsigned char *) CPC700_SERIAL_1, \
+ io_type: SERIAL_IO_MEM}, /* ttyS0 */ \
+ {0, BASE_BAUD, CPC700_SERIAL_2, 4, STD_COM_FLAGS, \
+ iomem_base: (unsigned char *) CPC700_SERIAL_2, \
+ io_type: SERIAL_IO_MEM}
+
+#endif
diff --git a/arch/ppc/platforms/pal4_setup.c b/arch/ppc/platforms/pal4_setup.c
new file mode 100644
index 0000000..12446b9
--- /dev/null
+++ b/arch/ppc/platforms/pal4_setup.c
@@ -0,0 +1,175 @@
+/*
+ * arch/ppc/platforms/pal4_setup.c
+ *
+ * Board setup routines for the SBS PalomarIV.
+ *
+ * Author: Dan Cox
+ *
+ * 2002 (c) MontaVista, Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/reboot.h>
+#include <linux/time.h>
+#include <linux/irq.h>
+#include <linux/kdev_t.h>
+#include <linux/initrd.h>
+#include <linux/console.h>
+#include <linux/seq_file.h>
+#include <linux/root_dev.h>
+
+#include <asm/io.h>
+#include <asm/todc.h>
+#include <asm/bootinfo.h>
+
+#include <syslib/cpc700.h>
+
+#include "pal4.h"
+
+extern void pal4_find_bridges(void);
+
+unsigned int cpc700_irq_assigns[][2] = {
+ {1, 1}, /* IRQ 0: ECC correctable error */
+ {1, 1}, /* IRQ 1: PCI write to memory range */
+ {0, 1}, /* IRQ 2: PCI write to command register */
+ {0, 1}, /* IRQ 3: UART 0 */
+ {0, 1}, /* IRQ 4: UART 1 */
+ {0, 1}, /* IRQ 5: ICC 0 */
+ {0, 1}, /* IRQ 6: ICC 1 */
+ {0, 1}, /* IRQ 7: GPT compare 0 */
+ {0, 1}, /* IRQ 8: GPT compare 1 */
+ {0, 1}, /* IRQ 9: GPT compare 2 */
+ {0, 1}, /* IRQ 10: GPT compare 3 */
+ {0, 1}, /* IRQ 11: GPT compare 4 */
+ {0, 1}, /* IRQ 12: GPT capture 0 */
+ {0, 1}, /* IRQ 13: GPT capture 1 */
+ {0, 1}, /* IRQ 14: GPT capture 2 */
+ {0, 1}, /* IRQ 15: GPT capture 3 */
+ {0, 1}, /* IRQ 16: GPT capture 4 */
+ {0, 0}, /* IRQ 17: reserved */
+ {0, 0}, /* IRQ 18: reserved */
+ {0, 0}, /* IRQ 19: reserved */
+ {0, 0}, /* IRQ 20: reserved */
+ {0, 1}, /* IRQ 21: Ethernet */
+ {0, 0}, /* IRQ 22: reserved */
+ {0, 0}, /* IRQ 23: reserved */
+ {0, 0}, /* IRQ 24: resreved */
+ {0, 0}, /* IRQ 25: reserved */
+ {0, 0}, /* IRQ 26: reserved */
+ {0, 0}, /* IRQ 27: reserved */
+ {0, 0}, /* IRQ 28: reserved */
+ {0, 0}, /* IRQ 29: reserved */
+ {0, 0}, /* IRQ 30: reserved */
+ {0, 0}, /* IRQ 31: reserved */
+};
+
+static int
+pal4_show_cpuinfo(struct seq_file *m)
+{
+ seq_printf(m, "board\t\t: SBS Palomar IV\n");
+
+ return 0;
+}
+
+static void
+pal4_restart(char *cmd)
+{
+ local_irq_disable();
+ __asm__ __volatile__("lis 3,0xfff0\n \
+ ori 3,3,0x100\n \
+ mtspr 26,3\n \
+ li 3,0\n \
+ mtspr 27,3\n \
+ rfi");
+
+ for(;;);
+}
+
+static void
+pal4_power_off(void)
+{
+ local_irq_disable();
+ for(;;);
+}
+
+static void
+pal4_halt(void)
+{
+ pal4_power_off();
+}
+
+TODC_ALLOC();
+
+static void __init
+pal4_setup_arch(void)
+{
+ unsigned long l2;
+
+ TODC_INIT(TODC_TYPE_MK48T37, 0, 0,
+ ioremap(PAL4_NVRAM, PAL4_NVRAM_SIZE), 8);
+
+ pal4_find_bridges();
+
+#ifdef CONFIG_BLK_DEV_INITRD
+ if (initrd_start)
+ ROOT_DEV = Root_RAM0;
+ else
+#endif
+ ROOT_DEV = Root_NFS;
+
+ /* The L2 gets disabled in the bootloader, but all the proper
+ bits should be present from the fw, so just re-enable it */
+ l2 = _get_L2CR();
+ if (!(l2 & L2CR_L2E)) {
+ /* presume that it was initially set if the size is
+ still present. */
+ if (l2 ^ L2CR_L2SIZ_MASK)
+ _set_L2CR(l2 | L2CR_L2E);
+ else
+ printk("L2 not set by firmware; left disabled.\n");
+ }
+}
+
+static void __init
+pal4_map_io(void)
+{
+ io_block_mapping(0xf0000000, 0xf0000000, 0x10000000, _PAGE_IO);
+}
+
+void __init
+platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
+ unsigned long r6, unsigned long r7)
+{
+ parse_bootinfo(find_bootinfo());
+
+ isa_io_base = 0 /*PAL4_ISA_IO_BASE*/;
+ pci_dram_offset = 0 /*PAL4_PCI_SYS_MEM_BASE*/;
+
+ ppc_md.setup_arch = pal4_setup_arch;
+ ppc_md.show_cpuinfo = pal4_show_cpuinfo;
+
+ ppc_md.setup_io_mappings = pal4_map_io;
+
+ ppc_md.init_IRQ = cpc700_init_IRQ;
+ ppc_md.get_irq = cpc700_get_irq;
+
+ ppc_md.restart = pal4_restart;
+ ppc_md.halt = pal4_halt;
+ ppc_md.power_off = pal4_power_off;
+
+ ppc_md.time_init = todc_time_init;
+ ppc_md.set_rtc_time = todc_set_rtc_time;
+ ppc_md.get_rtc_time = todc_get_rtc_time;
+ ppc_md.calibrate_decr = todc_calibrate_decr;
+
+ ppc_md.nvram_read_val = todc_direct_read_val;
+ ppc_md.nvram_write_val = todc_direct_write_val;
+}
+
diff --git a/arch/ppc/platforms/pcore.c b/arch/ppc/platforms/pcore.c
new file mode 100644
index 0000000..d719163
--- /dev/null
+++ b/arch/ppc/platforms/pcore.c
@@ -0,0 +1,352 @@
+/*
+ * arch/ppc/platforms/pcore_setup.c
+ *
+ * Setup routines for Force PCORE boards
+ *
+ * Author: Matt Porter <mporter@mvista.com>
+ *
+ * 2001 (c) MontaVista, Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+
+#include <linux/config.h>
+#include <linux/stddef.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/reboot.h>
+#include <linux/pci.h>
+#include <linux/kdev_t.h>
+#include <linux/types.h>
+#include <linux/major.h>
+#include <linux/initrd.h>
+#include <linux/console.h>
+#include <linux/irq.h>
+#include <linux/seq_file.h>
+#include <linux/root_dev.h>
+
+#include <asm/io.h>
+#include <asm/machdep.h>
+#include <asm/time.h>
+#include <asm/i8259.h>
+#include <asm/mpc10x.h>
+#include <asm/todc.h>
+#include <asm/bootinfo.h>
+#include <asm/kgdb.h>
+
+#include "pcore.h"
+
+extern unsigned long loops_per_jiffy;
+
+static int board_type;
+
+static inline int __init
+pcore_6750_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin)
+{
+ static char pci_irq_table[][4] =
+ /*
+ * PCI IDSEL/INTPIN->INTLINE
+ * A B C D
+ */
+ {
+ {9, 10, 11, 12}, /* IDSEL 24 - DEC 21554 */
+ {10, 0, 0, 0}, /* IDSEL 25 - DEC 21143 */
+ {11, 12, 9, 10}, /* IDSEL 26 - PMC I */
+ {12, 9, 10, 11}, /* IDSEL 27 - PMC II */
+ {0, 0, 0, 0}, /* IDSEL 28 - unused */
+ {0, 0, 9, 0}, /* IDSEL 29 - unused */
+ {0, 0, 0, 0}, /* IDSEL 30 - Winbond */
+ };
+ const long min_idsel = 24, max_idsel = 30, irqs_per_slot = 4;
+ return PCI_IRQ_TABLE_LOOKUP;
+};
+
+static inline int __init
+pcore_680_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin)
+{
+ static char pci_irq_table[][4] =
+ /*
+ * PCI IDSEL/INTPIN->INTLINE
+ * A B C D
+ */
+ {
+ {9, 10, 11, 12}, /* IDSEL 24 - Sentinel */
+ {10, 0, 0, 0}, /* IDSEL 25 - i82559 #1 */
+ {11, 12, 9, 10}, /* IDSEL 26 - PMC I */
+ {12, 9, 10, 11}, /* IDSEL 27 - PMC II */
+ {9, 0, 0, 0}, /* IDSEL 28 - i82559 #2 */
+ {0, 0, 0, 0}, /* IDSEL 29 - unused */
+ {0, 0, 0, 0}, /* IDSEL 30 - Winbond */
+ };
+ const long min_idsel = 24, max_idsel = 30, irqs_per_slot = 4;
+ return PCI_IRQ_TABLE_LOOKUP;
+};
+
+void __init
+pcore_pcibios_fixup(void)
+{
+ struct pci_dev *dev;
+
+ if ((dev = pci_get_device(PCI_VENDOR_ID_WINBOND,
+ PCI_DEVICE_ID_WINBOND_83C553,
+ 0)))
+ {
+ /* Reroute interrupts both IDE channels to 15 */
+ pci_write_config_byte(dev,
+ PCORE_WINBOND_IDE_INT,
+ 0xff);
+
+ /* Route INTA-D to IRQ9-12, respectively */
+ pci_write_config_word(dev,
+ PCORE_WINBOND_PCI_INT,
+ 0x9abc);
+
+ /*
+ * Set up 8259 edge/level triggering
+ */
+ outb(0x00, PCORE_WINBOND_PRI_EDG_LVL);
+ outb(0x1e, PCORE_WINBOND_SEC_EDG_LVL);
+ pci_dev_put(dev);
+ }
+}
+
+int __init
+pcore_find_bridges(void)
+{
+ struct pci_controller* hose;
+ int host_bridge, board_type;
+
+ hose = pcibios_alloc_controller();
+ if (!hose)
+ return 0;
+
+ mpc10x_bridge_init(hose,
+ MPC10X_MEM_MAP_B,
+ MPC10X_MEM_MAP_B,
+ MPC10X_MAPB_EUMB_BASE);
+
+ /* Determine board type */
+ early_read_config_dword(hose,
+ 0,
+ PCI_DEVFN(0,0),
+ PCI_VENDOR_ID,
+ &host_bridge);
+ if (host_bridge == MPC10X_BRIDGE_106)
+ board_type = PCORE_TYPE_6750;
+ else /* MPC10X_BRIDGE_107 */
+ board_type = PCORE_TYPE_680;
+
+ hose->last_busno = pciauto_bus_scan(hose, hose->first_busno);
+
+ ppc_md.pcibios_fixup = pcore_pcibios_fixup;
+ ppc_md.pci_swizzle = common_swizzle;
+
+ if (board_type == PCORE_TYPE_6750)
+ ppc_md.pci_map_irq = pcore_6750_map_irq;
+ else /* PCORE_TYPE_680 */
+ ppc_md.pci_map_irq = pcore_680_map_irq;
+
+ return board_type;
+}
+
+/* Dummy variable to satisfy mpc10x_common.o */
+void *OpenPIC_Addr;
+
+static int
+pcore_show_cpuinfo(struct seq_file *m)
+{
+ seq_printf(m, "vendor\t\t: Force Computers\n");
+
+ if (board_type == PCORE_TYPE_6750)
+ seq_printf(m, "machine\t\t: PowerCore 6750\n");
+ else /* PCORE_TYPE_680 */
+ seq_printf(m, "machine\t\t: PowerCore 680\n");
+
+ seq_printf(m, "L2\t\t: " );
+ if (board_type == PCORE_TYPE_6750)
+ switch (readb(PCORE_DCCR_REG) & PCORE_DCCR_L2_MASK)
+ {
+ case PCORE_DCCR_L2_0KB:
+ seq_printf(m, "nocache");
+ break;
+ case PCORE_DCCR_L2_256KB:
+ seq_printf(m, "256KB");
+ break;
+ case PCORE_DCCR_L2_1MB:
+ seq_printf(m, "1MB");
+ break;
+ case PCORE_DCCR_L2_512KB:
+ seq_printf(m, "512KB");
+ break;
+ default:
+ seq_printf(m, "error");
+ break;
+ }
+ else /* PCORE_TYPE_680 */
+ switch (readb(PCORE_DCCR_REG) & PCORE_DCCR_L2_MASK)
+ {
+ case PCORE_DCCR_L2_2MB:
+ seq_printf(m, "2MB");
+ break;
+ case PCORE_DCCR_L2_256KB:
+ seq_printf(m, "reserved");
+ break;
+ case PCORE_DCCR_L2_1MB:
+ seq_printf(m, "1MB");
+ break;
+ case PCORE_DCCR_L2_512KB:
+ seq_printf(m, "512KB");
+ break;
+ default:
+ seq_printf(m, "error");
+ break;
+ }
+
+ seq_printf(m, "\n");
+
+ return 0;
+}
+
+static void __init
+pcore_setup_arch(void)
+{
+ /* init to some ~sane value until calibrate_delay() runs */
+ loops_per_jiffy = 50000000/HZ;
+
+ /* Lookup PCI host bridges */
+ board_type = pcore_find_bridges();
+
+#ifdef CONFIG_BLK_DEV_INITRD
+ if (initrd_start)
+ ROOT_DEV = Root_RAM0;
+ else
+#endif
+#ifdef CONFIG_ROOT_NFS
+ ROOT_DEV = Root_NFS;
+#else
+ ROOT_DEV = Root_SDA2;
+#endif
+
+ printk(KERN_INFO "Force PowerCore ");
+ if (board_type == PCORE_TYPE_6750)
+ printk("6750\n");
+ else
+ printk("680\n");
+ printk(KERN_INFO "Port by MontaVista Software, Inc. (source@mvista.com)\n");
+ _set_L2CR(L2CR_L2E | _get_L2CR());
+
+}
+
+static void
+pcore_restart(char *cmd)
+{
+ local_irq_disable();
+ /* Hard reset */
+ writeb(0x11, 0xfe000332);
+ while(1);
+}
+
+static void
+pcore_halt(void)
+{
+ local_irq_disable();
+ /* Turn off user LEDs */
+ writeb(0x00, 0xfe000300);
+ while (1);
+}
+
+static void
+pcore_power_off(void)
+{
+ pcore_halt();
+}
+
+
+static void __init
+pcore_init_IRQ(void)
+{
+ int i;
+
+ for ( i = 0 ; i < 16 ; i++ )
+ irq_desc[i].handler = &i8259_pic;
+
+ i8259_init(0);
+}
+
+/*
+ * Set BAT 3 to map 0xf0000000 to end of physical memory space.
+ */
+static __inline__ void
+pcore_set_bat(void)
+{
+ mb();
+ mtspr(SPRN_DBAT3U, 0xf0001ffe);
+ mtspr(SPRN_DBAT3L, 0xfe80002a);
+ mb();
+
+}
+
+static unsigned long __init
+pcore_find_end_of_memory(void)
+{
+
+ return mpc10x_get_mem_size(MPC10X_MEM_MAP_B);
+}
+
+static void __init
+pcore_map_io(void)
+{
+ io_block_mapping(0xfe000000, 0xfe000000, 0x02000000, _PAGE_IO);
+}
+
+TODC_ALLOC();
+
+void __init
+platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
+ unsigned long r6, unsigned long r7)
+{
+ parse_bootinfo(find_bootinfo());
+
+ /* Cover I/O space with a BAT */
+ /* yuck, better hope your ram size is a power of 2 -- paulus */
+ pcore_set_bat();
+
+ isa_io_base = MPC10X_MAPB_ISA_IO_BASE;
+ isa_mem_base = MPC10X_MAPB_ISA_MEM_BASE;
+ pci_dram_offset = MPC10X_MAPB_DRAM_OFFSET;
+
+ ppc_md.setup_arch = pcore_setup_arch;
+ ppc_md.show_cpuinfo = pcore_show_cpuinfo;
+ ppc_md.init_IRQ = pcore_init_IRQ;
+ ppc_md.get_irq = i8259_irq;
+
+ ppc_md.find_end_of_memory = pcore_find_end_of_memory;
+ ppc_md.setup_io_mappings = pcore_map_io;
+
+ ppc_md.restart = pcore_restart;
+ ppc_md.power_off = pcore_power_off;
+ ppc_md.halt = pcore_halt;
+
+ TODC_INIT(TODC_TYPE_MK48T59,
+ PCORE_NVRAM_AS0,
+ PCORE_NVRAM_AS1,
+ PCORE_NVRAM_DATA,
+ 8);
+
+ ppc_md.time_init = todc_time_init;
+ ppc_md.get_rtc_time = todc_get_rtc_time;
+ ppc_md.set_rtc_time = todc_set_rtc_time;
+ ppc_md.calibrate_decr = todc_calibrate_decr;
+
+ ppc_md.nvram_read_val = todc_m48txx_read_val;
+ ppc_md.nvram_write_val = todc_m48txx_write_val;
+
+#ifdef CONFIG_SERIAL_TEXT_DEBUG
+ ppc_md.progress = gen550_progress;
+#endif
+#ifdef CONFIG_KGDB
+ ppc_md.kgdb_map_scc = gen550_kgdb_map_scc;
+#endif
+}
diff --git a/arch/ppc/platforms/pcore.h b/arch/ppc/platforms/pcore.h
new file mode 100644
index 0000000..c6a26e7
--- /dev/null
+++ b/arch/ppc/platforms/pcore.h
@@ -0,0 +1,39 @@
+/*
+ * arch/ppc/platforms/pcore.h
+ *
+ * Definitions for Force PowerCore board support
+ *
+ * Author: Matt Porter <mporter@mvista.com>
+ *
+ * 2001 (c) MontaVista, Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+
+#ifndef __PPC_PLATFORMS_PCORE_H
+#define __PPC_PLATFORMS_PCORE_H
+
+#include <asm/mpc10x.h>
+
+#define PCORE_TYPE_6750 1
+#define PCORE_TYPE_680 2
+
+#define PCORE_NVRAM_AS0 0x73
+#define PCORE_NVRAM_AS1 0x75
+#define PCORE_NVRAM_DATA 0x77
+
+#define PCORE_DCCR_REG (MPC10X_MAPB_ISA_IO_BASE + 0x308)
+#define PCORE_DCCR_L2_MASK 0xc0
+#define PCORE_DCCR_L2_0KB 0x00
+#define PCORE_DCCR_L2_256KB 0x40
+#define PCORE_DCCR_L2_512KB 0xc0
+#define PCORE_DCCR_L2_1MB 0x80
+#define PCORE_DCCR_L2_2MB 0x00
+
+#define PCORE_WINBOND_IDE_INT 0x43
+#define PCORE_WINBOND_PCI_INT 0x44
+#define PCORE_WINBOND_PRI_EDG_LVL 0x4d0
+#define PCORE_WINBOND_SEC_EDG_LVL 0x4d1
+
+#endif /* __PPC_PLATFORMS_PCORE_H */
diff --git a/arch/ppc/platforms/pcu_e.h b/arch/ppc/platforms/pcu_e.h
new file mode 100644
index 0000000..91a820a
--- /dev/null
+++ b/arch/ppc/platforms/pcu_e.h
@@ -0,0 +1,28 @@
+/*
+ * Siemens PCU E board specific definitions
+ *
+ * Copyright (c) 2001 Wolfgang Denk (wd@denx.de)
+ */
+
+#ifndef __MACH_PCU_E_H
+#define __MACH_PCU_E_H
+
+#include <linux/config.h>
+
+#include <asm/ppcboot.h>
+
+#define PCU_E_IMMR_BASE 0xFE000000 /* phys. addr of IMMR */
+#define PCU_E_IMAP_SIZE (64 * 1024) /* size of mapped area */
+
+#define IMAP_ADDR PCU_E_IMMR_BASE /* physical base address of IMMR area */
+#define IMAP_SIZE PCU_E_IMAP_SIZE /* mapped size of IMMR area */
+
+#define FEC_INTERRUPT 15 /* = SIU_LEVEL7 */
+#define DEC_INTERRUPT 13 /* = SIU_LEVEL6 */
+#define CPM_INTERRUPT 11 /* = SIU_LEVEL5 (was: SIU_LEVEL2) */
+
+/* We don't use the 8259.
+*/
+#define NR_8259_INTS 0
+
+#endif /* __MACH_PCU_E_H */
diff --git a/arch/ppc/platforms/pmac_backlight.c b/arch/ppc/platforms/pmac_backlight.c
new file mode 100644
index 0000000..ed2b1ce
--- /dev/null
+++ b/arch/ppc/platforms/pmac_backlight.c
@@ -0,0 +1,202 @@
+/*
+ * Miscellaneous procedures for dealing with the PowerMac hardware.
+ * Contains support for the backlight.
+ *
+ * Copyright (C) 2000 Benjamin Herrenschmidt
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/stddef.h>
+#include <linux/reboot.h>
+#include <linux/nvram.h>
+#include <linux/console.h>
+#include <asm/sections.h>
+#include <asm/ptrace.h>
+#include <asm/io.h>
+#include <asm/pgtable.h>
+#include <asm/system.h>
+#include <asm/prom.h>
+#include <asm/machdep.h>
+#include <asm/nvram.h>
+#include <asm/backlight.h>
+
+#include <linux/adb.h>
+#include <linux/pmu.h>
+
+static struct backlight_controller *backlighter;
+static void* backlighter_data;
+static int backlight_autosave;
+static int backlight_level = BACKLIGHT_MAX;
+static int backlight_enabled = 1;
+static int backlight_req_level = -1;
+static int backlight_req_enable = -1;
+
+static void backlight_callback(void *);
+static DECLARE_WORK(backlight_work, backlight_callback, NULL);
+
+void __pmac register_backlight_controller(struct backlight_controller *ctrler,
+ void *data, char *type)
+{
+ struct device_node* bk_node;
+ char *prop;
+ int valid = 0;
+
+ /* There's already a matching controller, bail out */
+ if (backlighter != NULL)
+ return;
+
+ bk_node = find_devices("backlight");
+
+#ifdef CONFIG_ADB_PMU
+ /* Special case for the old PowerBook since I can't test on it */
+ backlight_autosave = machine_is_compatible("AAPL,3400/2400")
+ || machine_is_compatible("AAPL,3500");
+ if ((backlight_autosave
+ || machine_is_compatible("AAPL,PowerBook1998")
+ || machine_is_compatible("PowerBook1,1"))
+ && !strcmp(type, "pmu"))
+ valid = 1;
+#endif
+ if (bk_node) {
+ prop = get_property(bk_node, "backlight-control", NULL);
+ if (prop && !strncmp(prop, type, strlen(type)))
+ valid = 1;
+ }
+ if (!valid)
+ return;
+ backlighter = ctrler;
+ backlighter_data = data;
+
+ if (bk_node && !backlight_autosave)
+ prop = get_property(bk_node, "bklt", NULL);
+ else
+ prop = NULL;
+ if (prop) {
+ backlight_level = ((*prop)+1) >> 1;
+ if (backlight_level > BACKLIGHT_MAX)
+ backlight_level = BACKLIGHT_MAX;
+ }
+
+#ifdef CONFIG_ADB_PMU
+ if (backlight_autosave) {
+ struct adb_request req;
+ pmu_request(&req, NULL, 2, 0xd9, 0);
+ while (!req.complete)
+ pmu_poll();
+ backlight_level = req.reply[0] >> 4;
+ }
+#endif
+ acquire_console_sem();
+ if (!backlighter->set_enable(1, backlight_level, data))
+ backlight_enabled = 1;
+ release_console_sem();
+
+ printk(KERN_INFO "Registered \"%s\" backlight controller,"
+ "level: %d/15\n", type, backlight_level);
+}
+EXPORT_SYMBOL(register_backlight_controller);
+
+void __pmac unregister_backlight_controller(struct backlight_controller
+ *ctrler, void *data)
+{
+ /* We keep the current backlight level (for now) */
+ if (ctrler == backlighter && data == backlighter_data)
+ backlighter = NULL;
+}
+EXPORT_SYMBOL(unregister_backlight_controller);
+
+static int __pmac __set_backlight_enable(int enable)
+{
+ int rc;
+
+ if (!backlighter)
+ return -ENODEV;
+ acquire_console_sem();
+ rc = backlighter->set_enable(enable, backlight_level,
+ backlighter_data);
+ if (!rc)
+ backlight_enabled = enable;
+ release_console_sem();
+ return rc;
+}
+int __pmac set_backlight_enable(int enable)
+{
+ if (!backlighter)
+ return -ENODEV;
+ backlight_req_enable = enable;
+ schedule_work(&backlight_work);
+ return 0;
+}
+
+EXPORT_SYMBOL(set_backlight_enable);
+
+int __pmac get_backlight_enable(void)
+{
+ if (!backlighter)
+ return -ENODEV;
+ return backlight_enabled;
+}
+EXPORT_SYMBOL(get_backlight_enable);
+
+static int __pmac __set_backlight_level(int level)
+{
+ int rc = 0;
+
+ if (!backlighter)
+ return -ENODEV;
+ if (level < BACKLIGHT_MIN)
+ level = BACKLIGHT_OFF;
+ if (level > BACKLIGHT_MAX)
+ level = BACKLIGHT_MAX;
+ acquire_console_sem();
+ if (backlight_enabled)
+ rc = backlighter->set_level(level, backlighter_data);
+ if (!rc)
+ backlight_level = level;
+ release_console_sem();
+ if (!rc && !backlight_autosave) {
+ level <<=1;
+ if (level & 0x10)
+ level |= 0x01;
+ // -- todo: save to property "bklt"
+ }
+ return rc;
+}
+int __pmac set_backlight_level(int level)
+{
+ if (!backlighter)
+ return -ENODEV;
+ backlight_req_level = level;
+ schedule_work(&backlight_work);
+ return 0;
+}
+
+EXPORT_SYMBOL(set_backlight_level);
+
+int __pmac get_backlight_level(void)
+{
+ if (!backlighter)
+ return -ENODEV;
+ return backlight_level;
+}
+EXPORT_SYMBOL(get_backlight_level);
+
+static void backlight_callback(void *dummy)
+{
+ int level, enable;
+
+ do {
+ level = backlight_req_level;
+ enable = backlight_req_enable;
+ mb();
+
+ if (level >= 0)
+ __set_backlight_level(level);
+ if (enable >= 0)
+ __set_backlight_enable(enable);
+ } while(cmpxchg(&backlight_req_level, level, -1) != level ||
+ cmpxchg(&backlight_req_enable, enable, -1) != enable);
+}
diff --git a/arch/ppc/platforms/pmac_cache.S b/arch/ppc/platforms/pmac_cache.S
new file mode 100644
index 0000000..c00e035
--- /dev/null
+++ b/arch/ppc/platforms/pmac_cache.S
@@ -0,0 +1,325 @@
+/*
+ * This file contains low-level cache management functions
+ * used for sleep and CPU speed changes on Apple machines.
+ * (In fact the only thing that is Apple-specific is that we assume
+ * that we can read from ROM at physical address 0xfff00000.)
+ *
+ * Copyright (C) 2004 Paul Mackerras (paulus@samba.org) and
+ * Benjamin Herrenschmidt (benh@kernel.crashing.org)
+ *
+ * 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.
+ *
+ */
+
+#include <linux/config.h>
+#include <asm/processor.h>
+#include <asm/ppc_asm.h>
+#include <asm/cputable.h>
+
+/*
+ * Flush and disable all data caches (dL1, L2, L3). This is used
+ * when going to sleep, when doing a PMU based cpufreq transition,
+ * or when "offlining" a CPU on SMP machines. This code is over
+ * paranoid, but I've had enough issues with various CPU revs and
+ * bugs that I decided it was worth beeing over cautious
+ */
+
+_GLOBAL(flush_disable_caches)
+BEGIN_FTR_SECTION
+ b flush_disable_745x
+END_FTR_SECTION_IFSET(CPU_FTR_SPEC7450)
+BEGIN_FTR_SECTION
+ b flush_disable_75x
+END_FTR_SECTION_IFSET(CPU_FTR_L2CR)
+ b __flush_disable_L1
+
+/* This is the code for G3 and 74[01]0 */
+flush_disable_75x:
+ mflr r10
+
+ /* Turn off EE and DR in MSR */
+ mfmsr r11
+ rlwinm r0,r11,0,~MSR_EE
+ rlwinm r0,r0,0,~MSR_DR
+ sync
+ mtmsr r0
+ isync
+
+ /* Stop DST streams */
+BEGIN_FTR_SECTION
+ DSSALL
+ sync
+END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
+
+ /* Stop DPM */
+ mfspr r8,SPRN_HID0 /* Save SPRN_HID0 in r8 */
+ rlwinm r4,r8,0,12,10 /* Turn off HID0[DPM] */
+ sync
+ mtspr SPRN_HID0,r4 /* Disable DPM */
+ sync
+
+ /* disp-flush L1 */
+ li r4,0x4000
+ mtctr r4
+ lis r4,0xfff0
+1: lwzx r0,r0,r4
+ addi r4,r4,32
+ bdnz 1b
+ sync
+ isync
+
+ /* disable / invalidate / enable L1 data */
+ mfspr r3,SPRN_HID0
+ rlwinm r0,r0,0,~HID0_DCE
+ mtspr SPRN_HID0,r3
+ sync
+ isync
+ ori r3,r3,HID0_DCE|HID0_DCI
+ sync
+ isync
+ mtspr SPRN_HID0,r3
+ xori r3,r3,HID0_DCI
+ mtspr SPRN_HID0,r3
+ sync
+
+ /* Get the current enable bit of the L2CR into r4 */
+ mfspr r5,SPRN_L2CR
+ /* Set to data-only (pre-745x bit) */
+ oris r3,r5,L2CR_L2DO@h
+ b 2f
+ /* When disabling L2, code must be in L1 */
+ .balign 32
+1: mtspr SPRN_L2CR,r3
+3: sync
+ isync
+ b 1f
+2: b 3f
+3: sync
+ isync
+ b 1b
+1: /* disp-flush L2. The interesting thing here is that the L2 can be
+ * up to 2Mb ... so using the ROM, we'll end up wrapping back to memory
+ * but that is probbaly fine. We disp-flush over 4Mb to be safe
+ */
+ lis r4,2
+ mtctr r4
+ lis r4,0xfff0
+1: lwzx r0,r0,r4
+ addi r4,r4,32
+ bdnz 1b
+ sync
+ isync
+ /* now disable L2 */
+ rlwinm r5,r5,0,~L2CR_L2E
+ b 2f
+ /* When disabling L2, code must be in L1 */
+ .balign 32
+1: mtspr SPRN_L2CR,r5
+3: sync
+ isync
+ b 1f
+2: b 3f
+3: sync
+ isync
+ b 1b
+1: sync
+ isync
+ /* Invalidate L2. This is pre-745x, we clear the L2I bit ourselves */
+ oris r4,r5,L2CR_L2I@h
+ mtspr SPRN_L2CR,r4
+ sync
+ isync
+ xoris r4,r4,L2CR_L2I@h
+ sync
+ mtspr SPRN_L2CR,r4
+ sync
+
+ /* now disable the L1 data cache */
+ mfspr r0,SPRN_HID0
+ rlwinm r0,r0,0,~HID0_DCE
+ mtspr SPRN_HID0,r0
+ sync
+ isync
+
+ /* Restore HID0[DPM] to whatever it was before */
+ sync
+ mtspr SPRN_HID0,r8
+ sync
+
+ /* restore DR and EE */
+ sync
+ mtmsr r11
+ isync
+
+ mtlr r10
+ blr
+
+/* This code is for 745x processors */
+flush_disable_745x:
+ /* Turn off EE and DR in MSR */
+ mfmsr r11
+ rlwinm r0,r11,0,~MSR_EE
+ rlwinm r0,r0,0,~MSR_DR
+ sync
+ mtmsr r0
+ isync
+
+ /* Stop prefetch streams */
+ DSSALL
+ sync
+
+ /* Disable L2 prefetching */
+ mfspr r0,SPRN_MSSCR0
+ rlwinm r0,r0,0,0,29
+ mtspr SPRN_MSSCR0,r0
+ sync
+ isync
+ lis r4,0
+ dcbf 0,r4
+ dcbf 0,r4
+ dcbf 0,r4
+ dcbf 0,r4
+ dcbf 0,r4
+ dcbf 0,r4
+ dcbf 0,r4
+ dcbf 0,r4
+
+ /* Due to a bug with the HW flush on some CPU revs, we occasionally
+ * experience data corruption. I'm adding a displacement flush along
+ * with a dcbf loop over a few Mb to "help". The problem isn't totally
+ * fixed by this in theory, but at least, in practice, I couldn't reproduce
+ * it even with a big hammer...
+ */
+
+ lis r4,0x0002
+ mtctr r4
+ li r4,0
+1:
+ lwzx r0,r0,r4
+ addi r4,r4,32 /* Go to start of next cache line */
+ bdnz 1b
+ isync
+
+ /* Now, flush the first 4MB of memory */
+ lis r4,0x0002
+ mtctr r4
+ li r4,0
+ sync
+1:
+ dcbf 0,r4
+ addi r4,r4,32 /* Go to start of next cache line */
+ bdnz 1b
+
+ /* Flush and disable the L1 data cache */
+ mfspr r6,SPRN_LDSTCR
+ lis r3,0xfff0 /* read from ROM for displacement flush */
+ li r4,0xfe /* start with only way 0 unlocked */
+ li r5,128 /* 128 lines in each way */
+1: mtctr r5
+ rlwimi r6,r4,0,24,31
+ mtspr SPRN_LDSTCR,r6
+ sync
+ isync
+2: lwz r0,0(r3) /* touch each cache line */
+ addi r3,r3,32
+ bdnz 2b
+ rlwinm r4,r4,1,24,30 /* move on to the next way */
+ ori r4,r4,1
+ cmpwi r4,0xff /* all done? */
+ bne 1b
+ /* now unlock the L1 data cache */
+ li r4,0
+ rlwimi r6,r4,0,24,31
+ sync
+ mtspr SPRN_LDSTCR,r6
+ sync
+ isync
+
+ /* Flush the L2 cache using the hardware assist */
+ mfspr r3,SPRN_L2CR
+ cmpwi r3,0 /* check if it is enabled first */
+ bge 4f
+ oris r0,r3,(L2CR_L2IO_745x|L2CR_L2DO_745x)@h
+ b 2f
+ /* When disabling/locking L2, code must be in L1 */
+ .balign 32
+1: mtspr SPRN_L2CR,r0 /* lock the L2 cache */
+3: sync
+ isync
+ b 1f
+2: b 3f
+3: sync
+ isync
+ b 1b
+1: sync
+ isync
+ ori r0,r3,L2CR_L2HWF_745x
+ sync
+ mtspr SPRN_L2CR,r0 /* set the hardware flush bit */
+3: mfspr r0,SPRN_L2CR /* wait for it to go to 0 */
+ andi. r0,r0,L2CR_L2HWF_745x
+ bne 3b
+ sync
+ rlwinm r3,r3,0,~L2CR_L2E
+ b 2f
+ /* When disabling L2, code must be in L1 */
+ .balign 32
+1: mtspr SPRN_L2CR,r3 /* disable the L2 cache */
+3: sync
+ isync
+ b 1f
+2: b 3f
+3: sync
+ isync
+ b 1b
+1: sync
+ isync
+ oris r4,r3,L2CR_L2I@h
+ mtspr SPRN_L2CR,r4
+ sync
+ isync
+1: mfspr r4,SPRN_L2CR
+ andis. r0,r4,L2CR_L2I@h
+ bne 1b
+ sync
+
+BEGIN_FTR_SECTION
+ /* Flush the L3 cache using the hardware assist */
+4: mfspr r3,SPRN_L3CR
+ cmpwi r3,0 /* check if it is enabled */
+ bge 6f
+ oris r0,r3,L3CR_L3IO@h
+ ori r0,r0,L3CR_L3DO
+ sync
+ mtspr SPRN_L3CR,r0 /* lock the L3 cache */
+ sync
+ isync
+ ori r0,r0,L3CR_L3HWF
+ sync
+ mtspr SPRN_L3CR,r0 /* set the hardware flush bit */
+5: mfspr r0,SPRN_L3CR /* wait for it to go to zero */
+ andi. r0,r0,L3CR_L3HWF
+ bne 5b
+ rlwinm r3,r3,0,~L3CR_L3E
+ sync
+ mtspr SPRN_L3CR,r3 /* disable the L3 cache */
+ sync
+ ori r4,r3,L3CR_L3I
+ mtspr SPRN_L3CR,r4
+1: mfspr r4,SPRN_L3CR
+ andi. r0,r4,L3CR_L3I
+ bne 1b
+ sync
+END_FTR_SECTION_IFSET(CPU_FTR_L3CR)
+
+6: mfspr r0,SPRN_HID0 /* now disable the L1 data cache */
+ rlwinm r0,r0,0,~HID0_DCE
+ mtspr SPRN_HID0,r0
+ sync
+ isync
+ mtmsr r11 /* restore DR and EE */
+ isync
+ blr
diff --git a/arch/ppc/platforms/pmac_cpufreq.c b/arch/ppc/platforms/pmac_cpufreq.c
new file mode 100644
index 0000000..9c85f9c
--- /dev/null
+++ b/arch/ppc/platforms/pmac_cpufreq.c
@@ -0,0 +1,571 @@
+/*
+ * arch/ppc/platforms/pmac_cpufreq.c
+ *
+ * Copyright (C) 2002 - 2004 Benjamin Herrenschmidt <benh@kernel.crashing.org>
+ * Copyright (C) 2004 John Steele Scott <toojays@toojays.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/sched.h>
+#include <linux/adb.h>
+#include <linux/pmu.h>
+#include <linux/slab.h>
+#include <linux/cpufreq.h>
+#include <linux/init.h>
+#include <linux/sysdev.h>
+#include <linux/i2c.h>
+#include <linux/hardirq.h>
+#include <asm/prom.h>
+#include <asm/machdep.h>
+#include <asm/irq.h>
+#include <asm/pmac_feature.h>
+#include <asm/mmu_context.h>
+#include <asm/sections.h>
+#include <asm/cputable.h>
+#include <asm/time.h>
+#include <asm/system.h>
+#include <asm/open_pic.h>
+
+/* WARNING !!! This will cause calibrate_delay() to be called,
+ * but this is an __init function ! So you MUST go edit
+ * init/main.c to make it non-init before enabling DEBUG_FREQ
+ */
+#undef DEBUG_FREQ
+
+/*
+ * There is a problem with the core cpufreq code on SMP kernels,
+ * it won't recalculate the Bogomips properly
+ */
+#ifdef CONFIG_SMP
+#warning "WARNING, CPUFREQ not recommended on SMP kernels"
+#endif
+
+extern void low_choose_7447a_dfs(int dfs);
+extern void low_choose_750fx_pll(int pll);
+extern void low_sleep_handler(void);
+
+/*
+ * Currently, PowerMac cpufreq supports only high & low frequencies
+ * that are set by the firmware
+ */
+static unsigned int low_freq;
+static unsigned int hi_freq;
+static unsigned int cur_freq;
+
+/*
+ * Different models uses different mecanisms to switch the frequency
+ */
+static int (*set_speed_proc)(int low_speed);
+
+/*
+ * Some definitions used by the various speedprocs
+ */
+static u32 voltage_gpio;
+static u32 frequency_gpio;
+static u32 slew_done_gpio;
+
+
+#define PMAC_CPU_LOW_SPEED 1
+#define PMAC_CPU_HIGH_SPEED 0
+
+/* There are only two frequency states for each processor. Values
+ * are in kHz for the time being.
+ */
+#define CPUFREQ_HIGH PMAC_CPU_HIGH_SPEED
+#define CPUFREQ_LOW PMAC_CPU_LOW_SPEED
+
+static struct cpufreq_frequency_table pmac_cpu_freqs[] = {
+ {CPUFREQ_HIGH, 0},
+ {CPUFREQ_LOW, 0},
+ {0, CPUFREQ_TABLE_END},
+};
+
+static inline void wakeup_decrementer(void)
+{
+ set_dec(tb_ticks_per_jiffy);
+ /* No currently-supported powerbook has a 601,
+ * so use get_tbl, not native
+ */
+ last_jiffy_stamp(0) = tb_last_stamp = get_tbl();
+}
+
+#ifdef DEBUG_FREQ
+static inline void debug_calc_bogomips(void)
+{
+ /* This will cause a recalc of bogomips and display the
+ * result. We backup/restore the value to avoid affecting the
+ * core cpufreq framework's own calculation.
+ */
+ extern void calibrate_delay(void);
+
+ unsigned long save_lpj = loops_per_jiffy;
+ calibrate_delay();
+ loops_per_jiffy = save_lpj;
+}
+#endif /* DEBUG_FREQ */
+
+/* Switch CPU speed under 750FX CPU control
+ */
+static int __pmac cpu_750fx_cpu_speed(int low_speed)
+{
+#ifdef DEBUG_FREQ
+ printk(KERN_DEBUG "HID1, before: %x\n", mfspr(SPRN_HID1));
+#endif
+#ifdef CONFIG_6xx
+ low_choose_750fx_pll(low_speed);
+#endif
+#ifdef DEBUG_FREQ
+ printk(KERN_DEBUG "HID1, after: %x\n", mfspr(SPRN_HID1));
+ debug_calc_bogomips();
+#endif
+
+ return 0;
+}
+
+/* Switch CPU speed using DFS */
+static int __pmac dfs_set_cpu_speed(int low_speed)
+{
+ if (low_speed == 0) {
+ /* ramping up, set voltage first */
+ pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, voltage_gpio, 0x05);
+ /* Make sure we sleep for at least 1ms */
+ msleep(1);
+ }
+
+ /* set frequency */
+ low_choose_7447a_dfs(low_speed);
+
+ if (low_speed == 1) {
+ /* ramping down, set voltage last */
+ pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, voltage_gpio, 0x04);
+ msleep(1);
+ }
+
+ return 0;
+}
+
+static unsigned int __pmac dfs_get_cpu_speed(unsigned int cpu)
+{
+ if (mfspr(SPRN_HID1) & HID1_DFS)
+ return low_freq;
+ else
+ return hi_freq;
+}
+
+
+/* Switch CPU speed using slewing GPIOs
+ */
+static int __pmac gpios_set_cpu_speed(int low_speed)
+{
+ int gpio;
+
+ /* If ramping up, set voltage first */
+ if (low_speed == 0) {
+ pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, voltage_gpio, 0x05);
+ /* Delay is way too big but it's ok, we schedule */
+ msleep(10);
+ }
+
+ /* Set frequency */
+ pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, frequency_gpio,
+ low_speed ? 0x04 : 0x05);
+ udelay(200);
+ do {
+ set_current_state(TASK_UNINTERRUPTIBLE);
+ schedule_timeout(1);
+ gpio = pmac_call_feature(PMAC_FTR_READ_GPIO, NULL, slew_done_gpio, 0);
+ } while((gpio & 0x02) == 0);
+
+ /* If ramping down, set voltage last */
+ if (low_speed == 1) {
+ pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, voltage_gpio, 0x04);
+ /* Delay is way too big but it's ok, we schedule */
+ msleep(10);
+ }
+
+#ifdef DEBUG_FREQ
+ debug_calc_bogomips();
+#endif
+
+ return 0;
+}
+
+/* Switch CPU speed under PMU control
+ */
+static int __pmac pmu_set_cpu_speed(int low_speed)
+{
+ struct adb_request req;
+ unsigned long save_l2cr;
+ unsigned long save_l3cr;
+
+ preempt_disable();
+
+#ifdef DEBUG_FREQ
+ printk(KERN_DEBUG "HID1, before: %x\n", mfspr(SPRN_HID1));
+#endif
+ /* Disable all interrupt sources on openpic */
+ openpic_set_priority(0xf);
+
+ /* Make sure the decrementer won't interrupt us */
+ asm volatile("mtdec %0" : : "r" (0x7fffffff));
+ /* Make sure any pending DEC interrupt occuring while we did
+ * the above didn't re-enable the DEC */
+ mb();
+ asm volatile("mtdec %0" : : "r" (0x7fffffff));
+
+ /* We can now disable MSR_EE */
+ local_irq_disable();
+
+ /* Giveup the FPU & vec */
+ enable_kernel_fp();
+
+#ifdef CONFIG_ALTIVEC
+ if (cpu_has_feature(CPU_FTR_ALTIVEC))
+ enable_kernel_altivec();
+#endif /* CONFIG_ALTIVEC */
+
+ /* Save & disable L2 and L3 caches */
+ save_l3cr = _get_L3CR(); /* (returns -1 if not available) */
+ save_l2cr = _get_L2CR(); /* (returns -1 if not available) */
+
+ /* Send the new speed command. My assumption is that this command
+ * will cause PLL_CFG[0..3] to be changed next time CPU goes to sleep
+ */
+ pmu_request(&req, NULL, 6, PMU_CPU_SPEED, 'W', 'O', 'O', 'F', low_speed);
+ while (!req.complete)
+ pmu_poll();
+
+ /* Prepare the northbridge for the speed transition */
+ pmac_call_feature(PMAC_FTR_SLEEP_STATE,NULL,1,1);
+
+ /* Call low level code to backup CPU state and recover from
+ * hardware reset
+ */
+ low_sleep_handler();
+
+ /* Restore the northbridge */
+ pmac_call_feature(PMAC_FTR_SLEEP_STATE,NULL,1,0);
+
+ /* Restore L2 cache */
+ if (save_l2cr != 0xffffffff && (save_l2cr & L2CR_L2E) != 0)
+ _set_L2CR(save_l2cr);
+ /* Restore L3 cache */
+ if (save_l3cr != 0xffffffff && (save_l3cr & L3CR_L3E) != 0)
+ _set_L3CR(save_l3cr);
+
+ /* Restore userland MMU context */
+ set_context(current->active_mm->context, current->active_mm->pgd);
+
+#ifdef DEBUG_FREQ
+ printk(KERN_DEBUG "HID1, after: %x\n", mfspr(SPRN_HID1));
+#endif
+
+ /* Restore low level PMU operations */
+ pmu_unlock();
+
+ /* Restore decrementer */
+ wakeup_decrementer();
+
+ /* Restore interrupts */
+ openpic_set_priority(0);
+
+ /* Let interrupts flow again ... */
+ local_irq_enable();
+
+#ifdef DEBUG_FREQ
+ debug_calc_bogomips();
+#endif
+
+ preempt_enable();
+
+ return 0;
+}
+
+static int __pmac do_set_cpu_speed(int speed_mode)
+{
+ struct cpufreq_freqs freqs;
+
+ freqs.old = cur_freq;
+ freqs.new = (speed_mode == PMAC_CPU_HIGH_SPEED) ? hi_freq : low_freq;
+ freqs.cpu = smp_processor_id();
+
+ if (freqs.old == freqs.new)
+ return 0;
+
+ cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
+ set_speed_proc(speed_mode == PMAC_CPU_LOW_SPEED);
+ cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
+ cur_freq = (speed_mode == PMAC_CPU_HIGH_SPEED) ? hi_freq : low_freq;
+
+ return 0;
+}
+
+static int __pmac pmac_cpufreq_verify(struct cpufreq_policy *policy)
+{
+ return cpufreq_frequency_table_verify(policy, pmac_cpu_freqs);
+}
+
+static int __pmac pmac_cpufreq_target( struct cpufreq_policy *policy,
+ unsigned int target_freq,
+ unsigned int relation)
+{
+ unsigned int newstate = 0;
+
+ if (cpufreq_frequency_table_target(policy, pmac_cpu_freqs,
+ target_freq, relation, &newstate))
+ return -EINVAL;
+
+ return do_set_cpu_speed(newstate);
+}
+
+unsigned int __pmac pmac_get_one_cpufreq(int i)
+{
+ /* Supports only one CPU for now */
+ return (i == 0) ? cur_freq : 0;
+}
+
+static int __pmac pmac_cpufreq_cpu_init(struct cpufreq_policy *policy)
+{
+ if (policy->cpu != 0)
+ return -ENODEV;
+
+ policy->governor = CPUFREQ_DEFAULT_GOVERNOR;
+ policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL;
+ policy->cur = cur_freq;
+
+ return cpufreq_frequency_table_cpuinfo(policy, &pmac_cpu_freqs[0]);
+}
+
+static u32 __pmac read_gpio(struct device_node *np)
+{
+ u32 *reg = (u32 *)get_property(np, "reg", NULL);
+
+ if (reg == NULL)
+ return 0;
+ /* That works for all keylargos but shall be fixed properly
+ * some day...
+ */
+ return 0x50 + (*reg);
+}
+
+static struct cpufreq_driver pmac_cpufreq_driver = {
+ .verify = pmac_cpufreq_verify,
+ .target = pmac_cpufreq_target,
+ .init = pmac_cpufreq_cpu_init,
+ .name = "powermac",
+ .owner = THIS_MODULE,
+};
+
+
+static int __pmac pmac_cpufreq_init_MacRISC3(struct device_node *cpunode)
+{
+ struct device_node *volt_gpio_np = of_find_node_by_name(NULL,
+ "voltage-gpio");
+ struct device_node *freq_gpio_np = of_find_node_by_name(NULL,
+ "frequency-gpio");
+ struct device_node *slew_done_gpio_np = of_find_node_by_name(NULL,
+ "slewing-done");
+ u32 *value;
+
+ /*
+ * Check to see if it's GPIO driven or PMU only
+ *
+ * The way we extract the GPIO address is slightly hackish, but it
+ * works well enough for now. We need to abstract the whole GPIO
+ * stuff sooner or later anyway
+ */
+
+ if (volt_gpio_np)
+ voltage_gpio = read_gpio(volt_gpio_np);
+ if (freq_gpio_np)
+ frequency_gpio = read_gpio(freq_gpio_np);
+ if (slew_done_gpio_np)
+ slew_done_gpio = read_gpio(slew_done_gpio_np);
+
+ /* If we use the frequency GPIOs, calculate the min/max speeds based
+ * on the bus frequencies
+ */
+ if (frequency_gpio && slew_done_gpio) {
+ int lenp, rc;
+ u32 *freqs, *ratio;
+
+ freqs = (u32 *)get_property(cpunode, "bus-frequencies", &lenp);
+ lenp /= sizeof(u32);
+ if (freqs == NULL || lenp != 2) {
+ printk(KERN_ERR "cpufreq: bus-frequencies incorrect or missing\n");
+ return 1;
+ }
+ ratio = (u32 *)get_property(cpunode, "processor-to-bus-ratio*2", NULL);
+ if (ratio == NULL) {
+ printk(KERN_ERR "cpufreq: processor-to-bus-ratio*2 missing\n");
+ return 1;
+ }
+
+ /* Get the min/max bus frequencies */
+ low_freq = min(freqs[0], freqs[1]);
+ hi_freq = max(freqs[0], freqs[1]);
+
+ /* Grrrr.. It _seems_ that the device-tree is lying on the low bus
+ * frequency, it claims it to be around 84Mhz on some models while
+ * it appears to be approx. 101Mhz on all. Let's hack around here...
+ * fortunately, we don't need to be too precise
+ */
+ if (low_freq < 98000000)
+ low_freq = 101000000;
+
+ /* Convert those to CPU core clocks */
+ low_freq = (low_freq * (*ratio)) / 2000;
+ hi_freq = (hi_freq * (*ratio)) / 2000;
+
+ /* Now we get the frequencies, we read the GPIO to see what is out current
+ * speed
+ */
+ rc = pmac_call_feature(PMAC_FTR_READ_GPIO, NULL, frequency_gpio, 0);
+ cur_freq = (rc & 0x01) ? hi_freq : low_freq;
+
+ set_speed_proc = gpios_set_cpu_speed;
+ return 1;
+ }
+
+ /* If we use the PMU, look for the min & max frequencies in the
+ * device-tree
+ */
+ value = (u32 *)get_property(cpunode, "min-clock-frequency", NULL);
+ if (!value)
+ return 1;
+ low_freq = (*value) / 1000;
+ /* The PowerBook G4 12" (PowerBook6,1) has an error in the device-tree
+ * here */
+ if (low_freq < 100000)
+ low_freq *= 10;
+
+ value = (u32 *)get_property(cpunode, "max-clock-frequency", NULL);
+ if (!value)
+ return 1;
+ hi_freq = (*value) / 1000;
+ set_speed_proc = pmu_set_cpu_speed;
+
+ return 0;
+}
+
+static int __pmac pmac_cpufreq_init_7447A(struct device_node *cpunode)
+{
+ struct device_node *volt_gpio_np;
+ u32 *reg;
+ struct cpufreq_driver *driver = &pmac_cpufreq_driver;
+
+ /* Look for voltage GPIO */
+ volt_gpio_np = of_find_node_by_name(NULL, "cpu-vcore-select");
+ reg = (u32 *)get_property(volt_gpio_np, "reg", NULL);
+ voltage_gpio = *reg;
+ if (!volt_gpio_np){
+ printk(KERN_ERR "cpufreq: missing cpu-vcore-select gpio\n");
+ return 1;
+ }
+
+ /* OF only reports the high frequency */
+ hi_freq = cur_freq;
+ low_freq = cur_freq/2;
+
+ /* Read actual frequency from CPU */
+ driver->get = dfs_get_cpu_speed;
+ cur_freq = driver->get(0);
+ set_speed_proc = dfs_set_cpu_speed;
+
+ return 0;
+}
+
+/* Currently, we support the following machines:
+ *
+ * - Titanium PowerBook 1Ghz (PMU based, 667Mhz & 1Ghz)
+ * - Titanium PowerBook 800 (PMU based, 667Mhz & 800Mhz)
+ * - Titanium PowerBook 400 (PMU based, 300Mhz & 400Mhz)
+ * - Titanium PowerBook 500 (PMU based, 300Mhz & 500Mhz)
+ * - iBook2 500/600 (PMU based, 400Mhz & 500/600Mhz)
+ * - iBook2 700 (CPU based, 400Mhz & 700Mhz, support low voltage)
+ * - Recent MacRISC3 laptops
+ * - All new machines with 7447A CPUs
+ */
+static int __init pmac_cpufreq_setup(void)
+{
+ struct device_node *cpunode;
+ u32 *value;
+
+ if (strstr(cmd_line, "nocpufreq"))
+ return 0;
+
+ /* Assume only one CPU */
+ cpunode = find_type_devices("cpu");
+ if (!cpunode)
+ goto out;
+
+ /* Get current cpu clock freq */
+ value = (u32 *)get_property(cpunode, "clock-frequency", NULL);
+ if (!value)
+ goto out;
+ cur_freq = (*value) / 1000;
+
+ /* Check for 7447A based MacRISC3 */
+ if (machine_is_compatible("MacRISC3") &&
+ get_property(cpunode, "dynamic-power-step", NULL) &&
+ PVR_VER(mfspr(SPRN_PVR)) == 0x8003) {
+ pmac_cpufreq_init_7447A(cpunode);
+ /* Check for other MacRISC3 machines */
+ } else if (machine_is_compatible("PowerBook3,4") ||
+ machine_is_compatible("PowerBook3,5") ||
+ machine_is_compatible("MacRISC3")) {
+ pmac_cpufreq_init_MacRISC3(cpunode);
+ /* Else check for iBook2 500/600 */
+ } else if (machine_is_compatible("PowerBook4,1")) {
+ hi_freq = cur_freq;
+ low_freq = 400000;
+ set_speed_proc = pmu_set_cpu_speed;
+ }
+ /* Else check for TiPb 400 & 500 */
+ else if (machine_is_compatible("PowerBook3,2")) {
+ /* We only know about the 400 MHz and the 500Mhz model
+ * they both have 300 MHz as low frequency
+ */
+ if (cur_freq < 350000 || cur_freq > 550000)
+ goto out;
+ hi_freq = cur_freq;
+ low_freq = 300000;
+ set_speed_proc = pmu_set_cpu_speed;
+ }
+ /* Else check for 750FX */
+ else if (PVR_VER(mfspr(SPRN_PVR)) == 0x7000) {
+ if (get_property(cpunode, "dynamic-power-step", NULL) == NULL)
+ goto out;
+ hi_freq = cur_freq;
+ value = (u32 *)get_property(cpunode, "reduced-clock-frequency", NULL);
+ if (!value)
+ goto out;
+ low_freq = (*value) / 1000;
+ set_speed_proc = cpu_750fx_cpu_speed;
+ }
+out:
+ if (set_speed_proc == NULL)
+ return -ENODEV;
+
+ pmac_cpu_freqs[CPUFREQ_LOW].frequency = low_freq;
+ pmac_cpu_freqs[CPUFREQ_HIGH].frequency = hi_freq;
+
+ printk(KERN_INFO "Registering PowerMac CPU frequency driver\n");
+ printk(KERN_INFO "Low: %d Mhz, High: %d Mhz, Boot: %d Mhz\n",
+ low_freq/1000, hi_freq/1000, cur_freq/1000);
+
+ return cpufreq_register_driver(&pmac_cpufreq_driver);
+}
+
+module_init(pmac_cpufreq_setup);
+
diff --git a/arch/ppc/platforms/pmac_feature.c b/arch/ppc/platforms/pmac_feature.c
new file mode 100644
index 0000000..8e60550
--- /dev/null
+++ b/arch/ppc/platforms/pmac_feature.c
@@ -0,0 +1,2972 @@
+/*
+ * arch/ppc/platforms/pmac_feature.c
+ *
+ * Copyright (C) 1996-2001 Paul Mackerras (paulus@cs.anu.edu.au)
+ * Ben. Herrenschmidt (benh@kernel.crashing.org)
+ *
+ * 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.
+ *
+ * TODO:
+ *
+ * - Replace mdelay with some schedule loop if possible
+ * - Shorten some obfuscated delays on some routines (like modem
+ * power)
+ * - Refcount some clocks (see darwin)
+ * - Split split split...
+ *
+ */
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/spinlock.h>
+#include <linux/adb.h>
+#include <linux/pmu.h>
+#include <linux/ioport.h>
+#include <linux/pci.h>
+#include <asm/sections.h>
+#include <asm/errno.h>
+#include <asm/ohare.h>
+#include <asm/heathrow.h>
+#include <asm/keylargo.h>
+#include <asm/uninorth.h>
+#include <asm/io.h>
+#include <asm/prom.h>
+#include <asm/machdep.h>
+#include <asm/pmac_feature.h>
+#include <asm/dbdma.h>
+#include <asm/pci-bridge.h>
+#include <asm/pmac_low_i2c.h>
+
+#undef DEBUG_FEATURE
+
+#ifdef DEBUG_FEATURE
+#define DBG(fmt,...) printk(KERN_DEBUG fmt)
+#else
+#define DBG(fmt,...)
+#endif
+
+#ifdef CONFIG_6xx
+extern int powersave_lowspeed;
+#endif
+
+extern int powersave_nap;
+extern struct device_node *k2_skiplist[2];
+
+
+/*
+ * We use a single global lock to protect accesses. Each driver has
+ * to take care of its own locking
+ */
+static DEFINE_SPINLOCK(feature_lock __pmacdata);
+
+#define LOCK(flags) spin_lock_irqsave(&feature_lock, flags);
+#define UNLOCK(flags) spin_unlock_irqrestore(&feature_lock, flags);
+
+
+/*
+ * Instance of some macio stuffs
+ */
+struct macio_chip macio_chips[MAX_MACIO_CHIPS] __pmacdata;
+
+struct macio_chip* __pmac
+macio_find(struct device_node* child, int type)
+{
+ while(child) {
+ int i;
+
+ for (i=0; i < MAX_MACIO_CHIPS && macio_chips[i].of_node; i++)
+ if (child == macio_chips[i].of_node &&
+ (!type || macio_chips[i].type == type))
+ return &macio_chips[i];
+ child = child->parent;
+ }
+ return NULL;
+}
+
+static const char* macio_names[] __pmacdata =
+{
+ "Unknown",
+ "Grand Central",
+ "OHare",
+ "OHareII",
+ "Heathrow",
+ "Gatwick",
+ "Paddington",
+ "Keylargo",
+ "Pangea",
+ "Intrepid",
+ "K2"
+};
+
+
+
+/*
+ * Uninorth reg. access. Note that Uni-N regs are big endian
+ */
+
+#define UN_REG(r) (uninorth_base + ((r) >> 2))
+#define UN_IN(r) (in_be32(UN_REG(r)))
+#define UN_OUT(r,v) (out_be32(UN_REG(r), (v)))
+#define UN_BIS(r,v) (UN_OUT((r), UN_IN(r) | (v)))
+#define UN_BIC(r,v) (UN_OUT((r), UN_IN(r) & ~(v)))
+
+static struct device_node* uninorth_node __pmacdata;
+static u32 __iomem * uninorth_base __pmacdata;
+static u32 uninorth_rev __pmacdata;
+static int uninorth_u3 __pmacdata;
+static void __iomem *u3_ht;
+
+/*
+ * For each motherboard family, we have a table of functions pointers
+ * that handle the various features.
+ */
+
+typedef long (*feature_call)(struct device_node* node, long param, long value);
+
+struct feature_table_entry {
+ unsigned int selector;
+ feature_call function;
+};
+
+struct pmac_mb_def
+{
+ const char* model_string;
+ const char* model_name;
+ int model_id;
+ struct feature_table_entry* features;
+ unsigned long board_flags;
+};
+static struct pmac_mb_def pmac_mb __pmacdata;
+
+/*
+ * Here are the chip specific feature functions
+ */
+
+static inline int __pmac
+simple_feature_tweak(struct device_node* node, int type, int reg, u32 mask, int value)
+{
+ struct macio_chip* macio;
+ unsigned long flags;
+
+ macio = macio_find(node, type);
+ if (!macio)
+ return -ENODEV;
+ LOCK(flags);
+ if (value)
+ MACIO_BIS(reg, mask);
+ else
+ MACIO_BIC(reg, mask);
+ (void)MACIO_IN32(reg);
+ UNLOCK(flags);
+
+ return 0;
+}
+
+#ifndef CONFIG_POWER4
+
+static long __pmac
+ohare_htw_scc_enable(struct device_node* node, long param, long value)
+{
+ struct macio_chip* macio;
+ unsigned long chan_mask;
+ unsigned long fcr;
+ unsigned long flags;
+ int htw, trans;
+ unsigned long rmask;
+
+ macio = macio_find(node, 0);
+ if (!macio)
+ return -ENODEV;
+ if (!strcmp(node->name, "ch-a"))
+ chan_mask = MACIO_FLAG_SCCA_ON;
+ else if (!strcmp(node->name, "ch-b"))
+ chan_mask = MACIO_FLAG_SCCB_ON;
+ else
+ return -ENODEV;
+
+ htw = (macio->type == macio_heathrow || macio->type == macio_paddington
+ || macio->type == macio_gatwick);
+ /* On these machines, the HRW_SCC_TRANS_EN_N bit mustn't be touched */
+ trans = (pmac_mb.model_id != PMAC_TYPE_YOSEMITE &&
+ pmac_mb.model_id != PMAC_TYPE_YIKES);
+ if (value) {
+#ifdef CONFIG_ADB_PMU
+ if ((param & 0xfff) == PMAC_SCC_IRDA)
+ pmu_enable_irled(1);
+#endif /* CONFIG_ADB_PMU */
+ LOCK(flags);
+ fcr = MACIO_IN32(OHARE_FCR);
+ /* Check if scc cell need enabling */
+ if (!(fcr & OH_SCC_ENABLE)) {
+ fcr |= OH_SCC_ENABLE;
+ if (htw) {
+ /* Side effect: this will also power up the
+ * modem, but it's too messy to figure out on which
+ * ports this controls the tranceiver and on which
+ * it controls the modem
+ */
+ if (trans)
+ fcr &= ~HRW_SCC_TRANS_EN_N;
+ MACIO_OUT32(OHARE_FCR, fcr);
+ fcr |= (rmask = HRW_RESET_SCC);
+ MACIO_OUT32(OHARE_FCR, fcr);
+ } else {
+ fcr |= (rmask = OH_SCC_RESET);
+ MACIO_OUT32(OHARE_FCR, fcr);
+ }
+ UNLOCK(flags);
+ (void)MACIO_IN32(OHARE_FCR);
+ mdelay(15);
+ LOCK(flags);
+ fcr &= ~rmask;
+ MACIO_OUT32(OHARE_FCR, fcr);
+ }
+ if (chan_mask & MACIO_FLAG_SCCA_ON)
+ fcr |= OH_SCCA_IO;
+ if (chan_mask & MACIO_FLAG_SCCB_ON)
+ fcr |= OH_SCCB_IO;
+ MACIO_OUT32(OHARE_FCR, fcr);
+ macio->flags |= chan_mask;
+ UNLOCK(flags);
+ if (param & PMAC_SCC_FLAG_XMON)
+ macio->flags |= MACIO_FLAG_SCC_LOCKED;
+ } else {
+ if (macio->flags & MACIO_FLAG_SCC_LOCKED)
+ return -EPERM;
+ LOCK(flags);
+ fcr = MACIO_IN32(OHARE_FCR);
+ if (chan_mask & MACIO_FLAG_SCCA_ON)
+ fcr &= ~OH_SCCA_IO;
+ if (chan_mask & MACIO_FLAG_SCCB_ON)
+ fcr &= ~OH_SCCB_IO;
+ MACIO_OUT32(OHARE_FCR, fcr);
+ if ((fcr & (OH_SCCA_IO | OH_SCCB_IO)) == 0) {
+ fcr &= ~OH_SCC_ENABLE;
+ if (htw && trans)
+ fcr |= HRW_SCC_TRANS_EN_N;
+ MACIO_OUT32(OHARE_FCR, fcr);
+ }
+ macio->flags &= ~(chan_mask);
+ UNLOCK(flags);
+ mdelay(10);
+#ifdef CONFIG_ADB_PMU
+ if ((param & 0xfff) == PMAC_SCC_IRDA)
+ pmu_enable_irled(0);
+#endif /* CONFIG_ADB_PMU */
+ }
+ return 0;
+}
+
+static long __pmac
+ohare_floppy_enable(struct device_node* node, long param, long value)
+{
+ return simple_feature_tweak(node, macio_ohare,
+ OHARE_FCR, OH_FLOPPY_ENABLE, value);
+}
+
+static long __pmac
+ohare_mesh_enable(struct device_node* node, long param, long value)
+{
+ return simple_feature_tweak(node, macio_ohare,
+ OHARE_FCR, OH_MESH_ENABLE, value);
+}
+
+static long __pmac
+ohare_ide_enable(struct device_node* node, long param, long value)
+{
+ switch(param) {
+ case 0:
+ /* For some reason, setting the bit in set_initial_features()
+ * doesn't stick. I'm still investigating... --BenH.
+ */
+ if (value)
+ simple_feature_tweak(node, macio_ohare,
+ OHARE_FCR, OH_IOBUS_ENABLE, 1);
+ return simple_feature_tweak(node, macio_ohare,
+ OHARE_FCR, OH_IDE0_ENABLE, value);
+ case 1:
+ return simple_feature_tweak(node, macio_ohare,
+ OHARE_FCR, OH_BAY_IDE_ENABLE, value);
+ default:
+ return -ENODEV;
+ }
+}
+
+static long __pmac
+ohare_ide_reset(struct device_node* node, long param, long value)
+{
+ switch(param) {
+ case 0:
+ return simple_feature_tweak(node, macio_ohare,
+ OHARE_FCR, OH_IDE0_RESET_N, !value);
+ case 1:
+ return simple_feature_tweak(node, macio_ohare,
+ OHARE_FCR, OH_IDE1_RESET_N, !value);
+ default:
+ return -ENODEV;
+ }
+}
+
+static long __pmac
+ohare_sleep_state(struct device_node* node, long param, long value)
+{
+ struct macio_chip* macio = &macio_chips[0];
+
+ if ((pmac_mb.board_flags & PMAC_MB_CAN_SLEEP) == 0)
+ return -EPERM;
+ if (value == 1) {
+ MACIO_BIC(OHARE_FCR, OH_IOBUS_ENABLE);
+ } else if (value == 0) {
+ MACIO_BIS(OHARE_FCR, OH_IOBUS_ENABLE);
+ }
+
+ return 0;
+}
+
+static long __pmac
+heathrow_modem_enable(struct device_node* node, long param, long value)
+{
+ struct macio_chip* macio;
+ u8 gpio;
+ unsigned long flags;
+
+ macio = macio_find(node, macio_unknown);
+ if (!macio)
+ return -ENODEV;
+ gpio = MACIO_IN8(HRW_GPIO_MODEM_RESET) & ~1;
+ if (!value) {
+ LOCK(flags);
+ MACIO_OUT8(HRW_GPIO_MODEM_RESET, gpio);
+ UNLOCK(flags);
+ (void)MACIO_IN8(HRW_GPIO_MODEM_RESET);
+ mdelay(250);
+ }
+ if (pmac_mb.model_id != PMAC_TYPE_YOSEMITE &&
+ pmac_mb.model_id != PMAC_TYPE_YIKES) {
+ LOCK(flags);
+ if (value)
+ MACIO_BIC(HEATHROW_FCR, HRW_SCC_TRANS_EN_N);
+ else
+ MACIO_BIS(HEATHROW_FCR, HRW_SCC_TRANS_EN_N);
+ UNLOCK(flags);
+ (void)MACIO_IN32(HEATHROW_FCR);
+ mdelay(250);
+ }
+ if (value) {
+ LOCK(flags);
+ MACIO_OUT8(HRW_GPIO_MODEM_RESET, gpio | 1);
+ (void)MACIO_IN8(HRW_GPIO_MODEM_RESET);
+ UNLOCK(flags); mdelay(250); LOCK(flags);
+ MACIO_OUT8(HRW_GPIO_MODEM_RESET, gpio);
+ (void)MACIO_IN8(HRW_GPIO_MODEM_RESET);
+ UNLOCK(flags); mdelay(250); LOCK(flags);
+ MACIO_OUT8(HRW_GPIO_MODEM_RESET, gpio | 1);
+ (void)MACIO_IN8(HRW_GPIO_MODEM_RESET);
+ UNLOCK(flags); mdelay(250);
+ }
+ return 0;
+}
+
+static long __pmac
+heathrow_floppy_enable(struct device_node* node, long param, long value)
+{
+ return simple_feature_tweak(node, macio_unknown,
+ HEATHROW_FCR,
+ HRW_SWIM_ENABLE|HRW_BAY_FLOPPY_ENABLE,
+ value);
+}
+
+static long __pmac
+heathrow_mesh_enable(struct device_node* node, long param, long value)
+{
+ struct macio_chip* macio;
+ unsigned long flags;
+
+ macio = macio_find(node, macio_unknown);
+ if (!macio)
+ return -ENODEV;
+ LOCK(flags);
+ /* Set clear mesh cell enable */
+ if (value)
+ MACIO_BIS(HEATHROW_FCR, HRW_MESH_ENABLE);
+ else
+ MACIO_BIC(HEATHROW_FCR, HRW_MESH_ENABLE);
+ (void)MACIO_IN32(HEATHROW_FCR);
+ udelay(10);
+ /* Set/Clear termination power */
+ if (value)
+ MACIO_BIC(HEATHROW_MBCR, 0x04000000);
+ else
+ MACIO_BIS(HEATHROW_MBCR, 0x04000000);
+ (void)MACIO_IN32(HEATHROW_MBCR);
+ udelay(10);
+ UNLOCK(flags);
+
+ return 0;
+}
+
+static long __pmac
+heathrow_ide_enable(struct device_node* node, long param, long value)
+{
+ switch(param) {
+ case 0:
+ return simple_feature_tweak(node, macio_unknown,
+ HEATHROW_FCR, HRW_IDE0_ENABLE, value);
+ case 1:
+ return simple_feature_tweak(node, macio_unknown,
+ HEATHROW_FCR, HRW_BAY_IDE_ENABLE, value);
+ default:
+ return -ENODEV;
+ }
+}
+
+static long __pmac
+heathrow_ide_reset(struct device_node* node, long param, long value)
+{
+ switch(param) {
+ case 0:
+ return simple_feature_tweak(node, macio_unknown,
+ HEATHROW_FCR, HRW_IDE0_RESET_N, !value);
+ case 1:
+ return simple_feature_tweak(node, macio_unknown,
+ HEATHROW_FCR, HRW_IDE1_RESET_N, !value);
+ default:
+ return -ENODEV;
+ }
+}
+
+static long __pmac
+heathrow_bmac_enable(struct device_node* node, long param, long value)
+{
+ struct macio_chip* macio;
+ unsigned long flags;
+
+ macio = macio_find(node, 0);
+ if (!macio)
+ return -ENODEV;
+ if (value) {
+ LOCK(flags);
+ MACIO_BIS(HEATHROW_FCR, HRW_BMAC_IO_ENABLE);
+ MACIO_BIS(HEATHROW_FCR, HRW_BMAC_RESET);
+ UNLOCK(flags);
+ (void)MACIO_IN32(HEATHROW_FCR);
+ mdelay(10);
+ LOCK(flags);
+ MACIO_BIC(HEATHROW_FCR, HRW_BMAC_RESET);
+ UNLOCK(flags);
+ (void)MACIO_IN32(HEATHROW_FCR);
+ mdelay(10);
+ } else {
+ LOCK(flags);
+ MACIO_BIC(HEATHROW_FCR, HRW_BMAC_IO_ENABLE);
+ UNLOCK(flags);
+ }
+ return 0;
+}
+
+static long __pmac
+heathrow_sound_enable(struct device_node* node, long param, long value)
+{
+ struct macio_chip* macio;
+ unsigned long flags;
+
+ /* B&W G3 and Yikes don't support that properly (the
+ * sound appear to never come back after beeing shut down).
+ */
+ if (pmac_mb.model_id == PMAC_TYPE_YOSEMITE ||
+ pmac_mb.model_id == PMAC_TYPE_YIKES)
+ return 0;
+
+ macio = macio_find(node, 0);
+ if (!macio)
+ return -ENODEV;
+ if (value) {
+ LOCK(flags);
+ MACIO_BIS(HEATHROW_FCR, HRW_SOUND_CLK_ENABLE);
+ MACIO_BIC(HEATHROW_FCR, HRW_SOUND_POWER_N);
+ UNLOCK(flags);
+ (void)MACIO_IN32(HEATHROW_FCR);
+ } else {
+ LOCK(flags);
+ MACIO_BIS(HEATHROW_FCR, HRW_SOUND_POWER_N);
+ MACIO_BIC(HEATHROW_FCR, HRW_SOUND_CLK_ENABLE);
+ UNLOCK(flags);
+ }
+ return 0;
+}
+
+static u32 save_fcr[6] __pmacdata;
+static u32 save_mbcr __pmacdata;
+static u32 save_gpio_levels[2] __pmacdata;
+static u8 save_gpio_extint[KEYLARGO_GPIO_EXTINT_CNT] __pmacdata;
+static u8 save_gpio_normal[KEYLARGO_GPIO_CNT] __pmacdata;
+static u32 save_unin_clock_ctl __pmacdata;
+static struct dbdma_regs save_dbdma[13] __pmacdata;
+static struct dbdma_regs save_alt_dbdma[13] __pmacdata;
+
+static void __pmac
+dbdma_save(struct macio_chip* macio, struct dbdma_regs* save)
+{
+ int i;
+
+ /* Save state & config of DBDMA channels */
+ for (i=0; i<13; i++) {
+ volatile struct dbdma_regs __iomem * chan = (void __iomem *)
+ (macio->base + ((0x8000+i*0x100)>>2));
+ save[i].cmdptr_hi = in_le32(&chan->cmdptr_hi);
+ save[i].cmdptr = in_le32(&chan->cmdptr);
+ save[i].intr_sel = in_le32(&chan->intr_sel);
+ save[i].br_sel = in_le32(&chan->br_sel);
+ save[i].wait_sel = in_le32(&chan->wait_sel);
+ }
+}
+
+static void __pmac
+dbdma_restore(struct macio_chip* macio, struct dbdma_regs* save)
+{
+ int i;
+
+ /* Save state & config of DBDMA channels */
+ for (i=0; i<13; i++) {
+ volatile struct dbdma_regs __iomem * chan = (void __iomem *)
+ (macio->base + ((0x8000+i*0x100)>>2));
+ out_le32(&chan->control, (ACTIVE|DEAD|WAKE|FLUSH|PAUSE|RUN)<<16);
+ while (in_le32(&chan->status) & ACTIVE)
+ mb();
+ out_le32(&chan->cmdptr_hi, save[i].cmdptr_hi);
+ out_le32(&chan->cmdptr, save[i].cmdptr);
+ out_le32(&chan->intr_sel, save[i].intr_sel);
+ out_le32(&chan->br_sel, save[i].br_sel);
+ out_le32(&chan->wait_sel, save[i].wait_sel);
+ }
+}
+
+static void __pmac
+heathrow_sleep(struct macio_chip* macio, int secondary)
+{
+ if (secondary) {
+ dbdma_save(macio, save_alt_dbdma);
+ save_fcr[2] = MACIO_IN32(0x38);
+ save_fcr[3] = MACIO_IN32(0x3c);
+ } else {
+ dbdma_save(macio, save_dbdma);
+ save_fcr[0] = MACIO_IN32(0x38);
+ save_fcr[1] = MACIO_IN32(0x3c);
+ save_mbcr = MACIO_IN32(0x34);
+ /* Make sure sound is shut down */
+ MACIO_BIS(HEATHROW_FCR, HRW_SOUND_POWER_N);
+ MACIO_BIC(HEATHROW_FCR, HRW_SOUND_CLK_ENABLE);
+ /* This seems to be necessary as well or the fan
+ * keeps coming up and battery drains fast */
+ MACIO_BIC(HEATHROW_FCR, HRW_IOBUS_ENABLE);
+ MACIO_BIC(HEATHROW_FCR, HRW_IDE0_RESET_N);
+ /* Make sure eth is down even if module or sleep
+ * won't work properly */
+ MACIO_BIC(HEATHROW_FCR, HRW_BMAC_IO_ENABLE | HRW_BMAC_RESET);
+ }
+ /* Make sure modem is shut down */
+ MACIO_OUT8(HRW_GPIO_MODEM_RESET,
+ MACIO_IN8(HRW_GPIO_MODEM_RESET) & ~1);
+ MACIO_BIS(HEATHROW_FCR, HRW_SCC_TRANS_EN_N);
+ MACIO_BIC(HEATHROW_FCR, OH_SCCA_IO|OH_SCCB_IO|HRW_SCC_ENABLE);
+
+ /* Let things settle */
+ (void)MACIO_IN32(HEATHROW_FCR);
+}
+
+static void __pmac
+heathrow_wakeup(struct macio_chip* macio, int secondary)
+{
+ if (secondary) {
+ MACIO_OUT32(0x38, save_fcr[2]);
+ (void)MACIO_IN32(0x38);
+ mdelay(1);
+ MACIO_OUT32(0x3c, save_fcr[3]);
+ (void)MACIO_IN32(0x38);
+ mdelay(10);
+ dbdma_restore(macio, save_alt_dbdma);
+ } else {
+ MACIO_OUT32(0x38, save_fcr[0] | HRW_IOBUS_ENABLE);
+ (void)MACIO_IN32(0x38);
+ mdelay(1);
+ MACIO_OUT32(0x3c, save_fcr[1]);
+ (void)MACIO_IN32(0x38);
+ mdelay(1);
+ MACIO_OUT32(0x34, save_mbcr);
+ (void)MACIO_IN32(0x38);
+ mdelay(10);
+ dbdma_restore(macio, save_dbdma);
+ }
+}
+
+static long __pmac
+heathrow_sleep_state(struct device_node* node, long param, long value)
+{
+ if ((pmac_mb.board_flags & PMAC_MB_CAN_SLEEP) == 0)
+ return -EPERM;
+ if (value == 1) {
+ if (macio_chips[1].type == macio_gatwick)
+ heathrow_sleep(&macio_chips[0], 1);
+ heathrow_sleep(&macio_chips[0], 0);
+ } else if (value == 0) {
+ heathrow_wakeup(&macio_chips[0], 0);
+ if (macio_chips[1].type == macio_gatwick)
+ heathrow_wakeup(&macio_chips[0], 1);
+ }
+ return 0;
+}
+
+static long __pmac
+core99_scc_enable(struct device_node* node, long param, long value)
+{
+ struct macio_chip* macio;
+ unsigned long flags;
+ unsigned long chan_mask;
+ u32 fcr;
+
+ macio = macio_find(node, 0);
+ if (!macio)
+ return -ENODEV;
+ if (!strcmp(node->name, "ch-a"))
+ chan_mask = MACIO_FLAG_SCCA_ON;
+ else if (!strcmp(node->name, "ch-b"))
+ chan_mask = MACIO_FLAG_SCCB_ON;
+ else
+ return -ENODEV;
+
+ if (value) {
+ int need_reset_scc = 0;
+ int need_reset_irda = 0;
+
+ LOCK(flags);
+ fcr = MACIO_IN32(KEYLARGO_FCR0);
+ /* Check if scc cell need enabling */
+ if (!(fcr & KL0_SCC_CELL_ENABLE)) {
+ fcr |= KL0_SCC_CELL_ENABLE;
+ need_reset_scc = 1;
+ }
+ if (chan_mask & MACIO_FLAG_SCCA_ON) {
+ fcr |= KL0_SCCA_ENABLE;
+ /* Don't enable line drivers for I2S modem */
+ if ((param & 0xfff) == PMAC_SCC_I2S1)
+ fcr &= ~KL0_SCC_A_INTF_ENABLE;
+ else
+ fcr |= KL0_SCC_A_INTF_ENABLE;
+ }
+ if (chan_mask & MACIO_FLAG_SCCB_ON) {
+ fcr |= KL0_SCCB_ENABLE;
+ /* Perform irda specific inits */
+ if ((param & 0xfff) == PMAC_SCC_IRDA) {
+ fcr &= ~KL0_SCC_B_INTF_ENABLE;
+ fcr |= KL0_IRDA_ENABLE;
+ fcr |= KL0_IRDA_CLK32_ENABLE | KL0_IRDA_CLK19_ENABLE;
+ fcr |= KL0_IRDA_SOURCE1_SEL;
+ fcr &= ~(KL0_IRDA_FAST_CONNECT|KL0_IRDA_DEFAULT1|KL0_IRDA_DEFAULT0);
+ fcr &= ~(KL0_IRDA_SOURCE2_SEL|KL0_IRDA_HIGH_BAND);
+ need_reset_irda = 1;
+ } else
+ fcr |= KL0_SCC_B_INTF_ENABLE;
+ }
+ MACIO_OUT32(KEYLARGO_FCR0, fcr);
+ macio->flags |= chan_mask;
+ if (need_reset_scc) {
+ MACIO_BIS(KEYLARGO_FCR0, KL0_SCC_RESET);
+ (void)MACIO_IN32(KEYLARGO_FCR0);
+ UNLOCK(flags);
+ mdelay(15);
+ LOCK(flags);
+ MACIO_BIC(KEYLARGO_FCR0, KL0_SCC_RESET);
+ }
+ if (need_reset_irda) {
+ MACIO_BIS(KEYLARGO_FCR0, KL0_IRDA_RESET);
+ (void)MACIO_IN32(KEYLARGO_FCR0);
+ UNLOCK(flags);
+ mdelay(15);
+ LOCK(flags);
+ MACIO_BIC(KEYLARGO_FCR0, KL0_IRDA_RESET);
+ }
+ UNLOCK(flags);
+ if (param & PMAC_SCC_FLAG_XMON)
+ macio->flags |= MACIO_FLAG_SCC_LOCKED;
+ } else {
+ if (macio->flags & MACIO_FLAG_SCC_LOCKED)
+ return -EPERM;
+ LOCK(flags);
+ fcr = MACIO_IN32(KEYLARGO_FCR0);
+ if (chan_mask & MACIO_FLAG_SCCA_ON)
+ fcr &= ~KL0_SCCA_ENABLE;
+ if (chan_mask & MACIO_FLAG_SCCB_ON) {
+ fcr &= ~KL0_SCCB_ENABLE;
+ /* Perform irda specific clears */
+ if ((param & 0xfff) == PMAC_SCC_IRDA) {
+ fcr &= ~KL0_IRDA_ENABLE;
+ fcr &= ~(KL0_IRDA_CLK32_ENABLE | KL0_IRDA_CLK19_ENABLE);
+ fcr &= ~(KL0_IRDA_FAST_CONNECT|KL0_IRDA_DEFAULT1|KL0_IRDA_DEFAULT0);
+ fcr &= ~(KL0_IRDA_SOURCE1_SEL|KL0_IRDA_SOURCE2_SEL|KL0_IRDA_HIGH_BAND);
+ }
+ }
+ MACIO_OUT32(KEYLARGO_FCR0, fcr);
+ if ((fcr & (KL0_SCCA_ENABLE | KL0_SCCB_ENABLE)) == 0) {
+ fcr &= ~KL0_SCC_CELL_ENABLE;
+ MACIO_OUT32(KEYLARGO_FCR0, fcr);
+ }
+ macio->flags &= ~(chan_mask);
+ UNLOCK(flags);
+ mdelay(10);
+ }
+ return 0;
+}
+
+static long __pmac
+core99_modem_enable(struct device_node* node, long param, long value)
+{
+ struct macio_chip* macio;
+ u8 gpio;
+ unsigned long flags;
+
+ /* Hack for internal USB modem */
+ if (node == NULL) {
+ if (macio_chips[0].type != macio_keylargo)
+ return -ENODEV;
+ node = macio_chips[0].of_node;
+ }
+ macio = macio_find(node, 0);
+ if (!macio)
+ return -ENODEV;
+ gpio = MACIO_IN8(KL_GPIO_MODEM_RESET);
+ gpio |= KEYLARGO_GPIO_OUTPUT_ENABLE;
+ gpio &= ~KEYLARGO_GPIO_OUTOUT_DATA;
+
+ if (!value) {
+ LOCK(flags);
+ MACIO_OUT8(KL_GPIO_MODEM_RESET, gpio);
+ UNLOCK(flags);
+ (void)MACIO_IN8(KL_GPIO_MODEM_RESET);
+ mdelay(250);
+ }
+ LOCK(flags);
+ if (value) {
+ MACIO_BIC(KEYLARGO_FCR2, KL2_ALT_DATA_OUT);
+ UNLOCK(flags);
+ (void)MACIO_IN32(KEYLARGO_FCR2);
+ mdelay(250);
+ } else {
+ MACIO_BIS(KEYLARGO_FCR2, KL2_ALT_DATA_OUT);
+ UNLOCK(flags);
+ }
+ if (value) {
+ LOCK(flags);
+ MACIO_OUT8(KL_GPIO_MODEM_RESET, gpio | KEYLARGO_GPIO_OUTOUT_DATA);
+ (void)MACIO_IN8(KL_GPIO_MODEM_RESET);
+ UNLOCK(flags); mdelay(250); LOCK(flags);
+ MACIO_OUT8(KL_GPIO_MODEM_RESET, gpio);
+ (void)MACIO_IN8(KL_GPIO_MODEM_RESET);
+ UNLOCK(flags); mdelay(250); LOCK(flags);
+ MACIO_OUT8(KL_GPIO_MODEM_RESET, gpio | KEYLARGO_GPIO_OUTOUT_DATA);
+ (void)MACIO_IN8(KL_GPIO_MODEM_RESET);
+ UNLOCK(flags); mdelay(250);
+ }
+ return 0;
+}
+
+static long __pmac
+pangea_modem_enable(struct device_node* node, long param, long value)
+{
+ struct macio_chip* macio;
+ u8 gpio;
+ unsigned long flags;
+
+ /* Hack for internal USB modem */
+ if (node == NULL) {
+ if (macio_chips[0].type != macio_pangea &&
+ macio_chips[0].type != macio_intrepid)
+ return -ENODEV;
+ node = macio_chips[0].of_node;
+ }
+ macio = macio_find(node, 0);
+ if (!macio)
+ return -ENODEV;
+ gpio = MACIO_IN8(KL_GPIO_MODEM_RESET);
+ gpio |= KEYLARGO_GPIO_OUTPUT_ENABLE;
+ gpio &= ~KEYLARGO_GPIO_OUTOUT_DATA;
+
+ if (!value) {
+ LOCK(flags);
+ MACIO_OUT8(KL_GPIO_MODEM_RESET, gpio);
+ UNLOCK(flags);
+ (void)MACIO_IN8(KL_GPIO_MODEM_RESET);
+ mdelay(250);
+ }
+ LOCK(flags);
+ if (value) {
+ MACIO_OUT8(KL_GPIO_MODEM_POWER,
+ KEYLARGO_GPIO_OUTPUT_ENABLE);
+ UNLOCK(flags);
+ (void)MACIO_IN32(KEYLARGO_FCR2);
+ mdelay(250);
+ } else {
+ MACIO_OUT8(KL_GPIO_MODEM_POWER,
+ KEYLARGO_GPIO_OUTPUT_ENABLE | KEYLARGO_GPIO_OUTOUT_DATA);
+ UNLOCK(flags);
+ }
+ if (value) {
+ LOCK(flags);
+ MACIO_OUT8(KL_GPIO_MODEM_RESET, gpio | KEYLARGO_GPIO_OUTOUT_DATA);
+ (void)MACIO_IN8(KL_GPIO_MODEM_RESET);
+ UNLOCK(flags); mdelay(250); LOCK(flags);
+ MACIO_OUT8(KL_GPIO_MODEM_RESET, gpio);
+ (void)MACIO_IN8(KL_GPIO_MODEM_RESET);
+ UNLOCK(flags); mdelay(250); LOCK(flags);
+ MACIO_OUT8(KL_GPIO_MODEM_RESET, gpio | KEYLARGO_GPIO_OUTOUT_DATA);
+ (void)MACIO_IN8(KL_GPIO_MODEM_RESET);
+ UNLOCK(flags); mdelay(250);
+ }
+ return 0;
+}
+
+static long __pmac
+core99_ata100_enable(struct device_node* node, long value)
+{
+ unsigned long flags;
+ struct pci_dev *pdev = NULL;
+ u8 pbus, pid;
+
+ if (uninorth_rev < 0x24)
+ return -ENODEV;
+
+ LOCK(flags);
+ if (value)
+ UN_BIS(UNI_N_CLOCK_CNTL, UNI_N_CLOCK_CNTL_ATA100);
+ else
+ UN_BIC(UNI_N_CLOCK_CNTL, UNI_N_CLOCK_CNTL_ATA100);
+ (void)UN_IN(UNI_N_CLOCK_CNTL);
+ UNLOCK(flags);
+ udelay(20);
+
+ if (value) {
+ if (pci_device_from_OF_node(node, &pbus, &pid) == 0)
+ pdev = pci_find_slot(pbus, pid);
+ if (pdev == NULL)
+ return 0;
+ pci_enable_device(pdev);
+ pci_set_master(pdev);
+ }
+ return 0;
+}
+
+static long __pmac
+core99_ide_enable(struct device_node* node, long param, long value)
+{
+ /* Bus ID 0 to 2 are KeyLargo based IDE, busID 3 is U2
+ * based ata-100
+ */
+ switch(param) {
+ case 0:
+ return simple_feature_tweak(node, macio_unknown,
+ KEYLARGO_FCR1, KL1_EIDE0_ENABLE, value);
+ case 1:
+ return simple_feature_tweak(node, macio_unknown,
+ KEYLARGO_FCR1, KL1_EIDE1_ENABLE, value);
+ case 2:
+ return simple_feature_tweak(node, macio_unknown,
+ KEYLARGO_FCR1, KL1_UIDE_ENABLE, value);
+ case 3:
+ return core99_ata100_enable(node, value);
+ default:
+ return -ENODEV;
+ }
+}
+
+static long __pmac
+core99_ide_reset(struct device_node* node, long param, long value)
+{
+ switch(param) {
+ case 0:
+ return simple_feature_tweak(node, macio_unknown,
+ KEYLARGO_FCR1, KL1_EIDE0_RESET_N, !value);
+ case 1:
+ return simple_feature_tweak(node, macio_unknown,
+ KEYLARGO_FCR1, KL1_EIDE1_RESET_N, !value);
+ case 2:
+ return simple_feature_tweak(node, macio_unknown,
+ KEYLARGO_FCR1, KL1_UIDE_RESET_N, !value);
+ default:
+ return -ENODEV;
+ }
+}
+
+static long __pmac
+core99_gmac_enable(struct device_node* node, long param, long value)
+{
+ unsigned long flags;
+
+ LOCK(flags);
+ if (value)
+ UN_BIS(UNI_N_CLOCK_CNTL, UNI_N_CLOCK_CNTL_GMAC);
+ else
+ UN_BIC(UNI_N_CLOCK_CNTL, UNI_N_CLOCK_CNTL_GMAC);
+ (void)UN_IN(UNI_N_CLOCK_CNTL);
+ UNLOCK(flags);
+ udelay(20);
+
+ return 0;
+}
+
+static long __pmac
+core99_gmac_phy_reset(struct device_node* node, long param, long value)
+{
+ unsigned long flags;
+ struct macio_chip* macio;
+
+ macio = &macio_chips[0];
+ if (macio->type != macio_keylargo && macio->type != macio_pangea &&
+ macio->type != macio_intrepid)
+ return -ENODEV;
+
+ LOCK(flags);
+ MACIO_OUT8(KL_GPIO_ETH_PHY_RESET, KEYLARGO_GPIO_OUTPUT_ENABLE);
+ (void)MACIO_IN8(KL_GPIO_ETH_PHY_RESET);
+ UNLOCK(flags);
+ mdelay(10);
+ LOCK(flags);
+ MACIO_OUT8(KL_GPIO_ETH_PHY_RESET, /*KEYLARGO_GPIO_OUTPUT_ENABLE | */
+ KEYLARGO_GPIO_OUTOUT_DATA);
+ UNLOCK(flags);
+ mdelay(10);
+
+ return 0;
+}
+
+static long __pmac
+core99_sound_chip_enable(struct device_node* node, long param, long value)
+{
+ struct macio_chip* macio;
+ unsigned long flags;
+
+ macio = macio_find(node, 0);
+ if (!macio)
+ return -ENODEV;
+
+ /* Do a better probe code, screamer G4 desktops &
+ * iMacs can do that too, add a recalibrate in
+ * the driver as well
+ */
+ if (pmac_mb.model_id == PMAC_TYPE_PISMO ||
+ pmac_mb.model_id == PMAC_TYPE_TITANIUM) {
+ LOCK(flags);
+ if (value)
+ MACIO_OUT8(KL_GPIO_SOUND_POWER,
+ KEYLARGO_GPIO_OUTPUT_ENABLE |
+ KEYLARGO_GPIO_OUTOUT_DATA);
+ else
+ MACIO_OUT8(KL_GPIO_SOUND_POWER,
+ KEYLARGO_GPIO_OUTPUT_ENABLE);
+ (void)MACIO_IN8(KL_GPIO_SOUND_POWER);
+ UNLOCK(flags);
+ }
+ return 0;
+}
+
+static long __pmac
+core99_airport_enable(struct device_node* node, long param, long value)
+{
+ struct macio_chip* macio;
+ unsigned long flags;
+ int state;
+
+ macio = macio_find(node, 0);
+ if (!macio)
+ return -ENODEV;
+
+ /* Hint: we allow passing of macio itself for the sake of the
+ * sleep code
+ */
+ if (node != macio->of_node &&
+ (!node->parent || node->parent != macio->of_node))
+ return -ENODEV;
+ state = (macio->flags & MACIO_FLAG_AIRPORT_ON) != 0;
+ if (value == state)
+ return 0;
+ if (value) {
+ /* This code is a reproduction of OF enable-cardslot
+ * and init-wireless methods, slightly hacked until
+ * I got it working.
+ */
+ LOCK(flags);
+ MACIO_OUT8(KEYLARGO_GPIO_0+0xf, 5);
+ (void)MACIO_IN8(KEYLARGO_GPIO_0+0xf);
+ UNLOCK(flags);
+ mdelay(10);
+ LOCK(flags);
+ MACIO_OUT8(KEYLARGO_GPIO_0+0xf, 4);
+ (void)MACIO_IN8(KEYLARGO_GPIO_0+0xf);
+ UNLOCK(flags);
+
+ mdelay(10);
+
+ LOCK(flags);
+ MACIO_BIC(KEYLARGO_FCR2, KL2_CARDSEL_16);
+ (void)MACIO_IN32(KEYLARGO_FCR2);
+ udelay(10);
+ MACIO_OUT8(KEYLARGO_GPIO_EXTINT_0+0xb, 0);
+ (void)MACIO_IN8(KEYLARGO_GPIO_EXTINT_0+0xb);
+ udelay(10);
+ MACIO_OUT8(KEYLARGO_GPIO_EXTINT_0+0xa, 0x28);
+ (void)MACIO_IN8(KEYLARGO_GPIO_EXTINT_0+0xa);
+ udelay(10);
+ MACIO_OUT8(KEYLARGO_GPIO_EXTINT_0+0xd, 0x28);
+ (void)MACIO_IN8(KEYLARGO_GPIO_EXTINT_0+0xd);
+ udelay(10);
+ MACIO_OUT8(KEYLARGO_GPIO_0+0xd, 0x28);
+ (void)MACIO_IN8(KEYLARGO_GPIO_0+0xd);
+ udelay(10);
+ MACIO_OUT8(KEYLARGO_GPIO_0+0xe, 0x28);
+ (void)MACIO_IN8(KEYLARGO_GPIO_0+0xe);
+ UNLOCK(flags);
+ udelay(10);
+ MACIO_OUT32(0x1c000, 0);
+ mdelay(1);
+ MACIO_OUT8(0x1a3e0, 0x41);
+ (void)MACIO_IN8(0x1a3e0);
+ udelay(10);
+ LOCK(flags);
+ MACIO_BIS(KEYLARGO_FCR2, KL2_CARDSEL_16);
+ (void)MACIO_IN32(KEYLARGO_FCR2);
+ UNLOCK(flags);
+ mdelay(100);
+
+ macio->flags |= MACIO_FLAG_AIRPORT_ON;
+ } else {
+ LOCK(flags);
+ MACIO_BIC(KEYLARGO_FCR2, KL2_CARDSEL_16);
+ (void)MACIO_IN32(KEYLARGO_FCR2);
+ MACIO_OUT8(KL_GPIO_AIRPORT_0, 0);
+ MACIO_OUT8(KL_GPIO_AIRPORT_1, 0);
+ MACIO_OUT8(KL_GPIO_AIRPORT_2, 0);
+ MACIO_OUT8(KL_GPIO_AIRPORT_3, 0);
+ MACIO_OUT8(KL_GPIO_AIRPORT_4, 0);
+ (void)MACIO_IN8(KL_GPIO_AIRPORT_4);
+ UNLOCK(flags);
+
+ macio->flags &= ~MACIO_FLAG_AIRPORT_ON;
+ }
+ return 0;
+}
+
+#ifdef CONFIG_SMP
+static long __pmac
+core99_reset_cpu(struct device_node* node, long param, long value)
+{
+ unsigned int reset_io = 0;
+ unsigned long flags;
+ struct macio_chip* macio;
+ struct device_node* np;
+ const int dflt_reset_lines[] = { KL_GPIO_RESET_CPU0,
+ KL_GPIO_RESET_CPU1,
+ KL_GPIO_RESET_CPU2,
+ KL_GPIO_RESET_CPU3 };
+
+ macio = &macio_chips[0];
+ if (macio->type != macio_keylargo)
+ return -ENODEV;
+
+ np = find_path_device("/cpus");
+ if (np == NULL)
+ return -ENODEV;
+ for (np = np->child; np != NULL; np = np->sibling) {
+ u32* num = (u32 *)get_property(np, "reg", NULL);
+ u32* rst = (u32 *)get_property(np, "soft-reset", NULL);
+ if (num == NULL || rst == NULL)
+ continue;
+ if (param == *num) {
+ reset_io = *rst;
+ break;
+ }
+ }
+ if (np == NULL || reset_io == 0)
+ reset_io = dflt_reset_lines[param];
+
+ LOCK(flags);
+ MACIO_OUT8(reset_io, KEYLARGO_GPIO_OUTPUT_ENABLE);
+ (void)MACIO_IN8(reset_io);
+ udelay(1);
+ MACIO_OUT8(reset_io, 0);
+ (void)MACIO_IN8(reset_io);
+ UNLOCK(flags);
+
+ return 0;
+}
+#endif /* CONFIG_SMP */
+
+static long __pmac
+core99_usb_enable(struct device_node* node, long param, long value)
+{
+ struct macio_chip* macio;
+ unsigned long flags;
+ char* prop;
+ int number;
+ u32 reg;
+
+ macio = &macio_chips[0];
+ if (macio->type != macio_keylargo && macio->type != macio_pangea &&
+ macio->type != macio_intrepid)
+ return -ENODEV;
+
+ prop = (char *)get_property(node, "AAPL,clock-id", NULL);
+ if (!prop)
+ return -ENODEV;
+ if (strncmp(prop, "usb0u048", 8) == 0)
+ number = 0;
+ else if (strncmp(prop, "usb1u148", 8) == 0)
+ number = 2;
+ else if (strncmp(prop, "usb2u248", 8) == 0)
+ number = 4;
+ else
+ return -ENODEV;
+
+ /* Sorry for the brute-force locking, but this is only used during
+ * sleep and the timing seem to be critical
+ */
+ LOCK(flags);
+ if (value) {
+ /* Turn ON */
+ if (number == 0) {
+ MACIO_BIC(KEYLARGO_FCR0, (KL0_USB0_PAD_SUSPEND0 | KL0_USB0_PAD_SUSPEND1));
+ (void)MACIO_IN32(KEYLARGO_FCR0);
+ UNLOCK(flags);
+ mdelay(1);
+ LOCK(flags);
+ MACIO_BIS(KEYLARGO_FCR0, KL0_USB0_CELL_ENABLE);
+ } else if (number == 2) {
+ MACIO_BIC(KEYLARGO_FCR0, (KL0_USB1_PAD_SUSPEND0 | KL0_USB1_PAD_SUSPEND1));
+ UNLOCK(flags);
+ (void)MACIO_IN32(KEYLARGO_FCR0);
+ mdelay(1);
+ LOCK(flags);
+ MACIO_BIS(KEYLARGO_FCR0, KL0_USB1_CELL_ENABLE);
+ } else if (number == 4) {
+ MACIO_BIC(KEYLARGO_FCR1, (KL1_USB2_PAD_SUSPEND0 | KL1_USB2_PAD_SUSPEND1));
+ UNLOCK(flags);
+ (void)MACIO_IN32(KEYLARGO_FCR1);
+ mdelay(1);
+ LOCK(flags);
+ MACIO_BIS(KEYLARGO_FCR1, KL1_USB2_CELL_ENABLE);
+ }
+ if (number < 4) {
+ reg = MACIO_IN32(KEYLARGO_FCR4);
+ reg &= ~(KL4_PORT_WAKEUP_ENABLE(number) | KL4_PORT_RESUME_WAKE_EN(number) |
+ KL4_PORT_CONNECT_WAKE_EN(number) | KL4_PORT_DISCONNECT_WAKE_EN(number));
+ reg &= ~(KL4_PORT_WAKEUP_ENABLE(number+1) | KL4_PORT_RESUME_WAKE_EN(number+1) |
+ KL4_PORT_CONNECT_WAKE_EN(number+1) | KL4_PORT_DISCONNECT_WAKE_EN(number+1));
+ MACIO_OUT32(KEYLARGO_FCR4, reg);
+ (void)MACIO_IN32(KEYLARGO_FCR4);
+ udelay(10);
+ } else {
+ reg = MACIO_IN32(KEYLARGO_FCR3);
+ reg &= ~(KL3_IT_PORT_WAKEUP_ENABLE(0) | KL3_IT_PORT_RESUME_WAKE_EN(0) |
+ KL3_IT_PORT_CONNECT_WAKE_EN(0) | KL3_IT_PORT_DISCONNECT_WAKE_EN(0));
+ reg &= ~(KL3_IT_PORT_WAKEUP_ENABLE(1) | KL3_IT_PORT_RESUME_WAKE_EN(1) |
+ KL3_IT_PORT_CONNECT_WAKE_EN(1) | KL3_IT_PORT_DISCONNECT_WAKE_EN(1));
+ MACIO_OUT32(KEYLARGO_FCR3, reg);
+ (void)MACIO_IN32(KEYLARGO_FCR3);
+ udelay(10);
+ }
+ if (macio->type == macio_intrepid) {
+ /* wait for clock stopped bits to clear */
+ u32 test0 = 0, test1 = 0;
+ u32 status0, status1;
+ int timeout = 1000;
+
+ UNLOCK(flags);
+ switch (number) {
+ case 0:
+ test0 = UNI_N_CLOCK_STOPPED_USB0;
+ test1 = UNI_N_CLOCK_STOPPED_USB0PCI;
+ break;
+ case 2:
+ test0 = UNI_N_CLOCK_STOPPED_USB1;
+ test1 = UNI_N_CLOCK_STOPPED_USB1PCI;
+ break;
+ case 4:
+ test0 = UNI_N_CLOCK_STOPPED_USB2;
+ test1 = UNI_N_CLOCK_STOPPED_USB2PCI;
+ break;
+ }
+ do {
+ if (--timeout <= 0) {
+ printk(KERN_ERR "core99_usb_enable: "
+ "Timeout waiting for clocks\n");
+ break;
+ }
+ mdelay(1);
+ status0 = UN_IN(UNI_N_CLOCK_STOP_STATUS0);
+ status1 = UN_IN(UNI_N_CLOCK_STOP_STATUS1);
+ } while ((status0 & test0) | (status1 & test1));
+ LOCK(flags);
+ }
+ } else {
+ /* Turn OFF */
+ if (number < 4) {
+ reg = MACIO_IN32(KEYLARGO_FCR4);
+ reg |= KL4_PORT_WAKEUP_ENABLE(number) | KL4_PORT_RESUME_WAKE_EN(number) |
+ KL4_PORT_CONNECT_WAKE_EN(number) | KL4_PORT_DISCONNECT_WAKE_EN(number);
+ reg |= KL4_PORT_WAKEUP_ENABLE(number+1) | KL4_PORT_RESUME_WAKE_EN(number+1) |
+ KL4_PORT_CONNECT_WAKE_EN(number+1) | KL4_PORT_DISCONNECT_WAKE_EN(number+1);
+ MACIO_OUT32(KEYLARGO_FCR4, reg);
+ (void)MACIO_IN32(KEYLARGO_FCR4);
+ udelay(1);
+ } else {
+ reg = MACIO_IN32(KEYLARGO_FCR3);
+ reg |= KL3_IT_PORT_WAKEUP_ENABLE(0) | KL3_IT_PORT_RESUME_WAKE_EN(0) |
+ KL3_IT_PORT_CONNECT_WAKE_EN(0) | KL3_IT_PORT_DISCONNECT_WAKE_EN(0);
+ reg |= KL3_IT_PORT_WAKEUP_ENABLE(1) | KL3_IT_PORT_RESUME_WAKE_EN(1) |
+ KL3_IT_PORT_CONNECT_WAKE_EN(1) | KL3_IT_PORT_DISCONNECT_WAKE_EN(1);
+ MACIO_OUT32(KEYLARGO_FCR3, reg);
+ (void)MACIO_IN32(KEYLARGO_FCR3);
+ udelay(1);
+ }
+ if (number == 0) {
+ if (macio->type != macio_intrepid)
+ MACIO_BIC(KEYLARGO_FCR0, KL0_USB0_CELL_ENABLE);
+ (void)MACIO_IN32(KEYLARGO_FCR0);
+ udelay(1);
+ MACIO_BIS(KEYLARGO_FCR0, (KL0_USB0_PAD_SUSPEND0 | KL0_USB0_PAD_SUSPEND1));
+ (void)MACIO_IN32(KEYLARGO_FCR0);
+ } else if (number == 2) {
+ if (macio->type != macio_intrepid)
+ MACIO_BIC(KEYLARGO_FCR0, KL0_USB1_CELL_ENABLE);
+ (void)MACIO_IN32(KEYLARGO_FCR0);
+ udelay(1);
+ MACIO_BIS(KEYLARGO_FCR0, (KL0_USB1_PAD_SUSPEND0 | KL0_USB1_PAD_SUSPEND1));
+ (void)MACIO_IN32(KEYLARGO_FCR0);
+ } else if (number == 4) {
+ udelay(1);
+ MACIO_BIS(KEYLARGO_FCR1, (KL1_USB2_PAD_SUSPEND0 | KL1_USB2_PAD_SUSPEND1));
+ (void)MACIO_IN32(KEYLARGO_FCR1);
+ }
+ udelay(1);
+ }
+ UNLOCK(flags);
+
+ return 0;
+}
+
+static long __pmac
+core99_firewire_enable(struct device_node* node, long param, long value)
+{
+ unsigned long flags;
+ struct macio_chip* macio;
+
+ macio = &macio_chips[0];
+ if (macio->type != macio_keylargo && macio->type != macio_pangea &&
+ macio->type != macio_intrepid)
+ return -ENODEV;
+ if (!(macio->flags & MACIO_FLAG_FW_SUPPORTED))
+ return -ENODEV;
+
+ LOCK(flags);
+ if (value) {
+ UN_BIS(UNI_N_CLOCK_CNTL, UNI_N_CLOCK_CNTL_FW);
+ (void)UN_IN(UNI_N_CLOCK_CNTL);
+ } else {
+ UN_BIC(UNI_N_CLOCK_CNTL, UNI_N_CLOCK_CNTL_FW);
+ (void)UN_IN(UNI_N_CLOCK_CNTL);
+ }
+ UNLOCK(flags);
+ mdelay(1);
+
+ return 0;
+}
+
+static long __pmac
+core99_firewire_cable_power(struct device_node* node, long param, long value)
+{
+ unsigned long flags;
+ struct macio_chip* macio;
+
+ /* Trick: we allow NULL node */
+ if ((pmac_mb.board_flags & PMAC_MB_HAS_FW_POWER) == 0)
+ return -ENODEV;
+ macio = &macio_chips[0];
+ if (macio->type != macio_keylargo && macio->type != macio_pangea &&
+ macio->type != macio_intrepid)
+ return -ENODEV;
+ if (!(macio->flags & MACIO_FLAG_FW_SUPPORTED))
+ return -ENODEV;
+
+ LOCK(flags);
+ if (value) {
+ MACIO_OUT8(KL_GPIO_FW_CABLE_POWER , 0);
+ MACIO_IN8(KL_GPIO_FW_CABLE_POWER);
+ udelay(10);
+ } else {
+ MACIO_OUT8(KL_GPIO_FW_CABLE_POWER , 4);
+ MACIO_IN8(KL_GPIO_FW_CABLE_POWER); udelay(10);
+ }
+ UNLOCK(flags);
+ mdelay(1);
+
+ return 0;
+}
+
+static long __pmac
+intrepid_aack_delay_enable(struct device_node* node, long param, long value)
+{
+ unsigned long flags;
+
+ if (uninorth_rev < 0xd2)
+ return -ENODEV;
+
+ LOCK(flags);
+ if (param)
+ UN_BIS(UNI_N_AACK_DELAY, UNI_N_AACK_DELAY_ENABLE);
+ else
+ UN_BIC(UNI_N_AACK_DELAY, UNI_N_AACK_DELAY_ENABLE);
+ UNLOCK(flags);
+
+ return 0;
+}
+
+
+#endif /* CONFIG_POWER4 */
+
+static long __pmac
+core99_read_gpio(struct device_node* node, long param, long value)
+{
+ struct macio_chip* macio = &macio_chips[0];
+
+ return MACIO_IN8(param);
+}
+
+
+static long __pmac
+core99_write_gpio(struct device_node* node, long param, long value)
+{
+ struct macio_chip* macio = &macio_chips[0];
+
+ MACIO_OUT8(param, (u8)(value & 0xff));
+ return 0;
+}
+
+#ifdef CONFIG_POWER4
+
+static long __pmac
+g5_gmac_enable(struct device_node* node, long param, long value)
+{
+ struct macio_chip* macio = &macio_chips[0];
+ unsigned long flags;
+ u8 pbus, pid;
+
+ LOCK(flags);
+ if (value) {
+ MACIO_BIS(KEYLARGO_FCR1, K2_FCR1_GMAC_CLK_ENABLE);
+ mb();
+ k2_skiplist[0] = NULL;
+ } else {
+ k2_skiplist[0] = node;
+ mb();
+ MACIO_BIC(KEYLARGO_FCR1, K2_FCR1_GMAC_CLK_ENABLE);
+ }
+
+ UNLOCK(flags);
+ mdelay(1);
+
+ return 0;
+}
+
+static long __pmac
+g5_fw_enable(struct device_node* node, long param, long value)
+{
+ struct macio_chip* macio = &macio_chips[0];
+ unsigned long flags;
+
+ LOCK(flags);
+ if (value) {
+ MACIO_BIS(KEYLARGO_FCR1, K2_FCR1_FW_CLK_ENABLE);
+ mb();
+ k2_skiplist[1] = NULL;
+ } else {
+ k2_skiplist[1] = node;
+ mb();
+ MACIO_BIC(KEYLARGO_FCR1, K2_FCR1_FW_CLK_ENABLE);
+ }
+
+ UNLOCK(flags);
+ mdelay(1);
+
+ return 0;
+}
+
+static long __pmac
+g5_mpic_enable(struct device_node* node, long param, long value)
+{
+ unsigned long flags;
+
+ if (node->parent == NULL || strcmp(node->parent->name, "u3"))
+ return 0;
+
+ LOCK(flags);
+ UN_BIS(U3_TOGGLE_REG, U3_MPIC_RESET | U3_MPIC_OUTPUT_ENABLE);
+ UNLOCK(flags);
+
+ return 0;
+}
+
+#ifdef CONFIG_SMP
+static long __pmac
+g5_reset_cpu(struct device_node* node, long param, long value)
+{
+ unsigned int reset_io = 0;
+ unsigned long flags;
+ struct macio_chip* macio;
+ struct device_node* np;
+
+ macio = &macio_chips[0];
+ if (macio->type != macio_keylargo2)
+ return -ENODEV;
+
+ np = find_path_device("/cpus");
+ if (np == NULL)
+ return -ENODEV;
+ for (np = np->child; np != NULL; np = np->sibling) {
+ u32* num = (u32 *)get_property(np, "reg", NULL);
+ u32* rst = (u32 *)get_property(np, "soft-reset", NULL);
+ if (num == NULL || rst == NULL)
+ continue;
+ if (param == *num) {
+ reset_io = *rst;
+ break;
+ }
+ }
+ if (np == NULL || reset_io == 0)
+ return -ENODEV;
+
+ LOCK(flags);
+ MACIO_OUT8(reset_io, KEYLARGO_GPIO_OUTPUT_ENABLE);
+ (void)MACIO_IN8(reset_io);
+ udelay(1);
+ MACIO_OUT8(reset_io, 0);
+ (void)MACIO_IN8(reset_io);
+ UNLOCK(flags);
+
+ return 0;
+}
+#endif /* CONFIG_SMP */
+
+/*
+ * This can be called from pmac_smp so isn't static
+ *
+ * This takes the second CPU off the bus on dual CPU machines
+ * running UP
+ */
+void __pmac g5_phy_disable_cpu1(void)
+{
+ UN_OUT(U3_API_PHY_CONFIG_1, 0);
+}
+
+#endif /* CONFIG_POWER4 */
+
+#ifndef CONFIG_POWER4
+
+static void __pmac
+keylargo_shutdown(struct macio_chip* macio, int sleep_mode)
+{
+ u32 temp;
+
+ if (sleep_mode) {
+ mdelay(1);
+ MACIO_BIS(KEYLARGO_FCR0, KL0_USB_REF_SUSPEND);
+ (void)MACIO_IN32(KEYLARGO_FCR0);
+ mdelay(1);
+ }
+
+ MACIO_BIC(KEYLARGO_FCR0,KL0_SCCA_ENABLE | KL0_SCCB_ENABLE |
+ KL0_SCC_CELL_ENABLE |
+ KL0_IRDA_ENABLE | KL0_IRDA_CLK32_ENABLE |
+ KL0_IRDA_CLK19_ENABLE);
+
+ MACIO_BIC(KEYLARGO_MBCR, KL_MBCR_MB0_DEV_MASK);
+ MACIO_BIS(KEYLARGO_MBCR, KL_MBCR_MB0_IDE_ENABLE);
+
+ MACIO_BIC(KEYLARGO_FCR1,
+ KL1_AUDIO_SEL_22MCLK | KL1_AUDIO_CLK_ENABLE_BIT |
+ KL1_AUDIO_CLK_OUT_ENABLE | KL1_AUDIO_CELL_ENABLE |
+ KL1_I2S0_CELL_ENABLE | KL1_I2S0_CLK_ENABLE_BIT |
+ KL1_I2S0_ENABLE | KL1_I2S1_CELL_ENABLE |
+ KL1_I2S1_CLK_ENABLE_BIT | KL1_I2S1_ENABLE |
+ KL1_EIDE0_ENABLE | KL1_EIDE0_RESET_N |
+ KL1_EIDE1_ENABLE | KL1_EIDE1_RESET_N |
+ KL1_UIDE_ENABLE);
+
+ MACIO_BIS(KEYLARGO_FCR2, KL2_ALT_DATA_OUT);
+ MACIO_BIC(KEYLARGO_FCR2, KL2_IOBUS_ENABLE);
+
+ temp = MACIO_IN32(KEYLARGO_FCR3);
+ if (macio->rev >= 2) {
+ temp |= KL3_SHUTDOWN_PLL2X;
+ if (sleep_mode)
+ temp |= KL3_SHUTDOWN_PLL_TOTAL;
+ }
+
+ temp |= KL3_SHUTDOWN_PLLKW6 | KL3_SHUTDOWN_PLLKW4 |
+ KL3_SHUTDOWN_PLLKW35;
+ if (sleep_mode)
+ temp |= KL3_SHUTDOWN_PLLKW12;
+ temp &= ~(KL3_CLK66_ENABLE | KL3_CLK49_ENABLE | KL3_CLK45_ENABLE
+ | KL3_CLK31_ENABLE | KL3_I2S1_CLK18_ENABLE | KL3_I2S0_CLK18_ENABLE);
+ if (sleep_mode)
+ temp &= ~(KL3_TIMER_CLK18_ENABLE | KL3_VIA_CLK16_ENABLE);
+ MACIO_OUT32(KEYLARGO_FCR3, temp);
+
+ /* Flush posted writes & wait a bit */
+ (void)MACIO_IN32(KEYLARGO_FCR0); mdelay(1);
+}
+
+static void __pmac
+pangea_shutdown(struct macio_chip* macio, int sleep_mode)
+{
+ u32 temp;
+
+ MACIO_BIC(KEYLARGO_FCR0,KL0_SCCA_ENABLE | KL0_SCCB_ENABLE |
+ KL0_SCC_CELL_ENABLE |
+ KL0_USB0_CELL_ENABLE | KL0_USB1_CELL_ENABLE);
+
+ MACIO_BIC(KEYLARGO_FCR1,
+ KL1_AUDIO_SEL_22MCLK | KL1_AUDIO_CLK_ENABLE_BIT |
+ KL1_AUDIO_CLK_OUT_ENABLE | KL1_AUDIO_CELL_ENABLE |
+ KL1_I2S0_CELL_ENABLE | KL1_I2S0_CLK_ENABLE_BIT |
+ KL1_I2S0_ENABLE | KL1_I2S1_CELL_ENABLE |
+ KL1_I2S1_CLK_ENABLE_BIT | KL1_I2S1_ENABLE |
+ KL1_UIDE_ENABLE);
+ if (pmac_mb.board_flags & PMAC_MB_MOBILE)
+ MACIO_BIC(KEYLARGO_FCR1, KL1_UIDE_RESET_N);
+
+ MACIO_BIS(KEYLARGO_FCR2, KL2_ALT_DATA_OUT);
+
+ temp = MACIO_IN32(KEYLARGO_FCR3);
+ temp |= KL3_SHUTDOWN_PLLKW6 | KL3_SHUTDOWN_PLLKW4 |
+ KL3_SHUTDOWN_PLLKW35;
+ temp &= ~(KL3_CLK49_ENABLE | KL3_CLK45_ENABLE | KL3_CLK31_ENABLE
+ | KL3_I2S0_CLK18_ENABLE | KL3_I2S1_CLK18_ENABLE);
+ if (sleep_mode)
+ temp &= ~(KL3_VIA_CLK16_ENABLE | KL3_TIMER_CLK18_ENABLE);
+ MACIO_OUT32(KEYLARGO_FCR3, temp);
+
+ /* Flush posted writes & wait a bit */
+ (void)MACIO_IN32(KEYLARGO_FCR0); mdelay(1);
+}
+
+static void __pmac
+intrepid_shutdown(struct macio_chip* macio, int sleep_mode)
+{
+ u32 temp;
+
+ MACIO_BIC(KEYLARGO_FCR0,KL0_SCCA_ENABLE | KL0_SCCB_ENABLE |
+ KL0_SCC_CELL_ENABLE);
+
+ MACIO_BIC(KEYLARGO_FCR1,
+ /*KL1_USB2_CELL_ENABLE |*/
+ KL1_I2S0_CELL_ENABLE | KL1_I2S0_CLK_ENABLE_BIT |
+ KL1_I2S0_ENABLE | KL1_I2S1_CELL_ENABLE |
+ KL1_I2S1_CLK_ENABLE_BIT | KL1_I2S1_ENABLE);
+ if (pmac_mb.board_flags & PMAC_MB_MOBILE)
+ MACIO_BIC(KEYLARGO_FCR1, KL1_UIDE_RESET_N);
+
+ temp = MACIO_IN32(KEYLARGO_FCR3);
+ temp &= ~(KL3_CLK49_ENABLE | KL3_CLK45_ENABLE |
+ KL3_I2S1_CLK18_ENABLE | KL3_I2S0_CLK18_ENABLE);
+ if (sleep_mode)
+ temp &= ~(KL3_TIMER_CLK18_ENABLE | KL3_IT_VIA_CLK32_ENABLE);
+ MACIO_OUT32(KEYLARGO_FCR3, temp);
+
+ /* Flush posted writes & wait a bit */
+ (void)MACIO_IN32(KEYLARGO_FCR0);
+ mdelay(10);
+}
+
+static int __pmac
+core99_sleep(void)
+{
+ struct macio_chip* macio;
+ int i;
+
+ macio = &macio_chips[0];
+ if (macio->type != macio_keylargo && macio->type != macio_pangea &&
+ macio->type != macio_intrepid)
+ return -ENODEV;
+
+ /* The device-tree contains that in the hwclock node */
+ if (macio->type == macio_intrepid) {
+ UN_OUT(UNI_N_CLOCK_SPREADING, 0);
+ mdelay(40);
+ }
+
+ /* We power off the wireless slot in case it was not done
+ * by the driver. We don't power it on automatically however
+ */
+ if (macio->flags & MACIO_FLAG_AIRPORT_ON)
+ core99_airport_enable(macio->of_node, 0, 0);
+
+ /* We power off the FW cable. Should be done by the driver... */
+ if (macio->flags & MACIO_FLAG_FW_SUPPORTED) {
+ core99_firewire_enable(NULL, 0, 0);
+ core99_firewire_cable_power(NULL, 0, 0);
+ }
+
+ /* We make sure int. modem is off (in case driver lost it) */
+ if (macio->type == macio_keylargo)
+ core99_modem_enable(macio->of_node, 0, 0);
+ else
+ pangea_modem_enable(macio->of_node, 0, 0);
+
+ /* We make sure the sound is off as well */
+ core99_sound_chip_enable(macio->of_node, 0, 0);
+
+ /*
+ * Save various bits of KeyLargo
+ */
+
+ /* Save the state of the various GPIOs */
+ save_gpio_levels[0] = MACIO_IN32(KEYLARGO_GPIO_LEVELS0);
+ save_gpio_levels[1] = MACIO_IN32(KEYLARGO_GPIO_LEVELS1);
+ for (i=0; i<KEYLARGO_GPIO_EXTINT_CNT; i++)
+ save_gpio_extint[i] = MACIO_IN8(KEYLARGO_GPIO_EXTINT_0+i);
+ for (i=0; i<KEYLARGO_GPIO_CNT; i++)
+ save_gpio_normal[i] = MACIO_IN8(KEYLARGO_GPIO_0+i);
+
+ /* Save the FCRs */
+ if (macio->type == macio_keylargo)
+ save_mbcr = MACIO_IN32(KEYLARGO_MBCR);
+ save_fcr[0] = MACIO_IN32(KEYLARGO_FCR0);
+ save_fcr[1] = MACIO_IN32(KEYLARGO_FCR1);
+ save_fcr[2] = MACIO_IN32(KEYLARGO_FCR2);
+ save_fcr[3] = MACIO_IN32(KEYLARGO_FCR3);
+ save_fcr[4] = MACIO_IN32(KEYLARGO_FCR4);
+ if (macio->type == macio_pangea || macio->type == macio_intrepid)
+ save_fcr[5] = MACIO_IN32(KEYLARGO_FCR5);
+
+ /* Save state & config of DBDMA channels */
+ dbdma_save(macio, save_dbdma);
+
+ /*
+ * Turn off as much as we can
+ */
+ if (macio->type == macio_pangea)
+ pangea_shutdown(macio, 1);
+ else if (macio->type == macio_intrepid)
+ intrepid_shutdown(macio, 1);
+ else if (macio->type == macio_keylargo)
+ keylargo_shutdown(macio, 1);
+
+ /*
+ * Put the host bridge to sleep
+ */
+
+ save_unin_clock_ctl = UN_IN(UNI_N_CLOCK_CNTL);
+ /* Note: do not switch GMAC off, driver does it when necessary, WOL must keep it
+ * enabled !
+ */
+ UN_OUT(UNI_N_CLOCK_CNTL, save_unin_clock_ctl &
+ ~(/*UNI_N_CLOCK_CNTL_GMAC|*/UNI_N_CLOCK_CNTL_FW/*|UNI_N_CLOCK_CNTL_PCI*/));
+ udelay(100);
+ UN_OUT(UNI_N_HWINIT_STATE, UNI_N_HWINIT_STATE_SLEEPING);
+ UN_OUT(UNI_N_POWER_MGT, UNI_N_POWER_MGT_SLEEP);
+ mdelay(10);
+
+ /*
+ * FIXME: A bit of black magic with OpenPIC (don't ask me why)
+ */
+ if (pmac_mb.model_id == PMAC_TYPE_SAWTOOTH) {
+ MACIO_BIS(0x506e0, 0x00400000);
+ MACIO_BIS(0x506e0, 0x80000000);
+ }
+ return 0;
+}
+
+static int __pmac
+core99_wake_up(void)
+{
+ struct macio_chip* macio;
+ int i;
+
+ macio = &macio_chips[0];
+ if (macio->type != macio_keylargo && macio->type != macio_pangea &&
+ macio->type != macio_intrepid)
+ return -ENODEV;
+
+ /*
+ * Wakeup the host bridge
+ */
+ UN_OUT(UNI_N_POWER_MGT, UNI_N_POWER_MGT_NORMAL);
+ udelay(10);
+ UN_OUT(UNI_N_HWINIT_STATE, UNI_N_HWINIT_STATE_RUNNING);
+ udelay(10);
+
+ /*
+ * Restore KeyLargo
+ */
+
+ if (macio->type == macio_keylargo) {
+ MACIO_OUT32(KEYLARGO_MBCR, save_mbcr);
+ (void)MACIO_IN32(KEYLARGO_MBCR); udelay(10);
+ }
+ MACIO_OUT32(KEYLARGO_FCR0, save_fcr[0]);
+ (void)MACIO_IN32(KEYLARGO_FCR0); udelay(10);
+ MACIO_OUT32(KEYLARGO_FCR1, save_fcr[1]);
+ (void)MACIO_IN32(KEYLARGO_FCR1); udelay(10);
+ MACIO_OUT32(KEYLARGO_FCR2, save_fcr[2]);
+ (void)MACIO_IN32(KEYLARGO_FCR2); udelay(10);
+ MACIO_OUT32(KEYLARGO_FCR3, save_fcr[3]);
+ (void)MACIO_IN32(KEYLARGO_FCR3); udelay(10);
+ MACIO_OUT32(KEYLARGO_FCR4, save_fcr[4]);
+ (void)MACIO_IN32(KEYLARGO_FCR4); udelay(10);
+ if (macio->type == macio_pangea || macio->type == macio_intrepid) {
+ MACIO_OUT32(KEYLARGO_FCR5, save_fcr[5]);
+ (void)MACIO_IN32(KEYLARGO_FCR5); udelay(10);
+ }
+
+ dbdma_restore(macio, save_dbdma);
+
+ MACIO_OUT32(KEYLARGO_GPIO_LEVELS0, save_gpio_levels[0]);
+ MACIO_OUT32(KEYLARGO_GPIO_LEVELS1, save_gpio_levels[1]);
+ for (i=0; i<KEYLARGO_GPIO_EXTINT_CNT; i++)
+ MACIO_OUT8(KEYLARGO_GPIO_EXTINT_0+i, save_gpio_extint[i]);
+ for (i=0; i<KEYLARGO_GPIO_CNT; i++)
+ MACIO_OUT8(KEYLARGO_GPIO_0+i, save_gpio_normal[i]);
+
+ /* FIXME more black magic with OpenPIC ... */
+ if (pmac_mb.model_id == PMAC_TYPE_SAWTOOTH) {
+ MACIO_BIC(0x506e0, 0x00400000);
+ MACIO_BIC(0x506e0, 0x80000000);
+ }
+
+ UN_OUT(UNI_N_CLOCK_CNTL, save_unin_clock_ctl);
+ udelay(100);
+
+ /* Restore clock spreading */
+ if (macio->type == macio_intrepid) {
+ UN_OUT(UNI_N_CLOCK_SPREADING, 2);
+ mdelay(40);
+ }
+
+ return 0;
+}
+
+static long __pmac
+core99_sleep_state(struct device_node* node, long param, long value)
+{
+ /* Param == 1 means to enter the "fake sleep" mode that is
+ * used for CPU speed switch
+ */
+ if (param == 1) {
+ if (value == 1) {
+ UN_OUT(UNI_N_HWINIT_STATE, UNI_N_HWINIT_STATE_SLEEPING);
+ UN_OUT(UNI_N_POWER_MGT, UNI_N_POWER_MGT_IDLE2);
+ } else {
+ UN_OUT(UNI_N_POWER_MGT, UNI_N_POWER_MGT_NORMAL);
+ udelay(10);
+ UN_OUT(UNI_N_HWINIT_STATE, UNI_N_HWINIT_STATE_RUNNING);
+ udelay(10);
+ }
+ return 0;
+ }
+ if ((pmac_mb.board_flags & PMAC_MB_CAN_SLEEP) == 0)
+ return -EPERM;
+
+#ifdef CONFIG_CPU_FREQ_PMAC
+ /* XXX should be elsewhere */
+ if (machine_is_compatible("PowerBook6,5") ||
+ machine_is_compatible("PowerBook6,4") ||
+ machine_is_compatible("PowerBook5,5") ||
+ machine_is_compatible("PowerBook5,4")) {
+ struct device_node *volt_gpio_np;
+ u32 *reg = NULL;
+
+ volt_gpio_np = of_find_node_by_name(NULL, "cpu-vcore-select");
+ if (volt_gpio_np != NULL)
+ reg = (u32 *)get_property(volt_gpio_np, "reg", NULL);
+ if (reg != NULL) {
+ /* Set the CPU voltage high if sleeping */
+ if (value == 1) {
+ pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL,
+ *reg, 0x05);
+ } else if (value == 0 && (mfspr(SPRN_HID1) & HID1_DFS)) {
+ pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL,
+ *reg, 0x04);
+ }
+ mdelay(2);
+ }
+ }
+#endif /* CONFIG_CPU_FREQ_PMAC */
+
+ if (value == 1)
+ return core99_sleep();
+ else if (value == 0)
+ return core99_wake_up();
+ return 0;
+}
+
+#endif /* CONFIG_POWER4 */
+
+static long __pmac
+generic_dev_can_wake(struct device_node* node, long param, long value)
+{
+ /* Todo: eventually check we are really dealing with on-board
+ * video device ...
+ */
+
+ if (pmac_mb.board_flags & PMAC_MB_MAY_SLEEP)
+ pmac_mb.board_flags |= PMAC_MB_CAN_SLEEP;
+ return 0;
+}
+
+static long __pmac
+generic_get_mb_info(struct device_node* node, long param, long value)
+{
+ switch(param) {
+ case PMAC_MB_INFO_MODEL:
+ return pmac_mb.model_id;
+ case PMAC_MB_INFO_FLAGS:
+ return pmac_mb.board_flags;
+ case PMAC_MB_INFO_NAME:
+ /* hack hack hack... but should work */
+ *((const char **)value) = pmac_mb.model_name;
+ return 0;
+ }
+ return -EINVAL;
+}
+
+
+/*
+ * Table definitions
+ */
+
+/* Used on any machine
+ */
+static struct feature_table_entry any_features[] __pmacdata = {
+ { PMAC_FTR_GET_MB_INFO, generic_get_mb_info },
+ { PMAC_FTR_DEVICE_CAN_WAKE, generic_dev_can_wake },
+ { 0, NULL }
+};
+
+#ifndef CONFIG_POWER4
+
+/* OHare based motherboards. Currently, we only use these on the
+ * 2400,3400 and 3500 series powerbooks. Some older desktops seem
+ * to have issues with turning on/off those asic cells
+ */
+static struct feature_table_entry ohare_features[] __pmacdata = {
+ { PMAC_FTR_SCC_ENABLE, ohare_htw_scc_enable },
+ { PMAC_FTR_SWIM3_ENABLE, ohare_floppy_enable },
+ { PMAC_FTR_MESH_ENABLE, ohare_mesh_enable },
+ { PMAC_FTR_IDE_ENABLE, ohare_ide_enable},
+ { PMAC_FTR_IDE_RESET, ohare_ide_reset},
+ { PMAC_FTR_SLEEP_STATE, ohare_sleep_state },
+ { 0, NULL }
+};
+
+/* Heathrow desktop machines (Beige G3).
+ * Separated as some features couldn't be properly tested
+ * and the serial port control bits appear to confuse it.
+ */
+static struct feature_table_entry heathrow_desktop_features[] __pmacdata = {
+ { PMAC_FTR_SWIM3_ENABLE, heathrow_floppy_enable },
+ { PMAC_FTR_MESH_ENABLE, heathrow_mesh_enable },
+ { PMAC_FTR_IDE_ENABLE, heathrow_ide_enable },
+ { PMAC_FTR_IDE_RESET, heathrow_ide_reset },
+ { PMAC_FTR_BMAC_ENABLE, heathrow_bmac_enable },
+ { 0, NULL }
+};
+
+/* Heathrow based laptop, that is the Wallstreet and mainstreet
+ * powerbooks.
+ */
+static struct feature_table_entry heathrow_laptop_features[] __pmacdata = {
+ { PMAC_FTR_SCC_ENABLE, ohare_htw_scc_enable },
+ { PMAC_FTR_MODEM_ENABLE, heathrow_modem_enable },
+ { PMAC_FTR_SWIM3_ENABLE, heathrow_floppy_enable },
+ { PMAC_FTR_MESH_ENABLE, heathrow_mesh_enable },
+ { PMAC_FTR_IDE_ENABLE, heathrow_ide_enable },
+ { PMAC_FTR_IDE_RESET, heathrow_ide_reset },
+ { PMAC_FTR_BMAC_ENABLE, heathrow_bmac_enable },
+ { PMAC_FTR_SOUND_CHIP_ENABLE, heathrow_sound_enable },
+ { PMAC_FTR_SLEEP_STATE, heathrow_sleep_state },
+ { 0, NULL }
+};
+
+/* Paddington based machines
+ * The lombard (101) powerbook, first iMac models, B&W G3 and Yikes G4.
+ */
+static struct feature_table_entry paddington_features[] __pmacdata = {
+ { PMAC_FTR_SCC_ENABLE, ohare_htw_scc_enable },
+ { PMAC_FTR_MODEM_ENABLE, heathrow_modem_enable },
+ { PMAC_FTR_SWIM3_ENABLE, heathrow_floppy_enable },
+ { PMAC_FTR_MESH_ENABLE, heathrow_mesh_enable },
+ { PMAC_FTR_IDE_ENABLE, heathrow_ide_enable },
+ { PMAC_FTR_IDE_RESET, heathrow_ide_reset },
+ { PMAC_FTR_BMAC_ENABLE, heathrow_bmac_enable },
+ { PMAC_FTR_SOUND_CHIP_ENABLE, heathrow_sound_enable },
+ { PMAC_FTR_SLEEP_STATE, heathrow_sleep_state },
+ { 0, NULL }
+};
+
+/* Core99 & MacRISC 2 machines (all machines released since the
+ * iBook (included), that is all AGP machines, except pangea
+ * chipset. The pangea chipset is the "combo" UniNorth/KeyLargo
+ * used on iBook2 & iMac "flow power".
+ */
+static struct feature_table_entry core99_features[] __pmacdata = {
+ { PMAC_FTR_SCC_ENABLE, core99_scc_enable },
+ { PMAC_FTR_MODEM_ENABLE, core99_modem_enable },
+ { PMAC_FTR_IDE_ENABLE, core99_ide_enable },
+ { PMAC_FTR_IDE_RESET, core99_ide_reset },
+ { PMAC_FTR_GMAC_ENABLE, core99_gmac_enable },
+ { PMAC_FTR_GMAC_PHY_RESET, core99_gmac_phy_reset },
+ { PMAC_FTR_SOUND_CHIP_ENABLE, core99_sound_chip_enable },
+ { PMAC_FTR_AIRPORT_ENABLE, core99_airport_enable },
+ { PMAC_FTR_USB_ENABLE, core99_usb_enable },
+ { PMAC_FTR_1394_ENABLE, core99_firewire_enable },
+ { PMAC_FTR_1394_CABLE_POWER, core99_firewire_cable_power },
+ { PMAC_FTR_SLEEP_STATE, core99_sleep_state },
+#ifdef CONFIG_SMP
+ { PMAC_FTR_RESET_CPU, core99_reset_cpu },
+#endif /* CONFIG_SMP */
+ { PMAC_FTR_READ_GPIO, core99_read_gpio },
+ { PMAC_FTR_WRITE_GPIO, core99_write_gpio },
+ { 0, NULL }
+};
+
+/* RackMac
+ */
+static struct feature_table_entry rackmac_features[] __pmacdata = {
+ { PMAC_FTR_SCC_ENABLE, core99_scc_enable },
+ { PMAC_FTR_IDE_ENABLE, core99_ide_enable },
+ { PMAC_FTR_IDE_RESET, core99_ide_reset },
+ { PMAC_FTR_GMAC_ENABLE, core99_gmac_enable },
+ { PMAC_FTR_GMAC_PHY_RESET, core99_gmac_phy_reset },
+ { PMAC_FTR_USB_ENABLE, core99_usb_enable },
+ { PMAC_FTR_1394_ENABLE, core99_firewire_enable },
+ { PMAC_FTR_1394_CABLE_POWER, core99_firewire_cable_power },
+ { PMAC_FTR_SLEEP_STATE, core99_sleep_state },
+#ifdef CONFIG_SMP
+ { PMAC_FTR_RESET_CPU, core99_reset_cpu },
+#endif /* CONFIG_SMP */
+ { PMAC_FTR_READ_GPIO, core99_read_gpio },
+ { PMAC_FTR_WRITE_GPIO, core99_write_gpio },
+ { 0, NULL }
+};
+
+/* Pangea features
+ */
+static struct feature_table_entry pangea_features[] __pmacdata = {
+ { PMAC_FTR_SCC_ENABLE, core99_scc_enable },
+ { PMAC_FTR_MODEM_ENABLE, pangea_modem_enable },
+ { PMAC_FTR_IDE_ENABLE, core99_ide_enable },
+ { PMAC_FTR_IDE_RESET, core99_ide_reset },
+ { PMAC_FTR_GMAC_ENABLE, core99_gmac_enable },
+ { PMAC_FTR_GMAC_PHY_RESET, core99_gmac_phy_reset },
+ { PMAC_FTR_SOUND_CHIP_ENABLE, core99_sound_chip_enable },
+ { PMAC_FTR_AIRPORT_ENABLE, core99_airport_enable },
+ { PMAC_FTR_USB_ENABLE, core99_usb_enable },
+ { PMAC_FTR_1394_ENABLE, core99_firewire_enable },
+ { PMAC_FTR_1394_CABLE_POWER, core99_firewire_cable_power },
+ { PMAC_FTR_SLEEP_STATE, core99_sleep_state },
+ { PMAC_FTR_READ_GPIO, core99_read_gpio },
+ { PMAC_FTR_WRITE_GPIO, core99_write_gpio },
+ { 0, NULL }
+};
+
+/* Intrepid features
+ */
+static struct feature_table_entry intrepid_features[] __pmacdata = {
+ { PMAC_FTR_SCC_ENABLE, core99_scc_enable },
+ { PMAC_FTR_MODEM_ENABLE, pangea_modem_enable },
+ { PMAC_FTR_IDE_ENABLE, core99_ide_enable },
+ { PMAC_FTR_IDE_RESET, core99_ide_reset },
+ { PMAC_FTR_GMAC_ENABLE, core99_gmac_enable },
+ { PMAC_FTR_GMAC_PHY_RESET, core99_gmac_phy_reset },
+ { PMAC_FTR_SOUND_CHIP_ENABLE, core99_sound_chip_enable },
+ { PMAC_FTR_AIRPORT_ENABLE, core99_airport_enable },
+ { PMAC_FTR_USB_ENABLE, core99_usb_enable },
+ { PMAC_FTR_1394_ENABLE, core99_firewire_enable },
+ { PMAC_FTR_1394_CABLE_POWER, core99_firewire_cable_power },
+ { PMAC_FTR_SLEEP_STATE, core99_sleep_state },
+ { PMAC_FTR_READ_GPIO, core99_read_gpio },
+ { PMAC_FTR_WRITE_GPIO, core99_write_gpio },
+ { PMAC_FTR_AACK_DELAY_ENABLE, intrepid_aack_delay_enable },
+ { 0, NULL }
+};
+
+#else /* CONFIG_POWER4 */
+
+/* G5 features
+ */
+static struct feature_table_entry g5_features[] __pmacdata = {
+ { PMAC_FTR_GMAC_ENABLE, g5_gmac_enable },
+ { PMAC_FTR_1394_ENABLE, g5_fw_enable },
+ { PMAC_FTR_ENABLE_MPIC, g5_mpic_enable },
+#ifdef CONFIG_SMP
+ { PMAC_FTR_RESET_CPU, g5_reset_cpu },
+#endif /* CONFIG_SMP */
+ { PMAC_FTR_READ_GPIO, core99_read_gpio },
+ { PMAC_FTR_WRITE_GPIO, core99_write_gpio },
+ { 0, NULL }
+};
+
+#endif /* CONFIG_POWER4 */
+
+static struct pmac_mb_def pmac_mb_defs[] __pmacdata = {
+#ifndef CONFIG_POWER4
+ /*
+ * Desktops
+ */
+
+ { "AAPL,8500", "PowerMac 8500/8600",
+ PMAC_TYPE_PSURGE, NULL,
+ 0
+ },
+ { "AAPL,9500", "PowerMac 9500/9600",
+ PMAC_TYPE_PSURGE, NULL,
+ 0
+ },
+ { "AAPL,7200", "PowerMac 7200",
+ PMAC_TYPE_PSURGE, NULL,
+ 0
+ },
+ { "AAPL,7300", "PowerMac 7200/7300",
+ PMAC_TYPE_PSURGE, NULL,
+ 0
+ },
+ { "AAPL,7500", "PowerMac 7500",
+ PMAC_TYPE_PSURGE, NULL,
+ 0
+ },
+ { "AAPL,ShinerESB", "Apple Network Server",
+ PMAC_TYPE_ANS, NULL,
+ 0
+ },
+ { "AAPL,e407", "Alchemy",
+ PMAC_TYPE_ALCHEMY, NULL,
+ 0
+ },
+ { "AAPL,e411", "Gazelle",
+ PMAC_TYPE_GAZELLE, NULL,
+ 0
+ },
+ { "AAPL,Gossamer", "PowerMac G3 (Gossamer)",
+ PMAC_TYPE_GOSSAMER, heathrow_desktop_features,
+ 0
+ },
+ { "AAPL,PowerMac G3", "PowerMac G3 (Silk)",
+ PMAC_TYPE_SILK, heathrow_desktop_features,
+ 0
+ },
+ { "PowerMac1,1", "Blue&White G3",
+ PMAC_TYPE_YOSEMITE, paddington_features,
+ 0
+ },
+ { "PowerMac1,2", "PowerMac G4 PCI Graphics",
+ PMAC_TYPE_YIKES, paddington_features,
+ 0
+ },
+ { "PowerMac2,1", "iMac FireWire",
+ PMAC_TYPE_FW_IMAC, core99_features,
+ PMAC_MB_MAY_SLEEP | PMAC_MB_OLD_CORE99
+ },
+ { "PowerMac2,2", "iMac FireWire",
+ PMAC_TYPE_FW_IMAC, core99_features,
+ PMAC_MB_MAY_SLEEP | PMAC_MB_OLD_CORE99
+ },
+ { "PowerMac3,1", "PowerMac G4 AGP Graphics",
+ PMAC_TYPE_SAWTOOTH, core99_features,
+ PMAC_MB_OLD_CORE99
+ },
+ { "PowerMac3,2", "PowerMac G4 AGP Graphics",
+ PMAC_TYPE_SAWTOOTH, core99_features,
+ PMAC_MB_MAY_SLEEP | PMAC_MB_OLD_CORE99
+ },
+ { "PowerMac3,3", "PowerMac G4 AGP Graphics",
+ PMAC_TYPE_SAWTOOTH, core99_features,
+ PMAC_MB_MAY_SLEEP | PMAC_MB_OLD_CORE99
+ },
+ { "PowerMac3,4", "PowerMac G4 Silver",
+ PMAC_TYPE_QUICKSILVER, core99_features,
+ PMAC_MB_MAY_SLEEP
+ },
+ { "PowerMac3,5", "PowerMac G4 Silver",
+ PMAC_TYPE_QUICKSILVER, core99_features,
+ PMAC_MB_MAY_SLEEP
+ },
+ { "PowerMac3,6", "PowerMac G4 Windtunnel",
+ PMAC_TYPE_WINDTUNNEL, core99_features,
+ PMAC_MB_MAY_SLEEP,
+ },
+ { "PowerMac4,1", "iMac \"Flower Power\"",
+ PMAC_TYPE_PANGEA_IMAC, pangea_features,
+ PMAC_MB_MAY_SLEEP
+ },
+ { "PowerMac4,2", "Flat panel iMac",
+ PMAC_TYPE_FLAT_PANEL_IMAC, pangea_features,
+ PMAC_MB_CAN_SLEEP
+ },
+ { "PowerMac4,4", "eMac",
+ PMAC_TYPE_EMAC, core99_features,
+ PMAC_MB_MAY_SLEEP
+ },
+ { "PowerMac5,1", "PowerMac G4 Cube",
+ PMAC_TYPE_CUBE, core99_features,
+ PMAC_MB_MAY_SLEEP | PMAC_MB_OLD_CORE99
+ },
+ { "PowerMac6,1", "Flat panel iMac",
+ PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features,
+ PMAC_MB_MAY_SLEEP,
+ },
+ { "PowerMac6,3", "Flat panel iMac",
+ PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features,
+ PMAC_MB_MAY_SLEEP,
+ },
+ { "PowerMac6,4", "eMac",
+ PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features,
+ PMAC_MB_MAY_SLEEP,
+ },
+ { "PowerMac10,1", "Mac mini",
+ PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features,
+ PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER,
+ },
+ { "iMac,1", "iMac (first generation)",
+ PMAC_TYPE_ORIG_IMAC, paddington_features,
+ 0
+ },
+
+ /*
+ * Xserve's
+ */
+
+ { "RackMac1,1", "XServe",
+ PMAC_TYPE_RACKMAC, rackmac_features,
+ 0,
+ },
+ { "RackMac1,2", "XServe rev. 2",
+ PMAC_TYPE_RACKMAC, rackmac_features,
+ 0,
+ },
+
+ /*
+ * Laptops
+ */
+
+ { "AAPL,3400/2400", "PowerBook 3400",
+ PMAC_TYPE_HOOPER, ohare_features,
+ PMAC_MB_CAN_SLEEP | PMAC_MB_MOBILE
+ },
+ { "AAPL,3500", "PowerBook 3500",
+ PMAC_TYPE_KANGA, ohare_features,
+ PMAC_MB_CAN_SLEEP | PMAC_MB_MOBILE
+ },
+ { "AAPL,PowerBook1998", "PowerBook Wallstreet",
+ PMAC_TYPE_WALLSTREET, heathrow_laptop_features,
+ PMAC_MB_CAN_SLEEP | PMAC_MB_MOBILE
+ },
+ { "PowerBook1,1", "PowerBook 101 (Lombard)",
+ PMAC_TYPE_101_PBOOK, paddington_features,
+ PMAC_MB_MAY_SLEEP | PMAC_MB_MOBILE
+ },
+ { "PowerBook2,1", "iBook (first generation)",
+ PMAC_TYPE_ORIG_IBOOK, core99_features,
+ PMAC_MB_CAN_SLEEP | PMAC_MB_OLD_CORE99 | PMAC_MB_MOBILE
+ },
+ { "PowerBook2,2", "iBook FireWire",
+ PMAC_TYPE_FW_IBOOK, core99_features,
+ PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER |
+ PMAC_MB_OLD_CORE99 | PMAC_MB_MOBILE
+ },
+ { "PowerBook3,1", "PowerBook Pismo",
+ PMAC_TYPE_PISMO, core99_features,
+ PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER |
+ PMAC_MB_OLD_CORE99 | PMAC_MB_MOBILE
+ },
+ { "PowerBook3,2", "PowerBook Titanium",
+ PMAC_TYPE_TITANIUM, core99_features,
+ PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE
+ },
+ { "PowerBook3,3", "PowerBook Titanium II",
+ PMAC_TYPE_TITANIUM2, core99_features,
+ PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE
+ },
+ { "PowerBook3,4", "PowerBook Titanium III",
+ PMAC_TYPE_TITANIUM3, core99_features,
+ PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE
+ },
+ { "PowerBook3,5", "PowerBook Titanium IV",
+ PMAC_TYPE_TITANIUM4, core99_features,
+ PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE
+ },
+ { "PowerBook4,1", "iBook 2",
+ PMAC_TYPE_IBOOK2, pangea_features,
+ PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE
+ },
+ { "PowerBook4,2", "iBook 2",
+ PMAC_TYPE_IBOOK2, pangea_features,
+ PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE
+ },
+ { "PowerBook4,3", "iBook 2 rev. 2",
+ PMAC_TYPE_IBOOK2, pangea_features,
+ PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE
+ },
+ { "PowerBook5,1", "PowerBook G4 17\"",
+ PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features,
+ PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE,
+ },
+ { "PowerBook5,2", "PowerBook G4 15\"",
+ PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features,
+ PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE,
+ },
+ { "PowerBook5,3", "PowerBook G4 17\"",
+ PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features,
+ PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE,
+ },
+ { "PowerBook5,4", "PowerBook G4 15\"",
+ PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features,
+ PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE,
+ },
+ { "PowerBook5,5", "PowerBook G4 17\"",
+ PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features,
+ PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE,
+ },
+ { "PowerBook5,6", "PowerBook G4 15\"",
+ PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features,
+ PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE,
+ },
+ { "PowerBook5,7", "PowerBook G4 17\"",
+ PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features,
+ PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE,
+ },
+ { "PowerBook6,1", "PowerBook G4 12\"",
+ PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features,
+ PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE,
+ },
+ { "PowerBook6,2", "PowerBook G4",
+ PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features,
+ PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE,
+ },
+ { "PowerBook6,3", "iBook G4",
+ PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features,
+ PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE,
+ },
+ { "PowerBook6,4", "PowerBook G4 12\"",
+ PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features,
+ PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE,
+ },
+ { "PowerBook6,5", "iBook G4",
+ PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features,
+ PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE,
+ },
+ { "PowerBook6,8", "PowerBook G4 12\"",
+ PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features,
+ PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE,
+ },
+#else /* CONFIG_POWER4 */
+ { "PowerMac7,2", "PowerMac G5",
+ PMAC_TYPE_POWERMAC_G5, g5_features,
+ 0,
+ },
+#endif /* CONFIG_POWER4 */
+};
+
+/*
+ * The toplevel feature_call callback
+ */
+long __pmac
+pmac_do_feature_call(unsigned int selector, ...)
+{
+ struct device_node* node;
+ long param, value;
+ int i;
+ feature_call func = NULL;
+ va_list args;
+
+ if (pmac_mb.features)
+ for (i=0; pmac_mb.features[i].function; i++)
+ if (pmac_mb.features[i].selector == selector) {
+ func = pmac_mb.features[i].function;
+ break;
+ }
+ if (!func)
+ for (i=0; any_features[i].function; i++)
+ if (any_features[i].selector == selector) {
+ func = any_features[i].function;
+ break;
+ }
+ if (!func)
+ return -ENODEV;
+
+ va_start(args, selector);
+ node = (struct device_node*)va_arg(args, void*);
+ param = va_arg(args, long);
+ value = va_arg(args, long);
+ va_end(args);
+
+ return func(node, param, value);
+}
+
+static int __init
+probe_motherboard(void)
+{
+ int i;
+ struct macio_chip* macio = &macio_chips[0];
+ const char* model = NULL;
+ struct device_node *dt;
+
+ /* Lookup known motherboard type in device-tree. First try an
+ * exact match on the "model" property, then try a "compatible"
+ * match is none is found.
+ */
+ dt = find_devices("device-tree");
+ if (dt != NULL)
+ model = (const char *) get_property(dt, "model", NULL);
+ for(i=0; model && i<(sizeof(pmac_mb_defs)/sizeof(struct pmac_mb_def)); i++) {
+ if (strcmp(model, pmac_mb_defs[i].model_string) == 0) {
+ pmac_mb = pmac_mb_defs[i];
+ goto found;
+ }
+ }
+ for(i=0; i<(sizeof(pmac_mb_defs)/sizeof(struct pmac_mb_def)); i++) {
+ if (machine_is_compatible(pmac_mb_defs[i].model_string)) {
+ pmac_mb = pmac_mb_defs[i];
+ goto found;
+ }
+ }
+
+ /* Fallback to selection depending on mac-io chip type */
+ switch(macio->type) {
+#ifndef CONFIG_POWER4
+ case macio_grand_central:
+ pmac_mb.model_id = PMAC_TYPE_PSURGE;
+ pmac_mb.model_name = "Unknown PowerSurge";
+ break;
+ case macio_ohare:
+ pmac_mb.model_id = PMAC_TYPE_UNKNOWN_OHARE;
+ pmac_mb.model_name = "Unknown OHare-based";
+ break;
+ case macio_heathrow:
+ pmac_mb.model_id = PMAC_TYPE_UNKNOWN_HEATHROW;
+ pmac_mb.model_name = "Unknown Heathrow-based";
+ pmac_mb.features = heathrow_desktop_features;
+ break;
+ case macio_paddington:
+ pmac_mb.model_id = PMAC_TYPE_UNKNOWN_PADDINGTON;
+ pmac_mb.model_name = "Unknown Paddington-based";
+ pmac_mb.features = paddington_features;
+ break;
+ case macio_keylargo:
+ pmac_mb.model_id = PMAC_TYPE_UNKNOWN_CORE99;
+ pmac_mb.model_name = "Unknown Keylargo-based";
+ pmac_mb.features = core99_features;
+ break;
+ case macio_pangea:
+ pmac_mb.model_id = PMAC_TYPE_UNKNOWN_PANGEA;
+ pmac_mb.model_name = "Unknown Pangea-based";
+ pmac_mb.features = pangea_features;
+ break;
+ case macio_intrepid:
+ pmac_mb.model_id = PMAC_TYPE_UNKNOWN_INTREPID;
+ pmac_mb.model_name = "Unknown Intrepid-based";
+ pmac_mb.features = intrepid_features;
+ break;
+#else /* CONFIG_POWER4 */
+ case macio_keylargo2:
+ pmac_mb.model_id = PMAC_TYPE_UNKNOWN_K2;
+ pmac_mb.model_name = "Unknown G5";
+ pmac_mb.features = g5_features;
+ break;
+#endif /* CONFIG_POWER4 */
+ default:
+ return -ENODEV;
+ }
+found:
+#ifndef CONFIG_POWER4
+ /* Fixup Hooper vs. Comet */
+ if (pmac_mb.model_id == PMAC_TYPE_HOOPER) {
+ u32 __iomem * mach_id_ptr = ioremap(0xf3000034, 4);
+ if (!mach_id_ptr)
+ return -ENODEV;
+ /* Here, I used to disable the media-bay on comet. It
+ * appears this is wrong, the floppy connector is actually
+ * a kind of media-bay and works with the current driver.
+ */
+ if (__raw_readl(mach_id_ptr) & 0x20000000UL)
+ pmac_mb.model_id = PMAC_TYPE_COMET;
+ iounmap(mach_id_ptr);
+ }
+#endif /* CONFIG_POWER4 */
+
+#ifdef CONFIG_6xx
+ /* Set default value of powersave_nap on machines that support it.
+ * It appears that uninorth rev 3 has a problem with it, we don't
+ * enable it on those. In theory, the flush-on-lock property is
+ * supposed to be set when not supported, but I'm not very confident
+ * that all Apple OF revs did it properly, I do it the paranoid way.
+ */
+ while (uninorth_base && uninorth_rev > 3) {
+ struct device_node* np = find_path_device("/cpus");
+ if (!np || !np->child) {
+ printk(KERN_WARNING "Can't find CPU(s) in device tree !\n");
+ break;
+ }
+ np = np->child;
+ /* Nap mode not supported on SMP */
+ if (np->sibling)
+ break;
+ /* Nap mode not supported if flush-on-lock property is present */
+ if (get_property(np, "flush-on-lock", NULL))
+ break;
+ powersave_nap = 1;
+ printk(KERN_INFO "Processor NAP mode on idle enabled.\n");
+ break;
+ }
+
+ /* On CPUs that support it (750FX), lowspeed by default during
+ * NAP mode
+ */
+ powersave_lowspeed = 1;
+#endif /* CONFIG_6xx */
+#ifdef CONFIG_POWER4
+ powersave_nap = 1;
+#endif
+ /* Check for "mobile" machine */
+ if (model && (strncmp(model, "PowerBook", 9) == 0
+ || strncmp(model, "iBook", 5) == 0))
+ pmac_mb.board_flags |= PMAC_MB_MOBILE;
+
+
+ printk(KERN_INFO "PowerMac motherboard: %s\n", pmac_mb.model_name);
+ return 0;
+}
+
+/* Initialize the Core99 UniNorth host bridge and memory controller
+ */
+static void __init
+probe_uninorth(void)
+{
+ unsigned long actrl;
+
+ /* Locate core99 Uni-N */
+ uninorth_node = of_find_node_by_name(NULL, "uni-n");
+ /* Locate G5 u3 */
+ if (uninorth_node == NULL) {
+ uninorth_node = of_find_node_by_name(NULL, "u3");
+ uninorth_u3 = 1;
+ }
+ if (uninorth_node && uninorth_node->n_addrs > 0) {
+ unsigned long address = uninorth_node->addrs[0].address;
+ uninorth_base = ioremap(address, 0x40000);
+ uninorth_rev = in_be32(UN_REG(UNI_N_VERSION));
+ if (uninorth_u3)
+ u3_ht = ioremap(address + U3_HT_CONFIG_BASE, 0x1000);
+ } else
+ uninorth_node = NULL;
+
+ if (!uninorth_node)
+ return;
+
+ printk(KERN_INFO "Found %s memory controller & host bridge, revision: %d\n",
+ uninorth_u3 ? "U3" : "UniNorth", uninorth_rev);
+ printk(KERN_INFO "Mapped at 0x%08lx\n", (unsigned long)uninorth_base);
+
+ /* Set the arbitrer QAck delay according to what Apple does
+ */
+ if (uninorth_rev < 0x11) {
+ actrl = UN_IN(UNI_N_ARB_CTRL) & ~UNI_N_ARB_CTRL_QACK_DELAY_MASK;
+ actrl |= ((uninorth_rev < 3) ? UNI_N_ARB_CTRL_QACK_DELAY105 :
+ UNI_N_ARB_CTRL_QACK_DELAY) << UNI_N_ARB_CTRL_QACK_DELAY_SHIFT;
+ UN_OUT(UNI_N_ARB_CTRL, actrl);
+ }
+
+ /* Some more magic as done by them in recent MacOS X on UniNorth
+ * revs 1.5 to 2.O and Pangea. Seem to toggle the UniN Maxbus/PCI
+ * memory timeout
+ */
+ if ((uninorth_rev >= 0x11 && uninorth_rev <= 0x24) || uninorth_rev == 0xc0)
+ UN_OUT(0x2160, UN_IN(0x2160) & 0x00ffffff);
+}
+
+static void __init
+probe_one_macio(const char* name, const char* compat, int type)
+{
+ struct device_node* node;
+ int i;
+ volatile u32 __iomem * base;
+ u32* revp;
+
+ node = find_devices(name);
+ if (!node || !node->n_addrs)
+ return;
+ if (compat)
+ do {
+ if (device_is_compatible(node, compat))
+ break;
+ node = node->next;
+ } while (node);
+ if (!node)
+ return;
+ for(i=0; i<MAX_MACIO_CHIPS; i++) {
+ if (!macio_chips[i].of_node)
+ break;
+ if (macio_chips[i].of_node == node)
+ return;
+ }
+ if (i >= MAX_MACIO_CHIPS) {
+ printk(KERN_ERR "pmac_feature: Please increase MAX_MACIO_CHIPS !\n");
+ printk(KERN_ERR "pmac_feature: %s skipped\n", node->full_name);
+ return;
+ }
+ base = ioremap(node->addrs[0].address, node->addrs[0].size);
+ if (!base) {
+ printk(KERN_ERR "pmac_feature: Can't map mac-io chip !\n");
+ return;
+ }
+ if (type == macio_keylargo) {
+ u32* did = (u32 *)get_property(node, "device-id", NULL);
+ if (*did == 0x00000025)
+ type = macio_pangea;
+ if (*did == 0x0000003e)
+ type = macio_intrepid;
+ }
+ macio_chips[i].of_node = node;
+ macio_chips[i].type = type;
+ macio_chips[i].base = base;
+ macio_chips[i].flags = MACIO_FLAG_SCCB_ON | MACIO_FLAG_SCCB_ON;
+ macio_chips[i].name = macio_names[type];
+ revp = (u32 *)get_property(node, "revision-id", NULL);
+ if (revp)
+ macio_chips[i].rev = *revp;
+ printk(KERN_INFO "Found a %s mac-io controller, rev: %d, mapped at 0x%p\n",
+ macio_names[type], macio_chips[i].rev, macio_chips[i].base);
+}
+
+static int __init
+probe_macios(void)
+{
+ /* Warning, ordering is important */
+ probe_one_macio("gc", NULL, macio_grand_central);
+ probe_one_macio("ohare", NULL, macio_ohare);
+ probe_one_macio("pci106b,7", NULL, macio_ohareII);
+ probe_one_macio("mac-io", "keylargo", macio_keylargo);
+ probe_one_macio("mac-io", "paddington", macio_paddington);
+ probe_one_macio("mac-io", "gatwick", macio_gatwick);
+ probe_one_macio("mac-io", "heathrow", macio_heathrow);
+ probe_one_macio("mac-io", "K2-Keylargo", macio_keylargo2);
+
+ /* Make sure the "main" macio chip appear first */
+ if (macio_chips[0].type == macio_gatwick
+ && macio_chips[1].type == macio_heathrow) {
+ struct macio_chip temp = macio_chips[0];
+ macio_chips[0] = macio_chips[1];
+ macio_chips[1] = temp;
+ }
+ if (macio_chips[0].type == macio_ohareII
+ && macio_chips[1].type == macio_ohare) {
+ struct macio_chip temp = macio_chips[0];
+ macio_chips[0] = macio_chips[1];
+ macio_chips[1] = temp;
+ }
+ macio_chips[0].lbus.index = 0;
+ macio_chips[1].lbus.index = 1;
+
+ return (macio_chips[0].of_node == NULL) ? -ENODEV : 0;
+}
+
+static void __init
+initial_serial_shutdown(struct device_node* np)
+{
+ int len;
+ struct slot_names_prop {
+ int count;
+ char name[1];
+ } *slots;
+ char *conn;
+ int port_type = PMAC_SCC_ASYNC;
+ int modem = 0;
+
+ slots = (struct slot_names_prop *)get_property(np, "slot-names", &len);
+ conn = get_property(np, "AAPL,connector", &len);
+ if (conn && (strcmp(conn, "infrared") == 0))
+ port_type = PMAC_SCC_IRDA;
+ else if (device_is_compatible(np, "cobalt"))
+ modem = 1;
+ else if (slots && slots->count > 0) {
+ if (strcmp(slots->name, "IrDA") == 0)
+ port_type = PMAC_SCC_IRDA;
+ else if (strcmp(slots->name, "Modem") == 0)
+ modem = 1;
+ }
+ if (modem)
+ pmac_call_feature(PMAC_FTR_MODEM_ENABLE, np, 0, 0);
+ pmac_call_feature(PMAC_FTR_SCC_ENABLE, np, port_type, 0);
+}
+
+static void __init
+set_initial_features(void)
+{
+ struct device_node* np;
+
+ /* That hack appears to be necessary for some StarMax motherboards
+ * but I'm not too sure it was audited for side-effects on other
+ * ohare based machines...
+ * Since I still have difficulties figuring the right way to
+ * differenciate them all and since that hack was there for a long
+ * time, I'll keep it around
+ */
+ if (macio_chips[0].type == macio_ohare && !find_devices("via-pmu")) {
+ struct macio_chip* macio = &macio_chips[0];
+ MACIO_OUT32(OHARE_FCR, STARMAX_FEATURES);
+ } else if (macio_chips[0].type == macio_ohare) {
+ struct macio_chip* macio = &macio_chips[0];
+ MACIO_BIS(OHARE_FCR, OH_IOBUS_ENABLE);
+ } else if (macio_chips[1].type == macio_ohare) {
+ struct macio_chip* macio = &macio_chips[1];
+ MACIO_BIS(OHARE_FCR, OH_IOBUS_ENABLE);
+ }
+
+#ifdef CONFIG_POWER4
+ if (macio_chips[0].type == macio_keylargo2) {
+#ifndef CONFIG_SMP
+ /* On SMP machines running UP, we have the second CPU eating
+ * bus cycles. We need to take it off the bus. This is done
+ * from pmac_smp for SMP kernels running on one CPU
+ */
+ np = of_find_node_by_type(NULL, "cpu");
+ if (np != NULL)
+ np = of_find_node_by_type(np, "cpu");
+ if (np != NULL) {
+ g5_phy_disable_cpu1();
+ of_node_put(np);
+ }
+#endif /* CONFIG_SMP */
+ /* Enable GMAC for now for PCI probing. It will be disabled
+ * later on after PCI probe
+ */
+ np = of_find_node_by_name(NULL, "ethernet");
+ while(np) {
+ if (device_is_compatible(np, "K2-GMAC"))
+ g5_gmac_enable(np, 0, 1);
+ np = of_find_node_by_name(np, "ethernet");
+ }
+
+ /* Enable FW before PCI probe. Will be disabled later on
+ * Note: We should have a batter way to check that we are
+ * dealing with uninorth internal cell and not a PCI cell
+ * on the external PCI. The code below works though.
+ */
+ np = of_find_node_by_name(NULL, "firewire");
+ while(np) {
+ if (device_is_compatible(np, "pci106b,5811")) {
+ macio_chips[0].flags |= MACIO_FLAG_FW_SUPPORTED;
+ g5_fw_enable(np, 0, 1);
+ }
+ np = of_find_node_by_name(np, "firewire");
+ }
+ }
+#else /* CONFIG_POWER4 */
+
+ if (macio_chips[0].type == macio_keylargo ||
+ macio_chips[0].type == macio_pangea ||
+ macio_chips[0].type == macio_intrepid) {
+ /* Enable GMAC for now for PCI probing. It will be disabled
+ * later on after PCI probe
+ */
+ np = of_find_node_by_name(NULL, "ethernet");
+ while(np) {
+ if (np->parent
+ && device_is_compatible(np->parent, "uni-north")
+ && device_is_compatible(np, "gmac"))
+ core99_gmac_enable(np, 0, 1);
+ np = of_find_node_by_name(np, "ethernet");
+ }
+
+ /* Enable FW before PCI probe. Will be disabled later on
+ * Note: We should have a batter way to check that we are
+ * dealing with uninorth internal cell and not a PCI cell
+ * on the external PCI. The code below works though.
+ */
+ np = of_find_node_by_name(NULL, "firewire");
+ while(np) {
+ if (np->parent
+ && device_is_compatible(np->parent, "uni-north")
+ && (device_is_compatible(np, "pci106b,18") ||
+ device_is_compatible(np, "pci106b,30") ||
+ device_is_compatible(np, "pci11c1,5811"))) {
+ macio_chips[0].flags |= MACIO_FLAG_FW_SUPPORTED;
+ core99_firewire_enable(np, 0, 1);
+ }
+ np = of_find_node_by_name(np, "firewire");
+ }
+
+ /* Enable ATA-100 before PCI probe. */
+ np = of_find_node_by_name(NULL, "ata-6");
+ while(np) {
+ if (np->parent
+ && device_is_compatible(np->parent, "uni-north")
+ && device_is_compatible(np, "kauai-ata")) {
+ core99_ata100_enable(np, 1);
+ }
+ np = of_find_node_by_name(np, "ata-6");
+ }
+
+ /* Switch airport off */
+ np = find_devices("radio");
+ while(np) {
+ if (np && np->parent == macio_chips[0].of_node) {
+ macio_chips[0].flags |= MACIO_FLAG_AIRPORT_ON;
+ core99_airport_enable(np, 0, 0);
+ }
+ np = np->next;
+ }
+ }
+
+ /* On all machines that support sound PM, switch sound off */
+ if (macio_chips[0].of_node)
+ pmac_do_feature_call(PMAC_FTR_SOUND_CHIP_ENABLE,
+ macio_chips[0].of_node, 0, 0);
+
+ /* While on some desktop G3s, we turn it back on */
+ if (macio_chips[0].of_node && macio_chips[0].type == macio_heathrow
+ && (pmac_mb.model_id == PMAC_TYPE_GOSSAMER ||
+ pmac_mb.model_id == PMAC_TYPE_SILK)) {
+ struct macio_chip* macio = &macio_chips[0];
+ MACIO_BIS(HEATHROW_FCR, HRW_SOUND_CLK_ENABLE);
+ MACIO_BIC(HEATHROW_FCR, HRW_SOUND_POWER_N);
+ }
+
+ /* Hack for bumping clock speed on the new PowerBooks and the
+ * iBook G4. This implements the "platform-do-clockspreading" OF
+ * property. For safety, we also check the product ID in the
+ * device-tree to make reasonably sure we won't set wrong values
+ * in the clock chip.
+ *
+ * Of course, ultimately, we have to implement a real parser for
+ * the platform-do-* stuff...
+ */
+ while (machine_is_compatible("PowerBook5,2") ||
+ machine_is_compatible("PowerBook5,3") ||
+ machine_is_compatible("PowerBook6,2") ||
+ machine_is_compatible("PowerBook6,3")) {
+ struct device_node *ui2c = of_find_node_by_type(NULL, "i2c");
+ struct device_node *dt = of_find_node_by_name(NULL, "device-tree");
+ u8 buffer[9];
+ u32 *productID;
+ int i, rc, changed = 0;
+
+ if (dt == NULL)
+ break;
+ productID = (u32 *)get_property(dt, "pid#", NULL);
+ if (productID == NULL)
+ break;
+ while(ui2c) {
+ struct device_node *p = of_get_parent(ui2c);
+ if (p && !strcmp(p->name, "uni-n"))
+ break;
+ ui2c = of_find_node_by_type(ui2c, "i2c");
+ }
+ if (ui2c == NULL)
+ break;
+ DBG("Trying to bump clock speed for PID: %08x...\n", *productID);
+ rc = pmac_low_i2c_open(ui2c, 1);
+ if (rc != 0)
+ break;
+ pmac_low_i2c_setmode(ui2c, pmac_low_i2c_mode_combined);
+ rc = pmac_low_i2c_xfer(ui2c, 0xd2 | pmac_low_i2c_read, 0x80, buffer, 9);
+ DBG("read result: %d,", rc);
+ if (rc != 0) {
+ pmac_low_i2c_close(ui2c);
+ break;
+ }
+ for (i=0; i<9; i++)
+ DBG(" %02x", buffer[i]);
+ DBG("\n");
+
+ switch(*productID) {
+ case 0x1182: /* AlBook 12" rev 2 */
+ case 0x1183: /* iBook G4 12" */
+ buffer[0] = (buffer[0] & 0x8f) | 0x70;
+ buffer[2] = (buffer[2] & 0x7f) | 0x00;
+ buffer[5] = (buffer[5] & 0x80) | 0x31;
+ buffer[6] = (buffer[6] & 0x40) | 0xb0;
+ buffer[7] = (buffer[7] & 0x00) | 0xc0;
+ buffer[8] = (buffer[8] & 0x00) | 0x30;
+ changed = 1;
+ break;
+ case 0x3142: /* AlBook 15" (ATI M10) */
+ case 0x3143: /* AlBook 17" (ATI M10) */
+ buffer[0] = (buffer[0] & 0xaf) | 0x50;
+ buffer[2] = (buffer[2] & 0x7f) | 0x00;
+ buffer[5] = (buffer[5] & 0x80) | 0x31;
+ buffer[6] = (buffer[6] & 0x40) | 0xb0;
+ buffer[7] = (buffer[7] & 0x00) | 0xd0;
+ buffer[8] = (buffer[8] & 0x00) | 0x30;
+ changed = 1;
+ break;
+ default:
+ DBG("i2c-hwclock: Machine model not handled\n");
+ break;
+ }
+ if (!changed) {
+ pmac_low_i2c_close(ui2c);
+ break;
+ }
+ pmac_low_i2c_setmode(ui2c, pmac_low_i2c_mode_stdsub);
+ rc = pmac_low_i2c_xfer(ui2c, 0xd2 | pmac_low_i2c_write, 0x80, buffer, 9);
+ DBG("write result: %d,", rc);
+ pmac_low_i2c_setmode(ui2c, pmac_low_i2c_mode_combined);
+ rc = pmac_low_i2c_xfer(ui2c, 0xd2 | pmac_low_i2c_read, 0x80, buffer, 9);
+ DBG("read result: %d,", rc);
+ if (rc != 0) {
+ pmac_low_i2c_close(ui2c);
+ break;
+ }
+ for (i=0; i<9; i++)
+ DBG(" %02x", buffer[i]);
+ pmac_low_i2c_close(ui2c);
+ break;
+ }
+
+#endif /* CONFIG_POWER4 */
+
+ /* On all machines, switch modem & serial ports off */
+ np = find_devices("ch-a");
+ while(np) {
+ initial_serial_shutdown(np);
+ np = np->next;
+ }
+ np = find_devices("ch-b");
+ while(np) {
+ initial_serial_shutdown(np);
+ np = np->next;
+ }
+}
+
+void __init
+pmac_feature_init(void)
+{
+ /* Detect the UniNorth memory controller */
+ probe_uninorth();
+
+ /* Probe mac-io controllers */
+ if (probe_macios()) {
+ printk(KERN_WARNING "No mac-io chip found\n");
+ return;
+ }
+
+ /* Setup low-level i2c stuffs */
+ pmac_init_low_i2c();
+
+ /* Probe machine type */
+ if (probe_motherboard())
+ printk(KERN_WARNING "Unknown PowerMac !\n");
+
+ /* Set some initial features (turn off some chips that will
+ * be later turned on)
+ */
+ set_initial_features();
+}
+
+int __init
+pmac_feature_late_init(void)
+{
+ struct device_node* np;
+
+ /* Request some resources late */
+ if (uninorth_node)
+ request_OF_resource(uninorth_node, 0, NULL);
+ np = find_devices("hammerhead");
+ if (np)
+ request_OF_resource(np, 0, NULL);
+ np = find_devices("interrupt-controller");
+ if (np)
+ request_OF_resource(np, 0, NULL);
+ return 0;
+}
+
+device_initcall(pmac_feature_late_init);
+
+#ifdef CONFIG_POWER4
+
+static void dump_HT_speeds(char *name, u32 cfg, u32 frq)
+{
+ int freqs[16] = { 200,300,400,500,600,800,1000,0,0,0,0,0,0,0,0,0 };
+ int bits[8] = { 8,16,0,32,2,4,0,0 };
+ int freq = (frq >> 8) & 0xf;
+
+ if (freqs[freq] == 0)
+ printk("%s: Unknown HT link frequency %x\n", name, freq);
+ else
+ printk("%s: %d MHz on main link, (%d in / %d out) bits width\n",
+ name, freqs[freq],
+ bits[(cfg >> 28) & 0x7], bits[(cfg >> 24) & 0x7]);
+}
+
+void __init pmac_check_ht_link(void)
+{
+ u32 ufreq, freq, ucfg, cfg;
+ struct device_node *pcix_node;
+ u8 px_bus, px_devfn;
+ struct pci_controller *px_hose;
+
+ (void)in_be32(u3_ht + U3_HT_LINK_COMMAND);
+ ucfg = cfg = in_be32(u3_ht + U3_HT_LINK_CONFIG);
+ ufreq = freq = in_be32(u3_ht + U3_HT_LINK_FREQ);
+ dump_HT_speeds("U3 HyperTransport", cfg, freq);
+
+ pcix_node = of_find_compatible_node(NULL, "pci", "pci-x");
+ if (pcix_node == NULL) {
+ printk("No PCI-X bridge found\n");
+ return;
+ }
+ if (pci_device_from_OF_node(pcix_node, &px_bus, &px_devfn) != 0) {
+ printk("PCI-X bridge found but not matched to pci\n");
+ return;
+ }
+ px_hose = pci_find_hose_for_OF_device(pcix_node);
+ if (px_hose == NULL) {
+ printk("PCI-X bridge found but not matched to host\n");
+ return;
+ }
+ early_read_config_dword(px_hose, px_bus, px_devfn, 0xc4, &cfg);
+ early_read_config_dword(px_hose, px_bus, px_devfn, 0xcc, &freq);
+ dump_HT_speeds("PCI-X HT Uplink", cfg, freq);
+ early_read_config_dword(px_hose, px_bus, px_devfn, 0xc8, &cfg);
+ early_read_config_dword(px_hose, px_bus, px_devfn, 0xd0, &freq);
+ dump_HT_speeds("PCI-X HT Downlink", cfg, freq);
+}
+
+#endif /* CONFIG_POWER4 */
+
+/*
+ * Early video resume hook
+ */
+
+static void (*pmac_early_vresume_proc)(void *data) __pmacdata;
+static void *pmac_early_vresume_data __pmacdata;
+
+void pmac_set_early_video_resume(void (*proc)(void *data), void *data)
+{
+ if (_machine != _MACH_Pmac)
+ return;
+ preempt_disable();
+ pmac_early_vresume_proc = proc;
+ pmac_early_vresume_data = data;
+ preempt_enable();
+}
+EXPORT_SYMBOL(pmac_set_early_video_resume);
+
+void __pmac pmac_call_early_video_resume(void)
+{
+ if (pmac_early_vresume_proc)
+ pmac_early_vresume_proc(pmac_early_vresume_data);
+}
diff --git a/arch/ppc/platforms/pmac_low_i2c.c b/arch/ppc/platforms/pmac_low_i2c.c
new file mode 100644
index 0000000..d07579f
--- /dev/null
+++ b/arch/ppc/platforms/pmac_low_i2c.c
@@ -0,0 +1,513 @@
+/*
+ * arch/ppc/platforms/pmac_low_i2c.c
+ *
+ * Copyright (C) 2003 Ben. Herrenschmidt (benh@kernel.crashing.org)
+ *
+ * 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 file contains some low-level i2c access routines that
+ * need to be used by various bits of the PowerMac platform code
+ * at times where the real asynchronous & interrupt driven driver
+ * cannot be used. The API borrows some semantics from the darwin
+ * driver in order to ease the implementation of the platform
+ * properties parser
+ */
+
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/delay.h>
+#include <linux/sched.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/adb.h>
+#include <linux/pmu.h>
+#include <asm/keylargo.h>
+#include <asm/uninorth.h>
+#include <asm/io.h>
+#include <asm/prom.h>
+#include <asm/machdep.h>
+#include <asm/pmac_low_i2c.h>
+
+#define MAX_LOW_I2C_HOST 4
+
+#if 1
+#define DBG(x...) do {\
+ printk(KERN_DEBUG "KW:" x); \
+ } while(0)
+#else
+#define DBGG(x...)
+#endif
+
+struct low_i2c_host;
+
+typedef int (*low_i2c_func_t)(struct low_i2c_host *host, u8 addr, u8 sub, u8 *data, int len);
+
+struct low_i2c_host
+{
+ struct device_node *np; /* OF device node */
+ struct semaphore mutex; /* Access mutex for use by i2c-keywest */
+ low_i2c_func_t func; /* Access function */
+ int is_open : 1; /* Poor man's access control */
+ int mode; /* Current mode */
+ int channel; /* Current channel */
+ int num_channels; /* Number of channels */
+ unsigned long base; /* For keywest-i2c, base address */
+ int bsteps; /* And register stepping */
+ int speed; /* And speed */
+};
+
+static struct low_i2c_host low_i2c_hosts[MAX_LOW_I2C_HOST];
+
+/* No locking is necessary on allocation, we are running way before
+ * anything can race with us
+ */
+static struct low_i2c_host *find_low_i2c_host(struct device_node *np)
+{
+ int i;
+
+ for (i = 0; i < MAX_LOW_I2C_HOST; i++)
+ if (low_i2c_hosts[i].np == np)
+ return &low_i2c_hosts[i];
+ return NULL;
+}
+
+/*
+ *
+ * i2c-keywest implementation (UniNorth, U2, U3, Keylargo's)
+ *
+ */
+
+/*
+ * Keywest i2c definitions borrowed from drivers/i2c/i2c-keywest.h,
+ * should be moved somewhere in include/asm-ppc/
+ */
+/* Register indices */
+typedef enum {
+ reg_mode = 0,
+ reg_control,
+ reg_status,
+ reg_isr,
+ reg_ier,
+ reg_addr,
+ reg_subaddr,
+ reg_data
+} reg_t;
+
+
+/* Mode register */
+#define KW_I2C_MODE_100KHZ 0x00
+#define KW_I2C_MODE_50KHZ 0x01
+#define KW_I2C_MODE_25KHZ 0x02
+#define KW_I2C_MODE_DUMB 0x00
+#define KW_I2C_MODE_STANDARD 0x04
+#define KW_I2C_MODE_STANDARDSUB 0x08
+#define KW_I2C_MODE_COMBINED 0x0C
+#define KW_I2C_MODE_MODE_MASK 0x0C
+#define KW_I2C_MODE_CHAN_MASK 0xF0
+
+/* Control register */
+#define KW_I2C_CTL_AAK 0x01
+#define KW_I2C_CTL_XADDR 0x02
+#define KW_I2C_CTL_STOP 0x04
+#define KW_I2C_CTL_START 0x08
+
+/* Status register */
+#define KW_I2C_STAT_BUSY 0x01
+#define KW_I2C_STAT_LAST_AAK 0x02
+#define KW_I2C_STAT_LAST_RW 0x04
+#define KW_I2C_STAT_SDA 0x08
+#define KW_I2C_STAT_SCL 0x10
+
+/* IER & ISR registers */
+#define KW_I2C_IRQ_DATA 0x01
+#define KW_I2C_IRQ_ADDR 0x02
+#define KW_I2C_IRQ_STOP 0x04
+#define KW_I2C_IRQ_START 0x08
+#define KW_I2C_IRQ_MASK 0x0F
+
+/* State machine states */
+enum {
+ state_idle,
+ state_addr,
+ state_read,
+ state_write,
+ state_stop,
+ state_dead
+};
+
+#define WRONG_STATE(name) do {\
+ printk(KERN_DEBUG "KW: wrong state. Got %s, state: %s (isr: %02x)\n", \
+ name, __kw_state_names[state], isr); \
+ } while(0)
+
+static const char *__kw_state_names[] = {
+ "state_idle",
+ "state_addr",
+ "state_read",
+ "state_write",
+ "state_stop",
+ "state_dead"
+};
+
+static inline u8 __kw_read_reg(struct low_i2c_host *host, reg_t reg)
+{
+ return in_8(((volatile u8 *)host->base)
+ + (((unsigned)reg) << host->bsteps));
+}
+
+static inline void __kw_write_reg(struct low_i2c_host *host, reg_t reg, u8 val)
+{
+ out_8(((volatile u8 *)host->base)
+ + (((unsigned)reg) << host->bsteps), val);
+ (void)__kw_read_reg(host, reg_subaddr);
+}
+
+#define kw_write_reg(reg, val) __kw_write_reg(host, reg, val)
+#define kw_read_reg(reg) __kw_read_reg(host, reg)
+
+
+/* Don't schedule, the g5 fan controller is too
+ * timing sensitive
+ */
+static u8 kw_wait_interrupt(struct low_i2c_host* host)
+{
+ int i;
+ u8 isr;
+
+ for (i = 0; i < 200000; i++) {
+ isr = kw_read_reg(reg_isr) & KW_I2C_IRQ_MASK;
+ if (isr != 0)
+ return isr;
+ udelay(1);
+ }
+ return isr;
+}
+
+static int kw_handle_interrupt(struct low_i2c_host *host, int state, int rw, int *rc, u8 **data, int *len, u8 isr)
+{
+ u8 ack;
+
+ if (isr == 0) {
+ if (state != state_stop) {
+ DBG("KW: Timeout !\n");
+ *rc = -EIO;
+ goto stop;
+ }
+ if (state == state_stop) {
+ ack = kw_read_reg(reg_status);
+ if (!(ack & KW_I2C_STAT_BUSY)) {
+ state = state_idle;
+ kw_write_reg(reg_ier, 0x00);
+ }
+ }
+ return state;
+ }
+
+ if (isr & KW_I2C_IRQ_ADDR) {
+ ack = kw_read_reg(reg_status);
+ if (state != state_addr) {
+ kw_write_reg(reg_isr, KW_I2C_IRQ_ADDR);
+ WRONG_STATE("KW_I2C_IRQ_ADDR");
+ *rc = -EIO;
+ goto stop;
+ }
+ if ((ack & KW_I2C_STAT_LAST_AAK) == 0) {
+ *rc = -ENODEV;
+ DBG("KW: NAK on address\n");
+ return state_stop;
+ } else {
+ if (rw) {
+ state = state_read;
+ if (*len > 1)
+ kw_write_reg(reg_control, KW_I2C_CTL_AAK);
+ } else {
+ state = state_write;
+ kw_write_reg(reg_data, **data);
+ (*data)++; (*len)--;
+ }
+ }
+ kw_write_reg(reg_isr, KW_I2C_IRQ_ADDR);
+ }
+
+ if (isr & KW_I2C_IRQ_DATA) {
+ if (state == state_read) {
+ **data = kw_read_reg(reg_data);
+ (*data)++; (*len)--;
+ kw_write_reg(reg_isr, KW_I2C_IRQ_DATA);
+ if ((*len) == 0)
+ state = state_stop;
+ else if ((*len) == 1)
+ kw_write_reg(reg_control, 0);
+ } else if (state == state_write) {
+ ack = kw_read_reg(reg_status);
+ if ((ack & KW_I2C_STAT_LAST_AAK) == 0) {
+ DBG("KW: nack on data write\n");
+ *rc = -EIO;
+ goto stop;
+ } else if (*len) {
+ kw_write_reg(reg_data, **data);
+ (*data)++; (*len)--;
+ } else {
+ kw_write_reg(reg_control, KW_I2C_CTL_STOP);
+ state = state_stop;
+ *rc = 0;
+ }
+ kw_write_reg(reg_isr, KW_I2C_IRQ_DATA);
+ } else {
+ kw_write_reg(reg_isr, KW_I2C_IRQ_DATA);
+ WRONG_STATE("KW_I2C_IRQ_DATA");
+ if (state != state_stop) {
+ *rc = -EIO;
+ goto stop;
+ }
+ }
+ }
+
+ if (isr & KW_I2C_IRQ_STOP) {
+ kw_write_reg(reg_isr, KW_I2C_IRQ_STOP);
+ if (state != state_stop) {
+ WRONG_STATE("KW_I2C_IRQ_STOP");
+ *rc = -EIO;
+ }
+ return state_idle;
+ }
+
+ if (isr & KW_I2C_IRQ_START)
+ kw_write_reg(reg_isr, KW_I2C_IRQ_START);
+
+ return state;
+
+ stop:
+ kw_write_reg(reg_control, KW_I2C_CTL_STOP);
+ return state_stop;
+}
+
+static int keywest_low_i2c_func(struct low_i2c_host *host, u8 addr, u8 subaddr, u8 *data, int len)
+{
+ u8 mode_reg = host->speed;
+ int state = state_addr;
+ int rc = 0;
+
+ /* Setup mode & subaddress if any */
+ switch(host->mode) {
+ case pmac_low_i2c_mode_dumb:
+ printk(KERN_ERR "low_i2c: Dumb mode not supported !\n");
+ return -EINVAL;
+ case pmac_low_i2c_mode_std:
+ mode_reg |= KW_I2C_MODE_STANDARD;
+ break;
+ case pmac_low_i2c_mode_stdsub:
+ mode_reg |= KW_I2C_MODE_STANDARDSUB;
+ kw_write_reg(reg_subaddr, subaddr);
+ break;
+ case pmac_low_i2c_mode_combined:
+ mode_reg |= KW_I2C_MODE_COMBINED;
+ kw_write_reg(reg_subaddr, subaddr);
+ break;
+ }
+
+ /* Setup channel & clear pending irqs */
+ kw_write_reg(reg_isr, kw_read_reg(reg_isr));
+ kw_write_reg(reg_mode, mode_reg | (host->channel << 4));
+ kw_write_reg(reg_status, 0);
+
+ /* Set up address and r/w bit */
+ kw_write_reg(reg_addr, addr);
+
+ /* Start sending address & disable interrupt*/
+ kw_write_reg(reg_ier, 0 /*KW_I2C_IRQ_MASK*/);
+ kw_write_reg(reg_control, KW_I2C_CTL_XADDR);
+
+ /* State machine, to turn into an interrupt handler */
+ while(state != state_idle) {
+ u8 isr = kw_wait_interrupt(host);
+ state = kw_handle_interrupt(host, state, addr & 1, &rc, &data, &len, isr);
+ }
+
+ return rc;
+}
+
+static void keywest_low_i2c_add(struct device_node *np)
+{
+ struct low_i2c_host *host = find_low_i2c_host(NULL);
+ unsigned long *psteps, *prate, steps, aoffset = 0;
+ struct device_node *parent;
+
+ if (host == NULL) {
+ printk(KERN_ERR "low_i2c: Can't allocate host for %s\n",
+ np->full_name);
+ return;
+ }
+ memset(host, 0, sizeof(*host));
+
+ init_MUTEX(&host->mutex);
+ host->np = of_node_get(np);
+ psteps = (unsigned long *)get_property(np, "AAPL,address-step", NULL);
+ steps = psteps ? (*psteps) : 0x10;
+ for (host->bsteps = 0; (steps & 0x01) == 0; host->bsteps++)
+ steps >>= 1;
+ parent = of_get_parent(np);
+ host->num_channels = 1;
+ if (parent && parent->name[0] == 'u') {
+ host->num_channels = 2;
+ aoffset = 3;
+ }
+ /* Select interface rate */
+ host->speed = KW_I2C_MODE_100KHZ;
+ prate = (unsigned long *)get_property(np, "AAPL,i2c-rate", NULL);
+ if (prate) switch(*prate) {
+ case 100:
+ host->speed = KW_I2C_MODE_100KHZ;
+ break;
+ case 50:
+ host->speed = KW_I2C_MODE_50KHZ;
+ break;
+ case 25:
+ host->speed = KW_I2C_MODE_25KHZ;
+ break;
+ }
+ host->mode = pmac_low_i2c_mode_std;
+ host->base = (unsigned long)ioremap(np->addrs[0].address + aoffset,
+ np->addrs[0].size);
+ host->func = keywest_low_i2c_func;
+}
+
+/*
+ *
+ * PMU implementation
+ *
+ */
+
+
+#ifdef CONFIG_ADB_PMU
+
+static int pmu_low_i2c_func(struct low_i2c_host *host, u8 addr, u8 sub, u8 *data, int len)
+{
+ // TODO
+ return -ENODEV;
+}
+
+static void pmu_low_i2c_add(struct device_node *np)
+{
+ struct low_i2c_host *host = find_low_i2c_host(NULL);
+
+ if (host == NULL) {
+ printk(KERN_ERR "low_i2c: Can't allocate host for %s\n",
+ np->full_name);
+ return;
+ }
+ memset(host, 0, sizeof(*host));
+
+ init_MUTEX(&host->mutex);
+ host->np = of_node_get(np);
+ host->num_channels = 3;
+ host->mode = pmac_low_i2c_mode_std;
+ host->func = pmu_low_i2c_func;
+}
+
+#endif /* CONFIG_ADB_PMU */
+
+void __init pmac_init_low_i2c(void)
+{
+ struct device_node *np;
+
+ /* Probe keywest-i2c busses */
+ np = of_find_compatible_node(NULL, "i2c", "keywest-i2c");
+ while(np) {
+ keywest_low_i2c_add(np);
+ np = of_find_compatible_node(np, "i2c", "keywest-i2c");
+ }
+
+#ifdef CONFIG_ADB_PMU
+ /* Probe PMU busses */
+ np = of_find_node_by_name(NULL, "via-pmu");
+ if (np)
+ pmu_low_i2c_add(np);
+#endif /* CONFIG_ADB_PMU */
+
+ /* TODO: Add CUDA support as well */
+}
+
+int pmac_low_i2c_lock(struct device_node *np)
+{
+ struct low_i2c_host *host = find_low_i2c_host(np);
+
+ if (!host)
+ return -ENODEV;
+ down(&host->mutex);
+ return 0;
+}
+EXPORT_SYMBOL(pmac_low_i2c_lock);
+
+int pmac_low_i2c_unlock(struct device_node *np)
+{
+ struct low_i2c_host *host = find_low_i2c_host(np);
+
+ if (!host)
+ return -ENODEV;
+ up(&host->mutex);
+ return 0;
+}
+EXPORT_SYMBOL(pmac_low_i2c_unlock);
+
+
+int pmac_low_i2c_open(struct device_node *np, int channel)
+{
+ struct low_i2c_host *host = find_low_i2c_host(np);
+
+ if (!host)
+ return -ENODEV;
+
+ if (channel >= host->num_channels)
+ return -EINVAL;
+
+ down(&host->mutex);
+ host->is_open = 1;
+ host->channel = channel;
+
+ return 0;
+}
+EXPORT_SYMBOL(pmac_low_i2c_open);
+
+int pmac_low_i2c_close(struct device_node *np)
+{
+ struct low_i2c_host *host = find_low_i2c_host(np);
+
+ if (!host)
+ return -ENODEV;
+
+ host->is_open = 0;
+ up(&host->mutex);
+
+ return 0;
+}
+EXPORT_SYMBOL(pmac_low_i2c_close);
+
+int pmac_low_i2c_setmode(struct device_node *np, int mode)
+{
+ struct low_i2c_host *host = find_low_i2c_host(np);
+
+ if (!host)
+ return -ENODEV;
+ WARN_ON(!host->is_open);
+ host->mode = mode;
+
+ return 0;
+}
+EXPORT_SYMBOL(pmac_low_i2c_setmode);
+
+int pmac_low_i2c_xfer(struct device_node *np, u8 addrdir, u8 subaddr, u8 *data, int len)
+{
+ struct low_i2c_host *host = find_low_i2c_host(np);
+
+ if (!host)
+ return -ENODEV;
+ WARN_ON(!host->is_open);
+
+ return host->func(host, addrdir, subaddr, data, len);
+}
+EXPORT_SYMBOL(pmac_low_i2c_xfer);
+
diff --git a/arch/ppc/platforms/pmac_nvram.c b/arch/ppc/platforms/pmac_nvram.c
new file mode 100644
index 0000000..c9de642
--- /dev/null
+++ b/arch/ppc/platforms/pmac_nvram.c
@@ -0,0 +1,584 @@
+/*
+ * arch/ppc/platforms/pmac_nvram.c
+ *
+ * Copyright (C) 2002 Benjamin Herrenschmidt (benh@kernel.crashing.org)
+ *
+ * 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.
+ *
+ * Todo: - add support for the OF persistent properties
+ */
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/stddef.h>
+#include <linux/string.h>
+#include <linux/nvram.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/adb.h>
+#include <linux/pmu.h>
+#include <linux/bootmem.h>
+#include <linux/completion.h>
+#include <linux/spinlock.h>
+#include <asm/sections.h>
+#include <asm/io.h>
+#include <asm/system.h>
+#include <asm/prom.h>
+#include <asm/machdep.h>
+#include <asm/nvram.h>
+
+#define DEBUG
+
+#ifdef DEBUG
+#define DBG(x...) printk(x)
+#else
+#define DBG(x...)
+#endif
+
+#define NVRAM_SIZE 0x2000 /* 8kB of non-volatile RAM */
+
+#define CORE99_SIGNATURE 0x5a
+#define CORE99_ADLER_START 0x14
+
+/* On Core99, nvram is either a sharp, a micron or an AMD flash */
+#define SM_FLASH_STATUS_DONE 0x80
+#define SM_FLASH_STATUS_ERR 0x38
+#define SM_FLASH_CMD_ERASE_CONFIRM 0xd0
+#define SM_FLASH_CMD_ERASE_SETUP 0x20
+#define SM_FLASH_CMD_RESET 0xff
+#define SM_FLASH_CMD_WRITE_SETUP 0x40
+#define SM_FLASH_CMD_CLEAR_STATUS 0x50
+#define SM_FLASH_CMD_READ_STATUS 0x70
+
+/* CHRP NVRAM header */
+struct chrp_header {
+ u8 signature;
+ u8 cksum;
+ u16 len;
+ char name[12];
+ u8 data[0];
+};
+
+struct core99_header {
+ struct chrp_header hdr;
+ u32 adler;
+ u32 generation;
+ u32 reserved[2];
+};
+
+/*
+ * Read and write the non-volatile RAM on PowerMacs and CHRP machines.
+ */
+static int nvram_naddrs;
+static volatile unsigned char *nvram_addr;
+static volatile unsigned char *nvram_data;
+static int nvram_mult, is_core_99;
+static int core99_bank = 0;
+static int nvram_partitions[3];
+static DEFINE_SPINLOCK(nv_lock);
+
+extern int pmac_newworld;
+extern int system_running;
+
+static int (*core99_write_bank)(int bank, u8* datas);
+static int (*core99_erase_bank)(int bank);
+
+static char *nvram_image __pmacdata;
+
+
+static unsigned char __pmac core99_nvram_read_byte(int addr)
+{
+ if (nvram_image == NULL)
+ return 0xff;
+ return nvram_image[addr];
+}
+
+static void __pmac core99_nvram_write_byte(int addr, unsigned char val)
+{
+ if (nvram_image == NULL)
+ return;
+ nvram_image[addr] = val;
+}
+
+
+static unsigned char __openfirmware direct_nvram_read_byte(int addr)
+{
+ return in_8(&nvram_data[(addr & (NVRAM_SIZE - 1)) * nvram_mult]);
+}
+
+static void __openfirmware direct_nvram_write_byte(int addr, unsigned char val)
+{
+ out_8(&nvram_data[(addr & (NVRAM_SIZE - 1)) * nvram_mult], val);
+}
+
+
+static unsigned char __pmac indirect_nvram_read_byte(int addr)
+{
+ unsigned char val;
+ unsigned long flags;
+
+ spin_lock_irqsave(&nv_lock, flags);
+ out_8(nvram_addr, addr >> 5);
+ val = in_8(&nvram_data[(addr & 0x1f) << 4]);
+ spin_unlock_irqrestore(&nv_lock, flags);
+
+ return val;
+}
+
+static void __pmac indirect_nvram_write_byte(int addr, unsigned char val)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&nv_lock, flags);
+ out_8(nvram_addr, addr >> 5);
+ out_8(&nvram_data[(addr & 0x1f) << 4], val);
+ spin_unlock_irqrestore(&nv_lock, flags);
+}
+
+
+#ifdef CONFIG_ADB_PMU
+
+static void __pmac pmu_nvram_complete(struct adb_request *req)
+{
+ if (req->arg)
+ complete((struct completion *)req->arg);
+}
+
+static unsigned char __pmac pmu_nvram_read_byte(int addr)
+{
+ struct adb_request req;
+ DECLARE_COMPLETION(req_complete);
+
+ req.arg = system_state == SYSTEM_RUNNING ? &req_complete : NULL;
+ if (pmu_request(&req, pmu_nvram_complete, 3, PMU_READ_NVRAM,
+ (addr >> 8) & 0xff, addr & 0xff))
+ return 0xff;
+ if (system_state == SYSTEM_RUNNING)
+ wait_for_completion(&req_complete);
+ while (!req.complete)
+ pmu_poll();
+ return req.reply[0];
+}
+
+static void __pmac pmu_nvram_write_byte(int addr, unsigned char val)
+{
+ struct adb_request req;
+ DECLARE_COMPLETION(req_complete);
+
+ req.arg = system_state == SYSTEM_RUNNING ? &req_complete : NULL;
+ if (pmu_request(&req, pmu_nvram_complete, 4, PMU_WRITE_NVRAM,
+ (addr >> 8) & 0xff, addr & 0xff, val))
+ return;
+ if (system_state == SYSTEM_RUNNING)
+ wait_for_completion(&req_complete);
+ while (!req.complete)
+ pmu_poll();
+}
+
+#endif /* CONFIG_ADB_PMU */
+
+
+static u8 __pmac chrp_checksum(struct chrp_header* hdr)
+{
+ u8 *ptr;
+ u16 sum = hdr->signature;
+ for (ptr = (u8 *)&hdr->len; ptr < hdr->data; ptr++)
+ sum += *ptr;
+ while (sum > 0xFF)
+ sum = (sum & 0xFF) + (sum>>8);
+ return sum;
+}
+
+static u32 __pmac core99_calc_adler(u8 *buffer)
+{
+ int cnt;
+ u32 low, high;
+
+ buffer += CORE99_ADLER_START;
+ low = 1;
+ high = 0;
+ for (cnt=0; cnt<(NVRAM_SIZE-CORE99_ADLER_START); cnt++) {
+ if ((cnt % 5000) == 0) {
+ high %= 65521UL;
+ high %= 65521UL;
+ }
+ low += buffer[cnt];
+ high += low;
+ }
+ low %= 65521UL;
+ high %= 65521UL;
+
+ return (high << 16) | low;
+}
+
+static u32 __pmac core99_check(u8* datas)
+{
+ struct core99_header* hdr99 = (struct core99_header*)datas;
+
+ if (hdr99->hdr.signature != CORE99_SIGNATURE) {
+ DBG("Invalid signature\n");
+ return 0;
+ }
+ if (hdr99->hdr.cksum != chrp_checksum(&hdr99->hdr)) {
+ DBG("Invalid checksum\n");
+ return 0;
+ }
+ if (hdr99->adler != core99_calc_adler(datas)) {
+ DBG("Invalid adler\n");
+ return 0;
+ }
+ return hdr99->generation;
+}
+
+static int __pmac sm_erase_bank(int bank)
+{
+ int stat, i;
+ unsigned long timeout;
+
+ u8* base = (u8 *)nvram_data + core99_bank*NVRAM_SIZE;
+
+ DBG("nvram: Sharp/Micron Erasing bank %d...\n", bank);
+
+ out_8(base, SM_FLASH_CMD_ERASE_SETUP);
+ out_8(base, SM_FLASH_CMD_ERASE_CONFIRM);
+ timeout = 0;
+ do {
+ if (++timeout > 1000000) {
+ printk(KERN_ERR "nvram: Sharp/Miron flash erase timeout !\n");
+ break;
+ }
+ out_8(base, SM_FLASH_CMD_READ_STATUS);
+ stat = in_8(base);
+ } while (!(stat & SM_FLASH_STATUS_DONE));
+
+ out_8(base, SM_FLASH_CMD_CLEAR_STATUS);
+ out_8(base, SM_FLASH_CMD_RESET);
+
+ for (i=0; i<NVRAM_SIZE; i++)
+ if (base[i] != 0xff) {
+ printk(KERN_ERR "nvram: Sharp/Micron flash erase failed !\n");
+ return -ENXIO;
+ }
+ return 0;
+}
+
+static int __pmac sm_write_bank(int bank, u8* datas)
+{
+ int i, stat = 0;
+ unsigned long timeout;
+
+ u8* base = (u8 *)nvram_data + core99_bank*NVRAM_SIZE;
+
+ DBG("nvram: Sharp/Micron Writing bank %d...\n", bank);
+
+ for (i=0; i<NVRAM_SIZE; i++) {
+ out_8(base+i, SM_FLASH_CMD_WRITE_SETUP);
+ udelay(1);
+ out_8(base+i, datas[i]);
+ timeout = 0;
+ do {
+ if (++timeout > 1000000) {
+ printk(KERN_ERR "nvram: Sharp/Micron flash write timeout !\n");
+ break;
+ }
+ out_8(base, SM_FLASH_CMD_READ_STATUS);
+ stat = in_8(base);
+ } while (!(stat & SM_FLASH_STATUS_DONE));
+ if (!(stat & SM_FLASH_STATUS_DONE))
+ break;
+ }
+ out_8(base, SM_FLASH_CMD_CLEAR_STATUS);
+ out_8(base, SM_FLASH_CMD_RESET);
+ for (i=0; i<NVRAM_SIZE; i++)
+ if (base[i] != datas[i]) {
+ printk(KERN_ERR "nvram: Sharp/Micron flash write failed !\n");
+ return -ENXIO;
+ }
+ return 0;
+}
+
+static int __pmac amd_erase_bank(int bank)
+{
+ int i, stat = 0;
+ unsigned long timeout;
+
+ u8* base = (u8 *)nvram_data + core99_bank*NVRAM_SIZE;
+
+ DBG("nvram: AMD Erasing bank %d...\n", bank);
+
+ /* Unlock 1 */
+ out_8(base+0x555, 0xaa);
+ udelay(1);
+ /* Unlock 2 */
+ out_8(base+0x2aa, 0x55);
+ udelay(1);
+
+ /* Sector-Erase */
+ out_8(base+0x555, 0x80);
+ udelay(1);
+ out_8(base+0x555, 0xaa);
+ udelay(1);
+ out_8(base+0x2aa, 0x55);
+ udelay(1);
+ out_8(base, 0x30);
+ udelay(1);
+
+ timeout = 0;
+ do {
+ if (++timeout > 1000000) {
+ printk(KERN_ERR "nvram: AMD flash erase timeout !\n");
+ break;
+ }
+ stat = in_8(base) ^ in_8(base);
+ } while (stat != 0);
+
+ /* Reset */
+ out_8(base, 0xf0);
+ udelay(1);
+
+ for (i=0; i<NVRAM_SIZE; i++)
+ if (base[i] != 0xff) {
+ printk(KERN_ERR "nvram: AMD flash erase failed !\n");
+ return -ENXIO;
+ }
+ return 0;
+}
+
+static int __pmac amd_write_bank(int bank, u8* datas)
+{
+ int i, stat = 0;
+ unsigned long timeout;
+
+ u8* base = (u8 *)nvram_data + core99_bank*NVRAM_SIZE;
+
+ DBG("nvram: AMD Writing bank %d...\n", bank);
+
+ for (i=0; i<NVRAM_SIZE; i++) {
+ /* Unlock 1 */
+ out_8(base+0x555, 0xaa);
+ udelay(1);
+ /* Unlock 2 */
+ out_8(base+0x2aa, 0x55);
+ udelay(1);
+
+ /* Write single word */
+ out_8(base+0x555, 0xa0);
+ udelay(1);
+ out_8(base+i, datas[i]);
+
+ timeout = 0;
+ do {
+ if (++timeout > 1000000) {
+ printk(KERN_ERR "nvram: AMD flash write timeout !\n");
+ break;
+ }
+ stat = in_8(base) ^ in_8(base);
+ } while (stat != 0);
+ if (stat != 0)
+ break;
+ }
+
+ /* Reset */
+ out_8(base, 0xf0);
+ udelay(1);
+
+ for (i=0; i<NVRAM_SIZE; i++)
+ if (base[i] != datas[i]) {
+ printk(KERN_ERR "nvram: AMD flash write failed !\n");
+ return -ENXIO;
+ }
+ return 0;
+}
+
+static void __init lookup_partitions(void)
+{
+ u8 buffer[17];
+ int i, offset;
+ struct chrp_header* hdr;
+
+ if (pmac_newworld) {
+ nvram_partitions[pmac_nvram_OF] = -1;
+ nvram_partitions[pmac_nvram_XPRAM] = -1;
+ nvram_partitions[pmac_nvram_NR] = -1;
+ hdr = (struct chrp_header *)buffer;
+
+ offset = 0;
+ buffer[16] = 0;
+ do {
+ for (i=0;i<16;i++)
+ buffer[i] = nvram_read_byte(offset+i);
+ if (!strcmp(hdr->name, "common"))
+ nvram_partitions[pmac_nvram_OF] = offset + 0x10;
+ if (!strcmp(hdr->name, "APL,MacOS75")) {
+ nvram_partitions[pmac_nvram_XPRAM] = offset + 0x10;
+ nvram_partitions[pmac_nvram_NR] = offset + 0x110;
+ }
+ offset += (hdr->len * 0x10);
+ } while(offset < NVRAM_SIZE);
+ } else {
+ nvram_partitions[pmac_nvram_OF] = 0x1800;
+ nvram_partitions[pmac_nvram_XPRAM] = 0x1300;
+ nvram_partitions[pmac_nvram_NR] = 0x1400;
+ }
+ DBG("nvram: OF partition at 0x%x\n", nvram_partitions[pmac_nvram_OF]);
+ DBG("nvram: XP partition at 0x%x\n", nvram_partitions[pmac_nvram_XPRAM]);
+ DBG("nvram: NR partition at 0x%x\n", nvram_partitions[pmac_nvram_NR]);
+}
+
+static void __pmac core99_nvram_sync(void)
+{
+ struct core99_header* hdr99;
+ unsigned long flags;
+
+ if (!is_core_99 || !nvram_data || !nvram_image)
+ return;
+
+ spin_lock_irqsave(&nv_lock, flags);
+ if (!memcmp(nvram_image, (u8*)nvram_data + core99_bank*NVRAM_SIZE,
+ NVRAM_SIZE))
+ goto bail;
+
+ DBG("Updating nvram...\n");
+
+ hdr99 = (struct core99_header*)nvram_image;
+ hdr99->generation++;
+ hdr99->hdr.signature = CORE99_SIGNATURE;
+ hdr99->hdr.cksum = chrp_checksum(&hdr99->hdr);
+ hdr99->adler = core99_calc_adler(nvram_image);
+ core99_bank = core99_bank ? 0 : 1;
+ if (core99_erase_bank)
+ if (core99_erase_bank(core99_bank)) {
+ printk("nvram: Error erasing bank %d\n", core99_bank);
+ goto bail;
+ }
+ if (core99_write_bank)
+ if (core99_write_bank(core99_bank, nvram_image))
+ printk("nvram: Error writing bank %d\n", core99_bank);
+ bail:
+ spin_unlock_irqrestore(&nv_lock, flags);
+
+#ifdef DEBUG
+ mdelay(2000);
+#endif
+}
+
+void __init pmac_nvram_init(void)
+{
+ struct device_node *dp;
+
+ nvram_naddrs = 0;
+
+ dp = find_devices("nvram");
+ if (dp == NULL) {
+ printk(KERN_ERR "Can't find NVRAM device\n");
+ return;
+ }
+ nvram_naddrs = dp->n_addrs;
+ is_core_99 = device_is_compatible(dp, "nvram,flash");
+ if (is_core_99) {
+ int i;
+ u32 gen_bank0, gen_bank1;
+
+ if (nvram_naddrs < 1) {
+ printk(KERN_ERR "nvram: no address\n");
+ return;
+ }
+ nvram_image = alloc_bootmem(NVRAM_SIZE);
+ if (nvram_image == NULL) {
+ printk(KERN_ERR "nvram: can't allocate ram image\n");
+ return;
+ }
+ nvram_data = ioremap(dp->addrs[0].address, NVRAM_SIZE*2);
+ nvram_naddrs = 1; /* Make sure we get the correct case */
+
+ DBG("nvram: Checking bank 0...\n");
+
+ gen_bank0 = core99_check((u8 *)nvram_data);
+ gen_bank1 = core99_check((u8 *)nvram_data + NVRAM_SIZE);
+ core99_bank = (gen_bank0 < gen_bank1) ? 1 : 0;
+
+ DBG("nvram: gen0=%d, gen1=%d\n", gen_bank0, gen_bank1);
+ DBG("nvram: Active bank is: %d\n", core99_bank);
+
+ for (i=0; i<NVRAM_SIZE; i++)
+ nvram_image[i] = nvram_data[i + core99_bank*NVRAM_SIZE];
+
+ ppc_md.nvram_read_val = core99_nvram_read_byte;
+ ppc_md.nvram_write_val = core99_nvram_write_byte;
+ ppc_md.nvram_sync = core99_nvram_sync;
+ /*
+ * Maybe we could be smarter here though making an exclusive list
+ * of known flash chips is a bit nasty as older OF didn't provide us
+ * with a useful "compatible" entry. A solution would be to really
+ * identify the chip using flash id commands and base ourselves on
+ * a list of known chips IDs
+ */
+ if (device_is_compatible(dp, "amd-0137")) {
+ core99_erase_bank = amd_erase_bank;
+ core99_write_bank = amd_write_bank;
+ } else {
+ core99_erase_bank = sm_erase_bank;
+ core99_write_bank = sm_write_bank;
+ }
+ } else if (_machine == _MACH_chrp && nvram_naddrs == 1) {
+ nvram_data = ioremap(dp->addrs[0].address + isa_mem_base,
+ dp->addrs[0].size);
+ nvram_mult = 1;
+ ppc_md.nvram_read_val = direct_nvram_read_byte;
+ ppc_md.nvram_write_val = direct_nvram_write_byte;
+ } else if (nvram_naddrs == 1) {
+ nvram_data = ioremap(dp->addrs[0].address, dp->addrs[0].size);
+ nvram_mult = (dp->addrs[0].size + NVRAM_SIZE - 1) / NVRAM_SIZE;
+ ppc_md.nvram_read_val = direct_nvram_read_byte;
+ ppc_md.nvram_write_val = direct_nvram_write_byte;
+ } else if (nvram_naddrs == 2) {
+ nvram_addr = ioremap(dp->addrs[0].address, dp->addrs[0].size);
+ nvram_data = ioremap(dp->addrs[1].address, dp->addrs[1].size);
+ ppc_md.nvram_read_val = indirect_nvram_read_byte;
+ ppc_md.nvram_write_val = indirect_nvram_write_byte;
+ } else if (nvram_naddrs == 0 && sys_ctrler == SYS_CTRLER_PMU) {
+#ifdef CONFIG_ADB_PMU
+ nvram_naddrs = -1;
+ ppc_md.nvram_read_val = pmu_nvram_read_byte;
+ ppc_md.nvram_write_val = pmu_nvram_write_byte;
+#endif /* CONFIG_ADB_PMU */
+ } else {
+ printk(KERN_ERR "Don't know how to access NVRAM with %d addresses\n",
+ nvram_naddrs);
+ }
+ lookup_partitions();
+}
+
+int __pmac pmac_get_partition(int partition)
+{
+ return nvram_partitions[partition];
+}
+
+u8 __pmac pmac_xpram_read(int xpaddr)
+{
+ int offset = nvram_partitions[pmac_nvram_XPRAM];
+
+ if (offset < 0)
+ return 0xff;
+
+ return ppc_md.nvram_read_val(xpaddr + offset);
+}
+
+void __pmac pmac_xpram_write(int xpaddr, u8 data)
+{
+ int offset = nvram_partitions[pmac_nvram_XPRAM];
+
+ if (offset < 0)
+ return;
+
+ ppc_md.nvram_write_val(xpaddr + offset, data);
+}
+
+EXPORT_SYMBOL(pmac_get_partition);
+EXPORT_SYMBOL(pmac_xpram_read);
+EXPORT_SYMBOL(pmac_xpram_write);
diff --git a/arch/ppc/platforms/pmac_pci.c b/arch/ppc/platforms/pmac_pci.c
new file mode 100644
index 0000000..f6ff519
--- /dev/null
+++ b/arch/ppc/platforms/pmac_pci.c
@@ -0,0 +1,1125 @@
+/*
+ * Support for PCI bridges found on Power Macintoshes.
+ * At present the "bandit" and "chaos" bridges are supported.
+ * Fortunately you access configuration space in the same
+ * way with either bridge.
+ *
+ * Copyright (C) 1997 Paul Mackerras (paulus@cs.anu.edu.au)
+ *
+ * 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.
+ */
+
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/delay.h>
+#include <linux/string.h>
+#include <linux/init.h>
+#include <linux/bootmem.h>
+
+#include <asm/sections.h>
+#include <asm/io.h>
+#include <asm/prom.h>
+#include <asm/pci-bridge.h>
+#include <asm/machdep.h>
+#include <asm/pmac_feature.h>
+
+#undef DEBUG
+
+#ifdef DEBUG
+#ifdef CONFIG_XMON
+extern void xmon_printf(const char *fmt, ...);
+#define DBG(x...) xmon_printf(x)
+#else
+#define DBG(x...) printk(x)
+#endif
+#else
+#define DBG(x...)
+#endif
+
+static int add_bridge(struct device_node *dev);
+extern void pmac_check_ht_link(void);
+
+/* XXX Could be per-controller, but I don't think we risk anything by
+ * assuming we won't have both UniNorth and Bandit */
+static int has_uninorth;
+#ifdef CONFIG_POWER4
+static struct pci_controller *u3_agp;
+#endif /* CONFIG_POWER4 */
+
+extern u8 pci_cache_line_size;
+extern int pcibios_assign_bus_offset;
+
+struct device_node *k2_skiplist[2];
+
+/*
+ * Magic constants for enabling cache coherency in the bandit/PSX bridge.
+ */
+#define BANDIT_DEVID_2 8
+#define BANDIT_REVID 3
+
+#define BANDIT_DEVNUM 11
+#define BANDIT_MAGIC 0x50
+#define BANDIT_COHERENT 0x40
+
+static int __init
+fixup_one_level_bus_range(struct device_node *node, int higher)
+{
+ for (; node != 0;node = node->sibling) {
+ int * bus_range;
+ unsigned int *class_code;
+ int len;
+
+ /* For PCI<->PCI bridges or CardBus bridges, we go down */
+ class_code = (unsigned int *) get_property(node, "class-code", NULL);
+ if (!class_code || ((*class_code >> 8) != PCI_CLASS_BRIDGE_PCI &&
+ (*class_code >> 8) != PCI_CLASS_BRIDGE_CARDBUS))
+ continue;
+ bus_range = (int *) get_property(node, "bus-range", &len);
+ if (bus_range != NULL && len > 2 * sizeof(int)) {
+ if (bus_range[1] > higher)
+ higher = bus_range[1];
+ }
+ higher = fixup_one_level_bus_range(node->child, higher);
+ }
+ return higher;
+}
+
+/* This routine fixes the "bus-range" property of all bridges in the
+ * system since they tend to have their "last" member wrong on macs
+ *
+ * Note that the bus numbers manipulated here are OF bus numbers, they
+ * are not Linux bus numbers.
+ */
+static void __init
+fixup_bus_range(struct device_node *bridge)
+{
+ int * bus_range;
+ int len;
+
+ /* Lookup the "bus-range" property for the hose */
+ bus_range = (int *) get_property(bridge, "bus-range", &len);
+ if (bus_range == NULL || len < 2 * sizeof(int)) {
+ printk(KERN_WARNING "Can't get bus-range for %s\n",
+ bridge->full_name);
+ return;
+ }
+ bus_range[1] = fixup_one_level_bus_range(bridge->child, bus_range[1]);
+}
+
+/*
+ * Apple MacRISC (U3, UniNorth, Bandit, Chaos) PCI controllers.
+ *
+ * The "Bandit" version is present in all early PCI PowerMacs,
+ * and up to the first ones using Grackle. Some machines may
+ * have 2 bandit controllers (2 PCI busses).
+ *
+ * "Chaos" is used in some "Bandit"-type machines as a bridge
+ * for the separate display bus. It is accessed the same
+ * way as bandit, but cannot be probed for devices. It therefore
+ * has its own config access functions.
+ *
+ * The "UniNorth" version is present in all Core99 machines
+ * (iBook, G4, new IMacs, and all the recent Apple machines).
+ * It contains 3 controllers in one ASIC.
+ *
+ * The U3 is the bridge used on G5 machines. It contains an
+ * AGP bus which is dealt with the old UniNorth access routines
+ * and a HyperTransport bus which uses its own set of access
+ * functions.
+ */
+
+#define MACRISC_CFA0(devfn, off) \
+ ((1 << (unsigned long)PCI_SLOT(dev_fn)) \
+ | (((unsigned long)PCI_FUNC(dev_fn)) << 8) \
+ | (((unsigned long)(off)) & 0xFCUL))
+
+#define MACRISC_CFA1(bus, devfn, off) \
+ ((((unsigned long)(bus)) << 16) \
+ |(((unsigned long)(devfn)) << 8) \
+ |(((unsigned long)(off)) & 0xFCUL) \
+ |1UL)
+
+static void volatile __iomem * __pmac
+macrisc_cfg_access(struct pci_controller* hose, u8 bus, u8 dev_fn, u8 offset)
+{
+ unsigned int caddr;
+
+ if (bus == hose->first_busno) {
+ if (dev_fn < (11 << 3))
+ return NULL;
+ caddr = MACRISC_CFA0(dev_fn, offset);
+ } else
+ caddr = MACRISC_CFA1(bus, dev_fn, offset);
+
+ /* Uninorth will return garbage if we don't read back the value ! */
+ do {
+ out_le32(hose->cfg_addr, caddr);
+ } while (in_le32(hose->cfg_addr) != caddr);
+
+ offset &= has_uninorth ? 0x07 : 0x03;
+ return hose->cfg_data + offset;
+}
+
+static int __pmac
+macrisc_read_config(struct pci_bus *bus, unsigned int devfn, int offset,
+ int len, u32 *val)
+{
+ struct pci_controller *hose = bus->sysdata;
+ void volatile __iomem *addr;
+
+ addr = macrisc_cfg_access(hose, bus->number, devfn, offset);
+ if (!addr)
+ return PCIBIOS_DEVICE_NOT_FOUND;
+ /*
+ * Note: the caller has already checked that offset is
+ * suitably aligned and that len is 1, 2 or 4.
+ */
+ switch (len) {
+ case 1:
+ *val = in_8(addr);
+ break;
+ case 2:
+ *val = in_le16(addr);
+ break;
+ default:
+ *val = in_le32(addr);
+ break;
+ }
+ return PCIBIOS_SUCCESSFUL;
+}
+
+static int __pmac
+macrisc_write_config(struct pci_bus *bus, unsigned int devfn, int offset,
+ int len, u32 val)
+{
+ struct pci_controller *hose = bus->sysdata;
+ void volatile __iomem *addr;
+
+ addr = macrisc_cfg_access(hose, bus->number, devfn, offset);
+ if (!addr)
+ return PCIBIOS_DEVICE_NOT_FOUND;
+ /*
+ * Note: the caller has already checked that offset is
+ * suitably aligned and that len is 1, 2 or 4.
+ */
+ switch (len) {
+ case 1:
+ out_8(addr, val);
+ (void) in_8(addr);
+ break;
+ case 2:
+ out_le16(addr, val);
+ (void) in_le16(addr);
+ break;
+ default:
+ out_le32(addr, val);
+ (void) in_le32(addr);
+ break;
+ }
+ return PCIBIOS_SUCCESSFUL;
+}
+
+static struct pci_ops macrisc_pci_ops =
+{
+ macrisc_read_config,
+ macrisc_write_config
+};
+
+/*
+ * Verifiy that a specific (bus, dev_fn) exists on chaos
+ */
+static int __pmac
+chaos_validate_dev(struct pci_bus *bus, int devfn, int offset)
+{
+ struct device_node *np;
+ u32 *vendor, *device;
+
+ np = pci_busdev_to_OF_node(bus, devfn);
+ if (np == NULL)
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
+ vendor = (u32 *)get_property(np, "vendor-id", NULL);
+ device = (u32 *)get_property(np, "device-id", NULL);
+ if (vendor == NULL || device == NULL)
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
+ if ((*vendor == 0x106b) && (*device == 3) && (offset >= 0x10)
+ && (offset != 0x14) && (offset != 0x18) && (offset <= 0x24))
+ return PCIBIOS_BAD_REGISTER_NUMBER;
+
+ return PCIBIOS_SUCCESSFUL;
+}
+
+static int __pmac
+chaos_read_config(struct pci_bus *bus, unsigned int devfn, int offset,
+ int len, u32 *val)
+{
+ int result = chaos_validate_dev(bus, devfn, offset);
+ if (result == PCIBIOS_BAD_REGISTER_NUMBER)
+ *val = ~0U;
+ if (result != PCIBIOS_SUCCESSFUL)
+ return result;
+ return macrisc_read_config(bus, devfn, offset, len, val);
+}
+
+static int __pmac
+chaos_write_config(struct pci_bus *bus, unsigned int devfn, int offset,
+ int len, u32 val)
+{
+ int result = chaos_validate_dev(bus, devfn, offset);
+ if (result != PCIBIOS_SUCCESSFUL)
+ return result;
+ return macrisc_write_config(bus, devfn, offset, len, val);
+}
+
+static struct pci_ops chaos_pci_ops =
+{
+ chaos_read_config,
+ chaos_write_config
+};
+
+#ifdef CONFIG_POWER4
+
+/*
+ * These versions of U3 HyperTransport config space access ops do not
+ * implement self-view of the HT host yet
+ */
+
+#define U3_HT_CFA0(devfn, off) \
+ ((((unsigned long)devfn) << 8) | offset)
+#define U3_HT_CFA1(bus, devfn, off) \
+ (U3_HT_CFA0(devfn, off) \
+ + (((unsigned long)bus) << 16) \
+ + 0x01000000UL)
+
+static void volatile __iomem * __pmac
+u3_ht_cfg_access(struct pci_controller* hose, u8 bus, u8 devfn, u8 offset)
+{
+ if (bus == hose->first_busno) {
+ /* For now, we don't self probe U3 HT bridge */
+ if (PCI_FUNC(devfn) != 0 || PCI_SLOT(devfn) > 7 ||
+ PCI_SLOT(devfn) < 1)
+ return 0;
+ return hose->cfg_data + U3_HT_CFA0(devfn, offset);
+ } else
+ return hose->cfg_data + U3_HT_CFA1(bus, devfn, offset);
+}
+
+static int __pmac
+u3_ht_read_config(struct pci_bus *bus, unsigned int devfn, int offset,
+ int len, u32 *val)
+{
+ struct pci_controller *hose = bus->sysdata;
+ void volatile __iomem *addr;
+ int i;
+
+ struct device_node *np = pci_busdev_to_OF_node(bus, devfn);
+ if (np == NULL)
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
+ /*
+ * When a device in K2 is powered down, we die on config
+ * cycle accesses. Fix that here.
+ */
+ for (i=0; i<2; i++)
+ if (k2_skiplist[i] == np) {
+ switch (len) {
+ case 1:
+ *val = 0xff; break;
+ case 2:
+ *val = 0xffff; break;
+ default:
+ *val = 0xfffffffful; break;
+ }
+ return PCIBIOS_SUCCESSFUL;
+ }
+
+ addr = u3_ht_cfg_access(hose, bus->number, devfn, offset);
+ if (!addr)
+ return PCIBIOS_DEVICE_NOT_FOUND;
+ /*
+ * Note: the caller has already checked that offset is
+ * suitably aligned and that len is 1, 2 or 4.
+ */
+ switch (len) {
+ case 1:
+ *val = in_8(addr);
+ break;
+ case 2:
+ *val = in_le16(addr);
+ break;
+ default:
+ *val = in_le32(addr);
+ break;
+ }
+ return PCIBIOS_SUCCESSFUL;
+}
+
+static int __pmac
+u3_ht_write_config(struct pci_bus *bus, unsigned int devfn, int offset,
+ int len, u32 val)
+{
+ struct pci_controller *hose = bus->sysdata;
+ void volatile __iomem *addr;
+ int i;
+
+ struct device_node *np = pci_busdev_to_OF_node(bus, devfn);
+ if (np == NULL)
+ return PCIBIOS_DEVICE_NOT_FOUND;
+ /*
+ * When a device in K2 is powered down, we die on config
+ * cycle accesses. Fix that here.
+ */
+ for (i=0; i<2; i++)
+ if (k2_skiplist[i] == np)
+ return PCIBIOS_SUCCESSFUL;
+
+ addr = u3_ht_cfg_access(hose, bus->number, devfn, offset);
+ if (!addr)
+ return PCIBIOS_DEVICE_NOT_FOUND;
+ /*
+ * Note: the caller has already checked that offset is
+ * suitably aligned and that len is 1, 2 or 4.
+ */
+ switch (len) {
+ case 1:
+ out_8(addr, val);
+ (void) in_8(addr);
+ break;
+ case 2:
+ out_le16(addr, val);
+ (void) in_le16(addr);
+ break;
+ default:
+ out_le32(addr, val);
+ (void) in_le32(addr);
+ break;
+ }
+ return PCIBIOS_SUCCESSFUL;
+}
+
+static struct pci_ops u3_ht_pci_ops =
+{
+ u3_ht_read_config,
+ u3_ht_write_config
+};
+
+#endif /* CONFIG_POWER4 */
+
+/*
+ * For a bandit bridge, turn on cache coherency if necessary.
+ * N.B. we could clean this up using the hose ops directly.
+ */
+static void __init
+init_bandit(struct pci_controller *bp)
+{
+ unsigned int vendev, magic;
+ int rev;
+
+ /* read the word at offset 0 in config space for device 11 */
+ out_le32(bp->cfg_addr, (1UL << BANDIT_DEVNUM) + PCI_VENDOR_ID);
+ udelay(2);
+ vendev = in_le32(bp->cfg_data);
+ if (vendev == (PCI_DEVICE_ID_APPLE_BANDIT << 16) +
+ PCI_VENDOR_ID_APPLE) {
+ /* read the revision id */
+ out_le32(bp->cfg_addr,
+ (1UL << BANDIT_DEVNUM) + PCI_REVISION_ID);
+ udelay(2);
+ rev = in_8(bp->cfg_data);
+ if (rev != BANDIT_REVID)
+ printk(KERN_WARNING
+ "Unknown revision %d for bandit\n", rev);
+ } else if (vendev != (BANDIT_DEVID_2 << 16) + PCI_VENDOR_ID_APPLE) {
+ printk(KERN_WARNING "bandit isn't? (%x)\n", vendev);
+ return;
+ }
+
+ /* read the word at offset 0x50 */
+ out_le32(bp->cfg_addr, (1UL << BANDIT_DEVNUM) + BANDIT_MAGIC);
+ udelay(2);
+ magic = in_le32(bp->cfg_data);
+ if ((magic & BANDIT_COHERENT) != 0)
+ return;
+ magic |= BANDIT_COHERENT;
+ udelay(2);
+ out_le32(bp->cfg_data, magic);
+ printk(KERN_INFO "Cache coherency enabled for bandit/PSX\n");
+}
+
+
+/*
+ * Tweak the PCI-PCI bridge chip on the blue & white G3s.
+ */
+static void __init
+init_p2pbridge(void)
+{
+ struct device_node *p2pbridge;
+ struct pci_controller* hose;
+ u8 bus, devfn;
+ u16 val;
+
+ /* XXX it would be better here to identify the specific
+ PCI-PCI bridge chip we have. */
+ if ((p2pbridge = find_devices("pci-bridge")) == 0
+ || p2pbridge->parent == NULL
+ || strcmp(p2pbridge->parent->name, "pci") != 0)
+ return;
+ if (pci_device_from_OF_node(p2pbridge, &bus, &devfn) < 0) {
+ DBG("Can't find PCI infos for PCI<->PCI bridge\n");
+ return;
+ }
+ /* Warning: At this point, we have not yet renumbered all busses.
+ * So we must use OF walking to find out hose
+ */
+ hose = pci_find_hose_for_OF_device(p2pbridge);
+ if (!hose) {
+ DBG("Can't find hose for PCI<->PCI bridge\n");
+ return;
+ }
+ if (early_read_config_word(hose, bus, devfn,
+ PCI_BRIDGE_CONTROL, &val) < 0) {
+ printk(KERN_ERR "init_p2pbridge: couldn't read bridge control\n");
+ return;
+ }
+ val &= ~PCI_BRIDGE_CTL_MASTER_ABORT;
+ early_write_config_word(hose, bus, devfn, PCI_BRIDGE_CONTROL, val);
+}
+
+/*
+ * Some Apple desktop machines have a NEC PD720100A USB2 controller
+ * on the motherboard. Open Firmware, on these, will disable the
+ * EHCI part of it so it behaves like a pair of OHCI's. This fixup
+ * code re-enables it ;)
+ */
+static void __init
+fixup_nec_usb2(void)
+{
+ struct device_node *nec;
+
+ for (nec = NULL; (nec = of_find_node_by_name(nec, "usb")) != NULL;) {
+ struct pci_controller *hose;
+ u32 data, *prop;
+ u8 bus, devfn;
+
+ prop = (u32 *)get_property(nec, "vendor-id", NULL);
+ if (prop == NULL)
+ continue;
+ if (0x1033 != *prop)
+ continue;
+ prop = (u32 *)get_property(nec, "device-id", NULL);
+ if (prop == NULL)
+ continue;
+ if (0x0035 != *prop)
+ continue;
+ prop = (u32 *)get_property(nec, "reg", NULL);
+ if (prop == NULL)
+ continue;
+ devfn = (prop[0] >> 8) & 0xff;
+ bus = (prop[0] >> 16) & 0xff;
+ if (PCI_FUNC(devfn) != 0)
+ continue;
+ hose = pci_find_hose_for_OF_device(nec);
+ if (!hose)
+ continue;
+ early_read_config_dword(hose, bus, devfn, 0xe4, &data);
+ if (data & 1UL) {
+ printk("Found NEC PD720100A USB2 chip with disabled EHCI, fixing up...\n");
+ data &= ~1UL;
+ early_write_config_dword(hose, bus, devfn, 0xe4, data);
+ early_write_config_byte(hose, bus, devfn | 2, PCI_INTERRUPT_LINE,
+ nec->intrs[0].line);
+ }
+ }
+}
+
+void __init
+pmac_find_bridges(void)
+{
+ struct device_node *np, *root;
+ struct device_node *ht = NULL;
+
+ root = of_find_node_by_path("/");
+ if (root == NULL) {
+ printk(KERN_CRIT "pmac_find_bridges: can't find root of device tree\n");
+ return;
+ }
+ for (np = NULL; (np = of_get_next_child(root, np)) != NULL;) {
+ if (np->name == NULL)
+ continue;
+ if (strcmp(np->name, "bandit") == 0
+ || strcmp(np->name, "chaos") == 0
+ || strcmp(np->name, "pci") == 0) {
+ if (add_bridge(np) == 0)
+ of_node_get(np);
+ }
+ if (strcmp(np->name, "ht") == 0) {
+ of_node_get(np);
+ ht = np;
+ }
+ }
+ of_node_put(root);
+
+ /* Probe HT last as it relies on the agp resources to be already
+ * setup
+ */
+ if (ht && add_bridge(ht) != 0)
+ of_node_put(ht);
+
+ init_p2pbridge();
+ fixup_nec_usb2();
+
+ /* We are still having some issues with the Xserve G4, enabling
+ * some offset between bus number and domains for now when we
+ * assign all busses should help for now
+ */
+ if (pci_assign_all_busses)
+ pcibios_assign_bus_offset = 0x10;
+
+#ifdef CONFIG_POWER4
+ /* There is something wrong with DMA on U3/HT. I haven't figured out
+ * the details yet, but if I set the cache line size to 128 bytes like
+ * it should, I'm getting memory corruption caused by devices like
+ * sungem (even without the MWI bit set, but maybe sungem doesn't
+ * care). Right now, it appears that setting up a 64 bytes line size
+ * works properly, 64 bytes beeing the max transfer size of HT, I
+ * suppose this is related the way HT/PCI are hooked together. I still
+ * need to dive into more specs though to be really sure of what's
+ * going on. --BenH.
+ *
+ * Ok, apparently, it's just that HT can't do more than 64 bytes
+ * transactions. MWI seem to be meaningless there as well, it may
+ * be worth nop'ing out pci_set_mwi too though I haven't done that
+ * yet.
+ *
+ * Note that it's a bit different for whatever is in the AGP slot.
+ * For now, I don't care, but this can become a real issue, we
+ * should probably hook pci_set_mwi anyway to make sure it sets
+ * the real cache line size in there.
+ */
+ if (machine_is_compatible("MacRISC4"))
+ pci_cache_line_size = 16; /* 64 bytes */
+
+ pmac_check_ht_link();
+#endif /* CONFIG_POWER4 */
+}
+
+#define GRACKLE_CFA(b, d, o) (0x80 | ((b) << 8) | ((d) << 16) \
+ | (((o) & ~3) << 24))
+
+#define GRACKLE_PICR1_STG 0x00000040
+#define GRACKLE_PICR1_LOOPSNOOP 0x00000010
+
+/* N.B. this is called before bridges is initialized, so we can't
+ use grackle_pcibios_{read,write}_config_dword. */
+static inline void grackle_set_stg(struct pci_controller* bp, int enable)
+{
+ unsigned int val;
+
+ out_be32(bp->cfg_addr, GRACKLE_CFA(0, 0, 0xa8));
+ val = in_le32(bp->cfg_data);
+ val = enable? (val | GRACKLE_PICR1_STG) :
+ (val & ~GRACKLE_PICR1_STG);
+ out_be32(bp->cfg_addr, GRACKLE_CFA(0, 0, 0xa8));
+ out_le32(bp->cfg_data, val);
+ (void)in_le32(bp->cfg_data);
+}
+
+static inline void grackle_set_loop_snoop(struct pci_controller *bp, int enable)
+{
+ unsigned int val;
+
+ out_be32(bp->cfg_addr, GRACKLE_CFA(0, 0, 0xa8));
+ val = in_le32(bp->cfg_data);
+ val = enable? (val | GRACKLE_PICR1_LOOPSNOOP) :
+ (val & ~GRACKLE_PICR1_LOOPSNOOP);
+ out_be32(bp->cfg_addr, GRACKLE_CFA(0, 0, 0xa8));
+ out_le32(bp->cfg_data, val);
+ (void)in_le32(bp->cfg_data);
+}
+
+static int __init
+setup_uninorth(struct pci_controller* hose, struct reg_property* addr)
+{
+ pci_assign_all_busses = 1;
+ has_uninorth = 1;
+ hose->ops = ¯isc_pci_ops;
+ hose->cfg_addr = ioremap(addr->address + 0x800000, 0x1000);
+ hose->cfg_data = ioremap(addr->address + 0xc00000, 0x1000);
+ /* We "know" that the bridge at f2000000 has the PCI slots. */
+ return addr->address == 0xf2000000;
+}
+
+static void __init
+setup_bandit(struct pci_controller* hose, struct reg_property* addr)
+{
+ hose->ops = ¯isc_pci_ops;
+ hose->cfg_addr = ioremap(addr->address + 0x800000, 0x1000);
+ hose->cfg_data = ioremap(addr->address + 0xc00000, 0x1000);
+ init_bandit(hose);
+}
+
+static void __init
+setup_chaos(struct pci_controller* hose, struct reg_property* addr)
+{
+ /* assume a `chaos' bridge */
+ hose->ops = &chaos_pci_ops;
+ hose->cfg_addr = ioremap(addr->address + 0x800000, 0x1000);
+ hose->cfg_data = ioremap(addr->address + 0xc00000, 0x1000);
+}
+
+#ifdef CONFIG_POWER4
+
+static void __init
+setup_u3_agp(struct pci_controller* hose, struct reg_property* addr)
+{
+ /* On G5, we move AGP up to high bus number so we don't need
+ * to reassign bus numbers for HT. If we ever have P2P bridges
+ * on AGP, we'll have to move pci_assign_all_busses to the
+ * pci_controller structure so we enable it for AGP and not for
+ * HT childs.
+ * We hard code the address because of the different size of
+ * the reg address cell, we shall fix that by killing struct
+ * reg_property and using some accessor functions instead
+ */
+ hose->first_busno = 0xf0;
+ hose->last_busno = 0xff;
+ has_uninorth = 1;
+ hose->ops = ¯isc_pci_ops;
+ hose->cfg_addr = ioremap(0xf0000000 + 0x800000, 0x1000);
+ hose->cfg_data = ioremap(0xf0000000 + 0xc00000, 0x1000);
+
+ u3_agp = hose;
+}
+
+static void __init
+setup_u3_ht(struct pci_controller* hose, struct reg_property *addr)
+{
+ struct device_node *np = (struct device_node *)hose->arch_data;
+ int i, cur;
+
+ hose->ops = &u3_ht_pci_ops;
+
+ /* We hard code the address because of the different size of
+ * the reg address cell, we shall fix that by killing struct
+ * reg_property and using some accessor functions instead
+ */
+ hose->cfg_data = ioremap(0xf2000000, 0x02000000);
+
+ /*
+ * /ht node doesn't expose a "ranges" property, so we "remove" regions that
+ * have been allocated to AGP. So far, this version of the code doesn't assign
+ * any of the 0xfxxxxxxx "fine" memory regions to /ht.
+ * We need to fix that sooner or later by either parsing all child "ranges"
+ * properties or figuring out the U3 address space decoding logic and
+ * then read its configuration register (if any).
+ */
+ hose->io_base_phys = 0xf4000000;
+ hose->io_base_virt = ioremap(hose->io_base_phys, 0x00400000);
+ isa_io_base = (unsigned long) hose->io_base_virt;
+ hose->io_resource.name = np->full_name;
+ hose->io_resource.start = 0;
+ hose->io_resource.end = 0x003fffff;
+ hose->io_resource.flags = IORESOURCE_IO;
+ hose->pci_mem_offset = 0;
+ hose->first_busno = 0;
+ hose->last_busno = 0xef;
+ hose->mem_resources[0].name = np->full_name;
+ hose->mem_resources[0].start = 0x80000000;
+ hose->mem_resources[0].end = 0xefffffff;
+ hose->mem_resources[0].flags = IORESOURCE_MEM;
+
+ if (u3_agp == NULL) {
+ DBG("U3 has no AGP, using full resource range\n");
+ return;
+ }
+
+ /* We "remove" the AGP resources from the resources allocated to HT, that
+ * is we create "holes". However, that code does assumptions that so far
+ * happen to be true (cross fingers...), typically that resources in the
+ * AGP node are properly ordered
+ */
+ cur = 0;
+ for (i=0; i<3; i++) {
+ struct resource *res = &u3_agp->mem_resources[i];
+ if (res->flags != IORESOURCE_MEM)
+ continue;
+ /* We don't care about "fine" resources */
+ if (res->start >= 0xf0000000)
+ continue;
+ /* Check if it's just a matter of "shrinking" us in one direction */
+ if (hose->mem_resources[cur].start == res->start) {
+ DBG("U3/HT: shrink start of %d, %08lx -> %08lx\n",
+ cur, hose->mem_resources[cur].start, res->end + 1);
+ hose->mem_resources[cur].start = res->end + 1;
+ continue;
+ }
+ if (hose->mem_resources[cur].end == res->end) {
+ DBG("U3/HT: shrink end of %d, %08lx -> %08lx\n",
+ cur, hose->mem_resources[cur].end, res->start - 1);
+ hose->mem_resources[cur].end = res->start - 1;
+ continue;
+ }
+ /* No, it's not the case, we need a hole */
+ if (cur == 2) {
+ /* not enough resources to make a hole, we drop part of the range */
+ printk(KERN_WARNING "Running out of resources for /ht host !\n");
+ hose->mem_resources[cur].end = res->start - 1;
+ continue;
+ }
+ cur++;
+ DBG("U3/HT: hole, %d end at %08lx, %d start at %08lx\n",
+ cur-1, res->start - 1, cur, res->end + 1);
+ hose->mem_resources[cur].name = np->full_name;
+ hose->mem_resources[cur].flags = IORESOURCE_MEM;
+ hose->mem_resources[cur].start = res->end + 1;
+ hose->mem_resources[cur].end = hose->mem_resources[cur-1].end;
+ hose->mem_resources[cur-1].end = res->start - 1;
+ }
+}
+
+#endif /* CONFIG_POWER4 */
+
+void __init
+setup_grackle(struct pci_controller *hose)
+{
+ setup_indirect_pci(hose, 0xfec00000, 0xfee00000);
+ if (machine_is_compatible("AAPL,PowerBook1998"))
+ grackle_set_loop_snoop(hose, 1);
+#if 0 /* Disabled for now, HW problems ??? */
+ grackle_set_stg(hose, 1);
+#endif
+}
+
+/*
+ * We assume that if we have a G3 powermac, we have one bridge called
+ * "pci" (a MPC106) and no bandit or chaos bridges, and contrariwise,
+ * if we have one or more bandit or chaos bridges, we don't have a MPC106.
+ */
+static int __init
+add_bridge(struct device_node *dev)
+{
+ int len;
+ struct pci_controller *hose;
+ struct reg_property *addr;
+ char* disp_name;
+ int *bus_range;
+ int primary = 1;
+
+ DBG("Adding PCI host bridge %s\n", dev->full_name);
+
+ addr = (struct reg_property *) get_property(dev, "reg", &len);
+ if (addr == NULL || len < sizeof(*addr)) {
+ printk(KERN_WARNING "Can't use %s: no address\n",
+ dev->full_name);
+ return -ENODEV;
+ }
+ bus_range = (int *) get_property(dev, "bus-range", &len);
+ if (bus_range == NULL || len < 2 * sizeof(int)) {
+ printk(KERN_WARNING "Can't get bus-range for %s, assume bus 0\n",
+ dev->full_name);
+ }
+
+ hose = pcibios_alloc_controller();
+ if (!hose)
+ return -ENOMEM;
+ hose->arch_data = dev;
+ hose->first_busno = bus_range ? bus_range[0] : 0;
+ hose->last_busno = bus_range ? bus_range[1] : 0xff;
+
+ disp_name = NULL;
+#ifdef CONFIG_POWER4
+ if (device_is_compatible(dev, "u3-agp")) {
+ setup_u3_agp(hose, addr);
+ disp_name = "U3-AGP";
+ primary = 0;
+ } else if (device_is_compatible(dev, "u3-ht")) {
+ setup_u3_ht(hose, addr);
+ disp_name = "U3-HT";
+ primary = 1;
+ } else
+#endif /* CONFIG_POWER4 */
+ if (device_is_compatible(dev, "uni-north")) {
+ primary = setup_uninorth(hose, addr);
+ disp_name = "UniNorth";
+ } else if (strcmp(dev->name, "pci") == 0) {
+ /* XXX assume this is a mpc106 (grackle) */
+ setup_grackle(hose);
+ disp_name = "Grackle (MPC106)";
+ } else if (strcmp(dev->name, "bandit") == 0) {
+ setup_bandit(hose, addr);
+ disp_name = "Bandit";
+ } else if (strcmp(dev->name, "chaos") == 0) {
+ setup_chaos(hose, addr);
+ disp_name = "Chaos";
+ primary = 0;
+ }
+ printk(KERN_INFO "Found %s PCI host bridge at 0x%08x. Firmware bus number: %d->%d\n",
+ disp_name, addr->address, hose->first_busno, hose->last_busno);
+ DBG(" ->Hose at 0x%p, cfg_addr=0x%p,cfg_data=0x%p\n",
+ hose, hose->cfg_addr, hose->cfg_data);
+
+ /* Interpret the "ranges" property */
+ /* This also maps the I/O region and sets isa_io/mem_base */
+ pci_process_bridge_OF_ranges(hose, dev, primary);
+
+ /* Fixup "bus-range" OF property */
+ fixup_bus_range(dev);
+
+ return 0;
+}
+
+static void __init
+pcibios_fixup_OF_interrupts(void)
+{
+ struct pci_dev* dev = NULL;
+
+ /*
+ * Open Firmware often doesn't initialize the
+ * PCI_INTERRUPT_LINE config register properly, so we
+ * should find the device node and apply the interrupt
+ * obtained from the OF device-tree
+ */
+ for_each_pci_dev(dev) {
+ struct device_node *node;
+ node = pci_device_to_OF_node(dev);
+ /* this is the node, see if it has interrupts */
+ if (node && node->n_intrs > 0)
+ dev->irq = node->intrs[0].line;
+ pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq);
+ }
+}
+
+void __init
+pmac_pcibios_fixup(void)
+{
+ /* Fixup interrupts according to OF tree */
+ pcibios_fixup_OF_interrupts();
+}
+
+int __pmac
+pmac_pci_enable_device_hook(struct pci_dev *dev, int initial)
+{
+ struct device_node* node;
+ int updatecfg = 0;
+ int uninorth_child;
+
+ node = pci_device_to_OF_node(dev);
+
+ /* We don't want to enable USB controllers absent from the OF tree
+ * (iBook second controller)
+ */
+ if (dev->vendor == PCI_VENDOR_ID_APPLE
+ && (dev->class == ((PCI_CLASS_SERIAL_USB << 8) | 0x10))
+ && !node) {
+ printk(KERN_INFO "Apple USB OHCI %s disabled by firmware\n",
+ pci_name(dev));
+ return -EINVAL;
+ }
+
+ if (!node)
+ return 0;
+
+ uninorth_child = node->parent &&
+ device_is_compatible(node->parent, "uni-north");
+
+ /* Firewire & GMAC were disabled after PCI probe, the driver is
+ * claiming them, we must re-enable them now.
+ */
+ if (uninorth_child && !strcmp(node->name, "firewire") &&
+ (device_is_compatible(node, "pci106b,18") ||
+ device_is_compatible(node, "pci106b,30") ||
+ device_is_compatible(node, "pci11c1,5811"))) {
+ pmac_call_feature(PMAC_FTR_1394_CABLE_POWER, node, 0, 1);
+ pmac_call_feature(PMAC_FTR_1394_ENABLE, node, 0, 1);
+ updatecfg = 1;
+ }
+ if (uninorth_child && !strcmp(node->name, "ethernet") &&
+ device_is_compatible(node, "gmac")) {
+ pmac_call_feature(PMAC_FTR_GMAC_ENABLE, node, 0, 1);
+ updatecfg = 1;
+ }
+
+ if (updatecfg) {
+ u16 cmd;
+
+ /*
+ * Make sure PCI is correctly configured
+ *
+ * We use old pci_bios versions of the function since, by
+ * default, gmac is not powered up, and so will be absent
+ * from the kernel initial PCI lookup.
+ *
+ * Should be replaced by 2.4 new PCI mechanisms and really
+ * register the device.
+ */
+ pci_read_config_word(dev, PCI_COMMAND, &cmd);
+ cmd |= PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER | PCI_COMMAND_INVALIDATE;
+ pci_write_config_word(dev, PCI_COMMAND, cmd);
+ pci_write_config_byte(dev, PCI_LATENCY_TIMER, 16);
+ pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, pci_cache_line_size);
+ }
+
+ return 0;
+}
+
+/* We power down some devices after they have been probed. They'll
+ * be powered back on later on
+ */
+void __init
+pmac_pcibios_after_init(void)
+{
+ struct device_node* nd;
+
+#ifdef CONFIG_BLK_DEV_IDE
+ struct pci_dev *dev = NULL;
+
+ /* OF fails to initialize IDE controllers on macs
+ * (and maybe other machines)
+ *
+ * Ideally, this should be moved to the IDE layer, but we need
+ * to check specifically with Andre Hedrick how to do it cleanly
+ * since the common IDE code seem to care about the fact that the
+ * BIOS may have disabled a controller.
+ *
+ * -- BenH
+ */
+ for_each_pci_dev(dev) {
+ if ((dev->class >> 16) == PCI_BASE_CLASS_STORAGE)
+ pci_enable_device(dev);
+ }
+#endif /* CONFIG_BLK_DEV_IDE */
+
+ nd = find_devices("firewire");
+ while (nd) {
+ if (nd->parent && (device_is_compatible(nd, "pci106b,18") ||
+ device_is_compatible(nd, "pci106b,30") ||
+ device_is_compatible(nd, "pci11c1,5811"))
+ && device_is_compatible(nd->parent, "uni-north")) {
+ pmac_call_feature(PMAC_FTR_1394_ENABLE, nd, 0, 0);
+ pmac_call_feature(PMAC_FTR_1394_CABLE_POWER, nd, 0, 0);
+ }
+ nd = nd->next;
+ }
+ nd = find_devices("ethernet");
+ while (nd) {
+ if (nd->parent && device_is_compatible(nd, "gmac")
+ && device_is_compatible(nd->parent, "uni-north"))
+ pmac_call_feature(PMAC_FTR_GMAC_ENABLE, nd, 0, 0);
+ nd = nd->next;
+ }
+}
+
+void pmac_pci_fixup_cardbus(struct pci_dev* dev)
+{
+ if (_machine != _MACH_Pmac)
+ return;
+ /*
+ * Fix the interrupt routing on the various cardbus bridges
+ * used on powerbooks
+ */
+ if (dev->vendor != PCI_VENDOR_ID_TI)
+ return;
+ if (dev->device == PCI_DEVICE_ID_TI_1130 ||
+ dev->device == PCI_DEVICE_ID_TI_1131) {
+ u8 val;
+ /* Enable PCI interrupt */
+ if (pci_read_config_byte(dev, 0x91, &val) == 0)
+ pci_write_config_byte(dev, 0x91, val | 0x30);
+ /* Disable ISA interrupt mode */
+ if (pci_read_config_byte(dev, 0x92, &val) == 0)
+ pci_write_config_byte(dev, 0x92, val & ~0x06);
+ }
+ if (dev->device == PCI_DEVICE_ID_TI_1210 ||
+ dev->device == PCI_DEVICE_ID_TI_1211 ||
+ dev->device == PCI_DEVICE_ID_TI_1410 ||
+ dev->device == PCI_DEVICE_ID_TI_1510) {
+ u8 val;
+ /* 0x8c == TI122X_IRQMUX, 2 says to route the INTA
+ signal out the MFUNC0 pin */
+ if (pci_read_config_byte(dev, 0x8c, &val) == 0)
+ pci_write_config_byte(dev, 0x8c, (val & ~0x0f) | 2);
+ /* Disable ISA interrupt mode */
+ if (pci_read_config_byte(dev, 0x92, &val) == 0)
+ pci_write_config_byte(dev, 0x92, val & ~0x06);
+ }
+}
+
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_TI, PCI_ANY_ID, pmac_pci_fixup_cardbus);
+
+void pmac_pci_fixup_pciata(struct pci_dev* dev)
+{
+ u8 progif = 0;
+
+ /*
+ * On PowerMacs, we try to switch any PCI ATA controller to
+ * fully native mode
+ */
+ if (_machine != _MACH_Pmac)
+ return;
+ /* Some controllers don't have the class IDE */
+ if (dev->vendor == PCI_VENDOR_ID_PROMISE)
+ switch(dev->device) {
+ case PCI_DEVICE_ID_PROMISE_20246:
+ case PCI_DEVICE_ID_PROMISE_20262:
+ case PCI_DEVICE_ID_PROMISE_20263:
+ case PCI_DEVICE_ID_PROMISE_20265:
+ case PCI_DEVICE_ID_PROMISE_20267:
+ case PCI_DEVICE_ID_PROMISE_20268:
+ case PCI_DEVICE_ID_PROMISE_20269:
+ case PCI_DEVICE_ID_PROMISE_20270:
+ case PCI_DEVICE_ID_PROMISE_20271:
+ case PCI_DEVICE_ID_PROMISE_20275:
+ case PCI_DEVICE_ID_PROMISE_20276:
+ case PCI_DEVICE_ID_PROMISE_20277:
+ goto good;
+ }
+ /* Others, check PCI class */
+ if ((dev->class >> 8) != PCI_CLASS_STORAGE_IDE)
+ return;
+ good:
+ pci_read_config_byte(dev, PCI_CLASS_PROG, &progif);
+ if ((progif & 5) != 5) {
+ printk(KERN_INFO "Forcing PCI IDE into native mode: %s\n", pci_name(dev));
+ (void) pci_write_config_byte(dev, PCI_CLASS_PROG, progif|5);
+ if (pci_read_config_byte(dev, PCI_CLASS_PROG, &progif) ||
+ (progif & 5) != 5)
+ printk(KERN_ERR "Rewrite of PROGIF failed !\n");
+ }
+}
+DECLARE_PCI_FIXUP_FINAL(PCI_ANY_ID, PCI_ANY_ID, pmac_pci_fixup_pciata);
+
+
+/*
+ * Disable second function on K2-SATA, it's broken
+ * and disable IO BARs on first one
+ */
+void __pmac pmac_pci_fixup_k2_sata(struct pci_dev* dev)
+{
+ int i;
+ u16 cmd;
+
+ if (PCI_FUNC(dev->devfn) > 0) {
+ pci_read_config_word(dev, PCI_COMMAND, &cmd);
+ cmd &= ~(PCI_COMMAND_IO | PCI_COMMAND_MEMORY);
+ pci_write_config_word(dev, PCI_COMMAND, cmd);
+ for (i = 0; i < 6; i++) {
+ dev->resource[i].start = dev->resource[i].end = 0;
+ dev->resource[i].flags = 0;
+ pci_write_config_dword(dev, PCI_BASE_ADDRESS_0 + 4 * i, 0);
+ }
+ } else {
+ pci_read_config_word(dev, PCI_COMMAND, &cmd);
+ cmd &= ~PCI_COMMAND_IO;
+ pci_write_config_word(dev, PCI_COMMAND, cmd);
+ for (i = 0; i < 5; i++) {
+ dev->resource[i].start = dev->resource[i].end = 0;
+ dev->resource[i].flags = 0;
+ pci_write_config_dword(dev, PCI_BASE_ADDRESS_0 + 4 * i, 0);
+ }
+ }
+}
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SERVERWORKS, 0x0240, pmac_pci_fixup_k2_sata);
diff --git a/arch/ppc/platforms/pmac_pic.c b/arch/ppc/platforms/pmac_pic.c
new file mode 100644
index 0000000..9f92e1b
--- /dev/null
+++ b/arch/ppc/platforms/pmac_pic.c
@@ -0,0 +1,689 @@
+/*
+ * Support for the interrupt controllers found on Power Macintosh,
+ * currently Apple's "Grand Central" interrupt controller in all
+ * it's incarnations. OpenPIC support used on newer machines is
+ * in a separate file
+ *
+ * Copyright (C) 1997 Paul Mackerras (paulus@cs.anu.edu.au)
+ *
+ * Maintained by Benjamin Herrenschmidt (benh@kernel.crashing.org)
+ *
+ * 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.
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/stddef.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/signal.h>
+#include <linux/pci.h>
+#include <linux/interrupt.h>
+#include <linux/sysdev.h>
+#include <linux/adb.h>
+#include <linux/pmu.h>
+
+#include <asm/sections.h>
+#include <asm/io.h>
+#include <asm/smp.h>
+#include <asm/prom.h>
+#include <asm/pci-bridge.h>
+#include <asm/time.h>
+#include <asm/open_pic.h>
+#include <asm/xmon.h>
+#include <asm/pmac_feature.h>
+
+#include "pmac_pic.h"
+
+/*
+ * XXX this should be in xmon.h, but putting it there means xmon.h
+ * has to include <linux/interrupt.h> (to get irqreturn_t), which
+ * causes all sorts of problems. -- paulus
+ */
+extern irqreturn_t xmon_irq(int, void *, struct pt_regs *);
+
+struct pmac_irq_hw {
+ unsigned int event;
+ unsigned int enable;
+ unsigned int ack;
+ unsigned int level;
+};
+
+/* Default addresses */
+static volatile struct pmac_irq_hw *pmac_irq_hw[4] __pmacdata = {
+ (struct pmac_irq_hw *) 0xf3000020,
+ (struct pmac_irq_hw *) 0xf3000010,
+ (struct pmac_irq_hw *) 0xf4000020,
+ (struct pmac_irq_hw *) 0xf4000010,
+};
+
+#define GC_LEVEL_MASK 0x3ff00000
+#define OHARE_LEVEL_MASK 0x1ff00000
+#define HEATHROW_LEVEL_MASK 0x1ff00000
+
+static int max_irqs __pmacdata;
+static int max_real_irqs __pmacdata;
+static u32 level_mask[4] __pmacdata;
+
+static DEFINE_SPINLOCK(pmac_pic_lock __pmacdata);
+
+
+#define GATWICK_IRQ_POOL_SIZE 10
+static struct interrupt_info gatwick_int_pool[GATWICK_IRQ_POOL_SIZE] __pmacdata;
+
+/*
+ * Mark an irq as "lost". This is only used on the pmac
+ * since it can lose interrupts (see pmac_set_irq_mask).
+ * -- Cort
+ */
+void __pmac
+__set_lost(unsigned long irq_nr, int nokick)
+{
+ if (!test_and_set_bit(irq_nr, ppc_lost_interrupts)) {
+ atomic_inc(&ppc_n_lost_interrupts);
+ if (!nokick)
+ set_dec(1);
+ }
+}
+
+static void __pmac
+pmac_mask_and_ack_irq(unsigned int irq_nr)
+{
+ unsigned long bit = 1UL << (irq_nr & 0x1f);
+ int i = irq_nr >> 5;
+ unsigned long flags;
+
+ if ((unsigned)irq_nr >= max_irqs)
+ return;
+
+ clear_bit(irq_nr, ppc_cached_irq_mask);
+ if (test_and_clear_bit(irq_nr, ppc_lost_interrupts))
+ atomic_dec(&ppc_n_lost_interrupts);
+ spin_lock_irqsave(&pmac_pic_lock, flags);
+ out_le32(&pmac_irq_hw[i]->enable, ppc_cached_irq_mask[i]);
+ out_le32(&pmac_irq_hw[i]->ack, bit);
+ do {
+ /* make sure ack gets to controller before we enable
+ interrupts */
+ mb();
+ } while((in_le32(&pmac_irq_hw[i]->enable) & bit)
+ != (ppc_cached_irq_mask[i] & bit));
+ spin_unlock_irqrestore(&pmac_pic_lock, flags);
+}
+
+static void __pmac pmac_set_irq_mask(unsigned int irq_nr, int nokicklost)
+{
+ unsigned long bit = 1UL << (irq_nr & 0x1f);
+ int i = irq_nr >> 5;
+ unsigned long flags;
+
+ if ((unsigned)irq_nr >= max_irqs)
+ return;
+
+ spin_lock_irqsave(&pmac_pic_lock, flags);
+ /* enable unmasked interrupts */
+ out_le32(&pmac_irq_hw[i]->enable, ppc_cached_irq_mask[i]);
+
+ do {
+ /* make sure mask gets to controller before we
+ return to user */
+ mb();
+ } while((in_le32(&pmac_irq_hw[i]->enable) & bit)
+ != (ppc_cached_irq_mask[i] & bit));
+
+ /*
+ * Unfortunately, setting the bit in the enable register
+ * when the device interrupt is already on *doesn't* set
+ * the bit in the flag register or request another interrupt.
+ */
+ if (bit & ppc_cached_irq_mask[i] & in_le32(&pmac_irq_hw[i]->level))
+ __set_lost((ulong)irq_nr, nokicklost);
+ spin_unlock_irqrestore(&pmac_pic_lock, flags);
+}
+
+/* When an irq gets requested for the first client, if it's an
+ * edge interrupt, we clear any previous one on the controller
+ */
+static unsigned int __pmac pmac_startup_irq(unsigned int irq_nr)
+{
+ unsigned long bit = 1UL << (irq_nr & 0x1f);
+ int i = irq_nr >> 5;
+
+ if ((irq_desc[irq_nr].status & IRQ_LEVEL) == 0)
+ out_le32(&pmac_irq_hw[i]->ack, bit);
+ set_bit(irq_nr, ppc_cached_irq_mask);
+ pmac_set_irq_mask(irq_nr, 0);
+
+ return 0;
+}
+
+static void __pmac pmac_mask_irq(unsigned int irq_nr)
+{
+ clear_bit(irq_nr, ppc_cached_irq_mask);
+ pmac_set_irq_mask(irq_nr, 0);
+ mb();
+}
+
+static void __pmac pmac_unmask_irq(unsigned int irq_nr)
+{
+ set_bit(irq_nr, ppc_cached_irq_mask);
+ pmac_set_irq_mask(irq_nr, 0);
+}
+
+static void __pmac pmac_end_irq(unsigned int irq_nr)
+{
+ if (!(irq_desc[irq_nr].status & (IRQ_DISABLED|IRQ_INPROGRESS))
+ && irq_desc[irq_nr].action) {
+ set_bit(irq_nr, ppc_cached_irq_mask);
+ pmac_set_irq_mask(irq_nr, 1);
+ }
+}
+
+
+struct hw_interrupt_type pmac_pic = {
+ .typename = " PMAC-PIC ",
+ .startup = pmac_startup_irq,
+ .enable = pmac_unmask_irq,
+ .disable = pmac_mask_irq,
+ .ack = pmac_mask_and_ack_irq,
+ .end = pmac_end_irq,
+};
+
+struct hw_interrupt_type gatwick_pic = {
+ .typename = " GATWICK ",
+ .startup = pmac_startup_irq,
+ .enable = pmac_unmask_irq,
+ .disable = pmac_mask_irq,
+ .ack = pmac_mask_and_ack_irq,
+ .end = pmac_end_irq,
+};
+
+static irqreturn_t gatwick_action(int cpl, void *dev_id, struct pt_regs *regs)
+{
+ int irq, bits;
+
+ for (irq = max_irqs; (irq -= 32) >= max_real_irqs; ) {
+ int i = irq >> 5;
+ bits = in_le32(&pmac_irq_hw[i]->event) | ppc_lost_interrupts[i];
+ /* We must read level interrupts from the level register */
+ bits |= (in_le32(&pmac_irq_hw[i]->level) & level_mask[i]);
+ bits &= ppc_cached_irq_mask[i];
+ if (bits == 0)
+ continue;
+ irq += __ilog2(bits);
+ __do_IRQ(irq, regs);
+ return IRQ_HANDLED;
+ }
+ printk("gatwick irq not from gatwick pic\n");
+ return IRQ_NONE;
+}
+
+int
+pmac_get_irq(struct pt_regs *regs)
+{
+ int irq;
+ unsigned long bits = 0;
+
+#ifdef CONFIG_SMP
+ void psurge_smp_message_recv(struct pt_regs *);
+
+ /* IPI's are a hack on the powersurge -- Cort */
+ if ( smp_processor_id() != 0 ) {
+ psurge_smp_message_recv(regs);
+ return -2; /* ignore, already handled */
+ }
+#endif /* CONFIG_SMP */
+ for (irq = max_real_irqs; (irq -= 32) >= 0; ) {
+ int i = irq >> 5;
+ bits = in_le32(&pmac_irq_hw[i]->event) | ppc_lost_interrupts[i];
+ /* We must read level interrupts from the level register */
+ bits |= (in_le32(&pmac_irq_hw[i]->level) & level_mask[i]);
+ bits &= ppc_cached_irq_mask[i];
+ if (bits == 0)
+ continue;
+ irq += __ilog2(bits);
+ break;
+ }
+
+ return irq;
+}
+
+/* This routine will fix some missing interrupt values in the device tree
+ * on the gatwick mac-io controller used by some PowerBooks
+ */
+static void __init
+pmac_fix_gatwick_interrupts(struct device_node *gw, int irq_base)
+{
+ struct device_node *node;
+ int count;
+
+ memset(gatwick_int_pool, 0, sizeof(gatwick_int_pool));
+ node = gw->child;
+ count = 0;
+ while(node)
+ {
+ /* Fix SCC */
+ if (strcasecmp(node->name, "escc") == 0)
+ if (node->child) {
+ if (node->child->n_intrs < 3) {
+ node->child->intrs = &gatwick_int_pool[count];
+ count += 3;
+ }
+ node->child->n_intrs = 3;
+ node->child->intrs[0].line = 15+irq_base;
+ node->child->intrs[1].line = 4+irq_base;
+ node->child->intrs[2].line = 5+irq_base;
+ printk(KERN_INFO "irq: fixed SCC on second controller (%d,%d,%d)\n",
+ node->child->intrs[0].line,
+ node->child->intrs[1].line,
+ node->child->intrs[2].line);
+ }
+ /* Fix media-bay & left SWIM */
+ if (strcasecmp(node->name, "media-bay") == 0) {
+ struct device_node* ya_node;
+
+ if (node->n_intrs == 0)
+ node->intrs = &gatwick_int_pool[count++];
+ node->n_intrs = 1;
+ node->intrs[0].line = 29+irq_base;
+ printk(KERN_INFO "irq: fixed media-bay on second controller (%d)\n",
+ node->intrs[0].line);
+
+ ya_node = node->child;
+ while(ya_node)
+ {
+ if (strcasecmp(ya_node->name, "floppy") == 0) {
+ if (ya_node->n_intrs < 2) {
+ ya_node->intrs = &gatwick_int_pool[count];
+ count += 2;
+ }
+ ya_node->n_intrs = 2;
+ ya_node->intrs[0].line = 19+irq_base;
+ ya_node->intrs[1].line = 1+irq_base;
+ printk(KERN_INFO "irq: fixed floppy on second controller (%d,%d)\n",
+ ya_node->intrs[0].line, ya_node->intrs[1].line);
+ }
+ if (strcasecmp(ya_node->name, "ata4") == 0) {
+ if (ya_node->n_intrs < 2) {
+ ya_node->intrs = &gatwick_int_pool[count];
+ count += 2;
+ }
+ ya_node->n_intrs = 2;
+ ya_node->intrs[0].line = 14+irq_base;
+ ya_node->intrs[1].line = 3+irq_base;
+ printk(KERN_INFO "irq: fixed ide on second controller (%d,%d)\n",
+ ya_node->intrs[0].line, ya_node->intrs[1].line);
+ }
+ ya_node = ya_node->sibling;
+ }
+ }
+ node = node->sibling;
+ }
+ if (count > 10) {
+ printk("WARNING !! Gatwick interrupt pool overflow\n");
+ printk(" GATWICK_IRQ_POOL_SIZE = %d\n", GATWICK_IRQ_POOL_SIZE);
+ printk(" requested = %d\n", count);
+ }
+}
+
+/*
+ * The PowerBook 3400/2400/3500 can have a combo ethernet/modem
+ * card which includes an ohare chip that acts as a second interrupt
+ * controller. If we find this second ohare, set it up and fix the
+ * interrupt value in the device tree for the ethernet chip.
+ */
+static int __init enable_second_ohare(void)
+{
+ unsigned char bus, devfn;
+ unsigned short cmd;
+ unsigned long addr;
+ struct device_node *irqctrler = find_devices("pci106b,7");
+ struct device_node *ether;
+
+ if (irqctrler == NULL || irqctrler->n_addrs <= 0)
+ return -1;
+ addr = (unsigned long) ioremap(irqctrler->addrs[0].address, 0x40);
+ pmac_irq_hw[1] = (volatile struct pmac_irq_hw *)(addr + 0x20);
+ max_irqs = 64;
+ if (pci_device_from_OF_node(irqctrler, &bus, &devfn) == 0) {
+ struct pci_controller* hose = pci_find_hose_for_OF_device(irqctrler);
+ if (!hose)
+ printk(KERN_ERR "Can't find PCI hose for OHare2 !\n");
+ else {
+ early_read_config_word(hose, bus, devfn, PCI_COMMAND, &cmd);
+ cmd |= PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER;
+ cmd &= ~PCI_COMMAND_IO;
+ early_write_config_word(hose, bus, devfn, PCI_COMMAND, cmd);
+ }
+ }
+
+ /* Fix interrupt for the modem/ethernet combo controller. The number
+ in the device tree (27) is bogus (correct for the ethernet-only
+ board but not the combo ethernet/modem board).
+ The real interrupt is 28 on the second controller -> 28+32 = 60.
+ */
+ ether = find_devices("pci1011,14");
+ if (ether && ether->n_intrs > 0) {
+ ether->intrs[0].line = 60;
+ printk(KERN_INFO "irq: Fixed ethernet IRQ to %d\n",
+ ether->intrs[0].line);
+ }
+
+ /* Return the interrupt number of the cascade */
+ return irqctrler->intrs[0].line;
+}
+
+#ifdef CONFIG_POWER4
+static irqreturn_t k2u3_action(int cpl, void *dev_id, struct pt_regs *regs)
+{
+ int irq;
+
+ irq = openpic2_get_irq(regs);
+ if (irq != -1)
+ __do_IRQ(irq, regs);
+ return IRQ_HANDLED;
+}
+
+static struct irqaction k2u3_cascade_action = {
+ .handler = k2u3_action,
+ .flags = 0,
+ .mask = CPU_MASK_NONE,
+ .name = "U3->K2 Cascade",
+};
+#endif /* CONFIG_POWER4 */
+
+#ifdef CONFIG_XMON
+static struct irqaction xmon_action = {
+ .handler = xmon_irq,
+ .flags = 0,
+ .mask = CPU_MASK_NONE,
+ .name = "NMI - XMON"
+};
+#endif
+
+static struct irqaction gatwick_cascade_action = {
+ .handler = gatwick_action,
+ .flags = SA_INTERRUPT,
+ .mask = CPU_MASK_NONE,
+ .name = "cascade",
+};
+
+void __init pmac_pic_init(void)
+{
+ int i;
+ struct device_node *irqctrler = NULL;
+ struct device_node *irqctrler2 = NULL;
+ struct device_node *np;
+ unsigned long addr;
+ int irq_cascade = -1;
+
+ /* We first try to detect Apple's new Core99 chipset, since mac-io
+ * is quite different on those machines and contains an IBM MPIC2.
+ */
+ np = find_type_devices("open-pic");
+ while(np) {
+ if (np->parent && !strcmp(np->parent->name, "u3"))
+ irqctrler2 = np;
+ else
+ irqctrler = np;
+ np = np->next;
+ }
+ if (irqctrler != NULL)
+ {
+ if (irqctrler->n_addrs > 0)
+ {
+ unsigned char senses[128];
+
+ printk(KERN_INFO "PowerMac using OpenPIC irq controller at 0x%08x\n",
+ irqctrler->addrs[0].address);
+
+ prom_get_irq_senses(senses, 0, 128);
+ OpenPIC_InitSenses = senses;
+ OpenPIC_NumInitSenses = 128;
+ ppc_md.get_irq = openpic_get_irq;
+ pmac_call_feature(PMAC_FTR_ENABLE_MPIC, irqctrler, 0, 0);
+ OpenPIC_Addr = ioremap(irqctrler->addrs[0].address,
+ irqctrler->addrs[0].size);
+ openpic_init(0);
+
+#ifdef CONFIG_POWER4
+ if (irqctrler2 != NULL && irqctrler2->n_intrs > 0 &&
+ irqctrler2->n_addrs > 0) {
+ printk(KERN_INFO "Slave OpenPIC at 0x%08x hooked on IRQ %d\n",
+ irqctrler2->addrs[0].address,
+ irqctrler2->intrs[0].line);
+ pmac_call_feature(PMAC_FTR_ENABLE_MPIC, irqctrler2, 0, 0);
+ OpenPIC2_Addr = ioremap(irqctrler2->addrs[0].address,
+ irqctrler2->addrs[0].size);
+ prom_get_irq_senses(senses, PMAC_OPENPIC2_OFFSET,
+ PMAC_OPENPIC2_OFFSET+128);
+ OpenPIC_InitSenses = senses;
+ OpenPIC_NumInitSenses = 128;
+ openpic2_init(PMAC_OPENPIC2_OFFSET);
+
+ if (setup_irq(irqctrler2->intrs[0].line,
+ &k2u3_cascade_action))
+ printk("Unable to get OpenPIC IRQ for cascade\n");
+ }
+#endif /* CONFIG_POWER4 */
+
+#ifdef CONFIG_XMON
+ {
+ struct device_node* pswitch;
+ int nmi_irq;
+
+ pswitch = find_devices("programmer-switch");
+ if (pswitch && pswitch->n_intrs) {
+ nmi_irq = pswitch->intrs[0].line;
+ openpic_init_nmi_irq(nmi_irq);
+ setup_irq(nmi_irq, &xmon_action);
+ }
+ }
+#endif /* CONFIG_XMON */
+ return;
+ }
+ irqctrler = NULL;
+ }
+
+ /* Get the level/edge settings, assume if it's not
+ * a Grand Central nor an OHare, then it's an Heathrow
+ * (or Paddington).
+ */
+ if (find_devices("gc"))
+ level_mask[0] = GC_LEVEL_MASK;
+ else if (find_devices("ohare")) {
+ level_mask[0] = OHARE_LEVEL_MASK;
+ /* We might have a second cascaded ohare */
+ level_mask[1] = OHARE_LEVEL_MASK;
+ } else {
+ level_mask[0] = HEATHROW_LEVEL_MASK;
+ level_mask[1] = 0;
+ /* We might have a second cascaded heathrow */
+ level_mask[2] = HEATHROW_LEVEL_MASK;
+ level_mask[3] = 0;
+ }
+
+ /*
+ * G3 powermacs and 1999 G3 PowerBooks have 64 interrupts,
+ * 1998 G3 Series PowerBooks have 128,
+ * other powermacs have 32.
+ * The combo ethernet/modem card for the Powerstar powerbooks
+ * (2400/3400/3500, ohare based) has a second ohare chip
+ * effectively making a total of 64.
+ */
+ max_irqs = max_real_irqs = 32;
+ irqctrler = find_devices("mac-io");
+ if (irqctrler)
+ {
+ max_real_irqs = 64;
+ if (irqctrler->next)
+ max_irqs = 128;
+ else
+ max_irqs = 64;
+ }
+ for ( i = 0; i < max_real_irqs ; i++ )
+ irq_desc[i].handler = &pmac_pic;
+
+ /* get addresses of first controller */
+ if (irqctrler) {
+ if (irqctrler->n_addrs > 0) {
+ addr = (unsigned long)
+ ioremap(irqctrler->addrs[0].address, 0x40);
+ for (i = 0; i < 2; ++i)
+ pmac_irq_hw[i] = (volatile struct pmac_irq_hw*)
+ (addr + (2 - i) * 0x10);
+ }
+
+ /* get addresses of second controller */
+ irqctrler = irqctrler->next;
+ if (irqctrler && irqctrler->n_addrs > 0) {
+ addr = (unsigned long)
+ ioremap(irqctrler->addrs[0].address, 0x40);
+ for (i = 2; i < 4; ++i)
+ pmac_irq_hw[i] = (volatile struct pmac_irq_hw*)
+ (addr + (4 - i) * 0x10);
+ irq_cascade = irqctrler->intrs[0].line;
+ if (device_is_compatible(irqctrler, "gatwick"))
+ pmac_fix_gatwick_interrupts(irqctrler, max_real_irqs);
+ }
+ } else {
+ /* older powermacs have a GC (grand central) or ohare at
+ f3000000, with interrupt control registers at f3000020. */
+ addr = (unsigned long) ioremap(0xf3000000, 0x40);
+ pmac_irq_hw[0] = (volatile struct pmac_irq_hw *) (addr + 0x20);
+ }
+
+ /* PowerBooks 3400 and 3500 can have a second controller in a second
+ ohare chip, on the combo ethernet/modem card */
+ if (machine_is_compatible("AAPL,3400/2400")
+ || machine_is_compatible("AAPL,3500"))
+ irq_cascade = enable_second_ohare();
+
+ /* disable all interrupts in all controllers */
+ for (i = 0; i * 32 < max_irqs; ++i)
+ out_le32(&pmac_irq_hw[i]->enable, 0);
+ /* mark level interrupts */
+ for (i = 0; i < max_irqs; i++)
+ if (level_mask[i >> 5] & (1UL << (i & 0x1f)))
+ irq_desc[i].status = IRQ_LEVEL;
+
+ /* get interrupt line of secondary interrupt controller */
+ if (irq_cascade >= 0) {
+ printk(KERN_INFO "irq: secondary controller on irq %d\n",
+ (int)irq_cascade);
+ for ( i = max_real_irqs ; i < max_irqs ; i++ )
+ irq_desc[i].handler = &gatwick_pic;
+ setup_irq(irq_cascade, &gatwick_cascade_action);
+ }
+ printk("System has %d possible interrupts\n", max_irqs);
+ if (max_irqs != max_real_irqs)
+ printk(KERN_DEBUG "%d interrupts on main controller\n",
+ max_real_irqs);
+
+#ifdef CONFIG_XMON
+ setup_irq(20, &xmon_action);
+#endif /* CONFIG_XMON */
+}
+
+#ifdef CONFIG_PM
+/*
+ * These procedures are used in implementing sleep on the powerbooks.
+ * sleep_save_intrs() saves the states of all interrupt enables
+ * and disables all interrupts except for the nominated one.
+ * sleep_restore_intrs() restores the states of all interrupt enables.
+ */
+unsigned long sleep_save_mask[2];
+
+/* This used to be passed by the PMU driver but that link got
+ * broken with the new driver model. We use this tweak for now...
+ */
+static int pmacpic_find_viaint(void)
+{
+ int viaint = -1;
+
+#ifdef CONFIG_ADB_PMU
+ struct device_node *np;
+
+ if (pmu_get_model() != PMU_OHARE_BASED)
+ goto not_found;
+ np = of_find_node_by_name(NULL, "via-pmu");
+ if (np == NULL)
+ goto not_found;
+ viaint = np->intrs[0].line;
+#endif /* CONFIG_ADB_PMU */
+
+not_found:
+ return viaint;
+}
+
+static int pmacpic_suspend(struct sys_device *sysdev, u32 state)
+{
+ int viaint = pmacpic_find_viaint();
+
+ sleep_save_mask[0] = ppc_cached_irq_mask[0];
+ sleep_save_mask[1] = ppc_cached_irq_mask[1];
+ ppc_cached_irq_mask[0] = 0;
+ ppc_cached_irq_mask[1] = 0;
+ if (viaint > 0)
+ set_bit(viaint, ppc_cached_irq_mask);
+ out_le32(&pmac_irq_hw[0]->enable, ppc_cached_irq_mask[0]);
+ if (max_real_irqs > 32)
+ out_le32(&pmac_irq_hw[1]->enable, ppc_cached_irq_mask[1]);
+ (void)in_le32(&pmac_irq_hw[0]->event);
+ /* make sure mask gets to controller before we return to caller */
+ mb();
+ (void)in_le32(&pmac_irq_hw[0]->enable);
+
+ return 0;
+}
+
+static int pmacpic_resume(struct sys_device *sysdev)
+{
+ int i;
+
+ out_le32(&pmac_irq_hw[0]->enable, 0);
+ if (max_real_irqs > 32)
+ out_le32(&pmac_irq_hw[1]->enable, 0);
+ mb();
+ for (i = 0; i < max_real_irqs; ++i)
+ if (test_bit(i, sleep_save_mask))
+ pmac_unmask_irq(i);
+
+ return 0;
+}
+
+#endif /* CONFIG_PM */
+
+static struct sysdev_class pmacpic_sysclass = {
+ set_kset_name("pmac_pic"),
+};
+
+static struct sys_device device_pmacpic = {
+ .id = 0,
+ .cls = &pmacpic_sysclass,
+};
+
+static struct sysdev_driver driver_pmacpic = {
+#ifdef CONFIG_PM
+ .suspend = &pmacpic_suspend,
+ .resume = &pmacpic_resume,
+#endif /* CONFIG_PM */
+};
+
+static int __init init_pmacpic_sysfs(void)
+{
+ if (max_irqs == 0)
+ return -ENODEV;
+
+ printk(KERN_DEBUG "Registering pmac pic with sysfs...\n");
+ sysdev_class_register(&pmacpic_sysclass);
+ sysdev_register(&device_pmacpic);
+ sysdev_driver_register(&pmacpic_sysclass, &driver_pmacpic);
+ return 0;
+}
+
+subsys_initcall(init_pmacpic_sysfs);
+
diff --git a/arch/ppc/platforms/pmac_pic.h b/arch/ppc/platforms/pmac_pic.h
new file mode 100644
index 0000000..664103d
--- /dev/null
+++ b/arch/ppc/platforms/pmac_pic.h
@@ -0,0 +1,11 @@
+#ifndef __PPC_PLATFORMS_PMAC_PIC_H
+#define __PPC_PLATFORMS_PMAC_PIC_H
+
+#include <linux/irq.h>
+
+extern struct hw_interrupt_type pmac_pic;
+
+void pmac_pic_init(void);
+int pmac_get_irq(struct pt_regs *regs);
+
+#endif /* __PPC_PLATFORMS_PMAC_PIC_H */
diff --git a/arch/ppc/platforms/pmac_setup.c b/arch/ppc/platforms/pmac_setup.c
new file mode 100644
index 0000000..4d324b6
--- /dev/null
+++ b/arch/ppc/platforms/pmac_setup.c
@@ -0,0 +1,745 @@
+/*
+ * arch/ppc/platforms/setup.c
+ *
+ * PowerPC version
+ * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
+ *
+ * Adapted for Power Macintosh by Paul Mackerras
+ * Copyright (C) 1996 Paul Mackerras (paulus@cs.anu.edu.au)
+ *
+ * Derived from "arch/alpha/kernel/setup.c"
+ * Copyright (C) 1995 Linus Torvalds
+ *
+ * Maintained by Benjamin Herrenschmidt (benh@kernel.crashing.org)
+ *
+ * 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.
+ *
+ */
+
+/*
+ * bootup setup stuff..
+ */
+
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/stddef.h>
+#include <linux/unistd.h>
+#include <linux/ptrace.h>
+#include <linux/slab.h>
+#include <linux/user.h>
+#include <linux/a.out.h>
+#include <linux/tty.h>
+#include <linux/string.h>
+#include <linux/delay.h>
+#include <linux/ioport.h>
+#include <linux/major.h>
+#include <linux/initrd.h>
+#include <linux/vt_kern.h>
+#include <linux/console.h>
+#include <linux/ide.h>
+#include <linux/pci.h>
+#include <linux/adb.h>
+#include <linux/cuda.h>
+#include <linux/pmu.h>
+#include <linux/irq.h>
+#include <linux/seq_file.h>
+#include <linux/root_dev.h>
+#include <linux/bitops.h>
+#include <linux/suspend.h>
+
+#include <asm/reg.h>
+#include <asm/sections.h>
+#include <asm/prom.h>
+#include <asm/system.h>
+#include <asm/pgtable.h>
+#include <asm/io.h>
+#include <asm/pci-bridge.h>
+#include <asm/ohare.h>
+#include <asm/mediabay.h>
+#include <asm/machdep.h>
+#include <asm/dma.h>
+#include <asm/bootx.h>
+#include <asm/cputable.h>
+#include <asm/btext.h>
+#include <asm/pmac_feature.h>
+#include <asm/time.h>
+#include <asm/of_device.h>
+#include <asm/mmu_context.h>
+
+#include "pmac_pic.h"
+#include "mem_pieces.h"
+
+#undef SHOW_GATWICK_IRQS
+
+extern long pmac_time_init(void);
+extern unsigned long pmac_get_rtc_time(void);
+extern int pmac_set_rtc_time(unsigned long nowtime);
+extern void pmac_read_rtc_time(void);
+extern void pmac_calibrate_decr(void);
+extern void pmac_pcibios_fixup(void);
+extern void pmac_find_bridges(void);
+extern unsigned long pmac_ide_get_base(int index);
+extern void pmac_ide_init_hwif_ports(hw_regs_t *hw,
+ unsigned long data_port, unsigned long ctrl_port, int *irq);
+
+extern void pmac_nvram_update(void);
+extern unsigned char pmac_nvram_read_byte(int addr);
+extern void pmac_nvram_write_byte(int addr, unsigned char val);
+extern int pmac_pci_enable_device_hook(struct pci_dev *dev, int initial);
+extern void pmac_pcibios_after_init(void);
+extern int of_show_percpuinfo(struct seq_file *m, int i);
+
+struct device_node *memory_node;
+
+unsigned char drive_info;
+
+int ppc_override_l2cr = 0;
+int ppc_override_l2cr_value;
+int has_l2cache = 0;
+
+static int current_root_goodness = -1;
+
+extern int pmac_newworld;
+
+#define DEFAULT_ROOT_DEVICE Root_SDA1 /* sda1 - slightly silly choice */
+
+extern void zs_kgdb_hook(int tty_num);
+static void ohare_init(void);
+#ifdef CONFIG_BOOTX_TEXT
+void pmac_progress(char *s, unsigned short hex);
+#endif
+
+sys_ctrler_t sys_ctrler = SYS_CTRLER_UNKNOWN;
+
+#ifdef CONFIG_SMP
+extern struct smp_ops_t psurge_smp_ops;
+extern struct smp_ops_t core99_smp_ops;
+#endif /* CONFIG_SMP */
+
+int __pmac
+pmac_show_cpuinfo(struct seq_file *m)
+{
+ struct device_node *np;
+ char *pp;
+ int plen;
+ int mbmodel = pmac_call_feature(PMAC_FTR_GET_MB_INFO,
+ NULL, PMAC_MB_INFO_MODEL, 0);
+ unsigned int mbflags = (unsigned int)pmac_call_feature(PMAC_FTR_GET_MB_INFO,
+ NULL, PMAC_MB_INFO_FLAGS, 0);
+ char* mbname;
+
+ if (pmac_call_feature(PMAC_FTR_GET_MB_INFO, NULL, PMAC_MB_INFO_NAME, (int)&mbname) != 0)
+ mbname = "Unknown";
+
+ /* find motherboard type */
+ seq_printf(m, "machine\t\t: ");
+ np = find_devices("device-tree");
+ if (np != NULL) {
+ pp = (char *) get_property(np, "model", NULL);
+ if (pp != NULL)
+ seq_printf(m, "%s\n", pp);
+ else
+ seq_printf(m, "PowerMac\n");
+ pp = (char *) get_property(np, "compatible", &plen);
+ if (pp != NULL) {
+ seq_printf(m, "motherboard\t:");
+ while (plen > 0) {
+ int l = strlen(pp) + 1;
+ seq_printf(m, " %s", pp);
+ plen -= l;
+ pp += l;
+ }
+ seq_printf(m, "\n");
+ }
+ } else
+ seq_printf(m, "PowerMac\n");
+
+ /* print parsed model */
+ seq_printf(m, "detected as\t: %d (%s)\n", mbmodel, mbname);
+ seq_printf(m, "pmac flags\t: %08x\n", mbflags);
+
+ /* find l2 cache info */
+ np = find_devices("l2-cache");
+ if (np == 0)
+ np = find_type_devices("cache");
+ if (np != 0) {
+ unsigned int *ic = (unsigned int *)
+ get_property(np, "i-cache-size", NULL);
+ unsigned int *dc = (unsigned int *)
+ get_property(np, "d-cache-size", NULL);
+ seq_printf(m, "L2 cache\t:");
+ has_l2cache = 1;
+ if (get_property(np, "cache-unified", NULL) != 0 && dc) {
+ seq_printf(m, " %dK unified", *dc / 1024);
+ } else {
+ if (ic)
+ seq_printf(m, " %dK instruction", *ic / 1024);
+ if (dc)
+ seq_printf(m, "%s %dK data",
+ (ic? " +": ""), *dc / 1024);
+ }
+ pp = get_property(np, "ram-type", NULL);
+ if (pp)
+ seq_printf(m, " %s", pp);
+ seq_printf(m, "\n");
+ }
+
+ /* find ram info */
+ np = find_devices("memory");
+ if (np != 0) {
+ int n;
+ struct reg_property *reg = (struct reg_property *)
+ get_property(np, "reg", &n);
+
+ if (reg != 0) {
+ unsigned long total = 0;
+
+ for (n /= sizeof(struct reg_property); n > 0; --n)
+ total += (reg++)->size;
+ seq_printf(m, "memory\t\t: %luMB\n", total >> 20);
+ }
+ }
+
+ /* Checks "l2cr-value" property in the registry */
+ np = find_devices("cpus");
+ if (np == 0)
+ np = find_type_devices("cpu");
+ if (np != 0) {
+ unsigned int *l2cr = (unsigned int *)
+ get_property(np, "l2cr-value", NULL);
+ if (l2cr != 0) {
+ seq_printf(m, "l2cr override\t: 0x%x\n", *l2cr);
+ }
+ }
+
+ /* Indicate newworld/oldworld */
+ seq_printf(m, "pmac-generation\t: %s\n",
+ pmac_newworld ? "NewWorld" : "OldWorld");
+
+
+ return 0;
+}
+
+int __openfirmware
+pmac_show_percpuinfo(struct seq_file *m, int i)
+{
+#ifdef CONFIG_CPU_FREQ_PMAC
+ extern unsigned int pmac_get_one_cpufreq(int i);
+ unsigned int freq = pmac_get_one_cpufreq(i);
+ if (freq != 0) {
+ seq_printf(m, "clock\t\t: %dMHz\n", freq/1000);
+ return 0;
+ }
+#endif /* CONFIG_CPU_FREQ_PMAC */
+ return of_show_percpuinfo(m, i);
+}
+
+static volatile u32 *sysctrl_regs;
+
+void __init
+pmac_setup_arch(void)
+{
+ struct device_node *cpu;
+ int *fp;
+ unsigned long pvr;
+
+ pvr = PVR_VER(mfspr(SPRN_PVR));
+
+ /* Set loops_per_jiffy to a half-way reasonable value,
+ for use until calibrate_delay gets called. */
+ cpu = find_type_devices("cpu");
+ if (cpu != 0) {
+ fp = (int *) get_property(cpu, "clock-frequency", NULL);
+ if (fp != 0) {
+ if (pvr == 4 || pvr >= 8)
+ /* 604, G3, G4 etc. */
+ loops_per_jiffy = *fp / HZ;
+ else
+ /* 601, 603, etc. */
+ loops_per_jiffy = *fp / (2*HZ);
+ } else
+ loops_per_jiffy = 50000000 / HZ;
+ }
+
+ /* this area has the CPU identification register
+ and some registers used by smp boards */
+ sysctrl_regs = (volatile u32 *) ioremap(0xf8000000, 0x1000);
+ ohare_init();
+
+ /* Lookup PCI hosts */
+ pmac_find_bridges();
+
+ /* Checks "l2cr-value" property in the registry */
+ if (cpu_has_feature(CPU_FTR_L2CR)) {
+ struct device_node *np = find_devices("cpus");
+ if (np == 0)
+ np = find_type_devices("cpu");
+ if (np != 0) {
+ unsigned int *l2cr = (unsigned int *)
+ get_property(np, "l2cr-value", NULL);
+ if (l2cr != 0) {
+ ppc_override_l2cr = 1;
+ ppc_override_l2cr_value = *l2cr;
+ _set_L2CR(0);
+ _set_L2CR(ppc_override_l2cr_value);
+ }
+ }
+ }
+
+ if (ppc_override_l2cr)
+ printk(KERN_INFO "L2CR overriden (0x%x), backside cache is %s\n",
+ ppc_override_l2cr_value, (ppc_override_l2cr_value & 0x80000000)
+ ? "enabled" : "disabled");
+
+#ifdef CONFIG_KGDB
+ zs_kgdb_hook(0);
+#endif
+
+#ifdef CONFIG_ADB_CUDA
+ find_via_cuda();
+#else
+ if (find_devices("via-cuda")) {
+ printk("WARNING ! Your machine is Cuda based but your kernel\n");
+ printk(" wasn't compiled with CONFIG_ADB_CUDA option !\n");
+ }
+#endif
+#ifdef CONFIG_ADB_PMU
+ find_via_pmu();
+#else
+ if (find_devices("via-pmu")) {
+ printk("WARNING ! Your machine is PMU based but your kernel\n");
+ printk(" wasn't compiled with CONFIG_ADB_PMU option !\n");
+ }
+#endif
+#ifdef CONFIG_NVRAM
+ pmac_nvram_init();
+#endif
+#ifdef CONFIG_BLK_DEV_INITRD
+ if (initrd_start)
+ ROOT_DEV = Root_RAM0;
+ else
+#endif
+ ROOT_DEV = DEFAULT_ROOT_DEVICE;
+
+#ifdef CONFIG_SMP
+ /* Check for Core99 */
+ if (find_devices("uni-n") || find_devices("u3"))
+ ppc_md.smp_ops = &core99_smp_ops;
+ else
+ ppc_md.smp_ops = &psurge_smp_ops;
+#endif /* CONFIG_SMP */
+
+ pci_create_OF_bus_map();
+}
+
+static void __init ohare_init(void)
+{
+ /*
+ * Turn on the L2 cache.
+ * We assume that we have a PSX memory controller iff
+ * we have an ohare I/O controller.
+ */
+ if (find_devices("ohare") != NULL) {
+ if (((sysctrl_regs[2] >> 24) & 0xf) >= 3) {
+ if (sysctrl_regs[4] & 0x10)
+ sysctrl_regs[4] |= 0x04000020;
+ else
+ sysctrl_regs[4] |= 0x04000000;
+ if(has_l2cache)
+ printk(KERN_INFO "Level 2 cache enabled\n");
+ }
+ }
+}
+
+extern char *bootpath;
+extern char *bootdevice;
+void *boot_host;
+int boot_target;
+int boot_part;
+extern dev_t boot_dev;
+
+#ifdef CONFIG_SCSI
+void __init
+note_scsi_host(struct device_node *node, void *host)
+{
+ int l;
+ char *p;
+
+ l = strlen(node->full_name);
+ if (bootpath != NULL && bootdevice != NULL
+ && strncmp(node->full_name, bootdevice, l) == 0
+ && (bootdevice[l] == '/' || bootdevice[l] == 0)) {
+ boot_host = host;
+ /*
+ * There's a bug in OF 1.0.5. (Why am I not surprised.)
+ * If you pass a path like scsi/sd@1:0 to canon, it returns
+ * something like /bandit@F2000000/gc@10/53c94@10000/sd@0,0
+ * That is, the scsi target number doesn't get preserved.
+ * So we pick the target number out of bootpath and use that.
+ */
+ p = strstr(bootpath, "/sd@");
+ if (p != NULL) {
+ p += 4;
+ boot_target = simple_strtoul(p, NULL, 10);
+ p = strchr(p, ':');
+ if (p != NULL)
+ boot_part = simple_strtoul(p + 1, NULL, 10);
+ }
+ }
+}
+#endif
+
+#if defined(CONFIG_BLK_DEV_IDE) && defined(CONFIG_BLK_DEV_IDE_PMAC)
+static dev_t __init
+find_ide_boot(void)
+{
+ char *p;
+ int n;
+ dev_t __init pmac_find_ide_boot(char *bootdevice, int n);
+
+ if (bootdevice == NULL)
+ return 0;
+ p = strrchr(bootdevice, '/');
+ if (p == NULL)
+ return 0;
+ n = p - bootdevice;
+
+ return pmac_find_ide_boot(bootdevice, n);
+}
+#endif /* CONFIG_BLK_DEV_IDE && CONFIG_BLK_DEV_IDE_PMAC */
+
+void __init
+find_boot_device(void)
+{
+#if defined(CONFIG_BLK_DEV_IDE) && defined(CONFIG_BLK_DEV_IDE_PMAC)
+ boot_dev = find_ide_boot();
+#endif
+}
+
+static int initializing = 1;
+/* TODO: Merge the suspend-to-ram with the common code !!!
+ * currently, this is a stub implementation for suspend-to-disk
+ * only
+ */
+
+#ifdef CONFIG_SOFTWARE_SUSPEND
+
+static int pmac_pm_prepare(suspend_state_t state)
+{
+ printk(KERN_DEBUG "%s(%d)\n", __FUNCTION__, state);
+
+ return 0;
+}
+
+static int pmac_pm_enter(suspend_state_t state)
+{
+ printk(KERN_DEBUG "%s(%d)\n", __FUNCTION__, state);
+
+ /* Giveup the lazy FPU & vec so we don't have to back them
+ * up from the low level code
+ */
+ enable_kernel_fp();
+
+#ifdef CONFIG_ALTIVEC
+ if (cur_cpu_spec[0]->cpu_features & CPU_FTR_ALTIVEC)
+ enable_kernel_altivec();
+#endif /* CONFIG_ALTIVEC */
+
+ return 0;
+}
+
+static int pmac_pm_finish(suspend_state_t state)
+{
+ printk(KERN_DEBUG "%s(%d)\n", __FUNCTION__, state);
+
+ /* Restore userland MMU context */
+ set_context(current->active_mm->context, current->active_mm->pgd);
+
+ return 0;
+}
+
+static struct pm_ops pmac_pm_ops = {
+ .pm_disk_mode = PM_DISK_SHUTDOWN,
+ .prepare = pmac_pm_prepare,
+ .enter = pmac_pm_enter,
+ .finish = pmac_pm_finish,
+};
+
+#endif /* CONFIG_SOFTWARE_SUSPEND */
+
+static int pmac_late_init(void)
+{
+ initializing = 0;
+#ifdef CONFIG_SOFTWARE_SUSPEND
+ pm_set_ops(&pmac_pm_ops);
+#endif /* CONFIG_SOFTWARE_SUSPEND */
+ return 0;
+}
+
+late_initcall(pmac_late_init);
+
+/* can't be __init - can be called whenever a disk is first accessed */
+void __pmac
+note_bootable_part(dev_t dev, int part, int goodness)
+{
+ static int found_boot = 0;
+ char *p;
+
+ if (!initializing)
+ return;
+ if ((goodness <= current_root_goodness) &&
+ ROOT_DEV != DEFAULT_ROOT_DEVICE)
+ return;
+ p = strstr(saved_command_line, "root=");
+ if (p != NULL && (p == saved_command_line || p[-1] == ' '))
+ return;
+
+ if (!found_boot) {
+ find_boot_device();
+ found_boot = 1;
+ }
+ if (!boot_dev || dev == boot_dev) {
+ ROOT_DEV = dev + part;
+ boot_dev = 0;
+ current_root_goodness = goodness;
+ }
+}
+
+void __pmac
+pmac_restart(char *cmd)
+{
+#ifdef CONFIG_ADB_CUDA
+ struct adb_request req;
+#endif /* CONFIG_ADB_CUDA */
+
+ switch (sys_ctrler) {
+#ifdef CONFIG_ADB_CUDA
+ case SYS_CTRLER_CUDA:
+ cuda_request(&req, NULL, 2, CUDA_PACKET,
+ CUDA_RESET_SYSTEM);
+ for (;;)
+ cuda_poll();
+ break;
+#endif /* CONFIG_ADB_CUDA */
+#ifdef CONFIG_ADB_PMU
+ case SYS_CTRLER_PMU:
+ pmu_restart();
+ break;
+#endif /* CONFIG_ADB_PMU */
+ default: ;
+ }
+}
+
+void __pmac
+pmac_power_off(void)
+{
+#ifdef CONFIG_ADB_CUDA
+ struct adb_request req;
+#endif /* CONFIG_ADB_CUDA */
+
+ switch (sys_ctrler) {
+#ifdef CONFIG_ADB_CUDA
+ case SYS_CTRLER_CUDA:
+ cuda_request(&req, NULL, 2, CUDA_PACKET,
+ CUDA_POWERDOWN);
+ for (;;)
+ cuda_poll();
+ break;
+#endif /* CONFIG_ADB_CUDA */
+#ifdef CONFIG_ADB_PMU
+ case SYS_CTRLER_PMU:
+ pmu_shutdown();
+ break;
+#endif /* CONFIG_ADB_PMU */
+ default: ;
+ }
+}
+
+void __pmac
+pmac_halt(void)
+{
+ pmac_power_off();
+}
+
+/*
+ * Read in a property describing some pieces of memory.
+ */
+
+static int __init
+get_mem_prop(char *name, struct mem_pieces *mp)
+{
+ struct reg_property *rp;
+ int i, s;
+ unsigned int *ip;
+ int nac = prom_n_addr_cells(memory_node);
+ int nsc = prom_n_size_cells(memory_node);
+
+ ip = (unsigned int *) get_property(memory_node, name, &s);
+ if (ip == NULL) {
+ printk(KERN_ERR "error: couldn't get %s property on /memory\n",
+ name);
+ return 0;
+ }
+ s /= (nsc + nac) * 4;
+ rp = mp->regions;
+ for (i = 0; i < s; ++i, ip += nac+nsc) {
+ if (nac >= 2 && ip[nac-2] != 0)
+ continue;
+ rp->address = ip[nac-1];
+ if (nsc >= 2 && ip[nac+nsc-2] != 0)
+ rp->size = ~0U;
+ else
+ rp->size = ip[nac+nsc-1];
+ ++rp;
+ }
+ mp->n_regions = rp - mp->regions;
+
+ /* Make sure the pieces are sorted. */
+ mem_pieces_sort(mp);
+ mem_pieces_coalesce(mp);
+ return 1;
+}
+
+/*
+ * On systems with Open Firmware, collect information about
+ * physical RAM and which pieces are already in use.
+ * At this point, we have (at least) the first 8MB mapped with a BAT.
+ * Our text, data, bss use something over 1MB, starting at 0.
+ * Open Firmware may be using 1MB at the 4MB point.
+ */
+unsigned long __init
+pmac_find_end_of_memory(void)
+{
+ unsigned long a, total;
+ struct mem_pieces phys_mem;
+
+ /*
+ * Find out where physical memory is, and check that it
+ * starts at 0 and is contiguous. It seems that RAM is
+ * always physically contiguous on Power Macintoshes.
+ *
+ * Supporting discontiguous physical memory isn't hard,
+ * it just makes the virtual <-> physical mapping functions
+ * more complicated (or else you end up wasting space
+ * in mem_map).
+ */
+ memory_node = find_devices("memory");
+ if (memory_node == NULL || !get_mem_prop("reg", &phys_mem)
+ || phys_mem.n_regions == 0)
+ panic("No RAM??");
+ a = phys_mem.regions[0].address;
+ if (a != 0)
+ panic("RAM doesn't start at physical address 0");
+ total = phys_mem.regions[0].size;
+
+ if (phys_mem.n_regions > 1) {
+ printk("RAM starting at 0x%x is not contiguous\n",
+ phys_mem.regions[1].address);
+ printk("Using RAM from 0 to 0x%lx\n", total-1);
+ }
+
+ return total;
+}
+
+void __init
+pmac_init(unsigned long r3, unsigned long r4, unsigned long r5,
+ unsigned long r6, unsigned long r7)
+{
+ /* isa_io_base gets set in pmac_find_bridges */
+ isa_mem_base = PMAC_ISA_MEM_BASE;
+ pci_dram_offset = PMAC_PCI_DRAM_OFFSET;
+ ISA_DMA_THRESHOLD = ~0L;
+ DMA_MODE_READ = 1;
+ DMA_MODE_WRITE = 2;
+
+ ppc_md.setup_arch = pmac_setup_arch;
+ ppc_md.show_cpuinfo = pmac_show_cpuinfo;
+ ppc_md.show_percpuinfo = pmac_show_percpuinfo;
+ ppc_md.irq_canonicalize = NULL;
+ ppc_md.init_IRQ = pmac_pic_init;
+ ppc_md.get_irq = pmac_get_irq; /* Changed later on ... */
+
+ ppc_md.pcibios_fixup = pmac_pcibios_fixup;
+ ppc_md.pcibios_enable_device_hook = pmac_pci_enable_device_hook;
+ ppc_md.pcibios_after_init = pmac_pcibios_after_init;
+ ppc_md.phys_mem_access_prot = pci_phys_mem_access_prot;
+
+ ppc_md.restart = pmac_restart;
+ ppc_md.power_off = pmac_power_off;
+ ppc_md.halt = pmac_halt;
+
+ ppc_md.time_init = pmac_time_init;
+ ppc_md.set_rtc_time = pmac_set_rtc_time;
+ ppc_md.get_rtc_time = pmac_get_rtc_time;
+ ppc_md.calibrate_decr = pmac_calibrate_decr;
+
+ ppc_md.find_end_of_memory = pmac_find_end_of_memory;
+
+ ppc_md.feature_call = pmac_do_feature_call;
+
+#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
+#ifdef CONFIG_BLK_DEV_IDE_PMAC
+ ppc_ide_md.ide_init_hwif = pmac_ide_init_hwif_ports;
+ ppc_ide_md.default_io_base = pmac_ide_get_base;
+#endif /* CONFIG_BLK_DEV_IDE_PMAC */
+#endif /* defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE) */
+
+#ifdef CONFIG_BOOTX_TEXT
+ ppc_md.progress = pmac_progress;
+#endif /* CONFIG_BOOTX_TEXT */
+
+ if (ppc_md.progress) ppc_md.progress("pmac_init(): exit", 0);
+
+}
+
+#ifdef CONFIG_BOOTX_TEXT
+void __init
+pmac_progress(char *s, unsigned short hex)
+{
+ if (boot_text_mapped) {
+ btext_drawstring(s);
+ btext_drawchar('\n');
+ }
+}
+#endif /* CONFIG_BOOTX_TEXT */
+
+static int __init
+pmac_declare_of_platform_devices(void)
+{
+ struct device_node *np;
+
+ np = find_devices("uni-n");
+ if (np) {
+ for (np = np->child; np != NULL; np = np->sibling)
+ if (strncmp(np->name, "i2c", 3) == 0) {
+ of_platform_device_create(np, "uni-n-i2c");
+ break;
+ }
+ }
+ np = find_devices("u3");
+ if (np) {
+ for (np = np->child; np != NULL; np = np->sibling)
+ if (strncmp(np->name, "i2c", 3) == 0) {
+ of_platform_device_create(np, "u3-i2c");
+ break;
+ }
+ }
+
+ np = find_devices("valkyrie");
+ if (np)
+ of_platform_device_create(np, "valkyrie");
+ np = find_devices("platinum");
+ if (np)
+ of_platform_device_create(np, "platinum");
+
+ return 0;
+}
+
+device_initcall(pmac_declare_of_platform_devices);
diff --git a/arch/ppc/platforms/pmac_sleep.S b/arch/ppc/platforms/pmac_sleep.S
new file mode 100644
index 0000000..3139b67
--- /dev/null
+++ b/arch/ppc/platforms/pmac_sleep.S
@@ -0,0 +1,390 @@
+/*
+ * This file contains sleep low-level functions for PowerBook G3.
+ * Copyright (C) 1999 Benjamin Herrenschmidt (benh@kernel.crashing.org)
+ * and Paul Mackerras (paulus@samba.org).
+ *
+ * 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.
+ *
+ */
+
+#include <linux/config.h>
+#include <asm/processor.h>
+#include <asm/page.h>
+#include <asm/ppc_asm.h>
+#include <asm/cputable.h>
+#include <asm/cache.h>
+#include <asm/thread_info.h>
+#include <asm/offsets.h>
+
+#define MAGIC 0x4c617273 /* 'Lars' */
+
+/*
+ * Structure for storing CPU registers on the stack.
+ */
+#define SL_SP 0
+#define SL_PC 4
+#define SL_MSR 8
+#define SL_SDR1 0xc
+#define SL_SPRG0 0x10 /* 4 sprg's */
+#define SL_DBAT0 0x20
+#define SL_IBAT0 0x28
+#define SL_DBAT1 0x30
+#define SL_IBAT1 0x38
+#define SL_DBAT2 0x40
+#define SL_IBAT2 0x48
+#define SL_DBAT3 0x50
+#define SL_IBAT3 0x58
+#define SL_TB 0x60
+#define SL_R2 0x68
+#define SL_CR 0x6c
+#define SL_R12 0x70 /* r12 to r31 */
+#define SL_SIZE (SL_R12 + 80)
+
+ .section .text
+ .align 5
+
+#if defined(CONFIG_PMAC_PBOOK) || defined(CONFIG_CPU_FREQ_PMAC)
+
+/* This gets called by via-pmu.c late during the sleep process.
+ * The PMU was already send the sleep command and will shut us down
+ * soon. We need to save all that is needed and setup the wakeup
+ * vector that will be called by the ROM on wakeup
+ */
+_GLOBAL(low_sleep_handler)
+#ifndef CONFIG_6xx
+ blr
+#else
+ mflr r0
+ stw r0,4(r1)
+ stwu r1,-SL_SIZE(r1)
+ mfcr r0
+ stw r0,SL_CR(r1)
+ stw r2,SL_R2(r1)
+ stmw r12,SL_R12(r1)
+
+ /* Save MSR & SDR1 */
+ mfmsr r4
+ stw r4,SL_MSR(r1)
+ mfsdr1 r4
+ stw r4,SL_SDR1(r1)
+
+ /* Get a stable timebase and save it */
+1: mftbu r4
+ stw r4,SL_TB(r1)
+ mftb r5
+ stw r5,SL_TB+4(r1)
+ mftbu r3
+ cmpw r3,r4
+ bne 1b
+
+ /* Save SPRGs */
+ mfsprg r4,0
+ stw r4,SL_SPRG0(r1)
+ mfsprg r4,1
+ stw r4,SL_SPRG0+4(r1)
+ mfsprg r4,2
+ stw r4,SL_SPRG0+8(r1)
+ mfsprg r4,3
+ stw r4,SL_SPRG0+12(r1)
+
+ /* Save BATs */
+ mfdbatu r4,0
+ stw r4,SL_DBAT0(r1)
+ mfdbatl r4,0
+ stw r4,SL_DBAT0+4(r1)
+ mfdbatu r4,1
+ stw r4,SL_DBAT1(r1)
+ mfdbatl r4,1
+ stw r4,SL_DBAT1+4(r1)
+ mfdbatu r4,2
+ stw r4,SL_DBAT2(r1)
+ mfdbatl r4,2
+ stw r4,SL_DBAT2+4(r1)
+ mfdbatu r4,3
+ stw r4,SL_DBAT3(r1)
+ mfdbatl r4,3
+ stw r4,SL_DBAT3+4(r1)
+ mfibatu r4,0
+ stw r4,SL_IBAT0(r1)
+ mfibatl r4,0
+ stw r4,SL_IBAT0+4(r1)
+ mfibatu r4,1
+ stw r4,SL_IBAT1(r1)
+ mfibatl r4,1
+ stw r4,SL_IBAT1+4(r1)
+ mfibatu r4,2
+ stw r4,SL_IBAT2(r1)
+ mfibatl r4,2
+ stw r4,SL_IBAT2+4(r1)
+ mfibatu r4,3
+ stw r4,SL_IBAT3(r1)
+ mfibatl r4,3
+ stw r4,SL_IBAT3+4(r1)
+
+ /* Backup various CPU config stuffs */
+ bl __save_cpu_setup
+
+ /* The ROM can wake us up via 2 different vectors:
+ * - On wallstreet & lombard, we must write a magic
+ * value 'Lars' at address 4 and a pointer to a
+ * memory location containing the PC to resume from
+ * at address 0.
+ * - On Core99, we must store the wakeup vector at
+ * address 0x80 and eventually it's parameters
+ * at address 0x84. I've have some trouble with those
+ * parameters however and I no longer use them.
+ */
+ lis r5,grackle_wake_up@ha
+ addi r5,r5,grackle_wake_up@l
+ tophys(r5,r5)
+ stw r5,SL_PC(r1)
+ lis r4,KERNELBASE@h
+ tophys(r5,r1)
+ addi r5,r5,SL_PC
+ lis r6,MAGIC@ha
+ addi r6,r6,MAGIC@l
+ stw r5,0(r4)
+ stw r6,4(r4)
+ /* Setup stuffs at 0x80-0x84 for Core99 */
+ lis r3,core99_wake_up@ha
+ addi r3,r3,core99_wake_up@l
+ tophys(r3,r3)
+ stw r3,0x80(r4)
+ stw r5,0x84(r4)
+ /* Store a pointer to our backup storage into
+ * a kernel global
+ */
+ lis r3,sleep_storage@ha
+ addi r3,r3,sleep_storage@l
+ stw r5,0(r3)
+
+ /* Flush & disable all caches */
+ bl flush_disable_caches
+
+ /* Turn off data relocation. */
+ mfmsr r3 /* Save MSR in r7 */
+ rlwinm r3,r3,0,28,26 /* Turn off DR bit */
+ sync
+ mtmsr r3
+ isync
+
+BEGIN_FTR_SECTION
+ /* Flush any pending L2 data prefetches to work around HW bug */
+ sync
+ lis r3,0xfff0
+ lwz r0,0(r3) /* perform cache-inhibited load to ROM */
+ sync /* (caches are disabled at this point) */
+END_FTR_SECTION_IFSET(CPU_FTR_SPEC7450)
+
+/*
+ * Set the HID0 and MSR for sleep.
+ */
+ mfspr r2,SPRN_HID0
+ rlwinm r2,r2,0,10,7 /* clear doze, nap */
+ oris r2,r2,HID0_SLEEP@h
+ sync
+ isync
+ mtspr SPRN_HID0,r2
+ sync
+
+/* This loop puts us back to sleep in case we have a spurrious
+ * wakeup so that the host bridge properly stays asleep. The
+ * CPU will be turned off, either after a known time (about 1
+ * second) on wallstreet & lombard, or as soon as the CPU enters
+ * SLEEP mode on core99
+ */
+ mfmsr r2
+ oris r2,r2,MSR_POW@h
+1: sync
+ mtmsr r2
+ isync
+ b 1b
+
+/*
+ * Here is the resume code.
+ */
+
+
+/*
+ * Core99 machines resume here
+ * r4 has the physical address of SL_PC(sp) (unused)
+ */
+_GLOBAL(core99_wake_up)
+ /* Make sure HID0 no longer contains any sleep bit and that data cache
+ * is disabled
+ */
+ mfspr r3,SPRN_HID0
+ rlwinm r3,r3,0,11,7 /* clear SLEEP, NAP, DOZE bits */
+ rlwinm 3,r3,0,18,15 /* clear DCE, ICE */
+ mtspr SPRN_HID0,r3
+ sync
+ isync
+
+ /* sanitize MSR */
+ mfmsr r3
+ ori r3,r3,MSR_EE|MSR_IP
+ xori r3,r3,MSR_EE|MSR_IP
+ sync
+ isync
+ mtmsr r3
+ sync
+ isync
+
+ /* Recover sleep storage */
+ lis r3,sleep_storage@ha
+ addi r3,r3,sleep_storage@l
+ tophys(r3,r3)
+ lwz r1,0(r3)
+
+ /* Pass thru to older resume code ... */
+/*
+ * Here is the resume code for older machines.
+ * r1 has the physical address of SL_PC(sp).
+ */
+
+grackle_wake_up:
+
+ /* Restore the kernel's segment registers before
+ * we do any r1 memory access as we are not sure they
+ * are in a sane state above the first 256Mb region
+ */
+ li r0,16 /* load up segment register values */
+ mtctr r0 /* for context 0 */
+ lis r3,0x2000 /* Ku = 1, VSID = 0 */
+ li r4,0
+3: mtsrin r3,r4
+ addi r3,r3,0x111 /* increment VSID */
+ addis r4,r4,0x1000 /* address of next segment */
+ bdnz 3b
+ sync
+ isync
+
+ subi r1,r1,SL_PC
+
+ /* Restore various CPU config stuffs */
+ bl __restore_cpu_setup
+
+ /* Invalidate & enable L1 cache, we don't care about
+ * whatever the ROM may have tried to write to memory
+ */
+ bl __inval_enable_L1
+
+ /* Restore the BATs, and SDR1. Then we can turn on the MMU. */
+ lwz r4,SL_SDR1(r1)
+ mtsdr1 r4
+ lwz r4,SL_SPRG0(r1)
+ mtsprg 0,r4
+ lwz r4,SL_SPRG0+4(r1)
+ mtsprg 1,r4
+ lwz r4,SL_SPRG0+8(r1)
+ mtsprg 2,r4
+ lwz r4,SL_SPRG0+12(r1)
+ mtsprg 3,r4
+
+ lwz r4,SL_DBAT0(r1)
+ mtdbatu 0,r4
+ lwz r4,SL_DBAT0+4(r1)
+ mtdbatl 0,r4
+ lwz r4,SL_DBAT1(r1)
+ mtdbatu 1,r4
+ lwz r4,SL_DBAT1+4(r1)
+ mtdbatl 1,r4
+ lwz r4,SL_DBAT2(r1)
+ mtdbatu 2,r4
+ lwz r4,SL_DBAT2+4(r1)
+ mtdbatl 2,r4
+ lwz r4,SL_DBAT3(r1)
+ mtdbatu 3,r4
+ lwz r4,SL_DBAT3+4(r1)
+ mtdbatl 3,r4
+ lwz r4,SL_IBAT0(r1)
+ mtibatu 0,r4
+ lwz r4,SL_IBAT0+4(r1)
+ mtibatl 0,r4
+ lwz r4,SL_IBAT1(r1)
+ mtibatu 1,r4
+ lwz r4,SL_IBAT1+4(r1)
+ mtibatl 1,r4
+ lwz r4,SL_IBAT2(r1)
+ mtibatu 2,r4
+ lwz r4,SL_IBAT2+4(r1)
+ mtibatl 2,r4
+ lwz r4,SL_IBAT3(r1)
+ mtibatu 3,r4
+ lwz r4,SL_IBAT3+4(r1)
+ mtibatl 3,r4
+
+BEGIN_FTR_SECTION
+ li r4,0
+ mtspr SPRN_DBAT4U,r4
+ mtspr SPRN_DBAT4L,r4
+ mtspr SPRN_DBAT5U,r4
+ mtspr SPRN_DBAT5L,r4
+ mtspr SPRN_DBAT6U,r4
+ mtspr SPRN_DBAT6L,r4
+ mtspr SPRN_DBAT7U,r4
+ mtspr SPRN_DBAT7L,r4
+ mtspr SPRN_IBAT4U,r4
+ mtspr SPRN_IBAT4L,r4
+ mtspr SPRN_IBAT5U,r4
+ mtspr SPRN_IBAT5L,r4
+ mtspr SPRN_IBAT6U,r4
+ mtspr SPRN_IBAT6L,r4
+ mtspr SPRN_IBAT7U,r4
+ mtspr SPRN_IBAT7L,r4
+END_FTR_SECTION_IFSET(CPU_FTR_HAS_HIGH_BATS)
+
+ /* Flush all TLBs */
+ lis r4,0x1000
+1: addic. r4,r4,-0x1000
+ tlbie r4
+ blt 1b
+ sync
+
+ /* restore the MSR and turn on the MMU */
+ lwz r3,SL_MSR(r1)
+ bl turn_on_mmu
+
+ /* get back the stack pointer */
+ tovirt(r1,r1)
+
+ /* Restore TB */
+ li r3,0
+ mttbl r3
+ lwz r3,SL_TB(r1)
+ lwz r4,SL_TB+4(r1)
+ mttbu r3
+ mttbl r4
+
+ /* Restore the callee-saved registers and return */
+ lwz r0,SL_CR(r1)
+ mtcr r0
+ lwz r2,SL_R2(r1)
+ lmw r12,SL_R12(r1)
+ addi r1,r1,SL_SIZE
+ lwz r0,4(r1)
+ mtlr r0
+ blr
+
+turn_on_mmu:
+ mflr r4
+ tovirt(r4,r4)
+ mtsrr0 r4
+ mtsrr1 r3
+ sync
+ isync
+ rfi
+
+#endif /* defined(CONFIG_PMAC_PBOOK) || defined(CONFIG_CPU_FREQ) */
+
+ .section .data
+ .balign L1_CACHE_LINE_SIZE
+sleep_storage:
+ .long 0
+ .balign L1_CACHE_LINE_SIZE, 0
+
+#endif /* CONFIG_6xx */
+ .section .text
diff --git a/arch/ppc/platforms/pmac_smp.c b/arch/ppc/platforms/pmac_smp.c
new file mode 100644
index 0000000..2b88745
--- /dev/null
+++ b/arch/ppc/platforms/pmac_smp.c
@@ -0,0 +1,640 @@
+/*
+ * SMP support for power macintosh.
+ *
+ * We support both the old "powersurge" SMP architecture
+ * and the current Core99 (G4 PowerMac) machines.
+ *
+ * Note that we don't support the very first rev. of
+ * Apple/DayStar 2 CPUs board, the one with the funky
+ * watchdog. Hopefully, none of these should be there except
+ * maybe internally to Apple. I should probably still add some
+ * code to detect this card though and disable SMP. --BenH.
+ *
+ * Support Macintosh G4 SMP by Troy Benjegerdes (hozer@drgw.net)
+ * and Ben Herrenschmidt <benh@kernel.crashing.org>.
+ *
+ * Support for DayStar quad CPU cards
+ * Copyright (C) XLR8, Inc. 1994-2000
+ *
+ * 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.
+ */
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/smp.h>
+#include <linux/smp_lock.h>
+#include <linux/interrupt.h>
+#include <linux/kernel_stat.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/spinlock.h>
+#include <linux/errno.h>
+#include <linux/hardirq.h>
+
+#include <asm/ptrace.h>
+#include <asm/atomic.h>
+#include <asm/irq.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <asm/sections.h>
+#include <asm/io.h>
+#include <asm/prom.h>
+#include <asm/smp.h>
+#include <asm/residual.h>
+#include <asm/machdep.h>
+#include <asm/pmac_feature.h>
+#include <asm/time.h>
+#include <asm/open_pic.h>
+#include <asm/cacheflush.h>
+#include <asm/keylargo.h>
+
+/*
+ * Powersurge (old powermac SMP) support.
+ */
+
+extern void __secondary_start_psurge(void);
+extern void __secondary_start_psurge2(void); /* Temporary horrible hack */
+extern void __secondary_start_psurge3(void); /* Temporary horrible hack */
+
+/* Addresses for powersurge registers */
+#define HAMMERHEAD_BASE 0xf8000000
+#define HHEAD_CONFIG 0x90
+#define HHEAD_SEC_INTR 0xc0
+
+/* register for interrupting the primary processor on the powersurge */
+/* N.B. this is actually the ethernet ROM! */
+#define PSURGE_PRI_INTR 0xf3019000
+
+/* register for storing the start address for the secondary processor */
+/* N.B. this is the PCI config space address register for the 1st bridge */
+#define PSURGE_START 0xf2800000
+
+/* Daystar/XLR8 4-CPU card */
+#define PSURGE_QUAD_REG_ADDR 0xf8800000
+
+#define PSURGE_QUAD_IRQ_SET 0
+#define PSURGE_QUAD_IRQ_CLR 1
+#define PSURGE_QUAD_IRQ_PRIMARY 2
+#define PSURGE_QUAD_CKSTOP_CTL 3
+#define PSURGE_QUAD_PRIMARY_ARB 4
+#define PSURGE_QUAD_BOARD_ID 6
+#define PSURGE_QUAD_WHICH_CPU 7
+#define PSURGE_QUAD_CKSTOP_RDBK 8
+#define PSURGE_QUAD_RESET_CTL 11
+
+#define PSURGE_QUAD_OUT(r, v) (out_8(quad_base + ((r) << 4) + 4, (v)))
+#define PSURGE_QUAD_IN(r) (in_8(quad_base + ((r) << 4) + 4) & 0x0f)
+#define PSURGE_QUAD_BIS(r, v) (PSURGE_QUAD_OUT((r), PSURGE_QUAD_IN(r) | (v)))
+#define PSURGE_QUAD_BIC(r, v) (PSURGE_QUAD_OUT((r), PSURGE_QUAD_IN(r) & ~(v)))
+
+/* virtual addresses for the above */
+static volatile u8 *hhead_base;
+static volatile u8 *quad_base;
+static volatile u32 *psurge_pri_intr;
+static volatile u8 *psurge_sec_intr;
+static volatile u32 *psurge_start;
+
+/* values for psurge_type */
+#define PSURGE_NONE -1
+#define PSURGE_DUAL 0
+#define PSURGE_QUAD_OKEE 1
+#define PSURGE_QUAD_COTTON 2
+#define PSURGE_QUAD_ICEGRASS 3
+
+/* what sort of powersurge board we have */
+static int psurge_type = PSURGE_NONE;
+
+/* L2 and L3 cache settings to pass from CPU0 to CPU1 */
+volatile static long int core99_l2_cache;
+volatile static long int core99_l3_cache;
+
+/* Timebase freeze GPIO */
+static unsigned int core99_tb_gpio;
+
+/* Sync flag for HW tb sync */
+static volatile int sec_tb_reset = 0;
+
+static void __init core99_init_caches(int cpu)
+{
+ if (!cpu_has_feature(CPU_FTR_L2CR))
+ return;
+
+ if (cpu == 0) {
+ core99_l2_cache = _get_L2CR();
+ printk("CPU0: L2CR is %lx\n", core99_l2_cache);
+ } else {
+ printk("CPU%d: L2CR was %lx\n", cpu, _get_L2CR());
+ _set_L2CR(0);
+ _set_L2CR(core99_l2_cache);
+ printk("CPU%d: L2CR set to %lx\n", cpu, core99_l2_cache);
+ }
+
+ if (!cpu_has_feature(CPU_FTR_L3CR))
+ return;
+
+ if (cpu == 0){
+ core99_l3_cache = _get_L3CR();
+ printk("CPU0: L3CR is %lx\n", core99_l3_cache);
+ } else {
+ printk("CPU%d: L3CR was %lx\n", cpu, _get_L3CR());
+ _set_L3CR(0);
+ _set_L3CR(core99_l3_cache);
+ printk("CPU%d: L3CR set to %lx\n", cpu, core99_l3_cache);
+ }
+}
+
+/*
+ * Set and clear IPIs for powersurge.
+ */
+static inline void psurge_set_ipi(int cpu)
+{
+ if (psurge_type == PSURGE_NONE)
+ return;
+ if (cpu == 0)
+ in_be32(psurge_pri_intr);
+ else if (psurge_type == PSURGE_DUAL)
+ out_8(psurge_sec_intr, 0);
+ else
+ PSURGE_QUAD_OUT(PSURGE_QUAD_IRQ_SET, 1 << cpu);
+}
+
+static inline void psurge_clr_ipi(int cpu)
+{
+ if (cpu > 0) {
+ switch(psurge_type) {
+ case PSURGE_DUAL:
+ out_8(psurge_sec_intr, ~0);
+ case PSURGE_NONE:
+ break;
+ default:
+ PSURGE_QUAD_OUT(PSURGE_QUAD_IRQ_CLR, 1 << cpu);
+ }
+ }
+}
+
+/*
+ * On powersurge (old SMP powermac architecture) we don't have
+ * separate IPIs for separate messages like openpic does. Instead
+ * we have a bitmap for each processor, where a 1 bit means that
+ * the corresponding message is pending for that processor.
+ * Ideally each cpu's entry would be in a different cache line.
+ * -- paulus.
+ */
+static unsigned long psurge_smp_message[NR_CPUS];
+
+void __pmac psurge_smp_message_recv(struct pt_regs *regs)
+{
+ int cpu = smp_processor_id();
+ int msg;
+
+ /* clear interrupt */
+ psurge_clr_ipi(cpu);
+
+ if (num_online_cpus() < 2)
+ return;
+
+ /* make sure there is a message there */
+ for (msg = 0; msg < 4; msg++)
+ if (test_and_clear_bit(msg, &psurge_smp_message[cpu]))
+ smp_message_recv(msg, regs);
+}
+
+irqreturn_t __pmac psurge_primary_intr(int irq, void *d, struct pt_regs *regs)
+{
+ psurge_smp_message_recv(regs);
+ return IRQ_HANDLED;
+}
+
+static void __pmac smp_psurge_message_pass(int target, int msg, unsigned long data,
+ int wait)
+{
+ int i;
+
+ if (num_online_cpus() < 2)
+ return;
+
+ for (i = 0; i < NR_CPUS; i++) {
+ if (!cpu_online(i))
+ continue;
+ if (target == MSG_ALL
+ || (target == MSG_ALL_BUT_SELF && i != smp_processor_id())
+ || target == i) {
+ set_bit(msg, &psurge_smp_message[i]);
+ psurge_set_ipi(i);
+ }
+ }
+}
+
+/*
+ * Determine a quad card presence. We read the board ID register, we
+ * force the data bus to change to something else, and we read it again.
+ * It it's stable, then the register probably exist (ugh !)
+ */
+static int __init psurge_quad_probe(void)
+{
+ int type;
+ unsigned int i;
+
+ type = PSURGE_QUAD_IN(PSURGE_QUAD_BOARD_ID);
+ if (type < PSURGE_QUAD_OKEE || type > PSURGE_QUAD_ICEGRASS
+ || type != PSURGE_QUAD_IN(PSURGE_QUAD_BOARD_ID))
+ return PSURGE_DUAL;
+
+ /* looks OK, try a slightly more rigorous test */
+ /* bogus is not necessarily cacheline-aligned,
+ though I don't suppose that really matters. -- paulus */
+ for (i = 0; i < 100; i++) {
+ volatile u32 bogus[8];
+ bogus[(0+i)%8] = 0x00000000;
+ bogus[(1+i)%8] = 0x55555555;
+ bogus[(2+i)%8] = 0xFFFFFFFF;
+ bogus[(3+i)%8] = 0xAAAAAAAA;
+ bogus[(4+i)%8] = 0x33333333;
+ bogus[(5+i)%8] = 0xCCCCCCCC;
+ bogus[(6+i)%8] = 0xCCCCCCCC;
+ bogus[(7+i)%8] = 0x33333333;
+ wmb();
+ asm volatile("dcbf 0,%0" : : "r" (bogus) : "memory");
+ mb();
+ if (type != PSURGE_QUAD_IN(PSURGE_QUAD_BOARD_ID))
+ return PSURGE_DUAL;
+ }
+ return type;
+}
+
+static void __init psurge_quad_init(void)
+{
+ int procbits;
+
+ if (ppc_md.progress) ppc_md.progress("psurge_quad_init", 0x351);
+ procbits = ~PSURGE_QUAD_IN(PSURGE_QUAD_WHICH_CPU);
+ if (psurge_type == PSURGE_QUAD_ICEGRASS)
+ PSURGE_QUAD_BIS(PSURGE_QUAD_RESET_CTL, procbits);
+ else
+ PSURGE_QUAD_BIC(PSURGE_QUAD_CKSTOP_CTL, procbits);
+ mdelay(33);
+ out_8(psurge_sec_intr, ~0);
+ PSURGE_QUAD_OUT(PSURGE_QUAD_IRQ_CLR, procbits);
+ PSURGE_QUAD_BIS(PSURGE_QUAD_RESET_CTL, procbits);
+ if (psurge_type != PSURGE_QUAD_ICEGRASS)
+ PSURGE_QUAD_BIS(PSURGE_QUAD_CKSTOP_CTL, procbits);
+ PSURGE_QUAD_BIC(PSURGE_QUAD_PRIMARY_ARB, procbits);
+ mdelay(33);
+ PSURGE_QUAD_BIC(PSURGE_QUAD_RESET_CTL, procbits);
+ mdelay(33);
+ PSURGE_QUAD_BIS(PSURGE_QUAD_PRIMARY_ARB, procbits);
+ mdelay(33);
+}
+
+static int __init smp_psurge_probe(void)
+{
+ int i, ncpus;
+
+ /* We don't do SMP on the PPC601 -- paulus */
+ if (PVR_VER(mfspr(SPRN_PVR)) == 1)
+ return 1;
+
+ /*
+ * The powersurge cpu board can be used in the generation
+ * of powermacs that have a socket for an upgradeable cpu card,
+ * including the 7500, 8500, 9500, 9600.
+ * The device tree doesn't tell you if you have 2 cpus because
+ * OF doesn't know anything about the 2nd processor.
+ * Instead we look for magic bits in magic registers,
+ * in the hammerhead memory controller in the case of the
+ * dual-cpu powersurge board. -- paulus.
+ */
+ if (find_devices("hammerhead") == NULL)
+ return 1;
+
+ hhead_base = ioremap(HAMMERHEAD_BASE, 0x800);
+ quad_base = ioremap(PSURGE_QUAD_REG_ADDR, 1024);
+ psurge_sec_intr = hhead_base + HHEAD_SEC_INTR;
+
+ psurge_type = psurge_quad_probe();
+ if (psurge_type != PSURGE_DUAL) {
+ psurge_quad_init();
+ /* All released cards using this HW design have 4 CPUs */
+ ncpus = 4;
+ } else {
+ iounmap((void *) quad_base);
+ if ((in_8(hhead_base + HHEAD_CONFIG) & 0x02) == 0) {
+ /* not a dual-cpu card */
+ iounmap((void *) hhead_base);
+ psurge_type = PSURGE_NONE;
+ return 1;
+ }
+ ncpus = 2;
+ }
+
+ psurge_start = ioremap(PSURGE_START, 4);
+ psurge_pri_intr = ioremap(PSURGE_PRI_INTR, 4);
+
+ /* this is not actually strictly necessary -- paulus. */
+ for (i = 1; i < ncpus; ++i)
+ smp_hw_index[i] = i;
+
+ if (ppc_md.progress) ppc_md.progress("smp_psurge_probe - done", 0x352);
+
+ return ncpus;
+}
+
+static void __init smp_psurge_kick_cpu(int nr)
+{
+ void (*start)(void) = __secondary_start_psurge;
+ unsigned long a;
+
+ /* may need to flush here if secondary bats aren't setup */
+ for (a = KERNELBASE; a < KERNELBASE + 0x800000; a += 32)
+ asm volatile("dcbf 0,%0" : : "r" (a) : "memory");
+ asm volatile("sync");
+
+ if (ppc_md.progress) ppc_md.progress("smp_psurge_kick_cpu", 0x353);
+
+ /* setup entry point of secondary processor */
+ switch (nr) {
+ case 2:
+ start = __secondary_start_psurge2;
+ break;
+ case 3:
+ start = __secondary_start_psurge3;
+ break;
+ }
+
+ out_be32(psurge_start, __pa(start));
+ mb();
+
+ psurge_set_ipi(nr);
+ udelay(10);
+ psurge_clr_ipi(nr);
+
+ if (ppc_md.progress) ppc_md.progress("smp_psurge_kick_cpu - done", 0x354);
+}
+
+/*
+ * With the dual-cpu powersurge board, the decrementers and timebases
+ * of both cpus are frozen after the secondary cpu is started up,
+ * until we give the secondary cpu another interrupt. This routine
+ * uses this to get the timebases synchronized.
+ * -- paulus.
+ */
+static void __init psurge_dual_sync_tb(int cpu_nr)
+{
+ int t;
+
+ set_dec(tb_ticks_per_jiffy);
+ set_tb(0, 0);
+ last_jiffy_stamp(cpu_nr) = 0;
+
+ if (cpu_nr > 0) {
+ mb();
+ sec_tb_reset = 1;
+ return;
+ }
+
+ /* wait for the secondary to have reset its TB before proceeding */
+ for (t = 10000000; t > 0 && !sec_tb_reset; --t)
+ ;
+
+ /* now interrupt the secondary, starting both TBs */
+ psurge_set_ipi(1);
+
+ smp_tb_synchronized = 1;
+}
+
+static struct irqaction psurge_irqaction = {
+ .handler = psurge_primary_intr,
+ .flags = SA_INTERRUPT,
+ .mask = CPU_MASK_NONE,
+ .name = "primary IPI",
+};
+
+static void __init smp_psurge_setup_cpu(int cpu_nr)
+{
+
+ if (cpu_nr == 0) {
+ /* If we failed to start the second CPU, we should still
+ * send it an IPI to start the timebase & DEC or we might
+ * have them stuck.
+ */
+ if (num_online_cpus() < 2) {
+ if (psurge_type == PSURGE_DUAL)
+ psurge_set_ipi(1);
+ return;
+ }
+ /* reset the entry point so if we get another intr we won't
+ * try to startup again */
+ out_be32(psurge_start, 0x100);
+ if (setup_irq(30, &psurge_irqaction))
+ printk(KERN_ERR "Couldn't get primary IPI interrupt");
+ }
+
+ if (psurge_type == PSURGE_DUAL)
+ psurge_dual_sync_tb(cpu_nr);
+}
+
+void __init smp_psurge_take_timebase(void)
+{
+ /* Dummy implementation */
+}
+
+void __init smp_psurge_give_timebase(void)
+{
+ /* Dummy implementation */
+}
+
+static int __init smp_core99_probe(void)
+{
+#ifdef CONFIG_6xx
+ extern int powersave_nap;
+#endif
+ struct device_node *cpus, *firstcpu;
+ int i, ncpus = 0, boot_cpu = -1;
+ u32 *tbprop;
+
+ if (ppc_md.progress) ppc_md.progress("smp_core99_probe", 0x345);
+ cpus = firstcpu = find_type_devices("cpu");
+ while(cpus != NULL) {
+ u32 *regprop = (u32 *)get_property(cpus, "reg", NULL);
+ char *stateprop = (char *)get_property(cpus, "state", NULL);
+ if (regprop != NULL && stateprop != NULL &&
+ !strncmp(stateprop, "running", 7))
+ boot_cpu = *regprop;
+ ++ncpus;
+ cpus = cpus->next;
+ }
+ if (boot_cpu == -1)
+ printk(KERN_WARNING "Couldn't detect boot CPU !\n");
+ if (boot_cpu != 0)
+ printk(KERN_WARNING "Boot CPU is %d, unsupported setup !\n", boot_cpu);
+
+ if (machine_is_compatible("MacRISC4")) {
+ extern struct smp_ops_t core99_smp_ops;
+
+ core99_smp_ops.take_timebase = smp_generic_take_timebase;
+ core99_smp_ops.give_timebase = smp_generic_give_timebase;
+ } else {
+ if (firstcpu != NULL)
+ tbprop = (u32 *)get_property(firstcpu, "timebase-enable", NULL);
+ if (tbprop)
+ core99_tb_gpio = *tbprop;
+ else
+ core99_tb_gpio = KL_GPIO_TB_ENABLE;
+ }
+
+ if (ncpus > 1) {
+ openpic_request_IPIs();
+ for (i = 1; i < ncpus; ++i)
+ smp_hw_index[i] = i;
+#ifdef CONFIG_6xx
+ powersave_nap = 0;
+#endif
+ core99_init_caches(0);
+ }
+
+ return ncpus;
+}
+
+static void __init smp_core99_kick_cpu(int nr)
+{
+ unsigned long save_vector, new_vector;
+ unsigned long flags;
+
+ volatile unsigned long *vector
+ = ((volatile unsigned long *)(KERNELBASE+0x100));
+ if (nr < 1 || nr > 3)
+ return;
+ if (ppc_md.progress) ppc_md.progress("smp_core99_kick_cpu", 0x346);
+
+ local_irq_save(flags);
+ local_irq_disable();
+
+ /* Save reset vector */
+ save_vector = *vector;
+
+ /* Setup fake reset vector that does
+ * b __secondary_start_psurge - KERNELBASE
+ */
+ switch(nr) {
+ case 1:
+ new_vector = (unsigned long)__secondary_start_psurge;
+ break;
+ case 2:
+ new_vector = (unsigned long)__secondary_start_psurge2;
+ break;
+ case 3:
+ new_vector = (unsigned long)__secondary_start_psurge3;
+ break;
+ }
+ *vector = 0x48000002 + new_vector - KERNELBASE;
+
+ /* flush data cache and inval instruction cache */
+ flush_icache_range((unsigned long) vector, (unsigned long) vector + 4);
+
+ /* Put some life in our friend */
+ pmac_call_feature(PMAC_FTR_RESET_CPU, NULL, nr, 0);
+
+ /* FIXME: We wait a bit for the CPU to take the exception, I should
+ * instead wait for the entry code to set something for me. Well,
+ * ideally, all that crap will be done in prom.c and the CPU left
+ * in a RAM-based wait loop like CHRP.
+ */
+ mdelay(1);
+
+ /* Restore our exception vector */
+ *vector = save_vector;
+ flush_icache_range((unsigned long) vector, (unsigned long) vector + 4);
+
+ local_irq_restore(flags);
+ if (ppc_md.progress) ppc_md.progress("smp_core99_kick_cpu done", 0x347);
+}
+
+static void __init smp_core99_setup_cpu(int cpu_nr)
+{
+ /* Setup L2/L3 */
+ if (cpu_nr != 0)
+ core99_init_caches(cpu_nr);
+
+ /* Setup openpic */
+ do_openpic_setup_cpu();
+
+ if (cpu_nr == 0) {
+#ifdef CONFIG_POWER4
+ extern void g5_phy_disable_cpu1(void);
+
+ /* If we didn't start the second CPU, we must take
+ * it off the bus
+ */
+ if (machine_is_compatible("MacRISC4") &&
+ num_online_cpus() < 2)
+ g5_phy_disable_cpu1();
+#endif /* CONFIG_POWER4 */
+ if (ppc_md.progress) ppc_md.progress("core99_setup_cpu 0 done", 0x349);
+ }
+}
+
+void __init smp_core99_take_timebase(void)
+{
+ /* Secondary processor "takes" the timebase by freezing
+ * it, resetting its local TB and telling CPU 0 to go on
+ */
+ pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, core99_tb_gpio, 4);
+ pmac_call_feature(PMAC_FTR_READ_GPIO, NULL, core99_tb_gpio, 0);
+ mb();
+
+ set_dec(tb_ticks_per_jiffy);
+ set_tb(0, 0);
+ last_jiffy_stamp(smp_processor_id()) = 0;
+
+ mb();
+ sec_tb_reset = 1;
+}
+
+void __init smp_core99_give_timebase(void)
+{
+ unsigned int t;
+
+ /* Primary processor waits for secondary to have frozen
+ * the timebase, resets local TB, and kick timebase again
+ */
+ /* wait for the secondary to have reset its TB before proceeding */
+ for (t = 1000; t > 0 && !sec_tb_reset; --t)
+ udelay(1000);
+ if (t == 0)
+ printk(KERN_WARNING "Timeout waiting sync on second CPU\n");
+
+ set_dec(tb_ticks_per_jiffy);
+ set_tb(0, 0);
+ last_jiffy_stamp(smp_processor_id()) = 0;
+ mb();
+
+ /* Now, restart the timebase by leaving the GPIO to an open collector */
+ pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, core99_tb_gpio, 0);
+ pmac_call_feature(PMAC_FTR_READ_GPIO, NULL, core99_tb_gpio, 0);
+
+ smp_tb_synchronized = 1;
+}
+
+
+/* PowerSurge-style Macs */
+struct smp_ops_t psurge_smp_ops __pmacdata = {
+ .message_pass = smp_psurge_message_pass,
+ .probe = smp_psurge_probe,
+ .kick_cpu = smp_psurge_kick_cpu,
+ .setup_cpu = smp_psurge_setup_cpu,
+ .give_timebase = smp_psurge_give_timebase,
+ .take_timebase = smp_psurge_take_timebase,
+};
+
+/* Core99 Macs (dual G4s) */
+struct smp_ops_t core99_smp_ops __pmacdata = {
+ .message_pass = smp_openpic_message_pass,
+ .probe = smp_core99_probe,
+ .kick_cpu = smp_core99_kick_cpu,
+ .setup_cpu = smp_core99_setup_cpu,
+ .give_timebase = smp_core99_give_timebase,
+ .take_timebase = smp_core99_take_timebase,
+};
diff --git a/arch/ppc/platforms/pmac_time.c b/arch/ppc/platforms/pmac_time.c
new file mode 100644
index 0000000..0963654
--- /dev/null
+++ b/arch/ppc/platforms/pmac_time.c
@@ -0,0 +1,292 @@
+/*
+ * Support for periodic interrupts (100 per second) and for getting
+ * the current time from the RTC on Power Macintoshes.
+ *
+ * We use the decrementer register for our periodic interrupts.
+ *
+ * Paul Mackerras August 1996.
+ * Copyright (C) 1996 Paul Mackerras.
+ */
+#include <linux/config.h>
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/param.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/init.h>
+#include <linux/time.h>
+#include <linux/adb.h>
+#include <linux/cuda.h>
+#include <linux/pmu.h>
+#include <linux/hardirq.h>
+
+#include <asm/sections.h>
+#include <asm/prom.h>
+#include <asm/system.h>
+#include <asm/io.h>
+#include <asm/pgtable.h>
+#include <asm/machdep.h>
+#include <asm/time.h>
+#include <asm/nvram.h>
+
+/* Apparently the RTC stores seconds since 1 Jan 1904 */
+#define RTC_OFFSET 2082844800
+
+/*
+ * Calibrate the decrementer frequency with the VIA timer 1.
+ */
+#define VIA_TIMER_FREQ_6 4700000 /* time 1 frequency * 6 */
+
+/* VIA registers */
+#define RS 0x200 /* skip between registers */
+#define T1CL (4*RS) /* Timer 1 ctr/latch (low 8 bits) */
+#define T1CH (5*RS) /* Timer 1 counter (high 8 bits) */
+#define T1LL (6*RS) /* Timer 1 latch (low 8 bits) */
+#define T1LH (7*RS) /* Timer 1 latch (high 8 bits) */
+#define ACR (11*RS) /* Auxiliary control register */
+#define IFR (13*RS) /* Interrupt flag register */
+
+/* Bits in ACR */
+#define T1MODE 0xc0 /* Timer 1 mode */
+#define T1MODE_CONT 0x40 /* continuous interrupts */
+
+/* Bits in IFR and IER */
+#define T1_INT 0x40 /* Timer 1 interrupt */
+
+extern struct timezone sys_tz;
+
+long __init
+pmac_time_init(void)
+{
+#ifdef CONFIG_NVRAM
+ s32 delta = 0;
+ int dst;
+
+ delta = ((s32)pmac_xpram_read(PMAC_XPRAM_MACHINE_LOC + 0x9)) << 16;
+ delta |= ((s32)pmac_xpram_read(PMAC_XPRAM_MACHINE_LOC + 0xa)) << 8;
+ delta |= pmac_xpram_read(PMAC_XPRAM_MACHINE_LOC + 0xb);
+ if (delta & 0x00800000UL)
+ delta |= 0xFF000000UL;
+ dst = ((pmac_xpram_read(PMAC_XPRAM_MACHINE_LOC + 0x8) & 0x80) != 0);
+ printk("GMT Delta read from XPRAM: %d minutes, DST: %s\n", delta/60,
+ dst ? "on" : "off");
+ return delta;
+#else
+ return 0;
+#endif
+}
+
+unsigned long __pmac
+pmac_get_rtc_time(void)
+{
+#if defined(CONFIG_ADB_CUDA) || defined(CONFIG_ADB_PMU)
+ struct adb_request req;
+ unsigned long now;
+#endif
+
+ /* Get the time from the RTC */
+ switch (sys_ctrler) {
+#ifdef CONFIG_ADB_CUDA
+ case SYS_CTRLER_CUDA:
+ if (cuda_request(&req, NULL, 2, CUDA_PACKET, CUDA_GET_TIME) < 0)
+ return 0;
+ while (!req.complete)
+ cuda_poll();
+ if (req.reply_len != 7)
+ printk(KERN_ERR "pmac_get_rtc_time: got %d byte reply\n",
+ req.reply_len);
+ now = (req.reply[3] << 24) + (req.reply[4] << 16)
+ + (req.reply[5] << 8) + req.reply[6];
+ return now - RTC_OFFSET;
+#endif /* CONFIG_ADB_CUDA */
+#ifdef CONFIG_ADB_PMU
+ case SYS_CTRLER_PMU:
+ if (pmu_request(&req, NULL, 1, PMU_READ_RTC) < 0)
+ return 0;
+ while (!req.complete)
+ pmu_poll();
+ if (req.reply_len != 4)
+ printk(KERN_ERR "pmac_get_rtc_time: got %d byte reply\n",
+ req.reply_len);
+ now = (req.reply[0] << 24) + (req.reply[1] << 16)
+ + (req.reply[2] << 8) + req.reply[3];
+ return now - RTC_OFFSET;
+#endif /* CONFIG_ADB_PMU */
+ default: ;
+ }
+ return 0;
+}
+
+int __pmac
+pmac_set_rtc_time(unsigned long nowtime)
+{
+#if defined(CONFIG_ADB_CUDA) || defined(CONFIG_ADB_PMU)
+ struct adb_request req;
+#endif
+
+ nowtime += RTC_OFFSET;
+
+ switch (sys_ctrler) {
+#ifdef CONFIG_ADB_CUDA
+ case SYS_CTRLER_CUDA:
+ if (cuda_request(&req, NULL, 6, CUDA_PACKET, CUDA_SET_TIME,
+ nowtime >> 24, nowtime >> 16, nowtime >> 8, nowtime) < 0)
+ return 0;
+ while (!req.complete)
+ cuda_poll();
+ if ((req.reply_len != 3) && (req.reply_len != 7))
+ printk(KERN_ERR "pmac_set_rtc_time: got %d byte reply\n",
+ req.reply_len);
+ return 1;
+#endif /* CONFIG_ADB_CUDA */
+#ifdef CONFIG_ADB_PMU
+ case SYS_CTRLER_PMU:
+ if (pmu_request(&req, NULL, 5, PMU_SET_RTC,
+ nowtime >> 24, nowtime >> 16, nowtime >> 8, nowtime) < 0)
+ return 0;
+ while (!req.complete)
+ pmu_poll();
+ if (req.reply_len != 0)
+ printk(KERN_ERR "pmac_set_rtc_time: got %d byte reply\n",
+ req.reply_len);
+ return 1;
+#endif /* CONFIG_ADB_PMU */
+ default:
+ return 0;
+ }
+}
+
+/*
+ * Calibrate the decrementer register using VIA timer 1.
+ * This is used both on powermacs and CHRP machines.
+ */
+int __init
+via_calibrate_decr(void)
+{
+ struct device_node *vias;
+ volatile unsigned char *via;
+ int count = VIA_TIMER_FREQ_6 / 100;
+ unsigned int dstart, dend;
+
+ vias = find_devices("via-cuda");
+ if (vias == 0)
+ vias = find_devices("via-pmu");
+ if (vias == 0)
+ vias = find_devices("via");
+ if (vias == 0 || vias->n_addrs == 0)
+ return 0;
+ via = (volatile unsigned char *)
+ ioremap(vias->addrs[0].address, vias->addrs[0].size);
+
+ /* set timer 1 for continuous interrupts */
+ out_8(&via[ACR], (via[ACR] & ~T1MODE) | T1MODE_CONT);
+ /* set the counter to a small value */
+ out_8(&via[T1CH], 2);
+ /* set the latch to `count' */
+ out_8(&via[T1LL], count);
+ out_8(&via[T1LH], count >> 8);
+ /* wait until it hits 0 */
+ while ((in_8(&via[IFR]) & T1_INT) == 0)
+ ;
+ dstart = get_dec();
+ /* clear the interrupt & wait until it hits 0 again */
+ in_8(&via[T1CL]);
+ while ((in_8(&via[IFR]) & T1_INT) == 0)
+ ;
+ dend = get_dec();
+
+ tb_ticks_per_jiffy = (dstart - dend) / (6 * (HZ/100));
+ tb_to_us = mulhwu_scale_factor(dstart - dend, 60000);
+
+ printk(KERN_INFO "via_calibrate_decr: ticks per jiffy = %u (%u ticks)\n",
+ tb_ticks_per_jiffy, dstart - dend);
+
+ iounmap((void*)via);
+
+ return 1;
+}
+
+#ifdef CONFIG_PMAC_PBOOK
+/*
+ * Reset the time after a sleep.
+ */
+static int __pmac
+time_sleep_notify(struct pmu_sleep_notifier *self, int when)
+{
+ static unsigned long time_diff;
+ unsigned long flags;
+ unsigned long seq;
+
+ switch (when) {
+ case PBOOK_SLEEP_NOW:
+ do {
+ seq = read_seqbegin_irqsave(&xtime_lock, flags);
+ time_diff = xtime.tv_sec - pmac_get_rtc_time();
+ } while (read_seqretry_irqrestore(&xtime_lock, seq, flags));
+ break;
+ case PBOOK_WAKE:
+ write_seqlock_irqsave(&xtime_lock, flags);
+ xtime.tv_sec = pmac_get_rtc_time() + time_diff;
+ xtime.tv_nsec = 0;
+ last_rtc_update = xtime.tv_sec;
+ write_sequnlock_irqrestore(&xtime_lock, flags);
+ break;
+ }
+ return PBOOK_SLEEP_OK;
+}
+
+static struct pmu_sleep_notifier time_sleep_notifier __pmacdata = {
+ time_sleep_notify, SLEEP_LEVEL_MISC,
+};
+#endif /* CONFIG_PMAC_PBOOK */
+
+/*
+ * Query the OF and get the decr frequency.
+ * This was taken from the pmac time_init() when merging the prep/pmac
+ * time functions.
+ */
+void __init
+pmac_calibrate_decr(void)
+{
+ struct device_node *cpu;
+ unsigned int freq, *fp;
+
+#ifdef CONFIG_PMAC_PBOOK
+ pmu_register_sleep_notifier(&time_sleep_notifier);
+#endif /* CONFIG_PMAC_PBOOK */
+
+ /* We assume MacRISC2 machines have correct device-tree
+ * calibration. That's better since the VIA itself seems
+ * to be slightly off. --BenH
+ */
+ if (!machine_is_compatible("MacRISC2") &&
+ !machine_is_compatible("MacRISC3") &&
+ !machine_is_compatible("MacRISC4"))
+ if (via_calibrate_decr())
+ return;
+
+ /* Special case: QuickSilver G4s seem to have a badly calibrated
+ * timebase-frequency in OF, VIA is much better on these. We should
+ * probably implement calibration based on the KL timer on these
+ * machines anyway... -BenH
+ */
+ if (machine_is_compatible("PowerMac3,5"))
+ if (via_calibrate_decr())
+ return;
+ /*
+ * The cpu node should have a timebase-frequency property
+ * to tell us the rate at which the decrementer counts.
+ */
+ cpu = find_type_devices("cpu");
+ if (cpu == 0)
+ panic("can't find cpu node in time_init");
+ fp = (unsigned int *) get_property(cpu, "timebase-frequency", NULL);
+ if (fp == 0)
+ panic("can't get cpu timebase frequency");
+ freq = *fp;
+ printk("time_init: decrementer frequency = %u.%.6u MHz\n",
+ freq/1000000, freq%1000000);
+ tb_ticks_per_jiffy = freq / HZ;
+ tb_to_us = mulhwu_scale_factor(freq, 1000000);
+}
diff --git a/arch/ppc/platforms/powerpmc250.c b/arch/ppc/platforms/powerpmc250.c
new file mode 100644
index 0000000..0abe151
--- /dev/null
+++ b/arch/ppc/platforms/powerpmc250.c
@@ -0,0 +1,383 @@
+/*
+ * arch/ppc/platforms/powerpmc250.c
+ *
+ * Board setup routines for Force PowerPMC-250 Processor PMC
+ *
+ * Author: Troy Benjegerdes <tbenjegerdes@mvista.com>
+ * Borrowed heavily from prpmc750_*.c by
+ * Matt Porter <mporter@mvista.com>
+ *
+ * 2001 (c) MontaVista, Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+
+#include <linux/config.h>
+#include <linux/stddef.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/reboot.h>
+#include <linux/pci.h>
+#include <linux/kdev_t.h>
+#include <linux/types.h>
+#include <linux/major.h>
+#include <linux/initrd.h>
+#include <linux/console.h>
+#include <linux/delay.h>
+#include <linux/irq.h>
+#include <linux/slab.h>
+#include <linux/seq_file.h>
+#include <linux/ide.h>
+#include <linux/root_dev.h>
+
+#include <asm/byteorder.h>
+#include <asm/system.h>
+#include <asm/pgtable.h>
+#include <asm/page.h>
+#include <asm/dma.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/machdep.h>
+#include <asm/time.h>
+#include <platforms/powerpmc250.h>
+#include <asm/open_pic.h>
+#include <asm/pci-bridge.h>
+#include <asm/mpc10x.h>
+#include <asm/uaccess.h>
+#include <asm/bootinfo.h>
+
+extern void powerpmc250_find_bridges(void);
+extern unsigned long loops_per_jiffy;
+
+static u_char powerpmc250_openpic_initsenses[] __initdata =
+{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 1, /* PMC INTA (also MPC107 output interrupt INTA) */
+ 1, /* PMC INTB (also I82559 Ethernet controller) */
+ 1, /* PMC INTC */
+ 1, /* PMC INTD */
+ 0, /* DUART interrupt (active high) */
+};
+
+static int
+powerpmc250_show_cpuinfo(struct seq_file *m)
+{
+ seq_printf(m,"machine\t\t: Force PowerPMC250\n");
+
+ return 0;
+}
+
+static void __init
+powerpmc250_setup_arch(void)
+{
+ /* init to some ~sane value until calibrate_delay() runs */
+ loops_per_jiffy = 50000000/HZ;
+
+ /* Lookup PCI host bridges */
+ powerpmc250_find_bridges();
+
+#ifdef CONFIG_BLK_DEV_INITRD
+ if (initrd_start)
+ ROOT_DEV = Root_RAM0;
+ else
+#endif
+#ifdef CONFIG_ROOT_NFS
+ ROOT_DEV = Root_NFS;
+#else
+ ROOT_DEV = Root_SDA2;
+#endif
+
+ printk("Force PowerPMC250 port (C) 2001 MontaVista Software, Inc. (source@mvista.com)\n");
+}
+
+#if 0
+/*
+ * Compute the PrPMC750's bus speed using the baud clock as a
+ * reference.
+ */
+unsigned long __init powerpmc250_get_bus_speed(void)
+{
+ unsigned long tbl_start, tbl_end;
+ unsigned long current_state, old_state, bus_speed;
+ unsigned char lcr, dll, dlm;
+ int baud_divisor, count;
+
+ /* Read the UART's baud clock divisor */
+ lcr = readb(PRPMC750_SERIAL_0_LCR);
+ writeb(lcr | UART_LCR_DLAB, PRPMC750_SERIAL_0_LCR);
+ dll = readb(PRPMC750_SERIAL_0_DLL);
+ dlm = readb(PRPMC750_SERIAL_0_DLM);
+ writeb(lcr & ~UART_LCR_DLAB, PRPMC750_SERIAL_0_LCR);
+ baud_divisor = (dlm << 8) | dll;
+
+ /*
+ * Use the baud clock divisor and base baud clock
+ * to determine the baud rate and use that as
+ * the number of baud clock edges we use for
+ * the time base sample. Make it half the baud
+ * rate.
+ */
+ count = PRPMC750_BASE_BAUD / (baud_divisor * 16);
+
+ /* Find the first edge of the baud clock */
+ old_state = readb(PRPMC750_STATUS_REG) & PRPMC750_BAUDOUT_MASK;
+ do {
+ current_state = readb(PRPMC750_STATUS_REG) &
+ PRPMC750_BAUDOUT_MASK;
+ } while(old_state == current_state);
+
+ old_state = current_state;
+
+ /* Get the starting time base value */
+ tbl_start = get_tbl();
+
+ /*
+ * Loop until we have found a number of edges equal
+ * to half the count (half the baud rate)
+ */
+ do {
+ do {
+ current_state = readb(PRPMC750_STATUS_REG) &
+ PRPMC750_BAUDOUT_MASK;
+ } while(old_state == current_state);
+ old_state = current_state;
+ } while (--count);
+
+ /* Get the ending time base value */
+ tbl_end = get_tbl();
+
+ /* Compute bus speed */
+ bus_speed = (tbl_end-tbl_start)*128;
+
+ return bus_speed;
+}
+#endif
+
+static void __init
+powerpmc250_calibrate_decr(void)
+{
+ unsigned long freq;
+ int divisor = 4;
+
+ //freq = powerpmc250_get_bus_speed();
+#warning hardcoded bus freq
+ freq = 100000000;
+
+ tb_ticks_per_jiffy = freq / (HZ * divisor);
+ tb_to_us = mulhwu_scale_factor(freq/divisor, 1000000);
+}
+
+static void
+powerpmc250_restart(char *cmd)
+{
+ local_irq_disable();
+ /* Hard reset */
+ writeb(0x11, 0xfe000332);
+ while(1);
+}
+
+static void
+powerpmc250_halt(void)
+{
+ local_irq_disable();
+ while (1);
+}
+
+static void
+powerpmc250_power_off(void)
+{
+ powerpmc250_halt();
+}
+
+static void __init
+powerpmc250_init_IRQ(void)
+{
+
+ OpenPIC_InitSenses = powerpmc250_openpic_initsenses;
+ OpenPIC_NumInitSenses = sizeof(powerpmc250_openpic_initsenses);
+ mpc10x_set_openpic();
+}
+
+/*
+ * Set BAT 3 to map 0xf0000000 to end of physical memory space.
+ */
+static __inline__ void
+powerpmc250_set_bat(void)
+{
+ unsigned long bat3u, bat3l;
+ static int mapping_set = 0;
+
+ if (!mapping_set)
+ {
+ __asm__ __volatile__(
+ " lis %0,0xf000\n \
+ ori %1,%0,0x002a\n \
+ ori %0,%0,0x1ffe\n \
+ mtspr 0x21e,%0\n \
+ mtspr 0x21f,%1\n \
+ isync\n \
+ sync "
+ : "=r" (bat3u), "=r" (bat3l));
+
+ mapping_set = 1;
+ }
+ return;
+}
+
+static unsigned long __init
+powerpmc250_find_end_of_memory(void)
+{
+ /* Cover I/O space with a BAT */
+ /* yuck, better hope your ram size is a power of 2 -- paulus */
+ powerpmc250_set_bat();
+
+ return mpc10x_get_mem_size(MPC10X_MEM_MAP_B);
+}
+
+static void __init
+powerpmc250_map_io(void)
+{
+ io_block_mapping(0xfe000000, 0xfe000000, 0x02000000, _PAGE_IO);
+}
+
+void __init
+platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
+ unsigned long r6, unsigned long r7)
+{
+ parse_bootinfo(find_bootinfo());
+
+#ifdef CONFIG_BLK_DEV_INITRD
+ if ( r4 )
+ {
+ initrd_start = r4 + KERNELBASE;
+ initrd_end = r5 + KERNELBASE;
+ }
+#endif
+
+ /* Copy cmd_line parameters */
+ if ( r6)
+ {
+ *(char *)(r7 + KERNELBASE) = 0;
+ strcpy(cmd_line, (char *)(r6 + KERNELBASE));
+ }
+
+ isa_io_base = MPC10X_MAPB_ISA_IO_BASE;
+ isa_mem_base = MPC10X_MAPB_ISA_MEM_BASE;
+ pci_dram_offset = MPC10X_MAPB_DRAM_OFFSET;
+
+ ppc_md.setup_arch = powerpmc250_setup_arch;
+ ppc_md.show_cpuinfo = powerpmc250_show_cpuinfo;
+ ppc_md.init_IRQ = powerpmc250_init_IRQ;
+ ppc_md.get_irq = openpic_get_irq;
+
+ ppc_md.find_end_of_memory = powerpmc250_find_end_of_memory;
+ ppc_md.setup_io_mappings = powerpmc250_map_io;
+
+ ppc_md.restart = powerpmc250_restart;
+ ppc_md.power_off = powerpmc250_power_off;
+ ppc_md.halt = powerpmc250_halt;
+
+ /* PowerPMC250 has no timekeeper part */
+ ppc_md.time_init = NULL;
+ ppc_md.get_rtc_time = NULL;
+ ppc_md.set_rtc_time = NULL;
+ ppc_md.calibrate_decr = powerpmc250_calibrate_decr;
+}
+
+
+/*
+ * (This used to be arch/ppc/platforms/powerpmc250_pci.c)
+ *
+ * PCI support for Force PowerPMC250
+ *
+ */
+
+#undef DEBUG
+#ifdef DEBUG
+#define DBG(x...) printk(x)
+#else
+#define DBG(x...)
+#endif /* DEBUG */
+
+static inline int __init
+powerpmc250_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin)
+{
+ static char pci_irq_table[][4] =
+ /*
+ * PCI IDSEL/INTPIN->INTLINE
+ * A B C D
+ */
+ {
+ {17, 0, 0, 0}, /* Device 11 - 82559 */
+ {0, 0, 0, 0}, /* 12 */
+ {0, 0, 0, 0}, /* 13 */
+ {0, 0, 0, 0}, /* 14 */
+ {0, 0, 0, 0}, /* 15 */
+ {16, 17, 18, 19}, /* Device 16 - PMC A1?? */
+ };
+ const long min_idsel = 11, max_idsel = 16, irqs_per_slot = 4;
+ return PCI_IRQ_TABLE_LOOKUP;
+};
+
+static int
+powerpmc250_exclude_device(u_char bus, u_char devfn)
+{
+ /*
+ * While doing PCI Scan the MPC107 will 'detect' itself as
+ * device on the PCI Bus, will create an incorrect response and
+ * later will respond incorrectly to Configuration read coming
+ * from another device.
+ *
+ * The work around is that when doing a PCI Scan one
+ * should skip its own device number in the scan.
+ *
+ * The top IDsel is AD13 and the middle is AD14.
+ *
+ * -- Note from force
+ */
+
+ if ((bus == 0) && (PCI_SLOT(devfn) == 13 || PCI_SLOT(devfn) == 14)) {
+ return PCIBIOS_DEVICE_NOT_FOUND;
+ }
+ else {
+ return PCIBIOS_SUCCESSFUL;
+ }
+}
+
+void __init
+powerpmc250_find_bridges(void)
+{
+ struct pci_controller* hose;
+
+ hose = pcibios_alloc_controller();
+ if (!hose){
+ printk("Can't allocate PCI 'hose' structure!!!\n");
+ return;
+ }
+
+ hose->first_busno = 0;
+ hose->last_busno = 0xff;
+
+ if (mpc10x_bridge_init(hose,
+ MPC10X_MEM_MAP_B,
+ MPC10X_MEM_MAP_B,
+ MPC10X_MAPB_EUMB_BASE) == 0) {
+
+ hose->mem_resources[0].end = 0xffffffff;
+
+ hose->last_busno = pciauto_bus_scan(hose, hose->first_busno);
+
+ /* ppc_md.pcibios_fixup = pcore_pcibios_fixup; */
+ ppc_md.pci_swizzle = common_swizzle;
+
+ ppc_md.pci_exclude_device = powerpmc250_exclude_device;
+ ppc_md.pci_map_irq = powerpmc250_map_irq;
+ } else {
+ if (ppc_md.progress)
+ ppc_md.progress("Bridge init failed", 0x100);
+ printk("Host bridge init failed\n");
+ }
+
+}
diff --git a/arch/ppc/platforms/powerpmc250.h b/arch/ppc/platforms/powerpmc250.h
new file mode 100644
index 0000000..41a6dc8
--- /dev/null
+++ b/arch/ppc/platforms/powerpmc250.h
@@ -0,0 +1,52 @@
+/*
+ * include/asm-ppc/platforms/powerpmc250.h
+ *
+ * Definitions for Force PowerPMC-250 board support
+ *
+ * Author: Troy Benjegerdes <tbenjegerdes@mvista.com>
+ *
+ * Borrowed heavily from prpmc750.h by Matt Porter <mporter@mvista.com>
+ *
+ * 2001-2004 (c) MontaVista, Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+
+#ifndef __ASMPPC_POWERPMC250_H
+#define __ASMPPC_POWERPMC250_H
+
+#define POWERPMC250_PCI_CONFIG_ADDR 0x80000cf8
+#define POWERPMC250_PCI_CONFIG_DATA 0x80000cfc
+
+#define POWERPMC250_PCI_PHY_MEM_BASE 0xc0000000
+#define POWERPMC250_PCI_MEM_BASE 0xf0000000
+#define POWERPMC250_PCI_IO_BASE 0x80000000
+
+#define POWERPMC250_ISA_IO_BASE POWERPMC250_PCI_IO_BASE
+#define POWERPMC250_ISA_MEM_BASE POWERPMC250_PCI_MEM_BASE
+#define POWERPMC250_PCI_MEM_OFFSET POWERPMC250_PCI_PHY_MEM_BASE
+
+#define POWERPMC250_SYS_MEM_BASE 0x80000000
+
+#define POWERPMC250_HAWK_SMC_BASE 0xfef80000
+
+#define POWERPMC250_BASE_BAUD 12288000
+#define POWERPMC250_SERIAL 0xff000000
+#define POWERPMC250_SERIAL_IRQ 20
+
+/* UART Defines. */
+#define RS_TABLE_SIZE 1
+
+#define BASE_BAUD (POWERPMC250_BASE_BAUD / 16)
+
+#define STD_COM_FLAGS ASYNC_BOOT_AUTOCONF
+
+#define SERIAL_PORT_DFNS \
+ { 0, BASE_BAUD, POWERPMC250_SERIAL, POWERPMC250_SERIAL_IRQ, \
+ STD_COM_FLAGS, /* ttyS0 */ \
+ iomem_base: (u8 *)POWERPMC250_SERIAL, \
+ iomem_reg_shift: 0, \
+ io_type: SERIAL_IO_MEM }
+
+#endif /* __ASMPPC_POWERPMC250_H */
diff --git a/arch/ppc/platforms/pplus.c b/arch/ppc/platforms/pplus.c
new file mode 100644
index 0000000..65705c9
--- /dev/null
+++ b/arch/ppc/platforms/pplus.c
@@ -0,0 +1,917 @@
+/*
+ * arch/ppc/platforms/pplus.c
+ *
+ * Board and PCI setup routines for MCG PowerPlus
+ *
+ * Author: Randy Vinson <rvinson@mvista.com>
+ *
+ * Derived from original PowerPlus PReP work by
+ * Cort Dougan, Johnnie Peters, Matt Porter, and
+ * Troy Benjegerdes.
+ *
+ * 2001-2004 (c) MontaVista, Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/interrupt.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/console.h>
+#include <linux/pci.h>
+#include <linux/irq.h>
+#include <linux/ide.h>
+#include <linux/seq_file.h>
+#include <linux/root_dev.h>
+
+#include <asm/system.h>
+#include <asm/io.h>
+#include <asm/pgtable.h>
+#include <asm/dma.h>
+#include <asm/machdep.h>
+#include <asm/prep_nvram.h>
+#include <asm/vga.h>
+#include <asm/i8259.h>
+#include <asm/open_pic.h>
+#include <asm/hawk.h>
+#include <asm/todc.h>
+#include <asm/bootinfo.h>
+#include <asm/kgdb.h>
+#include <asm/reg.h>
+
+#include "pplus.h"
+
+#undef DUMP_DBATS
+
+TODC_ALLOC();
+
+extern void pplus_setup_hose(void);
+extern void pplus_set_VIA_IDE_native(void);
+
+extern unsigned long loops_per_jiffy;
+unsigned char *Motherboard_map_name;
+
+/* Tables for known hardware */
+
+/* Motorola Mesquite */
+static inline int
+mesquite_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin)
+{
+ static char pci_irq_table[][4] =
+ /*
+ * MPIC interrupts for various IDSEL values (MPIC IRQ0 =
+ * Linux IRQ16 (to leave room for ISA IRQs at 0-15).
+ * PCI IDSEL/INTPIN->INTLINE
+ * A B C D
+ */
+ {
+ {18, 0, 0, 0}, /* IDSEL 14 - Enet 0 */
+ { 0, 0, 0, 0}, /* IDSEL 15 - unused */
+ {19, 19, 19, 19}, /* IDSEL 16 - PMC Slot 1 */
+ { 0, 0, 0, 0}, /* IDSEL 17 - unused */
+ { 0, 0, 0, 0}, /* IDSEL 18 - unused */
+ { 0, 0, 0, 0}, /* IDSEL 19 - unused */
+ {24, 25, 26, 27}, /* IDSEL 20 - P2P bridge (to cPCI 1) */
+ { 0, 0, 0, 0}, /* IDSEL 21 - unused */
+ {28, 29, 30, 31} /* IDSEL 22 - P2P bridge (to cPCI 2) */
+ };
+
+ const long min_idsel = 14, max_idsel = 22, irqs_per_slot = 4;
+ return PCI_IRQ_TABLE_LOOKUP;
+}
+
+/* Motorola Sitka */
+static inline int
+sitka_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin)
+{
+ static char pci_irq_table[][4] =
+ /*
+ * MPIC interrupts for various IDSEL values (MPIC IRQ0 =
+ * Linux IRQ16 (to leave room for ISA IRQs at 0-15).
+ * PCI IDSEL/INTPIN->INTLINE
+ * A B C D
+ */
+ {
+ {18, 0, 0, 0}, /* IDSEL 14 - Enet 0 */
+ { 0, 0, 0, 0}, /* IDSEL 15 - unused */
+ {25, 26, 27, 28}, /* IDSEL 16 - PMC Slot 1 */
+ {28, 25, 26, 27}, /* IDSEL 17 - PMC Slot 2 */
+ { 0, 0, 0, 0}, /* IDSEL 18 - unused */
+ { 0, 0, 0, 0}, /* IDSEL 19 - unused */
+ {20, 0, 0, 0} /* IDSEL 20 - P2P bridge (to cPCI) */
+ };
+
+ const long min_idsel = 14, max_idsel = 20, irqs_per_slot = 4;
+ return PCI_IRQ_TABLE_LOOKUP;
+}
+
+/* Motorola MTX */
+static inline int
+MTX_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin)
+{
+ static char pci_irq_table[][4] =
+ /*
+ * MPIC interrupts for various IDSEL values (MPIC IRQ0 =
+ * Linux IRQ16 (to leave room for ISA IRQs at 0-15).
+ * PCI IDSEL/INTPIN->INTLINE
+ * A B C D
+ */
+ {
+ {19, 0, 0, 0}, /* IDSEL 12 - SCSI */
+ { 0, 0, 0, 0}, /* IDSEL 13 - unused */
+ {18, 0, 0, 0}, /* IDSEL 14 - Enet */
+ { 0, 0, 0, 0}, /* IDSEL 15 - unused */
+ {25, 26, 27, 28}, /* IDSEL 16 - PMC Slot 1 */
+ {26, 27, 28, 25}, /* IDSEL 17 - PMC Slot 2 */
+ {27, 28, 25, 26} /* IDSEL 18 - PCI Slot 3 */
+ };
+
+ const long min_idsel = 12, max_idsel = 18, irqs_per_slot = 4;
+ return PCI_IRQ_TABLE_LOOKUP;
+}
+
+/* Motorola MTX Plus */
+/* Secondary bus interrupt routing is not supported yet */
+static inline int
+MTXplus_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin)
+{
+ static char pci_irq_table[][4] =
+ /*
+ * MPIC interrupts for various IDSEL values (MPIC IRQ0 =
+ * Linux IRQ16 (to leave room for ISA IRQs at 0-15).
+ * PCI IDSEL/INTPIN->INTLINE
+ * A B C D
+ */
+ {
+ {19, 0, 0, 0}, /* IDSEL 12 - SCSI */
+ { 0, 0, 0, 0}, /* IDSEL 13 - unused */
+ {18, 0, 0, 0}, /* IDSEL 14 - Enet 1 */
+ { 0, 0, 0, 0}, /* IDSEL 15 - unused */
+ {25, 26, 27, 28}, /* IDSEL 16 - PCI Slot 1P */
+ {26, 27, 28, 25}, /* IDSEL 17 - PCI Slot 2P */
+ {27, 28, 25, 26}, /* IDSEL 18 - PCI Slot 3P */
+ {26, 0, 0, 0}, /* IDSEL 19 - Enet 2 */
+ { 0, 0, 0, 0} /* IDSEL 20 - P2P Bridge */
+ };
+
+ const long min_idsel = 12, max_idsel = 20, irqs_per_slot = 4;
+ return PCI_IRQ_TABLE_LOOKUP;
+}
+
+static inline int
+Genesis2_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin)
+{
+ /* 2600
+ * Raven 31
+ * ISA 11
+ * SCSI 12 - IRQ3
+ * Univ 13
+ * eth 14 - IRQ2
+ * VGA 15 - IRQ4
+ * PMC1 16 - IRQ9,10,11,12 = PMC1 A-D
+ * PMC2 17 - IRQ12,9,10,11 = A-D
+ * SCSI2 18 - IRQ11
+ * eth2 19 - IRQ10
+ * PCIX 20 - IRQ9,10,11,12 = PCI A-D
+ */
+
+ /* 2400
+ * Hawk 31
+ * ISA 11
+ * Univ 13
+ * eth 14 - IRQ2
+ * PMC1 16 - IRQ9,10,11,12 = PMC A-D
+ * PMC2 17 - IRQ12,9,10,11 = PMC A-D
+ * PCIX 20 - IRQ9,10,11,12 = PMC A-D
+ */
+
+ /* 2300
+ * Raven 31
+ * ISA 11
+ * Univ 13
+ * eth 14 - IRQ2
+ * PMC1 16 - 9,10,11,12 = A-D
+ * PMC2 17 - 9,10,11,12 = B,C,D,A
+ */
+
+ static char pci_irq_table[][4] =
+ /*
+ * MPIC interrupts for various IDSEL values (MPIC IRQ0 =
+ * Linux IRQ16 (to leave room for ISA IRQs at 0-15).
+ * PCI IDSEL/INTPIN->INTLINE
+ * A B C D
+ */
+ {
+ {19, 0, 0, 0}, /* IDSEL 12 - SCSI */
+ { 0, 0, 0, 0}, /* IDSEL 13 - Universe PCI - VME */
+ {18, 0, 0, 0}, /* IDSEL 14 - Enet 1 */
+ { 0, 0, 0, 0}, /* IDSEL 15 - unused */
+ {25, 26, 27, 28}, /* IDSEL 16 - PCI/PMC Slot 1P */
+ {28, 25, 26, 27}, /* IDSEL 17 - PCI/PMC Slot 2P */
+ {27, 28, 25, 26}, /* IDSEL 18 - PCI Slot 3P */
+ {26, 0, 0, 0}, /* IDSEL 19 - Enet 2 */
+ {25, 26, 27, 28} /* IDSEL 20 - P2P Bridge */
+ };
+
+ const long min_idsel = 12, max_idsel = 20, irqs_per_slot = 4;
+ return PCI_IRQ_TABLE_LOOKUP;
+}
+
+#define MOTOROLA_CPUTYPE_REG 0x800
+#define MOTOROLA_BASETYPE_REG 0x803
+#define MPIC_RAVEN_ID 0x48010000
+#define MPIC_HAWK_ID 0x48030000
+#define MOT_PROC2_BIT 0x800
+
+static u_char pplus_openpic_initsenses[] __initdata = {
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* MVME2600_INT_SIO */
+ (IRQ_SENSE_EDGE | IRQ_POLARITY_NEGATIVE),/*MVME2600_INT_FALCN_ECC_ERR */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),/*MVME2600_INT_PCI_ETHERNET */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* MVME2600_INT_PCI_SCSI */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),/*MVME2600_INT_PCI_GRAPHICS */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* MVME2600_INT_PCI_VME0 */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* MVME2600_INT_PCI_VME1 */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* MVME2600_INT_PCI_VME2 */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* MVME2600_INT_PCI_VME3 */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* MVME2600_INT_PCI_INTA */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* MVME2600_INT_PCI_INTB */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* MVME2600_INT_PCI_INTC */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* MVME2600_INT_PCI_INTD */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* MVME2600_INT_LM_SIG0 */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* MVME2600_INT_LM_SIG1 */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),
+};
+
+int mot_entry = -1;
+int prep_keybd_present = 1;
+int mot_multi = 0;
+
+struct brd_info {
+ /* 0x100 mask assumes for Raven and Hawk boards that the level/edge
+ * are set */
+ int cpu_type;
+ /* 0x200 if this board has a Hawk chip. */
+ int base_type;
+ /* or'ed with 0x80 if this board should be checked for multi CPU */
+ int max_cpu;
+ const char *name;
+ int (*map_irq) (struct pci_dev *, unsigned char, unsigned char);
+};
+struct brd_info mot_info[] = {
+ {0x300, 0x00, 0x00, "MVME 2400", Genesis2_map_irq},
+ {0x1E0, 0xE0, 0x00, "Mesquite cPCI (MCP750)", mesquite_map_irq},
+ {0x1E0, 0xE1, 0x00, "Sitka cPCI (MCPN750)", sitka_map_irq},
+ {0x1E0, 0xE2, 0x00, "Mesquite cPCI (MCP750) w/ HAC", mesquite_map_irq},
+ {0x1E0, 0xF6, 0x80, "MTX Plus", MTXplus_map_irq},
+ {0x1E0, 0xF6, 0x81, "Dual MTX Plus", MTXplus_map_irq},
+ {0x1E0, 0xF7, 0x80, "MTX wo/ Parallel Port", MTX_map_irq},
+ {0x1E0, 0xF7, 0x81, "Dual MTX wo/ Parallel Port", MTX_map_irq},
+ {0x1E0, 0xF8, 0x80, "MTX w/ Parallel Port", MTX_map_irq},
+ {0x1E0, 0xF8, 0x81, "Dual MTX w/ Parallel Port", MTX_map_irq},
+ {0x1E0, 0xF9, 0x00, "MVME 2300", Genesis2_map_irq},
+ {0x1E0, 0xFA, 0x00, "MVME 2300SC/2600", Genesis2_map_irq},
+ {0x1E0, 0xFB, 0x00, "MVME 2600 with MVME712M", Genesis2_map_irq},
+ {0x1E0, 0xFC, 0x00, "MVME 2600/2700 with MVME761", Genesis2_map_irq},
+ {0x1E0, 0xFD, 0x80, "MVME 3600 with MVME712M", Genesis2_map_irq},
+ {0x1E0, 0xFD, 0x81, "MVME 4600 with MVME712M", Genesis2_map_irq},
+ {0x1E0, 0xFE, 0x80, "MVME 3600 with MVME761", Genesis2_map_irq},
+ {0x1E0, 0xFE, 0x81, "MVME 4600 with MVME761", Genesis2_map_irq},
+ {0x000, 0x00, 0x00, "", NULL}
+};
+
+void __init pplus_set_board_type(void)
+{
+ unsigned char cpu_type;
+ unsigned char base_mod;
+ int entry;
+ unsigned short devid;
+ unsigned long *ProcInfo = NULL;
+
+ cpu_type = inb(MOTOROLA_CPUTYPE_REG) & 0xF0;
+ base_mod = inb(MOTOROLA_BASETYPE_REG);
+ early_read_config_word(0, 0, 0, PCI_VENDOR_ID, &devid);
+
+ for (entry = 0; mot_info[entry].cpu_type != 0; entry++) {
+ /* Check for Hawk chip */
+ if (mot_info[entry].cpu_type & 0x200) {
+ if (devid != PCI_DEVICE_ID_MOTOROLA_HAWK)
+ continue;
+ } else {
+ /* store the system config register for later use. */
+ ProcInfo =
+ (unsigned long *)ioremap(PPLUS_SYS_CONFIG_REG, 4);
+
+ /* Check non hawk boards */
+ if ((mot_info[entry].cpu_type & 0xff) != cpu_type)
+ continue;
+
+ if (mot_info[entry].base_type == 0) {
+ mot_entry = entry;
+ break;
+ }
+
+ if (mot_info[entry].base_type != base_mod)
+ continue;
+ }
+
+ if (!(mot_info[entry].max_cpu & 0x80)) {
+ mot_entry = entry;
+ break;
+ }
+
+ /* processor 1 not present and max processor zero indicated */
+ if ((*ProcInfo & MOT_PROC2_BIT)
+ && !(mot_info[entry].max_cpu & 0x7f)) {
+ mot_entry = entry;
+ break;
+ }
+
+ /* processor 1 present and max processor zero indicated */
+ if (!(*ProcInfo & MOT_PROC2_BIT)
+ && (mot_info[entry].max_cpu & 0x7f)) {
+ mot_entry = entry;
+ break;
+ }
+
+ /* Indicate to system if this is a multiprocessor board */
+ if (!(*ProcInfo & MOT_PROC2_BIT))
+ mot_multi = 1;
+ }
+
+ if (mot_entry == -1)
+ /* No particular cpu type found - assume Mesquite (MCP750) */
+ mot_entry = 1;
+
+ Motherboard_map_name = (unsigned char *)mot_info[mot_entry].name;
+ ppc_md.pci_map_irq = mot_info[mot_entry].map_irq;
+}
+void __init pplus_pib_init(void)
+{
+ unsigned char reg;
+ unsigned short short_reg;
+
+ struct pci_dev *dev = NULL;
+
+ /*
+ * Perform specific configuration for the Via Tech or
+ * or Winbond PCI-ISA-Bridge part.
+ */
+ if ((dev = pci_get_device(PCI_VENDOR_ID_VIA,
+ PCI_DEVICE_ID_VIA_82C586_1, dev))) {
+ /*
+ * PPCBUG does not set the enable bits
+ * for the IDE device. Force them on here.
+ */
+ pci_read_config_byte(dev, 0x40, ®);
+
+ reg |= 0x03; /* IDE: Chip Enable Bits */
+ pci_write_config_byte(dev, 0x40, reg);
+ }
+
+ if ((dev = pci_get_device(PCI_VENDOR_ID_VIA,
+ PCI_DEVICE_ID_VIA_82C586_2,
+ dev)) && (dev->devfn = 0x5a)) {
+ /* Force correct USB interrupt */
+ dev->irq = 11;
+ pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq);
+ }
+
+ if ((dev = pci_get_device(PCI_VENDOR_ID_WINBOND,
+ PCI_DEVICE_ID_WINBOND_83C553, dev))) {
+ /* Clear PCI Interrupt Routing Control Register. */
+ short_reg = 0x0000;
+ pci_write_config_word(dev, 0x44, short_reg);
+ /* Route IDE interrupts to IRQ 14 */
+ reg = 0xEE;
+ pci_write_config_byte(dev, 0x43, reg);
+ }
+
+ if ((dev = pci_get_device(PCI_VENDOR_ID_WINBOND,
+ PCI_DEVICE_ID_WINBOND_82C105, dev))) {
+ /*
+ * Disable LEGIRQ mode so PCI INTS are routed
+ * directly to the 8259 and enable both channels
+ */
+ pci_write_config_dword(dev, 0x40, 0x10ff0033);
+
+ /* Force correct IDE interrupt */
+ dev->irq = 14;
+ pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq);
+ }
+ pci_dev_put(dev);
+}
+
+void __init pplus_set_VIA_IDE_legacy(void)
+{
+ unsigned short vend, dev;
+
+ early_read_config_word(0, 0, PCI_DEVFN(0xb, 1), PCI_VENDOR_ID, &vend);
+ early_read_config_word(0, 0, PCI_DEVFN(0xb, 1), PCI_DEVICE_ID, &dev);
+
+ if ((vend == PCI_VENDOR_ID_VIA) &&
+ (dev == PCI_DEVICE_ID_VIA_82C586_1)) {
+ unsigned char temp;
+
+ /* put back original "standard" port base addresses */
+ early_write_config_dword(0, 0, PCI_DEVFN(0xb, 1),
+ PCI_BASE_ADDRESS_0, 0x1f1);
+ early_write_config_dword(0, 0, PCI_DEVFN(0xb, 1),
+ PCI_BASE_ADDRESS_1, 0x3f5);
+ early_write_config_dword(0, 0, PCI_DEVFN(0xb, 1),
+ PCI_BASE_ADDRESS_2, 0x171);
+ early_write_config_dword(0, 0, PCI_DEVFN(0xb, 1),
+ PCI_BASE_ADDRESS_3, 0x375);
+ early_write_config_dword(0, 0, PCI_DEVFN(0xb, 1),
+ PCI_BASE_ADDRESS_4, 0xcc01);
+
+ /* put into legacy mode */
+ early_read_config_byte(0, 0, PCI_DEVFN(0xb, 1), PCI_CLASS_PROG,
+ &temp);
+ temp &= ~0x05;
+ early_write_config_byte(0, 0, PCI_DEVFN(0xb, 1), PCI_CLASS_PROG,
+ temp);
+ }
+}
+
+void pplus_set_VIA_IDE_native(void)
+{
+ unsigned short vend, dev;
+
+ early_read_config_word(0, 0, PCI_DEVFN(0xb, 1), PCI_VENDOR_ID, &vend);
+ early_read_config_word(0, 0, PCI_DEVFN(0xb, 1), PCI_DEVICE_ID, &dev);
+
+ if ((vend == PCI_VENDOR_ID_VIA) &&
+ (dev == PCI_DEVICE_ID_VIA_82C586_1)) {
+ unsigned char temp;
+
+ /* put into native mode */
+ early_read_config_byte(0, 0, PCI_DEVFN(0xb, 1), PCI_CLASS_PROG,
+ &temp);
+ temp |= 0x05;
+ early_write_config_byte(0, 0, PCI_DEVFN(0xb, 1), PCI_CLASS_PROG,
+ temp);
+ }
+}
+
+void __init pplus_pcibios_fixup(void)
+{
+
+ unsigned char reg;
+ unsigned short devid;
+ unsigned char base_mod;
+
+ printk(KERN_INFO "Setting PCI interrupts for a \"%s\"\n",
+ Motherboard_map_name);
+
+ /* Setup the Winbond or Via PIB */
+ pplus_pib_init();
+
+ /* Set up floppy in PS/2 mode */
+ outb(0x09, SIO_CONFIG_RA);
+ reg = inb(SIO_CONFIG_RD);
+ reg = (reg & 0x3F) | 0x40;
+ outb(reg, SIO_CONFIG_RD);
+ outb(reg, SIO_CONFIG_RD); /* Have to write twice to change! */
+
+ /* This is a hack. If this is a 2300 or 2400 mot board then there is
+ * no keyboard controller and we have to indicate that.
+ */
+
+ early_read_config_word(0, 0, 0, PCI_VENDOR_ID, &devid);
+ base_mod = inb(MOTOROLA_BASETYPE_REG);
+ if ((devid == PCI_DEVICE_ID_MOTOROLA_HAWK) ||
+ (base_mod == 0xF9) || (base_mod == 0xFA) || (base_mod == 0xE1))
+ prep_keybd_present = 0;
+}
+
+void __init pplus_find_bridges(void)
+{
+ struct pci_controller *hose;
+
+ hose = pcibios_alloc_controller();
+ if (!hose)
+ return;
+
+ hose->first_busno = 0;
+ hose->last_busno = 0xff;
+
+ hose->pci_mem_offset = PREP_ISA_MEM_BASE;
+ hose->io_base_virt = (void *)PREP_ISA_IO_BASE;
+
+ pci_init_resource(&hose->io_resource, PPLUS_PCI_IO_START,
+ PPLUS_PCI_IO_END, IORESOURCE_IO, "PCI host bridge");
+ pci_init_resource(&hose->mem_resources[0], PPLUS_PROC_PCI_MEM_START,
+ PPLUS_PROC_PCI_MEM_END, IORESOURCE_MEM,
+ "PCI host bridge");
+
+ hose->io_space.start = PPLUS_PCI_IO_START;
+ hose->io_space.end = PPLUS_PCI_IO_END;
+ hose->mem_space.start = PPLUS_PCI_MEM_START;
+ hose->mem_space.end = PPLUS_PCI_MEM_END - HAWK_MPIC_SIZE;
+
+ if (hawk_init(hose, PPLUS_HAWK_PPC_REG_BASE, PPLUS_PROC_PCI_MEM_START,
+ PPLUS_PROC_PCI_MEM_END - HAWK_MPIC_SIZE,
+ PPLUS_PROC_PCI_IO_START, PPLUS_PROC_PCI_IO_END,
+ PPLUS_PROC_PCI_MEM_END - HAWK_MPIC_SIZE + 1)
+ != 0) {
+ printk(KERN_CRIT "Could not initialize host bridge\n");
+
+ }
+
+ pplus_set_VIA_IDE_legacy();
+
+ hose->last_busno = pciauto_bus_scan(hose, hose->first_busno);
+
+ ppc_md.pcibios_fixup = pplus_pcibios_fixup;
+ ppc_md.pci_swizzle = common_swizzle;
+}
+
+static int pplus_show_cpuinfo(struct seq_file *m)
+{
+ seq_printf(m, "vendor\t\t: Motorola MCG\n");
+ seq_printf(m, "machine\t\t: %s\n", Motherboard_map_name);
+
+ return 0;
+}
+
+static void __init pplus_setup_arch(void)
+{
+ struct pci_controller *hose;
+
+ if (ppc_md.progress)
+ ppc_md.progress("pplus_setup_arch: enter", 0);
+
+ /* init to some ~sane value until calibrate_delay() runs */
+ loops_per_jiffy = 50000000;
+
+ if (ppc_md.progress)
+ ppc_md.progress("pplus_setup_arch: find_bridges", 0);
+
+ /* Setup PCI host bridge */
+ pplus_find_bridges();
+
+ hose = pci_bus_to_hose(0);
+ isa_io_base = (ulong) hose->io_base_virt;
+
+ if (ppc_md.progress)
+ ppc_md.progress("pplus_setup_arch: set_board_type", 0);
+
+ pplus_set_board_type();
+
+ /* Enable L2. Assume we don't need to flush -- Cort */
+ *(unsigned char *)(PPLUS_L2_CONTROL_REG) |= 3;
+
+#ifdef CONFIG_BLK_DEV_INITRD
+ if (initrd_start)
+ ROOT_DEV = Root_RAM0;
+ else
+#endif
+#ifdef CONFIG_ROOT_NFS
+ ROOT_DEV = Root_NFS;
+#else
+ ROOT_DEV = Root_SDA2;
+#endif
+
+ printk(KERN_INFO "Motorola PowerPlus Platform\n");
+ printk(KERN_INFO
+ "Port by MontaVista Software, Inc. (source@mvista.com)\n");
+
+#ifdef CONFIG_VGA_CONSOLE
+ /* remap the VGA memory */
+ vgacon_remap_base = (unsigned long)ioremap(PPLUS_ISA_MEM_BASE,
+ 0x08000000);
+ conswitchp = &vga_con;
+#endif
+#ifdef CONFIG_PPCBUG_NVRAM
+ /* Read in NVRAM data */
+ init_prep_nvram();
+
+ /* if no bootargs, look in NVRAM */
+ if (cmd_line[0] == '\0') {
+ char *bootargs;
+ bootargs = prep_nvram_get_var("bootargs");
+ if (bootargs != NULL) {
+ strcpy(cmd_line, bootargs);
+ /* again.. */
+ strcpy(saved_command_line, cmd_line);
+ }
+ }
+#endif
+ if (ppc_md.progress)
+ ppc_md.progress("pplus_setup_arch: exit", 0);
+}
+
+static void pplus_restart(char *cmd)
+{
+ unsigned long i = 10000;
+
+ local_irq_disable();
+
+ /* set VIA IDE controller into native mode */
+ pplus_set_VIA_IDE_native();
+
+ /* set exception prefix high - to the prom */
+ _nmask_and_or_msr(0, MSR_IP);
+
+ /* make sure bit 0 (reset) is a 0 */
+ outb(inb(0x92) & ~1L, 0x92);
+ /* signal a reset to system control port A - soft reset */
+ outb(inb(0x92) | 1, 0x92);
+
+ while (i != 0)
+ i++;
+ panic("restart failed\n");
+}
+
+static void pplus_halt(void)
+{
+ /* set exception prefix high - to the prom */
+ _nmask_and_or_msr(MSR_EE, MSR_IP);
+
+ /* make sure bit 0 (reset) is a 0 */
+ outb(inb(0x92) & ~1L, 0x92);
+ /* signal a reset to system control port A - soft reset */
+ outb(inb(0x92) | 1, 0x92);
+
+ while (1) ;
+ /*
+ * Not reached
+ */
+}
+
+static void pplus_power_off(void)
+{
+ pplus_halt();
+}
+
+static unsigned int pplus_irq_canonicalize(u_int irq)
+{
+ if (irq == 2)
+ return 9;
+ else
+ return irq;
+}
+
+static void __init pplus_init_IRQ(void)
+{
+ int i;
+
+ if (ppc_md.progress)
+ ppc_md.progress("init_irq: enter", 0);
+
+ OpenPIC_InitSenses = pplus_openpic_initsenses;
+ OpenPIC_NumInitSenses = sizeof(pplus_openpic_initsenses);
+
+ if (OpenPIC_Addr != NULL) {
+
+ openpic_set_sources(0, 16, OpenPIC_Addr + 0x10000);
+ openpic_init(NUM_8259_INTERRUPTS);
+ openpic_hookup_cascade(NUM_8259_INTERRUPTS, "82c59 cascade",
+ i8259_irq);
+ ppc_md.get_irq = openpic_get_irq;
+ }
+
+ for (i = 0; i < NUM_8259_INTERRUPTS; i++)
+ irq_desc[i].handler = &i8259_pic;
+
+ i8259_init(0);
+
+ if (ppc_md.progress)
+ ppc_md.progress("init_irq: exit", 0);
+}
+
+#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
+/*
+ * IDE stuff.
+ */
+static int pplus_ide_default_irq(unsigned long base)
+{
+ switch (base) {
+ case 0x1f0:
+ return 14;
+ case 0x170:
+ return 15;
+ default:
+ return 0;
+ }
+}
+
+static unsigned long pplus_ide_default_io_base(int index)
+{
+ switch (index) {
+ case 0:
+ return 0x1f0;
+ case 1:
+ return 0x170;
+ default:
+ return 0;
+ }
+}
+
+static void __init
+pplus_ide_init_hwif_ports(hw_regs_t * hw, unsigned long data_port,
+ unsigned long ctrl_port, int *irq)
+{
+ unsigned long reg = data_port;
+ int i;
+
+ for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) {
+ hw->io_ports[i] = reg;
+ reg += 1;
+ }
+
+ if (ctrl_port)
+ hw->io_ports[IDE_CONTROL_OFFSET] = ctrl_port;
+ else
+ hw->io_ports[IDE_CONTROL_OFFSET] =
+ hw->io_ports[IDE_DATA_OFFSET] + 0x206;
+
+ if (irq != NULL)
+ *irq = pplus_ide_default_irq(data_port);
+}
+#endif
+
+#ifdef CONFIG_SMP
+/* PowerPlus (MTX) support */
+static int __init smp_pplus_probe(void)
+{
+ extern int mot_multi;
+
+ if (mot_multi) {
+ openpic_request_IPIs();
+ smp_hw_index[1] = 1;
+ return 2;
+ }
+
+ return 1;
+}
+
+static void __init smp_pplus_kick_cpu(int nr)
+{
+ *(unsigned long *)KERNELBASE = nr;
+ asm volatile ("dcbf 0,%0"::"r" (KERNELBASE):"memory");
+ printk(KERN_INFO "CPU1 reset, waiting\n");
+}
+
+static void __init smp_pplus_setup_cpu(int cpu_nr)
+{
+ if (OpenPIC_Addr)
+ do_openpic_setup_cpu();
+}
+
+static struct smp_ops_t pplus_smp_ops = {
+ smp_openpic_message_pass,
+ smp_pplus_probe,
+ smp_pplus_kick_cpu,
+ smp_pplus_setup_cpu,
+ .give_timebase = smp_generic_give_timebase,
+ .take_timebase = smp_generic_take_timebase,
+};
+#endif /* CONFIG_SMP */
+
+#ifdef DUMP_DBATS
+static void print_dbat(int idx, u32 bat)
+{
+
+ char str[64];
+
+ sprintf(str, "DBAT%c%c = 0x%08x\n",
+ (char)((idx - DBAT0U) / 2) + '0', (idx & 1) ? 'L' : 'U', bat);
+ ppc_md.progress(str, 0);
+}
+
+#define DUMP_DBAT(x) \
+ do { \
+ u32 __temp = mfspr(x);\
+ print_dbat(x, __temp); \
+ } while (0)
+
+static void dump_dbats(void)
+{
+ if (ppc_md.progress) {
+ DUMP_DBAT(DBAT0U);
+ DUMP_DBAT(DBAT0L);
+ DUMP_DBAT(DBAT1U);
+ DUMP_DBAT(DBAT1L);
+ DUMP_DBAT(DBAT2U);
+ DUMP_DBAT(DBAT2L);
+ DUMP_DBAT(DBAT3U);
+ DUMP_DBAT(DBAT3L);
+ }
+}
+#endif
+
+static unsigned long __init pplus_find_end_of_memory(void)
+{
+ unsigned long total;
+
+ if (ppc_md.progress)
+ ppc_md.progress("pplus_find_end_of_memory", 0);
+
+#ifdef DUMP_DBATS
+ dump_dbats();
+#endif
+
+ total = hawk_get_mem_size(PPLUS_HAWK_SMC_BASE);
+ return (total);
+}
+
+static void __init pplus_map_io(void)
+{
+ io_block_mapping(PPLUS_ISA_IO_BASE, PPLUS_ISA_IO_BASE, 0x10000000,
+ _PAGE_IO);
+ io_block_mapping(0xfef80000, 0xfef80000, 0x00080000, _PAGE_IO);
+}
+
+static void __init pplus_init2(void)
+{
+#ifdef CONFIG_NVRAM
+ request_region(PREP_NVRAM_AS0, 0x8, "nvram");
+#endif
+ request_region(0x20, 0x20, "pic1");
+ request_region(0xa0, 0x20, "pic2");
+ request_region(0x00, 0x20, "dma1");
+ request_region(0x40, 0x20, "timer");
+ request_region(0x80, 0x10, "dma page reg");
+ request_region(0xc0, 0x20, "dma2");
+}
+
+/*
+ * Set BAT 2 to access 0x8000000 so progress messages will work and set BAT 3
+ * to 0xf0000000 to access Falcon/Raven or Hawk registers
+ */
+static __inline__ void pplus_set_bat(void)
+{
+ /* wait for all outstanding memory accesses to complete */
+ mb();
+
+ /* setup DBATs */
+ mtspr(SPRN_DBAT2U, 0x80001ffe);
+ mtspr(SPRN_DBAT2L, 0x8000002a);
+ mtspr(SPRN_DBAT3U, 0xf0001ffe);
+ mtspr(SPRN_DBAT3L, 0xf000002a);
+
+ /* wait for updates */
+ mb();
+}
+
+void __init
+platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
+ unsigned long r6, unsigned long r7)
+{
+ parse_bootinfo(find_bootinfo());
+
+ /* Map in board regs, etc. */
+ pplus_set_bat();
+
+ isa_io_base = PREP_ISA_IO_BASE;
+ isa_mem_base = PREP_ISA_MEM_BASE;
+ pci_dram_offset = PREP_PCI_DRAM_OFFSET;
+ ISA_DMA_THRESHOLD = 0x00ffffff;
+ DMA_MODE_READ = 0x44;
+ DMA_MODE_WRITE = 0x48;
+
+ ppc_md.setup_arch = pplus_setup_arch;
+ ppc_md.show_cpuinfo = pplus_show_cpuinfo;
+ ppc_md.irq_canonicalize = pplus_irq_canonicalize;
+ ppc_md.init_IRQ = pplus_init_IRQ;
+ /* this gets changed later on if we have an OpenPIC -- Cort */
+ ppc_md.get_irq = i8259_irq;
+ ppc_md.init = pplus_init2;
+
+ ppc_md.restart = pplus_restart;
+ ppc_md.power_off = pplus_power_off;
+ ppc_md.halt = pplus_halt;
+
+ TODC_INIT(TODC_TYPE_MK48T59, PREP_NVRAM_AS0, PREP_NVRAM_AS1,
+ PREP_NVRAM_DATA, 8);
+
+ ppc_md.time_init = todc_time_init;
+ ppc_md.set_rtc_time = todc_set_rtc_time;
+ ppc_md.get_rtc_time = todc_get_rtc_time;
+ ppc_md.calibrate_decr = todc_calibrate_decr;
+ ppc_md.nvram_read_val = todc_m48txx_read_val;
+ ppc_md.nvram_write_val = todc_m48txx_write_val;
+
+ ppc_md.find_end_of_memory = pplus_find_end_of_memory;
+ ppc_md.setup_io_mappings = pplus_map_io;
+
+#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
+ ppc_ide_md.default_irq = pplus_ide_default_irq;
+ ppc_ide_md.default_io_base = pplus_ide_default_io_base;
+ ppc_ide_md.ide_init_hwif = pplus_ide_init_hwif_ports;
+#endif
+
+#ifdef CONFIG_SERIAL_TEXT_DEBUG
+ ppc_md.progress = gen550_progress;
+#endif /* CONFIG_SERIAL_TEXT_DEBUG */
+#ifdef CONFIG_KGDB
+ ppc_md.kgdb_map_scc = gen550_kgdb_map_scc;
+#endif
+#ifdef CONFIG_SMP
+ ppc_md.smp_ops = &pplus_smp_ops;
+#endif /* CONFIG_SMP */
+}
diff --git a/arch/ppc/platforms/pplus.h b/arch/ppc/platforms/pplus.h
new file mode 100644
index 0000000..90f0cb2
--- /dev/null
+++ b/arch/ppc/platforms/pplus.h
@@ -0,0 +1,67 @@
+/*
+ * arch/ppc/platforms/pplus.h
+ *
+ * Definitions for Motorola MCG Falcon/Raven & HAWK North Bridge & Memory ctlr.
+ *
+ * Author: Mark A. Greerinclude/asm-ppc/hawk.h
+ * mgreer@mvista.com
+ *
+ * Modified by Randy Vinson (rvinson@mvista.com)
+ *
+ * 2001-2004 (c) MontaVista, Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+
+#ifndef __PPC_PPLUS_H
+#define __PPC_PPLUS_H
+
+#include <asm/io.h>
+
+/*
+ * Due to limiations imposed by legacy hardware (primaryily IDE controllers),
+ * the PPLUS boards operate using a PReP address map.
+ *
+ * From Processor (physical) -> PCI:
+ * PCI Mem Space: 0xc0000000 - 0xfe000000 -> 0x00000000 - 0x3e000000 (768 MB)
+ * PCI I/O Space: 0x80000000 - 0x90000000 -> 0x00000000 - 0x10000000 (256 MB)
+ * Note: Must skip 0xfe000000-0xfe400000 for CONFIG_HIGHMEM/PKMAP area
+ *
+ * From PCI -> Processor (physical):
+ * System Memory: 0x80000000 -> 0x00000000
+ */
+
+#define PPLUS_ISA_MEM_BASE PREP_ISA_MEM_BASE
+#define PPLUS_ISA_IO_BASE PREP_ISA_IO_BASE
+
+/* PCI Memory space mapping info */
+#define PPLUS_PCI_MEM_SIZE 0x30000000U
+#define PPLUS_PROC_PCI_MEM_START PPLUS_ISA_MEM_BASE
+#define PPLUS_PROC_PCI_MEM_END (PPLUS_PROC_PCI_MEM_START + \
+ PPLUS_PCI_MEM_SIZE - 1)
+#define PPLUS_PCI_MEM_START 0x00000000U
+#define PPLUS_PCI_MEM_END (PPLUS_PCI_MEM_START + \
+ PPLUS_PCI_MEM_SIZE - 1)
+
+/* PCI I/O space mapping info */
+#define PPLUS_PCI_IO_SIZE 0x10000000U
+#define PPLUS_PROC_PCI_IO_START PPLUS_ISA_IO_BASE
+#define PPLUS_PROC_PCI_IO_END (PPLUS_PROC_PCI_IO_START + \
+ PPLUS_PCI_IO_SIZE - 1)
+#define PPLUS_PCI_IO_START 0x00000000U
+#define PPLUS_PCI_IO_END (PPLUS_PCI_IO_START + \
+ PPLUS_PCI_IO_SIZE - 1)
+/* System memory mapping info */
+#define PPLUS_PCI_DRAM_OFFSET PREP_PCI_DRAM_OFFSET
+#define PPLUS_PCI_PHY_MEM_OFFSET (PPLUS_ISA_MEM_BASE-PPLUS_PCI_MEM_START)
+
+/* Define base addresses for important sets of registers */
+#define PPLUS_HAWK_SMC_BASE 0xfef80000U
+#define PPLUS_HAWK_PPC_REG_BASE 0xfeff0000U
+#define PPLUS_SYS_CONFIG_REG 0xfef80400U
+#define PPLUS_L2_CONTROL_REG 0x8000081cU
+
+#define PPLUS_VGA_MEM_BASE 0xf0000000U
+
+#endif /* __PPC_PPLUS_H */
diff --git a/arch/ppc/platforms/pq2ads.c b/arch/ppc/platforms/pq2ads.c
new file mode 100644
index 0000000..6a1475c
--- /dev/null
+++ b/arch/ppc/platforms/pq2ads.c
@@ -0,0 +1,26 @@
+/*
+ * arch/ppc/platforms/pq2ads.c
+ *
+ * PQ2ADS platform support
+ *
+ * Author: Kumar Gala <kumar.gala@freescale.com>
+ * Derived from: est8260_setup.c by Allen Curtis
+ *
+ * Copyright 2004 Freescale Semiconductor, Inc.
+ *
+ * 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.
+ */
+
+#include <linux/init.h>
+
+#include <asm/mpc8260.h>
+
+void __init
+m82xx_board_setup(void)
+{
+ /* Enable the 2nd UART port */
+ *(volatile uint *)(BCSR_ADDR + 4) &= ~BCSR1_RS232_EN2;
+}
diff --git a/arch/ppc/platforms/pq2ads.h b/arch/ppc/platforms/pq2ads.h
new file mode 100644
index 0000000..cf5e5dd
--- /dev/null
+++ b/arch/ppc/platforms/pq2ads.h
@@ -0,0 +1,96 @@
+/*
+ * A collection of structures, addresses, and values associated with
+ * the Motorola MPC8260ADS/MPC8266ADS-PCI boards.
+ * Copied from the RPX-Classic and SBS8260 stuff.
+ *
+ * Copyright (c) 2001 Dan Malek (dan@mvista.com)
+ */
+#ifdef __KERNEL__
+#ifndef __MACH_ADS8260_DEFS
+#define __MACH_ADS8260_DEFS
+
+#include <linux/config.h>
+
+#include <asm/ppcboot.h>
+
+/* Memory map is configured by the PROM startup.
+ * We just map a few things we need. The CSR is actually 4 byte-wide
+ * registers that can be accessed as 8-, 16-, or 32-bit values.
+ */
+#define CPM_MAP_ADDR ((uint)0xf0000000)
+#define BCSR_ADDR ((uint)0xf4500000)
+#define BCSR_SIZE ((uint)(32 * 1024))
+
+#define BOOTROM_RESTART_ADDR ((uint)0xff000104)
+
+/* For our show_cpuinfo hooks. */
+#define CPUINFO_VENDOR "Motorola"
+#define CPUINFO_MACHINE "PQ2 ADS PowerPC"
+
+/* The ADS8260 has 16, 32-bit wide control/status registers, accessed
+ * only on word boundaries.
+ * Not all are used (yet), or are interesting to us (yet).
+ */
+
+/* Things of interest in the CSR.
+*/
+#define BCSR0_LED0 ((uint)0x02000000) /* 0 == on */
+#define BCSR0_LED1 ((uint)0x01000000) /* 0 == on */
+#define BCSR1_FETHIEN ((uint)0x08000000) /* 0 == enable */
+#define BCSR1_FETH_RST ((uint)0x04000000) /* 0 == reset */
+#define BCSR1_RS232_EN1 ((uint)0x02000000) /* 0 == enable */
+#define BCSR1_RS232_EN2 ((uint)0x01000000) /* 0 == enable */
+#define BCSR3_FETHIEN2 ((uint)0x10000000) /* 0 == enable */
+#define BCSR3_FETH2_RST ((uint)0x80000000) /* 0 == reset */
+
+#define PHY_INTERRUPT SIU_INT_IRQ7
+
+#ifdef CONFIG_PCI
+/* PCI interrupt controller */
+#define PCI_INT_STAT_REG 0xF8200000
+#define PCI_INT_MASK_REG 0xF8200004
+#define PIRQA (NR_SIU_INTS + 0)
+#define PIRQB (NR_SIU_INTS + 1)
+#define PIRQC (NR_SIU_INTS + 2)
+#define PIRQD (NR_SIU_INTS + 3)
+
+/*
+ * PCI memory map definitions for MPC8266ADS-PCI.
+ *
+ * processor view
+ * local address PCI address target
+ * 0x80000000-0x9FFFFFFF 0x80000000-0x9FFFFFFF PCI mem with prefetch
+ * 0xA0000000-0xBFFFFFFF 0xA0000000-0xBFFFFFFF PCI mem w/o prefetch
+ * 0xF4000000-0xF7FFFFFF 0x00000000-0x03FFFFFF PCI IO
+ *
+ * PCI master view
+ * local address PCI address target
+ * 0x00000000-0x1FFFFFFF 0x00000000-0x1FFFFFFF MPC8266 local memory
+ */
+
+/* window for a PCI master to access MPC8266 memory */
+#define PCI_SLV_MEM_LOCAL 0x00000000 /* Local base */
+#define PCI_SLV_MEM_BUS 0x00000000 /* PCI base */
+
+/* window for the processor to access PCI memory with prefetching */
+#define PCI_MSTR_MEM_LOCAL 0x80000000 /* Local base */
+#define PCI_MSTR_MEM_BUS 0x80000000 /* PCI base */
+#define PCI_MSTR_MEM_SIZE 0x20000000 /* 512MB */
+
+/* window for the processor to access PCI memory without prefetching */
+#define PCI_MSTR_MEMIO_LOCAL 0xA0000000 /* Local base */
+#define PCI_MSTR_MEMIO_BUS 0xA0000000 /* PCI base */
+#define PCI_MSTR_MEMIO_SIZE 0x20000000 /* 512MB */
+
+/* window for the processor to access PCI I/O */
+#define PCI_MSTR_IO_LOCAL 0xF4000000 /* Local base */
+#define PCI_MSTR_IO_BUS 0x00000000 /* PCI base */
+#define PCI_MSTR_IO_SIZE 0x04000000 /* 64MB */
+
+#define _IO_BASE PCI_MSTR_IO_LOCAL
+#define _ISA_MEM_BASE PCI_MSTR_MEMIO_LOCAL
+#define PCI_DRAM_OFFSET PCI_SLV_MEM_BUS
+#endif /* CONFIG_PCI */
+
+#endif /* __MACH_ADS8260_DEFS */
+#endif /* __KERNEL__ */
diff --git a/arch/ppc/platforms/prep_pci.c b/arch/ppc/platforms/prep_pci.c
new file mode 100644
index 0000000..8cd80eb
--- /dev/null
+++ b/arch/ppc/platforms/prep_pci.c
@@ -0,0 +1,1336 @@
+/*
+ * PReP pci functions.
+ * Originally by Gary Thomas
+ * rewritten and updated by Cort Dougan (cort@cs.nmt.edu)
+ *
+ * The motherboard routes/maps will disappear shortly. -- Cort
+ */
+
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+
+#include <asm/sections.h>
+#include <asm/byteorder.h>
+#include <asm/io.h>
+#include <asm/ptrace.h>
+#include <asm/prom.h>
+#include <asm/pci-bridge.h>
+#include <asm/residual.h>
+#include <asm/irq.h>
+#include <asm/machdep.h>
+#include <asm/open_pic.h>
+
+extern void (*setup_ibm_pci)(char *irq_lo, char *irq_hi);
+
+/* Which PCI interrupt line does a given device [slot] use? */
+/* Note: This really should be two dimensional based in slot/pin used */
+static unsigned char *Motherboard_map;
+unsigned char *Motherboard_map_name;
+
+/* How is the 82378 PIRQ mapping setup? */
+static unsigned char *Motherboard_routes;
+
+static void (*Motherboard_non0)(struct pci_dev *);
+
+static void Powerplus_Map_Non0(struct pci_dev *);
+
+/* Used for Motorola to store system config register */
+static unsigned long *ProcInfo;
+
+/* Tables for known hardware */
+
+/* Motorola PowerStackII - Utah */
+static char Utah_pci_IRQ_map[23] __prepdata =
+{
+ 0, /* Slot 0 - unused */
+ 0, /* Slot 1 - unused */
+ 5, /* Slot 2 - SCSI - NCR825A */
+ 0, /* Slot 3 - unused */
+ 3, /* Slot 4 - Ethernet - DEC2114x */
+ 0, /* Slot 5 - unused */
+ 2, /* Slot 6 - PCI Card slot #1 */
+ 3, /* Slot 7 - PCI Card slot #2 */
+ 5, /* Slot 8 - PCI Card slot #3 */
+ 5, /* Slot 9 - PCI Bridge */
+ /* added here in case we ever support PCI bridges */
+ /* Secondary PCI bus cards are at slot-9,6 & slot-9,7 */
+ 0, /* Slot 10 - unused */
+ 0, /* Slot 11 - unused */
+ 5, /* Slot 12 - SCSI - NCR825A */
+ 0, /* Slot 13 - unused */
+ 3, /* Slot 14 - enet */
+ 0, /* Slot 15 - unused */
+ 2, /* Slot 16 - unused */
+ 3, /* Slot 17 - unused */
+ 5, /* Slot 18 - unused */
+ 0, /* Slot 19 - unused */
+ 0, /* Slot 20 - unused */
+ 0, /* Slot 21 - unused */
+ 0, /* Slot 22 - unused */
+};
+
+static char Utah_pci_IRQ_routes[] __prepdata =
+{
+ 0, /* Line 0 - Unused */
+ 9, /* Line 1 */
+ 10, /* Line 2 */
+ 11, /* Line 3 */
+ 14, /* Line 4 */
+ 15, /* Line 5 */
+};
+
+/* Motorola PowerStackII - Omaha */
+/* no integrated SCSI or ethernet */
+static char Omaha_pci_IRQ_map[23] __prepdata =
+{
+ 0, /* Slot 0 - unused */
+ 0, /* Slot 1 - unused */
+ 3, /* Slot 2 - Winbond EIDE */
+ 0, /* Slot 3 - unused */
+ 0, /* Slot 4 - unused */
+ 0, /* Slot 5 - unused */
+ 1, /* Slot 6 - PCI slot 1 */
+ 2, /* Slot 7 - PCI slot 2 */
+ 3, /* Slot 8 - PCI slot 3 */
+ 4, /* Slot 9 - PCI slot 4 */ /* needs indirect access */
+ 0, /* Slot 10 - unused */
+ 0, /* Slot 11 - unused */
+ 0, /* Slot 12 - unused */
+ 0, /* Slot 13 - unused */
+ 0, /* Slot 14 - unused */
+ 0, /* Slot 15 - unused */
+ 1, /* Slot 16 - PCI slot 1 */
+ 2, /* Slot 17 - PCI slot 2 */
+ 3, /* Slot 18 - PCI slot 3 */
+ 4, /* Slot 19 - PCI slot 4 */ /* needs indirect access */
+ 0,
+ 0,
+ 0,
+};
+
+static char Omaha_pci_IRQ_routes[] __prepdata =
+{
+ 0, /* Line 0 - Unused */
+ 9, /* Line 1 */
+ 11, /* Line 2 */
+ 14, /* Line 3 */
+ 15 /* Line 4 */
+};
+
+/* Motorola PowerStack */
+static char Blackhawk_pci_IRQ_map[19] __prepdata =
+{
+ 0, /* Slot 0 - unused */
+ 0, /* Slot 1 - unused */
+ 0, /* Slot 2 - unused */
+ 0, /* Slot 3 - unused */
+ 0, /* Slot 4 - unused */
+ 0, /* Slot 5 - unused */
+ 0, /* Slot 6 - unused */
+ 0, /* Slot 7 - unused */
+ 0, /* Slot 8 - unused */
+ 0, /* Slot 9 - unused */
+ 0, /* Slot 10 - unused */
+ 0, /* Slot 11 - unused */
+ 3, /* Slot 12 - SCSI */
+ 0, /* Slot 13 - unused */
+ 1, /* Slot 14 - Ethernet */
+ 0, /* Slot 15 - unused */
+ 1, /* Slot P7 */
+ 2, /* Slot P6 */
+ 3, /* Slot P5 */
+};
+
+static char Blackhawk_pci_IRQ_routes[] __prepdata =
+{
+ 0, /* Line 0 - Unused */
+ 9, /* Line 1 */
+ 11, /* Line 2 */
+ 15, /* Line 3 */
+ 15 /* Line 4 */
+};
+
+/* Motorola Mesquite */
+static char Mesquite_pci_IRQ_map[23] __prepdata =
+{
+ 0, /* Slot 0 - unused */
+ 0, /* Slot 1 - unused */
+ 0, /* Slot 2 - unused */
+ 0, /* Slot 3 - unused */
+ 0, /* Slot 4 - unused */
+ 0, /* Slot 5 - unused */
+ 0, /* Slot 6 - unused */
+ 0, /* Slot 7 - unused */
+ 0, /* Slot 8 - unused */
+ 0, /* Slot 9 - unused */
+ 0, /* Slot 10 - unused */
+ 0, /* Slot 11 - unused */
+ 0, /* Slot 12 - unused */
+ 0, /* Slot 13 - unused */
+ 2, /* Slot 14 - Ethernet */
+ 0, /* Slot 15 - unused */
+ 3, /* Slot 16 - PMC */
+ 0, /* Slot 17 - unused */
+ 0, /* Slot 18 - unused */
+ 0, /* Slot 19 - unused */
+ 0, /* Slot 20 - unused */
+ 0, /* Slot 21 - unused */
+ 0, /* Slot 22 - unused */
+};
+
+/* Motorola Sitka */
+static char Sitka_pci_IRQ_map[21] __prepdata =
+{
+ 0, /* Slot 0 - unused */
+ 0, /* Slot 1 - unused */
+ 0, /* Slot 2 - unused */
+ 0, /* Slot 3 - unused */
+ 0, /* Slot 4 - unused */
+ 0, /* Slot 5 - unused */
+ 0, /* Slot 6 - unused */
+ 0, /* Slot 7 - unused */
+ 0, /* Slot 8 - unused */
+ 0, /* Slot 9 - unused */
+ 0, /* Slot 10 - unused */
+ 0, /* Slot 11 - unused */
+ 0, /* Slot 12 - unused */
+ 0, /* Slot 13 - unused */
+ 2, /* Slot 14 - Ethernet */
+ 0, /* Slot 15 - unused */
+ 9, /* Slot 16 - PMC 1 */
+ 12, /* Slot 17 - PMC 2 */
+ 0, /* Slot 18 - unused */
+ 0, /* Slot 19 - unused */
+ 4, /* Slot 20 - NT P2P bridge */
+};
+
+/* Motorola MTX */
+static char MTX_pci_IRQ_map[23] __prepdata =
+{
+ 0, /* Slot 0 - unused */
+ 0, /* Slot 1 - unused */
+ 0, /* Slot 2 - unused */
+ 0, /* Slot 3 - unused */
+ 0, /* Slot 4 - unused */
+ 0, /* Slot 5 - unused */
+ 0, /* Slot 6 - unused */
+ 0, /* Slot 7 - unused */
+ 0, /* Slot 8 - unused */
+ 0, /* Slot 9 - unused */
+ 0, /* Slot 10 - unused */
+ 0, /* Slot 11 - unused */
+ 3, /* Slot 12 - SCSI */
+ 0, /* Slot 13 - unused */
+ 2, /* Slot 14 - Ethernet */
+ 0, /* Slot 15 - unused */
+ 9, /* Slot 16 - PCI/PMC slot 1 */
+ 10, /* Slot 17 - PCI/PMC slot 2 */
+ 11, /* Slot 18 - PCI slot 3 */
+ 0, /* Slot 19 - unused */
+ 0, /* Slot 20 - unused */
+ 0, /* Slot 21 - unused */
+ 0, /* Slot 22 - unused */
+};
+
+/* Motorola MTX Plus */
+/* Secondary bus interrupt routing is not supported yet */
+static char MTXplus_pci_IRQ_map[23] __prepdata =
+{
+ 0, /* Slot 0 - unused */
+ 0, /* Slot 1 - unused */
+ 0, /* Slot 2 - unused */
+ 0, /* Slot 3 - unused */
+ 0, /* Slot 4 - unused */
+ 0, /* Slot 5 - unused */
+ 0, /* Slot 6 - unused */
+ 0, /* Slot 7 - unused */
+ 0, /* Slot 8 - unused */
+ 0, /* Slot 9 - unused */
+ 0, /* Slot 10 - unused */
+ 0, /* Slot 11 - unused */
+ 3, /* Slot 12 - SCSI */
+ 0, /* Slot 13 - unused */
+ 2, /* Slot 14 - Ethernet 1 */
+ 0, /* Slot 15 - unused */
+ 9, /* Slot 16 - PCI slot 1P */
+ 10, /* Slot 17 - PCI slot 2P */
+ 11, /* Slot 18 - PCI slot 3P */
+ 10, /* Slot 19 - Ethernet 2 */
+ 0, /* Slot 20 - P2P Bridge */
+ 0, /* Slot 21 - unused */
+ 0, /* Slot 22 - unused */
+};
+
+static char Raven_pci_IRQ_routes[] __prepdata =
+{
+ 0, /* This is a dummy structure */
+};
+
+/* Motorola MVME16xx */
+static char Genesis_pci_IRQ_map[16] __prepdata =
+{
+ 0, /* Slot 0 - unused */
+ 0, /* Slot 1 - unused */
+ 0, /* Slot 2 - unused */
+ 0, /* Slot 3 - unused */
+ 0, /* Slot 4 - unused */
+ 0, /* Slot 5 - unused */
+ 0, /* Slot 6 - unused */
+ 0, /* Slot 7 - unused */
+ 0, /* Slot 8 - unused */
+ 0, /* Slot 9 - unused */
+ 0, /* Slot 10 - unused */
+ 0, /* Slot 11 - unused */
+ 3, /* Slot 12 - SCSI */
+ 0, /* Slot 13 - unused */
+ 1, /* Slot 14 - Ethernet */
+ 0, /* Slot 15 - unused */
+};
+
+static char Genesis_pci_IRQ_routes[] __prepdata =
+{
+ 0, /* Line 0 - Unused */
+ 10, /* Line 1 */
+ 11, /* Line 2 */
+ 14, /* Line 3 */
+ 15 /* Line 4 */
+};
+
+static char Genesis2_pci_IRQ_map[23] __prepdata =
+{
+ 0, /* Slot 0 - unused */
+ 0, /* Slot 1 - unused */
+ 0, /* Slot 2 - unused */
+ 0, /* Slot 3 - unused */
+ 0, /* Slot 4 - unused */
+ 0, /* Slot 5 - unused */
+ 0, /* Slot 6 - unused */
+ 0, /* Slot 7 - unused */
+ 0, /* Slot 8 - unused */
+ 0, /* Slot 9 - unused */
+ 0, /* Slot 10 - unused */
+ 0, /* Slot 11 - IDE */
+ 3, /* Slot 12 - SCSI */
+ 5, /* Slot 13 - Universe PCI - VME Bridge */
+ 2, /* Slot 14 - Ethernet */
+ 0, /* Slot 15 - unused */
+ 9, /* Slot 16 - PMC 1 */
+ 12, /* Slot 17 - pci */
+ 11, /* Slot 18 - pci */
+ 10, /* Slot 19 - pci */
+ 0, /* Slot 20 - pci */
+ 0, /* Slot 21 - unused */
+ 0, /* Slot 22 - unused */
+};
+
+/* Motorola Series-E */
+static char Comet_pci_IRQ_map[23] __prepdata =
+{
+ 0, /* Slot 0 - unused */
+ 0, /* Slot 1 - unused */
+ 0, /* Slot 2 - unused */
+ 0, /* Slot 3 - unused */
+ 0, /* Slot 4 - unused */
+ 0, /* Slot 5 - unused */
+ 0, /* Slot 6 - unused */
+ 0, /* Slot 7 - unused */
+ 0, /* Slot 8 - unused */
+ 0, /* Slot 9 - unused */
+ 0, /* Slot 10 - unused */
+ 0, /* Slot 11 - unused */
+ 3, /* Slot 12 - SCSI */
+ 0, /* Slot 13 - unused */
+ 1, /* Slot 14 - Ethernet */
+ 0, /* Slot 15 - unused */
+ 1, /* Slot 16 - PCI slot 1 */
+ 2, /* Slot 17 - PCI slot 2 */
+ 3, /* Slot 18 - PCI slot 3 */
+ 4, /* Slot 19 - PCI bridge */
+ 0,
+ 0,
+ 0,
+};
+
+static char Comet_pci_IRQ_routes[] __prepdata =
+{
+ 0, /* Line 0 - Unused */
+ 10, /* Line 1 */
+ 11, /* Line 2 */
+ 14, /* Line 3 */
+ 15 /* Line 4 */
+};
+
+/* Motorola Series-EX */
+static char Comet2_pci_IRQ_map[23] __prepdata =
+{
+ 0, /* Slot 0 - unused */
+ 0, /* Slot 1 - unused */
+ 3, /* Slot 2 - SCSI - NCR825A */
+ 0, /* Slot 3 - unused */
+ 1, /* Slot 4 - Ethernet - DEC2104X */
+ 0, /* Slot 5 - unused */
+ 1, /* Slot 6 - PCI slot 1 */
+ 2, /* Slot 7 - PCI slot 2 */
+ 3, /* Slot 8 - PCI slot 3 */
+ 4, /* Slot 9 - PCI bridge */
+ 0, /* Slot 10 - unused */
+ 0, /* Slot 11 - unused */
+ 3, /* Slot 12 - SCSI - NCR825A */
+ 0, /* Slot 13 - unused */
+ 1, /* Slot 14 - Ethernet - DEC2104X */
+ 0, /* Slot 15 - unused */
+ 1, /* Slot 16 - PCI slot 1 */
+ 2, /* Slot 17 - PCI slot 2 */
+ 3, /* Slot 18 - PCI slot 3 */
+ 4, /* Slot 19 - PCI bridge */
+ 0,
+ 0,
+ 0,
+};
+
+static char Comet2_pci_IRQ_routes[] __prepdata =
+{
+ 0, /* Line 0 - Unused */
+ 10, /* Line 1 */
+ 11, /* Line 2 */
+ 14, /* Line 3 */
+ 15, /* Line 4 */
+};
+
+/*
+ * ibm 830 (and 850?).
+ * This is actually based on the Carolina motherboard
+ * -- Cort
+ */
+static char ibm8xx_pci_IRQ_map[23] __prepdata = {
+ 0, /* Slot 0 - unused */
+ 0, /* Slot 1 - unused */
+ 0, /* Slot 2 - unused */
+ 0, /* Slot 3 - unused */
+ 0, /* Slot 4 - unused */
+ 0, /* Slot 5 - unused */
+ 0, /* Slot 6 - unused */
+ 0, /* Slot 7 - unused */
+ 0, /* Slot 8 - unused */
+ 0, /* Slot 9 - unused */
+ 0, /* Slot 10 - unused */
+ 0, /* Slot 11 - FireCoral */
+ 4, /* Slot 12 - Ethernet PCIINTD# */
+ 2, /* Slot 13 - PCI Slot #2 */
+ 2, /* Slot 14 - S3 Video PCIINTD# */
+ 0, /* Slot 15 - onboard SCSI (INDI) [1] */
+ 3, /* Slot 16 - NCR58C810 RS6000 Only PCIINTC# */
+ 0, /* Slot 17 - unused */
+ 2, /* Slot 18 - PCI Slot 2 PCIINTx# (See below) */
+ 0, /* Slot 19 - unused */
+ 0, /* Slot 20 - unused */
+ 0, /* Slot 21 - unused */
+ 2, /* Slot 22 - PCI slot 1 PCIINTx# (See below) */
+};
+
+static char ibm8xx_pci_IRQ_routes[] __prepdata = {
+ 0, /* Line 0 - unused */
+ 15, /* Line 1 */
+ 15, /* Line 2 */
+ 15, /* Line 3 */
+ 15, /* Line 4 */
+};
+
+/*
+ * a 6015 ibm board
+ * -- Cort
+ */
+static char ibm6015_pci_IRQ_map[23] __prepdata = {
+ 0, /* Slot 0 - unused */
+ 0, /* Slot 1 - unused */
+ 0, /* Slot 2 - unused */
+ 0, /* Slot 3 - unused */
+ 0, /* Slot 4 - unused */
+ 0, /* Slot 5 - unused */
+ 0, /* Slot 6 - unused */
+ 0, /* Slot 7 - unused */
+ 0, /* Slot 8 - unused */
+ 0, /* Slot 9 - unused */
+ 0, /* Slot 10 - unused */
+ 0, /* Slot 11 - */
+ 1, /* Slot 12 - SCSI */
+ 2, /* Slot 13 - */
+ 2, /* Slot 14 - */
+ 1, /* Slot 15 - */
+ 1, /* Slot 16 - */
+ 0, /* Slot 17 - */
+ 2, /* Slot 18 - */
+ 0, /* Slot 19 - */
+ 0, /* Slot 20 - */
+ 0, /* Slot 21 - */
+ 2, /* Slot 22 - */
+};
+
+static char ibm6015_pci_IRQ_routes[] __prepdata = {
+ 0, /* Line 0 - unused */
+ 13, /* Line 1 */
+ 15, /* Line 2 */
+ 15, /* Line 3 */
+ 15, /* Line 4 */
+};
+
+
+/* IBM Nobis and Thinkpad 850 */
+static char Nobis_pci_IRQ_map[23] __prepdata ={
+ 0, /* Slot 0 - unused */
+ 0, /* Slot 1 - unused */
+ 0, /* Slot 2 - unused */
+ 0, /* Slot 3 - unused */
+ 0, /* Slot 4 - unused */
+ 0, /* Slot 5 - unused */
+ 0, /* Slot 6 - unused */
+ 0, /* Slot 7 - unused */
+ 0, /* Slot 8 - unused */
+ 0, /* Slot 9 - unused */
+ 0, /* Slot 10 - unused */
+ 0, /* Slot 11 - unused */
+ 3, /* Slot 12 - SCSI */
+ 0, /* Slot 13 - unused */
+ 0, /* Slot 14 - unused */
+ 0, /* Slot 15 - unused */
+};
+
+static char Nobis_pci_IRQ_routes[] __prepdata = {
+ 0, /* Line 0 - Unused */
+ 13, /* Line 1 */
+ 13, /* Line 2 */
+ 13, /* Line 3 */
+ 13 /* Line 4 */
+};
+
+/*
+ * IBM RS/6000 43p/140 -- paulus
+ * XXX we should get all this from the residual data
+ */
+static char ibm43p_pci_IRQ_map[23] __prepdata = {
+ 0, /* Slot 0 - unused */
+ 0, /* Slot 1 - unused */
+ 0, /* Slot 2 - unused */
+ 0, /* Slot 3 - unused */
+ 0, /* Slot 4 - unused */
+ 0, /* Slot 5 - unused */
+ 0, /* Slot 6 - unused */
+ 0, /* Slot 7 - unused */
+ 0, /* Slot 8 - unused */
+ 0, /* Slot 9 - unused */
+ 0, /* Slot 10 - unused */
+ 0, /* Slot 11 - FireCoral ISA bridge */
+ 6, /* Slot 12 - Ethernet */
+ 0, /* Slot 13 - openpic */
+ 0, /* Slot 14 - unused */
+ 0, /* Slot 15 - unused */
+ 7, /* Slot 16 - NCR58C825a onboard scsi */
+ 0, /* Slot 17 - unused */
+ 2, /* Slot 18 - PCI Slot 2 PCIINTx# (See below) */
+ 0, /* Slot 19 - unused */
+ 0, /* Slot 20 - unused */
+ 0, /* Slot 21 - unused */
+ 1, /* Slot 22 - PCI slot 1 PCIINTx# (See below) */
+};
+
+static char ibm43p_pci_IRQ_routes[] __prepdata = {
+ 0, /* Line 0 - unused */
+ 15, /* Line 1 */
+ 15, /* Line 2 */
+ 15, /* Line 3 */
+ 15, /* Line 4 */
+};
+
+/* Motorola PowerPlus architecture PCI IRQ tables */
+/* Interrupt line values for INTA-D on primary/secondary MPIC inputs */
+
+struct powerplus_irq_list
+{
+ unsigned char primary[4]; /* INT A-D */
+ unsigned char secondary[4]; /* INT A-D */
+};
+
+/*
+ * For standard PowerPlus boards, bus 0 PCI INTs A-D are routed to
+ * OpenPIC inputs 9-12. PCI INTs A-D from the on board P2P bridge
+ * are routed to OpenPIC inputs 5-8. These values are offset by
+ * 16 in the table to reflect the Linux kernel interrupt value.
+ */
+struct powerplus_irq_list Powerplus_pci_IRQ_list __prepdata =
+{
+ {25, 26, 27, 28},
+ {21, 22, 23, 24}
+};
+
+/*
+ * For the MCP750 (system slot board), cPCI INTs A-D are routed to
+ * OpenPIC inputs 8-11 and the PMC INTs A-D are routed to OpenPIC
+ * input 3. On a hot swap MCP750, the companion card PCI INTs A-D
+ * are routed to OpenPIC inputs 12-15. These values are offset by
+ * 16 in the table to reflect the Linux kernel interrupt value.
+ */
+struct powerplus_irq_list Mesquite_pci_IRQ_list __prepdata =
+{
+ {24, 25, 26, 27},
+ {28, 29, 30, 31}
+};
+
+/*
+ * This table represents the standard PCI swizzle defined in the
+ * PCI bus specification.
+ */
+static unsigned char prep_pci_intpins[4][4] __prepdata =
+{
+ { 1, 2, 3, 4}, /* Buses 0, 4, 8, ... */
+ { 2, 3, 4, 1}, /* Buses 1, 5, 9, ... */
+ { 3, 4, 1, 2}, /* Buses 2, 6, 10 ... */
+ { 4, 1, 2, 3}, /* Buses 3, 7, 11 ... */
+};
+
+/* We have to turn on LEVEL mode for changed IRQ's */
+/* All PCI IRQ's need to be level mode, so this should be something
+ * other than hard-coded as well... IRQ's are individually mappable
+ * to either edge or level.
+ */
+
+/*
+ * 8259 edge/level control definitions
+ */
+#define ISA8259_M_ELCR 0x4d0
+#define ISA8259_S_ELCR 0x4d1
+
+#define ELCRS_INT15_LVL 0x80
+#define ELCRS_INT14_LVL 0x40
+#define ELCRS_INT12_LVL 0x10
+#define ELCRS_INT11_LVL 0x08
+#define ELCRS_INT10_LVL 0x04
+#define ELCRS_INT9_LVL 0x02
+#define ELCRS_INT8_LVL 0x01
+#define ELCRM_INT7_LVL 0x80
+#define ELCRM_INT5_LVL 0x20
+
+#if 0
+/*
+ * PCI config space access.
+ */
+#define CFGADDR(dev) ((1<<(dev>>3)) | ((dev&7)<<8))
+#define DEVNO(dev) (dev>>3)
+
+#define MIN_DEVNR 11
+#define MAX_DEVNR 22
+
+static int __prep
+prep_read_config(struct pci_bus *bus, unsigned int devfn, int offset,
+ int len, u32 *val)
+{
+ struct pci_controller *hose = bus->sysdata;
+ volatile void __iomem *cfg_data;
+
+ if (bus->number != 0 || DEVNO(devfn) < MIN_DEVNR
+ || DEVNO(devfn) > MAX_DEVNR)
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
+ /*
+ * Note: the caller has already checked that offset is
+ * suitably aligned and that len is 1, 2 or 4.
+ */
+ cfg_data = hose->cfg_data + CFGADDR(devfn) + offset;
+ switch (len) {
+ case 1:
+ *val = in_8(cfg_data);
+ break;
+ case 2:
+ *val = in_le16(cfg_data);
+ break;
+ default:
+ *val = in_le32(cfg_data);
+ break;
+ }
+ return PCIBIOS_SUCCESSFUL;
+}
+
+static int __prep
+prep_write_config(struct pci_bus *bus, unsigned int devfn, int offset,
+ int len, u32 val)
+{
+ struct pci_controller *hose = bus->sysdata;
+ volatile void __iomem *cfg_data;
+
+ if (bus->number != 0 || DEVNO(devfn) < MIN_DEVNR
+ || DEVNO(devfn) > MAX_DEVNR)
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
+ /*
+ * Note: the caller has already checked that offset is
+ * suitably aligned and that len is 1, 2 or 4.
+ */
+ cfg_data = hose->cfg_data + CFGADDR(devfn) + offset;
+ switch (len) {
+ case 1:
+ out_8(cfg_data, val);
+ break;
+ case 2:
+ out_le16(cfg_data, val);
+ break;
+ default:
+ out_le32(cfg_data, val);
+ break;
+ }
+ return PCIBIOS_SUCCESSFUL;
+}
+
+static struct pci_ops prep_pci_ops =
+{
+ prep_read_config,
+ prep_write_config
+};
+#endif
+
+#define MOTOROLA_CPUTYPE_REG 0x800
+#define MOTOROLA_BASETYPE_REG 0x803
+#define MPIC_RAVEN_ID 0x48010000
+#define MPIC_HAWK_ID 0x48030000
+#define MOT_PROC2_BIT 0x800
+
+static u_char prep_openpic_initsenses[] __initdata = {
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* MVME2600_INT_SIO */
+ (IRQ_SENSE_EDGE | IRQ_POLARITY_NEGATIVE), /* MVME2600_INT_FALCN_ECC_ERR */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* MVME2600_INT_PCI_ETHERNET */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* MVME2600_INT_PCI_SCSI */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* MVME2600_INT_PCI_GRAPHICS */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* MVME2600_INT_PCI_VME0 */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* MVME2600_INT_PCI_VME1 */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* MVME2600_INT_PCI_VME2 */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* MVME2600_INT_PCI_VME3 */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* MVME2600_INT_PCI_INTA */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* MVME2600_INT_PCI_INTB */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* MVME2600_INT_PCI_INTC */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* MVME2600_INT_PCI_INTD */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* MVME2600_INT_LM_SIG0 */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* MVME2600_INT_LM_SIG1 */
+};
+
+#define MOT_RAVEN_PRESENT 0x1
+#define MOT_HAWK_PRESENT 0x2
+
+int mot_entry = -1;
+int prep_keybd_present = 1;
+int MotMPIC;
+int mot_multi;
+
+int __init
+raven_init(void)
+{
+ unsigned int devid;
+ unsigned int pci_membase;
+ unsigned char base_mod;
+
+ /* Check to see if the Raven chip exists. */
+ if ( _prep_type != _PREP_Motorola) {
+ OpenPIC_Addr = NULL;
+ return 0;
+ }
+
+ /* Check to see if this board is a type that might have a Raven. */
+ if ((inb(MOTOROLA_CPUTYPE_REG) & 0xF0) != 0xE0) {
+ OpenPIC_Addr = NULL;
+ return 0;
+ }
+
+ /* Check the first PCI device to see if it is a Raven. */
+ early_read_config_dword(NULL, 0, 0, PCI_VENDOR_ID, &devid);
+
+ switch (devid & 0xffff0000) {
+ case MPIC_RAVEN_ID:
+ MotMPIC = MOT_RAVEN_PRESENT;
+ break;
+ case MPIC_HAWK_ID:
+ MotMPIC = MOT_HAWK_PRESENT;
+ break;
+ default:
+ OpenPIC_Addr = NULL;
+ return 0;
+ }
+
+
+ /* Read the memory base register. */
+ early_read_config_dword(NULL, 0, 0, PCI_BASE_ADDRESS_1, &pci_membase);
+
+ if (pci_membase == 0) {
+ OpenPIC_Addr = NULL;
+ return 0;
+ }
+
+ /* Map the Raven MPIC registers to virtual memory. */
+ OpenPIC_Addr = ioremap(pci_membase+0xC0000000, 0x22000);
+
+ OpenPIC_InitSenses = prep_openpic_initsenses;
+ OpenPIC_NumInitSenses = sizeof(prep_openpic_initsenses);
+
+ ppc_md.get_irq = openpic_get_irq;
+
+ /* If raven is present on Motorola store the system config register
+ * for later use.
+ */
+ ProcInfo = (unsigned long *)ioremap(0xfef80400, 4);
+
+ /* Indicate to system if this is a multiprocessor board */
+ if (!(*ProcInfo & MOT_PROC2_BIT)) {
+ mot_multi = 1;
+ }
+
+ /* This is a hack. If this is a 2300 or 2400 mot board then there is
+ * no keyboard controller and we have to indicate that.
+ */
+ base_mod = inb(MOTOROLA_BASETYPE_REG);
+ if ((MotMPIC == MOT_HAWK_PRESENT) || (base_mod == 0xF9) ||
+ (base_mod == 0xFA) || (base_mod == 0xE1))
+ prep_keybd_present = 0;
+
+ return 1;
+}
+
+struct mot_info {
+ int cpu_type; /* 0x100 mask assumes for Raven and Hawk boards that the level/edge are set */
+ /* 0x200 if this board has a Hawk chip. */
+ int base_type;
+ int max_cpu; /* ored with 0x80 if this board should be checked for multi CPU */
+ const char *name;
+ unsigned char *map;
+ unsigned char *routes;
+ void (*map_non0_bus)(struct pci_dev *); /* For boards with more than bus 0 devices. */
+ struct powerplus_irq_list *pci_irq_list; /* List of PCI MPIC inputs */
+ unsigned char secondary_bridge_devfn; /* devfn of secondary bus transparent bridge */
+} mot_info[] __prepdata = {
+ {0x300, 0x00, 0x00, "MVME 2400", Genesis2_pci_IRQ_map, Raven_pci_IRQ_routes, Powerplus_Map_Non0, &Powerplus_pci_IRQ_list, 0xFF},
+ {0x010, 0x00, 0x00, "Genesis", Genesis_pci_IRQ_map, Genesis_pci_IRQ_routes, Powerplus_Map_Non0, &Powerplus_pci_IRQ_list, 0x00},
+ {0x020, 0x00, 0x00, "Powerstack (Series E)", Comet_pci_IRQ_map, Comet_pci_IRQ_routes, NULL, NULL, 0x00},
+ {0x040, 0x00, 0x00, "Blackhawk (Powerstack)", Blackhawk_pci_IRQ_map, Blackhawk_pci_IRQ_routes, NULL, NULL, 0x00},
+ {0x050, 0x00, 0x00, "Omaha (PowerStack II Pro3000)", Omaha_pci_IRQ_map, Omaha_pci_IRQ_routes, NULL, NULL, 0x00},
+ {0x060, 0x00, 0x00, "Utah (Powerstack II Pro4000)", Utah_pci_IRQ_map, Utah_pci_IRQ_routes, NULL, NULL, 0x00},
+ {0x0A0, 0x00, 0x00, "Powerstack (Series EX)", Comet2_pci_IRQ_map, Comet2_pci_IRQ_routes, NULL, NULL, 0x00},
+ {0x1E0, 0xE0, 0x00, "Mesquite cPCI (MCP750)", Mesquite_pci_IRQ_map, Raven_pci_IRQ_routes, Powerplus_Map_Non0, &Mesquite_pci_IRQ_list, 0xFF},
+ {0x1E0, 0xE1, 0x00, "Sitka cPCI (MCPN750)", Sitka_pci_IRQ_map, Raven_pci_IRQ_routes, Powerplus_Map_Non0, &Powerplus_pci_IRQ_list, 0xFF},
+ {0x1E0, 0xE2, 0x00, "Mesquite cPCI (MCP750) w/ HAC", Mesquite_pci_IRQ_map, Raven_pci_IRQ_routes, Powerplus_Map_Non0, &Mesquite_pci_IRQ_list, 0xC0},
+ {0x1E0, 0xF6, 0x80, "MTX Plus", MTXplus_pci_IRQ_map, Raven_pci_IRQ_routes, Powerplus_Map_Non0, &Powerplus_pci_IRQ_list, 0xA0},
+ {0x1E0, 0xF6, 0x81, "Dual MTX Plus", MTXplus_pci_IRQ_map, Raven_pci_IRQ_routes, Powerplus_Map_Non0, &Powerplus_pci_IRQ_list, 0xA0},
+ {0x1E0, 0xF7, 0x80, "MTX wo/ Parallel Port", MTX_pci_IRQ_map, Raven_pci_IRQ_routes, Powerplus_Map_Non0, &Powerplus_pci_IRQ_list, 0x00},
+ {0x1E0, 0xF7, 0x81, "Dual MTX wo/ Parallel Port", MTX_pci_IRQ_map, Raven_pci_IRQ_routes, Powerplus_Map_Non0, &Powerplus_pci_IRQ_list, 0x00},
+ {0x1E0, 0xF8, 0x80, "MTX w/ Parallel Port", MTX_pci_IRQ_map, Raven_pci_IRQ_routes, Powerplus_Map_Non0, &Powerplus_pci_IRQ_list, 0x00},
+ {0x1E0, 0xF8, 0x81, "Dual MTX w/ Parallel Port", MTX_pci_IRQ_map, Raven_pci_IRQ_routes, Powerplus_Map_Non0, &Powerplus_pci_IRQ_list, 0x00},
+ {0x1E0, 0xF9, 0x00, "MVME 2300", Genesis2_pci_IRQ_map, Raven_pci_IRQ_routes, Powerplus_Map_Non0, &Powerplus_pci_IRQ_list, 0xFF},
+ {0x1E0, 0xFA, 0x00, "MVME 2300SC/2600", Genesis2_pci_IRQ_map, Raven_pci_IRQ_routes, Powerplus_Map_Non0, &Powerplus_pci_IRQ_list, 0xFF},
+ {0x1E0, 0xFB, 0x00, "MVME 2600 with MVME712M", Genesis2_pci_IRQ_map, Raven_pci_IRQ_routes, Powerplus_Map_Non0, &Powerplus_pci_IRQ_list, 0xFF},
+ {0x1E0, 0xFC, 0x00, "MVME 2600/2700 with MVME761", Genesis2_pci_IRQ_map, Raven_pci_IRQ_routes, Powerplus_Map_Non0, &Powerplus_pci_IRQ_list, 0xFF},
+ {0x1E0, 0xFD, 0x80, "MVME 3600 with MVME712M", Genesis2_pci_IRQ_map, Raven_pci_IRQ_routes, Powerplus_Map_Non0, &Powerplus_pci_IRQ_list, 0x00},
+ {0x1E0, 0xFD, 0x81, "MVME 4600 with MVME712M", Genesis2_pci_IRQ_map, Raven_pci_IRQ_routes, Powerplus_Map_Non0, &Powerplus_pci_IRQ_list, 0xFF},
+ {0x1E0, 0xFE, 0x80, "MVME 3600 with MVME761", Genesis2_pci_IRQ_map, Raven_pci_IRQ_routes, Powerplus_Map_Non0, &Powerplus_pci_IRQ_list, 0xFF},
+ {0x1E0, 0xFE, 0x81, "MVME 4600 with MVME761", Genesis2_pci_IRQ_map, Raven_pci_IRQ_routes, Powerplus_Map_Non0, &Powerplus_pci_IRQ_list, 0xFF},
+ {0x1E0, 0xFF, 0x00, "MVME 1600-001 or 1600-011", Genesis2_pci_IRQ_map, Raven_pci_IRQ_routes, Powerplus_Map_Non0, &Powerplus_pci_IRQ_list, 0xFF},
+ {0x000, 0x00, 0x00, "", NULL, NULL, NULL, NULL, 0x00}
+};
+
+void __init
+ibm_prep_init(void)
+{
+ if (have_residual_data) {
+ u32 addr, real_addr, len, offset;
+ PPC_DEVICE *mpic;
+ PnP_TAG_PACKET *pkt;
+
+ /* Use the PReP residual data to determine if an OpenPIC is
+ * present. If so, get the large vendor packet which will
+ * tell us the base address and length in memory.
+ * If we are successful, ioremap the memory area and set
+ * OpenPIC_Addr (this indicates that the OpenPIC was found).
+ */
+ mpic = residual_find_device(-1, NULL, SystemPeripheral,
+ ProgrammableInterruptController, MPIC, 0);
+ if (!mpic)
+ return;
+
+ pkt = PnP_find_large_vendor_packet(res->DevicePnPHeap +
+ mpic->AllocatedOffset, 9, 0);
+
+ if (!pkt)
+ return;
+
+#define p pkt->L4_Pack.L4_Data.L4_PPCPack
+ if (p.PPCData[1] == 32) {
+ switch (p.PPCData[0]) {
+ case 1: offset = PREP_ISA_IO_BASE; break;
+ case 2: offset = PREP_ISA_MEM_BASE; break;
+ default: return; /* Not I/O or memory?? */
+ }
+ }
+ else
+ return; /* Not a 32-bit address */
+
+ real_addr = ld_le32((unsigned int *) (p.PPCData + 4));
+ if (real_addr == 0xffffffff)
+ return;
+
+ /* Adjust address to be as seen by CPU */
+ addr = real_addr + offset;
+
+ len = ld_le32((unsigned int *) (p.PPCData + 12));
+ if (!len)
+ return;
+#undef p
+ OpenPIC_Addr = ioremap(addr, len);
+ ppc_md.get_irq = openpic_get_irq;
+
+ OpenPIC_InitSenses = prep_openpic_initsenses;
+ OpenPIC_NumInitSenses = sizeof(prep_openpic_initsenses);
+
+ printk(KERN_INFO "MPIC at 0x%08x (0x%08x), length 0x%08x "
+ "mapped to 0x%p\n", addr, real_addr, len, OpenPIC_Addr);
+ }
+}
+
+static void __init
+ibm43p_pci_map_non0(struct pci_dev *dev)
+{
+ unsigned char intpin;
+ static unsigned char bridge_intrs[4] = { 3, 4, 5, 8 };
+
+ if (dev == NULL)
+ return;
+ pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &intpin);
+ if (intpin < 1 || intpin > 4)
+ return;
+ intpin = (PCI_SLOT(dev->devfn) + intpin - 1) & 3;
+ dev->irq = openpic_to_irq(bridge_intrs[intpin]);
+ pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq);
+}
+
+void __init
+prep_residual_setup_pci(char *irq_edge_mask_lo, char *irq_edge_mask_hi)
+{
+ if (have_residual_data) {
+ Motherboard_map_name = res->VitalProductData.PrintableModel;
+ Motherboard_map = NULL;
+ Motherboard_routes = NULL;
+ residual_irq_mask(irq_edge_mask_lo, irq_edge_mask_hi);
+ }
+}
+
+void __init
+prep_sandalfoot_setup_pci(char *irq_edge_mask_lo, char *irq_edge_mask_hi)
+{
+ Motherboard_map_name = "IBM 6015/7020 (Sandalfoot/Sandalbow)";
+ Motherboard_map = ibm6015_pci_IRQ_map;
+ Motherboard_routes = ibm6015_pci_IRQ_routes;
+ *irq_edge_mask_lo = 0x00; /* irq's 0-7 all edge-triggered */
+ *irq_edge_mask_hi = 0xA0; /* irq's 13, 15 level-triggered */
+}
+
+void __init
+prep_thinkpad_setup_pci(char *irq_edge_mask_lo, char *irq_edge_mask_hi)
+{
+ Motherboard_map_name = "IBM Thinkpad 850/860";
+ Motherboard_map = Nobis_pci_IRQ_map;
+ Motherboard_routes = Nobis_pci_IRQ_routes;
+ *irq_edge_mask_lo = 0x00; /* irq's 0-7 all edge-triggered */
+ *irq_edge_mask_hi = 0xA0; /* irq's 13, 15 level-triggered */
+}
+
+void __init
+prep_carolina_setup_pci(char *irq_edge_mask_lo, char *irq_edge_mask_hi)
+{
+ Motherboard_map_name = "IBM 7248, PowerSeries 830/850 (Carolina)";
+ Motherboard_map = ibm8xx_pci_IRQ_map;
+ Motherboard_routes = ibm8xx_pci_IRQ_routes;
+ *irq_edge_mask_lo = 0x00; /* irq's 0-7 all edge-triggered */
+ *irq_edge_mask_hi = 0xA4; /* irq's 10, 13, 15 level-triggered */
+}
+
+void __init
+prep_tiger1_setup_pci(char *irq_edge_mask_lo, char *irq_edge_mask_hi)
+{
+ Motherboard_map_name = "IBM 43P-140 (Tiger1)";
+ Motherboard_map = ibm43p_pci_IRQ_map;
+ Motherboard_routes = ibm43p_pci_IRQ_routes;
+ Motherboard_non0 = ibm43p_pci_map_non0;
+ *irq_edge_mask_lo = 0x00; /* irq's 0-7 all edge-triggered */
+ *irq_edge_mask_hi = 0xA0; /* irq's 13, 15 level-triggered */
+}
+
+void __init
+prep_route_pci_interrupts(void)
+{
+ unsigned char *ibc_pirq = (unsigned char *)0x80800860;
+ unsigned char *ibc_pcicon = (unsigned char *)0x80800840;
+ int i;
+
+ if ( _prep_type == _PREP_Motorola)
+ {
+ unsigned short irq_mode;
+ unsigned char cpu_type;
+ unsigned char base_mod;
+ int entry;
+
+ cpu_type = inb(MOTOROLA_CPUTYPE_REG) & 0xF0;
+ base_mod = inb(MOTOROLA_BASETYPE_REG);
+
+ for (entry = 0; mot_info[entry].cpu_type != 0; entry++) {
+ if (mot_info[entry].cpu_type & 0x200) { /* Check for Hawk chip */
+ if (!(MotMPIC & MOT_HAWK_PRESENT))
+ continue;
+ } else { /* Check non hawk boards */
+ if ((mot_info[entry].cpu_type & 0xff) != cpu_type)
+ continue;
+
+ if (mot_info[entry].base_type == 0) {
+ mot_entry = entry;
+ break;
+ }
+
+ if (mot_info[entry].base_type != base_mod)
+ continue;
+ }
+
+ if (!(mot_info[entry].max_cpu & 0x80)) {
+ mot_entry = entry;
+ break;
+ }
+
+ /* processor 1 not present and max processor zero indicated */
+ if ((*ProcInfo & MOT_PROC2_BIT) && !(mot_info[entry].max_cpu & 0x7f)) {
+ mot_entry = entry;
+ break;
+ }
+
+ /* processor 1 present and max processor zero indicated */
+ if (!(*ProcInfo & MOT_PROC2_BIT) && (mot_info[entry].max_cpu & 0x7f)) {
+ mot_entry = entry;
+ break;
+ }
+ }
+
+ if (mot_entry == -1) /* No particular cpu type found - assume Blackhawk */
+ mot_entry = 3;
+
+ Motherboard_map_name = (unsigned char *)mot_info[mot_entry].name;
+ Motherboard_map = mot_info[mot_entry].map;
+ Motherboard_routes = mot_info[mot_entry].routes;
+ Motherboard_non0 = mot_info[mot_entry].map_non0_bus;
+
+ if (!(mot_info[entry].cpu_type & 0x100)) {
+ /* AJF adjust level/edge control according to routes */
+ irq_mode = 0;
+ for (i = 1; i <= 4; i++)
+ irq_mode |= ( 1 << Motherboard_routes[i] );
+ outb( irq_mode & 0xff, 0x4d0 );
+ outb( (irq_mode >> 8) & 0xff, 0x4d1 );
+ }
+ } else if ( _prep_type == _PREP_IBM ) {
+ unsigned char irq_edge_mask_lo, irq_edge_mask_hi;
+ unsigned short irq_edge_mask;
+ int i;
+
+ setup_ibm_pci(&irq_edge_mask_lo, &irq_edge_mask_hi);
+
+ outb(inb(0x04d0)|irq_edge_mask_lo, 0x4d0); /* primary 8259 */
+ outb(inb(0x04d1)|irq_edge_mask_hi, 0x4d1); /* cascaded 8259 */
+
+ irq_edge_mask = (irq_edge_mask_hi << 8) | irq_edge_mask_lo;
+ for (i = 0; i < 16; ++i, irq_edge_mask >>= 1)
+ if (irq_edge_mask & 1)
+ irq_desc[i].status |= IRQ_LEVEL;
+ } else {
+ printk("No known machine pci routing!\n");
+ return;
+ }
+
+ /* Set up mapping from slots */
+ if (Motherboard_routes) {
+ for (i = 1; i <= 4; i++)
+ ibc_pirq[i-1] = Motherboard_routes[i];
+
+ /* Enable PCI interrupts */
+ *ibc_pcicon |= 0x20;
+ }
+}
+
+void __init
+prep_pib_init(void)
+{
+ unsigned char reg;
+ unsigned short short_reg;
+
+ struct pci_dev *dev = NULL;
+
+ if (( _prep_type == _PREP_Motorola) && (OpenPIC_Addr)) {
+ /*
+ * Perform specific configuration for the Via Tech or
+ * or Winbond PCI-ISA-Bridge part.
+ */
+ if ((dev = pci_get_device(PCI_VENDOR_ID_VIA,
+ PCI_DEVICE_ID_VIA_82C586_1, dev))) {
+ /*
+ * PPCBUG does not set the enable bits
+ * for the IDE device. Force them on here.
+ */
+ pci_read_config_byte(dev, 0x40, ®);
+
+ reg |= 0x03; /* IDE: Chip Enable Bits */
+ pci_write_config_byte(dev, 0x40, reg);
+ }
+ if ((dev = pci_get_device(PCI_VENDOR_ID_VIA,
+ PCI_DEVICE_ID_VIA_82C586_2,
+ dev)) && (dev->devfn = 0x5a)) {
+ /* Force correct USB interrupt */
+ dev->irq = 11;
+ pci_write_config_byte(dev,
+ PCI_INTERRUPT_LINE,
+ dev->irq);
+ }
+ if ((dev = pci_get_device(PCI_VENDOR_ID_WINBOND,
+ PCI_DEVICE_ID_WINBOND_83C553, dev))) {
+ /* Clear PCI Interrupt Routing Control Register. */
+ short_reg = 0x0000;
+ pci_write_config_word(dev, 0x44, short_reg);
+ if (OpenPIC_Addr){
+ /* Route IDE interrupts to IRQ 14 */
+ reg = 0xEE;
+ pci_write_config_byte(dev, 0x43, reg);
+ }
+ }
+ pci_dev_put(dev);
+ }
+
+ if ((dev = pci_get_device(PCI_VENDOR_ID_WINBOND,
+ PCI_DEVICE_ID_WINBOND_82C105, dev))){
+ if (OpenPIC_Addr){
+ /*
+ * Disable LEGIRQ mode so PCI INTS are routed
+ * directly to the 8259 and enable both channels
+ */
+ pci_write_config_dword(dev, 0x40, 0x10ff0033);
+
+ /* Force correct IDE interrupt */
+ dev->irq = 14;
+ pci_write_config_byte(dev,
+ PCI_INTERRUPT_LINE,
+ dev->irq);
+ } else {
+ /* Enable LEGIRQ for PCI INT -> 8259 IRQ routing */
+ pci_write_config_dword(dev, 0x40, 0x10ff08a1);
+ }
+ }
+ pci_dev_put(dev);
+}
+
+static void __init
+Powerplus_Map_Non0(struct pci_dev *dev)
+{
+ struct pci_bus *pbus; /* Parent bus structure pointer */
+ struct pci_dev *tdev = dev; /* Temporary device structure */
+ unsigned int devnum; /* Accumulated device number */
+ unsigned char intline; /* Linux interrupt value */
+ unsigned char intpin; /* PCI interrupt pin */
+
+ /* Check for valid PCI dev pointer */
+ if (dev == NULL) return;
+
+ /* Initialize bridge IDSEL variable */
+ devnum = PCI_SLOT(tdev->devfn);
+
+ /* Read the interrupt pin of the device and adjust for indexing */
+ pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &intpin);
+
+ /* If device doesn't request an interrupt, return */
+ if ( (intpin < 1) || (intpin > 4) )
+ return;
+
+ intpin--;
+
+ /*
+ * Walk up to bus 0, adjusting the interrupt pin for the standard
+ * PCI bus swizzle.
+ */
+ do {
+ intpin = (prep_pci_intpins[devnum % 4][intpin]) - 1;
+ pbus = tdev->bus; /* up one level */
+ tdev = pbus->self;
+ devnum = PCI_SLOT(tdev->devfn);
+ } while(tdev->bus->number);
+
+ /* Use the primary interrupt inputs by default */
+ intline = mot_info[mot_entry].pci_irq_list->primary[intpin];
+
+ /*
+ * If the board has secondary interrupt inputs, walk the bus and
+ * note the devfn of the bridge from bus 0. If it is the same as
+ * the devfn of the bus bridge with secondary inputs, use those.
+ * Otherwise, assume it's a PMC site and get the interrupt line
+ * value from the interrupt routing table.
+ */
+ if (mot_info[mot_entry].secondary_bridge_devfn) {
+ pbus = dev->bus;
+
+ while (pbus->primary != 0)
+ pbus = pbus->parent;
+
+ if ((pbus->self)->devfn != 0xA0) {
+ if ((pbus->self)->devfn == mot_info[mot_entry].secondary_bridge_devfn)
+ intline = mot_info[mot_entry].pci_irq_list->secondary[intpin];
+ else {
+ if ((char *)(mot_info[mot_entry].map) == (char *)Mesquite_pci_IRQ_map)
+ intline = mot_info[mot_entry].map[((pbus->self)->devfn)/8] + 16;
+ else {
+ int i;
+ for (i=0;i<3;i++)
+ intpin = (prep_pci_intpins[devnum % 4][intpin]) - 1;
+ intline = mot_info[mot_entry].pci_irq_list->primary[intpin];
+ }
+ }
+ }
+ }
+
+ /* Write calculated interrupt value to header and device list */
+ dev->irq = intline;
+ pci_write_config_byte(dev, PCI_INTERRUPT_LINE, (u8)dev->irq);
+}
+
+void __init
+prep_pcibios_fixup(void)
+{
+ struct pci_dev *dev = NULL;
+ int irq;
+ int have_openpic = (OpenPIC_Addr != NULL);
+
+ prep_route_pci_interrupts();
+
+ printk("Setting PCI interrupts for a \"%s\"\n", Motherboard_map_name);
+
+ /* Iterate through all the PCI devices, setting the IRQ */
+ for_each_pci_dev(dev) {
+ /*
+ * If we have residual data, then this is easy: query the
+ * residual data for the IRQ line allocated to the device.
+ * This works the same whether we have an OpenPic or not.
+ */
+ if (have_residual_data) {
+ irq = residual_pcidev_irq(dev);
+ dev->irq = have_openpic ? openpic_to_irq(irq) : irq;
+ }
+ /*
+ * If we don't have residual data, then we need to use
+ * tables to determine the IRQ. The table organisation
+ * is different depending on whether there is an OpenPIC
+ * or not. The tables are only used for bus 0, so check
+ * this first.
+ */
+ else if (dev->bus->number == 0) {
+ irq = Motherboard_map[PCI_SLOT(dev->devfn)];
+ dev->irq = have_openpic ? openpic_to_irq(irq)
+ : Motherboard_routes[irq];
+ }
+ /*
+ * Finally, if we don't have residual data and the bus is
+ * non-zero, use the callback (if provided)
+ */
+ else {
+ if (Motherboard_non0 != NULL)
+ Motherboard_non0(dev);
+
+ continue;
+ }
+
+ pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq);
+ }
+
+ /* Setup the Winbond or Via PIB */
+ prep_pib_init();
+}
+
+static void __init
+prep_pcibios_after_init(void)
+{
+#if 0
+ struct pci_dev *dev;
+
+ /* If there is a WD 90C, reset the IO BAR to 0x0 (it started that
+ * way, but the PCI layer relocated it because it thought 0x0 was
+ * invalid for a BAR).
+ * If you don't do this, the card's VGA base will be <IO BAR>+0xc0000
+ * instead of 0xc0000. vgacon.c (for example) is completely unaware of
+ * this little quirk.
+ */
+ dev = pci_get_device(PCI_VENDOR_ID_WD, PCI_DEVICE_ID_WD_90C, NULL);
+ if (dev) {
+ dev->resource[1].end -= dev->resource[1].start;
+ dev->resource[1].start = 0;
+ /* tell the hardware */
+ pci_write_config_dword(dev, PCI_BASE_ADDRESS_1, 0x0);
+ pci_dev_put(dev);
+ }
+#endif
+}
+
+static void __init
+prep_init_resource(struct resource *res, unsigned long start,
+ unsigned long end, int flags)
+{
+ res->flags = flags;
+ res->start = start;
+ res->end = end;
+ res->name = "PCI host bridge";
+ res->parent = NULL;
+ res->sibling = NULL;
+ res->child = NULL;
+}
+
+void __init
+prep_find_bridges(void)
+{
+ struct pci_controller* hose;
+
+ hose = pcibios_alloc_controller();
+ if (!hose)
+ return;
+
+ hose->first_busno = 0;
+ hose->last_busno = 0xff;
+ hose->pci_mem_offset = PREP_ISA_MEM_BASE;
+ hose->io_base_phys = PREP_ISA_IO_BASE;
+ hose->io_base_virt = ioremap(PREP_ISA_IO_BASE, 0x800000);
+ prep_init_resource(&hose->io_resource, 0, 0x007fffff, IORESOURCE_IO);
+ prep_init_resource(&hose->mem_resources[0], 0xc0000000, 0xfeffffff,
+ IORESOURCE_MEM);
+ setup_indirect_pci(hose, PREP_ISA_IO_BASE + 0xcf8,
+ PREP_ISA_IO_BASE + 0xcfc);
+
+ printk("PReP architecture\n");
+
+ if (have_residual_data) {
+ PPC_DEVICE *hostbridge;
+
+ hostbridge = residual_find_device(PROCESSORDEVICE, NULL,
+ BridgeController, PCIBridge, -1, 0);
+ if (hostbridge &&
+ ((hostbridge->DeviceId.Interface == PCIBridgeIndirect) ||
+ (hostbridge->DeviceId.Interface == PCIBridgeRS6K))) {
+ PnP_TAG_PACKET * pkt;
+ pkt = PnP_find_large_vendor_packet(
+ res->DevicePnPHeap+hostbridge->AllocatedOffset,
+ 3, 0);
+ if(pkt) {
+#define p pkt->L4_Pack.L4_Data.L4_PPCPack
+ setup_indirect_pci(hose,
+ ld_le32((unsigned *) (p.PPCData)),
+ ld_le32((unsigned *) (p.PPCData+8)));
+#undef p
+ } else
+ setup_indirect_pci(hose, 0x80000cf8, 0x80000cfc);
+ }
+ }
+
+ ppc_md.pcibios_fixup = prep_pcibios_fixup;
+ ppc_md.pcibios_after_init = prep_pcibios_after_init;
+}
diff --git a/arch/ppc/platforms/prep_setup.c b/arch/ppc/platforms/prep_setup.c
new file mode 100644
index 0000000..bc926be
--- /dev/null
+++ b/arch/ppc/platforms/prep_setup.c
@@ -0,0 +1,1181 @@
+/*
+ * arch/ppc/platforms/setup.c
+ *
+ * Copyright (C) 1995 Linus Torvalds
+ * Adapted from 'alpha' version by Gary Thomas
+ * Modified by Cort Dougan (cort@cs.nmt.edu)
+ *
+ * Support for PReP (Motorola MTX/MVME)
+ * by Troy Benjegerdes (hozer@drgw.net)
+ */
+
+/*
+ * bootup setup stuff..
+ */
+
+#include <linux/config.h>
+#include <linux/delay.h>
+#include <linux/module.h>
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/stddef.h>
+#include <linux/unistd.h>
+#include <linux/ptrace.h>
+#include <linux/slab.h>
+#include <linux/user.h>
+#include <linux/a.out.h>
+#include <linux/tty.h>
+#include <linux/major.h>
+#include <linux/interrupt.h>
+#include <linux/reboot.h>
+#include <linux/init.h>
+#include <linux/initrd.h>
+#include <linux/ioport.h>
+#include <linux/console.h>
+#include <linux/timex.h>
+#include <linux/pci.h>
+#include <linux/ide.h>
+#include <linux/seq_file.h>
+#include <linux/root_dev.h>
+
+#include <asm/sections.h>
+#include <asm/mmu.h>
+#include <asm/processor.h>
+#include <asm/residual.h>
+#include <asm/io.h>
+#include <asm/pgtable.h>
+#include <asm/cache.h>
+#include <asm/dma.h>
+#include <asm/machdep.h>
+#include <asm/mc146818rtc.h>
+#include <asm/mk48t59.h>
+#include <asm/prep_nvram.h>
+#include <asm/raven.h>
+#include <asm/vga.h>
+#include <asm/time.h>
+#include <asm/mpc10x.h>
+#include <asm/i8259.h>
+#include <asm/open_pic.h>
+#include <asm/pci-bridge.h>
+#include <asm/todc.h>
+
+TODC_ALLOC();
+
+unsigned char ucSystemType;
+unsigned char ucBoardRev;
+unsigned char ucBoardRevMaj, ucBoardRevMin;
+
+extern unsigned char prep_nvram_read_val(int addr);
+extern void prep_nvram_write_val(int addr,
+ unsigned char val);
+extern unsigned char rs_nvram_read_val(int addr);
+extern void rs_nvram_write_val(int addr,
+ unsigned char val);
+extern void ibm_prep_init(void);
+
+extern void prep_find_bridges(void);
+
+int _prep_type;
+
+extern void prep_residual_setup_pci(char *irq_edge_mask_lo, char *irq_edge_mask_hi);
+extern void prep_sandalfoot_setup_pci(char *irq_edge_mask_lo, char *irq_edge_mask_hi);
+extern void prep_thinkpad_setup_pci(char *irq_edge_mask_lo, char *irq_edge_mask_hi);
+extern void prep_carolina_setup_pci(char *irq_edge_mask_lo, char *irq_edge_mask_hi);
+extern void prep_tiger1_setup_pci(char *irq_edge_mask_lo, char *irq_edge_mask_hi);
+
+
+#define cached_21 (((char *)(ppc_cached_irq_mask))[3])
+#define cached_A1 (((char *)(ppc_cached_irq_mask))[2])
+
+/* for the mac fs */
+dev_t boot_dev;
+
+#ifdef CONFIG_SOUND_CS4232
+long ppc_cs4232_dma, ppc_cs4232_dma2;
+#endif
+
+extern PTE *Hash, *Hash_end;
+extern unsigned long Hash_size, Hash_mask;
+extern int probingmem;
+extern unsigned long loops_per_jiffy;
+
+#ifdef CONFIG_SOUND_CS4232
+EXPORT_SYMBOL(ppc_cs4232_dma);
+EXPORT_SYMBOL(ppc_cs4232_dma2);
+#endif
+
+/* useful ISA ports */
+#define PREP_SYSCTL 0x81c
+/* present in the IBM reference design; possibly identical in Mot boxes: */
+#define PREP_IBM_SIMM_ID 0x803 /* SIMM size: 32 or 8 MiB */
+#define PREP_IBM_SIMM_PRESENCE 0x804
+#define PREP_IBM_EQUIPMENT 0x80c
+#define PREP_IBM_L2INFO 0x80d
+#define PREP_IBM_PM1 0x82a /* power management register 1 */
+#define PREP_IBM_PLANAR 0x852 /* planar ID - identifies the motherboard */
+#define PREP_IBM_DISP 0x8c0 /* 4-digit LED display */
+
+/* Equipment Present Register masks: */
+#define PREP_IBM_EQUIPMENT_RESERVED 0x80
+#define PREP_IBM_EQUIPMENT_SCSIFUSE 0x40
+#define PREP_IBM_EQUIPMENT_L2_COPYBACK 0x08
+#define PREP_IBM_EQUIPMENT_L2_256 0x04
+#define PREP_IBM_EQUIPMENT_CPU 0x02
+#define PREP_IBM_EQUIPMENT_L2 0x01
+
+/* planar ID values: */
+/* Sandalfoot/Sandalbow (6015/7020) */
+#define PREP_IBM_SANDALFOOT 0xfc
+/* Woodfield, Thinkpad 850/860 (6042/7249) */
+#define PREP_IBM_THINKPAD 0xff /* planar ID unimplemented */
+/* PowerSeries 830/850 (6050/6070) */
+#define PREP_IBM_CAROLINA_IDE_0 0xf0
+#define PREP_IBM_CAROLINA_IDE_1 0xf1
+#define PREP_IBM_CAROLINA_IDE_2 0xf2
+#define PREP_IBM_CAROLINA_IDE_3 0xf3
+/* 7248-43P */
+#define PREP_IBM_CAROLINA_SCSI_0 0xf4
+#define PREP_IBM_CAROLINA_SCSI_1 0xf5
+#define PREP_IBM_CAROLINA_SCSI_2 0xf6
+#define PREP_IBM_CAROLINA_SCSI_3 0xf7 /* missing from Carolina Tech Spec */
+/* Tiger1 (7043-140) */
+#define PREP_IBM_TIGER1_133 0xd1
+#define PREP_IBM_TIGER1_166 0xd2
+#define PREP_IBM_TIGER1_180 0xd3
+#define PREP_IBM_TIGER1_xxx 0xd4 /* unknown, but probably exists */
+#define PREP_IBM_TIGER1_333 0xd5 /* missing from Tiger Tech Spec */
+
+/* setup_ibm_pci:
+ * set Motherboard_map_name, Motherboard_map, Motherboard_routes.
+ * return 8259 edge/level masks.
+ */
+void (*setup_ibm_pci)(char *irq_lo, char *irq_hi);
+
+extern char *Motherboard_map_name; /* for use in *_cpuinfo */
+
+/*
+ * As found in the PReP reference implementation.
+ * Used by Thinkpad, Sandalfoot (6015/7020), and all Motorola PReP.
+ */
+static void __init
+prep_gen_enable_l2(void)
+{
+ outb(inb(PREP_SYSCTL) | 0x3, PREP_SYSCTL);
+}
+
+/* Used by Carolina and Tiger1 */
+static void __init
+prep_carolina_enable_l2(void)
+{
+ outb(inb(PREP_SYSCTL) | 0xc0, PREP_SYSCTL);
+}
+
+/* cpuinfo code common to all IBM PReP */
+static void __prep
+prep_ibm_cpuinfo(struct seq_file *m)
+{
+ unsigned int equip_reg = inb(PREP_IBM_EQUIPMENT);
+
+ seq_printf(m, "machine\t\t: PReP %s\n", Motherboard_map_name);
+
+ seq_printf(m, "upgrade cpu\t: ");
+ if (equip_reg & PREP_IBM_EQUIPMENT_CPU) {
+ seq_printf(m, "not ");
+ }
+ seq_printf(m, "present\n");
+
+ /* print info about the SCSI fuse */
+ seq_printf(m, "scsi fuse\t: ");
+ if (equip_reg & PREP_IBM_EQUIPMENT_SCSIFUSE)
+ seq_printf(m, "ok");
+ else
+ seq_printf(m, "bad");
+ seq_printf(m, "\n");
+
+ /* print info about SIMMs */
+ if (have_residual_data) {
+ int i;
+ seq_printf(m, "simms\t\t: ");
+ for (i = 0; (res->ActualNumMemories) && (i < MAX_MEMS); i++) {
+ if (res->Memories[i].SIMMSize != 0)
+ seq_printf(m, "%d:%ldMiB ", i,
+ (res->Memories[i].SIMMSize > 1024) ?
+ res->Memories[i].SIMMSize>>20 :
+ res->Memories[i].SIMMSize);
+ }
+ seq_printf(m, "\n");
+ }
+}
+
+static int __prep
+prep_gen_cpuinfo(struct seq_file *m)
+{
+ prep_ibm_cpuinfo(m);
+ return 0;
+}
+
+static int __prep
+prep_sandalfoot_cpuinfo(struct seq_file *m)
+{
+ unsigned int equip_reg = inb(PREP_IBM_EQUIPMENT);
+
+ prep_ibm_cpuinfo(m);
+
+ /* report amount and type of L2 cache present */
+ seq_printf(m, "L2 cache\t: ");
+ if (equip_reg & PREP_IBM_EQUIPMENT_L2) {
+ seq_printf(m, "not present");
+ } else {
+ if (equip_reg & PREP_IBM_EQUIPMENT_L2_256)
+ seq_printf(m, "256KiB");
+ else
+ seq_printf(m, "unknown size");
+
+ if (equip_reg & PREP_IBM_EQUIPMENT_L2_COPYBACK)
+ seq_printf(m, ", copy-back");
+ else
+ seq_printf(m, ", write-through");
+ }
+ seq_printf(m, "\n");
+
+ return 0;
+}
+
+static int __prep
+prep_thinkpad_cpuinfo(struct seq_file *m)
+{
+ unsigned int equip_reg = inb(PREP_IBM_EQUIPMENT);
+ char *cpubus_speed, *pci_speed;
+
+ prep_ibm_cpuinfo(m);
+
+ /* report amount and type of L2 cache present */
+ seq_printf(m, "l2 cache\t: ");
+ if ((equip_reg & 0x1) == 0) {
+ switch ((equip_reg & 0xc) >> 2) {
+ case 0x0:
+ seq_printf(m, "128KiB look-aside 2-way write-through\n");
+ break;
+ case 0x1:
+ seq_printf(m, "512KiB look-aside direct-mapped write-back\n");
+ break;
+ case 0x2:
+ seq_printf(m, "256KiB look-aside 2-way write-through\n");
+ break;
+ case 0x3:
+ seq_printf(m, "256KiB look-aside direct-mapped write-back\n");
+ break;
+ }
+ } else {
+ seq_printf(m, "not present\n");
+ }
+
+ /* report bus speeds because we can */
+ if ((equip_reg & 0x80) == 0) {
+ switch ((equip_reg & 0x30) >> 4) {
+ case 0x1:
+ cpubus_speed = "50";
+ pci_speed = "25";
+ break;
+ case 0x3:
+ cpubus_speed = "66";
+ pci_speed = "33";
+ break;
+ default:
+ cpubus_speed = "unknown";
+ pci_speed = "unknown";
+ break;
+ }
+ } else {
+ switch ((equip_reg & 0x30) >> 4) {
+ case 0x1:
+ cpubus_speed = "25";
+ pci_speed = "25";
+ break;
+ case 0x2:
+ cpubus_speed = "60";
+ pci_speed = "30";
+ break;
+ case 0x3:
+ cpubus_speed = "33";
+ pci_speed = "33";
+ break;
+ default:
+ cpubus_speed = "unknown";
+ pci_speed = "unknown";
+ break;
+ }
+ }
+ seq_printf(m, "60x bus\t\t: %sMHz\n", cpubus_speed);
+ seq_printf(m, "pci bus\t\t: %sMHz\n", pci_speed);
+
+ return 0;
+}
+
+static int __prep
+prep_carolina_cpuinfo(struct seq_file *m)
+{
+ unsigned int equip_reg = inb(PREP_IBM_EQUIPMENT);
+
+ prep_ibm_cpuinfo(m);
+
+ /* report amount and type of L2 cache present */
+ seq_printf(m, "l2 cache\t: ");
+ if ((equip_reg & 0x1) == 0) {
+ unsigned int l2_reg = inb(PREP_IBM_L2INFO);
+
+ /* L2 size */
+ if ((l2_reg & 0x60) == 0)
+ seq_printf(m, "256KiB");
+ else if ((l2_reg & 0x60) == 0x20)
+ seq_printf(m, "512KiB");
+ else
+ seq_printf(m, "unknown size");
+
+ /* L2 type */
+ if ((l2_reg & 0x3) == 0)
+ seq_printf(m, ", async");
+ else if ((l2_reg & 0x3) == 1)
+ seq_printf(m, ", sync");
+ else
+ seq_printf(m, ", unknown type");
+
+ seq_printf(m, "\n");
+ } else {
+ seq_printf(m, "not present\n");
+ }
+
+ return 0;
+}
+
+static int __prep
+prep_tiger1_cpuinfo(struct seq_file *m)
+{
+ unsigned int l2_reg = inb(PREP_IBM_L2INFO);
+
+ prep_ibm_cpuinfo(m);
+
+ /* report amount and type of L2 cache present */
+ seq_printf(m, "l2 cache\t: ");
+ if ((l2_reg & 0xf) == 0xf) {
+ seq_printf(m, "not present\n");
+ } else {
+ if (l2_reg & 0x8)
+ seq_printf(m, "async, ");
+ else
+ seq_printf(m, "sync burst, ");
+
+ if (l2_reg & 0x4)
+ seq_printf(m, "parity, ");
+ else
+ seq_printf(m, "no parity, ");
+
+ switch (l2_reg & 0x3) {
+ case 0x0:
+ seq_printf(m, "256KiB\n");
+ break;
+ case 0x1:
+ seq_printf(m, "512KiB\n");
+ break;
+ case 0x2:
+ seq_printf(m, "1MiB\n");
+ break;
+ default:
+ seq_printf(m, "unknown size\n");
+ break;
+ }
+ }
+
+ return 0;
+}
+
+
+/* Used by all Motorola PReP */
+static int __prep
+prep_mot_cpuinfo(struct seq_file *m)
+{
+ unsigned int cachew = *((unsigned char *)CACHECRBA);
+
+ seq_printf(m, "machine\t\t: PReP %s\n", Motherboard_map_name);
+
+ /* report amount and type of L2 cache present */
+ seq_printf(m, "l2 cache\t: ");
+ switch (cachew & L2CACHE_MASK) {
+ case L2CACHE_512KB:
+ seq_printf(m, "512KiB");
+ break;
+ case L2CACHE_256KB:
+ seq_printf(m, "256KiB");
+ break;
+ case L2CACHE_1MB:
+ seq_printf(m, "1MiB");
+ break;
+ case L2CACHE_NONE:
+ seq_printf(m, "none\n");
+ goto no_l2;
+ break;
+ default:
+ seq_printf(m, "%x\n", cachew);
+ }
+
+ seq_printf(m, ", parity %s",
+ (cachew & L2CACHE_PARITY)? "enabled" : "disabled");
+
+ seq_printf(m, " SRAM:");
+
+ switch ( ((cachew & 0xf0) >> 4) & ~(0x3) ) {
+ case 1: seq_printf(m, "synchronous, parity, flow-through\n");
+ break;
+ case 2: seq_printf(m, "asynchronous, no parity\n");
+ break;
+ case 3: seq_printf(m, "asynchronous, parity\n");
+ break;
+ default:seq_printf(m, "synchronous, pipelined, no parity\n");
+ break;
+ }
+
+no_l2:
+ /* print info about SIMMs */
+ if (have_residual_data) {
+ int i;
+ seq_printf(m, "simms\t\t: ");
+ for (i = 0; (res->ActualNumMemories) && (i < MAX_MEMS); i++) {
+ if (res->Memories[i].SIMMSize != 0)
+ seq_printf(m, "%d:%ldM ", i,
+ (res->Memories[i].SIMMSize > 1024) ?
+ res->Memories[i].SIMMSize>>20 :
+ res->Memories[i].SIMMSize);
+ }
+ seq_printf(m, "\n");
+ }
+
+ return 0;
+}
+
+static void __prep
+prep_restart(char *cmd)
+{
+#define PREP_SP92 0x92 /* Special Port 92 */
+ local_irq_disable(); /* no interrupts */
+
+ /* set exception prefix high - to the prom */
+ _nmask_and_or_msr(0, MSR_IP);
+
+ /* make sure bit 0 (reset) is a 0 */
+ outb( inb(PREP_SP92) & ~1L , PREP_SP92);
+ /* signal a reset to system control port A - soft reset */
+ outb( inb(PREP_SP92) | 1 , PREP_SP92);
+
+ while ( 1 ) ;
+ /* not reached */
+#undef PREP_SP92
+}
+
+static void __prep
+prep_halt(void)
+{
+ local_irq_disable(); /* no interrupts */
+
+ /* set exception prefix high - to the prom */
+ _nmask_and_or_msr(0, MSR_IP);
+
+ while ( 1 ) ;
+ /* not reached */
+}
+
+/* Carrera is the power manager in the Thinkpads. Unfortunately not much is
+ * known about it, so we can't power down.
+ */
+static void __prep
+prep_carrera_poweroff(void)
+{
+ prep_halt();
+}
+
+/*
+ * On most IBM PReP's, power management is handled by a Signetics 87c750
+ * behind the Utah component on the ISA bus. To access the 750 you must write
+ * a series of nibbles to port 0x82a (decoded by the Utah). This is described
+ * somewhat in the IBM Carolina Technical Specification.
+ * -Hollis
+ */
+static void __prep
+utah_sig87c750_setbit(unsigned int bytenum, unsigned int bitnum, int value)
+{
+ /*
+ * byte1: 0 0 0 1 0 d a5 a4
+ * byte2: 0 0 0 1 a3 a2 a1 a0
+ *
+ * d = the bit's value, enabled or disabled
+ * (a5 a4 a3) = the byte number, minus 20
+ * (a2 a1 a0) = the bit number
+ *
+ * example: set the 5th bit of byte 21 (21.5)
+ * a5 a4 a3 = 001 (byte 1)
+ * a2 a1 a0 = 101 (bit 5)
+ *
+ * byte1 = 0001 0100 (0x14)
+ * byte2 = 0001 1101 (0x1d)
+ */
+ unsigned char byte1=0x10, byte2=0x10;
+
+ /* the 750's '20.0' is accessed as '0.0' through Utah (which adds 20) */
+ bytenum -= 20;
+
+ byte1 |= (!!value) << 2; /* set d */
+ byte1 |= (bytenum >> 1) & 0x3; /* set a5, a4 */
+
+ byte2 |= (bytenum & 0x1) << 3; /* set a3 */
+ byte2 |= bitnum & 0x7; /* set a2, a1, a0 */
+
+ outb(byte1, PREP_IBM_PM1); /* first nibble */
+ mb();
+ udelay(100); /* important: let controller recover */
+
+ outb(byte2, PREP_IBM_PM1); /* second nibble */
+ mb();
+ udelay(100); /* important: let controller recover */
+}
+
+static void __prep
+prep_sig750_poweroff(void)
+{
+ /* tweak the power manager found in most IBM PRePs (except Thinkpads) */
+
+ local_irq_disable();
+ /* set exception prefix high - to the prom */
+ _nmask_and_or_msr(0, MSR_IP);
+
+ utah_sig87c750_setbit(21, 5, 1); /* set bit 21.5, "PMEXEC_OFF" */
+
+ while (1) ;
+ /* not reached */
+}
+
+static int __prep
+prep_show_percpuinfo(struct seq_file *m, int i)
+{
+ /* PREP's without residual data will give incorrect values here */
+ seq_printf(m, "clock\t\t: ");
+ if (have_residual_data)
+ seq_printf(m, "%ldMHz\n",
+ (res->VitalProductData.ProcessorHz > 1024) ?
+ res->VitalProductData.ProcessorHz / 1000000 :
+ res->VitalProductData.ProcessorHz);
+ else
+ seq_printf(m, "???\n");
+
+ return 0;
+}
+
+#ifdef CONFIG_SOUND_CS4232
+static long __init masktoint(unsigned int i)
+{
+ int t = -1;
+ while (i >> ++t)
+ ;
+ return (t-1);
+}
+
+/*
+ * ppc_cs4232_dma and ppc_cs4232_dma2 are used in include/asm/dma.h
+ * to distinguish sound dma-channels from others. This is because
+ * blocksize on 16 bit dma-channels 5,6,7 is 128k, but
+ * the cs4232.c uses 64k like on 8 bit dma-channels 0,1,2,3
+ */
+
+static void __init prep_init_sound(void)
+{
+ PPC_DEVICE *audiodevice = NULL;
+
+ /*
+ * Get the needed resource informations from residual data.
+ *
+ */
+ if (have_residual_data)
+ audiodevice = residual_find_device(~0, NULL,
+ MultimediaController, AudioController, -1, 0);
+
+ if (audiodevice != NULL) {
+ PnP_TAG_PACKET *pkt;
+
+ pkt = PnP_find_packet((unsigned char *)&res->DevicePnPHeap[audiodevice->AllocatedOffset],
+ S5_Packet, 0);
+ if (pkt != NULL)
+ ppc_cs4232_dma = masktoint(pkt->S5_Pack.DMAMask);
+ pkt = PnP_find_packet((unsigned char*)&res->DevicePnPHeap[audiodevice->AllocatedOffset],
+ S5_Packet, 1);
+ if (pkt != NULL)
+ ppc_cs4232_dma2 = masktoint(pkt->S5_Pack.DMAMask);
+ }
+
+ /*
+ * These are the PReP specs' defaults for the cs4231. We use these
+ * as fallback incase we don't have residual data.
+ * At least the IBM Thinkpad 850 with IDE DMA Channels at 6 and 7
+ * will use the other values.
+ */
+ if (audiodevice == NULL) {
+ switch (_prep_type) {
+ case _PREP_IBM:
+ ppc_cs4232_dma = 1;
+ ppc_cs4232_dma2 = -1;
+ break;
+ default:
+ ppc_cs4232_dma = 6;
+ ppc_cs4232_dma2 = 7;
+ }
+ }
+
+ /*
+ * Find a way to push these informations to the cs4232 driver
+ * Give it out with printk, when not in cmd_line?
+ * Append it to cmd_line and saved_command_line?
+ * Format is cs4232=io,irq,dma,dma2
+ */
+}
+#endif /* CONFIG_SOUND_CS4232 */
+
+/*
+ * Fill out screen_info according to the residual data. This allows us to use
+ * at least vesafb.
+ */
+static void __init
+prep_init_vesa(void)
+{
+#if (defined(CONFIG_FB_VGA16) || defined(CONFIG_FB_VGA16_MODULE) || \
+ defined(CONFIG_FB_VESA))
+ PPC_DEVICE *vgadev = NULL;
+
+ if (have_residual_data)
+ vgadev = residual_find_device(~0, NULL, DisplayController,
+ SVGAController, -1, 0);
+
+ if (vgadev != NULL) {
+ PnP_TAG_PACKET *pkt;
+
+ pkt = PnP_find_large_vendor_packet(
+ (unsigned char *)&res->DevicePnPHeap[vgadev->AllocatedOffset],
+ 0x04, 0); /* 0x04 = Display Tag */
+ if (pkt != NULL) {
+ unsigned char *ptr = (unsigned char *)pkt;
+
+ if (ptr[4]) {
+ /* graphics mode */
+ screen_info.orig_video_isVGA = VIDEO_TYPE_VLFB;
+
+ screen_info.lfb_depth = ptr[4] * 8;
+
+ screen_info.lfb_width = swab16(*(short *)(ptr+6));
+ screen_info.lfb_height = swab16(*(short *)(ptr+8));
+ screen_info.lfb_linelength = swab16(*(short *)(ptr+10));
+
+ screen_info.lfb_base = swab32(*(long *)(ptr+12));
+ screen_info.lfb_size = swab32(*(long *)(ptr+20)) / 65536;
+ }
+ }
+ }
+#endif
+}
+
+/*
+ * Set DBAT 2 to access 0x80000000 so early progress messages will work
+ */
+static __inline__ void
+prep_set_bat(void)
+{
+ /* wait for all outstanding memory access to complete */
+ mb();
+
+ /* setup DBATs */
+ mtspr(SPRN_DBAT2U, 0x80001ffe);
+ mtspr(SPRN_DBAT2L, 0x8000002a);
+
+ /* wait for updates */
+ mb();
+}
+
+/*
+ * IBM 3-digit status LED
+ */
+static unsigned int ibm_statusled_base __prepdata;
+
+static void __prep
+ibm_statusled_progress(char *s, unsigned short hex);
+
+static int __prep
+ibm_statusled_panic(struct notifier_block *dummy1, unsigned long dummy2,
+ void * dummy3)
+{
+ ibm_statusled_progress(NULL, 0x505); /* SOS */
+ return NOTIFY_DONE;
+}
+
+static struct notifier_block ibm_statusled_block __prepdata = {
+ ibm_statusled_panic,
+ NULL,
+ INT_MAX /* try to do it first */
+};
+
+static void __prep
+ibm_statusled_progress(char *s, unsigned short hex)
+{
+ static int notifier_installed;
+ /*
+ * Progress uses 4 digits and we have only 3. So, we map 0xffff to
+ * 0xfff for display switch off. Out of range values are mapped to
+ * 0xeff, as I'm told 0xf00 and above are reserved for hardware codes.
+ * Install the panic notifier when the display is first switched off.
+ */
+ if (hex == 0xffff) {
+ hex = 0xfff;
+ if (!notifier_installed) {
+ ++notifier_installed;
+ notifier_chain_register(&panic_notifier_list,
+ &ibm_statusled_block);
+ }
+ }
+ else
+ if (hex > 0xfff)
+ hex = 0xeff;
+
+ mb();
+ outw(hex, ibm_statusled_base);
+}
+
+static void __init
+ibm_statusled_init(void)
+{
+ /*
+ * The IBM 3-digit LED display is specified in the residual data
+ * as an operator panel device, type "System Status LED". Find
+ * that device and determine its address. We validate all the
+ * other parameters on the off-chance another, similar device
+ * exists.
+ */
+ if (have_residual_data) {
+ PPC_DEVICE *led;
+ PnP_TAG_PACKET *pkt;
+
+ led = residual_find_device(~0, NULL, SystemPeripheral,
+ OperatorPanel, SystemStatusLED, 0);
+ if (!led)
+ return;
+
+ pkt = PnP_find_packet((unsigned char *)
+ &res->DevicePnPHeap[led->AllocatedOffset], S8_Packet, 0);
+ if (!pkt)
+ return;
+
+ if (pkt->S8_Pack.IOInfo != ISAAddr16bit)
+ return;
+ if (*(unsigned short *)pkt->S8_Pack.RangeMin !=
+ *(unsigned short *)pkt->S8_Pack.RangeMax)
+ return;
+ if (pkt->S8_Pack.IOAlign != 2)
+ return;
+ if (pkt->S8_Pack.IONum != 2)
+ return;
+
+ ibm_statusled_base = ld_le16((unsigned short *)
+ (pkt->S8_Pack.RangeMin));
+ ppc_md.progress = ibm_statusled_progress;
+ }
+}
+
+static void __init
+prep_setup_arch(void)
+{
+ unsigned char reg;
+ int is_ide=0;
+
+ /* init to some ~sane value until calibrate_delay() runs */
+ loops_per_jiffy = 50000000;
+
+ /* Lookup PCI host bridges */
+ prep_find_bridges();
+
+ /* Set up floppy in PS/2 mode */
+ outb(0x09, SIO_CONFIG_RA);
+ reg = inb(SIO_CONFIG_RD);
+ reg = (reg & 0x3F) | 0x40;
+ outb(reg, SIO_CONFIG_RD);
+ outb(reg, SIO_CONFIG_RD); /* Have to write twice to change! */
+
+ switch ( _prep_type )
+ {
+ case _PREP_IBM:
+ reg = inb(PREP_IBM_PLANAR);
+ printk(KERN_INFO "IBM planar ID: %02x", reg);
+ switch (reg) {
+ case PREP_IBM_SANDALFOOT:
+ prep_gen_enable_l2();
+ setup_ibm_pci = prep_sandalfoot_setup_pci;
+ ppc_md.power_off = prep_sig750_poweroff;
+ ppc_md.show_cpuinfo = prep_sandalfoot_cpuinfo;
+ break;
+ case PREP_IBM_THINKPAD:
+ prep_gen_enable_l2();
+ setup_ibm_pci = prep_thinkpad_setup_pci;
+ ppc_md.power_off = prep_carrera_poweroff;
+ ppc_md.show_cpuinfo = prep_thinkpad_cpuinfo;
+ break;
+ default:
+ if (have_residual_data) {
+ prep_gen_enable_l2();
+ setup_ibm_pci = prep_residual_setup_pci;
+ ppc_md.power_off = prep_halt;
+ ppc_md.show_cpuinfo = prep_gen_cpuinfo;
+ break;
+ }
+ else
+ printk(" - unknown! Assuming Carolina");
+ /* fall through */
+ case PREP_IBM_CAROLINA_IDE_0:
+ case PREP_IBM_CAROLINA_IDE_1:
+ case PREP_IBM_CAROLINA_IDE_2:
+ case PREP_IBM_CAROLINA_IDE_3:
+ is_ide = 1;
+ case PREP_IBM_CAROLINA_SCSI_0:
+ case PREP_IBM_CAROLINA_SCSI_1:
+ case PREP_IBM_CAROLINA_SCSI_2:
+ case PREP_IBM_CAROLINA_SCSI_3:
+ prep_carolina_enable_l2();
+ setup_ibm_pci = prep_carolina_setup_pci;
+ ppc_md.power_off = prep_sig750_poweroff;
+ ppc_md.show_cpuinfo = prep_carolina_cpuinfo;
+ break;
+ case PREP_IBM_TIGER1_133:
+ case PREP_IBM_TIGER1_166:
+ case PREP_IBM_TIGER1_180:
+ case PREP_IBM_TIGER1_xxx:
+ case PREP_IBM_TIGER1_333:
+ prep_carolina_enable_l2();
+ setup_ibm_pci = prep_tiger1_setup_pci;
+ ppc_md.power_off = prep_sig750_poweroff;
+ ppc_md.show_cpuinfo = prep_tiger1_cpuinfo;
+ break;
+ }
+ printk("\n");
+
+ /* default root device */
+ if (is_ide)
+ ROOT_DEV = MKDEV(IDE0_MAJOR, 3);
+ else
+ ROOT_DEV = MKDEV(SCSI_DISK0_MAJOR, 3);
+
+ break;
+ case _PREP_Motorola:
+ prep_gen_enable_l2();
+ ppc_md.power_off = prep_halt;
+ ppc_md.show_cpuinfo = prep_mot_cpuinfo;
+
+#ifdef CONFIG_BLK_DEV_INITRD
+ if (initrd_start)
+ ROOT_DEV = Root_RAM0;
+ else
+#endif
+#ifdef CONFIG_ROOT_NFS
+ ROOT_DEV = Root_NFS;
+#else
+ ROOT_DEV = Root_SDA2;
+#endif
+ break;
+ }
+
+ /* Read in NVRAM data */
+ init_prep_nvram();
+
+ /* if no bootargs, look in NVRAM */
+ if ( cmd_line[0] == '\0' ) {
+ char *bootargs;
+ bootargs = prep_nvram_get_var("bootargs");
+ if (bootargs != NULL) {
+ strcpy(cmd_line, bootargs);
+ /* again.. */
+ strcpy(saved_command_line, cmd_line);
+ }
+ }
+
+#ifdef CONFIG_SOUND_CS4232
+ prep_init_sound();
+#endif /* CONFIG_SOUND_CS4232 */
+
+ prep_init_vesa();
+
+ switch (_prep_type) {
+ case _PREP_Motorola:
+ raven_init();
+ break;
+ case _PREP_IBM:
+ ibm_prep_init();
+ break;
+ }
+
+#ifdef CONFIG_VGA_CONSOLE
+ /* vgacon.c needs to know where we mapped IO memory in io_block_mapping() */
+ vgacon_remap_base = 0xf0000000;
+ conswitchp = &vga_con;
+#endif
+}
+
+/*
+ * First, see if we can get this information from the residual data.
+ * This is important on some IBM PReP systems. If we cannot, we let the
+ * TODC code handle doing this.
+ */
+static void __init
+prep_calibrate_decr(void)
+{
+ if (have_residual_data) {
+ unsigned long freq, divisor = 4;
+
+ if ( res->VitalProductData.ProcessorBusHz ) {
+ freq = res->VitalProductData.ProcessorBusHz;
+ printk("time_init: decrementer frequency = %lu.%.6lu MHz\n",
+ (freq/divisor)/1000000,
+ (freq/divisor)%1000000);
+ tb_to_us = mulhwu_scale_factor(freq/divisor, 1000000);
+ tb_ticks_per_jiffy = freq / HZ / divisor;
+ }
+ }
+ else
+ todc_calibrate_decr();
+}
+
+static unsigned int __prep
+prep_irq_canonicalize(u_int irq)
+{
+ if (irq == 2)
+ {
+ return 9;
+ }
+ else
+ {
+ return irq;
+ }
+}
+
+static void __init
+prep_init_IRQ(void)
+{
+ int i;
+ unsigned int pci_viddid, pci_did;
+
+ if (OpenPIC_Addr != NULL) {
+ openpic_init(NUM_8259_INTERRUPTS);
+ /* We have a cascade on OpenPIC IRQ 0, Linux IRQ 16 */
+ openpic_hookup_cascade(NUM_8259_INTERRUPTS, "82c59 cascade",
+ i8259_irq);
+ }
+ for ( i = 0 ; i < NUM_8259_INTERRUPTS ; i++ )
+ irq_desc[i].handler = &i8259_pic;
+
+ if (have_residual_data) {
+ i8259_init(residual_isapic_addr());
+ return;
+ }
+
+ /* If we have a Raven PCI bridge or a Hawk PCI bridge / Memory
+ * controller, we poll (as they have a different int-ack address). */
+ early_read_config_dword(NULL, 0, 0, PCI_VENDOR_ID, &pci_viddid);
+ pci_did = (pci_viddid & 0xffff0000) >> 16;
+ if (((pci_viddid & 0xffff) == PCI_VENDOR_ID_MOTOROLA)
+ && ((pci_did == PCI_DEVICE_ID_MOTOROLA_RAVEN)
+ || (pci_did == PCI_DEVICE_ID_MOTOROLA_HAWK)))
+ i8259_init(0);
+ else
+ /* PCI interrupt ack address given in section 6.1.8 of the
+ * PReP specification. */
+ i8259_init(MPC10X_MAPA_PCI_INTACK_ADDR);
+}
+
+#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
+/*
+ * IDE stuff.
+ */
+static int __prep
+prep_ide_default_irq(unsigned long base)
+{
+ switch (base) {
+ case 0x1f0: return 13;
+ case 0x170: return 13;
+ case 0x1e8: return 11;
+ case 0x168: return 10;
+ case 0xfff0: return 14; /* MCP(N)750 ide0 */
+ case 0xffe0: return 15; /* MCP(N)750 ide1 */
+ default: return 0;
+ }
+}
+
+static unsigned long __prep
+prep_ide_default_io_base(int index)
+{
+ switch (index) {
+ case 0: return 0x1f0;
+ case 1: return 0x170;
+ case 2: return 0x1e8;
+ case 3: return 0x168;
+ default:
+ return 0;
+ }
+}
+#endif
+
+#ifdef CONFIG_SMP
+/* PReP (MTX) support */
+static int __init
+smp_prep_probe(void)
+{
+ extern int mot_multi;
+
+ if (mot_multi) {
+ openpic_request_IPIs();
+ smp_hw_index[1] = 1;
+ return 2;
+ }
+
+ return 1;
+}
+
+static void __init
+smp_prep_kick_cpu(int nr)
+{
+ *(unsigned long *)KERNELBASE = nr;
+ asm volatile("dcbf 0,%0"::"r"(KERNELBASE):"memory");
+ printk("CPU1 released, waiting\n");
+}
+
+static void __init
+smp_prep_setup_cpu(int cpu_nr)
+{
+ if (OpenPIC_Addr)
+ do_openpic_setup_cpu();
+}
+
+static struct smp_ops_t prep_smp_ops __prepdata = {
+ smp_openpic_message_pass,
+ smp_prep_probe,
+ smp_prep_kick_cpu,
+ smp_prep_setup_cpu,
+ .give_timebase = smp_generic_give_timebase,
+ .take_timebase = smp_generic_take_timebase,
+};
+#endif /* CONFIG_SMP */
+
+/*
+ * Setup the bat mappings we're going to load that cover
+ * the io areas. RAM was mapped by mapin_ram().
+ * -- Cort
+ */
+static void __init
+prep_map_io(void)
+{
+ io_block_mapping(0x80000000, PREP_ISA_IO_BASE, 0x10000000, _PAGE_IO);
+ io_block_mapping(0xf0000000, PREP_ISA_MEM_BASE, 0x08000000, _PAGE_IO);
+}
+
+static int __init
+prep_request_io(void)
+{
+ if (_machine == _MACH_prep) {
+#ifdef CONFIG_NVRAM
+ request_region(PREP_NVRAM_AS0, 0x8, "nvram");
+#endif
+ request_region(0x00,0x20,"dma1");
+ request_region(0x40,0x20,"timer");
+ request_region(0x80,0x10,"dma page reg");
+ request_region(0xc0,0x20,"dma2");
+ }
+
+ return 0;
+}
+
+device_initcall(prep_request_io);
+
+void __init
+prep_init(unsigned long r3, unsigned long r4, unsigned long r5,
+ unsigned long r6, unsigned long r7)
+{
+#ifdef CONFIG_PREP_RESIDUAL
+ /* make a copy of residual data */
+ if ( r3 ) {
+ memcpy((void *)res,(void *)(r3+KERNELBASE),
+ sizeof(RESIDUAL));
+ }
+#endif
+
+ isa_io_base = PREP_ISA_IO_BASE;
+ isa_mem_base = PREP_ISA_MEM_BASE;
+ pci_dram_offset = PREP_PCI_DRAM_OFFSET;
+ ISA_DMA_THRESHOLD = 0x00ffffff;
+ DMA_MODE_READ = 0x44;
+ DMA_MODE_WRITE = 0x48;
+
+ /* figure out what kind of prep workstation we are */
+ if (have_residual_data) {
+ if ( !strncmp(res->VitalProductData.PrintableModel,"IBM",3) )
+ _prep_type = _PREP_IBM;
+ else
+ _prep_type = _PREP_Motorola;
+ }
+ else {
+ /* assume motorola if no residual (netboot?) */
+ _prep_type = _PREP_Motorola;
+ }
+
+#ifdef CONFIG_PREP_RESIDUAL
+ /* Switch off all residual data processing if the user requests it */
+ if (strstr(cmd_line, "noresidual") != NULL)
+ res = NULL;
+#endif
+
+ /* Initialise progress early to get maximum benefit */
+ prep_set_bat();
+ ibm_statusled_init();
+
+ ppc_md.setup_arch = prep_setup_arch;
+ ppc_md.show_percpuinfo = prep_show_percpuinfo;
+ ppc_md.show_cpuinfo = NULL; /* set in prep_setup_arch() */
+ ppc_md.irq_canonicalize = prep_irq_canonicalize;
+ ppc_md.init_IRQ = prep_init_IRQ;
+ /* this gets changed later on if we have an OpenPIC -- Cort */
+ ppc_md.get_irq = i8259_irq;
+
+ ppc_md.phys_mem_access_prot = pci_phys_mem_access_prot;
+
+ ppc_md.restart = prep_restart;
+ ppc_md.power_off = NULL; /* set in prep_setup_arch() */
+ ppc_md.halt = prep_halt;
+
+ ppc_md.nvram_read_val = prep_nvram_read_val;
+ ppc_md.nvram_write_val = prep_nvram_write_val;
+
+ ppc_md.time_init = todc_time_init;
+ if (_prep_type == _PREP_IBM) {
+ ppc_md.rtc_read_val = todc_mc146818_read_val;
+ ppc_md.rtc_write_val = todc_mc146818_write_val;
+ TODC_INIT(TODC_TYPE_MC146818, RTC_PORT(0), NULL, RTC_PORT(1),
+ 8);
+ } else {
+ TODC_INIT(TODC_TYPE_MK48T59, PREP_NVRAM_AS0, PREP_NVRAM_AS1,
+ PREP_NVRAM_DATA, 8);
+ }
+
+ ppc_md.calibrate_decr = prep_calibrate_decr;
+ ppc_md.set_rtc_time = todc_set_rtc_time;
+ ppc_md.get_rtc_time = todc_get_rtc_time;
+
+ ppc_md.setup_io_mappings = prep_map_io;
+
+#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
+ ppc_ide_md.default_irq = prep_ide_default_irq;
+ ppc_ide_md.default_io_base = prep_ide_default_io_base;
+#endif
+
+#ifdef CONFIG_SMP
+ ppc_md.smp_ops = &prep_smp_ops;
+#endif /* CONFIG_SMP */
+}
diff --git a/arch/ppc/platforms/prpmc750.c b/arch/ppc/platforms/prpmc750.c
new file mode 100644
index 0000000..c894e1a
--- /dev/null
+++ b/arch/ppc/platforms/prpmc750.c
@@ -0,0 +1,364 @@
+/*
+ * arch/ppc/platforms/prpmc750_setup.c
+ *
+ * Board setup routines for Motorola PrPMC750
+ *
+ * Author: Matt Porter <mporter@mvista.com>
+ *
+ * 2001-2004 (c) MontaVista, Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+
+#include <linux/config.h>
+#include <linux/stddef.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/reboot.h>
+#include <linux/pci.h>
+#include <linux/kdev_t.h>
+#include <linux/types.h>
+#include <linux/major.h>
+#include <linux/initrd.h>
+#include <linux/console.h>
+#include <linux/delay.h>
+#include <linux/irq.h>
+#include <linux/seq_file.h>
+#include <linux/ide.h>
+#include <linux/root_dev.h>
+#include <linux/slab.h>
+
+#include <asm/byteorder.h>
+#include <asm/system.h>
+#include <asm/pgtable.h>
+#include <asm/page.h>
+#include <asm/dma.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/machdep.h>
+#include <asm/pci-bridge.h>
+#include <asm/uaccess.h>
+#include <asm/time.h>
+#include <asm/open_pic.h>
+#include <asm/bootinfo.h>
+#include <asm/hawk.h>
+
+#include "prpmc750.h"
+
+extern unsigned long loops_per_jiffy;
+
+extern void gen550_progress(char *, unsigned short);
+
+static u_char prpmc750_openpic_initsenses[] __initdata =
+{
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* PRPMC750_INT_HOSTINT0 */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* PRPMC750_INT_UART */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* PRPMC750_INT_DEBUGINT */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* PRPMC750_INT_HAWK_WDT */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* PRPMC750_INT_UNUSED */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* PRPMC750_INT_ABORT */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* PRPMC750_INT_HOSTINT1 */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* PRPMC750_INT_HOSTINT2 */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* PRPMC750_INT_HOSTINT3 */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* PRPMC750_INT_PMC_INTA */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* PRPMC750_INT_PMC_INTB */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* PRPMC750_INT_PMC_INTC */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* PRPMC750_INT_PMC_INTD */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* PRPMC750_INT_UNUSED */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* PRPMC750_INT_UNUSED */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* PRPMC750_INT_UNUSED */
+};
+
+/*
+ * Motorola PrPMC750/PrPMC800 in PrPMCBASE or PrPMC-Carrier
+ * Combined irq tables. Only Base has IDSEL 14, only Carrier has 21 and 22.
+ */
+static inline int
+prpmc_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin)
+{
+ static char pci_irq_table[][4] =
+ /*
+ * PCI IDSEL/INTPIN->INTLINE
+ * A B C D
+ */
+ {
+ {12, 0, 0, 0}, /* IDSEL 14 - Ethernet, base */
+ {0, 0, 0, 0}, /* IDSEL 15 - unused */
+ {10, 11, 12, 9}, /* IDSEL 16 - PMC A1, PMC1 */
+ {10, 11, 12, 9}, /* IDSEL 17 - PrPMC-A-B, PMC2-B */
+ {11, 12, 9, 10}, /* IDSEL 18 - PMC A1-B, PMC1-B */
+ {0, 0, 0, 0}, /* IDSEL 19 - unused */
+ {9, 10, 11, 12}, /* IDSEL 20 - P2P Bridge */
+ {11, 12, 9, 10}, /* IDSEL 21 - PMC A2, carrier */
+ {12, 9, 10, 11}, /* IDSEL 22 - PMC A2-B, carrier */
+ };
+ const long min_idsel = 14, max_idsel = 22, irqs_per_slot = 4;
+ return PCI_IRQ_TABLE_LOOKUP;
+};
+
+static void __init prpmc750_pcibios_fixup(void)
+{
+ struct pci_dev *dev;
+ unsigned short wtmp;
+
+ /*
+ * Kludge to clean up after PPC6BUG which doesn't
+ * configure the CL5446 VGA card. Also the
+ * resource subsystem doesn't fixup the
+ * PCI mem resources on the CL5446.
+ */
+ if ((dev = pci_get_device(PCI_VENDOR_ID_CIRRUS,
+ PCI_DEVICE_ID_CIRRUS_5446, 0))) {
+ dev->resource[0].start += PRPMC750_PCI_PHY_MEM_OFFSET;
+ dev->resource[0].end += PRPMC750_PCI_PHY_MEM_OFFSET;
+ pci_read_config_word(dev, PCI_COMMAND, &wtmp);
+ pci_write_config_word(dev, PCI_COMMAND, wtmp | 3);
+ /* Enable Color mode in MISC reg */
+ outb(0x03, 0x3c2);
+ /* Select DRAM config reg */
+ outb(0x0f, 0x3c4);
+ /* Set proper DRAM config */
+ outb(0xdf, 0x3c5);
+ pci_dev_put(dev);
+ }
+}
+
+void __init prpmc750_find_bridges(void)
+{
+ struct pci_controller *hose;
+
+ hose = pcibios_alloc_controller();
+ if (!hose)
+ return;
+
+ hose->first_busno = 0;
+ hose->last_busno = 0xff;
+ hose->io_base_virt = (void *)PRPMC750_ISA_IO_BASE;
+ hose->pci_mem_offset = PRPMC750_PCI_PHY_MEM_OFFSET;
+
+ pci_init_resource(&hose->io_resource,
+ PRPMC750_PCI_IO_START,
+ PRPMC750_PCI_IO_END,
+ IORESOURCE_IO, "PCI host bridge");
+
+ pci_init_resource(&hose->mem_resources[0],
+ PRPMC750_PROC_PCI_MEM_START,
+ PRPMC750_PROC_PCI_MEM_END,
+ IORESOURCE_MEM, "PCI host bridge");
+
+ hose->io_space.start = PRPMC750_PCI_IO_START;
+ hose->io_space.end = PRPMC750_PCI_IO_END;
+ hose->mem_space.start = PRPMC750_PCI_MEM_START;
+ hose->mem_space.end = PRPMC750_PCI_MEM_END - HAWK_MPIC_SIZE;
+
+ if (hawk_init(hose, PRPMC750_HAWK_PPC_REG_BASE,
+ PRPMC750_PROC_PCI_MEM_START,
+ PRPMC750_PROC_PCI_MEM_END - HAWK_MPIC_SIZE,
+ PRPMC750_PROC_PCI_IO_START, PRPMC750_PROC_PCI_IO_END,
+ PRPMC750_PROC_PCI_MEM_END - HAWK_MPIC_SIZE + 1)
+ != 0) {
+ printk(KERN_CRIT "Could not initialize host bridge\n");
+ }
+
+ hose->last_busno = pciauto_bus_scan(hose, hose->first_busno);
+
+ ppc_md.pcibios_fixup = prpmc750_pcibios_fixup;
+ ppc_md.pci_swizzle = common_swizzle;
+ ppc_md.pci_map_irq = prpmc_map_irq;
+}
+static int prpmc750_show_cpuinfo(struct seq_file *m)
+{
+ seq_printf(m, "machine\t\t: PrPMC750\n");
+
+ return 0;
+}
+
+static void __init prpmc750_setup_arch(void)
+{
+ /* init to some ~sane value until calibrate_delay() runs */
+ loops_per_jiffy = 50000000 / HZ;
+
+ /* Lookup PCI host bridges */
+ prpmc750_find_bridges();
+
+#ifdef CONFIG_BLK_DEV_INITRD
+ if (initrd_start)
+ ROOT_DEV = Root_RAM0;
+ else
+#endif
+#ifdef CONFIG_ROOT_NFS
+ ROOT_DEV = Root_NFS;
+#else
+ ROOT_DEV = Root_SDA2;
+#endif
+
+ OpenPIC_InitSenses = prpmc750_openpic_initsenses;
+ OpenPIC_NumInitSenses = sizeof(prpmc750_openpic_initsenses);
+
+ printk(KERN_INFO "Port by MontaVista Software, Inc. "
+ "(source@mvista.com)\n");
+}
+
+/*
+ * Compute the PrPMC750's bus speed using the baud clock as a
+ * reference.
+ */
+static unsigned long __init prpmc750_get_bus_speed(void)
+{
+ unsigned long tbl_start, tbl_end;
+ unsigned long current_state, old_state, bus_speed;
+ unsigned char lcr, dll, dlm;
+ int baud_divisor, count;
+
+ /* Read the UART's baud clock divisor */
+ lcr = readb(PRPMC750_SERIAL_0_LCR);
+ writeb(lcr | UART_LCR_DLAB, PRPMC750_SERIAL_0_LCR);
+ dll = readb(PRPMC750_SERIAL_0_DLL);
+ dlm = readb(PRPMC750_SERIAL_0_DLM);
+ writeb(lcr & ~UART_LCR_DLAB, PRPMC750_SERIAL_0_LCR);
+ baud_divisor = (dlm << 8) | dll;
+
+ /*
+ * Use the baud clock divisor and base baud clock
+ * to determine the baud rate and use that as
+ * the number of baud clock edges we use for
+ * the time base sample. Make it half the baud
+ * rate.
+ */
+ count = PRPMC750_BASE_BAUD / (baud_divisor * 16);
+
+ /* Find the first edge of the baud clock */
+ old_state = readb(PRPMC750_STATUS_REG) & PRPMC750_BAUDOUT_MASK;
+ do {
+ current_state = readb(PRPMC750_STATUS_REG) &
+ PRPMC750_BAUDOUT_MASK;
+ } while (old_state == current_state);
+
+ old_state = current_state;
+
+ /* Get the starting time base value */
+ tbl_start = get_tbl();
+
+ /*
+ * Loop until we have found a number of edges equal
+ * to half the count (half the baud rate)
+ */
+ do {
+ do {
+ current_state = readb(PRPMC750_STATUS_REG) &
+ PRPMC750_BAUDOUT_MASK;
+ } while (old_state == current_state);
+ old_state = current_state;
+ } while (--count);
+
+ /* Get the ending time base value */
+ tbl_end = get_tbl();
+
+ /* Compute bus speed */
+ bus_speed = (tbl_end - tbl_start) * 128;
+
+ return bus_speed;
+}
+
+static void __init prpmc750_calibrate_decr(void)
+{
+ unsigned long freq;
+ int divisor = 4;
+
+ freq = prpmc750_get_bus_speed();
+
+ tb_ticks_per_jiffy = freq / (HZ * divisor);
+ tb_to_us = mulhwu_scale_factor(freq / divisor, 1000000);
+}
+
+static void prpmc750_restart(char *cmd)
+{
+ local_irq_disable();
+ writeb(PRPMC750_MODRST_MASK, PRPMC750_MODRST_REG);
+ while (1) ;
+}
+
+static void prpmc750_halt(void)
+{
+ local_irq_disable();
+ while (1) ;
+}
+
+static void prpmc750_power_off(void)
+{
+ prpmc750_halt();
+}
+
+static void __init prpmc750_init_IRQ(void)
+{
+ openpic_init(0);
+}
+
+/*
+ * Set BAT 3 to map 0xf0000000 to end of physical memory space.
+ */
+static __inline__ void prpmc750_set_bat(void)
+{
+ mb();
+ mtspr(SPRN_DBAT1U, 0xf0001ffe);
+ mtspr(SPRN_DBAT1L, 0xf000002a);
+ mb();
+}
+
+/*
+ * We need to read the Falcon/Hawk memory controller
+ * to properly determine this value
+ */
+static unsigned long __init prpmc750_find_end_of_memory(void)
+{
+ /* Read the memory size from the Hawk SMC */
+ return hawk_get_mem_size(PRPMC750_HAWK_SMC_BASE);
+}
+
+static void __init prpmc750_map_io(void)
+{
+ io_block_mapping(PRPMC750_ISA_IO_BASE, PRPMC750_ISA_IO_BASE,
+ 0x10000000, _PAGE_IO);
+#if 0
+ io_block_mapping(0xf0000000, 0xc0000000, 0x08000000, _PAGE_IO);
+#endif
+ io_block_mapping(0xf8000000, 0xf8000000, 0x08000000, _PAGE_IO);
+}
+
+void __init
+platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
+ unsigned long r6, unsigned long r7)
+{
+ parse_bootinfo(find_bootinfo());
+
+ /* Cover the Hawk registers with a BAT */
+ prpmc750_set_bat();
+
+ isa_io_base = PRPMC750_ISA_IO_BASE;
+ isa_mem_base = PRPMC750_ISA_MEM_BASE;
+ pci_dram_offset = PRPMC750_PCI_DRAM_OFFSET;
+
+ ppc_md.setup_arch = prpmc750_setup_arch;
+ ppc_md.show_cpuinfo = prpmc750_show_cpuinfo;
+ ppc_md.init_IRQ = prpmc750_init_IRQ;
+ ppc_md.get_irq = openpic_get_irq;
+
+ ppc_md.find_end_of_memory = prpmc750_find_end_of_memory;
+ ppc_md.setup_io_mappings = prpmc750_map_io;
+
+ ppc_md.restart = prpmc750_restart;
+ ppc_md.power_off = prpmc750_power_off;
+ ppc_md.halt = prpmc750_halt;
+
+ /* PrPMC750 has no timekeeper part */
+ ppc_md.time_init = NULL;
+ ppc_md.get_rtc_time = NULL;
+ ppc_md.set_rtc_time = NULL;
+ ppc_md.calibrate_decr = prpmc750_calibrate_decr;
+
+#ifdef CONFIG_SERIAL_TEXT_DEBUG
+ ppc_md.progress = gen550_progress;
+#endif /* CONFIG_SERIAL_TEXT_DEBUG */
+}
diff --git a/arch/ppc/platforms/prpmc750.h b/arch/ppc/platforms/prpmc750.h
new file mode 100644
index 0000000..015b4f5
--- /dev/null
+++ b/arch/ppc/platforms/prpmc750.h
@@ -0,0 +1,95 @@
+/*
+ * include/asm-ppc/platforms/prpmc750.h
+ *
+ * Definitions for Motorola PrPMC750 board support
+ *
+ * Author: Matt Porter <mporter@mvista.com>
+ *
+ * 2001-2004 (c) MontaVista, Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+
+#ifdef __KERNEL__
+#ifndef __ASM_PRPMC750_H__
+#define __ASM_PRPMC750_H__
+
+/*
+ * Due to limiations imposed by legacy hardware (primaryily IDE controllers),
+ * the PrPMC750 carrier board operates using a PReP address map.
+ *
+ * From Processor (physical) -> PCI:
+ * PCI Mem Space: 0xc0000000 - 0xfe000000 -> 0x00000000 - 0x3e000000 (768 MB)
+ * PCI I/O Space: 0x80000000 - 0x90000000 -> 0x00000000 - 0x10000000 (256 MB)
+ * Note: Must skip 0xfe000000-0xfe400000 for CONFIG_HIGHMEM/PKMAP area
+ *
+ * From PCI -> Processor (physical):
+ * System Memory: 0x80000000 -> 0x00000000
+ */
+
+#define PRPMC750_ISA_IO_BASE PREP_ISA_IO_BASE
+#define PRPMC750_ISA_MEM_BASE PREP_ISA_MEM_BASE
+
+/* PCI Memory space mapping info */
+#define PRPMC750_PCI_MEM_SIZE 0x30000000U
+#define PRPMC750_PROC_PCI_MEM_START PRPMC750_ISA_MEM_BASE
+#define PRPMC750_PROC_PCI_MEM_END (PRPMC750_PROC_PCI_MEM_START + \
+ PRPMC750_PCI_MEM_SIZE - 1)
+#define PRPMC750_PCI_MEM_START 0x00000000U
+#define PRPMC750_PCI_MEM_END (PRPMC750_PCI_MEM_START + \
+ PRPMC750_PCI_MEM_SIZE - 1)
+
+/* PCI I/O space mapping info */
+#define PRPMC750_PCI_IO_SIZE 0x10000000U
+#define PRPMC750_PROC_PCI_IO_START PRPMC750_ISA_IO_BASE
+#define PRPMC750_PROC_PCI_IO_END (PRPMC750_PROC_PCI_IO_START + \
+ PRPMC750_PCI_IO_SIZE - 1)
+#define PRPMC750_PCI_IO_START 0x00000000U
+#define PRPMC750_PCI_IO_END (PRPMC750_PCI_IO_START + \
+ PRPMC750_PCI_IO_SIZE - 1)
+
+/* System memory mapping info */
+#define PRPMC750_PCI_DRAM_OFFSET PREP_PCI_DRAM_OFFSET
+#define PRPMC750_PCI_PHY_MEM_OFFSET (PRPMC750_ISA_MEM_BASE-PRPMC750_PCI_MEM_START)
+
+/* Register address definitions */
+#define PRPMC750_HAWK_SMC_BASE 0xfef80000U
+#define PRPMC750_HAWK_PPC_REG_BASE 0xfeff0000U
+
+#define PRPMC750_BASE_BAUD 1843200
+#define PRPMC750_SERIAL_0 0xfef88000
+#define PRPMC750_SERIAL_0_DLL (PRPMC750_SERIAL_0 + (UART_DLL << 4))
+#define PRPMC750_SERIAL_0_DLM (PRPMC750_SERIAL_0 + (UART_DLM << 4))
+#define PRPMC750_SERIAL_0_LCR (PRPMC750_SERIAL_0 + (UART_LCR << 4))
+
+#define PRPMC750_STATUS_REG 0xfef88080
+#define PRPMC750_BAUDOUT_MASK 0x02
+#define PRPMC750_MONARCH_MASK 0x01
+
+#define PRPMC750_MODRST_REG 0xfef880a0
+#define PRPMC750_MODRST_MASK 0x01
+
+#define PRPMC750_PIRQ_REG 0xfef880b0
+#define PRPMC750_SEL1_MASK 0x02
+#define PRPMC750_SEL0_MASK 0x01
+
+#define PRPMC750_TBEN_REG 0xfef880c0
+#define PRPMC750_TBEN_MASK 0x01
+
+/* UART Defines. */
+#define RS_TABLE_SIZE 4
+
+/* Rate for the 1.8432 Mhz clock for the onboard serial chip */
+#define BASE_BAUD (PRPMC750_BASE_BAUD / 16)
+
+#define STD_COM_FLAGS ASYNC_BOOT_AUTOCONF
+
+#define SERIAL_PORT_DFNS \
+ { 0, BASE_BAUD, PRPMC750_SERIAL_0, 1, STD_COM_FLAGS, \
+ iomem_base: (unsigned char *)PRPMC750_SERIAL_0, \
+ iomem_reg_shift: 4, \
+ io_type: SERIAL_IO_MEM } /* ttyS0 */
+
+#endif /* __ASM_PRPMC750_H__ */
+#endif /* __KERNEL__ */
diff --git a/arch/ppc/platforms/prpmc800.c b/arch/ppc/platforms/prpmc800.c
new file mode 100644
index 0000000..8b09fa6
--- /dev/null
+++ b/arch/ppc/platforms/prpmc800.c
@@ -0,0 +1,477 @@
+/*
+ * arch/ppc/platforms/prpmc800.c
+ *
+ * Author: Dale Farnsworth <dale.farnsworth@mvista.com>
+ *
+ * 2001-2004 (c) MontaVista, Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+
+#include <linux/config.h>
+#include <linux/stddef.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/reboot.h>
+#include <linux/pci.h>
+#include <linux/kdev_t.h>
+#include <linux/types.h>
+#include <linux/major.h>
+#include <linux/initrd.h>
+#include <linux/console.h>
+#include <linux/delay.h>
+#include <linux/irq.h>
+#include <linux/seq_file.h>
+#include <linux/ide.h>
+#include <linux/root_dev.h>
+#include <linux/harrier_defs.h>
+
+#include <asm/byteorder.h>
+#include <asm/system.h>
+#include <asm/pgtable.h>
+#include <asm/page.h>
+#include <asm/dma.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/machdep.h>
+#include <asm/time.h>
+#include <asm/pci-bridge.h>
+#include <asm/open_pic.h>
+#include <asm/bootinfo.h>
+#include <asm/harrier.h>
+
+#include "prpmc800.h"
+
+#define HARRIER_REVI_REG (PRPMC800_HARRIER_XCSR_BASE+HARRIER_REVI_OFF)
+#define HARRIER_UCTL_REG (PRPMC800_HARRIER_XCSR_BASE+HARRIER_UCTL_OFF)
+#define HARRIER_MISC_CSR_REG (PRPMC800_HARRIER_XCSR_BASE+HARRIER_MISC_CSR_OFF)
+#define HARRIER_IFEVP_REG (PRPMC800_HARRIER_MPIC_BASE+HARRIER_MPIC_IFEVP_OFF)
+#define HARRIER_IFEDE_REG (PRPMC800_HARRIER_MPIC_BASE+HARRIER_MPIC_IFEDE_OFF)
+#define HARRIER_FEEN_REG (PRPMC800_HARRIER_XCSR_BASE+HARRIER_FEEN_OFF)
+#define HARRIER_FEMA_REG (PRPMC800_HARRIER_XCSR_BASE+HARRIER_FEMA_OFF)
+
+#define HARRIER_VENI_REG (PRPMC800_HARRIER_XCSR_BASE + HARRIER_VENI_OFF)
+#define HARRIER_MISC_CSR (PRPMC800_HARRIER_XCSR_BASE + \
+ HARRIER_MISC_CSR_OFF)
+
+#define MONARCH (monarch != 0)
+#define NON_MONARCH (monarch == 0)
+
+extern int mpic_init(void);
+extern unsigned long loops_per_jiffy;
+extern void gen550_progress(char *, unsigned short);
+
+static int monarch = 0;
+static int found_self = 0;
+static int self = 0;
+
+static u_char prpmc800_openpic_initsenses[] __initdata =
+{
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* PRPMC800_INT_HOSTINT0 */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* PRPMC800_INT_UNUSED */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* PRPMC800_INT_DEBUGINT */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* PRPMC800_INT_HARRIER_WDT */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* PRPMC800_INT_UNUSED */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* PRPMC800_INT_UNUSED */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* PRPMC800_INT_HOSTINT1 */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* PRPMC800_INT_HOSTINT2 */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* PRPMC800_INT_HOSTINT3 */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* PRPMC800_INT_PMC_INTA */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* PRPMC800_INT_PMC_INTB */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* PRPMC800_INT_PMC_INTC */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* PRPMC800_INT_PMC_INTD */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* PRPMC800_INT_UNUSED */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* PRPMC800_INT_UNUSED */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* PRPMC800_INT_UNUSED */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* PRPMC800_INT_HARRIER_INT (UARTS, ABORT, DMA) */
+};
+
+/*
+ * Motorola PrPMC750/PrPMC800 in PrPMCBASE or PrPMC-Carrier
+ * Combined irq tables. Only Base has IDSEL 14, only Carrier has 21 and 22.
+ */
+static inline int
+prpmc_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin)
+{
+ static char pci_irq_table[][4] =
+ /*
+ * PCI IDSEL/INTPIN->INTLINE
+ * A B C D
+ */
+ {
+ {12, 0, 0, 0}, /* IDSEL 14 - Ethernet, base */
+ {0, 0, 0, 0}, /* IDSEL 15 - unused */
+ {10, 11, 12, 9}, /* IDSEL 16 - PMC A1, PMC1 */
+ {10, 11, 12, 9}, /* IDSEL 17 - PrPMC-A-B, PMC2-B */
+ {11, 12, 9, 10}, /* IDSEL 18 - PMC A1-B, PMC1-B */
+ {0, 0, 0, 0}, /* IDSEL 19 - unused */
+ {9, 10, 11, 12}, /* IDSEL 20 - P2P Bridge */
+ {11, 12, 9, 10}, /* IDSEL 21 - PMC A2, carrier */
+ {12, 9, 10, 11}, /* IDSEL 22 - PMC A2-B, carrier */
+ };
+ const long min_idsel = 14, max_idsel = 22, irqs_per_slot = 4;
+ return PCI_IRQ_TABLE_LOOKUP;
+};
+
+static int
+prpmc_read_config_dword(struct pci_controller *hose, u8 bus, u8 devfn,
+ int offset, u32 * val)
+{
+ /* paranoia */
+ if ((hose == NULL) ||
+ (hose->cfg_addr == NULL) || (hose->cfg_data == NULL))
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
+ out_be32(hose->cfg_addr, ((offset & 0xfc) << 24) | (devfn << 16)
+ | ((bus - hose->bus_offset) << 8) | 0x80);
+ *val = in_le32((u32 *) (hose->cfg_data + (offset & 3)));
+
+ return PCIBIOS_SUCCESSFUL;
+}
+
+#define HARRIER_PCI_VEND_DEV_ID (PCI_VENDOR_ID_MOTOROLA | \
+ (PCI_DEVICE_ID_MOTOROLA_HARRIER << 16))
+static int prpmc_self(u8 bus, u8 devfn)
+{
+ /*
+ * Harriers always view themselves as being on bus 0. If we're not
+ * looking at bus 0, we're not going to find ourselves.
+ */
+ if (bus != 0)
+ return PCIBIOS_DEVICE_NOT_FOUND;
+ else {
+ int result;
+ int val;
+ struct pci_controller *hose;
+
+ hose = pci_bus_to_hose(bus);
+
+ /* See if target device is a Harrier */
+ result = prpmc_read_config_dword(hose, bus, devfn,
+ PCI_VENDOR_ID, &val);
+ if ((result != PCIBIOS_SUCCESSFUL) ||
+ (val != HARRIER_PCI_VEND_DEV_ID))
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
+ /*
+ * LBA bit is set if target Harrier == initiating Harrier
+ * (i.e. if we are reading our own PCI header).
+ */
+ result = prpmc_read_config_dword(hose, bus, devfn,
+ HARRIER_LBA_OFF, &val);
+ if ((result != PCIBIOS_SUCCESSFUL) ||
+ ((val & HARRIER_LBA_MSK) != HARRIER_LBA_MSK))
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
+ /* It's us, save our location for later */
+ self = devfn;
+ found_self = 1;
+ return PCIBIOS_SUCCESSFUL;
+ }
+}
+
+static int prpmc_exclude_device(u8 bus, u8 devfn)
+{
+ /*
+ * Monarch is allowed to access all PCI devices. Non-monarch is
+ * only allowed to access its own Harrier.
+ */
+
+ if (MONARCH)
+ return PCIBIOS_SUCCESSFUL;
+ if (found_self)
+ if ((bus == 0) && (devfn == self))
+ return PCIBIOS_SUCCESSFUL;
+ else
+ return PCIBIOS_DEVICE_NOT_FOUND;
+ else
+ return prpmc_self(bus, devfn);
+}
+
+void __init prpmc800_find_bridges(void)
+{
+ struct pci_controller *hose;
+ int host_bridge;
+
+ hose = pcibios_alloc_controller();
+ if (!hose)
+ return;
+
+ hose->first_busno = 0;
+ hose->last_busno = 0xff;
+
+ ppc_md.pci_exclude_device = prpmc_exclude_device;
+ ppc_md.pcibios_fixup = NULL;
+ ppc_md.pcibios_fixup_bus = NULL;
+ ppc_md.pci_swizzle = common_swizzle;
+ ppc_md.pci_map_irq = prpmc_map_irq;
+
+ setup_indirect_pci(hose,
+ PRPMC800_PCI_CONFIG_ADDR, PRPMC800_PCI_CONFIG_DATA);
+
+ /* Get host bridge vendor/dev id */
+
+ host_bridge = in_be32((uint *) (HARRIER_VENI_REG));
+
+ if (host_bridge != HARRIER_VEND_DEV_ID) {
+ printk(KERN_CRIT "Host bridge 0x%x not supported\n",
+ host_bridge);
+ return;
+ }
+
+ monarch = in_be32((uint *) HARRIER_MISC_CSR) & HARRIER_SYSCON;
+
+ printk(KERN_INFO "Running as %s.\n",
+ MONARCH ? "Monarch" : "Non-Monarch");
+
+ hose->io_space.start = PRPMC800_PCI_IO_START;
+ hose->io_space.end = PRPMC800_PCI_IO_END;
+ hose->io_base_virt = (void *)PRPMC800_ISA_IO_BASE;
+ hose->pci_mem_offset = PRPMC800_PCI_PHY_MEM_OFFSET;
+
+ pci_init_resource(&hose->io_resource,
+ PRPMC800_PCI_IO_START, PRPMC800_PCI_IO_END,
+ IORESOURCE_IO, "PCI host bridge");
+
+ if (MONARCH) {
+ hose->mem_space.start = PRPMC800_PCI_MEM_START;
+ hose->mem_space.end = PRPMC800_PCI_MEM_END;
+
+ pci_init_resource(&hose->mem_resources[0],
+ PRPMC800_PCI_MEM_START,
+ PRPMC800_PCI_MEM_END,
+ IORESOURCE_MEM, "PCI host bridge");
+
+ if (harrier_init(hose,
+ PRPMC800_HARRIER_XCSR_BASE,
+ PRPMC800_PROC_PCI_MEM_START,
+ PRPMC800_PROC_PCI_MEM_END,
+ PRPMC800_PROC_PCI_IO_START,
+ PRPMC800_PROC_PCI_IO_END,
+ PRPMC800_HARRIER_MPIC_BASE) != 0)
+ printk(KERN_CRIT "Could not initialize HARRIER "
+ "bridge\n");
+
+ harrier_release_eready(PRPMC800_HARRIER_XCSR_BASE);
+ harrier_wait_eready(PRPMC800_HARRIER_XCSR_BASE);
+ hose->last_busno = pciauto_bus_scan(hose, hose->first_busno);
+
+ } else {
+ pci_init_resource(&hose->mem_resources[0],
+ PRPMC800_NM_PCI_MEM_START,
+ PRPMC800_NM_PCI_MEM_END,
+ IORESOURCE_MEM, "PCI host bridge");
+
+ hose->mem_space.start = PRPMC800_NM_PCI_MEM_START;
+ hose->mem_space.end = PRPMC800_NM_PCI_MEM_END;
+
+ if (harrier_init(hose,
+ PRPMC800_HARRIER_XCSR_BASE,
+ PRPMC800_NM_PROC_PCI_MEM_START,
+ PRPMC800_NM_PROC_PCI_MEM_END,
+ PRPMC800_PROC_PCI_IO_START,
+ PRPMC800_PROC_PCI_IO_END,
+ PRPMC800_HARRIER_MPIC_BASE) != 0)
+ printk(KERN_CRIT "Could not initialize HARRIER "
+ "bridge\n");
+
+ harrier_setup_nonmonarch(PRPMC800_HARRIER_XCSR_BASE,
+ HARRIER_ITSZ_1MB);
+ harrier_release_eready(PRPMC800_HARRIER_XCSR_BASE);
+ }
+}
+
+static int prpmc800_show_cpuinfo(struct seq_file *m)
+{
+ seq_printf(m, "machine\t\t: PrPMC800\n");
+
+ return 0;
+}
+
+static void __init prpmc800_setup_arch(void)
+{
+ /* init to some ~sane value until calibrate_delay() runs */
+ loops_per_jiffy = 50000000 / HZ;
+
+ /* Lookup PCI host bridges */
+ prpmc800_find_bridges();
+
+#ifdef CONFIG_BLK_DEV_INITRD
+ if (initrd_start)
+ ROOT_DEV = Root_RAM0;
+ else
+#endif
+#ifdef CONFIG_ROOT_NFS
+ ROOT_DEV = Root_NFS;
+#else
+ ROOT_DEV = Root_SDA2;
+#endif
+
+ printk(KERN_INFO "Port by MontaVista Software, Inc. "
+ "(source@mvista.com)\n");
+}
+
+/*
+ * Compute the PrPMC800's tbl frequency using the baud clock as a reference.
+ */
+static void __init prpmc800_calibrate_decr(void)
+{
+ unsigned long tbl_start, tbl_end;
+ unsigned long current_state, old_state, tb_ticks_per_second;
+ unsigned int count;
+ unsigned int harrier_revision;
+
+ harrier_revision = readb(HARRIER_REVI_REG);
+ if (harrier_revision < 2) {
+ /* XTAL64 was broken in harrier revision 1 */
+ printk(KERN_INFO "time_init: Harrier revision %d, assuming "
+ "100 Mhz bus\n", harrier_revision);
+ tb_ticks_per_second = 100000000 / 4;
+ tb_ticks_per_jiffy = tb_ticks_per_second / HZ;
+ tb_to_us = mulhwu_scale_factor(tb_ticks_per_second, 1000000);
+ return;
+ }
+
+ /*
+ * The XTAL64 bit oscillates at the 1/64 the base baud clock
+ * Set count to XTAL64 cycles per second. Since we'll count
+ * half-cycles, we'll reach the count in half a second.
+ */
+ count = PRPMC800_BASE_BAUD / 64;
+
+ /* Find the first edge of the baud clock */
+ old_state = readb(HARRIER_UCTL_REG) & HARRIER_XTAL64_MASK;
+ do {
+ current_state = readb(HARRIER_UCTL_REG) & HARRIER_XTAL64_MASK;
+ } while (old_state == current_state);
+
+ old_state = current_state;
+
+ /* Get the starting time base value */
+ tbl_start = get_tbl();
+
+ /*
+ * Loop until we have found a number of edges (half-cycles)
+ * equal to the count (half a second)
+ */
+ do {
+ do {
+ current_state = readb(HARRIER_UCTL_REG) &
+ HARRIER_XTAL64_MASK;
+ } while (old_state == current_state);
+ old_state = current_state;
+ } while (--count);
+
+ /* Get the ending time base value */
+ tbl_end = get_tbl();
+
+ /* We only counted for half a second, so double to get ticks/second */
+ tb_ticks_per_second = (tbl_end - tbl_start) * 2;
+ tb_ticks_per_jiffy = tb_ticks_per_second / HZ;
+ tb_to_us = mulhwu_scale_factor(tb_ticks_per_second, 1000000);
+}
+
+static void prpmc800_restart(char *cmd)
+{
+ ulong temp;
+
+ local_irq_disable();
+ temp = in_be32((uint *) HARRIER_MISC_CSR_REG);
+ temp |= HARRIER_RSTOUT;
+ out_be32((uint *) HARRIER_MISC_CSR_REG, temp);
+ while (1) ;
+}
+
+static void prpmc800_halt(void)
+{
+ local_irq_disable();
+ while (1) ;
+}
+
+static void prpmc800_power_off(void)
+{
+ prpmc800_halt();
+}
+
+static void __init prpmc800_init_IRQ(void)
+{
+ OpenPIC_InitSenses = prpmc800_openpic_initsenses;
+ OpenPIC_NumInitSenses = sizeof(prpmc800_openpic_initsenses);
+
+ /* Setup external interrupt sources. */
+ openpic_set_sources(0, 16, OpenPIC_Addr + 0x10000);
+ /* Setup internal UART interrupt source. */
+ openpic_set_sources(16, 1, OpenPIC_Addr + 0x10200);
+
+ /* Do the MPIC initialization based on the above settings. */
+ openpic_init(0);
+
+ /* enable functional exceptions for uarts and abort */
+ out_8((u8 *) HARRIER_FEEN_REG, (HARRIER_FE_UA0 | HARRIER_FE_UA1));
+ out_8((u8 *) HARRIER_FEMA_REG, ~(HARRIER_FE_UA0 | HARRIER_FE_UA1));
+}
+
+/*
+ * Set BAT 3 to map 0xf0000000 to end of physical memory space.
+ */
+static __inline__ void prpmc800_set_bat(void)
+{
+ mb();
+ mtspr(SPRN_DBAT1U, 0xf0001ffe);
+ mtspr(SPRN_DBAT1L, 0xf000002a);
+ mb();
+}
+
+/*
+ * We need to read the Harrier memory controller
+ * to properly determine this value
+ */
+static unsigned long __init prpmc800_find_end_of_memory(void)
+{
+ /* Read the memory size from the Harrier XCSR */
+ return harrier_get_mem_size(PRPMC800_HARRIER_XCSR_BASE);
+}
+
+static void __init prpmc800_map_io(void)
+{
+ io_block_mapping(0x80000000, 0x80000000, 0x10000000, _PAGE_IO);
+ io_block_mapping(0xf0000000, 0xf0000000, 0x10000000, _PAGE_IO);
+}
+
+void __init
+platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
+ unsigned long r6, unsigned long r7)
+{
+ parse_bootinfo(find_bootinfo());
+
+ prpmc800_set_bat();
+
+ isa_io_base = PRPMC800_ISA_IO_BASE;
+ isa_mem_base = PRPMC800_ISA_MEM_BASE;
+ pci_dram_offset = PRPMC800_PCI_DRAM_OFFSET;
+
+ ppc_md.setup_arch = prpmc800_setup_arch;
+ ppc_md.show_cpuinfo = prpmc800_show_cpuinfo;
+ ppc_md.init_IRQ = prpmc800_init_IRQ;
+ ppc_md.get_irq = openpic_get_irq;
+
+ ppc_md.find_end_of_memory = prpmc800_find_end_of_memory;
+ ppc_md.setup_io_mappings = prpmc800_map_io;
+
+ ppc_md.restart = prpmc800_restart;
+ ppc_md.power_off = prpmc800_power_off;
+ ppc_md.halt = prpmc800_halt;
+
+ /* PrPMC800 has no timekeeper part */
+ ppc_md.time_init = NULL;
+ ppc_md.get_rtc_time = NULL;
+ ppc_md.set_rtc_time = NULL;
+ ppc_md.calibrate_decr = prpmc800_calibrate_decr;
+#ifdef CONFIG_SERIAL_TEXT_DEBUG
+ ppc_md.progress = gen550_progress;
+#else /* !CONFIG_SERIAL_TEXT_DEBUG */
+ ppc_md.progress = NULL;
+#endif /* CONFIG_SERIAL_TEXT_DEBUG */
+}
diff --git a/arch/ppc/platforms/prpmc800.h b/arch/ppc/platforms/prpmc800.h
new file mode 100644
index 0000000..e53ec9b
--- /dev/null
+++ b/arch/ppc/platforms/prpmc800.h
@@ -0,0 +1,82 @@
+/*
+ * include/asm-ppc/platforms/prpmc800.h
+ *
+ * Definitions for Motorola PrPMC800 board support
+ *
+ * Author: Dale Farnsworth <dale.farnsworth@mvista.com>
+ *
+ * 2001-2004 (c) MontaVista, Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+ /*
+ * From Processor to PCI:
+ * PCI Mem Space: 0x80000000 - 0xa0000000 -> 0x80000000 - 0xa0000000 (512 MB)
+ * PCI I/O Space: 0xfe400000 - 0xfeef0000 -> 0x00000000 - 0x00b00000 (11 MB)
+ * Note: Must skip 0xfe000000-0xfe400000 for CONFIG_HIGHMEM/PKMAP area
+ *
+ * From PCI to Processor:
+ * System Memory: 0x00000000 -> 0x00000000
+ */
+
+#ifndef __ASMPPC_PRPMC800_H
+#define __ASMPPC_PRPMC800_H
+
+#define PRPMC800_PCI_CONFIG_ADDR 0xfe000cf8
+#define PRPMC800_PCI_CONFIG_DATA 0xfe000cfc
+
+#define PRPMC800_PROC_PCI_IO_START 0xfe400000U
+#define PRPMC800_PROC_PCI_IO_END 0xfeefffffU
+#define PRPMC800_PCI_IO_START 0x00000000U
+#define PRPMC800_PCI_IO_END 0x00afffffU
+
+#define PRPMC800_PROC_PCI_MEM_START 0x80000000U
+#define PRPMC800_PROC_PCI_MEM_END 0x9fffffffU
+#define PRPMC800_PCI_MEM_START 0x80000000U
+#define PRPMC800_PCI_MEM_END 0x9fffffffU
+
+#define PRPMC800_NM_PROC_PCI_MEM_START 0x40000000U
+#define PRPMC800_NM_PROC_PCI_MEM_END 0xdfffffffU
+#define PRPMC800_NM_PCI_MEM_START 0x40000000U
+#define PRPMC800_NM_PCI_MEM_END 0xdfffffffU
+
+#define PRPMC800_PCI_DRAM_OFFSET 0x00000000U
+#define PRPMC800_PCI_PHY_MEM_OFFSET 0x00000000U
+
+#define PRPMC800_ISA_IO_BASE PRPMC800_PROC_PCI_IO_START
+#define PRPMC800_ISA_MEM_BASE 0x00000000U
+
+#define PRPMC800_HARRIER_XCSR_BASE HARRIER_DEFAULT_XCSR_BASE
+#define PRPMC800_HARRIER_MPIC_BASE 0xff000000
+
+#define PRPMC800_SERIAL_1 0xfeff00c0
+
+#define PRPMC800_BASE_BAUD 1843200
+
+/*
+ * interrupt vector number and priority for harrier internal interrupt
+ * sources
+ */
+#define PRPMC800_INT_IRQ 16
+#define PRPMC800_INT_PRI 15
+
+/* UART Defines. */
+#define RS_TABLE_SIZE 4
+
+/* Rate for the 1.8432 Mhz clock for the onboard serial chip */
+#define BASE_BAUD (PRPMC800_BASE_BAUD / 16)
+
+#define STD_COM_FLAGS ASYNC_BOOT_AUTOCONF
+
+/* UARTS are at IRQ 16 */
+#define STD_SERIAL_PORT_DFNS \
+ { 0, BASE_BAUD, PRPMC800_SERIAL_1, 16, STD_COM_FLAGS, /* ttyS0 */\
+ iomem_base: (unsigned char *)PRPMC800_SERIAL_1, \
+ iomem_reg_shift: 0, \
+ io_type: SERIAL_IO_MEM },
+
+#define SERIAL_PORT_DFNS \
+ STD_SERIAL_PORT_DFNS
+
+#endif /* __ASMPPC_PRPMC800_H */
diff --git a/arch/ppc/platforms/radstone_ppc7d.c b/arch/ppc/platforms/radstone_ppc7d.c
new file mode 100644
index 0000000..2a99b43
--- /dev/null
+++ b/arch/ppc/platforms/radstone_ppc7d.c
@@ -0,0 +1,1452 @@
+/*
+ * arch/ppc/platforms/radstone_ppc7d.c
+ *
+ * Board setup routines for the Radstone PPC7D boards.
+ *
+ * Author: James Chapman <jchapman@katalix.com>
+ *
+ * Based on code done by Rabeeh Khoury - rabeeh@galileo.co.il
+ * Based on code done by - Mark A. Greer <mgreer@mvista.com>
+ *
+ * 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.
+ */
+
+/* Radstone PPC7D boards are rugged VME boards with PPC 7447A CPUs,
+ * Discovery-II, dual gigabit ethernet, dual PMC, USB, keyboard/mouse,
+ * 4 serial ports, 2 high speed serial ports (MPSCs) and optional
+ * SCSI / VGA.
+ */
+
+#include <linux/config.h>
+#include <linux/stddef.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/reboot.h>
+#include <linux/pci.h>
+#include <linux/kdev_t.h>
+#include <linux/major.h>
+#include <linux/initrd.h>
+#include <linux/console.h>
+#include <linux/delay.h>
+#include <linux/irq.h>
+#include <linux/ide.h>
+#include <linux/seq_file.h>
+#include <linux/root_dev.h>
+#include <linux/serial.h>
+#include <linux/tty.h> /* for linux/serial_core.h */
+#include <linux/serial_core.h>
+#include <linux/mv643xx.h>
+#include <linux/netdevice.h>
+
+#include <asm/system.h>
+#include <asm/pgtable.h>
+#include <asm/page.h>
+#include <asm/time.h>
+#include <asm/dma.h>
+#include <asm/io.h>
+#include <asm/machdep.h>
+#include <asm/prom.h>
+#include <asm/smp.h>
+#include <asm/vga.h>
+#include <asm/open_pic.h>
+#include <asm/i8259.h>
+#include <asm/todc.h>
+#include <asm/bootinfo.h>
+#include <asm/mpc10x.h>
+#include <asm/pci-bridge.h>
+#include <asm/mv64x60.h>
+#include <asm/i8259.h>
+
+#include "radstone_ppc7d.h"
+
+#undef DEBUG
+
+#define PPC7D_RST_PIN 17 /* GPP17 */
+
+extern u32 mv64360_irq_base;
+
+static struct mv64x60_handle bh;
+static int ppc7d_has_alma;
+
+extern void gen550_progress(char *, unsigned short);
+extern void gen550_init(int, struct uart_port *);
+
+/* residual data */
+unsigned char __res[sizeof(bd_t)];
+
+/*****************************************************************************
+ * Serial port code
+ *****************************************************************************/
+
+#if defined(CONFIG_KGDB) || defined(CONFIG_SERIAL_TEXT_DEBUG)
+static void __init ppc7d_early_serial_map(void)
+{
+#if defined(CONFIG_SERIAL_MPSC_CONSOLE)
+ mv64x60_progress_init(CONFIG_MV64X60_NEW_BASE);
+#elif defined(CONFIG_SERIAL_8250)
+ struct uart_port serial_req;
+
+ /* Setup serial port access */
+ memset(&serial_req, 0, sizeof(serial_req));
+ serial_req.uartclk = UART_CLK;
+ serial_req.irq = 4;
+ serial_req.flags = STD_COM_FLAGS;
+ serial_req.iotype = SERIAL_IO_MEM;
+ serial_req.membase = (u_char *) PPC7D_SERIAL_0;
+
+ gen550_init(0, &serial_req);
+ if (early_serial_setup(&serial_req) != 0)
+ printk(KERN_ERR "Early serial init of port 0 failed\n");
+
+ /* Assume early_serial_setup() doesn't modify serial_req */
+ serial_req.line = 1;
+ serial_req.irq = 3;
+ serial_req.membase = (u_char *) PPC7D_SERIAL_1;
+
+ gen550_init(1, &serial_req);
+ if (early_serial_setup(&serial_req) != 0)
+ printk(KERN_ERR "Early serial init of port 1 failed\n");
+#else
+#error CONFIG_KGDB || CONFIG_SERIAL_TEXT_DEBUG has no supported CONFIG_SERIAL_XXX
+#endif
+}
+#endif /* CONFIG_KGDB || CONFIG_SERIAL_TEXT_DEBUG */
+
+/*****************************************************************************
+ * Low-level board support code
+ *****************************************************************************/
+
+static unsigned long __init ppc7d_find_end_of_memory(void)
+{
+ bd_t *bp = (bd_t *) __res;
+
+ if (bp->bi_memsize)
+ return bp->bi_memsize;
+
+ return (256 * 1024 * 1024);
+}
+
+static void __init ppc7d_map_io(void)
+{
+ /* remove temporary mapping */
+ mtspr(SPRN_DBAT3U, 0x00000000);
+ mtspr(SPRN_DBAT3L, 0x00000000);
+
+ io_block_mapping(0xe8000000, 0xe8000000, 0x08000000, _PAGE_IO);
+ io_block_mapping(0xfe000000, 0xfe000000, 0x02000000, _PAGE_IO);
+}
+
+static void ppc7d_restart(char *cmd)
+{
+ u32 data;
+
+ /* Disable GPP17 interrupt */
+ data = mv64x60_read(&bh, MV64x60_GPP_INTR_MASK);
+ data &= ~(1 << PPC7D_RST_PIN);
+ mv64x60_write(&bh, MV64x60_GPP_INTR_MASK, data);
+
+ /* Configure MPP17 as GPP */
+ data = mv64x60_read(&bh, MV64x60_MPP_CNTL_2);
+ data &= ~(0x0000000f << 4);
+ mv64x60_write(&bh, MV64x60_MPP_CNTL_2, data);
+
+ /* Enable pin GPP17 for output */
+ data = mv64x60_read(&bh, MV64x60_GPP_IO_CNTL);
+ data |= (1 << PPC7D_RST_PIN);
+ mv64x60_write(&bh, MV64x60_GPP_IO_CNTL, data);
+
+ /* Toggle GPP9 pin to reset the board */
+ mv64x60_write(&bh, MV64x60_GPP_VALUE_CLR, 1 << PPC7D_RST_PIN);
+ mv64x60_write(&bh, MV64x60_GPP_VALUE_SET, 1 << PPC7D_RST_PIN);
+
+ for (;;) ; /* Spin until reset happens */
+ /* NOTREACHED */
+}
+
+static void ppc7d_power_off(void)
+{
+ u32 data;
+
+ local_irq_disable();
+
+ /* Ensure that internal MV643XX watchdog is disabled.
+ * The Disco watchdog uses MPP17 on this hardware.
+ */
+ data = mv64x60_read(&bh, MV64x60_MPP_CNTL_2);
+ data &= ~(0x0000000f << 4);
+ mv64x60_write(&bh, MV64x60_MPP_CNTL_2, data);
+
+ data = mv64x60_read(&bh, MV64x60_WDT_WDC);
+ if (data & 0x80000000) {
+ mv64x60_write(&bh, MV64x60_WDT_WDC, 1 << 24);
+ mv64x60_write(&bh, MV64x60_WDT_WDC, 2 << 24);
+ }
+
+ for (;;) ; /* No way to shut power off with software */
+ /* NOTREACHED */
+}
+
+static void ppc7d_halt(void)
+{
+ ppc7d_power_off();
+ /* NOTREACHED */
+}
+
+static unsigned long ppc7d_led_no_pulse;
+
+static int __init ppc7d_led_pulse_disable(char *str)
+{
+ ppc7d_led_no_pulse = 1;
+ return 1;
+}
+
+/* This kernel option disables the heartbeat pulsing of a board LED */
+__setup("ledoff", ppc7d_led_pulse_disable);
+
+static void ppc7d_heartbeat(void)
+{
+ u32 data32;
+ u8 data8;
+ static int max706_wdog = 0;
+
+ /* Unfortunately we can't access the LED control registers
+ * during early init because they're on the CPLD which is the
+ * other side of a PCI bridge which goes unreachable during
+ * PCI scan. So write the LEDs only if the MV64360 watchdog is
+ * enabled (i.e. userspace apps are running so kernel is up)..
+ */
+ data32 = mv64x60_read(&bh, MV64x60_WDT_WDC);
+ if (data32 & 0x80000000) {
+ /* Enable MAX706 watchdog if not done already */
+ if (!max706_wdog) {
+ outb(3, PPC7D_CPLD_RESET);
+ max706_wdog = 1;
+ }
+
+ /* Hit the MAX706 watchdog */
+ outb(0, PPC7D_CPLD_WATCHDOG_TRIG);
+
+ /* Pulse LED DS219 if not disabled */
+ if (!ppc7d_led_no_pulse) {
+ static int led_on = 0;
+
+ data8 = inb(PPC7D_CPLD_LEDS);
+ if (led_on)
+ data8 &= ~PPC7D_CPLD_LEDS_DS219_MASK;
+ else
+ data8 |= PPC7D_CPLD_LEDS_DS219_MASK;
+
+ outb(data8, PPC7D_CPLD_LEDS);
+ led_on = !led_on;
+ }
+ }
+ ppc_md.heartbeat_count = ppc_md.heartbeat_reset;
+}
+
+static int ppc7d_show_cpuinfo(struct seq_file *m)
+{
+ u8 val;
+ u8 val1, val2;
+ static int flash_sizes[4] = { 64, 32, 0, 16 };
+ static int flash_banks[4] = { 4, 3, 2, 1 };
+ static char *pci_modes[] = { "PCI33", "PCI66",
+ "Unknown", "Unknown",
+ "PCIX33", "PCIX66",
+ "PCIX100", "PCIX133"
+ };
+
+ seq_printf(m, "vendor\t\t: Radstone Technology\n");
+ seq_printf(m, "machine\t\t: PPC7D\n");
+
+ val = inb(PPC7D_CPLD_BOARD_REVISION);
+ val1 = (val & PPC7D_CPLD_BOARD_REVISION_NUMBER_MASK) >> 5;
+ val2 = (val & PPC7D_CPLD_BOARD_REVISION_LETTER_MASK);
+ seq_printf(m, "revision\t: %hd%c%c\n",
+ val1,
+ (val2 <= 0x18) ? 'A' + val2 : 'Y',
+ (val2 > 0x18) ? 'A' + (val2 - 0x19) : ' ');
+
+ val = inb(PPC7D_CPLD_MOTHERBOARD_TYPE);
+ val1 = val & PPC7D_CPLD_MB_TYPE_PLL_MASK;
+ val2 = val & (PPC7D_CPLD_MB_TYPE_ECC_FITTED_MASK |
+ PPC7D_CPLD_MB_TYPE_ECC_ENABLE_MASK);
+ seq_printf(m, "bus speed\t: %dMHz\n",
+ (val1 == PPC7D_CPLD_MB_TYPE_PLL_133) ? 133 :
+ (val1 == PPC7D_CPLD_MB_TYPE_PLL_100) ? 100 :
+ (val1 == PPC7D_CPLD_MB_TYPE_PLL_64) ? 64 : 0);
+
+ val = inb(PPC7D_CPLD_MEM_CONFIG_EXTEND);
+ val1 = val & PPC7D_CPLD_SDRAM_BANK_SIZE_MASK;
+ seq_printf(m, "SDRAM\t\t: %d%c",
+ (val1 == PPC7D_CPLD_SDRAM_BANK_SIZE_128M) ? 128 :
+ (val1 == PPC7D_CPLD_SDRAM_BANK_SIZE_256M) ? 256 :
+ (val1 == PPC7D_CPLD_SDRAM_BANK_SIZE_512M) ? 512 : 1,
+ (val1 == PPC7D_CPLD_SDRAM_BANK_SIZE_1G) ? 'G' : 'M');
+ if (val2 & PPC7D_CPLD_MB_TYPE_ECC_FITTED_MASK) {
+ seq_printf(m, " [ECC %sabled]",
+ (val2 & PPC7D_CPLD_MB_TYPE_ECC_ENABLE_MASK) ? "en" :
+ "dis");
+ }
+ seq_printf(m, "\n");
+
+ val1 = (val & PPC7D_CPLD_FLASH_DEV_SIZE_MASK);
+ val2 = (val & PPC7D_CPLD_FLASH_BANK_NUM_MASK) >> 2;
+ seq_printf(m, "FLASH\t\t: %d banks of %dM, total %dM\n",
+ flash_banks[val2], flash_sizes[val1],
+ flash_banks[val2] * flash_sizes[val1]);
+
+ val = inb(PPC7D_CPLD_FLASH_WRITE_CNTL);
+ val1 = inb(PPC7D_CPLD_SW_FLASH_WRITE_PROTECT);
+ seq_printf(m, " write links\t: %s%s%s%s\n",
+ (val & PPD7D_CPLD_FLASH_CNTL_WR_LINK_MASK) ? "WRITE " : "",
+ (val & PPD7D_CPLD_FLASH_CNTL_BOOT_LINK_MASK) ? "BOOT " : "",
+ (val & PPD7D_CPLD_FLASH_CNTL_USER_LINK_MASK) ? "USER " : "",
+ (val & (PPD7D_CPLD_FLASH_CNTL_WR_LINK_MASK |
+ PPD7D_CPLD_FLASH_CNTL_BOOT_LINK_MASK |
+ PPD7D_CPLD_FLASH_CNTL_USER_LINK_MASK)) ==
+ 0 ? "NONE" : "");
+ seq_printf(m, " write sector h/w enables: %s%s%s%s%s\n",
+ (val & PPD7D_CPLD_FLASH_CNTL_RECO_WR_MASK) ? "RECOVERY " :
+ "",
+ (val & PPD7D_CPLD_FLASH_CNTL_BOOT_WR_MASK) ? "BOOT " : "",
+ (val & PPD7D_CPLD_FLASH_CNTL_USER_WR_MASK) ? "USER " : "",
+ (val1 & PPC7D_CPLD_FLASH_CNTL_NVRAM_PROT_MASK) ? "NVRAM " :
+ "",
+ (((val &
+ (PPD7D_CPLD_FLASH_CNTL_RECO_WR_MASK |
+ PPD7D_CPLD_FLASH_CNTL_BOOT_WR_MASK |
+ PPD7D_CPLD_FLASH_CNTL_BOOT_WR_MASK)) == 0)
+ && ((val1 & PPC7D_CPLD_FLASH_CNTL_NVRAM_PROT_MASK) ==
+ 0)) ? "NONE" : "");
+ val1 =
+ inb(PPC7D_CPLD_SW_FLASH_WRITE_PROTECT) &
+ (PPC7D_CPLD_SW_FLASH_WRPROT_SYSBOOT_MASK |
+ PPC7D_CPLD_SW_FLASH_WRPROT_USER_MASK);
+ seq_printf(m, " software sector enables: %s%s%s\n",
+ (val1 & PPC7D_CPLD_SW_FLASH_WRPROT_SYSBOOT_MASK) ? "SYSBOOT "
+ : "",
+ (val1 & PPC7D_CPLD_SW_FLASH_WRPROT_USER_MASK) ? "USER " : "",
+ (val1 == 0) ? "NONE " : "");
+
+ seq_printf(m, "Boot options\t: %s%s%s%s\n",
+ (val & PPC7D_CPLD_FLASH_CNTL_ALTBOOT_LINK_MASK) ?
+ "ALTERNATE " : "",
+ (val & PPC7D_CPLD_FLASH_CNTL_VMEBOOT_LINK_MASK) ? "VME " :
+ "",
+ (val & PPC7D_CPLD_FLASH_CNTL_RECBOOT_LINK_MASK) ? "RECOVERY "
+ : "",
+ ((val &
+ (PPC7D_CPLD_FLASH_CNTL_ALTBOOT_LINK_MASK |
+ PPC7D_CPLD_FLASH_CNTL_VMEBOOT_LINK_MASK |
+ PPC7D_CPLD_FLASH_CNTL_RECBOOT_LINK_MASK)) ==
+ 0) ? "NONE" : "");
+
+ val = inb(PPC7D_CPLD_EQUIPMENT_PRESENT_1);
+ seq_printf(m, "Fitted modules\t: %s%s%s%s\n",
+ (val & PPC7D_CPLD_EQPT_PRES_1_PMC1_MASK) ? "" : "PMC1 ",
+ (val & PPC7D_CPLD_EQPT_PRES_1_PMC2_MASK) ? "" : "PMC2 ",
+ (val & PPC7D_CPLD_EQPT_PRES_1_AFIX_MASK) ? "AFIX " : "",
+ ((val & (PPC7D_CPLD_EQPT_PRES_1_PMC1_MASK |
+ PPC7D_CPLD_EQPT_PRES_1_PMC2_MASK |
+ PPC7D_CPLD_EQPT_PRES_1_AFIX_MASK)) ==
+ (PPC7D_CPLD_EQPT_PRES_1_PMC1_MASK |
+ PPC7D_CPLD_EQPT_PRES_1_PMC2_MASK)) ? "NONE" : "");
+
+ if (val & PPC7D_CPLD_EQPT_PRES_1_AFIX_MASK) {
+ static const char *ids[] = {
+ "unknown",
+ "1553 (Dual Channel)",
+ "1553 (Single Channel)",
+ "8-bit SCSI + VGA",
+ "16-bit SCSI + VGA",
+ "1553 (Single Channel with sideband)",
+ "1553 (Dual Channel with sideband)",
+ NULL
+ };
+ u8 id = __raw_readb((void *)PPC7D_AFIX_REG_BASE + 0x03);
+ seq_printf(m, "AFIX module\t: 0x%hx [%s]\n", id,
+ id < 7 ? ids[id] : "unknown");
+ }
+
+ val = inb(PPC7D_CPLD_PCI_CONFIG);
+ val1 = (val & PPC7D_CPLD_PCI_CONFIG_PCI0_MASK) >> 4;
+ val2 = (val & PPC7D_CPLD_PCI_CONFIG_PCI1_MASK);
+ seq_printf(m, "PCI#0\t\t: %s\nPCI#1\t\t: %s\n",
+ pci_modes[val1], pci_modes[val2]);
+
+ val = inb(PPC7D_CPLD_EQUIPMENT_PRESENT_2);
+ seq_printf(m, "PMC1\t\t: %s\nPMC2\t\t: %s\n",
+ (val & PPC7D_CPLD_EQPT_PRES_3_PMC1_V_MASK) ? "3.3v" : "5v",
+ (val & PPC7D_CPLD_EQPT_PRES_3_PMC2_V_MASK) ? "3.3v" : "5v");
+ seq_printf(m, "PMC power source: %s\n",
+ (val & PPC7D_CPLD_EQPT_PRES_3_PMC_POWER_MASK) ? "VME" :
+ "internal");
+
+ val = inb(PPC7D_CPLD_EQUIPMENT_PRESENT_4);
+ val2 = inb(PPC7D_CPLD_EQUIPMENT_PRESENT_2);
+ seq_printf(m, "Fit options\t: %s%s%s%s%s%s%s\n",
+ (val & PPC7D_CPLD_EQPT_PRES_4_LPT_MASK) ? "LPT " : "",
+ (val & PPC7D_CPLD_EQPT_PRES_4_PS2_FITTED) ? "PS2 " : "",
+ (val & PPC7D_CPLD_EQPT_PRES_4_USB2_FITTED) ? "USB2 " : "",
+ (val2 & PPC7D_CPLD_EQPT_PRES_2_UNIVERSE_MASK) ? "VME " : "",
+ (val2 & PPC7D_CPLD_EQPT_PRES_2_COM36_MASK) ? "COM3-6 " : "",
+ (val2 & PPC7D_CPLD_EQPT_PRES_2_GIGE_MASK) ? "eth0 " : "",
+ (val2 & PPC7D_CPLD_EQPT_PRES_2_DUALGIGE_MASK) ? "eth1 " :
+ "");
+
+ val = inb(PPC7D_CPLD_ID_LINK);
+ val1 = val & (PPC7D_CPLD_ID_LINK_E6_MASK |
+ PPC7D_CPLD_ID_LINK_E7_MASK |
+ PPC7D_CPLD_ID_LINK_E12_MASK |
+ PPC7D_CPLD_ID_LINK_E13_MASK);
+
+ val = inb(PPC7D_CPLD_FLASH_WRITE_CNTL) &
+ (PPD7D_CPLD_FLASH_CNTL_WR_LINK_MASK |
+ PPD7D_CPLD_FLASH_CNTL_BOOT_LINK_MASK |
+ PPD7D_CPLD_FLASH_CNTL_USER_LINK_MASK);
+
+ seq_printf(m, "Board links present: %s%s%s%s%s%s%s%s\n",
+ (val1 & PPC7D_CPLD_ID_LINK_E6_MASK) ? "E6 " : "",
+ (val1 & PPC7D_CPLD_ID_LINK_E7_MASK) ? "E7 " : "",
+ (val & PPD7D_CPLD_FLASH_CNTL_WR_LINK_MASK) ? "E9 " : "",
+ (val & PPD7D_CPLD_FLASH_CNTL_BOOT_LINK_MASK) ? "E10 " : "",
+ (val & PPD7D_CPLD_FLASH_CNTL_USER_LINK_MASK) ? "E11 " : "",
+ (val1 & PPC7D_CPLD_ID_LINK_E12_MASK) ? "E12 " : "",
+ (val1 & PPC7D_CPLD_ID_LINK_E13_MASK) ? "E13 " : "",
+ ((val == 0) && (val1 == 0)) ? "NONE" : "");
+
+ val = inb(PPC7D_CPLD_WDOG_RESETSW_MASK);
+ seq_printf(m, "Front panel reset switch: %sabled\n",
+ (val & PPC7D_CPLD_WDOG_RESETSW_MASK) ? "dis" : "en");
+
+ return 0;
+}
+
+static void __init ppc7d_calibrate_decr(void)
+{
+ ulong freq;
+
+ freq = 100000000 / 4;
+
+ pr_debug("time_init: decrementer frequency = %lu.%.6lu MHz\n",
+ freq / 1000000, freq % 1000000);
+
+ tb_ticks_per_jiffy = freq / HZ;
+ tb_to_us = mulhwu_scale_factor(freq, 1000000);
+}
+
+/*****************************************************************************
+ * Interrupt stuff
+ *****************************************************************************/
+
+static irqreturn_t ppc7d_i8259_intr(int irq, void *dev_id, struct pt_regs *regs)
+{
+ u32 temp = mv64x60_read(&bh, MV64x60_GPP_INTR_CAUSE);
+ if (temp & (1 << 28)) {
+ i8259_irq(regs);
+ mv64x60_write(&bh, MV64x60_GPP_INTR_CAUSE, temp & (~(1 << 28)));
+ return IRQ_HANDLED;
+ }
+
+ return IRQ_NONE;
+}
+
+/*
+ * Each interrupt cause is assigned an IRQ number.
+ * Southbridge has 16*2 (two 8259's) interrupts.
+ * Discovery-II has 96 interrupts (cause-hi, cause-lo, gpp x 32).
+ * If multiple interrupts are pending, get_irq() returns the
+ * lowest pending irq number first.
+ *
+ *
+ * IRQ # Source Trig Active
+ * =============================================================
+ *
+ * Southbridge
+ * -----------
+ * IRQ # Source Trig
+ * =============================================================
+ * 0 ISA High Resolution Counter Edge
+ * 1 Keyboard Edge
+ * 2 Cascade From (IRQ 8-15) Edge
+ * 3 Com 2 (Uart 2) Edge
+ * 4 Com 1 (Uart 1) Edge
+ * 5 PCI Int D/AFIX IRQZ ID4 (2,7) Level
+ * 6 GPIO Level
+ * 7 LPT Edge
+ * 8 RTC Alarm Edge
+ * 9 PCI Int A/PMC 2/AFIX IRQW ID1 (2,0) Level
+ * 10 PCI Int B/PMC 1/AFIX IRQX ID2 (2,1) Level
+ * 11 USB2 Level
+ * 12 Mouse Edge
+ * 13 Reserved internally by Ali M1535+
+ * 14 PCI Int C/VME/AFIX IRQY ID3 (2,6) Level
+ * 15 COM 5/6 Level
+ *
+ * 16..112 Discovery-II...
+ *
+ * MPP28 Southbridge Edge High
+ *
+ *
+ * Interrupts are cascaded through to the Discovery-II.
+ *
+ * PCI ---
+ * \
+ * CPLD --> ALI1535 -------> DISCOVERY-II
+ * INTF MPP28
+ */
+static void __init ppc7d_init_irq(void)
+{
+ int irq;
+
+ pr_debug("%s\n", __FUNCTION__);
+ i8259_init(0);
+ mv64360_init_irq();
+
+ /* IRQ 0..15 are handled by the cascaded 8259's of the Ali1535 */
+ for (irq = 0; irq < 16; irq++) {
+ irq_desc[irq].handler = &i8259_pic;
+ }
+ /* IRQs 5,6,9,10,11,14,15 are level sensitive */
+ irq_desc[5].status |= IRQ_LEVEL;
+ irq_desc[6].status |= IRQ_LEVEL;
+ irq_desc[9].status |= IRQ_LEVEL;
+ irq_desc[10].status |= IRQ_LEVEL;
+ irq_desc[11].status |= IRQ_LEVEL;
+ irq_desc[14].status |= IRQ_LEVEL;
+ irq_desc[15].status |= IRQ_LEVEL;
+
+ /* GPP28 is edge triggered */
+ irq_desc[mv64360_irq_base + MV64x60_IRQ_GPP28].status &= ~IRQ_LEVEL;
+}
+
+static u32 ppc7d_irq_canonicalize(u32 irq)
+{
+ if ((irq >= 16) && (irq < (16 + 96)))
+ irq -= 16;
+
+ return irq;
+}
+
+static int ppc7d_get_irq(struct pt_regs *regs)
+{
+ int irq;
+
+ irq = mv64360_get_irq(regs);
+ if (irq == (mv64360_irq_base + MV64x60_IRQ_GPP28))
+ irq = i8259_irq(regs);
+ return irq;
+}
+
+/*
+ * 9 PCI Int A/PMC 2/AFIX IRQW ID1 (2,0) Level
+ * 10 PCI Int B/PMC 1/AFIX IRQX ID2 (2,1) Level
+ * 14 PCI Int C/VME/AFIX IRQY ID3 (2,6) Level
+ * 5 PCI Int D/AFIX IRQZ ID4 (2,7) Level
+ */
+static int __init ppc7d_map_irq(struct pci_dev *dev, unsigned char idsel,
+ unsigned char pin)
+{
+ static const char pci_irq_table[][4] =
+ /*
+ * PCI IDSEL/INTPIN->INTLINE
+ * A B C D
+ */
+ {
+ {10, 14, 5, 9}, /* IDSEL 10 - PMC2 / AFIX IRQW */
+ {9, 10, 14, 5}, /* IDSEL 11 - PMC1 / AFIX IRQX */
+ {5, 9, 10, 14}, /* IDSEL 12 - AFIX IRQY */
+ {14, 5, 9, 10}, /* IDSEL 13 - AFIX IRQZ */
+ };
+ const long min_idsel = 10, max_idsel = 14, irqs_per_slot = 4;
+
+ pr_debug("%s: %04x/%04x/%x: idsel=%hx pin=%hu\n", __FUNCTION__,
+ dev->vendor, dev->device, PCI_FUNC(dev->devfn), idsel, pin);
+
+ return PCI_IRQ_TABLE_LOOKUP;
+}
+
+void __init ppc7d_intr_setup(void)
+{
+ u32 data;
+
+ /*
+ * Define GPP 28 interrupt polarity as active high
+ * input signal and level triggered
+ */
+ data = mv64x60_read(&bh, MV64x60_GPP_LEVEL_CNTL);
+ data &= ~(1 << 28);
+ mv64x60_write(&bh, MV64x60_GPP_LEVEL_CNTL, data);
+ data = mv64x60_read(&bh, MV64x60_GPP_IO_CNTL);
+ data &= ~(1 << 28);
+ mv64x60_write(&bh, MV64x60_GPP_IO_CNTL, data);
+
+ /* Config GPP intr ctlr to respond to level trigger */
+ data = mv64x60_read(&bh, MV64x60_COMM_ARBITER_CNTL);
+ data |= (1 << 10);
+ mv64x60_write(&bh, MV64x60_COMM_ARBITER_CNTL, data);
+
+ /* XXXX Erranum FEr PCI-#8 */
+ data = mv64x60_read(&bh, MV64x60_PCI0_CMD);
+ data &= ~((1 << 5) | (1 << 9));
+ mv64x60_write(&bh, MV64x60_PCI0_CMD, data);
+ data = mv64x60_read(&bh, MV64x60_PCI1_CMD);
+ data &= ~((1 << 5) | (1 << 9));
+ mv64x60_write(&bh, MV64x60_PCI1_CMD, data);
+
+ /*
+ * Dismiss and then enable interrupt on GPP interrupt cause
+ * for CPU #0
+ */
+ mv64x60_write(&bh, MV64x60_GPP_INTR_CAUSE, ~(1 << 28));
+ data = mv64x60_read(&bh, MV64x60_GPP_INTR_MASK);
+ data |= (1 << 28);
+ mv64x60_write(&bh, MV64x60_GPP_INTR_MASK, data);
+
+ /*
+ * Dismiss and then enable interrupt on CPU #0 high cause reg
+ * BIT27 summarizes GPP interrupts 23-31
+ */
+ mv64x60_write(&bh, MV64360_IC_MAIN_CAUSE_HI, ~(1 << 27));
+ data = mv64x60_read(&bh, MV64360_IC_CPU0_INTR_MASK_HI);
+ data |= (1 << 27);
+ mv64x60_write(&bh, MV64360_IC_CPU0_INTR_MASK_HI, data);
+}
+
+/*****************************************************************************
+ * Platform device data fixup routines.
+ *****************************************************************************/
+
+#if defined(CONFIG_SERIAL_MPSC)
+static void __init ppc7d_fixup_mpsc_pdata(struct platform_device *pdev)
+{
+ struct mpsc_pdata *pdata;
+
+ pdata = (struct mpsc_pdata *)pdev->dev.platform_data;
+
+ pdata->max_idle = 40;
+ pdata->default_baud = PPC7D_DEFAULT_BAUD;
+ pdata->brg_clk_src = PPC7D_MPSC_CLK_SRC;
+ pdata->brg_clk_freq = PPC7D_MPSC_CLK_FREQ;
+
+ return;
+}
+#endif
+
+#if defined(CONFIG_MV643XX_ETH)
+static void __init ppc7d_fixup_eth_pdata(struct platform_device *pdev)
+{
+ struct mv643xx_eth_platform_data *eth_pd;
+ static u16 phy_addr[] = {
+ PPC7D_ETH0_PHY_ADDR,
+ PPC7D_ETH1_PHY_ADDR,
+ PPC7D_ETH2_PHY_ADDR,
+ };
+ int i;
+
+ eth_pd = pdev->dev.platform_data;
+ eth_pd->force_phy_addr = 1;
+ eth_pd->phy_addr = phy_addr[pdev->id];
+ eth_pd->tx_queue_size = PPC7D_ETH_TX_QUEUE_SIZE;
+ eth_pd->rx_queue_size = PPC7D_ETH_RX_QUEUE_SIZE;
+
+ /* Adjust IRQ by mv64360_irq_base */
+ for (i = 0; i < pdev->num_resources; i++) {
+ struct resource *r = &pdev->resource[i];
+
+ if (r->flags & IORESOURCE_IRQ) {
+ r->start += mv64360_irq_base;
+ r->end += mv64360_irq_base;
+ pr_debug("%s, uses IRQ %d\n", pdev->name,
+ (int)r->start);
+ }
+ }
+
+}
+#endif
+
+#if defined(CONFIG_I2C_MV64XXX)
+static void __init
+ppc7d_fixup_i2c_pdata(struct platform_device *pdev)
+{
+ struct mv64xxx_i2c_pdata *pdata;
+ int i;
+
+ pdata = pdev->dev.platform_data;
+ if (pdata == NULL) {
+ pdata = kmalloc(sizeof(*pdata), GFP_KERNEL);
+ if (pdata == NULL)
+ return;
+
+ memset(pdata, 0, sizeof(*pdata));
+ pdev->dev.platform_data = pdata;
+ }
+
+ /* divisors M=8, N=3 for 100kHz I2C from 133MHz system clock */
+ pdata->freq_m = 8;
+ pdata->freq_n = 3;
+ pdata->timeout = 500;
+ pdata->retries = 3;
+
+ /* Adjust IRQ by mv64360_irq_base */
+ for (i = 0; i < pdev->num_resources; i++) {
+ struct resource *r = &pdev->resource[i];
+
+ if (r->flags & IORESOURCE_IRQ) {
+ r->start += mv64360_irq_base;
+ r->end += mv64360_irq_base;
+ pr_debug("%s, uses IRQ %d\n", pdev->name, (int) r->start);
+ }
+ }
+}
+#endif
+
+static int __init ppc7d_platform_notify(struct device *dev)
+{
+ static struct {
+ char *bus_id;
+ void ((*rtn) (struct platform_device * pdev));
+ } dev_map[] = {
+#if defined(CONFIG_SERIAL_MPSC)
+ { MPSC_CTLR_NAME ".0", ppc7d_fixup_mpsc_pdata },
+ { MPSC_CTLR_NAME ".1", ppc7d_fixup_mpsc_pdata },
+#endif
+#if defined(CONFIG_MV643XX_ETH)
+ { MV643XX_ETH_NAME ".0", ppc7d_fixup_eth_pdata },
+ { MV643XX_ETH_NAME ".1", ppc7d_fixup_eth_pdata },
+ { MV643XX_ETH_NAME ".2", ppc7d_fixup_eth_pdata },
+#endif
+#if defined(CONFIG_I2C_MV64XXX)
+ { MV64XXX_I2C_CTLR_NAME ".0", ppc7d_fixup_i2c_pdata },
+#endif
+ };
+ struct platform_device *pdev;
+ int i;
+
+ if (dev && dev->bus_id)
+ for (i = 0; i < ARRAY_SIZE(dev_map); i++)
+ if (!strncmp(dev->bus_id, dev_map[i].bus_id,
+ BUS_ID_SIZE)) {
+
+ pdev = container_of(dev,
+ struct platform_device,
+ dev);
+ dev_map[i].rtn(pdev);
+ }
+
+ return 0;
+}
+
+/*****************************************************************************
+ * PCI device fixups.
+ * These aren't really fixups per se. They are used to init devices as they
+ * are found during PCI scan.
+ *
+ * The PPC7D has an HB8 PCI-X bridge which must be set up during a PCI
+ * scan in order to find other devices on its secondary side.
+ *****************************************************************************/
+
+static void __init ppc7d_fixup_hb8(struct pci_dev *dev)
+{
+ u16 val16;
+
+ if (dev->bus->number == 0) {
+ pr_debug("PCI: HB8 init\n");
+
+ pci_write_config_byte(dev, 0x1c,
+ ((PPC7D_PCI0_IO_START_PCI_ADDR & 0xf000)
+ >> 8) | 0x01);
+ pci_write_config_byte(dev, 0x1d,
+ (((PPC7D_PCI0_IO_START_PCI_ADDR +
+ PPC7D_PCI0_IO_SIZE -
+ 1) & 0xf000) >> 8) | 0x01);
+ pci_write_config_word(dev, 0x30,
+ PPC7D_PCI0_IO_START_PCI_ADDR >> 16);
+ pci_write_config_word(dev, 0x32,
+ ((PPC7D_PCI0_IO_START_PCI_ADDR +
+ PPC7D_PCI0_IO_SIZE -
+ 1) >> 16) & 0xffff);
+
+ pci_write_config_word(dev, 0x20,
+ PPC7D_PCI0_MEM0_START_PCI_LO_ADDR >> 16);
+ pci_write_config_word(dev, 0x22,
+ ((PPC7D_PCI0_MEM0_START_PCI_LO_ADDR +
+ PPC7D_PCI0_MEM0_SIZE -
+ 1) >> 16) & 0xffff);
+ pci_write_config_word(dev, 0x24, 0);
+ pci_write_config_word(dev, 0x26, 0);
+ pci_write_config_dword(dev, 0x28, 0);
+ pci_write_config_dword(dev, 0x2c, 0);
+
+ pci_read_config_word(dev, 0x3e, &val16);
+ val16 |= ((1 << 5) | (1 << 1)); /* signal master aborts and
+ * SERR to primary
+ */
+ val16 &= ~(1 << 2); /* ISA disable, so all ISA
+ * ports forwarded to secondary
+ */
+ pci_write_config_word(dev, 0x3e, val16);
+ }
+}
+
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_HINT, 0x0028, ppc7d_fixup_hb8);
+
+/* This should perhaps be a separate driver as we're actually initializing
+ * the chip for this board here. It's hardly a fixup...
+ */
+static void __init ppc7d_fixup_ali1535(struct pci_dev *dev)
+{
+ pr_debug("PCI: ALI1535 init\n");
+
+ if (dev->bus->number == 1) {
+ /* Configure the ISA Port Settings */
+ pci_write_config_byte(dev, 0x43, 0x00);
+
+ /* Disable PCI Interrupt polling mode */
+ pci_write_config_byte(dev, 0x45, 0x00);
+
+ /* Multifunction pin select INTFJ -> INTF */
+ pci_write_config_byte(dev, 0x78, 0x00);
+
+ /* Set PCI INT -> IRQ Routing control in for external
+ * pins south bridge.
+ */
+ pci_write_config_byte(dev, 0x48, 0x31); /* [7-4] INT B -> IRQ10
+ * [3-0] INT A -> IRQ9
+ */
+ pci_write_config_byte(dev, 0x49, 0x5D); /* [7-4] INT D -> IRQ5
+ * [3-0] INT C -> IRQ14
+ */
+
+ /* PPC7D setup */
+ /* NEC USB device on IRQ 11 (INTE) - INTF disabled */
+ pci_write_config_byte(dev, 0x4A, 0x09);
+
+ /* GPIO on IRQ 6 */
+ pci_write_config_byte(dev, 0x76, 0x07);
+
+ /* SIRQ I (COMS 5/6) use IRQ line 15.
+ * Positive (not subtractive) address decode.
+ */
+ pci_write_config_byte(dev, 0x44, 0x0f);
+
+ /* SIRQ II disabled */
+ pci_write_config_byte(dev, 0x75, 0x0);
+
+ /* On board USB and RTC disabled */
+ pci_write_config_word(dev, 0x52, (1 << 14));
+ pci_write_config_byte(dev, 0x74, 0x00);
+
+ /* On board IDE disabled */
+ pci_write_config_byte(dev, 0x58, 0x00);
+
+ /* Decode 32-bit addresses */
+ pci_write_config_byte(dev, 0x5b, 0);
+
+ /* Disable docking IO */
+ pci_write_config_word(dev, 0x5c, 0x0000);
+
+ /* Disable modem, enable sound */
+ pci_write_config_byte(dev, 0x77, (1 << 6));
+
+ /* Disable hot-docking mode */
+ pci_write_config_byte(dev, 0x7d, 0x00);
+ }
+}
+
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AL, 0x1533, ppc7d_fixup_ali1535);
+
+static int ppc7d_pci_exclude_device(u8 bus, u8 devfn)
+{
+ /* Early versions of this board were fitted with IBM ALMA
+ * PCI-VME bridge chips. The PCI config space of these devices
+ * was not set up correctly and causes PCI scan problems.
+ */
+ if ((bus == 1) && (PCI_SLOT(devfn) == 4) && ppc7d_has_alma)
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
+ return mv64x60_pci_exclude_device(bus, devfn);
+}
+
+/* This hook is called when each PCI bus is probed.
+ */
+static void ppc7d_pci_fixup_bus(struct pci_bus *bus)
+{
+ pr_debug("PCI BUS %hu: %lx/%lx %lx/%lx %lx/%lx %lx/%lx\n",
+ bus->number,
+ bus->resource[0] ? bus->resource[0]->start : 0,
+ bus->resource[0] ? bus->resource[0]->end : 0,
+ bus->resource[1] ? bus->resource[1]->start : 0,
+ bus->resource[1] ? bus->resource[1]->end : 0,
+ bus->resource[2] ? bus->resource[2]->start : 0,
+ bus->resource[2] ? bus->resource[2]->end : 0,
+ bus->resource[3] ? bus->resource[3]->start : 0,
+ bus->resource[3] ? bus->resource[3]->end : 0);
+
+ if ((bus->number == 1) && (bus->resource[2] != NULL)) {
+ /* Hide PCI window 2 of Bus 1 which is used only to
+ * map legacy ISA memory space.
+ */
+ bus->resource[2]->start = 0;
+ bus->resource[2]->end = 0;
+ bus->resource[2]->flags = 0;
+ }
+}
+
+/*****************************************************************************
+ * Board device setup code
+ *****************************************************************************/
+
+void __init ppc7d_setup_peripherals(void)
+{
+ u32 val32;
+
+ /* Set up windows for boot CS */
+ mv64x60_set_32bit_window(&bh, MV64x60_CPU2BOOT_WIN,
+ PPC7D_BOOT_WINDOW_BASE, PPC7D_BOOT_WINDOW_SIZE,
+ 0);
+ bh.ci->enable_window_32bit(&bh, MV64x60_CPU2BOOT_WIN);
+
+ /* Boot firmware configures the following DevCS addresses.
+ * DevCS0 - board control/status
+ * DevCS1 - test registers
+ * DevCS2 - AFIX port/address registers (for identifying)
+ * DevCS3 - FLASH
+ *
+ * We don't use DevCS0, DevCS1.
+ */
+ val32 = mv64x60_read(&bh, MV64360_CPU_BAR_ENABLE);
+ val32 |= ((1 << 4) | (1 << 5));
+ mv64x60_write(&bh, MV64360_CPU_BAR_ENABLE, val32);
+ mv64x60_write(&bh, MV64x60_CPU2DEV_0_BASE, 0);
+ mv64x60_write(&bh, MV64x60_CPU2DEV_0_SIZE, 0);
+ mv64x60_write(&bh, MV64x60_CPU2DEV_1_BASE, 0);
+ mv64x60_write(&bh, MV64x60_CPU2DEV_1_SIZE, 0);
+
+ mv64x60_set_32bit_window(&bh, MV64x60_CPU2DEV_2_WIN,
+ PPC7D_AFIX_REG_BASE, PPC7D_AFIX_REG_SIZE, 0);
+ bh.ci->enable_window_32bit(&bh, MV64x60_CPU2DEV_2_WIN);
+
+ mv64x60_set_32bit_window(&bh, MV64x60_CPU2DEV_3_WIN,
+ PPC7D_FLASH_BASE, PPC7D_FLASH_SIZE_ACTUAL, 0);
+ bh.ci->enable_window_32bit(&bh, MV64x60_CPU2DEV_3_WIN);
+
+ mv64x60_set_32bit_window(&bh, MV64x60_CPU2SRAM_WIN,
+ PPC7D_INTERNAL_SRAM_BASE, MV64360_SRAM_SIZE,
+ 0);
+ bh.ci->enable_window_32bit(&bh, MV64x60_CPU2SRAM_WIN);
+
+ /* Set up Enet->SRAM window */
+ mv64x60_set_32bit_window(&bh, MV64x60_ENET2MEM_4_WIN,
+ PPC7D_INTERNAL_SRAM_BASE, MV64360_SRAM_SIZE,
+ 0x2);
+ bh.ci->enable_window_32bit(&bh, MV64x60_ENET2MEM_4_WIN);
+
+ /* Give enet r/w access to memory region */
+ val32 = mv64x60_read(&bh, MV64360_ENET2MEM_ACC_PROT_0);
+ val32 |= (0x3 << (4 << 1));
+ mv64x60_write(&bh, MV64360_ENET2MEM_ACC_PROT_0, val32);
+ val32 = mv64x60_read(&bh, MV64360_ENET2MEM_ACC_PROT_1);
+ val32 |= (0x3 << (4 << 1));
+ mv64x60_write(&bh, MV64360_ENET2MEM_ACC_PROT_1, val32);
+ val32 = mv64x60_read(&bh, MV64360_ENET2MEM_ACC_PROT_2);
+ val32 |= (0x3 << (4 << 1));
+ mv64x60_write(&bh, MV64360_ENET2MEM_ACC_PROT_2, val32);
+
+ val32 = mv64x60_read(&bh, MV64x60_TIMR_CNTR_0_3_CNTL);
+ val32 &= ~((1 << 0) | (1 << 8) | (1 << 16) | (1 << 24));
+ mv64x60_write(&bh, MV64x60_TIMR_CNTR_0_3_CNTL, val32);
+
+ /* Enumerate pci bus.
+ *
+ * We scan PCI#0 first (the bus with the HB8 and other
+ * on-board peripherals). We must configure the 64360 before
+ * each scan, according to the bus number assignments. Busses
+ * are assigned incrementally, starting at 0. PCI#0 is
+ * usually assigned bus#0, the secondary side of the HB8 gets
+ * bus#1 and PCI#1 (second PMC site) gets bus#2. However, if
+ * any PMC card has a PCI bridge, these bus assignments will
+ * change.
+ */
+
+ /* Turn off PCI retries */
+ val32 = mv64x60_read(&bh, MV64x60_CPU_CONFIG);
+ val32 |= (1 << 17);
+ mv64x60_write(&bh, MV64x60_CPU_CONFIG, val32);
+
+ /* Scan PCI#0 */
+ mv64x60_set_bus(&bh, 0, 0);
+ bh.hose_a->first_busno = 0;
+ bh.hose_a->last_busno = 0xff;
+ bh.hose_a->last_busno = pciauto_bus_scan(bh.hose_a, 0);
+ printk(KERN_INFO "PCI#0: first=%d last=%d\n",
+ bh.hose_a->first_busno, bh.hose_a->last_busno);
+
+ /* Scan PCI#1 */
+ bh.hose_b->first_busno = bh.hose_a->last_busno + 1;
+ mv64x60_set_bus(&bh, 1, bh.hose_b->first_busno);
+ bh.hose_b->last_busno = 0xff;
+ bh.hose_b->last_busno = pciauto_bus_scan(bh.hose_b,
+ bh.hose_b->first_busno);
+ printk(KERN_INFO "PCI#1: first=%d last=%d\n",
+ bh.hose_b->first_busno, bh.hose_b->last_busno);
+
+ /* Turn on PCI retries */
+ val32 = mv64x60_read(&bh, MV64x60_CPU_CONFIG);
+ val32 &= ~(1 << 17);
+ mv64x60_write(&bh, MV64x60_CPU_CONFIG, val32);
+
+ /* Setup interrupts */
+ ppc7d_intr_setup();
+}
+
+static void __init ppc7d_setup_bridge(void)
+{
+ struct mv64x60_setup_info si;
+ int i;
+ u32 temp;
+
+ mv64360_irq_base = 16; /* first 16 intrs are 2 x 8259's */
+
+ memset(&si, 0, sizeof(si));
+
+ si.phys_reg_base = CONFIG_MV64X60_NEW_BASE;
+
+ si.pci_0.enable_bus = 1;
+ si.pci_0.pci_io.cpu_base = PPC7D_PCI0_IO_START_PROC_ADDR;
+ si.pci_0.pci_io.pci_base_hi = 0;
+ si.pci_0.pci_io.pci_base_lo = PPC7D_PCI0_IO_START_PCI_ADDR;
+ si.pci_0.pci_io.size = PPC7D_PCI0_IO_SIZE;
+ si.pci_0.pci_io.swap = MV64x60_CPU2PCI_SWAP_NONE;
+ si.pci_0.pci_mem[0].cpu_base = PPC7D_PCI0_MEM0_START_PROC_ADDR;
+ si.pci_0.pci_mem[0].pci_base_hi = PPC7D_PCI0_MEM0_START_PCI_HI_ADDR;
+ si.pci_0.pci_mem[0].pci_base_lo = PPC7D_PCI0_MEM0_START_PCI_LO_ADDR;
+ si.pci_0.pci_mem[0].size = PPC7D_PCI0_MEM0_SIZE;
+ si.pci_0.pci_mem[0].swap = MV64x60_CPU2PCI_SWAP_NONE;
+ si.pci_0.pci_mem[1].cpu_base = PPC7D_PCI0_MEM1_START_PROC_ADDR;
+ si.pci_0.pci_mem[1].pci_base_hi = PPC7D_PCI0_MEM1_START_PCI_HI_ADDR;
+ si.pci_0.pci_mem[1].pci_base_lo = PPC7D_PCI0_MEM1_START_PCI_LO_ADDR;
+ si.pci_0.pci_mem[1].size = PPC7D_PCI0_MEM1_SIZE;
+ si.pci_0.pci_mem[1].swap = MV64x60_CPU2PCI_SWAP_NONE;
+ si.pci_0.pci_cmd_bits = 0;
+ si.pci_0.latency_timer = 0x80;
+
+ si.pci_1.enable_bus = 1;
+ si.pci_1.pci_io.cpu_base = PPC7D_PCI1_IO_START_PROC_ADDR;
+ si.pci_1.pci_io.pci_base_hi = 0;
+ si.pci_1.pci_io.pci_base_lo = PPC7D_PCI1_IO_START_PCI_ADDR;
+ si.pci_1.pci_io.size = PPC7D_PCI1_IO_SIZE;
+ si.pci_1.pci_io.swap = MV64x60_CPU2PCI_SWAP_NONE;
+ si.pci_1.pci_mem[0].cpu_base = PPC7D_PCI1_MEM0_START_PROC_ADDR;
+ si.pci_1.pci_mem[0].pci_base_hi = PPC7D_PCI1_MEM0_START_PCI_HI_ADDR;
+ si.pci_1.pci_mem[0].pci_base_lo = PPC7D_PCI1_MEM0_START_PCI_LO_ADDR;
+ si.pci_1.pci_mem[0].size = PPC7D_PCI1_MEM0_SIZE;
+ si.pci_1.pci_mem[0].swap = MV64x60_CPU2PCI_SWAP_NONE;
+ si.pci_1.pci_mem[1].cpu_base = PPC7D_PCI1_MEM1_START_PROC_ADDR;
+ si.pci_1.pci_mem[1].pci_base_hi = PPC7D_PCI1_MEM1_START_PCI_HI_ADDR;
+ si.pci_1.pci_mem[1].pci_base_lo = PPC7D_PCI1_MEM1_START_PCI_LO_ADDR;
+ si.pci_1.pci_mem[1].size = PPC7D_PCI1_MEM1_SIZE;
+ si.pci_1.pci_mem[1].swap = MV64x60_CPU2PCI_SWAP_NONE;
+ si.pci_1.pci_cmd_bits = 0;
+ si.pci_1.latency_timer = 0x80;
+
+ /* Don't clear the SRAM window since we use it for debug */
+ si.window_preserve_mask_32_lo = (1 << MV64x60_CPU2SRAM_WIN);
+
+ printk(KERN_INFO "PCI: MV64360 PCI#0 IO at %x, size %x\n",
+ si.pci_0.pci_io.cpu_base, si.pci_0.pci_io.size);
+ printk(KERN_INFO "PCI: MV64360 PCI#1 IO at %x, size %x\n",
+ si.pci_1.pci_io.cpu_base, si.pci_1.pci_io.size);
+
+ for (i = 0; i < MV64x60_CPU2MEM_WINDOWS; i++) {
+#if defined(CONFIG_NOT_COHERENT_CACHE)
+ si.cpu_prot_options[i] = 0;
+ si.enet_options[i] = MV64360_ENET2MEM_SNOOP_NONE;
+ si.mpsc_options[i] = MV64360_MPSC2MEM_SNOOP_NONE;
+ si.idma_options[i] = MV64360_IDMA2MEM_SNOOP_NONE;
+
+ si.pci_0.acc_cntl_options[i] =
+ MV64360_PCI_ACC_CNTL_SNOOP_NONE |
+ MV64360_PCI_ACC_CNTL_SWAP_NONE |
+ MV64360_PCI_ACC_CNTL_MBURST_128_BYTES |
+ MV64360_PCI_ACC_CNTL_RDSIZE_256_BYTES;
+
+ si.pci_1.acc_cntl_options[i] =
+ MV64360_PCI_ACC_CNTL_SNOOP_NONE |
+ MV64360_PCI_ACC_CNTL_SWAP_NONE |
+ MV64360_PCI_ACC_CNTL_MBURST_128_BYTES |
+ MV64360_PCI_ACC_CNTL_RDSIZE_256_BYTES;
+#else
+ si.cpu_prot_options[i] = 0;
+ /* All PPC7D hardware uses B0 or newer MV64360 silicon which
+ * does not have snoop bugs.
+ */
+ si.enet_options[i] = MV64360_ENET2MEM_SNOOP_WB;
+ si.mpsc_options[i] = MV64360_MPSC2MEM_SNOOP_WB;
+ si.idma_options[i] = MV64360_IDMA2MEM_SNOOP_WB;
+
+ si.pci_0.acc_cntl_options[i] =
+ MV64360_PCI_ACC_CNTL_SNOOP_WB |
+ MV64360_PCI_ACC_CNTL_SWAP_NONE |
+ MV64360_PCI_ACC_CNTL_MBURST_32_BYTES |
+ MV64360_PCI_ACC_CNTL_RDSIZE_32_BYTES;
+
+ si.pci_1.acc_cntl_options[i] =
+ MV64360_PCI_ACC_CNTL_SNOOP_WB |
+ MV64360_PCI_ACC_CNTL_SWAP_NONE |
+ MV64360_PCI_ACC_CNTL_MBURST_32_BYTES |
+ MV64360_PCI_ACC_CNTL_RDSIZE_32_BYTES;
+#endif
+ }
+
+ /* Lookup PCI host bridges */
+ if (mv64x60_init(&bh, &si))
+ printk(KERN_ERR "MV64360 initialization failed.\n");
+
+ pr_debug("MV64360 regs @ %lx/%p\n", bh.p_base, bh.v_base);
+
+ /* Enable WB Cache coherency on SRAM */
+ temp = mv64x60_read(&bh, MV64360_SRAM_CONFIG);
+ pr_debug("SRAM_CONFIG: %x\n", temp);
+#if defined(CONFIG_NOT_COHERENT_CACHE)
+ mv64x60_write(&bh, MV64360_SRAM_CONFIG, temp & ~0x2);
+#else
+ mv64x60_write(&bh, MV64360_SRAM_CONFIG, temp | 0x2);
+#endif
+ /* If system operates with internal bus arbiter (CPU master
+ * control bit8) clear AACK Delay bit [25] in CPU
+ * configuration register.
+ */
+ temp = mv64x60_read(&bh, MV64x60_CPU_MASTER_CNTL);
+ if (temp & (1 << 8)) {
+ temp = mv64x60_read(&bh, MV64x60_CPU_CONFIG);
+ mv64x60_write(&bh, MV64x60_CPU_CONFIG, (temp & ~(1 << 25)));
+ }
+
+ /* Data and address parity is enabled */
+ temp = mv64x60_read(&bh, MV64x60_CPU_CONFIG);
+ mv64x60_write(&bh, MV64x60_CPU_CONFIG,
+ (temp | (1 << 26) | (1 << 19)));
+
+ pci_dram_offset = 0; /* sys mem at same addr on PCI & cpu bus */
+ ppc_md.pci_swizzle = common_swizzle;
+ ppc_md.pci_map_irq = ppc7d_map_irq;
+ ppc_md.pci_exclude_device = ppc7d_pci_exclude_device;
+
+ mv64x60_set_bus(&bh, 0, 0);
+ bh.hose_a->first_busno = 0;
+ bh.hose_a->last_busno = 0xff;
+ bh.hose_a->mem_space.start = PPC7D_PCI0_MEM0_START_PCI_LO_ADDR;
+ bh.hose_a->mem_space.end =
+ PPC7D_PCI0_MEM0_START_PCI_LO_ADDR + PPC7D_PCI0_MEM0_SIZE;
+
+ /* These will be set later, as a result of PCI0 scan */
+ bh.hose_b->first_busno = 0;
+ bh.hose_b->last_busno = 0xff;
+ bh.hose_b->mem_space.start = PPC7D_PCI1_MEM0_START_PCI_LO_ADDR;
+ bh.hose_b->mem_space.end =
+ PPC7D_PCI1_MEM0_START_PCI_LO_ADDR + PPC7D_PCI1_MEM0_SIZE;
+
+ pr_debug("MV64360: PCI#0 IO decode %08x/%08x IO remap %08x\n",
+ mv64x60_read(&bh, 0x48), mv64x60_read(&bh, 0x50),
+ mv64x60_read(&bh, 0xf0));
+}
+
+static void __init ppc7d_setup_arch(void)
+{
+ int port;
+
+ loops_per_jiffy = 100000000 / HZ;
+
+#ifdef CONFIG_BLK_DEV_INITRD
+ if (initrd_start)
+ ROOT_DEV = Root_RAM0;
+ else
+#endif
+#ifdef CONFIG_ROOT_NFS
+ ROOT_DEV = Root_NFS;
+#else
+ ROOT_DEV = Root_HDA1;
+#endif
+
+ if ((cur_cpu_spec[0]->cpu_features & CPU_FTR_SPEC7450) ||
+ (cur_cpu_spec[0]->cpu_features & CPU_FTR_L3CR))
+ /* 745x is different. We only want to pass along enable. */
+ _set_L2CR(L2CR_L2E);
+ else if (cur_cpu_spec[0]->cpu_features & CPU_FTR_L2CR)
+ /* All modules have 1MB of L2. We also assume that an
+ * L2 divisor of 3 will work.
+ */
+ _set_L2CR(L2CR_L2E | L2CR_L2SIZ_1MB | L2CR_L2CLK_DIV3
+ | L2CR_L2RAM_PIPE | L2CR_L2OH_1_0 | L2CR_L2DF);
+
+ if (cur_cpu_spec[0]->cpu_features & CPU_FTR_L3CR)
+ /* No L3 cache */
+ _set_L3CR(0);
+
+#ifdef CONFIG_DUMMY_CONSOLE
+ conswitchp = &dummy_con;
+#endif
+
+ /* Lookup PCI host bridges */
+ if (ppc_md.progress)
+ ppc_md.progress("ppc7d_setup_arch: calling setup_bridge", 0);
+
+ ppc7d_setup_bridge();
+ ppc7d_setup_peripherals();
+
+ /* Disable ethernet. It might have been setup by the bootrom */
+ for (port = 0; port < 3; port++)
+ mv64x60_write(&bh, MV643XX_ETH_RECEIVE_QUEUE_COMMAND_REG(port),
+ 0x0000ff00);
+
+ /* Clear queue pointers to ensure they are all initialized,
+ * otherwise since queues 1-7 are unused, they have random
+ * pointers which look strange in register dumps. Don't bother
+ * with queue 0 since it will be initialized later.
+ */
+ for (port = 0; port < 3; port++) {
+ mv64x60_write(&bh,
+ MV643XX_ETH_RX_CURRENT_QUEUE_DESC_PTR_1(port),
+ 0x00000000);
+ mv64x60_write(&bh,
+ MV643XX_ETH_RX_CURRENT_QUEUE_DESC_PTR_2(port),
+ 0x00000000);
+ mv64x60_write(&bh,
+ MV643XX_ETH_RX_CURRENT_QUEUE_DESC_PTR_3(port),
+ 0x00000000);
+ mv64x60_write(&bh,
+ MV643XX_ETH_RX_CURRENT_QUEUE_DESC_PTR_4(port),
+ 0x00000000);
+ mv64x60_write(&bh,
+ MV643XX_ETH_RX_CURRENT_QUEUE_DESC_PTR_5(port),
+ 0x00000000);
+ mv64x60_write(&bh,
+ MV643XX_ETH_RX_CURRENT_QUEUE_DESC_PTR_6(port),
+ 0x00000000);
+ mv64x60_write(&bh,
+ MV643XX_ETH_RX_CURRENT_QUEUE_DESC_PTR_7(port),
+ 0x00000000);
+ }
+
+ printk(KERN_INFO "Radstone Technology PPC7D\n");
+ if (ppc_md.progress)
+ ppc_md.progress("ppc7d_setup_arch: exit", 0);
+}
+
+/* This kernel command line parameter can be used to have the target
+ * wait for a JTAG debugger to attach. Of course, a JTAG debugger
+ * with hardware breakpoint support can have the target stop at any
+ * location during init, but this is a convenience feature that makes
+ * it easier in the common case of loading the code using the ppcboot
+ * bootloader..
+ */
+static unsigned long ppc7d_wait_debugger;
+
+static int __init ppc7d_waitdbg(char *str)
+{
+ ppc7d_wait_debugger = 1;
+ return 1;
+}
+
+__setup("waitdbg", ppc7d_waitdbg);
+
+/* Second phase board init, called after other (architecture common)
+ * low-level services have been initialized.
+ */
+static void ppc7d_init2(void)
+{
+ unsigned long flags;
+ u32 data;
+ u8 data8;
+
+ pr_debug("%s: enter\n", __FUNCTION__);
+
+ /* Wait for debugger? */
+ if (ppc7d_wait_debugger) {
+ printk("Waiting for debugger...\n");
+
+ while (readl(&ppc7d_wait_debugger)) ;
+ }
+
+ /* Hook up i8259 interrupt which is connected to GPP28 */
+ request_irq(mv64360_irq_base + MV64x60_IRQ_GPP28, ppc7d_i8259_intr,
+ SA_INTERRUPT, "I8259 (GPP28) interrupt", (void *)0);
+
+ /* Configure MPP16 as watchdog NMI, MPP17 as watchdog WDE */
+ spin_lock_irqsave(&mv64x60_lock, flags);
+ data = mv64x60_read(&bh, MV64x60_MPP_CNTL_2);
+ data &= ~(0x0000000f << 0);
+ data |= (0x00000004 << 0);
+ data &= ~(0x0000000f << 4);
+ data |= (0x00000004 << 4);
+ mv64x60_write(&bh, MV64x60_MPP_CNTL_2, data);
+ spin_unlock_irqrestore(&mv64x60_lock, flags);
+
+ /* All LEDs off */
+ data8 = inb(PPC7D_CPLD_LEDS);
+ data8 &= ~0x08;
+ data8 |= 0x07;
+ outb(data8, PPC7D_CPLD_LEDS);
+
+ pr_debug("%s: exit\n", __FUNCTION__);
+}
+
+/* Called from machine_init(), early, before any of the __init functions
+ * have run. We must init software-configurable pins before other functions
+ * such as interrupt controllers are initialised.
+ */
+void __init platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
+ unsigned long r6, unsigned long r7)
+{
+ u8 val8;
+ u8 rev_num;
+
+ /* Map 0xe0000000-0xffffffff early because we need access to SRAM
+ * and the ISA memory space (for serial port) here. This mapping
+ * is redone properly in ppc7d_map_io() later.
+ */
+ mtspr(SPRN_DBAT3U, 0xe0003fff);
+ mtspr(SPRN_DBAT3L, 0xe000002a);
+
+ /*
+ * Zero SRAM. Note that this generates parity errors on
+ * internal data path in SRAM if it's first time accessing it
+ * after reset.
+ *
+ * We do this ASAP to avoid parity errors when reading
+ * uninitialized SRAM.
+ */
+ memset((void *)PPC7D_INTERNAL_SRAM_BASE, 0, MV64360_SRAM_SIZE);
+
+ pr_debug("platform_init: r3-r7: %lx %lx %lx %lx %lx\n",
+ r3, r4, r5, r6, r7);
+
+ parse_bootinfo(find_bootinfo());
+
+ /* ASSUMPTION: If both r3 (bd_t pointer) and r6 (cmdline pointer)
+ * are non-zero, then we should use the board info from the bd_t
+ * structure and the cmdline pointed to by r6 instead of the
+ * information from birecs, if any. Otherwise, use the information
+ * from birecs as discovered by the preceeding call to
+ * parse_bootinfo(). This rule should work with both PPCBoot, which
+ * uses a bd_t board info structure, and the kernel boot wrapper,
+ * which uses birecs.
+ */
+ if (r3 && r6) {
+ bd_t *bp = (bd_t *) __res;
+
+ /* copy board info structure */
+ memcpy((void *)__res, (void *)(r3 + KERNELBASE), sizeof(bd_t));
+ /* copy command line */
+ *(char *)(r7 + KERNELBASE) = 0;
+ strcpy(cmd_line, (char *)(r6 + KERNELBASE));
+
+ printk(KERN_INFO "Board info data:-\n");
+ printk(KERN_INFO " Internal freq: %lu MHz, bus freq: %lu MHz\n",
+ bp->bi_intfreq, bp->bi_busfreq);
+ printk(KERN_INFO " Memory: %lx, size %lx\n", bp->bi_memstart,
+ bp->bi_memsize);
+ printk(KERN_INFO " Console baudrate: %lu\n", bp->bi_baudrate);
+ printk(KERN_INFO " Ethernet address: "
+ "%02x:%02x:%02x:%02x:%02x:%02x\n",
+ bp->bi_enetaddr[0], bp->bi_enetaddr[1],
+ bp->bi_enetaddr[2], bp->bi_enetaddr[3],
+ bp->bi_enetaddr[4], bp->bi_enetaddr[5]);
+ }
+#ifdef CONFIG_BLK_DEV_INITRD
+ /* take care of initrd if we have one */
+ if (r4) {
+ initrd_start = r4 + KERNELBASE;
+ initrd_end = r5 + KERNELBASE;
+ printk(KERN_INFO "INITRD @ %lx/%lx\n", initrd_start, initrd_end);
+ }
+#endif /* CONFIG_BLK_DEV_INITRD */
+
+ /* Map in board regs, etc. */
+ isa_io_base = 0xe8000000;
+ isa_mem_base = 0xe8000000;
+ pci_dram_offset = 0x00000000;
+ ISA_DMA_THRESHOLD = 0x00ffffff;
+ DMA_MODE_READ = 0x44;
+ DMA_MODE_WRITE = 0x48;
+
+ ppc_md.setup_arch = ppc7d_setup_arch;
+ ppc_md.init = ppc7d_init2;
+ ppc_md.show_cpuinfo = ppc7d_show_cpuinfo;
+ ppc_md.irq_canonicalize = ppc7d_irq_canonicalize;
+ ppc_md.init_IRQ = ppc7d_init_irq;
+ ppc_md.get_irq = ppc7d_get_irq;
+
+ ppc_md.restart = ppc7d_restart;
+ ppc_md.power_off = ppc7d_power_off;
+ ppc_md.halt = ppc7d_halt;
+
+ ppc_md.find_end_of_memory = ppc7d_find_end_of_memory;
+ ppc_md.setup_io_mappings = ppc7d_map_io;
+
+ ppc_md.time_init = NULL;
+ ppc_md.set_rtc_time = NULL;
+ ppc_md.get_rtc_time = NULL;
+ ppc_md.calibrate_decr = ppc7d_calibrate_decr;
+ ppc_md.nvram_read_val = NULL;
+ ppc_md.nvram_write_val = NULL;
+
+ ppc_md.heartbeat = ppc7d_heartbeat;
+ ppc_md.heartbeat_reset = HZ;
+ ppc_md.heartbeat_count = ppc_md.heartbeat_reset;
+
+ ppc_md.pcibios_fixup_bus = ppc7d_pci_fixup_bus;
+
+#if defined(CONFIG_SERIAL_MPSC) || defined(CONFIG_MV643XX_ETH) || \
+ defined(CONFIG_I2C_MV64XXX)
+ platform_notify = ppc7d_platform_notify;
+#endif
+
+#ifdef CONFIG_SERIAL_MPSC
+ /* On PPC7D, we must configure MPSC support via CPLD control
+ * registers.
+ */
+ outb(PPC7D_CPLD_RTS_COM4_SCLK |
+ PPC7D_CPLD_RTS_COM56_ENABLED, PPC7D_CPLD_RTS);
+ outb(PPC7D_CPLD_COMS_COM3_TCLKEN |
+ PPC7D_CPLD_COMS_COM3_TXEN |
+ PPC7D_CPLD_COMS_COM4_TCLKEN |
+ PPC7D_CPLD_COMS_COM4_TXEN, PPC7D_CPLD_COMS);
+#endif /* CONFIG_SERIAL_MPSC */
+
+#if defined(CONFIG_KGDB) || defined(CONFIG_SERIAL_TEXT_DEBUG)
+ ppc7d_early_serial_map();
+#ifdef CONFIG_SERIAL_TEXT_DEBUG
+#if defined(CONFIG_SERIAL_MPSC_CONSOLE)
+ ppc_md.progress = mv64x60_mpsc_progress;
+#elif defined(CONFIG_SERIAL_8250)
+ ppc_md.progress = gen550_progress;
+#else
+#error CONFIG_KGDB || CONFIG_SERIAL_TEXT_DEBUG has no supported CONFIG_SERIAL_XXX
+#endif /* CONFIG_SERIAL_8250 */
+#endif /* CONFIG_SERIAL_TEXT_DEBUG */
+#endif /* CONFIG_KGDB || CONFIG_SERIAL_TEXT_DEBUG */
+
+ /* Enable write access to user flash. This is necessary for
+ * flash probe.
+ */
+ val8 = readb((void *)isa_io_base + PPC7D_CPLD_SW_FLASH_WRITE_PROTECT);
+ writeb(val8 | (PPC7D_CPLD_SW_FLASH_WRPROT_ENABLED &
+ PPC7D_CPLD_SW_FLASH_WRPROT_USER_MASK),
+ (void *)isa_io_base + PPC7D_CPLD_SW_FLASH_WRITE_PROTECT);
+
+ /* Determine if this board has IBM ALMA VME devices */
+ val8 = readb((void *)isa_io_base + PPC7D_CPLD_BOARD_REVISION);
+ rev_num = (val8 & PPC7D_CPLD_BOARD_REVISION_NUMBER_MASK) >> 5;
+ if (rev_num <= 1)
+ ppc7d_has_alma = 1;
+
+#ifdef DEBUG
+ console_printk[0] = 8;
+#endif
+}
diff --git a/arch/ppc/platforms/radstone_ppc7d.h b/arch/ppc/platforms/radstone_ppc7d.h
new file mode 100644
index 0000000..4546fff2
--- /dev/null
+++ b/arch/ppc/platforms/radstone_ppc7d.h
@@ -0,0 +1,434 @@
+/*
+ * arch/ppc/platforms/radstone_ppc7d.h
+ *
+ * Board definitions for the Radstone PPC7D boards.
+ *
+ * Author: James Chapman <jchapman@katalix.com>
+ *
+ * Based on code done by Rabeeh Khoury - rabeeh@galileo.co.il
+ * Based on code done by - Mark A. Greer <mgreer@mvista.com>
+ *
+ * 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.
+ */
+
+/*
+ * The MV64360 has 2 PCI buses each with 1 window from the CPU bus to
+ * PCI I/O space and 4 windows from the CPU bus to PCI MEM space.
+ * We'll only use one PCI MEM window on each PCI bus.
+ *
+ * This is the CPU physical memory map (windows must be at least 1MB
+ * and start on a boundary that is a multiple of the window size):
+ *
+ * 0xff800000-0xffffffff - Boot window
+ * 0xff000000-0xff000fff - AFIX registers (DevCS2)
+ * 0xfef00000-0xfef0ffff - Internal MV64x60 registers
+ * 0xfef40000-0xfef7ffff - Internal SRAM
+ * 0xfef00000-0xfef0ffff - MV64360 Registers
+ * 0x70000000-0x7fffffff - soldered flash (DevCS3)
+ * 0xe8000000-0xe9ffffff - PCI I/O
+ * 0x80000000-0xbfffffff - PCI MEM
+ */
+
+#ifndef __PPC_PLATFORMS_PPC7D_H
+#define __PPC_PLATFORMS_PPC7D_H
+
+#include <asm/ppcboot.h>
+
+/*****************************************************************************
+ * CPU Physical Memory Map setup.
+ *****************************************************************************/
+
+#define PPC7D_BOOT_WINDOW_BASE 0xff800000
+#define PPC7D_AFIX_REG_BASE 0xff000000
+#define PPC7D_INTERNAL_SRAM_BASE 0xfef40000
+#define PPC7D_FLASH_BASE 0x70000000
+
+#define PPC7D_BOOT_WINDOW_SIZE_ACTUAL 0x00800000 /* 8MB */
+#define PPC7D_FLASH_SIZE_ACTUAL 0x10000000 /* 256MB */
+
+#define PPC7D_BOOT_WINDOW_SIZE max(MV64360_WINDOW_SIZE_MIN, \
+ PPC7D_BOOT_WINDOW_SIZE_ACTUAL)
+#define PPC7D_FLASH_SIZE max(MV64360_WINDOW_SIZE_MIN, \
+ PPC7D_FLASH_SIZE_ACTUAL)
+#define PPC7D_AFIX_REG_SIZE max(MV64360_WINDOW_SIZE_MIN, 0xff)
+
+
+#define PPC7D_PCI0_MEM0_START_PROC_ADDR 0x80000000UL
+#define PPC7D_PCI0_MEM0_START_PCI_HI_ADDR 0x00000000UL
+#define PPC7D_PCI0_MEM0_START_PCI_LO_ADDR 0x80000000UL
+#define PPC7D_PCI0_MEM0_SIZE 0x20000000UL
+#define PPC7D_PCI0_MEM1_START_PROC_ADDR 0xe8010000UL
+#define PPC7D_PCI0_MEM1_START_PCI_HI_ADDR 0x00000000UL
+#define PPC7D_PCI0_MEM1_START_PCI_LO_ADDR 0x00000000UL
+#define PPC7D_PCI0_MEM1_SIZE 0x000f0000UL
+#define PPC7D_PCI0_IO_START_PROC_ADDR 0xe8000000UL
+#define PPC7D_PCI0_IO_START_PCI_ADDR 0x00000000UL
+#define PPC7D_PCI0_IO_SIZE 0x00010000UL
+
+#define PPC7D_PCI1_MEM0_START_PROC_ADDR 0xa0000000UL
+#define PPC7D_PCI1_MEM0_START_PCI_HI_ADDR 0x00000000UL
+#define PPC7D_PCI1_MEM0_START_PCI_LO_ADDR 0xa0000000UL
+#define PPC7D_PCI1_MEM0_SIZE 0x20000000UL
+#define PPC7D_PCI1_MEM1_START_PROC_ADDR 0xe9800000UL
+#define PPC7D_PCI1_MEM1_START_PCI_HI_ADDR 0x00000000UL
+#define PPC7D_PCI1_MEM1_START_PCI_LO_ADDR 0x00000000UL
+#define PPC7D_PCI1_MEM1_SIZE 0x00800000UL
+#define PPC7D_PCI1_IO_START_PROC_ADDR 0xe9000000UL
+#define PPC7D_PCI1_IO_START_PCI_ADDR 0x00000000UL
+#define PPC7D_PCI1_IO_SIZE 0x00010000UL
+
+#define PPC7D_DEFAULT_BAUD 9600
+#define PPC7D_MPSC_CLK_SRC 8 /* TCLK */
+#define PPC7D_MPSC_CLK_FREQ 133333333 /* 133.3333... MHz */
+
+#define PPC7D_ETH0_PHY_ADDR 8
+#define PPC7D_ETH1_PHY_ADDR 9
+#define PPC7D_ETH2_PHY_ADDR 0
+
+#define PPC7D_ETH_TX_QUEUE_SIZE 400
+#define PPC7D_ETH_RX_QUEUE_SIZE 400
+
+#define PPC7D_ETH_PORT_CONFIG_VALUE \
+ MV64340_ETH_UNICAST_NORMAL_MODE | \
+ MV64340_ETH_DEFAULT_RX_QUEUE_0 | \
+ MV64340_ETH_DEFAULT_RX_ARP_QUEUE_0 | \
+ MV64340_ETH_RECEIVE_BC_IF_NOT_IP_OR_ARP | \
+ MV64340_ETH_RECEIVE_BC_IF_IP | \
+ MV64340_ETH_RECEIVE_BC_IF_ARP | \
+ MV64340_ETH_CAPTURE_TCP_FRAMES_DIS | \
+ MV64340_ETH_CAPTURE_UDP_FRAMES_DIS | \
+ MV64340_ETH_DEFAULT_RX_TCP_QUEUE_0 | \
+ MV64340_ETH_DEFAULT_RX_UDP_QUEUE_0 | \
+ MV64340_ETH_DEFAULT_RX_BPDU_QUEUE_0
+
+#define PPC7D_ETH_PORT_CONFIG_EXTEND_VALUE \
+ MV64340_ETH_SPAN_BPDU_PACKETS_AS_NORMAL | \
+ MV64340_ETH_PARTITION_DISABLE
+
+#define GT_ETH_IPG_INT_RX(value) \
+ ((value & 0x3fff) << 8)
+
+#define PPC7D_ETH_PORT_SDMA_CONFIG_VALUE \
+ MV64340_ETH_RX_BURST_SIZE_4_64BIT | \
+ GT_ETH_IPG_INT_RX(0) | \
+ MV64340_ETH_TX_BURST_SIZE_4_64BIT
+
+#define PPC7D_ETH_PORT_SERIAL_CONTROL_VALUE \
+ MV64340_ETH_ENABLE_AUTO_NEG_FOR_DUPLX | \
+ MV64340_ETH_DISABLE_AUTO_NEG_FOR_FLOW_CTRL | \
+ MV64340_ETH_ADV_SYMMETRIC_FLOW_CTRL | \
+ MV64340_ETH_FORCE_FC_MODE_NO_PAUSE_DIS_TX | \
+ MV64340_ETH_FORCE_BP_MODE_NO_JAM | \
+ (1 << 9) | \
+ MV64340_ETH_DO_NOT_FORCE_LINK_FAIL | \
+ MV64340_ETH_RETRANSMIT_16_ATTEMPTS | \
+ MV64340_ETH_ENABLE_AUTO_NEG_SPEED_GMII | \
+ MV64340_ETH_DTE_ADV_0 | \
+ MV64340_ETH_DISABLE_AUTO_NEG_BYPASS | \
+ MV64340_ETH_AUTO_NEG_NO_CHANGE | \
+ MV64340_ETH_MAX_RX_PACKET_9700BYTE | \
+ MV64340_ETH_CLR_EXT_LOOPBACK | \
+ MV64340_ETH_SET_FULL_DUPLEX_MODE | \
+ MV64340_ETH_ENABLE_FLOW_CTRL_TX_RX_IN_FULL_DUPLEX
+
+/*****************************************************************************
+ * Serial defines.
+ *****************************************************************************/
+
+#define PPC7D_SERIAL_0 0xe80003f8
+#define PPC7D_SERIAL_1 0xe80002f8
+
+#define RS_TABLE_SIZE 2
+
+/* Rate for the 1.8432 Mhz clock for the onboard serial chip */
+#define UART_CLK 1843200
+#define BASE_BAUD ( UART_CLK / 16 )
+
+#ifdef CONFIG_SERIAL_DETECT_IRQ
+#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF|ASYNC_AUTO_IRQ)
+#else
+#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF)
+#endif
+
+#define STD_SERIAL_PORT_DFNS \
+ { 0, BASE_BAUD, PPC7D_SERIAL_0, 4, STD_COM_FLAGS, /* ttyS0 */ \
+ iomem_base: (u8 *)PPC7D_SERIAL_0, \
+ io_type: SERIAL_IO_MEM, }, \
+ { 0, BASE_BAUD, PPC7D_SERIAL_1, 3, STD_COM_FLAGS, /* ttyS1 */ \
+ iomem_base: (u8 *)PPC7D_SERIAL_1, \
+ io_type: SERIAL_IO_MEM },
+
+#define SERIAL_PORT_DFNS \
+ STD_SERIAL_PORT_DFNS
+
+/*****************************************************************************
+ * CPLD defines.
+ *
+ * Register map:-
+ *
+ * 0000 to 000F South Bridge DMA 1 Control
+ * 0020 and 0021 South Bridge Interrupt 1 Control
+ * 0040 to 0043 South Bridge Counter Control
+ * 0060 Keyboard
+ * 0061 South Bridge NMI Status and Control
+ * 0064 Keyboard
+ * 0071 and 0072 RTC R/W
+ * 0078 to 007B South Bridge BIOS Timer
+ * 0080 to 0090 South Bridge DMA Pages
+ * 00A0 and 00A1 South Bridge Interrupt 2 Control
+ * 00C0 to 00DE South Bridge DMA 2 Control
+ * 02E8 to 02EF COM6 R/W
+ * 02F8 to 02FF South Bridge COM2 R/W
+ * 03E8 to 03EF COM5 R/W
+ * 03F8 to 03FF South Bridge COM1 R/W
+ * 040A South Bridge DMA Scatter/Gather RO
+ * 040B DMA 1 Extended Mode WO
+ * 0410 to 043F South Bridge DMA Scatter/Gather
+ * 0481 to 048B South Bridge DMA High Pages
+ * 04D0 and 04D1 South Bridge Edge/Level Control
+ * 04D6 DMA 2 Extended Mode WO
+ * 0804 Memory Configuration RO
+ * 0806 Memory Configuration Extend RO
+ * 0808 SCSI Activity LED R/W
+ * 080C Equipment Present 1 RO
+ * 080E Equipment Present 2 RO
+ * 0810 Equipment Present 3 RO
+ * 0812 Equipment Present 4 RO
+ * 0818 Key Lock RO
+ * 0820 LEDS R/W
+ * 0824 COMs R/W
+ * 0826 RTS R/W
+ * 0828 Reset R/W
+ * 082C Watchdog Trig R/W
+ * 082E Interrupt R/W
+ * 0830 Interrupt Status RO
+ * 0832 PCI configuration RO
+ * 0854 Board Revision RO
+ * 0858 Extended ID RO
+ * 0864 ID Link RO
+ * 0866 Motherboard Type RO
+ * 0868 FLASH Write control RO
+ * 086A Software FLASH write protect R/W
+ * 086E FLASH Control R/W
+ *****************************************************************************/
+
+#define PPC7D_CPLD_MEM_CONFIG 0x0804
+#define PPC7D_CPLD_MEM_CONFIG_EXTEND 0x0806
+#define PPC7D_CPLD_SCSI_ACTIVITY_LED 0x0808
+#define PPC7D_CPLD_EQUIPMENT_PRESENT_1 0x080C
+#define PPC7D_CPLD_EQUIPMENT_PRESENT_2 0x080E
+#define PPC7D_CPLD_EQUIPMENT_PRESENT_3 0x0810
+#define PPC7D_CPLD_EQUIPMENT_PRESENT_4 0x0812
+#define PPC7D_CPLD_KEY_LOCK 0x0818
+#define PPC7D_CPLD_LEDS 0x0820
+#define PPC7D_CPLD_COMS 0x0824
+#define PPC7D_CPLD_RTS 0x0826
+#define PPC7D_CPLD_RESET 0x0828
+#define PPC7D_CPLD_WATCHDOG_TRIG 0x082C
+#define PPC7D_CPLD_INTR 0x082E
+#define PPC7D_CPLD_INTR_STATUS 0x0830
+#define PPC7D_CPLD_PCI_CONFIG 0x0832
+#define PPC7D_CPLD_BOARD_REVISION 0x0854
+#define PPC7D_CPLD_EXTENDED_ID 0x0858
+#define PPC7D_CPLD_ID_LINK 0x0864
+#define PPC7D_CPLD_MOTHERBOARD_TYPE 0x0866
+#define PPC7D_CPLD_FLASH_WRITE_CNTL 0x0868
+#define PPC7D_CPLD_SW_FLASH_WRITE_PROTECT 0x086A
+#define PPC7D_CPLD_FLASH_CNTL 0x086E
+
+/* MEMORY_CONFIG_EXTEND */
+#define PPC7D_CPLD_SDRAM_BANK_SIZE_MASK 0xc0
+#define PPC7D_CPLD_SDRAM_BANK_SIZE_128M 0
+#define PPC7D_CPLD_SDRAM_BANK_SIZE_256M 0x40
+#define PPC7D_CPLD_SDRAM_BANK_SIZE_512M 0x80
+#define PPC7D_CPLD_SDRAM_BANK_SIZE_1G 0xc0
+#define PPC7D_CPLD_FLASH_DEV_SIZE_MASK 0x03
+#define PPC7D_CPLD_FLASH_BANK_NUM_MASK 0x0c
+#define PPC7D_CPLD_FLASH_DEV_SIZE_64M 0
+#define PPC7D_CPLD_FLASH_DEV_SIZE_32M 1
+#define PPC7D_CPLD_FLASH_DEV_SIZE_16M 3
+#define PPC7D_CPLD_FLASH_BANK_NUM_4 0x00
+#define PPC7D_CPLD_FLASH_BANK_NUM_3 0x04
+#define PPC7D_CPLD_FLASH_BANK_NUM_2 0x08
+#define PPC7D_CPLD_FLASH_BANK_NUM_1 0x0c
+
+/* SCSI_LED */
+#define PPC7D_CPLD_SCSI_ACTIVITY_LED_OFF 0
+#define PPC7D_CPLD_SCSI_ACTIVITY_LED_ON 1
+
+/* EQUIPMENT_PRESENT_1 */
+#define PPC7D_CPLD_EQPT_PRES_1_FITTED 0
+#define PPC7D_CPLD_EQPT_PRES_1_PMC2_MASK (0x80 >> 2)
+#define PPC7D_CPLD_EQPT_PRES_1_PMC1_MASK (0x80 >> 3)
+#define PPC7D_CPLD_EQPT_PRES_1_AFIX_MASK (0x80 >> 4)
+
+/* EQUIPMENT_PRESENT_2 */
+#define PPC7D_CPLD_EQPT_PRES_2_FITTED !0
+#define PPC7D_CPLD_EQPT_PRES_2_UNIVERSE_MASK (0x80 >> 0)
+#define PPC7D_CPLD_EQPT_PRES_2_COM36_MASK (0x80 >> 2)
+#define PPC7D_CPLD_EQPT_PRES_2_GIGE_MASK (0x80 >> 3)
+#define PPC7D_CPLD_EQPT_PRES_2_DUALGIGE_MASK (0x80 >> 4)
+
+/* EQUIPMENT_PRESENT_3 */
+#define PPC7D_CPLD_EQPT_PRES_3_PMC2_V_MASK (0x80 >> 3)
+#define PPC7D_CPLD_EQPT_PRES_3_PMC2_5V (0 >> 3)
+#define PPC7D_CPLD_EQPT_PRES_3_PMC2_3V (0x80 >> 3)
+#define PPC7D_CPLD_EQPT_PRES_3_PMC1_V_MASK (0x80 >> 4)
+#define PPC7D_CPLD_EQPT_PRES_3_PMC1_5V (0 >> 4)
+#define PPC7D_CPLD_EQPT_PRES_3_PMC1_3V (0x80 >> 4)
+#define PPC7D_CPLD_EQPT_PRES_3_PMC_POWER_MASK (0x80 >> 5)
+#define PPC7D_CPLD_EQPT_PRES_3_PMC_POWER_INTER (0 >> 5)
+#define PPC7D_CPLD_EQPT_PRES_3_PMC_POWER_VME (0x80 >> 5)
+
+/* EQUIPMENT_PRESENT_4 */
+#define PPC7D_CPLD_EQPT_PRES_4_LPT_MASK (0x80 >> 2)
+#define PPC7D_CPLD_EQPT_PRES_4_LPT_FITTED (0x80 >> 2)
+#define PPC7D_CPLD_EQPT_PRES_4_PS2_USB2_MASK (0xc0 >> 6)
+#define PPC7D_CPLD_EQPT_PRES_4_PS2_FITTED (0x40 >> 6)
+#define PPC7D_CPLD_EQPT_PRES_4_USB2_FITTED (0x80 >> 6)
+
+/* CPLD_LEDS */
+#define PPC7D_CPLD_LEDS_ON (!0)
+#define PPC7D_CPLD_LEDS_OFF (0)
+#define PPC7D_CPLD_LEDS_NVRAM_PAGE_MASK (0xc0 >> 2)
+#define PPC7D_CPLD_LEDS_DS201_MASK (0x80 >> 4)
+#define PPC7D_CPLD_LEDS_DS219_MASK (0x80 >> 5)
+#define PPC7D_CPLD_LEDS_DS220_MASK (0x80 >> 6)
+#define PPC7D_CPLD_LEDS_DS221_MASK (0x80 >> 7)
+
+/* CPLD_COMS */
+#define PPC7D_CPLD_COMS_COM3_TCLKEN (0x80 >> 0)
+#define PPC7D_CPLD_COMS_COM3_RTCLKEN (0x80 >> 1)
+#define PPC7D_CPLD_COMS_COM3_MODE_MASK (0x80 >> 2)
+#define PPC7D_CPLD_COMS_COM3_MODE_RS232 (0)
+#define PPC7D_CPLD_COMS_COM3_MODE_RS422 (0x80 >> 2)
+#define PPC7D_CPLD_COMS_COM3_TXEN (0x80 >> 3)
+#define PPC7D_CPLD_COMS_COM4_TCLKEN (0x80 >> 4)
+#define PPC7D_CPLD_COMS_COM4_RTCLKEN (0x80 >> 5)
+#define PPC7D_CPLD_COMS_COM4_MODE_MASK (0x80 >> 6)
+#define PPC7D_CPLD_COMS_COM4_MODE_RS232 (0)
+#define PPC7D_CPLD_COMS_COM4_MODE_RS422 (0x80 >> 6)
+#define PPC7D_CPLD_COMS_COM4_TXEN (0x80 >> 7)
+
+/* CPLD_RTS */
+#define PPC7D_CPLD_RTS_COM36_LOOPBACK (0x80 >> 0)
+#define PPC7D_CPLD_RTS_COM4_SCLK (0x80 >> 1)
+#define PPC7D_CPLD_RTS_COM3_TXFUNC_MASK (0xc0 >> 2)
+#define PPC7D_CPLD_RTS_COM3_TXFUNC_DISABLED (0 >> 2)
+#define PPC7D_CPLD_RTS_COM3_TXFUNC_ENABLED (0x80 >> 2)
+#define PPC7D_CPLD_RTS_COM3_TXFUNC_ENABLED_RTG3 (0xc0 >> 2)
+#define PPC7D_CPLD_RTS_COM3_TXFUNC_ENABLED_RTG3S (0xc0 >> 2)
+#define PPC7D_CPLD_RTS_COM56_MODE_MASK (0x80 >> 4)
+#define PPC7D_CPLD_RTS_COM56_MODE_RS232 (0)
+#define PPC7D_CPLD_RTS_COM56_MODE_RS422 (0x80 >> 4)
+#define PPC7D_CPLD_RTS_COM56_ENABLE_MASK (0x80 >> 5)
+#define PPC7D_CPLD_RTS_COM56_DISABLED (0)
+#define PPC7D_CPLD_RTS_COM56_ENABLED (0x80 >> 5)
+#define PPC7D_CPLD_RTS_COM4_TXFUNC_MASK (0xc0 >> 6)
+#define PPC7D_CPLD_RTS_COM4_TXFUNC_DISABLED (0 >> 6)
+#define PPC7D_CPLD_RTS_COM4_TXFUNC_ENABLED (0x80 >> 6)
+#define PPC7D_CPLD_RTS_COM4_TXFUNC_ENABLED_RTG3 (0x40 >> 6)
+#define PPC7D_CPLD_RTS_COM4_TXFUNC_ENABLED_RTG3S (0x40 >> 6)
+
+/* WATCHDOG_TRIG */
+#define PPC7D_CPLD_WDOG_CAUSE_MASK (0x80 >> 0)
+#define PPC7D_CPLD_WDOG_CAUSE_NORMAL_RESET (0 >> 0)
+#define PPC7D_CPLD_WDOG_CAUSE_WATCHDOG (0x80 >> 0)
+#define PPC7D_CPLD_WDOG_ENABLE_MASK (0x80 >> 6)
+#define PPC7D_CPLD_WDOG_ENABLE_OFF (0 >> 6)
+#define PPC7D_CPLD_WDOG_ENABLE_ON (0x80 >> 6)
+#define PPC7D_CPLD_WDOG_RESETSW_MASK (0x80 >> 7)
+#define PPC7D_CPLD_WDOG_RESETSW_OFF (0 >> 7)
+#define PPC7D_CPLD_WDOG_RESETSW_ON (0x80 >> 7)
+
+/* Interrupt mask and status bits */
+#define PPC7D_CPLD_INTR_TEMP_MASK (0x80 >> 0)
+#define PPC7D_CPLD_INTR_HB8_MASK (0x80 >> 1)
+#define PPC7D_CPLD_INTR_PHY1_MASK (0x80 >> 2)
+#define PPC7D_CPLD_INTR_PHY0_MASK (0x80 >> 3)
+#define PPC7D_CPLD_INTR_ISANMI_MASK (0x80 >> 5)
+#define PPC7D_CPLD_INTR_CRITTEMP_MASK (0x80 >> 6)
+
+/* CPLD_INTR */
+#define PPC7D_CPLD_INTR_ENABLE_OFF (0)
+#define PPC7D_CPLD_INTR_ENABLE_ON (!0)
+
+/* CPLD_INTR_STATUS */
+#define PPC7D_CPLD_INTR_STATUS_OFF (0)
+#define PPC7D_CPLD_INTR_STATUS_ON (!0)
+
+/* CPLD_PCI_CONFIG */
+#define PPC7D_CPLD_PCI_CONFIG_PCI0_MASK 0x70
+#define PPC7D_CPLD_PCI_CONFIG_PCI0_PCI33 0x00
+#define PPC7D_CPLD_PCI_CONFIG_PCI0_PCI66 0x10
+#define PPC7D_CPLD_PCI_CONFIG_PCI0_PCIX33 0x40
+#define PPC7D_CPLD_PCI_CONFIG_PCI0_PCIX66 0x50
+#define PPC7D_CPLD_PCI_CONFIG_PCI0_PCIX100 0x60
+#define PPC7D_CPLD_PCI_CONFIG_PCI0_PCIX133 0x70
+#define PPC7D_CPLD_PCI_CONFIG_PCI1_MASK 0x07
+#define PPC7D_CPLD_PCI_CONFIG_PCI1_PCI33 0x00
+#define PPC7D_CPLD_PCI_CONFIG_PCI1_PCI66 0x01
+#define PPC7D_CPLD_PCI_CONFIG_PCI1_PCIX33 0x04
+#define PPC7D_CPLD_PCI_CONFIG_PCI1_PCIX66 0x05
+#define PPC7D_CPLD_PCI_CONFIG_PCI1_PCIX100 0x06
+#define PPC7D_CPLD_PCI_CONFIG_PCI1_PCIX133 0x07
+
+/* CPLD_BOARD_REVISION */
+#define PPC7D_CPLD_BOARD_REVISION_NUMBER_MASK 0xe0
+#define PPC7D_CPLD_BOARD_REVISION_LETTER_MASK 0x1f
+
+/* CPLD_EXTENDED_ID */
+#define PPC7D_CPLD_EXTENDED_ID_PPC7D 0x18
+
+/* CPLD_ID_LINK */
+#define PPC7D_CPLD_ID_LINK_VME64_GAP_MASK (0x80 >> 2)
+#define PPC7D_CPLD_ID_LINK_VME64_GA4_MASK (0x80 >> 3)
+#define PPC7D_CPLD_ID_LINK_E13_MASK (0x80 >> 4)
+#define PPC7D_CPLD_ID_LINK_E12_MASK (0x80 >> 5)
+#define PPC7D_CPLD_ID_LINK_E7_MASK (0x80 >> 6)
+#define PPC7D_CPLD_ID_LINK_E6_MASK (0x80 >> 7)
+
+/* CPLD_MOTHERBOARD_TYPE */
+#define PPC7D_CPLD_MB_TYPE_ECC_ENABLE_MASK (0x80 >> 0)
+#define PPC7D_CPLD_MB_TYPE_ECC_ENABLED (0x80 >> 0)
+#define PPC7D_CPLD_MB_TYPE_ECC_DISABLED (0 >> 0)
+#define PPC7D_CPLD_MB_TYPE_ECC_FITTED_MASK (0x80 >> 3)
+#define PPC7D_CPLD_MB_TYPE_PLL_MASK 0x0c
+#define PPC7D_CPLD_MB_TYPE_PLL_133 0x00
+#define PPC7D_CPLD_MB_TYPE_PLL_100 0x08
+#define PPC7D_CPLD_MB_TYPE_PLL_64 0x04
+#define PPC7D_CPLD_MB_TYPE_HW_ID_MASK 0x03
+
+/* CPLD_FLASH_WRITE_CNTL */
+#define PPD7D_CPLD_FLASH_CNTL_WR_LINK_MASK (0x80 >> 0)
+#define PPD7D_CPLD_FLASH_CNTL_WR_LINK_FITTED (0x80 >> 0)
+#define PPD7D_CPLD_FLASH_CNTL_BOOT_LINK_MASK (0x80 >> 2)
+#define PPD7D_CPLD_FLASH_CNTL_BOOT_LINK_FITTED (0x80 >> 2)
+#define PPD7D_CPLD_FLASH_CNTL_USER_LINK_MASK (0x80 >> 3)
+#define PPD7D_CPLD_FLASH_CNTL_USER_LINK_FITTED (0x80 >> 3)
+#define PPD7D_CPLD_FLASH_CNTL_RECO_WR_MASK (0x80 >> 5)
+#define PPD7D_CPLD_FLASH_CNTL_RECO_WR_ENABLED (0x80 >> 5)
+#define PPD7D_CPLD_FLASH_CNTL_BOOT_WR_MASK (0x80 >> 6)
+#define PPD7D_CPLD_FLASH_CNTL_BOOT_WR_ENABLED (0x80 >> 6)
+#define PPD7D_CPLD_FLASH_CNTL_USER_WR_MASK (0x80 >> 7)
+#define PPD7D_CPLD_FLASH_CNTL_USER_WR_ENABLED (0x80 >> 7)
+
+/* CPLD_SW_FLASH_WRITE_PROTECT */
+#define PPC7D_CPLD_SW_FLASH_WRPROT_ENABLED (!0)
+#define PPC7D_CPLD_SW_FLASH_WRPROT_DISABLED (0)
+#define PPC7D_CPLD_SW_FLASH_WRPROT_SYSBOOT_MASK (0x80 >> 6)
+#define PPC7D_CPLD_SW_FLASH_WRPROT_USER_MASK (0x80 >> 7)
+
+/* CPLD_FLASH_WRITE_CNTL */
+#define PPC7D_CPLD_FLASH_CNTL_NVRAM_PROT_MASK (0x80 >> 0)
+#define PPC7D_CPLD_FLASH_CNTL_NVRAM_DISABLED (0 >> 0)
+#define PPC7D_CPLD_FLASH_CNTL_NVRAM_ENABLED (0x80 >> 0)
+#define PPC7D_CPLD_FLASH_CNTL_ALTBOOT_LINK_MASK (0x80 >> 1)
+#define PPC7D_CPLD_FLASH_CNTL_VMEBOOT_LINK_MASK (0x80 >> 2)
+#define PPC7D_CPLD_FLASH_CNTL_RECBOOT_LINK_MASK (0x80 >> 3)
+
+
+#endif /* __PPC_PLATFORMS_PPC7D_H */
diff --git a/arch/ppc/platforms/residual.c b/arch/ppc/platforms/residual.c
new file mode 100644
index 0000000..0f84ca6
--- /dev/null
+++ b/arch/ppc/platforms/residual.c
@@ -0,0 +1,1034 @@
+/*
+ * Code to deal with the PReP residual data.
+ *
+ * Written by: Cort Dougan (cort@cs.nmt.edu)
+ * Improved _greatly_ and rewritten by Gabriel Paubert (paubert@iram.es)
+ *
+ * This file is based on the following documentation:
+ *
+ * IBM Power Personal Systems Architecture
+ * Residual Data
+ * Document Number: PPS-AR-FW0001
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file COPYING in the main directory of this archive
+ * for more details.
+ *
+ */
+
+#include <linux/string.h>
+#include <asm/residual.h>
+#include <asm/pnp.h>
+#include <asm/byteorder.h>
+
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/stddef.h>
+#include <linux/unistd.h>
+#include <linux/ptrace.h>
+#include <linux/slab.h>
+#include <linux/user.h>
+#include <linux/a.out.h>
+#include <linux/tty.h>
+#include <linux/major.h>
+#include <linux/interrupt.h>
+#include <linux/reboot.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/pci.h>
+#include <linux/ide.h>
+
+#include <asm/sections.h>
+#include <asm/mmu.h>
+#include <asm/io.h>
+#include <asm/pgtable.h>
+#include <asm/ide.h>
+
+
+unsigned char __res[sizeof(RESIDUAL)] __prepdata = {0,};
+RESIDUAL *res = (RESIDUAL *)&__res;
+
+char * PnP_BASE_TYPES[] __initdata = {
+ "Reserved",
+ "MassStorageDevice",
+ "NetworkInterfaceController",
+ "DisplayController",
+ "MultimediaController",
+ "MemoryController",
+ "BridgeController",
+ "CommunicationsDevice",
+ "SystemPeripheral",
+ "InputDevice",
+ "ServiceProcessor"
+ };
+
+/* Device Sub Type Codes */
+
+unsigned char * PnP_SUB_TYPES[] __initdata = {
+ "\001\000SCSIController",
+ "\001\001IDEController",
+ "\001\002FloppyController",
+ "\001\003IPIController",
+ "\001\200OtherMassStorageController",
+ "\002\000EthernetController",
+ "\002\001TokenRingController",
+ "\002\002FDDIController",
+ "\002\0x80OtherNetworkController",
+ "\003\000VGAController",
+ "\003\001SVGAController",
+ "\003\002XGAController",
+ "\003\200OtherDisplayController",
+ "\004\000VideoController",
+ "\004\001AudioController",
+ "\004\200OtherMultimediaController",
+ "\005\000RAM",
+ "\005\001FLASH",
+ "\005\200OtherMemoryDevice",
+ "\006\000HostProcessorBridge",
+ "\006\001ISABridge",
+ "\006\002EISABridge",
+ "\006\003MicroChannelBridge",
+ "\006\004PCIBridge",
+ "\006\005PCMCIABridge",
+ "\006\006VMEBridge",
+ "\006\200OtherBridgeDevice",
+ "\007\000RS232Device",
+ "\007\001ATCompatibleParallelPort",
+ "\007\200OtherCommunicationsDevice",
+ "\010\000ProgrammableInterruptController",
+ "\010\001DMAController",
+ "\010\002SystemTimer",
+ "\010\003RealTimeClock",
+ "\010\004L2Cache",
+ "\010\005NVRAM",
+ "\010\006PowerManagement",
+ "\010\007CMOS",
+ "\010\010OperatorPanel",
+ "\010\011ServiceProcessorClass1",
+ "\010\012ServiceProcessorClass2",
+ "\010\013ServiceProcessorClass3",
+ "\010\014GraphicAssist",
+ "\010\017SystemPlanar",
+ "\010\200OtherSystemPeripheral",
+ "\011\000KeyboardController",
+ "\011\001Digitizer",
+ "\011\002MouseController",
+ "\011\003TabletController",
+ "\011\0x80OtherInputController",
+ "\012\000GeneralMemoryController",
+ NULL
+};
+
+/* Device Interface Type Codes */
+
+unsigned char * PnP_INTERFACES[] __initdata = {
+ "\000\000\000General",
+ "\001\000\000GeneralSCSI",
+ "\001\001\000GeneralIDE",
+ "\001\001\001ATACompatible",
+
+ "\001\002\000GeneralFloppy",
+ "\001\002\001Compatible765",
+ "\001\002\002NS398_Floppy", /* NS Super I/O wired to use index
+ register at port 398 and data
+ register at port 399 */
+ "\001\002\003NS26E_Floppy", /* Ports 26E and 26F */
+ "\001\002\004NS15C_Floppy", /* Ports 15C and 15D */
+ "\001\002\005NS2E_Floppy", /* Ports 2E and 2F */
+ "\001\002\006CHRP_Floppy", /* CHRP Floppy in PR*P system */
+
+ "\001\003\000GeneralIPI",
+
+ "\002\000\000GeneralEther",
+ "\002\001\000GeneralToken",
+ "\002\002\000GeneralFDDI",
+
+ "\003\000\000GeneralVGA",
+ "\003\001\000GeneralSVGA",
+ "\003\002\000GeneralXGA",
+
+ "\004\000\000GeneralVideo",
+ "\004\001\000GeneralAudio",
+ "\004\001\001CS4232Audio", /* CS 4232 Plug 'n Play Configured */
+
+ "\005\000\000GeneralRAM",
+ /* This one is obviously wrong ! */
+ "\005\000\000PCIMemoryController", /* PCI Config Method */
+ "\005\000\001RS6KMemoryController", /* RS6K Config Method */
+ "\005\001\000GeneralFLASH",
+
+ "\006\000\000GeneralHostBridge",
+ "\006\001\000GeneralISABridge",
+ "\006\002\000GeneralEISABridge",
+ "\006\003\000GeneralMCABridge",
+ /* GeneralPCIBridge = 0, */
+ "\006\004\000PCIBridgeDirect",
+ "\006\004\001PCIBridgeIndirect",
+ "\006\004\002PCIBridgeRS6K",
+ "\006\005\000GeneralPCMCIABridge",
+ "\006\006\000GeneralVMEBridge",
+
+ "\007\000\000GeneralRS232",
+ "\007\000\001COMx",
+ "\007\000\002Compatible16450",
+ "\007\000\003Compatible16550",
+ "\007\000\004NS398SerPort", /* NS Super I/O wired to use index
+ register at port 398 and data
+ register at port 399 */
+ "\007\000\005NS26ESerPort", /* Ports 26E and 26F */
+ "\007\000\006NS15CSerPort", /* Ports 15C and 15D */
+ "\007\000\007NS2ESerPort", /* Ports 2E and 2F */
+
+ "\007\001\000GeneralParPort",
+ "\007\001\001LPTx",
+ "\007\001\002NS398ParPort", /* NS Super I/O wired to use index
+ register at port 398 and data
+ register at port 399 */
+ "\007\001\003NS26EParPort", /* Ports 26E and 26F */
+ "\007\001\004NS15CParPort", /* Ports 15C and 15D */
+ "\007\001\005NS2EParPort", /* Ports 2E and 2F */
+
+ "\010\000\000GeneralPIC",
+ "\010\000\001ISA_PIC",
+ "\010\000\002EISA_PIC",
+ "\010\000\003MPIC",
+ "\010\000\004RS6K_PIC",
+
+ "\010\001\000GeneralDMA",
+ "\010\001\001ISA_DMA",
+ "\010\001\002EISA_DMA",
+
+ "\010\002\000GeneralTimer",
+ "\010\002\001ISA_Timer",
+ "\010\002\002EISA_Timer",
+ "\010\003\000GeneralRTC",
+ "\010\003\001ISA_RTC",
+
+ "\010\004\001StoreThruOnly",
+ "\010\004\002StoreInEnabled",
+ "\010\004\003RS6KL2Cache",
+
+ "\010\005\000IndirectNVRAM", /* Indirectly addressed */
+ "\010\005\001DirectNVRAM", /* Memory Mapped */
+ "\010\005\002IndirectNVRAM24", /* Indirectly addressed - 24 bit */
+
+ "\010\006\000GeneralPowerManagement",
+ "\010\006\001EPOWPowerManagement",
+ "\010\006\002PowerControl", // d1378
+
+ "\010\007\000GeneralCMOS",
+
+ "\010\010\000GeneralOPPanel",
+ "\010\010\001HarddiskLight",
+ "\010\010\002CDROMLight",
+ "\010\010\003PowerLight",
+ "\010\010\004KeyLock",
+ "\010\010\005ANDisplay", /* AlphaNumeric Display */
+ "\010\010\006SystemStatusLED", /* 3 digit 7 segment LED */
+ "\010\010\007CHRP_SystemStatusLED", /* CHRP LEDs in PR*P system */
+
+ "\010\011\000GeneralServiceProcessor",
+ "\010\012\000GeneralServiceProcessor",
+ "\010\013\000GeneralServiceProcessor",
+
+ "\010\014\001TransferData",
+ "\010\014\002IGMC32",
+ "\010\014\003IGMC64",
+
+ "\010\017\000GeneralSystemPlanar", /* 10/5/95 */
+ NULL
+ };
+
+static const unsigned char __init *PnP_SUB_TYPE_STR(unsigned char BaseType,
+ unsigned char SubType) {
+ unsigned char ** s=PnP_SUB_TYPES;
+ while (*s && !((*s)[0]==BaseType
+ && (*s)[1]==SubType)) s++;
+ if (*s) return *s+2;
+ else return("Unknown !");
+};
+
+static const unsigned char __init *PnP_INTERFACE_STR(unsigned char BaseType,
+ unsigned char SubType,
+ unsigned char Interface) {
+ unsigned char ** s=PnP_INTERFACES;
+ while (*s && !((*s)[0]==BaseType
+ && (*s)[1]==SubType
+ && (*s)[2]==Interface)) s++;
+ if (*s) return *s+3;
+ else return NULL;
+};
+
+static void __init printsmallvendor(PnP_TAG_PACKET *pkt, int size) {
+ int i, c;
+ char decomp[4];
+#define p pkt->S14_Pack.S14_Data.S14_PPCPack
+ switch(p.Type) {
+ case 1:
+ /* Decompress first 3 chars */
+ c = *(unsigned short *)p.PPCData;
+ decomp[0]='A'-1+((c>>10)&0x1F);
+ decomp[1]='A'-1+((c>>5)&0x1F);
+ decomp[2]='A'-1+(c&0x1F);
+ decomp[3]=0;
+ printk(" Chip identification: %s%4.4X\n",
+ decomp, ld_le16((unsigned short *)(p.PPCData+2)));
+ break;
+ default:
+ printk(" Small vendor item type 0x%2.2x, data (hex): ",
+ p.Type);
+ for(i=0; i<size-2; i++) printk("%2.2x ", p.PPCData[i]);
+ printk("\n");
+ break;
+ }
+#undef p
+}
+
+static void __init printsmallpacket(PnP_TAG_PACKET * pkt, int size) {
+ static const unsigned char * intlevel[] = {"high", "low"};
+ static const unsigned char * intsense[] = {"edge", "level"};
+
+ switch (tag_small_item_name(pkt->S1_Pack.Tag)) {
+ case PnPVersion:
+ printk(" PnPversion 0x%x.%x\n",
+ pkt->S1_Pack.Version[0], /* How to interpret version ? */
+ pkt->S1_Pack.Version[1]);
+ break;
+// case Logicaldevice:
+ break;
+// case CompatibleDevice:
+ break;
+ case IRQFormat:
+#define p pkt->S4_Pack
+ printk(" IRQ Mask 0x%4.4x, %s %s sensitive\n",
+ ld_le16((unsigned short *)p.IRQMask),
+ intlevel[(size>3) ? !(p.IRQInfo&0x05) : 0],
+ intsense[(size>3) ? !(p.IRQInfo&0x03) : 0]);
+#undef p
+ break;
+ case DMAFormat:
+#define p pkt->S5_Pack
+ printk(" DMA channel mask 0x%2.2x, info 0x%2.2x\n",
+ p.DMAMask, p.DMAInfo);
+#undef p
+ break;
+ case StartDepFunc:
+ printk("Start dependent function:\n");
+ break;
+ case EndDepFunc:
+ printk("End dependent function\n");
+ break;
+ case IOPort:
+#define p pkt->S8_Pack
+ printk(" Variable (%d decoded bits) I/O port\n"
+ " from 0x%4.4x to 0x%4.4x, alignment %d, %d ports\n",
+ p.IOInfo&ISAAddr16bit?16:10,
+ ld_le16((unsigned short *)p.RangeMin),
+ ld_le16((unsigned short *)p.RangeMax),
+ p.IOAlign, p.IONum);
+#undef p
+ break;
+ case FixedIOPort:
+#define p pkt->S9_Pack
+ printk(" Fixed (10 decoded bits) I/O port from %3.3x to %3.3x\n",
+ (p.Range[1]<<8)|p.Range[0],
+ ((p.Range[1]<<8)|p.Range[0])+p.IONum-1);
+#undef p
+ break;
+ case Res1:
+ case Res2:
+ case Res3:
+ printk(" Undefined packet type %d!\n",
+ tag_small_item_name(pkt->S1_Pack.Tag));
+ break;
+ case SmallVendorItem:
+ printsmallvendor(pkt,size);
+ break;
+ default:
+ printk(" Type 0x2.2x%d, size=%d\n",
+ pkt->S1_Pack.Tag, size);
+ break;
+ }
+}
+
+static void __init printlargevendor(PnP_TAG_PACKET * pkt, int size) {
+ static const unsigned char * addrtype[] = {"I/O", "Memory", "System"};
+ static const unsigned char * inttype[] = {"8259", "MPIC", "RS6k BUID %d"};
+ static const unsigned char * convtype[] = {"Bus Memory", "Bus I/O", "DMA"};
+ static const unsigned char * transtype[] = {"direct", "mapped", "direct-store segment"};
+ static const unsigned char * L2type[] = {"WriteThru", "CopyBack"};
+ static const unsigned char * L2assoc[] = {"DirectMapped", "2-way set"};
+
+ int i;
+ char tmpstr[30], *t;
+#define p pkt->L4_Pack.L4_Data.L4_PPCPack
+ switch(p.Type) {
+ case 2:
+ printk(" %d K %s %s L2 cache, %d/%d bytes line/sector size\n",
+ ld_le32((unsigned int *)p.PPCData),
+ L2type[p.PPCData[10]-1],
+ L2assoc[p.PPCData[4]-1],
+ ld_le16((unsigned short *)p.PPCData+3),
+ ld_le16((unsigned short *)p.PPCData+4));
+ break;
+ case 3:
+ printk(" PCI Bridge parameters\n"
+ " ConfigBaseAddress %0x\n"
+ " ConfigBaseData %0x\n"
+ " Bus number %d\n",
+ ld_le32((unsigned int *)p.PPCData),
+ ld_le32((unsigned int *)(p.PPCData+8)),
+ p.PPCData[16]);
+ for(i=20; i<size-4; i+=12) {
+ int j, first;
+ if(p.PPCData[i]) printk(" PCI Slot %d", p.PPCData[i]);
+ else printk (" Integrated PCI device");
+ for(j=0, first=1, t=tmpstr; j<4; j++) {
+ int line=ld_le16((unsigned short *)(p.PPCData+i+4)+j);
+ if(line!=0xffff){
+ if(first) first=0; else *t++='/';
+ *t++='A'+j;
+ }
+ }
+ *t='\0';
+ printk(" DevFunc 0x%x interrupt line(s) %s routed to",
+ p.PPCData[i+1],tmpstr);
+ sprintf(tmpstr,
+ inttype[p.PPCData[i+2]-1],
+ p.PPCData[i+3]);
+ printk(" %s line(s) ",
+ tmpstr);
+ for(j=0, first=1, t=tmpstr; j<4; j++) {
+ int line=ld_le16((unsigned short *)(p.PPCData+i+4)+j);
+ if(line!=0xffff){
+ if(first) first=0; else *t++='/';
+ t+=sprintf(t,"%d(%c)",
+ line&0x7fff,
+ line&0x8000?'E':'L');
+ }
+ }
+ printk("%s\n",tmpstr);
+ }
+ break;
+ case 5:
+ printk(" Bridge address translation, %s decoding:\n"
+ " Processor Bus Size Conversion Translation\n"
+ " 0x%8.8x 0x%8.8x 0x%8.8x %s %s\n",
+ p.PPCData[0]&1 ? "positive" : "subtractive",
+ ld_le32((unsigned int *)p.PPCData+1),
+ ld_le32((unsigned int *)p.PPCData+3),
+ ld_le32((unsigned int *)p.PPCData+5),
+ convtype[p.PPCData[2]-1],
+ transtype[p.PPCData[1]-1]);
+ break;
+ case 6:
+ printk(" Bus speed %d Hz, %d slot(s)\n",
+ ld_le32((unsigned int *)p.PPCData),
+ p.PPCData[4]);
+ break;
+ case 7:
+ printk(" SCSI buses: %d, id(s):", p.PPCData[0]);
+ for(i=1; i<=p.PPCData[0]; i++)
+ printk(" %d%c", p.PPCData[i], i==p.PPCData[0] ? '\n' : ',');
+ break;
+ case 9:
+ printk(" %s address (%d bits), at 0x%x size 0x%x bytes\n",
+ addrtype[p.PPCData[0]-1],
+ p.PPCData[1],
+ ld_le32((unsigned int *)(p.PPCData+4)),
+ ld_le32((unsigned int *)(p.PPCData+12)));
+ break;
+ case 10:
+ sprintf(tmpstr,
+ inttype[p.PPCData[0]-1],
+ p.PPCData[1]);
+
+ printk(" ISA interrupts routed to %s\n"
+ " lines",
+ tmpstr);
+ for(i=0; i<16; i++) {
+ int line=ld_le16((unsigned short *)p.PPCData+i+1);
+ if (line!=0xffff) printk(" %d(IRQ%d)", line, i);
+ }
+ printk("\n");
+ break;
+ default:
+ printk(" Large vendor item type 0x%2.2x\n Data (hex):",
+ p.Type);
+ for(i=0; i<size-4; i++) printk(" %2.2x", p.PPCData[i]);
+ printk("\n");
+#undef p
+ }
+}
+
+static void __init printlargepacket(PnP_TAG_PACKET * pkt, int size) {
+ switch (tag_large_item_name(pkt->S1_Pack.Tag)) {
+ case LargeVendorItem:
+ printlargevendor(pkt, size);
+ break;
+ default:
+ printk(" Type 0x2.2x%d, size=%d\n",
+ pkt->S1_Pack.Tag, size);
+ break;
+ }
+}
+
+static void __init printpackets(PnP_TAG_PACKET * pkt, const char * cat)
+{
+ if (pkt->S1_Pack.Tag== END_TAG) {
+ printk(" No packets describing %s resources.\n", cat);
+ return;
+ }
+ printk( " Packets describing %s resources:\n",cat);
+ do {
+ int size;
+ if (tag_type(pkt->S1_Pack.Tag)) {
+ size= 3 +
+ pkt->L1_Pack.Count0 +
+ pkt->L1_Pack.Count1*256;
+ printlargepacket(pkt, size);
+ } else {
+ size=tag_small_count(pkt->S1_Pack.Tag)+1;
+ printsmallpacket(pkt, size);
+ }
+ pkt = (PnP_TAG_PACKET *)((unsigned char *) pkt + size);
+ } while (pkt->S1_Pack.Tag != END_TAG);
+}
+
+void __init print_residual_device_info(void)
+{
+ int i;
+ PPC_DEVICE *dev;
+#define did dev->DeviceId
+
+ /* make sure we have residual data first */
+ if (!have_residual_data)
+ return;
+
+ printk("Residual: %ld devices\n", res->ActualNumDevices);
+ for ( i = 0;
+ i < res->ActualNumDevices ;
+ i++)
+ {
+ char decomp[4], sn[20];
+ const char * s;
+ dev = &res->Devices[i];
+ s = PnP_INTERFACE_STR(did.BaseType, did.SubType,
+ did.Interface);
+ if(!s) {
+ sprintf(sn, "interface %d", did.Interface);
+ s=sn;
+ }
+ if ( did.BusId & PCIDEVICE )
+ printk("PCI Device, Bus %d, DevFunc 0x%x:",
+ dev->BusAccess.PCIAccess.BusNumber,
+ dev->BusAccess.PCIAccess.DevFuncNumber);
+ if ( did.BusId & PNPISADEVICE ) printk("PNPISA Device:");
+ if ( did.BusId & ISADEVICE )
+ printk("ISA Device, Slot %d, LogicalDev %d:",
+ dev->BusAccess.ISAAccess.SlotNumber,
+ dev->BusAccess.ISAAccess.LogicalDevNumber);
+ if ( did.BusId & EISADEVICE ) printk("EISA Device:");
+ if ( did.BusId & PROCESSORDEVICE )
+ printk("ProcBus Device, Bus %d, BUID %d: ",
+ dev->BusAccess.ProcBusAccess.BusNumber,
+ dev->BusAccess.ProcBusAccess.BUID);
+ if ( did.BusId & PCMCIADEVICE ) printk("PCMCIA ");
+ if ( did.BusId & VMEDEVICE ) printk("VME ");
+ if ( did.BusId & MCADEVICE ) printk("MCA ");
+ if ( did.BusId & MXDEVICE ) printk("MX ");
+ /* Decompress first 3 chars */
+ decomp[0]='A'-1+((did.DevId>>26)&0x1F);
+ decomp[1]='A'-1+((did.DevId>>21)&0x1F);
+ decomp[2]='A'-1+((did.DevId>>16)&0x1F);
+ decomp[3]=0;
+ printk(" %s%4.4lX, %s, %s, %s\n",
+ decomp, did.DevId&0xffff,
+ PnP_BASE_TYPES[did.BaseType],
+ PnP_SUB_TYPE_STR(did.BaseType,did.SubType),
+ s);
+ if ( dev->AllocatedOffset )
+ printpackets( (union _PnP_TAG_PACKET *)
+ &res->DevicePnPHeap[dev->AllocatedOffset],
+ "allocated");
+ if ( dev->PossibleOffset )
+ printpackets( (union _PnP_TAG_PACKET *)
+ &res->DevicePnPHeap[dev->PossibleOffset],
+ "possible");
+ if ( dev->CompatibleOffset )
+ printpackets( (union _PnP_TAG_PACKET *)
+ &res->DevicePnPHeap[dev->CompatibleOffset],
+ "compatible");
+ }
+}
+
+
+#if 0
+static void __init printVPD(void) {
+#define vpd res->VitalProductData
+ int ps=vpd.PageSize, i, j;
+ static const char* Usage[]={
+ "FirmwareStack", "FirmwareHeap", "FirmwareCode", "BootImage",
+ "Free", "Unpopulated", "ISAAddr", "PCIConfig",
+ "IOMemory", "SystemIO", "SystemRegs", "PCIAddr",
+ "UnPopSystemRom", "SystemROM", "ResumeBlock", "Other"
+ };
+ static const unsigned char *FWMan[]={
+ "IBM", "Motorola", "FirmWorks", "Bull"
+ };
+ static const unsigned char *FWFlags[]={
+ "Conventional", "OpenFirmware", "Diagnostics", "LowDebug",
+ "MultiBoot", "LowClient", "Hex41", "FAT",
+ "ISO9660", "SCSI_ID_Override", "Tape_Boot", "FW_Boot_Path"
+ };
+ static const unsigned char *ESM[]={
+ "Port92", "PCIConfigA8", "FF001030", "????????"
+ };
+ static const unsigned char *SIOM[]={
+ "Port850", "????????", "PCIConfigA8", "????????"
+ };
+
+ printk("Model: %s\n",vpd.PrintableModel);
+ printk("Serial: %s\n", vpd.Serial);
+ printk("FirmwareSupplier: %s\n", FWMan[vpd.FirmwareSupplier]);
+ printk("FirmwareFlags:");
+ for(j=0; j<12; j++) {
+ if (vpd.FirmwareSupports & (1<<j)) {
+ printk(" %s%c", FWFlags[j],
+ vpd.FirmwareSupports&(-2<<j) ? ',' : '\n');
+ }
+ }
+ printk("NVRamSize: %ld\n", vpd.NvramSize);
+ printk("SIMMslots: %ld\n", vpd.NumSIMMSlots);
+ printk("EndianSwitchMethod: %s\n",
+ ESM[vpd.EndianSwitchMethod>2 ? 2 : vpd.EndianSwitchMethod]);
+ printk("SpreadIOMethod: %s\n",
+ SIOM[vpd.SpreadIOMethod>3 ? 3 : vpd.SpreadIOMethod]);
+ printk("Processor/Bus frequencies (Hz): %ld/%ld\n",
+ vpd.ProcessorHz, vpd.ProcessorBusHz);
+ printk("Time Base Divisor: %ld\n", vpd.TimeBaseDivisor);
+ printk("WordWidth, PageSize: %ld, %d\n", vpd.WordWidth, ps);
+ printk("Cache sector size, Lock granularity: %ld, %ld\n",
+ vpd.CoherenceBlockSize, vpd.GranuleSize);
+ for (i=0; i<res->ActualNumMemSegs; i++) {
+ int mask=res->Segs[i].Usage, first, j;
+ printk("%8.8lx-%8.8lx ",
+ res->Segs[i].BasePage*ps,
+ (res->Segs[i].PageCount+res->Segs[i].BasePage)*ps-1);
+ for(j=15, first=1; j>=0; j--) {
+ if (mask&(1<<j)) {
+ if (first) first=0;
+ else printk(", ");
+ printk("%s", Usage[j]);
+ }
+ }
+ printk("\n");
+ }
+}
+
+/*
+ * Spit out some info about residual data
+ */
+void print_residual_device_info(void)
+{
+ int i;
+ union _PnP_TAG_PACKET *pkt;
+ PPC_DEVICE *dev;
+#define did dev->DeviceId
+
+ /* make sure we have residual data first */
+ if (!have_residual_data)
+ return;
+ printk("Residual: %ld devices\n", res->ActualNumDevices);
+ for ( i = 0;
+ i < res->ActualNumDevices ;
+ i++)
+ {
+ dev = &res->Devices[i];
+ /*
+ * pci devices
+ */
+ if ( did.BusId & PCIDEVICE )
+ {
+ printk("PCI Device:");
+ /* unknown vendor */
+ if ( !strncmp( "Unknown", pci_strvendor(did.DevId>>16), 7) )
+ printk(" id %08lx types %d/%d", did.DevId,
+ did.BaseType, did.SubType);
+ /* known vendor */
+ else
+ printk(" %s %s",
+ pci_strvendor(did.DevId>>16),
+ pci_strdev(did.DevId>>16,
+ did.DevId&0xffff)
+ );
+
+ if ( did.BusId & PNPISADEVICE )
+ {
+ printk(" pnp:");
+ /* get pnp info on the device */
+ pkt = (union _PnP_TAG_PACKET *)
+ &res->DevicePnPHeap[dev->AllocatedOffset];
+ for (; pkt->S1_Pack.Tag != DF_END_TAG;
+ pkt++ )
+ {
+ if ( (pkt->S1_Pack.Tag == S4_Packet) ||
+ (pkt->S1_Pack.Tag == S4_Packet_flags) )
+ printk(" irq %02x%02x",
+ pkt->S4_Pack.IRQMask[0],
+ pkt->S4_Pack.IRQMask[1]);
+ }
+ }
+ printk("\n");
+ continue;
+ }
+ /*
+ * isa devices
+ */
+ if ( did.BusId & ISADEVICE )
+ {
+ printk("ISA Device: basetype: %d subtype: %d",
+ did.BaseType, did.SubType);
+ printk("\n");
+ continue;
+ }
+ /*
+ * eisa devices
+ */
+ if ( did.BusId & EISADEVICE )
+ {
+ printk("EISA Device: basetype: %d subtype: %d",
+ did.BaseType, did.SubType);
+ printk("\n");
+ continue;
+ }
+ /*
+ * proc bus devices
+ */
+ if ( did.BusId & PROCESSORDEVICE )
+ {
+ printk("ProcBus Device: basetype: %d subtype: %d",
+ did.BaseType, did.SubType);
+ printk("\n");
+ continue;
+ }
+ /*
+ * pcmcia devices
+ */
+ if ( did.BusId & PCMCIADEVICE )
+ {
+ printk("PCMCIA Device: basetype: %d subtype: %d",
+ did.BaseType, did.SubType);
+ printk("\n");
+ continue;
+ }
+ printk("Unknown bus access device: busid %lx\n",
+ did.BusId);
+ }
+}
+#endif
+
+/* Returns the device index in the residual data,
+ any of the search items may be set as -1 for wildcard,
+ DevID number field (second halfword) is big endian !
+
+ Examples:
+ - search for the Interrupt controller (8259 type), 2 methods:
+ 1) i8259 = residual_find_device(~0,
+ NULL,
+ SystemPeripheral,
+ ProgrammableInterruptController,
+ ISA_PIC,
+ 0);
+ 2) i8259 = residual_find_device(~0, "PNP0000", -1, -1, -1, 0)
+
+ - search for the first two serial devices, whatever their type)
+ iserial1 = residual_find_device(~0,NULL,
+ CommunicationsDevice,
+ RS232Device,
+ -1, 0)
+ iserial2 = residual_find_device(~0,NULL,
+ CommunicationsDevice,
+ RS232Device,
+ -1, 1)
+ - but search for typical COM1 and COM2 is not easy due to the
+ fact that the interface may be anything and the name "PNP0500" or
+ "PNP0501". Quite bad.
+
+*/
+
+/* devid are easier to uncompress than to compress, so to minimize bloat
+in this rarely used area we unencode and compare */
+
+/* in residual data number is big endian in the device table and
+little endian in the heap, so we use two parameters to avoid writing
+two very similar functions */
+
+static int __init same_DevID(unsigned short vendor,
+ unsigned short Number,
+ char * str)
+{
+ static unsigned const char hexdigit[]="0123456789ABCDEF";
+ if (strlen(str)!=7) return 0;
+ if ( ( ((vendor>>10)&0x1f)+'A'-1 == str[0]) &&
+ ( ((vendor>>5)&0x1f)+'A'-1 == str[1]) &&
+ ( (vendor&0x1f)+'A'-1 == str[2]) &&
+ (hexdigit[(Number>>12)&0x0f] == str[3]) &&
+ (hexdigit[(Number>>8)&0x0f] == str[4]) &&
+ (hexdigit[(Number>>4)&0x0f] == str[5]) &&
+ (hexdigit[Number&0x0f] == str[6]) ) return 1;
+ return 0;
+}
+
+PPC_DEVICE __init *residual_find_device(unsigned long BusMask,
+ unsigned char * DevID,
+ int BaseType,
+ int SubType,
+ int Interface,
+ int n)
+{
+ int i;
+ if (!have_residual_data) return NULL;
+ for (i=0; i<res->ActualNumDevices; i++) {
+#define Dev res->Devices[i].DeviceId
+ if ( (Dev.BusId&BusMask) &&
+ (BaseType==-1 || Dev.BaseType==BaseType) &&
+ (SubType==-1 || Dev.SubType==SubType) &&
+ (Interface==-1 || Dev.Interface==Interface) &&
+ (DevID==NULL || same_DevID((Dev.DevId>>16)&0xffff,
+ Dev.DevId&0xffff, DevID)) &&
+ !(n--) ) return res->Devices+i;
+#undef Dev
+ }
+ return NULL;
+}
+
+PPC_DEVICE __init *residual_find_device_id(unsigned long BusMask,
+ unsigned short DevID,
+ int BaseType,
+ int SubType,
+ int Interface,
+ int n)
+{
+ int i;
+ if (!have_residual_data) return NULL;
+ for (i=0; i<res->ActualNumDevices; i++) {
+#define Dev res->Devices[i].DeviceId
+ if ( (Dev.BusId&BusMask) &&
+ (BaseType==-1 || Dev.BaseType==BaseType) &&
+ (SubType==-1 || Dev.SubType==SubType) &&
+ (Interface==-1 || Dev.Interface==Interface) &&
+ (DevID==0xffff || (Dev.DevId&0xffff) == DevID) &&
+ !(n--) ) return res->Devices+i;
+#undef Dev
+ }
+ return NULL;
+}
+
+static int __init
+residual_scan_pcibridge(PnP_TAG_PACKET * pkt, struct pci_dev *dev)
+{
+ int irq = -1;
+
+#define data pkt->L4_Pack.L4_Data.L4_PPCPack.PPCData
+ if (dev->bus->number == data[16]) {
+ int i, size;
+
+ size = 3 + ld_le16((u_short *) (&pkt->L4_Pack.Count0));
+ for (i = 20; i < size - 4; i += 12) {
+ unsigned char pin;
+ int line_irq;
+
+ if (dev->devfn != data[i + 1])
+ continue;
+
+ pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
+ if (pin) {
+ line_irq = ld_le16((unsigned short *)
+ (&data[i + 4 + 2 * (pin - 1)]));
+ irq = (line_irq == 0xffff) ? 0
+ : line_irq & 0x7fff;
+ } else
+ irq = 0;
+
+ break;
+ }
+ }
+#undef data
+
+ return irq;
+}
+
+int __init
+residual_pcidev_irq(struct pci_dev *dev)
+{
+ int i = 0;
+ int irq = -1;
+ PPC_DEVICE *bridge;
+
+ while ((bridge = residual_find_device
+ (-1, NULL, BridgeController, PCIBridge, -1, i++))) {
+
+ PnP_TAG_PACKET *pkt;
+ if (bridge->AllocatedOffset) {
+ pkt = PnP_find_large_vendor_packet(res->DevicePnPHeap +
+ bridge->AllocatedOffset, 3, 0);
+ if (!pkt)
+ continue;
+
+ irq = residual_scan_pcibridge(pkt, dev);
+ if (irq != -1)
+ break;
+ }
+ }
+
+ return (irq < 0) ? 0 : irq;
+}
+
+void __init residual_irq_mask(char *irq_edge_mask_lo, char *irq_edge_mask_hi)
+{
+ PPC_DEVICE *dev;
+ int i = 0;
+ unsigned short irq_mask = 0x000; /* default to edge */
+
+ while ((dev = residual_find_device(-1, NULL, -1, -1, -1, i++))) {
+ PnP_TAG_PACKET *pkt;
+ unsigned short mask;
+ int size;
+ int offset = dev->AllocatedOffset;
+
+ if (!offset)
+ continue;
+
+ pkt = PnP_find_packet(res->DevicePnPHeap + offset,
+ IRQFormat, 0);
+ if (!pkt)
+ continue;
+
+ size = tag_small_count(pkt->S1_Pack.Tag) + 1;
+ mask = ld_le16((unsigned short *)pkt->S4_Pack.IRQMask);
+ if (size > 3 && (pkt->S4_Pack.IRQInfo & 0x0c))
+ irq_mask |= mask;
+ }
+
+ *irq_edge_mask_lo = irq_mask & 0xff;
+ *irq_edge_mask_hi = irq_mask >> 8;
+}
+
+unsigned int __init residual_isapic_addr(void)
+{
+ PPC_DEVICE *isapic;
+ PnP_TAG_PACKET *pkt;
+ unsigned int addr;
+
+ isapic = residual_find_device(~0, NULL, SystemPeripheral,
+ ProgrammableInterruptController,
+ ISA_PIC, 0);
+ if (!isapic)
+ goto unknown;
+
+ pkt = PnP_find_large_vendor_packet(res->DevicePnPHeap +
+ isapic->AllocatedOffset, 9, 0);
+ if (!pkt)
+ goto unknown;
+
+#define p pkt->L4_Pack.L4_Data.L4_PPCPack
+ /* Must be 32-bit system address */
+ if (!((p.PPCData[0] == 3) && (p.PPCData[1] == 32)))
+ goto unknown;
+
+ /* It doesn't seem to work where length != 1 (what can I say? :-/ ) */
+ if (ld_le32((unsigned int *)(p.PPCData + 12)) != 1)
+ goto unknown;
+
+ addr = ld_le32((unsigned int *) (p.PPCData + 4));
+#undef p
+ return addr;
+unknown:
+ return 0;
+}
+
+PnP_TAG_PACKET *PnP_find_packet(unsigned char *p,
+ unsigned packet_tag,
+ int n)
+{
+ unsigned mask, masked_tag, size;
+ if(!p) return NULL;
+ if (tag_type(packet_tag)) mask=0xff; else mask=0xF8;
+ masked_tag = packet_tag&mask;
+ for(; *p != END_TAG; p+=size) {
+ if ((*p & mask) == masked_tag && !(n--))
+ return (PnP_TAG_PACKET *) p;
+ if (tag_type(*p))
+ size=ld_le16((unsigned short *)(p+1))+3;
+ else
+ size=tag_small_count(*p)+1;
+ }
+ return NULL; /* not found */
+}
+
+PnP_TAG_PACKET __init *PnP_find_small_vendor_packet(unsigned char *p,
+ unsigned packet_type,
+ int n)
+{
+ int next=0;
+ while (p) {
+ p = (unsigned char *) PnP_find_packet(p, 0x70, next);
+ if (p && p[1]==packet_type && !(n--))
+ return (PnP_TAG_PACKET *) p;
+ next = 1;
+ };
+ return NULL; /* not found */
+}
+
+PnP_TAG_PACKET __init *PnP_find_large_vendor_packet(unsigned char *p,
+ unsigned packet_type,
+ int n)
+{
+ int next=0;
+ while (p) {
+ p = (unsigned char *) PnP_find_packet(p, 0x84, next);
+ if (p && p[3]==packet_type && !(n--))
+ return (PnP_TAG_PACKET *) p;
+ next = 1;
+ };
+ return NULL; /* not found */
+}
+
+#ifdef CONFIG_PROC_PREPRESIDUAL
+static int proc_prep_residual_read(char * buf, char ** start, off_t off,
+ int count, int *eof, void *data)
+{
+ int n;
+
+ n = res->ResidualLength - off;
+ if (n < 0) {
+ *eof = 1;
+ n = 0;
+ }
+ else {
+ if (n > count)
+ n = count;
+ else
+ *eof = 1;
+
+ memcpy(buf, (char *)res + off, n);
+ *start = buf;
+ }
+
+ return n;
+}
+
+int __init
+proc_prep_residual_init(void)
+{
+ if (have_residual_data)
+ create_proc_read_entry("residual", S_IRUGO, NULL,
+ proc_prep_residual_read, NULL);
+ return 0;
+}
+
+__initcall(proc_prep_residual_init);
+#endif
diff --git a/arch/ppc/platforms/rpx8260.h b/arch/ppc/platforms/rpx8260.h
new file mode 100644
index 0000000..843494a
--- /dev/null
+++ b/arch/ppc/platforms/rpx8260.h
@@ -0,0 +1,81 @@
+/*
+ * A collection of structures, addresses, and values associated with
+ * the Embedded Planet RPX6 (or RPX Super) MPC8260 board.
+ * Copied from the RPX-Classic and SBS8260 stuff.
+ *
+ * Copyright (c) 2001 Dan Malek <dan@embeddededge.com>
+ */
+#ifdef __KERNEL__
+#ifndef __ASM_PLATFORMS_RPX8260_H__
+#define __ASM_PLATFORMS_RPX8260_H__
+
+/* A Board Information structure that is given to a program when
+ * prom starts it up.
+ */
+typedef struct bd_info {
+ unsigned int bi_memstart; /* Memory start address */
+ unsigned int bi_memsize; /* Memory (end) size in bytes */
+ unsigned int bi_nvsize; /* NVRAM size in bytes (can be 0) */
+ unsigned int bi_intfreq; /* Internal Freq, in Hz */
+ unsigned int bi_busfreq; /* Bus Freq, in MHz */
+ unsigned int bi_cpmfreq; /* CPM Freq, in MHz */
+ unsigned int bi_brgfreq; /* BRG Freq, in MHz */
+ unsigned int bi_vco; /* VCO Out from PLL */
+ unsigned int bi_baudrate; /* Default console baud rate */
+ unsigned int bi_immr; /* IMMR when called from boot rom */
+ unsigned char bi_enetaddr[6];
+} bd_t;
+
+extern bd_t m8xx_board_info;
+
+/* Memory map is configured by the PROM startup.
+ * We just map a few things we need. The CSR is actually 4 byte-wide
+ * registers that can be accessed as 8-, 16-, or 32-bit values.
+ */
+#define CPM_MAP_ADDR ((uint)0xf0000000)
+#define RPX_CSR_ADDR ((uint)0xfa000000)
+#define RPX_CSR_SIZE ((uint)(512 * 1024))
+#define RPX_NVRTC_ADDR ((uint)0xfa080000)
+#define RPX_NVRTC_SIZE ((uint)(512 * 1024))
+
+/* The RPX6 has 16, byte wide control/status registers.
+ * Not all are used (yet).
+ */
+extern volatile u_char *rpx6_csr_addr;
+
+/* Things of interest in the CSR.
+*/
+#define BCSR0_ID_MASK ((u_char)0xf0) /* Read only */
+#define BCSR0_SWITCH_MASK ((u_char)0x0f) /* Read only */
+#define BCSR1_XCVR_SMC1 ((u_char)0x80)
+#define BCSR1_XCVR_SMC2 ((u_char)0x40)
+#define BCSR2_FLASH_WENABLE ((u_char)0x20)
+#define BCSR2_NVRAM_ENABLE ((u_char)0x10)
+#define BCSR2_ALT_IRQ2 ((u_char)0x08)
+#define BCSR2_ALT_IRQ3 ((u_char)0x04)
+#define BCSR2_PRST ((u_char)0x02) /* Force reset */
+#define BCSR2_ENPRST ((u_char)0x01) /* Enable POR */
+#define BCSR3_MODCLK_MASK ((u_char)0xe0)
+#define BCSR3_ENCLKHDR ((u_char)0x10)
+#define BCSR3_LED5 ((u_char)0x04) /* 0 == on */
+#define BCSR3_LED6 ((u_char)0x02) /* 0 == on */
+#define BCSR3_LED7 ((u_char)0x01) /* 0 == on */
+#define BCSR4_EN_PHY ((u_char)0x80) /* Enable PHY */
+#define BCSR4_EN_MII ((u_char)0x40) /* Enable PHY */
+#define BCSR4_MII_READ ((u_char)0x04)
+#define BCSR4_MII_MDC ((u_char)0x02)
+#define BCSR4_MII_MDIO ((u_char)0x01)
+#define BCSR13_FETH_IRQMASK ((u_char)0xf0)
+#define BCSR15_FETH_IRQ ((u_char)0x20)
+
+#define PHY_INTERRUPT SIU_INT_IRQ7
+
+/* For our show_cpuinfo hooks. */
+#define CPUINFO_VENDOR "Embedded Planet"
+#define CPUINFO_MACHINE "EP8260 PowerPC"
+
+/* Warm reset vector. */
+#define BOOTROM_RESTART_ADDR ((uint)0xfff00104)
+
+#endif /* __ASM_PLATFORMS_RPX8260_H__ */
+#endif /* __KERNEL__ */
diff --git a/arch/ppc/platforms/rpxclassic.h b/arch/ppc/platforms/rpxclassic.h
new file mode 100644
index 0000000..6daa109
--- /dev/null
+++ b/arch/ppc/platforms/rpxclassic.h
@@ -0,0 +1,119 @@
+/*
+ * A collection of structures, addresses, and values associated with
+ * the RPCG RPX-Classic board. Copied from the RPX-Lite stuff.
+ *
+ * Copyright (c) 1998 Dan Malek (dmalek@jlc.net)
+ */
+#ifdef __KERNEL__
+#ifndef __MACH_RPX_DEFS
+#define __MACH_RPX_DEFS
+
+#include <linux/config.h>
+
+#ifndef __ASSEMBLY__
+/* A Board Information structure that is given to a program when
+ * prom starts it up.
+ */
+typedef struct bd_info {
+ unsigned int bi_memstart; /* Memory start address */
+ unsigned int bi_memsize; /* Memory (end) size in bytes */
+ unsigned int bi_intfreq; /* Internal Freq, in Hz */
+ unsigned int bi_busfreq; /* Bus Freq, in Hz */
+ unsigned char bi_enetaddr[6];
+ unsigned int bi_baudrate;
+} bd_t;
+
+extern bd_t m8xx_board_info;
+
+/* Memory map is configured by the PROM startup.
+ * We just map a few things we need. The CSR is actually 4 byte-wide
+ * registers that can be accessed as 8-, 16-, or 32-bit values.
+ */
+#define PCI_ISA_IO_ADDR ((unsigned)0x80000000)
+#define PCI_ISA_IO_SIZE ((uint)(512 * 1024 * 1024))
+#define PCI_ISA_MEM_ADDR ((unsigned)0xc0000000)
+#define PCI_ISA_MEM_SIZE ((uint)(512 * 1024 * 1024))
+#define RPX_CSR_ADDR ((uint)0xfa400000)
+#define RPX_CSR_SIZE ((uint)(4 * 1024))
+#define IMAP_ADDR ((uint)0xfa200000)
+#define IMAP_SIZE ((uint)(64 * 1024))
+#define PCI_CSR_ADDR ((uint)0x80000000)
+#define PCI_CSR_SIZE ((uint)(64 * 1024))
+#define PCMCIA_MEM_ADDR ((uint)0xe0000000)
+#define PCMCIA_MEM_SIZE ((uint)(64 * 1024))
+#define PCMCIA_IO_ADDR ((uint)0xe4000000)
+#define PCMCIA_IO_SIZE ((uint)(4 * 1024))
+#define PCMCIA_ATTRB_ADDR ((uint)0xe8000000)
+#define PCMCIA_ATTRB_SIZE ((uint)(4 * 1024))
+
+/* Things of interest in the CSR.
+*/
+#define BCSR0_ETHEN ((uint)0x80000000)
+#define BCSR0_ETHLPBK ((uint)0x40000000)
+#define BCSR0_COLTESTDIS ((uint)0x20000000)
+#define BCSR0_FULLDPLXDIS ((uint)0x10000000)
+#define BCSR0_ENFLSHSEL ((uint)0x04000000)
+#define BCSR0_FLASH_SEL ((uint)0x02000000)
+#define BCSR0_ENMONXCVR ((uint)0x01000000)
+
+#define BCSR0_PCMCIAVOLT ((uint)0x000f0000) /* CLLF */
+#define BCSR0_PCMCIA3VOLT ((uint)0x000a0000) /* CLLF */
+#define BCSR0_PCMCIA5VOLT ((uint)0x00060000) /* CLLF */
+
+#define BCSR1_IPB5SEL ((uint)0x00100000)
+#define BCSR1_PCVCTL4 ((uint)0x00080000)
+#define BCSR1_PCVCTL5 ((uint)0x00040000)
+#define BCSR1_PCVCTL6 ((uint)0x00020000)
+#define BCSR1_PCVCTL7 ((uint)0x00010000)
+
+#define BCSR2_EN232XCVR ((uint)0x00008000)
+#define BCSR2_QSPACESEL ((uint)0x00004000)
+#define BCSR2_FETHLEDMODE ((uint)0x00000800) /* CLLF */
+
+#if defined(CONFIG_HTDMSOUND)
+#include <platforms/rpxhiox.h>
+#endif
+
+/* define IO_BASE for pcmcia, CLLF only */
+#if !defined(CONFIG_PCI)
+#define _IO_BASE 0x80000000
+#define _IO_BASE_SIZE 0x1000
+
+/* for pcmcia sandisk */
+#ifdef CONFIG_IDE
+# define MAX_HWIFS 1
+#endif
+#endif
+
+/* Interrupt level assignments.
+*/
+#define FEC_INTERRUPT SIU_LEVEL1 /* FEC interrupt */
+
+
+/* CPM Ethernet through SCCx.
+ *
+ * Bits in parallel I/O port registers that have to be set/cleared
+ * to configure the pins for SCC1 use.
+ */
+#define PA_ENET_RXD ((ushort)0x0001)
+#define PA_ENET_TXD ((ushort)0x0002)
+#define PA_ENET_TCLK ((ushort)0x0200)
+#define PA_ENET_RCLK ((ushort)0x0800)
+#define PB_ENET_TENA ((uint)0x00001000)
+#define PC_ENET_CLSN ((ushort)0x0010)
+#define PC_ENET_RENA ((ushort)0x0020)
+
+/* Control bits in the SICR to route TCLK (CLK2) and RCLK (CLK4) to
+ * SCC1. Also, make sure GR1 (bit 24) and SC1 (bit 25) are zero.
+ */
+#define SICR_ENET_MASK ((uint)0x000000ff)
+#define SICR_ENET_CLKRT ((uint)0x0000003d)
+
+/* We don't use the 8259.
+*/
+
+#define NR_8259_INTS 0
+
+#endif /* !__ASSEMBLY__ */
+#endif /* __MACH_RPX_DEFS */
+#endif /* __KERNEL__ */
diff --git a/arch/ppc/platforms/rpxhiox.h b/arch/ppc/platforms/rpxhiox.h
new file mode 100644
index 0000000..c3fa5a6
--- /dev/null
+++ b/arch/ppc/platforms/rpxhiox.h
@@ -0,0 +1,41 @@
+/*
+ * The Embedded Planet HIOX expansion card definitions.
+ * There were a few different versions of these cards, but only
+ * the one that escaped real production is defined here.
+ *
+ * Copyright (c) 2000 Dan Malek (dmalek@jlc.net)
+ */
+#ifndef __MACH_RPX_HIOX_DEFS
+#define __MACH_RPX_HIOX_DEFS
+
+#define HIOX_CSR_ADDR ((uint)0xfac00000)
+#define HIOX_CSR_SIZE ((uint)(4 * 1024))
+#define HIOX_CSR0_ADDR HIOX_CSR_ADDR
+#define HIOX_CSR4_ADDR ((uint)0xfac00004)
+
+#define HIOX_CSR0_DEFAULT ((uint)0x380f3c00)
+#define HIOX_CSR0_ENSCC2 ((uint)0x80000000)
+#define HIOX_CSR0_ENSMC2 ((uint)0x04000000)
+#define HIOX_CSR0_ENVDOCLK ((uint)0x02000000)
+#define HIOX_CSR0_VDORST_HL ((uint)0x01000000)
+#define HIOX_CSR0_RS232SEL ((uint)0x0000c000)
+#define HIOX_CSR0_SCC3SEL ((uint)0x0000c000)
+#define HIOX_CSR0_SMC1SEL ((uint)0x00008000)
+#define HIOX_CSR0_SCC1SEL ((uint)0x00004000)
+#define HIOX_CSR0_ENTOUCH ((uint)0x00000080)
+#define HIOX_CSR0_PDOWN100 ((uint)0x00000060)
+#define HIOX_CSR0_PDOWN10 ((uint)0x00000040)
+#define HIOX_CSR0_PDOWN1 ((uint)0x00000020)
+#define HIOX_CSR0_TSELSPI ((uint)0x00000010)
+#define HIOX_CSR0_TIRQSTAT ((uint)0x00000008)
+#define HIOX_CSR4_DEFAULT ((uint)0x00000000)
+#define HIOX_CSR4_ENTIRQ2 ((uint)0x20000000)
+#define HIOX_CSR4_ENTIRQ3 ((uint)0x10000000)
+#define HIOX_CSR4_ENAUDIO ((uint)0x00000080)
+#define HIOX_CSR4_RSTAUDIO ((uint)0x00000040) /* 0 == reset */
+#define HIOX_CSR4_AUDCLKHI ((uint)0x00000020)
+#define HIOX_CSR4_AUDSPISEL ((uint)0x00000010)
+#define HIOX_CSR4_AUDIRQSTAT ((uint)0x00000008)
+#define HIOX_CSR4_AUDCLKSEL ((uint)0x00000007)
+
+#endif
diff --git a/arch/ppc/platforms/rpxlite.h b/arch/ppc/platforms/rpxlite.h
new file mode 100644
index 0000000..deee5bd
--- /dev/null
+++ b/arch/ppc/platforms/rpxlite.h
@@ -0,0 +1,96 @@
+/*
+ * A collection of structures, addresses, and values associated with
+ * the RPCG RPX-Lite board. Copied from the MBX stuff.
+ *
+ * Copyright (c) 1998 Dan Malek (dmalek@jlc.net)
+ */
+#ifdef __KERNEL__
+#ifndef __MACH_RPX_DEFS
+#define __MACH_RPX_DEFS
+
+#include <linux/config.h>
+
+#ifndef __ASSEMBLY__
+/* A Board Information structure that is given to a program when
+ * prom starts it up.
+ */
+typedef struct bd_info {
+ unsigned int bi_memstart; /* Memory start address */
+ unsigned int bi_memsize; /* Memory (end) size in bytes */
+ unsigned int bi_intfreq; /* Internal Freq, in Hz */
+ unsigned int bi_busfreq; /* Bus Freq, in Hz */
+ unsigned char bi_enetaddr[6];
+ unsigned int bi_baudrate;
+} bd_t;
+
+extern bd_t m8xx_board_info;
+
+/* Memory map is configured by the PROM startup.
+ * We just map a few things we need. The CSR is actually 4 byte-wide
+ * registers that can be accessed as 8-, 16-, or 32-bit values.
+ */
+#define RPX_CSR_ADDR ((uint)0xfa400000)
+#define RPX_CSR_SIZE ((uint)(4 * 1024))
+#define IMAP_ADDR ((uint)0xfa200000)
+#define IMAP_SIZE ((uint)(64 * 1024))
+#define PCMCIA_MEM_ADDR ((uint)0x04000000)
+#define PCMCIA_MEM_SIZE ((uint)(64 * 1024))
+#define PCMCIA_IO_ADDR ((uint)0x04400000)
+#define PCMCIA_IO_SIZE ((uint)(4 * 1024))
+
+/* Things of interest in the CSR.
+*/
+#define BCSR0_ETHEN ((uint)0x80000000)
+#define BCSR0_ETHLPBK ((uint)0x40000000)
+#define BCSR0_COLTESTDIS ((uint)0x20000000)
+#define BCSR0_FULLDPLXDIS ((uint)0x10000000)
+#define BCSR0_LEDOFF ((uint)0x08000000)
+#define BCSR0_USBDISABLE ((uint)0x04000000)
+#define BCSR0_USBHISPEED ((uint)0x02000000)
+#define BCSR0_USBPWREN ((uint)0x01000000)
+#define BCSR0_PCMCIAVOLT ((uint)0x000f0000)
+#define BCSR0_PCMCIA3VOLT ((uint)0x000a0000)
+#define BCSR0_PCMCIA5VOLT ((uint)0x00060000)
+
+#define BCSR1_IPB5SEL ((uint)0x00100000)
+#define BCSR1_PCVCTL4 ((uint)0x00080000)
+#define BCSR1_PCVCTL5 ((uint)0x00040000)
+#define BCSR1_PCVCTL6 ((uint)0x00020000)
+#define BCSR1_PCVCTL7 ((uint)0x00010000)
+
+#if defined(CONFIG_HTDMSOUND)
+#include <platforms/rpxhiox.h>
+#endif
+
+/* define IO_BASE for pcmcia */
+#define _IO_BASE 0x80000000
+#define _IO_BASE_SIZE 0x1000
+
+#ifdef CONFIG_IDE
+# define MAX_HWIFS 1
+#endif
+
+/* CPM Ethernet through SCCx.
+ *
+ * This ENET stuff is for the MPC850 with ethernet on SCC2. Some of
+ * this may be unique to the RPX-Lite configuration.
+ * Note TENA is on Port B.
+ */
+#define PA_ENET_RXD ((ushort)0x0004)
+#define PA_ENET_TXD ((ushort)0x0008)
+#define PA_ENET_TCLK ((ushort)0x0200)
+#define PA_ENET_RCLK ((ushort)0x0800)
+#define PB_ENET_TENA ((uint)0x00002000)
+#define PC_ENET_CLSN ((ushort)0x0040)
+#define PC_ENET_RENA ((ushort)0x0080)
+
+#define SICR_ENET_MASK ((uint)0x0000ff00)
+#define SICR_ENET_CLKRT ((uint)0x00003d00)
+
+/* We don't use the 8259.
+*/
+#define NR_8259_INTS 0
+
+#endif /* !__ASSEMBLY__ */
+#endif /* __MACH_RPX_DEFS */
+#endif /* __KERNEL__ */
diff --git a/arch/ppc/platforms/sandpoint.c b/arch/ppc/platforms/sandpoint.c
new file mode 100644
index 0000000..531bfa0
--- /dev/null
+++ b/arch/ppc/platforms/sandpoint.c
@@ -0,0 +1,742 @@
+/*
+ * arch/ppc/platforms/sandpoint_setup.c
+ *
+ * Board setup routines for the Motorola SPS Sandpoint Test Platform.
+ *
+ * Author: Mark A. Greer
+ * mgreer@mvista.com
+ *
+ * 2000-2003 (c) MontaVista Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+
+/*
+ * This file adds support for the Motorola SPS Sandpoint Test Platform.
+ * These boards have a PPMC slot for the processor so any combination
+ * of cpu and host bridge can be attached. This port is for an 8240 PPMC
+ * module from Motorola SPS and other closely related cpu/host bridge
+ * combinations (e.g., 750/755/7400 with MPC107 host bridge).
+ * The sandpoint itself has a Windbond 83c553 (PCI-ISA bridge, 2 DMA ctlrs, 2
+ * cascaded 8259 interrupt ctlrs, 8254 Timer/Counter, and an IDE ctlr), a
+ * National 87308 (RTC, 2 UARTs, Keyboard & mouse ctlrs, and a floppy ctlr),
+ * and 4 PCI slots (only 2 of which are usable; the other 2 are keyed for 3.3V
+ * but are really 5V).
+ *
+ * The firmware on the sandpoint is called DINK (not my acronym :). This port
+ * depends on DINK to do some basic initialization (e.g., initialize the memory
+ * ctlr) and to ensure that the processor is using MAP B (CHRP map).
+ *
+ * The switch settings for the Sandpoint board MUST be as follows:
+ * S3: down
+ * S4: up
+ * S5: up
+ * S6: down
+ *
+ * 'down' is in the direction from the PCI slots towards the PPMC slot;
+ * 'up' is in the direction from the PPMC slot towards the PCI slots.
+ * Be careful, the way the sandpoint board is installed in XT chasses will
+ * make the directions reversed.
+ *
+ * Since Motorola listened to our suggestions for improvement, we now have
+ * the Sandpoint X3 board. All of the PCI slots are available, it uses
+ * the serial interrupt interface (just a hardware thing we need to
+ * configure properly).
+ *
+ * Use the default X3 switch settings. The interrupts are then:
+ * EPIC Source
+ * 0 SIOINT (8259, active low)
+ * 1 PCI #1
+ * 2 PCI #2
+ * 3 PCI #3
+ * 4 PCI #4
+ * 7 Winbond INTC (IDE interrupt)
+ * 8 Winbond INTD (IDE interrupt)
+ *
+ *
+ * Motorola has finally released a version of DINK32 that correctly
+ * (seemingly) initalizes the memory controller correctly, regardless
+ * of the amount of memory in the system. Once a method of determining
+ * what version of DINK initializes the system for us, if applicable, is
+ * found, we can hopefully stop hardcoding 32MB of RAM.
+ */
+
+#include <linux/config.h>
+#include <linux/stddef.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/reboot.h>
+#include <linux/pci.h>
+#include <linux/kdev_t.h>
+#include <linux/major.h>
+#include <linux/initrd.h>
+#include <linux/console.h>
+#include <linux/delay.h>
+#include <linux/irq.h>
+#include <linux/ide.h>
+#include <linux/seq_file.h>
+#include <linux/root_dev.h>
+#include <linux/serial.h>
+#include <linux/tty.h> /* for linux/serial_core.h */
+#include <linux/serial_core.h>
+
+#include <asm/system.h>
+#include <asm/pgtable.h>
+#include <asm/page.h>
+#include <asm/time.h>
+#include <asm/dma.h>
+#include <asm/io.h>
+#include <asm/machdep.h>
+#include <asm/prom.h>
+#include <asm/smp.h>
+#include <asm/vga.h>
+#include <asm/open_pic.h>
+#include <asm/i8259.h>
+#include <asm/todc.h>
+#include <asm/bootinfo.h>
+#include <asm/mpc10x.h>
+#include <asm/pci-bridge.h>
+#include <asm/kgdb.h>
+
+#include "sandpoint.h"
+
+/* Set non-zero if an X2 Sandpoint detected. */
+static int sandpoint_is_x2;
+
+unsigned char __res[sizeof(bd_t)];
+
+static void sandpoint_halt(void);
+static void sandpoint_probe_type(void);
+
+/*
+ * Define all of the IRQ senses and polarities. Taken from the
+ * Sandpoint X3 User's manual.
+ */
+static u_char sandpoint_openpic_initsenses[] __initdata = {
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* 0: SIOINT */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* 2: PCI Slot 1 */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* 3: PCI Slot 2 */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* 4: PCI Slot 3 */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* 5: PCI Slot 4 */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* 8: IDE (INT C) */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE) /* 9: IDE (INT D) */
+};
+
+/*
+ * Motorola SPS Sandpoint interrupt routing.
+ */
+static inline int
+x3_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin)
+{
+ static char pci_irq_table[][4] =
+ /*
+ * PCI IDSEL/INTPIN->INTLINE
+ * A B C D
+ */
+ {
+ { 16, 0, 0, 0 }, /* IDSEL 11 - i8259 on Winbond */
+ { 0, 0, 0, 0 }, /* IDSEL 12 - unused */
+ { 18, 21, 20, 19 }, /* IDSEL 13 - PCI slot 1 */
+ { 19, 18, 21, 20 }, /* IDSEL 14 - PCI slot 2 */
+ { 20, 19, 18, 21 }, /* IDSEL 15 - PCI slot 3 */
+ { 21, 20, 19, 18 }, /* IDSEL 16 - PCI slot 4 */
+ };
+
+ const long min_idsel = 11, max_idsel = 16, irqs_per_slot = 4;
+ return PCI_IRQ_TABLE_LOOKUP;
+}
+
+static inline int
+x2_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin)
+{
+ static char pci_irq_table[][4] =
+ /*
+ * PCI IDSEL/INTPIN->INTLINE
+ * A B C D
+ */
+ {
+ { 18, 0, 0, 0 }, /* IDSEL 11 - i8259 on Windbond */
+ { 0, 0, 0, 0 }, /* IDSEL 12 - unused */
+ { 16, 17, 18, 19 }, /* IDSEL 13 - PCI slot 1 */
+ { 17, 18, 19, 16 }, /* IDSEL 14 - PCI slot 2 */
+ { 18, 19, 16, 17 }, /* IDSEL 15 - PCI slot 3 */
+ { 19, 16, 17, 18 }, /* IDSEL 16 - PCI slot 4 */
+ };
+
+ const long min_idsel = 11, max_idsel = 16, irqs_per_slot = 4;
+ return PCI_IRQ_TABLE_LOOKUP;
+}
+
+static void __init
+sandpoint_setup_winbond_83553(struct pci_controller *hose)
+{
+ int devfn;
+
+ /*
+ * Route IDE interrupts directly to the 8259's IRQ 14 & 15.
+ * We can't route the IDE interrupt to PCI INTC# or INTD# because those
+ * woule interfere with the PMC's INTC# and INTD# lines.
+ */
+ /*
+ * Winbond Fcn 0
+ */
+ devfn = PCI_DEVFN(11,0);
+
+ early_write_config_byte(hose,
+ 0,
+ devfn,
+ 0x43, /* IDE Interrupt Routing Control */
+ 0xef);
+ early_write_config_word(hose,
+ 0,
+ devfn,
+ 0x44, /* PCI Interrupt Routing Control */
+ 0x0000);
+
+ /* Want ISA memory cycles to be forwarded to PCI bus */
+ early_write_config_byte(hose,
+ 0,
+ devfn,
+ 0x48, /* ISA-to-PCI Addr Decoder Control */
+ 0xf0);
+
+ /* Enable Port 92. */
+ early_write_config_byte(hose,
+ 0,
+ devfn,
+ 0x4e, /* AT System Control Register */
+ 0x06);
+ /*
+ * Winbond Fcn 1
+ */
+ devfn = PCI_DEVFN(11,1);
+
+ /* Put IDE controller into native mode. */
+ early_write_config_byte(hose,
+ 0,
+ devfn,
+ 0x09, /* Programming interface Register */
+ 0x8f);
+
+ /* Init IRQ routing, enable both ports, disable fast 16 */
+ early_write_config_dword(hose,
+ 0,
+ devfn,
+ 0x40, /* IDE Control/Status Register */
+ 0x00ff0011);
+ return;
+}
+
+/* On the sandpoint X2, we must avoid sending configuration cycles to
+ * device #12 (IDSEL addr = AD12).
+ */
+static int
+x2_exclude_device(u_char bus, u_char devfn)
+{
+ if ((bus == 0) && (PCI_SLOT(devfn) == SANDPOINT_HOST_BRIDGE_IDSEL))
+ return PCIBIOS_DEVICE_NOT_FOUND;
+ else
+ return PCIBIOS_SUCCESSFUL;
+}
+
+static void __init
+sandpoint_find_bridges(void)
+{
+ struct pci_controller *hose;
+
+ hose = pcibios_alloc_controller();
+
+ if (!hose)
+ return;
+
+ hose->first_busno = 0;
+ hose->last_busno = 0xff;
+
+ if (mpc10x_bridge_init(hose,
+ MPC10X_MEM_MAP_B,
+ MPC10X_MEM_MAP_B,
+ MPC10X_MAPB_EUMB_BASE) == 0) {
+
+ /* Do early winbond init, then scan PCI bus */
+ sandpoint_setup_winbond_83553(hose);
+ hose->last_busno = pciauto_bus_scan(hose, hose->first_busno);
+
+ ppc_md.pcibios_fixup = NULL;
+ ppc_md.pcibios_fixup_bus = NULL;
+ ppc_md.pci_swizzle = common_swizzle;
+ if (sandpoint_is_x2) {
+ ppc_md.pci_map_irq = x2_map_irq;
+ ppc_md.pci_exclude_device = x2_exclude_device;
+ } else
+ ppc_md.pci_map_irq = x3_map_irq;
+ }
+ else {
+ if (ppc_md.progress)
+ ppc_md.progress("Bridge init failed", 0x100);
+ printk("Host bridge init failed\n");
+ }
+
+ return;
+}
+
+static void __init
+sandpoint_setup_arch(void)
+{
+ /* Probe for Sandpoint model */
+ sandpoint_probe_type();
+ if (sandpoint_is_x2)
+ epic_serial_mode = 0;
+
+ loops_per_jiffy = 100000000 / HZ;
+
+#ifdef CONFIG_BLK_DEV_INITRD
+ if (initrd_start)
+ ROOT_DEV = Root_RAM0;
+ else
+#endif
+#ifdef CONFIG_ROOT_NFS
+ ROOT_DEV = Root_NFS;
+#else
+ ROOT_DEV = Root_HDA1;
+#endif
+
+ /* Lookup PCI host bridges */
+ sandpoint_find_bridges();
+
+ printk(KERN_INFO "Motorola SPS Sandpoint Test Platform\n");
+ printk(KERN_INFO "Port by MontaVista Software, Inc. (source@mvista.com)\n");
+
+ /* DINK32 12.3 and below do not correctly enable any caches.
+ * We will do this now with good known values. Future versions
+ * of DINK32 are supposed to get this correct.
+ */
+ if (cpu_has_feature(CPU_FTR_SPEC7450))
+ /* 745x is different. We only want to pass along enable. */
+ _set_L2CR(L2CR_L2E);
+ else if (cpu_has_feature(CPU_FTR_L2CR))
+ /* All modules have 1MB of L2. We also assume that an
+ * L2 divisor of 3 will work.
+ */
+ _set_L2CR(L2CR_L2E | L2CR_L2SIZ_1MB | L2CR_L2CLK_DIV3
+ | L2CR_L2RAM_PIPE | L2CR_L2OH_1_0 | L2CR_L2DF);
+#if 0
+ /* Untested right now. */
+ if (cpu_has_feature(CPU_FTR_L3CR)) {
+ /* Magic value. */
+ _set_L3CR(0x8f032000);
+ }
+#endif
+}
+
+#define SANDPOINT_87308_CFG_ADDR 0x15c
+#define SANDPOINT_87308_CFG_DATA 0x15d
+
+#define SANDPOINT_87308_CFG_INB(addr, byte) { \
+ outb((addr), SANDPOINT_87308_CFG_ADDR); \
+ (byte) = inb(SANDPOINT_87308_CFG_DATA); \
+}
+
+#define SANDPOINT_87308_CFG_OUTB(addr, byte) { \
+ outb((addr), SANDPOINT_87308_CFG_ADDR); \
+ outb((byte), SANDPOINT_87308_CFG_DATA); \
+}
+
+#define SANDPOINT_87308_SELECT_DEV(dev_num) { \
+ SANDPOINT_87308_CFG_OUTB(0x07, (dev_num)); \
+}
+
+#define SANDPOINT_87308_DEV_ENABLE(dev_num) { \
+ SANDPOINT_87308_SELECT_DEV(dev_num); \
+ SANDPOINT_87308_CFG_OUTB(0x30, 0x01); \
+}
+
+/*
+ * To probe the Sandpoint type, we need to check for a connection between GPIO
+ * pins 6 and 7 on the NS87308 SuperIO.
+ */
+static void __init sandpoint_probe_type(void)
+{
+ u8 x;
+ /* First, ensure that the GPIO pins are enabled. */
+ SANDPOINT_87308_SELECT_DEV(0x07); /* Select GPIO logical device */
+ SANDPOINT_87308_CFG_OUTB(0x60, 0x07); /* Base address 0x700 */
+ SANDPOINT_87308_CFG_OUTB(0x61, 0x00);
+ SANDPOINT_87308_CFG_OUTB(0x30, 0x01); /* Enable */
+
+ /* Now, set pin 7 to output and pin 6 to input. */
+ outb((inb(0x701) | 0x80) & 0xbf, 0x701);
+ /* Set push-pull output */
+ outb(inb(0x702) | 0x80, 0x702);
+ /* Set pull-up on input */
+ outb(inb(0x703) | 0x40, 0x703);
+ /* Set output high and check */
+ x = inb(0x700);
+ outb(x | 0x80, 0x700);
+ x = inb(0x700);
+ sandpoint_is_x2 = ! (x & 0x40);
+ if (ppc_md.progress && sandpoint_is_x2)
+ ppc_md.progress("High output says X2", 0);
+ /* Set output low and check */
+ outb(x & 0x7f, 0x700);
+ sandpoint_is_x2 |= inb(0x700) & 0x40;
+ if (ppc_md.progress && sandpoint_is_x2)
+ ppc_md.progress("Low output says X2", 0);
+ if (ppc_md.progress && ! sandpoint_is_x2)
+ ppc_md.progress("Sandpoint is X3", 0);
+}
+
+/*
+ * Fix IDE interrupts.
+ */
+static int __init
+sandpoint_fix_winbond_83553(void)
+{
+ /* Make some 8259 interrupt level sensitive */
+ outb(0xe0, 0x4d0);
+ outb(0xde, 0x4d1);
+
+ return 0;
+}
+
+arch_initcall(sandpoint_fix_winbond_83553);
+
+/*
+ * Initialize the ISA devices on the Nat'l PC87308VUL SuperIO chip.
+ */
+static int __init
+sandpoint_setup_natl_87308(void)
+{
+ u_char reg;
+
+ /*
+ * Enable all the devices on the Super I/O chip.
+ */
+ SANDPOINT_87308_SELECT_DEV(0x00); /* Select kbd logical device */
+ SANDPOINT_87308_CFG_OUTB(0xf0, 0x00); /* Set KBC clock to 8 Mhz */
+ SANDPOINT_87308_DEV_ENABLE(0x00); /* Enable keyboard */
+ SANDPOINT_87308_DEV_ENABLE(0x01); /* Enable mouse */
+ SANDPOINT_87308_DEV_ENABLE(0x02); /* Enable rtc */
+ SANDPOINT_87308_DEV_ENABLE(0x03); /* Enable fdc (floppy) */
+ SANDPOINT_87308_DEV_ENABLE(0x04); /* Enable parallel */
+ SANDPOINT_87308_DEV_ENABLE(0x05); /* Enable UART 2 */
+ SANDPOINT_87308_CFG_OUTB(0xf0, 0x82); /* Enable bank select regs */
+ SANDPOINT_87308_DEV_ENABLE(0x06); /* Enable UART 1 */
+ SANDPOINT_87308_CFG_OUTB(0xf0, 0x82); /* Enable bank select regs */
+
+ /* Set up floppy in PS/2 mode */
+ outb(0x09, SIO_CONFIG_RA);
+ reg = inb(SIO_CONFIG_RD);
+ reg = (reg & 0x3F) | 0x40;
+ outb(reg, SIO_CONFIG_RD);
+ outb(reg, SIO_CONFIG_RD); /* Have to write twice to change! */
+
+ return 0;
+}
+
+arch_initcall(sandpoint_setup_natl_87308);
+
+static int __init
+sandpoint_request_io(void)
+{
+ request_region(0x00,0x20,"dma1");
+ request_region(0x20,0x20,"pic1");
+ request_region(0x40,0x20,"timer");
+ request_region(0x80,0x10,"dma page reg");
+ request_region(0xa0,0x20,"pic2");
+ request_region(0xc0,0x20,"dma2");
+
+ return 0;
+}
+
+arch_initcall(sandpoint_request_io);
+
+/*
+ * Interrupt setup and service. Interrrupts on the Sandpoint come
+ * from the four PCI slots plus the 8259 in the Winbond Super I/O (SIO).
+ * The 8259 is cascaded from EPIC IRQ0, IRQ1-4 map to PCI slots 1-4,
+ * IDE is on EPIC 7 and 8.
+ */
+static void __init
+sandpoint_init_IRQ(void)
+{
+ int i;
+
+ OpenPIC_InitSenses = sandpoint_openpic_initsenses;
+ OpenPIC_NumInitSenses = sizeof(sandpoint_openpic_initsenses);
+
+ mpc10x_set_openpic();
+ openpic_hookup_cascade(sandpoint_is_x2 ? 17 : NUM_8259_INTERRUPTS, "82c59 cascade",
+ i8259_irq);
+
+ /*
+ * openpic_init() has set up irq_desc[16-31] to be openpic
+ * interrupts. We need to set irq_desc[0-15] to be i8259
+ * interrupts.
+ */
+ for(i=0; i < NUM_8259_INTERRUPTS; i++)
+ irq_desc[i].handler = &i8259_pic;
+
+ /*
+ * The EPIC allows for a read in the range of 0xFEF00000 ->
+ * 0xFEFFFFFF to generate a PCI interrupt-acknowledge transaction.
+ */
+ i8259_init(0xfef00000);
+}
+
+static u32
+sandpoint_irq_canonicalize(u32 irq)
+{
+ if (irq == 2)
+ return 9;
+ else
+ return irq;
+}
+
+static unsigned long __init
+sandpoint_find_end_of_memory(void)
+{
+ bd_t *bp = (bd_t *)__res;
+
+ if (bp->bi_memsize)
+ return bp->bi_memsize;
+
+ /* DINK32 13.0 correctly initalizes things, so iff you use
+ * this you _should_ be able to change this instead of a
+ * hardcoded value. */
+#if 0
+ return mpc10x_get_mem_size(MPC10X_MEM_MAP_B);
+#else
+ return 32*1024*1024;
+#endif
+}
+
+static void __init
+sandpoint_map_io(void)
+{
+ io_block_mapping(0xfe000000, 0xfe000000, 0x02000000, _PAGE_IO);
+}
+
+static void
+sandpoint_restart(char *cmd)
+{
+ local_irq_disable();
+
+ /* Set exception prefix high - to the firmware */
+ _nmask_and_or_msr(0, MSR_IP);
+
+ /* Reset system via Port 92 */
+ outb(0x00, 0x92);
+ outb(0x01, 0x92);
+ for(;;); /* Spin until reset happens */
+}
+
+static void
+sandpoint_power_off(void)
+{
+ local_irq_disable();
+ for(;;); /* No way to shut power off with software */
+ /* NOTREACHED */
+}
+
+static void
+sandpoint_halt(void)
+{
+ sandpoint_power_off();
+ /* NOTREACHED */
+}
+
+static int
+sandpoint_show_cpuinfo(struct seq_file *m)
+{
+ seq_printf(m, "vendor\t\t: Motorola SPS\n");
+ seq_printf(m, "machine\t\t: Sandpoint\n");
+
+ return 0;
+}
+
+#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
+/*
+ * IDE support.
+ */
+static int sandpoint_ide_ports_known = 0;
+static unsigned long sandpoint_ide_regbase[MAX_HWIFS];
+static unsigned long sandpoint_ide_ctl_regbase[MAX_HWIFS];
+static unsigned long sandpoint_idedma_regbase;
+
+static void
+sandpoint_ide_probe(void)
+{
+ struct pci_dev *pdev = pci_get_device(PCI_VENDOR_ID_WINBOND,
+ PCI_DEVICE_ID_WINBOND_82C105, NULL);
+
+ if (pdev) {
+ sandpoint_ide_regbase[0]=pdev->resource[0].start;
+ sandpoint_ide_regbase[1]=pdev->resource[2].start;
+ sandpoint_ide_ctl_regbase[0]=pdev->resource[1].start;
+ sandpoint_ide_ctl_regbase[1]=pdev->resource[3].start;
+ sandpoint_idedma_regbase=pdev->resource[4].start;
+ pci_dev_put(pdev);
+ }
+
+ sandpoint_ide_ports_known = 1;
+}
+
+static int
+sandpoint_ide_default_irq(unsigned long base)
+{
+ if (sandpoint_ide_ports_known == 0)
+ sandpoint_ide_probe();
+
+ if (base == sandpoint_ide_regbase[0])
+ return SANDPOINT_IDE_INT0;
+ else if (base == sandpoint_ide_regbase[1])
+ return SANDPOINT_IDE_INT1;
+ else
+ return 0;
+}
+
+static unsigned long
+sandpoint_ide_default_io_base(int index)
+{
+ if (sandpoint_ide_ports_known == 0)
+ sandpoint_ide_probe();
+
+ return sandpoint_ide_regbase[index];
+}
+
+static void __init
+sandpoint_ide_init_hwif_ports(hw_regs_t *hw, unsigned long data_port,
+ unsigned long ctrl_port, int *irq)
+{
+ unsigned long reg = data_port;
+ uint alt_status_base;
+ int i;
+
+ for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) {
+ hw->io_ports[i] = reg++;
+ }
+
+ if (data_port == sandpoint_ide_regbase[0]) {
+ alt_status_base = sandpoint_ide_ctl_regbase[0] + 2;
+ hw->irq = 14;
+ }
+ else if (data_port == sandpoint_ide_regbase[1]) {
+ alt_status_base = sandpoint_ide_ctl_regbase[1] + 2;
+ hw->irq = 15;
+ }
+ else {
+ alt_status_base = 0;
+ hw->irq = 0;
+ }
+
+ if (ctrl_port) {
+ hw->io_ports[IDE_CONTROL_OFFSET] = ctrl_port;
+ } else {
+ hw->io_ports[IDE_CONTROL_OFFSET] = alt_status_base;
+ }
+
+ if (irq != NULL) {
+ *irq = hw->irq;
+ }
+}
+#endif
+
+/*
+ * Set BAT 3 to map 0xf8000000 to end of physical memory space 1-to-1.
+ */
+static __inline__ void
+sandpoint_set_bat(void)
+{
+ unsigned long bat3u, bat3l;
+
+ __asm__ __volatile__(
+ " lis %0,0xf800\n \
+ ori %1,%0,0x002a\n \
+ ori %0,%0,0x0ffe\n \
+ mtspr 0x21e,%0\n \
+ mtspr 0x21f,%1\n \
+ isync\n \
+ sync "
+ : "=r" (bat3u), "=r" (bat3l));
+}
+
+TODC_ALLOC();
+
+void __init
+platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
+ unsigned long r6, unsigned long r7)
+{
+ parse_bootinfo(find_bootinfo());
+
+ /* ASSUMPTION: If both r3 (bd_t pointer) and r6 (cmdline pointer)
+ * are non-zero, then we should use the board info from the bd_t
+ * structure and the cmdline pointed to by r6 instead of the
+ * information from birecs, if any. Otherwise, use the information
+ * from birecs as discovered by the preceeding call to
+ * parse_bootinfo(). This rule should work with both PPCBoot, which
+ * uses a bd_t board info structure, and the kernel boot wrapper,
+ * which uses birecs.
+ */
+ if (r3 && r6) {
+ /* copy board info structure */
+ memcpy( (void *)__res,(void *)(r3+KERNELBASE), sizeof(bd_t) );
+ /* copy command line */
+ *(char *)(r7+KERNELBASE) = 0;
+ strcpy(cmd_line, (char *)(r6+KERNELBASE));
+ }
+
+#ifdef CONFIG_BLK_DEV_INITRD
+ /* take care of initrd if we have one */
+ if (r4) {
+ initrd_start = r4 + KERNELBASE;
+ initrd_end = r5 + KERNELBASE;
+ }
+#endif /* CONFIG_BLK_DEV_INITRD */
+
+ /* Map in board regs, etc. */
+ sandpoint_set_bat();
+
+ isa_io_base = MPC10X_MAPB_ISA_IO_BASE;
+ isa_mem_base = MPC10X_MAPB_ISA_MEM_BASE;
+ pci_dram_offset = MPC10X_MAPB_DRAM_OFFSET;
+ ISA_DMA_THRESHOLD = 0x00ffffff;
+ DMA_MODE_READ = 0x44;
+ DMA_MODE_WRITE = 0x48;
+
+ ppc_md.setup_arch = sandpoint_setup_arch;
+ ppc_md.show_cpuinfo = sandpoint_show_cpuinfo;
+ ppc_md.irq_canonicalize = sandpoint_irq_canonicalize;
+ ppc_md.init_IRQ = sandpoint_init_IRQ;
+ ppc_md.get_irq = openpic_get_irq;
+
+ ppc_md.restart = sandpoint_restart;
+ ppc_md.power_off = sandpoint_power_off;
+ ppc_md.halt = sandpoint_halt;
+
+ ppc_md.find_end_of_memory = sandpoint_find_end_of_memory;
+ ppc_md.setup_io_mappings = sandpoint_map_io;
+
+ TODC_INIT(TODC_TYPE_PC97307, 0x70, 0x00, 0x71, 8);
+ ppc_md.time_init = todc_time_init;
+ ppc_md.set_rtc_time = todc_set_rtc_time;
+ ppc_md.get_rtc_time = todc_get_rtc_time;
+ ppc_md.calibrate_decr = todc_calibrate_decr;
+
+ ppc_md.nvram_read_val = todc_mc146818_read_val;
+ ppc_md.nvram_write_val = todc_mc146818_write_val;
+
+#ifdef CONFIG_KGDB
+ ppc_md.kgdb_map_scc = gen550_kgdb_map_scc;
+#endif
+#ifdef CONFIG_SERIAL_TEXT_DEBUG
+ ppc_md.progress = gen550_progress;
+#endif
+
+#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
+ ppc_ide_md.default_irq = sandpoint_ide_default_irq;
+ ppc_ide_md.default_io_base = sandpoint_ide_default_io_base;
+ ppc_ide_md.ide_init_hwif = sandpoint_ide_init_hwif_ports;
+#endif
+}
diff --git a/arch/ppc/platforms/sandpoint.h b/arch/ppc/platforms/sandpoint.h
new file mode 100644
index 0000000..f4e982c
--- /dev/null
+++ b/arch/ppc/platforms/sandpoint.h
@@ -0,0 +1,80 @@
+/*
+ * arch/ppc/platforms/sandpoint.h
+ *
+ * Definitions for Motorola SPS Sandpoint Test Platform
+ *
+ * Author: Mark A. Greer
+ * mgreer@mvista.com
+ *
+ * 2000-2003 (c) MontaVista, Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+
+/*
+ * Sandpoint uses the CHRP map (Map B).
+ */
+
+#ifndef __PPC_PLATFORMS_SANDPOINT_H
+#define __PPC_PLATFORMS_SANDPOINT_H
+
+#include <asm/ppcboot.h>
+
+#if 0
+/* The Sandpoint X3 allows the IDE interrupt to be directly connected
+ * from the Windbond (PCI INTC or INTD) to the serial EPIC. Someday
+ * we should try this, but it was easier to use the existing 83c553
+ * initialization than change it to route the different interrupts :-).
+ * -- Dan
+ */
+#define SANDPOINT_IDE_INT0 23 /* EPIC 7 */
+#define SANDPOINT_IDE_INT1 24 /* EPIC 8 */
+#else
+#define SANDPOINT_IDE_INT0 14 /* 8259 Test */
+#define SANDPOINT_IDE_INT1 15 /* 8259 Test */
+#endif
+
+/*
+ * The sandpoint boards have processor modules that either have an 8240 or
+ * an MPC107 host bridge on them. These bridges have an IDSEL line that allows
+ * them to respond to PCI transactions as if they were a normal PCI devices.
+ * However, the processor on the processor side of the bridge can not reach
+ * out onto the PCI bus and then select the bridge or bad things will happen
+ * (documented in the 8240 and 107 manuals).
+ * Because of this, we always skip the bridge PCI device when accessing the
+ * PCI bus. The PCI slot that the bridge occupies is defined by the macro
+ * below.
+ */
+#define SANDPOINT_HOST_BRIDGE_IDSEL 12
+
+/*
+ * Serial defines.
+ */
+#define SANDPOINT_SERIAL_0 0xfe0003f8
+#define SANDPOINT_SERIAL_1 0xfe0002f8
+
+#define RS_TABLE_SIZE 2
+
+/* Rate for the 1.8432 Mhz clock for the onboard serial chip */
+#define BASE_BAUD ( 1843200 / 16 )
+#define UART_CLK 1843200
+
+#ifdef CONFIG_SERIAL_DETECT_IRQ
+#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF|ASYNC_AUTO_IRQ)
+#else
+#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF)
+#endif
+
+#define STD_SERIAL_PORT_DFNS \
+ { 0, BASE_BAUD, SANDPOINT_SERIAL_0, 4, STD_COM_FLAGS, /* ttyS0 */ \
+ iomem_base: (u8 *)SANDPOINT_SERIAL_0, \
+ io_type: SERIAL_IO_MEM }, \
+ { 0, BASE_BAUD, SANDPOINT_SERIAL_1, 3, STD_COM_FLAGS, /* ttyS1 */ \
+ iomem_base: (u8 *)SANDPOINT_SERIAL_1, \
+ io_type: SERIAL_IO_MEM },
+
+#define SERIAL_PORT_DFNS \
+ STD_SERIAL_PORT_DFNS
+
+#endif /* __PPC_PLATFORMS_SANDPOINT_H */
diff --git a/arch/ppc/platforms/sbc82xx.c b/arch/ppc/platforms/sbc82xx.c
new file mode 100644
index 0000000..74c9ff7
--- /dev/null
+++ b/arch/ppc/platforms/sbc82xx.c
@@ -0,0 +1,259 @@
+/*
+ * arch/ppc/platforms/sbc82xx.c
+ *
+ * SBC82XX platform support
+ *
+ * Author: Guy Streeter <streeter@redhat.com>
+ *
+ * Derived from: est8260_setup.c by Allen Curtis, ONZ
+ *
+ * Copyright 2004 Red Hat, Inc.
+ *
+ * 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.
+ */
+
+#include <linux/config.h>
+#include <linux/stddef.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+
+#include <asm/mpc8260.h>
+#include <asm/machdep.h>
+#include <asm/io.h>
+#include <asm/todc.h>
+#include <asm/immap_cpm2.h>
+#include <asm/pci.h>
+
+static void (*callback_init_IRQ)(void);
+
+extern unsigned char __res[sizeof(bd_t)];
+
+extern void (*late_time_init)(void);
+
+#ifdef CONFIG_GEN_RTC
+TODC_ALLOC();
+
+/*
+ * Timer init happens before mem_init but after paging init, so we cannot
+ * directly use ioremap() at that time.
+ * late_time_init() is call after paging init.
+ */
+
+static void sbc82xx_time_init(void)
+{
+ volatile memctl_cpm2_t *mc = &cpm2_immr->im_memctl;
+
+ /* Set up CS11 for RTC chip */
+ mc->memc_br11=0;
+ mc->memc_or11=0xffff0836;
+ mc->memc_br11=SBC82xx_TODC_NVRAM_ADDR | 0x0801;
+
+ TODC_INIT(TODC_TYPE_MK48T59, 0, 0, SBC82xx_TODC_NVRAM_ADDR, 0);
+
+ todc_info->nvram_data =
+ (unsigned int)ioremap(todc_info->nvram_data, 0x2000);
+ BUG_ON(!todc_info->nvram_data);
+ ppc_md.get_rtc_time = todc_get_rtc_time;
+ ppc_md.set_rtc_time = todc_set_rtc_time;
+ ppc_md.nvram_read_val = todc_direct_read_val;
+ ppc_md.nvram_write_val = todc_direct_write_val;
+ todc_time_init();
+}
+#endif /* CONFIG_GEN_RTC */
+
+static volatile char *sbc82xx_i8259_map;
+static char sbc82xx_i8259_mask = 0xff;
+static DEFINE_SPINLOCK(sbc82xx_i8259_lock);
+
+static void sbc82xx_i8259_mask_and_ack_irq(unsigned int irq_nr)
+{
+ unsigned long flags;
+
+ irq_nr -= NR_SIU_INTS;
+
+ spin_lock_irqsave(&sbc82xx_i8259_lock, flags);
+ sbc82xx_i8259_mask |= 1 << irq_nr;
+ (void) sbc82xx_i8259_map[1]; /* Dummy read */
+ sbc82xx_i8259_map[1] = sbc82xx_i8259_mask;
+ sbc82xx_i8259_map[0] = 0x20; /* OCW2: Non-specific EOI */
+ spin_unlock_irqrestore(&sbc82xx_i8259_lock, flags);
+}
+
+static void sbc82xx_i8259_mask_irq(unsigned int irq_nr)
+{
+ unsigned long flags;
+
+ irq_nr -= NR_SIU_INTS;
+
+ spin_lock_irqsave(&sbc82xx_i8259_lock, flags);
+ sbc82xx_i8259_mask |= 1 << irq_nr;
+ sbc82xx_i8259_map[1] = sbc82xx_i8259_mask;
+ spin_unlock_irqrestore(&sbc82xx_i8259_lock, flags);
+}
+
+static void sbc82xx_i8259_unmask_irq(unsigned int irq_nr)
+{
+ unsigned long flags;
+
+ irq_nr -= NR_SIU_INTS;
+
+ spin_lock_irqsave(&sbc82xx_i8259_lock, flags);
+ sbc82xx_i8259_mask &= ~(1 << irq_nr);
+ sbc82xx_i8259_map[1] = sbc82xx_i8259_mask;
+ spin_unlock_irqrestore(&sbc82xx_i8259_lock, flags);
+}
+
+static void sbc82xx_i8259_end_irq(unsigned int irq)
+{
+ if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))
+ && irq_desc[irq].action)
+ sbc82xx_i8259_unmask_irq(irq);
+}
+
+
+struct hw_interrupt_type sbc82xx_i8259_ic = {
+ .typename = " i8259 ",
+ .enable = sbc82xx_i8259_unmask_irq,
+ .disable = sbc82xx_i8259_mask_irq,
+ .ack = sbc82xx_i8259_mask_and_ack_irq,
+ .end = sbc82xx_i8259_end_irq,
+};
+
+static irqreturn_t sbc82xx_i8259_demux(int irq, void *dev_id, struct pt_regs *regs)
+{
+ spin_lock(&sbc82xx_i8259_lock);
+
+ sbc82xx_i8259_map[0] = 0x0c; /* OCW3: Read IR register on RD# pulse */
+ irq = sbc82xx_i8259_map[0] & 7; /* Read IRR */
+
+ if (irq == 7) {
+ /* Possible spurious interrupt */
+ int isr;
+ sbc82xx_i8259_map[0] = 0x0b; /* OCW3: Read IS register on RD# pulse */
+ isr = sbc82xx_i8259_map[0]; /* Read ISR */
+
+ if (!(isr & 0x80)) {
+ printk(KERN_INFO "Spurious i8259 interrupt\n");
+ return IRQ_HANDLED;
+ }
+ }
+ __do_IRQ(NR_SIU_INTS + irq, regs);
+ return IRQ_HANDLED;
+}
+
+static struct irqaction sbc82xx_i8259_irqaction = {
+ .handler = sbc82xx_i8259_demux,
+ .flags = SA_INTERRUPT,
+ .mask = CPU_MASK_NONE,
+ .name = "i8259 demux",
+};
+
+void __init sbc82xx_init_IRQ(void)
+{
+ volatile memctl_cpm2_t *mc = &cpm2_immr->im_memctl;
+ volatile intctl_cpm2_t *ic = &cpm2_immr->im_intctl;
+ int i;
+
+ callback_init_IRQ();
+
+ /* u-boot doesn't always set the board up correctly */
+ mc->memc_br5 = 0;
+ mc->memc_or5 = 0xfff00856;
+ mc->memc_br5 = 0x22000801;
+
+ sbc82xx_i8259_map = ioremap(0x22008000, 2);
+ if (!sbc82xx_i8259_map) {
+ printk(KERN_CRIT "Mapping i8259 interrupt controller failed\n");
+ return;
+ }
+
+ /* Set up the interrupt handlers for the i8259 IRQs */
+ for (i = NR_SIU_INTS; i < NR_SIU_INTS + 8; i++) {
+ irq_desc[i].handler = &sbc82xx_i8259_ic;
+ irq_desc[i].status |= IRQ_LEVEL;
+ }
+
+ /* make IRQ6 level sensitive */
+ ic->ic_siexr &= ~(1 << (14 - (SIU_INT_IRQ6 - SIU_INT_IRQ1)));
+ irq_desc[SIU_INT_IRQ6].status |= IRQ_LEVEL;
+
+ /* Initialise the i8259 */
+ sbc82xx_i8259_map[0] = 0x1b; /* ICW1: Level, no cascade, ICW4 */
+ sbc82xx_i8259_map[1] = 0x00; /* ICW2: vector base */
+ /* No ICW3 (no cascade) */
+ sbc82xx_i8259_map[1] = 0x01; /* ICW4: 8086 mode, normal EOI */
+
+ sbc82xx_i8259_map[0] = 0x0b; /* OCW3: Read IS register on RD# pulse */
+
+ sbc82xx_i8259_map[1] = sbc82xx_i8259_mask; /* Set interrupt mask */
+
+ /* Request cascade IRQ */
+ if (setup_irq(SIU_INT_IRQ6, &sbc82xx_i8259_irqaction)) {
+ printk("Installation of i8259 IRQ demultiplexer failed.\n");
+ }
+}
+
+static int sbc82xx_pci_map_irq(struct pci_dev *dev, unsigned char idsel,
+ unsigned char pin)
+{
+ static char pci_irq_table[][4] = {
+ /*
+ * PCI IDSEL/INTPIN->INTLINE
+ * A B C D
+ */
+ { SBC82xx_PIRQA, SBC82xx_PIRQB, SBC82xx_PIRQC, SBC82xx_PIRQD }, /* IDSEL 16 - PMC slot */
+ { SBC82xx_PC_IRQA, SBC82xx_PC_IRQB, -1, -1 }, /* IDSEL 17 - CardBus */
+ { SBC82xx_PIRQA, SBC82xx_PIRQB, SBC82xx_PIRQC, SBC82xx_PIRQD }, /* IDSEL 18 - PCI-X bridge */
+ };
+
+ const long min_idsel = 16, max_idsel = 18, irqs_per_slot = 4;
+
+ return PCI_IRQ_TABLE_LOOKUP;
+}
+
+static void __devinit quirk_sbc8260_cardbus(struct pci_dev *pdev)
+{
+ uint32_t ctrl;
+
+ if (pdev->bus->number != 0 || pdev->devfn != PCI_DEVFN(17, 0))
+ return;
+
+ printk(KERN_INFO "Setting up CardBus controller\n");
+
+ /* Set P2CCLK bit in System Control Register */
+ pci_read_config_dword(pdev, 0x80, &ctrl);
+ ctrl |= (1<<27);
+ pci_write_config_dword(pdev, 0x80, ctrl);
+
+ /* Set MFUNC up for PCI IRQ routing via INTA and INTB, and LEDs. */
+ pci_write_config_dword(pdev, 0x8c, 0x00c01d22);
+
+}
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_1420, quirk_sbc8260_cardbus);
+
+void __init
+m82xx_board_init(void)
+{
+ /* u-boot may be using one of the FCC Ethernet devices.
+ Use the MAC address to the SCC. */
+ __res[offsetof(bd_t, bi_enetaddr[5])] &= ~3;
+
+ /* Anything special for this platform */
+ callback_init_IRQ = ppc_md.init_IRQ;
+
+ ppc_md.init_IRQ = sbc82xx_init_IRQ;
+ ppc_md.pci_map_irq = sbc82xx_pci_map_irq;
+#ifdef CONFIG_GEN_RTC
+ ppc_md.time_init = NULL;
+ ppc_md.get_rtc_time = NULL;
+ ppc_md.set_rtc_time = NULL;
+ ppc_md.nvram_read_val = NULL;
+ ppc_md.nvram_write_val = NULL;
+ late_time_init = sbc82xx_time_init;
+#endif /* CONFIG_GEN_RTC */
+}
diff --git a/arch/ppc/platforms/sbc82xx.h b/arch/ppc/platforms/sbc82xx.h
new file mode 100644
index 0000000..e4042d4
--- /dev/null
+++ b/arch/ppc/platforms/sbc82xx.h
@@ -0,0 +1,36 @@
+/* Board information for the SBCPowerQUICCII, which should be generic for
+ * all 8260 boards. The IMMR is now given to us so the hard define
+ * will soon be removed. All of the clock values are computed from
+ * the configuration SCMR and the Power-On-Reset word.
+ */
+
+#ifndef __PPC_SBC82xx_H__
+#define __PPC_SBC82xx_H__
+
+#include <asm/ppcboot.h>
+
+#define CPM_MAP_ADDR 0xf0000000
+
+#define SBC82xx_TODC_NVRAM_ADDR 0xd0000000
+
+#define SBC82xx_MACADDR_NVRAM_FCC1 0x220000c9 /* JP6B */
+#define SBC82xx_MACADDR_NVRAM_SCC1 0x220000cf /* JP6A */
+#define SBC82xx_MACADDR_NVRAM_FCC2 0x220000d5 /* JP7A */
+#define SBC82xx_MACADDR_NVRAM_FCC3 0x220000db /* JP7B */
+
+/* For our show_cpuinfo hooks. */
+#define CPUINFO_VENDOR "Wind River"
+#define CPUINFO_MACHINE "SBC PowerQUICC II"
+
+#define BOOTROM_RESTART_ADDR ((uint)0x40000104)
+
+#define SBC82xx_PC_IRQA (NR_SIU_INTS+0)
+#define SBC82xx_PC_IRQB (NR_SIU_INTS+1)
+#define SBC82xx_MPC185_IRQ (NR_SIU_INTS+2)
+#define SBC82xx_ATM_IRQ (NR_SIU_INTS+3)
+#define SBC82xx_PIRQA (NR_SIU_INTS+4)
+#define SBC82xx_PIRQB (NR_SIU_INTS+5)
+#define SBC82xx_PIRQC (NR_SIU_INTS+6)
+#define SBC82xx_PIRQD (NR_SIU_INTS+7)
+
+#endif /* __PPC_SBC82xx_H__ */
diff --git a/arch/ppc/platforms/sbs8260.h b/arch/ppc/platforms/sbs8260.h
new file mode 100644
index 0000000..d51427a
--- /dev/null
+++ b/arch/ppc/platforms/sbs8260.h
@@ -0,0 +1,28 @@
+#ifndef __ASSEMBLY__
+/* Board information for various SBS 8260 cards, which should be generic for
+ * all 8260 boards. The IMMR is now given to us so the hard define
+ * will soon be removed. All of the clock values are computed from
+ * the configuration SCMR and the Power-On-Reset word.
+ */
+
+#define CPM_MAP_ADDR ((uint)0xfe000000)
+
+
+/* A Board Information structure that is given to a program when
+ * prom starts it up.
+ */
+typedef struct bd_info {
+ unsigned int bi_memstart; /* Memory start address */
+ unsigned int bi_memsize; /* Memory (end) size in bytes */
+ unsigned int bi_intfreq; /* Internal Freq, in Hz */
+ unsigned int bi_busfreq; /* Bus Freq, in MHz */
+ unsigned int bi_cpmfreq; /* CPM Freq, in MHz */
+ unsigned int bi_brgfreq; /* BRG Freq, in MHz */
+ unsigned int bi_vco; /* VCO Out from PLL */
+ unsigned int bi_baudrate; /* Default console baud rate */
+ unsigned int bi_immr; /* IMMR when called from boot rom */
+ unsigned char bi_enetaddr[6];
+} bd_t;
+
+extern bd_t m8xx_board_info;
+#endif /* !__ASSEMBLY__ */
diff --git a/arch/ppc/platforms/spd8xx.h b/arch/ppc/platforms/spd8xx.h
new file mode 100644
index 0000000..ed48d14
--- /dev/null
+++ b/arch/ppc/platforms/spd8xx.h
@@ -0,0 +1,92 @@
+/*
+ * Speech Design SPD8xxTS board specific definitions
+ *
+ * Copyright (c) 2000,2001 Wolfgang Denk (wd@denx.de)
+ */
+
+#ifdef __KERNEL__
+#ifndef __ASM_SPD8XX_H__
+#define __ASM_SPD8XX_H__
+
+#include <linux/config.h>
+
+#include <asm/ppcboot.h>
+
+#ifndef __ASSEMBLY__
+#define SPD_IMMR_BASE 0xFFF00000 /* phys. addr of IMMR */
+#define SPD_IMAP_SIZE (64 * 1024) /* size of mapped area */
+
+#define IMAP_ADDR SPD_IMMR_BASE /* physical base address of IMMR area */
+#define IMAP_SIZE SPD_IMAP_SIZE /* mapped size of IMMR area */
+
+#define PCMCIA_MEM_ADDR ((uint)0xFE100000)
+#define PCMCIA_MEM_SIZE ((uint)(64 * 1024))
+
+#define IDE0_INTERRUPT 10 /* = IRQ5 */
+#define IDE1_INTERRUPT 12 /* = IRQ6 */
+#define CPM_INTERRUPT 13 /* = SIU_LEVEL6 (was: SIU_LEVEL2) */
+
+/* override the default number of IDE hardware interfaces */
+#define MAX_HWIFS 2
+
+/*
+ * Definitions for IDE0 Interface
+ */
+#define IDE0_BASE_OFFSET 0x0000 /* Offset in PCMCIA memory */
+#define IDE0_DATA_REG_OFFSET 0x0000
+#define IDE0_ERROR_REG_OFFSET 0x0081
+#define IDE0_NSECTOR_REG_OFFSET 0x0082
+#define IDE0_SECTOR_REG_OFFSET 0x0083
+#define IDE0_LCYL_REG_OFFSET 0x0084
+#define IDE0_HCYL_REG_OFFSET 0x0085
+#define IDE0_SELECT_REG_OFFSET 0x0086
+#define IDE0_STATUS_REG_OFFSET 0x0087
+#define IDE0_CONTROL_REG_OFFSET 0x0106
+#define IDE0_IRQ_REG_OFFSET 0x000A /* not used */
+
+/*
+ * Definitions for IDE1 Interface
+ */
+#define IDE1_BASE_OFFSET 0x0C00 /* Offset in PCMCIA memory */
+#define IDE1_DATA_REG_OFFSET 0x0000
+#define IDE1_ERROR_REG_OFFSET 0x0081
+#define IDE1_NSECTOR_REG_OFFSET 0x0082
+#define IDE1_SECTOR_REG_OFFSET 0x0083
+#define IDE1_LCYL_REG_OFFSET 0x0084
+#define IDE1_HCYL_REG_OFFSET 0x0085
+#define IDE1_SELECT_REG_OFFSET 0x0086
+#define IDE1_STATUS_REG_OFFSET 0x0087
+#define IDE1_CONTROL_REG_OFFSET 0x0106
+#define IDE1_IRQ_REG_OFFSET 0x000A /* not used */
+
+/* CPM Ethernet through SCCx.
+ *
+ * Bits in parallel I/O port registers that have to be set/cleared
+ * to configure the pins for SCC2 use.
+ */
+#define PA_ENET_MDC ((ushort)0x0001) /* PA 15 !!! */
+#define PA_ENET_MDIO ((ushort)0x0002) /* PA 14 !!! */
+#define PA_ENET_RXD ((ushort)0x0004) /* PA 13 */
+#define PA_ENET_TXD ((ushort)0x0008) /* PA 12 */
+#define PA_ENET_RCLK ((ushort)0x0200) /* PA 6 */
+#define PA_ENET_TCLK ((ushort)0x0400) /* PA 5 */
+
+#define PB_ENET_TENA ((uint)0x00002000) /* PB 18 */
+
+#define PC_ENET_CLSN ((ushort)0x0040) /* PC 9 */
+#define PC_ENET_RENA ((ushort)0x0080) /* PC 8 */
+#define PC_ENET_RESET ((ushort)0x0100) /* PC 7 !!! */
+
+/* Control bits in the SICR to route TCLK (CLK3) and RCLK (CLK2) to
+ * SCC2. Also, make sure GR2 (bit 16) and SC2 (bit 17) are zero.
+ */
+#define SICR_ENET_MASK ((uint)0x0000ff00)
+#define SICR_ENET_CLKRT ((uint)0x00002E00)
+
+/* We don't use the 8259.
+*/
+#define NR_8259_INTS 0
+
+#endif /* !__ASSEMBLY__ */
+#endif /* __ASM_SPD8XX_H__ */
+#endif /* __KERNEL__ */
diff --git a/arch/ppc/platforms/spruce.c b/arch/ppc/platforms/spruce.c
new file mode 100644
index 0000000..5ad70d3
--- /dev/null
+++ b/arch/ppc/platforms/spruce.c
@@ -0,0 +1,325 @@
+/*
+ * arch/ppc/platforms/spruce.c
+ *
+ * Board and PCI setup routines for IBM Spruce
+ *
+ * Author: MontaVista Software <source@mvista.com>
+ *
+ * 2000-2004 (c) MontaVista, Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+
+#include <linux/config.h>
+#include <linux/stddef.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/reboot.h>
+#include <linux/pci.h>
+#include <linux/kdev_t.h>
+#include <linux/types.h>
+#include <linux/major.h>
+#include <linux/initrd.h>
+#include <linux/console.h>
+#include <linux/delay.h>
+#include <linux/seq_file.h>
+#include <linux/ide.h>
+#include <linux/root_dev.h>
+#include <linux/serial.h>
+#include <linux/tty.h>
+#include <linux/serial_core.h>
+
+#include <asm/system.h>
+#include <asm/pgtable.h>
+#include <asm/page.h>
+#include <asm/dma.h>
+#include <asm/io.h>
+#include <asm/machdep.h>
+#include <asm/time.h>
+#include <asm/todc.h>
+#include <asm/bootinfo.h>
+#include <asm/kgdb.h>
+
+#include <syslib/cpc700.h>
+
+#include "spruce.h"
+
+static inline int
+spruce_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin)
+{
+ static char pci_irq_table[][4] =
+ /*
+ * PCI IDSEL/INTPIN->INTLINE
+ * A B C D
+ */
+ {
+ {23, 24, 25, 26}, /* IDSEL 1 - PCI slot 3 */
+ {24, 25, 26, 23}, /* IDSEL 2 - PCI slot 2 */
+ {25, 26, 23, 24}, /* IDSEL 3 - PCI slot 1 */
+ {26, 23, 24, 25}, /* IDSEL 4 - PCI slot 0 */
+ };
+
+ const long min_idsel = 1, max_idsel = 4, irqs_per_slot = 4;
+ return PCI_IRQ_TABLE_LOOKUP;
+}
+
+static void __init
+spruce_setup_hose(void)
+{
+ struct pci_controller *hose;
+
+ /* Setup hose */
+ hose = pcibios_alloc_controller();
+ if (!hose)
+ return;
+
+ hose->first_busno = 0;
+ hose->last_busno = 0xff;
+
+ pci_init_resource(&hose->io_resource,
+ SPRUCE_PCI_LOWER_IO,
+ SPRUCE_PCI_UPPER_IO,
+ IORESOURCE_IO,
+ "PCI host bridge");
+
+ pci_init_resource(&hose->mem_resources[0],
+ SPRUCE_PCI_LOWER_MEM,
+ SPRUCE_PCI_UPPER_MEM,
+ IORESOURCE_MEM,
+ "PCI host bridge");
+
+ hose->io_space.start = SPRUCE_PCI_LOWER_IO;
+ hose->io_space.end = SPRUCE_PCI_UPPER_IO;
+ hose->mem_space.start = SPRUCE_PCI_LOWER_MEM;
+ hose->mem_space.end = SPRUCE_PCI_UPPER_MEM;
+ hose->io_base_virt = (void *)SPRUCE_ISA_IO_BASE;
+
+ setup_indirect_pci(hose,
+ SPRUCE_PCI_CONFIG_ADDR,
+ SPRUCE_PCI_CONFIG_DATA);
+
+ hose->last_busno = pciauto_bus_scan(hose, hose->first_busno);
+
+ ppc_md.pci_swizzle = common_swizzle;
+ ppc_md.pci_map_irq = spruce_map_irq;
+}
+
+/*
+ * CPC700 PIC interrupt programming table
+ *
+ * First entry is the sensitivity (level/edge), second is the polarity.
+ */
+unsigned int cpc700_irq_assigns[32][2] = {
+ { 1, 1 }, /* IRQ 0: ECC Correctable Error - rising edge */
+ { 1, 1 }, /* IRQ 1: PCI Write Mem Range - rising edge */
+ { 0, 1 }, /* IRQ 2: PCI Write Command Reg - active high */
+ { 0, 1 }, /* IRQ 3: UART 0 - active high */
+ { 0, 1 }, /* IRQ 4: UART 1 - active high */
+ { 0, 1 }, /* IRQ 5: ICC 0 - active high */
+ { 0, 1 }, /* IRQ 6: ICC 1 - active high */
+ { 0, 1 }, /* IRQ 7: GPT Compare 0 - active high */
+ { 0, 1 }, /* IRQ 8: GPT Compare 1 - active high */
+ { 0, 1 }, /* IRQ 9: GPT Compare 2 - active high */
+ { 0, 1 }, /* IRQ 10: GPT Compare 3 - active high */
+ { 0, 1 }, /* IRQ 11: GPT Compare 4 - active high */
+ { 0, 1 }, /* IRQ 12: GPT Capture 0 - active high */
+ { 0, 1 }, /* IRQ 13: GPT Capture 1 - active high */
+ { 0, 1 }, /* IRQ 14: GPT Capture 2 - active high */
+ { 0, 1 }, /* IRQ 15: GPT Capture 3 - active high */
+ { 0, 1 }, /* IRQ 16: GPT Capture 4 - active high */
+ { 0, 0 }, /* IRQ 17: Reserved */
+ { 0, 0 }, /* IRQ 18: Reserved */
+ { 0, 0 }, /* IRQ 19: Reserved */
+ { 0, 1 }, /* IRQ 20: FPGA EXT_IRQ0 - active high */
+ { 1, 1 }, /* IRQ 21: Mouse - rising edge */
+ { 1, 1 }, /* IRQ 22: Keyboard - rising edge */
+ { 0, 0 }, /* IRQ 23: PCI Slot 3 - active low */
+ { 0, 0 }, /* IRQ 24: PCI Slot 2 - active low */
+ { 0, 0 }, /* IRQ 25: PCI Slot 1 - active low */
+ { 0, 0 }, /* IRQ 26: PCI Slot 0 - active low */
+};
+
+static void __init
+spruce_calibrate_decr(void)
+{
+ int freq, divisor = 4;
+
+ /* determine processor bus speed */
+ freq = SPRUCE_BUS_SPEED;
+ tb_ticks_per_jiffy = freq / HZ / divisor;
+ tb_to_us = mulhwu_scale_factor(freq/divisor, 1000000);
+}
+
+static int
+spruce_show_cpuinfo(struct seq_file *m)
+{
+ seq_printf(m, "vendor\t\t: IBM\n");
+ seq_printf(m, "machine\t\t: Spruce\n");
+
+ return 0;
+}
+
+static void __init
+spruce_early_serial_map(void)
+{
+ u32 uart_clk;
+ struct uart_port serial_req;
+
+ if (SPRUCE_UARTCLK_IS_33M(readb(SPRUCE_FPGA_REG_A)))
+ uart_clk = SPRUCE_BAUD_33M * 16;
+ else
+ uart_clk = SPRUCE_BAUD_30M * 16;
+
+ /* Setup serial port access */
+ memset(&serial_req, 0, sizeof(serial_req));
+ serial_req.uartclk = uart_clk;
+ serial_req.irq = UART0_INT;
+ serial_req.flags = ASYNC_BOOT_AUTOCONF;
+ serial_req.iotype = SERIAL_IO_MEM;
+ serial_req.membase = (u_char *)UART0_IO_BASE;
+ serial_req.regshift = 0;
+
+#if defined(CONFIG_KGDB) || defined(CONFIG_SERIAL_TEXT_DEBUG)
+ gen550_init(0, &serial_req);
+#endif
+#ifdef CONFIG_SERIAL_8250
+ if (early_serial_setup(&serial_req) != 0)
+ printk("Early serial init of port 0 failed\n");
+#endif
+
+ /* Assume early_serial_setup() doesn't modify serial_req */
+ serial_req.line = 1;
+ serial_req.irq = UART1_INT;
+ serial_req.membase = (u_char *)UART1_IO_BASE;
+
+#if defined(CONFIG_KGDB) || defined(CONFIG_SERIAL_TEXT_DEBUG)
+ gen550_init(1, &serial_req);
+#endif
+#ifdef CONFIG_SERIAL_8250
+ if (early_serial_setup(&serial_req) != 0)
+ printk("Early serial init of port 1 failed\n");
+#endif
+}
+
+TODC_ALLOC();
+
+static void __init
+spruce_setup_arch(void)
+{
+ /* Setup TODC access */
+ TODC_INIT(TODC_TYPE_DS1643, 0, 0, SPRUCE_RTC_BASE_ADDR, 8);
+
+ /* init to some ~sane value until calibrate_delay() runs */
+ loops_per_jiffy = 50000000 / HZ;
+
+ /* Setup PCI host bridge */
+ spruce_setup_hose();
+
+#ifdef CONFIG_BLK_DEV_INITRD
+ if (initrd_start)
+ ROOT_DEV = Root_RAM0;
+ else
+#endif
+#ifdef CONFIG_ROOT_NFS
+ ROOT_DEV = Root_NFS;
+#else
+ ROOT_DEV = Root_SDA1;
+#endif
+
+ /* Identify the system */
+ printk(KERN_INFO "System Identification: IBM Spruce\n");
+ printk(KERN_INFO "Port by MontaVista Software, Inc. (source@mvista.com)\n");
+}
+
+static void
+spruce_restart(char *cmd)
+{
+ local_irq_disable();
+
+ /* SRR0 has system reset vector, SRR1 has default MSR value */
+ /* rfi restores MSR from SRR1 and sets the PC to the SRR0 value */
+ __asm__ __volatile__
+ ("\n\
+ lis 3,0xfff0 \n\
+ ori 3,3,0x0100 \n\
+ mtspr 26,3 \n\
+ li 3,0 \n\
+ mtspr 27,3 \n\
+ rfi \n\
+ ");
+ for(;;);
+}
+
+static void
+spruce_power_off(void)
+{
+ for(;;);
+}
+
+static void
+spruce_halt(void)
+{
+ spruce_restart(NULL);
+}
+
+static void __init
+spruce_map_io(void)
+{
+ io_block_mapping(SPRUCE_PCI_IO_BASE, SPRUCE_PCI_PHY_IO_BASE,
+ 0x08000000, _PAGE_IO);
+}
+
+/*
+ * Set BAT 3 to map 0xf8000000 to end of physical memory space 1-to-1.
+ */
+static __inline__ void
+spruce_set_bat(void)
+{
+ mb();
+ mtspr(SPRN_DBAT1U, 0xf8000ffe);
+ mtspr(SPRN_DBAT1L, 0xf800002a);
+ mb();
+}
+
+void __init
+platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
+ unsigned long r6, unsigned long r7)
+{
+ parse_bootinfo(find_bootinfo());
+
+ /* Map in board regs, etc. */
+ spruce_set_bat();
+
+ isa_io_base = SPRUCE_ISA_IO_BASE;
+ pci_dram_offset = SPRUCE_PCI_SYS_MEM_BASE;
+
+ ppc_md.setup_arch = spruce_setup_arch;
+ ppc_md.show_cpuinfo = spruce_show_cpuinfo;
+ ppc_md.init_IRQ = cpc700_init_IRQ;
+ ppc_md.get_irq = cpc700_get_irq;
+
+ ppc_md.setup_io_mappings = spruce_map_io;
+
+ ppc_md.restart = spruce_restart;
+ ppc_md.power_off = spruce_power_off;
+ ppc_md.halt = spruce_halt;
+
+ ppc_md.time_init = todc_time_init;
+ ppc_md.set_rtc_time = todc_set_rtc_time;
+ ppc_md.get_rtc_time = todc_get_rtc_time;
+ ppc_md.calibrate_decr = spruce_calibrate_decr;
+
+ ppc_md.nvram_read_val = todc_direct_read_val;
+ ppc_md.nvram_write_val = todc_direct_write_val;
+
+ spruce_early_serial_map();
+
+#ifdef CONFIG_SERIAL_TEXT_DEBUG
+ ppc_md.progress = gen550_progress;
+#endif /* CONFIG_SERIAL_TEXT_DEBUG */
+#ifdef CONFIG_KGDB
+ ppc_md.kgdb_map_scc = gen550_kgdb_map_scc;
+#endif
+}
diff --git a/arch/ppc/platforms/spruce.h b/arch/ppc/platforms/spruce.h
new file mode 100644
index 0000000..a31ff7e
--- /dev/null
+++ b/arch/ppc/platforms/spruce.h
@@ -0,0 +1,71 @@
+/*
+ * include/asm-ppc/platforms/spruce.h
+ *
+ * Definitions for IBM Spruce reference board support
+ *
+ * Authors: Matt Porter and Johnnie Peters
+ * mporter@mvista.com
+ * jpeters@mvista.com
+ *
+ * 2001 (c) MontaVista, Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+
+#ifdef __KERNEL__
+#ifndef __ASM_SPRUCE_H__
+#define __ASM_SPRUCE_H__
+
+#define SPRUCE_PCI_CONFIG_ADDR 0xfec00000
+#define SPRUCE_PCI_CONFIG_DATA 0xfec00004
+
+#define SPRUCE_PCI_PHY_IO_BASE 0xf8000000
+#define SPRUCE_PCI_IO_BASE SPRUCE_PCI_PHY_IO_BASE
+
+#define SPRUCE_PCI_SYS_MEM_BASE 0x00000000
+
+#define SPRUCE_PCI_LOWER_MEM 0x80000000
+#define SPRUCE_PCI_UPPER_MEM 0x9fffffff
+#define SPRUCE_PCI_LOWER_IO 0x00000000
+#define SPRUCE_PCI_UPPER_IO 0x03ffffff
+
+#define SPRUCE_ISA_IO_BASE SPRUCE_PCI_IO_BASE
+
+#define SPRUCE_MEM_SIZE 0x04000000
+#define SPRUCE_BUS_SPEED 66666667
+
+#define SPRUCE_NVRAM_BASE_ADDR 0xff800000
+#define SPRUCE_RTC_BASE_ADDR SPRUCE_NVRAM_BASE_ADDR
+
+/*
+ * Serial port defines
+ */
+#define SPRUCE_FPGA_REG_A 0xff820000
+#define SPRUCE_UARTCLK_33M 0x02
+#define SPRUCE_UARTCLK_IS_33M(reg) (reg & SPRUCE_UARTCLK_33M)
+
+#define UART0_IO_BASE 0xff600300
+#define UART1_IO_BASE 0xff600400
+
+#define RS_TABLE_SIZE 2
+
+#define SPRUCE_BAUD_33M (33000000/64)
+#define SPRUCE_BAUD_30M (30000000/64)
+#define BASE_BAUD SPRUCE_BAUD_33M
+
+#define UART0_INT 3
+#define UART1_INT 4
+
+#define STD_UART_OP(num) \
+ { 0, BASE_BAUD, 0, UART##num##_INT, \
+ ASYNC_BOOT_AUTOCONF, \
+ iomem_base: (unsigned char *) UART##num##_IO_BASE, \
+ io_type: SERIAL_IO_MEM},
+
+#define SERIAL_PORT_DFNS \
+ STD_UART_OP(0) \
+ STD_UART_OP(1)
+
+#endif /* __ASM_SPRUCE_H__ */
+#endif /* __KERNEL__ */
diff --git a/arch/ppc/platforms/tqm8260.h b/arch/ppc/platforms/tqm8260.h
new file mode 100644
index 0000000..c7a78a6
--- /dev/null
+++ b/arch/ppc/platforms/tqm8260.h
@@ -0,0 +1,23 @@
+/*
+ * TQM8260 board specific definitions
+ *
+ * Copyright (c) 2001 Wolfgang Denk (wd@denx.de)
+ */
+
+#ifndef __TQM8260_PLATFORM
+#define __TQM8260_PLATFORM
+
+#include <linux/config.h>
+
+#include <asm/ppcboot.h>
+
+#define CPM_MAP_ADDR ((uint)0xFFF00000)
+#define PHY_INTERRUPT 25
+
+/* For our show_cpuinfo hooks. */
+#define CPUINFO_VENDOR "IN2 Systems"
+#define CPUINFO_MACHINE "TQM8260 PowerPC"
+
+#define BOOTROM_RESTART_ADDR ((uint)0x40000104)
+
+#endif /* __TQM8260_PLATFORM */
diff --git a/arch/ppc/platforms/tqm8260_setup.c b/arch/ppc/platforms/tqm8260_setup.c
new file mode 100644
index 0000000..a8880bf
--- /dev/null
+++ b/arch/ppc/platforms/tqm8260_setup.c
@@ -0,0 +1,44 @@
+/*
+ * arch/ppc/platforms/tqm8260_setup.c
+ *
+ * TQM8260 platform support
+ *
+ * Author: Allen Curtis <acurtis@onz.com>
+ * Derived from: m8260_setup.c by Dan Malek, MVista
+ *
+ * Copyright 2002 Ones and Zeros, Inc.
+ *
+ * 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.
+ */
+
+#include <linux/init.h>
+
+#include <asm/immap_cpm2.h>
+#include <asm/mpc8260.h>
+#include <asm/machdep.h>
+
+static int
+tqm8260_set_rtc_time(unsigned long time)
+{
+ ((cpm2_map_t *)CPM_MAP_ADDR)->im_sit.sit_tmcnt = time;
+ ((cpm2_map_t *)CPM_MAP_ADDR)->im_sit.sit_tmcntsc = 0x3;
+
+ return(0);
+}
+
+static unsigned long
+tqm8260_get_rtc_time(void)
+{
+ return ((cpm2_map_t *)CPM_MAP_ADDR)->im_sit.sit_tmcnt;
+}
+
+void __init
+m82xx_board_init(void)
+{
+ /* Anything special for this platform */
+ ppc_md.set_rtc_time = tqm8260_set_rtc_time;
+ ppc_md.get_rtc_time = tqm8260_get_rtc_time;
+}
diff --git a/arch/ppc/platforms/tqm8xx.h b/arch/ppc/platforms/tqm8xx.h
new file mode 100644
index 0000000..2150dc8
--- /dev/null
+++ b/arch/ppc/platforms/tqm8xx.h
@@ -0,0 +1,179 @@
+/*
+ * TQM8xx(L) board specific definitions
+ *
+ * Copyright (c) 1999-2002 Wolfgang Denk (wd@denx.de)
+ */
+
+#ifdef __KERNEL__
+#ifndef __MACH_TQM8xx_H
+#define __MACH_TQM8xx_H
+
+#include <linux/config.h>
+
+#include <asm/ppcboot.h>
+
+#ifndef __ASSEMBLY__
+#define TQM_IMMR_BASE 0xFFF00000 /* phys. addr of IMMR */
+#define TQM_IMAP_SIZE (64 * 1024) /* size of mapped area */
+
+#define IMAP_ADDR TQM_IMMR_BASE /* physical base address of IMMR area */
+#define IMAP_SIZE TQM_IMAP_SIZE /* mapped size of IMMR area */
+
+/*-----------------------------------------------------------------------
+ * PCMCIA stuff
+ *-----------------------------------------------------------------------
+ *
+ */
+#define PCMCIA_MEM_SIZE ( 64 << 20 )
+
+#ifndef CONFIG_KUP4K
+# define MAX_HWIFS 1 /* overwrite default in include/asm-ppc/ide.h */
+
+#else /* CONFIG_KUP4K */
+
+# define MAX_HWIFS 2 /* overwrite default in include/asm-ppc/ide.h */
+# ifndef __ASSEMBLY__
+# include <asm/8xx_immap.h>
+static __inline__ void ide_led(int on)
+{
+ volatile immap_t *immap = (immap_t *)IMAP_ADDR;
+
+ if (on) {
+ immap->im_ioport.iop_padat &= ~0x80;
+ } else {
+ immap->im_ioport.iop_padat |= 0x80;
+ }
+}
+# endif /* __ASSEMBLY__ */
+# define IDE_LED(x) ide_led((x))
+#endif /* CONFIG_KUP4K */
+
+/*
+ * Definitions for IDE0 Interface
+ */
+#define IDE0_BASE_OFFSET 0
+#define IDE0_DATA_REG_OFFSET (PCMCIA_MEM_SIZE + 0x320)
+#define IDE0_ERROR_REG_OFFSET (2 * PCMCIA_MEM_SIZE + 0x320 + 1)
+#define IDE0_NSECTOR_REG_OFFSET (2 * PCMCIA_MEM_SIZE + 0x320 + 2)
+#define IDE0_SECTOR_REG_OFFSET (2 * PCMCIA_MEM_SIZE + 0x320 + 3)
+#define IDE0_LCYL_REG_OFFSET (2 * PCMCIA_MEM_SIZE + 0x320 + 4)
+#define IDE0_HCYL_REG_OFFSET (2 * PCMCIA_MEM_SIZE + 0x320 + 5)
+#define IDE0_SELECT_REG_OFFSET (2 * PCMCIA_MEM_SIZE + 0x320 + 6)
+#define IDE0_STATUS_REG_OFFSET (2 * PCMCIA_MEM_SIZE + 0x320 + 7)
+#define IDE0_CONTROL_REG_OFFSET 0x0106
+#define IDE0_IRQ_REG_OFFSET 0x000A /* not used */
+
+/* define IO_BASE for PCMCIA */
+#define _IO_BASE 0x80000000
+#define _IO_BASE_SIZE (64<<10)
+
+#define FEC_INTERRUPT 9 /* = SIU_LEVEL4 */
+#define PHY_INTERRUPT 12 /* = IRQ6 */
+#define IDE0_INTERRUPT 13
+
+#ifdef CONFIG_IDE
+#endif
+
+/*-----------------------------------------------------------------------
+ * CPM Ethernet through SCCx.
+ *-----------------------------------------------------------------------
+ *
+ */
+
+/*** TQM823L, TQM850L ***********************************************/
+
+#if defined(CONFIG_TQM823L) || defined(CONFIG_TQM850L)
+/* Bits in parallel I/O port registers that have to be set/cleared
+ * to configure the pins for SCC1 use.
+ */
+#define PA_ENET_RXD ((ushort)0x0004) /* PA 13 */
+#define PA_ENET_TXD ((ushort)0x0008) /* PA 12 */
+#define PA_ENET_RCLK ((ushort)0x0100) /* PA 7 */
+#define PA_ENET_TCLK ((ushort)0x0400) /* PA 5 */
+
+#define PB_ENET_TENA ((uint)0x00002000) /* PB 18 */
+
+#define PC_ENET_CLSN ((ushort)0x0040) /* PC 9 */
+#define PC_ENET_RENA ((ushort)0x0080) /* PC 8 */
+
+/* Control bits in the SICR to route TCLK (CLK3) and RCLK (CLK1) to
+ * SCC2. Also, make sure GR2 (bit 16) and SC2 (bit 17) are zero.
+ */
+#define SICR_ENET_MASK ((uint)0x0000ff00)
+#define SICR_ENET_CLKRT ((uint)0x00002600)
+#endif /* CONFIG_TQM823L, CONFIG_TQM850L */
+
+/*** TQM860L ********************************************************/
+
+#ifdef CONFIG_TQM860L
+/* Bits in parallel I/O port registers that have to be set/cleared
+ * to configure the pins for SCC1 use.
+ */
+#define PA_ENET_RXD ((ushort)0x0001) /* PA 15 */
+#define PA_ENET_TXD ((ushort)0x0002) /* PA 14 */
+#define PA_ENET_RCLK ((ushort)0x0100) /* PA 7 */
+#define PA_ENET_TCLK ((ushort)0x0400) /* PA 5 */
+
+#define PC_ENET_TENA ((ushort)0x0001) /* PC 15 */
+#define PC_ENET_CLSN ((ushort)0x0010) /* PC 11 */
+#define PC_ENET_RENA ((ushort)0x0020) /* PC 10 */
+
+/* Control bits in the SICR to route TCLK (CLK3) and RCLK (CLK1) to
+ * SCC1. Also, make sure GR1 (bit 24) and SC1 (bit 25) are zero.
+ */
+#define SICR_ENET_MASK ((uint)0x000000ff)
+#define SICR_ENET_CLKRT ((uint)0x00000026)
+#endif /* CONFIG_TQM860L */
+
+/*** FPS850L *********************************************************/
+
+#ifdef CONFIG_FPS850L
+/* Bits in parallel I/O port registers that have to be set/cleared
+ * to configure the pins for SCC1 use.
+ */
+#define PA_ENET_RXD ((ushort)0x0004) /* PA 13 */
+#define PA_ENET_TXD ((ushort)0x0008) /* PA 12 */
+#define PA_ENET_RCLK ((ushort)0x0100) /* PA 7 */
+#define PA_ENET_TCLK ((ushort)0x0400) /* PA 5 */
+
+#define PC_ENET_TENA ((ushort)0x0002) /* PC 14 */
+#define PC_ENET_CLSN ((ushort)0x0040) /* PC 9 */
+#define PC_ENET_RENA ((ushort)0x0080) /* PC 8 */
+
+/* Control bits in the SICR to route TCLK (CLK2) and RCLK (CLK4) to
+ * SCC2. Also, make sure GR2 (bit 16) and SC2 (bit 17) are zero.
+ */
+#define SICR_ENET_MASK ((uint)0x0000ff00)
+#define SICR_ENET_CLKRT ((uint)0x00002600)
+#endif /* CONFIG_FPS850L */
+
+/*** SM850 *********************************************************/
+
+/* The SM850 Service Module uses SCC2 for IrDA and SCC3 for Ethernet */
+
+#ifdef CONFIG_SM850
+#define PB_ENET_RXD ((uint)0x00000004) /* PB 29 */
+#define PB_ENET_TXD ((uint)0x00000002) /* PB 30 */
+#define PA_ENET_RCLK ((ushort)0x0100) /* PA 7 */
+#define PA_ENET_TCLK ((ushort)0x0400) /* PA 5 */
+
+#define PC_ENET_LBK ((ushort)0x0008) /* PC 12 */
+#define PC_ENET_TENA ((ushort)0x0004) /* PC 13 */
+
+#define PC_ENET_RENA ((ushort)0x0800) /* PC 4 */
+#define PC_ENET_CLSN ((ushort)0x0400) /* PC 5 */
+
+/* Control bits in the SICR to route TCLK (CLK3) and RCLK (CLK1) to
+ * SCC3. Also, make sure GR3 (bit 8) and SC3 (bit 9) are zero.
+ */
+#define SICR_ENET_MASK ((uint)0x00FF0000)
+#define SICR_ENET_CLKRT ((uint)0x00260000)
+#endif /* CONFIG_SM850 */
+
+/* We don't use the 8259.
+*/
+#define NR_8259_INTS 0
+
+#endif /* !__ASSEMBLY__ */
+#endif /* __MACH_TQM8xx_H */
+#endif /* __KERNEL__ */
diff --git a/arch/ppc/syslib/Makefile b/arch/ppc/syslib/Makefile
new file mode 100644
index 0000000..dd418ea
--- /dev/null
+++ b/arch/ppc/syslib/Makefile
@@ -0,0 +1,115 @@
+#
+# Makefile for the linux kernel.
+#
+
+CFLAGS_prom_init.o += -fPIC
+CFLAGS_btext.o += -fPIC
+
+wdt-mpc8xx-$(CONFIG_8xx_WDT) += m8xx_wdt.o
+
+obj-$(CONFIG_PPCBUG_NVRAM) += prep_nvram.o
+obj-$(CONFIG_PPC_OCP) += ocp.o
+obj-$(CONFIG_IBM_OCP) += ibm_ocp.o
+obj-$(CONFIG_44x) += ibm44x_common.o
+obj-$(CONFIG_440GP) += ibm440gp_common.o
+obj-$(CONFIG_440GX) += ibm440gx_common.o
+obj-$(CONFIG_440SP) += ibm440gx_common.o ibm440sp_common.o
+ifeq ($(CONFIG_4xx),y)
+ifeq ($(CONFIG_VIRTEX_II_PRO),y)
+obj-$(CONFIG_40x) += xilinx_pic.o
+else
+ifeq ($(CONFIG_403),y)
+obj-$(CONFIG_40x) += ppc403_pic.o
+else
+obj-$(CONFIG_40x) += ppc4xx_pic.o
+endif
+endif
+obj-$(CONFIG_44x) += ppc4xx_pic.o
+obj-$(CONFIG_40x) += ppc4xx_setup.o
+obj-$(CONFIG_GEN_RTC) += todc_time.o
+obj-$(CONFIG_PPC4xx_DMA) += ppc4xx_dma.o
+obj-$(CONFIG_PPC4xx_EDMA) += ppc4xx_sgdma.o
+ifeq ($(CONFIG_40x),y)
+obj-$(CONFIG_PCI) += indirect_pci.o pci_auto.o ppc405_pci.o
+endif
+endif
+obj-$(CONFIG_8xx) += m8xx_setup.o ppc8xx_pic.o $(wdt-mpc8xx-y)
+ifeq ($(CONFIG_8xx),y)
+obj-$(CONFIG_PCI) += qspan_pci.o i8259.o
+endif
+obj-$(CONFIG_PPC_OF) += prom_init.o prom.o of_device.o
+obj-$(CONFIG_PPC_PMAC) += open_pic.o indirect_pci.o
+obj-$(CONFIG_POWER4) += open_pic2.o
+obj-$(CONFIG_PPC_CHRP) += open_pic.o indirect_pci.o i8259.o
+obj-$(CONFIG_PPC_PREP) += open_pic.o indirect_pci.o i8259.o todc_time.o
+obj-$(CONFIG_ADIR) += i8259.o indirect_pci.o pci_auto.o \
+ todc_time.o
+obj-$(CONFIG_CPCI690) += todc_time.o pci_auto.o
+obj-$(CONFIG_EBONY) += indirect_pci.o pci_auto.o todc_time.o
+obj-$(CONFIG_EV64260) += todc_time.o pci_auto.o
+obj-$(CONFIG_CHESTNUT) += mv64360_pic.o pci_auto.o
+obj-$(CONFIG_GEMINI) += open_pic.o indirect_pci.o
+obj-$(CONFIG_GT64260) += gt64260_pic.o
+obj-$(CONFIG_K2) += i8259.o indirect_pci.o todc_time.o \
+ pci_auto.o
+obj-$(CONFIG_LOPEC) += i8259.o pci_auto.o todc_time.o
+obj-$(CONFIG_HDPU) += pci_auto.o
+obj-$(CONFIG_LUAN) += indirect_pci.o pci_auto.o todc_time.o
+obj-$(CONFIG_KATANA) += pci_auto.o
+obj-$(CONFIG_MCPN765) += todc_time.o indirect_pci.o pci_auto.o \
+ open_pic.o i8259.o hawk_common.o
+obj-$(CONFIG_MENF1) += todc_time.o i8259.o mpc10x_common.o \
+ pci_auto.o indirect_pci.o
+obj-$(CONFIG_MV64360) += mv64360_pic.o
+obj-$(CONFIG_MV64X60) += mv64x60.o mv64x60_win.o indirect_pci.o
+obj-$(CONFIG_MVME5100) += open_pic.o todc_time.o indirect_pci.o \
+ pci_auto.o hawk_common.o
+obj-$(CONFIG_MVME5100_IPMC761_PRESENT) += i8259.o
+obj-$(CONFIG_OCOTEA) += indirect_pci.o pci_auto.o todc_time.o
+obj-$(CONFIG_PAL4) += cpc700_pic.o
+obj-$(CONFIG_PCORE) += todc_time.o i8259.o pci_auto.o
+obj-$(CONFIG_POWERPMC250) += pci_auto.o
+obj-$(CONFIG_PPLUS) += hawk_common.o open_pic.o i8259.o \
+ indirect_pci.o todc_time.o pci_auto.o
+obj-$(CONFIG_PRPMC750) += open_pic.o indirect_pci.o pci_auto.o \
+ hawk_common.o
+obj-$(CONFIG_HARRIER) += harrier.o
+obj-$(CONFIG_PRPMC800) += open_pic.o indirect_pci.o pci_auto.o
+obj-$(CONFIG_RADSTONE_PPC7D) += i8259.o pci_auto.o
+obj-$(CONFIG_SANDPOINT) += i8259.o pci_auto.o todc_time.o
+obj-$(CONFIG_SBC82xx) += todc_time.o
+obj-$(CONFIG_SPRUCE) += cpc700_pic.o indirect_pci.o pci_auto.o \
+ todc_time.o
+obj-$(CONFIG_8260) += m8260_setup.o
+obj-$(CONFIG_PCI_8260) += m8260_pci.o indirect_pci.o
+obj-$(CONFIG_8260_PCI9) += m8260_pci_erratum9.o
+obj-$(CONFIG_CPM2) += cpm2_common.o cpm2_pic.o
+ifeq ($(CONFIG_PPC_GEN550),y)
+obj-$(CONFIG_KGDB) += gen550_kgdb.o gen550_dbg.o
+obj-$(CONFIG_SERIAL_TEXT_DEBUG) += gen550_dbg.o
+endif
+ifeq ($(CONFIG_SERIAL_MPSC_CONSOLE),y)
+obj-$(CONFIG_SERIAL_TEXT_DEBUG) += mv64x60_dbg.o
+endif
+obj-$(CONFIG_BOOTX_TEXT) += btext.o
+obj-$(CONFIG_MPC10X_BRIDGE) += mpc10x_common.o indirect_pci.o
+obj-$(CONFIG_MPC10X_OPENPIC) += open_pic.o
+obj-$(CONFIG_40x) += dcr.o
+obj-$(CONFIG_BOOKE) += dcr.o
+obj-$(CONFIG_85xx) += open_pic.o ppc85xx_common.o ppc85xx_setup.o \
+ ppc_sys.o mpc85xx_sys.o \
+ mpc85xx_devices.o
+ifeq ($(CONFIG_85xx),y)
+obj-$(CONFIG_PCI) += indirect_pci.o pci_auto.o
+endif
+obj-$(CONFIG_83xx) += ipic.o ppc83xx_setup.o ppc_sys.o \
+ mpc83xx_sys.o mpc83xx_devices.o
+ifeq ($(CONFIG_83xx),y)
+obj-$(CONFIG_PCI) += indirect_pci.o pci_auto.o
+endif
+obj-$(CONFIG_MPC8555_CDS) += todc_time.o
+obj-$(CONFIG_PPC_MPC52xx) += mpc52xx_setup.o mpc52xx_pic.o \
+ mpc52xx_sys.o mpc52xx_devices.o ppc_sys.o
+ifeq ($(CONFIG_PPC_MPC52xx),y)
+obj-$(CONFIG_PCI) += mpc52xx_pci.o
+endif
diff --git a/arch/ppc/syslib/btext.c b/arch/ppc/syslib/btext.c
new file mode 100644
index 0000000..7734f68
--- /dev/null
+++ b/arch/ppc/syslib/btext.c
@@ -0,0 +1,861 @@
+/*
+ * Procedures for drawing on the screen early on in the boot process.
+ *
+ * Benjamin Herrenschmidt <benh@kernel.crashing.org>
+ */
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/init.h>
+#include <linux/version.h>
+
+#include <asm/sections.h>
+#include <asm/bootx.h>
+#include <asm/btext.h>
+#include <asm/prom.h>
+#include <asm/page.h>
+#include <asm/mmu.h>
+#include <asm/pgtable.h>
+#include <asm/io.h>
+#include <asm/reg.h>
+
+#define NO_SCROLL
+
+#ifndef NO_SCROLL
+static void scrollscreen(void);
+#endif
+
+static void draw_byte(unsigned char c, long locX, long locY);
+static void draw_byte_32(unsigned char *bits, unsigned long *base, int rb);
+static void draw_byte_16(unsigned char *bits, unsigned long *base, int rb);
+static void draw_byte_8(unsigned char *bits, unsigned long *base, int rb);
+
+static int g_loc_X;
+static int g_loc_Y;
+static int g_max_loc_X;
+static int g_max_loc_Y;
+
+unsigned long disp_BAT[2] __initdata = {0, 0};
+
+#define cmapsz (16*256)
+
+static unsigned char vga_font[cmapsz];
+
+int boot_text_mapped;
+int force_printk_to_btext = 0;
+
+boot_infos_t disp_bi;
+
+extern char *klimit;
+
+/*
+ * Powermac can use btext_* after boot for xmon,
+ * chrp only uses it during early boot.
+ */
+#ifdef CONFIG_XMON
+#define BTEXT __pmac
+#define BTDATA __pmacdata
+#else
+#define BTEXT __init
+#define BTDATA __initdata
+#endif /* CONFIG_XMON */
+
+/*
+ * This is called only when we are booted via BootX.
+ */
+void __init
+btext_init(boot_infos_t *bi)
+{
+ g_loc_X = 0;
+ g_loc_Y = 0;
+ g_max_loc_X = (bi->dispDeviceRect[2] - bi->dispDeviceRect[0]) / 8;
+ g_max_loc_Y = (bi->dispDeviceRect[3] - bi->dispDeviceRect[1]) / 16;
+ disp_bi = *bi;
+ boot_text_mapped = 1;
+}
+
+void __init
+btext_welcome(void)
+{
+ unsigned long flags;
+ unsigned long pvr;
+ boot_infos_t* bi = &disp_bi;
+
+ btext_drawstring("Welcome to Linux, kernel " UTS_RELEASE "\n");
+ btext_drawstring("\nlinked at : 0x");
+ btext_drawhex(KERNELBASE);
+ btext_drawstring("\nframe buffer at : 0x");
+ btext_drawhex((unsigned long)bi->dispDeviceBase);
+ btext_drawstring(" (phys), 0x");
+ btext_drawhex((unsigned long)bi->logicalDisplayBase);
+ btext_drawstring(" (log)");
+ btext_drawstring("\nklimit : 0x");
+ btext_drawhex((unsigned long)klimit);
+ btext_drawstring("\nMSR : 0x");
+ __asm__ __volatile__ ("mfmsr %0" : "=r" (flags));
+ btext_drawhex(flags);
+ __asm__ __volatile__ ("mfspr %0, 287" : "=r" (pvr));
+ pvr >>= 16;
+ if (pvr > 1) {
+ btext_drawstring("\nHID0 : 0x");
+ __asm__ __volatile__ ("mfspr %0, 1008" : "=r" (flags));
+ btext_drawhex(flags);
+ }
+ if (pvr == 8 || pvr == 12 || pvr == 0x800c) {
+ btext_drawstring("\nICTC : 0x");
+ __asm__ __volatile__ ("mfspr %0, 1019" : "=r" (flags));
+ btext_drawhex(flags);
+ }
+ btext_drawstring("\n\n");
+}
+
+/* Calc BAT values for mapping the display and store them
+ * in disp_BAT. Those values are then used from head.S to map
+ * the display during identify_machine() and MMU_Init()
+ *
+ * The display is mapped to virtual address 0xD0000000, rather
+ * than 1:1, because some some CHRP machines put the frame buffer
+ * in the region starting at 0xC0000000 (KERNELBASE).
+ * This mapping is temporary and will disappear as soon as the
+ * setup done by MMU_Init() is applied.
+ *
+ * For now, we align the BAT and then map 8Mb on 601 and 16Mb
+ * on other PPCs. This may cause trouble if the framebuffer
+ * is really badly aligned, but I didn't encounter this case
+ * yet.
+ */
+void __init
+btext_prepare_BAT(void)
+{
+ boot_infos_t* bi = &disp_bi;
+ unsigned long vaddr = KERNELBASE + 0x10000000;
+ unsigned long addr;
+ unsigned long lowbits;
+
+ addr = (unsigned long)bi->dispDeviceBase;
+ if (!addr) {
+ boot_text_mapped = 0;
+ return;
+ }
+ if (PVR_VER(mfspr(SPRN_PVR)) != 1) {
+ /* 603, 604, G3, G4, ... */
+ lowbits = addr & ~0xFF000000UL;
+ addr &= 0xFF000000UL;
+ disp_BAT[0] = vaddr | (BL_16M<<2) | 2;
+ disp_BAT[1] = addr | (_PAGE_NO_CACHE | _PAGE_GUARDED | BPP_RW);
+ } else {
+ /* 601 */
+ lowbits = addr & ~0xFF800000UL;
+ addr &= 0xFF800000UL;
+ disp_BAT[0] = vaddr | (_PAGE_NO_CACHE | PP_RWXX) | 4;
+ disp_BAT[1] = addr | BL_8M | 0x40;
+ }
+ bi->logicalDisplayBase = (void *) (vaddr + lowbits);
+}
+
+/* This function will enable the early boot text when doing OF booting. This
+ * way, xmon output should work too
+ */
+void __init
+btext_setup_display(int width, int height, int depth, int pitch,
+ unsigned long address)
+{
+ boot_infos_t* bi = &disp_bi;
+
+ g_loc_X = 0;
+ g_loc_Y = 0;
+ g_max_loc_X = width / 8;
+ g_max_loc_Y = height / 16;
+ bi->logicalDisplayBase = (unsigned char *)address;
+ bi->dispDeviceBase = (unsigned char *)address;
+ bi->dispDeviceRowBytes = pitch;
+ bi->dispDeviceDepth = depth;
+ bi->dispDeviceRect[0] = bi->dispDeviceRect[1] = 0;
+ bi->dispDeviceRect[2] = width;
+ bi->dispDeviceRect[3] = height;
+ boot_text_mapped = 1;
+}
+
+/* Here's a small text engine to use during early boot
+ * or for debugging purposes
+ *
+ * todo:
+ *
+ * - build some kind of vgacon with it to enable early printk
+ * - move to a separate file
+ * - add a few video driver hooks to keep in sync with display
+ * changes.
+ */
+
+void __openfirmware
+map_boot_text(void)
+{
+ unsigned long base, offset, size;
+ boot_infos_t *bi = &disp_bi;
+ unsigned char *vbase;
+
+ /* By default, we are no longer mapped */
+ boot_text_mapped = 0;
+ if (bi->dispDeviceBase == 0)
+ return;
+ base = ((unsigned long) bi->dispDeviceBase) & 0xFFFFF000UL;
+ offset = ((unsigned long) bi->dispDeviceBase) - base;
+ size = bi->dispDeviceRowBytes * bi->dispDeviceRect[3] + offset
+ + bi->dispDeviceRect[0];
+ vbase = ioremap(base, size);
+ if (vbase == 0)
+ return;
+ bi->logicalDisplayBase = vbase + offset;
+ boot_text_mapped = 1;
+}
+
+/* Calc the base address of a given point (x,y) */
+static unsigned char * BTEXT
+calc_base(boot_infos_t *bi, int x, int y)
+{
+ unsigned char *base;
+
+ base = bi->logicalDisplayBase;
+ if (base == 0)
+ base = bi->dispDeviceBase;
+ base += (x + bi->dispDeviceRect[0]) * (bi->dispDeviceDepth >> 3);
+ base += (y + bi->dispDeviceRect[1]) * bi->dispDeviceRowBytes;
+ return base;
+}
+
+/* Adjust the display to a new resolution */
+void
+btext_update_display(unsigned long phys, int width, int height,
+ int depth, int pitch)
+{
+ boot_infos_t *bi = &disp_bi;
+
+ if (bi->dispDeviceBase == 0)
+ return;
+
+ /* check it's the same frame buffer (within 256MB) */
+ if ((phys ^ (unsigned long)bi->dispDeviceBase) & 0xf0000000)
+ return;
+
+ bi->dispDeviceBase = (__u8 *) phys;
+ bi->dispDeviceRect[0] = 0;
+ bi->dispDeviceRect[1] = 0;
+ bi->dispDeviceRect[2] = width;
+ bi->dispDeviceRect[3] = height;
+ bi->dispDeviceDepth = depth;
+ bi->dispDeviceRowBytes = pitch;
+ if (boot_text_mapped) {
+ iounmap(bi->logicalDisplayBase);
+ boot_text_mapped = 0;
+ }
+ map_boot_text();
+ g_loc_X = 0;
+ g_loc_Y = 0;
+ g_max_loc_X = width / 8;
+ g_max_loc_Y = height / 16;
+}
+
+void BTEXT btext_clearscreen(void)
+{
+ boot_infos_t* bi = &disp_bi;
+ unsigned long *base = (unsigned long *)calc_base(bi, 0, 0);
+ unsigned long width = ((bi->dispDeviceRect[2] - bi->dispDeviceRect[0]) *
+ (bi->dispDeviceDepth >> 3)) >> 2;
+ int i,j;
+
+ for (i=0; i<(bi->dispDeviceRect[3] - bi->dispDeviceRect[1]); i++)
+ {
+ unsigned long *ptr = base;
+ for(j=width; j; --j)
+ *(ptr++) = 0;
+ base += (bi->dispDeviceRowBytes >> 2);
+ }
+}
+
+__inline__ void dcbst(const void* addr)
+{
+ __asm__ __volatile__ ("dcbst 0,%0" :: "r" (addr));
+}
+
+void BTEXT btext_flushscreen(void)
+{
+ boot_infos_t* bi = &disp_bi;
+ unsigned long *base = (unsigned long *)calc_base(bi, 0, 0);
+ unsigned long width = ((bi->dispDeviceRect[2] - bi->dispDeviceRect[0]) *
+ (bi->dispDeviceDepth >> 3)) >> 2;
+ int i,j;
+
+ for (i=0; i<(bi->dispDeviceRect[3] - bi->dispDeviceRect[1]); i++)
+ {
+ unsigned long *ptr = base;
+ for(j=width; j>0; j-=8) {
+ dcbst(ptr);
+ ptr += 8;
+ }
+ base += (bi->dispDeviceRowBytes >> 2);
+ }
+}
+
+#ifndef NO_SCROLL
+static BTEXT void
+scrollscreen(void)
+{
+ boot_infos_t* bi = &disp_bi;
+ unsigned long *src = (unsigned long *)calc_base(bi,0,16);
+ unsigned long *dst = (unsigned long *)calc_base(bi,0,0);
+ unsigned long width = ((bi->dispDeviceRect[2] - bi->dispDeviceRect[0]) *
+ (bi->dispDeviceDepth >> 3)) >> 2;
+ int i,j;
+
+#ifdef CONFIG_ADB_PMU
+ pmu_suspend(); /* PMU will not shut us down ! */
+#endif
+ for (i=0; i<(bi->dispDeviceRect[3] - bi->dispDeviceRect[1] - 16); i++)
+ {
+ unsigned long *src_ptr = src;
+ unsigned long *dst_ptr = dst;
+ for(j=width; j; --j)
+ *(dst_ptr++) = *(src_ptr++);
+ src += (bi->dispDeviceRowBytes >> 2);
+ dst += (bi->dispDeviceRowBytes >> 2);
+ }
+ for (i=0; i<16; i++)
+ {
+ unsigned long *dst_ptr = dst;
+ for(j=width; j; --j)
+ *(dst_ptr++) = 0;
+ dst += (bi->dispDeviceRowBytes >> 2);
+ }
+#ifdef CONFIG_ADB_PMU
+ pmu_resume(); /* PMU will not shut us down ! */
+#endif
+}
+#endif /* ndef NO_SCROLL */
+
+void BTEXT btext_drawchar(char c)
+{
+ int cline = 0, x;
+
+ if (!boot_text_mapped)
+ return;
+
+ switch (c) {
+ case '\b':
+ if (g_loc_X > 0)
+ --g_loc_X;
+ break;
+ case '\t':
+ g_loc_X = (g_loc_X & -8) + 8;
+ break;
+ case '\r':
+ g_loc_X = 0;
+ break;
+ case '\n':
+ g_loc_X = 0;
+ g_loc_Y++;
+ cline = 1;
+ break;
+ default:
+ draw_byte(c, g_loc_X++, g_loc_Y);
+ }
+ if (g_loc_X >= g_max_loc_X) {
+ g_loc_X = 0;
+ g_loc_Y++;
+ cline = 1;
+ }
+#ifndef NO_SCROLL
+ while (g_loc_Y >= g_max_loc_Y) {
+ scrollscreen();
+ g_loc_Y--;
+ }
+#else
+ /* wrap around from bottom to top of screen so we don't
+ waste time scrolling each line. -- paulus. */
+ if (g_loc_Y >= g_max_loc_Y)
+ g_loc_Y = 0;
+ if (cline) {
+ for (x = 0; x < g_max_loc_X; ++x)
+ draw_byte(' ', x, g_loc_Y);
+ }
+#endif
+}
+
+void BTEXT
+btext_drawstring(const char *c)
+{
+ if (!boot_text_mapped)
+ return;
+ while (*c)
+ btext_drawchar(*c++);
+}
+
+void BTEXT
+btext_drawhex(unsigned long v)
+{
+ static char hex_table[] = "0123456789abcdef";
+
+ if (!boot_text_mapped)
+ return;
+ btext_drawchar(hex_table[(v >> 28) & 0x0000000FUL]);
+ btext_drawchar(hex_table[(v >> 24) & 0x0000000FUL]);
+ btext_drawchar(hex_table[(v >> 20) & 0x0000000FUL]);
+ btext_drawchar(hex_table[(v >> 16) & 0x0000000FUL]);
+ btext_drawchar(hex_table[(v >> 12) & 0x0000000FUL]);
+ btext_drawchar(hex_table[(v >> 8) & 0x0000000FUL]);
+ btext_drawchar(hex_table[(v >> 4) & 0x0000000FUL]);
+ btext_drawchar(hex_table[(v >> 0) & 0x0000000FUL]);
+ btext_drawchar(' ');
+}
+
+static void BTEXT
+draw_byte(unsigned char c, long locX, long locY)
+{
+ boot_infos_t* bi = &disp_bi;
+ unsigned char *base = calc_base(bi, locX << 3, locY << 4);
+ unsigned char *font = &vga_font[((unsigned long)c) * 16];
+ int rb = bi->dispDeviceRowBytes;
+
+ switch(bi->dispDeviceDepth) {
+ case 24:
+ case 32:
+ draw_byte_32(font, (unsigned long *)base, rb);
+ break;
+ case 15:
+ case 16:
+ draw_byte_16(font, (unsigned long *)base, rb);
+ break;
+ case 8:
+ draw_byte_8(font, (unsigned long *)base, rb);
+ break;
+ }
+}
+
+static unsigned long expand_bits_8[16] BTDATA = {
+ 0x00000000,
+ 0x000000ff,
+ 0x0000ff00,
+ 0x0000ffff,
+ 0x00ff0000,
+ 0x00ff00ff,
+ 0x00ffff00,
+ 0x00ffffff,
+ 0xff000000,
+ 0xff0000ff,
+ 0xff00ff00,
+ 0xff00ffff,
+ 0xffff0000,
+ 0xffff00ff,
+ 0xffffff00,
+ 0xffffffff
+};
+
+static unsigned long expand_bits_16[4] BTDATA = {
+ 0x00000000,
+ 0x0000ffff,
+ 0xffff0000,
+ 0xffffffff
+};
+
+
+static void BTEXT
+draw_byte_32(unsigned char *font, unsigned long *base, int rb)
+{
+ int l, bits;
+ int fg = 0xFFFFFFFFUL;
+ int bg = 0x00000000UL;
+
+ for (l = 0; l < 16; ++l)
+ {
+ bits = *font++;
+ base[0] = (-(bits >> 7) & fg) ^ bg;
+ base[1] = (-((bits >> 6) & 1) & fg) ^ bg;
+ base[2] = (-((bits >> 5) & 1) & fg) ^ bg;
+ base[3] = (-((bits >> 4) & 1) & fg) ^ bg;
+ base[4] = (-((bits >> 3) & 1) & fg) ^ bg;
+ base[5] = (-((bits >> 2) & 1) & fg) ^ bg;
+ base[6] = (-((bits >> 1) & 1) & fg) ^ bg;
+ base[7] = (-(bits & 1) & fg) ^ bg;
+ base = (unsigned long *) ((char *)base + rb);
+ }
+}
+
+static void BTEXT
+draw_byte_16(unsigned char *font, unsigned long *base, int rb)
+{
+ int l, bits;
+ int fg = 0xFFFFFFFFUL;
+ int bg = 0x00000000UL;
+ unsigned long *eb = expand_bits_16;
+
+ for (l = 0; l < 16; ++l)
+ {
+ bits = *font++;
+ base[0] = (eb[bits >> 6] & fg) ^ bg;
+ base[1] = (eb[(bits >> 4) & 3] & fg) ^ bg;
+ base[2] = (eb[(bits >> 2) & 3] & fg) ^ bg;
+ base[3] = (eb[bits & 3] & fg) ^ bg;
+ base = (unsigned long *) ((char *)base + rb);
+ }
+}
+
+static void BTEXT
+draw_byte_8(unsigned char *font, unsigned long *base, int rb)
+{
+ int l, bits;
+ int fg = 0x0F0F0F0FUL;
+ int bg = 0x00000000UL;
+ unsigned long *eb = expand_bits_8;
+
+ for (l = 0; l < 16; ++l)
+ {
+ bits = *font++;
+ base[0] = (eb[bits >> 4] & fg) ^ bg;
+ base[1] = (eb[bits & 0xf] & fg) ^ bg;
+ base = (unsigned long *) ((char *)base + rb);
+ }
+}
+
+static unsigned char vga_font[cmapsz] BTDATA = {
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x81, 0xa5, 0x81, 0x81, 0xbd,
+0x99, 0x81, 0x81, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0xff,
+0xdb, 0xff, 0xff, 0xc3, 0xe7, 0xff, 0xff, 0x7e, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x6c, 0xfe, 0xfe, 0xfe, 0xfe, 0x7c, 0x38, 0x10,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x7c, 0xfe,
+0x7c, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18,
+0x3c, 0x3c, 0xe7, 0xe7, 0xe7, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x18, 0x3c, 0x7e, 0xff, 0xff, 0x7e, 0x18, 0x18, 0x3c,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x3c,
+0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xe7, 0xc3, 0xc3, 0xe7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x42, 0x42, 0x66, 0x3c, 0x00,
+0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc3, 0x99, 0xbd,
+0xbd, 0x99, 0xc3, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x1e, 0x0e,
+0x1a, 0x32, 0x78, 0xcc, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x7e, 0x18, 0x18,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x33, 0x3f, 0x30, 0x30, 0x30,
+0x30, 0x70, 0xf0, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x63,
+0x7f, 0x63, 0x63, 0x63, 0x63, 0x67, 0xe7, 0xe6, 0xc0, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x18, 0x18, 0xdb, 0x3c, 0xe7, 0x3c, 0xdb, 0x18, 0x18,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfe, 0xf8,
+0xf0, 0xe0, 0xc0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x06, 0x0e,
+0x1e, 0x3e, 0xfe, 0x3e, 0x1e, 0x0e, 0x06, 0x02, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x18, 0x7e, 0x3c, 0x18, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
+0x66, 0x00, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xdb,
+0xdb, 0xdb, 0x7b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x7c, 0xc6, 0x60, 0x38, 0x6c, 0xc6, 0xc6, 0x6c, 0x38, 0x0c, 0xc6,
+0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0xfe, 0xfe, 0xfe, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x3c,
+0x7e, 0x18, 0x18, 0x18, 0x7e, 0x3c, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
+0x18, 0x7e, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x18, 0x0c, 0xfe, 0x0c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x60, 0xfe, 0x60, 0x30, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0,
+0xc0, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x24, 0x66, 0xff, 0x66, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x38, 0x7c, 0x7c, 0xfe, 0xfe, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xfe, 0x7c, 0x7c,
+0x38, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x18, 0x3c, 0x3c, 0x3c, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x24, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6c,
+0x6c, 0xfe, 0x6c, 0x6c, 0x6c, 0xfe, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00,
+0x18, 0x18, 0x7c, 0xc6, 0xc2, 0xc0, 0x7c, 0x06, 0x06, 0x86, 0xc6, 0x7c,
+0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc2, 0xc6, 0x0c, 0x18,
+0x30, 0x60, 0xc6, 0x86, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x6c,
+0x6c, 0x38, 0x76, 0xdc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x30, 0x30, 0x30, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x18, 0x30, 0x30, 0x30, 0x30,
+0x30, 0x30, 0x18, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x18,
+0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x3c, 0xff, 0x3c, 0x66, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x7e,
+0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x30, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x02, 0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0x80, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xce, 0xde, 0xf6, 0xe6, 0xc6, 0xc6, 0x7c,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x38, 0x78, 0x18, 0x18, 0x18,
+0x18, 0x18, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6,
+0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x7c, 0xc6, 0x06, 0x06, 0x3c, 0x06, 0x06, 0x06, 0xc6, 0x7c,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x1c, 0x3c, 0x6c, 0xcc, 0xfe,
+0x0c, 0x0c, 0x0c, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc0,
+0xc0, 0xc0, 0xfc, 0x06, 0x06, 0x06, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x38, 0x60, 0xc0, 0xc0, 0xfc, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc6, 0x06, 0x06, 0x0c, 0x18,
+0x30, 0x30, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6,
+0xc6, 0xc6, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x06, 0x06, 0x0c, 0x78,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00,
+0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x18, 0x18, 0x00, 0x00, 0x00, 0x18, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x06, 0x0c, 0x18, 0x30, 0x60, 0x30, 0x18, 0x0c, 0x06,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00,
+0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60,
+0x30, 0x18, 0x0c, 0x06, 0x0c, 0x18, 0x30, 0x60, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x7c, 0xc6, 0xc6, 0x0c, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xde, 0xde,
+0xde, 0xdc, 0xc0, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38,
+0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x66, 0x66, 0x66, 0x66, 0xfc,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0xc2, 0xc0, 0xc0, 0xc0,
+0xc0, 0xc2, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x6c,
+0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x6c, 0xf8, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, 0x60, 0x62, 0x66, 0xfe,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68,
+0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66,
+0xc2, 0xc0, 0xc0, 0xde, 0xc6, 0xc6, 0x66, 0x3a, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x18,
+0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x0c,
+0x0c, 0x0c, 0x0c, 0x0c, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0xe6, 0x66, 0x66, 0x6c, 0x78, 0x78, 0x6c, 0x66, 0x66, 0xe6,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x60, 0x60, 0x60, 0x60, 0x60,
+0x60, 0x62, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0xe7,
+0xff, 0xff, 0xdb, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0xc6, 0xe6, 0xf6, 0xfe, 0xde, 0xce, 0xc6, 0xc6, 0xc6, 0xc6,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6,
+0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x66,
+0x66, 0x66, 0x7c, 0x60, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xd6, 0xde, 0x7c,
+0x0c, 0x0e, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x6c,
+0x66, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6,
+0xc6, 0x60, 0x38, 0x0c, 0x06, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0xff, 0xdb, 0x99, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6,
+0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0xc3,
+0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0x66, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xdb, 0xdb, 0xff, 0x66, 0x66,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0xc3, 0x66, 0x3c, 0x18, 0x18,
+0x3c, 0x66, 0xc3, 0xc3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0xc3,
+0xc3, 0x66, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0xff, 0xc3, 0x86, 0x0c, 0x18, 0x30, 0x60, 0xc1, 0xc3, 0xff,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x30, 0x30, 0x30, 0x30, 0x30,
+0x30, 0x30, 0x30, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
+0xc0, 0xe0, 0x70, 0x38, 0x1c, 0x0e, 0x06, 0x02, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x3c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x3c,
+0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00,
+0x30, 0x30, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x0c, 0x7c,
+0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x60,
+0x60, 0x78, 0x6c, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc0, 0xc0, 0xc0, 0xc6, 0x7c,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x0c, 0x0c, 0x3c, 0x6c, 0xcc,
+0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x38, 0x6c, 0x64, 0x60, 0xf0, 0x60, 0x60, 0x60, 0x60, 0xf0,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xcc, 0xcc,
+0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0xcc, 0x78, 0x00, 0x00, 0x00, 0xe0, 0x60,
+0x60, 0x6c, 0x76, 0x66, 0x66, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x18, 0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x06, 0x00, 0x0e, 0x06, 0x06,
+0x06, 0x06, 0x06, 0x06, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0xe0, 0x60,
+0x60, 0x66, 0x6c, 0x78, 0x78, 0x6c, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe6, 0xff, 0xdb,
+0xdb, 0xdb, 0xdb, 0xdb, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x66, 0x66,
+0x66, 0x66, 0x66, 0x7c, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x76, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0x0c, 0x1e, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x76, 0x66, 0x60, 0x60, 0x60, 0xf0,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0x60,
+0x38, 0x0c, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x30,
+0x30, 0xfc, 0x30, 0x30, 0x30, 0x30, 0x36, 0x1c, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0xc3, 0xc3,
+0xc3, 0x66, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0xc3, 0xc3, 0xc3, 0xdb, 0xdb, 0xff, 0x66, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0x66, 0x3c, 0x18, 0x3c, 0x66, 0xc3,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xc6,
+0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x0c, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0xfe, 0xcc, 0x18, 0x30, 0x60, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x0e, 0x18, 0x18, 0x18, 0x70, 0x18, 0x18, 0x18, 0x18, 0x0e,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x00, 0x18,
+0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x18,
+0x18, 0x18, 0x0e, 0x18, 0x18, 0x18, 0x18, 0x70, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x76, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x6c, 0xc6,
+0xc6, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66,
+0xc2, 0xc0, 0xc0, 0xc0, 0xc2, 0x66, 0x3c, 0x0c, 0x06, 0x7c, 0x00, 0x00,
+0x00, 0x00, 0xcc, 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x18, 0x30, 0x00, 0x7c, 0xc6, 0xfe,
+0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x6c,
+0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0xcc, 0x00, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x30, 0x18, 0x00, 0x78, 0x0c, 0x7c,
+0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x6c, 0x38,
+0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x60, 0x60, 0x66, 0x3c, 0x0c, 0x06,
+0x3c, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x6c, 0x00, 0x7c, 0xc6, 0xfe,
+0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x00,
+0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x60, 0x30, 0x18, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x00, 0x00, 0x38, 0x18, 0x18,
+0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x3c, 0x66,
+0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x60, 0x30, 0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c,
+0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6,
+0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00, 0x38, 0x6c, 0x38, 0x00,
+0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00,
+0x18, 0x30, 0x60, 0x00, 0xfe, 0x66, 0x60, 0x7c, 0x60, 0x60, 0x66, 0xfe,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6e, 0x3b, 0x1b,
+0x7e, 0xd8, 0xdc, 0x77, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x6c,
+0xcc, 0xcc, 0xfe, 0xcc, 0xcc, 0xcc, 0xcc, 0xce, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x10, 0x38, 0x6c, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x00, 0x00, 0x7c, 0xc6, 0xc6,
+0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x30, 0x18,
+0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x30, 0x78, 0xcc, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x30, 0x18, 0x00, 0xcc, 0xcc, 0xcc,
+0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x00,
+0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x0c, 0x78, 0x00,
+0x00, 0xc6, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c,
+0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6,
+0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x7e,
+0xc3, 0xc0, 0xc0, 0xc0, 0xc3, 0x7e, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x38, 0x6c, 0x64, 0x60, 0xf0, 0x60, 0x60, 0x60, 0x60, 0xe6, 0xfc,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0x66, 0x3c, 0x18, 0xff, 0x18,
+0xff, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x66, 0x66,
+0x7c, 0x62, 0x66, 0x6f, 0x66, 0x66, 0x66, 0xf3, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x0e, 0x1b, 0x18, 0x18, 0x18, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18,
+0xd8, 0x70, 0x00, 0x00, 0x00, 0x18, 0x30, 0x60, 0x00, 0x78, 0x0c, 0x7c,
+0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x18, 0x30,
+0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x18, 0x30, 0x60, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x30, 0x60, 0x00, 0xcc, 0xcc, 0xcc,
+0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xdc,
+0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00,
+0x76, 0xdc, 0x00, 0xc6, 0xe6, 0xf6, 0xfe, 0xde, 0xce, 0xc6, 0xc6, 0xc6,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x6c, 0x6c, 0x3e, 0x00, 0x7e, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x6c, 0x6c,
+0x38, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x30, 0x30, 0x00, 0x30, 0x30, 0x60, 0xc0, 0xc6, 0xc6, 0x7c,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc0,
+0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0xfe, 0x06, 0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0xc0, 0xc0, 0xc2, 0xc6, 0xcc, 0x18, 0x30, 0x60, 0xce, 0x9b, 0x06,
+0x0c, 0x1f, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc2, 0xc6, 0xcc, 0x18, 0x30,
+0x66, 0xce, 0x96, 0x3e, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18,
+0x00, 0x18, 0x18, 0x18, 0x3c, 0x3c, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x6c, 0xd8, 0x6c, 0x36, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x6c, 0x36,
+0x6c, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x44, 0x11, 0x44,
+0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44,
+0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa,
+0x55, 0xaa, 0x55, 0xaa, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77,
+0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0x18, 0x18, 0x18, 0x18,
+0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
+0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0x18, 0x18, 0x18,
+0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0xf8,
+0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x36, 0x36, 0x36, 0x36,
+0x36, 0x36, 0x36, 0xf6, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x36, 0x36, 0x36, 0x36,
+0x36, 0x36, 0x36, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x18, 0xf8,
+0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x36, 0x36, 0x36, 0x36,
+0x36, 0xf6, 0x06, 0xf6, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
+0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
+0x36, 0x36, 0x36, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x06, 0xf6,
+0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
+0x36, 0xf6, 0x06, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xfe, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0xf8,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0xf8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
+0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xff,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
+0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x18, 0x18, 0x18, 0x18,
+0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18,
+0x18, 0x18, 0x18, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
+0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x18, 0x1f, 0x18, 0x18, 0x18, 0x18,
+0x18, 0x18, 0x18, 0x18, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x37,
+0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
+0x36, 0x37, 0x30, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x30, 0x37, 0x36, 0x36, 0x36, 0x36,
+0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xf7, 0x00, 0xff,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0xff, 0x00, 0xf7, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
+0x36, 0x36, 0x36, 0x36, 0x36, 0x37, 0x30, 0x37, 0x36, 0x36, 0x36, 0x36,
+0x36, 0x36, 0x36, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xff,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x36, 0x36, 0x36,
+0x36, 0xf7, 0x00, 0xf7, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
+0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xff,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0xff, 0x00, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x36, 0x36, 0x36, 0x36,
+0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x3f,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18,
+0x18, 0x1f, 0x18, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x18, 0x1f, 0x18, 0x18, 0x18, 0x18,
+0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f,
+0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
+0x36, 0x36, 0x36, 0xff, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
+0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x18, 0xff, 0x18, 0x18, 0x18, 0x18,
+0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x1f, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0xf0, 0xf0, 0xf0,
+0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0,
+0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f,
+0x0f, 0x0f, 0x0f, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x76, 0xdc, 0xd8, 0xd8, 0xd8, 0xdc, 0x76, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x78, 0xcc, 0xcc, 0xcc, 0xd8, 0xcc, 0xc6, 0xc6, 0xc6, 0xcc,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc6, 0xc6, 0xc0, 0xc0, 0xc0,
+0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0xfe, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0xfe, 0xc6, 0x60, 0x30, 0x18, 0x30, 0x60, 0xc6, 0xfe,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0xd8, 0xd8,
+0xd8, 0xd8, 0xd8, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x66, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x60, 0x60, 0xc0, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x76, 0xdc, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x18, 0x3c, 0x66, 0x66,
+0x66, 0x3c, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38,
+0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0x6c, 0x38, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x38, 0x6c, 0xc6, 0xc6, 0xc6, 0x6c, 0x6c, 0x6c, 0x6c, 0xee,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x30, 0x18, 0x0c, 0x3e, 0x66,
+0x66, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x7e, 0xdb, 0xdb, 0xdb, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x03, 0x06, 0x7e, 0xdb, 0xdb, 0xf3, 0x7e, 0x60, 0xc0,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x30, 0x60, 0x60, 0x7c, 0x60,
+0x60, 0x60, 0x30, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c,
+0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0xfe, 0x00, 0x00, 0xfe, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x7e, 0x18,
+0x18, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30,
+0x18, 0x0c, 0x06, 0x0c, 0x18, 0x30, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x0c, 0x18, 0x30, 0x60, 0x30, 0x18, 0x0c, 0x00, 0x7e,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x1b, 0x1b, 0x1b, 0x18, 0x18,
+0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
+0x18, 0x18, 0x18, 0x18, 0xd8, 0xd8, 0xd8, 0x70, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x7e, 0x00, 0x18, 0x18, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xdc, 0x00,
+0x76, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x6c, 0x6c,
+0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x0c, 0x0c,
+0x0c, 0x0c, 0x0c, 0xec, 0x6c, 0x6c, 0x3c, 0x1c, 0x00, 0x00, 0x00, 0x00,
+0x00, 0xd8, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0xd8, 0x30, 0x60, 0xc8, 0xf8, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00,
+};
diff --git a/arch/ppc/syslib/cpc700.h b/arch/ppc/syslib/cpc700.h
new file mode 100644
index 0000000..f2c0025
--- /dev/null
+++ b/arch/ppc/syslib/cpc700.h
@@ -0,0 +1,98 @@
+/*
+ * arch/ppc/syslib/cpc700.h
+ *
+ * Header file for IBM CPC700 Host Bridge, et. al.
+ *
+ * Author: Mark A. Greer
+ * mgreer@mvista.com
+ *
+ * 2000-2002 (c) MontaVista, Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+
+/*
+ * This file contains the defines and macros for the IBM CPC700 host bridge,
+ * memory controller, PIC, UARTs, IIC, and Timers.
+ */
+
+#ifndef __PPC_SYSLIB_CPC700_H__
+#define __PPC_SYSLIB_CPC700_H__
+
+#include <linux/stddef.h>
+#include <linux/types.h>
+#include <linux/init.h>
+
+/* XXX no barriers? not even any volatiles? -- paulus */
+#define CPC700_OUT_32(a,d) (*(u_int *)a = d)
+#define CPC700_IN_32(a) (*(u_int *)a)
+
+/*
+ * PCI Section
+ */
+#define CPC700_PCI_CONFIG_ADDR 0xfec00000
+#define CPC700_PCI_CONFIG_DATA 0xfec00004
+
+/* CPU -> PCI memory window 0 */
+#define CPC700_PMM0_LOCAL 0xff400000 /* CPU physical addr */
+#define CPC700_PMM0_MASK_ATTR 0xff400004 /* size and attrs */
+#define CPC700_PMM0_PCI_LOW 0xff400008 /* PCI addr, low word */
+#define CPC700_PMM0_PCI_HIGH 0xff40000c /* PCI addr, high wd */
+/* CPU -> PCI memory window 1 */
+#define CPC700_PMM1_LOCAL 0xff400010
+#define CPC700_PMM1_MASK_ATTR 0xff400014
+#define CPC700_PMM1_PCI_LOW 0xff400018
+#define CPC700_PMM1_PCI_HIGH 0xff40001c
+/* CPU -> PCI memory window 2 */
+#define CPC700_PMM2_LOCAL 0xff400020
+#define CPC700_PMM2_MASK_ATTR 0xff400024
+#define CPC700_PMM2_PCI_LOW 0xff400028
+#define CPC700_PMM2_PCI_HIGH 0xff40002c
+/* PCI memory -> CPU window 1 */
+#define CPC700_PTM1_MEMSIZE 0xff400030 /* window size */
+#define CPC700_PTM1_LOCAL 0xff400034 /* CPU phys addr */
+/* PCI memory -> CPU window 2 */
+#define CPC700_PTM2_MEMSIZE 0xff400038 /* size and enable */
+#define CPC700_PTM2_LOCAL 0xff40003c
+
+/*
+ * PIC Section
+ *
+ * IBM calls the CPC700's programmable interrupt controller the Universal
+ * Interrupt Controller or UIC.
+ */
+
+/*
+ * UIC Register Addresses.
+ */
+#define CPC700_UIC_UICSR 0xff500880 /* Status Reg (Rd/Clr)*/
+#define CPC700_UIC_UICSRS 0xff500884 /* Status Reg (Set) */
+#define CPC700_UIC_UICER 0xff500888 /* Enable Reg */
+#define CPC700_UIC_UICCR 0xff50088c /* Critical Reg */
+#define CPC700_UIC_UICPR 0xff500890 /* Polarity Reg */
+#define CPC700_UIC_UICTR 0xff500894 /* Trigger Reg */
+#define CPC700_UIC_UICMSR 0xff500898 /* Masked Status Reg */
+#define CPC700_UIC_UICVR 0xff50089c /* Vector Reg */
+#define CPC700_UIC_UICVCR 0xff5008a0 /* Vector Config Reg */
+
+#define CPC700_UIC_UICER_ENABLE 0x00000001 /* Enable an IRQ */
+
+#define CPC700_UIC_UICVCR_31_HI 0x00000000 /* IRQ 31 hi priority */
+#define CPC700_UIC_UICVCR_0_HI 0x00000001 /* IRQ 0 hi priority */
+#define CPC700_UIC_UICVCR_BASE_MASK 0xfffffffc
+#define CPC700_UIC_UICVCR_ORDER_MASK 0x00000001
+
+/* Specify value of a bit for an IRQ. */
+#define CPC700_UIC_IRQ_BIT(i) ((0x00000001) << (31 - (i)))
+
+/*
+ * UIC Exports...
+ */
+extern struct hw_interrupt_type cpc700_pic;
+extern unsigned int cpc700_irq_assigns[32][2];
+
+extern void __init cpc700_init_IRQ(void);
+extern int cpc700_get_irq(struct pt_regs *);
+
+#endif /* __PPC_SYSLIB_CPC700_H__ */
diff --git a/arch/ppc/syslib/cpc700_pic.c b/arch/ppc/syslib/cpc700_pic.c
new file mode 100644
index 0000000..7747098
--- /dev/null
+++ b/arch/ppc/syslib/cpc700_pic.c
@@ -0,0 +1,187 @@
+/*
+ * arch/ppc/syslib/cpc700_pic.c
+ *
+ * Interrupt controller support for IBM Spruce
+ *
+ * Authors: Mark Greer, Matt Porter, and Johnnie Peters
+ * mgreer@mvista.com
+ * mporter@mvista.com
+ * jpeters@mvista.com
+ *
+ * 2001-2002 (c) MontaVista, Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+
+#include <linux/stddef.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/signal.h>
+#include <linux/irq.h>
+
+#include <asm/io.h>
+#include <asm/system.h>
+#include <asm/irq.h>
+
+#include "cpc700.h"
+
+static void
+cpc700_unmask_irq(unsigned int irq)
+{
+ unsigned int tr_bits;
+
+ /*
+ * IRQ 31 is largest IRQ supported.
+ * IRQs 17-19 are reserved.
+ */
+ if ((irq <= 31) && ((irq < 17) || (irq > 19))) {
+ tr_bits = CPC700_IN_32(CPC700_UIC_UICTR);
+
+ if ((tr_bits & (1 << (31 - irq))) == 0) {
+ /* level trigger interrupt, clear bit in status
+ * register */
+ CPC700_OUT_32(CPC700_UIC_UICSR, 1 << (31 - irq));
+ }
+
+ /* Know IRQ fits in entry 0 of ppc_cached_irq_mask[] */
+ ppc_cached_irq_mask[0] |= CPC700_UIC_IRQ_BIT(irq);
+
+ CPC700_OUT_32(CPC700_UIC_UICER, ppc_cached_irq_mask[0]);
+ }
+ return;
+}
+
+static void
+cpc700_mask_irq(unsigned int irq)
+{
+ /*
+ * IRQ 31 is largest IRQ supported.
+ * IRQs 17-19 are reserved.
+ */
+ if ((irq <= 31) && ((irq < 17) || (irq > 19))) {
+ /* Know IRQ fits in entry 0 of ppc_cached_irq_mask[] */
+ ppc_cached_irq_mask[0] &=
+ ~CPC700_UIC_IRQ_BIT(irq);
+
+ CPC700_OUT_32(CPC700_UIC_UICER, ppc_cached_irq_mask[0]);
+ }
+ return;
+}
+
+static void
+cpc700_mask_and_ack_irq(unsigned int irq)
+{
+ u_int bit;
+
+ /*
+ * IRQ 31 is largest IRQ supported.
+ * IRQs 17-19 are reserved.
+ */
+ if ((irq <= 31) && ((irq < 17) || (irq > 19))) {
+ /* Know IRQ fits in entry 0 of ppc_cached_irq_mask[] */
+ bit = CPC700_UIC_IRQ_BIT(irq);
+
+ ppc_cached_irq_mask[0] &= ~bit;
+ CPC700_OUT_32(CPC700_UIC_UICER, ppc_cached_irq_mask[0]);
+ CPC700_OUT_32(CPC700_UIC_UICSR, bit); /* Write 1 clears IRQ */
+ }
+ return;
+}
+
+static struct hw_interrupt_type cpc700_pic = {
+ "CPC700 PIC",
+ NULL,
+ NULL,
+ cpc700_unmask_irq,
+ cpc700_mask_irq,
+ cpc700_mask_and_ack_irq,
+ NULL,
+ NULL
+};
+
+__init static void
+cpc700_pic_init_irq(unsigned int irq)
+{
+ unsigned int tmp;
+
+ /* Set interrupt sense */
+ tmp = CPC700_IN_32(CPC700_UIC_UICTR);
+ if (cpc700_irq_assigns[irq][0] == 0) {
+ tmp &= ~CPC700_UIC_IRQ_BIT(irq);
+ } else {
+ tmp |= CPC700_UIC_IRQ_BIT(irq);
+ }
+ CPC700_OUT_32(CPC700_UIC_UICTR, tmp);
+
+ /* Set interrupt polarity */
+ tmp = CPC700_IN_32(CPC700_UIC_UICPR);
+ if (cpc700_irq_assigns[irq][1]) {
+ tmp |= CPC700_UIC_IRQ_BIT(irq);
+ } else {
+ tmp &= ~CPC700_UIC_IRQ_BIT(irq);
+ }
+ CPC700_OUT_32(CPC700_UIC_UICPR, tmp);
+
+ /* Set interrupt critical */
+ tmp = CPC700_IN_32(CPC700_UIC_UICCR);
+ tmp |= CPC700_UIC_IRQ_BIT(irq);
+ CPC700_OUT_32(CPC700_UIC_UICCR, tmp);
+
+ return;
+}
+
+__init void
+cpc700_init_IRQ(void)
+{
+ int i;
+
+ ppc_cached_irq_mask[0] = 0;
+ CPC700_OUT_32(CPC700_UIC_UICER, 0x00000000); /* Disable all irq's */
+ CPC700_OUT_32(CPC700_UIC_UICSR, 0xffffffff); /* Clear cur intrs */
+ CPC700_OUT_32(CPC700_UIC_UICCR, 0xffffffff); /* Gen INT not MCP */
+ CPC700_OUT_32(CPC700_UIC_UICPR, 0x00000000); /* Active low */
+ CPC700_OUT_32(CPC700_UIC_UICTR, 0x00000000); /* Level Sensitive */
+ CPC700_OUT_32(CPC700_UIC_UICVR, CPC700_UIC_UICVCR_0_HI);
+ /* IRQ 0 is highest */
+
+ for (i = 0; i < 17; i++) {
+ irq_desc[i].handler = &cpc700_pic;
+ cpc700_pic_init_irq(i);
+ }
+
+ for (i = 20; i < 32; i++) {
+ irq_desc[i].handler = &cpc700_pic;
+ cpc700_pic_init_irq(i);
+ }
+
+ return;
+}
+
+
+
+/*
+ * Find the highest IRQ that generating an interrupt, if any.
+ */
+int
+cpc700_get_irq(struct pt_regs *regs)
+{
+ int irq = 0;
+ u_int irq_status, irq_test = 1;
+
+ irq_status = CPC700_IN_32(CPC700_UIC_UICMSR);
+
+ do
+ {
+ if (irq_status & irq_test)
+ break;
+ irq++;
+ irq_test <<= 1;
+ } while (irq < NR_IRQS);
+
+
+ if (irq == NR_IRQS)
+ irq = 33;
+
+ return (31 - irq);
+}
diff --git a/arch/ppc/syslib/cpc710.h b/arch/ppc/syslib/cpc710.h
new file mode 100644
index 0000000..cc0afd8
--- /dev/null
+++ b/arch/ppc/syslib/cpc710.h
@@ -0,0 +1,83 @@
+/*
+ * arch/ppc/syslib/cpc710.h
+ *
+ * Definitions for the IBM CPC710 PCI Host Bridge
+ *
+ * Author: Matt Porter <mporter@mvista.com>
+ *
+ * 2001 (c) MontaVista, Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+
+#ifndef __PPC_PLATFORMS_CPC710_H
+#define __PPC_PLATFORMS_CPC710_H
+
+/* General bridge and memory controller registers */
+#define PIDR 0xff000008
+#define CNFR 0xff00000c
+#define RSTR 0xff000010
+#define UCTL 0xff001000
+#define MPSR 0xff001010
+#define SIOC 0xff001020
+#define ABCNTL 0xff001030
+#define SRST 0xff001040
+#define ERRC 0xff001050
+#define SESR 0xff001060
+#define SEAR 0xff001070
+#define SIOC1 0xff001090
+#define PGCHP 0xff001100
+#define GPDIR 0xff001130
+#define GPOUT 0xff001150
+#define ATAS 0xff001160
+#define AVDG 0xff001170
+#define MCCR 0xff001200
+#define MESR 0xff001220
+#define MEAR 0xff001230
+#define MCER0 0xff001300
+#define MCER1 0xff001310
+#define MCER2 0xff001320
+#define MCER3 0xff001330
+#define MCER4 0xff001340
+#define MCER5 0xff001350
+#define MCER6 0xff001360
+#define MCER7 0xff001370
+
+/*
+ * PCI32/64 configuration registers
+ * Given as offsets from their
+ * respective physical segment BAR
+ */
+#define PIBAR 0x000f7800
+#define PMBAR 0x000f7810
+#define MSIZE 0x000f7f40
+#define IOSIZE 0x000f7f60
+#define SMBAR 0x000f7f80
+#define SIBAR 0x000f7fc0
+#define PSSIZE 0x000f8100
+#define PPSIZE 0x000f8110
+#define BARPS 0x000f8120
+#define BARPP 0x000f8130
+#define PSBAR 0x000f8140
+#define PPBAR 0x000f8150
+#define BPMDLK 0x000f8200 /* Bottom of Peripheral Memory Space */
+#define TPMDLK 0x000f8210 /* Top of Peripheral Memory Space */
+#define BIODLK 0x000f8220 /* Bottom of Peripheral I/O Space */
+#define TIODLK 0x000f8230 /* Top of Perioheral I/O Space */
+#define DLKCTRL 0x000f8240 /* Deadlock control */
+#define DLKDEV 0x000f8250 /* Deadlock device */
+
+/* System standard configuration registers space */
+#define DCR 0xff200000
+#define DID 0xff200004
+#define BAR 0xff200018
+
+/* Device specific configuration space */
+#define PCIENB 0xff201000
+
+/* Configuration space registers */
+#define CPC710_BUS_NUMBER 0x40
+#define CPC710_SUB_BUS_NUMBER 0x41
+
+#endif /* __PPC_PLATFORMS_CPC710_H */
diff --git a/arch/ppc/syslib/cpm2_common.c b/arch/ppc/syslib/cpm2_common.c
new file mode 100644
index 0000000..ea5e770
--- /dev/null
+++ b/arch/ppc/syslib/cpm2_common.c
@@ -0,0 +1,198 @@
+/*
+ * General Purpose functions for the global management of the
+ * 8260 Communication Processor Module.
+ * Copyright (c) 1999 Dan Malek (dmalek@jlc.net)
+ * Copyright (c) 2000 MontaVista Software, Inc (source@mvista.com)
+ * 2.3.99 Updates
+ *
+ * In addition to the individual control of the communication
+ * channels, there are a few functions that globally affect the
+ * communication processor.
+ *
+ * Buffer descriptors must be allocated from the dual ported memory
+ * space. The allocator for that is here. When the communication
+ * process is reset, we reclaim the memory available. There is
+ * currently no deallocator for this memory.
+ */
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/param.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/interrupt.h>
+#include <linux/bootmem.h>
+#include <linux/module.h>
+#include <asm/irq.h>
+#include <asm/mpc8260.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <asm/immap_cpm2.h>
+#include <asm/cpm2.h>
+#include <asm/rheap.h>
+
+static void cpm2_dpinit(void);
+cpm_cpm2_t *cpmp; /* Pointer to comm processor space */
+
+/* We allocate this here because it is used almost exclusively for
+ * the communication processor devices.
+ */
+cpm2_map_t *cpm2_immr;
+
+#define CPM_MAP_SIZE (0x40000) /* 256k - the PQ3 reserve this amount
+ of space for CPM as it is larger
+ than on PQ2 */
+
+void
+cpm2_reset(void)
+{
+ cpm2_immr = (cpm2_map_t *)ioremap(CPM_MAP_ADDR, CPM_MAP_SIZE);
+
+ /* Reclaim the DP memory for our use.
+ */
+ cpm2_dpinit();
+
+ /* Tell everyone where the comm processor resides.
+ */
+ cpmp = &cpm2_immr->im_cpm;
+}
+
+/* Set a baud rate generator. This needs lots of work. There are
+ * eight BRGs, which can be connected to the CPM channels or output
+ * as clocks. The BRGs are in two different block of internal
+ * memory mapped space.
+ * The baud rate clock is the system clock divided by something.
+ * It was set up long ago during the initial boot phase and is
+ * is given to us.
+ * Baud rate clocks are zero-based in the driver code (as that maps
+ * to port numbers). Documentation uses 1-based numbering.
+ */
+#define BRG_INT_CLK (((bd_t *)__res)->bi_brgfreq)
+#define BRG_UART_CLK (BRG_INT_CLK/16)
+
+/* This function is used by UARTS, or anything else that uses a 16x
+ * oversampled clock.
+ */
+void
+cpm_setbrg(uint brg, uint rate)
+{
+ volatile uint *bp;
+
+ /* This is good enough to get SMCs running.....
+ */
+ if (brg < 4) {
+ bp = (uint *)&cpm2_immr->im_brgc1;
+ }
+ else {
+ bp = (uint *)&cpm2_immr->im_brgc5;
+ brg -= 4;
+ }
+ bp += brg;
+ *bp = ((BRG_UART_CLK / rate) << 1) | CPM_BRG_EN;
+}
+
+/* This function is used to set high speed synchronous baud rate
+ * clocks.
+ */
+void
+cpm2_fastbrg(uint brg, uint rate, int div16)
+{
+ volatile uint *bp;
+
+ if (brg < 4) {
+ bp = (uint *)&cpm2_immr->im_brgc1;
+ }
+ else {
+ bp = (uint *)&cpm2_immr->im_brgc5;
+ brg -= 4;
+ }
+ bp += brg;
+ *bp = ((BRG_INT_CLK / rate) << 1) | CPM_BRG_EN;
+ if (div16)
+ *bp |= CPM_BRG_DIV16;
+}
+
+/*
+ * dpalloc / dpfree bits.
+ */
+static spinlock_t cpm_dpmem_lock;
+/* 16 blocks should be enough to satisfy all requests
+ * until the memory subsystem goes up... */
+static rh_block_t cpm_boot_dpmem_rh_block[16];
+static rh_info_t cpm_dpmem_info;
+
+static void cpm2_dpinit(void)
+{
+ spin_lock_init(&cpm_dpmem_lock);
+
+ /* initialize the info header */
+ rh_init(&cpm_dpmem_info, 1,
+ sizeof(cpm_boot_dpmem_rh_block) /
+ sizeof(cpm_boot_dpmem_rh_block[0]),
+ cpm_boot_dpmem_rh_block);
+
+ /* Attach the usable dpmem area */
+ /* XXX: This is actually crap. CPM_DATAONLY_BASE and
+ * CPM_DATAONLY_SIZE is only a subset of the available dpram. It
+ * varies with the processor and the microcode patches activated.
+ * But the following should be at least safe.
+ */
+ rh_attach_region(&cpm_dpmem_info, (void *)CPM_DATAONLY_BASE,
+ CPM_DATAONLY_SIZE);
+}
+
+/* This function returns an index into the DPRAM area.
+ */
+uint cpm_dpalloc(uint size, uint align)
+{
+ void *start;
+ unsigned long flags;
+
+ spin_lock_irqsave(&cpm_dpmem_lock, flags);
+ cpm_dpmem_info.alignment = align;
+ start = rh_alloc(&cpm_dpmem_info, size, "commproc");
+ spin_unlock_irqrestore(&cpm_dpmem_lock, flags);
+
+ return (uint)start;
+}
+EXPORT_SYMBOL(cpm_dpalloc);
+
+int cpm_dpfree(uint offset)
+{
+ int ret;
+ unsigned long flags;
+
+ spin_lock_irqsave(&cpm_dpmem_lock, flags);
+ ret = rh_free(&cpm_dpmem_info, (void *)offset);
+ spin_unlock_irqrestore(&cpm_dpmem_lock, flags);
+
+ return ret;
+}
+EXPORT_SYMBOL(cpm_dpfree);
+
+/* not sure if this is ever needed */
+uint cpm_dpalloc_fixed(uint offset, uint size, uint align)
+{
+ void *start;
+ unsigned long flags;
+
+ spin_lock_irqsave(&cpm_dpmem_lock, flags);
+ cpm_dpmem_info.alignment = align;
+ start = rh_alloc_fixed(&cpm_dpmem_info, (void *)offset, size, "commproc");
+ spin_unlock_irqrestore(&cpm_dpmem_lock, flags);
+
+ return (uint)start;
+}
+EXPORT_SYMBOL(cpm_dpalloc_fixed);
+
+void cpm_dpdump(void)
+{
+ rh_dump(&cpm_dpmem_info);
+}
+EXPORT_SYMBOL(cpm_dpdump);
+
+void *cpm_dpram_addr(uint offset)
+{
+ return (void *)&cpm2_immr->im_dprambase[offset];
+}
+EXPORT_SYMBOL(cpm_dpram_addr);
diff --git a/arch/ppc/syslib/cpm2_pic.c b/arch/ppc/syslib/cpm2_pic.c
new file mode 100644
index 0000000..954b07f
--- /dev/null
+++ b/arch/ppc/syslib/cpm2_pic.c
@@ -0,0 +1,172 @@
+/* The CPM2 internal interrupt controller. It is usually
+ * the only interrupt controller.
+ * There are two 32-bit registers (high/low) for up to 64
+ * possible interrupts.
+ *
+ * Now, the fun starts.....Interrupt Numbers DO NOT MAP
+ * in a simple arithmetic fashion to mask or pending registers.
+ * That is, interrupt 4 does not map to bit position 4.
+ * We create two tables, indexed by vector number, to indicate
+ * which register to use and which bit in the register to use.
+ */
+
+#include <linux/stddef.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/signal.h>
+#include <linux/irq.h>
+
+#include <asm/immap_cpm2.h>
+#include <asm/mpc8260.h>
+
+#include "cpm2_pic.h"
+
+static u_char irq_to_siureg[] = {
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+/* bit numbers do not match the docs, these are precomputed so the bit for
+ * a given irq is (1 << irq_to_siubit[irq]) */
+static u_char irq_to_siubit[] = {
+ 0, 15, 14, 13, 12, 11, 10, 9,
+ 8, 7, 6, 5, 4, 3, 2, 1,
+ 2, 1, 15, 14, 13, 12, 11, 10,
+ 9, 8, 7, 6, 5, 4, 3, 0,
+ 31, 30, 29, 28, 27, 26, 25, 24,
+ 23, 22, 21, 20, 19, 18, 17, 16,
+ 16, 17, 18, 19, 20, 21, 22, 23,
+ 24, 25, 26, 27, 28, 29, 30, 31,
+};
+
+static void cpm2_mask_irq(unsigned int irq_nr)
+{
+ int bit, word;
+ volatile uint *simr;
+
+ irq_nr -= CPM_IRQ_OFFSET;
+
+ bit = irq_to_siubit[irq_nr];
+ word = irq_to_siureg[irq_nr];
+
+ simr = &(cpm2_immr->im_intctl.ic_simrh);
+ ppc_cached_irq_mask[word] &= ~(1 << bit);
+ simr[word] = ppc_cached_irq_mask[word];
+}
+
+static void cpm2_unmask_irq(unsigned int irq_nr)
+{
+ int bit, word;
+ volatile uint *simr;
+
+ irq_nr -= CPM_IRQ_OFFSET;
+
+ bit = irq_to_siubit[irq_nr];
+ word = irq_to_siureg[irq_nr];
+
+ simr = &(cpm2_immr->im_intctl.ic_simrh);
+ ppc_cached_irq_mask[word] |= 1 << bit;
+ simr[word] = ppc_cached_irq_mask[word];
+}
+
+static void cpm2_mask_and_ack(unsigned int irq_nr)
+{
+ int bit, word;
+ volatile uint *simr, *sipnr;
+
+ irq_nr -= CPM_IRQ_OFFSET;
+
+ bit = irq_to_siubit[irq_nr];
+ word = irq_to_siureg[irq_nr];
+
+ simr = &(cpm2_immr->im_intctl.ic_simrh);
+ sipnr = &(cpm2_immr->im_intctl.ic_sipnrh);
+ ppc_cached_irq_mask[word] &= ~(1 << bit);
+ simr[word] = ppc_cached_irq_mask[word];
+ sipnr[word] = 1 << bit;
+}
+
+static void cpm2_end_irq(unsigned int irq_nr)
+{
+ int bit, word;
+ volatile uint *simr;
+
+ if (!(irq_desc[irq_nr].status & (IRQ_DISABLED|IRQ_INPROGRESS))
+ && irq_desc[irq_nr].action) {
+
+ irq_nr -= CPM_IRQ_OFFSET;
+ bit = irq_to_siubit[irq_nr];
+ word = irq_to_siureg[irq_nr];
+
+ simr = &(cpm2_immr->im_intctl.ic_simrh);
+ ppc_cached_irq_mask[word] |= 1 << bit;
+ simr[word] = ppc_cached_irq_mask[word];
+ }
+}
+
+static struct hw_interrupt_type cpm2_pic = {
+ .typename = " CPM2 SIU ",
+ .enable = cpm2_unmask_irq,
+ .disable = cpm2_mask_irq,
+ .ack = cpm2_mask_and_ack,
+ .end = cpm2_end_irq,
+};
+
+int cpm2_get_irq(struct pt_regs *regs)
+{
+ int irq;
+ unsigned long bits;
+
+ /* For CPM2, read the SIVEC register and shift the bits down
+ * to get the irq number. */
+ bits = cpm2_immr->im_intctl.ic_sivec;
+ irq = bits >> 26;
+
+ if (irq == 0)
+ return(-1);
+ return irq+CPM_IRQ_OFFSET;
+}
+
+void cpm2_init_IRQ(void)
+{
+ int i;
+
+ /* Clear the CPM IRQ controller, in case it has any bits set
+ * from the bootloader
+ */
+
+ /* Mask out everything */
+ cpm2_immr->im_intctl.ic_simrh = 0x00000000;
+ cpm2_immr->im_intctl.ic_simrl = 0x00000000;
+ wmb();
+
+ /* Ack everything */
+ cpm2_immr->im_intctl.ic_sipnrh = 0xffffffff;
+ cpm2_immr->im_intctl.ic_sipnrl = 0xffffffff;
+ wmb();
+
+ /* Dummy read of the vector */
+ i = cpm2_immr->im_intctl.ic_sivec;
+ rmb();
+
+ /* Initialize the default interrupt mapping priorities,
+ * in case the boot rom changed something on us.
+ */
+ cpm2_immr->im_intctl.ic_sicr = 0;
+ cpm2_immr->im_intctl.ic_scprrh = 0x05309770;
+ cpm2_immr->im_intctl.ic_scprrl = 0x05309770;
+
+
+ /* Enable chaining to OpenPIC, and make everything level
+ */
+ for (i = 0; i < NR_CPM_INTS; i++) {
+ irq_desc[i+CPM_IRQ_OFFSET].handler = &cpm2_pic;
+ irq_desc[i+CPM_IRQ_OFFSET].status |= IRQ_LEVEL;
+ }
+}
diff --git a/arch/ppc/syslib/cpm2_pic.h b/arch/ppc/syslib/cpm2_pic.h
new file mode 100644
index 0000000..97cab8f
--- /dev/null
+++ b/arch/ppc/syslib/cpm2_pic.h
@@ -0,0 +1,8 @@
+#ifndef _PPC_KERNEL_CPM2_H
+#define _PPC_KERNEL_CPM2_H
+
+extern int cpm2_get_irq(struct pt_regs *regs);
+
+extern void cpm2_init_IRQ(void);
+
+#endif /* _PPC_KERNEL_CPM2_H */
diff --git a/arch/ppc/syslib/dcr.S b/arch/ppc/syslib/dcr.S
new file mode 100644
index 0000000..895f102
--- /dev/null
+++ b/arch/ppc/syslib/dcr.S
@@ -0,0 +1,41 @@
+/*
+ * arch/ppc/syslib/dcr.S
+ *
+ * "Indirect" DCR access
+ *
+ * Copyright (c) 2004 Eugene Surovegin <ebs@ebshome.net>
+ *
+ * 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.
+ */
+
+#include <asm/ppc_asm.h>
+#include <asm/processor.h>
+
+#define DCR_ACCESS_PROLOG(table) \
+ rlwinm r3,r3,4,18,27; \
+ lis r5,table@h; \
+ ori r5,r5,table@l; \
+ add r3,r3,r5; \
+ mtctr r3; \
+ bctr
+
+_GLOBAL(__mfdcr)
+ DCR_ACCESS_PROLOG(__mfdcr_table)
+
+_GLOBAL(__mtdcr)
+ DCR_ACCESS_PROLOG(__mtdcr_table)
+
+__mfdcr_table:
+ mfdcr r3,0; blr
+__mtdcr_table:
+ mtdcr 0,r4; blr
+
+dcr = 1
+ .rept 1023
+ mfdcr r3,dcr; blr
+ mtdcr dcr,r4; blr
+ dcr = dcr + 1
+ .endr
diff --git a/arch/ppc/syslib/gen550.h b/arch/ppc/syslib/gen550.h
new file mode 100644
index 0000000..039d249
--- /dev/null
+++ b/arch/ppc/syslib/gen550.h
@@ -0,0 +1,16 @@
+/*
+ * arch/ppc/syslib/gen550.h
+ *
+ * gen550 prototypes
+ *
+ * Matt Porter <mporter@kernel.crashing.org>
+ *
+ * 2004 (c) MontaVista Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+
+extern void gen550_progress(char *, unsigned short);
+extern void gen550_init(int, struct uart_port *);
+extern void gen550_kgdb_map_scc(void);
diff --git a/arch/ppc/syslib/gen550_dbg.c b/arch/ppc/syslib/gen550_dbg.c
new file mode 100644
index 0000000..9ef0113
--- /dev/null
+++ b/arch/ppc/syslib/gen550_dbg.c
@@ -0,0 +1,182 @@
+/*
+ * arch/ppc/syslib/gen550_dbg.c
+ *
+ * A library of polled 16550 serial routines. These are intended to
+ * be used to support progress messages, xmon, kgdb, etc. on a
+ * variety of platforms.
+ *
+ * Adapted from lots of code ripped from the arch/ppc/boot/ polled
+ * 16550 support.
+ *
+ * Author: Matt Porter <mporter@mvista.com>
+ *
+ * 2002-2003 (c) MontaVista Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/serial.h>
+#include <linux/tty.h> /* For linux/serial_core.h */
+#include <linux/serial_core.h>
+#include <linux/serialP.h>
+#include <linux/serial_reg.h>
+#include <asm/machdep.h>
+#include <asm/serial.h>
+#include <asm/io.h>
+
+#define SERIAL_BAUD 9600
+
+/* SERIAL_PORT_DFNS is defined in <asm/serial.h> */
+#ifndef SERIAL_PORT_DFNS
+#define SERIAL_PORT_DFNS
+#endif
+
+static struct serial_state rs_table[RS_TABLE_SIZE] = {
+ SERIAL_PORT_DFNS /* defined in <asm/serial.h> */
+};
+
+static void (*serial_outb)(unsigned long, unsigned char);
+static unsigned long (*serial_inb)(unsigned long);
+
+static int shift;
+
+unsigned long direct_inb(unsigned long addr)
+{
+ return readb((void __iomem *)addr);
+}
+
+void direct_outb(unsigned long addr, unsigned char val)
+{
+ writeb(val, (void __iomem *)addr);
+}
+
+unsigned long io_inb(unsigned long port)
+{
+ return inb(port);
+}
+
+void io_outb(unsigned long port, unsigned char val)
+{
+ outb(val, port);
+}
+
+unsigned long serial_init(int chan, void *ignored)
+{
+ unsigned long com_port;
+ unsigned char lcr, dlm;
+
+ /* We need to find out which type io we're expecting. If it's
+ * 'SERIAL_IO_PORT', we get an offset from the isa_io_base.
+ * If it's 'SERIAL_IO_MEM', we can the exact location. -- Tom */
+ switch (rs_table[chan].io_type) {
+ case SERIAL_IO_PORT:
+ com_port = rs_table[chan].port;
+ serial_outb = io_outb;
+ serial_inb = io_inb;
+ break;
+ case SERIAL_IO_MEM:
+ com_port = (unsigned long)rs_table[chan].iomem_base;
+ serial_outb = direct_outb;
+ serial_inb = direct_inb;
+ break;
+ default:
+ /* We can't deal with it. */
+ return -1;
+ }
+
+ /* How far apart the registers are. */
+ shift = rs_table[chan].iomem_reg_shift;
+
+ /* save the LCR */
+ lcr = serial_inb(com_port + (UART_LCR << shift));
+
+ /* Access baud rate */
+ serial_outb(com_port + (UART_LCR << shift), UART_LCR_DLAB);
+ dlm = serial_inb(com_port + (UART_DLM << shift));
+
+ /*
+ * Test if serial port is unconfigured
+ * We assume that no-one uses less than 110 baud or
+ * less than 7 bits per character these days.
+ * -- paulus.
+ */
+ if ((dlm <= 4) && (lcr & 2)) {
+ /* port is configured, put the old LCR back */
+ serial_outb(com_port + (UART_LCR << shift), lcr);
+ }
+ else {
+ /* Input clock. */
+ serial_outb(com_port + (UART_DLL << shift),
+ (rs_table[chan].baud_base / SERIAL_BAUD) & 0xFF);
+ serial_outb(com_port + (UART_DLM << shift),
+ (rs_table[chan].baud_base / SERIAL_BAUD) >> 8);
+ /* 8 data, 1 stop, no parity */
+ serial_outb(com_port + (UART_LCR << shift), 0x03);
+ /* RTS/DTR */
+ serial_outb(com_port + (UART_MCR << shift), 0x03);
+
+ /* Clear & enable FIFOs */
+ serial_outb(com_port + (UART_FCR << shift), 0x07);
+ }
+
+ return (com_port);
+}
+
+void
+serial_putc(unsigned long com_port, unsigned char c)
+{
+ while ((serial_inb(com_port + (UART_LSR << shift)) & UART_LSR_THRE) == 0)
+ ;
+ serial_outb(com_port, c);
+}
+
+unsigned char
+serial_getc(unsigned long com_port)
+{
+ while ((serial_inb(com_port + (UART_LSR << shift)) & UART_LSR_DR) == 0)
+ ;
+ return serial_inb(com_port);
+}
+
+int
+serial_tstc(unsigned long com_port)
+{
+ return ((serial_inb(com_port + (UART_LSR << shift)) & UART_LSR_DR) != 0);
+}
+
+void
+serial_close(unsigned long com_port)
+{
+}
+
+void
+gen550_init(int i, struct uart_port *serial_req)
+{
+ rs_table[i].io_type = serial_req->iotype;
+ rs_table[i].port = serial_req->iobase;
+ rs_table[i].iomem_base = serial_req->membase;
+ rs_table[i].iomem_reg_shift = serial_req->regshift;
+ rs_table[i].baud_base = serial_req->uartclk ? serial_req->uartclk / 16 : BASE_BAUD;
+}
+
+#ifdef CONFIG_SERIAL_TEXT_DEBUG
+void
+gen550_progress(char *s, unsigned short hex)
+{
+ volatile unsigned int progress_debugport;
+ volatile char c;
+
+ progress_debugport = serial_init(0, NULL);
+
+ serial_putc(progress_debugport, '\r');
+
+ while ((c = *s++) != 0)
+ serial_putc(progress_debugport, c);
+
+ serial_putc(progress_debugport, '\n');
+ serial_putc(progress_debugport, '\r');
+}
+#endif /* CONFIG_SERIAL_TEXT_DEBUG */
diff --git a/arch/ppc/syslib/gen550_kgdb.c b/arch/ppc/syslib/gen550_kgdb.c
new file mode 100644
index 0000000..7239d5d
--- /dev/null
+++ b/arch/ppc/syslib/gen550_kgdb.c
@@ -0,0 +1,86 @@
+/*
+ * arch/ppc/syslib/gen550_kgdb.c
+ *
+ * Generic 16550 kgdb support intended to be useful on a variety
+ * of platforms. To enable this support, it is necessary to set
+ * the CONFIG_GEN550 option. Any virtual mapping of the serial
+ * port(s) to be used can be accomplished by setting
+ * ppc_md.early_serial_map to a platform-specific mapping function.
+ *
+ * Adapted from ppc4xx_kgdb.c.
+ *
+ * Author: Matt Porter <mporter@kernel.crashing.org>
+ *
+ * 2002-2004 (c) MontaVista Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+
+#include <asm/machdep.h>
+
+extern unsigned long serial_init(int, void *);
+extern unsigned long serial_getc(unsigned long);
+extern unsigned long serial_putc(unsigned long, unsigned char);
+
+#if defined(CONFIG_KGDB_TTYS0)
+#define KGDB_PORT 0
+#elif defined(CONFIG_KGDB_TTYS1)
+#define KGDB_PORT 1
+#elif defined(CONFIG_KGDB_TTYS2)
+#define KGDB_PORT 2
+#elif defined(CONFIG_KGDB_TTYS3)
+#define KGDB_PORT 3
+#else
+#error "invalid kgdb_tty port"
+#endif
+
+static volatile unsigned int kgdb_debugport;
+
+void putDebugChar(unsigned char c)
+{
+ if (kgdb_debugport == 0)
+ kgdb_debugport = serial_init(KGDB_PORT, NULL);
+
+ serial_putc(kgdb_debugport, c);
+}
+
+int getDebugChar(void)
+{
+ if (kgdb_debugport == 0)
+ kgdb_debugport = serial_init(KGDB_PORT, NULL);
+
+ return(serial_getc(kgdb_debugport));
+}
+
+void kgdb_interruptible(int enable)
+{
+ return;
+}
+
+void putDebugString(char* str)
+{
+ while (*str != '\0') {
+ putDebugChar(*str);
+ str++;
+ }
+ putDebugChar('\r');
+ return;
+}
+
+/*
+ * Note: gen550_init() must be called already on the port we are going
+ * to use.
+ */
+void
+gen550_kgdb_map_scc(void)
+{
+ printk(KERN_DEBUG "kgdb init\n");
+ if (ppc_md.early_serial_map)
+ ppc_md.early_serial_map();
+ kgdb_debugport = serial_init(KGDB_PORT, NULL);
+}
diff --git a/arch/ppc/syslib/gt64260_pic.c b/arch/ppc/syslib/gt64260_pic.c
new file mode 100644
index 0000000..44aa873
--- /dev/null
+++ b/arch/ppc/syslib/gt64260_pic.c
@@ -0,0 +1,328 @@
+/*
+ * arch/ppc/syslib/gt64260_pic.c
+ *
+ * Interrupt controller support for Galileo's GT64260.
+ *
+ * Author: Chris Zankel <source@mvista.com>
+ * Modified by: Mark A. Greer <mgreer@mvista.com>
+ *
+ * Based on sources from Rabeeh Khoury / Galileo Technology
+ *
+ * 2001 (c) MontaVista, Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+
+/*
+ * This file contains the specific functions to support the GT64260
+ * interrupt controller.
+ *
+ * The GT64260 has two main interrupt registers (high and low) that
+ * summarizes the interrupts generated by the units of the GT64260.
+ * Each bit is assigned to an interrupt number, where the low register
+ * are assigned from IRQ0 to IRQ31 and the high cause register
+ * from IRQ32 to IRQ63
+ * The GPP (General Purpose Port) interrupts are assigned from IRQ64 (GPP0)
+ * to IRQ95 (GPP31).
+ * get_irq() returns the lowest interrupt number that is currently asserted.
+ *
+ * Note:
+ * - This driver does not initialize the GPP when used as an interrupt
+ * input.
+ */
+
+#include <linux/stddef.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/sched.h>
+#include <linux/signal.h>
+#include <linux/stddef.h>
+#include <linux/delay.h>
+#include <linux/irq.h>
+
+#include <asm/io.h>
+#include <asm/system.h>
+#include <asm/irq.h>
+#include <asm/mv64x60.h>
+
+#define CPU_INTR_STR "gt64260 cpu interface error"
+#define PCI0_INTR_STR "gt64260 pci 0 error"
+#define PCI1_INTR_STR "gt64260 pci 1 error"
+
+/* ========================== forward declaration ========================== */
+
+static void gt64260_unmask_irq(unsigned int);
+static void gt64260_mask_irq(unsigned int);
+
+/* ========================== local declarations =========================== */
+
+struct hw_interrupt_type gt64260_pic = {
+ .typename = " gt64260_pic ",
+ .enable = gt64260_unmask_irq,
+ .disable = gt64260_mask_irq,
+ .ack = gt64260_mask_irq,
+ .end = gt64260_unmask_irq,
+};
+
+u32 gt64260_irq_base = 0; /* GT64260 handles the next 96 IRQs from here */
+
+static struct mv64x60_handle bh;
+
+/* gt64260_init_irq()
+ *
+ * This function initializes the interrupt controller. It assigns
+ * all interrupts from IRQ0 to IRQ95 to the gt64260 interrupt controller.
+ *
+ * Note:
+ * We register all GPP inputs as interrupt source, but disable them.
+ */
+void __init
+gt64260_init_irq(void)
+{
+ int i;
+
+ if (ppc_md.progress)
+ ppc_md.progress("gt64260_init_irq: enter", 0x0);
+
+ bh.v_base = mv64x60_get_bridge_vbase();
+
+ ppc_cached_irq_mask[0] = 0;
+ ppc_cached_irq_mask[1] = 0x0f000000; /* Enable GPP intrs */
+ ppc_cached_irq_mask[2] = 0;
+
+ /* disable all interrupts and clear current interrupts */
+ mv64x60_write(&bh, MV64x60_GPP_INTR_MASK, ppc_cached_irq_mask[2]);
+ mv64x60_write(&bh, MV64x60_GPP_INTR_CAUSE, 0);
+ mv64x60_write(&bh, GT64260_IC_CPU_INTR_MASK_LO, ppc_cached_irq_mask[0]);
+ mv64x60_write(&bh, GT64260_IC_CPU_INTR_MASK_HI, ppc_cached_irq_mask[1]);
+
+ /* use the gt64260 for all (possible) interrupt sources */
+ for (i = gt64260_irq_base; i < (gt64260_irq_base + 96); i++)
+ irq_desc[i].handler = >64260_pic;
+
+ if (ppc_md.progress)
+ ppc_md.progress("gt64260_init_irq: exit", 0x0);
+}
+
+/*
+ * gt64260_get_irq()
+ *
+ * This function returns the lowest interrupt number of all interrupts that
+ * are currently asserted.
+ *
+ * Input Variable(s):
+ * struct pt_regs* not used
+ *
+ * Output Variable(s):
+ * None.
+ *
+ * Returns:
+ * int <interrupt number> or -2 (bogus interrupt)
+ */
+int
+gt64260_get_irq(struct pt_regs *regs)
+{
+ int irq;
+ int irq_gpp;
+
+ irq = mv64x60_read(&bh, GT64260_IC_MAIN_CAUSE_LO);
+ irq = __ilog2((irq & 0x3dfffffe) & ppc_cached_irq_mask[0]);
+
+ if (irq == -1) {
+ irq = mv64x60_read(&bh, GT64260_IC_MAIN_CAUSE_HI);
+ irq = __ilog2((irq & 0x0f000db7) & ppc_cached_irq_mask[1]);
+
+ if (irq == -1)
+ irq = -2; /* bogus interrupt, should never happen */
+ else {
+ if (irq >= 24) {
+ irq_gpp = mv64x60_read(&bh,
+ MV64x60_GPP_INTR_CAUSE);
+ irq_gpp = __ilog2(irq_gpp &
+ ppc_cached_irq_mask[2]);
+
+ if (irq_gpp == -1)
+ irq = -2;
+ else {
+ irq = irq_gpp + 64;
+ mv64x60_write(&bh,
+ MV64x60_GPP_INTR_CAUSE,
+ ~(1 << (irq - 64)));
+ }
+ } else
+ irq += 32;
+ }
+ }
+
+ (void)mv64x60_read(&bh, MV64x60_GPP_INTR_CAUSE);
+
+ if (irq < 0)
+ return (irq);
+ else
+ return (gt64260_irq_base + irq);
+}
+
+/* gt64260_unmask_irq()
+ *
+ * This function enables an interrupt.
+ *
+ * Input Variable(s):
+ * unsigned int interrupt number (IRQ0...IRQ95).
+ *
+ * Output Variable(s):
+ * None.
+ *
+ * Returns:
+ * void
+ */
+static void
+gt64260_unmask_irq(unsigned int irq)
+{
+ irq -= gt64260_irq_base;
+
+ if (irq > 31)
+ if (irq > 63) /* unmask GPP irq */
+ mv64x60_write(&bh, MV64x60_GPP_INTR_MASK,
+ ppc_cached_irq_mask[2] |= (1 << (irq - 64)));
+ else /* mask high interrupt register */
+ mv64x60_write(&bh, GT64260_IC_CPU_INTR_MASK_HI,
+ ppc_cached_irq_mask[1] |= (1 << (irq - 32)));
+ else /* mask low interrupt register */
+ mv64x60_write(&bh, GT64260_IC_CPU_INTR_MASK_LO,
+ ppc_cached_irq_mask[0] |= (1 << irq));
+
+ (void)mv64x60_read(&bh, MV64x60_GPP_INTR_MASK);
+ return;
+}
+
+/* gt64260_mask_irq()
+ *
+ * This function disables the requested interrupt.
+ *
+ * Input Variable(s):
+ * unsigned int interrupt number (IRQ0...IRQ95).
+ *
+ * Output Variable(s):
+ * None.
+ *
+ * Returns:
+ * void
+ */
+static void
+gt64260_mask_irq(unsigned int irq)
+{
+ irq -= gt64260_irq_base;
+
+ if (irq > 31)
+ if (irq > 63) /* mask GPP irq */
+ mv64x60_write(&bh, MV64x60_GPP_INTR_MASK,
+ ppc_cached_irq_mask[2] &= ~(1 << (irq - 64)));
+ else /* mask high interrupt register */
+ mv64x60_write(&bh, GT64260_IC_CPU_INTR_MASK_HI,
+ ppc_cached_irq_mask[1] &= ~(1 << (irq - 32)));
+ else /* mask low interrupt register */
+ mv64x60_write(&bh, GT64260_IC_CPU_INTR_MASK_LO,
+ ppc_cached_irq_mask[0] &= ~(1 << irq));
+
+ (void)mv64x60_read(&bh, MV64x60_GPP_INTR_MASK);
+ return;
+}
+
+static irqreturn_t
+gt64260_cpu_error_int_handler(int irq, void *dev_id, struct pt_regs *regs)
+{
+ printk(KERN_ERR "gt64260_cpu_error_int_handler: %s 0x%08x\n",
+ "Error on CPU interface - Cause regiser",
+ mv64x60_read(&bh, MV64x60_CPU_ERR_CAUSE));
+ printk(KERN_ERR "\tCPU error register dump:\n");
+ printk(KERN_ERR "\tAddress low 0x%08x\n",
+ mv64x60_read(&bh, MV64x60_CPU_ERR_ADDR_LO));
+ printk(KERN_ERR "\tAddress high 0x%08x\n",
+ mv64x60_read(&bh, MV64x60_CPU_ERR_ADDR_HI));
+ printk(KERN_ERR "\tData low 0x%08x\n",
+ mv64x60_read(&bh, MV64x60_CPU_ERR_DATA_LO));
+ printk(KERN_ERR "\tData high 0x%08x\n",
+ mv64x60_read(&bh, MV64x60_CPU_ERR_DATA_HI));
+ printk(KERN_ERR "\tParity 0x%08x\n",
+ mv64x60_read(&bh, MV64x60_CPU_ERR_PARITY));
+ mv64x60_write(&bh, MV64x60_CPU_ERR_CAUSE, 0);
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t
+gt64260_pci_error_int_handler(int irq, void *dev_id, struct pt_regs *regs)
+{
+ u32 val;
+ unsigned int pci_bus = (unsigned int)dev_id;
+
+ if (pci_bus == 0) { /* Error on PCI 0 */
+ val = mv64x60_read(&bh, MV64x60_PCI0_ERR_CAUSE);
+ printk(KERN_ERR "%s: Error in PCI %d Interface\n",
+ "gt64260_pci_error_int_handler", pci_bus);
+ printk(KERN_ERR "\tPCI %d error register dump:\n", pci_bus);
+ printk(KERN_ERR "\tCause register 0x%08x\n", val);
+ printk(KERN_ERR "\tAddress Low 0x%08x\n",
+ mv64x60_read(&bh, MV64x60_PCI0_ERR_ADDR_LO));
+ printk(KERN_ERR "\tAddress High 0x%08x\n",
+ mv64x60_read(&bh, MV64x60_PCI0_ERR_ADDR_HI));
+ printk(KERN_ERR "\tAttribute 0x%08x\n",
+ mv64x60_read(&bh, MV64x60_PCI0_ERR_DATA_LO));
+ printk(KERN_ERR "\tCommand 0x%08x\n",
+ mv64x60_read(&bh, MV64x60_PCI0_ERR_CMD));
+ mv64x60_write(&bh, MV64x60_PCI0_ERR_CAUSE, ~val);
+ }
+ if (pci_bus == 1) { /* Error on PCI 1 */
+ val = mv64x60_read(&bh, MV64x60_PCI1_ERR_CAUSE);
+ printk(KERN_ERR "%s: Error in PCI %d Interface\n",
+ "gt64260_pci_error_int_handler", pci_bus);
+ printk(KERN_ERR "\tPCI %d error register dump:\n", pci_bus);
+ printk(KERN_ERR "\tCause register 0x%08x\n", val);
+ printk(KERN_ERR "\tAddress Low 0x%08x\n",
+ mv64x60_read(&bh, MV64x60_PCI1_ERR_ADDR_LO));
+ printk(KERN_ERR "\tAddress High 0x%08x\n",
+ mv64x60_read(&bh, MV64x60_PCI1_ERR_ADDR_HI));
+ printk(KERN_ERR "\tAttribute 0x%08x\n",
+ mv64x60_read(&bh, MV64x60_PCI1_ERR_DATA_LO));
+ printk(KERN_ERR "\tCommand 0x%08x\n",
+ mv64x60_read(&bh, MV64x60_PCI1_ERR_CMD));
+ mv64x60_write(&bh, MV64x60_PCI1_ERR_CAUSE, ~val);
+ }
+ return IRQ_HANDLED;
+}
+
+static int __init
+gt64260_register_hdlrs(void)
+{
+ int rc;
+
+ /* Register CPU interface error interrupt handler */
+ if ((rc = request_irq(MV64x60_IRQ_CPU_ERR,
+ gt64260_cpu_error_int_handler, SA_INTERRUPT, CPU_INTR_STR, 0)))
+ printk(KERN_WARNING "Can't register cpu error handler: %d", rc);
+
+ mv64x60_write(&bh, MV64x60_CPU_ERR_MASK, 0);
+ mv64x60_write(&bh, MV64x60_CPU_ERR_MASK, 0x000000fe);
+
+ /* Register PCI 0 error interrupt handler */
+ if ((rc = request_irq(MV64360_IRQ_PCI0, gt64260_pci_error_int_handler,
+ SA_INTERRUPT, PCI0_INTR_STR, (void *)0)))
+ printk(KERN_WARNING "Can't register pci 0 error handler: %d",
+ rc);
+
+ mv64x60_write(&bh, MV64x60_PCI0_ERR_MASK, 0);
+ mv64x60_write(&bh, MV64x60_PCI0_ERR_MASK, 0x003c0c24);
+
+ /* Register PCI 1 error interrupt handler */
+ if ((rc = request_irq(MV64360_IRQ_PCI1, gt64260_pci_error_int_handler,
+ SA_INTERRUPT, PCI1_INTR_STR, (void *)1)))
+ printk(KERN_WARNING "Can't register pci 1 error handler: %d",
+ rc);
+
+ mv64x60_write(&bh, MV64x60_PCI1_ERR_MASK, 0);
+ mv64x60_write(&bh, MV64x60_PCI1_ERR_MASK, 0x003c0c24);
+
+ return 0;
+}
+
+arch_initcall(gt64260_register_hdlrs);
diff --git a/arch/ppc/syslib/harrier.c b/arch/ppc/syslib/harrier.c
new file mode 100644
index 0000000..a6b3f864
--- /dev/null
+++ b/arch/ppc/syslib/harrier.c
@@ -0,0 +1,302 @@
+/*
+ * arch/ppc/syslib/harrier.c
+ *
+ * Motorola MCG Harrier northbridge/memory controller support
+ *
+ * Author: Dale Farnsworth
+ * dale.farnsworth@mvista.com
+ *
+ * 2001 (c) MontaVista, Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/harrier_defs.h>
+
+#include <asm/byteorder.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/pci.h>
+#include <asm/pci-bridge.h>
+#include <asm/open_pic.h>
+#include <asm/harrier.h>
+
+/* define defaults for inbound windows */
+#define HARRIER_ITAT_DEFAULT (HARRIER_ITAT_ENA | \
+ HARRIER_ITAT_MEM | \
+ HARRIER_ITAT_WPE | \
+ HARRIER_ITAT_GBL)
+
+#define HARRIER_MPAT_DEFAULT (HARRIER_ITAT_ENA | \
+ HARRIER_ITAT_MEM | \
+ HARRIER_ITAT_WPE | \
+ HARRIER_ITAT_GBL)
+
+/*
+ * Initialize the inbound window size on a non-monarch harrier.
+ */
+void __init harrier_setup_nonmonarch(uint ppc_reg_base, uint in0_size)
+{
+ u16 temps;
+ u32 temp;
+
+ if (in0_size > HARRIER_ITSZ_2GB) {
+ printk
+ ("harrier_setup_nonmonarch: Invalid window size code %d\n",
+ in0_size);
+ return;
+ }
+
+ /* Clear the PCI memory enable bit. If we don't, then when the
+ * inbound windows are enabled below, the corresponding BARs will be
+ * "live" and start answering to PCI memory reads from their default
+ * addresses (0x0), which overlap with system RAM.
+ */
+ temps = in_le16((u16 *) (ppc_reg_base +
+ HARRIER_XCSR_CONFIG(PCI_COMMAND)));
+ temps &= ~(PCI_COMMAND_MEMORY);
+ out_le16((u16 *) (ppc_reg_base + HARRIER_XCSR_CONFIG(PCI_COMMAND)),
+ temps);
+
+ /* Setup a non-prefetchable inbound window */
+ out_le32((u32 *) (ppc_reg_base +
+ HARRIER_XCSR_CONFIG(HARRIER_ITSZ0_OFF)), in0_size);
+
+ temp = in_le32((u32 *) (ppc_reg_base +
+ HARRIER_XCSR_CONFIG(HARRIER_ITAT0_OFF)));
+ temp &= ~HARRIER_ITAT_PRE;
+ temp |= HARRIER_ITAT_DEFAULT;
+ out_le32((u32 *) (ppc_reg_base +
+ HARRIER_XCSR_CONFIG(HARRIER_ITAT0_OFF)), temp);
+
+ /* Enable the message passing block */
+ temp = in_le32((u32 *) (ppc_reg_base +
+ HARRIER_XCSR_CONFIG(HARRIER_MPAT_OFF)));
+ temp |= HARRIER_MPAT_DEFAULT;
+ out_le32((u32 *) (ppc_reg_base +
+ HARRIER_XCSR_CONFIG(HARRIER_MPAT_OFF)), temp);
+}
+
+void __init harrier_release_eready(uint ppc_reg_base)
+{
+ ulong temp;
+
+ /*
+ * Set EREADY to allow the line to be pulled up after everyone is
+ * ready.
+ */
+ temp = in_be32((uint *) (ppc_reg_base + HARRIER_MISC_CSR_OFF));
+ temp |= HARRIER_EREADY;
+ out_be32((uint *) (ppc_reg_base + HARRIER_MISC_CSR_OFF), temp);
+}
+
+void __init harrier_wait_eready(uint ppc_reg_base)
+{
+ ulong temp;
+
+ /*
+ * Poll the ERDYS line until it goes high to indicate that all
+ * non-monarch PrPMCs are ready for bus enumeration (or that there are
+ * no PrPMCs present).
+ */
+
+ /* FIXME: Add a timeout of some kind to prevent endless waits. */
+ do {
+
+ temp = in_be32((uint *) (ppc_reg_base + HARRIER_MISC_CSR_OFF));
+
+ } while (!(temp & HARRIER_ERDYS));
+}
+
+/*
+ * Initialize the Motorola MCG Harrier host bridge.
+ *
+ * This means setting up the PPC bus to PCI memory and I/O space mappings,
+ * setting the PCI memory space address of the MPIC (mapped straight
+ * through), and ioremap'ing the mpic registers.
+ * 'OpenPIC_Addr' will be set correctly by this routine.
+ * This routine will not change the PCI_CONFIG_ADDR or PCI_CONFIG_DATA
+ * addresses and assumes that the mapping of PCI memory space back to system
+ * memory is set up correctly by PPCBug.
+ */
+int __init
+harrier_init(struct pci_controller *hose,
+ uint ppc_reg_base,
+ ulong processor_pci_mem_start,
+ ulong processor_pci_mem_end,
+ ulong processor_pci_io_start,
+ ulong processor_pci_io_end, ulong processor_mpic_base)
+{
+ uint addr, offset;
+
+ /*
+ * Some sanity checks...
+ */
+ if (((processor_pci_mem_start & 0xffff0000) != processor_pci_mem_start)
+ || ((processor_pci_io_start & 0xffff0000) !=
+ processor_pci_io_start)) {
+ printk("harrier_init: %s\n",
+ "PPC to PCI mappings must start on 64 KB boundaries");
+ return -1;
+ }
+
+ if (((processor_pci_mem_end & 0x0000ffff) != 0x0000ffff) ||
+ ((processor_pci_io_end & 0x0000ffff) != 0x0000ffff)) {
+ printk("harrier_init: PPC to PCI mappings %s\n",
+ "must end just before a 64 KB boundaries");
+ return -1;
+ }
+
+ if (((processor_pci_mem_end - processor_pci_mem_start) !=
+ (hose->mem_space.end - hose->mem_space.start)) ||
+ ((processor_pci_io_end - processor_pci_io_start) !=
+ (hose->io_space.end - hose->io_space.start))) {
+ printk("harrier_init: %s\n",
+ "PPC and PCI memory or I/O space sizes don't match");
+ return -1;
+ }
+
+ if ((processor_mpic_base & 0xfffc0000) != processor_mpic_base) {
+ printk("harrier_init: %s\n",
+ "MPIC address must start on 256 KB boundary");
+ return -1;
+ }
+
+ if ((pci_dram_offset & 0xffff0000) != pci_dram_offset) {
+ printk("harrier_init: %s\n",
+ "pci_dram_offset must be multiple of 64 KB");
+ return -1;
+ }
+
+ /*
+ * Program the OTAD/OTOF registers to set up the PCI Mem & I/O
+ * space mappings. These are the mappings going from the processor to
+ * the PCI bus.
+ *
+ * Note: Don't need to 'AND' start/end addresses with 0xffff0000
+ * because sanity check above ensures that they are properly
+ * aligned.
+ */
+
+ /* Set up PPC->PCI Mem mapping */
+ addr = processor_pci_mem_start | (processor_pci_mem_end >> 16);
+#ifdef CONFIG_HARRIER_STORE_GATHERING
+ offset = (hose->mem_space.start - processor_pci_mem_start) | 0x9a;
+#else
+ offset = (hose->mem_space.start - processor_pci_mem_start) | 0x92;
+#endif
+ out_be32((uint *) (ppc_reg_base + HARRIER_OTAD0_OFF), addr);
+ out_be32((uint *) (ppc_reg_base + HARRIER_OTOF0_OFF), offset);
+
+ /* Set up PPC->PCI I/O mapping -- Contiguous I/O space */
+ addr = processor_pci_io_start | (processor_pci_io_end >> 16);
+ offset = (hose->io_space.start - processor_pci_io_start) | 0x80;
+ out_be32((uint *) (ppc_reg_base + HARRIER_OTAD1_OFF), addr);
+ out_be32((uint *) (ppc_reg_base + HARRIER_OTOF1_OFF), offset);
+
+ /* Enable MPIC */
+ OpenPIC_Addr = (void *)processor_mpic_base;
+ addr = (processor_mpic_base >> 16) | 1;
+ out_be16((ushort *) (ppc_reg_base + HARRIER_MBAR_OFF), addr);
+ out_8((u_char *) (ppc_reg_base + HARRIER_MPIC_CSR_OFF),
+ HARRIER_MPIC_OPI_ENABLE);
+
+ return 0;
+}
+
+/*
+ * Find the amount of RAM present.
+ * This assumes that PPCBug has initialized the memory controller (SMC)
+ * on the Harrier correctly (i.e., it does no sanity checking).
+ * It also assumes that the memory base registers are set to configure the
+ * memory as contigous starting with "RAM A BASE", "RAM B BASE", etc.
+ * however, RAM base registers can be skipped (e.g. A, B, C are set,
+ * D is skipped but E is set is okay).
+ */
+#define MB (1024*1024UL)
+
+static uint harrier_size_table[] __initdata = {
+ 0 * MB, /* 0 ==> 0 MB */
+ 32 * MB, /* 1 ==> 32 MB */
+ 64 * MB, /* 2 ==> 64 MB */
+ 64 * MB, /* 3 ==> 64 MB */
+ 128 * MB, /* 4 ==> 128 MB */
+ 128 * MB, /* 5 ==> 128 MB */
+ 128 * MB, /* 6 ==> 128 MB */
+ 256 * MB, /* 7 ==> 256 MB */
+ 256 * MB, /* 8 ==> 256 MB */
+ 256 * MB, /* 9 ==> 256 MB */
+ 512 * MB, /* a ==> 512 MB */
+ 512 * MB, /* b ==> 512 MB */
+ 512 * MB, /* c ==> 512 MB */
+ 1024 * MB, /* d ==> 1024 MB */
+ 1024 * MB, /* e ==> 1024 MB */
+ 2048 * MB, /* f ==> 2048 MB */
+};
+
+/*
+ * *** WARNING: You MUST have a BAT set up to map in the XCSR regs ***
+ *
+ * Read the memory controller's registers to determine the amount of system
+ * memory. Assumes that the memory controller registers are already mapped
+ * into virtual memory--too early to use ioremap().
+ */
+unsigned long __init harrier_get_mem_size(uint xcsr_base)
+{
+ ulong last_addr;
+ int i;
+ uint vend_dev_id;
+ uint *size_table;
+ uint val;
+ uint *csrp;
+ uint size;
+ int size_table_entries;
+
+ vend_dev_id = in_be32((uint *) xcsr_base + PCI_VENDOR_ID);
+
+ if (((vend_dev_id & 0xffff0000) >> 16) != PCI_VENDOR_ID_MOTOROLA) {
+ printk("harrier_get_mem_size: %s (0x%x)\n",
+ "Not a Motorola Memory Controller", vend_dev_id);
+ return 0;
+ }
+
+ vend_dev_id &= 0x0000ffff;
+
+ if (vend_dev_id == PCI_DEVICE_ID_MOTOROLA_HARRIER) {
+ size_table = harrier_size_table;
+ size_table_entries = sizeof(harrier_size_table) /
+ sizeof(harrier_size_table[0]);
+ } else {
+ printk("harrier_get_mem_size: %s (0x%x)\n",
+ "Not a Harrier", vend_dev_id);
+ return 0;
+ }
+
+ last_addr = 0;
+
+ csrp = (uint *) (xcsr_base + HARRIER_SDBA_OFF);
+ for (i = 0; i < 8; i++) {
+ val = in_be32(csrp++);
+
+ if (val & 0x100) { /* If enabled */
+ size = val >> HARRIER_SDB_SIZE_SHIFT;
+ size &= HARRIER_SDB_SIZE_MASK;
+ if (size >= size_table_entries) {
+ break; /* Register not set correctly */
+ }
+ size = size_table[size];
+
+ val &= ~(size - 1);
+ val += size;
+
+ if (val > last_addr) {
+ last_addr = val;
+ }
+ }
+ }
+
+ return last_addr;
+}
diff --git a/arch/ppc/syslib/hawk_common.c b/arch/ppc/syslib/hawk_common.c
new file mode 100644
index 0000000..a9911dc
--- /dev/null
+++ b/arch/ppc/syslib/hawk_common.c
@@ -0,0 +1,319 @@
+/*
+ * arch/ppc/syslib/hawk_common.c
+ *
+ * Common Motorola PowerPlus Platform--really Falcon/Raven or HAWK.
+ *
+ * Author: Mark A. Greer
+ * mgreer@mvista.com
+ *
+ * 2001 (c) MontaVista, Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+
+#include <asm/byteorder.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/pci.h>
+#include <asm/pci-bridge.h>
+#include <asm/open_pic.h>
+#include <asm/hawk.h>
+
+/*
+ * The Falcon/Raven and HAWK has 4 sets of registers:
+ * 1) PPC Registers which define the mappings from PPC bus to PCI bus,
+ * etc.
+ * 2) PCI Registers which define the mappings from PCI bus to PPC bus and the
+ * MPIC base address.
+ * 3) MPIC registers.
+ * 4) System Memory Controller (SMC) registers.
+ */
+
+/*
+ * Initialize the Motorola MCG Raven or HAWK host bridge.
+ *
+ * This means setting up the PPC bus to PCI memory and I/O space mappings,
+ * setting the PCI memory space address of the MPIC (mapped straight
+ * through), and ioremap'ing the mpic registers.
+ * This routine will set the PCI_CONFIG_ADDR or PCI_CONFIG_DATA
+ * addresses based on the PCI I/O address that is passed in.
+ * 'OpenPIC_Addr' will be set correctly by this routine.
+ */
+int __init
+hawk_init(struct pci_controller *hose,
+ uint ppc_reg_base,
+ ulong processor_pci_mem_start,
+ ulong processor_pci_mem_end,
+ ulong processor_pci_io_start,
+ ulong processor_pci_io_end,
+ ulong processor_mpic_base)
+{
+ uint addr, offset;
+
+ /*
+ * Some sanity checks...
+ */
+ if (((processor_pci_mem_start&0xffff0000) != processor_pci_mem_start) ||
+ ((processor_pci_io_start &0xffff0000) != processor_pci_io_start)) {
+ printk("hawk_init: %s\n",
+ "PPC to PCI mappings must start on 64 KB boundaries");
+ return -1;
+ }
+
+ if (((processor_pci_mem_end &0x0000ffff) != 0x0000ffff) ||
+ ((processor_pci_io_end &0x0000ffff) != 0x0000ffff)) {
+ printk("hawk_init: PPC to PCI mappings %s\n",
+ "must end just before a 64 KB boundaries");
+ return -1;
+ }
+
+ if (((processor_pci_mem_end - processor_pci_mem_start) !=
+ (hose->mem_space.end - hose->mem_space.start)) ||
+ ((processor_pci_io_end - processor_pci_io_start) !=
+ (hose->io_space.end - hose->io_space.start))) {
+ printk("hawk_init: %s\n",
+ "PPC and PCI memory or I/O space sizes don't match");
+ return -1;
+ }
+
+ if ((processor_mpic_base & 0xfffc0000) != processor_mpic_base) {
+ printk("hawk_init: %s\n",
+ "MPIC address must start on 256 MB boundary");
+ return -1;
+ }
+
+ if ((pci_dram_offset & 0xffff0000) != pci_dram_offset) {
+ printk("hawk_init: %s\n",
+ "pci_dram_offset must be multiple of 64 KB");
+ return -1;
+ }
+
+ /*
+ * Disable previous PPC->PCI mappings.
+ */
+ out_be32((uint *)(ppc_reg_base + HAWK_PPC_XSOFF0_OFF), 0x00000000);
+ out_be32((uint *)(ppc_reg_base + HAWK_PPC_XSOFF1_OFF), 0x00000000);
+ out_be32((uint *)(ppc_reg_base + HAWK_PPC_XSOFF2_OFF), 0x00000000);
+ out_be32((uint *)(ppc_reg_base + HAWK_PPC_XSOFF3_OFF), 0x00000000);
+
+ /*
+ * Program the XSADD/XSOFF registers to set up the PCI Mem & I/O
+ * space mappings. These are the mappings going from the processor to
+ * the PCI bus.
+ *
+ * Note: Don't need to 'AND' start/end addresses with 0xffff0000
+ * because sanity check above ensures that they are properly
+ * aligned.
+ */
+
+ /* Set up PPC->PCI Mem mapping */
+ addr = processor_pci_mem_start | (processor_pci_mem_end >> 16);
+ offset = (hose->mem_space.start - processor_pci_mem_start) | 0xd2;
+ out_be32((uint *)(ppc_reg_base + HAWK_PPC_XSADD0_OFF), addr);
+ out_be32((uint *)(ppc_reg_base + HAWK_PPC_XSOFF0_OFF), offset);
+
+ /* Set up PPC->MPIC mapping on the bridge */
+ addr = processor_mpic_base |
+ (((processor_mpic_base + HAWK_MPIC_SIZE) >> 16) - 1);
+ /* No write posting for this PCI Mem space */
+ offset = (hose->mem_space.start - processor_pci_mem_start) | 0xc2;
+
+ out_be32((uint *)(ppc_reg_base + HAWK_PPC_XSADD1_OFF), addr);
+ out_be32((uint *)(ppc_reg_base + HAWK_PPC_XSOFF1_OFF), offset);
+
+ /* Set up PPC->PCI I/O mapping -- Contiguous I/O space */
+ addr = processor_pci_io_start | (processor_pci_io_end >> 16);
+ offset = (hose->io_space.start - processor_pci_io_start) | 0xc0;
+ out_be32((uint *)(ppc_reg_base + HAWK_PPC_XSADD3_OFF), addr);
+ out_be32((uint *)(ppc_reg_base + HAWK_PPC_XSOFF3_OFF), offset);
+
+ hose->io_base_virt = (void *)ioremap(processor_pci_io_start,
+ (processor_pci_io_end - processor_pci_io_start + 1));
+
+ /*
+ * Set up the indirect method of accessing PCI config space.
+ * The PCI config addr/data pair based on start addr of PCI I/O space.
+ */
+ setup_indirect_pci(hose,
+ processor_pci_io_start + HAWK_PCI_CONFIG_ADDR_OFF,
+ processor_pci_io_start + HAWK_PCI_CONFIG_DATA_OFF);
+
+ /*
+ * Disable previous PCI->PPC mappings.
+ */
+
+ /* XXXX Put in mappings from PCI bus to processor bus XXXX */
+
+ /*
+ * Disable MPIC response to PCI I/O space (BAR 0).
+ * Make MPIC respond to PCI Mem space at specified address.
+ * (BAR 1).
+ */
+ early_write_config_dword(hose,
+ 0,
+ PCI_DEVFN(0,0),
+ PCI_BASE_ADDRESS_0,
+ 0x00000000 | 0x1);
+
+ early_write_config_dword(hose,
+ 0,
+ PCI_DEVFN(0,0),
+ PCI_BASE_ADDRESS_1,
+ (processor_mpic_base -
+ processor_pci_mem_start +
+ hose->mem_space.start) | 0x0);
+
+ /* Map MPIC into vitual memory */
+ OpenPIC_Addr = ioremap(processor_mpic_base, HAWK_MPIC_SIZE);
+
+ return 0;
+}
+
+/*
+ * Find the amount of RAM present.
+ * This assumes that PPCBug has initialized the memory controller (SMC)
+ * on the Falcon/HAWK correctly (i.e., it does no sanity checking).
+ * It also assumes that the memory base registers are set to configure the
+ * memory as contigous starting with "RAM A BASE", "RAM B BASE", etc.
+ * however, RAM base registers can be skipped (e.g. A, B, C are set,
+ * D is skipped but E is set is okay).
+ */
+#define MB (1024*1024)
+
+static uint reg_offset_table[] __initdata = {
+ HAWK_SMC_RAM_A_SIZE_REG_OFF,
+ HAWK_SMC_RAM_B_SIZE_REG_OFF,
+ HAWK_SMC_RAM_C_SIZE_REG_OFF,
+ HAWK_SMC_RAM_D_SIZE_REG_OFF,
+ HAWK_SMC_RAM_E_SIZE_REG_OFF,
+ HAWK_SMC_RAM_F_SIZE_REG_OFF,
+ HAWK_SMC_RAM_G_SIZE_REG_OFF,
+ HAWK_SMC_RAM_H_SIZE_REG_OFF
+};
+
+static uint falcon_size_table[] __initdata = {
+ 0 * MB, /* 0 ==> 0 MB */
+ 16 * MB, /* 1 ==> 16 MB */
+ 32 * MB, /* 2 ==> 32 MB */
+ 64 * MB, /* 3 ==> 64 MB */
+ 128 * MB, /* 4 ==> 128 MB */
+ 256 * MB, /* 5 ==> 256 MB */
+ 1024 * MB, /* 6 ==> 1024 MB (1 GB) */
+};
+
+static uint hawk_size_table[] __initdata = {
+ 0 * MB, /* 0 ==> 0 MB */
+ 32 * MB, /* 1 ==> 32 MB */
+ 64 * MB, /* 2 ==> 64 MB */
+ 64 * MB, /* 3 ==> 64 MB */
+ 128 * MB, /* 4 ==> 128 MB */
+ 128 * MB, /* 5 ==> 128 MB */
+ 128 * MB, /* 6 ==> 128 MB */
+ 256 * MB, /* 7 ==> 256 MB */
+ 256 * MB, /* 8 ==> 256 MB */
+ 512 * MB, /* 9 ==> 512 MB */
+};
+
+/*
+ * *** WARNING: You MUST have a BAT set up to map in the SMC regs ***
+ *
+ * Read the memory controller's registers to determine the amount of system
+ * memory. Assumes that the memory controller registers are already mapped
+ * into virtual memory--too early to use ioremap().
+ */
+unsigned long __init
+hawk_get_mem_size(uint smc_base)
+{
+ unsigned long total;
+ int i, size_table_entries, reg_limit;
+ uint vend_dev_id;
+ uint *size_table;
+ u_char val;
+
+
+ vend_dev_id = in_be32((uint *)smc_base + PCI_VENDOR_ID);
+
+ if (((vend_dev_id & 0xffff0000) >> 16) != PCI_VENDOR_ID_MOTOROLA) {
+ printk("hawk_get_mem_size: %s (0x%x)\n",
+ "Not a Motorola Memory Controller", vend_dev_id);
+ return 0;
+ }
+
+ vend_dev_id &= 0x0000ffff;
+
+ if (vend_dev_id == PCI_DEVICE_ID_MOTOROLA_FALCON) {
+ size_table = falcon_size_table;
+ size_table_entries = sizeof(falcon_size_table) /
+ sizeof(falcon_size_table[0]);
+
+ reg_limit = FALCON_SMC_REG_COUNT;
+ }
+ else if (vend_dev_id == PCI_DEVICE_ID_MOTOROLA_HAWK) {
+ size_table = hawk_size_table;
+ size_table_entries = sizeof(hawk_size_table) /
+ sizeof(hawk_size_table[0]);
+ reg_limit = HAWK_SMC_REG_COUNT;
+ }
+ else {
+ printk("hawk_get_mem_size: %s (0x%x)\n",
+ "Not a Falcon or HAWK", vend_dev_id);
+ return 0;
+ }
+
+ total = 0;
+
+ /* Check every reg because PPCBug may skip some */
+ for (i=0; i<reg_limit; i++) {
+ val = in_8((u_char *)(smc_base + reg_offset_table[i]));
+
+ if (val & 0x80) { /* If enabled */
+ val &= 0x0f;
+
+ /* Don't go past end of size_table */
+ if (val < size_table_entries) {
+ total += size_table[val];
+ }
+ else { /* Register not set correctly */
+ break;
+ }
+ }
+ }
+
+ return total;
+}
+
+int __init
+hawk_mpic_init(unsigned int pci_mem_offset)
+{
+ unsigned short devid;
+ unsigned int pci_membase;
+
+ /* Check the first PCI device to see if it is a Raven or Hawk. */
+ early_read_config_word(0, 0, 0, PCI_DEVICE_ID, &devid);
+
+ switch (devid) {
+ case PCI_DEVICE_ID_MOTOROLA_RAVEN:
+ case PCI_DEVICE_ID_MOTOROLA_HAWK:
+ break;
+ default:
+ OpenPIC_Addr = NULL;
+ return 1;
+ }
+
+ /* Read the memory base register. */
+ early_read_config_dword(0, 0, 0, PCI_BASE_ADDRESS_1, &pci_membase);
+
+ if (pci_membase == 0) {
+ OpenPIC_Addr = NULL;
+ return 1;
+ }
+
+ /* Map the MPIC registers to virtual memory. */
+ OpenPIC_Addr = ioremap(pci_membase + pci_mem_offset, 0x22000);
+
+ return 0;
+}
diff --git a/arch/ppc/syslib/i8259.c b/arch/ppc/syslib/i8259.c
new file mode 100644
index 0000000..b9391e6
--- /dev/null
+++ b/arch/ppc/syslib/i8259.c
@@ -0,0 +1,211 @@
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/interrupt.h>
+#include <asm/io.h>
+#include <asm/i8259.h>
+
+static volatile unsigned char *pci_intack; /* RO, gives us the irq vector */
+
+unsigned char cached_8259[2] = { 0xff, 0xff };
+#define cached_A1 (cached_8259[0])
+#define cached_21 (cached_8259[1])
+
+static DEFINE_SPINLOCK(i8259_lock);
+
+int i8259_pic_irq_offset;
+
+/*
+ * Acknowledge the IRQ using either the PCI host bridge's interrupt
+ * acknowledge feature or poll. How i8259_init() is called determines
+ * which is called. It should be noted that polling is broken on some
+ * IBM and Motorola PReP boxes so we must use the int-ack feature on them.
+ */
+int
+i8259_irq(struct pt_regs *regs)
+{
+ int irq;
+
+ spin_lock(&i8259_lock);
+
+ /* Either int-ack or poll for the IRQ */
+ if (pci_intack)
+ irq = *pci_intack;
+ else {
+ /* Perform an interrupt acknowledge cycle on controller 1. */
+ outb(0x0C, 0x20); /* prepare for poll */
+ irq = inb(0x20) & 7;
+ if (irq == 2 ) {
+ /*
+ * Interrupt is cascaded so perform interrupt
+ * acknowledge on controller 2.
+ */
+ outb(0x0C, 0xA0); /* prepare for poll */
+ irq = (inb(0xA0) & 7) + 8;
+ }
+ }
+
+ if (irq == 7) {
+ /*
+ * This may be a spurious interrupt.
+ *
+ * Read the interrupt status register (ISR). If the most
+ * significant bit is not set then there is no valid
+ * interrupt.
+ */
+ if (!pci_intack)
+ outb(0x0B, 0x20); /* ISR register */
+ if(~inb(0x20) & 0x80)
+ irq = -1;
+ }
+
+ spin_unlock(&i8259_lock);
+ return irq;
+}
+
+static void i8259_mask_and_ack_irq(unsigned int irq_nr)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&i8259_lock, flags);
+ if ( irq_nr >= i8259_pic_irq_offset )
+ irq_nr -= i8259_pic_irq_offset;
+
+ if (irq_nr > 7) {
+ cached_A1 |= 1 << (irq_nr-8);
+ inb(0xA1); /* DUMMY */
+ outb(cached_A1,0xA1);
+ outb(0x20,0xA0); /* Non-specific EOI */
+ outb(0x20,0x20); /* Non-specific EOI to cascade */
+ } else {
+ cached_21 |= 1 << irq_nr;
+ inb(0x21); /* DUMMY */
+ outb(cached_21,0x21);
+ outb(0x20,0x20); /* Non-specific EOI */
+ }
+ spin_unlock_irqrestore(&i8259_lock, flags);
+}
+
+static void i8259_set_irq_mask(int irq_nr)
+{
+ outb(cached_A1,0xA1);
+ outb(cached_21,0x21);
+}
+
+static void i8259_mask_irq(unsigned int irq_nr)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&i8259_lock, flags);
+ if ( irq_nr >= i8259_pic_irq_offset )
+ irq_nr -= i8259_pic_irq_offset;
+ if ( irq_nr < 8 )
+ cached_21 |= 1 << irq_nr;
+ else
+ cached_A1 |= 1 << (irq_nr-8);
+ i8259_set_irq_mask(irq_nr);
+ spin_unlock_irqrestore(&i8259_lock, flags);
+}
+
+static void i8259_unmask_irq(unsigned int irq_nr)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&i8259_lock, flags);
+ if ( irq_nr >= i8259_pic_irq_offset )
+ irq_nr -= i8259_pic_irq_offset;
+ if ( irq_nr < 8 )
+ cached_21 &= ~(1 << irq_nr);
+ else
+ cached_A1 &= ~(1 << (irq_nr-8));
+ i8259_set_irq_mask(irq_nr);
+ spin_unlock_irqrestore(&i8259_lock, flags);
+}
+
+static void i8259_end_irq(unsigned int irq)
+{
+ if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))
+ && irq_desc[irq].action)
+ i8259_unmask_irq(irq);
+}
+
+struct hw_interrupt_type i8259_pic = {
+ " i8259 ",
+ NULL,
+ NULL,
+ i8259_unmask_irq,
+ i8259_mask_irq,
+ i8259_mask_and_ack_irq,
+ i8259_end_irq,
+ NULL
+};
+
+static struct resource pic1_iores = {
+ .name = "8259 (master)",
+ .start = 0x20,
+ .end = 0x21,
+ .flags = IORESOURCE_BUSY,
+};
+
+static struct resource pic2_iores = {
+ .name = "8259 (slave)",
+ .start = 0xa0,
+ .end = 0xa1,
+ .flags = IORESOURCE_BUSY,
+};
+
+static struct resource pic_edgectrl_iores = {
+ .name = "8259 edge control",
+ .start = 0x4d0,
+ .end = 0x4d1,
+ .flags = IORESOURCE_BUSY,
+};
+
+static struct irqaction i8259_irqaction = {
+ .handler = no_action,
+ .flags = SA_INTERRUPT,
+ .mask = CPU_MASK_NONE,
+ .name = "82c59 secondary cascade",
+};
+
+/*
+ * i8259_init()
+ * intack_addr - PCI interrupt acknowledge (real) address which will return
+ * the active irq from the 8259
+ */
+void __init
+i8259_init(long intack_addr)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&i8259_lock, flags);
+ /* init master interrupt controller */
+ outb(0x11, 0x20); /* Start init sequence */
+ outb(0x00, 0x21); /* Vector base */
+ outb(0x04, 0x21); /* edge tiggered, Cascade (slave) on IRQ2 */
+ outb(0x01, 0x21); /* Select 8086 mode */
+
+ /* init slave interrupt controller */
+ outb(0x11, 0xA0); /* Start init sequence */
+ outb(0x08, 0xA1); /* Vector base */
+ outb(0x02, 0xA1); /* edge triggered, Cascade (slave) on IRQ2 */
+ outb(0x01, 0xA1); /* Select 8086 mode */
+
+ /* always read ISR */
+ outb(0x0B, 0x20);
+ outb(0x0B, 0xA0);
+
+ /* Mask all interrupts */
+ outb(cached_A1, 0xA1);
+ outb(cached_21, 0x21);
+
+ spin_unlock_irqrestore(&i8259_lock, flags);
+
+ /* reserve our resources */
+ setup_irq( i8259_pic_irq_offset + 2, &i8259_irqaction);
+ request_resource(&ioport_resource, &pic1_iores);
+ request_resource(&ioport_resource, &pic2_iores);
+ request_resource(&ioport_resource, &pic_edgectrl_iores);
+
+ if (intack_addr != 0)
+ pci_intack = ioremap(intack_addr, 1);
+}
diff --git a/arch/ppc/syslib/ibm440gp_common.c b/arch/ppc/syslib/ibm440gp_common.c
new file mode 100644
index 0000000..0d6be2d
--- /dev/null
+++ b/arch/ppc/syslib/ibm440gp_common.c
@@ -0,0 +1,76 @@
+/*
+ * arch/ppc/syslib/ibm440gp_common.c
+ *
+ * PPC440GP system library
+ *
+ * Matt Porter <mporter@mvista.com>
+ * Copyright 2002-2003 MontaVista Software Inc.
+ *
+ * Eugene Surovegin <eugene.surovegin@zultys.com> or <ebs@ebshome.net>
+ * Copyright (c) 2003 Zultys Technologies
+ *
+ * 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.
+ *
+ */
+#include <linux/config.h>
+#include <linux/types.h>
+#include <asm/reg.h>
+#include <asm/ibm44x.h>
+#include <asm/mmu.h>
+
+/*
+ * Calculate 440GP clocks
+ */
+void __init ibm440gp_get_clocks(struct ibm44x_clocks* p,
+ unsigned int sys_clk,
+ unsigned int ser_clk)
+{
+ u32 cpc0_sys0 = mfdcr(DCRN_CPC0_SYS0);
+ u32 cpc0_cr0 = mfdcr(DCRN_CPC0_CR0);
+ u32 opdv = ((cpc0_sys0 >> 10) & 0x3) + 1;
+ u32 epdv = ((cpc0_sys0 >> 8) & 0x3) + 1;
+
+ if (cpc0_sys0 & 0x2){
+ /* Bypass system PLL */
+ p->cpu = p->plb = sys_clk;
+ }
+ else {
+ u32 fbdv, fwdva, fwdvb, m, vco;
+
+ fbdv = (cpc0_sys0 >> 18) & 0x0f;
+ if (!fbdv)
+ fbdv = 16;
+
+ fwdva = 8 - ((cpc0_sys0 >> 15) & 0x7);
+ fwdvb = 8 - ((cpc0_sys0 >> 12) & 0x7);
+
+ /* Feedback path */
+ if (cpc0_sys0 & 0x00000080){
+ /* PerClk */
+ m = fwdvb * opdv * epdv;
+ }
+ else {
+ /* CPU clock */
+ m = fbdv * fwdva;
+ }
+ vco = sys_clk * m;
+ p->cpu = vco / fwdva;
+ p->plb = vco / fwdvb;
+ }
+
+ p->opb = p->plb / opdv;
+ p->ebc = p->opb / epdv;
+
+ if (cpc0_cr0 & 0x00400000){
+ /* External UART clock */
+ p->uart0 = p->uart1 = ser_clk;
+ }
+ else {
+ /* Internal UART clock */
+ u32 uart_div = ((cpc0_cr0 >> 16) & 0x1f) + 1;
+ p->uart0 = p->uart1 = p->plb / uart_div;
+ }
+}
diff --git a/arch/ppc/syslib/ibm440gp_common.h b/arch/ppc/syslib/ibm440gp_common.h
new file mode 100644
index 0000000..a054d83
--- /dev/null
+++ b/arch/ppc/syslib/ibm440gp_common.h
@@ -0,0 +1,35 @@
+/*
+ * arch/ppc/kernel/ibm440gp_common.h
+ *
+ * PPC440GP system library
+ *
+ * Eugene Surovegin <eugene.surovegin@zultys.com> or <ebs@ebshome.net>
+ * Copyright (c) 2003 Zultys Technologies
+ *
+ * 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.
+ *
+ */
+#ifdef __KERNEL__
+#ifndef __PPC_SYSLIB_IBM440GP_COMMON_H
+#define __PPC_SYSLIB_IBM440GP_COMMON_H
+
+#ifndef __ASSEMBLY__
+
+#include <linux/config.h>
+#include <linux/init.h>
+#include <syslib/ibm44x_common.h>
+
+/*
+ * Please, refer to the Figure 13.1 in 440GP user manual
+ *
+ * if internal UART clock is used, ser_clk is ignored
+ */
+void ibm440gp_get_clocks(struct ibm44x_clocks*, unsigned int sys_clk,
+ unsigned int ser_clk) __init;
+
+#endif /* __ASSEMBLY__ */
+#endif /* __PPC_SYSLIB_IBM440GP_COMMON_H */
+#endif /* __KERNEL__ */
diff --git a/arch/ppc/syslib/ibm440gx_common.c b/arch/ppc/syslib/ibm440gx_common.c
new file mode 100644
index 0000000..4ad85e0
--- /dev/null
+++ b/arch/ppc/syslib/ibm440gx_common.c
@@ -0,0 +1,270 @@
+/*
+ * arch/ppc/kernel/ibm440gx_common.c
+ *
+ * PPC440GX system library
+ *
+ * Eugene Surovegin <eugene.surovegin@zultys.com> or <ebs@ebshome.net>
+ * Copyright (c) 2003, 2004 Zultys Technologies
+ *
+ * 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.
+ *
+ */
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/interrupt.h>
+#include <asm/ibm44x.h>
+#include <asm/mmu.h>
+#include <asm/processor.h>
+#include <syslib/ibm440gx_common.h>
+
+/*
+ * Calculate 440GX clocks
+ */
+static inline u32 __fix_zero(u32 v, u32 def){
+ return v ? v : def;
+}
+
+void __init ibm440gx_get_clocks(struct ibm44x_clocks* p, unsigned int sys_clk,
+ unsigned int ser_clk)
+{
+ u32 pllc = CPR_READ(DCRN_CPR_PLLC);
+ u32 plld = CPR_READ(DCRN_CPR_PLLD);
+ u32 uart0 = SDR_READ(DCRN_SDR_UART0);
+ u32 uart1 = SDR_READ(DCRN_SDR_UART1);
+
+ /* Dividers */
+ u32 fbdv = __fix_zero((plld >> 24) & 0x1f, 32);
+ u32 fwdva = __fix_zero((plld >> 16) & 0xf, 16);
+ u32 fwdvb = __fix_zero((plld >> 8) & 7, 8);
+ u32 lfbdv = __fix_zero(plld & 0x3f, 64);
+ u32 pradv0 = __fix_zero((CPR_READ(DCRN_CPR_PRIMAD) >> 24) & 7, 8);
+ u32 prbdv0 = __fix_zero((CPR_READ(DCRN_CPR_PRIMBD) >> 24) & 7, 8);
+ u32 opbdv0 = __fix_zero((CPR_READ(DCRN_CPR_OPBD) >> 24) & 3, 4);
+ u32 perdv0 = __fix_zero((CPR_READ(DCRN_CPR_PERD) >> 24) & 3, 4);
+
+ /* Input clocks for primary dividers */
+ u32 clk_a, clk_b;
+
+ if (pllc & 0x40000000){
+ u32 m;
+
+ /* Feedback path */
+ switch ((pllc >> 24) & 7){
+ case 0:
+ /* PLLOUTx */
+ m = ((pllc & 0x20000000) ? fwdvb : fwdva) * lfbdv;
+ break;
+ case 1:
+ /* CPU */
+ m = fwdva * pradv0;
+ break;
+ case 5:
+ /* PERClk */
+ m = fwdvb * prbdv0 * opbdv0 * perdv0;
+ break;
+ default:
+ printk(KERN_EMERG "invalid PLL feedback source\n");
+ goto bypass;
+ }
+ m *= fbdv;
+ p->vco = sys_clk * m;
+ clk_a = p->vco / fwdva;
+ clk_b = p->vco / fwdvb;
+ }
+ else {
+bypass:
+ /* Bypass system PLL */
+ p->vco = 0;
+ clk_a = clk_b = sys_clk;
+ }
+
+ p->cpu = clk_a / pradv0;
+ p->plb = clk_b / prbdv0;
+ p->opb = p->plb / opbdv0;
+ p->ebc = p->opb / perdv0;
+
+ /* UARTs clock */
+ if (uart0 & 0x00800000)
+ p->uart0 = ser_clk;
+ else
+ p->uart0 = p->plb / __fix_zero(uart0 & 0xff, 256);
+
+ if (uart1 & 0x00800000)
+ p->uart1 = ser_clk;
+ else
+ p->uart1 = p->plb / __fix_zero(uart1 & 0xff, 256);
+}
+
+/* Issue L2C diagnostic command */
+static inline u32 l2c_diag(u32 addr)
+{
+ mtdcr(DCRN_L2C0_ADDR, addr);
+ mtdcr(DCRN_L2C0_CMD, L2C_CMD_DIAG);
+ while (!(mfdcr(DCRN_L2C0_SR) & L2C_SR_CC)) ;
+ return mfdcr(DCRN_L2C0_DATA);
+}
+
+static irqreturn_t l2c_error_handler(int irq, void* dev, struct pt_regs* regs)
+{
+ u32 sr = mfdcr(DCRN_L2C0_SR);
+ if (sr & L2C_SR_CPE){
+ /* Read cache trapped address */
+ u32 addr = l2c_diag(0x42000000);
+ printk(KERN_EMERG "L2C: Cache Parity Error, addr[16:26] = 0x%08x\n", addr);
+ }
+ if (sr & L2C_SR_TPE){
+ /* Read tag trapped address */
+ u32 addr = l2c_diag(0x82000000) >> 16;
+ printk(KERN_EMERG "L2C: Tag Parity Error, addr[16:26] = 0x%08x\n", addr);
+ }
+
+ /* Clear parity errors */
+ if (sr & (L2C_SR_CPE | L2C_SR_TPE)){
+ mtdcr(DCRN_L2C0_ADDR, 0);
+ mtdcr(DCRN_L2C0_CMD, L2C_CMD_CCP | L2C_CMD_CTE);
+ } else
+ printk(KERN_EMERG "L2C: LRU error\n");
+
+ return IRQ_HANDLED;
+}
+
+/* Enable L2 cache */
+void __init ibm440gx_l2c_enable(void){
+ u32 r;
+ unsigned long flags;
+
+ /* Install error handler */
+ if (request_irq(87, l2c_error_handler, SA_INTERRUPT, "L2C", 0) < 0){
+ printk(KERN_ERR "Cannot install L2C error handler, cache is not enabled\n");
+ return;
+ }
+
+ local_irq_save(flags);
+ asm volatile ("sync" ::: "memory");
+
+ /* Disable SRAM */
+ mtdcr(DCRN_SRAM0_DPC, mfdcr(DCRN_SRAM0_DPC) & ~SRAM_DPC_ENABLE);
+ mtdcr(DCRN_SRAM0_SB0CR, mfdcr(DCRN_SRAM0_SB0CR) & ~SRAM_SBCR_BU_MASK);
+ mtdcr(DCRN_SRAM0_SB1CR, mfdcr(DCRN_SRAM0_SB1CR) & ~SRAM_SBCR_BU_MASK);
+ mtdcr(DCRN_SRAM0_SB2CR, mfdcr(DCRN_SRAM0_SB2CR) & ~SRAM_SBCR_BU_MASK);
+ mtdcr(DCRN_SRAM0_SB3CR, mfdcr(DCRN_SRAM0_SB3CR) & ~SRAM_SBCR_BU_MASK);
+
+ /* Enable L2_MODE without ICU/DCU */
+ r = mfdcr(DCRN_L2C0_CFG) & ~(L2C_CFG_ICU | L2C_CFG_DCU | L2C_CFG_SS_MASK);
+ r |= L2C_CFG_L2M | L2C_CFG_SS_256;
+ mtdcr(DCRN_L2C0_CFG, r);
+
+ mtdcr(DCRN_L2C0_ADDR, 0);
+
+ /* Hardware Clear Command */
+ mtdcr(DCRN_L2C0_CMD, L2C_CMD_HCC);
+ while (!(mfdcr(DCRN_L2C0_SR) & L2C_SR_CC)) ;
+
+ /* Clear Cache Parity and Tag Errors */
+ mtdcr(DCRN_L2C0_CMD, L2C_CMD_CCP | L2C_CMD_CTE);
+
+ /* Enable 64G snoop region starting at 0 */
+ r = mfdcr(DCRN_L2C0_SNP0) & ~(L2C_SNP_BA_MASK | L2C_SNP_SSR_MASK);
+ r |= L2C_SNP_SSR_32G | L2C_SNP_ESR;
+ mtdcr(DCRN_L2C0_SNP0, r);
+
+ r = mfdcr(DCRN_L2C0_SNP1) & ~(L2C_SNP_BA_MASK | L2C_SNP_SSR_MASK);
+ r |= 0x80000000 | L2C_SNP_SSR_32G | L2C_SNP_ESR;
+ mtdcr(DCRN_L2C0_SNP1, r);
+
+ asm volatile ("sync" ::: "memory");
+
+ /* Enable ICU/DCU ports */
+ r = mfdcr(DCRN_L2C0_CFG);
+ r &= ~(L2C_CFG_DCW_MASK | L2C_CFG_PMUX_MASK | L2C_CFG_PMIM | L2C_CFG_TPEI
+ | L2C_CFG_CPEI | L2C_CFG_NAM | L2C_CFG_NBRM);
+ r |= L2C_CFG_ICU | L2C_CFG_DCU | L2C_CFG_TPC | L2C_CFG_CPC | L2C_CFG_FRAN
+ | L2C_CFG_CPIM | L2C_CFG_TPIM | L2C_CFG_LIM | L2C_CFG_SMCM;
+ mtdcr(DCRN_L2C0_CFG, r);
+
+ asm volatile ("sync; isync" ::: "memory");
+ local_irq_restore(flags);
+}
+
+/* Disable L2 cache */
+void __init ibm440gx_l2c_disable(void){
+ u32 r;
+ unsigned long flags;
+
+ local_irq_save(flags);
+ asm volatile ("sync" ::: "memory");
+
+ /* Disable L2C mode */
+ r = mfdcr(DCRN_L2C0_CFG) & ~(L2C_CFG_L2M | L2C_CFG_ICU | L2C_CFG_DCU);
+ mtdcr(DCRN_L2C0_CFG, r);
+
+ /* Enable SRAM */
+ mtdcr(DCRN_SRAM0_DPC, mfdcr(DCRN_SRAM0_DPC) | SRAM_DPC_ENABLE);
+ mtdcr(DCRN_SRAM0_SB0CR,
+ SRAM_SBCR_BAS0 | SRAM_SBCR_BS_64KB | SRAM_SBCR_BU_RW);
+ mtdcr(DCRN_SRAM0_SB1CR,
+ SRAM_SBCR_BAS1 | SRAM_SBCR_BS_64KB | SRAM_SBCR_BU_RW);
+ mtdcr(DCRN_SRAM0_SB2CR,
+ SRAM_SBCR_BAS2 | SRAM_SBCR_BS_64KB | SRAM_SBCR_BU_RW);
+ mtdcr(DCRN_SRAM0_SB3CR,
+ SRAM_SBCR_BAS3 | SRAM_SBCR_BS_64KB | SRAM_SBCR_BU_RW);
+
+ asm volatile ("sync; isync" ::: "memory");
+ local_irq_restore(flags);
+}
+
+void __init ibm440gx_l2c_setup(struct ibm44x_clocks* p)
+{
+ /* Disable L2C on rev.A, rev.B and 800MHz version of rev.C,
+ enable it on all other revisions
+ */
+ u32 pvr = mfspr(SPRN_PVR);
+ if (pvr == PVR_440GX_RA || pvr == PVR_440GX_RB ||
+ (pvr == PVR_440GX_RC && p->cpu > 667000000))
+ ibm440gx_l2c_disable();
+ else
+ ibm440gx_l2c_enable();
+}
+
+int __init ibm440gx_get_eth_grp(void)
+{
+ return (SDR_READ(DCRN_SDR_PFC1) & DCRN_SDR_PFC1_EPS) >> DCRN_SDR_PFC1_EPS_SHIFT;
+}
+
+void __init ibm440gx_set_eth_grp(int group)
+{
+ SDR_WRITE(DCRN_SDR_PFC1, (SDR_READ(DCRN_SDR_PFC1) & ~DCRN_SDR_PFC1_EPS) | (group << DCRN_SDR_PFC1_EPS_SHIFT));
+}
+
+void __init ibm440gx_tah_enable(void)
+{
+ /* Enable TAH0 and TAH1 */
+ SDR_WRITE(DCRN_SDR_MFR,SDR_READ(DCRN_SDR_MFR) &
+ ~DCRN_SDR_MFR_TAH0);
+ SDR_WRITE(DCRN_SDR_MFR,SDR_READ(DCRN_SDR_MFR) &
+ ~DCRN_SDR_MFR_TAH1);
+}
+
+int ibm440gx_show_cpuinfo(struct seq_file *m){
+
+ u32 l2c_cfg = mfdcr(DCRN_L2C0_CFG);
+ const char* s;
+ if (l2c_cfg & L2C_CFG_L2M){
+ switch (l2c_cfg & (L2C_CFG_ICU | L2C_CFG_DCU)){
+ case L2C_CFG_ICU: s = "I-Cache only"; break;
+ case L2C_CFG_DCU: s = "D-Cache only"; break;
+ default: s = "I-Cache/D-Cache"; break;
+ }
+ }
+ else
+ s = "disabled";
+
+ seq_printf(m, "L2-Cache\t: %s (0x%08x 0x%08x)\n", s,
+ l2c_cfg, mfdcr(DCRN_L2C0_SR));
+
+ return 0;
+}
+
diff --git a/arch/ppc/syslib/ibm440gx_common.h b/arch/ppc/syslib/ibm440gx_common.h
new file mode 100644
index 0000000..e73aa04
--- /dev/null
+++ b/arch/ppc/syslib/ibm440gx_common.h
@@ -0,0 +1,57 @@
+/*
+ * arch/ppc/kernel/ibm440gx_common.h
+ *
+ * PPC440GX system library
+ *
+ * Eugene Surovegin <eugene.surovegin@zultys.com> or <ebs@ebshome.net>
+ * Copyright (c) 2003, 2004 Zultys Technologies
+ *
+ * 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.
+ *
+ */
+#ifdef __KERNEL__
+#ifndef __PPC_SYSLIB_IBM440GX_COMMON_H
+#define __PPC_SYSLIB_IBM440GX_COMMON_H
+
+#ifndef __ASSEMBLY__
+
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/seq_file.h>
+#include <syslib/ibm44x_common.h>
+
+/*
+ * Please, refer to the Figure 14.1 in 440GX user manual
+ *
+ * if internal UART clock is used, ser_clk is ignored
+ */
+void ibm440gx_get_clocks(struct ibm44x_clocks*, unsigned int sys_clk,
+ unsigned int ser_clk) __init;
+
+/* Enable L2 cache */
+void ibm440gx_l2c_enable(void) __init;
+
+/* Disable L2 cache */
+void ibm440gx_l2c_disable(void) __init;
+
+/* Enable/disable L2 cache for a particular chip revision */
+void ibm440gx_l2c_setup(struct ibm44x_clocks*) __init;
+
+/* Get Ethernet Group */
+int ibm440gx_get_eth_grp(void) __init;
+
+/* Set Ethernet Group */
+void ibm440gx_set_eth_grp(int group) __init;
+
+/* Enable TAH devices */
+void ibm440gx_tah_enable(void) __init;
+
+/* Add L2C info to /proc/cpuinfo */
+int ibm440gx_show_cpuinfo(struct seq_file*);
+
+#endif /* __ASSEMBLY__ */
+#endif /* __PPC_SYSLIB_IBM440GX_COMMON_H */
+#endif /* __KERNEL__ */
diff --git a/arch/ppc/syslib/ibm440sp_common.c b/arch/ppc/syslib/ibm440sp_common.c
new file mode 100644
index 0000000..417d4cf
--- /dev/null
+++ b/arch/ppc/syslib/ibm440sp_common.c
@@ -0,0 +1,71 @@
+/*
+ * arch/ppc/syslib/ibm440sp_common.c
+ *
+ * PPC440SP system library
+ *
+ * Matt Porter <mporter@kernel.crashing.org>
+ * Copyright 2002-2005 MontaVista Software Inc.
+ *
+ * Eugene Surovegin <eugene.surovegin@zultys.com> or <ebs@ebshome.net>
+ * Copyright (c) 2003, 2004 Zultys Technologies
+ *
+ * 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.
+ *
+ */
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/serial.h>
+
+#include <asm/param.h>
+#include <asm/ibm44x.h>
+#include <asm/mmu.h>
+#include <asm/machdep.h>
+#include <asm/time.h>
+#include <asm/ppc4xx_pic.h>
+
+/*
+ * Read the 440SP memory controller to get size of system memory.
+ */
+unsigned long __init ibm440sp_find_end_of_memory(void)
+{
+ u32 i;
+ u32 mem_size = 0;
+
+ /* Read two bank sizes and sum */
+ for (i=0; i<2; i++)
+ switch (mfdcr(DCRN_MQ0_BS0BAS + i) & MQ0_CONFIG_SIZE_MASK) {
+ case MQ0_CONFIG_SIZE_8M:
+ mem_size += PPC44x_MEM_SIZE_8M;
+ break;
+ case MQ0_CONFIG_SIZE_16M:
+ mem_size += PPC44x_MEM_SIZE_16M;
+ break;
+ case MQ0_CONFIG_SIZE_32M:
+ mem_size += PPC44x_MEM_SIZE_32M;
+ break;
+ case MQ0_CONFIG_SIZE_64M:
+ mem_size += PPC44x_MEM_SIZE_64M;
+ break;
+ case MQ0_CONFIG_SIZE_128M:
+ mem_size += PPC44x_MEM_SIZE_128M;
+ break;
+ case MQ0_CONFIG_SIZE_256M:
+ mem_size += PPC44x_MEM_SIZE_256M;
+ break;
+ case MQ0_CONFIG_SIZE_512M:
+ mem_size += PPC44x_MEM_SIZE_512M;
+ break;
+ case MQ0_CONFIG_SIZE_1G:
+ mem_size += PPC44x_MEM_SIZE_1G;
+ break;
+ case MQ0_CONFIG_SIZE_2G:
+ mem_size += PPC44x_MEM_SIZE_2G;
+ break;
+ default:
+ break;
+ }
+ return mem_size;
+}
diff --git a/arch/ppc/syslib/ibm440sp_common.h b/arch/ppc/syslib/ibm440sp_common.h
new file mode 100644
index 0000000..a21a990
--- /dev/null
+++ b/arch/ppc/syslib/ibm440sp_common.h
@@ -0,0 +1,25 @@
+/*
+ * arch/ppc/syslib/ibm440sp_common.h
+ *
+ * PPC440SP system library
+ *
+ * Matt Porter <mporter@kernel.crashing.org>
+ * Copyright 2004-2005 MontaVista Software, Inc.
+ *
+ * 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.
+ *
+ */
+#ifdef __KERNEL__
+#ifndef __PPC_SYSLIB_IBM440SP_COMMON_H
+#define __PPC_SYSLIB_IBM440SP_COMMON_H
+
+#ifndef __ASSEMBLY__
+
+extern unsigned long __init ibm440sp_find_end_of_memory(void);
+
+#endif /* __ASSEMBLY__ */
+#endif /* __PPC_SYSLIB_IBM440SP_COMMON_H */
+#endif /* __KERNEL__ */
diff --git a/arch/ppc/syslib/ibm44x_common.c b/arch/ppc/syslib/ibm44x_common.c
new file mode 100644
index 0000000..7612e06
--- /dev/null
+++ b/arch/ppc/syslib/ibm44x_common.c
@@ -0,0 +1,193 @@
+/*
+ * arch/ppc/syslib/ibm44x_common.c
+ *
+ * PPC44x system library
+ *
+ * Matt Porter <mporter@kernel.crashing.org>
+ * Copyright 2002-2005 MontaVista Software Inc.
+ *
+ * Eugene Surovegin <eugene.surovegin@zultys.com> or <ebs@ebshome.net>
+ * Copyright (c) 2003, 2004 Zultys Technologies
+ *
+ * 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.
+ *
+ */
+#include <linux/config.h>
+#include <linux/time.h>
+#include <linux/types.h>
+#include <linux/serial.h>
+#include <linux/module.h>
+
+#include <asm/ibm44x.h>
+#include <asm/mmu.h>
+#include <asm/machdep.h>
+#include <asm/time.h>
+#include <asm/ppc4xx_pic.h>
+#include <asm/param.h>
+
+#include <syslib/gen550.h>
+
+phys_addr_t fixup_bigphys_addr(phys_addr_t addr, phys_addr_t size)
+{
+ phys_addr_t page_4gb = 0;
+
+ /*
+ * Trap the least significant 32-bit portions of an
+ * address in the 440's 36-bit address space. Fix
+ * them up with the appropriate ERPN
+ */
+ if ((addr >= PPC44x_IO_LO) && (addr <= PPC44x_IO_HI))
+ page_4gb = PPC44x_IO_PAGE;
+ else if ((addr >= PPC44x_PCI0CFG_LO) && (addr <= PPC44x_PCI0CFG_HI))
+ page_4gb = PPC44x_PCICFG_PAGE;
+#ifdef CONFIG_440SP
+ else if ((addr >= PPC44x_PCI1CFG_LO) && (addr <= PPC44x_PCI1CFG_HI))
+ page_4gb = PPC44x_PCICFG_PAGE;
+ else if ((addr >= PPC44x_PCI2CFG_LO) && (addr <= PPC44x_PCI2CFG_HI))
+ page_4gb = PPC44x_PCICFG_PAGE;
+#endif
+ else if ((addr >= PPC44x_PCIMEM_LO) && (addr <= PPC44x_PCIMEM_HI))
+ page_4gb = PPC44x_PCIMEM_PAGE;
+
+ return (page_4gb | addr);
+};
+EXPORT_SYMBOL(fixup_bigphys_addr);
+
+void __init ibm44x_calibrate_decr(unsigned int freq)
+{
+ tb_ticks_per_jiffy = freq / HZ;
+ tb_to_us = mulhwu_scale_factor(freq, 1000000);
+
+ /* Set the time base to zero */
+ mtspr(SPRN_TBWL, 0);
+ mtspr(SPRN_TBWU, 0);
+
+ /* Clear any pending timer interrupts */
+ mtspr(SPRN_TSR, TSR_ENW | TSR_WIS | TSR_DIS | TSR_FIS);
+
+ /* Enable decrementer interrupt */
+ mtspr(SPRN_TCR, TCR_DIE);
+}
+
+extern void abort(void);
+
+static void ibm44x_restart(char *cmd)
+{
+ local_irq_disable();
+ abort();
+}
+
+static void ibm44x_power_off(void)
+{
+ local_irq_disable();
+ for(;;);
+}
+
+static void ibm44x_halt(void)
+{
+ local_irq_disable();
+ for(;;);
+}
+
+/*
+ * Read the 44x memory controller to get size of system memory.
+ */
+static unsigned long __init ibm44x_find_end_of_memory(void)
+{
+ u32 i, bank_config;
+ u32 mem_size = 0;
+
+ for (i=0; i<4; i++)
+ {
+ switch (i)
+ {
+ case 0:
+ mtdcr(DCRN_SDRAM0_CFGADDR, SDRAM0_B0CR);
+ break;
+ case 1:
+ mtdcr(DCRN_SDRAM0_CFGADDR, SDRAM0_B1CR);
+ break;
+ case 2:
+ mtdcr(DCRN_SDRAM0_CFGADDR, SDRAM0_B2CR);
+ break;
+ case 3:
+ mtdcr(DCRN_SDRAM0_CFGADDR, SDRAM0_B3CR);
+ break;
+ }
+
+ bank_config = mfdcr(DCRN_SDRAM0_CFGDATA);
+
+ if (!(bank_config & SDRAM_CONFIG_BANK_ENABLE))
+ continue;
+ switch (SDRAM_CONFIG_BANK_SIZE(bank_config))
+ {
+ case SDRAM_CONFIG_SIZE_8M:
+ mem_size += PPC44x_MEM_SIZE_8M;
+ break;
+ case SDRAM_CONFIG_SIZE_16M:
+ mem_size += PPC44x_MEM_SIZE_16M;
+ break;
+ case SDRAM_CONFIG_SIZE_32M:
+ mem_size += PPC44x_MEM_SIZE_32M;
+ break;
+ case SDRAM_CONFIG_SIZE_64M:
+ mem_size += PPC44x_MEM_SIZE_64M;
+ break;
+ case SDRAM_CONFIG_SIZE_128M:
+ mem_size += PPC44x_MEM_SIZE_128M;
+ break;
+ case SDRAM_CONFIG_SIZE_256M:
+ mem_size += PPC44x_MEM_SIZE_256M;
+ break;
+ case SDRAM_CONFIG_SIZE_512M:
+ mem_size += PPC44x_MEM_SIZE_512M;
+ break;
+ }
+ }
+ return mem_size;
+}
+
+void __init ibm44x_platform_init(void)
+{
+ ppc_md.init_IRQ = ppc4xx_pic_init;
+ ppc_md.find_end_of_memory = ibm44x_find_end_of_memory;
+ ppc_md.restart = ibm44x_restart;
+ ppc_md.power_off = ibm44x_power_off;
+ ppc_md.halt = ibm44x_halt;
+
+#ifdef CONFIG_SERIAL_TEXT_DEBUG
+ ppc_md.progress = gen550_progress;
+#endif /* CONFIG_SERIAL_TEXT_DEBUG */
+#ifdef CONFIG_KGDB
+ ppc_md.kgdb_map_scc = gen550_kgdb_map_scc;
+#endif
+
+ /*
+ * The Abatron BDI JTAG debugger does not tolerate others
+ * mucking with the debug registers.
+ */
+#if !defined(CONFIG_BDI_SWITCH)
+ /* Enable internal debug mode */
+ mtspr(SPRN_DBCR0, (DBCR0_IDM));
+
+ /* Clear any residual debug events */
+ mtspr(SPRN_DBSR, 0xffffffff);
+#endif
+}
+
+/* Called from MachineCheckException */
+void platform_machine_check(struct pt_regs *regs)
+{
+ printk("PLB0: BEAR=0x%08x%08x ACR= 0x%08x BESR= 0x%08x\n",
+ mfdcr(DCRN_PLB0_BEARH), mfdcr(DCRN_PLB0_BEARL),
+ mfdcr(DCRN_PLB0_ACR), mfdcr(DCRN_PLB0_BESR));
+ printk("POB0: BEAR=0x%08x%08x BESR0=0x%08x BESR1=0x%08x\n",
+ mfdcr(DCRN_POB0_BEARH), mfdcr(DCRN_POB0_BEARL),
+ mfdcr(DCRN_POB0_BESR0), mfdcr(DCRN_POB0_BESR1));
+ printk("OPB0: BEAR=0x%08x%08x BSTAT=0x%08x\n",
+ mfdcr(DCRN_OPB0_BEARH), mfdcr(DCRN_OPB0_BEARL),
+ mfdcr(DCRN_OPB0_BSTAT));
+}
diff --git a/arch/ppc/syslib/ibm44x_common.h b/arch/ppc/syslib/ibm44x_common.h
new file mode 100644
index 0000000..b14eb60
--- /dev/null
+++ b/arch/ppc/syslib/ibm44x_common.h
@@ -0,0 +1,42 @@
+/*
+ * arch/ppc/kernel/ibm44x_common.h
+ *
+ * PPC44x system library
+ *
+ * Eugene Surovegin <eugene.surovegin@zultys.com> or <ebs@ebshome.net>
+ * Copyright (c) 2003, 2004 Zultys Technologies
+ *
+ * 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.
+ *
+ */
+#ifdef __KERNEL__
+#ifndef __PPC_SYSLIB_IBM44x_COMMON_H
+#define __PPC_SYSLIB_IBM44x_COMMON_H
+
+#ifndef __ASSEMBLY__
+
+/*
+ * All clocks are in Hz
+ */
+struct ibm44x_clocks {
+ unsigned int vco; /* VCO, 0 if system PLL is bypassed */
+ unsigned int cpu; /* CPUCoreClk */
+ unsigned int plb; /* PLBClk */
+ unsigned int opb; /* OPBClk */
+ unsigned int ebc; /* PerClk */
+ unsigned int uart0;
+ unsigned int uart1;
+};
+
+/* common 44x platform init */
+void ibm44x_platform_init(void) __init;
+
+/* initialize decrementer and tick-related variables */
+void ibm44x_calibrate_decr(unsigned int freq) __init;
+
+#endif /* __ASSEMBLY__ */
+#endif /* __PPC_SYSLIB_IBM44x_COMMON_H */
+#endif /* __KERNEL__ */
diff --git a/arch/ppc/syslib/ibm_ocp.c b/arch/ppc/syslib/ibm_ocp.c
new file mode 100644
index 0000000..3f6e55c
--- /dev/null
+++ b/arch/ppc/syslib/ibm_ocp.c
@@ -0,0 +1,9 @@
+#include <linux/module.h>
+#include <asm/ocp.h>
+
+struct ocp_sys_info_data ocp_sys_info = {
+ .opb_bus_freq = 50000000, /* OPB Bus Frequency (Hz) */
+ .ebc_bus_freq = 33333333, /* EBC Bus Frequency (Hz) */
+};
+
+EXPORT_SYMBOL(ocp_sys_info);
diff --git a/arch/ppc/syslib/indirect_pci.c b/arch/ppc/syslib/indirect_pci.c
new file mode 100644
index 0000000..a5a7526
--- /dev/null
+++ b/arch/ppc/syslib/indirect_pci.c
@@ -0,0 +1,135 @@
+/*
+ * Support for indirect PCI bridges.
+ *
+ * Copyright (C) 1998 Gabriel Paubert.
+ *
+ * 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.
+ */
+
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/delay.h>
+#include <linux/string.h>
+#include <linux/init.h>
+#include <linux/bootmem.h>
+
+#include <asm/io.h>
+#include <asm/prom.h>
+#include <asm/pci-bridge.h>
+#include <asm/machdep.h>
+
+#ifdef CONFIG_PPC_INDIRECT_PCI_BE
+#define PCI_CFG_OUT out_be32
+#else
+#define PCI_CFG_OUT out_le32
+#endif
+
+static int
+indirect_read_config(struct pci_bus *bus, unsigned int devfn, int offset,
+ int len, u32 *val)
+{
+ struct pci_controller *hose = bus->sysdata;
+ volatile void __iomem *cfg_data;
+ u8 cfg_type = 0;
+
+ if (ppc_md.pci_exclude_device)
+ if (ppc_md.pci_exclude_device(bus->number, devfn))
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
+ if (hose->set_cfg_type)
+ if (bus->number != hose->first_busno)
+ cfg_type = 1;
+
+ PCI_CFG_OUT(hose->cfg_addr,
+ (0x80000000 | ((bus->number - hose->bus_offset) << 16)
+ | (devfn << 8) | ((offset & 0xfc) | cfg_type)));
+
+ /*
+ * Note: the caller has already checked that offset is
+ * suitably aligned and that len is 1, 2 or 4.
+ */
+ cfg_data = hose->cfg_data + (offset & 3);
+ switch (len) {
+ case 1:
+ *val = in_8(cfg_data);
+ break;
+ case 2:
+ *val = in_le16(cfg_data);
+ break;
+ default:
+ *val = in_le32(cfg_data);
+ break;
+ }
+ return PCIBIOS_SUCCESSFUL;
+}
+
+static int
+indirect_write_config(struct pci_bus *bus, unsigned int devfn, int offset,
+ int len, u32 val)
+{
+ struct pci_controller *hose = bus->sysdata;
+ volatile void __iomem *cfg_data;
+ u8 cfg_type = 0;
+
+ if (ppc_md.pci_exclude_device)
+ if (ppc_md.pci_exclude_device(bus->number, devfn))
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
+ if (hose->set_cfg_type)
+ if (bus->number != hose->first_busno)
+ cfg_type = 1;
+
+ PCI_CFG_OUT(hose->cfg_addr,
+ (0x80000000 | ((bus->number - hose->bus_offset) << 16)
+ | (devfn << 8) | ((offset & 0xfc) | cfg_type)));
+
+ /*
+ * Note: the caller has already checked that offset is
+ * suitably aligned and that len is 1, 2 or 4.
+ */
+ cfg_data = hose->cfg_data + (offset & 3);
+ switch (len) {
+ case 1:
+ out_8(cfg_data, val);
+ break;
+ case 2:
+ out_le16(cfg_data, val);
+ break;
+ default:
+ out_le32(cfg_data, val);
+ break;
+ }
+ return PCIBIOS_SUCCESSFUL;
+}
+
+static struct pci_ops indirect_pci_ops =
+{
+ indirect_read_config,
+ indirect_write_config
+};
+
+void __init
+setup_indirect_pci_nomap(struct pci_controller* hose, void __iomem * cfg_addr,
+ void __iomem * cfg_data)
+{
+ hose->cfg_addr = cfg_addr;
+ hose->cfg_data = cfg_data;
+ hose->ops = &indirect_pci_ops;
+}
+
+void __init
+setup_indirect_pci(struct pci_controller* hose, u32 cfg_addr, u32 cfg_data)
+{
+ unsigned long base = cfg_addr & PAGE_MASK;
+ void __iomem *mbase, *addr, *data;
+
+ mbase = ioremap(base, PAGE_SIZE);
+ addr = mbase + (cfg_addr & ~PAGE_MASK);
+ if ((cfg_data & PAGE_MASK) != base)
+ mbase = ioremap(cfg_data & PAGE_MASK, PAGE_SIZE);
+ data = mbase + (cfg_data & ~PAGE_MASK);
+ setup_indirect_pci_nomap(hose, addr, data);
+}
diff --git a/arch/ppc/syslib/ipic.c b/arch/ppc/syslib/ipic.c
new file mode 100644
index 0000000..acb2cde
--- /dev/null
+++ b/arch/ppc/syslib/ipic.c
@@ -0,0 +1,646 @@
+/*
+ * include/asm-ppc/ipic.c
+ *
+ * IPIC routines implementations.
+ *
+ * Copyright 2005 Freescale Semiconductor, Inc.
+ *
+ * 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.
+ */
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/reboot.h>
+#include <linux/slab.h>
+#include <linux/stddef.h>
+#include <linux/sched.h>
+#include <linux/signal.h>
+#include <linux/sysdev.h>
+#include <asm/irq.h>
+#include <asm/io.h>
+#include <asm/ipic.h>
+#include <asm/mpc83xx.h>
+
+#include "ipic.h"
+
+static struct ipic p_ipic;
+static struct ipic * primary_ipic;
+
+static struct ipic_info ipic_info[] = {
+ [9] = {
+ .pend = IPIC_SIPNR_H,
+ .mask = IPIC_SIMSR_H,
+ .prio = IPIC_SIPRR_D,
+ .force = IPIC_SIFCR_H,
+ .bit = 24,
+ .prio_mask = 0,
+ },
+ [10] = {
+ .pend = IPIC_SIPNR_H,
+ .mask = IPIC_SIMSR_H,
+ .prio = IPIC_SIPRR_D,
+ .force = IPIC_SIFCR_H,
+ .bit = 25,
+ .prio_mask = 1,
+ },
+ [11] = {
+ .pend = IPIC_SIPNR_H,
+ .mask = IPIC_SIMSR_H,
+ .prio = IPIC_SIPRR_D,
+ .force = IPIC_SIFCR_H,
+ .bit = 26,
+ .prio_mask = 2,
+ },
+ [14] = {
+ .pend = IPIC_SIPNR_H,
+ .mask = IPIC_SIMSR_H,
+ .prio = IPIC_SIPRR_D,
+ .force = IPIC_SIFCR_H,
+ .bit = 29,
+ .prio_mask = 5,
+ },
+ [15] = {
+ .pend = IPIC_SIPNR_H,
+ .mask = IPIC_SIMSR_H,
+ .prio = IPIC_SIPRR_D,
+ .force = IPIC_SIFCR_H,
+ .bit = 30,
+ .prio_mask = 6,
+ },
+ [16] = {
+ .pend = IPIC_SIPNR_H,
+ .mask = IPIC_SIMSR_H,
+ .prio = IPIC_SIPRR_D,
+ .force = IPIC_SIFCR_H,
+ .bit = 31,
+ .prio_mask = 7,
+ },
+ [17] = {
+ .pend = IPIC_SIPNR_H,
+ .mask = IPIC_SEMSR,
+ .prio = IPIC_SMPRR_A,
+ .force = IPIC_SEFCR,
+ .bit = 1,
+ .prio_mask = 5,
+ },
+ [18] = {
+ .pend = IPIC_SIPNR_H,
+ .mask = IPIC_SEMSR,
+ .prio = IPIC_SMPRR_A,
+ .force = IPIC_SEFCR,
+ .bit = 2,
+ .prio_mask = 6,
+ },
+ [19] = {
+ .pend = IPIC_SIPNR_H,
+ .mask = IPIC_SEMSR,
+ .prio = IPIC_SMPRR_A,
+ .force = IPIC_SEFCR,
+ .bit = 3,
+ .prio_mask = 7,
+ },
+ [20] = {
+ .pend = IPIC_SIPNR_H,
+ .mask = IPIC_SEMSR,
+ .prio = IPIC_SMPRR_B,
+ .force = IPIC_SEFCR,
+ .bit = 4,
+ .prio_mask = 4,
+ },
+ [21] = {
+ .pend = IPIC_SIPNR_H,
+ .mask = IPIC_SEMSR,
+ .prio = IPIC_SMPRR_B,
+ .force = IPIC_SEFCR,
+ .bit = 5,
+ .prio_mask = 5,
+ },
+ [22] = {
+ .pend = IPIC_SIPNR_H,
+ .mask = IPIC_SEMSR,
+ .prio = IPIC_SMPRR_B,
+ .force = IPIC_SEFCR,
+ .bit = 6,
+ .prio_mask = 6,
+ },
+ [23] = {
+ .pend = IPIC_SIPNR_H,
+ .mask = IPIC_SEMSR,
+ .prio = IPIC_SMPRR_B,
+ .force = IPIC_SEFCR,
+ .bit = 7,
+ .prio_mask = 7,
+ },
+ [32] = {
+ .pend = IPIC_SIPNR_H,
+ .mask = IPIC_SIMSR_H,
+ .prio = IPIC_SIPRR_A,
+ .force = IPIC_SIFCR_H,
+ .bit = 0,
+ .prio_mask = 0,
+ },
+ [33] = {
+ .pend = IPIC_SIPNR_H,
+ .mask = IPIC_SIMSR_H,
+ .prio = IPIC_SIPRR_A,
+ .force = IPIC_SIFCR_H,
+ .bit = 1,
+ .prio_mask = 1,
+ },
+ [34] = {
+ .pend = IPIC_SIPNR_H,
+ .mask = IPIC_SIMSR_H,
+ .prio = IPIC_SIPRR_A,
+ .force = IPIC_SIFCR_H,
+ .bit = 2,
+ .prio_mask = 2,
+ },
+ [35] = {
+ .pend = IPIC_SIPNR_H,
+ .mask = IPIC_SIMSR_H,
+ .prio = IPIC_SIPRR_A,
+ .force = IPIC_SIFCR_H,
+ .bit = 3,
+ .prio_mask = 3,
+ },
+ [36] = {
+ .pend = IPIC_SIPNR_H,
+ .mask = IPIC_SIMSR_H,
+ .prio = IPIC_SIPRR_A,
+ .force = IPIC_SIFCR_H,
+ .bit = 4,
+ .prio_mask = 4,
+ },
+ [37] = {
+ .pend = IPIC_SIPNR_H,
+ .mask = IPIC_SIMSR_H,
+ .prio = IPIC_SIPRR_A,
+ .force = IPIC_SIFCR_H,
+ .bit = 5,
+ .prio_mask = 5,
+ },
+ [38] = {
+ .pend = IPIC_SIPNR_H,
+ .mask = IPIC_SIMSR_H,
+ .prio = IPIC_SIPRR_A,
+ .force = IPIC_SIFCR_H,
+ .bit = 6,
+ .prio_mask = 6,
+ },
+ [39] = {
+ .pend = IPIC_SIPNR_H,
+ .mask = IPIC_SIMSR_H,
+ .prio = IPIC_SIPRR_A,
+ .force = IPIC_SIFCR_H,
+ .bit = 7,
+ .prio_mask = 7,
+ },
+ [48] = {
+ .pend = IPIC_SEPNR,
+ .mask = IPIC_SEMSR,
+ .prio = IPIC_SMPRR_A,
+ .force = IPIC_SEFCR,
+ .bit = 0,
+ .prio_mask = 4,
+ },
+ [64] = {
+ .pend = IPIC_SIPNR_H,
+ .mask = IPIC_SIMSR_L,
+ .prio = IPIC_SMPRR_A,
+ .force = IPIC_SIFCR_L,
+ .bit = 0,
+ .prio_mask = 0,
+ },
+ [65] = {
+ .pend = IPIC_SIPNR_H,
+ .mask = IPIC_SIMSR_L,
+ .prio = IPIC_SMPRR_A,
+ .force = IPIC_SIFCR_L,
+ .bit = 1,
+ .prio_mask = 1,
+ },
+ [66] = {
+ .pend = IPIC_SIPNR_H,
+ .mask = IPIC_SIMSR_L,
+ .prio = IPIC_SMPRR_A,
+ .force = IPIC_SIFCR_L,
+ .bit = 2,
+ .prio_mask = 2,
+ },
+ [67] = {
+ .pend = IPIC_SIPNR_H,
+ .mask = IPIC_SIMSR_L,
+ .prio = IPIC_SMPRR_A,
+ .force = IPIC_SIFCR_L,
+ .bit = 3,
+ .prio_mask = 3,
+ },
+ [68] = {
+ .pend = IPIC_SIPNR_H,
+ .mask = IPIC_SIMSR_L,
+ .prio = IPIC_SMPRR_B,
+ .force = IPIC_SIFCR_L,
+ .bit = 4,
+ .prio_mask = 0,
+ },
+ [69] = {
+ .pend = IPIC_SIPNR_H,
+ .mask = IPIC_SIMSR_L,
+ .prio = IPIC_SMPRR_B,
+ .force = IPIC_SIFCR_L,
+ .bit = 5,
+ .prio_mask = 1,
+ },
+ [70] = {
+ .pend = IPIC_SIPNR_H,
+ .mask = IPIC_SIMSR_L,
+ .prio = IPIC_SMPRR_B,
+ .force = IPIC_SIFCR_L,
+ .bit = 6,
+ .prio_mask = 2,
+ },
+ [71] = {
+ .pend = IPIC_SIPNR_H,
+ .mask = IPIC_SIMSR_L,
+ .prio = IPIC_SMPRR_B,
+ .force = IPIC_SIFCR_L,
+ .bit = 7,
+ .prio_mask = 3,
+ },
+ [72] = {
+ .pend = IPIC_SIPNR_H,
+ .mask = IPIC_SIMSR_L,
+ .prio = 0,
+ .force = IPIC_SIFCR_L,
+ .bit = 8,
+ },
+ [73] = {
+ .pend = IPIC_SIPNR_H,
+ .mask = IPIC_SIMSR_L,
+ .prio = 0,
+ .force = IPIC_SIFCR_L,
+ .bit = 9,
+ },
+ [74] = {
+ .pend = IPIC_SIPNR_H,
+ .mask = IPIC_SIMSR_L,
+ .prio = 0,
+ .force = IPIC_SIFCR_L,
+ .bit = 10,
+ },
+ [75] = {
+ .pend = IPIC_SIPNR_H,
+ .mask = IPIC_SIMSR_L,
+ .prio = 0,
+ .force = IPIC_SIFCR_L,
+ .bit = 11,
+ },
+ [76] = {
+ .pend = IPIC_SIPNR_H,
+ .mask = IPIC_SIMSR_L,
+ .prio = 0,
+ .force = IPIC_SIFCR_L,
+ .bit = 12,
+ },
+ [77] = {
+ .pend = IPIC_SIPNR_H,
+ .mask = IPIC_SIMSR_L,
+ .prio = 0,
+ .force = IPIC_SIFCR_L,
+ .bit = 13,
+ },
+ [78] = {
+ .pend = IPIC_SIPNR_H,
+ .mask = IPIC_SIMSR_L,
+ .prio = 0,
+ .force = IPIC_SIFCR_L,
+ .bit = 14,
+ },
+ [79] = {
+ .pend = IPIC_SIPNR_H,
+ .mask = IPIC_SIMSR_L,
+ .prio = 0,
+ .force = IPIC_SIFCR_L,
+ .bit = 15,
+ },
+ [80] = {
+ .pend = IPIC_SIPNR_H,
+ .mask = IPIC_SIMSR_L,
+ .prio = 0,
+ .force = IPIC_SIFCR_L,
+ .bit = 16,
+ },
+ [84] = {
+ .pend = IPIC_SIPNR_H,
+ .mask = IPIC_SIMSR_L,
+ .prio = 0,
+ .force = IPIC_SIFCR_L,
+ .bit = 20,
+ },
+ [85] = {
+ .pend = IPIC_SIPNR_H,
+ .mask = IPIC_SIMSR_L,
+ .prio = 0,
+ .force = IPIC_SIFCR_L,
+ .bit = 21,
+ },
+ [90] = {
+ .pend = IPIC_SIPNR_H,
+ .mask = IPIC_SIMSR_L,
+ .prio = 0,
+ .force = IPIC_SIFCR_L,
+ .bit = 26,
+ },
+ [91] = {
+ .pend = IPIC_SIPNR_H,
+ .mask = IPIC_SIMSR_L,
+ .prio = 0,
+ .force = IPIC_SIFCR_L,
+ .bit = 27,
+ },
+};
+
+static inline u32 ipic_read(volatile u32 __iomem *base, unsigned int reg)
+{
+ return in_be32(base + (reg >> 2));
+}
+
+static inline void ipic_write(volatile u32 __iomem *base, unsigned int reg, u32 value)
+{
+ out_be32(base + (reg >> 2), value);
+}
+
+static inline struct ipic * ipic_from_irq(unsigned int irq)
+{
+ return primary_ipic;
+}
+
+static void ipic_enable_irq(unsigned int irq)
+{
+ struct ipic *ipic = ipic_from_irq(irq);
+ unsigned int src = irq - ipic->irq_offset;
+ u32 temp;
+
+ temp = ipic_read(ipic->regs, ipic_info[src].mask);
+ temp |= (1 << (31 - ipic_info[src].bit));
+ ipic_write(ipic->regs, ipic_info[src].mask, temp);
+}
+
+static void ipic_disable_irq(unsigned int irq)
+{
+ struct ipic *ipic = ipic_from_irq(irq);
+ unsigned int src = irq - ipic->irq_offset;
+ u32 temp;
+
+ temp = ipic_read(ipic->regs, ipic_info[src].mask);
+ temp &= ~(1 << (31 - ipic_info[src].bit));
+ ipic_write(ipic->regs, ipic_info[src].mask, temp);
+}
+
+static void ipic_disable_irq_and_ack(unsigned int irq)
+{
+ struct ipic *ipic = ipic_from_irq(irq);
+ unsigned int src = irq - ipic->irq_offset;
+ u32 temp;
+
+ ipic_disable_irq(irq);
+
+ temp = ipic_read(ipic->regs, ipic_info[src].pend);
+ temp |= (1 << (31 - ipic_info[src].bit));
+ ipic_write(ipic->regs, ipic_info[src].pend, temp);
+}
+
+static void ipic_end_irq(unsigned int irq)
+{
+ if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
+ ipic_enable_irq(irq);
+}
+
+struct hw_interrupt_type ipic = {
+ .typename = " IPIC ",
+ .enable = ipic_enable_irq,
+ .disable = ipic_disable_irq,
+ .ack = ipic_disable_irq_and_ack,
+ .end = ipic_end_irq,
+};
+
+void __init ipic_init(phys_addr_t phys_addr,
+ unsigned int flags,
+ unsigned int irq_offset,
+ unsigned char *senses,
+ unsigned int senses_count)
+{
+ u32 i, temp = 0;
+
+ primary_ipic = &p_ipic;
+ primary_ipic->regs = ioremap(phys_addr, MPC83xx_IPIC_SIZE);
+
+ primary_ipic->irq_offset = irq_offset;
+
+ ipic_write(primary_ipic->regs, IPIC_SICNR, 0x0);
+
+ /* default priority scheme is grouped. If spread mode is required
+ * configure SICFR accordingly */
+ if (flags & IPIC_SPREADMODE_GRP_A)
+ temp |= SICFR_IPSA;
+ if (flags & IPIC_SPREADMODE_GRP_D)
+ temp |= SICFR_IPSD;
+ if (flags & IPIC_SPREADMODE_MIX_A)
+ temp |= SICFR_MPSA;
+ if (flags & IPIC_SPREADMODE_MIX_B)
+ temp |= SICFR_MPSB;
+
+ ipic_write(primary_ipic->regs, IPIC_SICNR, temp);
+
+ /* handle MCP route */
+ temp = 0;
+ if (flags & IPIC_DISABLE_MCP_OUT)
+ temp = SERCR_MCPR;
+ ipic_write(primary_ipic->regs, IPIC_SERCR, temp);
+
+ /* handle routing of IRQ0 to MCP */
+ temp = ipic_read(primary_ipic->regs, IPIC_SEMSR);
+
+ if (flags & IPIC_IRQ0_MCP)
+ temp |= SEMSR_SIRQ0;
+ else
+ temp &= ~SEMSR_SIRQ0;
+
+ ipic_write(primary_ipic->regs, IPIC_SEMSR, temp);
+
+ for (i = 0 ; i < NR_IPIC_INTS ; i++) {
+ irq_desc[i+irq_offset].handler = &ipic;
+ irq_desc[i+irq_offset].status = IRQ_LEVEL;
+ }
+
+ temp = 0;
+ for (i = 0 ; i < senses_count ; i++) {
+ if ((senses[i] & IRQ_SENSE_MASK) == IRQ_SENSE_EDGE) {
+ temp |= 1 << (16 - i);
+ if (i != 0)
+ irq_desc[i + irq_offset + MPC83xx_IRQ_EXT1 - 1].status = 0;
+ else
+ irq_desc[irq_offset + MPC83xx_IRQ_EXT0].status = 0;
+ }
+ }
+ ipic_write(primary_ipic->regs, IPIC_SECNR, temp);
+
+ printk ("IPIC (%d IRQ sources, %d External IRQs) at %p\n", NR_IPIC_INTS,
+ senses_count, primary_ipic->regs);
+}
+
+int ipic_set_priority(unsigned int irq, unsigned int priority)
+{
+ struct ipic *ipic = ipic_from_irq(irq);
+ unsigned int src = irq - ipic->irq_offset;
+ u32 temp;
+
+ if (priority > 7)
+ return -EINVAL;
+ if (src > 127)
+ return -EINVAL;
+ if (ipic_info[src].prio == 0)
+ return -EINVAL;
+
+ temp = ipic_read(ipic->regs, ipic_info[src].prio);
+
+ if (priority < 4) {
+ temp &= ~(0x7 << (20 + (3 - priority) * 3));
+ temp |= ipic_info[src].prio_mask << (20 + (3 - priority) * 3);
+ } else {
+ temp &= ~(0x7 << (4 + (7 - priority) * 3));
+ temp |= ipic_info[src].prio_mask << (4 + (7 - priority) * 3);
+ }
+
+ ipic_write(ipic->regs, ipic_info[src].prio, temp);
+
+ return 0;
+}
+
+void ipic_set_highest_priority(unsigned int irq)
+{
+ struct ipic *ipic = ipic_from_irq(irq);
+ unsigned int src = irq - ipic->irq_offset;
+ u32 temp;
+
+ temp = ipic_read(ipic->regs, IPIC_SICFR);
+
+ /* clear and set HPI */
+ temp &= 0x7f000000;
+ temp |= (src & 0x7f) << 24;
+
+ ipic_write(ipic->regs, IPIC_SICFR, temp);
+}
+
+void ipic_set_default_priority(void)
+{
+ ipic_set_priority(MPC83xx_IRQ_TSEC1_TX, 0);
+ ipic_set_priority(MPC83xx_IRQ_TSEC1_RX, 1);
+ ipic_set_priority(MPC83xx_IRQ_TSEC1_ERROR, 2);
+ ipic_set_priority(MPC83xx_IRQ_TSEC2_TX, 3);
+ ipic_set_priority(MPC83xx_IRQ_TSEC2_RX, 4);
+ ipic_set_priority(MPC83xx_IRQ_TSEC2_ERROR, 5);
+ ipic_set_priority(MPC83xx_IRQ_USB2_DR, 6);
+ ipic_set_priority(MPC83xx_IRQ_USB2_MPH, 7);
+
+ ipic_set_priority(MPC83xx_IRQ_UART1, 0);
+ ipic_set_priority(MPC83xx_IRQ_UART2, 1);
+ ipic_set_priority(MPC83xx_IRQ_SEC2, 2);
+ ipic_set_priority(MPC83xx_IRQ_IIC1, 5);
+ ipic_set_priority(MPC83xx_IRQ_IIC2, 6);
+ ipic_set_priority(MPC83xx_IRQ_SPI, 7);
+ ipic_set_priority(MPC83xx_IRQ_RTC_SEC, 0);
+ ipic_set_priority(MPC83xx_IRQ_PIT, 1);
+ ipic_set_priority(MPC83xx_IRQ_PCI1, 2);
+ ipic_set_priority(MPC83xx_IRQ_PCI2, 3);
+ ipic_set_priority(MPC83xx_IRQ_EXT0, 4);
+ ipic_set_priority(MPC83xx_IRQ_EXT1, 5);
+ ipic_set_priority(MPC83xx_IRQ_EXT2, 6);
+ ipic_set_priority(MPC83xx_IRQ_EXT3, 7);
+ ipic_set_priority(MPC83xx_IRQ_RTC_ALR, 0);
+ ipic_set_priority(MPC83xx_IRQ_MU, 1);
+ ipic_set_priority(MPC83xx_IRQ_SBA, 2);
+ ipic_set_priority(MPC83xx_IRQ_DMA, 3);
+ ipic_set_priority(MPC83xx_IRQ_EXT4, 4);
+ ipic_set_priority(MPC83xx_IRQ_EXT5, 5);
+ ipic_set_priority(MPC83xx_IRQ_EXT6, 6);
+ ipic_set_priority(MPC83xx_IRQ_EXT7, 7);
+}
+
+void ipic_enable_mcp(enum ipic_mcp_irq mcp_irq)
+{
+ struct ipic *ipic = primary_ipic;
+ u32 temp;
+
+ temp = ipic_read(ipic->regs, IPIC_SERMR);
+ temp |= (1 << (31 - mcp_irq));
+ ipic_write(ipic->regs, IPIC_SERMR, temp);
+}
+
+void ipic_disable_mcp(enum ipic_mcp_irq mcp_irq)
+{
+ struct ipic *ipic = primary_ipic;
+ u32 temp;
+
+ temp = ipic_read(ipic->regs, IPIC_SERMR);
+ temp &= (1 << (31 - mcp_irq));
+ ipic_write(ipic->regs, IPIC_SERMR, temp);
+}
+
+u32 ipic_get_mcp_status(void)
+{
+ return ipic_read(primary_ipic->regs, IPIC_SERMR);
+}
+
+void ipic_clear_mcp_status(u32 mask)
+{
+ ipic_write(primary_ipic->regs, IPIC_SERMR, mask);
+}
+
+/* Return an interrupt vector or -1 if no interrupt is pending. */
+int ipic_get_irq(struct pt_regs *regs)
+{
+ int irq;
+
+ irq = ipic_read(primary_ipic->regs, IPIC_SIVCR) & 0x7f;
+
+ if (irq == 0) /* 0 --> no irq is pending */
+ irq = -1;
+
+ return irq;
+}
+
+static struct sysdev_class ipic_sysclass = {
+ set_kset_name("ipic"),
+};
+
+static struct sys_device device_ipic = {
+ .id = 0,
+ .cls = &ipic_sysclass,
+};
+
+static int __init init_ipic_sysfs(void)
+{
+ int rc;
+
+ if (!primary_ipic->regs)
+ return -ENODEV;
+ printk(KERN_DEBUG "Registering ipic with sysfs...\n");
+
+ rc = sysdev_class_register(&ipic_sysclass);
+ if (rc) {
+ printk(KERN_ERR "Failed registering ipic sys class\n");
+ return -ENODEV;
+ }
+ rc = sysdev_register(&device_ipic);
+ if (rc) {
+ printk(KERN_ERR "Failed registering ipic sys device\n");
+ return -ENODEV;
+ }
+ return 0;
+}
+
+subsys_initcall(init_ipic_sysfs);
diff --git a/arch/ppc/syslib/ipic.h b/arch/ppc/syslib/ipic.h
new file mode 100644
index 0000000..2b56a4f
--- /dev/null
+++ b/arch/ppc/syslib/ipic.h
@@ -0,0 +1,49 @@
+/*
+ * arch/ppc/kernel/ipic.h
+ *
+ * IPIC private definitions and structure.
+ *
+ * Maintainer: Kumar Gala <kumar.gala@freescale.com>
+ *
+ * Copyright 2005 Freescale Semiconductor, Inc
+ *
+ * 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.
+ */
+#ifndef __IPIC_H__
+#define __IPIC_H__
+
+#include <asm/ipic.h>
+
+#define MPC83xx_IPIC_SIZE (0x00100)
+
+/* System Global Interrupt Configuration Register */
+#define SICFR_IPSA 0x00010000
+#define SICFR_IPSD 0x00080000
+#define SICFR_MPSA 0x00200000
+#define SICFR_MPSB 0x00400000
+
+/* System External Interrupt Mask Register */
+#define SEMSR_SIRQ0 0x00008000
+
+/* System Error Control Register */
+#define SERCR_MCPR 0x00000001
+
+struct ipic {
+ volatile u32 __iomem *regs;
+ unsigned int irq_offset;
+};
+
+struct ipic_info {
+ u8 pend; /* pending register offset from base */
+ u8 mask; /* mask register offset from base */
+ u8 prio; /* priority register offset from base */
+ u8 force; /* force register offset from base */
+ u8 bit; /* register bit position (as per doc)
+ bit mask = 1 << (31 - bit) */
+ u8 prio_mask; /* priority mask value */
+};
+
+#endif /* __IPIC_H__ */
diff --git a/arch/ppc/syslib/m8260_pci.c b/arch/ppc/syslib/m8260_pci.c
new file mode 100644
index 0000000..bd564fb
--- /dev/null
+++ b/arch/ppc/syslib/m8260_pci.c
@@ -0,0 +1,194 @@
+/*
+ * (C) Copyright 2003
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * (C) Copyright 2004 Red Hat, Inc.
+ *
+ * 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 <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+
+#include <asm/byteorder.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/uaccess.h>
+#include <asm/machdep.h>
+#include <asm/pci-bridge.h>
+#include <asm/immap_cpm2.h>
+#include <asm/mpc8260.h>
+
+#include "m8260_pci.h"
+
+
+/* PCI bus configuration registers.
+ */
+
+static void __init m8260_setup_pci(struct pci_controller *hose)
+{
+ volatile cpm2_map_t *immap = cpm2_immr;
+ unsigned long pocmr;
+ u16 tempShort;
+
+#ifndef CONFIG_ATC /* already done in U-Boot */
+ /*
+ * Setting required to enable IRQ1-IRQ7 (SIUMCR [DPPC]),
+ * and local bus for PCI (SIUMCR [LBPC]).
+ */
+ immap->im_siu_conf.siu_82xx.sc_siumcr = 0x00640000;
+#endif
+
+ /* Make PCI lowest priority */
+ /* Each 4 bits is a device bus request and the MS 4bits
+ is highest priority */
+ /* Bus 4bit value
+ --- ----------
+ CPM high 0b0000
+ CPM middle 0b0001
+ CPM low 0b0010
+ PCI reguest 0b0011
+ Reserved 0b0100
+ Reserved 0b0101
+ Internal Core 0b0110
+ External Master 1 0b0111
+ External Master 2 0b1000
+ External Master 3 0b1001
+ The rest are reserved */
+ immap->im_siu_conf.siu_82xx.sc_ppc_alrh = 0x61207893;
+
+ /* Park bus on core while modifying PCI Bus accesses */
+ immap->im_siu_conf.siu_82xx.sc_ppc_acr = 0x6;
+
+ /*
+ * Set up master window that allows the CPU to access PCI space. This
+ * window is set up using the first SIU PCIBR registers.
+ */
+ immap->im_memctl.memc_pcimsk0 = MPC826x_PCI_MASK;
+ immap->im_memctl.memc_pcibr0 = MPC826x_PCI_BASE | PCIBR_ENABLE;
+
+ /* Disable machine check on no response or target abort */
+ immap->im_pci.pci_emr = cpu_to_le32(0x1fe7);
+ /* Release PCI RST (by default the PCI RST signal is held low) */
+ immap->im_pci.pci_gcr = cpu_to_le32(PCIGCR_PCI_BUS_EN);
+
+ /* give it some time */
+ mdelay(1);
+
+ /*
+ * Set up master window that allows the CPU to access PCI Memory (prefetch)
+ * space. This window is set up using the first set of Outbound ATU registers.
+ */
+ immap->im_pci.pci_potar0 = cpu_to_le32(MPC826x_PCI_LOWER_MEM >> 12);
+ immap->im_pci.pci_pobar0 = cpu_to_le32((MPC826x_PCI_LOWER_MEM - MPC826x_PCI_MEM_OFFSET) >> 12);
+ pocmr = ((MPC826x_PCI_UPPER_MEM - MPC826x_PCI_LOWER_MEM) >> 12) ^ 0xfffff;
+ immap->im_pci.pci_pocmr0 = cpu_to_le32(pocmr | POCMR_ENABLE | POCMR_PREFETCH_EN);
+
+ /*
+ * Set up master window that allows the CPU to access PCI Memory (non-prefetch)
+ * space. This window is set up using the second set of Outbound ATU registers.
+ */
+ immap->im_pci.pci_potar1 = cpu_to_le32(MPC826x_PCI_LOWER_MMIO >> 12);
+ immap->im_pci.pci_pobar1 = cpu_to_le32((MPC826x_PCI_LOWER_MMIO - MPC826x_PCI_MMIO_OFFSET) >> 12);
+ pocmr = ((MPC826x_PCI_UPPER_MMIO - MPC826x_PCI_LOWER_MMIO) >> 12) ^ 0xfffff;
+ immap->im_pci.pci_pocmr1 = cpu_to_le32(pocmr | POCMR_ENABLE);
+
+ /*
+ * Set up master window that allows the CPU to access PCI IO space. This window
+ * is set up using the third set of Outbound ATU registers.
+ */
+ immap->im_pci.pci_potar2 = cpu_to_le32(MPC826x_PCI_IO_BASE >> 12);
+ immap->im_pci.pci_pobar2 = cpu_to_le32(MPC826x_PCI_LOWER_IO >> 12);
+ pocmr = ((MPC826x_PCI_UPPER_IO - MPC826x_PCI_LOWER_IO) >> 12) ^ 0xfffff;
+ immap->im_pci.pci_pocmr2 = cpu_to_le32(pocmr | POCMR_ENABLE | POCMR_PCI_IO);
+
+ /*
+ * Set up slave window that allows PCI masters to access MPC826x local memory.
+ * This window is set up using the first set of Inbound ATU registers
+ */
+
+ immap->im_pci.pci_pitar0 = cpu_to_le32(MPC826x_PCI_SLAVE_MEM_LOCAL >> 12);
+ immap->im_pci.pci_pibar0 = cpu_to_le32(MPC826x_PCI_SLAVE_MEM_BUS >> 12);
+ pocmr = ((MPC826x_PCI_SLAVE_MEM_SIZE-1) >> 12) ^ 0xfffff;
+ immap->im_pci.pci_picmr0 = cpu_to_le32(pocmr | PICMR_ENABLE | PICMR_PREFETCH_EN);
+
+ /* See above for description - puts PCI request as highest priority */
+ immap->im_siu_conf.siu_82xx.sc_ppc_alrh = 0x03124567;
+
+ /* Park the bus on the PCI */
+ immap->im_siu_conf.siu_82xx.sc_ppc_acr = PPC_ACR_BUS_PARK_PCI;
+
+ /* Host mode - specify the bridge as a host-PCI bridge */
+ early_write_config_word(hose, 0, 0, PCI_CLASS_DEVICE, PCI_CLASS_BRIDGE_HOST);
+
+ /* Enable the host bridge to be a master on the PCI bus, and to act as a PCI memory target */
+ early_read_config_word(hose, 0, 0, PCI_COMMAND, &tempShort);
+ early_write_config_word(hose, 0, 0, PCI_COMMAND,
+ tempShort | PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY);
+}
+
+void __init m8260_find_bridges(void)
+{
+ extern int pci_assign_all_busses;
+ struct pci_controller * hose;
+
+ pci_assign_all_busses = 1;
+
+ hose = pcibios_alloc_controller();
+
+ if (!hose)
+ return;
+
+ ppc_md.pci_swizzle = common_swizzle;
+
+ hose->first_busno = 0;
+ hose->bus_offset = 0;
+ hose->last_busno = 0xff;
+
+ setup_m8260_indirect_pci(hose,
+ (unsigned long)&cpm2_immr->im_pci.pci_cfg_addr,
+ (unsigned long)&cpm2_immr->im_pci.pci_cfg_data);
+
+ m8260_setup_pci(hose);
+ hose->pci_mem_offset = MPC826x_PCI_MEM_OFFSET;
+
+ isa_io_base =
+ (unsigned long) ioremap(MPC826x_PCI_IO_BASE,
+ MPC826x_PCI_IO_SIZE);
+ hose->io_base_virt = (void *) isa_io_base;
+
+ /* setup resources */
+ pci_init_resource(&hose->mem_resources[0],
+ MPC826x_PCI_LOWER_MEM,
+ MPC826x_PCI_UPPER_MEM,
+ IORESOURCE_MEM|IORESOURCE_PREFETCH, "PCI prefetchable memory");
+
+ pci_init_resource(&hose->mem_resources[1],
+ MPC826x_PCI_LOWER_MMIO,
+ MPC826x_PCI_UPPER_MMIO,
+ IORESOURCE_MEM, "PCI memory");
+
+ pci_init_resource(&hose->io_resource,
+ MPC826x_PCI_LOWER_IO,
+ MPC826x_PCI_UPPER_IO,
+ IORESOURCE_IO, "PCI I/O");
+}
diff --git a/arch/ppc/syslib/m8260_pci.h b/arch/ppc/syslib/m8260_pci.h
new file mode 100644
index 0000000..d1352120
--- /dev/null
+++ b/arch/ppc/syslib/m8260_pci.h
@@ -0,0 +1,76 @@
+
+#ifndef _PPC_KERNEL_M8260_PCI_H
+#define _PPC_KERNEL_M8260_PCI_H
+
+#include <asm/m8260_pci.h>
+
+/*
+ * Local->PCI map (from CPU) controlled by
+ * MPC826x master window
+ *
+ * 0x80000000 - 0xBFFFFFFF Total CPU2PCI space PCIBR0
+ *
+ * 0x80000000 - 0x9FFFFFFF PCI Mem with prefetch (Outbound ATU #1)
+ * 0xA0000000 - 0xAFFFFFFF PCI Mem w/o prefetch (Outbound ATU #2)
+ * 0xB0000000 - 0xB0FFFFFF 32-bit PCI IO (Outbound ATU #3)
+ *
+ * PCI->Local map (from PCI)
+ * MPC826x slave window controlled by
+ *
+ * 0x00000000 - 0x07FFFFFF MPC826x local memory (Inbound ATU #1)
+ */
+
+/*
+ * Slave window that allows PCI masters to access MPC826x local memory.
+ * This window is set up using the first set of Inbound ATU registers
+ */
+
+#ifndef MPC826x_PCI_SLAVE_MEM_LOCAL
+#define MPC826x_PCI_SLAVE_MEM_LOCAL (((struct bd_info *)__res)->bi_memstart)
+#define MPC826x_PCI_SLAVE_MEM_BUS (((struct bd_info *)__res)->bi_memstart)
+#define MPC826x_PCI_SLAVE_MEM_SIZE (((struct bd_info *)__res)->bi_memsize)
+#endif
+
+/*
+ * This is the window that allows the CPU to access PCI address space.
+ * It will be setup with the SIU PCIBR0 register. All three PCI master
+ * windows, which allow the CPU to access PCI prefetch, non prefetch,
+ * and IO space (see below), must all fit within this window.
+ */
+#ifndef MPC826x_PCI_BASE
+#define MPC826x_PCI_BASE 0x80000000
+#define MPC826x_PCI_MASK 0xc0000000
+#endif
+
+#ifndef MPC826x_PCI_LOWER_MEM
+#define MPC826x_PCI_LOWER_MEM 0x80000000
+#define MPC826x_PCI_UPPER_MEM 0x9fffffff
+#define MPC826x_PCI_MEM_OFFSET 0x00000000
+#endif
+
+#ifndef MPC826x_PCI_LOWER_MMIO
+#define MPC826x_PCI_LOWER_MMIO 0xa0000000
+#define MPC826x_PCI_UPPER_MMIO 0xafffffff
+#define MPC826x_PCI_MMIO_OFFSET 0x00000000
+#endif
+
+#ifndef MPC826x_PCI_LOWER_IO
+#define MPC826x_PCI_LOWER_IO 0x00000000
+#define MPC826x_PCI_UPPER_IO 0x00ffffff
+#define MPC826x_PCI_IO_BASE 0xb0000000
+#define MPC826x_PCI_IO_SIZE 0x01000000
+#endif
+
+#ifndef _IO_BASE
+#define _IO_BASE isa_io_base
+#endif
+
+#ifdef CONFIG_8260_PCI9
+struct pci_controller;
+extern void setup_m8260_indirect_pci(struct pci_controller* hose,
+ u32 cfg_addr, u32 cfg_data);
+#else
+#define setup_m8260_indirect_pci setup_indirect_pci
+#endif
+
+#endif /* _PPC_KERNEL_M8260_PCI_H */
diff --git a/arch/ppc/syslib/m8260_pci_erratum9.c b/arch/ppc/syslib/m8260_pci_erratum9.c
new file mode 100644
index 0000000..9c0582d
--- /dev/null
+++ b/arch/ppc/syslib/m8260_pci_erratum9.c
@@ -0,0 +1,473 @@
+/*
+ * arch/ppc/platforms/mpc8260_pci9.c
+ *
+ * Workaround for device erratum PCI 9.
+ * See Motorola's "XPC826xA Family Device Errata Reference."
+ * The erratum applies to all 8260 family Hip4 processors. It is scheduled
+ * to be fixed in HiP4 Rev C. Erratum PCI 9 states that a simultaneous PCI
+ * inbound write transaction and PCI outbound read transaction can result in a
+ * bus deadlock. The suggested workaround is to use the IDMA controller to
+ * perform all reads from PCI configuration, memory, and I/O space.
+ *
+ * Author: andy_lowe@mvista.com
+ *
+ * 2003 (c) MontaVista Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+#include <linux/kernel.h>
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/types.h>
+#include <linux/string.h>
+
+#include <asm/io.h>
+#include <asm/pci-bridge.h>
+#include <asm/machdep.h>
+#include <asm/byteorder.h>
+#include <asm/mpc8260.h>
+#include <asm/immap_cpm2.h>
+#include <asm/cpm2.h>
+
+#include "m8260_pci.h"
+
+#ifdef CONFIG_8260_PCI9
+/*#include <asm/mpc8260_pci9.h>*/ /* included in asm/io.h */
+
+#define IDMA_XFER_BUF_SIZE 64 /* size of the IDMA transfer buffer */
+
+/* define a structure for the IDMA dpram usage */
+typedef struct idma_dpram_s {
+ idma_t pram; /* IDMA parameter RAM */
+ u_char xfer_buf[IDMA_XFER_BUF_SIZE]; /* IDMA transfer buffer */
+ idma_bd_t bd; /* buffer descriptor */
+} idma_dpram_t;
+
+/* define offsets relative to start of IDMA dpram */
+#define IDMA_XFER_BUF_OFFSET (sizeof(idma_t))
+#define IDMA_BD_OFFSET (sizeof(idma_t) + IDMA_XFER_BUF_SIZE)
+
+/* define globals */
+static volatile idma_dpram_t *idma_dpram;
+
+/* Exactly one of CONFIG_8260_PCI9_IDMAn must be defined,
+ * where n is 1, 2, 3, or 4. This selects the IDMA channel used for
+ * the PCI9 workaround.
+ */
+#ifdef CONFIG_8260_PCI9_IDMA1
+#define IDMA_CHAN 0
+#define PROFF_IDMA PROFF_IDMA1_BASE
+#define IDMA_PAGE CPM_CR_IDMA1_PAGE
+#define IDMA_SBLOCK CPM_CR_IDMA1_SBLOCK
+#endif
+#ifdef CONFIG_8260_PCI9_IDMA2
+#define IDMA_CHAN 1
+#define PROFF_IDMA PROFF_IDMA2_BASE
+#define IDMA_PAGE CPM_CR_IDMA2_PAGE
+#define IDMA_SBLOCK CPM_CR_IDMA2_SBLOCK
+#endif
+#ifdef CONFIG_8260_PCI9_IDMA3
+#define IDMA_CHAN 2
+#define PROFF_IDMA PROFF_IDMA3_BASE
+#define IDMA_PAGE CPM_CR_IDMA3_PAGE
+#define IDMA_SBLOCK CPM_CR_IDMA3_SBLOCK
+#endif
+#ifdef CONFIG_8260_PCI9_IDMA4
+#define IDMA_CHAN 3
+#define PROFF_IDMA PROFF_IDMA4_BASE
+#define IDMA_PAGE CPM_CR_IDMA4_PAGE
+#define IDMA_SBLOCK CPM_CR_IDMA4_SBLOCK
+#endif
+
+void idma_pci9_init(void)
+{
+ uint dpram_offset;
+ volatile idma_t *pram;
+ volatile im_idma_t *idma_reg;
+ volatile cpm2_map_t *immap = cpm2_immr;
+
+ /* allocate IDMA dpram */
+ dpram_offset = cpm_dpalloc(sizeof(idma_dpram_t), 64);
+ idma_dpram = cpm_dpram_addr(dpram_offset);
+
+ /* initialize the IDMA parameter RAM */
+ memset((void *)idma_dpram, 0, sizeof(idma_dpram_t));
+ pram = &idma_dpram->pram;
+ pram->ibase = dpram_offset + IDMA_BD_OFFSET;
+ pram->dpr_buf = dpram_offset + IDMA_XFER_BUF_OFFSET;
+ pram->ss_max = 32;
+ pram->dts = 32;
+
+ /* initialize the IDMA_BASE pointer to the IDMA parameter RAM */
+ *((ushort *) &immap->im_dprambase[PROFF_IDMA]) = dpram_offset;
+
+ /* initialize the IDMA registers */
+ idma_reg = (volatile im_idma_t *) &immap->im_sdma.sdma_idsr1;
+ idma_reg[IDMA_CHAN].idmr = 0; /* mask all IDMA interrupts */
+ idma_reg[IDMA_CHAN].idsr = 0xff; /* clear all event flags */
+
+ printk("<4>Using IDMA%d for MPC8260 device erratum PCI 9 workaround\n",
+ IDMA_CHAN + 1);
+
+ return;
+}
+
+/* Use the IDMA controller to transfer data from I/O memory to local RAM.
+ * The src address must be a physical address suitable for use by the DMA
+ * controller with no translation. The dst address must be a kernel virtual
+ * address. The dst address is translated to a physical address via
+ * virt_to_phys().
+ * The sinc argument specifies whether or not the source address is incremented
+ * by the DMA controller. The source address is incremented if and only if sinc
+ * is non-zero. The destination address is always incremented since the
+ * destination is always host RAM.
+ */
+static void
+idma_pci9_read(u8 *dst, u8 *src, int bytes, int unit_size, int sinc)
+{
+ unsigned long flags;
+ volatile idma_t *pram = &idma_dpram->pram;
+ volatile idma_bd_t *bd = &idma_dpram->bd;
+ volatile cpm2_map_t *immap = cpm2_immr;
+
+ local_irq_save(flags);
+
+ /* initialize IDMA parameter RAM for this transfer */
+ if (sinc)
+ pram->dcm = IDMA_DCM_DMA_WRAP_64 | IDMA_DCM_SINC
+ | IDMA_DCM_DINC | IDMA_DCM_SD_MEM2MEM;
+ else
+ pram->dcm = IDMA_DCM_DMA_WRAP_64 | IDMA_DCM_DINC
+ | IDMA_DCM_SD_MEM2MEM;
+ pram->ibdptr = pram->ibase;
+ pram->sts = unit_size;
+ pram->istate = 0;
+
+ /* initialize the buffer descriptor */
+ bd->dst = virt_to_phys(dst);
+ bd->src = (uint) src;
+ bd->len = bytes;
+ bd->flags = IDMA_BD_V | IDMA_BD_W | IDMA_BD_I | IDMA_BD_L | IDMA_BD_DGBL
+ | IDMA_BD_DBO_BE | IDMA_BD_SBO_BE | IDMA_BD_SDTB;
+
+ /* issue the START_IDMA command to the CP */
+ while (immap->im_cpm.cp_cpcr & CPM_CR_FLG);
+ immap->im_cpm.cp_cpcr = mk_cr_cmd(IDMA_PAGE, IDMA_SBLOCK, 0,
+ CPM_CR_START_IDMA) | CPM_CR_FLG;
+ while (immap->im_cpm.cp_cpcr & CPM_CR_FLG);
+
+ /* wait for transfer to complete */
+ while(bd->flags & IDMA_BD_V);
+
+ local_irq_restore(flags);
+
+ return;
+}
+
+/* Use the IDMA controller to transfer data from I/O memory to local RAM.
+ * The dst address must be a physical address suitable for use by the DMA
+ * controller with no translation. The src address must be a kernel virtual
+ * address. The src address is translated to a physical address via
+ * virt_to_phys().
+ * The dinc argument specifies whether or not the dest address is incremented
+ * by the DMA controller. The source address is incremented if and only if sinc
+ * is non-zero. The source address is always incremented since the
+ * source is always host RAM.
+ */
+static void
+idma_pci9_write(u8 *dst, u8 *src, int bytes, int unit_size, int dinc)
+{
+ unsigned long flags;
+ volatile idma_t *pram = &idma_dpram->pram;
+ volatile idma_bd_t *bd = &idma_dpram->bd;
+ volatile cpm2_map_t *immap = cpm2_immr;
+
+ local_irq_save(flags);
+
+ /* initialize IDMA parameter RAM for this transfer */
+ if (dinc)
+ pram->dcm = IDMA_DCM_DMA_WRAP_64 | IDMA_DCM_SINC
+ | IDMA_DCM_DINC | IDMA_DCM_SD_MEM2MEM;
+ else
+ pram->dcm = IDMA_DCM_DMA_WRAP_64 | IDMA_DCM_SINC
+ | IDMA_DCM_SD_MEM2MEM;
+ pram->ibdptr = pram->ibase;
+ pram->sts = unit_size;
+ pram->istate = 0;
+
+ /* initialize the buffer descriptor */
+ bd->dst = (uint) dst;
+ bd->src = virt_to_phys(src);
+ bd->len = bytes;
+ bd->flags = IDMA_BD_V | IDMA_BD_W | IDMA_BD_I | IDMA_BD_L | IDMA_BD_DGBL
+ | IDMA_BD_DBO_BE | IDMA_BD_SBO_BE | IDMA_BD_SDTB;
+
+ /* issue the START_IDMA command to the CP */
+ while (immap->im_cpm.cp_cpcr & CPM_CR_FLG);
+ immap->im_cpm.cp_cpcr = mk_cr_cmd(IDMA_PAGE, IDMA_SBLOCK, 0,
+ CPM_CR_START_IDMA) | CPM_CR_FLG;
+ while (immap->im_cpm.cp_cpcr & CPM_CR_FLG);
+
+ /* wait for transfer to complete */
+ while(bd->flags & IDMA_BD_V);
+
+ local_irq_restore(flags);
+
+ return;
+}
+
+/* Same as idma_pci9_read, but 16-bit little-endian byte swapping is performed
+ * if the unit_size is 2, and 32-bit little-endian byte swapping is performed if
+ * the unit_size is 4.
+ */
+static void
+idma_pci9_read_le(u8 *dst, u8 *src, int bytes, int unit_size, int sinc)
+{
+ int i;
+ u8 *p;
+
+ idma_pci9_read(dst, src, bytes, unit_size, sinc);
+ switch(unit_size) {
+ case 2:
+ for (i = 0, p = dst; i < bytes; i += 2, p += 2)
+ swab16s((u16 *) p);
+ break;
+ case 4:
+ for (i = 0, p = dst; i < bytes; i += 4, p += 4)
+ swab32s((u32 *) p);
+ break;
+ default:
+ break;
+ }
+}
+EXPORT_SYMBOL(idma_pci9_init);
+EXPORT_SYMBOL(idma_pci9_read);
+EXPORT_SYMBOL(idma_pci9_read_le);
+
+static inline int is_pci_mem(unsigned long addr)
+{
+ if (addr >= MPC826x_PCI_LOWER_MMIO &&
+ addr <= MPC826x_PCI_UPPER_MMIO)
+ return 1;
+ if (addr >= MPC826x_PCI_LOWER_MEM &&
+ addr <= MPC826x_PCI_UPPER_MEM)
+ return 1;
+ return 0;
+}
+
+#define is_pci_mem(pa) ( (pa > 0x80000000) && (pa < 0xc0000000))
+int readb(volatile unsigned char *addr)
+{
+ u8 val;
+ unsigned long pa = iopa((unsigned long) addr);
+
+ if (!is_pci_mem(pa))
+ return in_8(addr);
+
+ idma_pci9_read((u8 *)&val, (u8 *)pa, sizeof(val), sizeof(val), 0);
+ return val;
+}
+
+int readw(volatile unsigned short *addr)
+{
+ u16 val;
+ unsigned long pa = iopa((unsigned long) addr);
+
+ if (!is_pci_mem(pa))
+ return in_le16(addr);
+
+ idma_pci9_read((u8 *)&val, (u8 *)pa, sizeof(val), sizeof(val), 0);
+ return swab16(val);
+}
+
+unsigned readl(volatile unsigned *addr)
+{
+ u32 val;
+ unsigned long pa = iopa((unsigned long) addr);
+
+ if (!is_pci_mem(pa))
+ return in_le32(addr);
+
+ idma_pci9_read((u8 *)&val, (u8 *)pa, sizeof(val), sizeof(val), 0);
+ return swab32(val);
+}
+
+int inb(unsigned port)
+{
+ u8 val;
+ u8 *addr = (u8 *)(port + _IO_BASE);
+
+ idma_pci9_read((u8 *)&val, (u8 *)addr, sizeof(val), sizeof(val), 0);
+ return val;
+}
+
+int inw(unsigned port)
+{
+ u16 val;
+ u8 *addr = (u8 *)(port + _IO_BASE);
+
+ idma_pci9_read((u8 *)&val, (u8 *)addr, sizeof(val), sizeof(val), 0);
+ return swab16(val);
+}
+
+unsigned inl(unsigned port)
+{
+ u32 val;
+ u8 *addr = (u8 *)(port + _IO_BASE);
+
+ idma_pci9_read((u8 *)&val, (u8 *)addr, sizeof(val), sizeof(val), 0);
+ return swab32(val);
+}
+
+void insb(unsigned port, void *buf, int ns)
+{
+ u8 *addr = (u8 *)(port + _IO_BASE);
+
+ idma_pci9_read((u8 *)buf, (u8 *)addr, ns*sizeof(u8), sizeof(u8), 0);
+}
+
+void insw(unsigned port, void *buf, int ns)
+{
+ u8 *addr = (u8 *)(port + _IO_BASE);
+
+ idma_pci9_read((u8 *)buf, (u8 *)addr, ns*sizeof(u16), sizeof(u16), 0);
+}
+
+void insl(unsigned port, void *buf, int nl)
+{
+ u8 *addr = (u8 *)(port + _IO_BASE);
+
+ idma_pci9_read((u8 *)buf, (u8 *)addr, nl*sizeof(u32), sizeof(u32), 0);
+}
+
+void insw_ns(unsigned port, void *buf, int ns)
+{
+ u8 *addr = (u8 *)(port + _IO_BASE);
+
+ idma_pci9_read((u8 *)buf, (u8 *)addr, ns*sizeof(u16), sizeof(u16), 0);
+}
+
+void insl_ns(unsigned port, void *buf, int nl)
+{
+ u8 *addr = (u8 *)(port + _IO_BASE);
+
+ idma_pci9_read((u8 *)buf, (u8 *)addr, nl*sizeof(u32), sizeof(u32), 0);
+}
+
+void *memcpy_fromio(void *dest, unsigned long src, size_t count)
+{
+ unsigned long pa = iopa((unsigned long) src);
+
+ if (is_pci_mem(pa))
+ idma_pci9_read((u8 *)dest, (u8 *)pa, count, 32, 1);
+ else
+ memcpy(dest, (void *)src, count);
+ return dest;
+}
+
+EXPORT_SYMBOL(readb);
+EXPORT_SYMBOL(readw);
+EXPORT_SYMBOL(readl);
+EXPORT_SYMBOL(inb);
+EXPORT_SYMBOL(inw);
+EXPORT_SYMBOL(inl);
+EXPORT_SYMBOL(insb);
+EXPORT_SYMBOL(insw);
+EXPORT_SYMBOL(insl);
+EXPORT_SYMBOL(insw_ns);
+EXPORT_SYMBOL(insl_ns);
+EXPORT_SYMBOL(memcpy_fromio);
+
+#endif /* ifdef CONFIG_8260_PCI9 */
+
+/* Indirect PCI routines adapted from arch/ppc/kernel/indirect_pci.c.
+ * Copyright (C) 1998 Gabriel Paubert.
+ */
+#ifndef CONFIG_8260_PCI9
+#define cfg_read(val, addr, type, op) *val = op((type)(addr))
+#else
+#define cfg_read(val, addr, type, op) \
+ idma_pci9_read_le((u8*)(val),(u8*)(addr),sizeof(*(val)),sizeof(*(val)),0)
+#endif
+
+#define cfg_write(val, addr, type, op) op((type *)(addr), (val))
+
+static int indirect_write_config(struct pci_bus *pbus, unsigned int devfn, int where,
+ int size, u32 value)
+{
+ struct pci_controller *hose = pbus->sysdata;
+ u8 cfg_type = 0;
+ if (ppc_md.pci_exclude_device)
+ if (ppc_md.pci_exclude_device(pbus->number, devfn))
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
+ if (hose->set_cfg_type)
+ if (pbus->number != hose->first_busno)
+ cfg_type = 1;
+
+ out_be32(hose->cfg_addr,
+ (((where & 0xfc) | cfg_type) << 24) | (devfn << 16)
+ | ((pbus->number - hose->bus_offset) << 8) | 0x80);
+
+ switch (size)
+ {
+ case 1:
+ cfg_write(value, hose->cfg_data + (where & 3), u8, out_8);
+ break;
+ case 2:
+ cfg_write(value, hose->cfg_data + (where & 2), u16, out_le16);
+ break;
+ case 4:
+ cfg_write(value, hose->cfg_data + (where & 0), u32, out_le32);
+ break;
+ }
+ return PCIBIOS_SUCCESSFUL;
+}
+
+static int indirect_read_config(struct pci_bus *pbus, unsigned int devfn, int where,
+ int size, u32 *value)
+{
+ struct pci_controller *hose = pbus->sysdata;
+ u8 cfg_type = 0;
+ if (ppc_md.pci_exclude_device)
+ if (ppc_md.pci_exclude_device(pbus->number, devfn))
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
+ if (hose->set_cfg_type)
+ if (pbus->number != hose->first_busno)
+ cfg_type = 1;
+
+ out_be32(hose->cfg_addr,
+ (((where & 0xfc) | cfg_type) << 24) | (devfn << 16)
+ | ((pbus->number - hose->bus_offset) << 8) | 0x80);
+
+ switch (size)
+ {
+ case 1:
+ cfg_read(value, hose->cfg_data + (where & 3), u8 *, in_8);
+ break;
+ case 2:
+ cfg_read(value, hose->cfg_data + (where & 2), u16 *, in_le16);
+ break;
+ case 4:
+ cfg_read(value, hose->cfg_data + (where & 0), u32 *, in_le32);
+ break;
+ }
+ return PCIBIOS_SUCCESSFUL;
+}
+
+static struct pci_ops indirect_pci_ops =
+{
+ .read = indirect_read_config,
+ .write = indirect_write_config,
+};
+
+void
+setup_m8260_indirect_pci(struct pci_controller* hose, u32 cfg_addr, u32 cfg_data)
+{
+ hose->ops = &indirect_pci_ops;
+ hose->cfg_addr = (unsigned int *) ioremap(cfg_addr, 4);
+ hose->cfg_data = (unsigned char *) ioremap(cfg_data, 4);
+}
diff --git a/arch/ppc/syslib/m8260_setup.c b/arch/ppc/syslib/m8260_setup.c
new file mode 100644
index 0000000..23ea3f6
--- /dev/null
+++ b/arch/ppc/syslib/m8260_setup.c
@@ -0,0 +1,264 @@
+/*
+ * arch/ppc/syslib/m8260_setup.c
+ *
+ * Copyright (C) 1995 Linus Torvalds
+ * Adapted from 'alpha' version by Gary Thomas
+ * Modified by Cort Dougan (cort@cs.nmt.edu)
+ * Modified for MBX using prep/chrp/pmac functions by Dan (dmalek@jlc.net)
+ * Further modified for generic 8xx and 8260 by Dan.
+ */
+
+#include <linux/config.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/stddef.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <linux/initrd.h>
+#include <linux/root_dev.h>
+#include <linux/seq_file.h>
+#include <linux/irq.h>
+
+#include <asm/mmu.h>
+#include <asm/io.h>
+#include <asm/pgtable.h>
+#include <asm/mpc8260.h>
+#include <asm/immap_cpm2.h>
+#include <asm/machdep.h>
+#include <asm/bootinfo.h>
+#include <asm/time.h>
+
+#include "cpm2_pic.h"
+
+unsigned char __res[sizeof(bd_t)];
+
+extern void cpm2_reset(void);
+extern void m8260_find_bridges(void);
+extern void idma_pci9_init(void);
+
+/* Place-holder for board-specific init */
+void __attribute__ ((weak)) __init
+m82xx_board_setup(void)
+{
+}
+
+static void __init
+m8260_setup_arch(void)
+{
+ /* Print out Vendor and Machine info. */
+ printk(KERN_INFO "%s %s port\n", CPUINFO_VENDOR, CPUINFO_MACHINE);
+
+ /* Reset the Communication Processor Module. */
+ cpm2_reset();
+#ifdef CONFIG_8260_PCI9
+ /* Initialise IDMA for PCI erratum workaround */
+ idma_pci9_init();
+#endif
+#ifdef CONFIG_PCI_8260
+ m8260_find_bridges();
+#endif
+#ifdef CONFIG_BLK_DEV_INITRD
+ if (initrd_start)
+ ROOT_DEV = Root_RAM0;
+#endif
+ m82xx_board_setup();
+}
+
+/* The decrementer counts at the system (internal) clock frequency
+ * divided by four.
+ */
+static void __init
+m8260_calibrate_decr(void)
+{
+ bd_t *binfo = (bd_t *)__res;
+ int freq, divisor;
+
+ freq = binfo->bi_busfreq;
+ divisor = 4;
+ tb_ticks_per_jiffy = freq / HZ / divisor;
+ tb_to_us = mulhwu_scale_factor(freq / divisor, 1000000);
+}
+
+/* The 8260 has an internal 1-second timer update register that
+ * we should use for this purpose.
+ */
+static uint rtc_time;
+
+static int
+m8260_set_rtc_time(unsigned long time)
+{
+ rtc_time = time;
+
+ return(0);
+}
+
+static unsigned long
+m8260_get_rtc_time(void)
+{
+ /* Get time from the RTC.
+ */
+ return((unsigned long)rtc_time);
+}
+
+#ifndef BOOTROM_RESTART_ADDR
+#warning "Using default BOOTROM_RESTART_ADDR!"
+#define BOOTROM_RESTART_ADDR 0xff000104
+#endif
+
+static void
+m8260_restart(char *cmd)
+{
+ extern void m8260_gorom(bd_t *bi, uint addr);
+ uint startaddr;
+
+ /* Most boot roms have a warmstart as the second instruction
+ * of the reset vector. If that doesn't work for you, change this
+ * or the reboot program to send a proper address.
+ */
+ startaddr = BOOTROM_RESTART_ADDR;
+ if (cmd != NULL) {
+ if (!strncmp(cmd, "startaddr=", 10))
+ startaddr = simple_strtoul(&cmd[10], NULL, 0);
+ }
+
+ m8260_gorom((void*)__pa(__res), startaddr);
+}
+
+static void
+m8260_halt(void)
+{
+ local_irq_disable();
+ while (1);
+}
+
+static void
+m8260_power_off(void)
+{
+ m8260_halt();
+}
+
+static int
+m8260_show_cpuinfo(struct seq_file *m)
+{
+ bd_t *bp = (bd_t *)__res;
+
+ seq_printf(m, "vendor\t\t: %s\n"
+ "machine\t\t: %s\n"
+ "\n"
+ "mem size\t\t: 0x%08x\n"
+ "console baud\t\t: %d\n"
+ "\n"
+ "core clock\t: %u MHz\n"
+ "CPM clock\t: %u MHz\n"
+ "bus clock\t: %u MHz\n",
+ CPUINFO_VENDOR, CPUINFO_MACHINE, bp->bi_memsize,
+ bp->bi_baudrate, bp->bi_intfreq / 1000000,
+ bp->bi_cpmfreq / 1000000, bp->bi_busfreq / 1000000);
+ return 0;
+}
+
+/* Initialize the internal interrupt controller. The number of
+ * interrupts supported can vary with the processor type, and the
+ * 8260 family can have up to 64.
+ * External interrupts can be either edge or level triggered, and
+ * need to be initialized by the appropriate driver.
+ */
+static void __init
+m8260_init_IRQ(void)
+{
+ cpm2_init_IRQ();
+
+ /* Initialize the default interrupt mapping priorities,
+ * in case the boot rom changed something on us.
+ */
+ cpm2_immr->im_intctl.ic_siprr = 0x05309770;
+}
+
+/*
+ * Same hack as 8xx
+ */
+static unsigned long __init
+m8260_find_end_of_memory(void)
+{
+ bd_t *binfo = (bd_t *)__res;
+
+ return binfo->bi_memsize;
+}
+
+/* Map the IMMR, plus anything else we can cover
+ * in that upper space according to the memory controller
+ * chip select mapping. Grab another bunch of space
+ * below that for stuff we can't cover in the upper.
+ */
+static void __init
+m8260_map_io(void)
+{
+ uint addr;
+
+ /* Map IMMR region to a 256MB BAT */
+ addr = (cpm2_immr != NULL) ? (uint)cpm2_immr : CPM_MAP_ADDR;
+ io_block_mapping(addr, addr, 0x10000000, _PAGE_IO);
+
+ /* Map I/O region to a 256MB BAT */
+ io_block_mapping(IO_VIRT_ADDR, IO_PHYS_ADDR, 0x10000000, _PAGE_IO);
+}
+
+/* Place-holder for board-specific ppc_md hooking */
+void __attribute__ ((weak)) __init
+m82xx_board_init(void)
+{
+}
+
+/* Inputs:
+ * r3 - Optional pointer to a board information structure.
+ * r4 - Optional pointer to the physical starting address of the init RAM
+ * disk.
+ * r5 - Optional pointer to the physical ending address of the init RAM
+ * disk.
+ * r6 - Optional pointer to the physical starting address of any kernel
+ * command-line parameters.
+ * r7 - Optional pointer to the physical ending address of any kernel
+ * command-line parameters.
+ */
+void __init
+platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
+ unsigned long r6, unsigned long r7)
+{
+ parse_bootinfo(find_bootinfo());
+
+ if ( r3 )
+ memcpy( (void *)__res,(void *)(r3+KERNELBASE), sizeof(bd_t) );
+
+#ifdef CONFIG_BLK_DEV_INITRD
+ /* take care of initrd if we have one */
+ if ( r4 ) {
+ initrd_start = r4 + KERNELBASE;
+ initrd_end = r5 + KERNELBASE;
+ }
+#endif /* CONFIG_BLK_DEV_INITRD */
+ /* take care of cmd line */
+ if ( r6 ) {
+ *(char *)(r7+KERNELBASE) = 0;
+ strcpy(cmd_line, (char *)(r6+KERNELBASE));
+ }
+
+ ppc_md.setup_arch = m8260_setup_arch;
+ ppc_md.show_cpuinfo = m8260_show_cpuinfo;
+ ppc_md.init_IRQ = m8260_init_IRQ;
+ ppc_md.get_irq = cpm2_get_irq;
+
+ ppc_md.restart = m8260_restart;
+ ppc_md.power_off = m8260_power_off;
+ ppc_md.halt = m8260_halt;
+
+ ppc_md.set_rtc_time = m8260_set_rtc_time;
+ ppc_md.get_rtc_time = m8260_get_rtc_time;
+ ppc_md.calibrate_decr = m8260_calibrate_decr;
+
+ ppc_md.find_end_of_memory = m8260_find_end_of_memory;
+ ppc_md.setup_io_mappings = m8260_map_io;
+
+ /* Call back for board-specific settings and overrides. */
+ m82xx_board_init();
+}
diff --git a/arch/ppc/syslib/m8xx_setup.c b/arch/ppc/syslib/m8xx_setup.c
new file mode 100644
index 0000000..c1db2ab
--- /dev/null
+++ b/arch/ppc/syslib/m8xx_setup.c
@@ -0,0 +1,433 @@
+/*
+ * arch/ppc/kernel/setup.c
+ *
+ * Copyright (C) 1995 Linus Torvalds
+ * Adapted from 'alpha' version by Gary Thomas
+ * Modified by Cort Dougan (cort@cs.nmt.edu)
+ * Modified for MBX using prep/chrp/pmac functions by Dan (dmalek@jlc.net)
+ * Further modified for generic 8xx by Dan.
+ */
+
+/*
+ * bootup setup stuff..
+ */
+
+#include <linux/config.h>
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/stddef.h>
+#include <linux/unistd.h>
+#include <linux/ptrace.h>
+#include <linux/slab.h>
+#include <linux/user.h>
+#include <linux/a.out.h>
+#include <linux/tty.h>
+#include <linux/major.h>
+#include <linux/interrupt.h>
+#include <linux/reboot.h>
+#include <linux/init.h>
+#include <linux/initrd.h>
+#include <linux/ioport.h>
+#include <linux/bootmem.h>
+#include <linux/seq_file.h>
+#include <linux/root_dev.h>
+
+#include <asm/mmu.h>
+#include <asm/reg.h>
+#include <asm/residual.h>
+#include <asm/io.h>
+#include <asm/pgtable.h>
+#include <asm/mpc8xx.h>
+#include <asm/8xx_immap.h>
+#include <asm/machdep.h>
+#include <asm/bootinfo.h>
+#include <asm/time.h>
+#include <asm/xmon.h>
+
+#include "ppc8xx_pic.h"
+
+static int m8xx_set_rtc_time(unsigned long time);
+static unsigned long m8xx_get_rtc_time(void);
+void m8xx_calibrate_decr(void);
+
+unsigned char __res[sizeof(bd_t)];
+
+extern void m8xx_ide_init(void);
+
+extern unsigned long find_available_memory(void);
+extern void m8xx_cpm_reset(uint cpm_page);
+extern void m8xx_wdt_handler_install(bd_t *bp);
+extern void rpxfb_alloc_pages(void);
+extern void cpm_interrupt_init(void);
+
+void __attribute__ ((weak))
+board_init(void)
+{
+}
+
+void __init
+m8xx_setup_arch(void)
+{
+ int cpm_page;
+
+ cpm_page = (int) alloc_bootmem_pages(PAGE_SIZE);
+
+ /* Reset the Communication Processor Module.
+ */
+ m8xx_cpm_reset(cpm_page);
+
+#ifdef CONFIG_FB_RPX
+ rpxfb_alloc_pages();
+#endif
+
+#ifdef notdef
+ ROOT_DEV = Root_HDA1; /* hda1 */
+#endif
+
+#ifdef CONFIG_BLK_DEV_INITRD
+#if 0
+ ROOT_DEV = Root_FD0; /* floppy */
+ rd_prompt = 1;
+ rd_doload = 1;
+ rd_image_start = 0;
+#endif
+#if 0 /* XXX this may need to be updated for the new bootmem stuff,
+ or possibly just deleted (see set_phys_avail() in init.c).
+ - paulus. */
+ /* initrd_start and size are setup by boot/head.S and kernel/head.S */
+ if ( initrd_start )
+ {
+ if (initrd_end > *memory_end_p)
+ {
+ printk("initrd extends beyond end of memory "
+ "(0x%08lx > 0x%08lx)\ndisabling initrd\n",
+ initrd_end,*memory_end_p);
+ initrd_start = 0;
+ }
+ }
+#endif
+#endif
+ board_init();
+}
+
+void
+abort(void)
+{
+#ifdef CONFIG_XMON
+ xmon(0);
+#endif
+ machine_restart(NULL);
+
+ /* not reached */
+ for (;;);
+}
+
+/* A place holder for time base interrupts, if they are ever enabled. */
+irqreturn_t timebase_interrupt(int irq, void * dev, struct pt_regs * regs)
+{
+ printk ("timebase_interrupt()\n");
+
+ return IRQ_HANDLED;
+}
+
+static struct irqaction tbint_irqaction = {
+ .handler = timebase_interrupt,
+ .mask = CPU_MASK_NONE,
+ .name = "tbint",
+};
+
+/* The decrementer counts at the system (internal) clock frequency divided by
+ * sixteen, or external oscillator divided by four. We force the processor
+ * to use system clock divided by sixteen.
+ */
+void __init m8xx_calibrate_decr(void)
+{
+ bd_t *binfo = (bd_t *)__res;
+ int freq, fp, divisor;
+
+ /* Unlock the SCCR. */
+ ((volatile immap_t *)IMAP_ADDR)->im_clkrstk.cark_sccrk = ~KAPWR_KEY;
+ ((volatile immap_t *)IMAP_ADDR)->im_clkrstk.cark_sccrk = KAPWR_KEY;
+
+ /* Force all 8xx processors to use divide by 16 processor clock. */
+ ((volatile immap_t *)IMAP_ADDR)->im_clkrst.car_sccr |= 0x02000000;
+
+ /* Processor frequency is MHz.
+ * The value 'fp' is the number of decrementer ticks per second.
+ */
+ fp = binfo->bi_intfreq / 16;
+ freq = fp*60; /* try to make freq/1e6 an integer */
+ divisor = 60;
+ printk("Decrementer Frequency = %d/%d\n", freq, divisor);
+ tb_ticks_per_jiffy = freq / HZ / divisor;
+ tb_to_us = mulhwu_scale_factor(freq / divisor, 1000000);
+
+ /* Perform some more timer/timebase initialization. This used
+ * to be done elsewhere, but other changes caused it to get
+ * called more than once....that is a bad thing.
+ *
+ * First, unlock all of the registers we are going to modify.
+ * To protect them from corruption during power down, registers
+ * that are maintained by keep alive power are "locked". To
+ * modify these registers we have to write the key value to
+ * the key location associated with the register.
+ * Some boards power up with these unlocked, while others
+ * are locked. Writing anything (including the unlock code?)
+ * to the unlocked registers will lock them again. So, here
+ * we guarantee the registers are locked, then we unlock them
+ * for our use.
+ */
+ ((volatile immap_t *)IMAP_ADDR)->im_sitk.sitk_tbscrk = ~KAPWR_KEY;
+ ((volatile immap_t *)IMAP_ADDR)->im_sitk.sitk_rtcsck = ~KAPWR_KEY;
+ ((volatile immap_t *)IMAP_ADDR)->im_sitk.sitk_tbk = ~KAPWR_KEY;
+ ((volatile immap_t *)IMAP_ADDR)->im_sitk.sitk_tbscrk = KAPWR_KEY;
+ ((volatile immap_t *)IMAP_ADDR)->im_sitk.sitk_rtcsck = KAPWR_KEY;
+ ((volatile immap_t *)IMAP_ADDR)->im_sitk.sitk_tbk = KAPWR_KEY;
+
+ /* Disable the RTC one second and alarm interrupts. */
+ ((volatile immap_t *)IMAP_ADDR)->im_sit.sit_rtcsc &=
+ ~(RTCSC_SIE | RTCSC_ALE);
+ /* Enable the RTC */
+ ((volatile immap_t *)IMAP_ADDR)->im_sit.sit_rtcsc |=
+ (RTCSC_RTF | RTCSC_RTE);
+
+ /* Enabling the decrementer also enables the timebase interrupts
+ * (or from the other point of view, to get decrementer interrupts
+ * we have to enable the timebase). The decrementer interrupt
+ * is wired into the vector table, nothing to do here for that.
+ */
+ ((volatile immap_t *)IMAP_ADDR)->im_sit.sit_tbscr =
+ ((mk_int_int_mask(DEC_INTERRUPT) << 8) |
+ (TBSCR_TBF | TBSCR_TBE));
+
+ if (setup_irq(DEC_INTERRUPT, &tbint_irqaction))
+ panic("Could not allocate timer IRQ!");
+
+#ifdef CONFIG_8xx_WDT
+ /* Install watchdog timer handler early because it might be
+ * already enabled by the bootloader
+ */
+ m8xx_wdt_handler_install(binfo);
+#endif
+}
+
+/* The RTC on the MPC8xx is an internal register.
+ * We want to protect this during power down, so we need to unlock,
+ * modify, and re-lock.
+ */
+static int
+m8xx_set_rtc_time(unsigned long time)
+{
+ ((volatile immap_t *)IMAP_ADDR)->im_sitk.sitk_rtck = KAPWR_KEY;
+ ((volatile immap_t *)IMAP_ADDR)->im_sit.sit_rtc = time;
+ ((volatile immap_t *)IMAP_ADDR)->im_sitk.sitk_rtck = ~KAPWR_KEY;
+ return(0);
+}
+
+static unsigned long
+m8xx_get_rtc_time(void)
+{
+ /* Get time from the RTC. */
+ return((unsigned long)(((immap_t *)IMAP_ADDR)->im_sit.sit_rtc));
+}
+
+static void
+m8xx_restart(char *cmd)
+{
+ __volatile__ unsigned char dummy;
+
+ local_irq_disable();
+ ((immap_t *)IMAP_ADDR)->im_clkrst.car_plprcr |= 0x00000080;
+
+ /* Clear the ME bit in MSR to cause checkstop on machine check
+ */
+ mtmsr(mfmsr() & ~0x1000);
+
+ dummy = ((immap_t *)IMAP_ADDR)->im_clkrst.res[0];
+ printk("Restart failed\n");
+ while(1);
+}
+
+static void
+m8xx_power_off(void)
+{
+ m8xx_restart(NULL);
+}
+
+static void
+m8xx_halt(void)
+{
+ m8xx_restart(NULL);
+}
+
+
+static int
+m8xx_show_percpuinfo(struct seq_file *m, int i)
+{
+ bd_t *bp;
+
+ bp = (bd_t *)__res;
+
+ seq_printf(m, "clock\t\t: %ldMHz\n"
+ "bus clock\t: %ldMHz\n",
+ bp->bi_intfreq / 1000000,
+ bp->bi_busfreq / 1000000);
+
+ return 0;
+}
+
+#ifdef CONFIG_PCI
+static struct irqaction mbx_i8259_irqaction = {
+ .handler = mbx_i8259_action,
+ .mask = CPU_MASK_NONE,
+ .name = "i8259 cascade",
+};
+#endif
+
+/* Initialize the internal interrupt controller. The number of
+ * interrupts supported can vary with the processor type, and the
+ * 82xx family can have up to 64.
+ * External interrupts can be either edge or level triggered, and
+ * need to be initialized by the appropriate driver.
+ */
+static void __init
+m8xx_init_IRQ(void)
+{
+ int i;
+
+ for (i = SIU_IRQ_OFFSET ; i < SIU_IRQ_OFFSET + NR_SIU_INTS ; i++)
+ irq_desc[i].handler = &ppc8xx_pic;
+
+ cpm_interrupt_init();
+
+#if defined(CONFIG_PCI)
+ for (i = I8259_IRQ_OFFSET ; i < I8259_IRQ_OFFSET + NR_8259_INTS ; i++)
+ irq_desc[i].handler = &i8259_pic;
+
+ i8259_pic_irq_offset = I8259_IRQ_OFFSET;
+ i8259_init(0);
+
+ /* The i8259 cascade interrupt must be level sensitive. */
+ ((immap_t *)IMAP_ADDR)->im_siu_conf.sc_siel &=
+ ~(0x80000000 >> ISA_BRIDGE_INT);
+
+ if (setup_irq(ISA_BRIDGE_INT, &mbx_i8259_irqaction))
+ enable_irq(ISA_BRIDGE_INT);
+#endif /* CONFIG_PCI */
+}
+
+/* -------------------------------------------------------------------- */
+
+/*
+ * This is a big hack right now, but it may turn into something real
+ * someday.
+ *
+ * For the 8xx boards (at this time anyway), there is nothing to initialize
+ * associated the PROM. Rather than include all of the prom.c
+ * functions in the image just to get prom_init, all we really need right
+ * now is the initialization of the physical memory region.
+ */
+static unsigned long __init
+m8xx_find_end_of_memory(void)
+{
+ bd_t *binfo;
+ extern unsigned char __res[];
+
+ binfo = (bd_t *)__res;
+
+ return binfo->bi_memsize;
+}
+
+/*
+ * Now map in some of the I/O space that is generically needed
+ * or shared with multiple devices.
+ * All of this fits into the same 4Mbyte region, so it only
+ * requires one page table page. (or at least it used to -- paulus)
+ */
+static void __init
+m8xx_map_io(void)
+{
+ io_block_mapping(IMAP_ADDR, IMAP_ADDR, IMAP_SIZE, _PAGE_IO);
+#ifdef CONFIG_MBX
+ io_block_mapping(NVRAM_ADDR, NVRAM_ADDR, NVRAM_SIZE, _PAGE_IO);
+ io_block_mapping(MBX_CSR_ADDR, MBX_CSR_ADDR, MBX_CSR_SIZE, _PAGE_IO);
+ io_block_mapping(PCI_CSR_ADDR, PCI_CSR_ADDR, PCI_CSR_SIZE, _PAGE_IO);
+
+ /* Map some of the PCI/ISA I/O space to get the IDE interface.
+ */
+ io_block_mapping(PCI_ISA_IO_ADDR, PCI_ISA_IO_ADDR, 0x4000, _PAGE_IO);
+ io_block_mapping(PCI_IDE_ADDR, PCI_IDE_ADDR, 0x4000, _PAGE_IO);
+#endif
+#if defined(CONFIG_RPXLITE) || defined(CONFIG_RPXCLASSIC)
+ io_block_mapping(RPX_CSR_ADDR, RPX_CSR_ADDR, RPX_CSR_SIZE, _PAGE_IO);
+#if !defined(CONFIG_PCI)
+ io_block_mapping(_IO_BASE,_IO_BASE,_IO_BASE_SIZE, _PAGE_IO);
+#endif
+#endif
+#if defined(CONFIG_HTDMSOUND) || defined(CONFIG_RPXTOUCH) || defined(CONFIG_FB_RPX)
+ io_block_mapping(HIOX_CSR_ADDR, HIOX_CSR_ADDR, HIOX_CSR_SIZE, _PAGE_IO);
+#endif
+#ifdef CONFIG_FADS
+ io_block_mapping(BCSR_ADDR, BCSR_ADDR, BCSR_SIZE, _PAGE_IO);
+#endif
+#ifdef CONFIG_PCI
+ io_block_mapping(PCI_CSR_ADDR, PCI_CSR_ADDR, PCI_CSR_SIZE, _PAGE_IO);
+#endif
+#if defined(CONFIG_NETTA)
+ io_block_mapping(_IO_BASE,_IO_BASE,_IO_BASE_SIZE, _PAGE_IO);
+#endif
+}
+
+void __init
+platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
+ unsigned long r6, unsigned long r7)
+{
+ parse_bootinfo(find_bootinfo());
+
+ if ( r3 )
+ memcpy( (void *)__res,(void *)(r3+KERNELBASE), sizeof(bd_t) );
+
+#ifdef CONFIG_PCI
+ m8xx_setup_pci_ptrs();
+#endif
+
+#ifdef CONFIG_BLK_DEV_INITRD
+ /* take care of initrd if we have one */
+ if ( r4 )
+ {
+ initrd_start = r4 + KERNELBASE;
+ initrd_end = r5 + KERNELBASE;
+ }
+#endif /* CONFIG_BLK_DEV_INITRD */
+ /* take care of cmd line */
+ if ( r6 )
+ {
+ *(char *)(r7+KERNELBASE) = 0;
+ strcpy(cmd_line, (char *)(r6+KERNELBASE));
+ }
+
+ ppc_md.setup_arch = m8xx_setup_arch;
+ ppc_md.show_percpuinfo = m8xx_show_percpuinfo;
+ ppc_md.irq_canonicalize = NULL;
+ ppc_md.init_IRQ = m8xx_init_IRQ;
+ ppc_md.get_irq = m8xx_get_irq;
+ ppc_md.init = NULL;
+
+ ppc_md.restart = m8xx_restart;
+ ppc_md.power_off = m8xx_power_off;
+ ppc_md.halt = m8xx_halt;
+
+ ppc_md.time_init = NULL;
+ ppc_md.set_rtc_time = m8xx_set_rtc_time;
+ ppc_md.get_rtc_time = m8xx_get_rtc_time;
+ ppc_md.calibrate_decr = m8xx_calibrate_decr;
+
+ ppc_md.find_end_of_memory = m8xx_find_end_of_memory;
+ ppc_md.setup_io_mappings = m8xx_map_io;
+
+#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
+ m8xx_ide_init();
+#endif
+}
diff --git a/arch/ppc/syslib/m8xx_wdt.c b/arch/ppc/syslib/m8xx_wdt.c
new file mode 100644
index 0000000..7838a44
--- /dev/null
+++ b/arch/ppc/syslib/m8xx_wdt.c
@@ -0,0 +1,99 @@
+/*
+ * m8xx_wdt.c - MPC8xx watchdog driver
+ *
+ * Author: Florian Schirmer <jolt@tuxbox.org>
+ *
+ * 2002 (c) Florian Schirmer <jolt@tuxbox.org> This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <asm/8xx_immap.h>
+#include <syslib/m8xx_wdt.h>
+
+static int wdt_timeout;
+
+void m8xx_wdt_reset(void)
+{
+ volatile immap_t *imap = (volatile immap_t *)IMAP_ADDR;
+
+ imap->im_siu_conf.sc_swsr = 0x556c; /* write magic1 */
+ imap->im_siu_conf.sc_swsr = 0xaa39; /* write magic2 */
+}
+
+static irqreturn_t m8xx_wdt_interrupt(int irq, void *dev, struct pt_regs *regs)
+{
+ volatile immap_t *imap = (volatile immap_t *)IMAP_ADDR;
+
+ m8xx_wdt_reset();
+
+ imap->im_sit.sit_piscr |= PISCR_PS; /* clear irq */
+
+ return IRQ_HANDLED;
+}
+
+void __init m8xx_wdt_handler_install(bd_t * binfo)
+{
+ volatile immap_t *imap = (volatile immap_t *)IMAP_ADDR;
+ u32 pitc;
+ u32 sypcr;
+ u32 pitrtclk;
+
+ sypcr = imap->im_siu_conf.sc_sypcr;
+
+ if (!(sypcr & 0x04)) {
+ printk(KERN_NOTICE "m8xx_wdt: wdt disabled (SYPCR: 0x%08X)\n",
+ sypcr);
+ return;
+ }
+
+ m8xx_wdt_reset();
+
+ printk(KERN_NOTICE
+ "m8xx_wdt: active wdt found (SWTC: 0x%04X, SWP: 0x%01X)\n",
+ (sypcr >> 16), sypcr & 0x01);
+
+ wdt_timeout = (sypcr >> 16) & 0xFFFF;
+
+ if (!wdt_timeout)
+ wdt_timeout = 0xFFFF;
+
+ if (sypcr & 0x01)
+ wdt_timeout *= 2048;
+
+ /*
+ * Fire trigger if half of the wdt ticked down
+ */
+
+ if (imap->im_sit.sit_rtcsc & RTCSC_38K)
+ pitrtclk = 9600;
+ else
+ pitrtclk = 8192;
+
+ if ((wdt_timeout) > (UINT_MAX / pitrtclk))
+ pitc = wdt_timeout / binfo->bi_intfreq * pitrtclk / 2;
+ else
+ pitc = pitrtclk * wdt_timeout / binfo->bi_intfreq / 2;
+
+ imap->im_sit.sit_pitc = pitc << 16;
+ imap->im_sit.sit_piscr =
+ (mk_int_int_mask(PIT_INTERRUPT) << 8) | PISCR_PIE | PISCR_PTE;
+
+ if (request_irq(PIT_INTERRUPT, m8xx_wdt_interrupt, 0, "watchdog", NULL))
+ panic("m8xx_wdt: could not allocate watchdog irq!");
+
+ printk(KERN_NOTICE
+ "m8xx_wdt: keep-alive trigger installed (PITC: 0x%04X)\n", pitc);
+
+ wdt_timeout /= binfo->bi_intfreq;
+}
+
+int m8xx_wdt_get_timeout(void)
+{
+ return wdt_timeout;
+}
diff --git a/arch/ppc/syslib/m8xx_wdt.h b/arch/ppc/syslib/m8xx_wdt.h
new file mode 100644
index 0000000..0d81a9f
--- /dev/null
+++ b/arch/ppc/syslib/m8xx_wdt.h
@@ -0,0 +1,16 @@
+/*
+ * Author: Florian Schirmer <jolt@tuxbox.org>
+ *
+ * 2002 (c) Florian Schirmer <jolt@tuxbox.org> This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+#ifndef _PPC_SYSLIB_M8XX_WDT_H
+#define _PPC_SYSLIB_M8XX_WDT_H
+
+extern void m8xx_wdt_handler_install(bd_t * binfo);
+extern int m8xx_wdt_get_timeout(void);
+extern void m8xx_wdt_reset(void);
+
+#endif /* _PPC_SYSLIB_M8XX_WDT_H */
diff --git a/arch/ppc/syslib/mpc10x_common.c b/arch/ppc/syslib/mpc10x_common.c
new file mode 100644
index 0000000..fd93adf
--- /dev/null
+++ b/arch/ppc/syslib/mpc10x_common.c
@@ -0,0 +1,510 @@
+/*
+ * arch/ppc/syslib/mpc10x_common.c
+ *
+ * Common routines for the Motorola SPS MPC106, MPC107 and MPC8240 Host bridge,
+ * Mem ctlr, EPIC, etc.
+ *
+ * Author: Mark A. Greer
+ * mgreer@mvista.com
+ *
+ * 2001 (c) MontaVista, Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+
+/*
+ * *** WARNING - A BAT MUST be set to access the PCI config addr/data regs ***
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/slab.h>
+
+#include <asm/byteorder.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/uaccess.h>
+#include <asm/machdep.h>
+#include <asm/pci-bridge.h>
+#include <asm/open_pic.h>
+#include <asm/mpc10x.h>
+#include <asm/ocp.h>
+
+/* The OCP structure is fixed by code below, before OCP initialises.
+ paddr depends on where the board places the EUMB.
+ - fixed in mpc10x_bridge_init().
+ irq depends on two things:
+ > does the board use the EPIC at all? (PCORE does not).
+ > is the EPIC in serial or parallel mode?
+ - fixed in mpc10x_set_openpic().
+*/
+
+#ifdef CONFIG_MPC10X_OPENPIC
+#ifdef CONFIG_EPIC_SERIAL_MODE
+#define EPIC_IRQ_BASE (epic_serial_mode ? 16 : 5)
+#else
+#define EPIC_IRQ_BASE 5
+#endif
+#define MPC10X_I2C_IRQ (EPIC_IRQ_BASE + NUM_8259_INTERRUPTS)
+#define MPC10X_DMA0_IRQ (EPIC_IRQ_BASE + 1 + NUM_8259_INTERRUPTS)
+#define MPC10X_DMA1_IRQ (EPIC_IRQ_BASE + 2 + NUM_8259_INTERRUPTS)
+#else
+#define MPC10X_I2C_IRQ OCP_IRQ_NA
+#define MPC10X_DMA0_IRQ OCP_IRQ_NA
+#define MPC10X_DMA1_IRQ OCP_IRQ_NA
+#endif
+
+
+struct ocp_def core_ocp[] = {
+ { .vendor = OCP_VENDOR_INVALID
+ }
+};
+
+static struct ocp_fs_i2c_data mpc10x_i2c_data = {
+ .flags = 0
+};
+static struct ocp_def mpc10x_i2c_ocp = {
+ .vendor = OCP_VENDOR_MOTOROLA,
+ .function = OCP_FUNC_IIC,
+ .index = 0,
+ .additions = &mpc10x_i2c_data
+};
+
+static struct ocp_def mpc10x_dma_ocp[2] = {
+{ .vendor = OCP_VENDOR_MOTOROLA,
+ .function = OCP_FUNC_DMA,
+ .index = 0 },
+{ .vendor = OCP_VENDOR_MOTOROLA,
+ .function = OCP_FUNC_DMA,
+ .index = 1 }
+};
+
+/* Set resources to match bridge memory map */
+void __init
+mpc10x_bridge_set_resources(int map, struct pci_controller *hose)
+{
+
+ switch (map) {
+ case MPC10X_MEM_MAP_A:
+ pci_init_resource(&hose->io_resource,
+ 0x00000000,
+ 0x3f7fffff,
+ IORESOURCE_IO,
+ "PCI host bridge");
+
+ pci_init_resource (&hose->mem_resources[0],
+ 0xc0000000,
+ 0xfeffffff,
+ IORESOURCE_MEM,
+ "PCI host bridge");
+ break;
+ case MPC10X_MEM_MAP_B:
+ pci_init_resource(&hose->io_resource,
+ 0x00000000,
+ 0x00bfffff,
+ IORESOURCE_IO,
+ "PCI host bridge");
+
+ pci_init_resource (&hose->mem_resources[0],
+ 0x80000000,
+ 0xfcffffff,
+ IORESOURCE_MEM,
+ "PCI host bridge");
+ break;
+ default:
+ printk("mpc10x_bridge_set_resources: "
+ "Invalid map specified\n");
+ if (ppc_md.progress)
+ ppc_md.progress("mpc10x:exit1", 0x100);
+ }
+}
+/*
+ * Do some initialization and put the EUMB registers at the specified address
+ * (also map the EPIC registers into virtual space--OpenPIC_Addr will be set).
+ *
+ * The EPIC is not on the 106, only the 8240 and 107.
+ */
+int __init
+mpc10x_bridge_init(struct pci_controller *hose,
+ uint current_map,
+ uint new_map,
+ uint phys_eumb_base)
+{
+ int host_bridge, picr1, picr1_bit;
+ ulong pci_config_addr, pci_config_data;
+ u_char pir, byte;
+
+ if (ppc_md.progress) ppc_md.progress("mpc10x:enter", 0x100);
+
+ /* Set up for current map so we can get at config regs */
+ switch (current_map) {
+ case MPC10X_MEM_MAP_A:
+ setup_indirect_pci(hose,
+ MPC10X_MAPA_CNFG_ADDR,
+ MPC10X_MAPA_CNFG_DATA);
+ break;
+ case MPC10X_MEM_MAP_B:
+ setup_indirect_pci(hose,
+ MPC10X_MAPB_CNFG_ADDR,
+ MPC10X_MAPB_CNFG_DATA);
+ break;
+ default:
+ printk("mpc10x_bridge_init: %s\n",
+ "Invalid current map specified");
+ if (ppc_md.progress)
+ ppc_md.progress("mpc10x:exit1", 0x100);
+ return -1;
+ }
+
+ /* Make sure it's a supported bridge */
+ early_read_config_dword(hose,
+ 0,
+ PCI_DEVFN(0,0),
+ PCI_VENDOR_ID,
+ &host_bridge);
+
+ switch (host_bridge) {
+ case MPC10X_BRIDGE_106:
+ case MPC10X_BRIDGE_8240:
+ case MPC10X_BRIDGE_107:
+ case MPC10X_BRIDGE_8245:
+ break;
+ default:
+ if (ppc_md.progress)
+ ppc_md.progress("mpc10x:exit2", 0x100);
+ return -1;
+ }
+
+ switch (new_map) {
+ case MPC10X_MEM_MAP_A:
+ MPC10X_SETUP_HOSE(hose, A);
+ pci_config_addr = MPC10X_MAPA_CNFG_ADDR;
+ pci_config_data = MPC10X_MAPA_CNFG_DATA;
+ picr1_bit = MPC10X_CFG_PICR1_ADDR_MAP_A;
+ break;
+ case MPC10X_MEM_MAP_B:
+ MPC10X_SETUP_HOSE(hose, B);
+ pci_config_addr = MPC10X_MAPB_CNFG_ADDR;
+ pci_config_data = MPC10X_MAPB_CNFG_DATA;
+ picr1_bit = MPC10X_CFG_PICR1_ADDR_MAP_B;
+ break;
+ default:
+ printk("mpc10x_bridge_init: %s\n",
+ "Invalid new map specified");
+ if (ppc_md.progress)
+ ppc_md.progress("mpc10x:exit3", 0x100);
+ return -1;
+ }
+
+ /* Make bridge use the 'new_map', if not already usng it */
+ if (current_map != new_map) {
+ early_read_config_dword(hose,
+ 0,
+ PCI_DEVFN(0,0),
+ MPC10X_CFG_PICR1_REG,
+ &picr1);
+
+ picr1 = (picr1 & ~MPC10X_CFG_PICR1_ADDR_MAP_MASK) |
+ picr1_bit;
+
+ early_write_config_dword(hose,
+ 0,
+ PCI_DEVFN(0,0),
+ MPC10X_CFG_PICR1_REG,
+ picr1);
+
+ asm volatile("sync");
+
+ /* Undo old mappings & map in new cfg data/addr regs */
+ iounmap((void *)hose->cfg_addr);
+ iounmap((void *)hose->cfg_data);
+
+ setup_indirect_pci(hose,
+ pci_config_addr,
+ pci_config_data);
+ }
+
+ /* Setup resources to match map */
+ mpc10x_bridge_set_resources(new_map, hose);
+
+ /*
+ * Want processor accesses of 0xFDxxxxxx to be mapped
+ * to PCI memory space at 0x00000000. Do not want
+ * host bridge to respond to PCI memory accesses of
+ * 0xFDxxxxxx. Do not want host bridge to respond
+ * to PCI memory addresses 0xFD000000-0xFDFFFFFF;
+ * want processor accesses from 0x000A0000-0x000BFFFF
+ * to be forwarded to system memory.
+ *
+ * Only valid if not in agent mode and using MAP B.
+ */
+ if (new_map == MPC10X_MEM_MAP_B) {
+ early_read_config_byte(hose,
+ 0,
+ PCI_DEVFN(0,0),
+ MPC10X_CFG_MAPB_OPTIONS_REG,
+ &byte);
+
+ byte &= ~(MPC10X_CFG_MAPB_OPTIONS_PFAE |
+ MPC10X_CFG_MAPB_OPTIONS_PCICH |
+ MPC10X_CFG_MAPB_OPTIONS_PROCCH);
+
+ if (host_bridge != MPC10X_BRIDGE_106) {
+ byte |= MPC10X_CFG_MAPB_OPTIONS_CFAE;
+ }
+
+ early_write_config_byte(hose,
+ 0,
+ PCI_DEVFN(0,0),
+ MPC10X_CFG_MAPB_OPTIONS_REG,
+ byte);
+ }
+
+ if (host_bridge != MPC10X_BRIDGE_106) {
+ early_read_config_byte(hose,
+ 0,
+ PCI_DEVFN(0,0),
+ MPC10X_CFG_PIR_REG,
+ &pir);
+
+ if (pir != MPC10X_CFG_PIR_HOST_BRIDGE) {
+ printk("Host bridge in Agent mode\n");
+ /* Read or Set LMBAR & PCSRBAR? */
+ }
+
+ /* Set base addr of the 8240/107 EUMB. */
+ early_write_config_dword(hose,
+ 0,
+ PCI_DEVFN(0,0),
+ MPC10X_CFG_EUMBBAR,
+ phys_eumb_base);
+#ifdef CONFIG_MPC10X_OPENPIC
+ /* Map EPIC register part of EUMB into vitual memory - PCORE
+ uses an i8259 instead of EPIC. */
+ OpenPIC_Addr =
+ ioremap(phys_eumb_base + MPC10X_EUMB_EPIC_OFFSET,
+ MPC10X_EUMB_EPIC_SIZE);
+#endif
+ mpc10x_i2c_ocp.paddr = phys_eumb_base + MPC10X_EUMB_I2C_OFFSET;
+ mpc10x_i2c_ocp.irq = MPC10X_I2C_IRQ;
+ ocp_add_one_device(&mpc10x_i2c_ocp);
+ mpc10x_dma_ocp[0].paddr = phys_eumb_base +
+ MPC10X_EUMB_DMA_OFFSET + 0x100;
+ mpc10x_dma_ocp[0].irq = MPC10X_DMA0_IRQ;
+ ocp_add_one_device(&mpc10x_dma_ocp[0]);
+ mpc10x_dma_ocp[1].paddr = phys_eumb_base +
+ MPC10X_EUMB_DMA_OFFSET + 0x200;
+ mpc10x_dma_ocp[1].irq = MPC10X_DMA1_IRQ;
+ ocp_add_one_device(&mpc10x_dma_ocp[1]);
+ }
+
+#ifdef CONFIG_MPC10X_STORE_GATHERING
+ mpc10x_enable_store_gathering(hose);
+#else
+ mpc10x_disable_store_gathering(hose);
+#endif
+
+ /*
+ * 8240 erratum 26, 8241/8245 erratum 29, 107 erratum 23: speculative
+ * PCI reads may return stale data so turn off.
+ */
+ if ((host_bridge == MPC10X_BRIDGE_8240)
+ || (host_bridge == MPC10X_BRIDGE_8245)
+ || (host_bridge == MPC10X_BRIDGE_107)) {
+
+ early_read_config_dword(hose, 0, PCI_DEVFN(0,0),
+ MPC10X_CFG_PICR1_REG, &picr1);
+
+ picr1 &= ~MPC10X_CFG_PICR1_SPEC_PCI_RD;
+
+ early_write_config_dword(hose, 0, PCI_DEVFN(0,0),
+ MPC10X_CFG_PICR1_REG, picr1);
+ }
+
+ /*
+ * 8241/8245 erratum 28: PCI reads from local memory may return
+ * stale data. Workaround by setting PICR2[0] to disable copyback
+ * optimization. Oddly, the latest available user manual for the
+ * 8245 (Rev 2., dated 10/2003) says PICR2[0] is reserverd.
+ */
+ if (host_bridge == MPC10X_BRIDGE_8245) {
+ ulong picr2;
+
+ early_read_config_dword(hose, 0, PCI_DEVFN(0,0),
+ MPC10X_CFG_PICR2_REG, &picr2);
+
+ picr2 |= MPC10X_CFG_PICR2_COPYBACK_OPT;
+
+ early_write_config_dword(hose, 0, PCI_DEVFN(0,0),
+ MPC10X_CFG_PICR2_REG, picr2);
+ }
+
+ if (ppc_md.progress) ppc_md.progress("mpc10x:exit", 0x100);
+ return 0;
+}
+
+/*
+ * Need to make our own PCI config space access macros because
+ * mpc10x_get_mem_size() is called before the data structures are set up for
+ * the 'early_xxx' and 'indirect_xxx' routines to work.
+ * Assumes bus 0.
+ */
+#define MPC10X_CFG_read(val, addr, type, op) *val = op((type)(addr))
+#define MPC10X_CFG_write(val, addr, type, op) op((type *)(addr), (val))
+
+#define MPC10X_PCI_OP(rw, size, type, op, mask) \
+static void \
+mpc10x_##rw##_config_##size(uint *cfg_addr, uint *cfg_data, int devfn, int offset, type val) \
+{ \
+ out_be32(cfg_addr, \
+ ((offset & 0xfc) << 24) | (devfn << 16) \
+ | (0 << 8) | 0x80); \
+ MPC10X_CFG_##rw(val, cfg_data + (offset & mask), type, op); \
+ return; \
+}
+
+MPC10X_PCI_OP(read, byte, u8 *, in_8, 3)
+MPC10X_PCI_OP(read, dword, u32 *, in_le32, 0)
+#if 0 /* Not used */
+MPC10X_PCI_OP(write, byte, u8, out_8, 3)
+MPC10X_PCI_OP(read, word, u16 *, in_le16, 2)
+MPC10X_PCI_OP(write, word, u16, out_le16, 2)
+MPC10X_PCI_OP(write, dword, u32, out_le32, 0)
+#endif
+
+/*
+ * Read the memory controller registers to determine the amount of memory in
+ * the system. This assumes that the firmware has correctly set up the memory
+ * controller registers.
+ */
+unsigned long __init
+mpc10x_get_mem_size(uint mem_map)
+{
+ uint *config_addr, *config_data, val;
+ ulong start, end, total, offset;
+ int i;
+ u_char bank_enables;
+
+ switch (mem_map) {
+ case MPC10X_MEM_MAP_A:
+ config_addr = (uint *)MPC10X_MAPA_CNFG_ADDR;
+ config_data = (uint *)MPC10X_MAPA_CNFG_DATA;
+ break;
+ case MPC10X_MEM_MAP_B:
+ config_addr = (uint *)MPC10X_MAPB_CNFG_ADDR;
+ config_data = (uint *)MPC10X_MAPB_CNFG_DATA;
+ break;
+ default:
+ return 0;
+ }
+
+ mpc10x_read_config_byte(config_addr,
+ config_data,
+ PCI_DEVFN(0,0),
+ MPC10X_MCTLR_MEM_BANK_ENABLES,
+ &bank_enables);
+
+ total = 0;
+
+ for (i=0; i<8; i++) {
+ if (bank_enables & (1 << i)) {
+ offset = MPC10X_MCTLR_MEM_START_1 + ((i > 3) ? 4 : 0);
+ mpc10x_read_config_dword(config_addr,
+ config_data,
+ PCI_DEVFN(0,0),
+ offset,
+ &val);
+ start = (val >> ((i & 3) << 3)) & 0xff;
+
+ offset = MPC10X_MCTLR_EXT_MEM_START_1 + ((i>3) ? 4 : 0);
+ mpc10x_read_config_dword(config_addr,
+ config_data,
+ PCI_DEVFN(0,0),
+ offset,
+ &val);
+ val = (val >> ((i & 3) << 3)) & 0x03;
+ start = (val << 28) | (start << 20);
+
+ offset = MPC10X_MCTLR_MEM_END_1 + ((i > 3) ? 4 : 0);
+ mpc10x_read_config_dword(config_addr,
+ config_data,
+ PCI_DEVFN(0,0),
+ offset,
+ &val);
+ end = (val >> ((i & 3) << 3)) & 0xff;
+
+ offset = MPC10X_MCTLR_EXT_MEM_END_1 + ((i > 3) ? 4 : 0);
+ mpc10x_read_config_dword(config_addr,
+ config_data,
+ PCI_DEVFN(0,0),
+ offset,
+ &val);
+ val = (val >> ((i & 3) << 3)) & 0x03;
+ end = (val << 28) | (end << 20) | 0xfffff;
+
+ total += (end - start + 1);
+ }
+ }
+
+ return total;
+}
+
+int __init
+mpc10x_enable_store_gathering(struct pci_controller *hose)
+{
+ uint picr1;
+
+ early_read_config_dword(hose,
+ 0,
+ PCI_DEVFN(0,0),
+ MPC10X_CFG_PICR1_REG,
+ &picr1);
+
+ picr1 |= MPC10X_CFG_PICR1_ST_GATH_EN;
+
+ early_write_config_dword(hose,
+ 0,
+ PCI_DEVFN(0,0),
+ MPC10X_CFG_PICR1_REG,
+ picr1);
+
+ return 0;
+}
+
+int __init
+mpc10x_disable_store_gathering(struct pci_controller *hose)
+{
+ uint picr1;
+
+ early_read_config_dword(hose,
+ 0,
+ PCI_DEVFN(0,0),
+ MPC10X_CFG_PICR1_REG,
+ &picr1);
+
+ picr1 &= ~MPC10X_CFG_PICR1_ST_GATH_EN;
+
+ early_write_config_dword(hose,
+ 0,
+ PCI_DEVFN(0,0),
+ MPC10X_CFG_PICR1_REG,
+ picr1);
+
+ return 0;
+}
+
+#ifdef CONFIG_MPC10X_OPENPIC
+void __init mpc10x_set_openpic(void)
+{
+ /* Map external IRQs */
+ openpic_set_sources(0, EPIC_IRQ_BASE, OpenPIC_Addr + 0x10200);
+ /* Skip reserved space and map i2c and DMA Ch[01] */
+ openpic_set_sources(EPIC_IRQ_BASE, 3, OpenPIC_Addr + 0x11020);
+ /* Skip reserved space and map Message Unit Interrupt (I2O) */
+ openpic_set_sources(EPIC_IRQ_BASE + 3, 1, OpenPIC_Addr + 0x110C0);
+
+ openpic_init(NUM_8259_INTERRUPTS);
+}
+#endif
diff --git a/arch/ppc/syslib/mpc52xx_devices.c b/arch/ppc/syslib/mpc52xx_devices.c
new file mode 100644
index 0000000..ad5182e
--- /dev/null
+++ b/arch/ppc/syslib/mpc52xx_devices.c
@@ -0,0 +1,318 @@
+/*
+ * arch/ppc/syslib/mpc52xx_devices.c
+ *
+ * Freescale MPC52xx device descriptions
+ *
+ *
+ * Maintainer : Sylvain Munaut <tnt@246tNt.com>
+ *
+ * Copyright (C) 2005 Sylvain Munaut <tnt@246tNt.com>
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2. This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ */
+
+#include <linux/fsl_devices.h>
+#include <linux/resource.h>
+#include <asm/mpc52xx.h>
+#include <asm/ppc_sys.h>
+
+
+static u64 mpc52xx_dma_mask = 0xffffffffULL;
+
+static struct fsl_i2c_platform_data mpc52xx_fsl_i2c_pdata = {
+ .device_flags = FSL_I2C_DEV_CLOCK_5200,
+};
+
+
+/* We use relative offsets for IORESOURCE_MEM to be independent from the
+ * MBAR location at compile time
+ */
+
+/* TODO Add the BestComm initiator channel to the device definitions,
+ possibly using IORESOURCE_DMA. But that's when BestComm is ready ... */
+
+struct platform_device ppc_sys_platform_devices[] = {
+ [MPC52xx_MSCAN1] = {
+ .name = "mpc52xx-mscan",
+ .id = 0,
+ .num_resources = 2,
+ .resource = (struct resource[]) {
+ {
+ .start = 0x0900,
+ .end = 0x097f,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = MPC52xx_MSCAN1_IRQ,
+ .end = MPC52xx_MSCAN1_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+ },
+ },
+ [MPC52xx_MSCAN2] = {
+ .name = "mpc52xx-mscan",
+ .id = 1,
+ .num_resources = 2,
+ .resource = (struct resource[]) {
+ {
+ .start = 0x0980,
+ .end = 0x09ff,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = MPC52xx_MSCAN2_IRQ,
+ .end = MPC52xx_MSCAN2_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+ },
+ },
+ [MPC52xx_SPI] = {
+ .name = "mpc52xx-spi",
+ .id = -1,
+ .num_resources = 3,
+ .resource = (struct resource[]) {
+ {
+ .start = 0x0f00,
+ .end = 0x0f1f,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .name = "modf",
+ .start = MPC52xx_SPI_MODF_IRQ,
+ .end = MPC52xx_SPI_MODF_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .name = "spif",
+ .start = MPC52xx_SPI_SPIF_IRQ,
+ .end = MPC52xx_SPI_SPIF_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+ },
+ },
+ [MPC52xx_USB] = {
+ .name = "ppc-soc-ohci",
+ .id = -1,
+ .num_resources = 2,
+ .dev.dma_mask = &mpc52xx_dma_mask,
+ .dev.coherent_dma_mask = 0xffffffffULL,
+ .resource = (struct resource[]) {
+ {
+ .start = 0x1000,
+ .end = 0x10ff,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = MPC52xx_USB_IRQ,
+ .end = MPC52xx_USB_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+ },
+ },
+ [MPC52xx_BDLC] = {
+ .name = "mpc52xx-bdlc",
+ .id = -1,
+ .num_resources = 2,
+ .resource = (struct resource[]) {
+ {
+ .start = 0x1300,
+ .end = 0x130f,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = MPC52xx_BDLC_IRQ,
+ .end = MPC52xx_BDLC_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+ },
+ },
+ [MPC52xx_PSC1] = {
+ .name = "mpc52xx-psc",
+ .id = 0,
+ .num_resources = 2,
+ .resource = (struct resource[]) {
+ {
+ .start = 0x2000,
+ .end = 0x209f,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = MPC52xx_PSC1_IRQ,
+ .end = MPC52xx_PSC1_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+ },
+ },
+ [MPC52xx_PSC2] = {
+ .name = "mpc52xx-psc",
+ .id = 1,
+ .num_resources = 2,
+ .resource = (struct resource[]) {
+ {
+ .start = 0x2200,
+ .end = 0x229f,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = MPC52xx_PSC2_IRQ,
+ .end = MPC52xx_PSC2_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+ },
+ },
+ [MPC52xx_PSC3] = {
+ .name = "mpc52xx-psc",
+ .id = 2,
+ .num_resources = 2,
+ .resource = (struct resource[]) {
+ {
+ .start = 0x2400,
+ .end = 0x249f,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = MPC52xx_PSC3_IRQ,
+ .end = MPC52xx_PSC3_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+ },
+ },
+ [MPC52xx_PSC4] = {
+ .name = "mpc52xx-psc",
+ .id = 3,
+ .num_resources = 2,
+ .resource = (struct resource[]) {
+ {
+ .start = 0x2600,
+ .end = 0x269f,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = MPC52xx_PSC4_IRQ,
+ .end = MPC52xx_PSC4_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+ },
+ },
+ [MPC52xx_PSC5] = {
+ .name = "mpc52xx-psc",
+ .id = 4,
+ .num_resources = 2,
+ .resource = (struct resource[]) {
+ {
+ .start = 0x2800,
+ .end = 0x289f,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = MPC52xx_PSC5_IRQ,
+ .end = MPC52xx_PSC5_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+ },
+ },
+ [MPC52xx_PSC6] = {
+ .name = "mpc52xx-psc",
+ .id = 5,
+ .num_resources = 2,
+ .resource = (struct resource[]) {
+ {
+ .start = 0x2c00,
+ .end = 0x2c9f,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = MPC52xx_PSC6_IRQ,
+ .end = MPC52xx_PSC6_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+ },
+ },
+ [MPC52xx_FEC] = {
+ .name = "mpc52xx-fec",
+ .id = -1,
+ .num_resources = 2,
+ .resource = (struct resource[]) {
+ {
+ .start = 0x3000,
+ .end = 0x33ff,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = MPC52xx_FEC_IRQ,
+ .end = MPC52xx_FEC_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+ },
+ },
+ [MPC52xx_ATA] = {
+ .name = "mpc52xx-ata",
+ .id = -1,
+ .num_resources = 2,
+ .resource = (struct resource[]) {
+ {
+ .start = 0x3a00,
+ .end = 0x3aff,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = MPC52xx_ATA_IRQ,
+ .end = MPC52xx_ATA_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+ },
+ },
+ [MPC52xx_I2C1] = {
+ .name = "fsl-i2c",
+ .id = 0,
+ .dev.platform_data = &mpc52xx_fsl_i2c_pdata,
+ .num_resources = 2,
+ .resource = (struct resource[]) {
+ {
+ .start = 0x3d00,
+ .end = 0x3d1f,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = MPC52xx_I2C1_IRQ,
+ .end = MPC52xx_I2C1_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+ },
+ },
+ [MPC52xx_I2C2] = {
+ .name = "fsl-i2c",
+ .id = 1,
+ .dev.platform_data = &mpc52xx_fsl_i2c_pdata,
+ .num_resources = 2,
+ .resource = (struct resource[]) {
+ {
+ .start = 0x3d40,
+ .end = 0x3d5f,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = MPC52xx_I2C2_IRQ,
+ .end = MPC52xx_I2C2_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+ },
+ },
+};
+
+
+static int __init mach_mpc52xx_fixup(struct platform_device *pdev)
+{
+ ppc_sys_fixup_mem_resource(pdev, MPC52xx_MBAR);
+ return 0;
+}
+
+static int __init mach_mpc52xx_init(void)
+{
+ ppc_sys_device_fixup = mach_mpc52xx_fixup;
+ return 0;
+}
+
+postcore_initcall(mach_mpc52xx_init);
diff --git a/arch/ppc/syslib/mpc52xx_pci.c b/arch/ppc/syslib/mpc52xx_pci.c
new file mode 100644
index 0000000..c723efd
--- /dev/null
+++ b/arch/ppc/syslib/mpc52xx_pci.c
@@ -0,0 +1,235 @@
+/*
+ * arch/ppc/syslib/mpc52xx_pci.c
+ *
+ * PCI code for the Freescale MPC52xx embedded CPU.
+ *
+ *
+ * Maintainer : Sylvain Munaut <tnt@246tNt.com>
+ *
+ * Copyright (C) 2004 Sylvain Munaut <tnt@246tNt.com>
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2. This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ */
+
+#include <linux/config.h>
+
+#include <asm/pci.h>
+
+#include <asm/mpc52xx.h>
+#include "mpc52xx_pci.h"
+
+#include <asm/delay.h>
+
+
+static int
+mpc52xx_pci_read_config(struct pci_bus *bus, unsigned int devfn,
+ int offset, int len, u32 *val)
+{
+ struct pci_controller *hose = bus->sysdata;
+ u32 value;
+
+ if (ppc_md.pci_exclude_device)
+ if (ppc_md.pci_exclude_device(bus->number, devfn))
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
+ out_be32(hose->cfg_addr,
+ (1 << 31) |
+ ((bus->number - hose->bus_offset) << 16) |
+ (devfn << 8) |
+ (offset & 0xfc));
+
+ value = in_le32(hose->cfg_data);
+
+ if (len != 4) {
+ value >>= ((offset & 0x3) << 3);
+ value &= 0xffffffff >> (32 - (len << 3));
+ }
+
+ *val = value;
+
+ out_be32(hose->cfg_addr, 0);
+
+ return PCIBIOS_SUCCESSFUL;
+}
+
+static int
+mpc52xx_pci_write_config(struct pci_bus *bus, unsigned int devfn,
+ int offset, int len, u32 val)
+{
+ struct pci_controller *hose = bus->sysdata;
+ u32 value, mask;
+
+ if (ppc_md.pci_exclude_device)
+ if (ppc_md.pci_exclude_device(bus->number, devfn))
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
+ out_be32(hose->cfg_addr,
+ (1 << 31) |
+ ((bus->number - hose->bus_offset) << 16) |
+ (devfn << 8) |
+ (offset & 0xfc));
+
+ if (len != 4) {
+ value = in_le32(hose->cfg_data);
+
+ offset = (offset & 0x3) << 3;
+ mask = (0xffffffff >> (32 - (len << 3)));
+ mask <<= offset;
+
+ value &= ~mask;
+ val = value | ((val << offset) & mask);
+ }
+
+ out_le32(hose->cfg_data, val);
+
+ out_be32(hose->cfg_addr, 0);
+
+ return PCIBIOS_SUCCESSFUL;
+}
+
+static struct pci_ops mpc52xx_pci_ops = {
+ .read = mpc52xx_pci_read_config,
+ .write = mpc52xx_pci_write_config
+};
+
+
+static void __init
+mpc52xx_pci_setup(struct mpc52xx_pci __iomem *pci_regs)
+{
+
+ /* Setup control regs */
+ /* Nothing to do afaik */
+
+ /* Setup windows */
+ out_be32(&pci_regs->iw0btar, MPC52xx_PCI_IWBTAR_TRANSLATION(
+ MPC52xx_PCI_MEM_START + MPC52xx_PCI_MEM_OFFSET,
+ MPC52xx_PCI_MEM_START,
+ MPC52xx_PCI_MEM_SIZE ));
+
+ out_be32(&pci_regs->iw1btar, MPC52xx_PCI_IWBTAR_TRANSLATION(
+ MPC52xx_PCI_MMIO_START + MPC52xx_PCI_MEM_OFFSET,
+ MPC52xx_PCI_MMIO_START,
+ MPC52xx_PCI_MMIO_SIZE ));
+
+ out_be32(&pci_regs->iw2btar, MPC52xx_PCI_IWBTAR_TRANSLATION(
+ MPC52xx_PCI_IO_BASE,
+ MPC52xx_PCI_IO_START,
+ MPC52xx_PCI_IO_SIZE ));
+
+ out_be32(&pci_regs->iwcr, MPC52xx_PCI_IWCR_PACK(
+ ( MPC52xx_PCI_IWCR_ENABLE | /* iw0btar */
+ MPC52xx_PCI_IWCR_READ_MULTI |
+ MPC52xx_PCI_IWCR_MEM ),
+ ( MPC52xx_PCI_IWCR_ENABLE | /* iw1btar */
+ MPC52xx_PCI_IWCR_READ |
+ MPC52xx_PCI_IWCR_MEM ),
+ ( MPC52xx_PCI_IWCR_ENABLE | /* iw2btar */
+ MPC52xx_PCI_IWCR_IO )
+ ));
+
+
+ out_be32(&pci_regs->tbatr0,
+ MPC52xx_PCI_TBATR_ENABLE | MPC52xx_PCI_TARGET_IO );
+ out_be32(&pci_regs->tbatr1,
+ MPC52xx_PCI_TBATR_ENABLE | MPC52xx_PCI_TARGET_MEM );
+
+ out_be32(&pci_regs->tcr, MPC52xx_PCI_TCR_LD);
+
+ /* Reset the exteral bus ( internal PCI controller is NOT resetted ) */
+ /* Not necessary and can be a bad thing if for example the bootloader
+ is displaying a splash screen or ... Just left here for
+ documentation purpose if anyone need it */
+#if 0
+ u32 tmp;
+ tmp = in_be32(&pci_regs->gscr);
+ out_be32(&pci_regs->gscr, tmp | MPC52xx_PCI_GSCR_PR);
+ udelay(50);
+ out_be32(&pci_regs->gscr, tmp);
+#endif
+}
+
+static void __init
+mpc52xx_pci_fixup_resources(struct pci_dev *dev)
+{
+ int i;
+
+ /* We don't rely on boot loader for PCI and resets all
+ devices */
+ for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {
+ struct resource *res = &dev->resource[i];
+ if (res->end > res->start) { /* Only valid resources */
+ res->end -= res->start;
+ res->start = 0;
+ res->flags |= IORESOURCE_UNSET;
+ }
+ }
+
+ /* The PCI Host bridge of MPC52xx has a prefetch memory resource
+ fixed to 1Gb. Doesn't fit in the resource system so we remove it */
+ if ( (dev->vendor == PCI_VENDOR_ID_MOTOROLA) &&
+ (dev->device == PCI_DEVICE_ID_MOTOROLA_MPC5200) ) {
+ struct resource *res = &dev->resource[1];
+ res->start = res->end = res->flags = 0;
+ }
+}
+
+void __init
+mpc52xx_find_bridges(void)
+{
+ struct mpc52xx_pci __iomem *pci_regs;
+ struct pci_controller *hose;
+
+ pci_assign_all_busses = 1;
+
+ pci_regs = ioremap(MPC52xx_PA(MPC52xx_PCI_OFFSET), MPC52xx_PCI_SIZE);
+ if (!pci_regs)
+ return;
+
+ hose = pcibios_alloc_controller();
+ if (!hose) {
+ iounmap(pci_regs);
+ return;
+ }
+
+ ppc_md.pci_swizzle = common_swizzle;
+ ppc_md.pcibios_fixup_resources = mpc52xx_pci_fixup_resources;
+
+ hose->first_busno = 0;
+ hose->last_busno = 0xff;
+ hose->bus_offset = 0;
+ hose->ops = &mpc52xx_pci_ops;
+
+ mpc52xx_pci_setup(pci_regs);
+
+ hose->pci_mem_offset = MPC52xx_PCI_MEM_OFFSET;
+
+ isa_io_base =
+ (unsigned long) ioremap(MPC52xx_PCI_IO_BASE,
+ MPC52xx_PCI_IO_SIZE);
+ hose->io_base_virt = (void *) isa_io_base;
+
+ hose->cfg_addr = &pci_regs->car;
+ hose->cfg_data = (void __iomem *) isa_io_base;
+
+ /* Setup resources */
+ pci_init_resource(&hose->mem_resources[0],
+ MPC52xx_PCI_MEM_START,
+ MPC52xx_PCI_MEM_STOP,
+ IORESOURCE_MEM|IORESOURCE_PREFETCH,
+ "PCI prefetchable memory");
+
+ pci_init_resource(&hose->mem_resources[1],
+ MPC52xx_PCI_MMIO_START,
+ MPC52xx_PCI_MMIO_STOP,
+ IORESOURCE_MEM,
+ "PCI memory");
+
+ pci_init_resource(&hose->io_resource,
+ MPC52xx_PCI_IO_START,
+ MPC52xx_PCI_IO_STOP,
+ IORESOURCE_IO,
+ "PCI I/O");
+
+}
diff --git a/arch/ppc/syslib/mpc52xx_pci.h b/arch/ppc/syslib/mpc52xx_pci.h
new file mode 100644
index 0000000..04b509a
--- /dev/null
+++ b/arch/ppc/syslib/mpc52xx_pci.h
@@ -0,0 +1,139 @@
+/*
+ * arch/ppc/syslib/mpc52xx_pci.h
+ *
+ * PCI Include file the Freescale MPC52xx embedded cpu chips
+ *
+ *
+ * Maintainer : Sylvain Munaut <tnt@246tNt.com>
+ *
+ * Inspired from code written by Dale Farnsworth <dfarnsworth@mvista.com>
+ * for the 2.4 kernel.
+ *
+ * Copyright (C) 2004 Sylvain Munaut <tnt@246tNt.com>
+ * Copyright (C) 2003 MontaVista, Software, Inc.
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2. This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ */
+
+#ifndef __SYSLIB_MPC52xx_PCI_H__
+#define __SYSLIB_MPC52xx_PCI_H__
+
+/* ======================================================================== */
+/* PCI windows config */
+/* ======================================================================== */
+
+/*
+ * Master windows : MPC52xx -> PCI
+ *
+ * 0x80000000 -> 0x9FFFFFFF PCI Mem prefetchable IW0BTAR
+ * 0xA0000000 -> 0xAFFFFFFF PCI Mem IW1BTAR
+ * 0xB0000000 -> 0xB0FFFFFF PCI IO IW2BTAR
+ *
+ * Slave windows : PCI -> MPC52xx
+ *
+ * 0xF0000000 -> 0xF003FFFF MPC52xx MBAR TBATR0
+ * 0x00000000 -> 0x3FFFFFFF MPC52xx local memory TBATR1
+ */
+
+#define MPC52xx_PCI_MEM_OFFSET 0x00000000 /* Offset for MEM MMIO */
+
+#define MPC52xx_PCI_MEM_START 0x80000000
+#define MPC52xx_PCI_MEM_SIZE 0x20000000
+#define MPC52xx_PCI_MEM_STOP (MPC52xx_PCI_MEM_START+MPC52xx_PCI_MEM_SIZE-1)
+
+#define MPC52xx_PCI_MMIO_START 0xa0000000
+#define MPC52xx_PCI_MMIO_SIZE 0x10000000
+#define MPC52xx_PCI_MMIO_STOP (MPC52xx_PCI_MMIO_START+MPC52xx_PCI_MMIO_SIZE-1)
+
+#define MPC52xx_PCI_IO_BASE 0xb0000000
+
+#define MPC52xx_PCI_IO_START 0x00000000
+#define MPC52xx_PCI_IO_SIZE 0x01000000
+#define MPC52xx_PCI_IO_STOP (MPC52xx_PCI_IO_START+MPC52xx_PCI_IO_SIZE-1)
+
+
+#define MPC52xx_PCI_TARGET_IO MPC52xx_MBAR
+#define MPC52xx_PCI_TARGET_MEM 0x00000000
+
+
+/* ======================================================================== */
+/* Structures mapping & Defines for PCI Unit */
+/* ======================================================================== */
+
+#define MPC52xx_PCI_GSCR_BM 0x40000000
+#define MPC52xx_PCI_GSCR_PE 0x20000000
+#define MPC52xx_PCI_GSCR_SE 0x10000000
+#define MPC52xx_PCI_GSCR_XLB2PCI_MASK 0x07000000
+#define MPC52xx_PCI_GSCR_XLB2PCI_SHIFT 24
+#define MPC52xx_PCI_GSCR_IPG2PCI_MASK 0x00070000
+#define MPC52xx_PCI_GSCR_IPG2PCI_SHIFT 16
+#define MPC52xx_PCI_GSCR_BME 0x00004000
+#define MPC52xx_PCI_GSCR_PEE 0x00002000
+#define MPC52xx_PCI_GSCR_SEE 0x00001000
+#define MPC52xx_PCI_GSCR_PR 0x00000001
+
+
+#define MPC52xx_PCI_IWBTAR_TRANSLATION(proc_ad,pci_ad,size) \
+ ( ( (proc_ad) & 0xff000000 ) | \
+ ( (((size) - 1) >> 8) & 0x00ff0000 ) | \
+ ( ((pci_ad) >> 16) & 0x0000ff00 ) )
+
+#define MPC52xx_PCI_IWCR_PACK(win0,win1,win2) (((win0) << 24) | \
+ ((win1) << 16) | \
+ ((win2) << 8))
+
+#define MPC52xx_PCI_IWCR_DISABLE 0x0
+#define MPC52xx_PCI_IWCR_ENABLE 0x1
+#define MPC52xx_PCI_IWCR_READ 0x0
+#define MPC52xx_PCI_IWCR_READ_LINE 0x2
+#define MPC52xx_PCI_IWCR_READ_MULTI 0x4
+#define MPC52xx_PCI_IWCR_MEM 0x0
+#define MPC52xx_PCI_IWCR_IO 0x8
+
+#define MPC52xx_PCI_TCR_P 0x01000000
+#define MPC52xx_PCI_TCR_LD 0x00010000
+
+#define MPC52xx_PCI_TBATR_DISABLE 0x0
+#define MPC52xx_PCI_TBATR_ENABLE 0x1
+
+
+#ifndef __ASSEMBLY__
+
+struct mpc52xx_pci {
+ u32 idr; /* PCI + 0x00 */
+ u32 scr; /* PCI + 0x04 */
+ u32 ccrir; /* PCI + 0x08 */
+ u32 cr1; /* PCI + 0x0C */
+ u32 bar0; /* PCI + 0x10 */
+ u32 bar1; /* PCI + 0x14 */
+ u8 reserved1[16]; /* PCI + 0x18 */
+ u32 ccpr; /* PCI + 0x28 */
+ u32 sid; /* PCI + 0x2C */
+ u32 erbar; /* PCI + 0x30 */
+ u32 cpr; /* PCI + 0x34 */
+ u8 reserved2[4]; /* PCI + 0x38 */
+ u32 cr2; /* PCI + 0x3C */
+ u8 reserved3[32]; /* PCI + 0x40 */
+ u32 gscr; /* PCI + 0x60 */
+ u32 tbatr0; /* PCI + 0x64 */
+ u32 tbatr1; /* PCI + 0x68 */
+ u32 tcr; /* PCI + 0x6C */
+ u32 iw0btar; /* PCI + 0x70 */
+ u32 iw1btar; /* PCI + 0x74 */
+ u32 iw2btar; /* PCI + 0x78 */
+ u8 reserved4[4]; /* PCI + 0x7C */
+ u32 iwcr; /* PCI + 0x80 */
+ u32 icr; /* PCI + 0x84 */
+ u32 isr; /* PCI + 0x88 */
+ u32 arb; /* PCI + 0x8C */
+ u8 reserved5[104]; /* PCI + 0x90 */
+ u32 car; /* PCI + 0xF8 */
+ u8 reserved6[4]; /* PCI + 0xFC */
+};
+
+#endif /* __ASSEMBLY__ */
+
+
+#endif /* __SYSLIB_MPC52xx_PCI_H__ */
diff --git a/arch/ppc/syslib/mpc52xx_pic.c b/arch/ppc/syslib/mpc52xx_pic.c
new file mode 100644
index 0000000..4c4497e
--- /dev/null
+++ b/arch/ppc/syslib/mpc52xx_pic.c
@@ -0,0 +1,257 @@
+/*
+ * arch/ppc/syslib/mpc52xx_pic.c
+ *
+ * Programmable Interrupt Controller functions for the Freescale MPC52xx
+ * embedded CPU.
+ *
+ *
+ * Maintainer : Sylvain Munaut <tnt@246tNt.com>
+ *
+ * Based on (well, mostly copied from) the code from the 2.4 kernel by
+ * Dale Farnsworth <dfarnsworth@mvista.com> and Kent Borg.
+ *
+ * Copyright (C) 2004 Sylvain Munaut <tnt@246tNt.com>
+ * Copyright (C) 2003 Montavista Software, Inc
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2. This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ */
+
+#include <linux/stddef.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/signal.h>
+#include <linux/stddef.h>
+#include <linux/delay.h>
+#include <linux/irq.h>
+
+#include <asm/io.h>
+#include <asm/processor.h>
+#include <asm/system.h>
+#include <asm/irq.h>
+#include <asm/mpc52xx.h>
+
+
+static struct mpc52xx_intr __iomem *intr;
+static struct mpc52xx_sdma __iomem *sdma;
+
+static void
+mpc52xx_ic_disable(unsigned int irq)
+{
+ u32 val;
+
+ if (irq == MPC52xx_IRQ0) {
+ val = in_be32(&intr->ctrl);
+ val &= ~(1 << 11);
+ out_be32(&intr->ctrl, val);
+ }
+ else if (irq < MPC52xx_IRQ1) {
+ BUG();
+ }
+ else if (irq <= MPC52xx_IRQ3) {
+ val = in_be32(&intr->ctrl);
+ val &= ~(1 << (10 - (irq - MPC52xx_IRQ1)));
+ out_be32(&intr->ctrl, val);
+ }
+ else if (irq < MPC52xx_SDMA_IRQ_BASE) {
+ val = in_be32(&intr->main_mask);
+ val |= 1 << (16 - (irq - MPC52xx_MAIN_IRQ_BASE));
+ out_be32(&intr->main_mask, val);
+ }
+ else if (irq < MPC52xx_PERP_IRQ_BASE) {
+ val = in_be32(&sdma->IntMask);
+ val |= 1 << (irq - MPC52xx_SDMA_IRQ_BASE);
+ out_be32(&sdma->IntMask, val);
+ }
+ else {
+ val = in_be32(&intr->per_mask);
+ val |= 1 << (31 - (irq - MPC52xx_PERP_IRQ_BASE));
+ out_be32(&intr->per_mask, val);
+ }
+}
+
+static void
+mpc52xx_ic_enable(unsigned int irq)
+{
+ u32 val;
+
+ if (irq == MPC52xx_IRQ0) {
+ val = in_be32(&intr->ctrl);
+ val |= 1 << 11;
+ out_be32(&intr->ctrl, val);
+ }
+ else if (irq < MPC52xx_IRQ1) {
+ BUG();
+ }
+ else if (irq <= MPC52xx_IRQ3) {
+ val = in_be32(&intr->ctrl);
+ val |= 1 << (10 - (irq - MPC52xx_IRQ1));
+ out_be32(&intr->ctrl, val);
+ }
+ else if (irq < MPC52xx_SDMA_IRQ_BASE) {
+ val = in_be32(&intr->main_mask);
+ val &= ~(1 << (16 - (irq - MPC52xx_MAIN_IRQ_BASE)));
+ out_be32(&intr->main_mask, val);
+ }
+ else if (irq < MPC52xx_PERP_IRQ_BASE) {
+ val = in_be32(&sdma->IntMask);
+ val &= ~(1 << (irq - MPC52xx_SDMA_IRQ_BASE));
+ out_be32(&sdma->IntMask, val);
+ }
+ else {
+ val = in_be32(&intr->per_mask);
+ val &= ~(1 << (31 - (irq - MPC52xx_PERP_IRQ_BASE)));
+ out_be32(&intr->per_mask, val);
+ }
+}
+
+static void
+mpc52xx_ic_ack(unsigned int irq)
+{
+ u32 val;
+
+ /*
+ * Only some irqs are reset here, others in interrupting hardware.
+ */
+
+ switch (irq) {
+ case MPC52xx_IRQ0:
+ val = in_be32(&intr->ctrl);
+ val |= 0x08000000;
+ out_be32(&intr->ctrl, val);
+ break;
+ case MPC52xx_CCS_IRQ:
+ val = in_be32(&intr->enc_status);
+ val |= 0x00000400;
+ out_be32(&intr->enc_status, val);
+ break;
+ case MPC52xx_IRQ1:
+ val = in_be32(&intr->ctrl);
+ val |= 0x04000000;
+ out_be32(&intr->ctrl, val);
+ break;
+ case MPC52xx_IRQ2:
+ val = in_be32(&intr->ctrl);
+ val |= 0x02000000;
+ out_be32(&intr->ctrl, val);
+ break;
+ case MPC52xx_IRQ3:
+ val = in_be32(&intr->ctrl);
+ val |= 0x01000000;
+ out_be32(&intr->ctrl, val);
+ break;
+ default:
+ if (irq >= MPC52xx_SDMA_IRQ_BASE
+ && irq < (MPC52xx_SDMA_IRQ_BASE + MPC52xx_SDMA_IRQ_NUM)) {
+ out_be32(&sdma->IntPend,
+ 1 << (irq - MPC52xx_SDMA_IRQ_BASE));
+ }
+ break;
+ }
+}
+
+static void
+mpc52xx_ic_disable_and_ack(unsigned int irq)
+{
+ mpc52xx_ic_disable(irq);
+ mpc52xx_ic_ack(irq);
+}
+
+static void
+mpc52xx_ic_end(unsigned int irq)
+{
+ if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS)))
+ mpc52xx_ic_enable(irq);
+}
+
+static struct hw_interrupt_type mpc52xx_ic = {
+ .typename = " MPC52xx ",
+ .enable = mpc52xx_ic_enable,
+ .disable = mpc52xx_ic_disable,
+ .ack = mpc52xx_ic_disable_and_ack,
+ .end = mpc52xx_ic_end,
+};
+
+void __init
+mpc52xx_init_irq(void)
+{
+ int i;
+ u32 intr_ctrl;
+
+ /* Remap the necessary zones */
+ intr = ioremap(MPC52xx_PA(MPC52xx_INTR_OFFSET), MPC52xx_INTR_SIZE);
+ sdma = ioremap(MPC52xx_PA(MPC52xx_SDMA_OFFSET), MPC52xx_SDMA_SIZE);
+
+ if ((intr==NULL) || (sdma==NULL))
+ panic("Can't ioremap PIC/SDMA register for init_irq !");
+
+ /* Disable all interrupt sources. */
+ out_be32(&sdma->IntPend, 0xffffffff); /* 1 means clear pending */
+ out_be32(&sdma->IntMask, 0xffffffff); /* 1 means disabled */
+ out_be32(&intr->per_mask, 0x7ffffc00); /* 1 means disabled */
+ out_be32(&intr->main_mask, 0x00010fff); /* 1 means disabled */
+ intr_ctrl = in_be32(&intr->ctrl);
+ intr_ctrl &= 0x00ff0000; /* Keeps IRQ[0-3] config */
+ intr_ctrl |= 0x0f000000 | /* clear IRQ 0-3 */
+ 0x00001000 | /* MEE master external enable */
+ 0x00000000 | /* 0 means disable IRQ 0-3 */
+ 0x00000001; /* CEb route critical normally */
+ out_be32(&intr->ctrl, intr_ctrl);
+
+ /* Zero a bunch of the priority settings. */
+ out_be32(&intr->per_pri1, 0);
+ out_be32(&intr->per_pri2, 0);
+ out_be32(&intr->per_pri3, 0);
+ out_be32(&intr->main_pri1, 0);
+ out_be32(&intr->main_pri2, 0);
+
+ /* Initialize irq_desc[i].handler's with mpc52xx_ic. */
+ for (i = 0; i < NR_IRQS; i++) {
+ irq_desc[i].handler = &mpc52xx_ic;
+ irq_desc[i].status = IRQ_LEVEL;
+ }
+
+ #define IRQn_MODE(intr_ctrl,irq) (((intr_ctrl) >> (22-(i<<1))) & 0x03)
+ for (i=0 ; i<4 ; i++) {
+ int mode;
+ mode = IRQn_MODE(intr_ctrl,i);
+ if ((mode == 0x1) || (mode == 0x2))
+ irq_desc[i?MPC52xx_IRQ1+i-1:MPC52xx_IRQ0].status = 0;
+ }
+}
+
+int
+mpc52xx_get_irq(struct pt_regs *regs)
+{
+ u32 status;
+ int irq = -1;
+
+ status = in_be32(&intr->enc_status);
+
+ if (status & 0x00000400) { /* critical */
+ irq = (status >> 8) & 0x3;
+ if (irq == 2) /* high priority peripheral */
+ goto peripheral;
+ irq += MPC52xx_CRIT_IRQ_BASE;
+ }
+ else if (status & 0x00200000) { /* main */
+ irq = (status >> 16) & 0x1f;
+ if (irq == 4) /* low priority peripheral */
+ goto peripheral;
+ irq += MPC52xx_MAIN_IRQ_BASE;
+ }
+ else if (status & 0x20000000) { /* peripheral */
+peripheral:
+ irq = (status >> 24) & 0x1f;
+ if (irq == 0) { /* bestcomm */
+ status = in_be32(&sdma->IntPend);
+ irq = ffs(status) + MPC52xx_SDMA_IRQ_BASE-1;
+ }
+ else
+ irq += MPC52xx_PERP_IRQ_BASE;
+ }
+
+ return irq;
+}
+
diff --git a/arch/ppc/syslib/mpc52xx_setup.c b/arch/ppc/syslib/mpc52xx_setup.c
new file mode 100644
index 0000000..bb23745
--- /dev/null
+++ b/arch/ppc/syslib/mpc52xx_setup.c
@@ -0,0 +1,230 @@
+/*
+ * arch/ppc/syslib/mpc52xx_setup.c
+ *
+ * Common code for the boards based on Freescale MPC52xx embedded CPU.
+ *
+ *
+ * Maintainer : Sylvain Munaut <tnt@246tNt.com>
+ *
+ * Support for other bootloaders than UBoot by Dale Farnsworth
+ * <dfarnsworth@mvista.com>
+ *
+ * Copyright (C) 2004 Sylvain Munaut <tnt@246tNt.com>
+ * Copyright (C) 2003 Montavista Software, Inc
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2. This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ */
+
+#include <linux/config.h>
+
+#include <asm/io.h>
+#include <asm/time.h>
+#include <asm/mpc52xx.h>
+#include <asm/mpc52xx_psc.h>
+#include <asm/pgtable.h>
+#include <asm/ppcboot.h>
+
+extern bd_t __res;
+
+static int core_mult[] = { /* CPU Frequency multiplier, taken */
+ 0, 0, 0, 10, 20, 20, 25, 45, /* from the datasheet used to compute */
+ 30, 55, 40, 50, 0, 60, 35, 0, /* CPU frequency from XLB freq and */
+ 30, 25, 65, 10, 70, 20, 75, 45, /* external jumper config */
+ 0, 55, 40, 50, 80, 60, 35, 0
+};
+
+void
+mpc52xx_restart(char *cmd)
+{
+ struct mpc52xx_gpt __iomem *gpt0 = MPC52xx_VA(MPC52xx_GPTx_OFFSET(0));
+
+ local_irq_disable();
+
+ /* Turn on the watchdog and wait for it to expire. It effectively
+ does a reset */
+ out_be32(&gpt0->count, 0x000000ff);
+ out_be32(&gpt0->mode, 0x00009004);
+
+ while (1);
+}
+
+void
+mpc52xx_halt(void)
+{
+ local_irq_disable();
+
+ while (1);
+}
+
+void
+mpc52xx_power_off(void)
+{
+ /* By default we don't have any way of shut down.
+ If a specific board wants to, it can set the power down
+ code to any hardware implementation dependent code */
+ mpc52xx_halt();
+}
+
+
+void __init
+mpc52xx_set_bat(void)
+{
+ /* Set BAT 2 to map the 0xf0000000 area */
+ /* This mapping is used during mpc52xx_progress,
+ * mpc52xx_find_end_of_memory, and UARTs/GPIO access for debug
+ */
+ mb();
+ mtspr(SPRN_DBAT2U, 0xf0001ffe);
+ mtspr(SPRN_DBAT2L, 0xf000002a);
+ mb();
+}
+
+void __init
+mpc52xx_map_io(void)
+{
+ /* Here we only map the MBAR */
+ io_block_mapping(
+ MPC52xx_MBAR_VIRT, MPC52xx_MBAR, MPC52xx_MBAR_SIZE, _PAGE_IO);
+}
+
+
+#ifdef CONFIG_SERIAL_TEXT_DEBUG
+#ifndef MPC52xx_PF_CONSOLE_PORT
+#error "mpc52xx PSC for console not selected"
+#endif
+
+static void
+mpc52xx_psc_putc(struct mpc52xx_psc __iomem *psc, unsigned char c)
+{
+ while (!(in_be16(&psc->mpc52xx_psc_status) &
+ MPC52xx_PSC_SR_TXRDY));
+ out_8(&psc->mpc52xx_psc_buffer_8, c);
+}
+
+void
+mpc52xx_progress(char *s, unsigned short hex)
+{
+ char c;
+ struct mpc52xx_psc __iomem *psc;
+
+ psc = MPC52xx_VA(MPC52xx_PSCx_OFFSET(MPC52xx_PF_CONSOLE_PORT));
+
+ while ((c = *s++) != 0) {
+ if (c == '\n')
+ mpc52xx_psc_putc(psc, '\r');
+ mpc52xx_psc_putc(psc, c);
+ }
+
+ mpc52xx_psc_putc(psc, '\r');
+ mpc52xx_psc_putc(psc, '\n');
+}
+
+#endif /* CONFIG_SERIAL_TEXT_DEBUG */
+
+
+unsigned long __init
+mpc52xx_find_end_of_memory(void)
+{
+ u32 ramsize = __res.bi_memsize;
+
+ /*
+ * if bootloader passed a memsize, just use it
+ * else get size from sdram config registers
+ */
+ if (ramsize == 0) {
+ struct mpc52xx_mmap_ctl __iomem *mmap_ctl;
+ u32 sdram_config_0, sdram_config_1;
+
+ /* Temp BAT2 mapping active when this is called ! */
+ mmap_ctl = MPC52xx_VA(MPC52xx_MMAP_CTL_OFFSET);
+
+ sdram_config_0 = in_be32(&mmap_ctl->sdram0);
+ sdram_config_1 = in_be32(&mmap_ctl->sdram1);
+
+ if ((sdram_config_0 & 0x1f) >= 0x13)
+ ramsize = 1 << ((sdram_config_0 & 0xf) + 17);
+
+ if (((sdram_config_1 & 0x1f) >= 0x13) &&
+ ((sdram_config_1 & 0xfff00000) == ramsize))
+ ramsize += 1 << ((sdram_config_1 & 0xf) + 17);
+ }
+
+ return ramsize;
+}
+
+void __init
+mpc52xx_calibrate_decr(void)
+{
+ int current_time, previous_time;
+ int tbl_start, tbl_end;
+ unsigned int xlbfreq, cpufreq, ipbfreq, pcifreq, divisor;
+
+ xlbfreq = __res.bi_busfreq;
+ /* if bootloader didn't pass bus frequencies, calculate them */
+ if (xlbfreq == 0) {
+ /* Get RTC & Clock manager modules */
+ struct mpc52xx_rtc __iomem *rtc;
+ struct mpc52xx_cdm __iomem *cdm;
+
+ rtc = ioremap(MPC52xx_PA(MPC52xx_RTC_OFFSET), MPC52xx_RTC_SIZE);
+ cdm = ioremap(MPC52xx_PA(MPC52xx_CDM_OFFSET), MPC52xx_CDM_SIZE);
+
+ if ((rtc==NULL) || (cdm==NULL))
+ panic("Can't ioremap RTC/CDM while computing bus freq");
+
+ /* Count bus clock during 1/64 sec */
+ out_be32(&rtc->dividers, 0x8f1f0000); /* Set RTC 64x faster */
+ previous_time = in_be32(&rtc->time);
+ while ((current_time = in_be32(&rtc->time)) == previous_time) ;
+ tbl_start = get_tbl();
+ previous_time = current_time;
+ while ((current_time = in_be32(&rtc->time)) == previous_time) ;
+ tbl_end = get_tbl();
+ out_be32(&rtc->dividers, 0xffff0000); /* Restore RTC */
+
+ /* Compute all frequency from that & CDM settings */
+ xlbfreq = (tbl_end - tbl_start) << 8;
+ cpufreq = (xlbfreq * core_mult[in_be32(&cdm->rstcfg)&0x1f])/10;
+ ipbfreq = (in_8(&cdm->ipb_clk_sel) & 1) ?
+ xlbfreq / 2 : xlbfreq;
+ switch (in_8(&cdm->pci_clk_sel) & 3) {
+ case 0:
+ pcifreq = ipbfreq;
+ break;
+ case 1:
+ pcifreq = ipbfreq / 2;
+ break;
+ default:
+ pcifreq = xlbfreq / 4;
+ break;
+ }
+ __res.bi_busfreq = xlbfreq;
+ __res.bi_intfreq = cpufreq;
+ __res.bi_ipbfreq = ipbfreq;
+ __res.bi_pcifreq = pcifreq;
+
+ /* Release mapping */
+ iounmap(rtc);
+ iounmap(cdm);
+ }
+
+ divisor = 4;
+
+ tb_ticks_per_jiffy = xlbfreq / HZ / divisor;
+ tb_to_us = mulhwu_scale_factor(xlbfreq / divisor, 1000000);
+}
+
+int mpc52xx_match_psc_function(int psc_idx, const char *func)
+{
+ struct mpc52xx_psc_func *cf = mpc52xx_psc_functions;
+
+ while ((cf->id != -1) && (cf->func != NULL)) {
+ if ((cf->id == psc_idx) && !strcmp(cf->func,func))
+ return 1;
+ cf++;
+ }
+
+ return 0;
+}
diff --git a/arch/ppc/syslib/mpc52xx_sys.c b/arch/ppc/syslib/mpc52xx_sys.c
new file mode 100644
index 0000000..9a0f90a
--- /dev/null
+++ b/arch/ppc/syslib/mpc52xx_sys.c
@@ -0,0 +1,38 @@
+/*
+ * arch/ppc/syslib/mpc52xx_sys.c
+ *
+ * Freescale MPC52xx system descriptions
+ *
+ *
+ * Maintainer : Sylvain Munaut <tnt@246tNt.com>
+ *
+ * Copyright (C) 2005 Sylvain Munaut <tnt@246tNt.com>
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2. This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ */
+
+#include <asm/ppc_sys.h>
+
+struct ppc_sys_spec *cur_ppc_sys_spec;
+struct ppc_sys_spec ppc_sys_specs[] = {
+ {
+ .ppc_sys_name = "5200",
+ .mask = 0xffff0000,
+ .value = 0x80110000,
+ .num_devices = 15,
+ .device_list = (enum ppc_sys_devices[])
+ {
+ MPC52xx_MSCAN1, MPC52xx_MSCAN2, MPC52xx_SPI,
+ MPC52xx_USB, MPC52xx_BDLC, MPC52xx_PSC1, MPC52xx_PSC2,
+ MPC52xx_PSC3, MPC52xx_PSC4, MPC52xx_PSC5, MPC52xx_PSC6,
+ MPC52xx_FEC, MPC52xx_ATA, MPC52xx_I2C1, MPC52xx_I2C2,
+ },
+ },
+ { /* default match */
+ .ppc_sys_name = "",
+ .mask = 0x00000000,
+ .value = 0x00000000,
+ },
+};
diff --git a/arch/ppc/syslib/mpc83xx_devices.c b/arch/ppc/syslib/mpc83xx_devices.c
new file mode 100644
index 0000000..5c1a919e
--- /dev/null
+++ b/arch/ppc/syslib/mpc83xx_devices.c
@@ -0,0 +1,237 @@
+/*
+ * arch/ppc/platforms/83xx/mpc83xx_devices.c
+ *
+ * MPC83xx Device descriptions
+ *
+ * Maintainer: Kumar Gala <kumar.gala@freescale.com>
+ *
+ * Copyright 2005 Freescale Semiconductor Inc.
+ *
+ * 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.
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/serial_8250.h>
+#include <linux/fsl_devices.h>
+#include <asm/mpc83xx.h>
+#include <asm/irq.h>
+#include <asm/ppc_sys.h>
+
+/* We use offsets for IORESOURCE_MEM since we do not know at compile time
+ * what IMMRBAR is, will get fixed up by mach_mpc83xx_fixup
+ */
+
+static struct gianfar_platform_data mpc83xx_tsec1_pdata = {
+ .device_flags = FSL_GIANFAR_DEV_HAS_GIGABIT |
+ FSL_GIANFAR_DEV_HAS_COALESCE | FSL_GIANFAR_DEV_HAS_RMON |
+ FSL_GIANFAR_DEV_HAS_MULTI_INTR,
+ .phy_reg_addr = 0x24000,
+};
+
+static struct gianfar_platform_data mpc83xx_tsec2_pdata = {
+ .device_flags = FSL_GIANFAR_DEV_HAS_GIGABIT |
+ FSL_GIANFAR_DEV_HAS_COALESCE | FSL_GIANFAR_DEV_HAS_RMON |
+ FSL_GIANFAR_DEV_HAS_MULTI_INTR,
+ .phy_reg_addr = 0x24000,
+};
+
+static struct fsl_i2c_platform_data mpc83xx_fsl_i2c1_pdata = {
+ .device_flags = FSL_I2C_DEV_SEPARATE_DFSRR,
+};
+
+static struct fsl_i2c_platform_data mpc83xx_fsl_i2c2_pdata = {
+ .device_flags = FSL_I2C_DEV_SEPARATE_DFSRR,
+};
+
+static struct plat_serial8250_port serial_platform_data[] = {
+ [0] = {
+ .mapbase = 0x4500,
+ .irq = MPC83xx_IRQ_UART1,
+ .iotype = UPIO_MEM,
+ .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
+ },
+ [1] = {
+ .mapbase = 0x4600,
+ .irq = MPC83xx_IRQ_UART2,
+ .iotype = UPIO_MEM,
+ .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
+ },
+};
+
+struct platform_device ppc_sys_platform_devices[] = {
+ [MPC83xx_TSEC1] = {
+ .name = "fsl-gianfar",
+ .id = 1,
+ .dev.platform_data = &mpc83xx_tsec1_pdata,
+ .num_resources = 4,
+ .resource = (struct resource[]) {
+ {
+ .start = 0x24000,
+ .end = 0x24fff,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .name = "tx",
+ .start = MPC83xx_IRQ_TSEC1_TX,
+ .end = MPC83xx_IRQ_TSEC1_TX,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .name = "rx",
+ .start = MPC83xx_IRQ_TSEC1_RX,
+ .end = MPC83xx_IRQ_TSEC1_RX,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .name = "error",
+ .start = MPC83xx_IRQ_TSEC1_ERROR,
+ .end = MPC83xx_IRQ_TSEC1_ERROR,
+ .flags = IORESOURCE_IRQ,
+ },
+ },
+ },
+ [MPC83xx_TSEC2] = {
+ .name = "fsl-gianfar",
+ .id = 2,
+ .dev.platform_data = &mpc83xx_tsec2_pdata,
+ .num_resources = 4,
+ .resource = (struct resource[]) {
+ {
+ .start = 0x25000,
+ .end = 0x25fff,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .name = "tx",
+ .start = MPC83xx_IRQ_TSEC2_TX,
+ .end = MPC83xx_IRQ_TSEC2_TX,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .name = "rx",
+ .start = MPC83xx_IRQ_TSEC2_RX,
+ .end = MPC83xx_IRQ_TSEC2_RX,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .name = "error",
+ .start = MPC83xx_IRQ_TSEC2_ERROR,
+ .end = MPC83xx_IRQ_TSEC2_ERROR,
+ .flags = IORESOURCE_IRQ,
+ },
+ },
+ },
+ [MPC83xx_IIC1] = {
+ .name = "fsl-i2c",
+ .id = 1,
+ .dev.platform_data = &mpc83xx_fsl_i2c1_pdata,
+ .num_resources = 2,
+ .resource = (struct resource[]) {
+ {
+ .start = 0x3000,
+ .end = 0x30ff,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = MPC83xx_IRQ_IIC1,
+ .end = MPC83xx_IRQ_IIC1,
+ .flags = IORESOURCE_IRQ,
+ },
+ },
+ },
+ [MPC83xx_IIC2] = {
+ .name = "fsl-i2c",
+ .id = 2,
+ .dev.platform_data = &mpc83xx_fsl_i2c2_pdata,
+ .num_resources = 2,
+ .resource = (struct resource[]) {
+ {
+ .start = 0x3100,
+ .end = 0x31ff,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = MPC83xx_IRQ_IIC2,
+ .end = MPC83xx_IRQ_IIC2,
+ .flags = IORESOURCE_IRQ,
+ },
+ },
+ },
+ [MPC83xx_DUART] = {
+ .name = "serial8250",
+ .id = 0,
+ .dev.platform_data = serial_platform_data,
+ },
+ [MPC83xx_SEC2] = {
+ .name = "fsl-sec2",
+ .id = 1,
+ .num_resources = 2,
+ .resource = (struct resource[]) {
+ {
+ .start = 0x30000,
+ .end = 0x3ffff,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = MPC83xx_IRQ_SEC2,
+ .end = MPC83xx_IRQ_SEC2,
+ .flags = IORESOURCE_IRQ,
+ },
+ },
+ },
+ [MPC83xx_USB2_DR] = {
+ .name = "fsl-usb2-dr",
+ .id = 1,
+ .num_resources = 2,
+ .resource = (struct resource[]) {
+ {
+ .start = 0x22000,
+ .end = 0x22fff,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = MPC83xx_IRQ_USB2_DR,
+ .end = MPC83xx_IRQ_USB2_DR,
+ .flags = IORESOURCE_IRQ,
+ },
+ },
+ },
+ [MPC83xx_USB2_MPH] = {
+ .name = "fsl-usb2-mph",
+ .id = 1,
+ .num_resources = 2,
+ .resource = (struct resource[]) {
+ {
+ .start = 0x23000,
+ .end = 0x23fff,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = MPC83xx_IRQ_USB2_MPH,
+ .end = MPC83xx_IRQ_USB2_MPH,
+ .flags = IORESOURCE_IRQ,
+ },
+ },
+ },
+};
+
+static int __init mach_mpc83xx_fixup(struct platform_device *pdev)
+{
+ ppc_sys_fixup_mem_resource(pdev, immrbar);
+ return 0;
+}
+
+static int __init mach_mpc83xx_init(void)
+{
+ if (ppc_md.progress)
+ ppc_md.progress("mach_mpc83xx_init:enter", 0);
+ ppc_sys_device_fixup = mach_mpc83xx_fixup;
+ return 0;
+}
+
+postcore_initcall(mach_mpc83xx_init);
diff --git a/arch/ppc/syslib/mpc83xx_sys.c b/arch/ppc/syslib/mpc83xx_sys.c
new file mode 100644
index 0000000..29aa633
--- /dev/null
+++ b/arch/ppc/syslib/mpc83xx_sys.c
@@ -0,0 +1,100 @@
+/*
+ * arch/ppc/platforms/83xx/mpc83xx_sys.c
+ *
+ * MPC83xx System descriptions
+ *
+ * Maintainer: Kumar Gala <kumar.gala@freescale.com>
+ *
+ * Copyright 2005 Freescale Semiconductor Inc.
+ *
+ * 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.
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <asm/ppc_sys.h>
+
+struct ppc_sys_spec *cur_ppc_sys_spec;
+struct ppc_sys_spec ppc_sys_specs[] = {
+ {
+ .ppc_sys_name = "8349E",
+ .mask = 0xFFFF0000,
+ .value = 0x80500000,
+ .num_devices = 8,
+ .device_list = (enum ppc_sys_devices[])
+ {
+ MPC83xx_TSEC1, MPC83xx_TSEC2, MPC83xx_IIC1,
+ MPC83xx_IIC2, MPC83xx_DUART, MPC83xx_SEC2,
+ MPC83xx_USB2_DR, MPC83xx_USB2_MPH
+ },
+ },
+ {
+ .ppc_sys_name = "8349",
+ .mask = 0xFFFF0000,
+ .value = 0x80510000,
+ .num_devices = 7,
+ .device_list = (enum ppc_sys_devices[])
+ {
+ MPC83xx_TSEC1, MPC83xx_TSEC2, MPC83xx_IIC1,
+ MPC83xx_IIC2, MPC83xx_DUART,
+ MPC83xx_USB2_DR, MPC83xx_USB2_MPH
+ },
+ },
+ {
+ .ppc_sys_name = "8347E",
+ .mask = 0xFFFF0000,
+ .value = 0x80520000,
+ .num_devices = 8,
+ .device_list = (enum ppc_sys_devices[])
+ {
+ MPC83xx_TSEC1, MPC83xx_TSEC2, MPC83xx_IIC1,
+ MPC83xx_IIC2, MPC83xx_DUART, MPC83xx_SEC2,
+ MPC83xx_USB2_DR, MPC83xx_USB2_MPH
+ },
+ },
+ {
+ .ppc_sys_name = "8347",
+ .mask = 0xFFFF0000,
+ .value = 0x80530000,
+ .num_devices = 7,
+ .device_list = (enum ppc_sys_devices[])
+ {
+ MPC83xx_TSEC1, MPC83xx_TSEC2, MPC83xx_IIC1,
+ MPC83xx_IIC2, MPC83xx_DUART,
+ MPC83xx_USB2_DR, MPC83xx_USB2_MPH
+ },
+ },
+ {
+ .ppc_sys_name = "8343E",
+ .mask = 0xFFFF0000,
+ .value = 0x80540000,
+ .num_devices = 7,
+ .device_list = (enum ppc_sys_devices[])
+ {
+ MPC83xx_TSEC1, MPC83xx_TSEC2, MPC83xx_IIC1,
+ MPC83xx_IIC2, MPC83xx_DUART, MPC83xx_SEC2,
+ MPC83xx_USB2_DR,
+ },
+ },
+ {
+ .ppc_sys_name = "8343",
+ .mask = 0xFFFF0000,
+ .value = 0x80550000,
+ .num_devices = 6,
+ .device_list = (enum ppc_sys_devices[])
+ {
+ MPC83xx_TSEC1, MPC83xx_TSEC2, MPC83xx_IIC1,
+ MPC83xx_IIC2, MPC83xx_DUART,
+ MPC83xx_USB2_DR,
+ },
+ },
+ { /* default match */
+ .ppc_sys_name = "",
+ .mask = 0x00000000,
+ .value = 0x00000000,
+ },
+};
diff --git a/arch/ppc/syslib/mpc85xx_devices.c b/arch/ppc/syslib/mpc85xx_devices.c
new file mode 100644
index 0000000..a231795
--- /dev/null
+++ b/arch/ppc/syslib/mpc85xx_devices.c
@@ -0,0 +1,552 @@
+/*
+ * arch/ppc/platforms/85xx/mpc85xx_devices.c
+ *
+ * MPC85xx Device descriptions
+ *
+ * Maintainer: Kumar Gala <kumar.gala@freescale.com>
+ *
+ * Copyright 2005 Freescale Semiconductor Inc.
+ *
+ * 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.
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/serial_8250.h>
+#include <linux/fsl_devices.h>
+#include <asm/mpc85xx.h>
+#include <asm/irq.h>
+#include <asm/ppc_sys.h>
+
+/* We use offsets for IORESOURCE_MEM since we do not know at compile time
+ * what CCSRBAR is, will get fixed up by mach_mpc85xx_fixup
+ */
+
+static struct gianfar_platform_data mpc85xx_tsec1_pdata = {
+ .device_flags = FSL_GIANFAR_DEV_HAS_GIGABIT |
+ FSL_GIANFAR_DEV_HAS_COALESCE | FSL_GIANFAR_DEV_HAS_RMON |
+ FSL_GIANFAR_DEV_HAS_MULTI_INTR,
+ .phy_reg_addr = MPC85xx_ENET1_OFFSET,
+};
+
+static struct gianfar_platform_data mpc85xx_tsec2_pdata = {
+ .device_flags = FSL_GIANFAR_DEV_HAS_GIGABIT |
+ FSL_GIANFAR_DEV_HAS_COALESCE | FSL_GIANFAR_DEV_HAS_RMON |
+ FSL_GIANFAR_DEV_HAS_MULTI_INTR,
+ .phy_reg_addr = MPC85xx_ENET1_OFFSET,
+};
+
+static struct gianfar_platform_data mpc85xx_fec_pdata = {
+ .phy_reg_addr = MPC85xx_ENET1_OFFSET,
+};
+
+static struct fsl_i2c_platform_data mpc85xx_fsl_i2c_pdata = {
+ .device_flags = FSL_I2C_DEV_SEPARATE_DFSRR,
+};
+
+static struct plat_serial8250_port serial_platform_data[] = {
+ [0] = {
+ .mapbase = 0x4500,
+ .irq = MPC85xx_IRQ_DUART,
+ .iotype = UPIO_MEM,
+ .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_SHARE_IRQ,
+ },
+ [1] = {
+ .mapbase = 0x4600,
+ .irq = MPC85xx_IRQ_DUART,
+ .iotype = UPIO_MEM,
+ .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_SHARE_IRQ,
+ },
+};
+
+struct platform_device ppc_sys_platform_devices[] = {
+ [MPC85xx_TSEC1] = {
+ .name = "fsl-gianfar",
+ .id = 1,
+ .dev.platform_data = &mpc85xx_tsec1_pdata,
+ .num_resources = 4,
+ .resource = (struct resource[]) {
+ {
+ .start = MPC85xx_ENET1_OFFSET,
+ .end = MPC85xx_ENET1_OFFSET +
+ MPC85xx_ENET1_SIZE - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .name = "tx",
+ .start = MPC85xx_IRQ_TSEC1_TX,
+ .end = MPC85xx_IRQ_TSEC1_TX,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .name = "rx",
+ .start = MPC85xx_IRQ_TSEC1_RX,
+ .end = MPC85xx_IRQ_TSEC1_RX,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .name = "error",
+ .start = MPC85xx_IRQ_TSEC1_ERROR,
+ .end = MPC85xx_IRQ_TSEC1_ERROR,
+ .flags = IORESOURCE_IRQ,
+ },
+ },
+ },
+ [MPC85xx_TSEC2] = {
+ .name = "fsl-gianfar",
+ .id = 2,
+ .dev.platform_data = &mpc85xx_tsec2_pdata,
+ .num_resources = 4,
+ .resource = (struct resource[]) {
+ {
+ .start = MPC85xx_ENET2_OFFSET,
+ .end = MPC85xx_ENET2_OFFSET +
+ MPC85xx_ENET2_SIZE - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .name = "tx",
+ .start = MPC85xx_IRQ_TSEC2_TX,
+ .end = MPC85xx_IRQ_TSEC2_TX,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .name = "rx",
+ .start = MPC85xx_IRQ_TSEC2_RX,
+ .end = MPC85xx_IRQ_TSEC2_RX,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .name = "error",
+ .start = MPC85xx_IRQ_TSEC2_ERROR,
+ .end = MPC85xx_IRQ_TSEC2_ERROR,
+ .flags = IORESOURCE_IRQ,
+ },
+ },
+ },
+ [MPC85xx_FEC] = {
+ .name = "fsl-gianfar",
+ .id = 3,
+ .dev.platform_data = &mpc85xx_fec_pdata,
+ .num_resources = 2,
+ .resource = (struct resource[]) {
+ {
+ .start = MPC85xx_ENET3_OFFSET,
+ .end = MPC85xx_ENET3_OFFSET +
+ MPC85xx_ENET3_SIZE - 1,
+ .flags = IORESOURCE_MEM,
+
+ },
+ {
+ .start = MPC85xx_IRQ_FEC,
+ .end = MPC85xx_IRQ_FEC,
+ .flags = IORESOURCE_IRQ,
+ },
+ },
+ },
+ [MPC85xx_IIC1] = {
+ .name = "fsl-i2c",
+ .id = 1,
+ .dev.platform_data = &mpc85xx_fsl_i2c_pdata,
+ .num_resources = 2,
+ .resource = (struct resource[]) {
+ {
+ .start = MPC85xx_IIC1_OFFSET,
+ .end = MPC85xx_IIC1_OFFSET +
+ MPC85xx_IIC1_SIZE - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = MPC85xx_IRQ_IIC1,
+ .end = MPC85xx_IRQ_IIC1,
+ .flags = IORESOURCE_IRQ,
+ },
+ },
+ },
+ [MPC85xx_DMA0] = {
+ .name = "fsl-dma",
+ .id = 0,
+ .num_resources = 2,
+ .resource = (struct resource[]) {
+ {
+ .start = MPC85xx_DMA0_OFFSET,
+ .end = MPC85xx_DMA0_OFFSET +
+ MPC85xx_DMA0_SIZE - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = MPC85xx_IRQ_DMA0,
+ .end = MPC85xx_IRQ_DMA0,
+ .flags = IORESOURCE_IRQ,
+ },
+ },
+ },
+ [MPC85xx_DMA1] = {
+ .name = "fsl-dma",
+ .id = 1,
+ .num_resources = 2,
+ .resource = (struct resource[]) {
+ {
+ .start = MPC85xx_DMA1_OFFSET,
+ .end = MPC85xx_DMA1_OFFSET +
+ MPC85xx_DMA1_SIZE - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = MPC85xx_IRQ_DMA1,
+ .end = MPC85xx_IRQ_DMA1,
+ .flags = IORESOURCE_IRQ,
+ },
+ },
+ },
+ [MPC85xx_DMA2] = {
+ .name = "fsl-dma",
+ .id = 2,
+ .num_resources = 2,
+ .resource = (struct resource[]) {
+ {
+ .start = MPC85xx_DMA2_OFFSET,
+ .end = MPC85xx_DMA2_OFFSET +
+ MPC85xx_DMA2_SIZE - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = MPC85xx_IRQ_DMA2,
+ .end = MPC85xx_IRQ_DMA2,
+ .flags = IORESOURCE_IRQ,
+ },
+ },
+ },
+ [MPC85xx_DMA3] = {
+ .name = "fsl-dma",
+ .id = 3,
+ .num_resources = 2,
+ .resource = (struct resource[]) {
+ {
+ .start = MPC85xx_DMA3_OFFSET,
+ .end = MPC85xx_DMA3_OFFSET +
+ MPC85xx_DMA3_SIZE - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = MPC85xx_IRQ_DMA3,
+ .end = MPC85xx_IRQ_DMA3,
+ .flags = IORESOURCE_IRQ,
+ },
+ },
+ },
+ [MPC85xx_DUART] = {
+ .name = "serial8250",
+ .id = 0,
+ .dev.platform_data = serial_platform_data,
+ },
+ [MPC85xx_PERFMON] = {
+ .name = "fsl-perfmon",
+ .id = 1,
+ .num_resources = 2,
+ .resource = (struct resource[]) {
+ {
+ .start = MPC85xx_PERFMON_OFFSET,
+ .end = MPC85xx_PERFMON_OFFSET +
+ MPC85xx_PERFMON_SIZE - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = MPC85xx_IRQ_PERFMON,
+ .end = MPC85xx_IRQ_PERFMON,
+ .flags = IORESOURCE_IRQ,
+ },
+ },
+ },
+ [MPC85xx_SEC2] = {
+ .name = "fsl-sec2",
+ .id = 1,
+ .num_resources = 2,
+ .resource = (struct resource[]) {
+ {
+ .start = MPC85xx_SEC2_OFFSET,
+ .end = MPC85xx_SEC2_OFFSET +
+ MPC85xx_SEC2_SIZE - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = MPC85xx_IRQ_SEC2,
+ .end = MPC85xx_IRQ_SEC2,
+ .flags = IORESOURCE_IRQ,
+ },
+ },
+ },
+#ifdef CONFIG_CPM2
+ [MPC85xx_CPM_FCC1] = {
+ .name = "fsl-cpm-fcc",
+ .id = 1,
+ .num_resources = 3,
+ .resource = (struct resource[]) {
+ {
+ .start = 0x91300,
+ .end = 0x9131F,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = 0x91380,
+ .end = 0x9139F,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = SIU_INT_FCC1,
+ .end = SIU_INT_FCC1,
+ .flags = IORESOURCE_IRQ,
+ },
+ },
+ },
+ [MPC85xx_CPM_FCC2] = {
+ .name = "fsl-cpm-fcc",
+ .id = 2,
+ .num_resources = 3,
+ .resource = (struct resource[]) {
+ {
+ .start = 0x91320,
+ .end = 0x9133F,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = 0x913A0,
+ .end = 0x913CF,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = SIU_INT_FCC2,
+ .end = SIU_INT_FCC2,
+ .flags = IORESOURCE_IRQ,
+ },
+ },
+ },
+ [MPC85xx_CPM_FCC3] = {
+ .name = "fsl-cpm-fcc",
+ .id = 3,
+ .num_resources = 3,
+ .resource = (struct resource[]) {
+ {
+ .start = 0x91340,
+ .end = 0x9135F,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = 0x913D0,
+ .end = 0x913FF,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = SIU_INT_FCC3,
+ .end = SIU_INT_FCC3,
+ .flags = IORESOURCE_IRQ,
+ },
+ },
+ },
+ [MPC85xx_CPM_I2C] = {
+ .name = "fsl-cpm-i2c",
+ .id = 1,
+ .num_resources = 2,
+ .resource = (struct resource[]) {
+ {
+ .start = 0x91860,
+ .end = 0x918BF,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = SIU_INT_I2C,
+ .end = SIU_INT_I2C,
+ .flags = IORESOURCE_IRQ,
+ },
+ },
+ },
+ [MPC85xx_CPM_SCC1] = {
+ .name = "fsl-cpm-scc",
+ .id = 1,
+ .num_resources = 2,
+ .resource = (struct resource[]) {
+ {
+ .start = 0x91A00,
+ .end = 0x91A1F,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = SIU_INT_SCC1,
+ .end = SIU_INT_SCC1,
+ .flags = IORESOURCE_IRQ,
+ },
+ },
+ },
+ [MPC85xx_CPM_SCC2] = {
+ .name = "fsl-cpm-scc",
+ .id = 2,
+ .num_resources = 2,
+ .resource = (struct resource[]) {
+ {
+ .start = 0x91A20,
+ .end = 0x91A3F,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = SIU_INT_SCC2,
+ .end = SIU_INT_SCC2,
+ .flags = IORESOURCE_IRQ,
+ },
+ },
+ },
+ [MPC85xx_CPM_SCC3] = {
+ .name = "fsl-cpm-scc",
+ .id = 3,
+ .num_resources = 2,
+ .resource = (struct resource[]) {
+ {
+ .start = 0x91A40,
+ .end = 0x91A5F,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = SIU_INT_SCC3,
+ .end = SIU_INT_SCC3,
+ .flags = IORESOURCE_IRQ,
+ },
+ },
+ },
+ [MPC85xx_CPM_SCC4] = {
+ .name = "fsl-cpm-scc",
+ .id = 4,
+ .num_resources = 2,
+ .resource = (struct resource[]) {
+ {
+ .start = 0x91A60,
+ .end = 0x91A7F,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = SIU_INT_SCC4,
+ .end = SIU_INT_SCC4,
+ .flags = IORESOURCE_IRQ,
+ },
+ },
+ },
+ [MPC85xx_CPM_SPI] = {
+ .name = "fsl-cpm-spi",
+ .id = 1,
+ .num_resources = 2,
+ .resource = (struct resource[]) {
+ {
+ .start = 0x91AA0,
+ .end = 0x91AFF,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = SIU_INT_SPI,
+ .end = SIU_INT_SPI,
+ .flags = IORESOURCE_IRQ,
+ },
+ },
+ },
+ [MPC85xx_CPM_MCC1] = {
+ .name = "fsl-cpm-mcc",
+ .id = 1,
+ .num_resources = 2,
+ .resource = (struct resource[]) {
+ {
+ .start = 0x91B30,
+ .end = 0x91B3F,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = SIU_INT_MCC1,
+ .end = SIU_INT_MCC1,
+ .flags = IORESOURCE_IRQ,
+ },
+ },
+ },
+ [MPC85xx_CPM_MCC2] = {
+ .name = "fsl-cpm-mcc",
+ .id = 2,
+ .num_resources = 2,
+ .resource = (struct resource[]) {
+ {
+ .start = 0x91B50,
+ .end = 0x91B5F,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = SIU_INT_MCC2,
+ .end = SIU_INT_MCC2,
+ .flags = IORESOURCE_IRQ,
+ },
+ },
+ },
+ [MPC85xx_CPM_SMC1] = {
+ .name = "fsl-cpm-smc",
+ .id = 1,
+ .num_resources = 2,
+ .resource = (struct resource[]) {
+ {
+ .start = 0x91A80,
+ .end = 0x91A8F,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = SIU_INT_SMC1,
+ .end = SIU_INT_SMC1,
+ .flags = IORESOURCE_IRQ,
+ },
+ },
+ },
+ [MPC85xx_CPM_SMC2] = {
+ .name = "fsl-cpm-smc",
+ .id = 2,
+ .num_resources = 2,
+ .resource = (struct resource[]) {
+ {
+ .start = 0x91A90,
+ .end = 0x91A9F,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = SIU_INT_SMC2,
+ .end = SIU_INT_SMC2,
+ .flags = IORESOURCE_IRQ,
+ },
+ },
+ },
+ [MPC85xx_CPM_USB] = {
+ .name = "fsl-cpm-usb",
+ .id = 2,
+ .num_resources = 2,
+ .resource = (struct resource[]) {
+ {
+ .start = 0x91B60,
+ .end = 0x91B7F,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = SIU_INT_USB,
+ .end = SIU_INT_USB,
+ .flags = IORESOURCE_IRQ,
+ },
+ },
+ },
+#endif /* CONFIG_CPM2 */
+};
+
+static int __init mach_mpc85xx_fixup(struct platform_device *pdev)
+{
+ ppc_sys_fixup_mem_resource(pdev, CCSRBAR);
+ return 0;
+}
+
+static int __init mach_mpc85xx_init(void)
+{
+ ppc_sys_device_fixup = mach_mpc85xx_fixup;
+ return 0;
+}
+
+postcore_initcall(mach_mpc85xx_init);
diff --git a/arch/ppc/syslib/mpc85xx_sys.c b/arch/ppc/syslib/mpc85xx_sys.c
new file mode 100644
index 0000000..d806a92
--- /dev/null
+++ b/arch/ppc/syslib/mpc85xx_sys.c
@@ -0,0 +1,118 @@
+/*
+ * arch/ppc/platforms/85xx/mpc85xx_sys.c
+ *
+ * MPC85xx System descriptions
+ *
+ * Maintainer: Kumar Gala <kumar.gala@freescale.com>
+ *
+ * Copyright 2005 Freescale Semiconductor Inc.
+ *
+ * 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.
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <asm/ppc_sys.h>
+
+struct ppc_sys_spec *cur_ppc_sys_spec;
+struct ppc_sys_spec ppc_sys_specs[] = {
+ {
+ .ppc_sys_name = "8540",
+ .mask = 0xFFFF0000,
+ .value = 0x80300000,
+ .num_devices = 10,
+ .device_list = (enum ppc_sys_devices[])
+ {
+ MPC85xx_TSEC1, MPC85xx_TSEC2, MPC85xx_FEC, MPC85xx_IIC1,
+ MPC85xx_DMA0, MPC85xx_DMA1, MPC85xx_DMA2, MPC85xx_DMA3,
+ MPC85xx_PERFMON, MPC85xx_DUART,
+ },
+ },
+ {
+ .ppc_sys_name = "8560",
+ .mask = 0xFFFF0000,
+ .value = 0x80700000,
+ .num_devices = 19,
+ .device_list = (enum ppc_sys_devices[])
+ {
+ MPC85xx_TSEC1, MPC85xx_TSEC2, MPC85xx_IIC1,
+ MPC85xx_DMA0, MPC85xx_DMA1, MPC85xx_DMA2, MPC85xx_DMA3,
+ MPC85xx_PERFMON,
+ MPC85xx_CPM_SPI, MPC85xx_CPM_I2C, MPC85xx_CPM_SCC1,
+ MPC85xx_CPM_SCC2, MPC85xx_CPM_SCC3, MPC85xx_CPM_SCC4,
+ MPC85xx_CPM_FCC1, MPC85xx_CPM_FCC2, MPC85xx_CPM_FCC3,
+ MPC85xx_CPM_MCC1, MPC85xx_CPM_MCC2,
+ },
+ },
+ {
+ .ppc_sys_name = "8541",
+ .mask = 0xFFFF0000,
+ .value = 0x80720000,
+ .num_devices = 13,
+ .device_list = (enum ppc_sys_devices[])
+ {
+ MPC85xx_TSEC1, MPC85xx_TSEC2, MPC85xx_IIC1,
+ MPC85xx_DMA0, MPC85xx_DMA1, MPC85xx_DMA2, MPC85xx_DMA3,
+ MPC85xx_PERFMON, MPC85xx_DUART,
+ MPC85xx_CPM_SPI, MPC85xx_CPM_I2C,
+ MPC85xx_CPM_FCC1, MPC85xx_CPM_FCC2,
+ },
+ },
+ {
+ .ppc_sys_name = "8541E",
+ .mask = 0xFFFF0000,
+ .value = 0x807A0000,
+ .num_devices = 14,
+ .device_list = (enum ppc_sys_devices[])
+ {
+ MPC85xx_TSEC1, MPC85xx_TSEC2, MPC85xx_IIC1,
+ MPC85xx_DMA0, MPC85xx_DMA1, MPC85xx_DMA2, MPC85xx_DMA3,
+ MPC85xx_PERFMON, MPC85xx_DUART, MPC85xx_SEC2,
+ MPC85xx_CPM_SPI, MPC85xx_CPM_I2C,
+ MPC85xx_CPM_FCC1, MPC85xx_CPM_FCC2,
+ },
+ },
+ {
+ .ppc_sys_name = "8555",
+ .mask = 0xFFFF0000,
+ .value = 0x80710000,
+ .num_devices = 19,
+ .device_list = (enum ppc_sys_devices[])
+ {
+ MPC85xx_TSEC1, MPC85xx_TSEC2, MPC85xx_IIC1,
+ MPC85xx_DMA0, MPC85xx_DMA1, MPC85xx_DMA2, MPC85xx_DMA3,
+ MPC85xx_PERFMON, MPC85xx_DUART,
+ MPC85xx_CPM_SPI, MPC85xx_CPM_I2C, MPC85xx_CPM_SCC1,
+ MPC85xx_CPM_SCC2, MPC85xx_CPM_SCC3,
+ MPC85xx_CPM_FCC1, MPC85xx_CPM_FCC2,
+ MPC85xx_CPM_SMC1, MPC85xx_CPM_SMC2,
+ MPC85xx_CPM_USB,
+ },
+ },
+ {
+ .ppc_sys_name = "8555E",
+ .mask = 0xFFFF0000,
+ .value = 0x80790000,
+ .num_devices = 20,
+ .device_list = (enum ppc_sys_devices[])
+ {
+ MPC85xx_TSEC1, MPC85xx_TSEC2, MPC85xx_IIC1,
+ MPC85xx_DMA0, MPC85xx_DMA1, MPC85xx_DMA2, MPC85xx_DMA3,
+ MPC85xx_PERFMON, MPC85xx_DUART, MPC85xx_SEC2,
+ MPC85xx_CPM_SPI, MPC85xx_CPM_I2C, MPC85xx_CPM_SCC1,
+ MPC85xx_CPM_SCC2, MPC85xx_CPM_SCC3,
+ MPC85xx_CPM_FCC1, MPC85xx_CPM_FCC2,
+ MPC85xx_CPM_SMC1, MPC85xx_CPM_SMC2,
+ MPC85xx_CPM_USB,
+ },
+ },
+ { /* default match */
+ .ppc_sys_name = "",
+ .mask = 0x00000000,
+ .value = 0x00000000,
+ },
+};
diff --git a/arch/ppc/syslib/mv64360_pic.c b/arch/ppc/syslib/mv64360_pic.c
new file mode 100644
index 0000000..74d8996
--- /dev/null
+++ b/arch/ppc/syslib/mv64360_pic.c
@@ -0,0 +1,426 @@
+/*
+ * arch/ppc/kernel/mv64360_pic.c
+ *
+ * Interrupt controller support for Marvell's MV64360.
+ *
+ * Author: Rabeeh Khoury <rabeeh@galileo.co.il>
+ * Based on MV64360 PIC written by
+ * Chris Zankel <chris@mvista.com>
+ * Mark A. Greer <mgreer@mvista.com>
+ *
+ * Copyright 2004 MontaVista Software, Inc.
+ *
+ * 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 file contains the specific functions to support the MV64360
+ * interrupt controller.
+ *
+ * The MV64360 has two main interrupt registers (high and low) that
+ * summarizes the interrupts generated by the units of the MV64360.
+ * Each bit is assigned to an interrupt number, where the low register
+ * are assigned from IRQ0 to IRQ31 and the high cause register
+ * from IRQ32 to IRQ63
+ * The GPP (General Purpose Pins) interrupts are assigned from IRQ64 (GPP0)
+ * to IRQ95 (GPP31).
+ * get_irq() returns the lowest interrupt number that is currently asserted.
+ *
+ * Note:
+ * - This driver does not initialize the GPP when used as an interrupt
+ * input.
+ */
+
+#include <linux/stddef.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/signal.h>
+#include <linux/stddef.h>
+#include <linux/delay.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+
+#include <asm/io.h>
+#include <asm/processor.h>
+#include <asm/system.h>
+#include <asm/irq.h>
+#include <asm/mv64x60.h>
+
+#ifdef CONFIG_IRQ_ALL_CPUS
+#error "The mv64360 does not support distribution of IRQs on all CPUs"
+#endif
+/* ========================== forward declaration ========================== */
+
+static void mv64360_unmask_irq(unsigned int);
+static void mv64360_mask_irq(unsigned int);
+static irqreturn_t mv64360_cpu_error_int_handler(int, void *, struct pt_regs *);
+static irqreturn_t mv64360_sram_error_int_handler(int, void *,
+ struct pt_regs *);
+static irqreturn_t mv64360_pci_error_int_handler(int, void *, struct pt_regs *);
+
+/* ========================== local declarations =========================== */
+
+struct hw_interrupt_type mv64360_pic = {
+ .typename = " mv64360 ",
+ .enable = mv64360_unmask_irq,
+ .disable = mv64360_mask_irq,
+ .ack = mv64360_mask_irq,
+ .end = mv64360_unmask_irq,
+};
+
+#define CPU_INTR_STR "mv64360 cpu interface error"
+#define SRAM_INTR_STR "mv64360 internal sram error"
+#define PCI0_INTR_STR "mv64360 pci 0 error"
+#define PCI1_INTR_STR "mv64360 pci 1 error"
+
+static struct mv64x60_handle bh;
+
+u32 mv64360_irq_base = 0; /* MV64360 handles the next 96 IRQs from here */
+
+/* mv64360_init_irq()
+ *
+ * This function initializes the interrupt controller. It assigns
+ * all interrupts from IRQ0 to IRQ95 to the mv64360 interrupt controller.
+ *
+ * Input Variable(s):
+ * None.
+ *
+ * Outpu. Variable(s):
+ * None.
+ *
+ * Returns:
+ * void
+ *
+ * Note:
+ * We register all GPP inputs as interrupt source, but disable them.
+ */
+void __init
+mv64360_init_irq(void)
+{
+ int i;
+
+ if (ppc_md.progress)
+ ppc_md.progress("mv64360_init_irq: enter", 0x0);
+
+ bh.v_base = mv64x60_get_bridge_vbase();
+
+ ppc_cached_irq_mask[0] = 0;
+ ppc_cached_irq_mask[1] = 0x0f000000; /* Enable GPP intrs */
+ ppc_cached_irq_mask[2] = 0;
+
+ /* disable all interrupts and clear current interrupts */
+ mv64x60_write(&bh, MV64x60_GPP_INTR_CAUSE, 0);
+ mv64x60_write(&bh, MV64x60_GPP_INTR_MASK, ppc_cached_irq_mask[2]);
+ mv64x60_write(&bh, MV64360_IC_CPU0_INTR_MASK_LO,ppc_cached_irq_mask[0]);
+ mv64x60_write(&bh, MV64360_IC_CPU0_INTR_MASK_HI,ppc_cached_irq_mask[1]);
+
+ /* All interrupts are level interrupts */
+ for (i = mv64360_irq_base; i < (mv64360_irq_base + 96); i++) {
+ irq_desc[i].status |= IRQ_LEVEL;
+ irq_desc[i].handler = &mv64360_pic;
+ }
+
+ if (ppc_md.progress)
+ ppc_md.progress("mv64360_init_irq: exit", 0x0);
+}
+
+/* mv64360_get_irq()
+ *
+ * This function returns the lowest interrupt number of all interrupts that
+ * are currently asserted.
+ *
+ * Input Variable(s):
+ * struct pt_regs* not used
+ *
+ * Output Variable(s):
+ * None.
+ *
+ * Returns:
+ * int <interrupt number> or -2 (bogus interrupt)
+ *
+ */
+int
+mv64360_get_irq(struct pt_regs *regs)
+{
+ int irq;
+ int irq_gpp;
+
+#ifdef CONFIG_SMP
+ /*
+ * Second CPU gets only doorbell (message) interrupts.
+ * The doorbell interrupt is BIT28 in the main interrupt low cause reg.
+ */
+ int cpu_nr = smp_processor_id();
+ if (cpu_nr == 1) {
+ if (!(mv64x60_read(&bh, MV64360_IC_MAIN_CAUSE_LO) &
+ (1 << MV64x60_IRQ_DOORBELL)))
+ return -1;
+ return mv64360_irq_base + MV64x60_IRQ_DOORBELL;
+ }
+#endif
+
+ irq = mv64x60_read(&bh, MV64360_IC_MAIN_CAUSE_LO);
+ irq = __ilog2((irq & 0x3dfffffe) & ppc_cached_irq_mask[0]);
+
+ if (irq == -1) {
+ irq = mv64x60_read(&bh, MV64360_IC_MAIN_CAUSE_HI);
+ irq = __ilog2((irq & 0x1f0003f7) & ppc_cached_irq_mask[1]);
+
+ if (irq == -1)
+ irq = -2; /* bogus interrupt, should never happen */
+ else {
+ if ((irq >= 24) && (irq < MV64x60_IRQ_DOORBELL)) {
+ irq_gpp = mv64x60_read(&bh,
+ MV64x60_GPP_INTR_CAUSE);
+ irq_gpp = __ilog2(irq_gpp &
+ ppc_cached_irq_mask[2]);
+
+ if (irq_gpp == -1)
+ irq = -2;
+ else {
+ irq = irq_gpp + 64;
+ mv64x60_write(&bh,
+ MV64x60_GPP_INTR_CAUSE,
+ ~(1 << (irq - 64)));
+ }
+ }
+ else
+ irq += 32;
+ }
+ }
+
+ (void)mv64x60_read(&bh, MV64x60_GPP_INTR_CAUSE);
+
+ if (irq < 0)
+ return (irq);
+ else
+ return (mv64360_irq_base + irq);
+}
+
+/* mv64360_unmask_irq()
+ *
+ * This function enables an interrupt.
+ *
+ * Input Variable(s):
+ * unsigned int interrupt number (IRQ0...IRQ95).
+ *
+ * Output Variable(s):
+ * None.
+ *
+ * Returns:
+ * void
+ */
+static void
+mv64360_unmask_irq(unsigned int irq)
+{
+#ifdef CONFIG_SMP
+ /* second CPU gets only doorbell interrupts */
+ if ((irq - mv64360_irq_base) == MV64x60_IRQ_DOORBELL) {
+ mv64x60_set_bits(&bh, MV64360_IC_CPU1_INTR_MASK_LO,
+ (1 << MV64x60_IRQ_DOORBELL));
+ return;
+ }
+#endif
+ irq -= mv64360_irq_base;
+
+ if (irq > 31) {
+ if (irq > 63) /* unmask GPP irq */
+ mv64x60_write(&bh, MV64x60_GPP_INTR_MASK,
+ ppc_cached_irq_mask[2] |= (1 << (irq - 64)));
+ else /* mask high interrupt register */
+ mv64x60_write(&bh, MV64360_IC_CPU0_INTR_MASK_HI,
+ ppc_cached_irq_mask[1] |= (1 << (irq - 32)));
+ }
+ else /* mask low interrupt register */
+ mv64x60_write(&bh, MV64360_IC_CPU0_INTR_MASK_LO,
+ ppc_cached_irq_mask[0] |= (1 << irq));
+
+ (void)mv64x60_read(&bh, MV64x60_GPP_INTR_MASK);
+ return;
+}
+
+/* mv64360_mask_irq()
+ *
+ * This function disables the requested interrupt.
+ *
+ * Input Variable(s):
+ * unsigned int interrupt number (IRQ0...IRQ95).
+ *
+ * Output Variable(s):
+ * None.
+ *
+ * Returns:
+ * void
+ */
+static void
+mv64360_mask_irq(unsigned int irq)
+{
+#ifdef CONFIG_SMP
+ if ((irq - mv64360_irq_base) == MV64x60_IRQ_DOORBELL) {
+ mv64x60_clr_bits(&bh, MV64360_IC_CPU1_INTR_MASK_LO,
+ (1 << MV64x60_IRQ_DOORBELL));
+ return;
+ }
+#endif
+ irq -= mv64360_irq_base;
+
+ if (irq > 31) {
+ if (irq > 63) /* mask GPP irq */
+ mv64x60_write(&bh, MV64x60_GPP_INTR_MASK,
+ ppc_cached_irq_mask[2] &= ~(1 << (irq - 64)));
+ else /* mask high interrupt register */
+ mv64x60_write(&bh, MV64360_IC_CPU0_INTR_MASK_HI,
+ ppc_cached_irq_mask[1] &= ~(1 << (irq - 32)));
+ }
+ else /* mask low interrupt register */
+ mv64x60_write(&bh, MV64360_IC_CPU0_INTR_MASK_LO,
+ ppc_cached_irq_mask[0] &= ~(1 << irq));
+
+ (void)mv64x60_read(&bh, MV64x60_GPP_INTR_MASK);
+ return;
+}
+
+static irqreturn_t
+mv64360_cpu_error_int_handler(int irq, void *dev_id, struct pt_regs *regs)
+{
+ printk(KERN_ERR "mv64360_cpu_error_int_handler: %s 0x%08x\n",
+ "Error on CPU interface - Cause regiser",
+ mv64x60_read(&bh, MV64x60_CPU_ERR_CAUSE));
+ printk(KERN_ERR "\tCPU error register dump:\n");
+ printk(KERN_ERR "\tAddress low 0x%08x\n",
+ mv64x60_read(&bh, MV64x60_CPU_ERR_ADDR_LO));
+ printk(KERN_ERR "\tAddress high 0x%08x\n",
+ mv64x60_read(&bh, MV64x60_CPU_ERR_ADDR_HI));
+ printk(KERN_ERR "\tData low 0x%08x\n",
+ mv64x60_read(&bh, MV64x60_CPU_ERR_DATA_LO));
+ printk(KERN_ERR "\tData high 0x%08x\n",
+ mv64x60_read(&bh, MV64x60_CPU_ERR_DATA_HI));
+ printk(KERN_ERR "\tParity 0x%08x\n",
+ mv64x60_read(&bh, MV64x60_CPU_ERR_PARITY));
+ mv64x60_write(&bh, MV64x60_CPU_ERR_CAUSE, 0);
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t
+mv64360_sram_error_int_handler(int irq, void *dev_id, struct pt_regs *regs)
+{
+ printk(KERN_ERR "mv64360_sram_error_int_handler: %s 0x%08x\n",
+ "Error in internal SRAM - Cause register",
+ mv64x60_read(&bh, MV64360_SRAM_ERR_CAUSE));
+ printk(KERN_ERR "\tSRAM error register dump:\n");
+ printk(KERN_ERR "\tAddress Low 0x%08x\n",
+ mv64x60_read(&bh, MV64360_SRAM_ERR_ADDR_LO));
+ printk(KERN_ERR "\tAddress High 0x%08x\n",
+ mv64x60_read(&bh, MV64360_SRAM_ERR_ADDR_HI));
+ printk(KERN_ERR "\tData Low 0x%08x\n",
+ mv64x60_read(&bh, MV64360_SRAM_ERR_DATA_LO));
+ printk(KERN_ERR "\tData High 0x%08x\n",
+ mv64x60_read(&bh, MV64360_SRAM_ERR_DATA_HI));
+ printk(KERN_ERR "\tParity 0x%08x\n",
+ mv64x60_read(&bh, MV64360_SRAM_ERR_PARITY));
+ mv64x60_write(&bh, MV64360_SRAM_ERR_CAUSE, 0);
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t
+mv64360_pci_error_int_handler(int irq, void *dev_id, struct pt_regs *regs)
+{
+ u32 val;
+ unsigned int pci_bus = (unsigned int)dev_id;
+
+ if (pci_bus == 0) { /* Error on PCI 0 */
+ val = mv64x60_read(&bh, MV64x60_PCI0_ERR_CAUSE);
+ printk(KERN_ERR "%s: Error in PCI %d Interface\n",
+ "mv64360_pci_error_int_handler", pci_bus);
+ printk(KERN_ERR "\tPCI %d error register dump:\n", pci_bus);
+ printk(KERN_ERR "\tCause register 0x%08x\n", val);
+ printk(KERN_ERR "\tAddress Low 0x%08x\n",
+ mv64x60_read(&bh, MV64x60_PCI0_ERR_ADDR_LO));
+ printk(KERN_ERR "\tAddress High 0x%08x\n",
+ mv64x60_read(&bh, MV64x60_PCI0_ERR_ADDR_HI));
+ printk(KERN_ERR "\tAttribute 0x%08x\n",
+ mv64x60_read(&bh, MV64x60_PCI0_ERR_DATA_LO));
+ printk(KERN_ERR "\tCommand 0x%08x\n",
+ mv64x60_read(&bh, MV64x60_PCI0_ERR_CMD));
+ mv64x60_write(&bh, MV64x60_PCI0_ERR_CAUSE, ~val);
+ }
+ if (pci_bus == 1) { /* Error on PCI 1 */
+ val = mv64x60_read(&bh, MV64x60_PCI1_ERR_CAUSE);
+ printk(KERN_ERR "%s: Error in PCI %d Interface\n",
+ "mv64360_pci_error_int_handler", pci_bus);
+ printk(KERN_ERR "\tPCI %d error register dump:\n", pci_bus);
+ printk(KERN_ERR "\tCause register 0x%08x\n", val);
+ printk(KERN_ERR "\tAddress Low 0x%08x\n",
+ mv64x60_read(&bh, MV64x60_PCI1_ERR_ADDR_LO));
+ printk(KERN_ERR "\tAddress High 0x%08x\n",
+ mv64x60_read(&bh, MV64x60_PCI1_ERR_ADDR_HI));
+ printk(KERN_ERR "\tAttribute 0x%08x\n",
+ mv64x60_read(&bh, MV64x60_PCI1_ERR_DATA_LO));
+ printk(KERN_ERR "\tCommand 0x%08x\n",
+ mv64x60_read(&bh, MV64x60_PCI1_ERR_CMD));
+ mv64x60_write(&bh, MV64x60_PCI1_ERR_CAUSE, ~val);
+ }
+ return IRQ_HANDLED;
+}
+
+static int __init
+mv64360_register_hdlrs(void)
+{
+ u32 mask;
+ int rc;
+
+ /* Clear old errors and register CPU interface error intr handler */
+ mv64x60_write(&bh, MV64x60_CPU_ERR_CAUSE, 0);
+ if ((rc = request_irq(MV64x60_IRQ_CPU_ERR + mv64360_irq_base,
+ mv64360_cpu_error_int_handler, SA_INTERRUPT, CPU_INTR_STR, 0)))
+ printk(KERN_WARNING "Can't register cpu error handler: %d", rc);
+
+ mv64x60_write(&bh, MV64x60_CPU_ERR_MASK, 0);
+ mv64x60_write(&bh, MV64x60_CPU_ERR_MASK, 0x000000ff);
+
+ /* Clear old errors and register internal SRAM error intr handler */
+ mv64x60_write(&bh, MV64360_SRAM_ERR_CAUSE, 0);
+ if ((rc = request_irq(MV64360_IRQ_SRAM_PAR_ERR + mv64360_irq_base,
+ mv64360_sram_error_int_handler,SA_INTERRUPT,SRAM_INTR_STR, 0)))
+ printk(KERN_WARNING "Can't register SRAM error handler: %d",rc);
+
+ /*
+ * Bit 0 reserved on 64360 and erratum FEr PCI-#11 (PCI internal
+ * data parity error set incorrectly) on rev 0 & 1 of 64460 requires
+ * bit 0 to be cleared.
+ */
+ mask = 0x00a50c24;
+
+ if ((mv64x60_get_bridge_type() == MV64x60_TYPE_MV64460) &&
+ (mv64x60_get_bridge_rev() > 1))
+ mask |= 0x1; /* enable DPErr on 64460 */
+
+ /* Clear old errors and register PCI 0 error intr handler */
+ mv64x60_write(&bh, MV64x60_PCI0_ERR_CAUSE, 0);
+ if ((rc = request_irq(MV64360_IRQ_PCI0 + mv64360_irq_base,
+ mv64360_pci_error_int_handler,
+ SA_INTERRUPT, PCI0_INTR_STR, (void *)0)))
+ printk(KERN_WARNING "Can't register pci 0 error handler: %d",
+ rc);
+
+ mv64x60_write(&bh, MV64x60_PCI0_ERR_MASK, 0);
+ mv64x60_write(&bh, MV64x60_PCI0_ERR_MASK, mask);
+
+ /* Clear old errors and register PCI 1 error intr handler */
+ mv64x60_write(&bh, MV64x60_PCI1_ERR_CAUSE, 0);
+ if ((rc = request_irq(MV64360_IRQ_PCI1 + mv64360_irq_base,
+ mv64360_pci_error_int_handler,
+ SA_INTERRUPT, PCI1_INTR_STR, (void *)1)))
+ printk(KERN_WARNING "Can't register pci 1 error handler: %d",
+ rc);
+
+ mv64x60_write(&bh, MV64x60_PCI1_ERR_MASK, 0);
+ mv64x60_write(&bh, MV64x60_PCI1_ERR_MASK, mask);
+
+ return 0;
+}
+
+arch_initcall(mv64360_register_hdlrs);
diff --git a/arch/ppc/syslib/mv64x60.c b/arch/ppc/syslib/mv64x60.c
new file mode 100644
index 0000000..7b241e7
--- /dev/null
+++ b/arch/ppc/syslib/mv64x60.c
@@ -0,0 +1,2392 @@
+/*
+ * arch/ppc/syslib/mv64x60.c
+ *
+ * Common routines for the Marvell/Galileo Discovery line of host bridges
+ * (gt64260, mv64360, mv64460, ...).
+ *
+ * Author: Mark A. Greer <mgreer@mvista.com>
+ *
+ * 2004 (c) MontaVista, Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/bootmem.h>
+#include <linux/spinlock.h>
+#include <linux/mv643xx.h>
+
+#include <asm/byteorder.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/uaccess.h>
+#include <asm/machdep.h>
+#include <asm/pci-bridge.h>
+#include <asm/delay.h>
+#include <asm/mv64x60.h>
+
+
+u8 mv64x60_pci_exclude_bridge = 1;
+spinlock_t mv64x60_lock = SPIN_LOCK_UNLOCKED;
+
+static phys_addr_t mv64x60_bridge_pbase = 0;
+static void *mv64x60_bridge_vbase = 0;
+static u32 mv64x60_bridge_type = MV64x60_TYPE_INVALID;
+static u32 mv64x60_bridge_rev = 0;
+
+static u32 gt64260_translate_size(u32 base, u32 size, u32 num_bits);
+static u32 gt64260_untranslate_size(u32 base, u32 size, u32 num_bits);
+static void gt64260_set_pci2mem_window(struct pci_controller *hose, u32 bus,
+ u32 window, u32 base);
+static void gt64260_set_pci2regs_window(struct mv64x60_handle *bh,
+ struct pci_controller *hose, u32 bus, u32 base);
+static u32 gt64260_is_enabled_32bit(struct mv64x60_handle *bh, u32 window);
+static void gt64260_enable_window_32bit(struct mv64x60_handle *bh, u32 window);
+static void gt64260_disable_window_32bit(struct mv64x60_handle *bh, u32 window);
+static void gt64260_enable_window_64bit(struct mv64x60_handle *bh, u32 window);
+static void gt64260_disable_window_64bit(struct mv64x60_handle *bh, u32 window);
+static void gt64260_disable_all_windows(struct mv64x60_handle *bh,
+ struct mv64x60_setup_info *si);
+static void gt64260a_chip_specific_init(struct mv64x60_handle *bh,
+ struct mv64x60_setup_info *si);
+static void gt64260b_chip_specific_init(struct mv64x60_handle *bh,
+ struct mv64x60_setup_info *si);
+
+static u32 mv64360_translate_size(u32 base, u32 size, u32 num_bits);
+static u32 mv64360_untranslate_size(u32 base, u32 size, u32 num_bits);
+static void mv64360_set_pci2mem_window(struct pci_controller *hose, u32 bus,
+ u32 window, u32 base);
+static void mv64360_set_pci2regs_window(struct mv64x60_handle *bh,
+ struct pci_controller *hose, u32 bus, u32 base);
+static u32 mv64360_is_enabled_32bit(struct mv64x60_handle *bh, u32 window);
+static void mv64360_enable_window_32bit(struct mv64x60_handle *bh, u32 window);
+static void mv64360_disable_window_32bit(struct mv64x60_handle *bh, u32 window);
+static void mv64360_enable_window_64bit(struct mv64x60_handle *bh, u32 window);
+static void mv64360_disable_window_64bit(struct mv64x60_handle *bh, u32 window);
+static void mv64360_disable_all_windows(struct mv64x60_handle *bh,
+ struct mv64x60_setup_info *si);
+static void mv64360_config_io2mem_windows(struct mv64x60_handle *bh,
+ struct mv64x60_setup_info *si,
+ u32 mem_windows[MV64x60_CPU2MEM_WINDOWS][2]);
+static void mv64360_set_mpsc2regs_window(struct mv64x60_handle *bh, u32 base);
+static void mv64360_chip_specific_init(struct mv64x60_handle *bh,
+ struct mv64x60_setup_info *si);
+static void mv64460_chip_specific_init(struct mv64x60_handle *bh,
+ struct mv64x60_setup_info *si);
+
+
+/*
+ * Define tables that have the chip-specific info for each type of
+ * Marvell bridge chip.
+ */
+static struct mv64x60_chip_info gt64260a_ci __initdata = { /* GT64260A */
+ .translate_size = gt64260_translate_size,
+ .untranslate_size = gt64260_untranslate_size,
+ .set_pci2mem_window = gt64260_set_pci2mem_window,
+ .set_pci2regs_window = gt64260_set_pci2regs_window,
+ .is_enabled_32bit = gt64260_is_enabled_32bit,
+ .enable_window_32bit = gt64260_enable_window_32bit,
+ .disable_window_32bit = gt64260_disable_window_32bit,
+ .enable_window_64bit = gt64260_enable_window_64bit,
+ .disable_window_64bit = gt64260_disable_window_64bit,
+ .disable_all_windows = gt64260_disable_all_windows,
+ .chip_specific_init = gt64260a_chip_specific_init,
+ .window_tab_32bit = gt64260_32bit_windows,
+ .window_tab_64bit = gt64260_64bit_windows,
+};
+
+static struct mv64x60_chip_info gt64260b_ci __initdata = { /* GT64260B */
+ .translate_size = gt64260_translate_size,
+ .untranslate_size = gt64260_untranslate_size,
+ .set_pci2mem_window = gt64260_set_pci2mem_window,
+ .set_pci2regs_window = gt64260_set_pci2regs_window,
+ .is_enabled_32bit = gt64260_is_enabled_32bit,
+ .enable_window_32bit = gt64260_enable_window_32bit,
+ .disable_window_32bit = gt64260_disable_window_32bit,
+ .enable_window_64bit = gt64260_enable_window_64bit,
+ .disable_window_64bit = gt64260_disable_window_64bit,
+ .disable_all_windows = gt64260_disable_all_windows,
+ .chip_specific_init = gt64260b_chip_specific_init,
+ .window_tab_32bit = gt64260_32bit_windows,
+ .window_tab_64bit = gt64260_64bit_windows,
+};
+
+static struct mv64x60_chip_info mv64360_ci __initdata = { /* MV64360 */
+ .translate_size = mv64360_translate_size,
+ .untranslate_size = mv64360_untranslate_size,
+ .set_pci2mem_window = mv64360_set_pci2mem_window,
+ .set_pci2regs_window = mv64360_set_pci2regs_window,
+ .is_enabled_32bit = mv64360_is_enabled_32bit,
+ .enable_window_32bit = mv64360_enable_window_32bit,
+ .disable_window_32bit = mv64360_disable_window_32bit,
+ .enable_window_64bit = mv64360_enable_window_64bit,
+ .disable_window_64bit = mv64360_disable_window_64bit,
+ .disable_all_windows = mv64360_disable_all_windows,
+ .config_io2mem_windows = mv64360_config_io2mem_windows,
+ .set_mpsc2regs_window = mv64360_set_mpsc2regs_window,
+ .chip_specific_init = mv64360_chip_specific_init,
+ .window_tab_32bit = mv64360_32bit_windows,
+ .window_tab_64bit = mv64360_64bit_windows,
+};
+
+static struct mv64x60_chip_info mv64460_ci __initdata = { /* MV64460 */
+ .translate_size = mv64360_translate_size,
+ .untranslate_size = mv64360_untranslate_size,
+ .set_pci2mem_window = mv64360_set_pci2mem_window,
+ .set_pci2regs_window = mv64360_set_pci2regs_window,
+ .is_enabled_32bit = mv64360_is_enabled_32bit,
+ .enable_window_32bit = mv64360_enable_window_32bit,
+ .disable_window_32bit = mv64360_disable_window_32bit,
+ .enable_window_64bit = mv64360_enable_window_64bit,
+ .disable_window_64bit = mv64360_disable_window_64bit,
+ .disable_all_windows = mv64360_disable_all_windows,
+ .config_io2mem_windows = mv64360_config_io2mem_windows,
+ .set_mpsc2regs_window = mv64360_set_mpsc2regs_window,
+ .chip_specific_init = mv64460_chip_specific_init,
+ .window_tab_32bit = mv64360_32bit_windows,
+ .window_tab_64bit = mv64360_64bit_windows,
+};
+
+/*
+ *****************************************************************************
+ *
+ * Platform Device Definitions
+ *
+ *****************************************************************************
+ */
+#ifdef CONFIG_SERIAL_MPSC
+static struct mpsc_shared_pdata mv64x60_mpsc_shared_pdata = {
+ .mrr_val = 0x3ffffe38,
+ .rcrr_val = 0,
+ .tcrr_val = 0,
+ .intr_cause_val = 0,
+ .intr_mask_val = 0,
+};
+
+static struct resource mv64x60_mpsc_shared_resources[] = {
+ /* Do not change the order of the IORESOURCE_MEM resources */
+ [0] = {
+ .name = "mpsc routing base",
+ .start = MV64x60_MPSC_ROUTING_OFFSET,
+ .end = MV64x60_MPSC_ROUTING_OFFSET +
+ MPSC_ROUTING_REG_BLOCK_SIZE - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .name = "sdma intr base",
+ .start = MV64x60_SDMA_INTR_OFFSET,
+ .end = MV64x60_SDMA_INTR_OFFSET +
+ MPSC_SDMA_INTR_REG_BLOCK_SIZE - 1,
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+static struct platform_device mpsc_shared_device = { /* Shared device */
+ .name = MPSC_SHARED_NAME,
+ .id = 0,
+ .num_resources = ARRAY_SIZE(mv64x60_mpsc_shared_resources),
+ .resource = mv64x60_mpsc_shared_resources,
+ .dev = {
+ .platform_data = &mv64x60_mpsc_shared_pdata,
+ },
+};
+
+static struct mpsc_pdata mv64x60_mpsc0_pdata = {
+ .mirror_regs = 0,
+ .cache_mgmt = 0,
+ .max_idle = 0,
+ .default_baud = 9600,
+ .default_bits = 8,
+ .default_parity = 'n',
+ .default_flow = 'n',
+ .chr_1_val = 0x00000000,
+ .chr_2_val = 0x00000000,
+ .chr_10_val = 0x00000003,
+ .mpcr_val = 0,
+ .bcr_val = 0,
+ .brg_can_tune = 0,
+ .brg_clk_src = 8, /* Default to TCLK */
+ .brg_clk_freq = 100000000, /* Default to 100 MHz */
+};
+
+static struct resource mv64x60_mpsc0_resources[] = {
+ /* Do not change the order of the IORESOURCE_MEM resources */
+ [0] = {
+ .name = "mpsc 0 base",
+ .start = MV64x60_MPSC_0_OFFSET,
+ .end = MV64x60_MPSC_0_OFFSET + MPSC_REG_BLOCK_SIZE - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .name = "sdma 0 base",
+ .start = MV64x60_SDMA_0_OFFSET,
+ .end = MV64x60_SDMA_0_OFFSET + MPSC_SDMA_REG_BLOCK_SIZE - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [2] = {
+ .name = "brg 0 base",
+ .start = MV64x60_BRG_0_OFFSET,
+ .end = MV64x60_BRG_0_OFFSET + MPSC_BRG_REG_BLOCK_SIZE - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [3] = {
+ .name = "sdma 0 irq",
+ .start = MV64x60_IRQ_SDMA_0,
+ .end = MV64x60_IRQ_SDMA_0,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device mpsc0_device = {
+ .name = MPSC_CTLR_NAME,
+ .id = 0,
+ .num_resources = ARRAY_SIZE(mv64x60_mpsc0_resources),
+ .resource = mv64x60_mpsc0_resources,
+ .dev = {
+ .platform_data = &mv64x60_mpsc0_pdata,
+ },
+};
+
+static struct mpsc_pdata mv64x60_mpsc1_pdata = {
+ .mirror_regs = 0,
+ .cache_mgmt = 0,
+ .max_idle = 0,
+ .default_baud = 9600,
+ .default_bits = 8,
+ .default_parity = 'n',
+ .default_flow = 'n',
+ .chr_1_val = 0x00000000,
+ .chr_1_val = 0x00000000,
+ .chr_2_val = 0x00000000,
+ .chr_10_val = 0x00000003,
+ .mpcr_val = 0,
+ .bcr_val = 0,
+ .brg_can_tune = 0,
+ .brg_clk_src = 8, /* Default to TCLK */
+ .brg_clk_freq = 100000000, /* Default to 100 MHz */
+};
+
+static struct resource mv64x60_mpsc1_resources[] = {
+ /* Do not change the order of the IORESOURCE_MEM resources */
+ [0] = {
+ .name = "mpsc 1 base",
+ .start = MV64x60_MPSC_1_OFFSET,
+ .end = MV64x60_MPSC_1_OFFSET + MPSC_REG_BLOCK_SIZE - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .name = "sdma 1 base",
+ .start = MV64x60_SDMA_1_OFFSET,
+ .end = MV64x60_SDMA_1_OFFSET + MPSC_SDMA_REG_BLOCK_SIZE - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [2] = {
+ .name = "brg 1 base",
+ .start = MV64x60_BRG_1_OFFSET,
+ .end = MV64x60_BRG_1_OFFSET + MPSC_BRG_REG_BLOCK_SIZE - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [3] = {
+ .name = "sdma 1 irq",
+ .start = MV64360_IRQ_SDMA_1,
+ .end = MV64360_IRQ_SDMA_1,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device mpsc1_device = {
+ .name = MPSC_CTLR_NAME,
+ .id = 1,
+ .num_resources = ARRAY_SIZE(mv64x60_mpsc1_resources),
+ .resource = mv64x60_mpsc1_resources,
+ .dev = {
+ .platform_data = &mv64x60_mpsc1_pdata,
+ },
+};
+#endif
+
+#ifdef CONFIG_MV643XX_ETH
+static struct resource mv64x60_eth_shared_resources[] = {
+ [0] = {
+ .name = "ethernet shared base",
+ .start = MV643XX_ETH_SHARED_REGS,
+ .end = MV643XX_ETH_SHARED_REGS +
+ MV643XX_ETH_SHARED_REGS_SIZE - 1,
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+static struct platform_device mv64x60_eth_shared_device = {
+ .name = MV643XX_ETH_SHARED_NAME,
+ .id = 0,
+ .num_resources = ARRAY_SIZE(mv64x60_eth_shared_resources),
+ .resource = mv64x60_eth_shared_resources,
+};
+
+#ifdef CONFIG_MV643XX_ETH_0
+static struct resource mv64x60_eth0_resources[] = {
+ [0] = {
+ .name = "eth0 irq",
+ .start = MV64x60_IRQ_ETH_0,
+ .end = MV64x60_IRQ_ETH_0,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct mv643xx_eth_platform_data eth0_pd;
+
+static struct platform_device eth0_device = {
+ .name = MV643XX_ETH_NAME,
+ .id = 0,
+ .num_resources = ARRAY_SIZE(mv64x60_eth0_resources),
+ .resource = mv64x60_eth0_resources,
+ .dev = {
+ .platform_data = ð0_pd,
+ },
+};
+#endif
+
+#ifdef CONFIG_MV643XX_ETH_1
+static struct resource mv64x60_eth1_resources[] = {
+ [0] = {
+ .name = "eth1 irq",
+ .start = MV64x60_IRQ_ETH_1,
+ .end = MV64x60_IRQ_ETH_1,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct mv643xx_eth_platform_data eth1_pd;
+
+static struct platform_device eth1_device = {
+ .name = MV643XX_ETH_NAME,
+ .id = 1,
+ .num_resources = ARRAY_SIZE(mv64x60_eth1_resources),
+ .resource = mv64x60_eth1_resources,
+ .dev = {
+ .platform_data = ð1_pd,
+ },
+};
+#endif
+
+#ifdef CONFIG_MV643XX_ETH_2
+static struct resource mv64x60_eth2_resources[] = {
+ [0] = {
+ .name = "eth2 irq",
+ .start = MV64x60_IRQ_ETH_2,
+ .end = MV64x60_IRQ_ETH_2,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct mv643xx_eth_platform_data eth2_pd;
+
+static struct platform_device eth2_device = {
+ .name = MV643XX_ETH_NAME,
+ .id = 2,
+ .num_resources = ARRAY_SIZE(mv64x60_eth2_resources),
+ .resource = mv64x60_eth2_resources,
+ .dev = {
+ .platform_data = ð2_pd,
+ },
+};
+#endif
+#endif
+
+#ifdef CONFIG_I2C_MV64XXX
+static struct mv64xxx_i2c_pdata mv64xxx_i2c_pdata = {
+ .freq_m = 8,
+ .freq_n = 3,
+ .timeout = 1000, /* Default timeout of 1 second */
+ .retries = 1,
+};
+
+static struct resource mv64xxx_i2c_resources[] = {
+ /* Do not change the order of the IORESOURCE_MEM resources */
+ [0] = {
+ .name = "mv64xxx i2c base",
+ .start = MV64XXX_I2C_OFFSET,
+ .end = MV64XXX_I2C_OFFSET + MV64XXX_I2C_REG_BLOCK_SIZE - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .name = "mv64xxx i2c irq",
+ .start = MV64x60_IRQ_I2C,
+ .end = MV64x60_IRQ_I2C,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device i2c_device = {
+ .name = MV64XXX_I2C_CTLR_NAME,
+ .id = 0,
+ .num_resources = ARRAY_SIZE(mv64xxx_i2c_resources),
+ .resource = mv64xxx_i2c_resources,
+ .dev = {
+ .platform_data = &mv64xxx_i2c_pdata,
+ },
+};
+#endif
+
+static struct platform_device *mv64x60_pd_devs[] __initdata = {
+#ifdef CONFIG_SERIAL_MPSC
+ &mpsc_shared_device,
+ &mpsc0_device,
+ &mpsc1_device,
+#endif
+#ifdef CONFIG_MV643XX_ETH
+ &mv64x60_eth_shared_device,
+#endif
+#ifdef CONFIG_MV643XX_ETH_0
+ ð0_device,
+#endif
+#ifdef CONFIG_MV643XX_ETH_1
+ ð1_device,
+#endif
+#ifdef CONFIG_MV643XX_ETH_2
+ ð2_device,
+#endif
+#ifdef CONFIG_I2C_MV64XXX
+ &i2c_device,
+#endif
+};
+
+/*
+ *****************************************************************************
+ *
+ * Bridge Initialization Routines
+ *
+ *****************************************************************************
+ */
+/*
+ * mv64x60_init()
+ *
+ * Initialze the bridge based on setting passed in via 'si'. The bridge
+ * handle, 'bh', will be set so that it can be used to make subsequent
+ * calls to routines in this file.
+ */
+int __init
+mv64x60_init(struct mv64x60_handle *bh, struct mv64x60_setup_info *si)
+{
+ u32 mem_windows[MV64x60_CPU2MEM_WINDOWS][2];
+
+ if (ppc_md.progress)
+ ppc_md.progress("mv64x60 initialization", 0x0);
+
+ spin_lock_init(&mv64x60_lock);
+ mv64x60_early_init(bh, si);
+
+ if (mv64x60_get_type(bh) || mv64x60_setup_for_chip(bh)) {
+ iounmap(bh->v_base);
+ bh->v_base = 0;
+ if (ppc_md.progress)
+ ppc_md.progress("mv64x60_init: Can't determine chip",0);
+ return -1;
+ }
+
+ bh->ci->disable_all_windows(bh, si);
+ mv64x60_get_mem_windows(bh, mem_windows);
+ mv64x60_config_cpu2mem_windows(bh, si, mem_windows);
+
+ if (bh->ci->config_io2mem_windows)
+ bh->ci->config_io2mem_windows(bh, si, mem_windows);
+ if (bh->ci->set_mpsc2regs_window)
+ bh->ci->set_mpsc2regs_window(bh, si->phys_reg_base);
+
+ if (si->pci_1.enable_bus) {
+ bh->io_base_b = (u32)ioremap(si->pci_1.pci_io.cpu_base,
+ si->pci_1.pci_io.size);
+ isa_io_base = bh->io_base_b;
+ }
+
+ if (si->pci_0.enable_bus) {
+ bh->io_base_a = (u32)ioremap(si->pci_0.pci_io.cpu_base,
+ si->pci_0.pci_io.size);
+ isa_io_base = bh->io_base_a;
+
+ mv64x60_alloc_hose(bh, MV64x60_PCI0_CONFIG_ADDR,
+ MV64x60_PCI0_CONFIG_DATA, &bh->hose_a);
+ mv64x60_config_resources(bh->hose_a, &si->pci_0, bh->io_base_a);
+ mv64x60_config_pci_params(bh->hose_a, &si->pci_0);
+
+ mv64x60_config_cpu2pci_windows(bh, &si->pci_0, 0);
+ mv64x60_config_pci2mem_windows(bh, bh->hose_a, &si->pci_0, 0,
+ mem_windows);
+ bh->ci->set_pci2regs_window(bh, bh->hose_a, 0,
+ si->phys_reg_base);
+ }
+
+ if (si->pci_1.enable_bus) {
+ mv64x60_alloc_hose(bh, MV64x60_PCI1_CONFIG_ADDR,
+ MV64x60_PCI1_CONFIG_DATA, &bh->hose_b);
+ mv64x60_config_resources(bh->hose_b, &si->pci_1, bh->io_base_b);
+ mv64x60_config_pci_params(bh->hose_b, &si->pci_1);
+
+ mv64x60_config_cpu2pci_windows(bh, &si->pci_1, 1);
+ mv64x60_config_pci2mem_windows(bh, bh->hose_b, &si->pci_1, 1,
+ mem_windows);
+ bh->ci->set_pci2regs_window(bh, bh->hose_b, 1,
+ si->phys_reg_base);
+ }
+
+ bh->ci->chip_specific_init(bh, si);
+ mv64x60_pd_fixup(bh, mv64x60_pd_devs, ARRAY_SIZE(mv64x60_pd_devs));
+
+ return 0;
+}
+
+/*
+ * mv64x60_early_init()
+ *
+ * Do some bridge work that must take place before we start messing with
+ * the bridge for real.
+ */
+void __init
+mv64x60_early_init(struct mv64x60_handle *bh, struct mv64x60_setup_info *si)
+{
+ struct pci_controller hose_a, hose_b;
+
+ memset(bh, 0, sizeof(*bh));
+
+ bh->p_base = si->phys_reg_base;
+ bh->v_base = ioremap(bh->p_base, MV64x60_INTERNAL_SPACE_SIZE);
+
+ mv64x60_bridge_pbase = bh->p_base;
+ mv64x60_bridge_vbase = bh->v_base;
+
+ /* Assuming pci mode [reserved] bits 4:5 on 64260 are 0 */
+ bh->pci_mode_a = mv64x60_read(bh, MV64x60_PCI0_MODE) &
+ MV64x60_PCIMODE_MASK;
+ bh->pci_mode_b = mv64x60_read(bh, MV64x60_PCI1_MODE) &
+ MV64x60_PCIMODE_MASK;
+
+ /* Need temporary hose structs to call mv64x60_set_bus() */
+ memset(&hose_a, 0, sizeof(hose_a));
+ memset(&hose_b, 0, sizeof(hose_b));
+ setup_indirect_pci_nomap(&hose_a, bh->v_base + MV64x60_PCI0_CONFIG_ADDR,
+ bh->v_base + MV64x60_PCI0_CONFIG_DATA);
+ setup_indirect_pci_nomap(&hose_b, bh->v_base + MV64x60_PCI1_CONFIG_ADDR,
+ bh->v_base + MV64x60_PCI1_CONFIG_DATA);
+ bh->hose_a = &hose_a;
+ bh->hose_b = &hose_b;
+
+ mv64x60_set_bus(bh, 0, 0);
+ mv64x60_set_bus(bh, 1, 0);
+
+ bh->hose_a = NULL;
+ bh->hose_b = NULL;
+
+ /* Clear bit 0 of PCI addr decode control so PCI->CPU remap 1:1 */
+ mv64x60_clr_bits(bh, MV64x60_PCI0_PCI_DECODE_CNTL, 0x00000001);
+ mv64x60_clr_bits(bh, MV64x60_PCI1_PCI_DECODE_CNTL, 0x00000001);
+
+ /* Bit 12 MUST be 0; set bit 27--don't auto-update cpu remap regs */
+ mv64x60_clr_bits(bh, MV64x60_CPU_CONFIG, (1<<12));
+ mv64x60_set_bits(bh, MV64x60_CPU_CONFIG, (1<<27));
+
+ mv64x60_set_bits(bh, MV64x60_PCI0_TO_RETRY, 0xffff);
+ mv64x60_set_bits(bh, MV64x60_PCI1_TO_RETRY, 0xffff);
+
+ return;
+}
+
+/*
+ *****************************************************************************
+ *
+ * Window Config Routines
+ *
+ *****************************************************************************
+ */
+/*
+ * mv64x60_get_32bit_window()
+ *
+ * Determine the base address and size of a 32-bit window on the bridge.
+ */
+void __init
+mv64x60_get_32bit_window(struct mv64x60_handle *bh, u32 window,
+ u32 *base, u32 *size)
+{
+ u32 val, base_reg, size_reg, base_bits, size_bits;
+ u32 (*get_from_field)(u32 val, u32 num_bits);
+
+ base_reg = bh->ci->window_tab_32bit[window].base_reg;
+
+ if (base_reg != 0) {
+ size_reg = bh->ci->window_tab_32bit[window].size_reg;
+ base_bits = bh->ci->window_tab_32bit[window].base_bits;
+ size_bits = bh->ci->window_tab_32bit[window].size_bits;
+ get_from_field= bh->ci->window_tab_32bit[window].get_from_field;
+
+ val = mv64x60_read(bh, base_reg);
+ *base = get_from_field(val, base_bits);
+
+ if (size_reg != 0) {
+ val = mv64x60_read(bh, size_reg);
+ val = get_from_field(val, size_bits);
+ *size = bh->ci->untranslate_size(*base, val, size_bits);
+ }
+ else
+ *size = 0;
+ }
+ else {
+ *base = 0;
+ *size = 0;
+ }
+
+ pr_debug("get 32bit window: %d, base: 0x%x, size: 0x%x\n",
+ window, *base, *size);
+
+ return;
+}
+
+/*
+ * mv64x60_set_32bit_window()
+ *
+ * Set the base address and size of a 32-bit window on the bridge.
+ */
+void __init
+mv64x60_set_32bit_window(struct mv64x60_handle *bh, u32 window,
+ u32 base, u32 size, u32 other_bits)
+{
+ u32 val, base_reg, size_reg, base_bits, size_bits;
+ u32 (*map_to_field)(u32 val, u32 num_bits);
+
+ pr_debug("set 32bit window: %d, base: 0x%x, size: 0x%x, other: 0x%x\n",
+ window, base, size, other_bits);
+
+ base_reg = bh->ci->window_tab_32bit[window].base_reg;
+
+ if (base_reg != 0) {
+ size_reg = bh->ci->window_tab_32bit[window].size_reg;
+ base_bits = bh->ci->window_tab_32bit[window].base_bits;
+ size_bits = bh->ci->window_tab_32bit[window].size_bits;
+ map_to_field = bh->ci->window_tab_32bit[window].map_to_field;
+
+ val = map_to_field(base, base_bits) | other_bits;
+ mv64x60_write(bh, base_reg, val);
+
+ if (size_reg != 0) {
+ val = bh->ci->translate_size(base, size, size_bits);
+ val = map_to_field(val, size_bits);
+ mv64x60_write(bh, size_reg, val);
+ }
+
+ (void)mv64x60_read(bh, base_reg); /* Flush FIFO */
+ }
+
+ return;
+}
+
+/*
+ * mv64x60_get_64bit_window()
+ *
+ * Determine the base address and size of a 64-bit window on the bridge.
+ */
+void __init
+mv64x60_get_64bit_window(struct mv64x60_handle *bh, u32 window,
+ u32 *base_hi, u32 *base_lo, u32 *size)
+{
+ u32 val, base_lo_reg, size_reg, base_lo_bits, size_bits;
+ u32 (*get_from_field)(u32 val, u32 num_bits);
+
+ base_lo_reg = bh->ci->window_tab_64bit[window].base_lo_reg;
+
+ if (base_lo_reg != 0) {
+ size_reg = bh->ci->window_tab_64bit[window].size_reg;
+ base_lo_bits = bh->ci->window_tab_64bit[window].base_lo_bits;
+ size_bits = bh->ci->window_tab_64bit[window].size_bits;
+ get_from_field= bh->ci->window_tab_64bit[window].get_from_field;
+
+ *base_hi = mv64x60_read(bh,
+ bh->ci->window_tab_64bit[window].base_hi_reg);
+
+ val = mv64x60_read(bh, base_lo_reg);
+ *base_lo = get_from_field(val, base_lo_bits);
+
+ if (size_reg != 0) {
+ val = mv64x60_read(bh, size_reg);
+ val = get_from_field(val, size_bits);
+ *size = bh->ci->untranslate_size(*base_lo, val,
+ size_bits);
+ }
+ else
+ *size = 0;
+ }
+ else {
+ *base_hi = 0;
+ *base_lo = 0;
+ *size = 0;
+ }
+
+ pr_debug("get 64bit window: %d, base hi: 0x%x, base lo: 0x%x, "
+ "size: 0x%x\n", window, *base_hi, *base_lo, *size);
+
+ return;
+}
+
+/*
+ * mv64x60_set_64bit_window()
+ *
+ * Set the base address and size of a 64-bit window on the bridge.
+ */
+void __init
+mv64x60_set_64bit_window(struct mv64x60_handle *bh, u32 window,
+ u32 base_hi, u32 base_lo, u32 size, u32 other_bits)
+{
+ u32 val, base_lo_reg, size_reg, base_lo_bits, size_bits;
+ u32 (*map_to_field)(u32 val, u32 num_bits);
+
+ pr_debug("set 64bit window: %d, base hi: 0x%x, base lo: 0x%x, "
+ "size: 0x%x, other: 0x%x\n",
+ window, base_hi, base_lo, size, other_bits);
+
+ base_lo_reg = bh->ci->window_tab_64bit[window].base_lo_reg;
+
+ if (base_lo_reg != 0) {
+ size_reg = bh->ci->window_tab_64bit[window].size_reg;
+ base_lo_bits = bh->ci->window_tab_64bit[window].base_lo_bits;
+ size_bits = bh->ci->window_tab_64bit[window].size_bits;
+ map_to_field = bh->ci->window_tab_64bit[window].map_to_field;
+
+ mv64x60_write(bh, bh->ci->window_tab_64bit[window].base_hi_reg,
+ base_hi);
+
+ val = map_to_field(base_lo, base_lo_bits) | other_bits;
+ mv64x60_write(bh, base_lo_reg, val);
+
+ if (size_reg != 0) {
+ val = bh->ci->translate_size(base_lo, size, size_bits);
+ val = map_to_field(val, size_bits);
+ mv64x60_write(bh, size_reg, val);
+ }
+
+ (void)mv64x60_read(bh, base_lo_reg); /* Flush FIFO */
+ }
+
+ return;
+}
+
+/*
+ * mv64x60_mask()
+ *
+ * Take the high-order 'num_bits' of 'val' & mask off low bits.
+ */
+u32 __init
+mv64x60_mask(u32 val, u32 num_bits)
+{
+ return val & (0xffffffff << (32 - num_bits));
+}
+
+/*
+ * mv64x60_shift_left()
+ *
+ * Take the low-order 'num_bits' of 'val', shift left to align at bit 31 (MSB).
+ */
+u32 __init
+mv64x60_shift_left(u32 val, u32 num_bits)
+{
+ return val << (32 - num_bits);
+}
+
+/*
+ * mv64x60_shift_right()
+ *
+ * Take the high-order 'num_bits' of 'val', shift right to align at bit 0 (LSB).
+ */
+u32 __init
+mv64x60_shift_right(u32 val, u32 num_bits)
+{
+ return val >> (32 - num_bits);
+}
+
+/*
+ *****************************************************************************
+ *
+ * Chip Identification Routines
+ *
+ *****************************************************************************
+ */
+/*
+ * mv64x60_get_type()
+ *
+ * Determine the type of bridge chip we have.
+ */
+int __init
+mv64x60_get_type(struct mv64x60_handle *bh)
+{
+ struct pci_controller hose;
+ u16 val;
+ u8 save_exclude;
+
+ memset(&hose, 0, sizeof(hose));
+ setup_indirect_pci_nomap(&hose, bh->v_base + MV64x60_PCI0_CONFIG_ADDR,
+ bh->v_base + MV64x60_PCI0_CONFIG_DATA);
+
+ save_exclude = mv64x60_pci_exclude_bridge;
+ mv64x60_pci_exclude_bridge = 0;
+ /* Sanity check of bridge's Vendor ID */
+ early_read_config_word(&hose, 0, PCI_DEVFN(0, 0), PCI_VENDOR_ID, &val);
+
+ if (val != PCI_VENDOR_ID_MARVELL) {
+ mv64x60_pci_exclude_bridge = save_exclude;
+ return -1;
+ }
+
+ /* Get the revision of the chip */
+ early_read_config_word(&hose, 0, PCI_DEVFN(0, 0), PCI_CLASS_REVISION,
+ &val);
+ bh->rev = (u32)(val & 0xff);
+
+ /* Figure out the type of Marvell bridge it is */
+ early_read_config_word(&hose, 0, PCI_DEVFN(0, 0), PCI_DEVICE_ID, &val);
+ mv64x60_pci_exclude_bridge = save_exclude;
+
+ switch (val) {
+ case PCI_DEVICE_ID_MARVELL_GT64260:
+ switch (bh->rev) {
+ case GT64260_REV_A:
+ bh->type = MV64x60_TYPE_GT64260A;
+ break;
+
+ default:
+ printk(KERN_WARNING "Unsupported GT64260 rev %04x\n",
+ bh->rev);
+ /* Assume its similar to a 'B' rev and fallthru */
+ case GT64260_REV_B:
+ bh->type = MV64x60_TYPE_GT64260B;
+ break;
+ }
+ break;
+
+ case PCI_DEVICE_ID_MARVELL_MV64360:
+ /* Marvell won't tell me how to distinguish a 64361 & 64362 */
+ bh->type = MV64x60_TYPE_MV64360;
+ break;
+
+ case PCI_DEVICE_ID_MARVELL_MV64460:
+ bh->type = MV64x60_TYPE_MV64460;
+ break;
+
+ default:
+ printk(KERN_ERR "Unknown Marvell bridge type %04x\n", val);
+ return -1;
+ }
+
+ /* Hang onto bridge type & rev for PIC code */
+ mv64x60_bridge_type = bh->type;
+ mv64x60_bridge_rev = bh->rev;
+
+ return 0;
+}
+
+/*
+ * mv64x60_setup_for_chip()
+ *
+ * Set 'bh' to use the proper set of routine for the bridge chip that we have.
+ */
+int __init
+mv64x60_setup_for_chip(struct mv64x60_handle *bh)
+{
+ int rc = 0;
+
+ /* Set up chip-specific info based on the chip/bridge type */
+ switch(bh->type) {
+ case MV64x60_TYPE_GT64260A:
+ bh->ci = >64260a_ci;
+ break;
+
+ case MV64x60_TYPE_GT64260B:
+ bh->ci = >64260b_ci;
+ break;
+
+ case MV64x60_TYPE_MV64360:
+ bh->ci = &mv64360_ci;
+ break;
+
+ case MV64x60_TYPE_MV64460:
+ bh->ci = &mv64460_ci;
+ break;
+
+ case MV64x60_TYPE_INVALID:
+ default:
+ if (ppc_md.progress)
+ ppc_md.progress("mv64x60: Unsupported bridge", 0x0);
+ printk(KERN_ERR "mv64x60: Unsupported bridge\n");
+ rc = -1;
+ }
+
+ return rc;
+}
+
+/*
+ * mv64x60_get_bridge_vbase()
+ *
+ * Return the virtual address of the bridge's registers.
+ */
+void *
+mv64x60_get_bridge_vbase(void)
+{
+ return mv64x60_bridge_vbase;
+}
+
+/*
+ * mv64x60_get_bridge_type()
+ *
+ * Return the type of bridge on the platform.
+ */
+u32
+mv64x60_get_bridge_type(void)
+{
+ return mv64x60_bridge_type;
+}
+
+/*
+ * mv64x60_get_bridge_rev()
+ *
+ * Return the revision of the bridge on the platform.
+ */
+u32
+mv64x60_get_bridge_rev(void)
+{
+ return mv64x60_bridge_rev;
+}
+
+/*
+ *****************************************************************************
+ *
+ * System Memory Window Related Routines
+ *
+ *****************************************************************************
+ */
+/*
+ * mv64x60_get_mem_size()
+ *
+ * Calculate the amount of memory that the memory controller is set up for.
+ * This should only be used by board-specific code if there is no other
+ * way to determine the amount of memory in the system.
+ */
+u32 __init
+mv64x60_get_mem_size(u32 bridge_base, u32 chip_type)
+{
+ struct mv64x60_handle bh;
+ u32 mem_windows[MV64x60_CPU2MEM_WINDOWS][2];
+ u32 rc = 0;
+
+ memset(&bh, 0, sizeof(bh));
+
+ bh.type = chip_type;
+ bh.v_base = (void *)bridge_base;
+
+ if (!mv64x60_setup_for_chip(&bh)) {
+ mv64x60_get_mem_windows(&bh, mem_windows);
+ rc = mv64x60_calc_mem_size(&bh, mem_windows);
+ }
+
+ return rc;
+}
+
+/*
+ * mv64x60_get_mem_windows()
+ *
+ * Get the values in the memory controller & return in the 'mem_windows' array.
+ */
+void __init
+mv64x60_get_mem_windows(struct mv64x60_handle *bh,
+ u32 mem_windows[MV64x60_CPU2MEM_WINDOWS][2])
+{
+ u32 i, win;
+
+ for (win=MV64x60_CPU2MEM_0_WIN,i=0;win<=MV64x60_CPU2MEM_3_WIN;win++,i++)
+ if (bh->ci->is_enabled_32bit(bh, win))
+ mv64x60_get_32bit_window(bh, win,
+ &mem_windows[i][0], &mem_windows[i][1]);
+ else {
+ mem_windows[i][0] = 0;
+ mem_windows[i][1] = 0;
+ }
+
+ return;
+}
+
+/*
+ * mv64x60_calc_mem_size()
+ *
+ * Using the memory controller register values in 'mem_windows', determine
+ * how much memory it is set up for.
+ */
+u32 __init
+mv64x60_calc_mem_size(struct mv64x60_handle *bh,
+ u32 mem_windows[MV64x60_CPU2MEM_WINDOWS][2])
+{
+ u32 i, total = 0;
+
+ for (i=0; i<MV64x60_CPU2MEM_WINDOWS; i++)
+ total += mem_windows[i][1];
+
+ return total;
+}
+
+/*
+ *****************************************************************************
+ *
+ * CPU->System MEM, PCI Config Routines
+ *
+ *****************************************************************************
+ */
+/*
+ * mv64x60_config_cpu2mem_windows()
+ *
+ * Configure CPU->Memory windows on the bridge.
+ */
+static u32 prot_tab[] __initdata = {
+ MV64x60_CPU_PROT_0_WIN, MV64x60_CPU_PROT_1_WIN,
+ MV64x60_CPU_PROT_2_WIN, MV64x60_CPU_PROT_3_WIN
+};
+
+static u32 cpu_snoop_tab[] __initdata = {
+ MV64x60_CPU_SNOOP_0_WIN, MV64x60_CPU_SNOOP_1_WIN,
+ MV64x60_CPU_SNOOP_2_WIN, MV64x60_CPU_SNOOP_3_WIN
+};
+
+void __init
+mv64x60_config_cpu2mem_windows(struct mv64x60_handle *bh,
+ struct mv64x60_setup_info *si,
+ u32 mem_windows[MV64x60_CPU2MEM_WINDOWS][2])
+{
+ u32 i, win;
+
+ /* Set CPU protection & snoop windows */
+ for (win=MV64x60_CPU2MEM_0_WIN,i=0;win<=MV64x60_CPU2MEM_3_WIN;win++,i++)
+ if (bh->ci->is_enabled_32bit(bh, win)) {
+ mv64x60_set_32bit_window(bh, prot_tab[i],
+ mem_windows[i][0], mem_windows[i][1],
+ si->cpu_prot_options[i]);
+ bh->ci->enable_window_32bit(bh, prot_tab[i]);
+
+ if (bh->ci->window_tab_32bit[cpu_snoop_tab[i]].
+ base_reg != 0) {
+ mv64x60_set_32bit_window(bh, cpu_snoop_tab[i],
+ mem_windows[i][0], mem_windows[i][1],
+ si->cpu_snoop_options[i]);
+ bh->ci->enable_window_32bit(bh,
+ cpu_snoop_tab[i]);
+ }
+
+ }
+
+ return;
+}
+
+/*
+ * mv64x60_config_cpu2pci_windows()
+ *
+ * Configure the CPU->PCI windows for one of the PCI buses.
+ */
+static u32 win_tab[2][4] __initdata = {
+ { MV64x60_CPU2PCI0_IO_WIN, MV64x60_CPU2PCI0_MEM_0_WIN,
+ MV64x60_CPU2PCI0_MEM_1_WIN, MV64x60_CPU2PCI0_MEM_2_WIN },
+ { MV64x60_CPU2PCI1_IO_WIN, MV64x60_CPU2PCI1_MEM_0_WIN,
+ MV64x60_CPU2PCI1_MEM_1_WIN, MV64x60_CPU2PCI1_MEM_2_WIN },
+};
+
+static u32 remap_tab[2][4] __initdata = {
+ { MV64x60_CPU2PCI0_IO_REMAP_WIN, MV64x60_CPU2PCI0_MEM_0_REMAP_WIN,
+ MV64x60_CPU2PCI0_MEM_1_REMAP_WIN, MV64x60_CPU2PCI0_MEM_2_REMAP_WIN },
+ { MV64x60_CPU2PCI1_IO_REMAP_WIN, MV64x60_CPU2PCI1_MEM_0_REMAP_WIN,
+ MV64x60_CPU2PCI1_MEM_1_REMAP_WIN, MV64x60_CPU2PCI1_MEM_2_REMAP_WIN }
+};
+
+void __init
+mv64x60_config_cpu2pci_windows(struct mv64x60_handle *bh,
+ struct mv64x60_pci_info *pi, u32 bus)
+{
+ int i;
+
+ if (pi->pci_io.size > 0) {
+ mv64x60_set_32bit_window(bh, win_tab[bus][0],
+ pi->pci_io.cpu_base, pi->pci_io.size, pi->pci_io.swap);
+ mv64x60_set_32bit_window(bh, remap_tab[bus][0],
+ pi->pci_io.pci_base_lo, 0, 0);
+ bh->ci->enable_window_32bit(bh, win_tab[bus][0]);
+ }
+ else /* Actually, the window should already be disabled */
+ bh->ci->disable_window_32bit(bh, win_tab[bus][0]);
+
+ for (i=0; i<3; i++)
+ if (pi->pci_mem[i].size > 0) {
+ mv64x60_set_32bit_window(bh, win_tab[bus][i+1],
+ pi->pci_mem[i].cpu_base, pi->pci_mem[i].size,
+ pi->pci_mem[i].swap);
+ mv64x60_set_64bit_window(bh, remap_tab[bus][i+1],
+ pi->pci_mem[i].pci_base_hi,
+ pi->pci_mem[i].pci_base_lo, 0, 0);
+ bh->ci->enable_window_32bit(bh, win_tab[bus][i+1]);
+ }
+ else /* Actually, the window should already be disabled */
+ bh->ci->disable_window_32bit(bh, win_tab[bus][i+1]);
+
+ return;
+}
+
+/*
+ *****************************************************************************
+ *
+ * PCI->System MEM Config Routines
+ *
+ *****************************************************************************
+ */
+/*
+ * mv64x60_config_pci2mem_windows()
+ *
+ * Configure the PCI->Memory windows on the bridge.
+ */
+static u32 pci_acc_tab[2][4] __initdata = {
+ { MV64x60_PCI02MEM_ACC_CNTL_0_WIN, MV64x60_PCI02MEM_ACC_CNTL_1_WIN,
+ MV64x60_PCI02MEM_ACC_CNTL_2_WIN, MV64x60_PCI02MEM_ACC_CNTL_3_WIN },
+ { MV64x60_PCI12MEM_ACC_CNTL_0_WIN, MV64x60_PCI12MEM_ACC_CNTL_1_WIN,
+ MV64x60_PCI12MEM_ACC_CNTL_2_WIN, MV64x60_PCI12MEM_ACC_CNTL_3_WIN }
+};
+
+static u32 pci_snoop_tab[2][4] __initdata = {
+ { MV64x60_PCI02MEM_SNOOP_0_WIN, MV64x60_PCI02MEM_SNOOP_1_WIN,
+ MV64x60_PCI02MEM_SNOOP_2_WIN, MV64x60_PCI02MEM_SNOOP_3_WIN },
+ { MV64x60_PCI12MEM_SNOOP_0_WIN, MV64x60_PCI12MEM_SNOOP_1_WIN,
+ MV64x60_PCI12MEM_SNOOP_2_WIN, MV64x60_PCI12MEM_SNOOP_3_WIN }
+};
+
+static u32 pci_size_tab[2][4] __initdata = {
+ { MV64x60_PCI0_MEM_0_SIZE, MV64x60_PCI0_MEM_1_SIZE,
+ MV64x60_PCI0_MEM_2_SIZE, MV64x60_PCI0_MEM_3_SIZE },
+ { MV64x60_PCI1_MEM_0_SIZE, MV64x60_PCI1_MEM_1_SIZE,
+ MV64x60_PCI1_MEM_2_SIZE, MV64x60_PCI1_MEM_3_SIZE }
+};
+
+void __init
+mv64x60_config_pci2mem_windows(struct mv64x60_handle *bh,
+ struct pci_controller *hose, struct mv64x60_pci_info *pi,
+ u32 bus, u32 mem_windows[MV64x60_CPU2MEM_WINDOWS][2])
+{
+ u32 i, win;
+
+ /*
+ * Set the access control, snoop, BAR size, and window base addresses.
+ * PCI->MEM windows base addresses will match exactly what the
+ * CPU->MEM windows are.
+ */
+ for (win=MV64x60_CPU2MEM_0_WIN,i=0;win<=MV64x60_CPU2MEM_3_WIN;win++,i++)
+ if (bh->ci->is_enabled_32bit(bh, win)) {
+ mv64x60_set_64bit_window(bh,
+ pci_acc_tab[bus][i], 0,
+ mem_windows[i][0], mem_windows[i][1],
+ pi->acc_cntl_options[i]);
+ bh->ci->enable_window_64bit(bh, pci_acc_tab[bus][i]);
+
+ if (bh->ci->window_tab_64bit[
+ pci_snoop_tab[bus][i]].base_lo_reg != 0) {
+
+ mv64x60_set_64bit_window(bh,
+ pci_snoop_tab[bus][i], 0,
+ mem_windows[i][0], mem_windows[i][1],
+ pi->snoop_options[i]);
+ bh->ci->enable_window_64bit(bh,
+ pci_snoop_tab[bus][i]);
+ }
+
+ bh->ci->set_pci2mem_window(hose, bus, i,
+ mem_windows[i][0]);
+ mv64x60_write(bh, pci_size_tab[bus][i],
+ mv64x60_mask(mem_windows[i][1] - 1, 20));
+
+ /* Enable the window */
+ mv64x60_clr_bits(bh, ((bus == 0) ?
+ MV64x60_PCI0_BAR_ENABLE :
+ MV64x60_PCI1_BAR_ENABLE), (1 << i));
+ }
+
+ return;
+}
+
+/*
+ *****************************************************************************
+ *
+ * Hose & Resource Alloc/Init Routines
+ *
+ *****************************************************************************
+ */
+/*
+ * mv64x60_alloc_hoses()
+ *
+ * Allocate the PCI hose structures for the bridge's PCI buses.
+ */
+void __init
+mv64x60_alloc_hose(struct mv64x60_handle *bh, u32 cfg_addr, u32 cfg_data,
+ struct pci_controller **hose)
+{
+ *hose = pcibios_alloc_controller();
+ setup_indirect_pci_nomap(*hose, bh->v_base + cfg_addr,
+ bh->v_base + cfg_data);
+ return;
+}
+
+/*
+ * mv64x60_config_resources()
+ *
+ * Calculate the offsets, etc. for the hose structures to reflect all of
+ * the address remapping that happens as you go from CPU->PCI and PCI->MEM.
+ */
+void __init
+mv64x60_config_resources(struct pci_controller *hose,
+ struct mv64x60_pci_info *pi, u32 io_base)
+{
+ int i;
+ /* 2 hoses; 4 resources/hose; string <= 64 bytes */
+ static char s[2][4][64];
+
+ if (pi->pci_io.size != 0) {
+ sprintf(s[hose->index][0], "PCI hose %d I/O Space",
+ hose->index);
+ pci_init_resource(&hose->io_resource, io_base - isa_io_base,
+ io_base - isa_io_base + pi->pci_io.size - 1,
+ IORESOURCE_IO, s[hose->index][0]);
+ hose->io_space.start = pi->pci_io.pci_base_lo;
+ hose->io_space.end = pi->pci_io.pci_base_lo + pi->pci_io.size-1;
+ hose->io_base_phys = pi->pci_io.cpu_base;
+ hose->io_base_virt = (void *)isa_io_base;
+ }
+
+ for (i=0; i<3; i++)
+ if (pi->pci_mem[i].size != 0) {
+ sprintf(s[hose->index][i+1], "PCI hose %d MEM Space %d",
+ hose->index, i);
+ pci_init_resource(&hose->mem_resources[i],
+ pi->pci_mem[i].cpu_base,
+ pi->pci_mem[i].cpu_base + pi->pci_mem[i].size-1,
+ IORESOURCE_MEM, s[hose->index][i+1]);
+ }
+
+ hose->mem_space.end = pi->pci_mem[0].pci_base_lo +
+ pi->pci_mem[0].size - 1;
+ hose->pci_mem_offset = pi->pci_mem[0].cpu_base -
+ pi->pci_mem[0].pci_base_lo;
+ return;
+}
+
+/*
+ * mv64x60_config_pci_params()
+ *
+ * Configure a hose's PCI config space parameters.
+ */
+void __init
+mv64x60_config_pci_params(struct pci_controller *hose,
+ struct mv64x60_pci_info *pi)
+{
+ u32 devfn;
+ u16 u16_val;
+ u8 save_exclude;
+
+ devfn = PCI_DEVFN(0,0);
+
+ save_exclude = mv64x60_pci_exclude_bridge;
+ mv64x60_pci_exclude_bridge = 0;
+
+ /* Set class code to indicate host bridge */
+ u16_val = PCI_CLASS_BRIDGE_HOST; /* 0x0600 (host bridge) */
+ early_write_config_word(hose, 0, devfn, PCI_CLASS_DEVICE, u16_val);
+
+ /* Enable bridge to be PCI master & respond to PCI MEM cycles */
+ early_read_config_word(hose, 0, devfn, PCI_COMMAND, &u16_val);
+ u16_val &= ~(PCI_COMMAND_IO | PCI_COMMAND_INVALIDATE |
+ PCI_COMMAND_PARITY | PCI_COMMAND_SERR | PCI_COMMAND_FAST_BACK);
+ u16_val |= pi->pci_cmd_bits | PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY;
+ early_write_config_word(hose, 0, devfn, PCI_COMMAND, u16_val);
+
+ /* Set latency timer, cache line size, clear BIST */
+ u16_val = (pi->latency_timer << 8) | (L1_CACHE_LINE_SIZE >> 2);
+ early_write_config_word(hose, 0, devfn, PCI_CACHE_LINE_SIZE, u16_val);
+
+ mv64x60_pci_exclude_bridge = save_exclude;
+ return;
+}
+
+/*
+ *****************************************************************************
+ *
+ * PCI Related Routine
+ *
+ *****************************************************************************
+ */
+/*
+ * mv64x60_set_bus()
+ *
+ * Set the bus number for the hose directly under the bridge.
+ */
+void __init
+mv64x60_set_bus(struct mv64x60_handle *bh, u32 bus, u32 child_bus)
+{
+ struct pci_controller *hose;
+ u32 pci_mode, p2p_cfg, pci_cfg_offset, val;
+ u8 save_exclude;
+
+ if (bus == 0) {
+ pci_mode = bh->pci_mode_a;
+ p2p_cfg = MV64x60_PCI0_P2P_CONFIG;
+ pci_cfg_offset = 0x64;
+ hose = bh->hose_a;
+ }
+ else {
+ pci_mode = bh->pci_mode_b;
+ p2p_cfg = MV64x60_PCI1_P2P_CONFIG;
+ pci_cfg_offset = 0xe4;
+ hose = bh->hose_b;
+ }
+
+ child_bus &= 0xff;
+ val = mv64x60_read(bh, p2p_cfg);
+
+ if (pci_mode == MV64x60_PCIMODE_CONVENTIONAL) {
+ val &= 0xe0000000; /* Force dev num to 0, turn off P2P bridge */
+ val |= (child_bus << 16) | 0xff;
+ mv64x60_write(bh, p2p_cfg, val);
+ (void)mv64x60_read(bh, p2p_cfg); /* Flush FIFO */
+ }
+ else { /* PCI-X */
+ /*
+ * Need to use the current bus/dev number (that's in the
+ * P2P CONFIG reg) to access the bridge's pci config space.
+ */
+ save_exclude = mv64x60_pci_exclude_bridge;
+ mv64x60_pci_exclude_bridge = 0;
+ early_write_config_dword(hose, (val & 0x00ff0000) >> 16,
+ PCI_DEVFN(((val & 0x1f000000) >> 24), 0),
+ pci_cfg_offset, child_bus << 8);
+ mv64x60_pci_exclude_bridge = save_exclude;
+ }
+
+ return;
+}
+
+/*
+ * mv64x60_pci_exclude_device()
+ *
+ * This routine is used to make the bridge not appear when the
+ * PCI subsystem is accessing PCI devices (in PCI config space).
+ */
+int
+mv64x60_pci_exclude_device(u8 bus, u8 devfn)
+{
+ struct pci_controller *hose;
+
+ hose = pci_bus_to_hose(bus);
+
+ /* Skip slot 0 on both hoses */
+ if ((mv64x60_pci_exclude_bridge == 1) && (PCI_SLOT(devfn) == 0) &&
+ (hose->first_busno == bus))
+
+ return PCIBIOS_DEVICE_NOT_FOUND;
+ else
+ return PCIBIOS_SUCCESSFUL;
+} /* mv64x60_pci_exclude_device() */
+
+/*
+ *****************************************************************************
+ *
+ * Platform Device Routines
+ *
+ *****************************************************************************
+ */
+
+/*
+ * mv64x60_pd_fixup()
+ *
+ * Need to add the base addr of where the bridge's regs are mapped in the
+ * physical addr space so drivers can ioremap() them.
+ */
+void __init
+mv64x60_pd_fixup(struct mv64x60_handle *bh, struct platform_device *pd_devs[],
+ u32 entries)
+{
+ struct resource *r;
+ u32 i, j;
+
+ for (i=0; i<entries; i++) {
+ j = 0;
+
+ while ((r = platform_get_resource(pd_devs[i],IORESOURCE_MEM,j))
+ != NULL) {
+
+ r->start += bh->p_base;
+ r->end += bh->p_base;
+ j++;
+ }
+ }
+
+ return;
+}
+
+/*
+ * mv64x60_add_pds()
+ *
+ * Add the mv64x60 platform devices to the list of platform devices.
+ */
+static int __init
+mv64x60_add_pds(void)
+{
+ return platform_add_devices(mv64x60_pd_devs,
+ ARRAY_SIZE(mv64x60_pd_devs));
+}
+arch_initcall(mv64x60_add_pds);
+
+/*
+ *****************************************************************************
+ *
+ * GT64260-Specific Routines
+ *
+ *****************************************************************************
+ */
+/*
+ * gt64260_translate_size()
+ *
+ * On the GT64260, the size register is really the "top" address of the window.
+ */
+static u32 __init
+gt64260_translate_size(u32 base, u32 size, u32 num_bits)
+{
+ return base + mv64x60_mask(size - 1, num_bits);
+}
+
+/*
+ * gt64260_untranslate_size()
+ *
+ * Translate the top address of a window into a window size.
+ */
+static u32 __init
+gt64260_untranslate_size(u32 base, u32 size, u32 num_bits)
+{
+ if (size >= base)
+ size = size - base + (1 << (32 - num_bits));
+ else
+ size = 0;
+
+ return size;
+}
+
+/*
+ * gt64260_set_pci2mem_window()
+ *
+ * The PCI->MEM window registers are actually in PCI config space so need
+ * to set them by setting the correct config space BARs.
+ */
+static u32 gt64260_reg_addrs[2][4] __initdata = {
+ { 0x10, 0x14, 0x18, 0x1c }, { 0x90, 0x94, 0x98, 0x9c }
+};
+
+static void __init
+gt64260_set_pci2mem_window(struct pci_controller *hose, u32 bus, u32 window,
+ u32 base)
+{
+ u8 save_exclude;
+
+ pr_debug("set pci->mem window: %d, hose: %d, base: 0x%x\n", window,
+ hose->index, base);
+
+ save_exclude = mv64x60_pci_exclude_bridge;
+ mv64x60_pci_exclude_bridge = 0;
+ early_write_config_dword(hose, 0, PCI_DEVFN(0, 0),
+ gt64260_reg_addrs[bus][window], mv64x60_mask(base, 20) | 0x8);
+ mv64x60_pci_exclude_bridge = save_exclude;
+
+ return;
+}
+
+/*
+ * gt64260_set_pci2regs_window()
+ *
+ * Set where the bridge's registers appear in PCI MEM space.
+ */
+static u32 gt64260_offset[2] __initdata = {0x20, 0xa0};
+
+static void __init
+gt64260_set_pci2regs_window(struct mv64x60_handle *bh,
+ struct pci_controller *hose, u32 bus, u32 base)
+{
+ u8 save_exclude;
+
+ pr_debug("set pci->internal regs hose: %d, base: 0x%x\n", hose->index,
+ base);
+
+ save_exclude = mv64x60_pci_exclude_bridge;
+ mv64x60_pci_exclude_bridge = 0;
+ early_write_config_dword(hose, 0, PCI_DEVFN(0,0), gt64260_offset[bus],
+ (base << 16));
+ mv64x60_pci_exclude_bridge = save_exclude;
+
+ return;
+}
+
+/*
+ * gt64260_is_enabled_32bit()
+ *
+ * On a GT64260, a window is enabled iff its top address is >= to its base
+ * address.
+ */
+static u32 __init
+gt64260_is_enabled_32bit(struct mv64x60_handle *bh, u32 window)
+{
+ u32 rc = 0;
+
+ if ((gt64260_32bit_windows[window].base_reg != 0) &&
+ (gt64260_32bit_windows[window].size_reg != 0) &&
+ ((mv64x60_read(bh, gt64260_32bit_windows[window].size_reg) &
+ ((1 << gt64260_32bit_windows[window].size_bits) - 1)) >=
+ (mv64x60_read(bh, gt64260_32bit_windows[window].base_reg) &
+ ((1 << gt64260_32bit_windows[window].base_bits) - 1))))
+
+ rc = 1;
+
+ return rc;
+}
+
+/*
+ * gt64260_enable_window_32bit()
+ *
+ * On the GT64260, a window is enabled iff the top address is >= to the base
+ * address of the window. Since the window has already been configured by
+ * the time this routine is called, we have nothing to do here.
+ */
+static void __init
+gt64260_enable_window_32bit(struct mv64x60_handle *bh, u32 window)
+{
+ pr_debug("enable 32bit window: %d\n", window);
+ return;
+}
+
+/*
+ * gt64260_disable_window_32bit()
+ *
+ * On a GT64260, you disable a window by setting its top address to be less
+ * than its base address.
+ */
+static void __init
+gt64260_disable_window_32bit(struct mv64x60_handle *bh, u32 window)
+{
+ pr_debug("disable 32bit window: %d, base_reg: 0x%x, size_reg: 0x%x\n",
+ window, gt64260_32bit_windows[window].base_reg,
+ gt64260_32bit_windows[window].size_reg);
+
+ if ((gt64260_32bit_windows[window].base_reg != 0) &&
+ (gt64260_32bit_windows[window].size_reg != 0)) {
+
+ /* To disable, make bottom reg higher than top reg */
+ mv64x60_write(bh, gt64260_32bit_windows[window].base_reg,0xfff);
+ mv64x60_write(bh, gt64260_32bit_windows[window].size_reg, 0);
+ }
+
+ return;
+}
+
+/*
+ * gt64260_enable_window_64bit()
+ *
+ * On the GT64260, a window is enabled iff the top address is >= to the base
+ * address of the window. Since the window has already been configured by
+ * the time this routine is called, we have nothing to do here.
+ */
+static void __init
+gt64260_enable_window_64bit(struct mv64x60_handle *bh, u32 window)
+{
+ pr_debug("enable 64bit window: %d\n", window);
+ return; /* Enabled when window configured (i.e., when top >= base) */
+}
+
+/*
+ * gt64260_disable_window_64bit()
+ *
+ * On a GT64260, you disable a window by setting its top address to be less
+ * than its base address.
+ */
+static void __init
+gt64260_disable_window_64bit(struct mv64x60_handle *bh, u32 window)
+{
+ pr_debug("disable 64bit window: %d, base_reg: 0x%x, size_reg: 0x%x\n",
+ window, gt64260_64bit_windows[window].base_lo_reg,
+ gt64260_64bit_windows[window].size_reg);
+
+ if ((gt64260_64bit_windows[window].base_lo_reg != 0) &&
+ (gt64260_64bit_windows[window].size_reg != 0)) {
+
+ /* To disable, make bottom reg higher than top reg */
+ mv64x60_write(bh, gt64260_64bit_windows[window].base_lo_reg,
+ 0xfff);
+ mv64x60_write(bh, gt64260_64bit_windows[window].base_hi_reg, 0);
+ mv64x60_write(bh, gt64260_64bit_windows[window].size_reg, 0);
+ }
+
+ return;
+}
+
+/*
+ * gt64260_disable_all_windows()
+ *
+ * The GT64260 has several windows that aren't represented in the table of
+ * windows at the top of this file. This routine turns all of them off
+ * except for the memory controller windows, of course.
+ */
+static void __init
+gt64260_disable_all_windows(struct mv64x60_handle *bh,
+ struct mv64x60_setup_info *si)
+{
+ u32 i, preserve;
+
+ /* Disable 32bit windows (don't disable cpu->mem windows) */
+ for (i=MV64x60_CPU2DEV_0_WIN; i<MV64x60_32BIT_WIN_COUNT; i++) {
+ if (i < 32)
+ preserve = si->window_preserve_mask_32_lo & (1 << i);
+ else
+ preserve = si->window_preserve_mask_32_hi & (1<<(i-32));
+
+ if (!preserve)
+ gt64260_disable_window_32bit(bh, i);
+ }
+
+ /* Disable 64bit windows */
+ for (i=0; i<MV64x60_64BIT_WIN_COUNT; i++)
+ if (!(si->window_preserve_mask_64 & (1<<i)))
+ gt64260_disable_window_64bit(bh, i);
+
+ /* Turn off cpu protection windows not in gt64260_32bit_windows[] */
+ mv64x60_write(bh, GT64260_CPU_PROT_BASE_4, 0xfff);
+ mv64x60_write(bh, GT64260_CPU_PROT_SIZE_4, 0);
+ mv64x60_write(bh, GT64260_CPU_PROT_BASE_5, 0xfff);
+ mv64x60_write(bh, GT64260_CPU_PROT_SIZE_5, 0);
+ mv64x60_write(bh, GT64260_CPU_PROT_BASE_6, 0xfff);
+ mv64x60_write(bh, GT64260_CPU_PROT_SIZE_6, 0);
+ mv64x60_write(bh, GT64260_CPU_PROT_BASE_7, 0xfff);
+ mv64x60_write(bh, GT64260_CPU_PROT_SIZE_7, 0);
+
+ /* Turn off PCI->MEM access cntl wins not in gt64260_64bit_windows[] */
+ mv64x60_write(bh, MV64x60_PCI0_ACC_CNTL_4_BASE_LO, 0xfff);
+ mv64x60_write(bh, MV64x60_PCI0_ACC_CNTL_4_BASE_HI, 0);
+ mv64x60_write(bh, MV64x60_PCI0_ACC_CNTL_4_SIZE, 0);
+ mv64x60_write(bh, MV64x60_PCI0_ACC_CNTL_5_BASE_LO, 0xfff);
+ mv64x60_write(bh, MV64x60_PCI0_ACC_CNTL_5_BASE_HI, 0);
+ mv64x60_write(bh, MV64x60_PCI0_ACC_CNTL_5_SIZE, 0);
+ mv64x60_write(bh, GT64260_PCI0_ACC_CNTL_6_BASE_LO, 0xfff);
+ mv64x60_write(bh, GT64260_PCI0_ACC_CNTL_6_BASE_HI, 0);
+ mv64x60_write(bh, GT64260_PCI0_ACC_CNTL_6_SIZE, 0);
+ mv64x60_write(bh, GT64260_PCI0_ACC_CNTL_7_BASE_LO, 0xfff);
+ mv64x60_write(bh, GT64260_PCI0_ACC_CNTL_7_BASE_HI, 0);
+ mv64x60_write(bh, GT64260_PCI0_ACC_CNTL_7_SIZE, 0);
+
+ mv64x60_write(bh, MV64x60_PCI1_ACC_CNTL_4_BASE_LO, 0xfff);
+ mv64x60_write(bh, MV64x60_PCI1_ACC_CNTL_4_BASE_HI, 0);
+ mv64x60_write(bh, MV64x60_PCI1_ACC_CNTL_4_SIZE, 0);
+ mv64x60_write(bh, MV64x60_PCI1_ACC_CNTL_5_BASE_LO, 0xfff);
+ mv64x60_write(bh, MV64x60_PCI1_ACC_CNTL_5_BASE_HI, 0);
+ mv64x60_write(bh, MV64x60_PCI1_ACC_CNTL_5_SIZE, 0);
+ mv64x60_write(bh, GT64260_PCI1_ACC_CNTL_6_BASE_LO, 0xfff);
+ mv64x60_write(bh, GT64260_PCI1_ACC_CNTL_6_BASE_HI, 0);
+ mv64x60_write(bh, GT64260_PCI1_ACC_CNTL_6_SIZE, 0);
+ mv64x60_write(bh, GT64260_PCI1_ACC_CNTL_7_BASE_LO, 0xfff);
+ mv64x60_write(bh, GT64260_PCI1_ACC_CNTL_7_BASE_HI, 0);
+ mv64x60_write(bh, GT64260_PCI1_ACC_CNTL_7_SIZE, 0);
+
+ /* Disable all PCI-><whatever> windows */
+ mv64x60_set_bits(bh, MV64x60_PCI0_BAR_ENABLE, 0x07fffdff);
+ mv64x60_set_bits(bh, MV64x60_PCI1_BAR_ENABLE, 0x07fffdff);
+
+ /*
+ * Some firmwares enable a bunch of intr sources
+ * for the PCI INT output pins.
+ */
+ mv64x60_write(bh, GT64260_IC_CPU_INTR_MASK_LO, 0);
+ mv64x60_write(bh, GT64260_IC_CPU_INTR_MASK_HI, 0);
+ mv64x60_write(bh, GT64260_IC_PCI0_INTR_MASK_LO, 0);
+ mv64x60_write(bh, GT64260_IC_PCI0_INTR_MASK_HI, 0);
+ mv64x60_write(bh, GT64260_IC_PCI1_INTR_MASK_LO, 0);
+ mv64x60_write(bh, GT64260_IC_PCI1_INTR_MASK_HI, 0);
+ mv64x60_write(bh, GT64260_IC_CPU_INT_0_MASK, 0);
+ mv64x60_write(bh, GT64260_IC_CPU_INT_1_MASK, 0);
+ mv64x60_write(bh, GT64260_IC_CPU_INT_2_MASK, 0);
+ mv64x60_write(bh, GT64260_IC_CPU_INT_3_MASK, 0);
+
+ return;
+}
+
+/*
+ * gt64260a_chip_specific_init()
+ *
+ * Implement errata work arounds for the GT64260A.
+ */
+static void __init
+gt64260a_chip_specific_init(struct mv64x60_handle *bh,
+ struct mv64x60_setup_info *si)
+{
+#ifdef CONFIG_SERIAL_MPSC
+ struct resource *r;
+#endif
+#if !defined(CONFIG_NOT_COHERENT_CACHE)
+ u32 val;
+ u8 save_exclude;
+#endif
+
+ if (si->pci_0.enable_bus)
+ mv64x60_set_bits(bh, MV64x60_PCI0_CMD,
+ ((1<<4) | (1<<5) | (1<<9) | (1<<13)));
+
+ if (si->pci_1.enable_bus)
+ mv64x60_set_bits(bh, MV64x60_PCI1_CMD,
+ ((1<<4) | (1<<5) | (1<<9) | (1<<13)));
+
+ /*
+ * Dave Wilhardt found that bit 4 in the PCI Command registers must
+ * be set if you are using cache coherency.
+ */
+#if !defined(CONFIG_NOT_COHERENT_CACHE)
+ /* Res #MEM-4 -- cpu read buffer to buffer 1 */
+ if ((mv64x60_read(bh, MV64x60_CPU_MODE) & 0xf0) == 0x40)
+ mv64x60_set_bits(bh, GT64260_SDRAM_CONFIG, (1<<26));
+
+ save_exclude = mv64x60_pci_exclude_bridge;
+ mv64x60_pci_exclude_bridge = 0;
+ if (si->pci_0.enable_bus) {
+ early_read_config_dword(bh->hose_a, 0, PCI_DEVFN(0,0),
+ PCI_COMMAND, &val);
+ val |= PCI_COMMAND_INVALIDATE;
+ early_write_config_dword(bh->hose_a, 0, PCI_DEVFN(0,0),
+ PCI_COMMAND, val);
+ }
+
+ if (si->pci_1.enable_bus) {
+ early_read_config_dword(bh->hose_b, 0, PCI_DEVFN(0,0),
+ PCI_COMMAND, &val);
+ val |= PCI_COMMAND_INVALIDATE;
+ early_write_config_dword(bh->hose_b, 0, PCI_DEVFN(0,0),
+ PCI_COMMAND, val);
+ }
+ mv64x60_pci_exclude_bridge = save_exclude;
+#endif
+
+ /* Disable buffer/descriptor snooping */
+ mv64x60_clr_bits(bh, 0xf280, (1<< 6) | (1<<14) | (1<<22) | (1<<30));
+ mv64x60_clr_bits(bh, 0xf2c0, (1<< 6) | (1<<14) | (1<<22) | (1<<30));
+
+#ifdef CONFIG_SERIAL_MPSC
+ mv64x60_mpsc0_pdata.mirror_regs = 1;
+ mv64x60_mpsc0_pdata.cache_mgmt = 1;
+ mv64x60_mpsc1_pdata.mirror_regs = 1;
+ mv64x60_mpsc1_pdata.cache_mgmt = 1;
+
+ if ((r = platform_get_resource(&mpsc1_device, IORESOURCE_IRQ, 0))
+ != NULL) {
+
+ r->start = MV64x60_IRQ_SDMA_0;
+ r->end = MV64x60_IRQ_SDMA_0;
+ }
+#endif
+
+ return;
+}
+
+/*
+ * gt64260b_chip_specific_init()
+ *
+ * Implement errata work arounds for the GT64260B.
+ */
+static void __init
+gt64260b_chip_specific_init(struct mv64x60_handle *bh,
+ struct mv64x60_setup_info *si)
+{
+#ifdef CONFIG_SERIAL_MPSC
+ struct resource *r;
+#endif
+#if !defined(CONFIG_NOT_COHERENT_CACHE)
+ u32 val;
+ u8 save_exclude;
+#endif
+
+ if (si->pci_0.enable_bus)
+ mv64x60_set_bits(bh, MV64x60_PCI0_CMD,
+ ((1<<4) | (1<<5) | (1<<9) | (1<<13)));
+
+ if (si->pci_1.enable_bus)
+ mv64x60_set_bits(bh, MV64x60_PCI1_CMD,
+ ((1<<4) | (1<<5) | (1<<9) | (1<<13)));
+
+ /*
+ * Dave Wilhardt found that bit 4 in the PCI Command registers must
+ * be set if you are using cache coherency.
+ */
+#if !defined(CONFIG_NOT_COHERENT_CACHE)
+ mv64x60_set_bits(bh, GT64260_CPU_WB_PRIORITY_BUFFER_DEPTH, 0xf);
+
+ /* Res #MEM-4 -- cpu read buffer to buffer 1 */
+ if ((mv64x60_read(bh, MV64x60_CPU_MODE) & 0xf0) == 0x40)
+ mv64x60_set_bits(bh, GT64260_SDRAM_CONFIG, (1<<26));
+
+ save_exclude = mv64x60_pci_exclude_bridge;
+ mv64x60_pci_exclude_bridge = 0;
+ if (si->pci_0.enable_bus) {
+ early_read_config_dword(bh->hose_a, 0, PCI_DEVFN(0,0),
+ PCI_COMMAND, &val);
+ val |= PCI_COMMAND_INVALIDATE;
+ early_write_config_dword(bh->hose_a, 0, PCI_DEVFN(0,0),
+ PCI_COMMAND, val);
+ }
+
+ if (si->pci_1.enable_bus) {
+ early_read_config_dword(bh->hose_b, 0, PCI_DEVFN(0,0),
+ PCI_COMMAND, &val);
+ val |= PCI_COMMAND_INVALIDATE;
+ early_write_config_dword(bh->hose_b, 0, PCI_DEVFN(0,0),
+ PCI_COMMAND, val);
+ }
+ mv64x60_pci_exclude_bridge = save_exclude;
+#endif
+
+ /* Disable buffer/descriptor snooping */
+ mv64x60_clr_bits(bh, 0xf280, (1<< 6) | (1<<14) | (1<<22) | (1<<30));
+ mv64x60_clr_bits(bh, 0xf2c0, (1<< 6) | (1<<14) | (1<<22) | (1<<30));
+
+#ifdef CONFIG_SERIAL_MPSC
+ /*
+ * The 64260B is not supposed to have the bug where the MPSC & ENET
+ * can't access cache coherent regions. However, testing has shown
+ * that the MPSC, at least, still has this bug.
+ */
+ mv64x60_mpsc0_pdata.cache_mgmt = 1;
+ mv64x60_mpsc1_pdata.cache_mgmt = 1;
+
+ if ((r = platform_get_resource(&mpsc1_device, IORESOURCE_IRQ, 0))
+ != NULL) {
+
+ r->start = MV64x60_IRQ_SDMA_0;
+ r->end = MV64x60_IRQ_SDMA_0;
+ }
+#endif
+
+ return;
+}
+
+/*
+ *****************************************************************************
+ *
+ * MV64360-Specific Routines
+ *
+ *****************************************************************************
+ */
+/*
+ * mv64360_translate_size()
+ *
+ * On the MV64360, the size register is set similar to the size you get
+ * from a pci config space BAR register. That is, programmed from LSB to MSB
+ * as a sequence of 1's followed by a sequence of 0's. IOW, "size -1" with the
+ * assumption that the size is a power of 2.
+ */
+static u32 __init
+mv64360_translate_size(u32 base_addr, u32 size, u32 num_bits)
+{
+ return mv64x60_mask(size - 1, num_bits);
+}
+
+/*
+ * mv64360_untranslate_size()
+ *
+ * Translate the size register value of a window into a window size.
+ */
+static u32 __init
+mv64360_untranslate_size(u32 base_addr, u32 size, u32 num_bits)
+{
+ if (size > 0) {
+ size >>= (32 - num_bits);
+ size++;
+ size <<= (32 - num_bits);
+ }
+
+ return size;
+}
+
+/*
+ * mv64360_set_pci2mem_window()
+ *
+ * The PCI->MEM window registers are actually in PCI config space so need
+ * to set them by setting the correct config space BARs.
+ */
+struct {
+ u32 fcn;
+ u32 base_hi_bar;
+ u32 base_lo_bar;
+} static mv64360_reg_addrs[2][4] __initdata = {
+ {{ 0, 0x14, 0x10 }, { 0, 0x1c, 0x18 },
+ { 1, 0x14, 0x10 }, { 1, 0x1c, 0x18 }},
+ {{ 0, 0x94, 0x90 }, { 0, 0x9c, 0x98 },
+ { 1, 0x94, 0x90 }, { 1, 0x9c, 0x98 }}
+};
+
+static void __init
+mv64360_set_pci2mem_window(struct pci_controller *hose, u32 bus, u32 window,
+ u32 base)
+{
+ u8 save_exclude;
+
+ pr_debug("set pci->mem window: %d, hose: %d, base: 0x%x\n", window,
+ hose->index, base);
+
+ save_exclude = mv64x60_pci_exclude_bridge;
+ mv64x60_pci_exclude_bridge = 0;
+ early_write_config_dword(hose, 0,
+ PCI_DEVFN(0, mv64360_reg_addrs[bus][window].fcn),
+ mv64360_reg_addrs[bus][window].base_hi_bar, 0);
+ early_write_config_dword(hose, 0,
+ PCI_DEVFN(0, mv64360_reg_addrs[bus][window].fcn),
+ mv64360_reg_addrs[bus][window].base_lo_bar,
+ mv64x60_mask(base,20) | 0xc);
+ mv64x60_pci_exclude_bridge = save_exclude;
+
+ return;
+}
+
+/*
+ * mv64360_set_pci2regs_window()
+ *
+ * Set where the bridge's registers appear in PCI MEM space.
+ */
+static u32 mv64360_offset[2][2] __initdata = {{0x20, 0x24}, {0xa0, 0xa4}};
+
+static void __init
+mv64360_set_pci2regs_window(struct mv64x60_handle *bh,
+ struct pci_controller *hose, u32 bus, u32 base)
+{
+ u8 save_exclude;
+
+ pr_debug("set pci->internal regs hose: %d, base: 0x%x\n", hose->index,
+ base);
+
+ save_exclude = mv64x60_pci_exclude_bridge;
+ mv64x60_pci_exclude_bridge = 0;
+ early_write_config_dword(hose, 0, PCI_DEVFN(0,0),
+ mv64360_offset[bus][0], (base << 16));
+ early_write_config_dword(hose, 0, PCI_DEVFN(0,0),
+ mv64360_offset[bus][1], 0);
+ mv64x60_pci_exclude_bridge = save_exclude;
+
+ return;
+}
+
+/*
+ * mv64360_is_enabled_32bit()
+ *
+ * On a MV64360, a window is enabled by either clearing a bit in the
+ * CPU BAR Enable reg or setting a bit in the window's base reg.
+ * Note that this doesn't work for windows on the PCI slave side but we don't
+ * check those so its okay.
+ */
+static u32 __init
+mv64360_is_enabled_32bit(struct mv64x60_handle *bh, u32 window)
+{
+ u32 extra, rc = 0;
+
+ if (((mv64360_32bit_windows[window].base_reg != 0) &&
+ (mv64360_32bit_windows[window].size_reg != 0)) ||
+ (window == MV64x60_CPU2SRAM_WIN)) {
+
+ extra = mv64360_32bit_windows[window].extra;
+
+ switch (extra & MV64x60_EXTRA_MASK) {
+ case MV64x60_EXTRA_CPUWIN_ENAB:
+ rc = (mv64x60_read(bh, MV64360_CPU_BAR_ENABLE) &
+ (1 << (extra & 0x1f))) == 0;
+ break;
+
+ case MV64x60_EXTRA_CPUPROT_ENAB:
+ rc = (mv64x60_read(bh,
+ mv64360_32bit_windows[window].base_reg) &
+ (1 << (extra & 0x1f))) != 0;
+ break;
+
+ case MV64x60_EXTRA_ENET_ENAB:
+ rc = (mv64x60_read(bh, MV64360_ENET2MEM_BAR_ENABLE) &
+ (1 << (extra & 0x7))) == 0;
+ break;
+
+ case MV64x60_EXTRA_MPSC_ENAB:
+ rc = (mv64x60_read(bh, MV64360_MPSC2MEM_BAR_ENABLE) &
+ (1 << (extra & 0x3))) == 0;
+ break;
+
+ case MV64x60_EXTRA_IDMA_ENAB:
+ rc = (mv64x60_read(bh, MV64360_IDMA2MEM_BAR_ENABLE) &
+ (1 << (extra & 0x7))) == 0;
+ break;
+
+ default:
+ printk(KERN_ERR "mv64360_is_enabled: %s\n",
+ "32bit table corrupted");
+ }
+ }
+
+ return rc;
+}
+
+/*
+ * mv64360_enable_window_32bit()
+ *
+ * On a MV64360, a window is enabled by either clearing a bit in the
+ * CPU BAR Enable reg or setting a bit in the window's base reg.
+ */
+static void __init
+mv64360_enable_window_32bit(struct mv64x60_handle *bh, u32 window)
+{
+ u32 extra;
+
+ pr_debug("enable 32bit window: %d\n", window);
+
+ if (((mv64360_32bit_windows[window].base_reg != 0) &&
+ (mv64360_32bit_windows[window].size_reg != 0)) ||
+ (window == MV64x60_CPU2SRAM_WIN)) {
+
+ extra = mv64360_32bit_windows[window].extra;
+
+ switch (extra & MV64x60_EXTRA_MASK) {
+ case MV64x60_EXTRA_CPUWIN_ENAB:
+ mv64x60_clr_bits(bh, MV64360_CPU_BAR_ENABLE,
+ (1 << (extra & 0x1f)));
+ break;
+
+ case MV64x60_EXTRA_CPUPROT_ENAB:
+ mv64x60_set_bits(bh,
+ mv64360_32bit_windows[window].base_reg,
+ (1 << (extra & 0x1f)));
+ break;
+
+ case MV64x60_EXTRA_ENET_ENAB:
+ mv64x60_clr_bits(bh, MV64360_ENET2MEM_BAR_ENABLE,
+ (1 << (extra & 0x7)));
+ break;
+
+ case MV64x60_EXTRA_MPSC_ENAB:
+ mv64x60_clr_bits(bh, MV64360_MPSC2MEM_BAR_ENABLE,
+ (1 << (extra & 0x3)));
+ break;
+
+ case MV64x60_EXTRA_IDMA_ENAB:
+ mv64x60_clr_bits(bh, MV64360_IDMA2MEM_BAR_ENABLE,
+ (1 << (extra & 0x7)));
+ break;
+
+ default:
+ printk(KERN_ERR "mv64360_enable: %s\n",
+ "32bit table corrupted");
+ }
+ }
+
+ return;
+}
+
+/*
+ * mv64360_disable_window_32bit()
+ *
+ * On a MV64360, a window is disabled by either setting a bit in the
+ * CPU BAR Enable reg or clearing a bit in the window's base reg.
+ */
+static void __init
+mv64360_disable_window_32bit(struct mv64x60_handle *bh, u32 window)
+{
+ u32 extra;
+
+ pr_debug("disable 32bit window: %d, base_reg: 0x%x, size_reg: 0x%x\n",
+ window, mv64360_32bit_windows[window].base_reg,
+ mv64360_32bit_windows[window].size_reg);
+
+ if (((mv64360_32bit_windows[window].base_reg != 0) &&
+ (mv64360_32bit_windows[window].size_reg != 0)) ||
+ (window == MV64x60_CPU2SRAM_WIN)) {
+
+ extra = mv64360_32bit_windows[window].extra;
+
+ switch (extra & MV64x60_EXTRA_MASK) {
+ case MV64x60_EXTRA_CPUWIN_ENAB:
+ mv64x60_set_bits(bh, MV64360_CPU_BAR_ENABLE,
+ (1 << (extra & 0x1f)));
+ break;
+
+ case MV64x60_EXTRA_CPUPROT_ENAB:
+ mv64x60_clr_bits(bh,
+ mv64360_32bit_windows[window].base_reg,
+ (1 << (extra & 0x1f)));
+ break;
+
+ case MV64x60_EXTRA_ENET_ENAB:
+ mv64x60_set_bits(bh, MV64360_ENET2MEM_BAR_ENABLE,
+ (1 << (extra & 0x7)));
+ break;
+
+ case MV64x60_EXTRA_MPSC_ENAB:
+ mv64x60_set_bits(bh, MV64360_MPSC2MEM_BAR_ENABLE,
+ (1 << (extra & 0x3)));
+ break;
+
+ case MV64x60_EXTRA_IDMA_ENAB:
+ mv64x60_set_bits(bh, MV64360_IDMA2MEM_BAR_ENABLE,
+ (1 << (extra & 0x7)));
+ break;
+
+ default:
+ printk(KERN_ERR "mv64360_disable: %s\n",
+ "32bit table corrupted");
+ }
+ }
+
+ return;
+}
+
+/*
+ * mv64360_enable_window_64bit()
+ *
+ * On the MV64360, a 64-bit window is enabled by setting a bit in the window's
+ * base reg.
+ */
+static void __init
+mv64360_enable_window_64bit(struct mv64x60_handle *bh, u32 window)
+{
+ pr_debug("enable 64bit window: %d\n", window);
+
+ if ((mv64360_64bit_windows[window].base_lo_reg!= 0) &&
+ (mv64360_64bit_windows[window].size_reg != 0)) {
+
+ if ((mv64360_64bit_windows[window].extra & MV64x60_EXTRA_MASK)
+ == MV64x60_EXTRA_PCIACC_ENAB)
+
+ mv64x60_set_bits(bh,
+ mv64360_64bit_windows[window].base_lo_reg,
+ (1 << (mv64360_64bit_windows[window].extra &
+ 0x1f)));
+ else
+ printk(KERN_ERR "mv64360_enable: %s\n",
+ "64bit table corrupted");
+ }
+
+ return;
+}
+
+/*
+ * mv64360_disable_window_64bit()
+ *
+ * On a MV64360, a 64-bit window is disabled by clearing a bit in the window's
+ * base reg.
+ */
+static void __init
+mv64360_disable_window_64bit(struct mv64x60_handle *bh, u32 window)
+{
+ pr_debug("disable 64bit window: %d, base_reg: 0x%x, size_reg: 0x%x\n",
+ window, mv64360_64bit_windows[window].base_lo_reg,
+ mv64360_64bit_windows[window].size_reg);
+
+ if ((mv64360_64bit_windows[window].base_lo_reg != 0) &&
+ (mv64360_64bit_windows[window].size_reg != 0)) {
+
+ if ((mv64360_64bit_windows[window].extra & MV64x60_EXTRA_MASK)
+ == MV64x60_EXTRA_PCIACC_ENAB)
+
+ mv64x60_clr_bits(bh,
+ mv64360_64bit_windows[window].base_lo_reg,
+ (1 << (mv64360_64bit_windows[window].extra &
+ 0x1f)));
+ else
+ printk(KERN_ERR "mv64360_disable: %s\n",
+ "64bit table corrupted");
+ }
+
+ return;
+}
+
+/*
+ * mv64360_disable_all_windows()
+ *
+ * The MV64360 has a few windows that aren't represented in the table of
+ * windows at the top of this file. This routine turns all of them off
+ * except for the memory controller windows, of course.
+ */
+static void __init
+mv64360_disable_all_windows(struct mv64x60_handle *bh,
+ struct mv64x60_setup_info *si)
+{
+ u32 preserve, i;
+
+ /* Disable 32bit windows (don't disable cpu->mem windows) */
+ for (i=MV64x60_CPU2DEV_0_WIN; i<MV64x60_32BIT_WIN_COUNT; i++) {
+ if (i < 32)
+ preserve = si->window_preserve_mask_32_lo & (1 << i);
+ else
+ preserve = si->window_preserve_mask_32_hi & (1<<(i-32));
+
+ if (!preserve)
+ mv64360_disable_window_32bit(bh, i);
+ }
+
+ /* Disable 64bit windows */
+ for (i=0; i<MV64x60_64BIT_WIN_COUNT; i++)
+ if (!(si->window_preserve_mask_64 & (1<<i)))
+ mv64360_disable_window_64bit(bh, i);
+
+ /* Turn off PCI->MEM access cntl wins not in mv64360_64bit_windows[] */
+ mv64x60_clr_bits(bh, MV64x60_PCI0_ACC_CNTL_4_BASE_LO, 0);
+ mv64x60_clr_bits(bh, MV64x60_PCI0_ACC_CNTL_5_BASE_LO, 0);
+ mv64x60_clr_bits(bh, MV64x60_PCI1_ACC_CNTL_4_BASE_LO, 0);
+ mv64x60_clr_bits(bh, MV64x60_PCI1_ACC_CNTL_5_BASE_LO, 0);
+
+ /* Disable all PCI-><whatever> windows */
+ mv64x60_set_bits(bh, MV64x60_PCI0_BAR_ENABLE, 0x0000f9ff);
+ mv64x60_set_bits(bh, MV64x60_PCI1_BAR_ENABLE, 0x0000f9ff);
+
+ return;
+}
+
+/*
+ * mv64360_config_io2mem_windows()
+ *
+ * ENET, MPSC, and IDMA ctlrs on the MV64[34]60 have separate windows that
+ * must be set up so that the respective ctlr can access system memory.
+ */
+static u32 enet_tab[MV64x60_CPU2MEM_WINDOWS] __initdata = {
+ MV64x60_ENET2MEM_0_WIN, MV64x60_ENET2MEM_1_WIN,
+ MV64x60_ENET2MEM_2_WIN, MV64x60_ENET2MEM_3_WIN,
+};
+
+static u32 mpsc_tab[MV64x60_CPU2MEM_WINDOWS] __initdata = {
+ MV64x60_MPSC2MEM_0_WIN, MV64x60_MPSC2MEM_1_WIN,
+ MV64x60_MPSC2MEM_2_WIN, MV64x60_MPSC2MEM_3_WIN,
+};
+
+static u32 idma_tab[MV64x60_CPU2MEM_WINDOWS] __initdata = {
+ MV64x60_IDMA2MEM_0_WIN, MV64x60_IDMA2MEM_1_WIN,
+ MV64x60_IDMA2MEM_2_WIN, MV64x60_IDMA2MEM_3_WIN,
+};
+
+static u32 dram_selects[MV64x60_CPU2MEM_WINDOWS] __initdata =
+ { 0xe, 0xd, 0xb, 0x7 };
+
+static void __init
+mv64360_config_io2mem_windows(struct mv64x60_handle *bh,
+ struct mv64x60_setup_info *si,
+ u32 mem_windows[MV64x60_CPU2MEM_WINDOWS][2])
+{
+ u32 i, win;
+
+ pr_debug("config_io2regs_windows: enet, mpsc, idma -> bridge regs\n");
+
+ mv64x60_write(bh, MV64360_ENET2MEM_ACC_PROT_0, 0);
+ mv64x60_write(bh, MV64360_ENET2MEM_ACC_PROT_1, 0);
+ mv64x60_write(bh, MV64360_ENET2MEM_ACC_PROT_2, 0);
+
+ mv64x60_write(bh, MV64360_MPSC2MEM_ACC_PROT_0, 0);
+ mv64x60_write(bh, MV64360_MPSC2MEM_ACC_PROT_1, 0);
+
+ mv64x60_write(bh, MV64360_IDMA2MEM_ACC_PROT_0, 0);
+ mv64x60_write(bh, MV64360_IDMA2MEM_ACC_PROT_1, 0);
+ mv64x60_write(bh, MV64360_IDMA2MEM_ACC_PROT_2, 0);
+ mv64x60_write(bh, MV64360_IDMA2MEM_ACC_PROT_3, 0);
+
+ /* Assume that mem ctlr has no more windows than embedded I/O ctlr */
+ for (win=MV64x60_CPU2MEM_0_WIN,i=0;win<=MV64x60_CPU2MEM_3_WIN;win++,i++)
+ if (bh->ci->is_enabled_32bit(bh, win)) {
+ mv64x60_set_32bit_window(bh, enet_tab[i],
+ mem_windows[i][0], mem_windows[i][1],
+ (dram_selects[i] << 8) |
+ (si->enet_options[i] & 0x3000));
+ bh->ci->enable_window_32bit(bh, enet_tab[i]);
+
+ /* Give enet r/w access to memory region */
+ mv64x60_set_bits(bh, MV64360_ENET2MEM_ACC_PROT_0,
+ (0x3 << (i << 1)));
+ mv64x60_set_bits(bh, MV64360_ENET2MEM_ACC_PROT_1,
+ (0x3 << (i << 1)));
+ mv64x60_set_bits(bh, MV64360_ENET2MEM_ACC_PROT_2,
+ (0x3 << (i << 1)));
+
+ mv64x60_set_32bit_window(bh, mpsc_tab[i],
+ mem_windows[i][0], mem_windows[i][1],
+ (dram_selects[i] << 8) |
+ (si->mpsc_options[i] & 0x3000));
+ bh->ci->enable_window_32bit(bh, mpsc_tab[i]);
+
+ /* Give mpsc r/w access to memory region */
+ mv64x60_set_bits(bh, MV64360_MPSC2MEM_ACC_PROT_0,
+ (0x3 << (i << 1)));
+ mv64x60_set_bits(bh, MV64360_MPSC2MEM_ACC_PROT_1,
+ (0x3 << (i << 1)));
+
+ mv64x60_set_32bit_window(bh, idma_tab[i],
+ mem_windows[i][0], mem_windows[i][1],
+ (dram_selects[i] << 8) |
+ (si->idma_options[i] & 0x3000));
+ bh->ci->enable_window_32bit(bh, idma_tab[i]);
+
+ /* Give idma r/w access to memory region */
+ mv64x60_set_bits(bh, MV64360_IDMA2MEM_ACC_PROT_0,
+ (0x3 << (i << 1)));
+ mv64x60_set_bits(bh, MV64360_IDMA2MEM_ACC_PROT_1,
+ (0x3 << (i << 1)));
+ mv64x60_set_bits(bh, MV64360_IDMA2MEM_ACC_PROT_2,
+ (0x3 << (i << 1)));
+ mv64x60_set_bits(bh, MV64360_IDMA2MEM_ACC_PROT_3,
+ (0x3 << (i << 1)));
+ }
+
+ return;
+}
+
+/*
+ * mv64360_set_mpsc2regs_window()
+ *
+ * MPSC has a window to the bridge's internal registers. Call this routine
+ * to change that window so it doesn't conflict with the windows mapping the
+ * mpsc to system memory.
+ */
+static void __init
+mv64360_set_mpsc2regs_window(struct mv64x60_handle *bh, u32 base)
+{
+ pr_debug("set mpsc->internal regs, base: 0x%x\n", base);
+
+ mv64x60_write(bh, MV64360_MPSC2REGS_BASE, base & 0xffff0000);
+ return;
+}
+
+/*
+ * mv64360_chip_specific_init()
+ *
+ * No errata work arounds for the MV64360 implemented at this point.
+ */
+static void __init
+mv64360_chip_specific_init(struct mv64x60_handle *bh,
+ struct mv64x60_setup_info *si)
+{
+#ifdef CONFIG_SERIAL_MPSC
+ mv64x60_mpsc0_pdata.brg_can_tune = 1;
+ mv64x60_mpsc0_pdata.cache_mgmt = 1;
+ mv64x60_mpsc1_pdata.brg_can_tune = 1;
+ mv64x60_mpsc1_pdata.cache_mgmt = 1;
+#endif
+
+ return;
+}
+
+/*
+ * mv64460_chip_specific_init()
+ *
+ * No errata work arounds for the MV64460 implemented at this point.
+ */
+static void __init
+mv64460_chip_specific_init(struct mv64x60_handle *bh,
+ struct mv64x60_setup_info *si)
+{
+#ifdef CONFIG_SERIAL_MPSC
+ mv64x60_mpsc0_pdata.brg_can_tune = 1;
+ mv64x60_mpsc1_pdata.brg_can_tune = 1;
+#endif
+ return;
+}
diff --git a/arch/ppc/syslib/mv64x60_dbg.c b/arch/ppc/syslib/mv64x60_dbg.c
new file mode 100644
index 0000000..2927c7a
--- /dev/null
+++ b/arch/ppc/syslib/mv64x60_dbg.c
@@ -0,0 +1,123 @@
+/*
+ * arch/ppc/syslib/mv64x60_dbg.c
+ *
+ * KGDB and progress routines for the Marvell/Galileo MV64x60 (Discovery).
+ *
+ * Author: Mark A. Greer <mgreer@mvista.com>
+ *
+ * 2003 (c) MontaVista Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+
+/*
+ *****************************************************************************
+ *
+ * Low-level MPSC/UART I/O routines
+ *
+ *****************************************************************************
+ */
+
+
+#include <linux/config.h>
+#include <linux/irq.h>
+#include <asm/delay.h>
+#include <asm/mv64x60.h>
+
+
+#if defined(CONFIG_SERIAL_TEXT_DEBUG)
+
+#define MPSC_CHR_1 0x000c
+#define MPSC_CHR_2 0x0010
+
+static struct mv64x60_handle mv64x60_dbg_bh;
+
+void
+mv64x60_progress_init(u32 base)
+{
+ mv64x60_dbg_bh.v_base = base;
+ return;
+}
+
+static void
+mv64x60_polled_putc(int chan, char c)
+{
+ u32 offset;
+
+ if (chan == 0)
+ offset = 0x8000;
+ else
+ offset = 0x9000;
+
+ mv64x60_write(&mv64x60_dbg_bh, offset + MPSC_CHR_1, (u32)c);
+ mv64x60_write(&mv64x60_dbg_bh, offset + MPSC_CHR_2, 0x200);
+ udelay(2000);
+}
+
+void
+mv64x60_mpsc_progress(char *s, unsigned short hex)
+{
+ volatile char c;
+
+ mv64x60_polled_putc(0, '\r');
+
+ while ((c = *s++) != 0)
+ mv64x60_polled_putc(0, c);
+
+ mv64x60_polled_putc(0, '\n');
+ mv64x60_polled_putc(0, '\r');
+
+ return;
+}
+#endif /* CONFIG_SERIAL_TEXT_DEBUG */
+
+
+#if defined(CONFIG_KGDB)
+
+#if defined(CONFIG_KGDB_TTYS0)
+#define KGDB_PORT 0
+#elif defined(CONFIG_KGDB_TTYS1)
+#define KGDB_PORT 1
+#else
+#error "Invalid kgdb_tty port"
+#endif
+
+void
+putDebugChar(unsigned char c)
+{
+ mv64x60_polled_putc(KGDB_PORT, (char)c);
+}
+
+int
+getDebugChar(void)
+{
+ unsigned char c;
+
+ while (!mv64x60_polled_getc(KGDB_PORT, &c));
+ return (int)c;
+}
+
+void
+putDebugString(char* str)
+{
+ while (*str != '\0') {
+ putDebugChar(*str);
+ str++;
+ }
+ putDebugChar('\r');
+ return;
+}
+
+void
+kgdb_interruptible(int enable)
+{
+}
+
+void
+kgdb_map_scc(void)
+{
+ if (ppc_md.early_serial_map)
+ ppc_md.early_serial_map();
+}
+#endif /* CONFIG_KGDB */
diff --git a/arch/ppc/syslib/mv64x60_win.c b/arch/ppc/syslib/mv64x60_win.c
new file mode 100644
index 0000000..b6f0f5d
--- /dev/null
+++ b/arch/ppc/syslib/mv64x60_win.c
@@ -0,0 +1,1168 @@
+/*
+ * arch/ppc/syslib/mv64x60_win.c
+ *
+ * Tables with info on how to manipulate the 32 & 64 bit windows on the
+ * various types of Marvell bridge chips.
+ *
+ * Author: Mark A. Greer <mgreer@mvista.com>
+ *
+ * 2004 (c) MontaVista, Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/bootmem.h>
+#include <linux/mv643xx.h>
+
+#include <asm/byteorder.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/uaccess.h>
+#include <asm/machdep.h>
+#include <asm/pci-bridge.h>
+#include <asm/delay.h>
+#include <asm/mv64x60.h>
+
+
+/*
+ *****************************************************************************
+ *
+ * Tables describing how to set up windows on each type of bridge
+ *
+ *****************************************************************************
+ */
+struct mv64x60_32bit_window
+ gt64260_32bit_windows[MV64x60_32BIT_WIN_COUNT] __initdata = {
+ /* CPU->MEM Windows */
+ [MV64x60_CPU2MEM_0_WIN] = {
+ .base_reg = MV64x60_CPU2MEM_0_BASE,
+ .size_reg = MV64x60_CPU2MEM_0_SIZE,
+ .base_bits = 12,
+ .size_bits = 12,
+ .get_from_field = mv64x60_shift_left,
+ .map_to_field = mv64x60_shift_right,
+ .extra = 0 },
+ [MV64x60_CPU2MEM_1_WIN] = {
+ .base_reg = MV64x60_CPU2MEM_1_BASE,
+ .size_reg = MV64x60_CPU2MEM_1_SIZE,
+ .base_bits = 12,
+ .size_bits = 12,
+ .get_from_field = mv64x60_shift_left,
+ .map_to_field = mv64x60_shift_right,
+ .extra = 0 },
+ [MV64x60_CPU2MEM_2_WIN] = {
+ .base_reg = MV64x60_CPU2MEM_2_BASE,
+ .size_reg = MV64x60_CPU2MEM_2_SIZE,
+ .base_bits = 12,
+ .size_bits = 12,
+ .get_from_field = mv64x60_shift_left,
+ .map_to_field = mv64x60_shift_right,
+ .extra = 0 },
+ [MV64x60_CPU2MEM_3_WIN] = {
+ .base_reg = MV64x60_CPU2MEM_3_BASE,
+ .size_reg = MV64x60_CPU2MEM_3_SIZE,
+ .base_bits = 12,
+ .size_bits = 12,
+ .get_from_field = mv64x60_shift_left,
+ .map_to_field = mv64x60_shift_right,
+ .extra = 0 },
+ /* CPU->Device Windows */
+ [MV64x60_CPU2DEV_0_WIN] = {
+ .base_reg = MV64x60_CPU2DEV_0_BASE,
+ .size_reg = MV64x60_CPU2DEV_0_SIZE,
+ .base_bits = 12,
+ .size_bits = 12,
+ .get_from_field = mv64x60_shift_left,
+ .map_to_field = mv64x60_shift_right,
+ .extra = 0 },
+ [MV64x60_CPU2DEV_1_WIN] = {
+ .base_reg = MV64x60_CPU2DEV_1_BASE,
+ .size_reg = MV64x60_CPU2DEV_1_SIZE,
+ .base_bits = 12,
+ .size_bits = 12,
+ .get_from_field = mv64x60_shift_left,
+ .map_to_field = mv64x60_shift_right,
+ .extra = 0 },
+ [MV64x60_CPU2DEV_2_WIN] = {
+ .base_reg = MV64x60_CPU2DEV_2_BASE,
+ .size_reg = MV64x60_CPU2DEV_2_SIZE,
+ .base_bits = 12,
+ .size_bits = 12,
+ .get_from_field = mv64x60_shift_left,
+ .map_to_field = mv64x60_shift_right,
+ .extra = 0 },
+ [MV64x60_CPU2DEV_3_WIN] = {
+ .base_reg = MV64x60_CPU2DEV_3_BASE,
+ .size_reg = MV64x60_CPU2DEV_3_SIZE,
+ .base_bits = 12,
+ .size_bits = 12,
+ .get_from_field = mv64x60_shift_left,
+ .map_to_field = mv64x60_shift_right,
+ .extra = 0 },
+ /* CPU->Boot Window */
+ [MV64x60_CPU2BOOT_WIN] = {
+ .base_reg = MV64x60_CPU2BOOT_0_BASE,
+ .size_reg = MV64x60_CPU2BOOT_0_SIZE,
+ .base_bits = 12,
+ .size_bits = 12,
+ .get_from_field = mv64x60_shift_left,
+ .map_to_field = mv64x60_shift_right,
+ .extra = 0 },
+ /* CPU->PCI 0 Windows */
+ [MV64x60_CPU2PCI0_IO_WIN] = {
+ .base_reg = MV64x60_CPU2PCI0_IO_BASE,
+ .size_reg = MV64x60_CPU2PCI0_IO_SIZE,
+ .base_bits = 12,
+ .size_bits = 12,
+ .get_from_field = mv64x60_shift_left,
+ .map_to_field = mv64x60_shift_right,
+ .extra = 0 },
+ [MV64x60_CPU2PCI0_MEM_0_WIN] = {
+ .base_reg = MV64x60_CPU2PCI0_MEM_0_BASE,
+ .size_reg = MV64x60_CPU2PCI0_MEM_0_SIZE,
+ .base_bits = 12,
+ .size_bits = 12,
+ .get_from_field = mv64x60_shift_left,
+ .map_to_field = mv64x60_shift_right,
+ .extra = 0 },
+ [MV64x60_CPU2PCI0_MEM_1_WIN] = {
+ .base_reg = MV64x60_CPU2PCI0_MEM_1_BASE,
+ .size_reg = MV64x60_CPU2PCI0_MEM_1_SIZE,
+ .base_bits = 12,
+ .size_bits = 12,
+ .get_from_field = mv64x60_shift_left,
+ .map_to_field = mv64x60_shift_right,
+ .extra = 0 },
+ [MV64x60_CPU2PCI0_MEM_2_WIN] = {
+ .base_reg = MV64x60_CPU2PCI0_MEM_2_BASE,
+ .size_reg = MV64x60_CPU2PCI0_MEM_2_SIZE,
+ .base_bits = 12,
+ .size_bits = 12,
+ .get_from_field = mv64x60_shift_left,
+ .map_to_field = mv64x60_shift_right,
+ .extra = 0 },
+ [MV64x60_CPU2PCI0_MEM_3_WIN] = {
+ .base_reg = MV64x60_CPU2PCI0_MEM_3_BASE,
+ .size_reg = MV64x60_CPU2PCI0_MEM_3_SIZE,
+ .base_bits = 12,
+ .size_bits = 12,
+ .get_from_field = mv64x60_shift_left,
+ .map_to_field = mv64x60_shift_right,
+ .extra = 0 },
+ /* CPU->PCI 1 Windows */
+ [MV64x60_CPU2PCI1_IO_WIN] = {
+ .base_reg = MV64x60_CPU2PCI1_IO_BASE,
+ .size_reg = MV64x60_CPU2PCI1_IO_SIZE,
+ .base_bits = 12,
+ .size_bits = 12,
+ .get_from_field = mv64x60_shift_left,
+ .map_to_field = mv64x60_shift_right,
+ .extra = 0 },
+ [MV64x60_CPU2PCI1_MEM_0_WIN] = {
+ .base_reg = MV64x60_CPU2PCI1_MEM_0_BASE,
+ .size_reg = MV64x60_CPU2PCI1_MEM_0_SIZE,
+ .base_bits = 12,
+ .size_bits = 12,
+ .get_from_field = mv64x60_shift_left,
+ .map_to_field = mv64x60_shift_right,
+ .extra = 0 },
+ [MV64x60_CPU2PCI1_MEM_1_WIN] = {
+ .base_reg = MV64x60_CPU2PCI1_MEM_1_BASE,
+ .size_reg = MV64x60_CPU2PCI1_MEM_1_SIZE,
+ .base_bits = 12,
+ .size_bits = 12,
+ .get_from_field = mv64x60_shift_left,
+ .map_to_field = mv64x60_shift_right,
+ .extra = 0 },
+ [MV64x60_CPU2PCI1_MEM_2_WIN] = {
+ .base_reg = MV64x60_CPU2PCI1_MEM_2_BASE,
+ .size_reg = MV64x60_CPU2PCI1_MEM_2_SIZE,
+ .base_bits = 12,
+ .size_bits = 12,
+ .get_from_field = mv64x60_shift_left,
+ .map_to_field = mv64x60_shift_right,
+ .extra = 0 },
+ [MV64x60_CPU2PCI1_MEM_3_WIN] = {
+ .base_reg = MV64x60_CPU2PCI1_MEM_3_BASE,
+ .size_reg = MV64x60_CPU2PCI1_MEM_3_SIZE,
+ .base_bits = 12,
+ .size_bits = 12,
+ .get_from_field = mv64x60_shift_left,
+ .map_to_field = mv64x60_shift_right,
+ .extra = 0 },
+ /* CPU->SRAM Window (64260 has no integrated SRAM) */
+ /* CPU->PCI 0 Remap I/O Window */
+ [MV64x60_CPU2PCI0_IO_REMAP_WIN] = {
+ .base_reg = MV64x60_CPU2PCI0_IO_REMAP,
+ .size_reg = 0,
+ .base_bits = 12,
+ .size_bits = 0,
+ .get_from_field = mv64x60_shift_left,
+ .map_to_field = mv64x60_shift_right,
+ .extra = 0 },
+ /* CPU->PCI 1 Remap I/O Window */
+ [MV64x60_CPU2PCI1_IO_REMAP_WIN] = {
+ .base_reg = MV64x60_CPU2PCI1_IO_REMAP,
+ .size_reg = 0,
+ .base_bits = 12,
+ .size_bits = 0,
+ .get_from_field = mv64x60_shift_left,
+ .map_to_field = mv64x60_shift_right,
+ .extra = 0 },
+ /* CPU Memory Protection Windows */
+ [MV64x60_CPU_PROT_0_WIN] = {
+ .base_reg = MV64x60_CPU_PROT_BASE_0,
+ .size_reg = MV64x60_CPU_PROT_SIZE_0,
+ .base_bits = 12,
+ .size_bits = 12,
+ .get_from_field = mv64x60_shift_left,
+ .map_to_field = mv64x60_shift_right,
+ .extra = 0 },
+ [MV64x60_CPU_PROT_1_WIN] = {
+ .base_reg = MV64x60_CPU_PROT_BASE_1,
+ .size_reg = MV64x60_CPU_PROT_SIZE_1,
+ .base_bits = 12,
+ .size_bits = 12,
+ .get_from_field = mv64x60_shift_left,
+ .map_to_field = mv64x60_shift_right,
+ .extra = 0 },
+ [MV64x60_CPU_PROT_2_WIN] = {
+ .base_reg = MV64x60_CPU_PROT_BASE_2,
+ .size_reg = MV64x60_CPU_PROT_SIZE_2,
+ .base_bits = 12,
+ .size_bits = 12,
+ .get_from_field = mv64x60_shift_left,
+ .map_to_field = mv64x60_shift_right,
+ .extra = 0 },
+ [MV64x60_CPU_PROT_3_WIN] = {
+ .base_reg = MV64x60_CPU_PROT_BASE_3,
+ .size_reg = MV64x60_CPU_PROT_SIZE_3,
+ .base_bits = 12,
+ .size_bits = 12,
+ .get_from_field = mv64x60_shift_left,
+ .map_to_field = mv64x60_shift_right,
+ .extra = 0 },
+ /* CPU Snoop Windows */
+ [MV64x60_CPU_SNOOP_0_WIN] = {
+ .base_reg = GT64260_CPU_SNOOP_BASE_0,
+ .size_reg = GT64260_CPU_SNOOP_SIZE_0,
+ .base_bits = 12,
+ .size_bits = 12,
+ .get_from_field = mv64x60_shift_left,
+ .map_to_field = mv64x60_shift_right,
+ .extra = 0 },
+ [MV64x60_CPU_SNOOP_1_WIN] = {
+ .base_reg = GT64260_CPU_SNOOP_BASE_1,
+ .size_reg = GT64260_CPU_SNOOP_SIZE_1,
+ .base_bits = 12,
+ .size_bits = 12,
+ .get_from_field = mv64x60_shift_left,
+ .map_to_field = mv64x60_shift_right,
+ .extra = 0 },
+ [MV64x60_CPU_SNOOP_2_WIN] = {
+ .base_reg = GT64260_CPU_SNOOP_BASE_2,
+ .size_reg = GT64260_CPU_SNOOP_SIZE_2,
+ .base_bits = 12,
+ .size_bits = 12,
+ .get_from_field = mv64x60_shift_left,
+ .map_to_field = mv64x60_shift_right,
+ .extra = 0 },
+ [MV64x60_CPU_SNOOP_3_WIN] = {
+ .base_reg = GT64260_CPU_SNOOP_BASE_3,
+ .size_reg = GT64260_CPU_SNOOP_SIZE_3,
+ .base_bits = 12,
+ .size_bits = 12,
+ .get_from_field = mv64x60_shift_left,
+ .map_to_field = mv64x60_shift_right,
+ .extra = 0 },
+ /* PCI 0->System Memory Remap Windows */
+ [MV64x60_PCI02MEM_REMAP_0_WIN] = {
+ .base_reg = MV64x60_PCI0_SLAVE_MEM_0_REMAP,
+ .size_reg = 0,
+ .base_bits = 20,
+ .size_bits = 0,
+ .get_from_field = mv64x60_mask,
+ .map_to_field = mv64x60_mask,
+ .extra = 0 },
+ [MV64x60_PCI02MEM_REMAP_1_WIN] = {
+ .base_reg = MV64x60_PCI0_SLAVE_MEM_1_REMAP,
+ .size_reg = 0,
+ .base_bits = 20,
+ .size_bits = 0,
+ .get_from_field = mv64x60_mask,
+ .map_to_field = mv64x60_mask,
+ .extra = 0 },
+ [MV64x60_PCI02MEM_REMAP_2_WIN] = {
+ .base_reg = MV64x60_PCI0_SLAVE_MEM_1_REMAP,
+ .size_reg = 0,
+ .base_bits = 20,
+ .size_bits = 0,
+ .get_from_field = mv64x60_mask,
+ .map_to_field = mv64x60_mask,
+ .extra = 0 },
+ [MV64x60_PCI02MEM_REMAP_3_WIN] = {
+ .base_reg = MV64x60_PCI0_SLAVE_MEM_1_REMAP,
+ .size_reg = 0,
+ .base_bits = 20,
+ .size_bits = 0,
+ .get_from_field = mv64x60_mask,
+ .map_to_field = mv64x60_mask,
+ .extra = 0 },
+ /* PCI 1->System Memory Remap Windows */
+ [MV64x60_PCI12MEM_REMAP_0_WIN] = {
+ .base_reg = MV64x60_PCI1_SLAVE_MEM_0_REMAP,
+ .size_reg = 0,
+ .base_bits = 20,
+ .size_bits = 0,
+ .get_from_field = mv64x60_mask,
+ .map_to_field = mv64x60_mask,
+ .extra = 0 },
+ [MV64x60_PCI12MEM_REMAP_1_WIN] = {
+ .base_reg = MV64x60_PCI1_SLAVE_MEM_1_REMAP,
+ .size_reg = 0,
+ .base_bits = 20,
+ .size_bits = 0,
+ .get_from_field = mv64x60_mask,
+ .map_to_field = mv64x60_mask,
+ .extra = 0 },
+ [MV64x60_PCI12MEM_REMAP_2_WIN] = {
+ .base_reg = MV64x60_PCI1_SLAVE_MEM_1_REMAP,
+ .size_reg = 0,
+ .base_bits = 20,
+ .size_bits = 0,
+ .get_from_field = mv64x60_mask,
+ .map_to_field = mv64x60_mask,
+ .extra = 0 },
+ [MV64x60_PCI12MEM_REMAP_3_WIN] = {
+ .base_reg = MV64x60_PCI1_SLAVE_MEM_1_REMAP,
+ .size_reg = 0,
+ .base_bits = 20,
+ .size_bits = 0,
+ .get_from_field = mv64x60_mask,
+ .map_to_field = mv64x60_mask,
+ .extra = 0 },
+ /* ENET->SRAM Window (64260 doesn't have separate windows) */
+ /* MPSC->SRAM Window (64260 doesn't have separate windows) */
+ /* IDMA->SRAM Window (64260 doesn't have separate windows) */
+};
+
+struct mv64x60_64bit_window
+ gt64260_64bit_windows[MV64x60_64BIT_WIN_COUNT] __initdata = {
+ /* CPU->PCI 0 MEM Remap Windows */
+ [MV64x60_CPU2PCI0_MEM_0_REMAP_WIN] = {
+ .base_hi_reg = MV64x60_CPU2PCI0_MEM_0_REMAP_HI,
+ .base_lo_reg = MV64x60_CPU2PCI0_MEM_0_REMAP_LO,
+ .size_reg = 0,
+ .base_lo_bits = 12,
+ .size_bits = 0,
+ .get_from_field = mv64x60_shift_left,
+ .map_to_field = mv64x60_shift_right,
+ .extra = 0 },
+ [MV64x60_CPU2PCI0_MEM_1_REMAP_WIN] = {
+ .base_hi_reg = MV64x60_CPU2PCI0_MEM_1_REMAP_HI,
+ .base_lo_reg = MV64x60_CPU2PCI0_MEM_1_REMAP_LO,
+ .size_reg = 0,
+ .base_lo_bits = 12,
+ .size_bits = 0,
+ .get_from_field = mv64x60_shift_left,
+ .map_to_field = mv64x60_shift_right,
+ .extra = 0 },
+ [MV64x60_CPU2PCI0_MEM_2_REMAP_WIN] = {
+ .base_hi_reg = MV64x60_CPU2PCI0_MEM_2_REMAP_HI,
+ .base_lo_reg = MV64x60_CPU2PCI0_MEM_2_REMAP_LO,
+ .size_reg = 0,
+ .base_lo_bits = 12,
+ .size_bits = 0,
+ .get_from_field = mv64x60_shift_left,
+ .map_to_field = mv64x60_shift_right,
+ .extra = 0 },
+ [MV64x60_CPU2PCI0_MEM_3_REMAP_WIN] = {
+ .base_hi_reg = MV64x60_CPU2PCI0_MEM_3_REMAP_HI,
+ .base_lo_reg = MV64x60_CPU2PCI0_MEM_3_REMAP_LO,
+ .size_reg = 0,
+ .base_lo_bits = 12,
+ .size_bits = 0,
+ .get_from_field = mv64x60_shift_left,
+ .map_to_field = mv64x60_shift_right,
+ .extra = 0 },
+ /* CPU->PCI 1 MEM Remap Windows */
+ [MV64x60_CPU2PCI1_MEM_0_REMAP_WIN] = {
+ .base_hi_reg = MV64x60_CPU2PCI1_MEM_0_REMAP_HI,
+ .base_lo_reg = MV64x60_CPU2PCI1_MEM_0_REMAP_LO,
+ .size_reg = 0,
+ .base_lo_bits = 12,
+ .size_bits = 0,
+ .get_from_field = mv64x60_shift_left,
+ .map_to_field = mv64x60_shift_right,
+ .extra = 0 },
+ [MV64x60_CPU2PCI1_MEM_1_REMAP_WIN] = {
+ .base_hi_reg = MV64x60_CPU2PCI1_MEM_1_REMAP_HI,
+ .base_lo_reg = MV64x60_CPU2PCI1_MEM_1_REMAP_LO,
+ .size_reg = 0,
+ .base_lo_bits = 12,
+ .size_bits = 0,
+ .get_from_field = mv64x60_shift_left,
+ .map_to_field = mv64x60_shift_right,
+ .extra = 0 },
+ [MV64x60_CPU2PCI1_MEM_2_REMAP_WIN] = {
+ .base_hi_reg = MV64x60_CPU2PCI1_MEM_2_REMAP_HI,
+ .base_lo_reg = MV64x60_CPU2PCI1_MEM_2_REMAP_LO,
+ .size_reg = 0,
+ .base_lo_bits = 12,
+ .size_bits = 0,
+ .get_from_field = mv64x60_shift_left,
+ .map_to_field = mv64x60_shift_right,
+ .extra = 0 },
+ [MV64x60_CPU2PCI1_MEM_3_REMAP_WIN] = {
+ .base_hi_reg = MV64x60_CPU2PCI1_MEM_3_REMAP_HI,
+ .base_lo_reg = MV64x60_CPU2PCI1_MEM_3_REMAP_LO,
+ .size_reg = 0,
+ .base_lo_bits = 12,
+ .size_bits = 0,
+ .get_from_field = mv64x60_shift_left,
+ .map_to_field = mv64x60_shift_right,
+ .extra = 0 },
+ /* PCI 0->MEM Access Control Windows */
+ [MV64x60_PCI02MEM_ACC_CNTL_0_WIN] = {
+ .base_hi_reg = MV64x60_PCI0_ACC_CNTL_0_BASE_HI,
+ .base_lo_reg = MV64x60_PCI0_ACC_CNTL_0_BASE_LO,
+ .size_reg = MV64x60_PCI0_ACC_CNTL_0_SIZE,
+ .base_lo_bits = 12,
+ .size_bits = 12,
+ .get_from_field = mv64x60_shift_left,
+ .map_to_field = mv64x60_shift_right,
+ .extra = 0 },
+ [MV64x60_PCI02MEM_ACC_CNTL_1_WIN] = {
+ .base_hi_reg = MV64x60_PCI0_ACC_CNTL_1_BASE_HI,
+ .base_lo_reg = MV64x60_PCI0_ACC_CNTL_1_BASE_LO,
+ .size_reg = MV64x60_PCI0_ACC_CNTL_1_SIZE,
+ .base_lo_bits = 12,
+ .size_bits = 12,
+ .get_from_field = mv64x60_shift_left,
+ .map_to_field = mv64x60_shift_right,
+ .extra = 0 },
+ [MV64x60_PCI02MEM_ACC_CNTL_2_WIN] = {
+ .base_hi_reg = MV64x60_PCI0_ACC_CNTL_2_BASE_HI,
+ .base_lo_reg = MV64x60_PCI0_ACC_CNTL_2_BASE_LO,
+ .size_reg = MV64x60_PCI0_ACC_CNTL_2_SIZE,
+ .base_lo_bits = 12,
+ .size_bits = 12,
+ .get_from_field = mv64x60_shift_left,
+ .map_to_field = mv64x60_shift_right,
+ .extra = 0 },
+ [MV64x60_PCI02MEM_ACC_CNTL_3_WIN] = {
+ .base_hi_reg = MV64x60_PCI0_ACC_CNTL_3_BASE_HI,
+ .base_lo_reg = MV64x60_PCI0_ACC_CNTL_3_BASE_LO,
+ .size_reg = MV64x60_PCI0_ACC_CNTL_3_SIZE,
+ .base_lo_bits = 12,
+ .size_bits = 12,
+ .get_from_field = mv64x60_shift_left,
+ .map_to_field = mv64x60_shift_right,
+ .extra = 0 },
+ /* PCI 1->MEM Access Control Windows */
+ [MV64x60_PCI12MEM_ACC_CNTL_0_WIN] = {
+ .base_hi_reg = MV64x60_PCI1_ACC_CNTL_0_BASE_HI,
+ .base_lo_reg = MV64x60_PCI1_ACC_CNTL_0_BASE_LO,
+ .size_reg = MV64x60_PCI1_ACC_CNTL_0_SIZE,
+ .base_lo_bits = 12,
+ .size_bits = 12,
+ .get_from_field = mv64x60_shift_left,
+ .map_to_field = mv64x60_shift_right,
+ .extra = 0 },
+ [MV64x60_PCI12MEM_ACC_CNTL_1_WIN] = {
+ .base_hi_reg = MV64x60_PCI1_ACC_CNTL_1_BASE_HI,
+ .base_lo_reg = MV64x60_PCI1_ACC_CNTL_1_BASE_LO,
+ .size_reg = MV64x60_PCI1_ACC_CNTL_1_SIZE,
+ .base_lo_bits = 12,
+ .size_bits = 12,
+ .get_from_field = mv64x60_shift_left,
+ .map_to_field = mv64x60_shift_right,
+ .extra = 0 },
+ [MV64x60_PCI12MEM_ACC_CNTL_2_WIN] = {
+ .base_hi_reg = MV64x60_PCI1_ACC_CNTL_2_BASE_HI,
+ .base_lo_reg = MV64x60_PCI1_ACC_CNTL_2_BASE_LO,
+ .size_reg = MV64x60_PCI1_ACC_CNTL_2_SIZE,
+ .base_lo_bits = 12,
+ .size_bits = 12,
+ .get_from_field = mv64x60_shift_left,
+ .map_to_field = mv64x60_shift_right,
+ .extra = 0 },
+ [MV64x60_PCI12MEM_ACC_CNTL_3_WIN] = {
+ .base_hi_reg = MV64x60_PCI1_ACC_CNTL_3_BASE_HI,
+ .base_lo_reg = MV64x60_PCI1_ACC_CNTL_3_BASE_LO,
+ .size_reg = MV64x60_PCI1_ACC_CNTL_3_SIZE,
+ .base_lo_bits = 12,
+ .size_bits = 12,
+ .get_from_field = mv64x60_shift_left,
+ .map_to_field = mv64x60_shift_right,
+ .extra = 0 },
+ /* PCI 0->MEM Snoop Windows */
+ [MV64x60_PCI02MEM_SNOOP_0_WIN] = {
+ .base_hi_reg = GT64260_PCI0_SNOOP_0_BASE_HI,
+ .base_lo_reg = GT64260_PCI0_SNOOP_0_BASE_LO,
+ .size_reg = GT64260_PCI0_SNOOP_0_SIZE,
+ .base_lo_bits = 12,
+ .size_bits = 12,
+ .get_from_field = mv64x60_shift_left,
+ .map_to_field = mv64x60_shift_right,
+ .extra = 0 },
+ [MV64x60_PCI02MEM_SNOOP_1_WIN] = {
+ .base_hi_reg = GT64260_PCI0_SNOOP_1_BASE_HI,
+ .base_lo_reg = GT64260_PCI0_SNOOP_1_BASE_LO,
+ .size_reg = GT64260_PCI0_SNOOP_1_SIZE,
+ .base_lo_bits = 12,
+ .size_bits = 12,
+ .get_from_field = mv64x60_shift_left,
+ .map_to_field = mv64x60_shift_right,
+ .extra = 0 },
+ [MV64x60_PCI02MEM_SNOOP_2_WIN] = {
+ .base_hi_reg = GT64260_PCI0_SNOOP_2_BASE_HI,
+ .base_lo_reg = GT64260_PCI0_SNOOP_2_BASE_LO,
+ .size_reg = GT64260_PCI0_SNOOP_2_SIZE,
+ .base_lo_bits = 12,
+ .size_bits = 12,
+ .get_from_field = mv64x60_shift_left,
+ .map_to_field = mv64x60_shift_right,
+ .extra = 0 },
+ [MV64x60_PCI02MEM_SNOOP_3_WIN] = {
+ .base_hi_reg = GT64260_PCI0_SNOOP_3_BASE_HI,
+ .base_lo_reg = GT64260_PCI0_SNOOP_3_BASE_LO,
+ .size_reg = GT64260_PCI0_SNOOP_3_SIZE,
+ .base_lo_bits = 12,
+ .size_bits = 12,
+ .get_from_field = mv64x60_shift_left,
+ .map_to_field = mv64x60_shift_right,
+ .extra = 0 },
+ /* PCI 1->MEM Snoop Windows */
+ [MV64x60_PCI12MEM_SNOOP_0_WIN] = {
+ .base_hi_reg = GT64260_PCI1_SNOOP_0_BASE_HI,
+ .base_lo_reg = GT64260_PCI1_SNOOP_0_BASE_LO,
+ .size_reg = GT64260_PCI1_SNOOP_0_SIZE,
+ .base_lo_bits = 12,
+ .size_bits = 12,
+ .get_from_field = mv64x60_shift_left,
+ .map_to_field = mv64x60_shift_right,
+ .extra = 0 },
+ [MV64x60_PCI12MEM_SNOOP_1_WIN] = {
+ .base_hi_reg = GT64260_PCI1_SNOOP_1_BASE_HI,
+ .base_lo_reg = GT64260_PCI1_SNOOP_1_BASE_LO,
+ .size_reg = GT64260_PCI1_SNOOP_1_SIZE,
+ .base_lo_bits = 12,
+ .size_bits = 12,
+ .get_from_field = mv64x60_shift_left,
+ .map_to_field = mv64x60_shift_right,
+ .extra = 0 },
+ [MV64x60_PCI12MEM_SNOOP_2_WIN] = {
+ .base_hi_reg = GT64260_PCI1_SNOOP_2_BASE_HI,
+ .base_lo_reg = GT64260_PCI1_SNOOP_2_BASE_LO,
+ .size_reg = GT64260_PCI1_SNOOP_2_SIZE,
+ .base_lo_bits = 12,
+ .size_bits = 12,
+ .get_from_field = mv64x60_shift_left,
+ .map_to_field = mv64x60_shift_right,
+ .extra = 0 },
+ [MV64x60_PCI12MEM_SNOOP_3_WIN] = {
+ .base_hi_reg = GT64260_PCI1_SNOOP_3_BASE_HI,
+ .base_lo_reg = GT64260_PCI1_SNOOP_3_BASE_LO,
+ .size_reg = GT64260_PCI1_SNOOP_3_SIZE,
+ .base_lo_bits = 12,
+ .size_bits = 12,
+ .get_from_field = mv64x60_shift_left,
+ .map_to_field = mv64x60_shift_right,
+ .extra = 0 },
+};
+
+struct mv64x60_32bit_window
+ mv64360_32bit_windows[MV64x60_32BIT_WIN_COUNT] __initdata = {
+ /* CPU->MEM Windows */
+ [MV64x60_CPU2MEM_0_WIN] = {
+ .base_reg = MV64x60_CPU2MEM_0_BASE,
+ .size_reg = MV64x60_CPU2MEM_0_SIZE,
+ .base_bits = 16,
+ .size_bits = 16,
+ .get_from_field = mv64x60_shift_left,
+ .map_to_field = mv64x60_shift_right,
+ .extra = MV64x60_EXTRA_CPUWIN_ENAB | 0 },
+ [MV64x60_CPU2MEM_1_WIN] = {
+ .base_reg = MV64x60_CPU2MEM_1_BASE,
+ .size_reg = MV64x60_CPU2MEM_1_SIZE,
+ .base_bits = 16,
+ .size_bits = 16,
+ .get_from_field = mv64x60_shift_left,
+ .map_to_field = mv64x60_shift_right,
+ .extra = MV64x60_EXTRA_CPUWIN_ENAB | 1 },
+ [MV64x60_CPU2MEM_2_WIN] = {
+ .base_reg = MV64x60_CPU2MEM_2_BASE,
+ .size_reg = MV64x60_CPU2MEM_2_SIZE,
+ .base_bits = 16,
+ .size_bits = 16,
+ .get_from_field = mv64x60_shift_left,
+ .map_to_field = mv64x60_shift_right,
+ .extra = MV64x60_EXTRA_CPUWIN_ENAB | 2 },
+ [MV64x60_CPU2MEM_3_WIN] = {
+ .base_reg = MV64x60_CPU2MEM_3_BASE,
+ .size_reg = MV64x60_CPU2MEM_3_SIZE,
+ .base_bits = 16,
+ .size_bits = 16,
+ .get_from_field = mv64x60_shift_left,
+ .map_to_field = mv64x60_shift_right,
+ .extra = MV64x60_EXTRA_CPUWIN_ENAB | 3 },
+ /* CPU->Device Windows */
+ [MV64x60_CPU2DEV_0_WIN] = {
+ .base_reg = MV64x60_CPU2DEV_0_BASE,
+ .size_reg = MV64x60_CPU2DEV_0_SIZE,
+ .base_bits = 16,
+ .size_bits = 16,
+ .get_from_field = mv64x60_shift_left,
+ .map_to_field = mv64x60_shift_right,
+ .extra = MV64x60_EXTRA_CPUWIN_ENAB | 4 },
+ [MV64x60_CPU2DEV_1_WIN] = {
+ .base_reg = MV64x60_CPU2DEV_1_BASE,
+ .size_reg = MV64x60_CPU2DEV_1_SIZE,
+ .base_bits = 16,
+ .size_bits = 16,
+ .get_from_field = mv64x60_shift_left,
+ .map_to_field = mv64x60_shift_right,
+ .extra = MV64x60_EXTRA_CPUWIN_ENAB | 5 },
+ [MV64x60_CPU2DEV_2_WIN] = {
+ .base_reg = MV64x60_CPU2DEV_2_BASE,
+ .size_reg = MV64x60_CPU2DEV_2_SIZE,
+ .base_bits = 16,
+ .size_bits = 16,
+ .get_from_field = mv64x60_shift_left,
+ .map_to_field = mv64x60_shift_right,
+ .extra = MV64x60_EXTRA_CPUWIN_ENAB | 6 },
+ [MV64x60_CPU2DEV_3_WIN] = {
+ .base_reg = MV64x60_CPU2DEV_3_BASE,
+ .size_reg = MV64x60_CPU2DEV_3_SIZE,
+ .base_bits = 16,
+ .size_bits = 16,
+ .get_from_field = mv64x60_shift_left,
+ .map_to_field = mv64x60_shift_right,
+ .extra = MV64x60_EXTRA_CPUWIN_ENAB | 7 },
+ /* CPU->Boot Window */
+ [MV64x60_CPU2BOOT_WIN] = {
+ .base_reg = MV64x60_CPU2BOOT_0_BASE,
+ .size_reg = MV64x60_CPU2BOOT_0_SIZE,
+ .base_bits = 16,
+ .size_bits = 16,
+ .get_from_field = mv64x60_shift_left,
+ .map_to_field = mv64x60_shift_right,
+ .extra = MV64x60_EXTRA_CPUWIN_ENAB | 8 },
+ /* CPU->PCI 0 Windows */
+ [MV64x60_CPU2PCI0_IO_WIN] = {
+ .base_reg = MV64x60_CPU2PCI0_IO_BASE,
+ .size_reg = MV64x60_CPU2PCI0_IO_SIZE,
+ .base_bits = 16,
+ .size_bits = 16,
+ .get_from_field = mv64x60_shift_left,
+ .map_to_field = mv64x60_shift_right,
+ .extra = MV64x60_EXTRA_CPUWIN_ENAB | 9 },
+ [MV64x60_CPU2PCI0_MEM_0_WIN] = {
+ .base_reg = MV64x60_CPU2PCI0_MEM_0_BASE,
+ .size_reg = MV64x60_CPU2PCI0_MEM_0_SIZE,
+ .base_bits = 16,
+ .size_bits = 16,
+ .get_from_field = mv64x60_shift_left,
+ .map_to_field = mv64x60_shift_right,
+ .extra = MV64x60_EXTRA_CPUWIN_ENAB | 10 },
+ [MV64x60_CPU2PCI0_MEM_1_WIN] = {
+ .base_reg = MV64x60_CPU2PCI0_MEM_1_BASE,
+ .size_reg = MV64x60_CPU2PCI0_MEM_1_SIZE,
+ .base_bits = 16,
+ .size_bits = 16,
+ .get_from_field = mv64x60_shift_left,
+ .map_to_field = mv64x60_shift_right,
+ .extra = MV64x60_EXTRA_CPUWIN_ENAB | 11 },
+ [MV64x60_CPU2PCI0_MEM_2_WIN] = {
+ .base_reg = MV64x60_CPU2PCI0_MEM_2_BASE,
+ .size_reg = MV64x60_CPU2PCI0_MEM_2_SIZE,
+ .base_bits = 16,
+ .size_bits = 16,
+ .get_from_field = mv64x60_shift_left,
+ .map_to_field = mv64x60_shift_right,
+ .extra = MV64x60_EXTRA_CPUWIN_ENAB | 12 },
+ [MV64x60_CPU2PCI0_MEM_3_WIN] = {
+ .base_reg = MV64x60_CPU2PCI0_MEM_3_BASE,
+ .size_reg = MV64x60_CPU2PCI0_MEM_3_SIZE,
+ .base_bits = 16,
+ .size_bits = 16,
+ .get_from_field = mv64x60_shift_left,
+ .map_to_field = mv64x60_shift_right,
+ .extra = MV64x60_EXTRA_CPUWIN_ENAB | 13 },
+ /* CPU->PCI 1 Windows */
+ [MV64x60_CPU2PCI1_IO_WIN] = {
+ .base_reg = MV64x60_CPU2PCI1_IO_BASE,
+ .size_reg = MV64x60_CPU2PCI1_IO_SIZE,
+ .base_bits = 16,
+ .size_bits = 16,
+ .get_from_field = mv64x60_shift_left,
+ .map_to_field = mv64x60_shift_right,
+ .extra = MV64x60_EXTRA_CPUWIN_ENAB | 14 },
+ [MV64x60_CPU2PCI1_MEM_0_WIN] = {
+ .base_reg = MV64x60_CPU2PCI1_MEM_0_BASE,
+ .size_reg = MV64x60_CPU2PCI1_MEM_0_SIZE,
+ .base_bits = 16,
+ .size_bits = 16,
+ .get_from_field = mv64x60_shift_left,
+ .map_to_field = mv64x60_shift_right,
+ .extra = MV64x60_EXTRA_CPUWIN_ENAB | 15 },
+ [MV64x60_CPU2PCI1_MEM_1_WIN] = {
+ .base_reg = MV64x60_CPU2PCI1_MEM_1_BASE,
+ .size_reg = MV64x60_CPU2PCI1_MEM_1_SIZE,
+ .base_bits = 16,
+ .size_bits = 16,
+ .get_from_field = mv64x60_shift_left,
+ .map_to_field = mv64x60_shift_right,
+ .extra = MV64x60_EXTRA_CPUWIN_ENAB | 16 },
+ [MV64x60_CPU2PCI1_MEM_2_WIN] = {
+ .base_reg = MV64x60_CPU2PCI1_MEM_2_BASE,
+ .size_reg = MV64x60_CPU2PCI1_MEM_2_SIZE,
+ .base_bits = 16,
+ .size_bits = 16,
+ .get_from_field = mv64x60_shift_left,
+ .map_to_field = mv64x60_shift_right,
+ .extra = MV64x60_EXTRA_CPUWIN_ENAB | 17 },
+ [MV64x60_CPU2PCI1_MEM_3_WIN] = {
+ .base_reg = MV64x60_CPU2PCI1_MEM_3_BASE,
+ .size_reg = MV64x60_CPU2PCI1_MEM_3_SIZE,
+ .base_bits = 16,
+ .size_bits = 16,
+ .get_from_field = mv64x60_shift_left,
+ .map_to_field = mv64x60_shift_right,
+ .extra = MV64x60_EXTRA_CPUWIN_ENAB | 18 },
+ /* CPU->SRAM Window */
+ [MV64x60_CPU2SRAM_WIN] = {
+ .base_reg = MV64360_CPU2SRAM_BASE,
+ .size_reg = 0,
+ .base_bits = 16,
+ .size_bits = 0,
+ .get_from_field = mv64x60_shift_left,
+ .map_to_field = mv64x60_shift_right,
+ .extra = MV64x60_EXTRA_CPUWIN_ENAB | 19 },
+ /* CPU->PCI 0 Remap I/O Window */
+ [MV64x60_CPU2PCI0_IO_REMAP_WIN] = {
+ .base_reg = MV64x60_CPU2PCI0_IO_REMAP,
+ .size_reg = 0,
+ .base_bits = 16,
+ .size_bits = 0,
+ .get_from_field = mv64x60_shift_left,
+ .map_to_field = mv64x60_shift_right,
+ .extra = 0 },
+ /* CPU->PCI 1 Remap I/O Window */
+ [MV64x60_CPU2PCI1_IO_REMAP_WIN] = {
+ .base_reg = MV64x60_CPU2PCI1_IO_REMAP,
+ .size_reg = 0,
+ .base_bits = 16,
+ .size_bits = 0,
+ .get_from_field = mv64x60_shift_left,
+ .map_to_field = mv64x60_shift_right,
+ .extra = 0 },
+ /* CPU Memory Protection Windows */
+ [MV64x60_CPU_PROT_0_WIN] = {
+ .base_reg = MV64x60_CPU_PROT_BASE_0,
+ .size_reg = MV64x60_CPU_PROT_SIZE_0,
+ .base_bits = 16,
+ .size_bits = 16,
+ .get_from_field = mv64x60_shift_left,
+ .map_to_field = mv64x60_shift_right,
+ .extra = MV64x60_EXTRA_CPUPROT_ENAB | 31 },
+ [MV64x60_CPU_PROT_1_WIN] = {
+ .base_reg = MV64x60_CPU_PROT_BASE_1,
+ .size_reg = MV64x60_CPU_PROT_SIZE_1,
+ .base_bits = 16,
+ .size_bits = 16,
+ .get_from_field = mv64x60_shift_left,
+ .map_to_field = mv64x60_shift_right,
+ .extra = MV64x60_EXTRA_CPUPROT_ENAB | 31 },
+ [MV64x60_CPU_PROT_2_WIN] = {
+ .base_reg = MV64x60_CPU_PROT_BASE_2,
+ .size_reg = MV64x60_CPU_PROT_SIZE_2,
+ .base_bits = 16,
+ .size_bits = 16,
+ .get_from_field = mv64x60_shift_left,
+ .map_to_field = mv64x60_shift_right,
+ .extra = MV64x60_EXTRA_CPUPROT_ENAB | 31 },
+ [MV64x60_CPU_PROT_3_WIN] = {
+ .base_reg = MV64x60_CPU_PROT_BASE_3,
+ .size_reg = MV64x60_CPU_PROT_SIZE_3,
+ .base_bits = 16,
+ .size_bits = 16,
+ .get_from_field = mv64x60_shift_left,
+ .map_to_field = mv64x60_shift_right,
+ .extra = MV64x60_EXTRA_CPUPROT_ENAB | 31 },
+ /* CPU Snoop Windows -- don't exist on 64360 */
+ /* PCI 0->System Memory Remap Windows */
+ [MV64x60_PCI02MEM_REMAP_0_WIN] = {
+ .base_reg = MV64x60_PCI0_SLAVE_MEM_0_REMAP,
+ .size_reg = 0,
+ .base_bits = 20,
+ .size_bits = 0,
+ .get_from_field = mv64x60_mask,
+ .map_to_field = mv64x60_mask,
+ .extra = 0 },
+ [MV64x60_PCI02MEM_REMAP_1_WIN] = {
+ .base_reg = MV64x60_PCI0_SLAVE_MEM_1_REMAP,
+ .size_reg = 0,
+ .base_bits = 20,
+ .size_bits = 0,
+ .get_from_field = mv64x60_mask,
+ .map_to_field = mv64x60_mask,
+ .extra = 0 },
+ [MV64x60_PCI02MEM_REMAP_2_WIN] = {
+ .base_reg = MV64x60_PCI0_SLAVE_MEM_1_REMAP,
+ .size_reg = 0,
+ .base_bits = 20,
+ .size_bits = 0,
+ .get_from_field = mv64x60_mask,
+ .map_to_field = mv64x60_mask,
+ .extra = 0 },
+ [MV64x60_PCI02MEM_REMAP_3_WIN] = {
+ .base_reg = MV64x60_PCI0_SLAVE_MEM_1_REMAP,
+ .size_reg = 0,
+ .base_bits = 20,
+ .size_bits = 0,
+ .get_from_field = mv64x60_mask,
+ .map_to_field = mv64x60_mask,
+ .extra = 0 },
+ /* PCI 1->System Memory Remap Windows */
+ [MV64x60_PCI12MEM_REMAP_0_WIN] = {
+ .base_reg = MV64x60_PCI1_SLAVE_MEM_0_REMAP,
+ .size_reg = 0,
+ .base_bits = 20,
+ .size_bits = 0,
+ .get_from_field = mv64x60_mask,
+ .map_to_field = mv64x60_mask,
+ .extra = 0 },
+ [MV64x60_PCI12MEM_REMAP_1_WIN] = {
+ .base_reg = MV64x60_PCI1_SLAVE_MEM_1_REMAP,
+ .size_reg = 0,
+ .base_bits = 20,
+ .size_bits = 0,
+ .get_from_field = mv64x60_mask,
+ .map_to_field = mv64x60_mask,
+ .extra = 0 },
+ [MV64x60_PCI12MEM_REMAP_2_WIN] = {
+ .base_reg = MV64x60_PCI1_SLAVE_MEM_1_REMAP,
+ .size_reg = 0,
+ .base_bits = 20,
+ .size_bits = 0,
+ .get_from_field = mv64x60_mask,
+ .map_to_field = mv64x60_mask,
+ .extra = 0 },
+ [MV64x60_PCI12MEM_REMAP_3_WIN] = {
+ .base_reg = MV64x60_PCI1_SLAVE_MEM_1_REMAP,
+ .size_reg = 0,
+ .base_bits = 20,
+ .size_bits = 0,
+ .get_from_field = mv64x60_mask,
+ .map_to_field = mv64x60_mask,
+ .extra = 0 },
+ /* ENET->System Memory Windows */
+ [MV64x60_ENET2MEM_0_WIN] = {
+ .base_reg = MV64360_ENET2MEM_0_BASE,
+ .size_reg = MV64360_ENET2MEM_0_SIZE,
+ .base_bits = 16,
+ .size_bits = 16,
+ .get_from_field = mv64x60_mask,
+ .map_to_field = mv64x60_mask,
+ .extra = MV64x60_EXTRA_ENET_ENAB | 0 },
+ [MV64x60_ENET2MEM_1_WIN] = {
+ .base_reg = MV64360_ENET2MEM_1_BASE,
+ .size_reg = MV64360_ENET2MEM_1_SIZE,
+ .base_bits = 16,
+ .size_bits = 16,
+ .get_from_field = mv64x60_mask,
+ .map_to_field = mv64x60_mask,
+ .extra = MV64x60_EXTRA_ENET_ENAB | 1 },
+ [MV64x60_ENET2MEM_2_WIN] = {
+ .base_reg = MV64360_ENET2MEM_2_BASE,
+ .size_reg = MV64360_ENET2MEM_2_SIZE,
+ .base_bits = 16,
+ .size_bits = 16,
+ .get_from_field = mv64x60_mask,
+ .map_to_field = mv64x60_mask,
+ .extra = MV64x60_EXTRA_ENET_ENAB | 2 },
+ [MV64x60_ENET2MEM_3_WIN] = {
+ .base_reg = MV64360_ENET2MEM_3_BASE,
+ .size_reg = MV64360_ENET2MEM_3_SIZE,
+ .base_bits = 16,
+ .size_bits = 16,
+ .get_from_field = mv64x60_mask,
+ .map_to_field = mv64x60_mask,
+ .extra = MV64x60_EXTRA_ENET_ENAB | 3 },
+ [MV64x60_ENET2MEM_4_WIN] = {
+ .base_reg = MV64360_ENET2MEM_4_BASE,
+ .size_reg = MV64360_ENET2MEM_4_SIZE,
+ .base_bits = 16,
+ .size_bits = 16,
+ .get_from_field = mv64x60_mask,
+ .map_to_field = mv64x60_mask,
+ .extra = MV64x60_EXTRA_ENET_ENAB | 4 },
+ [MV64x60_ENET2MEM_5_WIN] = {
+ .base_reg = MV64360_ENET2MEM_5_BASE,
+ .size_reg = MV64360_ENET2MEM_5_SIZE,
+ .base_bits = 16,
+ .size_bits = 16,
+ .get_from_field = mv64x60_mask,
+ .map_to_field = mv64x60_mask,
+ .extra = MV64x60_EXTRA_ENET_ENAB | 5 },
+ /* MPSC->System Memory Windows */
+ [MV64x60_MPSC2MEM_0_WIN] = {
+ .base_reg = MV64360_MPSC2MEM_0_BASE,
+ .size_reg = MV64360_MPSC2MEM_0_SIZE,
+ .base_bits = 16,
+ .size_bits = 16,
+ .get_from_field = mv64x60_mask,
+ .map_to_field = mv64x60_mask,
+ .extra = MV64x60_EXTRA_MPSC_ENAB | 0 },
+ [MV64x60_MPSC2MEM_1_WIN] = {
+ .base_reg = MV64360_MPSC2MEM_1_BASE,
+ .size_reg = MV64360_MPSC2MEM_1_SIZE,
+ .base_bits = 16,
+ .size_bits = 16,
+ .get_from_field = mv64x60_mask,
+ .map_to_field = mv64x60_mask,
+ .extra = MV64x60_EXTRA_MPSC_ENAB | 1 },
+ [MV64x60_MPSC2MEM_2_WIN] = {
+ .base_reg = MV64360_MPSC2MEM_2_BASE,
+ .size_reg = MV64360_MPSC2MEM_2_SIZE,
+ .base_bits = 16,
+ .size_bits = 16,
+ .get_from_field = mv64x60_mask,
+ .map_to_field = mv64x60_mask,
+ .extra = MV64x60_EXTRA_MPSC_ENAB | 2 },
+ [MV64x60_MPSC2MEM_3_WIN] = {
+ .base_reg = MV64360_MPSC2MEM_3_BASE,
+ .size_reg = MV64360_MPSC2MEM_3_SIZE,
+ .base_bits = 16,
+ .size_bits = 16,
+ .get_from_field = mv64x60_mask,
+ .map_to_field = mv64x60_mask,
+ .extra = MV64x60_EXTRA_MPSC_ENAB | 3 },
+ /* IDMA->System Memory Windows */
+ [MV64x60_IDMA2MEM_0_WIN] = {
+ .base_reg = MV64360_IDMA2MEM_0_BASE,
+ .size_reg = MV64360_IDMA2MEM_0_SIZE,
+ .base_bits = 16,
+ .size_bits = 16,
+ .get_from_field = mv64x60_mask,
+ .map_to_field = mv64x60_mask,
+ .extra = MV64x60_EXTRA_IDMA_ENAB | 0 },
+ [MV64x60_IDMA2MEM_1_WIN] = {
+ .base_reg = MV64360_IDMA2MEM_1_BASE,
+ .size_reg = MV64360_IDMA2MEM_1_SIZE,
+ .base_bits = 16,
+ .size_bits = 16,
+ .get_from_field = mv64x60_mask,
+ .map_to_field = mv64x60_mask,
+ .extra = MV64x60_EXTRA_IDMA_ENAB | 1 },
+ [MV64x60_IDMA2MEM_2_WIN] = {
+ .base_reg = MV64360_IDMA2MEM_2_BASE,
+ .size_reg = MV64360_IDMA2MEM_2_SIZE,
+ .base_bits = 16,
+ .size_bits = 16,
+ .get_from_field = mv64x60_mask,
+ .map_to_field = mv64x60_mask,
+ .extra = MV64x60_EXTRA_IDMA_ENAB | 2 },
+ [MV64x60_IDMA2MEM_3_WIN] = {
+ .base_reg = MV64360_IDMA2MEM_3_BASE,
+ .size_reg = MV64360_IDMA2MEM_3_SIZE,
+ .base_bits = 16,
+ .size_bits = 16,
+ .get_from_field = mv64x60_mask,
+ .map_to_field = mv64x60_mask,
+ .extra = MV64x60_EXTRA_IDMA_ENAB | 3 },
+ [MV64x60_IDMA2MEM_4_WIN] = {
+ .base_reg = MV64360_IDMA2MEM_4_BASE,
+ .size_reg = MV64360_IDMA2MEM_4_SIZE,
+ .base_bits = 16,
+ .size_bits = 16,
+ .get_from_field = mv64x60_mask,
+ .map_to_field = mv64x60_mask,
+ .extra = MV64x60_EXTRA_IDMA_ENAB | 4 },
+ [MV64x60_IDMA2MEM_5_WIN] = {
+ .base_reg = MV64360_IDMA2MEM_5_BASE,
+ .size_reg = MV64360_IDMA2MEM_5_SIZE,
+ .base_bits = 16,
+ .size_bits = 16,
+ .get_from_field = mv64x60_mask,
+ .map_to_field = mv64x60_mask,
+ .extra = MV64x60_EXTRA_IDMA_ENAB | 5 },
+ [MV64x60_IDMA2MEM_6_WIN] = {
+ .base_reg = MV64360_IDMA2MEM_6_BASE,
+ .size_reg = MV64360_IDMA2MEM_6_SIZE,
+ .base_bits = 16,
+ .size_bits = 16,
+ .get_from_field = mv64x60_mask,
+ .map_to_field = mv64x60_mask,
+ .extra = MV64x60_EXTRA_IDMA_ENAB | 6 },
+ [MV64x60_IDMA2MEM_7_WIN] = {
+ .base_reg = MV64360_IDMA2MEM_7_BASE,
+ .size_reg = MV64360_IDMA2MEM_7_SIZE,
+ .base_bits = 16,
+ .size_bits = 16,
+ .get_from_field = mv64x60_mask,
+ .map_to_field = mv64x60_mask,
+ .extra = MV64x60_EXTRA_IDMA_ENAB | 7 },
+};
+
+struct mv64x60_64bit_window
+ mv64360_64bit_windows[MV64x60_64BIT_WIN_COUNT] __initdata = {
+ /* CPU->PCI 0 MEM Remap Windows */
+ [MV64x60_CPU2PCI0_MEM_0_REMAP_WIN] = {
+ .base_hi_reg = MV64x60_CPU2PCI0_MEM_0_REMAP_HI,
+ .base_lo_reg = MV64x60_CPU2PCI0_MEM_0_REMAP_LO,
+ .size_reg = 0,
+ .base_lo_bits = 16,
+ .size_bits = 0,
+ .get_from_field = mv64x60_shift_left,
+ .map_to_field = mv64x60_shift_right,
+ .extra = 0 },
+ [MV64x60_CPU2PCI0_MEM_1_REMAP_WIN] = {
+ .base_hi_reg = MV64x60_CPU2PCI0_MEM_1_REMAP_HI,
+ .base_lo_reg = MV64x60_CPU2PCI0_MEM_1_REMAP_LO,
+ .size_reg = 0,
+ .base_lo_bits = 16,
+ .size_bits = 0,
+ .get_from_field = mv64x60_shift_left,
+ .map_to_field = mv64x60_shift_right,
+ .extra = 0 },
+ [MV64x60_CPU2PCI0_MEM_2_REMAP_WIN] = {
+ .base_hi_reg = MV64x60_CPU2PCI0_MEM_2_REMAP_HI,
+ .base_lo_reg = MV64x60_CPU2PCI0_MEM_2_REMAP_LO,
+ .size_reg = 0,
+ .base_lo_bits = 16,
+ .size_bits = 0,
+ .get_from_field = mv64x60_shift_left,
+ .map_to_field = mv64x60_shift_right,
+ .extra = 0 },
+ [MV64x60_CPU2PCI0_MEM_3_REMAP_WIN] = {
+ .base_hi_reg = MV64x60_CPU2PCI0_MEM_3_REMAP_HI,
+ .base_lo_reg = MV64x60_CPU2PCI0_MEM_3_REMAP_LO,
+ .size_reg = 0,
+ .base_lo_bits = 16,
+ .size_bits = 0,
+ .get_from_field = mv64x60_shift_left,
+ .map_to_field = mv64x60_shift_right,
+ .extra = 0 },
+ /* CPU->PCI 1 MEM Remap Windows */
+ [MV64x60_CPU2PCI1_MEM_0_REMAP_WIN] = {
+ .base_hi_reg = MV64x60_CPU2PCI1_MEM_0_REMAP_HI,
+ .base_lo_reg = MV64x60_CPU2PCI1_MEM_0_REMAP_LO,
+ .size_reg = 0,
+ .base_lo_bits = 16,
+ .size_bits = 0,
+ .get_from_field = mv64x60_shift_left,
+ .map_to_field = mv64x60_shift_right,
+ .extra = 0 },
+ [MV64x60_CPU2PCI1_MEM_1_REMAP_WIN] = {
+ .base_hi_reg = MV64x60_CPU2PCI1_MEM_1_REMAP_HI,
+ .base_lo_reg = MV64x60_CPU2PCI1_MEM_1_REMAP_LO,
+ .size_reg = 0,
+ .base_lo_bits = 16,
+ .size_bits = 0,
+ .get_from_field = mv64x60_shift_left,
+ .map_to_field = mv64x60_shift_right,
+ .extra = 0 },
+ [MV64x60_CPU2PCI1_MEM_2_REMAP_WIN] = {
+ .base_hi_reg = MV64x60_CPU2PCI1_MEM_2_REMAP_HI,
+ .base_lo_reg = MV64x60_CPU2PCI1_MEM_2_REMAP_LO,
+ .size_reg = 0,
+ .base_lo_bits = 16,
+ .size_bits = 0,
+ .get_from_field = mv64x60_shift_left,
+ .map_to_field = mv64x60_shift_right,
+ .extra = 0 },
+ [MV64x60_CPU2PCI1_MEM_3_REMAP_WIN] = {
+ .base_hi_reg = MV64x60_CPU2PCI1_MEM_3_REMAP_HI,
+ .base_lo_reg = MV64x60_CPU2PCI1_MEM_3_REMAP_LO,
+ .size_reg = 0,
+ .base_lo_bits = 16,
+ .size_bits = 0,
+ .get_from_field = mv64x60_shift_left,
+ .map_to_field = mv64x60_shift_right,
+ .extra = 0 },
+ /* PCI 0->MEM Access Control Windows */
+ [MV64x60_PCI02MEM_ACC_CNTL_0_WIN] = {
+ .base_hi_reg = MV64x60_PCI0_ACC_CNTL_0_BASE_HI,
+ .base_lo_reg = MV64x60_PCI0_ACC_CNTL_0_BASE_LO,
+ .size_reg = MV64x60_PCI0_ACC_CNTL_0_SIZE,
+ .base_lo_bits = 20,
+ .size_bits = 20,
+ .get_from_field = mv64x60_mask,
+ .map_to_field = mv64x60_mask,
+ .extra = MV64x60_EXTRA_PCIACC_ENAB | 0 },
+ [MV64x60_PCI02MEM_ACC_CNTL_1_WIN] = {
+ .base_hi_reg = MV64x60_PCI0_ACC_CNTL_1_BASE_HI,
+ .base_lo_reg = MV64x60_PCI0_ACC_CNTL_1_BASE_LO,
+ .size_reg = MV64x60_PCI0_ACC_CNTL_1_SIZE,
+ .base_lo_bits = 20,
+ .size_bits = 20,
+ .get_from_field = mv64x60_mask,
+ .map_to_field = mv64x60_mask,
+ .extra = MV64x60_EXTRA_PCIACC_ENAB | 0 },
+ [MV64x60_PCI02MEM_ACC_CNTL_2_WIN] = {
+ .base_hi_reg = MV64x60_PCI0_ACC_CNTL_2_BASE_HI,
+ .base_lo_reg = MV64x60_PCI0_ACC_CNTL_2_BASE_LO,
+ .size_reg = MV64x60_PCI0_ACC_CNTL_2_SIZE,
+ .base_lo_bits = 20,
+ .size_bits = 20,
+ .get_from_field = mv64x60_mask,
+ .map_to_field = mv64x60_mask,
+ .extra = MV64x60_EXTRA_PCIACC_ENAB | 0 },
+ [MV64x60_PCI02MEM_ACC_CNTL_3_WIN] = {
+ .base_hi_reg = MV64x60_PCI0_ACC_CNTL_3_BASE_HI,
+ .base_lo_reg = MV64x60_PCI0_ACC_CNTL_3_BASE_LO,
+ .size_reg = MV64x60_PCI0_ACC_CNTL_3_SIZE,
+ .base_lo_bits = 20,
+ .size_bits = 20,
+ .get_from_field = mv64x60_mask,
+ .map_to_field = mv64x60_mask,
+ .extra = MV64x60_EXTRA_PCIACC_ENAB | 0 },
+ /* PCI 1->MEM Access Control Windows */
+ [MV64x60_PCI12MEM_ACC_CNTL_0_WIN] = {
+ .base_hi_reg = MV64x60_PCI1_ACC_CNTL_0_BASE_HI,
+ .base_lo_reg = MV64x60_PCI1_ACC_CNTL_0_BASE_LO,
+ .size_reg = MV64x60_PCI1_ACC_CNTL_0_SIZE,
+ .base_lo_bits = 20,
+ .size_bits = 20,
+ .get_from_field = mv64x60_mask,
+ .map_to_field = mv64x60_mask,
+ .extra = MV64x60_EXTRA_PCIACC_ENAB | 0 },
+ [MV64x60_PCI12MEM_ACC_CNTL_1_WIN] = {
+ .base_hi_reg = MV64x60_PCI1_ACC_CNTL_1_BASE_HI,
+ .base_lo_reg = MV64x60_PCI1_ACC_CNTL_1_BASE_LO,
+ .size_reg = MV64x60_PCI1_ACC_CNTL_1_SIZE,
+ .base_lo_bits = 20,
+ .size_bits = 20,
+ .get_from_field = mv64x60_mask,
+ .map_to_field = mv64x60_mask,
+ .extra = MV64x60_EXTRA_PCIACC_ENAB | 0 },
+ [MV64x60_PCI12MEM_ACC_CNTL_2_WIN] = {
+ .base_hi_reg = MV64x60_PCI1_ACC_CNTL_2_BASE_HI,
+ .base_lo_reg = MV64x60_PCI1_ACC_CNTL_2_BASE_LO,
+ .size_reg = MV64x60_PCI1_ACC_CNTL_2_SIZE,
+ .base_lo_bits = 20,
+ .size_bits = 20,
+ .get_from_field = mv64x60_mask,
+ .map_to_field = mv64x60_mask,
+ .extra = MV64x60_EXTRA_PCIACC_ENAB | 0 },
+ [MV64x60_PCI12MEM_ACC_CNTL_3_WIN] = {
+ .base_hi_reg = MV64x60_PCI1_ACC_CNTL_3_BASE_HI,
+ .base_lo_reg = MV64x60_PCI1_ACC_CNTL_3_BASE_LO,
+ .size_reg = MV64x60_PCI1_ACC_CNTL_3_SIZE,
+ .base_lo_bits = 20,
+ .size_bits = 20,
+ .get_from_field = mv64x60_mask,
+ .map_to_field = mv64x60_mask,
+ .extra = MV64x60_EXTRA_PCIACC_ENAB | 0 },
+ /* PCI 0->MEM Snoop Windows -- don't exist on 64360 */
+ /* PCI 1->MEM Snoop Windows -- don't exist on 64360 */
+};
diff --git a/arch/ppc/syslib/ocp.c b/arch/ppc/syslib/ocp.c
new file mode 100644
index 0000000..a5156c5
--- /dev/null
+++ b/arch/ppc/syslib/ocp.c
@@ -0,0 +1,485 @@
+/*
+ * ocp.c
+ *
+ * (c) Benjamin Herrenschmidt (benh@kernel.crashing.org)
+ * Mipsys - France
+ *
+ * Derived from work (c) Armin Kuster akuster@pacbell.net
+ *
+ * Additional support and port to 2.6 LDM/sysfs by
+ * Matt Porter <mporter@kernel.crashing.org>
+ * Copyright 2004 MontaVista Software, Inc.
+ *
+ * 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.
+ *
+ * OCP (On Chip Peripheral) is a software emulated "bus" with a
+ * pseudo discovery method for dumb peripherals. Usually these type
+ * of peripherals are found on embedded SoC (System On a Chip)
+ * processors or highly integrated system controllers that have
+ * a host bridge and many peripherals. Common examples where
+ * this is already used include the PPC4xx, PPC85xx, MPC52xx,
+ * and MV64xxx parts.
+ *
+ * This subsystem creates a standard OCP bus type within the
+ * device model. The devices on the OCP bus are seeded by an
+ * an initial OCP device array created by the arch-specific
+ * Device entries can be added/removed/modified through OCP
+ * helper functions to accomodate system and board-specific
+ * parameters commonly found in embedded systems. OCP also
+ * provides a standard method for devices to describe extended
+ * attributes about themselves to the system. A standard access
+ * method allows OCP drivers to obtain the information, both
+ * SoC-specific and system/board-specific, needed for operation.
+ */
+
+#include <linux/module.h>
+#include <linux/config.h>
+#include <linux/list.h>
+#include <linux/miscdevice.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/pm.h>
+#include <linux/bootmem.h>
+#include <linux/device.h>
+
+#include <asm/io.h>
+#include <asm/ocp.h>
+#include <asm/errno.h>
+#include <asm/rwsem.h>
+#include <asm/semaphore.h>
+
+//#define DBG(x) printk x
+#define DBG(x)
+
+extern int mem_init_done;
+
+extern struct ocp_def core_ocp[]; /* Static list of devices, provided by
+ CPU core */
+
+LIST_HEAD(ocp_devices); /* List of all OCP devices */
+DECLARE_RWSEM(ocp_devices_sem); /* Global semaphores for those lists */
+
+static int ocp_inited;
+
+/* Sysfs support */
+#define OCP_DEF_ATTR(field, format_string) \
+static ssize_t \
+show_##field(struct device *dev, char *buf) \
+{ \
+ struct ocp_device *odev = to_ocp_dev(dev); \
+ \
+ return sprintf(buf, format_string, odev->def->field); \
+} \
+static DEVICE_ATTR(field, S_IRUGO, show_##field, NULL);
+
+OCP_DEF_ATTR(vendor, "0x%04x\n");
+OCP_DEF_ATTR(function, "0x%04x\n");
+OCP_DEF_ATTR(index, "0x%04x\n");
+#ifdef CONFIG_PTE_64BIT
+OCP_DEF_ATTR(paddr, "0x%016Lx\n");
+#else
+OCP_DEF_ATTR(paddr, "0x%08lx\n");
+#endif
+OCP_DEF_ATTR(irq, "%d\n");
+OCP_DEF_ATTR(pm, "%lu\n");
+
+void ocp_create_sysfs_dev_files(struct ocp_device *odev)
+{
+ struct device *dev = &odev->dev;
+
+ /* Current OCP device def attributes */
+ device_create_file(dev, &dev_attr_vendor);
+ device_create_file(dev, &dev_attr_function);
+ device_create_file(dev, &dev_attr_index);
+ device_create_file(dev, &dev_attr_paddr);
+ device_create_file(dev, &dev_attr_irq);
+ device_create_file(dev, &dev_attr_pm);
+ /* Current OCP device additions attributes */
+ if (odev->def->additions && odev->def->show)
+ odev->def->show(dev);
+}
+
+/**
+ * ocp_device_match - Match one driver to one device
+ * @drv: driver to match
+ * @dev: device to match
+ *
+ * This function returns 0 if the driver and device don't match
+ */
+static int
+ocp_device_match(struct device *dev, struct device_driver *drv)
+{
+ struct ocp_device *ocp_dev = to_ocp_dev(dev);
+ struct ocp_driver *ocp_drv = to_ocp_drv(drv);
+ const struct ocp_device_id *ids = ocp_drv->id_table;
+
+ if (!ids)
+ return 0;
+
+ while (ids->vendor || ids->function) {
+ if ((ids->vendor == OCP_ANY_ID
+ || ids->vendor == ocp_dev->def->vendor)
+ && (ids->function == OCP_ANY_ID
+ || ids->function == ocp_dev->def->function))
+ return 1;
+ ids++;
+ }
+ return 0;
+}
+
+static int
+ocp_device_probe(struct device *dev)
+{
+ int error = 0;
+ struct ocp_driver *drv;
+ struct ocp_device *ocp_dev;
+
+ drv = to_ocp_drv(dev->driver);
+ ocp_dev = to_ocp_dev(dev);
+
+ if (drv->probe) {
+ error = drv->probe(ocp_dev);
+ if (error >= 0) {
+ ocp_dev->driver = drv;
+ error = 0;
+ }
+ }
+ return error;
+}
+
+static int
+ocp_device_remove(struct device *dev)
+{
+ struct ocp_device *ocp_dev = to_ocp_dev(dev);
+
+ if (ocp_dev->driver) {
+ if (ocp_dev->driver->remove)
+ ocp_dev->driver->remove(ocp_dev);
+ ocp_dev->driver = NULL;
+ }
+ return 0;
+}
+
+static int
+ocp_device_suspend(struct device *dev, u32 state)
+{
+ struct ocp_device *ocp_dev = to_ocp_dev(dev);
+ struct ocp_driver *ocp_drv = to_ocp_drv(dev->driver);
+
+ if (dev->driver && ocp_drv->suspend)
+ return ocp_drv->suspend(ocp_dev, state);
+ return 0;
+}
+
+static int
+ocp_device_resume(struct device *dev)
+{
+ struct ocp_device *ocp_dev = to_ocp_dev(dev);
+ struct ocp_driver *ocp_drv = to_ocp_drv(dev->driver);
+
+ if (dev->driver && ocp_drv->resume)
+ return ocp_drv->resume(ocp_dev);
+ return 0;
+}
+
+struct bus_type ocp_bus_type = {
+ .name = "ocp",
+ .match = ocp_device_match,
+ .suspend = ocp_device_suspend,
+ .resume = ocp_device_resume,
+};
+
+/**
+ * ocp_register_driver - Register an OCP driver
+ * @drv: pointer to statically defined ocp_driver structure
+ *
+ * The driver's probe() callback is called either recursively
+ * by this function or upon later call of ocp_driver_init
+ *
+ * NOTE: Detection of devices is a 2 pass step on this implementation,
+ * hotswap isn't supported. First, all OCP devices are put in the device
+ * list, _then_ all drivers are probed on each match.
+ */
+int
+ocp_register_driver(struct ocp_driver *drv)
+{
+ /* initialize common driver fields */
+ drv->driver.name = drv->name;
+ drv->driver.bus = &ocp_bus_type;
+ drv->driver.probe = ocp_device_probe;
+ drv->driver.remove = ocp_device_remove;
+
+ /* register with core */
+ return driver_register(&drv->driver);
+}
+
+/**
+ * ocp_unregister_driver - Unregister an OCP driver
+ * @drv: pointer to statically defined ocp_driver structure
+ *
+ * The driver's remove() callback is called recursively
+ * by this function for any device already registered
+ */
+void
+ocp_unregister_driver(struct ocp_driver *drv)
+{
+ DBG(("ocp: ocp_unregister_driver(%s)...\n", drv->name));
+
+ driver_unregister(&drv->driver);
+
+ DBG(("ocp: ocp_unregister_driver(%s)... done.\n", drv->name));
+}
+
+/* Core of ocp_find_device(). Caller must hold ocp_devices_sem */
+static struct ocp_device *
+__ocp_find_device(unsigned int vendor, unsigned int function, int index)
+{
+ struct list_head *entry;
+ struct ocp_device *dev, *found = NULL;
+
+ DBG(("ocp: __ocp_find_device(vendor: %x, function: %x, index: %d)...\n", vendor, function, index));
+
+ list_for_each(entry, &ocp_devices) {
+ dev = list_entry(entry, struct ocp_device, link);
+ if (vendor != OCP_ANY_ID && vendor != dev->def->vendor)
+ continue;
+ if (function != OCP_ANY_ID && function != dev->def->function)
+ continue;
+ if (index != OCP_ANY_INDEX && index != dev->def->index)
+ continue;
+ found = dev;
+ break;
+ }
+
+ DBG(("ocp: __ocp_find_device(vendor: %x, function: %x, index: %d)... done\n", vendor, function, index));
+
+ return found;
+}
+
+/**
+ * ocp_find_device - Find a device by function & index
+ * @vendor: vendor ID of the device (or OCP_ANY_ID)
+ * @function: function code of the device (or OCP_ANY_ID)
+ * @idx: index of the device (or OCP_ANY_INDEX)
+ *
+ * This function allows a lookup of a given function by it's
+ * index, it's typically used to find the MAL or ZMII associated
+ * with an EMAC or similar horrors.
+ * You can pass vendor, though you usually want OCP_ANY_ID there...
+ */
+struct ocp_device *
+ocp_find_device(unsigned int vendor, unsigned int function, int index)
+{
+ struct ocp_device *dev;
+
+ down_read(&ocp_devices_sem);
+ dev = __ocp_find_device(vendor, function, index);
+ up_read(&ocp_devices_sem);
+
+ return dev;
+}
+
+/**
+ * ocp_get_one_device - Find a def by function & index
+ * @vendor: vendor ID of the device (or OCP_ANY_ID)
+ * @function: function code of the device (or OCP_ANY_ID)
+ * @idx: index of the device (or OCP_ANY_INDEX)
+ *
+ * This function allows a lookup of a given ocp_def by it's
+ * vendor, function, and index. The main purpose for is to
+ * allow modification of the def before binding to the driver
+ */
+struct ocp_def *
+ocp_get_one_device(unsigned int vendor, unsigned int function, int index)
+{
+ struct ocp_device *dev;
+ struct ocp_def *found = NULL;
+
+ DBG(("ocp: ocp_get_one_device(vendor: %x, function: %x, index: %d)...\n",
+ vendor, function, index));
+
+ dev = ocp_find_device(vendor, function, index);
+
+ if (dev)
+ found = dev->def;
+
+ DBG(("ocp: ocp_get_one_device(vendor: %x, function: %x, index: %d)... done.\n",
+ vendor, function, index));
+
+ return found;
+}
+
+/**
+ * ocp_add_one_device - Add a device
+ * @def: static device definition structure
+ *
+ * This function adds a device definition to the
+ * device list. It may only be called before
+ * ocp_driver_init() and will return an error
+ * otherwise.
+ */
+int
+ocp_add_one_device(struct ocp_def *def)
+{
+ struct ocp_device *dev;
+
+ DBG(("ocp: ocp_add_one_device()...\n"));
+
+ /* Can't be called after ocp driver init */
+ if (ocp_inited)
+ return 1;
+
+ if (mem_init_done)
+ dev = kmalloc(sizeof(*dev), GFP_KERNEL);
+ else
+ dev = alloc_bootmem(sizeof(*dev));
+
+ if (dev == NULL)
+ return 1;
+ memset(dev, 0, sizeof(*dev));
+ dev->def = def;
+ dev->current_state = 4;
+ sprintf(dev->name, "OCP device %04x:%04x:%04x",
+ dev->def->vendor, dev->def->function, dev->def->index);
+ down_write(&ocp_devices_sem);
+ list_add_tail(&dev->link, &ocp_devices);
+ up_write(&ocp_devices_sem);
+
+ DBG(("ocp: ocp_add_one_device()...done\n"));
+
+ return 0;
+}
+
+/**
+ * ocp_remove_one_device - Remove a device by function & index
+ * @vendor: vendor ID of the device (or OCP_ANY_ID)
+ * @function: function code of the device (or OCP_ANY_ID)
+ * @idx: index of the device (or OCP_ANY_INDEX)
+ *
+ * This function allows removal of a given function by its
+ * index. It may only be called before ocp_driver_init()
+ * and will return an error otherwise.
+ */
+int
+ocp_remove_one_device(unsigned int vendor, unsigned int function, int index)
+{
+ struct ocp_device *dev;
+
+ DBG(("ocp: ocp_remove_one_device(vendor: %x, function: %x, index: %d)...\n", vendor, function, index));
+
+ /* Can't be called after ocp driver init */
+ if (ocp_inited)
+ return 1;
+
+ down_write(&ocp_devices_sem);
+ dev = __ocp_find_device(vendor, function, index);
+ list_del((struct list_head *)dev);
+ up_write(&ocp_devices_sem);
+
+ DBG(("ocp: ocp_remove_one_device(vendor: %x, function: %x, index: %d)... done.\n", vendor, function, index));
+
+ return 0;
+}
+
+/**
+ * ocp_for_each_device - Iterate over OCP devices
+ * @callback: routine to execute for each ocp device.
+ * @arg: user data to be passed to callback routine.
+ *
+ * This routine holds the ocp_device semaphore, so the
+ * callback routine cannot modify the ocp_device list.
+ */
+void
+ocp_for_each_device(void(*callback)(struct ocp_device *, void *arg), void *arg)
+{
+ struct list_head *entry;
+
+ if (callback) {
+ down_read(&ocp_devices_sem);
+ list_for_each(entry, &ocp_devices)
+ callback(list_entry(entry, struct ocp_device, link),
+ arg);
+ up_read(&ocp_devices_sem);
+ }
+}
+
+/**
+ * ocp_early_init - Init OCP device management
+ *
+ * This function builds the list of devices before setup_arch.
+ * This allows platform code to modify the device lists before
+ * they are bound to drivers (changes to paddr, removing devices
+ * etc)
+ */
+int __init
+ocp_early_init(void)
+{
+ struct ocp_def *def;
+
+ DBG(("ocp: ocp_early_init()...\n"));
+
+ /* Fill the devices list */
+ for (def = core_ocp; def->vendor != OCP_VENDOR_INVALID; def++)
+ ocp_add_one_device(def);
+
+ DBG(("ocp: ocp_early_init()... done.\n"));
+
+ return 0;
+}
+
+/**
+ * ocp_driver_init - Init OCP device management
+ *
+ * This function is meant to be called via OCP bus registration.
+ */
+static int __init
+ocp_driver_init(void)
+{
+ int ret = 0, index = 0;
+ struct device *ocp_bus;
+ struct list_head *entry;
+ struct ocp_device *dev;
+
+ if (ocp_inited)
+ return ret;
+ ocp_inited = 1;
+
+ DBG(("ocp: ocp_driver_init()...\n"));
+
+ /* Allocate/register primary OCP bus */
+ ocp_bus = kmalloc(sizeof(struct device), GFP_KERNEL);
+ if (ocp_bus == NULL)
+ return 1;
+ memset(ocp_bus, 0, sizeof(struct device));
+ strcpy(ocp_bus->bus_id, "ocp");
+
+ bus_register(&ocp_bus_type);
+
+ device_register(ocp_bus);
+
+ /* Put each OCP device into global device list */
+ list_for_each(entry, &ocp_devices) {
+ dev = list_entry(entry, struct ocp_device, link);
+ sprintf(dev->dev.bus_id, "%2.2x", index);
+ dev->dev.parent = ocp_bus;
+ dev->dev.bus = &ocp_bus_type;
+ device_register(&dev->dev);
+ ocp_create_sysfs_dev_files(dev);
+ index++;
+ }
+
+ DBG(("ocp: ocp_driver_init()... done.\n"));
+
+ return 0;
+}
+
+postcore_initcall(ocp_driver_init);
+
+EXPORT_SYMBOL(ocp_bus_type);
+EXPORT_SYMBOL(ocp_find_device);
+EXPORT_SYMBOL(ocp_register_driver);
+EXPORT_SYMBOL(ocp_unregister_driver);
diff --git a/arch/ppc/syslib/of_device.c b/arch/ppc/syslib/of_device.c
new file mode 100644
index 0000000..46269ed
--- /dev/null
+++ b/arch/ppc/syslib/of_device.c
@@ -0,0 +1,273 @@
+#include <linux/config.h>
+#include <linux/string.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <asm/errno.h>
+#include <asm/of_device.h>
+
+/**
+ * of_match_device - Tell if an of_device structure has a matching
+ * of_match structure
+ * @ids: array of of device match structures to search in
+ * @dev: the of device structure to match against
+ *
+ * Used by a driver to check whether an of_device present in the
+ * system is in its list of supported devices.
+ */
+const struct of_match * of_match_device(const struct of_match *matches,
+ const struct of_device *dev)
+{
+ if (!dev->node)
+ return NULL;
+ while (matches->name || matches->type || matches->compatible) {
+ int match = 1;
+ if (matches->name && matches->name != OF_ANY_MATCH)
+ match &= dev->node->name
+ && !strcmp(matches->name, dev->node->name);
+ if (matches->type && matches->type != OF_ANY_MATCH)
+ match &= dev->node->type
+ && !strcmp(matches->type, dev->node->type);
+ if (matches->compatible && matches->compatible != OF_ANY_MATCH)
+ match &= device_is_compatible(dev->node,
+ matches->compatible);
+ if (match)
+ return matches;
+ matches++;
+ }
+ return NULL;
+}
+
+static int of_platform_bus_match(struct device *dev, struct device_driver *drv)
+{
+ struct of_device * of_dev = to_of_device(dev);
+ struct of_platform_driver * of_drv = to_of_platform_driver(drv);
+ const struct of_match * matches = of_drv->match_table;
+
+ if (!matches)
+ return 0;
+
+ return of_match_device(matches, of_dev) != NULL;
+}
+
+struct of_device *of_dev_get(struct of_device *dev)
+{
+ struct device *tmp;
+
+ if (!dev)
+ return NULL;
+ tmp = get_device(&dev->dev);
+ if (tmp)
+ return to_of_device(tmp);
+ else
+ return NULL;
+}
+
+void of_dev_put(struct of_device *dev)
+{
+ if (dev)
+ put_device(&dev->dev);
+}
+
+
+static int of_device_probe(struct device *dev)
+{
+ int error = -ENODEV;
+ struct of_platform_driver *drv;
+ struct of_device *of_dev;
+ const struct of_match *match;
+
+ drv = to_of_platform_driver(dev->driver);
+ of_dev = to_of_device(dev);
+
+ if (!drv->probe)
+ return error;
+
+ of_dev_get(of_dev);
+
+ match = of_match_device(drv->match_table, of_dev);
+ if (match)
+ error = drv->probe(of_dev, match);
+ if (error)
+ of_dev_put(of_dev);
+
+ return error;
+}
+
+static int of_device_remove(struct device *dev)
+{
+ struct of_device * of_dev = to_of_device(dev);
+ struct of_platform_driver * drv = to_of_platform_driver(dev->driver);
+
+ if (dev->driver && drv->remove)
+ drv->remove(of_dev);
+ return 0;
+}
+
+static int of_device_suspend(struct device *dev, u32 state)
+{
+ struct of_device * of_dev = to_of_device(dev);
+ struct of_platform_driver * drv = to_of_platform_driver(dev->driver);
+ int error = 0;
+
+ if (dev->driver && drv->suspend)
+ error = drv->suspend(of_dev, state);
+ return error;
+}
+
+static int of_device_resume(struct device * dev)
+{
+ struct of_device * of_dev = to_of_device(dev);
+ struct of_platform_driver * drv = to_of_platform_driver(dev->driver);
+ int error = 0;
+
+ if (dev->driver && drv->resume)
+ error = drv->resume(of_dev);
+ return error;
+}
+
+struct bus_type of_platform_bus_type = {
+ .name = "of_platform",
+ .match = of_platform_bus_match,
+ .suspend = of_device_suspend,
+ .resume = of_device_resume,
+};
+
+static int __init of_bus_driver_init(void)
+{
+ return bus_register(&of_platform_bus_type);
+}
+
+postcore_initcall(of_bus_driver_init);
+
+int of_register_driver(struct of_platform_driver *drv)
+{
+ int count = 0;
+
+ /* initialize common driver fields */
+ drv->driver.name = drv->name;
+ drv->driver.bus = &of_platform_bus_type;
+ drv->driver.probe = of_device_probe;
+ drv->driver.remove = of_device_remove;
+
+ /* register with core */
+ count = driver_register(&drv->driver);
+ return count ? count : 1;
+}
+
+void of_unregister_driver(struct of_platform_driver *drv)
+{
+ driver_unregister(&drv->driver);
+}
+
+
+static ssize_t dev_show_devspec(struct device *dev, char *buf)
+{
+ struct of_device *ofdev;
+
+ ofdev = to_of_device(dev);
+ return sprintf(buf, "%s", ofdev->node->full_name);
+}
+
+static DEVICE_ATTR(devspec, S_IRUGO, dev_show_devspec, NULL);
+
+/**
+ * of_release_dev - free an of device structure when all users of it are finished.
+ * @dev: device that's been disconnected
+ *
+ * Will be called only by the device core when all users of this of device are
+ * done.
+ */
+void of_release_dev(struct device *dev)
+{
+ struct of_device *ofdev;
+
+ ofdev = to_of_device(dev);
+ of_node_put(ofdev->node);
+ kfree(ofdev);
+}
+
+int of_device_register(struct of_device *ofdev)
+{
+ int rc;
+ struct of_device **odprop;
+
+ BUG_ON(ofdev->node == NULL);
+
+ odprop = (struct of_device **)get_property(ofdev->node, "linux,device", NULL);
+ if (!odprop) {
+ struct property *new_prop;
+
+ new_prop = kmalloc(sizeof(struct property) + sizeof(struct of_device *),
+ GFP_KERNEL);
+ if (new_prop == NULL)
+ return -ENOMEM;
+ new_prop->name = "linux,device";
+ new_prop->length = sizeof(sizeof(struct of_device *));
+ new_prop->value = (unsigned char *)&new_prop[1];
+ odprop = (struct of_device **)new_prop->value;
+ *odprop = NULL;
+ prom_add_property(ofdev->node, new_prop);
+ }
+ *odprop = ofdev;
+
+ rc = device_register(&ofdev->dev);
+ if (rc)
+ return rc;
+
+ device_create_file(&ofdev->dev, &dev_attr_devspec);
+
+ return 0;
+}
+
+void of_device_unregister(struct of_device *ofdev)
+{
+ struct of_device **odprop;
+
+ device_remove_file(&ofdev->dev, &dev_attr_devspec);
+
+ odprop = (struct of_device **)get_property(ofdev->node, "linux,device", NULL);
+ if (odprop)
+ *odprop = NULL;
+
+ device_unregister(&ofdev->dev);
+}
+
+struct of_device* of_platform_device_create(struct device_node *np, const char *bus_id)
+{
+ struct of_device *dev;
+ u32 *reg;
+
+ dev = kmalloc(sizeof(*dev), GFP_KERNEL);
+ if (!dev)
+ return NULL;
+ memset(dev, 0, sizeof(*dev));
+
+ dev->node = of_node_get(np);
+ dev->dma_mask = 0xffffffffUL;
+ dev->dev.dma_mask = &dev->dma_mask;
+ dev->dev.parent = NULL;
+ dev->dev.bus = &of_platform_bus_type;
+ dev->dev.release = of_release_dev;
+
+ reg = (u32 *)get_property(np, "reg", NULL);
+ strlcpy(dev->dev.bus_id, bus_id, BUS_ID_SIZE);
+
+ if (of_device_register(dev) != 0) {
+ kfree(dev);
+ return NULL;
+ }
+
+ return dev;
+}
+
+EXPORT_SYMBOL(of_match_device);
+EXPORT_SYMBOL(of_platform_bus_type);
+EXPORT_SYMBOL(of_register_driver);
+EXPORT_SYMBOL(of_unregister_driver);
+EXPORT_SYMBOL(of_device_register);
+EXPORT_SYMBOL(of_device_unregister);
+EXPORT_SYMBOL(of_dev_get);
+EXPORT_SYMBOL(of_dev_put);
+EXPORT_SYMBOL(of_platform_device_create);
+EXPORT_SYMBOL(of_release_dev);
diff --git a/arch/ppc/syslib/open_pic.c b/arch/ppc/syslib/open_pic.c
new file mode 100644
index 0000000..406f36a
--- /dev/null
+++ b/arch/ppc/syslib/open_pic.c
@@ -0,0 +1,1083 @@
+/*
+ * arch/ppc/kernel/open_pic.c -- OpenPIC Interrupt Handling
+ *
+ * Copyright (C) 1997 Geert Uytterhoeven
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file COPYING in the main directory of this archive
+ * for more details.
+ */
+
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <linux/sysdev.h>
+#include <linux/errno.h>
+#include <asm/ptrace.h>
+#include <asm/signal.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/prom.h>
+#include <asm/sections.h>
+#include <asm/open_pic.h>
+#include <asm/i8259.h>
+
+#include "open_pic_defs.h"
+
+#if defined(CONFIG_PRPMC800) || defined(CONFIG_85xx)
+#define OPENPIC_BIG_ENDIAN
+#endif
+
+void __iomem *OpenPIC_Addr;
+static volatile struct OpenPIC __iomem *OpenPIC = NULL;
+
+/*
+ * We define OpenPIC_InitSenses table thusly:
+ * bit 0x1: sense, 0 for edge and 1 for level.
+ * bit 0x2: polarity, 0 for negative, 1 for positive.
+ */
+u_int OpenPIC_NumInitSenses __initdata = 0;
+u_char *OpenPIC_InitSenses __initdata = NULL;
+extern int use_of_interrupt_tree;
+
+static u_int NumProcessors;
+static u_int NumSources;
+static int open_pic_irq_offset;
+static volatile OpenPIC_Source __iomem *ISR[NR_IRQS];
+static int openpic_cascade_irq = -1;
+static int (*openpic_cascade_fn)(struct pt_regs *);
+
+/* Global Operations */
+static void openpic_disable_8259_pass_through(void);
+static void openpic_set_spurious(u_int vector);
+
+#ifdef CONFIG_SMP
+/* Interprocessor Interrupts */
+static void openpic_initipi(u_int ipi, u_int pri, u_int vector);
+static irqreturn_t openpic_ipi_action(int cpl, void *dev_id, struct pt_regs *);
+#endif
+
+/* Timer Interrupts */
+static void openpic_inittimer(u_int timer, u_int pri, u_int vector);
+static void openpic_maptimer(u_int timer, cpumask_t cpumask);
+
+/* Interrupt Sources */
+static void openpic_enable_irq(u_int irq);
+static void openpic_disable_irq(u_int irq);
+static void openpic_initirq(u_int irq, u_int pri, u_int vector, int polarity,
+ int is_level);
+static void openpic_mapirq(u_int irq, cpumask_t cpumask, cpumask_t keepmask);
+
+/*
+ * These functions are not used but the code is kept here
+ * for completeness and future reference.
+ */
+#ifdef notused
+static void openpic_enable_8259_pass_through(void);
+static u_int openpic_get_priority(void);
+static u_int openpic_get_spurious(void);
+static void openpic_set_sense(u_int irq, int sense);
+#endif /* notused */
+
+/*
+ * Description of the openpic for the higher-level irq code
+ */
+static void openpic_end_irq(unsigned int irq_nr);
+static void openpic_ack_irq(unsigned int irq_nr);
+static void openpic_set_affinity(unsigned int irq_nr, cpumask_t cpumask);
+
+struct hw_interrupt_type open_pic = {
+ .typename = " OpenPIC ",
+ .enable = openpic_enable_irq,
+ .disable = openpic_disable_irq,
+ .ack = openpic_ack_irq,
+ .end = openpic_end_irq,
+ .set_affinity = openpic_set_affinity,
+};
+
+#ifdef CONFIG_SMP
+static void openpic_end_ipi(unsigned int irq_nr);
+static void openpic_ack_ipi(unsigned int irq_nr);
+static void openpic_enable_ipi(unsigned int irq_nr);
+static void openpic_disable_ipi(unsigned int irq_nr);
+
+struct hw_interrupt_type open_pic_ipi = {
+ .typename = " OpenPIC ",
+ .enable = openpic_enable_ipi,
+ .disable = openpic_disable_ipi,
+ .ack = openpic_ack_ipi,
+ .end = openpic_end_ipi,
+};
+#endif /* CONFIG_SMP */
+
+/*
+ * Accesses to the current processor's openpic registers
+ */
+#ifdef CONFIG_SMP
+#define THIS_CPU Processor[cpu]
+#define DECL_THIS_CPU int cpu = smp_hw_index[smp_processor_id()]
+#define CHECK_THIS_CPU check_arg_cpu(cpu)
+#else
+#define THIS_CPU Processor[0]
+#define DECL_THIS_CPU
+#define CHECK_THIS_CPU
+#endif /* CONFIG_SMP */
+
+#if 1
+#define check_arg_ipi(ipi) \
+ if (ipi < 0 || ipi >= OPENPIC_NUM_IPI) \
+ printk("open_pic.c:%d: invalid ipi %d\n", __LINE__, ipi);
+#define check_arg_timer(timer) \
+ if (timer < 0 || timer >= OPENPIC_NUM_TIMERS) \
+ printk("open_pic.c:%d: invalid timer %d\n", __LINE__, timer);
+#define check_arg_vec(vec) \
+ if (vec < 0 || vec >= OPENPIC_NUM_VECTORS) \
+ printk("open_pic.c:%d: invalid vector %d\n", __LINE__, vec);
+#define check_arg_pri(pri) \
+ if (pri < 0 || pri >= OPENPIC_NUM_PRI) \
+ printk("open_pic.c:%d: invalid priority %d\n", __LINE__, pri);
+/*
+ * Print out a backtrace if it's out of range, since if it's larger than NR_IRQ's
+ * data has probably been corrupted and we're going to panic or deadlock later
+ * anyway --Troy
+ */
+#define check_arg_irq(irq) \
+ if (irq < open_pic_irq_offset || irq >= NumSources+open_pic_irq_offset \
+ || ISR[irq - open_pic_irq_offset] == 0) { \
+ printk("open_pic.c:%d: invalid irq %d\n", __LINE__, irq); \
+ dump_stack(); }
+#define check_arg_cpu(cpu) \
+ if (cpu < 0 || cpu >= NumProcessors){ \
+ printk("open_pic.c:%d: invalid cpu %d\n", __LINE__, cpu); \
+ dump_stack(); }
+#else
+#define check_arg_ipi(ipi) do {} while (0)
+#define check_arg_timer(timer) do {} while (0)
+#define check_arg_vec(vec) do {} while (0)
+#define check_arg_pri(pri) do {} while (0)
+#define check_arg_irq(irq) do {} while (0)
+#define check_arg_cpu(cpu) do {} while (0)
+#endif
+
+u_int openpic_read(volatile u_int __iomem *addr)
+{
+ u_int val;
+
+#ifdef OPENPIC_BIG_ENDIAN
+ val = in_be32(addr);
+#else
+ val = in_le32(addr);
+#endif
+ return val;
+}
+
+static inline void openpic_write(volatile u_int __iomem *addr, u_int val)
+{
+#ifdef OPENPIC_BIG_ENDIAN
+ out_be32(addr, val);
+#else
+ out_le32(addr, val);
+#endif
+}
+
+static inline u_int openpic_readfield(volatile u_int __iomem *addr, u_int mask)
+{
+ u_int val = openpic_read(addr);
+ return val & mask;
+}
+
+inline void openpic_writefield(volatile u_int __iomem *addr, u_int mask,
+ u_int field)
+{
+ u_int val = openpic_read(addr);
+ openpic_write(addr, (val & ~mask) | (field & mask));
+}
+
+static inline void openpic_clearfield(volatile u_int __iomem *addr, u_int mask)
+{
+ openpic_writefield(addr, mask, 0);
+}
+
+static inline void openpic_setfield(volatile u_int __iomem *addr, u_int mask)
+{
+ openpic_writefield(addr, mask, mask);
+}
+
+static void openpic_safe_writefield(volatile u_int __iomem *addr, u_int mask,
+ u_int field)
+{
+ openpic_setfield(addr, OPENPIC_MASK);
+ while (openpic_read(addr) & OPENPIC_ACTIVITY);
+ openpic_writefield(addr, mask | OPENPIC_MASK, field | OPENPIC_MASK);
+}
+
+#ifdef CONFIG_SMP
+/* yes this is right ... bug, feature, you decide! -- tgall */
+u_int openpic_read_IPI(volatile u_int __iomem * addr)
+{
+ u_int val = 0;
+#if defined(OPENPIC_BIG_ENDIAN) || defined(CONFIG_POWER3)
+ val = in_be32(addr);
+#else
+ val = in_le32(addr);
+#endif
+ return val;
+}
+
+/* because of the power3 be / le above, this is needed */
+inline void openpic_writefield_IPI(volatile u_int __iomem * addr, u_int mask, u_int field)
+{
+ u_int val = openpic_read_IPI(addr);
+ openpic_write(addr, (val & ~mask) | (field & mask));
+}
+
+static inline void openpic_clearfield_IPI(volatile u_int __iomem *addr, u_int mask)
+{
+ openpic_writefield_IPI(addr, mask, 0);
+}
+
+static inline void openpic_setfield_IPI(volatile u_int __iomem *addr, u_int mask)
+{
+ openpic_writefield_IPI(addr, mask, mask);
+}
+
+static void openpic_safe_writefield_IPI(volatile u_int __iomem *addr, u_int mask, u_int field)
+{
+ openpic_setfield_IPI(addr, OPENPIC_MASK);
+
+ /* wait until it's not in use */
+ /* BenH: Is this code really enough ? I would rather check the result
+ * and eventually retry ...
+ */
+ while(openpic_read_IPI(addr) & OPENPIC_ACTIVITY);
+
+ openpic_writefield_IPI(addr, mask | OPENPIC_MASK, field | OPENPIC_MASK);
+}
+#endif /* CONFIG_SMP */
+
+#ifdef CONFIG_EPIC_SERIAL_MODE
+/* On platforms that may use EPIC serial mode, the default is enabled. */
+int epic_serial_mode = 1;
+
+static void __init openpic_eicr_set_clk(u_int clkval)
+{
+ openpic_writefield(&OpenPIC->Global.Global_Configuration1,
+ OPENPIC_EICR_S_CLK_MASK, (clkval << 28));
+}
+
+static void __init openpic_enable_sie(void)
+{
+ openpic_setfield(&OpenPIC->Global.Global_Configuration1,
+ OPENPIC_EICR_SIE);
+}
+#endif
+
+#if defined(CONFIG_EPIC_SERIAL_MODE) || defined(CONFIG_PM)
+static void openpic_reset(void)
+{
+ openpic_setfield(&OpenPIC->Global.Global_Configuration0,
+ OPENPIC_CONFIG_RESET);
+ while (openpic_readfield(&OpenPIC->Global.Global_Configuration0,
+ OPENPIC_CONFIG_RESET))
+ mb();
+}
+#endif
+
+void __init openpic_set_sources(int first_irq, int num_irqs, void __iomem *first_ISR)
+{
+ volatile OpenPIC_Source __iomem *src = first_ISR;
+ int i, last_irq;
+
+ last_irq = first_irq + num_irqs;
+ if (last_irq > NumSources)
+ NumSources = last_irq;
+ if (src == 0)
+ src = &((struct OpenPIC __iomem *)OpenPIC_Addr)->Source[first_irq];
+ for (i = first_irq; i < last_irq; ++i, ++src)
+ ISR[i] = src;
+}
+
+/*
+ * The `offset' parameter defines where the interrupts handled by the
+ * OpenPIC start in the space of interrupt numbers that the kernel knows
+ * about. In other words, the OpenPIC's IRQ0 is numbered `offset' in the
+ * kernel's interrupt numbering scheme.
+ * We assume there is only one OpenPIC.
+ */
+void __init openpic_init(int offset)
+{
+ u_int t, i;
+ u_int timerfreq;
+ const char *version;
+
+ if (!OpenPIC_Addr) {
+ printk("No OpenPIC found !\n");
+ return;
+ }
+ OpenPIC = (volatile struct OpenPIC __iomem *)OpenPIC_Addr;
+
+#ifdef CONFIG_EPIC_SERIAL_MODE
+ /* Have to start from ground zero.
+ */
+ openpic_reset();
+#endif
+
+ if (ppc_md.progress) ppc_md.progress("openpic: enter", 0x122);
+
+ t = openpic_read(&OpenPIC->Global.Feature_Reporting0);
+ switch (t & OPENPIC_FEATURE_VERSION_MASK) {
+ case 1:
+ version = "1.0";
+ break;
+ case 2:
+ version = "1.2";
+ break;
+ case 3:
+ version = "1.3";
+ break;
+ default:
+ version = "?";
+ break;
+ }
+ NumProcessors = ((t & OPENPIC_FEATURE_LAST_PROCESSOR_MASK) >>
+ OPENPIC_FEATURE_LAST_PROCESSOR_SHIFT) + 1;
+ if (NumSources == 0)
+ openpic_set_sources(0,
+ ((t & OPENPIC_FEATURE_LAST_SOURCE_MASK) >>
+ OPENPIC_FEATURE_LAST_SOURCE_SHIFT) + 1,
+ NULL);
+ printk("OpenPIC Version %s (%d CPUs and %d IRQ sources) at %p\n",
+ version, NumProcessors, NumSources, OpenPIC);
+ timerfreq = openpic_read(&OpenPIC->Global.Timer_Frequency);
+ if (timerfreq)
+ printk("OpenPIC timer frequency is %d.%06d MHz\n",
+ timerfreq / 1000000, timerfreq % 1000000);
+
+ open_pic_irq_offset = offset;
+
+ /* Initialize timer interrupts */
+ if ( ppc_md.progress ) ppc_md.progress("openpic: timer",0x3ba);
+ for (i = 0; i < OPENPIC_NUM_TIMERS; i++) {
+ /* Disabled, Priority 0 */
+ openpic_inittimer(i, 0, OPENPIC_VEC_TIMER+i+offset);
+ /* No processor */
+ openpic_maptimer(i, CPU_MASK_NONE);
+ }
+
+#ifdef CONFIG_SMP
+ /* Initialize IPI interrupts */
+ if ( ppc_md.progress ) ppc_md.progress("openpic: ipi",0x3bb);
+ for (i = 0; i < OPENPIC_NUM_IPI; i++) {
+ /* Disabled, Priority 10..13 */
+ openpic_initipi(i, 10+i, OPENPIC_VEC_IPI+i+offset);
+ /* IPIs are per-CPU */
+ irq_desc[OPENPIC_VEC_IPI+i+offset].status |= IRQ_PER_CPU;
+ irq_desc[OPENPIC_VEC_IPI+i+offset].handler = &open_pic_ipi;
+ }
+#endif
+
+ /* Initialize external interrupts */
+ if (ppc_md.progress) ppc_md.progress("openpic: external",0x3bc);
+
+ openpic_set_priority(0xf);
+
+ /* Init all external sources, including possibly the cascade. */
+ for (i = 0; i < NumSources; i++) {
+ int sense;
+
+ if (ISR[i] == 0)
+ continue;
+
+ /* the bootloader may have left it enabled (bad !) */
+ openpic_disable_irq(i+offset);
+
+ sense = (i < OpenPIC_NumInitSenses)? OpenPIC_InitSenses[i]: \
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE);
+
+ if (sense & IRQ_SENSE_MASK)
+ irq_desc[i+offset].status = IRQ_LEVEL;
+
+ /* Enabled, Priority 8 */
+ openpic_initirq(i, 8, i+offset, (sense & IRQ_POLARITY_MASK),
+ (sense & IRQ_SENSE_MASK));
+ /* Processor 0 */
+ openpic_mapirq(i, CPU_MASK_CPU0, CPU_MASK_NONE);
+ }
+
+ /* Init descriptors */
+ for (i = offset; i < NumSources + offset; i++)
+ irq_desc[i].handler = &open_pic;
+
+ /* Initialize the spurious interrupt */
+ if (ppc_md.progress) ppc_md.progress("openpic: spurious",0x3bd);
+ openpic_set_spurious(OPENPIC_VEC_SPURIOUS);
+ openpic_disable_8259_pass_through();
+#ifdef CONFIG_EPIC_SERIAL_MODE
+ if (epic_serial_mode) {
+ openpic_eicr_set_clk(7); /* Slowest value until we know better */
+ openpic_enable_sie();
+ }
+#endif
+ openpic_set_priority(0);
+
+ if (ppc_md.progress) ppc_md.progress("openpic: exit",0x222);
+}
+
+#ifdef notused
+static void openpic_enable_8259_pass_through(void)
+{
+ openpic_clearfield(&OpenPIC->Global.Global_Configuration0,
+ OPENPIC_CONFIG_8259_PASSTHROUGH_DISABLE);
+}
+#endif /* notused */
+
+static void openpic_disable_8259_pass_through(void)
+{
+ openpic_setfield(&OpenPIC->Global.Global_Configuration0,
+ OPENPIC_CONFIG_8259_PASSTHROUGH_DISABLE);
+}
+
+/*
+ * Find out the current interrupt
+ */
+u_int openpic_irq(void)
+{
+ u_int vec;
+ DECL_THIS_CPU;
+
+ CHECK_THIS_CPU;
+ vec = openpic_readfield(&OpenPIC->THIS_CPU.Interrupt_Acknowledge,
+ OPENPIC_VECTOR_MASK);
+ return vec;
+}
+
+void openpic_eoi(void)
+{
+ DECL_THIS_CPU;
+
+ CHECK_THIS_CPU;
+ openpic_write(&OpenPIC->THIS_CPU.EOI, 0);
+ /* Handle PCI write posting */
+ (void)openpic_read(&OpenPIC->THIS_CPU.EOI);
+}
+
+#ifdef notused
+static u_int openpic_get_priority(void)
+{
+ DECL_THIS_CPU;
+
+ CHECK_THIS_CPU;
+ return openpic_readfield(&OpenPIC->THIS_CPU.Current_Task_Priority,
+ OPENPIC_CURRENT_TASK_PRIORITY_MASK);
+}
+#endif /* notused */
+
+void openpic_set_priority(u_int pri)
+{
+ DECL_THIS_CPU;
+
+ CHECK_THIS_CPU;
+ check_arg_pri(pri);
+ openpic_writefield(&OpenPIC->THIS_CPU.Current_Task_Priority,
+ OPENPIC_CURRENT_TASK_PRIORITY_MASK, pri);
+}
+
+/*
+ * Get/set the spurious vector
+ */
+#ifdef notused
+static u_int openpic_get_spurious(void)
+{
+ return openpic_readfield(&OpenPIC->Global.Spurious_Vector,
+ OPENPIC_VECTOR_MASK);
+}
+#endif /* notused */
+
+static void openpic_set_spurious(u_int vec)
+{
+ check_arg_vec(vec);
+ openpic_writefield(&OpenPIC->Global.Spurious_Vector, OPENPIC_VECTOR_MASK,
+ vec);
+}
+
+#ifdef CONFIG_SMP
+/*
+ * Convert a cpu mask from logical to physical cpu numbers.
+ */
+static inline cpumask_t physmask(cpumask_t cpumask)
+{
+ int i;
+ cpumask_t mask = CPU_MASK_NONE;
+
+ cpus_and(cpumask, cpu_online_map, cpumask);
+
+ for (i = 0; i < NR_CPUS; i++)
+ if (cpu_isset(i, cpumask))
+ cpu_set(smp_hw_index[i], mask);
+
+ return mask;
+}
+#else
+#define physmask(cpumask) (cpumask)
+#endif
+
+void openpic_reset_processor_phys(u_int mask)
+{
+ openpic_write(&OpenPIC->Global.Processor_Initialization, mask);
+}
+
+#if defined(CONFIG_SMP) || defined(CONFIG_PM)
+static DEFINE_SPINLOCK(openpic_setup_lock);
+#endif
+
+#ifdef CONFIG_SMP
+/*
+ * Initialize an interprocessor interrupt (and disable it)
+ *
+ * ipi: OpenPIC interprocessor interrupt number
+ * pri: interrupt source priority
+ * vec: the vector it will produce
+ */
+static void __init openpic_initipi(u_int ipi, u_int pri, u_int vec)
+{
+ check_arg_ipi(ipi);
+ check_arg_pri(pri);
+ check_arg_vec(vec);
+ openpic_safe_writefield_IPI(&OpenPIC->Global.IPI_Vector_Priority(ipi),
+ OPENPIC_PRIORITY_MASK | OPENPIC_VECTOR_MASK,
+ (pri << OPENPIC_PRIORITY_SHIFT) | vec);
+}
+
+/*
+ * Send an IPI to one or more CPUs
+ *
+ * Externally called, however, it takes an IPI number (0...OPENPIC_NUM_IPI)
+ * and not a system-wide interrupt number
+ */
+void openpic_cause_IPI(u_int ipi, cpumask_t cpumask)
+{
+ cpumask_t phys;
+ DECL_THIS_CPU;
+
+ CHECK_THIS_CPU;
+ check_arg_ipi(ipi);
+ phys = physmask(cpumask);
+ openpic_write(&OpenPIC->THIS_CPU.IPI_Dispatch(ipi),
+ cpus_addr(physmask(cpumask))[0]);
+}
+
+void openpic_request_IPIs(void)
+{
+ int i;
+
+ /*
+ * Make sure this matches what is defined in smp.c for
+ * smp_message_{pass|recv}() or what shows up in
+ * /proc/interrupts will be wrong!!! --Troy */
+
+ if (OpenPIC == NULL)
+ return;
+
+ /* IPIs are marked SA_INTERRUPT as they must run with irqs disabled */
+ request_irq(OPENPIC_VEC_IPI+open_pic_irq_offset,
+ openpic_ipi_action, SA_INTERRUPT,
+ "IPI0 (call function)", NULL);
+ request_irq(OPENPIC_VEC_IPI+open_pic_irq_offset+1,
+ openpic_ipi_action, SA_INTERRUPT,
+ "IPI1 (reschedule)", NULL);
+ request_irq(OPENPIC_VEC_IPI+open_pic_irq_offset+2,
+ openpic_ipi_action, SA_INTERRUPT,
+ "IPI2 (invalidate tlb)", NULL);
+ request_irq(OPENPIC_VEC_IPI+open_pic_irq_offset+3,
+ openpic_ipi_action, SA_INTERRUPT,
+ "IPI3 (xmon break)", NULL);
+
+ for ( i = 0; i < OPENPIC_NUM_IPI ; i++ )
+ openpic_enable_ipi(OPENPIC_VEC_IPI+open_pic_irq_offset+i);
+}
+
+/*
+ * Do per-cpu setup for SMP systems.
+ *
+ * Get IPI's working and start taking interrupts.
+ * -- Cort
+ */
+
+void __devinit do_openpic_setup_cpu(void)
+{
+#ifdef CONFIG_IRQ_ALL_CPUS
+ int i;
+ cpumask_t msk = CPU_MASK_NONE;
+#endif
+ spin_lock(&openpic_setup_lock);
+
+#ifdef CONFIG_IRQ_ALL_CPUS
+ cpu_set(smp_hw_index[smp_processor_id()], msk);
+
+ /* let the openpic know we want intrs. default affinity
+ * is 0xffffffff until changed via /proc
+ * That's how it's done on x86. If we want it differently, then
+ * we should make sure we also change the default values of irq_affinity
+ * in irq.c.
+ */
+ for (i = 0; i < NumSources; i++)
+ openpic_mapirq(i, msk, CPU_MASK_ALL);
+#endif /* CONFIG_IRQ_ALL_CPUS */
+ openpic_set_priority(0);
+
+ spin_unlock(&openpic_setup_lock);
+}
+#endif /* CONFIG_SMP */
+
+/*
+ * Initialize a timer interrupt (and disable it)
+ *
+ * timer: OpenPIC timer number
+ * pri: interrupt source priority
+ * vec: the vector it will produce
+ */
+static void __init openpic_inittimer(u_int timer, u_int pri, u_int vec)
+{
+ check_arg_timer(timer);
+ check_arg_pri(pri);
+ check_arg_vec(vec);
+ openpic_safe_writefield(&OpenPIC->Global.Timer[timer].Vector_Priority,
+ OPENPIC_PRIORITY_MASK | OPENPIC_VECTOR_MASK,
+ (pri << OPENPIC_PRIORITY_SHIFT) | vec);
+}
+
+/*
+ * Map a timer interrupt to one or more CPUs
+ */
+static void __init openpic_maptimer(u_int timer, cpumask_t cpumask)
+{
+ cpumask_t phys = physmask(cpumask);
+ check_arg_timer(timer);
+ openpic_write(&OpenPIC->Global.Timer[timer].Destination,
+ cpus_addr(phys)[0]);
+}
+
+/*
+ * Initalize the interrupt source which will generate an NMI.
+ * This raises the interrupt's priority from 8 to 9.
+ *
+ * irq: The logical IRQ which generates an NMI.
+ */
+void __init
+openpic_init_nmi_irq(u_int irq)
+{
+ check_arg_irq(irq);
+ openpic_safe_writefield(&ISR[irq - open_pic_irq_offset]->Vector_Priority,
+ OPENPIC_PRIORITY_MASK,
+ 9 << OPENPIC_PRIORITY_SHIFT);
+}
+
+/*
+ *
+ * All functions below take an offset'ed irq argument
+ *
+ */
+
+/*
+ * Hookup a cascade to the OpenPIC.
+ */
+
+static struct irqaction openpic_cascade_irqaction = {
+ .handler = no_action,
+ .flags = SA_INTERRUPT,
+ .mask = CPU_MASK_NONE,
+};
+
+void __init
+openpic_hookup_cascade(u_int irq, char *name,
+ int (*cascade_fn)(struct pt_regs *))
+{
+ openpic_cascade_irq = irq;
+ openpic_cascade_fn = cascade_fn;
+
+ if (setup_irq(irq, &openpic_cascade_irqaction))
+ printk("Unable to get OpenPIC IRQ %d for cascade\n",
+ irq - open_pic_irq_offset);
+}
+
+/*
+ * Enable/disable an external interrupt source
+ *
+ * Externally called, irq is an offseted system-wide interrupt number
+ */
+static void openpic_enable_irq(u_int irq)
+{
+ volatile u_int __iomem *vpp;
+
+ check_arg_irq(irq);
+ vpp = &ISR[irq - open_pic_irq_offset]->Vector_Priority;
+ openpic_clearfield(vpp, OPENPIC_MASK);
+ /* make sure mask gets to controller before we return to user */
+ do {
+ mb(); /* sync is probably useless here */
+ } while (openpic_readfield(vpp, OPENPIC_MASK));
+}
+
+static void openpic_disable_irq(u_int irq)
+{
+ volatile u_int __iomem *vpp;
+ u32 vp;
+
+ check_arg_irq(irq);
+ vpp = &ISR[irq - open_pic_irq_offset]->Vector_Priority;
+ openpic_setfield(vpp, OPENPIC_MASK);
+ /* make sure mask gets to controller before we return to user */
+ do {
+ mb(); /* sync is probably useless here */
+ vp = openpic_readfield(vpp, OPENPIC_MASK | OPENPIC_ACTIVITY);
+ } while((vp & OPENPIC_ACTIVITY) && !(vp & OPENPIC_MASK));
+}
+
+#ifdef CONFIG_SMP
+/*
+ * Enable/disable an IPI interrupt source
+ *
+ * Externally called, irq is an offseted system-wide interrupt number
+ */
+void openpic_enable_ipi(u_int irq)
+{
+ irq -= (OPENPIC_VEC_IPI+open_pic_irq_offset);
+ check_arg_ipi(irq);
+ openpic_clearfield_IPI(&OpenPIC->Global.IPI_Vector_Priority(irq), OPENPIC_MASK);
+
+}
+
+void openpic_disable_ipi(u_int irq)
+{
+ irq -= (OPENPIC_VEC_IPI+open_pic_irq_offset);
+ check_arg_ipi(irq);
+ openpic_setfield_IPI(&OpenPIC->Global.IPI_Vector_Priority(irq), OPENPIC_MASK);
+}
+#endif
+
+/*
+ * Initialize an interrupt source (and disable it!)
+ *
+ * irq: OpenPIC interrupt number
+ * pri: interrupt source priority
+ * vec: the vector it will produce
+ * pol: polarity (1 for positive, 0 for negative)
+ * sense: 1 for level, 0 for edge
+ */
+static void __init
+openpic_initirq(u_int irq, u_int pri, u_int vec, int pol, int sense)
+{
+ openpic_safe_writefield(&ISR[irq]->Vector_Priority,
+ OPENPIC_PRIORITY_MASK | OPENPIC_VECTOR_MASK |
+ OPENPIC_SENSE_MASK | OPENPIC_POLARITY_MASK,
+ (pri << OPENPIC_PRIORITY_SHIFT) | vec |
+ (pol ? OPENPIC_POLARITY_POSITIVE :
+ OPENPIC_POLARITY_NEGATIVE) |
+ (sense ? OPENPIC_SENSE_LEVEL : OPENPIC_SENSE_EDGE));
+}
+
+/*
+ * Map an interrupt source to one or more CPUs
+ */
+static void openpic_mapirq(u_int irq, cpumask_t physmask, cpumask_t keepmask)
+{
+ if (ISR[irq] == 0)
+ return;
+ if (!cpus_empty(keepmask)) {
+ cpumask_t irqdest = { .bits[0] = openpic_read(&ISR[irq]->Destination) };
+ cpus_and(irqdest, irqdest, keepmask);
+ cpus_or(physmask, physmask, irqdest);
+ }
+ openpic_write(&ISR[irq]->Destination, cpus_addr(physmask)[0]);
+}
+
+#ifdef notused
+/*
+ * Set the sense for an interrupt source (and disable it!)
+ *
+ * sense: 1 for level, 0 for edge
+ */
+static void openpic_set_sense(u_int irq, int sense)
+{
+ if (ISR[irq] != 0)
+ openpic_safe_writefield(&ISR[irq]->Vector_Priority,
+ OPENPIC_SENSE_LEVEL,
+ (sense ? OPENPIC_SENSE_LEVEL : 0));
+}
+#endif /* notused */
+
+/* No spinlocks, should not be necessary with the OpenPIC
+ * (1 register = 1 interrupt and we have the desc lock).
+ */
+static void openpic_ack_irq(unsigned int irq_nr)
+{
+#ifdef __SLOW_VERSION__
+ openpic_disable_irq(irq_nr);
+ openpic_eoi();
+#else
+ if ((irq_desc[irq_nr].status & IRQ_LEVEL) == 0)
+ openpic_eoi();
+#endif
+}
+
+static void openpic_end_irq(unsigned int irq_nr)
+{
+#ifdef __SLOW_VERSION__
+ if (!(irq_desc[irq_nr].status & (IRQ_DISABLED|IRQ_INPROGRESS))
+ && irq_desc[irq_nr].action)
+ openpic_enable_irq(irq_nr);
+#else
+ if ((irq_desc[irq_nr].status & IRQ_LEVEL) != 0)
+ openpic_eoi();
+#endif
+}
+
+static void openpic_set_affinity(unsigned int irq_nr, cpumask_t cpumask)
+{
+ openpic_mapirq(irq_nr - open_pic_irq_offset, physmask(cpumask), CPU_MASK_NONE);
+}
+
+#ifdef CONFIG_SMP
+static void openpic_ack_ipi(unsigned int irq_nr)
+{
+ openpic_eoi();
+}
+
+static void openpic_end_ipi(unsigned int irq_nr)
+{
+}
+
+static irqreturn_t openpic_ipi_action(int cpl, void *dev_id, struct pt_regs *regs)
+{
+ smp_message_recv(cpl-OPENPIC_VEC_IPI-open_pic_irq_offset, regs);
+ return IRQ_HANDLED;
+}
+
+#endif /* CONFIG_SMP */
+
+int
+openpic_get_irq(struct pt_regs *regs)
+{
+ int irq = openpic_irq();
+
+ /*
+ * Check for the cascade interrupt and call the cascaded
+ * interrupt controller function (usually i8259_irq) if so.
+ * This should move to irq.c eventually. -- paulus
+ */
+ if (irq == openpic_cascade_irq && openpic_cascade_fn != NULL) {
+ int cirq = openpic_cascade_fn(regs);
+
+ /* Allow for the cascade being shared with other devices */
+ if (cirq != -1) {
+ irq = cirq;
+ openpic_eoi();
+ }
+ } else if (irq == OPENPIC_VEC_SPURIOUS)
+ irq = -1;
+ return irq;
+}
+
+#ifdef CONFIG_SMP
+void
+smp_openpic_message_pass(int target, int msg, unsigned long data, int wait)
+{
+ cpumask_t mask = CPU_MASK_ALL;
+ /* make sure we're sending something that translates to an IPI */
+ if (msg > 0x3) {
+ printk("SMP %d: smp_message_pass: unknown msg %d\n",
+ smp_processor_id(), msg);
+ return;
+ }
+ switch (target) {
+ case MSG_ALL:
+ openpic_cause_IPI(msg, mask);
+ break;
+ case MSG_ALL_BUT_SELF:
+ cpu_clear(smp_processor_id(), mask);
+ openpic_cause_IPI(msg, mask);
+ break;
+ default:
+ openpic_cause_IPI(msg, cpumask_of_cpu(target));
+ break;
+ }
+}
+#endif /* CONFIG_SMP */
+
+#ifdef CONFIG_PM
+
+/*
+ * We implement the IRQ controller as a sysdev and put it
+ * to sleep at powerdown stage (the callback is named suspend,
+ * but it's old semantics, for the Device Model, it's really
+ * powerdown). The possible problem is that another sysdev that
+ * happens to be suspend after this one will have interrupts off,
+ * that may be an issue... For now, this isn't an issue on pmac
+ * though...
+ */
+
+static u32 save_ipi_vp[OPENPIC_NUM_IPI];
+static u32 save_irq_src_vp[OPENPIC_MAX_SOURCES];
+static u32 save_irq_src_dest[OPENPIC_MAX_SOURCES];
+static u32 save_cpu_task_pri[OPENPIC_MAX_PROCESSORS];
+static int openpic_suspend_count;
+
+static void openpic_cached_enable_irq(u_int irq)
+{
+ check_arg_irq(irq);
+ save_irq_src_vp[irq - open_pic_irq_offset] &= ~OPENPIC_MASK;
+}
+
+static void openpic_cached_disable_irq(u_int irq)
+{
+ check_arg_irq(irq);
+ save_irq_src_vp[irq - open_pic_irq_offset] |= OPENPIC_MASK;
+}
+
+/* WARNING: Can be called directly by the cpufreq code with NULL parameter,
+ * we need something better to deal with that... Maybe switch to S1 for
+ * cpufreq changes
+ */
+int openpic_suspend(struct sys_device *sysdev, u32 state)
+{
+ int i;
+ unsigned long flags;
+
+ spin_lock_irqsave(&openpic_setup_lock, flags);
+
+ if (openpic_suspend_count++ > 0) {
+ spin_unlock_irqrestore(&openpic_setup_lock, flags);
+ return 0;
+ }
+
+ openpic_set_priority(0xf);
+
+ open_pic.enable = openpic_cached_enable_irq;
+ open_pic.disable = openpic_cached_disable_irq;
+
+ for (i=0; i<NumProcessors; i++) {
+ save_cpu_task_pri[i] = openpic_read(&OpenPIC->Processor[i].Current_Task_Priority);
+ openpic_writefield(&OpenPIC->Processor[i].Current_Task_Priority,
+ OPENPIC_CURRENT_TASK_PRIORITY_MASK, 0xf);
+ }
+
+ for (i=0; i<OPENPIC_NUM_IPI; i++)
+ save_ipi_vp[i] = openpic_read(&OpenPIC->Global.IPI_Vector_Priority(i));
+ for (i=0; i<NumSources; i++) {
+ if (ISR[i] == 0)
+ continue;
+ save_irq_src_vp[i] = openpic_read(&ISR[i]->Vector_Priority) & ~OPENPIC_ACTIVITY;
+ save_irq_src_dest[i] = openpic_read(&ISR[i]->Destination);
+ }
+
+ spin_unlock_irqrestore(&openpic_setup_lock, flags);
+
+ return 0;
+}
+
+/* WARNING: Can be called directly by the cpufreq code with NULL parameter,
+ * we need something better to deal with that... Maybe switch to S1 for
+ * cpufreq changes
+ */
+int openpic_resume(struct sys_device *sysdev)
+{
+ int i;
+ unsigned long flags;
+ u32 vppmask = OPENPIC_PRIORITY_MASK | OPENPIC_VECTOR_MASK |
+ OPENPIC_SENSE_MASK | OPENPIC_POLARITY_MASK |
+ OPENPIC_MASK;
+
+ spin_lock_irqsave(&openpic_setup_lock, flags);
+
+ if ((--openpic_suspend_count) > 0) {
+ spin_unlock_irqrestore(&openpic_setup_lock, flags);
+ return 0;
+ }
+
+ openpic_reset();
+
+ /* OpenPIC sometimes seem to need some time to be fully back up... */
+ do {
+ openpic_set_spurious(OPENPIC_VEC_SPURIOUS);
+ } while(openpic_readfield(&OpenPIC->Global.Spurious_Vector, OPENPIC_VECTOR_MASK)
+ != OPENPIC_VEC_SPURIOUS);
+
+ openpic_disable_8259_pass_through();
+
+ for (i=0; i<OPENPIC_NUM_IPI; i++)
+ openpic_write(&OpenPIC->Global.IPI_Vector_Priority(i),
+ save_ipi_vp[i]);
+ for (i=0; i<NumSources; i++) {
+ if (ISR[i] == 0)
+ continue;
+ openpic_write(&ISR[i]->Destination, save_irq_src_dest[i]);
+ openpic_write(&ISR[i]->Vector_Priority, save_irq_src_vp[i]);
+ /* make sure mask gets to controller before we return to user */
+ do {
+ openpic_write(&ISR[i]->Vector_Priority, save_irq_src_vp[i]);
+ } while (openpic_readfield(&ISR[i]->Vector_Priority, vppmask)
+ != (save_irq_src_vp[i] & vppmask));
+ }
+ for (i=0; i<NumProcessors; i++)
+ openpic_write(&OpenPIC->Processor[i].Current_Task_Priority,
+ save_cpu_task_pri[i]);
+
+ open_pic.enable = openpic_enable_irq;
+ open_pic.disable = openpic_disable_irq;
+
+ openpic_set_priority(0);
+
+ spin_unlock_irqrestore(&openpic_setup_lock, flags);
+
+ return 0;
+}
+
+#endif /* CONFIG_PM */
+
+static struct sysdev_class openpic_sysclass = {
+ set_kset_name("openpic"),
+};
+
+static struct sys_device device_openpic = {
+ .id = 0,
+ .cls = &openpic_sysclass,
+};
+
+static struct sysdev_driver driver_openpic = {
+#ifdef CONFIG_PM
+ .suspend = &openpic_suspend,
+ .resume = &openpic_resume,
+#endif /* CONFIG_PM */
+};
+
+static int __init init_openpic_sysfs(void)
+{
+ int rc;
+
+ if (!OpenPIC_Addr)
+ return -ENODEV;
+ printk(KERN_DEBUG "Registering openpic with sysfs...\n");
+ rc = sysdev_class_register(&openpic_sysclass);
+ if (rc) {
+ printk(KERN_ERR "Failed registering openpic sys class\n");
+ return -ENODEV;
+ }
+ rc = sysdev_register(&device_openpic);
+ if (rc) {
+ printk(KERN_ERR "Failed registering openpic sys device\n");
+ return -ENODEV;
+ }
+ rc = sysdev_driver_register(&openpic_sysclass, &driver_openpic);
+ if (rc) {
+ printk(KERN_ERR "Failed registering openpic sys driver\n");
+ return -ENODEV;
+ }
+ return 0;
+}
+
+subsys_initcall(init_openpic_sysfs);
+
diff --git a/arch/ppc/syslib/open_pic2.c b/arch/ppc/syslib/open_pic2.c
new file mode 100644
index 0000000..ea26da0
--- /dev/null
+++ b/arch/ppc/syslib/open_pic2.c
@@ -0,0 +1,716 @@
+/*
+ * arch/ppc/kernel/open_pic.c -- OpenPIC Interrupt Handling
+ *
+ * Copyright (C) 1997 Geert Uytterhoeven
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file COPYING in the main directory of this archive
+ * for more details.
+ *
+ * This is a duplicate of open_pic.c that deals with U3s MPIC on
+ * G5 PowerMacs. It's the same file except it's using big endian
+ * register accesses
+ */
+
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <linux/sysdev.h>
+#include <linux/errno.h>
+#include <asm/ptrace.h>
+#include <asm/signal.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/prom.h>
+#include <asm/sections.h>
+#include <asm/open_pic.h>
+#include <asm/i8259.h>
+
+#include "open_pic_defs.h"
+
+void *OpenPIC2_Addr;
+static volatile struct OpenPIC *OpenPIC2 = NULL;
+/*
+ * We define OpenPIC_InitSenses table thusly:
+ * bit 0x1: sense, 0 for edge and 1 for level.
+ * bit 0x2: polarity, 0 for negative, 1 for positive.
+ */
+extern u_int OpenPIC_NumInitSenses;
+extern u_char *OpenPIC_InitSenses;
+extern int use_of_interrupt_tree;
+
+static u_int NumProcessors;
+static u_int NumSources;
+static int open_pic2_irq_offset;
+static volatile OpenPIC_Source *ISR[NR_IRQS];
+
+/* Global Operations */
+static void openpic2_disable_8259_pass_through(void);
+static void openpic2_set_priority(u_int pri);
+static void openpic2_set_spurious(u_int vector);
+
+/* Timer Interrupts */
+static void openpic2_inittimer(u_int timer, u_int pri, u_int vector);
+static void openpic2_maptimer(u_int timer, u_int cpumask);
+
+/* Interrupt Sources */
+static void openpic2_enable_irq(u_int irq);
+static void openpic2_disable_irq(u_int irq);
+static void openpic2_initirq(u_int irq, u_int pri, u_int vector, int polarity,
+ int is_level);
+static void openpic2_mapirq(u_int irq, u_int cpumask, u_int keepmask);
+
+/*
+ * These functions are not used but the code is kept here
+ * for completeness and future reference.
+ */
+static void openpic2_reset(void);
+#ifdef notused
+static void openpic2_enable_8259_pass_through(void);
+static u_int openpic2_get_priority(void);
+static u_int openpic2_get_spurious(void);
+static void openpic2_set_sense(u_int irq, int sense);
+#endif /* notused */
+
+/*
+ * Description of the openpic for the higher-level irq code
+ */
+static void openpic2_end_irq(unsigned int irq_nr);
+static void openpic2_ack_irq(unsigned int irq_nr);
+
+struct hw_interrupt_type open_pic2 = {
+ " OpenPIC2 ",
+ NULL,
+ NULL,
+ openpic2_enable_irq,
+ openpic2_disable_irq,
+ openpic2_ack_irq,
+ openpic2_end_irq,
+};
+
+/*
+ * Accesses to the current processor's openpic registers
+ * On cascaded controller, this is only CPU 0
+ */
+#define THIS_CPU Processor[0]
+#define DECL_THIS_CPU
+#define CHECK_THIS_CPU
+
+#if 1
+#define check_arg_ipi(ipi) \
+ if (ipi < 0 || ipi >= OPENPIC_NUM_IPI) \
+ printk("open_pic.c:%d: illegal ipi %d\n", __LINE__, ipi);
+#define check_arg_timer(timer) \
+ if (timer < 0 || timer >= OPENPIC_NUM_TIMERS) \
+ printk("open_pic.c:%d: illegal timer %d\n", __LINE__, timer);
+#define check_arg_vec(vec) \
+ if (vec < 0 || vec >= OPENPIC_NUM_VECTORS) \
+ printk("open_pic.c:%d: illegal vector %d\n", __LINE__, vec);
+#define check_arg_pri(pri) \
+ if (pri < 0 || pri >= OPENPIC_NUM_PRI) \
+ printk("open_pic.c:%d: illegal priority %d\n", __LINE__, pri);
+/*
+ * Print out a backtrace if it's out of range, since if it's larger than NR_IRQ's
+ * data has probably been corrupted and we're going to panic or deadlock later
+ * anyway --Troy
+ */
+extern unsigned long* _get_SP(void);
+#define check_arg_irq(irq) \
+ if (irq < open_pic2_irq_offset || irq >= NumSources+open_pic2_irq_offset \
+ || ISR[irq - open_pic2_irq_offset] == 0) { \
+ printk("open_pic.c:%d: illegal irq %d\n", __LINE__, irq); \
+ /*print_backtrace(_get_SP());*/ }
+#define check_arg_cpu(cpu) \
+ if (cpu < 0 || cpu >= NumProcessors){ \
+ printk("open_pic2.c:%d: illegal cpu %d\n", __LINE__, cpu); \
+ /*print_backtrace(_get_SP());*/ }
+#else
+#define check_arg_ipi(ipi) do {} while (0)
+#define check_arg_timer(timer) do {} while (0)
+#define check_arg_vec(vec) do {} while (0)
+#define check_arg_pri(pri) do {} while (0)
+#define check_arg_irq(irq) do {} while (0)
+#define check_arg_cpu(cpu) do {} while (0)
+#endif
+
+static u_int openpic2_read(volatile u_int *addr)
+{
+ u_int val;
+
+ val = in_be32(addr);
+ return val;
+}
+
+static inline void openpic2_write(volatile u_int *addr, u_int val)
+{
+ out_be32(addr, val);
+}
+
+static inline u_int openpic2_readfield(volatile u_int *addr, u_int mask)
+{
+ u_int val = openpic2_read(addr);
+ return val & mask;
+}
+
+inline void openpic2_writefield(volatile u_int *addr, u_int mask,
+ u_int field)
+{
+ u_int val = openpic2_read(addr);
+ openpic2_write(addr, (val & ~mask) | (field & mask));
+}
+
+static inline void openpic2_clearfield(volatile u_int *addr, u_int mask)
+{
+ openpic2_writefield(addr, mask, 0);
+}
+
+static inline void openpic2_setfield(volatile u_int *addr, u_int mask)
+{
+ openpic2_writefield(addr, mask, mask);
+}
+
+static void openpic2_safe_writefield(volatile u_int *addr, u_int mask,
+ u_int field)
+{
+ openpic2_setfield(addr, OPENPIC_MASK);
+ while (openpic2_read(addr) & OPENPIC_ACTIVITY);
+ openpic2_writefield(addr, mask | OPENPIC_MASK, field | OPENPIC_MASK);
+}
+
+static void openpic2_reset(void)
+{
+ openpic2_setfield(&OpenPIC2->Global.Global_Configuration0,
+ OPENPIC_CONFIG_RESET);
+ while (openpic2_readfield(&OpenPIC2->Global.Global_Configuration0,
+ OPENPIC_CONFIG_RESET))
+ mb();
+}
+
+void __init openpic2_set_sources(int first_irq, int num_irqs, void *first_ISR)
+{
+ volatile OpenPIC_Source *src = first_ISR;
+ int i, last_irq;
+
+ last_irq = first_irq + num_irqs;
+ if (last_irq > NumSources)
+ NumSources = last_irq;
+ if (src == 0)
+ src = &((struct OpenPIC *)OpenPIC2_Addr)->Source[first_irq];
+ for (i = first_irq; i < last_irq; ++i, ++src)
+ ISR[i] = src;
+}
+
+/*
+ * The `offset' parameter defines where the interrupts handled by the
+ * OpenPIC start in the space of interrupt numbers that the kernel knows
+ * about. In other words, the OpenPIC's IRQ0 is numbered `offset' in the
+ * kernel's interrupt numbering scheme.
+ * We assume there is only one OpenPIC.
+ */
+void __init openpic2_init(int offset)
+{
+ u_int t, i;
+ u_int timerfreq;
+ const char *version;
+
+ if (!OpenPIC2_Addr) {
+ printk("No OpenPIC2 found !\n");
+ return;
+ }
+ OpenPIC2 = (volatile struct OpenPIC *)OpenPIC2_Addr;
+
+ if (ppc_md.progress) ppc_md.progress("openpic: enter", 0x122);
+
+ t = openpic2_read(&OpenPIC2->Global.Feature_Reporting0);
+ switch (t & OPENPIC_FEATURE_VERSION_MASK) {
+ case 1:
+ version = "1.0";
+ break;
+ case 2:
+ version = "1.2";
+ break;
+ case 3:
+ version = "1.3";
+ break;
+ default:
+ version = "?";
+ break;
+ }
+ NumProcessors = ((t & OPENPIC_FEATURE_LAST_PROCESSOR_MASK) >>
+ OPENPIC_FEATURE_LAST_PROCESSOR_SHIFT) + 1;
+ if (NumSources == 0)
+ openpic2_set_sources(0,
+ ((t & OPENPIC_FEATURE_LAST_SOURCE_MASK) >>
+ OPENPIC_FEATURE_LAST_SOURCE_SHIFT) + 1,
+ NULL);
+ printk("OpenPIC (2) Version %s (%d CPUs and %d IRQ sources) at %p\n",
+ version, NumProcessors, NumSources, OpenPIC2);
+ timerfreq = openpic2_read(&OpenPIC2->Global.Timer_Frequency);
+ if (timerfreq)
+ printk("OpenPIC timer frequency is %d.%06d MHz\n",
+ timerfreq / 1000000, timerfreq % 1000000);
+
+ open_pic2_irq_offset = offset;
+
+ /* Initialize timer interrupts */
+ if ( ppc_md.progress ) ppc_md.progress("openpic2: timer",0x3ba);
+ for (i = 0; i < OPENPIC_NUM_TIMERS; i++) {
+ /* Disabled, Priority 0 */
+ openpic2_inittimer(i, 0, OPENPIC2_VEC_TIMER+i+offset);
+ /* No processor */
+ openpic2_maptimer(i, 0);
+ }
+
+ /* Initialize external interrupts */
+ if (ppc_md.progress) ppc_md.progress("openpic2: external",0x3bc);
+
+ openpic2_set_priority(0xf);
+
+ /* Init all external sources, including possibly the cascade. */
+ for (i = 0; i < NumSources; i++) {
+ int sense;
+
+ if (ISR[i] == 0)
+ continue;
+
+ /* the bootloader may have left it enabled (bad !) */
+ openpic2_disable_irq(i+offset);
+
+ sense = (i < OpenPIC_NumInitSenses)? OpenPIC_InitSenses[i]: \
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE);
+
+ if (sense & IRQ_SENSE_MASK)
+ irq_desc[i+offset].status = IRQ_LEVEL;
+
+ /* Enabled, Priority 8 */
+ openpic2_initirq(i, 8, i+offset, (sense & IRQ_POLARITY_MASK),
+ (sense & IRQ_SENSE_MASK));
+ /* Processor 0 */
+ openpic2_mapirq(i, 1<<0, 0);
+ }
+
+ /* Init descriptors */
+ for (i = offset; i < NumSources + offset; i++)
+ irq_desc[i].handler = &open_pic2;
+
+ /* Initialize the spurious interrupt */
+ if (ppc_md.progress) ppc_md.progress("openpic2: spurious",0x3bd);
+ openpic2_set_spurious(OPENPIC2_VEC_SPURIOUS+offset);
+
+ openpic2_disable_8259_pass_through();
+ openpic2_set_priority(0);
+
+ if (ppc_md.progress) ppc_md.progress("openpic2: exit",0x222);
+}
+
+#ifdef notused
+static void openpic2_enable_8259_pass_through(void)
+{
+ openpic2_clearfield(&OpenPIC2->Global.Global_Configuration0,
+ OPENPIC_CONFIG_8259_PASSTHROUGH_DISABLE);
+}
+#endif /* notused */
+
+/* This can't be __init, it is used in openpic_sleep_restore_intrs */
+static void openpic2_disable_8259_pass_through(void)
+{
+ openpic2_setfield(&OpenPIC2->Global.Global_Configuration0,
+ OPENPIC_CONFIG_8259_PASSTHROUGH_DISABLE);
+}
+
+/*
+ * Find out the current interrupt
+ */
+u_int openpic2_irq(void)
+{
+ u_int vec;
+ DECL_THIS_CPU;
+
+ CHECK_THIS_CPU;
+ vec = openpic2_readfield(&OpenPIC2->THIS_CPU.Interrupt_Acknowledge,
+ OPENPIC_VECTOR_MASK);
+ return vec;
+}
+
+void openpic2_eoi(void)
+{
+ DECL_THIS_CPU;
+
+ CHECK_THIS_CPU;
+ openpic2_write(&OpenPIC2->THIS_CPU.EOI, 0);
+ /* Handle PCI write posting */
+ (void)openpic2_read(&OpenPIC2->THIS_CPU.EOI);
+}
+
+#ifdef notused
+static u_int openpic2_get_priority(void)
+{
+ DECL_THIS_CPU;
+
+ CHECK_THIS_CPU;
+ return openpic2_readfield(&OpenPIC2->THIS_CPU.Current_Task_Priority,
+ OPENPIC_CURRENT_TASK_PRIORITY_MASK);
+}
+#endif /* notused */
+
+static void __init openpic2_set_priority(u_int pri)
+{
+ DECL_THIS_CPU;
+
+ CHECK_THIS_CPU;
+ check_arg_pri(pri);
+ openpic2_writefield(&OpenPIC2->THIS_CPU.Current_Task_Priority,
+ OPENPIC_CURRENT_TASK_PRIORITY_MASK, pri);
+}
+
+/*
+ * Get/set the spurious vector
+ */
+#ifdef notused
+static u_int openpic2_get_spurious(void)
+{
+ return openpic2_readfield(&OpenPIC2->Global.Spurious_Vector,
+ OPENPIC_VECTOR_MASK);
+}
+#endif /* notused */
+
+/* This can't be __init, it is used in openpic_sleep_restore_intrs */
+static void openpic2_set_spurious(u_int vec)
+{
+ check_arg_vec(vec);
+ openpic2_writefield(&OpenPIC2->Global.Spurious_Vector, OPENPIC_VECTOR_MASK,
+ vec);
+}
+
+static DEFINE_SPINLOCK(openpic2_setup_lock);
+
+/*
+ * Initialize a timer interrupt (and disable it)
+ *
+ * timer: OpenPIC timer number
+ * pri: interrupt source priority
+ * vec: the vector it will produce
+ */
+static void __init openpic2_inittimer(u_int timer, u_int pri, u_int vec)
+{
+ check_arg_timer(timer);
+ check_arg_pri(pri);
+ check_arg_vec(vec);
+ openpic2_safe_writefield(&OpenPIC2->Global.Timer[timer].Vector_Priority,
+ OPENPIC_PRIORITY_MASK | OPENPIC_VECTOR_MASK,
+ (pri << OPENPIC_PRIORITY_SHIFT) | vec);
+}
+
+/*
+ * Map a timer interrupt to one or more CPUs
+ */
+static void __init openpic2_maptimer(u_int timer, u_int cpumask)
+{
+ check_arg_timer(timer);
+ openpic2_write(&OpenPIC2->Global.Timer[timer].Destination,
+ cpumask);
+}
+
+/*
+ * Initalize the interrupt source which will generate an NMI.
+ * This raises the interrupt's priority from 8 to 9.
+ *
+ * irq: The logical IRQ which generates an NMI.
+ */
+void __init
+openpic2_init_nmi_irq(u_int irq)
+{
+ check_arg_irq(irq);
+ openpic2_safe_writefield(&ISR[irq - open_pic2_irq_offset]->Vector_Priority,
+ OPENPIC_PRIORITY_MASK,
+ 9 << OPENPIC_PRIORITY_SHIFT);
+}
+
+/*
+ *
+ * All functions below take an offset'ed irq argument
+ *
+ */
+
+
+/*
+ * Enable/disable an external interrupt source
+ *
+ * Externally called, irq is an offseted system-wide interrupt number
+ */
+static void openpic2_enable_irq(u_int irq)
+{
+ volatile u_int *vpp;
+
+ check_arg_irq(irq);
+ vpp = &ISR[irq - open_pic2_irq_offset]->Vector_Priority;
+ openpic2_clearfield(vpp, OPENPIC_MASK);
+ /* make sure mask gets to controller before we return to user */
+ do {
+ mb(); /* sync is probably useless here */
+ } while (openpic2_readfield(vpp, OPENPIC_MASK));
+}
+
+static void openpic2_disable_irq(u_int irq)
+{
+ volatile u_int *vpp;
+ u32 vp;
+
+ check_arg_irq(irq);
+ vpp = &ISR[irq - open_pic2_irq_offset]->Vector_Priority;
+ openpic2_setfield(vpp, OPENPIC_MASK);
+ /* make sure mask gets to controller before we return to user */
+ do {
+ mb(); /* sync is probably useless here */
+ vp = openpic2_readfield(vpp, OPENPIC_MASK | OPENPIC_ACTIVITY);
+ } while((vp & OPENPIC_ACTIVITY) && !(vp & OPENPIC_MASK));
+}
+
+
+/*
+ * Initialize an interrupt source (and disable it!)
+ *
+ * irq: OpenPIC interrupt number
+ * pri: interrupt source priority
+ * vec: the vector it will produce
+ * pol: polarity (1 for positive, 0 for negative)
+ * sense: 1 for level, 0 for edge
+ */
+static void __init
+openpic2_initirq(u_int irq, u_int pri, u_int vec, int pol, int sense)
+{
+ openpic2_safe_writefield(&ISR[irq]->Vector_Priority,
+ OPENPIC_PRIORITY_MASK | OPENPIC_VECTOR_MASK |
+ OPENPIC_SENSE_MASK | OPENPIC_POLARITY_MASK,
+ (pri << OPENPIC_PRIORITY_SHIFT) | vec |
+ (pol ? OPENPIC_POLARITY_POSITIVE :
+ OPENPIC_POLARITY_NEGATIVE) |
+ (sense ? OPENPIC_SENSE_LEVEL : OPENPIC_SENSE_EDGE));
+}
+
+/*
+ * Map an interrupt source to one or more CPUs
+ */
+static void openpic2_mapirq(u_int irq, u_int physmask, u_int keepmask)
+{
+ if (ISR[irq] == 0)
+ return;
+ if (keepmask != 0)
+ physmask |= openpic2_read(&ISR[irq]->Destination) & keepmask;
+ openpic2_write(&ISR[irq]->Destination, physmask);
+}
+
+#ifdef notused
+/*
+ * Set the sense for an interrupt source (and disable it!)
+ *
+ * sense: 1 for level, 0 for edge
+ */
+static void openpic2_set_sense(u_int irq, int sense)
+{
+ if (ISR[irq] != 0)
+ openpic2_safe_writefield(&ISR[irq]->Vector_Priority,
+ OPENPIC_SENSE_LEVEL,
+ (sense ? OPENPIC_SENSE_LEVEL : 0));
+}
+#endif /* notused */
+
+/* No spinlocks, should not be necessary with the OpenPIC
+ * (1 register = 1 interrupt and we have the desc lock).
+ */
+static void openpic2_ack_irq(unsigned int irq_nr)
+{
+ openpic2_disable_irq(irq_nr);
+ openpic2_eoi();
+}
+
+static void openpic2_end_irq(unsigned int irq_nr)
+{
+ if (!(irq_desc[irq_nr].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
+ openpic2_enable_irq(irq_nr);
+}
+
+int
+openpic2_get_irq(struct pt_regs *regs)
+{
+ int irq = openpic2_irq();
+
+ if (irq == (OPENPIC2_VEC_SPURIOUS + open_pic2_irq_offset))
+ irq = -1;
+ return irq;
+}
+
+#ifdef CONFIG_PM
+
+/*
+ * We implement the IRQ controller as a sysdev and put it
+ * to sleep at powerdown stage (the callback is named suspend,
+ * but it's old semantics, for the Device Model, it's really
+ * powerdown). The possible problem is that another sysdev that
+ * happens to be suspend after this one will have interrupts off,
+ * that may be an issue... For now, this isn't an issue on pmac
+ * though...
+ */
+
+static u32 save_ipi_vp[OPENPIC_NUM_IPI];
+static u32 save_irq_src_vp[OPENPIC_MAX_SOURCES];
+static u32 save_irq_src_dest[OPENPIC_MAX_SOURCES];
+static u32 save_cpu_task_pri[OPENPIC_MAX_PROCESSORS];
+static int openpic_suspend_count;
+
+static void openpic2_cached_enable_irq(u_int irq)
+{
+ check_arg_irq(irq);
+ save_irq_src_vp[irq - open_pic2_irq_offset] &= ~OPENPIC_MASK;
+}
+
+static void openpic2_cached_disable_irq(u_int irq)
+{
+ check_arg_irq(irq);
+ save_irq_src_vp[irq - open_pic2_irq_offset] |= OPENPIC_MASK;
+}
+
+/* WARNING: Can be called directly by the cpufreq code with NULL parameter,
+ * we need something better to deal with that... Maybe switch to S1 for
+ * cpufreq changes
+ */
+int openpic2_suspend(struct sys_device *sysdev, u32 state)
+{
+ int i;
+ unsigned long flags;
+
+ spin_lock_irqsave(&openpic2_setup_lock, flags);
+
+ if (openpic_suspend_count++ > 0) {
+ spin_unlock_irqrestore(&openpic2_setup_lock, flags);
+ return 0;
+ }
+
+ open_pic2.enable = openpic2_cached_enable_irq;
+ open_pic2.disable = openpic2_cached_disable_irq;
+
+ for (i=0; i<NumProcessors; i++) {
+ save_cpu_task_pri[i] = openpic2_read(&OpenPIC2->Processor[i].Current_Task_Priority);
+ openpic2_writefield(&OpenPIC2->Processor[i].Current_Task_Priority,
+ OPENPIC_CURRENT_TASK_PRIORITY_MASK, 0xf);
+ }
+
+ for (i=0; i<OPENPIC_NUM_IPI; i++)
+ save_ipi_vp[i] = openpic2_read(&OpenPIC2->Global.IPI_Vector_Priority(i));
+ for (i=0; i<NumSources; i++) {
+ if (ISR[i] == 0)
+ continue;
+ save_irq_src_vp[i] = openpic2_read(&ISR[i]->Vector_Priority) & ~OPENPIC_ACTIVITY;
+ save_irq_src_dest[i] = openpic2_read(&ISR[i]->Destination);
+ }
+
+ spin_unlock_irqrestore(&openpic2_setup_lock, flags);
+
+ return 0;
+}
+
+/* WARNING: Can be called directly by the cpufreq code with NULL parameter,
+ * we need something better to deal with that... Maybe switch to S1 for
+ * cpufreq changes
+ */
+int openpic2_resume(struct sys_device *sysdev)
+{
+ int i;
+ unsigned long flags;
+ u32 vppmask = OPENPIC_PRIORITY_MASK | OPENPIC_VECTOR_MASK |
+ OPENPIC_SENSE_MASK | OPENPIC_POLARITY_MASK |
+ OPENPIC_MASK;
+
+ spin_lock_irqsave(&openpic2_setup_lock, flags);
+
+ if ((--openpic_suspend_count) > 0) {
+ spin_unlock_irqrestore(&openpic2_setup_lock, flags);
+ return 0;
+ }
+
+ openpic2_reset();
+
+ /* OpenPIC sometimes seem to need some time to be fully back up... */
+ do {
+ openpic2_set_spurious(OPENPIC2_VEC_SPURIOUS+open_pic2_irq_offset);
+ } while(openpic2_readfield(&OpenPIC2->Global.Spurious_Vector, OPENPIC_VECTOR_MASK)
+ != (OPENPIC2_VEC_SPURIOUS + open_pic2_irq_offset));
+
+ openpic2_disable_8259_pass_through();
+
+ for (i=0; i<OPENPIC_NUM_IPI; i++)
+ openpic2_write(&OpenPIC2->Global.IPI_Vector_Priority(i),
+ save_ipi_vp[i]);
+ for (i=0; i<NumSources; i++) {
+ if (ISR[i] == 0)
+ continue;
+ openpic2_write(&ISR[i]->Destination, save_irq_src_dest[i]);
+ openpic2_write(&ISR[i]->Vector_Priority, save_irq_src_vp[i]);
+ /* make sure mask gets to controller before we return to user */
+ do {
+ openpic2_write(&ISR[i]->Vector_Priority, save_irq_src_vp[i]);
+ } while (openpic2_readfield(&ISR[i]->Vector_Priority, vppmask)
+ != (save_irq_src_vp[i] & vppmask));
+ }
+ for (i=0; i<NumProcessors; i++)
+ openpic2_write(&OpenPIC2->Processor[i].Current_Task_Priority,
+ save_cpu_task_pri[i]);
+
+ open_pic2.enable = openpic2_enable_irq;
+ open_pic2.disable = openpic2_disable_irq;
+
+ spin_unlock_irqrestore(&openpic2_setup_lock, flags);
+
+ return 0;
+}
+
+#endif /* CONFIG_PM */
+
+/* HACK ALERT */
+static struct sysdev_class openpic2_sysclass = {
+ set_kset_name("openpic2"),
+};
+
+static struct sys_device device_openpic2 = {
+ .id = 0,
+ .cls = &openpic2_sysclass,
+};
+
+static struct sysdev_driver driver_openpic2 = {
+#ifdef CONFIG_PM
+ .suspend = &openpic2_suspend,
+ .resume = &openpic2_resume,
+#endif /* CONFIG_PM */
+};
+
+static int __init init_openpic2_sysfs(void)
+{
+ int rc;
+
+ if (!OpenPIC2_Addr)
+ return -ENODEV;
+ printk(KERN_DEBUG "Registering openpic2 with sysfs...\n");
+ rc = sysdev_class_register(&openpic2_sysclass);
+ if (rc) {
+ printk(KERN_ERR "Failed registering openpic sys class\n");
+ return -ENODEV;
+ }
+ rc = sysdev_register(&device_openpic2);
+ if (rc) {
+ printk(KERN_ERR "Failed registering openpic sys device\n");
+ return -ENODEV;
+ }
+ rc = sysdev_driver_register(&openpic2_sysclass, &driver_openpic2);
+ if (rc) {
+ printk(KERN_ERR "Failed registering openpic sys driver\n");
+ return -ENODEV;
+ }
+ return 0;
+}
+
+subsys_initcall(init_openpic2_sysfs);
+
diff --git a/arch/ppc/syslib/open_pic_defs.h b/arch/ppc/syslib/open_pic_defs.h
new file mode 100644
index 0000000..4f05624
--- /dev/null
+++ b/arch/ppc/syslib/open_pic_defs.h
@@ -0,0 +1,292 @@
+/*
+ * arch/ppc/kernel/open_pic_defs.h -- OpenPIC definitions
+ *
+ * Copyright (C) 1997 Geert Uytterhoeven
+ *
+ * This file is based on the following documentation:
+ *
+ * The Open Programmable Interrupt Controller (PIC)
+ * Register Interface Specification Revision 1.2
+ *
+ * Issue Date: October 1995
+ *
+ * Issued jointly by Advanced Micro Devices and Cyrix Corporation
+ *
+ * AMD is a registered trademark of Advanced Micro Devices, Inc.
+ * Copyright (C) 1995, Advanced Micro Devices, Inc. and Cyrix, Inc.
+ * All Rights Reserved.
+ *
+ * To receive a copy of this documentation, send an email to openpic@amd.com.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file COPYING in the main directory of this archive
+ * for more details.
+ */
+
+#ifndef _LINUX_OPENPIC_H
+#define _LINUX_OPENPIC_H
+
+#ifdef __KERNEL__
+
+ /*
+ * OpenPIC supports up to 2048 interrupt sources and up to 32 processors
+ */
+
+#define OPENPIC_MAX_SOURCES 2048
+#define OPENPIC_MAX_PROCESSORS 32
+#define OPENPIC_MAX_ISU 16
+
+#define OPENPIC_NUM_TIMERS 4
+#define OPENPIC_NUM_IPI 4
+#define OPENPIC_NUM_PRI 16
+#define OPENPIC_NUM_VECTORS 256
+
+
+
+ /*
+ * OpenPIC Registers are 32 bits and aligned on 128 bit boundaries
+ */
+
+typedef struct _OpenPIC_Reg {
+ u_int Reg; /* Little endian! */
+ char Pad[0xc];
+} OpenPIC_Reg;
+
+
+ /*
+ * Per Processor Registers
+ */
+
+typedef struct _OpenPIC_Processor {
+ /*
+ * Private Shadow Registers (for SLiC backwards compatibility)
+ */
+ u_int IPI0_Dispatch_Shadow; /* Write Only */
+ char Pad1[0x4];
+ u_int IPI0_Vector_Priority_Shadow; /* Read/Write */
+ char Pad2[0x34];
+ /*
+ * Interprocessor Interrupt Command Ports
+ */
+ OpenPIC_Reg _IPI_Dispatch[OPENPIC_NUM_IPI]; /* Write Only */
+ /*
+ * Current Task Priority Register
+ */
+ OpenPIC_Reg _Current_Task_Priority; /* Read/Write */
+ char Pad3[0x10];
+ /*
+ * Interrupt Acknowledge Register
+ */
+ OpenPIC_Reg _Interrupt_Acknowledge; /* Read Only */
+ /*
+ * End of Interrupt (EOI) Register
+ */
+ OpenPIC_Reg _EOI; /* Read/Write */
+ char Pad5[0xf40];
+} OpenPIC_Processor;
+
+
+ /*
+ * Timer Registers
+ */
+
+typedef struct _OpenPIC_Timer {
+ OpenPIC_Reg _Current_Count; /* Read Only */
+ OpenPIC_Reg _Base_Count; /* Read/Write */
+ OpenPIC_Reg _Vector_Priority; /* Read/Write */
+ OpenPIC_Reg _Destination; /* Read/Write */
+} OpenPIC_Timer;
+
+
+ /*
+ * Global Registers
+ */
+
+typedef struct _OpenPIC_Global {
+ /*
+ * Feature Reporting Registers
+ */
+ OpenPIC_Reg _Feature_Reporting0; /* Read Only */
+ OpenPIC_Reg _Feature_Reporting1; /* Future Expansion */
+ /*
+ * Global Configuration Registers
+ */
+ OpenPIC_Reg _Global_Configuration0; /* Read/Write */
+ OpenPIC_Reg _Global_Configuration1; /* Future Expansion */
+ /*
+ * Vendor Specific Registers
+ */
+ OpenPIC_Reg _Vendor_Specific[4];
+ /*
+ * Vendor Identification Register
+ */
+ OpenPIC_Reg _Vendor_Identification; /* Read Only */
+ /*
+ * Processor Initialization Register
+ */
+ OpenPIC_Reg _Processor_Initialization; /* Read/Write */
+ /*
+ * IPI Vector/Priority Registers
+ */
+ OpenPIC_Reg _IPI_Vector_Priority[OPENPIC_NUM_IPI]; /* Read/Write */
+ /*
+ * Spurious Vector Register
+ */
+ OpenPIC_Reg _Spurious_Vector; /* Read/Write */
+ /*
+ * Global Timer Registers
+ */
+ OpenPIC_Reg _Timer_Frequency; /* Read/Write */
+ OpenPIC_Timer Timer[OPENPIC_NUM_TIMERS];
+ char Pad1[0xee00];
+} OpenPIC_Global;
+
+
+ /*
+ * Interrupt Source Registers
+ */
+
+typedef struct _OpenPIC_Source {
+ OpenPIC_Reg _Vector_Priority; /* Read/Write */
+ OpenPIC_Reg _Destination; /* Read/Write */
+} OpenPIC_Source, *OpenPIC_SourcePtr;
+
+
+ /*
+ * OpenPIC Register Map
+ */
+
+struct OpenPIC {
+ char Pad1[0x1000];
+ /*
+ * Global Registers
+ */
+ OpenPIC_Global Global;
+ /*
+ * Interrupt Source Configuration Registers
+ */
+ OpenPIC_Source Source[OPENPIC_MAX_SOURCES];
+ /*
+ * Per Processor Registers
+ */
+ OpenPIC_Processor Processor[OPENPIC_MAX_PROCESSORS];
+};
+
+extern volatile struct OpenPIC __iomem *OpenPIC;
+
+
+ /*
+ * Current Task Priority Register
+ */
+
+#define OPENPIC_CURRENT_TASK_PRIORITY_MASK 0x0000000f
+
+ /*
+ * Who Am I Register
+ */
+
+#define OPENPIC_WHO_AM_I_ID_MASK 0x0000001f
+
+ /*
+ * Feature Reporting Register 0
+ */
+
+#define OPENPIC_FEATURE_LAST_SOURCE_MASK 0x07ff0000
+#define OPENPIC_FEATURE_LAST_SOURCE_SHIFT 16
+#define OPENPIC_FEATURE_LAST_PROCESSOR_MASK 0x00001f00
+#define OPENPIC_FEATURE_LAST_PROCESSOR_SHIFT 8
+#define OPENPIC_FEATURE_VERSION_MASK 0x000000ff
+
+ /*
+ * Global Configuration Register 0
+ */
+
+#define OPENPIC_CONFIG_RESET 0x80000000
+#define OPENPIC_CONFIG_8259_PASSTHROUGH_DISABLE 0x20000000
+#define OPENPIC_CONFIG_BASE_MASK 0x000fffff
+
+ /*
+ * Global Configuration Register 1
+ * This is the EICR on EPICs.
+ */
+
+#define OPENPIC_EICR_S_CLK_MASK 0x70000000
+#define OPENPIC_EICR_SIE 0x08000000
+
+ /*
+ * Vendor Identification Register
+ */
+
+#define OPENPIC_VENDOR_ID_STEPPING_MASK 0x00ff0000
+#define OPENPIC_VENDOR_ID_STEPPING_SHIFT 16
+#define OPENPIC_VENDOR_ID_DEVICE_ID_MASK 0x0000ff00
+#define OPENPIC_VENDOR_ID_DEVICE_ID_SHIFT 8
+#define OPENPIC_VENDOR_ID_VENDOR_ID_MASK 0x000000ff
+
+ /*
+ * Vector/Priority Registers
+ */
+
+#define OPENPIC_MASK 0x80000000
+#define OPENPIC_ACTIVITY 0x40000000 /* Read Only */
+#define OPENPIC_PRIORITY_MASK 0x000f0000
+#define OPENPIC_PRIORITY_SHIFT 16
+#define OPENPIC_VECTOR_MASK 0x000000ff
+
+
+ /*
+ * Interrupt Source Registers
+ */
+
+#define OPENPIC_POLARITY_POSITIVE 0x00800000
+#define OPENPIC_POLARITY_NEGATIVE 0x00000000
+#define OPENPIC_POLARITY_MASK 0x00800000
+#define OPENPIC_SENSE_LEVEL 0x00400000
+#define OPENPIC_SENSE_EDGE 0x00000000
+#define OPENPIC_SENSE_MASK 0x00400000
+
+
+ /*
+ * Timer Registers
+ */
+
+#define OPENPIC_COUNT_MASK 0x7fffffff
+#define OPENPIC_TIMER_TOGGLE 0x80000000
+#define OPENPIC_TIMER_COUNT_INHIBIT 0x80000000
+
+
+ /*
+ * Aliases to make life simpler
+ */
+
+/* Per Processor Registers */
+#define IPI_Dispatch(i) _IPI_Dispatch[i].Reg
+#define Current_Task_Priority _Current_Task_Priority.Reg
+#define Interrupt_Acknowledge _Interrupt_Acknowledge.Reg
+#define EOI _EOI.Reg
+
+/* Global Registers */
+#define Feature_Reporting0 _Feature_Reporting0.Reg
+#define Feature_Reporting1 _Feature_Reporting1.Reg
+#define Global_Configuration0 _Global_Configuration0.Reg
+#define Global_Configuration1 _Global_Configuration1.Reg
+#define Vendor_Specific(i) _Vendor_Specific[i].Reg
+#define Vendor_Identification _Vendor_Identification.Reg
+#define Processor_Initialization _Processor_Initialization.Reg
+#define IPI_Vector_Priority(i) _IPI_Vector_Priority[i].Reg
+#define Spurious_Vector _Spurious_Vector.Reg
+#define Timer_Frequency _Timer_Frequency.Reg
+
+/* Timer Registers */
+#define Current_Count _Current_Count.Reg
+#define Base_Count _Base_Count.Reg
+#define Vector_Priority _Vector_Priority.Reg
+#define Destination _Destination.Reg
+
+/* Interrupt Source Registers */
+#define Vector_Priority _Vector_Priority.Reg
+#define Destination _Destination.Reg
+
+#endif /* __KERNEL__ */
+
+#endif /* _LINUX_OPENPIC_H */
diff --git a/arch/ppc/syslib/pci_auto.c b/arch/ppc/syslib/pci_auto.c
new file mode 100644
index 0000000..d64207c
--- /dev/null
+++ b/arch/ppc/syslib/pci_auto.c
@@ -0,0 +1,517 @@
+/*
+ * arch/ppc/syslib/pci_auto.c
+ *
+ * PCI autoconfiguration library
+ *
+ * Author: Matt Porter <mporter@mvista.com>
+ *
+ * 2001 (c) MontaVista, Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+
+/*
+ * The CardBus support is very preliminary. Preallocating space is
+ * the way to go but will require some change in card services to
+ * make it useful. Eventually this will ensure that we can put
+ * multiple CB bridges behind multiple P2P bridges. For now, at
+ * least it ensures that we place the CB bridge BAR and assigned
+ * initial bus numbers. I definitely need to do something about
+ * the lack of 16-bit I/O support. -MDP
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+
+#include <asm/pci-bridge.h>
+
+#define PCIAUTO_IDE_MODE_MASK 0x05
+
+#undef DEBUG
+
+#ifdef DEBUG
+#define DBG(x...) printk(x)
+#else
+#define DBG(x...)
+#endif /* DEBUG */
+
+static int pciauto_upper_iospc;
+static int pciauto_upper_memspc;
+
+void __init pciauto_setup_bars(struct pci_controller *hose,
+ int current_bus,
+ int pci_devfn,
+ int bar_limit)
+{
+ int bar_response, bar_size, bar_value;
+ int bar, addr_mask;
+ int * upper_limit;
+ int found_mem64 = 0;
+
+ DBG("PCI Autoconfig: Found Bus %d, Device %d, Function %d\n",
+ current_bus, PCI_SLOT(pci_devfn), PCI_FUNC(pci_devfn) );
+
+ for (bar = PCI_BASE_ADDRESS_0; bar <= bar_limit; bar+=4) {
+ /* Tickle the BAR and get the response */
+ early_write_config_dword(hose,
+ current_bus,
+ pci_devfn,
+ bar,
+ 0xffffffff);
+ early_read_config_dword(hose,
+ current_bus,
+ pci_devfn,
+ bar,
+ &bar_response);
+
+ /* If BAR is not implemented go to the next BAR */
+ if (!bar_response)
+ continue;
+
+ /* Check the BAR type and set our address mask */
+ if (bar_response & PCI_BASE_ADDRESS_SPACE) {
+ addr_mask = PCI_BASE_ADDRESS_IO_MASK;
+ upper_limit = &pciauto_upper_iospc;
+ DBG("PCI Autoconfig: BAR 0x%x, I/O, ", bar);
+ } else {
+ if ( (bar_response & PCI_BASE_ADDRESS_MEM_TYPE_MASK) ==
+ PCI_BASE_ADDRESS_MEM_TYPE_64)
+ found_mem64 = 1;
+
+ addr_mask = PCI_BASE_ADDRESS_MEM_MASK;
+ upper_limit = &pciauto_upper_memspc;
+ DBG("PCI Autoconfig: BAR 0x%x, Mem ", bar);
+ }
+
+ /* Calculate requested size */
+ bar_size = ~(bar_response & addr_mask) + 1;
+
+ /* Allocate a base address */
+ bar_value = (*upper_limit - bar_size) & ~(bar_size - 1);
+
+ /* Write it out and update our limit */
+ early_write_config_dword(hose,
+ current_bus,
+ pci_devfn,
+ bar,
+ bar_value);
+
+ *upper_limit = bar_value;
+
+ /*
+ * If we are a 64-bit decoder then increment to the
+ * upper 32 bits of the bar and force it to locate
+ * in the lower 4GB of memory.
+ */
+ if (found_mem64) {
+ bar += 4;
+ early_write_config_dword(hose,
+ current_bus,
+ pci_devfn,
+ bar,
+ 0x00000000);
+ found_mem64 = 0;
+ }
+
+ DBG("size=0x%x, address=0x%x\n",
+ bar_size, bar_value);
+ }
+
+}
+
+void __init pciauto_prescan_setup_bridge(struct pci_controller *hose,
+ int current_bus,
+ int pci_devfn,
+ int sub_bus,
+ int *iosave,
+ int *memsave)
+{
+ /* Configure bus number registers */
+ early_write_config_byte(hose,
+ current_bus,
+ pci_devfn,
+ PCI_PRIMARY_BUS,
+ current_bus);
+ early_write_config_byte(hose,
+ current_bus,
+ pci_devfn,
+ PCI_SECONDARY_BUS,
+ sub_bus + 1);
+ early_write_config_byte(hose,
+ current_bus,
+ pci_devfn,
+ PCI_SUBORDINATE_BUS,
+ 0xff);
+
+ /* Round memory allocator to 1MB boundary */
+ pciauto_upper_memspc &= ~(0x100000 - 1);
+ *memsave = pciauto_upper_memspc;
+
+ /* Round I/O allocator to 4KB boundary */
+ pciauto_upper_iospc &= ~(0x1000 - 1);
+ *iosave = pciauto_upper_iospc;
+
+ /* Set up memory and I/O filter limits, assume 32-bit I/O space */
+ early_write_config_word(hose,
+ current_bus,
+ pci_devfn,
+ PCI_MEMORY_LIMIT,
+ ((pciauto_upper_memspc - 1) & 0xfff00000) >> 16);
+ early_write_config_byte(hose,
+ current_bus,
+ pci_devfn,
+ PCI_IO_LIMIT,
+ ((pciauto_upper_iospc - 1) & 0x0000f000) >> 8);
+ early_write_config_word(hose,
+ current_bus,
+ pci_devfn,
+ PCI_IO_LIMIT_UPPER16,
+ ((pciauto_upper_iospc - 1) & 0xffff0000) >> 16);
+
+ /* Zero upper 32 bits of prefetchable base/limit */
+ early_write_config_dword(hose,
+ current_bus,
+ pci_devfn,
+ PCI_PREF_BASE_UPPER32,
+ 0);
+ early_write_config_dword(hose,
+ current_bus,
+ pci_devfn,
+ PCI_PREF_LIMIT_UPPER32,
+ 0);
+}
+
+void __init pciauto_postscan_setup_bridge(struct pci_controller *hose,
+ int current_bus,
+ int pci_devfn,
+ int sub_bus,
+ int *iosave,
+ int *memsave)
+{
+ int cmdstat;
+
+ /* Configure bus number registers */
+ early_write_config_byte(hose,
+ current_bus,
+ pci_devfn,
+ PCI_SUBORDINATE_BUS,
+ sub_bus);
+
+ /*
+ * Round memory allocator to 1MB boundary.
+ * If no space used, allocate minimum.
+ */
+ pciauto_upper_memspc &= ~(0x100000 - 1);
+ if (*memsave == pciauto_upper_memspc)
+ pciauto_upper_memspc -= 0x00100000;
+
+ early_write_config_word(hose,
+ current_bus,
+ pci_devfn,
+ PCI_MEMORY_BASE,
+ pciauto_upper_memspc >> 16);
+
+ /* Allocate 1MB for pre-fretch */
+ early_write_config_word(hose,
+ current_bus,
+ pci_devfn,
+ PCI_PREF_MEMORY_LIMIT,
+ ((pciauto_upper_memspc - 1) & 0xfff00000) >> 16);
+
+ pciauto_upper_memspc -= 0x100000;
+
+ early_write_config_word(hose,
+ current_bus,
+ pci_devfn,
+ PCI_PREF_MEMORY_BASE,
+ pciauto_upper_memspc >> 16);
+
+ /* Round I/O allocator to 4KB boundary */
+ pciauto_upper_iospc &= ~(0x1000 - 1);
+ if (*iosave == pciauto_upper_iospc)
+ pciauto_upper_iospc -= 0x1000;
+
+ early_write_config_byte(hose,
+ current_bus,
+ pci_devfn,
+ PCI_IO_BASE,
+ (pciauto_upper_iospc & 0x0000f000) >> 8);
+ early_write_config_word(hose,
+ current_bus,
+ pci_devfn,
+ PCI_IO_BASE_UPPER16,
+ pciauto_upper_iospc >> 16);
+
+ /* Enable memory and I/O accesses, enable bus master */
+ early_read_config_dword(hose,
+ current_bus,
+ pci_devfn,
+ PCI_COMMAND,
+ &cmdstat);
+ early_write_config_dword(hose,
+ current_bus,
+ pci_devfn,
+ PCI_COMMAND,
+ cmdstat |
+ PCI_COMMAND_IO |
+ PCI_COMMAND_MEMORY |
+ PCI_COMMAND_MASTER);
+}
+
+void __init pciauto_prescan_setup_cardbus_bridge(struct pci_controller *hose,
+ int current_bus,
+ int pci_devfn,
+ int sub_bus,
+ int *iosave,
+ int *memsave)
+{
+ /* Configure bus number registers */
+ early_write_config_byte(hose,
+ current_bus,
+ pci_devfn,
+ PCI_PRIMARY_BUS,
+ current_bus);
+ early_write_config_byte(hose,
+ current_bus,
+ pci_devfn,
+ PCI_SECONDARY_BUS,
+ sub_bus + 1);
+ early_write_config_byte(hose,
+ current_bus,
+ pci_devfn,
+ PCI_SUBORDINATE_BUS,
+ 0xff);
+
+ /* Round memory allocator to 4KB boundary */
+ pciauto_upper_memspc &= ~(0x1000 - 1);
+ *memsave = pciauto_upper_memspc;
+
+ /* Round I/O allocator to 4 byte boundary */
+ pciauto_upper_iospc &= ~(0x4 - 1);
+ *iosave = pciauto_upper_iospc;
+
+ /* Set up memory and I/O filter limits, assume 32-bit I/O space */
+ early_write_config_dword(hose,
+ current_bus,
+ pci_devfn,
+ 0x20,
+ pciauto_upper_memspc - 1);
+ early_write_config_dword(hose,
+ current_bus,
+ pci_devfn,
+ 0x30,
+ pciauto_upper_iospc - 1);
+}
+
+void __init pciauto_postscan_setup_cardbus_bridge(struct pci_controller *hose,
+ int current_bus,
+ int pci_devfn,
+ int sub_bus,
+ int *iosave,
+ int *memsave)
+{
+ int cmdstat;
+
+ /*
+ * Configure subordinate bus number. The PCI subsystem
+ * bus scan will renumber buses (reserving three additional
+ * for this PCI<->CardBus bridge for the case where a CardBus
+ * adapter contains a P2P or CB2CB bridge.
+ */
+ early_write_config_byte(hose,
+ current_bus,
+ pci_devfn,
+ PCI_SUBORDINATE_BUS,
+ sub_bus);
+
+ /*
+ * Reserve an additional 4MB for mem space and 16KB for
+ * I/O space. This should cover any additional space
+ * requirement of unusual CardBus devices with
+ * additional bridges that can consume more address space.
+ *
+ * Although pcmcia-cs currently will reprogram bridge
+ * windows, the goal is to add an option to leave them
+ * alone and use the bridge window ranges as the regions
+ * that are searched for free resources upon hot-insertion
+ * of a device. This will allow a PCI<->CardBus bridge
+ * configured by this routine to happily live behind a
+ * P2P bridge in a system.
+ */
+ pciauto_upper_memspc -= 0x00400000;
+ pciauto_upper_iospc -= 0x00004000;
+
+ /* Round memory allocator to 4KB boundary */
+ pciauto_upper_memspc &= ~(0x1000 - 1);
+
+ early_write_config_dword(hose,
+ current_bus,
+ pci_devfn,
+ 0x1c,
+ pciauto_upper_memspc);
+
+ /* Round I/O allocator to 4 byte boundary */
+ pciauto_upper_iospc &= ~(0x4 - 1);
+ early_write_config_dword(hose,
+ current_bus,
+ pci_devfn,
+ 0x2c,
+ pciauto_upper_iospc);
+
+ /* Enable memory and I/O accesses, enable bus master */
+ early_read_config_dword(hose,
+ current_bus,
+ pci_devfn,
+ PCI_COMMAND,
+ &cmdstat);
+ early_write_config_dword(hose,
+ current_bus,
+ pci_devfn,
+ PCI_COMMAND,
+ cmdstat |
+ PCI_COMMAND_IO |
+ PCI_COMMAND_MEMORY |
+ PCI_COMMAND_MASTER);
+}
+
+int __init pciauto_bus_scan(struct pci_controller *hose, int current_bus)
+{
+ int sub_bus, pci_devfn, pci_class, cmdstat, found_multi = 0;
+ unsigned short vid;
+ unsigned char header_type;
+
+ /*
+ * Fetch our I/O and memory space upper boundaries used
+ * to allocated base addresses on this hose.
+ */
+ if (current_bus == hose->first_busno) {
+ pciauto_upper_iospc = hose->io_space.end + 1;
+ pciauto_upper_memspc = hose->mem_space.end + 1;
+ }
+
+ sub_bus = current_bus;
+
+ for (pci_devfn = 0; pci_devfn < 0xff; pci_devfn++) {
+ /* Skip our host bridge */
+ if ( (current_bus == hose->first_busno) && (pci_devfn == 0) )
+ continue;
+
+ if (PCI_FUNC(pci_devfn) && !found_multi)
+ continue;
+
+ /* If config space read fails from this device, move on */
+ if (early_read_config_byte(hose,
+ current_bus,
+ pci_devfn,
+ PCI_HEADER_TYPE,
+ &header_type))
+ continue;
+
+ if (!PCI_FUNC(pci_devfn))
+ found_multi = header_type & 0x80;
+
+ early_read_config_word(hose,
+ current_bus,
+ pci_devfn,
+ PCI_VENDOR_ID,
+ &vid);
+
+ if (vid != 0xffff) {
+ early_read_config_dword(hose,
+ current_bus,
+ pci_devfn,
+ PCI_CLASS_REVISION, &pci_class);
+ if ( (pci_class >> 16) == PCI_CLASS_BRIDGE_PCI ) {
+ int iosave, memsave;
+
+ DBG("PCI Autoconfig: Found P2P bridge, device %d\n", PCI_SLOT(pci_devfn));
+ /* Allocate PCI I/O and/or memory space */
+ pciauto_setup_bars(hose,
+ current_bus,
+ pci_devfn,
+ PCI_BASE_ADDRESS_1);
+
+ pciauto_prescan_setup_bridge(hose,
+ current_bus,
+ pci_devfn,
+ sub_bus,
+ &iosave,
+ &memsave);
+ sub_bus = pciauto_bus_scan(hose, sub_bus+1);
+ pciauto_postscan_setup_bridge(hose,
+ current_bus,
+ pci_devfn,
+ sub_bus,
+ &iosave,
+ &memsave);
+ } else if ((pci_class >> 16) == PCI_CLASS_BRIDGE_CARDBUS) {
+ int iosave, memsave;
+
+ DBG("PCI Autoconfig: Found CardBus bridge, device %d function %d\n", PCI_SLOT(pci_devfn), PCI_FUNC(pci_devfn));
+ /* Place CardBus Socket/ExCA registers */
+ pciauto_setup_bars(hose,
+ current_bus,
+ pci_devfn,
+ PCI_BASE_ADDRESS_0);
+
+ pciauto_prescan_setup_cardbus_bridge(hose,
+ current_bus,
+ pci_devfn,
+ sub_bus,
+ &iosave,
+ &memsave);
+ sub_bus = pciauto_bus_scan(hose, sub_bus+1);
+ pciauto_postscan_setup_cardbus_bridge(hose,
+ current_bus,
+ pci_devfn,
+ sub_bus,
+ &iosave,
+ &memsave);
+ } else {
+ if ((pci_class >> 16) == PCI_CLASS_STORAGE_IDE) {
+ unsigned char prg_iface;
+
+ early_read_config_byte(hose,
+ current_bus,
+ pci_devfn,
+ PCI_CLASS_PROG,
+ &prg_iface);
+ if (!(prg_iface & PCIAUTO_IDE_MODE_MASK)) {
+ DBG("PCI Autoconfig: Skipping legacy mode IDE controller\n");
+ continue;
+ }
+ }
+ /* Allocate PCI I/O and/or memory space */
+ pciauto_setup_bars(hose,
+ current_bus,
+ pci_devfn,
+ PCI_BASE_ADDRESS_5);
+
+ /*
+ * Enable some standard settings
+ */
+ early_read_config_dword(hose,
+ current_bus,
+ pci_devfn,
+ PCI_COMMAND,
+ &cmdstat);
+ early_write_config_dword(hose,
+ current_bus,
+ pci_devfn,
+ PCI_COMMAND,
+ cmdstat |
+ PCI_COMMAND_IO |
+ PCI_COMMAND_MEMORY |
+ PCI_COMMAND_MASTER);
+ early_write_config_byte(hose,
+ current_bus,
+ pci_devfn,
+ PCI_LATENCY_TIMER,
+ 0x80);
+ }
+ }
+ }
+ return sub_bus;
+}
diff --git a/arch/ppc/syslib/ppc403_pic.c b/arch/ppc/syslib/ppc403_pic.c
new file mode 100644
index 0000000..06cb0af
--- /dev/null
+++ b/arch/ppc/syslib/ppc403_pic.c
@@ -0,0 +1,127 @@
+/*
+ *
+ * Copyright (c) 1999 Grant Erickson <grant@lcse.umn.edu>
+ *
+ * Module name: ppc403_pic.c
+ *
+ * Description:
+ * Interrupt controller driver for PowerPC 403-based processors.
+ */
+
+/*
+ * The PowerPC 403 cores' Asynchronous Interrupt Controller (AIC) has
+ * 32 possible interrupts, a majority of which are not implemented on
+ * all cores. There are six configurable, external interrupt pins and
+ * there are eight internal interrupts for the on-chip serial port
+ * (SPU), DMA controller, and JTAG controller.
+ *
+ */
+
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/signal.h>
+#include <linux/stddef.h>
+
+#include <asm/processor.h>
+#include <asm/system.h>
+#include <asm/irq.h>
+#include <asm/ppc4xx_pic.h>
+
+/* Function Prototypes */
+
+static void ppc403_aic_enable(unsigned int irq);
+static void ppc403_aic_disable(unsigned int irq);
+static void ppc403_aic_disable_and_ack(unsigned int irq);
+
+static struct hw_interrupt_type ppc403_aic = {
+ "403GC AIC",
+ NULL,
+ NULL,
+ ppc403_aic_enable,
+ ppc403_aic_disable,
+ ppc403_aic_disable_and_ack,
+ 0
+};
+
+int
+ppc403_pic_get_irq(struct pt_regs *regs)
+{
+ int irq;
+ unsigned long bits;
+
+ /*
+ * Only report the status of those interrupts that are actually
+ * enabled.
+ */
+
+ bits = mfdcr(DCRN_EXISR) & mfdcr(DCRN_EXIER);
+
+ /*
+ * Walk through the interrupts from highest priority to lowest, and
+ * report the first pending interrupt found.
+ * We want PPC, not C bit numbering, so just subtract the ffs()
+ * result from 32.
+ */
+ irq = 32 - ffs(bits);
+
+ if (irq == NR_AIC_IRQS)
+ irq = -1;
+
+ return (irq);
+}
+
+static void
+ppc403_aic_enable(unsigned int irq)
+{
+ int bit, word;
+
+ bit = irq & 0x1f;
+ word = irq >> 5;
+
+ ppc_cached_irq_mask[word] |= (1 << (31 - bit));
+ mtdcr(DCRN_EXIER, ppc_cached_irq_mask[word]);
+}
+
+static void
+ppc403_aic_disable(unsigned int irq)
+{
+ int bit, word;
+
+ bit = irq & 0x1f;
+ word = irq >> 5;
+
+ ppc_cached_irq_mask[word] &= ~(1 << (31 - bit));
+ mtdcr(DCRN_EXIER, ppc_cached_irq_mask[word]);
+}
+
+static void
+ppc403_aic_disable_and_ack(unsigned int irq)
+{
+ int bit, word;
+
+ bit = irq & 0x1f;
+ word = irq >> 5;
+
+ ppc_cached_irq_mask[word] &= ~(1 << (31 - bit));
+ mtdcr(DCRN_EXIER, ppc_cached_irq_mask[word]);
+ mtdcr(DCRN_EXISR, (1 << (31 - bit)));
+}
+
+void __init
+ppc4xx_pic_init(void)
+{
+ int i;
+
+ /*
+ * Disable all external interrupts until they are
+ * explicity requested.
+ */
+ ppc_cached_irq_mask[0] = 0;
+
+ mtdcr(DCRN_EXIER, ppc_cached_irq_mask[0]);
+
+ ppc_md.get_irq = ppc403_pic_get_irq;
+
+ for (i = 0; i < NR_IRQS; i++)
+ irq_desc[i].handler = &ppc403_aic;
+}
diff --git a/arch/ppc/syslib/ppc405_pci.c b/arch/ppc/syslib/ppc405_pci.c
new file mode 100644
index 0000000..81c83bf
--- /dev/null
+++ b/arch/ppc/syslib/ppc405_pci.c
@@ -0,0 +1,177 @@
+/*
+ * Authors: Frank Rowand <frank_rowand@mvista.com>,
+ * Debbie Chu <debbie_chu@mvista.com>, or source@mvista.com
+ * Further modifications by Armin Kuster <akuster@mvista.com>
+ *
+ * 2000 (c) MontaVista, Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ *
+ * Based on arch/ppc/kernel/indirect.c, Copyright (C) 1998 Gabriel Paubert.
+ */
+
+#include <linux/pci.h>
+#include <asm/io.h>
+#include <asm/system.h>
+#include <asm/machdep.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <asm/ocp.h>
+#include <asm/ibm4xx.h>
+#include <asm/pci-bridge.h>
+#include <asm/ibm_ocp_pci.h>
+
+
+extern void bios_fixup(struct pci_controller *, struct pcil0_regs *);
+extern int ppc405_map_irq(struct pci_dev *dev, unsigned char idsel,
+ unsigned char pin);
+
+void
+ppc405_pcibios_fixup_resources(struct pci_dev *dev)
+{
+ int i;
+ unsigned long max_host_addr;
+ unsigned long min_host_addr;
+ struct resource *res;
+
+ /*
+ * openbios puts some graphics cards in the same range as the host
+ * controller uses to map to SDRAM. Fix it.
+ */
+
+ min_host_addr = 0;
+ max_host_addr = PPC405_PCI_MEM_BASE - 1;
+
+ for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {
+ res = dev->resource + i;
+ if (!res->start)
+ continue;
+ if ((res->flags & IORESOURCE_MEM) &&
+ (((res->start >= min_host_addr)
+ && (res->start <= max_host_addr))
+ || ((res->end >= min_host_addr)
+ && (res->end <= max_host_addr))
+ || ((res->start < min_host_addr)
+ && (res->end > max_host_addr))
+ )
+ ) {
+
+ /* force pcibios_assign_resources() to assign a new address */
+ res->end -= res->start;
+ res->start = 0;
+ }
+ }
+}
+
+static int
+ppc4xx_exclude_device(unsigned char bus, unsigned char devfn)
+{
+ /* We prevent us from seeing ourselves to avoid having
+ * the kernel try to remap our BAR #1 and fuck up bus
+ * master from external PCI devices
+ */
+ return (bus == 0 && devfn == 0);
+}
+
+void
+ppc4xx_find_bridges(void)
+{
+ struct pci_controller *hose_a;
+ struct pcil0_regs *pcip;
+ unsigned int tmp_addr;
+ unsigned int tmp_size;
+ unsigned int reg_index;
+ unsigned int new_pmm_max = 0;
+ unsigned int new_pmm_min = 0;
+
+ isa_io_base = 0;
+ isa_mem_base = 0;
+ pci_dram_offset = 0;
+
+#if (PSR_PCI_ARBIT_EN > 1)
+ /* Check if running in slave mode */
+ if ((mfdcr(DCRN_CHPSR) & PSR_PCI_ARBIT_EN) == 0) {
+ printk("Running as PCI slave, kernel PCI disabled !\n");
+ return;
+ }
+#endif
+ /* Setup PCI32 hose */
+ hose_a = pcibios_alloc_controller();
+ if (!hose_a)
+ return;
+ setup_indirect_pci(hose_a, PPC405_PCI_CONFIG_ADDR,
+ PPC405_PCI_CONFIG_DATA);
+
+ pcip = ioremap(PPC4xx_PCI_LCFG_PADDR, PAGE_SIZE);
+ if (pcip != NULL) {
+
+#if defined(CONFIG_BIOS_FIXUP)
+ bios_fixup(hose_a, pcip);
+#endif
+ new_pmm_min = 0xffffffff;
+ for (reg_index = 0; reg_index < 3; reg_index++) {
+ tmp_size = in_le32(&pcip->pmm[reg_index].ma); // mask & attrs
+ /* test the enable bit */
+ if ((tmp_size & 0x1) == 0)
+ continue;
+ tmp_addr = in_le32(&pcip->pmm[reg_index].pcila); // PCI addr
+ if (tmp_addr < PPC405_PCI_PHY_MEM_BASE) {
+ printk(KERN_DEBUG
+ "Disabling mapping to PCI mem addr 0x%8.8x\n",
+ tmp_addr);
+ out_le32(&pcip->pmm[reg_index].ma, tmp_size & ~1); // *_PMMOMA
+ continue;
+ }
+ tmp_addr = in_le32(&pcip->pmm[reg_index].la); // *_PMMOLA
+ if (tmp_addr < new_pmm_min)
+ new_pmm_min = tmp_addr;
+ tmp_addr = tmp_addr +
+ (0xffffffff - (tmp_size & 0xffffc000));
+ if (tmp_addr > PPC405_PCI_UPPER_MEM) {
+ new_pmm_max = tmp_addr; // PPC405_PCI_UPPER_MEM
+ } else {
+ new_pmm_max = PPC405_PCI_UPPER_MEM;
+ }
+
+ } // for
+
+ iounmap(pcip);
+ }
+
+ hose_a->first_busno = 0;
+ hose_a->last_busno = 0xff;
+ hose_a->pci_mem_offset = 0;
+
+ /* Setup bridge memory/IO ranges & resources
+ * TODO: Handle firmwares setting up a legacy ISA mem base
+ */
+ hose_a->io_space.start = PPC405_PCI_LOWER_IO;
+ hose_a->io_space.end = PPC405_PCI_UPPER_IO;
+ hose_a->mem_space.start = new_pmm_min;
+ hose_a->mem_space.end = new_pmm_max;
+ hose_a->io_base_phys = PPC405_PCI_PHY_IO_BASE;
+ hose_a->io_base_virt = ioremap(hose_a->io_base_phys, 0x10000);
+ hose_a->io_resource.start = 0;
+ hose_a->io_resource.end = PPC405_PCI_UPPER_IO - PPC405_PCI_LOWER_IO;
+ hose_a->io_resource.flags = IORESOURCE_IO;
+ hose_a->io_resource.name = "PCI I/O";
+ hose_a->mem_resources[0].start = new_pmm_min;
+ hose_a->mem_resources[0].end = new_pmm_max;
+ hose_a->mem_resources[0].flags = IORESOURCE_MEM;
+ hose_a->mem_resources[0].name = "PCI Memory";
+ isa_io_base = (int) hose_a->io_base_virt;
+ isa_mem_base = 0; /* ISA not implemented */
+ ISA_DMA_THRESHOLD = 0x00ffffff; /* ??? ISA not implemented */
+
+ /* Scan busses & initial setup by pci_auto */
+ hose_a->last_busno = pciauto_bus_scan(hose_a, hose_a->first_busno);
+ hose_a->last_busno = 0;
+
+ /* Setup ppc_md */
+ ppc_md.pcibios_fixup = NULL;
+ ppc_md.pci_exclude_device = ppc4xx_exclude_device;
+ ppc_md.pcibios_fixup_resources = ppc405_pcibios_fixup_resources;
+ ppc_md.pci_swizzle = common_swizzle;
+ ppc_md.pci_map_irq = ppc405_map_irq;
+}
diff --git a/arch/ppc/syslib/ppc4xx_dma.c b/arch/ppc/syslib/ppc4xx_dma.c
new file mode 100644
index 0000000..5015ab9
--- /dev/null
+++ b/arch/ppc/syslib/ppc4xx_dma.c
@@ -0,0 +1,708 @@
+/*
+ * arch/ppc/kernel/ppc4xx_dma.c
+ *
+ * IBM PPC4xx DMA engine core library
+ *
+ * Copyright 2000-2004 MontaVista Software Inc.
+ *
+ * Cleaned up and converted to new DCR access
+ * Matt Porter <mporter@kernel.crashing.org>
+ *
+ * Original code by Armin Kuster <akuster@mvista.com>
+ * and Pete Popov <ppopov@mvista.com>
+ *
+ * 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.
+ *
+ * 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.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/miscdevice.h>
+#include <linux/init.h>
+#include <linux/module.h>
+
+#include <asm/system.h>
+#include <asm/io.h>
+#include <asm/ppc4xx_dma.h>
+
+ppc_dma_ch_t dma_channels[MAX_PPC4xx_DMA_CHANNELS];
+
+int
+ppc4xx_get_dma_status(void)
+{
+ return (mfdcr(DCRN_DMASR));
+}
+
+void
+ppc4xx_set_src_addr(int dmanr, phys_addr_t src_addr)
+{
+ if (dmanr >= MAX_PPC4xx_DMA_CHANNELS) {
+ printk("set_src_addr: bad channel: %d\n", dmanr);
+ return;
+ }
+
+#ifdef PPC4xx_DMA_64BIT
+ mtdcr(DCRN_DMASAH0 + dmanr*2, (u32)(src_addr >> 32));
+#else
+ mtdcr(DCRN_DMASA0 + dmanr*2, (u32)src_addr);
+#endif
+}
+
+void
+ppc4xx_set_dst_addr(int dmanr, phys_addr_t dst_addr)
+{
+ if (dmanr >= MAX_PPC4xx_DMA_CHANNELS) {
+ printk("set_dst_addr: bad channel: %d\n", dmanr);
+ return;
+ }
+
+#ifdef PPC4xx_DMA_64BIT
+ mtdcr(DCRN_DMADAH0 + dmanr*2, (u32)(dst_addr >> 32));
+#else
+ mtdcr(DCRN_DMADA0 + dmanr*2, (u32)dst_addr);
+#endif
+}
+
+void
+ppc4xx_enable_dma(unsigned int dmanr)
+{
+ unsigned int control;
+ ppc_dma_ch_t *p_dma_ch = &dma_channels[dmanr];
+ unsigned int status_bits[] = { DMA_CS0 | DMA_TS0 | DMA_CH0_ERR,
+ DMA_CS1 | DMA_TS1 | DMA_CH1_ERR,
+ DMA_CS2 | DMA_TS2 | DMA_CH2_ERR,
+ DMA_CS3 | DMA_TS3 | DMA_CH3_ERR};
+
+ if (p_dma_ch->in_use) {
+ printk("enable_dma: channel %d in use\n", dmanr);
+ return;
+ }
+
+ if (dmanr >= MAX_PPC4xx_DMA_CHANNELS) {
+ printk("enable_dma: bad channel: %d\n", dmanr);
+ return;
+ }
+
+ if (p_dma_ch->mode == DMA_MODE_READ) {
+ /* peripheral to memory */
+ ppc4xx_set_src_addr(dmanr, 0);
+ ppc4xx_set_dst_addr(dmanr, p_dma_ch->addr);
+ } else if (p_dma_ch->mode == DMA_MODE_WRITE) {
+ /* memory to peripheral */
+ ppc4xx_set_src_addr(dmanr, p_dma_ch->addr);
+ ppc4xx_set_dst_addr(dmanr, 0);
+ }
+
+ /* for other xfer modes, the addresses are already set */
+ control = mfdcr(DCRN_DMACR0 + (dmanr * 0x8));
+
+ control &= ~(DMA_TM_MASK | DMA_TD); /* clear all mode bits */
+ if (p_dma_ch->mode == DMA_MODE_MM) {
+ /* software initiated memory to memory */
+ control |= DMA_ETD_OUTPUT | DMA_TCE_ENABLE;
+ }
+
+ mtdcr(DCRN_DMACR0 + (dmanr * 0x8), control);
+
+ /*
+ * Clear the CS, TS, RI bits for the channel from DMASR. This
+ * has been observed to happen correctly only after the mode and
+ * ETD/DCE bits in DMACRx are set above. Must do this before
+ * enabling the channel.
+ */
+
+ mtdcr(DCRN_DMASR, status_bits[dmanr]);
+
+ /*
+ * For device-paced transfers, Terminal Count Enable apparently
+ * must be on, and this must be turned on after the mode, etc.
+ * bits are cleared above (at least on Redwood-6).
+ */
+
+ if ((p_dma_ch->mode == DMA_MODE_MM_DEVATDST) ||
+ (p_dma_ch->mode == DMA_MODE_MM_DEVATSRC))
+ control |= DMA_TCE_ENABLE;
+
+ /*
+ * Now enable the channel.
+ */
+
+ control |= (p_dma_ch->mode | DMA_CE_ENABLE);
+
+ mtdcr(DCRN_DMACR0 + (dmanr * 0x8), control);
+
+ p_dma_ch->in_use = 1;
+}
+
+void
+ppc4xx_disable_dma(unsigned int dmanr)
+{
+ unsigned int control;
+ ppc_dma_ch_t *p_dma_ch = &dma_channels[dmanr];
+
+ if (!p_dma_ch->in_use) {
+ printk("disable_dma: channel %d not in use\n", dmanr);
+ return;
+ }
+
+ if (dmanr >= MAX_PPC4xx_DMA_CHANNELS) {
+ printk("disable_dma: bad channel: %d\n", dmanr);
+ return;
+ }
+
+ control = mfdcr(DCRN_DMACR0 + (dmanr * 0x8));
+ control &= ~DMA_CE_ENABLE;
+ mtdcr(DCRN_DMACR0 + (dmanr * 0x8), control);
+
+ p_dma_ch->in_use = 0;
+}
+
+/*
+ * Sets the dma mode for single DMA transfers only.
+ * For scatter/gather transfers, the mode is passed to the
+ * alloc_dma_handle() function as one of the parameters.
+ *
+ * The mode is simply saved and used later. This allows
+ * the driver to call set_dma_mode() and set_dma_addr() in
+ * any order.
+ *
+ * Valid mode values are:
+ *
+ * DMA_MODE_READ peripheral to memory
+ * DMA_MODE_WRITE memory to peripheral
+ * DMA_MODE_MM memory to memory
+ * DMA_MODE_MM_DEVATSRC device-paced memory to memory, device at src
+ * DMA_MODE_MM_DEVATDST device-paced memory to memory, device at dst
+ */
+int
+ppc4xx_set_dma_mode(unsigned int dmanr, unsigned int mode)
+{
+ ppc_dma_ch_t *p_dma_ch = &dma_channels[dmanr];
+
+ if (dmanr >= MAX_PPC4xx_DMA_CHANNELS) {
+ printk("set_dma_mode: bad channel 0x%x\n", dmanr);
+ return DMA_STATUS_BAD_CHANNEL;
+ }
+
+ p_dma_ch->mode = mode;
+
+ return DMA_STATUS_GOOD;
+}
+
+/*
+ * Sets the DMA Count register. Note that 'count' is in bytes.
+ * However, the DMA Count register counts the number of "transfers",
+ * where each transfer is equal to the bus width. Thus, count
+ * MUST be a multiple of the bus width.
+ */
+void
+ppc4xx_set_dma_count(unsigned int dmanr, unsigned int count)
+{
+ ppc_dma_ch_t *p_dma_ch = &dma_channels[dmanr];
+
+#ifdef DEBUG_4xxDMA
+ {
+ int error = 0;
+ switch (p_dma_ch->pwidth) {
+ case PW_8:
+ break;
+ case PW_16:
+ if (count & 0x1)
+ error = 1;
+ break;
+ case PW_32:
+ if (count & 0x3)
+ error = 1;
+ break;
+ case PW_64:
+ if (count & 0x7)
+ error = 1;
+ break;
+ default:
+ printk("set_dma_count: invalid bus width: 0x%x\n",
+ p_dma_ch->pwidth);
+ return;
+ }
+ if (error)
+ printk
+ ("Warning: set_dma_count count 0x%x bus width %d\n",
+ count, p_dma_ch->pwidth);
+ }
+#endif
+
+ count = count >> p_dma_ch->shift;
+
+ mtdcr(DCRN_DMACT0 + (dmanr * 0x8), count);
+}
+
+/*
+ * Returns the number of bytes left to be transfered.
+ * After a DMA transfer, this should return zero.
+ * Reading this while a DMA transfer is still in progress will return
+ * unpredictable results.
+ */
+int
+ppc4xx_get_dma_residue(unsigned int dmanr)
+{
+ unsigned int count;
+ ppc_dma_ch_t *p_dma_ch = &dma_channels[dmanr];
+
+ if (dmanr >= MAX_PPC4xx_DMA_CHANNELS) {
+ printk("ppc4xx_get_dma_residue: bad channel 0x%x\n", dmanr);
+ return DMA_STATUS_BAD_CHANNEL;
+ }
+
+ count = mfdcr(DCRN_DMACT0 + (dmanr * 0x8));
+
+ return (count << p_dma_ch->shift);
+}
+
+/*
+ * Sets the DMA address for a memory to peripheral or peripheral
+ * to memory transfer. The address is just saved in the channel
+ * structure for now and used later in enable_dma().
+ */
+void
+ppc4xx_set_dma_addr(unsigned int dmanr, phys_addr_t addr)
+{
+ ppc_dma_ch_t *p_dma_ch = &dma_channels[dmanr];
+
+ if (dmanr >= MAX_PPC4xx_DMA_CHANNELS) {
+ printk("ppc4xx_set_dma_addr: bad channel: %d\n", dmanr);
+ return;
+ }
+
+#ifdef DEBUG_4xxDMA
+ {
+ int error = 0;
+ switch (p_dma_ch->pwidth) {
+ case PW_8:
+ break;
+ case PW_16:
+ if ((unsigned) addr & 0x1)
+ error = 1;
+ break;
+ case PW_32:
+ if ((unsigned) addr & 0x3)
+ error = 1;
+ break;
+ case PW_64:
+ if ((unsigned) addr & 0x7)
+ error = 1;
+ break;
+ default:
+ printk("ppc4xx_set_dma_addr: invalid bus width: 0x%x\n",
+ p_dma_ch->pwidth);
+ return;
+ }
+ if (error)
+ printk("Warning: ppc4xx_set_dma_addr addr 0x%x bus width %d\n",
+ addr, p_dma_ch->pwidth);
+ }
+#endif
+
+ /* save dma address and program it later after we know the xfer mode */
+ p_dma_ch->addr = addr;
+}
+
+/*
+ * Sets both DMA addresses for a memory to memory transfer.
+ * For memory to peripheral or peripheral to memory transfers
+ * the function set_dma_addr() should be used instead.
+ */
+void
+ppc4xx_set_dma_addr2(unsigned int dmanr, phys_addr_t src_dma_addr,
+ phys_addr_t dst_dma_addr)
+{
+ if (dmanr >= MAX_PPC4xx_DMA_CHANNELS) {
+ printk("ppc4xx_set_dma_addr2: bad channel: %d\n", dmanr);
+ return;
+ }
+
+#ifdef DEBUG_4xxDMA
+ {
+ ppc_dma_ch_t *p_dma_ch = &dma_channels[dmanr];
+ int error = 0;
+ switch (p_dma_ch->pwidth) {
+ case PW_8:
+ break;
+ case PW_16:
+ if (((unsigned) src_dma_addr & 0x1) ||
+ ((unsigned) dst_dma_addr & 0x1)
+ )
+ error = 1;
+ break;
+ case PW_32:
+ if (((unsigned) src_dma_addr & 0x3) ||
+ ((unsigned) dst_dma_addr & 0x3)
+ )
+ error = 1;
+ break;
+ case PW_64:
+ if (((unsigned) src_dma_addr & 0x7) ||
+ ((unsigned) dst_dma_addr & 0x7)
+ )
+ error = 1;
+ break;
+ default:
+ printk("ppc4xx_set_dma_addr2: invalid bus width: 0x%x\n",
+ p_dma_ch->pwidth);
+ return;
+ }
+ if (error)
+ printk
+ ("Warning: ppc4xx_set_dma_addr2 src 0x%x dst 0x%x bus width %d\n",
+ src_dma_addr, dst_dma_addr, p_dma_ch->pwidth);
+ }
+#endif
+
+ ppc4xx_set_src_addr(dmanr, src_dma_addr);
+ ppc4xx_set_dst_addr(dmanr, dst_dma_addr);
+}
+
+/*
+ * Enables the channel interrupt.
+ *
+ * If performing a scatter/gatter transfer, this function
+ * MUST be called before calling alloc_dma_handle() and building
+ * the sgl list. Otherwise, interrupts will not be enabled, if
+ * they were previously disabled.
+ */
+int
+ppc4xx_enable_dma_interrupt(unsigned int dmanr)
+{
+ unsigned int control;
+ ppc_dma_ch_t *p_dma_ch = &dma_channels[dmanr];
+
+ if (dmanr >= MAX_PPC4xx_DMA_CHANNELS) {
+ printk("ppc4xx_enable_dma_interrupt: bad channel: %d\n", dmanr);
+ return DMA_STATUS_BAD_CHANNEL;
+ }
+
+ p_dma_ch->int_enable = 1;
+
+ control = mfdcr(DCRN_DMACR0 + (dmanr * 0x8));
+ control |= DMA_CIE_ENABLE; /* Channel Interrupt Enable */
+ mtdcr(DCRN_DMACR0 + (dmanr * 0x8), control);
+
+ return DMA_STATUS_GOOD;
+}
+
+/*
+ * Disables the channel interrupt.
+ *
+ * If performing a scatter/gatter transfer, this function
+ * MUST be called before calling alloc_dma_handle() and building
+ * the sgl list. Otherwise, interrupts will not be disabled, if
+ * they were previously enabled.
+ */
+int
+ppc4xx_disable_dma_interrupt(unsigned int dmanr)
+{
+ unsigned int control;
+ ppc_dma_ch_t *p_dma_ch = &dma_channels[dmanr];
+
+ if (dmanr >= MAX_PPC4xx_DMA_CHANNELS) {
+ printk("ppc4xx_disable_dma_interrupt: bad channel: %d\n", dmanr);
+ return DMA_STATUS_BAD_CHANNEL;
+ }
+
+ p_dma_ch->int_enable = 0;
+
+ control = mfdcr(DCRN_DMACR0 + (dmanr * 0x8));
+ control &= ~DMA_CIE_ENABLE; /* Channel Interrupt Enable */
+ mtdcr(DCRN_DMACR0 + (dmanr * 0x8), control);
+
+ return DMA_STATUS_GOOD;
+}
+
+/*
+ * Configures a DMA channel, including the peripheral bus width, if a
+ * peripheral is attached to the channel, the polarity of the DMAReq and
+ * DMAAck signals, etc. This information should really be setup by the boot
+ * code, since most likely the configuration won't change dynamically.
+ * If the kernel has to call this function, it's recommended that it's
+ * called from platform specific init code. The driver should not need to
+ * call this function.
+ */
+int
+ppc4xx_init_dma_channel(unsigned int dmanr, ppc_dma_ch_t * p_init)
+{
+ unsigned int polarity;
+ uint32_t control = 0;
+ ppc_dma_ch_t *p_dma_ch = &dma_channels[dmanr];
+
+ DMA_MODE_READ = (unsigned long) DMA_TD; /* Peripheral to Memory */
+ DMA_MODE_WRITE = 0; /* Memory to Peripheral */
+
+ if (!p_init) {
+ printk("ppc4xx_init_dma_channel: NULL p_init\n");
+ return DMA_STATUS_NULL_POINTER;
+ }
+
+ if (dmanr >= MAX_PPC4xx_DMA_CHANNELS) {
+ printk("ppc4xx_init_dma_channel: bad channel %d\n", dmanr);
+ return DMA_STATUS_BAD_CHANNEL;
+ }
+
+#if DCRN_POL > 0
+ polarity = mfdcr(DCRN_POL);
+#else
+ polarity = 0;
+#endif
+
+ /* Setup the control register based on the values passed to
+ * us in p_init. Then, over-write the control register with this
+ * new value.
+ */
+ control |= SET_DMA_CONTROL;
+
+ /* clear all polarity signals and then "or" in new signal levels */
+ polarity &= ~GET_DMA_POLARITY(dmanr);
+ polarity |= p_init->polarity;
+#if DCRN_POL > 0
+ mtdcr(DCRN_POL, polarity);
+#endif
+ mtdcr(DCRN_DMACR0 + (dmanr * 0x8), control);
+
+ /* save these values in our dma channel structure */
+ memcpy(p_dma_ch, p_init, sizeof (ppc_dma_ch_t));
+
+ /*
+ * The peripheral width values written in the control register are:
+ * PW_8 0
+ * PW_16 1
+ * PW_32 2
+ * PW_64 3
+ *
+ * Since the DMA count register takes the number of "transfers",
+ * we need to divide the count sent to us in certain
+ * functions by the appropriate number. It so happens that our
+ * right shift value is equal to the peripheral width value.
+ */
+ p_dma_ch->shift = p_init->pwidth;
+
+ /*
+ * Save the control word for easy access.
+ */
+ p_dma_ch->control = control;
+
+ mtdcr(DCRN_DMASR, 0xffffffff); /* clear status register */
+ return DMA_STATUS_GOOD;
+}
+
+/*
+ * This function returns the channel configuration.
+ */
+int
+ppc4xx_get_channel_config(unsigned int dmanr, ppc_dma_ch_t * p_dma_ch)
+{
+ unsigned int polarity;
+ unsigned int control;
+
+ if (dmanr >= MAX_PPC4xx_DMA_CHANNELS) {
+ printk("ppc4xx_get_channel_config: bad channel %d\n", dmanr);
+ return DMA_STATUS_BAD_CHANNEL;
+ }
+
+ memcpy(p_dma_ch, &dma_channels[dmanr], sizeof (ppc_dma_ch_t));
+
+#if DCRN_POL > 0
+ polarity = mfdcr(DCRN_POL);
+#else
+ polarity = 0;
+#endif
+
+ p_dma_ch->polarity = polarity & GET_DMA_POLARITY(dmanr);
+ control = mfdcr(DCRN_DMACR0 + (dmanr * 0x8));
+
+ p_dma_ch->cp = GET_DMA_PRIORITY(control);
+ p_dma_ch->pwidth = GET_DMA_PW(control);
+ p_dma_ch->psc = GET_DMA_PSC(control);
+ p_dma_ch->pwc = GET_DMA_PWC(control);
+ p_dma_ch->phc = GET_DMA_PHC(control);
+ p_dma_ch->ce = GET_DMA_CE_ENABLE(control);
+ p_dma_ch->int_enable = GET_DMA_CIE_ENABLE(control);
+ p_dma_ch->shift = GET_DMA_PW(control);
+
+#ifdef CONFIG_PPC4xx_EDMA
+ p_dma_ch->pf = GET_DMA_PREFETCH(control);
+#else
+ p_dma_ch->ch_enable = GET_DMA_CH(control);
+ p_dma_ch->ece_enable = GET_DMA_ECE(control);
+ p_dma_ch->tcd_disable = GET_DMA_TCD(control);
+#endif
+ return DMA_STATUS_GOOD;
+}
+
+/*
+ * Sets the priority for the DMA channel dmanr.
+ * Since this is setup by the hardware init function, this function
+ * can be used to dynamically change the priority of a channel.
+ *
+ * Acceptable priorities:
+ *
+ * PRIORITY_LOW
+ * PRIORITY_MID_LOW
+ * PRIORITY_MID_HIGH
+ * PRIORITY_HIGH
+ *
+ */
+int
+ppc4xx_set_channel_priority(unsigned int dmanr, unsigned int priority)
+{
+ unsigned int control;
+
+ if (dmanr >= MAX_PPC4xx_DMA_CHANNELS) {
+ printk("ppc4xx_set_channel_priority: bad channel %d\n", dmanr);
+ return DMA_STATUS_BAD_CHANNEL;
+ }
+
+ if ((priority != PRIORITY_LOW) &&
+ (priority != PRIORITY_MID_LOW) &&
+ (priority != PRIORITY_MID_HIGH) && (priority != PRIORITY_HIGH)) {
+ printk("ppc4xx_set_channel_priority: bad priority: 0x%x\n", priority);
+ }
+
+ control = mfdcr(DCRN_DMACR0 + (dmanr * 0x8));
+ control |= SET_DMA_PRIORITY(priority);
+ mtdcr(DCRN_DMACR0 + (dmanr * 0x8), control);
+
+ return DMA_STATUS_GOOD;
+}
+
+/*
+ * Returns the width of the peripheral attached to this channel. This assumes
+ * that someone who knows the hardware configuration, boot code or some other
+ * init code, already set the width.
+ *
+ * The return value is one of:
+ * PW_8
+ * PW_16
+ * PW_32
+ * PW_64
+ *
+ * The function returns 0 on error.
+ */
+unsigned int
+ppc4xx_get_peripheral_width(unsigned int dmanr)
+{
+ unsigned int control;
+
+ if (dmanr >= MAX_PPC4xx_DMA_CHANNELS) {
+ printk("ppc4xx_get_peripheral_width: bad channel %d\n", dmanr);
+ return DMA_STATUS_BAD_CHANNEL;
+ }
+
+ control = mfdcr(DCRN_DMACR0 + (dmanr * 0x8));
+
+ return (GET_DMA_PW(control));
+}
+
+/*
+ * Clears the channel status bits
+ */
+int
+ppc4xx_clr_dma_status(unsigned int dmanr)
+{
+ if (dmanr >= MAX_PPC4xx_DMA_CHANNELS) {
+ printk(KERN_ERR "ppc4xx_clr_dma_status: bad channel: %d\n", dmanr);
+ return DMA_STATUS_BAD_CHANNEL;
+ }
+ mtdcr(DCRN_DMASR, ((u32)DMA_CH0_ERR | (u32)DMA_CS0 | (u32)DMA_TS0) >> dmanr);
+ return DMA_STATUS_GOOD;
+}
+
+/*
+ * Enables the burst on the channel (BTEN bit in the control/count register)
+ * Note:
+ * For scatter/gather dma, this function MUST be called before the
+ * ppc4xx_alloc_dma_handle() func as the chan count register is copied into the
+ * sgl list and used as each sgl element is added.
+ */
+int
+ppc4xx_enable_burst(unsigned int dmanr)
+{
+ unsigned int ctc;
+ if (dmanr >= MAX_PPC4xx_DMA_CHANNELS) {
+ printk(KERN_ERR "ppc4xx_enable_burst: bad channel: %d\n", dmanr);
+ return DMA_STATUS_BAD_CHANNEL;
+ }
+ ctc = mfdcr(DCRN_DMACT0 + (dmanr * 0x8)) | DMA_CTC_BTEN;
+ mtdcr(DCRN_DMACT0 + (dmanr * 0x8), ctc);
+ return DMA_STATUS_GOOD;
+}
+/*
+ * Disables the burst on the channel (BTEN bit in the control/count register)
+ * Note:
+ * For scatter/gather dma, this function MUST be called before the
+ * ppc4xx_alloc_dma_handle() func as the chan count register is copied into the
+ * sgl list and used as each sgl element is added.
+ */
+int
+ppc4xx_disable_burst(unsigned int dmanr)
+{
+ unsigned int ctc;
+ if (dmanr >= MAX_PPC4xx_DMA_CHANNELS) {
+ printk(KERN_ERR "ppc4xx_disable_burst: bad channel: %d\n", dmanr);
+ return DMA_STATUS_BAD_CHANNEL;
+ }
+ ctc = mfdcr(DCRN_DMACT0 + (dmanr * 0x8)) &~ DMA_CTC_BTEN;
+ mtdcr(DCRN_DMACT0 + (dmanr * 0x8), ctc);
+ return DMA_STATUS_GOOD;
+}
+/*
+ * Sets the burst size (number of peripheral widths) for the channel
+ * (BSIZ bits in the control/count register))
+ * must be one of:
+ * DMA_CTC_BSIZ_2
+ * DMA_CTC_BSIZ_4
+ * DMA_CTC_BSIZ_8
+ * DMA_CTC_BSIZ_16
+ * Note:
+ * For scatter/gather dma, this function MUST be called before the
+ * ppc4xx_alloc_dma_handle() func as the chan count register is copied into the
+ * sgl list and used as each sgl element is added.
+ */
+int
+ppc4xx_set_burst_size(unsigned int dmanr, unsigned int bsize)
+{
+ unsigned int ctc;
+ if (dmanr >= MAX_PPC4xx_DMA_CHANNELS) {
+ printk(KERN_ERR "ppc4xx_set_burst_size: bad channel: %d\n", dmanr);
+ return DMA_STATUS_BAD_CHANNEL;
+ }
+ ctc = mfdcr(DCRN_DMACT0 + (dmanr * 0x8)) &~ DMA_CTC_BSIZ_MSK;
+ ctc |= (bsize & DMA_CTC_BSIZ_MSK);
+ mtdcr(DCRN_DMACT0 + (dmanr * 0x8), ctc);
+ return DMA_STATUS_GOOD;
+}
+
+EXPORT_SYMBOL(ppc4xx_init_dma_channel);
+EXPORT_SYMBOL(ppc4xx_get_channel_config);
+EXPORT_SYMBOL(ppc4xx_set_channel_priority);
+EXPORT_SYMBOL(ppc4xx_get_peripheral_width);
+EXPORT_SYMBOL(dma_channels);
+EXPORT_SYMBOL(ppc4xx_set_src_addr);
+EXPORT_SYMBOL(ppc4xx_set_dst_addr);
+EXPORT_SYMBOL(ppc4xx_set_dma_addr);
+EXPORT_SYMBOL(ppc4xx_set_dma_addr2);
+EXPORT_SYMBOL(ppc4xx_enable_dma);
+EXPORT_SYMBOL(ppc4xx_disable_dma);
+EXPORT_SYMBOL(ppc4xx_set_dma_mode);
+EXPORT_SYMBOL(ppc4xx_set_dma_count);
+EXPORT_SYMBOL(ppc4xx_get_dma_residue);
+EXPORT_SYMBOL(ppc4xx_enable_dma_interrupt);
+EXPORT_SYMBOL(ppc4xx_disable_dma_interrupt);
+EXPORT_SYMBOL(ppc4xx_get_dma_status);
+EXPORT_SYMBOL(ppc4xx_clr_dma_status);
+EXPORT_SYMBOL(ppc4xx_enable_burst);
+EXPORT_SYMBOL(ppc4xx_disable_burst);
+EXPORT_SYMBOL(ppc4xx_set_burst_size);
diff --git a/arch/ppc/syslib/ppc4xx_kgdb.c b/arch/ppc/syslib/ppc4xx_kgdb.c
new file mode 100644
index 0000000..fe8668b
--- /dev/null
+++ b/arch/ppc/syslib/ppc4xx_kgdb.c
@@ -0,0 +1,124 @@
+#include <linux/config.h>
+#include <linux/types.h>
+#include <asm/ibm4xx.h>
+#include <linux/kernel.h>
+
+
+
+#define LSR_DR 0x01 /* Data ready */
+#define LSR_OE 0x02 /* Overrun */
+#define LSR_PE 0x04 /* Parity error */
+#define LSR_FE 0x08 /* Framing error */
+#define LSR_BI 0x10 /* Break */
+#define LSR_THRE 0x20 /* Xmit holding register empty */
+#define LSR_TEMT 0x40 /* Xmitter empty */
+#define LSR_ERR 0x80 /* Error */
+
+#include <platforms/4xx/ibm_ocp.h>
+
+extern struct NS16550* COM_PORTS[];
+#ifndef NULL
+#define NULL 0x00
+#endif
+
+static volatile struct NS16550 *kgdb_debugport = NULL;
+
+volatile struct NS16550 *
+NS16550_init(int chan)
+{
+ volatile struct NS16550 *com_port;
+ int quot;
+#ifdef BASE_BAUD
+ quot = BASE_BAUD / 9600;
+#else
+ quot = 0x000c; /* 0xc = 9600 baud (on a pc) */
+#endif
+
+ com_port = (struct NS16550 *) COM_PORTS[chan];
+
+ com_port->lcr = 0x00;
+ com_port->ier = 0xFF;
+ com_port->ier = 0x00;
+ com_port->lcr = com_port->lcr | 0x80; /* Access baud rate */
+ com_port->dll = ( quot & 0x00ff ); /* 0xc = 9600 baud */
+ com_port->dlm = ( quot & 0xff00 ) >> 8;
+ com_port->lcr = 0x03; /* 8 data, 1 stop, no parity */
+ com_port->mcr = 0x00; /* RTS/DTR */
+ com_port->fcr = 0x07; /* Clear & enable FIFOs */
+
+ return( com_port );
+}
+
+
+void
+NS16550_putc(volatile struct NS16550 *com_port, unsigned char c)
+{
+ while ((com_port->lsr & LSR_THRE) == 0)
+ ;
+ com_port->thr = c;
+ return;
+}
+
+unsigned char
+NS16550_getc(volatile struct NS16550 *com_port)
+{
+ while ((com_port->lsr & LSR_DR) == 0)
+ ;
+ return (com_port->rbr);
+}
+
+unsigned char
+NS16550_tstc(volatile struct NS16550 *com_port)
+{
+ return ((com_port->lsr & LSR_DR) != 0);
+}
+
+
+#if defined(CONFIG_KGDB_TTYS0)
+#define KGDB_PORT 0
+#elif defined(CONFIG_KGDB_TTYS1)
+#define KGDB_PORT 1
+#elif defined(CONFIG_KGDB_TTYS2)
+#define KGDB_PORT 2
+#elif defined(CONFIG_KGDB_TTYS3)
+#define KGDB_PORT 3
+#else
+#error "invalid kgdb_tty port"
+#endif
+
+void putDebugChar( unsigned char c )
+{
+ if ( kgdb_debugport == NULL )
+ kgdb_debugport = NS16550_init(KGDB_PORT);
+ NS16550_putc( kgdb_debugport, c );
+}
+
+int getDebugChar( void )
+{
+ if (kgdb_debugport == NULL)
+ kgdb_debugport = NS16550_init(KGDB_PORT);
+
+ return(NS16550_getc(kgdb_debugport));
+}
+
+void kgdb_interruptible(int enable)
+{
+ return;
+}
+
+void putDebugString(char* str)
+{
+ while (*str != '\0') {
+ putDebugChar(*str);
+ str++;
+ }
+ putDebugChar('\r');
+ return;
+}
+
+void
+kgdb_map_scc(void)
+{
+ printk("kgdb init \n");
+ kgdb_debugport = NS16550_init(KGDB_PORT);
+}
diff --git a/arch/ppc/syslib/ppc4xx_pic.c b/arch/ppc/syslib/ppc4xx_pic.c
new file mode 100644
index 0000000..08f06dd
--- /dev/null
+++ b/arch/ppc/syslib/ppc4xx_pic.c
@@ -0,0 +1,244 @@
+/*
+ * arch/ppc/syslib/ppc4xx_pic.c
+ *
+ * Interrupt controller driver for PowerPC 4xx-based processors.
+ *
+ * Eugene Surovegin <eugene.surovegin@zultys.com> or <ebs@ebshome.net>
+ * Copyright (c) 2004, 2005 Zultys Technologies
+ *
+ * Based on original code by
+ * Copyright (c) 1999 Grant Erickson <grant@lcse.umn.edu>
+ * Armin Custer <akuster@mvista.com>
+ *
+ * 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.
+*/
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/signal.h>
+#include <linux/stddef.h>
+
+#include <asm/processor.h>
+#include <asm/system.h>
+#include <asm/irq.h>
+#include <asm/ppc4xx_pic.h>
+
+/* See comment in include/arch-ppc/ppc4xx_pic.h
+ * for more info about these two variables
+ */
+extern struct ppc4xx_uic_settings ppc4xx_core_uic_cfg[NR_UICS]
+ __attribute__ ((weak));
+extern unsigned char ppc4xx_uic_ext_irq_cfg[] __attribute__ ((weak));
+
+#define IRQ_MASK_UIC0(irq) (1 << (31 - (irq)))
+#define IRQ_MASK_UICx(irq) (1 << (31 - ((irq) & 0x1f)))
+#define IRQ_MASK_UIC1(irq) IRQ_MASK_UICx(irq)
+#define IRQ_MASK_UIC2(irq) IRQ_MASK_UICx(irq)
+
+#define UIC_HANDLERS(n) \
+static void ppc4xx_uic##n##_enable(unsigned int irq) \
+{ \
+ ppc_cached_irq_mask[n] |= IRQ_MASK_UIC##n(irq); \
+ mtdcr(DCRN_UIC_ER(UIC##n), ppc_cached_irq_mask[n]); \
+} \
+ \
+static void ppc4xx_uic##n##_disable(unsigned int irq) \
+{ \
+ ppc_cached_irq_mask[n] &= ~IRQ_MASK_UIC##n(irq); \
+ mtdcr(DCRN_UIC_ER(UIC##n), ppc_cached_irq_mask[n]); \
+ ACK_UIC##n##_PARENT \
+} \
+ \
+static void ppc4xx_uic##n##_ack(unsigned int irq) \
+{ \
+ u32 mask = IRQ_MASK_UIC##n(irq); \
+ ppc_cached_irq_mask[n] &= ~mask; \
+ mtdcr(DCRN_UIC_ER(UIC##n), ppc_cached_irq_mask[n]); \
+ mtdcr(DCRN_UIC_SR(UIC##n), mask); \
+ ACK_UIC##n##_PARENT \
+} \
+ \
+static void ppc4xx_uic##n##_end(unsigned int irq) \
+{ \
+ unsigned int status = irq_desc[irq].status; \
+ u32 mask = IRQ_MASK_UIC##n(irq); \
+ if (status & IRQ_LEVEL) { \
+ mtdcr(DCRN_UIC_SR(UIC##n), mask); \
+ ACK_UIC##n##_PARENT \
+ } \
+ if (!(status & (IRQ_DISABLED | IRQ_INPROGRESS))) { \
+ ppc_cached_irq_mask[n] |= mask; \
+ mtdcr(DCRN_UIC_ER(UIC##n), ppc_cached_irq_mask[n]); \
+ } \
+}
+
+#define DECLARE_UIC(n) \
+{ \
+ .typename = "UIC"#n, \
+ .enable = ppc4xx_uic##n##_enable, \
+ .disable = ppc4xx_uic##n##_disable, \
+ .ack = ppc4xx_uic##n##_ack, \
+ .end = ppc4xx_uic##n##_end, \
+} \
+
+#if NR_UICS == 3
+#define ACK_UIC0_PARENT mtdcr(DCRN_UIC_SR(UICB), UICB_UIC0NC);
+#define ACK_UIC1_PARENT mtdcr(DCRN_UIC_SR(UICB), UICB_UIC1NC);
+#define ACK_UIC2_PARENT mtdcr(DCRN_UIC_SR(UICB), UICB_UIC2NC);
+UIC_HANDLERS(0);
+UIC_HANDLERS(1);
+UIC_HANDLERS(2);
+
+static int ppc4xx_pic_get_irq(struct pt_regs *regs)
+{
+ u32 uicb = mfdcr(DCRN_UIC_MSR(UICB));
+ if (uicb & UICB_UIC0NC)
+ return 32 - ffs(mfdcr(DCRN_UIC_MSR(UIC0)));
+ else if (uicb & UICB_UIC1NC)
+ return 64 - ffs(mfdcr(DCRN_UIC_MSR(UIC1)));
+ else if (uicb & UICB_UIC2NC)
+ return 96 - ffs(mfdcr(DCRN_UIC_MSR(UIC2)));
+ else
+ return -1;
+}
+
+static void __init ppc4xx_pic_impl_init(void)
+{
+ /* Configure Base UIC */
+ mtdcr(DCRN_UIC_CR(UICB), 0);
+ mtdcr(DCRN_UIC_TR(UICB), 0);
+ mtdcr(DCRN_UIC_PR(UICB), 0xffffffff);
+ mtdcr(DCRN_UIC_SR(UICB), 0xffffffff);
+ mtdcr(DCRN_UIC_ER(UICB), UICB_UIC0NC | UICB_UIC1NC | UICB_UIC2NC);
+}
+
+#elif NR_UICS == 2
+#define ACK_UIC0_PARENT
+#define ACK_UIC1_PARENT mtdcr(DCRN_UIC_SR(UIC0), UIC0_UIC1NC);
+UIC_HANDLERS(0);
+UIC_HANDLERS(1);
+
+static int ppc4xx_pic_get_irq(struct pt_regs *regs)
+{
+ u32 uic0 = mfdcr(DCRN_UIC_MSR(UIC0));
+ if (uic0 & UIC0_UIC1NC)
+ return 64 - ffs(mfdcr(DCRN_UIC_MSR(UIC1)));
+ else
+ return uic0 ? 32 - ffs(uic0) : -1;
+}
+
+static void __init ppc4xx_pic_impl_init(void)
+{
+ /* Enable cascade interrupt in UIC0 */
+ ppc_cached_irq_mask[0] |= UIC0_UIC1NC;
+ mtdcr(DCRN_UIC_SR(UIC0), UIC0_UIC1NC);
+ mtdcr(DCRN_UIC_ER(UIC0), ppc_cached_irq_mask[0]);
+}
+
+#elif NR_UICS == 1
+#define ACK_UIC0_PARENT
+UIC_HANDLERS(0);
+
+static int ppc4xx_pic_get_irq(struct pt_regs *regs)
+{
+ u32 uic0 = mfdcr(DCRN_UIC_MSR(UIC0));
+ return uic0 ? 32 - ffs(uic0) : -1;
+}
+
+static inline void ppc4xx_pic_impl_init(void)
+{
+}
+#endif
+
+static struct ppc4xx_uic_impl {
+ struct hw_interrupt_type decl;
+ int base; /* Base DCR number */
+} __uic[] = {
+ { .decl = DECLARE_UIC(0), .base = UIC0 },
+#if NR_UICS > 1
+ { .decl = DECLARE_UIC(1), .base = UIC1 },
+#if NR_UICS > 2
+ { .decl = DECLARE_UIC(2), .base = UIC2 },
+#endif
+#endif
+};
+
+static inline int is_level_sensitive(int irq)
+{
+ u32 tr = mfdcr(DCRN_UIC_TR(__uic[irq >> 5].base));
+ return (tr & IRQ_MASK_UICx(irq)) == 0;
+}
+
+void __init ppc4xx_pic_init(void)
+{
+ int i;
+ unsigned char *eirqs = ppc4xx_uic_ext_irq_cfg;
+
+ for (i = 0; i < NR_UICS; ++i) {
+ int base = __uic[i].base;
+
+ /* Disable everything by default */
+ ppc_cached_irq_mask[i] = 0;
+ mtdcr(DCRN_UIC_ER(base), 0);
+
+ /* We don't use critical interrupts */
+ mtdcr(DCRN_UIC_CR(base), 0);
+
+ /* Configure polarity and triggering */
+ if (ppc4xx_core_uic_cfg) {
+ struct ppc4xx_uic_settings *p = ppc4xx_core_uic_cfg + i;
+ u32 mask = p->ext_irq_mask;
+ u32 pr = mfdcr(DCRN_UIC_PR(base)) & mask;
+ u32 tr = mfdcr(DCRN_UIC_TR(base)) & mask;
+
+ /* "Fixed" interrupts (on-chip devices) */
+ pr |= p->polarity & ~mask;
+ tr |= p->triggering & ~mask;
+
+ /* Merge external IRQs settings if board port
+ * provided them
+ */
+ if (eirqs && mask) {
+ pr &= ~mask;
+ tr &= ~mask;
+ while (mask) {
+ /* Extract current external IRQ mask */
+ u32 eirq_mask = 1 << __ilog2(mask);
+
+ if (!(*eirqs & IRQ_SENSE_LEVEL))
+ tr |= eirq_mask;
+
+ if (*eirqs & IRQ_POLARITY_POSITIVE)
+ pr |= eirq_mask;
+
+ mask &= ~eirq_mask;
+ ++eirqs;
+ }
+ }
+ mtdcr(DCRN_UIC_PR(base), pr);
+ mtdcr(DCRN_UIC_TR(base), tr);
+ }
+
+ /* ACK any pending interrupts to prevent false
+ * triggering after first enable
+ */
+ mtdcr(DCRN_UIC_SR(base), 0xffffffff);
+ }
+
+ /* Perform optional implementation specific setup
+ * (e.g. enable cascade interrupts for multi-UIC configurations)
+ */
+ ppc4xx_pic_impl_init();
+
+ /* Attach low-level handlers */
+ for (i = 0; i < (NR_UICS << 5); ++i) {
+ irq_desc[i].handler = &__uic[i >> 5].decl;
+ if (is_level_sensitive(i))
+ irq_desc[i].status |= IRQ_LEVEL;
+ }
+
+ ppc_md.get_irq = ppc4xx_pic_get_irq;
+}
diff --git a/arch/ppc/syslib/ppc4xx_pm.c b/arch/ppc/syslib/ppc4xx_pm.c
new file mode 100644
index 0000000..60a4792
--- /dev/null
+++ b/arch/ppc/syslib/ppc4xx_pm.c
@@ -0,0 +1,47 @@
+/*
+ * Author: Armin Kuster <akuster@mvista.com>
+ *
+ * 2002 (c) MontaVista, Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ *
+ * This an attempt to get Power Management going for the IBM 4xx processor.
+ * This was derived from the ppc4xx._setup.c file
+ */
+
+#include <linux/config.h>
+#include <linux/init.h>
+
+#include <asm/ibm4xx.h>
+
+void __init
+ppc4xx_pm_init(void)
+{
+
+ unsigned int value = 0;
+
+ /* turn off unused hardware to save power */
+#ifdef CONFIG_405GP
+ value |= CPM_DCP; /* CodePack */
+#endif
+
+#if !defined(CONFIG_IBM_OCP_GPIO)
+ value |= CPM_GPIO0;
+#endif
+
+#if !defined(CONFIG_PPC405_I2C_ADAP)
+ value |= CPM_IIC0;
+#ifdef CONFIG_STB03xxx
+ value |= CPM_IIC1;
+#endif
+#endif
+
+
+#if !defined(CONFIG_405_DMA)
+ value |= CPM_DMA;
+#endif
+
+ mtdcr(DCRN_CPMFR, value);
+
+}
diff --git a/arch/ppc/syslib/ppc4xx_setup.c b/arch/ppc/syslib/ppc4xx_setup.c
new file mode 100644
index 0000000..e170aeb
--- /dev/null
+++ b/arch/ppc/syslib/ppc4xx_setup.c
@@ -0,0 +1,321 @@
+/*
+ *
+ * Copyright (c) 1999-2000 Grant Erickson <grant@lcse.umn.edu>
+ *
+ * Copyright 2000-2001 MontaVista Software Inc.
+ * Completed implementation.
+ * Author: MontaVista Software, Inc. <source@mvista.com>
+ * Frank Rowand <frank_rowand@mvista.com>
+ * Debbie Chu <debbie_chu@mvista.com>
+ * Further modifications by Armin Kuster
+ *
+ * Module name: ppc4xx_setup.c
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/smp.h>
+#include <linux/threads.h>
+#include <linux/spinlock.h>
+#include <linux/irq.h>
+#include <linux/reboot.h>
+#include <linux/param.h>
+#include <linux/string.h>
+#include <linux/initrd.h>
+#include <linux/pci.h>
+#include <linux/rtc.h>
+#include <linux/console.h>
+#include <linux/ide.h>
+#include <linux/serial_reg.h>
+#include <linux/seq_file.h>
+
+#include <asm/system.h>
+#include <asm/processor.h>
+#include <asm/machdep.h>
+#include <asm/page.h>
+#include <asm/kgdb.h>
+#include <asm/ibm4xx.h>
+#include <asm/time.h>
+#include <asm/todc.h>
+#include <asm/ppc4xx_pic.h>
+#include <asm/pci-bridge.h>
+#include <asm/bootinfo.h>
+
+#include <syslib/gen550.h>
+
+/* Function Prototypes */
+extern void abort(void);
+extern void ppc4xx_find_bridges(void);
+
+extern void ppc4xx_wdt_heartbeat(void);
+extern int wdt_enable;
+extern unsigned long wdt_period;
+
+/* Global Variables */
+bd_t __res;
+
+void __init
+ppc4xx_setup_arch(void)
+{
+#if !defined(CONFIG_BDI_SWITCH)
+ /*
+ * The Abatron BDI JTAG debugger does not tolerate others
+ * mucking with the debug registers.
+ */
+ mtspr(SPRN_DBCR0, (DBCR0_IDM));
+ mtspr(SPRN_DBSR, 0xffffffff);
+#endif
+
+ /* Setup PCI host bridges */
+#ifdef CONFIG_PCI
+ ppc4xx_find_bridges();
+#endif
+}
+
+/*
+ * This routine pretty-prints the platform's internal CPU clock
+ * frequencies into the buffer for usage in /proc/cpuinfo.
+ */
+
+static int
+ppc4xx_show_percpuinfo(struct seq_file *m, int i)
+{
+ seq_printf(m, "clock\t\t: %ldMHz\n", (long)__res.bi_intfreq / 1000000);
+
+ return 0;
+}
+
+/*
+ * This routine pretty-prints the platform's internal bus clock
+ * frequencies into the buffer for usage in /proc/cpuinfo.
+ */
+static int
+ppc4xx_show_cpuinfo(struct seq_file *m)
+{
+ bd_t *bip = &__res;
+
+ seq_printf(m, "machine\t\t: %s\n", PPC4xx_MACHINE_NAME);
+ seq_printf(m, "plb bus clock\t: %ldMHz\n",
+ (long) bip->bi_busfreq / 1000000);
+#ifdef CONFIG_PCI
+ seq_printf(m, "pci bus clock\t: %dMHz\n",
+ bip->bi_pci_busfreq / 1000000);
+#endif
+
+ return 0;
+}
+
+/*
+ * Return the virtual address representing the top of physical RAM.
+ */
+static unsigned long __init
+ppc4xx_find_end_of_memory(void)
+{
+ return ((unsigned long) __res.bi_memsize);
+}
+
+void __init
+ppc4xx_map_io(void)
+{
+ io_block_mapping(PPC4xx_ONB_IO_VADDR,
+ PPC4xx_ONB_IO_PADDR, PPC4xx_ONB_IO_SIZE, _PAGE_IO);
+#ifdef CONFIG_PCI
+ io_block_mapping(PPC4xx_PCI_IO_VADDR,
+ PPC4xx_PCI_IO_PADDR, PPC4xx_PCI_IO_SIZE, _PAGE_IO);
+ io_block_mapping(PPC4xx_PCI_CFG_VADDR,
+ PPC4xx_PCI_CFG_PADDR, PPC4xx_PCI_CFG_SIZE, _PAGE_IO);
+ io_block_mapping(PPC4xx_PCI_LCFG_VADDR,
+ PPC4xx_PCI_LCFG_PADDR, PPC4xx_PCI_LCFG_SIZE, _PAGE_IO);
+#endif
+}
+
+void __init
+ppc4xx_init_IRQ(void)
+{
+ ppc4xx_pic_init();
+}
+
+static void
+ppc4xx_restart(char *cmd)
+{
+ printk("%s\n", cmd);
+ abort();
+}
+
+static void
+ppc4xx_power_off(void)
+{
+ printk("System Halted\n");
+ local_irq_disable();
+ while (1) ;
+}
+
+static void
+ppc4xx_halt(void)
+{
+ printk("System Halted\n");
+ local_irq_disable();
+ while (1) ;
+}
+
+/*
+ * This routine retrieves the internal processor frequency from the board
+ * information structure, sets up the kernel timer decrementer based on
+ * that value, enables the 4xx programmable interval timer (PIT) and sets
+ * it up for auto-reload.
+ */
+static void __init
+ppc4xx_calibrate_decr(void)
+{
+ unsigned int freq;
+ bd_t *bip = &__res;
+
+#if defined(CONFIG_WALNUT) || defined(CONFIG_ASH) || defined(CONFIG_SYCAMORE)
+ /* Walnut boot rom sets DCR CHCR1 (aka CPC0_CR1) bit CETE to 1 */
+ mtdcr(DCRN_CHCR1, mfdcr(DCRN_CHCR1) & ~CHR1_CETE);
+#endif
+ freq = bip->bi_tbfreq;
+ tb_ticks_per_jiffy = freq / HZ;
+ tb_to_us = mulhwu_scale_factor(freq, 1000000);
+
+ /* Set the time base to zero.
+ ** At 200 Mhz, time base will rollover in ~2925 years.
+ */
+
+ mtspr(SPRN_TBWL, 0);
+ mtspr(SPRN_TBWU, 0);
+
+ /* Clear any pending timer interrupts */
+
+ mtspr(SPRN_TSR, TSR_ENW | TSR_WIS | TSR_PIS | TSR_FIS);
+ mtspr(SPRN_TCR, TCR_PIE | TCR_ARE);
+
+ /* Set the PIT reload value and just let it run. */
+ mtspr(SPRN_PIT, tb_ticks_per_jiffy);
+}
+
+/*
+ * IDE stuff.
+ * should be generic for every IDE PCI chipset
+ */
+#if defined(CONFIG_PCI) && defined(CONFIG_IDE)
+static void
+ppc4xx_ide_init_hwif_ports(hw_regs_t * hw, unsigned long data_port,
+ unsigned long ctrl_port, int *irq)
+{
+ int i;
+
+ for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; ++i)
+ hw->io_ports[i] = data_port + i - IDE_DATA_OFFSET;
+
+ hw->io_ports[IDE_CONTROL_OFFSET] = ctrl_port;
+}
+#endif /* defined(CONFIG_PCI) && defined(CONFIG_IDE) */
+
+TODC_ALLOC();
+
+/*
+ * Input(s):
+ * r3 - Optional pointer to a board information structure.
+ * r4 - Optional pointer to the physical starting address of the init RAM
+ * disk.
+ * r5 - Optional pointer to the physical ending address of the init RAM
+ * disk.
+ * r6 - Optional pointer to the physical starting address of any kernel
+ * command-line parameters.
+ * r7 - Optional pointer to the physical ending address of any kernel
+ * command-line parameters.
+ */
+void __init
+ppc4xx_init(unsigned long r3, unsigned long r4, unsigned long r5,
+ unsigned long r6, unsigned long r7)
+{
+ parse_bootinfo(find_bootinfo());
+
+ /*
+ * If we were passed in a board information, copy it into the
+ * residual data area.
+ */
+ if (r3)
+ __res = *(bd_t *)(r3 + KERNELBASE);
+
+#if defined(CONFIG_BLK_DEV_INITRD)
+ /*
+ * If the init RAM disk has been configured in, and there's a valid
+ * starting address for it, set it up.
+ */
+ if (r4) {
+ initrd_start = r4 + KERNELBASE;
+ initrd_end = r5 + KERNELBASE;
+ }
+#endif /* CONFIG_BLK_DEV_INITRD */
+
+ /* Copy the kernel command line arguments to a safe place. */
+
+ if (r6) {
+ *(char *) (r7 + KERNELBASE) = 0;
+ strcpy(cmd_line, (char *) (r6 + KERNELBASE));
+ }
+#if defined(CONFIG_PPC405_WDT)
+/* Look for wdt= option on command line */
+ if (strstr(cmd_line, "wdt=")) {
+ int valid_wdt = 0;
+ char *p, *q;
+ for (q = cmd_line; (p = strstr(q, "wdt=")) != 0;) {
+ q = p + 4;
+ if (p > cmd_line && p[-1] != ' ')
+ continue;
+ wdt_period = simple_strtoul(q, &q, 0);
+ valid_wdt = 1;
+ ++q;
+ }
+ wdt_enable = valid_wdt;
+ }
+#endif
+
+ /* Initialize machine-dependent vectors */
+
+ ppc_md.setup_arch = ppc4xx_setup_arch;
+ ppc_md.show_percpuinfo = ppc4xx_show_percpuinfo;
+ ppc_md.show_cpuinfo = ppc4xx_show_cpuinfo;
+ ppc_md.init_IRQ = ppc4xx_init_IRQ;
+
+ ppc_md.restart = ppc4xx_restart;
+ ppc_md.power_off = ppc4xx_power_off;
+ ppc_md.halt = ppc4xx_halt;
+
+ ppc_md.calibrate_decr = ppc4xx_calibrate_decr;
+
+#ifdef CONFIG_PPC405_WDT
+ ppc_md.heartbeat = ppc4xx_wdt_heartbeat;
+#endif
+ ppc_md.heartbeat_count = 0;
+
+ ppc_md.find_end_of_memory = ppc4xx_find_end_of_memory;
+ ppc_md.setup_io_mappings = ppc4xx_map_io;
+
+#ifdef CONFIG_SERIAL_TEXT_DEBUG
+ ppc_md.progress = gen550_progress;
+#endif
+
+#if defined(CONFIG_PCI) && defined(CONFIG_IDE)
+ ppc_ide_md.ide_init_hwif = ppc4xx_ide_init_hwif_ports;
+#endif /* defined(CONFIG_PCI) && defined(CONFIG_IDE) */
+}
+
+/* Called from MachineCheckException */
+void platform_machine_check(struct pt_regs *regs)
+{
+#if defined(DCRN_PLB0_BEAR)
+ printk("PLB0: BEAR= 0x%08x ACR= 0x%08x BESR= 0x%08x\n",
+ mfdcr(DCRN_PLB0_BEAR), mfdcr(DCRN_PLB0_ACR),
+ mfdcr(DCRN_PLB0_BESR));
+#endif
+#if defined(DCRN_POB0_BEAR)
+ printk("PLB0 to OPB: BEAR= 0x%08x BESR0= 0x%08x BESR1= 0x%08x\n",
+ mfdcr(DCRN_POB0_BEAR), mfdcr(DCRN_POB0_BESR0),
+ mfdcr(DCRN_POB0_BESR1));
+#endif
+
+}
diff --git a/arch/ppc/syslib/ppc4xx_sgdma.c b/arch/ppc/syslib/ppc4xx_sgdma.c
new file mode 100644
index 0000000..9f76e8e
--- /dev/null
+++ b/arch/ppc/syslib/ppc4xx_sgdma.c
@@ -0,0 +1,467 @@
+/*
+ * arch/ppc/kernel/ppc4xx_sgdma.c
+ *
+ * IBM PPC4xx DMA engine scatter/gather library
+ *
+ * Copyright 2002-2003 MontaVista Software Inc.
+ *
+ * Cleaned up and converted to new DCR access
+ * Matt Porter <mporter@kernel.crashing.org>
+ *
+ * Original code by Armin Kuster <akuster@mvista.com>
+ * and Pete Popov <ppopov@mvista.com>
+ *
+ * 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.
+ *
+ * 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.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+
+#include <asm/system.h>
+#include <asm/io.h>
+#include <asm/ppc4xx_dma.h>
+
+void
+ppc4xx_set_sg_addr(int dmanr, phys_addr_t sg_addr)
+{
+ if (dmanr >= MAX_PPC4xx_DMA_CHANNELS) {
+ printk("ppc4xx_set_sg_addr: bad channel: %d\n", dmanr);
+ return;
+ }
+
+#ifdef PPC4xx_DMA_64BIT
+ mtdcr(DCRN_ASGH0 + (dmanr * 0x8), (u32)(sg_addr >> 32));
+#endif
+ mtdcr(DCRN_ASG0 + (dmanr * 0x8), (u32)sg_addr);
+}
+
+/*
+ * Add a new sgl descriptor to the end of a scatter/gather list
+ * which was created by alloc_dma_handle().
+ *
+ * For a memory to memory transfer, both dma addresses must be
+ * valid. For a peripheral to memory transfer, one of the addresses
+ * must be set to NULL, depending on the direction of the transfer:
+ * memory to peripheral: set dst_addr to NULL,
+ * peripheral to memory: set src_addr to NULL.
+ */
+int
+ppc4xx_add_dma_sgl(sgl_handle_t handle, phys_addr_t src_addr, phys_addr_t dst_addr,
+ unsigned int count)
+{
+ sgl_list_info_t *psgl = (sgl_list_info_t *) handle;
+ ppc_dma_ch_t *p_dma_ch;
+
+ if (!handle) {
+ printk("ppc4xx_add_dma_sgl: null handle\n");
+ return DMA_STATUS_BAD_HANDLE;
+ }
+
+ if (psgl->dmanr >= MAX_PPC4xx_DMA_CHANNELS) {
+ printk("ppc4xx_add_dma_sgl: bad channel: %d\n", psgl->dmanr);
+ return DMA_STATUS_BAD_CHANNEL;
+ }
+
+ p_dma_ch = &dma_channels[psgl->dmanr];
+
+#ifdef DEBUG_4xxDMA
+ {
+ int error = 0;
+ unsigned int aligned =
+ (unsigned) src_addr | (unsigned) dst_addr | count;
+ switch (p_dma_ch->pwidth) {
+ case PW_8:
+ break;
+ case PW_16:
+ if (aligned & 0x1)
+ error = 1;
+ break;
+ case PW_32:
+ if (aligned & 0x3)
+ error = 1;
+ break;
+ case PW_64:
+ if (aligned & 0x7)
+ error = 1;
+ break;
+ default:
+ printk("ppc4xx_add_dma_sgl: invalid bus width: 0x%x\n",
+ p_dma_ch->pwidth);
+ return DMA_STATUS_GENERAL_ERROR;
+ }
+ if (error)
+ printk
+ ("Alignment warning: ppc4xx_add_dma_sgl src 0x%x dst 0x%x count 0x%x bus width var %d\n",
+ src_addr, dst_addr, count, p_dma_ch->pwidth);
+
+ }
+#endif
+
+ if ((unsigned) (psgl->ptail + 1) >= ((unsigned) psgl + SGL_LIST_SIZE)) {
+ printk("sgl handle out of memory \n");
+ return DMA_STATUS_OUT_OF_MEMORY;
+ }
+
+ if (!psgl->ptail) {
+ psgl->phead = (ppc_sgl_t *)
+ ((unsigned) psgl + sizeof (sgl_list_info_t));
+ psgl->phead_dma = psgl->dma_addr + sizeof(sgl_list_info_t);
+ psgl->ptail = psgl->phead;
+ psgl->ptail_dma = psgl->phead_dma;
+ } else {
+ if(p_dma_ch->int_on_final_sg) {
+ /* mask out all dma interrupts, except error, on tail
+ before adding new tail. */
+ psgl->ptail->control_count &=
+ ~(SG_TCI_ENABLE | SG_ETI_ENABLE);
+ }
+ psgl->ptail->next = psgl->ptail_dma + sizeof(ppc_sgl_t);
+ psgl->ptail++;
+ psgl->ptail_dma += sizeof(ppc_sgl_t);
+ }
+
+ psgl->ptail->control = psgl->control;
+ psgl->ptail->src_addr = src_addr;
+ psgl->ptail->dst_addr = dst_addr;
+ psgl->ptail->control_count = (count >> p_dma_ch->shift) |
+ psgl->sgl_control;
+ psgl->ptail->next = (uint32_t) NULL;
+
+ return DMA_STATUS_GOOD;
+}
+
+/*
+ * Enable (start) the DMA described by the sgl handle.
+ */
+void
+ppc4xx_enable_dma_sgl(sgl_handle_t handle)
+{
+ sgl_list_info_t *psgl = (sgl_list_info_t *) handle;
+ ppc_dma_ch_t *p_dma_ch;
+ uint32_t sg_command;
+
+ if (!handle) {
+ printk("ppc4xx_enable_dma_sgl: null handle\n");
+ return;
+ } else if (psgl->dmanr > (MAX_PPC4xx_DMA_CHANNELS - 1)) {
+ printk("ppc4xx_enable_dma_sgl: bad channel in handle %d\n",
+ psgl->dmanr);
+ return;
+ } else if (!psgl->phead) {
+ printk("ppc4xx_enable_dma_sgl: sg list empty\n");
+ return;
+ }
+
+ p_dma_ch = &dma_channels[psgl->dmanr];
+ psgl->ptail->control_count &= ~SG_LINK; /* make this the last dscrptr */
+ sg_command = mfdcr(DCRN_ASGC);
+
+ ppc4xx_set_sg_addr(psgl->dmanr, psgl->phead_dma);
+
+ sg_command |= SSG_ENABLE(psgl->dmanr);
+
+ mtdcr(DCRN_ASGC, sg_command); /* start transfer */
+}
+
+/*
+ * Halt an active scatter/gather DMA operation.
+ */
+void
+ppc4xx_disable_dma_sgl(sgl_handle_t handle)
+{
+ sgl_list_info_t *psgl = (sgl_list_info_t *) handle;
+ uint32_t sg_command;
+
+ if (!handle) {
+ printk("ppc4xx_enable_dma_sgl: null handle\n");
+ return;
+ } else if (psgl->dmanr > (MAX_PPC4xx_DMA_CHANNELS - 1)) {
+ printk("ppc4xx_enable_dma_sgl: bad channel in handle %d\n",
+ psgl->dmanr);
+ return;
+ }
+
+ sg_command = mfdcr(DCRN_ASGC);
+ sg_command &= ~SSG_ENABLE(psgl->dmanr);
+ mtdcr(DCRN_ASGC, sg_command); /* stop transfer */
+}
+
+/*
+ * Returns number of bytes left to be transferred from the entire sgl list.
+ * *src_addr and *dst_addr get set to the source/destination address of
+ * the sgl descriptor where the DMA stopped.
+ *
+ * An sgl transfer must NOT be active when this function is called.
+ */
+int
+ppc4xx_get_dma_sgl_residue(sgl_handle_t handle, phys_addr_t * src_addr,
+ phys_addr_t * dst_addr)
+{
+ sgl_list_info_t *psgl = (sgl_list_info_t *) handle;
+ ppc_dma_ch_t *p_dma_ch;
+ ppc_sgl_t *pnext, *sgl_addr;
+ uint32_t count_left;
+
+ if (!handle) {
+ printk("ppc4xx_get_dma_sgl_residue: null handle\n");
+ return DMA_STATUS_BAD_HANDLE;
+ } else if (psgl->dmanr > (MAX_PPC4xx_DMA_CHANNELS - 1)) {
+ printk("ppc4xx_get_dma_sgl_residue: bad channel in handle %d\n",
+ psgl->dmanr);
+ return DMA_STATUS_BAD_CHANNEL;
+ }
+
+ sgl_addr = (ppc_sgl_t *) __va(mfdcr(DCRN_ASG0 + (psgl->dmanr * 0x8)));
+ count_left = mfdcr(DCRN_DMACT0 + (psgl->dmanr * 0x8)) & SG_COUNT_MASK;
+
+ if (!sgl_addr) {
+ printk("ppc4xx_get_dma_sgl_residue: sgl addr register is null\n");
+ goto error;
+ }
+
+ pnext = psgl->phead;
+ while (pnext &&
+ ((unsigned) pnext < ((unsigned) psgl + SGL_LIST_SIZE) &&
+ (pnext != sgl_addr))
+ ) {
+ pnext++;
+ }
+
+ if (pnext == sgl_addr) { /* found the sgl descriptor */
+
+ *src_addr = pnext->src_addr;
+ *dst_addr = pnext->dst_addr;
+
+ /*
+ * Now search the remaining descriptors and add their count.
+ * We already have the remaining count from this descriptor in
+ * count_left.
+ */
+ pnext++;
+
+ while ((pnext != psgl->ptail) &&
+ ((unsigned) pnext < ((unsigned) psgl + SGL_LIST_SIZE))
+ ) {
+ count_left += pnext->control_count & SG_COUNT_MASK;
+ }
+
+ if (pnext != psgl->ptail) { /* should never happen */
+ printk
+ ("ppc4xx_get_dma_sgl_residue error (1) psgl->ptail 0x%x handle 0x%x\n",
+ (unsigned int) psgl->ptail, (unsigned int) handle);
+ goto error;
+ }
+
+ /* success */
+ p_dma_ch = &dma_channels[psgl->dmanr];
+ return (count_left << p_dma_ch->shift); /* count in bytes */
+
+ } else {
+ /* this shouldn't happen */
+ printk
+ ("get_dma_sgl_residue, unable to match current address 0x%x, handle 0x%x\n",
+ (unsigned int) sgl_addr, (unsigned int) handle);
+
+ }
+
+ error:
+ *src_addr = (phys_addr_t) NULL;
+ *dst_addr = (phys_addr_t) NULL;
+ return 0;
+}
+
+/*
+ * Returns the address(es) of the buffer(s) contained in the head element of
+ * the scatter/gather list. The element is removed from the scatter/gather
+ * list and the next element becomes the head.
+ *
+ * This function should only be called when the DMA is not active.
+ */
+int
+ppc4xx_delete_dma_sgl_element(sgl_handle_t handle, phys_addr_t * src_dma_addr,
+ phys_addr_t * dst_dma_addr)
+{
+ sgl_list_info_t *psgl = (sgl_list_info_t *) handle;
+
+ if (!handle) {
+ printk("ppc4xx_delete_sgl_element: null handle\n");
+ return DMA_STATUS_BAD_HANDLE;
+ } else if (psgl->dmanr > (MAX_PPC4xx_DMA_CHANNELS - 1)) {
+ printk("ppc4xx_delete_sgl_element: bad channel in handle %d\n",
+ psgl->dmanr);
+ return DMA_STATUS_BAD_CHANNEL;
+ }
+
+ if (!psgl->phead) {
+ printk("ppc4xx_delete_sgl_element: sgl list empty\n");
+ *src_dma_addr = (phys_addr_t) NULL;
+ *dst_dma_addr = (phys_addr_t) NULL;
+ return DMA_STATUS_SGL_LIST_EMPTY;
+ }
+
+ *src_dma_addr = (phys_addr_t) psgl->phead->src_addr;
+ *dst_dma_addr = (phys_addr_t) psgl->phead->dst_addr;
+
+ if (psgl->phead == psgl->ptail) {
+ /* last descriptor on the list */
+ psgl->phead = NULL;
+ psgl->ptail = NULL;
+ } else {
+ psgl->phead++;
+ psgl->phead_dma += sizeof(ppc_sgl_t);
+ }
+
+ return DMA_STATUS_GOOD;
+}
+
+
+/*
+ * Create a scatter/gather list handle. This is simply a structure which
+ * describes a scatter/gather list.
+ *
+ * A handle is returned in "handle" which the driver should save in order to
+ * be able to access this list later. A chunk of memory will be allocated
+ * to be used by the API for internal management purposes, including managing
+ * the sg list and allocating memory for the sgl descriptors. One page should
+ * be more than enough for that purpose. Perhaps it's a bit wasteful to use
+ * a whole page for a single sg list, but most likely there will be only one
+ * sg list per channel.
+ *
+ * Interrupt notes:
+ * Each sgl descriptor has a copy of the DMA control word which the DMA engine
+ * loads in the control register. The control word has a "global" interrupt
+ * enable bit for that channel. Interrupts are further qualified by a few bits
+ * in the sgl descriptor count register. In order to setup an sgl, we have to
+ * know ahead of time whether or not interrupts will be enabled at the completion
+ * of the transfers. Thus, enable_dma_interrupt()/disable_dma_interrupt() MUST
+ * be called before calling alloc_dma_handle(). If the interrupt mode will never
+ * change after powerup, then enable_dma_interrupt()/disable_dma_interrupt()
+ * do not have to be called -- interrupts will be enabled or disabled based
+ * on how the channel was configured after powerup by the hw_init_dma_channel()
+ * function. Each sgl descriptor will be setup to interrupt if an error occurs;
+ * however, only the last descriptor will be setup to interrupt. Thus, an
+ * interrupt will occur (if interrupts are enabled) only after the complete
+ * sgl transfer is done.
+ */
+int
+ppc4xx_alloc_dma_handle(sgl_handle_t * phandle, unsigned int mode, unsigned int dmanr)
+{
+ sgl_list_info_t *psgl=NULL;
+ dma_addr_t dma_addr;
+ ppc_dma_ch_t *p_dma_ch = &dma_channels[dmanr];
+ uint32_t sg_command;
+ uint32_t ctc_settings;
+ void *ret;
+
+ if (dmanr >= MAX_PPC4xx_DMA_CHANNELS) {
+ printk("ppc4xx_alloc_dma_handle: invalid channel 0x%x\n", dmanr);
+ return DMA_STATUS_BAD_CHANNEL;
+ }
+
+ if (!phandle) {
+ printk("ppc4xx_alloc_dma_handle: null handle pointer\n");
+ return DMA_STATUS_NULL_POINTER;
+ }
+
+ /* Get a page of memory, which is zeroed out by consistent_alloc() */
+ ret = dma_alloc_coherent(NULL, DMA_PPC4xx_SIZE, &dma_addr, GFP_KERNEL);
+ if (ret != NULL) {
+ memset(ret, 0, DMA_PPC4xx_SIZE);
+ psgl = (sgl_list_info_t *) ret;
+ }
+
+ if (psgl == NULL) {
+ *phandle = (sgl_handle_t) NULL;
+ return DMA_STATUS_OUT_OF_MEMORY;
+ }
+
+ psgl->dma_addr = dma_addr;
+ psgl->dmanr = dmanr;
+
+ /*
+ * Modify and save the control word. These words will be
+ * written to each sgl descriptor. The DMA engine then
+ * loads this control word into the control register
+ * every time it reads a new descriptor.
+ */
+ psgl->control = p_dma_ch->control;
+ /* Clear all mode bits */
+ psgl->control &= ~(DMA_TM_MASK | DMA_TD);
+ /* Save control word and mode */
+ psgl->control |= (mode | DMA_CE_ENABLE);
+
+ /* In MM mode, we must set ETD/TCE */
+ if (mode == DMA_MODE_MM)
+ psgl->control |= DMA_ETD_OUTPUT | DMA_TCE_ENABLE;
+
+ if (p_dma_ch->int_enable) {
+ /* Enable channel interrupt */
+ psgl->control |= DMA_CIE_ENABLE;
+ } else {
+ psgl->control &= ~DMA_CIE_ENABLE;
+ }
+
+ sg_command = mfdcr(DCRN_ASGC);
+ sg_command |= SSG_MASK_ENABLE(dmanr);
+
+ /* Enable SGL control access */
+ mtdcr(DCRN_ASGC, sg_command);
+ psgl->sgl_control = SG_ERI_ENABLE | SG_LINK;
+
+ /* keep control count register settings */
+ ctc_settings = mfdcr(DCRN_DMACT0 + (dmanr * 0x8))
+ & (DMA_CTC_BSIZ_MSK | DMA_CTC_BTEN); /*burst mode settings*/
+ psgl->sgl_control |= ctc_settings;
+
+ if (p_dma_ch->int_enable) {
+ if (p_dma_ch->tce_enable)
+ psgl->sgl_control |= SG_TCI_ENABLE;
+ else
+ psgl->sgl_control |= SG_ETI_ENABLE;
+ }
+
+ *phandle = (sgl_handle_t) psgl;
+ return DMA_STATUS_GOOD;
+}
+
+/*
+ * Destroy a scatter/gather list handle that was created by alloc_dma_handle().
+ * The list must be empty (contain no elements).
+ */
+void
+ppc4xx_free_dma_handle(sgl_handle_t handle)
+{
+ sgl_list_info_t *psgl = (sgl_list_info_t *) handle;
+
+ if (!handle) {
+ printk("ppc4xx_free_dma_handle: got NULL\n");
+ return;
+ } else if (psgl->phead) {
+ printk("ppc4xx_free_dma_handle: list not empty\n");
+ return;
+ } else if (!psgl->dma_addr) { /* should never happen */
+ printk("ppc4xx_free_dma_handle: no dma address\n");
+ return;
+ }
+
+ dma_free_coherent(NULL, DMA_PPC4xx_SIZE, (void *) psgl, 0);
+}
+
+EXPORT_SYMBOL(ppc4xx_alloc_dma_handle);
+EXPORT_SYMBOL(ppc4xx_free_dma_handle);
+EXPORT_SYMBOL(ppc4xx_add_dma_sgl);
+EXPORT_SYMBOL(ppc4xx_delete_dma_sgl_element);
+EXPORT_SYMBOL(ppc4xx_enable_dma_sgl);
+EXPORT_SYMBOL(ppc4xx_disable_dma_sgl);
+EXPORT_SYMBOL(ppc4xx_get_dma_sgl_residue);
diff --git a/arch/ppc/syslib/ppc83xx_setup.c b/arch/ppc/syslib/ppc83xx_setup.c
new file mode 100644
index 0000000..c28f9d6
--- /dev/null
+++ b/arch/ppc/syslib/ppc83xx_setup.c
@@ -0,0 +1,138 @@
+/*
+ * arch/ppc/syslib/ppc83xx_setup.c
+ *
+ * MPC83XX common board code
+ *
+ * Maintainer: Kumar Gala <kumar.gala@freescale.com>
+ *
+ * Copyright 2005 Freescale Semiconductor Inc.
+ *
+ * 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.
+ */
+
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/serial.h>
+#include <linux/tty.h> /* for linux/serial_core.h */
+#include <linux/serial_core.h>
+#include <linux/serial_8250.h>
+
+#include <asm/prom.h>
+#include <asm/time.h>
+#include <asm/mpc83xx.h>
+#include <asm/mmu.h>
+#include <asm/ppc_sys.h>
+#include <asm/kgdb.h>
+
+#include <syslib/ppc83xx_setup.h>
+
+phys_addr_t immrbar;
+
+/* Return the amount of memory */
+unsigned long __init
+mpc83xx_find_end_of_memory(void)
+{
+ bd_t *binfo;
+
+ binfo = (bd_t *) __res;
+
+ return binfo->bi_memsize;
+}
+
+long __init
+mpc83xx_time_init(void)
+{
+#define SPCR_OFFS 0x00000110
+#define SPCR_TBEN 0x00400000
+
+ bd_t *binfo = (bd_t *)__res;
+ u32 *spcr = ioremap(binfo->bi_immr_base + SPCR_OFFS, 4);
+
+ *spcr |= SPCR_TBEN;
+
+ iounmap(spcr);
+
+ return 0;
+}
+
+/* The decrementer counts at the system (internal) clock freq divided by 4 */
+void __init
+mpc83xx_calibrate_decr(void)
+{
+ bd_t *binfo = (bd_t *) __res;
+ unsigned int freq, divisor;
+
+ freq = binfo->bi_busfreq;
+ divisor = 4;
+ tb_ticks_per_jiffy = freq / HZ / divisor;
+ tb_to_us = mulhwu_scale_factor(freq / divisor, 1000000);
+}
+
+#ifdef CONFIG_SERIAL_8250
+void __init
+mpc83xx_early_serial_map(void)
+{
+#if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB)
+ struct uart_port serial_req;
+#endif
+ struct plat_serial8250_port *pdata;
+ bd_t *binfo = (bd_t *) __res;
+ pdata = (struct plat_serial8250_port *) ppc_sys_get_pdata(MPC83xx_DUART);
+
+ /* Setup serial port access */
+ pdata[0].uartclk = binfo->bi_busfreq;
+ pdata[0].mapbase += binfo->bi_immr_base;
+ pdata[0].membase = ioremap(pdata[0].mapbase, 0x100);
+
+#if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB)
+ memset(&serial_req, 0, sizeof (serial_req));
+ serial_req.iotype = SERIAL_IO_MEM;
+ serial_req.mapbase = pdata[0].mapbase;
+ serial_req.membase = pdata[0].membase;
+ serial_req.regshift = 0;
+
+ gen550_init(0, &serial_req);
+#endif
+
+ pdata[1].uartclk = binfo->bi_busfreq;
+ pdata[1].mapbase += binfo->bi_immr_base;
+ pdata[1].membase = ioremap(pdata[1].mapbase, 0x100);
+
+#if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB)
+ /* Assume gen550_init() doesn't modify serial_req */
+ serial_req.mapbase = pdata[1].mapbase;
+ serial_req.membase = pdata[1].membase;
+
+ gen550_init(1, &serial_req);
+#endif
+}
+#endif
+
+void
+mpc83xx_restart(char *cmd)
+{
+ local_irq_disable();
+ for(;;);
+}
+
+void
+mpc83xx_power_off(void)
+{
+ local_irq_disable();
+ for(;;);
+}
+
+void
+mpc83xx_halt(void)
+{
+ local_irq_disable();
+ for(;;);
+}
+
+/* PCI SUPPORT DOES NOT EXIT, MODEL after ppc85xx_setup.c */
diff --git a/arch/ppc/syslib/ppc83xx_setup.h b/arch/ppc/syslib/ppc83xx_setup.h
new file mode 100644
index 0000000..683f179
--- /dev/null
+++ b/arch/ppc/syslib/ppc83xx_setup.h
@@ -0,0 +1,53 @@
+/*
+ * arch/ppc/syslib/ppc83xx_setup.h
+ *
+ * MPC83XX common board definitions
+ *
+ * Maintainer: Kumar Gala <kumar.gala@freescale.com>
+ *
+ * Copyright 2005 Freescale Semiconductor Inc.
+ *
+ * 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.
+ *
+ */
+
+#ifndef __PPC_SYSLIB_PPC83XX_SETUP_H
+#define __PPC_SYSLIB_PPC83XX_SETUP_H
+
+#include <linux/config.h>
+#include <linux/init.h>
+#include <asm/ppcboot.h>
+
+extern unsigned long mpc83xx_find_end_of_memory(void) __init;
+extern long mpc83xx_time_init(void) __init;
+extern void mpc83xx_calibrate_decr(void) __init;
+extern void mpc83xx_early_serial_map(void) __init;
+extern void mpc83xx_restart(char *cmd);
+extern void mpc83xx_power_off(void);
+extern void mpc83xx_halt(void);
+extern void mpc83xx_setup_hose(void) __init;
+
+/* PCI config */
+#if 0
+#define PCI1_CFG_ADDR_OFFSET (FIXME)
+#define PCI1_CFG_DATA_OFFSET (FIXME)
+
+#define PCI2_CFG_ADDR_OFFSET (FIXME)
+#define PCI2_CFG_DATA_OFFSET (FIXME)
+#endif
+
+/* Serial Config */
+#ifdef CONFIG_SERIAL_MANY_PORTS
+#define RS_TABLE_SIZE 64
+#else
+#define RS_TABLE_SIZE 2
+#endif
+
+#ifndef BASE_BAUD
+#define BASE_BAUD 115200
+#endif
+
+#endif /* __PPC_SYSLIB_PPC83XX_SETUP_H */
diff --git a/arch/ppc/syslib/ppc85xx_common.c b/arch/ppc/syslib/ppc85xx_common.c
new file mode 100644
index 0000000..e83f2f8
--- /dev/null
+++ b/arch/ppc/syslib/ppc85xx_common.c
@@ -0,0 +1,33 @@
+/*
+ * arch/ppc/syslib/ppc85xx_common.c
+ *
+ * MPC85xx support routines
+ *
+ * Maintainer: Kumar Gala <kumar.gala@freescale.com>
+ *
+ * Copyright 2004 Freescale Semiconductor Inc.
+ *
+ * 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.
+ */
+
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/module.h>
+#include <linux/init.h>
+
+#include <asm/mpc85xx.h>
+#include <asm/mmu.h>
+
+/* ************************************************************************ */
+/* Return the value of CCSRBAR for the current board */
+
+phys_addr_t
+get_ccsrbar(void)
+{
+ return BOARD_CCSRBAR;
+}
+
+EXPORT_SYMBOL(get_ccsrbar);
diff --git a/arch/ppc/syslib/ppc85xx_common.h b/arch/ppc/syslib/ppc85xx_common.h
new file mode 100644
index 0000000..2c8f304
--- /dev/null
+++ b/arch/ppc/syslib/ppc85xx_common.h
@@ -0,0 +1,25 @@
+/*
+ * arch/ppc/syslib/ppc85xx_common.h
+ *
+ * MPC85xx support routines
+ *
+ * Maintainer: Kumar Gala <kumar.gala@freescale.com>
+ *
+ * Copyright 2004 Freescale Semiconductor Inc.
+ *
+ * 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.
+ */
+
+#ifndef __PPC_SYSLIB_PPC85XX_COMMON_H
+#define __PPC_SYSLIB_PPC85XX_COMMON_H
+
+#include <linux/config.h>
+#include <linux/init.h>
+
+/* Provide access to ccsrbar for any modules, etc */
+phys_addr_t get_ccsrbar(void);
+
+#endif /* __PPC_SYSLIB_PPC85XX_COMMON_H */
diff --git a/arch/ppc/syslib/ppc85xx_setup.c b/arch/ppc/syslib/ppc85xx_setup.c
new file mode 100644
index 0000000..81f1968
--- /dev/null
+++ b/arch/ppc/syslib/ppc85xx_setup.c
@@ -0,0 +1,354 @@
+/*
+ * arch/ppc/syslib/ppc85xx_setup.c
+ *
+ * MPC85XX common board code
+ *
+ * Maintainer: Kumar Gala <kumar.gala@freescale.com>
+ *
+ * Copyright 2004 Freescale Semiconductor Inc.
+ *
+ * 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.
+ */
+
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/serial.h>
+#include <linux/tty.h> /* for linux/serial_core.h */
+#include <linux/serial_core.h>
+#include <linux/serial_8250.h>
+
+#include <asm/prom.h>
+#include <asm/time.h>
+#include <asm/mpc85xx.h>
+#include <asm/immap_85xx.h>
+#include <asm/mmu.h>
+#include <asm/ppc_sys.h>
+#include <asm/kgdb.h>
+
+#include <syslib/ppc85xx_setup.h>
+
+/* Return the amount of memory */
+unsigned long __init
+mpc85xx_find_end_of_memory(void)
+{
+ bd_t *binfo;
+
+ binfo = (bd_t *) __res;
+
+ return binfo->bi_memsize;
+}
+
+/* The decrementer counts at the system (internal) clock freq divided by 8 */
+void __init
+mpc85xx_calibrate_decr(void)
+{
+ bd_t *binfo = (bd_t *) __res;
+ unsigned int freq, divisor;
+
+ /* get the core frequency */
+ freq = binfo->bi_busfreq;
+
+ /* The timebase is updated every 8 bus clocks, HID0[SEL_TBCLK] = 0 */
+ divisor = 8;
+ tb_ticks_per_jiffy = freq / divisor / HZ;
+ tb_to_us = mulhwu_scale_factor(freq / divisor, 1000000);
+
+ /* Set the time base to zero */
+ mtspr(SPRN_TBWL, 0);
+ mtspr(SPRN_TBWU, 0);
+
+ /* Clear any pending timer interrupts */
+ mtspr(SPRN_TSR, TSR_ENW | TSR_WIS | TSR_DIS | TSR_FIS);
+
+ /* Enable decrementer interrupt */
+ mtspr(SPRN_TCR, TCR_DIE);
+}
+
+#ifdef CONFIG_SERIAL_8250
+void __init
+mpc85xx_early_serial_map(void)
+{
+#if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB)
+ struct uart_port serial_req;
+#endif
+ struct plat_serial8250_port *pdata;
+ bd_t *binfo = (bd_t *) __res;
+ pdata = (struct plat_serial8250_port *) ppc_sys_get_pdata(MPC85xx_DUART);
+
+ /* Setup serial port access */
+ pdata[0].uartclk = binfo->bi_busfreq;
+ pdata[0].mapbase += binfo->bi_immr_base;
+ pdata[0].membase = ioremap(pdata[0].mapbase, MPC85xx_UART0_SIZE);
+
+#if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB)
+ memset(&serial_req, 0, sizeof (serial_req));
+ serial_req.iotype = SERIAL_IO_MEM;
+ serial_req.mapbase = pdata[0].mapbase;
+ serial_req.membase = pdata[0].membase;
+ serial_req.regshift = 0;
+
+ gen550_init(0, &serial_req);
+#endif
+
+ pdata[1].uartclk = binfo->bi_busfreq;
+ pdata[1].mapbase += binfo->bi_immr_base;
+ pdata[1].membase = ioremap(pdata[1].mapbase, MPC85xx_UART0_SIZE);
+
+#if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB)
+ /* Assume gen550_init() doesn't modify serial_req */
+ serial_req.mapbase = pdata[1].mapbase;
+ serial_req.membase = pdata[1].membase;
+
+ gen550_init(1, &serial_req);
+#endif
+}
+#endif
+
+void
+mpc85xx_restart(char *cmd)
+{
+ local_irq_disable();
+ abort();
+}
+
+void
+mpc85xx_power_off(void)
+{
+ local_irq_disable();
+ for(;;);
+}
+
+void
+mpc85xx_halt(void)
+{
+ local_irq_disable();
+ for(;;);
+}
+
+#ifdef CONFIG_PCI
+static void __init
+mpc85xx_setup_pci1(struct pci_controller *hose)
+{
+ volatile struct ccsr_pci *pci;
+ volatile struct ccsr_guts *guts;
+ unsigned short temps;
+ bd_t *binfo = (bd_t *) __res;
+
+ pci = ioremap(binfo->bi_immr_base + MPC85xx_PCI1_OFFSET,
+ MPC85xx_PCI1_SIZE);
+
+ guts = ioremap(binfo->bi_immr_base + MPC85xx_GUTS_OFFSET,
+ MPC85xx_GUTS_SIZE);
+
+ early_read_config_word(hose, 0, 0, PCI_COMMAND, &temps);
+ temps |= PCI_COMMAND_SERR | PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY;
+ early_write_config_word(hose, 0, 0, PCI_COMMAND, temps);
+
+#define PORDEVSR_PCI (0x00800000) /* PCI Mode */
+ if (guts->pordevsr & PORDEVSR_PCI) {
+ early_write_config_byte(hose, 0, 0, PCI_LATENCY_TIMER, 0x80);
+ } else {
+ /* PCI-X init */
+ temps = PCI_X_CMD_MAX_SPLIT | PCI_X_CMD_MAX_READ
+ | PCI_X_CMD_ERO | PCI_X_CMD_DPERR_E;
+ early_write_config_word(hose, 0, 0, PCIX_COMMAND, temps);
+ }
+
+ /* Disable all windows (except powar0 since its ignored) */
+ pci->powar1 = 0;
+ pci->powar2 = 0;
+ pci->powar3 = 0;
+ pci->powar4 = 0;
+ pci->piwar1 = 0;
+ pci->piwar2 = 0;
+ pci->piwar3 = 0;
+
+ /* Setup Phys:PCI 1:1 outbound mem window @ MPC85XX_PCI1_LOWER_MEM */
+ pci->potar1 = (MPC85XX_PCI1_LOWER_MEM >> 12) & 0x000fffff;
+ pci->potear1 = 0x00000000;
+ pci->powbar1 = (MPC85XX_PCI1_LOWER_MEM >> 12) & 0x000fffff;
+ /* Enable, Mem R/W */
+ pci->powar1 = 0x80044000 |
+ (__ilog2(MPC85XX_PCI1_UPPER_MEM - MPC85XX_PCI1_LOWER_MEM + 1) - 1);
+
+ /* Setup outboud IO windows @ MPC85XX_PCI1_IO_BASE */
+ pci->potar2 = 0x00000000;
+ pci->potear2 = 0x00000000;
+ pci->powbar2 = (MPC85XX_PCI1_IO_BASE >> 12) & 0x000fffff;
+ /* Enable, IO R/W */
+ pci->powar2 = 0x80088000 | (__ilog2(MPC85XX_PCI1_IO_SIZE) - 1);
+
+ /* Setup 2G inbound Memory Window @ 0 */
+ pci->pitar1 = 0x00000000;
+ pci->piwbar1 = 0x00000000;
+ pci->piwar1 = 0xa0f5501e; /* Enable, Prefetch, Local
+ Mem, Snoop R/W, 2G */
+}
+
+
+extern int mpc85xx_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin);
+extern int mpc85xx_exclude_device(u_char bus, u_char devfn);
+
+#ifdef CONFIG_85xx_PCI2
+static void __init
+mpc85xx_setup_pci2(struct pci_controller *hose)
+{
+ volatile struct ccsr_pci *pci;
+ unsigned short temps;
+ bd_t *binfo = (bd_t *) __res;
+
+ pci = ioremap(binfo->bi_immr_base + MPC85xx_PCI2_OFFSET,
+ MPC85xx_PCI2_SIZE);
+
+ early_read_config_word(hose, hose->bus_offset, 0, PCI_COMMAND, &temps);
+ temps |= PCI_COMMAND_SERR | PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY;
+ early_write_config_word(hose, hose->bus_offset, 0, PCI_COMMAND, temps);
+ early_write_config_byte(hose, hose->bus_offset, 0, PCI_LATENCY_TIMER, 0x80);
+
+ /* Disable all windows (except powar0 since its ignored) */
+ pci->powar1 = 0;
+ pci->powar2 = 0;
+ pci->powar3 = 0;
+ pci->powar4 = 0;
+ pci->piwar1 = 0;
+ pci->piwar2 = 0;
+ pci->piwar3 = 0;
+
+ /* Setup Phys:PCI 1:1 outbound mem window @ MPC85XX_PCI2_LOWER_MEM */
+ pci->potar1 = (MPC85XX_PCI2_LOWER_MEM >> 12) & 0x000fffff;
+ pci->potear1 = 0x00000000;
+ pci->powbar1 = (MPC85XX_PCI2_LOWER_MEM >> 12) & 0x000fffff;
+ /* Enable, Mem R/W */
+ pci->powar1 = 0x80044000 |
+ (__ilog2(MPC85XX_PCI1_UPPER_MEM - MPC85XX_PCI1_LOWER_MEM + 1) - 1);
+
+ /* Setup outboud IO windows @ MPC85XX_PCI2_IO_BASE */
+ pci->potar2 = 0x00000000;
+ pci->potear2 = 0x00000000;
+ pci->powbar2 = (MPC85XX_PCI2_IO_BASE >> 12) & 0x000fffff;
+ /* Enable, IO R/W */
+ pci->powar2 = 0x80088000 | (__ilog2(MPC85XX_PCI1_IO_SIZE) - 1);
+
+ /* Setup 2G inbound Memory Window @ 0 */
+ pci->pitar1 = 0x00000000;
+ pci->piwbar1 = 0x00000000;
+ pci->piwar1 = 0xa0f5501e; /* Enable, Prefetch, Local
+ Mem, Snoop R/W, 2G */
+}
+#endif /* CONFIG_85xx_PCI2 */
+
+int mpc85xx_pci1_last_busno = 0;
+
+void __init
+mpc85xx_setup_hose(void)
+{
+ struct pci_controller *hose_a;
+#ifdef CONFIG_85xx_PCI2
+ struct pci_controller *hose_b;
+#endif
+ bd_t *binfo = (bd_t *) __res;
+
+ hose_a = pcibios_alloc_controller();
+
+ if (!hose_a)
+ return;
+
+ ppc_md.pci_swizzle = common_swizzle;
+ ppc_md.pci_map_irq = mpc85xx_map_irq;
+
+ hose_a->first_busno = 0;
+ hose_a->bus_offset = 0;
+ hose_a->last_busno = 0xff;
+
+ setup_indirect_pci(hose_a, binfo->bi_immr_base + PCI1_CFG_ADDR_OFFSET,
+ binfo->bi_immr_base + PCI1_CFG_DATA_OFFSET);
+ hose_a->set_cfg_type = 1;
+
+ mpc85xx_setup_pci1(hose_a);
+
+ hose_a->pci_mem_offset = MPC85XX_PCI1_MEM_OFFSET;
+ hose_a->mem_space.start = MPC85XX_PCI1_LOWER_MEM;
+ hose_a->mem_space.end = MPC85XX_PCI1_UPPER_MEM;
+
+ hose_a->io_space.start = MPC85XX_PCI1_LOWER_IO;
+ hose_a->io_space.end = MPC85XX_PCI1_UPPER_IO;
+ hose_a->io_base_phys = MPC85XX_PCI1_IO_BASE;
+#ifdef CONFIG_85xx_PCI2
+ isa_io_base =
+ (unsigned long) ioremap(MPC85XX_PCI1_IO_BASE,
+ MPC85XX_PCI1_IO_SIZE +
+ MPC85XX_PCI2_IO_SIZE);
+#else
+ isa_io_base =
+ (unsigned long) ioremap(MPC85XX_PCI1_IO_BASE,
+ MPC85XX_PCI1_IO_SIZE);
+#endif
+ hose_a->io_base_virt = (void *) isa_io_base;
+
+ /* setup resources */
+ pci_init_resource(&hose_a->mem_resources[0],
+ MPC85XX_PCI1_LOWER_MEM,
+ MPC85XX_PCI1_UPPER_MEM,
+ IORESOURCE_MEM, "PCI1 host bridge");
+
+ pci_init_resource(&hose_a->io_resource,
+ MPC85XX_PCI1_LOWER_IO,
+ MPC85XX_PCI1_UPPER_IO,
+ IORESOURCE_IO, "PCI1 host bridge");
+
+ ppc_md.pci_exclude_device = mpc85xx_exclude_device;
+
+ hose_a->last_busno = pciauto_bus_scan(hose_a, hose_a->first_busno);
+
+#ifdef CONFIG_85xx_PCI2
+ hose_b = pcibios_alloc_controller();
+
+ if (!hose_b)
+ return;
+
+ hose_b->bus_offset = hose_a->last_busno + 1;
+ hose_b->first_busno = hose_a->last_busno + 1;
+ hose_b->last_busno = 0xff;
+
+ setup_indirect_pci(hose_b, binfo->bi_immr_base + PCI2_CFG_ADDR_OFFSET,
+ binfo->bi_immr_base + PCI2_CFG_DATA_OFFSET);
+ hose_b->set_cfg_type = 1;
+
+ mpc85xx_setup_pci2(hose_b);
+
+ hose_b->pci_mem_offset = MPC85XX_PCI2_MEM_OFFSET;
+ hose_b->mem_space.start = MPC85XX_PCI2_LOWER_MEM;
+ hose_b->mem_space.end = MPC85XX_PCI2_UPPER_MEM;
+
+ hose_b->io_space.start = MPC85XX_PCI2_LOWER_IO;
+ hose_b->io_space.end = MPC85XX_PCI2_UPPER_IO;
+ hose_b->io_base_phys = MPC85XX_PCI2_IO_BASE;
+ hose_b->io_base_virt = (void *) isa_io_base + MPC85XX_PCI1_IO_SIZE;
+
+ /* setup resources */
+ pci_init_resource(&hose_b->mem_resources[0],
+ MPC85XX_PCI2_LOWER_MEM,
+ MPC85XX_PCI2_UPPER_MEM,
+ IORESOURCE_MEM, "PCI2 host bridge");
+
+ pci_init_resource(&hose_b->io_resource,
+ MPC85XX_PCI2_LOWER_IO,
+ MPC85XX_PCI2_UPPER_IO,
+ IORESOURCE_IO, "PCI2 host bridge");
+
+ hose_b->last_busno = pciauto_bus_scan(hose_b, hose_b->first_busno);
+
+ /* let board code know what the last bus number was on PCI1 */
+ mpc85xx_pci1_last_busno = hose_a->last_busno;
+#endif
+ return;
+}
+#endif /* CONFIG_PCI */
+
+
diff --git a/arch/ppc/syslib/ppc85xx_setup.h b/arch/ppc/syslib/ppc85xx_setup.h
new file mode 100644
index 0000000..6e6cfe1
--- /dev/null
+++ b/arch/ppc/syslib/ppc85xx_setup.h
@@ -0,0 +1,59 @@
+/*
+ * arch/ppc/syslib/ppc85xx_setup.h
+ *
+ * MPC85XX common board definitions
+ *
+ * Maintainer: Kumar Gala <kumar.gala@freescale.com>
+ *
+ * Copyright 2004 Freescale Semiconductor Inc.
+ *
+ * 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.
+ *
+ */
+
+#ifndef __PPC_SYSLIB_PPC85XX_SETUP_H
+#define __PPC_SYSLIB_PPC85XX_SETUP_H
+
+#include <linux/config.h>
+#include <linux/init.h>
+#include <asm/ppcboot.h>
+
+extern unsigned long mpc85xx_find_end_of_memory(void) __init;
+extern void mpc85xx_calibrate_decr(void) __init;
+extern void mpc85xx_early_serial_map(void) __init;
+extern void mpc85xx_restart(char *cmd);
+extern void mpc85xx_power_off(void);
+extern void mpc85xx_halt(void);
+extern void mpc85xx_setup_hose(void) __init;
+
+/* PCI config */
+#define PCI1_CFG_ADDR_OFFSET (0x8000)
+#define PCI1_CFG_DATA_OFFSET (0x8004)
+
+#define PCI2_CFG_ADDR_OFFSET (0x9000)
+#define PCI2_CFG_DATA_OFFSET (0x9004)
+
+/* Additional register for PCI-X configuration */
+#define PCIX_NEXT_CAP 0x60
+#define PCIX_CAP_ID 0x61
+#define PCIX_COMMAND 0x62
+#define PCIX_STATUS 0x64
+
+/* Serial Config */
+#ifdef CONFIG_SERIAL_MANY_PORTS
+#define RS_TABLE_SIZE 64
+#else
+#define RS_TABLE_SIZE 2
+#endif
+
+#ifndef BASE_BAUD
+#define BASE_BAUD 115200
+#endif
+
+/* Offset of CPM register space */
+#define CPM_MAP_ADDR (CCSRBAR + MPC85xx_CPM_OFFSET)
+
+#endif /* __PPC_SYSLIB_PPC85XX_SETUP_H */
diff --git a/arch/ppc/syslib/ppc8xx_pic.c b/arch/ppc/syslib/ppc8xx_pic.c
new file mode 100644
index 0000000..d3b01c6
--- /dev/null
+++ b/arch/ppc/syslib/ppc8xx_pic.c
@@ -0,0 +1,130 @@
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/stddef.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/signal.h>
+#include <linux/interrupt.h>
+#include <asm/irq.h>
+#include <asm/8xx_immap.h>
+#include <asm/mpc8xx.h>
+#include "ppc8xx_pic.h"
+
+extern int cpm_get_irq(struct pt_regs *regs);
+
+/* The 8xx internal interrupt controller. It is usually
+ * the only interrupt controller. Some boards, like the MBX and
+ * Sandpoint have the 8259 as a secondary controller. Depending
+ * upon the processor type, the internal controller can have as
+ * few as 16 interrups or as many as 64. We could use the
+ * "clear_bit()" and "set_bit()" functions like other platforms,
+ * but they are overkill for us.
+ */
+
+static void m8xx_mask_irq(unsigned int irq_nr)
+{
+ int bit, word;
+
+ bit = irq_nr & 0x1f;
+ word = irq_nr >> 5;
+
+ ppc_cached_irq_mask[word] &= ~(1 << (31-bit));
+ ((immap_t *)IMAP_ADDR)->im_siu_conf.sc_simask =
+ ppc_cached_irq_mask[word];
+}
+
+static void m8xx_unmask_irq(unsigned int irq_nr)
+{
+ int bit, word;
+
+ bit = irq_nr & 0x1f;
+ word = irq_nr >> 5;
+
+ ppc_cached_irq_mask[word] |= (1 << (31-bit));
+ ((immap_t *)IMAP_ADDR)->im_siu_conf.sc_simask =
+ ppc_cached_irq_mask[word];
+}
+
+static void m8xx_end_irq(unsigned int irq_nr)
+{
+ if (!(irq_desc[irq_nr].status & (IRQ_DISABLED|IRQ_INPROGRESS))
+ && irq_desc[irq_nr].action) {
+ int bit, word;
+
+ bit = irq_nr & 0x1f;
+ word = irq_nr >> 5;
+
+ ppc_cached_irq_mask[word] |= (1 << (31-bit));
+ ((immap_t *)IMAP_ADDR)->im_siu_conf.sc_simask =
+ ppc_cached_irq_mask[word];
+ }
+}
+
+
+static void m8xx_mask_and_ack(unsigned int irq_nr)
+{
+ int bit, word;
+
+ bit = irq_nr & 0x1f;
+ word = irq_nr >> 5;
+
+ ppc_cached_irq_mask[word] &= ~(1 << (31-bit));
+ ((immap_t *)IMAP_ADDR)->im_siu_conf.sc_simask =
+ ppc_cached_irq_mask[word];
+ ((immap_t *)IMAP_ADDR)->im_siu_conf.sc_sipend = 1 << (31-bit);
+}
+
+struct hw_interrupt_type ppc8xx_pic = {
+ .typename = " 8xx SIU ",
+ .enable = m8xx_unmask_irq,
+ .disable = m8xx_mask_irq,
+ .ack = m8xx_mask_and_ack,
+ .end = m8xx_end_irq,
+};
+
+/*
+ * We either return a valid interrupt or -1 if there is nothing pending
+ */
+int
+m8xx_get_irq(struct pt_regs *regs)
+{
+ int irq;
+
+ /* For MPC8xx, read the SIVEC register and shift the bits down
+ * to get the irq number.
+ */
+ irq = ((immap_t *)IMAP_ADDR)->im_siu_conf.sc_sivec >> 26;
+
+ /*
+ * When we read the sivec without an interrupt to process, we will
+ * get back SIU_LEVEL7. In this case, return -1
+ */
+ if (irq == CPM_INTERRUPT)
+ irq = CPM_IRQ_OFFSET + cpm_get_irq(regs);
+#if defined(CONFIG_PCI)
+ else if (irq == ISA_BRIDGE_INT) {
+ int isa_irq;
+
+ if ((isa_irq = i8259_poll(regs)) >= 0)
+ irq = I8259_IRQ_OFFSET + isa_irq;
+ }
+#endif /* CONFIG_PCI */
+ else if (irq == SIU_LEVEL7)
+ irq = -1;
+
+ return irq;
+}
+
+#if defined(CONFIG_MBX) && defined(CONFIG_PCI)
+/* Only the MBX uses the external 8259. This allows us to catch standard
+ * drivers that may mess up the internal interrupt controllers, and also
+ * allow them to run without modification on the MBX.
+ */
+void mbx_i8259_action(int irq, void *dev_id, struct pt_regs *regs)
+{
+ /* This interrupt handler never actually gets called. It is
+ * installed only to unmask the 8259 cascade interrupt in the SIU
+ * and to make the 8259 cascade interrupt visible in /proc/interrupts.
+ */
+}
+#endif /* CONFIG_PCI */
diff --git a/arch/ppc/syslib/ppc8xx_pic.h b/arch/ppc/syslib/ppc8xx_pic.h
new file mode 100644
index 0000000..784935e
--- /dev/null
+++ b/arch/ppc/syslib/ppc8xx_pic.h
@@ -0,0 +1,21 @@
+#ifndef _PPC_KERNEL_PPC8xx_H
+#define _PPC_KERNEL_PPC8xx_H
+
+#include <linux/config.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+
+extern struct hw_interrupt_type ppc8xx_pic;
+
+void m8xx_pic_init(void);
+void m8xx_do_IRQ(struct pt_regs *regs,
+ int cpu);
+int m8xx_get_irq(struct pt_regs *regs);
+
+#ifdef CONFIG_MBX
+#include <asm/i8259.h>
+#include <asm/io.h>
+void mbx_i8259_action(int cpl, void *dev_id, struct pt_regs *regs);
+#endif
+
+#endif /* _PPC_KERNEL_PPC8xx_H */
diff --git a/arch/ppc/syslib/ppc_sys.c b/arch/ppc/syslib/ppc_sys.c
new file mode 100644
index 0000000..8792023
--- /dev/null
+++ b/arch/ppc/syslib/ppc_sys.c
@@ -0,0 +1,103 @@
+/*
+ * arch/ppc/syslib/ppc_sys.c
+ *
+ * PPC System library functions
+ *
+ * Maintainer: Kumar Gala <kumar.gala@freescale.com>
+ *
+ * Copyright 2005 Freescale Semiconductor Inc.
+ *
+ * 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.
+ */
+
+#include <asm/ppc_sys.h>
+
+int (*ppc_sys_device_fixup) (struct platform_device * pdev);
+
+static int ppc_sys_inited;
+
+void __init identify_ppc_sys_by_id(u32 id)
+{
+ unsigned int i = 0;
+ while (1) {
+ if ((ppc_sys_specs[i].mask & id) == ppc_sys_specs[i].value)
+ break;
+ i++;
+ }
+
+ cur_ppc_sys_spec = &ppc_sys_specs[i];
+
+ return;
+}
+
+void __init identify_ppc_sys_by_name(char *name)
+{
+ /* TODO */
+ return;
+}
+
+/* Update all memory resources by paddr, call before platform_device_register */
+void __init
+ppc_sys_fixup_mem_resource(struct platform_device *pdev, phys_addr_t paddr)
+{
+ int i;
+ for (i = 0; i < pdev->num_resources; i++) {
+ struct resource *r = &pdev->resource[i];
+ if ((r->flags & IORESOURCE_MEM) == IORESOURCE_MEM) {
+ r->start += paddr;
+ r->end += paddr;
+ }
+ }
+}
+
+/* Get platform_data pointer out of platform device, call before platform_device_register */
+void *__init ppc_sys_get_pdata(enum ppc_sys_devices dev)
+{
+ return ppc_sys_platform_devices[dev].dev.platform_data;
+}
+
+void ppc_sys_device_remove(enum ppc_sys_devices dev)
+{
+ unsigned int i;
+
+ if (ppc_sys_inited) {
+ platform_device_unregister(&ppc_sys_platform_devices[dev]);
+ } else {
+ if (cur_ppc_sys_spec == NULL)
+ return;
+ for (i = 0; i < cur_ppc_sys_spec->num_devices; i++)
+ if (cur_ppc_sys_spec->device_list[i] == dev)
+ cur_ppc_sys_spec->device_list[i] = -1;
+ }
+}
+
+static int __init ppc_sys_init(void)
+{
+ unsigned int i, dev_id, ret = 0;
+
+ BUG_ON(cur_ppc_sys_spec == NULL);
+
+ for (i = 0; i < cur_ppc_sys_spec->num_devices; i++) {
+ dev_id = cur_ppc_sys_spec->device_list[i];
+ if (dev_id != -1) {
+ if (ppc_sys_device_fixup != NULL)
+ ppc_sys_device_fixup(&ppc_sys_platform_devices
+ [dev_id]);
+ if (platform_device_register
+ (&ppc_sys_platform_devices[dev_id])) {
+ ret = 1;
+ printk(KERN_ERR
+ "unable to register device %d\n",
+ dev_id);
+ }
+ }
+ }
+
+ ppc_sys_inited = 1;
+ return ret;
+}
+
+subsys_initcall(ppc_sys_init);
diff --git a/arch/ppc/syslib/prep_nvram.c b/arch/ppc/syslib/prep_nvram.c
new file mode 100644
index 0000000..2bcf8a1
--- /dev/null
+++ b/arch/ppc/syslib/prep_nvram.c
@@ -0,0 +1,141 @@
+/*
+ * arch/ppc/kernel/prep_nvram.c
+ *
+ * Copyright (C) 1998 Corey Minyard
+ *
+ * This reads the NvRAM on PReP compliant machines (generally from IBM or
+ * Motorola). Motorola kept the format of NvRAM in their ROM, PPCBUG, the
+ * same, long after they had stopped producing PReP compliant machines. So
+ * this code is useful in those cases as well.
+ *
+ */
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/ioport.h>
+
+#include <asm/sections.h>
+#include <asm/segment.h>
+#include <asm/io.h>
+#include <asm/machdep.h>
+#include <asm/prep_nvram.h>
+
+static char nvramData[MAX_PREP_NVRAM];
+static NVRAM_MAP *nvram=(NVRAM_MAP *)&nvramData[0];
+
+unsigned char __prep prep_nvram_read_val(int addr)
+{
+ outb(addr, PREP_NVRAM_AS0);
+ outb(addr>>8, PREP_NVRAM_AS1);
+ return inb(PREP_NVRAM_DATA);
+}
+
+void __prep prep_nvram_write_val(int addr,
+ unsigned char val)
+{
+ outb(addr, PREP_NVRAM_AS0);
+ outb(addr>>8, PREP_NVRAM_AS1);
+ outb(val, PREP_NVRAM_DATA);
+}
+
+void __init init_prep_nvram(void)
+{
+ unsigned char *nvp;
+ int i;
+ int nvramSize;
+
+ /*
+ * The following could fail if the NvRAM were corrupt but
+ * we expect the boot firmware to have checked its checksum
+ * before boot
+ */
+ nvp = (char *) &nvram->Header;
+ for (i=0; i<sizeof(HEADER); i++)
+ {
+ *nvp = ppc_md.nvram_read_val(i);
+ nvp++;
+ }
+
+ /*
+ * The PReP NvRAM may be any size so read in the header to
+ * determine how much we must read in order to get the complete
+ * GE area
+ */
+ nvramSize=(int)nvram->Header.GEAddress+nvram->Header.GELength;
+ if(nvramSize>MAX_PREP_NVRAM)
+ {
+ /*
+ * NvRAM is too large
+ */
+ nvram->Header.GELength=0;
+ return;
+ }
+
+ /*
+ * Read the remainder of the PReP NvRAM
+ */
+ nvp = (char *) &nvram->GEArea[0];
+ for (i=sizeof(HEADER); i<nvramSize; i++)
+ {
+ *nvp = ppc_md.nvram_read_val(i);
+ nvp++;
+ }
+}
+
+__prep
+char __prep *prep_nvram_get_var(const char *name)
+{
+ char *cp;
+ int namelen;
+
+ namelen = strlen(name);
+ cp = prep_nvram_first_var();
+ while (cp != NULL) {
+ if ((strncmp(name, cp, namelen) == 0)
+ && (cp[namelen] == '='))
+ {
+ return cp+namelen+1;
+ }
+ cp = prep_nvram_next_var(cp);
+ }
+
+ return NULL;
+}
+
+__prep
+char __prep *prep_nvram_first_var(void)
+{
+ if (nvram->Header.GELength == 0) {
+ return NULL;
+ } else {
+ return (((char *)nvram)
+ + ((unsigned int) nvram->Header.GEAddress));
+ }
+}
+
+__prep
+char __prep *prep_nvram_next_var(char *name)
+{
+ char *cp;
+
+
+ cp = name;
+ while (((cp - ((char *) nvram->GEArea)) < nvram->Header.GELength)
+ && (*cp != '\0'))
+ {
+ cp++;
+ }
+
+ /* Skip over any null characters. */
+ while (((cp - ((char *) nvram->GEArea)) < nvram->Header.GELength)
+ && (*cp == '\0'))
+ {
+ cp++;
+ }
+
+ if ((cp - ((char *) nvram->GEArea)) < nvram->Header.GELength) {
+ return cp;
+ } else {
+ return NULL;
+ }
+}
diff --git a/arch/ppc/syslib/prom.c b/arch/ppc/syslib/prom.c
new file mode 100644
index 0000000..2c64ed6
--- /dev/null
+++ b/arch/ppc/syslib/prom.c
@@ -0,0 +1,1447 @@
+/*
+ * Procedures for interfacing to the Open Firmware PROM on
+ * Power Macintosh computers.
+ *
+ * In particular, we are interested in the device tree
+ * and in using some of its services (exit, write to stdout).
+ *
+ * Paul Mackerras August 1996.
+ * Copyright (C) 1996 Paul Mackerras.
+ */
+#include <stdarg.h>
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/init.h>
+#include <linux/version.h>
+#include <linux/threads.h>
+#include <linux/spinlock.h>
+#include <linux/ioport.h>
+#include <linux/pci.h>
+#include <linux/slab.h>
+#include <linux/bitops.h>
+
+#include <asm/sections.h>
+#include <asm/prom.h>
+#include <asm/page.h>
+#include <asm/processor.h>
+#include <asm/irq.h>
+#include <asm/io.h>
+#include <asm/smp.h>
+#include <asm/bootx.h>
+#include <asm/system.h>
+#include <asm/mmu.h>
+#include <asm/pgtable.h>
+#include <asm/bootinfo.h>
+#include <asm/btext.h>
+#include <asm/pci-bridge.h>
+#include <asm/open_pic.h>
+
+
+struct pci_address {
+ unsigned a_hi;
+ unsigned a_mid;
+ unsigned a_lo;
+};
+
+struct pci_reg_property {
+ struct pci_address addr;
+ unsigned size_hi;
+ unsigned size_lo;
+};
+
+struct isa_reg_property {
+ unsigned space;
+ unsigned address;
+ unsigned size;
+};
+
+typedef unsigned long interpret_func(struct device_node *, unsigned long,
+ int, int);
+static interpret_func interpret_pci_props;
+static interpret_func interpret_dbdma_props;
+static interpret_func interpret_isa_props;
+static interpret_func interpret_macio_props;
+static interpret_func interpret_root_props;
+
+extern char *klimit;
+
+/* Set for a newworld or CHRP machine */
+int use_of_interrupt_tree;
+struct device_node *dflt_interrupt_controller;
+int num_interrupt_controllers;
+
+int pmac_newworld;
+
+extern unsigned int rtas_entry; /* physical pointer */
+
+extern struct device_node *allnodes;
+
+static unsigned long finish_node(struct device_node *, unsigned long,
+ interpret_func *, int, int);
+static unsigned long finish_node_interrupts(struct device_node *, unsigned long);
+static struct device_node *find_phandle(phandle);
+
+extern void enter_rtas(void *);
+void phys_call_rtas(int, int, int, ...);
+
+extern char cmd_line[512]; /* XXX */
+extern boot_infos_t *boot_infos;
+unsigned long dev_tree_size;
+
+void __openfirmware
+phys_call_rtas(int service, int nargs, int nret, ...)
+{
+ va_list list;
+ union {
+ unsigned long words[16];
+ double align;
+ } u;
+ void (*rtas)(void *, unsigned long);
+ int i;
+
+ u.words[0] = service;
+ u.words[1] = nargs;
+ u.words[2] = nret;
+ va_start(list, nret);
+ for (i = 0; i < nargs; ++i)
+ u.words[i+3] = va_arg(list, unsigned long);
+ va_end(list);
+
+ rtas = (void (*)(void *, unsigned long)) rtas_entry;
+ rtas(&u, rtas_data);
+}
+
+/*
+ * finish_device_tree is called once things are running normally
+ * (i.e. with text and data mapped to the address they were linked at).
+ * It traverses the device tree and fills in the name, type,
+ * {n_}addrs and {n_}intrs fields of each node.
+ */
+void __init
+finish_device_tree(void)
+{
+ unsigned long mem = (unsigned long) klimit;
+ struct device_node *np;
+
+ /* All newworld pmac machines and CHRPs now use the interrupt tree */
+ for (np = allnodes; np != NULL; np = np->allnext) {
+ if (get_property(np, "interrupt-parent", NULL)) {
+ use_of_interrupt_tree = 1;
+ break;
+ }
+ }
+ if (_machine == _MACH_Pmac && use_of_interrupt_tree)
+ pmac_newworld = 1;
+
+#ifdef CONFIG_BOOTX_TEXT
+ if (boot_infos && pmac_newworld) {
+ prom_print("WARNING ! BootX/miBoot booting is not supported on this machine\n");
+ prom_print(" You should use an Open Firmware bootloader\n");
+ }
+#endif /* CONFIG_BOOTX_TEXT */
+
+ if (use_of_interrupt_tree) {
+ /*
+ * We want to find out here how many interrupt-controller
+ * nodes there are, and if we are booted from BootX,
+ * we need a pointer to the first (and hopefully only)
+ * such node. But we can't use find_devices here since
+ * np->name has not been set yet. -- paulus
+ */
+ int n = 0;
+ char *name, *ic;
+ int iclen;
+
+ for (np = allnodes; np != NULL; np = np->allnext) {
+ ic = get_property(np, "interrupt-controller", &iclen);
+ name = get_property(np, "name", NULL);
+ /* checking iclen makes sure we don't get a false
+ match on /chosen.interrupt_controller */
+ if ((name != NULL
+ && strcmp(name, "interrupt-controller") == 0)
+ || (ic != NULL && iclen == 0 && strcmp(name, "AppleKiwi"))) {
+ if (n == 0)
+ dflt_interrupt_controller = np;
+ ++n;
+ }
+ }
+ num_interrupt_controllers = n;
+ }
+
+ mem = finish_node(allnodes, mem, NULL, 1, 1);
+ dev_tree_size = mem - (unsigned long) allnodes;
+ klimit = (char *) mem;
+}
+
+static unsigned long __init
+finish_node(struct device_node *np, unsigned long mem_start,
+ interpret_func *ifunc, int naddrc, int nsizec)
+{
+ struct device_node *child;
+ int *ip;
+
+ np->name = get_property(np, "name", NULL);
+ np->type = get_property(np, "device_type", NULL);
+
+ if (!np->name)
+ np->name = "<NULL>";
+ if (!np->type)
+ np->type = "<NULL>";
+
+ /* get the device addresses and interrupts */
+ if (ifunc != NULL)
+ mem_start = ifunc(np, mem_start, naddrc, nsizec);
+
+ if (use_of_interrupt_tree)
+ mem_start = finish_node_interrupts(np, mem_start);
+
+ /* Look for #address-cells and #size-cells properties. */
+ ip = (int *) get_property(np, "#address-cells", NULL);
+ if (ip != NULL)
+ naddrc = *ip;
+ ip = (int *) get_property(np, "#size-cells", NULL);
+ if (ip != NULL)
+ nsizec = *ip;
+
+ if (np->parent == NULL)
+ ifunc = interpret_root_props;
+ else if (np->type == 0)
+ ifunc = NULL;
+ else if (!strcmp(np->type, "pci") || !strcmp(np->type, "vci"))
+ ifunc = interpret_pci_props;
+ else if (!strcmp(np->type, "dbdma"))
+ ifunc = interpret_dbdma_props;
+ else if (!strcmp(np->type, "mac-io")
+ || ifunc == interpret_macio_props)
+ ifunc = interpret_macio_props;
+ else if (!strcmp(np->type, "isa"))
+ ifunc = interpret_isa_props;
+ else if (!strcmp(np->name, "uni-n") || !strcmp(np->name, "u3"))
+ ifunc = interpret_root_props;
+ else if (!((ifunc == interpret_dbdma_props
+ || ifunc == interpret_macio_props)
+ && (!strcmp(np->type, "escc")
+ || !strcmp(np->type, "media-bay"))))
+ ifunc = NULL;
+
+ /* if we were booted from BootX, convert the full name */
+ if (boot_infos
+ && strncmp(np->full_name, "Devices:device-tree", 19) == 0) {
+ if (np->full_name[19] == 0) {
+ strcpy(np->full_name, "/");
+ } else if (np->full_name[19] == ':') {
+ char *p = np->full_name + 19;
+ np->full_name = p;
+ for (; *p; ++p)
+ if (*p == ':')
+ *p = '/';
+ }
+ }
+
+ for (child = np->child; child != NULL; child = child->sibling)
+ mem_start = finish_node(child, mem_start, ifunc,
+ naddrc, nsizec);
+
+ return mem_start;
+}
+
+/*
+ * Find the interrupt parent of a node.
+ */
+static struct device_node * __init
+intr_parent(struct device_node *p)
+{
+ phandle *parp;
+
+ parp = (phandle *) get_property(p, "interrupt-parent", NULL);
+ if (parp == NULL)
+ return p->parent;
+ p = find_phandle(*parp);
+ if (p != NULL)
+ return p;
+ /*
+ * On a powermac booted with BootX, we don't get to know the
+ * phandles for any nodes, so find_phandle will return NULL.
+ * Fortunately these machines only have one interrupt controller
+ * so there isn't in fact any ambiguity. -- paulus
+ */
+ if (num_interrupt_controllers == 1)
+ p = dflt_interrupt_controller;
+ return p;
+}
+
+/*
+ * Find out the size of each entry of the interrupts property
+ * for a node.
+ */
+static int __init
+prom_n_intr_cells(struct device_node *np)
+{
+ struct device_node *p;
+ unsigned int *icp;
+
+ for (p = np; (p = intr_parent(p)) != NULL; ) {
+ icp = (unsigned int *)
+ get_property(p, "#interrupt-cells", NULL);
+ if (icp != NULL)
+ return *icp;
+ if (get_property(p, "interrupt-controller", NULL) != NULL
+ || get_property(p, "interrupt-map", NULL) != NULL) {
+ printk("oops, node %s doesn't have #interrupt-cells\n",
+ p->full_name);
+ return 1;
+ }
+ }
+ printk("prom_n_intr_cells failed for %s\n", np->full_name);
+ return 1;
+}
+
+/*
+ * Map an interrupt from a device up to the platform interrupt
+ * descriptor.
+ */
+static int __init
+map_interrupt(unsigned int **irq, struct device_node **ictrler,
+ struct device_node *np, unsigned int *ints, int nintrc)
+{
+ struct device_node *p, *ipar;
+ unsigned int *imap, *imask, *ip;
+ int i, imaplen, match;
+ int newintrc = 1, newaddrc = 1;
+ unsigned int *reg;
+ int naddrc;
+
+ reg = (unsigned int *) get_property(np, "reg", NULL);
+ naddrc = prom_n_addr_cells(np);
+ p = intr_parent(np);
+ while (p != NULL) {
+ if (get_property(p, "interrupt-controller", NULL) != NULL)
+ /* this node is an interrupt controller, stop here */
+ break;
+ imap = (unsigned int *)
+ get_property(p, "interrupt-map", &imaplen);
+ if (imap == NULL) {
+ p = intr_parent(p);
+ continue;
+ }
+ imask = (unsigned int *)
+ get_property(p, "interrupt-map-mask", NULL);
+ if (imask == NULL) {
+ printk("oops, %s has interrupt-map but no mask\n",
+ p->full_name);
+ return 0;
+ }
+ imaplen /= sizeof(unsigned int);
+ match = 0;
+ ipar = NULL;
+ while (imaplen > 0 && !match) {
+ /* check the child-interrupt field */
+ match = 1;
+ for (i = 0; i < naddrc && match; ++i)
+ match = ((reg[i] ^ imap[i]) & imask[i]) == 0;
+ for (; i < naddrc + nintrc && match; ++i)
+ match = ((ints[i-naddrc] ^ imap[i]) & imask[i]) == 0;
+ imap += naddrc + nintrc;
+ imaplen -= naddrc + nintrc;
+ /* grab the interrupt parent */
+ ipar = find_phandle((phandle) *imap++);
+ --imaplen;
+ if (ipar == NULL && num_interrupt_controllers == 1)
+ /* cope with BootX not giving us phandles */
+ ipar = dflt_interrupt_controller;
+ if (ipar == NULL) {
+ printk("oops, no int parent %x in map of %s\n",
+ imap[-1], p->full_name);
+ return 0;
+ }
+ /* find the parent's # addr and intr cells */
+ ip = (unsigned int *)
+ get_property(ipar, "#interrupt-cells", NULL);
+ if (ip == NULL) {
+ printk("oops, no #interrupt-cells on %s\n",
+ ipar->full_name);
+ return 0;
+ }
+ newintrc = *ip;
+ ip = (unsigned int *)
+ get_property(ipar, "#address-cells", NULL);
+ newaddrc = (ip == NULL)? 0: *ip;
+ imap += newaddrc + newintrc;
+ imaplen -= newaddrc + newintrc;
+ }
+ if (imaplen < 0) {
+ printk("oops, error decoding int-map on %s, len=%d\n",
+ p->full_name, imaplen);
+ return 0;
+ }
+ if (!match) {
+ printk("oops, no match in %s int-map for %s\n",
+ p->full_name, np->full_name);
+ return 0;
+ }
+ p = ipar;
+ naddrc = newaddrc;
+ nintrc = newintrc;
+ ints = imap - nintrc;
+ reg = ints - naddrc;
+ }
+ if (p == NULL)
+ printk("hmmm, int tree for %s doesn't have ctrler\n",
+ np->full_name);
+ *irq = ints;
+ *ictrler = p;
+ return nintrc;
+}
+
+/*
+ * New version of finish_node_interrupts.
+ */
+static unsigned long __init
+finish_node_interrupts(struct device_node *np, unsigned long mem_start)
+{
+ unsigned int *ints;
+ int intlen, intrcells;
+ int i, j, n, offset;
+ unsigned int *irq;
+ struct device_node *ic;
+
+ ints = (unsigned int *) get_property(np, "interrupts", &intlen);
+ if (ints == NULL)
+ return mem_start;
+ intrcells = prom_n_intr_cells(np);
+ intlen /= intrcells * sizeof(unsigned int);
+ np->n_intrs = intlen;
+ np->intrs = (struct interrupt_info *) mem_start;
+ mem_start += intlen * sizeof(struct interrupt_info);
+
+ for (i = 0; i < intlen; ++i) {
+ np->intrs[i].line = 0;
+ np->intrs[i].sense = 1;
+ n = map_interrupt(&irq, &ic, np, ints, intrcells);
+ if (n <= 0)
+ continue;
+ offset = 0;
+ /*
+ * On a CHRP we have an 8259 which is subordinate to
+ * the openpic in the interrupt tree, but we want the
+ * openpic's interrupt numbers offsetted, not the 8259's.
+ * So we apply the offset if the controller is at the
+ * root of the interrupt tree, i.e. has no interrupt-parent.
+ * This doesn't cope with the general case of multiple
+ * cascaded interrupt controllers, but then neither will
+ * irq.c at the moment either. -- paulus
+ * The G5 triggers that code, I add a machine test. On
+ * those machines, we want to offset interrupts from the
+ * second openpic by 128 -- BenH
+ */
+ if (_machine != _MACH_Pmac && num_interrupt_controllers > 1
+ && ic != NULL
+ && get_property(ic, "interrupt-parent", NULL) == NULL)
+ offset = 16;
+ else if (_machine == _MACH_Pmac && num_interrupt_controllers > 1
+ && ic != NULL && ic->parent != NULL) {
+ char *name = get_property(ic->parent, "name", NULL);
+ if (name && !strcmp(name, "u3"))
+ offset = 128;
+ }
+
+ np->intrs[i].line = irq[0] + offset;
+ if (n > 1)
+ np->intrs[i].sense = irq[1];
+ if (n > 2) {
+ printk("hmmm, got %d intr cells for %s:", n,
+ np->full_name);
+ for (j = 0; j < n; ++j)
+ printk(" %d", irq[j]);
+ printk("\n");
+ }
+ ints += intrcells;
+ }
+
+ return mem_start;
+}
+
+/*
+ * When BootX makes a copy of the device tree from the MacOS
+ * Name Registry, it is in the format we use but all of the pointers
+ * are offsets from the start of the tree.
+ * This procedure updates the pointers.
+ */
+void __init
+relocate_nodes(void)
+{
+ unsigned long base;
+ struct device_node *np;
+ struct property *pp;
+
+#define ADDBASE(x) (x = (typeof (x))((x)? ((unsigned long)(x) + base): 0))
+
+ base = (unsigned long) boot_infos + boot_infos->deviceTreeOffset;
+ allnodes = (struct device_node *)(base + 4);
+ for (np = allnodes; np != 0; np = np->allnext) {
+ ADDBASE(np->full_name);
+ ADDBASE(np->properties);
+ ADDBASE(np->parent);
+ ADDBASE(np->child);
+ ADDBASE(np->sibling);
+ ADDBASE(np->allnext);
+ for (pp = np->properties; pp != 0; pp = pp->next) {
+ ADDBASE(pp->name);
+ ADDBASE(pp->value);
+ ADDBASE(pp->next);
+ }
+ }
+}
+
+int
+prom_n_addr_cells(struct device_node* np)
+{
+ int* ip;
+ do {
+ if (np->parent)
+ np = np->parent;
+ ip = (int *) get_property(np, "#address-cells", NULL);
+ if (ip != NULL)
+ return *ip;
+ } while (np->parent);
+ /* No #address-cells property for the root node, default to 1 */
+ return 1;
+}
+
+int
+prom_n_size_cells(struct device_node* np)
+{
+ int* ip;
+ do {
+ if (np->parent)
+ np = np->parent;
+ ip = (int *) get_property(np, "#size-cells", NULL);
+ if (ip != NULL)
+ return *ip;
+ } while (np->parent);
+ /* No #size-cells property for the root node, default to 1 */
+ return 1;
+}
+
+static unsigned long __init
+map_addr(struct device_node *np, unsigned long space, unsigned long addr)
+{
+ int na;
+ unsigned int *ranges;
+ int rlen = 0;
+ unsigned int type;
+
+ type = (space >> 24) & 3;
+ if (type == 0)
+ return addr;
+
+ while ((np = np->parent) != NULL) {
+ if (strcmp(np->type, "pci") != 0)
+ continue;
+ /* PCI bridge: map the address through the ranges property */
+ na = prom_n_addr_cells(np);
+ ranges = (unsigned int *) get_property(np, "ranges", &rlen);
+ while ((rlen -= (na + 5) * sizeof(unsigned int)) >= 0) {
+ if (((ranges[0] >> 24) & 3) == type
+ && ranges[2] <= addr
+ && addr - ranges[2] < ranges[na+4]) {
+ /* ok, this matches, translate it */
+ addr += ranges[na+2] - ranges[2];
+ break;
+ }
+ ranges += na + 5;
+ }
+ }
+ return addr;
+}
+
+static unsigned long __init
+interpret_pci_props(struct device_node *np, unsigned long mem_start,
+ int naddrc, int nsizec)
+{
+ struct address_range *adr;
+ struct pci_reg_property *pci_addrs;
+ int i, l, *ip;
+
+ pci_addrs = (struct pci_reg_property *)
+ get_property(np, "assigned-addresses", &l);
+ if (pci_addrs != 0 && l >= sizeof(struct pci_reg_property)) {
+ i = 0;
+ adr = (struct address_range *) mem_start;
+ while ((l -= sizeof(struct pci_reg_property)) >= 0) {
+ adr[i].space = pci_addrs[i].addr.a_hi;
+ adr[i].address = map_addr(np, pci_addrs[i].addr.a_hi,
+ pci_addrs[i].addr.a_lo);
+ adr[i].size = pci_addrs[i].size_lo;
+ ++i;
+ }
+ np->addrs = adr;
+ np->n_addrs = i;
+ mem_start += i * sizeof(struct address_range);
+ }
+
+ if (use_of_interrupt_tree)
+ return mem_start;
+
+ ip = (int *) get_property(np, "AAPL,interrupts", &l);
+ if (ip == 0 && np->parent)
+ ip = (int *) get_property(np->parent, "AAPL,interrupts", &l);
+ if (ip == 0)
+ ip = (int *) get_property(np, "interrupts", &l);
+ if (ip != 0) {
+ np->intrs = (struct interrupt_info *) mem_start;
+ np->n_intrs = l / sizeof(int);
+ mem_start += np->n_intrs * sizeof(struct interrupt_info);
+ for (i = 0; i < np->n_intrs; ++i) {
+ np->intrs[i].line = *ip++;
+ np->intrs[i].sense = 1;
+ }
+ }
+
+ return mem_start;
+}
+
+static unsigned long __init
+interpret_dbdma_props(struct device_node *np, unsigned long mem_start,
+ int naddrc, int nsizec)
+{
+ struct reg_property *rp;
+ struct address_range *adr;
+ unsigned long base_address;
+ int i, l, *ip;
+ struct device_node *db;
+
+ base_address = 0;
+ for (db = np->parent; db != NULL; db = db->parent) {
+ if (!strcmp(db->type, "dbdma") && db->n_addrs != 0) {
+ base_address = db->addrs[0].address;
+ break;
+ }
+ }
+
+ rp = (struct reg_property *) get_property(np, "reg", &l);
+ if (rp != 0 && l >= sizeof(struct reg_property)) {
+ i = 0;
+ adr = (struct address_range *) mem_start;
+ while ((l -= sizeof(struct reg_property)) >= 0) {
+ adr[i].space = 2;
+ adr[i].address = rp[i].address + base_address;
+ adr[i].size = rp[i].size;
+ ++i;
+ }
+ np->addrs = adr;
+ np->n_addrs = i;
+ mem_start += i * sizeof(struct address_range);
+ }
+
+ if (use_of_interrupt_tree)
+ return mem_start;
+
+ ip = (int *) get_property(np, "AAPL,interrupts", &l);
+ if (ip == 0)
+ ip = (int *) get_property(np, "interrupts", &l);
+ if (ip != 0) {
+ np->intrs = (struct interrupt_info *) mem_start;
+ np->n_intrs = l / sizeof(int);
+ mem_start += np->n_intrs * sizeof(struct interrupt_info);
+ for (i = 0; i < np->n_intrs; ++i) {
+ np->intrs[i].line = *ip++;
+ np->intrs[i].sense = 1;
+ }
+ }
+
+ return mem_start;
+}
+
+static unsigned long __init
+interpret_macio_props(struct device_node *np, unsigned long mem_start,
+ int naddrc, int nsizec)
+{
+ struct reg_property *rp;
+ struct address_range *adr;
+ unsigned long base_address;
+ int i, l, *ip;
+ struct device_node *db;
+
+ base_address = 0;
+ for (db = np->parent; db != NULL; db = db->parent) {
+ if (!strcmp(db->type, "mac-io") && db->n_addrs != 0) {
+ base_address = db->addrs[0].address;
+ break;
+ }
+ }
+
+ rp = (struct reg_property *) get_property(np, "reg", &l);
+ if (rp != 0 && l >= sizeof(struct reg_property)) {
+ i = 0;
+ adr = (struct address_range *) mem_start;
+ while ((l -= sizeof(struct reg_property)) >= 0) {
+ adr[i].space = 2;
+ adr[i].address = rp[i].address + base_address;
+ adr[i].size = rp[i].size;
+ ++i;
+ }
+ np->addrs = adr;
+ np->n_addrs = i;
+ mem_start += i * sizeof(struct address_range);
+ }
+
+ if (use_of_interrupt_tree)
+ return mem_start;
+
+ ip = (int *) get_property(np, "interrupts", &l);
+ if (ip == 0)
+ ip = (int *) get_property(np, "AAPL,interrupts", &l);
+ if (ip != 0) {
+ np->intrs = (struct interrupt_info *) mem_start;
+ np->n_intrs = l / sizeof(int);
+ for (i = 0; i < np->n_intrs; ++i) {
+ np->intrs[i].line = *ip++;
+ np->intrs[i].sense = 1;
+ }
+ mem_start += np->n_intrs * sizeof(struct interrupt_info);
+ }
+
+ return mem_start;
+}
+
+static unsigned long __init
+interpret_isa_props(struct device_node *np, unsigned long mem_start,
+ int naddrc, int nsizec)
+{
+ struct isa_reg_property *rp;
+ struct address_range *adr;
+ int i, l, *ip;
+
+ rp = (struct isa_reg_property *) get_property(np, "reg", &l);
+ if (rp != 0 && l >= sizeof(struct isa_reg_property)) {
+ i = 0;
+ adr = (struct address_range *) mem_start;
+ while ((l -= sizeof(struct reg_property)) >= 0) {
+ adr[i].space = rp[i].space;
+ adr[i].address = rp[i].address
+ + (adr[i].space? 0: _ISA_MEM_BASE);
+ adr[i].size = rp[i].size;
+ ++i;
+ }
+ np->addrs = adr;
+ np->n_addrs = i;
+ mem_start += i * sizeof(struct address_range);
+ }
+
+ if (use_of_interrupt_tree)
+ return mem_start;
+
+ ip = (int *) get_property(np, "interrupts", &l);
+ if (ip != 0) {
+ np->intrs = (struct interrupt_info *) mem_start;
+ np->n_intrs = l / (2 * sizeof(int));
+ mem_start += np->n_intrs * sizeof(struct interrupt_info);
+ for (i = 0; i < np->n_intrs; ++i) {
+ np->intrs[i].line = *ip++;
+ np->intrs[i].sense = *ip++;
+ }
+ }
+
+ return mem_start;
+}
+
+static unsigned long __init
+interpret_root_props(struct device_node *np, unsigned long mem_start,
+ int naddrc, int nsizec)
+{
+ struct address_range *adr;
+ int i, l, *ip;
+ unsigned int *rp;
+ int rpsize = (naddrc + nsizec) * sizeof(unsigned int);
+
+ rp = (unsigned int *) get_property(np, "reg", &l);
+ if (rp != 0 && l >= rpsize) {
+ i = 0;
+ adr = (struct address_range *) mem_start;
+ while ((l -= rpsize) >= 0) {
+ adr[i].space = (naddrc >= 2? rp[naddrc-2]: 2);
+ adr[i].address = rp[naddrc - 1];
+ adr[i].size = rp[naddrc + nsizec - 1];
+ ++i;
+ rp += naddrc + nsizec;
+ }
+ np->addrs = adr;
+ np->n_addrs = i;
+ mem_start += i * sizeof(struct address_range);
+ }
+
+ if (use_of_interrupt_tree)
+ return mem_start;
+
+ ip = (int *) get_property(np, "AAPL,interrupts", &l);
+ if (ip == 0)
+ ip = (int *) get_property(np, "interrupts", &l);
+ if (ip != 0) {
+ np->intrs = (struct interrupt_info *) mem_start;
+ np->n_intrs = l / sizeof(int);
+ mem_start += np->n_intrs * sizeof(struct interrupt_info);
+ for (i = 0; i < np->n_intrs; ++i) {
+ np->intrs[i].line = *ip++;
+ np->intrs[i].sense = 1;
+ }
+ }
+
+ return mem_start;
+}
+
+/*
+ * Work out the sense (active-low level / active-high edge)
+ * of each interrupt from the device tree.
+ */
+void __init
+prom_get_irq_senses(unsigned char *senses, int off, int max)
+{
+ struct device_node *np;
+ int i, j;
+
+ /* default to level-triggered */
+ memset(senses, 1, max - off);
+ if (!use_of_interrupt_tree)
+ return;
+
+ for (np = allnodes; np != 0; np = np->allnext) {
+ for (j = 0; j < np->n_intrs; j++) {
+ i = np->intrs[j].line;
+ if (i >= off && i < max) {
+ if (np->intrs[j].sense == 1)
+ senses[i-off] = (IRQ_SENSE_LEVEL
+ | IRQ_POLARITY_NEGATIVE);
+ else
+ senses[i-off] = (IRQ_SENSE_EDGE
+ | IRQ_POLARITY_POSITIVE);
+ }
+ }
+ }
+}
+
+/*
+ * Construct and return a list of the device_nodes with a given name.
+ */
+struct device_node *
+find_devices(const char *name)
+{
+ struct device_node *head, **prevp, *np;
+
+ prevp = &head;
+ for (np = allnodes; np != 0; np = np->allnext) {
+ if (np->name != 0 && strcasecmp(np->name, name) == 0) {
+ *prevp = np;
+ prevp = &np->next;
+ }
+ }
+ *prevp = NULL;
+ return head;
+}
+
+/*
+ * Construct and return a list of the device_nodes with a given type.
+ */
+struct device_node *
+find_type_devices(const char *type)
+{
+ struct device_node *head, **prevp, *np;
+
+ prevp = &head;
+ for (np = allnodes; np != 0; np = np->allnext) {
+ if (np->type != 0 && strcasecmp(np->type, type) == 0) {
+ *prevp = np;
+ prevp = &np->next;
+ }
+ }
+ *prevp = NULL;
+ return head;
+}
+
+/*
+ * Returns all nodes linked together
+ */
+struct device_node * __openfirmware
+find_all_nodes(void)
+{
+ struct device_node *head, **prevp, *np;
+
+ prevp = &head;
+ for (np = allnodes; np != 0; np = np->allnext) {
+ *prevp = np;
+ prevp = &np->next;
+ }
+ *prevp = NULL;
+ return head;
+}
+
+/* Checks if the given "compat" string matches one of the strings in
+ * the device's "compatible" property
+ */
+int
+device_is_compatible(struct device_node *device, const char *compat)
+{
+ const char* cp;
+ int cplen, l;
+
+ cp = (char *) get_property(device, "compatible", &cplen);
+ if (cp == NULL)
+ return 0;
+ while (cplen > 0) {
+ if (strncasecmp(cp, compat, strlen(compat)) == 0)
+ return 1;
+ l = strlen(cp) + 1;
+ cp += l;
+ cplen -= l;
+ }
+
+ return 0;
+}
+
+
+/*
+ * Indicates whether the root node has a given value in its
+ * compatible property.
+ */
+int
+machine_is_compatible(const char *compat)
+{
+ struct device_node *root;
+
+ root = find_path_device("/");
+ if (root == 0)
+ return 0;
+ return device_is_compatible(root, compat);
+}
+
+/*
+ * Construct and return a list of the device_nodes with a given type
+ * and compatible property.
+ */
+struct device_node *
+find_compatible_devices(const char *type, const char *compat)
+{
+ struct device_node *head, **prevp, *np;
+
+ prevp = &head;
+ for (np = allnodes; np != 0; np = np->allnext) {
+ if (type != NULL
+ && !(np->type != 0 && strcasecmp(np->type, type) == 0))
+ continue;
+ if (device_is_compatible(np, compat)) {
+ *prevp = np;
+ prevp = &np->next;
+ }
+ }
+ *prevp = NULL;
+ return head;
+}
+
+/*
+ * Find the device_node with a given full_name.
+ */
+struct device_node *
+find_path_device(const char *path)
+{
+ struct device_node *np;
+
+ for (np = allnodes; np != 0; np = np->allnext)
+ if (np->full_name != 0 && strcasecmp(np->full_name, path) == 0)
+ return np;
+ return NULL;
+}
+
+/*******
+ *
+ * New implementation of the OF "find" APIs, return a refcounted
+ * object, call of_node_put() when done. Currently, still lacks
+ * locking as old implementation, this is beeing done for ppc64.
+ *
+ * Note that property management will need some locking as well,
+ * this isn't dealt with yet
+ *
+ *******/
+
+/**
+ * of_find_node_by_name - Find a node by it's "name" property
+ * @from: The node to start searching from or NULL, the node
+ * you pass will not be searched, only the next one
+ * will; typically, you pass what the previous call
+ * returned. of_node_put() will be called on it
+ * @name: The name string to match against
+ *
+ * Returns a node pointer with refcount incremented, use
+ * of_node_put() on it when done.
+ */
+struct device_node *of_find_node_by_name(struct device_node *from,
+ const char *name)
+{
+ struct device_node *np = from ? from->allnext : allnodes;
+
+ for (; np != 0; np = np->allnext)
+ if (np->name != 0 && strcasecmp(np->name, name) == 0)
+ break;
+ if (from)
+ of_node_put(from);
+ return of_node_get(np);
+}
+
+/**
+ * of_find_node_by_type - Find a node by it's "device_type" property
+ * @from: The node to start searching from or NULL, the node
+ * you pass will not be searched, only the next one
+ * will; typically, you pass what the previous call
+ * returned. of_node_put() will be called on it
+ * @name: The type string to match against
+ *
+ * Returns a node pointer with refcount incremented, use
+ * of_node_put() on it when done.
+ */
+struct device_node *of_find_node_by_type(struct device_node *from,
+ const char *type)
+{
+ struct device_node *np = from ? from->allnext : allnodes;
+
+ for (; np != 0; np = np->allnext)
+ if (np->type != 0 && strcasecmp(np->type, type) == 0)
+ break;
+ if (from)
+ of_node_put(from);
+ return of_node_get(np);
+}
+
+/**
+ * of_find_compatible_node - Find a node based on type and one of the
+ * tokens in it's "compatible" property
+ * @from: The node to start searching from or NULL, the node
+ * you pass will not be searched, only the next one
+ * will; typically, you pass what the previous call
+ * returned. of_node_put() will be called on it
+ * @type: The type string to match "device_type" or NULL to ignore
+ * @compatible: The string to match to one of the tokens in the device
+ * "compatible" list.
+ *
+ * Returns a node pointer with refcount incremented, use
+ * of_node_put() on it when done.
+ */
+struct device_node *of_find_compatible_node(struct device_node *from,
+ const char *type, const char *compatible)
+{
+ struct device_node *np = from ? from->allnext : allnodes;
+
+ for (; np != 0; np = np->allnext) {
+ if (type != NULL
+ && !(np->type != 0 && strcasecmp(np->type, type) == 0))
+ continue;
+ if (device_is_compatible(np, compatible))
+ break;
+ }
+ if (from)
+ of_node_put(from);
+ return of_node_get(np);
+}
+
+/**
+ * of_find_node_by_path - Find a node matching a full OF path
+ * @path: The full path to match
+ *
+ * Returns a node pointer with refcount incremented, use
+ * of_node_put() on it when done.
+ */
+struct device_node *of_find_node_by_path(const char *path)
+{
+ struct device_node *np = allnodes;
+
+ for (; np != 0; np = np->allnext)
+ if (np->full_name != 0 && strcasecmp(np->full_name, path) == 0)
+ break;
+ return of_node_get(np);
+}
+
+/**
+ * of_find_all_nodes - Get next node in global list
+ * @prev: Previous node or NULL to start iteration
+ * of_node_put() will be called on it
+ *
+ * Returns a node pointer with refcount incremented, use
+ * of_node_put() on it when done.
+ */
+struct device_node *of_find_all_nodes(struct device_node *prev)
+{
+ return of_node_get(prev ? prev->allnext : allnodes);
+}
+
+/**
+ * of_get_parent - Get a node's parent if any
+ * @node: Node to get parent
+ *
+ * Returns a node pointer with refcount incremented, use
+ * of_node_put() on it when done.
+ */
+struct device_node *of_get_parent(const struct device_node *node)
+{
+ return node ? of_node_get(node->parent) : NULL;
+}
+
+/**
+ * of_get_next_child - Iterate a node childs
+ * @node: parent node
+ * @prev: previous child of the parent node, or NULL to get first
+ *
+ * Returns a node pointer with refcount incremented, use
+ * of_node_put() on it when done.
+ */
+struct device_node *of_get_next_child(const struct device_node *node,
+ struct device_node *prev)
+{
+ struct device_node *next = prev ? prev->sibling : node->child;
+
+ for (; next != 0; next = next->sibling)
+ if (of_node_get(next))
+ break;
+ if (prev)
+ of_node_put(prev);
+ return next;
+}
+
+/**
+ * of_node_get - Increment refcount of a node
+ * @node: Node to inc refcount, NULL is supported to
+ * simplify writing of callers
+ *
+ * Returns the node itself or NULL if gone. Current implementation
+ * does nothing as we don't yet do dynamic node allocation on ppc32
+ */
+struct device_node *of_node_get(struct device_node *node)
+{
+ return node;
+}
+
+/**
+ * of_node_put - Decrement refcount of a node
+ * @node: Node to dec refcount, NULL is supported to
+ * simplify writing of callers
+ *
+ * Current implementation does nothing as we don't yet do dynamic node
+ * allocation on ppc32
+ */
+void of_node_put(struct device_node *node)
+{
+}
+
+/*
+ * Find the device_node with a given phandle.
+ */
+static struct device_node * __init
+find_phandle(phandle ph)
+{
+ struct device_node *np;
+
+ for (np = allnodes; np != 0; np = np->allnext)
+ if (np->node == ph)
+ return np;
+ return NULL;
+}
+
+/*
+ * Find a property with a given name for a given node
+ * and return the value.
+ */
+unsigned char *
+get_property(struct device_node *np, const char *name, int *lenp)
+{
+ struct property *pp;
+
+ for (pp = np->properties; pp != 0; pp = pp->next)
+ if (pp->name != NULL && strcmp(pp->name, name) == 0) {
+ if (lenp != 0)
+ *lenp = pp->length;
+ return pp->value;
+ }
+ return NULL;
+}
+
+/*
+ * Add a property to a node
+ */
+void __openfirmware
+prom_add_property(struct device_node* np, struct property* prop)
+{
+ struct property **next = &np->properties;
+
+ prop->next = NULL;
+ while (*next)
+ next = &(*next)->next;
+ *next = prop;
+}
+
+/* I quickly hacked that one, check against spec ! */
+static inline unsigned long __openfirmware
+bus_space_to_resource_flags(unsigned int bus_space)
+{
+ u8 space = (bus_space >> 24) & 0xf;
+ if (space == 0)
+ space = 0x02;
+ if (space == 0x02)
+ return IORESOURCE_MEM;
+ else if (space == 0x01)
+ return IORESOURCE_IO;
+ else {
+ printk(KERN_WARNING "prom.c: bus_space_to_resource_flags(), space: %x\n",
+ bus_space);
+ return 0;
+ }
+}
+
+static struct resource* __openfirmware
+find_parent_pci_resource(struct pci_dev* pdev, struct address_range *range)
+{
+ unsigned long mask;
+ int i;
+
+ /* Check this one */
+ mask = bus_space_to_resource_flags(range->space);
+ for (i=0; i<DEVICE_COUNT_RESOURCE; i++) {
+ if ((pdev->resource[i].flags & mask) == mask &&
+ pdev->resource[i].start <= range->address &&
+ pdev->resource[i].end > range->address) {
+ if ((range->address + range->size - 1) > pdev->resource[i].end) {
+ /* Add better message */
+ printk(KERN_WARNING "PCI/OF resource overlap !\n");
+ return NULL;
+ }
+ break;
+ }
+ }
+ if (i == DEVICE_COUNT_RESOURCE)
+ return NULL;
+ return &pdev->resource[i];
+}
+
+/*
+ * Request an OF device resource. Currently handles child of PCI devices,
+ * or other nodes attached to the root node. Ultimately, put some
+ * link to resources in the OF node.
+ */
+struct resource* __openfirmware
+request_OF_resource(struct device_node* node, int index, const char* name_postfix)
+{
+ struct pci_dev* pcidev;
+ u8 pci_bus, pci_devfn;
+ unsigned long iomask;
+ struct device_node* nd;
+ struct resource* parent;
+ struct resource *res = NULL;
+ int nlen, plen;
+
+ if (index >= node->n_addrs)
+ goto fail;
+
+ /* Sanity check on bus space */
+ iomask = bus_space_to_resource_flags(node->addrs[index].space);
+ if (iomask & IORESOURCE_MEM)
+ parent = &iomem_resource;
+ else if (iomask & IORESOURCE_IO)
+ parent = &ioport_resource;
+ else
+ goto fail;
+
+ /* Find a PCI parent if any */
+ nd = node;
+ pcidev = NULL;
+ while(nd) {
+ if (!pci_device_from_OF_node(nd, &pci_bus, &pci_devfn))
+ pcidev = pci_find_slot(pci_bus, pci_devfn);
+ if (pcidev) break;
+ nd = nd->parent;
+ }
+ if (pcidev)
+ parent = find_parent_pci_resource(pcidev, &node->addrs[index]);
+ if (!parent) {
+ printk(KERN_WARNING "request_OF_resource(%s), parent not found\n",
+ node->name);
+ goto fail;
+ }
+
+ res = __request_region(parent, node->addrs[index].address, node->addrs[index].size, NULL);
+ if (!res)
+ goto fail;
+ nlen = strlen(node->name);
+ plen = name_postfix ? strlen(name_postfix) : 0;
+ res->name = (const char *)kmalloc(nlen+plen+1, GFP_KERNEL);
+ if (res->name) {
+ strcpy((char *)res->name, node->name);
+ if (plen)
+ strcpy((char *)res->name+nlen, name_postfix);
+ }
+ return res;
+fail:
+ return NULL;
+}
+
+int __openfirmware
+release_OF_resource(struct device_node* node, int index)
+{
+ struct pci_dev* pcidev;
+ u8 pci_bus, pci_devfn;
+ unsigned long iomask, start, end;
+ struct device_node* nd;
+ struct resource* parent;
+ struct resource *res = NULL;
+
+ if (index >= node->n_addrs)
+ return -EINVAL;
+
+ /* Sanity check on bus space */
+ iomask = bus_space_to_resource_flags(node->addrs[index].space);
+ if (iomask & IORESOURCE_MEM)
+ parent = &iomem_resource;
+ else if (iomask & IORESOURCE_IO)
+ parent = &ioport_resource;
+ else
+ return -EINVAL;
+
+ /* Find a PCI parent if any */
+ nd = node;
+ pcidev = NULL;
+ while(nd) {
+ if (!pci_device_from_OF_node(nd, &pci_bus, &pci_devfn))
+ pcidev = pci_find_slot(pci_bus, pci_devfn);
+ if (pcidev) break;
+ nd = nd->parent;
+ }
+ if (pcidev)
+ parent = find_parent_pci_resource(pcidev, &node->addrs[index]);
+ if (!parent) {
+ printk(KERN_WARNING "release_OF_resource(%s), parent not found\n",
+ node->name);
+ return -ENODEV;
+ }
+
+ /* Find us in the parent and its childs */
+ res = parent->child;
+ start = node->addrs[index].address;
+ end = start + node->addrs[index].size - 1;
+ while (res) {
+ if (res->start == start && res->end == end &&
+ (res->flags & IORESOURCE_BUSY))
+ break;
+ if (res->start <= start && res->end >= end)
+ res = res->child;
+ else
+ res = res->sibling;
+ }
+ if (!res)
+ return -ENODEV;
+
+ if (res->name) {
+ kfree(res->name);
+ res->name = NULL;
+ }
+ release_resource(res);
+ kfree(res);
+
+ return 0;
+}
+
+#if 0
+void __openfirmware
+print_properties(struct device_node *np)
+{
+ struct property *pp;
+ char *cp;
+ int i, n;
+
+ for (pp = np->properties; pp != 0; pp = pp->next) {
+ printk(KERN_INFO "%s", pp->name);
+ for (i = strlen(pp->name); i < 16; ++i)
+ printk(" ");
+ cp = (char *) pp->value;
+ for (i = pp->length; i > 0; --i, ++cp)
+ if ((i > 1 && (*cp < 0x20 || *cp > 0x7e))
+ || (i == 1 && *cp != 0))
+ break;
+ if (i == 0 && pp->length > 1) {
+ /* looks like a string */
+ printk(" %s\n", (char *) pp->value);
+ } else {
+ /* dump it in hex */
+ n = pp->length;
+ if (n > 64)
+ n = 64;
+ if (pp->length % 4 == 0) {
+ unsigned int *p = (unsigned int *) pp->value;
+
+ n /= 4;
+ for (i = 0; i < n; ++i) {
+ if (i != 0 && (i % 4) == 0)
+ printk("\n ");
+ printk(" %08x", *p++);
+ }
+ } else {
+ unsigned char *bp = pp->value;
+
+ for (i = 0; i < n; ++i) {
+ if (i != 0 && (i % 16) == 0)
+ printk("\n ");
+ printk(" %02x", *bp++);
+ }
+ }
+ printk("\n");
+ if (pp->length > 64)
+ printk(" ... (length = %d)\n",
+ pp->length);
+ }
+ }
+}
+#endif
+
+static DEFINE_SPINLOCK(rtas_lock);
+
+/* this can be called after setup -- Cort */
+int __openfirmware
+call_rtas(const char *service, int nargs, int nret,
+ unsigned long *outputs, ...)
+{
+ va_list list;
+ int i;
+ unsigned long s;
+ struct device_node *rtas;
+ int *tokp;
+ union {
+ unsigned long words[16];
+ double align;
+ } u;
+
+ rtas = find_devices("rtas");
+ if (rtas == NULL)
+ return -1;
+ tokp = (int *) get_property(rtas, service, NULL);
+ if (tokp == NULL) {
+ printk(KERN_ERR "No RTAS service called %s\n", service);
+ return -1;
+ }
+ u.words[0] = *tokp;
+ u.words[1] = nargs;
+ u.words[2] = nret;
+ va_start(list, outputs);
+ for (i = 0; i < nargs; ++i)
+ u.words[i+3] = va_arg(list, unsigned long);
+ va_end(list);
+
+ /*
+ * RTAS doesn't use floating point.
+ * Or at least, according to the CHRP spec we enter RTAS
+ * with FP disabled, and it doesn't change the FP registers.
+ * -- paulus.
+ */
+ spin_lock_irqsave(&rtas_lock, s);
+ enter_rtas((void *)__pa(&u));
+ spin_unlock_irqrestore(&rtas_lock, s);
+
+ if (nret > 1 && outputs != NULL)
+ for (i = 0; i < nret-1; ++i)
+ outputs[i] = u.words[i+nargs+4];
+ return u.words[nargs+3];
+}
diff --git a/arch/ppc/syslib/prom_init.c b/arch/ppc/syslib/prom_init.c
new file mode 100644
index 0000000..2cee871
--- /dev/null
+++ b/arch/ppc/syslib/prom_init.c
@@ -0,0 +1,1002 @@
+/*
+ * Note that prom_init() and anything called from prom_init()
+ * may be running at an address that is different from the address
+ * that it was linked at. References to static data items are
+ * handled by compiling this file with -mrelocatable-lib.
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/init.h>
+#include <linux/version.h>
+#include <linux/threads.h>
+#include <linux/spinlock.h>
+#include <linux/ioport.h>
+#include <linux/pci.h>
+#include <linux/slab.h>
+#include <linux/bitops.h>
+
+#include <asm/sections.h>
+#include <asm/prom.h>
+#include <asm/page.h>
+#include <asm/irq.h>
+#include <asm/io.h>
+#include <asm/smp.h>
+#include <asm/bootx.h>
+#include <asm/system.h>
+#include <asm/mmu.h>
+#include <asm/pgtable.h>
+#include <asm/bootinfo.h>
+#include <asm/btext.h>
+#include <asm/pci-bridge.h>
+#include <asm/open_pic.h>
+#include <asm/cacheflush.h>
+
+#ifdef CONFIG_LOGO_LINUX_CLUT224
+#include <linux/linux_logo.h>
+extern const struct linux_logo logo_linux_clut224;
+#endif
+
+/*
+ * Properties whose value is longer than this get excluded from our
+ * copy of the device tree. This way we don't waste space storing
+ * things like "driver,AAPL,MacOS,PowerPC" properties. But this value
+ * does need to be big enough to ensure that we don't lose things
+ * like the interrupt-map property on a PCI-PCI bridge.
+ */
+#define MAX_PROPERTY_LENGTH 4096
+
+#ifndef FB_MAX /* avoid pulling in all of the fb stuff */
+#define FB_MAX 8
+#endif
+
+#define ALIGNUL(x) (((x) + sizeof(unsigned long)-1) & -sizeof(unsigned long))
+
+typedef u32 prom_arg_t;
+
+struct prom_args {
+ const char *service;
+ int nargs;
+ int nret;
+ prom_arg_t args[10];
+};
+
+struct pci_address {
+ unsigned a_hi;
+ unsigned a_mid;
+ unsigned a_lo;
+};
+
+struct pci_reg_property {
+ struct pci_address addr;
+ unsigned size_hi;
+ unsigned size_lo;
+};
+
+struct pci_range {
+ struct pci_address addr;
+ unsigned phys;
+ unsigned size_hi;
+ unsigned size_lo;
+};
+
+struct isa_reg_property {
+ unsigned space;
+ unsigned address;
+ unsigned size;
+};
+
+struct pci_intr_map {
+ struct pci_address addr;
+ unsigned dunno;
+ phandle int_ctrler;
+ unsigned intr;
+};
+
+static void prom_exit(void);
+static int call_prom(const char *service, int nargs, int nret, ...);
+static int call_prom_ret(const char *service, int nargs, int nret,
+ prom_arg_t *rets, ...);
+static void prom_print_hex(unsigned int v);
+static int prom_set_color(ihandle ih, int i, int r, int g, int b);
+static int prom_next_node(phandle *nodep);
+static unsigned long check_display(unsigned long mem);
+static void setup_disp_fake_bi(ihandle dp);
+static unsigned long copy_device_tree(unsigned long mem_start,
+ unsigned long mem_end);
+static unsigned long inspect_node(phandle node, struct device_node *dad,
+ unsigned long mem_start, unsigned long mem_end,
+ struct device_node ***allnextpp);
+static void prom_hold_cpus(unsigned long mem);
+static void prom_instantiate_rtas(void);
+static void * early_get_property(unsigned long base, unsigned long node,
+ char *prop);
+
+prom_entry prom __initdata;
+ihandle prom_chosen __initdata;
+ihandle prom_stdout __initdata;
+
+static char *prom_display_paths[FB_MAX] __initdata;
+static phandle prom_display_nodes[FB_MAX] __initdata;
+static unsigned int prom_num_displays __initdata;
+static ihandle prom_disp_node __initdata;
+char *of_stdout_device __initdata;
+
+unsigned int rtas_data; /* physical pointer */
+unsigned int rtas_entry; /* physical pointer */
+unsigned int rtas_size;
+unsigned int old_rtas;
+
+boot_infos_t *boot_infos;
+char *bootpath;
+char *bootdevice;
+struct device_node *allnodes;
+
+extern char *klimit;
+
+static void __init
+prom_exit(void)
+{
+ struct prom_args args;
+
+ args.service = "exit";
+ args.nargs = 0;
+ args.nret = 0;
+ prom(&args);
+ for (;;) /* should never get here */
+ ;
+}
+
+static int __init
+call_prom(const char *service, int nargs, int nret, ...)
+{
+ va_list list;
+ int i;
+ struct prom_args prom_args;
+
+ prom_args.service = service;
+ prom_args.nargs = nargs;
+ prom_args.nret = nret;
+ va_start(list, nret);
+ for (i = 0; i < nargs; ++i)
+ prom_args.args[i] = va_arg(list, prom_arg_t);
+ va_end(list);
+ for (i = 0; i < nret; ++i)
+ prom_args.args[i + nargs] = 0;
+ prom(&prom_args);
+ return prom_args.args[nargs];
+}
+
+static int __init
+call_prom_ret(const char *service, int nargs, int nret, prom_arg_t *rets, ...)
+{
+ va_list list;
+ int i;
+ struct prom_args prom_args;
+
+ prom_args.service = service;
+ prom_args.nargs = nargs;
+ prom_args.nret = nret;
+ va_start(list, rets);
+ for (i = 0; i < nargs; ++i)
+ prom_args.args[i] = va_arg(list, int);
+ va_end(list);
+ for (i = 0; i < nret; ++i)
+ prom_args.args[i + nargs] = 0;
+ prom(&prom_args);
+ for (i = 1; i < nret; ++i)
+ rets[i-1] = prom_args.args[nargs + i];
+ return prom_args.args[nargs];
+}
+
+void __init
+prom_print(const char *msg)
+{
+ const char *p, *q;
+
+ if (prom_stdout == 0)
+ return;
+
+ for (p = msg; *p != 0; p = q) {
+ for (q = p; *q != 0 && *q != '\n'; ++q)
+ ;
+ if (q > p)
+ call_prom("write", 3, 1, prom_stdout, p, q - p);
+ if (*q != 0) {
+ ++q;
+ call_prom("write", 3, 1, prom_stdout, "\r\n", 2);
+ }
+ }
+}
+
+static void __init
+prom_print_hex(unsigned int v)
+{
+ char buf[16];
+ int i, c;
+
+ for (i = 0; i < 8; ++i) {
+ c = (v >> ((7-i)*4)) & 0xf;
+ c += (c >= 10)? ('a' - 10): '0';
+ buf[i] = c;
+ }
+ buf[i] = ' ';
+ buf[i+1] = 0;
+ prom_print(buf);
+}
+
+static int __init
+prom_set_color(ihandle ih, int i, int r, int g, int b)
+{
+ return call_prom("call-method", 6, 1, "color!", ih, i, b, g, r);
+}
+
+static int __init
+prom_next_node(phandle *nodep)
+{
+ phandle node;
+
+ if ((node = *nodep) != 0
+ && (*nodep = call_prom("child", 1, 1, node)) != 0)
+ return 1;
+ if ((*nodep = call_prom("peer", 1, 1, node)) != 0)
+ return 1;
+ for (;;) {
+ if ((node = call_prom("parent", 1, 1, node)) == 0)
+ return 0;
+ if ((*nodep = call_prom("peer", 1, 1, node)) != 0)
+ return 1;
+ }
+}
+
+#ifdef CONFIG_POWER4
+/*
+ * Set up a hash table with a set of entries in it to map the
+ * first 64MB of RAM. This is used on 64-bit machines since
+ * some of them don't have BATs.
+ */
+
+static inline void make_pte(unsigned long htab, unsigned int hsize,
+ unsigned int va, unsigned int pa, int mode)
+{
+ unsigned int *pteg;
+ unsigned int hash, i, vsid;
+
+ vsid = ((va >> 28) * 0x111) << 12;
+ hash = ((va ^ vsid) >> 5) & 0x7fff80;
+ pteg = (unsigned int *)(htab + (hash & (hsize - 1)));
+ for (i = 0; i < 8; ++i, pteg += 4) {
+ if ((pteg[1] & 1) == 0) {
+ pteg[1] = vsid | ((va >> 16) & 0xf80) | 1;
+ pteg[3] = pa | mode;
+ break;
+ }
+ }
+}
+
+extern unsigned long _SDR1;
+extern PTE *Hash;
+extern unsigned long Hash_size;
+
+static void __init
+prom_alloc_htab(void)
+{
+ unsigned int hsize;
+ unsigned long htab;
+ unsigned int addr;
+
+ /*
+ * Because of OF bugs we can't use the "claim" client
+ * interface to allocate memory for the hash table.
+ * This code is only used on 64-bit PPCs, and the only
+ * 64-bit PPCs at the moment are RS/6000s, and their
+ * OF is based at 0xc00000 (the 12M point), so we just
+ * arbitrarily use the 0x800000 - 0xc00000 region for the
+ * hash table.
+ * -- paulus.
+ */
+ hsize = 4 << 20; /* POWER4 has no BATs */
+ htab = (8 << 20);
+ call_prom("claim", 3, 1, htab, hsize, 0);
+ Hash = (void *)(htab + KERNELBASE);
+ Hash_size = hsize;
+ _SDR1 = htab + __ilog2(hsize) - 18;
+
+ /*
+ * Put in PTEs for the first 64MB of RAM
+ */
+ memset((void *)htab, 0, hsize);
+ for (addr = 0; addr < 0x4000000; addr += 0x1000)
+ make_pte(htab, hsize, addr + KERNELBASE, addr,
+ _PAGE_ACCESSED | _PAGE_COHERENT | PP_RWXX);
+#if 0 /* DEBUG stuff mapping the SCC */
+ make_pte(htab, hsize, 0x80013000, 0x80013000,
+ _PAGE_ACCESSED | _PAGE_NO_CACHE | _PAGE_GUARDED | PP_RWXX);
+#endif
+}
+#endif /* CONFIG_POWER4 */
+
+
+/*
+ * If we have a display that we don't know how to drive,
+ * we will want to try to execute OF's open method for it
+ * later. However, OF will probably fall over if we do that
+ * we've taken over the MMU.
+ * So we check whether we will need to open the display,
+ * and if so, open it now.
+ */
+static unsigned long __init
+check_display(unsigned long mem)
+{
+ phandle node;
+ ihandle ih;
+ int i, j;
+ char type[16], *path;
+ static unsigned char default_colors[] = {
+ 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0xaa,
+ 0x00, 0xaa, 0x00,
+ 0x00, 0xaa, 0xaa,
+ 0xaa, 0x00, 0x00,
+ 0xaa, 0x00, 0xaa,
+ 0xaa, 0xaa, 0x00,
+ 0xaa, 0xaa, 0xaa,
+ 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0xff,
+ 0x55, 0xff, 0x55,
+ 0x55, 0xff, 0xff,
+ 0xff, 0x55, 0x55,
+ 0xff, 0x55, 0xff,
+ 0xff, 0xff, 0x55,
+ 0xff, 0xff, 0xff
+ };
+ const unsigned char *clut;
+
+ prom_disp_node = 0;
+
+ for (node = 0; prom_next_node(&node); ) {
+ type[0] = 0;
+ call_prom("getprop", 4, 1, node, "device_type",
+ type, sizeof(type));
+ if (strcmp(type, "display") != 0)
+ continue;
+ /* It seems OF doesn't null-terminate the path :-( */
+ path = (char *) mem;
+ memset(path, 0, 256);
+ if (call_prom("package-to-path", 3, 1, node, path, 255) < 0)
+ continue;
+
+ /*
+ * If this display is the device that OF is using for stdout,
+ * move it to the front of the list.
+ */
+ mem += strlen(path) + 1;
+ i = prom_num_displays++;
+ if (of_stdout_device != 0 && i > 0
+ && strcmp(of_stdout_device, path) == 0) {
+ for (; i > 0; --i) {
+ prom_display_paths[i]
+ = prom_display_paths[i-1];
+ prom_display_nodes[i]
+ = prom_display_nodes[i-1];
+ }
+ }
+ prom_display_paths[i] = path;
+ prom_display_nodes[i] = node;
+ if (i == 0)
+ prom_disp_node = node;
+ if (prom_num_displays >= FB_MAX)
+ break;
+ }
+
+ for (j=0; j<prom_num_displays; j++) {
+ path = prom_display_paths[j];
+ node = prom_display_nodes[j];
+ prom_print("opening display ");
+ prom_print(path);
+ ih = call_prom("open", 1, 1, path);
+ if (ih == 0 || ih == (ihandle) -1) {
+ prom_print("... failed\n");
+ for (i=j+1; i<prom_num_displays; i++) {
+ prom_display_paths[i-1] = prom_display_paths[i];
+ prom_display_nodes[i-1] = prom_display_nodes[i];
+ }
+ if (--prom_num_displays > 0) {
+ prom_disp_node = prom_display_nodes[j];
+ j--;
+ } else
+ prom_disp_node = 0;
+ continue;
+ } else {
+ prom_print("... ok\n");
+ call_prom("setprop", 4, 1, node, "linux,opened", 0, 0);
+
+ /*
+ * Setup a usable color table when the appropriate
+ * method is available.
+ * Should update this to use set-colors.
+ */
+ clut = default_colors;
+ for (i = 0; i < 32; i++, clut += 3)
+ if (prom_set_color(ih, i, clut[0], clut[1],
+ clut[2]) != 0)
+ break;
+
+#ifdef CONFIG_LOGO_LINUX_CLUT224
+ clut = PTRRELOC(logo_linux_clut224.clut);
+ for (i = 0; i < logo_linux_clut224.clutsize;
+ i++, clut += 3)
+ if (prom_set_color(ih, i + 32, clut[0],
+ clut[1], clut[2]) != 0)
+ break;
+#endif /* CONFIG_LOGO_LINUX_CLUT224 */
+ }
+ }
+
+ if (prom_stdout) {
+ phandle p;
+ p = call_prom("instance-to-package", 1, 1, prom_stdout);
+ if (p && p != -1) {
+ type[0] = 0;
+ call_prom("getprop", 4, 1, p, "device_type",
+ type, sizeof(type));
+ if (strcmp(type, "display") == 0)
+ call_prom("setprop", 4, 1, p, "linux,boot-display",
+ 0, 0);
+ }
+ }
+
+ return ALIGNUL(mem);
+}
+
+/* This function will enable the early boot text when doing OF booting. This
+ * way, xmon output should work too
+ */
+static void __init
+setup_disp_fake_bi(ihandle dp)
+{
+#ifdef CONFIG_BOOTX_TEXT
+ int width = 640, height = 480, depth = 8, pitch;
+ unsigned address;
+ struct pci_reg_property addrs[8];
+ int i, naddrs;
+ char name[32];
+ char *getprop = "getprop";
+
+ prom_print("Initializing fake screen: ");
+
+ memset(name, 0, sizeof(name));
+ call_prom(getprop, 4, 1, dp, "name", name, sizeof(name));
+ name[sizeof(name)-1] = 0;
+ prom_print(name);
+ prom_print("\n");
+ call_prom(getprop, 4, 1, dp, "width", &width, sizeof(width));
+ call_prom(getprop, 4, 1, dp, "height", &height, sizeof(height));
+ call_prom(getprop, 4, 1, dp, "depth", &depth, sizeof(depth));
+ pitch = width * ((depth + 7) / 8);
+ call_prom(getprop, 4, 1, dp, "linebytes",
+ &pitch, sizeof(pitch));
+ if (pitch == 1)
+ pitch = 0x1000; /* for strange IBM display */
+ address = 0;
+ call_prom(getprop, 4, 1, dp, "address",
+ &address, sizeof(address));
+ if (address == 0) {
+ /* look for an assigned address with a size of >= 1MB */
+ naddrs = call_prom(getprop, 4, 1, dp, "assigned-addresses",
+ addrs, sizeof(addrs));
+ naddrs /= sizeof(struct pci_reg_property);
+ for (i = 0; i < naddrs; ++i) {
+ if (addrs[i].size_lo >= (1 << 20)) {
+ address = addrs[i].addr.a_lo;
+ /* use the BE aperture if possible */
+ if (addrs[i].size_lo >= (16 << 20))
+ address += (8 << 20);
+ break;
+ }
+ }
+ if (address == 0) {
+ prom_print("Failed to get address\n");
+ return;
+ }
+ }
+ /* kludge for valkyrie */
+ if (strcmp(name, "valkyrie") == 0)
+ address += 0x1000;
+
+#ifdef CONFIG_POWER4
+#if CONFIG_TASK_SIZE > 0x80000000
+#error CONFIG_TASK_SIZE cannot be above 0x80000000 with BOOTX_TEXT on G5
+#endif
+ {
+ extern boot_infos_t disp_bi;
+ unsigned long va, pa, i, offset;
+ va = 0x90000000;
+ pa = address & 0xfffff000ul;
+ offset = address & 0x00000fff;
+
+ for (i=0; i<0x4000; i++) {
+ make_pte((unsigned long)Hash - KERNELBASE, Hash_size, va, pa,
+ _PAGE_ACCESSED | _PAGE_NO_CACHE |
+ _PAGE_GUARDED | PP_RWXX);
+ va += 0x1000;
+ pa += 0x1000;
+ }
+ btext_setup_display(width, height, depth, pitch, 0x90000000 | offset);
+ disp_bi.dispDeviceBase = (u8 *)address;
+ }
+#else /* CONFIG_POWER4 */
+ btext_setup_display(width, height, depth, pitch, address);
+ btext_prepare_BAT();
+#endif /* CONFIG_POWER4 */
+#endif /* CONFIG_BOOTX_TEXT */
+}
+
+/*
+ * Make a copy of the device tree from the PROM.
+ */
+static unsigned long __init
+copy_device_tree(unsigned long mem_start, unsigned long mem_end)
+{
+ phandle root;
+ unsigned long new_start;
+ struct device_node **allnextp;
+
+ root = call_prom("peer", 1, 1, (phandle)0);
+ if (root == (phandle)0) {
+ prom_print("couldn't get device tree root\n");
+ prom_exit();
+ }
+ allnextp = &allnodes;
+ mem_start = ALIGNUL(mem_start);
+ new_start = inspect_node(root, NULL, mem_start, mem_end, &allnextp);
+ *allnextp = NULL;
+ return new_start;
+}
+
+static unsigned long __init
+inspect_node(phandle node, struct device_node *dad,
+ unsigned long mem_start, unsigned long mem_end,
+ struct device_node ***allnextpp)
+{
+ int l;
+ phandle child;
+ struct device_node *np;
+ struct property *pp, **prev_propp;
+ char *prev_name, *namep;
+ unsigned char *valp;
+
+ np = (struct device_node *) mem_start;
+ mem_start += sizeof(struct device_node);
+ memset(np, 0, sizeof(*np));
+ np->node = node;
+ **allnextpp = PTRUNRELOC(np);
+ *allnextpp = &np->allnext;
+ if (dad != 0) {
+ np->parent = PTRUNRELOC(dad);
+ /* we temporarily use the `next' field as `last_child'. */
+ if (dad->next == 0)
+ dad->child = PTRUNRELOC(np);
+ else
+ dad->next->sibling = PTRUNRELOC(np);
+ dad->next = np;
+ }
+
+ /* get and store all properties */
+ prev_propp = &np->properties;
+ prev_name = "";
+ for (;;) {
+ pp = (struct property *) mem_start;
+ namep = (char *) (pp + 1);
+ pp->name = PTRUNRELOC(namep);
+ if (call_prom("nextprop", 3, 1, node, prev_name, namep) <= 0)
+ break;
+ mem_start = ALIGNUL((unsigned long)namep + strlen(namep) + 1);
+ prev_name = namep;
+ valp = (unsigned char *) mem_start;
+ pp->value = PTRUNRELOC(valp);
+ pp->length = call_prom("getprop", 4, 1, node, namep,
+ valp, mem_end - mem_start);
+ if (pp->length < 0)
+ continue;
+#ifdef MAX_PROPERTY_LENGTH
+ if (pp->length > MAX_PROPERTY_LENGTH)
+ continue; /* ignore this property */
+#endif
+ mem_start = ALIGNUL(mem_start + pp->length);
+ *prev_propp = PTRUNRELOC(pp);
+ prev_propp = &pp->next;
+ }
+ if (np->node != 0) {
+ /* Add a "linux,phandle" property" */
+ pp = (struct property *) mem_start;
+ *prev_propp = PTRUNRELOC(pp);
+ prev_propp = &pp->next;
+ namep = (char *) (pp + 1);
+ pp->name = PTRUNRELOC(namep);
+ strcpy(namep, "linux,phandle");
+ mem_start = ALIGNUL((unsigned long)namep + strlen(namep) + 1);
+ pp->value = (unsigned char *) PTRUNRELOC(&np->node);
+ pp->length = sizeof(np->node);
+ }
+ *prev_propp = NULL;
+
+ /* get the node's full name */
+ l = call_prom("package-to-path", 3, 1, node,
+ mem_start, mem_end - mem_start);
+ if (l >= 0) {
+ np->full_name = PTRUNRELOC((char *) mem_start);
+ *(char *)(mem_start + l) = 0;
+ mem_start = ALIGNUL(mem_start + l + 1);
+ }
+
+ /* do all our children */
+ child = call_prom("child", 1, 1, node);
+ while (child != 0) {
+ mem_start = inspect_node(child, np, mem_start, mem_end,
+ allnextpp);
+ child = call_prom("peer", 1, 1, child);
+ }
+
+ return mem_start;
+}
+
+unsigned long smp_chrp_cpu_nr __initdata = 0;
+
+/*
+ * With CHRP SMP we need to use the OF to start the other
+ * processors so we can't wait until smp_boot_cpus (the OF is
+ * trashed by then) so we have to put the processors into
+ * a holding pattern controlled by the kernel (not OF) before
+ * we destroy the OF.
+ *
+ * This uses a chunk of high memory, puts some holding pattern
+ * code there and sends the other processors off to there until
+ * smp_boot_cpus tells them to do something. We do that by using
+ * physical address 0x0. The holding pattern checks that address
+ * until its cpu # is there, when it is that cpu jumps to
+ * __secondary_start(). smp_boot_cpus() takes care of setting those
+ * values.
+ *
+ * We also use physical address 0x4 here to tell when a cpu
+ * is in its holding pattern code.
+ *
+ * -- Cort
+ *
+ * Note that we have to do this if we have more than one CPU,
+ * even if this is a UP kernel. Otherwise when we trash OF
+ * the other CPUs will start executing some random instructions
+ * and crash the system. -- paulus
+ */
+static void __init
+prom_hold_cpus(unsigned long mem)
+{
+ extern void __secondary_hold(void);
+ unsigned long i;
+ int cpu;
+ phandle node;
+ char type[16], *path;
+ unsigned int reg;
+
+ /*
+ * XXX: hack to make sure we're chrp, assume that if we're
+ * chrp we have a device_type property -- Cort
+ */
+ node = call_prom("finddevice", 1, 1, "/");
+ if (call_prom("getprop", 4, 1, node,
+ "device_type", type, sizeof(type)) <= 0)
+ return;
+
+ /* copy the holding pattern code to someplace safe (0) */
+ /* the holding pattern is now within the first 0x100
+ bytes of the kernel image -- paulus */
+ memcpy((void *)0, _stext, 0x100);
+ flush_icache_range(0, 0x100);
+
+ /* look for cpus */
+ *(unsigned long *)(0x0) = 0;
+ asm volatile("dcbf 0,%0": : "r" (0) : "memory");
+ for (node = 0; prom_next_node(&node); ) {
+ type[0] = 0;
+ call_prom("getprop", 4, 1, node, "device_type",
+ type, sizeof(type));
+ if (strcmp(type, "cpu") != 0)
+ continue;
+ path = (char *) mem;
+ memset(path, 0, 256);
+ if (call_prom("package-to-path", 3, 1, node, path, 255) < 0)
+ continue;
+ reg = -1;
+ call_prom("getprop", 4, 1, node, "reg", ®, sizeof(reg));
+ cpu = smp_chrp_cpu_nr++;
+#ifdef CONFIG_SMP
+ smp_hw_index[cpu] = reg;
+#endif /* CONFIG_SMP */
+ /* XXX: hack - don't start cpu 0, this cpu -- Cort */
+ if (cpu == 0)
+ continue;
+ prom_print("starting cpu ");
+ prom_print(path);
+ *(ulong *)(0x4) = 0;
+ call_prom("start-cpu", 3, 0, node,
+ (char *)__secondary_hold - _stext, cpu);
+ prom_print("...");
+ for ( i = 0 ; (i < 10000) && (*(ulong *)(0x4) == 0); i++ )
+ ;
+ if (*(ulong *)(0x4) == cpu)
+ prom_print("ok\n");
+ else {
+ prom_print("failed: ");
+ prom_print_hex(*(ulong *)0x4);
+ prom_print("\n");
+ }
+ }
+}
+
+static void __init
+prom_instantiate_rtas(void)
+{
+ ihandle prom_rtas;
+ prom_arg_t result;
+
+ prom_rtas = call_prom("finddevice", 1, 1, "/rtas");
+ if (prom_rtas == -1)
+ return;
+
+ rtas_size = 0;
+ call_prom("getprop", 4, 1, prom_rtas,
+ "rtas-size", &rtas_size, sizeof(rtas_size));
+ prom_print("instantiating rtas");
+ if (rtas_size == 0) {
+ rtas_data = 0;
+ } else {
+ /*
+ * Ask OF for some space for RTAS.
+ * Actually OF has bugs so we just arbitrarily
+ * use memory at the 6MB point.
+ */
+ rtas_data = 6 << 20;
+ prom_print(" at ");
+ prom_print_hex(rtas_data);
+ }
+
+ prom_rtas = call_prom("open", 1, 1, "/rtas");
+ prom_print("...");
+ rtas_entry = 0;
+ if (call_prom_ret("call-method", 3, 2, &result,
+ "instantiate-rtas", prom_rtas, rtas_data) == 0)
+ rtas_entry = result;
+ if ((rtas_entry == -1) || (rtas_entry == 0))
+ prom_print(" failed\n");
+ else
+ prom_print(" done\n");
+}
+
+/*
+ * We enter here early on, when the Open Firmware prom is still
+ * handling exceptions and the MMU hash table for us.
+ */
+unsigned long __init
+prom_init(int r3, int r4, prom_entry pp)
+{
+ unsigned long mem;
+ ihandle prom_mmu;
+ unsigned long offset = reloc_offset();
+ int i, l;
+ char *p, *d;
+ unsigned long phys;
+ prom_arg_t result[3];
+ char model[32];
+ phandle node;
+ int rc;
+
+ /* Default */
+ phys = (unsigned long) &_stext;
+
+ /* First get a handle for the stdout device */
+ prom = pp;
+ prom_chosen = call_prom("finddevice", 1, 1, "/chosen");
+ if (prom_chosen == -1)
+ prom_exit();
+ if (call_prom("getprop", 4, 1, prom_chosen, "stdout",
+ &prom_stdout, sizeof(prom_stdout)) <= 0)
+ prom_exit();
+
+ /* Get the full OF pathname of the stdout device */
+ mem = (unsigned long) klimit + offset;
+ p = (char *) mem;
+ memset(p, 0, 256);
+ call_prom("instance-to-path", 3, 1, prom_stdout, p, 255);
+ of_stdout_device = p;
+ mem += strlen(p) + 1;
+
+ /* Get the boot device and translate it to a full OF pathname. */
+ p = (char *) mem;
+ l = call_prom("getprop", 4, 1, prom_chosen, "bootpath", p, 1<<20);
+ if (l > 0) {
+ p[l] = 0; /* should already be null-terminated */
+ bootpath = PTRUNRELOC(p);
+ mem += l + 1;
+ d = (char *) mem;
+ *d = 0;
+ call_prom("canon", 3, 1, p, d, 1<<20);
+ bootdevice = PTRUNRELOC(d);
+ mem = ALIGNUL(mem + strlen(d) + 1);
+ }
+
+ prom_instantiate_rtas();
+
+#ifdef CONFIG_POWER4
+ /*
+ * Find out how much memory we have and allocate a
+ * suitably-sized hash table.
+ */
+ prom_alloc_htab();
+#endif
+ mem = check_display(mem);
+
+ prom_print("copying OF device tree...");
+ mem = copy_device_tree(mem, mem + (1<<20));
+ prom_print("done\n");
+
+ prom_hold_cpus(mem);
+
+ klimit = (char *) (mem - offset);
+
+ node = call_prom("finddevice", 1, 1, "/");
+ rc = call_prom("getprop", 4, 1, node, "model", model, sizeof(model));
+ if (rc > 0 && !strncmp (model, "Pegasos", 7)
+ && strncmp (model, "Pegasos2", 8)) {
+ /* Pegasos 1 has a broken translate method in the OF,
+ * and furthermore the BATs are mapped 1:1 so the phys
+ * address calculated above is correct, so let's use
+ * it directly.
+ */
+ } else if (offset == 0) {
+ /* If we are already running at 0xc0000000, we assume we were
+ * loaded by an OF bootloader which did set a BAT for us.
+ * This breaks OF translate so we force phys to be 0.
+ */
+ prom_print("(already at 0xc0000000) phys=0\n");
+ phys = 0;
+ } else if (call_prom("getprop", 4, 1, prom_chosen, "mmu",
+ &prom_mmu, sizeof(prom_mmu)) <= 0) {
+ prom_print(" no MMU found\n");
+ } else if (call_prom_ret("call-method", 4, 4, result, "translate",
+ prom_mmu, &_stext, 1) != 0) {
+ prom_print(" (translate failed)\n");
+ } else {
+ /* We assume the phys. address size is 3 cells */
+ phys = result[2];
+ }
+
+ if (prom_disp_node != 0)
+ setup_disp_fake_bi(prom_disp_node);
+
+ /* Use quiesce call to get OF to shut down any devices it's using */
+ prom_print("Calling quiesce ...\n");
+ call_prom("quiesce", 0, 0);
+
+ /* Relocate various pointers which will be used once the
+ kernel is running at the address it was linked at. */
+ for (i = 0; i < prom_num_displays; ++i)
+ prom_display_paths[i] = PTRUNRELOC(prom_display_paths[i]);
+
+#ifdef CONFIG_SERIAL_CORE_CONSOLE
+ /* Relocate the of stdout for console autodetection */
+ of_stdout_device = PTRUNRELOC(of_stdout_device);
+#endif
+
+ prom_print("returning 0x");
+ prom_print_hex(phys);
+ prom_print("from prom_init\n");
+ prom_stdout = 0;
+
+ return phys;
+}
+
+/*
+ * early_get_property is used to access the device tree image prepared
+ * by BootX very early on, before the pointers in it have been relocated.
+ */
+static void * __init
+early_get_property(unsigned long base, unsigned long node, char *prop)
+{
+ struct device_node *np = (struct device_node *)(base + node);
+ struct property *pp;
+
+ for (pp = np->properties; pp != 0; pp = pp->next) {
+ pp = (struct property *) (base + (unsigned long)pp);
+ if (strcmp((char *)((unsigned long)pp->name + base),
+ prop) == 0) {
+ return (void *)((unsigned long)pp->value + base);
+ }
+ }
+ return NULL;
+}
+
+/* Is boot-info compatible ? */
+#define BOOT_INFO_IS_COMPATIBLE(bi) ((bi)->compatible_version <= BOOT_INFO_VERSION)
+#define BOOT_INFO_IS_V2_COMPATIBLE(bi) ((bi)->version >= 2)
+#define BOOT_INFO_IS_V4_COMPATIBLE(bi) ((bi)->version >= 4)
+
+void __init
+bootx_init(unsigned long r4, unsigned long phys)
+{
+ boot_infos_t *bi = (boot_infos_t *) r4;
+ unsigned long space;
+ unsigned long ptr, x;
+ char *model;
+
+ boot_infos = PTRUNRELOC(bi);
+ if (!BOOT_INFO_IS_V2_COMPATIBLE(bi))
+ bi->logicalDisplayBase = NULL;
+
+#ifdef CONFIG_BOOTX_TEXT
+ btext_init(bi);
+
+ /*
+ * Test if boot-info is compatible. Done only in config
+ * CONFIG_BOOTX_TEXT since there is nothing much we can do
+ * with an incompatible version, except display a message
+ * and eventually hang the processor...
+ *
+ * I'll try to keep enough of boot-info compatible in the
+ * future to always allow display of this message;
+ */
+ if (!BOOT_INFO_IS_COMPATIBLE(bi)) {
+ btext_drawstring(" !!! WARNING - Incompatible version of BootX !!!\n\n\n");
+ btext_flushscreen();
+ }
+#endif /* CONFIG_BOOTX_TEXT */
+
+ /* New BootX enters kernel with MMU off, i/os are not allowed
+ here. This hack will have been done by the boostrap anyway.
+ */
+ if (bi->version < 4) {
+ /*
+ * XXX If this is an iMac, turn off the USB controller.
+ */
+ model = (char *) early_get_property
+ (r4 + bi->deviceTreeOffset, 4, "model");
+ if (model
+ && (strcmp(model, "iMac,1") == 0
+ || strcmp(model, "PowerMac1,1") == 0)) {
+ out_le32((unsigned *)0x80880008, 1); /* XXX */
+ }
+ }
+
+ /* Move klimit to enclose device tree, args, ramdisk, etc... */
+ if (bi->version < 5) {
+ space = bi->deviceTreeOffset + bi->deviceTreeSize;
+ if (bi->ramDisk)
+ space = bi->ramDisk + bi->ramDiskSize;
+ } else
+ space = bi->totalParamsSize;
+ klimit = PTRUNRELOC((char *) bi + space);
+
+ /* New BootX will have flushed all TLBs and enters kernel with
+ MMU switched OFF, so this should not be useful anymore.
+ */
+ if (bi->version < 4) {
+ /*
+ * Touch each page to make sure the PTEs for them
+ * are in the hash table - the aim is to try to avoid
+ * getting DSI exceptions while copying the kernel image.
+ */
+ for (ptr = ((unsigned long) &_stext) & PAGE_MASK;
+ ptr < (unsigned long)bi + space; ptr += PAGE_SIZE)
+ x = *(volatile unsigned long *)ptr;
+ }
+
+#ifdef CONFIG_BOOTX_TEXT
+ /*
+ * Note that after we call btext_prepare_BAT, we can't do
+ * prom_draw*, flushscreen or clearscreen until we turn the MMU
+ * on, since btext_prepare_BAT sets disp_bi.logicalDisplayBase
+ * to a virtual address.
+ */
+ btext_prepare_BAT();
+#endif
+}
diff --git a/arch/ppc/syslib/qspan_pci.c b/arch/ppc/syslib/qspan_pci.c
new file mode 100644
index 0000000..57f4ed5
--- /dev/null
+++ b/arch/ppc/syslib/qspan_pci.c
@@ -0,0 +1,381 @@
+/*
+ * QSpan pci routines.
+ * Most 8xx boards use the QSpan PCI bridge. The config address register
+ * is located 0x500 from the base of the bridge control/status registers.
+ * The data register is located at 0x504.
+ * This is a two step operation. First, the address register is written,
+ * then the data register is read/written as required.
+ * I don't know what to do about interrupts (yet).
+ *
+ * The RPX Classic implementation shares a chip select for normal
+ * PCI access and QSpan control register addresses. The selection is
+ * further selected by a bit setting in a board control register.
+ * Although it should happen, we disable interrupts during this operation
+ * to make sure some driver doesn't accidentally access the PCI while
+ * we have switched the chip select.
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/delay.h>
+#include <linux/string.h>
+#include <linux/init.h>
+
+#include <asm/io.h>
+#include <asm/mpc8xx.h>
+#include <asm/system.h>
+#include <asm/machdep.h>
+#include <asm/pci-bridge.h>
+
+
+/*
+ * This blows......
+ * When reading the configuration space, if something does not respond
+ * the bus times out and we get a machine check interrupt. So, the
+ * good ol' exception tables come to mind to trap it and return some
+ * value.
+ *
+ * On an error we just return a -1, since that is what the caller wants
+ * returned if nothing is present. I copied this from __get_user_asm,
+ * with the only difference of returning -1 instead of EFAULT.
+ * There is an associated hack in the machine check trap code.
+ *
+ * The QSPAN is also a big endian device, that is it makes the PCI
+ * look big endian to us. This presents a problem for the Linux PCI
+ * functions, which assume little endian. For example, we see the
+ * first 32-bit word like this:
+ * ------------------------
+ * | Device ID | Vendor ID |
+ * ------------------------
+ * If we read/write as a double word, that's OK. But in our world,
+ * when read as a word, device ID is at location 0, not location 2 as
+ * the little endian PCI would believe. We have to switch bits in
+ * the PCI addresses given to us to get the data to/from the correct
+ * byte lanes.
+ *
+ * The QSPAN only supports 4 bits of "slot" in the dev_fn instead of 5.
+ * It always forces the MS bit to zero. Therefore, dev_fn values
+ * greater than 128 are returned as "no device found" errors.
+ *
+ * The QSPAN can only perform long word (32-bit) configuration cycles.
+ * The "offset" must have the two LS bits set to zero. Read operations
+ * require we read the entire word and then sort out what should be
+ * returned. Write operations other than long word require that we
+ * read the long word, update the proper word or byte, then write the
+ * entire long word back.
+ *
+ * PCI Bridge hack. We assume (correctly) that bus 0 is the primary
+ * PCI bus from the QSPAN. If we are called with a bus number other
+ * than zero, we create a Type 1 configuration access that a downstream
+ * PCI bridge will interpret.
+ */
+
+#define __get_qspan_pci_config(x, addr, op) \
+ __asm__ __volatile__( \
+ "1: "op" %0,0(%1)\n" \
+ " eieio\n" \
+ "2:\n" \
+ ".section .fixup,\"ax\"\n" \
+ "3: li %0,-1\n" \
+ " b 2b\n" \
+ ".section __ex_table,\"a\"\n" \
+ " .align 2\n" \
+ " .long 1b,3b\n" \
+ ".text" \
+ : "=r"(x) : "r"(addr) : " %0")
+
+#define QS_CONFIG_ADDR ((volatile uint *)(PCI_CSR_ADDR + 0x500))
+#define QS_CONFIG_DATA ((volatile uint *)(PCI_CSR_ADDR + 0x504))
+
+#define mk_config_addr(bus, dev, offset) \
+ (((bus)<<16) | ((dev)<<8) | (offset & 0xfc))
+
+#define mk_config_type1(bus, dev, offset) \
+ mk_config_addr(bus, dev, offset) | 1;
+
+static spinlock_t pcibios_lock = SPIN_LOCK_UNLOCKED;
+
+int qspan_pcibios_read_config_byte(unsigned char bus, unsigned char dev_fn,
+ unsigned char offset, unsigned char *val)
+{
+ uint temp;
+ u_char *cp;
+#ifdef CONFIG_RPXCLASSIC
+ unsigned long flags;
+#endif
+
+ if ((bus > 7) || (dev_fn > 127)) {
+ *val = 0xff;
+ return PCIBIOS_DEVICE_NOT_FOUND;
+ }
+
+#ifdef CONFIG_RPXCLASSIC
+ /* disable interrupts */
+ spin_lock_irqsave(&pcibios_lock, flags);
+ *((uint *)RPX_CSR_ADDR) &= ~BCSR2_QSPACESEL;
+ eieio();
+#endif
+
+ if (bus == 0)
+ *QS_CONFIG_ADDR = mk_config_addr(bus, dev_fn, offset);
+ else
+ *QS_CONFIG_ADDR = mk_config_type1(bus, dev_fn, offset);
+ __get_qspan_pci_config(temp, QS_CONFIG_DATA, "lwz");
+
+#ifdef CONFIG_RPXCLASSIC
+ *((uint *)RPX_CSR_ADDR) |= BCSR2_QSPACESEL;
+ eieio();
+ spin_unlock_irqrestore(&pcibios_lock, flags);
+#endif
+
+ offset ^= 0x03;
+ cp = ((u_char *)&temp) + (offset & 0x03);
+ *val = *cp;
+ return PCIBIOS_SUCCESSFUL;
+}
+
+int qspan_pcibios_read_config_word(unsigned char bus, unsigned char dev_fn,
+ unsigned char offset, unsigned short *val)
+{
+ uint temp;
+ ushort *sp;
+#ifdef CONFIG_RPXCLASSIC
+ unsigned long flags;
+#endif
+
+ if ((bus > 7) || (dev_fn > 127)) {
+ *val = 0xffff;
+ return PCIBIOS_DEVICE_NOT_FOUND;
+ }
+
+#ifdef CONFIG_RPXCLASSIC
+ /* disable interrupts */
+ spin_lock_irqsave(&pcibios_lock, flags);
+ *((uint *)RPX_CSR_ADDR) &= ~BCSR2_QSPACESEL;
+ eieio();
+#endif
+
+ if (bus == 0)
+ *QS_CONFIG_ADDR = mk_config_addr(bus, dev_fn, offset);
+ else
+ *QS_CONFIG_ADDR = mk_config_type1(bus, dev_fn, offset);
+ __get_qspan_pci_config(temp, QS_CONFIG_DATA, "lwz");
+ offset ^= 0x02;
+
+#ifdef CONFIG_RPXCLASSIC
+ *((uint *)RPX_CSR_ADDR) |= BCSR2_QSPACESEL;
+ eieio();
+ spin_unlock_irqrestore(&pcibios_lock, flags);
+#endif
+
+ sp = ((ushort *)&temp) + ((offset >> 1) & 1);
+ *val = *sp;
+ return PCIBIOS_SUCCESSFUL;
+}
+
+int qspan_pcibios_read_config_dword(unsigned char bus, unsigned char dev_fn,
+ unsigned char offset, unsigned int *val)
+{
+#ifdef CONFIG_RPXCLASSIC
+ unsigned long flags;
+#endif
+
+ if ((bus > 7) || (dev_fn > 127)) {
+ *val = 0xffffffff;
+ return PCIBIOS_DEVICE_NOT_FOUND;
+ }
+
+#ifdef CONFIG_RPXCLASSIC
+ /* disable interrupts */
+ spin_lock_irqsave(&pcibios_lock, flags);
+ *((uint *)RPX_CSR_ADDR) &= ~BCSR2_QSPACESEL;
+ eieio();
+#endif
+
+ if (bus == 0)
+ *QS_CONFIG_ADDR = mk_config_addr(bus, dev_fn, offset);
+ else
+ *QS_CONFIG_ADDR = mk_config_type1(bus, dev_fn, offset);
+ __get_qspan_pci_config(*val, QS_CONFIG_DATA, "lwz");
+
+#ifdef CONFIG_RPXCLASSIC
+ *((uint *)RPX_CSR_ADDR) |= BCSR2_QSPACESEL;
+ eieio();
+ spin_unlock_irqrestore(&pcibios_lock, flags);
+#endif
+
+ return PCIBIOS_SUCCESSFUL;
+}
+
+int qspan_pcibios_write_config_byte(unsigned char bus, unsigned char dev_fn,
+ unsigned char offset, unsigned char val)
+{
+ uint temp;
+ u_char *cp;
+#ifdef CONFIG_RPXCLASSIC
+ unsigned long flags;
+#endif
+
+ if ((bus > 7) || (dev_fn > 127))
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
+ qspan_pcibios_read_config_dword(bus, dev_fn, offset, &temp);
+
+ offset ^= 0x03;
+ cp = ((u_char *)&temp) + (offset & 0x03);
+ *cp = val;
+
+#ifdef CONFIG_RPXCLASSIC
+ /* disable interrupts */
+ spin_lock_irqsave(&pcibios_lock, flags);
+ *((uint *)RPX_CSR_ADDR) &= ~BCSR2_QSPACESEL;
+ eieio();
+#endif
+
+ if (bus == 0)
+ *QS_CONFIG_ADDR = mk_config_addr(bus, dev_fn, offset);
+ else
+ *QS_CONFIG_ADDR = mk_config_type1(bus, dev_fn, offset);
+ *QS_CONFIG_DATA = temp;
+
+#ifdef CONFIG_RPXCLASSIC
+ *((uint *)RPX_CSR_ADDR) |= BCSR2_QSPACESEL;
+ eieio();
+ spin_unlock_irqrestore(&pcibios_lock, flags);
+#endif
+
+ return PCIBIOS_SUCCESSFUL;
+}
+
+int qspan_pcibios_write_config_word(unsigned char bus, unsigned char dev_fn,
+ unsigned char offset, unsigned short val)
+{
+ uint temp;
+ ushort *sp;
+#ifdef CONFIG_RPXCLASSIC
+ unsigned long flags;
+#endif
+
+ if ((bus > 7) || (dev_fn > 127))
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
+ qspan_pcibios_read_config_dword(bus, dev_fn, offset, &temp);
+
+ offset ^= 0x02;
+ sp = ((ushort *)&temp) + ((offset >> 1) & 1);
+ *sp = val;
+
+#ifdef CONFIG_RPXCLASSIC
+ /* disable interrupts */
+ spin_lock_irqsave(&pcibios_lock, flags);
+ *((uint *)RPX_CSR_ADDR) &= ~BCSR2_QSPACESEL;
+ eieio();
+#endif
+
+ if (bus == 0)
+ *QS_CONFIG_ADDR = mk_config_addr(bus, dev_fn, offset);
+ else
+ *QS_CONFIG_ADDR = mk_config_type1(bus, dev_fn, offset);
+ *QS_CONFIG_DATA = temp;
+
+#ifdef CONFIG_RPXCLASSIC
+ *((uint *)RPX_CSR_ADDR) |= BCSR2_QSPACESEL;
+ eieio();
+ spin_unlock_irqrestore(&pcibios_lock, flags);
+#endif
+
+ return PCIBIOS_SUCCESSFUL;
+}
+
+int qspan_pcibios_write_config_dword(unsigned char bus, unsigned char dev_fn,
+ unsigned char offset, unsigned int val)
+{
+#ifdef CONFIG_RPXCLASSIC
+ unsigned long flags;
+#endif
+
+ if ((bus > 7) || (dev_fn > 127))
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
+#ifdef CONFIG_RPXCLASSIC
+ /* disable interrupts */
+ spin_lock_irqsave(&pcibios_lock, flags);
+ *((uint *)RPX_CSR_ADDR) &= ~BCSR2_QSPACESEL;
+ eieio();
+#endif
+
+ if (bus == 0)
+ *QS_CONFIG_ADDR = mk_config_addr(bus, dev_fn, offset);
+ else
+ *QS_CONFIG_ADDR = mk_config_type1(bus, dev_fn, offset);
+ *(unsigned int *)QS_CONFIG_DATA = val;
+
+#ifdef CONFIG_RPXCLASSIC
+ *((uint *)RPX_CSR_ADDR) |= BCSR2_QSPACESEL;
+ eieio();
+ spin_unlock_irqrestore(&pcibios_lock, flags);
+#endif
+
+ return PCIBIOS_SUCCESSFUL;
+}
+
+int qspan_pcibios_find_device(unsigned short vendor, unsigned short dev_id,
+ unsigned short index, unsigned char *bus_ptr,
+ unsigned char *dev_fn_ptr)
+{
+ int num, devfn;
+ unsigned int x, vendev;
+
+ if (vendor == 0xffff)
+ return PCIBIOS_BAD_VENDOR_ID;
+ vendev = (dev_id << 16) + vendor;
+ num = 0;
+ for (devfn = 0; devfn < 32; devfn++) {
+ qspan_pcibios_read_config_dword(0, devfn<<3, PCI_VENDOR_ID, &x);
+ if (x == vendev) {
+ if (index == num) {
+ *bus_ptr = 0;
+ *dev_fn_ptr = devfn<<3;
+ return PCIBIOS_SUCCESSFUL;
+ }
+ ++num;
+ }
+ }
+ return PCIBIOS_DEVICE_NOT_FOUND;
+}
+
+int qspan_pcibios_find_class(unsigned int class_code, unsigned short index,
+ unsigned char *bus_ptr, unsigned char *dev_fn_ptr)
+{
+ int devnr, x, num;
+
+ num = 0;
+ for (devnr = 0; devnr < 32; devnr++) {
+ qspan_pcibios_read_config_dword(0, devnr<<3, PCI_CLASS_REVISION, &x);
+ if ((x>>8) == class_code) {
+ if (index == num) {
+ *bus_ptr = 0;
+ *dev_fn_ptr = devnr<<3;
+ return PCIBIOS_SUCCESSFUL;
+ }
+ ++num;
+ }
+ }
+ return PCIBIOS_DEVICE_NOT_FOUND;
+}
+
+void __init
+m8xx_pcibios_fixup(void))
+{
+ /* Lots to do here, all board and configuration specific. */
+}
+
+void __init
+m8xx_setup_pci_ptrs(void))
+{
+ set_config_access_method(qspan);
+
+ ppc_md.pcibios_fixup = m8xx_pcibios_fixup;
+}
+
diff --git a/arch/ppc/syslib/todc_time.c b/arch/ppc/syslib/todc_time.c
new file mode 100644
index 0000000..1323c64
--- /dev/null
+++ b/arch/ppc/syslib/todc_time.c
@@ -0,0 +1,513 @@
+/*
+ * arch/ppc/syslib/todc_time.c
+ *
+ * Time of Day Clock support for the M48T35, M48T37, M48T59, and MC146818
+ * Real Time Clocks/Timekeepers.
+ *
+ * Author: Mark A. Greer
+ * mgreer@mvista.com
+ *
+ * 2001-2004 (c) MontaVista, Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/time.h>
+#include <linux/timex.h>
+#include <linux/bcd.h>
+#include <linux/mc146818rtc.h>
+
+#include <asm/machdep.h>
+#include <asm/io.h>
+#include <asm/time.h>
+#include <asm/todc.h>
+
+/*
+ * Depending on the hardware on your board and your board design, the
+ * RTC/NVRAM may be accessed either directly (like normal memory) or via
+ * address/data registers. If your board uses the direct method, set
+ * 'nvram_data' to the base address of your nvram and leave 'nvram_as0' and
+ * 'nvram_as1' NULL. If your board uses address/data regs to access nvram,
+ * set 'nvram_as0' to the address of the lower byte, set 'nvram_as1' to the
+ * address of the upper byte (leave NULL if using mc146818), and set
+ * 'nvram_data' to the address of the 8-bit data register.
+ *
+ * In order to break the assumption that the RTC and NVRAM are accessed by
+ * the same mechanism, you need to explicitly set 'ppc_md.rtc_read_val' and
+ * 'ppc_md.rtc_write_val', otherwise the values of 'ppc_md.rtc_read_val'
+ * and 'ppc_md.rtc_write_val' will be used.
+ *
+ * Note: Even though the documentation for the various RTC chips say that it
+ * take up to a second before it starts updating once the 'R' bit is
+ * cleared, they always seem to update even though we bang on it many
+ * times a second. This is true, except for the Dallas Semi 1746/1747
+ * (possibly others). Those chips seem to have a real problem whenever
+ * we set the 'R' bit before reading them, they basically stop counting.
+ * --MAG
+ */
+
+/*
+ * 'todc_info' should be initialized in your *_setup.c file to
+ * point to a fully initialized 'todc_info_t' structure.
+ * This structure holds all the register offsets for your particular
+ * TODC/RTC chip.
+ * TODC_ALLOC()/TODC_INIT() will allocate and initialize this table for you.
+ */
+
+#ifdef RTC_FREQ_SELECT
+#undef RTC_FREQ_SELECT
+#define RTC_FREQ_SELECT control_b /* Register A */
+#endif
+
+#ifdef RTC_CONTROL
+#undef RTC_CONTROL
+#define RTC_CONTROL control_a /* Register B */
+#endif
+
+#ifdef RTC_INTR_FLAGS
+#undef RTC_INTR_FLAGS
+#define RTC_INTR_FLAGS watchdog /* Register C */
+#endif
+
+#ifdef RTC_VALID
+#undef RTC_VALID
+#define RTC_VALID interrupts /* Register D */
+#endif
+
+/* Access routines when RTC accessed directly (like normal memory) */
+u_char
+todc_direct_read_val(int addr)
+{
+ return readb((void __iomem *)(todc_info->nvram_data + addr));
+}
+
+void
+todc_direct_write_val(int addr, unsigned char val)
+{
+ writeb(val, (void __iomem *)(todc_info->nvram_data + addr));
+ return;
+}
+
+/* Access routines for accessing m48txx type chips via addr/data regs */
+u_char
+todc_m48txx_read_val(int addr)
+{
+ outb(addr, todc_info->nvram_as0);
+ outb(addr>>todc_info->as0_bits, todc_info->nvram_as1);
+ return inb(todc_info->nvram_data);
+}
+
+void
+todc_m48txx_write_val(int addr, unsigned char val)
+{
+ outb(addr, todc_info->nvram_as0);
+ outb(addr>>todc_info->as0_bits, todc_info->nvram_as1);
+ outb(val, todc_info->nvram_data);
+ return;
+}
+
+/* Access routines for accessing mc146818 type chips via addr/data regs */
+u_char
+todc_mc146818_read_val(int addr)
+{
+ outb_p(addr, todc_info->nvram_as0);
+ return inb_p(todc_info->nvram_data);
+}
+
+void
+todc_mc146818_write_val(int addr, unsigned char val)
+{
+ outb_p(addr, todc_info->nvram_as0);
+ outb_p(val, todc_info->nvram_data);
+}
+
+
+/*
+ * Routines to make RTC chips with NVRAM buried behind an addr/data pair
+ * have the NVRAM and clock regs appear at the same level.
+ * The NVRAM will appear to start at addr 0 and the clock regs will appear
+ * to start immediately after the NVRAM (actually, start at offset
+ * todc_info->nvram_size).
+ */
+static inline u_char
+todc_read_val(int addr)
+{
+ u_char val;
+
+ if (todc_info->sw_flags & TODC_FLAG_2_LEVEL_NVRAM) {
+ if (addr < todc_info->nvram_size) { /* NVRAM */
+ ppc_md.rtc_write_val(todc_info->nvram_addr_reg, addr);
+ val = ppc_md.rtc_read_val(todc_info->nvram_data_reg);
+ }
+ else { /* Clock Reg */
+ addr -= todc_info->nvram_size;
+ val = ppc_md.rtc_read_val(addr);
+ }
+ }
+ else {
+ val = ppc_md.rtc_read_val(addr);
+ }
+
+ return val;
+}
+
+static inline void
+todc_write_val(int addr, u_char val)
+{
+ if (todc_info->sw_flags & TODC_FLAG_2_LEVEL_NVRAM) {
+ if (addr < todc_info->nvram_size) { /* NVRAM */
+ ppc_md.rtc_write_val(todc_info->nvram_addr_reg, addr);
+ ppc_md.rtc_write_val(todc_info->nvram_data_reg, val);
+ }
+ else { /* Clock Reg */
+ addr -= todc_info->nvram_size;
+ ppc_md.rtc_write_val(addr, val);
+ }
+ }
+ else {
+ ppc_md.rtc_write_val(addr, val);
+ }
+}
+
+/*
+ * TODC routines
+ *
+ * There is some ugly stuff in that there are assumptions for the mc146818.
+ *
+ * Assumptions:
+ * - todc_info->control_a has the offset as mc146818 Register B reg
+ * - todc_info->control_b has the offset as mc146818 Register A reg
+ * - m48txx control reg's write enable or 'W' bit is same as
+ * mc146818 Register B 'SET' bit (i.e., 0x80)
+ *
+ * These assumptions were made to make the code simpler.
+ */
+long __init
+todc_time_init(void)
+{
+ u_char cntl_b;
+
+ if (!ppc_md.rtc_read_val)
+ ppc_md.rtc_read_val = ppc_md.nvram_read_val;
+ if (!ppc_md.rtc_write_val)
+ ppc_md.rtc_write_val = ppc_md.nvram_write_val;
+
+ cntl_b = todc_read_val(todc_info->control_b);
+
+ if (todc_info->rtc_type == TODC_TYPE_MC146818) {
+ if ((cntl_b & 0x70) != 0x20) {
+ printk(KERN_INFO "TODC %s %s\n",
+ "real-time-clock was stopped.",
+ "Now starting...");
+ cntl_b &= ~0x70;
+ cntl_b |= 0x20;
+ }
+
+ todc_write_val(todc_info->control_b, cntl_b);
+ } else if (todc_info->rtc_type == TODC_TYPE_DS17285) {
+ u_char mode;
+
+ mode = todc_read_val(TODC_TYPE_DS17285_CNTL_A);
+ /* Make sure countdown clear is not set */
+ mode &= ~0x40;
+ /* Enable oscillator, extended register set */
+ mode |= 0x30;
+ todc_write_val(TODC_TYPE_DS17285_CNTL_A, mode);
+
+ } else if (todc_info->rtc_type == TODC_TYPE_DS1501) {
+ u_char month;
+
+ todc_info->enable_read = TODC_DS1501_CNTL_B_TE;
+ todc_info->enable_write = TODC_DS1501_CNTL_B_TE;
+
+ month = todc_read_val(todc_info->month);
+
+ if ((month & 0x80) == 0x80) {
+ printk(KERN_INFO "TODC %s %s\n",
+ "real-time-clock was stopped.",
+ "Now starting...");
+ month &= ~0x80;
+ todc_write_val(todc_info->month, month);
+ }
+
+ cntl_b &= ~TODC_DS1501_CNTL_B_TE;
+ todc_write_val(todc_info->control_b, cntl_b);
+ } else { /* must be a m48txx type */
+ u_char cntl_a;
+
+ todc_info->enable_read = TODC_MK48TXX_CNTL_A_R;
+ todc_info->enable_write = TODC_MK48TXX_CNTL_A_W;
+
+ cntl_a = todc_read_val(todc_info->control_a);
+
+ /* Check & clear STOP bit in control B register */
+ if (cntl_b & TODC_MK48TXX_DAY_CB) {
+ printk(KERN_INFO "TODC %s %s\n",
+ "real-time-clock was stopped.",
+ "Now starting...");
+
+ cntl_a |= todc_info->enable_write;
+ cntl_b &= ~TODC_MK48TXX_DAY_CB;/* Start Oscil */
+
+ todc_write_val(todc_info->control_a, cntl_a);
+ todc_write_val(todc_info->control_b, cntl_b);
+ }
+
+ /* Make sure READ & WRITE bits are cleared. */
+ cntl_a &= ~(todc_info->enable_write |
+ todc_info->enable_read);
+ todc_write_val(todc_info->control_a, cntl_a);
+ }
+
+ return 0;
+}
+
+/*
+ * There is some ugly stuff in that there are assumptions that for a mc146818,
+ * the todc_info->control_a has the offset of the mc146818 Register B reg and
+ * that the register'ss 'SET' bit is the same as the m48txx's write enable
+ * bit in the control register of the m48txx (i.e., 0x80).
+ *
+ * It was done to make the code look simpler.
+ */
+ulong
+todc_get_rtc_time(void)
+{
+ uint year = 0, mon = 0, day = 0, hour = 0, min = 0, sec = 0;
+ uint limit, i;
+ u_char save_control, uip = 0;
+
+ spin_lock(&rtc_lock);
+ save_control = todc_read_val(todc_info->control_a);
+
+ if (todc_info->rtc_type != TODC_TYPE_MC146818) {
+ limit = 1;
+
+ switch (todc_info->rtc_type) {
+ case TODC_TYPE_DS1553:
+ case TODC_TYPE_DS1557:
+ case TODC_TYPE_DS1743:
+ case TODC_TYPE_DS1746: /* XXXX BAD HACK -> FIX */
+ case TODC_TYPE_DS1747:
+ case TODC_TYPE_DS17285:
+ break;
+ default:
+ todc_write_val(todc_info->control_a,
+ (save_control | todc_info->enable_read));
+ }
+ }
+ else {
+ limit = 100000000;
+ }
+
+ for (i=0; i<limit; i++) {
+ if (todc_info->rtc_type == TODC_TYPE_MC146818) {
+ uip = todc_read_val(todc_info->RTC_FREQ_SELECT);
+ }
+
+ sec = todc_read_val(todc_info->seconds) & 0x7f;
+ min = todc_read_val(todc_info->minutes) & 0x7f;
+ hour = todc_read_val(todc_info->hours) & 0x3f;
+ day = todc_read_val(todc_info->day_of_month) & 0x3f;
+ mon = todc_read_val(todc_info->month) & 0x1f;
+ year = todc_read_val(todc_info->year) & 0xff;
+
+ if (todc_info->rtc_type == TODC_TYPE_MC146818) {
+ uip |= todc_read_val(todc_info->RTC_FREQ_SELECT);
+ if ((uip & RTC_UIP) == 0) break;
+ }
+ }
+
+ if (todc_info->rtc_type != TODC_TYPE_MC146818) {
+ switch (todc_info->rtc_type) {
+ case TODC_TYPE_DS1553:
+ case TODC_TYPE_DS1557:
+ case TODC_TYPE_DS1743:
+ case TODC_TYPE_DS1746: /* XXXX BAD HACK -> FIX */
+ case TODC_TYPE_DS1747:
+ case TODC_TYPE_DS17285:
+ break;
+ default:
+ save_control &= ~(todc_info->enable_read);
+ todc_write_val(todc_info->control_a,
+ save_control);
+ }
+ }
+ spin_unlock(&rtc_lock);
+
+ if ((todc_info->rtc_type != TODC_TYPE_MC146818) ||
+ ((save_control & RTC_DM_BINARY) == 0) ||
+ RTC_ALWAYS_BCD) {
+
+ BCD_TO_BIN(sec);
+ BCD_TO_BIN(min);
+ BCD_TO_BIN(hour);
+ BCD_TO_BIN(day);
+ BCD_TO_BIN(mon);
+ BCD_TO_BIN(year);
+ }
+
+ year = year + 1900;
+ if (year < 1970) {
+ year += 100;
+ }
+
+ return mktime(year, mon, day, hour, min, sec);
+}
+
+int
+todc_set_rtc_time(unsigned long nowtime)
+{
+ struct rtc_time tm;
+ u_char save_control, save_freq_select = 0;
+
+ spin_lock(&rtc_lock);
+ to_tm(nowtime, &tm);
+
+ save_control = todc_read_val(todc_info->control_a);
+
+ /* Assuming MK48T59_RTC_CA_WRITE & RTC_SET are equal */
+ todc_write_val(todc_info->control_a,
+ (save_control | todc_info->enable_write));
+ save_control &= ~(todc_info->enable_write); /* in case it was set */
+
+ if (todc_info->rtc_type == TODC_TYPE_MC146818) {
+ save_freq_select = todc_read_val(todc_info->RTC_FREQ_SELECT);
+ todc_write_val(todc_info->RTC_FREQ_SELECT,
+ save_freq_select | RTC_DIV_RESET2);
+ }
+
+
+ tm.tm_year = (tm.tm_year - 1900) % 100;
+
+ if ((todc_info->rtc_type != TODC_TYPE_MC146818) ||
+ ((save_control & RTC_DM_BINARY) == 0) ||
+ RTC_ALWAYS_BCD) {
+
+ BIN_TO_BCD(tm.tm_sec);
+ BIN_TO_BCD(tm.tm_min);
+ BIN_TO_BCD(tm.tm_hour);
+ BIN_TO_BCD(tm.tm_mon);
+ BIN_TO_BCD(tm.tm_mday);
+ BIN_TO_BCD(tm.tm_year);
+ }
+
+ todc_write_val(todc_info->seconds, tm.tm_sec);
+ todc_write_val(todc_info->minutes, tm.tm_min);
+ todc_write_val(todc_info->hours, tm.tm_hour);
+ todc_write_val(todc_info->month, tm.tm_mon);
+ todc_write_val(todc_info->day_of_month, tm.tm_mday);
+ todc_write_val(todc_info->year, tm.tm_year);
+
+ todc_write_val(todc_info->control_a, save_control);
+
+ if (todc_info->rtc_type == TODC_TYPE_MC146818) {
+ todc_write_val(todc_info->RTC_FREQ_SELECT, save_freq_select);
+ }
+ spin_unlock(&rtc_lock);
+
+ return 0;
+}
+
+/*
+ * Manipulates read bit to reliably read seconds at a high rate.
+ */
+static unsigned char __init todc_read_timereg(int addr)
+{
+ unsigned char save_control = 0, val;
+
+ switch (todc_info->rtc_type) {
+ case TODC_TYPE_DS1553:
+ case TODC_TYPE_DS1557:
+ case TODC_TYPE_DS1746: /* XXXX BAD HACK -> FIX */
+ case TODC_TYPE_DS1747:
+ case TODC_TYPE_DS17285:
+ case TODC_TYPE_MC146818:
+ break;
+ default:
+ save_control = todc_read_val(todc_info->control_a);
+ todc_write_val(todc_info->control_a,
+ (save_control | todc_info->enable_read));
+ }
+ val = todc_read_val(addr);
+
+ switch (todc_info->rtc_type) {
+ case TODC_TYPE_DS1553:
+ case TODC_TYPE_DS1557:
+ case TODC_TYPE_DS1746: /* XXXX BAD HACK -> FIX */
+ case TODC_TYPE_DS1747:
+ case TODC_TYPE_DS17285:
+ case TODC_TYPE_MC146818:
+ break;
+ default:
+ save_control &= ~(todc_info->enable_read);
+ todc_write_val(todc_info->control_a, save_control);
+ }
+
+ return val;
+}
+
+/*
+ * This was taken from prep_setup.c
+ * Use the NVRAM RTC to time a second to calibrate the decrementer.
+ */
+void __init
+todc_calibrate_decr(void)
+{
+ ulong freq;
+ ulong tbl, tbu;
+ long i, loop_count;
+ u_char sec;
+
+ todc_time_init();
+
+ /*
+ * Actually this is bad for precision, we should have a loop in
+ * which we only read the seconds counter. todc_read_val writes
+ * the address bytes on every call and this takes a lot of time.
+ * Perhaps an nvram_wait_change method returning a time
+ * stamp with a loop count as parameter would be the solution.
+ */
+ /*
+ * Need to make sure the tbl doesn't roll over so if tbu increments
+ * during this test, we need to do it again.
+ */
+ loop_count = 0;
+
+ sec = todc_read_timereg(todc_info->seconds) & 0x7f;
+
+ do {
+ tbu = get_tbu();
+
+ for (i = 0 ; i < 10000000 ; i++) {/* may take up to 1 second */
+ tbl = get_tbl();
+
+ if ((todc_read_timereg(todc_info->seconds) & 0x7f) != sec) {
+ break;
+ }
+ }
+
+ sec = todc_read_timereg(todc_info->seconds) & 0x7f;
+
+ for (i = 0 ; i < 10000000 ; i++) { /* Should take 1 second */
+ freq = get_tbl();
+
+ if ((todc_read_timereg(todc_info->seconds) & 0x7f) != sec) {
+ break;
+ }
+ }
+
+ freq -= tbl;
+ } while ((get_tbu() != tbu) && (++loop_count < 2));
+
+ printk("time_init: decrementer frequency = %lu.%.6lu MHz\n",
+ freq/1000000, freq%1000000);
+
+ tb_ticks_per_jiffy = freq / HZ;
+ tb_to_us = mulhwu_scale_factor(freq, 1000000);
+
+ return;
+}
diff --git a/arch/ppc/syslib/xilinx_pic.c b/arch/ppc/syslib/xilinx_pic.c
new file mode 100644
index 0000000..e0bd66f
--- /dev/null
+++ b/arch/ppc/syslib/xilinx_pic.c
@@ -0,0 +1,157 @@
+/*
+ * arch/ppc/syslib/xilinx_pic.c
+ *
+ * Interrupt controller driver for Xilinx Virtex-II Pro.
+ *
+ * Author: MontaVista Software, Inc.
+ * source@mvista.com
+ *
+ * 2002-2004 (c) MontaVista Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+
+#include <linux/init.h>
+#include <linux/irq.h>
+#include <asm/io.h>
+#include <asm/xparameters.h>
+#include <asm/ibm4xx.h>
+
+/* No one else should require these constants, so define them locally here. */
+#define ISR 0 /* Interrupt Status Register */
+#define IPR 1 /* Interrupt Pending Register */
+#define IER 2 /* Interrupt Enable Register */
+#define IAR 3 /* Interrupt Acknowledge Register */
+#define SIE 4 /* Set Interrupt Enable bits */
+#define CIE 5 /* Clear Interrupt Enable bits */
+#define IVR 6 /* Interrupt Vector Register */
+#define MER 7 /* Master Enable Register */
+
+#if XPAR_XINTC_USE_DCR == 0
+static volatile u32 *intc;
+#define intc_out_be32(addr, mask) out_be32((addr), (mask))
+#define intc_in_be32(addr) in_be32((addr))
+#else
+#define intc XPAR_INTC_0_BASEADDR
+#define intc_out_be32(addr, mask) mtdcr((addr), (mask))
+#define intc_in_be32(addr) mfdcr((addr))
+#endif
+
+static void
+xilinx_intc_enable(unsigned int irq)
+{
+ unsigned long mask = (0x00000001 << (irq & 31));
+ pr_debug("enable: %d\n", irq);
+ intc_out_be32(intc + SIE, mask);
+}
+
+static void
+xilinx_intc_disable(unsigned int irq)
+{
+ unsigned long mask = (0x00000001 << (irq & 31));
+ pr_debug("disable: %d\n", irq);
+ intc_out_be32(intc + CIE, mask);
+}
+
+static void
+xilinx_intc_disable_and_ack(unsigned int irq)
+{
+ unsigned long mask = (0x00000001 << (irq & 31));
+ pr_debug("disable_and_ack: %d\n", irq);
+ intc_out_be32(intc + CIE, mask);
+ if (!(irq_desc[irq].status & IRQ_LEVEL))
+ intc_out_be32(intc + IAR, mask); /* ack edge triggered intr */
+}
+
+static void
+xilinx_intc_end(unsigned int irq)
+{
+ unsigned long mask = (0x00000001 << (irq & 31));
+
+ pr_debug("end: %d\n", irq);
+ if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) {
+ intc_out_be32(intc + SIE, mask);
+ /* ack level sensitive intr */
+ if (irq_desc[irq].status & IRQ_LEVEL)
+ intc_out_be32(intc + IAR, mask);
+ }
+}
+
+static struct hw_interrupt_type xilinx_intc = {
+ "Xilinx Interrupt Controller",
+ NULL,
+ NULL,
+ xilinx_intc_enable,
+ xilinx_intc_disable,
+ xilinx_intc_disable_and_ack,
+ xilinx_intc_end,
+ 0
+};
+
+int
+xilinx_pic_get_irq(struct pt_regs *regs)
+{
+ int irq;
+
+ /*
+ * NOTE: This function is the one that needs to be improved in
+ * order to handle multiple interrupt controllers. It currently
+ * is hardcoded to check for interrupts only on the first INTC.
+ */
+
+ irq = intc_in_be32(intc + IVR);
+ if (irq != -1)
+ irq = irq;
+
+ pr_debug("get_irq: %d\n", irq);
+
+ return (irq);
+}
+
+void __init
+ppc4xx_pic_init(void)
+{
+ int i;
+
+ /*
+ * NOTE: The assumption here is that NR_IRQS is 32 or less
+ * (NR_IRQS is 32 for PowerPC 405 cores by default).
+ */
+#if (NR_IRQS > 32)
+#error NR_IRQS > 32 not supported
+#endif
+
+#if XPAR_XINTC_USE_DCR == 0
+ intc = ioremap(XPAR_INTC_0_BASEADDR, 32);
+
+ printk(KERN_INFO "Xilinx INTC #0 at 0x%08lX mapped to 0x%08lX\n",
+ (unsigned long) XPAR_INTC_0_BASEADDR, (unsigned long) intc);
+#else
+ printk(KERN_INFO "Xilinx INTC #0 at 0x%08lX (DCR)\n",
+ (unsigned long) XPAR_INTC_0_BASEADDR);
+#endif
+
+ /*
+ * Disable all external interrupts until they are
+ * explicity requested.
+ */
+ intc_out_be32(intc + IER, 0);
+
+ /* Acknowledge any pending interrupts just in case. */
+ intc_out_be32(intc + IAR, ~(u32) 0);
+
+ /* Turn on the Master Enable. */
+ intc_out_be32(intc + MER, 0x3UL);
+
+ ppc_md.get_irq = xilinx_pic_get_irq;
+
+ for (i = 0; i < NR_IRQS; ++i) {
+ irq_desc[i].handler = &xilinx_intc;
+
+ if (XPAR_INTC_0_KIND_OF_INTR & (0x00000001 << i))
+ irq_desc[i].status &= ~IRQ_LEVEL;
+ else
+ irq_desc[i].status |= IRQ_LEVEL;
+ }
+}
diff --git a/arch/ppc/xmon/Makefile b/arch/ppc/xmon/Makefile
new file mode 100644
index 0000000..9aa260b
--- /dev/null
+++ b/arch/ppc/xmon/Makefile
@@ -0,0 +1,8 @@
+# Makefile for xmon
+
+ifdef CONFIG_8xx
+obj-y := start_8xx.o
+else
+obj-y := start.o
+endif
+obj-y += xmon.o ppc-dis.o ppc-opc.o subr_prf.o setjmp.o
diff --git a/arch/ppc/xmon/adb.c b/arch/ppc/xmon/adb.c
new file mode 100644
index 0000000..e91384d
--- /dev/null
+++ b/arch/ppc/xmon/adb.c
@@ -0,0 +1,212 @@
+/*
+ * Copyright (C) 1996 Paul Mackerras.
+ */
+#include "nonstdio.h"
+#include "privinst.h"
+
+#define scanhex xmon_scanhex
+#define skipbl xmon_skipbl
+
+#define ADB_B (*(volatile unsigned char *)0xf3016000)
+#define ADB_SR (*(volatile unsigned char *)0xf3017400)
+#define ADB_ACR (*(volatile unsigned char *)0xf3017600)
+#define ADB_IFR (*(volatile unsigned char *)0xf3017a00)
+
+static inline void eieio(void) { asm volatile ("eieio" : :); }
+
+#define N_ADB_LOG 1000
+struct adb_log {
+ unsigned char b;
+ unsigned char ifr;
+ unsigned char acr;
+ unsigned int time;
+} adb_log[N_ADB_LOG];
+int n_adb_log;
+
+void
+init_adb_log(void)
+{
+ adb_log[0].b = ADB_B;
+ adb_log[0].ifr = ADB_IFR;
+ adb_log[0].acr = ADB_ACR;
+ adb_log[0].time = get_dec();
+ n_adb_log = 0;
+}
+
+void
+dump_adb_log(void)
+{
+ unsigned t, t0;
+ struct adb_log *ap;
+ int i;
+
+ ap = adb_log;
+ t0 = ap->time;
+ for (i = 0; i <= n_adb_log; ++i, ++ap) {
+ t = t0 - ap->time;
+ printf("b=%x ifr=%x acr=%x at %d.%.7d\n", ap->b, ap->ifr, ap->acr,
+ t / 1000000000, (t % 1000000000) / 100);
+ }
+}
+
+void
+adb_chklog(void)
+{
+ struct adb_log *ap = &adb_log[n_adb_log + 1];
+
+ ap->b = ADB_B;
+ ap->ifr = ADB_IFR;
+ ap->acr = ADB_ACR;
+ if (ap->b != ap[-1].b || (ap->ifr & 4) != (ap[-1].ifr & 4)
+ || ap->acr != ap[-1].acr) {
+ ap->time = get_dec();
+ ++n_adb_log;
+ }
+}
+
+int
+adb_bitwait(int bmask, int bval, int fmask, int fval)
+{
+ int i;
+ struct adb_log *ap;
+
+ for (i = 10000; i > 0; --i) {
+ adb_chklog();
+ ap = &adb_log[n_adb_log];
+ if ((ap->b & bmask) == bval && (ap->ifr & fmask) == fval)
+ return 0;
+ }
+ return -1;
+}
+
+int
+adb_wait(void)
+{
+ if (adb_bitwait(0, 0, 4, 4) < 0) {
+ printf("adb: ready wait timeout\n");
+ return -1;
+ }
+ return 0;
+}
+
+void
+adb_readin(void)
+{
+ int i, j;
+ unsigned char d[64];
+
+ if (ADB_B & 8) {
+ printf("ADB_B: %x\n", ADB_B);
+ return;
+ }
+ i = 0;
+ adb_wait();
+ j = ADB_SR;
+ eieio();
+ ADB_B &= ~0x20;
+ eieio();
+ for (;;) {
+ if (adb_wait() < 0)
+ break;
+ d[i++] = ADB_SR;
+ eieio();
+ if (ADB_B & 8)
+ break;
+ ADB_B ^= 0x10;
+ eieio();
+ }
+ ADB_B |= 0x30;
+ if (adb_wait() == 0)
+ j = ADB_SR;
+ for (j = 0; j < i; ++j)
+ printf("%.2x ", d[j]);
+ printf("\n");
+}
+
+int
+adb_write(unsigned char *d, int i)
+{
+ int j;
+ unsigned x;
+
+ if ((ADB_B & 8) == 0) {
+ printf("r: ");
+ adb_readin();
+ }
+ for (;;) {
+ ADB_ACR = 0x1c;
+ eieio();
+ ADB_SR = d[0];
+ eieio();
+ ADB_B &= ~0x20;
+ eieio();
+ if (ADB_B & 8)
+ break;
+ ADB_ACR = 0xc;
+ eieio();
+ ADB_B |= 0x20;
+ eieio();
+ adb_readin();
+ }
+ adb_wait();
+ for (j = 1; j < i; ++j) {
+ ADB_SR = d[j];
+ eieio();
+ ADB_B ^= 0x10;
+ eieio();
+ if (adb_wait() < 0)
+ break;
+ }
+ ADB_ACR = 0xc;
+ eieio();
+ x = ADB_SR;
+ eieio();
+ ADB_B |= 0x30;
+ return j;
+}
+
+void
+adbcmds(void)
+{
+ char cmd;
+ unsigned rtcu, rtcl, dec, pdec, x;
+ int i, j;
+ unsigned char d[64];
+
+ cmd = skipbl();
+ switch (cmd) {
+ case 't':
+ for (;;) {
+ rtcl = get_rtcl();
+ rtcu = get_rtcu();
+ dec = get_dec();
+ printf("rtc u=%u l=%u dec=%x (%d = %d.%.7d)\n",
+ rtcu, rtcl, dec, pdec - dec, (pdec - dec) / 1000000000,
+ ((pdec - dec) % 1000000000) / 100);
+ pdec = dec;
+ if (cmd == 'x')
+ break;
+ while (xmon_read(stdin, &cmd, 1) != 1)
+ ;
+ }
+ break;
+ case 'r':
+ init_adb_log();
+ while (adb_bitwait(8, 0, 0, 0) == 0)
+ adb_readin();
+ break;
+ case 'w':
+ i = 0;
+ while (scanhex(&x))
+ d[i++] = x;
+ init_adb_log();
+ j = adb_write(d, i);
+ printf("sent %d bytes\n", j);
+ while (adb_bitwait(8, 0, 0, 0) == 0)
+ adb_readin();
+ break;
+ case 'l':
+ dump_adb_log();
+ break;
+ }
+}
diff --git a/arch/ppc/xmon/ansidecl.h b/arch/ppc/xmon/ansidecl.h
new file mode 100644
index 0000000..c9b9f09
--- /dev/null
+++ b/arch/ppc/xmon/ansidecl.h
@@ -0,0 +1,141 @@
+/* ANSI and traditional C compatibility macros
+ Copyright 1991, 1992 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+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. */
+
+/* ANSI and traditional C compatibility macros
+
+ ANSI C is assumed if __STDC__ is #defined.
+
+ Macro ANSI C definition Traditional C definition
+ ----- ---- - ---------- ----------- - ----------
+ PTR `void *' `char *'
+ LONG_DOUBLE `long double' `double'
+ VOLATILE `volatile' `'
+ SIGNED `signed' `'
+ PTRCONST `void *const' `char *'
+ ANSI_PROTOTYPES 1 not defined
+
+ CONST is also defined, but is obsolete. Just use const.
+
+ DEFUN (name, arglist, args)
+
+ Defines function NAME.
+
+ ARGLIST lists the arguments, separated by commas and enclosed in
+ parentheses. ARGLIST becomes the argument list in traditional C.
+
+ ARGS list the arguments with their types. It becomes a prototype in
+ ANSI C, and the type declarations in traditional C. Arguments should
+ be separated with `AND'. For functions with a variable number of
+ arguments, the last thing listed should be `DOTS'.
+
+ DEFUN_VOID (name)
+
+ Defines a function NAME, which takes no arguments.
+
+ obsolete -- EXFUN (name, (prototype)) -- obsolete.
+
+ Replaced by PARAMS. Do not use; will disappear someday soon.
+ Was used in external function declarations.
+ In ANSI C it is `NAME PROTOTYPE' (so PROTOTYPE should be enclosed in
+ parentheses). In traditional C it is `NAME()'.
+ For a function that takes no arguments, PROTOTYPE should be `(void)'.
+
+ PARAMS ((args))
+
+ We could use the EXFUN macro to handle prototype declarations, but
+ the name is misleading and the result is ugly. So we just define a
+ simple macro to handle the parameter lists, as in:
+
+ static int foo PARAMS ((int, char));
+
+ This produces: `static int foo();' or `static int foo (int, char);'
+
+ EXFUN would have done it like this:
+
+ static int EXFUN (foo, (int, char));
+
+ but the function is not external...and it's hard to visually parse
+ the function name out of the mess. EXFUN should be considered
+ obsolete; new code should be written to use PARAMS.
+
+ For example:
+ extern int printf PARAMS ((CONST char *format DOTS));
+ int DEFUN(fprintf, (stream, format),
+ FILE *stream AND CONST char *format DOTS) { ... }
+ void DEFUN_VOID(abort) { ... }
+*/
+
+#ifndef _ANSIDECL_H
+
+#define _ANSIDECL_H 1
+
+
+/* Every source file includes this file,
+ so they will all get the switch for lint. */
+/* LINTLIBRARY */
+
+
+#if defined (__STDC__) || defined (_AIX) || (defined (__mips) && defined (_SYSTYPE_SVR4)) || defined(WIN32)
+/* All known AIX compilers implement these things (but don't always
+ define __STDC__). The RISC/OS MIPS compiler defines these things
+ in SVR4 mode, but does not define __STDC__. */
+
+#define PTR void *
+#define PTRCONST void *CONST
+#define LONG_DOUBLE long double
+
+#define AND ,
+#define NOARGS void
+#define CONST const
+#define VOLATILE volatile
+#define SIGNED signed
+#define DOTS , ...
+
+#define EXFUN(name, proto) name proto
+#define DEFUN(name, arglist, args) name(args)
+#define DEFUN_VOID(name) name(void)
+
+#define PROTO(type, name, arglist) type name arglist
+#define PARAMS(paramlist) paramlist
+#define ANSI_PROTOTYPES 1
+
+#else /* Not ANSI C. */
+
+#define PTR char *
+#define PTRCONST PTR
+#define LONG_DOUBLE double
+
+#define AND ;
+#define NOARGS
+#define CONST
+#ifndef const /* some systems define it in header files for non-ansi mode */
+#define const
+#endif
+#define VOLATILE
+#define SIGNED
+#define DOTS
+
+#define EXFUN(name, proto) name()
+#define DEFUN(name, arglist, args) name arglist args;
+#define DEFUN_VOID(name) name()
+#define PROTO(type, name, arglist) type name ()
+#define PARAMS(paramlist) ()
+
+#endif /* ANSI C. */
+
+#endif /* ansidecl.h */
diff --git a/arch/ppc/xmon/nonstdio.h b/arch/ppc/xmon/nonstdio.h
new file mode 100644
index 0000000..0240bc5
--- /dev/null
+++ b/arch/ppc/xmon/nonstdio.h
@@ -0,0 +1,22 @@
+typedef int FILE;
+extern FILE *xmon_stdin, *xmon_stdout;
+#define EOF (-1)
+#define stdin xmon_stdin
+#define stdout xmon_stdout
+#define printf xmon_printf
+#define fprintf xmon_fprintf
+#define fputs xmon_fputs
+#define fgets xmon_fgets
+#define putchar xmon_putchar
+#define getchar xmon_getchar
+#define putc xmon_putc
+#define getc xmon_getc
+#define fopen(n, m) NULL
+#define fflush(f) do {} while (0)
+#define fclose(f) do {} while (0)
+extern char *fgets(char *, int, void *);
+extern void xmon_fprintf(void *, const char *, ...);
+extern void xmon_sprintf(char *, const char *, ...);
+extern void xmon_puts(char*);
+
+#define perror(s) printf("%s: no files!\n", (s))
diff --git a/arch/ppc/xmon/ppc-dis.c b/arch/ppc/xmon/ppc-dis.c
new file mode 100644
index 0000000..798ac1a
--- /dev/null
+++ b/arch/ppc/xmon/ppc-dis.c
@@ -0,0 +1,190 @@
+/* ppc-dis.c -- Disassemble PowerPC instructions
+ Copyright 1994 Free Software Foundation, Inc.
+ Written by Ian Lance Taylor, Cygnus Support
+
+This file is part of GDB, GAS, and the GNU binutils.
+
+GDB, GAS, and the GNU binutils are free software; you can redistribute
+them and/or modify them under the terms of the GNU General Public
+License as published by the Free Software Foundation; either version
+2, or (at your option) any later version.
+
+GDB, GAS, and the GNU binutils are distributed in the hope that they
+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 file; see the file COPYING. If not, write to the Free
+Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "nonstdio.h"
+#include "ansidecl.h"
+#include "ppc.h"
+
+static int print_insn_powerpc PARAMS ((FILE *, unsigned long insn,
+ unsigned memaddr, int dialect));
+
+extern void print_address PARAMS((unsigned memaddr));
+
+/* Print a big endian PowerPC instruction. For convenience, also
+ disassemble instructions supported by the Motorola PowerPC 601. */
+
+int
+print_insn_big_powerpc (FILE *out, unsigned long insn, unsigned memaddr)
+{
+ return print_insn_powerpc (out, insn, memaddr,
+ PPC_OPCODE_PPC | PPC_OPCODE_601);
+}
+
+/* Print a PowerPC or POWER instruction. */
+
+static int
+print_insn_powerpc (FILE *out, unsigned long insn, unsigned memaddr,
+ int dialect)
+{
+ const struct powerpc_opcode *opcode;
+ const struct powerpc_opcode *opcode_end;
+ unsigned long op;
+
+ /* Get the major opcode of the instruction. */
+ op = PPC_OP (insn);
+
+ /* Find the first match in the opcode table. We could speed this up
+ a bit by doing a binary search on the major opcode. */
+ opcode_end = powerpc_opcodes + powerpc_num_opcodes;
+ for (opcode = powerpc_opcodes; opcode < opcode_end; opcode++)
+ {
+ unsigned long table_op;
+ const unsigned char *opindex;
+ const struct powerpc_operand *operand;
+ int invalid;
+ int need_comma;
+ int need_paren;
+
+ table_op = PPC_OP (opcode->opcode);
+ if (op < table_op)
+ break;
+ if (op > table_op)
+ continue;
+
+ if ((insn & opcode->mask) != opcode->opcode
+ || (opcode->flags & dialect) == 0)
+ continue;
+
+ /* Make two passes over the operands. First see if any of them
+ have extraction functions, and, if they do, make sure the
+ instruction is valid. */
+ invalid = 0;
+ for (opindex = opcode->operands; *opindex != 0; opindex++)
+ {
+ operand = powerpc_operands + *opindex;
+ if (operand->extract)
+ (*operand->extract) (insn, &invalid);
+ }
+ if (invalid)
+ continue;
+
+ /* The instruction is valid. */
+ fprintf(out, "%s", opcode->name);
+ if (opcode->operands[0] != 0)
+ fprintf(out, "\t");
+
+ /* Now extract and print the operands. */
+ need_comma = 0;
+ need_paren = 0;
+ for (opindex = opcode->operands; *opindex != 0; opindex++)
+ {
+ long value;
+
+ operand = powerpc_operands + *opindex;
+
+ /* Operands that are marked FAKE are simply ignored. We
+ already made sure that the extract function considered
+ the instruction to be valid. */
+ if ((operand->flags & PPC_OPERAND_FAKE) != 0)
+ continue;
+
+ /* Extract the value from the instruction. */
+ if (operand->extract)
+ value = (*operand->extract) (insn, (int *) 0);
+ else
+ {
+ value = (insn >> operand->shift) & ((1 << operand->bits) - 1);
+ if ((operand->flags & PPC_OPERAND_SIGNED) != 0
+ && (value & (1 << (operand->bits - 1))) != 0)
+ value -= 1 << operand->bits;
+ }
+
+ /* If the operand is optional, and the value is zero, don't
+ print anything. */
+ if ((operand->flags & PPC_OPERAND_OPTIONAL) != 0
+ && (operand->flags & PPC_OPERAND_NEXT) == 0
+ && value == 0)
+ continue;
+
+ if (need_comma)
+ {
+ fprintf(out, ",");
+ need_comma = 0;
+ }
+
+ /* Print the operand as directed by the flags. */
+ if ((operand->flags & PPC_OPERAND_GPR) != 0)
+ fprintf(out, "r%ld", value);
+ else if ((operand->flags & PPC_OPERAND_FPR) != 0)
+ fprintf(out, "f%ld", value);
+ else if ((operand->flags & PPC_OPERAND_RELATIVE) != 0)
+ print_address (memaddr + value);
+ else if ((operand->flags & PPC_OPERAND_ABSOLUTE) != 0)
+ print_address (value & 0xffffffff);
+ else if ((operand->flags & PPC_OPERAND_CR) == 0
+ || (dialect & PPC_OPCODE_PPC) == 0)
+ fprintf(out, "%ld", value);
+ else
+ {
+ if (operand->bits == 3)
+ fprintf(out, "cr%d", value);
+ else
+ {
+ static const char *cbnames[4] = { "lt", "gt", "eq", "so" };
+ int cr;
+ int cc;
+
+ cr = value >> 2;
+ if (cr != 0)
+ fprintf(out, "4*cr%d", cr);
+ cc = value & 3;
+ if (cc != 0)
+ {
+ if (cr != 0)
+ fprintf(out, "+");
+ fprintf(out, "%s", cbnames[cc]);
+ }
+ }
+ }
+
+ if (need_paren)
+ {
+ fprintf(out, ")");
+ need_paren = 0;
+ }
+
+ if ((operand->flags & PPC_OPERAND_PARENS) == 0)
+ need_comma = 1;
+ else
+ {
+ fprintf(out, "(");
+ need_paren = 1;
+ }
+ }
+
+ /* We have found and printed an instruction; return. */
+ return 4;
+ }
+
+ /* We could not find a match. */
+ fprintf(out, ".long 0x%lx", insn);
+
+ return 4;
+}
diff --git a/arch/ppc/xmon/ppc-opc.c b/arch/ppc/xmon/ppc-opc.c
new file mode 100644
index 0000000..533a6c9
--- /dev/null
+++ b/arch/ppc/xmon/ppc-opc.c
@@ -0,0 +1,2721 @@
+/* ppc-opc.c -- PowerPC opcode list
+ Copyright 1994 Free Software Foundation, Inc.
+ Written by Ian Lance Taylor, Cygnus Support
+
+This file is part of GDB, GAS, and the GNU binutils.
+
+GDB, GAS, and the GNU binutils are free software; you can redistribute
+them and/or modify them under the terms of the GNU General Public
+License as published by the Free Software Foundation; either version
+2, or (at your option) any later version.
+
+GDB, GAS, and the GNU binutils are distributed in the hope that they
+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 file; see the file COPYING. If not, write to the Free
+Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include <linux/posix_types.h>
+#include "ansidecl.h"
+#include "ppc.h"
+
+/* This file holds the PowerPC opcode table. The opcode table
+ includes almost all of the extended instruction mnemonics. This
+ permits the disassembler to use them, and simplifies the assembler
+ logic, at the cost of increasing the table size. The table is
+ strictly constant data, so the compiler should be able to put it in
+ the .text section.
+
+ This file also holds the operand table. All knowledge about
+ inserting operands into instructions and vice-versa is kept in this
+ file. */
+
+/* Local insertion and extraction functions. */
+
+static unsigned long insert_bat PARAMS ((unsigned long, long, const char **));
+static long extract_bat PARAMS ((unsigned long, int *));
+static unsigned long insert_bba PARAMS ((unsigned long, long, const char **));
+static long extract_bba PARAMS ((unsigned long, int *));
+static unsigned long insert_bd PARAMS ((unsigned long, long, const char **));
+static long extract_bd PARAMS ((unsigned long, int *));
+static unsigned long insert_bdm PARAMS ((unsigned long, long, const char **));
+static long extract_bdm PARAMS ((unsigned long, int *));
+static unsigned long insert_bdp PARAMS ((unsigned long, long, const char **));
+static long extract_bdp PARAMS ((unsigned long, int *));
+static unsigned long insert_bo PARAMS ((unsigned long, long, const char **));
+static long extract_bo PARAMS ((unsigned long, int *));
+static unsigned long insert_boe PARAMS ((unsigned long, long, const char **));
+static long extract_boe PARAMS ((unsigned long, int *));
+static unsigned long insert_ds PARAMS ((unsigned long, long, const char **));
+static long extract_ds PARAMS ((unsigned long, int *));
+static unsigned long insert_li PARAMS ((unsigned long, long, const char **));
+static long extract_li PARAMS ((unsigned long, int *));
+static unsigned long insert_mbe PARAMS ((unsigned long, long, const char **));
+static long extract_mbe PARAMS ((unsigned long, int *));
+static unsigned long insert_mb6 PARAMS ((unsigned long, long, const char **));
+static long extract_mb6 PARAMS ((unsigned long, int *));
+static unsigned long insert_nb PARAMS ((unsigned long, long, const char **));
+static long extract_nb PARAMS ((unsigned long, int *));
+static unsigned long insert_nsi PARAMS ((unsigned long, long, const char **));
+static long extract_nsi PARAMS ((unsigned long, int *));
+static unsigned long insert_ral PARAMS ((unsigned long, long, const char **));
+static unsigned long insert_ram PARAMS ((unsigned long, long, const char **));
+static unsigned long insert_ras PARAMS ((unsigned long, long, const char **));
+static unsigned long insert_rbs PARAMS ((unsigned long, long, const char **));
+static long extract_rbs PARAMS ((unsigned long, int *));
+static unsigned long insert_sh6 PARAMS ((unsigned long, long, const char **));
+static long extract_sh6 PARAMS ((unsigned long, int *));
+static unsigned long insert_spr PARAMS ((unsigned long, long, const char **));
+static long extract_spr PARAMS ((unsigned long, int *));
+static unsigned long insert_tbr PARAMS ((unsigned long, long, const char **));
+static long extract_tbr PARAMS ((unsigned long, int *));
+
+/* The operands table.
+
+ The fields are bits, shift, signed, insert, extract, flags. */
+
+const struct powerpc_operand powerpc_operands[] =
+{
+ /* The zero index is used to indicate the end of the list of
+ operands. */
+#define UNUSED (0)
+ { 0, 0, NULL, NULL, 0 },
+
+ /* The BA field in an XL form instruction. */
+#define BA (1)
+#define BA_MASK (0x1f << 16)
+ { 5, 16, NULL, NULL, PPC_OPERAND_CR },
+
+ /* The BA field in an XL form instruction when it must be the same
+ as the BT field in the same instruction. */
+#define BAT (2)
+ { 5, 16, insert_bat, extract_bat, PPC_OPERAND_FAKE },
+
+ /* The BB field in an XL form instruction. */
+#define BB (3)
+#define BB_MASK (0x1f << 11)
+ { 5, 11, NULL, NULL, PPC_OPERAND_CR },
+
+ /* The BB field in an XL form instruction when it must be the same
+ as the BA field in the same instruction. */
+#define BBA (4)
+ { 5, 11, insert_bba, extract_bba, PPC_OPERAND_FAKE },
+
+ /* The BD field in a B form instruction. The lower two bits are
+ forced to zero. */
+#define BD (5)
+ { 16, 0, insert_bd, extract_bd, PPC_OPERAND_RELATIVE | PPC_OPERAND_SIGNED },
+
+ /* The BD field in a B form instruction when absolute addressing is
+ used. */
+#define BDA (6)
+ { 16, 0, insert_bd, extract_bd, PPC_OPERAND_ABSOLUTE | PPC_OPERAND_SIGNED },
+
+ /* The BD field in a B form instruction when the - modifier is used.
+ This sets the y bit of the BO field appropriately. */
+#define BDM (7)
+ { 16, 0, insert_bdm, extract_bdm,
+ PPC_OPERAND_RELATIVE | PPC_OPERAND_SIGNED },
+
+ /* The BD field in a B form instruction when the - modifier is used
+ and absolute address is used. */
+#define BDMA (8)
+ { 16, 0, insert_bdm, extract_bdm,
+ PPC_OPERAND_ABSOLUTE | PPC_OPERAND_SIGNED },
+
+ /* The BD field in a B form instruction when the + modifier is used.
+ This sets the y bit of the BO field appropriately. */
+#define BDP (9)
+ { 16, 0, insert_bdp, extract_bdp,
+ PPC_OPERAND_RELATIVE | PPC_OPERAND_SIGNED },
+
+ /* The BD field in a B form instruction when the + modifier is used
+ and absolute addressing is used. */
+#define BDPA (10)
+ { 16, 0, insert_bdp, extract_bdp,
+ PPC_OPERAND_ABSOLUTE | PPC_OPERAND_SIGNED },
+
+ /* The BF field in an X or XL form instruction. */
+#define BF (11)
+ { 3, 23, NULL, NULL, PPC_OPERAND_CR },
+
+ /* An optional BF field. This is used for comparison instructions,
+ in which an omitted BF field is taken as zero. */
+#define OBF (12)
+ { 3, 23, NULL, NULL, PPC_OPERAND_CR | PPC_OPERAND_OPTIONAL },
+
+ /* The BFA field in an X or XL form instruction. */
+#define BFA (13)
+ { 3, 18, NULL, NULL, PPC_OPERAND_CR },
+
+ /* The BI field in a B form or XL form instruction. */
+#define BI (14)
+#define BI_MASK (0x1f << 16)
+ { 5, 16, NULL, NULL, PPC_OPERAND_CR },
+
+ /* The BO field in a B form instruction. Certain values are
+ illegal. */
+#define BO (15)
+#define BO_MASK (0x1f << 21)
+ { 5, 21, insert_bo, extract_bo, 0 },
+
+ /* The BO field in a B form instruction when the + or - modifier is
+ used. This is like the BO field, but it must be even. */
+#define BOE (16)
+ { 5, 21, insert_boe, extract_boe, 0 },
+
+ /* The BT field in an X or XL form instruction. */
+#define BT (17)
+ { 5, 21, NULL, NULL, PPC_OPERAND_CR },
+
+ /* The condition register number portion of the BI field in a B form
+ or XL form instruction. This is used for the extended
+ conditional branch mnemonics, which set the lower two bits of the
+ BI field. This field is optional. */
+#define CR (18)
+ { 3, 18, NULL, NULL, PPC_OPERAND_CR | PPC_OPERAND_OPTIONAL },
+
+ /* The D field in a D form instruction. This is a displacement off
+ a register, and implies that the next operand is a register in
+ parentheses. */
+#define D (19)
+ { 16, 0, NULL, NULL, PPC_OPERAND_PARENS | PPC_OPERAND_SIGNED },
+
+ /* The DS field in a DS form instruction. This is like D, but the
+ lower two bits are forced to zero. */
+#define DS (20)
+ { 16, 0, insert_ds, extract_ds, PPC_OPERAND_PARENS | PPC_OPERAND_SIGNED },
+
+ /* The FL1 field in a POWER SC form instruction. */
+#define FL1 (21)
+ { 4, 12, NULL, NULL, 0 },
+
+ /* The FL2 field in a POWER SC form instruction. */
+#define FL2 (22)
+ { 3, 2, NULL, NULL, 0 },
+
+ /* The FLM field in an XFL form instruction. */
+#define FLM (23)
+ { 8, 17, NULL, NULL, 0 },
+
+ /* The FRA field in an X or A form instruction. */
+#define FRA (24)
+#define FRA_MASK (0x1f << 16)
+ { 5, 16, NULL, NULL, PPC_OPERAND_FPR },
+
+ /* The FRB field in an X or A form instruction. */
+#define FRB (25)
+#define FRB_MASK (0x1f << 11)
+ { 5, 11, NULL, NULL, PPC_OPERAND_FPR },
+
+ /* The FRC field in an A form instruction. */
+#define FRC (26)
+#define FRC_MASK (0x1f << 6)
+ { 5, 6, NULL, NULL, PPC_OPERAND_FPR },
+
+ /* The FRS field in an X form instruction or the FRT field in a D, X
+ or A form instruction. */
+#define FRS (27)
+#define FRT (FRS)
+ { 5, 21, NULL, NULL, PPC_OPERAND_FPR },
+
+ /* The FXM field in an XFX instruction. */
+#define FXM (28)
+#define FXM_MASK (0xff << 12)
+ { 8, 12, NULL, NULL, 0 },
+
+ /* The L field in a D or X form instruction. */
+#define L (29)
+ { 1, 21, NULL, NULL, PPC_OPERAND_OPTIONAL },
+
+ /* The LEV field in a POWER SC form instruction. */
+#define LEV (30)
+ { 7, 5, NULL, NULL, 0 },
+
+ /* The LI field in an I form instruction. The lower two bits are
+ forced to zero. */
+#define LI (31)
+ { 26, 0, insert_li, extract_li, PPC_OPERAND_RELATIVE | PPC_OPERAND_SIGNED },
+
+ /* The LI field in an I form instruction when used as an absolute
+ address. */
+#define LIA (32)
+ { 26, 0, insert_li, extract_li, PPC_OPERAND_ABSOLUTE | PPC_OPERAND_SIGNED },
+
+ /* The MB field in an M form instruction. */
+#define MB (33)
+#define MB_MASK (0x1f << 6)
+ { 5, 6, NULL, NULL, 0 },
+
+ /* The ME field in an M form instruction. */
+#define ME (34)
+#define ME_MASK (0x1f << 1)
+ { 5, 1, NULL, NULL, 0 },
+
+ /* The MB and ME fields in an M form instruction expressed a single
+ operand which is a bitmask indicating which bits to select. This
+ is a two operand form using PPC_OPERAND_NEXT. See the
+ description in opcode/ppc.h for what this means. */
+#define MBE (35)
+ { 5, 6, NULL, NULL, PPC_OPERAND_OPTIONAL | PPC_OPERAND_NEXT },
+ { 32, 0, insert_mbe, extract_mbe, 0 },
+
+ /* The MB or ME field in an MD or MDS form instruction. The high
+ bit is wrapped to the low end. */
+#define MB6 (37)
+#define ME6 (MB6)
+#define MB6_MASK (0x3f << 5)
+ { 6, 5, insert_mb6, extract_mb6, 0 },
+
+ /* The NB field in an X form instruction. The value 32 is stored as
+ 0. */
+#define NB (38)
+ { 6, 11, insert_nb, extract_nb, 0 },
+
+ /* The NSI field in a D form instruction. This is the same as the
+ SI field, only negated. */
+#define NSI (39)
+ { 16, 0, insert_nsi, extract_nsi,
+ PPC_OPERAND_NEGATIVE | PPC_OPERAND_SIGNED },
+
+ /* The RA field in an D, DS, X, XO, M, or MDS form instruction. */
+#define RA (40)
+#define RA_MASK (0x1f << 16)
+ { 5, 16, NULL, NULL, PPC_OPERAND_GPR },
+
+ /* The RA field in a D or X form instruction which is an updating
+ load, which means that the RA field may not be zero and may not
+ equal the RT field. */
+#define RAL (41)
+ { 5, 16, insert_ral, NULL, PPC_OPERAND_GPR },
+
+ /* The RA field in an lmw instruction, which has special value
+ restrictions. */
+#define RAM (42)
+ { 5, 16, insert_ram, NULL, PPC_OPERAND_GPR },
+
+ /* The RA field in a D or X form instruction which is an updating
+ store or an updating floating point load, which means that the RA
+ field may not be zero. */
+#define RAS (43)
+ { 5, 16, insert_ras, NULL, PPC_OPERAND_GPR },
+
+ /* The RB field in an X, XO, M, or MDS form instruction. */
+#define RB (44)
+#define RB_MASK (0x1f << 11)
+ { 5, 11, NULL, NULL, PPC_OPERAND_GPR },
+
+ /* The RB field in an X form instruction when it must be the same as
+ the RS field in the instruction. This is used for extended
+ mnemonics like mr. */
+#define RBS (45)
+ { 5, 1, insert_rbs, extract_rbs, PPC_OPERAND_FAKE },
+
+ /* The RS field in a D, DS, X, XFX, XS, M, MD or MDS form
+ instruction or the RT field in a D, DS, X, XFX or XO form
+ instruction. */
+#define RS (46)
+#define RT (RS)
+#define RT_MASK (0x1f << 21)
+ { 5, 21, NULL, NULL, PPC_OPERAND_GPR },
+
+ /* The SH field in an X or M form instruction. */
+#define SH (47)
+#define SH_MASK (0x1f << 11)
+ { 5, 11, NULL, NULL, 0 },
+
+ /* The SH field in an MD form instruction. This is split. */
+#define SH6 (48)
+#define SH6_MASK ((0x1f << 11) | (1 << 1))
+ { 6, 1, insert_sh6, extract_sh6, 0 },
+
+ /* The SI field in a D form instruction. */
+#define SI (49)
+ { 16, 0, NULL, NULL, PPC_OPERAND_SIGNED },
+
+ /* The SI field in a D form instruction when we accept a wide range
+ of positive values. */
+#define SISIGNOPT (50)
+ { 16, 0, NULL, NULL, PPC_OPERAND_SIGNED | PPC_OPERAND_SIGNOPT },
+
+ /* The SPR field in an XFX form instruction. This is flipped--the
+ lower 5 bits are stored in the upper 5 and vice- versa. */
+#define SPR (51)
+#define SPR_MASK (0x3ff << 11)
+ { 10, 11, insert_spr, extract_spr, 0 },
+
+ /* The BAT index number in an XFX form m[ft]ibat[lu] instruction. */
+#define SPRBAT (52)
+#define SPRBAT_MASK (0x3 << 17)
+ { 2, 17, NULL, NULL, 0 },
+
+ /* The SPRG register number in an XFX form m[ft]sprg instruction. */
+#define SPRG (53)
+#define SPRG_MASK (0x3 << 16)
+ { 2, 16, NULL, NULL, 0 },
+
+ /* The SR field in an X form instruction. */
+#define SR (54)
+ { 4, 16, NULL, NULL, 0 },
+
+ /* The SV field in a POWER SC form instruction. */
+#define SV (55)
+ { 14, 2, NULL, NULL, 0 },
+
+ /* The TBR field in an XFX form instruction. This is like the SPR
+ field, but it is optional. */
+#define TBR (56)
+ { 10, 11, insert_tbr, extract_tbr, PPC_OPERAND_OPTIONAL },
+
+ /* The TO field in a D or X form instruction. */
+#define TO (57)
+#define TO_MASK (0x1f << 21)
+ { 5, 21, NULL, NULL, 0 },
+
+ /* The U field in an X form instruction. */
+#define U (58)
+ { 4, 12, NULL, NULL, 0 },
+
+ /* The UI field in a D form instruction. */
+#define UI (59)
+ { 16, 0, NULL, NULL, 0 },
+};
+
+/* The functions used to insert and extract complicated operands. */
+
+/* The BA field in an XL form instruction when it must be the same as
+ the BT field in the same instruction. This operand is marked FAKE.
+ The insertion function just copies the BT field into the BA field,
+ and the extraction function just checks that the fields are the
+ same. */
+
+/*ARGSUSED*/
+static unsigned long
+insert_bat(unsigned long insn, long value, const char **errmsg)
+{
+ return insn | (((insn >> 21) & 0x1f) << 16);
+}
+
+static long
+extract_bat(unsigned long insn, int *invalid)
+{
+ if (invalid != (int *) NULL
+ && ((insn >> 21) & 0x1f) != ((insn >> 16) & 0x1f))
+ *invalid = 1;
+ return 0;
+}
+
+/* The BB field in an XL form instruction when it must be the same as
+ the BA field in the same instruction. This operand is marked FAKE.
+ The insertion function just copies the BA field into the BB field,
+ and the extraction function just checks that the fields are the
+ same. */
+
+/*ARGSUSED*/
+static unsigned long
+insert_bba(unsigned long insn, long value, const char **errmsg)
+{
+ return insn | (((insn >> 16) & 0x1f) << 11);
+}
+
+static long
+extract_bba(unsigned long insn, int *invalid)
+{
+ if (invalid != (int *) NULL
+ && ((insn >> 16) & 0x1f) != ((insn >> 11) & 0x1f))
+ *invalid = 1;
+ return 0;
+}
+
+/* The BD field in a B form instruction. The lower two bits are
+ forced to zero. */
+
+/*ARGSUSED*/
+static unsigned long
+insert_bd(unsigned long insn, long value, const char **errmsg)
+{
+ return insn | (value & 0xfffc);
+}
+
+/*ARGSUSED*/
+static long
+extract_bd(unsigned long insn, int *invalid)
+{
+ if ((insn & 0x8000) != 0)
+ return (insn & 0xfffc) - 0x10000;
+ else
+ return insn & 0xfffc;
+}
+
+/* The BD field in a B form instruction when the - modifier is used.
+ This modifier means that the branch is not expected to be taken.
+ We must set the y bit of the BO field to 1 if the offset is
+ negative. When extracting, we require that the y bit be 1 and that
+ the offset be positive, since if the y bit is 0 we just want to
+ print the normal form of the instruction. */
+
+/*ARGSUSED*/
+static unsigned long
+insert_bdm(unsigned long insn, long value, const char **errmsg)
+{
+ if ((value & 0x8000) != 0)
+ insn |= 1 << 21;
+ return insn | (value & 0xfffc);
+}
+
+static long
+extract_bdm(unsigned long insn, int *invalid)
+{
+ if (invalid != (int *) NULL
+ && ((insn & (1 << 21)) == 0
+ || (insn & (1 << 15)) == 0))
+ *invalid = 1;
+ if ((insn & 0x8000) != 0)
+ return (insn & 0xfffc) - 0x10000;
+ else
+ return insn & 0xfffc;
+}
+
+/* The BD field in a B form instruction when the + modifier is used.
+ This is like BDM, above, except that the branch is expected to be
+ taken. */
+
+/*ARGSUSED*/
+static unsigned long
+insert_bdp(unsigned long insn, long value, const char **errmsg)
+{
+ if ((value & 0x8000) == 0)
+ insn |= 1 << 21;
+ return insn | (value & 0xfffc);
+}
+
+static long
+extract_bdp(unsigned long insn, int *invalid)
+{
+ if (invalid != (int *) NULL
+ && ((insn & (1 << 21)) == 0
+ || (insn & (1 << 15)) != 0))
+ *invalid = 1;
+ if ((insn & 0x8000) != 0)
+ return (insn & 0xfffc) - 0x10000;
+ else
+ return insn & 0xfffc;
+}
+
+/* Check for legal values of a BO field. */
+
+static int
+valid_bo (long value)
+{
+ /* Certain encodings have bits that are required to be zero. These
+ are (z must be zero, y may be anything):
+ 001zy
+ 011zy
+ 1z00y
+ 1z01y
+ 1z1zz
+ */
+ switch (value & 0x14)
+ {
+ default:
+ case 0:
+ return 1;
+ case 0x4:
+ return (value & 0x2) == 0;
+ case 0x10:
+ return (value & 0x8) == 0;
+ case 0x14:
+ return value == 0x14;
+ }
+}
+
+/* The BO field in a B form instruction. Warn about attempts to set
+ the field to an illegal value. */
+
+static unsigned long
+insert_bo(unsigned long insn, long value, const char **errmsg)
+{
+ if (errmsg != (const char **) NULL
+ && ! valid_bo (value))
+ *errmsg = "invalid conditional option";
+ return insn | ((value & 0x1f) << 21);
+}
+
+static long
+extract_bo(unsigned long insn, int *invalid)
+{
+ long value;
+
+ value = (insn >> 21) & 0x1f;
+ if (invalid != (int *) NULL
+ && ! valid_bo (value))
+ *invalid = 1;
+ return value;
+}
+
+/* The BO field in a B form instruction when the + or - modifier is
+ used. This is like the BO field, but it must be even. When
+ extracting it, we force it to be even. */
+
+static unsigned long
+insert_boe(unsigned long insn, long value, const char **errmsg)
+{
+ if (errmsg != (const char **) NULL)
+ {
+ if (! valid_bo (value))
+ *errmsg = "invalid conditional option";
+ else if ((value & 1) != 0)
+ *errmsg = "attempt to set y bit when using + or - modifier";
+ }
+ return insn | ((value & 0x1f) << 21);
+}
+
+static long
+extract_boe(unsigned long insn, int *invalid)
+{
+ long value;
+
+ value = (insn >> 21) & 0x1f;
+ if (invalid != (int *) NULL
+ && ! valid_bo (value))
+ *invalid = 1;
+ return value & 0x1e;
+}
+
+/* The DS field in a DS form instruction. This is like D, but the
+ lower two bits are forced to zero. */
+
+/*ARGSUSED*/
+static unsigned long
+insert_ds(unsigned long insn, long value, const char **errmsg)
+{
+ return insn | (value & 0xfffc);
+}
+
+/*ARGSUSED*/
+static long
+extract_ds(unsigned long insn, int *invalid)
+{
+ if ((insn & 0x8000) != 0)
+ return (insn & 0xfffc) - 0x10000;
+ else
+ return insn & 0xfffc;
+}
+
+/* The LI field in an I form instruction. The lower two bits are
+ forced to zero. */
+
+/*ARGSUSED*/
+static unsigned long
+insert_li(unsigned long insn, long value, const char **errmsg)
+{
+ return insn | (value & 0x3fffffc);
+}
+
+/*ARGSUSED*/
+static long
+extract_li(unsigned long insn, int *invalid)
+{
+ if ((insn & 0x2000000) != 0)
+ return (insn & 0x3fffffc) - 0x4000000;
+ else
+ return insn & 0x3fffffc;
+}
+
+/* The MB and ME fields in an M form instruction expressed as a single
+ operand which is itself a bitmask. The extraction function always
+ marks it as invalid, since we never want to recognize an
+ instruction which uses a field of this type. */
+
+static unsigned long
+insert_mbe(unsigned long insn, long value, const char **errmsg)
+{
+ unsigned long uval;
+ int mb, me;
+
+ uval = value;
+
+ if (uval == 0)
+ {
+ if (errmsg != (const char **) NULL)
+ *errmsg = "illegal bitmask";
+ return insn;
+ }
+
+ me = 31;
+ while ((uval & 1) == 0)
+ {
+ uval >>= 1;
+ --me;
+ }
+
+ mb = me;
+ uval >>= 1;
+ while ((uval & 1) != 0)
+ {
+ uval >>= 1;
+ --mb;
+ }
+
+ if (uval != 0)
+ {
+ if (errmsg != (const char **) NULL)
+ *errmsg = "illegal bitmask";
+ }
+
+ return insn | (mb << 6) | (me << 1);
+}
+
+static long
+extract_mbe(unsigned long insn, int *invalid)
+{
+ long ret;
+ int mb, me;
+ int i;
+
+ if (invalid != (int *) NULL)
+ *invalid = 1;
+
+ ret = 0;
+ mb = (insn >> 6) & 0x1f;
+ me = (insn >> 1) & 0x1f;
+ for (i = mb; i < me; i++)
+ ret |= 1 << (31 - i);
+ return ret;
+}
+
+/* The MB or ME field in an MD or MDS form instruction. The high bit
+ is wrapped to the low end. */
+
+/*ARGSUSED*/
+static unsigned long
+insert_mb6(unsigned long insn, long value, const char **errmsg)
+{
+ return insn | ((value & 0x1f) << 6) | (value & 0x20);
+}
+
+/*ARGSUSED*/
+static long
+extract_mb6(unsigned long insn, int *invalid)
+{
+ return ((insn >> 6) & 0x1f) | (insn & 0x20);
+}
+
+/* The NB field in an X form instruction. The value 32 is stored as
+ 0. */
+
+static unsigned long
+insert_nb(unsigned long insn, long value, const char **errmsg)
+{
+ if (value < 0 || value > 32)
+ *errmsg = "value out of range";
+ if (value == 32)
+ value = 0;
+ return insn | ((value & 0x1f) << 11);
+}
+
+/*ARGSUSED*/
+static long
+extract_nb(unsigned long insn, int *invalid)
+{
+ long ret;
+
+ ret = (insn >> 11) & 0x1f;
+ if (ret == 0)
+ ret = 32;
+ return ret;
+}
+
+/* The NSI field in a D form instruction. This is the same as the SI
+ field, only negated. The extraction function always marks it as
+ invalid, since we never want to recognize an instruction which uses
+ a field of this type. */
+
+/*ARGSUSED*/
+static unsigned long
+insert_nsi(unsigned long insn, long value, const char **errmsg)
+{
+ return insn | ((- value) & 0xffff);
+}
+
+static long
+extract_nsi(unsigned long insn, int *invalid)
+{
+ if (invalid != (int *) NULL)
+ *invalid = 1;
+ if ((insn & 0x8000) != 0)
+ return - ((insn & 0xffff) - 0x10000);
+ else
+ return - (insn & 0xffff);
+}
+
+/* The RA field in a D or X form instruction which is an updating
+ load, which means that the RA field may not be zero and may not
+ equal the RT field. */
+
+static unsigned long
+insert_ral(unsigned long insn, long value, const char **errmsg)
+{
+ if (value == 0
+ || value == ((insn >> 21) & 0x1f))
+ *errmsg = "invalid register operand when updating";
+ return insn | ((value & 0x1f) << 16);
+}
+
+/* The RA field in an lmw instruction, which has special value
+ restrictions. */
+
+static unsigned long
+insert_ram(unsigned long insn, long value, const char **errmsg)
+{
+ if (value >= ((insn >> 21) & 0x1f))
+ *errmsg = "index register in load range";
+ return insn | ((value & 0x1f) << 16);
+}
+
+/* The RA field in a D or X form instruction which is an updating
+ store or an updating floating point load, which means that the RA
+ field may not be zero. */
+
+static unsigned long
+insert_ras(unsigned long insn, long value, const char **errmsg)
+{
+ if (value == 0)
+ *errmsg = "invalid register operand when updating";
+ return insn | ((value & 0x1f) << 16);
+}
+
+/* The RB field in an X form instruction when it must be the same as
+ the RS field in the instruction. This is used for extended
+ mnemonics like mr. This operand is marked FAKE. The insertion
+ function just copies the BT field into the BA field, and the
+ extraction function just checks that the fields are the same. */
+
+/*ARGSUSED*/
+static unsigned long
+insert_rbs(unsigned long insn, long value, const char **errmsg)
+{
+ return insn | (((insn >> 21) & 0x1f) << 11);
+}
+
+static long
+extract_rbs(unsigned long insn, int *invalid)
+{
+ if (invalid != (int *) NULL
+ && ((insn >> 21) & 0x1f) != ((insn >> 11) & 0x1f))
+ *invalid = 1;
+ return 0;
+}
+
+/* The SH field in an MD form instruction. This is split. */
+
+/*ARGSUSED*/
+static unsigned long
+insert_sh6(unsigned long insn, long value, const char **errmsg)
+{
+ return insn | ((value & 0x1f) << 11) | ((value & 0x20) >> 4);
+}
+
+/*ARGSUSED*/
+static long
+extract_sh6(unsigned long insn, int *invalid)
+{
+ return ((insn >> 11) & 0x1f) | ((insn << 4) & 0x20);
+}
+
+/* The SPR field in an XFX form instruction. This is flipped--the
+ lower 5 bits are stored in the upper 5 and vice- versa. */
+
+static unsigned long
+insert_spr(unsigned long insn, long value, const char **errmsg)
+{
+ return insn | ((value & 0x1f) << 16) | ((value & 0x3e0) << 6);
+}
+
+static long
+extract_spr(unsigned long insn, int *invalid)
+{
+ return ((insn >> 16) & 0x1f) | ((insn >> 6) & 0x3e0);
+}
+
+/* The TBR field in an XFX instruction. This is just like SPR, but it
+ is optional. When TBR is omitted, it must be inserted as 268 (the
+ magic number of the TB register). These functions treat 0
+ (indicating an omitted optional operand) as 268. This means that
+ ``mftb 4,0'' is not handled correctly. This does not matter very
+ much, since the architecture manual does not define mftb as
+ accepting any values other than 268 or 269. */
+
+#define TB (268)
+
+static unsigned long
+insert_tbr(unsigned long insn, long value, const char **errmsg)
+{
+ if (value == 0)
+ value = TB;
+ return insn | ((value & 0x1f) << 16) | ((value & 0x3e0) << 6);
+}
+
+static long
+extract_tbr(unsigned long insn, int *invalid)
+{
+ long ret;
+
+ ret = ((insn >> 16) & 0x1f) | ((insn >> 6) & 0x3e0);
+ if (ret == TB)
+ ret = 0;
+ return ret;
+}
+
+/* Macros used to form opcodes. */
+
+/* The main opcode. */
+#define OP(x) (((x) & 0x3f) << 26)
+#define OP_MASK OP (0x3f)
+
+/* The main opcode combined with a trap code in the TO field of a D
+ form instruction. Used for extended mnemonics for the trap
+ instructions. */
+#define OPTO(x,to) (OP (x) | (((to) & 0x1f) << 21))
+#define OPTO_MASK (OP_MASK | TO_MASK)
+
+/* The main opcode combined with a comparison size bit in the L field
+ of a D form or X form instruction. Used for extended mnemonics for
+ the comparison instructions. */
+#define OPL(x,l) (OP (x) | (((l) & 1) << 21))
+#define OPL_MASK OPL (0x3f,1)
+
+/* An A form instruction. */
+#define A(op, xop, rc) (OP (op) | (((xop) & 0x1f) << 1) | ((rc) & 1))
+#define A_MASK A (0x3f, 0x1f, 1)
+
+/* An A_MASK with the FRB field fixed. */
+#define AFRB_MASK (A_MASK | FRB_MASK)
+
+/* An A_MASK with the FRC field fixed. */
+#define AFRC_MASK (A_MASK | FRC_MASK)
+
+/* An A_MASK with the FRA and FRC fields fixed. */
+#define AFRAFRC_MASK (A_MASK | FRA_MASK | FRC_MASK)
+
+/* A B form instruction. */
+#define B(op, aa, lk) (OP (op) | (((aa) & 1) << 1) | ((lk) & 1))
+#define B_MASK B (0x3f, 1, 1)
+
+/* A B form instruction setting the BO field. */
+#define BBO(op, bo, aa, lk) (B ((op), (aa), (lk)) | (((bo) & 0x1f) << 21))
+#define BBO_MASK BBO (0x3f, 0x1f, 1, 1)
+
+/* A BBO_MASK with the y bit of the BO field removed. This permits
+ matching a conditional branch regardless of the setting of the y
+ bit. */
+#define Y_MASK (1 << 21)
+#define BBOY_MASK (BBO_MASK &~ Y_MASK)
+
+/* A B form instruction setting the BO field and the condition bits of
+ the BI field. */
+#define BBOCB(op, bo, cb, aa, lk) \
+ (BBO ((op), (bo), (aa), (lk)) | (((cb) & 0x3) << 16))
+#define BBOCB_MASK BBOCB (0x3f, 0x1f, 0x3, 1, 1)
+
+/* A BBOCB_MASK with the y bit of the BO field removed. */
+#define BBOYCB_MASK (BBOCB_MASK &~ Y_MASK)
+
+/* A BBOYCB_MASK in which the BI field is fixed. */
+#define BBOYBI_MASK (BBOYCB_MASK | BI_MASK)
+
+/* The main opcode mask with the RA field clear. */
+#define DRA_MASK (OP_MASK | RA_MASK)
+
+/* A DS form instruction. */
+#define DSO(op, xop) (OP (op) | ((xop) & 0x3))
+#define DS_MASK DSO (0x3f, 3)
+
+/* An M form instruction. */
+#define M(op, rc) (OP (op) | ((rc) & 1))
+#define M_MASK M (0x3f, 1)
+
+/* An M form instruction with the ME field specified. */
+#define MME(op, me, rc) (M ((op), (rc)) | (((me) & 0x1f) << 1))
+
+/* An M_MASK with the MB and ME fields fixed. */
+#define MMBME_MASK (M_MASK | MB_MASK | ME_MASK)
+
+/* An M_MASK with the SH and ME fields fixed. */
+#define MSHME_MASK (M_MASK | SH_MASK | ME_MASK)
+
+/* An MD form instruction. */
+#define MD(op, xop, rc) (OP (op) | (((xop) & 0x7) << 2) | ((rc) & 1))
+#define MD_MASK MD (0x3f, 0x7, 1)
+
+/* An MD_MASK with the MB field fixed. */
+#define MDMB_MASK (MD_MASK | MB6_MASK)
+
+/* An MD_MASK with the SH field fixed. */
+#define MDSH_MASK (MD_MASK | SH6_MASK)
+
+/* An MDS form instruction. */
+#define MDS(op, xop, rc) (OP (op) | (((xop) & 0xf) << 1) | ((rc) & 1))
+#define MDS_MASK MDS (0x3f, 0xf, 1)
+
+/* An MDS_MASK with the MB field fixed. */
+#define MDSMB_MASK (MDS_MASK | MB6_MASK)
+
+/* An SC form instruction. */
+#define SC(op, sa, lk) (OP (op) | (((sa) & 1) << 1) | ((lk) & 1))
+#define SC_MASK (OP_MASK | (0x3ff << 16) | (1 << 1) | 1)
+
+/* An X form instruction. */
+#define X(op, xop) (OP (op) | (((xop) & 0x3ff) << 1))
+
+/* An X form instruction with the RC bit specified. */
+#define XRC(op, xop, rc) (X ((op), (xop)) | ((rc) & 1))
+
+/* The mask for an X form instruction. */
+#define X_MASK XRC (0x3f, 0x3ff, 1)
+
+/* An X_MASK with the RA field fixed. */
+#define XRA_MASK (X_MASK | RA_MASK)
+
+/* An X_MASK with the RB field fixed. */
+#define XRB_MASK (X_MASK | RB_MASK)
+
+/* An X_MASK with the RT field fixed. */
+#define XRT_MASK (X_MASK | RT_MASK)
+
+/* An X_MASK with the RA and RB fields fixed. */
+#define XRARB_MASK (X_MASK | RA_MASK | RB_MASK)
+
+/* An X_MASK with the RT and RA fields fixed. */
+#define XRTRA_MASK (X_MASK | RT_MASK | RA_MASK)
+
+/* An X form comparison instruction. */
+#define XCMPL(op, xop, l) (X ((op), (xop)) | (((l) & 1) << 21))
+
+/* The mask for an X form comparison instruction. */
+#define XCMP_MASK (X_MASK | (1 << 22))
+
+/* The mask for an X form comparison instruction with the L field
+ fixed. */
+#define XCMPL_MASK (XCMP_MASK | (1 << 21))
+
+/* An X form trap instruction with the TO field specified. */
+#define XTO(op, xop, to) (X ((op), (xop)) | (((to) & 0x1f) << 21))
+#define XTO_MASK (X_MASK | TO_MASK)
+
+/* An XFL form instruction. */
+#define XFL(op, xop, rc) (OP (op) | (((xop) & 0x3ff) << 1) | ((rc) & 1))
+#define XFL_MASK (XFL (0x3f, 0x3ff, 1) | (1 << 25) | (1 << 16))
+
+/* An XL form instruction with the LK field set to 0. */
+#define XL(op, xop) (OP (op) | (((xop) & 0x3ff) << 1))
+
+/* An XL form instruction which uses the LK field. */
+#define XLLK(op, xop, lk) (XL ((op), (xop)) | ((lk) & 1))
+
+/* The mask for an XL form instruction. */
+#define XL_MASK XLLK (0x3f, 0x3ff, 1)
+
+/* An XL form instruction which explicitly sets the BO field. */
+#define XLO(op, bo, xop, lk) \
+ (XLLK ((op), (xop), (lk)) | (((bo) & 0x1f) << 21))
+#define XLO_MASK (XL_MASK | BO_MASK)
+
+/* An XL form instruction which explicitly sets the y bit of the BO
+ field. */
+#define XLYLK(op, xop, y, lk) (XLLK ((op), (xop), (lk)) | (((y) & 1) << 21))
+#define XLYLK_MASK (XL_MASK | Y_MASK)
+
+/* An XL form instruction which sets the BO field and the condition
+ bits of the BI field. */
+#define XLOCB(op, bo, cb, xop, lk) \
+ (XLO ((op), (bo), (xop), (lk)) | (((cb) & 3) << 16))
+#define XLOCB_MASK XLOCB (0x3f, 0x1f, 0x3, 0x3ff, 1)
+
+/* An XL_MASK or XLYLK_MASK or XLOCB_MASK with the BB field fixed. */
+#define XLBB_MASK (XL_MASK | BB_MASK)
+#define XLYBB_MASK (XLYLK_MASK | BB_MASK)
+#define XLBOCBBB_MASK (XLOCB_MASK | BB_MASK)
+
+/* An XL_MASK with the BO and BB fields fixed. */
+#define XLBOBB_MASK (XL_MASK | BO_MASK | BB_MASK)
+
+/* An XL_MASK with the BO, BI and BB fields fixed. */
+#define XLBOBIBB_MASK (XL_MASK | BO_MASK | BI_MASK | BB_MASK)
+
+/* An XO form instruction. */
+#define XO(op, xop, oe, rc) \
+ (OP (op) | (((xop) & 0x1ff) << 1) | (((oe) & 1) << 10) | ((rc) & 1))
+#define XO_MASK XO (0x3f, 0x1ff, 1, 1)
+
+/* An XO_MASK with the RB field fixed. */
+#define XORB_MASK (XO_MASK | RB_MASK)
+
+/* An XS form instruction. */
+#define XS(op, xop, rc) (OP (op) | (((xop) & 0x1ff) << 2) | ((rc) & 1))
+#define XS_MASK XS (0x3f, 0x1ff, 1)
+
+/* A mask for the FXM version of an XFX form instruction. */
+#define XFXFXM_MASK (X_MASK | (1 << 20) | (1 << 11))
+
+/* An XFX form instruction with the FXM field filled in. */
+#define XFXM(op, xop, fxm) \
+ (X ((op), (xop)) | (((fxm) & 0xff) << 12))
+
+/* An XFX form instruction with the SPR field filled in. */
+#define XSPR(op, xop, spr) \
+ (X ((op), (xop)) | (((spr) & 0x1f) << 16) | (((spr) & 0x3e0) << 6))
+#define XSPR_MASK (X_MASK | SPR_MASK)
+
+/* An XFX form instruction with the SPR field filled in except for the
+ SPRBAT field. */
+#define XSPRBAT_MASK (XSPR_MASK &~ SPRBAT_MASK)
+
+/* An XFX form instruction with the SPR field filled in except for the
+ SPRG field. */
+#define XSPRG_MASK (XSPR_MASK &~ SPRG_MASK)
+
+/* The BO encodings used in extended conditional branch mnemonics. */
+#define BODNZF (0x0)
+#define BODNZFP (0x1)
+#define BODZF (0x2)
+#define BODZFP (0x3)
+#define BOF (0x4)
+#define BOFP (0x5)
+#define BODNZT (0x8)
+#define BODNZTP (0x9)
+#define BODZT (0xa)
+#define BODZTP (0xb)
+#define BOT (0xc)
+#define BOTP (0xd)
+#define BODNZ (0x10)
+#define BODNZP (0x11)
+#define BODZ (0x12)
+#define BODZP (0x13)
+#define BOU (0x14)
+
+/* The BI condition bit encodings used in extended conditional branch
+ mnemonics. */
+#define CBLT (0)
+#define CBGT (1)
+#define CBEQ (2)
+#define CBSO (3)
+
+/* The TO encodings used in extended trap mnemonics. */
+#define TOLGT (0x1)
+#define TOLLT (0x2)
+#define TOEQ (0x4)
+#define TOLGE (0x5)
+#define TOLNL (0x5)
+#define TOLLE (0x6)
+#define TOLNG (0x6)
+#define TOGT (0x8)
+#define TOGE (0xc)
+#define TONL (0xc)
+#define TOLT (0x10)
+#define TOLE (0x14)
+#define TONG (0x14)
+#define TONE (0x18)
+#define TOU (0x1f)
+
+/* Smaller names for the flags so each entry in the opcodes table will
+ fit on a single line. */
+#undef PPC
+#define PPC PPC_OPCODE_PPC
+#define POWER PPC_OPCODE_POWER
+#define POWER2 PPC_OPCODE_POWER2
+#define B32 PPC_OPCODE_32
+#define B64 PPC_OPCODE_64
+#define M601 PPC_OPCODE_601
+
+/* The opcode table.
+
+ The format of the opcode table is:
+
+ NAME OPCODE MASK FLAGS { OPERANDS }
+
+ NAME is the name of the instruction.
+ OPCODE is the instruction opcode.
+ MASK is the opcode mask; this is used to tell the disassembler
+ which bits in the actual opcode must match OPCODE.
+ FLAGS are flags indicated what processors support the instruction.
+ OPERANDS is the list of operands.
+
+ The disassembler reads the table in order and prints the first
+ instruction which matches, so this table is sorted to put more
+ specific instructions before more general instructions. It is also
+ sorted by major opcode. */
+
+const struct powerpc_opcode powerpc_opcodes[] = {
+{ "tdlgti", OPTO(2,TOLGT), OPTO_MASK, PPC|B64, { RA, SI } },
+{ "tdllti", OPTO(2,TOLLT), OPTO_MASK, PPC|B64, { RA, SI } },
+{ "tdeqi", OPTO(2,TOEQ), OPTO_MASK, PPC|B64, { RA, SI } },
+{ "tdlgei", OPTO(2,TOLGE), OPTO_MASK, PPC|B64, { RA, SI } },
+{ "tdlnli", OPTO(2,TOLNL), OPTO_MASK, PPC|B64, { RA, SI } },
+{ "tdllei", OPTO(2,TOLLE), OPTO_MASK, PPC|B64, { RA, SI } },
+{ "tdlngi", OPTO(2,TOLNG), OPTO_MASK, PPC|B64, { RA, SI } },
+{ "tdgti", OPTO(2,TOGT), OPTO_MASK, PPC|B64, { RA, SI } },
+{ "tdgei", OPTO(2,TOGE), OPTO_MASK, PPC|B64, { RA, SI } },
+{ "tdnli", OPTO(2,TONL), OPTO_MASK, PPC|B64, { RA, SI } },
+{ "tdlti", OPTO(2,TOLT), OPTO_MASK, PPC|B64, { RA, SI } },
+{ "tdlei", OPTO(2,TOLE), OPTO_MASK, PPC|B64, { RA, SI } },
+{ "tdngi", OPTO(2,TONG), OPTO_MASK, PPC|B64, { RA, SI } },
+{ "tdnei", OPTO(2,TONE), OPTO_MASK, PPC|B64, { RA, SI } },
+{ "tdi", OP(2), OP_MASK, PPC|B64, { TO, RA, SI } },
+
+{ "twlgti", OPTO(3,TOLGT), OPTO_MASK, PPC, { RA, SI } },
+{ "tlgti", OPTO(3,TOLGT), OPTO_MASK, POWER, { RA, SI } },
+{ "twllti", OPTO(3,TOLLT), OPTO_MASK, PPC, { RA, SI } },
+{ "tllti", OPTO(3,TOLLT), OPTO_MASK, POWER, { RA, SI } },
+{ "tweqi", OPTO(3,TOEQ), OPTO_MASK, PPC, { RA, SI } },
+{ "teqi", OPTO(3,TOEQ), OPTO_MASK, POWER, { RA, SI } },
+{ "twlgei", OPTO(3,TOLGE), OPTO_MASK, PPC, { RA, SI } },
+{ "tlgei", OPTO(3,TOLGE), OPTO_MASK, POWER, { RA, SI } },
+{ "twlnli", OPTO(3,TOLNL), OPTO_MASK, PPC, { RA, SI } },
+{ "tlnli", OPTO(3,TOLNL), OPTO_MASK, POWER, { RA, SI } },
+{ "twllei", OPTO(3,TOLLE), OPTO_MASK, PPC, { RA, SI } },
+{ "tllei", OPTO(3,TOLLE), OPTO_MASK, POWER, { RA, SI } },
+{ "twlngi", OPTO(3,TOLNG), OPTO_MASK, PPC, { RA, SI } },
+{ "tlngi", OPTO(3,TOLNG), OPTO_MASK, POWER, { RA, SI } },
+{ "twgti", OPTO(3,TOGT), OPTO_MASK, PPC, { RA, SI } },
+{ "tgti", OPTO(3,TOGT), OPTO_MASK, POWER, { RA, SI } },
+{ "twgei", OPTO(3,TOGE), OPTO_MASK, PPC, { RA, SI } },
+{ "tgei", OPTO(3,TOGE), OPTO_MASK, POWER, { RA, SI } },
+{ "twnli", OPTO(3,TONL), OPTO_MASK, PPC, { RA, SI } },
+{ "tnli", OPTO(3,TONL), OPTO_MASK, POWER, { RA, SI } },
+{ "twlti", OPTO(3,TOLT), OPTO_MASK, PPC, { RA, SI } },
+{ "tlti", OPTO(3,TOLT), OPTO_MASK, POWER, { RA, SI } },
+{ "twlei", OPTO(3,TOLE), OPTO_MASK, PPC, { RA, SI } },
+{ "tlei", OPTO(3,TOLE), OPTO_MASK, POWER, { RA, SI } },
+{ "twngi", OPTO(3,TONG), OPTO_MASK, PPC, { RA, SI } },
+{ "tngi", OPTO(3,TONG), OPTO_MASK, POWER, { RA, SI } },
+{ "twnei", OPTO(3,TONE), OPTO_MASK, PPC, { RA, SI } },
+{ "tnei", OPTO(3,TONE), OPTO_MASK, POWER, { RA, SI } },
+{ "twi", OP(3), OP_MASK, PPC, { TO, RA, SI } },
+{ "ti", OP(3), OP_MASK, POWER, { TO, RA, SI } },
+
+{ "mulli", OP(7), OP_MASK, PPC, { RT, RA, SI } },
+{ "muli", OP(7), OP_MASK, POWER, { RT, RA, SI } },
+
+{ "subfic", OP(8), OP_MASK, PPC, { RT, RA, SI } },
+{ "sfi", OP(8), OP_MASK, POWER, { RT, RA, SI } },
+
+{ "dozi", OP(9), OP_MASK, POWER|M601, { RT, RA, SI } },
+
+{ "cmplwi", OPL(10,0), OPL_MASK, PPC, { OBF, RA, UI } },
+{ "cmpldi", OPL(10,1), OPL_MASK, PPC|B64, { OBF, RA, UI } },
+{ "cmpli", OP(10), OP_MASK, PPC, { BF, L, RA, UI } },
+{ "cmpli", OP(10), OP_MASK, POWER, { BF, RA, UI } },
+
+{ "cmpwi", OPL(11,0), OPL_MASK, PPC, { OBF, RA, SI } },
+{ "cmpdi", OPL(11,1), OPL_MASK, PPC|B64, { OBF, RA, SI } },
+{ "cmpi", OP(11), OP_MASK, PPC, { BF, L, RA, SI } },
+{ "cmpi", OP(11), OP_MASK, POWER, { BF, RA, SI } },
+
+{ "addic", OP(12), OP_MASK, PPC, { RT, RA, SI } },
+{ "ai", OP(12), OP_MASK, POWER, { RT, RA, SI } },
+{ "subic", OP(12), OP_MASK, PPC, { RT, RA, NSI } },
+
+{ "addic.", OP(13), OP_MASK, PPC, { RT, RA, SI } },
+{ "ai.", OP(13), OP_MASK, POWER, { RT, RA, SI } },
+{ "subic.", OP(13), OP_MASK, PPC, { RT, RA, NSI } },
+
+{ "li", OP(14), DRA_MASK, PPC, { RT, SI } },
+{ "lil", OP(14), DRA_MASK, POWER, { RT, SI } },
+{ "addi", OP(14), OP_MASK, PPC, { RT, RA, SI } },
+{ "cal", OP(14), OP_MASK, POWER, { RT, D, RA } },
+{ "subi", OP(14), OP_MASK, PPC, { RT, RA, NSI } },
+{ "la", OP(14), OP_MASK, PPC, { RT, D, RA } },
+
+{ "lis", OP(15), DRA_MASK, PPC, { RT, SISIGNOPT } },
+{ "liu", OP(15), DRA_MASK, POWER, { RT, SISIGNOPT } },
+{ "addis", OP(15), OP_MASK, PPC, { RT,RA,SISIGNOPT } },
+{ "cau", OP(15), OP_MASK, POWER, { RT,RA,SISIGNOPT } },
+{ "subis", OP(15), OP_MASK, PPC, { RT, RA, NSI } },
+
+{ "bdnz-", BBO(16,BODNZ,0,0), BBOYBI_MASK, PPC, { BDM } },
+{ "bdnz+", BBO(16,BODNZ,0,0), BBOYBI_MASK, PPC, { BDP } },
+{ "bdnz", BBO(16,BODNZ,0,0), BBOYBI_MASK, PPC, { BD } },
+{ "bdn", BBO(16,BODNZ,0,0), BBOYBI_MASK, POWER, { BD } },
+{ "bdnzl-", BBO(16,BODNZ,0,1), BBOYBI_MASK, PPC, { BDM } },
+{ "bdnzl+", BBO(16,BODNZ,0,1), BBOYBI_MASK, PPC, { BDP } },
+{ "bdnzl", BBO(16,BODNZ,0,1), BBOYBI_MASK, PPC, { BD } },
+{ "bdnl", BBO(16,BODNZ,0,1), BBOYBI_MASK, POWER, { BD } },
+{ "bdnza-", BBO(16,BODNZ,1,0), BBOYBI_MASK, PPC, { BDMA } },
+{ "bdnza+", BBO(16,BODNZ,1,0), BBOYBI_MASK, PPC, { BDPA } },
+{ "bdnza", BBO(16,BODNZ,1,0), BBOYBI_MASK, PPC, { BDA } },
+{ "bdna", BBO(16,BODNZ,1,0), BBOYBI_MASK, POWER, { BDA } },
+{ "bdnzla-", BBO(16,BODNZ,1,1), BBOYBI_MASK, PPC, { BDMA } },
+{ "bdnzla+", BBO(16,BODNZ,1,1), BBOYBI_MASK, PPC, { BDPA } },
+{ "bdnzla", BBO(16,BODNZ,1,1), BBOYBI_MASK, PPC, { BDA } },
+{ "bdnla", BBO(16,BODNZ,1,1), BBOYBI_MASK, POWER, { BDA } },
+{ "bdz-", BBO(16,BODZ,0,0), BBOYBI_MASK, PPC, { BDM } },
+{ "bdz+", BBO(16,BODZ,0,0), BBOYBI_MASK, PPC, { BDP } },
+{ "bdz", BBO(16,BODZ,0,0), BBOYBI_MASK, PPC|POWER, { BD } },
+{ "bdzl-", BBO(16,BODZ,0,1), BBOYBI_MASK, PPC, { BDM } },
+{ "bdzl+", BBO(16,BODZ,0,1), BBOYBI_MASK, PPC, { BDP } },
+{ "bdzl", BBO(16,BODZ,0,1), BBOYBI_MASK, PPC|POWER, { BD } },
+{ "bdza-", BBO(16,BODZ,1,0), BBOYBI_MASK, PPC, { BDMA } },
+{ "bdza+", BBO(16,BODZ,1,0), BBOYBI_MASK, PPC, { BDPA } },
+{ "bdza", BBO(16,BODZ,1,0), BBOYBI_MASK, PPC|POWER, { BDA } },
+{ "bdzla-", BBO(16,BODZ,1,1), BBOYBI_MASK, PPC, { BDMA } },
+{ "bdzla+", BBO(16,BODZ,1,1), BBOYBI_MASK, PPC, { BDPA } },
+{ "bdzla", BBO(16,BODZ,1,1), BBOYBI_MASK, PPC|POWER, { BDA } },
+{ "blt-", BBOCB(16,BOT,CBLT,0,0), BBOYCB_MASK, PPC, { CR, BDM } },
+{ "blt+", BBOCB(16,BOT,CBLT,0,0), BBOYCB_MASK, PPC, { CR, BDP } },
+{ "blt", BBOCB(16,BOT,CBLT,0,0), BBOYCB_MASK, PPC|POWER, { CR, BD } },
+{ "bltl-", BBOCB(16,BOT,CBLT,0,1), BBOYCB_MASK, PPC, { CR, BDM } },
+{ "bltl+", BBOCB(16,BOT,CBLT,0,1), BBOYCB_MASK, PPC, { CR, BDP } },
+{ "bltl", BBOCB(16,BOT,CBLT,0,1), BBOYCB_MASK, PPC|POWER, { CR, BD } },
+{ "blta-", BBOCB(16,BOT,CBLT,1,0), BBOYCB_MASK, PPC, { CR, BDMA } },
+{ "blta+", BBOCB(16,BOT,CBLT,1,0), BBOYCB_MASK, PPC, { CR, BDPA } },
+{ "blta", BBOCB(16,BOT,CBLT,1,0), BBOYCB_MASK, PPC|POWER, { CR, BDA } },
+{ "bltla-", BBOCB(16,BOT,CBLT,1,1), BBOYCB_MASK, PPC, { CR, BDMA } },
+{ "bltla+", BBOCB(16,BOT,CBLT,1,1), BBOYCB_MASK, PPC, { CR, BDPA } },
+{ "bltla", BBOCB(16,BOT,CBLT,1,1), BBOYCB_MASK, PPC|POWER, { CR, BDA } },
+{ "bgt-", BBOCB(16,BOT,CBGT,0,0), BBOYCB_MASK, PPC, { CR, BDM } },
+{ "bgt+", BBOCB(16,BOT,CBGT,0,0), BBOYCB_MASK, PPC, { CR, BDP } },
+{ "bgt", BBOCB(16,BOT,CBGT,0,0), BBOYCB_MASK, PPC|POWER, { CR, BD } },
+{ "bgtl-", BBOCB(16,BOT,CBGT,0,1), BBOYCB_MASK, PPC, { CR, BDM } },
+{ "bgtl+", BBOCB(16,BOT,CBGT,0,1), BBOYCB_MASK, PPC, { CR, BDP } },
+{ "bgtl", BBOCB(16,BOT,CBGT,0,1), BBOYCB_MASK, PPC|POWER, { CR, BD } },
+{ "bgta-", BBOCB(16,BOT,CBGT,1,0), BBOYCB_MASK, PPC, { CR, BDMA } },
+{ "bgta+", BBOCB(16,BOT,CBGT,1,0), BBOYCB_MASK, PPC, { CR, BDPA } },
+{ "bgta", BBOCB(16,BOT,CBGT,1,0), BBOYCB_MASK, PPC|POWER, { CR, BDA } },
+{ "bgtla-", BBOCB(16,BOT,CBGT,1,1), BBOYCB_MASK, PPC, { CR, BDMA } },
+{ "bgtla+", BBOCB(16,BOT,CBGT,1,1), BBOYCB_MASK, PPC, { CR, BDPA } },
+{ "bgtla", BBOCB(16,BOT,CBGT,1,1), BBOYCB_MASK, PPC|POWER, { CR, BDA } },
+{ "beq-", BBOCB(16,BOT,CBEQ,0,0), BBOYCB_MASK, PPC, { CR, BDM } },
+{ "beq+", BBOCB(16,BOT,CBEQ,0,0), BBOYCB_MASK, PPC, { CR, BDP } },
+{ "beq", BBOCB(16,BOT,CBEQ,0,0), BBOYCB_MASK, PPC|POWER, { CR, BD } },
+{ "beql-", BBOCB(16,BOT,CBEQ,0,1), BBOYCB_MASK, PPC, { CR, BDM } },
+{ "beql+", BBOCB(16,BOT,CBEQ,0,1), BBOYCB_MASK, PPC, { CR, BDP } },
+{ "beql", BBOCB(16,BOT,CBEQ,0,1), BBOYCB_MASK, PPC|POWER, { CR, BD } },
+{ "beqa-", BBOCB(16,BOT,CBEQ,1,0), BBOYCB_MASK, PPC, { CR, BDMA } },
+{ "beqa+", BBOCB(16,BOT,CBEQ,1,0), BBOYCB_MASK, PPC, { CR, BDPA } },
+{ "beqa", BBOCB(16,BOT,CBEQ,1,0), BBOYCB_MASK, PPC|POWER, { CR, BDA } },
+{ "beqla-", BBOCB(16,BOT,CBEQ,1,1), BBOYCB_MASK, PPC, { CR, BDMA } },
+{ "beqla+", BBOCB(16,BOT,CBEQ,1,1), BBOYCB_MASK, PPC, { CR, BDPA } },
+{ "beqla", BBOCB(16,BOT,CBEQ,1,1), BBOYCB_MASK, PPC|POWER, { CR, BDA } },
+{ "bso-", BBOCB(16,BOT,CBSO,0,0), BBOYCB_MASK, PPC, { CR, BDM } },
+{ "bso+", BBOCB(16,BOT,CBSO,0,0), BBOYCB_MASK, PPC, { CR, BDP } },
+{ "bso", BBOCB(16,BOT,CBSO,0,0), BBOYCB_MASK, PPC|POWER, { CR, BD } },
+{ "bsol-", BBOCB(16,BOT,CBSO,0,1), BBOYCB_MASK, PPC, { CR, BDM } },
+{ "bsol+", BBOCB(16,BOT,CBSO,0,1), BBOYCB_MASK, PPC, { CR, BDP } },
+{ "bsol", BBOCB(16,BOT,CBSO,0,1), BBOYCB_MASK, PPC|POWER, { CR, BD } },
+{ "bsoa-", BBOCB(16,BOT,CBSO,1,0), BBOYCB_MASK, PPC, { CR, BDMA } },
+{ "bsoa+", BBOCB(16,BOT,CBSO,1,0), BBOYCB_MASK, PPC, { CR, BDPA } },
+{ "bsoa", BBOCB(16,BOT,CBSO,1,0), BBOYCB_MASK, PPC|POWER, { CR, BDA } },
+{ "bsola-", BBOCB(16,BOT,CBSO,1,1), BBOYCB_MASK, PPC, { CR, BDMA } },
+{ "bsola+", BBOCB(16,BOT,CBSO,1,1), BBOYCB_MASK, PPC, { CR, BDPA } },
+{ "bsola", BBOCB(16,BOT,CBSO,1,1), BBOYCB_MASK, PPC|POWER, { CR, BDA } },
+{ "bun-", BBOCB(16,BOT,CBSO,0,0), BBOYCB_MASK, PPC, { CR, BDM } },
+{ "bun+", BBOCB(16,BOT,CBSO,0,0), BBOYCB_MASK, PPC, { CR, BDP } },
+{ "bun", BBOCB(16,BOT,CBSO,0,0), BBOYCB_MASK, PPC, { CR, BD } },
+{ "bunl-", BBOCB(16,BOT,CBSO,0,1), BBOYCB_MASK, PPC, { CR, BDM } },
+{ "bunl+", BBOCB(16,BOT,CBSO,0,1), BBOYCB_MASK, PPC, { CR, BDP } },
+{ "bunl", BBOCB(16,BOT,CBSO,0,1), BBOYCB_MASK, PPC, { CR, BD } },
+{ "buna-", BBOCB(16,BOT,CBSO,1,0), BBOYCB_MASK, PPC, { CR, BDMA } },
+{ "buna+", BBOCB(16,BOT,CBSO,1,0), BBOYCB_MASK, PPC, { CR, BDPA } },
+{ "buna", BBOCB(16,BOT,CBSO,1,0), BBOYCB_MASK, PPC, { CR, BDA } },
+{ "bunla-", BBOCB(16,BOT,CBSO,1,1), BBOYCB_MASK, PPC, { CR, BDMA } },
+{ "bunla+", BBOCB(16,BOT,CBSO,1,1), BBOYCB_MASK, PPC, { CR, BDPA } },
+{ "bunla", BBOCB(16,BOT,CBSO,1,1), BBOYCB_MASK, PPC, { CR, BDA } },
+{ "bge-", BBOCB(16,BOF,CBLT,0,0), BBOYCB_MASK, PPC, { CR, BDM } },
+{ "bge+", BBOCB(16,BOF,CBLT,0,0), BBOYCB_MASK, PPC, { CR, BDP } },
+{ "bge", BBOCB(16,BOF,CBLT,0,0), BBOYCB_MASK, PPC|POWER, { CR, BD } },
+{ "bgel-", BBOCB(16,BOF,CBLT,0,1), BBOYCB_MASK, PPC, { CR, BDM } },
+{ "bgel+", BBOCB(16,BOF,CBLT,0,1), BBOYCB_MASK, PPC, { CR, BDP } },
+{ "bgel", BBOCB(16,BOF,CBLT,0,1), BBOYCB_MASK, PPC|POWER, { CR, BD } },
+{ "bgea-", BBOCB(16,BOF,CBLT,1,0), BBOYCB_MASK, PPC, { CR, BDMA } },
+{ "bgea+", BBOCB(16,BOF,CBLT,1,0), BBOYCB_MASK, PPC, { CR, BDPA } },
+{ "bgea", BBOCB(16,BOF,CBLT,1,0), BBOYCB_MASK, PPC|POWER, { CR, BDA } },
+{ "bgela-", BBOCB(16,BOF,CBLT,1,1), BBOYCB_MASK, PPC, { CR, BDMA } },
+{ "bgela+", BBOCB(16,BOF,CBLT,1,1), BBOYCB_MASK, PPC, { CR, BDPA } },
+{ "bgela", BBOCB(16,BOF,CBLT,1,1), BBOYCB_MASK, PPC|POWER, { CR, BDA } },
+{ "bnl-", BBOCB(16,BOF,CBLT,0,0), BBOYCB_MASK, PPC, { CR, BDM } },
+{ "bnl+", BBOCB(16,BOF,CBLT,0,0), BBOYCB_MASK, PPC, { CR, BDP } },
+{ "bnl", BBOCB(16,BOF,CBLT,0,0), BBOYCB_MASK, PPC|POWER, { CR, BD } },
+{ "bnll-", BBOCB(16,BOF,CBLT,0,1), BBOYCB_MASK, PPC, { CR, BDM } },
+{ "bnll+", BBOCB(16,BOF,CBLT,0,1), BBOYCB_MASK, PPC, { CR, BDP } },
+{ "bnll", BBOCB(16,BOF,CBLT,0,1), BBOYCB_MASK, PPC|POWER, { CR, BD } },
+{ "bnla-", BBOCB(16,BOF,CBLT,1,0), BBOYCB_MASK, PPC, { CR, BDMA } },
+{ "bnla+", BBOCB(16,BOF,CBLT,1,0), BBOYCB_MASK, PPC, { CR, BDPA } },
+{ "bnla", BBOCB(16,BOF,CBLT,1,0), BBOYCB_MASK, PPC|POWER, { CR, BDA } },
+{ "bnlla-", BBOCB(16,BOF,CBLT,1,1), BBOYCB_MASK, PPC, { CR, BDMA } },
+{ "bnlla+", BBOCB(16,BOF,CBLT,1,1), BBOYCB_MASK, PPC, { CR, BDPA } },
+{ "bnlla", BBOCB(16,BOF,CBLT,1,1), BBOYCB_MASK, PPC|POWER, { CR, BDA } },
+{ "ble-", BBOCB(16,BOF,CBGT,0,0), BBOYCB_MASK, PPC, { CR, BDM } },
+{ "ble+", BBOCB(16,BOF,CBGT,0,0), BBOYCB_MASK, PPC, { CR, BDP } },
+{ "ble", BBOCB(16,BOF,CBGT,0,0), BBOYCB_MASK, PPC|POWER, { CR, BD } },
+{ "blel-", BBOCB(16,BOF,CBGT,0,1), BBOYCB_MASK, PPC, { CR, BDM } },
+{ "blel+", BBOCB(16,BOF,CBGT,0,1), BBOYCB_MASK, PPC, { CR, BDP } },
+{ "blel", BBOCB(16,BOF,CBGT,0,1), BBOYCB_MASK, PPC|POWER, { CR, BD } },
+{ "blea-", BBOCB(16,BOF,CBGT,1,0), BBOYCB_MASK, PPC, { CR, BDMA } },
+{ "blea+", BBOCB(16,BOF,CBGT,1,0), BBOYCB_MASK, PPC, { CR, BDPA } },
+{ "blea", BBOCB(16,BOF,CBGT,1,0), BBOYCB_MASK, PPC|POWER, { CR, BDA } },
+{ "blela-", BBOCB(16,BOF,CBGT,1,1), BBOYCB_MASK, PPC, { CR, BDMA } },
+{ "blela+", BBOCB(16,BOF,CBGT,1,1), BBOYCB_MASK, PPC, { CR, BDPA } },
+{ "blela", BBOCB(16,BOF,CBGT,1,1), BBOYCB_MASK, PPC|POWER, { CR, BDA } },
+{ "bng-", BBOCB(16,BOF,CBGT,0,0), BBOYCB_MASK, PPC, { CR, BDM } },
+{ "bng+", BBOCB(16,BOF,CBGT,0,0), BBOYCB_MASK, PPC, { CR, BDP } },
+{ "bng", BBOCB(16,BOF,CBGT,0,0), BBOYCB_MASK, PPC|POWER, { CR, BD } },
+{ "bngl-", BBOCB(16,BOF,CBGT,0,1), BBOYCB_MASK, PPC, { CR, BDM } },
+{ "bngl+", BBOCB(16,BOF,CBGT,0,1), BBOYCB_MASK, PPC, { CR, BDP } },
+{ "bngl", BBOCB(16,BOF,CBGT,0,1), BBOYCB_MASK, PPC|POWER, { CR, BD } },
+{ "bnga-", BBOCB(16,BOF,CBGT,1,0), BBOYCB_MASK, PPC, { CR, BDMA } },
+{ "bnga+", BBOCB(16,BOF,CBGT,1,0), BBOYCB_MASK, PPC, { CR, BDPA } },
+{ "bnga", BBOCB(16,BOF,CBGT,1,0), BBOYCB_MASK, PPC|POWER, { CR, BDA } },
+{ "bngla-", BBOCB(16,BOF,CBGT,1,1), BBOYCB_MASK, PPC, { CR, BDMA } },
+{ "bngla+", BBOCB(16,BOF,CBGT,1,1), BBOYCB_MASK, PPC, { CR, BDPA } },
+{ "bngla", BBOCB(16,BOF,CBGT,1,1), BBOYCB_MASK, PPC|POWER, { CR, BDA } },
+{ "bne-", BBOCB(16,BOF,CBEQ,0,0), BBOYCB_MASK, PPC, { CR, BDM } },
+{ "bne+", BBOCB(16,BOF,CBEQ,0,0), BBOYCB_MASK, PPC, { CR, BDP } },
+{ "bne", BBOCB(16,BOF,CBEQ,0,0), BBOYCB_MASK, PPC|POWER, { CR, BD } },
+{ "bnel-", BBOCB(16,BOF,CBEQ,0,1), BBOYCB_MASK, PPC, { CR, BDM } },
+{ "bnel+", BBOCB(16,BOF,CBEQ,0,1), BBOYCB_MASK, PPC, { CR, BDP } },
+{ "bnel", BBOCB(16,BOF,CBEQ,0,1), BBOYCB_MASK, PPC|POWER, { CR, BD } },
+{ "bnea-", BBOCB(16,BOF,CBEQ,1,0), BBOYCB_MASK, PPC, { CR, BDMA } },
+{ "bnea+", BBOCB(16,BOF,CBEQ,1,0), BBOYCB_MASK, PPC, { CR, BDPA } },
+{ "bnea", BBOCB(16,BOF,CBEQ,1,0), BBOYCB_MASK, PPC|POWER, { CR, BDA } },
+{ "bnela-", BBOCB(16,BOF,CBEQ,1,1), BBOYCB_MASK, PPC, { CR, BDMA } },
+{ "bnela+", BBOCB(16,BOF,CBEQ,1,1), BBOYCB_MASK, PPC, { CR, BDPA } },
+{ "bnela", BBOCB(16,BOF,CBEQ,1,1), BBOYCB_MASK, PPC|POWER, { CR, BDA } },
+{ "bns-", BBOCB(16,BOF,CBSO,0,0), BBOYCB_MASK, PPC, { CR, BDM } },
+{ "bns+", BBOCB(16,BOF,CBSO,0,0), BBOYCB_MASK, PPC, { CR, BDP } },
+{ "bns", BBOCB(16,BOF,CBSO,0,0), BBOYCB_MASK, PPC|POWER, { CR, BD } },
+{ "bnsl-", BBOCB(16,BOF,CBSO,0,1), BBOYCB_MASK, PPC, { CR, BDM } },
+{ "bnsl+", BBOCB(16,BOF,CBSO,0,1), BBOYCB_MASK, PPC, { CR, BDP } },
+{ "bnsl", BBOCB(16,BOF,CBSO,0,1), BBOYCB_MASK, PPC|POWER, { CR, BD } },
+{ "bnsa-", BBOCB(16,BOF,CBSO,1,0), BBOYCB_MASK, PPC, { CR, BDMA } },
+{ "bnsa+", BBOCB(16,BOF,CBSO,1,0), BBOYCB_MASK, PPC, { CR, BDPA } },
+{ "bnsa", BBOCB(16,BOF,CBSO,1,0), BBOYCB_MASK, PPC|POWER, { CR, BDA } },
+{ "bnsla-", BBOCB(16,BOF,CBSO,1,1), BBOYCB_MASK, PPC, { CR, BDMA } },
+{ "bnsla+", BBOCB(16,BOF,CBSO,1,1), BBOYCB_MASK, PPC, { CR, BDPA } },
+{ "bnsla", BBOCB(16,BOF,CBSO,1,1), BBOYCB_MASK, PPC|POWER, { CR, BDA } },
+{ "bnu-", BBOCB(16,BOF,CBSO,0,0), BBOYCB_MASK, PPC, { CR, BDM } },
+{ "bnu+", BBOCB(16,BOF,CBSO,0,0), BBOYCB_MASK, PPC, { CR, BDP } },
+{ "bnu", BBOCB(16,BOF,CBSO,0,0), BBOYCB_MASK, PPC, { CR, BD } },
+{ "bnul-", BBOCB(16,BOF,CBSO,0,1), BBOYCB_MASK, PPC, { CR, BDM } },
+{ "bnul+", BBOCB(16,BOF,CBSO,0,1), BBOYCB_MASK, PPC, { CR, BDP } },
+{ "bnul", BBOCB(16,BOF,CBSO,0,1), BBOYCB_MASK, PPC, { CR, BD } },
+{ "bnua-", BBOCB(16,BOF,CBSO,1,0), BBOYCB_MASK, PPC, { CR, BDMA } },
+{ "bnua+", BBOCB(16,BOF,CBSO,1,0), BBOYCB_MASK, PPC, { CR, BDPA } },
+{ "bnua", BBOCB(16,BOF,CBSO,1,0), BBOYCB_MASK, PPC, { CR, BDA } },
+{ "bnula-", BBOCB(16,BOF,CBSO,1,1), BBOYCB_MASK, PPC, { CR, BDMA } },
+{ "bnula+", BBOCB(16,BOF,CBSO,1,1), BBOYCB_MASK, PPC, { CR, BDPA } },
+{ "bnula", BBOCB(16,BOF,CBSO,1,1), BBOYCB_MASK, PPC, { CR, BDA } },
+{ "bdnzt-", BBO(16,BODNZT,0,0), BBOY_MASK, PPC, { BI, BDM } },
+{ "bdnzt+", BBO(16,BODNZT,0,0), BBOY_MASK, PPC, { BI, BDP } },
+{ "bdnzt", BBO(16,BODNZT,0,0), BBOY_MASK, PPC, { BI, BD } },
+{ "bdnztl-", BBO(16,BODNZT,0,1), BBOY_MASK, PPC, { BI, BDM } },
+{ "bdnztl+", BBO(16,BODNZT,0,1), BBOY_MASK, PPC, { BI, BDP } },
+{ "bdnztl", BBO(16,BODNZT,0,1), BBOY_MASK, PPC, { BI, BD } },
+{ "bdnzta-", BBO(16,BODNZT,1,0), BBOY_MASK, PPC, { BI, BDMA } },
+{ "bdnzta+", BBO(16,BODNZT,1,0), BBOY_MASK, PPC, { BI, BDPA } },
+{ "bdnzta", BBO(16,BODNZT,1,0), BBOY_MASK, PPC, { BI, BDA } },
+{ "bdnztla-",BBO(16,BODNZT,1,1), BBOY_MASK, PPC, { BI, BDMA } },
+{ "bdnztla+",BBO(16,BODNZT,1,1), BBOY_MASK, PPC, { BI, BDPA } },
+{ "bdnztla", BBO(16,BODNZT,1,1), BBOY_MASK, PPC, { BI, BDA } },
+{ "bdnzf-", BBO(16,BODNZF,0,0), BBOY_MASK, PPC, { BI, BDM } },
+{ "bdnzf+", BBO(16,BODNZF,0,0), BBOY_MASK, PPC, { BI, BDP } },
+{ "bdnzf", BBO(16,BODNZF,0,0), BBOY_MASK, PPC, { BI, BD } },
+{ "bdnzfl-", BBO(16,BODNZF,0,1), BBOY_MASK, PPC, { BI, BDM } },
+{ "bdnzfl+", BBO(16,BODNZF,0,1), BBOY_MASK, PPC, { BI, BDP } },
+{ "bdnzfl", BBO(16,BODNZF,0,1), BBOY_MASK, PPC, { BI, BD } },
+{ "bdnzfa-", BBO(16,BODNZF,1,0), BBOY_MASK, PPC, { BI, BDMA } },
+{ "bdnzfa+", BBO(16,BODNZF,1,0), BBOY_MASK, PPC, { BI, BDPA } },
+{ "bdnzfa", BBO(16,BODNZF,1,0), BBOY_MASK, PPC, { BI, BDA } },
+{ "bdnzfla-",BBO(16,BODNZF,1,1), BBOY_MASK, PPC, { BI, BDMA } },
+{ "bdnzfla+",BBO(16,BODNZF,1,1), BBOY_MASK, PPC, { BI, BDPA } },
+{ "bdnzfla", BBO(16,BODNZF,1,1), BBOY_MASK, PPC, { BI, BDA } },
+{ "bt-", BBO(16,BOT,0,0), BBOY_MASK, PPC, { BI, BDM } },
+{ "bt+", BBO(16,BOT,0,0), BBOY_MASK, PPC, { BI, BDP } },
+{ "bt", BBO(16,BOT,0,0), BBOY_MASK, PPC, { BI, BD } },
+{ "bbt", BBO(16,BOT,0,0), BBOY_MASK, POWER, { BI, BD } },
+{ "btl-", BBO(16,BOT,0,1), BBOY_MASK, PPC, { BI, BDM } },
+{ "btl+", BBO(16,BOT,0,1), BBOY_MASK, PPC, { BI, BDP } },
+{ "btl", BBO(16,BOT,0,1), BBOY_MASK, PPC, { BI, BD } },
+{ "bbtl", BBO(16,BOT,0,1), BBOY_MASK, POWER, { BI, BD } },
+{ "bta-", BBO(16,BOT,1,0), BBOY_MASK, PPC, { BI, BDMA } },
+{ "bta+", BBO(16,BOT,1,0), BBOY_MASK, PPC, { BI, BDPA } },
+{ "bta", BBO(16,BOT,1,0), BBOY_MASK, PPC, { BI, BDA } },
+{ "bbta", BBO(16,BOT,1,0), BBOY_MASK, POWER, { BI, BDA } },
+{ "btla-", BBO(16,BOT,1,1), BBOY_MASK, PPC, { BI, BDMA } },
+{ "btla+", BBO(16,BOT,1,1), BBOY_MASK, PPC, { BI, BDPA } },
+{ "btla", BBO(16,BOT,1,1), BBOY_MASK, PPC, { BI, BDA } },
+{ "bbtla", BBO(16,BOT,1,1), BBOY_MASK, POWER, { BI, BDA } },
+{ "bf-", BBO(16,BOF,0,0), BBOY_MASK, PPC, { BI, BDM } },
+{ "bf+", BBO(16,BOF,0,0), BBOY_MASK, PPC, { BI, BDP } },
+{ "bf", BBO(16,BOF,0,0), BBOY_MASK, PPC, { BI, BD } },
+{ "bbf", BBO(16,BOF,0,0), BBOY_MASK, POWER, { BI, BD } },
+{ "bfl-", BBO(16,BOF,0,1), BBOY_MASK, PPC, { BI, BDM } },
+{ "bfl+", BBO(16,BOF,0,1), BBOY_MASK, PPC, { BI, BDP } },
+{ "bfl", BBO(16,BOF,0,1), BBOY_MASK, PPC, { BI, BD } },
+{ "bbfl", BBO(16,BOF,0,1), BBOY_MASK, POWER, { BI, BD } },
+{ "bfa-", BBO(16,BOF,1,0), BBOY_MASK, PPC, { BI, BDMA } },
+{ "bfa+", BBO(16,BOF,1,0), BBOY_MASK, PPC, { BI, BDPA } },
+{ "bfa", BBO(16,BOF,1,0), BBOY_MASK, PPC, { BI, BDA } },
+{ "bbfa", BBO(16,BOF,1,0), BBOY_MASK, POWER, { BI, BDA } },
+{ "bfla-", BBO(16,BOF,1,1), BBOY_MASK, PPC, { BI, BDMA } },
+{ "bfla+", BBO(16,BOF,1,1), BBOY_MASK, PPC, { BI, BDPA } },
+{ "bfla", BBO(16,BOF,1,1), BBOY_MASK, PPC, { BI, BDA } },
+{ "bbfla", BBO(16,BOF,1,1), BBOY_MASK, POWER, { BI, BDA } },
+{ "bdzt-", BBO(16,BODZT,0,0), BBOY_MASK, PPC, { BI, BDM } },
+{ "bdzt+", BBO(16,BODZT,0,0), BBOY_MASK, PPC, { BI, BDP } },
+{ "bdzt", BBO(16,BODZT,0,0), BBOY_MASK, PPC, { BI, BD } },
+{ "bdztl-", BBO(16,BODZT,0,1), BBOY_MASK, PPC, { BI, BDM } },
+{ "bdztl+", BBO(16,BODZT,0,1), BBOY_MASK, PPC, { BI, BDP } },
+{ "bdztl", BBO(16,BODZT,0,1), BBOY_MASK, PPC, { BI, BD } },
+{ "bdzta-", BBO(16,BODZT,1,0), BBOY_MASK, PPC, { BI, BDMA } },
+{ "bdzta+", BBO(16,BODZT,1,0), BBOY_MASK, PPC, { BI, BDPA } },
+{ "bdzta", BBO(16,BODZT,1,0), BBOY_MASK, PPC, { BI, BDA } },
+{ "bdztla-", BBO(16,BODZT,1,1), BBOY_MASK, PPC, { BI, BDMA } },
+{ "bdztla+", BBO(16,BODZT,1,1), BBOY_MASK, PPC, { BI, BDPA } },
+{ "bdztla", BBO(16,BODZT,1,1), BBOY_MASK, PPC, { BI, BDA } },
+{ "bdzf-", BBO(16,BODZF,0,0), BBOY_MASK, PPC, { BI, BDM } },
+{ "bdzf+", BBO(16,BODZF,0,0), BBOY_MASK, PPC, { BI, BDP } },
+{ "bdzf", BBO(16,BODZF,0,0), BBOY_MASK, PPC, { BI, BD } },
+{ "bdzfl-", BBO(16,BODZF,0,1), BBOY_MASK, PPC, { BI, BDM } },
+{ "bdzfl+", BBO(16,BODZF,0,1), BBOY_MASK, PPC, { BI, BDP } },
+{ "bdzfl", BBO(16,BODZF,0,1), BBOY_MASK, PPC, { BI, BD } },
+{ "bdzfa-", BBO(16,BODZF,1,0), BBOY_MASK, PPC, { BI, BDMA } },
+{ "bdzfa+", BBO(16,BODZF,1,0), BBOY_MASK, PPC, { BI, BDPA } },
+{ "bdzfa", BBO(16,BODZF,1,0), BBOY_MASK, PPC, { BI, BDA } },
+{ "bdzfla-", BBO(16,BODZF,1,1), BBOY_MASK, PPC, { BI, BDMA } },
+{ "bdzfla+", BBO(16,BODZF,1,1), BBOY_MASK, PPC, { BI, BDPA } },
+{ "bdzfla", BBO(16,BODZF,1,1), BBOY_MASK, PPC, { BI, BDA } },
+{ "bc-", B(16,0,0), B_MASK, PPC, { BOE, BI, BDM } },
+{ "bc+", B(16,0,0), B_MASK, PPC, { BOE, BI, BDP } },
+{ "bc", B(16,0,0), B_MASK, PPC|POWER, { BO, BI, BD } },
+{ "bcl-", B(16,0,1), B_MASK, PPC, { BOE, BI, BDM } },
+{ "bcl+", B(16,0,1), B_MASK, PPC, { BOE, BI, BDP } },
+{ "bcl", B(16,0,1), B_MASK, PPC|POWER, { BO, BI, BD } },
+{ "bca-", B(16,1,0), B_MASK, PPC, { BOE, BI, BDMA } },
+{ "bca+", B(16,1,0), B_MASK, PPC, { BOE, BI, BDPA } },
+{ "bca", B(16,1,0), B_MASK, PPC|POWER, { BO, BI, BDA } },
+{ "bcla-", B(16,1,1), B_MASK, PPC, { BOE, BI, BDMA } },
+{ "bcla+", B(16,1,1), B_MASK, PPC, { BOE, BI, BDPA } },
+{ "bcla", B(16,1,1), B_MASK, PPC|POWER, { BO, BI, BDA } },
+
+{ "sc", SC(17,1,0), 0xffffffff, PPC, { 0 } },
+{ "svc", SC(17,0,0), SC_MASK, POWER, { LEV, FL1, FL2 } },
+{ "svcl", SC(17,0,1), SC_MASK, POWER, { LEV, FL1, FL2 } },
+{ "svca", SC(17,1,0), SC_MASK, POWER, { SV } },
+{ "svcla", SC(17,1,1), SC_MASK, POWER, { SV } },
+
+{ "b", B(18,0,0), B_MASK, PPC|POWER, { LI } },
+{ "bl", B(18,0,1), B_MASK, PPC|POWER, { LI } },
+{ "ba", B(18,1,0), B_MASK, PPC|POWER, { LIA } },
+{ "bla", B(18,1,1), B_MASK, PPC|POWER, { LIA } },
+
+{ "mcrf", XL(19,0), XLBB_MASK|(3<<21)|(3<<16), PPC|POWER, { BF, BFA } },
+
+{ "blr", XLO(19,BOU,16,0), XLBOBIBB_MASK, PPC, { 0 } },
+{ "br", XLO(19,BOU,16,0), XLBOBIBB_MASK, POWER, { 0 } },
+{ "blrl", XLO(19,BOU,16,1), XLBOBIBB_MASK, PPC, { 0 } },
+{ "brl", XLO(19,BOU,16,1), XLBOBIBB_MASK, POWER, { 0 } },
+{ "bdnzlr", XLO(19,BODNZ,16,0), XLBOBIBB_MASK, PPC, { 0 } },
+{ "bdnzlr-", XLO(19,BODNZ,16,0), XLBOBIBB_MASK, PPC, { 0 } },
+{ "bdnzlr+", XLO(19,BODNZP,16,0), XLBOBIBB_MASK, PPC, { 0 } },
+{ "bdnzlrl", XLO(19,BODNZ,16,1), XLBOBIBB_MASK, PPC, { 0 } },
+{ "bdnzlrl-",XLO(19,BODNZ,16,1), XLBOBIBB_MASK, PPC, { 0 } },
+{ "bdnzlrl+",XLO(19,BODNZP,16,1), XLBOBIBB_MASK, PPC, { 0 } },
+{ "bdzlr", XLO(19,BODZ,16,0), XLBOBIBB_MASK, PPC, { 0 } },
+{ "bdzlr-", XLO(19,BODZ,16,0), XLBOBIBB_MASK, PPC, { 0 } },
+{ "bdzlr+", XLO(19,BODZP,16,0), XLBOBIBB_MASK, PPC, { 0 } },
+{ "bdzlrl", XLO(19,BODZ,16,1), XLBOBIBB_MASK, PPC, { 0 } },
+{ "bdzlrl-", XLO(19,BODZ,16,1), XLBOBIBB_MASK, PPC, { 0 } },
+{ "bdzlrl+", XLO(19,BODZP,16,1), XLBOBIBB_MASK, PPC, { 0 } },
+{ "bltlr", XLOCB(19,BOT,CBLT,16,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "bltlr-", XLOCB(19,BOT,CBLT,16,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "bltlr+", XLOCB(19,BOTP,CBLT,16,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "bltr", XLOCB(19,BOT,CBLT,16,0), XLBOCBBB_MASK, POWER, { CR } },
+{ "bltlrl", XLOCB(19,BOT,CBLT,16,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "bltlrl-", XLOCB(19,BOT,CBLT,16,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "bltlrl+", XLOCB(19,BOTP,CBLT,16,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "bltrl", XLOCB(19,BOT,CBLT,16,1), XLBOCBBB_MASK, POWER, { CR } },
+{ "bgtlr", XLOCB(19,BOT,CBGT,16,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "bgtlr-", XLOCB(19,BOT,CBGT,16,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "bgtlr+", XLOCB(19,BOTP,CBGT,16,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "bgtr", XLOCB(19,BOT,CBGT,16,0), XLBOCBBB_MASK, POWER, { CR } },
+{ "bgtlrl", XLOCB(19,BOT,CBGT,16,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "bgtlrl-", XLOCB(19,BOT,CBGT,16,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "bgtlrl+", XLOCB(19,BOTP,CBGT,16,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "bgtrl", XLOCB(19,BOT,CBGT,16,1), XLBOCBBB_MASK, POWER, { CR } },
+{ "beqlr", XLOCB(19,BOT,CBEQ,16,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "beqlr-", XLOCB(19,BOT,CBEQ,16,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "beqlr+", XLOCB(19,BOTP,CBEQ,16,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "beqr", XLOCB(19,BOT,CBEQ,16,0), XLBOCBBB_MASK, POWER, { CR } },
+{ "beqlrl", XLOCB(19,BOT,CBEQ,16,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "beqlrl-", XLOCB(19,BOT,CBEQ,16,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "beqlrl+", XLOCB(19,BOTP,CBEQ,16,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "beqrl", XLOCB(19,BOT,CBEQ,16,1), XLBOCBBB_MASK, POWER, { CR } },
+{ "bsolr", XLOCB(19,BOT,CBSO,16,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "bsolr-", XLOCB(19,BOT,CBSO,16,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "bsolr+", XLOCB(19,BOTP,CBSO,16,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "bsor", XLOCB(19,BOT,CBSO,16,0), XLBOCBBB_MASK, POWER, { CR } },
+{ "bsolrl", XLOCB(19,BOT,CBSO,16,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "bsolrl-", XLOCB(19,BOT,CBSO,16,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "bsolrl+", XLOCB(19,BOTP,CBSO,16,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "bsorl", XLOCB(19,BOT,CBSO,16,1), XLBOCBBB_MASK, POWER, { CR } },
+{ "bunlr", XLOCB(19,BOT,CBSO,16,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "bunlr-", XLOCB(19,BOT,CBSO,16,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "bunlr+", XLOCB(19,BOTP,CBSO,16,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "bunlrl", XLOCB(19,BOT,CBSO,16,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "bunlrl-", XLOCB(19,BOT,CBSO,16,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "bunlrl+", XLOCB(19,BOTP,CBSO,16,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "bgelr", XLOCB(19,BOF,CBLT,16,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "bgelr-", XLOCB(19,BOF,CBLT,16,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "bgelr+", XLOCB(19,BOFP,CBLT,16,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "bger", XLOCB(19,BOF,CBLT,16,0), XLBOCBBB_MASK, POWER, { CR } },
+{ "bgelrl", XLOCB(19,BOF,CBLT,16,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "bgelrl-", XLOCB(19,BOF,CBLT,16,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "bgelrl+", XLOCB(19,BOFP,CBLT,16,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "bgerl", XLOCB(19,BOF,CBLT,16,1), XLBOCBBB_MASK, POWER, { CR } },
+{ "bnllr", XLOCB(19,BOF,CBLT,16,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "bnllr-", XLOCB(19,BOF,CBLT,16,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "bnllr+", XLOCB(19,BOFP,CBLT,16,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "bnlr", XLOCB(19,BOF,CBLT,16,0), XLBOCBBB_MASK, POWER, { CR } },
+{ "bnllrl", XLOCB(19,BOF,CBLT,16,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "bnllrl-", XLOCB(19,BOF,CBLT,16,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "bnllrl+", XLOCB(19,BOFP,CBLT,16,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "bnlrl", XLOCB(19,BOF,CBLT,16,1), XLBOCBBB_MASK, POWER, { CR } },
+{ "blelr", XLOCB(19,BOF,CBGT,16,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "blelr-", XLOCB(19,BOF,CBGT,16,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "blelr+", XLOCB(19,BOFP,CBGT,16,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "bler", XLOCB(19,BOF,CBGT,16,0), XLBOCBBB_MASK, POWER, { CR } },
+{ "blelrl", XLOCB(19,BOF,CBGT,16,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "blelrl-", XLOCB(19,BOF,CBGT,16,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "blelrl+", XLOCB(19,BOFP,CBGT,16,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "blerl", XLOCB(19,BOF,CBGT,16,1), XLBOCBBB_MASK, POWER, { CR } },
+{ "bnglr", XLOCB(19,BOF,CBGT,16,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "bnglr-", XLOCB(19,BOF,CBGT,16,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "bnglr+", XLOCB(19,BOFP,CBGT,16,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "bngr", XLOCB(19,BOF,CBGT,16,0), XLBOCBBB_MASK, POWER, { CR } },
+{ "bnglrl", XLOCB(19,BOF,CBGT,16,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "bnglrl-", XLOCB(19,BOF,CBGT,16,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "bnglrl+", XLOCB(19,BOFP,CBGT,16,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "bngrl", XLOCB(19,BOF,CBGT,16,1), XLBOCBBB_MASK, POWER, { CR } },
+{ "bnelr", XLOCB(19,BOF,CBEQ,16,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "bnelr-", XLOCB(19,BOF,CBEQ,16,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "bnelr+", XLOCB(19,BOFP,CBEQ,16,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "bner", XLOCB(19,BOF,CBEQ,16,0), XLBOCBBB_MASK, POWER, { CR } },
+{ "bnelrl", XLOCB(19,BOF,CBEQ,16,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "bnelrl-", XLOCB(19,BOF,CBEQ,16,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "bnelrl+", XLOCB(19,BOFP,CBEQ,16,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "bnerl", XLOCB(19,BOF,CBEQ,16,1), XLBOCBBB_MASK, POWER, { CR } },
+{ "bnslr", XLOCB(19,BOF,CBSO,16,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "bnslr-", XLOCB(19,BOF,CBSO,16,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "bnslr+", XLOCB(19,BOFP,CBSO,16,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "bnsr", XLOCB(19,BOF,CBSO,16,0), XLBOCBBB_MASK, POWER, { CR } },
+{ "bnslrl", XLOCB(19,BOF,CBSO,16,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "bnslrl-", XLOCB(19,BOF,CBSO,16,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "bnslrl+", XLOCB(19,BOFP,CBSO,16,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "bnsrl", XLOCB(19,BOF,CBSO,16,1), XLBOCBBB_MASK, POWER, { CR } },
+{ "bnulr", XLOCB(19,BOF,CBSO,16,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "bnulr-", XLOCB(19,BOF,CBSO,16,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "bnulr+", XLOCB(19,BOFP,CBSO,16,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "bnulrl", XLOCB(19,BOF,CBSO,16,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "bnulrl-", XLOCB(19,BOF,CBSO,16,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "bnulrl+", XLOCB(19,BOFP,CBSO,16,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "btlr", XLO(19,BOT,16,0), XLBOBB_MASK, PPC, { BI } },
+{ "btlr-", XLO(19,BOT,16,0), XLBOBB_MASK, PPC, { BI } },
+{ "btlr+", XLO(19,BOTP,16,0), XLBOBB_MASK, PPC, { BI } },
+{ "bbtr", XLO(19,BOT,16,0), XLBOBB_MASK, POWER, { BI } },
+{ "btlrl", XLO(19,BOT,16,1), XLBOBB_MASK, PPC, { BI } },
+{ "btlrl-", XLO(19,BOT,16,1), XLBOBB_MASK, PPC, { BI } },
+{ "btlrl+", XLO(19,BOTP,16,1), XLBOBB_MASK, PPC, { BI } },
+{ "bbtrl", XLO(19,BOT,16,1), XLBOBB_MASK, POWER, { BI } },
+{ "bflr", XLO(19,BOF,16,0), XLBOBB_MASK, PPC, { BI } },
+{ "bflr-", XLO(19,BOF,16,0), XLBOBB_MASK, PPC, { BI } },
+{ "bflr+", XLO(19,BOFP,16,0), XLBOBB_MASK, PPC, { BI } },
+{ "bbfr", XLO(19,BOF,16,0), XLBOBB_MASK, POWER, { BI } },
+{ "bflrl", XLO(19,BOF,16,1), XLBOBB_MASK, PPC, { BI } },
+{ "bflrl-", XLO(19,BOF,16,1), XLBOBB_MASK, PPC, { BI } },
+{ "bflrl+", XLO(19,BOFP,16,1), XLBOBB_MASK, PPC, { BI } },
+{ "bbfrl", XLO(19,BOF,16,1), XLBOBB_MASK, POWER, { BI } },
+{ "bdnztlr", XLO(19,BODNZT,16,0), XLBOBB_MASK, PPC, { BI } },
+{ "bdnztlr-",XLO(19,BODNZT,16,0), XLBOBB_MASK, PPC, { BI } },
+{ "bdnztlr+",XLO(19,BODNZTP,16,0), XLBOBB_MASK, PPC, { BI } },
+{ "bdnztlrl",XLO(19,BODNZT,16,1), XLBOBB_MASK, PPC, { BI } },
+{ "bdnztlrl-",XLO(19,BODNZT,16,1), XLBOBB_MASK, PPC, { BI } },
+{ "bdnztlrl+",XLO(19,BODNZTP,16,1), XLBOBB_MASK, PPC, { BI } },
+{ "bdnzflr", XLO(19,BODNZF,16,0), XLBOBB_MASK, PPC, { BI } },
+{ "bdnzflr-",XLO(19,BODNZF,16,0), XLBOBB_MASK, PPC, { BI } },
+{ "bdnzflr+",XLO(19,BODNZFP,16,0), XLBOBB_MASK, PPC, { BI } },
+{ "bdnzflrl",XLO(19,BODNZF,16,1), XLBOBB_MASK, PPC, { BI } },
+{ "bdnzflrl-",XLO(19,BODNZF,16,1), XLBOBB_MASK, PPC, { BI } },
+{ "bdnzflrl+",XLO(19,BODNZFP,16,1), XLBOBB_MASK, PPC, { BI } },
+{ "bdztlr", XLO(19,BODZT,16,0), XLBOBB_MASK, PPC, { BI } },
+{ "bdztlr-", XLO(19,BODZT,16,0), XLBOBB_MASK, PPC, { BI } },
+{ "bdztlr+", XLO(19,BODZTP,16,0), XLBOBB_MASK, PPC, { BI } },
+{ "bdztlrl", XLO(19,BODZT,16,1), XLBOBB_MASK, PPC, { BI } },
+{ "bdztlrl-",XLO(19,BODZT,16,1), XLBOBB_MASK, PPC, { BI } },
+{ "bdztlrl+",XLO(19,BODZTP,16,1), XLBOBB_MASK, PPC, { BI } },
+{ "bdzflr", XLO(19,BODZF,16,0), XLBOBB_MASK, PPC, { BI } },
+{ "bdzflr-", XLO(19,BODZF,16,0), XLBOBB_MASK, PPC, { BI } },
+{ "bdzflr+", XLO(19,BODZFP,16,0), XLBOBB_MASK, PPC, { BI } },
+{ "bdzflrl", XLO(19,BODZF,16,1), XLBOBB_MASK, PPC, { BI } },
+{ "bdzflrl-",XLO(19,BODZF,16,1), XLBOBB_MASK, PPC, { BI } },
+{ "bdzflrl+",XLO(19,BODZFP,16,1), XLBOBB_MASK, PPC, { BI } },
+{ "bclr", XLLK(19,16,0), XLYBB_MASK, PPC, { BO, BI } },
+{ "bclrl", XLLK(19,16,1), XLYBB_MASK, PPC, { BO, BI } },
+{ "bclr+", XLYLK(19,16,1,0), XLYBB_MASK, PPC, { BOE, BI } },
+{ "bclrl+", XLYLK(19,16,1,1), XLYBB_MASK, PPC, { BOE, BI } },
+{ "bclr-", XLYLK(19,16,0,0), XLYBB_MASK, PPC, { BOE, BI } },
+{ "bclrl-", XLYLK(19,16,0,1), XLYBB_MASK, PPC, { BOE, BI } },
+{ "bcr", XLLK(19,16,0), XLBB_MASK, POWER, { BO, BI } },
+{ "bcrl", XLLK(19,16,1), XLBB_MASK, POWER, { BO, BI } },
+
+{ "crnot", XL(19,33), XL_MASK, PPC, { BT, BA, BBA } },
+{ "crnor", XL(19,33), XL_MASK, PPC|POWER, { BT, BA, BB } },
+
+{ "rfi", XL(19,50), 0xffffffff, PPC|POWER, { 0 } },
+{ "rfci", XL(19,51), 0xffffffff, PPC, { 0 } },
+
+{ "rfsvc", XL(19,82), 0xffffffff, POWER, { 0 } },
+
+{ "crandc", XL(19,129), XL_MASK, PPC|POWER, { BT, BA, BB } },
+
+{ "isync", XL(19,150), 0xffffffff, PPC, { 0 } },
+{ "ics", XL(19,150), 0xffffffff, POWER, { 0 } },
+
+{ "crclr", XL(19,193), XL_MASK, PPC, { BT, BAT, BBA } },
+{ "crxor", XL(19,193), XL_MASK, PPC|POWER, { BT, BA, BB } },
+
+{ "crnand", XL(19,225), XL_MASK, PPC|POWER, { BT, BA, BB } },
+
+{ "crand", XL(19,257), XL_MASK, PPC|POWER, { BT, BA, BB } },
+
+{ "crset", XL(19,289), XL_MASK, PPC, { BT, BAT, BBA } },
+{ "creqv", XL(19,289), XL_MASK, PPC|POWER, { BT, BA, BB } },
+
+{ "crorc", XL(19,417), XL_MASK, PPC|POWER, { BT, BA, BB } },
+
+{ "crmove", XL(19,449), XL_MASK, PPC, { BT, BA, BBA } },
+{ "cror", XL(19,449), XL_MASK, PPC|POWER, { BT, BA, BB } },
+
+{ "bctr", XLO(19,BOU,528,0), XLBOBIBB_MASK, PPC|POWER, { 0 } },
+{ "bctrl", XLO(19,BOU,528,1), XLBOBIBB_MASK, PPC|POWER, { 0 } },
+{ "bltctr", XLOCB(19,BOT,CBLT,528,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "bltctr-", XLOCB(19,BOT,CBLT,528,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "bltctr+", XLOCB(19,BOTP,CBLT,528,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "bltctrl", XLOCB(19,BOT,CBLT,528,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "bltctrl-",XLOCB(19,BOT,CBLT,528,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "bltctrl+",XLOCB(19,BOTP,CBLT,528,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "bgtctr", XLOCB(19,BOT,CBGT,528,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "bgtctr-", XLOCB(19,BOT,CBGT,528,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "bgtctr+", XLOCB(19,BOTP,CBGT,528,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "bgtctrl", XLOCB(19,BOT,CBGT,528,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "bgtctrl-",XLOCB(19,BOT,CBGT,528,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "bgtctrl+",XLOCB(19,BOTP,CBGT,528,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "beqctr", XLOCB(19,BOT,CBEQ,528,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "beqctr-", XLOCB(19,BOT,CBEQ,528,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "beqctr+", XLOCB(19,BOTP,CBEQ,528,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "beqctrl", XLOCB(19,BOT,CBEQ,528,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "beqctrl-",XLOCB(19,BOT,CBEQ,528,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "beqctrl+",XLOCB(19,BOTP,CBEQ,528,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "bsoctr", XLOCB(19,BOT,CBSO,528,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "bsoctr-", XLOCB(19,BOT,CBSO,528,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "bsoctr+", XLOCB(19,BOTP,CBSO,528,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "bsoctrl", XLOCB(19,BOT,CBSO,528,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "bsoctrl-",XLOCB(19,BOT,CBSO,528,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "bsoctrl+",XLOCB(19,BOTP,CBSO,528,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "bunctr", XLOCB(19,BOT,CBSO,528,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "bunctr-", XLOCB(19,BOT,CBSO,528,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "bunctr+", XLOCB(19,BOTP,CBSO,528,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "bunctrl", XLOCB(19,BOT,CBSO,528,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "bunctrl-",XLOCB(19,BOT,CBSO,528,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "bunctrl+",XLOCB(19,BOTP,CBSO,528,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "bgectr", XLOCB(19,BOF,CBLT,528,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "bgectr-", XLOCB(19,BOF,CBLT,528,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "bgectr+", XLOCB(19,BOFP,CBLT,528,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "bgectrl", XLOCB(19,BOF,CBLT,528,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "bgectrl-",XLOCB(19,BOF,CBLT,528,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "bgectrl+",XLOCB(19,BOFP,CBLT,528,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "bnlctr", XLOCB(19,BOF,CBLT,528,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "bnlctr-", XLOCB(19,BOF,CBLT,528,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "bnlctr+", XLOCB(19,BOFP,CBLT,528,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "bnlctrl", XLOCB(19,BOF,CBLT,528,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "bnlctrl-",XLOCB(19,BOF,CBLT,528,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "bnlctrl+",XLOCB(19,BOFP,CBLT,528,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "blectr", XLOCB(19,BOF,CBGT,528,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "blectr-", XLOCB(19,BOF,CBGT,528,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "blectr+", XLOCB(19,BOFP,CBGT,528,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "blectrl", XLOCB(19,BOF,CBGT,528,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "blectrl-",XLOCB(19,BOF,CBGT,528,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "blectrl+",XLOCB(19,BOFP,CBGT,528,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "bngctr", XLOCB(19,BOF,CBGT,528,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "bngctr-", XLOCB(19,BOF,CBGT,528,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "bngctr+", XLOCB(19,BOFP,CBGT,528,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "bngctrl", XLOCB(19,BOF,CBGT,528,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "bngctrl-",XLOCB(19,BOF,CBGT,528,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "bngctrl+",XLOCB(19,BOFP,CBGT,528,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "bnectr", XLOCB(19,BOF,CBEQ,528,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "bnectr-", XLOCB(19,BOF,CBEQ,528,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "bnectr+", XLOCB(19,BOFP,CBEQ,528,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "bnectrl", XLOCB(19,BOF,CBEQ,528,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "bnectrl-",XLOCB(19,BOF,CBEQ,528,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "bnectrl+",XLOCB(19,BOFP,CBEQ,528,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "bnsctr", XLOCB(19,BOF,CBSO,528,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "bnsctr-", XLOCB(19,BOF,CBSO,528,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "bnsctr+", XLOCB(19,BOFP,CBSO,528,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "bnsctrl", XLOCB(19,BOF,CBSO,528,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "bnsctrl-",XLOCB(19,BOF,CBSO,528,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "bnsctrl+",XLOCB(19,BOFP,CBSO,528,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "bnuctr", XLOCB(19,BOF,CBSO,528,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "bnuctr-", XLOCB(19,BOF,CBSO,528,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "bnuctr+", XLOCB(19,BOFP,CBSO,528,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "bnuctrl", XLOCB(19,BOF,CBSO,528,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "bnuctrl-",XLOCB(19,BOF,CBSO,528,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "bnuctrl+",XLOCB(19,BOFP,CBSO,528,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "btctr", XLO(19,BOT,528,0), XLBOBB_MASK, PPC, { BI } },
+{ "btctr-", XLO(19,BOT,528,0), XLBOBB_MASK, PPC, { BI } },
+{ "btctr+", XLO(19,BOTP,528,0), XLBOBB_MASK, PPC, { BI } },
+{ "btctrl", XLO(19,BOT,528,1), XLBOBB_MASK, PPC, { BI } },
+{ "btctrl-", XLO(19,BOT,528,1), XLBOBB_MASK, PPC, { BI } },
+{ "btctrl+", XLO(19,BOTP,528,1), XLBOBB_MASK, PPC, { BI } },
+{ "bfctr", XLO(19,BOF,528,0), XLBOBB_MASK, PPC, { BI } },
+{ "bfctr-", XLO(19,BOF,528,0), XLBOBB_MASK, PPC, { BI } },
+{ "bfctr+", XLO(19,BOFP,528,0), XLBOBB_MASK, PPC, { BI } },
+{ "bfctrl", XLO(19,BOF,528,1), XLBOBB_MASK, PPC, { BI } },
+{ "bfctrl-", XLO(19,BOF,528,1), XLBOBB_MASK, PPC, { BI } },
+{ "bfctrl+", XLO(19,BOFP,528,1), XLBOBB_MASK, PPC, { BI } },
+{ "bcctr", XLLK(19,528,0), XLYBB_MASK, PPC, { BO, BI } },
+{ "bcctr-", XLYLK(19,528,0,0), XLYBB_MASK, PPC, { BOE, BI } },
+{ "bcctr+", XLYLK(19,528,1,0), XLYBB_MASK, PPC, { BOE, BI } },
+{ "bcctrl", XLLK(19,528,1), XLYBB_MASK, PPC, { BO, BI } },
+{ "bcctrl-", XLYLK(19,528,0,1), XLYBB_MASK, PPC, { BOE, BI } },
+{ "bcctrl+", XLYLK(19,528,1,1), XLYBB_MASK, PPC, { BOE, BI } },
+{ "bcc", XLLK(19,528,0), XLBB_MASK, POWER, { BO, BI } },
+{ "bccl", XLLK(19,528,1), XLBB_MASK, POWER, { BO, BI } },
+
+{ "rlwimi", M(20,0), M_MASK, PPC, { RA,RS,SH,MBE,ME } },
+{ "rlimi", M(20,0), M_MASK, POWER, { RA,RS,SH,MBE,ME } },
+
+{ "rlwimi.", M(20,1), M_MASK, PPC, { RA,RS,SH,MBE,ME } },
+{ "rlimi.", M(20,1), M_MASK, POWER, { RA,RS,SH,MBE,ME } },
+
+{ "rotlwi", MME(21,31,0), MMBME_MASK, PPC, { RA, RS, SH } },
+{ "clrlwi", MME(21,31,0), MSHME_MASK, PPC, { RA, RS, MB } },
+{ "rlwinm", M(21,0), M_MASK, PPC, { RA,RS,SH,MBE,ME } },
+{ "rlinm", M(21,0), M_MASK, POWER, { RA,RS,SH,MBE,ME } },
+{ "rotlwi.", MME(21,31,1), MMBME_MASK, PPC, { RA,RS,SH } },
+{ "clrlwi.", MME(21,31,1), MSHME_MASK, PPC, { RA, RS, MB } },
+{ "rlwinm.", M(21,1), M_MASK, PPC, { RA,RS,SH,MBE,ME } },
+{ "rlinm.", M(21,1), M_MASK, POWER, { RA,RS,SH,MBE,ME } },
+
+{ "rlmi", M(22,0), M_MASK, POWER|M601, { RA,RS,RB,MBE,ME } },
+{ "rlmi.", M(22,1), M_MASK, POWER|M601, { RA,RS,RB,MBE,ME } },
+
+{ "rotlw", MME(23,31,0), MMBME_MASK, PPC, { RA, RS, RB } },
+{ "rlwnm", M(23,0), M_MASK, PPC, { RA,RS,RB,MBE,ME } },
+{ "rlnm", M(23,0), M_MASK, POWER, { RA,RS,RB,MBE,ME } },
+{ "rotlw.", MME(23,31,1), MMBME_MASK, PPC, { RA, RS, RB } },
+{ "rlwnm.", M(23,1), M_MASK, PPC, { RA,RS,RB,MBE,ME } },
+{ "rlnm.", M(23,1), M_MASK, POWER, { RA,RS,RB,MBE,ME } },
+
+{ "nop", OP(24), 0xffffffff, PPC, { 0 } },
+{ "ori", OP(24), OP_MASK, PPC, { RA, RS, UI } },
+{ "oril", OP(24), OP_MASK, POWER, { RA, RS, UI } },
+
+{ "oris", OP(25), OP_MASK, PPC, { RA, RS, UI } },
+{ "oriu", OP(25), OP_MASK, POWER, { RA, RS, UI } },
+
+{ "xori", OP(26), OP_MASK, PPC, { RA, RS, UI } },
+{ "xoril", OP(26), OP_MASK, POWER, { RA, RS, UI } },
+
+{ "xoris", OP(27), OP_MASK, PPC, { RA, RS, UI } },
+{ "xoriu", OP(27), OP_MASK, POWER, { RA, RS, UI } },
+
+{ "andi.", OP(28), OP_MASK, PPC, { RA, RS, UI } },
+{ "andil.", OP(28), OP_MASK, POWER, { RA, RS, UI } },
+
+{ "andis.", OP(29), OP_MASK, PPC, { RA, RS, UI } },
+{ "andiu.", OP(29), OP_MASK, POWER, { RA, RS, UI } },
+
+{ "rotldi", MD(30,0,0), MDMB_MASK, PPC|B64, { RA, RS, SH6 } },
+{ "clrldi", MD(30,0,0), MDSH_MASK, PPC|B64, { RA, RS, MB6 } },
+{ "rldicl", MD(30,0,0), MD_MASK, PPC|B64, { RA, RS, SH6, MB6 } },
+{ "rotldi.", MD(30,0,1), MDMB_MASK, PPC|B64, { RA, RS, SH6 } },
+{ "clrldi.", MD(30,0,1), MDSH_MASK, PPC|B64, { RA, RS, MB6 } },
+{ "rldicl.", MD(30,0,1), MD_MASK, PPC|B64, { RA, RS, SH6, MB6 } },
+
+{ "rldicr", MD(30,1,0), MD_MASK, PPC|B64, { RA, RS, SH6, ME6 } },
+{ "rldicr.", MD(30,1,1), MD_MASK, PPC|B64, { RA, RS, SH6, ME6 } },
+
+{ "rldic", MD(30,2,0), MD_MASK, PPC|B64, { RA, RS, SH6, MB6 } },
+{ "rldic.", MD(30,2,1), MD_MASK, PPC|B64, { RA, RS, SH6, MB6 } },
+
+{ "rldimi", MD(30,3,0), MD_MASK, PPC|B64, { RA, RS, SH6, MB6 } },
+{ "rldimi.", MD(30,3,1), MD_MASK, PPC|B64, { RA, RS, SH6, MB6 } },
+
+{ "rotld", MDS(30,8,0), MDSMB_MASK, PPC|B64, { RA, RS, RB } },
+{ "rldcl", MDS(30,8,0), MDS_MASK, PPC|B64, { RA, RS, RB, MB6 } },
+{ "rotld.", MDS(30,8,1), MDSMB_MASK, PPC|B64, { RA, RS, RB } },
+{ "rldcl.", MDS(30,8,1), MDS_MASK, PPC|B64, { RA, RS, RB, MB6 } },
+
+{ "rldcr", MDS(30,9,0), MDS_MASK, PPC|B64, { RA, RS, RB, ME6 } },
+{ "rldcr.", MDS(30,9,1), MDS_MASK, PPC|B64, { RA, RS, RB, ME6 } },
+
+{ "cmpw", XCMPL(31,0,0), XCMPL_MASK, PPC, { OBF, RA, RB } },
+{ "cmpd", XCMPL(31,0,1), XCMPL_MASK, PPC|B64, { OBF, RA, RB } },
+{ "cmp", X(31,0), XCMP_MASK, PPC, { BF, L, RA, RB } },
+{ "cmp", X(31,0), XCMPL_MASK, POWER, { BF, RA, RB } },
+
+{ "twlgt", XTO(31,4,TOLGT), XTO_MASK, PPC, { RA, RB } },
+{ "tlgt", XTO(31,4,TOLGT), XTO_MASK, POWER, { RA, RB } },
+{ "twllt", XTO(31,4,TOLLT), XTO_MASK, PPC, { RA, RB } },
+{ "tllt", XTO(31,4,TOLLT), XTO_MASK, POWER, { RA, RB } },
+{ "tweq", XTO(31,4,TOEQ), XTO_MASK, PPC, { RA, RB } },
+{ "teq", XTO(31,4,TOEQ), XTO_MASK, POWER, { RA, RB } },
+{ "twlge", XTO(31,4,TOLGE), XTO_MASK, PPC, { RA, RB } },
+{ "tlge", XTO(31,4,TOLGE), XTO_MASK, POWER, { RA, RB } },
+{ "twlnl", XTO(31,4,TOLNL), XTO_MASK, PPC, { RA, RB } },
+{ "tlnl", XTO(31,4,TOLNL), XTO_MASK, POWER, { RA, RB } },
+{ "twlle", XTO(31,4,TOLLE), XTO_MASK, PPC, { RA, RB } },
+{ "tlle", XTO(31,4,TOLLE), XTO_MASK, POWER, { RA, RB } },
+{ "twlng", XTO(31,4,TOLNG), XTO_MASK, PPC, { RA, RB } },
+{ "tlng", XTO(31,4,TOLNG), XTO_MASK, POWER, { RA, RB } },
+{ "twgt", XTO(31,4,TOGT), XTO_MASK, PPC, { RA, RB } },
+{ "tgt", XTO(31,4,TOGT), XTO_MASK, POWER, { RA, RB } },
+{ "twge", XTO(31,4,TOGE), XTO_MASK, PPC, { RA, RB } },
+{ "tge", XTO(31,4,TOGE), XTO_MASK, POWER, { RA, RB } },
+{ "twnl", XTO(31,4,TONL), XTO_MASK, PPC, { RA, RB } },
+{ "tnl", XTO(31,4,TONL), XTO_MASK, POWER, { RA, RB } },
+{ "twlt", XTO(31,4,TOLT), XTO_MASK, PPC, { RA, RB } },
+{ "tlt", XTO(31,4,TOLT), XTO_MASK, POWER, { RA, RB } },
+{ "twle", XTO(31,4,TOLE), XTO_MASK, PPC, { RA, RB } },
+{ "tle", XTO(31,4,TOLE), XTO_MASK, POWER, { RA, RB } },
+{ "twng", XTO(31,4,TONG), XTO_MASK, PPC, { RA, RB } },
+{ "tng", XTO(31,4,TONG), XTO_MASK, POWER, { RA, RB } },
+{ "twne", XTO(31,4,TONE), XTO_MASK, PPC, { RA, RB } },
+{ "tne", XTO(31,4,TONE), XTO_MASK, POWER, { RA, RB } },
+{ "trap", XTO(31,4,TOU), 0xffffffff, PPC, { 0 } },
+{ "tw", X(31,4), X_MASK, PPC, { TO, RA, RB } },
+{ "t", X(31,4), X_MASK, POWER, { TO, RA, RB } },
+
+{ "subfc", XO(31,8,0,0), XO_MASK, PPC, { RT, RA, RB } },
+{ "sf", XO(31,8,0,0), XO_MASK, POWER, { RT, RA, RB } },
+{ "subc", XO(31,8,0,0), XO_MASK, PPC, { RT, RB, RA } },
+{ "subfc.", XO(31,8,0,1), XO_MASK, PPC, { RT, RA, RB } },
+{ "sf.", XO(31,8,0,1), XO_MASK, POWER, { RT, RA, RB } },
+{ "subc.", XO(31,8,0,1), XO_MASK, PPC, { RT, RB, RA } },
+{ "subfco", XO(31,8,1,0), XO_MASK, PPC, { RT, RA, RB } },
+{ "sfo", XO(31,8,1,0), XO_MASK, POWER, { RT, RA, RB } },
+{ "subco", XO(31,8,1,0), XO_MASK, PPC, { RT, RB, RA } },
+{ "subfco.", XO(31,8,1,1), XO_MASK, PPC, { RT, RA, RB } },
+{ "sfo.", XO(31,8,1,1), XO_MASK, POWER, { RT, RA, RB } },
+{ "subco.", XO(31,8,1,1), XO_MASK, PPC, { RT, RB, RA } },
+
+{ "mulhdu", XO(31,9,0,0), XO_MASK, PPC|B64, { RT, RA, RB } },
+{ "mulhdu.", XO(31,9,0,1), XO_MASK, PPC|B64, { RT, RA, RB } },
+
+{ "addc", XO(31,10,0,0), XO_MASK, PPC, { RT, RA, RB } },
+{ "a", XO(31,10,0,0), XO_MASK, POWER, { RT, RA, RB } },
+{ "addc.", XO(31,10,0,1), XO_MASK, PPC, { RT, RA, RB } },
+{ "a.", XO(31,10,0,1), XO_MASK, POWER, { RT, RA, RB } },
+{ "addco", XO(31,10,1,0), XO_MASK, PPC, { RT, RA, RB } },
+{ "ao", XO(31,10,1,0), XO_MASK, POWER, { RT, RA, RB } },
+{ "addco.", XO(31,10,1,1), XO_MASK, PPC, { RT, RA, RB } },
+{ "ao.", XO(31,10,1,1), XO_MASK, POWER, { RT, RA, RB } },
+
+{ "mulhwu", XO(31,11,0,0), XO_MASK, PPC, { RT, RA, RB } },
+{ "mulhwu.", XO(31,11,0,1), XO_MASK, PPC, { RT, RA, RB } },
+
+{ "mfcr", X(31,19), XRARB_MASK, POWER|PPC, { RT } },
+
+{ "lwarx", X(31,20), X_MASK, PPC, { RT, RA, RB } },
+
+{ "ldx", X(31,21), X_MASK, PPC|B64, { RT, RA, RB } },
+
+{ "lwzx", X(31,23), X_MASK, PPC, { RT, RA, RB } },
+{ "lx", X(31,23), X_MASK, POWER, { RT, RA, RB } },
+
+{ "slw", XRC(31,24,0), X_MASK, PPC, { RA, RS, RB } },
+{ "sl", XRC(31,24,0), X_MASK, POWER, { RA, RS, RB } },
+{ "slw.", XRC(31,24,1), X_MASK, PPC, { RA, RS, RB } },
+{ "sl.", XRC(31,24,1), X_MASK, POWER, { RA, RS, RB } },
+
+{ "cntlzw", XRC(31,26,0), XRB_MASK, PPC, { RA, RS } },
+{ "cntlz", XRC(31,26,0), XRB_MASK, POWER, { RA, RS } },
+{ "cntlzw.", XRC(31,26,1), XRB_MASK, PPC, { RA, RS } },
+{ "cntlz.", XRC(31,26,1), XRB_MASK, POWER, { RA, RS } },
+
+{ "sld", XRC(31,27,0), X_MASK, PPC|B64, { RA, RS, RB } },
+{ "sld.", XRC(31,27,1), X_MASK, PPC|B64, { RA, RS, RB } },
+
+{ "and", XRC(31,28,0), X_MASK, PPC|POWER, { RA, RS, RB } },
+{ "and.", XRC(31,28,1), X_MASK, PPC|POWER, { RA, RS, RB } },
+
+{ "maskg", XRC(31,29,0), X_MASK, POWER|M601, { RA, RS, RB } },
+{ "maskg.", XRC(31,29,1), X_MASK, POWER|M601, { RA, RS, RB } },
+
+{ "cmplw", XCMPL(31,32,0), XCMPL_MASK, PPC, { OBF, RA, RB } },
+{ "cmpld", XCMPL(31,32,1), XCMPL_MASK, PPC|B64, { OBF, RA, RB } },
+{ "cmpl", X(31,32), XCMP_MASK, PPC, { BF, L, RA, RB } },
+{ "cmpl", X(31,32), XCMPL_MASK, POWER, { BF, RA, RB } },
+
+{ "subf", XO(31,40,0,0), XO_MASK, PPC, { RT, RA, RB } },
+{ "sub", XO(31,40,0,0), XO_MASK, PPC, { RT, RB, RA } },
+{ "subf.", XO(31,40,0,1), XO_MASK, PPC, { RT, RA, RB } },
+{ "sub.", XO(31,40,0,1), XO_MASK, PPC, { RT, RB, RA } },
+{ "subfo", XO(31,40,1,0), XO_MASK, PPC, { RT, RA, RB } },
+{ "subo", XO(31,40,1,0), XO_MASK, PPC, { RT, RB, RA } },
+{ "subfo.", XO(31,40,1,1), XO_MASK, PPC, { RT, RA, RB } },
+{ "subo.", XO(31,40,1,1), XO_MASK, PPC, { RT, RB, RA } },
+
+{ "ldux", X(31,53), X_MASK, PPC|B64, { RT, RAL, RB } },
+
+{ "dcbst", X(31,54), XRT_MASK, PPC, { RA, RB } },
+
+{ "lwzux", X(31,55), X_MASK, PPC, { RT, RAL, RB } },
+{ "lux", X(31,55), X_MASK, POWER, { RT, RA, RB } },
+
+{ "cntlzd", XRC(31,58,0), XRB_MASK, PPC|B64, { RA, RS } },
+{ "cntlzd.", XRC(31,58,1), XRB_MASK, PPC|B64, { RA, RS } },
+
+{ "andc", XRC(31,60,0), X_MASK, PPC|POWER, { RA, RS, RB } },
+{ "andc.", XRC(31,60,1), X_MASK, PPC|POWER, { RA, RS, RB } },
+
+{ "tdlgt", XTO(31,68,TOLGT), XTO_MASK, PPC|B64, { RA, RB } },
+{ "tdllt", XTO(31,68,TOLLT), XTO_MASK, PPC|B64, { RA, RB } },
+{ "tdeq", XTO(31,68,TOEQ), XTO_MASK, PPC|B64, { RA, RB } },
+{ "tdlge", XTO(31,68,TOLGE), XTO_MASK, PPC|B64, { RA, RB } },
+{ "tdlnl", XTO(31,68,TOLNL), XTO_MASK, PPC|B64, { RA, RB } },
+{ "tdlle", XTO(31,68,TOLLE), XTO_MASK, PPC|B64, { RA, RB } },
+{ "tdlng", XTO(31,68,TOLNG), XTO_MASK, PPC|B64, { RA, RB } },
+{ "tdgt", XTO(31,68,TOGT), XTO_MASK, PPC|B64, { RA, RB } },
+{ "tdge", XTO(31,68,TOGE), XTO_MASK, PPC|B64, { RA, RB } },
+{ "tdnl", XTO(31,68,TONL), XTO_MASK, PPC|B64, { RA, RB } },
+{ "tdlt", XTO(31,68,TOLT), XTO_MASK, PPC|B64, { RA, RB } },
+{ "tdle", XTO(31,68,TOLE), XTO_MASK, PPC|B64, { RA, RB } },
+{ "tdng", XTO(31,68,TONG), XTO_MASK, PPC|B64, { RA, RB } },
+{ "tdne", XTO(31,68,TONE), XTO_MASK, PPC|B64, { RA, RB } },
+{ "td", X(31,68), X_MASK, PPC|B64, { TO, RA, RB } },
+
+{ "mulhd", XO(31,73,0,0), XO_MASK, PPC|B64, { RT, RA, RB } },
+{ "mulhd.", XO(31,73,0,1), XO_MASK, PPC|B64, { RT, RA, RB } },
+
+{ "mulhw", XO(31,75,0,0), XO_MASK, PPC, { RT, RA, RB } },
+{ "mulhw.", XO(31,75,0,1), XO_MASK, PPC, { RT, RA, RB } },
+
+{ "mfmsr", X(31,83), XRARB_MASK, PPC|POWER, { RT } },
+
+{ "ldarx", X(31,84), X_MASK, PPC|B64, { RT, RA, RB } },
+
+{ "dcbf", X(31,86), XRT_MASK, PPC, { RA, RB } },
+
+{ "lbzx", X(31,87), X_MASK, PPC|POWER, { RT, RA, RB } },
+
+{ "neg", XO(31,104,0,0), XORB_MASK, PPC|POWER, { RT, RA } },
+{ "neg.", XO(31,104,0,1), XORB_MASK, PPC|POWER, { RT, RA } },
+{ "nego", XO(31,104,1,0), XORB_MASK, PPC|POWER, { RT, RA } },
+{ "nego.", XO(31,104,1,1), XORB_MASK, PPC|POWER, { RT, RA } },
+
+{ "mul", XO(31,107,0,0), XO_MASK, POWER|M601, { RT, RA, RB } },
+{ "mul.", XO(31,107,0,1), XO_MASK, POWER|M601, { RT, RA, RB } },
+{ "mulo", XO(31,107,1,0), XO_MASK, POWER|M601, { RT, RA, RB } },
+{ "mulo.", XO(31,107,1,1), XO_MASK, POWER|M601, { RT, RA, RB } },
+
+{ "clf", X(31,118), XRB_MASK, POWER, { RT, RA } },
+
+{ "lbzux", X(31,119), X_MASK, PPC|POWER, { RT, RAL, RB } },
+
+{ "not", XRC(31,124,0), X_MASK, PPC|POWER, { RA, RS, RBS } },
+{ "nor", XRC(31,124,0), X_MASK, PPC|POWER, { RA, RS, RB } },
+{ "not.", XRC(31,124,1), X_MASK, PPC|POWER, { RA, RS, RBS } },
+{ "nor.", XRC(31,124,1), X_MASK, PPC|POWER, { RA, RS, RB } },
+
+{ "subfe", XO(31,136,0,0), XO_MASK, PPC, { RT, RA, RB } },
+{ "sfe", XO(31,136,0,0), XO_MASK, POWER, { RT, RA, RB } },
+{ "subfe.", XO(31,136,0,1), XO_MASK, PPC, { RT, RA, RB } },
+{ "sfe.", XO(31,136,0,1), XO_MASK, POWER, { RT, RA, RB } },
+{ "subfeo", XO(31,136,1,0), XO_MASK, PPC, { RT, RA, RB } },
+{ "sfeo", XO(31,136,1,0), XO_MASK, POWER, { RT, RA, RB } },
+{ "subfeo.", XO(31,136,1,1), XO_MASK, PPC, { RT, RA, RB } },
+{ "sfeo.", XO(31,136,1,1), XO_MASK, POWER, { RT, RA, RB } },
+
+{ "adde", XO(31,138,0,0), XO_MASK, PPC, { RT, RA, RB } },
+{ "ae", XO(31,138,0,0), XO_MASK, POWER, { RT, RA, RB } },
+{ "adde.", XO(31,138,0,1), XO_MASK, PPC, { RT, RA, RB } },
+{ "ae.", XO(31,138,0,1), XO_MASK, POWER, { RT, RA, RB } },
+{ "addeo", XO(31,138,1,0), XO_MASK, PPC, { RT, RA, RB } },
+{ "aeo", XO(31,138,1,0), XO_MASK, POWER, { RT, RA, RB } },
+{ "addeo.", XO(31,138,1,1), XO_MASK, PPC, { RT, RA, RB } },
+{ "aeo.", XO(31,138,1,1), XO_MASK, POWER, { RT, RA, RB } },
+
+{ "mtcr", XFXM(31,144,0xff), XFXFXM_MASK|FXM_MASK, PPC|POWER, { RS }},
+{ "mtcrf", X(31,144), XFXFXM_MASK, PPC|POWER, { FXM, RS } },
+
+{ "mtmsr", X(31,146), XRARB_MASK, PPC|POWER, { RS } },
+
+{ "stdx", X(31,149), X_MASK, PPC|B64, { RS, RA, RB } },
+
+{ "stwcx.", XRC(31,150,1), X_MASK, PPC, { RS, RA, RB } },
+
+{ "stwx", X(31,151), X_MASK, PPC, { RS, RA, RB } },
+{ "stx", X(31,151), X_MASK, POWER, { RS, RA, RB } },
+
+{ "slq", XRC(31,152,0), X_MASK, POWER|M601, { RA, RS, RB } },
+{ "slq.", XRC(31,152,1), X_MASK, POWER|M601, { RA, RS, RB } },
+
+{ "sle", XRC(31,153,0), X_MASK, POWER|M601, { RA, RS, RB } },
+{ "sle.", XRC(31,153,1), X_MASK, POWER|M601, { RA, RS, RB } },
+
+{ "stdux", X(31,181), X_MASK, PPC|B64, { RS, RAS, RB } },
+
+{ "stwux", X(31,183), X_MASK, PPC, { RS, RAS, RB } },
+{ "stux", X(31,183), X_MASK, POWER, { RS, RA, RB } },
+
+{ "sliq", XRC(31,184,0), X_MASK, POWER|M601, { RA, RS, SH } },
+{ "sliq.", XRC(31,184,1), X_MASK, POWER|M601, { RA, RS, SH } },
+
+{ "subfze", XO(31,200,0,0), XORB_MASK, PPC, { RT, RA } },
+{ "sfze", XO(31,200,0,0), XORB_MASK, POWER, { RT, RA } },
+{ "subfze.", XO(31,200,0,1), XORB_MASK, PPC, { RT, RA } },
+{ "sfze.", XO(31,200,0,1), XORB_MASK, POWER, { RT, RA } },
+{ "subfzeo", XO(31,200,1,0), XORB_MASK, PPC, { RT, RA } },
+{ "sfzeo", XO(31,200,1,0), XORB_MASK, POWER, { RT, RA } },
+{ "subfzeo.",XO(31,200,1,1), XORB_MASK, PPC, { RT, RA } },
+{ "sfzeo.", XO(31,200,1,1), XORB_MASK, POWER, { RT, RA } },
+
+{ "addze", XO(31,202,0,0), XORB_MASK, PPC, { RT, RA } },
+{ "aze", XO(31,202,0,0), XORB_MASK, POWER, { RT, RA } },
+{ "addze.", XO(31,202,0,1), XORB_MASK, PPC, { RT, RA } },
+{ "aze.", XO(31,202,0,1), XORB_MASK, POWER, { RT, RA } },
+{ "addzeo", XO(31,202,1,0), XORB_MASK, PPC, { RT, RA } },
+{ "azeo", XO(31,202,1,0), XORB_MASK, POWER, { RT, RA } },
+{ "addzeo.", XO(31,202,1,1), XORB_MASK, PPC, { RT, RA } },
+{ "azeo.", XO(31,202,1,1), XORB_MASK, POWER, { RT, RA } },
+
+{ "mtsr", X(31,210), XRB_MASK|(1<<20), PPC|POWER|B32, { SR, RS } },
+
+{ "stdcx.", XRC(31,214,1), X_MASK, PPC|B64, { RS, RA, RB } },
+
+{ "stbx", X(31,215), X_MASK, PPC|POWER, { RS, RA, RB } },
+
+{ "sllq", XRC(31,216,0), X_MASK, POWER|M601, { RA, RS, RB } },
+{ "sllq.", XRC(31,216,1), X_MASK, POWER|M601, { RA, RS, RB } },
+
+{ "sleq", XRC(31,217,0), X_MASK, POWER|M601, { RA, RS, RB } },
+{ "sleq.", XRC(31,217,1), X_MASK, POWER|M601, { RA, RS, RB } },
+
+{ "subfme", XO(31,232,0,0), XORB_MASK, PPC, { RT, RA } },
+{ "sfme", XO(31,232,0,0), XORB_MASK, POWER, { RT, RA } },
+{ "subfme.", XO(31,232,0,1), XORB_MASK, PPC, { RT, RA } },
+{ "sfme.", XO(31,232,0,1), XORB_MASK, POWER, { RT, RA } },
+{ "subfmeo", XO(31,232,1,0), XORB_MASK, PPC, { RT, RA } },
+{ "sfmeo", XO(31,232,1,0), XORB_MASK, POWER, { RT, RA } },
+{ "subfmeo.",XO(31,232,1,1), XORB_MASK, PPC, { RT, RA } },
+{ "sfmeo.", XO(31,232,1,1), XORB_MASK, POWER, { RT, RA } },
+
+{ "mulld", XO(31,233,0,0), XO_MASK, PPC|B64, { RT, RA, RB } },
+{ "mulld.", XO(31,233,0,1), XO_MASK, PPC|B64, { RT, RA, RB } },
+{ "mulldo", XO(31,233,1,0), XO_MASK, PPC|B64, { RT, RA, RB } },
+{ "mulldo.", XO(31,233,1,1), XO_MASK, PPC|B64, { RT, RA, RB } },
+
+{ "addme", XO(31,234,0,0), XORB_MASK, PPC, { RT, RA } },
+{ "ame", XO(31,234,0,0), XORB_MASK, POWER, { RT, RA } },
+{ "addme.", XO(31,234,0,1), XORB_MASK, PPC, { RT, RA } },
+{ "ame.", XO(31,234,0,1), XORB_MASK, POWER, { RT, RA } },
+{ "addmeo", XO(31,234,1,0), XORB_MASK, PPC, { RT, RA } },
+{ "ameo", XO(31,234,1,0), XORB_MASK, POWER, { RT, RA } },
+{ "addmeo.", XO(31,234,1,1), XORB_MASK, PPC, { RT, RA } },
+{ "ameo.", XO(31,234,1,1), XORB_MASK, POWER, { RT, RA } },
+
+{ "mullw", XO(31,235,0,0), XO_MASK, PPC, { RT, RA, RB } },
+{ "muls", XO(31,235,0,0), XO_MASK, POWER, { RT, RA, RB } },
+{ "mullw.", XO(31,235,0,1), XO_MASK, PPC, { RT, RA, RB } },
+{ "muls.", XO(31,235,0,1), XO_MASK, POWER, { RT, RA, RB } },
+{ "mullwo", XO(31,235,1,0), XO_MASK, PPC, { RT, RA, RB } },
+{ "mulso", XO(31,235,1,0), XO_MASK, POWER, { RT, RA, RB } },
+{ "mullwo.", XO(31,235,1,1), XO_MASK, PPC, { RT, RA, RB } },
+{ "mulso.", XO(31,235,1,1), XO_MASK, POWER, { RT, RA, RB } },
+
+{ "mtsrin", X(31,242), XRA_MASK, PPC|B32, { RS, RB } },
+{ "mtsri", X(31,242), XRA_MASK, POWER|B32, { RS, RB } },
+
+{ "dcbtst", X(31,246), XRT_MASK, PPC, { RA, RB } },
+
+{ "stbux", X(31,247), X_MASK, PPC|POWER, { RS, RAS, RB } },
+
+{ "slliq", XRC(31,248,0), X_MASK, POWER|M601, { RA, RS, SH } },
+{ "slliq.", XRC(31,248,1), X_MASK, POWER|M601, { RA, RS, SH } },
+
+{ "doz", XO(31,264,0,0), XO_MASK, POWER|M601, { RT, RA, RB } },
+{ "doz.", XO(31,264,0,1), XO_MASK, POWER|M601, { RT, RA, RB } },
+{ "dozo", XO(31,264,1,0), XO_MASK, POWER|M601, { RT, RA, RB } },
+{ "dozo.", XO(31,264,1,1), XO_MASK, POWER|M601, { RT, RA, RB } },
+
+{ "add", XO(31,266,0,0), XO_MASK, PPC, { RT, RA, RB } },
+{ "cax", XO(31,266,0,0), XO_MASK, POWER, { RT, RA, RB } },
+{ "add.", XO(31,266,0,1), XO_MASK, PPC, { RT, RA, RB } },
+{ "cax.", XO(31,266,0,1), XO_MASK, POWER, { RT, RA, RB } },
+{ "addo", XO(31,266,1,0), XO_MASK, PPC, { RT, RA, RB } },
+{ "caxo", XO(31,266,1,0), XO_MASK, POWER, { RT, RA, RB } },
+{ "addo.", XO(31,266,1,1), XO_MASK, PPC, { RT, RA, RB } },
+{ "caxo.", XO(31,266,1,1), XO_MASK, POWER, { RT, RA, RB } },
+
+{ "lscbx", XRC(31,277,0), X_MASK, POWER|M601, { RT, RA, RB } },
+{ "lscbx.", XRC(31,277,1), X_MASK, POWER|M601, { RT, RA, RB } },
+
+{ "dcbt", X(31,278), XRT_MASK, PPC, { RA, RB } },
+
+{ "lhzx", X(31,279), X_MASK, PPC|POWER, { RT, RA, RB } },
+
+{ "icbt", X(31,262), XRT_MASK, PPC, { RA, RB } },
+
+{ "eqv", XRC(31,284,0), X_MASK, PPC|POWER, { RA, RS, RB } },
+{ "eqv.", XRC(31,284,1), X_MASK, PPC|POWER, { RA, RS, RB } },
+
+{ "tlbie", X(31,306), XRTRA_MASK, PPC, { RB } },
+{ "tlbi", X(31,306), XRTRA_MASK, POWER, { RB } },
+
+{ "eciwx", X(31,310), X_MASK, PPC, { RT, RA, RB } },
+
+{ "lhzux", X(31,311), X_MASK, PPC|POWER, { RT, RAL, RB } },
+
+{ "xor", XRC(31,316,0), X_MASK, PPC|POWER, { RA, RS, RB } },
+{ "xor.", XRC(31,316,1), X_MASK, PPC|POWER, { RA, RS, RB } },
+
+{ "mfdcr", X(31,323), X_MASK, PPC, { RT, SPR } },
+
+{ "div", XO(31,331,0,0), XO_MASK, POWER|M601, { RT, RA, RB } },
+{ "div.", XO(31,331,0,1), XO_MASK, POWER|M601, { RT, RA, RB } },
+{ "divo", XO(31,331,1,0), XO_MASK, POWER|M601, { RT, RA, RB } },
+{ "divo.", XO(31,331,1,1), XO_MASK, POWER|M601, { RT, RA, RB } },
+
+{ "mfmq", XSPR(31,339,0), XSPR_MASK, POWER|M601, { RT } },
+{ "mfxer", XSPR(31,339,1), XSPR_MASK, PPC|POWER, { RT } },
+{ "mfrtcu", XSPR(31,339,4), XSPR_MASK, PPC|POWER, { RT } },
+{ "mfrtcl", XSPR(31,339,5), XSPR_MASK, PPC|POWER, { RT } },
+{ "mfdec", XSPR(31,339,6), XSPR_MASK, POWER|M601, { RT } },
+{ "mflr", XSPR(31,339,8), XSPR_MASK, PPC|POWER, { RT } },
+{ "mfctr", XSPR(31,339,9), XSPR_MASK, PPC|POWER, { RT } },
+{ "mftid", XSPR(31,339,17), XSPR_MASK, POWER, { RT } },
+{ "mfdsisr", XSPR(31,339,18), XSPR_MASK, PPC|POWER, { RT } },
+{ "mfdar", XSPR(31,339,19), XSPR_MASK, PPC|POWER, { RT } },
+{ "mfdec", XSPR(31,339,22), XSPR_MASK, PPC, { RT } },
+{ "mfsdr0", XSPR(31,339,24), XSPR_MASK, POWER, { RT } },
+{ "mfsdr1", XSPR(31,339,25), XSPR_MASK, PPC|POWER, { RT } },
+{ "mfsrr0", XSPR(31,339,26), XSPR_MASK, PPC|POWER, { RT } },
+{ "mfsrr1", XSPR(31,339,27), XSPR_MASK, PPC|POWER, { RT } },
+{ "mfsprg", XSPR(31,339,272), XSPRG_MASK, PPC, { RT, SPRG } },
+{ "mfasr", XSPR(31,339,280), XSPR_MASK, PPC|B64, { RT } },
+{ "mfear", XSPR(31,339,282), XSPR_MASK, PPC, { RT } },
+{ "mfpvr", XSPR(31,339,287), XSPR_MASK, PPC, { RT } },
+{ "mfibatu", XSPR(31,339,528), XSPRBAT_MASK, PPC, { RT, SPRBAT } },
+{ "mfibatl", XSPR(31,339,529), XSPRBAT_MASK, PPC, { RT, SPRBAT } },
+{ "mfdbatu", XSPR(31,339,536), XSPRBAT_MASK, PPC, { RT, SPRBAT } },
+{ "mfdbatl", XSPR(31,339,537), XSPRBAT_MASK, PPC, { RT, SPRBAT } },
+{ "mfspr", X(31,339), X_MASK, PPC|POWER, { RT, SPR } },
+
+{ "lwax", X(31,341), X_MASK, PPC|B64, { RT, RA, RB } },
+
+{ "lhax", X(31,343), X_MASK, PPC|POWER, { RT, RA, RB } },
+
+{ "dccci", X(31,454), XRT_MASK, PPC, { RA, RB } },
+
+{ "abs", XO(31,360,0,0), XORB_MASK, POWER|M601, { RT, RA } },
+{ "abs.", XO(31,360,0,1), XORB_MASK, POWER|M601, { RT, RA } },
+{ "abso", XO(31,360,1,0), XORB_MASK, POWER|M601, { RT, RA } },
+{ "abso.", XO(31,360,1,1), XORB_MASK, POWER|M601, { RT, RA } },
+
+{ "divs", XO(31,363,0,0), XO_MASK, POWER|M601, { RT, RA, RB } },
+{ "divs.", XO(31,363,0,1), XO_MASK, POWER|M601, { RT, RA, RB } },
+{ "divso", XO(31,363,1,0), XO_MASK, POWER|M601, { RT, RA, RB } },
+{ "divso.", XO(31,363,1,1), XO_MASK, POWER|M601, { RT, RA, RB } },
+
+{ "tlbia", X(31,370), 0xffffffff, PPC, { 0 } },
+
+{ "mftbu", XSPR(31,371,269), XSPR_MASK, PPC, { RT } },
+{ "mftb", X(31,371), X_MASK, PPC, { RT, TBR } },
+
+{ "lwaux", X(31,373), X_MASK, PPC|B64, { RT, RAL, RB } },
+
+{ "lhaux", X(31,375), X_MASK, PPC|POWER, { RT, RAL, RB } },
+
+{ "sthx", X(31,407), X_MASK, PPC|POWER, { RS, RA, RB } },
+
+{ "lfqx", X(31,791), X_MASK, POWER2, { FRT, RA, RB } },
+
+{ "lfqux", X(31,823), X_MASK, POWER2, { FRT, RA, RB } },
+
+{ "stfqx", X(31,919), X_MASK, POWER2, { FRS, RA, RB } },
+
+{ "stfqux", X(31,951), X_MASK, POWER2, { FRS, RA, RB } },
+
+{ "orc", XRC(31,412,0), X_MASK, PPC|POWER, { RA, RS, RB } },
+{ "orc.", XRC(31,412,1), X_MASK, PPC|POWER, { RA, RS, RB } },
+
+{ "sradi", XS(31,413,0), XS_MASK, PPC|B64, { RA, RS, SH6 } },
+{ "sradi.", XS(31,413,1), XS_MASK, PPC|B64, { RA, RS, SH6 } },
+
+{ "slbie", X(31,434), XRTRA_MASK, PPC|B64, { RB } },
+
+{ "ecowx", X(31,438), X_MASK, PPC, { RT, RA, RB } },
+
+{ "sthux", X(31,439), X_MASK, PPC|POWER, { RS, RAS, RB } },
+
+{ "mr", XRC(31,444,0), X_MASK, PPC|POWER, { RA, RS, RBS } },
+{ "or", XRC(31,444,0), X_MASK, PPC|POWER, { RA, RS, RB } },
+{ "mr.", XRC(31,444,1), X_MASK, PPC|POWER, { RA, RS, RBS } },
+{ "or.", XRC(31,444,1), X_MASK, PPC|POWER, { RA, RS, RB } },
+
+{ "mtdcr", X(31,451), X_MASK, PPC, { SPR, RS } },
+
+{ "divdu", XO(31,457,0,0), XO_MASK, PPC|B64, { RT, RA, RB } },
+{ "divdu.", XO(31,457,0,1), XO_MASK, PPC|B64, { RT, RA, RB } },
+{ "divduo", XO(31,457,1,0), XO_MASK, PPC|B64, { RT, RA, RB } },
+{ "divduo.", XO(31,457,1,1), XO_MASK, PPC|B64, { RT, RA, RB } },
+
+{ "divwu", XO(31,459,0,0), XO_MASK, PPC, { RT, RA, RB } },
+{ "divwu.", XO(31,459,0,1), XO_MASK, PPC, { RT, RA, RB } },
+{ "divwuo", XO(31,459,1,0), XO_MASK, PPC, { RT, RA, RB } },
+{ "divwuo.", XO(31,459,1,1), XO_MASK, PPC, { RT, RA, RB } },
+
+{ "mtmq", XSPR(31,467,0), XSPR_MASK, POWER|M601, { RS } },
+{ "mtxer", XSPR(31,467,1), XSPR_MASK, PPC|POWER, { RS } },
+{ "mtlr", XSPR(31,467,8), XSPR_MASK, PPC|POWER, { RS } },
+{ "mtctr", XSPR(31,467,9), XSPR_MASK, PPC|POWER, { RS } },
+{ "mttid", XSPR(31,467,17), XSPR_MASK, POWER, { RS } },
+{ "mtdsisr", XSPR(31,467,18), XSPR_MASK, PPC|POWER, { RS } },
+{ "mtdar", XSPR(31,467,19), XSPR_MASK, PPC|POWER, { RS } },
+{ "mtrtcu", XSPR(31,467,20), XSPR_MASK, PPC|POWER, { RS } },
+{ "mtrtcl", XSPR(31,467,21), XSPR_MASK, PPC|POWER, { RS } },
+{ "mtdec", XSPR(31,467,22), XSPR_MASK, PPC|POWER, { RS } },
+{ "mtsdr0", XSPR(31,467,24), XSPR_MASK, POWER, { RS } },
+{ "mtsdr1", XSPR(31,467,25), XSPR_MASK, PPC|POWER, { RS } },
+{ "mtsrr0", XSPR(31,467,26), XSPR_MASK, PPC|POWER, { RS } },
+{ "mtsrr1", XSPR(31,467,27), XSPR_MASK, PPC|POWER, { RS } },
+{ "mtsprg", XSPR(31,467,272), XSPRG_MASK, PPC, { SPRG, RS } },
+{ "mtasr", XSPR(31,467,280), XSPR_MASK, PPC|B64, { RS } },
+{ "mtear", XSPR(31,467,282), XSPR_MASK, PPC, { RS } },
+{ "mttbl", XSPR(31,467,284), XSPR_MASK, PPC, { RS } },
+{ "mttbu", XSPR(31,467,285), XSPR_MASK, PPC, { RS } },
+{ "mtibatu", XSPR(31,467,528), XSPRBAT_MASK, PPC, { SPRBAT, RS } },
+{ "mtibatl", XSPR(31,467,529), XSPRBAT_MASK, PPC, { SPRBAT, RS } },
+{ "mtdbatu", XSPR(31,467,536), XSPRBAT_MASK, PPC, { SPRBAT, RS } },
+{ "mtdbatl", XSPR(31,467,537), XSPRBAT_MASK, PPC, { SPRBAT, RS } },
+{ "mtspr", X(31,467), X_MASK, PPC|POWER, { SPR, RS } },
+
+{ "dcbi", X(31,470), XRT_MASK, PPC, { RA, RB } },
+
+{ "nand", XRC(31,476,0), X_MASK, PPC|POWER, { RA, RS, RB } },
+{ "nand.", XRC(31,476,1), X_MASK, PPC|POWER, { RA, RS, RB } },
+
+{ "nabs", XO(31,488,0,0), XORB_MASK, POWER|M601, { RT, RA } },
+{ "nabs.", XO(31,488,0,1), XORB_MASK, POWER|M601, { RT, RA } },
+{ "nabso", XO(31,488,1,0), XORB_MASK, POWER|M601, { RT, RA } },
+{ "nabso.", XO(31,488,1,1), XORB_MASK, POWER|M601, { RT, RA } },
+
+{ "divd", XO(31,489,0,0), XO_MASK, PPC|B64, { RT, RA, RB } },
+{ "divd.", XO(31,489,0,1), XO_MASK, PPC|B64, { RT, RA, RB } },
+{ "divdo", XO(31,489,1,0), XO_MASK, PPC|B64, { RT, RA, RB } },
+{ "divdo.", XO(31,489,1,1), XO_MASK, PPC|B64, { RT, RA, RB } },
+
+{ "divw", XO(31,491,0,0), XO_MASK, PPC, { RT, RA, RB } },
+{ "divw.", XO(31,491,0,1), XO_MASK, PPC, { RT, RA, RB } },
+{ "divwo", XO(31,491,1,0), XO_MASK, PPC, { RT, RA, RB } },
+{ "divwo.", XO(31,491,1,1), XO_MASK, PPC, { RT, RA, RB } },
+
+{ "slbia", X(31,498), 0xffffffff, PPC|B64, { 0 } },
+
+{ "cli", X(31,502), XRB_MASK, POWER, { RT, RA } },
+
+{ "mcrxr", X(31,512), XRARB_MASK|(3<<21), PPC|POWER, { BF } },
+
+{ "clcs", X(31,531), XRB_MASK, POWER|M601, { RT, RA } },
+
+{ "lswx", X(31,533), X_MASK, PPC, { RT, RA, RB } },
+{ "lsx", X(31,533), X_MASK, POWER, { RT, RA, RB } },
+
+{ "lwbrx", X(31,534), X_MASK, PPC, { RT, RA, RB } },
+{ "lbrx", X(31,534), X_MASK, POWER, { RT, RA, RB } },
+
+{ "lfsx", X(31,535), X_MASK, PPC|POWER, { FRT, RA, RB } },
+
+{ "srw", XRC(31,536,0), X_MASK, PPC, { RA, RS, RB } },
+{ "sr", XRC(31,536,0), X_MASK, POWER, { RA, RS, RB } },
+{ "srw.", XRC(31,536,1), X_MASK, PPC, { RA, RS, RB } },
+{ "sr.", XRC(31,536,1), X_MASK, POWER, { RA, RS, RB } },
+
+{ "rrib", XRC(31,537,0), X_MASK, POWER|M601, { RA, RS, RB } },
+{ "rrib.", XRC(31,537,1), X_MASK, POWER|M601, { RA, RS, RB } },
+
+{ "srd", XRC(31,539,0), X_MASK, PPC|B64, { RA, RS, RB } },
+{ "srd.", XRC(31,539,1), X_MASK, PPC|B64, { RA, RS, RB } },
+
+{ "maskir", XRC(31,541,0), X_MASK, POWER|M601, { RA, RS, RB } },
+{ "maskir.", XRC(31,541,1), X_MASK, POWER|M601, { RA, RS, RB } },
+
+{ "tlbsync", X(31,566), 0xffffffff, PPC, { 0 } },
+
+{ "lfsux", X(31,567), X_MASK, PPC|POWER, { FRT, RAS, RB } },
+
+{ "mfsr", X(31,595), XRB_MASK|(1<<20), PPC|POWER|B32, { RT, SR } },
+
+{ "lswi", X(31,597), X_MASK, PPC, { RT, RA, NB } },
+{ "lsi", X(31,597), X_MASK, POWER, { RT, RA, NB } },
+
+{ "sync", X(31,598), 0xffffffff, PPC, { 0 } },
+{ "dcs", X(31,598), 0xffffffff, POWER, { 0 } },
+
+{ "lfdx", X(31,599), X_MASK, PPC|POWER, { FRT, RA, RB } },
+
+{ "mfsri", X(31,627), X_MASK, POWER, { RT, RA, RB } },
+
+{ "dclst", X(31,630), XRB_MASK, POWER, { RS, RA } },
+
+{ "lfdux", X(31,631), X_MASK, PPC|POWER, { FRT, RAS, RB } },
+
+{ "mfsrin", X(31,659), XRA_MASK, PPC|B32, { RT, RB } },
+
+{ "stswx", X(31,661), X_MASK, PPC, { RS, RA, RB } },
+{ "stsx", X(31,661), X_MASK, POWER, { RS, RA, RB } },
+
+{ "stwbrx", X(31,662), X_MASK, PPC, { RS, RA, RB } },
+{ "stbrx", X(31,662), X_MASK, POWER, { RS, RA, RB } },
+
+{ "stfsx", X(31,663), X_MASK, PPC|POWER, { FRS, RA, RB } },
+
+{ "srq", XRC(31,664,0), X_MASK, POWER|M601, { RA, RS, RB } },
+{ "srq.", XRC(31,664,1), X_MASK, POWER|M601, { RA, RS, RB } },
+
+{ "sre", XRC(31,665,0), X_MASK, POWER|M601, { RA, RS, RB } },
+{ "sre.", XRC(31,665,1), X_MASK, POWER|M601, { RA, RS, RB } },
+
+{ "stfsux", X(31,695), X_MASK, PPC|POWER, { FRS, RAS, RB } },
+
+{ "sriq", XRC(31,696,0), X_MASK, POWER|M601, { RA, RS, SH } },
+{ "sriq.", XRC(31,696,1), X_MASK, POWER|M601, { RA, RS, SH } },
+
+{ "stswi", X(31,725), X_MASK, PPC, { RS, RA, NB } },
+{ "stsi", X(31,725), X_MASK, POWER, { RS, RA, NB } },
+
+{ "stfdx", X(31,727), X_MASK, PPC|POWER, { FRS, RA, RB } },
+
+{ "srlq", XRC(31,728,0), X_MASK, POWER|M601, { RA, RS, RB } },
+{ "srlq.", XRC(31,728,1), X_MASK, POWER|M601, { RA, RS, RB } },
+
+{ "sreq", XRC(31,729,0), X_MASK, POWER|M601, { RA, RS, RB } },
+{ "sreq.", XRC(31,729,1), X_MASK, POWER|M601, { RA, RS, RB } },
+
+{ "stfdux", X(31,759), X_MASK, PPC|POWER, { FRS, RAS, RB } },
+
+{ "srliq", XRC(31,760,0), X_MASK, POWER|M601, { RA, RS, SH } },
+{ "srliq.", XRC(31,760,1), X_MASK, POWER|M601, { RA, RS, SH } },
+
+{ "lhbrx", X(31,790), X_MASK, PPC|POWER, { RT, RA, RB } },
+
+{ "sraw", XRC(31,792,0), X_MASK, PPC, { RA, RS, RB } },
+{ "sra", XRC(31,792,0), X_MASK, POWER, { RA, RS, RB } },
+{ "sraw.", XRC(31,792,1), X_MASK, PPC, { RA, RS, RB } },
+{ "sra.", XRC(31,792,1), X_MASK, POWER, { RA, RS, RB } },
+
+{ "srad", XRC(31,794,0), X_MASK, PPC|B64, { RA, RS, RB } },
+{ "srad.", XRC(31,794,1), X_MASK, PPC|B64, { RA, RS, RB } },
+
+{ "rac", X(31,818), X_MASK, POWER, { RT, RA, RB } },
+
+{ "srawi", XRC(31,824,0), X_MASK, PPC, { RA, RS, SH } },
+{ "srai", XRC(31,824,0), X_MASK, POWER, { RA, RS, SH } },
+{ "srawi.", XRC(31,824,1), X_MASK, PPC, { RA, RS, SH } },
+{ "srai.", XRC(31,824,1), X_MASK, POWER, { RA, RS, SH } },
+
+{ "eieio", X(31,854), 0xffffffff, PPC, { 0 } },
+
+{ "sthbrx", X(31,918), X_MASK, PPC|POWER, { RS, RA, RB } },
+
+{ "sraq", XRC(31,920,0), X_MASK, POWER|M601, { RA, RS, RB } },
+{ "sraq.", XRC(31,920,1), X_MASK, POWER|M601, { RA, RS, RB } },
+
+{ "srea", XRC(31,921,0), X_MASK, POWER|M601, { RA, RS, RB } },
+{ "srea.", XRC(31,921,1), X_MASK, POWER|M601, { RA, RS, RB } },
+
+{ "extsh", XRC(31,922,0), XRB_MASK, PPC, { RA, RS } },
+{ "exts", XRC(31,922,0), XRB_MASK, POWER, { RA, RS } },
+{ "extsh.", XRC(31,922,1), XRB_MASK, PPC, { RA, RS } },
+{ "exts.", XRC(31,922,1), XRB_MASK, POWER, { RA, RS } },
+
+{ "sraiq", XRC(31,952,0), X_MASK, POWER|M601, { RA, RS, SH } },
+{ "sraiq.", XRC(31,952,1), X_MASK, POWER|M601, { RA, RS, SH } },
+
+{ "extsb", XRC(31,954,0), XRB_MASK, PPC, { RA, RS} },
+{ "extsb.", XRC(31,954,1), XRB_MASK, PPC, { RA, RS} },
+
+{ "iccci", X(31,966), XRT_MASK, PPC, { RA, RB } },
+
+{ "icbi", X(31,982), XRT_MASK, PPC, { RA, RB } },
+
+{ "stfiwx", X(31,983), X_MASK, PPC, { FRS, RA, RB } },
+
+{ "extsw", XRC(31,986,0), XRB_MASK, PPC, { RA, RS } },
+{ "extsw.", XRC(31,986,1), XRB_MASK, PPC, { RA, RS } },
+
+{ "dcbz", X(31,1014), XRT_MASK, PPC, { RA, RB } },
+{ "dclz", X(31,1014), XRT_MASK, PPC, { RA, RB } },
+
+{ "lwz", OP(32), OP_MASK, PPC, { RT, D, RA } },
+{ "l", OP(32), OP_MASK, POWER, { RT, D, RA } },
+
+{ "lwzu", OP(33), OP_MASK, PPC, { RT, D, RAL } },
+{ "lu", OP(33), OP_MASK, POWER, { RT, D, RA } },
+
+{ "lbz", OP(34), OP_MASK, PPC|POWER, { RT, D, RA } },
+
+{ "lbzu", OP(35), OP_MASK, PPC|POWER, { RT, D, RAL } },
+
+{ "stw", OP(36), OP_MASK, PPC, { RS, D, RA } },
+{ "st", OP(36), OP_MASK, POWER, { RS, D, RA } },
+
+{ "stwu", OP(37), OP_MASK, PPC, { RS, D, RAS } },
+{ "stu", OP(37), OP_MASK, POWER, { RS, D, RA } },
+
+{ "stb", OP(38), OP_MASK, PPC|POWER, { RS, D, RA } },
+
+{ "stbu", OP(39), OP_MASK, PPC|POWER, { RS, D, RAS } },
+
+{ "lhz", OP(40), OP_MASK, PPC|POWER, { RT, D, RA } },
+
+{ "lhzu", OP(41), OP_MASK, PPC|POWER, { RT, D, RAL } },
+
+{ "lha", OP(42), OP_MASK, PPC|POWER, { RT, D, RA } },
+
+{ "lhau", OP(43), OP_MASK, PPC|POWER, { RT, D, RAL } },
+
+{ "sth", OP(44), OP_MASK, PPC|POWER, { RS, D, RA } },
+
+{ "sthu", OP(45), OP_MASK, PPC|POWER, { RS, D, RAS } },
+
+{ "lmw", OP(46), OP_MASK, PPC, { RT, D, RAM } },
+{ "lm", OP(46), OP_MASK, POWER, { RT, D, RA } },
+
+{ "stmw", OP(47), OP_MASK, PPC, { RS, D, RA } },
+{ "stm", OP(47), OP_MASK, POWER, { RS, D, RA } },
+
+{ "lfs", OP(48), OP_MASK, PPC|POWER, { FRT, D, RA } },
+
+{ "lfsu", OP(49), OP_MASK, PPC|POWER, { FRT, D, RAS } },
+
+{ "lfd", OP(50), OP_MASK, PPC|POWER, { FRT, D, RA } },
+
+{ "lfdu", OP(51), OP_MASK, PPC|POWER, { FRT, D, RAS } },
+
+{ "stfs", OP(52), OP_MASK, PPC|POWER, { FRS, D, RA } },
+
+{ "stfsu", OP(53), OP_MASK, PPC|POWER, { FRS, D, RAS } },
+
+{ "stfd", OP(54), OP_MASK, PPC|POWER, { FRS, D, RA } },
+
+{ "stfdu", OP(55), OP_MASK, PPC|POWER, { FRS, D, RAS } },
+
+{ "lfq", OP(56), OP_MASK, POWER2, { FRT, D, RA } },
+
+{ "lfqu", OP(57), OP_MASK, POWER2, { FRT, D, RA } },
+
+{ "ld", DSO(58,0), DS_MASK, PPC|B64, { RT, DS, RA } },
+
+{ "ldu", DSO(58,1), DS_MASK, PPC|B64, { RT, DS, RAL } },
+
+{ "lwa", DSO(58,2), DS_MASK, PPC|B64, { RT, DS, RA } },
+
+{ "fdivs", A(59,18,0), AFRC_MASK, PPC, { FRT, FRA, FRB } },
+{ "fdivs.", A(59,18,1), AFRC_MASK, PPC, { FRT, FRA, FRB } },
+
+{ "fsubs", A(59,20,0), AFRC_MASK, PPC, { FRT, FRA, FRB } },
+{ "fsubs.", A(59,20,1), AFRC_MASK, PPC, { FRT, FRA, FRB } },
+
+{ "fadds", A(59,21,0), AFRC_MASK, PPC, { FRT, FRA, FRB } },
+{ "fadds.", A(59,21,1), AFRC_MASK, PPC, { FRT, FRA, FRB } },
+
+{ "fsqrts", A(59,22,0), AFRAFRC_MASK, PPC, { FRT, FRB } },
+{ "fsqrts.", A(59,22,1), AFRAFRC_MASK, PPC, { FRT, FRB } },
+
+{ "fres", A(59,24,0), AFRAFRC_MASK, PPC, { FRT, FRB } },
+{ "fres.", A(59,24,1), AFRAFRC_MASK, PPC, { FRT, FRB } },
+
+{ "fmuls", A(59,25,0), AFRB_MASK, PPC, { FRT, FRA, FRC } },
+{ "fmuls.", A(59,25,1), AFRB_MASK, PPC, { FRT, FRA, FRC } },
+
+{ "fmsubs", A(59,28,0), A_MASK, PPC, { FRT,FRA,FRC,FRB } },
+{ "fmsubs.", A(59,28,1), A_MASK, PPC, { FRT,FRA,FRC,FRB } },
+
+{ "fmadds", A(59,29,0), A_MASK, PPC, { FRT,FRA,FRC,FRB } },
+{ "fmadds.", A(59,29,1), A_MASK, PPC, { FRT,FRA,FRC,FRB } },
+
+{ "fnmsubs", A(59,30,0), A_MASK, PPC, { FRT,FRA,FRC,FRB } },
+{ "fnmsubs.",A(59,30,1), A_MASK, PPC, { FRT,FRA,FRC,FRB } },
+
+{ "fnmadds", A(59,31,0), A_MASK, PPC, { FRT,FRA,FRC,FRB } },
+{ "fnmadds.",A(59,31,1), A_MASK, PPC, { FRT,FRA,FRC,FRB } },
+
+{ "stfq", OP(60), OP_MASK, POWER2, { FRS, D, RA } },
+
+{ "stfqu", OP(61), OP_MASK, POWER2, { FRS, D, RA } },
+
+{ "std", DSO(62,0), DS_MASK, PPC|B64, { RS, DS, RA } },
+
+{ "stdu", DSO(62,1), DS_MASK, PPC|B64, { RS, DS, RAS } },
+
+{ "fcmpu", X(63,0), X_MASK|(3<<21), PPC|POWER, { BF, FRA, FRB } },
+
+{ "frsp", XRC(63,12,0), XRA_MASK, PPC|POWER, { FRT, FRB } },
+{ "frsp.", XRC(63,12,1), XRA_MASK, PPC|POWER, { FRT, FRB } },
+
+{ "fctiw", XRC(63,14,0), XRA_MASK, PPC, { FRT, FRB } },
+{ "fcir", XRC(63,14,0), XRA_MASK, POWER2, { FRT, FRB } },
+{ "fctiw.", XRC(63,14,1), XRA_MASK, PPC, { FRT, FRB } },
+{ "fcir.", XRC(63,14,1), XRA_MASK, POWER2, { FRT, FRB } },
+
+{ "fctiwz", XRC(63,15,0), XRA_MASK, PPC, { FRT, FRB } },
+{ "fcirz", XRC(63,15,0), XRA_MASK, POWER2, { FRT, FRB } },
+{ "fctiwz.", XRC(63,15,1), XRA_MASK, PPC, { FRT, FRB } },
+{ "fcirz.", XRC(63,15,1), XRA_MASK, POWER2, { FRT, FRB } },
+
+{ "fdiv", A(63,18,0), AFRC_MASK, PPC, { FRT, FRA, FRB } },
+{ "fd", A(63,18,0), AFRC_MASK, POWER, { FRT, FRA, FRB } },
+{ "fdiv.", A(63,18,1), AFRC_MASK, PPC, { FRT, FRA, FRB } },
+{ "fd.", A(63,18,1), AFRC_MASK, POWER, { FRT, FRA, FRB } },
+
+{ "fsub", A(63,20,0), AFRC_MASK, PPC, { FRT, FRA, FRB } },
+{ "fs", A(63,20,0), AFRC_MASK, POWER, { FRT, FRA, FRB } },
+{ "fsub.", A(63,20,1), AFRC_MASK, PPC, { FRT, FRA, FRB } },
+{ "fs.", A(63,20,1), AFRC_MASK, POWER, { FRT, FRA, FRB } },
+
+{ "fadd", A(63,21,0), AFRC_MASK, PPC, { FRT, FRA, FRB } },
+{ "fa", A(63,21,0), AFRC_MASK, POWER, { FRT, FRA, FRB } },
+{ "fadd.", A(63,21,1), AFRC_MASK, PPC, { FRT, FRA, FRB } },
+{ "fa.", A(63,21,1), AFRC_MASK, POWER, { FRT, FRA, FRB } },
+
+{ "fsqrt", A(63,22,0), AFRAFRC_MASK, PPC|POWER2, { FRT, FRB } },
+{ "fsqrt.", A(63,22,1), AFRAFRC_MASK, PPC|POWER2, { FRT, FRB } },
+
+{ "fsel", A(63,23,0), A_MASK, PPC, { FRT,FRA,FRC,FRB } },
+{ "fsel.", A(63,23,1), A_MASK, PPC, { FRT,FRA,FRC,FRB } },
+
+{ "fmul", A(63,25,0), AFRB_MASK, PPC, { FRT, FRA, FRC } },
+{ "fm", A(63,25,0), AFRB_MASK, POWER, { FRT, FRA, FRC } },
+{ "fmul.", A(63,25,1), AFRB_MASK, PPC, { FRT, FRA, FRC } },
+{ "fm.", A(63,25,1), AFRB_MASK, POWER, { FRT, FRA, FRC } },
+
+{ "frsqrte", A(63,26,0), AFRAFRC_MASK, PPC, { FRT, FRB } },
+{ "frsqrte.",A(63,26,1), AFRAFRC_MASK, PPC, { FRT, FRB } },
+
+{ "fmsub", A(63,28,0), A_MASK, PPC, { FRT,FRA,FRC,FRB } },
+{ "fms", A(63,28,0), A_MASK, POWER, { FRT,FRA,FRC,FRB } },
+{ "fmsub.", A(63,28,1), A_MASK, PPC, { FRT,FRA,FRC,FRB } },
+{ "fms.", A(63,28,1), A_MASK, POWER, { FRT,FRA,FRC,FRB } },
+
+{ "fmadd", A(63,29,0), A_MASK, PPC, { FRT,FRA,FRC,FRB } },
+{ "fma", A(63,29,0), A_MASK, POWER, { FRT,FRA,FRC,FRB } },
+{ "fmadd.", A(63,29,1), A_MASK, PPC, { FRT,FRA,FRC,FRB } },
+{ "fma.", A(63,29,1), A_MASK, POWER, { FRT,FRA,FRC,FRB } },
+
+{ "fnmsub", A(63,30,0), A_MASK, PPC, { FRT,FRA,FRC,FRB } },
+{ "fnms", A(63,30,0), A_MASK, POWER, { FRT,FRA,FRC,FRB } },
+{ "fnmsub.", A(63,30,1), A_MASK, PPC, { FRT,FRA,FRC,FRB } },
+{ "fnms.", A(63,30,1), A_MASK, POWER, { FRT,FRA,FRC,FRB } },
+
+{ "fnmadd", A(63,31,0), A_MASK, PPC, { FRT,FRA,FRC,FRB } },
+{ "fnma", A(63,31,0), A_MASK, POWER, { FRT,FRA,FRC,FRB } },
+{ "fnmadd.", A(63,31,1), A_MASK, PPC, { FRT,FRA,FRC,FRB } },
+{ "fnma.", A(63,31,1), A_MASK, POWER, { FRT,FRA,FRC,FRB } },
+
+{ "fcmpo", X(63,30), X_MASK|(3<<21), PPC|POWER, { BF, FRA, FRB } },
+
+{ "mtfsb1", XRC(63,38,0), XRARB_MASK, PPC|POWER, { BT } },
+{ "mtfsb1.", XRC(63,38,1), XRARB_MASK, PPC|POWER, { BT } },
+
+{ "fneg", XRC(63,40,0), XRA_MASK, PPC|POWER, { FRT, FRB } },
+{ "fneg.", XRC(63,40,1), XRA_MASK, PPC|POWER, { FRT, FRB } },
+
+{ "mcrfs", X(63,64), XRB_MASK|(3<<21)|(3<<16), PPC|POWER, { BF, BFA } },
+
+{ "mtfsb0", XRC(63,70,0), XRARB_MASK, PPC|POWER, { BT } },
+{ "mtfsb0.", XRC(63,70,1), XRARB_MASK, PPC|POWER, { BT } },
+
+{ "fmr", XRC(63,72,0), XRA_MASK, PPC|POWER, { FRT, FRB } },
+{ "fmr.", XRC(63,72,1), XRA_MASK, PPC|POWER, { FRT, FRB } },
+
+{ "mtfsfi", XRC(63,134,0), XRA_MASK|(3<<21)|(1<<11), PPC|POWER, { BF, U } },
+{ "mtfsfi.", XRC(63,134,1), XRA_MASK|(3<<21)|(1<<11), PPC|POWER, { BF, U } },
+
+{ "fnabs", XRC(63,136,0), XRA_MASK, PPC|POWER, { FRT, FRB } },
+{ "fnabs.", XRC(63,136,1), XRA_MASK, PPC|POWER, { FRT, FRB } },
+
+{ "fabs", XRC(63,264,0), XRA_MASK, PPC|POWER, { FRT, FRB } },
+{ "fabs.", XRC(63,264,1), XRA_MASK, PPC|POWER, { FRT, FRB } },
+
+{ "mffs", XRC(63,583,0), XRARB_MASK, PPC|POWER, { FRT } },
+{ "mffs.", XRC(63,583,1), XRARB_MASK, PPC|POWER, { FRT } },
+
+{ "mtfsf", XFL(63,711,0), XFL_MASK, PPC|POWER, { FLM, FRB } },
+{ "mtfsf.", XFL(63,711,1), XFL_MASK, PPC|POWER, { FLM, FRB } },
+
+{ "fctid", XRC(63,814,0), XRA_MASK, PPC|B64, { FRT, FRB } },
+{ "fctid.", XRC(63,814,1), XRA_MASK, PPC|B64, { FRT, FRB } },
+
+{ "fctidz", XRC(63,815,0), XRA_MASK, PPC|B64, { FRT, FRB } },
+{ "fctidz.", XRC(63,815,1), XRA_MASK, PPC|B64, { FRT, FRB } },
+
+{ "fcfid", XRC(63,846,0), XRA_MASK, PPC|B64, { FRT, FRB } },
+{ "fcfid.", XRC(63,846,1), XRA_MASK, PPC|B64, { FRT, FRB } },
+
+};
+
+const int powerpc_num_opcodes =
+ sizeof (powerpc_opcodes) / sizeof (powerpc_opcodes[0]);
+
+/* The macro table. This is only used by the assembler. */
+
+const struct powerpc_macro powerpc_macros[] = {
+{ "extldi", 4, PPC|B64, "rldicr %0,%1,%3,(%2)-1" },
+{ "extldi.", 4, PPC|B64, "rldicr. %0,%1,%3,(%2)-1" },
+{ "extrdi", 4, PPC|B64, "rldicl %0,%1,(%2)+(%3),64-(%2)" },
+{ "extrdi.", 4, PPC|B64, "rldicl. %0,%1,(%2)+(%3),64-(%2)" },
+{ "insrdi", 4, PPC|B64, "rldimi %0,%1,64-((%2)+(%3)),%3" },
+{ "insrdi.", 4, PPC|B64, "rldimi. %0,%1,64-((%2)+(%3)),%3" },
+{ "rotrdi", 3, PPC|B64, "rldicl %0,%1,64-(%2),0" },
+{ "rotrdi.", 3, PPC|B64, "rldicl. %0,%1,64-(%2),0" },
+{ "sldi", 3, PPC|B64, "rldicr %0,%1,%2,63-(%2)" },
+{ "sldi.", 3, PPC|B64, "rldicr. %0,%1,%2,63-(%2)" },
+{ "srdi", 3, PPC|B64, "rldicl %0,%1,64-(%2),%2" },
+{ "srdi.", 3, PPC|B64, "rldicl. %0,%1,64-(%2),%2" },
+{ "clrrdi", 3, PPC|B64, "rldicr %0,%1,0,63-(%2)" },
+{ "clrrdi.", 3, PPC|B64, "rldicr. %0,%1,0,63-(%2)" },
+{ "clrlsldi",4, PPC|B64, "rldic %0,%1,%3,(%2)-(%3)" },
+{ "clrlsldi.",4, PPC|B64, "rldic. %0,%1,%3,(%2)-(%3)" },
+
+{ "extlwi", 4, PPC, "rlwinm %0,%1,%3,0,(%2)-1" },
+{ "extlwi.", 4, PPC, "rlwinm. %0,%1,%3,0,(%2)-1" },
+{ "extrwi", 4, PPC, "rlwinm %0,%1,(%2)+(%3),32-(%2),31" },
+{ "extrwi.", 4, PPC, "rlwinm. %0,%1,(%2)+(%3),32-(%2),31" },
+{ "inslwi", 4, PPC, "rlwimi %0,%1,32-(%3),%3,(%2)+(%3)-1" },
+{ "inslwi.", 4, PPC, "rlwimi. %0,%1,32-(%3),%3,(%2)+(%3)-1" },
+{ "insrwi", 4, PPC, "rlwimi %0,%1,32-((%2)+(%3)),%3,(%2)+(%3)-1" },
+{ "insrwi.", 4, PPC, "rlwimi. %0,%1,32-((%2)+(%3)),%3,(%2)+(%3)-1"},
+{ "rotrwi", 3, PPC, "rlwinm %0,%1,32-(%2),0,31" },
+{ "rotrwi.", 3, PPC, "rlwinm. %0,%1,32-(%2),0,31" },
+{ "slwi", 3, PPC, "rlwinm %0,%1,%2,0,31-(%2)" },
+{ "sli", 3, POWER, "rlinm %0,%1,%2,0,31-(%2)" },
+{ "slwi.", 3, PPC, "rlwinm. %0,%1,%2,0,31-(%2)" },
+{ "sli.", 3, POWER, "rlinm. %0,%1,%2,0,31-(%2)" },
+{ "srwi", 3, PPC, "rlwinm %0,%1,32-(%2),%2,31" },
+{ "sri", 3, POWER, "rlinm %0,%1,32-(%2),%2,31" },
+{ "srwi.", 3, PPC, "rlwinm. %0,%1,32-(%2),%2,31" },
+{ "sri.", 3, POWER, "rlinm. %0,%1,32-(%2),%2,31" },
+{ "clrrwi", 3, PPC, "rlwinm %0,%1,0,0,31-(%2)" },
+{ "clrrwi.", 3, PPC, "rlwinm. %0,%1,0,0,31-(%2)" },
+{ "clrlslwi",4, PPC, "rlwinm %0,%1,%3,(%2)-(%3),31-(%3)" },
+{ "clrlslwi.",4, PPC, "rlwinm. %0,%1,%3,(%2)-(%3),31-(%3)" },
+
+};
+
+const int powerpc_num_macros =
+ sizeof (powerpc_macros) / sizeof (powerpc_macros[0]);
diff --git a/arch/ppc/xmon/ppc.h b/arch/ppc/xmon/ppc.h
new file mode 100644
index 0000000..2345ecb
--- /dev/null
+++ b/arch/ppc/xmon/ppc.h
@@ -0,0 +1,240 @@
+/* ppc.h -- Header file for PowerPC opcode table
+ Copyright 1994 Free Software Foundation, Inc.
+ Written by Ian Lance Taylor, Cygnus Support
+
+This file is part of GDB, GAS, and the GNU binutils.
+
+GDB, GAS, and the GNU binutils are free software; you can redistribute
+them and/or modify them under the terms of the GNU General Public
+License as published by the Free Software Foundation; either version
+1, or (at your option) any later version.
+
+GDB, GAS, and the GNU binutils are distributed in the hope that they
+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 file; see the file COPYING. If not, write to the Free
+Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#ifndef PPC_H
+#define PPC_H
+
+/* The opcode table is an array of struct powerpc_opcode. */
+
+struct powerpc_opcode
+{
+ /* The opcode name. */
+ const char *name;
+
+ /* The opcode itself. Those bits which will be filled in with
+ operands are zeroes. */
+ unsigned long opcode;
+
+ /* The opcode mask. This is used by the disassembler. This is a
+ mask containing ones indicating those bits which must match the
+ opcode field, and zeroes indicating those bits which need not
+ match (and are presumably filled in by operands). */
+ unsigned long mask;
+
+ /* One bit flags for the opcode. These are used to indicate which
+ specific processors support the instructions. The defined values
+ are listed below. */
+ unsigned long flags;
+
+ /* An array of operand codes. Each code is an index into the
+ operand table. They appear in the order which the operands must
+ appear in assembly code, and are terminated by a zero. */
+ unsigned char operands[8];
+};
+
+/* The table itself is sorted by major opcode number, and is otherwise
+ in the order in which the disassembler should consider
+ instructions. */
+extern const struct powerpc_opcode powerpc_opcodes[];
+extern const int powerpc_num_opcodes;
+
+/* Values defined for the flags field of a struct powerpc_opcode. */
+
+/* Opcode is defined for the PowerPC architecture. */
+#define PPC_OPCODE_PPC (01)
+
+/* Opcode is defined for the POWER (RS/6000) architecture. */
+#define PPC_OPCODE_POWER (02)
+
+/* Opcode is defined for the POWER2 (Rios 2) architecture. */
+#define PPC_OPCODE_POWER2 (04)
+
+/* Opcode is only defined on 32 bit architectures. */
+#define PPC_OPCODE_32 (010)
+
+/* Opcode is only defined on 64 bit architectures. */
+#define PPC_OPCODE_64 (020)
+
+/* Opcode is supported by the Motorola PowerPC 601 processor. The 601
+ is assumed to support all PowerPC (PPC_OPCODE_PPC) instructions,
+ but it also supports many additional POWER instructions. */
+#define PPC_OPCODE_601 (040)
+
+/* A macro to extract the major opcode from an instruction. */
+#define PPC_OP(i) (((i) >> 26) & 0x3f)
+
+/* The operands table is an array of struct powerpc_operand. */
+
+struct powerpc_operand
+{
+ /* The number of bits in the operand. */
+ int bits;
+
+ /* How far the operand is left shifted in the instruction. */
+ int shift;
+
+ /* Insertion function. This is used by the assembler. To insert an
+ operand value into an instruction, check this field.
+
+ If it is NULL, execute
+ i |= (op & ((1 << o->bits) - 1)) << o->shift;
+ (i is the instruction which we are filling in, o is a pointer to
+ this structure, and op is the opcode value; this assumes twos
+ complement arithmetic).
+
+ If this field is not NULL, then simply call it with the
+ instruction and the operand value. It will return the new value
+ of the instruction. If the ERRMSG argument is not NULL, then if
+ the operand value is illegal, *ERRMSG will be set to a warning
+ string (the operand will be inserted in any case). If the
+ operand value is legal, *ERRMSG will be unchanged (most operands
+ can accept any value). */
+ unsigned long (*insert) PARAMS ((unsigned long instruction, long op,
+ const char **errmsg));
+
+ /* Extraction function. This is used by the disassembler. To
+ extract this operand type from an instruction, check this field.
+
+ If it is NULL, compute
+ op = ((i) >> o->shift) & ((1 << o->bits) - 1);
+ if ((o->flags & PPC_OPERAND_SIGNED) != 0
+ && (op & (1 << (o->bits - 1))) != 0)
+ op -= 1 << o->bits;
+ (i is the instruction, o is a pointer to this structure, and op
+ is the result; this assumes twos complement arithmetic).
+
+ If this field is not NULL, then simply call it with the
+ instruction value. It will return the value of the operand. If
+ the INVALID argument is not NULL, *INVALID will be set to
+ non-zero if this operand type can not actually be extracted from
+ this operand (i.e., the instruction does not match). If the
+ operand is valid, *INVALID will not be changed. */
+ long (*extract) PARAMS ((unsigned long instruction, int *invalid));
+
+ /* One bit syntax flags. */
+ unsigned long flags;
+};
+
+/* Elements in the table are retrieved by indexing with values from
+ the operands field of the powerpc_opcodes table. */
+
+extern const struct powerpc_operand powerpc_operands[];
+
+/* Values defined for the flags field of a struct powerpc_operand. */
+
+/* This operand takes signed values. */
+#define PPC_OPERAND_SIGNED (01)
+
+/* This operand takes signed values, but also accepts a full positive
+ range of values when running in 32 bit mode. That is, if bits is
+ 16, it takes any value from -0x8000 to 0xffff. In 64 bit mode,
+ this flag is ignored. */
+#define PPC_OPERAND_SIGNOPT (02)
+
+/* This operand does not actually exist in the assembler input. This
+ is used to support extended mnemonics such as mr, for which two
+ operands fields are identical. The assembler should call the
+ insert function with any op value. The disassembler should call
+ the extract function, ignore the return value, and check the value
+ placed in the valid argument. */
+#define PPC_OPERAND_FAKE (04)
+
+/* The next operand should be wrapped in parentheses rather than
+ separated from this one by a comma. This is used for the load and
+ store instructions which want their operands to look like
+ reg,displacement(reg)
+ */
+#define PPC_OPERAND_PARENS (010)
+
+/* This operand may use the symbolic names for the CR fields, which
+ are
+ lt 0 gt 1 eq 2 so 3 un 3
+ cr0 0 cr1 1 cr2 2 cr3 3
+ cr4 4 cr5 5 cr6 6 cr7 7
+ These may be combined arithmetically, as in cr2*4+gt. These are
+ only supported on the PowerPC, not the POWER. */
+#define PPC_OPERAND_CR (020)
+
+/* This operand names a register. The disassembler uses this to print
+ register names with a leading 'r'. */
+#define PPC_OPERAND_GPR (040)
+
+/* This operand names a floating point register. The disassembler
+ prints these with a leading 'f'. */
+#define PPC_OPERAND_FPR (0100)
+
+/* This operand is a relative branch displacement. The disassembler
+ prints these symbolically if possible. */
+#define PPC_OPERAND_RELATIVE (0200)
+
+/* This operand is an absolute branch address. The disassembler
+ prints these symbolically if possible. */
+#define PPC_OPERAND_ABSOLUTE (0400)
+
+/* This operand is optional, and is zero if omitted. This is used for
+ the optional BF and L fields in the comparison instructions. The
+ assembler must count the number of operands remaining on the line,
+ and the number of operands remaining for the opcode, and decide
+ whether this operand is present or not. The disassembler should
+ print this operand out only if it is not zero. */
+#define PPC_OPERAND_OPTIONAL (01000)
+
+/* This flag is only used with PPC_OPERAND_OPTIONAL. If this operand
+ is omitted, then for the next operand use this operand value plus
+ 1, ignoring the next operand field for the opcode. This wretched
+ hack is needed because the Power rotate instructions can take
+ either 4 or 5 operands. The disassembler should print this operand
+ out regardless of the PPC_OPERAND_OPTIONAL field. */
+#define PPC_OPERAND_NEXT (02000)
+
+/* This operand should be regarded as a negative number for the
+ purposes of overflow checking (i.e., the normal most negative
+ number is disallowed and one more than the normal most positive
+ number is allowed). This flag will only be set for a signed
+ operand. */
+#define PPC_OPERAND_NEGATIVE (04000)
+
+/* The POWER and PowerPC assemblers use a few macros. We keep them
+ with the operands table for simplicity. The macro table is an
+ array of struct powerpc_macro. */
+
+struct powerpc_macro
+{
+ /* The macro name. */
+ const char *name;
+
+ /* The number of operands the macro takes. */
+ unsigned int operands;
+
+ /* One bit flags for the opcode. These are used to indicate which
+ specific processors support the instructions. The values are the
+ same as those for the struct powerpc_opcode flags field. */
+ unsigned long flags;
+
+ /* A format string to turn the macro into a normal instruction.
+ Each %N in the string is replaced with operand number N (zero
+ based). */
+ const char *format;
+};
+
+extern const struct powerpc_macro powerpc_macros[];
+extern const int powerpc_num_macros;
+
+#endif /* PPC_H */
diff --git a/arch/ppc/xmon/privinst.h b/arch/ppc/xmon/privinst.h
new file mode 100644
index 0000000..93978c0
--- /dev/null
+++ b/arch/ppc/xmon/privinst.h
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 1996 Paul Mackerras.
+ */
+#include <linux/config.h>
+
+#define GETREG(reg) \
+ static inline int get_ ## reg (void) \
+ { int ret; asm volatile ("mf" #reg " %0" : "=r" (ret) :); return ret; }
+
+#define SETREG(reg) \
+ static inline void set_ ## reg (int val) \
+ { asm volatile ("mt" #reg " %0" : : "r" (val)); }
+
+GETREG(msr)
+SETREG(msr)
+GETREG(cr)
+
+#define GSETSPR(n, name) \
+ static inline int get_ ## name (void) \
+ { int ret; asm volatile ("mfspr %0," #n : "=r" (ret) : ); return ret; } \
+ static inline void set_ ## name (int val) \
+ { asm volatile ("mtspr " #n ",%0" : : "r" (val)); }
+
+GSETSPR(0, mq)
+GSETSPR(1, xer)
+GSETSPR(4, rtcu)
+GSETSPR(5, rtcl)
+GSETSPR(8, lr)
+GSETSPR(9, ctr)
+GSETSPR(18, dsisr)
+GSETSPR(19, dar)
+GSETSPR(22, dec)
+GSETSPR(25, sdr1)
+GSETSPR(26, srr0)
+GSETSPR(27, srr1)
+GSETSPR(272, sprg0)
+GSETSPR(273, sprg1)
+GSETSPR(274, sprg2)
+GSETSPR(275, sprg3)
+GSETSPR(282, ear)
+GSETSPR(287, pvr)
+#ifndef CONFIG_8xx
+GSETSPR(528, bat0u)
+GSETSPR(529, bat0l)
+GSETSPR(530, bat1u)
+GSETSPR(531, bat1l)
+GSETSPR(532, bat2u)
+GSETSPR(533, bat2l)
+GSETSPR(534, bat3u)
+GSETSPR(535, bat3l)
+GSETSPR(1008, hid0)
+GSETSPR(1009, hid1)
+GSETSPR(1010, iabr)
+GSETSPR(1013, dabr)
+GSETSPR(1023, pir)
+#else
+GSETSPR(144, cmpa)
+GSETSPR(145, cmpb)
+GSETSPR(146, cmpc)
+GSETSPR(147, cmpd)
+GSETSPR(158, ictrl)
+#endif
+
+static inline int get_sr(int n)
+{
+ int ret;
+
+ asm (" mfsrin %0,%1" : "=r" (ret) : "r" (n << 28));
+ return ret;
+}
+
+static inline void set_sr(int n, int val)
+{
+ asm ("mtsrin %0,%1" : : "r" (val), "r" (n << 28));
+}
+
+static inline void store_inst(void *p)
+{
+ asm volatile ("dcbst 0,%0; sync; icbi 0,%0; isync" : : "r" (p));
+}
+
+static inline void cflush(void *p)
+{
+ asm volatile ("dcbf 0,%0; icbi 0,%0" : : "r" (p));
+}
+
+static inline void cinval(void *p)
+{
+ asm volatile ("dcbi 0,%0; icbi 0,%0" : : "r" (p));
+}
+
diff --git a/arch/ppc/xmon/setjmp.c b/arch/ppc/xmon/setjmp.c
new file mode 100644
index 0000000..28352ba
--- /dev/null
+++ b/arch/ppc/xmon/setjmp.c
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 1996 Paul Mackerras.
+ *
+ * NB this file must be compiled with -O2.
+ */
+
+int
+xmon_setjmp(long *buf)
+{
+ asm ("mflr 0; stw 0,0(%0);"
+ "stw 1,4(%0); stw 2,8(%0);"
+ "mfcr 0; stw 0,12(%0);"
+ "stmw 13,16(%0)"
+ : : "r" (buf));
+ /* XXX should save fp regs as well */
+ return 0;
+}
+
+void
+xmon_longjmp(long *buf, int val)
+{
+ if (val == 0)
+ val = 1;
+ asm ("lmw 13,16(%0);"
+ "lwz 0,12(%0); mtcrf 0x38,0;"
+ "lwz 0,0(%0); lwz 1,4(%0); lwz 2,8(%0);"
+ "mtlr 0; mr 3,%1"
+ : : "r" (buf), "r" (val));
+}
diff --git a/arch/ppc/xmon/start.c b/arch/ppc/xmon/start.c
new file mode 100644
index 0000000..507d4ee
--- /dev/null
+++ b/arch/ppc/xmon/start.c
@@ -0,0 +1,646 @@
+/*
+ * Copyright (C) 1996 Paul Mackerras.
+ */
+#include <linux/config.h>
+#include <linux/string.h>
+#include <asm/machdep.h>
+#include <asm/io.h>
+#include <asm/page.h>
+#include <linux/adb.h>
+#include <linux/pmu.h>
+#include <linux/cuda.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/sysrq.h>
+#include <linux/bitops.h>
+#include <asm/xmon.h>
+#include <asm/prom.h>
+#include <asm/bootx.h>
+#include <asm/machdep.h>
+#include <asm/errno.h>
+#include <asm/pmac_feature.h>
+#include <asm/processor.h>
+#include <asm/delay.h>
+#include <asm/btext.h>
+
+static volatile unsigned char *sccc, *sccd;
+unsigned int TXRDY, RXRDY, DLAB;
+static int xmon_expect(const char *str, unsigned int timeout);
+
+static int use_serial;
+static int use_screen;
+static int via_modem;
+static int xmon_use_sccb;
+static struct device_node *channel_node;
+
+#define TB_SPEED 25000000
+
+static inline unsigned int readtb(void)
+{
+ unsigned int ret;
+
+ asm volatile("mftb %0" : "=r" (ret) :);
+ return ret;
+}
+
+void buf_access(void)
+{
+ if (DLAB)
+ sccd[3] &= ~DLAB; /* reset DLAB */
+}
+
+extern int adb_init(void);
+
+#ifdef CONFIG_PPC_CHRP
+/*
+ * This looks in the "ranges" property for the primary PCI host bridge
+ * to find the physical address of the start of PCI/ISA I/O space.
+ * It is basically a cut-down version of pci_process_bridge_OF_ranges.
+ */
+static unsigned long chrp_find_phys_io_base(void)
+{
+ struct device_node *node;
+ unsigned int *ranges;
+ unsigned long base = CHRP_ISA_IO_BASE;
+ int rlen = 0;
+ int np;
+
+ node = find_devices("isa");
+ if (node != NULL) {
+ node = node->parent;
+ if (node == NULL || node->type == NULL
+ || strcmp(node->type, "pci") != 0)
+ node = NULL;
+ }
+ if (node == NULL)
+ node = find_devices("pci");
+ if (node == NULL)
+ return base;
+
+ ranges = (unsigned int *) get_property(node, "ranges", &rlen);
+ np = prom_n_addr_cells(node) + 5;
+ while ((rlen -= np * sizeof(unsigned int)) >= 0) {
+ if ((ranges[0] >> 24) == 1 && ranges[2] == 0) {
+ /* I/O space starting at 0, grab the phys base */
+ base = ranges[np - 3];
+ break;
+ }
+ ranges += np;
+ }
+ return base;
+}
+#endif /* CONFIG_PPC_CHRP */
+
+#ifdef CONFIG_MAGIC_SYSRQ
+static void sysrq_handle_xmon(int key, struct pt_regs *regs,
+ struct tty_struct *tty)
+{
+ xmon(regs);
+}
+
+static struct sysrq_key_op sysrq_xmon_op =
+{
+ .handler = sysrq_handle_xmon,
+ .help_msg = "Xmon",
+ .action_msg = "Entering xmon",
+};
+#endif
+
+void
+xmon_map_scc(void)
+{
+#ifdef CONFIG_PPC_MULTIPLATFORM
+ volatile unsigned char *base;
+
+ if (_machine == _MACH_Pmac) {
+ struct device_node *np;
+ unsigned long addr;
+#ifdef CONFIG_BOOTX_TEXT
+ if (!use_screen && !use_serial
+ && !machine_is_compatible("iMac")) {
+ /* see if there is a keyboard in the device tree
+ with a parent of type "adb" */
+ for (np = find_devices("keyboard"); np; np = np->next)
+ if (np->parent && np->parent->type
+ && strcmp(np->parent->type, "adb") == 0)
+ break;
+
+ /* needs to be hacked if xmon_printk is to be used
+ from within find_via_pmu() */
+#ifdef CONFIG_ADB_PMU
+ if (np != NULL && boot_text_mapped && find_via_pmu())
+ use_screen = 1;
+#endif
+#ifdef CONFIG_ADB_CUDA
+ if (np != NULL && boot_text_mapped && find_via_cuda())
+ use_screen = 1;
+#endif
+ }
+ if (!use_screen && (np = find_devices("escc")) != NULL) {
+ /*
+ * look for the device node for the serial port
+ * we're using and see if it says it has a modem
+ */
+ char *name = xmon_use_sccb? "ch-b": "ch-a";
+ char *slots;
+ int l;
+
+ np = np->child;
+ while (np != NULL && strcmp(np->name, name) != 0)
+ np = np->sibling;
+ if (np != NULL) {
+ /* XXX should parse this properly */
+ channel_node = np;
+ slots = get_property(np, "slot-names", &l);
+ if (slots != NULL && l >= 10
+ && strcmp(slots+4, "Modem") == 0)
+ via_modem = 1;
+ }
+ }
+ btext_drawstring("xmon uses ");
+ if (use_screen)
+ btext_drawstring("screen and keyboard\n");
+ else {
+ if (via_modem)
+ btext_drawstring("modem on ");
+ btext_drawstring(xmon_use_sccb? "printer": "modem");
+ btext_drawstring(" port\n");
+ }
+
+#endif /* CONFIG_BOOTX_TEXT */
+
+#ifdef CHRP_ESCC
+ addr = 0xc1013020;
+#else
+ addr = 0xf3013020;
+#endif
+ TXRDY = 4;
+ RXRDY = 1;
+
+ np = find_devices("mac-io");
+ if (np && np->n_addrs)
+ addr = np->addrs[0].address + 0x13020;
+ base = (volatile unsigned char *) ioremap(addr & PAGE_MASK, PAGE_SIZE);
+ sccc = base + (addr & ~PAGE_MASK);
+ sccd = sccc + 0x10;
+
+ } else {
+ base = (volatile unsigned char *) isa_io_base;
+ if (_machine == _MACH_chrp)
+ base = (volatile unsigned char *)
+ ioremap(chrp_find_phys_io_base(), 0x1000);
+
+ sccc = base + 0x3fd;
+ sccd = base + 0x3f8;
+ if (xmon_use_sccb) {
+ sccc -= 0x100;
+ sccd -= 0x100;
+ }
+ TXRDY = 0x20;
+ RXRDY = 1;
+ DLAB = 0x80;
+ }
+#elif defined(CONFIG_GEMINI)
+ /* should already be mapped by the kernel boot */
+ sccc = (volatile unsigned char *) 0xffeffb0d;
+ sccd = (volatile unsigned char *) 0xffeffb08;
+ TXRDY = 0x20;
+ RXRDY = 1;
+ DLAB = 0x80;
+#elif defined(CONFIG_405GP)
+ sccc = (volatile unsigned char *)0xef600305;
+ sccd = (volatile unsigned char *)0xef600300;
+ TXRDY = 0x20;
+ RXRDY = 1;
+ DLAB = 0x80;
+#endif /* platform */
+
+ register_sysrq_key('x', &sysrq_xmon_op);
+}
+
+static int scc_initialized = 0;
+
+void xmon_init_scc(void);
+extern void cuda_poll(void);
+
+static inline void do_poll_adb(void)
+{
+#ifdef CONFIG_ADB_PMU
+ if (sys_ctrler == SYS_CTRLER_PMU)
+ pmu_poll_adb();
+#endif /* CONFIG_ADB_PMU */
+#ifdef CONFIG_ADB_CUDA
+ if (sys_ctrler == SYS_CTRLER_CUDA)
+ cuda_poll();
+#endif /* CONFIG_ADB_CUDA */
+}
+
+int
+xmon_write(void *handle, void *ptr, int nb)
+{
+ char *p = ptr;
+ int i, c, ct;
+
+#ifdef CONFIG_SMP
+ static unsigned long xmon_write_lock;
+ int lock_wait = 1000000;
+ int locked;
+
+ while ((locked = test_and_set_bit(0, &xmon_write_lock)) != 0)
+ if (--lock_wait == 0)
+ break;
+#endif
+
+#ifdef CONFIG_BOOTX_TEXT
+ if (use_screen) {
+ /* write it on the screen */
+ for (i = 0; i < nb; ++i)
+ btext_drawchar(*p++);
+ goto out;
+ }
+#endif
+ if (!scc_initialized)
+ xmon_init_scc();
+ ct = 0;
+ for (i = 0; i < nb; ++i) {
+ while ((*sccc & TXRDY) == 0)
+ do_poll_adb();
+ c = p[i];
+ if (c == '\n' && !ct) {
+ c = '\r';
+ ct = 1;
+ --i;
+ } else {
+ ct = 0;
+ }
+ buf_access();
+ *sccd = c;
+ eieio();
+ }
+
+ out:
+#ifdef CONFIG_SMP
+ if (!locked)
+ clear_bit(0, &xmon_write_lock);
+#endif
+ return nb;
+}
+
+int xmon_wants_key;
+int xmon_adb_keycode;
+
+#ifdef CONFIG_BOOTX_TEXT
+static int xmon_adb_shiftstate;
+
+static unsigned char xmon_keytab[128] =
+ "asdfhgzxcv\000bqwer" /* 0x00 - 0x0f */
+ "yt123465=97-80]o" /* 0x10 - 0x1f */
+ "u[ip\rlj'k;\\,/nm." /* 0x20 - 0x2f */
+ "\t `\177\0\033\0\0\0\0\0\0\0\0\0\0" /* 0x30 - 0x3f */
+ "\0.\0*\0+\0\0\0\0\0/\r\0-\0" /* 0x40 - 0x4f */
+ "\0\0000123456789\0\0\0"; /* 0x50 - 0x5f */
+
+static unsigned char xmon_shift_keytab[128] =
+ "ASDFHGZXCV\000BQWER" /* 0x00 - 0x0f */
+ "YT!@#$^%+(&_*)}O" /* 0x10 - 0x1f */
+ "U{IP\rLJ\"K:|<?NM>" /* 0x20 - 0x2f */
+ "\t ~\177\0\033\0\0\0\0\0\0\0\0\0\0" /* 0x30 - 0x3f */
+ "\0.\0*\0+\0\0\0\0\0/\r\0-\0" /* 0x40 - 0x4f */
+ "\0\0000123456789\0\0\0"; /* 0x50 - 0x5f */
+
+static int
+xmon_get_adb_key(void)
+{
+ int k, t, on;
+
+ xmon_wants_key = 1;
+ for (;;) {
+ xmon_adb_keycode = -1;
+ t = 0;
+ on = 0;
+ do {
+ if (--t < 0) {
+ on = 1 - on;
+ btext_drawchar(on? 0xdb: 0x20);
+ btext_drawchar('\b');
+ t = 200000;
+ }
+ do_poll_adb();
+ } while (xmon_adb_keycode == -1);
+ k = xmon_adb_keycode;
+ if (on)
+ btext_drawstring(" \b");
+
+ /* test for shift keys */
+ if ((k & 0x7f) == 0x38 || (k & 0x7f) == 0x7b) {
+ xmon_adb_shiftstate = (k & 0x80) == 0;
+ continue;
+ }
+ if (k >= 0x80)
+ continue; /* ignore up transitions */
+ k = (xmon_adb_shiftstate? xmon_shift_keytab: xmon_keytab)[k];
+ if (k != 0)
+ break;
+ }
+ xmon_wants_key = 0;
+ return k;
+}
+#endif /* CONFIG_BOOTX_TEXT */
+
+int
+xmon_read(void *handle, void *ptr, int nb)
+{
+ char *p = ptr;
+ int i;
+
+#ifdef CONFIG_BOOTX_TEXT
+ if (use_screen) {
+ for (i = 0; i < nb; ++i)
+ *p++ = xmon_get_adb_key();
+ return i;
+ }
+#endif
+ if (!scc_initialized)
+ xmon_init_scc();
+ for (i = 0; i < nb; ++i) {
+ while ((*sccc & RXRDY) == 0)
+ do_poll_adb();
+ buf_access();
+ *p++ = *sccd;
+ }
+ return i;
+}
+
+int
+xmon_read_poll(void)
+{
+ if ((*sccc & RXRDY) == 0) {
+ do_poll_adb();
+ return -1;
+ }
+ buf_access();
+ return *sccd;
+}
+
+static unsigned char scc_inittab[] = {
+ 13, 0, /* set baud rate divisor */
+ 12, 1,
+ 14, 1, /* baud rate gen enable, src=rtxc */
+ 11, 0x50, /* clocks = br gen */
+ 5, 0xea, /* tx 8 bits, assert DTR & RTS */
+ 4, 0x46, /* x16 clock, 1 stop */
+ 3, 0xc1, /* rx enable, 8 bits */
+};
+
+void
+xmon_init_scc(void)
+{
+ if ( _machine == _MACH_chrp )
+ {
+ sccd[3] = 0x83; eieio(); /* LCR = 8N1 + DLAB */
+ sccd[0] = 12; eieio(); /* DLL = 9600 baud */
+ sccd[1] = 0; eieio();
+ sccd[2] = 0; eieio(); /* FCR = 0 */
+ sccd[3] = 3; eieio(); /* LCR = 8N1 */
+ sccd[1] = 0; eieio(); /* IER = 0 */
+ }
+ else if ( _machine == _MACH_Pmac )
+ {
+ int i, x;
+
+ if (channel_node != 0)
+ pmac_call_feature(
+ PMAC_FTR_SCC_ENABLE,
+ channel_node,
+ PMAC_SCC_ASYNC | PMAC_SCC_FLAG_XMON, 1);
+ printk(KERN_INFO "Serial port locked ON by debugger !\n");
+ if (via_modem && channel_node != 0) {
+ unsigned int t0;
+
+ pmac_call_feature(
+ PMAC_FTR_MODEM_ENABLE,
+ channel_node, 0, 1);
+ printk(KERN_INFO "Modem powered up by debugger !\n");
+ t0 = readtb();
+ while (readtb() - t0 < 3*TB_SPEED)
+ eieio();
+ }
+ /* use the B channel if requested */
+ if (xmon_use_sccb) {
+ sccc = (volatile unsigned char *)
+ ((unsigned long)sccc & ~0x20);
+ sccd = sccc + 0x10;
+ }
+ for (i = 20000; i != 0; --i) {
+ x = *sccc; eieio();
+ }
+ *sccc = 9; eieio(); /* reset A or B side */
+ *sccc = ((unsigned long)sccc & 0x20)? 0x80: 0x40; eieio();
+ for (i = 0; i < sizeof(scc_inittab); ++i) {
+ *sccc = scc_inittab[i];
+ eieio();
+ }
+ }
+ scc_initialized = 1;
+ if (via_modem) {
+ for (;;) {
+ xmon_write(NULL, "ATE1V1\r", 7);
+ if (xmon_expect("OK", 5)) {
+ xmon_write(NULL, "ATA\r", 4);
+ if (xmon_expect("CONNECT", 40))
+ break;
+ }
+ xmon_write(NULL, "+++", 3);
+ xmon_expect("OK", 3);
+ }
+ }
+}
+
+#if 0
+extern int (*prom_entry)(void *);
+
+int
+xmon_exit(void)
+{
+ struct prom_args {
+ char *service;
+ } args;
+
+ for (;;) {
+ args.service = "exit";
+ (*prom_entry)(&args);
+ }
+}
+#endif
+
+void *xmon_stdin;
+void *xmon_stdout;
+void *xmon_stderr;
+
+void
+xmon_init(void)
+{
+}
+
+int
+xmon_putc(int c, void *f)
+{
+ char ch = c;
+
+ if (c == '\n')
+ xmon_putc('\r', f);
+ return xmon_write(f, &ch, 1) == 1? c: -1;
+}
+
+int
+xmon_putchar(int c)
+{
+ return xmon_putc(c, xmon_stdout);
+}
+
+int
+xmon_fputs(char *str, void *f)
+{
+ int n = strlen(str);
+
+ return xmon_write(f, str, n) == n? 0: -1;
+}
+
+int
+xmon_readchar(void)
+{
+ char ch;
+
+ for (;;) {
+ switch (xmon_read(xmon_stdin, &ch, 1)) {
+ case 1:
+ return ch;
+ case -1:
+ xmon_printf("read(stdin) returned -1\r\n", 0, 0);
+ return -1;
+ }
+ }
+}
+
+static char line[256];
+static char *lineptr;
+static int lineleft;
+
+int xmon_expect(const char *str, unsigned int timeout)
+{
+ int c;
+ unsigned int t0;
+
+ timeout *= TB_SPEED;
+ t0 = readtb();
+ do {
+ lineptr = line;
+ for (;;) {
+ c = xmon_read_poll();
+ if (c == -1) {
+ if (readtb() - t0 > timeout)
+ return 0;
+ continue;
+ }
+ if (c == '\n')
+ break;
+ if (c != '\r' && lineptr < &line[sizeof(line) - 1])
+ *lineptr++ = c;
+ }
+ *lineptr = 0;
+ } while (strstr(line, str) == NULL);
+ return 1;
+}
+
+int
+xmon_getchar(void)
+{
+ int c;
+
+ if (lineleft == 0) {
+ lineptr = line;
+ for (;;) {
+ c = xmon_readchar();
+ if (c == -1 || c == 4)
+ break;
+ if (c == '\r' || c == '\n') {
+ *lineptr++ = '\n';
+ xmon_putchar('\n');
+ break;
+ }
+ switch (c) {
+ case 0177:
+ case '\b':
+ if (lineptr > line) {
+ xmon_putchar('\b');
+ xmon_putchar(' ');
+ xmon_putchar('\b');
+ --lineptr;
+ }
+ break;
+ case 'U' & 0x1F:
+ while (lineptr > line) {
+ xmon_putchar('\b');
+ xmon_putchar(' ');
+ xmon_putchar('\b');
+ --lineptr;
+ }
+ break;
+ default:
+ if (lineptr >= &line[sizeof(line) - 1])
+ xmon_putchar('\a');
+ else {
+ xmon_putchar(c);
+ *lineptr++ = c;
+ }
+ }
+ }
+ lineleft = lineptr - line;
+ lineptr = line;
+ }
+ if (lineleft == 0)
+ return -1;
+ --lineleft;
+ return *lineptr++;
+}
+
+char *
+xmon_fgets(char *str, int nb, void *f)
+{
+ char *p;
+ int c;
+
+ for (p = str; p < str + nb - 1; ) {
+ c = xmon_getchar();
+ if (c == -1) {
+ if (p == str)
+ return NULL;
+ break;
+ }
+ *p++ = c;
+ if (c == '\n')
+ break;
+ }
+ *p = 0;
+ return str;
+}
+
+void
+xmon_enter(void)
+{
+#ifdef CONFIG_ADB_PMU
+ if (_machine == _MACH_Pmac) {
+ pmu_suspend();
+ }
+#endif
+}
+
+void
+xmon_leave(void)
+{
+#ifdef CONFIG_ADB_PMU
+ if (_machine == _MACH_Pmac) {
+ pmu_resume();
+ }
+#endif
+}
diff --git a/arch/ppc/xmon/start_8xx.c b/arch/ppc/xmon/start_8xx.c
new file mode 100644
index 0000000..a48bd59
--- /dev/null
+++ b/arch/ppc/xmon/start_8xx.c
@@ -0,0 +1,287 @@
+/*
+ * Copyright (C) 1996 Paul Mackerras.
+ * Copyright (C) 2000 Dan Malek.
+ * Quick hack of Paul's code to make XMON work on 8xx processors. Lots
+ * of assumptions, like the SMC1 is used, it has been initialized by the
+ * loader at some point, and we can just stuff and suck bytes.
+ * We rely upon the 8xx uart driver to support us, as the interface
+ * changes between boot up and operational phases of the kernel.
+ */
+#include <linux/string.h>
+#include <asm/machdep.h>
+#include <asm/io.h>
+#include <asm/page.h>
+#include <linux/kernel.h>
+#include <asm/8xx_immap.h>
+#include <asm/mpc8xx.h>
+#include <asm/commproc.h>
+
+extern void xmon_printf(const char *fmt, ...);
+extern int xmon_8xx_write(char *str, int nb);
+extern int xmon_8xx_read_poll(void);
+extern int xmon_8xx_read_char(void);
+void prom_drawhex(uint);
+void prom_drawstring(const char *str);
+
+static int use_screen = 1; /* default */
+
+#define TB_SPEED 25000000
+
+static inline unsigned int readtb(void)
+{
+ unsigned int ret;
+
+ asm volatile("mftb %0" : "=r" (ret) :);
+ return ret;
+}
+
+void buf_access(void)
+{
+}
+
+void
+xmon_map_scc(void)
+{
+
+ cpmp = (cpm8xx_t *)&(((immap_t *)IMAP_ADDR)->im_cpm);
+ use_screen = 0;
+
+ prom_drawstring("xmon uses serial port\n");
+}
+
+static int scc_initialized = 0;
+
+void xmon_init_scc(void);
+
+int
+xmon_write(void *handle, void *ptr, int nb)
+{
+ char *p = ptr;
+ int i, c, ct;
+
+ if (!scc_initialized)
+ xmon_init_scc();
+
+ return(xmon_8xx_write(ptr, nb));
+}
+
+int xmon_wants_key;
+
+int
+xmon_read(void *handle, void *ptr, int nb)
+{
+ char *p = ptr;
+ int i;
+
+ if (!scc_initialized)
+ xmon_init_scc();
+
+ for (i = 0; i < nb; ++i) {
+ *p++ = xmon_8xx_read_char();
+ }
+ return i;
+}
+
+int
+xmon_read_poll(void)
+{
+ return(xmon_8xx_read_poll());
+}
+
+void
+xmon_init_scc()
+{
+ scc_initialized = 1;
+}
+
+#if 0
+extern int (*prom_entry)(void *);
+
+int
+xmon_exit(void)
+{
+ struct prom_args {
+ char *service;
+ } args;
+
+ for (;;) {
+ args.service = "exit";
+ (*prom_entry)(&args);
+ }
+}
+#endif
+
+void *xmon_stdin;
+void *xmon_stdout;
+void *xmon_stderr;
+
+void
+xmon_init(void)
+{
+}
+
+int
+xmon_putc(int c, void *f)
+{
+ char ch = c;
+
+ if (c == '\n')
+ xmon_putc('\r', f);
+ return xmon_write(f, &ch, 1) == 1? c: -1;
+}
+
+int
+xmon_putchar(int c)
+{
+ return xmon_putc(c, xmon_stdout);
+}
+
+int
+xmon_fputs(char *str, void *f)
+{
+ int n = strlen(str);
+
+ return xmon_write(f, str, n) == n? 0: -1;
+}
+
+int
+xmon_readchar(void)
+{
+ char ch;
+
+ for (;;) {
+ switch (xmon_read(xmon_stdin, &ch, 1)) {
+ case 1:
+ return ch;
+ case -1:
+ xmon_printf("read(stdin) returned -1\r\n", 0, 0);
+ return -1;
+ }
+ }
+}
+
+static char line[256];
+static char *lineptr;
+static int lineleft;
+
+#if 0
+int xmon_expect(const char *str, unsigned int timeout)
+{
+ int c;
+ unsigned int t0;
+
+ timeout *= TB_SPEED;
+ t0 = readtb();
+ do {
+ lineptr = line;
+ for (;;) {
+ c = xmon_read_poll();
+ if (c == -1) {
+ if (readtb() - t0 > timeout)
+ return 0;
+ continue;
+ }
+ if (c == '\n')
+ break;
+ if (c != '\r' && lineptr < &line[sizeof(line) - 1])
+ *lineptr++ = c;
+ }
+ *lineptr = 0;
+ } while (strstr(line, str) == NULL);
+ return 1;
+}
+#endif
+
+int
+xmon_getchar(void)
+{
+ int c;
+
+ if (lineleft == 0) {
+ lineptr = line;
+ for (;;) {
+ c = xmon_readchar();
+ if (c == -1 || c == 4)
+ break;
+ if (c == '\r' || c == '\n') {
+ *lineptr++ = '\n';
+ xmon_putchar('\n');
+ break;
+ }
+ switch (c) {
+ case 0177:
+ case '\b':
+ if (lineptr > line) {
+ xmon_putchar('\b');
+ xmon_putchar(' ');
+ xmon_putchar('\b');
+ --lineptr;
+ }
+ break;
+ case 'U' & 0x1F:
+ while (lineptr > line) {
+ xmon_putchar('\b');
+ xmon_putchar(' ');
+ xmon_putchar('\b');
+ --lineptr;
+ }
+ break;
+ default:
+ if (lineptr >= &line[sizeof(line) - 1])
+ xmon_putchar('\a');
+ else {
+ xmon_putchar(c);
+ *lineptr++ = c;
+ }
+ }
+ }
+ lineleft = lineptr - line;
+ lineptr = line;
+ }
+ if (lineleft == 0)
+ return -1;
+ --lineleft;
+ return *lineptr++;
+}
+
+char *
+xmon_fgets(char *str, int nb, void *f)
+{
+ char *p;
+ int c;
+
+ for (p = str; p < str + nb - 1; ) {
+ c = xmon_getchar();
+ if (c == -1) {
+ if (p == str)
+ return 0;
+ break;
+ }
+ *p++ = c;
+ if (c == '\n')
+ break;
+ }
+ *p = 0;
+ return str;
+}
+
+void
+prom_drawhex(uint val)
+{
+ unsigned char buf[10];
+
+ int i;
+ for (i = 7; i >= 0; i--)
+ {
+ buf[i] = "0123456789abcdef"[val & 0x0f];
+ val >>= 4;
+ }
+ buf[8] = '\0';
+ xmon_fputs(buf, xmon_stdout);
+}
+
+void
+prom_drawstring(const char *str)
+{
+ xmon_fputs(str, xmon_stdout);
+}
diff --git a/arch/ppc/xmon/subr_prf.c b/arch/ppc/xmon/subr_prf.c
new file mode 100644
index 0000000..126624f
--- /dev/null
+++ b/arch/ppc/xmon/subr_prf.c
@@ -0,0 +1,55 @@
+/*
+ * Written by Cort Dougan to replace the version originally used
+ * by Paul Mackerras, which came from NetBSD and thus had copyright
+ * conflicts with Linux.
+ *
+ * This file makes liberal use of the standard linux utility
+ * routines to reduce the size of the binary. We assume we can
+ * trust some parts of Linux inside the debugger.
+ * -- Cort (cort@cs.nmt.edu)
+ *
+ * Copyright (C) 1999 Cort Dougan.
+ */
+
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <stdarg.h>
+#include "nonstdio.h"
+
+extern int xmon_write(void *, void *, int);
+
+void
+xmon_vfprintf(void *f, const char *fmt, va_list ap)
+{
+ static char xmon_buf[2048];
+ int n;
+
+ n = vsprintf(xmon_buf, fmt, ap);
+ xmon_write(f, xmon_buf, n);
+}
+
+void
+xmon_printf(const char *fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ xmon_vfprintf(stdout, fmt, ap);
+ va_end(ap);
+}
+
+void
+xmon_fprintf(void *f, const char *fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ xmon_vfprintf(f, fmt, ap);
+ va_end(ap);
+}
+
+void
+xmon_puts(char *s)
+{
+ xmon_write(stdout, s, strlen(s));
+}
diff --git a/arch/ppc/xmon/xmon.c b/arch/ppc/xmon/xmon.c
new file mode 100644
index 0000000..8565f49
--- /dev/null
+++ b/arch/ppc/xmon/xmon.c
@@ -0,0 +1,2008 @@
+/*
+ * Routines providing a simple monitor for use on the PowerMac.
+ *
+ * Copyright (C) 1996 Paul Mackerras.
+ */
+#include <linux/config.h>
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/smp.h>
+#include <linux/interrupt.h>
+#include <linux/bitops.h>
+#include <asm/ptrace.h>
+#include <asm/string.h>
+#include <asm/prom.h>
+#include <asm/bootx.h>
+#include <asm/machdep.h>
+#include <asm/xmon.h>
+#ifdef CONFIG_PMAC_BACKLIGHT
+#include <asm/backlight.h>
+#endif
+#include "nonstdio.h"
+#include "privinst.h"
+
+#define scanhex xmon_scanhex
+#define skipbl xmon_skipbl
+
+#ifdef CONFIG_SMP
+static unsigned long cpus_in_xmon = 0;
+static unsigned long got_xmon = 0;
+static volatile int take_xmon = -1;
+#endif /* CONFIG_SMP */
+
+static unsigned adrs;
+static int size = 1;
+static unsigned ndump = 64;
+static unsigned nidump = 16;
+static unsigned ncsum = 4096;
+static int termch;
+
+static u_int bus_error_jmp[100];
+#define setjmp xmon_setjmp
+#define longjmp xmon_longjmp
+
+/* Breakpoint stuff */
+struct bpt {
+ unsigned address;
+ unsigned instr;
+ unsigned count;
+ unsigned char enabled;
+};
+
+#define NBPTS 16
+static struct bpt bpts[NBPTS];
+static struct bpt dabr;
+static struct bpt iabr;
+static unsigned bpinstr = 0x7fe00008; /* trap */
+
+/* Prototypes */
+extern void (*debugger_fault_handler)(struct pt_regs *);
+static int cmds(struct pt_regs *);
+static int mread(unsigned, void *, int);
+static int mwrite(unsigned, void *, int);
+static void handle_fault(struct pt_regs *);
+static void byterev(unsigned char *, int);
+static void memex(void);
+static int bsesc(void);
+static void dump(void);
+static void prdump(unsigned, int);
+#ifdef __MWERKS__
+static void prndump(unsigned, int);
+static int nvreadb(unsigned);
+#endif
+static int ppc_inst_dump(unsigned, int);
+void print_address(unsigned);
+static int getsp(void);
+static void dump_hash_table(void);
+static void backtrace(struct pt_regs *);
+static void excprint(struct pt_regs *);
+static void prregs(struct pt_regs *);
+static void memops(int);
+static void memlocate(void);
+static void memzcan(void);
+static void memdiffs(unsigned char *, unsigned char *, unsigned, unsigned);
+int skipbl(void);
+int scanhex(unsigned *valp);
+static void scannl(void);
+static int hexdigit(int);
+void getstring(char *, int);
+static void flush_input(void);
+static int inchar(void);
+static void take_input(char *);
+/* static void openforth(void); */
+static unsigned read_spr(int);
+static void write_spr(int, unsigned);
+static void super_regs(void);
+static void print_sysmap(void);
+static void sysmap_lookup(void);
+static void remove_bpts(void);
+static void insert_bpts(void);
+static struct bpt *at_breakpoint(unsigned pc);
+static void bpt_cmds(void);
+static void cacheflush(void);
+#ifdef CONFIG_SMP
+static void cpu_cmd(void);
+#endif /* CONFIG_SMP */
+static int pretty_print_addr(unsigned long addr);
+static void csum(void);
+#ifdef CONFIG_BOOTX_TEXT
+static void vidcmds(void);
+#endif
+static void bootcmds(void);
+static void proccall(void);
+static void printtime(void);
+
+extern int print_insn_big_powerpc(FILE *, unsigned long, unsigned);
+extern void printf(const char *fmt, ...);
+extern int putchar(int ch);
+extern int setjmp(u_int *);
+extern void longjmp(u_int *, int);
+
+extern void xmon_enter(void);
+extern void xmon_leave(void);
+extern char* xmon_find_symbol(unsigned long addr, unsigned long* saddr);
+extern unsigned long xmon_symbol_to_addr(char* symbol);
+
+static unsigned start_tb[NR_CPUS][2];
+static unsigned stop_tb[NR_CPUS][2];
+
+#define GETWORD(v) (((v)[0] << 24) + ((v)[1] << 16) + ((v)[2] << 8) + (v)[3])
+
+#define isxdigit(c) (('0' <= (c) && (c) <= '9') \
+ || ('a' <= (c) && (c) <= 'f') \
+ || ('A' <= (c) && (c) <= 'F'))
+#define isalnum(c) (('0' <= (c) && (c) <= '9') \
+ || ('a' <= (c) && (c) <= 'z') \
+ || ('A' <= (c) && (c) <= 'Z'))
+#define isspace(c) (c == ' ' || c == '\t' || c == 10 || c == 13 || c == 0)
+
+static char *help_string = "\
+Commands:\n\
+ d dump bytes\n\
+ di dump instructions\n\
+ df dump float values\n\
+ dd dump double values\n\
+ e print exception information\n\
+ h dump hash table\n\
+ m examine/change memory\n\
+ mm move a block of memory\n\
+ ms set a block of memory\n\
+ md compare two blocks of memory\n\
+ M print System.map\n\
+ r print registers\n\
+ S print special registers\n\
+ t print backtrace\n\
+ la lookup address in system.map\n\
+ ls lookup symbol in system.map\n\
+ x exit monitor\n\
+";
+
+static int xmon_trace[NR_CPUS];
+#define SSTEP 1 /* stepping because of 's' command */
+#define BRSTEP 2 /* stepping over breakpoint */
+
+static struct pt_regs *xmon_regs[NR_CPUS];
+
+extern inline void sync(void)
+{
+ asm volatile("sync; isync");
+}
+
+extern inline void __delay(unsigned int loops)
+{
+ if (loops != 0)
+ __asm__ __volatile__("mtctr %0; 1: bdnz 1b" : :
+ "r" (loops) : "ctr");
+}
+
+static void get_tb(unsigned *p)
+{
+ unsigned hi, lo, hiagain;
+
+ if ((get_pvr() >> 16) == 1)
+ return;
+
+ do {
+ asm volatile("mftbu %0; mftb %1; mftbu %2"
+ : "=r" (hi), "=r" (lo), "=r" (hiagain));
+ } while (hi != hiagain);
+ p[0] = hi;
+ p[1] = lo;
+}
+
+void
+xmon(struct pt_regs *excp)
+{
+ struct pt_regs regs;
+ int msr, cmd;
+
+ get_tb(stop_tb[smp_processor_id()]);
+ if (excp == NULL) {
+ asm volatile ("stw 0,0(%0)\n\
+ lwz 0,0(1)\n\
+ stw 0,4(%0)\n\
+ stmw 2,8(%0)" : : "b" (®s));
+ regs.nip = regs.link = ((unsigned long *)regs.gpr[1])[1];
+ regs.msr = get_msr();
+ regs.ctr = get_ctr();
+ regs.xer = get_xer();
+ regs.ccr = get_cr();
+ regs.trap = 0;
+ excp = ®s;
+ }
+
+ msr = get_msr();
+ set_msr(msr & ~0x8000); /* disable interrupts */
+ xmon_regs[smp_processor_id()] = excp;
+ xmon_enter();
+ excprint(excp);
+#ifdef CONFIG_SMP
+ if (test_and_set_bit(smp_processor_id(), &cpus_in_xmon))
+ for (;;)
+ ;
+ while (test_and_set_bit(0, &got_xmon)) {
+ if (take_xmon == smp_processor_id()) {
+ take_xmon = -1;
+ break;
+ }
+ }
+ /*
+ * XXX: breakpoints are removed while any cpu is in xmon
+ */
+#endif /* CONFIG_SMP */
+ remove_bpts();
+#ifdef CONFIG_PMAC_BACKLIGHT
+ if( setjmp(bus_error_jmp) == 0 ) {
+ debugger_fault_handler = handle_fault;
+ sync();
+ set_backlight_enable(1);
+ set_backlight_level(BACKLIGHT_MAX);
+ sync();
+ }
+ debugger_fault_handler = NULL;
+#endif /* CONFIG_PMAC_BACKLIGHT */
+ cmd = cmds(excp);
+ if (cmd == 's') {
+ xmon_trace[smp_processor_id()] = SSTEP;
+ excp->msr |= 0x400;
+ } else if (at_breakpoint(excp->nip)) {
+ xmon_trace[smp_processor_id()] = BRSTEP;
+ excp->msr |= 0x400;
+ } else {
+ xmon_trace[smp_processor_id()] = 0;
+ insert_bpts();
+ }
+ xmon_leave();
+ xmon_regs[smp_processor_id()] = NULL;
+#ifdef CONFIG_SMP
+ clear_bit(0, &got_xmon);
+ clear_bit(smp_processor_id(), &cpus_in_xmon);
+#endif /* CONFIG_SMP */
+ set_msr(msr); /* restore interrupt enable */
+ get_tb(start_tb[smp_processor_id()]);
+}
+
+irqreturn_t
+xmon_irq(int irq, void *d, struct pt_regs *regs)
+{
+ unsigned long flags;
+ local_irq_save(flags);
+ printf("Keyboard interrupt\n");
+ xmon(regs);
+ local_irq_restore(flags);
+ return IRQ_HANDLED;
+}
+
+int
+xmon_bpt(struct pt_regs *regs)
+{
+ struct bpt *bp;
+
+ bp = at_breakpoint(regs->nip);
+ if (!bp)
+ return 0;
+ if (bp->count) {
+ --bp->count;
+ remove_bpts();
+ excprint(regs);
+ xmon_trace[smp_processor_id()] = BRSTEP;
+ regs->msr |= 0x400;
+ } else {
+ xmon(regs);
+ }
+ return 1;
+}
+
+int
+xmon_sstep(struct pt_regs *regs)
+{
+ if (!xmon_trace[smp_processor_id()])
+ return 0;
+ if (xmon_trace[smp_processor_id()] == BRSTEP) {
+ xmon_trace[smp_processor_id()] = 0;
+ insert_bpts();
+ } else {
+ xmon(regs);
+ }
+ return 1;
+}
+
+int
+xmon_dabr_match(struct pt_regs *regs)
+{
+ if (dabr.enabled && dabr.count) {
+ --dabr.count;
+ remove_bpts();
+ excprint(regs);
+ xmon_trace[smp_processor_id()] = BRSTEP;
+ regs->msr |= 0x400;
+ } else {
+ dabr.instr = regs->nip;
+ xmon(regs);
+ }
+ return 1;
+}
+
+int
+xmon_iabr_match(struct pt_regs *regs)
+{
+ if (iabr.enabled && iabr.count) {
+ --iabr.count;
+ remove_bpts();
+ excprint(regs);
+ xmon_trace[smp_processor_id()] = BRSTEP;
+ regs->msr |= 0x400;
+ } else {
+ xmon(regs);
+ }
+ return 1;
+}
+
+static struct bpt *
+at_breakpoint(unsigned pc)
+{
+ int i;
+ struct bpt *bp;
+
+ if (dabr.enabled && pc == dabr.instr)
+ return &dabr;
+ if (iabr.enabled && pc == iabr.address)
+ return &iabr;
+ bp = bpts;
+ for (i = 0; i < NBPTS; ++i, ++bp)
+ if (bp->enabled && pc == bp->address)
+ return bp;
+ return NULL;
+}
+
+static void
+insert_bpts(void)
+{
+ int i;
+ struct bpt *bp;
+
+ bp = bpts;
+ for (i = 0; i < NBPTS; ++i, ++bp) {
+ if (!bp->enabled)
+ continue;
+ if (mread(bp->address, &bp->instr, 4) != 4
+ || mwrite(bp->address, &bpinstr, 4) != 4) {
+ printf("Couldn't insert breakpoint at %x, disabling\n",
+ bp->address);
+ bp->enabled = 0;
+ }
+ store_inst((void *) bp->address);
+ }
+#if !defined(CONFIG_8xx)
+ if (dabr.enabled)
+ set_dabr(dabr.address);
+ if (iabr.enabled)
+ set_iabr(iabr.address);
+#endif
+}
+
+static void
+remove_bpts(void)
+{
+ int i;
+ struct bpt *bp;
+ unsigned instr;
+
+#if !defined(CONFIG_8xx)
+ set_dabr(0);
+ set_iabr(0);
+#endif
+ bp = bpts;
+ for (i = 0; i < NBPTS; ++i, ++bp) {
+ if (!bp->enabled)
+ continue;
+ if (mread(bp->address, &instr, 4) == 4
+ && instr == bpinstr
+ && mwrite(bp->address, &bp->instr, 4) != 4)
+ printf("Couldn't remove breakpoint at %x\n",
+ bp->address);
+ store_inst((void *) bp->address);
+ }
+}
+
+static char *last_cmd;
+
+/* Command interpreting routine */
+static int
+cmds(struct pt_regs *excp)
+{
+ int cmd;
+
+ last_cmd = NULL;
+ for(;;) {
+#ifdef CONFIG_SMP
+ printf("%d:", smp_processor_id());
+#endif /* CONFIG_SMP */
+ printf("mon> ");
+ fflush(stdout);
+ flush_input();
+ termch = 0;
+ cmd = skipbl();
+ if( cmd == '\n' ) {
+ if (last_cmd == NULL)
+ continue;
+ take_input(last_cmd);
+ last_cmd = NULL;
+ cmd = inchar();
+ }
+ switch (cmd) {
+ case 'm':
+ cmd = inchar();
+ switch (cmd) {
+ case 'm':
+ case 's':
+ case 'd':
+ memops(cmd);
+ break;
+ case 'l':
+ memlocate();
+ break;
+ case 'z':
+ memzcan();
+ break;
+ default:
+ termch = cmd;
+ memex();
+ }
+ break;
+ case 'd':
+ dump();
+ break;
+ case 'l':
+ sysmap_lookup();
+ break;
+ case 'r':
+ if (excp != NULL)
+ prregs(excp); /* print regs */
+ break;
+ case 'e':
+ if (excp == NULL)
+ printf("No exception information\n");
+ else
+ excprint(excp);
+ break;
+ case 'M':
+ print_sysmap();
+ break;
+ case 'S':
+ super_regs();
+ break;
+ case 't':
+ backtrace(excp);
+ break;
+ case 'f':
+ cacheflush();
+ break;
+ case 'h':
+ dump_hash_table();
+ break;
+ case 's':
+ case 'x':
+ case EOF:
+ return cmd;
+ case '?':
+ printf(help_string);
+ break;
+ default:
+ printf("Unrecognized command: ");
+ if( ' ' < cmd && cmd <= '~' )
+ putchar(cmd);
+ else
+ printf("\\x%x", cmd);
+ printf(" (type ? for help)\n");
+ break;
+ case 'b':
+ bpt_cmds();
+ break;
+ case 'C':
+ csum();
+ break;
+#ifdef CONFIG_SMP
+ case 'c':
+ cpu_cmd();
+ break;
+#endif /* CONFIG_SMP */
+#ifdef CONFIG_BOOTX_TEXT
+ case 'v':
+ vidcmds();
+ break;
+#endif
+ case 'z':
+ bootcmds();
+ break;
+ case 'p':
+ proccall();
+ break;
+ case 'T':
+ printtime();
+ break;
+ }
+ }
+}
+
+extern unsigned tb_to_us;
+
+#define mulhwu(x,y) \
+({unsigned z; asm ("mulhwu %0,%1,%2" : "=r" (z) : "r" (x), "r" (y)); z;})
+
+static void printtime(void)
+{
+ unsigned int delta;
+
+ delta = stop_tb[smp_processor_id()][1]
+ - start_tb[smp_processor_id()][1];
+ delta = mulhwu(tb_to_us, delta);
+ printf("%u.%06u seconds\n", delta / 1000000, delta % 1000000);
+}
+
+static void bootcmds(void)
+{
+ int cmd;
+
+ cmd = inchar();
+ if (cmd == 'r')
+ ppc_md.restart(NULL);
+ else if (cmd == 'h')
+ ppc_md.halt();
+ else if (cmd == 'p')
+ ppc_md.power_off();
+}
+
+#ifdef CONFIG_SMP
+static void cpu_cmd(void)
+{
+ unsigned cpu;
+ int timeout;
+ int cmd;
+
+ cmd = inchar();
+ if (cmd == 'i') {
+ /* interrupt other cpu(s) */
+ cpu = MSG_ALL_BUT_SELF;
+ if (scanhex(&cpu))
+ smp_send_xmon_break(cpu);
+ return;
+ }
+ termch = cmd;
+ if (!scanhex(&cpu)) {
+ /* print cpus waiting or in xmon */
+ printf("cpus stopped:");
+ for (cpu = 0; cpu < NR_CPUS; ++cpu) {
+ if (test_bit(cpu, &cpus_in_xmon)) {
+ printf(" %d", cpu);
+ if (cpu == smp_processor_id())
+ printf("*", cpu);
+ }
+ }
+ printf("\n");
+ return;
+ }
+ /* try to switch to cpu specified */
+ take_xmon = cpu;
+ timeout = 10000000;
+ while (take_xmon >= 0) {
+ if (--timeout == 0) {
+ /* yes there's a race here */
+ take_xmon = -1;
+ printf("cpu %u didn't take control\n", cpu);
+ return;
+ }
+ }
+ /* now have to wait to be given control back */
+ while (test_and_set_bit(0, &got_xmon)) {
+ if (take_xmon == smp_processor_id()) {
+ take_xmon = -1;
+ break;
+ }
+ }
+}
+#endif /* CONFIG_SMP */
+
+#ifdef CONFIG_BOOTX_TEXT
+extern boot_infos_t disp_bi;
+
+static void vidcmds(void)
+{
+ int c = inchar();
+ unsigned int val, w;
+ extern int boot_text_mapped;
+
+ if (!boot_text_mapped)
+ return;
+ if (c != '\n' && scanhex(&val)) {
+ switch (c) {
+ case 'd':
+ w = disp_bi.dispDeviceRowBytes
+ / (disp_bi.dispDeviceDepth >> 3);
+ disp_bi.dispDeviceDepth = val;
+ disp_bi.dispDeviceRowBytes = w * (val >> 3);
+ return;
+ case 'p':
+ disp_bi.dispDeviceRowBytes = val;
+ return;
+ case 'w':
+ disp_bi.dispDeviceRect[2] = val;
+ return;
+ case 'h':
+ disp_bi.dispDeviceRect[3] = val;
+ return;
+ }
+ }
+ printf("W = %d (0x%x) H = %d (0x%x) D = %d (0x%x) P = %d (0x%x)\n",
+ disp_bi.dispDeviceRect[2], disp_bi.dispDeviceRect[2],
+ disp_bi.dispDeviceRect[3], disp_bi.dispDeviceRect[3],
+ disp_bi.dispDeviceDepth, disp_bi.dispDeviceDepth,
+ disp_bi.dispDeviceRowBytes, disp_bi.dispDeviceRowBytes);
+}
+#endif /* CONFIG_BOOTX_TEXT */
+
+static unsigned short fcstab[256] = {
+ 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
+ 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
+ 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
+ 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
+ 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
+ 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
+ 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
+ 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
+ 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
+ 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
+ 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
+ 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
+ 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
+ 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
+ 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
+ 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
+ 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
+ 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
+ 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
+ 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
+ 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
+ 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
+ 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
+ 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
+ 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
+ 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
+ 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
+ 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
+ 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
+ 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
+ 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
+ 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
+};
+
+#define FCS(fcs, c) (((fcs) >> 8) ^ fcstab[((fcs) ^ (c)) & 0xff])
+
+static void
+csum(void)
+{
+ unsigned int i;
+ unsigned short fcs;
+ unsigned char v;
+
+ if (!scanhex(&adrs))
+ return;
+ if (!scanhex(&ncsum))
+ return;
+ fcs = 0xffff;
+ for (i = 0; i < ncsum; ++i) {
+ if (mread(adrs+i, &v, 1) == 0) {
+ printf("csum stopped at %x\n", adrs+i);
+ break;
+ }
+ fcs = FCS(fcs, v);
+ }
+ printf("%x\n", fcs);
+}
+
+static void
+bpt_cmds(void)
+{
+ int cmd;
+ unsigned a;
+ int mode, i;
+ struct bpt *bp;
+
+ cmd = inchar();
+ switch (cmd) {
+#if !defined(CONFIG_8xx)
+ case 'd':
+ mode = 7;
+ cmd = inchar();
+ if (cmd == 'r')
+ mode = 5;
+ else if (cmd == 'w')
+ mode = 6;
+ else
+ termch = cmd;
+ cmd = inchar();
+ if (cmd == 'p')
+ mode &= ~4;
+ else
+ termch = cmd;
+ dabr.address = 0;
+ dabr.count = 0;
+ dabr.enabled = scanhex(&dabr.address);
+ scanhex(&dabr.count);
+ if (dabr.enabled)
+ dabr.address = (dabr.address & ~7) | mode;
+ break;
+ case 'i':
+ cmd = inchar();
+ if (cmd == 'p')
+ mode = 2;
+ else
+ mode = 3;
+ iabr.address = 0;
+ iabr.count = 0;
+ iabr.enabled = scanhex(&iabr.address);
+ if (iabr.enabled)
+ iabr.address |= mode;
+ scanhex(&iabr.count);
+ break;
+#endif
+ case 'c':
+ if (!scanhex(&a)) {
+ /* clear all breakpoints */
+ for (i = 0; i < NBPTS; ++i)
+ bpts[i].enabled = 0;
+ iabr.enabled = 0;
+ dabr.enabled = 0;
+ printf("All breakpoints cleared\n");
+ } else {
+ bp = at_breakpoint(a);
+ if (bp == 0) {
+ printf("No breakpoint at %x\n", a);
+ } else {
+ bp->enabled = 0;
+ }
+ }
+ break;
+ default:
+ termch = cmd;
+ if (!scanhex(&a)) {
+ /* print all breakpoints */
+ printf("type address count\n");
+ if (dabr.enabled) {
+ printf("data %.8x %8x [", dabr.address & ~7,
+ dabr.count);
+ if (dabr.address & 1)
+ printf("r");
+ if (dabr.address & 2)
+ printf("w");
+ if (!(dabr.address & 4))
+ printf("p");
+ printf("]\n");
+ }
+ if (iabr.enabled)
+ printf("inst %.8x %8x\n", iabr.address & ~3,
+ iabr.count);
+ for (bp = bpts; bp < &bpts[NBPTS]; ++bp)
+ if (bp->enabled)
+ printf("trap %.8x %8x\n", bp->address,
+ bp->count);
+ break;
+ }
+ bp = at_breakpoint(a);
+ if (bp == 0) {
+ for (bp = bpts; bp < &bpts[NBPTS]; ++bp)
+ if (!bp->enabled)
+ break;
+ if (bp >= &bpts[NBPTS]) {
+ printf("Sorry, no free breakpoints\n");
+ break;
+ }
+ }
+ bp->enabled = 1;
+ bp->address = a;
+ bp->count = 0;
+ scanhex(&bp->count);
+ break;
+ }
+}
+
+static void
+backtrace(struct pt_regs *excp)
+{
+ unsigned sp;
+ unsigned stack[2];
+ struct pt_regs regs;
+ extern char ret_from_except, ret_from_except_full, ret_from_syscall;
+
+ printf("backtrace:\n");
+
+ if (excp != NULL)
+ sp = excp->gpr[1];
+ else
+ sp = getsp();
+ scanhex(&sp);
+ scannl();
+ for (; sp != 0; sp = stack[0]) {
+ if (mread(sp, stack, sizeof(stack)) != sizeof(stack))
+ break;
+ pretty_print_addr(stack[1]);
+ printf(" ");
+ if (stack[1] == (unsigned) &ret_from_except
+ || stack[1] == (unsigned) &ret_from_except_full
+ || stack[1] == (unsigned) &ret_from_syscall) {
+ if (mread(sp+16, ®s, sizeof(regs)) != sizeof(regs))
+ break;
+ printf("\nexception:%x [%x] %x ", regs.trap, sp+16,
+ regs.nip);
+ sp = regs.gpr[1];
+ if (mread(sp, stack, sizeof(stack)) != sizeof(stack))
+ break;
+ }
+ printf("\n");
+ }
+}
+
+int
+getsp(void)
+{
+ int x;
+
+ asm("mr %0,1" : "=r" (x) :);
+ return x;
+}
+
+void
+excprint(struct pt_regs *fp)
+{
+ int trap;
+
+#ifdef CONFIG_SMP
+ printf("cpu %d: ", smp_processor_id());
+#endif /* CONFIG_SMP */
+ printf("vector: %x at pc = ", fp->trap);
+ pretty_print_addr(fp->nip);
+ printf(", lr = ");
+ pretty_print_addr(fp->link);
+ printf("\nmsr = %x, sp = %x [%x]\n", fp->msr, fp->gpr[1], fp);
+ trap = TRAP(fp);
+ if (trap == 0x300 || trap == 0x600)
+ printf("dar = %x, dsisr = %x\n", fp->dar, fp->dsisr);
+ if (current)
+ printf("current = %x, pid = %d, comm = %s\n",
+ current, current->pid, current->comm);
+}
+
+void
+prregs(struct pt_regs *fp)
+{
+ int n;
+ unsigned base;
+
+ if (scanhex(&base))
+ fp = (struct pt_regs *) base;
+ for (n = 0; n < 32; ++n) {
+ printf("R%.2d = %.8x%s", n, fp->gpr[n],
+ (n & 3) == 3? "\n": " ");
+ if (n == 12 && !FULL_REGS(fp)) {
+ printf("\n");
+ break;
+ }
+ }
+ printf("pc = %.8x msr = %.8x lr = %.8x cr = %.8x\n",
+ fp->nip, fp->msr, fp->link, fp->ccr);
+ printf("ctr = %.8x xer = %.8x trap = %4x\n",
+ fp->ctr, fp->xer, fp->trap);
+}
+
+void
+cacheflush(void)
+{
+ int cmd;
+ unsigned nflush;
+
+ cmd = inchar();
+ if (cmd != 'i')
+ termch = cmd;
+ scanhex(&adrs);
+ if (termch != '\n')
+ termch = 0;
+ nflush = 1;
+ scanhex(&nflush);
+ nflush = (nflush + 31) / 32;
+ if (cmd != 'i') {
+ for (; nflush > 0; --nflush, adrs += 0x20)
+ cflush((void *) adrs);
+ } else {
+ for (; nflush > 0; --nflush, adrs += 0x20)
+ cinval((void *) adrs);
+ }
+}
+
+unsigned int
+read_spr(int n)
+{
+ unsigned int instrs[2];
+ int (*code)(void);
+
+ instrs[0] = 0x7c6002a6 + ((n & 0x1F) << 16) + ((n & 0x3e0) << 6);
+ instrs[1] = 0x4e800020;
+ store_inst(instrs);
+ store_inst(instrs+1);
+ code = (int (*)(void)) instrs;
+ return code();
+}
+
+void
+write_spr(int n, unsigned int val)
+{
+ unsigned int instrs[2];
+ int (*code)(unsigned int);
+
+ instrs[0] = 0x7c6003a6 + ((n & 0x1F) << 16) + ((n & 0x3e0) << 6);
+ instrs[1] = 0x4e800020;
+ store_inst(instrs);
+ store_inst(instrs+1);
+ code = (int (*)(unsigned int)) instrs;
+ code(val);
+}
+
+static unsigned int regno;
+extern char exc_prolog;
+extern char dec_exc;
+
+void
+print_sysmap(void)
+{
+ extern char *sysmap;
+ if ( sysmap ) {
+ printf("System.map: \n");
+ if( setjmp(bus_error_jmp) == 0 ) {
+ debugger_fault_handler = handle_fault;
+ sync();
+ xmon_puts(sysmap);
+ sync();
+ }
+ debugger_fault_handler = NULL;
+ }
+ else
+ printf("No System.map\n");
+}
+
+void
+super_regs(void)
+{
+ int i, cmd;
+ unsigned val;
+
+ cmd = skipbl();
+ if (cmd == '\n') {
+ printf("msr = %x, pvr = %x\n", get_msr(), get_pvr());
+ printf("sprg0-3 = %x %x %x %x\n", get_sprg0(), get_sprg1(),
+ get_sprg2(), get_sprg3());
+ printf("srr0 = %x, srr1 = %x\n", get_srr0(), get_srr1());
+#ifdef CONFIG_PPC_STD_MMU
+ printf("sr0-15 =");
+ for (i = 0; i < 16; ++i)
+ printf(" %x", get_sr(i));
+ printf("\n");
+#endif
+ asm("mr %0,1" : "=r" (i) :);
+ printf("sp = %x ", i);
+ asm("mr %0,2" : "=r" (i) :);
+ printf("toc = %x\n", i);
+ return;
+ }
+
+ scanhex(®no);
+ switch (cmd) {
+ case 'w':
+ val = read_spr(regno);
+ scanhex(&val);
+ write_spr(regno, val);
+ /* fall through */
+ case 'r':
+ printf("spr %x = %x\n", regno, read_spr(regno));
+ break;
+ case 's':
+ val = get_sr(regno);
+ scanhex(&val);
+ set_sr(regno, val);
+ break;
+ case 'm':
+ val = get_msr();
+ scanhex(&val);
+ set_msr(val);
+ break;
+ }
+ scannl();
+}
+
+#ifndef CONFIG_PPC_STD_MMU
+static void
+dump_hash_table(void)
+{
+ printf("This CPU doesn't have a hash table.\n");
+}
+#else
+
+#ifndef CONFIG_PPC64BRIDGE
+static void
+dump_hash_table_seg(unsigned seg, unsigned start, unsigned end)
+{
+ extern void *Hash;
+ extern unsigned long Hash_size;
+ unsigned *htab = Hash;
+ unsigned hsize = Hash_size;
+ unsigned v, hmask, va, last_va = 0;
+ int found, last_found, i;
+ unsigned *hg, w1, last_w2 = 0, last_va0 = 0;
+
+ last_found = 0;
+ hmask = hsize / 64 - 1;
+ va = start;
+ start = (start >> 12) & 0xffff;
+ end = (end >> 12) & 0xffff;
+ for (v = start; v < end; ++v) {
+ found = 0;
+ hg = htab + (((v ^ seg) & hmask) * 16);
+ w1 = 0x80000000 | (seg << 7) | (v >> 10);
+ for (i = 0; i < 8; ++i, hg += 2) {
+ if (*hg == w1) {
+ found = 1;
+ break;
+ }
+ }
+ if (!found) {
+ w1 ^= 0x40;
+ hg = htab + ((~(v ^ seg) & hmask) * 16);
+ for (i = 0; i < 8; ++i, hg += 2) {
+ if (*hg == w1) {
+ found = 1;
+ break;
+ }
+ }
+ }
+ if (!(last_found && found && (hg[1] & ~0x180) == last_w2 + 4096)) {
+ if (last_found) {
+ if (last_va != last_va0)
+ printf(" ... %x", last_va);
+ printf("\n");
+ }
+ if (found) {
+ printf("%x to %x", va, hg[1]);
+ last_va0 = va;
+ }
+ last_found = found;
+ }
+ if (found) {
+ last_w2 = hg[1] & ~0x180;
+ last_va = va;
+ }
+ va += 4096;
+ }
+ if (last_found)
+ printf(" ... %x\n", last_va);
+}
+
+#else /* CONFIG_PPC64BRIDGE */
+static void
+dump_hash_table_seg(unsigned seg, unsigned start, unsigned end)
+{
+ extern void *Hash;
+ extern unsigned long Hash_size;
+ unsigned *htab = Hash;
+ unsigned hsize = Hash_size;
+ unsigned v, hmask, va, last_va;
+ int found, last_found, i;
+ unsigned *hg, w1, last_w2, last_va0;
+
+ last_found = 0;
+ hmask = hsize / 128 - 1;
+ va = start;
+ start = (start >> 12) & 0xffff;
+ end = (end >> 12) & 0xffff;
+ for (v = start; v < end; ++v) {
+ found = 0;
+ hg = htab + (((v ^ seg) & hmask) * 32);
+ w1 = 1 | (seg << 12) | ((v & 0xf800) >> 4);
+ for (i = 0; i < 8; ++i, hg += 4) {
+ if (hg[1] == w1) {
+ found = 1;
+ break;
+ }
+ }
+ if (!found) {
+ w1 ^= 2;
+ hg = htab + ((~(v ^ seg) & hmask) * 32);
+ for (i = 0; i < 8; ++i, hg += 4) {
+ if (hg[1] == w1) {
+ found = 1;
+ break;
+ }
+ }
+ }
+ if (!(last_found && found && (hg[3] & ~0x180) == last_w2 + 4096)) {
+ if (last_found) {
+ if (last_va != last_va0)
+ printf(" ... %x", last_va);
+ printf("\n");
+ }
+ if (found) {
+ printf("%x to %x", va, hg[3]);
+ last_va0 = va;
+ }
+ last_found = found;
+ }
+ if (found) {
+ last_w2 = hg[3] & ~0x180;
+ last_va = va;
+ }
+ va += 4096;
+ }
+ if (last_found)
+ printf(" ... %x\n", last_va);
+}
+#endif /* CONFIG_PPC64BRIDGE */
+
+static unsigned hash_ctx;
+static unsigned hash_start;
+static unsigned hash_end;
+
+static void
+dump_hash_table(void)
+{
+ int seg;
+ unsigned seg_start, seg_end;
+
+ hash_ctx = 0;
+ hash_start = 0;
+ hash_end = 0xfffff000;
+ scanhex(&hash_ctx);
+ scanhex(&hash_start);
+ scanhex(&hash_end);
+ printf("Mappings for context %x\n", hash_ctx);
+ seg_start = hash_start;
+ for (seg = hash_start >> 28; seg <= hash_end >> 28; ++seg) {
+ seg_end = (seg << 28) | 0x0ffff000;
+ if (seg_end > hash_end)
+ seg_end = hash_end;
+ dump_hash_table_seg((hash_ctx << 4) + (seg * 0x111),
+ seg_start, seg_end);
+ seg_start = seg_end + 0x1000;
+ }
+}
+#endif /* CONFIG_PPC_STD_MMU */
+
+/*
+ * Stuff for reading and writing memory safely
+ */
+
+int
+mread(unsigned adrs, void *buf, int size)
+{
+ volatile int n;
+ char *p, *q;
+
+ n = 0;
+ if( setjmp(bus_error_jmp) == 0 ){
+ debugger_fault_handler = handle_fault;
+ sync();
+ p = (char *) adrs;
+ q = (char *) buf;
+ switch (size) {
+ case 2: *(short *)q = *(short *)p; break;
+ case 4: *(int *)q = *(int *)p; break;
+ default:
+ for( ; n < size; ++n ) {
+ *q++ = *p++;
+ sync();
+ }
+ }
+ sync();
+ /* wait a little while to see if we get a machine check */
+ __delay(200);
+ n = size;
+ }
+ debugger_fault_handler = NULL;
+ return n;
+}
+
+int
+mwrite(unsigned adrs, void *buf, int size)
+{
+ volatile int n;
+ char *p, *q;
+
+ n = 0;
+ if( setjmp(bus_error_jmp) == 0 ){
+ debugger_fault_handler = handle_fault;
+ sync();
+ p = (char *) adrs;
+ q = (char *) buf;
+ switch (size) {
+ case 2: *(short *)p = *(short *)q; break;
+ case 4: *(int *)p = *(int *)q; break;
+ default:
+ for( ; n < size; ++n ) {
+ *p++ = *q++;
+ sync();
+ }
+ }
+ sync();
+ n = size;
+ } else {
+ printf("*** Error writing address %x\n", adrs + n);
+ }
+ debugger_fault_handler = NULL;
+ return n;
+}
+
+static int fault_type;
+static int fault_except;
+static char *fault_chars[] = { "--", "**", "##" };
+
+static void
+handle_fault(struct pt_regs *regs)
+{
+ fault_except = TRAP(regs);
+ fault_type = TRAP(regs) == 0x200? 0: TRAP(regs) == 0x300? 1: 2;
+ longjmp(bus_error_jmp, 1);
+}
+
+#define SWAP(a, b, t) ((t) = (a), (a) = (b), (b) = (t))
+
+void
+byterev(unsigned char *val, int size)
+{
+ int t;
+
+ switch (size) {
+ case 2:
+ SWAP(val[0], val[1], t);
+ break;
+ case 4:
+ SWAP(val[0], val[3], t);
+ SWAP(val[1], val[2], t);
+ break;
+ }
+}
+
+static int brev;
+static int mnoread;
+
+void
+memex(void)
+{
+ int cmd, inc, i, nslash;
+ unsigned n;
+ unsigned char val[4];
+
+ last_cmd = "m\n";
+ scanhex(&adrs);
+ while ((cmd = skipbl()) != '\n') {
+ switch( cmd ){
+ case 'b': size = 1; break;
+ case 'w': size = 2; break;
+ case 'l': size = 4; break;
+ case 'r': brev = !brev; break;
+ case 'n': mnoread = 1; break;
+ case '.': mnoread = 0; break;
+ }
+ }
+ if( size <= 0 )
+ size = 1;
+ else if( size > 4 )
+ size = 4;
+ for(;;){
+ if (!mnoread)
+ n = mread(adrs, val, size);
+ printf("%.8x%c", adrs, brev? 'r': ' ');
+ if (!mnoread) {
+ if (brev)
+ byterev(val, size);
+ putchar(' ');
+ for (i = 0; i < n; ++i)
+ printf("%.2x", val[i]);
+ for (; i < size; ++i)
+ printf("%s", fault_chars[fault_type]);
+ }
+ putchar(' ');
+ inc = size;
+ nslash = 0;
+ for(;;){
+ if( scanhex(&n) ){
+ for (i = 0; i < size; ++i)
+ val[i] = n >> (i * 8);
+ if (!brev)
+ byterev(val, size);
+ mwrite(adrs, val, size);
+ inc = size;
+ }
+ cmd = skipbl();
+ if (cmd == '\n')
+ break;
+ inc = 0;
+ switch (cmd) {
+ case '\'':
+ for(;;){
+ n = inchar();
+ if( n == '\\' )
+ n = bsesc();
+ else if( n == '\'' )
+ break;
+ for (i = 0; i < size; ++i)
+ val[i] = n >> (i * 8);
+ if (!brev)
+ byterev(val, size);
+ mwrite(adrs, val, size);
+ adrs += size;
+ }
+ adrs -= size;
+ inc = size;
+ break;
+ case ',':
+ adrs += size;
+ break;
+ case '.':
+ mnoread = 0;
+ break;
+ case ';':
+ break;
+ case 'x':
+ case EOF:
+ scannl();
+ return;
+ case 'b':
+ case 'v':
+ size = 1;
+ break;
+ case 'w':
+ size = 2;
+ break;
+ case 'l':
+ size = 4;
+ break;
+ case '^':
+ adrs -= size;
+ break;
+ break;
+ case '/':
+ if (nslash > 0)
+ adrs -= 1 << nslash;
+ else
+ nslash = 0;
+ nslash += 4;
+ adrs += 1 << nslash;
+ break;
+ case '\\':
+ if (nslash < 0)
+ adrs += 1 << -nslash;
+ else
+ nslash = 0;
+ nslash -= 4;
+ adrs -= 1 << -nslash;
+ break;
+ case 'm':
+ scanhex(&adrs);
+ break;
+ case 'n':
+ mnoread = 1;
+ break;
+ case 'r':
+ brev = !brev;
+ break;
+ case '<':
+ n = size;
+ scanhex(&n);
+ adrs -= n;
+ break;
+ case '>':
+ n = size;
+ scanhex(&n);
+ adrs += n;
+ break;
+ }
+ }
+ adrs += inc;
+ }
+}
+
+int
+bsesc(void)
+{
+ int c;
+
+ c = inchar();
+ switch( c ){
+ case 'n': c = '\n'; break;
+ case 'r': c = '\r'; break;
+ case 'b': c = '\b'; break;
+ case 't': c = '\t'; break;
+ }
+ return c;
+}
+
+void
+dump(void)
+{
+ int c;
+
+ c = inchar();
+ if ((isxdigit(c) && c != 'f' && c != 'd') || c == '\n')
+ termch = c;
+ scanhex(&adrs);
+ if( termch != '\n')
+ termch = 0;
+ if( c == 'i' ){
+ scanhex(&nidump);
+ if( nidump == 0 )
+ nidump = 16;
+ adrs += ppc_inst_dump(adrs, nidump);
+ last_cmd = "di\n";
+ } else {
+ scanhex(&ndump);
+ if( ndump == 0 )
+ ndump = 64;
+ prdump(adrs, ndump);
+ adrs += ndump;
+ last_cmd = "d\n";
+ }
+}
+
+void
+prdump(unsigned adrs, int ndump)
+{
+ register int n, m, c, r, nr;
+ unsigned char temp[16];
+
+ for( n = ndump; n > 0; ){
+ printf("%.8x", adrs);
+ putchar(' ');
+ r = n < 16? n: 16;
+ nr = mread(adrs, temp, r);
+ adrs += nr;
+ for( m = 0; m < r; ++m ){
+ putchar((m & 3) == 0 && m > 0? '.': ' ');
+ if( m < nr )
+ printf("%.2x", temp[m]);
+ else
+ printf("%s", fault_chars[fault_type]);
+ }
+ for(; m < 16; ++m )
+ printf(" ");
+ printf(" |");
+ for( m = 0; m < r; ++m ){
+ if( m < nr ){
+ c = temp[m];
+ putchar(' ' <= c && c <= '~'? c: '.');
+ } else
+ putchar(' ');
+ }
+ n -= r;
+ for(; m < 16; ++m )
+ putchar(' ');
+ printf("|\n");
+ if( nr < r )
+ break;
+ }
+}
+
+int
+ppc_inst_dump(unsigned adr, int count)
+{
+ int nr, dotted;
+ unsigned first_adr;
+ unsigned long inst, last_inst = 0;
+ unsigned char val[4];
+
+ dotted = 0;
+ for (first_adr = adr; count > 0; --count, adr += 4){
+ nr = mread(adr, val, 4);
+ if( nr == 0 ){
+ const char *x = fault_chars[fault_type];
+ printf("%.8x %s%s%s%s\n", adr, x, x, x, x);
+ break;
+ }
+ inst = GETWORD(val);
+ if (adr > first_adr && inst == last_inst) {
+ if (!dotted) {
+ printf(" ...\n");
+ dotted = 1;
+ }
+ continue;
+ }
+ dotted = 0;
+ last_inst = inst;
+ printf("%.8x ", adr);
+ printf("%.8x\t", inst);
+ print_insn_big_powerpc(stdout, inst, adr); /* always returns 4 */
+ printf("\n");
+ }
+ return adr - first_adr;
+}
+
+void
+print_address(unsigned addr)
+{
+ printf("0x%x", addr);
+}
+
+/*
+ * Memory operations - move, set, print differences
+ */
+static unsigned mdest; /* destination address */
+static unsigned msrc; /* source address */
+static unsigned mval; /* byte value to set memory to */
+static unsigned mcount; /* # bytes to affect */
+static unsigned mdiffs; /* max # differences to print */
+
+void
+memops(int cmd)
+{
+ scanhex(&mdest);
+ if( termch != '\n' )
+ termch = 0;
+ scanhex(cmd == 's'? &mval: &msrc);
+ if( termch != '\n' )
+ termch = 0;
+ scanhex(&mcount);
+ switch( cmd ){
+ case 'm':
+ memmove((void *)mdest, (void *)msrc, mcount);
+ break;
+ case 's':
+ memset((void *)mdest, mval, mcount);
+ break;
+ case 'd':
+ if( termch != '\n' )
+ termch = 0;
+ scanhex(&mdiffs);
+ memdiffs((unsigned char *)mdest, (unsigned char *)msrc, mcount, mdiffs);
+ break;
+ }
+}
+
+void
+memdiffs(unsigned char *p1, unsigned char *p2, unsigned nb, unsigned maxpr)
+{
+ unsigned n, prt;
+
+ prt = 0;
+ for( n = nb; n > 0; --n )
+ if( *p1++ != *p2++ )
+ if( ++prt <= maxpr )
+ printf("%.8x %.2x # %.8x %.2x\n", (unsigned)p1 - 1,
+ p1[-1], (unsigned)p2 - 1, p2[-1]);
+ if( prt > maxpr )
+ printf("Total of %d differences\n", prt);
+}
+
+static unsigned mend;
+static unsigned mask;
+
+void
+memlocate(void)
+{
+ unsigned a, n;
+ unsigned char val[4];
+
+ last_cmd = "ml";
+ scanhex(&mdest);
+ if (termch != '\n') {
+ termch = 0;
+ scanhex(&mend);
+ if (termch != '\n') {
+ termch = 0;
+ scanhex(&mval);
+ mask = ~0;
+ if (termch != '\n') termch = 0;
+ scanhex(&mask);
+ }
+ }
+ n = 0;
+ for (a = mdest; a < mend; a += 4) {
+ if (mread(a, val, 4) == 4
+ && ((GETWORD(val) ^ mval) & mask) == 0) {
+ printf("%.8x: %.8x\n", a, GETWORD(val));
+ if (++n >= 10)
+ break;
+ }
+ }
+}
+
+static unsigned mskip = 0x1000;
+static unsigned mlim = 0xffffffff;
+
+void
+memzcan(void)
+{
+ unsigned char v;
+ unsigned a;
+ int ok, ook;
+
+ scanhex(&mdest);
+ if (termch != '\n') termch = 0;
+ scanhex(&mskip);
+ if (termch != '\n') termch = 0;
+ scanhex(&mlim);
+ ook = 0;
+ for (a = mdest; a < mlim; a += mskip) {
+ ok = mread(a, &v, 1);
+ if (ok && !ook) {
+ printf("%.8x .. ", a);
+ fflush(stdout);
+ } else if (!ok && ook)
+ printf("%.8x\n", a - mskip);
+ ook = ok;
+ if (a + mskip < a)
+ break;
+ }
+ if (ook)
+ printf("%.8x\n", a - mskip);
+}
+
+void proccall(void)
+{
+ unsigned int args[8];
+ unsigned int ret;
+ int i;
+ typedef unsigned int (*callfunc_t)(unsigned int, unsigned int,
+ unsigned int, unsigned int, unsigned int,
+ unsigned int, unsigned int, unsigned int);
+ callfunc_t func;
+
+ scanhex(&adrs);
+ if (termch != '\n')
+ termch = 0;
+ for (i = 0; i < 8; ++i)
+ args[i] = 0;
+ for (i = 0; i < 8; ++i) {
+ if (!scanhex(&args[i]) || termch == '\n')
+ break;
+ termch = 0;
+ }
+ func = (callfunc_t) adrs;
+ ret = 0;
+ if (setjmp(bus_error_jmp) == 0) {
+ debugger_fault_handler = handle_fault;
+ sync();
+ ret = func(args[0], args[1], args[2], args[3],
+ args[4], args[5], args[6], args[7]);
+ sync();
+ printf("return value is %x\n", ret);
+ } else {
+ printf("*** %x exception occurred\n", fault_except);
+ }
+ debugger_fault_handler = NULL;
+}
+
+/* Input scanning routines */
+int
+skipbl(void)
+{
+ int c;
+
+ if( termch != 0 ){
+ c = termch;
+ termch = 0;
+ } else
+ c = inchar();
+ while( c == ' ' || c == '\t' )
+ c = inchar();
+ return c;
+}
+
+#define N_PTREGS 44
+static char *regnames[N_PTREGS] = {
+ "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
+ "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
+ "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
+ "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
+ "pc", "msr", "or3", "ctr", "lr", "xer", "ccr", "mq",
+ "trap", "dar", "dsisr", "res"
+};
+
+int
+scanhex(unsigned *vp)
+{
+ int c, d;
+ unsigned v;
+
+ c = skipbl();
+ if (c == '%') {
+ /* parse register name */
+ char regname[8];
+ int i;
+
+ for (i = 0; i < sizeof(regname) - 1; ++i) {
+ c = inchar();
+ if (!isalnum(c)) {
+ termch = c;
+ break;
+ }
+ regname[i] = c;
+ }
+ regname[i] = 0;
+ for (i = 0; i < N_PTREGS; ++i) {
+ if (strcmp(regnames[i], regname) == 0) {
+ unsigned *rp = (unsigned *)
+ xmon_regs[smp_processor_id()];
+ if (rp == NULL) {
+ printf("regs not available\n");
+ return 0;
+ }
+ *vp = rp[i];
+ return 1;
+ }
+ }
+ printf("invalid register name '%%%s'\n", regname);
+ return 0;
+ } else if (c == '$') {
+ static char symname[64];
+ int i;
+ for (i=0; i<63; i++) {
+ c = inchar();
+ if (isspace(c)) {
+ termch = c;
+ break;
+ }
+ symname[i] = c;
+ }
+ symname[i++] = 0;
+ *vp = xmon_symbol_to_addr(symname);
+ if (!(*vp)) {
+ printf("unknown symbol\n");
+ return 0;
+ }
+ return 1;
+ }
+
+ d = hexdigit(c);
+ if( d == EOF ){
+ termch = c;
+ return 0;
+ }
+ v = 0;
+ do {
+ v = (v << 4) + d;
+ c = inchar();
+ d = hexdigit(c);
+ } while( d != EOF );
+ termch = c;
+ *vp = v;
+ return 1;
+}
+
+void
+scannl(void)
+{
+ int c;
+
+ c = termch;
+ termch = 0;
+ while( c != '\n' )
+ c = inchar();
+}
+
+int hexdigit(int c)
+{
+ if( '0' <= c && c <= '9' )
+ return c - '0';
+ if( 'A' <= c && c <= 'F' )
+ return c - ('A' - 10);
+ if( 'a' <= c && c <= 'f' )
+ return c - ('a' - 10);
+ return EOF;
+}
+
+void
+getstring(char *s, int size)
+{
+ int c;
+
+ c = skipbl();
+ do {
+ if( size > 1 ){
+ *s++ = c;
+ --size;
+ }
+ c = inchar();
+ } while( c != ' ' && c != '\t' && c != '\n' );
+ termch = c;
+ *s = 0;
+}
+
+static char line[256];
+static char *lineptr;
+
+void
+flush_input(void)
+{
+ lineptr = NULL;
+}
+
+int
+inchar(void)
+{
+ if (lineptr == NULL || *lineptr == 0) {
+ if (fgets(line, sizeof(line), stdin) == NULL) {
+ lineptr = NULL;
+ return EOF;
+ }
+ lineptr = line;
+ }
+ return *lineptr++;
+}
+
+void
+take_input(char *str)
+{
+ lineptr = str;
+}
+
+void
+sysmap_lookup(void)
+{
+ int type = inchar();
+ unsigned addr;
+ static char tmp[64];
+ char* cur;
+
+ extern char *sysmap;
+ extern unsigned long sysmap_size;
+ if ( !sysmap || !sysmap_size )
+ return;
+
+ switch(type) {
+ case 'a':
+ if (scanhex(&addr)) {
+ pretty_print_addr(addr);
+ printf("\n");
+ }
+ termch = 0;
+ break;
+ case 's':
+ getstring(tmp, 64);
+ if( setjmp(bus_error_jmp) == 0 ) {
+ debugger_fault_handler = handle_fault;
+ sync();
+ cur = sysmap;
+ do {
+ cur = strstr(cur, tmp);
+ if (cur) {
+ static char res[64];
+ char *p, *d;
+ p = cur;
+ while(p > sysmap && *p != 10)
+ p--;
+ if (*p == 10) p++;
+ d = res;
+ while(*p && p < (sysmap + sysmap_size) && *p != 10)
+ *(d++) = *(p++);
+ *(d++) = 0;
+ printf("%s\n", res);
+ cur++;
+ }
+ } while (cur);
+ sync();
+ }
+ debugger_fault_handler = NULL;
+ termch = 0;
+ break;
+ }
+}
+
+static int
+pretty_print_addr(unsigned long addr)
+{
+ char *sym;
+ unsigned long saddr;
+
+ printf("%08x", addr);
+ sym = xmon_find_symbol(addr, &saddr);
+ if (sym)
+ printf(" (%s+0x%x)", sym, addr-saddr);
+ return (sym != 0);
+}
+
+char*
+xmon_find_symbol(unsigned long addr, unsigned long* saddr)
+{
+ static char rbuffer[64];
+ char *p, *ep, *limit;
+ unsigned long prev, next;
+ char* psym;
+
+ extern char *sysmap;
+ extern unsigned long sysmap_size;
+ if ( !sysmap || !sysmap_size )
+ return NULL;
+
+ prev = 0;
+ psym = NULL;
+ p = sysmap;
+ limit = p + sysmap_size;
+ if( setjmp(bus_error_jmp) == 0 ) {
+ debugger_fault_handler = handle_fault;
+ sync();
+ do {
+ next = simple_strtoul(p, &p, 16);
+ if (next > addr && prev <= addr) {
+ if (!psym)
+ goto bail;
+ ep = rbuffer;
+ p = psym;
+ while(*p && p < limit && *p == 32)
+ p++;
+ while(*p && p < limit && *p != 10 && (ep - rbuffer) < 63)
+ *(ep++) = *(p++);
+ *(ep++) = 0;
+ if (saddr)
+ *saddr = prev;
+ debugger_fault_handler = NULL;
+ return rbuffer;
+ }
+ prev = next;
+ psym = p;
+ while(*p && p < limit && *p != 10)
+ p++;
+ if (*p) p++;
+ } while(*p && p < limit && next);
+bail:
+ sync();
+ }
+ debugger_fault_handler = NULL;
+ return NULL;
+}
+
+unsigned long
+xmon_symbol_to_addr(char* symbol)
+{
+ char *p, *cur;
+ char *match = NULL;
+ int goodness = 0;
+ int result = 0;
+
+ extern char *sysmap;
+ extern unsigned long sysmap_size;
+ if ( !sysmap || !sysmap_size )
+ return 0;
+
+ if( setjmp(bus_error_jmp) == 0 ) {
+ debugger_fault_handler = handle_fault;
+ sync();
+ cur = sysmap;
+ while(cur) {
+ cur = strstr(cur, symbol);
+ if (cur) {
+ int gd = 1;
+
+ /* best match if equal, better match if
+ * begins with
+ */
+ if (cur == sysmap || *(cur-1) == ' ') {
+ gd++;
+ if (cur[strlen(symbol)] == 10)
+ gd++;
+ }
+ if (gd > goodness) {
+ match = cur;
+ goodness = gd;
+ if (gd == 3)
+ break;
+ }
+ cur++;
+ }
+ }
+ if (goodness) {
+ p = match;
+ while(p > sysmap && *p != 10)
+ p--;
+ if (*p == 10) p++;
+ result = simple_strtoul(p, &p, 16);
+ }
+ sync();
+ }
+ debugger_fault_handler = NULL;
+ return result;
+}