Root/
1 | /* |
2 | * linux/drivers/pcmcia/pxa2xx_palmtc.c |
3 | * |
4 | * Driver for Palm Tungsten|C PCMCIA |
5 | * |
6 | * Copyright (C) 2008 Alex Osborne <ato@meshy.org> |
7 | * Copyright (C) 2009-2011 Marek Vasut <marek.vasut@gmail.com> |
8 | * |
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. |
12 | * |
13 | */ |
14 | |
15 | #include <linux/module.h> |
16 | #include <linux/platform_device.h> |
17 | #include <linux/gpio.h> |
18 | #include <linux/delay.h> |
19 | |
20 | #include <asm/mach-types.h> |
21 | #include <mach/palmtc.h> |
22 | #include "soc_common.h" |
23 | |
24 | static struct gpio palmtc_pcmcia_gpios[] = { |
25 | { GPIO_NR_PALMTC_PCMCIA_POWER1, GPIOF_INIT_LOW, "PCMCIA Power 1" }, |
26 | { GPIO_NR_PALMTC_PCMCIA_POWER2, GPIOF_INIT_LOW, "PCMCIA Power 2" }, |
27 | { GPIO_NR_PALMTC_PCMCIA_POWER3, GPIOF_INIT_LOW, "PCMCIA Power 3" }, |
28 | { GPIO_NR_PALMTC_PCMCIA_RESET, GPIOF_INIT_HIGH,"PCMCIA Reset" }, |
29 | { GPIO_NR_PALMTC_PCMCIA_PWRREADY, GPIOF_IN, "PCMCIA Power Ready" }, |
30 | }; |
31 | |
32 | static int palmtc_pcmcia_hw_init(struct soc_pcmcia_socket *skt) |
33 | { |
34 | int ret; |
35 | |
36 | ret = gpio_request_array(palmtc_pcmcia_gpios, |
37 | ARRAY_SIZE(palmtc_pcmcia_gpios)); |
38 | |
39 | skt->stat[SOC_STAT_RDY].gpio = GPIO_NR_PALMTC_PCMCIA_READY; |
40 | skt->stat[SOC_STAT_RDY].name = "PCMCIA Ready"; |
41 | |
42 | return ret; |
43 | } |
44 | |
45 | static void palmtc_pcmcia_hw_shutdown(struct soc_pcmcia_socket *skt) |
46 | { |
47 | gpio_free_array(palmtc_pcmcia_gpios, ARRAY_SIZE(palmtc_pcmcia_gpios)); |
48 | } |
49 | |
50 | static void palmtc_pcmcia_socket_state(struct soc_pcmcia_socket *skt, |
51 | struct pcmcia_state *state) |
52 | { |
53 | state->detect = 1; /* always inserted */ |
54 | state->vs_3v = 1; |
55 | state->vs_Xv = 0; |
56 | } |
57 | |
58 | static int palmtc_wifi_powerdown(void) |
59 | { |
60 | gpio_set_value(GPIO_NR_PALMTC_PCMCIA_RESET, 1); |
61 | gpio_set_value(GPIO_NR_PALMTC_PCMCIA_POWER2, 0); |
62 | mdelay(40); |
63 | gpio_set_value(GPIO_NR_PALMTC_PCMCIA_POWER1, 0); |
64 | return 0; |
65 | } |
66 | |
67 | static int palmtc_wifi_powerup(void) |
68 | { |
69 | int timeout = 50; |
70 | |
71 | gpio_set_value(GPIO_NR_PALMTC_PCMCIA_POWER3, 1); |
72 | mdelay(50); |
73 | |
74 | /* Power up the card, 1.8V first, after a while 3.3V */ |
75 | gpio_set_value(GPIO_NR_PALMTC_PCMCIA_POWER1, 1); |
76 | mdelay(100); |
77 | gpio_set_value(GPIO_NR_PALMTC_PCMCIA_POWER2, 1); |
78 | |
79 | /* Wait till the card is ready */ |
80 | while (!gpio_get_value(GPIO_NR_PALMTC_PCMCIA_PWRREADY) && |
81 | timeout) { |
82 | mdelay(1); |
83 | timeout--; |
84 | } |
85 | |
86 | /* Power down the WiFi in case of error */ |
87 | if (!timeout) { |
88 | palmtc_wifi_powerdown(); |
89 | return 1; |
90 | } |
91 | |
92 | /* Reset the card */ |
93 | gpio_set_value(GPIO_NR_PALMTC_PCMCIA_RESET, 1); |
94 | mdelay(20); |
95 | gpio_set_value(GPIO_NR_PALMTC_PCMCIA_RESET, 0); |
96 | mdelay(25); |
97 | |
98 | gpio_set_value(GPIO_NR_PALMTC_PCMCIA_POWER3, 0); |
99 | |
100 | return 0; |
101 | } |
102 | |
103 | static int palmtc_pcmcia_configure_socket(struct soc_pcmcia_socket *skt, |
104 | const socket_state_t *state) |
105 | { |
106 | int ret = 1; |
107 | |
108 | if (state->Vcc == 0) |
109 | ret = palmtc_wifi_powerdown(); |
110 | else if (state->Vcc == 33) |
111 | ret = palmtc_wifi_powerup(); |
112 | |
113 | return ret; |
114 | } |
115 | |
116 | static struct pcmcia_low_level palmtc_pcmcia_ops = { |
117 | .owner = THIS_MODULE, |
118 | |
119 | .first = 0, |
120 | .nr = 1, |
121 | |
122 | .hw_init = palmtc_pcmcia_hw_init, |
123 | .hw_shutdown = palmtc_pcmcia_hw_shutdown, |
124 | |
125 | .socket_state = palmtc_pcmcia_socket_state, |
126 | .configure_socket = palmtc_pcmcia_configure_socket, |
127 | }; |
128 | |
129 | static struct platform_device *palmtc_pcmcia_device; |
130 | |
131 | static int __init palmtc_pcmcia_init(void) |
132 | { |
133 | int ret; |
134 | |
135 | if (!machine_is_palmtc()) |
136 | return -ENODEV; |
137 | |
138 | palmtc_pcmcia_device = platform_device_alloc("pxa2xx-pcmcia", -1); |
139 | if (!palmtc_pcmcia_device) |
140 | return -ENOMEM; |
141 | |
142 | ret = platform_device_add_data(palmtc_pcmcia_device, &palmtc_pcmcia_ops, |
143 | sizeof(palmtc_pcmcia_ops)); |
144 | |
145 | if (!ret) |
146 | ret = platform_device_add(palmtc_pcmcia_device); |
147 | |
148 | if (ret) |
149 | platform_device_put(palmtc_pcmcia_device); |
150 | |
151 | return ret; |
152 | } |
153 | |
154 | static void __exit palmtc_pcmcia_exit(void) |
155 | { |
156 | platform_device_unregister(palmtc_pcmcia_device); |
157 | } |
158 | |
159 | module_init(palmtc_pcmcia_init); |
160 | module_exit(palmtc_pcmcia_exit); |
161 | |
162 | MODULE_AUTHOR("Alex Osborne <ato@meshy.org>," |
163 | " Marek Vasut <marek.vasut@gmail.com>"); |
164 | MODULE_DESCRIPTION("PCMCIA support for Palm Tungsten|C"); |
165 | MODULE_ALIAS("platform:pxa2xx-pcmcia"); |
166 | MODULE_LICENSE("GPL"); |
167 |
Branches:
ben-wpan
ben-wpan-stefan
javiroman/ks7010
jz-2.6.34
jz-2.6.34-rc5
jz-2.6.34-rc6
jz-2.6.34-rc7
jz-2.6.35
jz-2.6.36
jz-2.6.37
jz-2.6.38
jz-2.6.39
jz-3.0
jz-3.1
jz-3.11
jz-3.12
jz-3.13
jz-3.15
jz-3.16
jz-3.18-dt
jz-3.2
jz-3.3
jz-3.4
jz-3.5
jz-3.6
jz-3.6-rc2-pwm
jz-3.9
jz-3.9-clk
jz-3.9-rc8
jz47xx
jz47xx-2.6.38
master
Tags:
od-2011-09-04
od-2011-09-18
v2.6.34-rc5
v2.6.34-rc6
v2.6.34-rc7
v3.9