linux/arch/arm/mach-sa1100/pci-nanoengine.c
<<
>>
Prefs
   1/*
   2 * linux/arch/arm/mach-sa1100/pci-nanoengine.c
   3 *
   4 * PCI functions for BSE nanoEngine PCI
   5 *
   6 * Copyright (C) 2010 Marcelo Roberto Jimenez <mroberto@cpti.cetuc.puc-rio.br>
   7 *
   8 * This program is free software; you can redistribute it and/or modify
   9 * it under the terms of the GNU General Public License as published by
  10 * the Free Software Foundation; either version 2 of the License, or
  11 * (at your option) any later version.
  12 *
  13 * This program is distributed in the hope that it will be useful,
  14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16 * GNU General Public License for more details.
  17 *
  18 * You should have received a copy of the GNU General Public License
  19 * along with this program; if not, write to the Free Software
  20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  21 */
  22#include <linux/kernel.h>
  23#include <linux/irq.h>
  24#include <linux/pci.h>
  25#include <linux/spinlock.h>
  26
  27#include <asm/mach/pci.h>
  28#include <asm/mach-types.h>
  29
  30#include <mach/nanoengine.h>
  31#include <mach/hardware.h>
  32
  33static DEFINE_SPINLOCK(nano_lock);
  34
  35static int nanoengine_get_pci_address(struct pci_bus *bus,
  36        unsigned int devfn, int where, unsigned long *address)
  37{
  38        int ret = PCIBIOS_DEVICE_NOT_FOUND;
  39        unsigned int busnr = bus->number;
  40
  41        *address = NANO_PCI_CONFIG_SPACE_VIRT +
  42                ((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
  50static int nanoengine_read_config(struct pci_bus *bus, unsigned int devfn, int where,
  51        int size, u32 *val)
  52{
  53        int ret;
  54        unsigned long 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
  79exit_function:
  80        *val = v;
  81        return PCIBIOS_SUCCESSFUL;
  82}
  83
  84static int nanoengine_write_config(struct pci_bus *bus, unsigned int devfn, int where,
  85        int size, u32 val)
  86{
  87        int ret;
  88        unsigned long 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}
 120
 121static struct pci_ops pci_nano_ops = {
 122        .read   = nanoengine_read_config,
 123        .write  = nanoengine_write_config,
 124};
 125
 126static int __init pci_nanoengine_map_irq(const struct pci_dev *dev, u8 slot,
 127        u8 pin)
 128{
 129        return NANOENGINE_IRQ_GPIO_PCI;
 130}
 131
 132static struct resource pci_io_ports =
 133        DEFINE_RES_IO_NAMED(0x400, 0x400, "PCI IO");
 134
 135static struct resource pci_non_prefetchable_memory = {
 136        .name   = "PCI non-prefetchable",
 137        .start  = NANO_PCI_MEM_RW_PHYS,
 138        /* nanoEngine documentation says there is a 1 Megabyte window here,
 139         * but PCI reports just 128 + 8 kbytes. */
 140        .end    = NANO_PCI_MEM_RW_PHYS + NANO_PCI_MEM_RW_SIZE - 1,
 141/*      .end    = NANO_PCI_MEM_RW_PHYS + SZ_128K + SZ_8K - 1,*/
 142        .flags  = IORESOURCE_MEM,
 143};
 144
 145/*
 146 * nanoEngine PCI reports 1 Megabyte of prefetchable memory, but it
 147 * overlaps with previously defined memory.
 148 *
 149 * Here is what happens:
 150 *
 151# dmesg
 152...
 153pci 0000:00:00.0: [8086:1209] type 0 class 0x000200
 154pci 0000:00:00.0: reg 10: [mem 0x00021000-0x00021fff]
 155pci 0000:00:00.0: reg 14: [io  0x0000-0x003f]
 156pci 0000:00:00.0: reg 18: [mem 0x00000000-0x0001ffff]
 157pci 0000:00:00.0: reg 30: [mem 0x00000000-0x000fffff pref]
 158pci 0000:00:00.0: supports D1 D2
 159pci 0000:00:00.0: PME# supported from D0 D1 D2 D3hot
 160pci 0000:00:00.0: PME# disabled
 161PCI: bus0: Fast back to back transfers enabled
 162pci 0000:00:00.0: BAR 6: can't assign mem pref (size 0x100000)
 163pci 0000:00:00.0: BAR 2: assigned [mem 0x18600000-0x1861ffff]
 164pci 0000:00:00.0: BAR 2: set to [mem 0x18600000-0x1861ffff] (PCI address [0x0-0x1ffff])
 165pci 0000:00:00.0: BAR 0: assigned [mem 0x18620000-0x18620fff]
 166pci 0000:00:00.0: BAR 0: set to [mem 0x18620000-0x18620fff] (PCI address [0x20000-0x20fff])
 167pci 0000:00:00.0: BAR 1: assigned [io  0x0400-0x043f]
 168pci 0000:00:00.0: BAR 1: set to [io  0x0400-0x043f] (PCI address [0x0-0x3f])
 169 *
 170 * On the other hand, if we do not request the prefetchable memory resource,
 171 * linux will alloc it first and the two non-prefetchable memory areas that
 172 * are our real interest will not be mapped. So we choose to map it to an
 173 * unused area. It gets recognized as expansion ROM, but becomes disabled.
 174 *
 175 * Here is what happens then:
 176 *
 177# dmesg
 178...
 179pci 0000:00:00.0: [8086:1209] type 0 class 0x000200
 180pci 0000:00:00.0: reg 10: [mem 0x00021000-0x00021fff]
 181pci 0000:00:00.0: reg 14: [io  0x0000-0x003f]
 182pci 0000:00:00.0: reg 18: [mem 0x00000000-0x0001ffff]
 183pci 0000:00:00.0: reg 30: [mem 0x00000000-0x000fffff pref]
 184pci 0000:00:00.0: supports D1 D2
 185pci 0000:00:00.0: PME# supported from D0 D1 D2 D3hot
 186pci 0000:00:00.0: PME# disabled
 187PCI: bus0: Fast back to back transfers enabled
 188pci 0000:00:00.0: BAR 6: assigned [mem 0x78000000-0x780fffff pref]
 189pci 0000:00:00.0: BAR 2: assigned [mem 0x18600000-0x1861ffff]
 190pci 0000:00:00.0: BAR 2: set to [mem 0x18600000-0x1861ffff] (PCI address [0x0-0x1ffff])
 191pci 0000:00:00.0: BAR 0: assigned [mem 0x18620000-0x18620fff]
 192pci 0000:00:00.0: BAR 0: set to [mem 0x18620000-0x18620fff] (PCI address [0x20000-0x20fff])
 193pci 0000:00:00.0: BAR 1: assigned [io  0x0400-0x043f]
 194pci 0000:00:00.0: BAR 1: set to [io  0x0400-0x043f] (PCI address [0x0-0x3f])
 195
 196# lspci -vv -s 0000:00:00.0
 19700:00.0 Class 0200: Device 8086:1209 (rev 09)
 198        Control: I/O+ Mem+ BusMaster+ SpecCycle- MemWINV- VGASnoop- ParErr+ Stepping- SERR+ FastB2B- DisINTx-
 199        Status: Cap+ 66MHz- UDF- FastB2B+ ParErr- DEVSEL=medium >TAbort- <TAbort- <MAbort- >SERR+ <PERR+ INTx-
 200        Latency: 0 (2000ns min, 14000ns max), Cache Line Size: 32 bytes
 201        Interrupt: pin A routed to IRQ 0
 202        Region 0: Memory at 18620000 (32-bit, non-prefetchable) [size=4K]
 203        Region 1: I/O ports at 0400 [size=64]
 204        Region 2: [virtual] Memory at 18600000 (32-bit, non-prefetchable) [size=128K]
 205        [virtual] Expansion ROM at 78000000 [disabled] [size=1M]
 206        Capabilities: [dc] Power Management version 2
 207                Flags: PMEClk- DSI+ D1+ D2+ AuxCurrent=0mA PME(D0+,D1+,D2+,D3hot+,D3cold-)
 208                Status: D0 NoSoftRst- PME-Enable- DSel=0 DScale=2 PME-
 209        Kernel driver in use: e100
 210        Kernel modules: e100
 211 *
 212 */
 213static struct resource pci_prefetchable_memory = {
 214        .name   = "PCI prefetchable",
 215        .start  = 0x78000000,
 216        .end    = 0x78000000 + NANO_PCI_MEM_RW_SIZE - 1,
 217        .flags  = IORESOURCE_MEM  | IORESOURCE_PREFETCH,
 218};
 219
 220static int __init pci_nanoengine_setup_resources(struct pci_sys_data *sys)
 221{
 222        if (request_resource(&ioport_resource, &pci_io_ports)) {
 223                printk(KERN_ERR "PCI: unable to allocate io port region\n");
 224                return -EBUSY;
 225        }
 226        if (request_resource(&iomem_resource, &pci_non_prefetchable_memory)) {
 227                release_resource(&pci_io_ports);
 228                printk(KERN_ERR "PCI: unable to allocate non prefetchable\n");
 229                return -EBUSY;
 230        }
 231        if (request_resource(&iomem_resource, &pci_prefetchable_memory)) {
 232                release_resource(&pci_io_ports);
 233                release_resource(&pci_non_prefetchable_memory);
 234                printk(KERN_ERR "PCI: unable to allocate prefetchable\n");
 235                return -EBUSY;
 236        }
 237        pci_add_resource_offset(&sys->resources, &pci_io_ports, sys->io_offset);
 238        pci_add_resource_offset(&sys->resources,
 239                                &pci_non_prefetchable_memory, sys->mem_offset);
 240        pci_add_resource_offset(&sys->resources,
 241                                &pci_prefetchable_memory, sys->mem_offset);
 242
 243        return 1;
 244}
 245
 246int __init pci_nanoengine_setup(int nr, struct pci_sys_data *sys)
 247{
 248        int ret = 0;
 249
 250        pcibios_min_io = 0;
 251        pcibios_min_mem = 0;
 252
 253        if (nr == 0) {
 254                sys->mem_offset = NANO_PCI_MEM_RW_PHYS;
 255                sys->io_offset = 0x400;
 256                ret = pci_nanoengine_setup_resources(sys);
 257                /* Enable alternate memory bus master mode, see
 258                 * "Intel StrongARM SA1110 Developer's Manual",
 259                 * section 10.8, "Alternate Memory Bus Master Mode". */
 260                GPDR = (GPDR & ~GPIO_MBREQ) | GPIO_MBGNT;
 261                GAFR |= GPIO_MBGNT | GPIO_MBREQ;
 262                TUCR |= TUCR_MBGPIO;
 263        }
 264
 265        return ret;
 266}
 267
 268static struct hw_pci nanoengine_pci __initdata = {
 269        .map_irq                = pci_nanoengine_map_irq,
 270        .nr_controllers         = 1,
 271        .ops                    = &pci_nano_ops,
 272        .setup                  = pci_nanoengine_setup,
 273};
 274
 275static int __init nanoengine_pci_init(void)
 276{
 277        if (machine_is_nanoengine())
 278                pci_common_init(&nanoengine_pci);
 279        return 0;
 280}
 281
 282subsys_initcall(nanoengine_pci_init);
 283