Resubmitting this with hopefully proper signoff:

This is a patch for a old IBM Thinkpad 760ED notebook.

The pci irq pin of the ti1130 pcmcia bridge is not connected.
To use the cardbus, the irq has to be routed to an isa irq.
This patch detects an valid irq and route cardbus interupts to isa instead of 
pci.
(If a valid pci irq is detected it should use it and not the isa irq.)

I have tested it in my laptop only. I tested a ethernet and a usb cardbus card. 
Both OK
I also inserted but don't realy used a old pcmcia modem card. It detected the 
irq correct.

Maybe some of you can test this patch on other hardware.
And please review the changes, especially those in yenta_socket.c
I am not sure about these changes not breaking other ti pcmcia bridges.

       Signed-off-by: Jens Kuenzer <jens.kuen...@fpga.homeip.net>


diff -u linux-2.6.15.1/drivers/pcmcia/i82365.h 
linux-2.6.15.1-jck/drivers/pcmcia/i82365.h
--- linux-2.6.15.1/drivers/pcmcia/i82365.h      2006-01-15 07:16:02.000000000 
+0100
+++ linux-2.6.15.1-jck/drivers/pcmcia/i82365.h  2006-02-18 17:34:35.000000000 
+0100
@@ -88,13 +88,14 @@
#define I365_IRQ_MASK   0x0F

/* Flags for I365_CSC and I365_CSCINT*/
-#define I365_CSC_BVD1  0x01
-#define I365_CSC_STSCHG        0x01
-#define I365_CSC_BVD2  0x02
-#define I365_CSC_READY 0x04
-#define I365_CSC_DETECT        0x08
-#define I365_CSC_ANY   0x0F
-#define I365_CSC_GPI   0x10
+#define I365_CSC_BVD1          0x01
+#define I365_CSC_STSCHG                0x01
+#define I365_CSC_BVD2          0x02
+#define I365_CSC_READY         0x04
+#define I365_CSC_DETECT                0x08
+#define I365_CSC_ANY           0x0F
+#define I365_CSC_GPI           0x10
+#define I365_CSC_IRQ_MASK      0xF0

/* Flags for I365_ADDRWIN */
#define I365_ENA_IO(map)        (0x40 << (map))
diff -u linux-2.6.15.1/drivers/pcmcia/ti113x.h 
linux-2.6.15.1-jck/drivers/pcmcia/ti113x.h
--- linux-2.6.15.1/drivers/pcmcia/ti113x.h      2006-01-15 07:16:02.000000000 
+0100
+++ linux-2.6.15.1-jck/drivers/pcmcia/ti113x.h  2006-03-15 10:13:32.000000000 
+0100
@@ -304,6 +304,18 @@
        return 0;
}

+static int ti113x_init(struct yenta_socket *socket)
+{
+        u8 new, reg = exca_readb(socket, I365_INTCTL);
+
+        new = reg & ~I365_INTR_ENA;
+        if ( socket->dev->irq ) /* PCI IRQ */
+                new |= I365_INTR_ENA;
+        if (new != reg)
+                exca_writeb(socket, I365_INTCTL, new);
+        return 0;
+}
+
static int ti_override(struct yenta_socket *socket)
{
        u8 new, reg = exca_readb(socket, I365_INTCTL);
@@ -317,14 +329,42 @@
        return 0;
}

+static void ti113x_use_isa_irq(struct yenta_socket *socket)
+{
+       int isa_irq;
+       u8 intctl;
+       u32 isa_irq_mask;
+
+       /* get a free isa int */
+       isa_irq_mask = 0;
+        if (isa_probe)
+                isa_irq_mask = yenta_probe_irq(socket, 0x0ef8); /* 0x0ef8 => 
only common isa irqs */
+       if ( !(isa_irq_mask & 0xFFFF) ) return; /* no useable isa irq found */
+       for(isa_irq = -1 ; isa_irq_mask ; isa_irq++ ) /* choose highest 
available */
+               isa_irq_mask >>= 1;
+
+       exca_writeb(socket, I365_CSCINT, (isa_irq << 4) );  /* CSC */
+
+       socket->cb_irq = isa_irq;
+
+       intctl = exca_readb(socket, I365_INTCTL);
+       intctl &= ~(I365_INTR_ENA | I365_IRQ_MASK); /* CSC Enable */
+       exca_writeb(socket, I365_INTCTL, intctl );
+
+        printk(KERN_INFO "Yenta TI113x: using isa irq %d\n", isa_irq);
+}
+
static int ti113x_override(struct yenta_socket *socket)
{
        u8 cardctl;

        cardctl = config_readb(socket, TI113X_CARD_CONTROL);
        cardctl &= ~(TI113X_CCR_PCI_IRQ_ENA | TI113X_CCR_PCI_IREQ | 
TI113X_CCR_PCI_CSC);
-       if (socket->cb_irq)
+       if (socket->dev->irq)
                cardctl |= TI113X_CCR_PCI_IRQ_ENA | TI113X_CCR_PCI_CSC | 
TI113X_CCR_PCI_IREQ;
+       else
+               ti113x_use_isa_irq(socket);
+
        config_writeb(socket, TI113X_CARD_CONTROL, cardctl);

        return ti_override(socket);
diff -u linux-2.6.15.1/drivers/pcmcia/yenta_socket.c 
linux-2.6.15.1-jck/drivers/pcmcia/yenta_socket.c
--- linux-2.6.15.1/drivers/pcmcia/yenta_socket.c        2006-01-15 
07:16:02.000000000 +0100
+++ linux-2.6.15.1-jck/drivers/pcmcia/yenta_socket.c    2006-03-12 
01:05:34.000000000 +0100
@@ -50,7 +50,7 @@
#define to_ns(cycles)   ((cycles)*120)

static int yenta_probe_cb_irq(struct yenta_socket *socket);
-
+static unsigned int yenta_probe_irq(struct yenta_socket *socket, u32 
isa_irq_mask);

static unsigned int override_bios;
module_param(override_bios, uint, 0000);
@@ -379,9 +379,12 @@

                /* ISA interrupt control? */
                intr = exca_readb(socket, I365_INTCTL);
-               intr = (intr & ~0xf);
-               if (!socket->cb_irq) {
-                       intr |= state->io_irq;
+               intr &= ~(I365_IRQ_MASK);
+               if (!socket->dev->irq) {  /* is there a valid pci irq ? */
+                       if(socket->cb_irq)
+                               intr |= socket->cb_irq;
+                       else
+                               intr |= socket->io_irq;
                        bridge |= CB_BRIDGE_INTR;
                }
                exca_writeb(socket, I365_INTCTL, intr);
@@ -391,7 +394,7 @@
                reg = exca_readb(socket, I365_INTCTL) & (I365_RING_ENA | 
I365_INTR_ENA);
                reg |= (state->flags & SS_RESET) ? 0 : I365_PC_RESET;
                reg |= (state->flags & SS_IOCARD) ? I365_PC_IOCARD : 0;
-               if (state->io_irq != socket->cb_irq) {
+               if (state->io_irq) {
                        reg |= state->io_irq;
                        bridge |= CB_BRIDGE_INTR;
                }
@@ -404,8 +407,10 @@
                if (exca_readb(socket, I365_POWER) != reg)
                        exca_writeb(socket, I365_POWER, reg);

-               /* CSC interrupt: no ISA irq for CSC */
-               reg = I365_CSC_DETECT;
+               reg = exca_readb(socket, I365_CSCINT);  /*keep isa IRQs for 
CSC*/
+               reg &= I365_CSC_IRQ_MASK;
+               reg |= I365_CSC_DETECT;
+
                if (state->flags & SS_IOCARD) {
                        if (state->csc_mask & SS_STSCHG) reg |= I365_CSC_STSCHG;
                } else {
@@ -868,7 +873,7 @@
                .override       = ti113x_override,
                .save_state     = ti_save_state,
                .restore_state  = ti_restore_state,
-               .sock_init      = ti_init,
+               .sock_init      = ti113x_init,
        },
        [CARDBUS_TYPE_TI12XX]   = {
                .override       = ti12xx_override,
@@ -922,6 +927,7 @@
        int i;
        unsigned long val;
        u32 mask;
+       u8 reg;

        /*
         * Probe for usable interrupts using the force
@@ -929,6 +935,7 @@
         */
        cb_writel(socket, CB_SOCKET_EVENT, -1);
        cb_writel(socket, CB_SOCKET_MASK, CB_CSTSMASK);
+       reg = exca_readb(socket, I365_CSCINT); /* save */
        exca_writeb(socket, I365_CSCINT, 0);
        val = probe_irq_on() & isa_irq_mask;
        for (i = 1; i < 16; i++) {
@@ -940,7 +947,7 @@
                cb_writel(socket, CB_SOCKET_EVENT, -1);
        }
        cb_writel(socket, CB_SOCKET_MASK, 0);
-       exca_writeb(socket, I365_CSCINT, 0);
+       exca_writeb(socket, I365_CSCINT, reg); /* restore */

        mask = probe_irq_mask(val) & 0xffff;

@@ -971,6 +978,8 @@
/* probes the PCI interrupt, use only on override functions */
static int yenta_probe_cb_irq(struct yenta_socket *socket)
{
+       u8 reg;
+
        if (!socket->cb_irq)
                return -1;

@@ -982,7 +991,9 @@
        }

        /* generate interrupt, wait */
-       exca_writeb(socket, I365_CSCINT, I365_CSC_STSCHG);
+       reg = exca_readb(socket, I365_CSCINT); /* save */
+       exca_writeb(socket, I365_CSCINT, reg | I365_CSC_STSCHG);
+
        cb_writel(socket, CB_SOCKET_EVENT, -1);
        cb_writel(socket, CB_SOCKET_MASK, CB_CSTSMASK);
        cb_writel(socket, CB_SOCKET_FORCE, CB_FCARDSTS);
@@ -991,7 +1002,7 @@

        /* disable interrupts */
        cb_writel(socket, CB_SOCKET_MASK, 0);
-       exca_writeb(socket, I365_CSCINT, 0);
+       exca_writeb(socket, I365_CSCINT, reg); /* restore */
        cb_writel(socket, CB_SOCKET_EVENT, -1);
        exca_readb(socket, I365_CSC);



_______________________________________________
Linux PCMCIA reimplementation list
http://lists.infradead.org/mailman/listinfo/linux-pcmcia

Reply via email to