xref: /freebsd/sys/dev/pci/controller/pci_n1sdp.c (revision 667c3fc0f658d3d345ff0e1b4b7c6bf42a959040)
1*667c3fc0SRuslan Bukin /*-
2*667c3fc0SRuslan Bukin  * SPDX-License-Identifier: BSD-2-Clause
3*667c3fc0SRuslan Bukin  *
4*667c3fc0SRuslan Bukin  * Copyright (c) 2019 Andrew Turner
5*667c3fc0SRuslan Bukin  * Copyright (c) 2019 Ruslan Bukin <br@bsdpad.com>
6*667c3fc0SRuslan Bukin  *
7*667c3fc0SRuslan Bukin  * This software was developed by SRI International and the University of
8*667c3fc0SRuslan Bukin  * Cambridge Computer Laboratory (Department of Computer Science and
9*667c3fc0SRuslan Bukin  * Technology) under DARPA contract HR0011-18-C-0016 ("ECATS"), as part of the
10*667c3fc0SRuslan Bukin  * DARPA SSITH research programme.
11*667c3fc0SRuslan Bukin  *
12*667c3fc0SRuslan Bukin  * Redistribution and use in source and binary forms, with or without
13*667c3fc0SRuslan Bukin  * modification, are permitted provided that the following conditions
14*667c3fc0SRuslan Bukin  * are met:
15*667c3fc0SRuslan Bukin  * 1. Redistributions of source code must retain the above copyright
16*667c3fc0SRuslan Bukin  *    notice, this list of conditions and the following disclaimer.
17*667c3fc0SRuslan Bukin  * 2. Redistributions in binary form must reproduce the above copyright
18*667c3fc0SRuslan Bukin  *    notice, this list of conditions and the following disclaimer in the
19*667c3fc0SRuslan Bukin  *    documentation and/or other materials provided with the distribution.
20*667c3fc0SRuslan Bukin  *
21*667c3fc0SRuslan Bukin  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
22*667c3fc0SRuslan Bukin  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23*667c3fc0SRuslan Bukin  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24*667c3fc0SRuslan Bukin  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
25*667c3fc0SRuslan Bukin  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26*667c3fc0SRuslan Bukin  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27*667c3fc0SRuslan Bukin  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28*667c3fc0SRuslan Bukin  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29*667c3fc0SRuslan Bukin  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30*667c3fc0SRuslan Bukin  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31*667c3fc0SRuslan Bukin  * SUCH DAMAGE.
32*667c3fc0SRuslan Bukin  */
33*667c3fc0SRuslan Bukin 
34*667c3fc0SRuslan Bukin #include <sys/cdefs.h>
35*667c3fc0SRuslan Bukin __FBSDID("$FreeBSD$");
36*667c3fc0SRuslan Bukin 
37*667c3fc0SRuslan Bukin #include <sys/param.h>
38*667c3fc0SRuslan Bukin #include <sys/systm.h>
39*667c3fc0SRuslan Bukin #include <sys/malloc.h>
40*667c3fc0SRuslan Bukin #include <sys/bus.h>
41*667c3fc0SRuslan Bukin #include <sys/endian.h>
42*667c3fc0SRuslan Bukin #include <sys/kernel.h>
43*667c3fc0SRuslan Bukin #include <sys/module.h>
44*667c3fc0SRuslan Bukin #include <sys/rman.h>
45*667c3fc0SRuslan Bukin 
46*667c3fc0SRuslan Bukin #include <vm/vm.h>
47*667c3fc0SRuslan Bukin #include <vm/vm_extern.h>
48*667c3fc0SRuslan Bukin #include <vm/vm_page.h>
49*667c3fc0SRuslan Bukin 
50*667c3fc0SRuslan Bukin #include <contrib/dev/acpica/include/acpi.h>
51*667c3fc0SRuslan Bukin #include <contrib/dev/acpica/include/accommon.h>
52*667c3fc0SRuslan Bukin 
53*667c3fc0SRuslan Bukin #include <dev/acpica/acpivar.h>
54*667c3fc0SRuslan Bukin #include <dev/acpica/acpi_pcibvar.h>
55*667c3fc0SRuslan Bukin 
56*667c3fc0SRuslan Bukin #include <dev/pci/pcivar.h>
57*667c3fc0SRuslan Bukin #include <dev/pci/pcireg.h>
58*667c3fc0SRuslan Bukin #include <dev/pci/pcib_private.h>
59*667c3fc0SRuslan Bukin #include <dev/pci/pci_host_generic.h>
60*667c3fc0SRuslan Bukin #include <dev/pci/pci_host_generic_acpi.h>
61*667c3fc0SRuslan Bukin 
62*667c3fc0SRuslan Bukin #include "pcib_if.h"
63*667c3fc0SRuslan Bukin 
64*667c3fc0SRuslan Bukin #define	AP_NS_SHARED_MEM_BASE	0x06000000
65*667c3fc0SRuslan Bukin #define	N1SDP_MAX_SEGMENTS	2 /* Two PCIe root complex devices. */
66*667c3fc0SRuslan Bukin #define	BDF_TABLE_SIZE		(16 * 1024)
67*667c3fc0SRuslan Bukin #define	PCI_CFG_SPACE_SIZE	0x1000
68*667c3fc0SRuslan Bukin 
69*667c3fc0SRuslan Bukin struct pcie_discovery_data {
70*667c3fc0SRuslan Bukin 	uint32_t rc_base_addr;
71*667c3fc0SRuslan Bukin 	uint32_t nr_bdfs;
72*667c3fc0SRuslan Bukin 	uint32_t valid_bdfs[0];
73*667c3fc0SRuslan Bukin };
74*667c3fc0SRuslan Bukin 
75*667c3fc0SRuslan Bukin struct generic_pcie_n1sdp_softc {
76*667c3fc0SRuslan Bukin 	struct generic_pcie_acpi_softc acpi;
77*667c3fc0SRuslan Bukin 	struct pcie_discovery_data *n1_discovery_data;
78*667c3fc0SRuslan Bukin 	bus_space_handle_t n1_bsh;
79*667c3fc0SRuslan Bukin };
80*667c3fc0SRuslan Bukin 
81*667c3fc0SRuslan Bukin static int
82*667c3fc0SRuslan Bukin n1sdp_init(struct generic_pcie_n1sdp_softc *sc)
83*667c3fc0SRuslan Bukin {
84*667c3fc0SRuslan Bukin 	struct pcie_discovery_data *shared_data;
85*667c3fc0SRuslan Bukin 	vm_offset_t vaddr;
86*667c3fc0SRuslan Bukin 	vm_paddr_t paddr_rc;
87*667c3fc0SRuslan Bukin 	vm_paddr_t paddr;
88*667c3fc0SRuslan Bukin 	int table_count;
89*667c3fc0SRuslan Bukin 	int bdfs_size;
90*667c3fc0SRuslan Bukin 	int error, i;
91*667c3fc0SRuslan Bukin 
92*667c3fc0SRuslan Bukin 	paddr = AP_NS_SHARED_MEM_BASE + sc->acpi.segment * BDF_TABLE_SIZE;
93*667c3fc0SRuslan Bukin 	vaddr = kva_alloc((vm_size_t)BDF_TABLE_SIZE);
94*667c3fc0SRuslan Bukin 	if (vaddr == 0) {
95*667c3fc0SRuslan Bukin 		printf("%s: Can't allocate KVA memory.", __func__);
96*667c3fc0SRuslan Bukin 		return (ENXIO);
97*667c3fc0SRuslan Bukin 	}
98*667c3fc0SRuslan Bukin 	pmap_kenter(vaddr, (vm_size_t)BDF_TABLE_SIZE, paddr,
99*667c3fc0SRuslan Bukin 	    VM_MEMATTR_UNCACHEABLE);
100*667c3fc0SRuslan Bukin 
101*667c3fc0SRuslan Bukin 	shared_data = (struct pcie_discovery_data *)vaddr;
102*667c3fc0SRuslan Bukin 	bdfs_size = sizeof(struct pcie_discovery_data) +
103*667c3fc0SRuslan Bukin 	    sizeof(uint32_t) * shared_data->nr_bdfs;
104*667c3fc0SRuslan Bukin 	sc->n1_discovery_data = malloc(bdfs_size, M_DEVBUF, M_WAITOK | M_ZERO);
105*667c3fc0SRuslan Bukin 	memcpy(sc->n1_discovery_data, shared_data, bdfs_size);
106*667c3fc0SRuslan Bukin 
107*667c3fc0SRuslan Bukin 	paddr_rc = (vm_offset_t)shared_data->rc_base_addr;
108*667c3fc0SRuslan Bukin 	error = bus_space_map(sc->acpi.base.bst, paddr_rc, PCI_CFG_SPACE_SIZE,
109*667c3fc0SRuslan Bukin 	    0, &sc->n1_bsh);
110*667c3fc0SRuslan Bukin 	if (error != 0)
111*667c3fc0SRuslan Bukin 		return (error);
112*667c3fc0SRuslan Bukin 
113*667c3fc0SRuslan Bukin 	if (bootverbose) {
114*667c3fc0SRuslan Bukin 		table_count = sc->n1_discovery_data->nr_bdfs;
115*667c3fc0SRuslan Bukin 		for (i = 0; i < table_count; i++)
116*667c3fc0SRuslan Bukin 			printf("valid bdf %x\n",
117*667c3fc0SRuslan Bukin 			    sc->n1_discovery_data->valid_bdfs[i]);
118*667c3fc0SRuslan Bukin 	}
119*667c3fc0SRuslan Bukin 
120*667c3fc0SRuslan Bukin 	pmap_kremove(vaddr);
121*667c3fc0SRuslan Bukin 	kva_free(vaddr, (vm_size_t)BDF_TABLE_SIZE);
122*667c3fc0SRuslan Bukin 
123*667c3fc0SRuslan Bukin 	return (0);
124*667c3fc0SRuslan Bukin }
125*667c3fc0SRuslan Bukin 
126*667c3fc0SRuslan Bukin static int
127*667c3fc0SRuslan Bukin n1sdp_check_bdf(struct generic_pcie_n1sdp_softc *sc,
128*667c3fc0SRuslan Bukin     u_int bus, u_int slot, u_int func)
129*667c3fc0SRuslan Bukin {
130*667c3fc0SRuslan Bukin 	int table_count;
131*667c3fc0SRuslan Bukin 	int bdf;
132*667c3fc0SRuslan Bukin 	int i;
133*667c3fc0SRuslan Bukin 
134*667c3fc0SRuslan Bukin 	bdf = PCIE_ADDR_OFFSET(bus, slot, func, 0);
135*667c3fc0SRuslan Bukin 	if (bdf == 0)
136*667c3fc0SRuslan Bukin 		return (1);
137*667c3fc0SRuslan Bukin 
138*667c3fc0SRuslan Bukin 	table_count = sc->n1_discovery_data->nr_bdfs;
139*667c3fc0SRuslan Bukin 
140*667c3fc0SRuslan Bukin 	for (i = 0; i < table_count; i++)
141*667c3fc0SRuslan Bukin 		if (bdf == sc->n1_discovery_data->valid_bdfs[i])
142*667c3fc0SRuslan Bukin 			return (1);
143*667c3fc0SRuslan Bukin 
144*667c3fc0SRuslan Bukin 	return (0);
145*667c3fc0SRuslan Bukin }
146*667c3fc0SRuslan Bukin 
147*667c3fc0SRuslan Bukin static int
148*667c3fc0SRuslan Bukin n1sdp_pcie_acpi_probe(device_t dev)
149*667c3fc0SRuslan Bukin {
150*667c3fc0SRuslan Bukin 	ACPI_DEVICE_INFO *devinfo;
151*667c3fc0SRuslan Bukin 	ACPI_TABLE_HEADER *hdr;
152*667c3fc0SRuslan Bukin 	ACPI_STATUS status;
153*667c3fc0SRuslan Bukin 	ACPI_HANDLE h;
154*667c3fc0SRuslan Bukin 	int root;
155*667c3fc0SRuslan Bukin 
156*667c3fc0SRuslan Bukin 	if (acpi_disabled("pcib") || (h = acpi_get_handle(dev)) == NULL ||
157*667c3fc0SRuslan Bukin 	    ACPI_FAILURE(AcpiGetObjectInfo(h, &devinfo)))
158*667c3fc0SRuslan Bukin 		return (ENXIO);
159*667c3fc0SRuslan Bukin 
160*667c3fc0SRuslan Bukin 	root = (devinfo->Flags & ACPI_PCI_ROOT_BRIDGE) != 0;
161*667c3fc0SRuslan Bukin 	AcpiOsFree(devinfo);
162*667c3fc0SRuslan Bukin 	if (!root)
163*667c3fc0SRuslan Bukin 		return (ENXIO);
164*667c3fc0SRuslan Bukin 
165*667c3fc0SRuslan Bukin 	/* TODO: Move this to an ACPI quirk? */
166*667c3fc0SRuslan Bukin 	status = AcpiGetTable(ACPI_SIG_MCFG, 1, &hdr);
167*667c3fc0SRuslan Bukin 	if (ACPI_FAILURE(status))
168*667c3fc0SRuslan Bukin 		return (ENXIO);
169*667c3fc0SRuslan Bukin 
170*667c3fc0SRuslan Bukin 	if (memcmp(hdr->OemId, "ARMLTD", ACPI_OEM_ID_SIZE) != 0 ||
171*667c3fc0SRuslan Bukin 	    memcmp(hdr->OemTableId, "ARMN1SDP", ACPI_OEM_TABLE_ID_SIZE) != 0 ||
172*667c3fc0SRuslan Bukin 	    hdr->OemRevision != 0x20181101)
173*667c3fc0SRuslan Bukin 		return (ENXIO);
174*667c3fc0SRuslan Bukin 
175*667c3fc0SRuslan Bukin 	device_set_desc(dev, "ARM N1SDP PCI host controller");
176*667c3fc0SRuslan Bukin 	return (BUS_PROBE_DEFAULT);
177*667c3fc0SRuslan Bukin }
178*667c3fc0SRuslan Bukin 
179*667c3fc0SRuslan Bukin static int
180*667c3fc0SRuslan Bukin n1sdp_pcie_acpi_attach(device_t dev)
181*667c3fc0SRuslan Bukin {
182*667c3fc0SRuslan Bukin 	struct generic_pcie_n1sdp_softc *sc;
183*667c3fc0SRuslan Bukin 	ACPI_HANDLE handle;
184*667c3fc0SRuslan Bukin 	ACPI_STATUS status;
185*667c3fc0SRuslan Bukin 	int err;
186*667c3fc0SRuslan Bukin 
187*667c3fc0SRuslan Bukin 	err = pci_host_generic_acpi_init(dev);
188*667c3fc0SRuslan Bukin 	if (err != 0)
189*667c3fc0SRuslan Bukin 		return (err);
190*667c3fc0SRuslan Bukin 
191*667c3fc0SRuslan Bukin 	sc = device_get_softc(dev);
192*667c3fc0SRuslan Bukin 	handle = acpi_get_handle(dev);
193*667c3fc0SRuslan Bukin 
194*667c3fc0SRuslan Bukin 	/* Get PCI Segment (domain) needed for IOMMU space remap. */
195*667c3fc0SRuslan Bukin 	status = acpi_GetInteger(handle, "_SEG", &sc->acpi.segment);
196*667c3fc0SRuslan Bukin 	if (ACPI_FAILURE(status)) {
197*667c3fc0SRuslan Bukin 		device_printf(dev, "No _SEG for PCI Bus\n");
198*667c3fc0SRuslan Bukin 		return (ENXIO);
199*667c3fc0SRuslan Bukin 	}
200*667c3fc0SRuslan Bukin 
201*667c3fc0SRuslan Bukin 	if (sc->acpi.segment >= N1SDP_MAX_SEGMENTS) {
202*667c3fc0SRuslan Bukin 		device_printf(dev, "Unknown PCI Bus segment (domain) %d\n",
203*667c3fc0SRuslan Bukin 		    sc->acpi.segment);
204*667c3fc0SRuslan Bukin 		return (ENXIO);
205*667c3fc0SRuslan Bukin 	}
206*667c3fc0SRuslan Bukin 
207*667c3fc0SRuslan Bukin 	err = n1sdp_init(sc);
208*667c3fc0SRuslan Bukin 	if (err)
209*667c3fc0SRuslan Bukin 		return (err);
210*667c3fc0SRuslan Bukin 
211*667c3fc0SRuslan Bukin 	device_add_child(dev, "pci", -1);
212*667c3fc0SRuslan Bukin 	return (bus_generic_attach(dev));
213*667c3fc0SRuslan Bukin }
214*667c3fc0SRuslan Bukin 
215*667c3fc0SRuslan Bukin static int
216*667c3fc0SRuslan Bukin n1sdp_get_bus_space(device_t dev, u_int bus, u_int slot, u_int func, u_int reg,
217*667c3fc0SRuslan Bukin     bus_space_tag_t *bst, bus_space_handle_t *bsh, bus_size_t *offset)
218*667c3fc0SRuslan Bukin {
219*667c3fc0SRuslan Bukin 	struct generic_pcie_n1sdp_softc *sc;
220*667c3fc0SRuslan Bukin 
221*667c3fc0SRuslan Bukin 	sc = device_get_softc(dev);
222*667c3fc0SRuslan Bukin 
223*667c3fc0SRuslan Bukin 	if (n1sdp_check_bdf(sc, bus, slot, func) == 0)
224*667c3fc0SRuslan Bukin 		return (EINVAL);
225*667c3fc0SRuslan Bukin 
226*667c3fc0SRuslan Bukin 	if (bus == sc->acpi.base.bus_start) {
227*667c3fc0SRuslan Bukin 		if (slot != 0 || func != 0)
228*667c3fc0SRuslan Bukin 			return (EINVAL);
229*667c3fc0SRuslan Bukin 		*bsh = sc->n1_bsh;
230*667c3fc0SRuslan Bukin 	} else {
231*667c3fc0SRuslan Bukin 		*bsh = sc->acpi.base.bsh;
232*667c3fc0SRuslan Bukin 	}
233*667c3fc0SRuslan Bukin 
234*667c3fc0SRuslan Bukin 	*bst = sc->acpi.base.bst;
235*667c3fc0SRuslan Bukin 	*offset = PCIE_ADDR_OFFSET(bus - sc->acpi.base.bus_start, slot, func,
236*667c3fc0SRuslan Bukin 	    reg);
237*667c3fc0SRuslan Bukin 
238*667c3fc0SRuslan Bukin 	return (0);
239*667c3fc0SRuslan Bukin }
240*667c3fc0SRuslan Bukin 
241*667c3fc0SRuslan Bukin static uint32_t
242*667c3fc0SRuslan Bukin n1sdp_pcie_read_config(device_t dev, u_int bus, u_int slot,
243*667c3fc0SRuslan Bukin     u_int func, u_int reg, int bytes)
244*667c3fc0SRuslan Bukin {
245*667c3fc0SRuslan Bukin 	struct generic_pcie_n1sdp_softc *sc_n1sdp;
246*667c3fc0SRuslan Bukin 	struct generic_pcie_acpi_softc *sc_acpi;
247*667c3fc0SRuslan Bukin 	struct generic_pcie_core_softc *sc;
248*667c3fc0SRuslan Bukin 	bus_space_handle_t h;
249*667c3fc0SRuslan Bukin 	bus_space_tag_t t;
250*667c3fc0SRuslan Bukin 	bus_size_t offset;
251*667c3fc0SRuslan Bukin 	uint32_t data;
252*667c3fc0SRuslan Bukin 
253*667c3fc0SRuslan Bukin 	sc_n1sdp = device_get_softc(dev);
254*667c3fc0SRuslan Bukin 	sc_acpi = &sc_n1sdp->acpi;
255*667c3fc0SRuslan Bukin 	sc = &sc_acpi->base;
256*667c3fc0SRuslan Bukin 
257*667c3fc0SRuslan Bukin 	if ((bus < sc->bus_start) || (bus > sc->bus_end))
258*667c3fc0SRuslan Bukin 		return (~0U);
259*667c3fc0SRuslan Bukin 	if ((slot > PCI_SLOTMAX) || (func > PCI_FUNCMAX) ||
260*667c3fc0SRuslan Bukin 	    (reg > PCIE_REGMAX))
261*667c3fc0SRuslan Bukin 		return (~0U);
262*667c3fc0SRuslan Bukin 
263*667c3fc0SRuslan Bukin 	if (n1sdp_get_bus_space(dev, bus, slot, func, reg, &t, &h, &offset) !=0)
264*667c3fc0SRuslan Bukin 		return (~0U);
265*667c3fc0SRuslan Bukin 
266*667c3fc0SRuslan Bukin 	data = bus_space_read_4(t, h, offset & ~3);
267*667c3fc0SRuslan Bukin 
268*667c3fc0SRuslan Bukin 	switch (bytes) {
269*667c3fc0SRuslan Bukin 	case 1:
270*667c3fc0SRuslan Bukin 		data >>= (offset & 3) * 8;
271*667c3fc0SRuslan Bukin 		data &= 0xff;
272*667c3fc0SRuslan Bukin 		break;
273*667c3fc0SRuslan Bukin 	case 2:
274*667c3fc0SRuslan Bukin 		data >>= (offset & 3) * 8;
275*667c3fc0SRuslan Bukin 		data = le16toh(data);
276*667c3fc0SRuslan Bukin 		break;
277*667c3fc0SRuslan Bukin 	case 4:
278*667c3fc0SRuslan Bukin 		data = le32toh(data);
279*667c3fc0SRuslan Bukin 		break;
280*667c3fc0SRuslan Bukin 	default:
281*667c3fc0SRuslan Bukin 		return (~0U);
282*667c3fc0SRuslan Bukin 	}
283*667c3fc0SRuslan Bukin 
284*667c3fc0SRuslan Bukin 	return (data);
285*667c3fc0SRuslan Bukin }
286*667c3fc0SRuslan Bukin 
287*667c3fc0SRuslan Bukin static void
288*667c3fc0SRuslan Bukin n1sdp_pcie_write_config(device_t dev, u_int bus, u_int slot,
289*667c3fc0SRuslan Bukin     u_int func, u_int reg, uint32_t val, int bytes)
290*667c3fc0SRuslan Bukin {
291*667c3fc0SRuslan Bukin 	struct generic_pcie_n1sdp_softc *sc_n1sdp;
292*667c3fc0SRuslan Bukin 	struct generic_pcie_acpi_softc *sc_acpi;
293*667c3fc0SRuslan Bukin 	struct generic_pcie_core_softc *sc;
294*667c3fc0SRuslan Bukin 	bus_space_handle_t h;
295*667c3fc0SRuslan Bukin 	bus_space_tag_t t;
296*667c3fc0SRuslan Bukin 	bus_size_t offset;
297*667c3fc0SRuslan Bukin 	uint32_t data;
298*667c3fc0SRuslan Bukin 
299*667c3fc0SRuslan Bukin 	sc_n1sdp = device_get_softc(dev);
300*667c3fc0SRuslan Bukin 	sc_acpi = &sc_n1sdp->acpi;
301*667c3fc0SRuslan Bukin 	sc = &sc_acpi->base;
302*667c3fc0SRuslan Bukin 
303*667c3fc0SRuslan Bukin 	if ((bus < sc->bus_start) || (bus > sc->bus_end))
304*667c3fc0SRuslan Bukin 		return;
305*667c3fc0SRuslan Bukin 	if ((slot > PCI_SLOTMAX) || (func > PCI_FUNCMAX) ||
306*667c3fc0SRuslan Bukin 	    (reg > PCIE_REGMAX))
307*667c3fc0SRuslan Bukin 		return;
308*667c3fc0SRuslan Bukin 
309*667c3fc0SRuslan Bukin 	if (n1sdp_get_bus_space(dev, bus, slot, func, reg, &t, &h, &offset) !=0)
310*667c3fc0SRuslan Bukin 		return;
311*667c3fc0SRuslan Bukin 
312*667c3fc0SRuslan Bukin 	data = bus_space_read_4(t, h, offset & ~3);
313*667c3fc0SRuslan Bukin 
314*667c3fc0SRuslan Bukin 	switch (bytes) {
315*667c3fc0SRuslan Bukin 	case 1:
316*667c3fc0SRuslan Bukin 		data &= ~(0xff << ((offset & 3) * 8));
317*667c3fc0SRuslan Bukin 		data |= (val & 0xff) << ((offset & 3) * 8);
318*667c3fc0SRuslan Bukin 		break;
319*667c3fc0SRuslan Bukin 	case 2:
320*667c3fc0SRuslan Bukin 		data &= ~(0xffff << ((offset & 3) * 8));
321*667c3fc0SRuslan Bukin 		data |= (val & 0xffff) << ((offset & 3) * 8);
322*667c3fc0SRuslan Bukin 		break;
323*667c3fc0SRuslan Bukin 	case 4:
324*667c3fc0SRuslan Bukin 		data = val;
325*667c3fc0SRuslan Bukin 		break;
326*667c3fc0SRuslan Bukin 	default:
327*667c3fc0SRuslan Bukin 		return;
328*667c3fc0SRuslan Bukin 	}
329*667c3fc0SRuslan Bukin 
330*667c3fc0SRuslan Bukin 	bus_space_write_4(t, h, offset & ~3, data);
331*667c3fc0SRuslan Bukin }
332*667c3fc0SRuslan Bukin 
333*667c3fc0SRuslan Bukin static device_method_t n1sdp_pcie_acpi_methods[] = {
334*667c3fc0SRuslan Bukin 	DEVMETHOD(device_probe,		n1sdp_pcie_acpi_probe),
335*667c3fc0SRuslan Bukin 	DEVMETHOD(device_attach,	n1sdp_pcie_acpi_attach),
336*667c3fc0SRuslan Bukin 
337*667c3fc0SRuslan Bukin 	/* pcib interface */
338*667c3fc0SRuslan Bukin 	DEVMETHOD(pcib_read_config,	n1sdp_pcie_read_config),
339*667c3fc0SRuslan Bukin 	DEVMETHOD(pcib_write_config,	n1sdp_pcie_write_config),
340*667c3fc0SRuslan Bukin 
341*667c3fc0SRuslan Bukin 	DEVMETHOD_END
342*667c3fc0SRuslan Bukin };
343*667c3fc0SRuslan Bukin 
344*667c3fc0SRuslan Bukin DEFINE_CLASS_1(pcib, n1sdp_pcie_acpi_driver, n1sdp_pcie_acpi_methods,
345*667c3fc0SRuslan Bukin     sizeof(struct generic_pcie_n1sdp_softc), generic_pcie_acpi_driver);
346*667c3fc0SRuslan Bukin 
347*667c3fc0SRuslan Bukin static devclass_t n1sdp_pcie_acpi_devclass;
348*667c3fc0SRuslan Bukin 
349*667c3fc0SRuslan Bukin DRIVER_MODULE(n1sdp_pcib, acpi, n1sdp_pcie_acpi_driver,
350*667c3fc0SRuslan Bukin     n1sdp_pcie_acpi_devclass, 0, 0);
351