mirror of
git://projects.qi-hardware.com/openwrt-xburst.git
synced 2024-12-25 21:59:34 +02:00
343c185b7d
git-svn-id: svn://svn.openwrt.org/openwrt/trunk@16547 3c298f89-4303-0410-b956-a3cf2f4a3e73
2624 lines
77 KiB
Diff
2624 lines
77 KiB
Diff
From 7f92b68c12c1891435c75f7f83a6390b4c73eaa6 Mon Sep 17 00:00:00 2001
|
|
From: Kurt Mahan <kmahan@freescale.com>
|
|
Date: Thu, 10 Jul 2008 19:17:11 -0600
|
|
Subject: [PATCH] Add PCI to m547x/m548x.
|
|
|
|
LTIBName: m547x-8x-pci-initial
|
|
Signed-off-by: Kurt Mahan <kmahan@freescale.com>
|
|
Signed-off-by: Shrek Wu <b16972@freescale.com>
|
|
---
|
|
arch/m68k/Kconfig | 4 +-
|
|
arch/m68k/coldfire/Makefile | 7 +-
|
|
arch/m68k/coldfire/ints.c | 8 +-
|
|
arch/m68k/coldfire/mcf548x-pci.c | 934 +++++++++++++++++++++++++++++++++++++
|
|
arch/m68k/kernel/Makefile | 3 +
|
|
arch/m68k/kernel/bios32_mcf548x.c | 631 +++++++++++++++++++++++++
|
|
arch/m68k/kernel/dma.c | 32 +-
|
|
arch/m68k/mm/kmap.c | 11 +-
|
|
drivers/pci/access.c | 16 +-
|
|
drivers/usb/host/Makefile | 2 +-
|
|
include/asm-m68k/5445x_pci.h | 94 ++++
|
|
include/asm-m68k/548x_pci.h | 99 ++++
|
|
include/asm-m68k/io.h | 65 +++-
|
|
include/asm-m68k/m5485pci.h | 330 +++++++++++++
|
|
include/asm-m68k/pci.h | 96 +----
|
|
include/asm-m68k/raw_io.h | 26 +
|
|
include/asm-m68k/virtconvert.h | 5 +
|
|
include/linux/pci.h | 2 +
|
|
18 files changed, 2250 insertions(+), 115 deletions(-)
|
|
create mode 100644 arch/m68k/coldfire/mcf548x-pci.c
|
|
create mode 100644 arch/m68k/kernel/bios32_mcf548x.c
|
|
create mode 100644 include/asm-m68k/5445x_pci.h
|
|
create mode 100644 include/asm-m68k/548x_pci.h
|
|
create mode 100644 include/asm-m68k/m5485pci.h
|
|
|
|
--- a/arch/m68k/Kconfig
|
|
+++ b/arch/m68k/Kconfig
|
|
@@ -175,8 +175,8 @@ config HADES
|
|
to use this kernel on a Hades, say Y here; otherwise say N.
|
|
|
|
config PCI
|
|
- bool
|
|
- depends on HADES || M54455
|
|
+ bool "PCI bus support"
|
|
+ depends on HADES || M54455 || M547X_8X
|
|
default n
|
|
help
|
|
Find out whether you have a PCI motherboard. PCI is the name of a
|
|
--- a/arch/m68k/coldfire/Makefile
|
|
+++ b/arch/m68k/coldfire/Makefile
|
|
@@ -3,12 +3,17 @@
|
|
#
|
|
|
|
obj-y:= entry.o config.o cache.o signal.o muldi3.o traps.o ints.o
|
|
-
|
|
+ifdef CONFIG_M5445X
|
|
ifneq ($(strip $(CONFIG_USB) $(CONFIG_USB_GADGET_MCF5445X)),)
|
|
obj-y += usb.o usb/
|
|
endif
|
|
+endif
|
|
|
|
+ifdef CONFIG_M547X_8X
|
|
+obj-$(CONFIG_PCI) += mcf548x-pci.o
|
|
+else
|
|
obj-$(CONFIG_PCI) += pci.o mcf5445x-pci.o iomap.o
|
|
+endif
|
|
obj-$(CONFIG_M5445X) += mcf5445x-devices.o
|
|
obj-$(CONFIG_M547X_8X) += m547x_8x-devices.o
|
|
obj-$(CONFIG_M547X_8X) += mcf548x-devices.o
|
|
--- a/arch/m68k/coldfire/ints.c
|
|
+++ b/arch/m68k/coldfire/ints.c
|
|
@@ -192,6 +192,8 @@ int setup_irq(unsigned int irq, struct i
|
|
/* Can't share interrupts unless both agree to */
|
|
if (!((*prev)->flags & node->flags & IRQF_SHARED)) {
|
|
spin_unlock_irqrestore(&contr->lock, flags);
|
|
+ printk(KERN_INFO "%s: -BUSY-Incorrect IRQ %d \n",
|
|
+ __FUNCTION__, irq);
|
|
return -EBUSY;
|
|
}
|
|
while (*prev)
|
|
@@ -219,9 +221,11 @@ int request_irq(unsigned int irq,
|
|
struct irq_node *node = get_irq_node();
|
|
int res;
|
|
|
|
- if (!node)
|
|
+ if (!node) {
|
|
+ printk(KERN_INFO "%s:get_irq_node error %x\n",
|
|
+ __FUNCTION__,(unsigned int) node);
|
|
return -ENOMEM;
|
|
-
|
|
+ }
|
|
node->handler = handler;
|
|
node->flags = flags;
|
|
node->dev_id = dev_id;
|
|
--- /dev/null
|
|
+++ b/arch/m68k/coldfire/mcf548x-pci.c
|
|
@@ -0,0 +1,934 @@
|
|
+/*
|
|
+ * ColdFire 547x/548x PCI Host Controller functions
|
|
+ */
|
|
+#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/dma-mapping.h>
|
|
+#include <asm/coldfire.h>
|
|
+#include <asm/io.h>
|
|
+#include <asm/m5485sim.h>
|
|
+#include <asm/m5485pci.h>
|
|
+#include <asm/irq.h>
|
|
+#include <asm/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
|
|
+
|
|
+#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,5,75))
|
|
+# define irqreturn_t void
|
|
+# define IRQ_HANDLED
|
|
+# define IRQ_NONE
|
|
+#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 /* 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 ^ 3));
|
|
+ else
|
|
+ *value = 0;
|
|
+ } else {
|
|
+ address = mk_conf_addr(bus, devfn, where);
|
|
+ if (!address)
|
|
+ result = PCIBIOS_DEVICE_NOT_FOUND;
|
|
+ else {
|
|
+ MCF_PCICAR = address;
|
|
+ *value = *(volatile u8 *) (HOST_CFG_BASE + (where & 3));
|
|
+ }
|
|
+ }
|
|
+ __asm__ __volatile__("nop");
|
|
+ __asm__ __volatile__("nop");
|
|
+ MCF_PCICAR &= ~MCF_PCICAR_E;
|
|
+
|
|
+ DBG("PCI: read_config_byte bus=%d, devfn=%d, addr=0x%02X, val=0x%02X, ret=%02X\n",
|
|
+ bus->number, 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 ^ 2));
|
|
+ else
|
|
+ *value = 0;
|
|
+ } else {
|
|
+ address = mk_conf_addr(bus, devfn, where);
|
|
+ if (!address)
|
|
+ result = PCIBIOS_DEVICE_NOT_FOUND;
|
|
+ else {
|
|
+ MCF_PCICAR = address;
|
|
+ *value = le16_to_cpu(*(volatile u16 *)
|
|
+ (HOST_CFG_BASE +
|
|
+ (where & 2)));
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ __asm__ __volatile__("nop");
|
|
+ __asm__ __volatile__("nop");
|
|
+ MCF_PCICAR &= ~MCF_PCICAR_E;
|
|
+
|
|
+ DBG("PCI: read_config_word bus=%d, devfn=%d, addr=0x%02X, val=0x%04X ret=%02X\n",
|
|
+ bus->number, 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__ __volatile__("nop");
|
|
+ __asm__ __volatile__("nop");
|
|
+ } else {
|
|
+ address = mk_conf_addr(bus, devfn, where);
|
|
+ if (!address)
|
|
+ result = PCIBIOS_DEVICE_NOT_FOUND;
|
|
+ else {
|
|
+ MCF_PCICAR = address;
|
|
+ *value = le32_to_cpu(*(volatile u32 *)
|
|
+ (HOST_CFG_BASE));
|
|
+ __asm__ __volatile__("nop");
|
|
+ __asm__ __volatile__("nop");
|
|
+ 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, devfn=%d, addr=0x%02X, value=0x%08X ret=%02X\n",
|
|
+ bus->number, 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 ^ 3)) = value;
|
|
+ } else {
|
|
+ address = mk_conf_addr(bus, devfn, where);
|
|
+ if (!address)
|
|
+ result = PCIBIOS_DEVICE_NOT_FOUND;
|
|
+ else {
|
|
+ MCF_PCICAR = address;
|
|
+ *(volatile u8 *) (HOST_CFG_BASE + (where & 3)) = value;
|
|
+ }
|
|
+ }
|
|
+ __asm__ __volatile__("nop");
|
|
+ __asm__ __volatile__("nop");
|
|
+ MCF_PCICAR &= ~MCF_PCICAR_E;
|
|
+
|
|
+ DBG("PCI: write_config_byte bus=%d, devfn=%d, addr=0x%02X, value=0x%02X ret=%02X\n",
|
|
+ bus->number, 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 ^ 2)) =
|
|
+ value;
|
|
+ } else {
|
|
+ address = mk_conf_addr(bus, devfn, where);
|
|
+ if (!address)
|
|
+ result = PCIBIOS_DEVICE_NOT_FOUND;
|
|
+ else {
|
|
+ MCF_PCICAR = address;
|
|
+ *(volatile u16 *) (HOST_CFG_BASE + (where & 2)) =
|
|
+ cpu_to_le16(value);
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ __asm__ __volatile__("nop");
|
|
+ __asm__ __volatile__("nop");
|
|
+ MCF_PCICAR &= ~MCF_PCICAR_E;
|
|
+
|
|
+ DBG("PCI: write_config_word bus=%d, devfn=%d, addr=0x%02X, value=0x%04X ret=%02X\n",
|
|
+ bus->number, 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;
|
|
+ *(volatile u32 *) (HOST_CFG_BASE) =
|
|
+ cpu_to_le32(value);
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ __asm__ __volatile__("nop");
|
|
+ __asm__ __volatile__("nop");
|
|
+ MCF_PCICAR &= ~MCF_PCICAR_E;
|
|
+
|
|
+ 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("%s\n",__FUNCTION__);
|
|
+ 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;
|
|
+}
|
|
+
|
|
+
|
|
+/*
|
|
+ * 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",__FUNCTION__);
|
|
+#ifdef NL_ORIGINAL
|
|
+ pci_for_each_dev(dev) {
|
|
+#else
|
|
+ dev = NULL;
|
|
+ while ((dev = pci_find_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",__FUNCTION__);
|
|
+#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);
|
|
+#endif
|
|
+}
|
|
+
|
|
+struct pci_bus_info *__init init_coldfire_pci(void)
|
|
+{
|
|
+ static struct pci_bus_info bus;
|
|
+ int i;
|
|
+ int pci_mem_va;
|
|
+ static char irq_name[N_IRQS][15];
|
|
+
|
|
+ /* Get controller revision */
|
|
+ revision = MCF_PCICCRIR;
|
|
+ printk("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);
|
|
+
|
|
+ /* 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("Failed to request bridge iomem resource\n");
|
|
+ return NULL;
|
|
+ }
|
|
+
|
|
+ /* Request intiator memory resource */
|
|
+ bus.io_space.start = 0;
|
|
+ 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("Failed to request bridge ioport resource\n");
|
|
+ return NULL;
|
|
+ }
|
|
+
|
|
+ /* Set up the arbiter */
|
|
+ MCF_PCIARB_PACR = 0 /*MCF_PCIARB_PACR_PKMD*/
|
|
+ | MCF_PCIARB_PACR_INTMPRI
|
|
+ | MCF_PCIARB_PACR_INTMINTEN
|
|
+ | MCF_PCIARB_PACR_EXTMPRI(0x1F)
|
|
+ | MCF_PCIARB_PACR_EXTMINTEN(0x1F);
|
|
+
|
|
+ /* 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 | MCF_PCISCR_MW;
|
|
+
|
|
+ /* Setup burst parameters */
|
|
+ MCF_PCICR1 = MCF_PCICR1_LATTIMER(32) |
|
|
+ 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_MEMRDLINE;
|
|
+
|
|
+ /* Target PCI DMA Windows */
|
|
+ MCF_PCIBAR1 = PCI_DMA_BASE;
|
|
+ MCF_PCITBATR1 = HOST_DMA_BASE | MCF_PCITBATR1_EN;
|
|
+ MCF_PCIBAR0 = MCF_RAMBAR0;;
|
|
+ MCF_PCITBATR0 = MCF_RAMBAR0 | MCF_PCITBATR0_EN;
|
|
+ DBG("PCI TCR %x,MCF_PCIBAR1 %x,MCF_PCITBATR1 %x."
|
|
+ "MCF_PCIBAR0 %x,MCF_PCITBATR9 %x\n", MCF_PCITCR, MCF_PCIBAR1,
|
|
+ MCF_PCITBATR1, MCF_PCIBAR0, MCF_PCITBATR0);
|
|
+ /* 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("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("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("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) / 10);
|
|
+ /* 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);
|
|
+#if 1
|
|
+ printk("%s: MEMBase_phy %x, Virt %x, len %x\n",__FUNCTION__,
|
|
+ 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;
|
|
+}
|
|
+
|
|
--- a/arch/m68k/kernel/Makefile
|
|
+++ b/arch/m68k/kernel/Makefile
|
|
@@ -12,6 +12,9 @@ ifndef CONFIG_COLDFIRE
|
|
obj-$(CONFIG_PCI) += bios32.o
|
|
else # CONFIG_COLDFIRE
|
|
extra-y := ../coldfire/head.o vmlinux.lds
|
|
+ifdef CONFIG_M547X_8X
|
|
+ obj-$(CONFIG_PCI) += bios32_mcf548x.o
|
|
+endif
|
|
endif
|
|
endif
|
|
|
|
--- /dev/null
|
|
+++ b/arch/m68k/kernel/bios32_mcf548x.c
|
|
@@ -0,0 +1,631 @@
|
|
+/*
|
|
+ * bios32.c - PCI BIOS functions for m68k systems.
|
|
+ *
|
|
+ * Written by Wout Klaren.
|
|
+ *
|
|
+ * Based on the DEC Alpha bios32.c by Dave Rusling and David Mosberger.
|
|
+ */
|
|
+#include <linux/init.h>
|
|
+#include <linux/kernel.h>
|
|
+
|
|
+#if 0
|
|
+# define DBG_DEVS(args) printk args
|
|
+#else
|
|
+# define DBG_DEVS(args)
|
|
+#endif
|
|
+
|
|
+#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 */
|
|
+
|
|
+/*
|
|
+ * Declarations of hardware specific initialisation functions.
|
|
+ */
|
|
+
|
|
+extern struct pci_bus_info *init_hades_pci(void);
|
|
+
|
|
+/*
|
|
+ * 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 unsigned int io_base;
|
|
+static 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("PCI: Device %s not available because"
|
|
+ " of resource collisions\n", dev->dev.bus_id);
|
|
+ return -EINVAL;
|
|
+ }
|
|
+ if (r->flags & IORESOURCE_IO)
|
|
+ cmd |= PCI_COMMAND_IO;
|
|
+ if (r->flags & IORESOURCE_MEM)
|
|
+ cmd |= PCI_COMMAND_MEMORY;
|
|
+ }
|
|
+ if (dev->resource[PCI_ROM_RESOURCE].start)
|
|
+ cmd |= PCI_COMMAND_MEMORY;
|
|
+ if (cmd != old_cmd) {
|
|
+ printk("PCI: Enabling device %s (%04x -> %04x)\n", dev->dev.bus_id, 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("%s: VGA\n",__FUNCTION__);
|
|
+ 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("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",
|
|
+ __FUNCTION__, 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",
|
|
+ __FUNCTION__, 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("%s:type == 64\n",__FUNCTION__);
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+
|
|
+ /*
|
|
+ * 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", __FUNCTION__));
|
|
+ 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", __FUNCTION__));
|
|
+#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_find_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("PCI: Address space collision on region %d of device %s\n", i, dev->dev.bus_id);
|
|
+#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", __FUNCTION__, IO_ALLOC_OFFSET));
|
|
+ if (!pr)
|
|
+ return -EINVAL;
|
|
+
|
|
+ if (r->flags & IORESOURCE_IO)
|
|
+ {
|
|
+ DBG_DEVS(("%s:IORESOURCE_IO:start %x, size %lx\n",
|
|
+ __FUNCTION__, 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",
|
|
+ __FUNCTION__, 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_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL)
|
|
+#endif
|
|
+ dev->sysdata = sysdata;
|
|
+}
|
|
+
|
|
+int __init pcibios_init(void)
|
|
+{
|
|
+ printk("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("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("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/arch/m68k/kernel/dma.c
|
|
+++ b/arch/m68k/kernel/dma.c
|
|
@@ -11,13 +11,24 @@
|
|
#include <linux/kernel.h>
|
|
#include <linux/scatterlist.h>
|
|
#include <linux/vmalloc.h>
|
|
-
|
|
+#include <linux/pci.h>
|
|
#include <asm/pgalloc.h>
|
|
|
|
void *dma_alloc_coherent(struct device *dev, size_t size,
|
|
dma_addr_t *handle, gfp_t flag)
|
|
{
|
|
-#ifndef CONFIG_M5445X
|
|
+#if defined(CONFIG_M547X_8X) | defined(CONFIG_M54455)
|
|
+ /*
|
|
+ * On the M5445x platform the memory allocated with GFP_DMA
|
|
+ * is guaranteed to be DMA'able.
|
|
+ */
|
|
+ void *addr;
|
|
+
|
|
+ size = PAGE_ALIGN(size);
|
|
+ addr = kmalloc(size, GFP_DMA);
|
|
+ *handle = virt_to_phys(addr);
|
|
+ return addr;
|
|
+#else
|
|
struct page *page, **map;
|
|
pgprot_t pgprot;
|
|
void *addr;
|
|
@@ -56,17 +67,6 @@ void *dma_alloc_coherent(struct device *
|
|
kfree(map);
|
|
|
|
return addr;
|
|
-#else
|
|
- /*
|
|
- * On the M5445x platform the memory allocated with GFP_DMA
|
|
- * is guaranteed to be DMA'able.
|
|
- */
|
|
- void *addr;
|
|
-
|
|
- size = PAGE_ALIGN(size);
|
|
- addr = kmalloc(size, GFP_DMA);
|
|
- *handle = virt_to_phys(addr);
|
|
- return addr;
|
|
#endif
|
|
}
|
|
EXPORT_SYMBOL(dma_alloc_coherent);
|
|
@@ -75,10 +75,10 @@ void dma_free_coherent(struct device *de
|
|
void *addr, dma_addr_t handle)
|
|
{
|
|
pr_debug("dma_free_coherent: %p, %x\n", addr, handle);
|
|
-#ifndef CONFIG_M5445X
|
|
- vfree(addr);
|
|
-#else
|
|
+#if defined(CONFIG_M547X_8X) | defined(CONFIG_M54455)
|
|
kfree(addr);
|
|
+#else
|
|
+ vfree(addr);
|
|
#endif
|
|
}
|
|
EXPORT_SYMBOL(dma_free_coherent);
|
|
--- a/arch/m68k/mm/kmap.c
|
|
+++ b/arch/m68k/mm/kmap.c
|
|
@@ -153,6 +153,10 @@ void __iomem *__ioremap(unsigned long ph
|
|
*/
|
|
return (void __iomem *)physaddr;
|
|
}
|
|
+ if ((physaddr >= 0xd0000000) && (physaddr + size < 0xd800ffff)) {
|
|
+ printk("ioremap:PCI 0x%lx,0x%lx(%d) - PCI area hit\n", physaddr, size, cacheflag);
|
|
+ return (void *)physaddr;
|
|
+ }
|
|
#endif
|
|
|
|
#ifdef DEBUG
|
|
@@ -284,7 +288,12 @@ void __iounmap(void *addr, unsigned long
|
|
pgd_t *pgd_dir;
|
|
pmd_t *pmd_dir;
|
|
pte_t *pte_dir;
|
|
-
|
|
+#ifdef CONFIG_M547X_8X
|
|
+ if ((addr >= (void*)0xd0000000) && (addr + size < (void*)0xd800ffff)) {
|
|
+ printk("%s: PCI address\n",__FUNCTION__);
|
|
+ return;
|
|
+ }
|
|
+#endif
|
|
while ((long)size > 0) {
|
|
pgd_dir = pgd_offset_k(virtaddr);
|
|
if (pgd_bad(*pgd_dir)) {
|
|
--- a/drivers/pci/access.c
|
|
+++ b/drivers/pci/access.c
|
|
@@ -23,6 +23,7 @@ static DEFINE_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) \
|
|
@@ -37,7 +38,20 @@ int pci_bus_read_config_##size \
|
|
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; \
|
|
+ spin_lock_irqsave(&pci_lock, flags); \
|
|
+ res = bus->ops->read(bus, devfn, pos, len, (u32 *)value); \
|
|
+ spin_unlock_irqrestore(&pci_lock, flags); \
|
|
+ return res; \
|
|
+}
|
|
+#endif /* NL_ORIGINAL */
|
|
#define PCI_OP_WRITE(size,type,len) \
|
|
int pci_bus_write_config_##size \
|
|
(struct pci_bus *bus, unsigned int devfn, int pos, type value) \
|
|
--- a/drivers/usb/host/Makefile
|
|
+++ b/drivers/usb/host/Makefile
|
|
@@ -6,7 +6,7 @@ ifeq ($(CONFIG_USB_DEBUG),y)
|
|
EXTRA_CFLAGS += -DDEBUG
|
|
endif
|
|
|
|
-obj-$(CONFIG_PCI) += pci-quirks.o
|
|
+#obj-$(CONFIG_PCI) += pci-quirks.o
|
|
|
|
obj-$(CONFIG_USB_EHCI_HCD) += ehci-hcd.o
|
|
obj-$(CONFIG_USB_ISP116X_HCD) += isp116x-hcd.o
|
|
--- /dev/null
|
|
+++ b/include/asm-m68k/5445x_pci.h
|
|
@@ -0,0 +1,94 @@
|
|
+/*
|
|
+ * asm-m68k/pci.h - m68k specific PCI declarations.
|
|
+ *
|
|
+ * Coldfire Implementation Copyright (c) 2007 Freescale Semiconductor, Inc.
|
|
+ * 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>
|
|
+
|
|
+/*
|
|
+ * 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
|
|
+
|
|
+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)
|
|
+{
|
|
+#ifdef CONFIG_M54455
|
|
+ if ((res->start == 0xa0000000) || (res->start == 0xa8000000)) {
|
|
+ /* HACK! FIX! kludge to fix bridge mapping */
|
|
+ region->start = res->start & 0x0fffffff;
|
|
+ region->end = res->end & 0x0fffffff;
|
|
+ } else {
|
|
+ region->start = res->start;
|
|
+ region->end = res->end;
|
|
+ }
|
|
+#else
|
|
+ region->start = res->start;
|
|
+ region->end = res->end;
|
|
+#endif
|
|
+}
|
|
+
|
|
+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;
|
|
+}
|
|
+
|
|
+#endif /* CONFIG_PCI */
|
|
+#endif /* _ASM_M68K_5445X_PCI_H */
|
|
--- /dev/null
|
|
+++ b/include/asm-m68k/548x_pci.h
|
|
@@ -0,0 +1,99 @@
|
|
+#ifndef _ASM_M68K_548X_PCI_H
|
|
+#define _ASM_M68K_548X_PCI_H
|
|
+
|
|
+/*
|
|
+ * asm-m68k/pci_m68k.h - m68k specific PCI declarations.
|
|
+ *
|
|
+ * Written by Wout Klaren.
|
|
+ */
|
|
+#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)
|
|
+
|
|
+static inline void pcibios_align_resource(void *data, struct resource *res, unsigned long size, unsigned long align)
|
|
+{
|
|
+}
|
|
+
|
|
+#endif /* !CONFIG_COLDFIRE*/
|
|
+#endif /* _ASM_M68K_548X_PCI_H */
|
|
--- a/include/asm-m68k/io.h
|
|
+++ b/include/asm-m68k/io.h
|
|
@@ -204,6 +204,12 @@ static inline u16 __iomem *isa_mtw(unsig
|
|
#define isa_outw(val,port) (ISA_SEX ? out_be16(isa_itw(port),(val)) : out_le16(isa_itw(port),(val)))
|
|
#define isa_outl(val,port) (ISA_SEX ? out_be32(isa_itl(port),(val)) : out_le32(isa_itl(port),(val)))
|
|
|
|
+#ifndef CONFIG_COLDFIRE
|
|
+#define isa_readb(p) in_8(isa_mtb(p))
|
|
+#define isa_readw(p) (ISA_SEX ? in_be16(isa_mtw(p)) : in_le16(isa_mtw(p)))
|
|
+#define isa_writeb(val,p) out_8(isa_mtb(p),(val))
|
|
+#define isa_writew(val,p) (ISA_SEX ? out_be16(isa_mtw(p),(val)) : out_le16(isa_mtw(p),(val)))
|
|
+#else
|
|
#define isa_readb(p) in_8(isa_mtb((unsigned long)(p)))
|
|
#define isa_readw(p) \
|
|
(ISA_SEX ? in_be16(isa_mtw((unsigned long)(p))) \
|
|
@@ -212,7 +218,7 @@ static inline u16 __iomem *isa_mtw(unsig
|
|
#define isa_writew(val,p) \
|
|
(ISA_SEX ? out_be16(isa_mtw((unsigned long)(p)),(val)) \
|
|
: out_le16(isa_mtw((unsigned long)(p)),(val)))
|
|
-
|
|
+#endif
|
|
static inline void isa_delay(void)
|
|
{
|
|
switch(ISA_TYPE)
|
|
@@ -285,6 +291,29 @@ static inline void isa_delay(void)
|
|
#endif /* CONFIG_ISA */
|
|
|
|
#if defined(CONFIG_PCI)
|
|
+#ifdef CONFIG_COLDFIRE
|
|
+#define inb_p inb
|
|
+#define inw_p inw
|
|
+#define inl_p inl
|
|
+#define outb_p outb
|
|
+#define outw_p outw
|
|
+#define outl_p outl
|
|
+
|
|
+unsigned char pci_inb(long addr);
|
|
+unsigned short pci_inw(long addr);
|
|
+unsigned long pci_inl(long addr);
|
|
+void pci_outb(unsigned char val, long addr);
|
|
+void pci_outw(unsigned short val, long addr);
|
|
+void pci_outl(unsigned long val, long addr);
|
|
+
|
|
+void pci_insb(volatile unsigned char* addr, unsigned char* buf, int len);
|
|
+void pci_insw(volatile unsigned short* addr, unsigned short* buf, int len);
|
|
+void pci_insl(volatile unsigned long* addr, unsigned long* buf, int len);
|
|
+
|
|
+void pci_outsb(volatile unsigned char* addr, const unsigned char* buf, int len);
|
|
+void pci_outsw(volatile unsigned short* addr, const unsigned short* buf, int len);
|
|
+void pci_outsl(volatile unsigned long* addr, const unsigned long* buf, int len);
|
|
+#endif
|
|
|
|
#define readl(addr) in_le32(addr)
|
|
#define writel(val,addr) out_le32((addr),(val))
|
|
@@ -300,6 +329,7 @@ static inline void isa_delay(void)
|
|
#define readl_relaxed(addr) readl(addr)
|
|
|
|
#ifndef CONFIG_ISA
|
|
+#ifndef CONFIG_COLDFIRE
|
|
#define inb(port) in_8(port)
|
|
#define outb(val,port) out_8((port),(val))
|
|
#define inw(port) in_le16(port)
|
|
@@ -319,6 +349,30 @@ static inline void isa_delay(void)
|
|
#define outsl(port, buf, nr) \
|
|
raw_outsw_swapw((u16 *)(port), (u16 *)(buf), (nr)<<1)
|
|
#else
|
|
+#define inb(port) pci_inb(port)
|
|
+#define outb(val,port) pci_outb((val),(port))
|
|
+#define inw(port) pci_inw(port)
|
|
+#define outw(val,port) pci_outw((val),(port))
|
|
+#define insb(a,b,c) pci_insb((volatile unsigned char*)a,(unsigned char*)b,c)
|
|
+#define insw(a,b,c) pci_insw((volatile unsigned short*)a,(const unsigned short*)b,c)
|
|
+#define insl(a,b,c) pci_insl((volatile unsigned long*)a,(const unsigned long*)b,c)
|
|
+#define outsb(a,b,c) pci_outsb((volatile unsigned char*)a,(const unsigned char*)b,c)
|
|
+#define outsw(a,b,c) pci_outsw((volatile unsigned short*)a,(const unsigned short*)b,c)
|
|
+#define outsl(a,b,c) pci_outsl((volatile unsigned long*)a,(const unsigned long*)b,c)
|
|
+#define inl(port) pci_inl(port)
|
|
+#define outl(val,port) pci_outl((val),(port))
|
|
+#endif
|
|
+
|
|
+#ifndef CONFIG_COLDFIRE
|
|
+#define __raw_readb readb
|
|
+#define __raw_readw readw
|
|
+#define __raw_readl readl
|
|
+#define __raw_writeb writeb
|
|
+#define __raw_writew writew
|
|
+#define __raw_writel writel
|
|
+#endif
|
|
+
|
|
+#else
|
|
/*
|
|
* kernel with both ISA and PCI compiled in, those have
|
|
* conflicting defs for in/out. Simply consider port < 1024
|
|
@@ -432,6 +486,15 @@ static inline void memcpy_toio(volatile
|
|
#define xlate_dev_kmem_ptr(p) p
|
|
|
|
#ifdef CONFIG_COLDFIRE
|
|
+#define __raw_readb(addr) \
|
|
+ ({ unsigned char __v = (*(volatile unsigned char *) (addr)); __v; })
|
|
+#define __raw_readw(addr) \
|
|
+ ({ unsigned short __v = (*(volatile unsigned short *) (addr)); __v; })
|
|
+#define __raw_readl(addr) \
|
|
+ ({ unsigned long __v = (*(volatile unsigned long *) (addr)); __v; })
|
|
+#define __raw_writeb(b,addr) (void)((*(volatile unsigned char *) (addr)) = (b))
|
|
+#define __raw_writew(b,addr) (void)((*(volatile unsigned short *) (addr)) = (b))
|
|
+#define __raw_writel(b,addr) (void)((*(volatile unsigned int *) (addr)) = (b))
|
|
|
|
#define memset_io(a, b, c) memset((void *)(a), (b), (c))
|
|
#define memcpy_fromio(a, b, c) memcpy((a), (void *)(b), (c))
|
|
--- /dev/null
|
|
+++ b/include/asm-m68k/m5485pci.h
|
|
@@ -0,0 +1,330 @@
|
|
+/*
|
|
+ * m5485pci.h -- ColdFire 547x/548x PCI controller support.
|
|
+ */
|
|
+#ifndef __MCF548X_PCI_H__
|
|
+#define __MCF548X_PCI_H__
|
|
+
|
|
+
|
|
+/* PCI Type 0 Configuration Registers */
|
|
+#define MCF_PCIIDR MCF_REG32(0x000B00) /* PCI Device ID/Vendor ID */
|
|
+#define MCF_PCISCR MCF_REG32(0x000B04) /* PCI Status/Command */
|
|
+#define MCF_PCICCRIR MCF_REG32(0x000B08) /* PCI Class Code / Revision ID */
|
|
+#define MCF_PCICR1 MCF_REG32(0x000B0C) /* PCI Configuration 1 Register */
|
|
+#define MCF_PCIBAR0 MCF_REG32(0x000B10) /* PCI Base Address Register 0 */
|
|
+#define MCF_PCIBAR1 MCF_REG32(0x000B14) /* PCI Base Address Register 1 */
|
|
+#define MCF_PCICCPR MCF_REG32(0x000B28) /* PCI Cardbus CIS Pointer */
|
|
+#define MCF_PCISID MCF_REG32(0x000B2C) /* Subsystem ID/Subsystem Vendor ID*/
|
|
+#define MCF_PCIERBAR MCF_REG32(0x000B30) /* PCI Expansion ROM */
|
|
+#define MCF_PCICPR MCF_REG32(0x000B30) /* PCI Capabilities Pointer */
|
|
+#define MCF_PCICR2 MCF_REG32(0x000B3C) /* PCI Configuration Register 2 */
|
|
+
|
|
+/* General Control/Status Registers */
|
|
+#define MCF_PCIGSCR MCF_REG32(0x000B60) /* Global Status/Control Register */
|
|
+#define MCF_PCITBATR0 MCF_REG32(0x000B64) /* Target Base Address Translation 0*/
|
|
+#define MCF_PCITBATR1 MCF_REG32(0x000B68) /* Target Base Address Translation 1*/
|
|
+#define MCF_PCITCR MCF_REG32(0x000B6C) /* Target Control Register */
|
|
+#define MCF_PCIIW0BTAR MCF_REG32(0x000B70) /* Initiator Window 0 Base Address */
|
|
+#define MCF_PCIIW1BTAR MCF_REG32(0x000B74) /* Initiator Window 1 Base Address */
|
|
+#define MCF_PCIIW2BTAR MCF_REG32(0x000B78) /* Initiator Window 2 Base Address */
|
|
+#define MCF_PCIIWCR MCF_REG32(0x000B80) /* Initiator Window Configuration */
|
|
+#define MCF_PCIICR MCF_REG32(0x000B84) /* Initiator Control Register */
|
|
+#define MCF_PCIISR MCF_REG32(0x000B88) /* Initiator Status Register */
|
|
+#define MCF_PCICAR MCF_REG32(0x000BF8) /* Configuration Address Register */
|
|
+
|
|
+/* CommBus FIFO Transmit Interface Registers */
|
|
+#define MCF_PCITPSR MCF_REG32(0x008400) /* Tx Packet Size Register */
|
|
+#define MCF_PCITSAR MCF_REG32(0x008404) /* Tx Start Address Register */
|
|
+#define MCF_PCITTCR MCF_REG32(0x008408) /* Tx Transaction Control Register */
|
|
+#define MCF_PCITER MCF_REG32(0x00840C) /* Tx Enables Register */
|
|
+#define MCF_PCITNAR MCF_REG32(0x008410) /* Tx Next Address Register */
|
|
+#define MCF_PCITLWR MCF_REG32(0x008414) /* Tx Last Word Register */
|
|
+#define MCF_PCITDCR MCF_REG32(0x008418) /* Tx Done Counts Register */
|
|
+#define MCF_PCITSR MCF_REG32(0x00841C) /* Tx Status Register */
|
|
+#define MCF_PCITFDR MCF_REG32(0x008440) /* Tx FIFO Data Register */
|
|
+#define MCF_PCITFSR MCF_REG32(0x008444) /* Tx FIFO Status Register */
|
|
+#define MCF_PCITFCR MCF_REG32(0x008448) /* Tx FIFO Control Register */
|
|
+#define MCF_PCITFAR MCF_REG32(0x00844C) /* Tx FIFO Alarm Register */
|
|
+#define MCF_PCITFRPR MCF_REG32(0x008450) /* Tx FIFO Read Pointer Register */
|
|
+#define MCF_PCITFWPR MCF_REG32(0x008454) /* Tx FIFO Write Pointer Register */
|
|
+
|
|
+/* CommBus FIFO Receive Interface Registers */
|
|
+#define MCF_PCIRPSR MCF_REG32(0x008480) /* Tx Packet Size Register */
|
|
+#define MCF_PCIRSAR MCF_REG32(0x008484) /* Tx Start Address Register */
|
|
+#define MCF_PCIRTCR MCF_REG32(0x008488) /* Tx Transaction Control Register */
|
|
+#define MCF_PCIRER MCF_REG32(0x00848C) /* Tx Enables Register */
|
|
+#define MCF_PCIRNAR MCF_REG32(0x008490) /* Tx Next Address Register */
|
|
+#define MCF_PCIRDCR MCF_REG32(0x008498) /* Tx Done Counts Register */
|
|
+#define MCF_PCIRSR MCF_REG32(0x00849C) /* Tx Status Register */
|
|
+#define MCF_PCIRFDR MCF_REG32(0x0084C0) /* Tx FIFO Data Register */
|
|
+#define MCF_PCIRFSR MCF_REG32(0x0084C4) /* Tx FIFO Status Register */
|
|
+#define MCF_PCIRFCR MCF_REG32(0x0084C8) /* Tx FIFO Control Register */
|
|
+#define MCF_PCIRFAR MCF_REG32(0x0084CC) /* Tx FIFO Alarm Register */
|
|
+#define MCF_PCIRFRPR MCF_REG32(0x0084D0) /* Tx FIFO Read Pointer Register */
|
|
+#define MCF_PCIRFWPR MCF_REG32(0x0084D4) /* Tx FIFO Write Pointer Register */
|
|
+
|
|
+/* PCI Arbiter Registers */
|
|
+#define MCF_PCIARB_PACR MCF_REG32(0x000C00)
|
|
+#define MCF_PCIARB_PASR MCF_REG32(0x000C04)
|
|
+
|
|
+
|
|
+/* Bit definitions and macros for MCF_PCIIDR */
|
|
+#define MCF_PCIIDR_VENDORID(x) (((x)&0x0000FFFF)<<0)
|
|
+#define MCF_PCIIDR_DEVICEID(x) (((x)&0x0000FFFF)<<16)
|
|
+
|
|
+/* Bit definitions and macros for MCF_PCISCR */
|
|
+#define MCF_PCISCR_M (0x00000002)
|
|
+#define MCF_PCISCR_B (0x00000004)
|
|
+#define MCF_PCISCR_SP (0x00000008)
|
|
+#define MCF_PCISCR_MW (0x00000010)
|
|
+#define MCF_PCISCR_PER (0x00000040)
|
|
+#define MCF_PCISCR_S (0x00000100)
|
|
+#define MCF_PCISCR_F (0x00000200)
|
|
+#define MCF_PCISCR_C (0x00100000)
|
|
+#define MCF_PCISCR_66M (0x00200000)
|
|
+#define MCF_PCISCR_R (0x00400000)
|
|
+#define MCF_PCISCR_FC (0x00800000)
|
|
+#define MCF_PCISCR_DP (0x01000000)
|
|
+#define MCF_PCISCR_DT(x) (((x)&0x00000003)<<25)
|
|
+#define MCF_PCISCR_TS (0x08000000)
|
|
+#define MCF_PCISCR_TR (0x10000000)
|
|
+#define MCF_PCISCR_MA (0x20000000)
|
|
+#define MCF_PCISCR_SE (0x40000000)
|
|
+#define MCF_PCISCR_PE (0x80000000)
|
|
+
|
|
+/* Bit definitions and macros for MCF_PCICCRIR */
|
|
+#define MCF_PCICCRIR_REVID(x) (((x)&0x000000FF)<<0)
|
|
+#define MCF_PCICCRIR_CLASSCODE(x) (((x)&0x00FFFFFF)<<8)
|
|
+
|
|
+/* Bit definitions and macros for MCF_PCICR1 */
|
|
+#define MCF_PCICR1_CACHELINESIZE(x) (((x)&0x0000000F)<<0)
|
|
+#define MCF_PCICR1_LATTIMER(x) (((x)&0x000000FF)<<8)
|
|
+#define MCF_PCICR1_HEADERTYPE(x) (((x)&0x000000FF)<<16)
|
|
+#define MCF_PCICR1_BIST(x) (((x)&0x000000FF)<<24)
|
|
+
|
|
+/* Bit definitions and macros for MCF_PCIBAR# */
|
|
+#define MCF_PCIBAR0_ADDR(x) (((x)&0x00003FFF)<<18)
|
|
+#define MCF_PCIBAR1_ADDR(x) (((x)&0x00000003)<<30)
|
|
+
|
|
+/* Bit definitions and macros for MCF_PCICR2 */
|
|
+#define MCF_PCICR2_INTLINE(x) (((x)&0x000000FF)<<0)
|
|
+#define MCF_PCICR2_INTPIN(x) (((x)&0x000000FF)<<8)
|
|
+#define MCF_PCICR2_MINGNT(x) (((x)&0x000000FF)<<16)
|
|
+#define MCF_PCICR2_MAXLAT(x) (((x)&0x000000FF)<<24)
|
|
+
|
|
+/* Bit definitions and macros for MCF_PCIGSCR */
|
|
+#define MCF_PCIGSCR_PR (0x00000001)
|
|
+#define MCF_PCIGSCR_SEE (0x00001000)
|
|
+#define MCF_PCIGSCR_PEE (0x00002000)
|
|
+#define MCF_PCIGSCR_SE (0x10000000)
|
|
+#define MCF_PCIGSCR_PE (0x20000000)
|
|
+
|
|
+/* Bit definitions and macros for MCF_PCITBATR0 */
|
|
+#define MCF_PCITBATR0_EN (0x00000001)
|
|
+#define MCF_PCITBATR0_BAT0(x) (((x)&0x00003FFF)<<18)
|
|
+
|
|
+/* Bit definitions and macros for MCF_PCITBATR1 */
|
|
+#define MCF_PCITBATR1_EN (0x00000001)
|
|
+#define MCF_PCITBATR1_BAT1(x) (((x)&0x00000003)<<30)
|
|
+
|
|
+/* Bit definitions and macros for MCF_PCITCR */
|
|
+#define MCF_PCITCR_P (0x00010000)
|
|
+#define MCF_PCITCR_LD (0x01000000)
|
|
+
|
|
+/* Bit definitions and macros for MCF_PCIIW0BTAR */
|
|
+#define MCF_PCIIW0BTAR_WTA0(x) (((x)&0x000000FF)<<8)
|
|
+#define MCF_PCIIW0BTAR_WAM0(x) (((x)&0x000000FF)<<16)
|
|
+#define MCF_PCIIW0BTAR_WBA0(x) (((x)&0x000000FF)<<24)
|
|
+
|
|
+/* Bit definitions and macros for MCF_PCIIW1BTAR */
|
|
+#define MCF_PCIIW1BTAR_WTA1(x) (((x)&0x000000FF)<<8)
|
|
+#define MCF_PCIIW1BTAR_WAM1(x) (((x)&0x000000FF)<<16)
|
|
+#define MCF_PCIIW1BTAR_WBA1(x) (((x)&0x000000FF)<<24)
|
|
+
|
|
+/* Bit definitions and macros for MCF_PCIIW2BTAR */
|
|
+#define MCF_PCIIW2BTAR_WTA2(x) (((x)&0x000000FF)<<8)
|
|
+#define MCF_PCIIW2BTAR_WAM2(x) (((x)&0x000000FF)<<16)
|
|
+#define MCF_PCIIW2BTAR_WBA2(x) (((x)&0x000000FF)<<24)
|
|
+
|
|
+/* Bit definitions and macros for MCF_PCIIWCR */
|
|
+#define MCF_PCIIWCR_WINCTRL2(x) (((x)&0x0000000F)<<8)
|
|
+#define MCF_PCIIWCR_WINCTRL1(x) (((x)&0x0000000F)<<16)
|
|
+#define MCF_PCIIWCR_WINCTRL0(x) (((x)&0x0000000F)<<24)
|
|
+#define MCF_PCIIWCR_WINCTRL0_MEMREAD (0x01000000)
|
|
+#define MCF_PCIIWCR_WINCTRL0_MEMRDLINE (0x03000000)
|
|
+#define MCF_PCIIWCR_WINCTRL0_MEMRDMUL (0x05000000)
|
|
+#define MCF_PCIIWCR_WINCTRL0_IO (0x09000000)
|
|
+#define MCF_PCIIWCR_WINCTRL0_E (0x01000000)
|
|
+#define MCF_PCIIWCR_WINCTRL1_MEMREAD (0x00010000)
|
|
+#define MCF_PCIIWCR_WINCTRL1_MEMRDLINE (0x00030000)
|
|
+#define MCF_PCIIWCR_WINCTRL1_MEMRDMUL (0x00050000)
|
|
+#define MCF_PCIIWCR_WINCTRL1_IO (0x00090000)
|
|
+#define MCF_PCIIWCR_WINCTRL1_E (0x00010000)
|
|
+#define MCF_PCIIWCR_WINCTRL2_MEMREAD (0x00000100)
|
|
+#define MCF_PCIIWCR_WINCTRL2_MEMRDLINE (0x00000300)
|
|
+#define MCF_PCIIWCR_WINCTRL2_MEMRDMUL (0x00000500)
|
|
+#define MCF_PCIIWCR_WINCTRL2_IO (0x00000900)
|
|
+#define MCF_PCIIWCR_WINCTRL2_E (0x00000100)
|
|
+
|
|
+
|
|
+/* Bit definitions and macros for MCF_PCIICR */
|
|
+#define MCF_PCIICR_MAXRETRY(x) (((x)&0x000000FF)<<0)
|
|
+#define MCF_PCIICR_TAE (0x01000000)
|
|
+#define MCF_PCIICR_IAE (0x02000000)
|
|
+#define MCF_PCIICR_REE (0x04000000)
|
|
+
|
|
+/* Bit definitions and macros for MCF_PCIISR */
|
|
+#define MCF_PCIISR_TA (0x01000000)
|
|
+#define MCF_PCIISR_IA (0x02000000)
|
|
+#define MCF_PCIISR_RE (0x04000000)
|
|
+
|
|
+/* Bit definitions and macros for MCF_PCICAR */
|
|
+#define MCF_PCICAR_DWORD(x) (((x)&0x0000003F)<<2)
|
|
+#define MCF_PCICAR_FUNCNUM(x) (((x)&0x00000007)<<8)
|
|
+#define MCF_PCICAR_DEVNUM(x) (((x)&0x0000001F)<<11)
|
|
+#define MCF_PCICAR_BUSNUM(x) (((x)&0x000000FF)<<16)
|
|
+#define MCF_PCICAR_E (0x80000000)
|
|
+
|
|
+/* Bit definitions and macros for MCF_PCITPSR */
|
|
+#define MCF_PCITPSR_PKTSIZE(x) (((x)&0x0000FFFF)<<16)
|
|
+
|
|
+/* Bit definitions and macros for MCF_PCITTCR */
|
|
+#define MCF_PCITTCR_DI (0x00000001)
|
|
+#define MCF_PCITTCR_W (0x00000010)
|
|
+#define MCF_PCITTCR_MAXBEATS(x) (((x)&0x00000007)<<8)
|
|
+#define MCF_PCITTCR_MAXRETRY(x) (((x)&0x000000FF)<<16)
|
|
+#define MCF_PCITTCR_PCICMD(x) (((x)&0x0000000F)<<24)
|
|
+
|
|
+/* Bit definitions and macros for MCF_PCITER */
|
|
+#define MCF_PCITER_NE (0x00010000)
|
|
+#define MCF_PCITER_IAE (0x00020000)
|
|
+#define MCF_PCITER_TAE (0x00040000)
|
|
+#define MCF_PCITER_RE (0x00080000)
|
|
+#define MCF_PCITER_SE (0x00100000)
|
|
+#define MCF_PCITER_FEE (0x00200000)
|
|
+#define MCF_PCITER_ME (0x01000000)
|
|
+#define MCF_PCITER_BE (0x08000000)
|
|
+#define MCF_PCITER_CM (0x10000000)
|
|
+#define MCF_PCITER_RF (0x40000000)
|
|
+#define MCF_PCITER_RC (0x80000000)
|
|
+
|
|
+/* Bit definitions and macros for MCF_PCITDCR */
|
|
+#define MCF_PCITDCR_PKTSDONE(x) (((x)&0x0000FFFF)<<0)
|
|
+#define MCF_PCITDCR_BYTESDONE(x) (((x)&0x0000FFFF)<<16)
|
|
+
|
|
+/* Bit definitions and macros for MCF_PCITSR */
|
|
+#define MCF_PCITSR_IA (0x00010000)
|
|
+#define MCF_PCITSR_TA (0x00020000)
|
|
+#define MCF_PCITSR_RE (0x00040000)
|
|
+#define MCF_PCITSR_SE (0x00080000)
|
|
+#define MCF_PCITSR_FE (0x00100000)
|
|
+#define MCF_PCITSR_BE1 (0x00200000)
|
|
+#define MCF_PCITSR_BE2 (0x00400000)
|
|
+#define MCF_PCITSR_BE3 (0x00800000)
|
|
+#define MCF_PCITSR_NT (0x01000000)
|
|
+
|
|
+/* Bit definitions and macros for MCF_PCITFSR */
|
|
+#define MCF_PCITFSR_EMT (0x00010000)
|
|
+#define MCF_PCITFSR_ALARM (0x00020000)
|
|
+#define MCF_PCITFSR_FU (0x00040000)
|
|
+#define MCF_PCITFSR_FR (0x00080000)
|
|
+#define MCF_PCITFSR_OF (0x00100000)
|
|
+#define MCF_PCITFSR_UF (0x00200000)
|
|
+#define MCF_PCITFSR_RXW (0x00400000)
|
|
+
|
|
+/* Bit definitions and macros for MCF_PCITFCR */
|
|
+#define MCF_PCITFCR_OF_MSK (0x00080000)
|
|
+#define MCF_PCITFCR_UF_MSK (0x00100000)
|
|
+#define MCF_PCITFCR_RXW_MSK (0x00200000)
|
|
+#define MCF_PCITFCR_FAE_MSK (0x00400000)
|
|
+#define MCF_PCITFCR_IP_MSK (0x00800000)
|
|
+#define MCF_PCITFCR_GR(x) (((x)&0x00000007)<<24)
|
|
+
|
|
+/* Bit definitions and macros for MCF_PCITFAR */
|
|
+#define MCF_PCITFAR_ALARM(x) (((x)&0x0000007F)<<0)
|
|
+
|
|
+/* Bit definitions and macros for MCF_PCITFRPR */
|
|
+#define MCF_PCITFRPR_READ(x) (((x)&0x00000FFF)<<0)
|
|
+
|
|
+/* Bit definitions and macros for MCF_PCITFWPR */
|
|
+#define MCF_PCITFWPR_WRITE(x) (((x)&0x00000FFF)<<0)
|
|
+
|
|
+/* Bit definitions and macros for MCF_PCIRPSR */
|
|
+#define MCF_PCIRPSR_PKTSIZE(x) (((x)&0x0000FFFF)<<16)
|
|
+
|
|
+/* Bit definitions and macros for MCF_PCIRTCR */
|
|
+#define MCF_PCIRTCR_DI (0x00000001)
|
|
+#define MCF_PCIRTCR_W (0x00000010)
|
|
+#define MCF_PCIRTCR_MAXBEATS(x) (((x)&0x00000007)<<8)
|
|
+#define MCF_PCIRTCR_FB (0x00001000)
|
|
+#define MCF_PCIRTCR_MAXRETRY(x) (((x)&0x000000FF)<<16)
|
|
+#define MCF_PCIRTCR_PCICMD(x) (((x)&0x0000000F)<<24)
|
|
+
|
|
+/* Bit definitions and macros for MCF_PCIRER */
|
|
+#define MCF_PCIRER_NE (0x00010000)
|
|
+#define MCF_PCIRER_IAE (0x00020000)
|
|
+#define MCF_PCIRER_TAE (0x00040000)
|
|
+#define MCF_PCIRER_RE (0x00080000)
|
|
+#define MCF_PCIRER_SE (0x00100000)
|
|
+#define MCF_PCIRER_FEE (0x00200000)
|
|
+#define MCF_PCIRER_ME (0x01000000)
|
|
+#define MCF_PCIRER_BE (0x08000000)
|
|
+#define MCF_PCIRER_CM (0x10000000)
|
|
+#define MCF_PCIRER_FE (0x20000000)
|
|
+#define MCF_PCIRER_RF (0x40000000)
|
|
+#define MCF_PCIRER_RC (0x80000000)
|
|
+
|
|
+/* Bit definitions and macros for MCF_PCIRDCR */
|
|
+#define MCF_PCIRDCR_PKTSDONE(x) (((x)&0x0000FFFF)<<0)
|
|
+#define MCF_PCIRDCR_BYTESDONE(x) (((x)&0x0000FFFF)<<16)
|
|
+
|
|
+/* Bit definitions and macros for MCF_PCIRSR */
|
|
+#define MCF_PCIRSR_IA (0x00010000)
|
|
+#define MCF_PCIRSR_TA (0x00020000)
|
|
+#define MCF_PCIRSR_RE (0x00040000)
|
|
+#define MCF_PCIRSR_SE (0x00080000)
|
|
+#define MCF_PCIRSR_FE (0x00100000)
|
|
+#define MCF_PCIRSR_BE1 (0x00200000)
|
|
+#define MCF_PCIRSR_BE2 (0x00400000)
|
|
+#define MCF_PCIRSR_BE3 (0x00800000)
|
|
+#define MCF_PCIRSR_NT (0x01000000)
|
|
+
|
|
+/* Bit definitions and macros for MCF_PCIRFSR */
|
|
+#define MCF_PCIRFSR_EMT (0x00010000)
|
|
+#define MCF_PCIRFSR_ALARM (0x00020000)
|
|
+#define MCF_PCIRFSR_FU (0x00040000)
|
|
+#define MCF_PCIRFSR_FR (0x00080000)
|
|
+#define MCF_PCIRFSR_OF (0x00100000)
|
|
+#define MCF_PCIRFSR_UF (0x00200000)
|
|
+#define MCF_PCIRFSR_RXW (0x00400000)
|
|
+
|
|
+/* Bit definitions and macros for MCF_PCIRFCR */
|
|
+#define MCF_PCIRFCR_OF_MSK (0x00080000)
|
|
+#define MCF_PCIRFCR_UF_MSK (0x00100000)
|
|
+#define MCF_PCIRFCR_RXW_MSK (0x00200000)
|
|
+#define MCF_PCIRFCR_FAE_MSK (0x00400000)
|
|
+#define MCF_PCIRFCR_IP_MSK (0x00800000)
|
|
+#define MCF_PCIRFCR_GR(x) (((x)&0x00000007)<<24)
|
|
+
|
|
+/* Bit definitions and macros for MCF_PCIRFAR */
|
|
+#define MCF_PCIRFAR_ALARM(x) (((x)&0x0000007F)<<0)
|
|
+
|
|
+/* Bit definitions and macros for MCF_PCIRFRPR */
|
|
+#define MCF_PCIRFRPR_READ(x) (((x)&0x00000FFF)<<0)
|
|
+
|
|
+/* Bit definitions and macros for MCF_PCIRFWPR */
|
|
+#define MCF_PCIRFWPR_WRITE(x) (((x)&0x00000FFF)<<0)
|
|
+
|
|
+
|
|
+/* Bit definitions and macros for MCF_PCIARB_PACR */
|
|
+#define MCF_PCIARB_PACR_INTMPRI (0x00000001)
|
|
+#define MCF_PCIARB_PACR_EXTMPRI(x) (((x)&0x0000001F)<<1)
|
|
+#define MCF_PCIARB_PACR_INTMINTEN (0x00010000)
|
|
+#define MCF_PCIARB_PACR_EXTMINTEN(x) (((x)&0x0000001F)<<17)
|
|
+#define MCF_PCIARB_PACR_PKMD (0x40000000)
|
|
+#define MCF_PCIARB_PACR_DS (0x80000000)
|
|
+
|
|
+/* Bit definitions and macros for MCF_PCIARB_PASR */
|
|
+#define MCF_PCIARB_PASR_ITLMBK (0x00010000)
|
|
+#define MCF_PCIARB_PASR_EXTMBK(x) (((x)&0x0000001F)<<17)
|
|
+
|
|
+#endif /* __MCF548X_PCI_H__ */
|
|
--- a/include/asm-m68k/pci.h
|
|
+++ b/include/asm-m68k/pci.h
|
|
@@ -1,94 +1,10 @@
|
|
-/*
|
|
- * asm-m68k/pci.h - m68k specific PCI declarations.
|
|
- *
|
|
- * Coldfire Implementation Copyright (c) 2007 Freescale Semiconductor, Inc.
|
|
- * Kurt Mahan <kmahan@freescale.com>
|
|
- */
|
|
-#ifndef _ASM_M68K_PCI_H
|
|
-#define _ASM_M68K_PCI_H
|
|
+#ifndef M68K_PCI_H
|
|
+#define M68K_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)
|
|
+#ifdef CONFIG_M5445X
|
|
+#include "5445x_pci.h"
|
|
#else
|
|
-#include <asm-generic/pci-dma-compat.h>
|
|
-
|
|
-/*
|
|
- * 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
|
|
-
|
|
-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 */
|
|
-}
|
|
+#include "548x_pci.h"
|
|
#endif
|
|
|
|
-static inline void
|
|
-pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region,
|
|
- struct resource *res)
|
|
-{
|
|
-#ifdef CONFIG_M54455
|
|
- if ((res->start == 0xa0000000) || (res->start == 0xa8000000)) {
|
|
- /* HACK! FIX! kludge to fix bridge mapping */
|
|
- region->start = res->start & 0x0fffffff;
|
|
- region->end = res->end & 0x0fffffff;
|
|
- } else {
|
|
- region->start = res->start;
|
|
- region->end = res->end;
|
|
- }
|
|
-#else
|
|
- region->start = res->start;
|
|
- region->end = res->end;
|
|
-#endif
|
|
-}
|
|
-
|
|
-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;
|
|
-}
|
|
-
|
|
-#endif /* CONFIG_PCI */
|
|
-#endif /* _ASM_M68K_PCI_H */
|
|
+#endif /* M68K_PCI_H */
|
|
--- a/include/asm-m68k/raw_io.h
|
|
+++ b/include/asm-m68k/raw_io.h
|
|
@@ -46,6 +46,29 @@ extern void __iounmap(void *addr, unsign
|
|
#define out_le16(addr,w) (void)((*(__force volatile __le16 *) (addr)) = cpu_to_le16(w))
|
|
#define out_le32(addr,l) (void)((*(__force volatile __le32 *) (addr)) = cpu_to_le32(l))
|
|
|
|
+#if (defined CONFIG_COLDFIRE) && (defined CONFIG_PCI)
|
|
+unsigned char pci_inb(long addr);
|
|
+unsigned short pci_inw(long addr);
|
|
+unsigned long pci_inl(long addr);
|
|
+void pci_outb(unsigned char val, long addr);
|
|
+void pci_outw(unsigned short val, long addr);
|
|
+void pci_outl(unsigned long val, long addr);
|
|
+unsigned short pci_raw_inw(long addr);
|
|
+unsigned long pci_raw_inl(long addr);
|
|
+void pci_raw_outw(unsigned short val, long addr);
|
|
+void pci_raw_outl(unsigned long val, long addr);
|
|
+#define raw_inb(port) pci_inb((long)((volatile unsigned char *)(port)))
|
|
+#define raw_inw(port) pci_raw_inw((long)((volatile unsigned short *)(port)))
|
|
+#define raw_inl(port) pci_raw_inl((long)((volatile unsigned long *)(port)))
|
|
+
|
|
+#define raw_outb(val,port) pci_outb((val),(long)((volatile unsigned char *)(port)))
|
|
+#define raw_outw(val,port) pci_raw_outw((val),(long)((volatile unsigned short *)(port)))
|
|
+#define raw_outl(val,port) pci_raw_outl((val),(long)((volatile unsigned long *)(port)))
|
|
+
|
|
+#define swap_inw(port) pci_inw((long)((volatile unsigned short *)(port)))
|
|
+#define swap_outw(val,port) pci_outw((val),(long)((volatile unsigned short *)(port)))
|
|
+
|
|
+#else
|
|
#define raw_inb in_8
|
|
#define raw_inw in_be16
|
|
#define raw_inl in_be32
|
|
@@ -60,6 +83,9 @@ extern void __iounmap(void *addr, unsign
|
|
#define __raw_writew(val,addr) out_be16((addr),(val))
|
|
#define __raw_writel(val,addr) out_be32((addr),(val))
|
|
|
|
+#define swap_inw(port) in_le16((port))
|
|
+#define swap_outw(val,port) out_le16((port),(val))
|
|
+#endif
|
|
static inline void raw_insb(volatile u8 __iomem *port, u8 *buf, unsigned int len)
|
|
{
|
|
unsigned int i;
|
|
--- a/include/asm-m68k/virtconvert.h
|
|
+++ b/include/asm-m68k/virtconvert.h
|
|
@@ -46,9 +46,14 @@ static inline void *phys_to_virt(unsigne
|
|
#define virt_to_bus(a) (virt_to_phys(a) + (MACH_IS_HADES ? 0x80000000 : 0))
|
|
#define bus_to_virt(a) (phys_to_virt((a) - (MACH_IS_HADES ? 0x80000000 : 0)))
|
|
#else
|
|
+#ifdef CONFIG_COLDFIRE
|
|
+#define virt_to_bus(a) (a - PAGE_OFFSET + PCI_DMA_BASE)
|
|
+#define bus_to_virt(a) (a - PCI_DMA_BASE + PAGE_OFFSET)
|
|
+#else /* CONFIG_COLDFIRE */
|
|
#define virt_to_bus virt_to_phys
|
|
#define bus_to_virt phys_to_virt
|
|
#endif
|
|
+#endif
|
|
|
|
#endif
|
|
#endif
|
|
--- a/include/linux/pci.h
|
|
+++ b/include/linux/pci.h
|
|
@@ -458,8 +458,10 @@ int __must_check pcibios_enable_device(s
|
|
char *pcibios_setup(char *str);
|
|
|
|
/* Used only when drivers/pci/setup.c is used */
|
|
+#ifndef CONFIG_COLDFIRE
|
|
void pcibios_align_resource(void *, struct resource *, resource_size_t,
|
|
resource_size_t);
|
|
+#endif
|
|
void pcibios_update_irq(struct pci_dev *, int irq);
|
|
|
|
/* Generic PCI functions used internally */
|