video: tegra: nvmap: support for carveout resize
[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 "dvfs.h"
39 #include "iomap.h"
40 #include "tegra-board-id.h"
41
42 #define ARDBEG_WLAN_RST TEGRA_GPIO_PCC5
43 #define ARDBEG_WLAN_PWR TEGRA_GPIO_PX7
44 #define ARDBEG_WLAN_WOW TEGRA_GPIO_PU5
45 #if defined(CONFIG_BCMDHD_EDP_SUPPORT)
46 #define ON 3070 /* 3069mW */
47 #define OFF 0
48 static unsigned int wifi_states[] = {ON, OFF};
49 #endif
50
51 #define ARDBEG_SD_CD    TEGRA_GPIO_PV2
52 #define ARDBEG_SD_WP    TEGRA_GPIO_PQ4
53
54 static void (*wifi_status_cb)(int card_present, void *dev_id);
55 static void *wifi_status_cb_devid;
56 static int ardbeg_wifi_status_register(void (*callback)(int , void *), void *);
57
58 static int ardbeg_wifi_reset(int on);
59 static int ardbeg_wifi_power(int on);
60 static int ardbeg_wifi_set_carddetect(int val);
61
62 static struct wifi_platform_data ardbeg_wifi_control = {
63         .set_power      = ardbeg_wifi_power,
64         .set_reset      = ardbeg_wifi_reset,
65         .set_carddetect = ardbeg_wifi_set_carddetect,
66 #if defined (CONFIG_BCMDHD_EDP_SUPPORT)
67         /* wifi edp client information */
68         .client_info    = {
69                 .name           = "wifi_edp_client",
70                 .states         = wifi_states,
71                 .num_states     = ARRAY_SIZE(wifi_states),
72                 .e0_index       = 0,
73                 .priority       = EDP_MAX_PRIO,
74         },
75 #endif
76 };
77
78 static struct resource wifi_resource[] = {
79         [0] = {
80                 .name   = "bcm4329_wlan_irq",
81                 .flags  = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL
82                                 | IORESOURCE_IRQ_SHAREABLE,
83         },
84 };
85
86 static struct platform_device ardbeg_wifi_device = {
87         .name           = "bcm4329_wlan",
88         .id             = 1,
89         .num_resources  = 1,
90         .resource       = wifi_resource,
91         .dev            = {
92                 .platform_data = &ardbeg_wifi_control,
93         },
94 };
95
96 static struct resource mrvl_wifi_resource[] = {
97         [0] = {
98                 .name   = "mrvl_wlan_irq",
99                 .flags  = IORESOURCE_IRQ | IORESOURCE_IRQ_LOWLEVEL | IORESOURCE_IRQ_SHAREABLE,
100         },
101 };
102
103 static struct platform_device marvell_wifi_device = {
104         .name           = "mrvl_wlan",
105         .id             = 1,
106         .num_resources  = 1,
107         .resource       = mrvl_wifi_resource,
108         .dev            = {
109                 .platform_data = &ardbeg_wifi_control,
110         },
111 };
112
113 static struct resource sdhci_resource0[] = {
114         [0] = {
115                 .start  = INT_SDMMC1,
116                 .end    = INT_SDMMC1,
117                 .flags  = IORESOURCE_IRQ,
118         },
119         [1] = {
120                 .start  = TEGRA_SDMMC1_BASE,
121                 .end    = TEGRA_SDMMC1_BASE + TEGRA_SDMMC1_SIZE-1,
122                 .flags  = IORESOURCE_MEM,
123         },
124 };
125
126 static struct resource sdhci_resource2[] = {
127         [0] = {
128                 .start  = INT_SDMMC3,
129                 .end    = INT_SDMMC3,
130                 .flags  = IORESOURCE_IRQ,
131         },
132         [1] = {
133                 .start  = TEGRA_SDMMC3_BASE,
134                 .end    = TEGRA_SDMMC3_BASE + TEGRA_SDMMC3_SIZE-1,
135                 .flags  = IORESOURCE_MEM,
136         },
137 };
138
139 static struct resource sdhci_resource3[] = {
140         [0] = {
141                 .start  = INT_SDMMC4,
142                 .end    = INT_SDMMC4,
143                 .flags  = IORESOURCE_IRQ,
144         },
145         [1] = {
146                 .start  = TEGRA_SDMMC4_BASE,
147                 .end    = TEGRA_SDMMC4_BASE + TEGRA_SDMMC4_SIZE-1,
148                 .flags  = IORESOURCE_MEM,
149         },
150 };
151
152 #ifdef CONFIG_MMC_EMBEDDED_SDIO
153 static struct embedded_sdio_data embedded_sdio_data0 = {
154         .cccr   = {
155                 .sdio_vsn       = 2,
156                 .multi_block    = 1,
157                 .low_speed      = 0,
158                 .wide_bus       = 0,
159                 .high_power     = 1,
160                 .high_speed     = 1,
161         },
162         .cis  = {
163                 .vendor  = 0x02d0,
164                 .device  = 0x4329,
165         },
166 };
167 #endif
168
169 static struct tegra_sdhci_platform_data tegra_sdhci_platform_data0 = {
170         .mmc_data = {
171                 .register_status_notify = ardbeg_wifi_status_register,
172 #ifdef CONFIG_MMC_EMBEDDED_SDIO
173                 .embedded_sdio = &embedded_sdio_data0,
174 #endif
175                 .built_in = 0,
176                 .ocr_mask = MMC_OCR_1V8_MASK,
177         },
178         .cd_gpio = -1,
179         .wp_gpio = -1,
180         .power_gpio = -1,
181         .tap_delay = 0,
182         .trim_delay = 0x2,
183         .ddr_clk_limit = 41000000,
184         .uhs_mask = MMC_UHS_MASK_DDR50 |
185                 MMC_UHS_MASK_SDR50,
186         .calib_3v3_offsets = 0x7676,
187         .calib_1v8_offsets = 0x7676,
188 };
189
190 static struct tegra_sdhci_platform_data tegra_sdhci_platform_data2 = {
191         .cd_gpio = ARDBEG_SD_CD,
192         .wp_gpio = ARDBEG_SD_WP,
193         .power_gpio = -1,
194         .tap_delay = 0,
195         .trim_delay = 0x3,
196         .uhs_mask = MMC_UHS_MASK_DDR50,
197         .calib_3v3_offsets = 0x7676,
198         .calib_1v8_offsets = 0x7676,
199 };
200
201 static struct tegra_sdhci_platform_data tegra_sdhci_platform_data3 = {
202         .cd_gpio = -1,
203         .wp_gpio = -1,
204         .power_gpio = -1,
205         .is_8bit = 1,
206         .tap_delay = 0x4,
207         .trim_delay = 0x4,
208         .ddr_trim_delay = 0x0,
209         .mmc_data = {
210                 .built_in = 1,
211                 .ocr_mask = MMC_OCR_1V8_MASK,
212         },
213         .ddr_clk_limit = 51000000,
214         .max_clk_limit = 102000000,
215         .calib_3v3_offsets = 0x0202,
216         .calib_1v8_offsets = 0x0202,
217 };
218
219 static struct platform_device tegra_sdhci_device0 = {
220         .name           = "sdhci-tegra",
221         .id             = 0,
222         .resource       = sdhci_resource0,
223         .num_resources  = ARRAY_SIZE(sdhci_resource0),
224         .dev = {
225                 .platform_data = &tegra_sdhci_platform_data0,
226         },
227 };
228
229 static struct platform_device tegra_sdhci_device2 = {
230         .name           = "sdhci-tegra",
231         .id             = 2,
232         .resource       = sdhci_resource2,
233         .num_resources  = ARRAY_SIZE(sdhci_resource2),
234         .dev = {
235                 .platform_data = &tegra_sdhci_platform_data2,
236         },
237 };
238
239 static struct platform_device tegra_sdhci_device3 = {
240         .name           = "sdhci-tegra",
241         .id             = 3,
242         .resource       = sdhci_resource3,
243         .num_resources  = ARRAY_SIZE(sdhci_resource3),
244         .dev = {
245                 .platform_data = &tegra_sdhci_platform_data3,
246         },
247 };
248
249 static int ardbeg_wifi_status_register(
250                 void (*callback)(int card_present, void *dev_id),
251                 void *dev_id)
252 {
253         if (wifi_status_cb)
254                 return -EAGAIN;
255         wifi_status_cb = callback;
256         wifi_status_cb_devid = dev_id;
257         return 0;
258 }
259
260 static int ardbeg_wifi_set_carddetect(int val)
261 {
262         pr_debug("%s: %d\n", __func__, val);
263         if (wifi_status_cb)
264                 wifi_status_cb(val, wifi_status_cb_devid);
265         else
266                 pr_warn("%s: Nobody to notify\n", __func__);
267         return 0;
268 }
269
270 static int ardbeg_wifi_power(int on)
271 {
272         pr_err("%s: %d\n", __func__, on);
273
274         gpio_set_value(ARDBEG_WLAN_PWR, on);
275         gpio_set_value(ARDBEG_WLAN_RST, on);
276         mdelay(100);
277
278         return 0;
279 }
280
281 static int ardbeg_wifi_reset(int on)
282 {
283         pr_debug("%s: do nothing\n", __func__);
284         return 0;
285 }
286
287 static int __init ardbeg_wifi_init(void)
288 {
289         int rc;
290
291         rc = gpio_request(ARDBEG_WLAN_PWR, "wlan_power");
292         if (rc)
293                 pr_err("WLAN_PWR gpio request failed:%d\n", rc);
294         rc = gpio_request(ARDBEG_WLAN_RST, "wlan_rst");
295         if (rc)
296                 pr_err("WLAN_RST gpio request failed:%d\n", rc);
297         rc = gpio_request(ARDBEG_WLAN_WOW, "bcmsdh_sdmmc");
298         if (rc)
299                 pr_err("WLAN_WOW gpio request failed:%d\n", rc);
300
301         rc = gpio_direction_output(ARDBEG_WLAN_PWR, 0);
302         if (rc)
303                 pr_err("WLAN_PWR gpio direction configuration failed:%d\n", rc);
304         rc = gpio_direction_output(ARDBEG_WLAN_RST, 0);
305         if (rc)
306                 pr_err("WLAN_RST gpio direction configuration failed:%d\n", rc);
307
308         rc = gpio_direction_input(ARDBEG_WLAN_WOW);
309         if (rc)
310                 pr_err("WLAN_WOW gpio direction configuration failed:%d\n", rc);
311
312         wifi_resource[0].start = wifi_resource[0].end =
313                 gpio_to_irq(ARDBEG_WLAN_WOW);
314
315         platform_device_register(&ardbeg_wifi_device);
316
317         mrvl_wifi_resource[0].start = mrvl_wifi_resource[0].end =
318                 gpio_to_irq(ARDBEG_WLAN_WOW);
319         platform_device_register(&marvell_wifi_device);
320
321         return 0;
322 }
323
324 #ifdef CONFIG_TEGRA_PREPOWER_WIFI
325 static int __init ardbeg_wifi_prepower(void)
326 {
327         if (!of_machine_is_compatible("nvidia,ardbeg") &&
328                 !of_machine_is_compatible("nvidia,laguna") &&
329                 !of_machine_is_compatible("nvidia,ardbeg_sata") &&
330                 !of_machine_is_compatible("nvidia,tn8"))
331                 return 0;
332         ardbeg_wifi_power(1);
333
334         return 0;
335 }
336
337 subsys_initcall_sync(ardbeg_wifi_prepower);
338 #endif
339
340 int __init ardbeg_sdhci_init(void)
341 {
342         int nominal_core_mv;
343         int min_vcore_override_mv;
344         int boot_vcore_mv;
345         struct board_info board_info;
346
347         nominal_core_mv =
348                 tegra_dvfs_rail_get_nominal_millivolts(tegra_core_rail);
349         if (nominal_core_mv) {
350                 tegra_sdhci_platform_data0.nominal_vcore_mv = nominal_core_mv;
351                 tegra_sdhci_platform_data2.nominal_vcore_mv = nominal_core_mv;
352                 tegra_sdhci_platform_data3.nominal_vcore_mv = nominal_core_mv;
353         }
354         min_vcore_override_mv =
355                 tegra_dvfs_rail_get_override_floor(tegra_core_rail);
356         if (min_vcore_override_mv) {
357                 tegra_sdhci_platform_data0.min_vcore_override_mv =
358                         min_vcore_override_mv;
359                 tegra_sdhci_platform_data2.min_vcore_override_mv =
360                         min_vcore_override_mv;
361                 tegra_sdhci_platform_data3.min_vcore_override_mv =
362                         min_vcore_override_mv;
363         }
364         boot_vcore_mv = tegra_dvfs_rail_get_boot_level(tegra_core_rail);
365         if (boot_vcore_mv) {
366                 tegra_sdhci_platform_data0.boot_vcore_mv = boot_vcore_mv;
367                 tegra_sdhci_platform_data2.boot_vcore_mv = boot_vcore_mv;
368                 tegra_sdhci_platform_data3.boot_vcore_mv = boot_vcore_mv;
369         }
370
371         tegra_get_board_info(&board_info);
372         if (board_info.board_id == BOARD_E1780) {
373                 tegra_sdhci_platform_data3.max_clk_limit = 200000000;
374                 tegra_sdhci_platform_data2.max_clk_limit = 204000000;
375                 tegra_sdhci_platform_data0.max_clk_limit = 204000000;
376         } else {
377                 tegra_sdhci_platform_data3.uhs_mask = MMC_MASK_HS200;
378         }
379
380         platform_device_register(&tegra_sdhci_device3);
381         platform_device_register(&tegra_sdhci_device2);
382         platform_device_register(&tegra_sdhci_device0);
383         ardbeg_wifi_init();
384
385         return 0;
386 }