Modifications for 1.1.1:
======================================================================
+* Add CPU Support for MPC 75x;
+ add board support for Eltec BAB750 board
+ Patch by Andreas Heppel, 22 Nov 2001
+
* Fix problem with TFTP server in different subnet, or with
"gatewayip" set when not needed.
Patch by Nye Liu, 21 Nov 2001
E: Anne-Sophie.Harnois@nextream.fr
D: Port to Walnut405 board
+N: Andreas Heppel
+E: aheppel@sysgo.de
+D: CPU Support for MPC 75x; board support for Eltec BAB750
+
N: Josh Huber
E: huber@alum.wpi.edu
D: Port to the Galileo Evaluation Board, and the MPC74xx cpu series.
EVB64260 \
"
-LIST_all="${LIST_8xx} ${LIST_8240} ${LIST_8260} ${LIST_4xx}"
+#########################################################################
+## MPC7xx Systems
+#########################################################################
+
+LIST_7xx=" \
+ BAB750 \
+"
+
+LIST_all="${LIST_8xx} ${LIST_8240} ${LIST_8260} \
+ ${LIST_4xx} ${LIST_74xx} ${LIST_7xx}"
[ $# = 0 ] && set $LIST_all
echo "CPU = mpc74xx" >>config.mk ; \
echo "#include <config_$(@:_config=).h>" >config.h
+#########################################################################
+## MPC7xx Systems
+#########################################################################
+
+BAB750_config: unconfig
+ @echo "Configuring for $(@:_config=) Board..." ; \
+ cd include ; \
+ echo "ARCH = ppc" > config.mk ; \
+ echo "VENDOR= eltec" >>config.mk ; \
+ echo "BOARD = bab750" >>config.mk ; \
+ echo "CPU = mpc75x" >>config.mk ; \
+ echo "#include <config_$(@:_config=).h>" >config.h
+
#########################################################################
clean:
--- /dev/null
+#
+# (C) Copyright 2001
+# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+#
+# See file CREDITS for list of people who contributed to this
+# project.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2 of
+# the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+# MA 02111-1307 USA
+#
+
+include $(TOPDIR)/config.mk
+
+LIB = lib$(BOARD).a
+
+OBJS = $(BOARD).o flash.o ns16550.o ns87308.o serial.o speed.o \
+ dc2114x.o w83c553f.o mpc106_pci.o mpc106.o sym53c8xx.o
+SOBJS = mpc106_init.o
+
+$(LIB): .depend $(OBJS) $(SOBJS)
+ $(AR) crv $@ $^
+
+clean:
+ rm -f $(SOBJS) $(OBJS)
+
+distclean: clean
+ rm -f $(LIB) core *.bak .depend
+
+#########################################################################
+
+.depend: Makefile $(SOBJS:.o=.S) $(OBJS:.o=.c)
+ $(CC) -M $(CFLAGS) $(SOBJS:.o=.S) $(OBJS:.o=.c) > $@
+
+sinclude .depend
+
+#########################################################################
--- /dev/null
+/*
+ * (C) Copyright 2001 Sysgo Real-Time Solutions, GmbH <www.elinos.com>
+ * Andreas Heppel <aheppel@sysgo.de>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <ppcboot.h>
+#include <command.h>
+#include <config.h>
+#include <mpc106.h>
+#include <mk48t59.h>
+
+
+int checkboard (void)
+{
+ printf("BAB 750\n");
+ return 0;
+}
+
+int checkflash (void)
+{
+ /* TODO: XXX XXX XXX */
+ printf ("2 MB ## Test not implemented yet ##\n");
+
+ return (0);
+}
+
+long int dram_size (int board_type)
+{
+ /* No actual initialisation to do - done when setting up PICRs MCCRs ME/SARs etc
+ * in ram_init.S.
+ */
+ #if defined(CFG_MEMTEST)
+
+ register unsigned long reg;
+
+ printf("Testing DRAM\n");
+
+ /* write each mem addr with it's address */
+ for (reg = CFG_MEMTEST_START; reg < CFG_MEMTEST_END; reg+=4
+ *reg = reg;
+
+ for (reg = CFG_MEMTEST_START; reg < CFG_MEMTEST_END; reg+=4
+ {
+ if (*reg != reg)
+ return -1;
+ }
+ #endif
+
+ /* TODO: calculate amount of dram..for now just return MEMTEST_END */
+ return CFG_MEMTEST_END;
+
+}
+
+long int initdram(int board_type)
+{
+ return dram_size(board_type);
+}
+/* ------------------------------------------------------------------------- */
+
+/*
+ * do_reset is done here because in this case it is board specific, since the
+ * 7xx CPUs can only be reset by external HW (the RTC in this case).
+ */
+void
+do_reset (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
+{
+#if defined(CONFIG_RTC_MK48T59)
+ /* trigger watchdog immediately */
+ rtc_set_watchdog(1, RTC_WD_RB_16TH);
+#else
+ #error "You must define the macro CONFIG_RTC_MK48T59."
+#endif
+}
+
+/* ------------------------------------------------------------------------- */
+
+#if defined(CONFIG_WATCHDOG)
+
+/*
+ * Since the 7xx CPUs don't have an internal watchdog, this function is board specific.
+ * We use the RTC here.
+ */
+void watchdog_reset(void)
+{
+#if defined(CONFIG_RTC_MK48T59)
+ /* we use a 32 sec watchdog timer */
+ rtc_set_watchdog(8, RTC_WD_RB_4);
+#else
+ #error "You must define the macro CONFIG_RTC_MK48T59."
+#endif
+}
+#endif /* CONFIG_WATCHDOG */
+
+
--- /dev/null
+#
+# (C) Copyright 2000
+# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+#
+# See file CREDITS for list of people who contributed to this
+# project.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2 of
+# the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+# MA 02111-1307 USA
+#
+
+#
+# BAB740 boards
+#
+
+TEXT_BASE = 0xFFC00000
+#TEXT_BASE = 0x400000
+
+PLATFORM_CPPFLAGS += -DTEXT_BASE=$(TEXT_BASE)
--- /dev/null
+/*
+ * 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 <ppcboot.h>
+#include <net.h>
+#include <mpc106.h>
+
+
+/* PCI Registers.
+ */
+#define PCI_CFDA_PSM 0x43
+
+#define CFRV_RN 0x000000f0 /* Revision Number */
+#define CBIO_MASK 0xffffff80
+
+#define WAKEUP 0x00 /* Power Saving Wakeup */
+#define SLEEP 0x80 /* Power Saving Sleep Mode */
+
+
+#define DC2114x_VID 0x1011 /* DC2114[23] Manufacturer */
+#define DC2114x_DID 0x0019 /* Unique Device ID # */
+#define DC2114x_BRK 0x0020 /* CFRV break between DC21142 & DC21143 */
+#define DC21142 (DC2114x_DID << 8 | 0x0010)
+#define DC21143 (DC2114x_DID << 8 | 0x0030)
+
+#define is_DC2114x ((vendor == DC2114x_VID) && (device == DC2114x_DID))
+
+/* Ethernet chip registers.
+ */
+#define DE4X5_BMR iobase + 0x000 /* Bus Mode Register */
+#define DE4X5_TPD iobase + 0x008 /* Transmit Poll Demand Reg */
+#define DE4X5_RRBA iobase + 0x018 /* RX Ring Base Address Reg */
+#define DE4X5_TRBA iobase + 0x020 /* TX Ring Base Address Reg */
+#define DE4X5_STS iobase + 0x028 /* Status Register */
+#define DE4X5_OMR iobase + 0x030 /* Operation Mode Register */
+#define DE4X5_SICR iobase + 0x068 /* SIA Connectivity Register */
+#define DE4X5_APROM iobase + 0x048 /* Ethernet Address PROM */
+
+/* Register bits.
+ */
+#define BMR_SWR 0x00000001 /* Software Reset */
+#define STS_TS 0x00700000 /* Transmit Process State */
+#define STS_RS 0x000e0000 /* Receive Process State */
+#define OMR_ST 0x00002000 /* Start/Stop Transmission Command */
+#define OMR_SR 0x00000002 /* Start/Stop Receive */
+#define OMR_PS 0x00040000 /* Port Select */
+#define OMR_SDP 0x02000000 /* SD Polarity - MUST BE ASSERTED */
+#define OMR_PM 0x00000080 /* Pass All Multicast */
+
+/* Descriptor bits.
+ */
+#define R_OWN 0x80000000 /* Own Bit */
+#define RD_RER 0x02000000 /* Receive End Of Ring */
+#define RD_LS 0x00000100 /* Last Descriptor */
+#define RD_ES 0x00008000 /* Error Summary */
+#define TD_TER 0x02000000 /* Transmit End Of Ring */
+#define T_OWN 0x80000000 /* Own Bit */
+#define TD_LS 0x40000000 /* Last Segment */
+#define TD_FS 0x20000000 /* First Segment */
+#define TD_ES 0x00008000 /* Error Summary */
+#define TD_SET 0x08000000 /* Setup Packet */
+
+
+#define SROM_HWADD 0x0014 /* Hardware Address offset in SROM */
+#define SROM_RD 0x00004000 /* Read from Boot ROM */
+#define SROM_SR 0x00000800 /* Select Serial ROM when set */
+
+#define DT_IN 0x00000004 /* Serial Data In */
+#define DT_CLK 0x00000002 /* Serial ROM Clock */
+#define DT_CS 0x00000001 /* Serial ROM Chip Select */
+
+#define POLL_DEMAND 1
+
+#define RESET_DE4X5 {\
+ int i;\
+ i=inl(DE4X5_BMR);\
+ udelay(1000);\
+ outl(i | BMR_SWR, DE4X5_BMR);\
+ udelay(1000);\
+ outl(i, DE4X5_BMR);\
+ udelay(1000);\
+ for (i=0;i<5;i++) {inl(DE4X5_BMR); udelay(10000);}\
+ udelay(1000);\
+}
+
+#define START_DE4X5 {\
+ s32 omr; \
+ omr = inl(DE4X5_OMR);\
+ omr |= OMR_ST | OMR_SR;\
+ outl(omr, DE4X5_OMR); /* Enable the TX and/or RX */\
+}
+
+#define STOP_DE4X5 {\
+ s32 omr; \
+ omr = inl(DE4X5_OMR);\
+ omr &= ~(OMR_ST|OMR_SR);\
+ outl(omr, DE4X5_OMR); /* Disable the TX and/or RX */ \
+}
+
+#define NUM_RX_DESC PKTBUFSRX
+#define NUM_TX_DESC 1 /* Number of TX descriptors */
+#define RX_BUFF_SZ PKTSIZE_ALIGN
+
+#define TOUT_LOOP 1000000
+
+#define SETUP_FRAME_LEN 192
+#define ETH_ALEN 6
+
+
+struct de4x5_desc {
+ volatile s32 status;
+ u32 des1;
+ u32 buf;
+ u32 next;
+};
+
+static struct de4x5_desc rx_ring[NUM_RX_DESC]; /* RX descriptor ring */
+static struct de4x5_desc tx_ring[NUM_TX_DESC]; /* TX descriptor ring */
+static int rx_new; /* RX descriptor ring pointer */
+static int tx_new; /* TX descriptor ring pointer */
+
+static char rxRingSize;
+static char txRingSize;
+
+static u_long iobase;
+
+unsigned int PCI_Read_CFG_Reg(int BusDevFunc, int Reg, int Width);
+int PCI_Write_CFG_Reg(int BusDevFunc, int Reg, unsigned int Value, int Width);
+
+static void send_setup_frame(bd_t * bis);
+static void check_hw_addr(bd_t * bis);
+static short srom_rd(u_long address, u_char offset);
+static void srom_latch(u_int command, u_long address);
+static void srom_command(u_int command, u_long address);
+static void srom_address(u_int command, u_long address, u_char offset);
+static short srom_data(u_int command, u_long address);
+static void sendto_srom(u_int command, u_long addr);
+static int getfrom_srom(u_long addr);
+
+static int inl(u_long addr)
+{
+ return le32_to_cpu(*(volatile u_long *)(addr));
+}
+
+static void outl (int command, u_long addr)
+{
+ *(volatile u_long *)(addr) = cpu_to_le32(command);
+}
+
+
+int devbusfn = 0;
+
+int eth_init(bd_t *bis)
+{
+ int i, status = 0;
+ int device;
+ int cfrv;
+ unsigned char timer;
+
+ devbusfn = PCI_Find_Device(DC2114x_VID, DC2114x_DID);
+ if (devbusfn == -1)
+ {
+ printf("Error: Cannot find an ethernet card on any PCI bus.");
+ goto Done;
+ }
+
+ /* Get the chip configuration revision register. */
+ cfrv = PCI_Read_CFG_Reg(devbusfn, PCI_CFG_REVISION, 4);
+
+ device = ((cfrv & CFRV_RN) < DC2114x_BRK ? DC21142 : DC21143);
+
+ if (device != DC21143)
+ {
+ printf("Error: The chip is not DC21143.\n");
+ goto Done;
+ }
+
+ status = PCI_Read_CFG_Reg(devbusfn, PCI_CFG_COMMAND, 2);
+ status |= PCI_CMD_MASTER | PCI_CMD_IOEN | PCI_CMD_MEMEN;
+ PCI_Write_CFG_Reg(devbusfn, PCI_CFG_COMMAND, status, 2);
+
+ /* Check the latency timer for values >= 0x60. */
+ timer = PCI_Read_CFG_Reg(devbusfn, PCI_CFG_LATENCY_TIMER, 1);
+
+ if (timer < 0x60)
+ {
+ PCI_Write_CFG_Reg(devbusfn, PCI_CFG_LATENCY_TIMER, 0x60, 1);
+ }
+
+ /* read BAR for memory space access */
+ iobase = PCI_Read_CFG_Reg(devbusfn, PCI_CFG_BASE_ADDRESS_1, 4);
+
+ iobase &= CBIO_MASK;
+ iobase |= CFG_60X_PCI_MEM_OFFSET;
+
+ /* Ensure we're not sleeping. */
+ PCI_Write_CFG_Reg(devbusfn, PCI_CFDA_PSM, WAKEUP, 1);
+
+ udelay(10 * 1000);
+
+ check_hw_addr(bis);
+
+ RESET_DE4X5;
+
+ if ((inl(DE4X5_STS) & (STS_TS | STS_RS)) != 0)
+ {
+ printf("Error: Cannot reset ethernet controller.\n");
+ goto Done;
+ }
+
+ outl(OMR_SDP | OMR_PS | OMR_PM, DE4X5_OMR);
+
+ for (i = 0; i < NUM_RX_DESC; i++)
+ {
+ rx_ring[i].status = cpu_to_le32(R_OWN);
+ rx_ring[i].des1 = cpu_to_le32(RX_BUFF_SZ);
+ rx_ring[i].buf = cpu_to_le32(phys_to_bus((void*)NetRxPackets[i]));
+ rx_ring[i].next = 0;
+ }
+
+ for (i=0; i < NUM_TX_DESC; i++)
+ {
+ tx_ring[i].status = 0;
+ tx_ring[i].des1 = 0;
+ tx_ring[i].buf = 0;
+ tx_ring[i].next = 0;
+ }
+
+ rxRingSize = NUM_RX_DESC;
+ txRingSize = NUM_TX_DESC;
+
+ /* Write the end of list marker to the descriptor lists. */
+ rx_ring[rxRingSize - 1].des1 |= cpu_to_le32(RD_RER);
+ tx_ring[txRingSize - 1].des1 |= cpu_to_le32(TD_TER);
+
+ /* Tell the adapter where the TX/RX rings are located. */
+ outl(phys_to_bus(&rx_ring), DE4X5_RRBA);
+ outl(phys_to_bus(&tx_ring), DE4X5_TRBA);
+
+ START_DE4X5;
+
+ tx_new = 0;
+ rx_new = 0;
+
+ send_setup_frame(bis);
+
+Done:
+ return 0;
+}
+
+int eth_send(volatile void *packet, int length)
+{
+ int status = 0;
+ int i;
+
+ if (length <= 0)
+ {
+ printf("eth: bad packet size: %d\n", length);
+ goto out;
+ }
+
+ for(i = 0; tx_ring[tx_new].status & cpu_to_le32(T_OWN); i++)
+ {
+ if (i >= TOUT_LOOP)
+ {
+ printf("eth: tx error buffer not ready\n");
+ goto out;
+ }
+ }
+
+ tx_ring[tx_new].buf = cpu_to_le32(phys_to_bus((void*)packet));
+ tx_ring[tx_new].des1 = cpu_to_le32(TD_TER | TD_LS | TD_FS | length);
+ tx_ring[tx_new].status = cpu_to_le32(T_OWN);
+
+ outl(POLL_DEMAND, DE4X5_TPD);
+
+ for(i = 0; tx_ring[tx_new].status & cpu_to_le32(T_OWN); i++)
+ {
+ if (i >= TOUT_LOOP)
+ {
+ printf("eth: tx buffer not ready\n");
+ goto out;
+ }
+ }
+
+#if 0 /* test-only */
+ if (le32_to_cpu(tx_ring[tx_new].status) & TD_ES)
+ {
+ printf("TX error status = 0x%08X\n",
+ le32_to_cpu(tx_ring[tx_new].status));
+ status++;
+ }
+#endif
+
+ out:
+ return status;
+}
+
+int eth_rx(void)
+{
+ s32 status;
+ int length = 0;
+
+ for ( ; ; ) {
+ status = (s32)le32_to_cpu(rx_ring[rx_new].status);
+
+ if (status & R_OWN) {
+ break;
+ }
+
+ if (status & RD_LS) {
+ /* Valid frame status.
+ */
+ if (status & RD_ES) {
+ /* There was an error.
+ */
+ printf("RX error status = 0x%08X\n", status);
+ }
+ else {
+ /* A valid frame received.
+ */
+ length = (le32_to_cpu(rx_ring[rx_new].status) >>
+ 16);
+
+ /* Pass the packet up to the protocol
+ * layers.
+ */
+ NetReceive(NetRxPackets[rx_new], length - 4);
+ }
+
+ /* Change buffer ownership for this frame, back
+ * to the adapter.
+ */
+ rx_ring[rx_new].status = cpu_to_le32(R_OWN);
+ }
+
+ /* Update entry information.
+ */
+ rx_new = (++rx_new) % rxRingSize;
+ }
+
+ return length;
+}
+
+void eth_halt(void)
+{
+#if 1
+ STOP_DE4X5;
+ outl(0, DE4X5_SICR);
+ if (devbusfn > 0)
+ PCI_Write_CFG_Reg(devbusfn, PCI_CFDA_PSM, SLEEP, 1);
+#endif
+}
+
+static void check_hw_addr(bd_t *bis)
+{
+ unsigned char hw_addr[ETH_ALEN];
+ u_short tmp, *p = (short *)(&hw_addr[0]);
+ int i, j = 0;
+
+ for (i = 0; i < (ETH_ALEN >> 1); i++) {
+ tmp = srom_rd(DE4X5_APROM, (SROM_HWADD >> 1) + i);
+ *p = le16_to_cpu(tmp);
+ j += *p++;
+ }
+
+ if ((j == 0) || (j == 0x2fffd)) {
+ printf("Warning: can't read HW address from SROM.\n");
+ goto Done;
+ }
+
+ for (i = 0; i < ETH_ALEN; i++) {
+ if (hw_addr[i] != bis->bi_enetaddr[i]) {
+ printf("Warning: HW addresses don't match:\n");
+ printf("Address in SROM is "
+ "%02X:%02X:%02X:%02X:%02X:%02X\n",
+ hw_addr[0], hw_addr[1], hw_addr[2],
+ hw_addr[3], hw_addr[4], hw_addr[5]);
+ printf("Address used by ppcboot is "
+ "%02X:%02X:%02X:%02X:%02X:%02X\n",
+ bis->bi_enetaddr[0], bis->bi_enetaddr[1],
+ bis->bi_enetaddr[2], bis->bi_enetaddr[3],
+ bis->bi_enetaddr[4], bis->bi_enetaddr[5]);
+ goto Done;
+ }
+ }
+
+Done:
+}
+
+static void send_setup_frame(bd_t *bis)
+{
+ int i;
+ char setup_frame[SETUP_FRAME_LEN];
+ char *pa = &setup_frame[0];
+
+ memset(pa, 0xff, SETUP_FRAME_LEN);
+
+ for (i = 0; i < ETH_ALEN; i++) {
+ *(pa + (i & 1)) = bis->bi_enetaddr[i];
+ if (i & 0x01)
+ {
+ pa += 4;
+ }
+ }
+
+ for(i = 0; tx_ring[tx_new].status & cpu_to_le32(T_OWN); i++) {
+ if (i >= TOUT_LOOP) {
+ printf("eth: tx error buffer not ready\n");
+ goto out;
+ }
+ }
+
+ tx_ring[tx_new].buf = cpu_to_le32(phys_to_bus(&setup_frame[0]));
+ tx_ring[tx_new].des1 = cpu_to_le32(TD_TER | TD_SET| SETUP_FRAME_LEN);
+ tx_ring[tx_new].status = cpu_to_le32(T_OWN);
+
+ outl(POLL_DEMAND, DE4X5_TPD);
+
+ for(i = 0; tx_ring[tx_new].status & cpu_to_le32(T_OWN); i++) {
+ if (i >= TOUT_LOOP) {
+ printf("eth: tx buffer not ready\n");
+ goto out;
+ }
+ }
+
+ if (le32_to_cpu(tx_ring[tx_new].status) != 0x7FFFFFFF) {
+ printf("TX error status2 = 0x%08X\n", le32_to_cpu(tx_ring[tx_new].status));
+ }
+out:
+}
+
+/* SROM Read.
+ */
+static short
+srom_rd(u_long addr, u_char offset)
+{
+ sendto_srom(SROM_RD | SROM_SR, addr);
+
+ srom_latch(SROM_RD | SROM_SR | DT_CS, addr);
+ srom_command(SROM_RD | SROM_SR | DT_IN | DT_CS, addr);
+ srom_address(SROM_RD | SROM_SR | DT_CS, addr, offset);
+
+ return srom_data(SROM_RD | SROM_SR | DT_CS, addr);
+}
+
+static void
+srom_latch(u_int command, u_long addr)
+{
+ sendto_srom(command, addr);
+ sendto_srom(command | DT_CLK, addr);
+ sendto_srom(command, addr);
+
+ return;
+}
+
+static void
+srom_command(u_int command, u_long addr)
+{
+ srom_latch(command, addr);
+ srom_latch(command, addr);
+ srom_latch((command & 0x0000ff00) | DT_CS, addr);
+
+ return;
+}
+
+static void
+srom_address(u_int command, u_long addr, u_char offset)
+{
+ int i;
+ signed char a;
+
+ a = (char)(offset << 2);
+ for (i=0; i<6; i++, a <<= 1) {
+ srom_latch(command | ((a < 0) ? DT_IN : 0), addr);
+ }
+ udelay(1);
+
+ i = (getfrom_srom(addr) >> 3) & 0x01;
+
+ return;
+}
+
+static short
+srom_data(u_int command, u_long addr)
+{
+ int i;
+ short word = 0;
+ s32 tmp;
+
+ for (i=0; i<16; i++) {
+ sendto_srom(command | DT_CLK, addr);
+ tmp = getfrom_srom(addr);
+ sendto_srom(command, addr);
+
+ word = (word << 1) | ((tmp >> 3) & 0x01);
+ }
+
+ sendto_srom(command & 0x0000ff00, addr);
+
+ return word;
+}
+
+static void
+sendto_srom(u_int command, u_long addr)
+{
+ outl(command, addr);
+ udelay(1);
+
+ return;
+}
+
+static int
+getfrom_srom(u_long addr)
+{
+ s32 tmp;
+
+ tmp = inl(addr);
+ udelay(1);
+
+ return tmp;
+}
+
--- /dev/null
+/*
+ * (C) Copyright 2000
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+/*
+ * 09-18-2001, Andreas Heppel: Reduced the code in here to the usage
+ * of AMD's 29F040 and 29F016 flashes, since the BAB750 does use
+ * any other.
+ */
+
+#include <ppcboot.h>
+#include <asm/processor.h>
+#include <asm/pci_io.h>
+
+flash_info_t flash_info[CFG_MAX_FLASH_BANKS]; /* info for FLASH chips */
+
+/*-----------------------------------------------------------------------
+ * Functions
+ */
+ulong flash_get_size (vu_long *addr, flash_info_t *info);
+static int write_word (flash_info_t *info, ulong dest, ulong data);
+
+/*flash command address offsets*/
+
+#define ADDR0 (0x555)
+#define ADDR1 (0x2AA)
+#define ADDR3 (0x001)
+
+#define FLASH_WORD_SIZE unsigned char
+
+/*-----------------------------------------------------------------------
+ */
+
+unsigned long flash_init (void)
+{
+ unsigned long size1, size2;
+ int i;
+ unsigned long base;
+
+
+ /* Init: no FLASHes known */
+ for (i=0; i<CFG_MAX_FLASH_BANKS; ++i) {
+ flash_info[i].flash_id = FLASH_UNKNOWN;
+ }
+
+ /* initialise 1st flash */
+ size1 = flash_get_size((vu_long *)FLASH_BASE0_PRELIM, &flash_info[0]);
+
+ if (flash_info[0].flash_id == FLASH_UNKNOWN) {
+ printf ("## Unknown FLASH on Bank 0 - Size = 0x%08lx = %ld MB\n",
+ size1, size1<<20);
+ }
+
+ /* monitor protection ON by default */
+ flash_protect(FLAG_PROTECT_SET,
+ base + size1 - CFG_MONITOR_LEN,
+ base + size1 - 1,
+ &flash_info[0]);
+
+ /* initialise 2nd flash */
+ size2 = flash_get_size((vu_long *)FLASH_BASE1_PRELIM, &flash_info[1]);
+
+ if (flash_info[0].flash_id == FLASH_UNKNOWN) {
+ printf ("## Unknown FLASH on Bank 1 - Size = 0x%08lx = %ld MB\n",
+ size2, size2<<20);
+ }
+
+ return (size1 + size2);
+}
+
+/*-----------------------------------------------------------------------
+ */
+void flash_print_info (flash_info_t *info)
+{
+ int i;
+ int k;
+ int size;
+ int erased;
+ volatile unsigned long *flash;
+
+ if (info->flash_id == FLASH_UNKNOWN) {
+ printf ("missing or unknown FLASH type\n");
+ flash_init();
+ }
+
+ if (info->flash_id == FLASH_UNKNOWN) {
+ printf ("missing or unknown FLASH type\n");
+ return;
+ }
+
+ switch (info->flash_id & FLASH_VENDMASK) {
+ case FLASH_MAN_AMD:
+ printf ("AMD ");
+ break;
+ default:
+ printf ("Unknown Vendor ");
+ break;
+ }
+
+ switch (info->flash_id & FLASH_TYPEMASK) {
+ case AMD_ID_F040B:
+ printf ("AM29F040B (4 Mbit)\n");
+ break;
+ case AMD_ID_F016D:
+ printf ("AM29F016D (16 Mbit)\n");
+ break;
+ default:
+ printf ("Unknown Chip Type\n");
+ break;
+ }
+
+ if (info->size >= (1 << 20)) {
+ printf (" Size: %ld MB in %d Sectors\n", info->size >> 20, info->sector_count);
+ } else {
+ printf (" Size: %ld kB in %d Sectors\n", info->size >> 10, info->sector_count);
+ }
+
+ printf (" Sector Start Addresses:");
+ for (i=0; i<info->sector_count; ++i) {
+ /*
+ * Check if whole sector is erased
+ */
+ if (i != (info->sector_count-1))
+ size = info->start[i+1] - info->start[i];
+ else
+ size = info->start[0] + info->size - info->start[i];
+
+ erased = 1;
+ flash = (volatile unsigned long *)info->start[i];
+ size = size >> 2; /* divide by 4 for longword access */
+ for (k=0; k<size; k++) {
+ if (*flash++ != 0xffffffff) {
+ erased = 0;
+ break;
+ }
+ }
+
+ if ((i % 5) == 0)
+ printf ("\n ");
+
+ printf (" %08lX%s%s",
+ info->start[i],
+ erased ? " E" : " ",
+ info->protect[i] ? "RO " : " ");
+ }
+ printf ("\n");
+}
+
+
+/*-----------------------------------------------------------------------
+ */
+
+/*
+ * The following code cannot be run from FLASH!
+ */
+ulong flash_get_size (vu_long *addr, flash_info_t *info)
+{
+ short i;
+ ulong vendor, devid;
+ ulong base = (ulong)addr;
+ volatile unsigned char *caddr = (unsigned char *)addr;
+
+#ifdef DEBUG
+ printf("flash_get_size for address 0x%lx: \n", (unsigned long)caddr);
+#endif
+
+ /* Write auto select command: read Manufacturer ID */
+ caddr[0] = 0xF0; /* reset bank */
+ udelay(10);
+
+ eieio();
+ caddr[0x555] = 0xAA;
+ udelay(10);
+ caddr[0x2AA] = 0x55;
+ udelay(10);
+ caddr[0x555] = 0x90;
+
+ udelay(10);
+
+ vendor = caddr[0];
+ devid = caddr[1];
+
+#ifdef DEBUG
+ printf("Manufacturer: 0x%lx\n", vendor);
+#endif
+
+ vendor &= 0xff;
+ devid &= 0xff;
+
+ /* We accept only two AMD types */
+ switch (vendor) {
+ case (FLASH_WORD_SIZE)AMD_MANUFACT:
+ info->flash_id = FLASH_MAN_AMD;
+ break;
+ default:
+ info->flash_id = FLASH_UNKNOWN;
+ info->sector_count = 0;
+ info->size = 0;
+ return (0); /* no or unknown flash */
+ }
+
+ switch (devid) {
+ case (FLASH_WORD_SIZE)AMD_ID_F040B:
+ info->flash_id |= AMD_ID_F040B;
+ info->sector_count = 8;
+ info->size = 0x00080000;
+ break; /* => 0.5 MB */
+
+ case (FLASH_WORD_SIZE)AMD_ID_F016D:
+ info->flash_id |= AMD_ID_F016D;
+ info->sector_count = 32;
+ info->size = 0x00200000;
+ break; /* => 2 MB */
+
+ default:
+ info->flash_id = FLASH_UNKNOWN;
+ return (0); /* => no or unknown flash */
+
+ }
+
+#ifdef DEBUG
+ printf("flash id 0x%lx; sector count 0x%x, size 0x%lx\n", info->flash_id, info->sector_count, info->size);
+#endif
+
+ /* check for protected sectors */
+ for (i = 0; i < info->sector_count; i++) {
+ /* sector base address */
+ info->start[i] = base + i * (info->size / info->sector_count);
+ /* read sector protection at sector address, (A7 .. A0) = 0x02 */
+ /* D0 = 1 if protected */
+ caddr = (volatile unsigned char *)(info->start[i]);
+ info->protect[i] = caddr[2] & 1;
+ }
+
+ /*
+ * Prevent writes to uninitialized FLASH.
+ */
+ if (info->flash_id != FLASH_UNKNOWN) {
+ caddr = (volatile unsigned char *)info->start[0];
+ caddr[0] = 0xF0; /* reset bank */
+ }
+
+ return (info->size);
+}
+
+
+/*-----------------------------------------------------------------------
+ */
+
+int flash_erase (flash_info_t *info, int s_first, int s_last)
+{
+ volatile FLASH_WORD_SIZE *addr = (FLASH_WORD_SIZE *)(info->start[0]);
+ int flag, prot, sect, l_sect;
+ ulong start, now, last;
+
+ if ((s_first < 0) || (s_first > s_last)) {
+ if (info->flash_id == FLASH_UNKNOWN) {
+ printf ("- missing\n");
+ } else {
+ printf ("- no sectors to erase\n");
+ }
+ return ERR_NOT_ERASED;
+ }
+
+ if ((info->flash_id == FLASH_UNKNOWN) || (info->flash_id > FLASH_AMD_COMP)) {
+ printf ("Can't erase unknown flash type - aborted\n");
+ return ERR_NOT_ERASED;
+ }
+
+ prot = 0;
+ for (sect=s_first; sect<=s_last; ++sect) {
+ if (info->protect[sect]) {
+ prot++;
+ }
+ }
+
+ if (prot) {
+ printf ("- Warning: %d protected sectors will not be erased!\n", prot);
+ } else {
+ printf ("\n");
+ }
+
+ l_sect = -1;
+
+ /* Disable interrupts which might cause a timeout here */
+ flag = disable_interrupts();
+
+ addr[ADDR0] = (FLASH_WORD_SIZE)0x00AA00AA;
+ addr[ADDR1] = (FLASH_WORD_SIZE)0x00550055;
+ addr[ADDR0] = (FLASH_WORD_SIZE)0x00800080;
+ addr[ADDR0] = (FLASH_WORD_SIZE)0x00AA00AA;
+ addr[ADDR1] = (FLASH_WORD_SIZE)0x00550055;
+
+ /* Start erase on unprotected sectors */
+ for (sect = s_first; sect<=s_last; sect++) {
+ if (info->protect[sect] == 0) { /* not protected */
+ addr = (FLASH_WORD_SIZE *)(info->start[sect]);
+ if (info->flash_id & FLASH_MAN_SST) {
+ addr[ADDR0] = (FLASH_WORD_SIZE)0x00AA00AA;
+ addr[ADDR1] = (FLASH_WORD_SIZE)0x00550055;
+ addr[ADDR0] = (FLASH_WORD_SIZE)0x00800080;
+ addr[ADDR0] = (FLASH_WORD_SIZE)0x00AA00AA;
+ addr[ADDR1] = (FLASH_WORD_SIZE)0x00550055;
+ addr[0] = (FLASH_WORD_SIZE)0x00500050; /* block erase */
+ udelay(30000); /* wait 30 ms */
+ }
+ else
+ addr[0] = (FLASH_WORD_SIZE)0x00300030; /* sector erase */
+ l_sect = sect;
+ }
+ }
+
+ /* re-enable interrupts if necessary */
+ if (flag)
+ enable_interrupts();
+
+ /* wait at least 80us - let's wait 1 ms */
+ udelay (1000);
+
+ /*
+ * We wait for the last triggered sector
+ */
+ if (l_sect < 0)
+ goto DONE;
+
+ start = get_timer (0);
+ last = start;
+ addr = (FLASH_WORD_SIZE *)(info->start[l_sect]);
+ while ((addr[0] & (FLASH_WORD_SIZE)0x00800080) != (FLASH_WORD_SIZE)0x00800080) {
+ if ((now = get_timer(start)) > CFG_FLASH_ERASE_TOUT) {
+ printf ("Timeout\n");
+ return ERR_TIMOUT;
+ }
+ /* show that we're waiting */
+ if ((now - last) > 1000) { /* every second */
+ serial_putc ('.');
+ last = now;
+ }
+ }
+
+DONE:
+ /* reset to read mode */
+ addr = (FLASH_WORD_SIZE *)info->start[0];
+ addr[0] = (FLASH_WORD_SIZE)0x00F000F0; /* reset bank */
+
+ printf (" done\n");
+ return ERR_OK;
+}
+
+/*-----------------------------------------------------------------------
+ * Copy memory to flash, returns:
+ * 0 - OK
+ * 1 - write timeout
+ * 2 - Flash not erased
+ */
+
+int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt)
+{
+ ulong cp, wp, data;
+ int i, l, rc;
+
+ wp = (addr & ~3); /* get lower word aligned address */
+
+ /*
+ * handle unaligned start bytes
+ */
+ if ((l = addr - wp) != 0) {
+ data = 0;
+ for (i=0, cp=wp; i<l; ++i, ++cp) {
+ data = (data << 8) | (*(uchar *)cp);
+ }
+ for (; i<4 && cnt>0; ++i) {
+ data = (data << 8) | *src++;
+ --cnt;
+ ++cp;
+ }
+ for (; cnt==0 && i<4; ++i, ++cp) {
+ data = (data << 8) | (*(uchar *)cp);
+ }
+
+ if ((rc = write_word(info, wp, data)) != 0) {
+ return (rc);
+ }
+ wp += 4;
+ }
+
+ /*
+ * handle word aligned part
+ */
+ while (cnt >= 4) {
+ data = 0;
+ for (i=0; i<4; ++i) {
+ data = (data << 8) | *src++;
+ }
+ if ((rc = write_word(info, wp, data)) != 0) {
+ return (rc);
+ }
+ wp += 4;
+ cnt -= 4;
+ }
+
+ if (cnt == 0) {
+ return (0);
+ }
+
+ /*
+ * handle unaligned tail bytes
+ */
+ data = 0;
+ for (i=0, cp=wp; i<4 && cnt>0; ++i, ++cp) {
+ data = (data << 8) | *src++;
+ --cnt;
+ }
+ for (; i<4; ++i, ++cp) {
+ data = (data << 8) | (*(uchar *)cp);
+ }
+
+ return (write_word(info, wp, data));
+}
+
+/*-----------------------------------------------------------------------
+ * Write a word to Flash, returns:
+ * 0 - OK
+ * 1 - write timeout
+ * 2 - Flash not erased
+ */
+static int write_word (flash_info_t *info, ulong dest, ulong data)
+{
+ volatile FLASH_WORD_SIZE *addr2 = (FLASH_WORD_SIZE *)(info->start[0]);
+ volatile FLASH_WORD_SIZE *dest2 = (FLASH_WORD_SIZE *)dest;
+ volatile FLASH_WORD_SIZE *data2 = (FLASH_WORD_SIZE *)&data;
+ ulong start;
+ int flag;
+ int i;
+
+ /* Check if Flash is (sufficiently) erased */
+ if ((*((volatile FLASH_WORD_SIZE *)dest) &
+ (FLASH_WORD_SIZE)data) != (FLASH_WORD_SIZE)data) {
+ return (2);
+ }
+ /* Disable interrupts which might cause a timeout here */
+ flag = disable_interrupts();
+
+ for (i=0; i<4/sizeof(FLASH_WORD_SIZE); i++)
+ {
+ addr2[ADDR0] = (FLASH_WORD_SIZE)0x00AA00AA;
+ addr2[ADDR1] = (FLASH_WORD_SIZE)0x00550055;
+ addr2[ADDR0] = (FLASH_WORD_SIZE)0x00A000A0;
+
+ dest2[i] = data2[i];
+
+ /* re-enable interrupts if necessary */
+ if (flag)
+ enable_interrupts();
+
+ /* data polling for D7 */
+ start = get_timer (0);
+ while ((dest2[i] & (FLASH_WORD_SIZE)0x00800080) !=
+ (data2[i] & (FLASH_WORD_SIZE)0x00800080)) {
+ if (get_timer(start) > CFG_FLASH_WRITE_TOUT) {
+ return (1);
+ }
+ }
+ }
+
+ return (0);
+}
+
+/*-----------------------------------------------------------------------
+ */
--- /dev/null
+/*
+ * (C) Copyright 2001 Sysgo Real-Time Solutions, GmbH <www.elinos.com>
+ * Andreas Heppel <aheppel@sysgo.de>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+/*
+ * memory routines for the MPC106 CPU.
+ */
+
+#include <ppcboot.h>
+#include <config.h>
+#include <mpc106.h>
+
+
+/*
+ * The local DRAM may have a different address from the PCI
+ * point of view, thus buffer addresses have to be modified
+ * [mapped] appropriately.
+ */
+unsigned long phys_to_bus(void * address)
+{
+ if (address == (void *)0)
+ return 0;
+ return (unsigned long)address + CFG_PCI_DRAM_OFFSET;
+}
+
+void * bus_to_phys(unsigned long address)
+{
+ if (address == 0)
+ return 0;
+ return (void *)(address - CFG_PCI_DRAM_OFFSET);
+}
--- /dev/null
+#include <config.h>
+#include <mpc75x.h>
+#include <version.h>
+
+#include <ppc_asm.tmpl>
+#include <ppc_defs.h>
+
+#define DEFS_ONLY
+
+#include <mpc106.h>
+
+
+
+ .globl set_address_map
+set_address_map:
+ /*
+ * Switch to address map A if necessary.
+ */
+#ifdef CFG_ADDRESS_MAP_A
+ lis r1, 0xfec0
+ ori r1, r1, 0x0cf8
+ lis r2, 0xfee0
+ ori r2, r2, 0xcfc
+
+ lis r3, MPC106_REG@h
+ ori r3, r3, PCI_PICR1
+ stwbrx r3, 0, r1
+ sync
+ lwbrx r4, 0, r2
+ sync
+ lis r0, PICR1_XIO_MODE@h
+ ori r0, r0, PICR1_XIO_MODE@l
+ andc r4, r4, r0
+ lis r0, PICR1_ADDRESS_MAP@h
+ ori r0, r0, PICR1_ADDRESS_MAP@l
+ or r4, r4, r0
+ stwbrx r4, 0, r2
+
+ sync
+#endif
+ blr
+
+
+ /*
+ * This following contains the entry code for the initialization code
+ * for the MPC 106, a PCI Bridge/Memory Controller.
+ * Register usage:
+ * r0 = ramtest scratch register, toggleError loop counter
+ * r1 = CONFIG_ADDRESS
+ * r2 = CONFIG_DATA
+ * r3 = scratch register, subroutine argument and return value, ramtest size
+ * r4 = scratch register, spdRead clock mask, OutHex loop count
+ * r5 = ramtest scratch register
+ * r6 = toggleError 1st value, spdRead port mask
+ * r7 = toggleError 2nd value, ramtest scratch register, spdRead scratch register (0x00)
+ * r8 = ramtest scratch register, spdRead scratch register (0x80)
+ * r9 = ramtest scratch register, toggleError loop end, OutHex digit
+ * r10 = ramtest scratch register, spdWriteByte parameter, spdReadByte return value, printf pointer to COM1
+ * r11 = startType
+ * r12 = ramtest scratch register, spdRead data mask
+ * r14 = pointer to GOT
+ * r15 = scratch register, SPD save
+ * r16 = bank0 size, total memory size
+ * r17 = bank1 size
+ * r18 = bank2 size
+ * r19 = bank3 size
+ * r20 = MCCR1, MSAR1
+ * r21 = MCCR3, MEAR1
+ * r22 = MCCR4, MBER
+ * r23 = EMSAR1
+ * r24 = EMEAR1
+ * r25 = save link register 1st level
+ * r26 = save link register 2nd level
+ * r27 = save link register 3rd level
+ * r30 = pointer to GPIO for spdRead
+ * r31 = pointer to message block
+ */
+
+ .globl ram_init
+ram_init:
+ mflr r25 /* save away link register */
+
+ /* set pointer to message block */
+ lis r4, CFG_MONITOR_BASE@h
+ ori r4, r4, CFG_MONITOR_BASE@l
+ addi r4, r4, EXC_OFF_SYS_RESET
+ bl get_startaddr
+ sub r4, r4,r3
+ bl get_msgblk
+ add r4, r4,r3
+ mr r31, r4
+
+ /*
+ * Do the init for the SIO.
+ */
+ bl .sioInit
+
+ addi r3, r31, (MinitLogo-MessageBlock)
+ bl Printf
+
+ addi r3, r31, (Mspd01-MessageBlock)
+ bl Printf
+
+ /*
+ * Memory cofiguration using SPD information stored on the SODIMMs
+ */
+
+ li r17,0
+ li r18,0
+ li r19,0
+
+ li r3, 0x0002 /* get RAM type from spd for bank0/1 */
+ bl spdRead
+
+ cmpi 0, 0, r3, -1 /* error ? */
+ bne noSpdError
+
+ addi r3, r31, (Mfail-MessageBlock)
+ bl Printf
+
+ li r6, 0xe0 /* error codes in r6 and r7 */
+ li r7, 0x00
+ b toggleError /* fail - loop forever */
+
+noSpdError:
+ mr r15, r3 /* save r3 (RAM type) */
+
+ addi r3, r31, (Mok-MessageBlock)
+ bl Printf
+
+ cmpli 0, 0, r15, 0x0001 /* FPM ? */
+ beq configFPM
+ cmpli 0, 0, r15, 0x0002 /* EDO ? */
+ beq configEDO
+ cmpli 0, 0, r15, 0x0004 /* SDRAM ? */
+ beq configSDRAM
+
+ li r6, 0xe0 /* error codes in r6 and r7 */
+ li r7, 0x01
+ b toggleError /* fail - loop forever */
+
+configSDRAM:
+ addi r3, r31, (MsdRam-MessageBlock)
+ bl Printf
+
+ /* set the Memory Configuration Reg. 1 */
+ li r3, 0x001f /* get bank size from spd for bank0/1 */
+ bl spdRead
+
+ li r20, 0x00ff /* 16-Mbit SDRAM 2 banks */
+
+ andi. r3,r3,0x0038 /* not 32MB, 64MB or 128MB */
+ beq sizeofSDRAM
+
+ li r3, 0x0011 /* get number of internal banks from spd for bank0/1 */
+ bl spdRead
+
+ li r20, 0x0055 /* 64-Mbit SDRAM 2 banks */
+
+ cmpli 0, 0, r3, 0x02 /* 2 banks */
+ beq sizeofSDRAM
+
+ li r20, 0x0000 /* 64-Mbit SDRAM 4 banks */
+
+ cmpli 0, 0, r3, 0x04 /* 4 banks */
+ beq sizeofSDRAM
+
+ li r6, 0xe0 /* error codes in r6 and r7 */
+ li r7, 0x02
+ b toggleError /* fail - loop forever */
+
+sizeofSDRAM:
+ /* set the Memory Configuration Reg. 3 */
+ lis r21, 0x8630 /* BSTOPRE = 0x80, REFREC = 6, RDLAT = 3 */
+
+ /* set the Memory Configuration Reg. 4 */
+ lis r22, 0x2430 /* PRETOACT = 2, ACTOPRE = 4, WCBUF = 1, RCBUF = 1 */
+ ori r22, r22, 0x2220 /* SDMODE = 0x022, ACTORW = 2 */
+
+ /* get the size of bank 0-3 */
+
+ li r3, 0x001f /* get bank size from spd for bank0/1 */
+ bl spdRead
+
+ rlwinm r16, r3, 2, 24, 29 /* calculate size in MByte (128 MB max.) */
+
+ li r3, 0x0005 /* get number of banks from spd for bank0/1 */
+ bl spdRead
+
+ cmpi 0, 0, r3, 2 /* 2 banks on module ? */
+ bne SDRAMnobank1
+
+ mr r17, r16 /* save size of bank 1 */
+
+SDRAMnobank1:
+ addi r3, r31, (Mspd23-MessageBlock)
+ bl Printf
+
+ li r3, 0x0102 /* get RAM type spd for bank2/3 */
+ bl spdRead
+
+ cmpli 0, 0, r3, 0x0001 /* FPM ? */
+ bne 1f
+ addi r3, r31, (Mok-MessageBlock)
+ bl Printf
+ addi r3, r31, (MfpmRam-MessageBlock)
+ bl Printf
+ b configRAMcommon
+1:
+ cmpli 0, 0, r3, 0x0002 /* EDO ? */
+ bne 2f
+ addi r3, r31, (Mok-MessageBlock)
+ bl Printf
+ addi r3, r31, (MedoRam-MessageBlock)
+ bl Printf
+ b configRAMcommon
+2:
+ cmpli 0, 0, r3, 0x0004 /* SDRAM ? */
+ bne 3f
+ addi r3, r31, (Mok-MessageBlock)
+ bl Printf
+ addi r3, r31, (MsdRam-MessageBlock)
+ bl Printf
+ b configSDRAM23
+3:
+ addi r3, r31, (Mfail-MessageBlock)
+ bl Printf
+ b configRAMcommon /* bank2/3 is not present or no SDRAM */
+
+configSDRAM23:
+ li r3, 0x011f /* get bank size from spd for bank2/3 */
+ bl spdRead
+
+ rlwinm r18, r3, 2, 24, 29 /* calculate size in MByte (128 MB max.) */
+
+ li r3, 0x0105 /* get number of banks from spd for bank2/3 */
+ bl spdRead
+
+ cmpi 0, 0, r3, 2 /* 2 banks ? */
+ bne configRAMcommon
+
+ mr r19, r18 /* save size of bank 3 */
+ b configRAMcommon
+
+configFPM:
+ addi r3, r31, (MfpmRam-MessageBlock)
+ bl Printf
+ b configEDO0
+configEDO:
+ addi r3, r31, (MedoRam-MessageBlock)
+ bl Printf
+
+configEDO0:
+ /* set the Memory Configuration Reg. 1 */
+ /* set RAM type to not SDRAM */
+ lis r20, MCCR1_TYPE_EDO@h
+
+ li r3, 0x0003 /* get # of row bits from spd for bank0/1 */
+ bl spdRead
+
+ ori r20, r20, (MCCR1_BK0_9BITS | MCCR1_BK1_9BITS)
+ cmpli 0, 0, r3, 0x0009 /* bank0 - 9 row bits */
+ beq sizeofEDO
+
+ ori r20, r20, (MCCR1_BK0_10BITS | MCCR1_BK1_10BITS)
+ cmpli 0, 0, r3, 0x000a /* bank0 - 10 row bits */
+ beq sizeofEDO
+
+ ori r20, r20, (MCCR1_BK0_11BITS | MCCR1_BK1_11BITS)
+ cmpli 0, 0, r3, 0x000b /* bank0 - 11 row bits */
+ beq sizeofEDO
+
+ ori r20, r20, (MCCR1_BK0_12BITS | MCCR1_BK1_12BITS)
+ cmpli 0, 0, r3, 0x000c /* bank0 - 12 row bits */
+ beq sizeofEDO
+
+ cmpli 0, 0, r3, 0x000d /* bank0 - 13 row bits */
+ beq sizeofEDO
+
+ li r6, 0xe0 /* error codes in r6 and r7 */
+ li r7, 0x10
+ b toggleError /* fail - loop forever */
+
+sizeofEDO:
+ /* set the Memory Configuration Reg. 3 */
+ lis r21, 0x000a /* CPX = 1, RAS6P = 4 */
+ ori r21, r21, 0x2293 /* CAS5 = 2, CP4 = 1, CAS3 = 2, RCD2 = 2, RP = 3 */
+
+ /* set the Memory Configuration Reg. 4 */
+ lis r22, 0x0010 /* all SDRAM parameter 0, WCBUF flow through, RCBUF registered */
+
+ /* get the size of bank 0-3 */
+ li r3, 0x0003 /* get row bits from spd for bank0/1 */
+ bl spdRead
+
+ li r16, 0 /* bank size is (8 * 2^row * 2^column) / 0x100000 MB */
+ ori r16, r16, 0x8000
+ rlwnm r16, r16, r3, 0, 31
+
+ li r3, 0x0004 /* get column bits from spd for bank0/1 */
+ bl spdRead
+
+ rlwnm r16, r16, r3, 0, 31
+
+ li r3, 0x0005 /* get number of banks from spd for bank0/1 */
+ bl spdRead
+
+ cmpi 0, 0, r3, 2 /* 2 banks on module ? */
+ bne EDOnobank1
+
+ mr r17, r16 /* save size of bank 1 */
+
+EDOnobank1:
+ addi r3, r31, (Mspd23-MessageBlock)
+ bl Printf
+
+ li r3, 0x0102 /* get RAM type spd for bank2/3 */
+ bl spdRead
+
+ cmpli 0, 0, r3, 0x0001 /* FPM ? */
+ bne 1f
+ addi r3, r31, (Mok-MessageBlock)
+ bl Printf
+ addi r3, r31, (MfpmRam-MessageBlock)
+ bl Printf
+ b configEDO23
+1:
+ cmpli 0, 0, r3, 0x0002 /* EDO ? */
+ bne 2f
+ addi r3, r31, (Mok-MessageBlock)
+ bl Printf
+ addi r3, r31, (MedoRam-MessageBlock)
+ bl Printf
+ b configEDO23
+2:
+ cmpli 0, 0, r3, 0x0004 /* SDRAM ? */
+ bne 3f
+ addi r3, r31, (Mok-MessageBlock)
+ bl Printf
+ addi r3, r31, (MsdRam-MessageBlock)
+ bl Printf
+ b configRAMcommon
+3:
+ addi r3, r31, (Mfail-MessageBlock)
+ bl Printf
+ b configRAMcommon /* bank2/3 is not present or no SDRAM */
+
+configEDO23:
+ li r3, 0x0103 /* get row bits from spd for bank2/3 */
+ bl spdRead
+
+ li r18, 0 /* bank size is (8 * 2^row * 2^column) / 0x100000 MB */
+ ori r18, r18, 0x8000
+ rlwnm r18, r18, r3, 0, 31
+
+ li r3, 0x0104 /* get column bits from spd for bank2/3 */
+ bl spdRead
+
+ rlwnm r18, r18, r3, 0, 31
+
+ li r3, 0x0105 /* get number of banks from spd for bank2/3 */
+ bl spdRead
+
+ cmpi 0, 0, r3, 2 /* 2 banks ? */
+ bne configRAMcommon
+
+ mr r19, r18 /* save size of bank 3 */
+
+configRAMcommon:
+ lis r1, MPC106_REG_ADDR@h
+ ori r1, r1, MPC106_REG_ADDR@l
+ lis r2, MPC106_REG_DATA@h
+ ori r2, r2, MPC106_REG_DATA@l
+
+ li r0, 0
+
+/*
+ * If we are already running in RAM (debug mode), we should
+ * NOT reset the MEMGO flag. Otherwise we will stop all memory
+ * accesses.
+ */
+#ifdef IN_RAM
+ lis r4, MCCR1_MEMGO@h
+ ori r4,r4, MCCR1_MEMGO@l
+ or r20,r20,r4
+#endif
+
+ /* set the Memory Configuration Reg. 1 */
+ lis r3, MPC106_REG@h /* start building new reg number */
+ ori r3, r3, MPC106_MCCR1 /* register number 0xf0 */
+ stwbrx r3, r0, r1 /* write this value to CONFIG_ADDR */
+ eieio /* make sure mem. access is complete */
+
+ stwbrx r20, r0, r2 /* write data to CONFIG_DATA */
+
+ /* set the Memory Configuration Reg. 3 */
+ lis r3, MPC106_REG@h /* start building new reg number */
+ ori r3, r3, MPC106_MCCR3 /* register number 0xf8 */
+ stwbrx r3, r0, r1 /* write this value to CONFIG_ADDR */
+ eieio /* make sure mem. access is complete */
+
+ stwbrx r21, r0, r2 /* write data to CONFIG_DATA */
+
+ /* set the Memory Configuration Reg. 4 */
+ lis r3, MPC106_REG@h /* start building new reg number */
+ ori r3, r3, MPC106_MCCR4 /* register number 0xfc */
+ stwbrx r3, r0, r1 /* write this value to CONFIG_ADDR */
+ eieio /* make sure mem. access is complete */
+
+ stwbrx r22, r0, r2 /* write data to CONFIG_DATA */
+
+ /* set the memory boundary registers for bank 0-3 */
+ li r20, 0
+ li r23, 0
+ li r24, 0
+ subi r21, r16, 1 /* calculate end address bank0 */
+ li r22, MBER_BANK0
+
+ cmpi 0, 0, r17, 0 /* bank1 present ? */
+ beq nobank1
+
+ rlwinm r3, r16, 8, 16, 23 /* calculate start address of bank1 */
+ or r20, r20, r3
+
+ add r16, r16, r17 /* add to total memory size */
+
+ subi r3, r16, 1 /* calculate end address of bank1 */
+ rlwinm r3, r3, 8, 16, 23
+ or r21, r21, r3
+
+ ori r22, r22, MBER_BANK1 /* enable bank1 */
+ b bank2
+
+nobank1:
+ ori r23,r23,0x0300 /* set bank1 start to unused area */
+ ori r24,r24,0x0300 /* set bank1 end to unused area */
+
+bank2:
+ cmpi 0, 0, r18, 0 /* bank2 present ? */
+ beq nobank2
+
+ andi. r3, r16, 0x00ff /* calculate start address of bank2 */
+ andi. r4, r16, 0x0300
+ rlwinm r3, r3, 16, 8, 15
+ or r20, r20, r3
+ rlwinm r3, r4, 8, 8, 15
+ or r23, r23, r3
+
+ add r16, r16, r18 /* add to total memory size */
+
+ subi r3, r16, 1 /* calculate end address of bank2 */
+ andi. r4, r3, 0x0300
+ andi. r3, r3, 0x00ff
+ rlwinm r3, r3, 16, 8, 15
+ or r21, r21, r3
+ rlwinm r3, r4, 8, 8, 15
+ or r24, r24, r3
+
+ ori r22, r22, (MBER_BANK2) /* enable bank2 */
+ b bank3
+
+nobank2:
+ lis r3,0x0003
+ or r23,r23,r3 /* set bank2 start to unused area */
+ or r24,r24,r3 /* set bank2 end to unused area */
+
+bank3:
+ cmpi 0, 0, r19, 0 /* bank3 present ? */
+ beq nobank3
+
+ andi. r3, r16, 0x00ff /* calculate start address of bank3 */
+ andi. r4, r16, 0x0300
+ rlwinm r3, r3, 24, 0, 7
+ or r20, r20, r3
+ rlwinm r3, r4, 16, 0, 7
+ or r23, r23, r3
+
+ add r16, r16, r19 /* add to total memory size */
+
+ subi r3, r16, 1 /* calculate end address of bank3 */
+ andi. r4, r3, 0x0300
+ andi. r3, r3, 0x00ff
+ rlwinm r3, r3, 24, 0, 7
+ or r21, r21, r3
+ rlwinm r3, r4, 16, 0, 7
+ or r24, r24, r3
+
+ ori r22, r22, (MBER_BANK3) /* enable bank3 */
+ b writebound
+
+nobank3:
+ lis r3,0x0300
+ or r23,r23,r3 /* set bank3 start to unused area */
+ or r24,r24,r3 /* set bank3 end to unused area */
+
+writebound:
+ lis r3, MPC106_REG@h /* start building new reg number */
+ ori r3, r3, MPC106_MSAR1 /* register number 0x80 */
+ stwbrx r3, r0, r1 /* write this value to CONFIG_ADDR */
+ eieio /* make sure mem. access is complete */
+ stwbrx r20, r0, r2 /* write data to CONFIG_DATA */
+
+ lis r3, MPC106_REG@h /* start building new reg number */
+ ori r3, r3, MPC106_MEAR1 /* register number 0x90 */
+ stwbrx r3, r0, r1 /* write this value to CONFIG_ADDR */
+ eieio /* make sure mem. access is complete */
+ stwbrx r21, r0, r2 /* write data to CONFIG_DATA */
+
+ lis r3, MPC106_REG@h /* start building new reg number */
+ ori r3, r3, MPC106_EMSAR1 /* register number 0x88 */
+ stwbrx r3, r0, r1 /* write this value to CONFIG_ADDR */
+ eieio /* make sure mem. access is complete */
+ stwbrx r23, r0, r2 /* write data to CONFIG_DATA */
+
+ lis r3, MPC106_REG@h /* start building new reg number */
+ ori r3, r3, MPC106_EMEAR1 /* register number 0x98 */
+ stwbrx r3, r0, r1 /* write this value to CONFIG_ADDR */
+ eieio /* make sure mem. access is complete */
+ stwbrx r24, r0, r2 /* write data to CONFIG_DATA */
+
+ /* set boundaries of unused banks to unused address space */
+ lis r4, 0x0303
+ ori r4, r4, 0x0303 /* bank 4-7 start and end adresses */
+ lis r3, MPC106_REG@h /* start building new reg number */
+ ori r3, r3, MPC106_EMSAR2 /* register number 0x8C */
+ stwbrx r3, r0, r1 /* write this value to CONFIG_ADDR */
+ eieio /* make sure mem. access is complete */
+ stwbrx r4, r0, r2 /* write data to CONFIG_DATA */
+
+ lis r3, MPC106_REG@h /* start building new reg number */
+ ori r3, r3, MPC106_EMEAR2 /* register number 0x9C */
+ stwbrx r3, r0, r1 /* write this value to CONFIG_ADDR */
+ eieio /* make sure mem. access is complete */
+ stwbrx r4, r0, r2 /* write data to CONFIG_DATA */
+
+
+ /* set the Memory Configuration Reg. 2 */
+ lis r3, MPC106_REG@h /* start building new reg number */
+ ori r3, r3, MPC106_MCCR2 /* register number 0xf4 */
+ stwbrx r3, r0, r1 /* write this value to CONFIG_ADDR */
+ eieio /* make sure mem. access is complete */
+
+ li r3, 0x000c /* get refresh from spd for bank0/1 */
+ bl spdRead
+
+ cmpi 0, 0, r3, -1 /* error ? */
+ bne common1
+
+ li r6, 0xe0 /* error codes in r6 and r7 */
+ li r7, 0x20
+ b toggleError /* fail - loop forever */
+
+common1:
+ andi. r15, r3, 0x007f /* mask selfrefresh bit */
+ li r3, 0x010c /* get refresh from spd for bank2/3 */
+ bl spdRead
+
+ cmpi 0, 0, r3, -1 /* error ? */
+ beq common2
+ andi. r3, r3, 0x007f /* mask selfrefresh bit */
+ cmp 0, 0, r3, r15 /* find the lower */
+ blt common3
+common2:
+ mr r3, r15
+common3:
+ li r4, 0x1010 /* refesh cycle 1028 clocks left shifted 2 */
+ cmpli 0, 0, r3, 0x0000 /* 15.6 us ? */
+ beq writeRefresh
+
+ li r4, 0x0808 /* refesh cycle 514 clocks left shifted 2 */
+ cmpli 0, 0, r3, 0x0002 /* 7.8 us ? */
+ beq writeRefresh
+
+ li r4, 0x2020 /* refesh cycle 2056 clocks left shifted 2 */
+ cmpli 0, 0, r3, 0x0003 /* 31.3 us ? */
+ beq writeRefresh
+
+ li r4, 0x4040 /* refesh cycle 4112 clocks left shifted 2 */
+ cmpli 0, 0, r3, 0x0004 /* 62.5 us ? */
+ beq writeRefresh
+
+ li r4, 0
+ ori r4, r4, 0x8080 /* refesh cycle 8224 clocks left shifted 2 */
+ cmpli 0, 0, r3, 0x0005 /* 125 us ? */
+ beq writeRefresh
+
+ li r6, 0xe0 /* error codes in r6 and r7 */
+ li r7, 0x21
+ b toggleError /* fail - loop forever */
+
+writeRefresh:
+ stwbrx r4, r0, r2 /* write data to CONFIG_DATA */
+
+ /* DRAM BANKS SHOULD BE ENABLED */
+ addi r3, r31, (Mactivate-MessageBlock)
+ bl Printf
+ mr r3, r16
+ bl OutDec
+ addi r3, r31, (Mmbyte-MessageBlock)
+ bl Printf
+
+ lis r3, MPC106_REG@h /* start building new reg number */
+ ori r3, r3, MPC106_MBER /* register number 0xa0 */
+ stwbrx r3, r0, r1 /* write this value to CONFIG_ADDR */
+ eieio /* make sure mem. access is complete */
+ stb r22, 0(r2) /* write data to CONFIG_DATA */
+
+ li r8, 0x63 /* PGMAX = 99 */
+
+ stb r8, 3(r2) /* write data to CONFIG_DATA */
+
+ /*
+ DRAM SHOULD NOW BE CONFIGURED AND ENABLED -
+ MUST WAIT 200us BEFORE ACCESSING
+ */
+
+ li r0, 0x3800
+ mtctr r0
+
+wait200us:
+ bdnz wait200us
+
+ lis r3, MPC106_REG@h /* start building new reg number */
+ ori r3, r3, MPC106_MCCR1 /* register number 0xf0 */
+ stwbrx r3, r0, r1 /* write this value to CONFIG_ADDR */
+ eieio /* make sure mem. access is complete */
+
+ lwbrx r4, r0, r2 /* load r4 from CONFIG_DATA */
+
+ lis r0, MCCR1_MEMGO@h /* MEMGO=1 */
+ ori r0, r0, MCCR1_MEMGO@l
+ or r4, r4, r0 /* set the MEMGO bit */
+ stwbrx r4, r0, r2 /* write mdfd data to CONFIG_DATA */
+
+ li r0, 0x7000
+ mtctr r0
+wait8ref:
+ bdnz wait8ref
+
+ addi r3, r31, (Mok-MessageBlock)
+ bl Printf
+
+ mtlr r25
+ blr
+
+/*
+ * Infinite loop called in case of an error during RAM initialisation.
+ * error codes in r6 and r7.
+ */
+toggleError:
+ li r0,0
+ lis r9,127
+ ori r9,r9,65535
+toggleError1:
+ addic r0,r0,1
+ cmpw cr1,r0,r9
+ ble cr1,toggleError1
+ li r0,0
+ lis r9,127
+ ori r9,r9,65535
+toggleError2:
+ addic r0,r0,1
+ cmpw cr1,r0,r9
+ ble cr1,toggleError2
+ b toggleError
+
+
+/****************************************************************************/
+
+ .set SIO_LUNINDEX,0x07 /* SIO LUN index register */
+ .set SIO_CNFG1,0x21 /* SIO configuration #1 register */
+ .set SIO_PCSCI,0x23 /* SIO PCS configuration index reg */
+ .set SIO_PCSCD,0x24 /* SIO PCS configuration data reg */
+ .set SIO_ACTIVATE,0x30 /* SIO activate register */
+ .set SIO_IOBASEHI,0x60 /* SIO I/O port base address, 15:8 */
+ .set SIO_IOBASELO,0x61 /* SIO I/O port base address, 7:0 */
+ .set SIO_LUNENABLE,0x01 /* SIO LUN enable */
+
+/*
+ * This function performs a basic initialisation of the superio chip
+ * to enable basic console output and SPD access during RAM initialisation.
+ *
+ * Upon completion, SIO resource registers are mapped as follows:
+ * Resource Enabled Address
+ * UART1 Yes COM1 3F8-3FF
+ * UART2 Yes COM2 2F8-2FF
+ * GPIO Yes 220-227
+ */
+
+.sioInit:
+ mfspr r7,8 /* save link register */
+
+.sioInit_87308:
+
+ /*
+ * Get base addr of ISA I/O space
+ */
+ lis r6,CFG_ISA_IO@h
+ ori r6,r6,CFG_ISA_IO@l
+
+ /*
+ * Set offset to base address for config registers.
+ */
+#if defined(CFG_NS87308_BADDR_0x)
+ addi r4,r0,0x0279
+#elif defined(CFG_NS87308_BADDR_10)
+ addi r4,r0,0x015C
+#elif defined(CFG_NS87308_BADDR_11)
+ addi r4,r0,0x002E
+#endif
+
+ add r6,r6,r4 /* add offset to base */
+ or r3,r6,r6 /* make a copy */
+
+/*
+ * PMC (LUN 8)
+ */
+ addi r4,r0,SIO_LUNINDEX /* select PMC LUN */
+ addi r5,r0,0x8
+ bl .sio_bw
+ addi r4,r0,SIO_IOBASEHI /* initialize PMC address to 0x460 */
+ addi r5,r0,0x04
+ bl .sio_bw
+ addi r4,r0,SIO_IOBASELO
+ addi r5,r0,0x60
+ bl .sio_bw
+ addi r4,r0,SIO_ACTIVATE /* enable PMC */
+ addi r5,r0,SIO_LUNENABLE
+ bl .sio_bw
+
+ lis r8,CFG_ISA_IO@h
+ ori r8,r8,0x0460
+ li r9,0x03
+ stb r9,0(r8) /* select PMC2 register */
+ eieio
+ li r9,0x00
+ stb r9,1(r8) /* SuperI/O clock source is 24MHz via X1 */
+ eieio
+
+/*
+ * map UART1 (LUN 6) or UART2 (LUN 5) to COM1 (0x3F8)
+ */
+ addi r4,r0,SIO_LUNINDEX /* select COM1 LUN */
+ addi r5,r0,0x6
+ bl .sio_bw
+ addi r4,r0,SIO_IOBASEHI /* initialize COM1 address to 0x3F8 */
+ addi r5,r0,0x03
+ bl .sio_bw
+ addi r4,r0,SIO_IOBASELO
+ addi r5,r0,0xF8
+ bl .sio_bw
+ addi r4,r0,SIO_ACTIVATE /* enable COM1 */
+ addi r5,r0,SIO_LUNENABLE
+ bl .sio_bw
+/*
+ * Init COM1 for polled output
+ *
+ */
+ lis r8,CFG_ISA_IO@h
+ ori r8,r8,0x03f8
+ li r9,0x00
+ stb r9,1(r8) /* int disabled */
+ eieio
+ li r9,0x00
+ stb r9,4(r8) /* modem ctrl */
+ eieio
+ li r9,0x80
+ stb r9,3(r8) /* link ctrl, bank select */
+ eieio
+ li r9,115200/CONFIG_BAUDRATE
+ stb r9,0(r8) /* baud rate (LSB)*/
+ eieio
+ rotrwi r9,r9,8
+ stb r9,1(r8) /* baud rate (MSB) */
+ eieio
+ li r9,0x03
+ stb r9,3(r8) /* 8 data bits, 1 stop bit, no parity */
+ eieio
+ li r9,0x0b
+ stb r9,4(r8) /* enable the receiver and transmitter (modem ctrl) */
+ eieio
+waitEmpty:
+ lbz r9,5(r8) /* transmit empty */
+ andi. r9,r9,0x40
+ beq waitEmpty
+ li r9,0x47
+ stb r9,3(r8) /* send break; 8 data bits, 2 stop bit, no parity */
+ eieio
+
+ lis r0, 0x0001 /* */
+ mtctr r0
+waitCOM1:
+ lwz r0, 5(r8) /* load from port for delay */
+ bdnz waitCOM1
+
+waitEmpty1:
+ lbz r9,5(r8) /* transmit empty */
+ andi. r9,r9,0x40
+ beq waitEmpty1
+ li r9,0x07
+ stb r9,3(r8) /* 8 data bits, 2 stop bit, no parity */
+ eieio
+
+/*
+; GPIO (LUN 7)
+*/
+ addi r4,r0,SIO_LUNINDEX /* select GPIO LUN */
+ addi r5,r0,0x7
+ bl .sio_bw
+ addi r4,r0,SIO_IOBASEHI /* initialize GPIO address to 0x220 */
+ addi r5,r0,0x02
+ bl .sio_bw
+ addi r4,r0,SIO_IOBASELO
+ addi r5,r0,0x20
+ bl .sio_bw
+ addi r4,r0,SIO_ACTIVATE /* enable GPIO */
+ addi r5,r0,SIO_LUNENABLE
+ bl .sio_bw
+
+.sioInit_done:
+
+ /*
+ * Get base addr of ISA I/O space
+ */
+ lis r3,CFG_ISA_IO@h
+ ori r3,r3,CFG_ISA_IO@l
+
+ addi r3,r3,0x015C /* adjust to superI/O 87308 base */
+ or r6,r3,r3 /* make a copy */
+/*
+; CS0
+*/
+ addi r4,r0,SIO_PCSCI /* select PCSCIR */
+ addi r5,r0,0x00
+ bl .sio_bw
+ addi r4,r0,SIO_PCSCD /* select PCSCDR */
+ addi r5,r0,0x00
+ bl .sio_bw
+ addi r4,r0,SIO_PCSCI /* select PCSCIR */
+ addi r5,r0,0x01
+ bl .sio_bw
+ addi r4,r0,SIO_PCSCD /* select PCSCDR */
+ addi r5,r0,0x76
+ bl .sio_bw
+ addi r4,r0,SIO_PCSCI /* select PCSCIR */
+ addi r5,r0,0x02
+ bl .sio_bw
+ addi r4,r0,SIO_PCSCD /* select PCSCDR */
+ addi r5,r0,0x40
+ bl .sio_bw
+/*
+; CS1
+*/
+ addi r4,r0,SIO_PCSCI /* select PCSCIR */
+ addi r5,r0,0x05
+ bl .sio_bw
+ addi r4,r0,SIO_PCSCD /* select PCSCDR */
+ addi r5,r0,0x00
+ bl .sio_bw
+ addi r4,r0,SIO_PCSCI /* select PCSCIR */
+ addi r5,r0,0x05
+ bl .sio_bw
+ addi r4,r0,SIO_PCSCD /* select PCSCDR */
+ addi r5,r0,0x70
+ bl .sio_bw
+ addi r4,r0,SIO_PCSCI /* select PCSCIR */
+ addi r5,r0,0x06
+ bl .sio_bw
+ addi r4,r0,SIO_PCSCD /* select PCSCDR */
+ addi r5,r0,0x1C
+ bl .sio_bw
+/*
+; CS2
+*/
+ addi r4,r0,SIO_PCSCI /* select PCSCIR */
+ addi r5,r0,0x08
+ bl .sio_bw
+ addi r4,r0,SIO_PCSCD /* select PCSCDR */
+ addi r5,r0,0x00
+ bl .sio_bw
+ addi r4,r0,SIO_PCSCI /* select PCSCIR */
+ addi r5,r0,0x09
+ bl .sio_bw
+ addi r4,r0,SIO_PCSCD /* select PCSCDR */
+ addi r5,r0,0x71
+ bl .sio_bw
+ addi r4,r0,SIO_PCSCI /* select PCSCIR */
+ addi r5,r0,0x0A
+ bl .sio_bw
+ addi r4,r0,SIO_PCSCD /* select PCSCDR */
+ addi r5,r0,0x1C
+ bl .sio_bw
+
+ mtspr 8,r7 /* restore link register */
+ bclr 20,0 /* return to caller */
+
+/*
+; routine: sio_bw
+; this function writes a register to the SIO chip
+; call:
+; sio_bw(sioaddr, regnum, value)
+; return:
+; none
+*/
+.sio_bw:
+ stb r4,0(r3) /* write index register with register offset */
+ eieio
+ sync
+ stb r5,1(r3) /* 1st write */
+ eieio
+ sync
+ stb r5,1(r3) /* 2nd write */
+ eieio
+ sync
+ bclr 20,0 /* return to caller */
+/*
+; routine: sio_br
+; this function reads a register from the SIO chip
+; call:
+; sioInit(sioaddr, regnum)
+; return:
+; register value
+*/
+.sio_br:
+ stb r4,0(r3) /* write index register with register offset */
+ eieio
+ sync
+ lbz r3,1(r3) /* retrieve specified reg offset contents */
+ eieio
+ sync
+ bclr 20,0 /* return to caller */
+
+/*
+ * Print a message to COM1 in polling mode
+ * r10=COM1 port, r3=(char*)string
+ */
+ .globl Printf
+Printf:
+ lis r10,CFG_ISA_IO@h /* COM1 port */
+ ori r10,r10,0x03f8
+
+WaitChr:
+ lbz r0,5(r10) /* read link status */
+ eieio
+ andi. r0,r0,0x40 /* mask transmitter empty bit */
+ beq cr0,WaitChr /* wait till empty */
+ lbzx r0,r0,r3 /* get char */
+ stb r0,0(r10) /* write to transmit reg */
+ eieio
+ addi r3,r3,1 /* next char */
+ lbzx r0,r0,r3 /* get char */
+ cmpwi cr1,r0,0 /* end of string ? */
+ bne cr1,WaitChr
+ blr
+
+/*
+ * Print 8/4/2 digits hex value to COM1 in polling mode
+ * r10=COM1 port, r3=val
+ */
+OutHex2:
+ li r9,4 /* shift reg for 2 digits */
+ b OHstart
+OutHex4:
+ li r9,12 /* shift reg for 4 digits */
+ b OHstart
+ .globl OutHex
+OutHex:
+ li r9,28 /* shift reg for 8 digits */
+OHstart:
+ lis r10,CFG_ISA_IO@h /* COM1 port */
+ ori r10,r10,0x03f8
+OutDig:
+ lbz r0,0(r29) /* slow down dummy read */
+ lbz r0,5(r10) /* read link status */
+ eieio
+ andi. r0,r0,0x40 /* mask transmitter empty bit */
+ beq cr0,OutDig
+ sraw r0,r3,r9
+ clrlwi r0,r0,28
+ cmpwi cr1,r0,9
+ ble cr1,digIsNum
+ addic r0,r0,55
+ b nextDig
+digIsNum:
+ addic r0,r0,48
+nextDig:
+ stb r0,0(r10) /* write to transmit reg */
+ eieio
+ addic. r9,r9,-4
+ bge OutDig
+ blr
+
+/*
+ * Print 3 digits hdec value to COM1 in polling mode
+ * r10=COM1 port, r3=val, r7=x00, r8=x0, r9=x, r0,r6=scratch
+ */
+ .globl OutDec
+OutDec:
+ li r6, 10
+ divwu r0, r3, r6 /* r0 = r3 / 10, r9 = r3 mod 10 */
+ mullw r10, r0, r6
+ subf r9, r10, r3
+
+ mr r3, r0
+ divwu r0, r3, r6 /* r0 = r3 / 10, r8 = r3 mod 10 */
+ mullw r10, r0, r6
+ subf r8, r10, r3
+
+ mr r3, r0
+ divwu r0, r3, r6 /* r0 = r3 / 10, r7 = r3 mod 10 */
+ mullw r10, r0, r6
+ subf r7, r10, r3
+
+ lis r10,CFG_ISA_IO@h /* COM1 port */
+ ori r10,r10,0x03f8
+
+ or. r7, r7, r7
+ bne noblank1
+ li r3, 0x20
+ b OutDec4
+noblank1:
+ addi r3, r7, 48 /* convert to ASCII */
+OutDec4:
+ lbz r0,0(r31) /* slow down dummy read */
+ lbz r0,5(r10) /* read link status */
+ eieio
+ andi. r0,r0,0x40 /* mask transmitter empty bit */
+ beq cr0,OutDec4
+ stb r3,0(r10) /* x00 to transmit */
+ eieio
+
+ or. r7, r7, r8
+ beq OutDec5
+
+ addi r3, r8, 48 /* convert to ASCII */
+OutDec5:
+ lbz r0,0(r31) /* slow down dummy read */
+ lbz r0,5(r10) /* read link status */
+ eieio
+ andi. r0,r0,0x40 /* mask transmitter empty bit */
+ beq cr0,OutDec5
+ stb r3,0(r10) /* x0 to transmit */
+ eieio
+
+ addi r3, r9, 48 /* convert to ASCII */
+OutDec6:
+ lbz r0,0(r31) /* slow down dummy read */
+ lbz r0,5(r10) /* read link status */
+ eieio
+ andi. r0,r0,0x40 /* mask transmitter empty bit */
+ beq cr0,OutDec6
+ stb r3,0(r10) /* x to transmit */
+ eieio
+
+ blr
+
+/*
+ * Print a char to COM1 in polling mode
+ * r10=COM1 port, r3=char
+ */
+ .globl OutChr
+OutChr:
+ lis r10,CFG_ISA_IO@h /* COM1 port */
+ ori r10,r10,0x03f8
+
+OutChr1:
+ lbz r0,5(r10) /* read link status */
+ eieio
+ andi. r0,r0,0x40 /* mask transmitter empty bit */
+ beq cr0,OutChr1 /* wait till empty */
+ stb r3,0(r10) /* write to transmit reg */
+ eieio
+ blr
+
+
+/*
+ * IN: r3 adr to read
+ * OUT: r3 val or -1 for error
+ */
+spdRead:
+ mfspr r26,8 /* save link register */
+
+ lis r30, CFG_ISA_IO@h
+ ori r30, r30, 0x220 /* GPIO Port 1 */
+ li r7, 0x00
+ li r8, 0x100
+ and. r5,r3,r8
+ beq spdbank0
+ li r12, 0x08
+ li r4, 0x10
+ li r6, 0x18
+ b spdRead1
+spdbank0:
+ li r12, 0x20 /* set I2C data */
+ li r4, 0x40 /* set I2C clock */
+ li r6, 0x60 /* set I2C clock and data */
+spdRead1:
+ li r8, 0x80
+
+ bl spdStart /* access I2C bus as master */
+
+ li r10,0xa0 /* write to SPD */
+ bl spdWriteByte
+ bl spdReadAck /* ACK returns in r10 */
+ cmpw cr0,r10,r7
+ bne AckErr /* r10 must be 0, if ACK received */
+ mr r10,r3 /* adr to read */
+ bl spdWriteByte
+ bl spdReadAck
+ cmpw cr0,r10,r7
+ bne AckErr
+ bl spdStart
+ li r10,0xa1 /* read from SPD */
+ bl spdWriteByte
+ bl spdReadAck
+ cmpw cr0,r10,r7
+ bne AckErr
+ bl spdReadByte /* return val in r10 */
+ bl spdWriteAck
+ bl spdStop /* release I2C bus */
+
+ mr r3,r10
+
+ mtspr 8,r26 /* restore link register */
+ blr
+
+/*
+ * ACK error occurred
+ */
+AckErr:
+ bl spdStop
+ orc r3,r0,r0 /* return -1 */
+ mtspr 8,r26 /* restore link register */
+ blr
+
+/*
+ * Routines to read from RAM spd.
+ * r30 - GPIO Port1 address in all cases.
+ * r4 - clock mask for SPD
+ * r6 - port mask for SPD
+ * r12 - data mask for SPD
+ */
+waitSpd:
+ li r0,0x1000
+ mtctr r0
+wSpd: bdnz wSpd
+ bclr 20,0 /* return to caller */
+
+/*
+ * establish START condition on I2C bus
+ */
+spdStart:
+ mfspr r27,8 /* save link register */
+ stb r6,0(r30) /* set SDA and SCL */
+ eieio
+ stb r6,1(r30) /* switch GPIO to output */
+ eieio
+ bl waitSpd
+ stb r4,0(r30) /* reset SDA */
+ eieio
+ bl waitSpd
+ stb r7,0(r30) /* reset SCL */
+ eieio
+ bl waitSpd
+ mtspr 8,r27
+ bclr 20,0 /* return to caller */
+
+/*
+ * establish STOP condition on I2C bus
+ */
+spdStop:
+ mfspr r27,8 /* save link register */
+ stb r7,0(r30) /* reset SCL and SDA */
+ eieio
+ stb r6,1(r30) /* switch GPIO to output */
+ eieio
+ bl waitSpd
+ stb r4,0(r30) /* set SCL */
+ eieio
+ bl waitSpd
+ stb r6,0(r30) /* set SDA and SCL */
+ eieio
+ bl waitSpd
+ stb r7,1(r30) /* switch GPIO to input */
+ eieio
+ mtspr 8,r27
+ bclr 20,0 /* return to caller */
+
+spdReadByte:
+ mfspr r27,8
+ stb r4,1(r30) /* set GPIO for SCL output */
+ eieio
+ li r9,0x08
+ li r10,0x00
+loopRB:
+ stb r7,0(r30) /* reset SDA and SCL */
+ eieio
+ bl waitSpd
+ stb r4,0(r30) /* set SCL */
+ eieio
+ bl waitSpd
+ lbz r5,0(r30) /* read from GPIO Port1*/
+ rlwinm r10, r10, 1, 0, 31
+ and. r5,r5,r12
+ beq clearBit
+ ori r10,r10,0x01 /* append _1_ */
+clearBit:
+ stb r7,0(r30) /* reset SCL */
+ eieio
+ bl waitSpd
+ addic. r9,r9,-1
+ bne loopRB
+ mtspr 8,r27
+ bclr 20,0 /* return (r10) to caller */
+
+/*
+ * spdWriteByte writes bits 24 - 31 of r10 to I2C.
+ * r8 contains bit mask 0x80
+ */
+spdWriteByte:
+ mfspr r27,8 /* save link register */
+ li r9,0x08 /* write octet */
+ and. r5,r10,r8
+ bne sWB1
+ stb r7,0(r30) /* set SDA to _0_ */
+ eieio
+ b sWB2
+sWB1: stb r12,0(r30) /* set SDA to _1_ */
+ eieio
+sWB2: stb r6,1(r30) /* set GPIO to output */
+ eieio
+loopWB:
+ and. r5,r10,r8
+ bne sWB3
+ stb r7,0(r30) /* set SDA to _0_ */
+ eieio
+ b sWB4
+sWB3: stb r12,0(r30) /* set SDA to _1_ */
+ eieio
+sWB4: bl waitSpd
+ and. r5,r10,r8
+ bne sWB5
+ stb r4,0(r30) /* set SDA to _0_ and SCL */
+ eieio
+ b sWB6
+sWB5: stb r6,0(r30) /* set SDA to _1_ and SCL */
+ eieio
+sWB6: bl waitSpd
+ and. r5,r10,r8
+ bne sWB7
+ stb r7,0(r30) /* set SDA to _0_ and reset SCL */
+ eieio
+ b sWB8
+sWB7: stb r12,0(r30) /* set SDA to _1_ and reset SCL */
+ eieio
+sWB8: bl waitSpd
+ rlwinm r10, r10, 1, 0, 31 /* next bit */
+ addic. r9,r9,-1
+ bne loopWB
+ mtspr 8,r27
+ bclr 20,0 /* return to caller */
+
+/*
+ * Read ACK from SPD, return value in r10
+ */
+spdReadAck:
+ mfspr r27,8 /* save link register */
+ stb r4,1(r30) /* set GPIO to output */
+ eieio
+ stb r7,0(r30) /* reset SDA and SCL */
+ eieio
+ bl waitSpd
+ stb r4,0(r30) /* set SCL */
+ eieio
+ bl waitSpd
+ lbz r10,0(r30) /* read GPIO Port 1 and mask SDA */
+ and r10,r10,r12
+ bl waitSpd
+ stb r7,0(r30) /* reset SDA and SCL */
+ eieio
+ bl waitSpd
+ mtspr 8,r27
+ bclr 20,0 /* return (r10) to caller */
+
+spdWriteAck:
+ mfspr r27,8
+ stb r12,0(r30) /* set SCL */
+ eieio
+ stb r6,1(r30) /* set GPIO to output */
+ eieio
+ bl waitSpd
+ stb r6,0(r30) /* SDA and SCL */
+ eieio
+ bl waitSpd
+ stb r12,0(r30) /* reset SCL */
+ eieio
+ bl waitSpd
+ mtspr 8,r27
+ bclr 20,0 /* return to caller */
+
+
+
+/*
+ * Message for outport to console.
+ */
+ .globl MessageBlock
+MessageBlock:
+Mok:
+ .ascii "....... OK \015\012\000"
+Mfail:
+ .ascii "... FAILED \015\012\000"
+MinitLogo:
+ .ascii "*** ELTEC Elektronik, Mainz ***\015\012"
+ .ascii "\015\012"
+ .ascii "BAB 750\015\012"
+ .ascii "\015\012"
+ .ascii "Initialising RAM\015\012\000"
+Mspd01:
+ .ascii " Reading SPD of bank 0/1 ........\000"
+Mspd23:
+ .ascii " Reading SPD of bank 2/3 ........\000"
+MfpmRam:
+ .ascii " RAM-Type: FPM\015\012\000"
+MedoRam:
+ .ascii " RAM-Type: EDO\015\012\000"
+MsdRam:
+ .ascii " RAM-Type: SDRAM\015\012\000"
+Mactivate:
+ .ascii " Activating \000"
+Mmbyte:
+ .ascii " MB ....\000"
--- /dev/null
+/*
+ * (C) Copyright 2001 Sysgo Real-Time Solutions, GmbH <www.elinos.com>
+ * Andreas Heppel <aheppel@sysgo.de>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+/*
+ * PCI routines for the MPC106 CPU.
+ */
+
+#include <ppcboot.h>
+#include <command.h>
+#include <cmd_boot.h>
+#include <mpc106.h>
+#include <asm/processor.h>
+
+#ifdef CONFIG_PCI
+
+/*
+ * These are the lowest addresses allowed for PCI configuration.
+ * They correspond to lowest available I/O and Memory addresses.
+ * In the case where where multiple PMM regs are being used to map
+ * different PLB to PCI regions, each region should have it's own
+ * minimum address.
+ */
+unsigned long LowestMemAddr1 = CFG_MIN_PCI_MEMADDR1;
+unsigned long LowestMemAddr2 = CFG_MIN_PCI_MEMADDR2;
+unsigned long LowestIOAddr = CFG_PCI_PCI_IOADDR;
+
+unsigned long MaxBusNum = 0;
+
+unsigned char ShortPCIListing = 0;
+
+/*
+ * Subroutine: pci_init
+ *
+ * Description: Initialises the MPC106 PCI Configuration regs.
+ *
+ * Inputs: bd board info structure
+ *
+ * Return: None
+ *
+ */
+void pci_init(bd_t *bd)
+{
+ unsigned int pcicmd;
+ unsigned int pcistat;
+ unsigned int picr1;
+ unsigned int picr2;
+ unsigned int pvr = get_pvr();
+
+ puts("PCI: ");
+
+ picr2 = PCI_Read_CFG_Reg(PCIDEVID_MPC106, PCI_PICR2, 4);
+ picr2 |= PICR2_CF_SNOOP_WS(3) |
+ PICR2_CF_FLUSH_L2 |
+ PICR2_CF_L2_HIT_DELAY(3) |
+ PICR2_CF_APHASE_WS(3);
+ picr2 &= ~(PICR2_L2_EN | PICR2_L2_UPDATE_EN);
+ PCI_Write_CFG_Reg(PCIDEVID_MPC106, PCI_PICR2, picr2, 4);
+
+ pcicmd = PCI_Read_CFG_Reg(PCIDEVID_MPC106, PCI_CFG_COMMAND, 2);
+ pcicmd |= (CMD_SERR | PCI_CMD_MASTER | PCI_CMD_MEMEN);
+ PCI_Write_CFG_Reg(PCIDEVID_MPC106, PCI_CFG_COMMAND, pcicmd, 2);
+
+ /* clear non-reserved bits in status register */
+ pcistat = PCI_Read_CFG_Reg(PCIDEVID_MPC106, PCI_CFG_STATUS, 2);
+ pcistat |= PCI_STAT_NO_RSV_BITS;
+ PCI_Write_CFG_Reg(PCIDEVID_MPC106, PCI_CFG_STATUS, pcistat, 2);
+
+ picr1 = PCI_Read_CFG_Reg(PCIDEVID_MPC106, PCI_PICR1, 4);
+ if (PVR_VER(pvr) == 0x0008)
+ picr1 |= PICR1_PROC_TYPE_603;
+ else
+ picr1 |= PICR1_PROC_TYPE_604;
+
+ picr1 |= PICR1_CF_CBA(63) | PICR1_CF_BREAD_WS(2);
+ picr1 |= PICR1_MCP_EN | PICR1_CF_DPARK |
+ PICR1_CF_LOOP_SNOOP | PICR1_CF_APARK;
+ PCI_Write_CFG_Reg(PCIDEVID_MPC106, PCI_PICR1, picr1, 4);
+
+#ifdef CONFIG_PCI_PNP
+ /*
+ * Scan the PCI bus and configure devices found.
+ */
+ puts("scanning bus for devices ...");
+
+ PCI_Scan(0);
+#endif /* CONFIG_PCI_PNP */
+ puts("OK\n");
+}
+
+/*
+ * Subroutine: PCI_Scan
+ *
+ * Description: Scan through all allowable PCI IDs and configure
+ * those for which the vendor ID indicates there is a
+ * device present. Routine scans only function 0.
+ *
+ * Inputs: BusNum Bus number where scanning begins
+ *
+ * Return: Number of devices found on the bus.
+ *
+ */
+int PCI_Scan(int BusNum)
+{
+ int Device;
+ int Function;
+ int BusDevFunc;
+ int Found = 0;
+ unsigned int HeaderType = 0;
+ unsigned int VendorID = 0;
+
+#ifdef DEBUG
+ printf("Scanning PCI bus %d\n", BusNum);
+#endif
+
+ /*
+ * Start with device 0, the MPC106 is device 0. sr: 09-07-2001
+ */
+ for (Device = 0; Device < CFG_MAX_PCI_DEVICES; Device++) {
+ HeaderType = 0;
+ VendorID = 0;
+ for (Function = 0; Function < CFG_MAX_PCI_FUNCTIONS; Function++) {
+ /*
+ * If this is not a multi-function device, we skip the rest
+ */
+ if (Function && !(HeaderType & 0x80))
+ break;
+
+ BusDevFunc = (BusNum << 16) |
+ (Device << 11) |
+ (Function << 8);
+
+ VendorID = PCI_Read_CFG_Reg (BusDevFunc,
+ PCI_CFG_VENDOR_ID, 2);
+ if ((VendorID == 0xFFFF) || (VendorID == 0x0000))
+ continue;
+
+ HeaderType = PCI_Read_CFG_Reg(BusDevFunc,
+ PCI_CFG_HEADER_TYPE, 1);
+#ifdef DEBUG
+ printf("\nPCI Device %d Funtion %d is present\n",
+ Device, Function);
+#endif
+ if (HeaderType & 0x01) {
+ /* PCI-PCI Bridge */
+ PCI_Config_Bridge(BusDevFunc);
+ } else {
+ PCI_Config_Device(BusDevFunc, 6);
+ }
+ Found++;
+ }
+ }
+ return Found;
+}
+
+/*
+ * Subroutine: PCI_Read_CFG_Reg
+ *
+ * Description: Read a PCI configuration register
+ *
+ * Inputs: BusDevFunc PCI Bus+Device+Function number
+ * Reg Configuration register number
+ * Width Number of bytes to read (1, 2, or 4)
+ *
+ * Return: Value of the configuration register read.
+ * For reads shorter than 4 bytes, return value
+ * is LSB-justified
+ */
+unsigned int PCI_Read_CFG_Reg(int BusDevFunc, int Reg, int Width)
+{
+ unsigned int RegAddr;
+
+ /*
+ * bit 31 must be 1 and bits 1:0 must be 0 (note Little Endian bit notation)
+ */
+ RegAddr = MPC106_REG | ((Reg|BusDevFunc) & 0xFFFFFFFC);
+
+ /*
+ * Write reg to PCI Config Address
+ */
+ out32r(MPC106_REG_ADDR, RegAddr);
+
+ /*
+ * Read reg value from PCI Config Data
+ */
+ switch (Width) {
+ case 1:
+ return ((unsigned int) in8(MPC106_REG_DATA | (Reg & 0x3)));
+ case 2:
+ return ((unsigned int) in16r(MPC106_REG_DATA | (Reg & 0x3)));
+ case 4:
+ return (in32r(MPC106_REG_DATA | (Reg & 0x3)));
+ }
+
+ return 0; /* not reached: just to satisfy the compiler */
+}
+
+/*
+ * Subroutine: PCI_Write_CFG_Reg
+ *
+ * Description: Write a PCI configuration register.
+ *
+ * Inputs: BusDevFunc PCI Bus+Device+Function number
+ * Reg Configuration register number
+ * Value Configuration register value
+ * Width Number of bytes to write (1, 2, or 4)
+ *
+ * Return: 0 Successful
+ *
+ */
+int PCI_Write_CFG_Reg(int BusDevFunc, int Reg, unsigned int Value, int Width)
+{
+ unsigned int RegAddr;
+
+ /*
+ * bit 31 must be 1 and bits 1:0 must be 0 (note Little Endian bit notation)
+ * (DWORD alignment)
+ */
+ RegAddr = MPC106_REG | ((Reg|BusDevFunc) & 0xFFFFFFFC);
+
+ /*
+ * Write reg to PCI Config Address
+ */
+ out32r(MPC106_REG_ADDR, RegAddr);
+
+ /*
+ * Perform a read to update the data register.
+ */
+ in32r(MPC106_REG_DATA | (Reg & 0x3));
+
+ /*
+ * Write reg value to PCI Config Data
+ */
+ switch (Width) {
+ case 1: out8 (MPC106_REG_DATA | (Reg & 0x3),
+ (unsigned char)(Value & 0xFF));
+ break;
+ case 2: out16r (MPC106_REG_DATA | (Reg & 0x3),
+ (unsigned short)(Value & 0xFFFF));
+ break;
+ case 4: out32r (MPC106_REG_DATA | (Reg & 0x3), Value);
+ break;
+ }
+
+ return 0;
+}
+
+/*
+ * Subroutine: PCI_Config_Device
+ *
+ * Description: Configure a PCI device by examining its I/O and memory
+ * address space needs and allocating address space to it by
+ * programming the address decoders in the Base Address Registers.
+ *
+ * Inputs: BusDevFunc Bus+Device+Function number
+ * NumBaseAddr Number of base address registers to
+ * configure
+ *
+ * Return: None
+ *
+ */
+void PCI_Config_Device(int BusDevFunc, int NumBaseAddr)
+{
+ int AddrSlot, i;
+ unsigned long AddrDesc, AddrProg, Min_Gnt_Val;
+
+ unsigned long pcicmd;
+ pcicmd = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_COMMAND, 2);
+ PCI_Write_CFG_Reg (BusDevFunc, PCI_CFG_COMMAND,
+ pcicmd & ~(PCI_CMD_MEMEN|PCI_CMD_IOEN), 2);
+
+ for (AddrSlot = 0; AddrSlot < NumBaseAddr; AddrSlot++) {
+ /*
+ * Write virtual address into register to check LSB.
+ * LSB == 1 => IO space, else memory space.
+ */
+ PCI_Write_CFG_Reg (BusDevFunc,
+ PCI_CFG_BASE_ADDRESS_0 + (4*AddrSlot),
+ 0xFFFFFFFF, 4);
+
+ AddrDesc = PCI_Read_CFG_Reg (BusDevFunc,
+ PCI_CFG_BASE_ADDRESS_0 + (4*AddrSlot),
+ 4);
+
+ if (AddrDesc == 0) /* unimplemented, stop looking */
+ continue; /* 01/04/99 MCG */
+
+#ifdef DEBUG
+ printf ("Read Base Addr Reg %d = 0x%08lx\n",
+ AddrSlot, AddrDesc);
+#endif
+
+ if ((AddrDesc & 1) == 1) { /* I/O space */
+ AddrDesc &= 0xFFFFFFFC;
+
+ for (i = 0; (AddrDesc & 1) != 1; i++)
+ AddrDesc = AddrDesc >> 1;
+
+ AddrDesc = 1 << i;
+#ifdef DEBUG
+ printf(" PCI I/O space = 0x%lx bytes\n", AddrDesc);
+#endif
+ for (AddrProg = CFG_PCI_PCI_IOADDR;
+ AddrProg < LowestIOAddr;
+ AddrProg += AddrDesc) {
+ ; /* empty */
+ }
+ PCI_Write_CFG_Reg (BusDevFunc,
+ PCI_CFG_BASE_ADDRESS_0 + (4*AddrSlot),
+ AddrProg, 4);
+#ifdef DEBUG
+ printf(" PCI I/O addr = 0x%lx\n", AddrProg);
+#endif
+ LowestIOAddr = AddrProg + AddrDesc;
+ } else { /* memory space */
+ AddrDesc &= 0xFFFFFFF0;
+
+ for (i = 0; (AddrDesc & 1) != 1; i++)
+ AddrDesc = AddrDesc >> 1;
+
+ AddrDesc = 1 << i;
+
+ if ((unsigned long)AddrDesc < 4096)
+ AddrDesc = 4096;
+#ifdef DEBUG
+ printf(" PCI memory space = 0x%lx bytes \n",AddrDesc);
+#endif
+ for (AddrProg = CFG_MIN_PCI_MEMADDR1;
+ AddrProg < LowestMemAddr1;
+ AddrProg += AddrDesc) {
+ ; /* empty */
+ }
+
+ PCI_Write_CFG_Reg (BusDevFunc,
+ PCI_CFG_BASE_ADDRESS_0 + (4*AddrSlot),
+ AddrProg, 4);
+#ifdef DEBUG
+ printf(" PCI memory addr = 0x%lx\n", AddrProg);
+#endif
+ LowestMemAddr1 = AddrProg + AddrDesc;
+ }
+ }
+
+ /*
+ * Assign expansion ROM address
+ */
+ PCI_Write_CFG_Reg(BusDevFunc, PCI_CFG_EXPANSION_ROM, 0xFFFFFFFE, 4);
+
+ AddrDesc = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_EXPANSION_ROM, 4);
+
+ if (AddrDesc != 0) {
+#ifdef DEBUG
+ printf("Read Expansion ROM Addr Reg = 0x%08lx\n" , AddrDesc);
+#endif
+ for (i = 0; (AddrDesc & 1) != 1; i++)
+ AddrDesc = AddrDesc >> 1;
+
+ AddrDesc = 1 << i;
+#ifdef DEBUG
+ printf(" PCI Expansion ROM space = 0x%lx bytes\n", AddrDesc);
+#endif
+ for (AddrProg = CFG_MIN_PCI_MEMADDR1;
+ AddrProg < LowestMemAddr1;
+ AddrProg += AddrDesc) {
+ ; /* empty */
+ }
+ PCI_Write_CFG_Reg(BusDevFunc, PCI_CFG_EXPANSION_ROM, AddrProg, 4);
+#ifdef DEBUG
+ printf(" PCI Expansion ROM addr = 0x%lx\n", AddrProg);
+#endif
+ LowestMemAddr1 = AddrProg + AddrDesc;
+ }
+
+ Min_Gnt_Val = 0x80;
+ PCI_Write_CFG_Reg(BusDevFunc, PCI_CFG_LATENCY_TIMER, Min_Gnt_Val, 1);
+
+ /*
+ * Disable interrupt line, if device says it wants to use interrupts
+ */
+ if (PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_DEV_INT_PIN, 1) != 0)
+ PCI_Write_CFG_Reg(BusDevFunc, PCI_CFG_DEV_INT_LINE, 0xFF, 1);
+ /*
+ * Enable i/o space and memory space on this device
+ */
+ PCI_Write_CFG_Reg (BusDevFunc, PCI_CFG_COMMAND,
+ pcicmd | PCI_CMD_MEMEN | PCI_CMD_IOEN, 2);
+}
+
+/*
+ * Subroutine: PCI_Config_VGA_Device
+ *
+ * Description: Configure a PCI VGA device by examining its I/O and memory
+ * address space needs and allocating address space to it by
+ * programming the address decoders in the Base Address Registers.
+ *
+ * Inputs: BusDevFunc Bus+Device+Function number
+ * NumBaseAddr Number of base address registers to
+ * configure
+ *
+ * Return: None
+ *
+ */
+void PCI_Config_VGA_Device(int BusDevFunc, int NumBaseAddr)
+{
+ int AddrSlot, i;
+ unsigned long AddrDesc, AddrProg, Min_Gnt_Val;
+
+ unsigned long pcicmd;
+ pcicmd = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_COMMAND, 2);
+ PCI_Write_CFG_Reg (BusDevFunc, PCI_CFG_COMMAND,
+ pcicmd & ~(PCI_CMD_MEMEN|PCI_CMD_IOEN), 2);
+
+ for (AddrSlot = 0; AddrSlot < NumBaseAddr; AddrSlot++) {
+ /*
+ * Write virtual address into register to check LSB.
+ * LSB == 1 => IO space, else memory space.
+ */
+ PCI_Write_CFG_Reg (BusDevFunc,
+ PCI_CFG_BASE_ADDRESS_0 + (4*AddrSlot),
+ 0xFFFFFFFF, 4);
+
+ AddrDesc = PCI_Read_CFG_Reg (BusDevFunc,
+ PCI_CFG_BASE_ADDRESS_0 + (4*AddrSlot),
+ 4);
+
+ if (AddrDesc == 0) /* unimplemented, stop looking */
+ continue; /* 01/04/99 MCG */
+
+#ifdef DEBUG
+ printf("Read Base Addr Reg %d = 0x%08lx\n",AddrSlot,AddrDesc);
+#endif
+
+ if ((AddrDesc & 1) == 1) { /* I/O space */
+ AddrDesc &= 0xFFFFFFFC;
+
+ for (i = 0; (AddrDesc & 1) != 1; i++)
+ AddrDesc = AddrDesc >> 1;
+
+ AddrDesc = 1 << i;
+#ifdef DEBUG
+ printf(" PCI I/O space = 0x%lx bytes \n",AddrDesc);
+#endif
+ for (AddrProg = CFG_PCI_PCI_IOADDR;
+ AddrProg < LowestIOAddr;
+ AddrProg += AddrDesc) {
+ ; /* empty */
+ }
+
+ PCI_Write_CFG_Reg (BusDevFunc,
+ PCI_CFG_BASE_ADDRESS_0 + (4*AddrSlot),
+ AddrProg, 4);
+ LowestIOAddr = AddrProg + AddrDesc;
+ }
+ else { /* memory space */
+ AddrDesc &= 0xFFFFFFF0;
+
+ for (i = 0; (AddrDesc & 1) != 1; i++)
+ AddrDesc = AddrDesc >> 1;
+
+ AddrDesc = 1 << i;
+
+ if ((unsigned long)AddrDesc < 4096)
+ AddrDesc = 4096;
+#ifdef DEBUG
+ printf(" PCI Memory space = 0x%lx bytes \n",AddrDesc);
+#endif
+ for (AddrProg = CFG_MIN_PCI_MEMADDR2;
+ AddrProg < LowestMemAddr2;
+ AddrProg += AddrDesc) {
+ ; /* empty */
+ }
+
+ PCI_Write_CFG_Reg (BusDevFunc,
+ PCI_CFG_BASE_ADDRESS_0 + (4*AddrSlot),
+ AddrProg, 4);
+ LowestMemAddr2 = AddrProg + AddrDesc;
+ }
+ }
+
+ /*
+ * Assign expansion ROM address
+ */
+ PCI_Write_CFG_Reg(BusDevFunc, PCI_CFG_EXPANSION_ROM, 0xFFFFFFFE, 4);
+
+ AddrDesc = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_EXPANSION_ROM, 4);
+
+ if (AddrDesc != 0) {
+#ifdef DEBUG
+ printf("Read Expansion ROM Addr Reg = 0x%08lx\n" , AddrDesc);
+#endif
+ for (i = 0; (AddrDesc & 1) != 1; i++)
+ AddrDesc = AddrDesc >> 1;
+
+ AddrDesc = 1 << i;
+#ifdef DEBUG
+ printf(" PCI Expansion ROM space = 0x%lx bytes\n", AddrDesc);
+#endif
+ for (AddrProg = CFG_MIN_PCI_MEMADDR2;
+ AddrProg < LowestMemAddr2;
+ AddrProg += AddrDesc) {
+ ; /* empty */
+ }
+ PCI_Write_CFG_Reg(BusDevFunc, PCI_CFG_EXPANSION_ROM, AddrProg, 4);
+#ifdef DEBUG
+ printf(" PCI Expansion ROM addr = 0x%lx\n", AddrProg);
+#endif
+ LowestMemAddr2 = AddrProg + AddrDesc;
+ }
+
+ Min_Gnt_Val = 0x80;
+ PCI_Write_CFG_Reg(BusDevFunc, PCI_CFG_LATENCY_TIMER, Min_Gnt_Val, 1);
+
+ /*
+ * Disable interrupt line, if device says it wants to use interrupts
+ */
+ if (PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_DEV_INT_PIN, 1) != 0)
+ PCI_Write_CFG_Reg(BusDevFunc, PCI_CFG_DEV_INT_LINE, 0xFF, 1);
+
+ /*
+ * Enable i/o space, memory space and master on this device
+ */
+ PCI_Write_CFG_Reg (BusDevFunc, PCI_CFG_COMMAND,
+ pcicmd | PCI_CMD_MEMEN | PCI_CMD_IOEN, 2);
+}
+
+/*
+ * Subroutine: PCI_Config_Bridge
+ *
+ * Description: Configure a PCI-PCI bridge
+ *
+ * Inputs: BusDevFunc Bus+Device+Function number
+ *
+ * Return: None
+ *
+ */
+void PCI_Config_Bridge(int BusDevFunc)
+{
+ int SecondaryBus;
+ int PrimaryBus;
+ int CommandReg_Val;
+ int InitialLowestIOAddr, InitialLowestMemAddr;
+ int IOBase, MemBase;
+ int IOLimit, MemLimit;
+
+ InitialLowestIOAddr = LowestIOAddr;
+ InitialLowestMemAddr = LowestMemAddr1;
+
+ CommandReg_Val = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_COMMAND, 2);
+
+ /* Configure bridge's base address registers */
+ PCI_Config_Device(BusDevFunc, 2);
+
+ /*
+ * PCI_config_device() for the bridge could have changed the values in
+ * LowestIOAddr and LowestMemAddr1, if the bridge itself uses
+ * I/O and/or memory space.
+ */
+ if ( LowestIOAddr > InitialLowestIOAddr ) /* bridge uses IO space? */
+ CommandReg_Val |= 0x01; /* enable I/O Space */
+
+ if ( LowestMemAddr1 > InitialLowestMemAddr ) /* bridge uses memory space? */
+ CommandReg_Val |= 0x02; /* enable Memory Space */
+
+ PrimaryBus = (BusDevFunc >> 16) & 0xFF;
+ PCI_Write_CFG_Reg(BusDevFunc, PCIPCI_PRIMARYBUS, PrimaryBus, 1);
+
+ SecondaryBus = ++MaxBusNum;
+ PCI_Write_CFG_Reg(BusDevFunc, PCIPCI_SECONDARYBUS, SecondaryBus, 1);
+
+ /*
+ * Start with max. possible value for subordinate bus number
+ * Later, after any additional child busses are found, we'll update this
+ */
+ PCI_Write_CFG_Reg(BusDevFunc, PCIPCI_SUBORDINATEBUS, 0xFF, 1);
+
+ /* IO Base must be on 4Kb boundary. Adjust if needed */
+ if ((LowestIOAddr % 4096) != 0)
+ LowestIOAddr += 4096 - (LowestIOAddr % 4096);
+
+ PCI_Write_CFG_Reg (BusDevFunc, PCIPCI_IOBASE,
+ (LowestIOAddr>>8) & 0xF0, 1);
+ PCI_Write_CFG_Reg (BusDevFunc, PCIPCI_IOBASEUPPER16,
+ (LowestIOAddr>>16) & 0xFFFF, 2);
+
+ IOBase = LowestIOAddr;
+
+ /* Mem Base must be on 1 MB boundary. adjust if needed */
+ if ((LowestMemAddr1 % 0x100000) != 0)
+ LowestMemAddr1 += 0x100000 - (LowestMemAddr1 % 0x100000);
+
+ PCI_Write_CFG_Reg (BusDevFunc, PCIPCI_MEMBASE,
+ (LowestMemAddr1>>16) & 0xFFF0, 2);
+ MemBase = LowestMemAddr1;
+
+ /*
+ * secondary bus on this bridge
+ */
+ PCI_Scan(SecondaryBus);
+
+ PCI_Write_CFG_Reg(BusDevFunc, PCIPCI_SUBORDINATEBUS, MaxBusNum, 1);
+
+ IOLimit = LowestIOAddr;
+ if (LowestIOAddr > IOBase) { /* IO space used on secondary bus? */
+ CommandReg_Val |= 0x01; /* enable IO Space */
+ IOLimit--; /* IOLimit is highest used address */
+ }
+
+ PCI_Write_CFG_Reg (BusDevFunc, PCIPCI_IOLIMIT,
+ ((IOLimit)>>8) & 0xF0, 1);
+ PCI_Write_CFG_Reg (BusDevFunc, PCIPCI_IOLIMITUPPER16,
+ ((IOLimit)>>16) & 0xFFFF, 2);
+
+ /*
+ * IOLIMIT is the starting address of a 4K block forwarded by the bridge.
+ * Round LowestIOAddr up to the next 4K boundary if IO space is enabled.
+ */
+ if ((CommandReg_Val & 0x01) == 0x01)
+ LowestIOAddr = (IOLimit | 0xFFF) + 1;
+
+ MemLimit = LowestMemAddr1;
+ if ( LowestMemAddr1 > MemBase ) { /* mem. space is used on secondary bus? */
+ CommandReg_Val |= 0x02; /* enable Memory Space */
+ MemLimit--; /* MemLimit is highest used address */
+ }
+
+ PCI_Write_CFG_Reg (BusDevFunc, PCIPCI_MEMLIMIT,
+ ((MemLimit)>>16) & 0xFFF0, 2);
+
+ /*
+ * MEMLIMIT is the starting address of a 1M block forwarded by the bridge.
+ * Round LowestMemAddr up to the next 1M boundary
+ * if Memory space is enabled.
+ */
+
+ if ( (CommandReg_Val & 0x02) == 0x02 )
+ LowestMemAddr1 = (MemLimit | 0xFFFFF) + 1;
+
+ /* Enable Bus Master on secondary bus */
+ CommandReg_Val |= 0x04;
+
+ PCI_Write_CFG_Reg(BusDevFunc, PCI_CFG_COMMAND, CommandReg_Val, 2);
+}
+
+/*
+ * Subroutine: PCI_Find_Device
+ *
+ * Description: Locate a PCI device by vendor and device number on any bus.
+ *
+ * Inputs: VendorID Value of the device's Vendor ID field
+ * DeviceID Value of the device's Device ID field
+ *
+ * Return: < 0 Device not found
+ * (int) PCI Bus+Device+Function number
+ *
+ */
+int PCI_Find_Device(unsigned short VendorID, unsigned short DeviceID)
+{
+ int Device;
+ int BusDevFunc;
+ int BusNum;
+
+#if CFG_SCSI_SCAN_BUS_REVERSE
+ for (BusNum = MaxBusNum; BusNum >= 0; BusNum--) {
+#else
+ for (BusNum = 0; BusNum <= MaxBusNum; BusNum++) {
+#endif
+ for (Device = 0; Device < CFG_MAX_PCI_DEVICES; Device++) {
+ BusDevFunc = (BusNum << 16) | (Device << 11);
+
+ if (PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_VENDOR_ID, 2) == VendorID
+ && PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_DEVICE_ID, 2) == DeviceID) {
+ return (BusDevFunc);
+ }
+ }
+ }
+ return (-1);
+}
+
+
+#if (CONFIG_COMMANDS & CFG_CMD_PCI)
+/*
+ * Follows routines for the output of infos about devices on PCI bus.
+ */
+
+/*
+ * Subroutine: do_pciinfo
+ *
+ * Description: Handler for 'pciinfo' command..
+ *
+ * Inputs: argv[1] may contain the number of the bus to be scanned.
+ * Default is bus 0.
+ *
+ * Return: None
+ *
+ */
+void do_pciinfo(cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
+{
+ char *s;
+ int bus_no = 0;
+
+ if (argc == 2)
+ {
+ bus_no = (int)simple_strtoul(argv[1], NULL, 10);
+ }
+
+ if ((s = getenv("pci_listing")) != NULL)
+ ShortPCIListing = (strcmp(s, "short") == 0) ? 1 : 0;
+ else
+ ShortPCIListing = 0;
+
+ pciinfo(bus_no);
+}
+
+
+/*
+ * Subroutine: pciinfo
+ *
+ * Description: Show information about devices on PCI bus.
+ * Depending on the define CFG_SHORT_PCI_LISTING
+ * the output will be more or less exhaustive.
+ *
+ * Inputs: bus_no the number of the bus to be scanned.
+ *
+ * Return: None
+ *
+ */
+void pciinfo(int BusNum)
+{
+ int Device;
+ int Function;
+ unsigned int HeaderType;
+ unsigned int VendorID;
+ int BusDevFunc;
+
+ printf("Scanning PCI devices on bus %d\n", BusNum);
+
+ if (ShortPCIListing) {
+ printf("No. VendorId DeviceId Device Class Sub-Class\n");
+ printf("________________________________________________________\n");
+ }
+
+ for (Device = 0; Device < CFG_MAX_PCI_DEVICES; Device++) {
+ HeaderType = 0;
+ VendorID = 0;
+ for (Function = 0; Function < CFG_MAX_PCI_FUNCTIONS; Function++) {
+ /*
+ * If this is not a multi-function device, we skip the rest.
+ */
+ if (Function && !(HeaderType & 0x80))
+ break;
+
+ BusDevFunc = (BusNum << 16) |
+ (Device << 11) |
+ (Function << 8);
+
+ VendorID = PCI_Read_CFG_Reg (BusDevFunc, PCI_CFG_VENDOR_ID, 2);
+ if ((VendorID == 0xFFFF) || (VendorID == 0x0000))
+ continue;
+
+ HeaderType = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_HEADER_TYPE, 1);
+
+ if (ShortPCIListing)
+ printf("%02d.%d ", Device, Function);
+ else
+ printf("\nFound PCI device %d, function %d:\n",
+ Device, Function);
+
+ PCI_Header_Show(BusDevFunc);
+ }
+ }
+}
+
+
+/*
+ * Subroutine: PCI_Header_Show
+ *
+ * Description: Reads the header of the specified PCI device.
+ *
+ * Inputs: BusDevFunc Bus+Device+Function number
+ *
+ * Return: None
+ *
+ */
+void PCI_Header_Show(int BusDevFunc)
+{
+ PCI_HEADER_DEVICE headerDevice;
+ PCI_HEADER_BRIDGE headerBridge;
+ PCI_HEADER_DEVICE * pD = &headerDevice;
+ PCI_HEADER_BRIDGE * pB = &headerBridge;
+
+ pD->headerType = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_HEADER_TYPE, 1);
+
+ if (pD->headerType & 0x01) { /* PCI-to-PCI bridge */
+ pB->vendorId = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_VENDOR_ID, 2);
+ pB->deviceId = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_DEVICE_ID, 2);
+ pB->command = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_COMMAND, 2);
+ pB->status = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_STATUS, 2);
+ pB->revisionId = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_REVISION, 1);
+ pB->progIf = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_PROGRAMMING_IF, 1);
+ pB->subClass = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_SUBCLASS, 1);
+ pB->classCode = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_CLASS, 1);
+ pB->cacheLine = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_CACHE_LINE_SIZE, 1);
+ pB->latency = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_LATENCY_TIMER, 1);
+ pB->headerType = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_HEADER_TYPE, 1);
+ pB->bist = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_BIST, 1);
+ pB->base0 = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_BASE_ADDRESS_0, 4);
+ pB->base1 = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_BASE_ADDRESS_1, 4);
+ pB->priBus = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_PRIMARY_BUS, 1);
+ pB->secBus = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_SECONDARY_BUS, 1);
+ pB->subBus = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_SUBORDINATE_BUS, 1);
+ pB->secLatency = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_SEC_LATENCY, 1);
+ pB->ioBase = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_IO_BASE, 1);
+ pB->ioLimit = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_IO_LIMIT, 1);
+ pB->secStatus = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_SEC_STATUS, 2);
+ pB->memBase = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_MEM_BASE, 2);
+ pB->memLimit = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_MEM_LIMIT, 2);
+ pB->preBase = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_PRE_MEM_BASE, 2);
+ pB->preLimit = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_PRE_MEM_LIMIT, 2);
+ pB->preBaseUpper = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_PRE_MEM_BASE_U, 4);
+ pB->preLimitUpper = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_PRE_MEM_LIMIT_U, 4);
+ pB->ioBaseUpper = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_IO_BASE_U, 2);
+ pB->ioLimitUpper = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_IO_LIMIT_U, 2);
+ pB->romBase = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_ROM_BASE, 4);
+ pB->intLine = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_BRG_INT_LINE, 1);
+ pB->intPin = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_BRG_INT_PIN, 1);
+ pB->control = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_BRIDGE_CONTROL, 2);
+ PCI_Bheader_Print(pB);
+ } else { /* PCI device */
+ pD->vendorId = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_VENDOR_ID, 2);
+ pD->deviceId = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_DEVICE_ID, 2);
+ pD->command = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_COMMAND, 2);
+ pD->status = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_STATUS, 1);
+ pD->revisionId = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_REVISION, 1);
+ pD->progIf = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_PROGRAMMING_IF, 1);
+ pD->subClass = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_SUBCLASS, 1);
+ pD->classCode = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_CLASS, 1);
+ pD->cacheLine = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_CACHE_LINE_SIZE, 1);
+ pD->latency = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_LATENCY_TIMER, 1);
+ pD->headerType = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_HEADER_TYPE, 1);
+ pD->bist = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_BIST, 1);
+ pD->base0 = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_BASE_ADDRESS_0, 4);
+ pD->base1 = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_BASE_ADDRESS_1, 4);
+ pD->base2 = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_BASE_ADDRESS_2, 4);
+ pD->base3 = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_BASE_ADDRESS_3, 4);
+ pD->base4 = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_BASE_ADDRESS_4, 4);
+ pD->base5 = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_BASE_ADDRESS_5, 4);
+ pD->cis = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_CIS, 4);
+ pD->subVendorId = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_SUB_VENDER_ID, 2);
+ pD->subSystemId = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_SUB_SYSTEM_ID, 2);
+ pD->romBase = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_EXPANSION_ROM, 4);
+ pD->intLine = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_DEV_INT_LINE, 1);
+ pD->intPin = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_DEV_INT_PIN, 1);
+ pD->minGrant = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_MIN_GRANT, 1);
+ pD->maxLatency = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_MAX_LATENCY, 1);
+ PCI_Dheader_Print(pD);
+ }
+}
+
+static char *PCI_classes[] = {
+ "Build before PCI Rev2.0",
+ "Mass storage controller",
+ "Network controller ",
+ "Display controller ",
+ "Multimedia device ",
+ "Memory controller ",
+ "Bridge device ",
+ "Simple comm. controller",
+ "Base system peripheral ",
+ "Input device ",
+ "Docking station ",
+ "Processor ",
+ "Serial bus controller ",
+ "Reserved entry ",
+ "Does not fit any class "
+};
+
+/*
+ * Subroutine: PCI_Dheader_Print
+ *
+ * Description: Prints the header of the specified PCI device.
+ *
+ * Inputs: pD pointer to device header info
+ *
+ * Return: None
+ *
+ */
+void PCI_Dheader_Print(PCI_HEADER_DEVICE * pD)
+{
+ if (ShortPCIListing) {
+ printf("0x%.4x 0x%.4x %s 0x%.2x\n",
+ (ushort)pD->vendorId,
+ (ushort)pD->deviceId,
+ PCI_classes[(uchar)pD->classCode],
+ (uchar)pD->subClass);
+ } else {
+ printf(" vendor ID = 0x%.4x\n", (ushort)pD->vendorId);
+ printf(" device ID = 0x%.4x\n", (ushort)pD->deviceId);
+ printf(" command register = 0x%.4x\n", (ushort)pD->command);
+ printf(" status register = 0x%.4x\n", (ushort)pD->status);
+ printf(" revision ID = 0x%.2x\n", (uchar)pD->revisionId);
+ printf(" class code = 0x%.2x (%s)\n",
+ (uchar)pD->classCode,
+ PCI_classes[(int)pD->classCode]);
+ printf(" sub class code = 0x%.2x\n", (uchar)pD->subClass);
+ printf(" programming interface = 0x%.2x\n", (uchar)pD->progIf);
+ printf(" cache line = 0x%.2x\n", (uchar)pD->cacheLine);
+ printf(" latency time = 0x%.2x\n", (uchar)pD->latency);
+ printf(" header type = 0x%.2x\n", (uchar)pD->headerType);
+ printf(" BIST = 0x%.2x\n", (uchar)pD->bist);
+ printf(" base address 0 = 0x%.8x\n", pD->base0);
+ printf(" base address 1 = 0x%.8x\n", pD->base1);
+ printf(" base address 2 = 0x%.8x\n", pD->base2);
+ printf(" base address 3 = 0x%.8x\n", pD->base3);
+ printf(" base address 4 = 0x%.8x\n", pD->base4);
+ printf(" base address 5 = 0x%.8x\n", pD->base5);
+ printf(" cardBus CIS pointer = 0x%.8x\n", pD->cis);
+ printf(" sub system vendor ID = 0x%.4x\n", (ushort)pD->subVendorId);
+ printf(" sub system ID = 0x%.4x\n", (ushort)pD->subSystemId);
+ printf(" expansion ROM base address = 0x%.8x\n", pD->romBase);
+ printf(" interrupt line = 0x%.2x\n", (uchar)pD->intLine);
+ printf(" interrupt pin = 0x%.2x\n", (uchar)pD->intPin);
+ printf(" min Grant = 0x%.2x\n", (uchar)pD->minGrant);
+ printf(" max Latency = 0x%.2x\n", (uchar)pD->maxLatency);
+ }
+}
+
+/*
+ * Subroutine: PCI_Bheader_Print
+ *
+ * Description: Prints the header of the specified PCI-to-PCI bridge.
+ *
+ * Inputs: pB pointer to bridge header info
+ *
+ * Return: None
+ *
+ */
+void PCI_Bheader_Print (PCI_HEADER_BRIDGE * pB)
+{
+ if (ShortPCIListing) {
+ printf("0x%.4x 0x%.4x %s 0x%.2x\n",
+ (ushort)pB->vendorId,
+ (ushort)pB->deviceId,
+ PCI_classes[(uchar)pB->classCode],
+ (uchar)pB->subClass);
+ } else {
+ printf (" vendor ID = 0x%.4x\n", (ushort)pB->vendorId);
+ printf (" device ID = 0x%.4x\n", (ushort)pB->deviceId);
+ printf (" command register = 0x%.4x\n", (ushort)pB->command);
+ printf (" status register = 0x%.4x\n", (ushort)pB->status);
+ printf (" revision ID = 0x%.2x\n", (uchar)pB->revisionId);
+ printf (" class code = 0x%.2x (%s)\n",
+ (uchar)pB->classCode,
+ PCI_classes[(int)pB->classCode]);
+ printf (" sub class code = 0x%.2x\n", (uchar)pB->subClass);
+ printf (" programming interface = 0x%.2x\n", (uchar)pB->progIf);
+ printf (" cache line = 0x%.2x\n", (uchar)pB->cacheLine);
+ printf (" latency time = 0x%.2x\n", (uchar)pB->latency);
+ printf (" header type = 0x%.2x\n", (uchar)pB->headerType);
+ printf (" BIST = 0x%.2x\n", (uchar)pB->bist);
+ printf (" base address 0 = 0x%.8x\n", pB->base0);
+ printf (" base address 1 = 0x%.8x\n", pB->base1);
+ printf (" primary bus number = 0x%.2x\n", (uchar)pB->priBus);
+ printf (" secondary bus number = 0x%.2x\n", (uchar)pB->secBus);
+ printf (" subordinate bus number = 0x%.2x\n", (uchar)pB->subBus);
+ printf (" secondary latency timer = 0x%.2x\n", (uchar)pB->secLatency);
+ printf (" IO base = 0x%.2x\n", (uchar)pB->ioBase);
+ printf (" IO limit = 0x%.2x\n", (uchar)pB->ioLimit);
+ printf (" secondary status = 0x%.4x\n", (ushort)pB->secStatus);
+ printf (" memory base = 0x%.4x\n", (ushort)pB->memBase);
+ printf (" memory limit = 0x%.4x\n", (ushort)pB->memLimit);
+ printf (" prefetch memory base = 0x%.4x\n", (ushort)pB->preBase);
+ printf (" prefetch memory limit = 0x%.4x\n", (ushort)pB->preLimit);
+ printf (" prefetch memory base upper = 0x%.8x\n", pB->preBaseUpper);
+ printf (" prefetch memory limit upper = 0x%.8x\n", pB->preLimitUpper);
+ printf (" IO base upper 16 bits = 0x%.4x\n", (ushort)pB->ioBaseUpper);
+ printf (" IO limit upper 16 bits = 0x%.4x\n", (ushort)pB->ioLimitUpper);
+ printf (" expansion ROM base address = 0x%.8x\n", pB->romBase);
+ printf (" interrupt line = 0x%.2x\n", (uchar)pB->intLine);
+ printf (" interrupt pin = 0x%.2x\n", (uchar)pB->intPin);
+ printf (" bridge control = 0x%.4x\n", (ushort)pB->control);
+ }
+}
+
+#endif /* CONFIG_COMMANDS & CFG_CMD_PCI */
+
+#endif /* CONFIG_PCI */
--- /dev/null
+/*
+ * COM1 NS16550 support
+ * originally from linux source (arch/ppc/boot/ns16550.c)
+ * modified to use CFG_ISA_MEM and new defines
+ */
+
+#include <config.h>
+#include "ns16550.h"
+
+
+void
+NS16550_init(volatile struct NS16550 *com_port, int baud_divisor)
+{
+ com_port->ier = 0x00; /* interrupt enable register */
+ com_port->lcr = LCR_BKSE; /* Access baud rate */
+ com_port->dll = baud_divisor & 0xff; /* 9600 baud */
+ com_port->dlm = (baud_divisor >> 8) & 0xff;
+ com_port->lcr = LCR_8N1; /* 8 data, 1 stop, no parity */
+ com_port->mcr = MCR_DTR | MCR_RTS; /* RTS/DTR */
+ com_port->fcr = FCR_FIFO_EN | FCR_RXSR | FCR_TXSR; /* Clear & enable FIFOs */
+}
+
+void
+NS16550_reinit(volatile struct NS16550 *com_port, int baud_divisor)
+{
+ com_port->ier = 0x00;
+ com_port->lcr = LCR_BKSE; /* Access baud rate */
+ com_port->dll = baud_divisor & 0xff; /* 9600 baud */
+ com_port->dlm = (baud_divisor >> 8) & 0xff;
+ com_port->lcr = LCR_8N1; /* 8 data, 1 stop, no parity */
+ com_port->mcr = MCR_DTR | MCR_RTS; /* RTS/DTR */
+ com_port->fcr = FCR_FIFO_EN | FCR_RXSR | FCR_TXSR; /* Clear & enable FIFOs */
+}
+
+void NS16550_putc(volatile struct NS16550 *com_port, unsigned char c)
+{
+ while ((com_port->lsr & LSR_THRE) == 0) ;
+ com_port->thr = c;
+}
+
+unsigned char
+NS16550_getc(volatile struct NS16550 *com_port)
+{
+ while ((com_port->lsr & LSR_DR) == 0) ;
+ return (com_port->rbr);
+}
+
+int NS16550_tstc(volatile struct NS16550 *com_port)
+{
+ return ((com_port->lsr & LSR_DR) != 0);
+}
+
+
+
--- /dev/null
+/*
+ * NS16550 Serial Port
+ * originally from linux source (arch/ppc/boot/ns16550.h)
+ * modified slightly to
+ * have addresses as offsets from CFG_ISA_BASE
+ * added a few more definitions
+ * added prototypes for ns16550.c
+ * reduced no of com ports to 2
+ * modifications (c) Rob Taylor, Flying Pig Systems. 2000.
+ */
+
+
+struct NS16550
+ {
+ unsigned char rbr; /* 0 Rx */
+ unsigned char ier; /* 1 interrupt enable register, Divisor Latch High */
+ unsigned char fcr; /* 2 fifo control rgister */
+ unsigned char lcr; /* 3 line control register */
+ unsigned char mcr; /* 4 modem control register */
+ unsigned char lsr; /* 5 line status register */
+ unsigned char msr; /* 6 modem status register */
+ unsigned char scr; /* 7 scratch pad register */
+ };
+
+typedef struct NS16550 *NS16550_t;
+
+#define thr rbr /* Tx */
+#define iir fcr /* interrupt identification register */
+#define dll rbr /* divisor latch low */
+#define dlm ier /* divisor latch high */
+
+#define FCR_FIFO_EN 0x01 /*fifo enable*/
+#define FCR_RXSR 0x02 /*reciever soft reset*/
+#define FCR_TXSR 0x04 /*transmitter soft reset*/
+
+
+#define MCR_DTR 0x01
+#define MCR_RTS 0x02
+#define MCR_DMA_EN 0x04
+#define MCR_TX_DFR 0x08
+
+
+#define LCR_WLS_MSK 0x03 /* character length slect mask*/
+#define LCR_WLS_5 0x00 /* 5 bit character length */
+#define LCR_WLS_6 0x01 /* 6 bit character length */
+#define LCR_WLS_7 0x02 /* 7 bit character length */
+#define LCR_WLS_8 0x03 /* 8 bit character length */
+#define LCR_STB 0x04 /* Number of stop Bits, off = 1, on = 1.5 or 2) */
+#define LCR_PEN 0x08 /* Parity eneble*/
+#define LCR_EPS 0x10 /* Even Parity Select*/
+#define LCR_STKP 0x20 /* Stick Parity*/
+#define LCR_SBRK 0x40 /* Set Break*/
+#define LCR_BKSE 0x80 /* Bank select enable*/
+
+#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 */
+
+/* useful defaults for LCR*/
+#define LCR_8N1 0x03
+
+
+#define COM1 0x03F8
+#define COM2 0x02F8
+
+void NS16550_init(volatile struct NS16550 *com_port, int baud_divisor);
+void NS16550_reinit(volatile struct NS16550 *com_port, int baud_divisor);
+void NS16550_putc(volatile struct NS16550 *com_port, unsigned char c);
+unsigned char NS16550_getc(volatile struct NS16550 *com_port);
+int NS16550_tstc(volatile struct NS16550 *com_port);
+
--- /dev/null
+/*
+ * (C) Copyright 2000
+ * Rob Taylor, Flying Pig Systems. robt@flyingpig.com.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+/*
+ * 09-18-2001 Andreas Heppel, Sysgo RTS GmbH:
+ * Added initialisation of additional logical devices on the chip.
+ */
+
+#include <config.h>
+
+#include "ns87308.h"
+#include "ns16550.h" /* to configure the 87308's internal 16550's */
+#include <asm/mc146818rtc.h> /* to configure 87308's RTC */
+
+void initialise_ns87308 (void)
+{
+ unsigned char data;
+
+ /*
+ * Switch floppy drive to PS/2 mode.
+ */
+ read_pnp_config(SUPOERIO_CONF1, &data);
+ data &= 0xFB;
+ write_pnp_config(SUPOERIO_CONF1, data);
+
+ PNP_SET_DEVICE_BASE(LDEV_UART1, COM1);
+ PNP_SET_DEVICE_BASE(LDEV_UART2, COM2);
+
+ PNP_SET_DEVICE_BASE(LDEV_KBC1, KBC1_BASE);
+ write_pnp_config(LUN_CONFIG_REG, 0);
+ write_pnp_config(CBASE_HIGH, 0x00);
+ write_pnp_config(CBASE_LOW, 0x64);
+
+ PNP_ACTIVATE_DEVICE(LDEV_MOUSE);
+
+ PNP_SET_DEVICE_BASE(LDEV_FDC, FDC_BASE);
+ write_pnp_config(LUN_CONFIG_REG, 0x40);
+
+ PNP_SET_DEVICE_BASE(LDEV_PARP, LPT_BASE);
+ PNP_SET_DEVICE_BASE(LDEV_GPIO, GPIO_BASE);
+
+ PNP_SET_DEVICE_BASE(LDEV_RTC_APC, RTC_PORT(0));
+ PNP_SET_DEVICE_BASE(LDEV_POWRMAN, PWMAN_BASE);
+
+ /* Enable all units */
+ pci_writeb(0x00, CFG_ISA_IO + PWMAN_BASE);
+ eieio();
+ pci_writeb(0x7d, CFG_ISA_IO + PWMAN_BASE + 1);
+
+ pci_writeb(0x01, CFG_ISA_IO + PWMAN_BASE);
+ eieio();
+ pci_writeb(0x87, CFG_ISA_IO + PWMAN_BASE + 1);
+
+ /* SuperI/O clock source is 24MHz via X1 */
+ pci_writeb(0x03, CFG_ISA_IO + PWMAN_BASE);
+ eieio();
+ pci_writeb(0x00, CFG_ISA_IO + PWMAN_BASE + 1);
+
+ /*
+ * set up the NVRAM access registers
+ * NVRAM's controlled by the configurable CS line from the 87308
+ */
+ PNP_PGCS_CSLINE_BASE(0, 0x76);
+ PNP_PGCS_CSLINE_CONF(0, 0x40);
+ PNP_PGCS_CSLINE_BASE(1, 0x70);
+ PNP_PGCS_CSLINE_CONF(1, 0x1C);
+ PNP_PGCS_CSLINE_BASE(2, 0x71);
+ PNP_PGCS_CSLINE_CONF(2, 0x1C);
+}
--- /dev/null
+/*
+ * (C) Copyright 2000
+ * Rob Taylor, Flying Pig Systems. robt@flyingpig.com.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#ifndef _NS87308_H_
+#define _NS87308_H_
+
+#include <asm/pci_io.h>
+
+/* Note: I couldn't find a full data sheet for the ns87308, but the ns87307 seems to be pretty
+ functionally- (and pin-) equivalent to the 87308, but the 308 has better ir support. */
+
+void initialise_ns87308(void);
+
+/*
+ * The following struct represents the GPIO registers on the NS87308/NS97307
+ */
+struct GPIO
+{
+ unsigned char dta1; /* 0 data port 1 */
+ unsigned char dir1; /* 1 direction port 1 */
+ unsigned char out1; /* 2 output type port 1 */
+ unsigned char puc1; /* 3 pull-up control port 1 */
+ unsigned char dta2; /* 4 data port 2 */
+ unsigned char dir2; /* 5 direction port 2 */
+ unsigned char out2; /* 6 output type port 2 */
+ unsigned char puc2; /* 7 pull-up control port 2 */
+};
+
+#define GPIO_BASE 0x0220
+#define LPT_BASE 0x0278
+#define KBC1_BASE 0x0060
+#define FDC_BASE 0x03F0
+
+#define PWMAN_BASE 0x460
+/*
+ * The following represents the power management registers on the NS87308/NS97307
+ */
+#define PWM_FER1 0 /* 0 function enable reg. 1 */
+#define PWM_FER2 1 /* 1 function enable reg. 2 */
+#define PWM_PMC1 2 /* 2 power mgmt. control 1 */
+#define PWM_PMC2 3 /* 3 power mgmt. control 2 */
+#define PWM_PMC3 4 /* 4 power mgmt. control 3 */
+#define PWM_WDTO 5 /* 5 watchdog time-out */
+#define PWM_WDCF 6 /* 6 watchdog config. */
+#define PWM_WDST 7 /* 7 watchdog status */
+
+/*PNP config registers:
+ * these depend on the stated of BADDR1 and BADDR0 on startup
+ * so there's three versions here with the last two digits indicating
+ * for which configuration their valid
+ * the 1st of the two digits indicates the state of BADDR1
+ * the 2st of the two digits indicates the state of BADDR0
+ */
+
+
+#define IO_INDEX_OFFSET_0x 0x0279 /* full PnP isa Mode */
+#define IO_INDEX_OFFSET_10 0x015C /* PnP motherboard mode */
+#define IO_INDEX_OFFSET_11 0x002E /* PnP motherboard mode */
+#define IO_DATA_OFFSET_0x 0x0A79 /* full PnP isa Mode */
+#define IO_DATA_OFFSET_10 0x015D /* PnP motherboard mode */
+#define IO_DATA_OFFSET_11 0x002F /* PnP motherboard mode */
+
+#if defined(CFG_NS87308_BADDR_0x)
+#define IO_INDEX (CFG_ISA_IO + IO_INDEX_OFFSET_0x)
+#define IO_DATA (CFG_ISA_IO + IO_DATA_OFFSET_0x)
+#elif defined(CFG_NS87308_BADDR_10)
+#define IO_INDEX (CFG_ISA_IO + IO_INDEX_OFFSET_10)
+#define IO_DATA (CFG_ISA_IO + IO_DATA_OFFSET_10)
+#elif defined(CFG_NS87308_BADDR_11)
+#define IO_INDEX (CFG_ISA_IO + IO_INDEX_OFFSET_11)
+#define IO_DATA (CFG_ISA_IO + IO_DATA_OFFSET_11)
+#endif
+
+/* PnP register definitions */
+
+#define SET_RD_DATA_PORT 0x00
+#define SERIAL_ISOLATION 0x01
+#define CONFIG_CONTROL 0x02
+#define WAKE_CSN 0x03
+#define RES_DATA 0x04
+#define STATUS 0x05
+#define SET_CSN 0x06
+#define LOGICAL_DEVICE 0x07
+
+/*vendor defined values */
+#define SID_REG 0x20
+#define SUPOERIO_CONF1 0x21
+#define SUPOERIO_CONF2 0x22
+#define PGCS_INDEX 0x23
+#define PGCS_DATA 0x24
+
+/* values above 30 are different for each logical device
+ but I can't be arsed to enter them all. the ones here
+ are pretty consistent between all logical devices
+ feel free to correct the situation if you want.. ;)
+ */
+#define ACTIVATE 0x30
+#define ACTIVATE_OFF 0x00
+#define ACTIVATE_ON 0x01
+
+#define BASE_ADDR_HIGH 0x60
+#define BASE_ADDR_LOW 0x61
+#define LUN_CONFIG_REG 0xF0
+#define DBASE_HIGH 0x60 /* SIO KBC data base address, 15:8 */
+#define DBASE_LOW 0x61 /* SIO KBC data base address, 7:0 */
+#define CBASE_HIGH 0x62 /* SIO KBC command base addr, 15:8 */
+#define CBASE_LOW 0x63 /* SIO KBC command base addr, 7:0 */
+
+/* the logical devices*/
+#define LDEV_KBC1 0x00 /* 2 devices for keyboard and mouse controller*/
+#define LDEV_KBC2 0x01
+#define LDEV_MOUSE 0x01
+#define LDEV_RTC_APC 0x02 /*Real Time Clock and Advanced Power Control*/
+#define LDEV_FDC 0x03 /*floppy disk controller*/
+#define LDEV_PARP 0x04 /*Parallel port*/
+#define LDEV_UART1 0x06
+#define LDEV_UART2 0x05
+#define LDEV_GPIO 0x07 /*General Purpose IO and chip select output signals*/
+#define LDEV_POWRMAN 0x08 /*Power Managment*/
+
+/*some functions and macro's for doing configuration */
+
+static inline void read_pnp_config(unsigned char index, unsigned char *data)
+{
+ pci_writeb(index,IO_INDEX);
+ pci_readb(IO_DATA, *data);
+}
+
+static inline void write_pnp_config(unsigned char index, unsigned char data)
+{
+ pci_writeb(index,IO_INDEX);
+ pci_writeb(data, IO_DATA);
+}
+
+static inline void pnp_set_device(unsigned char dev)
+{
+ write_pnp_config(LOGICAL_DEVICE, dev);
+}
+
+
+/*void write_pnp_config(unsigned char index, unsigned char data);
+void pnp_set_device(unsigned char dev);
+*/
+
+#define PNP_SET_DEVICE_BASE(dev,base) \
+ pnp_set_device(dev); \
+ write_pnp_config(ACTIVATE, ACTIVATE_OFF); \
+ write_pnp_config(BASE_ADDR_HIGH, ((base) >> 8) & 0xff ); \
+ write_pnp_config(BASE_ADDR_LOW, (base) &0xff); \
+ write_pnp_config(ACTIVATE, ACTIVATE_ON);
+
+#define PNP_ACTIVATE_DEVICE(dev) \
+ pnp_set_device(dev); \
+ write_pnp_config(ACTIVATE, ACTIVATE_ON);
+
+#define PNP_DEACTIVATE_DEVICE(dev) \
+ pnp_set_device(dev); \
+ write_pnp_config(ACTIVATE, ACTIVATE_OFF);
+
+
+static inline void write_pgcs_config(unsigned char index, unsigned char data)
+{
+ write_pnp_config(PGCS_INDEX, index);
+ write_pnp_config(PGCS_DATA, data);
+}
+
+/* these macrose configure the 3 CS lines
+ on the sandpoint board these controll NVRAM
+ CS0 is connected to NVRAMCS
+ CS1 is connected to NVRAMAS0
+ CS2 is connected to NVRAMAS1
+ */
+#define PGCS_CS_ASSERT_ON_WRITE 0x10
+#define PGCS_CS_ASSERT_ON_READ 0x20
+
+#define PNP_PGCS_CSLINE_BASE(cs, base) \
+ write_pgcs_config((cs) << 2, ((base) >> 8) & 0xff ); \
+ write_pgcs_config(((cs) << 2) + 1, (base) & 0xff );
+
+#define PNP_PGCS_CSLINE_CONF(cs, conf) \
+ write_pgcs_config(((cs) << 2) + 2, (conf) );
+
+
+/* The following sections are for 87308 extensions to the standard compoents it emulates */
+
+/* extensions to 16550*/
+
+#define MCR_MDSL_MSK 0xe0 /*mode select mask*/
+#define MCR_MDSL_UART 0x00 /*uart, default*/
+#define MCR_MDSL_SHRPIR 0x02 /*Sharp IR*/
+#define MCR_MDSL_SIR 0x03 /*SIR*/
+#define MCR_MDSL_CIR 0x06 /*Consumer IR*/
+
+#define FCR_TXFTH0 0x10 /* these bits control threshod of data level in fifo */
+#define FCR_TXFTH1 0x20 /* for interrupt trigger */
+
+
+#endif /*_NS87308_H_*/
--- /dev/null
+/*
+ * (C) Copyright 2001
+ * Josh Huber <huber@mclx.com>, Mission Critical Linux, 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
+ */
+
+/*
+ * ppcboot.lds - linker script for ppcboot on the Galileo Eval Board.
+ */
+
+OUTPUT_ARCH(powerpc)
+SEARCH_DIR(/lib); SEARCH_DIR(/usr/lib); SEARCH_DIR(/usr/local/lib); SEARCH_DIR(/usr/local/powerpc-any-elf/lib);
+/* Do we need any of these for elf?
+ __DYNAMIC = 0; */
+SECTIONS
+{
+ /* Read-only sections, merged into text segment: */
+ . = + SIZEOF_HEADERS;
+ .interp : { *(.interp) }
+ .hash : { *(.hash) }
+ .dynsym : { *(.dynsym) }
+ .dynstr : { *(.dynstr) }
+ .rel.text : { *(.rel.text) }
+ .rela.text : { *(.rela.text) }
+ .rel.data : { *(.rel.data) }
+ .rela.data : { *(.rela.data) }
+ .rel.rodata : { *(.rel.rodata) }
+ .rela.rodata : { *(.rela.rodata) }
+ .rel.got : { *(.rel.got) }
+ .rela.got : { *(.rela.got) }
+ .rel.ctors : { *(.rel.ctors) }
+ .rela.ctors : { *(.rela.ctors) }
+ .rel.dtors : { *(.rel.dtors) }
+ .rela.dtors : { *(.rela.dtors) }
+ .rel.bss : { *(.rel.bss) }
+ .rela.bss : { *(.rela.bss) }
+ .rel.plt : { *(.rel.plt) }
+ .rela.plt : { *(.rela.plt) }
+ .init : { *(.init) }
+ .plt : { *(.plt) }
+ .text :
+ {
+ cpu/mpc75x/start.o (.text)
+
+/* store the environment in a seperate sector in the boot flash */
+/* . = env_offset; */
+/* common/environment.o(.text) */
+
+ *(.text)
+ *(.fixup)
+ *(.got1)
+ }
+ _etext = .;
+ PROVIDE (etext = .);
+ .rodata :
+ {
+ *(.rodata)
+ *(.rodata1)
+ }
+ .fini : { *(.fini) } =0
+ .ctors : { *(.ctors) }
+ .dtors : { *(.dtors) }
+
+ /* Read-write section, merged into data segment: */
+ . = (. + 0x00FF) & 0xFFFFFF00;
+ _erotext = .;
+ PROVIDE (erotext = .);
+ .reloc :
+ {
+ *(.got)
+ _GOT2_TABLE_ = .;
+ *(.got2)
+ _FIXUP_TABLE_ = .;
+ *(.fixup)
+ }
+ __got2_entries = (_FIXUP_TABLE_ - _GOT2_TABLE_) >>2;
+ __fixup_entries = (. - _FIXUP_TABLE_)>>2;
+
+ .data :
+ {
+ *(.data)
+ *(.data1)
+ *(.sdata)
+ *(.sdata2)
+ *(.dynamic)
+ CONSTRUCTORS
+ }
+ _edata = .;
+ PROVIDE (edata = .);
+
+ __start___ex_table = .;
+ __ex_table : { *(__ex_table) }
+ __stop___ex_table = .;
+
+ . = ALIGN(256);
+ __init_begin = .;
+ .text.init : { *(.text.init) }
+ .data.init : { *(.data.init) }
+ . = ALIGN(256);
+ __init_end = .;
+
+ __bss_start = .;
+ .bss :
+ {
+ *(.sbss) *(.scommon)
+ *(.dynbss)
+ *(.bss)
+ *(COMMON)
+ }
+ _end = . ;
+ PROVIDE (end = .);
+}
--- /dev/null
+/*
+ * (C) Copyright 2000
+ * Rob Taylor, Flying Pig Systems Ltd. robt@flyingpig.com
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+OUTPUT_ARCH(powerpc)
+SEARCH_DIR(/lib); SEARCH_DIR(/usr/lib); SEARCH_DIR(/usr/local/lib); SEARCH_DIR(/usr/local/powerpc-any-elf/lib);
+
+MEMORY {
+ ram (!rx) : org = 0x00000000 , LENGTH = 8M
+ code (!rx) : org = 0x00002000 , LENGTH = (4M - 0x2000)
+ rom (rx) : org = 0xfe000000 , LENGTH = (0x100000000 - 0xfe000000)
+}
+
+SECTIONS
+{
+ _f_init = .;
+ PROVIDE(_f_init = .);
+ _f_init_rom = .;
+ PROVIDE(_f_init_rom = .);
+
+ .init : {
+ cpu/mpc8240/start.o (.text)
+ *(.init)
+ } > ram
+ _init_size = SIZEOF(.init);
+ PROVIDE(_init_size = SIZEOF(.init));
+
+ ENTRY(_start)
+
+/* _ftext = .;
+ _ftext_rom = .;
+ _text_size = SIZEOF(.text);
+ */
+ .text : {
+ *(.text)
+ *(.got1)
+ } > ram
+ .rodata : { *(.rodata) } > ram
+ .dtors : { *(.dtors) } > ram
+ .data : { *(.data) } > ram
+ .sdata : { *(.sdata) } > ram
+ .sdata2 : { *(.sdata2)
+ *(.got)
+ _GOT2_TABLE_ = .;
+ *(.got2)
+ _FIXUP_TABLE_ = .;
+ *(.fixup)
+ } > ram
+ __got2_entries = (_FIXUP_TABLE_ - _GOT2_TABLE_) >>2;
+ __fixup_entries = (. - _FIXUP_TABLE_)>>2;
+
+ .sbss : { *(.sbss) } > ram
+ .sbss2 : { *(.sbss2) } > ram
+ .bss : { *(.bss) } > ram
+ .debug : { *(.debug) } > ram
+ .line : { *(.line) } > ram
+ .symtab : { *(.symtab) } > ram
+ .shrstrtab : { *(.shstrtab) } > ram
+ .strtab : { *(.strtab) } > ram
+ /* .reloc :
+ {
+ *(.got)
+ _GOT2_TABLE_ = .;
+ *(.got2)
+ _FIXUP_TABLE_ = .;
+ *(.fixup)
+ } > ram
+ */
+ __start___ex_table = .;
+ __ex_table : { *(__ex_table) } > ram
+ __stop___ex_table = .;
+
+
+ .ppcenv :
+ {
+ common/environment.o (.ppcenv)
+ } > ram
+
+ _end = . ;
+ PROVIDE (end = .);
+}
+
--- /dev/null
+/*
+ * (C) Copyright 2000
+ * Rob Taylor, Flying Pig Systems. robt@flyingpig.com.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include "config.h"
+#include "ns16550.h"
+#include "ns87308.h"
+
+/*
+ * Minimal serial functions needed to use one87308's UARTs
+ * as serial console interface.
+ */
+
+#if (CONFIG_CONS_INDEX == 1)
+#define console (CFG_ISA_IO + COM1)
+#elif (CONFIG_CONS_INDEX == 2)
+#define console (CFG_ISA_IO + COM2)
+#else
+#error "Invalid COM port for console output (must be 1 or 2)."
+#endif
+
+void
+serial_init (unsigned long dummy, int baudrate)
+{
+ int clock_divisor = 115200/baudrate;
+
+ initialise_ns87308();
+
+ NS16550_init((NS16550_t)console, clock_divisor);
+}
+
+void
+serial_putc(const char c)
+{
+ if (c == '\n')
+ NS16550_putc((NS16550_t)console, '\r');
+
+ NS16550_putc((NS16550_t)console, c);
+}
+
+void
+serial_puts (const char *s)
+{
+ while (*s) {
+ serial_putc (*s++);
+ }
+}
+
+
+int
+serial_getc(void)
+{
+ return NS16550_getc((NS16550_t)console);
+}
+
+int
+serial_tstc(void)
+{
+ return NS16550_tstc((NS16550_t)console);
+}
+
+void
+serial_setbrg (unsigned long dummy, int baudrate)
+{
+ int clock_divisor = 115200/baudrate;
+ NS16550_reinit((NS16550_t)console, clock_divisor);
+}
--- /dev/null
+/*
+ * (C) Copyright 2000
+ * Rob Taylor, Flying Pig Systems. robt@flyingpig.com.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
--- /dev/null
+/*
+ * (C) Copyright 2000
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+/*
+ * 09-18-2001 Andreas Heppel, Sysgo RTS GmbH <aheppel@sysgo.de>
+ * We use the GPIO device on the ns87308 chip to read the bus speed
+ */
+
+#include <ppcboot.h>
+#include <asm/processor.h>
+#include "ns87308.h"
+
+
+/* Access functions for the Machine State Register */
+static __inline__ unsigned long get_msr(void)
+{
+ unsigned long msr;
+
+ asm volatile("mfmsr %0" : "=r" (msr) :);
+ return msr;
+}
+
+static __inline__ void set_msr(unsigned long msr)
+{
+ asm volatile("mtmsr %0" : : "r" (msr));
+}
+
+/* ------------------------------------------------------------------------- */
+
+ulong get_bus_freq (ulong ignore)
+{
+ /*
+ * The GPIO Port 1 on BAB750 reflects the bus speed.
+ */
+ volatile struct GPIO *gpio = (struct GPIO *)(CFG_ISA_IO + GPIO_BASE);
+
+ unsigned char data = gpio->dta1;
+
+ if (data & 0x02)
+ return 66000000;
+
+ return 83000000;
+}
+
+/* ------------------------------------------------------------------------- */
+
+
--- /dev/null
+/*
+ * (C) Copyright 2001
+ * Denis Peter, MPL AG Switzerland, d.peter@mpl.ch.
+ *
+ * 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
+ * partly derived from
+ * linux/drivers/scsi/sym53c8xx.c
+ *
+ */
+
+/*
+ * SCSI support based on the chip sym53C810.
+ *
+ * 09-19-2001 Andreas Heppel, Sysgo RTS GmbH <aheppel@sysgo.de>
+ * The local version of this driver for the BAB750 board does not
+ * use interrupts but polls the chip instead (see the call of
+ * 'handle_scsi_int()' in 'scsi_issue()'.
+ */
+
+#include <ppcboot.h>
+#include <command.h>
+#include <cmd_boot.h>
+#include <mpc106.h>
+#include <asm/processor.h>
+#include "sym53c8xx.h"
+#include <scsi.h>
+
+#undef SYM53C8XX_DEBUG
+
+#ifdef SYM53C8XX_DEBUG
+#define PRINTF(fmt,args...) printf (fmt ,##args)
+#else
+#define PRINTF(fmt,args...)
+#endif
+
+#if (CONFIG_COMMANDS & CFG_CMD_SCSI) && defined(CONFIG_SCSI_SYM53C8XX)
+
+
+#undef SCSI_SINGLE_STEP
+/*
+ * Single Step is only used for debug purposes
+ */
+#ifdef SCSI_SINGLE_STEP
+static unsigned long start_script_select;
+static unsigned long start_script_msgout;
+static unsigned long start_script_msgin;
+static unsigned long start_script_msg_ext;
+static unsigned long start_script_cmd;
+static unsigned long start_script_data_in;
+static unsigned long start_script_data_out;
+static unsigned long start_script_status;
+static unsigned long start_script_complete;
+static unsigned long start_script_error;
+static unsigned long start_script_reselection;
+static unsigned int len_script_select;
+static unsigned int len_script_msgout;
+static unsigned int len_script_msgin;
+static unsigned int len_script_msg_ext;
+static unsigned int len_script_cmd;
+static unsigned int len_script_data_in;
+static unsigned int len_script_data_out;
+static unsigned int len_script_status;
+static unsigned int len_script_complete;
+static unsigned int len_script_error;
+static unsigned int len_script_reselection;
+#endif
+
+
+static unsigned short scsi_int_mask; /* shadow register for SCSI related interrupts */
+static unsigned char script_int_mask; /* shadow register for SCRIPT related interrupts */
+static unsigned long script_select[8]; /* script for selection */
+static unsigned long script_msgout[8]; /* script for message out phase (NOT USED) */
+static unsigned long script_msgin[14]; /* script for message in phase */
+static unsigned long script_msg_ext[32]; /* script for message in phase when more than 1 byte message */
+static unsigned long script_cmd[18]; /* script for command phase */
+static unsigned long script_data_in[8]; /* script for data in phase */
+static unsigned long script_data_out[8]; /* script for data out phase */
+static unsigned long script_status[6]; /* script for status phase */
+static unsigned long script_complete[10]; /* script for complete */
+static unsigned long script_reselection[4]; /* script for reselection (NOT USED) */
+static unsigned long script_error[2]; /* script for error handling */
+
+static unsigned long int_stat[3]; /* interrupt status */
+static unsigned long scsi_mem_addr; /* base memory address =SCSI_MEM_ADDRESS; */
+
+
+#define SCSI_MAX_RETRY 3 /* number of retries in scsi_issue() */
+
+#define SCSI_MAX_RETRY_NOT_READY 10 /* number of retries when device is not ready */
+#define SCSI_NOT_READY_TIME_OUT 500 /* timeout per retry when not ready */
+
+/*********************************************************************************
+ * forward declerations
+ */
+
+void scsi_chip_init(void);
+void handle_scsi_int(void);
+
+
+/********************************************************************************
+ * reports SCSI errors to the user
+ */
+void scsi_print_error(ccb *pccb)
+{
+ int i;
+ printf("SCSI Error: Target %d LUN %d Command %02X\n",pccb->target, pccb->lun, pccb->cmd[0]);
+ printf(" CCB: ");
+ for(i=0;i<pccb->cmdlen;i++)
+ printf("%02X ",pccb->cmd[i]);
+ printf("(len=%d)\n",pccb->cmdlen);
+ printf(" Cntrl: ");
+ switch(pccb->contr_stat) {
+ case SIR_COMPLETE: printf("Complete (no Error)\n"); break;
+ case SIR_SEL_ATN_NO_MSG_OUT: printf("Selected with ATN no MSG out phase\n"); break;
+ case SIR_CMD_OUT_ILL_PH: printf("Command out illegal phase\n"); break;
+ case SIR_MSG_RECEIVED: printf("MSG received Error\n"); break;
+ case SIR_DATA_IN_ERR: printf("Data in Error\n"); break;
+ case SIR_DATA_OUT_ERR: printf("Data out Error\n"); break;
+ case SIR_SCRIPT_ERROR: printf("Script Error\n"); break;
+ case SIR_MSG_OUT_NO_CMD: printf("MSG out no Command phase\n"); break;
+ case SIR_MSG_OVER7: printf("MSG in over 7 bytes\n"); break;
+ case INT_ON_FY: printf("Interrupt on fly\n"); break;
+ case SCSI_SEL_TIME_OUT: printf("SCSI Selection Timeout\n"); break;
+ case SCSI_HNS_TIME_OUT: printf("SCSI Handshake Timeout\n"); break;
+ case SCSI_MA_TIME_OUT: printf("SCSI Phase Error\n"); break;
+ case SCSI_UNEXP_DIS: printf("SCSI unexpected disconnect\n"); break;
+ default: printf("unknown status %lx\n",pccb->contr_stat); break;
+ }
+ printf(" Sense: SK %x (",pccb->sense_buf[2]&0x0f);
+ switch(pccb->sense_buf[2]&0xf) {
+ case SENSE_NO_SENSE: printf("No Sense)"); break;
+ case SENSE_RECOVERED_ERROR: printf("Recovered Error)"); break;
+ case SENSE_NOT_READY: printf("Not Ready)"); break;
+ case SENSE_MEDIUM_ERROR: printf("Medium Error)"); break;
+ case SENSE_HARDWARE_ERROR: printf("Hardware Error)"); break;
+ case SENSE_ILLEGAL_REQUEST: printf("Illegal request)"); break;
+ case SENSE_UNIT_ATTENTION: printf("Unit Attention)"); break;
+ case SENSE_DATA_PROTECT: printf("Data Protect)"); break;
+ case SENSE_BLANK_CHECK: printf("Blank check)"); break;
+ case SENSE_VENDOR_SPECIFIC: printf("Vendor specific)"); break;
+ case SENSE_COPY_ABORTED: printf("Copy aborted)"); break;
+ case SENSE_ABORTED_COMMAND: printf("Aborted Command)"); break;
+ case SENSE_VOLUME_OVERFLOW: printf("Volume overflow)"); break;
+ case SENSE_MISCOMPARE: printf("Misscompare\n"); break;
+ default: printf("Illegal Sensecode\n"); break;
+ }
+ printf(" ASC %x ASCQ %x\n",pccb->sense_buf[12],pccb->sense_buf[13]);
+ printf(" Status: ");
+ switch(pccb->status) {
+ case S_GOOD : printf("Good\n"); break;
+ case S_CHECK_COND: printf("Check condition\n"); break;
+ case S_COND_MET: printf("Condition Met\n"); break;
+ case S_BUSY: printf("Busy\n"); break;
+ case S_INT: printf("Intermediate\n"); break;
+ case S_INT_COND_MET: printf("Intermediate condition met\n"); break;
+ case S_CONFLICT: printf("Reservation conflict\n"); break;
+ case S_TERMINATED: printf("Command terminated\n"); break;
+ case S_QUEUE_FULL: printf("Task set full\n"); break;
+ default: printf("unknown: %02X\n",pccb->status); break;
+ }
+
+}
+
+
+
+/******************************************************************************
+ * sets-up the SCSI controller
+ * the base memory address is retrived via the PCI_Read_CFG_Reg
+ */
+void scsi_low_level_init(int busdevfunc)
+{
+ unsigned long cmd;
+ unsigned long addr;
+ unsigned char vec;
+ vec=PCI_Read_CFG_Reg(busdevfunc, PCI_CFG_DEV_INT_LINE, 1);
+ addr=PCI_Read_CFG_Reg(busdevfunc, PCI_CFG_BASE_ADDRESS_1, 4);
+
+ addr |= CFG_60X_PCI_MEM_OFFSET;
+ /*
+ * Enable bus mastering in case this has not been done, yet.
+ */
+ cmd=PCI_Read_CFG_Reg(busdevfunc, PCI_CFG_COMMAND, 4);
+ cmd |= PCI_CMD_MASTER;
+ PCI_Write_CFG_Reg(busdevfunc, PCI_CFG_COMMAND, cmd, 4);
+
+ scsi_mem_addr=addr;
+ scsi_chip_init();
+ scsi_bus_reset();
+}
+
+
+/************************************************************************************
+ * Low level Part of SCSI Driver
+ */
+
+/*
+ * big-endian -> little endian conversion for the script
+ */
+unsigned long swap_script(unsigned long val)
+{
+ unsigned long tmp;
+ tmp = ((val>>24)&0xff) | ((val>>8)&0xff00) | ((val<<8)&0xff0000) | ((val<<24)&0xff000000);
+ return tmp;
+}
+
+
+void scsi_write_byte(ulong offset,unsigned char val)
+{
+ out8(scsi_mem_addr+offset,val);
+}
+
+
+unsigned char scsi_read_byte(ulong offset)
+{
+ return(in8(scsi_mem_addr+offset));
+}
+
+
+/********************************************************************************
+ * interrupt handler
+ */
+void handle_scsi_int(void)
+{
+ unsigned char stat,stat1,stat2;
+ unsigned short sstat;
+ int i;
+#ifdef SCSI_SINGLE_STEP
+ unsigned long tt;
+#endif
+ stat=scsi_read_byte(ISTAT);
+ if((stat & DIP)==DIP) { /* DMA Interrupt pending */
+ stat1=scsi_read_byte(DSTAT);
+#ifdef SCSI_SINGLE_STEP
+ if((stat1 & SSI)==SSI)
+ {
+ tt=in32r(scsi_mem_addr+DSP);
+ if(((tt)>=start_script_select) && ((tt)<start_script_select+len_script_select)) {
+ printf("select %d\n",(tt-start_script_select)>>2);
+ goto end_single;
+ }
+ if(((tt)>=start_script_msgout) && ((tt)<start_script_msgout+len_script_msgout)) {
+ printf("msgout %d\n",(tt-start_script_msgout)>>2);
+ goto end_single;
+ }
+ if(((tt)>=start_script_msgin) && ((tt)<start_script_msgin+len_script_msgin)) {
+ printf("msgin %d\n",(tt-start_script_msgin)>>2);
+ goto end_single;
+ }
+ if(((tt)>=start_script_msg_ext) && ((tt)<start_script_msg_ext+len_script_msg_ext)) {
+ printf("msgin_ext %d\n",(tt-start_script_msg_ext)>>2);
+ goto end_single;
+ }
+ if(((tt)>=start_script_cmd) && ((tt)<start_script_cmd+len_script_cmd)) {
+ printf("cmd %d\n",(tt-start_script_cmd)>>2);
+ goto end_single;
+ }
+ if(((tt)>=start_script_data_in) && ((tt)<start_script_data_in+len_script_data_in)) {
+ printf("data_in %d\n",(tt-start_script_data_in)>>2);
+ goto end_single;
+ }
+ if(((tt)>=start_script_data_out) && ((tt)<start_script_data_out+len_script_data_out)) {
+ printf("data_out %d\n",(tt-start_script_data_out)>>2);
+ goto end_single;
+ }
+ if(((tt)>=start_script_status) && ((tt)<start_script_status+len_script_status)) {
+ printf("status %d\n",(tt-start_script_status)>>2);
+ goto end_single;
+ }
+ if(((tt)>=start_script_complete) && ((tt)<start_script_complete+len_script_complete)) {
+ printf("complete %d\n",(tt-start_script_complete)>>2);
+ goto end_single;
+ }
+ if(((tt)>=start_script_error) && ((tt)<start_script_error+len_script_error)) {
+ printf("error %d\n",(tt-start_script_error)>>2);
+ goto end_single;
+ }
+ if(((tt)>=start_script_reselection) && ((tt)<start_script_reselection+len_script_reselection)) {
+ printf("reselection %d\n",(tt-start_script_reselection)>>2);
+ goto end_single;
+ }
+ printf("sc: %lx\n",tt);
+end_single:
+ stat2=scsi_read_byte(DCNTL);
+ stat2|=STD;
+ scsi_write_byte(DCNTL,stat2);
+ }
+#endif
+ if((stat1 & SIR)==SIR) /* script interrupt */
+ {
+ int_stat[0]=in32(scsi_mem_addr+DSPS);
+ }
+ if((stat1 & DFE)==0) { /* fifo not epmty */
+ scsi_write_byte(CTEST3,CLF); /* Clear DMA FIFO */
+ stat2=scsi_read_byte(STEST3);
+ scsi_write_byte(STEST3,(stat2 | CSF)); /* Clear SCSI FIFO */
+ }
+ }
+ if((stat & SIP)==SIP) { /* scsi interrupt */
+ sstat = (unsigned short)scsi_read_byte(SIST+1);
+ sstat <<=8;
+ sstat |= (unsigned short)scsi_read_byte(SIST);
+ for(i=0;i<3;i++) {
+ if(int_stat[i]==0)
+ break; /* found an empty int status */
+ }
+ int_stat[i]=SCSI_INT_STATE | sstat;
+ stat1=scsi_read_byte(DSTAT);
+ if((stat1 & DFE)==0) { /* fifo not epmty */
+ scsi_write_byte(CTEST3,CLF); /* Clear DMA FIFO */
+ stat2=scsi_read_byte(STEST3);
+ scsi_write_byte(STEST3,(stat2 | CSF)); /* Clear SCSI FIFO */
+ }
+ }
+ if((stat & INTF)==INTF) { /* interrupt on Fly */
+ scsi_write_byte(ISTAT,stat); /* clear it */
+ for(i=0;i<3;i++) {
+ if(int_stat[i]==0)
+ break; /* found an empty int status */
+ }
+ int_stat[i]=INT_ON_FY;
+ }
+}
+
+void scsi_bus_reset(void)
+{
+ unsigned char t;
+ int i;
+ int end = CFG_SCSI_SPIN_UP_TIME*1000;
+
+ t=scsi_read_byte(SCNTL1);
+ scsi_write_byte(SCNTL1,(t | CRST));
+ udelay(50);
+ scsi_write_byte(SCNTL1,t);
+
+ puts("SCSI: waiting for devices to spin up");
+ for(i=0;i<end;i++) {
+ udelay(1000); /* give the devices time to spin up */
+ if (i % 1000 == 0)
+ putc('.');
+ }
+ putc('\n');
+ scsi_chip_init(); /* reinit the chip ...*/
+
+}
+
+void scsi_int_enable(void)
+{
+ scsi_write_byte(SIEN,(unsigned char)scsi_int_mask);
+ scsi_write_byte(SIEN+1,(unsigned char)(scsi_int_mask>>8));
+ scsi_write_byte(DIEN,script_int_mask);
+}
+
+void scsi_write_dsp(unsigned long start)
+{
+ unsigned long val;
+#ifdef SCSI_SINGLE_STEP
+ unsigned char t;
+#endif
+ val = start;
+ out32r(scsi_mem_addr + DSP,start);
+#ifdef SCSI_SINGLE_STEP
+ t=scsi_read_byte(DCNTL);
+ t|=STD;
+ scsi_write_byte(DCNTL,t);
+#endif
+}
+
+/* only used for debug purposes */
+void scsi_print_script(void)
+{
+ printf("script_select @ 0x%08lX\n",(unsigned long)&script_select[0]);
+ printf("script_msgout @ 0x%08lX\n",(unsigned long)&script_msgout[0]);
+ printf("script_msgin @ 0x%08lX\n",(unsigned long)&script_msgin[0]);
+ printf("script_msgext @ 0x%08lX\n",(unsigned long)&script_msg_ext[0]);
+ printf("script_cmd @ 0x%08lX\n",(unsigned long)&script_cmd[0]);
+ printf("script_data_in @ 0x%08lX\n",(unsigned long)&script_data_in[0]);
+ printf("script_data_out @ 0x%08lX\n",(unsigned long)&script_data_out[0]);
+ printf("script_status @ 0x%08lX\n",(unsigned long)&script_status[0]);
+ printf("script_complete @ 0x%08lX\n",(unsigned long)&script_complete[0]);
+ printf("script_error @ 0x%08lX\n",(unsigned long)&script_error[0]);
+}
+
+
+
+void scsi_set_script(ccb *pccb)
+{
+ int i;
+ i=0;
+ script_select[i++]=swap_script(SCR_REG_REG(GPREG, SCR_AND, 0xfe));
+ script_select[i++]=0; /* LED ON */
+ script_select[i++]=swap_script(SCR_CLR(SCR_TRG)); /* select initiator mode */
+ script_select[i++]=0;
+ /* script_select[i++]=swap_script(SCR_SEL_ABS_ATN | pccb->target << 16); */
+ script_select[i++]=swap_script(SCR_SEL_ABS | pccb->target << 16);
+ script_select[i++]=swap_script(phys_to_bus(&script_cmd[4])); /* error handling */
+ script_select[i++]=swap_script(SCR_JUMP); /* next section */
+ /* script_select[i++]=swap_script((unsigned long)&script_msgout[0]); */ /* message out */
+ script_select[i++]=swap_script(phys_to_bus(&script_cmd[0])); /* command out */
+
+#ifdef SCSI_SINGLE_STEP
+ start_script_select=(unsigned long)&script_select[0];
+ len_script_select=i*4;
+#endif
+
+ i=0;
+ script_msgout[i++]=swap_script(SCR_INT ^ IFFALSE (WHEN (SCR_MSG_OUT)));
+ script_msgout[i++]=SIR_SEL_ATN_NO_MSG_OUT;
+ script_msgout[i++]=swap_script( SCR_MOVE_ABS(1) ^ SCR_MSG_OUT);
+ script_msgout[i++]=swap_script(phys_to_bus(&pccb->msgout[0]));
+ script_msgout[i++]=swap_script(SCR_JUMP ^ IFTRUE (WHEN (SCR_COMMAND))); /* if Command phase */
+ script_msgout[i++]=swap_script(phys_to_bus(&script_cmd[0])); /* switch to command */
+ script_msgout[i++]=swap_script(SCR_INT); /* interrupt if not */
+ script_msgout[i++]=SIR_MSG_OUT_NO_CMD;
+
+#ifdef SCSI_SINGLE_STEP
+ start_script_msgout=(unsigned long)&script_msgout[0];
+ len_script_msgout=i*4;
+#endif
+ i=0;
+ script_cmd[i++]=swap_script(SCR_MOVE_ABS(pccb->cmdlen) ^ SCR_COMMAND);
+ script_cmd[i++]=swap_script(phys_to_bus(&pccb->cmd[0]));
+ script_cmd[i++]=swap_script(SCR_JUMP ^ IFTRUE (WHEN (SCR_MSG_IN))); /* message in ? */
+ script_cmd[i++]=swap_script(phys_to_bus(&script_msgin[0]));
+ script_cmd[i++]=swap_script(SCR_JUMP ^ IFTRUE (IF (SCR_DATA_OUT))); /* data out ? */
+ script_cmd[i++]=swap_script(phys_to_bus(&script_data_out[0]));
+ script_cmd[i++]=swap_script(SCR_JUMP ^ IFTRUE (IF (SCR_DATA_IN))); /* data in ? */
+ script_cmd[i++]=swap_script(phys_to_bus(&script_data_in[0]));
+ script_cmd[i++]=swap_script(SCR_JUMP ^ IFTRUE (IF (SCR_STATUS))); /* status ? */
+ script_cmd[i++]=swap_script(phys_to_bus(&script_status[0]));
+ script_cmd[i++]=swap_script(SCR_JUMP ^ IFTRUE (IF (SCR_COMMAND))); /* command ? */
+ script_cmd[i++]=swap_script(phys_to_bus(&script_cmd[0]));
+ script_cmd[i++]=swap_script(SCR_JUMP ^ IFTRUE (IF (SCR_MSG_OUT))); /* message out ? */
+ script_cmd[i++]=swap_script(phys_to_bus(&script_msgout[0]));
+ script_cmd[i++]=swap_script(SCR_JUMP ^ IFTRUE (IF (SCR_MSG_IN))); /* just for error handling message in ? */
+ script_cmd[i++]=swap_script(phys_to_bus(&script_msgin[0]));
+ script_cmd[i++]=swap_script(SCR_INT); /* interrupt if not */
+ script_cmd[i++]=SIR_CMD_OUT_ILL_PH;
+#ifdef SCSI_SINGLE_STEP
+ start_script_cmd=(unsigned long)&script_cmd[0];
+ len_script_cmd=i*4;
+#endif
+ i=0;
+ script_data_out[i++]=swap_script(SCR_MOVE_ABS(pccb->datalen)^ SCR_DATA_OUT); /* move */
+ script_data_out[i++]=swap_script(phys_to_bus(pccb->pdata)); /* pointer to buffer */
+ script_data_out[i++]=swap_script(SCR_JUMP ^ IFTRUE (WHEN (SCR_STATUS)));
+ script_data_out[i++]=swap_script(phys_to_bus(&script_status[0]));
+ script_data_out[i++]=swap_script(SCR_INT);
+ script_data_out[i++]=SIR_DATA_OUT_ERR;
+
+#ifdef SCSI_SINGLE_STEP
+ start_script_data_out=(unsigned long)&script_data_out[0];
+ len_script_data_out=i*4;
+#endif
+ i=0;
+ script_data_in[i++]=swap_script(SCR_MOVE_ABS(pccb->datalen)^ SCR_DATA_IN); /* move */
+ script_data_in[i++]=swap_script(phys_to_bus(pccb->pdata)); /* pointer to buffer */
+ script_data_in[i++]=swap_script(SCR_JUMP ^ IFTRUE (WHEN (SCR_STATUS)));
+ script_data_in[i++]=swap_script(phys_to_bus(&script_status[0]));
+ script_data_in[i++]=swap_script(SCR_INT);
+ script_data_in[i++]=SIR_DATA_IN_ERR;
+#ifdef SCSI_SINGLE_STEP
+ start_script_data_in=(unsigned long)&script_data_in[0];
+ len_script_data_in=i*4;
+#endif
+ i=0;
+ script_msgin[i++]=swap_script(SCR_MOVE_ABS (1) ^ SCR_MSG_IN);
+ script_msgin[i++]=swap_script(phys_to_bus(&pccb->msgin[0]));
+ script_msgin[i++]=swap_script(SCR_JUMP ^ IFTRUE (DATA (M_COMPLETE)));
+ script_msgin[i++]=swap_script(phys_to_bus(&script_complete[0]));
+ script_msgin[i++]=swap_script(SCR_JUMP ^ IFTRUE (DATA (M_DISCONNECT)));
+ script_msgin[i++]=swap_script(phys_to_bus(&script_complete[0]));
+ script_msgin[i++]=swap_script(SCR_JUMP ^ IFTRUE (DATA (M_SAVE_DP)));
+ script_msgin[i++]=swap_script(phys_to_bus(&script_complete[0]));
+ script_msgin[i++]=swap_script(SCR_JUMP ^ IFTRUE (DATA (M_RESTORE_DP)));
+ script_msgin[i++]=swap_script(phys_to_bus(&script_complete[0]));
+ script_msgin[i++]=swap_script(SCR_JUMP ^ IFTRUE (DATA (M_EXTENDED)));
+ script_msgin[i++]=swap_script(phys_to_bus(&script_msg_ext[0]));
+ script_msgin[i++]=swap_script(SCR_INT);
+ script_msgin[i++]=SIR_MSG_RECEIVED;
+#ifdef SCSI_SINGLE_STEP
+ start_script_msgin=(unsigned long)&script_msgin[0];
+ len_script_msgin=i*4;
+#endif
+ i=0;
+ script_msg_ext[i++]=swap_script(SCR_CLR (SCR_ACK)); /* clear ACK */
+ script_msg_ext[i++]=0;
+ script_msg_ext[i++]=swap_script(SCR_MOVE_ABS (1) ^ SCR_MSG_IN); /* assuming this is the msg length */
+ script_msg_ext[i++]=swap_script(phys_to_bus(&pccb->msgin[1]));
+ script_msg_ext[i++]=swap_script(SCR_JUMP ^ IFFALSE (IF (SCR_MSG_IN)));
+ script_msg_ext[i++]=swap_script(phys_to_bus(&script_complete[0])); /* no more bytes */
+ script_msg_ext[i++]=swap_script(SCR_MOVE_ABS (1) ^ SCR_MSG_IN); /* next */
+ script_msg_ext[i++]=swap_script(phys_to_bus(&pccb->msgin[2]));
+ script_msg_ext[i++]=swap_script(SCR_JUMP ^ IFFALSE (IF (SCR_MSG_IN)));
+ script_msg_ext[i++]=swap_script(phys_to_bus(&script_complete[0])); /* no more bytes */
+ script_msg_ext[i++]=swap_script(SCR_MOVE_ABS (1) ^ SCR_MSG_IN); /* next */
+ script_msg_ext[i++]=swap_script(phys_to_bus(&pccb->msgin[3]));
+ script_msg_ext[i++]=swap_script(SCR_JUMP ^ IFFALSE (IF (SCR_MSG_IN)));
+ script_msg_ext[i++]=swap_script(phys_to_bus(&script_complete[0])); /* no more bytes */
+ script_msg_ext[i++]=swap_script(SCR_MOVE_ABS (1) ^ SCR_MSG_IN); /* next */
+ script_msg_ext[i++]=swap_script(phys_to_bus(&pccb->msgin[4]));
+ script_msg_ext[i++]=swap_script(SCR_JUMP ^ IFFALSE (IF (SCR_MSG_IN)));
+ script_msg_ext[i++]=swap_script(phys_to_bus(&script_complete[0])); /* no more bytes */
+ script_msg_ext[i++]=swap_script(SCR_MOVE_ABS (1) ^ SCR_MSG_IN); /* next */
+ script_msg_ext[i++]=swap_script(phys_to_bus(&pccb->msgin[5]));
+ script_msg_ext[i++]=swap_script(SCR_JUMP ^ IFFALSE (IF (SCR_MSG_IN)));
+ script_msg_ext[i++]=swap_script(phys_to_bus(&script_complete[0])); /* no more bytes */
+ script_msg_ext[i++]=swap_script(SCR_MOVE_ABS (1) ^ SCR_MSG_IN); /* next */
+ script_msg_ext[i++]=swap_script(phys_to_bus(&pccb->msgin[6]));
+ script_msg_ext[i++]=swap_script(SCR_JUMP ^ IFFALSE (IF (SCR_MSG_IN)));
+ script_msg_ext[i++]=swap_script(phys_to_bus(&script_complete[0])); /* no more bytes */
+ script_msg_ext[i++]=swap_script(SCR_MOVE_ABS (1) ^ SCR_MSG_IN); /* next */
+ script_msg_ext[i++]=swap_script(phys_to_bus(&pccb->msgin[7]));
+ script_msg_ext[i++]=swap_script(SCR_JUMP ^ IFFALSE (IF (SCR_MSG_IN)));
+ script_msg_ext[i++]=swap_script(phys_to_bus(&script_complete[0])); /* no more bytes */
+ script_msg_ext[i++]=swap_script(SCR_INT);
+ script_msg_ext[i++]=SIR_MSG_OVER7;
+#ifdef SCSI_SINGLE_STEP
+ start_script_msg_ext=(unsigned long)&script_msg_ext[0];
+ len_script_msg_ext=i*4;
+#endif
+ i=0;
+ script_status[i++]=swap_script(SCR_MOVE_ABS (1) ^ SCR_STATUS);
+ script_status[i++]=swap_script(phys_to_bus(&pccb->status));
+ script_status[i++]=swap_script(SCR_JUMP ^ IFTRUE (WHEN (SCR_MSG_IN)));
+ script_status[i++]=swap_script(phys_to_bus(&script_msgin[0]));
+ script_status[i++]=swap_script(SCR_INT);
+ script_status[i++]=SIR_STATUS_ILL_PH;
+#ifdef SCSI_SINGLE_STEP
+ start_script_status=(unsigned long)&script_status[0];
+ len_script_status=i*4;
+#endif
+ i=0;
+ script_complete[i++]=swap_script(SCR_REG_REG (SCNTL2, SCR_AND, 0x7f));
+ script_complete[i++]=0;
+ script_complete[i++]=swap_script(SCR_CLR (SCR_ACK|SCR_ATN));
+ script_complete[i++]=0;
+ script_complete[i++]=swap_script(SCR_WAIT_DISC);
+ script_complete[i++]=0;
+ script_complete[i++]=swap_script(SCR_REG_REG(GPREG, SCR_OR, 0x01));
+ script_complete[i++]=0; /* LED OFF */
+ script_complete[i++]=swap_script(SCR_INT);
+ script_complete[i++]=SIR_COMPLETE;
+#ifdef SCSI_SINGLE_STEP
+ start_script_complete=(unsigned long)&script_complete[0];
+ len_script_complete=i*4;
+#endif
+ i=0;
+ script_error[i++]=swap_script(SCR_INT); /* interrupt if error */
+ script_error[i++]=SIR_SCRIPT_ERROR;
+#ifdef SCSI_SINGLE_STEP
+ start_script_error=(unsigned long)&script_error[0];
+ len_script_error=i*4;
+#endif
+ i=0;
+ script_reselection[i++]=swap_script(SCR_CLR (SCR_TRG)); /* target status */
+ script_reselection[i++]=0;
+ script_reselection[i++]=swap_script(SCR_WAIT_RESEL);
+ script_reselection[i++]=swap_script(phys_to_bus(&script_select[0])); /* len = 4 */
+#ifdef SCSI_SINGLE_STEP
+ start_script_reselection=(unsigned long)&script_reselection[0];
+ len_script_reselection=i*4;
+#endif
+}
+
+
+
+void scsi_issue(ccb *pccb)
+{
+ int i;
+ unsigned short sstat;
+ int retrycnt; /* retry counter */
+ for(i=0;i<3;i++)
+ int_stat[i]=0; /* delete all int status */
+ /* struct pccb must be set-up correctly */
+ retrycnt=0;
+ PRINTF("ID %d issue cmd %02X\n",pccb->target,pccb->cmd[0]);
+ pccb->trans_bytes=0; /* no bytes transfered yet */
+ scsi_set_script(pccb); /* fill in SCRIPT */
+ scsi_int_mask=STO | UDC | MA; /* | CMP; / * Interrupts which are enabled */
+ script_int_mask=0xff; /* enable all Ints */
+ scsi_int_enable();
+ scsi_write_dsp(phys_to_bus(&script_select[0])); /* start script */
+ /* now we have to wait for IRQs */
+retry:
+ /*
+ * This version of the driver is _not_ interrupt driven,
+ * but polls the chip's interrupt registers (ISTAT, DSTAT).
+ */
+ while(int_stat[0]==0)
+ handle_scsi_int();
+
+ if(int_stat[0]==SIR_COMPLETE) {
+ if(pccb->msgin[0]==M_DISCONNECT) {
+ PRINTF("Wait for reselection\n");
+ for(i=0;i<3;i++)
+ int_stat[i]=0; /* delete all int status */
+ scsi_write_dsp(phys_to_bus(&script_reselection[0])); /* start reselection script */
+ goto retry;
+ }
+ pccb->contr_stat=SIR_COMPLETE;
+ return;
+ }
+ if((int_stat[0] & SCSI_INT_STATE)==SCSI_INT_STATE) { /* scsi interrupt */
+ sstat=(unsigned short)int_stat[0];
+ if((sstat & STO)==STO) { /* selection timeout */
+ pccb->contr_stat=SCSI_SEL_TIME_OUT;
+ scsi_write_byte(GPREG,0x01);
+ PRINTF("ID: %X Selection Timeout\n",pccb->target);
+ return;
+ }
+ if((sstat & UDC)==UDC) { /* unexpected disconnect */
+ pccb->contr_stat=SCSI_UNEXP_DIS;
+ scsi_write_byte(GPREG,0x01);
+ PRINTF("ID: %X Unexpected Disconnect\n",pccb->target);
+ return;
+ }
+ if((sstat & RSL)==RSL) { /* reselection */
+ pccb->contr_stat=SCSI_UNEXP_DIS;
+ scsi_write_byte(GPREG,0x01);
+ PRINTF("ID: %X Unexpected Disconnect\n",pccb->target);
+ return;
+ }
+ if(((sstat & MA)==MA)||((sstat & HTH)==HTH)) { /* phase missmatch */
+ if(retrycnt<SCSI_MAX_RETRY) {
+ pccb->trans_bytes=pccb->datalen -
+ ((unsigned long)scsi_read_byte(DBC) |
+ ((unsigned long)scsi_read_byte(DBC+1)<<8) |
+ ((unsigned long)scsi_read_byte(DBC+2)<<16));
+ for(i=0;i<3;i++)
+ int_stat[i]=0; /* delete all int status */
+ retrycnt++;
+ PRINTF("ID: %X Phase Missmatch Retry %d Phase %02X transfered %lx\n",
+ pccb->target,retrycnt,scsi_read_byte(SBCL),pccb->trans_bytes);
+ scsi_write_dsp(phys_to_bus(&script_cmd[4])); /* start retry script */
+ goto retry;
+ }
+ if((sstat & MA)==MA)
+ pccb->contr_stat=SCSI_MA_TIME_OUT;
+ else
+ pccb->contr_stat=SCSI_HNS_TIME_OUT;
+ PRINTF("Phase Missmatch stat %lx\n",pccb->contr_stat);
+ return;
+ } /* no phase int */
+/* if((sstat & CMP)==CMP) {
+ pccb->contr_stat=SIR_COMPLETE;
+ return;
+ }
+*/
+ PRINTF("SCSI INT %lX\n",int_stat[0]);
+ pccb->contr_stat=int_stat[0];
+ return;
+ } /* end scsi int */
+ PRINTF("SCRIPT INT %lX phase %02X\n",int_stat[0],scsi_read_byte(SBCL));
+ pccb->contr_stat=int_stat[0];
+ return;
+}
+
+int scsi_exec(ccb *pccb)
+{
+ unsigned char tmpcmd[16],tmpstat;
+ int i,retrycnt,t;
+ unsigned long transbytes,datalen;
+ unsigned char *tmpptr;
+ retrycnt=0;
+retry:
+ scsi_issue(pccb);
+ if(pccb->contr_stat!=SIR_COMPLETE)
+ return FALSE;
+ if(pccb->status==S_GOOD)
+ return TRUE;
+ if(pccb->status==S_CHECK_COND) { /* check condition */
+ for(i=0;i<16;i++)
+ tmpcmd[i]=pccb->cmd[i];
+ pccb->cmd[0]=SCSI_REQ_SENSE;
+ pccb->cmd[1]=pccb->lun<<5;
+ pccb->cmd[2]=0;
+ pccb->cmd[3]=0;
+ pccb->cmd[4]=14;
+ pccb->cmd[5]=0;
+ pccb->cmdlen=6;
+ pccb->msgout[0]=SCSI_IDENTIFY;
+ transbytes=pccb->trans_bytes;
+ tmpptr=pccb->pdata;
+ pccb->pdata=&pccb->sense_buf[0];
+ datalen=pccb->datalen;
+ pccb->datalen=14;
+ tmpstat=pccb->status;
+ scsi_issue(pccb);
+ for(i=0;i<16;i++)
+ pccb->cmd[i]=tmpcmd[i];
+ pccb->trans_bytes=transbytes;
+ pccb->pdata=tmpptr;
+ pccb->datalen=datalen;
+ pccb->status=tmpstat;
+ PRINTF("Request_sense sense key %x ASC %x ASCQ %x\n",pccb->sense_buf[2]&0x0f,
+ pccb->sense_buf[12],pccb->sense_buf[13]);
+ switch(pccb->sense_buf[2]&0xf) {
+ case SENSE_NO_SENSE:
+ case SENSE_RECOVERED_ERROR:
+ /* seems to be ok */
+ return TRUE;
+ break;
+ case SENSE_NOT_READY:
+ if((pccb->sense_buf[12]!=0x04)||(pccb->sense_buf[13]!=0x01)) {
+ /* if device is not in process of becoming ready */
+ return FALSE;
+ break;
+ } /* else fall through */
+ case SENSE_UNIT_ATTENTION:
+ if(retrycnt<SCSI_MAX_RETRY_NOT_READY) {
+ PRINTF("Target %d not ready, retry %d\n",pccb->target,retrycnt);
+ for(t=0;t<SCSI_NOT_READY_TIME_OUT;t++)
+ udelay(1000); /* 1sec wait */
+ retrycnt++;
+ goto retry;
+ }
+ PRINTF("Target %d not ready, %d retried\n",pccb->target,retrycnt);
+ return FALSE;
+ default:
+ return FALSE;
+ }
+ }
+ PRINTF("Status = %X\n",pccb->status);
+ return FALSE;
+}
+
+
+
+
+void scsi_chip_init(void)
+{
+ /* first we issue a soft reset */
+ scsi_write_byte(ISTAT,SRST);
+ udelay(1000);
+ scsi_write_byte(ISTAT,0);
+ /* setup chip */
+ scsi_write_byte(SCNTL0,0xC0); /* full arbitration no start, no message, parity disabled, master */
+ scsi_write_byte(SCNTL1,0x00);
+ scsi_write_byte(SCNTL2,0x00);
+ scsi_write_byte(SCNTL3,0x13); /* synchronous clock 40/4=10MHz, asynchronous 40MHz */
+ scsi_write_byte(SCID,0x47); /* ID=7, enable reselection */
+ scsi_write_byte(SXFER,0x00); /* synchronous transfer period 10MHz, asynchronous */
+ scsi_write_byte(SDID,0x00); /* targed SCSI ID = 0 */
+ scsi_int_mask=0x0000; /* no Interrupt is enabled */
+ script_int_mask=0x00;
+ scsi_int_enable();
+ scsi_write_byte(GPREG,0x01); /* GPIO0 is LED (off) */
+ scsi_write_byte(GPCNTL,0x0E); /* GPIO0 is Output */
+ scsi_write_byte(STIME0,0x08); /* handshake timer disabled, selection timeout 512msec */
+ scsi_write_byte(RESPID,0x80); /* repond only to the own ID (reselection) */
+ scsi_write_byte(STEST1,0x00); /* not isolated, SCLK is used */
+ scsi_write_byte(STEST2,0x00); /* no Lowlevel Mode? */
+ scsi_write_byte(STEST3,0x80); /* enable tolerANT */
+ scsi_write_byte(CTEST3,0x04); /* clear FIFO */
+ scsi_write_byte(CTEST4,0x00);
+ scsi_write_byte(CTEST5,0x00);
+#ifdef SCSI_SINGLE_STEP
+/* scsi_write_byte(DCNTL,IRQM | SSM); */
+ scsi_write_byte(DCNTL,IRQD | SSM);
+ scsi_write_byte(DMODE,MAN);
+#else
+/* scsi_write_byte(DCNTL,IRQM); */
+ scsi_write_byte(DCNTL,IRQD);
+ scsi_write_byte(DMODE,0x00);
+#endif
+}
+#endif /* (CONFIG_COMMANDS & CFG_CMD_SCSI) */
+
+
--- /dev/null
+/*
+ * (C) Copyright 2001
+ * Denis Peter, MPL AG Switzerland
+ *
+ * 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
+ *
+ *
+ * Most of these definitions are derived from
+ * linux/drivers/scsi/sym53c8xx_defs.h
+ *
+ */
+
+#ifndef _SYM53C8XX_DEFS_H
+#define _SYM53C8XX_DEFS_H
+
+
+#define SCNTL0 0x00 /* full arb., ena parity, par->ATN */
+
+#define SCNTL1 0x01 /* no reset */
+ #define ISCON 0x10 /* connected to scsi */
+ #define CRST 0x08 /* force reset */
+ #define IARB 0x02 /* immediate arbitration */
+
+#define SCNTL2 0x02 /* no disconnect expected */
+ #define SDU 0x80 /* cmd: disconnect will raise error */
+ #define CHM 0x40 /* sta: chained mode */
+ #define WSS 0x08 /* sta: wide scsi send [W]*/
+ #define WSR 0x01 /* sta: wide scsi received [W]*/
+
+#define SCNTL3 0x03 /* cnf system clock dependent */
+ #define EWS 0x08 /* cmd: enable wide scsi [W]*/
+ #define ULTRA 0x80 /* cmd: ULTRA enable */
+ /* bits 0-2, 7 rsvd for C1010 */
+
+#define SCID 0x04 /* cnf host adapter scsi address */
+ #define RRE 0x40 /* r/w:e enable response to resel. */
+ #define SRE 0x20 /* r/w:e enable response to select */
+
+#define SXFER 0x05 /* ### Sync speed and count */
+ /* bits 6-7 rsvd for C1010 */
+
+#define SDID 0x06 /* ### Destination-ID */
+
+#define GPREG 0x07 /* ??? IO-Pins */
+
+#define SFBR 0x08 /* ### First byte in phase */
+
+#define SOCL 0x09
+ #define CREQ 0x80 /* r/w: SCSI-REQ */
+ #define CACK 0x40 /* r/w: SCSI-ACK */
+ #define CBSY 0x20 /* r/w: SCSI-BSY */
+ #define CSEL 0x10 /* r/w: SCSI-SEL */
+ #define CATN 0x08 /* r/w: SCSI-ATN */
+ #define CMSG 0x04 /* r/w: SCSI-MSG */
+ #define CC_D 0x02 /* r/w: SCSI-C_D */
+ #define CI_O 0x01 /* r/w: SCSI-I_O */
+
+#define SSID 0x0a
+
+#define SBCL 0x0b
+
+#define DSTAT 0x0c
+ #define DFE 0x80 /* sta: dma fifo empty */
+ #define MDPE 0x40 /* int: master data parity error */
+ #define BF 0x20 /* int: script: bus fault */
+ #define ABRT 0x10 /* int: script: command aborted */
+ #define SSI 0x08 /* int: script: single step */
+ #define SIR 0x04 /* int: script: interrupt instruct. */
+ #define IID 0x01 /* int: script: illegal instruct. */
+
+#define SSTAT0 0x0d
+ #define ILF 0x80 /* sta: data in SIDL register lsb */
+ #define ORF 0x40 /* sta: data in SODR register lsb */
+ #define OLF 0x20 /* sta: data in SODL register lsb */
+ #define AIP 0x10 /* sta: arbitration in progress */
+ #define LOA 0x08 /* sta: arbitration lost */
+ #define WOA 0x04 /* sta: arbitration won */
+ #define IRST 0x02 /* sta: scsi reset signal */
+ #define SDP 0x01 /* sta: scsi parity signal */
+
+#define SSTAT1 0x0e
+ #define FF3210 0xf0 /* sta: bytes in the scsi fifo */
+
+#define SSTAT2 0x0f
+ #define ILF1 0x80 /* sta: data in SIDL register msb[W]*/
+ #define ORF1 0x40 /* sta: data in SODR register msb[W]*/
+ #define OLF1 0x20 /* sta: data in SODL register msb[W]*/
+ #define DM 0x04 /* sta: DIFFSENS mismatch (895/6 only) */
+ #define LDSC 0x02 /* sta: disconnect & reconnect */
+
+#define DSA 0x10 /* --> Base page */
+#define DSA1 0x11
+#define DSA2 0x12
+#define DSA3 0x13
+
+#define ISTAT 0x14 /* --> Main Command and status */
+ #define CABRT 0x80 /* cmd: abort current operation */
+ #define SRST 0x40 /* mod: reset chip */
+ #define SIGP 0x20 /* r/w: message from host to ncr */
+ #define SEM 0x10 /* r/w: message between host + ncr */
+ #define CON 0x08 /* sta: connected to scsi */
+ #define INTF 0x04 /* sta: int on the fly (reset by wr)*/
+ #define SIP 0x02 /* sta: scsi-interrupt */
+ #define DIP 0x01 /* sta: host/script interrupt */
+
+
+#define CTEST0 0x18
+#define CTEST1 0x19
+#define CTEST2 0x1a
+ #define CSIGP 0x40
+ /* bits 0-2,7 rsvd for C1010 */
+
+#define CTEST3 0x1b
+ #define FLF 0x08 /* cmd: flush dma fifo */
+ #define CLF 0x04 /* cmd: clear dma fifo */
+ #define FM 0x02 /* mod: fetch pin mode */
+ #define WRIE 0x01 /* mod: write and invalidate enable */
+ /* bits 4-7 rsvd for C1010 */
+
+#define DFIFO 0x20
+#define CTEST4 0x21
+ #define BDIS 0x80 /* mod: burst disable */
+ #define MPEE 0x08 /* mod: master parity error enable */
+
+#define CTEST5 0x22
+ #define DFS 0x20 /* mod: dma fifo size */
+ /* bits 0-1, 3-7 rsvd for C1010 */
+#define CTEST6 0x23
+
+#define DBC 0x24 /* ### Byte count and command */
+#define DNAD 0x28 /* ### Next command register */
+#define DSP 0x2c /* --> Script Pointer */
+#define DSPS 0x30 /* --> Script pointer save/opcode#2 */
+
+#define SCRATCHA 0x34 /* Temporary register a */
+#define SCRATCHA1 0x35
+#define SCRATCHA2 0x36
+#define SCRATCHA3 0x37
+
+#define DMODE 0x38
+ #define BL_2 0x80 /* mod: burst length shift value +2 */
+ #define BL_1 0x40 /* mod: burst length shift value +1 */
+ #define ERL 0x08 /* mod: enable read line */
+ #define ERMP 0x04 /* mod: enable read multiple */
+ #define BOF 0x02 /* mod: burst op code fetch */
+ #define MAN 0x01 /* mod: manual start */
+
+#define DIEN 0x39
+#define SBR 0x3a
+
+#define DCNTL 0x3b /* --> Script execution control */
+ #define CLSE 0x80 /* mod: cache line size enable */
+ #define PFF 0x40 /* cmd: pre-fetch flush */
+ #define PFEN 0x20 /* mod: pre-fetch enable */
+ #define SSM 0x10 /* mod: single step mode */
+ #define IRQM 0x08 /* mod: irq mode (1 = totem pole !) */
+ #define STD 0x04 /* cmd: start dma mode */
+ #define IRQD 0x02 /* mod: irq disable */
+ #define NOCOM 0x01 /* cmd: protect sfbr while reselect */
+ /* bits 0-1 rsvd for C1010 */
+
+#define ADDER 0x3c
+
+#define SIEN 0x40 /* -->: interrupt enable */
+#define SIST 0x42 /* <--: interrupt status */
+ #define SBMC 0x1000/* sta: SCSI Bus Mode Change (895/6 only) */
+ #define STO 0x0400/* sta: timeout (select) */
+ #define GEN 0x0200/* sta: timeout (general) */
+ #define HTH 0x0100/* sta: timeout (handshake) */
+ #define MA 0x80 /* sta: phase mismatch */
+ #define CMP 0x40 /* sta: arbitration complete */
+ #define SEL 0x20 /* sta: selected by another device */
+ #define RSL 0x10 /* sta: reselected by another device*/
+ #define SGE 0x08 /* sta: gross error (over/underflow)*/
+ #define UDC 0x04 /* sta: unexpected disconnect */
+ #define RST 0x02 /* sta: scsi bus reset detected */
+ #define PAR 0x01 /* sta: scsi parity error */
+
+#define SLPAR 0x44
+#define SWIDE 0x45
+#define MACNTL 0x46
+#define GPCNTL 0x47
+#define STIME0 0x48 /* cmd: timeout for select&handshake*/
+#define STIME1 0x49 /* cmd: timeout user defined */
+#define RESPID 0x4a /* sta: Reselect-IDs */
+
+#define STEST0 0x4c
+
+#define STEST1 0x4d
+ #define SCLK 0x80 /* Use the PCI clock as SCSI clock */
+ #define DBLEN 0x08 /* clock doubler running */
+ #define DBLSEL 0x04 /* clock doubler selected */
+
+
+#define STEST2 0x4e
+ #define ROF 0x40 /* reset scsi offset (after gross error!) */
+ #define EXT 0x02 /* extended filtering */
+
+#define STEST3 0x4f
+ #define TE 0x80 /* c: tolerAnt enable */
+ #define HSC 0x20 /* c: Halt SCSI Clock */
+ #define CSF 0x02 /* c: clear scsi fifo */
+
+#define SIDL 0x50 /* Lowlevel: latched from scsi data */
+#define STEST4 0x52
+ #define SMODE 0xc0 /* SCSI bus mode (895/6 only) */
+ #define SMODE_HVD 0x40 /* High Voltage Differential */
+ #define SMODE_SE 0x80 /* Single Ended */
+ #define SMODE_LVD 0xc0 /* Low Voltage Differential */
+ #define LCKFRQ 0x20 /* Frequency Lock (895/6 only) */
+ /* bits 0-5 rsvd for C1010 */
+
+#define SODL 0x54 /* Lowlevel: data out to scsi data */
+
+#define SBDL 0x58 /* Lowlevel: data from scsi data */
+
+
+
+
+/*-----------------------------------------------------------
+**
+** Utility macros for the script.
+**
+**-----------------------------------------------------------
+*/
+
+#define REG(r) (r)
+
+/*-----------------------------------------------------------
+**
+** SCSI phases
+**
+** DT phases illegal for ncr driver.
+**
+**-----------------------------------------------------------
+*/
+
+#define SCR_DATA_OUT 0x00000000
+#define SCR_DATA_IN 0x01000000
+#define SCR_COMMAND 0x02000000
+#define SCR_STATUS 0x03000000
+#define SCR_DT_DATA_OUT 0x04000000
+#define SCR_DT_DATA_IN 0x05000000
+#define SCR_MSG_OUT 0x06000000
+#define SCR_MSG_IN 0x07000000
+
+#define SCR_ILG_OUT 0x04000000
+#define SCR_ILG_IN 0x05000000
+
+/*-----------------------------------------------------------
+**
+** Data transfer via SCSI.
+**
+**-----------------------------------------------------------
+**
+** MOVE_ABS (LEN)
+** <<start address>>
+**
+** MOVE_IND (LEN)
+** <<dnad_offset>>
+**
+** MOVE_TBL
+** <<dnad_offset>>
+**
+**-----------------------------------------------------------
+*/
+
+#define OPC_MOVE 0x08000000
+
+#define SCR_MOVE_ABS(l) ((0x00000000 | OPC_MOVE) | (l))
+#define SCR_MOVE_IND(l) ((0x20000000 | OPC_MOVE) | (l))
+#define SCR_MOVE_TBL (0x10000000 | OPC_MOVE)
+
+#define SCR_CHMOV_ABS(l) ((0x00000000) | (l))
+#define SCR_CHMOV_IND(l) ((0x20000000) | (l))
+#define SCR_CHMOV_TBL (0x10000000)
+
+
+/*-----------------------------------------------------------
+**
+** Selection
+**
+**-----------------------------------------------------------
+**
+** SEL_ABS | SCR_ID (0..15) [ | REL_JMP]
+** <<alternate_address>>
+**
+** SEL_TBL | << dnad_offset>> [ | REL_JMP]
+** <<alternate_address>>
+**
+**-----------------------------------------------------------
+*/
+
+#define SCR_SEL_ABS 0x40000000
+#define SCR_SEL_ABS_ATN 0x41000000
+#define SCR_SEL_TBL 0x42000000
+#define SCR_SEL_TBL_ATN 0x43000000
+
+
+#define SCR_JMP_REL 0x04000000
+#define SCR_ID(id) (((unsigned long)(id)) << 16)
+
+/*-----------------------------------------------------------
+**
+** Waiting for Disconnect or Reselect
+**
+**-----------------------------------------------------------
+**
+** WAIT_DISC
+** dummy: <<alternate_address>>
+**
+** WAIT_RESEL
+** <<alternate_address>>
+**
+**-----------------------------------------------------------
+*/
+
+#define SCR_WAIT_DISC 0x48000000
+#define SCR_WAIT_RESEL 0x50000000
+
+/*-----------------------------------------------------------
+**
+** Bit Set / Reset
+**
+**-----------------------------------------------------------
+**
+** SET (flags {|.. })
+**
+** CLR (flags {|.. })
+**
+**-----------------------------------------------------------
+*/
+
+#define SCR_SET(f) (0x58000000 | (f))
+#define SCR_CLR(f) (0x60000000 | (f))
+
+#define SCR_CARRY 0x00000400
+#define SCR_TRG 0x00000200
+#define SCR_ACK 0x00000040
+#define SCR_ATN 0x00000008
+
+
+
+
+/*-----------------------------------------------------------
+**
+** Memory to memory move
+**
+**-----------------------------------------------------------
+**
+** COPY (bytecount)
+** << source_address >>
+** << destination_address >>
+**
+** SCR_COPY sets the NO FLUSH option by default.
+** SCR_COPY_F does not set this option.
+**
+** For chips which do not support this option,
+** ncr_copy_and_bind() will remove this bit.
+**-----------------------------------------------------------
+*/
+
+#define SCR_NO_FLUSH 0x01000000
+
+#define SCR_COPY(n) (0xc0000000 | SCR_NO_FLUSH | (n))
+#define SCR_COPY_F(n) (0xc0000000 | (n))
+
+/*-----------------------------------------------------------
+**
+** Register move and binary operations
+**
+**-----------------------------------------------------------
+**
+** SFBR_REG (reg, op, data) reg = SFBR op data
+** << 0 >>
+**
+** REG_SFBR (reg, op, data) SFBR = reg op data
+** << 0 >>
+**
+** REG_REG (reg, op, data) reg = reg op data
+** << 0 >>
+**
+**-----------------------------------------------------------
+** On 810A, 860, 825A, 875, 895 and 896 chips the content
+** of SFBR register can be used as data (SCR_SFBR_DATA).
+** The 896 has additionnal IO registers starting at
+** offset 0x80. Bit 7 of register offset is stored in
+** bit 7 of the SCRIPTS instruction first DWORD.
+**-----------------------------------------------------------
+*/
+
+#define SCR_REG_OFS(ofs) ((((ofs) & 0x7f) << 16ul)) /* + ((ofs) & 0x80)) */
+
+#define SCR_SFBR_REG(reg,op,data) \
+ (0x68000000 | (SCR_REG_OFS(REG(reg))) | (op) | (((data)&0xff)<<8ul))
+
+#define SCR_REG_SFBR(reg,op,data) \
+ (0x70000000 | (SCR_REG_OFS(REG(reg))) | (op) | (((data)&0xff)<<8ul))
+
+#define SCR_REG_REG(reg,op,data) \
+ (0x78000000 | (SCR_REG_OFS(REG(reg))) | (op) | (((data)&0xff)<<8ul))
+
+
+#define SCR_LOAD 0x00000000
+#define SCR_SHL 0x01000000
+#define SCR_OR 0x02000000
+#define SCR_XOR 0x03000000
+#define SCR_AND 0x04000000
+#define SCR_SHR 0x05000000
+#define SCR_ADD 0x06000000
+#define SCR_ADDC 0x07000000
+
+#define SCR_SFBR_DATA (0x00800000>>8ul) /* Use SFBR as data */
+
+/*-----------------------------------------------------------
+**
+** FROM_REG (reg) SFBR = reg
+** << 0 >>
+**
+** TO_REG (reg) reg = SFBR
+** << 0 >>
+**
+** LOAD_REG (reg, data) reg = <data>
+** << 0 >>
+**
+** LOAD_SFBR(data) SFBR = <data>
+** << 0 >>
+**
+**-----------------------------------------------------------
+*/
+
+#define SCR_FROM_REG(reg) \
+ SCR_REG_SFBR(reg,SCR_OR,0)
+
+#define SCR_TO_REG(reg) \
+ SCR_SFBR_REG(reg,SCR_OR,0)
+
+#define SCR_LOAD_REG(reg,data) \
+ SCR_REG_REG(reg,SCR_LOAD,data)
+
+#define SCR_LOAD_SFBR(data) \
+ (SCR_REG_SFBR (gpreg, SCR_LOAD, data))
+
+/*-----------------------------------------------------------
+**
+** LOAD from memory to register.
+** STORE from register to memory.
+**
+** Only supported by 810A, 860, 825A, 875, 895 and 896.
+**
+**-----------------------------------------------------------
+**
+** LOAD_ABS (LEN)
+** <<start address>>
+**
+** LOAD_REL (LEN) (DSA relative)
+** <<dsa_offset>>
+**
+**-----------------------------------------------------------
+*/
+
+#define SCR_REG_OFS2(ofs) (((ofs) & 0xff) << 16ul)
+#define SCR_NO_FLUSH2 0x02000000
+#define SCR_DSA_REL2 0x10000000
+
+#define SCR_LOAD_R(reg, how, n) \
+ (0xe1000000 | how | (SCR_REG_OFS2(REG(reg))) | (n))
+
+#define SCR_STORE_R(reg, how, n) \
+ (0xe0000000 | how | (SCR_REG_OFS2(REG(reg))) | (n))
+
+#define SCR_LOAD_ABS(reg, n) SCR_LOAD_R(reg, SCR_NO_FLUSH2, n)
+#define SCR_LOAD_REL(reg, n) SCR_LOAD_R(reg, SCR_NO_FLUSH2|SCR_DSA_REL2, n)
+#define SCR_LOAD_ABS_F(reg, n) SCR_LOAD_R(reg, 0, n)
+#define SCR_LOAD_REL_F(reg, n) SCR_LOAD_R(reg, SCR_DSA_REL2, n)
+
+#define SCR_STORE_ABS(reg, n) SCR_STORE_R(reg, SCR_NO_FLUSH2, n)
+#define SCR_STORE_REL(reg, n) SCR_STORE_R(reg, SCR_NO_FLUSH2|SCR_DSA_REL2,n)
+#define SCR_STORE_ABS_F(reg, n) SCR_STORE_R(reg, 0, n)
+#define SCR_STORE_REL_F(reg, n) SCR_STORE_R(reg, SCR_DSA_REL2, n)
+
+
+/*-----------------------------------------------------------
+**
+** Waiting for Disconnect or Reselect
+**
+**-----------------------------------------------------------
+**
+** JUMP [ | IFTRUE/IFFALSE ( ... ) ]
+** <<address>>
+**
+** JUMPR [ | IFTRUE/IFFALSE ( ... ) ]
+** <<distance>>
+**
+** CALL [ | IFTRUE/IFFALSE ( ... ) ]
+** <<address>>
+**
+** CALLR [ | IFTRUE/IFFALSE ( ... ) ]
+** <<distance>>
+**
+** RETURN [ | IFTRUE/IFFALSE ( ... ) ]
+** <<dummy>>
+**
+** INT [ | IFTRUE/IFFALSE ( ... ) ]
+** <<ident>>
+**
+** INT_FLY [ | IFTRUE/IFFALSE ( ... ) ]
+** <<ident>>
+**
+** Conditions:
+** WHEN (phase)
+** IF (phase)
+** CARRYSET
+** DATA (data, mask)
+**
+**-----------------------------------------------------------
+*/
+
+#define SCR_NO_OP 0x80000000
+#define SCR_JUMP 0x80080000
+#define SCR_JUMP64 0x80480000
+#define SCR_JUMPR 0x80880000
+#define SCR_CALL 0x88080000
+#define SCR_CALLR 0x88880000
+#define SCR_RETURN 0x90080000
+#define SCR_INT 0x98080000
+#define SCR_INT_FLY 0x98180000
+
+#define IFFALSE(arg) (0x00080000 | (arg))
+#define IFTRUE(arg) (0x00000000 | (arg))
+
+#define WHEN(phase) (0x00030000 | (phase))
+#define IF(phase) (0x00020000 | (phase))
+
+#define DATA(D) (0x00040000 | ((D) & 0xff))
+#define MASK(D,M) (0x00040000 | (((M ^ 0xff) & 0xff) << 8ul)|((D) & 0xff))
+
+#define CARRYSET (0x00200000)
+
+
+
+#define SIR_COMPLETE 0x10000000
+/* script errors */
+#define SIR_SEL_ATN_NO_MSG_OUT 0x00000001
+#define SIR_CMD_OUT_ILL_PH 0x00000002
+#define SIR_STATUS_ILL_PH 0x00000003
+#define SIR_MSG_RECEIVED 0x00000004
+#define SIR_DATA_IN_ERR 0x00000005
+#define SIR_DATA_OUT_ERR 0x00000006
+#define SIR_SCRIPT_ERROR 0x00000007
+#define SIR_MSG_OUT_NO_CMD 0x00000008
+#define SIR_MSG_OVER7 0x00000009
+/* Fly interrupt */
+#define INT_ON_FY 0x00000080
+
+/* Hardware errors are defined in scsi.h */
+
+#define SCSI_IDENTIFY 0xC0
+
+#ifndef TRUE
+#define TRUE 1
+#endif
+#ifndef FALSE
+#define FALSE 0
+#endif
+
+#endif
--- /dev/null
+/*
+ * (C) Copyright 2001 Sysgo Real-Time Solutions, GmbH <www.elinos.com>
+ * Andreas Heppel <aheppel@sysgo.de>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+/*
+ * Initialisation of the PCI-to-ISA bridge and disabling the BIOS
+ * write protection (for flash) in function 0 of the chip.
+ * Enabling function 1 (IDE controller of the chip.
+ */
+
+#include <ppcboot.h>
+#include <config.h>
+#include <mpc106.h>
+
+#include <w83c553f.h>
+
+#define EIEIO_SYNC __asm__ volatile ("eieio;sync")
+
+ulong bus_offset[CFG_IDE_MAXBUS];
+
+void initialise_pic(void);
+void initialise_dma(void);
+
+void initialise_w83c553f(void)
+{
+ int regval = 0;
+ int devbusfn = 0;
+
+ devbusfn = PCI_Find_Device(W83C553F_VID, W83C553F_DID);
+ if (devbusfn == -1)
+ {
+ printf("Error: Cannot find W83C553F controller on any PCI bus.");
+ return;
+ }
+
+ regval = PCI_Read_CFG_Reg(devbusfn, PCI_CFG_COMMAND, 2);
+ regval |= PCI_CMD_MASTER | PCI_CMD_IOEN | PCI_CMD_MEMEN;
+ PCI_Write_CFG_Reg(devbusfn, PCI_CFG_COMMAND, regval, 2);
+
+ regval = PCI_Read_CFG_Reg(devbusfn, WINBOND_IPADCR, 1);
+ /* 16 MB ISA memory space */
+ regval |= (IPADCR_IPATOM4 | IPADCR_IPATOM5 | IPADCR_IPATOM6 | IPADCR_IPATOM7);
+ regval &= ~IPADCR_MBE512;
+ PCI_Write_CFG_Reg(devbusfn, WINBOND_IPADCR, regval, 1);
+
+ regval = PCI_Read_CFG_Reg(devbusfn, WINBOND_CSCR, 1);
+ /* switch off BIOS write protection */
+ regval |= CSCR_UBIOSCSE;
+ regval &= ~CSCR_BIOSWP;
+ PCI_Write_CFG_Reg(devbusfn, WINBOND_CSCR, regval, 1);
+
+ /*
+ * Interrupt routing:
+ * - IDE -> IRQ 9/0
+ * - INTA -> IRQ 10
+ * - INTB -> IRQ 11
+ * - INTC -> IRQ 14
+ * - INTD -> IRQ 15
+ */
+ PCI_Write_CFG_Reg(devbusfn, WINBOND_IDEIRCR, 0x90, 1);
+ PCI_Write_CFG_Reg(devbusfn, WINBOND_PCIIRCR, 0xABEF, 2);
+
+ /*
+ * Read IDE bus offsets from function 1 device.
+ * We must unmask the LSB indicating that ist is an IO address.
+ */
+ devbusfn |= (1<<8);
+
+ /*
+ * Switch off legacy IRQ for IDE and IDE port 1.
+ */
+ PCI_Write_CFG_Reg(devbusfn, 0x09, 0x8F, 1);
+
+ regval = PCI_Read_CFG_Reg(devbusfn, WINDOND_IDECSR, 4);
+ regval &= ~(IDECSR_LEGIRQ | IDECSR_P1EN | IDECSR_P1F16);
+ PCI_Write_CFG_Reg(devbusfn, WINDOND_IDECSR, regval, 4);
+
+ bus_offset[0] = PCI_Read_CFG_Reg(devbusfn, PCI_CFG_BASE_ADDRESS_0, 4) & ~1;
+#if CFG_IDE_MAXBUS > 1
+ bus_offset[1] = PCI_Read_CFG_Reg(devbusfn, PCI_CFG_BASE_ADDRESS_2, 4) & ~1;
+#endif
+
+ /*
+ * Enable function 1, IDE -> busmastering and IO space access
+ */
+ regval = PCI_Read_CFG_Reg(devbusfn, PCI_CFG_COMMAND, 2);
+ regval |= PCI_CMD_MASTER | PCI_CMD_IOEN;
+ PCI_Write_CFG_Reg(devbusfn, PCI_CFG_COMMAND, regval, 2);
+
+ /*
+ * Initialise ISA interrupt controller
+ */
+ initialise_pic();
+
+ /*
+ * Initialise DMA controller
+ */
+ initialise_dma();
+}
+
+void initialise_pic(void)
+{
+ out8(W83C553F_PIC1_ICW1, 0x11);
+ out8(W83C553F_PIC1_ICW2, 0x08);
+ out8(W83C553F_PIC1_ICW3, 0x04);
+ out8(W83C553F_PIC1_ICW4, 0x01);
+ out8(W83C553F_PIC1_OCW1, 0xfb);
+ out8(W83C553F_PIC1_ELC, 0x20);
+
+ out8(W83C553F_PIC2_ICW1, 0x11);
+ out8(W83C553F_PIC2_ICW2, 0x08);
+ out8(W83C553F_PIC2_ICW3, 0x02);
+ out8(W83C553F_PIC2_ICW4, 0x01);
+ out8(W83C553F_PIC2_OCW1, 0xff);
+ out8(W83C553F_PIC2_ELC, 0xce);
+
+ out8(W83C553F_TMR1_CMOD, 0x74);
+
+ out8(W83C553F_PIC2_OCW1, 0x20);
+ out8(W83C553F_PIC1_OCW1, 0x20);
+
+ out8(W83C553F_PIC2_OCW1, 0x2b);
+ out8(W83C553F_PIC1_OCW1, 0x2b);
+}
+
+void initialise_dma(void)
+{
+ unsigned int channel;
+ unsigned int rvalue1, rvalue2;
+
+ /* perform a H/W reset of the devices */
+
+ out8(W83C553F_DMA1 + W83C553F_DMA1_MC, 0x00);
+ out16(W83C553F_DMA2 + W83C553F_DMA2_MC, 0x0000);
+
+ /* initialise all channels to a sane state */
+
+ for (channel = 0; channel < 4; channel++) {
+ /*
+ * dependent upon the channel, setup the specifics:
+ *
+ * demand
+ * address-increment
+ * autoinitialize-disable
+ * verify-transfer
+ */
+
+ switch (channel) {
+ case 0:
+ rvalue1 = (W83C553F_MODE_TM_DEMAND|W83C553F_MODE_CH0SEL|W83C553F_MODE_TT_VERIFY);
+ rvalue2 = (W83C553F_MODE_TM_CASCADE|W83C553F_MODE_CH0SEL);
+ break;
+ case 1:
+ rvalue1 = (W83C553F_MODE_TM_DEMAND|W83C553F_MODE_CH1SEL|W83C553F_MODE_TT_VERIFY);
+ rvalue2 = (W83C553F_MODE_TM_DEMAND|W83C553F_MODE_CH1SEL|W83C553F_MODE_TT_VERIFY);
+ break;
+ case 2:
+ rvalue1 = (W83C553F_MODE_TM_DEMAND|W83C553F_MODE_CH2SEL|W83C553F_MODE_TT_VERIFY);
+ rvalue2 = (W83C553F_MODE_TM_DEMAND|W83C553F_MODE_CH2SEL|W83C553F_MODE_TT_VERIFY);
+ break;
+ case 3:
+ rvalue1 = (W83C553F_MODE_TM_DEMAND|W83C553F_MODE_CH3SEL|W83C553F_MODE_TT_VERIFY);
+ rvalue2 = (W83C553F_MODE_TM_DEMAND|W83C553F_MODE_CH3SEL|W83C553F_MODE_TT_VERIFY);
+ break;
+ default:
+ rvalue1 = 0x00;
+ rvalue2 = 0x00;
+ break;
+ }
+
+ /* write to write mode registers */
+
+ out8(W83C553F_DMA1 + W83C553F_DMA1_WM, rvalue1 & 0xFF);
+ out16(W83C553F_DMA2 + W83C553F_DMA2_WM, rvalue2 & 0x00FF);
+ }
+
+ /* enable all channels */
+
+ out8(W83C553F_DMA1 + W83C553F_DMA1_CM, 0x00);
+ out16(W83C553F_DMA2 + W83C553F_DMA2_CM, 0x0000);
+ /*
+ * initialize the global DMA configuration
+ *
+ * DACK# active low
+ * DREQ active high
+ * fixed priority
+ * channel group enable
+ */
+
+ out8(W83C553F_DMA1 + W83C553F_DMA1_CS, 0x00);
+ out16(W83C553F_DMA2 + W83C553F_DMA2_CS, 0x0000);
+}
+
#include <commproc.h>
#endif
#include <version.h>
+#if defined(CONFIG_BAB750)
+#include <w83c553f.h>
+#endif
#undef DEBUG
icache_enable(); /* it's time to enable the instruction cache */
#endif
+#if defined(CONFIG_BAB750)
+ /*
+ * Do pci configuration on BAB 750 _before_ the flash
+ * is initialised, because we need the ISA bridge there.
+ */
+ pci_init(bd);
+ /*
+ * Initialise the ISA bridge
+ */
+ initialise_w83c553f();
+#endif
+
asm ("sync ; isync");
/*
watchdog_reset ();
#endif /* CONFIG_WATCHDOG */
-#ifdef CONFIG_PCI
+#if defined(CONFIG_PCI) && !defined(CONFIG_BAB750)
/*
* Do pci configuration
*/
/* Current offset for IDE0 / IDE1 bus access */
static ulong bus_offset[CFG_IDE_MAXBUS] = {
+#if defined(CFG_ATA_IDE0_OFFSET)
CFG_ATA_IDE0_OFFSET,
-#if CFG_IDE_MAXBUS > 1
+#endif
+#if defined(CFG_ATA_IDE1_OFFSET) && (CFG_IDE_MAXBUS > 1)
CFG_ATA_IDE1_OFFSET,
#endif
};
* (C) Copyright 2000
* Wolfgang Denk, DENX Software Engineering, wd@denx.de.
*
+ * (C) Copyright 2001 Sysgo Real-Time Solutions, GmbH <www.elinos.com>
+ * Andreas Heppel <aheppel@sysgo.de>
+
* See file CREDITS for list of people who contributed to this
* project.
*
/*
* Support for persistent environment data
*/
+
+/*
+ * 09-18-2001 Andreas Heppel, Sysgo RTS GmbH <aheppel@sysgo.de>
+ *
+ * It might not be possible in all cases to use 'memcpy()' to copy
+ * the environment to NVRAM, as the NVRAM might not be mapped into
+ * the memory space. (I.e. this is the case for the BAB750). In those
+ * cases it might be possible to access the NVRAM using a different
+ * method. For example, the RTC on the BAB750 is accessible in IO
+ * space using its address and data registers. To enable usage of
+ * NVRAM in those cases I invented the functions 'nvram_read()' and
+ * 'nvram_write()', which will be activated upon the configuration
+ * #define CFG_NVRAM_ACCESS_ROUTINE. Note, that those functions are
+ * strongly dependent on the used HW, and must be redefined for each
+ * board that wants to use them.
+ */
+
#include <ppcboot.h>
#include <command.h>
#include <cmd_nvedit.h>
/*--- NVRAM ----------------------------------------------------------*/
#ifdef CFG_ENV_IS_IN_NVRAM /* Environment is in NVRAM */
+#ifdef CFG_NVRAM_ACCESS_ROUTINE
+
+static env_t *env_ptr = NULL;
+void *nvram_read(void *dest, const short src, size_t count);
+void nvram_write(short dest, const void *src, size_t count);
+
+#else
+
static env_t *env_ptr = (env_t *)CFG_ENV_ADDR;
+#endif
+
/*--- EEPROM ----------------------------------------------------------*/
#elif defined(CFG_ENV_IS_IN_EEPROM) /* Environment is in EEPROM */
static env_t *env_ptr = NULL;
#ifdef CFG_ENV_IS_IN_EEPROM
static uchar get_env_char_eeprom(int);
#endif
+#if defined(CFG_ENV_IS_IN_NVRAM) && defined(CFG_NVRAM_ACCESS_ROUTINE)
+static uchar get_env_char_nvram(int);
+#endif
static uchar get_env_char_memory(int);
static uchar *get_env_addr_memory(int);
static uchar (*get_env_char)(int) =
#ifdef CFG_ENV_IS_IN_EEPROM
get_env_char_eeprom;
+#elif defined(CFG_ENV_IS_IN_NVRAM) && defined(CFG_NVRAM_ACCESS_ROUTINE)
+ get_env_char_nvram;
#else
get_env_char_memory;
#endif
eeprom_read (CFG_ENV_OFFSET+offsetof(env_t,data),
env_ptr->data,
ENV_SIZE);
+#elif defined(CFG_ENV_IS_IN_NVRAM) && defined(CFG_NVRAM_ACCESS_ROUTINE)
+ DEBUGF ("%s[%d] read ENV from NVRAM\n", __FUNCTION__,__LINE__);
+ nvram_read(env_ptr->data,
+ CFG_ENV_ADDR + sizeof(long),
+ ENV_SIZE);
# else
DEBUGF ("%s[%d] read ENV from NVRAM/FLASH\n",__FUNCTION__,__LINE__);
memcpy (env_ptr->data,
}
}
+#if defined(CFG_ENV_IS_IN_NVRAM) && defined(CFG_NVRAM_ACCESS_ROUTINE)
+static uchar get_env_char_nvram(int index)
+{
+ uchar c;
+ init_data_t *idata = (init_data_t*)(CFG_INIT_RAM_ADDR+CFG_INIT_DATA_OFFSET);
+
+ /* if the NVRAM crc was bad, use the default environment */
+ if (idata->env_valid)
+ nvram_read(&c, CFG_ENV_ADDR+index, 1);
+ else
+ c = default_environment[index];
+
+ return c;
+}
+#endif
+
#ifdef CFG_ENV_IS_IN_EEPROM
/*
* Utility function when we have to read from serial device
{
int rcode = 0;
printf ("Saving Environment to NVRAM...\n");
+
+#ifdef CFG_NVRAM_ACCESS_ROUTINE
+ nvram_write((short)CFG_ENV_ADDR, env_ptr, CFG_ENV_SIZE);
+ rcode = 0;
+#else
if (memcpy ((char *)CFG_ENV_ADDR, env_ptr, CFG_ENV_SIZE) == NULL)
rcode = 1 ;
+#endif
return rcode;
}
* We are still running from ROM, so data use is limited
*/
#ifndef CFG_ENV_IS_IN_EEPROM
+
+#if defined(CFG_ENV_IS_IN_NVRAM) && defined(CFG_NVRAM_ACCESS_ROUTINE)
+
+void env_init(init_data_t *idata)
+{
+ ulong crc;
+ uchar data[ENV_SIZE];
+ nvram_read (&crc, CFG_ENV_ADDR, sizeof(ulong));
+ nvram_read (data, CFG_ENV_ADDR+sizeof(ulong), ENV_SIZE);
+
+ if (crc32(0, data, ENV_SIZE) == crc) {
+ idata->env_addr = (ulong)CFG_ENV_ADDR + sizeof(long);
+ idata->env_valid = 1;
+ } else {
+ idata->env_addr = (ulong)&default_environment[0];
+ idata->env_valid = 0;
+ }
+}
+#else
void env_init(init_data_t *idata)
{
if (crc32(0, env_ptr->data, ENV_SIZE) == env_ptr->crc) {
idata->env_valid = 0;
}
}
+#endif /* defined(CFG_ENV_IS_IN_NVRAM) && defined(CFG_NVRAM_ACCESS_ROUTINE) */
+
#else /* CFG_ENV_IS_IN_EEPROM */
/*
* Use a (moderately small) buffer on the stack
--- /dev/null
+#
+# (C) Copyright 2001
+# Josh Huber <huber@mclx.com>, Mission Critical Linux, 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 $(TOPDIR)/config.mk
+
+LIB = lib$(CPU).a
+
+START = start.o kgdb.o
+OBJS = traps.o cpu.o cpu_init.o speed.o interrupts.o
+
+all: .depend $(START) $(LIB)
+
+$(LIB): $(OBJS)
+ $(AR) crv $@ $(OBJS) kgdb.o start.o
+
+#########################################################################
+
+.depend: Makefile $(START:.o=.S) $(OBJS:.o=.c)
+ $(CC) -M $(CFLAGS) $(START:.o=.S) $(OBJS:.o=.c) > $@
+
+sinclude .depend
+
+#########################################################################
--- /dev/null
+#
+# (C) Copyright 2001
+# Josh Huber <huber@mclx.com>, Mission Critical Linux, 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
+#
+
+PLATFORM_RELFLAGS += -mrelocatable -ffixed-r14
+
+PLATFORM_CPPFLAGS += -DCONFIG_75x -ffixed-r2 -mstring
--- /dev/null
+/*
+ * (C) Copyright 2001 Sysgo Real-Time Solutions, GmbH <www.elinos.com>
+ * Andreas Heppel <aheppel@sysgo.de>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+/*
+ * cpu.c
+ *
+ * CPU specific code
+ *
+ * written or collected and sometimes rewritten by
+ * Magnus Damm <damm@bitsmart.com>
+ *
+ * minor modifications by
+ * Wolfgang Denk <wd@denx.de>
+ *
+ * more minor modifications by
+ * Andreas Heppel <aheppel@sysgo.de>
+ */
+
+#include <ppcboot.h>
+#include <mpc75x.h>
+#include <asm/cache.h>
+#include <config.h>
+
+#if !defined(CONFIG_74x) && !defined(CONFIG_75x) && !defined(CONFIG_74xx)
+#error CPU undefined
+#endif
+
+int
+checkcpu(long clock)
+{
+ uint pvr = get_pvr(); /* processor version register */
+
+ switch (PVR_VER(pvr)) {
+ case 0x0008:
+ puts("PPC74x/75x ");
+ break;
+
+ case 0x000c:
+ puts("PPC7400 ");
+ break;
+
+ default:
+ puts("Unknown CPU -- configuration error!\n");
+ return -1;
+ break;
+ }
+
+ printf("v%d.%d at %ld / %ld MHz\n", (pvr >> 8) & 0xFF, pvr & 0xFF, clock/1000000, get_bus_freq(0)/1000000);
+
+ return 0;
+}
+
+/* these two functions are unimplemented currently [josh] */
+
+/* ------------------------------------------------------------------------- */
+/* L1 i-cache */
+
+int
+checkicache(void)
+{
+ return 0; /* XXX */
+}
+
+/* ------------------------------------------------------------------------- */
+/* L1 d-cache */
+
+int
+checkdcache(void)
+{
+ return 0; /* XXX */
+}
+
+/* ------------------------------------------------------------------------- */
+
+/*
+ * For the 603 the TB clock runs at 1/4 the cpu bus speed.
+ */
+unsigned long
+get_tbclk (void)
+{
+ return get_bus_freq(0) / 4;
+}
+
+/* ------------------------------------------------------------------------- */
+
+/*
+ * The MPC7xx/74xx CPUs do not have an internal watchdog and also do not have
+ * any possibility to reset on check stop. If any of those features is to be
+ * used, there must be a board specific solution. Thus, the functions do_reset()
+ * and watchdog_reset() are not implemented here, but in the board's main file.
+ */
+
+/*void
+do_reset (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
+{
+}
+*/
+
+/* ------------------------------------------------------------------------- */
+
+/*#if defined(CONFIG_WATCHDOG)
+void
+watchdog_reset(void)
+{
+}
+#endif
+*/
+
+/* ------------------------------------------------------------------------- */
--- /dev/null
+/*
+ * (C) Copyright 2001 Sysgo Real-Time Solutions, GmbH <www.elinos.com>
+ * Andreas Heppel <aheppel@sysgo.de>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+/*
+ * cpu_init.c - low level cpu init
+ */
+
+#include <ppcboot.h>
+#include <mpc75x.h>
+
+/*
+ * Breath some life into the CPU...
+ *
+ * there's basically nothing to do here since the memory controller
+ * isn't on the CPU in this case.
+ */
+
+void l2_enable(void);
+
+void
+cpu_init_f (void)
+{
+}
+
+/*
+ * initialize higher level parts of CPU like timers and L2 cache
+ */
+void
+cpu_init_r (bd_t *bd)
+{
+#if defined(CFG_L2) && (defined(CONFIG_75x) || defined(CONFIG_74xx))
+ l2_enable();
+#endif
+}
--- /dev/null
+/*
+ * (C) Copyright 2001
+ * Josh Huber <huber@mclx.com>, Mission Critical Linux, 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
+ */
+
+/*
+ * interrupts.c - just enough support for the decrementer/timer
+ */
+
+#include <ppcboot.h>
+#include <asm/processor.h>
+#include <commproc.h>
+#include <command.h>
+
+/*#define DEBUG */
+
+/****************************************************************************/
+
+unsigned decrementer_count; /* count value for 1e6/HZ microseconds */
+
+/****************************************************************************/
+
+static __inline__ unsigned long
+get_msr(void)
+{
+ unsigned long msr;
+
+ asm volatile("mfmsr %0" : "=r" (msr) :);
+ return msr;
+}
+
+static __inline__ void
+set_msr(unsigned long msr)
+{
+ asm volatile("mtmsr %0" : : "r" (msr));
+}
+
+static __inline__ unsigned long
+get_dec(void)
+{
+ unsigned long val;
+
+ asm volatile("mfdec %0" : "=r" (val) :);
+ return val;
+}
+
+
+static __inline__ void
+set_dec(unsigned long val)
+{
+ asm volatile("mtdec %0" : : "r" (val));
+}
+
+
+void
+enable_interrupts(void)
+{
+/* set_msr (get_msr() | MSR_EE);*/
+}
+
+/* returns flag if MSR_EE was set before */
+int
+disable_interrupts(void)
+{
+ ulong msr = get_msr();
+ set_msr (msr & ~MSR_EE);
+ return ((msr & MSR_EE) != 0);
+}
+
+/****************************************************************************/
+
+void
+interrupt_init(bd_t *bd)
+{
+ decrementer_count = get_tbclk() / CFG_HZ;
+
+ set_dec (decrementer_count);
+
+ enable_interrupts();
+}
+
+/****************************************************************************/
+
+/*
+ * Handle external interrupts
+ */
+void
+external_interrupt(struct pt_regs *regs)
+{
+ puts("external_interrupt (oops!)\n");
+}
+
+volatile ulong timestamp = 0;
+
+/*
+ * timer_interrupt - gets called when the decrementer overflows,
+ * with interrupts disabled.
+ * Trivial implementation - no need to be really accurate.
+ */
+void
+timer_interrupt(struct pt_regs *regs)
+{
+ set_dec(decrementer_count);
+ timestamp++;
+}
+
+/****************************************************************************/
+
+void
+reset_timer(void)
+{
+ timestamp = 0;
+}
+
+ulong
+get_timer(ulong base)
+{
+ return (timestamp - base);
+}
+
+void
+set_timer(ulong t)
+{
+ timestamp = t;
+}
+
+/****************************************************************************/
+
+/*
+ * Install and free a interrupt handler.
+ */
+
+void
+irq_install_handler(int vec, interrupt_handler_t *handler, void *arg)
+{
+
+}
+
+void
+irq_free_handler(int vec)
+{
+
+}
+
+/****************************************************************************/
+
+void
+do_irqinfo(cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
+{
+ puts("IRQ related functions are unimplemented currently.\n");
+}
--- /dev/null
+/*
+ * Copyright (C) 2000 Murray Jensen <Murray.Jensen@cmst.csiro.au>
+ *
+ * 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-1307USA
+ */
+
+/* note - this won't work with the 74xx cpus. needs more work [josh] */
+
+#include <config.h>
+#include <command.h>
+#include <mpc75x.h>
+#include "version.h"
+
+#include <ppc_asm.tmpl>
+#include <ppc_defs.h>
+
+#include <asm/cache.h>
+#include <asm/mmu.h>
+
+#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
+
+ /*
+ * cache flushing routines for kgdb
+ */
+
+ .globl kgdb_flush_cache_all
+kgdb_flush_cache_all:
+ lis r3, IDC_INVALL@h
+ mtspr DC_CST, r3
+ sync
+ lis r3, IDC_INVALL@h
+ mtspr IC_CST, r3
+ SYNC
+ blr
+
+ .globl kgdb_flush_cache_range
+kgdb_flush_cache_range:
+ li r5,CFG_CACHELINE_SIZE-1
+ andc r3,r3,r5
+ subf r4,r3,r4
+ add r4,r4,r5
+ srwi. r4,r4,CFG_CACHELINE_SHIFT
+ beqlr
+ mtctr r4
+ mr r6,r3
+1: dcbst 0,r3
+ addi r3,r3,CFG_CACHELINE_SIZE
+ bdnz 1b
+ sync /* wait for dcbst's to get to ram */
+ mtctr r4
+2: icbi 0,r6
+ addi r6,r6,CFG_CACHELINE_SIZE
+ bdnz 2b
+ SYNC
+ blr
+
+#endif /* CFG_CMD_KGDB */
--- /dev/null
+/*
+ * (C) Copyright 2000
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <ppcboot.h>
+#include <mpc75x.h>
+#include <asm/processor.h>
+
+/*
+ * 7xx CPU specific modifications by
+ * Andreas Heppel <aheppel@sysgo.de>
+ */
+
+
+/* Access functions for the Machine State Register */
+static __inline__ unsigned long
+get_msr(void)
+{
+ unsigned long msr;
+
+ asm volatile("mfmsr %0" : "=r" (msr) :);
+ return msr;
+}
+
+static __inline__ void
+set_msr(unsigned long msr)
+{
+ asm volatile("mtmsr %0" : : "r" (msr));
+}
+
+/* ------------------------------------------------------------------------- */
+
+/*
+ * Measure CPU clock speed (core clock GCLK1)
+ *
+ * (Approx. GCLK frequency in Hz)
+ */
+short pllratio_to_factor[] = {
+ 00, 75, 70, 00, 20, 65, 100, 45, 30, 55, 40, 50, 80, 60, 35, 00,
+};
+
+ulong
+get_gclk_freq (void)
+{
+ uint hid1 = mfspr(HID1);
+
+ hid1 = (hid1 >> (32-4)) & 0xf;
+
+ return (pllratio_to_factor[hid1] * get_bus_freq(0)) / 10;
+}
+
+/* ------------------------------------------------------------------------- */
+
--- /dev/null
+/*
+ * Copyright (C) 1998 Dan Malek <dmalek@jlc.net>
+ * Copyright (C) 1999 Magnus Damm <kieraypc01.p.y.kie.era.ericsson.se>
+ * Copyright (C) 2000 Wolfgang Denk <wd@denx.de>
+ * Copyright (C) 2001 Sysgo Real-Time Solutions, GmbH <www.elinos.com>
+ * Andreas Heppel <aheppel@sysgo.de>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+/* ppcboot - Startup Code for PowerPC based Embedded Boards
+ *
+ *
+ * The processor starts at 0xfff00100 and the code is executed
+ * from flash. The code is organized to be at an other address
+ * in memory, but as long we don't jump around before relocating.
+ * board_init lies at a quite high address and when the cpu has
+ * jumped there, everything is ok.
+ */
+
+/* Although this file was originally dvelopped for the MPC750 CPU,
+ * it should be possible to use it for MPC740/MPC7400 CPUs as well
+ * since there are anly small differences in the basic operation.
+ * However, the code has been tested with an MPC750 CPU only.
+ */
+
+#include <config.h>
+#include <mpc75x.h>
+#include "version.h"
+
+#include <ppc_asm.tmpl>
+#include <ppc_defs.h>
+
+#include <asm/cache.h>
+#include <asm/mmu.h>
+
+#ifndef CONFIG_IDENT_STRING
+#define CONFIG_IDENT_STRING ""
+#endif
+
+/* We don't want the MMU yet.
+*/
+#undef MSR_KERNEL
+/* Machine Check and Recoverable Interr. */
+#define MSR_KERNEL ( MSR_ME | MSR_RI )
+
+
+/*
+ * Set up GOT: Global Offset Table
+ *
+ * Use r14 to access the GOT
+ */
+ START_GOT
+ GOT_ENTRY(_GOT2_TABLE_)
+ GOT_ENTRY(_FIXUP_TABLE_)
+
+ GOT_ENTRY(_start)
+ GOT_ENTRY(_start_of_vectors)
+ GOT_ENTRY(_end_of_vectors)
+ GOT_ENTRY(transfer_to_handler)
+
+ GOT_ENTRY(MessageBlock)
+/* GOT_ENTRY(spdRead)*/
+ GOT_ENTRY(_end)
+ GOT_ENTRY(.bss)
+ END_GOT
+
+/*
+ * r3 - 1st arg to board_init(): IMMP pointer
+ * r4 - 2nd arg to board_init(): boot flag
+ */
+ .text
+ .long 0x27051956 /* PPCBOOT Magic Number */
+
+ .globl version_string
+version_string:
+ .ascii PPCBOOT_VERSION
+ .ascii " (", __DATE__, " - ", __TIME__, ")"
+ .ascii CONFIG_IDENT_STRING, "\0"
+
+ . = EXC_OFF_SYS_RESET
+ .globl _start
+_start:
+ li r21, BOOTFLAG_COLD /* Normal Power-On: Boot from FLASH */
+ b boot_cold
+
+ . = EXC_OFF_SYS_RESET + 0x10
+
+ .globl _start_warm
+_start_warm:
+ li r21, BOOTFLAG_WARM /* Software reboot */
+ b boot_warm
+
+ /* the boot code is located below the exception table */
+
+ .globl _start_of_vectors
+_start_of_vectors:
+
+/* Machine check */
+ STD_EXCEPTION(0x200, MachineCheck, MachineCheckException)
+
+/* Data Storage exception. "Never" generated on the 860. */
+ STD_EXCEPTION(0x300, DataStorage, UnknownException)
+
+/* Instruction Storage exception. "Never" generated on the 860. */
+ STD_EXCEPTION(0x400, InstStorage, UnknownException)
+
+/* External Interrupt exception. */
+ STD_EXCEPTION(0x500, ExtInterrupt, external_interrupt)
+
+/* Alignment exception. */
+ . = 0x600
+Alignment:
+ EXCEPTION_PROLOG
+ mfspr r4,DAR
+ stw r4,_DAR(r21)
+ mfspr r5,DSISR
+ stw r5,_DSISR(r21)
+ addi r3,r1,STACK_FRAME_OVERHEAD
+ li r20,MSR_KERNEL
+ rlwimi r20,r23,0,16,16 /* copy EE bit from saved MSR */
+ lwz r6,GOT(transfer_to_handler)
+ mtlr r6
+ blrl
+.L_Alignment:
+ .long AlignmentException - _start + EXC_OFF_SYS_RESET
+ .long int_return - _start + EXC_OFF_SYS_RESET
+
+/* Program check exception */
+ . = 0x700
+ProgramCheck:
+ EXCEPTION_PROLOG
+ addi r3,r1,STACK_FRAME_OVERHEAD
+ li r20,MSR_KERNEL
+ rlwimi r20,r23,0,16,16 /* copy EE bit from saved MSR */
+ lwz r6,GOT(transfer_to_handler)
+ mtlr r6
+ blrl
+.L_ProgramCheck:
+ .long ProgramCheckException - _start + EXC_OFF_SYS_RESET
+ .long int_return - _start + EXC_OFF_SYS_RESET
+
+ /* No FPU on MPC8xx. This exception is not supposed to happen.
+ */
+ STD_EXCEPTION(0x800, FPUnavailable, UnknownException)
+
+ /* I guess we could implement decrementer, and may have
+ * to someday for timekeeping.
+ */
+ STD_EXCEPTION(0x900, Decrementer, timer_interrupt)
+ STD_EXCEPTION(0xa00, Trap_0a, UnknownException)
+ STD_EXCEPTION(0xb00, Trap_0b, UnknownException)
+
+ STD_EXCEPTION(0xc00, SystemCall, UnknownException)
+ STD_EXCEPTION(0xd00, SingleStep, UnknownException)
+
+ STD_EXCEPTION(0xe00, Trap_0e, UnknownException)
+ STD_EXCEPTION(0xf00, Trap_0f, UnknownException)
+
+ /* On the MPC8xx, this is a software emulation interrupt. It occurs
+ * for all unimplemented and illegal instructions.
+ */
+ STD_EXCEPTION(0x1000, SoftEmu, SoftEmuException)
+
+ STD_EXCEPTION(0x1100, InstructionTLBMiss, UnknownException)
+ STD_EXCEPTION(0x1200, DataTLBMiss, UnknownException)
+ STD_EXCEPTION(0x1300, InstructionTLBError, UnknownException)
+ STD_EXCEPTION(0x1400, DataTLBError, UnknownException)
+
+ STD_EXCEPTION(0x1500, Reserved5, UnknownException)
+ STD_EXCEPTION(0x1600, Reserved6, UnknownException)
+ STD_EXCEPTION(0x1700, Reserved7, UnknownException)
+ STD_EXCEPTION(0x1800, Reserved8, UnknownException)
+ STD_EXCEPTION(0x1900, Reserved9, UnknownException)
+ STD_EXCEPTION(0x1a00, ReservedA, UnknownException)
+ STD_EXCEPTION(0x1b00, ReservedB, UnknownException)
+
+ STD_EXCEPTION(0x1c00, DataBreakpoint, UnknownException)
+ STD_EXCEPTION(0x1d00, InstructionBreakpoint, UnknownException)
+ STD_EXCEPTION(0x1e00, PeripheralBreakpoint, UnknownException)
+ STD_EXCEPTION(0x1f00, DevPortBreakpoint, UnknownException)
+
+ /* PPC documentation says that the vector table ends at 0x3000 */
+ .globl _end_of_vectors
+_end_of_vectors:
+
+ . = 0x3000
+
+boot_cold:
+boot_warm:
+ /* disable everything */
+ li r0, 0
+
+ /* hardware imlementation register */
+ mtspr HID0, r0
+ sync
+ mtmsr 0
+
+ /* invalidate BATs */
+ mtspr IBAT0U, r0
+ mtspr IBAT1U, r0
+ mtspr IBAT2U, r0
+ mtspr IBAT3U, r0
+ isync
+ mtspr DBAT0U, r0
+ mtspr DBAT1U, r0
+ mtspr DBAT2U, r0
+ mtspr DBAT3U, r0
+ isync
+
+ /* Turn off data and instruction cache control bits */
+ mfspr r3, HID0
+ isync
+ rlwinm r4, r3, 0, 18, 15
+ sync
+ isync
+ mtspr HID0, r4
+ isync
+
+ /* invalidate the MPU's data/instruction caches */
+ ori r3, r3, 0xCC00
+ or r4, r4, r3
+ isync
+ mtspr HID0, r4
+ andc r4, r4, r3
+ isync
+ mtspr HID0, r4
+ isync
+
+ ori r4, r4, 0x8800
+
+ /*
+ * The setting of the instruction cache enable (ICE) bit must be
+ * preceded by an isync instruction to prevent the cache from being
+ * enabled or disabled while an instruction access is in progress.
+ */
+ isync
+
+ mtspr HID0, r4
+ isync
+
+#if defined(CFG_L2) && (defined(CONFIG_75x) || defined(CONFIG_74xx))
+ /* init the L2 cache */
+ addis r3, r0, L2_INIT@h
+ ori r3, r3, L2_INIT@l
+ mtspr l2cr, r3
+
+ /* invalidate the L2 cache */
+ sync
+ oris r3, r3, L2CR_L2I@h
+ mtspr l2cr, r3
+ sync
+
+invl2:
+ mfspr r3, l2cr
+ andi. r3, r3, L2CR_L2IP
+ bne invl2
+
+ /* turn off the global invalidate bit */
+ mfspr r3, l2cr
+ rlwinm r3, r3, 0, 11, 9
+ mtspr l2cr, r3
+#endif
+
+ /* setup the bats */
+ bl setup_bats
+ sync
+
+#if CFG_MMU
+ /*enable address translation */
+ bl enable_addr_trans
+ sync
+#endif
+
+ /*
+ * Calculate absolute address in FLASH and jump there
+ *------------------------------------------------------*/
+ lis r3, CFG_MONITOR_BASE@h
+ ori r3, r3, CFG_MONITOR_BASE@l
+ addi r3, r3, in_flash - _start + EXC_OFF_SYS_RESET
+ mtlr r3
+ blr
+
+in_flash:
+ /* let the C-code set up the rest */
+ /* */
+ /* Be careful to keep code relocatable ! */
+ /*------------------------------------------------------*/
+
+ GET_GOT /* initialize GOT access */
+
+ /*
+ * Change the address map if this is configured
+ */
+ bl set_address_map
+
+ /*
+ * Since the 7xx/7xxx CPUs do not have any RAM on chip
+ * we cannot wait to initialise the RAM during board_init_f.
+ * We need some RAM before we can run C code.
+ */
+ bl ram_init
+
+ /* set up r1 (SP) */
+ lis r1,CFG_INIT_RAM_ADDR@h
+ ori r1,r1,CFG_INIT_SP_OFFSET /* set up the stack in SDRAM */
+ stwu r1, -8(r1) /* make room for stack frame header */
+
+ /* run low-level CPU init code (from Flash) */
+ bl cpu_init_f
+
+ /* r3: BOOTFLAG */
+ mr r3, r21
+ /* run 1st part of board init code (from Flash) */
+ bl board_init_f
+
+ /* NOTREACHED */
+
+ /* setup_bats - set them up to some initial state */
+ .globl setup_bats
+setup_bats:
+
+ /*
+ * We need the bats only, if we use the MMU, otherwise they may remain
+ * invalidated
+ */
+#ifdef CFG_MMU
+ addis r0, r0, 0x0000
+
+ /* IBAT 0 */
+ addis r4, r0, CFG_IBAT0L@h
+ ori r4, r4, CFG_IBAT0L@l
+ addis r3, r0, CFG_IBAT0U@h
+ ori r3, r3, CFG_IBAT0U@l
+ mtspr IBAT0L, r4
+ mtspr IBAT0U, r3
+ isync
+
+ /* DBAT 0 */
+ addis r4, r0, CFG_DBAT0L@h
+ ori r4, r4, CFG_DBAT0L@l
+ addis r3, r0, CFG_DBAT0U@h
+ ori r3, r3, CFG_DBAT0U@l
+ mtspr DBAT0L, r4
+ mtspr DBAT0U, r3
+ isync
+
+ /* IBAT 1 */
+ addis r4, r0, CFG_IBAT1L@h
+ ori r4, r4, CFG_IBAT1L@l
+ addis r3, r0, CFG_IBAT1U@h
+ ori r3, r3, CFG_IBAT1U@l
+ mtspr IBAT1L, r4
+ mtspr IBAT1U, r3
+ isync
+
+ /* DBAT 1 */
+ addis r4, r0, CFG_DBAT1L@h
+ ori r4, r4, CFG_DBAT1L@l
+ addis r3, r0, CFG_DBAT1U@h
+ ori r3, r3, CFG_DBAT1U@l
+ mtspr DBAT1L, r4
+ mtspr DBAT1U, r3
+ isync
+
+ /* IBAT 2 */
+ addis r4, r0, CFG_IBAT2L@h
+ ori r4, r4, CFG_IBAT2L@l
+ addis r3, r0, CFG_IBAT2U@h
+ ori r3, r3, CFG_IBAT2U@l
+ mtspr IBAT2L, r4
+ mtspr IBAT2U, r3
+ isync
+
+ /* DBAT 2 */
+ addis r4, r0, CFG_DBAT2L@h
+ ori r4, r4, CFG_DBAT2L@l
+ addis r3, r0, CFG_DBAT2U@h
+ ori r3, r3, CFG_DBAT2U@l
+ mtspr DBAT2L, r4
+ mtspr DBAT2U, r3
+ isync
+
+ /* IBAT 3 */
+ addis r4, r0, CFG_IBAT3L@h
+ ori r4, r4, CFG_IBAT3L@l
+ addis r3, r0, CFG_IBAT3U@h
+ ori r3, r3, CFG_IBAT3U@l
+ mtspr IBAT3L, r4
+ mtspr IBAT3U, r3
+ isync
+
+ /* DBAT 3 */
+ addis r4, r0, CFG_DBAT3L@h
+ ori r4, r4, CFG_DBAT3L@l
+ addis r3, r0, CFG_DBAT3U@h
+ ori r3, r3, CFG_DBAT3U@l
+ mtspr DBAT3L, r4
+ mtspr DBAT3U, r3
+ isync
+#endif
+
+ /* now invalidate the TLBs */
+ addis r3, 0, 0x0000
+#ifdef CONFIG_74x
+ addis r5, 0, 0x2 /* upper bound of 0x00020000 for 740 (603e) */
+#endif
+#if defined(CONFIG_75x) || defined(CONFIG_74xx)
+ addis r5, 0, 0x4 /* upper bound of 0x00040000 for 750/7400 */
+#endif
+ isync
+
+tlblp:
+ tlbie r3
+ sync
+ addi r3, r3, 0x1000
+ cmp 0, 0, r3, r5
+ blt tlblp
+
+ blr
+
+ .globl enable_addr_trans
+enable_addr_trans:
+ /* enable address translation */
+ mfmsr r5
+ ori r5, r5, (MSR_IR | MSR_DR)
+ mtmsr r5
+ isync
+ blr
+
+ .globl disable_addr_trans
+disable_addr_trans:
+ /* disable address translation */
+ mfmsr r5
+ andi. r5, r5, (~(MSR_IR | MSR_DR) & 0xFFFF)
+ mtmsr r5
+ isync
+ blr
+
+
+/*
+ * This code finishes saving the registers to the exception frame
+ * and jumps to the appropriate handler for the exception.
+ * Register r21 is pointer into trap frame, r1 has new stack pointer.
+ */
+ .globl transfer_to_handler
+transfer_to_handler:
+ stw r22,_NIP(r21)
+ lis r22,MSR_POW@h
+ andc r23,r23,r22
+ stw r23,_MSR(r21)
+ SAVE_GPR(7, r21)
+ SAVE_4GPRS(8, r21)
+ SAVE_8GPRS(12, r21)
+ SAVE_8GPRS(24, r21)
+ mflr r23
+ andi. r24,r23,0x3f00 /* get vector offset */
+ stw r24,TRAP(r21)
+ li r22,0
+ stw r22,RESULT(r21)
+ mtspr SPRG2,r22 /* r1 is now kernel sp */
+ lwz r24,0(r23) /* virtual address of handler */
+ lwz r23,4(r23) /* where to go when done */
+ mtspr SRR0,r24
+ mtspr SRR1,r20
+ mtlr r23
+ SYNC
+ rfi /* jump to handler, enable MMU */
+
+int_return:
+ mfmsr r29 /* Disable interrupts */
+ li r4,0
+ ori r4,r4,MSR_EE
+ andc r29,r29,r4
+ SYNC /* Some chip revs need this... */
+ mtmsr r29
+ SYNC
+ lwz r2,_CTR(r1)
+ lwz r0,_LINK(r1)
+ mtctr r2
+ mtlr r0
+ lwz r2,_XER(r1)
+ lwz r0,_CCR(r1)
+ mtspr XER,r2
+ mtcrf 0xFF,r0
+ REST_10GPRS(3, r1)
+ REST_10GPRS(13, r1)
+ REST_8GPRS(23, r1)
+ REST_GPR(31, r1)
+ lwz r2,_NIP(r1) /* Restore environment */
+ lwz r0,_MSR(r1)
+ mtspr SRR0,r2
+ mtspr SRR1,r0
+ lwz r0,GPR0(r1)
+ lwz r2,GPR2(r1)
+ lwz r1,GPR1(r1)
+ SYNC
+ rfi
+
+/* Cache functions. XXX fix these, I think they're broken [josh].
+*/
+ .globl icache_enable
+icache_enable:
+ mfspr r3, HID0
+ ori r3, r3, (HID0_ICE | HID0_ICFI)
+ isync
+ mtspr HID0, r3
+ blr
+
+ .globl icache_disable
+icache_disable:
+ mfspr r3, HID0
+ li r4, 0
+ ori r4, r4, HID0_ICE
+ andc r3, r3, r4
+ isync
+ mtspr HID0, r3
+ blr
+
+ .globl icache_status
+icache_status:
+ mfspr r3, HID0
+ andi. r3, r3, HID0_ICE
+ blr
+
+ .globl dcache_enable
+dcache_enable:
+ mfspr r3, HID0
+ ori r3, r3, (HID0_DCI | HID0_DCE)
+ sync
+ mtspr HID0, r3
+ blr
+
+ .globl dcache_disable
+dcache_disable:
+ mfspr r3, HID0
+ li r4, HID0_DCE
+ andc r3, r3, r4
+ sync
+ mtspr HID0, r3
+ blr
+
+ .globl dcache_status
+dcache_status:
+ mfspr r3, HID0
+ andi. r3, r3, HID0_DCE
+ blr
+
+ .globl l2_enable
+l2_enable:
+ addis r3, r0, L2_ENABLE@h
+ ori r3, r3, L2_ENABLE@l
+ mtspr l2cr, r3
+ blr
+
+ .globl dc_read
+dc_read:
+ blr
+
+ .globl get_pvr
+get_pvr:
+ mfspr r3, PVR
+ blr
+
+/*-----------------------------------------------------------------------*/
+
+/*
+ * void relocate_code (addr_sp, bd, addr_moni)
+ *
+ * This "function" does not return, instead it continues in RAM
+ * after relocating the monitor code.
+ *
+ * r3 = dest
+ * r4 = src
+ * r5 = length in bytes
+ * r6 = cachelinesize
+ */
+ .globl relocate_code
+relocate_code:
+ mr r1, r3 /* Set new stack pointer */
+ mr r9, r4 /* Save copy of Board Info pointer */
+ mr r10, r5 /* Save copy of Destination Address */
+
+ mr r3, r5 /* Destination Address */
+ lis r4, CFG_MONITOR_BASE@h /* Source Address */
+ ori r4, r4, CFG_MONITOR_BASE@l
+ lis r5, CFG_MONITOR_LEN@h /* Length in Bytes */
+ ori r5, r5, CFG_MONITOR_LEN@l
+ li r6, CFG_CACHELINE_SIZE /* Cache Line Size */
+
+ /*
+ * Fix GOT pointer:
+ *
+ * New GOT-PTR = (old GOT-PTR - CFG_MONITOR_BASE) + Destination Address
+ *
+ * Offset:
+ */
+ sub r15, r10, r4 /* dest addr - moni base */
+
+ /* First our own GOT */
+ add r14, r14, r15
+ /* then the one used by the C code */
+ add r30, r30, r15
+
+ /*
+ * Now relocate code
+ */
+
+ cmplw cr1,r3,r4 /* cmp dest addr /w src addr */
+ addi r0,r5,3
+ srwi. r0,r0,2
+ beq cr1,4f /* In place copy is not necessary */
+ beq 7f /* Protect against 0 count */
+ mtctr r0 /* ctr contains now moni len in DWORDS */
+ bge cr1,2f
+
+ la r8,-4(r4)
+ la r7,-4(r3)
+1: lwzu r0,4(r8)
+ stwu r0,4(r7)
+ bdnz 1b
+ b 4f
+
+2: slwi r0,r0,2
+ add r8,r4,r0
+ add r7,r3,r0
+3: lwzu r0,-4(r8)
+ stwu r0,-4(r7)
+ bdnz 3b
+
+/*
+ * Now flush the cache: note that we must start from a cache aligned
+ * address. Otherwise we might miss one cache line.
+ */
+4:
+ cmpwi r6,0
+ add r5,r3,r5
+ beq 7f /* Always flush prefetch queue in any case */
+ subi r0,r6,1
+ andc r3,r3,r0
+ mr r4,r3
+5: cmplw r4,r5
+ dcbst 0,r4
+ add r4,r4,r6
+ blt 5b
+ sync /* Wait for all dcbst to complete on bus */
+ mr r4,r3
+6: cmplw r4,r5
+ icbi 0,r4
+ add r4,r4,r6
+ blt 6b
+
+7:
+ sync /* Wait for all icbi to complete on bus */
+ isync
+
+/*
+ * We are done. Do not return, instead branch to second part of board
+ * initialization, now running from RAM.
+ */
+ addi r0, r10, in_ram - _start + EXC_OFF_SYS_RESET
+ mtlr r0
+ blr
+
+in_ram:
+ /*
+ * Relocation Function, r14 point to got2+0x8000
+ *
+ * Adjust got2 pointers, no need to check for 0, this code
+ * already puts a few entries in the table.
+ */
+ li r0,__got2_entries@sectoff@l
+ la r3,GOT(_GOT2_TABLE_)
+ lwz r11,GOT(_GOT2_TABLE_)
+ mtctr r0
+ sub r11,r3,r11
+ addi r3,r3,-4
+1: lwzu r0,4(r3)
+ add r0,r0,r11
+ stw r0,0(r3)
+ bdnz 1b
+
+ /*
+ * Now adjust the fixups and the pointers to the fixups
+ * in case we need to move ourselves again.
+ */
+2: li r0,__fixup_entries@sectoff@l
+ lwz r3,GOT(_FIXUP_TABLE_)
+ cmpwi r0,0
+ mtctr r0
+ addi r3,r3,-4
+ beq 4f
+3: lwzu r4,4(r3)
+ lwzux r0,r4,r11
+ add r0,r0,r11
+ stw r10,0(r3)
+ stw r0,0(r4)
+ bdnz 3b
+4:
+clear_bss:
+ /*
+ * Now clear BSS segment
+ */
+ lwz r3,GOT(.bss)
+ lwz r4,GOT(_end)
+
+ cmplw 0, r3, r4
+ beq 6f
+
+ li r0, 0
+5:
+ stw r0, 0(r3)
+ addi r3, r3, 4
+ cmplw 0, r3, r4
+ bne 5b
+6:
+ mr r3, r9 /* Board Info pointer */
+ mr r4, r10 /* Destination Address */
+
+ bl board_init_r
+
+ /* Problems accessing "end" in C, so do it here */
+ .globl get_endaddr
+get_endaddr:
+ lwz r3,GOT(_end)
+ blr
+
+ .globl get_startaddr
+get_startaddr:
+ lwz r3,GOT(_start)
+ blr
+
+ .globl get_msgblk
+get_msgblk:
+ lwz r3,GOT(MessageBlock)
+ blr
+
+/* .globl get_spdread
+get_spdread:
+ lwz r3,GOT(spdRead)
+ blr
+
+*/
+ /*
+ * Copy exception vector code to low memory
+ *
+ * r3: dest_addr
+ * r7: source address, r8: end address, r9: target address
+ */
+ .globl trap_init
+trap_init:
+ lwz r7, GOT(_start)
+ lwz r8, GOT(_end_of_vectors)
+
+ rlwinm r9, r7, 0, 18, 31 /* _start & 0x3FFF */
+
+ cmplw 0, r7, r8
+ bgelr /* return if r7>=r8 - just in case */
+
+ mflr r4 /* save link register */
+1:
+ lwz r0, 0(r7)
+ stw r0, 0(r9)
+ addi r7, r7, 4
+ addi r9, r9, 4
+ cmplw 0, r7, r8
+ bne 1b
+
+ /*
+ * relocate `hdlr' and `int_return' entries
+ */
+ li r7, .L_MachineCheck - _start + EXC_OFF_SYS_RESET
+ li r8, Alignment - _start + EXC_OFF_SYS_RESET
+2:
+ bl trap_reloc
+ addi r7, r7, 0x100 /* next exception vector */
+ cmplw 0, r7, r8
+ blt 2b
+
+ li r7, .L_Alignment - _start + EXC_OFF_SYS_RESET
+ bl trap_reloc
+
+ li r7, .L_ProgramCheck - _start + EXC_OFF_SYS_RESET
+ bl trap_reloc
+
+ li r7, .L_FPUnavailable - _start + EXC_OFF_SYS_RESET
+ li r8, _end_of_vectors - _start + EXC_OFF_SYS_RESET
+3:
+ bl trap_reloc
+ addi r7, r7, 0x100 /* next exception vector */
+ cmplw 0, r7, r8
+ blt 3b
+
+ mtlr r4 /* restore link register */
+ blr
+
+ /*
+ * Function: relocate entries for one exception vector
+ */
+trap_reloc:
+ lwz r0, 0(r7) /* hdlr ... */
+ add r0, r0, r3 /* ... += dest_addr */
+ stw r0, 0(r7)
+
+ lwz r0, 4(r7) /* int_return ... */
+ add r0, r0, r3 /* ... += dest_addr */
+ stw r0, 4(r7)
+
+ sync
+ isync
+
+ blr
+
+/* ------------------------------------------------------------------------------- */
+/* Function: in8 */
+/* Description: Input 8 bits */
+/* ------------------------------------------------------------------------------- */
+ .globl in8
+in8:
+ lbz r3,0(r3)
+ sync
+ blr
+
+/* ------------------------------------------------------------------------------- */
+/* Function: in16 */
+/* Description: Input 16 bits */
+/* ------------------------------------------------------------------------------- */
+ .globl in16
+in16:
+ lhz r3,0(r3)
+ sync
+ blr
+
+/* ------------------------------------------------------------------------------- */
+/* Function: in16r */
+/* Description: Input 16 bits and byte reverse */
+/* ------------------------------------------------------------------------------- */
+ .globl in16r
+in16r:
+ lhbrx r3,0,r3
+ sync
+ blr
+
+/* ------------------------------------------------------------------------------- */
+/* Function: in32 */
+/* Description: Input 32 bits */
+/* ------------------------------------------------------------------------------- */
+ .globl in32
+in32:
+ lwz 3,0(3)
+ sync
+ blr
+
+/* ------------------------------------------------------------------------------- */
+/* Function: in32r */
+/* Description: Input 32 bits and byte reverse */
+/* ------------------------------------------------------------------------------- */
+ .globl in32r
+in32r:
+ lwbrx r3,0,r3
+ sync
+ blr
+
+/* ------------------------------------------------------------------------------- */
+/* Function: out8 */
+/* Description: Output 8 bits */
+/* ------------------------------------------------------------------------------- */
+ .globl out8
+out8:
+ stb r4,0(r3)
+ sync
+ blr
+
+/* ------------------------------------------------------------------------------- */
+/* Function: out16 */
+/* Description: Output 16 bits */
+/* ------------------------------------------------------------------------------- */
+ .globl out16
+out16:
+ sth r4,0(r3)
+ sync
+ blr
+
+/* ------------------------------------------------------------------------------- */
+/* Function: out16r */
+/* Description: Byte reverse and output 16 bits */
+/* ------------------------------------------------------------------------------- */
+ .globl out16r
+out16r:
+ sthbrx r4,0,r3
+ sync
+ blr
+
+/* ------------------------------------------------------------------------------- */
+/* Function: out32 */
+/* Description: Output 32 bits */
+/* ------------------------------------------------------------------------------- */
+ .globl out32
+out32:
+ stw r4,0(r3)
+ sync
+ blr
+
+/* ------------------------------------------------------------------------------- */
+/* Function: out32r */
+/* Description: Byte reverse and output 32 bits */
+/* ------------------------------------------------------------------------------- */
+ .globl out32r
+out32r:
+ stwbrx r4,0,r3
+ sync
+ blr
+
--- /dev/null
+/*
+ * linux/arch/ppc/kernel/traps.c
+ *
+ * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
+ *
+ * Modified by Cort Dougan (cort@cs.nmt.edu)
+ * and Paul Mackerras (paulus@cs.anu.edu.au)
+ *
+ * (C) Copyright 2000
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+/*
+ * This file handles the architecture-dependent parts of hardware exceptions
+ */
+
+#include <ppcboot.h>
+#include <command.h>
+#include <asm/processor.h>
+
+#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
+int (*debugger_exception_handler)(struct pt_regs *) = 0;
+#endif
+
+/* Returns 0 if exception not found and fixup otherwise. */
+extern unsigned long search_exception_table(unsigned long);
+
+/* THIS NEEDS CHANGING to use the board info structure.
+*/
+#define END_OF_MEM 0x02000000
+
+/*
+ * Trap & Exception support
+ */
+
+void
+print_backtrace(unsigned long *sp)
+{
+ int cnt = 0;
+ unsigned long i;
+
+ printf("Call backtrace: ");
+ while (sp) {
+ if ((uint)sp > END_OF_MEM)
+ break;
+
+ i = sp[1];
+ if (cnt++ % 7 == 0)
+ printf("\n");
+ printf("%08lX ", i);
+ if (cnt > 32) break;
+ sp = (unsigned long *)*sp;
+ }
+ printf("\n");
+}
+
+void
+show_regs(struct pt_regs * regs)
+{
+ int i;
+
+ printf("NIP: %08lX XER: %08lX LR: %08lX REGS:"
+ " %p TRAP: %04lx DAR: %08lX\n",
+ regs->nip, regs->xer, regs->link, regs, regs->trap, regs->dar);
+ printf("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);
+
+ printf("\n");
+ for (i = 0; i < 32; i++) {
+ if ((i % 8) == 0)
+ {
+ printf("GPR%02d: ", i);
+ }
+
+ printf("%08lX ", regs->gpr[i]);
+ if ((i % 8) == 7)
+ {
+ printf("\n");
+ }
+ }
+}
+
+
+void
+_exception(int signr, struct pt_regs *regs)
+{
+ show_regs(regs);
+ print_backtrace((unsigned long *)regs->gpr[1]);
+ panic("Exception in kernel pc %lx signal %d",regs->nip,signr);
+}
+
+void
+MachineCheckException(struct pt_regs *regs)
+{
+ unsigned long fixup;
+
+ /* Probing PCI using config cycles cause this exception
+ * when a device is not present. Catch it and return to
+ * the PCI exception handler.
+ */
+ if ((fixup = search_exception_table(regs->nip)) != 0) {
+ regs->nip = fixup;
+ return;
+ }
+
+#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
+ if (debugger_exception_handler && (*debugger_exception_handler)(regs))
+ return;
+#endif
+
+ printf("Machine check in kernel mode.\n");
+ printf("Caused by (from msr): ");
+ printf("regs %p ",regs);
+ switch( regs->msr & 0x0000F000)
+ {
+ case (1<<12) :
+ printf("Machine check signal - probably due to mm fault\n"
+ "with mmu off\n");
+ break;
+ case (1<<13) :
+ printf("Transfer error ack signal\n");
+ break;
+ case (1<<14) :
+ printf("Data parity signal\n");
+ break;
+ case (1<<15) :
+ printf("Address parity signal\n");
+ break;
+ default:
+ printf("Unknown values in msr\n");
+ }
+ show_regs(regs);
+ print_backtrace((unsigned long *)regs->gpr[1]);
+ panic("machine check");
+}
+
+void
+AlignmentException(struct pt_regs *regs)
+{
+#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
+ if (debugger_exception_handler && (*debugger_exception_handler)(regs))
+ return;
+#endif
+ show_regs(regs);
+ print_backtrace((unsigned long *)regs->gpr[1]);
+ panic("Alignment Exception");
+}
+
+void
+ProgramCheckException(struct pt_regs *regs)
+{
+#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
+ if (debugger_exception_handler && (*debugger_exception_handler)(regs))
+ return;
+#endif
+ show_regs(regs);
+ print_backtrace((unsigned long *)regs->gpr[1]);
+ panic("Program Check Exception");
+}
+
+void
+SoftEmuException(struct pt_regs *regs)
+{
+#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
+ if (debugger_exception_handler && (*debugger_exception_handler)(regs))
+ return;
+#endif
+ show_regs(regs);
+ print_backtrace((unsigned long *)regs->gpr[1]);
+ panic("Software Emulation Exception");
+}
+
+
+void
+UnknownException(struct pt_regs *regs)
+{
+#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
+ if (debugger_exception_handler && (*debugger_exception_handler)(regs))
+ return;
+#endif
+ printf("Bad trap at PC: %lx, SR: %lx, vector=%lx\n",
+ regs->nip, regs->msr, regs->trap);
+ _exception(0, regs);
+}
+
+/* Probe an address by reading. If not present, return -1, otherwise
+ * return 0.
+ */
+int
+addr_probe(uint *addr)
+{
+#if 0
+ int retval;
+
+ __asm__ __volatile__( \
+ "1: lwz %0,0(%1)\n" \
+ " eieio\n" \
+ " li %0,0\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" (retval) : "r"(addr));
+
+ return (retval);
+#endif
+ return 0;
+}
--- /dev/null
+/*
+ * (C) Copyright 2001
+ * Josh Huber <huber@mclx.com>, Mission Critical Linux, 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
+ */
+
+/*
+ * board/config.h - configuration options, board specific
+ */
+
+#ifndef __CONFIG_H
+#define __CONFIG_H
+
+#include <asm/processor.h>
+
+/*#define DEBUG 1*/
+/*
+ * High Level Configuration Options
+ * (easy to change)
+ */
+
+/* these hardware addresses are pretty bogus, please change them to
+ suit your needs */
+
+/* first ethernet */
+#define CONFIG_ETHADDR 00:00:5B:00:6E:8A
+
+#define CONFIG_IPADDR 172.22.2.112
+#define CONFIG_SERVERIP 172.22.2.111
+
+#define CONFIG_ENV_OVERWRITE
+
+#if 0
+
+#define CFG_ENV_IS_IN_FLASH 1 /* use Flash for environment vars */
+#define CFG_ENV_OFFSET 0x70000 /* Last sector of AMD29F040 flash */
+#define CFG_ENV_SECT_SIZE 0x10000 /* Total Size of Environment Sector (64kB) */
+
+#else
+
+#define CFG_ENV_IS_IN_NVRAM 1 /* use NVRAM for environment vars */
+#define CFG_NVRAM_SIZE (8*1024-16) /* NVRAM size (8kB), we must protect the clock data (16 bytes) */
+#define CFG_ENV_SIZE 0x400 /* Size of Environment vars (1kB)*/
+/*
+ * We store the environment in the upper part of the NVRAM. Thus,
+ * user applications can use the remaining space for other purposes.
+ */
+#define CFG_ENV_ADDR (CFG_NVRAM_SIZE-CFG_ENV_SIZE)
+#define CFG_NVRAM_ACCESS_ROUTINE 1 /* This board needs a special routine to access the NVRAM */
+
+#endif
+
+#define CONFIG_75x 1 /* This is a MPC75x */
+#define CONFIG_BAB750 1 /* ...on an BAB750 board */
+
+#define CONFIG_BAUDRATE 115200 /* console baudrate = 115kbps */
+
+#undef CONFIG_WATCHDOG
+
+/* to change the default ethernet port, use this define (options: 0, 1, 2) */
+#define CONFIG_ETHER_PORT 0
+
+#if 1
+#define CONFIG_BOOTDELAY -1 /* autoboot disabled */
+#else
+#define CONFIG_BOOTDELAY 5 /* autoboot after 5 seconds */
+#endif
+#define CONFIG_ZERO_BOOTDELAY_CHECK
+
+#undef CONFIG_BOOTARGS
+
+#define CONFIG_BOOTCOMMAND \
+ "bootp 1000000; " \
+ "setenv bootargs root=/dev/nfs rw nfsroot=$(serverip):$(rootpath) " \
+ "ip=$(ipaddr):$(serverip):$(gatewayip):" \
+ "$(netmask):$(hostname):eth0:none; "\
+ "bootm"
+
+#define CONFIG_LOADS_ECHO 0 /* echo off for serial download */
+#define CFG_LOADS_BAUD_CHANGE /* allow baudrate changes */
+
+#define CONFIG_BOOTP_MASK (CONFIG_BOOTP_DEFAULT | \
+ CONFIG_BOOTP_BOOTFILESIZE)
+
+#define CONFIG_COMMANDS (CONFIG_CMD_DFL | CFG_CMD_PCI | CFG_CMD_SCSI | CFG_CMD_IDE | CFG_CMD_DATE | CFG_CMD_FDC)
+
+/* this must be included AFTER the definition of CONFIG_COMMANDS (if any) */
+#include <cmd_confdefs.h>
+
+/*
+ * Miscellaneous configurable options
+ */
+#define CFG_LONGHELP /* undef to save memory */
+#define CFG_PROMPT "=> " /* Monitor Command Prompt */
+
+/*
+ * choose between COM1 and COM2 as serial console
+ */
+#define CONFIG_CONS_INDEX 1
+
+#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
+#define CFG_CBSIZE 1024 /* Console I/O Buffer Size */
+#else
+#define CFG_CBSIZE 256 /* Console I/O Buffer Size */
+#endif
+#define CFG_PBSIZE (CFG_CBSIZE+sizeof(CFG_PROMPT)+16) /* Print Buffer Size */
+#define CFG_MAXARGS 16 /* max number of command args */
+#define CFG_BARGSIZE CFG_CBSIZE /* Boot Argument Buffer Size */
+
+#define CFG_MEMTEST_START 0x00000000 /* memtest works on */
+#define CFG_MEMTEST_END 0x04000000 /* 0 ... 64 MB in DRAM */
+
+#define CFG_LOAD_ADDR 0x100000 /* default load address */
+
+#define CFG_HZ 1000 /* decrementer freq: 1 ms ticks */
+
+#define CFG_BAUDRATE_TABLE { 9600, 19200, 38400, 57600, 115200, 230400 }
+
+/*
+ * Choose the address mapping scheme for the MPC106 mem controller.
+ * Default is mapping B (CHRP), set this define to choose mapping A (PReP).
+ */
+#define CFG_ADDRESS_MAP_A 1
+
+/*
+ * Low Level Configuration Settings
+ * (address mappings, register initial values, etc.)
+ * You should know what you are doing if you make changes here.
+ */
+
+/*
+ * Definitions for initial stack pointer and data area
+ */
+#define CFG_INIT_RAM_ADDR 0x00fd0000 /* above the memtest region */
+#define CFG_INIT_RAM_END 0x4000
+#define CFG_INIT_DATA_SIZE 64 /* size in bytes reserved for init data */
+#define CFG_INIT_DATA_OFFSET (CFG_INIT_RAM_END - CFG_INIT_DATA_SIZE)
+#define CFG_INIT_SP_OFFSET CFG_INIT_DATA_OFFSET
+
+/*
+ * Start addresses for the final memory configuration
+ * (Set up by the startup code)
+ * Please note that CFG_SDRAM_BASE _must_ start at 0
+ */
+#define CFG_SDRAM_BASE 0x00000000
+
+/*
+ * The mapped position of the flashes is independent from
+ * the chosen address map for the MPC106.
+ */
+#define CFG_FLASH_BASE 0xFFC00000
+#define FLASH_BASE0_PRELIM 0xFFC00000
+#define FLASH_BASE1_PRELIM 0xFF800000
+
+#define CFG_MONITOR_BASE TEXT_BASE
+
+#ifdef IN_RAM
+ #define CFG_MONITOR_LEN (4 <<20) /* if we're running in ram, give us plenty of space for debug info*/
+ #undef CFG_MEMTEST
+#else
+ #define CFG_MONITOR_LEN (256 << 10) /* Reserve 256 kB for Monitor */
+ #undef CFG_MEMTEST
+#endif
+
+#define CFG_MALLOC_LEN (128 << 10) /* Reserve 128 kB for malloc() */
+
+#define CFG_CPU_CLK 266000000
+#define CFG_BUS_CLK 6600000
+
+/*
+ * Do NOT change the following table!!! Important mapping information!!
+ */
+#ifdef CFG_ADDRESS_MAP_A
+#define CFG_ISA_MEM 0xC0000000
+#define CFG_ISA_IO_BASE_ADDRESS 0x80000000
+#define CFG_ISA_IO CFG_ISA_IO_BASE_ADDRESS
+#define CFG_PCI_IO_BASE_ADDRESS 0x81000000
+#define CFG_PCI_IO CFG_PCI_IO_BASE_ADDRESS
+#else
+#define CFG_ISA_MEM 0xFD000000
+#define CFG_ISA_IO_BASE_ADDRESS 0xFE000000
+#define CFG_ISA_IO CFG_ISA_IO_BASE_ADDRESS
+#define CFG_PCI_IO_BASE_ADDRESS 0xFE800000
+#define CFG_PCI_IO CFG_PCI_IO_BASE_ADDRESS
+#endif
+
+/*
+ * PCI stuff
+ */
+#define CONFIG_PCI /* include pci support */
+#define CONFIG_PCI_HOST PCI_HOST_AUTO
+#define CONFIG_PCI_PNP /* pci plug-and-play */
+
+/*
+ * Do NOT change the following table!!! Important mapping information!!
+ */
+#ifdef CFG_ADDRESS_MAP_A
+#define CFG_PCI_DRAM_OFFSET 0x80000000
+#define CFG_60X_PCI_MEM_OFFSET 0xC0000000
+#define CFG_60X_PCI_IO_OFFSET 0x80000000
+#define CFG_MIN_PCI_MEMADDR1 0x01010000
+#define CFG_MIN_PCI_MEMADDR2 0x01010000
+#define CFG_PCI_PCI_IOADDR 0x01000000
+#else
+#define CFG_PCI_DRAM_OFFSET 0x00000000
+#define CFG_60X_PCI_MEM_OFFSET 0x00000000
+#define CFG_60X_PCI_IO_OFFSET 0xFE000000
+#define CFG_MIN_PCI_MEMADDR1 0xF9000000
+#define CFG_MIN_PCI_MEMADDR2 0xFA000000
+#define CFG_PCI_PCI_IOADDR 0x00800000
+#endif
+
+#define CFG_MAX_PCI_DEVICES 32
+#define CFG_MAX_PCI_FUNCTIONS 8
+
+/*
+ * IDE/ATA stuff
+ */
+#define CFG_IDE_MAXBUS 1 /* max. 2 IDE busses */
+#define CFG_IDE_MAXDEVICE (CFG_IDE_MAXBUS*2) /* max. 2 drives per IDE bus */
+
+#define CFG_ATA_BASE_ADDR CFG_60X_PCI_IO_OFFSET /* base address */
+#define CFG_ATA_IDE0_OFFSET 0x1F0 /* default ide0 offste */
+#define CFG_ATA_IDE1_OFFSET 0x170 /* default ide1 offset */
+#define CFG_ATA_DATA_OFFSET 0 /* data reg offset */
+#define CFG_ATA_REG_OFFSET 0 /* reg offset */
+#define CFG_ATA_ALT_OFFSET 0x200 /* alternate register offset */
+
+#undef CONFIG_IDE_PCMCIA /* no pcmcia interface required */
+#undef CONFIG_IDE_LED /* no led for ide supported */
+
+/*
+ * ATAPI support (experimental)
+ */
+#define CONFIG_ATAPI /* enable ATAPI Support */
+
+
+/*
+ * SCSI support (experimental) only SYM53C8xx supported
+ */
+#define CONFIG_SCSI_SYM53C8XX
+#define CONFIG_SCSI_DEV_ID 0x000F /* 53c875 */
+#define CFG_SCSI_MAX_LUN 8 /* number of supported LUNs */
+#define CFG_SCSI_MAX_SCSI_ID 15 /* maximum SCSI ID (0..6) */
+#define CFG_SCSI_MAX_DEVICE CFG_SCSI_MAX_SCSI_ID * CFG_SCSI_MAX_LUN /* maximum Target devices */
+#define CFG_SCSI_SPIN_UP_TIME 2
+#define CFG_SCSI_SCAN_BUS_REVERSE 0
+#define CONFIG_DOS_PARTITION
+#define CONFIG_MAC_PARTITION
+#define CONFIG_ISO_PARTITION
+
+#define CFG_WINBOND_83C553 1 /*has a winbond bridge */
+#define CFG_USE_WINBOND_IDE 0 /*use winbond 83c553 internal ide controller */
+#define CFG_WINBOND_ISA_CFG_ADDR 0x80005800 /*pci-isa bridge config addr */
+#define CFG_WINBOND_IDE_CFG_ADDR 0x80005900 /*ide config addr */
+#define CFG_NS87308_BADDR_10 1
+
+#define CFG_NS_PC87308UL 1 /* Nat Semi super-io controller on ISA bus */
+
+#define CONFIG_RTC_MK48T59
+
+/*
+ * Initial BAT mappings
+ */
+
+/* do we need the MMU? probably not, but if we do, we must use the BATs */
+#undef CFG_MMU
+
+#ifdef CFG_MMU
+/* SDRAM */
+#define CFG_IBAT0L (CFG_SDRAM_BASE | BATL_RW)
+#define CFG_IBAT0U (CFG_SDRAM_BASE | BATU_BL_256M | BATU_VS | BATU_VP)
+#define CFG_DBAT0L CFG_IBAT1L
+#define CFG_DBAT0U CFG_IBAT1U
+
+/* address range for flashes */
+#define CFG_IBAT1L (CFG_FLASH_BASE | BATL_RW | BATL_CACHEINHIBIT)
+#define CFG_IBAT1U (CFG_FLASH_BASE | BATU_BL_16M | BATU_VS | BATU_VP)
+#define CFG_DBAT1L CFG_IBAT1L
+#define CFG_DBAT1U CFG_IBAT1U
+
+/* ISA IO space */
+#define CFG_IBAT2L (CFG_ISA_IO | BATL_RW | BATL_CACHEINHIBIT)
+#define CFG_IBAT2U (CFG_ISA_IO | BATU_BL_16M | BATU_VS | BATU_VP)
+#define CFG_DBAT2L CFG_IBAT2L
+#define CFG_DBAT2U CFG_IBAT2U
+
+/* ISA memory space */
+#define CFG_IBAT3L (CFG_ISA_MEM | BATL_RW | BATL_CACHEINHIBIT)
+#define CFG_IBAT3U (CFG_ISA_MEM | BATU_BL_16M | BATU_VS | BATU_VP)
+#define CFG_DBAT3L CFG_IBAT3L
+#define CFG_DBAT3U CFG_IBAT3U
+
+#else
+
+#define CFG_IBAT0L 0
+#define CFG_IBAT0U 0
+#define CFG_DBAT0L CFG_IBAT1L
+#define CFG_DBAT0U CFG_IBAT1U
+
+#define CFG_IBAT1L 0
+#define CFG_IBAT1U 0
+#define CFG_DBAT1L CFG_IBAT1L
+#define CFG_DBAT1U CFG_IBAT1U
+
+/* ISA IO space */
+#define CFG_IBAT2L 0
+#define CFG_IBAT2U 0
+#define CFG_DBAT2L CFG_IBAT2L
+#define CFG_DBAT2U CFG_IBAT2U
+
+/* ISA memory space */
+#define CFG_IBAT3L 0
+#define CFG_IBAT3U 0
+#define CFG_DBAT3L CFG_IBAT3L
+#define CFG_DBAT3U CFG_IBAT3U
+
+#endif
+
+/*
+ * For booting Linux, the board info and command line data
+ * have to be in the first 8 MB of memory, since this is
+ * the maximum mapped by the Linux kernel during initialization.
+ */
+#define CFG_BOOTMAPSZ (8 << 20) /* Initial Memory map for Linux */
+
+/*
+ * FLASH organization
+ */
+#define CFG_MAX_FLASH_BANKS 2 /* max number of memory banks */
+#define CFG_MAX_FLASH_SECT 67 /* max number of sectors on one chip */
+
+#define CFG_FLASH_ERASE_TOUT 120000 /* Timeout for Flash Erase (in ms) */
+#define CFG_FLASH_WRITE_TOUT 500 /* Timeout for Flash Write (in ms) */
+
+/*
+ * Cache Configuration
+ */
+#define CFG_CACHELINE_SIZE 32 /* For all MPC74xx CPUs */
+#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
+#define CFG_CACHELINE_SHIFT 5 /* log base 2 of the above value */
+#endif
+
+/*
+ * L2CR setup -- make sure this is right for your board!
+ * look in include/mpc74xx.h for the defines used here
+ */
+/*#define CFG_L2*/
+#define L2_INIT (L2CR_L2SIZ_HM | L2CR_L2CLK_3 | L2CR_L2RAM_BURST | \
+ L2CR_L2OH_5 | L2CR_L2CTL | L2CR_L2WT)
+#define L2_ENABLE (L2_INIT | L2CR_L2E)
+
+/*
+ * Internal Definitions
+ *
+ * Boot Flags
+ */
+#define BOOTFLAG_COLD 0x01 /* Normal Power-On: Boot from FLASH */
+#define BOOTFLAG_WARM 0x02 /* Software reboot */
+
+#endif /* __CONFIG_H */
--- /dev/null
+/*
+ * (C) Copyright 2001 Sysgo Real-Time Solutions, GmbH <www.elinos.com>
+ * Andreas Heppel <aheppel@sysgo.de>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+/*
+ * Date & Time support for the MK48T59 RTC
+ */
+
+
+#if defined(CONFIG_RTC_MK48T59) && (CONFIG_COMMANDS & CFG_CMD_DATE)
+
+#define RTC_PORT_ADDR0 CFG_ISA_IO + 0x70
+#define RTC_PORT_ADDR1 RTC_PORT_ADDR0 + 0x1
+#define RTC_PORT_DATA CFG_ISA_IO + 0x76
+
+/* RTC Offsets */
+#define RTC_SECONDS 0x1FF9
+#define RTC_MINUTES 0x1FFA
+#define RTC_HOURS 0x1FFB
+#define RTC_DAY_OF_WEEK 0x1FFC
+#define RTC_DAY_OF_MONTH 0x1FFD
+#define RTC_MONTH 0x1FFE
+#define RTC_YEAR 0x1FFF
+
+#define RTC_CONTROLA 0x1FF8
+#define RTC_CA_WRITE 0x80
+#define RTC_CA_READ 0x40
+#define RTC_CA_CALIB_SIGN 0x20
+#define RTC_CA_CALIB_MASK 0x1f
+
+#define RTC_CONTROLB 0x1FF9
+#define RTC_CB_STOP 0x80
+
+#define RTC_WATCHDOG 0x1FF7
+#define RTC_WDS 0x80
+#define RTC_WD_RB_16TH 0x0
+#define RTC_WD_RB_4TH 0x1
+#define RTC_WD_RB_1 0x2
+#define RTC_WD_RB_4 0x3
+
+void rtc_set_watchdog(short multi, short res);
+void *nvram_read(void *dest, const short src, size_t count);
+void nvram_write(short dest, const void *src, size_t count);
+
+#endif
--- /dev/null
+/*
+ * (C) Copyright 2001 Sysgo Real-Time Solutions, GmbH <www.elinos.com>
+ * Andreas Heppel <aheppel@sysgo.de>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#ifndef _MPC106_PCI_H
+#define _MPC106_PCI_H
+
+#ifndef DEFS_ONLY
+typedef struct pciHeaderDevice {
+ short vendorId; /* vendor ID */
+ short deviceId; /* device ID */
+ short command; /* command register */
+ short status; /* status register */
+ char revisionId; /* revision ID */
+ char classCode; /* class code */
+ char subClass; /* sub class code */
+ char progIf; /* programming interface */
+ char cacheLine; /* cache line */
+ char latency; /* latency time */
+ char headerType; /* header type */
+ char bist; /* BIST */
+ int base0; /* base address 0 */
+ int base1; /* base address 1 */
+ int base2; /* base address 2 */
+ int base3; /* base address 3 */
+ int base4; /* base address 4 */
+ int base5; /* base address 5 */
+ int cis; /* cardBus CIS pointer */
+ short subVendorId; /* sub system vendor ID */
+ short subSystemId; /* sub system ID */
+ int romBase; /* expansion ROM base address */
+ int reserved0; /* reserved */
+ int reserved1; /* reserved */
+ char intLine; /* interrupt line */
+ char intPin; /* interrupt pin */
+ char minGrant; /* min Grant */
+ char maxLatency; /* max Latency */
+} PCI_HEADER_DEVICE;
+
+typedef struct pciHeaderBridge {
+ short vendorId; /* vendor ID */
+ short deviceId; /* device ID */
+ short command; /* command register */
+ short status; /* status register */
+ char revisionId; /* revision ID */
+ char classCode; /* class code */
+ char subClass; /* sub class code */
+ char progIf; /* programming interface */
+ char cacheLine; /* cache line */
+ char latency; /* latency time */
+ char headerType; /* header type */
+ char bist; /* BIST */
+ int base0; /* base address 0 */
+ int base1; /* base address 1 */
+ char priBus; /* primary bus number */
+ char secBus; /* secondary bus number */
+ char subBus; /* subordinate bus number */
+ char secLatency; /* secondary latency timer */
+ char ioBase; /* IO base */
+ char ioLimit; /* IO limit */
+ short secStatus; /* secondary status */
+ short memBase; /* memory base */
+ short memLimit; /* memory limit */
+ short preBase; /* prefetchable memory base */
+ short preLimit; /* prefetchable memory limit */
+ int preBaseUpper; /* prefetchable memory base upper 32 bits */
+ int preLimitUpper; /* prefetchable memory base upper 32 bits */
+ short ioBaseUpper; /* IO base upper 16 bits */
+ short ioLimitUpper; /* IO limit upper 16 bits */
+ int reserved; /* reserved */
+ int romBase; /* expansion ROM base address */
+ char intLine; /* interrupt line */
+ char intPin; /* interrupt pin */
+ short control; /* bridge control */
+} PCI_HEADER_BRIDGE;
+
+#endif /* DEFS_ONLY */
+
+
+/*
+ * Defines for the MPC106 PCI Config address and data registers followed by
+ * defines for the standard PCI device configuration header.
+ */
+
+#define PCIDEVID_MPC106 0x0
+
+/*
+ * MPC106 Registers
+ */
+#define MPC106_REG 0x80000000
+
+#ifdef CFG_ADDRESS_MAP_A
+#define MPC106_REG_ADDR 0x80000cf8
+#define MPC106_REG_DATA 0x80000cfc
+#else
+#define MPC106_REG_ADDR 0xfec00cf8
+#define MPC106_REG_DATA 0xfee00cfc
+#endif
+
+#define CMD_SERR 0x0100
+#define PCI_CMD_MASTER 0x0004
+#define PCI_CMD_MEMEN 0x0002
+#define PCI_CMD_IOEN 0x0001
+
+#define PCI_STAT_NO_RSV_BITS 0xffff
+
+#define PCI_BUSNUM 0x40
+#define PCI_SUBBUSNUM 0x41
+#define PCI_DISCOUNT 0x42
+
+#define PCI_PICR1 0xA8
+#define PICR1_CF_CBA(value) ((value & 0xff) << 24)
+#define PICR1_CF_BREAD_WS(value) ((value & 0x3) << 22)
+#define PICR1_PROC_TYPE_603 0x40000
+#define PICR1_PROC_TYPE_604 0x60000
+#define PICR1_MCP_EN 0x800
+#define PICR1_CF_DPARK 0x200
+#define PICR1_CF_LOOP_SNOOP 0x10
+#define PICR1_CF_APARK 0x8
+#define PICR1_ADDRESS_MAP 0x10000
+#define PICR1_XIO_MODE 0x80000
+
+#define PCI_PICR2 0xAC
+#define PICR2_CF_SNOOP_WS(value) ((value & 0x3) << 18)
+#define PICR2_CF_FLUSH_L2 0x10000000
+#define PICR2_CF_L2_HIT_DELAY(value) ((value & 0x3) << 9)
+#define PICR2_CF_APHASE_WS(value) ((value & 0x3) << 2)
+#define PICR2_L2_EN 0x40000000
+#define PICR2_L2_UPDATE_EN 0x80000000
+
+/*
+ * PCI-PCI bridge header
+ */
+#define PCIPCI_PRIMARYBUS 0x18
+#define PCIPCI_SECONDARYBUS 0x19
+#define PCIPCI_SUBORDINATEBUS 0x1A
+#define PCIPCI_SECONDARYLATENCY 0x1B
+#define PCIPCI_IOBASE 0x1C
+#define PCIPCI_IOLIMIT 0x1D
+#define PCIPCI_SECONDARYSTATUS 0x1E
+#define PCIPCI_MEMBASE 0x20
+#define PCIPCI_MEMLIMIT 0x22
+#define PCIPCI_PREFETCHMEMBASE 0x24
+#define PCIPCI_PREFETCHMEMLIMIT 0x26
+#define PCIPCI_IOBASEUPPER16 0x30
+#define PCIPCI_IOLIMITUPPER16 0x32
+
+/*
+ * Standard device configuration register offsets
+ * Note that only modulo-4 addresses are written to the address register
+ */
+#define PCI_CFG_VENDOR_ID 0x00
+#define PCI_CFG_DEVICE_ID 0x02
+#define PCI_CFG_COMMAND 0x04
+#define PCI_CFG_STATUS 0x06
+#define PCI_CFG_REVISION 0x08
+#define PCI_CFG_PROGRAMMING_IF 0x09
+#define PCI_CFG_SUBCLASS 0x0a
+#define PCI_CFG_CLASS 0x0b
+#define PCI_CFG_CACHE_LINE_SIZE 0x0c
+#define PCI_CFG_LATENCY_TIMER 0x0d
+#define PCI_CFG_HEADER_TYPE 0x0e
+#define PCI_CFG_BIST 0x0f
+#define PCI_CFG_BASE_ADDRESS_0 0x10
+#define PCI_CFG_BASE_ADDRESS_1 0x14
+#define PCI_CFG_BASE_ADDRESS_2 0x18
+#define PCI_CFG_BASE_ADDRESS_3 0x1c
+#define PCI_CFG_BASE_ADDRESS_4 0x20
+#define PCI_CFG_BASE_ADDRESS_5 0x24
+#define PCI_CFG_CIS 0x28
+#define PCI_CFG_SUB_VENDER_ID 0x2c
+#define PCI_CFG_SUB_SYSTEM_ID 0x2e
+#define PCI_CFG_EXPANSION_ROM 0x30
+#define PCI_CFG_RESERVED_0 0x34
+#define PCI_CFG_RESERVED_1 0x38
+#define PCI_CFG_DEV_INT_LINE 0x3c
+#define PCI_CFG_DEV_INT_PIN 0x3d
+#define PCI_CFG_MIN_GRANT 0x3e
+#define PCI_CFG_MAX_LATENCY 0x3f
+#define PCI_CFG_SPECIAL_USE 0x41
+#define PCI_CFG_MODE 0x43
+
+
+/*
+ * PCI-to-PCI bridge configuration register offsets
+ * Note that only modulo-4 addresses are written to the address register
+ */
+#define PCI_CFG_PRIMARY_BUS 0x18
+#define PCI_CFG_SECONDARY_BUS 0x19
+#define PCI_CFG_SUBORDINATE_BUS 0x1a
+#define PCI_CFG_SEC_LATENCY 0x1b
+#define PCI_CFG_IO_BASE 0x1c
+#define PCI_CFG_IO_LIMIT 0x1d
+#define PCI_CFG_SEC_STATUS 0x1e
+#define PCI_CFG_MEM_BASE 0x20
+#define PCI_CFG_MEM_LIMIT 0x22
+#define PCI_CFG_PRE_MEM_BASE 0x24
+#define PCI_CFG_PRE_MEM_LIMIT 0x26
+#define PCI_CFG_PRE_MEM_BASE_U 0x28
+#define PCI_CFG_PRE_MEM_LIMIT_U 0x2c
+#define PCI_CFG_IO_BASE_U 0x30
+#define PCI_CFG_IO_LIMIT_U 0x32
+#define PCI_CFG_ROM_BASE 0x38
+#define PCI_CFG_BRG_INT_LINE 0x3c
+#define PCI_CFG_BRG_INT_PIN 0x3d
+#define PCI_CFG_BRIDGE_CONTROL 0x3e
+
+
+/*
+ * Memory controller
+ */
+#define MPC106_MCCR1 0xF0
+#define MCCR1_TYPE_EDO 0x00020000
+#define MCCR1_BK0_9BITS 0x0
+#define MCCR1_BK0_10BITS 0x1
+#define MCCR1_BK0_11BITS 0x2
+#define MCCR1_BK0_12BITS 0x3
+#define MCCR1_BK1_9BITS 0x0
+#define MCCR1_BK1_10BITS 0x4
+#define MCCR1_BK1_11BITS 0x8
+#define MCCR1_BK1_12BITS 0xC
+#define MCCR1_BK2_9BITS 0x00
+#define MCCR1_BK2_10BITS 0x10
+#define MCCR1_BK2_11BITS 0x20
+#define MCCR1_BK2_12BITS 0x30
+#define MCCR1_BK3_9BITS 0x00
+#define MCCR1_BK3_10BITS 0x40
+#define MCCR1_BK3_11BITS 0x80
+#define MCCR1_BK3_12BITS 0xC0
+#define MCCR1_MEMGO 0x00080000
+
+#define MPC106_MCCR2 0xF4
+#define MPC106_MCCR3 0xF8
+#define MPC106_MCCR4 0xFC
+
+#define MPC106_MSAR1 0x80
+#define MPC106_EMSAR1 0x88
+#define MPC106_EMSAR2 0x8C
+#define MPC106_MEAR1 0x90
+#define MPC106_EMEAR1 0x98
+#define MPC106_EMEAR2 0x9C
+
+#define MPC106_MBER 0xA0
+#define MBER_BANK0 0x1
+#define MBER_BANK1 0x2
+#define MBER_BANK2 0x4
+#define MBER_BANK3 0x8
+
+
+#ifndef DEFS_ONLY
+
+unsigned int PCI_Read_CFG_Reg(int BusDevFunc, int Reg, int Width);
+int PCI_Write_CFG_Reg(int BusDevFunc, int Reg, unsigned int Value, int Width);
+int PCI_Scan(int BusNum);
+void PCI_Config_Device(int BusDevFunc, int NumBaseAddr);
+void PCI_Config_VGA_Device(int BusDevFunc, int NumBaseAddr);
+void PCI_Config_Bridge(int BusDevFunc);
+int PCI_Find_Device(unsigned short VendorID, unsigned short DeviceID);
+void PCI_Header_Show(int BusDevFunc);
+void PCI_Dheader_Print(PCI_HEADER_DEVICE * pD);
+void PCI_Bheader_Print(PCI_HEADER_BRIDGE * pB);
+
+/*
+ * memory mapping functions
+ */
+unsigned long phys_to_bus(void*);
+void *bus_to_phys(unsigned long);
+
+#endif /* DEFS_ONLY */
+
+
+#endif
+
--- /dev/null
+/*
+ * (C) Copyright 2001 Sysgo Real-Time Solutions, GmbH <www.elinos.com>
+ * Andreas Heppel <aheppel@sysgo.de>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+/*
+ * mpc75x.h
+ *
+ * MPC75x/MPC74xx specific definitions
+ */
+
+#ifndef __MPC75X_H__
+#define __MPC75X_H__
+
+/*----------------------------------------------------------------
+ * Exception offsets (PowerPC standard)
+ */
+#define EXC_OFF_SYS_RESET 0x0100 /* default system reset offset */
+
+/*----------------------------------------------------------------
+ * l2cr values
+ */
+#define l2cr 1017
+
+#define L2CR_L2E 0x80000000 /* bit 0 - enable */
+#define L2CR_L2PE 0x40000000 /* bit 1 - data parity */
+#define L2CR_L2SIZ_2M 0x00000000 /* bits 2-3 - 2MB, MPC7400 only! */
+#define L2CR_L2SIZ_1M 0x30000000 /* ... 1MB */
+#define L2CR_L2SIZ_HM 0x20000000 /* ... 512K */
+#define L2CR_L2SIZ_QM 0x10000000 /* ... 256k */
+#define L2CR_L2CLK_1 0x02000000 /* bits 4-6 clock ratio div 1 */
+#define L2CR_L2CLK_1_5 0x04000000 /* bits 4-6 clock ratio div 1.5 */
+#define L2CR_L2CLK_2 0x08000000 /* bits 4-6 clock ratio div 2 */
+#define L2CR_L2CLK_2_5 0x0a000000 /* bits 4-6 clock ratio div 2.5 */
+#define L2CR_L2CLK_3 0x0c000000 /* bits 4-6 clock ratio div 3 */
+#define L2CR_L2CLK_3_5 0x06000000 /* bits 4-6 clock ratio div 3.5 */
+#define L2CR_L2CLK_4 0x0e000000 /* bits 4-6 clock ratio div 4 */
+#define L2CR_L2RAM_BURST 0x01000000 /* bits 7-8 - burst SRAM */
+#define L2CR_DO 0x00400000 /* bit 9 - enable caching of instr. in L2 */
+#define L2CR_L2I 0x00200000 /* bit 10 - global invalidate bit */
+#define L2CR_L2CTL 0x00100000 /* bit 11 - l2 ram control */
+#define L2CR_L2WT 0x00080000 /* bit 12 - l2 write-through */
+#define L2CR_TS 0x00040000 /* bit 13 - test support on */
+#define L2CR_TS_OFF -L2CR_TS /* bit 13 - test support off */
+#define L2CR_L2OH_5 0x00000000 /* bits 14-15 - output hold time = short */
+#define L2CR_L2OH_1 0x00010000 /* bits 14-15 - output hold time = medium */
+#define L2CR_L2OH_INV 0x00020000 /* bits 14-15 - output hold time = long */
+#define L2CR_L2IP 0x00000001 /* global invalidate in progress */
+
+/*----------------------------------------------------------------
+ * BAT settings. Look in config_<BOARD>.h for the actual setup
+ */
+
+#define BATU_BL_128K 0x00000000
+#define BATU_BL_256K 0x00000004
+#define BATU_BL_512K 0x0000000c
+#define BATU_BL_1M 0x0000001c
+#define BATU_BL_2M 0x0000003c
+#define BATU_BL_4M 0x0000007c
+#define BATU_BL_8M 0x000000fc
+#define BATU_BL_16M 0x000001fc
+#define BATU_BL_32M 0x000003fc
+#define BATU_BL_64M 0x000007fc
+#define BATU_BL_128M 0x00000ffc
+#define BATU_BL_256M 0x00001ffc
+
+#define BATU_VS 0x00000002
+#define BATU_VP 0x00000001
+#define BATU_INVALID 0x00000000
+
+#define BATL_WRITETHROUGH 0x00000080
+#define BATL_CACHEINHIBIT 0x00000040
+#define BATL_COHERENT 0x00000020
+#define BATL_GUARDED 0x00000010
+
+#define BATL_NO_ACCESS 0x00000000
+#define BATL_RO 0x00000001
+#define BATL_RW 0x00000002
+
+#endif /* __MPC75X_H__ */
defined (CONFIG_DASA_SIM) || \
defined (CONFIG_ERIC) || \
defined (CONFIG_MOUSSE) || \
+ defined (CONFIG_BAB750) || \
defined (CONFIG_W7O)
/* $(CPU)/405gp_pci.c */
void pci_init (bd_t *);
void relocate_code (ulong, bd_t *, ulong);
ulong get_endaddr (void);
void trap_init (ulong);
-#ifdef CONFIG_4xx
+#if defined (CONFIG_4xx) || \
+ defined (CONFIG_74x) || \
+ defined (CONFIG_75x) || \
+ defined (CONFIG_74xx)
unsigned char in8(unsigned int);
void out8(unsigned int, unsigned char);
unsigned short in16(unsigned int);
defined(CONFIG_EVB64260) || \
defined(CONFIG_IOP480) || \
defined(CONFIG_MOUSSE) || \
+ defined(CONFIG_BAB750) || \
defined(CONFIG_SANDPOINT)
ulong get_gclk_freq (void);
ulong get_OPB_freq (void);
--- /dev/null
+/*
+ * (C) Copyright 2000
+ * Rob Taylor, Flying Pig Systems. robt@flyingpig.com.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+ /* winbond access routines and defines*/
+
+/* from the winbond data sheet -
+ The W83C553F SIO controller with PCI arbiter is a multi-function PCI device.
+ Function 0 is the ISA bridge, and Function 1 is the bus master IDE controller.
+*/
+
+/*ISA bridge configuration space*/
+
+#define W83C553F_VID 0x10AD
+#define W83C553F_DID 0x0565
+
+#define WINBOND_PCICONTR 0x40 /*pci control reg*/
+#define WINBOND_SGBAR 0x41 /*scatter/gather base address reg*/
+#define WINBOND_LBCR 0x42 /*Line Buffer Control reg*/
+#define WINBOND_IDEIRCR 0x43 /*IDE Interrupt Routing Control Reg*/
+#define WINBOND_PCIIRCR 0x44 /*PCI Interrupt Routing Control Reg*/
+#define WINBOND_BTBAR 0x46 /*BIOS Timer Base Address Register*/
+#define WINBOND_IPADCR 0x48 /*ISA to PCI Address Decoder Control Register*/
+#define WINBOND_IRADCR 0x49 /*ISA ROM Address Decoder Control Register*/
+#define WINBOND_IPMHSAR 0x4a /*ISA to PCI Memory Hole STart Address Register*/
+#define WINBOND_IPMHSR 0x4b /*ISA to PCI Memory Hols Size Register*/
+#define WINBOND_CDR 0x4c /*Clock Divisor Register*/
+#define WINBOND_CSCR 0x4d /*Chip Select Control Register*/
+#define WINBOND_ATSCR 0x4e /*AT System Control register*/
+#define WINBOND_ATBCR 0x4f /*AT Bus ControL Register*/
+#define WINBOND_IRQBEE0R 0x60 /*IRQ Break Event Enable 0 Register*/
+#define WINBOND_IRQBEE1R 0x61 /*IRQ Break Event Enable 1 Register*/
+#define WINBOND_ABEER 0x62 /*Additional Break Event Enable Register*/
+#define WINBOND_DMABEER 0x63 /*DMA Break Event Enable Register*/
+
+#define WINDOND_IDECSR 0x40 /*IDE Control/Status Register, Function 1*/
+
+#define IPADCR_MBE512 0x1
+#define IPADCR_MBE640 0x2
+#define IPADCR_IPATOM4 0x10
+#define IPADCR_IPATOM5 0x20
+#define IPADCR_IPATOM6 0x40
+#define IPADCR_IPATOM7 0x80
+
+#define CSCR_UBIOSCSE 0x10
+#define CSCR_BIOSWP 0x20
+
+#define IDECSR_P0EN 0x01
+#define IDECSR_P0F16 0x02
+#define IDECSR_P1EN 0x10
+#define IDECSR_P1F16 0x20
+#define IDECSR_LEGIRQ 0x800
+
+/*
+ * Interrupt controller
+ */
+#define W83C553F_PIC1_ICW1 CFG_ISA_IO + 0x20
+#define W83C553F_PIC1_ICW2 CFG_ISA_IO + 0x21
+#define W83C553F_PIC1_ICW3 CFG_ISA_IO + 0x21
+#define W83C553F_PIC1_ICW4 CFG_ISA_IO + 0x21
+#define W83C553F_PIC1_OCW1 CFG_ISA_IO + 0x21
+#define W83C553F_PIC1_OCW2 CFG_ISA_IO + 0x20
+#define W83C553F_PIC1_OCW3 CFG_ISA_IO + 0x20
+#define W83C553F_PIC1_ELC CFG_ISA_IO + 0x4D0
+#define W83C553F_PIC2_ICW1 CFG_ISA_IO + 0xA0
+#define W83C553F_PIC2_ICW2 CFG_ISA_IO + 0xA1
+#define W83C553F_PIC2_ICW3 CFG_ISA_IO + 0xA1
+#define W83C553F_PIC2_ICW4 CFG_ISA_IO + 0xA1
+#define W83C553F_PIC2_OCW1 CFG_ISA_IO + 0xA1
+#define W83C553F_PIC2_OCW2 CFG_ISA_IO + 0xA0
+#define W83C553F_PIC2_OCW3 CFG_ISA_IO + 0xA0
+#define W83C553F_PIC2_ELC CFG_ISA_IO + 0x4D1
+
+#define W83C553F_TMR1_CMOD CFG_ISA_IO + 0x43
+
+/*
+ * DMA controller
+ */
+#define W83C553F_DMA1 CFG_ISA_IO + 0x000 /* channel 0 - 3 */
+#define W83C553F_DMA2 CFG_ISA_IO + 0x0C0 /* channel 4 - 7 */
+
+/* command/status register bit definitions */
+
+#define W83C553F_CS_COM_DACKAL (1<<7) /* DACK# assert level */
+#define W83C553F_CS_COM_DREQSAL (1<<6) /* DREQ sense assert level */
+#define W83C553F_CS_COM_GAP (1<<4) /* group arbitration priority */
+#define W83C553F_CS_COM_CGE (1<<2) /* channel group enable */
+
+#define W83C553F_CS_STAT_CH0REQ (1<<4) /* channel 0 (4) DREQ status */
+#define W83C553F_CS_STAT_CH1REQ (1<<5) /* channel 1 (5) DREQ status */
+#define W83C553F_CS_STAT_CH2REQ (1<<6) /* channel 2 (6) DREQ status */
+#define W83C553F_CS_STAT_CH3REQ (1<<7) /* channel 3 (7) DREQ status */
+
+#define W83C553F_CS_STAT_CH0TC (1<<0) /* channel 0 (4) TC status */
+#define W83C553F_CS_STAT_CH1TC (1<<1) /* channel 1 (5) TC status */
+#define W83C553F_CS_STAT_CH2TC (1<<2) /* channel 2 (6) TC status */
+#define W83C553F_CS_STAT_CH3TC (1<<3) /* channel 3 (7) TC status */
+
+/* mode register bit definitions */
+
+#define W83C553F_MODE_TM_DEMAND (0<<6) /* transfer mode - demand */
+#define W83C553F_MODE_TM_SINGLE (1<<6) /* transfer mode - single */
+#define W83C553F_MODE_TM_BLOCK (2<<6) /* transfer mode - block */
+#define W83C553F_MODE_TM_CASCADE (3<<6) /* transfer mode - cascade */
+#define W83C553F_MODE_ADDRDEC (1<<5) /* address increment/decrement select */
+#define W83C553F_MODE_AUTOINIT (1<<4) /* autoinitialize enable */
+#define W83C553F_MODE_TT_VERIFY (0<<2) /* transfer type - verify */
+#define W83C553F_MODE_TT_WRITE (1<<2) /* transfer type - write */
+#define W83C553F_MODE_TT_READ (2<<2) /* transfer type - read */
+#define W83C553F_MODE_TT_ILLEGAL (3<<2) /* transfer type - illegal */
+#define W83C553F_MODE_CH0SEL (0<<0) /* channel 0 (4) select */
+#define W83C553F_MODE_CH1SEL (1<<0) /* channel 1 (5) select */
+#define W83C553F_MODE_CH2SEL (2<<0) /* channel 2 (6) select */
+#define W83C553F_MODE_CH3SEL (3<<0) /* channel 3 (7) select */
+
+/* request register bit definitions */
+
+#define W83C553F_REQ_CHSERREQ (1<<2) /* channel service request */
+#define W83C553F_REQ_CH0SEL (0<<0) /* channel 0 (4) select */
+#define W83C553F_REQ_CH1SEL (1<<0) /* channel 1 (5) select */
+#define W83C553F_REQ_CH2SEL (2<<0) /* channel 2 (6) select */
+#define W83C553F_REQ_CH3SEL (3<<0) /* channel 3 (7) select */
+
+/* write single mask bit register bit definitions */
+
+#define W83C553F_WSMB_CHMASKSEL (1<<2) /* channel mask select */
+#define W83C553F_WSMB_CH0SEL (0<<0) /* channel 0 (4) select */
+#define W83C553F_WSMB_CH1SEL (1<<0) /* channel 1 (5) select */
+#define W83C553F_WSMB_CH2SEL (2<<0) /* channel 2 (6) select */
+#define W83C553F_WSMB_CH3SEL (3<<0) /* channel 3 (7) select */
+
+/* read/write all mask bits register bit definitions */
+
+#define W83C553F_RWAMB_CH0MASK (1<<0) /* channel 0 (4) mask */
+#define W83C553F_RWAMB_CH1MASK (1<<1) /* channel 1 (5) mask */
+#define W83C553F_RWAMB_CH2MASK (1<<2) /* channel 2 (6) mask */
+#define W83C553F_RWAMB_CH3MASK (1<<3) /* channel 3 (7) mask */
+
+/* typedefs */
+
+#define W83C553F_DMA1_CS 0x8
+#define W83C553F_DMA1_WR 0x9
+#define W83C553F_DMA1_WSMB 0xA
+#define W83C553F_DMA1_WM 0xB
+#define W83C553F_DMA1_CBP 0xC
+#define W83C553F_DMA1_MC 0xD
+#define W83C553F_DMA1_CM 0xE
+#define W83C553F_DMA1_RWAMB 0xF
+
+#define W83C553F_DMA2_CS 0x10
+#define W83C553F_DMA2_WR 0x12
+#define W83C553F_DMA2_WSMB 0x14
+#define W83C553F_DMA2_WM 0x16
+#define W83C553F_DMA2_CBP 0x18
+#define W83C553F_DMA2_MC 0x1A
+#define W83C553F_DMA2_CM 0x1C
+#define W83C553F_DMA2_RWAMB 0x1E
+
+void initialise_w83c553f(void);
LIB = librtc.a
-OBJS = date.o pcf8563.o mpc8xx.o mc146818.o ds174x.o m48t35ax.o
+OBJS = date.o pcf8563.o mpc8xx.o mc146818.o ds174x.o m48t35ax.o mk48t59.o
all: $(LIB)
--- /dev/null
+/*
+ * (C) Copyright 2001 Sysgo Real-Time Solutions, GmbH <www.elinos.com>
+ * Andreas Heppel <aheppel@sysgo.de>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+/*
+ * Date & Time support for the MK48T59 RTC
+ */
+
+#undef RTC_DEBUG
+
+#include <ppcboot.h>
+#include <command.h>
+#include <config.h>
+#include <rtc.h>
+#include <mk48t59.h>
+
+#if defined(CONFIG_RTC_MK48T59)
+
+static uchar rtc_read (short reg)
+{
+ out8(RTC_PORT_ADDR0, reg & 0xFF);
+ out8(RTC_PORT_ADDR1, (reg>>8) & 0xFF);
+ return in8(RTC_PORT_DATA);
+}
+
+static void rtc_write (short reg, uchar val)
+{
+ out8(RTC_PORT_ADDR0, reg & 0xFF);
+ out8(RTC_PORT_ADDR1, (reg>>8) & 0xFF);
+ out8(RTC_PORT_DATA, val);
+}
+
+static unsigned bcd2bin (uchar n)
+{
+ return ((((n >> 4) & 0x0F) * 10) + (n & 0x0F));
+}
+
+static unsigned char bin2bcd (unsigned int n)
+{
+ return (((n / 10) << 4) | (n % 10));
+}
+
+/* ------------------------------------------------------------------------- */
+
+void *nvram_read(void *dest, const short src, size_t count)
+{
+ uchar *d = (uchar *) dest;
+ short s = src;
+
+ while (count--)
+ *d++ = rtc_read(s++);
+
+ return dest;
+}
+
+void nvram_write(short dest, const void *src, size_t count)
+{
+ short d = dest;
+ uchar *s = (uchar *) src;
+
+ while (count--)
+ rtc_write(d++, *s++);
+}
+
+#if (CONFIG_COMMANDS & CFG_CMD_DATE)
+
+/* ------------------------------------------------------------------------- */
+
+void rtc_get (struct rtc_time *tmp)
+{
+ uchar save_ctrl_a;
+ uchar sec, min, hour, mday, wday, mon, year;
+
+ /* Simple: freeze the clock, read it and allow updates again */
+ save_ctrl_a = rtc_read(RTC_CONTROLA);
+
+ /* Set the register to read the value. */
+ save_ctrl_a |= RTC_CA_READ;
+ rtc_write(RTC_CONTROLA, save_ctrl_a);
+
+ sec = rtc_read (RTC_SECONDS);
+ min = rtc_read (RTC_MINUTES);
+ hour = rtc_read (RTC_HOURS);
+ mday = rtc_read (RTC_DAY_OF_MONTH);
+ wday = rtc_read (RTC_DAY_OF_WEEK);
+ mon = rtc_read (RTC_MONTH);
+ year = rtc_read (RTC_YEAR);
+
+ /* re-enable update */
+ save_ctrl_a &= ~RTC_CA_READ;
+ rtc_write(RTC_CONTROLA, save_ctrl_a);
+
+#ifdef RTC_DEBUG
+ printf ( "Get RTC year: %02x mon/cent: %02x mday: %02x wday: %02x "
+ "hr: %02x min: %02x sec: %02x\n",
+ year, mon, mday, wday,
+ hour, min, sec );
+#endif
+ tmp->tm_sec = bcd2bin (sec & 0x7F);
+ tmp->tm_min = bcd2bin (min & 0x7F);
+ tmp->tm_hour = bcd2bin (hour & 0x3F);
+ tmp->tm_mday = bcd2bin (mday & 0x3F);
+ tmp->tm_mon = bcd2bin (mon & 0x1F);
+ tmp->tm_year = bcd2bin (year);
+ tmp->tm_wday = bcd2bin (wday & 0x07);
+ if(tmp->tm_year<70)
+ tmp->tm_year+=2000;
+ else
+ tmp->tm_year+=1900;
+ tmp->tm_yday = 0;
+ tmp->tm_isdst= 0;
+#ifdef RTC_DEBUG
+ printf ( "Get DATE: %4d-%02d-%02d (wday=%d) TIME: %2d:%02d:%02d\n",
+ tmp->tm_year, tmp->tm_mon, tmp->tm_mday, tmp->tm_wday,
+ tmp->tm_hour, tmp->tm_min, tmp->tm_sec);
+#endif
+}
+
+void rtc_set (struct rtc_time *tmp)
+{
+ uchar save_ctrl_a;
+
+#ifdef RTC_DEBUG
+ printf ( "Set DATE: %4d-%02d-%02d (wday=%d) TIME: %2d:%02d:%02d\n",
+ tmp->tm_year, tmp->tm_mon, tmp->tm_mday, tmp->tm_wday,
+ tmp->tm_hour, tmp->tm_min, tmp->tm_sec);
+#endif
+ save_ctrl_a = rtc_read(RTC_CONTROLA);
+
+ save_ctrl_a |= RTC_CA_WRITE;
+ rtc_write(RTC_CONTROLA, save_ctrl_a); /* disables the RTC to update the regs */
+
+ rtc_write (RTC_YEAR, bin2bcd(tmp->tm_year % 100));
+ rtc_write (RTC_MONTH, bin2bcd(tmp->tm_mon));
+
+ rtc_write (RTC_DAY_OF_WEEK, bin2bcd(tmp->tm_wday));
+ rtc_write (RTC_DAY_OF_MONTH, bin2bcd(tmp->tm_mday));
+ rtc_write (RTC_HOURS, bin2bcd(tmp->tm_hour));
+ rtc_write (RTC_MINUTES, bin2bcd(tmp->tm_min ));
+ rtc_write (RTC_SECONDS, bin2bcd(tmp->tm_sec ));
+
+ save_ctrl_a &= ~RTC_CA_WRITE;
+ rtc_write(RTC_CONTROLA, save_ctrl_a); /* enables the RTC to update the regs */
+}
+
+void rtc_reset (void)
+{
+ uchar control_b;
+
+ /*
+ * Start oscillator here.
+ */
+ control_b = rtc_read(RTC_CONTROLB);
+
+ control_b &= ~RTC_CB_STOP;
+ rtc_write(RTC_CONTROLB, control_b);
+}
+
+void rtc_set_watchdog(short multi, short res)
+{
+ uchar wd_value;
+
+ wd_value = RTC_WDS | ((multi & 0x1F) << 2) | (res & 0x3);
+ rtc_write(RTC_WATCHDOG, wd_value);
+}
+
+#endif /* (CONFIG_COMMANDS & CFG_CMD_DATE) */
+#endif /* CONFIG_RTC_MK48T59 */