3 * bcm47xx pcmcia driver
5 * Copyright 2004, Broadcom Corporation
8 * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY
9 * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM
10 * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
11 * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE.
13 * Based on sa1100_generic.c from www.handhelds.org,
14 * and au1000_generic.c from oss.sgi.com.
18 #include <linux/module.h>
19 #include <linux/init.h>
20 #include <linux/config.h>
21 #include <linux/delay.h>
22 #include <linux/ioport.h>
23 #include <linux/kernel.h>
24 #include <linux/tqueue.h>
25 #include <linux/timer.h>
27 #include <linux/proc_fs.h>
28 #include <linux/version.h>
29 #include <linux/types.h>
30 #include <linux/vmalloc.h>
32 #include <pcmcia/version.h>
33 #include <pcmcia/cs_types.h>
34 #include <pcmcia/cs.h>
35 #include <pcmcia/ss.h>
36 #include <pcmcia/bulkmem.h>
37 #include <pcmcia/cistpl.h>
38 #include <pcmcia/bus_ops.h>
39 #include "cs_internal.h"
43 #include <asm/system.h>
49 #include "bcm4710pcmcia.h"
52 static int pc_debug
= PCMCIA_DEBUG
;
55 MODULE_DESCRIPTION("Linux PCMCIA Card Services: bcm47xx Socket Controller");
57 /* This structure maintains housekeeping state for each socket, such
58 * as the last known values of the card detect pins, or the Card Services
59 * callback value associated with the socket:
61 static struct bcm47xx_pcmcia_socket
*pcmcia_socket
;
62 static int socket_count
;
65 /* Returned by the low-level PCMCIA interface: */
66 static struct pcmcia_low_level
*pcmcia_low_level
;
68 /* Event poll timer structure */
69 static struct timer_list poll_timer
;
72 /* Prototypes for routines which are used internally: */
74 static int bcm47xx_pcmcia_driver_init(void);
75 static void bcm47xx_pcmcia_driver_shutdown(void);
76 static void bcm47xx_pcmcia_task_handler(void *data
);
77 static void bcm47xx_pcmcia_poll_event(unsigned long data
);
78 static void bcm47xx_pcmcia_interrupt(int irq
, void *dev
, struct pt_regs
*regs
);
79 static struct tq_struct bcm47xx_pcmcia_task
;
82 static int bcm47xx_pcmcia_proc_status(char *buf
, char **start
,
83 off_t pos
, int count
, int *eof
, void *data
);
87 /* Prototypes for operations which are exported to the
88 * in-kernel PCMCIA core:
91 static int bcm47xx_pcmcia_init(unsigned int sock
);
92 static int bcm47xx_pcmcia_suspend(unsigned int sock
);
93 static int bcm47xx_pcmcia_register_callback(unsigned int sock
,
94 void (*handler
)(void *, unsigned int), void *info
);
95 static int bcm47xx_pcmcia_inquire_socket(unsigned int sock
, socket_cap_t
*cap
);
96 static int bcm47xx_pcmcia_get_status(unsigned int sock
, u_int
*value
);
97 static int bcm47xx_pcmcia_get_socket(unsigned int sock
, socket_state_t
*state
);
98 static int bcm47xx_pcmcia_set_socket(unsigned int sock
, socket_state_t
*state
);
99 static int bcm47xx_pcmcia_get_io_map(unsigned int sock
, struct pccard_io_map
*io
);
100 static int bcm47xx_pcmcia_set_io_map(unsigned int sock
, struct pccard_io_map
*io
);
101 static int bcm47xx_pcmcia_get_mem_map(unsigned int sock
, struct pccard_mem_map
*mem
);
102 static int bcm47xx_pcmcia_set_mem_map(unsigned int sock
, struct pccard_mem_map
*mem
);
103 #ifdef CONFIG_PROC_FS
104 static void bcm47xx_pcmcia_proc_setup(unsigned int sock
, struct proc_dir_entry
*base
);
107 static struct pccard_operations bcm47xx_pcmcia_operations
= {
109 bcm47xx_pcmcia_suspend
,
110 bcm47xx_pcmcia_register_callback
,
111 bcm47xx_pcmcia_inquire_socket
,
112 bcm47xx_pcmcia_get_status
,
113 bcm47xx_pcmcia_get_socket
,
114 bcm47xx_pcmcia_set_socket
,
115 bcm47xx_pcmcia_get_io_map
,
116 bcm47xx_pcmcia_set_io_map
,
117 bcm47xx_pcmcia_get_mem_map
,
118 bcm47xx_pcmcia_set_mem_map
,
119 #ifdef CONFIG_PROC_FS
120 bcm47xx_pcmcia_proc_setup
126 * bcm47xx_pcmcia_driver_init()
128 * This routine performs a basic sanity check to ensure that this
129 * kernel has been built with the appropriate board-specific low-level
130 * PCMCIA support, performs low-level PCMCIA initialization, registers
131 * this socket driver with Card Services, and then spawns the daemon
132 * thread which is the real workhorse of the socket driver.
134 * Please see linux/Documentation/arm/SA1100/PCMCIA for more information
135 * on the low-level kernel interface.
137 * Returns: 0 on success, -1 on error
139 static int __init
bcm47xx_pcmcia_driver_init(void)
142 struct pcmcia_init pcmcia_init
;
143 struct pcmcia_state state
;
148 printk("\nBCM47XX PCMCIA (CS release %s)\n", CS_RELEASE
);
150 CardServices(GetCardServicesInfo
, &info
);
152 if (info
.Revision
!= CS_RELEASE_CODE
) {
153 printk(KERN_ERR
"Card Services release codes do not match\n");
157 #ifdef CONFIG_BCM4710
158 pcmcia_low_level
=&bcm4710_pcmcia_ops
;
160 #error Unsupported Broadcom BCM47XX board.
163 pcmcia_init
.handler
=bcm47xx_pcmcia_interrupt
;
165 if ((socket_count
= pcmcia_low_level
->init(&pcmcia_init
)) < 0) {
166 printk(KERN_ERR
"Unable to initialize PCMCIA service.\n");
169 printk("\t%d PCMCIA sockets initialized.\n", socket_count
);
173 kmalloc(sizeof(struct bcm47xx_pcmcia_socket
) * socket_count
,
175 memset(pcmcia_socket
, 0,
176 sizeof(struct bcm47xx_pcmcia_socket
) * socket_count
);
177 if (!pcmcia_socket
) {
178 printk(KERN_ERR
"Card Services can't get memory \n");
182 for (i
= 0; i
< socket_count
; i
++) {
183 if (pcmcia_low_level
->socket_state(i
, &state
) < 0) {
184 printk(KERN_ERR
"Unable to get PCMCIA status\n");
187 pcmcia_socket
[i
].k_state
= state
;
188 pcmcia_socket
[i
].cs_state
.csc_mask
= SS_DETECT
;
191 pcmcia_socket
[i
].virt_io
=
192 (unsigned long)ioremap_nocache(EXTIF_PCMCIA_IOBASE(BCM4710_EXTIF
), 0x1000);
193 /* Substract ioport base which gets added by in/out */
194 pcmcia_socket
[i
].virt_io
-= mips_io_port_base
;
195 pcmcia_socket
[i
].phys_attr
=
196 (unsigned long)EXTIF_PCMCIA_CFGBASE(BCM4710_EXTIF
);
197 pcmcia_socket
[i
].phys_mem
=
198 (unsigned long)EXTIF_PCMCIA_MEMBASE(BCM4710_EXTIF
);
200 printk(KERN_ERR
"bcm4710: socket 1 not supported\n");
205 /* Only advertise as many sockets as we can detect: */
206 if (register_ss_entry(socket_count
, &bcm47xx_pcmcia_operations
) < 0) {
207 printk(KERN_ERR
"Unable to register socket service routine\n");
211 /* Start the event poll timer.
212 * It will reschedule by itself afterwards.
214 bcm47xx_pcmcia_poll_event(0);
216 DEBUG(1, "bcm4710: initialization complete\n");
221 module_init(bcm47xx_pcmcia_driver_init
);
225 * bcm47xx_pcmcia_driver_shutdown()
227 * Invokes the low-level kernel service to free IRQs associated with this
228 * socket controller and reset GPIO edge detection.
230 static void __exit
bcm47xx_pcmcia_driver_shutdown(void)
234 del_timer_sync(&poll_timer
);
235 unregister_ss_entry(&bcm47xx_pcmcia_operations
);
236 pcmcia_low_level
->shutdown();
237 flush_scheduled_tasks();
238 for (i
= 0; i
< socket_count
; i
++) {
239 if (pcmcia_socket
[i
].virt_io
)
240 iounmap((void *)pcmcia_socket
[i
].virt_io
);
241 if (pcmcia_socket
[i
].phys_attr
)
242 iounmap((void *)pcmcia_socket
[i
].phys_attr
);
243 if (pcmcia_socket
[i
].phys_mem
)
244 iounmap((void *)pcmcia_socket
[i
].phys_mem
);
246 DEBUG(1, "bcm4710: shutdown complete\n");
249 module_exit(bcm47xx_pcmcia_driver_shutdown
);
252 * bcm47xx_pcmcia_init()
253 * We perform all of the interesting initialization tasks in
254 * bcm47xx_pcmcia_driver_init().
258 static int bcm47xx_pcmcia_init(unsigned int sock
)
260 DEBUG(1, "%s(): initializing socket %u\n", __FUNCTION__
, sock
);
266 * bcm47xx_pcmcia_suspend()
268 * We don't currently perform any actions on a suspend.
272 static int bcm47xx_pcmcia_suspend(unsigned int sock
)
274 DEBUG(1, "%s(): suspending socket %u\n", __FUNCTION__
, sock
);
281 * bcm47xx_pcmcia_events()
283 * Helper routine to generate a Card Services event mask based on
284 * state information obtained from the kernel low-level PCMCIA layer
285 * in a recent (and previous) sampling. Updates `prev_state'.
287 * Returns: an event mask for the given socket state.
289 static inline unsigned
290 bcm47xx_pcmcia_events(struct pcmcia_state
*state
,
291 struct pcmcia_state
*prev_state
,
292 unsigned int mask
, unsigned int flags
)
294 unsigned int events
=0;
296 if (state
->bvd1
!= prev_state
->bvd1
) {
298 DEBUG(3, "%s(): card BVD1 value %u\n", __FUNCTION__
, state
->bvd1
);
300 events
|= mask
& (flags
& SS_IOCARD
) ? SS_STSCHG
: SS_BATDEAD
;
303 if (state
->bvd2
!= prev_state
->bvd2
) {
305 DEBUG(3, "%s(): card BVD2 value %u\n", __FUNCTION__
, state
->bvd2
);
307 events
|= mask
& (flags
& SS_IOCARD
) ? 0 : SS_BATWARN
;
310 if (state
->detect
!= prev_state
->detect
) {
312 DEBUG(3, "%s(): card detect value %u\n", __FUNCTION__
, state
->detect
);
314 events
|= mask
& SS_DETECT
;
318 if (state
->ready
!= prev_state
->ready
) {
320 DEBUG(3, "%s(): card ready value %u\n", __FUNCTION__
, state
->ready
);
322 events
|= mask
& ((flags
& SS_IOCARD
) ? 0 : SS_READY
);
326 DEBUG(2, "events: %s%s%s%s%s\n",
327 (events
& SS_DETECT
) ? "DETECT " : "",
328 (events
& SS_READY
) ? "READY " : "",
329 (events
& SS_BATDEAD
) ? "BATDEAD " : "",
330 (events
& SS_BATWARN
) ? "BATWARN " : "",
331 (events
& SS_STSCHG
) ? "STSCHG " : "");
340 * bcm47xx_pcmcia_task_handler()
342 * Processes serviceable socket events using the "eventd" thread context.
344 * Event processing (specifically, the invocation of the Card Services event
345 * callback) occurs in this thread rather than in the actual interrupt
346 * handler due to the use of scheduling operations in the PCMCIA core.
348 static void bcm47xx_pcmcia_task_handler(void *data
)
350 struct pcmcia_state state
;
351 int i
, events
, irq_status
;
353 DEBUG(4, "%s(): entering PCMCIA monitoring thread\n", __FUNCTION__
);
355 for (i
= 0; i
< socket_count
; i
++) {
356 if ((irq_status
= pcmcia_low_level
->socket_state(i
, &state
)) < 0)
357 printk(KERN_ERR
"Error in kernel low-level PCMCIA service.\n");
359 events
= bcm47xx_pcmcia_events(&state
,
360 &pcmcia_socket
[i
].k_state
,
361 pcmcia_socket
[i
].cs_state
.csc_mask
,
362 pcmcia_socket
[i
].cs_state
.flags
);
364 if (pcmcia_socket
[i
].handler
!= NULL
) {
365 pcmcia_socket
[i
].handler(pcmcia_socket
[i
].handler_info
,
371 static struct tq_struct bcm47xx_pcmcia_task
= {
372 routine
: bcm47xx_pcmcia_task_handler
377 * bcm47xx_pcmcia_poll_event()
379 * Let's poll for events in addition to IRQs since IRQ only is unreliable...
381 static void bcm47xx_pcmcia_poll_event(unsigned long dummy
)
383 DEBUG(4, "%s(): polling for events\n", __FUNCTION__
);
385 poll_timer
.function
= bcm47xx_pcmcia_poll_event
;
386 poll_timer
.expires
= jiffies
+ BCM47XX_PCMCIA_POLL_PERIOD
;
387 add_timer(&poll_timer
);
388 schedule_task(&bcm47xx_pcmcia_task
);
393 * bcm47xx_pcmcia_interrupt()
395 * Service routine for socket driver interrupts (requested by the
396 * low-level PCMCIA init() operation via bcm47xx_pcmcia_thread()).
398 * The actual interrupt-servicing work is performed by
399 * bcm47xx_pcmcia_task(), largely because the Card Services event-
400 * handling code performs scheduling operations which cannot be
401 * executed from within an interrupt context.
404 bcm47xx_pcmcia_interrupt(int irq
, void *dev
, struct pt_regs
*regs
)
406 DEBUG(3, "%s(): servicing IRQ %d\n", __FUNCTION__
, irq
);
407 schedule_task(&bcm47xx_pcmcia_task
);
412 * bcm47xx_pcmcia_register_callback()
414 * Implements the register_callback() operation for the in-kernel
415 * PCMCIA service (formerly SS_RegisterCallback in Card Services). If
416 * the function pointer `handler' is not NULL, remember the callback
417 * location in the state for `sock', and increment the usage counter
418 * for the driver module. (The callback is invoked from the interrupt
419 * service routine, bcm47xx_pcmcia_interrupt(), to notify Card Services
420 * of interesting events.) Otherwise, clear the callback pointer in the
421 * socket state and decrement the module usage count.
426 bcm47xx_pcmcia_register_callback(unsigned int sock
,
427 void (*handler
)(void *, unsigned int), void *info
)
429 if (handler
== NULL
) {
430 pcmcia_socket
[sock
].handler
= NULL
;
434 pcmcia_socket
[sock
].handler
= handler
;
435 pcmcia_socket
[sock
].handler_info
= info
;
442 * bcm47xx_pcmcia_inquire_socket()
444 * Implements the inquire_socket() operation for the in-kernel PCMCIA
445 * service (formerly SS_InquireSocket in Card Services). Of note is
446 * the setting of the SS_CAP_PAGE_REGS bit in the `features' field of
447 * `cap' to "trick" Card Services into tolerating large "I/O memory"
448 * addresses. Also set is SS_CAP_STATIC_MAP, which disables the memory
449 * resource database check. (Mapped memory is set up within the socket
452 * In conjunction with the STATIC_MAP capability is a new field,
453 * `io_offset', recommended by David Hinds. Rather than go through
454 * the SetIOMap interface (which is not quite suited for communicating
455 * window locations up from the socket driver), we just pass up
456 * an offset which is applied to client-requested base I/O addresses
457 * in alloc_io_space().
459 * Returns: 0 on success, -1 if no pin has been configured for `sock'
462 bcm47xx_pcmcia_inquire_socket(unsigned int sock
, socket_cap_t
*cap
)
464 struct pcmcia_irq_info irq_info
;
466 if (sock
>= socket_count
) {
467 printk(KERN_ERR
"bcm47xx: socket %u not configured\n", sock
);
471 /* SS_CAP_PAGE_REGS: used by setup_cis_mem() in cistpl.c to set the
472 * force_low argument to validate_mem() in rsrc_mgr.c -- since in
473 * general, the mapped * addresses of the PCMCIA memory regions
474 * will not be within 0xffff, setting force_low would be
477 * SS_CAP_STATIC_MAP: don't bother with the (user-configured) memory
478 * resource database; we instead pass up physical address ranges
479 * and allow other parts of Card Services to deal with remapping.
481 * SS_CAP_PCCARD: we can deal with 16-bit PCMCIA & CF cards, but
482 * not 32-bit CardBus devices.
484 cap
->features
= (SS_CAP_PAGE_REGS
| SS_CAP_STATIC_MAP
| SS_CAP_PCCARD
);
486 irq_info
.sock
= sock
;
489 if (pcmcia_low_level
->get_irq_info(&irq_info
) < 0) {
490 printk(KERN_ERR
"Error obtaining IRQ info socket %u\n", sock
);
495 cap
->map_size
= PAGE_SIZE
;
496 cap
->pci_irq
= irq_info
.irq
;
497 cap
->io_offset
= pcmcia_socket
[sock
].virt_io
;
504 * bcm47xx_pcmcia_get_status()
506 * Implements the get_status() operation for the in-kernel PCMCIA
507 * service (formerly SS_GetStatus in Card Services). Essentially just
508 * fills in bits in `status' according to internal driver state or
509 * the value of the voltage detect chipselect register.
511 * As a debugging note, during card startup, the PCMCIA core issues
512 * three set_socket() commands in a row the first with RESET deasserted,
513 * the second with RESET asserted, and the last with RESET deasserted
514 * again. Following the third set_socket(), a get_status() command will
515 * be issued. The kernel is looking for the SS_READY flag (see
516 * setup_socket(), reset_socket(), and unreset_socket() in cs.c).
521 bcm47xx_pcmcia_get_status(unsigned int sock
, unsigned int *status
)
523 struct pcmcia_state state
;
526 if ((pcmcia_low_level
->socket_state(sock
, &state
)) < 0) {
527 printk(KERN_ERR
"Unable to get PCMCIA status from kernel.\n");
531 pcmcia_socket
[sock
].k_state
= state
;
533 *status
= state
.detect
? SS_DETECT
: 0;
535 *status
|= state
.ready
? SS_READY
: 0;
537 /* The power status of individual sockets is not available
538 * explicitly from the hardware, so we just remember the state
539 * and regurgitate it upon request:
541 *status
|= pcmcia_socket
[sock
].cs_state
.Vcc
? SS_POWERON
: 0;
543 if (pcmcia_socket
[sock
].cs_state
.flags
& SS_IOCARD
)
544 *status
|= state
.bvd1
? SS_STSCHG
: 0;
547 *status
|= SS_BATDEAD
;
548 else if (state
.bvd2
== 0)
549 *status
|= SS_BATWARN
;
552 *status
|= state
.vs_3v
? SS_3VCARD
: 0;
554 *status
|= state
.vs_Xv
? SS_XVCARD
: 0;
556 DEBUG(2, "\tstatus: %s%s%s%s%s%s%s%s\n",
557 (*status
&SS_DETECT
)?"DETECT ":"",
558 (*status
&SS_READY
)?"READY ":"",
559 (*status
&SS_BATDEAD
)?"BATDEAD ":"",
560 (*status
&SS_BATWARN
)?"BATWARN ":"",
561 (*status
&SS_POWERON
)?"POWERON ":"",
562 (*status
&SS_STSCHG
)?"STSCHG ":"",
563 (*status
&SS_3VCARD
)?"3VCARD ":"",
564 (*status
&SS_XVCARD
)?"XVCARD ":"");
571 * bcm47xx_pcmcia_get_socket()
573 * Implements the get_socket() operation for the in-kernel PCMCIA
574 * service (formerly SS_GetSocket in Card Services). Not a very
580 bcm47xx_pcmcia_get_socket(unsigned int sock
, socket_state_t
*state
)
582 DEBUG(2, "%s() for sock %u\n", __FUNCTION__
, sock
);
584 /* This information was given to us in an earlier call to set_socket(),
585 * so we're just regurgitating it here:
587 *state
= pcmcia_socket
[sock
].cs_state
;
593 * bcm47xx_pcmcia_set_socket()
595 * Implements the set_socket() operation for the in-kernel PCMCIA
596 * service (formerly SS_SetSocket in Card Services). We more or
597 * less punt all of this work and let the kernel handle the details
598 * of power configuration, reset, &c. We also record the value of
599 * `state' in order to regurgitate it to the PCMCIA core later.
604 bcm47xx_pcmcia_set_socket(unsigned int sock
, socket_state_t
*state
)
606 struct pcmcia_configure configure
;
608 DEBUG(2, "\tmask: %s%s%s%s%s%s\n\tflags: %s%s%s%s%s%s\n"
609 "\tVcc %d Vpp %d irq %d\n",
610 (state
->csc_mask
== 0) ? "<NONE>" : "",
611 (state
->csc_mask
& SS_DETECT
) ? "DETECT " : "",
612 (state
->csc_mask
& SS_READY
) ? "READY " : "",
613 (state
->csc_mask
& SS_BATDEAD
) ? "BATDEAD " : "",
614 (state
->csc_mask
& SS_BATWARN
) ? "BATWARN " : "",
615 (state
->csc_mask
& SS_STSCHG
) ? "STSCHG " : "",
616 (state
->flags
== 0) ? "<NONE>" : "",
617 (state
->flags
& SS_PWR_AUTO
) ? "PWR_AUTO " : "",
618 (state
->flags
& SS_IOCARD
) ? "IOCARD " : "",
619 (state
->flags
& SS_RESET
) ? "RESET " : "",
620 (state
->flags
& SS_SPKR_ENA
) ? "SPKR_ENA " : "",
621 (state
->flags
& SS_OUTPUT_ENA
) ? "OUTPUT_ENA " : "",
622 state
->Vcc
, state
->Vpp
, state
->io_irq
);
624 configure
.sock
= sock
;
625 configure
.vcc
= state
->Vcc
;
626 configure
.vpp
= state
->Vpp
;
627 configure
.output
= (state
->flags
& SS_OUTPUT_ENA
) ? 1 : 0;
628 configure
.speaker
= (state
->flags
& SS_SPKR_ENA
) ? 1 : 0;
629 configure
.reset
= (state
->flags
& SS_RESET
) ? 1 : 0;
631 if (pcmcia_low_level
->configure_socket(&configure
) < 0) {
632 printk(KERN_ERR
"Unable to configure socket %u\n", sock
);
636 pcmcia_socket
[sock
].cs_state
= *state
;
642 * bcm47xx_pcmcia_get_io_map()
644 * Implements the get_io_map() operation for the in-kernel PCMCIA
645 * service (formerly SS_GetIOMap in Card Services). Just returns an
646 * I/O map descriptor which was assigned earlier by a set_io_map().
648 * Returns: 0 on success, -1 if the map index was out of range
651 bcm47xx_pcmcia_get_io_map(unsigned int sock
, struct pccard_io_map
*map
)
653 DEBUG(2, "bcm47xx_pcmcia_get_io_map: sock %d\n", sock
);
655 if (map
->map
>= MAX_IO_WIN
) {
656 printk(KERN_ERR
"%s(): map (%d) out of range\n",
657 __FUNCTION__
, map
->map
);
661 *map
= pcmcia_socket
[sock
].io_map
[map
->map
];
667 * bcm47xx_pcmcia_set_io_map()
669 * Implements the set_io_map() operation for the in-kernel PCMCIA
670 * service (formerly SS_SetIOMap in Card Services). We configure
671 * the map speed as requested, but override the address ranges
672 * supplied by Card Services.
674 * Returns: 0 on success, -1 on error
677 bcm47xx_pcmcia_set_io_map(unsigned int sock
, struct pccard_io_map
*map
)
682 DEBUG(2, "\tmap %u speed %u\n\tstart 0x%08lx stop 0x%08lx\n"
683 "\tflags: %s%s%s%s%s%s%s%s\n",
684 map
->map
, map
->speed
, map
->start
, map
->stop
,
685 (map
->flags
== 0) ? "<NONE>" : "",
686 (map
->flags
& MAP_ACTIVE
) ? "ACTIVE " : "",
687 (map
->flags
& MAP_16BIT
) ? "16BIT " : "",
688 (map
->flags
& MAP_AUTOSZ
) ? "AUTOSZ " : "",
689 (map
->flags
& MAP_0WS
) ? "0WS " : "",
690 (map
->flags
& MAP_WRPROT
) ? "WRPROT " : "",
691 (map
->flags
& MAP_USE_WAIT
) ? "USE_WAIT " : "",
692 (map
->flags
& MAP_PREFETCH
) ? "PREFETCH " : "");
694 if (map
->map
>= MAX_IO_WIN
) {
695 printk(KERN_ERR
"%s(): map (%d) out of range\n",
696 __FUNCTION__
, map
->map
);
700 if (map
->flags
& MAP_ACTIVE
) {
701 speed
= (map
->speed
> 0) ? map
->speed
: BCM47XX_PCMCIA_IO_SPEED
;
702 pcmcia_socket
[sock
].speed_io
= speed
;
707 if (map
->stop
== 1) {
708 map
->stop
= PAGE_SIZE
- 1;
711 map
->start
= pcmcia_socket
[sock
].virt_io
;
712 map
->stop
= map
->start
+ (map
->stop
- start
);
713 pcmcia_socket
[sock
].io_map
[map
->map
] = *map
;
714 DEBUG(2, "set_io_map %d start %x stop %x\n",
715 map
->map
, map
->start
, map
->stop
);
721 * bcm47xx_pcmcia_get_mem_map()
723 * Implements the get_mem_map() operation for the in-kernel PCMCIA
724 * service (formerly SS_GetMemMap in Card Services). Just returns a
725 * memory map descriptor which was assigned earlier by a
726 * set_mem_map() request.
728 * Returns: 0 on success, -1 if the map index was out of range
731 bcm47xx_pcmcia_get_mem_map(unsigned int sock
, struct pccard_mem_map
*map
)
733 DEBUG(2, "%s() for sock %u\n", __FUNCTION__
, sock
);
735 if (map
->map
>= MAX_WIN
) {
736 printk(KERN_ERR
"%s(): map (%d) out of range\n",
737 __FUNCTION__
, map
->map
);
741 *map
= pcmcia_socket
[sock
].mem_map
[map
->map
];
747 * bcm47xx_pcmcia_set_mem_map()
749 * Implements the set_mem_map() operation for the in-kernel PCMCIA
750 * service (formerly SS_SetMemMap in Card Services). We configure
751 * the map speed as requested, but override the address ranges
752 * supplied by Card Services.
754 * Returns: 0 on success, -1 on error
757 bcm47xx_pcmcia_set_mem_map(unsigned int sock
, struct pccard_mem_map
*map
)
763 if (map
->map
>= MAX_WIN
) {
764 printk(KERN_ERR
"%s(): map (%d) out of range\n",
765 __FUNCTION__
, map
->map
);
769 DEBUG(2, "\tmap %u speed %u\n\tsys_start %#lx\n"
770 "\tsys_stop %#lx\n\tcard_start %#x\n"
771 "\tflags: %s%s%s%s%s%s%s%s\n",
772 map
->map
, map
->speed
, map
->sys_start
, map
->sys_stop
,
773 map
->card_start
, (map
->flags
== 0) ? "<NONE>" : "",
774 (map
->flags
& MAP_ACTIVE
) ? "ACTIVE " : "",
775 (map
->flags
& MAP_16BIT
) ? "16BIT " : "",
776 (map
->flags
& MAP_AUTOSZ
) ? "AUTOSZ " : "",
777 (map
->flags
& MAP_0WS
) ? "0WS " : "",
778 (map
->flags
& MAP_WRPROT
) ? "WRPROT " : "",
779 (map
->flags
& MAP_ATTRIB
) ? "ATTRIB " : "",
780 (map
->flags
& MAP_USE_WAIT
) ? "USE_WAIT " : "");
782 if (map
->flags
& MAP_ACTIVE
) {
783 /* When clients issue RequestMap, the access speed is not always
784 * properly configured:
786 speed
= (map
->speed
> 0) ? map
->speed
: BCM47XX_PCMCIA_MEM_SPEED
;
789 if (map
->flags
& MAP_ATTRIB
) {
790 pcmcia_socket
[sock
].speed_attr
= speed
;
792 pcmcia_socket
[sock
].speed_mem
= speed
;
798 start
= map
->sys_start
;
800 if (map
->sys_stop
== 0)
801 map
->sys_stop
= PAGE_SIZE
- 1;
803 if (map
->flags
& MAP_ATTRIB
) {
804 map
->sys_start
= pcmcia_socket
[sock
].phys_attr
+
807 map
->sys_start
= pcmcia_socket
[sock
].phys_mem
+
811 map
->sys_stop
= map
->sys_start
+ (map
->sys_stop
- start
);
812 pcmcia_socket
[sock
].mem_map
[map
->map
] = *map
;
813 restore_flags(flags
);
814 DEBUG(2, "set_mem_map %d start %x stop %x card_start %x\n",
815 map
->map
, map
->sys_start
, map
->sys_stop
,
821 #if defined(CONFIG_PROC_FS)
824 * bcm47xx_pcmcia_proc_setup()
826 * Implements the proc_setup() operation for the in-kernel PCMCIA
827 * service (formerly SS_ProcSetup in Card Services).
829 * Returns: 0 on success, -1 on error
832 bcm47xx_pcmcia_proc_setup(unsigned int sock
, struct proc_dir_entry
*base
)
834 struct proc_dir_entry
*entry
;
836 if ((entry
= create_proc_entry("status", 0, base
)) == NULL
) {
837 printk(KERN_ERR
"Unable to install \"status\" procfs entry\n");
841 entry
->read_proc
= bcm47xx_pcmcia_proc_status
;
842 entry
->data
= (void *)sock
;
847 * bcm47xx_pcmcia_proc_status()
849 * Implements the /proc/bus/pccard/??/status file.
851 * Returns: the number of characters added to the buffer
854 bcm47xx_pcmcia_proc_status(char *buf
, char **start
, off_t pos
,
855 int count
, int *eof
, void *data
)
858 unsigned int sock
= (unsigned int)data
;
860 p
+= sprintf(p
, "k_flags : %s%s%s%s%s%s%s\n",
861 pcmcia_socket
[sock
].k_state
.detect
? "detect " : "",
862 pcmcia_socket
[sock
].k_state
.ready
? "ready " : "",
863 pcmcia_socket
[sock
].k_state
.bvd1
? "bvd1 " : "",
864 pcmcia_socket
[sock
].k_state
.bvd2
? "bvd2 " : "",
865 pcmcia_socket
[sock
].k_state
.wrprot
? "wrprot " : "",
866 pcmcia_socket
[sock
].k_state
.vs_3v
? "vs_3v " : "",
867 pcmcia_socket
[sock
].k_state
.vs_Xv
? "vs_Xv " : "");
869 p
+= sprintf(p
, "status : %s%s%s%s%s%s%s%s%s\n",
870 pcmcia_socket
[sock
].k_state
.detect
? "SS_DETECT " : "",
871 pcmcia_socket
[sock
].k_state
.ready
? "SS_READY " : "",
872 pcmcia_socket
[sock
].cs_state
.Vcc
? "SS_POWERON " : "",
873 pcmcia_socket
[sock
].cs_state
.flags
& SS_IOCARD
? "SS_IOCARD " : "",
874 (pcmcia_socket
[sock
].cs_state
.flags
& SS_IOCARD
&&
875 pcmcia_socket
[sock
].k_state
.bvd1
) ? "SS_STSCHG " : "",
876 ((pcmcia_socket
[sock
].cs_state
.flags
& SS_IOCARD
) == 0 &&
877 (pcmcia_socket
[sock
].k_state
.bvd1
== 0)) ? "SS_BATDEAD " : "",
878 ((pcmcia_socket
[sock
].cs_state
.flags
& SS_IOCARD
) == 0 &&
879 (pcmcia_socket
[sock
].k_state
.bvd2
== 0)) ? "SS_BATWARN " : "",
880 pcmcia_socket
[sock
].k_state
.vs_3v
? "SS_3VCARD " : "",
881 pcmcia_socket
[sock
].k_state
.vs_Xv
? "SS_XVCARD " : "");
883 p
+= sprintf(p
, "mask : %s%s%s%s%s\n",
884 pcmcia_socket
[sock
].cs_state
.csc_mask
& SS_DETECT
? "SS_DETECT " : "",
885 pcmcia_socket
[sock
].cs_state
.csc_mask
& SS_READY
? "SS_READY " : "",
886 pcmcia_socket
[sock
].cs_state
.csc_mask
& SS_BATDEAD
? "SS_BATDEAD " : "",
887 pcmcia_socket
[sock
].cs_state
.csc_mask
& SS_BATWARN
? "SS_BATWARN " : "",
888 pcmcia_socket
[sock
].cs_state
.csc_mask
& SS_STSCHG
? "SS_STSCHG " : "");
890 p
+= sprintf(p
, "cs_flags : %s%s%s%s%s\n",
891 pcmcia_socket
[sock
].cs_state
.flags
& SS_PWR_AUTO
?
893 pcmcia_socket
[sock
].cs_state
.flags
& SS_IOCARD
?
895 pcmcia_socket
[sock
].cs_state
.flags
& SS_RESET
?
897 pcmcia_socket
[sock
].cs_state
.flags
& SS_SPKR_ENA
?
899 pcmcia_socket
[sock
].cs_state
.flags
& SS_OUTPUT_ENA
?
900 "SS_OUTPUT_ENA " : "");
902 p
+= sprintf(p
, "Vcc : %d\n", pcmcia_socket
[sock
].cs_state
.Vcc
);
903 p
+= sprintf(p
, "Vpp : %d\n", pcmcia_socket
[sock
].cs_state
.Vpp
);
904 p
+= sprintf(p
, "irq : %d\n", pcmcia_socket
[sock
].cs_state
.io_irq
);
905 p
+= sprintf(p
, "I/O : %u\n", pcmcia_socket
[sock
].speed_io
);
906 p
+= sprintf(p
, "attribute: %u\n", pcmcia_socket
[sock
].speed_attr
);
907 p
+= sprintf(p
, "common : %u\n", pcmcia_socket
[sock
].speed_mem
);
912 #endif /* defined(CONFIG_PROC_FS) */