Subject: kern/36652: cbb0: Bad Vcc status once set will not clear -ThinkPad 570 / PCI1450
To: None <kern-bug-people@netbsd.org, gnats-admin@netbsd.org,>
From: None <djb_netbsd@charter.net>
List: netbsd-bugs
Date: 07/15/2007 20:40:00
>Number: 36652
>Category: kern
>Synopsis: cbb0: Bad Vcc status once set will not clear -ThinkPad 570 / PCI1450
>Confidential: no
>Severity: serious
>Priority: medium
>Responsible: kern-bug-people
>State: open
>Class: sw-bug
>Submitter-Id: net
>Arrival-Date: Sun Jul 15 20:40:00 +0000 2007
>Originator: Dave Barnes
>Release: 4.99.19
>Organization:
>Environment:
ThinkPad 570
>Description:
Once bad Vcc bit gets set, removing and reinserting card doesn't clear bad Vcc.
during boot:
cbb0: bad Vcc request. sock_ctrl 0x0, sock_status 0x30000b20
cbb0: disabling socket
new status 0x30000b20
card removal and re-insert:
/netbsd: cbb0: bad Vcc request. sock_ctrl 0x0, sock_status 0x30000326
/netbsd: cbb0: disabling socket
/netbsd: new status 0x30000326
/netbsd: cbb0: bad Vcc request. sock_ctrl 0x30, sock_status 0x30000b68
/netbsd: cbb0: disabling socket
/netbsd: new status 0x30000b68
/netbsd: cbb0: bad Vcc request. sock_ctrl 0x0, sock_status 0x30000386
/netbsd: cbb0: disabling socket
/netbsd: new status 0x30000386
/netbsd: cbb0: bad Vcc request. sock_ctrl 0x30, sock_status 0x30000b68
/netbsd: cbb0: disabling socket
/netbsd: new status 0x30000b68
/netbsd: cbb0: bad Vcc request. sock_ctrl 0x0, sock_status 0x30000386
/netbsd: cbb0: disabling socket
/netbsd: new status 0x30000386
>How-To-Repeat:
For whatever reason, if you cold boot a ThinkPad 570 with a cardbus card in either slot you get bad Vcc set for the slot.
cbb0: bad Vcc request. sock_ctrl 0x0, sock_status 0x30000b20
cbb0: disabling socket
new status 0x30000b20
>Fix:
sys/dev/pci/pccbb.c starting with line 1363:
if (status & CB_SOCKET_STAT_BADVCC) { /* bad Vcc request */
printf("%s: bad Vcc request. sock_ctrl 0x%x, sock_status 0x%x\n",
sc->sc_dev.dv_xname, sock_ctrl, status);
printf("%s: disabling socket\n", sc->sc_dev.dv_xname);
sock_ctrl &= ~CB_SOCKET_CTRL_VCCMASK;
sock_ctrl &= ~CB_SOCKET_CTRL_VPPMASK;
bus_space_write_4(memt, memh, CB_SOCKET_CTRL, sock_ctrl);
status &= ~CB_SOCKET_STAT_BADVCC;
bus_space_write_4(memt, memh, CB_SOCKET_STAT, status);
printf("new status 0x%x\n", bus_space_read_4(memt, memh,
CB_SOCKET_STAT));
return 0;
}
"bus_space_write_4(memt, memh, CB_SOCKET_STAT, status);" does nothing since, at least on the PCI1450, CB_SOCKET_STAT is read only.
Correct register to use here is CB_SOCKET_FORCE.
A kernel with this one change shows:
boot:
pccbb_power: CARDBUS_VCC_3V and CARDBUS_VPP_UC [0x1]
cbb0: power on failed?
cbb0: bad Vcc request. sock_ctrl 0x30, sock_status 0x30000b20
cbb0: disabling socket
new status 0x30000920
...
card removed and reinserted:
cbb0: 0x00000006 card removed, 0x30000926
pccbb_power: CARDBUS_VCC_0V and CARDBUS_VPP_0V [0x44]
cbb0: 0x00000000 card inserted, 0x30000920
pccbb_power: CARDBUS_VCC_3V and CARDBUS_VPP_UC [0x1]
Powercycling because of socket event
rtw0 at cardbus0 function 0: Realtek RTL8180 802.11 MAC/BBP
...
... card now works normally.
probably need to clear "data_lost" bit too:
#define CB_SOCKET_STAT_DATALOST 0x0100 /* data lost */
May need to set bit 14 also to force re-interrogation of the card, update status registers and re-enable socket power control. See TI PCI1450 programming manual, page 111.
I don't know whether this fix applies to cardbus chips other than the PCI1450.