[ARM] pxa: Gumstix Verdex PCMCIA support
[linux-2.6/verdex.git] / drivers / pcmcia / pxa2xx_gumstix.c
blob2877a8ac993a00e45925a32c6e1a937b835b0c00
1 /*
2 * linux/drivers/pcmcia/pxa2xx_gumstix.c
4 * Gumstix PCMCIA specific routines. Based on Mainstone
6 * Copyright 2004, Craig Hughes <craig@gumstix.com>
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.
13 #include <linux/module.h>
14 #include <linux/init.h>
15 #include <linux/kernel.h>
16 #include <linux/errno.h>
17 #include <linux/interrupt.h>
18 #include <linux/irq.h>
19 #include <linux/gpio.h>
21 #include <linux/delay.h>
22 #include <linux/platform_device.h>
24 #include <pcmcia/ss.h>
26 #include <mach/hardware.h>
27 #include <asm/mach-types.h>
29 #ifdef CONFIG_MACH_GUMSTIX_VERDEX
30 #include <mach/pxa27x.h>
31 #else
32 #include <mach/pxa27x.h>
33 #endif
35 #include <asm/io.h>
36 #include <mach/gpio.h>
37 #include <mach/gumstix.h>
38 #include "soc_common.h"
40 #define ARRAY_AND_SIZE(x) (x), ARRAY_SIZE(x)
42 static struct pcmcia_irqs gumstix_pcmcia_irqs0[] = {
43 { 0, GUMSTIX_S0_nCD_IRQ, "CF0 nCD" },
44 { 0, GUMSTIX_S0_nSTSCHG_IRQ, "CF0 nSTSCHG" },
47 static struct pcmcia_irqs gumstix_pcmcia_irqs1[] = {
48 { 1, GUMSTIX_S1_nCD_IRQ, "CF1 nCD" },
49 { 1, GUMSTIX_S1_nSTSCHG_IRQ, "CF1 nSTSCHG" },
53 static int net_cf_vx_mode = 0;
55 static int gumstix_pcmcia_hw_init(struct soc_pcmcia_socket *skt)
57 /* Note: The verdex_pcmcia_pin_config is moved to gumstix_verdex.c in order to use mfp_pxa2xx_config
58 for board-specific pin configuration instead of the old deprecated pxa_gpio_mode function. Thus,
59 only the IRQ init is still needed to be done here. */
60 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;
62 return (skt->nr == 0) ? soc_pcmcia_request_irqs(skt, gumstix_pcmcia_irqs0, ARRAY_SIZE(gumstix_pcmcia_irqs0)) :
63 soc_pcmcia_request_irqs(skt, gumstix_pcmcia_irqs1, ARRAY_SIZE(gumstix_pcmcia_irqs1));
66 static void gumstix_pcmcia_hw_shutdown(struct soc_pcmcia_socket *skt)
68 if(skt->nr == 0)
70 soc_pcmcia_free_irqs(skt, gumstix_pcmcia_irqs0, ARRAY_SIZE(gumstix_pcmcia_irqs0));
71 } else {
72 soc_pcmcia_free_irqs(skt, gumstix_pcmcia_irqs1, ARRAY_SIZE(gumstix_pcmcia_irqs1));
75 if (net_cf_vx_mode) {
76 gpio_free(GPIO_GUMSTIX_CF_OLD_RESET);
77 } else {
78 gpio_free(GPIO_GUMSTIX_CF_RESET);
83 static void gumstix_pcmcia_socket_state(struct soc_pcmcia_socket *skt,
84 struct pcmcia_state *state)
86 unsigned int cd, prdy_nbsy, nbvd1;
87 if(skt->nr == 0)
89 cd = GPIO_GUMSTIX_nCD_0;
90 if(net_cf_vx_mode)
91 prdy_nbsy = GPIO_GUMSTIX_PRDY_nBSY_0_OLD;
92 else
93 prdy_nbsy = GPIO_GUMSTIX_PRDY_nBSY_0;
94 nbvd1 = GPIO_GUMSTIX_nBVD1_0;
95 } else {
96 cd = GPIO_GUMSTIX_nCD_1;
97 prdy_nbsy = GPIO_GUMSTIX_PRDY_nBSY_1;
98 nbvd1 = GPIO_GUMSTIX_nBVD1_1;
100 state->detect = !(GPLR(cd) & GPIO_bit(cd));
101 state->ready = !!(GPLR(prdy_nbsy) & GPIO_bit(prdy_nbsy));
102 state->bvd1 = !!(GPLR(nbvd1) & GPIO_bit(nbvd1));
103 state->bvd2 = 1;
104 state->vs_3v = 0;
105 state->vs_Xv = 0;
106 state->wrprot = 0;
109 static int gumstix_pcmcia_configure_socket(struct soc_pcmcia_socket *skt,
110 const socket_state_t *state)
112 return 0;
115 static void gumstix_pcmcia_socket_init(struct soc_pcmcia_socket *skt)
117 if(skt->nr) {
118 soc_pcmcia_enable_irqs(skt, gumstix_pcmcia_irqs0, ARRAY_SIZE(gumstix_pcmcia_irqs0));
119 } else {
120 soc_pcmcia_enable_irqs(skt, gumstix_pcmcia_irqs1, ARRAY_SIZE(gumstix_pcmcia_irqs1));
124 static void gumstix_pcmcia_socket_suspend(struct soc_pcmcia_socket *skt)
126 if(skt->nr) {
127 soc_pcmcia_disable_irqs(skt, gumstix_pcmcia_irqs0, ARRAY_SIZE(gumstix_pcmcia_irqs0));
128 } else {
129 soc_pcmcia_disable_irqs(skt, gumstix_pcmcia_irqs1, ARRAY_SIZE(gumstix_pcmcia_irqs1));
133 static struct pcmcia_low_level gumstix_pcmcia_ops = {
134 .owner = THIS_MODULE,
135 .hw_init = gumstix_pcmcia_hw_init,
136 .hw_shutdown = gumstix_pcmcia_hw_shutdown,
137 .socket_state = gumstix_pcmcia_socket_state,
138 .configure_socket = gumstix_pcmcia_configure_socket,
139 .socket_init = gumstix_pcmcia_socket_init,
140 .socket_suspend = gumstix_pcmcia_socket_suspend,
141 .nr = 2,
144 static struct platform_device *gumstix_pcmcia_device;
146 extern int __init gumstix_get_cf_cards(void);
148 #ifdef CONFIG_MACH_GUMSTIX_VERDEX
149 extern int __init gumstix_check_if_netCF_vx(void);
150 #endif
152 static int __init gumstix_pcmcia_init(void)
154 int ret;
156 #ifdef CONFIG_MACH_GUMSTIX_VERDEX
157 net_cf_vx_mode = gumstix_check_if_netCF_vx();
158 #endif
160 gumstix_pcmcia_ops.nr = gumstix_get_cf_cards();
162 gumstix_pcmcia_device = platform_device_alloc("pxa2xx-pcmcia", -1);
163 if (!gumstix_pcmcia_device)
164 return -ENOMEM;
166 ret = platform_device_add_data(gumstix_pcmcia_device, &gumstix_pcmcia_ops,
167 sizeof(gumstix_pcmcia_ops));
169 if (ret == 0) {
170 printk(KERN_INFO "Registering gumstix PCMCIA interface.\n");
171 ret = platform_device_add(gumstix_pcmcia_device);
174 if (ret)
175 platform_device_put(gumstix_pcmcia_device);
177 return ret;
180 static void __exit gumstix_pcmcia_exit(void)
183 * This call is supposed to free our gumstix_pcmcia_device.
184 * Unfortunately platform_device don't have a free method, and
185 * we can't assume it's free of any reference at this point so we
186 * can't free it either.
188 platform_device_unregister(gumstix_pcmcia_device);
191 fs_initcall(gumstix_pcmcia_init);
192 module_exit(gumstix_pcmcia_exit);
194 MODULE_LICENSE("GPL");