aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pcmcia/pxa2xx_sharpsl.c
diff options
context:
space:
mode:
authorRichard Purdie <rpurdie@rpsys.net>2005-09-05 15:49:54 -0400
committerRussell King <rmk+kernel@arm.linux.org.uk>2005-09-05 15:49:54 -0400
commit0ce7625f3c1e3f921f6b83f7e944e00031a39dfa (patch)
treebf04a478adbad082fe4689cecd02c2cd8c1f6031 /drivers/pcmcia/pxa2xx_sharpsl.c
parent027da01d734db0ca9dd1a084339dab07ab576935 (diff)
[ARM] 2882/1: pxa2xx_sharpsl: Update PCMCIA driver to support variety of new hardware
Patch from Richard Purdie This patch updates the PCMCIA pxa2xx_sharpsl driver to support multiple scoop devices by adding a scoop to pcmcia slot mapping structure. It adds platform support for poodle, is known to work on spitz (which is dual slot) and should also support collie with a minor amount of further work. Signed-off-by: Richard Purdie <rpurdie@rpsys.net> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Diffstat (limited to 'drivers/pcmcia/pxa2xx_sharpsl.c')
-rw-r--r--drivers/pcmcia/pxa2xx_sharpsl.c114
1 files changed, 62 insertions, 52 deletions
diff --git a/drivers/pcmcia/pxa2xx_sharpsl.c b/drivers/pcmcia/pxa2xx_sharpsl.c
index 7bac2f7d8b3f..a1178a600e3c 100644
--- a/drivers/pcmcia/pxa2xx_sharpsl.c
+++ b/drivers/pcmcia/pxa2xx_sharpsl.c
@@ -20,27 +20,18 @@
20 20
21#include <asm/hardware.h> 21#include <asm/hardware.h>
22#include <asm/irq.h> 22#include <asm/irq.h>
23
24#include <asm/hardware/scoop.h> 23#include <asm/hardware/scoop.h>
25#include <asm/arch/corgi.h>
26#include <asm/arch/pxa-regs.h> 24#include <asm/arch/pxa-regs.h>
27 25
28#include "soc_common.h" 26#include "soc_common.h"
29 27
30#define NO_KEEP_VS 0x0001 28#define NO_KEEP_VS 0x0001
31 29
32static unsigned char keep_vs; 30static void sharpsl_pcmcia_init_reset(struct scoop_pcmcia_dev *scoopdev)
33static unsigned char keep_rd;
34
35static struct pcmcia_irqs irqs[] = {
36 { 0, CORGI_IRQ_GPIO_CF_CD, "PCMCIA0 CD"},
37};
38
39static void sharpsl_pcmcia_init_reset(void)
40{ 31{
41 reset_scoop(&corgiscoop_device.dev); 32 reset_scoop(scoopdev->dev);
42 keep_vs = NO_KEEP_VS; 33 scoopdev->keep_vs = NO_KEEP_VS;
43 keep_rd = 0; 34 scoopdev->keep_rd = 0;
44} 35}
45 36
46static int sharpsl_pcmcia_hw_init(struct soc_pcmcia_socket *skt) 37static int sharpsl_pcmcia_hw_init(struct soc_pcmcia_socket *skt)
@@ -71,29 +62,35 @@ static int sharpsl_pcmcia_hw_init(struct soc_pcmcia_socket *skt)
71 pxa_gpio_mode(GPIO57_nIOIS16_MD); 62 pxa_gpio_mode(GPIO57_nIOIS16_MD);
72 63
73 /* Register interrupts */ 64 /* Register interrupts */
74 ret = soc_pcmcia_request_irqs(skt, irqs, ARRAY_SIZE(irqs)); 65 if (scoop_devs[skt->nr].cd_irq >= 0) {
75 66 struct pcmcia_irqs cd_irq;
76 if (ret) { 67
77 printk(KERN_ERR "Request for Compact Flash IRQ failed\n"); 68 cd_irq.sock = skt->nr;
78 return ret; 69 cd_irq.irq = scoop_devs[skt->nr].cd_irq;
70 cd_irq.str = scoop_devs[skt->nr].cd_irq_str;
71 ret = soc_pcmcia_request_irqs(skt, &cd_irq, 1);
72
73 if (ret) {
74 printk(KERN_ERR "Request for Compact Flash IRQ failed\n");
75 return ret;
76 }
79 } 77 }
80 78
81 /* Enable interrupt */ 79 skt->irq = scoop_devs[skt->nr].irq;
82 write_scoop_reg(&corgiscoop_device.dev, SCOOP_IMR, 0x00C0);
83 write_scoop_reg(&corgiscoop_device.dev, SCOOP_MCR, 0x0101);
84 keep_vs = NO_KEEP_VS;
85
86 skt->irq = CORGI_IRQ_GPIO_CF_IRQ;
87 80
88 return 0; 81 return 0;
89} 82}
90 83
91static void sharpsl_pcmcia_hw_shutdown(struct soc_pcmcia_socket *skt) 84static void sharpsl_pcmcia_hw_shutdown(struct soc_pcmcia_socket *skt)
92{ 85{
93 soc_pcmcia_free_irqs(skt, irqs, ARRAY_SIZE(irqs)); 86 if (scoop_devs[skt->nr].cd_irq >= 0) {
87 struct pcmcia_irqs cd_irq;
94 88
95 /* CF_BUS_OFF */ 89 cd_irq.sock = skt->nr;
96 sharpsl_pcmcia_init_reset(); 90 cd_irq.irq = scoop_devs[skt->nr].cd_irq;
91 cd_irq.str = scoop_devs[skt->nr].cd_irq_str;
92 soc_pcmcia_free_irqs(skt, &cd_irq, 1);
93 }
97} 94}
98 95
99 96
@@ -101,31 +98,32 @@ static void sharpsl_pcmcia_socket_state(struct soc_pcmcia_socket *skt,
101 struct pcmcia_state *state) 98 struct pcmcia_state *state)
102{ 99{
103 unsigned short cpr, csr; 100 unsigned short cpr, csr;
101 struct device *scoop = scoop_devs[skt->nr].dev;
104 102
105 cpr = read_scoop_reg(&corgiscoop_device.dev, SCOOP_CPR); 103 cpr = read_scoop_reg(scoop_devs[skt->nr].dev, SCOOP_CPR);
106 104
107 write_scoop_reg(&corgiscoop_device.dev, SCOOP_IRM, 0x00FF); 105 write_scoop_reg(scoop, SCOOP_IRM, 0x00FF);
108 write_scoop_reg(&corgiscoop_device.dev, SCOOP_ISR, 0x0000); 106 write_scoop_reg(scoop, SCOOP_ISR, 0x0000);
109 write_scoop_reg(&corgiscoop_device.dev, SCOOP_IRM, 0x0000); 107 write_scoop_reg(scoop, SCOOP_IRM, 0x0000);
110 csr = read_scoop_reg(&corgiscoop_device.dev, SCOOP_CSR); 108 csr = read_scoop_reg(scoop, SCOOP_CSR);
111 if (csr & 0x0004) { 109 if (csr & 0x0004) {
112 /* card eject */ 110 /* card eject */
113 write_scoop_reg(&corgiscoop_device.dev, SCOOP_CDR, 0x0000); 111 write_scoop_reg(scoop, SCOOP_CDR, 0x0000);
114 keep_vs = NO_KEEP_VS; 112 scoop_devs[skt->nr].keep_vs = NO_KEEP_VS;
115 } 113 }
116 else if (!(keep_vs & NO_KEEP_VS)) { 114 else if (!(scoop_devs[skt->nr].keep_vs & NO_KEEP_VS)) {
117 /* keep vs1,vs2 */ 115 /* keep vs1,vs2 */
118 write_scoop_reg(&corgiscoop_device.dev, SCOOP_CDR, 0x0000); 116 write_scoop_reg(scoop, SCOOP_CDR, 0x0000);
119 csr |= keep_vs; 117 csr |= scoop_devs[skt->nr].keep_vs;
120 } 118 }
121 else if (cpr & 0x0003) { 119 else if (cpr & 0x0003) {
122 /* power on */ 120 /* power on */
123 write_scoop_reg(&corgiscoop_device.dev, SCOOP_CDR, 0x0000); 121 write_scoop_reg(scoop, SCOOP_CDR, 0x0000);
124 keep_vs = (csr & 0x00C0); 122 scoop_devs[skt->nr].keep_vs = (csr & 0x00C0);
125 } 123 }
126 else { 124 else {
127 /* card detect */ 125 /* card detect */
128 write_scoop_reg(&corgiscoop_device.dev, SCOOP_CDR, 0x0002); 126 write_scoop_reg(scoop, SCOOP_CDR, 0x0002);
129 } 127 }
130 128
131 state->detect = (csr & 0x0004) ? 0 : 1; 129 state->detect = (csr & 0x0004) ? 0 : 1;
@@ -147,6 +145,7 @@ static int sharpsl_pcmcia_configure_socket(struct soc_pcmcia_socket *skt,
147 const socket_state_t *state) 145 const socket_state_t *state)
148{ 146{
149 unsigned long flags; 147 unsigned long flags;
148 struct device *scoop = scoop_devs[skt->nr].dev;
150 149
151 unsigned short cpr, ncpr, ccr, nccr, mcr, nmcr, imr, nimr; 150 unsigned short cpr, ncpr, ccr, nccr, mcr, nmcr, imr, nimr;
152 151
@@ -166,10 +165,10 @@ static int sharpsl_pcmcia_configure_socket(struct soc_pcmcia_socket *skt,
166 165
167 local_irq_save(flags); 166 local_irq_save(flags);
168 167
169 nmcr = (mcr = read_scoop_reg(&corgiscoop_device.dev, SCOOP_MCR)) & ~0x0010; 168 nmcr = (mcr = read_scoop_reg(scoop, SCOOP_MCR)) & ~0x0010;
170 ncpr = (cpr = read_scoop_reg(&corgiscoop_device.dev, SCOOP_CPR)) & ~0x0083; 169 ncpr = (cpr = read_scoop_reg(scoop, SCOOP_CPR)) & ~0x0083;
171 nccr = (ccr = read_scoop_reg(&corgiscoop_device.dev, SCOOP_CCR)) & ~0x0080; 170 nccr = (ccr = read_scoop_reg(scoop, SCOOP_CCR)) & ~0x0080;
172 nimr = (imr = read_scoop_reg(&corgiscoop_device.dev, SCOOP_IMR)) & ~0x003E; 171 nimr = (imr = read_scoop_reg(scoop, SCOOP_IMR)) & ~0x003E;
173 172
174 ncpr |= (state->Vcc == 33) ? 0x0001 : 173 ncpr |= (state->Vcc == 33) ? 0x0001 :
175 (state->Vcc == 50) ? 0x0002 : 0; 174 (state->Vcc == 50) ? 0x0002 : 0;
@@ -184,22 +183,22 @@ static int sharpsl_pcmcia_configure_socket(struct soc_pcmcia_socket *skt,
184 ((skt->status&SS_WRPROT) ? 0x0008 : 0); 183 ((skt->status&SS_WRPROT) ? 0x0008 : 0);
185 184
186 if (!(ncpr & 0x0003)) { 185 if (!(ncpr & 0x0003)) {
187 keep_rd = 0; 186 scoop_devs[skt->nr].keep_rd = 0;
188 } else if (!keep_rd) { 187 } else if (!scoop_devs[skt->nr].keep_rd) {
189 if (nccr & 0x0080) 188 if (nccr & 0x0080)
190 keep_rd = 1; 189 scoop_devs[skt->nr].keep_rd = 1;
191 else 190 else
192 nccr |= 0x0080; 191 nccr |= 0x0080;
193 } 192 }
194 193
195 if (mcr != nmcr) 194 if (mcr != nmcr)
196 write_scoop_reg(&corgiscoop_device.dev, SCOOP_MCR, nmcr); 195 write_scoop_reg(scoop, SCOOP_MCR, nmcr);
197 if (cpr != ncpr) 196 if (cpr != ncpr)
198 write_scoop_reg(&corgiscoop_device.dev, SCOOP_CPR, ncpr); 197 write_scoop_reg(scoop, SCOOP_CPR, ncpr);
199 if (ccr != nccr) 198 if (ccr != nccr)
200 write_scoop_reg(&corgiscoop_device.dev, SCOOP_CCR, nccr); 199 write_scoop_reg(scoop, SCOOP_CCR, nccr);
201 if (imr != nimr) 200 if (imr != nimr)
202 write_scoop_reg(&corgiscoop_device.dev, SCOOP_IMR, nimr); 201 write_scoop_reg(scoop, SCOOP_IMR, nimr);
203 202
204 local_irq_restore(flags); 203 local_irq_restore(flags);
205 204
@@ -208,10 +207,18 @@ static int sharpsl_pcmcia_configure_socket(struct soc_pcmcia_socket *skt,
208 207
209static void sharpsl_pcmcia_socket_init(struct soc_pcmcia_socket *skt) 208static void sharpsl_pcmcia_socket_init(struct soc_pcmcia_socket *skt)
210{ 209{
210 sharpsl_pcmcia_init_reset(&scoop_devs[skt->nr]);
211
212 /* Enable interrupt */
213 write_scoop_reg(scoop_devs[skt->nr].dev, SCOOP_IMR, 0x00C0);
214 write_scoop_reg(scoop_devs[skt->nr].dev, SCOOP_MCR, 0x0101);
215 scoop_devs[skt->nr].keep_vs = NO_KEEP_VS;
211} 216}
212 217
213static void sharpsl_pcmcia_socket_suspend(struct soc_pcmcia_socket *skt) 218static void sharpsl_pcmcia_socket_suspend(struct soc_pcmcia_socket *skt)
214{ 219{
220 /* CF_BUS_OFF */
221 sharpsl_pcmcia_init_reset(&scoop_devs[skt->nr]);
215} 222}
216 223
217static struct pcmcia_low_level sharpsl_pcmcia_ops = { 224static struct pcmcia_low_level sharpsl_pcmcia_ops = {
@@ -223,7 +230,7 @@ static struct pcmcia_low_level sharpsl_pcmcia_ops = {
223 .socket_init = sharpsl_pcmcia_socket_init, 230 .socket_init = sharpsl_pcmcia_socket_init,
224 .socket_suspend = sharpsl_pcmcia_socket_suspend, 231 .socket_suspend = sharpsl_pcmcia_socket_suspend,
225 .first = 0, 232 .first = 0,
226 .nr = 1, 233 .nr = 0,
227}; 234};
228 235
229static struct platform_device *sharpsl_pcmcia_device; 236static struct platform_device *sharpsl_pcmcia_device;
@@ -232,12 +239,15 @@ static int __init sharpsl_pcmcia_init(void)
232{ 239{
233 int ret; 240 int ret;
234 241
242 sharpsl_pcmcia_ops.nr=scoop_num;
235 sharpsl_pcmcia_device = kmalloc(sizeof(*sharpsl_pcmcia_device), GFP_KERNEL); 243 sharpsl_pcmcia_device = kmalloc(sizeof(*sharpsl_pcmcia_device), GFP_KERNEL);
236 if (!sharpsl_pcmcia_device) 244 if (!sharpsl_pcmcia_device)
237 return -ENOMEM; 245 return -ENOMEM;
246
238 memset(sharpsl_pcmcia_device, 0, sizeof(*sharpsl_pcmcia_device)); 247 memset(sharpsl_pcmcia_device, 0, sizeof(*sharpsl_pcmcia_device));
239 sharpsl_pcmcia_device->name = "pxa2xx-pcmcia"; 248 sharpsl_pcmcia_device->name = "pxa2xx-pcmcia";
240 sharpsl_pcmcia_device->dev.platform_data = &sharpsl_pcmcia_ops; 249 sharpsl_pcmcia_device->dev.platform_data = &sharpsl_pcmcia_ops;
250 sharpsl_pcmcia_device->dev.parent=scoop_devs[0].dev;
241 251
242 ret = platform_device_register(sharpsl_pcmcia_device); 252 ret = platform_device_register(sharpsl_pcmcia_device);
243 if (ret) 253 if (ret)