arm: tegra: Correct tap delay for all T30 sdhci controllers
[linux-2.6.git] / arch / arm / mach-tegra / board-enterprise-sdhci.c
1 /*
2  * arch/arm/mach-tegra/board-enterprise-sdhci.c
3  *
4  * Copyright (C) 2011-2012 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 #ifdef CONFIG_MMC_EMBEDDED_SDIO
113 static struct embedded_sdio_data embedded_sdio_data0 = {
114         .cccr   = {
115                 .sdio_vsn       = 2,
116                 .multi_block    = 1,
117                 .low_speed      = 0,
118                 .wide_bus       = 0,
119                 .high_power     = 1,
120                 .high_speed     = 1,
121         },
122         .cis  = {
123                 .vendor         = 0x02d0,
124                 .device         = 0x4329,
125         },
126 };
127 #endif
128
129 static struct tegra_sdhci_platform_data tegra_sdhci_platform_data0 = {
130         .mmc_data = {
131                 .register_status_notify = enterprise_wifi_status_register,
132 #ifdef CONFIG_MMC_EMBEDDED_SDIO
133                 .embedded_sdio = &embedded_sdio_data0,
134 #endif
135                 /* FIXME need to revert the built_in change
136                 once we use get the signal strength fix of
137                 bcmdhd driver from broadcom for bcm4329 chipset*/
138                 .built_in = 0,
139         },
140 #ifndef CONFIG_MMC_EMBEDDED_SDIO
141         .pm_flags = MMC_PM_KEEP_POWER,
142 #endif
143         .cd_gpio = -1,
144         .wp_gpio = -1,
145         .power_gpio = -1,
146         .tap_delay = 0x0F,
147         .max_clk_limit = 45000000,
148 };
149
150 static struct tegra_sdhci_platform_data tegra_sdhci_platform_data2 = {
151         .cd_gpio = -1,
152         .wp_gpio = -1,
153         .power_gpio = -1,
154         .tap_delay = 0x0F,
155 };
156
157 static struct tegra_sdhci_platform_data tegra_sdhci_platform_data3 = {
158         .cd_gpio = -1,
159         .wp_gpio = -1,
160         .power_gpio = -1,
161         .is_8bit = 1,
162         .tap_delay = 0x0F,
163         .mmc_data = {
164                 .built_in = 1,
165         }
166 };
167
168 static struct platform_device tegra_sdhci_device0 = {
169         .name           = "sdhci-tegra",
170         .id             = 0,
171         .resource       = sdhci_resource0,
172         .num_resources  = ARRAY_SIZE(sdhci_resource0),
173         .dev = {
174                 .platform_data = &tegra_sdhci_platform_data0,
175         },
176 };
177
178 static struct platform_device tegra_sdhci_device2 = {
179         .name           = "sdhci-tegra",
180         .id             = 2,
181         .resource       = sdhci_resource2,
182         .num_resources  = ARRAY_SIZE(sdhci_resource2),
183         .dev = {
184                 .platform_data = &tegra_sdhci_platform_data2,
185         },
186 };
187
188 static struct platform_device tegra_sdhci_device3 = {
189         .name           = "sdhci-tegra",
190         .id             = 3,
191         .resource       = sdhci_resource3,
192         .num_resources  = ARRAY_SIZE(sdhci_resource3),
193         .dev = {
194                 .platform_data = &tegra_sdhci_platform_data3,
195         },
196 };
197
198 static int enterprise_wifi_status_register(
199                 void (*callback)(int card_present, void *dev_id),
200                 void *dev_id)
201 {
202         if (wifi_status_cb)
203                 return -EAGAIN;
204         wifi_status_cb = callback;
205         wifi_status_cb_devid = dev_id;
206         return 0;
207 }
208
209 static int enterprise_wifi_set_carddetect(int val)
210 {
211         pr_debug("%s: %d\n", __func__, val);
212         if (wifi_status_cb)
213                 wifi_status_cb(val, wifi_status_cb_devid);
214         else
215                 pr_warning("%s: Nobody to notify\n", __func__);
216         return 0;
217 }
218
219 static int enterprise_wifi_power(int on)
220 {
221         pr_debug("%s: %d\n", __func__, on);
222         gpio_set_value(ENTERPRISE_WLAN_PWR, on);
223         mdelay(100);
224         gpio_set_value(ENTERPRISE_WLAN_RST, on);
225         mdelay(200);
226
227         return 0;
228 }
229
230 static int enterprise_wifi_reset(int on)
231 {
232         pr_debug("%s: do nothing\n", __func__);
233         return 0;
234 }
235
236 #ifdef CONFIG_TEGRA_PREPOWER_WIFI
237 static int __init enterprise_wifi_prepower(void)
238 {
239         if (!machine_is_tegra_enterprise())
240                 return 0;
241
242         enterprise_wifi_power(1);
243
244         return 0;
245 }
246
247 subsys_initcall_sync(enterprise_wifi_prepower);
248 #endif
249
250 static int __init enterprise_wifi_init(void)
251 {
252         int rc;
253
254         rc = gpio_request(ENTERPRISE_WLAN_PWR, "wlan_power");
255         if (rc)
256                 pr_err("WLAN_PWR gpio request failed:%d\n", rc);
257         rc = gpio_request(ENTERPRISE_WLAN_RST, "wlan_rst");
258         if (rc)
259                 pr_err("WLAN_RST gpio request failed:%d\n", rc);
260         rc = gpio_request(ENTERPRISE_WLAN_WOW, "bcmsdh_sdmmc");
261         if (rc)
262                 pr_err("WLAN_WOW gpio request failed:%d\n", rc);
263
264         tegra_gpio_enable(ENTERPRISE_WLAN_PWR);
265         tegra_gpio_enable(ENTERPRISE_WLAN_RST);
266         tegra_gpio_enable(ENTERPRISE_WLAN_WOW);
267
268         rc = gpio_direction_output(ENTERPRISE_WLAN_PWR, 0);
269         if (rc)
270                 pr_err("WLAN_PWR gpio direction configuration failed:%d\n", rc);
271         gpio_direction_output(ENTERPRISE_WLAN_RST, 0);
272         if (rc)
273                 pr_err("WLAN_RST gpio direction configuration failed:%d\n", rc);
274         rc = gpio_direction_input(ENTERPRISE_WLAN_WOW);
275         if (rc)
276                 pr_err("WLAN_WOW gpio direction configuration failed:%d\n", rc);
277
278         platform_device_register(&enterprise_wifi_device);
279         return 0;
280 }
281
282 int __init enterprise_sdhci_init(void)
283 {
284         platform_device_register(&tegra_sdhci_device3);
285
286         tegra_gpio_enable(ENTERPRISE_SD_CD);
287         tegra_sdhci_platform_data2.cd_gpio = ENTERPRISE_SD_CD;
288         platform_device_register(&tegra_sdhci_device2);
289
290         platform_device_register(&tegra_sdhci_device0);
291         enterprise_wifi_init();
292         return 0;
293 }