ARM: tegra12: set CPU rate to 2.2GHz for sku 0x87
[linux-3.10.git] / arch / arm / mach-tegra / board-macallan-sdhci.c
1 /*
2  * arch/arm/mach-tegra/board-macallan-sdhci.c
3  *
4  * Copyright (c) 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/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>
26
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>
32
33 #include "gpio-names.h"
34 #include "board.h"
35 #include "board-macallan.h"
36 #include "dvfs.h"
37 #include "iomap.h"
38
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 *);
47
48 static int macallan_wifi_power(int on);
49 static int macallan_wifi_set_carddetect(int val);
50
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,
56 };
57
58 #ifdef CONFIG_MMC_EMBEDDED_SDIO
59 static struct embedded_sdio_data embedded_sdio_data0 = {
60         .cccr   = {
61                 .sdio_vsn       = 2,
62                 .multi_block    = 1,
63                 .low_speed      = 0,
64                 .wide_bus       = 0,
65                 .high_power     = 1,
66                 .high_speed     = 1,
67         },
68         .cis  = {
69                 .vendor  = 0x02d0,
70                 .device  = 0x4329,
71         },
72 };
73 #endif
74
75 struct tegra_sdhci_platform_data macallan_tegra_sdhci_platform_data0 = {
76         .mmc_data = {
77                 .register_status_notify = macallan_wifi_status_register,
78 #ifdef CONFIG_MMC_EMBEDDED_SDIO
79                 .embedded_sdio = &embedded_sdio_data0,
80 #endif
81                 .built_in = 0,
82                 .ocr_mask = MMC_OCR_1V8_MASK,
83         },
84 #ifndef CONFIG_MMC_EMBEDDED_SDIO
85         .pm_flags = MMC_PM_KEEP_POWER,
86 #endif
87         .cd_gpio = -1,
88         .wp_gpio = -1,
89         .power_gpio = -1,
90         .tap_delay = 0x2,
91         .trim_delay = 0x2,
92         .ddr_clk_limit = 41000000,
93         .uhs_mask = MMC_UHS_MASK_DDR50,
94         .disable_clock_gate = true,
95 };
96
97 #ifndef CONFIG_USE_OF
98 static struct resource sdhci_resource0[] = {
99         [0] = {
100                 .start  = INT_SDMMC1,
101                 .end    = INT_SDMMC1,
102                 .flags  = IORESOURCE_IRQ,
103         },
104         [1] = {
105                 .start  = TEGRA_SDMMC1_BASE,
106                 .end    = TEGRA_SDMMC1_BASE + TEGRA_SDMMC1_SIZE-1,
107                 .flags  = IORESOURCE_MEM,
108         },
109 };
110
111 static struct resource sdhci_resource2[] = {
112         [0] = {
113                 .start  = INT_SDMMC3,
114                 .end    = INT_SDMMC3,
115                 .flags  = IORESOURCE_IRQ,
116         },
117         [1] = {
118                 .start  = TEGRA_SDMMC3_BASE,
119                 .end    = TEGRA_SDMMC3_BASE + TEGRA_SDMMC3_SIZE-1,
120                 .flags  = IORESOURCE_MEM,
121         },
122 };
123
124 static struct resource sdhci_resource3[] = {
125         [0] = {
126                 .start  = INT_SDMMC4,
127                 .end    = INT_SDMMC4,
128                 .flags  = IORESOURCE_IRQ,
129         },
130         [1] = {
131                 .start  = TEGRA_SDMMC4_BASE,
132                 .end    = TEGRA_SDMMC4_BASE + TEGRA_SDMMC4_SIZE-1,
133                 .flags  = IORESOURCE_MEM,
134         },
135 };
136
137
138 static struct tegra_sdhci_platform_data tegra_sdhci_platform_data2 = {
139         .cd_gpio = MACALLAN_SD_CD,
140         .wp_gpio = MACALLAN_SD_WP,
141         .power_gpio = -1,
142         .tap_delay = 0x3,
143         .trim_delay = 0x3,
144         .ddr_clk_limit = 41000000,
145         .uhs_mask = MMC_UHS_MASK_DDR50,
146 };
147
148 static struct tegra_sdhci_platform_data tegra_sdhci_platform_data3 = {
149         .cd_gpio = -1,
150         .wp_gpio = -1,
151         .power_gpio = -1,
152         .is_8bit = 1,
153         .tap_delay = 0x5,
154         .trim_delay = 0xA,
155         .ddr_trim_delay = -1,
156         .ddr_clk_limit = 41000000,
157         .max_clk_limit = 156000000,
158         .mmc_data = {
159                 .built_in = 1,
160                 .ocr_mask = MMC_OCR_1V8_MASK,
161         }
162 };
163
164 static struct platform_device tegra_sdhci_device0 = {
165         .name           = "sdhci-tegra",
166         .id             = 0,
167         .resource       = sdhci_resource0,
168         .num_resources  = ARRAY_SIZE(sdhci_resource0),
169         .dev = {
170                 .platform_data = &macallan_tegra_sdhci_platform_data0,
171         },
172 };
173
174 static struct platform_device tegra_sdhci_device2 = {
175         .name           = "sdhci-tegra",
176         .id             = 2,
177         .resource       = sdhci_resource2,
178         .num_resources  = ARRAY_SIZE(sdhci_resource2),
179         .dev = {
180                 .platform_data = &tegra_sdhci_platform_data2,
181         },
182 };
183
184 static struct platform_device tegra_sdhci_device3 = {
185         .name           = "sdhci-tegra",
186         .id             = 3,
187         .resource       = sdhci_resource3,
188         .num_resources  = ARRAY_SIZE(sdhci_resource3),
189         .dev = {
190                 .platform_data = &tegra_sdhci_platform_data3,
191         },
192 };
193 #endif
194
195 static int macallan_wifi_status_register(
196                 void (*callback)(int card_present, void *dev_id),
197                 void *dev_id)
198 {
199         if (wifi_status_cb)
200                 return -EAGAIN;
201         wifi_status_cb = callback;
202         wifi_status_cb_devid = dev_id;
203         return 0;
204 }
205
206 static int macallan_wifi_set_carddetect(int val)
207 {
208         pr_debug("%s: %d\n", __func__, val);
209         if (wifi_status_cb)
210                 wifi_status_cb(val, wifi_status_cb_devid);
211         else
212                 pr_warning("%s: Nobody to notify\n", __func__);
213         return 0;
214 }
215
216 static int macallan_wifi_power(int on)
217 {
218         pr_debug("%s: %d\n", __func__, on);
219
220         if (on) {
221                 gpio_set_value(MACALLAN_WLAN_RST, 1);
222                 mdelay(100);
223                 gpio_set_value(MACALLAN_WLAN_RST, 0);
224                 mdelay(100);
225                 gpio_set_value(MACALLAN_WLAN_RST, 1);
226                 mdelay(100);
227                 gpio_set_value(MACALLAN_WLAN_PWR, 1);
228                 mdelay(200);
229         } else {
230                 gpio_set_value(MACALLAN_WLAN_RST, 0);
231                 mdelay(100);
232                 gpio_set_value(MACALLAN_WLAN_PWR, 0);
233         }
234
235         return 0;
236 }
237
238 static int __init macallan_wifi_init(void)
239 {
240         int rc;
241
242         rc = gpio_request(MACALLAN_WLAN_PWR, "wlan_power");
243         if (rc)
244                 pr_err("WLAN_PWR gpio request failed:%d\n", rc);
245         rc = gpio_request(MACALLAN_WLAN_RST, "wlan_rst");
246         if (rc)
247                 pr_err("WLAN_RST gpio request failed:%d\n", rc);
248         rc = gpio_request(MACALLAN_WLAN_WOW, "bcmsdh_sdmmc");
249         if (rc)
250                 pr_err("WLAN_WOW gpio request failed:%d\n", rc);
251
252         rc = gpio_direction_output(MACALLAN_WLAN_PWR, 0);
253         if (rc)
254                 pr_err("WLAN_PWR gpio direction configuration failed:%d\n", rc);
255         rc = gpio_direction_output(MACALLAN_WLAN_RST, 0);
256         if (rc)
257                 pr_err("WLAN_RST gpio direction configuration failed:%d\n", rc);
258         rc = gpio_direction_input(MACALLAN_WLAN_WOW);
259         if (rc)
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);
263         return 0;
264 }
265
266 #ifdef CONFIG_TEGRA_PREPOWER_WIFI
267 static int __init macallan_wifi_prepower(void)
268 {
269         if (!machine_is_macallan())
270                 return 0;
271
272         macallan_wifi_power(1);
273
274         return 0;
275 }
276
277 subsys_initcall_sync(macallan_wifi_prepower);
278 #endif
279
280 int __init macallan_sdhci_init(void)
281 {
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;
287
288         int nominal_core_mv;
289         int min_vcore_override_mv;
290         int boot_vcore_mv;
291
292         nominal_core_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 =
296                         nominal_core_mv;
297                 tegra_sdhci_platform_data2.nominal_vcore_mv = nominal_core_mv;
298                 tegra_sdhci_platform_data3.nominal_vcore_mv = nominal_core_mv;
299         }
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;
309         }
310         boot_vcore_mv = tegra_dvfs_rail_get_boot_level(tegra_core_rail);
311         if (boot_vcore_mv) {
312                 macallan_tegra_sdhci_platform_data0.boot_vcore_mv =
313                         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;
316         }
317
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;
322
323         platform_device_register(&tegra_sdhci_device3);
324         platform_device_register(&tegra_sdhci_device2);
325         platform_device_register(&tegra_sdhci_device0);
326 #endif
327         macallan_wifi_init();
328         return 0;
329 }