TI cardbus bridges, 12xx and newer, have an interesting register. It

is the diagnostics register at offset 0x93.  When bit 5 is set in this
register, bits 4-7 in ExCA register 0x5 being 0000 are required for
pci interrupt routing.  When it is clear, then bit 4 of ExCA register
0x3 is used to enable it.

The only other issue is that when you route interrupts this way, you
must read ExCA register 0x4 in order to clear the interrupt, else you
get an interrupt storm.

Deal with this requirement by setting things up.  It is believed that
this won't hurt other chipsets, but other chipsets may require their
own work arounds.
This commit is contained in:
Warner Losh 2001-08-01 19:41:56 +00:00
parent 802f355a3f
commit 53af1c8a3d
4 changed files with 58 additions and 10 deletions

View file

@ -138,7 +138,7 @@
#define PCIC_IOCARD 0x20
#define PCIC_MEMCARD 0x00
#define PCIC_CARDRESET 0x40 /* Card reset 0 = Reset, 1 = Normal */
#define PCIC_INTR_ENA 0x10 /* Interrupt enable */
#define PCIC_INTR_ENA 0x10 /* PCI CSC Interrupt enable */
/* For the Card Status Change register (PCIC_STAT_CHG) */
#define PCIC_CDTCH 0x08 /* Card Detect Change */
@ -146,6 +146,14 @@
#define PCIC_BATWRN 0x02 /* Battery Warning */
#define PCIC_BATDED 0x01 /* Battery Dead */
/* For the Card status change interrupt PCIC_STAT_INT */
#define PCIC_CSCSELECT 0xf0 /* CSCSELECT */
#define PCIC_SI_IRQ_SHIFT 4
#define PCIC_CDEN 0x8
#define PCIC_READYEN 0x4
#define PCIC_BATWARNEN 0x2
#define PCIC_BATDEADEN 0x1
/*
* For the Address Window Enable Register (PCIC_ADDRWINE)
* The lower 6 bits contain enable bits for the memory

View file

@ -308,13 +308,34 @@ pcic_do_mgt_irq(struct pcic_slot *sp, int irq)
u_int32_t reg;
if (sp->sc->csc_route == pci_parallel) {
/* Do the PCI side of things: Enable the Card Change int */
reg = CB_SM_CD;
bus_space_write_4(sp->bst, sp->bsh, CB_SOCKET_MASK, reg);
/*
* TI Chips need us to set the following. We tell the
* controller to route things via PCI interrupts. Also
* we clear the interrupt number in the STAT_INT register
* as well. The TI-12xx and newer chips require one or the
* other of these to happen, depending on what is set in the
* diagnostic register. I do both on the theory that other
* chips might need one or the other and that no harm will
* come from it. If there is harm, then I'll make it a bit
* in the tables.
*/
pcic_setb(sp, PCIC_INT_GEN, PCIC_INTR_ENA);
pcic_clrb(sp, PCIC_STAT_INT, PCIC_CSCSELECT);
} else {
/* Management IRQ changes */
/*
* The PCIC_INTR_ENA bit means either "tie the function
* and csc interrupts together" or "Route csc interrupts
* via PCI" or "Reserved". In any case, we want to clear
* it since we're using ISA interrupts.
*/
pcic_clrb(sp, PCIC_INT_GEN, PCIC_INTR_ENA);
irq = host_irq_to_pcic(irq);
sp->putb(sp, PCIC_STAT_INT, (irq << 4) | 0x8);
sp->putb(sp, PCIC_STAT_INT, (irq << PCIC_SI_IRQ_SHIFT) |
PCIC_CDEN);
}
}
@ -629,7 +650,7 @@ pcic_disable(struct slot *slt)
struct pcic_slot *sp = slt->cdata;
sp->putb(sp, PCIC_INT_GEN, 0);
sp->putb(sp, PCIC_POWER, 0);
/* sp->putb(sp, PCIC_POWER, 0); */
}
/*

View file

@ -247,10 +247,10 @@ pcic_pci_pd6832_init(device_t dev)
static void
pcic_pci_ti_init(device_t dev)
{
u_long syscntl,devcntl,cardcntl;
u_int32_t device_id = pci_get_devid(dev);
u_int32_t syscntl, diagctl, devcntl, cardcntl;
u_int32_t device_id = pci_get_devid(dev);
struct pcic_softc *sc = device_get_softc(dev);
int ti113x = (device_id == PCI_DEVICE_ID_PCIC_TI1031) ||
int ti113x = (device_id == PCI_DEVICE_ID_PCIC_TI1031) ||
(device_id == PCI_DEVICE_ID_PCIC_TI1130) ||
(device_id == PCI_DEVICE_ID_PCIC_TI1131);
@ -258,9 +258,12 @@ pcic_pci_ti_init(device_t dev)
devcntl = pci_read_config(dev, TI113X_PCI_DEVICE_CONTROL, 1);
cardcntl = pci_read_config(dev, TI113X_PCI_CARD_CONTROL, 1);
switch(ti113x){
switch (ti113x) {
case 0 :
device_printf(dev, "TI12XX PCI Config Reg: ");
diagctl = pci_read_config(dev, TI12XX_PCI_DIAGNOSTIC, 1);
diagctl |= TI12XX_DIAG_CSC_INTR;
pci_write_config(dev, TI12XX_PCI_DIAGNOSTIC, diagctl, 1);
break;
case 1 :
device_printf(dev, "TI113X PCI Config Reg: ");
@ -305,7 +308,7 @@ pcic_pci_ti_init(device_t dev)
printf("[speaker enable]");
if (syscntl & TI113X_SYSCNTL_PWRSAVINGS)
printf("[pwr save]");
switch (devcntl & TI113X_DEVCNTL_INTR_MASK) {
switch(devcntl & TI113X_DEVCNTL_INTR_MASK){
case TI113X_DEVCNTL_INTR_ISA :
printf("[CSC parallel isa irq]");
break;
@ -436,10 +439,21 @@ pcic_pci_intr(void *arg)
bus_space_write_4(sp->bst, sp->bsh, 0, 0xffffffff);
}
/*
* TI chips also require us to read the old ExCA register for
* card status change when we route CSC via PCI! So, we go ahead
* and read it to clear the bits. Maybe we should check the status
* ala the ISA interrupt handler, but those changes should be caught
* in the CD change.
*/
sp->getb(sp, PCIC_STAT_CHG);
/* Now call children interrupts if any */
stat = bus_space_read_4(sp->bst, sp->bsh, CB_SOCKET_STATE);
if (sp->intr && (stat & CB_SS_CD) == 0)
sp->intr(sp->argp);
if ((stat & CB_SS_CD) == 0) {
if (sp->intr != NULL)
sp->intr(sp->argp);
}
}
/*

View file

@ -46,6 +46,7 @@
#define TI113X_PCI_CARD_CONTROL 0x91 /* Card Control */
#define TI113X_PCI_DEVICE_CONTROL 0x92 /* Device Control */
#define TI113X_PCI_BUFFER_CONTROL 0x93 /* Buffer Control */
#define TI12XX_PCI_DIAGNOSTIC 0x93 /* Diagnostic register */
#define TI113X_PCI_SOCKET_DMA0 0x94 /* Socket DMA Register 0 */
#define TI113X_PCI_SOCKET_DMA1 0x98 /* Socket DMA Register 1 */
@ -80,6 +81,10 @@
#define TI113X_DEVCNTL_INTR_SERIAL 0x04u
/* TI12XX specific code */
#define TI12XX_DEVCNTL_INTR_ALLSERIAL 0x06u
/* Diagnostic register (misnamed) TI12XX_PCI_DIAGNOSTIC == 0x93 */
#define TI12XX_DIAG_CSC_INTR 0x20 /* see datasheet */
/* Texas Instruments PCI-1130/1131 CardBus Controller */
#define TI113X_ExCA_IO_OFFSET0 0x36 /* Offset of I/O window */
#define TI113X_ExCA_IO_OFFSET1 0x38 /* Offset of I/O window */