Subject: kern/6172: Additions/corrections to PCIC code to better handle CL-67XX
To: None <gnats-bugs@gnats.netbsd.org>
From: Johnny C. Lam <lamj@stat.cmu.edu>
List: netbsd-bugs
Date: 09/17/1998 15:43:30
>Number: 6172
>Category: kern
>Synopsis: Additions/corrections to PCIC code to better handle CL-67XX
>Confidential: no
>Severity: non-critical
>Priority: medium
>Responsible: kern-bug-people (Kernel Bug People)
>State: open
>Class: sw-bug
>Submitter-Id: net
>Arrival-Date: Thu Sep 17 12:50:00 1998
>Last-Modified:
>Originator: Johnny C. Lam
>Organization:
Carnegie Mellon University
>Release: 1.3G
>Environment:
NetBSD 1.3G (MARIPOSA) #14: Mon Aug 24 07:25:44 EST 1998
kroot@mariposa:/usr/src/sys/arch/i386/compile/MARIPOSA
>Description:
The CL-67XX PCIC's have extra registers that extend the I82365
register set. Below are patches to four files:
1) sys/dev/ic/i82365.c: More descriptive/correct settings of
registers, and additions to better handle the CL-67XX
PCIC's.
2) sys/dev/ic/i82365reg.h: Corrections to register values and
additional registers for CL-67XX.
3) sys/dev/isa/i82365_isasubr.c: More descriptive/correct setting
of registers.
4) sys/dev/pci/pcidevs: Correct product name of CL-PD6729
>How-To-Repeat:
>Fix:
*** src/sys/dev/ic/i82365.c.orig Thu Sep 17 02:32:22 1998
--- src/sys/dev/ic/i82365.c Thu Sep 17 02:32:43 1998
***************
*** 53,59 ****
#ifdef PCICDEBUG
int pcic_debug = 0;
! #define DPRINTF(arg) if (pcic_debug) printf arg;
#else
#define DPRINTF(arg)
#endif
--- 53,59 ----
#ifdef PCICDEBUG
int pcic_debug = 0;
! #define DPRINTF(arg) if (pcic_debug) printf arg
#else
#define DPRINTF(arg)
#endif
***************
*** 63,68 ****
--- 63,69 ----
#define PCIC_VENDOR_I82365SLR1 2
#define PCIC_VENDOR_CIRRUS_PD6710 3
#define PCIC_VENDOR_CIRRUS_PD672X 4
+ #define PCIC_VENDOR_CIRRUS_PD6729 5
/*
* Individual drivers will allocate their own memory and io regions. Memory
***************
*** 123,142 ****
PCIC_CIRRUS_CHIP_INFO_CHIP_ID) {
reg = pcic_read(h, -1);
if ((reg & PCIC_CIRRUS_CHIP_INFO_CHIP_ID) == 0) {
! if (reg & PCIC_CIRRUS_CHIP_INFO_SLOTS)
! return (PCIC_VENDOR_CIRRUS_PD672X);
! else
return (PCIC_VENDOR_CIRRUS_PD6710);
}
}
- /* XXX how do I identify the GD6729? */
reg = pcic_read(h, PCIC_IDENT);
! if ((reg & PCIC_IDENT_REV_MASK) == PCIC_IDENT_REV_I82365SLR0)
return (PCIC_VENDOR_I82365SLR0);
! else
return (PCIC_VENDOR_I82365SLR1);
return (PCIC_VENDOR_UNKNOWN);
}
--- 124,154 ----
PCIC_CIRRUS_CHIP_INFO_CHIP_ID) {
reg = pcic_read(h, -1);
if ((reg & PCIC_CIRRUS_CHIP_INFO_CHIP_ID) == 0) {
! switch (reg & PCIC_CIRRUS_CHIP_INFO_SLOTS_MASK) {
! case PCIC_CIRRUS_CHIP_INFO_SLOTS_SINGLE:
return (PCIC_VENDOR_CIRRUS_PD6710);
+ case PCIC_CIRRUS_CHIP_INFO_SLOTS_DUAL:
+ pcic_write(h, PCIC_CIRRUS_EXT_INDEX,
+ PCIC_CIRRUS_PROD_ID);
+ reg = pcic_read(h, PCIC_CIRRUS_EXT_DATA);
+ switch (reg & PCIC_CIRRUS_PROD_ID_FAM_MASK) {
+ case PCIC_CIRRUS_PROD_ID_FAM_PD6729:
+ return (PCIC_VENDOR_CIRRUS_PD6729);
+ default:
+ return (PCIC_VENDOR_CIRRUS_PD672X);
+ }
+ }
}
}
reg = pcic_read(h, PCIC_IDENT);
! switch (reg & PCIC_IDENT_REV_MASK) {
! case PCIC_IDENT_REV_I82365SLR0:
return (PCIC_VENDOR_I82365SLR0);
! case PCIC_IDENT_REV_I82365SLR1:
return (PCIC_VENDOR_I82365SLR1);
+ }
return (PCIC_VENDOR_UNKNOWN);
}
***************
*** 154,159 ****
--- 166,173 ----
return ("Cirrus PD6710");
case PCIC_VENDOR_CIRRUS_PD672X:
return ("Cirrus PD672X");
+ case PCIC_VENDOR_CIRRUS_PD6729:
+ return ("Cirrus PD6729");
}
return ("Unknown controller");
***************
*** 163,169 ****
pcic_attach(sc)
struct pcic_softc *sc;
{
! int vendor, count, i, reg;
/* now check for each controller/socket */
--- 177,183 ----
pcic_attach(sc)
struct pcic_softc *sc;
{
! int vendor, count, i, reg, one_ctrl;
/* now check for each controller/socket */
***************
*** 198,206 ****
DPRINTF((" 0x%02x", reg));
sc->handle[2].sc = sc;
sc->handle[2].sock = C1SA;
! if (pcic_ident_ok(reg = pcic_read(&sc->handle[2], PCIC_IDENT))) {
sc->handle[2].flags = PCIC_FLAG_SOCKETP;
count++;
} else {
--- 212,233 ----
DPRINTF((" 0x%02x", reg));
+ /*
+ * CL-PD6729 has only one controller. Trying to
+ * read from the second one is undefined, so don't.
+ */
+ one_ctrl = 0;
+ if (sc->handle[0].flags & PCIC_FLAG_SOCKETP)
+ switch (pcic_vendor(&sc->handle[0])) {
+ case PCIC_VENDOR_CIRRUS_PD6729:
+ one_ctrl = 1;
+ break;
+ }
+
sc->handle[2].sc = sc;
sc->handle[2].sock = C1SA;
! if (pcic_ident_ok(reg = pcic_read(&sc->handle[2], PCIC_IDENT)) &&
! one_ctrl == 0) {
sc->handle[2].flags = PCIC_FLAG_SOCKETP;
count++;
} else {
***************
*** 211,217 ****
sc->handle[3].sc = sc;
sc->handle[3].sock = C1SB;
! if (pcic_ident_ok(reg = pcic_read(&sc->handle[3], PCIC_IDENT))) {
sc->handle[3].flags = PCIC_FLAG_SOCKETP;
count++;
} else {
--- 238,245 ----
sc->handle[3].sc = sc;
sc->handle[3].sock = C1SB;
! if (pcic_ident_ok(reg = pcic_read(&sc->handle[3], PCIC_IDENT)) &&
! one_ctrl == 0) {
sc->handle[3].flags = PCIC_FLAG_SOCKETP;
count++;
} else {
***************
*** 330,344 ****
/* set up the card to interrupt on card detect */
! pcic_write(h, PCIC_CSC_INTR, (h->sc->irq << PCIC_CSC_INTR_IRQ_SHIFT) |
! PCIC_CSC_INTR_CD_ENABLE);
pcic_write(h, PCIC_INTR, 0);
pcic_read(h, PCIC_CSC);
/* unsleep the cirrus controller */
! if ((h->vendor == PCIC_VENDOR_CIRRUS_PD6710) ||
! (h->vendor == PCIC_VENDOR_CIRRUS_PD672X)) {
reg = pcic_read(h, PCIC_CIRRUS_MISC_CTL_2);
if (reg & PCIC_CIRRUS_MISC_CTL_2_SUSPEND) {
DPRINTF(("%s: socket %02x was suspended\n",
--- 358,375 ----
/* set up the card to interrupt on card detect */
! reg = (h->sc->irq << PCIC_CSC_INTR_IRQ_SHIFT) & PCIC_CSC_INTR_IRQ_MASK;
! reg |= PCIC_CSC_INTR_CD_ENABLE;
! pcic_write(h, PCIC_CSC_INTR, reg);
pcic_write(h, PCIC_INTR, 0);
pcic_read(h, PCIC_CSC);
/* unsleep the cirrus controller */
! switch (h->vendor) {
! case PCIC_VENDOR_CIRRUS_PD6710:
! case PCIC_VENDOR_CIRRUS_PD672X:
! case PCIC_VENDOR_CIRRUS_PD6729:
reg = pcic_read(h, PCIC_CIRRUS_MISC_CTL_2);
if (reg & PCIC_CIRRUS_MISC_CTL_2_SUSPEND) {
DPRINTF(("%s: socket %02x was suspended\n",
***************
*** 346,352 ****
--- 377,411 ----
reg &= ~PCIC_CIRRUS_MISC_CTL_2_SUSPEND;
pcic_write(h, PCIC_CIRRUS_MISC_CTL_2, reg);
}
+ break;
}
+
+ /* Set up Low Power Dynamic Mode for the CL-PD67XX */
+
+ switch (h->vendor) {
+ case PCIC_VENDOR_CIRRUS_PD6710:
+ case PCIC_VENDOR_CIRRUS_PD672X:
+ case PCIC_VENDOR_CIRRUS_PD6729:
+ reg = pcic_read(h, PCIC_CIRRUS_MISC_CTL_2);
+ reg |= PCIC_CIRRUS_MISC_CTL_2_LP_DYNAMIC_MODE;
+ pcic_write(h, PCIC_CIRRUS_MISC_CTL_2, reg);
+ DPRINTF(("%s: low power dynamic mode enabled on socket %02x\n",
+ h->sc->dev.dv_xname, h->sock));
+ }
+
+ /* Enable the speaker for modem PC cards. */
+
+ switch (h->vendor) {
+ case PCIC_VENDOR_CIRRUS_PD6710:
+ case PCIC_VENDOR_CIRRUS_PD672X:
+ case PCIC_VENDOR_CIRRUS_PD6729:
+ reg = pcic_read(h, PCIC_CIRRUS_MISC_CTL_1);
+ reg |= PCIC_CIRRUS_MISC_CTL_1_SPKR_ENABLE;
+ pcic_write(h, PCIC_CIRRUS_MISC_CTL_1, reg);
+ DPRINTF(("%s: speaker enabled on socket %02x\n",
+ h->sc->dev.dv_xname, h->sock));
+ }
+
/* if there's a card there, then attach it. */
reg = pcic_read(h, PCIC_IF_STATUS);
***************
*** 537,543 ****
h->flags &= ~PCIC_FLAG_CARDP;
! /* call the MI attach function */
pcmcia_card_detach(h->pcmcia);
--- 596,602 ----
h->flags &= ~PCIC_FLAG_CARDP;
! /* call the MI detach function */
pcmcia_card_detach(h->pcmcia);
***************
*** 1099,1109 ****
cardtype = pcmcia_card_gettype(h->pcmcia);
reg = pcic_read(h, PCIC_INTR);
! reg &= ~PCIC_INTR_CARDTYPE_MASK;
reg |= ((cardtype == PCMCIA_IFTYPE_IO) ?
PCIC_INTR_CARDTYPE_IO :
PCIC_INTR_CARDTYPE_MEM);
! reg |= h->ih_irq;
pcic_write(h, PCIC_INTR, reg);
DPRINTF(("%s: pcic_chip_socket_enable %02x cardtype %s %02x\n",
--- 1158,1168 ----
cardtype = pcmcia_card_gettype(h->pcmcia);
reg = pcic_read(h, PCIC_INTR);
! reg &= ~(PCIC_INTR_CARDTYPE_MASK | PCIC_INTR_IRQ_MASK);
reg |= ((cardtype == PCMCIA_IFTYPE_IO) ?
PCIC_INTR_CARDTYPE_IO :
PCIC_INTR_CARDTYPE_MEM);
! reg |= (h->ih_irq << PCIC_INTR_IRQ_SHIFT) & PCIC_INTR_IRQ_MASK;
pcic_write(h, PCIC_INTR, reg);
DPRINTF(("%s: pcic_chip_socket_enable %02x cardtype %s %02x\n",
***************
*** 1128,1133 ****
--- 1187,1203 ----
struct pcic_handle *h = (struct pcic_handle *) pch;
DPRINTF(("pcic_chip_socket_disable\n"));
+
+ /* flush write FIFO on CL-PD67XX */
+
+ switch (h->vendor) {
+ case PCIC_VENDOR_CIRRUS_PD6710:
+ case PCIC_VENDOR_CIRRUS_PD672X:
+ case PCIC_VENDOR_CIRRUS_PD6729:
+ pcic_write(h, PCIC_CIRRUS_FIFO_CTL,
+ PCIC_CIRRUS_FIFO_CTL_FLUSH);
+ break;
+ }
/* power down the socket */
*** src/sys/dev/ic/i82365reg.h.orig Thu Sep 17 02:32:22 1998
--- src/sys/dev/ic/i82365reg.h Thu Sep 17 02:32:43 1998
***************
*** 32,38 ****
/*
* All information is from the intel 82365sl PC Card Interface Controller
* (PCIC) data sheet, marked "preliminary". Order number 290423-002, January
! * 1993.
*/
#define PCIC_IOSIZE 2
--- 32,39 ----
/*
* All information is from the intel 82365sl PC Card Interface Controller
* (PCIC) data sheet, marked "preliminary". Order number 290423-002, January
! * 1993. Added information from the Cirrus Logic CL-PD6729 PCI-to-PCMCIA
! * Host Adapter data sheet, marked "preliminary", version 2.0, January 1997.
*/
#define PCIC_IOSIZE 2
***************
*** 76,83 ****
#define PCIC_IF_STATUS_CARDDETECT_PRESENT 0x0C
#define PCIC_IF_STATUS_BATTERY_MASK 0x03
#define PCIC_IF_STATUS_BATTERY_DEAD1 0x00
! #define PCIC_IF_STATUS_BATTERY_DEAD2 0x01
! #define PCIC_IF_STATUS_BATTERY_WARNING 0x02
#define PCIC_IF_STATUS_BATTERY_GOOD 0x03
#define PCIC_PWRCTL 0x02 /* RW */
--- 77,84 ----
#define PCIC_IF_STATUS_CARDDETECT_PRESENT 0x0C
#define PCIC_IF_STATUS_BATTERY_MASK 0x03
#define PCIC_IF_STATUS_BATTERY_DEAD1 0x00
! #define PCIC_IF_STATUS_BATTERY_WARNING 0x01
! #define PCIC_IF_STATUS_BATTERY_DEAD2 0x02
#define PCIC_IF_STATUS_BATTERY_GOOD 0x03
#define PCIC_PWRCTL 0x02 /* RW */
***************
*** 98,104 ****
#define PCIC_PWRCTL_VPP1_EN0 0x01
#define PCIC_PWRCTL_VPP1_ENX 0x00
! #define PCIC_CSC 0x04 /* RW */
#define PCIC_CSC_ZERO 0xE0
#define PCIC_CSC_GPI 0x10
#define PCIC_CSC_CD 0x08 /* Card Detect Change */
--- 99,105 ----
#define PCIC_PWRCTL_VPP1_EN0 0x01
#define PCIC_PWRCTL_VPP1_ENX 0x00
! #define PCIC_CSC 0x04 /* RO */
#define PCIC_CSC_ZERO 0xE0
#define PCIC_CSC_GPI 0x10
#define PCIC_CSC_CD 0x08 /* Card Detect Change */
***************
*** 323,332 ****
#define PCIC_INTEL_GLOBAL_CTL_IRQLEVEL_ENABLE 0x02
#define PCIC_INTEL_GLOBAL_CTL_POWERDOWN 0x01
! #define PCIC_CIRRUS_MISC_CTL_2 0x1E
#define PCIC_CIRRUS_MISC_CTL_2_SUSPEND 0x04
! #define PCIC_CIRRUS_CHIP_INFO 0x1F
#define PCIC_CIRRUS_CHIP_INFO_CHIP_ID 0xC0
! #define PCIC_CIRRUS_CHIP_INFO_SLOTS 0x20
#define PCIC_CIRRUS_CHIP_INFO_REV 0x1F
--- 324,352 ----
#define PCIC_INTEL_GLOBAL_CTL_IRQLEVEL_ENABLE 0x02
#define PCIC_INTEL_GLOBAL_CTL_POWERDOWN 0x01
! #define PCIC_CIRRUS_MISC_CTL_1 0x16 /* RW */
! #define PCIC_CIRRUS_MISC_CTL_1_SPKR_ENABLE 0x10
!
! #define PCIC_CIRRUS_FIFO_CTL 0x17 /* RW */
! #define PCIC_CIRRUS_FIFO_CTL_EMPTY 0x80 /* I/O read */
! #define PCIC_CIRRUS_FIFO_CTL_FLUSH 0x80 /* I/O write */
!
! #define PCIC_CIRRUS_MISC_CTL_2 0x1E /* RW */
#define PCIC_CIRRUS_MISC_CTL_2_SUSPEND 0x04
+ #define PCIC_CIRRUS_MISC_CTL_2_LP_DYNAMIC_MODE 0x02
! #define PCIC_CIRRUS_CHIP_INFO 0x1F /* RO */
#define PCIC_CIRRUS_CHIP_INFO_CHIP_ID 0xC0
! #define PCIC_CIRRUS_CHIP_INFO_SLOTS_MASK 0x20
! #define PCIC_CIRRUS_CHIP_INFO_SLOTS_DUAL 0x20
! #define PCIC_CIRRUS_CHIP_INFO_SLOTS_SINGLE 0x00
#define PCIC_CIRRUS_CHIP_INFO_REV 0x1F
+
+ #define PCIC_CIRRUS_EXT_INDEX 0x2E
+ #define PCIC_CIRRUS_EXT_DATA 0x2F
+
+ #define PCIC_CIRRUS_PROD_ID 0x35 /* RO */
+ #define PCIC_CIRRUS_PROD_ID_FAM_MASK 0xF0
+ #define PCIC_CIRRUS_PROD_ID_FAM_PD6729 0x20
+ #define PCIC_CIRRUS_PROD_ID_PROD_MASK 0x0F
+ #define PCIC_CIRRUS_PROD_ID_PROD_PD6729 0x00
*** src/sys/dev/isa/i82365_isasubr.c.orig Thu Sep 17 02:32:23 1998
--- src/sys/dev/isa/i82365_isasubr.c Thu Sep 17 02:32:43 1998
***************
*** 238,244 ****
reg = pcic_read(h, PCIC_INTR);
reg &= ~PCIC_INTR_IRQ_MASK;
! reg |= irq;
pcic_write(h, PCIC_INTR, reg);
h->ih_irq = irq;
--- 238,245 ----
reg = pcic_read(h, PCIC_INTR);
reg &= ~PCIC_INTR_IRQ_MASK;
! reg |= (irq << PCIC_INTR_IRQ_SHIFT) & PCIC_INTR_IRQ_MASK;
! reg |= PCIC_INTR_ENABLE;
pcic_write(h, PCIC_INTR, reg);
h->ih_irq = irq;
*** src/sys/dev/pci/pcidevs.orig Thu Sep 17 02:32:24 1998
--- src/sys/dev/pci/pcidevs Thu Sep 17 02:32:43 1998
***************
*** 656,662 ****
product CIRRUS CL_GD5434_8 0x00a8 CL-GD5434-8
product CIRRUS CL_GD5436 0x00ac CL-GD5436
product CIRRUS CL_GD5446 0x00b8 CL-GD5446
! product CIRRUS CL_GD6729 0x1100 CL-GD6729
product CIRRUS CL_GD7542 0x1200 CL-GD7542
product CIRRUS CL_GD7543 0x1202 CL-GD7543
product CIRRUS CL_GD7541 0x1204 CL-GD7541
--- 656,662 ----
product CIRRUS CL_GD5434_8 0x00a8 CL-GD5434-8
product CIRRUS CL_GD5436 0x00ac CL-GD5436
product CIRRUS CL_GD5446 0x00b8 CL-GD5446
! product CIRRUS CL_PD6729 0x1100 CL-PD6729
product CIRRUS CL_GD7542 0x1200 CL-GD7542
product CIRRUS CL_GD7543 0x1202 CL-GD7543
product CIRRUS CL_GD7541 0x1204 CL-GD7541
>Audit-Trail:
>Unformatted: