drivers/pcmcia/ricoh.h        |   33 ++++++++++++++++----------
 drivers/pcmcia/ti113x.h       |   20 ++++++++++++++++
 drivers/pcmcia/yenta_socket.c |   52 ++++++++++++++++++++++++++++++------------
 drivers/pcmcia/yenta_socket.h |    5 ++++
 4 files changed, 83 insertions(+), 27 deletions(-)

diff -puN drivers/pcmcia/ricoh.h~yenta-20030817-4-pm drivers/pcmcia/ricoh.h
--- 25/drivers/pcmcia/ricoh.h~yenta-20030817-4-pm	2003-08-17 14:20:44.000000000 -0700
+++ 25-akpm/drivers/pcmcia/ricoh.h	2003-08-17 14:20:44.000000000 -0700
@@ -156,39 +156,46 @@ static void ricoh_set_zv(struct yenta_so
         }
 }
 
-static int ricoh_init(struct yenta_socket *socket)
+static void ricoh_save_state(struct yenta_socket *socket)
+{
+	rl_misc(socket) = config_readw(socket, RL5C4XX_MISC);
+	rl_ctl(socket) = config_readw(socket, RL5C4XX_16BIT_CTL);
+	rl_io(socket) = config_readw(socket, RL5C4XX_16BIT_IO_0);
+	rl_mem(socket) = config_readw(socket, RL5C4XX_16BIT_MEM_0);
+	rl_config(socket) = config_readw(socket, RL5C4XX_CONFIG);
+}
+
+static void ricoh_restore_state(struct yenta_socket *socket)
 {
 	config_writew(socket, RL5C4XX_MISC, rl_misc(socket));
 	config_writew(socket, RL5C4XX_16BIT_CTL, rl_ctl(socket));
 	config_writew(socket, RL5C4XX_16BIT_IO_0, rl_io(socket));
 	config_writew(socket, RL5C4XX_16BIT_MEM_0, rl_mem(socket));
 	config_writew(socket, RL5C4XX_CONFIG, rl_config(socket));
-	
-	return 0;
 }
 
 
 /*
- * Magic Ricoh initialization code.. Save state at
- * beginning, re-initialize it after suspend.
+ * Magic Ricoh initialization code..
  */
 static int ricoh_override(struct yenta_socket *socket)
 {
-	rl_misc(socket) = config_readw(socket, RL5C4XX_MISC);
-	rl_ctl(socket) = config_readw(socket, RL5C4XX_16BIT_CTL);
-	rl_io(socket) = config_readw(socket, RL5C4XX_16BIT_IO_0);
-	rl_mem(socket) = config_readw(socket, RL5C4XX_16BIT_MEM_0);
-	rl_config(socket) = config_readw(socket, RL5C4XX_CONFIG);
+	u16 config, ctl;
+
+	config = config_readw(socket, RL5C4XX_CONFIG);
 
 	/* Set the default timings, don't trust the original values */
-	rl_ctl(socket) = RL5C4XX_16CTL_IO_TIMING | RL5C4XX_16CTL_MEM_TIMING;
+	ctl = RL5C4XX_16CTL_IO_TIMING | RL5C4XX_16CTL_MEM_TIMING;
 
 	if(socket->dev->device < PCI_DEVICE_ID_RICOH_RL5C475) {
-		rl_ctl(socket) |= RL5C46X_16CTL_LEVEL_1 | RL5C46X_16CTL_LEVEL_2;
+		ctl |= RL5C46X_16CTL_LEVEL_1 | RL5C46X_16CTL_LEVEL_2;
 	} else {
-		rl_config(socket) |= RL5C4XX_CONFIG_PREFETCH;
+		config |= RL5C4XX_CONFIG_PREFETCH;
 	}
 
+	config_writew(socket, RL5C4XX_16BIT_CTL, ctl);
+	config_writew(socket, RL5C4XX_CONFIG, config);
+
 	ricoh_set_zv(socket);
 
 	return 0;
diff -puN drivers/pcmcia/ti113x.h~yenta-20030817-4-pm drivers/pcmcia/ti113x.h
--- 25/drivers/pcmcia/ti113x.h~yenta-20030817-4-pm	2003-08-17 14:20:44.000000000 -0700
+++ 25-akpm/drivers/pcmcia/ti113x.h	2003-08-17 14:20:44.000000000 -0700
@@ -145,6 +145,26 @@
 #define ti_diag(socket)		((socket)->private[3])
 #define ti_irqmux(socket)	((socket)->private[4])
 
+/*
+ * These are the TI specific power management handlers.
+ */
+static void ti_save_state(struct yenta_socket *socket)
+{
+	ti_sysctl(socket) = config_readl(socket, TI113X_SYSTEM_CONTROL);
+	ti_irqmux(socket) = config_readl(socket, TI122X_IRQMUX);
+	ti_cardctl(socket) = config_readb(socket, TI113X_CARD_CONTROL);
+	ti_devctl(socket) = config_readb(socket, TI113X_DEVICE_CONTROL);
+	ti_diag(socket) = config_readb(socket, TI1250_DIAGNOSTIC);
+}
+
+static void ti_restore_state(struct yenta_socket *socket)
+{
+	config_writel(socket, TI113X_SYSTEM_CONTROL, ti_sysctl(socket));
+	config_writel(socket, TI122X_IRQMUX, ti_irqmux(socket));
+	config_writeb(socket, TI113X_CARD_CONTROL, ti_cardctl(socket));
+	config_writeb(socket, TI113X_DEVICE_CONTROL, ti_devctl(socket));
+	config_writeb(socket, TI1250_DIAGNOSTIC, ti_diag(socket));
+}
 
 static int ti_intctl(struct yenta_socket *socket)
 {
diff -puN drivers/pcmcia/yenta_socket.c~yenta-20030817-4-pm drivers/pcmcia/yenta_socket.c
--- 25/drivers/pcmcia/yenta_socket.c~yenta-20030817-4-pm	2003-08-17 14:20:44.000000000 -0700
+++ 25-akpm/drivers/pcmcia/yenta_socket.c	2003-08-17 14:20:44.000000000 -0700
@@ -601,18 +601,6 @@ static int yenta_sock_suspend(struct pcm
 	/* Disable CSC interrupts */
 	cb_writel(socket, CB_SOCKET_MASK, 0x0);
 
-	/*
-	 * This does not work currently. The controller
-	 * loses too much information during D3 to come up
-	 * cleanly. We should probably fix yenta_sock_init()
-	 * to update all the critical registers, notably
-	 * the IO and MEM bridging region data.. That is
-	 * something that pci_set_power_state() should
-	 * probably know about bridges anyway.
-	 *
-	pci_set_power_state(socket->dev, 3);
-	 */
-
 	return 0;
 }
 
@@ -792,23 +780,32 @@ enum {
 struct cardbus_type cardbus_type[] = {
 	[CARDBUS_TYPE_TI]	= {
 		.override	= ti_override,
+		.save_state	= ti_save_state,
+		.restore_state	= ti_restore_state,
 		.sock_init	= ti_init,
 	},
 	[CARDBUS_TYPE_TI113X]	= {
 		.override	= ti113x_override,
+		.save_state	= ti_save_state,
+		.restore_state	= ti_restore_state,
 		.sock_init	= ti113x_init,
 	},
 	[CARDBUS_TYPE_TI12XX]	= {
 		.override	= ti12xx_override,
+		.save_state	= ti_save_state,
+		.restore_state	= ti_restore_state,
 		.sock_init	= ti113x_init,
 	},
 	[CARDBUS_TYPE_TI1250]	= {
 		.override	= ti1250_override,
+		.save_state	= ti_save_state,
+		.restore_state	= ti_restore_state,
 		.sock_init	= ti1250_init,
 	},
 	[CARDBUS_TYPE_RICOH]	= {
 		.override	= ricoh_override,
-		.sock_init	= ricoh_init,
+		.save_state	= ricoh_save_state,
+		.restore_state	= ricoh_restore_state,
 	},
 };
 
@@ -929,12 +926,39 @@ static int __devinit yenta_probe (struct
 
 static int yenta_dev_suspend (struct pci_dev *dev, u32 state)
 {
-	return pcmcia_socket_dev_suspend(&dev->dev, state, SUSPEND_SAVE_STATE);
+	struct yenta_socket *socket = pci_get_drvdata(dev);
+	int ret;
+
+	ret = pcmcia_socket_dev_suspend(&dev->dev, state, SUSPEND_SAVE_STATE);
+
+	if (socket) {
+		if (socket->type && socket->type->save_state)
+			socket->type->save_state(socket);
+
+		pci_save_state(dev, socket->saved_state);
+		pci_read_config_dword(dev, 16*4, &socket->saved_state[16]);
+		pci_read_config_dword(dev, 17*4, &socket->saved_state[17]);
+		pci_set_power_state(dev, 3);
+	}
+
+	return ret;
 }
 
 
 static int yenta_dev_resume (struct pci_dev *dev)
 {
+	struct yenta_socket *socket = pci_get_drvdata(dev);
+
+	if (socket) {
+		pci_set_power_state(dev, 0);
+		pci_restore_state(dev, socket->saved_state);
+		pci_write_config_dword(dev, 16*4, socket->saved_state[16]);
+		pci_write_config_dword(dev, 17*4, socket->saved_state[17]);
+
+		if (socket->type && socket->type->restore_state)
+			socket->type->restore_state(socket);
+	}
+
 	return pcmcia_socket_dev_resume(&dev->dev, RESUME_RESTORE_STATE);
 }
 
diff -puN drivers/pcmcia/yenta_socket.h~yenta-20030817-4-pm drivers/pcmcia/yenta_socket.h
--- 25/drivers/pcmcia/yenta_socket.h~yenta-20030817-4-pm	2003-08-17 14:20:44.000000000 -0700
+++ 25-akpm/drivers/pcmcia/yenta_socket.h	2003-08-17 14:20:44.000000000 -0700
@@ -99,6 +99,8 @@ struct yenta_socket;
 
 struct cardbus_type {
 	int	(*override)(struct yenta_socket *);
+	void	(*save_state)(struct yenta_socket *);
+	void	(*restore_state)(struct yenta_socket *);
 	int	(*sock_init)(struct yenta_socket *);
 };
 
@@ -113,6 +115,9 @@ struct yenta_socket {
 
 	/* A few words of private data for special stuff of overrides... */
 	unsigned int private[8];
+
+	/* PCI saved state */
+	u32 saved_state[18];
 };
 
 

_