summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sys/pccard/pccard.c2
-rw-r--r--sys/pccard/pcic.c137
2 files changed, 83 insertions, 56 deletions
diff --git a/sys/pccard/pccard.c b/sys/pccard/pccard.c
index 6eeeabe..36556f9 100644
--- a/sys/pccard/pccard.c
+++ b/sys/pccard/pccard.c
@@ -305,7 +305,7 @@ inserted(void *arg)
/*
* Enable 5V to the card so that the CIS can be read.
*/
- slt->pwr.vcc = 50;
+ slt->pwr.vcc = -1;
slt->pwr.vpp = 50;
/*
diff --git a/sys/pccard/pcic.c b/sys/pccard/pcic.c
index b3ad06e..2694025 100644
--- a/sys/pccard/pcic.c
+++ b/sys/pccard/pcic.c
@@ -251,7 +251,7 @@ pcic_io(struct slot *slt, int win)
struct io_desc *ip = &slt->io[win];
if (bootverbose) {
printf("pcic: I/O win %d flags %x %x-%x\n", win, ip->flags,
- ip->start, ip->start+ip->size-1);
+ ip->start, ip->start + ip->size - 1);
}
switch (win) {
@@ -271,7 +271,7 @@ pcic_io(struct slot *slt, int win)
unsigned char x, ioctlv;
pcic_putw(sp, reg, ip->start);
- pcic_putw(sp, reg+2, ip->start+ip->size-1);
+ pcic_putw(sp, reg+2, ip->start + ip->size - 1);
x = 0;
if (ip->flags & IODF_ZEROWS)
x |= PCIC_IO_0WS;
@@ -503,29 +503,31 @@ pcic_ioctl(struct slot *slt, int cmd, caddr_t data)
static int
pcic_cardbus_power(struct pcic_slot *sp, struct slot *slt)
{
- uint32_t reg;
+ uint32_t power;
+ uint32_t state;
/*
* Preserve the clock stop bit of the socket power register.
*/
- reg = bus_space_read_4(sp->bst, sp->bsh, CB_SOCKET_POWER);
- printf("old value 0x%x\n", reg);
- reg &= CB_SP_CLKSTOP;
+ power = bus_space_read_4(sp->bst, sp->bsh, CB_SOCKET_POWER);
+ state = bus_space_read_4(sp->bst, sp->bsh, CB_SOCKET_STATE);
+ printf("old value 0x%x\n", power);
+ power &= ~CB_SP_CLKSTOP;
switch(slt->pwr.vpp) {
default:
return (EINVAL);
case 0:
- reg |= CB_SP_VPP_0V;
+ power |= CB_SP_VPP_0V;
break;
case 33:
- reg |= CB_SP_VPP_3V;
+ power |= CB_SP_VPP_3V;
break;
case 50:
- reg |= CB_SP_VPP_5V;
+ power |= CB_SP_VPP_5V;
break;
case 120:
- reg |= CB_SP_VPP_12V;
+ power |= CB_SP_VPP_12V;
break;
}
@@ -533,17 +535,27 @@ pcic_cardbus_power(struct pcic_slot *sp, struct slot *slt)
default:
return (EINVAL);
case 0:
- reg |= CB_SP_VCC_0V;
+ power |= CB_SP_VCC_0V;
break;
case 33:
- reg |= CB_SP_VCC_3V;
+ power |= CB_SP_VCC_3V;
break;
case 50:
- reg |= CB_SP_VCC_5V;
+ power |= CB_SP_VCC_5V;
+ break;
+ case -1:
+ if (state & CB_SS_5VCARD)
+ power |= CB_SP_VCC_5V;
+ else if (state & CB_SS_3VCARD)
+ power |= CB_SP_VCC_3V;
+ else if (state & CB_SS_XVCARD)
+ power |= CB_SP_VCC_XV;
+ else if (state & CB_SS_YVCARD)
+ power |= CB_SP_VCC_YV;
break;
}
- printf("Setting power reg to 0x%x", reg);
- bus_space_write_4(sp->bst, sp->bsh, CB_SOCKET_POWER, reg);
+ printf("Setting power reg to 0x%x", power);
+ bus_space_write_4(sp->bst, sp->bsh, CB_SOCKET_POWER, power);
return (EIO);
}
@@ -567,53 +579,67 @@ pcic_power(struct slot *slt)
if (sc->flags & PCIC_CARDBUS_POWER)
return (pcic_cardbus_power(sp, slt));
- if (sc->flags & PCIC_DF_POWER) {
- /*
- * Look at the VS[12]# bits on the card. If VS1 is clear
- * then we should apply 3.3 volts.
- */
- c = sp->getb(sp, PCIC_CDGC);
- if ((c & PCIC_VS1STAT) == 0)
- slt->pwr.vcc = 33;
- }
- if (sc->flags & PCIC_PD_POWER) {
- /*
- * The 6710 does it one way, and the '22 and '29 do it
- * another. And it appears that the '32 and '33 yet
- * another way (which I don't know).
- */
- switch (sp->controller) {
- case PCIC_PD6710:
- c = sp->getb(sp, PCIC_MISC1);
- if ((c & PCIC_MISC1_5V_DETECT) == 0)
+ /*
+ * If we're automatically detecting what voltage to use, then we need
+ * to ask the bridge what type (voltage-wise) the card is.
+ */
+ if (slt->pwr.vcc == -1) {
+ if (sc->flags & PCIC_DF_POWER) {
+ /*
+ * Look at the VS[12]# bits on the card. If VS1 is
+ * clear then the card needs 3.3V instead of 5.0V.
+ */
+ c = sp->getb(sp, PCIC_CDGC);
+ if ((c & PCIC_VS1STAT) == 0)
slt->pwr.vcc = 33;
- break;
- case PCIC_PD6722:
- case PCIC_PD6729:
+ else
+ slt->pwr.vcc = 50;
+ }
+ if (sc->flags & PCIC_PD_POWER) {
/*
- * VS[12] signals are in slot1's extended reg 0xa.
+ * The 6710 does it one way, and the '22 and '29 do it
+ * another. And it appears that the '32 and '33 yet
+ * another way (which I don't know).
*/
- sp2 = &sc->slots[1];
- sp2->putb(sp2, PCIC_EXT_IND, PCIC_EXT_DATA);
- c = sp2->getb(sp2, PCIC_EXTENDED);
- if (sp == sp2) { /* slot 1 */
- if ((c & PCIC_VS1B) == 0)
+ switch (sp->controller) {
+ case PCIC_PD6710:
+ c = sp->getb(sp, PCIC_MISC1);
+ if ((c & PCIC_MISC1_5V_DETECT) == 0)
slt->pwr.vcc = 33;
- } else {
+ else
+ slt->pwr.vcc = 50;
+ break;
+ case PCIC_PD6722:
+ case PCIC_PD6729:
+ /*
+ * VS[12] signals are in slot1's
+ * extended reg 0xa for both slots.
+ */
+ sp2 = &sc->slots[1];
+ sp2->putb(sp2, PCIC_EXT_IND, PCIC_EXT_DATA);
+ c = sp2->getb(sp2, PCIC_EXTENDED);
+ if (sp == sp2) /* slot 1 */
+ c >>= 2;
if ((c & PCIC_VS1A) == 0)
slt->pwr.vcc = 33;
+ else
+ slt->pwr.vcc = 50;
+ break;
+ default:
+ /* I have no idea how do do this for others */
+ break;
}
- break;
- default:
- /* I have no idea how do do this for others */
- break;
- }
- /*
- * Regardless of the above, setting the Auto Power Switch
- * enable for the CL-PD 6722 seems to help too.
- */
- reg |= PCIC_APSENA;
+ /*
+ * Regardless of the above, setting the Auto Power
+ * Switch Enable appears to help.
+ */
+ reg |= PCIC_APSENA;
+ }
+ /* Other bridges here */
+ if (bootverbose && slt->pwr.vcc != -1)
+ device_printf(sc->dev, "Autodetected %d.%dV card\n",
+ slt->pwr.vcc / 10, slt->pwr.vcc %10);
}
/*
@@ -675,6 +701,7 @@ pcic_power(struct slot *slt)
if (sc->flags & PCIC_DF_POWER)
reg |= PCIC_VCC_3V;
break;
+ case -1: /* Treat default like 5.0V */
case 50:
if (sc->flags & PCIC_KING_POWER)
reg |= PCIC_VCC_5V_KING;
@@ -709,7 +736,7 @@ pcic_power(struct slot *slt)
* parts of the system. I suspect they are in the pccard bus
* driver, but may be in pccardd as well.
*/
- if (!(sp->getb(sp, PCIC_STATUS) & PCIC_POW) && slt->pwr.vcc == 50) {
+ if (!(sp->getb(sp, PCIC_STATUS) & PCIC_POW) && slt->pwr.vcc == -1) {
slt->pwr.vcc = 33;
slt->pwr.vpp = 0;
return (pcic_power(slt));
OpenPOWER on IntegriCloud