diff options
| -rw-r--r-- | arch/arm/mach-sa1100/pci-nanoengine.c | 94 |
1 files changed, 8 insertions, 86 deletions
diff --git a/arch/arm/mach-sa1100/pci-nanoengine.c b/arch/arm/mach-sa1100/pci-nanoengine.c index b704433c529c..d7ae8d50f6d8 100644 --- a/arch/arm/mach-sa1100/pci-nanoengine.c +++ b/arch/arm/mach-sa1100/pci-nanoengine.c | |||
| @@ -22,7 +22,6 @@ | |||
| 22 | #include <linux/kernel.h> | 22 | #include <linux/kernel.h> |
| 23 | #include <linux/irq.h> | 23 | #include <linux/irq.h> |
| 24 | #include <linux/pci.h> | 24 | #include <linux/pci.h> |
| 25 | #include <linux/spinlock.h> | ||
| 26 | 25 | ||
| 27 | #include <asm/mach/pci.h> | 26 | #include <asm/mach/pci.h> |
| 28 | #include <asm/mach-types.h> | 27 | #include <asm/mach-types.h> |
| @@ -30,97 +29,20 @@ | |||
| 30 | #include <mach/nanoengine.h> | 29 | #include <mach/nanoengine.h> |
| 31 | #include <mach/hardware.h> | 30 | #include <mach/hardware.h> |
| 32 | 31 | ||
| 33 | static DEFINE_SPINLOCK(nano_lock); | 32 | static void __iomem *nanoengine_pci_map_bus(struct pci_bus *bus, |
| 34 | 33 | unsigned int devfn, int where) | |
| 35 | static int nanoengine_get_pci_address(struct pci_bus *bus, | ||
| 36 | unsigned int devfn, int where, void __iomem **address) | ||
| 37 | { | 34 | { |
| 38 | int ret = PCIBIOS_DEVICE_NOT_FOUND; | 35 | if (bus->number != 0 || (devfn >> 3) != 0) |
| 39 | unsigned int busnr = bus->number; | 36 | return NULL; |
| 40 | 37 | ||
| 41 | *address = (void __iomem *)NANO_PCI_CONFIG_SPACE_VIRT + | 38 | return (void __iomem *)NANO_PCI_CONFIG_SPACE_VIRT + |
| 42 | ((bus->number << 16) | (devfn << 8) | (where & ~3)); | 39 | ((bus->number << 16) | (devfn << 8) | (where & ~3)); |
| 43 | |||
| 44 | ret = (busnr > 255 || devfn > 255 || where > 255) ? | ||
| 45 | PCIBIOS_DEVICE_NOT_FOUND : PCIBIOS_SUCCESSFUL; | ||
| 46 | |||
| 47 | return ret; | ||
| 48 | } | ||
| 49 | |||
| 50 | static int nanoengine_read_config(struct pci_bus *bus, unsigned int devfn, int where, | ||
| 51 | int size, u32 *val) | ||
| 52 | { | ||
| 53 | int ret; | ||
| 54 | void __iomem *address; | ||
| 55 | unsigned long flags; | ||
| 56 | u32 v; | ||
| 57 | |||
| 58 | /* nanoEngine PCI bridge does not return -1 for a non-existing | ||
| 59 | * device. We must fake the answer. We know that the only valid | ||
| 60 | * device is device zero at bus 0, which is the network chip. */ | ||
| 61 | if (bus->number != 0 || (devfn >> 3) != 0) { | ||
| 62 | v = -1; | ||
| 63 | nanoengine_get_pci_address(bus, devfn, where, &address); | ||
| 64 | goto exit_function; | ||
| 65 | } | ||
| 66 | |||
| 67 | spin_lock_irqsave(&nano_lock, flags); | ||
| 68 | |||
| 69 | ret = nanoengine_get_pci_address(bus, devfn, where, &address); | ||
| 70 | if (ret != PCIBIOS_SUCCESSFUL) | ||
| 71 | return ret; | ||
| 72 | v = __raw_readl(address); | ||
| 73 | |||
| 74 | spin_unlock_irqrestore(&nano_lock, flags); | ||
| 75 | |||
| 76 | v >>= ((where & 3) * 8); | ||
| 77 | v &= (unsigned long)(-1) >> ((4 - size) * 8); | ||
| 78 | |||
| 79 | exit_function: | ||
| 80 | *val = v; | ||
| 81 | return PCIBIOS_SUCCESSFUL; | ||
| 82 | } | ||
| 83 | |||
| 84 | static int nanoengine_write_config(struct pci_bus *bus, unsigned int devfn, int where, | ||
| 85 | int size, u32 val) | ||
| 86 | { | ||
| 87 | int ret; | ||
| 88 | void __iomem *address; | ||
| 89 | unsigned long flags; | ||
| 90 | unsigned shift; | ||
| 91 | u32 v; | ||
| 92 | |||
| 93 | shift = (where & 3) * 8; | ||
| 94 | |||
| 95 | spin_lock_irqsave(&nano_lock, flags); | ||
| 96 | |||
| 97 | ret = nanoengine_get_pci_address(bus, devfn, where, &address); | ||
| 98 | if (ret != PCIBIOS_SUCCESSFUL) | ||
| 99 | return ret; | ||
| 100 | v = __raw_readl(address); | ||
| 101 | switch (size) { | ||
| 102 | case 1: | ||
| 103 | v &= ~(0xFF << shift); | ||
| 104 | v |= val << shift; | ||
| 105 | break; | ||
| 106 | case 2: | ||
| 107 | v &= ~(0xFFFF << shift); | ||
| 108 | v |= val << shift; | ||
| 109 | break; | ||
| 110 | case 4: | ||
| 111 | v = val; | ||
| 112 | break; | ||
| 113 | } | ||
| 114 | __raw_writel(v, address); | ||
| 115 | |||
| 116 | spin_unlock_irqrestore(&nano_lock, flags); | ||
| 117 | |||
| 118 | return PCIBIOS_SUCCESSFUL; | ||
| 119 | } | 40 | } |
| 120 | 41 | ||
| 121 | static struct pci_ops pci_nano_ops = { | 42 | static struct pci_ops pci_nano_ops = { |
| 122 | .read = nanoengine_read_config, | 43 | .map_bus = nanoengine_pci_map_bus, |
| 123 | .write = nanoengine_write_config, | 44 | .read = pci_generic_config_read32, |
| 45 | .write = pci_generic_config_write32, | ||
| 124 | }; | 46 | }; |
| 125 | 47 | ||
| 126 | static int __init pci_nanoengine_map_irq(const struct pci_dev *dev, u8 slot, | 48 | static int __init pci_nanoengine_map_irq(const struct pci_dev *dev, u8 slot, |
