diff options
author | Jonathan Herman <hermanjl@cs.unc.edu> | 2013-01-22 10:38:37 -0500 |
---|---|---|
committer | Jonathan Herman <hermanjl@cs.unc.edu> | 2013-01-22 10:38:37 -0500 |
commit | fcc9d2e5a6c89d22b8b773a64fb4ad21ac318446 (patch) | |
tree | a57612d1888735a2ec7972891b68c1ac5ec8faea /arch/arm/mach-tegra/board-enterprise-sdhci.c | |
parent | 8dea78da5cee153b8af9c07a2745f6c55057fe12 (diff) |
Diffstat (limited to 'arch/arm/mach-tegra/board-enterprise-sdhci.c')
-rw-r--r-- | arch/arm/mach-tegra/board-enterprise-sdhci.c | 269 |
1 files changed, 269 insertions, 0 deletions
diff --git a/arch/arm/mach-tegra/board-enterprise-sdhci.c b/arch/arm/mach-tegra/board-enterprise-sdhci.c new file mode 100644 index 00000000000..af1a9ea3dd5 --- /dev/null +++ b/arch/arm/mach-tegra/board-enterprise-sdhci.c | |||
@@ -0,0 +1,269 @@ | |||
1 | /* | ||
2 | * arch/arm/mach-tegra/board-enterprise-sdhci.c | ||
3 | * | ||
4 | * Copyright (C) 2011 NVIDIA Corporation. | ||
5 | * | ||
6 | * This software is licensed under the terms of the GNU General Public | ||
7 | * License version 2, as published by the Free Software Foundation, and | ||
8 | * may be copied, distributed, and modified under those terms. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU General Public License for more details. | ||
14 | * | ||
15 | */ | ||
16 | |||
17 | #include <linux/resource.h> | ||
18 | #include <linux/platform_device.h> | ||
19 | #include <linux/wlan_plat.h> | ||
20 | #include <linux/delay.h> | ||
21 | #include <linux/gpio.h> | ||
22 | #include <linux/clk.h> | ||
23 | #include <linux/err.h> | ||
24 | #include <linux/mmc/host.h> | ||
25 | |||
26 | #include <asm/mach-types.h> | ||
27 | #include <mach/irqs.h> | ||
28 | #include <mach/iomap.h> | ||
29 | #include <mach/sdhci.h> | ||
30 | |||
31 | #include "gpio-names.h" | ||
32 | #include "board.h" | ||
33 | |||
34 | |||
35 | #define ENTERPRISE_WLAN_PWR TEGRA_GPIO_PV2 | ||
36 | #define ENTERPRISE_WLAN_RST TEGRA_GPIO_PV3 | ||
37 | #define ENTERPRISE_WLAN_WOW TEGRA_GPIO_PU6 | ||
38 | #define ENTERPRISE_SD_CD TEGRA_GPIO_PI5 | ||
39 | |||
40 | static void (*wifi_status_cb)(int card_present, void *dev_id); | ||
41 | static void *wifi_status_cb_devid; | ||
42 | static int enterprise_wifi_status_register(void (*callback)(int , void *), void *); | ||
43 | |||
44 | static int enterprise_wifi_reset(int on); | ||
45 | static int enterprise_wifi_power(int on); | ||
46 | static int enterprise_wifi_set_carddetect(int val); | ||
47 | |||
48 | static struct wifi_platform_data enterprise_wifi_control = { | ||
49 | .set_power = enterprise_wifi_power, | ||
50 | .set_reset = enterprise_wifi_reset, | ||
51 | .set_carddetect = enterprise_wifi_set_carddetect, | ||
52 | }; | ||
53 | |||
54 | static struct resource wifi_resource[] = { | ||
55 | [0] = { | ||
56 | .name = "bcm4329_wlan_irq", | ||
57 | .start = TEGRA_GPIO_TO_IRQ(TEGRA_GPIO_PU6), | ||
58 | .end = TEGRA_GPIO_TO_IRQ(TEGRA_GPIO_PU6), | ||
59 | .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL | IORESOURCE_IRQ_SHAREABLE, | ||
60 | }, | ||
61 | }; | ||
62 | |||
63 | static struct platform_device enterprise_wifi_device = { | ||
64 | .name = "bcm4329_wlan", | ||
65 | .id = 1, | ||
66 | .num_resources = 1, | ||
67 | .resource = wifi_resource, | ||
68 | .dev = { | ||
69 | .platform_data = &enterprise_wifi_control, | ||
70 | }, | ||
71 | }; | ||
72 | |||
73 | static struct resource sdhci_resource0[] = { | ||
74 | [0] = { | ||
75 | .start = INT_SDMMC1, | ||
76 | .end = INT_SDMMC1, | ||
77 | .flags = IORESOURCE_IRQ, | ||
78 | }, | ||
79 | [1] = { | ||
80 | .start = TEGRA_SDMMC1_BASE, | ||
81 | .end = TEGRA_SDMMC1_BASE + TEGRA_SDMMC1_SIZE-1, | ||
82 | .flags = IORESOURCE_MEM, | ||
83 | }, | ||
84 | }; | ||
85 | |||
86 | static struct resource sdhci_resource2[] = { | ||
87 | [0] = { | ||
88 | .start = INT_SDMMC3, | ||
89 | .end = INT_SDMMC3, | ||
90 | .flags = IORESOURCE_IRQ, | ||
91 | }, | ||
92 | [1] = { | ||
93 | .start = TEGRA_SDMMC3_BASE, | ||
94 | .end = TEGRA_SDMMC3_BASE + TEGRA_SDMMC3_SIZE-1, | ||
95 | .flags = IORESOURCE_MEM, | ||
96 | }, | ||
97 | }; | ||
98 | |||
99 | static struct resource sdhci_resource3[] = { | ||
100 | [0] = { | ||
101 | .start = INT_SDMMC4, | ||
102 | .end = INT_SDMMC4, | ||
103 | .flags = IORESOURCE_IRQ, | ||
104 | }, | ||
105 | [1] = { | ||
106 | .start = TEGRA_SDMMC4_BASE, | ||
107 | .end = TEGRA_SDMMC4_BASE + TEGRA_SDMMC4_SIZE-1, | ||
108 | .flags = IORESOURCE_MEM, | ||
109 | }, | ||
110 | }; | ||
111 | |||
112 | static struct embedded_sdio_data embedded_sdio_data0 = { | ||
113 | .cccr = { | ||
114 | .sdio_vsn = 2, | ||
115 | .multi_block = 1, | ||
116 | .low_speed = 0, | ||
117 | .wide_bus = 0, | ||
118 | .high_power = 1, | ||
119 | .high_speed = 1, | ||
120 | }, | ||
121 | .cis = { | ||
122 | .vendor = 0x02d0, | ||
123 | .device = 0x4329, | ||
124 | }, | ||
125 | }; | ||
126 | |||
127 | static struct tegra_sdhci_platform_data tegra_sdhci_platform_data0 = { | ||
128 | .mmc_data = { | ||
129 | .register_status_notify = enterprise_wifi_status_register, | ||
130 | .embedded_sdio = &embedded_sdio_data0, | ||
131 | /* FIXME need to revert the built_in change | ||
132 | once we use get the signal strength fix of | ||
133 | bcmdhd driver from broadcom for bcm4329 chipset*/ | ||
134 | .built_in = 0, | ||
135 | }, | ||
136 | .cd_gpio = -1, | ||
137 | .wp_gpio = -1, | ||
138 | .power_gpio = -1, | ||
139 | .max_clk_limit = 45000000, | ||
140 | }; | ||
141 | |||
142 | static struct tegra_sdhci_platform_data tegra_sdhci_platform_data2 = { | ||
143 | .cd_gpio = -1, | ||
144 | .wp_gpio = -1, | ||
145 | .power_gpio = -1, | ||
146 | }; | ||
147 | |||
148 | static struct tegra_sdhci_platform_data tegra_sdhci_platform_data3 = { | ||
149 | .cd_gpio = -1, | ||
150 | .wp_gpio = -1, | ||
151 | .power_gpio = -1, | ||
152 | .is_8bit = 1, | ||
153 | .mmc_data = { | ||
154 | .built_in = 1, | ||
155 | } | ||
156 | }; | ||
157 | |||
158 | static struct platform_device tegra_sdhci_device0 = { | ||
159 | .name = "sdhci-tegra", | ||
160 | .id = 0, | ||
161 | .resource = sdhci_resource0, | ||
162 | .num_resources = ARRAY_SIZE(sdhci_resource0), | ||
163 | .dev = { | ||
164 | .platform_data = &tegra_sdhci_platform_data0, | ||
165 | }, | ||
166 | }; | ||
167 | |||
168 | static struct platform_device tegra_sdhci_device2 = { | ||
169 | .name = "sdhci-tegra", | ||
170 | .id = 2, | ||
171 | .resource = sdhci_resource2, | ||
172 | .num_resources = ARRAY_SIZE(sdhci_resource2), | ||
173 | .dev = { | ||
174 | .platform_data = &tegra_sdhci_platform_data2, | ||
175 | }, | ||
176 | }; | ||
177 | |||
178 | static struct platform_device tegra_sdhci_device3 = { | ||
179 | .name = "sdhci-tegra", | ||
180 | .id = 3, | ||
181 | .resource = sdhci_resource3, | ||
182 | .num_resources = ARRAY_SIZE(sdhci_resource3), | ||
183 | .dev = { | ||
184 | .platform_data = &tegra_sdhci_platform_data3, | ||
185 | }, | ||
186 | }; | ||
187 | |||
188 | static int enterprise_wifi_status_register( | ||
189 | void (*callback)(int card_present, void *dev_id), | ||
190 | void *dev_id) | ||
191 | { | ||
192 | if (wifi_status_cb) | ||
193 | return -EAGAIN; | ||
194 | wifi_status_cb = callback; | ||
195 | wifi_status_cb_devid = dev_id; | ||
196 | return 0; | ||
197 | } | ||
198 | |||
199 | static int enterprise_wifi_set_carddetect(int val) | ||
200 | { | ||
201 | pr_debug("%s: %d\n", __func__, val); | ||
202 | if (wifi_status_cb) | ||
203 | wifi_status_cb(val, wifi_status_cb_devid); | ||
204 | else | ||
205 | pr_warning("%s: Nobody to notify\n", __func__); | ||
206 | return 0; | ||
207 | } | ||
208 | |||
209 | static int enterprise_wifi_power(int on) | ||
210 | { | ||
211 | pr_debug("%s: %d\n", __func__, on); | ||
212 | gpio_set_value(ENTERPRISE_WLAN_PWR, on); | ||
213 | mdelay(100); | ||
214 | gpio_set_value(ENTERPRISE_WLAN_RST, on); | ||
215 | mdelay(200); | ||
216 | |||
217 | return 0; | ||
218 | } | ||
219 | |||
220 | static int enterprise_wifi_reset(int on) | ||
221 | { | ||
222 | pr_debug("%s: do nothing\n", __func__); | ||
223 | return 0; | ||
224 | } | ||
225 | |||
226 | static int __init enterprise_wifi_init(void) | ||
227 | { | ||
228 | int rc; | ||
229 | |||
230 | rc = gpio_request(ENTERPRISE_WLAN_PWR, "wlan_power"); | ||
231 | if (rc) | ||
232 | pr_err("WLAN_PWR gpio request failed:%d\n", rc); | ||
233 | rc = gpio_request(ENTERPRISE_WLAN_RST, "wlan_rst"); | ||
234 | if (rc) | ||
235 | pr_err("WLAN_RST gpio request failed:%d\n", rc); | ||
236 | rc = gpio_request(ENTERPRISE_WLAN_WOW, "bcmsdh_sdmmc"); | ||
237 | if (rc) | ||
238 | pr_err("WLAN_WOW gpio request failed:%d\n", rc); | ||
239 | |||
240 | tegra_gpio_enable(ENTERPRISE_WLAN_PWR); | ||
241 | tegra_gpio_enable(ENTERPRISE_WLAN_RST); | ||
242 | tegra_gpio_enable(ENTERPRISE_WLAN_WOW); | ||
243 | |||
244 | rc = gpio_direction_output(ENTERPRISE_WLAN_PWR, 0); | ||
245 | if (rc) | ||
246 | pr_err("WLAN_PWR gpio direction configuration failed:%d\n", rc); | ||
247 | gpio_direction_output(ENTERPRISE_WLAN_RST, 0); | ||
248 | if (rc) | ||
249 | pr_err("WLAN_RST gpio direction configuration failed:%d\n", rc); | ||
250 | rc = gpio_direction_input(ENTERPRISE_WLAN_WOW); | ||
251 | if (rc) | ||
252 | pr_err("WLAN_WOW gpio direction configuration failed:%d\n", rc); | ||
253 | |||
254 | platform_device_register(&enterprise_wifi_device); | ||
255 | return 0; | ||
256 | } | ||
257 | |||
258 | int __init enterprise_sdhci_init(void) | ||
259 | { | ||
260 | platform_device_register(&tegra_sdhci_device3); | ||
261 | |||
262 | tegra_gpio_enable(ENTERPRISE_SD_CD); | ||
263 | tegra_sdhci_platform_data2.cd_gpio = ENTERPRISE_SD_CD; | ||
264 | platform_device_register(&tegra_sdhci_device2); | ||
265 | |||
266 | platform_device_register(&tegra_sdhci_device0); | ||
267 | enterprise_wifi_init(); | ||
268 | return 0; | ||
269 | } | ||