ARM: tegra12: set CPU rate to 2.2GHz for sku 0x87
[linux-3.10.git] / arch / arm / mach-tegra / board-pluto-sdhci.c
1 /*
2  * arch/arm/mach-tegra/board-pluto-sdhci.c
3  *
4  * Copyright (c) 2012-2013 NVIDIA Corporation. All rights reserved.
5  *
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.
9  *
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.
14  *
15  */
16
17 #include <linux/resource.h>
18 #include <linux/platform_device.h>
19 #include <linux/wlan_plat.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 #include <linux/platform_data/mmc-sdhci-tegra.h>
27
28 #include "tegra-board-id.h"
29 #include <asm/mach-types.h>
30 #include <mach/irqs.h>
31 #include <mach/gpio-tegra.h>
32
33 #include "gpio-names.h"
34 #include "board.h"
35 #include "board-pluto.h"
36 #include "dvfs.h"
37 #include "iomap.h"
38
39 #define PLUTO_WLAN_PWR  TEGRA_GPIO_PCC5
40 #define PLUTO_WLAN_WOW  TEGRA_GPIO_PU5
41 #define PLUTO_SD_CD     TEGRA_GPIO_PV2
42 #define WLAN_PWR_STR    "wlan_power"
43 #define WLAN_WOW_STR    "bcmsdh_sdmmc"
44 #if defined(CONFIG_BCMDHD_EDP_SUPPORT)
45 /* Wifi power levels */
46 #define ON  1080 /* 1080 mW */
47 #define OFF 0
48 static unsigned int wifi_states[] = {ON, OFF};
49 #endif
50
51 static void (*wifi_status_cb)(int card_present, void *dev_id);
52 static void *wifi_status_cb_devid;
53 static int pluto_wifi_status_register(void (*callback)(int , void *), void *);
54
55 static int pluto_wifi_reset(int on);
56 static int pluto_wifi_power(int on);
57 static int pluto_wifi_set_carddetect(int val);
58
59 static struct wifi_platform_data pluto_wifi_control = {
60         .set_power      = pluto_wifi_power,
61         .set_reset      = pluto_wifi_reset,
62         .set_carddetect = pluto_wifi_set_carddetect,
63 };
64
65 static struct resource wifi_resource[] = {
66         [0] = {
67                 .name   = "bcm4329_wlan_irq",
68                 .flags  = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL
69                                 | IORESOURCE_IRQ_SHAREABLE,
70         },
71 };
72
73 static struct platform_device pluto_wifi_device = {
74         .name           = "bcm4329_wlan",
75         .id             = 1,
76         .num_resources  = 1,
77         .resource       = wifi_resource,
78         .dev            = {
79                 .platform_data = &pluto_wifi_control,
80         },
81 };
82
83 #ifdef CONFIG_MMC_EMBEDDED_SDIO
84 static struct embedded_sdio_data embedded_sdio_data0 = {
85         .cccr   = {
86                 .sdio_vsn       = 2,
87                 .multi_block    = 1,
88                 .low_speed      = 0,
89                 .wide_bus       = 0,
90                 .high_power     = 1,
91                 .high_speed     = 1,
92         },
93         .cis  = {
94                 .vendor         = 0x02d0,
95                 .device         = 0x4329,
96         },
97 };
98 #endif
99
100 struct tegra_sdhci_platform_data pluto_tegra_sdhci_platform_data0 = {
101         .mmc_data = {
102                 .register_status_notify = pluto_wifi_status_register,
103 #ifdef CONFIG_MMC_EMBEDDED_SDIO
104                 .embedded_sdio = &embedded_sdio_data0,
105 #endif
106                 .built_in = 0,
107                 .ocr_mask = MMC_OCR_1V8_MASK,
108         },
109 #ifndef CONFIG_MMC_EMBEDDED_SDIO
110         .pm_flags = MMC_PM_KEEP_POWER,
111 #endif
112         .cd_gpio = -1,
113         .wp_gpio = -1,
114         .power_gpio = -1,
115         .tap_delay = 0x2,
116         .trim_delay = 0x2,
117         .ddr_clk_limit = 41000000,
118         .max_clk_limit = 82000000,
119         .uhs_mask = MMC_UHS_MASK_DDR50,
120         .disable_clock_gate = true,
121 };
122
123 static struct resource sdhci_resource0[] = {
124         [0] = {
125                 .start  = INT_SDMMC1,
126                 .end    = INT_SDMMC1,
127                 .flags  = IORESOURCE_IRQ,
128         },
129         [1] = {
130                 .start  = TEGRA_SDMMC1_BASE,
131                 .end    = TEGRA_SDMMC1_BASE + TEGRA_SDMMC1_SIZE-1,
132                 .flags  = IORESOURCE_MEM,
133         },
134 };
135
136 static struct resource sdhci_resource2[] = {
137         [0] = {
138                 .start  = INT_SDMMC3,
139                 .end    = INT_SDMMC3,
140                 .flags  = IORESOURCE_IRQ,
141         },
142         [1] = {
143                 .start  = TEGRA_SDMMC3_BASE,
144                 .end    = TEGRA_SDMMC3_BASE + TEGRA_SDMMC3_SIZE-1,
145                 .flags  = IORESOURCE_MEM,
146         },
147 };
148
149 static struct resource sdhci_resource3[] = {
150         [0] = {
151                 .start  = INT_SDMMC4,
152                 .end    = INT_SDMMC4,
153                 .flags  = IORESOURCE_IRQ,
154         },
155         [1] = {
156                 .start  = TEGRA_SDMMC4_BASE,
157                 .end    = TEGRA_SDMMC4_BASE + TEGRA_SDMMC4_SIZE-1,
158                 .flags  = IORESOURCE_MEM,
159         },
160 };
161
162 static struct tegra_sdhci_platform_data tegra_sdhci_platform_data2 = {
163         .cd_gpio = PLUTO_SD_CD,
164         .wp_gpio = -1,
165         .power_gpio = -1,
166         .tap_delay = 0x3,
167         .trim_delay = 0x3,
168         .ddr_clk_limit = 41000000,
169         .max_clk_limit = 156000000,
170         .uhs_mask = MMC_UHS_MASK_DDR50,
171 };
172
173 static struct tegra_sdhci_platform_data tegra_sdhci_platform_data3 = {
174         .cd_gpio = -1,
175         .wp_gpio = -1,
176         .power_gpio = -1,
177         .is_8bit = 1,
178         .tap_delay = 0x5,
179         .trim_delay = 0xA,
180         .ddr_trim_delay = -1,
181         .ddr_clk_limit = 41000000,
182         .max_clk_limit = 156000000,
183         .mmc_data = {
184                 .built_in = 1,
185                 .ocr_mask = MMC_OCR_1V8_MASK,
186         }
187 };
188
189 static struct platform_device tegra_sdhci_device0 = {
190         .name           = "sdhci-tegra",
191         .id             = 0,
192         .resource       = sdhci_resource0,
193         .num_resources  = ARRAY_SIZE(sdhci_resource0),
194         .dev = {
195                 .platform_data = &pluto_tegra_sdhci_platform_data0,
196         },
197 };
198
199 static struct platform_device tegra_sdhci_device2 = {
200         .name           = "sdhci-tegra",
201         .id             = 2,
202         .resource       = sdhci_resource2,
203         .num_resources  = ARRAY_SIZE(sdhci_resource2),
204         .dev = {
205                 .platform_data = &tegra_sdhci_platform_data2,
206         },
207 };
208
209 static struct platform_device tegra_sdhci_device3 = {
210         .name           = "sdhci-tegra",
211         .id             = 3,
212         .resource       = sdhci_resource3,
213         .num_resources  = ARRAY_SIZE(sdhci_resource3),
214         .dev = {
215                 .platform_data = &tegra_sdhci_platform_data3,
216         },
217 };
218
219 static int pluto_wifi_status_register(
220                 void (*callback)(int card_present, void *dev_id),
221                 void *dev_id)
222 {
223         if (wifi_status_cb)
224                 return -EAGAIN;
225         wifi_status_cb = callback;
226         wifi_status_cb_devid = dev_id;
227         return 0;
228 }
229
230 static int pluto_wifi_set_carddetect(int val)
231 {
232         pr_debug("%s: %d\n", __func__, val);
233         if (wifi_status_cb)
234                 wifi_status_cb(val, wifi_status_cb_devid);
235         else
236                 pr_warning("%s: Nobody to notify\n", __func__);
237         return 0;
238 }
239
240 static int pluto_wifi_power(int on)
241 {
242         pr_debug("%s: %d\n", __func__, on);
243
244         gpio_set_value(PLUTO_WLAN_PWR, on);
245         mdelay(100);
246
247         return 0;
248 }
249
250 static int pluto_wifi_reset(int on)
251 {
252         pr_debug("%s: do nothing\n", __func__);
253         return 0;
254 }
255
256 static int __init pluto_wifi_init(void)
257 {
258         int rc = 0;
259
260         /* init wlan_pwr gpio */
261         rc = gpio_request(PLUTO_WLAN_PWR, WLAN_PWR_STR);
262         /* Due to pre powering, sometimes gpio req returns EBUSY */
263         if ((rc < 0) && (rc != -EBUSY)) {
264                 pr_err("Wifi init: gpio req failed:%d\n", rc);
265                 return rc;
266         }
267
268         /* Due to pre powering, sometimes gpio req returns EBUSY */
269         rc = gpio_direction_output(PLUTO_WLAN_PWR, 0);
270         if ((rc < 0) && (rc != -EBUSY)) {
271                 gpio_free(PLUTO_WLAN_PWR);
272                 return rc;
273         }
274         /* init wlan_wow gpio */
275         rc = gpio_request(PLUTO_WLAN_WOW, WLAN_WOW_STR);
276         if (rc < 0) {
277                 pr_err("wifi init: gpio req failed:%d\n", rc);
278                 gpio_free(PLUTO_WLAN_PWR);
279                 return rc;
280         }
281
282         rc = gpio_direction_input(PLUTO_WLAN_WOW);
283         if (rc < 0) {
284                 gpio_free(PLUTO_WLAN_WOW);
285                 gpio_free(PLUTO_WLAN_PWR);
286                 return rc;
287         }
288
289         wifi_resource[0].start = wifi_resource[0].end =
290                 gpio_to_irq(PLUTO_WLAN_WOW);
291
292         platform_device_register(&pluto_wifi_device);
293         return rc;
294 }
295
296 #ifdef CONFIG_TEGRA_PREPOWER_WIFI
297 static int __init pluto_wifi_prepower(void)
298 {
299         if (!machine_is_tegra_pluto())
300                 return 0;
301
302         pluto_wifi_power(1);
303
304         return 0;
305 }
306
307 subsys_initcall_sync(pluto_wifi_prepower);
308 #endif
309
310 int __init pluto_sdhci_init(void)
311 {
312         int nominal_core_mv;
313         int min_vcore_override_mv;
314         int boot_vcore_mv;
315
316         nominal_core_mv =
317                 tegra_dvfs_rail_get_nominal_millivolts(tegra_core_rail);
318         if (nominal_core_mv > 0) {
319                 pluto_tegra_sdhci_platform_data0.nominal_vcore_mv =
320                         nominal_core_mv;
321                 tegra_sdhci_platform_data2.nominal_vcore_mv = nominal_core_mv;
322                 tegra_sdhci_platform_data3.nominal_vcore_mv = nominal_core_mv;
323         }
324         min_vcore_override_mv =
325                 tegra_dvfs_rail_get_override_floor(tegra_core_rail);
326         if (min_vcore_override_mv) {
327                 pluto_tegra_sdhci_platform_data0.min_vcore_override_mv =
328                         min_vcore_override_mv;
329                 tegra_sdhci_platform_data2.min_vcore_override_mv =
330                         min_vcore_override_mv;
331                 tegra_sdhci_platform_data3.min_vcore_override_mv =
332                         min_vcore_override_mv;
333         }
334         boot_vcore_mv = tegra_dvfs_rail_get_boot_level(tegra_core_rail);
335         if (boot_vcore_mv) {
336                 pluto_tegra_sdhci_platform_data0.boot_vcore_mv = boot_vcore_mv;
337                 tegra_sdhci_platform_data2.boot_vcore_mv = boot_vcore_mv;
338                 tegra_sdhci_platform_data3.boot_vcore_mv = boot_vcore_mv;
339         }
340
341         if ((tegra_sdhci_platform_data3.uhs_mask & MMC_MASK_HS200)
342                 && (!(tegra_sdhci_platform_data3.uhs_mask &
343                 MMC_UHS_MASK_DDR50)))
344                 tegra_sdhci_platform_data3.trim_delay = 0;
345         platform_device_register(&tegra_sdhci_device3);
346         platform_device_register(&tegra_sdhci_device2);
347         platform_device_register(&tegra_sdhci_device0);
348         pluto_wifi_init();
349         return 0;
350 }