1 /*-
2 * Copyright (c) 1997, Stefan Esser <se@freebsd.org>
3 * Copyright (c) 2000, Michael Smith <msmith@freebsd.org>
4 * Copyright (c) 2000, BSDi
5 * Copyright (c) 2003, Thomas Moestl <tmm@FreeBSD.org>
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice unmodified, this list of conditions, and the following
13 * disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 *
29 * $FreeBSD$
30 */
31
32 #include "opt_ofw_pci.h"
33
34 #include <sys/param.h>
35 #include <sys/bus.h>
36 #include <sys/kernel.h>
37 #include <sys/libkern.h>
38 #include <sys/module.h>
39 #include <sys/pciio.h>
40
41 #include <dev/ofw/ofw_bus.h>
42 #include <dev/ofw/ofw_pci.h>
43 #include <dev/ofw/openfirm.h>
44
45 #include <machine/bus.h>
46 #include <machine/bus_common.h>
47 #include <machine/cache.h>
48 #include <machine/iommureg.h>
49 #include <machine/resource.h>
50
51 #include <dev/pci/pcireg.h>
52 #include <dev/pci/pcivar.h>
53 #include <dev/pci/pci_private.h>
54
55 #include <sparc64/pci/ofw_pci.h>
56
57 #include "pcib_if.h"
58 #include "pci_if.h"
59
60 /* Helper functions. */
61 static void ofw_pcibus_setup_device(device_t, u_int, u_int, u_int);
62
63 /* Methods. */
64 static device_probe_t ofw_pcibus_probe;
65 static device_attach_t ofw_pcibus_attach;
66 static pci_assign_interrupt_t ofw_pcibus_assign_interrupt;
67 static ofw_bus_get_compat_t ofw_pcibus_get_compat;
68 static ofw_bus_get_model_t ofw_pcibus_get_model;
69 static ofw_bus_get_name_t ofw_pcibus_get_name;
70 static ofw_bus_get_node_t ofw_pcibus_get_node;
71 static ofw_bus_get_type_t ofw_pcibus_get_type;
72
73 static device_method_t ofw_pcibus_methods[] = {
74 /* Device interface */
75 DEVMETHOD(device_probe, ofw_pcibus_probe),
76 DEVMETHOD(device_attach, ofw_pcibus_attach),
77 DEVMETHOD(device_shutdown, bus_generic_shutdown),
78 DEVMETHOD(device_suspend, bus_generic_suspend),
79 DEVMETHOD(device_resume, bus_generic_resume),
80
81 /* Bus interface */
82 DEVMETHOD(bus_print_child, pci_print_child),
83 DEVMETHOD(bus_probe_nomatch, pci_probe_nomatch),
84 DEVMETHOD(bus_read_ivar, pci_read_ivar),
85 DEVMETHOD(bus_write_ivar, pci_write_ivar),
86 DEVMETHOD(bus_driver_added, pci_driver_added),
87 DEVMETHOD(bus_setup_intr, bus_generic_setup_intr),
88 DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr),
89
90 DEVMETHOD(bus_get_resource_list, pci_get_resource_list),
91 DEVMETHOD(bus_set_resource, bus_generic_rl_set_resource),
92 DEVMETHOD(bus_get_resource, bus_generic_rl_get_resource),
93 DEVMETHOD(bus_delete_resource, pci_delete_resource),
94 DEVMETHOD(bus_alloc_resource, pci_alloc_resource),
95 DEVMETHOD(bus_release_resource, bus_generic_rl_release_resource),
96 DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
97 DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
98 DEVMETHOD(bus_child_pnpinfo_str, pci_child_pnpinfo_str_method),
99 DEVMETHOD(bus_child_location_str, pci_child_location_str_method),
100
101 /* PCI interface */
102 DEVMETHOD(pci_read_config, pci_read_config_method),
103 DEVMETHOD(pci_write_config, pci_write_config_method),
104 DEVMETHOD(pci_enable_busmaster, pci_enable_busmaster_method),
105 DEVMETHOD(pci_disable_busmaster, pci_disable_busmaster_method),
106 DEVMETHOD(pci_enable_io, pci_enable_io_method),
107 DEVMETHOD(pci_disable_io, pci_disable_io_method),
108 DEVMETHOD(pci_get_powerstate, pci_get_powerstate_method),
109 DEVMETHOD(pci_set_powerstate, pci_set_powerstate_method),
110 DEVMETHOD(pci_assign_interrupt, ofw_pcibus_assign_interrupt),
111
112 /* ofw_bus interface */
113 DEVMETHOD(ofw_bus_get_compat, ofw_pcibus_get_compat),
114 DEVMETHOD(ofw_bus_get_model, ofw_pcibus_get_model),
115 DEVMETHOD(ofw_bus_get_name, ofw_pcibus_get_name),
116 DEVMETHOD(ofw_bus_get_node, ofw_pcibus_get_node),
117 DEVMETHOD(ofw_bus_get_type, ofw_pcibus_get_type),
118
119 { 0, 0 }
120 };
121
122 struct ofw_pcibus_devinfo {
123 struct pci_devinfo opd_dinfo;
124 char *opd_compat;
125 char *opd_model;
126 char *opd_name;
127 char *opd_type;
128 phandle_t opd_node;
129 };
130
131 struct ofw_pcibus_softc {
132 phandle_t ops_node;
133 };
134
135 static driver_t ofw_pcibus_driver = {
136 "pci",
137 ofw_pcibus_methods,
138 sizeof(struct ofw_pcibus_softc),
139 };
140
141 DRIVER_MODULE(ofw_pcibus, pcib, ofw_pcibus_driver, pci_devclass, 0, 0);
142 MODULE_VERSION(ofw_pcibus, 1);
143 MODULE_DEPEND(ofw_pcibus, pci, 1, 1, 1);
144
145 static int
146 ofw_pcibus_probe(device_t dev)
147 {
148
149 if (ofw_bus_get_node(dev) == 0)
150 return (ENXIO);
151 device_set_desc(dev, "OFW PCI bus");
152
153 return (0);
154 }
155
156 /*
157 * Perform miscellaneous setups the firmware usually does not do for us.
158 */
159 static void
160 ofw_pcibus_setup_device(device_t bridge, u_int busno, u_int slot, u_int func)
161 {
162 u_int lat, clnsz;
163
164 /*
165 * Initialize the latency timer register for busmaster devices to work
166 * properly. This is another task which the firmware does not always
167 * perform. The Min_Gnt register can be used to compute it's recommended
168 * value: it contains the desired latency in units of 1/4 us. To
169 * calculate the correct latency timer value, a bus clock of 33MHz and
170 * no wait states should be assumed.
171 */
172 lat = PCIB_READ_CONFIG(bridge, busno, slot, func, PCIR_MINGNT, 1) *
173 33 / 4;
174 if (lat != 0) {
175 #ifdef OFW_PCI_DEBUG
176 device_printf(bridge, "device %d/%d/%d: latency timer %d -> "
177 "%d\n", busno, slot, func,
178 PCIB_READ_CONFIG(bridge, busno, slot, func,
179 PCIR_LATTIMER, 1), lat);
180 #endif /* OFW_PCI_DEBUG */
181 PCIB_WRITE_CONFIG(bridge, busno, slot, func,
182 PCIR_LATTIMER, min(lat, 255), 1);
183 }
184
185 /*
186 * Compute a value to write into the cache line size register.
187 * The role of the streaming cache is unclear in write invalidate
188 * transfers, so it is made sure that it's line size is always reached.
189 */
190 clnsz = max(cache.ec_linesize, STRBUF_LINESZ);
191 KASSERT((clnsz / STRBUF_LINESZ) * STRBUF_LINESZ == clnsz &&
192 (clnsz / cache.ec_linesize) * cache.ec_linesize == clnsz &&
193 (clnsz / 4) * 4 == clnsz, ("bogus cache line size %d", clnsz));
194 PCIB_WRITE_CONFIG(bridge, busno, slot, func, PCIR_CACHELNSZ,
195 clnsz / 4, 1);
196
197 /*
198 * The preset in the intline register is usually wrong. Reset it to 255,
199 * so that the PCI code will reroute the interrupt if needed.
200 */
201 PCIB_WRITE_CONFIG(bridge, busno, slot, func, PCIR_INTLINE,
202 PCI_INVALID_IRQ, 1);
203 }
204
205 static int
206 ofw_pcibus_attach(device_t dev)
207 {
208 device_t pcib = device_get_parent(dev);
209 struct ofw_pci_register pcir;
210 struct ofw_pcibus_devinfo *dinfo;
211 phandle_t node, child;
212 char *cname;
213 u_int slot, busno, func;
214
215 /*
216 * Ask the bridge for the bus number - in some cases, we need to
217 * renumber buses, so the firmware information cannot be trusted.
218 */
219 busno = pcib_get_bus(dev);
220 if (bootverbose)
221 device_printf(dev, "physical bus=%d\n", busno);
222
223 node = ofw_bus_get_node(dev);
224 for (child = OF_child(node); child != 0; child = OF_peer(child)) {
225 if ((OF_getprop_alloc(child, "name", 1, (void **)&cname)) == -1)
226 continue;
227
228 if (OF_getprop(child, "reg", &pcir, sizeof(pcir)) == -1) {
229 device_printf(dev, "<%s>: incomplete\n", cname);
230 free(cname, M_OFWPROP);
231 continue;
232 }
233 slot = OFW_PCI_PHYS_HI_DEVICE(pcir.phys_hi);
234 func = OFW_PCI_PHYS_HI_FUNCTION(pcir.phys_hi);
235 ofw_pcibus_setup_device(pcib, busno, slot, func);
236 dinfo = (struct ofw_pcibus_devinfo *)pci_read_device(pcib,
237 busno, slot, func, sizeof(*dinfo));
238 if (dinfo != NULL) {
239 dinfo->opd_name = cname;
240 dinfo->opd_node = child;
241 OF_getprop_alloc(child, "compatible", 1,
242 (void **)&dinfo->opd_compat);
243 OF_getprop_alloc(child, "device_type", 1,
244 (void **)&dinfo->opd_type);
245 OF_getprop_alloc(child, "model", 1,
246 (void **)&dinfo->opd_model);
247 pci_add_child(dev, (struct pci_devinfo *)dinfo);
248 } else
249 free(cname, M_OFWPROP);
250 }
251
252 return (bus_generic_attach(dev));
253 }
254
255 static int
256 ofw_pcibus_assign_interrupt(device_t dev, device_t child)
257 {
258 struct ofw_pcibus_devinfo *dinfo = device_get_ivars(child);
259 pcicfgregs *cfg = &dinfo->opd_dinfo.cfg;
260 ofw_pci_intr_t intr;
261 int isz;
262
263 isz = OF_getprop(dinfo->opd_node, "interrupts", &intr, sizeof(intr));
264 if (isz != sizeof(intr)) {
265 /* No property; our best guess is the intpin. */
266 intr = cfg->intpin;
267 } else if (intr >= 255) {
268 /*
269 * A fully specified interrupt (including IGN), as present on
270 * SPARCengine Ultra AX and e450. Extract the INO and return it.
271 */
272 return (INTINO(intr));
273 }
274 /*
275 * If we got intr from a property, it may or may not be an intpin.
276 * For on-board devices, it frequently is not, and is completely out
277 * of the valid intpin range. For PCI slots, it hopefully is, otherwise
278 * we will have trouble interfacing with non-OFW buses such as cardbus.
279 * Since we cannot tell which it is without violating layering, we
280 * will always use the route_interrupt method, and treat exceptions on
281 * the level they become apparent.
282 */
283 return (PCIB_ROUTE_INTERRUPT(device_get_parent(dev), child, intr));
284 }
285
286 static const char *
287 ofw_pcibus_get_compat(device_t bus, device_t dev)
288 {
289 struct ofw_pcibus_devinfo *dinfo;
290
291 dinfo = device_get_ivars(dev);
292 return (dinfo->opd_compat);
293 }
294
295 static const char *
296 ofw_pcibus_get_model(device_t bus, device_t dev)
297 {
298 struct ofw_pcibus_devinfo *dinfo;
299
300 dinfo = device_get_ivars(dev);
301 return (dinfo->opd_model);
302 }
303
304 static const char *
305 ofw_pcibus_get_name(device_t bus, device_t dev)
306 {
307 struct ofw_pcibus_devinfo *dinfo;
308
309 dinfo = device_get_ivars(dev);
310 return (dinfo->opd_name);
311 }
312
313 static phandle_t
314 ofw_pcibus_get_node(device_t bus, device_t dev)
315 {
316 struct ofw_pcibus_devinfo *dinfo;
317
318 dinfo = device_get_ivars(dev);
319 return (dinfo->opd_node);
320 }
321
322 static const char *
323 ofw_pcibus_get_type(device_t bus, device_t dev)
324 {
325 struct ofw_pcibus_devinfo *dinfo;
326
327 dinfo = device_get_ivars(dev);
328 return (dinfo->opd_type);
329 }
Cache object: fa9696c4964d4ebce03abf76551b1b74
|