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