xref: /freebsd/sys/dev/pci/pci_dw.c (revision 26abae3f17644c606271c829b0b3e9332422bd22)
1*26abae3fSMichal Meloun /*-
2*26abae3fSMichal Meloun  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3*26abae3fSMichal Meloun  *
4*26abae3fSMichal Meloun  * Copyright (c) 2019 Michal Meloun <mmel@FreeBSD.org>
5*26abae3fSMichal Meloun  *
6*26abae3fSMichal Meloun  * Redistribution and use in source and binary forms, with or without
7*26abae3fSMichal Meloun  * modification, are permitted provided that the following conditions
8*26abae3fSMichal Meloun  * are met:
9*26abae3fSMichal Meloun  * 1. Redistributions of source code must retain the above copyright
10*26abae3fSMichal Meloun  *    notice, this list of conditions and the following disclaimer.
11*26abae3fSMichal Meloun  * 2. Redistributions in binary form must reproduce the above copyright
12*26abae3fSMichal Meloun  *    notice, this list of conditions and the following disclaimer in the
13*26abae3fSMichal Meloun  *    documentation and/or other materials provided with the distribution.
14*26abae3fSMichal Meloun  *
15*26abae3fSMichal Meloun  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16*26abae3fSMichal Meloun  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17*26abae3fSMichal Meloun  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18*26abae3fSMichal Meloun  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19*26abae3fSMichal Meloun  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20*26abae3fSMichal Meloun  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21*26abae3fSMichal Meloun  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22*26abae3fSMichal Meloun  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23*26abae3fSMichal Meloun  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24*26abae3fSMichal Meloun  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25*26abae3fSMichal Meloun  * SUCH DAMAGE.
26*26abae3fSMichal Meloun  *
27*26abae3fSMichal Meloun  */
28*26abae3fSMichal Meloun 
29*26abae3fSMichal Meloun /* Base class for all Synopsys DesignWare PCI/PCIe drivers */
30*26abae3fSMichal Meloun 
31*26abae3fSMichal Meloun #include <sys/cdefs.h>
32*26abae3fSMichal Meloun __FBSDID("$FreeBSD$");
33*26abae3fSMichal Meloun 
34*26abae3fSMichal Meloun 
35*26abae3fSMichal Meloun #include <sys/param.h>
36*26abae3fSMichal Meloun #include <sys/systm.h>
37*26abae3fSMichal Meloun #include <sys/bus.h>
38*26abae3fSMichal Meloun #include <sys/devmap.h>
39*26abae3fSMichal Meloun #include <sys/proc.h>
40*26abae3fSMichal Meloun #include <sys/kernel.h>
41*26abae3fSMichal Meloun #include <sys/lock.h>
42*26abae3fSMichal Meloun #include <sys/malloc.h>
43*26abae3fSMichal Meloun #include <sys/module.h>
44*26abae3fSMichal Meloun #include <sys/mutex.h>
45*26abae3fSMichal Meloun #include <sys/rman.h>
46*26abae3fSMichal Meloun 
47*26abae3fSMichal Meloun #include <machine/bus.h>
48*26abae3fSMichal Meloun #include <machine/intr.h>
49*26abae3fSMichal Meloun #include <machine/resource.h>
50*26abae3fSMichal Meloun 
51*26abae3fSMichal Meloun #include <dev/ofw/ofw_bus.h>
52*26abae3fSMichal Meloun #include <dev/ofw/ofw_bus_subr.h>
53*26abae3fSMichal Meloun #include <dev/ofw/ofw_pci.h>
54*26abae3fSMichal Meloun #include <dev/ofw/ofwpci.h>
55*26abae3fSMichal Meloun #include <dev/pci/pcivar.h>
56*26abae3fSMichal Meloun #include <dev/pci/pcireg.h>
57*26abae3fSMichal Meloun #include <dev/pci/pcib_private.h>
58*26abae3fSMichal Meloun #include <dev/pci/pci_dw.h>
59*26abae3fSMichal Meloun 
60*26abae3fSMichal Meloun #include "pcib_if.h"
61*26abae3fSMichal Meloun #include "pci_dw_if.h"
62*26abae3fSMichal Meloun 
63*26abae3fSMichal Meloun #define	DEBUG
64*26abae3fSMichal Meloun #ifdef DEBUG
65*26abae3fSMichal Meloun #define	debugf(fmt, args...) do { printf(fmt,##args); } while (0)
66*26abae3fSMichal Meloun #else
67*26abae3fSMichal Meloun #define	debugf(fmt, args...)
68*26abae3fSMichal Meloun #endif
69*26abae3fSMichal Meloun 
70*26abae3fSMichal Meloun #define	DBI_WR1(sc, reg, val)	pci_dw_dbi_wr1((sc)->dev, reg, val)
71*26abae3fSMichal Meloun #define	DBI_WR2(sc, reg, val)	pci_dw_dbi_wr2((sc)->dev, reg, val)
72*26abae3fSMichal Meloun #define	DBI_WR4(sc, reg, val)	pci_dw_dbi_wr4((sc)->dev, reg, val)
73*26abae3fSMichal Meloun #define	DBI_RD1(sc, reg)	pci_dw_dbi_rd1((sc)->dev, reg)
74*26abae3fSMichal Meloun #define	DBI_RD2(sc, reg)	pci_dw_dbi_rd2((sc)->dev, reg)
75*26abae3fSMichal Meloun #define	DBI_RD4(sc, reg)	pci_dw_dbi_rd4((sc)->dev, reg)
76*26abae3fSMichal Meloun 
77*26abae3fSMichal Meloun #define	PCI_BUS_SHIFT		20
78*26abae3fSMichal Meloun #define	PCI_SLOT_SHIFT		15
79*26abae3fSMichal Meloun #define	PCI_FUNC_SHIFT		12
80*26abae3fSMichal Meloun #define	PCI_BUS_MASK		0xFF
81*26abae3fSMichal Meloun #define	PCI_SLOT_MASK		0x1F
82*26abae3fSMichal Meloun #define	PCI_FUNC_MASK		0x07
83*26abae3fSMichal Meloun #define	PCI_REG_MASK		0xFFF
84*26abae3fSMichal Meloun 
85*26abae3fSMichal Meloun 
86*26abae3fSMichal Meloun #define	IATU_CFG_BUS(bus)	((uint64_t)((bus)  & 0xff) << 24)
87*26abae3fSMichal Meloun #define	IATU_CFG_SLOT(slot)	((uint64_t)((slot) & 0x1f) << 19)
88*26abae3fSMichal Meloun #define	IATU_CFG_FUNC(func)	((uint64_t)((func) & 0x07) << 16)
89*26abae3fSMichal Meloun 
90*26abae3fSMichal Meloun 
91*26abae3fSMichal Meloun 
92*26abae3fSMichal Meloun static uint32_t
93*26abae3fSMichal Meloun pci_dw_dbi_read(device_t dev, u_int reg, int width)
94*26abae3fSMichal Meloun {
95*26abae3fSMichal Meloun 	struct pci_dw_softc *sc;
96*26abae3fSMichal Meloun 
97*26abae3fSMichal Meloun 	sc = device_get_softc(dev);
98*26abae3fSMichal Meloun 	MPASS(sc->dbi_res != NULL);
99*26abae3fSMichal Meloun 
100*26abae3fSMichal Meloun 	switch (width) {
101*26abae3fSMichal Meloun 	case 4:
102*26abae3fSMichal Meloun 		return (bus_read_4(sc->dbi_res, reg));
103*26abae3fSMichal Meloun 	case 2:
104*26abae3fSMichal Meloun 		return (bus_read_2(sc->dbi_res, reg));
105*26abae3fSMichal Meloun 	case 1:
106*26abae3fSMichal Meloun 		return (bus_read_1(sc->dbi_res, reg));
107*26abae3fSMichal Meloun 	default:
108*26abae3fSMichal Meloun 		device_printf(sc->dev, "Unsupported width: %d\n", width);
109*26abae3fSMichal Meloun 		return (0xFFFFFFFF);
110*26abae3fSMichal Meloun 	}
111*26abae3fSMichal Meloun }
112*26abae3fSMichal Meloun 
113*26abae3fSMichal Meloun static void
114*26abae3fSMichal Meloun pci_dw_dbi_write(device_t dev, u_int reg, uint32_t val, int width)
115*26abae3fSMichal Meloun {
116*26abae3fSMichal Meloun 	struct pci_dw_softc *sc;
117*26abae3fSMichal Meloun 
118*26abae3fSMichal Meloun 	sc = device_get_softc(dev);
119*26abae3fSMichal Meloun 	MPASS(sc->dbi_res != NULL);
120*26abae3fSMichal Meloun 
121*26abae3fSMichal Meloun 	switch (width) {
122*26abae3fSMichal Meloun 	case 4:
123*26abae3fSMichal Meloun 		bus_write_4(sc->dbi_res, reg, val);
124*26abae3fSMichal Meloun 		break;
125*26abae3fSMichal Meloun 	case 2:
126*26abae3fSMichal Meloun 		bus_write_2(sc->dbi_res, reg, val);
127*26abae3fSMichal Meloun 		break;
128*26abae3fSMichal Meloun 	case 1:
129*26abae3fSMichal Meloun 		bus_write_1(sc->dbi_res, reg, val);
130*26abae3fSMichal Meloun 		break;
131*26abae3fSMichal Meloun 	default:
132*26abae3fSMichal Meloun 		device_printf(sc->dev, "Unsupported width: %d\n", width);
133*26abae3fSMichal Meloun 		break;
134*26abae3fSMichal Meloun 	}
135*26abae3fSMichal Meloun }
136*26abae3fSMichal Meloun 
137*26abae3fSMichal Meloun 
138*26abae3fSMichal Meloun static void
139*26abae3fSMichal Meloun pci_dw_dbi_protect(struct pci_dw_softc *sc, bool protect)
140*26abae3fSMichal Meloun {
141*26abae3fSMichal Meloun 	uint32_t reg;
142*26abae3fSMichal Meloun 
143*26abae3fSMichal Meloun 	reg = DBI_RD4(sc, DW_MISC_CONTROL_1);
144*26abae3fSMichal Meloun 	if (protect)
145*26abae3fSMichal Meloun 		reg &= ~DBI_RO_WR_EN;
146*26abae3fSMichal Meloun 	else
147*26abae3fSMichal Meloun 		reg |= DBI_RO_WR_EN;
148*26abae3fSMichal Meloun 	DBI_WR4(sc, DW_MISC_CONTROL_1, reg);
149*26abae3fSMichal Meloun }
150*26abae3fSMichal Meloun 
151*26abae3fSMichal Meloun static bool
152*26abae3fSMichal Meloun pci_dw_check_dev(struct pci_dw_softc *sc, u_int bus, u_int slot, u_int func,
153*26abae3fSMichal Meloun     u_int reg)
154*26abae3fSMichal Meloun {
155*26abae3fSMichal Meloun 	bool status;
156*26abae3fSMichal Meloun 	int rv;
157*26abae3fSMichal Meloun 
158*26abae3fSMichal Meloun 	if (bus < sc->bus_start || bus > sc->bus_end || slot > PCI_SLOTMAX ||
159*26abae3fSMichal Meloun 	    func > PCI_FUNCMAX || reg > PCI_REGMAX)
160*26abae3fSMichal Meloun 		return (false);
161*26abae3fSMichal Meloun 
162*26abae3fSMichal Meloun 	/* link is needed for access to all non-root busses */
163*26abae3fSMichal Meloun 	if (bus != sc->root_bus) {
164*26abae3fSMichal Meloun 		rv = PCI_DW_GET_LINK(sc->dev, &status);
165*26abae3fSMichal Meloun 		if (rv != 0 || !status)
166*26abae3fSMichal Meloun 			return (false);
167*26abae3fSMichal Meloun 		return (true);
168*26abae3fSMichal Meloun 	}
169*26abae3fSMichal Meloun 
170*26abae3fSMichal Meloun 	/* we have only 1 device with 1 function root port */
171*26abae3fSMichal Meloun 	if (slot > 0 || func > 0)
172*26abae3fSMichal Meloun 		return (false);
173*26abae3fSMichal Meloun 	return (true);
174*26abae3fSMichal Meloun }
175*26abae3fSMichal Meloun 
176*26abae3fSMichal Meloun /* Map one uoutbound ATU region */
177*26abae3fSMichal Meloun static int
178*26abae3fSMichal Meloun pci_dw_map_out_atu(struct pci_dw_softc *sc, int idx, int type,
179*26abae3fSMichal Meloun     uint64_t pa, uint64_t pci_addr, uint32_t size)
180*26abae3fSMichal Meloun {
181*26abae3fSMichal Meloun 	uint32_t reg;
182*26abae3fSMichal Meloun 	int i;
183*26abae3fSMichal Meloun 
184*26abae3fSMichal Meloun 	if (size == 0)
185*26abae3fSMichal Meloun 		return (0);
186*26abae3fSMichal Meloun 
187*26abae3fSMichal Meloun 	DBI_WR4(sc, DW_IATU_VIEWPORT, IATU_REGION_INDEX(idx));
188*26abae3fSMichal Meloun 	DBI_WR4(sc, DW_IATU_LWR_BASE_ADDR, pa & 0xFFFFFFFF);
189*26abae3fSMichal Meloun 	DBI_WR4(sc, DW_IATU_UPPER_BASE_ADDR, (pa >> 32) & 0xFFFFFFFF);
190*26abae3fSMichal Meloun 	DBI_WR4(sc, DW_IATU_LIMIT_ADDR, (pa + size - 1) & 0xFFFFFFFF);
191*26abae3fSMichal Meloun 	DBI_WR4(sc, DW_IATU_LWR_TARGET_ADDR, pci_addr & 0xFFFFFFFF);
192*26abae3fSMichal Meloun 	DBI_WR4(sc, DW_IATU_UPPER_TARGET_ADDR, (pci_addr  >> 32) & 0xFFFFFFFF);
193*26abae3fSMichal Meloun 	DBI_WR4(sc, DW_IATU_CTRL1, IATU_CTRL1_TYPE(type));
194*26abae3fSMichal Meloun 	DBI_WR4(sc, DW_IATU_CTRL2, IATU_CTRL2_REGION_EN);
195*26abae3fSMichal Meloun 
196*26abae3fSMichal Meloun 	/* Wait until setup becomes valid */
197*26abae3fSMichal Meloun 	for (i = 10; i > 0; i--) {
198*26abae3fSMichal Meloun 		reg = DBI_RD4(sc, DW_IATU_CTRL2);
199*26abae3fSMichal Meloun 		if (reg & IATU_CTRL2_REGION_EN)
200*26abae3fSMichal Meloun 			return (0);
201*26abae3fSMichal Meloun 		DELAY(5);
202*26abae3fSMichal Meloun 	}
203*26abae3fSMichal Meloun 	device_printf(sc->dev,
204*26abae3fSMichal Meloun 	    "Cannot map outbound region(%d) in iATU\n", idx);
205*26abae3fSMichal Meloun 	return (ETIMEDOUT);
206*26abae3fSMichal Meloun }
207*26abae3fSMichal Meloun 
208*26abae3fSMichal Meloun static int
209*26abae3fSMichal Meloun pci_dw_setup_hw(struct pci_dw_softc *sc)
210*26abae3fSMichal Meloun {
211*26abae3fSMichal Meloun 	uint32_t reg;
212*26abae3fSMichal Meloun 	int rv;
213*26abae3fSMichal Meloun 
214*26abae3fSMichal Meloun 	pci_dw_dbi_protect(sc, false);
215*26abae3fSMichal Meloun 
216*26abae3fSMichal Meloun 	/* Setup config registers */
217*26abae3fSMichal Meloun 	DBI_WR1(sc, PCIR_CLASS, PCIC_BRIDGE);
218*26abae3fSMichal Meloun 	DBI_WR1(sc, PCIR_SUBCLASS, PCIS_BRIDGE_PCI);
219*26abae3fSMichal Meloun 	DBI_WR4(sc, PCIR_BAR(0), 4);
220*26abae3fSMichal Meloun 	DBI_WR4(sc, PCIR_BAR(1), 0);
221*26abae3fSMichal Meloun 	DBI_WR1(sc, PCIR_INTPIN, 1);
222*26abae3fSMichal Meloun 	DBI_WR1(sc, PCIR_PRIBUS_1, sc->root_bus);
223*26abae3fSMichal Meloun 	DBI_WR1(sc, PCIR_SECBUS_1, sc->sub_bus);
224*26abae3fSMichal Meloun 	DBI_WR1(sc, PCIR_SUBBUS_1, sc->bus_end);
225*26abae3fSMichal Meloun 	DBI_WR2(sc, PCIR_COMMAND,
226*26abae3fSMichal Meloun 	   PCIM_CMD_PORTEN | PCIM_CMD_MEMEN |
227*26abae3fSMichal Meloun 	   PCIM_CMD_BUSMASTEREN | PCIM_CMD_SERRESPEN);
228*26abae3fSMichal Meloun 	pci_dw_dbi_protect(sc, true);
229*26abae3fSMichal Meloun 
230*26abae3fSMichal Meloun 	/* Setup outbound memory window */
231*26abae3fSMichal Meloun 	rv = pci_dw_map_out_atu(sc, 0, IATU_CTRL1_TYPE_MEM,
232*26abae3fSMichal Meloun 	    sc->mem_range.host, sc->mem_range.pci, sc->mem_range.size);
233*26abae3fSMichal Meloun 	if (rv != 0)
234*26abae3fSMichal Meloun 		return (rv);
235*26abae3fSMichal Meloun 
236*26abae3fSMichal Meloun 	/* If we have enouht viewports ..*/
237*26abae3fSMichal Meloun 	if (sc->num_viewport >= 3) {
238*26abae3fSMichal Meloun 		/* Setup outbound I/O window */
239*26abae3fSMichal Meloun 		rv = pci_dw_map_out_atu(sc, 0, IATU_CTRL1_TYPE_MEM,
240*26abae3fSMichal Meloun 		    sc->io_range.host, sc->io_range.pci, sc->io_range.size);
241*26abae3fSMichal Meloun 		if (rv != 0)
242*26abae3fSMichal Meloun 			return (rv);
243*26abae3fSMichal Meloun 	}
244*26abae3fSMichal Meloun 	/* XXX Should we handle also prefetch memory? */
245*26abae3fSMichal Meloun 
246*26abae3fSMichal Meloun 
247*26abae3fSMichal Meloun 	/* Adjust number of lanes */
248*26abae3fSMichal Meloun 	reg = DBI_RD4(sc, DW_PORT_LINK_CTRL);
249*26abae3fSMichal Meloun 	reg &= ~PORT_LINK_CAPABLE(~0);
250*26abae3fSMichal Meloun 	switch (sc->num_lanes) {
251*26abae3fSMichal Meloun 	case 1:
252*26abae3fSMichal Meloun 		reg |= PORT_LINK_CAPABLE(PORT_LINK_CAPABLE_1);
253*26abae3fSMichal Meloun 		break;
254*26abae3fSMichal Meloun 	case 2:
255*26abae3fSMichal Meloun 		reg |= PORT_LINK_CAPABLE(PORT_LINK_CAPABLE_2);
256*26abae3fSMichal Meloun 		break;
257*26abae3fSMichal Meloun 	case 4:
258*26abae3fSMichal Meloun 		reg |= PORT_LINK_CAPABLE(PORT_LINK_CAPABLE_4);
259*26abae3fSMichal Meloun 		break;
260*26abae3fSMichal Meloun 	case 8:
261*26abae3fSMichal Meloun 		reg |= PORT_LINK_CAPABLE(PORT_LINK_CAPABLE_8);
262*26abae3fSMichal Meloun 		break;
263*26abae3fSMichal Meloun 	case 16:
264*26abae3fSMichal Meloun 		reg |= PORT_LINK_CAPABLE(PORT_LINK_CAPABLE_16);
265*26abae3fSMichal Meloun 		break;
266*26abae3fSMichal Meloun 	case 32:
267*26abae3fSMichal Meloun 		reg |= PORT_LINK_CAPABLE(PORT_LINK_CAPABLE_32);
268*26abae3fSMichal Meloun 		break;
269*26abae3fSMichal Meloun 	default:
270*26abae3fSMichal Meloun 		device_printf(sc->dev,
271*26abae3fSMichal Meloun 		    "'num-lanes' property have invalid value: %d\n",
272*26abae3fSMichal Meloun 		    sc->num_lanes);
273*26abae3fSMichal Meloun 		return (EINVAL);
274*26abae3fSMichal Meloun 	}
275*26abae3fSMichal Meloun 	DBI_WR4(sc, DW_PORT_LINK_CTRL, reg);
276*26abae3fSMichal Meloun 
277*26abae3fSMichal Meloun 
278*26abae3fSMichal Meloun 	/* And link width */
279*26abae3fSMichal Meloun 	reg = DBI_RD4(sc, DW_GEN2_CTRL);
280*26abae3fSMichal Meloun 	reg &= ~GEN2_CTRL_NUM_OF_LANES(~0);
281*26abae3fSMichal Meloun 	switch (sc->num_lanes) {
282*26abae3fSMichal Meloun 	case 1:
283*26abae3fSMichal Meloun 		reg |= GEN2_CTRL_NUM_OF_LANES(GEN2_CTRL_NUM_OF_LANES_1);
284*26abae3fSMichal Meloun 		break;
285*26abae3fSMichal Meloun 	case 2:
286*26abae3fSMichal Meloun 		reg |= GEN2_CTRL_NUM_OF_LANES(GEN2_CTRL_NUM_OF_LANES_2);
287*26abae3fSMichal Meloun 		break;
288*26abae3fSMichal Meloun 	case 4:
289*26abae3fSMichal Meloun 		reg |= GEN2_CTRL_NUM_OF_LANES(GEN2_CTRL_NUM_OF_LANES_4);
290*26abae3fSMichal Meloun 		break;
291*26abae3fSMichal Meloun 	case 8:
292*26abae3fSMichal Meloun 		reg |= GEN2_CTRL_NUM_OF_LANES(GEN2_CTRL_NUM_OF_LANES_8);
293*26abae3fSMichal Meloun 		break;
294*26abae3fSMichal Meloun 	case 16:
295*26abae3fSMichal Meloun 		reg |= GEN2_CTRL_NUM_OF_LANES(GEN2_CTRL_NUM_OF_LANES_16);
296*26abae3fSMichal Meloun 		break;
297*26abae3fSMichal Meloun 	case 32:
298*26abae3fSMichal Meloun 		reg |= GEN2_CTRL_NUM_OF_LANES(GEN2_CTRL_NUM_OF_LANES_32);
299*26abae3fSMichal Meloun 		break;
300*26abae3fSMichal Meloun 	}
301*26abae3fSMichal Meloun 	DBI_WR4(sc, DW_GEN2_CTRL, reg);
302*26abae3fSMichal Meloun 
303*26abae3fSMichal Meloun 	reg = DBI_RD4(sc, DW_GEN2_CTRL);
304*26abae3fSMichal Meloun 	reg |= DIRECT_SPEED_CHANGE;
305*26abae3fSMichal Meloun 	DBI_WR4(sc, DW_GEN2_CTRL, reg);
306*26abae3fSMichal Meloun 
307*26abae3fSMichal Meloun 
308*26abae3fSMichal Meloun 	return (0);
309*26abae3fSMichal Meloun }
310*26abae3fSMichal Meloun 
311*26abae3fSMichal Meloun static int
312*26abae3fSMichal Meloun pci_dw_decode_ranges(struct pci_dw_softc *sc, struct ofw_pci_range *ranges,
313*26abae3fSMichal Meloun      int nranges)
314*26abae3fSMichal Meloun {
315*26abae3fSMichal Meloun 	int i;
316*26abae3fSMichal Meloun 
317*26abae3fSMichal Meloun 	for (i = 0; i < nranges; i++) {
318*26abae3fSMichal Meloun 		if ((ranges[i].pci_hi & OFW_PCI_PHYS_HI_SPACEMASK)  ==
319*26abae3fSMichal Meloun 		    OFW_PCI_PHYS_HI_SPACE_IO) {
320*26abae3fSMichal Meloun 			if (sc->io_range.size != 0) {
321*26abae3fSMichal Meloun 				device_printf(sc->dev,
322*26abae3fSMichal Meloun 				    "Duplicated IO range found in DT\n");
323*26abae3fSMichal Meloun 				return (ENXIO);
324*26abae3fSMichal Meloun 			}
325*26abae3fSMichal Meloun 			sc->io_range = ranges[i];
326*26abae3fSMichal Meloun 		}
327*26abae3fSMichal Meloun 		if (((ranges[i].pci_hi & OFW_PCI_PHYS_HI_SPACEMASK) ==
328*26abae3fSMichal Meloun 		    OFW_PCI_PHYS_HI_SPACE_MEM32))  {
329*26abae3fSMichal Meloun 			if (ranges[i].pci_hi & OFW_PCI_PHYS_HI_PREFETCHABLE) {
330*26abae3fSMichal Meloun 				if (sc->pref_mem_range.size != 0) {
331*26abae3fSMichal Meloun 					device_printf(sc->dev,
332*26abae3fSMichal Meloun 					    "Duplicated memory range found "
333*26abae3fSMichal Meloun 					    "in DT\n");
334*26abae3fSMichal Meloun 					return (ENXIO);
335*26abae3fSMichal Meloun 				}
336*26abae3fSMichal Meloun 				sc->pref_mem_range = ranges[i];
337*26abae3fSMichal Meloun 			} else {
338*26abae3fSMichal Meloun 				if (sc->mem_range.size != 0) {
339*26abae3fSMichal Meloun 					device_printf(sc->dev,
340*26abae3fSMichal Meloun 					    "Duplicated memory range found "
341*26abae3fSMichal Meloun 					    "in DT\n");
342*26abae3fSMichal Meloun 					return (ENXIO);
343*26abae3fSMichal Meloun 				}
344*26abae3fSMichal Meloun 				sc->mem_range = ranges[i];
345*26abae3fSMichal Meloun 			}
346*26abae3fSMichal Meloun 		}
347*26abae3fSMichal Meloun 	}
348*26abae3fSMichal Meloun 	if ((sc->io_range.size == 0) || (sc->mem_range.size == 0)) {
349*26abae3fSMichal Meloun 		device_printf(sc->dev,
350*26abae3fSMichal Meloun 		    " Not all required ranges are found in DT\n");
351*26abae3fSMichal Meloun 		return (ENXIO);
352*26abae3fSMichal Meloun 	}
353*26abae3fSMichal Meloun 	return (0);
354*26abae3fSMichal Meloun }
355*26abae3fSMichal Meloun 
356*26abae3fSMichal Meloun 
357*26abae3fSMichal Meloun 
358*26abae3fSMichal Meloun /*-----------------------------------------------------------------------------
359*26abae3fSMichal Meloun  *
360*26abae3fSMichal Meloun  *  P C I B   I N T E R F A C E
361*26abae3fSMichal Meloun  */
362*26abae3fSMichal Meloun 
363*26abae3fSMichal Meloun static uint32_t
364*26abae3fSMichal Meloun pci_dw_read_config(device_t dev, u_int bus, u_int slot,
365*26abae3fSMichal Meloun     u_int func, u_int reg, int bytes)
366*26abae3fSMichal Meloun {
367*26abae3fSMichal Meloun 	struct pci_dw_softc *sc;
368*26abae3fSMichal Meloun 	struct resource	*res;
369*26abae3fSMichal Meloun 	uint32_t data;
370*26abae3fSMichal Meloun 	uint64_t addr;
371*26abae3fSMichal Meloun 	int type, rv;
372*26abae3fSMichal Meloun 
373*26abae3fSMichal Meloun 	sc = device_get_softc(dev);
374*26abae3fSMichal Meloun 
375*26abae3fSMichal Meloun 	if (!pci_dw_check_dev(sc, bus, slot, func, reg))
376*26abae3fSMichal Meloun 		return (0xFFFFFFFFU);
377*26abae3fSMichal Meloun 
378*26abae3fSMichal Meloun 	if ((slot > PCI_SLOTMAX) || (func > PCI_FUNCMAX) ||
379*26abae3fSMichal Meloun 	    (reg > PCI_REGMAX))
380*26abae3fSMichal Meloun 		return (0xFFFFFFFFU);
381*26abae3fSMichal Meloun 
382*26abae3fSMichal Meloun 	if (bus == sc->root_bus) {
383*26abae3fSMichal Meloun 		res = (sc->dbi_res);
384*26abae3fSMichal Meloun 	} else {
385*26abae3fSMichal Meloun 		addr = IATU_CFG_BUS(bus) | IATU_CFG_SLOT(slot) |
386*26abae3fSMichal Meloun 		    IATU_CFG_FUNC(func);
387*26abae3fSMichal Meloun 		if (bus == sc->sub_bus)
388*26abae3fSMichal Meloun 			type = IATU_CTRL1_TYPE_CFG0;
389*26abae3fSMichal Meloun 		else
390*26abae3fSMichal Meloun 			type = IATU_CTRL1_TYPE_CFG1;
391*26abae3fSMichal Meloun 		rv = pci_dw_map_out_atu(sc, 1, type,
392*26abae3fSMichal Meloun 		    sc->cfg_pa, addr, sc->cfg_size);
393*26abae3fSMichal Meloun 		if (rv != 0)
394*26abae3fSMichal Meloun 			return (0xFFFFFFFFU);
395*26abae3fSMichal Meloun 		res = sc->cfg_res;
396*26abae3fSMichal Meloun 	}
397*26abae3fSMichal Meloun 
398*26abae3fSMichal Meloun 	switch (bytes) {
399*26abae3fSMichal Meloun 	case 1:
400*26abae3fSMichal Meloun 		data = bus_read_1(res, reg);
401*26abae3fSMichal Meloun 		break;
402*26abae3fSMichal Meloun 	case 2:
403*26abae3fSMichal Meloun 		data = bus_read_2(res, reg);
404*26abae3fSMichal Meloun 		break;
405*26abae3fSMichal Meloun 	case 4:
406*26abae3fSMichal Meloun 		data = bus_read_4(res, reg);
407*26abae3fSMichal Meloun 		break;
408*26abae3fSMichal Meloun 	default:
409*26abae3fSMichal Meloun 		data =  0xFFFFFFFFU;
410*26abae3fSMichal Meloun 	}
411*26abae3fSMichal Meloun 
412*26abae3fSMichal Meloun 	return (data);
413*26abae3fSMichal Meloun 
414*26abae3fSMichal Meloun }
415*26abae3fSMichal Meloun 
416*26abae3fSMichal Meloun static void
417*26abae3fSMichal Meloun pci_dw_write_config(device_t dev, u_int bus, u_int slot,
418*26abae3fSMichal Meloun     u_int func, u_int reg, uint32_t val, int bytes)
419*26abae3fSMichal Meloun {
420*26abae3fSMichal Meloun 	struct pci_dw_softc *sc;
421*26abae3fSMichal Meloun 	struct resource	*res;
422*26abae3fSMichal Meloun 	uint64_t addr;
423*26abae3fSMichal Meloun 	int type, rv;
424*26abae3fSMichal Meloun 
425*26abae3fSMichal Meloun 	sc = device_get_softc(dev);
426*26abae3fSMichal Meloun 	if (!pci_dw_check_dev(sc, bus, slot, func, reg))
427*26abae3fSMichal Meloun 		return;
428*26abae3fSMichal Meloun 
429*26abae3fSMichal Meloun 	if ((slot > PCI_SLOTMAX) || (func > PCI_FUNCMAX) ||
430*26abae3fSMichal Meloun 	    (reg > PCI_REGMAX))
431*26abae3fSMichal Meloun 		return;
432*26abae3fSMichal Meloun 
433*26abae3fSMichal Meloun 	if (bus == sc->root_bus) {
434*26abae3fSMichal Meloun 		res = (sc->dbi_res);
435*26abae3fSMichal Meloun 	} else {
436*26abae3fSMichal Meloun 		addr = IATU_CFG_BUS(bus) | IATU_CFG_SLOT(slot) |
437*26abae3fSMichal Meloun 		    IATU_CFG_FUNC(func);
438*26abae3fSMichal Meloun 		if (bus == sc->sub_bus)
439*26abae3fSMichal Meloun 			type = IATU_CTRL1_TYPE_CFG0;
440*26abae3fSMichal Meloun 		else
441*26abae3fSMichal Meloun 			type = IATU_CTRL1_TYPE_CFG1;
442*26abae3fSMichal Meloun 		rv = pci_dw_map_out_atu(sc, 1, type,
443*26abae3fSMichal Meloun 		    sc->cfg_pa, addr, sc->cfg_size);
444*26abae3fSMichal Meloun 		if (rv != 0)
445*26abae3fSMichal Meloun 			return ;
446*26abae3fSMichal Meloun 		res = sc->cfg_res;
447*26abae3fSMichal Meloun 	}
448*26abae3fSMichal Meloun 
449*26abae3fSMichal Meloun 
450*26abae3fSMichal Meloun 	switch (bytes) {
451*26abae3fSMichal Meloun 	case 1:
452*26abae3fSMichal Meloun 		bus_write_1(res, reg, val);
453*26abae3fSMichal Meloun 		break;
454*26abae3fSMichal Meloun 	case 2:
455*26abae3fSMichal Meloun 		bus_write_2(res, reg, val);
456*26abae3fSMichal Meloun 		break;
457*26abae3fSMichal Meloun 	case 4:
458*26abae3fSMichal Meloun 		bus_write_4(res, reg, val);
459*26abae3fSMichal Meloun 		break;
460*26abae3fSMichal Meloun 	default:
461*26abae3fSMichal Meloun 		break;
462*26abae3fSMichal Meloun 	}
463*26abae3fSMichal Meloun }
464*26abae3fSMichal Meloun 
465*26abae3fSMichal Meloun static int
466*26abae3fSMichal Meloun pci_dw_alloc_msi(device_t pci, device_t child, int count,
467*26abae3fSMichal Meloun     int maxcount, int *irqs)
468*26abae3fSMichal Meloun {
469*26abae3fSMichal Meloun 	phandle_t msi_parent;
470*26abae3fSMichal Meloun 	int rv;
471*26abae3fSMichal Meloun 
472*26abae3fSMichal Meloun 	rv = ofw_bus_msimap(ofw_bus_get_node(pci), pci_get_rid(child),
473*26abae3fSMichal Meloun 	    &msi_parent, NULL);
474*26abae3fSMichal Meloun 	if (rv != 0)
475*26abae3fSMichal Meloun 		return (rv);
476*26abae3fSMichal Meloun 
477*26abae3fSMichal Meloun 	return (intr_alloc_msi(pci, child, msi_parent, count, maxcount,
478*26abae3fSMichal Meloun 	    irqs));
479*26abae3fSMichal Meloun }
480*26abae3fSMichal Meloun 
481*26abae3fSMichal Meloun static int
482*26abae3fSMichal Meloun pci_dw_release_msi(device_t pci, device_t child, int count, int *irqs)
483*26abae3fSMichal Meloun {
484*26abae3fSMichal Meloun 	phandle_t msi_parent;
485*26abae3fSMichal Meloun 	int rv;
486*26abae3fSMichal Meloun 
487*26abae3fSMichal Meloun 	rv = ofw_bus_msimap(ofw_bus_get_node(pci), pci_get_rid(child),
488*26abae3fSMichal Meloun 	    &msi_parent, NULL);
489*26abae3fSMichal Meloun 	if (rv != 0)
490*26abae3fSMichal Meloun 		return (rv);
491*26abae3fSMichal Meloun 	return (intr_release_msi(pci, child, msi_parent, count, irqs));
492*26abae3fSMichal Meloun }
493*26abae3fSMichal Meloun 
494*26abae3fSMichal Meloun static int
495*26abae3fSMichal Meloun pci_dw_map_msi(device_t pci, device_t child, int irq, uint64_t *addr,
496*26abae3fSMichal Meloun     uint32_t *data)
497*26abae3fSMichal Meloun {
498*26abae3fSMichal Meloun 	phandle_t msi_parent;
499*26abae3fSMichal Meloun 	int rv;
500*26abae3fSMichal Meloun 
501*26abae3fSMichal Meloun 	rv = ofw_bus_msimap(ofw_bus_get_node(pci), pci_get_rid(child),
502*26abae3fSMichal Meloun 	    &msi_parent, NULL);
503*26abae3fSMichal Meloun 	if (rv != 0)
504*26abae3fSMichal Meloun 		return (rv);
505*26abae3fSMichal Meloun 
506*26abae3fSMichal Meloun 	return (intr_map_msi(pci, child, msi_parent, irq, addr, data));
507*26abae3fSMichal Meloun }
508*26abae3fSMichal Meloun 
509*26abae3fSMichal Meloun static int
510*26abae3fSMichal Meloun pci_dw_alloc_msix(device_t pci, device_t child, int *irq)
511*26abae3fSMichal Meloun {
512*26abae3fSMichal Meloun 	phandle_t msi_parent;
513*26abae3fSMichal Meloun 	int rv;
514*26abae3fSMichal Meloun 
515*26abae3fSMichal Meloun 	rv = ofw_bus_msimap(ofw_bus_get_node(pci), pci_get_rid(child),
516*26abae3fSMichal Meloun 	    &msi_parent, NULL);
517*26abae3fSMichal Meloun 	if (rv != 0)
518*26abae3fSMichal Meloun 		return (rv);
519*26abae3fSMichal Meloun 	return (intr_alloc_msix(pci, child, msi_parent, irq));
520*26abae3fSMichal Meloun }
521*26abae3fSMichal Meloun 
522*26abae3fSMichal Meloun static int
523*26abae3fSMichal Meloun pci_dw_release_msix(device_t pci, device_t child, int irq)
524*26abae3fSMichal Meloun {
525*26abae3fSMichal Meloun 	phandle_t msi_parent;
526*26abae3fSMichal Meloun 	int rv;
527*26abae3fSMichal Meloun 
528*26abae3fSMichal Meloun 	rv = ofw_bus_msimap(ofw_bus_get_node(pci), pci_get_rid(child),
529*26abae3fSMichal Meloun 	    &msi_parent, NULL);
530*26abae3fSMichal Meloun 	if (rv != 0)
531*26abae3fSMichal Meloun 		return (rv);
532*26abae3fSMichal Meloun 	return (intr_release_msix(pci, child, msi_parent, irq));
533*26abae3fSMichal Meloun }
534*26abae3fSMichal Meloun 
535*26abae3fSMichal Meloun static int
536*26abae3fSMichal Meloun pci_dw_get_id(device_t pci, device_t child, enum pci_id_type type,
537*26abae3fSMichal Meloun     uintptr_t *id)
538*26abae3fSMichal Meloun {
539*26abae3fSMichal Meloun 	phandle_t node;
540*26abae3fSMichal Meloun 	int rv;
541*26abae3fSMichal Meloun 	uint32_t rid;
542*26abae3fSMichal Meloun 	uint16_t pci_rid;
543*26abae3fSMichal Meloun 
544*26abae3fSMichal Meloun 	if (type != PCI_ID_MSI)
545*26abae3fSMichal Meloun 		return (pcib_get_id(pci, child, type, id));
546*26abae3fSMichal Meloun 
547*26abae3fSMichal Meloun 	node = ofw_bus_get_node(pci);
548*26abae3fSMichal Meloun 	pci_rid = pci_get_rid(child);
549*26abae3fSMichal Meloun 
550*26abae3fSMichal Meloun 	rv = ofw_bus_msimap(node, pci_rid, NULL, &rid);
551*26abae3fSMichal Meloun 	if (rv != 0)
552*26abae3fSMichal Meloun 		return (rv);
553*26abae3fSMichal Meloun 	*id = rid;
554*26abae3fSMichal Meloun 
555*26abae3fSMichal Meloun 	return (0);
556*26abae3fSMichal Meloun }
557*26abae3fSMichal Meloun 
558*26abae3fSMichal Meloun /*-----------------------------------------------------------------------------
559*26abae3fSMichal Meloun  *
560*26abae3fSMichal Meloun  *  B U S  / D E V I C E   I N T E R F A C E
561*26abae3fSMichal Meloun  */
562*26abae3fSMichal Meloun static bus_dma_tag_t
563*26abae3fSMichal Meloun pci_dw_get_dma_tag(device_t dev, device_t child)
564*26abae3fSMichal Meloun {
565*26abae3fSMichal Meloun 	struct pci_dw_softc *sc;
566*26abae3fSMichal Meloun 
567*26abae3fSMichal Meloun 	sc = device_get_softc(dev);
568*26abae3fSMichal Meloun 	return (sc->dmat);
569*26abae3fSMichal Meloun }
570*26abae3fSMichal Meloun 
571*26abae3fSMichal Meloun int
572*26abae3fSMichal Meloun pci_dw_init(device_t dev)
573*26abae3fSMichal Meloun {
574*26abae3fSMichal Meloun 	struct pci_dw_softc *sc;
575*26abae3fSMichal Meloun 	int rv, rid;
576*26abae3fSMichal Meloun 
577*26abae3fSMichal Meloun 	sc = device_get_softc(dev);
578*26abae3fSMichal Meloun 	sc->dev = dev;
579*26abae3fSMichal Meloun 	sc->node = ofw_bus_get_node(dev);
580*26abae3fSMichal Meloun 
581*26abae3fSMichal Meloun 	mtx_init(&sc->mtx, "pci_dw_mtx", NULL, MTX_DEF);
582*26abae3fSMichal Meloun 
583*26abae3fSMichal Meloun 	/* XXXn Should not be this configurable ? */
584*26abae3fSMichal Meloun 	sc->bus_start = 0;
585*26abae3fSMichal Meloun 	sc->bus_end = 255;
586*26abae3fSMichal Meloun 	sc->root_bus = 0;
587*26abae3fSMichal Meloun 	sc->sub_bus = 1;
588*26abae3fSMichal Meloun 
589*26abae3fSMichal Meloun 	/* Read FDT properties */
590*26abae3fSMichal Meloun 	if (!sc->coherent)
591*26abae3fSMichal Meloun 		sc->coherent = OF_hasprop(sc->node, "dma-coherent");
592*26abae3fSMichal Meloun 
593*26abae3fSMichal Meloun 	rv = OF_getencprop(sc->node, "num-viewport", &sc->num_viewport,
594*26abae3fSMichal Meloun 	    sizeof(sc->num_viewport));
595*26abae3fSMichal Meloun 	if (rv != sizeof(sc->num_viewport))
596*26abae3fSMichal Meloun 		sc->num_viewport = 2;
597*26abae3fSMichal Meloun 
598*26abae3fSMichal Meloun 	rv = OF_getencprop(sc->node, "num-lanes", &sc->num_lanes,
599*26abae3fSMichal Meloun 	    sizeof(sc->num_viewport));
600*26abae3fSMichal Meloun 	if (rv != sizeof(sc->num_lanes))
601*26abae3fSMichal Meloun 		sc->num_lanes = 1;
602*26abae3fSMichal Meloun 	if (sc->num_lanes != 1 && sc->num_lanes != 2 &&
603*26abae3fSMichal Meloun 	    sc->num_lanes != 4 && sc->num_lanes != 8) {
604*26abae3fSMichal Meloun 		device_printf(dev,
605*26abae3fSMichal Meloun 		    "invalid number of lanes: %d\n",sc->num_lanes);
606*26abae3fSMichal Meloun 		sc->num_lanes = 0;
607*26abae3fSMichal Meloun 		rv = ENXIO;
608*26abae3fSMichal Meloun 		goto out;
609*26abae3fSMichal Meloun 	}
610*26abae3fSMichal Meloun 
611*26abae3fSMichal Meloun 	rid = 0;
612*26abae3fSMichal Meloun 	rv = ofw_bus_find_string_index(sc->node, "reg-names", "config", &rid);
613*26abae3fSMichal Meloun 	if (rv != 0) {
614*26abae3fSMichal Meloun 		device_printf(dev, "Cannot get config space memory\n");
615*26abae3fSMichal Meloun 		rv = ENXIO;
616*26abae3fSMichal Meloun 		goto out;
617*26abae3fSMichal Meloun 	}
618*26abae3fSMichal Meloun 	sc->cfg_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
619*26abae3fSMichal Meloun 	    RF_ACTIVE);
620*26abae3fSMichal Meloun 	if (sc->cfg_res == NULL) {
621*26abae3fSMichal Meloun 		device_printf(dev, "Cannot allocate config space(rid: %d)\n",
622*26abae3fSMichal Meloun 		    rid);
623*26abae3fSMichal Meloun 		rv = ENXIO;
624*26abae3fSMichal Meloun 		goto out;
625*26abae3fSMichal Meloun 	}
626*26abae3fSMichal Meloun 
627*26abae3fSMichal Meloun 	/* Fill up config region related variables */
628*26abae3fSMichal Meloun 	sc->cfg_size = rman_get_size(sc->cfg_res);
629*26abae3fSMichal Meloun 	sc->cfg_pa = rman_get_start(sc->cfg_res) ;
630*26abae3fSMichal Meloun 
631*26abae3fSMichal Meloun 	if (bootverbose)
632*26abae3fSMichal Meloun 		device_printf(dev, "Bus is%s cache-coherent\n",
633*26abae3fSMichal Meloun 		    sc->coherent ? "" : " not");
634*26abae3fSMichal Meloun 	rv = bus_dma_tag_create(bus_get_dma_tag(dev), /* parent */
635*26abae3fSMichal Meloun 	    1, 0,				/* alignment, bounds */
636*26abae3fSMichal Meloun 	    BUS_SPACE_MAXADDR,			/* lowaddr */
637*26abae3fSMichal Meloun 	    BUS_SPACE_MAXADDR,			/* highaddr */
638*26abae3fSMichal Meloun 	    NULL, NULL,				/* filter, filterarg */
639*26abae3fSMichal Meloun 	    BUS_SPACE_MAXSIZE,			/* maxsize */
640*26abae3fSMichal Meloun 	    BUS_SPACE_UNRESTRICTED,		/* nsegments */
641*26abae3fSMichal Meloun 	    BUS_SPACE_MAXSIZE,			/* maxsegsize */
642*26abae3fSMichal Meloun 	    sc->coherent ? BUS_DMA_COHERENT : 0, /* flags */
643*26abae3fSMichal Meloun 	    NULL, NULL,				/* lockfunc, lockarg */
644*26abae3fSMichal Meloun 	    &sc->dmat);
645*26abae3fSMichal Meloun 	if (rv != 0)
646*26abae3fSMichal Meloun 		goto out;
647*26abae3fSMichal Meloun 
648*26abae3fSMichal Meloun 	rv = ofw_pci_init(dev);
649*26abae3fSMichal Meloun 	if (rv != 0)
650*26abae3fSMichal Meloun 		goto out;
651*26abae3fSMichal Meloun 	rv = pci_dw_decode_ranges(sc, sc->ofw_pci.sc_range,
652*26abae3fSMichal Meloun 	    sc->ofw_pci.sc_nrange);
653*26abae3fSMichal Meloun 	if (rv != 0)
654*26abae3fSMichal Meloun 		goto out;
655*26abae3fSMichal Meloun 
656*26abae3fSMichal Meloun 	rv = pci_dw_setup_hw(sc);
657*26abae3fSMichal Meloun 	if (rv != 0)
658*26abae3fSMichal Meloun 		goto out;
659*26abae3fSMichal Meloun 
660*26abae3fSMichal Meloun 	device_add_child(dev, "pci", -1);
661*26abae3fSMichal Meloun 
662*26abae3fSMichal Meloun 	return (bus_generic_attach(dev));
663*26abae3fSMichal Meloun out:
664*26abae3fSMichal Meloun 	/* XXX Cleanup */
665*26abae3fSMichal Meloun 	return (rv);
666*26abae3fSMichal Meloun }
667*26abae3fSMichal Meloun 
668*26abae3fSMichal Meloun static device_method_t pci_dw_methods[] = {
669*26abae3fSMichal Meloun 
670*26abae3fSMichal Meloun 	/* Bus interface */
671*26abae3fSMichal Meloun 	DEVMETHOD(bus_get_dma_tag,	pci_dw_get_dma_tag),
672*26abae3fSMichal Meloun 
673*26abae3fSMichal Meloun 	/* pcib interface */
674*26abae3fSMichal Meloun 	DEVMETHOD(pcib_read_config,	pci_dw_read_config),
675*26abae3fSMichal Meloun 	DEVMETHOD(pcib_write_config,	pci_dw_write_config),
676*26abae3fSMichal Meloun 	DEVMETHOD(pcib_alloc_msi,	pci_dw_alloc_msi),
677*26abae3fSMichal Meloun 	DEVMETHOD(pcib_release_msi,	pci_dw_release_msi),
678*26abae3fSMichal Meloun 	DEVMETHOD(pcib_alloc_msix,	pci_dw_alloc_msix),
679*26abae3fSMichal Meloun 	DEVMETHOD(pcib_release_msix,	pci_dw_release_msix),
680*26abae3fSMichal Meloun 	DEVMETHOD(pcib_map_msi,		pci_dw_map_msi),
681*26abae3fSMichal Meloun 	DEVMETHOD(pcib_get_id,		pci_dw_get_id),
682*26abae3fSMichal Meloun 
683*26abae3fSMichal Meloun 	/* OFW bus interface */
684*26abae3fSMichal Meloun 	DEVMETHOD(ofw_bus_get_compat,	ofw_bus_gen_get_compat),
685*26abae3fSMichal Meloun 	DEVMETHOD(ofw_bus_get_model,	ofw_bus_gen_get_model),
686*26abae3fSMichal Meloun 	DEVMETHOD(ofw_bus_get_name,	ofw_bus_gen_get_name),
687*26abae3fSMichal Meloun 	DEVMETHOD(ofw_bus_get_node,	ofw_bus_gen_get_node),
688*26abae3fSMichal Meloun 	DEVMETHOD(ofw_bus_get_type,	ofw_bus_gen_get_type),
689*26abae3fSMichal Meloun 
690*26abae3fSMichal Meloun 	/* PCI DW interface  */
691*26abae3fSMichal Meloun 	DEVMETHOD(pci_dw_dbi_read,	pci_dw_dbi_read),
692*26abae3fSMichal Meloun 	DEVMETHOD(pci_dw_dbi_write,	pci_dw_dbi_write),
693*26abae3fSMichal Meloun 	DEVMETHOD_END
694*26abae3fSMichal Meloun };
695*26abae3fSMichal Meloun 
696*26abae3fSMichal Meloun DEFINE_CLASS_1(pcib, pci_dw_driver, pci_dw_methods,
697*26abae3fSMichal Meloun     sizeof(struct pci_dw_softc), ofw_pci_driver);
698