aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-tegra/board-kai-sdhci.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/mach-tegra/board-kai-sdhci.c')
-rw-r--r--arch/arm/mach-tegra/board-kai-sdhci.c267
1 files changed, 267 insertions, 0 deletions
diff --git a/arch/arm/mach-tegra/board-kai-sdhci.c b/arch/arm/mach-tegra/board-kai-sdhci.c
new file mode 100644
index 00000000000..3e489927108
--- /dev/null
+++ b/arch/arm/mach-tegra/board-kai-sdhci.c
@@ -0,0 +1,267 @@
1/*
2 * arch/arm/mach-tegra/board-kai-sdhci.c
3 *
4 * Copyright (C) 2010 Google, Inc.
5 * Copyright (C) 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/delay.h>
21#include <linux/gpio.h>
22#include <linux/clk.h>
23#include <linux/err.h>
24#include <linux/mmc/host.h>
25#include <linux/wl12xx.h>
26
27#include <asm/mach-types.h>
28#include <mach/irqs.h>
29#include <mach/iomap.h>
30#include <mach/sdhci.h>
31
32#include "gpio-names.h"
33#include "board.h"
34#include "board-kai.h"
35
36#define KAI_SD_CD TEGRA_GPIO_PI5
37#define KAI_WLAN_EN TEGRA_GPIO_PD3
38#define KAI_WLAN_IRQ TEGRA_GPIO_PV1
39
40static void (*wifi_status_cb)(int card_present, void *dev_id);
41static void *wifi_status_cb_devid;
42static int kai_wifi_power(int power_on);
43static int kai_wifi_set_carddetect(int val);
44
45static int kai_wifi_status_register(
46 void (*callback)(int card_present, void *dev_id),
47 void *dev_id)
48{
49 if (wifi_status_cb)
50 return -EAGAIN;
51 wifi_status_cb = callback;
52 wifi_status_cb_devid = dev_id;
53 return 0;
54}
55
56
57static struct wl12xx_platform_data kai_wlan_data __initdata = {
58 .irq = TEGRA_GPIO_TO_IRQ(KAI_WLAN_IRQ),
59 .board_ref_clock = WL12XX_REFCLOCK_26,
60 .board_tcxo_clock = 1,
61 .set_power = kai_wifi_power,
62 .set_carddetect = kai_wifi_set_carddetect,
63};
64
65static struct resource sdhci_resource0[] = {
66 [0] = {
67 .start = INT_SDMMC1,
68 .end = INT_SDMMC1,
69 .flags = IORESOURCE_IRQ,
70 },
71 [1] = {
72 .start = TEGRA_SDMMC1_BASE,
73 .end = TEGRA_SDMMC1_BASE + TEGRA_SDMMC1_SIZE-1,
74 .flags = IORESOURCE_MEM,
75 },
76};
77
78static struct resource sdhci_resource2[] = {
79 [0] = {
80 .start = INT_SDMMC3,
81 .end = INT_SDMMC3,
82 .flags = IORESOURCE_IRQ,
83 },
84 [1] = {
85 .start = TEGRA_SDMMC3_BASE,
86 .end = TEGRA_SDMMC3_BASE + TEGRA_SDMMC3_SIZE-1,
87 .flags = IORESOURCE_MEM,
88 },
89};
90
91static struct resource sdhci_resource3[] = {
92 [0] = {
93 .start = INT_SDMMC4,
94 .end = INT_SDMMC4,
95 .flags = IORESOURCE_IRQ,
96 },
97 [1] = {
98 .start = TEGRA_SDMMC4_BASE,
99 .end = TEGRA_SDMMC4_BASE + TEGRA_SDMMC4_SIZE-1,
100 .flags = IORESOURCE_MEM,
101 },
102};
103
104static struct embedded_sdio_data embedded_sdio_data2 = {
105 .cccr = {
106 .sdio_vsn = 2,
107 .multi_block = 1,
108 .low_speed = 0,
109 .wide_bus = 0,
110 .high_power = 1,
111 .high_speed = 1,
112 },
113 .cis = {
114 .vendor = 0x0097,
115 .device = 0x4076,
116 },
117};
118
119static struct tegra_sdhci_platform_data tegra_sdhci_platform_data2 = {
120 .mmc_data = {
121 .register_status_notify = kai_wifi_status_register,
122 /* .embedded_sdio = &embedded_sdio_data2, */
123 .built_in = 1,
124 },
125 .cd_gpio = -1,
126 .wp_gpio = -1,
127 .power_gpio = -1,
128/* .tap_delay = 6,
129 .is_voltage_switch_supported = false,
130 .vdd_rail_name = NULL,
131 .slot_rail_name = NULL,
132 .vdd_max_uv = -1,
133 .vdd_min_uv = -1,
134 .max_clk = 0,
135 .is_8bit_supported = false, */
136 /* .max_clk = 25000000, */
137};
138
139static struct tegra_sdhci_platform_data tegra_sdhci_platform_data0 = {
140 .cd_gpio = KAI_SD_CD,
141 .wp_gpio = -1,
142 .power_gpio = -1,
143/* .tap_delay = 6,
144 .is_voltage_switch_supported = true,
145 .vdd_rail_name = "vddio_sdmmc1",
146 .slot_rail_name = "vddio_sd_slot",
147 .vdd_max_uv = 3320000,
148 .vdd_min_uv = 3280000,
149 .max_clk = 208000000,
150 .is_8bit_supported = false, */
151};
152
153static struct tegra_sdhci_platform_data tegra_sdhci_platform_data3 = {
154 .cd_gpio = -1,
155 .wp_gpio = -1,
156 .power_gpio = -1,
157 .is_8bit = 1,
158 .tap_delay = 0x0F,
159 .mmc_data = {
160 .built_in = 1,
161 }
162/* .tap_delay = 6,
163 .is_voltage_switch_supported = false,
164 .vdd_rail_name = NULL,
165 .slot_rail_name = NULL,
166 .vdd_max_uv = -1,
167 .vdd_min_uv = -1,
168 .max_clk = 48000000,
169 .is_8bit_supported = true, */
170};
171
172static 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
182static 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
192static 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
202static int kai_wifi_set_carddetect(int val)
203{
204 pr_debug("%s: %d\n", __func__, val);
205 if (wifi_status_cb)
206 wifi_status_cb(val, wifi_status_cb_devid);
207 else
208 pr_warning("%s: Nobody to notify\n", __func__);
209 return 0;
210}
211
212static int kai_wifi_power(int power_on)
213{
214 pr_err("Powering %s wifi\n", (power_on ? "on" : "off"));
215
216 if (power_on) {
217 gpio_set_value(KAI_WLAN_EN, 1);
218 mdelay(15);
219 gpio_set_value(KAI_WLAN_EN, 0);
220 mdelay(1);
221 gpio_set_value(KAI_WLAN_EN, 1);
222 mdelay(70);
223 } else {
224 gpio_set_value(KAI_WLAN_EN, 0);
225 }
226
227 return 0;
228}
229
230static int __init kai_wifi_init(void)
231{
232 int rc;
233
234 rc = gpio_request(KAI_WLAN_EN, "wl12xx");
235 if (rc)
236 pr_err("WLAN_EN gpio request failed:%d\n", rc);
237
238 rc = gpio_request(KAI_WLAN_IRQ, "wl12xx");
239 if (rc)
240 pr_err("WLAN_IRQ gpio request failed:%d\n", rc);
241
242 tegra_gpio_enable(KAI_WLAN_EN);
243 tegra_gpio_enable(KAI_WLAN_IRQ);
244
245 rc = gpio_direction_output(KAI_WLAN_EN, 0);
246 if (rc)
247 pr_err("WLAN_EN gpio direction configuration failed:%d\n", rc);
248
249 rc = gpio_direction_input(KAI_WLAN_IRQ);
250 if (rc)
251 pr_err("WLAN_IRQ gpio direction configuration failed:%d\n", rc);
252
253 if (wl12xx_set_platform_data(&kai_wlan_data))
254 pr_err("Error setting wl12xx data\n");
255
256 return 0;
257}
258
259int __init kai_sdhci_init(void)
260{
261 platform_device_register(&tegra_sdhci_device3);
262 platform_device_register(&tegra_sdhci_device2);
263 platform_device_register(&tegra_sdhci_device0);
264
265 kai_wifi_init();
266 return 0;
267}