linux/arch/powerpc/kernel/isa-bridge.c
<<
>>
Prefs
   1/*
   2 * Routines for tracking a legacy ISA bridge
   3 *
   4 * Copyrigh 2007 Benjamin Herrenschmidt <benh@kernel.crashing.org>, IBM Corp.
   5 *
   6 * Some bits and pieces moved over from pci_64.c
   7 *
   8 * Copyrigh 2003 Anton Blanchard <anton@au.ibm.com>, IBM Corp.
   9 *
  10 *      This program is free software; you can redistribute it and/or
  11 *      modify it under the terms of the GNU General Public License
  12 *      as published by the Free Software Foundation; either version
  13 *      2 of the License, or (at your option) any later version.
  14 */
  15
  16#define DEBUG
  17
  18#include <linux/kernel.h>
  19#include <linux/pci.h>
  20#include <linux/string.h>
  21#include <linux/export.h>
  22#include <linux/init.h>
  23#include <linux/mm.h>
  24#include <linux/notifier.h>
  25
  26#include <asm/processor.h>
  27#include <asm/io.h>
  28#include <asm/prom.h>
  29#include <asm/pci-bridge.h>
  30#include <asm/machdep.h>
  31#include <asm/ppc-pci.h>
  32
  33unsigned long isa_io_base;      /* NULL if no ISA bus */
  34EXPORT_SYMBOL(isa_io_base);
  35
  36/* Cached ISA bridge dev. */
  37static struct device_node *isa_bridge_devnode;
  38struct pci_dev *isa_bridge_pcidev;
  39EXPORT_SYMBOL_GPL(isa_bridge_pcidev);
  40
  41#define ISA_SPACE_MASK 0x1
  42#define ISA_SPACE_IO 0x1
  43
  44static void pci_process_ISA_OF_ranges(struct device_node *isa_node,
  45                                      unsigned long phb_io_base_phys)
  46{
  47        /* We should get some saner parsing here and remove these structs */
  48        struct pci_address {
  49                u32 a_hi;
  50                u32 a_mid;
  51                u32 a_lo;
  52        };
  53
  54        struct isa_address {
  55                u32 a_hi;
  56                u32 a_lo;
  57        };
  58
  59        struct isa_range {
  60                struct isa_address isa_addr;
  61                struct pci_address pci_addr;
  62                unsigned int size;
  63        };
  64
  65        const struct isa_range *range;
  66        unsigned long pci_addr;
  67        unsigned int isa_addr;
  68        unsigned int size;
  69        int rlen = 0;
  70
  71        range = of_get_property(isa_node, "ranges", &rlen);
  72        if (range == NULL || (rlen < sizeof(struct isa_range)))
  73                goto inval_range;
  74
  75        /* From "ISA Binding to 1275"
  76         * The ranges property is laid out as an array of elements,
  77         * each of which comprises:
  78         *   cells 0 - 1:       an ISA address
  79         *   cells 2 - 4:       a PCI address
  80         *                      (size depending on dev->n_addr_cells)
  81         *   cell 5:            the size of the range
  82         */
  83        if ((range->isa_addr.a_hi & ISA_SPACE_MASK) != ISA_SPACE_IO) {
  84                range++;
  85                rlen -= sizeof(struct isa_range);
  86                if (rlen < sizeof(struct isa_range))
  87                        goto inval_range;
  88        }
  89        if ((range->isa_addr.a_hi & ISA_SPACE_MASK) != ISA_SPACE_IO)
  90                goto inval_range;
  91
  92        isa_addr = range->isa_addr.a_lo;
  93        pci_addr = (unsigned long) range->pci_addr.a_mid << 32 |
  94                range->pci_addr.a_lo;
  95
  96        /* Assume these are both zero. Note: We could fix that and
  97         * do a proper parsing instead ... oh well, that will do for
  98         * now as nobody uses fancy mappings for ISA bridges
  99         */
 100        if ((pci_addr != 0) || (isa_addr != 0)) {
 101                printk(KERN_ERR "unexpected isa to pci mapping: %s\n",
 102                       __func__);
 103                return;
 104        }
 105
 106        /* Align size and make sure it's cropped to 64K */
 107        size = PAGE_ALIGN(range->size);
 108        if (size > 0x10000)
 109                size = 0x10000;
 110
 111        __ioremap_at(phb_io_base_phys, (void *)ISA_IO_BASE,
 112                     size, _PAGE_NO_CACHE|_PAGE_GUARDED);
 113        return;
 114
 115inval_range:
 116        printk(KERN_ERR "no ISA IO ranges or unexpected isa range, "
 117               "mapping 64k\n");
 118        __ioremap_at(phb_io_base_phys, (void *)ISA_IO_BASE,
 119                     0x10000, _PAGE_NO_CACHE|_PAGE_GUARDED);
 120}
 121
 122
 123/**
 124 * isa_bridge_find_early - Find and map the ISA IO space early before
 125 *                         main PCI discovery. This is optionally called by
 126 *                         the arch code when adding PCI PHBs to get early
 127 *                         access to ISA IO ports
 128 */
 129void __init isa_bridge_find_early(struct pci_controller *hose)
 130{
 131        struct device_node *np, *parent = NULL, *tmp;
 132
 133        /* If we already have an ISA bridge, bail off */
 134        if (isa_bridge_devnode != NULL)
 135                return;
 136
 137        /* For each "isa" node in the system. Note : we do a search by
 138         * type and not by name. It might be better to do by name but that's
 139         * what the code used to do and I don't want to break too much at
 140         * once. We can look into changing that separately
 141         */
 142        for_each_node_by_type(np, "isa") {
 143                /* Look for our hose being a parent */
 144                for (parent = of_get_parent(np); parent;) {
 145                        if (parent == hose->dn) {
 146                                of_node_put(parent);
 147                                break;
 148                        }
 149                        tmp = parent;
 150                        parent = of_get_parent(parent);
 151                        of_node_put(tmp);
 152                }
 153                if (parent != NULL)
 154                        break;
 155        }
 156        if (np == NULL)
 157                return;
 158        isa_bridge_devnode = np;
 159
 160        /* Now parse the "ranges" property and setup the ISA mapping */
 161        pci_process_ISA_OF_ranges(np, hose->io_base_phys);
 162
 163        /* Set the global ISA io base to indicate we have an ISA bridge */
 164        isa_io_base = ISA_IO_BASE;
 165
 166        pr_debug("ISA bridge (early) is %s\n", np->full_name);
 167}
 168
 169/**
 170 * isa_bridge_find_late - Find and map the ISA IO space upon discovery of
 171 *                        a new ISA bridge
 172 */
 173static void isa_bridge_find_late(struct pci_dev *pdev,
 174                                 struct device_node *devnode)
 175{
 176        struct pci_controller *hose = pci_bus_to_host(pdev->bus);
 177
 178        /* Store ISA device node and PCI device */
 179        isa_bridge_devnode = of_node_get(devnode);
 180        isa_bridge_pcidev = pdev;
 181
 182        /* Now parse the "ranges" property and setup the ISA mapping */
 183        pci_process_ISA_OF_ranges(devnode, hose->io_base_phys);
 184
 185        /* Set the global ISA io base to indicate we have an ISA bridge */
 186        isa_io_base = ISA_IO_BASE;
 187
 188        pr_debug("ISA bridge (late) is %s on %s\n",
 189                 devnode->full_name, pci_name(pdev));
 190}
 191
 192/**
 193 * isa_bridge_remove - Remove/unmap an ISA bridge
 194 */
 195static void isa_bridge_remove(void)
 196{
 197        pr_debug("ISA bridge removed !\n");
 198
 199        /* Clear the global ISA io base to indicate that we have no more
 200         * ISA bridge. Note that drivers don't quite handle that, though
 201         * we should probably do something about it. But do we ever really
 202         * have ISA bridges being removed on machines using legacy devices ?
 203         */
 204        isa_io_base = ISA_IO_BASE;
 205
 206        /* Clear references to the bridge */
 207        of_node_put(isa_bridge_devnode);
 208        isa_bridge_devnode = NULL;
 209        isa_bridge_pcidev = NULL;
 210
 211        /* Unmap the ISA area */
 212        __iounmap_at((void *)ISA_IO_BASE, 0x10000);
 213}
 214
 215/**
 216 * isa_bridge_notify - Get notified of PCI devices addition/removal
 217 */
 218static int isa_bridge_notify(struct notifier_block *nb, unsigned long action,
 219                             void *data)
 220{
 221        struct device *dev = data;
 222        struct pci_dev *pdev = to_pci_dev(dev);
 223        struct device_node *devnode = pci_device_to_OF_node(pdev);
 224
 225        switch(action) {
 226        case BUS_NOTIFY_ADD_DEVICE:
 227                /* Check if we have an early ISA device, without PCI dev */
 228                if (isa_bridge_devnode && isa_bridge_devnode == devnode &&
 229                    !isa_bridge_pcidev) {
 230                        pr_debug("ISA bridge PCI attached: %s\n",
 231                                 pci_name(pdev));
 232                        isa_bridge_pcidev = pdev;
 233                }
 234
 235                /* Check if we have no ISA device, and this happens to be one,
 236                 * register it as such if it has an OF device
 237                 */
 238                if (!isa_bridge_devnode && devnode && devnode->type &&
 239                    !strcmp(devnode->type, "isa"))
 240                        isa_bridge_find_late(pdev, devnode);
 241
 242                return 0;
 243        case BUS_NOTIFY_DEL_DEVICE:
 244                /* Check if this our existing ISA device */
 245                if (pdev == isa_bridge_pcidev ||
 246                    (devnode && devnode == isa_bridge_devnode))
 247                        isa_bridge_remove();
 248                return 0;
 249        }
 250        return 0;
 251}
 252
 253static struct notifier_block isa_bridge_notifier = {
 254        .notifier_call = isa_bridge_notify
 255};
 256
 257/**
 258 * isa_bridge_init - register to be notified of ISA bridge addition/removal
 259 *
 260 */
 261static int __init isa_bridge_init(void)
 262{
 263        bus_register_notifier(&pci_bus_type, &isa_bridge_notifier);
 264        return 0;
 265}
 266arch_initcall(isa_bridge_init);
 267