hh.org updates
[hh.org.git] / arch / arm / mach-pxa / rover / roverp5p_pcmcia.c
blobd60ea52f4e4593609603b5ec061eab942360709e
1 /*
2 * Rover P5+ PCMCIA support
3 *
4 * Konstantine A. Beklemishev <konstantine@r66.ru>
6 * This file is subject to the terms and conditions of the GNU General Public
7 * License. See the file COPYING in the main directory of this archive for
8 * more details.
9 */
11 #include <linux/module.h>
12 #include <linux/kernel.h>
13 #include <linux/errno.h>
14 #include <linux/interrupt.h>
15 #include <linux/device.h>
16 #include <linux/init.h>
18 #include <asm/hardware.h>
19 #include <asm/mach-types.h>
20 #include <asm/irq.h>
21 #include <asm/signal.h>
23 #include <../drivers/pcmcia/soc_common.h>
24 #include <asm/arch/pxa-regs.h>
25 #include <asm/arch/roverp5p-gpio.h>
27 #if 0
28 # define rover_debug(s, args...) printk (KERN_INFO s, ##args)
29 #else
30 # define rover_debug(s, args...)
31 #endif
32 #define debug_func(s, args...) rover_debug ("%s: " s, __FUNCTION__, ##args)
34 #define GPIO_STATE(x) (GPLR (x) & GPIO_bit (x))
35 #define GPIO_SET(x) (GPSR (x) = GPIO_bit (x))
36 #define GPIO_CLR(x) (GPCR (x) = GPIO_bit (x))
38 static struct pcmcia_irqs cd_irqs[] = {
39 { 0, IRQ_GPIO(GPIO_NR_ROVERP5P_CF_DETECT), "PCMCIA CD" },
42 static void roverp5p_pcmcia_hw_rst (int state)
44 debug_func ("\n");
45 SET_ROVERP5P_GPIO (CF_RESET, state);
46 /* if (state)
47 GPIO_SET (GPIO_NR_ROVERP5P_CF_RESET);
48 else
49 GPIO_CLR (GPIO_NR_ROVERP5P_CF_RESET);*/
52 static int roverp5p_pcmcia_hw_init(struct soc_pcmcia_socket *skt)
54 unsigned long flags;
56 skt->irq = IRQ_GPIO(GPIO_NR_ROVERP5P_PXA_PRDY);
58 local_irq_save (flags);
59 pxa_gpio_mode (GPIO_NR_ROVERP5P_CF_RESET | GPIO_OUT);
60 pxa_gpio_mode (GPIO_NR_ROVERP5P_CF_PWR_ON | GPIO_OUT);
61 pxa_gpio_mode (GPIO_NR_ROVERP5P_CF_BUS_nON | GPIO_OUT);
62 pxa_gpio_mode (GPIO_NR_ROVERP5P_CF_DETECT | GPIO_IN);
63 pxa_gpio_mode (GPIO_NR_ROVERP5P_PXA_PRDY | GPIO_IN);
64 local_irq_restore (flags);
66 return soc_pcmcia_request_irqs(skt, cd_irqs, ARRAY_SIZE(cd_irqs));
71 * Release all resources.
73 static void roverp5p_pcmcia_hw_shutdown(struct soc_pcmcia_socket *skt)
75 soc_pcmcia_free_irqs(skt, cd_irqs, ARRAY_SIZE(cd_irqs));
78 static void
79 roverp5p_pcmcia_socket_state(struct soc_pcmcia_socket *skt, struct pcmcia_state *state)
81 state->detect = GET_ROVERP5P_GPIO (CF_DETECT) ? 0 : 1;
82 state->ready = GET_ROVERP5P_GPIO (PXA_PRDY) ? 1 : 0;
83 state->bvd1 = 1;
84 state->bvd2 = 1;
85 state->wrprot = 0;
86 state->vs_3v = GET_ROVERP5P_GPIO (CF_PWR_ON) ? 0 : 1;
87 state->vs_Xv = 0;
89 rover_debug ("detect:%d ready:%d vcc:%d\n",
90 state->detect, state->ready, state->vs_3v);
93 static int
94 roverp5p_pcmcia_configure_socket(struct soc_pcmcia_socket *skt, const socket_state_t *state)
96 /* Silently ignore Vpp, output enable, speaker enable. */
97 debug_func ("Reset:%d Vcc:%d\n", (state->flags & SS_RESET) ? 1 : 0,
98 state->Vcc);
100 roverp5p_pcmcia_hw_rst (state->flags & SS_RESET);
102 /* Apply socket voltage */
103 switch (state->Vcc) {
104 case 0:
105 SET_ROVERP5P_GPIO (CF_PWR_ON, 1);
106 SET_ROVERP5P_GPIO (CF_BUS_nON, 1);
107 /*GPIO_CLR (GPIO_NR_ROVERP5P_CF_PWR_ON);
108 GPIO_CLR (GPIO_NR_ROVERP5P_CF_BUS_nON);*/
109 break;
110 case 50:
111 /*GPIO_SET (GPIO_NR_ROVERP5P_CF_PWR_ON);
112 break;*/
113 case 33:
114 /* Apply power to socket */
115 SET_ROVERP5P_GPIO (CF_PWR_ON, 0);
116 SET_ROVERP5P_GPIO (CF_BUS_nON, 0);
117 /*GPIO_SET (GPIO_NR_ROVERP5P_CF_PWR_ON);
118 GPIO_SET (GPIO_NR_ROVERP5P_CF_BUS_nON);*/
119 break;
120 default:
121 printk (KERN_ERR "%s: Unsupported Vcc:%d\n",
122 __FUNCTION__, state->Vcc);
125 return 0;
129 * Enable card status IRQs on (re-)initialisation. This can
130 * be called at initialisation, power management event, or
131 * pcmcia event.
133 static void roverp5p_pcmcia_socket_init(struct soc_pcmcia_socket *skt)
135 debug_func ("\n");
136 soc_pcmcia_enable_irqs (skt, cd_irqs, ARRAY_SIZE(cd_irqs));
140 * Disable card status IRQs on suspend.
142 static void roverp5p_pcmcia_socket_suspend(struct soc_pcmcia_socket *skt)
144 debug_func ("\n");
145 roverp5p_pcmcia_hw_rst(1);
146 soc_pcmcia_disable_irqs(skt, cd_irqs, ARRAY_SIZE(cd_irqs));
149 static struct pcmcia_low_level roverp5p_pcmcia_ops = {
150 .owner = THIS_MODULE,
152 .first = 0,
153 .nr = 1,
155 .hw_init = roverp5p_pcmcia_hw_init,
156 .hw_shutdown = roverp5p_pcmcia_hw_shutdown,
158 .socket_state = roverp5p_pcmcia_socket_state,
159 .configure_socket = roverp5p_pcmcia_configure_socket,
161 .socket_init = roverp5p_pcmcia_socket_init,
162 .socket_suspend = roverp5p_pcmcia_socket_suspend,
165 static struct platform_device roverp5p_pcmcia_device = {
166 .name = "pxa2xx-pcmcia",
167 .id = 0,
168 .dev = {
169 .platform_data = &roverp5p_pcmcia_ops
173 static int __init roverp5p_pcmcia_init(void)
175 return platform_device_register(&roverp5p_pcmcia_device);
178 static void __exit roverp5p_pcmcia_exit(void)
180 platform_device_unregister (&roverp5p_pcmcia_device);
183 module_init(roverp5p_pcmcia_init);
184 module_exit(roverp5p_pcmcia_exit);
186 MODULE_AUTHOR("Konstantine A. Beklemishev");
187 MODULE_DESCRIPTION("Rover P5+ PCMCIA driver");
188 MODULE_LICENSE("GPL");