ARM: tegra: ardbeg: Enable Wifi platform data
[linux-3.10.git] / arch / arm / mach-tegra / board-ardbeg-sdhci.c
1 /*
2  * arch/arm/mach-tegra/board-ardbeg-sdhci.c
3  *
4  * Copyright (c) 2013, NVIDIA CORPORATION.  All rights reserved.
5  *
6  * This program is free software; you can redistribute it and/or modify it
7  * under the terms and conditions of the GNU General Public License,
8  * version 2, as published by the Free Software Foundation.
9  *
10  * This program is distributed in the hope it will be useful, but WITHOUT
11  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
13  * more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
17  */
18
19 #include <linux/resource.h>
20 #include <linux/platform_device.h>
21 #include <linux/wlan_plat.h>
22 #include <linux/delay.h>
23 #include <linux/gpio.h>
24 #include <linux/clk.h>
25 #include <linux/err.h>
26 #include <linux/mmc/host.h>
27 #include <linux/wl12xx.h>
28 #include <linux/platform_data/mmc-sdhci-tegra.h>
29 #include <linux/mfd/max77660/max77660-core.h>
30
31 #include <asm/mach-types.h>
32 #include <mach/irqs.h>
33 #include <mach/gpio-tegra.h>
34
35 #include "gpio-names.h"
36 #include "board.h"
37 #include "board-ardbeg.h"
38 #include "iomap.h"
39
40 #define ARDBEG_WLAN_RST TEGRA_GPIO_PCC5
41 #define ARDBEG_WLAN_PWR TEGRA_GPIO_PX7
42 #define ARDBEG_WLAN_WOW TEGRA_GPIO_PU5
43
44 #define ARDBEG_SD_CD    (MAX77660_GPIO_BASE + MAX77660_GPIO9)
45
46 static void (*wifi_status_cb)(int card_present, void *dev_id);
47 static void *wifi_status_cb_devid;
48 static int ardbeg_wifi_status_register(void (*callback)(int , void *), void *);
49
50 static int ardbeg_wifi_reset(int on);
51 static int ardbeg_wifi_power(int on);
52 static int ardbeg_wifi_set_carddetect(int val);
53
54 static struct wifi_platform_data ardbeg_wifi_control = {
55         .set_power      = ardbeg_wifi_power,
56         .set_reset      = ardbeg_wifi_reset,
57         .set_carddetect = ardbeg_wifi_set_carddetect,
58 };
59
60 static struct resource wifi_resource[] = {
61         [0] = {
62                 .name   = "bcm4329_wlan_irq",
63                 .flags  = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL
64                                 | IORESOURCE_IRQ_SHAREABLE,
65         },
66 };
67
68 static struct platform_device ardbeg_wifi_device = {
69         .name           = "bcm4329_wlan",
70         .id             = 1,
71         .num_resources  = 1,
72         .resource       = wifi_resource,
73         .dev            = {
74                 .platform_data = &ardbeg_wifi_control,
75         },
76 };
77
78 static struct resource sdhci_resource0[] = {
79         [0] = {
80                 .start  = INT_SDMMC1,
81                 .end    = INT_SDMMC1,
82                 .flags  = IORESOURCE_IRQ,
83         },
84         [1] = {
85                 .start  = TEGRA_SDMMC1_BASE,
86                 .end    = TEGRA_SDMMC1_BASE + TEGRA_SDMMC1_SIZE-1,
87                 .flags  = IORESOURCE_MEM,
88         },
89 };
90
91 static struct resource sdhci_resource2[] = {
92         [0] = {
93                 .start  = INT_SDMMC3,
94                 .end    = INT_SDMMC3,
95                 .flags  = IORESOURCE_IRQ,
96         },
97         [1] = {
98                 .start  = TEGRA_SDMMC3_BASE,
99                 .end    = TEGRA_SDMMC3_BASE + TEGRA_SDMMC3_SIZE-1,
100                 .flags  = IORESOURCE_MEM,
101         },
102 };
103
104 static struct resource sdhci_resource3[] = {
105         [0] = {
106                 .start  = INT_SDMMC4,
107                 .end    = INT_SDMMC4,
108                 .flags  = IORESOURCE_IRQ,
109         },
110         [1] = {
111                 .start  = TEGRA_SDMMC4_BASE,
112                 .end    = TEGRA_SDMMC4_BASE + TEGRA_SDMMC4_SIZE-1,
113                 .flags  = IORESOURCE_MEM,
114         },
115 };
116
117 #ifdef CONFIG_MMC_EMBEDDED_SDIO
118 static struct embedded_sdio_data embedded_sdio_data0 = {
119         .cccr   = {
120                 .sdio_vsn       = 2,
121                 .multi_block    = 1,
122                 .low_speed      = 0,
123                 .wide_bus       = 0,
124                 .high_power     = 1,
125                 .high_speed     = 1,
126         },
127         .cis  = {
128                 .vendor  = 0x02d0,
129                 .device  = 0x4329,
130         },
131 };
132 #endif
133
134 static struct tegra_sdhci_platform_data tegra_sdhci_platform_data0 = {
135         .mmc_data = {
136                 .register_status_notify = ardbeg_wifi_status_register,
137 #ifdef CONFIG_MMC_EMBEDDED_SDIO
138                 .embedded_sdio = &embedded_sdio_data0,
139 #endif
140                 .built_in = 0,
141                 .ocr_mask = MMC_OCR_1V8_MASK,
142         },
143 #ifndef CONFIG_MMC_EMBEDDED_SDIO
144         .pm_flags = MMC_PM_KEEP_POWER,
145 #endif
146         .cd_gpio = -1,
147         .wp_gpio = -1,
148         .power_gpio = -1,
149         .tap_delay = 0x3,
150         .trim_delay = 0xA,
151         .ddr_clk_limit = 41000000,
152         /* FIXME remove uhs_mask for T148 silicon */
153         .uhs_mask = MMC_UHS_MASK_SDR104 |
154                 MMC_UHS_MASK_DDR50,
155 };
156
157 static struct tegra_sdhci_platform_data tegra_sdhci_platform_data2 = {
158         .cd_gpio = -1,
159         .wp_gpio = -1,
160         .power_gpio = -1,
161 /*      .max_clk = 12000000, */
162 };
163
164 static struct tegra_sdhci_platform_data tegra_sdhci_platform_data3 = {
165         .cd_gpio = -1,
166         .wp_gpio = -1,
167         .power_gpio = -1,
168         .is_8bit = 1,
169         .mmc_data = {
170                 .built_in = 1,
171                 .ocr_mask = MMC_OCR_1V8_MASK,
172         }
173 /*      .max_clk = 12000000, */
174 };
175
176 static struct platform_device tegra_sdhci_device0 = {
177         .name           = "sdhci-tegra",
178         .id             = 0,
179         .resource       = sdhci_resource0,
180         .num_resources  = ARRAY_SIZE(sdhci_resource0),
181         .dev = {
182                 .platform_data = &tegra_sdhci_platform_data0,
183         },
184 };
185
186 static struct platform_device tegra_sdhci_device2 = {
187         .name           = "sdhci-tegra",
188         .id             = 2,
189         .resource       = sdhci_resource2,
190         .num_resources  = ARRAY_SIZE(sdhci_resource2),
191         .dev = {
192                 .platform_data = &tegra_sdhci_platform_data2,
193         },
194 };
195
196 static struct platform_device tegra_sdhci_device3 = {
197         .name           = "sdhci-tegra",
198         .id             = 3,
199         .resource       = sdhci_resource3,
200         .num_resources  = ARRAY_SIZE(sdhci_resource3),
201         .dev = {
202                 .platform_data = &tegra_sdhci_platform_data3,
203         },
204 };
205
206 static int ardbeg_wifi_status_register(
207                 void (*callback)(int card_present, void *dev_id),
208                 void *dev_id)
209 {
210         if (wifi_status_cb)
211                 return -EAGAIN;
212         wifi_status_cb = callback;
213         wifi_status_cb_devid = dev_id;
214         return 0;
215 }
216
217 static int ardbeg_wifi_set_carddetect(int val)
218 {
219         pr_debug("%s: %d\n", __func__, val);
220         if (wifi_status_cb)
221                 wifi_status_cb(val, wifi_status_cb_devid);
222         else
223                 pr_warn("%s: Nobody to notify\n", __func__);
224         return 0;
225 }
226
227 static int ardbeg_wifi_power(int on)
228 {
229         pr_err("%s: %d\n", __func__, on);
230
231         gpio_set_value(ARDBEG_WLAN_PWR, on);
232         gpio_set_value(ARDBEG_WLAN_RST, on);
233         mdelay(100);
234
235         return 0;
236 }
237
238 static int ardbeg_wifi_reset(int on)
239 {
240         pr_debug("%s: do nothing\n", __func__);
241         return 0;
242 }
243
244 static int __init ardbeg_wifi_init(void)
245 {
246         int rc;
247
248         rc = gpio_request(ARDBEG_WLAN_PWR, "wlan_power");
249         if (rc)
250                 pr_err("WLAN_PWR gpio request failed:%d\n", rc);
251         rc = gpio_request(ARDBEG_WLAN_RST, "wlan_rst");
252         if (rc)
253                 pr_err("WLAN_RST gpio request failed:%d\n", rc);
254         rc = gpio_request(ARDBEG_WLAN_WOW, "bcmsdh_sdmmc");
255         if (rc)
256                 pr_err("WLAN_WOW gpio request failed:%d\n", rc);
257
258         rc = gpio_direction_output(ARDBEG_WLAN_PWR, 0);
259         if (rc)
260                 pr_err("WLAN_PWR gpio direction configuration failed:%d\n", rc);
261         rc = gpio_direction_output(ARDBEG_WLAN_RST, 0);
262         if (rc)
263                 pr_err("WLAN_RST gpio direction configuration failed:%d\n", rc);
264
265         rc = gpio_direction_input(ARDBEG_WLAN_WOW);
266         if (rc)
267                 pr_err("WLAN_WOW gpio direction configuration failed:%d\n", rc);
268
269         wifi_resource[0].start = wifi_resource[0].end =
270                 gpio_to_irq(ARDBEG_WLAN_WOW);
271
272         platform_device_register(&ardbeg_wifi_device);
273         return 0;
274 }
275
276 #ifdef CONFIG_TEGRA_PREPOWER_WIFI
277 static int __init ardbeg_wifi_prepower(void)
278 {
279         if (!of_machine_is_compatible("nvidia,ardbeg"))
280                 return 0;
281         ardbeg_wifi_power(1);
282
283         return 0;
284 }
285
286 subsys_initcall_sync(ardbeg_wifi_prepower);
287 #endif
288
289 int __init ardbeg_sdhci_init(void)
290 {
291         /* FIXME: Disabled SDMMC1 and WiFi */
292 #ifndef CONFIG_USE_OF
293         platform_device_register(&tegra_sdhci_device3);
294         platform_device_register(&tegra_sdhci_device2);
295 #endif
296         platform_device_register(&tegra_sdhci_device0);
297         ardbeg_wifi_init();
298
299         return 0;
300 }