2 * linux/drivers/pcmcia/pxa2xx_palmtc.c
4 * Driver for Palm Tungsten|C PCMCIA
6 * Copyright (C) 2008 Alex Osborne <ato@meshy.org>
7 * Copyright (C) 2009 Marek Vasut <marek.vasut@gmail.com>
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License version 2 as
11 * published by the Free Software Foundation.
15 #include <linux/module.h>
16 #include <linux/platform_device.h>
17 #include <linux/gpio.h>
18 #include <linux/delay.h>
20 #include <asm/mach-types.h>
21 #include <mach/palmtc.h>
22 #include "soc_common.h"
24 static int palmtc_pcmcia_hw_init(struct soc_pcmcia_socket
*skt
)
28 ret
= gpio_request(GPIO_NR_PALMTC_PCMCIA_POWER1
, "PCMCIA PWR1");
31 ret
= gpio_direction_output(GPIO_NR_PALMTC_PCMCIA_POWER1
, 0);
35 ret
= gpio_request(GPIO_NR_PALMTC_PCMCIA_POWER2
, "PCMCIA PWR2");
38 ret
= gpio_direction_output(GPIO_NR_PALMTC_PCMCIA_POWER2
, 0);
42 ret
= gpio_request(GPIO_NR_PALMTC_PCMCIA_POWER3
, "PCMCIA PWR3");
45 ret
= gpio_direction_output(GPIO_NR_PALMTC_PCMCIA_POWER3
, 0);
49 ret
= gpio_request(GPIO_NR_PALMTC_PCMCIA_RESET
, "PCMCIA RST");
52 ret
= gpio_direction_output(GPIO_NR_PALMTC_PCMCIA_RESET
, 1);
56 ret
= gpio_request(GPIO_NR_PALMTC_PCMCIA_READY
, "PCMCIA RDY");
59 ret
= gpio_direction_input(GPIO_NR_PALMTC_PCMCIA_READY
);
63 ret
= gpio_request(GPIO_NR_PALMTC_PCMCIA_PWRREADY
, "PCMCIA PWRRDY");
66 ret
= gpio_direction_input(GPIO_NR_PALMTC_PCMCIA_PWRREADY
);
70 skt
->socket
.pci_irq
= IRQ_GPIO(GPIO_NR_PALMTC_PCMCIA_READY
);
74 gpio_free(GPIO_NR_PALMTC_PCMCIA_PWRREADY
);
76 gpio_free(GPIO_NR_PALMTC_PCMCIA_READY
);
78 gpio_free(GPIO_NR_PALMTC_PCMCIA_RESET
);
80 gpio_free(GPIO_NR_PALMTC_PCMCIA_POWER3
);
82 gpio_free(GPIO_NR_PALMTC_PCMCIA_POWER2
);
84 gpio_free(GPIO_NR_PALMTC_PCMCIA_POWER1
);
89 static void palmtc_pcmcia_hw_shutdown(struct soc_pcmcia_socket
*skt
)
91 gpio_free(GPIO_NR_PALMTC_PCMCIA_PWRREADY
);
92 gpio_free(GPIO_NR_PALMTC_PCMCIA_READY
);
93 gpio_free(GPIO_NR_PALMTC_PCMCIA_RESET
);
94 gpio_free(GPIO_NR_PALMTC_PCMCIA_POWER3
);
95 gpio_free(GPIO_NR_PALMTC_PCMCIA_POWER2
);
96 gpio_free(GPIO_NR_PALMTC_PCMCIA_POWER1
);
99 static void palmtc_pcmcia_socket_state(struct soc_pcmcia_socket
*skt
,
100 struct pcmcia_state
*state
)
102 state
->detect
= 1; /* always inserted */
103 state
->ready
= !!gpio_get_value(GPIO_NR_PALMTC_PCMCIA_READY
);
111 static int palmtc_wifi_powerdown(void)
113 gpio_set_value(GPIO_NR_PALMTC_PCMCIA_RESET
, 1);
114 gpio_set_value(GPIO_NR_PALMTC_PCMCIA_POWER2
, 0);
116 gpio_set_value(GPIO_NR_PALMTC_PCMCIA_POWER1
, 0);
120 static int palmtc_wifi_powerup(void)
124 gpio_set_value(GPIO_NR_PALMTC_PCMCIA_POWER3
, 1);
127 /* Power up the card, 1.8V first, after a while 3.3V */
128 gpio_set_value(GPIO_NR_PALMTC_PCMCIA_POWER1
, 1);
130 gpio_set_value(GPIO_NR_PALMTC_PCMCIA_POWER2
, 1);
132 /* Wait till the card is ready */
133 while (!gpio_get_value(GPIO_NR_PALMTC_PCMCIA_PWRREADY
) &&
139 /* Power down the WiFi in case of error */
141 palmtc_wifi_powerdown();
146 gpio_set_value(GPIO_NR_PALMTC_PCMCIA_RESET
, 1);
148 gpio_set_value(GPIO_NR_PALMTC_PCMCIA_RESET
, 0);
151 gpio_set_value(GPIO_NR_PALMTC_PCMCIA_POWER3
, 0);
156 static int palmtc_pcmcia_configure_socket(struct soc_pcmcia_socket
*skt
,
157 const socket_state_t
*state
)
162 ret
= palmtc_wifi_powerdown();
163 else if (state
->Vcc
== 33)
164 ret
= palmtc_wifi_powerup();
169 static void palmtc_pcmcia_socket_init(struct soc_pcmcia_socket
*skt
)
173 static void palmtc_pcmcia_socket_suspend(struct soc_pcmcia_socket
*skt
)
177 static struct pcmcia_low_level palmtc_pcmcia_ops
= {
178 .owner
= THIS_MODULE
,
183 .hw_init
= palmtc_pcmcia_hw_init
,
184 .hw_shutdown
= palmtc_pcmcia_hw_shutdown
,
186 .socket_state
= palmtc_pcmcia_socket_state
,
187 .configure_socket
= palmtc_pcmcia_configure_socket
,
189 .socket_init
= palmtc_pcmcia_socket_init
,
190 .socket_suspend
= palmtc_pcmcia_socket_suspend
,
193 static struct platform_device
*palmtc_pcmcia_device
;
195 static int __init
palmtc_pcmcia_init(void)
199 if (!machine_is_palmtc())
202 palmtc_pcmcia_device
= platform_device_alloc("pxa2xx-pcmcia", -1);
203 if (!palmtc_pcmcia_device
)
206 ret
= platform_device_add_data(palmtc_pcmcia_device
, &palmtc_pcmcia_ops
,
207 sizeof(palmtc_pcmcia_ops
));
210 ret
= platform_device_add(palmtc_pcmcia_device
);
213 platform_device_put(palmtc_pcmcia_device
);
218 static void __exit
palmtc_pcmcia_exit(void)
220 platform_device_unregister(palmtc_pcmcia_device
);
223 module_init(palmtc_pcmcia_init
);
224 module_exit(palmtc_pcmcia_exit
);
226 MODULE_AUTHOR("Alex Osborne <ato@meshy.org>,"
227 " Marek Vasut <marek.vasut@gmail.com>");
228 MODULE_DESCRIPTION("PCMCIA support for Palm Tungsten|C");
229 MODULE_ALIAS("platform:pxa2xx-pcmcia");
230 MODULE_LICENSE("GPL");