2 * drivers/pcmcia/sa1100_nanoengine.c
4 * PCMCIA implementation routines for BSI nanoEngine.
6 * In order to have a fully functional pcmcia subsystem in a BSE nanoEngine
7 * board you should carefully read this:
8 * http://cambuca.ldhs.cetuc.puc-rio.br/nanoengine/
10 * Copyright (C) 2010 Marcelo Roberto Jimenez <mroberto@cpti.cetuc.puc-rio.br>
12 * Based on original work for kernel 2.4 by
13 * Miguel Freitas <miguel@cpti.cetuc.puc-rio.br>
15 * This program is free software; you can redistribute it and/or modify
16 * it under the terms of the GNU General Public License version 2 as
17 * published by the Free Software Foundation.
20 #include <linux/device.h>
21 #include <linux/errno.h>
22 #include <linux/interrupt.h>
23 #include <linux/irq.h>
24 #include <linux/init.h>
25 #include <linux/kernel.h>
26 #include <linux/module.h>
27 #include <linux/signal.h>
29 #include <asm/mach-types.h>
32 #include <mach/hardware.h>
33 #include <mach/nanoengine.h>
35 #include "sa1100_generic.h"
37 static struct pcmcia_irqs irqs_skt0
[] = {
38 /* socket, IRQ, name */
39 { 0, NANOENGINE_IRQ_GPIO_PC_CD0
, "PC CD0" },
42 static struct pcmcia_irqs irqs_skt1
[] = {
43 /* socket, IRQ, name */
44 { 1, NANOENGINE_IRQ_GPIO_PC_CD1
, "PC CD1" },
47 struct nanoengine_pins
{
50 unsigned clear_outputs
;
51 unsigned transition_pins
;
53 struct pcmcia_irqs
*pcmcia_irqs
;
54 unsigned pcmcia_irqs_size
;
57 static struct nanoengine_pins nano_skts
[] = {
59 .input_pins
= GPIO_PC_READY0
| GPIO_PC_CD0
,
60 .output_pins
= GPIO_PC_RESET0
,
61 .clear_outputs
= GPIO_PC_RESET0
,
62 .transition_pins
= NANOENGINE_IRQ_GPIO_PC_CD0
,
63 .pci_irq
= NANOENGINE_IRQ_GPIO_PC_READY0
,
64 .pcmcia_irqs
= irqs_skt0
,
65 .pcmcia_irqs_size
= ARRAY_SIZE(irqs_skt0
)
67 .input_pins
= GPIO_PC_READY1
| GPIO_PC_CD1
,
68 .output_pins
= GPIO_PC_RESET1
,
69 .clear_outputs
= GPIO_PC_RESET1
,
70 .transition_pins
= NANOENGINE_IRQ_GPIO_PC_CD1
,
71 .pci_irq
= NANOENGINE_IRQ_GPIO_PC_READY1
,
72 .pcmcia_irqs
= irqs_skt1
,
73 .pcmcia_irqs_size
= ARRAY_SIZE(irqs_skt1
)
77 unsigned num_nano_pcmcia_sockets
= ARRAY_SIZE(nano_skts
);
79 static int nanoengine_pcmcia_hw_init(struct soc_pcmcia_socket
*skt
)
83 if (i
>= num_nano_pcmcia_sockets
)
86 GPDR
&= ~nano_skts
[i
].input_pins
;
87 GPDR
|= nano_skts
[i
].output_pins
;
88 GPCR
= nano_skts
[i
].clear_outputs
;
89 set_irq_type(nano_skts
[i
].transition_pins
, IRQ_TYPE_EDGE_BOTH
);
90 skt
->socket
.pci_irq
= nano_skts
[i
].pci_irq
;
92 return soc_pcmcia_request_irqs(skt
,
93 nano_skts
[i
].pcmcia_irqs
, nano_skts
[i
].pcmcia_irqs_size
);
97 * Release all resources.
99 static void nanoengine_pcmcia_hw_shutdown(struct soc_pcmcia_socket
*skt
)
101 unsigned i
= skt
->nr
;
103 if (i
>= num_nano_pcmcia_sockets
)
106 soc_pcmcia_free_irqs(skt
,
107 nano_skts
[i
].pcmcia_irqs
, nano_skts
[i
].pcmcia_irqs_size
);
110 static int nanoengine_pcmcia_configure_socket(
111 struct soc_pcmcia_socket
*skt
, const socket_state_t
*state
)
114 unsigned i
= skt
->nr
;
116 if (i
>= num_nano_pcmcia_sockets
)
121 reset
= GPIO_PC_RESET0
;
124 reset
= GPIO_PC_RESET1
;
130 if (state
->flags
& SS_RESET
)
138 static void nanoengine_pcmcia_socket_state(
139 struct soc_pcmcia_socket
*skt
, struct pcmcia_state
*state
)
141 unsigned long levels
= GPLR
;
142 unsigned i
= skt
->nr
;
144 if (i
>= num_nano_pcmcia_sockets
)
147 memset(state
, 0, sizeof(struct pcmcia_state
));
150 state
->ready
= (levels
& GPIO_PC_READY0
) ? 1 : 0;
151 state
->detect
= !(levels
& GPIO_PC_CD0
) ? 1 : 0;
154 state
->ready
= (levels
& GPIO_PC_READY1
) ? 1 : 0;
155 state
->detect
= !(levels
& GPIO_PC_CD1
) ? 1 : 0;
162 state
->wrprot
= 0; /* Not available */
163 state
->vs_3v
= 1; /* Can only apply 3.3V */
168 * Enable card status IRQs on (re-)initialisation. This can
169 * be called at initialisation, power management event, or
172 static void nanoengine_pcmcia_socket_init(struct soc_pcmcia_socket
*skt
)
174 unsigned i
= skt
->nr
;
176 if (i
>= num_nano_pcmcia_sockets
)
179 soc_pcmcia_enable_irqs(skt
,
180 nano_skts
[i
].pcmcia_irqs
, nano_skts
[i
].pcmcia_irqs_size
);
184 * Disable card status IRQs on suspend.
186 static void nanoengine_pcmcia_socket_suspend(struct soc_pcmcia_socket
*skt
)
188 unsigned i
= skt
->nr
;
190 if (i
>= num_nano_pcmcia_sockets
)
193 soc_pcmcia_disable_irqs(skt
,
194 nano_skts
[i
].pcmcia_irqs
, nano_skts
[i
].pcmcia_irqs_size
);
197 static struct pcmcia_low_level nanoengine_pcmcia_ops
= {
198 .owner
= THIS_MODULE
,
200 .hw_init
= nanoengine_pcmcia_hw_init
,
201 .hw_shutdown
= nanoengine_pcmcia_hw_shutdown
,
203 .configure_socket
= nanoengine_pcmcia_configure_socket
,
204 .socket_state
= nanoengine_pcmcia_socket_state
,
205 .socket_init
= nanoengine_pcmcia_socket_init
,
206 .socket_suspend
= nanoengine_pcmcia_socket_suspend
,
209 int pcmcia_nanoengine_init(struct device
*dev
)
213 if (machine_is_nanoengine())
214 ret
= sa11xx_drv_pcmcia_probe(
215 dev
, &nanoengine_pcmcia_ops
, 0, 2);