aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pcmcia/sa1100_nanoengine.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/pcmcia/sa1100_nanoengine.c')
-rw-r--r--drivers/pcmcia/sa1100_nanoengine.c132
1 files changed, 23 insertions, 109 deletions
diff --git a/drivers/pcmcia/sa1100_nanoengine.c b/drivers/pcmcia/sa1100_nanoengine.c
index 93b9c9ba57c3..35c30ff41e81 100644
--- a/drivers/pcmcia/sa1100_nanoengine.c
+++ b/drivers/pcmcia/sa1100_nanoengine.c
@@ -19,6 +19,7 @@
19 */ 19 */
20#include <linux/device.h> 20#include <linux/device.h>
21#include <linux/errno.h> 21#include <linux/errno.h>
22#include <linux/gpio.h>
22#include <linux/interrupt.h> 23#include <linux/interrupt.h>
23#include <linux/irq.h> 24#include <linux/irq.h>
24#include <linux/init.h> 25#include <linux/init.h>
@@ -34,43 +35,23 @@
34 35
35#include "sa1100_generic.h" 36#include "sa1100_generic.h"
36 37
37static struct pcmcia_irqs irqs_skt0[] = {
38 /* socket, IRQ, name */
39 { 0, NANOENGINE_IRQ_GPIO_PC_CD0, "PC CD0" },
40};
41
42static struct pcmcia_irqs irqs_skt1[] = {
43 /* socket, IRQ, name */
44 { 1, NANOENGINE_IRQ_GPIO_PC_CD1, "PC CD1" },
45};
46
47struct nanoengine_pins { 38struct nanoengine_pins {
48 unsigned input_pins;
49 unsigned output_pins; 39 unsigned output_pins;
50 unsigned clear_outputs; 40 unsigned clear_outputs;
51 unsigned transition_pins; 41 int gpio_rst;
52 unsigned pci_irq; 42 int gpio_cd;
53 struct pcmcia_irqs *pcmcia_irqs; 43 int gpio_rdy;
54 unsigned pcmcia_irqs_size;
55}; 44};
56 45
57static struct nanoengine_pins nano_skts[] = { 46static struct nanoengine_pins nano_skts[] = {
58 { 47 {
59 .input_pins = GPIO_PC_READY0 | GPIO_PC_CD0, 48 .gpio_rst = GPIO_PC_RESET0,
60 .output_pins = GPIO_PC_RESET0, 49 .gpio_cd = GPIO_PC_CD0,
61 .clear_outputs = GPIO_PC_RESET0, 50 .gpio_rdy = GPIO_PC_READY0,
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)
66 }, { 51 }, {
67 .input_pins = GPIO_PC_READY1 | GPIO_PC_CD1, 52 .gpio_rst = GPIO_PC_RESET1,
68 .output_pins = GPIO_PC_RESET1, 53 .gpio_cd = GPIO_PC_CD1,
69 .clear_outputs = GPIO_PC_RESET1, 54 .gpio_rdy = GPIO_PC_READY1,
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)
74 } 55 }
75}; 56};
76 57
@@ -79,58 +60,38 @@ unsigned num_nano_pcmcia_sockets = ARRAY_SIZE(nano_skts);
79static int nanoengine_pcmcia_hw_init(struct soc_pcmcia_socket *skt) 60static int nanoengine_pcmcia_hw_init(struct soc_pcmcia_socket *skt)
80{ 61{
81 unsigned i = skt->nr; 62 unsigned i = skt->nr;
63 int ret;
82 64
83 if (i >= num_nano_pcmcia_sockets) 65 if (i >= num_nano_pcmcia_sockets)
84 return -ENXIO; 66 return -ENXIO;
85 67
86 GPDR &= ~nano_skts[i].input_pins; 68 ret = gpio_request_one(nano_skts[i].gpio_rst, GPIOF_OUT_INIT_LOW,
87 GPDR |= nano_skts[i].output_pins; 69 i ? "PC RST1" : "PC RST0");
88 GPCR = nano_skts[i].clear_outputs; 70 if (ret)
89 irq_set_irq_type(nano_skts[i].transition_pins, IRQ_TYPE_EDGE_BOTH); 71 return ret;
90 skt->socket.pci_irq = nano_skts[i].pci_irq; 72
73 skt->stat[SOC_STAT_CD].gpio = nano_skts[i].gpio_cd;
74 skt->stat[SOC_STAT_CD].name = i ? "PC CD1" : "PC CD0";
75 skt->stat[SOC_STAT_RDY].gpio = nano_skts[i].gpio_rdy;
76 skt->stat[SOC_STAT_RDY].name = i ? "PC RDY1" : "PC RDY0";
91 77
92 return soc_pcmcia_request_irqs(skt, 78 return 0;
93 nano_skts[i].pcmcia_irqs, nano_skts[i].pcmcia_irqs_size);
94} 79}
95 80
96/*
97 * Release all resources.
98 */
99static void nanoengine_pcmcia_hw_shutdown(struct soc_pcmcia_socket *skt) 81static void nanoengine_pcmcia_hw_shutdown(struct soc_pcmcia_socket *skt)
100{ 82{
101 unsigned i = skt->nr; 83 gpio_free(nano_skts[skt->nr].gpio_rst);
102
103 if (i >= num_nano_pcmcia_sockets)
104 return;
105
106 soc_pcmcia_free_irqs(skt,
107 nano_skts[i].pcmcia_irqs, nano_skts[i].pcmcia_irqs_size);
108} 84}
109 85
110static int nanoengine_pcmcia_configure_socket( 86static int nanoengine_pcmcia_configure_socket(
111 struct soc_pcmcia_socket *skt, const socket_state_t *state) 87 struct soc_pcmcia_socket *skt, const socket_state_t *state)
112{ 88{
113 unsigned reset;
114 unsigned i = skt->nr; 89 unsigned i = skt->nr;
115 90
116 if (i >= num_nano_pcmcia_sockets) 91 if (i >= num_nano_pcmcia_sockets)
117 return -ENXIO; 92 return -ENXIO;
118 93
119 switch (i) { 94 gpio_set_value(nano_skts[skt->nr].gpio_rst, !!(state->flags & SS_RESET));
120 case 0:
121 reset = GPIO_PC_RESET0;
122 break;
123 case 1:
124 reset = GPIO_PC_RESET1;
125 break;
126 default:
127 return -ENXIO;
128 }
129
130 if (state->flags & SS_RESET)
131 GPSR = reset;
132 else
133 GPCR = reset;
134 95
135 return 0; 96 return 0;
136} 97}
@@ -138,62 +99,17 @@ static int nanoengine_pcmcia_configure_socket(
138static void nanoengine_pcmcia_socket_state( 99static void nanoengine_pcmcia_socket_state(
139 struct soc_pcmcia_socket *skt, struct pcmcia_state *state) 100 struct soc_pcmcia_socket *skt, struct pcmcia_state *state)
140{ 101{
141 unsigned long levels = GPLR;
142 unsigned i = skt->nr; 102 unsigned i = skt->nr;
143 103
144 if (i >= num_nano_pcmcia_sockets) 104 if (i >= num_nano_pcmcia_sockets)
145 return; 105 return;
146 106
147 memset(state, 0, sizeof(struct pcmcia_state));
148 switch (i) {
149 case 0:
150 state->ready = (levels & GPIO_PC_READY0) ? 1 : 0;
151 state->detect = !(levels & GPIO_PC_CD0) ? 1 : 0;
152 break;
153 case 1:
154 state->ready = (levels & GPIO_PC_READY1) ? 1 : 0;
155 state->detect = !(levels & GPIO_PC_CD1) ? 1 : 0;
156 break;
157 default:
158 return;
159 }
160 state->bvd1 = 1; 107 state->bvd1 = 1;
161 state->bvd2 = 1; 108 state->bvd2 = 1;
162 state->wrprot = 0; /* Not available */
163 state->vs_3v = 1; /* Can only apply 3.3V */ 109 state->vs_3v = 1; /* Can only apply 3.3V */
164 state->vs_Xv = 0; 110 state->vs_Xv = 0;
165} 111}
166 112
167/*
168 * Enable card status IRQs on (re-)initialisation. This can
169 * be called at initialisation, power management event, or
170 * pcmcia event.
171 */
172static void nanoengine_pcmcia_socket_init(struct soc_pcmcia_socket *skt)
173{
174 unsigned i = skt->nr;
175
176 if (i >= num_nano_pcmcia_sockets)
177 return;
178
179 soc_pcmcia_enable_irqs(skt,
180 nano_skts[i].pcmcia_irqs, nano_skts[i].pcmcia_irqs_size);
181}
182
183/*
184 * Disable card status IRQs on suspend.
185 */
186static void nanoengine_pcmcia_socket_suspend(struct soc_pcmcia_socket *skt)
187{
188 unsigned i = skt->nr;
189
190 if (i >= num_nano_pcmcia_sockets)
191 return;
192
193 soc_pcmcia_disable_irqs(skt,
194 nano_skts[i].pcmcia_irqs, nano_skts[i].pcmcia_irqs_size);
195}
196
197static struct pcmcia_low_level nanoengine_pcmcia_ops = { 113static struct pcmcia_low_level nanoengine_pcmcia_ops = {
198 .owner = THIS_MODULE, 114 .owner = THIS_MODULE,
199 115
@@ -202,8 +118,6 @@ static struct pcmcia_low_level nanoengine_pcmcia_ops = {
202 118
203 .configure_socket = nanoengine_pcmcia_configure_socket, 119 .configure_socket = nanoengine_pcmcia_configure_socket,
204 .socket_state = nanoengine_pcmcia_socket_state, 120 .socket_state = nanoengine_pcmcia_socket_state,
205 .socket_init = nanoengine_pcmcia_socket_init,
206 .socket_suspend = nanoengine_pcmcia_socket_suspend,
207}; 121};
208 122
209int pcmcia_nanoengine_init(struct device *dev) 123int pcmcia_nanoengine_init(struct device *dev)