arm: tegra: sd: enable sd dpd
[linux-2.6.git] / arch / arm / mach-tegra / board-whistler-sdhci.c
1 /*
2  * arch/arm/mach-tegra/board-whistler-sdhci.c
3  *
4  * Copyright (C) 2010 Google, Inc.
5  * Copyright (C) 2011-2012 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
35 #define WHISTLER_WLAN_PWR       TEGRA_GPIO_PK5
36 #define WHISTLER_WLAN_RST       TEGRA_GPIO_PK6
37 #define WHISTLER_WLAN_WOW       TEGRA_GPIO_PU5
38
39 #define WHISTLER_EXT_SDCARD_DETECT      TEGRA_GPIO_PI5
40
41 static void (*wifi_status_cb)(int card_present, void *dev_id);
42 static void *wifi_status_cb_devid;
43
44 static int whistler_wifi_status_register(
45                 void (*sdhcicallback)(int card_present, void *dev_id),
46                 void *dev_id)
47 {
48         if (wifi_status_cb)
49                 return -EAGAIN;
50         wifi_status_cb = sdhcicallback;
51         wifi_status_cb_devid = dev_id;
52         return 0;
53 }
54
55 static int whistler_wifi_set_carddetect(int val)
56 {
57         pr_debug("%s: %d\n", __func__, val);
58         if (wifi_status_cb)
59                 wifi_status_cb(val, wifi_status_cb_devid);
60         else
61                 pr_warning("%s: Nobody to notify\n", __func__);
62         return 0;
63 }
64
65 static int whistler_wifi_power(int on)
66 {
67         gpio_set_value(WHISTLER_WLAN_PWR, on);
68         mdelay(100);
69         gpio_set_value(WHISTLER_WLAN_RST, on);
70         mdelay(200);
71
72         return 0;
73 }
74
75 static int whistler_wifi_reset(int on)
76 {
77         pr_debug("%s: do nothing\n", __func__);
78         return 0;
79 }
80
81
82 static struct wifi_platform_data whistler_wifi_control = {
83         .set_power      = whistler_wifi_power,
84         .set_reset      = whistler_wifi_reset,
85         .set_carddetect = whistler_wifi_set_carddetect,
86 };
87
88 static struct resource wifi_resource[] = {
89         [0] = {
90                 .name   = "bcm4329_wlan_irq",
91                 .start  = TEGRA_GPIO_TO_IRQ(TEGRA_GPIO_PU5),
92                 .end    = TEGRA_GPIO_TO_IRQ(TEGRA_GPIO_PU5),
93                 .flags  = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL | IORESOURCE_IRQ_SHAREABLE,
94         },
95 };
96
97 static struct platform_device whistler_wifi_device = {
98         .name           = "bcm4329_wlan",
99         .id             = 1,
100         .num_resources  = 1,
101         .resource       = wifi_resource,
102         .dev            = {
103                 .platform_data = &whistler_wifi_control,
104         },
105 };
106
107 static struct resource sdhci_resource1[] = {
108         [0] = {
109                 .start  = INT_SDMMC2,
110                 .end    = INT_SDMMC2,
111                 .flags  = IORESOURCE_IRQ,
112         },
113         [1] = {
114                 .start  = TEGRA_SDMMC2_BASE,
115                 .end    = TEGRA_SDMMC2_BASE + TEGRA_SDMMC2_SIZE-1,
116                 .flags  = IORESOURCE_MEM,
117         },
118 };
119
120
121 static struct resource sdhci_resource2[] = {
122         [0] = {
123                 .start  = INT_SDMMC3,
124                 .end    = INT_SDMMC3,
125                 .flags  = IORESOURCE_IRQ,
126         },
127         [1] = {
128                 .start  = TEGRA_SDMMC3_BASE,
129                 .end    = TEGRA_SDMMC3_BASE + TEGRA_SDMMC3_SIZE-1,
130                 .flags  = IORESOURCE_MEM,
131         },
132 };
133
134 static struct resource sdhci_resource3[] = {
135         [0] = {
136                 .start  = INT_SDMMC4,
137                 .end    = INT_SDMMC4,
138                 .flags  = IORESOURCE_IRQ,
139         },
140         [1] = {
141                 .start  = TEGRA_SDMMC4_BASE,
142                 .end    = TEGRA_SDMMC4_BASE + TEGRA_SDMMC4_SIZE-1,
143                 .flags  = IORESOURCE_MEM,
144         },
145 };
146
147 #ifdef CONFIG_MMC_EMBEDDED_SDIO
148 static struct embedded_sdio_data embedded_sdio_data1 = {
149         .cccr   = {
150                 .sdio_vsn       = 2,
151                 .multi_block    = 1,
152                 .low_speed      = 0,
153                 .wide_bus       = 0,
154                 .high_power     = 1,
155                 .high_speed     = 1,
156         },
157         .cis  = {
158                 .vendor         = 0x02d0,
159                 .device         = 0x4329,
160         },
161 };
162 #endif
163
164 static struct tegra_sdhci_platform_data tegra_sdhci_platform_data1 = {
165         .mmc_data = {
166                 .register_status_notify = whistler_wifi_status_register,
167 #ifdef CONFIG_MMC_EMBEDDED_SDIO
168                 .embedded_sdio = &embedded_sdio_data1,
169 #endif
170                 .built_in = 0,
171                 .ocr_mask = MMC_OCR_1V8_MASK,
172         },
173 #ifndef CONFIG_MMC_EMBEDDED_SDIO
174         .pm_flags = MMC_PM_KEEP_POWER,
175 #endif
176         .cd_gpio = -1,
177         .wp_gpio = -1,
178         .power_gpio = -1,
179         .max_clk_limit = 25000000,
180 };
181
182 static struct tegra_sdhci_platform_data tegra_sdhci_platform_data2 = {
183         .cd_gpio = WHISTLER_EXT_SDCARD_DETECT,
184         .wp_gpio = -1,
185         .power_gpio = -1,
186 };
187
188 static struct tegra_sdhci_platform_data tegra_sdhci_platform_data3 = {
189         .cd_gpio = -1,
190         .wp_gpio = -1,
191         .power_gpio = -1,
192         .mmc_data = {
193                 .built_in = 1,
194         }
195 };
196
197 static struct platform_device tegra_sdhci_device1 = {
198         .name           = "sdhci-tegra",
199         .id             = 1,
200         .resource       = sdhci_resource1,
201         .num_resources  = ARRAY_SIZE(sdhci_resource1),
202         .dev = {
203                 .platform_data = &tegra_sdhci_platform_data1,
204         },
205 };
206
207 static struct platform_device tegra_sdhci_device2 = {
208         .name           = "sdhci-tegra",
209         .id             = 2,
210         .resource       = sdhci_resource2,
211         .num_resources  = ARRAY_SIZE(sdhci_resource2),
212         .dev = {
213                 .platform_data = &tegra_sdhci_platform_data2,
214         },
215 };
216
217 static struct platform_device tegra_sdhci_device3 = {
218         .name           = "sdhci-tegra",
219         .id             = 3,
220         .resource       = sdhci_resource3,
221         .num_resources  = ARRAY_SIZE(sdhci_resource3),
222         .dev = {
223                 .platform_data = &tegra_sdhci_platform_data3,
224         },
225 };
226
227 #ifdef CONFIG_TEGRA_PREPOWER_WIFI
228 static int __init whistler_wifi_prepower(void)
229 {
230         if (!machine_is_whistler())
231                 return 0;
232
233         whistler_wifi_power(1);
234
235         return 0;
236 }
237
238 subsys_initcall_sync(whistler_wifi_prepower);
239 #endif
240
241 static int __init whistler_wifi_init(void)
242 {
243         gpio_request(WHISTLER_WLAN_PWR, "wlan_power");
244         gpio_request(WHISTLER_WLAN_RST, "wlan_rst");
245         gpio_request(WHISTLER_WLAN_WOW, "bcmsdh_sdmmc");
246
247         gpio_direction_output(WHISTLER_WLAN_PWR, 0);
248         gpio_direction_output(WHISTLER_WLAN_RST, 0);
249         gpio_direction_input(WHISTLER_WLAN_WOW);
250
251         platform_device_register(&whistler_wifi_device);
252         return 0;
253 }
254 int __init whistler_sdhci_init(void)
255 {
256         platform_device_register(&tegra_sdhci_device3);
257         platform_device_register(&tegra_sdhci_device2);
258         platform_device_register(&tegra_sdhci_device1);
259
260         whistler_wifi_init();
261         return 0;
262 }