mirror of
				git://git.openwrt.org/openwrt/openwrt.git
				synced 2025-11-03 14:34:27 -05:00 
			
		
		
		
	
		
			
				
	
	
		
			3052 lines
		
	
	
		
			76 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
			
		
		
	
	
			3052 lines
		
	
	
		
			76 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
From 3f21ef5f7b72937a1ae293e8ba6ebd0bb0b175e3 Mon Sep 17 00:00:00 2001
 | 
						|
From: Jingchang Lu <b35083@freescale.com>
 | 
						|
Date: Thu, 4 Aug 2011 09:59:49 +0800
 | 
						|
Subject: [PATCH 39/52] Add PCI bus driver for M54455EVB and M547X_8X
 | 
						|
 | 
						|
Signed-off-by: Jingchang Lu <b35083@freescale.com>
 | 
						|
---
 | 
						|
 arch/m68k/coldfire/m5445x/devices.c      |    9 +
 | 
						|
 arch/m68k/coldfire/m5445x/mcf5445x-pci.c |  721 +++++++++++++++++++++
 | 
						|
 arch/m68k/coldfire/m5445x/pci.c          |  247 +++++++
 | 
						|
 arch/m68k/coldfire/m547x/pci.c           | 1023 ++++++++++++++++++++++++++++++
 | 
						|
 arch/m68k/coldfire/m547x/pci_dummy.S     |   45 ++
 | 
						|
 arch/m68k/include/asm/5445x_pci.h        |  111 ++++
 | 
						|
 arch/m68k/include/asm/548x_pci.h         |   99 +++
 | 
						|
 arch/m68k/include/asm/pci.h              |    6 +
 | 
						|
 arch/m68k/kernel/bios32_mcf548x.c        |  632 ++++++++++++++++++
 | 
						|
 drivers/pci/Makefile                     |    1 +
 | 
						|
 drivers/pci/access.c                     |   18 +
 | 
						|
 drivers/pci/setup-bus.c                  |    6 +
 | 
						|
 lib/iomap.c                              |    4 +
 | 
						|
 13 files changed, 2922 insertions(+), 0 deletions(-)
 | 
						|
 create mode 100644 arch/m68k/coldfire/m5445x/mcf5445x-pci.c
 | 
						|
 create mode 100644 arch/m68k/coldfire/m5445x/pci.c
 | 
						|
 create mode 100644 arch/m68k/coldfire/m547x/pci.c
 | 
						|
 create mode 100644 arch/m68k/coldfire/m547x/pci_dummy.S
 | 
						|
 create mode 100644 arch/m68k/include/asm/5445x_pci.h
 | 
						|
 create mode 100644 arch/m68k/include/asm/548x_pci.h
 | 
						|
 create mode 100644 arch/m68k/kernel/bios32_mcf548x.c
 | 
						|
 | 
						|
--- a/arch/m68k/coldfire/m5445x/devices.c
 | 
						|
+++ b/arch/m68k/coldfire/m5445x/devices.c
 | 
						|
@@ -25,12 +25,15 @@
 | 
						|
 #include <linux/spi/mmc_spi.h>
 | 
						|
 #endif
 | 
						|
 
 | 
						|
+#include <linux/pci.h>
 | 
						|
+
 | 
						|
 #include <asm/coldfire.h>
 | 
						|
 #include <asm/mcfsim.h>
 | 
						|
 #include <asm/mcfuart.h>
 | 
						|
 #include <asm/mcfqspi.h>
 | 
						|
 #include <asm/mcfdspi.h>
 | 
						|
 #include <asm/cf_io.h>
 | 
						|
+#include <asm/pci.h>
 | 
						|
 
 | 
						|
 /* ATA Interrupt */
 | 
						|
 #define IRQ_ATA		(64 + 64 + 54)
 | 
						|
@@ -517,6 +520,12 @@ void m5445x_uarts_init(void)
 | 
						|
 
 | 
						|
 static int __init init_BSP(void)
 | 
						|
 {
 | 
						|
+#ifndef CONFIG_M54455_PCI_initcall
 | 
						|
+#if defined(CONFIG_M54455) && defined(CONFIG_PCI)
 | 
						|
+	pci_init();
 | 
						|
+	pcibios_init();
 | 
						|
+#endif
 | 
						|
+#endif
 | 
						|
 	m5445x_uarts_init();
 | 
						|
 	platform_add_devices(m5445x_devices, ARRAY_SIZE(m5445x_devices));
 | 
						|
 	return 0;
 | 
						|
--- /dev/null
 | 
						|
+++ b/arch/m68k/coldfire/m5445x/mcf5445x-pci.c
 | 
						|
@@ -0,0 +1,721 @@
 | 
						|
+/*
 | 
						|
+ * arch/m68k/coldfire/m5445x/mcf5445x-pci.c
 | 
						|
+ *
 | 
						|
+ * Coldfire M5445x specific PCI implementation.
 | 
						|
+ *
 | 
						|
+ * Copyright (C) 2007-2011 Freescale Semiconductor, Inc. All Rights Reserved.
 | 
						|
+ * Kurt Mahan <kmahan@freescale.com>
 | 
						|
+ */
 | 
						|
+
 | 
						|
+#include <linux/delay.h>
 | 
						|
+#include <linux/interrupt.h>
 | 
						|
+#include <linux/pci.h>
 | 
						|
+
 | 
						|
+#include <asm/mcfsim.h>
 | 
						|
+#include <asm/pci.h>
 | 
						|
+#include <asm/irq.h>
 | 
						|
+#include <asm/mcf5445x_pciarb.h>
 | 
						|
+#include <asm/mcf5445x_pci.h>
 | 
						|
+#include <asm/cf_io.h>
 | 
						|
+/*
 | 
						|
+ * Layout MCF5445x to PCI memory mappings:
 | 
						|
+ *
 | 
						|
+ *	WIN         MCF5445x                    PCI            TYPE
 | 
						|
+ *	---         --------                    ---            ----
 | 
						|
+ *     [0] 0xA0000000 -> 0xACFFFFFF  0xA0000000 -> 0xACFFFFFF  MEM
 | 
						|
+ *     [1] 0xAC000000 -> 0xAEFFFFFF  0xAC000000 -> 0xAEFFFFFF  IO
 | 
						|
+ *     [2] 0xAF000000 -> 0xAFFFFFFF  0xAF000000 -> 0xAFFFFFFF  CONFIG
 | 
						|
+ */
 | 
						|
+
 | 
						|
+void __iomem *pci_mem_map;
 | 
						|
+unsigned long pci_mem_mapsize = 256 * 1024 * 1024;
 | 
						|
+
 | 
						|
+#define MCF5445X_PCI_MEM_BASE		((unsigned int)pci_mem_map)
 | 
						|
+#define MCF5445X_PCI_MEM_BASE_PHY	0xA0000000
 | 
						|
+#define MCF5445X_PCI_MEM_SIZE		0x0C000000
 | 
						|
+
 | 
						|
+#define MCF5445X_PCI_IO_BASE		\
 | 
						|
+	(MCF5445X_PCI_MEM_BASE + MCF5445X_PCI_MEM_SIZE)
 | 
						|
+#define MCF5445X_PCI_IO_SIZE		0x03000000
 | 
						|
+
 | 
						|
+#define MCF5445X_PCI_CONFIG_BASE	\
 | 
						|
+	(MCF5445X_PCI_IO_BASE + MCF5445X_PCI_IO_SIZE)
 | 
						|
+#define MCF5445X_PCI_CONFIG_SIZE	0x01000000
 | 
						|
+
 | 
						|
+#define HOST_IO_BASE			\
 | 
						|
+	(MCF5445X_PCI_MEM_BASE + MCF5445X_PCI_MEM_SIZE)
 | 
						|
+#define PCI_IO_MASK			(MCF5445X_PCI_IO_SIZE - 1)
 | 
						|
+
 | 
						|
+#undef DEBUG
 | 
						|
+#ifdef DEBUG
 | 
						|
+# define DBG(x...) printk(x)
 | 
						|
+#else
 | 
						|
+# define DBG(x...)
 | 
						|
+#endif
 | 
						|
+
 | 
						|
+/* PCI Bus memory resource block */
 | 
						|
+struct resource pci_iomem_resource = {
 | 
						|
+	.name = "PCI memory space",
 | 
						|
+	.flags = IORESOURCE_MEM,
 | 
						|
+};
 | 
						|
+
 | 
						|
+/* PCI Bus ioport resource block */
 | 
						|
+struct resource pci_ioport_resource = {
 | 
						|
+	.name = "PCI I/O space",
 | 
						|
+	.flags = IORESOURCE_IO,
 | 
						|
+};
 | 
						|
+
 | 
						|
+/*
 | 
						|
+ * The M54455EVB multiplexes all the PCI interrupts via
 | 
						|
+ * the FPGA and routes them to a single interrupt.  The
 | 
						|
+ * PCI spec requires all PCI interrupt routines be smart
 | 
						|
+ * enough to sort out their own interrupts.
 | 
						|
+ * The interrupt source from the FPGA is configured
 | 
						|
+ * to EPORT 3.
 | 
						|
+ */
 | 
						|
+#define MCF5445X_PCI_IRQ		0x43
 | 
						|
+
 | 
						|
+#define PCI_SLOTS			4
 | 
						|
+
 | 
						|
+/*
 | 
						|
+ * FPGA Info
 | 
						|
+ */
 | 
						|
+#define FPGA_PCI_IRQ_ENABLE		(u32 *)0x09000000
 | 
						|
+#define FPGA_PCI_IRQ_STATUS		(u32 *)0x09000004
 | 
						|
+#define FPGA_PCI_IRQ_ROUTE		(u32 *)0x0900000c
 | 
						|
+#define FPGA_SEVEN_LED			(u32 *)0x09000014
 | 
						|
+
 | 
						|
+
 | 
						|
+/*
 | 
						|
+ * mcf5445x_conf_device(struct pci_dev *dev)
 | 
						|
+ *
 | 
						|
+ * Machine dependent Configure the given device.
 | 
						|
+ *
 | 
						|
+ * Parameters:
 | 
						|
+ *
 | 
						|
+ * dev		- the pci device.
 | 
						|
+ */
 | 
						|
+void
 | 
						|
+mcf5445x_conf_device(struct pci_dev *dev)
 | 
						|
+{
 | 
						|
+	set_fpga(FPGA_PCI_IRQ_ENABLE, 0x0f);
 | 
						|
+}
 | 
						|
+
 | 
						|
+/*
 | 
						|
+ * int mcf5445x_pci_config_read(unsigned int seg, unsigned int bus,
 | 
						|
+ *				unsigned int devfn, int reg,
 | 
						|
+ *				u32 *value)
 | 
						|
+ *
 | 
						|
+ * Read from PCI configuration space.
 | 
						|
+ *
 | 
						|
+ */
 | 
						|
+int mcf5445x_pci_config_read(unsigned int seg, unsigned int bus,
 | 
						|
+			unsigned int devfn, int reg, int len, u32 *value)
 | 
						|
+{
 | 
						|
+	u32 addr = MCF_PCI_PCICAR_BUSNUM(bus) |
 | 
						|
+		   MCF_PCI_PCICAR_DEVNUM(PCI_SLOT(devfn)) |
 | 
						|
+		   MCF_PCI_PCICAR_FUNCNUM(PCI_FUNC(devfn)) |
 | 
						|
+		   MCF_PCI_PCICAR_DWORD(reg) |
 | 
						|
+		   MCF_PCI_PCICAR_E;
 | 
						|
+
 | 
						|
+	if ((bus > 255) || (devfn > 255) || (reg > 255)) {
 | 
						|
+		*value = -1;
 | 
						|
+		return -EINVAL;
 | 
						|
+	}
 | 
						|
+
 | 
						|
+	/* setup for config mode */
 | 
						|
+	MCF_PCI_PCICAR = addr;
 | 
						|
+	__asm__ __volatile__("nop");
 | 
						|
+
 | 
						|
+	switch (len) {
 | 
						|
+	case 1:
 | 
						|
+		*value = *(volatile u8 *)(MCF5445X_PCI_CONFIG_BASE+(reg&3));
 | 
						|
+		break;
 | 
						|
+	case 2:
 | 
						|
+		*value = le16_to_cpu(*(volatile u16 *)
 | 
						|
+				(MCF5445X_PCI_CONFIG_BASE + (reg&2)));
 | 
						|
+		break;
 | 
						|
+	case 4:
 | 
						|
+		*value = le32_to_cpu(*(volatile u32 *)
 | 
						|
+				(MCF5445X_PCI_CONFIG_BASE));
 | 
						|
+		break;
 | 
						|
+	}
 | 
						|
+
 | 
						|
+	/* clear config mode */
 | 
						|
+	MCF_PCI_PCICAR = ~MCF_PCI_PCICAR_E;
 | 
						|
+	__asm__ __volatile__("nop");
 | 
						|
+
 | 
						|
+	return 0;
 | 
						|
+}
 | 
						|
+
 | 
						|
+/*
 | 
						|
+ * int mcf5445x_pci_config_write(unsigned int seg, unsigned int bus,
 | 
						|
+ *				unsigned int devfn, int reg,
 | 
						|
+ *				u32 *value)
 | 
						|
+ *
 | 
						|
+ * Write to PCI configuration space
 | 
						|
+ */
 | 
						|
+int mcf5445x_pci_config_write(unsigned int seg, unsigned int bus,
 | 
						|
+		    unsigned int devfn, int reg, int len, u32 value)
 | 
						|
+{
 | 
						|
+	u32 addr = MCF_PCI_PCICAR_BUSNUM(bus) |
 | 
						|
+		   MCF_PCI_PCICAR_DEVNUM(PCI_SLOT(devfn)) |
 | 
						|
+		   MCF_PCI_PCICAR_FUNCNUM(PCI_FUNC(devfn)) |
 | 
						|
+		   MCF_PCI_PCICAR_DWORD(reg) |
 | 
						|
+		   MCF_PCI_PCICAR_E;
 | 
						|
+
 | 
						|
+	if ((bus > 255) || (devfn > 255) || (reg > 255))
 | 
						|
+		return -EINVAL;
 | 
						|
+
 | 
						|
+	/* setup for config mode */
 | 
						|
+	MCF_PCI_PCICAR = addr;
 | 
						|
+	__asm__ __volatile__("nop");
 | 
						|
+
 | 
						|
+	switch (len) {
 | 
						|
+	case 1:
 | 
						|
+		*(volatile u8 *)(MCF5445X_PCI_CONFIG_BASE+(reg&3)) = (u8)value;
 | 
						|
+		break;
 | 
						|
+	case 2:
 | 
						|
+		*(volatile u16 *)(MCF5445X_PCI_CONFIG_BASE+(reg&2)) =
 | 
						|
+				cpu_to_le16((u16)value);
 | 
						|
+		break;
 | 
						|
+	case 4:
 | 
						|
+		*(volatile u32 *)(MCF5445X_PCI_CONFIG_BASE) =
 | 
						|
+				cpu_to_le32(value);
 | 
						|
+		break;
 | 
						|
+	}
 | 
						|
+
 | 
						|
+	/* clear config mode */
 | 
						|
+	MCF_PCI_PCICAR = ~MCF_PCI_PCICAR_E;
 | 
						|
+	__asm__ __volatile__("nop");
 | 
						|
+
 | 
						|
+	return 0;
 | 
						|
+}
 | 
						|
+
 | 
						|
+/* hardware operations */
 | 
						|
+static struct pci_raw_ops mcf5445x_pci_ops = {
 | 
						|
+	.read =		mcf5445x_pci_config_read,
 | 
						|
+	.write =	mcf5445x_pci_config_write,
 | 
						|
+};
 | 
						|
+
 | 
						|
+/************************************************************************/
 | 
						|
+
 | 
						|
+/*
 | 
						|
+ * u8 pci_inb()
 | 
						|
+ *
 | 
						|
+ * Read a byte at specified address from I/O space
 | 
						|
+ */
 | 
						|
+unsigned char pci_inb(long addr)
 | 
						|
+{
 | 
						|
+	char value;
 | 
						|
+
 | 
						|
+	value = *(volatile unsigned char *) (HOST_IO_BASE |
 | 
						|
+			(addr & PCI_IO_MASK));
 | 
						|
+	DBG("PCI: inb addr=0x%08X, value=0x%02X\n", addr, value);
 | 
						|
+
 | 
						|
+	return (unsigned char) value;
 | 
						|
+}
 | 
						|
+
 | 
						|
+
 | 
						|
+/*
 | 
						|
+ * u16 pci_inw()
 | 
						|
+ *
 | 
						|
+ * Read a word at specified address from I/O space
 | 
						|
+ */
 | 
						|
+unsigned short pci_inw(long addr)
 | 
						|
+{
 | 
						|
+	short value;
 | 
						|
+	volatile unsigned short *ptr;
 | 
						|
+
 | 
						|
+	ptr = (volatile unsigned short *) (HOST_IO_BASE | (addr & PCI_IO_MASK));
 | 
						|
+	value = le16_to_cpu(*ptr);
 | 
						|
+
 | 
						|
+	DBG("PCI: inw addr=0x%08X, value=0x%04X\n",  addr, value);
 | 
						|
+	return (unsigned short) value;
 | 
						|
+}
 | 
						|
+
 | 
						|
+/*
 | 
						|
+ * u16 pci_raw_inw()
 | 
						|
+ *
 | 
						|
+ * Read a raw word at specified address from I/O space
 | 
						|
+ */
 | 
						|
+unsigned short pci_raw_inw(long addr)
 | 
						|
+{
 | 
						|
+	short value;
 | 
						|
+	volatile unsigned short *ptr;
 | 
						|
+
 | 
						|
+	ptr = (volatile unsigned short *) (HOST_IO_BASE | (addr & PCI_IO_MASK));
 | 
						|
+	value = *ptr;
 | 
						|
+
 | 
						|
+	DBG("PCI: raw_inw addr=0x%08X, value=0x%04X\n",  addr, value);
 | 
						|
+	return (unsigned short) value;
 | 
						|
+}
 | 
						|
+
 | 
						|
+/*
 | 
						|
+ * u32 pci_inl()
 | 
						|
+ *
 | 
						|
+ * Read a dword at specified address from I/O space
 | 
						|
+ */
 | 
						|
+unsigned long pci_inl(long addr)
 | 
						|
+{
 | 
						|
+	long value;
 | 
						|
+	volatile unsigned long *ptr;
 | 
						|
+
 | 
						|
+	ptr = (volatile unsigned long *) (HOST_IO_BASE | (addr & PCI_IO_MASK));
 | 
						|
+	value = le32_to_cpu(*ptr);
 | 
						|
+
 | 
						|
+	DBG("PCI: inl addr=0x%08X, value=0x%08X\n",  addr, value);
 | 
						|
+	return (unsigned long) value;
 | 
						|
+}
 | 
						|
+
 | 
						|
+/*
 | 
						|
+ * u32 pci_raw_inl()
 | 
						|
+ *
 | 
						|
+ * Read a raw dword at specified address from I/O space
 | 
						|
+ */
 | 
						|
+unsigned long pci_raw_inl(long addr)
 | 
						|
+{
 | 
						|
+	long value;
 | 
						|
+	volatile unsigned long *ptr;
 | 
						|
+
 | 
						|
+	ptr = (volatile unsigned long *) (HOST_IO_BASE | (addr & PCI_IO_MASK));
 | 
						|
+	value = *ptr;
 | 
						|
+
 | 
						|
+	DBG("PCI: raw_inl addr=0x%08X, value=0x%08X\n",  addr, value);
 | 
						|
+	return (unsigned long) value;
 | 
						|
+}
 | 
						|
+
 | 
						|
+/*
 | 
						|
+ * void pci_outb()
 | 
						|
+ *
 | 
						|
+ * Write a byte value at specified address to I/O space
 | 
						|
+ */
 | 
						|
+void pci_outb(unsigned char value,  long addr)
 | 
						|
+{
 | 
						|
+
 | 
						|
+	*(volatile unsigned char *) (HOST_IO_BASE | (addr & PCI_IO_MASK)) \
 | 
						|
+		= value;
 | 
						|
+	DBG("PCI: outb addr=0x%08X, value=0x%02X\n",  addr, value);
 | 
						|
+}
 | 
						|
+
 | 
						|
+
 | 
						|
+/*
 | 
						|
+ * void pci_outw()
 | 
						|
+ *
 | 
						|
+ * Write a word value at specified address to I/O space
 | 
						|
+ */
 | 
						|
+void pci_outw(volatile unsigned short value, volatile  long addr)
 | 
						|
+{
 | 
						|
+	volatile unsigned short *ptr;
 | 
						|
+
 | 
						|
+	ptr = (volatile unsigned short *) (HOST_IO_BASE | (addr & PCI_IO_MASK));
 | 
						|
+	*ptr = cpu_to_le16(value);
 | 
						|
+	DBG("PCI: outw addr=0x%08X, value=0x%04X\n",  addr, value);
 | 
						|
+}
 | 
						|
+
 | 
						|
+/*
 | 
						|
+ * void pci_raw_outw()
 | 
						|
+ *
 | 
						|
+ * Write a raw word value at specified address to I/O space
 | 
						|
+ */
 | 
						|
+void pci_raw_outw(volatile unsigned short value, volatile  long addr)
 | 
						|
+{
 | 
						|
+	volatile unsigned short *ptr;
 | 
						|
+
 | 
						|
+	ptr = (volatile unsigned short *) (HOST_IO_BASE | (addr & PCI_IO_MASK));
 | 
						|
+	*ptr = value;
 | 
						|
+	DBG("PCI: raw_outw addr=0x%08X, value=0x%04X\n",  addr, value);
 | 
						|
+}
 | 
						|
+
 | 
						|
+/*
 | 
						|
+ * void pci_outl()
 | 
						|
+ *
 | 
						|
+ * Write a long word value at specified address to I/O space
 | 
						|
+ */
 | 
						|
+void pci_outl(volatile unsigned long value, volatile long addr)
 | 
						|
+{
 | 
						|
+	volatile unsigned long *ptr;
 | 
						|
+
 | 
						|
+	ptr = (volatile unsigned long *)(HOST_IO_BASE | (addr & PCI_IO_MASK));
 | 
						|
+	*ptr = cpu_to_le32(value);
 | 
						|
+	DBG("PCI: outl addr=0x%08X, value=0x%08X\n", addr, value);
 | 
						|
+}
 | 
						|
+
 | 
						|
+/*
 | 
						|
+ * void pci_raw_outl()
 | 
						|
+ *
 | 
						|
+ * Write a raw long word value at specified address to I/O space
 | 
						|
+ */
 | 
						|
+void pci_raw_outl(volatile unsigned long value, volatile long addr)
 | 
						|
+{
 | 
						|
+	volatile unsigned long *ptr;
 | 
						|
+
 | 
						|
+	ptr = (volatile unsigned long *)(HOST_IO_BASE | (addr & PCI_IO_MASK));
 | 
						|
+	*ptr = value;
 | 
						|
+	DBG("PCI: raw_outl addr=0x%08X, value=0x%08X\n", addr, value);
 | 
						|
+}
 | 
						|
+
 | 
						|
+/*
 | 
						|
+ * void pci_insb()
 | 
						|
+ *
 | 
						|
+ * Read several byte values from specified I/O port
 | 
						|
+ */
 | 
						|
+void pci_insb(volatile unsigned char *addr, unsigned char *buf, int len)
 | 
						|
+{
 | 
						|
+	for (; len--; buf++)
 | 
						|
+		*buf = pci_inb((unsigned long)addr);
 | 
						|
+	DBG("PCI: pci_insb addr=0x%08X, buf=%p, len=%d\n", addr, buf, len);
 | 
						|
+}
 | 
						|
+
 | 
						|
+
 | 
						|
+/*
 | 
						|
+ * void pci_insw()
 | 
						|
+ *
 | 
						|
+ * Read several word values from specified I/O port
 | 
						|
+ */
 | 
						|
+void pci_insw(volatile unsigned short *addr, unsigned short *buf, int len)
 | 
						|
+{
 | 
						|
+	for (; len--; buf++)
 | 
						|
+		*buf = pci_inw((unsigned long)addr);
 | 
						|
+	DBG("PCI: pci_insw addr=0x%08X, buf=%p, len=%d\n", addr, buf, len);
 | 
						|
+}
 | 
						|
+
 | 
						|
+/*
 | 
						|
+ * void pci_insl()
 | 
						|
+ *
 | 
						|
+ * Read several dword values from specified I/O port
 | 
						|
+ */
 | 
						|
+void pci_insl(volatile unsigned long *addr, unsigned long *buf, int len)
 | 
						|
+{
 | 
						|
+	for (; len--; buf++)
 | 
						|
+		*buf = pci_inl((unsigned long)addr);
 | 
						|
+	DBG("PCI: pci_insl addr=0x%08X, buf=%p, len=%d\n", addr, buf, len);
 | 
						|
+}
 | 
						|
+
 | 
						|
+/*
 | 
						|
+ * void pci_outsb()
 | 
						|
+ *
 | 
						|
+ * Write several byte values to specified I/O port
 | 
						|
+ */
 | 
						|
+void pci_outsb(volatile unsigned char *addr, const unsigned char *buf, int len)
 | 
						|
+{
 | 
						|
+	for (; len--; buf++)
 | 
						|
+		pci_outb((unsigned long)addr, *buf);
 | 
						|
+	DBG("PCI: pci_outsb addr=0x%08X, buf=%p, len=%d\n", addr, buf, len);
 | 
						|
+}
 | 
						|
+
 | 
						|
+/*
 | 
						|
+ * void pci_outsw()
 | 
						|
+ *
 | 
						|
+ * Write several word values to specified I/O port
 | 
						|
+ */
 | 
						|
+void
 | 
						|
+pci_outsw(volatile unsigned short *addr, const unsigned short *buf, int len)
 | 
						|
+{
 | 
						|
+	for (; len--; buf++)
 | 
						|
+		pci_outw((unsigned long)addr, *buf);
 | 
						|
+	DBG("PCI: pci_outsw addr=0x%08X, buf=%p, len=%d\n", addr, buf, len);
 | 
						|
+}
 | 
						|
+
 | 
						|
+/*
 | 
						|
+ * void pci_outsl()
 | 
						|
+ *
 | 
						|
+ * Write several dword values to specified I/O port
 | 
						|
+ */
 | 
						|
+void pci_outsl(volatile unsigned long *addr, const unsigned long *buf, int len)
 | 
						|
+{
 | 
						|
+	for (; len--; buf++)
 | 
						|
+		pci_outl((unsigned long)addr, *buf);
 | 
						|
+	DBG("PCI: pci_outsl addr=0x%08X, buf=%p, len=%d\n", addr, buf, len);
 | 
						|
+}
 | 
						|
+/*
 | 
						|
+ * irqreturn_t mcf5445x_pci_interrupt( int irq, void *dev)
 | 
						|
+ *
 | 
						|
+ * PCI controller interrupt handler.
 | 
						|
+ */
 | 
						|
+static irqreturn_t
 | 
						|
+mcf5445x_pci_interrupt(int irq, void *dev)
 | 
						|
+{
 | 
						|
+	u32 status = MCF_PCI_PCIGSCR;
 | 
						|
+#ifdef DEBUG
 | 
						|
+	printk(KERN_INFO "PCI: Controller irq status=0x%08x\n", status);
 | 
						|
+#endif
 | 
						|
+	/* clear */
 | 
						|
+	MCF_PCI_PCIGSCR = status;
 | 
						|
+
 | 
						|
+	return IRQ_HANDLED;
 | 
						|
+}
 | 
						|
+
 | 
						|
+/*
 | 
						|
+ * irqreturn_t mcf5445x_pci_arb_interrupt( int irq, void *dev)
 | 
						|
+ *
 | 
						|
+ * PCI Arbiter interrupt handler.
 | 
						|
+ */
 | 
						|
+static irqreturn_t
 | 
						|
+mcf5445x_pci_arb_interrupt(int irq, void *dev)
 | 
						|
+{
 | 
						|
+	u32 status = MCF_PCIARB_PASR;
 | 
						|
+#ifdef DEBUG
 | 
						|
+	printk(KERN_INFO "PCI: Arbiter irq status=0x%08x\n", status);
 | 
						|
+#endif
 | 
						|
+	/* clear */
 | 
						|
+	MCF_PCIARB_PASR = status;
 | 
						|
+	return IRQ_HANDLED;
 | 
						|
+}
 | 
						|
+
 | 
						|
+/*
 | 
						|
+ * struct pci_bus_info *init_mcf5445x_pci(void)
 | 
						|
+ *
 | 
						|
+ * Machine specific initialisation:
 | 
						|
+ *
 | 
						|
+ * - Allocate and initialise a 'pci_bus_info' structure
 | 
						|
+ * - Initialize hardware
 | 
						|
+ *
 | 
						|
+ * Result: pointer to 'pci_bus_info' structure.
 | 
						|
+ */
 | 
						|
+int __init
 | 
						|
+init_mcf5445x_pci(void)
 | 
						|
+{
 | 
						|
+	/*
 | 
						|
+	 * Initialize the PCI core
 | 
						|
+	 */
 | 
						|
+	printk(KERN_INFO "init_mcf5445x_pci\n");
 | 
						|
+
 | 
						|
+	/* pci memory mapping */
 | 
						|
+	pci_mem_map = ioremap(MCF5445X_PCI_MEM_BASE_PHY, pci_mem_mapsize);
 | 
						|
+	if (!pci_mem_map) {
 | 
						|
+		printk(KERN_ERR "PCI memory map failed by ioremap!\n");
 | 
						|
+		return -ENOMEM;
 | 
						|
+	}
 | 
						|
+	printk(KERN_INFO "MCF5445X_PCI_MEM_BASE value is 0x%x\n", \
 | 
						|
+			MCF5445X_PCI_MEM_BASE);
 | 
						|
+
 | 
						|
+	/* Initialize pci resource */
 | 
						|
+	pci_iomem_resource.start = MCF5445X_PCI_MEM_BASE;
 | 
						|
+	pci_iomem_resource.end = MCF5445X_PCI_MEM_BASE + \
 | 
						|
+				 MCF5445X_PCI_MEM_SIZE - 1;
 | 
						|
+
 | 
						|
+	pci_ioport_resource.start = MCF5445X_PCI_IO_BASE;
 | 
						|
+	pci_ioport_resource.end = MCF5445X_PCI_IO_BASE + \
 | 
						|
+				  MCF5445X_PCI_IO_SIZE - 1;
 | 
						|
+
 | 
						|
+	/*
 | 
						|
+	* Must Reset!!! If bootloader has PCI enabled, it will cause
 | 
						|
+	* problem in linux when it tries to configure/find resources
 | 
						|
+	* for the pci devices
 | 
						|
+	*/
 | 
						|
+	MCF_PCI_PCIGSCR = 1;
 | 
						|
+
 | 
						|
+	/* arbitration controller */
 | 
						|
+	MCF_PCIARB_PACR = MCF_PCIARB_PACR_INTMPRI |
 | 
						|
+			  MCF_PCIARB_PACR_EXTMPRI(0x0f) |
 | 
						|
+			  MCF_PCIARB_PACR_INTMINTEN |
 | 
						|
+			  MCF_PCIARB_PACR_EXTMINTEN(0x0f);
 | 
						|
+
 | 
						|
+	/* pci pin assignment regs */
 | 
						|
+#if defined(CONFIG_PATA_FSL) || defined(CONFIG_PATA_FSL_MODULE)
 | 
						|
+	MCF_GPIO_PAR_PCI = MCF_GPIO_PAR_PCI_GNT0 |
 | 
						|
+			MCF_GPIO_PAR_PCI_GNT1 |
 | 
						|
+			MCF_GPIO_PAR_PCI_GNT2 |
 | 
						|
+			MCF_GPIO_PAR_PCI_GNT3_GNT3 |
 | 
						|
+			MCF_GPIO_PAR_PCI_REQ0 |
 | 
						|
+			MCF_GPIO_PAR_PCI_REQ1 |
 | 
						|
+			MCF_GPIO_PAR_PCI_REQ2 |
 | 
						|
+			MCF_GPIO_PAR_PCI_REQ3_REQ3;
 | 
						|
+
 | 
						|
+	MCF_GPIO_PAR_PCI = (MCF_GPIO_PAR_PCI &
 | 
						|
+			(MCF_GPIO_PAR_PCI_GNT3_MASK &
 | 
						|
+			 MCF_GPIO_PAR_PCI_REQ3_MASK)) |
 | 
						|
+			MCF_GPIO_PAR_PCI_GNT3_ATA_DMACK |
 | 
						|
+			MCF_GPIO_PAR_PCI_REQ3_ATA_INTRQ;
 | 
						|
+#else
 | 
						|
+	MCF_GPIO_PAR_PCI = MCF_GPIO_PAR_PCI_GNT0 |
 | 
						|
+			   MCF_GPIO_PAR_PCI_GNT1 |
 | 
						|
+			   MCF_GPIO_PAR_PCI_GNT2 |
 | 
						|
+			   MCF_GPIO_PAR_PCI_GNT3_GNT3 |
 | 
						|
+			   MCF_GPIO_PAR_PCI_REQ0 |
 | 
						|
+			   MCF_GPIO_PAR_PCI_REQ1 |
 | 
						|
+			   MCF_GPIO_PAR_PCI_REQ2 |
 | 
						|
+			   MCF_GPIO_PAR_PCI_REQ3_REQ3;
 | 
						|
+#endif
 | 
						|
+	/* target control reg */
 | 
						|
+	MCF_PCI_PCITCR = MCF_PCI_PCITCR_P |
 | 
						|
+			 MCF_PCI_PCITCR_WCT(8);
 | 
						|
+
 | 
						|
+	/* PCI MEM address */
 | 
						|
+	MCF_PCI_PCIIW0BTAR = MCF5445X_PCI_MEM_BASE_PHY |
 | 
						|
+			     (MCF5445X_PCI_MEM_BASE >> 16);
 | 
						|
+
 | 
						|
+	/* PCI MEM address */
 | 
						|
+	MCF_PCI_PCIIW1BTAR = (MCF5445X_PCI_MEM_BASE_PHY +
 | 
						|
+				MCF5445X_PCI_MEM_SIZE)
 | 
						|
+				| (MCF5445X_PCI_IO_BASE >> 16);
 | 
						|
+
 | 
						|
+	/* PCI IO address */
 | 
						|
+	MCF_PCI_PCIIW2BTAR = (MCF5445X_PCI_MEM_BASE_PHY +
 | 
						|
+				MCF5445X_PCI_MEM_SIZE + MCF5445X_PCI_IO_SIZE)
 | 
						|
+				| (MCF5445X_PCI_CONFIG_BASE >> 16);
 | 
						|
+
 | 
						|
+	/* window control */
 | 
						|
+	MCF_PCI_PCIIWCR = MCF_PCI_PCIIWCR_WINCTRL0_ENABLE |
 | 
						|
+			  MCF_PCI_PCIIWCR_WINCTRL0_MEMREAD |
 | 
						|
+			  MCF_PCI_PCIIWCR_WINCTRL1_ENABLE |
 | 
						|
+			  MCF_PCI_PCIIWCR_WINCTRL1_IO |
 | 
						|
+			  MCF_PCI_PCIIWCR_WINCTRL2_ENABLE |
 | 
						|
+			  MCF_PCI_PCIIWCR_WINCTRL2_IO;
 | 
						|
+
 | 
						|
+	/* initiator control reg */
 | 
						|
+	MCF_PCI_PCIICR = 0;
 | 
						|
+
 | 
						|
+	/* type 0 - command */
 | 
						|
+	MCF_PCI_PCISCR = MCF_PCI_PCISCR_MW |	/* mem write/inval */
 | 
						|
+			 MCF_PCI_PCISCR_B |	/* bus master enable */
 | 
						|
+			 MCF_PCI_PCISCR_MA |	/* clear master abort error */
 | 
						|
+			 MCF_PCI_PCISCR_M;	/* mem access enable */
 | 
						|
+
 | 
						|
+	/* type 0 - config reg */
 | 
						|
+	MCF_PCI_PCICR1 = MCF_PCI_PCICR1_CACHELINESIZE(4) |
 | 
						|
+			 MCF_PCI_PCICR1_LATTIMER(0xFF);
 | 
						|
+	/* type 0 - config 2 reg */
 | 
						|
+	MCF_PCI_PCICR2 = 0;
 | 
						|
+
 | 
						|
+	/* target control reg */
 | 
						|
+	MCF_PCI_PCITCR2 = MCF_PCI_PCITCR2_B0E | MCF_PCI_PCITCR2_B5E;
 | 
						|
+
 | 
						|
+	/* translate addresses from PCI[0] to CF[SDRAM] */
 | 
						|
+	MCF_PCI_PCITBATR0 = 0xFC000000 | MCF_PCI_PCITBATR5_EN;
 | 
						|
+	MCF_PCI_PCITBATR5 = MCF_RAMBAR1 | MCF_PCI_PCITBATR5_EN;
 | 
						|
+
 | 
						|
+	/* inbound window for memory */
 | 
						|
+	MCF_PCI_PCIBAR0 = 0xFC000000;
 | 
						|
+	MCF_PCI_PCIBAR5 = MCF_RAMBAR1;
 | 
						|
+
 | 
						|
+	/* setup controller interrupt handlers */
 | 
						|
+	if (request_irq(55+128, mcf5445x_pci_interrupt, IRQF_SHARED,
 | 
						|
+			"PCI Controller", NULL))
 | 
						|
+		printk(KERN_ERR "PCI: Unable to register controller irq\n");
 | 
						|
+
 | 
						|
+	if (request_irq(56+128, mcf5445x_pci_arb_interrupt, IRQF_SHARED,
 | 
						|
+			"PCI Arbiter", NULL))
 | 
						|
+		printk(KERN_ERR "PCI: Unable to register arbiter irq\n");
 | 
						|
+
 | 
						|
+	/* global control - clear reset bit */
 | 
						|
+	MCF_PCI_PCIGSCR = MCF_PCI_PCIGSCR_SEE |
 | 
						|
+			  MCF_PCI_PCIGSCR_PEE;
 | 
						|
+
 | 
						|
+	/* let everything settle */
 | 
						|
+	udelay(1000);
 | 
						|
+
 | 
						|
+	/* allocate bus ioport resource */
 | 
						|
+	if (request_resource(&ioport_resource, &pci_ioport_resource) < 0)
 | 
						|
+		printk(KERN_ERR "PCI: Unable to alloc ioport resource\n");
 | 
						|
+
 | 
						|
+	/* allocate bus iomem resource */
 | 
						|
+	if (request_resource(&iomem_resource, &pci_iomem_resource) < 0)
 | 
						|
+		printk(KERN_ERR "PCI: Unable to alloc iomem resource\n");
 | 
						|
+
 | 
						|
+	/* setup FPGA to route PCI to IRQ3(67), SW7 to IRQ7, SW6 to IRQ4 */
 | 
						|
+	set_fpga(FPGA_PCI_IRQ_ENABLE, 0x00000000);
 | 
						|
+	set_fpga(FPGA_PCI_IRQ_ROUTE, 0x00000039);
 | 
						|
+	set_fpga(FPGA_SEVEN_LED, 0x000000FF);
 | 
						|
+
 | 
						|
+	raw_pci_ops = &mcf5445x_pci_ops;
 | 
						|
+#ifdef DEBUG
 | 
						|
+	mcf5445x_pci_dumpregs();
 | 
						|
+#endif
 | 
						|
+	return 0;
 | 
						|
+}
 | 
						|
+
 | 
						|
+/*
 | 
						|
+ * DEBUGGING
 | 
						|
+ */
 | 
						|
+
 | 
						|
+#ifdef DEBUG
 | 
						|
+struct regdump {
 | 
						|
+	u32 addr;
 | 
						|
+	char regname[16];
 | 
						|
+};
 | 
						|
+
 | 
						|
+struct regdump type0regs[] = {
 | 
						|
+	{ 0xfc0a8000, "PCIIDR" },
 | 
						|
+	{ 0xfc0a8004, "PCISCR" },
 | 
						|
+	{ 0xfc0a8008, "PCICCRIR" },
 | 
						|
+	{ 0xfc0a800c, "PCICR1" },
 | 
						|
+	{ 0xfc0a8010, "PCIBAR0" },
 | 
						|
+	{ 0xfc0a8014, "PCIBAR1" },
 | 
						|
+	{ 0xfc0a8018, "PCIBAR2" },
 | 
						|
+	{ 0xfc0a801c, "PCIBAR3" },
 | 
						|
+	{ 0xfc0a8020, "PCIBAR4" },
 | 
						|
+	{ 0xfc0a8024, "PCIBAR5" },
 | 
						|
+	{ 0xfc0a8028, "PCICCPR" },
 | 
						|
+	{ 0xfc0a802c, "PCISID" },
 | 
						|
+	{ 0xfc0a8030, "PCIERBAR" },
 | 
						|
+	{ 0xfc0a8034, "PCICPR" },
 | 
						|
+	{ 0xfc0a803c, "PCICR2" },
 | 
						|
+	{ 0, "" }
 | 
						|
+};
 | 
						|
+
 | 
						|
+struct regdump genregs[] = {
 | 
						|
+	{ 0xfc0a8060, "PCIGSCR" },
 | 
						|
+	{ 0xfc0a8064, "PCITBATR0" },
 | 
						|
+	{ 0xfc0a8068, "PCITBATR1" },
 | 
						|
+	{ 0xfc0a806c, "PCITCR1" },
 | 
						|
+	{ 0xfc0a8070, "PCIIW0BTAR" },
 | 
						|
+	{ 0xfc0a8074, "PCIIW1BTAR" },
 | 
						|
+	{ 0xfc0a8078, "PCIIW2BTAR" },
 | 
						|
+	{ 0xfc0a8080, "PCIIWCR" },
 | 
						|
+	{ 0xfc0a8084, "PCIICR" },
 | 
						|
+	{ 0xfc0a8088, "PCIISR" },
 | 
						|
+	{ 0xfc0a808c, "PCITCR2" },
 | 
						|
+	{ 0xfc0a8090, "PCITBATR0" },
 | 
						|
+	{ 0xfc0a8094, "PCITBATR1" },
 | 
						|
+	{ 0xfc0a8098, "PCITBATR2" },
 | 
						|
+	{ 0xfc0a809c, "PCITBATR3" },
 | 
						|
+	{ 0xfc0a80a0, "PCITBATR4" },
 | 
						|
+	{ 0xfc0a80a4, "PCITBATR5" },
 | 
						|
+	{ 0xfc0a80a8, "PCIINTR" },
 | 
						|
+	{ 0xfc0a80f8, "PCICAR" },
 | 
						|
+	{ 0, "" }
 | 
						|
+};
 | 
						|
+
 | 
						|
+struct regdump arbregs[] = {
 | 
						|
+	{ 0xfc0ac000, "PACR" },
 | 
						|
+	{ 0xfc0ac004, "PASR" },	/* documentation error */
 | 
						|
+	{ 0, "" }
 | 
						|
+};
 | 
						|
+
 | 
						|
+/*
 | 
						|
+ * void mcf5445x_pci_dumpregs()
 | 
						|
+ *
 | 
						|
+ * Dump out all the PCI registers
 | 
						|
+ */
 | 
						|
+void
 | 
						|
+mcf5445x_pci_dumpregs(void)
 | 
						|
+{
 | 
						|
+	struct regdump *reg;
 | 
						|
+
 | 
						|
+	printk(KERN_INFO "*** MCF5445x PCI TARGET 0 REGISTERS ***\n");
 | 
						|
+
 | 
						|
+	reg = type0regs;
 | 
						|
+	while (reg->addr) {
 | 
						|
+		printk(KERN_INFO "0x%08x  0x%08x  %s\n", reg->addr,
 | 
						|
+			*((u32 *)reg->addr), reg->regname);
 | 
						|
+		reg++;
 | 
						|
+	}
 | 
						|
+
 | 
						|
+	printk(KERN_INFO "\n*** MCF5445x PCI GENERAL REGISTERS ***\n");
 | 
						|
+	reg = genregs;
 | 
						|
+	while (reg->addr) {
 | 
						|
+		printk(KERN_INFO "0x%08x  0x%08x  %s\n", reg->addr,
 | 
						|
+			*((u32 *)reg->addr), reg->regname);
 | 
						|
+		reg++;
 | 
						|
+	}
 | 
						|
+	printk(KERN_INFO "\n*** MCF5445x PCI ARBITER REGISTERS ***\n");
 | 
						|
+	reg = arbregs;
 | 
						|
+	while (reg->addr) {
 | 
						|
+		printk(KERN_INFO "0x%08x  0x%08x  %s\n", reg->addr,
 | 
						|
+			*((u32 *)reg->addr), reg->regname);
 | 
						|
+		reg++;
 | 
						|
+	}
 | 
						|
+}
 | 
						|
+#endif /* DEBUG */
 | 
						|
--- /dev/null
 | 
						|
+++ b/arch/m68k/coldfire/m5445x/pci.c
 | 
						|
@@ -0,0 +1,247 @@
 | 
						|
+/*
 | 
						|
+ * linux/arch/m68k/coldfire/m5445x/pci.c
 | 
						|
+ *
 | 
						|
+ * PCI initialization for Coldfire architectures.
 | 
						|
+ *
 | 
						|
+ * Currently Supported:
 | 
						|
+ *	M5445x
 | 
						|
+ *
 | 
						|
+ * Copyright (C) 2007-2011 Freescale Semiconductor, Inc. All Rights Reserved.
 | 
						|
+ * Kurt Mahan <kmahan@freescale.com>
 | 
						|
+ */
 | 
						|
+
 | 
						|
+#include <linux/kernel.h>
 | 
						|
+#include <linux/init.h>
 | 
						|
+#include <linux/pci.h>
 | 
						|
+
 | 
						|
+#include <asm/mcfsim.h>
 | 
						|
+#include <asm/pci.h>
 | 
						|
+
 | 
						|
+/* pci ops for reading/writing config */
 | 
						|
+struct pci_raw_ops *raw_pci_ops;
 | 
						|
+
 | 
						|
+/* pci debug flag */
 | 
						|
+static int debug_pci;
 | 
						|
+
 | 
						|
+static int
 | 
						|
+pci_read(struct pci_bus *bus, unsigned int devfn, int where,
 | 
						|
+	 int size, u32 *value)
 | 
						|
+{
 | 
						|
+	return raw_pci_ops->read(0, bus->number, devfn, where, size, value);
 | 
						|
+}
 | 
						|
+
 | 
						|
+static int
 | 
						|
+pci_write(struct pci_bus *bus, unsigned int devfn, int where,
 | 
						|
+	  int size, u32 value)
 | 
						|
+{
 | 
						|
+	return raw_pci_ops->write(0, bus->number, devfn, where, size, value);
 | 
						|
+}
 | 
						|
+
 | 
						|
+struct pci_ops pci_root_ops = {
 | 
						|
+	.read = pci_read,
 | 
						|
+	.write = pci_write,
 | 
						|
+};
 | 
						|
+
 | 
						|
+/*
 | 
						|
+ * pcibios_setup(char *)
 | 
						|
+ *
 | 
						|
+ * Initialize the pcibios based on cmd line params.
 | 
						|
+ */
 | 
						|
+char *
 | 
						|
+pcibios_setup(char *str)
 | 
						|
+{
 | 
						|
+	if (!strcmp(str, "debug")) {
 | 
						|
+		debug_pci = 1;
 | 
						|
+		return NULL;
 | 
						|
+	}
 | 
						|
+	return str;
 | 
						|
+}
 | 
						|
+
 | 
						|
+/*
 | 
						|
+ * We need to avoid collisions with `mirrored' VGA ports
 | 
						|
+ * and other strange ISA hardware, so we always want the
 | 
						|
+ * addresses to be allocated in the 0x000-0x0ff region
 | 
						|
+ * modulo 0x400.
 | 
						|
+ *
 | 
						|
+ * Why? Because some silly external IO cards only decode
 | 
						|
+ * the low 10 bits of the IO address. The 0x00-0xff region
 | 
						|
+ * is reserved for motherboard devices that decode all 16
 | 
						|
+ * bits, so it's ok to allocate at, say, 0x2800-0x28ff,
 | 
						|
+ * but we want to try to avoid allocating at 0x2900-0x2bff
 | 
						|
+ * which might have be mirrored at 0x0100-0x03ff..
 | 
						|
+ */
 | 
						|
+resource_size_t
 | 
						|
+pcibios_align_resource(void *data, const struct resource *res,
 | 
						|
+		resource_size_t size, resource_size_t align)
 | 
						|
+{
 | 
						|
+	struct pci_dev *dev = data;
 | 
						|
+	resource_size_t start = res->start;
 | 
						|
+
 | 
						|
+	if (res->flags & IORESOURCE_IO) {
 | 
						|
+		if (size > 0x100)
 | 
						|
+			printk(KERN_ERR "PCI: I/O Region %s/%d too large"
 | 
						|
+			       " (%ld bytes)\n", pci_name(dev),
 | 
						|
+			       dev->resource - res, (long int)size);
 | 
						|
+
 | 
						|
+		if (start & 0x3ff)
 | 
						|
+			start = (start + 0x3ff) & ~0x3ff;
 | 
						|
+	}
 | 
						|
+
 | 
						|
+	return start;
 | 
						|
+}
 | 
						|
+EXPORT_SYMBOL(pcibios_align_resource);
 | 
						|
+
 | 
						|
+/*
 | 
						|
+ * Swizzle the device pin each time we cross a bridge
 | 
						|
+ * and return the slot number.
 | 
						|
+ */
 | 
						|
+static u8 __devinit
 | 
						|
+pcibios_swizzle(struct pci_dev *dev, u8 *pin)
 | 
						|
+{
 | 
						|
+	return 0;
 | 
						|
+}
 | 
						|
+
 | 
						|
+/*
 | 
						|
+ * Map a slot/pin to an IRQ.
 | 
						|
+ */
 | 
						|
+static int
 | 
						|
+pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
 | 
						|
+{
 | 
						|
+	return 0x43;
 | 
						|
+}
 | 
						|
+
 | 
						|
+/*
 | 
						|
+ * pcibios_update_irq(struct pci_dev *dev, int irq)
 | 
						|
+ *
 | 
						|
+ * Update a PCI interrupt.
 | 
						|
+ */
 | 
						|
+void
 | 
						|
+pcibios_update_irq(struct pci_dev *dev, int irq)
 | 
						|
+{
 | 
						|
+	pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq);
 | 
						|
+}
 | 
						|
+
 | 
						|
+/*
 | 
						|
+ * pcibios_enable_device(struct pci_dev *dev, int mask)
 | 
						|
+ *
 | 
						|
+ * Enable a device on the PCI bus.
 | 
						|
+ */
 | 
						|
+int
 | 
						|
+pcibios_enable_device(struct pci_dev *dev, int mask)
 | 
						|
+{
 | 
						|
+	u16 cmd, old_cmd;
 | 
						|
+	int idx;
 | 
						|
+	struct resource *r;
 | 
						|
+
 | 
						|
+	pci_read_config_word(dev, PCI_COMMAND, &cmd);
 | 
						|
+	old_cmd = cmd;
 | 
						|
+	for (idx = 0; idx < DEVICE_COUNT_RESOURCE; idx++) {
 | 
						|
+		r = &dev->resource[idx];
 | 
						|
+		if (!r->start && r->end) {
 | 
						|
+			printk(KERN_ERR "PCI: Device %s not available because "
 | 
						|
+			       "of resource collisions\n", pci_name(dev));
 | 
						|
+			return -EINVAL;
 | 
						|
+		}
 | 
						|
+		if (r->flags & IORESOURCE_IO)
 | 
						|
+			cmd |= PCI_COMMAND_IO;
 | 
						|
+		if (r->flags & IORESOURCE_MEM)
 | 
						|
+			cmd |= PCI_COMMAND_MEMORY;
 | 
						|
+	}
 | 
						|
+	if (cmd != old_cmd) {
 | 
						|
+		printk("PCI: Enabling device %s (%04x -> %04x)\n",
 | 
						|
+		       pci_name(dev), old_cmd, cmd);
 | 
						|
+		pci_write_config_word(dev, PCI_COMMAND, cmd);
 | 
						|
+#ifdef CONFIG_M54455
 | 
						|
+		mcf5445x_conf_device(dev);
 | 
						|
+#endif
 | 
						|
+	}
 | 
						|
+
 | 
						|
+	return 0;
 | 
						|
+}
 | 
						|
+
 | 
						|
+/*
 | 
						|
+ * pcibios_fixup_bus(struct pci_bus *bus)
 | 
						|
+ */
 | 
						|
+void
 | 
						|
+pcibios_fixup_bus(struct pci_bus *bus)
 | 
						|
+{
 | 
						|
+	struct pci_dev *dev = bus->self;
 | 
						|
+
 | 
						|
+	if (!dev) {
 | 
						|
+		/* Root bus. */
 | 
						|
+#ifdef CONFIG_M54455
 | 
						|
+		bus->resource[0] = &pci_ioport_resource;
 | 
						|
+		bus->resource[1] = &pci_iomem_resource;
 | 
						|
+#endif
 | 
						|
+	}
 | 
						|
+}
 | 
						|
+
 | 
						|
+/*
 | 
						|
+ * pcibios_init(void)
 | 
						|
+ *
 | 
						|
+ * Allocate/initialize low level pci bus/devices.
 | 
						|
+ */
 | 
						|
+#ifdef CONFIG_M54455_PCI_initcall
 | 
						|
+static int __init
 | 
						|
+#else
 | 
						|
+int __init
 | 
						|
+#endif
 | 
						|
+pcibios_init(void)
 | 
						|
+{
 | 
						|
+	struct pci_bus *bus;
 | 
						|
+
 | 
						|
+	if (!raw_pci_ops) {
 | 
						|
+		printk(KERN_WARNING "PCIBIOS: FATAL: NO PCI Hardware found\n");
 | 
						|
+		return 0;
 | 
						|
+	}
 | 
						|
+
 | 
						|
+	/* allocate and scan the (only) bus */
 | 
						|
+	bus = pci_scan_bus_parented(NULL, 0, &pci_root_ops, NULL);
 | 
						|
+
 | 
						|
+	/* setup everything */
 | 
						|
+	if (bus) {
 | 
						|
+		/* compute the bridge window sizes */
 | 
						|
+		pci_bus_size_bridges(bus);
 | 
						|
+
 | 
						|
+		/* (re)assign device resources */
 | 
						|
+		pci_bus_assign_resources(bus);
 | 
						|
+
 | 
						|
+		/* add the bus to the system */
 | 
						|
+		pci_bus_add_devices(bus);
 | 
						|
+
 | 
						|
+		/* fixup irqs */
 | 
						|
+		pci_fixup_irqs(pcibios_swizzle, pcibios_map_irq);
 | 
						|
+	}
 | 
						|
+
 | 
						|
+	return 0;
 | 
						|
+}
 | 
						|
+
 | 
						|
+/*
 | 
						|
+ * pci_init(void)
 | 
						|
+ *
 | 
						|
+ * Initialize the PCI Hardware.
 | 
						|
+ */
 | 
						|
+#ifdef CONFIG_M54455_PCI_initcall
 | 
						|
+static int __init
 | 
						|
+#else
 | 
						|
+int __init
 | 
						|
+#endif
 | 
						|
+pci_init(void)
 | 
						|
+{
 | 
						|
+	printk(KERN_INFO "pci_init\n");
 | 
						|
+#if defined(CONFIG_M54455)
 | 
						|
+	init_mcf5445x_pci();
 | 
						|
+#endif
 | 
						|
+	if (!raw_pci_ops)
 | 
						|
+		printk(KERN_ERR "PCI: FATAL: NO PCI Detected\n");
 | 
						|
+
 | 
						|
+	return 0;
 | 
						|
+}
 | 
						|
+
 | 
						|
+#ifdef CONFIG_M54455_PCI_initcall
 | 
						|
+/* low level hardware (first) */
 | 
						|
+arch_initcall(pci_init);
 | 
						|
+
 | 
						|
+/* basic bios init (second) */
 | 
						|
+subsys_initcall(pcibios_init);
 | 
						|
+#endif
 | 
						|
--- /dev/null
 | 
						|
+++ b/arch/m68k/coldfire/m547x/pci.c
 | 
						|
@@ -0,0 +1,1023 @@
 | 
						|
+/*
 | 
						|
+ * ColdFire 547x/548x PCI Host Controller functions
 | 
						|
+ *
 | 
						|
+ * Copyright (C) 2005-2011 Freescale Semiconductor, Inc. All Rights Reserved.
 | 
						|
+ * Shrek Wu b16972@freescale.com
 | 
						|
+ * This code is based on the 2.6.10 version of pci.c
 | 
						|
+ *
 | 
						|
+ * This program is free software; you can redistribute it and/or modify
 | 
						|
+ * it under the terms of the GNU General Public License as published by
 | 
						|
+ * the Free Software Foundation; either version 2 of the License, or
 | 
						|
+ * (at your option) any later version.
 | 
						|
+ *
 | 
						|
+ * This program is distributed in the hope that it will be useful,
 | 
						|
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
						|
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
						|
+ * GNU General Public License for more details.
 | 
						|
+ *
 | 
						|
+ * You should have received a copy of the GNU General Public License
 | 
						|
+ * along with this program; if not, write to the Free Software
 | 
						|
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 | 
						|
+ */
 | 
						|
+#include <linux/kernel.h>
 | 
						|
+#include <linux/types.h>
 | 
						|
+#include <linux/init.h>
 | 
						|
+#include <linux/mm.h>
 | 
						|
+#include <linux/string.h>
 | 
						|
+#include <linux/pci.h>
 | 
						|
+#include <linux/ioport.h>
 | 
						|
+#include <linux/slab.h>
 | 
						|
+#include <linux/version.h>
 | 
						|
+#include <linux/interrupt.h>
 | 
						|
+#include <linux/delay.h>
 | 
						|
+
 | 
						|
+#include <linux/dma-mapping.h>
 | 
						|
+#include <asm/coldfire.h>
 | 
						|
+#include <linux/io.h>
 | 
						|
+#include <asm/m5485sim.h>
 | 
						|
+#include <asm/m5485pci.h>
 | 
						|
+#include <asm/irq.h>
 | 
						|
+#include <linux/pci.h>
 | 
						|
+#include <asm/virtconvert.h>
 | 
						|
+
 | 
						|
+
 | 
						|
+#undef DEBUG
 | 
						|
+/*define DEBUG*/
 | 
						|
+#ifdef DEBUG
 | 
						|
+/*#define DBG(x...) printk(KERN_DEBUG x)*/
 | 
						|
+#define DBG(x...) printk(x)
 | 
						|
+#else
 | 
						|
+#define DBG(x...)
 | 
						|
+#endif
 | 
						|
+
 | 
						|
+/*
 | 
						|
+ *  Bridge configration dafaults
 | 
						|
+ */
 | 
						|
+#define PCI_RETRIES	0
 | 
						|
+#define PCI_CACHE_LINE	8
 | 
						|
+#define PCI_MINGNT	1
 | 
						|
+#define PCI_MAXLAT	42
 | 
						|
+
 | 
						|
+
 | 
						|
+/*
 | 
						|
+ *  Initiator windows setting
 | 
						|
+ */
 | 
						|
+#define HOST_MEM_BASE		0xD0000000
 | 
						|
+/* ColdFire Memory window base 	*/
 | 
						|
+#define PCI_MEM_BASE		0xD0000000
 | 
						|
+/* PCI Memory window base	*/
 | 
						|
+#define PCI_MEM_SIZE		0x08000000
 | 
						|
+/* Memory window size (128M)	*/
 | 
						|
+#define HOST_IO_BASE		0xD8000000
 | 
						|
+/* ColdFire I/O window base 	*/
 | 
						|
+#define PCI_IO_BASE_ADDR	0x00000000
 | 
						|
+/* PCI I/O window base 		*/
 | 
						|
+#define PCI_IO_SIZE		0x00010000
 | 
						|
+/* I/O window size (64K) 	*/
 | 
						|
+/*#define HOST_CFG_BASE		0xD8000000*/
 | 
						|
+#define HOST_CFG_BASE		0xD8008000
 | 
						|
+/* ColdFire config window base 	*/
 | 
						|
+#define HOST_DMA_BASE		CONFIG_SDRAM_BASE
 | 
						|
+/* ColdFire PCI-DMA window base */
 | 
						|
+#define PCI_HDR_BASE		(MCF_MBAR+0xB00)
 | 
						|
+/* ColdFire config registers    */
 | 
						|
+
 | 
						|
+#define PCI_MEM_MASK		(PCI_MEM_SIZE-1)
 | 
						|
+#define PCI_IO_MASK		(PCI_IO_SIZE-1)
 | 
						|
+
 | 
						|
+/* Macro to set initiator window */
 | 
						|
+#define WxBAR(host_address, pci_address, size)	\
 | 
						|
+	(((host_address)  & 0xff000000)      |	\
 | 
						|
+	((((size)-1) & 0xff000000) >> 8)     |	\
 | 
						|
+	((pci_address) & 0xff000000) >> 16)
 | 
						|
+
 | 
						|
+/*
 | 
						|
+ *  BIOS internal data
 | 
						|
+ */
 | 
						|
+static u8 revision;		/* controller revision */
 | 
						|
+
 | 
						|
+/*
 | 
						|
+ *	Board specific setting
 | 
						|
+ */
 | 
						|
+const unsigned int irq_lines[] = { 5, 7 };
 | 
						|
+
 | 
						|
+#define N_SLOTS		(sizeof(board_info) / sizeof(board_info[0]))
 | 
						|
+#define N_IRQS		(sizeof(irq_lines)  / sizeof(irq_lines[0]))
 | 
						|
+#define BRIDGE_SLOT	0
 | 
						|
+
 | 
						|
+const struct slotinfo {
 | 
						|
+	unsigned char idsel;	/* device number     */
 | 
						|
+	unsigned char irq;	/* external IRQ      */
 | 
						|
+	unsigned char req;	/* REQ line number   */
 | 
						|
+	unsigned char gnt;	/* GNT line number   */
 | 
						|
+} board_info[] = {
 | 
						|
+	{0,  0, 0, 0},		/* Bridge      */
 | 
						|
+	{17, 5, 1, 1},		/* Slot #1     */
 | 
						|
+	{18, 5, 2, 2},		/* Slot #2     */
 | 
						|
+	{20, 7, 3, 3},		/* Slot #3     */
 | 
						|
+	{21, 7, 4, 4},		/* Slot #4     */
 | 
						|
+};
 | 
						|
+
 | 
						|
+/************************************************************************/
 | 
						|
+
 | 
						|
+/*
 | 
						|
+ * static int mk_conf_addr()
 | 
						|
+ *
 | 
						|
+ * Return type0 or type1 configuration address
 | 
						|
+ * by the means of device address and PCI dword location
 | 
						|
+ * 0 - for not existing slots
 | 
						|
+ */
 | 
						|
+static int mk_conf_addr(/*struct pci_dev *dev*/
 | 
						|
+	struct pci_bus *bus, unsigned int devfn, int where)
 | 
						|
+{
 | 
						|
+	int slot, func, address, idsel, dev_fn;
 | 
						|
+
 | 
						|
+	if (bus->number) {
 | 
						|
+		address = MCF_PCICAR_E | (bus->number << 16) |
 | 
						|
+		    (devfn << 8) | (where & 0xfc);
 | 
						|
+	} else {
 | 
						|
+		slot = PCI_SLOT(devfn);
 | 
						|
+		if (slot > N_SLOTS || slot == BRIDGE_SLOT)
 | 
						|
+			return 0;
 | 
						|
+		else {
 | 
						|
+			func = PCI_FUNC(devfn);
 | 
						|
+			idsel = board_info[slot].idsel;
 | 
						|
+
 | 
						|
+			dev_fn = PCI_DEVFN(idsel, func);
 | 
						|
+			address = MCF_PCICAR_E | (bus->number << 16) |
 | 
						|
+			    (dev_fn << 8) | (where & 0xfc);
 | 
						|
+		}
 | 
						|
+	}
 | 
						|
+
 | 
						|
+	return address;
 | 
						|
+}
 | 
						|
+
 | 
						|
+/*
 | 
						|
+ * static int read_config_byte()
 | 
						|
+ *
 | 
						|
+ * Read a byte from configuration space of specified device
 | 
						|
+ */
 | 
						|
+static int read_config_byte(/*struct pci_dev *dev*/
 | 
						|
+	struct pci_bus *bus, unsigned int devfn, int where, u8 *value)
 | 
						|
+{
 | 
						|
+	int slot;
 | 
						|
+	int address;
 | 
						|
+	int result;
 | 
						|
+
 | 
						|
+	*value = 0xff;
 | 
						|
+	result = PCIBIOS_SUCCESSFUL;
 | 
						|
+
 | 
						|
+	slot = PCI_SLOT(devfn);
 | 
						|
+	if (slot == BRIDGE_SLOT) {
 | 
						|
+		if (where <= 0x40)
 | 
						|
+			*value = *(volatile u8 *) (PCI_HDR_BASE +
 | 
						|
+						(where & 0xfc) + (where & 3));
 | 
						|
+		else
 | 
						|
+			*value = 0;
 | 
						|
+	} else {
 | 
						|
+		address = mk_conf_addr(bus, devfn, where);
 | 
						|
+		if (!address)
 | 
						|
+			result = PCIBIOS_DEVICE_NOT_FOUND;
 | 
						|
+		else {
 | 
						|
+			MCF_PCICAR = address;
 | 
						|
+			__asm__ __volatile__("nop");
 | 
						|
+			*value = *(volatile u8 *) (HOST_CFG_BASE + (where & 3));
 | 
						|
+		}
 | 
						|
+	}
 | 
						|
+	__asm("tpf");
 | 
						|
+	MCF_PCICAR &= ~MCF_PCICAR_E;
 | 
						|
+	DBG("PCI: read_config_byte bus=%d, dev=%d, fn=%d,"
 | 
						|
+		" addr=0x%02X, val=0x%02X, ret=%02X\n",
 | 
						|
+	bus->number, PCI_SLOT(devfn), PCI_FUNC(devfn), where, *value, result);
 | 
						|
+
 | 
						|
+	return result;
 | 
						|
+}
 | 
						|
+
 | 
						|
+/*
 | 
						|
+ * static int read_config_word()
 | 
						|
+ *
 | 
						|
+ * Read a word from configuration space of specified device
 | 
						|
+ */
 | 
						|
+static int read_config_word(/*struct pci_dev *dev*/
 | 
						|
+	struct pci_bus *bus, unsigned int devfn, int where, u16 *value)
 | 
						|
+{
 | 
						|
+	int slot;
 | 
						|
+	int address;
 | 
						|
+	int result;
 | 
						|
+
 | 
						|
+	*value = 0xffff;
 | 
						|
+	result = PCIBIOS_SUCCESSFUL;
 | 
						|
+
 | 
						|
+	if (where & 0x1)
 | 
						|
+		result = PCIBIOS_BAD_REGISTER_NUMBER;
 | 
						|
+	else {
 | 
						|
+		slot = PCI_SLOT(devfn);
 | 
						|
+		if (slot == BRIDGE_SLOT) {
 | 
						|
+			if (where <= 0x3f)
 | 
						|
+				*value =
 | 
						|
+				    *(volatile u16 *) (PCI_HDR_BASE +
 | 
						|
+					(where & 0xfc) + (where & 2));
 | 
						|
+			else
 | 
						|
+				*value = 0;
 | 
						|
+		} else {
 | 
						|
+			address = mk_conf_addr(bus, devfn, where);
 | 
						|
+			if (!address)
 | 
						|
+				result = PCIBIOS_DEVICE_NOT_FOUND;
 | 
						|
+			else {
 | 
						|
+				MCF_PCICAR = address;
 | 
						|
+				__asm__ __volatile__("nop");
 | 
						|
+				*value = le16_to_cpu(*(volatile u16 *)
 | 
						|
+						     (HOST_CFG_BASE +
 | 
						|
+						      (where & 2)));
 | 
						|
+			}
 | 
						|
+		}
 | 
						|
+	}
 | 
						|
+	__asm("tpf");
 | 
						|
+	MCF_PCICAR &= ~MCF_PCICAR_E;
 | 
						|
+	DBG("PCI: read_config_word bus=%d, dev=%d, fn=%d,"
 | 
						|
+		" addr=0x%02X, val=0x%04X ret=%02X\n",
 | 
						|
+	bus->number, PCI_SLOT(devfn), PCI_FUNC(devfn), where, *value, result);
 | 
						|
+
 | 
						|
+	return result;
 | 
						|
+}
 | 
						|
+
 | 
						|
+/*
 | 
						|
+ * static int read_config_dword()
 | 
						|
+ *
 | 
						|
+ * Read a long word from configuration space of specified device
 | 
						|
+ */
 | 
						|
+static int read_config_dword(/*struct pci_dev *dev*/
 | 
						|
+	struct pci_bus *bus, unsigned int devfn, int where, u32 *value)
 | 
						|
+{
 | 
						|
+	int slot;
 | 
						|
+	int address;
 | 
						|
+	int result;
 | 
						|
+
 | 
						|
+	*value = 0xffffffff;
 | 
						|
+	result = PCIBIOS_SUCCESSFUL;
 | 
						|
+
 | 
						|
+	if (where & 0x3)
 | 
						|
+		result = PCIBIOS_BAD_REGISTER_NUMBER;
 | 
						|
+	else {
 | 
						|
+		slot = PCI_SLOT(devfn);
 | 
						|
+		if (slot == BRIDGE_SLOT) {
 | 
						|
+			if (where <= 0x3d)
 | 
						|
+				*value =
 | 
						|
+				    *(volatile u32 *) (PCI_HDR_BASE + where);
 | 
						|
+			else
 | 
						|
+				*value = 0;
 | 
						|
+			__asm("tpf");
 | 
						|
+		} else {
 | 
						|
+			address = mk_conf_addr(bus, devfn, where);
 | 
						|
+			if (!address)
 | 
						|
+				result = PCIBIOS_DEVICE_NOT_FOUND;
 | 
						|
+			else {
 | 
						|
+				MCF_PCICAR = address;
 | 
						|
+				__asm__ __volatile__("nop");
 | 
						|
+				*value = le32_to_cpu(*(volatile u32 *)
 | 
						|
+						     (HOST_CFG_BASE));
 | 
						|
+				__asm("tpf");
 | 
						|
+				if (bus->number != 0 && revision < 1) {
 | 
						|
+					volatile u32 temp;
 | 
						|
+					MCF_PCICAR |= 0xff0000;
 | 
						|
+					temp = *(volatile u32 *)
 | 
						|
+						(HOST_CFG_BASE);
 | 
						|
+				}
 | 
						|
+			}
 | 
						|
+		}
 | 
						|
+	}
 | 
						|
+
 | 
						|
+	MCF_PCICAR &= ~MCF_PCICAR_E;
 | 
						|
+	DBG("PCI: read_config_dword bus=%d, dev=%d, fn=%d, "
 | 
						|
+		"addr=0x%02X, value=0x%08X ret=%02X\n",
 | 
						|
+	bus->number, PCI_SLOT(devfn), PCI_FUNC(devfn), where, *value, result);
 | 
						|
+
 | 
						|
+	return result;
 | 
						|
+}
 | 
						|
+
 | 
						|
+
 | 
						|
+
 | 
						|
+/*
 | 
						|
+ * static int write_config_byte()
 | 
						|
+ *
 | 
						|
+ * Write a byte to configuration space of specified device
 | 
						|
+ */
 | 
						|
+static int write_config_byte(/*struct pci_dev *dev*/
 | 
						|
+	struct pci_bus *bus, unsigned int devfn, int where, u8 value)
 | 
						|
+{
 | 
						|
+	int slot;
 | 
						|
+	int address;
 | 
						|
+	int result;
 | 
						|
+
 | 
						|
+	result = PCIBIOS_SUCCESSFUL;
 | 
						|
+
 | 
						|
+	slot = PCI_SLOT(devfn);
 | 
						|
+	if (slot == BRIDGE_SLOT) {
 | 
						|
+		if (where <= 0x40)
 | 
						|
+			*(volatile u8 *) (PCI_HDR_BASE + (where & 0xfc)
 | 
						|
+					+ (where & 3)) = value;
 | 
						|
+	} else {
 | 
						|
+		address = mk_conf_addr(bus, devfn, where);
 | 
						|
+		if (!address)
 | 
						|
+			result = PCIBIOS_DEVICE_NOT_FOUND;
 | 
						|
+		else {
 | 
						|
+			MCF_PCICAR = address;
 | 
						|
+			__asm__ __volatile__("tpf");
 | 
						|
+			*(volatile u8 *) (HOST_CFG_BASE + (where & 3)) = value;
 | 
						|
+		}
 | 
						|
+	}
 | 
						|
+	__asm("tpf");
 | 
						|
+	MCF_PCICAR &= ~MCF_PCICAR_E;
 | 
						|
+	pci_dummy_function();
 | 
						|
+
 | 
						|
+	DBG("PCI: write_config_byte bus=%d, dev=%d, fn=%d, "
 | 
						|
+		"addr=0x%02X, value=0x%02X ret=%02X\n",
 | 
						|
+	bus->number, PCI_SLOT(devfn), PCI_FUNC(devfn), where, value, result);
 | 
						|
+
 | 
						|
+	return result;
 | 
						|
+}
 | 
						|
+
 | 
						|
+/*
 | 
						|
+ * static int write_config_word()
 | 
						|
+ *
 | 
						|
+ * Write a word to configuration space of specified device
 | 
						|
+ */
 | 
						|
+static int write_config_word(/*struct pci_dev *dev*/
 | 
						|
+	struct pci_bus *bus, unsigned int devfn, int where, u16 value)
 | 
						|
+{
 | 
						|
+	int slot;
 | 
						|
+	int address;
 | 
						|
+	int result;
 | 
						|
+
 | 
						|
+	result = PCIBIOS_SUCCESSFUL;
 | 
						|
+
 | 
						|
+	if (where & 0x1)
 | 
						|
+		result = PCIBIOS_BAD_REGISTER_NUMBER;
 | 
						|
+	else {
 | 
						|
+		slot = PCI_SLOT(devfn);
 | 
						|
+		if (slot == BRIDGE_SLOT) {
 | 
						|
+			if (where <= 0x3f)
 | 
						|
+				*(volatile u16 *) (PCI_HDR_BASE +
 | 
						|
+					(where & 0xfc) + (where & 2)) = value;
 | 
						|
+		} else {
 | 
						|
+			address = mk_conf_addr(bus, devfn, where);
 | 
						|
+			if (!address)
 | 
						|
+				result = PCIBIOS_DEVICE_NOT_FOUND;
 | 
						|
+			else {
 | 
						|
+				MCF_PCICAR = address;
 | 
						|
+				__asm__ __volatile__("tpf");
 | 
						|
+				*(volatile u16 *) (HOST_CFG_BASE
 | 
						|
+					+ (where & 2)) =
 | 
						|
+						cpu_to_le16(value);
 | 
						|
+			}
 | 
						|
+		}
 | 
						|
+	}
 | 
						|
+	__asm("tpf");
 | 
						|
+	MCF_PCICAR &= ~MCF_PCICAR_E;
 | 
						|
+	pci_dummy_function();
 | 
						|
+
 | 
						|
+	DBG("PCI: write_config_word bus=%d, dev=%d, fn=%d, "
 | 
						|
+		"addr=0x%02X, value=0x%04X ret=%02X\n",
 | 
						|
+	bus->number, PCI_SLOT(devfn), PCI_FUNC(devfn), where, value, result);
 | 
						|
+
 | 
						|
+	return result;
 | 
						|
+}
 | 
						|
+
 | 
						|
+/*
 | 
						|
+ * static int write_config_dword()
 | 
						|
+ *
 | 
						|
+ * Write a long word to configuration space of specified device
 | 
						|
+ */
 | 
						|
+static int write_config_dword(/*struct pci_dev *dev*/
 | 
						|
+	struct pci_bus *bus, unsigned int devfn, int where, u32 value)
 | 
						|
+{
 | 
						|
+	int slot;
 | 
						|
+	int address;
 | 
						|
+	int result;
 | 
						|
+
 | 
						|
+	result = PCIBIOS_SUCCESSFUL;
 | 
						|
+
 | 
						|
+	if (where & 0x3)
 | 
						|
+		result = PCIBIOS_BAD_REGISTER_NUMBER;
 | 
						|
+	else {
 | 
						|
+		slot = PCI_SLOT(devfn);
 | 
						|
+		if (slot == BRIDGE_SLOT) {
 | 
						|
+			if (where <= 0x3d)
 | 
						|
+				*(volatile u32 *) (PCI_HDR_BASE + where) =
 | 
						|
+				    value;
 | 
						|
+		} else {
 | 
						|
+			address = mk_conf_addr(bus, devfn, where);
 | 
						|
+			if (!address)
 | 
						|
+				result = PCIBIOS_DEVICE_NOT_FOUND;
 | 
						|
+			else {
 | 
						|
+				MCF_PCICAR = address;
 | 
						|
+				__asm__ __volatile__("tpf");
 | 
						|
+				*(volatile u32 *) (HOST_CFG_BASE) =
 | 
						|
+				    cpu_to_le32(value);
 | 
						|
+			}
 | 
						|
+		}
 | 
						|
+	}
 | 
						|
+	__asm("tpf");
 | 
						|
+	MCF_PCICAR &= ~MCF_PCICAR_E;
 | 
						|
+	pci_dummy_function();
 | 
						|
+
 | 
						|
+	DBG("PCI: write_config_dword dev=%d, fn=%d,"
 | 
						|
+		"addr=0x%02X, value=0x%08X ret=%02X\n",
 | 
						|
+	    PCI_SLOT(devfn), PCI_FUNC(devfn), where,  value, result);
 | 
						|
+
 | 
						|
+	return result;
 | 
						|
+}
 | 
						|
+
 | 
						|
+static int config_read(struct pci_bus *bus, unsigned int devfn,
 | 
						|
+		       int where, int size, u32 *val)
 | 
						|
+{
 | 
						|
+	switch (size) {
 | 
						|
+	case 1:
 | 
						|
+		return read_config_byte(bus, devfn, where, (u8 *) val);
 | 
						|
+	case 2:
 | 
						|
+		return read_config_word(bus, devfn, where, (u16 *) val);
 | 
						|
+	default:
 | 
						|
+		return read_config_dword(bus, devfn, where, val);
 | 
						|
+	}
 | 
						|
+}
 | 
						|
+
 | 
						|
+static int config_write(struct pci_bus *bus, unsigned int devfn,
 | 
						|
+			int where, int size, u32 val)
 | 
						|
+{
 | 
						|
+	switch (size) {
 | 
						|
+	case 1:
 | 
						|
+		return write_config_byte(bus, devfn, where, (u8) val);
 | 
						|
+	case 2:
 | 
						|
+		return write_config_word(bus, devfn, where, (u16) val);
 | 
						|
+	default:
 | 
						|
+		return write_config_dword(bus, devfn, where, val);
 | 
						|
+	}
 | 
						|
+}
 | 
						|
+
 | 
						|
+/*
 | 
						|
+ *  configuration routines entry points
 | 
						|
+ */
 | 
						|
+static struct pci_ops bus_ops = {
 | 
						|
+	.read = config_read,
 | 
						|
+	.write = config_write,
 | 
						|
+};
 | 
						|
+
 | 
						|
+/************************************************************************/
 | 
						|
+
 | 
						|
+/*
 | 
						|
+ * u8 pci_inb()
 | 
						|
+ *
 | 
						|
+ * Read a byte at specified address from I/O space
 | 
						|
+ */
 | 
						|
+unsigned char pci_inb(long addr)
 | 
						|
+{
 | 
						|
+	char value;
 | 
						|
+
 | 
						|
+	value = *(volatile unsigned char *)(HOST_IO_BASE |
 | 
						|
+			(addr & PCI_IO_MASK));
 | 
						|
+	DBG("PCI: inb addr=0x%08X, value=0x%02X\n", addr, value);
 | 
						|
+
 | 
						|
+	return (unsigned char) value;
 | 
						|
+}
 | 
						|
+
 | 
						|
+
 | 
						|
+/*
 | 
						|
+ * u16 pci_inw()
 | 
						|
+ *
 | 
						|
+ * Read a word at specified address from I/O space
 | 
						|
+ */
 | 
						|
+unsigned short pci_inw(long addr)
 | 
						|
+{
 | 
						|
+	short value;
 | 
						|
+	volatile unsigned short *ptr;
 | 
						|
+
 | 
						|
+	ptr = (volatile unsigned short *) (HOST_IO_BASE | (addr & PCI_IO_MASK));
 | 
						|
+	value = le16_to_cpu(*ptr);
 | 
						|
+
 | 
						|
+	DBG("PCI: inw addr=0x%08X, value=0x%04X\n",  addr, value);
 | 
						|
+	return (unsigned short) value;
 | 
						|
+}
 | 
						|
+
 | 
						|
+/*
 | 
						|
+ * u16 pci_raw_inw()
 | 
						|
+ *
 | 
						|
+ * Read a raw word at specified address from I/O space
 | 
						|
+ */
 | 
						|
+unsigned short pci_raw_inw(long addr)
 | 
						|
+{
 | 
						|
+	short value;
 | 
						|
+	volatile unsigned short *ptr;
 | 
						|
+
 | 
						|
+	ptr = (volatile unsigned short *) (HOST_IO_BASE | (addr & PCI_IO_MASK));
 | 
						|
+	value = *ptr;
 | 
						|
+
 | 
						|
+	DBG("PCI: raw_inw addr=0x%08X, value=0x%04X\n",  addr, value);
 | 
						|
+	return (unsigned short) value;
 | 
						|
+}
 | 
						|
+
 | 
						|
+/*
 | 
						|
+ * u32 pci_inl()
 | 
						|
+ *
 | 
						|
+ * Read a dword at specified address from I/O space
 | 
						|
+ */
 | 
						|
+unsigned long pci_inl(long addr)
 | 
						|
+{
 | 
						|
+	long value;
 | 
						|
+	volatile unsigned long *ptr;
 | 
						|
+
 | 
						|
+	ptr = (volatile unsigned long *) (HOST_IO_BASE | (addr & PCI_IO_MASK));
 | 
						|
+	value = le32_to_cpu(*ptr);
 | 
						|
+
 | 
						|
+	DBG("PCI: inl addr=0x%08X, value=0x%08X\n",  addr, value);
 | 
						|
+	return (unsigned long) value;
 | 
						|
+}
 | 
						|
+
 | 
						|
+/*
 | 
						|
+ * u32 pci_raw_inl()
 | 
						|
+ *
 | 
						|
+ * Read a raw dword at specified address from I/O space
 | 
						|
+ */
 | 
						|
+unsigned long pci_raw_inl(long addr)
 | 
						|
+{
 | 
						|
+	long value;
 | 
						|
+	volatile unsigned long *ptr;
 | 
						|
+
 | 
						|
+	ptr = (volatile unsigned long *) (HOST_IO_BASE | (addr & PCI_IO_MASK));
 | 
						|
+	value = *ptr;
 | 
						|
+
 | 
						|
+	DBG("PCI: raw_inl addr=0x%08X, value=0x%08X\n",  addr, value);
 | 
						|
+	return (unsigned long) value;
 | 
						|
+}
 | 
						|
+
 | 
						|
+/*
 | 
						|
+ * void pci_outb()
 | 
						|
+ *
 | 
						|
+ * Write a byte value at specified address to I/O space
 | 
						|
+ */
 | 
						|
+void pci_outb(unsigned char value,  long addr)
 | 
						|
+{
 | 
						|
+
 | 
						|
+	*(volatile unsigned char *)(HOST_IO_BASE | (addr & PCI_IO_MASK))
 | 
						|
+		= value;
 | 
						|
+	DBG("PCI: outb addr=0x%08X, value=0x%02X\n",  addr, value);
 | 
						|
+}
 | 
						|
+
 | 
						|
+
 | 
						|
+/*
 | 
						|
+ * void pci_outw()
 | 
						|
+ *
 | 
						|
+ * Write a word value at specified address to I/O space
 | 
						|
+ */
 | 
						|
+void pci_outw(volatile unsigned short value, volatile  long addr)
 | 
						|
+{
 | 
						|
+	volatile unsigned short *ptr;
 | 
						|
+
 | 
						|
+	ptr = (volatile unsigned short *) (HOST_IO_BASE | (addr & PCI_IO_MASK));
 | 
						|
+	*ptr = cpu_to_le16(value);
 | 
						|
+	DBG("PCI: outw addr=0x%08X, value=0x%04X\n",  addr, value);
 | 
						|
+}
 | 
						|
+
 | 
						|
+/*
 | 
						|
+ * void pci_raw_outw()
 | 
						|
+ *
 | 
						|
+ * Write a raw word value at specified address to I/O space
 | 
						|
+ */
 | 
						|
+void pci_raw_outw(volatile unsigned short value, volatile  long addr)
 | 
						|
+{
 | 
						|
+	volatile unsigned short *ptr;
 | 
						|
+
 | 
						|
+	ptr = (volatile unsigned short *) (HOST_IO_BASE | (addr & PCI_IO_MASK));
 | 
						|
+	*ptr = value;
 | 
						|
+	DBG("PCI: raw_outw addr=0x%08X, value=0x%04X\n",  addr, value);
 | 
						|
+}
 | 
						|
+
 | 
						|
+/*
 | 
						|
+ * void pci_outl()
 | 
						|
+ *
 | 
						|
+ * Write a long word value at specified address to I/O space
 | 
						|
+ */
 | 
						|
+void pci_outl(volatile unsigned long value, volatile long addr)
 | 
						|
+{
 | 
						|
+	volatile unsigned long *ptr;
 | 
						|
+
 | 
						|
+	ptr = (volatile unsigned long *)(HOST_IO_BASE | (addr & PCI_IO_MASK));
 | 
						|
+	*ptr = cpu_to_le32(value);
 | 
						|
+	DBG("PCI: outl addr=0x%08X, value=0x%08X\n", addr, value);
 | 
						|
+}
 | 
						|
+
 | 
						|
+/*
 | 
						|
+ * void pci_raw_outl()
 | 
						|
+ *
 | 
						|
+ * Write a raw long word value at specified address to I/O space
 | 
						|
+ */
 | 
						|
+void pci_raw_outl(volatile unsigned long value, volatile long addr)
 | 
						|
+{
 | 
						|
+	volatile unsigned long *ptr;
 | 
						|
+
 | 
						|
+	ptr = (volatile unsigned long *)(HOST_IO_BASE | (addr & PCI_IO_MASK));
 | 
						|
+	*ptr = value;
 | 
						|
+	DBG("PCI: raw_outl addr=0x%08X, value=0x%08X\n", addr, value);
 | 
						|
+}
 | 
						|
+
 | 
						|
+/*
 | 
						|
+ * void pci_insb()
 | 
						|
+ *
 | 
						|
+ * Read several byte values from specified I/O port
 | 
						|
+ */
 | 
						|
+void pci_insb(volatile unsigned char *addr, unsigned char *buf, int len)
 | 
						|
+{
 | 
						|
+	for (; len--; buf++)
 | 
						|
+		*buf = pci_inb((unsigned long)addr);
 | 
						|
+	DBG("PCI: pci_insb addr=0x%08X, buf=%p, len=%d\n", addr, buf, len);
 | 
						|
+}
 | 
						|
+
 | 
						|
+
 | 
						|
+/*
 | 
						|
+ * void pci_insw()
 | 
						|
+ *
 | 
						|
+ * Read several word values from specified I/O port
 | 
						|
+ */
 | 
						|
+void pci_insw(volatile unsigned short *addr, unsigned short *buf, int len)
 | 
						|
+{
 | 
						|
+	for (; len--; buf++)
 | 
						|
+		*buf = pci_inw((unsigned long)addr);
 | 
						|
+	DBG("PCI: pci_insw addr=0x%08X, buf=%p, len=%d\n", addr, buf, len);
 | 
						|
+}
 | 
						|
+
 | 
						|
+/*
 | 
						|
+ * void pci_insl()
 | 
						|
+ *
 | 
						|
+ * Read several dword values from specified I/O port
 | 
						|
+ */
 | 
						|
+void pci_insl(volatile unsigned long *addr, unsigned long *buf, int len)
 | 
						|
+{
 | 
						|
+	for (; len--; buf++)
 | 
						|
+		*buf = pci_inl((unsigned long)addr);
 | 
						|
+	DBG("PCI: pci_insl addr=0x%08X, buf=%p, len=%d\n", addr, buf, len);
 | 
						|
+}
 | 
						|
+
 | 
						|
+/*
 | 
						|
+ * void pci_outsb()
 | 
						|
+ *
 | 
						|
+ * Write several byte values to specified I/O port
 | 
						|
+ */
 | 
						|
+void pci_outsb(volatile unsigned char *addr, const unsigned char *buf, int len)
 | 
						|
+{
 | 
						|
+	for (; len--; buf++)
 | 
						|
+		pci_outb((unsigned long)addr, *buf);
 | 
						|
+	DBG("PCI: pci_outsb addr=0x%08X, buf=%p, len=%d\n", addr, buf, len);
 | 
						|
+}
 | 
						|
+
 | 
						|
+/*
 | 
						|
+ * void pci_outsw()
 | 
						|
+ *
 | 
						|
+ * Write several word values to specified I/O port
 | 
						|
+ */
 | 
						|
+void pci_outsw(volatile unsigned short *addr,
 | 
						|
+		const unsigned short *buf, int len)
 | 
						|
+{
 | 
						|
+	for (; len--; buf++)
 | 
						|
+		pci_outw((unsigned long)addr, *buf);
 | 
						|
+	DBG("PCI: pci_outsw addr=0x%08X, buf=%p, len=%d\n", addr, buf, len);
 | 
						|
+}
 | 
						|
+
 | 
						|
+/*
 | 
						|
+ * void pci_outsl()
 | 
						|
+ *
 | 
						|
+ * Write several dword values to specified I/O port
 | 
						|
+ */
 | 
						|
+void pci_outsl(volatile unsigned long *addr, const unsigned long *buf, int len)
 | 
						|
+{
 | 
						|
+	for (; len--; buf++)
 | 
						|
+		pci_outl((unsigned long)addr, *buf);
 | 
						|
+	DBG("PCI: pci_outsl addr=0x%08X, buf=%p, len=%d\n", addr, buf, len);
 | 
						|
+}
 | 
						|
+
 | 
						|
+/*
 | 
						|
+ * void pci_xlb_handler()
 | 
						|
+ *
 | 
						|
+ * PCI XLB interrupt handler
 | 
						|
+ */
 | 
						|
+irqreturn_t xlb_interrupt(int irq, void *dev)
 | 
						|
+{
 | 
						|
+	volatile int xlb_error = MCF_PCIISR;
 | 
						|
+
 | 
						|
+	/* Acknowlege interrupt */
 | 
						|
+	MCF_PCIISR = xlb_error;
 | 
						|
+
 | 
						|
+	/* Dump interrupt reason */
 | 
						|
+	if (xlb_error & MCF_PCIISR_RE)
 | 
						|
+		DBG("PCI: Retry Error Received\n");
 | 
						|
+
 | 
						|
+	if (xlb_error & MCF_PCIISR_IA)
 | 
						|
+		DBG("PCI: Initiator Abort Received\n");
 | 
						|
+
 | 
						|
+	if (xlb_error & MCF_PCIISR_TA)
 | 
						|
+		DBG("PCI: Target Abort Received\n");
 | 
						|
+
 | 
						|
+	return IRQ_HANDLED;
 | 
						|
+}
 | 
						|
+
 | 
						|
+
 | 
						|
+/*
 | 
						|
+ * void pci_arbiter_handler()
 | 
						|
+ *
 | 
						|
+ * PCI arbiter interrupt handler
 | 
						|
+ */
 | 
						|
+irqreturn_t arb_interrupt(int irq, void *dev)
 | 
						|
+{
 | 
						|
+	volatile unsigned long arb_error = MCF_PCIARB_PASR;
 | 
						|
+
 | 
						|
+	/* Acknowlege interrupt */
 | 
						|
+	printk(KERN_ERR "%s\n", __func__);
 | 
						|
+	MCF_PCIARB_PASR = arb_error;
 | 
						|
+
 | 
						|
+	if (arb_error & MCF_PCIARB_PASR_ITLMBK) {
 | 
						|
+		DBG("PCI: coldfire master time-out\n");
 | 
						|
+
 | 
						|
+		/* Set infinite  number of retries */
 | 
						|
+		MCF_PCIICR &= ~0xFF;
 | 
						|
+	}
 | 
						|
+
 | 
						|
+	if (arb_error & MCF_PCIARB_PASR_EXTMBK(0x1F)) {
 | 
						|
+		arb_error >>= 17;
 | 
						|
+		DBG("PCI: external master time-out (mask = 0x%X)\n", arb_error);
 | 
						|
+
 | 
						|
+		/* raise arbitration priority level */
 | 
						|
+		MCF_PCIARB_PACR = MCF_PCIARB_PACR_EXTMPRI(arb_error);
 | 
						|
+	}
 | 
						|
+
 | 
						|
+	return IRQ_HANDLED;
 | 
						|
+}
 | 
						|
+
 | 
						|
+
 | 
						|
+/*
 | 
						|
+ * void pci_eint_handler()
 | 
						|
+ *
 | 
						|
+ * Eport interrupt handler
 | 
						|
+ */
 | 
						|
+irqreturn_t eint_handler(int irq, void *dev)
 | 
						|
+{
 | 
						|
+	/* Just acknowlege interrupt and exit */
 | 
						|
+	MCF_EPFR = 0x1 << (irq - 64);
 | 
						|
+	return IRQ_HANDLED;
 | 
						|
+}
 | 
						|
+
 | 
						|
+resource_size_t
 | 
						|
+pcibios_align_resource(void *data, const struct resource *res,
 | 
						|
+		resource_size_t size, resource_size_t align)
 | 
						|
+{
 | 
						|
+	struct pci_dev *dev = data;
 | 
						|
+	resource_size_t start = res->start;
 | 
						|
+
 | 
						|
+	if (res->flags & IORESOURCE_IO) {
 | 
						|
+		if (size > 0x100)
 | 
						|
+			printk(KERN_ERR "PCI: I/O Region %s/%d too large"
 | 
						|
+			       " (%ld bytes)\n", pci_name(dev),
 | 
						|
+			       dev->resource - res, (long int)size);
 | 
						|
+
 | 
						|
+		if (start & 0x3ff)
 | 
						|
+			start = (start + 0x3ff) & ~0x3ff;
 | 
						|
+	}
 | 
						|
+
 | 
						|
+	return start;
 | 
						|
+}
 | 
						|
+EXPORT_SYMBOL(pcibios_align_resource);
 | 
						|
+
 | 
						|
+/*
 | 
						|
+ * void __init coldfire_fixup(int pci_modify)
 | 
						|
+ *
 | 
						|
+ * Assign IRQ numbers as used by Linux to the interrupt pins
 | 
						|
+ * of the PCI cards.
 | 
						|
+ */
 | 
						|
+static void __init coldfire_fixup(int pci_modify)
 | 
						|
+{
 | 
						|
+	struct pci_dev *dev;
 | 
						|
+	unsigned char slot, pin;
 | 
						|
+
 | 
						|
+	DBG("%s\n", __func__);
 | 
						|
+#ifdef NL_ORIGINAL
 | 
						|
+	pci_for_each_dev(dev) {
 | 
						|
+#else
 | 
						|
+	dev = NULL;
 | 
						|
+	while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
 | 
						|
+#endif
 | 
						|
+		if (dev->class >> 16 != PCI_BASE_CLASS_BRIDGE) {
 | 
						|
+			slot = PCI_SLOT(dev->devfn);
 | 
						|
+			dev->irq = 64 + board_info[slot].irq;
 | 
						|
+
 | 
						|
+			/* Check if device needs interrupt */
 | 
						|
+#ifdef NL_ORIGINAL
 | 
						|
+			pcibios_read_config_byte(
 | 
						|
+				dev->bus->number, dev->devfn,
 | 
						|
+				PCI_INTERRUPT_PIN, &pin);
 | 
						|
+
 | 
						|
+			if (pin) {
 | 
						|
+				pcibios_write_config_byte(
 | 
						|
+					dev->bus->number, dev->devfn,
 | 
						|
+					PCI_INTERRUPT_LINE, dev->irq);
 | 
						|
+			}
 | 
						|
+#else
 | 
						|
+			pci_read_config_byte(dev,
 | 
						|
+				PCI_INTERRUPT_PIN, &pin);
 | 
						|
+
 | 
						|
+			if (pin) {
 | 
						|
+				pci_write_config_byte(dev,
 | 
						|
+					PCI_INTERRUPT_LINE, dev->irq);
 | 
						|
+			}
 | 
						|
+#endif
 | 
						|
+		}
 | 
						|
+	}
 | 
						|
+}
 | 
						|
+
 | 
						|
+static void __init configure_device(struct pci_dev *dev)
 | 
						|
+{
 | 
						|
+	/* TODO: This should depend from disable_pci_burst setting */
 | 
						|
+	DBG("%s\n", __func__);
 | 
						|
+#ifdef NL_ORIGINAL
 | 
						|
+	pcibios_write_config_byte(bus, devfn,
 | 
						|
+			PCI_CACHE_LINE_SIZE, PCI_CACHE_LINE);
 | 
						|
+#else
 | 
						|
+	pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, PCI_CACHE_LINE);
 | 
						|
+
 | 
						|
+	MCF_PCICR1 = MCF_PCICR1_LATTIMER(0xF8) |
 | 
						|
+		MCF_PCICR1_CACHELINESIZE(PCI_CACHE_LINE);
 | 
						|
+
 | 
						|
+#endif
 | 
						|
+}
 | 
						|
+
 | 
						|
+
 | 
						|
+struct pci_bus_info *__init init_coldfire_pci(void)
 | 
						|
+{
 | 
						|
+	struct pci_bus_info *bus;
 | 
						|
+	int i;
 | 
						|
+	unsigned long pci_mem_va;
 | 
						|
+	static char irq_name[N_IRQS][15];
 | 
						|
+
 | 
						|
+	MCF_SPCR |= 0x02; /*Enable the PCI clock*/
 | 
						|
+
 | 
						|
+	/* Get controller revision */
 | 
						|
+	revision = MCF_PCICCRIR;
 | 
						|
+	printk(KERN_INFO "ColdFire PCI Host Bridge "
 | 
						|
+		"(Rev. %d) detected:"
 | 
						|
+		"MEMBase %x,MEMLen %x,IOBase %x,IOLen %x\n",
 | 
						|
+		revision, HOST_MEM_BASE,
 | 
						|
+		PCI_MEM_SIZE - 1, 0, PCI_IO_SIZE - 1);
 | 
						|
+
 | 
						|
+	bus = (struct pci_bus_info *)kmalloc(sizeof(struct pci_bus_info),
 | 
						|
+			GFP_KERNEL);
 | 
						|
+	if (!bus) {
 | 
						|
+		printk(KERN_ERR "can not alloc mem for pci bus!\n");
 | 
						|
+		return NULL;
 | 
						|
+	}
 | 
						|
+
 | 
						|
+	/* Setup bus info structure. */
 | 
						|
+	memset(bus, 0, sizeof(struct pci_bus_info));
 | 
						|
+
 | 
						|
+	/* Request intiator memory resource */
 | 
						|
+	bus->mem_space.start = PCI_MEM_BASE;/*HOST_MEM_BASE;*/
 | 
						|
+	bus->mem_space.end = bus->mem_space.start + PCI_MEM_SIZE - 1;
 | 
						|
+	bus->mem_space.name = "PCI Bus #0";
 | 
						|
+	if (request_resource(&iomem_resource,
 | 
						|
+				&(bus->mem_space)) != 0) {
 | 
						|
+		printk(KERN_ERR "Failed to request bridge iomem resource\n");
 | 
						|
+		return NULL;
 | 
						|
+	}
 | 
						|
+
 | 
						|
+	/* Request intiator memory resource */
 | 
						|
+	/*bus->io_space.start = 0;*/
 | 
						|
+	bus->io_space.start = HOST_IO_BASE;
 | 
						|
+	bus->io_space.end = bus->io_space.start + PCI_IO_SIZE - 1;
 | 
						|
+	bus->io_space.name =  "PCI Bus #0";
 | 
						|
+	if (request_resource(&ioport_resource,
 | 
						|
+				&(bus->io_space)) != 0) {
 | 
						|
+		printk(KERN_ERR "Failed to request bridge "
 | 
						|
+			"ioport resource\n");
 | 
						|
+		return NULL;
 | 
						|
+	}
 | 
						|
+
 | 
						|
+	/* Must Reset!!! If bootloader has PCI enabled, it will cause
 | 
						|
+	 * problem in linux when it tries to configure/find resources
 | 
						|
+	 * for the pci devices.  Both registers need to be reset.
 | 
						|
+	 */
 | 
						|
+	/*MCF_PCIGSCR |= 0x1;*/
 | 
						|
+	MCF_PCIGSCR = 0x1;
 | 
						|
+	MCF_PCITCR = 0x00000000;
 | 
						|
+
 | 
						|
+	/* Set up the arbiter */
 | 
						|
+	MCF_PCIARB_PACR = 0; /*MCF_PCIARB_PACR_PKMD*/
 | 
						|
+
 | 
						|
+	/* GNT and REQ */
 | 
						|
+	MCF_PAR_PCIBG = 0x3FF;
 | 
						|
+	MCF_PAR_PCIBR = 0x3FF;
 | 
						|
+
 | 
						|
+	/* Enable bus mastering, memory access and MWI */
 | 
						|
+	MCF_PCISCR = (MCF_PCISCR_B | MCF_PCISCR_M);
 | 
						|
+
 | 
						|
+	/* Setup burst parameters */
 | 
						|
+	/*The offset 0x0e normally was header_type, set it to 0 and fix later*/
 | 
						|
+	MCF_PCICR1 = MCF_PCICR1_LATTIMER(0x00) |
 | 
						|
+		MCF_PCICR1_CACHELINESIZE(PCI_CACHE_LINE);
 | 
						|
+
 | 
						|
+	MCF_PCICR2 = 0;
 | 
						|
+	/*MCF_PCICR2_MINGNT(PCI_MINGNT) |
 | 
						|
+		MCF_PCICR2_MAXLAT(PCI_MAXLAT);
 | 
						|
+	*/
 | 
						|
+	/* Turn on error signaling */
 | 
						|
+	MCF_PCIICR = MCF_PCIICR_TAE | MCF_PCIICR_IAE | PCI_RETRIES;
 | 
						|
+	MCF_PCIGSCR |= MCF_PCIGSCR_SEE;
 | 
						|
+	/*
 | 
						|
+	 * Configure Initiator Windows
 | 
						|
+	 * Window 0: 128M PCI Memory @ HOST_MEM_BASE, 1:1 mapping
 | 
						|
+	 * Window 1: 64K  I/O Memory @ HOST_IO_BASE,  1:0 mapping
 | 
						|
+	 */
 | 
						|
+	MCF_PCIIW0BTAR = WxBAR(HOST_MEM_BASE, PCI_MEM_BASE, PCI_MEM_SIZE);
 | 
						|
+	MCF_PCIIW1BTAR = WxBAR(HOST_IO_BASE,  PCI_IO_BASE_ADDR,  PCI_IO_SIZE);
 | 
						|
+
 | 
						|
+	MCF_PCIIWCR = MCF_PCIIWCR_WINCTRL1_IO |
 | 
						|
+		MCF_PCIIWCR_WINCTRL0_MEMREAD;
 | 
						|
+
 | 
						|
+	/* Target PCI DMA Windows */
 | 
						|
+	MCF_PCIBAR1   = PCI_DMA_BASE;
 | 
						|
+	MCF_PCITBATR1 = HOST_DMA_BASE | MCF_PCITBATR1_EN;
 | 
						|
+
 | 
						|
+	/* Enable internal PCI controller interrupts */
 | 
						|
+	MCF_ICR(ISC_PCI_XLB) = ILP_PCI_XLB;
 | 
						|
+	/*request_irq(64+ISC_PCI_XLB, xlb_interrupt,
 | 
						|
+			SA_INTERRUPT, "PCI XL Bus", (void*)-1);
 | 
						|
+	enable_irq (64+ISC_PCI_XLB);
 | 
						|
+	*/
 | 
						|
+	if (request_irq(64+ISC_PCI_XLB, xlb_interrupt,
 | 
						|
+		IRQF_DISABLED, "PCI XL Bus", (void *)-1)) {
 | 
						|
+		printk(KERN_ERR "Cannot allocate "
 | 
						|
+			"ISC_PCI_XLB  IRQ\n");
 | 
						|
+		return (struct pci_bus_info *)-EBUSY;
 | 
						|
+	}
 | 
						|
+
 | 
						|
+	MCF_ICR(ISC_PCI_ARB) = ILP_PCI_ARB;
 | 
						|
+	/*request_irq(64+ISC_PCI_ARB, arb_interrupt,
 | 
						|
+			SA_INTERRUPT, "PCI Arbiter", (void*)-1);
 | 
						|
+	enable_irq (64+ISC_PCI_ARB);
 | 
						|
+	*/
 | 
						|
+	if (request_irq(64 + ISC_PCI_ARB, arb_interrupt,
 | 
						|
+		IRQF_DISABLED, "PCI Arbiter", (void *)-1)) {
 | 
						|
+		printk(KERN_ERR "Cannot allocate "
 | 
						|
+			"ISC_PCI_ARB  IRQ\n");
 | 
						|
+		return (struct pci_bus_info *)-EBUSY;
 | 
						|
+	}
 | 
						|
+
 | 
						|
+	/* Set slots interrupt setting */
 | 
						|
+	for (i = 0; i < N_IRQS; i++) {
 | 
						|
+		/* Set trailing edge for PCI interrupts */
 | 
						|
+		MCF_EPPAR &= ~MCF_EPPAR_EPPA(irq_lines[i], 0x3);
 | 
						|
+		if (irq_lines[i] == 5)
 | 
						|
+			MCF_EPPAR |= MCF_EPPAR_EPPA(irq_lines[i],
 | 
						|
+					MCF_EPPAR_EPPAx_FALLING);
 | 
						|
+		else
 | 
						|
+			MCF_EPPAR |= MCF_EPPAR_EPPA(irq_lines[i],
 | 
						|
+					0/*MCF_EPPAR_EPPAx_FALLING*/);
 | 
						|
+		/* Turn on irq line in eport */
 | 
						|
+		MCF_EPIER |= MCF_EPIER_EPIE(irq_lines[i]);
 | 
						|
+
 | 
						|
+		/* Enable irq in gpio */
 | 
						|
+		if (irq_lines[i] == 5)
 | 
						|
+			MCF_PAR_FECI2CIRQ |= 1;
 | 
						|
+
 | 
						|
+		if (irq_lines[i] == 6)
 | 
						|
+			MCF_PAR_FECI2CIRQ |= 2;
 | 
						|
+
 | 
						|
+		/* Register external interrupt handlers */
 | 
						|
+		sprintf(irq_name[i], "PCI IRQ%d", irq_lines[i]);
 | 
						|
+		/*request_irq(64 + irq_lines[i], eint_handler,
 | 
						|
+			    SA_SHIRQ, irq_name[i], (void*)-1);
 | 
						|
+		enable_irq(64 + irq_lines[i]);*/
 | 
						|
+		if (request_irq(64 + irq_lines[i], eint_handler,
 | 
						|
+			IRQF_SHARED, irq_name[i], (void *)-1)) {
 | 
						|
+			printk(KERN_ERR "Cannot allocate "
 | 
						|
+				"irq_lines[%d] IRQ\n",
 | 
						|
+				irq_lines[i]);
 | 
						|
+			return (struct pci_bus_info *)-EBUSY;
 | 
						|
+		}
 | 
						|
+	}
 | 
						|
+
 | 
						|
+	/* Clear PCI Reset and wait for devices to reset */
 | 
						|
+	MCF_PCIGSCR &= ~MCF_PCIGSCR_PR;
 | 
						|
+	schedule_timeout((5 * HZ));
 | 
						|
+	/* Remap initiator windows (should be 1:1 to the physical memory) */
 | 
						|
+	pci_mem_va = (int) ioremap_nocache(HOST_MEM_BASE,
 | 
						|
+			PCI_MEM_SIZE + PCI_IO_SIZE);
 | 
						|
+	udelay(1000); /* let every thing effect */
 | 
						|
+#if 1
 | 
						|
+	printk(KERN_INFO "%s: MEMBase_phy %x, Virt %x, len %x\n",
 | 
						|
+		__func__, HOST_MEM_BASE, pci_mem_va,
 | 
						|
+		PCI_MEM_SIZE + PCI_IO_SIZE);
 | 
						|
+#endif
 | 
						|
+	BUG_ON(pci_mem_va != HOST_MEM_BASE);
 | 
						|
+
 | 
						|
+	/* Setup bios32 and pci bus driver callbacks */
 | 
						|
+	bus->m68k_pci_ops = &bus_ops;
 | 
						|
+	bus->fixup = coldfire_fixup;
 | 
						|
+	bus->conf_device = configure_device;
 | 
						|
+
 | 
						|
+	return bus;
 | 
						|
+}
 | 
						|
--- /dev/null
 | 
						|
+++ b/arch/m68k/coldfire/m547x/pci_dummy.S
 | 
						|
@@ -0,0 +1,45 @@
 | 
						|
+/*
 | 
						|
+ * Copyright (C) 2010-2011 Freescale Semiconductor, Inc. All Rights Reserved.
 | 
						|
+ * Author: Jason Jin <Jason.jin@freescale.com>
 | 
						|
+ *
 | 
						|
+ * This routine is the dummy function for PCI errata
 | 
						|
+ *
 | 
						|
+ * 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
 | 
						|
+ */
 | 
						|
+
 | 
						|
+.global _pci_dummy_function
 | 
						|
+.global pci_dummy_function
 | 
						|
+.text
 | 
						|
+
 | 
						|
+pci_dummy_function:
 | 
						|
+_pci_dummy_function:
 | 
						|
+
 | 
						|
+/* force function start to 16-byte boundary.Can be done in linker file also */
 | 
						|
+.align 16
 | 
						|
+clr.l %d0
 | 
						|
+move.l %d0, 0xF0000F0C
 | 
						|
+/* Must use direct addressing. write to EPORT module
 | 
						|
+* xlbus -> slavebus -> eport, writing '0' to register has no
 | 
						|
+* effect
 | 
						|
+*/
 | 
						|
+
 | 
						|
+rts
 | 
						|
+tpf.l #0x0
 | 
						|
+tpf.l #0x0
 | 
						|
+tpf.l #0x0
 | 
						|
+tpf.l #0x0
 | 
						|
+tpf.l #0x0
 | 
						|
+.end
 | 
						|
--- /dev/null
 | 
						|
+++ b/arch/m68k/include/asm/5445x_pci.h
 | 
						|
@@ -0,0 +1,111 @@
 | 
						|
+/*
 | 
						|
+ * asm-m68k/pci.h - m68k specific PCI declarations.
 | 
						|
+ *
 | 
						|
+ * Copyright (C) 2007, 2009-2011 Freescale Semiconductor, Inc.
 | 
						|
+ * All Rights Reserved.
 | 
						|
+ * Kurt Mahan <kmahan@freescale.com>
 | 
						|
+ */
 | 
						|
+#ifndef _ASM_M68K_5445X_PCI_H
 | 
						|
+#define _ASM_M68K_5445x_PCI_H
 | 
						|
+
 | 
						|
+#ifndef CONFIG_PCI
 | 
						|
+/*
 | 
						|
+ * The PCI address space does equal the physical memory
 | 
						|
+ * address space.  The networking and block device layers use
 | 
						|
+ * this boolean for bounce buffer decisions.
 | 
						|
+ */
 | 
						|
+#define PCI_DMA_BUS_IS_PHYS		(1)
 | 
						|
+#else
 | 
						|
+#include <asm-generic/pci-dma-compat.h>
 | 
						|
+
 | 
						|
+#define PCI_DMA_BASE                    0 /* PCI-DMA window base */
 | 
						|
+#define NL_ORIGINAL
 | 
						|
+/*
 | 
						|
+ * The PCI address space does equal the physical memory
 | 
						|
+ * address space.  The networking and block device layers use
 | 
						|
+ * this boolean for bounce buffer decisions.
 | 
						|
+ */
 | 
						|
+#define PCI_DMA_BUS_IS_PHYS		(1)
 | 
						|
+
 | 
						|
+#define PCIBIOS_MIN_IO			0x00004000
 | 
						|
+#define PCIBIOS_MIN_MEM			0x02000000
 | 
						|
+
 | 
						|
+#define pcibios_assign_all_busses()	0
 | 
						|
+#define pcibios_scan_all_fns(a, b)	0
 | 
						|
+
 | 
						|
+struct pci_raw_ops {
 | 
						|
+	int (*read)(unsigned int domain, unsigned int bus, unsigned int devfn,
 | 
						|
+			int reg, int len, u32 *val);
 | 
						|
+	int (*write)(unsigned int domain, unsigned int bus, unsigned int devfn,
 | 
						|
+			int reg, int len, u32 val);
 | 
						|
+};
 | 
						|
+
 | 
						|
+extern struct pci_raw_ops *raw_pci_ops;
 | 
						|
+
 | 
						|
+static inline void
 | 
						|
+pcibios_set_master(struct pci_dev *dev)
 | 
						|
+{
 | 
						|
+	/* no special bus mastering setup handling */
 | 
						|
+}
 | 
						|
+
 | 
						|
+static inline void
 | 
						|
+pcibios_penalize_isa_irq(int irq, int active)
 | 
						|
+{
 | 
						|
+	/* no dynamic PCI IRQ allocation */
 | 
						|
+}
 | 
						|
+
 | 
						|
+#if 0
 | 
						|
+static inline void
 | 
						|
+pcibios_add_platform_entries(struct pci_dev *dev)
 | 
						|
+{
 | 
						|
+	/* no special handling */
 | 
						|
+}
 | 
						|
+#endif
 | 
						|
+
 | 
						|
+static inline void
 | 
						|
+pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region,
 | 
						|
+			 struct resource *res)
 | 
						|
+{
 | 
						|
+	region->start = res->start;
 | 
						|
+	region->end = res->end;
 | 
						|
+}
 | 
						|
+
 | 
						|
+static inline void
 | 
						|
+pcibios_bus_to_resource(struct pci_dev *dev, struct resource *res,
 | 
						|
+			struct pci_bus_region *region)
 | 
						|
+{
 | 
						|
+	res->start = region->start;
 | 
						|
+	res->end = region->end;
 | 
						|
+}
 | 
						|
+
 | 
						|
+static inline struct resource *
 | 
						|
+pcibios_select_root(struct pci_dev *pdev, struct resource *res)
 | 
						|
+{
 | 
						|
+	struct resource *root = NULL;
 | 
						|
+
 | 
						|
+	if (res->flags & IORESOURCE_IO)
 | 
						|
+		root = &ioport_resource;
 | 
						|
+	if (res->flags & IORESOURCE_MEM)
 | 
						|
+		root = &iomem_resource;
 | 
						|
+
 | 
						|
+	return root;
 | 
						|
+}
 | 
						|
+
 | 
						|
+#ifndef CONFIG_M54455_PCI_initcall
 | 
						|
+extern int pci_init(void);
 | 
						|
+extern int pcibios_init(void);
 | 
						|
+#endif
 | 
						|
+
 | 
						|
+extern void set_fpga(u32 *addr, u32 val);
 | 
						|
+
 | 
						|
+#ifdef CONFIG_M54455
 | 
						|
+extern int init_mcf5445x_pci(void);
 | 
						|
+extern void mcf5445x_conf_device(struct pci_dev *dev);
 | 
						|
+extern void mcf5445x_pci_dumpregs(void);
 | 
						|
+
 | 
						|
+extern struct resource pci_ioport_resource;
 | 
						|
+extern struct resource pci_iomem_resource;
 | 
						|
+#endif
 | 
						|
+
 | 
						|
+#endif /* CONFIG_PCI */
 | 
						|
+#endif /* _ASM_M68K_5445X_PCI_H */
 | 
						|
--- /dev/null
 | 
						|
+++ b/arch/m68k/include/asm/548x_pci.h
 | 
						|
@@ -0,0 +1,99 @@
 | 
						|
+/*
 | 
						|
+ * Copyright (C) 2009-2011 Freescale Semiconductor, Inc. All Rights Reserved.
 | 
						|
+ * Written by Wout Klaren.
 | 
						|
+ */
 | 
						|
+
 | 
						|
+#ifndef _ASM_M68K_548X_PCI_H
 | 
						|
+#define _ASM_M68K_548X_PCI_H
 | 
						|
+
 | 
						|
+#include <linux/mm.h>
 | 
						|
+#include <asm/scatterlist.h>
 | 
						|
+
 | 
						|
+#include <asm-generic/pci.h>
 | 
						|
+
 | 
						|
+struct pci_ops;
 | 
						|
+
 | 
						|
+/*
 | 
						|
+ * Structure with hardware dependent information and functions of the
 | 
						|
+ * PCI bus.
 | 
						|
+ */
 | 
						|
+
 | 
						|
+struct pci_bus_info {
 | 
						|
+	/*
 | 
						|
+	 * Resources of the PCI bus.
 | 
						|
+	 */
 | 
						|
+
 | 
						|
+	struct resource mem_space;
 | 
						|
+	struct resource io_space;
 | 
						|
+
 | 
						|
+	/*
 | 
						|
+	 * System dependent functions.
 | 
						|
+	 */
 | 
						|
+
 | 
						|
+	struct pci_ops *m68k_pci_ops;
 | 
						|
+
 | 
						|
+	void (*fixup)(int pci_modify);
 | 
						|
+	void (*conf_device)(struct pci_dev *dev);
 | 
						|
+};
 | 
						|
+
 | 
						|
+#define pcibios_assign_all_busses()	0
 | 
						|
+#define pcibios_scan_all_fns(a, b)	0
 | 
						|
+
 | 
						|
+static inline void pcibios_set_master(struct pci_dev *dev)
 | 
						|
+{
 | 
						|
+	/* No special bus mastering setup handling */
 | 
						|
+}
 | 
						|
+
 | 
						|
+static inline void pcibios_penalize_isa_irq(int irq)
 | 
						|
+{
 | 
						|
+	/* We don't do dynamic PCI IRQ allocation */
 | 
						|
+}
 | 
						|
+
 | 
						|
+#ifndef CONFIG_COLDFIRE
 | 
						|
+/* The PCI address space does equal the physical memory
 | 
						|
+ * address space.  The networking and block device layers use
 | 
						|
+ * this boolean for bounce buffer decisions.
 | 
						|
+ */
 | 
						|
+#define PCI_DMA_BUS_IS_PHYS	(1)
 | 
						|
+
 | 
						|
+#define PCIBIOS_MIN_IO		0x00004000
 | 
						|
+#define PCIBIOS_MIN_MEM		0x04000000
 | 
						|
+
 | 
						|
+#else /* !CONFIG_COLDFIRE */
 | 
						|
+#include <asm-generic/pci-dma-compat.h>
 | 
						|
+#define PCI_DMA_BASE		/*0x40000000*/0
 | 
						|
+/* PCI-DMA window base */
 | 
						|
+
 | 
						|
+extern struct pci_bus_info *__init init_coldfire_pci(void);
 | 
						|
+extern void *pci_alloc_son(struct pci_dev *, size_t,
 | 
						|
+		dma_addr_t *, int);
 | 
						|
+/*
 | 
						|
+ * The PCI address space equal the virtual memory
 | 
						|
+ * address space on m547X/m548X.
 | 
						|
+ */
 | 
						|
+#define PCI_DMA_BUS_IS_PHYS	(1)
 | 
						|
+
 | 
						|
+#define PCIBIOS_MIN_IO		0x00000100
 | 
						|
+#define PCIBIOS_MIN_MEM		0x02000000
 | 
						|
+
 | 
						|
+struct scatterlist;
 | 
						|
+
 | 
						|
+
 | 
						|
+/* This is always fine. */
 | 
						|
+#define pci_dac_dma_supported(pci_dev, mask)	(1)
 | 
						|
+
 | 
						|
+
 | 
						|
+/* These macros should be used after a pci_map_sg call has been done
 | 
						|
+ * to get bus addresses of each of the SG entries and their lengths.
 | 
						|
+ * You should only work with the number of sg entries pci_map_sg
 | 
						|
+ * returns.
 | 
						|
+ */
 | 
						|
+#define sg_dma_address(sg)	((sg)->dma_address)
 | 
						|
+#define sg_dma_len(sg)		((sg)->length)
 | 
						|
+
 | 
						|
+extern void pci_dummy_function(void);
 | 
						|
+/*Declarations of hardware specific initialisation functions*/
 | 
						|
+extern struct pci_bus_info *init_hades_pci(void);
 | 
						|
+
 | 
						|
+#endif /* !CONFIG_COLDFIRE*/
 | 
						|
+#endif /* _ASM_M68K_548X_PCI_H */
 | 
						|
--- a/arch/m68k/include/asm/pci.h
 | 
						|
+++ b/arch/m68k/include/asm/pci.h
 | 
						|
@@ -1,7 +1,13 @@
 | 
						|
 #ifndef _ASM_M68K_PCI_H
 | 
						|
 #define _ASM_M68K_PCI_H
 | 
						|
 
 | 
						|
+#if defined(CONFIG_M5445X)
 | 
						|
+#include "5445x_pci.h"
 | 
						|
+#elif defined(CONFIG_M547X_8X)
 | 
						|
+#include "548x_pci.h"
 | 
						|
+#else
 | 
						|
 #include <asm-generic/pci-dma-compat.h>
 | 
						|
+#endif
 | 
						|
 
 | 
						|
 /* The PCI address space does equal the physical memory
 | 
						|
  * address space.  The networking and block device layers use
 | 
						|
--- /dev/null
 | 
						|
+++ b/arch/m68k/kernel/bios32_mcf548x.c
 | 
						|
@@ -0,0 +1,632 @@
 | 
						|
+/*
 | 
						|
+ * bios32.c - PCI BIOS functions for m68k systems.
 | 
						|
+ *
 | 
						|
+ * Written by Wout Klaren.
 | 
						|
+ *
 | 
						|
+ * Copyright (C) 2008-2011 Freescale Semiconductor, Inc. All Rights Reserved.
 | 
						|
+ * Shrek Wu B16972@freescale.com
 | 
						|
+ *
 | 
						|
+ * Based on the DEC Alpha bios32.c by Dave Rusling and David Mosberger.
 | 
						|
+ */
 | 
						|
+#include <linux/init.h>
 | 
						|
+#include <linux/kernel.h>
 | 
						|
+#include <linux/device.h>
 | 
						|
+#include <linux/delay.h>
 | 
						|
+
 | 
						|
+# define DBG_DEVS(args)
 | 
						|
+
 | 
						|
+#ifdef CONFIG_PCI
 | 
						|
+
 | 
						|
+/*
 | 
						|
+ * PCI support for Linux/m68k. Currently only the Hades is supported.
 | 
						|
+ *
 | 
						|
+ * The support for PCI bridges in the DEC Alpha version has
 | 
						|
+ * been removed in this version.
 | 
						|
+ */
 | 
						|
+
 | 
						|
+#include <linux/pci.h>
 | 
						|
+#include <linux/slab.h>
 | 
						|
+#include <linux/mm.h>
 | 
						|
+
 | 
						|
+#include <asm/io.h>
 | 
						|
+#include <asm/pci.h>
 | 
						|
+#include <asm/uaccess.h>
 | 
						|
+
 | 
						|
+#define KB		1024
 | 
						|
+#define MB		(1024*KB)
 | 
						|
+#define GB		(1024*MB)
 | 
						|
+
 | 
						|
+#define MAJOR_REV	0
 | 
						|
+#define MINOR_REV	5
 | 
						|
+
 | 
						|
+/*
 | 
						|
+ * Align VAL to ALIGN, which must be a power of two.
 | 
						|
+ */
 | 
						|
+
 | 
						|
+#define MAX(val1, val2)		(((val1) > (val2)) ? val1 : val2)
 | 
						|
+
 | 
						|
+/*
 | 
						|
+ * Offsets relative to the I/O and memory base addresses from where resources
 | 
						|
+ * are allocated.
 | 
						|
+ */
 | 
						|
+
 | 
						|
+#ifdef CONFIG_COLDFIRE
 | 
						|
+#define IO_ALLOC_OFFSET		0x00000100
 | 
						|
+#define MEM_ALLOC_OFFSET	0x00000000
 | 
						|
+#else /* CONFIG_COLDFIRE */
 | 
						|
+#define IO_ALLOC_OFFSET		0x00004000
 | 
						|
+#define MEM_ALLOC_OFFSET	0x04000000
 | 
						|
+#endif /* CONFIG_COLDFIRE */
 | 
						|
+
 | 
						|
+/*
 | 
						|
+ * Bus info structure of the PCI bus. A pointer to this structure is
 | 
						|
+ * put in the sysdata member of the pci_bus structure.
 | 
						|
+ */
 | 
						|
+
 | 
						|
+static struct pci_bus_info *bus_info;
 | 
						|
+
 | 
						|
+static int pci_modify = 1;
 | 
						|
+/* If set, layout the PCI bus ourself. */
 | 
						|
+static int skip_vga;
 | 
						|
+/* If set do not modify base addresses of vga cards.*/
 | 
						|
+static int disable_pci_burst;
 | 
						|
+/* If set do not allow PCI bursts. */
 | 
						|
+
 | 
						|
+static volatile unsigned int io_base;
 | 
						|
+static volatile unsigned int mem_base;
 | 
						|
+
 | 
						|
+/*
 | 
						|
+ * static void disable_dev(struct pci_dev *dev)
 | 
						|
+ *
 | 
						|
+ * Disable PCI device DEV so that it does not respond to I/O or memory
 | 
						|
+ * accesses.
 | 
						|
+ *
 | 
						|
+ * Parameters:
 | 
						|
+ *
 | 
						|
+ * dev	- device to disable.
 | 
						|
+ */
 | 
						|
+
 | 
						|
+static void __init disable_dev(struct pci_dev *dev)
 | 
						|
+{
 | 
						|
+	unsigned short cmd;
 | 
						|
+
 | 
						|
+	if (((dev->class >> 8 == PCI_CLASS_NOT_DEFINED_VGA) ||
 | 
						|
+	     (dev->class >> 8 == PCI_CLASS_DISPLAY_VGA) ||
 | 
						|
+	     (dev->class >> 8 == PCI_CLASS_DISPLAY_XGA)) && skip_vga)
 | 
						|
+		return;
 | 
						|
+
 | 
						|
+	pci_read_config_word(dev, PCI_COMMAND, &cmd);
 | 
						|
+
 | 
						|
+	cmd &= (~PCI_COMMAND_IO & ~PCI_COMMAND_MEMORY & ~PCI_COMMAND_MASTER);
 | 
						|
+	pci_write_config_word(dev, PCI_COMMAND, cmd);
 | 
						|
+}
 | 
						|
+
 | 
						|
+/* Stolen from pcibios_enable_resources/i386 */
 | 
						|
+int pcibios_enable_device(struct pci_dev *dev, int mask)
 | 
						|
+{
 | 
						|
+	u16 cmd, old_cmd;
 | 
						|
+	int idx;
 | 
						|
+	struct resource *r;
 | 
						|
+
 | 
						|
+	pci_read_config_word(dev, PCI_COMMAND, &cmd);
 | 
						|
+	old_cmd = cmd;
 | 
						|
+	for (idx = 0; idx < 6; idx++) {
 | 
						|
+		/* Only set up the requested stuff */
 | 
						|
+		if (!(mask & (1<<idx)))
 | 
						|
+			continue;
 | 
						|
+
 | 
						|
+		r = &dev->resource[idx];
 | 
						|
+		if (!r->start && r->end) {
 | 
						|
+			printk(KERN_ERR "PCI: Device %s not"
 | 
						|
+				" available because"
 | 
						|
+				" of resource collisions\n",
 | 
						|
+				dev_name(&(dev->dev)));
 | 
						|
+			return -EINVAL;
 | 
						|
+		}
 | 
						|
+		if (r->flags & IORESOURCE_IO)
 | 
						|
+			cmd |= PCI_COMMAND_IO;
 | 
						|
+		if (r->flags & IORESOURCE_MEM)
 | 
						|
+			cmd |= PCI_COMMAND_MEMORY;
 | 
						|
+	}
 | 
						|
+	if (dev->resource[PCI_ROM_RESOURCE].start)
 | 
						|
+		cmd |= PCI_COMMAND_MEMORY;
 | 
						|
+	if (cmd != old_cmd) {
 | 
						|
+		printk(KERN_ERR "PCI: Enabling device "
 | 
						|
+			"%s (%04x -> %04x)\n",
 | 
						|
+			dev_name(&(dev->dev)), old_cmd, cmd);
 | 
						|
+		pci_write_config_word(dev, PCI_COMMAND, cmd);
 | 
						|
+	}
 | 
						|
+	return 0;
 | 
						|
+}
 | 
						|
+
 | 
						|
+/*
 | 
						|
+ * static void layout_dev(struct pci_dev *dev)
 | 
						|
+ *
 | 
						|
+ * Layout memory and I/O for a device.
 | 
						|
+ *
 | 
						|
+ * Parameters:
 | 
						|
+ *
 | 
						|
+ * device	- device to layout memory and I/O for.
 | 
						|
+ */
 | 
						|
+
 | 
						|
+static void __init layout_dev(struct pci_dev *dev)
 | 
						|
+{
 | 
						|
+	unsigned short cmd;
 | 
						|
+	unsigned int base, mask, size, reg;
 | 
						|
+	unsigned int alignto;
 | 
						|
+	int i;
 | 
						|
+
 | 
						|
+	/*
 | 
						|
+	 * Skip video cards if requested.
 | 
						|
+	 */
 | 
						|
+	if (((dev->class >> 8 == PCI_CLASS_NOT_DEFINED_VGA) ||
 | 
						|
+	     (dev->class >> 8 == PCI_CLASS_DISPLAY_VGA) ||
 | 
						|
+	     (dev->class >> 8 == PCI_CLASS_DISPLAY_XGA)) && skip_vga) {
 | 
						|
+		printk(KERN_ERR "%s: VGA\n", __func__);
 | 
						|
+		return;
 | 
						|
+	}
 | 
						|
+
 | 
						|
+	pci_read_config_word(dev, PCI_COMMAND, &cmd);
 | 
						|
+
 | 
						|
+	for (reg = PCI_BASE_ADDRESS_0, i = 0;
 | 
						|
+		reg <= PCI_BASE_ADDRESS_5; reg += 4, i++) {
 | 
						|
+		/*
 | 
						|
+		 * Figure out how much space and of what type this
 | 
						|
+		 * device wants.
 | 
						|
+		 */
 | 
						|
+
 | 
						|
+		pci_write_config_dword(dev, reg, 0xffffffff);
 | 
						|
+		pci_read_config_dword(dev, reg, &base);
 | 
						|
+		if (!base) {
 | 
						|
+			/* this base-address register is unused */
 | 
						|
+			dev->resource[i].start = 0;
 | 
						|
+			dev->resource[i].end = 0;
 | 
						|
+			dev->resource[i].flags = 0;
 | 
						|
+			continue;
 | 
						|
+		}
 | 
						|
+
 | 
						|
+		/*
 | 
						|
+		* We've read the base address register back after
 | 
						|
+		* writing all ones and so now we must decode it.
 | 
						|
+		*/
 | 
						|
+		if (base & PCI_BASE_ADDRESS_SPACE_IO) {
 | 
						|
+			/*
 | 
						|
+			 * I/O space base address register.
 | 
						|
+			 */
 | 
						|
+
 | 
						|
+			cmd |= PCI_COMMAND_IO;
 | 
						|
+
 | 
						|
+			base &= PCI_BASE_ADDRESS_IO_MASK;
 | 
						|
+			mask = (~base << 1) | 0x1;
 | 
						|
+			size = (mask & base) & 0xffffffff;
 | 
						|
+
 | 
						|
+			/*
 | 
						|
+			 * Align to multiple of size of minimum base.
 | 
						|
+			 */
 | 
						|
+
 | 
						|
+#ifdef CONFIG_COLDFIRE
 | 
						|
+			alignto = MAX(PAGE_SIZE, size) ;
 | 
						|
+#else /* !CONFIG_COLDFIRE */
 | 
						|
+			alignto = MAX(0x040, size) ;
 | 
						|
+#endif /* CONFIG_COLDFIRE */
 | 
						|
+			base = ALIGN(io_base, alignto);
 | 
						|
+			io_base = base + size;
 | 
						|
+			pci_write_config_dword(dev, reg,
 | 
						|
+				base | PCI_BASE_ADDRESS_SPACE_IO);
 | 
						|
+			dev->resource[i].start = base;
 | 
						|
+			dev->resource[i].end =
 | 
						|
+				dev->resource[i].start + size - 1;
 | 
						|
+			dev->resource[i].flags =
 | 
						|
+				IORESOURCE_IO | PCI_BASE_ADDRESS_SPACE_IO;
 | 
						|
+
 | 
						|
+			DBG_DEVS(("layout_dev: IO address: %x\n", base));
 | 
						|
+		} else {
 | 
						|
+			unsigned int type;
 | 
						|
+
 | 
						|
+			/*
 | 
						|
+			 * Memory space base address register.
 | 
						|
+			 */
 | 
						|
+			cmd |= PCI_COMMAND_MEMORY;
 | 
						|
+
 | 
						|
+			type = base & PCI_BASE_ADDRESS_MEM_TYPE_MASK;
 | 
						|
+			base &= PCI_BASE_ADDRESS_MEM_MASK;
 | 
						|
+			mask = (~base << 1) | 0x1;
 | 
						|
+			size = (mask & base) & 0xffffffff;
 | 
						|
+			switch (type) {
 | 
						|
+			case PCI_BASE_ADDRESS_MEM_TYPE_32:
 | 
						|
+			case PCI_BASE_ADDRESS_MEM_TYPE_64:
 | 
						|
+				break;
 | 
						|
+
 | 
						|
+			case PCI_BASE_ADDRESS_MEM_TYPE_1M:
 | 
						|
+				printk(KERN_INFO "bios32 WARNING: slot %d,"
 | 
						|
+					" function %d "
 | 
						|
+				       "requests memory below 1MB---don't "
 | 
						|
+				       "know how to do that.\n",
 | 
						|
+				       PCI_SLOT(dev->devfn),
 | 
						|
+				       PCI_FUNC(dev->devfn));
 | 
						|
+				continue;
 | 
						|
+			}
 | 
						|
+			DBG_DEVS(("%s MEM: base %x,type %x,mask %x,size %x\n",
 | 
						|
+				__func__, base, type, mask, size));
 | 
						|
+			/*
 | 
						|
+			 * Align to multiple of size of minimum base.
 | 
						|
+			 */
 | 
						|
+
 | 
						|
+			alignto = max_t(unsigned int, 0x1000, size);
 | 
						|
+			base = ALIGN(mem_base, alignto);
 | 
						|
+			mem_base = base + size;
 | 
						|
+			pci_write_config_dword(dev, reg, base);
 | 
						|
+			dev->resource[i].start = base;
 | 
						|
+			dev->resource[i].end =
 | 
						|
+				dev->resource[i].start + size - 1;
 | 
						|
+			dev->resource[i].flags = IORESOURCE_MEM;
 | 
						|
+
 | 
						|
+			DBG_DEVS(("%s MEM :base %x,size %x\n",
 | 
						|
+				__func__, base, size));
 | 
						|
+			if (type == PCI_BASE_ADDRESS_MEM_TYPE_64) {
 | 
						|
+				/*
 | 
						|
+				 * 64-bit address, set the highest 32 bits
 | 
						|
+				 * to zero.
 | 
						|
+				 */
 | 
						|
+
 | 
						|
+				reg += 4;
 | 
						|
+				pci_write_config_dword(dev, reg, 0);
 | 
						|
+
 | 
						|
+				i++;
 | 
						|
+				dev->resource[i].start = 0;
 | 
						|
+				dev->resource[i].end = 0;
 | 
						|
+				dev->resource[i].flags = 0;
 | 
						|
+				printk(KERN_ERR "%s:type == 64\n", __func__);
 | 
						|
+			}
 | 
						|
+		}
 | 
						|
+	}
 | 
						|
+	/*
 | 
						|
+	 * Enable device:
 | 
						|
+	 */
 | 
						|
+	if (dev->class >> 8 == PCI_CLASS_NOT_DEFINED ||
 | 
						|
+			dev->class >> 8 == PCI_CLASS_NOT_DEFINED_VGA ||
 | 
						|
+			dev->class >> 8 == PCI_CLASS_DISPLAY_VGA ||
 | 
						|
+			dev->class >> 8 == PCI_CLASS_DISPLAY_XGA) {
 | 
						|
+		/*
 | 
						|
+		 * All of these (may) have I/O scattered all around
 | 
						|
+		 * and may not use i/o-base address registers at all.
 | 
						|
+		 * So we just have to always enable I/O to these
 | 
						|
+		 * devices.
 | 
						|
+		 */
 | 
						|
+		cmd |= PCI_COMMAND_IO;
 | 
						|
+		pci_write_config_word(dev, PCI_COMMAND,
 | 
						|
+				cmd | PCI_COMMAND_MASTER);
 | 
						|
+	}
 | 
						|
+
 | 
						|
+	pci_write_config_byte(dev, PCI_LATENCY_TIMER,
 | 
						|
+			(disable_pci_burst) ? 0 : 32);
 | 
						|
+
 | 
						|
+	if (bus_info != NULL)
 | 
						|
+		bus_info->conf_device(dev);
 | 
						|
+	/* Machine dependent configuration. */
 | 
						|
+
 | 
						|
+	printk(KERN_INFO "layout_dev: bus %d  slot 0x%x  "
 | 
						|
+			"VID 0x%x  DID 0x%x  class 0x%x\n",
 | 
						|
+		dev->bus->number, PCI_SLOT(dev->devfn),
 | 
						|
+		dev->vendor, dev->device, dev->class);
 | 
						|
+}
 | 
						|
+
 | 
						|
+/*
 | 
						|
+ * static void layout_bus(struct pci_bus *bus)
 | 
						|
+ *
 | 
						|
+ * Layout memory and I/O for all devices on the given bus.
 | 
						|
+ *
 | 
						|
+ * Parameters:
 | 
						|
+ *
 | 
						|
+ * bus	- bus.
 | 
						|
+ */
 | 
						|
+
 | 
						|
+static void __init layout_bus(struct pci_bus *bus)
 | 
						|
+{
 | 
						|
+	unsigned int bio, bmem;
 | 
						|
+	struct pci_dev *dev;
 | 
						|
+
 | 
						|
+	DBG_DEVS(("layout_bus: starting bus %d\n", bus->number));
 | 
						|
+
 | 
						|
+	if (list_empty(&bus->devices) && list_empty(&bus->children))
 | 
						|
+		return;
 | 
						|
+
 | 
						|
+	/*
 | 
						|
+	 * Align the current bases on appropriate boundaries (4K for
 | 
						|
+	 * IO and 1MB for memory).
 | 
						|
+	 */
 | 
						|
+
 | 
						|
+	bio = io_base = ALIGN(io_base, 4*KB);
 | 
						|
+	bmem = mem_base = ALIGN(mem_base, 1*MB);
 | 
						|
+
 | 
						|
+	/*
 | 
						|
+	 * PCI devices might have been setup by a PCI BIOS emulation
 | 
						|
+	 * running under TOS. In these cases there is a
 | 
						|
+	 * window during which two devices may have an overlapping
 | 
						|
+	 * address range. To avoid this causing trouble, we first
 | 
						|
+	 * turn off the I/O and memory address decoders for all PCI
 | 
						|
+	 * devices.  They'll be re-enabled only once all address
 | 
						|
+	 * decoders are programmed consistently.
 | 
						|
+	 */
 | 
						|
+
 | 
						|
+	DBG_DEVS(("layout_bus: disable_dev for bus %d\n", bus->number));
 | 
						|
+
 | 
						|
+#ifdef NL_ORIGINAL
 | 
						|
+	for (dev = bus->devices; dev; dev = dev->sibling) {
 | 
						|
+#else
 | 
						|
+	dev = NULL;
 | 
						|
+	while ((dev = pci_get_device(
 | 
						|
+			PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
 | 
						|
+#endif
 | 
						|
+		if ((dev->class >> 16 != PCI_BASE_CLASS_BRIDGE) ||
 | 
						|
+		    (dev->class >> 8 == PCI_CLASS_BRIDGE_PCMCIA))
 | 
						|
+			disable_dev(dev);
 | 
						|
+	}
 | 
						|
+
 | 
						|
+	/*
 | 
						|
+	 * Allocate space to each device:
 | 
						|
+	 */
 | 
						|
+
 | 
						|
+	DBG_DEVS(("layout_bus: starting bus %d devices\n", bus->number));
 | 
						|
+
 | 
						|
+#ifdef NL_ORIGINAL
 | 
						|
+	for (dev = bus->devices; dev; dev = dev->sibling) {
 | 
						|
+#else
 | 
						|
+	dev = NULL;
 | 
						|
+	while ((dev = pci_get_device(
 | 
						|
+		PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
 | 
						|
+#endif
 | 
						|
+
 | 
						|
+		if ((dev->class >> 16 != PCI_BASE_CLASS_BRIDGE) ||
 | 
						|
+		    (dev->class >> 8 == PCI_CLASS_BRIDGE_PCMCIA))
 | 
						|
+			layout_dev(dev);
 | 
						|
+	}
 | 
						|
+
 | 
						|
+	DBG_DEVS(("layout_bus: bus %d finished\n", bus->number));
 | 
						|
+}
 | 
						|
+
 | 
						|
+/*
 | 
						|
+ * static void pcibios_fixup(void)
 | 
						|
+ *
 | 
						|
+ * Layout memory and I/O of all devices on the PCI bus if 'pci_modify' is
 | 
						|
+ * true. This might be necessary because not every m68k machine with a PCI
 | 
						|
+ * bus has a PCI BIOS. This function should be called right after
 | 
						|
+ * pci_scan_bus() in pcibios_init().
 | 
						|
+ */
 | 
						|
+
 | 
						|
+static void __init pcibios_fixup(void)
 | 
						|
+{
 | 
						|
+	DBG_DEVS(("%s\n", __func__));
 | 
						|
+	if (pci_modify) {
 | 
						|
+		/*
 | 
						|
+		 * Set base addresses for allocation of I/O and memory space.
 | 
						|
+		 */
 | 
						|
+
 | 
						|
+		io_base = bus_info->io_space.start + IO_ALLOC_OFFSET;
 | 
						|
+		mem_base = bus_info->mem_space.start + MEM_ALLOC_OFFSET;
 | 
						|
+
 | 
						|
+		/*
 | 
						|
+		 * Scan the tree, allocating PCI memory and I/O space.
 | 
						|
+		 */
 | 
						|
+
 | 
						|
+#ifdef NL_ORIGINAL
 | 
						|
+		layout_bus(pci_bus_b(pci_root.next));
 | 
						|
+#else
 | 
						|
+		layout_bus(pci_bus_b(pci_root_buses.next));
 | 
						|
+#endif
 | 
						|
+	}
 | 
						|
+
 | 
						|
+	/*
 | 
						|
+	 * Fix interrupt assignments, etc.
 | 
						|
+	 */
 | 
						|
+
 | 
						|
+	bus_info->fixup(pci_modify);
 | 
						|
+}
 | 
						|
+
 | 
						|
+/*
 | 
						|
+ * static void pcibios_claim_resources(struct pci_bus *bus)
 | 
						|
+ *
 | 
						|
+ * Claim all resources that are assigned to devices on the given bus.
 | 
						|
+ *
 | 
						|
+ * Parameters:
 | 
						|
+ *
 | 
						|
+ * bus	- bus.
 | 
						|
+ */
 | 
						|
+
 | 
						|
+static void __init pcibios_claim_resources(struct pci_bus *bus)
 | 
						|
+{
 | 
						|
+	struct pci_dev *dev;
 | 
						|
+	int i;
 | 
						|
+	DBG_DEVS(("%s\n", __func__));
 | 
						|
+#ifdef NL_ORIGINAL
 | 
						|
+	while (bus) {
 | 
						|
+#else
 | 
						|
+	while ((bus = pci_find_next_bus(bus)) != NULL) {
 | 
						|
+#endif
 | 
						|
+
 | 
						|
+#ifdef NL_ORIGINAL
 | 
						|
+		for (dev = bus->devices; (dev != NULL);
 | 
						|
+			dev = dev->sibling) {
 | 
						|
+#else
 | 
						|
+		dev = NULL;
 | 
						|
+		while ((dev = pci_get_device(
 | 
						|
+			PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
 | 
						|
+#endif
 | 
						|
+			for (i = 0; i < PCI_NUM_RESOURCES; i++) {
 | 
						|
+				struct resource *r = &dev->resource[i];
 | 
						|
+				struct resource *pr;
 | 
						|
+				struct pci_bus_info *bus_info =
 | 
						|
+					(struct pci_bus_info *)dev->sysdata;
 | 
						|
+
 | 
						|
+				if ((r->start == 0) || (r->parent != NULL))
 | 
						|
+					continue;
 | 
						|
+
 | 
						|
+#ifdef CONFIG_COLDFIRE
 | 
						|
+				if (dev->class >> 16 == PCI_BASE_CLASS_BRIDGE)
 | 
						|
+					continue;
 | 
						|
+#endif /* CONFIG_COLDFIRE */
 | 
						|
+#if 1
 | 
						|
+				if (r->flags & IORESOURCE_IO)
 | 
						|
+					pr = &bus_info->io_space;
 | 
						|
+				else
 | 
						|
+					pr = &bus_info->mem_space;
 | 
						|
+#else
 | 
						|
+				if (r->flags & IORESOURCE_IO)
 | 
						|
+					pr = &ioport_resource;
 | 
						|
+				else
 | 
						|
+					pr = &iomem_resource;
 | 
						|
+#endif
 | 
						|
+				if (request_resource(pr, r) < 0) {
 | 
						|
+#ifdef NL_ORIGINAL
 | 
						|
+					DBG_DEVS(("PCI: Address space"
 | 
						|
+						" collision on "
 | 
						|
+						"region %d of device %s\n",
 | 
						|
+						i, dev->name));
 | 
						|
+#else
 | 
						|
+					printk(KERN_INFO "PCI: Address space"
 | 
						|
+						" collision on region %d of"
 | 
						|
+						" device %s\n",
 | 
						|
+						i, dev_name(&(dev->dev)));
 | 
						|
+#endif
 | 
						|
+				}
 | 
						|
+			}
 | 
						|
+
 | 
						|
+#ifdef NL_ORIGINAL
 | 
						|
+		}
 | 
						|
+		if (bus->children)
 | 
						|
+			pcibios_claim_resources(bus->children);
 | 
						|
+#else
 | 
						|
+		}
 | 
						|
+		if (!list_empty(&bus->children))
 | 
						|
+			pcibios_claim_resources(pci_bus_b(bus->children.next));
 | 
						|
+#endif
 | 
						|
+
 | 
						|
+#ifdef NL_ORIGINAL
 | 
						|
+		bus = bus->next;
 | 
						|
+#endif
 | 
						|
+	}
 | 
						|
+}
 | 
						|
+
 | 
						|
+/*
 | 
						|
+ * int pcibios_assign_resource(struct pci_dev *dev, int i)
 | 
						|
+ *
 | 
						|
+ * Assign a new address to a PCI resource.
 | 
						|
+ *
 | 
						|
+ * Parameters:
 | 
						|
+ *
 | 
						|
+ * dev	- device.
 | 
						|
+ * i	- resource.
 | 
						|
+ *
 | 
						|
+ * Result: 0 if successful.
 | 
						|
+ */
 | 
						|
+
 | 
						|
+int __init pcibios_assign_resource(struct pci_dev *dev, int i)
 | 
						|
+{
 | 
						|
+	struct resource *r = &dev->resource[i];
 | 
						|
+	struct resource *pr = pci_find_parent_resource(dev, r);
 | 
						|
+	unsigned long size = r->end + 1;
 | 
						|
+	DBG_DEVS(("%s:IO_ALLOC_OFFSET %x\n", __func__, IO_ALLOC_OFFSET));
 | 
						|
+	if (!pr)
 | 
						|
+		return -EINVAL;
 | 
						|
+
 | 
						|
+	if (r->flags & IORESOURCE_IO) {
 | 
						|
+		DBG_DEVS(("%s:IORESOURCE_IO:start %x, size %lx\n",
 | 
						|
+			__func__, bus_info->io_space.start, size));
 | 
						|
+		if (size > 0x100)
 | 
						|
+			return -EFBIG;
 | 
						|
+
 | 
						|
+#ifdef NL_ORIGINAL
 | 
						|
+		if (allocate_resource(pr, r, size, bus_info->io_space.start +
 | 
						|
+				IO_ALLOC_OFFSET,
 | 
						|
+				bus_info->io_space.end,
 | 
						|
+				1024))
 | 
						|
+#else
 | 
						|
+		if (allocate_resource(pr, r, size, bus_info->io_space.start +
 | 
						|
+				IO_ALLOC_OFFSET,
 | 
						|
+				bus_info->io_space.end,
 | 
						|
+				1024, NULL, NULL))
 | 
						|
+#endif
 | 
						|
+			return -EBUSY;
 | 
						|
+	} else {
 | 
						|
+		DBG_DEVS(("%s:IORESOURCE_MEM:start %x, size %lx\n",
 | 
						|
+				__func__, bus_info->mem_space.start, size));
 | 
						|
+#ifdef NL_ORIGINAL
 | 
						|
+		if (allocate_resource(pr, r, size, bus_info->mem_space.start +
 | 
						|
+				      MEM_ALLOC_OFFSET,
 | 
						|
+				      bus_info->mem_space.end, size))
 | 
						|
+#else
 | 
						|
+		if (allocate_resource(pr, r, size, bus_info->io_space.start +
 | 
						|
+			IO_ALLOC_OFFSET,  bus_info->io_space.end,
 | 
						|
+			1024, NULL, NULL))
 | 
						|
+#endif
 | 
						|
+			return -EBUSY;
 | 
						|
+	}
 | 
						|
+
 | 
						|
+	if (i < 6)
 | 
						|
+		pci_write_config_dword(dev,
 | 
						|
+			PCI_BASE_ADDRESS_0 + 4 * i, r->start);
 | 
						|
+
 | 
						|
+	return 0;
 | 
						|
+}
 | 
						|
+
 | 
						|
+void pcibios_fixup_bus(struct pci_bus *bus)
 | 
						|
+{
 | 
						|
+	struct pci_dev *dev;
 | 
						|
+	void *sysdata;
 | 
						|
+
 | 
						|
+	sysdata = (bus->parent) ? bus->parent->sysdata : bus->sysdata;
 | 
						|
+
 | 
						|
+#ifdef NL_ORIGINAL
 | 
						|
+	for (dev = bus->devices; (dev != NULL); dev = dev->sibling)
 | 
						|
+#else
 | 
						|
+	dev = NULL;
 | 
						|
+	while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL)
 | 
						|
+#endif
 | 
						|
+		dev->sysdata = sysdata;
 | 
						|
+}
 | 
						|
+
 | 
						|
+int __init pcibios_init(void)
 | 
						|
+{
 | 
						|
+	printk(KERN_INFO "Linux/m68k PCI BIOS32 "
 | 
						|
+		"revision %x.%02x\n", MAJOR_REV, MINOR_REV);
 | 
						|
+
 | 
						|
+	bus_info = NULL;
 | 
						|
+#ifdef CONFIG_COLDFIRE
 | 
						|
+	bus_info = init_coldfire_pci();
 | 
						|
+#endif /* CONFIG_COLDFIRE */
 | 
						|
+#ifdef CONFIG_HADES
 | 
						|
+	if (MACH_IS_HADES)
 | 
						|
+		bus_info = init_hades_pci();
 | 
						|
+#endif
 | 
						|
+	if (bus_info != NULL) {
 | 
						|
+		printk(KERN_ERR "PCI: Probing PCI hardware\n");
 | 
						|
+		pci_scan_bus(0, bus_info->m68k_pci_ops, bus_info);
 | 
						|
+		pcibios_fixup();
 | 
						|
+#ifdef NL_ORIGINAL
 | 
						|
+		pcibios_claim_resources(pci_root);
 | 
						|
+#else
 | 
						|
+		pcibios_claim_resources(pci_bus_b(pci_root_buses.next));
 | 
						|
+#endif
 | 
						|
+	} else
 | 
						|
+		printk(KERN_ERR "PCI: No PCI bus detected\n");
 | 
						|
+	return 0;
 | 
						|
+}
 | 
						|
+
 | 
						|
+subsys_initcall(pcibios_init);
 | 
						|
+
 | 
						|
+char *pcibios_setup(char *str)
 | 
						|
+{
 | 
						|
+	if (!strcmp(str, "nomodify")) {
 | 
						|
+		pci_modify = 0;
 | 
						|
+		return NULL;
 | 
						|
+	} else if (!strcmp(str, "skipvga")) {
 | 
						|
+		skip_vga = 1;
 | 
						|
+		return NULL;
 | 
						|
+	} else if (!strcmp(str, "noburst")) {
 | 
						|
+		disable_pci_burst = 1;
 | 
						|
+		return NULL;
 | 
						|
+	}
 | 
						|
+
 | 
						|
+	return str;
 | 
						|
+}
 | 
						|
+#endif /* CONFIG_PCI */
 | 
						|
--- a/drivers/pci/Makefile
 | 
						|
+++ b/drivers/pci/Makefile
 | 
						|
@@ -50,6 +50,7 @@ obj-$(CONFIG_X86_VISWS) += setup-irq.o
 | 
						|
 obj-$(CONFIG_MN10300) += setup-bus.o
 | 
						|
 obj-$(CONFIG_MICROBLAZE) += setup-bus.o
 | 
						|
 obj-$(CONFIG_TILE) += setup-bus.o setup-irq.o
 | 
						|
+obj-$(CONFIG_M54455) += setup-bus.o setup-irq.o
 | 
						|
 
 | 
						|
 #
 | 
						|
 # ACPI Related PCI FW Functions
 | 
						|
--- a/drivers/pci/access.c
 | 
						|
+++ b/drivers/pci/access.c
 | 
						|
@@ -25,6 +25,7 @@ static DEFINE_RAW_SPINLOCK(pci_lock);
 | 
						|
 #define PCI_word_BAD (pos & 1)
 | 
						|
 #define PCI_dword_BAD (pos & 3)
 | 
						|
 
 | 
						|
+#ifdef NL_ORIGINAL
 | 
						|
 #define PCI_OP_READ(size,type,len) \
 | 
						|
 int pci_bus_read_config_##size \
 | 
						|
 	(struct pci_bus *bus, unsigned int devfn, int pos, type *value)	\
 | 
						|
@@ -39,6 +40,23 @@ int pci_bus_read_config_##size \
 | 
						|
 	raw_spin_unlock_irqrestore(&pci_lock, flags);		\
 | 
						|
 	return res;							\
 | 
						|
 }
 | 
						|
+#else /* NL_ORIGINAL */
 | 
						|
+#define PCI_OP_READ(size, type, len) \
 | 
						|
+	int pci_bus_read_config_##size \
 | 
						|
+	(struct pci_bus *bus, unsigned int devfn, \
 | 
						|
+	 int pos, type * value) \
 | 
						|
+{									\
 | 
						|
+		int res;                                                \
 | 
						|
+		unsigned long flags;                                    \
 | 
						|
+		if (PCI_##size##_BAD)					\
 | 
						|
+			return PCIBIOS_BAD_REGISTER_NUMBER;             \
 | 
						|
+		raw_spin_lock_irqsave(&pci_lock, flags);                    \
 | 
						|
+		res = bus->ops->read(                                   \
 | 
						|
+				bus, devfn, pos, len, (u32 *)value);    \
 | 
						|
+		raw_spin_unlock_irqrestore(&pci_lock, flags);               \
 | 
						|
+		return res;                                             \
 | 
						|
+}
 | 
						|
+#endif /* NL_ORIGINAL */
 | 
						|
 
 | 
						|
 #define PCI_OP_WRITE(size,type,len) \
 | 
						|
 int pci_bus_write_config_##size \
 | 
						|
--- a/drivers/pci/setup-bus.c
 | 
						|
+++ b/drivers/pci/setup-bus.c
 | 
						|
@@ -77,7 +77,13 @@ static void __dev_sort_resources(struct
 | 
						|
 	u16 class = dev->class >> 8;
 | 
						|
 
 | 
						|
 	/* Don't touch classless devices or host bridges or ioapics.  */
 | 
						|
+#ifdef CONFIG_M5445X
 | 
						|
+	if (class == PCI_CLASS_NOT_DEFINED || \
 | 
						|
+			class == PCI_CLASS_BRIDGE_HOST || \
 | 
						|
+			class == PCI_CLASS_BRIDGE_OTHER)
 | 
						|
+#else
 | 
						|
 	if (class == PCI_CLASS_NOT_DEFINED || class == PCI_CLASS_BRIDGE_HOST)
 | 
						|
+#endif
 | 
						|
 		return;
 | 
						|
 
 | 
						|
 	/* Don't touch ioapic devices already enabled by firmware */
 | 
						|
--- a/lib/iomap.c
 | 
						|
+++ b/lib/iomap.c
 | 
						|
@@ -227,9 +227,13 @@ EXPORT_SYMBOL(iowrite32_rep);
 | 
						|
 /* Create a virtual mapping cookie for an IO port range */
 | 
						|
 void __iomem *ioport_map(unsigned long port, unsigned int nr)
 | 
						|
 {
 | 
						|
+#ifndef CONFIG_M54455
 | 
						|
 	if (port > PIO_MASK)
 | 
						|
 		return NULL;
 | 
						|
 	return (void __iomem *) (unsigned long) (port + PIO_OFFSET);
 | 
						|
+#else
 | 
						|
+	return (void __iomem *) (unsigned long) port;
 | 
						|
+#endif
 | 
						|
 }
 | 
						|
 
 | 
						|
 void ioport_unmap(void __iomem *addr)
 |