rtc: tps80031: register as mfd sub device
[linux-2.6.git] / arch / arm / mach-tegra / board-cardhu-sdhci.c
1 /*
2  * arch/arm/mach-tegra/board-harmony-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 #include <mach/io_dpd.h>
32
33 #include "gpio-names.h"
34 #include "board.h"
35 #include "board-cardhu.h"
36
37 #define CARDHU_WLAN_PWR TEGRA_GPIO_PD4
38 #define CARDHU_WLAN_RST TEGRA_GPIO_PD3
39 #define CARDHU_WLAN_WOW TEGRA_GPIO_PO4
40 #define CARDHU_SD_CD TEGRA_GPIO_PI5
41 #define CARDHU_SD_WP TEGRA_GPIO_PT3
42 #define PM269_SD_WP -1
43
44 static void (*wifi_status_cb)(int card_present, void *dev_id);
45 static void *wifi_status_cb_devid;
46 static int cardhu_wifi_status_register(void (*callback)(int , void *), void *);
47
48 static int cardhu_wifi_reset(int on);
49 static int cardhu_wifi_power(int on);
50 static int cardhu_wifi_set_carddetect(int val);
51
52 static struct wifi_platform_data cardhu_wifi_control = {
53         .set_power      = cardhu_wifi_power,
54         .set_reset      = cardhu_wifi_reset,
55         .set_carddetect = cardhu_wifi_set_carddetect,
56 };
57
58 static struct resource wifi_resource[] = {
59         [0] = {
60                 .name   = "bcm4329_wlan_irq",
61                 .start  = TEGRA_GPIO_TO_IRQ(TEGRA_GPIO_PO4),
62                 .end    = TEGRA_GPIO_TO_IRQ(TEGRA_GPIO_PO4),
63                 .flags  = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL | IORESOURCE_IRQ_SHAREABLE,
64         },
65 };
66
67 static struct platform_device broadcom_wifi_device = {
68         .name           = "bcm4329_wlan",
69         .id             = 1,
70         .num_resources  = 1,
71         .resource       = wifi_resource,
72         .dev            = {
73                 .platform_data = &cardhu_wifi_control,
74         },
75 };
76
77 static struct platform_device marvell_wifi_device = {
78         .name           = "mrvl8797_wlan",
79         .id             = 1,
80         .num_resources  = 0,
81         .dev            = {
82                 .platform_data = &cardhu_wifi_control,
83         },
84 };
85
86 static struct resource sdhci_resource0[] = {
87         [0] = {
88                 .start  = INT_SDMMC1,
89                 .end    = INT_SDMMC1,
90                 .flags  = IORESOURCE_IRQ,
91         },
92         [1] = {
93                 .start  = TEGRA_SDMMC1_BASE,
94                 .end    = TEGRA_SDMMC1_BASE + TEGRA_SDMMC1_SIZE-1,
95                 .flags  = IORESOURCE_MEM,
96         },
97 };
98
99 static struct resource sdhci_resource2[] = {
100         [0] = {
101                 .start  = INT_SDMMC3,
102                 .end    = INT_SDMMC3,
103                 .flags  = IORESOURCE_IRQ,
104         },
105         [1] = {
106                 .start  = TEGRA_SDMMC3_BASE,
107                 .end    = TEGRA_SDMMC3_BASE + TEGRA_SDMMC3_SIZE-1,
108                 .flags  = IORESOURCE_MEM,
109         },
110 };
111
112 static struct resource sdhci_resource3[] = {
113         [0] = {
114                 .start  = INT_SDMMC4,
115                 .end    = INT_SDMMC4,
116                 .flags  = IORESOURCE_IRQ,
117         },
118         [1] = {
119                 .start  = TEGRA_SDMMC4_BASE,
120                 .end    = TEGRA_SDMMC4_BASE + TEGRA_SDMMC4_SIZE-1,
121                 .flags  = IORESOURCE_MEM,
122         },
123 };
124
125 #ifdef CONFIG_MMC_EMBEDDED_SDIO
126 static struct embedded_sdio_data embedded_sdio_data2 = {
127         .cccr   = {
128                 .sdio_vsn       = 2,
129                 .multi_block    = 1,
130                 .low_speed      = 0,
131                 .wide_bus       = 0,
132                 .high_power     = 1,
133                 .high_speed     = 1,
134         },
135         .cis  = {
136                 .vendor         = 0x02d0,
137                 .device         = 0x4329,
138         },
139 };
140 #endif
141
142 static struct tegra_sdhci_platform_data tegra_sdhci_platform_data2 = {
143         .mmc_data = {
144                 .register_status_notify = cardhu_wifi_status_register,
145 #ifdef CONFIG_MMC_EMBEDDED_SDIO
146                 .embedded_sdio = &embedded_sdio_data2,
147 #endif
148                 .built_in = 0,
149                 .ocr_mask = MMC_OCR_1V8_MASK,
150         },
151 #ifndef CONFIG_MMC_EMBEDDED_SDIO
152         .pm_flags = MMC_PM_KEEP_POWER,
153 #endif
154         .cd_gpio = -1,
155         .wp_gpio = -1,
156         .power_gpio = -1,
157         .tap_delay = 0x0F,
158         .ddr_clk_limit = 41000000,
159 /*      .is_voltage_switch_supported = false,
160         .vdd_rail_name = NULL,
161         .slot_rail_name = NULL,
162         .vdd_max_uv = -1,
163         .vdd_min_uv = -1,
164         .max_clk = 0,
165         .is_8bit_supported = false, */
166 };
167
168 static struct tegra_sdhci_platform_data tegra_sdhci_platform_data0 = {
169         .cd_gpio = CARDHU_SD_CD,
170         .wp_gpio = CARDHU_SD_WP,
171         .power_gpio = -1,
172         .tap_delay = 0x0F,
173         .ddr_clk_limit = 41000000,
174 /*      .is_voltage_switch_supported = true,
175         .vdd_rail_name = "vddio_sdmmc1",
176         .slot_rail_name = "vddio_sd_slot",
177         .vdd_max_uv = 3320000,
178         .vdd_min_uv = 3280000,
179         .max_clk = 208000000,
180         .is_8bit_supported = false, */
181 };
182
183 static struct tegra_sdhci_platform_data tegra_sdhci_platform_data3 = {
184         .cd_gpio = -1,
185         .wp_gpio = -1,
186         .power_gpio = -1,
187         .is_8bit = 1,
188         .tap_delay = 0x0F,
189         .ddr_clk_limit = 41000000,
190         .mmc_data = {
191                 .built_in = 1,
192         }
193 /*      .is_voltage_switch_supported = false,
194         .vdd_rail_name = NULL,
195         .slot_rail_name = NULL,
196         .vdd_max_uv = -1,
197         .vdd_min_uv = -1,
198         .max_clk = 48000000,
199         .is_8bit_supported = true, */
200 };
201
202 static struct platform_device tegra_sdhci_device0 = {
203         .name           = "sdhci-tegra",
204         .id             = 0,
205         .resource       = sdhci_resource0,
206         .num_resources  = ARRAY_SIZE(sdhci_resource0),
207         .dev = {
208                 .platform_data = &tegra_sdhci_platform_data0,
209         },
210 };
211
212 static struct platform_device tegra_sdhci_device2 = {
213         .name           = "sdhci-tegra",
214         .id             = 2,
215         .resource       = sdhci_resource2,
216         .num_resources  = ARRAY_SIZE(sdhci_resource2),
217         .dev = {
218                 .platform_data = &tegra_sdhci_platform_data2,
219         },
220 };
221
222 static struct platform_device tegra_sdhci_device3 = {
223         .name           = "sdhci-tegra",
224         .id             = 3,
225         .resource       = sdhci_resource3,
226         .num_resources  = ARRAY_SIZE(sdhci_resource3),
227         .dev = {
228                 .platform_data = &tegra_sdhci_platform_data3,
229         },
230 };
231
232 static int cardhu_wifi_status_register(
233                 void (*callback)(int card_present, void *dev_id),
234                 void *dev_id)
235 {
236         if (wifi_status_cb)
237                 return -EAGAIN;
238         wifi_status_cb = callback;
239         wifi_status_cb_devid = dev_id;
240         return 0;
241 }
242
243 static int cardhu_wifi_set_carddetect(int val)
244 {
245         pr_debug("%s: %d\n", __func__, val);
246         if (wifi_status_cb)
247                 wifi_status_cb(val, wifi_status_cb_devid);
248         else
249                 pr_warning("%s: Nobody to notify\n", __func__);
250         return 0;
251 }
252
253 static int cardhu_wifi_power(int on)
254 {
255         struct tegra_io_dpd *sd_dpd;
256
257         pr_debug("%s: %d\n", __func__, on);
258
259         /*
260          * FIXME : we need to revisit IO DPD code
261          * on how should multiple pins under DPD get controlled
262          *
263          * cardhu GPIO WLAN enable is part of SDMMC3 pin group
264          */
265         sd_dpd = tegra_io_dpd_get(&tegra_sdhci_device2.dev);
266         if (sd_dpd) {
267                 mutex_lock(&sd_dpd->delay_lock);
268                 tegra_io_dpd_disable(sd_dpd);
269                 mutex_unlock(&sd_dpd->delay_lock);
270         }
271         gpio_set_value(CARDHU_WLAN_PWR, on);
272         mdelay(100);
273         gpio_set_value(CARDHU_WLAN_RST, on);
274         mdelay(200);
275         if (sd_dpd) {
276                 mutex_lock(&sd_dpd->delay_lock);
277                 tegra_io_dpd_enable(sd_dpd);
278                 mutex_unlock(&sd_dpd->delay_lock);
279         }
280
281         return 0;
282 }
283
284 static int cardhu_wifi_reset(int on)
285 {
286         pr_debug("%s: do nothing\n", __func__);
287         return 0;
288 }
289
290 static int __init cardhu_wifi_init(void)
291 {
292         int rc;
293         int commchip_id = tegra_get_commchip_id();
294
295         rc = gpio_request(CARDHU_WLAN_PWR, "wlan_power");
296         if (rc)
297                 pr_err("WLAN_PWR gpio request failed:%d\n", rc);
298         rc = gpio_request(CARDHU_WLAN_RST, "wlan_rst");
299         if (rc)
300                 pr_err("WLAN_RST gpio request failed:%d\n", rc);
301         rc = gpio_request(CARDHU_WLAN_WOW, "bcmsdh_sdmmc");
302         if (rc)
303                 pr_err("WLAN_WOW gpio request failed:%d\n", rc);
304
305         rc = gpio_direction_output(CARDHU_WLAN_PWR, 0);
306         if (rc)
307                 pr_err("WLAN_PWR gpio direction configuration failed:%d\n", rc);
308         gpio_direction_output(CARDHU_WLAN_RST, 0);
309         if (rc)
310                 pr_err("WLAN_RST gpio direction configuration failed:%d\n", rc);
311         rc = gpio_direction_input(CARDHU_WLAN_WOW);
312         if (rc)
313                 pr_err("WLAN_WOW gpio direction configuration failed:%d\n", rc);
314
315         if (commchip_id == COMMCHIP_MARVELL_SD8797)
316                 platform_device_register(&marvell_wifi_device);
317         else
318                 platform_device_register(&broadcom_wifi_device);
319
320         return 0;
321 }
322
323 #ifdef CONFIG_TEGRA_PREPOWER_WIFI
324 static int __init cardhu_wifi_prepower(void)
325 {
326         if (!machine_is_cardhu())
327                 return 0;
328
329         cardhu_wifi_power(1);
330
331         return 0;
332 }
333
334 subsys_initcall_sync(cardhu_wifi_prepower);
335 #endif
336
337 int __init cardhu_sdhci_init(void)
338 {
339         struct board_info board_info;
340         tegra_get_board_info(&board_info);
341         if ((board_info.board_id == BOARD_PM269) ||
342                 (board_info.board_id == BOARD_E1257) ||
343                 (board_info.board_id == BOARD_PM305) ||
344                 (board_info.board_id == BOARD_PM311)) {
345                         tegra_sdhci_platform_data0.wp_gpio = PM269_SD_WP;
346                         tegra_sdhci_platform_data2.max_clk_limit = 12000000;
347         }
348
349         platform_device_register(&tegra_sdhci_device3);
350         platform_device_register(&tegra_sdhci_device2);
351         platform_device_register(&tegra_sdhci_device0);
352
353         cardhu_wifi_init();
354         return 0;
355 }