Attach elansc(4) at mainbus(4) instead of at pci(4). Attach pci(4)

at elansc(4).  Take advantage of a suspend/resume cycle to reconfigure
the SC520's PCI host-bridge bus for higher performance.  Update
the manual pages and the NET4501 kernel.
This commit is contained in:
dyoung 2008-04-08 20:30:16 +00:00
parent 112605d50a
commit 2c7f43b53e
5 changed files with 138 additions and 32 deletions
share/man/man4/man4.i386
sys/arch/i386

@ -1,4 +1,4 @@
.\" $NetBSD: elanpar.4,v 1.2 2008/01/21 21:51:57 dyoung Exp $
.\" $NetBSD: elanpar.4,v 1.3 2008/04/08 20:30:16 dyoung Exp $
.\"
.\"
.\" Copyright (c) 2008 David Young. All rights reserved.
@ -38,7 +38,7 @@
.Nm elanpar
.Nd AMD Elan SC520 Programmable Address Regions
.Sh SYNOPSIS
.Cd "elansc* at pci? dev ? function ?"
.Cd "elansc* at mainbus? bus ?"
.Cd "elanpar* at elansc?"
.Sh DESCRIPTION
The

@ -1,4 +1,4 @@
.\" $NetBSD: elanpex.4,v 1.2 2008/01/21 21:51:57 dyoung Exp $
.\" $NetBSD: elanpex.4,v 1.3 2008/04/08 20:30:16 dyoung Exp $
.\"
.\"
.\" Copyright (c) 2008 David Young. All rights reserved.
@ -38,7 +38,7 @@
.Nm elanpex
.Nd AMD Elan SC520 PCI Exception Instrumentation
.Sh SYNOPSIS
.Cd "elansc* at pci? dev ? function ?"
.Cd "elansc* at mainbus? bus ?"
.Cd "elanpex* at elansc?"
.Sh DESCRIPTION
The

@ -1,4 +1,4 @@
.\" $NetBSD: elansc.4,v 1.9 2008/01/21 22:00:37 dyoung Exp $
.\" $NetBSD: elansc.4,v 1.10 2008/04/08 20:30:16 dyoung Exp $
.\"
.\" Copyright (c) 2002 The NetBSD Foundation, Inc.
.\" All rights reserved.
@ -41,8 +41,9 @@
.Nm elansc
.Nd AMD Elan SC520 System Controller driver
.Sh SYNOPSIS
.Cd "elansc* at pci? dev ? function ?"
.Cd "elansc* at mainbus? bus ?"
.Cd "gpio* at elansc?"
.Cd "pci* at elansc?"
.Cd "elanpar* at elansc?"
.Cd "elanpex* at elansc?"
.Sh DESCRIPTION
@ -91,6 +92,11 @@ framework.
The
.Xr gpioctl 8
program allows easy manipulation of pins from userland.
.It
PCI host-bridge optimization.
.Nm
takes advantage of a suspend/resume cycle to tune the PCI host-bridge
for higher performance.
.El
.Sh SEE ALSO
.Xr elanpar 4 ,

@ -1,4 +1,4 @@
# $NetBSD: NET4501,v 1.60 2008/01/16 09:37:07 ad Exp $
# $NetBSD: NET4501,v 1.61 2008/04/08 20:30:17 dyoung Exp $
#
# NET4501 -- kernel configuration for a Soekris Engineering net4501
# single-board computer.
@ -10,7 +10,7 @@ include "arch/i386/conf/std.i386"
#options INCLUDE_CONFIG_FILE # embed config file in kernel binary
#ident "NET4501-$Revision: 1.60 $"
#ident "NET4501-$Revision: 1.61 $"
maxusers 32 # estimated number of users
@ -180,7 +180,7 @@ cpu0 at mainbus0
# Basic Bus Support
# PCI bus support
pci* at mainbus? bus ?
pci* at elansc? bus ?
# Configure PCI using BIOS information
#options PCIBIOS # PCI BIOS support
@ -193,7 +193,7 @@ pci* at mainbus? bus ?
#options PCIINTR_DEBUG # super-verbose PCI interrupt fixup
# PCI bridges
elansc* at pci? dev ? function ? # Elan SC520 System Controller
elansc* at mainbus? bus ? # Elan SC520 System Controller
gpio* at elansc?
#gpioow* at gpio? offset 6 mask 0x1 # 1-wire bus bitbanging via gpio
#onewire* at gpioow?

@ -1,4 +1,4 @@
/* $NetBSD: elan520.c,v 1.30 2008/04/07 03:59:46 dyoung Exp $ */
/* $NetBSD: elan520.c,v 1.31 2008/04/08 20:30:17 dyoung Exp $ */
/*-
* Copyright (c) 2002 The NetBSD Foundation, Inc.
@ -47,7 +47,7 @@
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: elan520.c,v 1.30 2008/04/07 03:59:46 dyoung Exp $");
__KERNEL_RCSID(0, "$NetBSD: elan520.c,v 1.31 2008/04/08 20:30:17 dyoung Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@ -81,6 +81,7 @@ struct elansc_softc {
device_t sc_dev;
device_t sc_par;
device_t sc_pex;
device_t sc_pci;
pci_chipset_tag_t sc_pc;
pcitag_t sc_tag;
@ -105,6 +106,7 @@ struct elansc_softc {
#endif
};
static bool elansc_attached = false;
int elansc_wpvnmi = 1;
int elansc_pcinmi = 1;
int elansc_do_protect_pg0 = 1;
@ -116,11 +118,13 @@ static void elansc_gpio_pin_ctl(void *, int, int);
#endif
static void elansc_print_par(device_t, int, uint32_t);
static void elanpex_intr_establish(device_t, struct elansc_softc *);
static void elanpar_intr_establish(device_t, struct elansc_softc *);
static void elanpex_intr_disestablish(struct elansc_softc *);
static void elanpar_intr_disestablish(struct elansc_softc *);
static bool elanpar_shutdown(device_t, int);
static void elanpex_intr_establish(device_t, struct elansc_softc *);
static void elanpex_intr_disestablish(struct elansc_softc *);
static bool elanpex_shutdown(device_t, int);
static void elansc_protect(struct elansc_softc *, int, paddr_t, uint32_t);
@ -136,11 +140,114 @@ elansc_childdetached(device_t self, device_t child)
sc->sc_par = NULL;
if (child == sc->sc_pex)
sc->sc_pex = NULL;
if (child == sc->sc_pci)
sc->sc_pci = NULL;
/* elansc does not presently keep a pointer to
* the gpio, so there is nothing to do if it is detached.
*/
}
static int
elansc_match(device_t parent, cfdata_t match, void *aux)
{
struct pcibus_attach_args *pba = aux;
pcitag_t tag;
pcireg_t id;
if (elansc_attached)
return 0;
if (pcimatch(parent, match, aux) == 0)
return 0;
if (pba->pba_bus != 0)
return 0;
tag = pci_make_tag(pba->pba_pc, 0, 0, 0);
id = pci_conf_read(pba->pba_pc, tag, PCI_ID_REG);
if (PCI_VENDOR(id) == PCI_VENDOR_AMD &&
PCI_PRODUCT(id) == PCI_PRODUCT_AMD_SC520_SC)
return 10;
return 0;
}
/*
* Performance tuning for Soekris net4501:
* - enable SDRAM write buffer and read prefetching
*/
#if 0
uint8_t dbctl;
dbctl = bus_space_read_1(memt, memh, MMCR_DBCTL);
dbctl &= ~MMCR_DBCTL_WB_WM_MASK;
dbctl |= MMCR_DBCTL_WB_WM_16DW;
dbctl |= MMCR_DBCTL_WB_ENB | MMCR_DBCTL_RAB_ENB;
bus_space_write_1(memt, memh, MMCR_DBCTL, dbctl);
#endif
/*
* Performance tuning for PCI bus on the AMD Elan SC520:
* - enable concurrent arbitration of PCI and CPU busses
* (and PCI buffer)
* - enable PCI automatic delayed read transactions and
* write posting
* - enable PCI read buffer snooping (coherency)
*/
static void
elansc_perf_tune(device_t self, bus_space_tag_t memt, bus_space_handle_t memh)
{
uint8_t sysarbctl;
uint16_t hbctl;
const bool concurrency = true; /* concurrent bus arbitration */
sysarbctl = bus_space_read_1(memt, memh, MMCR_SYSARBCTL);
if ((sysarbctl & MMCR_SYSARBCTL_CNCR_MODE_ENB) != 0) {
aprint_debug_dev(self,
"concurrent arbitration mode is active\n");
} else if (concurrency) {
aprint_verbose_dev(self, "activating concurrent "
"arbitration mode\n");
/* activate concurrent bus arbitration */
sysarbctl |= MMCR_SYSARBCTL_CNCR_MODE_ENB;
bus_space_write_1(memt, memh, MMCR_SYSARBCTL, sysarbctl);
}
hbctl = bus_space_read_2(memt, memh, MMCR_HBCTL);
/* target read FIFO snoop */
if ((hbctl & MMCR_HBCTL_T_PURGE_RD_ENB) != 0)
aprint_debug_dev(self, "read-FIFO snooping is active\n");
else {
aprint_verbose_dev(self, "activating read-FIFO snooping\n");
hbctl |= MMCR_HBCTL_T_PURGE_RD_ENB;
}
if ((hbctl & MMCR_HBCTL_M_WPOST_ENB) != 0)
aprint_debug_dev(self, "CPU->PCI write-posting is active\n");
else if (concurrency) {
aprint_verbose_dev(self, "activating CPU->PCI write-posting\n");
hbctl |= MMCR_HBCTL_M_WPOST_ENB;
}
/* auto delay read txn: looks safe, but seems to cause
* net4526 w/ minipci ath fits
*/
#if 0
if ((hbctl & MMCR_HBCTL_T_DLYTR_ENB_AUTORETRY) != 0)
aprint_debug_dev(self,
"automatic read transaction delay is active\n");
else {
aprint_verbose_dev(self,
"activating automatic read transaction delay\n");
hbctl |= MMCR_HBCTL_T_DLYTR_ENB_AUTORETRY;
}
#endif
bus_space_write_2(memt, memh, MMCR_HBCTL, hbctl);
}
static void
elansc_wdogctl_write(struct elansc_softc *sc, uint16_t val)
{
@ -271,18 +378,6 @@ elansc_wdog_tickle(struct sysmon_wdog *smw)
return 0;
}
static int
elansc_match(device_t parent, struct cfdata *match, void *aux)
{
struct pci_attach_args *pa = aux;
if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_AMD &&
PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_AMD_SC520_SC)
return (10); /* beat pchb */
return (0);
}
static const char *elansc_speeds[] = {
"(reserved 00)",
"100MHz",
@ -774,6 +869,8 @@ elansc_resume(device_t dev PMF_FN_ARGS)
elansc_wdogctl_reset(sc);
mutex_exit(&sc->sc_mtx);
elansc_perf_tune(dev, sc->sc_memt, sc->sc_memh);
return true;
}
@ -806,6 +903,7 @@ elansc_detach(device_t self, int flags)
mutex_exit(&sc->sc_mtx);
mutex_destroy(&sc->sc_mtx);
elansc_attached = false;
return 0;
}
@ -1138,7 +1236,7 @@ static void
elansc_attach(device_t parent, device_t self, void *aux)
{
struct elansc_softc *sc = device_private(self);
struct pci_attach_args *pa = aux;
struct pcibus_attach_args *pba = aux;
uint16_t rev;
uint8_t cpuctl, picicr, ressta;
#if NGPIO > 0
@ -1149,13 +1247,13 @@ elansc_attach(device_t parent, device_t self, void *aux)
sc->sc_dev = self;
sc->sc_pc = pa->pa_pc;
sc->sc_tag = pa->pa_tag;
sc->sc_pc = pba->pba_pc;
sc->sc_tag = pci_make_tag(sc->sc_pc, 0, 0, 0);
aprint_naive(": System Controller\n");
aprint_normal(": AMD Elan SC520 System Controller\n");
sc->sc_memt = pa->pa_memt;
sc->sc_memt = pba->pba_memt;
if (bus_space_map(sc->sc_memt, MMCR_BASE_ADDR, PAGE_SIZE, 0,
&sc->sc_memh) != 0) {
aprint_error_dev(sc->sc_dev, "unable to map registers\n");
@ -1284,6 +1382,8 @@ elansc_attach(device_t parent, device_t self, void *aux)
aprint_error_dev(sc->sc_dev,
"unable to register watchdog with sysmon\n");
}
elansc_attached = true;
sc->sc_pci = config_found_ia(self, "pcibus", pba, pcibusprint);
}
static int
@ -1302,10 +1402,10 @@ elanpar_match(device_t parent, struct cfdata *match, void *aux)
return sc->sc_par == NULL;
}
CFATTACH_DECL_NEW(elanpar, sizeof(struct device),
CFATTACH_DECL_NEW(elanpar, 0,
elanpar_match, elanpar_attach, elanpar_detach, NULL);
CFATTACH_DECL_NEW(elanpex, sizeof(struct device),
CFATTACH_DECL_NEW(elanpex, 0,
elanpex_match, elanpex_attach, elanpex_detach, NULL);
CFATTACH_DECL2_NEW(elansc, sizeof(struct elansc_softc),