Make PSC better able to support different protocols, as developed for SPI.
The main changes needed are: 1) pass address and IRQ information from aubus (auspi uses interrupts) 2) all Au1550 PSC protocols have the same status and register bits for enable, so clean that up (clock registers could be different) 3) improve timeout logic on enable (a fixed delay isn't good enough) 4) make aupsc_print return QUIET, as it is annoying to see messages for unconfigured protocols. This whole mechanism should be re- engineered, to either use indirect configuration or provide more detailed board-driven configuration. A comment to that effect is placed in the source. This is shown to work on DBAU1550.
This commit is contained in:
parent
5c050c465e
commit
3bd9bd2f64
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: aupsc.c,v 1.4 2006/03/06 23:06:17 shige Exp $ */
|
||||
/* $NetBSD: aupsc.c,v 1.5 2006/10/02 07:32:16 gdamore Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2006 Shigeyuki Fukushima.
|
||||
|
@ -33,7 +33,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: aupsc.c,v 1.4 2006/03/06 23:06:17 shige Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: aupsc.c,v 1.5 2006/10/02 07:32:16 gdamore Exp $");
|
||||
|
||||
#include "locators.h"
|
||||
|
||||
|
@ -61,16 +61,14 @@ struct aupsc_softc {
|
|||
const struct aupsc_proto {
|
||||
const char *name;
|
||||
int protocol;
|
||||
int statreg;
|
||||
int statbit;
|
||||
} aupsc_protos [] = {
|
||||
{ "ausmbus", AUPSC_SEL_SMBUS, AUPSC_SMBSTAT, SMBUS_STAT_SR },
|
||||
{ "ausmbus", AUPSC_SEL_SMBUS },
|
||||
{ "auspi", AUPSC_SEL_SPI },
|
||||
#if 0
|
||||
{ "auaudio" },
|
||||
{ "aui2s" },
|
||||
{ "auspi" },
|
||||
#endif
|
||||
{ NULL, AUPSC_SEL_DISABLE, 0, 0 }
|
||||
{ NULL, AUPSC_SEL_DISABLE }
|
||||
};
|
||||
|
||||
static int aupsc_match(struct device *, struct cfdata *, void *);
|
||||
|
@ -132,6 +130,8 @@ aupsc_attach(struct device *parent, struct device *self, void *aux)
|
|||
ctrl.psc_disable = aupsc_disable;
|
||||
ctrl.psc_suspend = aupsc_suspend;
|
||||
pa.aupsc_ctrl = ctrl;
|
||||
pa.aupsc_addr = aa->aa_addr;
|
||||
pa.aupsc_irq = aa->aa_irq[0];
|
||||
|
||||
for (i = 0 ; aupsc_protos[i].name != NULL ; i++) {
|
||||
struct aupsc_protocol_device p;
|
||||
|
@ -143,11 +143,10 @@ aupsc_attach(struct device *parent, struct device *self, void *aux)
|
|||
p.sc_ctrl = ctrl;
|
||||
|
||||
aupsc_enable(&p, aupsc_protos[i].protocol);
|
||||
s = bus_space_read_4(sc->sc_bust, sc->sc_bush,
|
||||
aupsc_protos[i].statreg);
|
||||
s = bus_space_read_4(sc->sc_bust, sc->sc_bush, AUPSC_STAT);
|
||||
aupsc_disable(&p);
|
||||
|
||||
if (s & aupsc_protos[i].statbit) {
|
||||
if (s & AUPSC_STAT_SR) {
|
||||
(void) config_found_sm_loc(self, "aupsc", NULL,
|
||||
&pa, aupsc_print, aupsc_submatch);
|
||||
}
|
||||
|
@ -165,18 +164,31 @@ aupsc_submatch(struct device *parent, struct cfdata *cf,
|
|||
static int
|
||||
aupsc_print(void *aux, const char *pnp)
|
||||
{
|
||||
struct aupsc_attach_args *pa = aux;
|
||||
/*
|
||||
* By default we don't want to print anything, because
|
||||
* otherwise we see complaints about protocols that aren't
|
||||
* configured on every port. (E.g. each PSC can support 4
|
||||
* protocols, but on a typical design, only one protocol can
|
||||
* be configured per board.)
|
||||
*
|
||||
* Basically, this whole thing should be replaced with an
|
||||
* indirect configuration mechanism. Direct configuration
|
||||
* doesn't make sense when we absolutely require kernel
|
||||
* configuration to operate.
|
||||
*
|
||||
* Alternatively, a board-specific configuration mechanism
|
||||
* could determine this, and provide direct configuration as
|
||||
* we do for PCMCIA.
|
||||
*/
|
||||
|
||||
if (pnp)
|
||||
aprint_normal("%s at %s", pa->aupsc_name, pnp);
|
||||
|
||||
return UNCONF;
|
||||
return QUIET;
|
||||
}
|
||||
|
||||
static void
|
||||
aupsc_enable(void *arg, int proto)
|
||||
{
|
||||
struct aupsc_protocol_device *sc = arg;
|
||||
int i;
|
||||
|
||||
/* XXX: (TODO) setting clock AUPSC_SEL_CLK */
|
||||
switch (proto) {
|
||||
|
@ -204,7 +216,14 @@ aupsc_enable(void *arg, int proto)
|
|||
AUPSC_SEL, AUPSC_SEL_PS(proto));
|
||||
bus_space_write_4(sc->sc_ctrl.psc_bust, sc->sc_ctrl.psc_bush,
|
||||
AUPSC_CTRL, AUPSC_CTRL_ENA(AUPSC_CTRL_ENABLE));
|
||||
delay(1);
|
||||
|
||||
/* wait up to a whole second, but test every 10us */
|
||||
for (i = 1000000; i; i -= 10) {
|
||||
if (bus_space_read_4(sc->sc_ctrl.psc_bust,
|
||||
sc->sc_ctrl.psc_bush, AUPSC_STAT) & AUPSC_STAT_SR)
|
||||
return;
|
||||
delay(10);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: aupscreg.h,v 1.2 2006/03/06 17:10:46 shige Exp $ */
|
||||
/* $NetBSD: aupscreg.h,v 1.3 2006/10/02 07:32:16 gdamore Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2006 Shigeyuki Fukushima.
|
||||
|
@ -78,6 +78,19 @@
|
|||
|
||||
/* 0x0008 - 0x002F: Protocol-specific registers */
|
||||
|
||||
/* psc_stat: PSC status
|
||||
* DI [1]
|
||||
* 1 = Device interrupt
|
||||
* DR [1]
|
||||
* 1 = Device ready
|
||||
* SR [0]
|
||||
* 1 = PSC ready
|
||||
* all other bits a are protocol specific
|
||||
*/
|
||||
#define AUPSC_STAT 0x14
|
||||
# define AUPSC_STAT_SR 1
|
||||
# define AUPSC_STAT_DR 2
|
||||
# define AUPSC_STAT_DI 4
|
||||
/* PSC registers size */
|
||||
#define AUPSC_SIZE 0x2f
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: aupscvar.h,v 1.2 2006/03/06 17:15:03 shige Exp $ */
|
||||
/* $NetBSD: aupscvar.h,v 1.3 2006/10/02 07:32:16 gdamore Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2006 Shigeyuki Fukushima.
|
||||
|
@ -47,6 +47,8 @@ struct aupsc_controller {
|
|||
struct aupsc_attach_args {
|
||||
const char * aupsc_name;
|
||||
struct aupsc_controller aupsc_ctrl;
|
||||
bus_addr_t aupsc_addr; /* Bus address */
|
||||
int aupsc_irq;
|
||||
};
|
||||
|
||||
struct aupsc_protocol_device {
|
||||
|
|
Loading…
Reference in New Issue