xref: /linux/arch/powerpc/platforms/pseries/pci.c (revision eeea8b40cd2866ca24f25e5ef09225edb076ae45)
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
35 void 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 }
58 DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, pcibios_name_device);
59 #endif
60 
61 static 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 
74 void __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  */
86 static 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 }
110 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_WINBOND, PCI_DEVICE_ID_WINBOND_82C105,
111 			 fixup_winbond_82c105);
112 
113 int 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 	/* Rely on the pcibios_free_controller_deferred() callback. */
123 	pci_set_host_bridge_release(bridge, pcibios_free_controller_deferred,
124 					(void *) pci_bus_to_host(bus));
125 
126 	dn = pcibios_get_phb_of_node(bus);
127 	if (!dn)
128 		return 0;
129 
130 	for (pdn = dn; pdn != NULL; pdn = of_get_next_parent(pdn)) {
131 		rc = of_property_read_u32_array(pdn,
132 				"ibm,pcie-link-speed-stats",
133 				&pcie_link_speed_stats[0], 2);
134 		if (!rc)
135 			break;
136 	}
137 
138 	of_node_put(pdn);
139 
140 	if (rc) {
141 		pr_debug("no ibm,pcie-link-speed-stats property\n");
142 		return 0;
143 	}
144 
145 	switch (pcie_link_speed_stats[0]) {
146 	case 0x01:
147 		bus->max_bus_speed = PCIE_SPEED_2_5GT;
148 		break;
149 	case 0x02:
150 		bus->max_bus_speed = PCIE_SPEED_5_0GT;
151 		break;
152 	case 0x04:
153 		bus->max_bus_speed = PCIE_SPEED_8_0GT;
154 		break;
155 	default:
156 		bus->max_bus_speed = PCI_SPEED_UNKNOWN;
157 		break;
158 	}
159 
160 	switch (pcie_link_speed_stats[1]) {
161 	case 0x01:
162 		bus->cur_bus_speed = PCIE_SPEED_2_5GT;
163 		break;
164 	case 0x02:
165 		bus->cur_bus_speed = PCIE_SPEED_5_0GT;
166 		break;
167 	case 0x04:
168 		bus->cur_bus_speed = PCIE_SPEED_8_0GT;
169 		break;
170 	default:
171 		bus->cur_bus_speed = PCI_SPEED_UNKNOWN;
172 		break;
173 	}
174 
175 	return 0;
176 }
177