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-cardhu-sdhci.c | |
parent | 8dea78da5cee153b8af9c07a2745f6c55057fe12 (diff) |
Diffstat (limited to 'arch/arm/mach-tegra/board-cardhu-sdhci.c')
-rw-r--r-- | arch/arm/mach-tegra/board-cardhu-sdhci.c | 305 |
1 files changed, 305 insertions, 0 deletions
diff --git a/arch/arm/mach-tegra/board-cardhu-sdhci.c b/arch/arm/mach-tegra/board-cardhu-sdhci.c new file mode 100644 index 00000000000..cbe948fa4a3 --- /dev/null +++ b/arch/arm/mach-tegra/board-cardhu-sdhci.c | |||
@@ -0,0 +1,305 @@ | |||
1 | /* | ||
2 | * arch/arm/mach-tegra/board-harmony-sdhci.c | ||
3 | * | ||
4 | * Copyright (C) 2010 Google, Inc. | ||
5 | * Copyright (C) 2011 NVIDIA Corporation. | ||
6 | * | ||
7 | * This software is licensed under the terms of the GNU General Public | ||
8 | * License version 2, as published by the Free Software Foundation, and | ||
9 | * may be copied, distributed, and modified under those terms. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | */ | ||
17 | |||
18 | #include <linux/resource.h> | ||
19 | #include <linux/platform_device.h> | ||
20 | #include <linux/wlan_plat.h> | ||
21 | #include <linux/delay.h> | ||
22 | #include <linux/gpio.h> | ||
23 | #include <linux/clk.h> | ||
24 | #include <linux/err.h> | ||
25 | #include <linux/mmc/host.h> | ||
26 | |||
27 | #include <asm/mach-types.h> | ||
28 | #include <mach/irqs.h> | ||
29 | #include <mach/iomap.h> | ||
30 | #include <mach/sdhci.h> | ||
31 | |||
32 | #include "gpio-names.h" | ||
33 | #include "board.h" | ||
34 | #include "board-cardhu.h" | ||
35 | |||
36 | #define CARDHU_WLAN_PWR TEGRA_GPIO_PD4 | ||
37 | #define CARDHU_WLAN_RST TEGRA_GPIO_PD3 | ||
38 | #define CARDHU_WLAN_WOW TEGRA_GPIO_PO4 | ||
39 | #define CARDHU_SD_CD TEGRA_GPIO_PV3 | ||
40 | #ifndef CONFIG_TEGRA_SDMMC1_UNLOCK | ||
41 | #define CARDHU_SD_WP TEGRA_GPIO_PV2 | ||
42 | #else | ||
43 | #define CARDHU_SD_WP -1 | ||
44 | #endif | ||
45 | //#define CARDHU_SD_PWR TEGRA_GPIO_PD4 | ||
46 | #define PM269_SD_WP -1 | ||
47 | |||
48 | static void (*wifi_status_cb)(int card_present, void *dev_id); | ||
49 | static void *wifi_status_cb_devid; | ||
50 | static int cardhu_wifi_status_register(void (*callback)(int , void *), void *); | ||
51 | |||
52 | static int cardhu_wifi_reset(int on); | ||
53 | static int cardhu_wifi_power(int on); | ||
54 | static int cardhu_wifi_set_carddetect(int val); | ||
55 | |||
56 | static struct wifi_platform_data cardhu_wifi_control = { | ||
57 | .set_power = cardhu_wifi_power, | ||
58 | .set_reset = cardhu_wifi_reset, | ||
59 | .set_carddetect = cardhu_wifi_set_carddetect, | ||
60 | }; | ||
61 | |||
62 | static struct resource wifi_resource[] = { | ||
63 | [0] = { | ||
64 | .name = "bcm4329_wlan_irq", | ||
65 | .start = TEGRA_GPIO_TO_IRQ(TEGRA_GPIO_PO4), | ||
66 | .end = TEGRA_GPIO_TO_IRQ(TEGRA_GPIO_PO4), | ||
67 | .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL | IORESOURCE_IRQ_SHAREABLE, | ||
68 | }, | ||
69 | }; | ||
70 | |||
71 | static struct platform_device cardhu_wifi_device = { | ||
72 | .name = "bcm4329_wlan", | ||
73 | .id = 1, | ||
74 | .num_resources = 1, | ||
75 | .resource = wifi_resource, | ||
76 | .dev = { | ||
77 | .platform_data = &cardhu_wifi_control, | ||
78 | }, | ||
79 | }; | ||
80 | |||
81 | static struct resource sdhci_resource0[] = { | ||
82 | [0] = { | ||
83 | .start = INT_SDMMC1, | ||
84 | .end = INT_SDMMC1, | ||
85 | .flags = IORESOURCE_IRQ, | ||
86 | }, | ||
87 | [1] = { | ||
88 | .start = TEGRA_SDMMC1_BASE, | ||
89 | .end = TEGRA_SDMMC1_BASE + TEGRA_SDMMC1_SIZE-1, | ||
90 | .flags = IORESOURCE_MEM, | ||
91 | }, | ||
92 | }; | ||
93 | |||
94 | static struct resource sdhci_resource2[] = { | ||
95 | [0] = { | ||
96 | .start = INT_SDMMC3, | ||
97 | .end = INT_SDMMC3, | ||
98 | .flags = IORESOURCE_IRQ, | ||
99 | }, | ||
100 | [1] = { | ||
101 | .start = TEGRA_SDMMC3_BASE, | ||
102 | .end = TEGRA_SDMMC3_BASE + TEGRA_SDMMC3_SIZE-1, | ||
103 | .flags = IORESOURCE_MEM, | ||
104 | }, | ||
105 | }; | ||
106 | |||
107 | static struct resource sdhci_resource3[] = { | ||
108 | [0] = { | ||
109 | .start = INT_SDMMC4, | ||
110 | .end = INT_SDMMC4, | ||
111 | .flags = IORESOURCE_IRQ, | ||
112 | }, | ||
113 | [1] = { | ||
114 | .start = TEGRA_SDMMC4_BASE, | ||
115 | .end = TEGRA_SDMMC4_BASE + TEGRA_SDMMC4_SIZE-1, | ||
116 | .flags = IORESOURCE_MEM, | ||
117 | }, | ||
118 | }; | ||
119 | |||
120 | static struct embedded_sdio_data embedded_sdio_data2 = { | ||
121 | .cccr = { | ||
122 | .sdio_vsn = 2, | ||
123 | .multi_block = 1, | ||
124 | .low_speed = 0, | ||
125 | .wide_bus = 0, | ||
126 | .high_power = 1, | ||
127 | .high_speed = 1, | ||
128 | }, | ||
129 | .cis = { | ||
130 | .vendor = 0x02d0, | ||
131 | .device = 0x4329, | ||
132 | }, | ||
133 | }; | ||
134 | |||
135 | static struct tegra_sdhci_platform_data tegra_sdhci_platform_data2 = { | ||
136 | .mmc_data = { | ||
137 | .register_status_notify = cardhu_wifi_status_register, | ||
138 | .embedded_sdio = &embedded_sdio_data2, | ||
139 | .built_in = 1, | ||
140 | }, | ||
141 | .cd_gpio = -1, | ||
142 | .wp_gpio = -1, | ||
143 | .power_gpio = -1, | ||
144 | /* .tap_delay = 6, | ||
145 | .is_voltage_switch_supported = false, | ||
146 | .vdd_rail_name = NULL, | ||
147 | .slot_rail_name = NULL, | ||
148 | .vdd_max_uv = -1, | ||
149 | .vdd_min_uv = -1, | ||
150 | .max_clk = 0, | ||
151 | .is_8bit_supported = false, */ | ||
152 | }; | ||
153 | |||
154 | static struct tegra_sdhci_platform_data tegra_sdhci_platform_data0 = { | ||
155 | .cd_gpio = CARDHU_SD_CD, | ||
156 | .wp_gpio = CARDHU_SD_WP, | ||
157 | .power_gpio = -1, | ||
158 | /* .tap_delay = 6, | ||
159 | .is_voltage_switch_supported = true, | ||
160 | .vdd_rail_name = "vddio_sdmmc1", | ||
161 | .slot_rail_name = "vddio_sd_slot", | ||
162 | .vdd_max_uv = 3320000, | ||
163 | .vdd_min_uv = 3280000, | ||
164 | .max_clk = 208000000, | ||
165 | .is_8bit_supported = false, */ | ||
166 | }; | ||
167 | |||
168 | static struct tegra_sdhci_platform_data tegra_sdhci_platform_data3 = { | ||
169 | .cd_gpio = -1, | ||
170 | .wp_gpio = -1, | ||
171 | .power_gpio = -1, | ||
172 | .is_8bit = 1, | ||
173 | .tap_delay = 0x0F, | ||
174 | .mmc_data = { | ||
175 | .built_in = 1, | ||
176 | } | ||
177 | /* .tap_delay = 6, | ||
178 | .is_voltage_switch_supported = false, | ||
179 | .vdd_rail_name = NULL, | ||
180 | .slot_rail_name = NULL, | ||
181 | .vdd_max_uv = -1, | ||
182 | .vdd_min_uv = -1, | ||
183 | .max_clk = 48000000, | ||
184 | .is_8bit_supported = true, */ | ||
185 | }; | ||
186 | |||
187 | static struct platform_device tegra_sdhci_device0 = { | ||
188 | .name = "sdhci-tegra", | ||
189 | .id = 0, | ||
190 | .resource = sdhci_resource0, | ||
191 | .num_resources = ARRAY_SIZE(sdhci_resource0), | ||
192 | .dev = { | ||
193 | .platform_data = &tegra_sdhci_platform_data0, | ||
194 | }, | ||
195 | }; | ||
196 | |||
197 | static struct platform_device tegra_sdhci_device2 = { | ||
198 | .name = "sdhci-tegra", | ||
199 | .id = 2, | ||
200 | .resource = sdhci_resource2, | ||
201 | .num_resources = ARRAY_SIZE(sdhci_resource2), | ||
202 | .dev = { | ||
203 | .platform_data = &tegra_sdhci_platform_data2, | ||
204 | }, | ||
205 | }; | ||
206 | |||
207 | static struct platform_device tegra_sdhci_device3 = { | ||
208 | .name = "sdhci-tegra", | ||
209 | .id = 3, | ||
210 | .resource = sdhci_resource3, | ||
211 | .num_resources = ARRAY_SIZE(sdhci_resource3), | ||
212 | .dev = { | ||
213 | .platform_data = &tegra_sdhci_platform_data3, | ||
214 | }, | ||
215 | }; | ||
216 | |||
217 | static int cardhu_wifi_status_register( | ||
218 | void (*callback)(int card_present, void *dev_id), | ||
219 | void *dev_id) | ||
220 | { | ||
221 | if (wifi_status_cb) | ||
222 | return -EAGAIN; | ||
223 | wifi_status_cb = callback; | ||
224 | wifi_status_cb_devid = dev_id; | ||
225 | return 0; | ||
226 | } | ||
227 | |||
228 | static int cardhu_wifi_set_carddetect(int val) | ||
229 | { | ||
230 | pr_debug("%s: %d\n", __func__, val); | ||
231 | if (wifi_status_cb) | ||
232 | wifi_status_cb(val, wifi_status_cb_devid); | ||
233 | else | ||
234 | pr_warning("%s: Nobody to notify\n", __func__); | ||
235 | return 0; | ||
236 | } | ||
237 | |||
238 | static int cardhu_wifi_power(int on) | ||
239 | { | ||
240 | pr_debug("%s: %d\n", __func__, on); | ||
241 | gpio_set_value(CARDHU_WLAN_PWR, on); | ||
242 | mdelay(100); | ||
243 | gpio_set_value(CARDHU_WLAN_RST, on); | ||
244 | mdelay(200); | ||
245 | |||
246 | return 0; | ||
247 | } | ||
248 | |||
249 | static int cardhu_wifi_reset(int on) | ||
250 | { | ||
251 | pr_debug("%s: do nothing\n", __func__); | ||
252 | return 0; | ||
253 | } | ||
254 | |||
255 | static int __init cardhu_wifi_init(void) | ||
256 | { | ||
257 | int rc; | ||
258 | |||
259 | rc = gpio_request(CARDHU_WLAN_PWR, "wlan_power"); | ||
260 | if (rc) | ||
261 | pr_err("WLAN_PWR gpio request failed:%d\n", rc); | ||
262 | rc = gpio_request(CARDHU_WLAN_RST, "wlan_rst"); | ||
263 | if (rc) | ||
264 | pr_err("WLAN_RST gpio request failed:%d\n", rc); | ||
265 | rc = gpio_request(CARDHU_WLAN_WOW, "bcmsdh_sdmmc"); | ||
266 | if (rc) | ||
267 | pr_err("WLAN_WOW gpio request failed:%d\n", rc); | ||
268 | |||
269 | tegra_gpio_enable(CARDHU_WLAN_PWR); | ||
270 | tegra_gpio_enable(CARDHU_WLAN_RST); | ||
271 | tegra_gpio_enable(CARDHU_WLAN_WOW); | ||
272 | |||
273 | rc = gpio_direction_output(CARDHU_WLAN_PWR, 0); | ||
274 | if (rc) | ||
275 | pr_err("WLAN_PWR gpio direction configuration failed:%d\n", rc); | ||
276 | gpio_direction_output(CARDHU_WLAN_RST, 0); | ||
277 | if (rc) | ||
278 | pr_err("WLAN_RST gpio direction configuration failed:%d\n", rc); | ||
279 | rc = gpio_direction_input(CARDHU_WLAN_WOW); | ||
280 | if (rc) | ||
281 | pr_err("WLAN_WOW gpio direction configuration failed:%d\n", rc); | ||
282 | |||
283 | platform_device_register(&cardhu_wifi_device); | ||
284 | return 0; | ||
285 | } | ||
286 | |||
287 | int __init cardhu_sdhci_init(void) | ||
288 | { | ||
289 | struct board_info board_info; | ||
290 | tegra_get_board_info(&board_info); | ||
291 | if ((board_info.board_id == BOARD_PM269) || | ||
292 | (board_info.board_id == BOARD_E1257) || | ||
293 | (board_info.board_id == BOARD_PM305) || | ||
294 | (board_info.board_id == BOARD_PM311)) { | ||
295 | tegra_sdhci_platform_data0.wp_gpio = PM269_SD_WP; | ||
296 | tegra_sdhci_platform_data2.max_clk_limit = 12000000; | ||
297 | } | ||
298 | |||
299 | platform_device_register(&tegra_sdhci_device3); | ||
300 | platform_device_register(&tegra_sdhci_device2); | ||
301 | platform_device_register(&tegra_sdhci_device0); | ||
302 | |||
303 | //cardhu_wifi_init(); | ||
304 | return 0; | ||
305 | } | ||