diff options
author | Jeff Garzik <jgarzik@pobox.com> | 2005-09-08 05:39:55 -0400 |
---|---|---|
committer | Jeff Garzik <jgarzik@pobox.com> | 2005-09-08 05:39:55 -0400 |
commit | c324b44c34050cf2a9b58830e11c974806bd85d8 (patch) | |
tree | 3ac45a783221283925cd698334a8f5e7dd4c1df8 /drivers/pcmcia | |
parent | 2fcf522509cceea524b6e7ece8fd6759b682175a (diff) | |
parent | caf39e87cc1182f7dae84eefc43ca14d54c78ef9 (diff) |
Merge /spare/repo/linux-2.6/
Diffstat (limited to 'drivers/pcmcia')
-rw-r--r-- | drivers/pcmcia/pxa2xx_base.c | 2 | ||||
-rw-r--r-- | drivers/pcmcia/pxa2xx_mainstone.c | 2 | ||||
-rw-r--r-- | drivers/pcmcia/pxa2xx_sharpsl.c | 116 | ||||
-rw-r--r-- | drivers/pcmcia/sa1100_generic.c | 2 | ||||
-rw-r--r-- | drivers/pcmcia/sa1111_generic.c | 2 | ||||
-rw-r--r-- | drivers/pcmcia/sa11xx_base.c | 2 | ||||
-rw-r--r-- | drivers/pcmcia/topic.h | 17 | ||||
-rw-r--r-- | drivers/pcmcia/yenta_socket.c | 125 | ||||
-rw-r--r-- | drivers/pcmcia/yenta_socket.h | 8 |
9 files changed, 190 insertions, 86 deletions
diff --git a/drivers/pcmcia/pxa2xx_base.c b/drivers/pcmcia/pxa2xx_base.c index 3e23cd461fb1..325c992f7d8f 100644 --- a/drivers/pcmcia/pxa2xx_base.c +++ b/drivers/pcmcia/pxa2xx_base.c | |||
@@ -246,7 +246,7 @@ static void __exit pxa2xx_pcmcia_exit(void) | |||
246 | driver_unregister(&pxa2xx_pcmcia_driver); | 246 | driver_unregister(&pxa2xx_pcmcia_driver); |
247 | } | 247 | } |
248 | 248 | ||
249 | module_init(pxa2xx_pcmcia_init); | 249 | fs_initcall(pxa2xx_pcmcia_init); |
250 | module_exit(pxa2xx_pcmcia_exit); | 250 | module_exit(pxa2xx_pcmcia_exit); |
251 | 251 | ||
252 | MODULE_AUTHOR("Stefan Eletzhofer <stefan.eletzhofer@inquant.de> and Ian Molton <spyro@f2s.com>"); | 252 | MODULE_AUTHOR("Stefan Eletzhofer <stefan.eletzhofer@inquant.de> and Ian Molton <spyro@f2s.com>"); |
diff --git a/drivers/pcmcia/pxa2xx_mainstone.c b/drivers/pcmcia/pxa2xx_mainstone.c index 5309734e1687..bbe69b07ce50 100644 --- a/drivers/pcmcia/pxa2xx_mainstone.c +++ b/drivers/pcmcia/pxa2xx_mainstone.c | |||
@@ -196,7 +196,7 @@ static void __exit mst_pcmcia_exit(void) | |||
196 | platform_device_unregister(mst_pcmcia_device); | 196 | platform_device_unregister(mst_pcmcia_device); |
197 | } | 197 | } |
198 | 198 | ||
199 | module_init(mst_pcmcia_init); | 199 | fs_initcall(mst_pcmcia_init); |
200 | module_exit(mst_pcmcia_exit); | 200 | module_exit(mst_pcmcia_exit); |
201 | 201 | ||
202 | MODULE_LICENSE("GPL"); | 202 | MODULE_LICENSE("GPL"); |
diff --git a/drivers/pcmcia/pxa2xx_sharpsl.c b/drivers/pcmcia/pxa2xx_sharpsl.c index 42efe218867a..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 | ||
32 | static unsigned char keep_vs; | 30 | static void sharpsl_pcmcia_init_reset(struct scoop_pcmcia_dev *scoopdev) |
33 | static unsigned char keep_rd; | ||
34 | |||
35 | static struct pcmcia_irqs irqs[] = { | ||
36 | { 0, CORGI_IRQ_GPIO_CF_CD, "PCMCIA0 CD"}, | ||
37 | }; | ||
38 | |||
39 | static 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 | ||
46 | static int sharpsl_pcmcia_hw_init(struct soc_pcmcia_socket *skt) | 37 | static 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 | ||
91 | static void sharpsl_pcmcia_hw_shutdown(struct soc_pcmcia_socket *skt) | 84 | static 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 | ||
209 | static void sharpsl_pcmcia_socket_init(struct soc_pcmcia_socket *skt) | 208 | static 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 | ||
213 | static void sharpsl_pcmcia_socket_suspend(struct soc_pcmcia_socket *skt) | 218 | static 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 | ||
217 | static struct pcmcia_low_level sharpsl_pcmcia_ops = { | 224 | static 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 | ||
229 | static struct platform_device *sharpsl_pcmcia_device; | 236 | static 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) |
@@ -257,7 +267,7 @@ static void __exit sharpsl_pcmcia_exit(void) | |||
257 | platform_device_unregister(sharpsl_pcmcia_device); | 267 | platform_device_unregister(sharpsl_pcmcia_device); |
258 | } | 268 | } |
259 | 269 | ||
260 | module_init(sharpsl_pcmcia_init); | 270 | fs_initcall(sharpsl_pcmcia_init); |
261 | module_exit(sharpsl_pcmcia_exit); | 271 | module_exit(sharpsl_pcmcia_exit); |
262 | 272 | ||
263 | MODULE_DESCRIPTION("Sharp SL Series PCMCIA Support"); | 273 | MODULE_DESCRIPTION("Sharp SL Series PCMCIA Support"); |
diff --git a/drivers/pcmcia/sa1100_generic.c b/drivers/pcmcia/sa1100_generic.c index e98bb3d80e7c..d4ed508b38be 100644 --- a/drivers/pcmcia/sa1100_generic.c +++ b/drivers/pcmcia/sa1100_generic.c | |||
@@ -126,5 +126,5 @@ MODULE_AUTHOR("John Dorsey <john+@cs.cmu.edu>"); | |||
126 | MODULE_DESCRIPTION("Linux PCMCIA Card Services: SA-11x0 Socket Controller"); | 126 | MODULE_DESCRIPTION("Linux PCMCIA Card Services: SA-11x0 Socket Controller"); |
127 | MODULE_LICENSE("Dual MPL/GPL"); | 127 | MODULE_LICENSE("Dual MPL/GPL"); |
128 | 128 | ||
129 | module_init(sa11x0_pcmcia_init); | 129 | fs_initcall(sa11x0_pcmcia_init); |
130 | module_exit(sa11x0_pcmcia_exit); | 130 | module_exit(sa11x0_pcmcia_exit); |
diff --git a/drivers/pcmcia/sa1111_generic.c b/drivers/pcmcia/sa1111_generic.c index b441f43a6a55..bb90a1448a53 100644 --- a/drivers/pcmcia/sa1111_generic.c +++ b/drivers/pcmcia/sa1111_generic.c | |||
@@ -189,7 +189,7 @@ static void __exit sa1111_drv_pcmcia_exit(void) | |||
189 | sa1111_driver_unregister(&pcmcia_driver); | 189 | sa1111_driver_unregister(&pcmcia_driver); |
190 | } | 190 | } |
191 | 191 | ||
192 | module_init(sa1111_drv_pcmcia_init); | 192 | fs_initcall(sa1111_drv_pcmcia_init); |
193 | module_exit(sa1111_drv_pcmcia_exit); | 193 | module_exit(sa1111_drv_pcmcia_exit); |
194 | 194 | ||
195 | MODULE_DESCRIPTION("SA1111 PCMCIA card socket driver"); | 195 | MODULE_DESCRIPTION("SA1111 PCMCIA card socket driver"); |
diff --git a/drivers/pcmcia/sa11xx_base.c b/drivers/pcmcia/sa11xx_base.c index db04ffb6f68c..59c5d968e9f6 100644 --- a/drivers/pcmcia/sa11xx_base.c +++ b/drivers/pcmcia/sa11xx_base.c | |||
@@ -189,7 +189,7 @@ static int __init sa11xx_pcmcia_init(void) | |||
189 | { | 189 | { |
190 | return 0; | 190 | return 0; |
191 | } | 191 | } |
192 | module_init(sa11xx_pcmcia_init); | 192 | fs_initcall(sa11xx_pcmcia_init); |
193 | 193 | ||
194 | static void __exit sa11xx_pcmcia_exit(void) {} | 194 | static void __exit sa11xx_pcmcia_exit(void) {} |
195 | 195 | ||
diff --git a/drivers/pcmcia/topic.h b/drivers/pcmcia/topic.h index be420bb29113..edccfa5bb400 100644 --- a/drivers/pcmcia/topic.h +++ b/drivers/pcmcia/topic.h | |||
@@ -101,6 +101,8 @@ | |||
101 | #define TOPIC97_AVS_AUDIO_CONTROL 0x02 | 101 | #define TOPIC97_AVS_AUDIO_CONTROL 0x02 |
102 | #define TOPIC97_AVS_VIDEO_CONTROL 0x01 | 102 | #define TOPIC97_AVS_VIDEO_CONTROL 0x01 |
103 | 103 | ||
104 | #define TOPIC_EXCA_IF_CONTROL 0x3e /* 8 bit */ | ||
105 | #define TOPIC_EXCA_IFC_33V_ENA 0x01 | ||
104 | 106 | ||
105 | static void topic97_zoom_video(struct pcmcia_socket *sock, int onoff) | 107 | static void topic97_zoom_video(struct pcmcia_socket *sock, int onoff) |
106 | { | 108 | { |
@@ -137,4 +139,19 @@ static int topic97_override(struct yenta_socket *socket) | |||
137 | return 0; | 139 | return 0; |
138 | } | 140 | } |
139 | 141 | ||
142 | |||
143 | static int topic95_override(struct yenta_socket *socket) | ||
144 | { | ||
145 | u8 fctrl; | ||
146 | |||
147 | /* enable 3.3V support for 16bit cards */ | ||
148 | fctrl = exca_readb(socket, TOPIC_EXCA_IF_CONTROL); | ||
149 | exca_writeb(socket, TOPIC_EXCA_IF_CONTROL, fctrl | TOPIC_EXCA_IFC_33V_ENA); | ||
150 | |||
151 | /* tell yenta to use exca registers to power 16bit cards */ | ||
152 | socket->flags |= YENTA_16BIT_POWER_EXCA | YENTA_16BIT_POWER_DF; | ||
153 | |||
154 | return 0; | ||
155 | } | ||
156 | |||
140 | #endif /* _LINUX_TOPIC_H */ | 157 | #endif /* _LINUX_TOPIC_H */ |
diff --git a/drivers/pcmcia/yenta_socket.c b/drivers/pcmcia/yenta_socket.c index 62fd705203fb..0347a29f297b 100644 --- a/drivers/pcmcia/yenta_socket.c +++ b/drivers/pcmcia/yenta_socket.c | |||
@@ -184,22 +184,52 @@ static int yenta_get_status(struct pcmcia_socket *sock, unsigned int *value) | |||
184 | return 0; | 184 | return 0; |
185 | } | 185 | } |
186 | 186 | ||
187 | static int yenta_Vcc_power(u32 control) | 187 | static void yenta_get_power(struct yenta_socket *socket, socket_state_t *state) |
188 | { | 188 | { |
189 | switch (control & CB_SC_VCC_MASK) { | 189 | if (!(cb_readl(socket, CB_SOCKET_STATE) & CB_CBCARD) && |
190 | case CB_SC_VCC_5V: return 50; | 190 | (socket->flags & YENTA_16BIT_POWER_EXCA)) { |
191 | case CB_SC_VCC_3V: return 33; | 191 | u8 reg, vcc, vpp; |
192 | default: return 0; | 192 | |
193 | } | 193 | reg = exca_readb(socket, I365_POWER); |
194 | } | 194 | vcc = reg & I365_VCC_MASK; |
195 | vpp = reg & I365_VPP1_MASK; | ||
196 | state->Vcc = state->Vpp = 0; | ||
197 | |||
198 | if (socket->flags & YENTA_16BIT_POWER_DF) { | ||
199 | if (vcc == I365_VCC_3V) | ||
200 | state->Vcc = 33; | ||
201 | if (vcc == I365_VCC_5V) | ||
202 | state->Vcc = 50; | ||
203 | if (vpp == I365_VPP1_5V) | ||
204 | state->Vpp = state->Vcc; | ||
205 | if (vpp == I365_VPP1_12V) | ||
206 | state->Vpp = 120; | ||
207 | } else { | ||
208 | if (reg & I365_VCC_5V) { | ||
209 | state->Vcc = 50; | ||
210 | if (vpp == I365_VPP1_5V) | ||
211 | state->Vpp = 50; | ||
212 | if (vpp == I365_VPP1_12V) | ||
213 | state->Vpp = 120; | ||
214 | } | ||
215 | } | ||
216 | } else { | ||
217 | u32 control; | ||
195 | 218 | ||
196 | static int yenta_Vpp_power(u32 control) | 219 | control = cb_readl(socket, CB_SOCKET_CONTROL); |
197 | { | 220 | |
198 | switch (control & CB_SC_VPP_MASK) { | 221 | switch (control & CB_SC_VCC_MASK) { |
199 | case CB_SC_VPP_12V: return 120; | 222 | case CB_SC_VCC_5V: state->Vcc = 50; break; |
200 | case CB_SC_VPP_5V: return 50; | 223 | case CB_SC_VCC_3V: state->Vcc = 33; break; |
201 | case CB_SC_VPP_3V: return 33; | 224 | default: state->Vcc = 0; |
202 | default: return 0; | 225 | } |
226 | |||
227 | switch (control & CB_SC_VPP_MASK) { | ||
228 | case CB_SC_VPP_12V: state->Vpp = 120; break; | ||
229 | case CB_SC_VPP_5V: state->Vpp = 50; break; | ||
230 | case CB_SC_VPP_3V: state->Vpp = 33; break; | ||
231 | default: state->Vpp = 0; | ||
232 | } | ||
203 | } | 233 | } |
204 | } | 234 | } |
205 | 235 | ||
@@ -211,8 +241,7 @@ static int yenta_get_socket(struct pcmcia_socket *sock, socket_state_t *state) | |||
211 | 241 | ||
212 | control = cb_readl(socket, CB_SOCKET_CONTROL); | 242 | control = cb_readl(socket, CB_SOCKET_CONTROL); |
213 | 243 | ||
214 | state->Vcc = yenta_Vcc_power(control); | 244 | yenta_get_power(socket, state); |
215 | state->Vpp = yenta_Vpp_power(control); | ||
216 | state->io_irq = socket->io_irq; | 245 | state->io_irq = socket->io_irq; |
217 | 246 | ||
218 | if (cb_readl(socket, CB_SOCKET_STATE) & CB_CBCARD) { | 247 | if (cb_readl(socket, CB_SOCKET_STATE) & CB_CBCARD) { |
@@ -246,19 +275,54 @@ static int yenta_get_socket(struct pcmcia_socket *sock, socket_state_t *state) | |||
246 | 275 | ||
247 | static void yenta_set_power(struct yenta_socket *socket, socket_state_t *state) | 276 | static void yenta_set_power(struct yenta_socket *socket, socket_state_t *state) |
248 | { | 277 | { |
249 | u32 reg = 0; /* CB_SC_STPCLK? */ | 278 | /* some birdges require to use the ExCA registers to power 16bit cards */ |
250 | switch (state->Vcc) { | 279 | if (!(cb_readl(socket, CB_SOCKET_STATE) & CB_CBCARD) && |
251 | case 33: reg = CB_SC_VCC_3V; break; | 280 | (socket->flags & YENTA_16BIT_POWER_EXCA)) { |
252 | case 50: reg = CB_SC_VCC_5V; break; | 281 | u8 reg, old; |
253 | default: reg = 0; break; | 282 | reg = old = exca_readb(socket, I365_POWER); |
254 | } | 283 | reg &= ~(I365_VCC_MASK | I365_VPP1_MASK | I365_VPP2_MASK); |
255 | switch (state->Vpp) { | 284 | |
256 | case 33: reg |= CB_SC_VPP_3V; break; | 285 | /* i82365SL-DF style */ |
257 | case 50: reg |= CB_SC_VPP_5V; break; | 286 | if (socket->flags & YENTA_16BIT_POWER_DF) { |
258 | case 120: reg |= CB_SC_VPP_12V; break; | 287 | switch (state->Vcc) { |
288 | case 33: reg |= I365_VCC_3V; break; | ||
289 | case 50: reg |= I365_VCC_5V; break; | ||
290 | default: reg = 0; break; | ||
291 | } | ||
292 | switch (state->Vpp) { | ||
293 | case 33: | ||
294 | case 50: reg |= I365_VPP1_5V; break; | ||
295 | case 120: reg |= I365_VPP1_12V; break; | ||
296 | } | ||
297 | } else { | ||
298 | /* i82365SL-B style */ | ||
299 | switch (state->Vcc) { | ||
300 | case 50: reg |= I365_VCC_5V; break; | ||
301 | default: reg = 0; break; | ||
302 | } | ||
303 | switch (state->Vpp) { | ||
304 | case 50: reg |= I365_VPP1_5V | I365_VPP2_5V; break; | ||
305 | case 120: reg |= I365_VPP1_12V | I365_VPP2_12V; break; | ||
306 | } | ||
307 | } | ||
308 | |||
309 | if (reg != old) | ||
310 | exca_writeb(socket, I365_POWER, reg); | ||
311 | } else { | ||
312 | u32 reg = 0; /* CB_SC_STPCLK? */ | ||
313 | switch (state->Vcc) { | ||
314 | case 33: reg = CB_SC_VCC_3V; break; | ||
315 | case 50: reg = CB_SC_VCC_5V; break; | ||
316 | default: reg = 0; break; | ||
317 | } | ||
318 | switch (state->Vpp) { | ||
319 | case 33: reg |= CB_SC_VPP_3V; break; | ||
320 | case 50: reg |= CB_SC_VPP_5V; break; | ||
321 | case 120: reg |= CB_SC_VPP_12V; break; | ||
322 | } | ||
323 | if (reg != cb_readl(socket, CB_SOCKET_CONTROL)) | ||
324 | cb_writel(socket, CB_SOCKET_CONTROL, reg); | ||
259 | } | 325 | } |
260 | if (reg != cb_readl(socket, CB_SOCKET_CONTROL)) | ||
261 | cb_writel(socket, CB_SOCKET_CONTROL, reg); | ||
262 | } | 326 | } |
263 | 327 | ||
264 | static int yenta_set_socket(struct pcmcia_socket *sock, socket_state_t *state) | 328 | static int yenta_set_socket(struct pcmcia_socket *sock, socket_state_t *state) |
@@ -751,6 +815,7 @@ enum { | |||
751 | CARDBUS_TYPE_TI12XX, | 815 | CARDBUS_TYPE_TI12XX, |
752 | CARDBUS_TYPE_TI1250, | 816 | CARDBUS_TYPE_TI1250, |
753 | CARDBUS_TYPE_RICOH, | 817 | CARDBUS_TYPE_RICOH, |
818 | CARDBUS_TYPE_TOPIC95, | ||
754 | CARDBUS_TYPE_TOPIC97, | 819 | CARDBUS_TYPE_TOPIC97, |
755 | CARDBUS_TYPE_O2MICRO, | 820 | CARDBUS_TYPE_O2MICRO, |
756 | }; | 821 | }; |
@@ -789,6 +854,9 @@ static struct cardbus_type cardbus_type[] = { | |||
789 | .save_state = ricoh_save_state, | 854 | .save_state = ricoh_save_state, |
790 | .restore_state = ricoh_restore_state, | 855 | .restore_state = ricoh_restore_state, |
791 | }, | 856 | }, |
857 | [CARDBUS_TYPE_TOPIC95] = { | ||
858 | .override = topic95_override, | ||
859 | }, | ||
792 | [CARDBUS_TYPE_TOPIC97] = { | 860 | [CARDBUS_TYPE_TOPIC97] = { |
793 | .override = topic97_override, | 861 | .override = topic97_override, |
794 | }, | 862 | }, |
@@ -1196,6 +1264,7 @@ static struct pci_device_id yenta_table [] = { | |||
1196 | CB_ID(PCI_VENDOR_ID_RICOH, PCI_DEVICE_ID_RICOH_RL5C476, RICOH), | 1264 | CB_ID(PCI_VENDOR_ID_RICOH, PCI_DEVICE_ID_RICOH_RL5C476, RICOH), |
1197 | CB_ID(PCI_VENDOR_ID_RICOH, PCI_DEVICE_ID_RICOH_RL5C478, RICOH), | 1265 | CB_ID(PCI_VENDOR_ID_RICOH, PCI_DEVICE_ID_RICOH_RL5C478, RICOH), |
1198 | 1266 | ||
1267 | CB_ID(PCI_VENDOR_ID_TOSHIBA, PCI_DEVICE_ID_TOSHIBA_TOPIC95, TOPIC95), | ||
1199 | CB_ID(PCI_VENDOR_ID_TOSHIBA, PCI_DEVICE_ID_TOSHIBA_TOPIC97, TOPIC97), | 1268 | CB_ID(PCI_VENDOR_ID_TOSHIBA, PCI_DEVICE_ID_TOSHIBA_TOPIC97, TOPIC97), |
1200 | CB_ID(PCI_VENDOR_ID_TOSHIBA, PCI_DEVICE_ID_TOSHIBA_TOPIC100, TOPIC97), | 1269 | CB_ID(PCI_VENDOR_ID_TOSHIBA, PCI_DEVICE_ID_TOSHIBA_TOPIC100, TOPIC97), |
1201 | 1270 | ||
diff --git a/drivers/pcmcia/yenta_socket.h b/drivers/pcmcia/yenta_socket.h index 4e637eef2076..4e75e9e258cd 100644 --- a/drivers/pcmcia/yenta_socket.h +++ b/drivers/pcmcia/yenta_socket.h | |||
@@ -95,6 +95,12 @@ | |||
95 | */ | 95 | */ |
96 | #define CB_MEM_PAGE(map) (0x40 + (map)) | 96 | #define CB_MEM_PAGE(map) (0x40 + (map)) |
97 | 97 | ||
98 | |||
99 | /* control how 16bit cards are powered */ | ||
100 | #define YENTA_16BIT_POWER_EXCA 0x00000001 | ||
101 | #define YENTA_16BIT_POWER_DF 0x00000002 | ||
102 | |||
103 | |||
98 | struct yenta_socket; | 104 | struct yenta_socket; |
99 | 105 | ||
100 | struct cardbus_type { | 106 | struct cardbus_type { |
@@ -113,6 +119,8 @@ struct yenta_socket { | |||
113 | struct pcmcia_socket socket; | 119 | struct pcmcia_socket socket; |
114 | struct cardbus_type *type; | 120 | struct cardbus_type *type; |
115 | 121 | ||
122 | u32 flags; | ||
123 | |||
116 | /* for PCI interrupt probing */ | 124 | /* for PCI interrupt probing */ |
117 | unsigned int probe_status; | 125 | unsigned int probe_status; |
118 | 126 | ||