aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pcmcia
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/pcmcia')
-rw-r--r--drivers/pcmcia/Kconfig7
-rw-r--r--drivers/pcmcia/Makefile1
-rw-r--r--drivers/pcmcia/cs.c9
-rw-r--r--drivers/pcmcia/cs_internal.h4
-rw-r--r--drivers/pcmcia/ds.c34
-rw-r--r--drivers/pcmcia/omap_cf.c373
-rw-r--r--drivers/pcmcia/pcmcia_resource.c11
-rw-r--r--drivers/pcmcia/yenta_socket.c47
8 files changed, 442 insertions, 44 deletions
diff --git a/drivers/pcmcia/Kconfig b/drivers/pcmcia/Kconfig
index 6485f75d2fb3..ddc741e6ecbf 100644
--- a/drivers/pcmcia/Kconfig
+++ b/drivers/pcmcia/Kconfig
@@ -221,6 +221,13 @@ config PCMCIA_VRC4173
221 tristate "NEC VRC4173 CARDU support" 221 tristate "NEC VRC4173 CARDU support"
222 depends on CPU_VR41XX && PCI && PCMCIA 222 depends on CPU_VR41XX && PCI && PCMCIA
223 223
224config OMAP_CF
225 tristate "OMAP CompactFlash Controller"
226 depends on PCMCIA && ARCH_OMAP16XX
227 help
228 Say Y here to support the CompactFlash controller on OMAP.
229 Note that this doesn't support "True IDE" mode.
230
224config PCCARD_NONSTATIC 231config PCCARD_NONSTATIC
225 tristate 232 tristate
226 233
diff --git a/drivers/pcmcia/Makefile b/drivers/pcmcia/Makefile
index ef694c74dfb7..a41fbb38fdcb 100644
--- a/drivers/pcmcia/Makefile
+++ b/drivers/pcmcia/Makefile
@@ -34,6 +34,7 @@ obj-$(CONFIG_M32R_CFC) += m32r_cfc.o
34obj-$(CONFIG_PCMCIA_AU1X00) += au1x00_ss.o 34obj-$(CONFIG_PCMCIA_AU1X00) += au1x00_ss.o
35obj-$(CONFIG_PCMCIA_VRC4171) += vrc4171_card.o 35obj-$(CONFIG_PCMCIA_VRC4171) += vrc4171_card.o
36obj-$(CONFIG_PCMCIA_VRC4173) += vrc4173_cardu.o 36obj-$(CONFIG_PCMCIA_VRC4173) += vrc4173_cardu.o
37obj-$(CONFIG_OMAP_CF) += omap_cf.o
37 38
38sa11xx_core-y += soc_common.o sa11xx_base.o 39sa11xx_core-y += soc_common.o sa11xx_base.o
39pxa2xx_core-y += soc_common.o pxa2xx_base.o 40pxa2xx_core-y += soc_common.o pxa2xx_base.o
diff --git a/drivers/pcmcia/cs.c b/drivers/pcmcia/cs.c
index e39178fc59d0..fabd3529cebc 100644
--- a/drivers/pcmcia/cs.c
+++ b/drivers/pcmcia/cs.c
@@ -654,9 +654,10 @@ static int pccardd(void *__skt)
654 skt->thread = NULL; 654 skt->thread = NULL;
655 complete_and_exit(&skt->thread_done, 0); 655 complete_and_exit(&skt->thread_done, 0);
656 } 656 }
657 complete(&skt->thread_done);
658 657
659 add_wait_queue(&skt->thread_wait, &wait); 658 add_wait_queue(&skt->thread_wait, &wait);
659 complete(&skt->thread_done);
660
660 for (;;) { 661 for (;;) {
661 unsigned long flags; 662 unsigned long flags;
662 unsigned int events; 663 unsigned int events;
@@ -682,11 +683,11 @@ static int pccardd(void *__skt)
682 continue; 683 continue;
683 } 684 }
684 685
685 schedule();
686 try_to_freeze();
687
688 if (!skt->thread) 686 if (!skt->thread)
689 break; 687 break;
688
689 schedule();
690 try_to_freeze();
690 } 691 }
691 remove_wait_queue(&skt->thread_wait, &wait); 692 remove_wait_queue(&skt->thread_wait, &wait);
692 693
diff --git a/drivers/pcmcia/cs_internal.h b/drivers/pcmcia/cs_internal.h
index 6bbfbd0e02a5..55867bc7f199 100644
--- a/drivers/pcmcia/cs_internal.h
+++ b/drivers/pcmcia/cs_internal.h
@@ -17,9 +17,6 @@
17 17
18#include <linux/config.h> 18#include <linux/config.h>
19 19
20#define CLIENT_MAGIC 0x51E6
21typedef struct client_t client_t;
22
23/* Flags in client state */ 20/* Flags in client state */
24#define CLIENT_CONFIG_LOCKED 0x0001 21#define CLIENT_CONFIG_LOCKED 0x0001
25#define CLIENT_IRQ_REQ 0x0002 22#define CLIENT_IRQ_REQ 0x0002
@@ -45,7 +42,6 @@ typedef struct region_t {
45typedef struct config_t { 42typedef struct config_t {
46 u_int state; 43 u_int state;
47 u_int Attributes; 44 u_int Attributes;
48 u_int Vcc, Vpp1, Vpp2;
49 u_int IntType; 45 u_int IntType;
50 u_int ConfigBase; 46 u_int ConfigBase;
51 u_char Status, Pin, Copy, Option, ExtStatus; 47 u_char Status, Pin, Copy, Option, ExtStatus;
diff --git a/drivers/pcmcia/ds.c b/drivers/pcmcia/ds.c
index 43da2e92d50f..080608c7381a 100644
--- a/drivers/pcmcia/ds.c
+++ b/drivers/pcmcia/ds.c
@@ -354,6 +354,7 @@ static void pcmcia_release_dev(struct device *dev)
354 struct pcmcia_device *p_dev = to_pcmcia_dev(dev); 354 struct pcmcia_device *p_dev = to_pcmcia_dev(dev);
355 ds_dbg(1, "releasing dev %p\n", p_dev); 355 ds_dbg(1, "releasing dev %p\n", p_dev);
356 pcmcia_put_socket(p_dev->socket); 356 pcmcia_put_socket(p_dev->socket);
357 kfree(p_dev->devname);
357 kfree(p_dev); 358 kfree(p_dev);
358} 359}
359 360
@@ -424,9 +425,13 @@ static int pcmcia_device_query(struct pcmcia_device *p_dev)
424{ 425{
425 cistpl_manfid_t manf_id; 426 cistpl_manfid_t manf_id;
426 cistpl_funcid_t func_id; 427 cistpl_funcid_t func_id;
427 cistpl_vers_1_t vers1; 428 cistpl_vers_1_t *vers1;
428 unsigned int i; 429 unsigned int i;
429 430
431 vers1 = kmalloc(sizeof(*vers1), GFP_KERNEL);
432 if (!vers1)
433 return -ENOMEM;
434
430 if (!pccard_read_tuple(p_dev->socket, p_dev->func, 435 if (!pccard_read_tuple(p_dev->socket, p_dev->func,
431 CISTPL_MANFID, &manf_id)) { 436 CISTPL_MANFID, &manf_id)) {
432 p_dev->manf_id = manf_id.manf; 437 p_dev->manf_id = manf_id.manf;
@@ -443,23 +448,30 @@ static int pcmcia_device_query(struct pcmcia_device *p_dev)
443 /* rule of thumb: cards with no FUNCID, but with 448 /* rule of thumb: cards with no FUNCID, but with
444 * common memory device geometry information, are 449 * common memory device geometry information, are
445 * probably memory cards (from pcmcia-cs) */ 450 * probably memory cards (from pcmcia-cs) */
446 cistpl_device_geo_t devgeo; 451 cistpl_device_geo_t *devgeo;
452
453 devgeo = kmalloc(sizeof(*devgeo), GFP_KERNEL);
454 if (!devgeo) {
455 kfree(vers1);
456 return -ENOMEM;
457 }
447 if (!pccard_read_tuple(p_dev->socket, p_dev->func, 458 if (!pccard_read_tuple(p_dev->socket, p_dev->func,
448 CISTPL_DEVICE_GEO, &devgeo)) { 459 CISTPL_DEVICE_GEO, devgeo)) {
449 ds_dbg(0, "mem device geometry probably means " 460 ds_dbg(0, "mem device geometry probably means "
450 "FUNCID_MEMORY\n"); 461 "FUNCID_MEMORY\n");
451 p_dev->func_id = CISTPL_FUNCID_MEMORY; 462 p_dev->func_id = CISTPL_FUNCID_MEMORY;
452 p_dev->has_func_id = 1; 463 p_dev->has_func_id = 1;
453 } 464 }
465 kfree(devgeo);
454 } 466 }
455 467
456 if (!pccard_read_tuple(p_dev->socket, p_dev->func, CISTPL_VERS_1, 468 if (!pccard_read_tuple(p_dev->socket, p_dev->func, CISTPL_VERS_1,
457 &vers1)) { 469 vers1)) {
458 for (i=0; i < vers1.ns; i++) { 470 for (i=0; i < vers1->ns; i++) {
459 char *tmp; 471 char *tmp;
460 unsigned int length; 472 unsigned int length;
461 473
462 tmp = vers1.str + vers1.ofs[i]; 474 tmp = vers1->str + vers1->ofs[i];
463 475
464 length = strlen(tmp) + 1; 476 length = strlen(tmp) + 1;
465 if ((length < 3) || (length > 255)) 477 if ((length < 3) || (length > 255))
@@ -475,6 +487,7 @@ static int pcmcia_device_query(struct pcmcia_device *p_dev)
475 } 487 }
476 } 488 }
477 489
490 kfree(vers1);
478 return 0; 491 return 0;
479} 492}
480 493
@@ -492,6 +505,7 @@ struct pcmcia_device * pcmcia_device_add(struct pcmcia_socket *s, unsigned int f
492{ 505{
493 struct pcmcia_device *p_dev; 506 struct pcmcia_device *p_dev;
494 unsigned long flags; 507 unsigned long flags;
508 int bus_id_len;
495 509
496 s = pcmcia_get_socket(s); 510 s = pcmcia_get_socket(s);
497 if (!s) 511 if (!s)
@@ -515,7 +529,12 @@ struct pcmcia_device * pcmcia_device_add(struct pcmcia_socket *s, unsigned int f
515 p_dev->dev.bus = &pcmcia_bus_type; 529 p_dev->dev.bus = &pcmcia_bus_type;
516 p_dev->dev.parent = s->dev.dev; 530 p_dev->dev.parent = s->dev.dev;
517 p_dev->dev.release = pcmcia_release_dev; 531 p_dev->dev.release = pcmcia_release_dev;
518 sprintf (p_dev->dev.bus_id, "%d.%d", p_dev->socket->sock, p_dev->device_no); 532 bus_id_len = sprintf (p_dev->dev.bus_id, "%d.%d", p_dev->socket->sock, p_dev->device_no);
533
534 p_dev->devname = kmalloc(6 + bus_id_len + 1, GFP_KERNEL);
535 if (!p_dev->devname)
536 goto err_free;
537 sprintf (p_dev->devname, "pcmcia%s", p_dev->dev.bus_id);
519 538
520 /* compat */ 539 /* compat */
521 p_dev->state = CLIENT_UNBOUND; 540 p_dev->state = CLIENT_UNBOUND;
@@ -540,6 +559,7 @@ struct pcmcia_device * pcmcia_device_add(struct pcmcia_socket *s, unsigned int f
540 return p_dev; 559 return p_dev;
541 560
542 err_free: 561 err_free:
562 kfree(p_dev->devname);
543 kfree(p_dev); 563 kfree(p_dev);
544 s->device_count--; 564 s->device_count--;
545 err_put: 565 err_put:
diff --git a/drivers/pcmcia/omap_cf.c b/drivers/pcmcia/omap_cf.c
new file mode 100644
index 000000000000..08d1c9288264
--- /dev/null
+++ b/drivers/pcmcia/omap_cf.c
@@ -0,0 +1,373 @@
1/*
2 * omap_cf.c -- OMAP 16xx CompactFlash controller driver
3 *
4 * Copyright (c) 2005 David Brownell
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 */
11
12#include <linux/module.h>
13#include <linux/kernel.h>
14#include <linux/sched.h>
15#include <linux/device.h>
16#include <linux/errno.h>
17#include <linux/init.h>
18#include <linux/delay.h>
19#include <linux/interrupt.h>
20
21#include <pcmcia/ss.h>
22
23#include <asm/hardware.h>
24#include <asm/io.h>
25#include <asm/mach-types.h>
26#include <asm/sizes.h>
27
28#include <asm/arch/mux.h>
29#include <asm/arch/tc.h>
30
31
32/* NOTE: don't expect this to support many I/O cards. The 16xx chips have
33 * hard-wired timings to support Compact Flash memory cards; they won't work
34 * with various other devices (like WLAN adapters) without some external
35 * logic to help out.
36 *
37 * NOTE: CF controller docs disagree with address space docs as to where
38 * CF_BASE really lives; this is a doc erratum.
39 */
40#define CF_BASE 0xfffe2800
41
42/* status; read after IRQ */
43#define CF_STATUS_REG __REG16(CF_BASE + 0x00)
44# define CF_STATUS_BAD_READ (1 << 2)
45# define CF_STATUS_BAD_WRITE (1 << 1)
46# define CF_STATUS_CARD_DETECT (1 << 0)
47
48/* which chipselect (CS0..CS3) is used for CF (active low) */
49#define CF_CFG_REG __REG16(CF_BASE + 0x02)
50
51/* card reset */
52#define CF_CONTROL_REG __REG16(CF_BASE + 0x04)
53# define CF_CONTROL_RESET (1 << 0)
54
55#define omap_cf_present() (!(CF_STATUS_REG & CF_STATUS_CARD_DETECT))
56
57/*--------------------------------------------------------------------------*/
58
59static const char driver_name[] = "omap_cf";
60
61struct omap_cf_socket {
62 struct pcmcia_socket socket;
63
64 struct timer_list timer;
65 unsigned present:1;
66 unsigned active:1;
67
68 struct platform_device *pdev;
69 unsigned long phys_cf;
70 u_int irq;
71};
72
73#define POLL_INTERVAL (2 * HZ)
74
75#define SZ_2K (2 * SZ_1K)
76
77/*--------------------------------------------------------------------------*/
78
79static int omap_cf_ss_init(struct pcmcia_socket *s)
80{
81 return 0;
82}
83
84/* the timer is primarily to kick this socket's pccardd */
85static void omap_cf_timer(unsigned long _cf)
86{
87 struct omap_cf_socket *cf = (void *) _cf;
88 unsigned present = omap_cf_present();
89
90 if (present != cf->present) {
91 cf->present = present;
92 pr_debug("%s: card %s\n", driver_name,
93 present ? "present" : "gone");
94 pcmcia_parse_events(&cf->socket, SS_DETECT);
95 }
96
97 if (cf->active)
98 mod_timer(&cf->timer, jiffies + POLL_INTERVAL);
99}
100
101/* This irq handler prevents "irqNNN: nobody cared" messages as drivers
102 * claim the card's IRQ. It may also detect some card insertions, but
103 * not removals; it can't always eliminate timer irqs.
104 */
105static irqreturn_t omap_cf_irq(int irq, void *_cf, struct pt_regs *r)
106{
107 omap_cf_timer((unsigned long)_cf);
108 return IRQ_HANDLED;
109}
110
111static int omap_cf_get_status(struct pcmcia_socket *s, u_int *sp)
112{
113 if (!sp)
114 return -EINVAL;
115
116 /* FIXME power management should probably be board-specific:
117 * - 3VCARD vs XVCARD (OSK only handles 3VCARD)
118 * - POWERON (switched on/off by set_socket)
119 */
120 if (omap_cf_present()) {
121 struct omap_cf_socket *cf;
122
123 *sp = SS_READY | SS_DETECT | SS_POWERON | SS_3VCARD;
124 cf = container_of(s, struct omap_cf_socket, socket);
125 s->irq.AssignedIRQ = cf->irq;
126 } else
127 *sp = 0;
128 return 0;
129}
130
131static int
132omap_cf_set_socket(struct pcmcia_socket *sock, struct socket_state_t *s)
133{
134 u16 control;
135
136 /* FIXME some non-OSK boards will support power switching */
137 switch (s->Vcc) {
138 case 0:
139 case 33:
140 break;
141 default:
142 return -EINVAL;
143 }
144
145 control = CF_CONTROL_REG;
146 if (s->flags & SS_RESET)
147 CF_CONTROL_REG = CF_CONTROL_RESET;
148 else
149 CF_CONTROL_REG = 0;
150
151 pr_debug("%s: Vcc %d, io_irq %d, flags %04x csc %04x\n",
152 driver_name, s->Vcc, s->io_irq, s->flags, s->csc_mask);
153
154 return 0;
155}
156
157static int omap_cf_ss_suspend(struct pcmcia_socket *s)
158{
159 pr_debug("%s: %s\n", driver_name, __FUNCTION__);
160 return omap_cf_set_socket(s, &dead_socket);
161}
162
163/* regions are 2K each: mem, attrib, io (and reserved-for-ide) */
164
165static int
166omap_cf_set_io_map(struct pcmcia_socket *s, struct pccard_io_map *io)
167{
168 struct omap_cf_socket *cf;
169
170 cf = container_of(s, struct omap_cf_socket, socket);
171 io->flags &= MAP_ACTIVE|MAP_ATTRIB|MAP_16BIT;
172 io->start = cf->phys_cf + SZ_4K;
173 io->stop = io->start + SZ_2K - 1;
174 return 0;
175}
176
177static int
178omap_cf_set_mem_map(struct pcmcia_socket *s, struct pccard_mem_map *map)
179{
180 struct omap_cf_socket *cf;
181
182 if (map->card_start)
183 return -EINVAL;
184 cf = container_of(s, struct omap_cf_socket, socket);
185 map->static_start = cf->phys_cf;
186 map->flags &= MAP_ACTIVE|MAP_ATTRIB|MAP_16BIT;
187 if (map->flags & MAP_ATTRIB)
188 map->static_start += SZ_2K;
189 return 0;
190}
191
192static struct pccard_operations omap_cf_ops = {
193 .init = omap_cf_ss_init,
194 .suspend = omap_cf_ss_suspend,
195 .get_status = omap_cf_get_status,
196 .set_socket = omap_cf_set_socket,
197 .set_io_map = omap_cf_set_io_map,
198 .set_mem_map = omap_cf_set_mem_map,
199};
200
201/*--------------------------------------------------------------------------*/
202
203/*
204 * NOTE: right now the only board-specific platform_data is
205 * "what chipselect is used". Boards could want more.
206 */
207
208static int __init omap_cf_probe(struct device *dev)
209{
210 unsigned seg;
211 struct omap_cf_socket *cf;
212 struct platform_device *pdev = to_platform_device(dev);
213 int irq;
214 int status;
215
216 seg = (int) dev->platform_data;
217 if (seg == 0 || seg > 3)
218 return -ENODEV;
219
220 /* either CFLASH.IREQ (INT_1610_CF) or some GPIO */
221 irq = platform_get_irq(pdev, 0);
222 if (!irq)
223 return -EINVAL;
224
225 cf = kcalloc(1, sizeof *cf, GFP_KERNEL);
226 if (!cf)
227 return -ENOMEM;
228 init_timer(&cf->timer);
229 cf->timer.function = omap_cf_timer;
230 cf->timer.data = (unsigned long) cf;
231
232 cf->pdev = pdev;
233 dev_set_drvdata(dev, cf);
234
235 /* this primarily just shuts up irq handling noise */
236 status = request_irq(irq, omap_cf_irq, SA_SHIRQ,
237 driver_name, cf);
238 if (status < 0)
239 goto fail0;
240 cf->irq = irq;
241 cf->socket.pci_irq = irq;
242
243 switch (seg) {
244 /* NOTE: CS0 could be configured too ... */
245 case 1:
246 cf->phys_cf = OMAP_CS1_PHYS;
247 break;
248 case 2:
249 cf->phys_cf = OMAP_CS2_PHYS;
250 break;
251 case 3:
252 cf->phys_cf = omap_cs3_phys();
253 break;
254 default:
255 goto fail1;
256 }
257
258 /* pcmcia layer only remaps "real" memory */
259 cf->socket.io_offset = (unsigned long)
260 ioremap(cf->phys_cf + SZ_4K, SZ_2K);
261 if (!cf->socket.io_offset)
262 goto fail1;
263
264 if (!request_mem_region(cf->phys_cf, SZ_8K, driver_name))
265 goto fail1;
266
267 /* NOTE: CF conflicts with MMC1 */
268 omap_cfg_reg(W11_1610_CF_CD1);
269 omap_cfg_reg(P11_1610_CF_CD2);
270 omap_cfg_reg(R11_1610_CF_IOIS16);
271 omap_cfg_reg(V10_1610_CF_IREQ);
272 omap_cfg_reg(W10_1610_CF_RESET);
273
274 CF_CFG_REG = ~(1 << seg);
275
276 pr_info("%s: cs%d on irq %d\n", driver_name, seg, irq);
277
278 /* NOTE: better EMIFS setup might support more cards; but the
279 * TRM only shows how to affect regular flash signals, not their
280 * CF/PCMCIA variants...
281 */
282 pr_debug("%s: cs%d, previous ccs %08x acs %08x\n", driver_name,
283 seg, EMIFS_CCS(seg), EMIFS_ACS(seg));
284 EMIFS_CCS(seg) = 0x0004a1b3; /* synch mode 4 etc */
285 EMIFS_ACS(seg) = 0x00000000; /* OE hold/setup */
286
287 /* CF uses armxor_ck, which is "always" available */
288
289 pr_debug("%s: sts %04x cfg %04x control %04x %s\n", driver_name,
290 CF_STATUS_REG, CF_CFG_REG, CF_CONTROL_REG,
291 omap_cf_present() ? "present" : "(not present)");
292
293 cf->socket.owner = THIS_MODULE;
294 cf->socket.dev.dev = dev;
295 cf->socket.ops = &omap_cf_ops;
296 cf->socket.resource_ops = &pccard_static_ops;
297 cf->socket.features = SS_CAP_PCCARD | SS_CAP_STATIC_MAP
298 | SS_CAP_MEM_ALIGN;
299 cf->socket.map_size = SZ_2K;
300
301 status = pcmcia_register_socket(&cf->socket);
302 if (status < 0)
303 goto fail2;
304
305 cf->active = 1;
306 mod_timer(&cf->timer, jiffies + POLL_INTERVAL);
307 return 0;
308
309fail2:
310 iounmap((void __iomem *) cf->socket.io_offset);
311 release_mem_region(cf->phys_cf, SZ_8K);
312fail1:
313 free_irq(irq, cf);
314fail0:
315 kfree(cf);
316 return status;
317}
318
319static int __devexit omap_cf_remove(struct device *dev)
320{
321 struct omap_cf_socket *cf = dev_get_drvdata(dev);
322
323 cf->active = 0;
324 pcmcia_unregister_socket(&cf->socket);
325 del_timer_sync(&cf->timer);
326 iounmap((void __iomem *) cf->socket.io_offset);
327 release_mem_region(cf->phys_cf, SZ_8K);
328 free_irq(cf->irq, cf);
329 kfree(cf);
330 return 0;
331}
332
333static int omap_cf_suspend(struct device *dev, pm_message_t mesg, u32 level)
334{
335 if (level != SUSPEND_SAVE_STATE)
336 return 0;
337 return pcmcia_socket_dev_suspend(dev, mesg);
338}
339
340static int omap_cf_resume(struct device *dev, u32 level)
341{
342 if (level != RESUME_RESTORE_STATE)
343 return 0;
344 return pcmcia_socket_dev_resume(dev);
345}
346
347static struct device_driver omap_cf_driver = {
348 .name = (char *) driver_name,
349 .bus = &platform_bus_type,
350 .probe = omap_cf_probe,
351 .remove = __devexit_p(omap_cf_remove),
352 .suspend = omap_cf_suspend,
353 .resume = omap_cf_resume,
354};
355
356static int __init omap_cf_init(void)
357{
358 if (cpu_is_omap16xx())
359 driver_register(&omap_cf_driver);
360 return 0;
361}
362
363static void __exit omap_cf_exit(void)
364{
365 if (cpu_is_omap16xx())
366 driver_unregister(&omap_cf_driver);
367}
368
369module_init(omap_cf_init);
370module_exit(omap_cf_exit);
371
372MODULE_DESCRIPTION("OMAP CF Driver");
373MODULE_LICENSE("GPL");
diff --git a/drivers/pcmcia/pcmcia_resource.c b/drivers/pcmcia/pcmcia_resource.c
index 599b116d9747..89022ad5b520 100644
--- a/drivers/pcmcia/pcmcia_resource.c
+++ b/drivers/pcmcia/pcmcia_resource.c
@@ -447,7 +447,7 @@ int pcmcia_modify_configuration(struct pcmcia_device *p_dev,
447 (mod->Attributes & CONF_VPP2_CHANGE_VALID)) { 447 (mod->Attributes & CONF_VPP2_CHANGE_VALID)) {
448 if (mod->Vpp1 != mod->Vpp2) 448 if (mod->Vpp1 != mod->Vpp2)
449 return CS_BAD_VPP; 449 return CS_BAD_VPP;
450 c->Vpp1 = c->Vpp2 = s->socket.Vpp = mod->Vpp1; 450 s->socket.Vpp = mod->Vpp1;
451 if (s->ops->set_socket(s, &s->socket)) 451 if (s->ops->set_socket(s, &s->socket))
452 return CS_BAD_VPP; 452 return CS_BAD_VPP;
453 } else if ((mod->Attributes & CONF_VPP1_CHANGE_VALID) || 453 } else if ((mod->Attributes & CONF_VPP1_CHANGE_VALID) ||
@@ -623,8 +623,6 @@ int pcmcia_request_configuration(struct pcmcia_device *p_dev,
623 if (s->ops->set_socket(s, &s->socket)) 623 if (s->ops->set_socket(s, &s->socket))
624 return CS_BAD_VPP; 624 return CS_BAD_VPP;
625 625
626 c->Vcc = req->Vcc; c->Vpp1 = c->Vpp2 = req->Vpp1;
627
628 /* Pick memory or I/O card, DMA mode, interrupt */ 626 /* Pick memory or I/O card, DMA mode, interrupt */
629 c->IntType = req->IntType; 627 c->IntType = req->IntType;
630 c->Attributes = req->Attributes; 628 c->Attributes = req->Attributes;
@@ -822,7 +820,7 @@ int pcmcia_request_irq(struct pcmcia_device *p_dev, irq_req_t *req)
822 ((req->Attributes & IRQ_TYPE_DYNAMIC_SHARING) || 820 ((req->Attributes & IRQ_TYPE_DYNAMIC_SHARING) ||
823 (s->functions > 1) || 821 (s->functions > 1) ||
824 (irq == s->pci_irq)) ? SA_SHIRQ : 0, 822 (irq == s->pci_irq)) ? SA_SHIRQ : 0,
825 p_dev->dev.bus_id, 823 p_dev->devname,
826 (req->Attributes & IRQ_HANDLE_PRESENT) ? req->Instance : data); 824 (req->Attributes & IRQ_HANDLE_PRESENT) ? req->Instance : data);
827 if (!ret) { 825 if (!ret) {
828 if (!(req->Attributes & IRQ_HANDLE_PRESENT)) 826 if (!(req->Attributes & IRQ_HANDLE_PRESENT))
@@ -832,7 +830,8 @@ int pcmcia_request_irq(struct pcmcia_device *p_dev, irq_req_t *req)
832 } 830 }
833 } 831 }
834#endif 832#endif
835 if (ret) { 833 /* only assign PCI irq if no IRQ already assigned */
834 if (ret && !s->irq.AssignedIRQ) {
836 if (!s->pci_irq) 835 if (!s->pci_irq)
837 return ret; 836 return ret;
838 irq = s->pci_irq; 837 irq = s->pci_irq;
@@ -843,7 +842,7 @@ int pcmcia_request_irq(struct pcmcia_device *p_dev, irq_req_t *req)
843 ((req->Attributes & IRQ_TYPE_DYNAMIC_SHARING) || 842 ((req->Attributes & IRQ_TYPE_DYNAMIC_SHARING) ||
844 (s->functions > 1) || 843 (s->functions > 1) ||
845 (irq == s->pci_irq)) ? SA_SHIRQ : 0, 844 (irq == s->pci_irq)) ? SA_SHIRQ : 0,
846 p_dev->dev.bus_id, req->Instance)) 845 p_dev->devname, req->Instance))
847 return CS_IN_USE; 846 return CS_IN_USE;
848 } 847 }
849 848
diff --git a/drivers/pcmcia/yenta_socket.c b/drivers/pcmcia/yenta_socket.c
index 0347a29f297b..f0997c36c9b7 100644
--- a/drivers/pcmcia/yenta_socket.c
+++ b/drivers/pcmcia/yenta_socket.c
@@ -72,6 +72,7 @@ static inline void cb_writel(struct yenta_socket *socket, unsigned reg, u32 val)
72{ 72{
73 debug("%p %04x %08x\n", socket, reg, val); 73 debug("%p %04x %08x\n", socket, reg, val);
74 writel(val, socket->base + reg); 74 writel(val, socket->base + reg);
75 readl(socket->base + reg); /* avoid problems with PCI write posting */
75} 76}
76 77
77static inline u8 config_readb(struct yenta_socket *socket, unsigned offset) 78static inline u8 config_readb(struct yenta_socket *socket, unsigned offset)
@@ -136,6 +137,7 @@ static inline void exca_writeb(struct yenta_socket *socket, unsigned reg, u8 val
136{ 137{
137 debug("%p %04x %02x\n", socket, reg, val); 138 debug("%p %04x %02x\n", socket, reg, val);
138 writeb(val, socket->base + 0x800 + reg); 139 writeb(val, socket->base + 0x800 + reg);
140 readb(socket->base + 0x800 + reg); /* PCI write posting... */
139} 141}
140 142
141static void exca_writew(struct yenta_socket *socket, unsigned reg, u16 val) 143static void exca_writew(struct yenta_socket *socket, unsigned reg, u16 val)
@@ -143,6 +145,10 @@ static void exca_writew(struct yenta_socket *socket, unsigned reg, u16 val)
143 debug("%p %04x %04x\n", socket, reg, val); 145 debug("%p %04x %04x\n", socket, reg, val);
144 writeb(val, socket->base + 0x800 + reg); 146 writeb(val, socket->base + 0x800 + reg);
145 writeb(val >> 8, socket->base + 0x800 + reg + 1); 147 writeb(val >> 8, socket->base + 0x800 + reg + 1);
148
149 /* PCI write posting... */
150 readb(socket->base + 0x800 + reg);
151 readb(socket->base + 0x800 + reg + 1);
146} 152}
147 153
148/* 154/*
@@ -667,7 +673,7 @@ static int yenta_search_res(struct yenta_socket *socket, struct resource *res,
667 return 0; 673 return 0;
668} 674}
669 675
670static void yenta_allocate_res(struct yenta_socket *socket, int nr, unsigned type, int addr_start, int addr_end) 676static int yenta_allocate_res(struct yenta_socket *socket, int nr, unsigned type, int addr_start, int addr_end)
671{ 677{
672 struct resource *root, *res; 678 struct resource *root, *res;
673 struct pci_bus_region region; 679 struct pci_bus_region region;
@@ -676,7 +682,7 @@ static void yenta_allocate_res(struct yenta_socket *socket, int nr, unsigned typ
676 res = socket->dev->resource + PCI_BRIDGE_RESOURCES + nr; 682 res = socket->dev->resource + PCI_BRIDGE_RESOURCES + nr;
677 /* Already allocated? */ 683 /* Already allocated? */
678 if (res->parent) 684 if (res->parent)
679 return; 685 return 0;
680 686
681 /* The granularity of the memory limit is 4kB, on IO it's 4 bytes */ 687 /* The granularity of the memory limit is 4kB, on IO it's 4 bytes */
682 mask = ~0xfff; 688 mask = ~0xfff;
@@ -692,7 +698,7 @@ static void yenta_allocate_res(struct yenta_socket *socket, int nr, unsigned typ
692 pcibios_bus_to_resource(socket->dev, res, &region); 698 pcibios_bus_to_resource(socket->dev, res, &region);
693 root = pci_find_parent_resource(socket->dev, res); 699 root = pci_find_parent_resource(socket->dev, res);
694 if (root && (request_resource(root, res) == 0)) 700 if (root && (request_resource(root, res) == 0))
695 return; 701 return 0;
696 printk(KERN_INFO "yenta %s: Preassigned resource %d busy or not available, reconfiguring...\n", 702 printk(KERN_INFO "yenta %s: Preassigned resource %d busy or not available, reconfiguring...\n",
697 pci_name(socket->dev), nr); 703 pci_name(socket->dev), nr);
698 } 704 }
@@ -700,35 +706,27 @@ static void yenta_allocate_res(struct yenta_socket *socket, int nr, unsigned typ
700 if (type & IORESOURCE_IO) { 706 if (type & IORESOURCE_IO) {
701 if ((yenta_search_res(socket, res, BRIDGE_IO_MAX)) || 707 if ((yenta_search_res(socket, res, BRIDGE_IO_MAX)) ||
702 (yenta_search_res(socket, res, BRIDGE_IO_ACC)) || 708 (yenta_search_res(socket, res, BRIDGE_IO_ACC)) ||
703 (yenta_search_res(socket, res, BRIDGE_IO_MIN))) { 709 (yenta_search_res(socket, res, BRIDGE_IO_MIN)))
704 config_writel(socket, addr_start, res->start); 710 return 1;
705 config_writel(socket, addr_end, res->end);
706 return;
707 }
708 } else { 711 } else {
709 if (type & IORESOURCE_PREFETCH) { 712 if (type & IORESOURCE_PREFETCH) {
710 if ((yenta_search_res(socket, res, BRIDGE_MEM_MAX)) || 713 if ((yenta_search_res(socket, res, BRIDGE_MEM_MAX)) ||
711 (yenta_search_res(socket, res, BRIDGE_MEM_ACC)) || 714 (yenta_search_res(socket, res, BRIDGE_MEM_ACC)) ||
712 (yenta_search_res(socket, res, BRIDGE_MEM_MIN))) { 715 (yenta_search_res(socket, res, BRIDGE_MEM_MIN)))
713 config_writel(socket, addr_start, res->start); 716 return 1;
714 config_writel(socket, addr_end, res->end);
715 return;
716 }
717 /* Approximating prefetchable by non-prefetchable */ 717 /* Approximating prefetchable by non-prefetchable */
718 res->flags = IORESOURCE_MEM; 718 res->flags = IORESOURCE_MEM;
719 } 719 }
720 if ((yenta_search_res(socket, res, BRIDGE_MEM_MAX)) || 720 if ((yenta_search_res(socket, res, BRIDGE_MEM_MAX)) ||
721 (yenta_search_res(socket, res, BRIDGE_MEM_ACC)) || 721 (yenta_search_res(socket, res, BRIDGE_MEM_ACC)) ||
722 (yenta_search_res(socket, res, BRIDGE_MEM_MIN))) { 722 (yenta_search_res(socket, res, BRIDGE_MEM_MIN)))
723 config_writel(socket, addr_start, res->start); 723 return 1;
724 config_writel(socket, addr_end, res->end);
725 return;
726 }
727 } 724 }
728 725
729 printk(KERN_INFO "yenta %s: no resource of type %x available, trying to continue...\n", 726 printk(KERN_INFO "yenta %s: no resource of type %x available, trying to continue...\n",
730 pci_name(socket->dev), type); 727 pci_name(socket->dev), type);
731 res->start = res->end = res->flags = 0; 728 res->start = res->end = res->flags = 0;
729 return 0;
732} 730}
733 731
734/* 732/*
@@ -736,14 +734,17 @@ static void yenta_allocate_res(struct yenta_socket *socket, int nr, unsigned typ
736 */ 734 */
737static void yenta_allocate_resources(struct yenta_socket *socket) 735static void yenta_allocate_resources(struct yenta_socket *socket)
738{ 736{
739 yenta_allocate_res(socket, 0, IORESOURCE_IO, 737 int program = 0;
738 program += yenta_allocate_res(socket, 0, IORESOURCE_IO,
740 PCI_CB_IO_BASE_0, PCI_CB_IO_LIMIT_0); 739 PCI_CB_IO_BASE_0, PCI_CB_IO_LIMIT_0);
741 yenta_allocate_res(socket, 1, IORESOURCE_IO, 740 program += yenta_allocate_res(socket, 1, IORESOURCE_IO,
742 PCI_CB_IO_BASE_1, PCI_CB_IO_LIMIT_1); 741 PCI_CB_IO_BASE_1, PCI_CB_IO_LIMIT_1);
743 yenta_allocate_res(socket, 2, IORESOURCE_MEM|IORESOURCE_PREFETCH, 742 program += yenta_allocate_res(socket, 2, IORESOURCE_MEM|IORESOURCE_PREFETCH,
744 PCI_CB_MEMORY_BASE_0, PCI_CB_MEMORY_LIMIT_0); 743 PCI_CB_MEMORY_BASE_0, PCI_CB_MEMORY_LIMIT_0);
745 yenta_allocate_res(socket, 3, IORESOURCE_MEM, 744 program += yenta_allocate_res(socket, 3, IORESOURCE_MEM,
746 PCI_CB_MEMORY_BASE_1, PCI_CB_MEMORY_LIMIT_1); 745 PCI_CB_MEMORY_BASE_1, PCI_CB_MEMORY_LIMIT_1);
746 if (program)
747 pci_setup_cardbus(socket->dev->subordinate);
747} 748}
748 749
749 750
@@ -758,7 +759,7 @@ static void yenta_free_resources(struct yenta_socket *socket)
758 res = socket->dev->resource + PCI_BRIDGE_RESOURCES + i; 759 res = socket->dev->resource + PCI_BRIDGE_RESOURCES + i;
759 if (res->start != 0 && res->end != 0) 760 if (res->start != 0 && res->end != 0)
760 release_resource(res); 761 release_resource(res);
761 res->start = res->end = 0; 762 res->start = res->end = res->flags = 0;
762 } 763 }
763} 764}
764 765