Next step on the road to pci: power taming.

Work through the various power commands and convert them from a "is
this a foo controller or a foo' controller or a foo''' controller" to
a cabability based scheme.  We have bits in the softc that tell us
what kind of power control scheme the controller uses, rather than
relying on being able to enumerate them all.  Cardbus bridges are
numerous, but nearly all implement the i82365sl-DF scheme (well, a few
implement cirrus CL-PD67xx, but those were made by Cirrus Logic!).

Add a pointer back to the softc in each pcic_slot so we can access
these flags.

Add comments that talk about the issues here.  Also note in passing
that there are two differ Vpp schemes in use and that we may need to
adjust the code to deal with both of them.  Note why it usually works
now.

We have 5 power management modes right now: KING, AB, DF, PD and VG.
AB is for the i82365 stpes A, B and C.  DF is for step DF.  PD is the
cirrus logic extensions for 3.3V while VG is the VADEM extensions for
3.3V.  KING is for the IBM KING controller found on some old cards.
# I'm looking for one of those old cards or a laptop that has the KING
# bridge in it.

We have to still cheat and treat the AB parts like the DF parts
because pci isn't here yet.  As far as I can tell, this is harmless
for actual old parts and necessary to work with 3.3V cards in some
laptops.

This almost eliminates all tests for controller in the code.  There
are still a few unrelated to power that need taming as well.
This commit is contained in:
Warner Losh 2001-05-21 04:44:14 +00:00
parent e67316366d
commit 57462c010c
4 changed files with 109 additions and 85 deletions

View File

@ -122,6 +122,7 @@
#define PCIC_PCPWRE 0x10 /* PC Card Power Enable */
#define PCIC_VCC 0x18 /* Vcc control bits */
#define PCIC_VCC_5V 0x10 /* 5 volts */
#define PCIC_VCC_ON 0x10 /* Turn on VCC on some chips. */
#define PCIC_VCC_3V 0x18 /* 3 volts */
#define PCIC_VCC_5V_KING 0x14 /* 5 volts for KING PCIC */
#define PCIC_VPP 0x03 /* Vpp control bits */

View File

@ -292,6 +292,7 @@ pcic_attach(device_t dev)
sc->slotmask |= (1 << i);
slt->cdata = sp;
sp->slt = slt;
sp->sc = sc;
}
if (sc->flags & PCIC_IO_MAPPED) {
@ -365,7 +366,7 @@ pcic_attach(device_t dev)
do_mgt_irq(sp, irq);
/* Check for changes */
pcic_setb(sp, PCIC_POWER, PCIC_PCPWRE| PCIC_DISRST);
pcic_setb(sp, PCIC_POWER, PCIC_PCPWRE | PCIC_DISRST);
stat = sp->getb(sp, PCIC_STATUS);
if (bootverbose)
printf("stat is %x\n", stat);
@ -415,85 +416,97 @@ static int
pcic_power(struct slot *slt)
{
unsigned char c;
unsigned char reg = PCIC_DISRST|PCIC_PCPWRE;
unsigned char reg = PCIC_DISRST | PCIC_PCPWRE;
struct pcic_slot *sp = slt->cdata;
struct pcic_softc *sc = sp->sc;
switch(sp->controller) {
case PCIC_I82365SL_DF:
if (sc->flags & (PCIC_DF_POWER | PCIC_AB_POWER)) {
/*
* Look at the VS[12]# bits on the card. If VS1 is clear
* then we should apply 3.3 volts. Maybe we should do this
* with other cards too. Cirrus logic cards (PD67[12]*) do
* things like this in a different way.
* then we should apply 3.3 volts.
*/
c = sp->getb(sp, PCIC_CDGC);
if ((c & PCIC_VS1STAT) == 0)
slt->pwr.vcc = 33;
/* FALL THROUGH */
case PCIC_I82365:
case PCIC_PD672X:
case PCIC_PD6710:
case PCIC_VG365:
case PCIC_VG465:
case PCIC_VG468:
case PCIC_VG469:
case PCIC_RF5C396:
case PCIC_IBM_KING:
switch(slt->pwr.vpp) {
default:
return (EINVAL);
case 0:
break;
case 50:
case 33:
reg |= PCIC_VPP_5V;
break;
case 120:
reg |= PCIC_VPP_12V;
}
/*
* XXX Note: The Vpp controls varies quit a bit between bridge chips
* and the following might not be right in all cases. The Linux
* code and wildboar code bases are more complex. However, most
* applications want vpp == vcc and the following code does appear
* to do that for all bridge sets.
*/
switch(slt->pwr.vpp) {
default:
return (EINVAL);
case 0:
break;
case 50:
case 33:
reg |= PCIC_VPP_5V;
break;
case 120:
reg |= PCIC_VPP_12V;
break;
}
switch(slt->pwr.vcc) {
default:
return (EINVAL);
case 0:
break;
case 33:
reg |= PCIC_VCC_ON;
/*
* The wildboar code has comments that state that
* the IBM KING controller doesn't support 3.3V
* on the "IBM Smart PC card drive". The code
* intemates that's the only place they have seen
* it used and that there's a boatload of issues
* with it. I'm not even sure this is right because
* the only docs I've been able to find say this is for
* 5V power. Of course, this "doc" is just code comments
* so who knows for sure.
*/
if (sc->flags & PCIC_KING_POWER) {
reg |= PCIC_VCC_5V_KING;
break;
}
switch(slt->pwr.vcc) {
default:
return (EINVAL);
case 0:
if (sc->flags & PCIC_VG_POWER) {
pcic_setb(sp, PCIC_CVSR, PCIC_CVSR_VS);
break;
case 33:
/*
* The wildboar code has comments that state that
* the IBM KING controller doesn't support 3.3V
* on the "IBM Smart PC card drive". The code
* intemates that's the only place they have seen
* it used and that there's a boatload of issues
* with it.
*/
if (sp->controller == PCIC_IBM_KING) {
reg |= PCIC_VCC_5V_KING;
break;
}
}
if (sc->flags & PCIC_PD_POWER) {
pcic_setb(sp, PCIC_MISC1, PCIC_MISC1_VCC_33);
break;
}
/*
* Technically, The A, B, C stepping didn't support the 3.3V
* cards. However, many cardbus bridges are identified
* as AB cards by our probe routine, so we do both. It
* won't hurt the A, B, C bridges that don't support this
* bit since it is one of the reserved bits.
*/
if (sc->flags & (PCIC_AB_POWER | PCIC_DF_POWER))
reg |= PCIC_VCC_3V;
if ((sp->controller == PCIC_VG468) ||
(sp->controller == PCIC_VG469) ||
(sp->controller == PCIC_VG465) ||
(sp->controller == PCIC_VG365))
pcic_setb(sp, PCIC_CVSR, PCIC_CVSR_VS);
else
pcic_setb(sp, PCIC_MISC1, PCIC_MISC1_VCC_33);
break;
case 50:
if (sp->controller == PCIC_IBM_KING) {
reg |= PCIC_VCC_5V_KING;
break;
}
reg |= PCIC_VCC_5V;
if ((sp->controller == PCIC_VG468) ||
(sp->controller == PCIC_VG469) ||
(sp->controller == PCIC_VG465) ||
(sp->controller == PCIC_VG365))
pcic_clrb(sp, PCIC_CVSR, PCIC_CVSR_VS);
else
pcic_clrb(sp, PCIC_MISC1, PCIC_MISC1_VCC_33);
break;
}
break;
case 50:
if (sc->flags & PCIC_KING_POWER)
reg |= PCIC_VCC_5V_KING;
/*
* For either of the two variant power schemes for 3.3V
* go ahead and turn off the 3.3V magic. Then set the
* 5V bits in all cases. This works because bit 4 is
* set in PCIC_VCC_5V and in the altenrate PCIC_VCC_ON
* is what non-82365 datasheets would lead one to believe
* the bits are for.
*/
if (sc->flags & PCIC_VG_POWER)
pcic_clrb(sp, PCIC_CVSR, PCIC_CVSR_VS);
else if (sc->flags & PCIC_PD_POWER)
pcic_clrb(sp, PCIC_MISC1, PCIC_MISC1_VCC_33);
reg |= PCIC_VCC_5V;
break;
}
sp->putb(sp, PCIC_POWER, reg);
@ -503,6 +516,7 @@ pcic_power(struct slot *slt)
sp->putb(sp, PCIC_POWER, reg);
DELAY(100*1000);
}
/*
* Some chips are smarter than us it seems, so if we weren't
* allowed to use 5V, try 3.3 instead

View File

@ -53,20 +53,22 @@ static struct isa_pnp_id pcic_ids[] = {
{0}
};
static char *bridges[] =
{
"Intel i82365SL-A/B",
"IBM PCIC",
"VLSI 82C146",
"Cirrus logic 672x",
"Cirrus logic 6710",
"Vadem 365",
"Vadem 465",
"Vadem 468",
"Vadem 469",
"Ricoh RF5C396",
"IBM KING PCMCIA Controller",
"Intel i82365SL-DF"
static struct {
const char *name;
u_int32_t flags;
} bridges[] = {
{ "Intel i82365SL-A/B", PCIC_AB_POWER},
{ "IBM PCIC", PCIC_AB_POWER},
{ "VLSI 82C146", PCIC_AB_POWER},
{ "Cirrus logic 672x", PCIC_PD_POWER},
{ "Cirrus logic 6710", PCIC_PD_POWER},
{ "Vadem 365", PCIC_VG_POWER},
{ "Vadem 465", PCIC_VG_POWER},
{ "Vadem 468", PCIC_VG_POWER},
{ "Vadem 469", PCIC_VG_POWER},
{ "Ricoh RF5C396", PCIC_AB_POWER},
{ "IBM KING", PCIC_KING_POWER},
{ "Intel i82365SL-DF", PCIC_DF_POWER}
};
/*
@ -256,7 +258,8 @@ pcic_isa_probe(device_t dev)
sp->revision = 8 - ((c & 0x1F) >> 2);
}
}
device_set_desc(dev, bridges[(int) sp->controller]);
device_set_desc(dev, bridges[(int) sp->controller].name);
sc->flags = bridges[(int) sp->controller].flags;
/*
* OK it seems we have a PCIC or lookalike.
* Allocate a slot and initialise the data structures.

View File

@ -34,6 +34,7 @@ struct pcic_slot {
char controller; /* Device type */
char revision; /* Device Revision */
struct slot *slt; /* Back ptr to slot */
struct pcic_softc *sc; /* Back pointer to softc */
u_char (*getb)(struct pcic_slot *, int);
void (*putb)(struct pcic_slot *, int, u_char);
u_char *regs; /* Pointer to regs in mem */
@ -43,8 +44,13 @@ struct pcic_softc
{
u_int32_t slotmask; /* Mask of valid slots */
u_int32_t flags; /* Interesting flags */
#define PCIC_IO_MAPPED 0x00000001
#define PCIC_MEM_MAPPED 0x00000002
#define PCIC_IO_MAPPED 0x00000001 /* ExCA registers are io mapped */
#define PCIC_MEM_MAPPED 0x00000002 /* ExCA registers mem mapped */
#define PCIC_VG_POWER 0x00000004 /* Uses VG power regs */
#define PCIC_DF_POWER 0x00000008 /* Uses DF step regs */
#define PCIC_PD_POWER 0x00000010 /* Uses CL-PD regs */
#define PCIC_KING_POWER 0x00000020 /* Uses IBM KING regs */
#define PCIC_AB_POWER 0x00000040 /* Use old A/B step power */
int iorid; /* Rid of I/O region */
struct resource *iores; /* resource for I/O region */
int memrid;