Toshiba ToPIC developer info

Daniel Ritz daniel.ritz at gmx.ch
Sat Jun 25 20:25:28 EDT 2005


hi

attached a patch that makes the ToPIC95 work for both 16bit and cardbus
cards. tested on my old tecra530cdt. my topic97 rev5 does not require this.
akpm: -mm please

rgds
-daniel

-----

[PATCH] yenta: make ToPIC95 bridges work with 16bit cards

ToPIC95 brides (and maybe some other too) require to use the ExCA registers
to power up the socket if a 16bit card is pluged. allow socket drivers to
set a flag so that yenta does just that. also clean up yenta_get_status()
a bit to use the new yenta_get_power() function.

side note: ToPIC97 bridges (at least in Rev.5 i have) don't require this.

Signed-off-by: Daniel Ritz <daniel.ritz at gmx.ch>

Index: drivers/pcmcia/topic.h
===================================================================
--- c830ffbdea3c6ab00f31afeedc26392bd4a55d63/drivers/pcmcia/topic.h  (mode:100644 sha1:be420bb291135a8cee511c9df3edf91e79b1ea27)
+++ uncommitted/drivers/pcmcia/topic.h  (mode:100664)
@@ -101,6 +101,8 @@
 #define  TOPIC97_AVS_AUDIO_CONTROL	0x02
 #define  TOPIC97_AVS_VIDEO_CONTROL	0x01
 
+#define TOPIC_EXCA_IF_CONTROL		0x3e	/* 8 bit */
+#define TOPIC_EXCA_IFC_33V_ENA		0x01
 
 static void topic97_zoom_video(struct pcmcia_socket *sock, int onoff)
 {
@@ -137,4 +139,19 @@
 	return 0;
 }
 
+
+static int topic95_override(struct yenta_socket *socket)
+{
+	u8 fctrl;
+
+	/* enable 3.3V support for 16bit cards */
+	fctrl = exca_readb(socket, TOPIC_EXCA_IF_CONTROL);
+	exca_writeb(socket, TOPIC_EXCA_IF_CONTROL, fctrl | TOPIC_EXCA_IFC_33V_ENA);
+
+	/* tell yenta to use exca registers to power 16bit cards */
+	socket->flags |= YENTA_16BIT_POWER_EXCA | YENTA_16BIT_POWER_DF;
+
+	return 0;
+}
+
 #endif /* _LINUX_TOPIC_H */
Index: drivers/pcmcia/yenta_socket.c
===================================================================
--- c830ffbdea3c6ab00f31afeedc26392bd4a55d63/drivers/pcmcia/yenta_socket.c  (mode:100644 sha1:bee05362fd244dc46762a0979e3c009c62752a24)
+++ uncommitted/drivers/pcmcia/yenta_socket.c  (mode:100664)
@@ -185,22 +185,52 @@
 	return 0;
 }
 
-static int yenta_Vcc_power(u32 control)
+static void yenta_get_power(struct yenta_socket *socket, socket_state_t *state)
 {
-	switch (control & CB_SC_VCC_MASK) {
-	case CB_SC_VCC_5V: return 50;
-	case CB_SC_VCC_3V: return 33;
-	default: return 0;
-	}
-}
+	if (!(cb_readl(socket, CB_SOCKET_STATE) & CB_CBCARD) &&
+	    (socket->flags & YENTA_16BIT_POWER_EXCA)) {
+		u8 reg, vcc, vpp;
+
+		reg = exca_readb(socket, I365_POWER);
+		vcc = reg & I365_VCC_MASK;
+		vpp = reg & I365_VPP1_MASK;
+		state->Vcc = state->Vpp = 0;
+		
+		if (socket->flags & YENTA_16BIT_POWER_DF) {
+			if (vcc == I365_VCC_3V)
+				state->Vcc = 33;
+			if (vcc == I365_VCC_5V)
+				state->Vcc = 50;
+			if (vpp == I365_VPP1_5V)
+				state->Vpp = state->Vcc;
+			if (vpp == I365_VPP1_12V)
+				state->Vpp = 120;
+		} else {
+			if (reg & I365_VCC_5V) {
+				state->Vcc = 50;
+				if (vpp == I365_VPP1_5V)
+					state->Vpp = 50;
+				if (vpp == I365_VPP1_12V)
+					state->Vpp = 120;
+			}
+		}
+	} else {
+		u32 control;
 
-static int yenta_Vpp_power(u32 control)
-{
-	switch (control & CB_SC_VPP_MASK) {
-	case CB_SC_VPP_12V: return 120;
-	case CB_SC_VPP_5V: return 50;
-	case CB_SC_VPP_3V: return 33;
-	default: return 0;
+		control = cb_readl(socket, CB_SOCKET_CONTROL);
+
+		switch (control & CB_SC_VCC_MASK) {
+		case CB_SC_VCC_5V: state->Vcc = 50; break;
+		case CB_SC_VCC_3V: state->Vcc = 33; break;
+		default: state->Vcc = 0;
+		}
+
+		switch (control & CB_SC_VPP_MASK) {
+		case CB_SC_VPP_12V: state->Vpp = 120; break;
+		case CB_SC_VPP_5V: state->Vpp = 50; break;
+		case CB_SC_VPP_3V: state->Vpp = 33; break;
+		default: state->Vpp = 0;
+		}
 	}
 }
 
@@ -212,8 +242,7 @@
 
 	control = cb_readl(socket, CB_SOCKET_CONTROL);
 
-	state->Vcc = yenta_Vcc_power(control);
-	state->Vpp = yenta_Vpp_power(control);
+	yenta_get_power(socket, state);
 	state->io_irq = socket->io_irq;
 
 	if (cb_readl(socket, CB_SOCKET_STATE) & CB_CBCARD) {
@@ -247,19 +276,54 @@
 
 static void yenta_set_power(struct yenta_socket *socket, socket_state_t *state)
 {
-	u32 reg = 0;	/* CB_SC_STPCLK? */
-	switch (state->Vcc) {
-	case 33: reg = CB_SC_VCC_3V; break;
-	case 50: reg = CB_SC_VCC_5V; break;
-	default: reg = 0; break;
-	}
-	switch (state->Vpp) {
-	case 33:  reg |= CB_SC_VPP_3V; break;
-	case 50:  reg |= CB_SC_VPP_5V; break;
-	case 120: reg |= CB_SC_VPP_12V; break;
+	/* some birdges require to use the ExCA registers to power 16bit cards */
+	if (!(cb_readl(socket, CB_SOCKET_STATE) & CB_CBCARD) &&
+	    (socket->flags & YENTA_16BIT_POWER_EXCA)) {
+		u8 reg, old;
+		reg = old = exca_readb(socket, I365_POWER);
+		reg &= ~(I365_VCC_MASK | I365_VPP1_MASK | I365_VPP2_MASK);
+
+		/* i82365SL-DF style */
+		if (socket->flags & YENTA_16BIT_POWER_DF) {
+			switch (state->Vcc) {
+			case 33: reg |= I365_VCC_3V; break;
+			case 50: reg |= I365_VCC_5V; break;
+			default: reg = 0; break;
+			}
+			switch (state->Vpp) {
+			case 33:
+			case 50: reg |= I365_VPP1_5V; break;
+			case 120: reg |= I365_VPP1_12V; break;
+			}
+		} else {
+			/* i82365SL-B style */
+			switch (state->Vcc) {
+			case 50: reg |= I365_VCC_5V; break;
+			default: reg = 0; break;
+			}
+			switch (state->Vpp) {
+			case 50: reg |= I365_VPP1_5V | I365_VPP2_5V; break;
+			case 120: reg |= I365_VPP1_12V | I365_VPP2_12V; break;
+			}
+		}
+
+		if (reg != old)
+			exca_writeb(socket, I365_POWER, reg);
+	} else {
+		u32 reg = 0;	/* CB_SC_STPCLK? */
+		switch (state->Vcc) {
+		case 33: reg = CB_SC_VCC_3V; break;
+		case 50: reg = CB_SC_VCC_5V; break;
+		default: reg = 0; break;
+		}
+		switch (state->Vpp) {
+		case 33:  reg |= CB_SC_VPP_3V; break;
+		case 50:  reg |= CB_SC_VPP_5V; break;
+		case 120: reg |= CB_SC_VPP_12V; break;
+		}
+		if (reg != cb_readl(socket, CB_SOCKET_CONTROL))
+			cb_writel(socket, CB_SOCKET_CONTROL, reg);
 	}
-	if (reg != cb_readl(socket, CB_SOCKET_CONTROL))
-		cb_writel(socket, CB_SOCKET_CONTROL, reg);
 }
 
 static int yenta_set_socket(struct pcmcia_socket *sock, socket_state_t *state)
@@ -698,6 +762,7 @@
 	CARDBUS_TYPE_TI12XX,
 	CARDBUS_TYPE_TI1250,
 	CARDBUS_TYPE_RICOH,
+	CARDBUS_TYPE_TOPIC95,
 	CARDBUS_TYPE_TOPIC97,
 	CARDBUS_TYPE_O2MICRO,
 };
@@ -736,6 +801,9 @@
 		.save_state	= ricoh_save_state,
 		.restore_state	= ricoh_restore_state,
 	},
+	[CARDBUS_TYPE_TOPIC95]	= {
+		.override	= topic95_override,
+	},
 	[CARDBUS_TYPE_TOPIC97]	= {
 		.override	= topic97_override,
 	},
@@ -1136,6 +1204,7 @@
 	CB_ID(PCI_VENDOR_ID_RICOH, PCI_DEVICE_ID_RICOH_RL5C476, RICOH),
 	CB_ID(PCI_VENDOR_ID_RICOH, PCI_DEVICE_ID_RICOH_RL5C478, RICOH),
 
+	CB_ID(PCI_VENDOR_ID_TOSHIBA, PCI_DEVICE_ID_TOSHIBA_TOPIC95, TOPIC95),
 	CB_ID(PCI_VENDOR_ID_TOSHIBA, PCI_DEVICE_ID_TOSHIBA_TOPIC97, TOPIC97),
 	CB_ID(PCI_VENDOR_ID_TOSHIBA, PCI_DEVICE_ID_TOSHIBA_TOPIC100, TOPIC97),
 
Index: drivers/pcmcia/yenta_socket.h
===================================================================
--- c830ffbdea3c6ab00f31afeedc26392bd4a55d63/drivers/pcmcia/yenta_socket.h  (mode:100644 sha1:4e637eef207652a33beaa752d1c6d6fdd2367ea3)
+++ uncommitted/drivers/pcmcia/yenta_socket.h  (mode:100664)
@@ -95,6 +95,12 @@
  */
 #define CB_MEM_PAGE(map)	(0x40 + (map))
 
+
+/* control how 16bit cards are powered */
+#define YENTA_16BIT_POWER_EXCA	0x00000001
+#define YENTA_16BIT_POWER_DF	0x00000002
+
+
 struct yenta_socket;
 
 struct cardbus_type {
@@ -113,6 +119,8 @@
 	struct pcmcia_socket socket;
 	struct cardbus_type *type;
 
+	u32 flags;
+
 	/* for PCI interrupt probing */
 	unsigned int probe_status;
 



More information about the linux-pcmcia mailing list