rtc: tps80031: register as mfd sub device
[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 #include <mach/io_dpd.h>
31
32 #include "gpio-names.h"
33 #include "board.h"
34
35
36 #define ENTERPRISE_WLAN_PWR     TEGRA_GPIO_PV2
37 #define ENTERPRISE_WLAN_RST     TEGRA_GPIO_PV3
38 #define ENTERPRISE_WLAN_WOW     TEGRA_GPIO_PU6
39 #define ENTERPRISE_SD_CD TEGRA_GPIO_PI5
40
41 static void (*wifi_status_cb)(int card_present, void *dev_id);
42 static void *wifi_status_cb_devid;
43 static int enterprise_wifi_status_register(void (*callback)(int , void *), void *);
44
45 static int enterprise_wifi_reset(int on);
46 static int enterprise_wifi_power(int on);
47 static int enterprise_wifi_set_carddetect(int val);
48
49 static struct wifi_platform_data enterprise_wifi_control = {
50         .set_power      = enterprise_wifi_power,
51         .set_reset      = enterprise_wifi_reset,
52         .set_carddetect = enterprise_wifi_set_carddetect,
53 };
54
55 static struct resource wifi_resource[] = {
56         [0] = {
57                 .name   = "bcm4329_wlan_irq",
58                 .start  = TEGRA_GPIO_TO_IRQ(TEGRA_GPIO_PU6),
59                 .end    = TEGRA_GPIO_TO_IRQ(TEGRA_GPIO_PU6),
60                 .flags  = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL | IORESOURCE_IRQ_SHAREABLE,
61         },
62 };
63
64 static struct platform_device enterprise_wifi_device = {
65         .name           = "bcm4329_wlan",
66         .id             = 1,
67         .num_resources  = 1,
68         .resource       = wifi_resource,
69         .dev            = {
70                 .platform_data = &enterprise_wifi_control,
71         },
72 };
73
74 static struct resource sdhci_resource0[] = {
75         [0] = {
76                 .start  = INT_SDMMC1,
77                 .end    = INT_SDMMC1,
78                 .flags  = IORESOURCE_IRQ,
79         },
80         [1] = {
81                 .start  = TEGRA_SDMMC1_BASE,
82                 .end    = TEGRA_SDMMC1_BASE + TEGRA_SDMMC1_SIZE-1,
83                 .flags  = IORESOURCE_MEM,
84         },
85 };
86
87 static struct resource sdhci_resource2[] = {
88         [0] = {
89                 .start  = INT_SDMMC3,
90                 .end    = INT_SDMMC3,
91                 .flags  = IORESOURCE_IRQ,
92         },
93         [1] = {
94                 .start  = TEGRA_SDMMC3_BASE,
95                 .end    = TEGRA_SDMMC3_BASE + TEGRA_SDMMC3_SIZE-1,
96                 .flags  = IORESOURCE_MEM,
97         },
98 };
99
100 static struct resource sdhci_resource3[] = {
101         [0] = {
102                 .start  = INT_SDMMC4,
103                 .end    = INT_SDMMC4,
104                 .flags  = IORESOURCE_IRQ,
105         },
106         [1] = {
107                 .start  = TEGRA_SDMMC4_BASE,
108                 .end    = TEGRA_SDMMC4_BASE + TEGRA_SDMMC4_SIZE-1,
109                 .flags  = IORESOURCE_MEM,
110         },
111 };
112
113 #ifdef CONFIG_MMC_EMBEDDED_SDIO
114 static struct embedded_sdio_data embedded_sdio_data0 = {
115         .cccr   = {
116                 .sdio_vsn       = 2,
117                 .multi_block    = 1,
118                 .low_speed      = 0,
119                 .wide_bus       = 0,
120                 .high_power     = 1,
121                 .high_speed     = 1,
122         },
123         .cis  = {
124                 .vendor         = 0x02d0,
125                 .device         = 0x4329,
126         },
127 };
128 #endif
129
130 static struct tegra_sdhci_platform_data tegra_sdhci_platform_data0 = {
131         .mmc_data = {
132                 .register_status_notify = enterprise_wifi_status_register,
133 #ifdef CONFIG_MMC_EMBEDDED_SDIO
134                 .embedded_sdio = &embedded_sdio_data0,
135 #endif
136                 /* FIXME need to revert the built_in change
137                 once we use get the signal strength fix of
138                 bcmdhd driver from broadcom for bcm4329 chipset*/
139                 .built_in = 0,
140         },
141 #ifndef CONFIG_MMC_EMBEDDED_SDIO
142         .pm_flags = MMC_PM_KEEP_POWER,
143 #endif
144         .cd_gpio = -1,
145         .wp_gpio = -1,
146         .power_gpio = -1,
147         .tap_delay = 0x0F,
148         .max_clk_limit = 45000000,
149         .ddr_clk_limit = 41000000,
150 };
151
152 static struct tegra_sdhci_platform_data tegra_sdhci_platform_data2 = {
153         .cd_gpio = -1,
154         .wp_gpio = -1,
155         .power_gpio = -1,
156         .tap_delay = 0x0F,
157         .ddr_clk_limit = 41000000,
158 };
159
160 static struct tegra_sdhci_platform_data tegra_sdhci_platform_data3 = {
161         .cd_gpio = -1,
162         .wp_gpio = -1,
163         .power_gpio = -1,
164         .is_8bit = 1,
165         .tap_delay = 0x0F,
166         .ddr_clk_limit = 41000000,
167         .mmc_data = {
168                 .built_in = 1,
169         }
170 };
171
172 static struct platform_device tegra_sdhci_device0 = {
173         .name           = "sdhci-tegra",
174         .id             = 0,
175         .resource       = sdhci_resource0,
176         .num_resources  = ARRAY_SIZE(sdhci_resource0),
177         .dev = {
178                 .platform_data = &tegra_sdhci_platform_data0,
179         },
180 };
181
182 static struct platform_device tegra_sdhci_device2 = {
183         .name           = "sdhci-tegra",
184         .id             = 2,
185         .resource       = sdhci_resource2,
186         .num_resources  = ARRAY_SIZE(sdhci_resource2),
187         .dev = {
188                 .platform_data = &tegra_sdhci_platform_data2,
189         },
190 };
191
192 static struct platform_device tegra_sdhci_device3 = {
193         .name           = "sdhci-tegra",
194         .id             = 3,
195         .resource       = sdhci_resource3,
196         .num_resources  = ARRAY_SIZE(sdhci_resource3),
197         .dev = {
198                 .platform_data = &tegra_sdhci_platform_data3,
199         },
200 };
201
202 static int enterprise_wifi_status_register(
203                 void (*callback)(int card_present, void *dev_id),
204                 void *dev_id)
205 {
206         if (wifi_status_cb)
207                 return -EAGAIN;
208         wifi_status_cb = callback;
209         wifi_status_cb_devid = dev_id;
210         return 0;
211 }
212
213 static int enterprise_wifi_set_carddetect(int val)
214 {
215         pr_debug("%s: %d\n", __func__, val);
216         if (wifi_status_cb)
217                 wifi_status_cb(val, wifi_status_cb_devid);
218         else
219                 pr_warning("%s: Nobody to notify\n", __func__);
220         return 0;
221 }
222
223 static int enterprise_wifi_power(int on)
224 {
225         struct tegra_io_dpd *sd_dpd;
226
227         pr_debug("%s: %d\n", __func__, on);
228
229         /*
230          * FIXME : we need to revisit IO DPD code
231          * on how should multiple pins under DPD get controlled
232          *
233          * enterprise GPIO WLAN enable is part of SDMMC1 pin group
234          */
235         sd_dpd = tegra_io_dpd_get(&tegra_sdhci_device0.dev);
236         if (sd_dpd) {
237                 mutex_lock(&sd_dpd->delay_lock);
238                 tegra_io_dpd_disable(sd_dpd);
239                 mutex_unlock(&sd_dpd->delay_lock);
240         }
241         gpio_set_value(ENTERPRISE_WLAN_PWR, on);
242         mdelay(100);
243         gpio_set_value(ENTERPRISE_WLAN_RST, on);
244         mdelay(200);
245         if (sd_dpd) {
246                 mutex_lock(&sd_dpd->delay_lock);
247                 tegra_io_dpd_enable(sd_dpd);
248                 mutex_unlock(&sd_dpd->delay_lock);
249         }
250
251         return 0;
252 }
253
254 static int enterprise_wifi_reset(int on)
255 {
256         pr_debug("%s: do nothing\n", __func__);
257         return 0;
258 }
259
260 #ifdef CONFIG_TEGRA_PREPOWER_WIFI
261 static int __init enterprise_wifi_prepower(void)
262 {
263         if (!machine_is_tegra_enterprise())
264                 return 0;
265
266         enterprise_wifi_power(1);
267
268         return 0;
269 }
270
271 subsys_initcall_sync(enterprise_wifi_prepower);
272 #endif
273
274 static int __init enterprise_wifi_init(void)
275 {
276         int rc;
277
278         rc = gpio_request(ENTERPRISE_WLAN_PWR, "wlan_power");
279         if (rc)
280                 pr_err("WLAN_PWR gpio request failed:%d\n", rc);
281         rc = gpio_request(ENTERPRISE_WLAN_RST, "wlan_rst");
282         if (rc)
283                 pr_err("WLAN_RST gpio request failed:%d\n", rc);
284         rc = gpio_request(ENTERPRISE_WLAN_WOW, "bcmsdh_sdmmc");
285         if (rc)
286                 pr_err("WLAN_WOW gpio request failed:%d\n", rc);
287
288         rc = gpio_direction_output(ENTERPRISE_WLAN_PWR, 0);
289         if (rc)
290                 pr_err("WLAN_PWR gpio direction configuration failed:%d\n", rc);
291         gpio_direction_output(ENTERPRISE_WLAN_RST, 0);
292         if (rc)
293                 pr_err("WLAN_RST gpio direction configuration failed:%d\n", rc);
294         rc = gpio_direction_input(ENTERPRISE_WLAN_WOW);
295         if (rc)
296                 pr_err("WLAN_WOW gpio direction configuration failed:%d\n", rc);
297
298         platform_device_register(&enterprise_wifi_device);
299         return 0;
300 }
301
302 int __init enterprise_sdhci_init(void)
303 {
304         platform_device_register(&tegra_sdhci_device3);
305
306         tegra_sdhci_platform_data2.cd_gpio = ENTERPRISE_SD_CD;
307         platform_device_register(&tegra_sdhci_device2);
308
309         platform_device_register(&tegra_sdhci_device0);
310         enterprise_wifi_init();
311         return 0;
312 }