Difference between revisions of "760ed yenta patch"

From ThinkWiki
Jump to: navigation, search
m
(Undo corruption)
Line 8: Line 8:
 
<code><pre><nowiki>
 
<code><pre><nowiki>
 
diff -u linux-2.6.15.1/drivers/pcmcia/i82365.h linux-2.6.15.1-jck/drivers/pcmcia/i82365.h
 
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/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
+
+++ linux-2.6.15.1-jck/drivers/pcmcia/i82365.h 2006-02-18 17:34:35.000000000 +0100
@@ -88,13 88,14 @@
+
@@ -88,13 +88,14 @@
 
  #define I365_IRQ_MASK 0x0F
 
  #define I365_IRQ_MASK 0x0F
 
   
 
   
Line 21: Line 21:
 
-#define I365_CSC_ANY 0x0F
 
-#define I365_CSC_ANY 0x0F
 
-#define I365_CSC_GPI 0x10
 
-#define I365_CSC_GPI 0x10
#define I365_CSC_BVD1 0x01
+
+#define I365_CSC_BVD1 0x01
#define I365_CSC_STSCHG 0x01
+
+#define I365_CSC_STSCHG 0x01
#define I365_CSC_BVD2 0x02
+
+#define I365_CSC_BVD2 0x02
#define I365_CSC_READY 0x04
+
+#define I365_CSC_READY 0x04
#define I365_CSC_DETECT 0x08
+
+#define I365_CSC_DETECT 0x08
#define I365_CSC_ANY 0x0F
+
+#define I365_CSC_ANY 0x0F
#define I365_CSC_GPI 0x10
+
+#define I365_CSC_GPI 0x10
#define I365_CSC_IRQ_MASK 0xF0
+
+#define I365_CSC_IRQ_MASK 0xF0
 
   
 
   
 
  /* Flags for I365_ADDRWIN */
 
  /* Flags for I365_ADDRWIN */
 
  #define I365_ENA_IO(map) (0x40 << (map))
 
  #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
 
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/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
+
+++ linux-2.6.15.1-jck/drivers/pcmcia/ti113x.h 2006-03-15 10:13:32.000000000 +0100
@@ -304,6 304,18 @@
+
@@ -304,6 +304,18 @@
 
  return 0;
 
  return 0;
 
  }
 
  }
 
   
 
   
  static int ti113x_init(struct yenta_socket *socket)
+
+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);
+
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);
 
   
 
   
        new = reg
+
</nowiki></pre></code>
 +
 
 +
{{HELP|
 +
It is untested if these changes are not breaking other ti pcmcia bridges.
 +
( Maybe someone can test this patch on other hardware.
 +
And please review the changes, especially those in yenta_socket.c )
 +
}}
 +
 
 +
[[Category:760ED]]

Revision as of 15:22, 11 April 2007

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

The pci irq pin of the ti1130 pcmcia bridge is not connected. To use the cardbus, the kernel has to route the cardbus irq 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.)

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);
 
Help needed

It is untested if these changes are not breaking other ti pcmcia bridges. ( Maybe someone can test this patch on other hardware. And please review the changes, especially those in yenta_socket.c )