diff options
Diffstat (limited to 'drivers/pcmcia/pxa2xx_lubbock.c')
-rw-r--r-- | drivers/pcmcia/pxa2xx_lubbock.c | 269 |
1 files changed, 269 insertions, 0 deletions
diff --git a/drivers/pcmcia/pxa2xx_lubbock.c b/drivers/pcmcia/pxa2xx_lubbock.c new file mode 100644 index 000000000000..fd1f691c7c2c --- /dev/null +++ b/drivers/pcmcia/pxa2xx_lubbock.c | |||
@@ -0,0 +1,269 @@ | |||
1 | /* | ||
2 | * linux/drivers/pcmcia/pxa2xx_lubbock.c | ||
3 | * | ||
4 | * Author: George Davis | ||
5 | * Created: Jan 10, 2002 | ||
6 | * Copyright: MontaVista Software Inc. | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | * | ||
12 | * Originally based upon linux/drivers/pcmcia/sa1100_neponset.c | ||
13 | * | ||
14 | * Lubbock PCMCIA specific routines. | ||
15 | * | ||
16 | */ | ||
17 | #include <linux/module.h> | ||
18 | #include <linux/kernel.h> | ||
19 | #include <linux/sched.h> | ||
20 | #include <linux/device.h> | ||
21 | #include <linux/errno.h> | ||
22 | #include <linux/init.h> | ||
23 | #include <linux/delay.h> | ||
24 | |||
25 | #include <asm/hardware.h> | ||
26 | #include <asm/hardware/sa1111.h> | ||
27 | #include <asm/mach-types.h> | ||
28 | #include <asm/arch/pxa-regs.h> | ||
29 | #include <asm/arch/lubbock.h> | ||
30 | |||
31 | #include "sa1111_generic.h" | ||
32 | |||
33 | static int | ||
34 | lubbock_pcmcia_hw_init(struct soc_pcmcia_socket *skt) | ||
35 | { | ||
36 | /* | ||
37 | * Setup default state of GPIO outputs | ||
38 | * before we enable them as outputs. | ||
39 | */ | ||
40 | GPSR(GPIO48_nPOE) = | ||
41 | GPIO_bit(GPIO48_nPOE) | | ||
42 | GPIO_bit(GPIO49_nPWE) | | ||
43 | GPIO_bit(GPIO50_nPIOR) | | ||
44 | GPIO_bit(GPIO51_nPIOW) | | ||
45 | GPIO_bit(GPIO52_nPCE_1) | | ||
46 | GPIO_bit(GPIO53_nPCE_2); | ||
47 | |||
48 | pxa_gpio_mode(GPIO48_nPOE_MD); | ||
49 | pxa_gpio_mode(GPIO49_nPWE_MD); | ||
50 | pxa_gpio_mode(GPIO50_nPIOR_MD); | ||
51 | pxa_gpio_mode(GPIO51_nPIOW_MD); | ||
52 | pxa_gpio_mode(GPIO52_nPCE_1_MD); | ||
53 | pxa_gpio_mode(GPIO53_nPCE_2_MD); | ||
54 | pxa_gpio_mode(GPIO54_pSKTSEL_MD); | ||
55 | pxa_gpio_mode(GPIO55_nPREG_MD); | ||
56 | pxa_gpio_mode(GPIO56_nPWAIT_MD); | ||
57 | pxa_gpio_mode(GPIO57_nIOIS16_MD); | ||
58 | |||
59 | return sa1111_pcmcia_hw_init(skt); | ||
60 | } | ||
61 | |||
62 | static int | ||
63 | lubbock_pcmcia_configure_socket(struct soc_pcmcia_socket *skt, | ||
64 | const socket_state_t *state) | ||
65 | { | ||
66 | unsigned int pa_dwr_mask, pa_dwr_set, misc_mask, misc_set; | ||
67 | int ret = 0; | ||
68 | |||
69 | pa_dwr_mask = pa_dwr_set = misc_mask = misc_set = 0; | ||
70 | |||
71 | /* Lubbock uses the Maxim MAX1602, with the following connections: | ||
72 | * | ||
73 | * Socket 0 (PCMCIA): | ||
74 | * MAX1602 Lubbock Register | ||
75 | * Pin Signal | ||
76 | * ----- ------- ---------------------- | ||
77 | * A0VPP S0_PWR0 SA-1111 GPIO A<0> | ||
78 | * A1VPP S0_PWR1 SA-1111 GPIO A<1> | ||
79 | * A0VCC S0_PWR2 SA-1111 GPIO A<2> | ||
80 | * A1VCC S0_PWR3 SA-1111 GPIO A<3> | ||
81 | * VX VCC | ||
82 | * VY +3.3V | ||
83 | * 12IN +12V | ||
84 | * CODE +3.3V Cirrus Code, CODE = High (VY) | ||
85 | * | ||
86 | * Socket 1 (CF): | ||
87 | * MAX1602 Lubbock Register | ||
88 | * Pin Signal | ||
89 | * ----- ------- ---------------------- | ||
90 | * A0VPP GND VPP is not connected | ||
91 | * A1VPP GND VPP is not connected | ||
92 | * A0VCC S1_PWR0 MISC_WR<14> | ||
93 | * A1VCC S1_PWR1 MISC_WR<15> | ||
94 | * VX VCC | ||
95 | * VY +3.3V | ||
96 | * 12IN GND VPP is not connected | ||
97 | * CODE +3.3V Cirrus Code, CODE = High (VY) | ||
98 | * | ||
99 | */ | ||
100 | |||
101 | again: | ||
102 | switch (skt->nr) { | ||
103 | case 0: | ||
104 | pa_dwr_mask = GPIO_A0 | GPIO_A1 | GPIO_A2 | GPIO_A3; | ||
105 | |||
106 | switch (state->Vcc) { | ||
107 | case 0: /* Hi-Z */ | ||
108 | break; | ||
109 | |||
110 | case 33: /* VY */ | ||
111 | pa_dwr_set |= GPIO_A3; | ||
112 | break; | ||
113 | |||
114 | case 50: /* VX */ | ||
115 | pa_dwr_set |= GPIO_A2; | ||
116 | break; | ||
117 | |||
118 | default: | ||
119 | printk(KERN_ERR "%s(): unrecognized Vcc %u\n", | ||
120 | __FUNCTION__, state->Vcc); | ||
121 | ret = -1; | ||
122 | } | ||
123 | |||
124 | switch (state->Vpp) { | ||
125 | case 0: /* Hi-Z */ | ||
126 | break; | ||
127 | |||
128 | case 120: /* 12IN */ | ||
129 | pa_dwr_set |= GPIO_A1; | ||
130 | break; | ||
131 | |||
132 | default: /* VCC */ | ||
133 | if (state->Vpp == state->Vcc) | ||
134 | pa_dwr_set |= GPIO_A0; | ||
135 | else { | ||
136 | printk(KERN_ERR "%s(): unrecognized Vpp %u\n", | ||
137 | __FUNCTION__, state->Vpp); | ||
138 | ret = -1; | ||
139 | break; | ||
140 | } | ||
141 | } | ||
142 | break; | ||
143 | |||
144 | case 1: | ||
145 | misc_mask = (1 << 15) | (1 << 14); | ||
146 | |||
147 | switch (state->Vcc) { | ||
148 | case 0: /* Hi-Z */ | ||
149 | break; | ||
150 | |||
151 | case 33: /* VY */ | ||
152 | misc_set |= 1 << 15; | ||
153 | break; | ||
154 | |||
155 | case 50: /* VX */ | ||
156 | misc_set |= 1 << 14; | ||
157 | break; | ||
158 | |||
159 | default: | ||
160 | printk(KERN_ERR "%s(): unrecognized Vcc %u\n", | ||
161 | __FUNCTION__, state->Vcc); | ||
162 | ret = -1; | ||
163 | break; | ||
164 | } | ||
165 | |||
166 | if (state->Vpp != state->Vcc && state->Vpp != 0) { | ||
167 | printk(KERN_ERR "%s(): CF slot cannot support Vpp %u\n", | ||
168 | __FUNCTION__, state->Vpp); | ||
169 | ret = -1; | ||
170 | break; | ||
171 | } | ||
172 | break; | ||
173 | |||
174 | default: | ||
175 | ret = -1; | ||
176 | } | ||
177 | |||
178 | if (ret == 0) | ||
179 | ret = sa1111_pcmcia_configure_socket(skt, state); | ||
180 | |||
181 | if (ret == 0) { | ||
182 | lubbock_set_misc_wr(misc_mask, misc_set); | ||
183 | sa1111_set_io(SA1111_DEV(skt->dev), pa_dwr_mask, pa_dwr_set); | ||
184 | } | ||
185 | |||
186 | #if 1 | ||
187 | if (ret == 0 && state->Vcc == 33) { | ||
188 | struct pcmcia_state new_state; | ||
189 | |||
190 | /* | ||
191 | * HACK ALERT: | ||
192 | * We can't sense the voltage properly on Lubbock before | ||
193 | * actually applying some power to the socket (catch 22). | ||
194 | * Resense the socket Voltage Sense pins after applying | ||
195 | * socket power. | ||
196 | * | ||
197 | * Note: It takes about 2.5ms for the MAX1602 VCC output | ||
198 | * to rise. | ||
199 | */ | ||
200 | mdelay(3); | ||
201 | |||
202 | sa1111_pcmcia_socket_state(skt, &new_state); | ||
203 | |||
204 | if (!new_state.vs_3v && !new_state.vs_Xv) { | ||
205 | /* | ||
206 | * Switch to 5V, Configure socket with 5V voltage | ||
207 | */ | ||
208 | lubbock_set_misc_wr(misc_mask, 0); | ||
209 | sa1111_set_io(SA1111_DEV(skt->dev), pa_dwr_mask, 0); | ||
210 | |||
211 | /* | ||
212 | * It takes about 100ms to turn off Vcc. | ||
213 | */ | ||
214 | mdelay(100); | ||
215 | |||
216 | /* | ||
217 | * We need to hack around the const qualifier as | ||
218 | * well to keep this ugly workaround localized and | ||
219 | * not force it to the rest of the code. Barf bags | ||
220 | * avaliable in the seat pocket in front of you! | ||
221 | */ | ||
222 | ((socket_state_t *)state)->Vcc = 50; | ||
223 | ((socket_state_t *)state)->Vpp = 50; | ||
224 | goto again; | ||
225 | } | ||
226 | } | ||
227 | #endif | ||
228 | |||
229 | return ret; | ||
230 | } | ||
231 | |||
232 | static struct pcmcia_low_level lubbock_pcmcia_ops = { | ||
233 | .owner = THIS_MODULE, | ||
234 | .hw_init = lubbock_pcmcia_hw_init, | ||
235 | .hw_shutdown = sa1111_pcmcia_hw_shutdown, | ||
236 | .socket_state = sa1111_pcmcia_socket_state, | ||
237 | .configure_socket = lubbock_pcmcia_configure_socket, | ||
238 | .socket_init = sa1111_pcmcia_socket_init, | ||
239 | .socket_suspend = sa1111_pcmcia_socket_suspend, | ||
240 | .first = 0, | ||
241 | .nr = 2, | ||
242 | }; | ||
243 | |||
244 | #include "pxa2xx_base.h" | ||
245 | |||
246 | int __init pcmcia_lubbock_init(struct sa1111_dev *sadev) | ||
247 | { | ||
248 | int ret = -ENODEV; | ||
249 | |||
250 | if (machine_is_lubbock()) { | ||
251 | /* | ||
252 | * Set GPIO_A<3:0> to be outputs for the MAX1600, | ||
253 | * and switch to standby mode. | ||
254 | */ | ||
255 | sa1111_set_io_dir(sadev, GPIO_A0|GPIO_A1|GPIO_A2|GPIO_A3, 0, 0); | ||
256 | sa1111_set_io(sadev, GPIO_A0|GPIO_A1|GPIO_A2|GPIO_A3, 0); | ||
257 | sa1111_set_sleep_io(sadev, GPIO_A0|GPIO_A1|GPIO_A2|GPIO_A3, 0); | ||
258 | |||
259 | /* Set CF Socket 1 power to standby mode. */ | ||
260 | lubbock_set_misc_wr((1 << 15) | (1 << 14), 0); | ||
261 | |||
262 | sadev->dev.platform_data = &lubbock_pcmcia_ops; | ||
263 | ret = pxa2xx_drv_pcmcia_probe(&sadev->dev); | ||
264 | } | ||
265 | |||
266 | return ret; | ||
267 | } | ||
268 | |||
269 | MODULE_LICENSE("GPL"); | ||