ixp425_pci.c revision 189630
167754Smsmith/*	$NetBSD: ixp425_pci.c,v 1.5 2006/04/10 03:36:03 simonb Exp $ */
267754Smsmith
367754Smsmith/*
467754Smsmith * Copyright (c) 2003
567754Smsmith *	Ichiro FUKUHARA <ichiro@ichiro.org>.
6138287Smarks * All rights reserved.
767754Smsmith *
867754Smsmith * Redistribution and use in source and binary forms, with or without
967754Smsmith * modification, are permitted provided that the following conditions
1067754Smsmith * are met:
1167754Smsmith * 1. Redistributions of source code must retain the above copyright
1267754Smsmith *    notice, this list of conditions and the following disclaimer.
1367754Smsmith * 2. Redistributions in binary form must reproduce the above copyright
14126372Snjl *    notice, this list of conditions and the following disclaimer in the
1570243Smsmith *    documentation and/or other materials provided with the distribution.
1667754Smsmith * 3. All advertising materials mentioning features or use of this software
1767754Smsmith *    must display the following acknowledgement:
1867754Smsmith *	This product includes software developed by Ichiro FUKUHARA.
1967754Smsmith * 4. The name of the company nor the name of the author may be used to
2067754Smsmith *    endorse or promote products derived from this software without specific
2167754Smsmith *    prior written permission.
2267754Smsmith *
2367754Smsmith * THIS SOFTWARE IS PROVIDED BY ICHIRO FUKUHARA ``AS IS'' AND ANY EXPRESS OR
2467754Smsmith * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
2567754Smsmith * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
2667754Smsmith * IN NO EVENT SHALL ICHIRO FUKUHARA OR THE VOICES IN HIS HEAD BE LIABLE FOR
2767754Smsmith * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2867754Smsmith * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2967754Smsmith * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
3067754Smsmith * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
3167754Smsmith * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3267754Smsmith * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3367754Smsmith * SUCH DAMAGE.
3467754Smsmith */
3567754Smsmith
3667754Smsmith#include <sys/cdefs.h>
3767754Smsmith__FBSDID("$FreeBSD: head/sys/arm/xscale/ixp425/ixp425_pci.c 189630 2009-03-10 16:42:49Z sam $");
3867754Smsmith
3967754Smsmith#include <sys/param.h>
4067754Smsmith#include <sys/systm.h>
4167754Smsmith#include <sys/malloc.h>
4267754Smsmith#define _ARM32_BUS_DMA_PRIVATE
4367754Smsmith#include <sys/bus.h>
4467754Smsmith#include <sys/kernel.h>
4567754Smsmith#include <sys/module.h>
4667754Smsmith#include <sys/rman.h>
4767754Smsmith
4867754Smsmith#include <machine/bus.h>
4967754Smsmith#include <machine/cpu.h>
5067754Smsmith#include <machine/pcb.h>
5167754Smsmith#include <vm/vm.h>
5267754Smsmith#include <vm/pmap.h>
5367754Smsmith#include <vm/vm_extern.h>
5467754Smsmith#include <machine/pmap.h>
5567754Smsmith
5667754Smsmith#include <arm/xscale/ixp425/ixp425reg.h>
5767754Smsmith#include <arm/xscale/ixp425/ixp425var.h>
5867754Smsmith
5967754Smsmith#include <dev/pci/pcib_private.h>
6067754Smsmith#include "pcib_if.h"
6167754Smsmith
6267754Smsmith#include <dev/pci/pcireg.h>
6367754Smsmithextern struct ixp425_softc *ixp425_softc;
6467754Smsmith
6567754Smsmith#define	PCI_CSR_WRITE_4(sc, reg, data)	\
6667754Smsmith	bus_write_4(sc->sc_csr, reg, data)
6767754Smsmith
6867754Smsmith#define	PCI_CSR_READ_4(sc, reg)	\
6967754Smsmith	bus_read_4(sc->sc_csr, reg)
7067754Smsmith
7167754Smsmith#define PCI_CONF_LOCK(s)	(s) = disable_interrupts(I32_bit)
7267754Smsmith#define PCI_CONF_UNLOCK(s)	restore_interrupts((s))
7367754Smsmith
7467754Smsmithstatic device_probe_t ixppcib_probe;
7567754Smsmithstatic device_attach_t ixppcib_attach;
7667754Smsmithstatic bus_read_ivar_t ixppcib_read_ivar;
7767754Smsmithstatic bus_write_ivar_t ixppcib_write_ivar;
7867754Smsmithstatic bus_setup_intr_t ixppcib_setup_intr;
7967754Smsmithstatic bus_teardown_intr_t ixppcib_teardown_intr;
8067754Smsmithstatic bus_alloc_resource_t ixppcib_alloc_resource;
8167754Smsmithstatic bus_activate_resource_t ixppcib_activate_resource;
8267754Smsmithstatic bus_deactivate_resource_t ixppcib_deactivate_resource;
8367754Smsmithstatic bus_release_resource_t ixppcib_release_resource;
8467754Smsmithstatic pcib_maxslots_t ixppcib_maxslots;
8567754Smsmithstatic pcib_read_config_t ixppcib_read_config;
8667754Smsmithstatic pcib_write_config_t ixppcib_write_config;
8767754Smsmithstatic pcib_route_interrupt_t ixppcib_route_interrupt;
8867754Smsmith
8967754Smsmithstatic int
9067754Smsmithixppcib_probe(device_t dev)
9167754Smsmith{
9267754Smsmith	device_set_desc(dev, "IXP4XX PCI Bus");
9367754Smsmith        return (0);
9467754Smsmith}
9567754Smsmith
9667754Smsmithstatic void
9767754Smsmithixp425_pci_conf_reg_write(struct ixppcib_softc *sc, uint32_t reg,
9867754Smsmith    uint32_t data)
9967754Smsmith{
10067754Smsmith	PCI_CSR_WRITE_4(sc, PCI_CRP_AD_CBE, ((reg & ~3) | COMMAND_CRP_WRITE));
10167754Smsmith	PCI_CSR_WRITE_4(sc, PCI_CRP_AD_WDATA, data);
10267754Smsmith}
10367754Smsmith
10467754Smsmithstatic int
10567754Smsmithixppcib_attach(device_t dev)
10667754Smsmith{
10767754Smsmith	int rid;
10867754Smsmith	struct ixppcib_softc *sc;
10967754Smsmith
11067754Smsmith	sc = device_get_softc(dev);
11167754Smsmith
11267754Smsmith	rid = 0;
11367754Smsmith	sc->sc_csr = bus_alloc_resource(dev, SYS_RES_MEMORY, &rid,
11467754Smsmith	    IXP425_PCI_HWBASE, IXP425_PCI_HWBASE + IXP425_PCI_SIZE,
11567754Smsmith	    IXP425_PCI_SIZE, RF_ACTIVE);
11667754Smsmith	if (sc->sc_csr == NULL)
11767754Smsmith		panic("cannot allocate PCI CSR registers");
11867754Smsmith
11967754Smsmith	ixp425_md_attach(dev);
12067754Smsmith	/* always setup the base, incase another OS messes w/ it */
12167754Smsmith	PCI_CSR_WRITE_4(sc, PCI_PCIMEMBASE, 0x48494a4b);
12267754Smsmith
123117521Snjl	rid = 0;
12467754Smsmith	sc->sc_mem = bus_alloc_resource(dev, SYS_RES_MEMORY, &rid,
12577424Smsmith	    IXP425_PCI_MEM_HWBASE, IXP425_PCI_MEM_HWBASE + IXP425_PCI_MEM_SIZE,
12691116Smsmith	    IXP425_PCI_MEM_SIZE, RF_ACTIVE);
12767754Smsmith	if (sc->sc_mem == NULL)
12867754Smsmith		panic("cannot allocate PCI MEM space");
12967754Smsmith
13067754Smsmith	/* NB: PCI dma window is 64M so anything above must be bounced */
13167754Smsmith	if (bus_dma_tag_create(NULL, 1, 0, IXP425_AHB_OFFSET + 64 * 1024 * 1024,
13267754Smsmith	    BUS_SPACE_MAXADDR, NULL, NULL,  0xffffffff, 0xff, 0xffffffff, 0,
133117521Snjl	    NULL, NULL, &sc->sc_dmat))
13467754Smsmith		panic("couldn't create the PCI dma tag !");
13567754Smsmith	/*
13667754Smsmith	 * The PCI bus can only address 64MB. However, due to the way our
13767754Smsmith	 * implementation of busdma works, busdma can't tell if a device
138138287Smarks	 * is a PCI device or not. So defaults to the PCI dma tag, which
13967754Smsmith	 * restrict the DMA'able memory to the first 64MB, and explicitely
14067754Smsmith	 * create less restrictive tags for non-PCI devices.
14167754Smsmith	 */
14299679Siwasaki	arm_root_dma_tag = sc->sc_dmat;
143117521Snjl	/*
144117521Snjl	 * Initialize the bus space tags.
14567754Smsmith	 */
14691116Smsmith	ixp425_io_bs_init(&sc->sc_pci_iot, sc);
14767754Smsmith	ixp425_mem_bs_init(&sc->sc_pci_memt, sc);
14867754Smsmith
14991116Smsmith	sc->sc_dev = dev;
15067754Smsmith
15167754Smsmith	/* Initialize memory and i/o rmans. */
15282367Smsmith	sc->sc_io_rman.rm_type = RMAN_ARRAY;
15391116Smsmith	sc->sc_io_rman.rm_descr = "IXP4XX PCI I/O Ports";
15477424Smsmith	if (rman_init(&sc->sc_io_rman) != 0 ||
15567754Smsmith		rman_manage_region(&sc->sc_io_rman, 0,
156117521Snjl	    	    IXP425_PCI_IO_SIZE) != 0) {
15791116Smsmith		panic("ixppcib_probe: failed to set up I/O rman");
158117521Snjl	}
159117521Snjl
160117521Snjl	sc->sc_mem_rman.rm_type = RMAN_ARRAY;
161117521Snjl	sc->sc_mem_rman.rm_descr = "IXP4XX PCI Memory";
162117521Snjl	if (rman_init(&sc->sc_mem_rman) != 0 ||
16391116Smsmith		rman_manage_region(&sc->sc_mem_rman, IXP425_PCI_MEM_HWBASE,
16467754Smsmith		    IXP425_PCI_MEM_HWBASE + IXP425_PCI_MEM_SIZE) != 0) {
16599679Siwasaki		panic("ixppcib_probe: failed to set up memory rman");
16699679Siwasaki	}
16799679Siwasaki
16899679Siwasaki	/*
16999679Siwasaki	 * PCI->AHB address translation
17099679Siwasaki	 * 	begin at the physical memory start + OFFSET
17167754Smsmith	 */
17291116Smsmith	PCI_CSR_WRITE_4(sc, PCI_AHBMEMBASE,
17369450Smsmith	    (IXP425_AHB_OFFSET & 0xFF000000) +
17470243Smsmith	    ((IXP425_AHB_OFFSET & 0xFF000000) >> 8) +
17567754Smsmith	    ((IXP425_AHB_OFFSET & 0xFF000000) >> 16) +
17699679Siwasaki	    ((IXP425_AHB_OFFSET & 0xFF000000) >> 24) +
177117521Snjl	    0x00010203);
17899679Siwasaki
17999679Siwasaki#define IXPPCIB_WRITE_CONF(sc, reg, val) \
18099679Siwasaki	ixp425_pci_conf_reg_write(sc, reg, val)
18199679Siwasaki	/* Write Mapping registers PCI Configuration Registers */
18267754Smsmith	/* Base Address 0 - 3 */
18367754Smsmith	IXPPCIB_WRITE_CONF(sc, PCI_MAPREG_BAR0, IXP425_AHB_OFFSET + 0x00000000);
184114237Snjl	IXPPCIB_WRITE_CONF(sc, PCI_MAPREG_BAR1, IXP425_AHB_OFFSET + 0x01000000);
18567754Smsmith	IXPPCIB_WRITE_CONF(sc, PCI_MAPREG_BAR2, IXP425_AHB_OFFSET + 0x02000000);
186138287Smarks	IXPPCIB_WRITE_CONF(sc, PCI_MAPREG_BAR3, IXP425_AHB_OFFSET + 0x03000000);
187117521Snjl
188117521Snjl	/* Base Address 4 */
189117521Snjl	IXPPCIB_WRITE_CONF(sc, PCI_MAPREG_BAR4, 0xffffffff);
19067754Smsmith
191117521Snjl	/* Base Address 5 */
19267754Smsmith	IXPPCIB_WRITE_CONF(sc, PCI_MAPREG_BAR5, 0x00000000);
19399679Siwasaki
19467754Smsmith	/* Assert some PCI errors */
19567754Smsmith	PCI_CSR_WRITE_4(sc, PCI_ISR, ISR_AHBE | ISR_PPE | ISR_PFE | ISR_PSE);
19667754Smsmith
19767754Smsmith#ifdef __ARMEB__
19867754Smsmith	/*
19999679Siwasaki	 * Set up byte lane swapping between little-endian PCI
20067754Smsmith	 * and the big-endian AHB bus
20191116Smsmith	 */
20291116Smsmith	PCI_CSR_WRITE_4(sc, PCI_CSR, CSR_IC | CSR_ABE | CSR_PDS);
20391116Smsmith#else
20467754Smsmith	PCI_CSR_WRITE_4(sc, PCI_CSR, CSR_IC | CSR_ABE);
20567754Smsmith#endif
20667754Smsmith
20791116Smsmith	/*
20891116Smsmith	 * Enable bus mastering and I/O,memory access
20967754Smsmith	 */
21067754Smsmith	IXPPCIB_WRITE_CONF(sc, PCIR_COMMAND,
21167754Smsmith	    PCIM_CMD_MEMEN | PCIM_CMD_BUSMASTEREN);
21267754Smsmith
21399679Siwasaki	/*
21467754Smsmith	 * Wait some more to ensure PCI devices have stabilised.
21591116Smsmith	 */
21691116Smsmith	DELAY(50000);
21767754Smsmith
21867754Smsmith	device_add_child(dev, "pci", -1);
219129684Snjl	return (bus_generic_attach(dev));
22067754Smsmith}
22167754Smsmith
22299679Siwasakistatic int
22367754Smsmithixppcib_read_ivar(device_t dev, device_t child, int which, uintptr_t *result)
22467754Smsmith{
22567754Smsmith	struct ixppcib_softc *sc;
22699679Siwasaki
22767754Smsmith	sc = device_get_softc(dev);
22867754Smsmith	switch (which) {
22991116Smsmith	case PCIB_IVAR_DOMAIN:
23067754Smsmith		*result = 0;
23167754Smsmith		return (0);
23267754Smsmith	case PCIB_IVAR_BUS:
23367754Smsmith		*result = sc->sc_bus;
23467754Smsmith		return (0);
23599679Siwasaki	}
23667754Smsmith
237129684Snjl	return (ENOENT);
238126372Snjl}
239129684Snjl
24067754Smsmithstatic int
24167754Smsmithixppcib_write_ivar(device_t dev, device_t child, int which, uintptr_t value)
242114237Snjl{
243126372Snjl	struct ixppcib_softc *sc;
244114237Snjl
24567754Smsmith	sc = device_get_softc(dev);
24667754Smsmith	switch (which) {
24767754Smsmith	case PCIB_IVAR_DOMAIN:
24899679Siwasaki		return (EINVAL);
24999679Siwasaki	case PCIB_IVAR_BUS:
250129684Snjl		sc->sc_bus = value;
25167754Smsmith		return (0);
25291116Smsmith	}
25399679Siwasaki
25467754Smsmith	return (ENOENT);
25567754Smsmith}
25699679Siwasaki
25767754Smsmithstatic int
258129684Snjlixppcib_setup_intr(device_t dev, device_t child, struct resource *ires,
25999679Siwasaki    int flags, driver_filter_t *filt, driver_intr_t *intr, void *arg,
26099679Siwasaki    void **cookiep)
26199679Siwasaki{
26299679Siwasaki
26367754Smsmith	return (BUS_SETUP_INTR(device_get_parent(dev), child, ires, flags,
26499679Siwasaki	    filt, intr, arg, cookiep));
26599679Siwasaki}
266129684Snjl
26767754Smsmithstatic int
26891116Smsmithixppcib_teardown_intr(device_t dev, device_t child, struct resource *vec,
26991116Smsmith     void *cookie)
27067754Smsmith{
27199679Siwasaki
27299679Siwasaki	return (BUS_TEARDOWN_INTR(device_get_parent(dev), child, vec, cookie));
27399679Siwasaki}
274129684Snjl
275129684Snjlstatic struct resource *
27667754Smsmithixppcib_alloc_resource(device_t bus, device_t child, int type, int *rid,
27799679Siwasaki    u_long start, u_long end, u_long count, u_int flags)
278129684Snjl{
279129684Snjl	struct ixppcib_softc *sc = device_get_softc(bus);
28091116Smsmith	struct rman *rmanp;
28167754Smsmith	struct resource *rv;
28267754Smsmith
28367754Smsmith	rv = NULL;
28467754Smsmith	switch (type) {
28599679Siwasaki	case SYS_RES_IRQ:
28667754Smsmith		rmanp = &sc->sc_irq_rman;
287129684Snjl		break;
288129684Snjl
28967754Smsmith	case SYS_RES_IOPORT:
29067754Smsmith		rmanp = &sc->sc_io_rman;
29167754Smsmith		break;
29267754Smsmith
293129684Snjl	case SYS_RES_MEMORY:
294129684Snjl		rmanp = &sc->sc_mem_rman;
295129684Snjl		break;
296129684Snjl
29767754Smsmith	default:
29867754Smsmith		return (rv);
299129684Snjl	}
30067754Smsmith
30167754Smsmith	rv = rman_reserve_resource(rmanp, start, end, count, flags & ~RF_ACTIVE,
30267754Smsmith	    child);
30367754Smsmith	if (rv == NULL)
30467754Smsmith		return (NULL);
30567754Smsmith	rman_set_rid(rv, *rid);
30691116Smsmith	if (flags & RF_ACTIVE) {
30767754Smsmith		if (bus_activate_resource(child, type, *rid, rv)) {
30899679Siwasaki			rman_release_resource(rv);
309102550Siwasaki			return (NULL);
31091116Smsmith		}
31191116Smsmith	}
31291116Smsmith
31391116Smsmith	return (rv);
31491116Smsmith}
31591116Smsmith
31691116Smsmithstatic int
31791116Smsmithixppcib_activate_resource(device_t bus, device_t child, int type, int rid,
31891116Smsmith    struct resource *r)
31991116Smsmith{
32091116Smsmith
32191116Smsmith	struct ixppcib_softc *sc = device_get_softc(bus);
32291116Smsmith
32391116Smsmith	switch (type) {
32491116Smsmith	case SYS_RES_IOPORT:
32591116Smsmith		rman_set_bustag(r, &sc->sc_pci_iot);
32691116Smsmith		rman_set_bushandle(r, rman_get_start(r));
32791116Smsmith		break;
32891116Smsmith	case SYS_RES_MEMORY:
32991116Smsmith		rman_set_bustag(r, &sc->sc_pci_memt);
33091116Smsmith		rman_set_bushandle(r, rman_get_bushandle(sc->sc_mem) +
33191116Smsmith		    (rman_get_start(r) - IXP425_PCI_MEM_HWBASE));
33291116Smsmith		break;
33391116Smsmith	}
33491116Smsmith
33599679Siwasaki	return (rman_activate_resource(r));
33691116Smsmith}
337117521Snjl
338117521Snjlstatic int
339117521Snjlixppcib_deactivate_resource(device_t bus, device_t child, int type, int rid,
34067754Smsmith    struct resource *r)
341138287Smarks{
342138287Smarks
34367754Smsmith	device_printf(bus, "%s called deactivate_resource (unexpected)\n",
34491116Smsmith	    device_get_nameunit(child));
34567754Smsmith	return (ENXIO);
34667754Smsmith}
34767754Smsmith
34899679Siwasakistatic int
34999679Siwasakiixppcib_release_resource(device_t bus, device_t child, int type, int rid,
35067754Smsmith    struct resource *r)
35199679Siwasaki{
35291116Smsmith
35367754Smsmith	device_printf(bus, "%s called release_resource (unexpected)\n",
35467754Smsmith	    device_get_nameunit(child));
35591116Smsmith	return (ENXIO);
35699679Siwasaki}
35767754Smsmith
35877424Smsmithstatic void
35999679Siwasakiixppcib_conf_setup(struct ixppcib_softc *sc, int bus, int slot, int func,
36067754Smsmith    int reg)
36167754Smsmith{
36291116Smsmith	if (bus == 0) {
36391116Smsmith		/* configuration type 0 */
36491116Smsmith		PCI_CSR_WRITE_4(sc, PCI_NP_AD,
36591116Smsmith		    (1U << (32 - (slot & 0x1f))) |
36677424Smsmith		    ((func & 0x7) << 8) | (reg & ~3));
36791116Smsmith	} else {
36869450Smsmith		/* configuration type 1 */
36967754Smsmith		PCI_CSR_WRITE_4(sc, PCI_NP_AD,
37099679Siwasaki		    (bus << 16) | (slot << 11) |
37199679Siwasaki		    (func << 8) | (reg & ~3) | 1);
37299679Siwasaki	}
37399679Siwasaki
37499679Siwasaki}
37599679Siwasaki
37699679Siwasakistatic int
37799679Siwasakiixppcib_maxslots(device_t dev)
37891116Smsmith{
379138287Smarks
380138287Smarks	return (PCI_SLOTMAX);
381102550Siwasaki}
38299679Siwasaki
38399679Siwasakistatic u_int32_t
38491116Smsmithixppcib_read_config(device_t dev, u_int bus, u_int slot, u_int func, u_int reg,
38567754Smsmith    int bytes)
38691116Smsmith{
38791116Smsmith	struct ixppcib_softc *sc = device_get_softc(dev);
38867754Smsmith	u_int32_t data, ret;
38999679Siwasaki
39099679Siwasaki	ixppcib_conf_setup(sc, bus, slot, func, reg & ~3);
39199679Siwasaki
39267754Smsmith	PCI_CSR_WRITE_4(sc, PCI_NP_CBE, COMMAND_NP_CONF_READ);
393102550Siwasaki	ret = PCI_CSR_READ_4(sc, PCI_NP_RDATA);
39499679Siwasaki	ret >>= (reg & 3) * 8;
39567754Smsmith	ret &= 0xffffffff >> ((4 - bytes) * 8);
39699679Siwasaki#if 0
39799679Siwasaki	device_printf(dev, "%s: %u:%u:%u %#x(%d) = %#x\n",
398123315Snjl	    __func__, bus, slot, func, reg, bytes, ret);
399117521Snjl#endif
40099679Siwasaki	/* check & clear PCI abort */
40199679Siwasaki	data = PCI_CSR_READ_4(sc, PCI_ISR);
40299679Siwasaki	if (data & ISR_PFE) {
40391116Smsmith		PCI_CSR_WRITE_4(sc, PCI_ISR, ISR_PFE);
40467754Smsmith		return (-1);
40567754Smsmith	}
40691116Smsmith	return (ret);
40791116Smsmith}
40899679Siwasaki
40991116Smsmithstatic const int byteenables[] = { 0, 0x10, 0x30, 0x70, 0xf0 };
41091116Smsmith
41191116Smsmithstatic void
412138287Smarksixppcib_write_config(device_t dev, u_int bus, u_int slot, u_int func, u_int reg,
41391116Smsmith    u_int32_t val, int bytes)
41491116Smsmith{
415138287Smarks	struct ixppcib_softc *sc = device_get_softc(dev);
41691116Smsmith	u_int32_t data;
41791116Smsmith
41891116Smsmith#if 0
41991116Smsmith	device_printf(dev, "%s: %u:%u:%u %#x(%d) = %#x\n",
42067754Smsmith	    __func__, bus, slot, func, reg, bytes, val);
42199679Siwasaki#endif
42299679Siwasaki	ixppcib_conf_setup(sc, bus, slot, func, reg & ~3);
42391116Smsmith
42491116Smsmith	/* Byte enables are active low, so not them first */
42591116Smsmith	PCI_CSR_WRITE_4(sc, PCI_NP_CBE, COMMAND_NP_CONF_WRITE |
42691116Smsmith	    (~(byteenables[bytes] << (reg & 3)) & 0xf0));
42791116Smsmith	PCI_CSR_WRITE_4(sc, PCI_NP_WDATA, val << ((reg & 3) * 8));
42891116Smsmith
42999679Siwasaki	/* check & clear PCI abort */
43067754Smsmith	data = PCI_CSR_READ_4(sc, PCI_ISR);
43167754Smsmith	if (data & ISR_PFE)
43299679Siwasaki		PCI_CSR_WRITE_4(sc, PCI_ISR, ISR_PFE);
43367754Smsmith}
43467754Smsmith
43591116Smsmithstatic int
43667754Smsmithixppcib_route_interrupt(device_t bridge, device_t device, int pin)
43791116Smsmith{
43891116Smsmith
43991116Smsmith	return (ixp425_md_route_interrupt(bridge, device, pin));
44099679Siwasaki}
44191116Smsmith
44291116Smsmithstatic device_method_t ixppcib_methods[] = {
44367754Smsmith	/* Device interface */
44499679Siwasaki	DEVMETHOD(device_probe,			ixppcib_probe),
44599679Siwasaki	DEVMETHOD(device_attach,		ixppcib_attach),
44699679Siwasaki
44799679Siwasaki	/* Bus interface */
44899679Siwasaki	DEVMETHOD(bus_print_child,		bus_generic_print_child),
44999679Siwasaki	DEVMETHOD(bus_read_ivar,		ixppcib_read_ivar),
45099679Siwasaki	DEVMETHOD(bus_write_ivar,		ixppcib_write_ivar),
45199679Siwasaki	DEVMETHOD(bus_setup_intr,		ixppcib_setup_intr),
45299679Siwasaki	DEVMETHOD(bus_teardown_intr,		ixppcib_teardown_intr),
45391116Smsmith	DEVMETHOD(bus_alloc_resource,		ixppcib_alloc_resource),
45467754Smsmith	DEVMETHOD(bus_activate_resource,	ixppcib_activate_resource),
455102550Siwasaki	DEVMETHOD(bus_deactivate_resource,	ixppcib_deactivate_resource),
45699679Siwasaki	DEVMETHOD(bus_release_resource,		ixppcib_release_resource),
45799679Siwasaki	/* DEVMETHOD(bus_get_dma_tag,		ixppcib_get_dma_tag), */
45899679Siwasaki
45999679Siwasaki	/* pcib interface */
46099679Siwasaki	DEVMETHOD(pcib_maxslots,		ixppcib_maxslots),
46167754Smsmith	DEVMETHOD(pcib_read_config,		ixppcib_read_config),
46291116Smsmith	DEVMETHOD(pcib_write_config,		ixppcib_write_config),
46391116Smsmith	DEVMETHOD(pcib_route_interrupt,		ixppcib_route_interrupt),
464123315Snjl
46591116Smsmith	{0, 0},
466123315Snjl};
46791116Smsmith
46891116Smsmithstatic driver_t ixppcib_driver = {
46991116Smsmith	"pcib",
47091116Smsmith	ixppcib_methods,
47191116Smsmith	sizeof(struct ixppcib_softc),
47267754Smsmith};
47391116Smsmithstatic devclass_t ixppcib_devclass;
47491116Smsmith
475123315SnjlDRIVER_MODULE(ixppcib, ixp, ixppcib_driver, ixppcib_devclass, 0, 0);
47691116Smsmith