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:
parent
112605d50a
commit
2c7f43b53e
@ -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),
|
||||
|
Loading…
x
Reference in New Issue
Block a user