linux/arch/powerpc/platforms/pseries/pci.c
<<
>>
Prefs
   1/*
   2 * Copyright (C) 2001 Dave Engebretsen, IBM Corporation
   3 * Copyright (C) 2003 Anton Blanchard <anton@au.ibm.com>, IBM
   4 *
   5 * pSeries specific routines for PCI.
   6 * 
   7 * This program is free software; you can redistribute it and/or modify
   8 * it under the terms of the GNU General Public License as published by
   9 * the Free Software Foundation; either version 2 of the License, or
  10 * (at your option) any later version.
  11 *    
  12 * This program is distributed in the hope that it will be useful,
  13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15 * GNU General Public License for more details.
  16 * 
  17 * You should have received a copy of the GNU General Public License
  18 * along with this program; if not, write to the Free Software
  19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
  20 */
  21
  22#include <linux/init.h>
  23#include <linux/ioport.h>
  24#include <linux/kernel.h>
  25#include <linux/pci.h>
  26#include <linux/string.h>
  27
  28#include <asm/eeh.h>
  29#include <asm/pci-bridge.h>
  30#include <asm/prom.h>
  31#include <asm/ppc-pci.h>
  32#include "pseries.h"
  33
  34#if 0
  35void pcibios_name_device(struct pci_dev *dev)
  36{
  37        struct device_node *dn;
  38
  39        /*
  40         * Add IBM loc code (slot) as a prefix to the device names for service
  41         */
  42        dn = pci_device_to_OF_node(dev);
  43        if (dn) {
  44                const char *loc_code = of_get_property(dn, "ibm,loc-code",
  45                                NULL);
  46                if (loc_code) {
  47                        int loc_len = strlen(loc_code);
  48                        if (loc_len < sizeof(dev->dev.name)) {
  49                                memmove(dev->dev.name+loc_len+1, dev->dev.name,
  50                                        sizeof(dev->dev.name)-loc_len-1);
  51                                memcpy(dev->dev.name, loc_code, loc_len);
  52                                dev->dev.name[loc_len] = ' ';
  53                                dev->dev.name[sizeof(dev->dev.name)-1] = '\0';
  54                        }
  55                }
  56        }
  57}   
  58DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, pcibios_name_device);
  59#endif
  60
  61static void __init pSeries_request_regions(void)
  62{
  63        if (!isa_io_base)
  64                return;
  65
  66        request_region(0x20,0x20,"pic1");
  67        request_region(0xa0,0x20,"pic2");
  68        request_region(0x00,0x20,"dma1");
  69        request_region(0x40,0x20,"timer");
  70        request_region(0x80,0x10,"dma page reg");
  71        request_region(0xc0,0x20,"dma2");
  72}
  73
  74void __init pSeries_final_fixup(void)
  75{
  76        pSeries_request_regions();
  77
  78        eeh_addr_cache_build();
  79}
  80
  81/*
  82 * Assume the winbond 82c105 is the IDE controller on a
  83 * p610/p615/p630. We should probably be more careful in case
  84 * someone tries to plug in a similar adapter.
  85 */
  86static void fixup_winbond_82c105(struct pci_dev* dev)
  87{
  88        int i;
  89        unsigned int reg;
  90
  91        if (!machine_is(pseries))
  92                return;
  93
  94        printk("Using INTC for W82c105 IDE controller.\n");
  95        pci_read_config_dword(dev, 0x40, &reg);
  96        /* Enable LEGIRQ to use INTC instead of ISA interrupts */
  97        pci_write_config_dword(dev, 0x40, reg | (1<<11));
  98
  99        for (i = 0; i < DEVICE_COUNT_RESOURCE; ++i) {
 100                /* zap the 2nd function of the winbond chip */
 101                if (dev->resource[i].flags & IORESOURCE_IO
 102                    && dev->bus->number == 0 && dev->devfn == 0x81)
 103                        dev->resource[i].flags &= ~IORESOURCE_IO;
 104                if (dev->resource[i].start == 0 && dev->resource[i].end) {
 105                        dev->resource[i].flags = 0;
 106                        dev->resource[i].end = 0;
 107                }
 108        }
 109}
 110DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_WINBOND, PCI_DEVICE_ID_WINBOND_82C105,
 111                         fixup_winbond_82c105);
 112
 113int pseries_root_bridge_prepare(struct pci_host_bridge *bridge)
 114{
 115        struct device_node *dn, *pdn;
 116        struct pci_bus *bus;
 117        u32 pcie_link_speed_stats[2];
 118        int rc;
 119
 120        bus = bridge->bus;
 121
 122        dn = pcibios_get_phb_of_node(bus);
 123        if (!dn)
 124                return 0;
 125
 126        for (pdn = dn; pdn != NULL; pdn = of_get_next_parent(pdn)) {
 127                rc = of_property_read_u32_array(pdn,
 128                                "ibm,pcie-link-speed-stats",
 129                                &pcie_link_speed_stats[0], 2);
 130                if (!rc)
 131                        break;
 132        }
 133
 134        of_node_put(pdn);
 135
 136        if (rc) {
 137                pr_debug("no ibm,pcie-link-speed-stats property\n");
 138                return 0;
 139        }
 140
 141        switch (pcie_link_speed_stats[0]) {
 142        case 0x01:
 143                bus->max_bus_speed = PCIE_SPEED_2_5GT;
 144                break;
 145        case 0x02:
 146                bus->max_bus_speed = PCIE_SPEED_5_0GT;
 147                break;
 148        case 0x04:
 149                bus->max_bus_speed = PCIE_SPEED_8_0GT;
 150                break;
 151        default:
 152                bus->max_bus_speed = PCI_SPEED_UNKNOWN;
 153                break;
 154        }
 155
 156        switch (pcie_link_speed_stats[1]) {
 157        case 0x01:
 158                bus->cur_bus_speed = PCIE_SPEED_2_5GT;
 159                break;
 160        case 0x02:
 161                bus->cur_bus_speed = PCIE_SPEED_5_0GT;
 162                break;
 163        case 0x04:
 164                bus->cur_bus_speed = PCIE_SPEED_8_0GT;
 165                break;
 166        default:
 167                bus->cur_bus_speed = PCI_SPEED_UNKNOWN;
 168                break;
 169        }
 170
 171        return 0;
 172}
 173