2 * arch/arm/mach-tegra/board-macallan-sdhci.c
4 * Copyright (c) 2013, NVIDIA CORPORATION. All rights reserved.
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.
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.
17 #include <linux/resource.h>
18 #include <linux/platform_device.h>
19 #include <linux/delay.h>
20 #include <linux/gpio.h>
21 #include <linux/clk.h>
22 #include <linux/err.h>
23 #include <linux/regulator/consumer.h>
24 #include <linux/mmc/host.h>
25 #include <linux/platform_data/mmc-sdhci-tegra.h>
27 #include <asm/mach-types.h>
28 #include <mach/irqs.h>
29 #include <mach/gpio-tegra.h>
30 #include <mach/io_dpd.h>
31 #include <linux/wl12xx.h>
33 #include "gpio-names.h"
35 #include "board-macallan.h"
39 #define MACALLAN_SD_CD TEGRA_GPIO_PV2
40 #define MACALLAN_SD_WP TEGRA_GPIO_PQ4
41 #define MACALLAN_WLAN_PWR TEGRA_GPIO_PCC5
42 #define MACALLAN_WLAN_RST TEGRA_GPIO_PX7
43 #define MACALLAN_WLAN_WOW TEGRA_GPIO_PU5
44 static void (*wifi_status_cb)(int card_present, void *dev_id);
45 static void *wifi_status_cb_devid;
46 static int macallan_wifi_status_register(void (*callback)(int , void *), void *);
48 static int macallan_wifi_power(int on);
49 static int macallan_wifi_set_carddetect(int val);
51 static struct wl12xx_platform_data macallan_wl12xx_wlan_data __initdata = {
52 .board_ref_clock = WL12XX_REFCLOCK_26,
53 .board_tcxo_clock = 1,
54 .set_power = macallan_wifi_power,
55 .set_carddetect = macallan_wifi_set_carddetect,
58 #ifdef CONFIG_MMC_EMBEDDED_SDIO
59 static struct embedded_sdio_data embedded_sdio_data0 = {
75 struct tegra_sdhci_platform_data macallan_tegra_sdhci_platform_data0 = {
77 .register_status_notify = macallan_wifi_status_register,
78 #ifdef CONFIG_MMC_EMBEDDED_SDIO
79 .embedded_sdio = &embedded_sdio_data0,
82 .ocr_mask = MMC_OCR_1V8_MASK,
84 #ifndef CONFIG_MMC_EMBEDDED_SDIO
85 .pm_flags = MMC_PM_KEEP_POWER,
92 .ddr_clk_limit = 41000000,
93 .uhs_mask = MMC_UHS_MASK_DDR50,
94 .disable_clock_gate = true,
98 static struct resource sdhci_resource0[] = {
102 .flags = IORESOURCE_IRQ,
105 .start = TEGRA_SDMMC1_BASE,
106 .end = TEGRA_SDMMC1_BASE + TEGRA_SDMMC1_SIZE-1,
107 .flags = IORESOURCE_MEM,
111 static struct resource sdhci_resource2[] = {
115 .flags = IORESOURCE_IRQ,
118 .start = TEGRA_SDMMC3_BASE,
119 .end = TEGRA_SDMMC3_BASE + TEGRA_SDMMC3_SIZE-1,
120 .flags = IORESOURCE_MEM,
124 static struct resource sdhci_resource3[] = {
128 .flags = IORESOURCE_IRQ,
131 .start = TEGRA_SDMMC4_BASE,
132 .end = TEGRA_SDMMC4_BASE + TEGRA_SDMMC4_SIZE-1,
133 .flags = IORESOURCE_MEM,
138 static struct tegra_sdhci_platform_data tegra_sdhci_platform_data2 = {
139 .cd_gpio = MACALLAN_SD_CD,
140 .wp_gpio = MACALLAN_SD_WP,
144 .ddr_clk_limit = 41000000,
145 .uhs_mask = MMC_UHS_MASK_DDR50,
148 static struct tegra_sdhci_platform_data tegra_sdhci_platform_data3 = {
155 .ddr_trim_delay = -1,
156 .ddr_clk_limit = 41000000,
157 .max_clk_limit = 156000000,
160 .ocr_mask = MMC_OCR_1V8_MASK,
164 static struct platform_device tegra_sdhci_device0 = {
165 .name = "sdhci-tegra",
167 .resource = sdhci_resource0,
168 .num_resources = ARRAY_SIZE(sdhci_resource0),
170 .platform_data = &macallan_tegra_sdhci_platform_data0,
174 static struct platform_device tegra_sdhci_device2 = {
175 .name = "sdhci-tegra",
177 .resource = sdhci_resource2,
178 .num_resources = ARRAY_SIZE(sdhci_resource2),
180 .platform_data = &tegra_sdhci_platform_data2,
184 static struct platform_device tegra_sdhci_device3 = {
185 .name = "sdhci-tegra",
187 .resource = sdhci_resource3,
188 .num_resources = ARRAY_SIZE(sdhci_resource3),
190 .platform_data = &tegra_sdhci_platform_data3,
195 static int macallan_wifi_status_register(
196 void (*callback)(int card_present, void *dev_id),
201 wifi_status_cb = callback;
202 wifi_status_cb_devid = dev_id;
206 static int macallan_wifi_set_carddetect(int val)
208 pr_debug("%s: %d\n", __func__, val);
210 wifi_status_cb(val, wifi_status_cb_devid);
212 pr_warning("%s: Nobody to notify\n", __func__);
216 static int macallan_wifi_power(int on)
218 pr_debug("%s: %d\n", __func__, on);
221 gpio_set_value(MACALLAN_WLAN_RST, 1);
223 gpio_set_value(MACALLAN_WLAN_RST, 0);
225 gpio_set_value(MACALLAN_WLAN_RST, 1);
227 gpio_set_value(MACALLAN_WLAN_PWR, 1);
230 gpio_set_value(MACALLAN_WLAN_RST, 0);
232 gpio_set_value(MACALLAN_WLAN_PWR, 0);
238 static int __init macallan_wifi_init(void)
242 rc = gpio_request(MACALLAN_WLAN_PWR, "wlan_power");
244 pr_err("WLAN_PWR gpio request failed:%d\n", rc);
245 rc = gpio_request(MACALLAN_WLAN_RST, "wlan_rst");
247 pr_err("WLAN_RST gpio request failed:%d\n", rc);
248 rc = gpio_request(MACALLAN_WLAN_WOW, "bcmsdh_sdmmc");
250 pr_err("WLAN_WOW gpio request failed:%d\n", rc);
252 rc = gpio_direction_output(MACALLAN_WLAN_PWR, 0);
254 pr_err("WLAN_PWR gpio direction configuration failed:%d\n", rc);
255 rc = gpio_direction_output(MACALLAN_WLAN_RST, 0);
257 pr_err("WLAN_RST gpio direction configuration failed:%d\n", rc);
258 rc = gpio_direction_input(MACALLAN_WLAN_WOW);
260 pr_err("WLAN_WOW gpio direction configuration failed:%d\n", rc);
261 macallan_wl12xx_wlan_data.irq = gpio_to_irq(MACALLAN_WLAN_WOW);
262 wl12xx_set_platform_data(&macallan_wl12xx_wlan_data);
266 #ifdef CONFIG_TEGRA_PREPOWER_WIFI
267 static int __init macallan_wifi_prepower(void)
269 if (!machine_is_macallan())
272 macallan_wifi_power(1);
277 subsys_initcall_sync(macallan_wifi_prepower);
280 int __init macallan_sdhci_init(void)
282 #ifndef CONFIG_USE_OF
283 if ((tegra_sdhci_platform_data3.uhs_mask & MMC_MASK_HS200)
284 && (!(tegra_sdhci_platform_data3.uhs_mask &
285 MMC_UHS_MASK_DDR50)))
286 tegra_sdhci_platform_data3.trim_delay = 0;
289 int min_vcore_override_mv;
293 tegra_dvfs_rail_get_nominal_millivolts(tegra_core_rail);
294 if (nominal_core_mv > 0) {
295 macallan_tegra_sdhci_platform_data0.nominal_vcore_mv =
297 tegra_sdhci_platform_data2.nominal_vcore_mv = nominal_core_mv;
298 tegra_sdhci_platform_data3.nominal_vcore_mv = nominal_core_mv;
300 min_vcore_override_mv =
301 tegra_dvfs_rail_get_override_floor(tegra_core_rail);
302 if (min_vcore_override_mv) {
303 macallan_tegra_sdhci_platform_data0.min_vcore_override_mv =
304 min_vcore_override_mv;
305 tegra_sdhci_platform_data2.min_vcore_override_mv =
306 min_vcore_override_mv;
307 tegra_sdhci_platform_data3.min_vcore_override_mv =
308 min_vcore_override_mv;
310 boot_vcore_mv = tegra_dvfs_rail_get_boot_level(tegra_core_rail);
312 macallan_tegra_sdhci_platform_data0.boot_vcore_mv =
314 tegra_sdhci_platform_data2.boot_vcore_mv = boot_vcore_mv;
315 tegra_sdhci_platform_data3.boot_vcore_mv = boot_vcore_mv;
318 if ((tegra_sdhci_platform_data3.uhs_mask & MMC_MASK_HS200)
319 && (!(tegra_sdhci_platform_data3.uhs_mask &
320 MMC_UHS_MASK_DDR50)))
321 tegra_sdhci_platform_data3.trim_delay = 0;
323 platform_device_register(&tegra_sdhci_device3);
324 platform_device_register(&tegra_sdhci_device2);
325 platform_device_register(&tegra_sdhci_device0);
327 macallan_wifi_init();