aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRichard Purdie <rpurdie@rpsys.net>2006-01-05 15:44:57 -0500
committerRussell King <rmk+kernel@arm.linux.org.uk>2006-01-05 15:44:57 -0500
commit945b957972844881002ab4f68534581f4427a30b (patch)
tree0b9a1deb5094b847ce943b8f101386f373f472c6
parent53b7c2b243bd31f857dddabd9339f2dd6ae3fb67 (diff)
[ARM] 3230/1: Sharp Scoop: Fix Shared Power Control Issues
Patch from Richard Purdie The SL-Cxx00 devices have a power control register in SCOOP that is shared by both CF and MMC/SD card slots. The CF reset code was resetting this register leading to various lockups as the MMC power was suddenly lost. This patch handles the CPR register in a more sensitive manner. It also removes some unneeded collie specific calls as the reset code handles this. Signed-off-by: Richard Purdie <rpurdie@rpsys.net> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
-rw-r--r--arch/arm/common/scoop.c2
-rw-r--r--arch/arm/mach-pxa/spitz.c4
-rw-r--r--drivers/pcmcia/pxa2xx_sharpsl.c24
3 files changed, 16 insertions, 14 deletions
diff --git a/arch/arm/common/scoop.c b/arch/arm/common/scoop.c
index 0c3cbd9a388b..b6de43e73699 100644
--- a/arch/arm/common/scoop.c
+++ b/arch/arm/common/scoop.c
@@ -33,7 +33,6 @@ void reset_scoop(struct device *dev)
33 33
34 SCOOP_REG(sdev->base,SCOOP_MCR) = 0x0100; // 00 34 SCOOP_REG(sdev->base,SCOOP_MCR) = 0x0100; // 00
35 SCOOP_REG(sdev->base,SCOOP_CDR) = 0x0000; // 04 35 SCOOP_REG(sdev->base,SCOOP_CDR) = 0x0000; // 04
36 SCOOP_REG(sdev->base,SCOOP_CPR) = 0x0000; // 0C
37 SCOOP_REG(sdev->base,SCOOP_CCR) = 0x0000; // 10 36 SCOOP_REG(sdev->base,SCOOP_CCR) = 0x0000; // 10
38 SCOOP_REG(sdev->base,SCOOP_IMR) = 0x0000; // 18 37 SCOOP_REG(sdev->base,SCOOP_IMR) = 0x0000; // 18
39 SCOOP_REG(sdev->base,SCOOP_IRM) = 0x00FF; // 14 38 SCOOP_REG(sdev->base,SCOOP_IRM) = 0x00FF; // 14
@@ -154,6 +153,7 @@ int __init scoop_probe(struct platform_device *pdev)
154 153
155 SCOOP_REG(devptr->base, SCOOP_MCR) = 0x0140; 154 SCOOP_REG(devptr->base, SCOOP_MCR) = 0x0140;
156 reset_scoop(&pdev->dev); 155 reset_scoop(&pdev->dev);
156 SCOOP_REG(devptr->base, SCOOP_CPR) = 0x0000;
157 SCOOP_REG(devptr->base, SCOOP_GPCR) = inf->io_dir & 0xffff; 157 SCOOP_REG(devptr->base, SCOOP_GPCR) = inf->io_dir & 0xffff;
158 SCOOP_REG(devptr->base, SCOOP_GPWR) = inf->io_out & 0xffff; 158 SCOOP_REG(devptr->base, SCOOP_GPWR) = inf->io_out & 0xffff;
159 159
diff --git a/arch/arm/mach-pxa/spitz.c b/arch/arm/mach-pxa/spitz.c
index 5d34abc64af7..f2007db0cda5 100644
--- a/arch/arm/mach-pxa/spitz.c
+++ b/arch/arm/mach-pxa/spitz.c
@@ -127,10 +127,12 @@ static void spitz_card_pwr_ctrl(int device, unsigned short new_cpr)
127 cpr &= ~0x0002; 127 cpr &= ~0x0002;
128 if (device == SPITZ_PWR_SD) 128 if (device == SPITZ_PWR_SD)
129 cpr &= ~0x0004; 129 cpr &= ~0x0004;
130 write_scoop_reg(&spitzscoop_device.dev, SCOOP_CPR, cpr | new_cpr);
131 if (!(cpr & 0x0002) && !(cpr & 0x0004)) { 130 if (!(cpr & 0x0002) && !(cpr & 0x0004)) {
131 write_scoop_reg(&spitzscoop_device.dev, SCOOP_CPR, 0x0000);
132 mdelay(1); 132 mdelay(1);
133 reset_scoop_gpio(&spitzscoop_device.dev, SPITZ_SCP_CF_POWER); 133 reset_scoop_gpio(&spitzscoop_device.dev, SPITZ_SCP_CF_POWER);
134 } else {
135 write_scoop_reg(&spitzscoop_device.dev, SCOOP_CPR, cpr | new_cpr);
134 } 136 }
135 } 137 }
136} 138}
diff --git a/drivers/pcmcia/pxa2xx_sharpsl.c b/drivers/pcmcia/pxa2xx_sharpsl.c
index 56c58831e80e..4fbd995360b0 100644
--- a/drivers/pcmcia/pxa2xx_sharpsl.c
+++ b/drivers/pcmcia/pxa2xx_sharpsl.c
@@ -36,9 +36,18 @@
36struct scoop_pcmcia_config *platform_scoop_config; 36struct scoop_pcmcia_config *platform_scoop_config;
37#define SCOOP_DEV platform_scoop_config->devs 37#define SCOOP_DEV platform_scoop_config->devs
38 38
39static void sharpsl_pcmcia_init_reset(struct scoop_pcmcia_dev *scoopdev) 39static void sharpsl_pcmcia_init_reset(struct soc_pcmcia_socket *skt)
40{ 40{
41 struct scoop_pcmcia_dev *scoopdev = &SCOOP_DEV[skt->nr];
42
41 reset_scoop(scoopdev->dev); 43 reset_scoop(scoopdev->dev);
44
45 /* Shared power controls need to be handled carefully */
46 if (platform_scoop_config->power_ctrl)
47 platform_scoop_config->power_ctrl(scoopdev->dev, 0x0000, skt->nr);
48 else
49 write_scoop_reg(scoopdev->dev, SCOOP_CPR, 0x0000);
50
42 scoopdev->keep_vs = NO_KEEP_VS; 51 scoopdev->keep_vs = NO_KEEP_VS;
43 scoopdev->keep_rd = 0; 52 scoopdev->keep_rd = 0;
44} 53}
@@ -208,26 +217,17 @@ static int sharpsl_pcmcia_configure_socket(struct soc_pcmcia_socket *skt,
208 217
209static void sharpsl_pcmcia_socket_init(struct soc_pcmcia_socket *skt) 218static void sharpsl_pcmcia_socket_init(struct soc_pcmcia_socket *skt)
210{ 219{
211 sharpsl_pcmcia_init_reset(&SCOOP_DEV[skt->nr]); 220 sharpsl_pcmcia_init_reset(skt);
212 221
213 /* Enable interrupt */ 222 /* Enable interrupt */
214 write_scoop_reg(SCOOP_DEV[skt->nr].dev, SCOOP_IMR, 0x00C0); 223 write_scoop_reg(SCOOP_DEV[skt->nr].dev, SCOOP_IMR, 0x00C0);
215 write_scoop_reg(SCOOP_DEV[skt->nr].dev, SCOOP_MCR, 0x0101); 224 write_scoop_reg(SCOOP_DEV[skt->nr].dev, SCOOP_MCR, 0x0101);
216 SCOOP_DEV[skt->nr].keep_vs = NO_KEEP_VS; 225 SCOOP_DEV[skt->nr].keep_vs = NO_KEEP_VS;
217
218 if (machine_is_collie())
219 /* We need to disable SS_OUTPUT_ENA here. */
220 write_scoop_reg(SCOOP_DEV[skt->nr].dev, SCOOP_CPR, read_scoop_reg(SCOOP_DEV[skt->nr].dev, SCOOP_CPR) & ~0x0080);
221} 226}
222 227
223static void sharpsl_pcmcia_socket_suspend(struct soc_pcmcia_socket *skt) 228static void sharpsl_pcmcia_socket_suspend(struct soc_pcmcia_socket *skt)
224{ 229{
225 /* CF_BUS_OFF */ 230 sharpsl_pcmcia_init_reset(skt);
226 sharpsl_pcmcia_init_reset(&SCOOP_DEV[skt->nr]);
227
228 if (machine_is_collie())
229 /* We need to disable SS_OUTPUT_ENA here. */
230 write_scoop_reg(SCOOP_DEV[skt->nr].dev, SCOOP_CPR, read_scoop_reg(SCOOP_DEV[skt->nr].dev, SCOOP_CPR) & ~0x0080);
231} 231}
232 232
233static struct pcmcia_low_level sharpsl_pcmcia_ops = { 233static struct pcmcia_low_level sharpsl_pcmcia_ops = {