add preliminary MPC83xx support
[openwrt.git] / target / linux / pxa / patches-2.6.21 / 005-compact-flash.patch
1 --- a/drivers/pcmcia/Makefile
2 +++ b/drivers/pcmcia/Makefile
3 @@ -69,4 +69,4 @@ sa1100_cs-$(CONFIG_SA1100_SIMPAD) += sa
4 pxa2xx_cs-$(CONFIG_ARCH_LUBBOCK) += pxa2xx_lubbock.o sa1111_generic.o
5 pxa2xx_cs-$(CONFIG_MACH_MAINSTONE) += pxa2xx_mainstone.o
6 pxa2xx_cs-$(CONFIG_PXA_SHARPSL) += pxa2xx_sharpsl.o
7 -
8 +pxa2xx_cs-$(CONFIG_ARCH_GUMSTIX) += pxa2xx_gumstix.o
9 --- /dev/null
10 +++ b/drivers/pcmcia/pxa2xx_gumstix.c
11 @@ -0,0 +1,272 @@
12 +/*
13 + * linux/drivers/pcmcia/pxa2xx_gumstix.c
14 + *
15 + * Gumstix PCMCIA specific routines. Based on Mainstone
16 + *
17 + * Copyright 2004, Craig Hughes <craig@gumstix.com>
18 + *
19 + * This program is free software; you can redistribute it and/or modify
20 + * it under the terms of the GNU General Public License version 2 as
21 + * published by the Free Software Foundation.
22 + */
23 +
24 +#include <linux/module.h>
25 +#include <linux/init.h>
26 +#include <linux/kernel.h>
27 +#include <linux/errno.h>
28 +#include <linux/interrupt.h>
29 +#include <linux/device.h>
30 +#include <linux/platform_device.h>
31 +
32 +#include <pcmcia/ss.h>
33 +
34 +#include <asm/hardware.h>
35 +#include <asm/delay.h>
36 +#include <asm/arch/pxa-regs.h>
37 +#include <asm/irq.h>
38 +#include <asm/io.h>
39 +
40 +#include <asm/arch/gumstix.h>
41 +
42 +#include "soc_common.h"
43 +
44 +static struct pcmcia_irqs gumstix_pcmcia_irqs0[] = {
45 + { 0, GUMSTIX_S0_nCD_IRQ, "CF0 nCD" },
46 + { 0, GUMSTIX_S0_nSTSCHG_IRQ, "CF0 nSTSCHG" },
47 +};
48 +
49 +static struct pcmcia_irqs gumstix_pcmcia_irqs1[] = {
50 + { 1, GUMSTIX_S1_nCD_IRQ, "CF1 nCD" },
51 + { 1, GUMSTIX_S1_nSTSCHG_IRQ, "CF1 nSTSCHG" },
52 +};
53 +
54 +static int net_cf_vx_mode = 0;
55 +
56 +static int gumstix_pcmcia_hw_init(struct soc_pcmcia_socket *skt)
57 +{
58 + if(skt->nr == 0)
59 + {
60 + pxa_gpio_mode(GPIO_GUMSTIX_nSTSCHG_0_MD);
61 + pxa_gpio_mode(GPIO_GUMSTIX_nCD_0_MD);
62 + if(net_cf_vx_mode)
63 + pxa_gpio_mode(GPIO_GUMSTIX_PRDY_nBSY_0_OLD_MD);
64 + else
65 + pxa_gpio_mode(GPIO_GUMSTIX_PRDY_nBSY_0_MD);
66 + } else {
67 + pxa_gpio_mode(GPIO_GUMSTIX_nSTSCHG_1_MD);
68 + pxa_gpio_mode(GPIO_GUMSTIX_nCD_1_MD);
69 + pxa_gpio_mode(GPIO_GUMSTIX_PRDY_nBSY_1_MD);
70 + }
71 +
72 + pxa_gpio_mode(GPIO_GUMSTIX_nPOE_MD);
73 + pxa_gpio_mode(GPIO_GUMSTIX_nPWE_MD);
74 + pxa_gpio_mode(GPIO_GUMSTIX_nPIOR_MD);
75 + pxa_gpio_mode(GPIO_GUMSTIX_nPIOW_MD);
76 + pxa_gpio_mode(GPIO_GUMSTIX_nPCE_1_MD);
77 + pxa_gpio_mode(GPIO_GUMSTIX_nPCE_2_MD);
78 + pxa_gpio_mode(GPIO_GUMSTIX_pSKTSEL_MD);
79 + pxa_gpio_mode(GPIO_GUMSTIX_nPREG_MD);
80 + pxa_gpio_mode(GPIO_GUMSTIX_nPWAIT_MD);
81 + pxa_gpio_mode(GPIO_GUMSTIX_nIOIS16_MD);
82 +
83 + skt->irq = (skt->nr == 0) ? ((net_cf_vx_mode == 0) ? GUMSTIX_S0_PRDY_nBSY_IRQ : GUMSTIX_S0_PRDY_nBSY_OLD_IRQ) : GUMSTIX_S1_PRDY_nBSY_IRQ;
84 +
85 + return (skt->nr == 0) ? soc_pcmcia_request_irqs(skt, gumstix_pcmcia_irqs0, ARRAY_SIZE(gumstix_pcmcia_irqs0)) :
86 + soc_pcmcia_request_irqs(skt, gumstix_pcmcia_irqs1, ARRAY_SIZE(gumstix_pcmcia_irqs1));
87 +}
88 +
89 +static void gumstix_pcmcia_hw_shutdown(struct soc_pcmcia_socket *skt)
90 +{
91 + if(skt->nr == 0)
92 + {
93 + soc_pcmcia_free_irqs(skt, gumstix_pcmcia_irqs0, ARRAY_SIZE(gumstix_pcmcia_irqs0));
94 + } else {
95 + soc_pcmcia_free_irqs(skt, gumstix_pcmcia_irqs1, ARRAY_SIZE(gumstix_pcmcia_irqs1));
96 + }
97 +}
98 +
99 +static void gumstix_pcmcia_socket_state(struct soc_pcmcia_socket *skt,
100 + struct pcmcia_state *state)
101 +{
102 + unsigned int cd, prdy_nbsy, nbvd1;
103 + if(skt->nr == 0)
104 + {
105 + cd = GPIO_GUMSTIX_nCD_0;
106 + if(net_cf_vx_mode)
107 + prdy_nbsy = GPIO_GUMSTIX_PRDY_nBSY_0_OLD;
108 + else
109 + prdy_nbsy = GPIO_GUMSTIX_PRDY_nBSY_0;
110 + nbvd1 = GPIO_GUMSTIX_nBVD1_0;
111 + } else {
112 + cd = GPIO_GUMSTIX_nCD_1;
113 + prdy_nbsy = GPIO_GUMSTIX_PRDY_nBSY_1;
114 + nbvd1 = GPIO_GUMSTIX_nBVD1_1;
115 + }
116 + state->detect = !(GPLR(cd) & GPIO_bit(cd));
117 + state->ready = !!(GPLR(prdy_nbsy) & GPIO_bit(prdy_nbsy));
118 + state->bvd1 = !!(GPLR(nbvd1) & GPIO_bit(nbvd1));
119 + state->bvd2 = 1;
120 + state->vs_3v = 0;
121 + state->vs_Xv = 0;
122 + state->wrprot = 0;
123 +}
124 +
125 +static int gumstix_pcmcia_configure_socket(struct soc_pcmcia_socket *skt,
126 + const socket_state_t *state)
127 +{
128 + return 0;
129 +}
130 +
131 +static void gumstix_pcmcia_socket_init(struct soc_pcmcia_socket *skt)
132 +{
133 + if(skt->nr) {
134 + soc_pcmcia_enable_irqs(skt, gumstix_pcmcia_irqs0, ARRAY_SIZE(gumstix_pcmcia_irqs0));
135 + } else {
136 + soc_pcmcia_enable_irqs(skt, gumstix_pcmcia_irqs1, ARRAY_SIZE(gumstix_pcmcia_irqs1));
137 + }
138 +}
139 +
140 +static void gumstix_pcmcia_socket_suspend(struct soc_pcmcia_socket *skt)
141 +{
142 + if(skt->nr) {
143 + soc_pcmcia_disable_irqs(skt, gumstix_pcmcia_irqs0, ARRAY_SIZE(gumstix_pcmcia_irqs0));
144 + } else {
145 + soc_pcmcia_disable_irqs(skt, gumstix_pcmcia_irqs1, ARRAY_SIZE(gumstix_pcmcia_irqs1));
146 + }
147 +}
148 +
149 +static struct pcmcia_low_level gumstix_pcmcia_ops = {
150 + .owner = THIS_MODULE,
151 + .hw_init = gumstix_pcmcia_hw_init,
152 + .hw_shutdown = gumstix_pcmcia_hw_shutdown,
153 + .socket_state = gumstix_pcmcia_socket_state,
154 + .configure_socket = gumstix_pcmcia_configure_socket,
155 + .socket_init = gumstix_pcmcia_socket_init,
156 + .socket_suspend = gumstix_pcmcia_socket_suspend,
157 + .nr = 2,
158 +};
159 +
160 +static struct platform_device *gumstix_pcmcia_device;
161 +
162 +inline void __init gumstix_pcmcia_cpld_clk(void)
163 +{
164 + GPCR(GPIO_GUMSTIX_nPOE) = GPIO_bit(GPIO_GUMSTIX_nPOE);
165 + GPSR(GPIO_GUMSTIX_nPOE) = GPIO_bit(GPIO_GUMSTIX_nPOE);
166 +}
167 +
168 +inline unsigned char __init gumstix_pcmcia_cpld_read_bits(int bits)
169 +{
170 + unsigned char result = 0;
171 + unsigned int shift = 0;
172 + while(bits--)
173 + {
174 + result |= !!(GPLR(GPIO_GUMSTIX_nCD_0) & GPIO_bit(GPIO_GUMSTIX_nCD_0)) << shift;
175 + shift ++;
176 + gumstix_pcmcia_cpld_clk();
177 + }
178 + printk("CPLD responded with: %02x\n",result);
179 + return result;
180 +}
181 +
182 +/* We use the CPLD on the CF-CF card to read a value from a shift register. If we can read that
183 + * magic sequence, then we have 2 CF cards; otherwise we assume just one
184 + * The CPLD will send the value of the shift register on GPIO11 (the CD line for slot 0)
185 + * when RESET is held in reset. We use GPIO48 (nPOE) as a clock signal,
186 + * GPIO52/53 (card enable for both cards) to control read/write to the shift register
187 + */
188 +static void __init gumstix_count_cards(void)
189 +{
190 + pxa_gpio_mode(GPIO_GUMSTIX_nPOE | GPIO_OUT);
191 + pxa_gpio_mode(GPIO_GUMSTIX_nPCE_1 | GPIO_OUT);
192 + pxa_gpio_mode(GPIO_GUMSTIX_nPCE_2 | GPIO_OUT);
193 + pxa_gpio_mode(GPIO_GUMSTIX_nCD_0 | GPIO_IN);
194 + if(net_cf_vx_mode)
195 + pxa_gpio_mode(GPIO_GUMSTIX_CF_OLD_RESET | GPIO_OUT);
196 + else
197 + pxa_gpio_mode(GPIO_GUMSTIX_CF_RESET | GPIO_OUT);
198 +
199 + // Enter reset
200 + if(net_cf_vx_mode)
201 + GPSR(GPIO_GUMSTIX_CF_OLD_RESET) = GPIO_bit(GPIO_GUMSTIX_CF_OLD_RESET);
202 + else
203 + GPSR(GPIO_GUMSTIX_CF_RESET) = GPIO_bit(GPIO_GUMSTIX_CF_RESET);
204 +
205 + // Setup the shift register
206 + GPSR(GPIO_GUMSTIX_nPCE_1) = GPIO_bit(GPIO_GUMSTIX_nPCE_1);
207 + GPCR(GPIO_GUMSTIX_nPCE_2) = GPIO_bit(GPIO_GUMSTIX_nPCE_2);
208 +
209 + // Tick the clock to program the shift register
210 + gumstix_pcmcia_cpld_clk();
211 +
212 + // Now set shift register into read mode
213 + GPCR(GPIO_GUMSTIX_nPCE_1) = GPIO_bit(GPIO_GUMSTIX_nPCE_1);
214 + GPSR(GPIO_GUMSTIX_nPCE_2) = GPIO_bit(GPIO_GUMSTIX_nPCE_2);
215 +
216 + // We can read the bits now -- 0xC2 means "Dual compact flash"
217 + if(gumstix_pcmcia_cpld_read_bits(8) != 0xC2)
218 + {
219 + // We do not have 2 CF slots
220 + gumstix_pcmcia_ops.nr = 1;
221 + }
222 +}
223 +
224 +#ifdef CONFIG_ARCH_GUMSTIX_VERDEX
225 +static void __init gumstix_check_if_netCF_vx(void)
226 +{
227 + void *network_controller_memory = ioremap(0x04000300,16);
228 + // Look for the special 91c111 value in the bank select register
229 + if((0xff00 & readw(network_controller_memory+0x0e)) == 0x3300) {
230 + printk("Detected netCF-vx board: using older GPIO configuration\n");
231 + net_cf_vx_mode = 1;
232 + } else {
233 + printk("Not netCF-vx board: using newer GPIO configuration\n");
234 + net_cf_vx_mode = 0;
235 + }
236 + iounmap(network_controller_memory);
237 +}
238 +#endif
239 +
240 +static int __init gumstix_pcmcia_init(void)
241 +{
242 + int ret;
243 +
244 +#ifdef CONFIG_ARCH_GUMSTIX_VERDEX
245 + gumstix_check_if_netCF_vx();
246 +#endif
247 +
248 + gumstix_count_cards();
249 +
250 + udelay(50);
251 + if(net_cf_vx_mode)
252 + GPCR(GPIO_GUMSTIX_CF_OLD_RESET) = GPIO_bit(GPIO_GUMSTIX_CF_OLD_RESET);
253 + else
254 + GPCR(GPIO_GUMSTIX_CF_RESET) = GPIO_bit(GPIO_GUMSTIX_CF_RESET);
255 +
256 + gumstix_pcmcia_device = platform_device_alloc("pxa2xx-pcmcia", -1);
257 + if (!gumstix_pcmcia_device)
258 + return -ENOMEM;
259 +
260 + gumstix_pcmcia_device->dev.platform_data = &gumstix_pcmcia_ops;
261 +
262 + ret = platform_device_add(gumstix_pcmcia_device);
263 + if (ret)
264 + platform_device_put(gumstix_pcmcia_device);
265 +
266 + return ret;
267 +}
268 +
269 +static void __exit gumstix_pcmcia_exit(void)
270 +{
271 + /*
272 + * This call is supposed to free our gumstix_pcmcia_device.
273 + * Unfortunately platform_device don't have a free method, and
274 + * we can't assume it's free of any reference at this point so we
275 + * can't free it either.
276 + */
277 + platform_device_unregister(gumstix_pcmcia_device);
278 +}
279 +
280 +fs_initcall(gumstix_pcmcia_init);
281 +module_exit(gumstix_pcmcia_exit);
282 +
283 +MODULE_LICENSE("GPL");
This page took 0.056999 seconds and 5 git commands to generate.