ARM: tegra12: set CPU rate to 2.2GHz for sku 0x87
[linux-3.10.git] / arch / arm / mach-tegra / board-dalmore-sdhci.c
1 /*
2  * arch/arm/mach-tegra/board-dalmore-sdhci.c
3  *
4  * Copyright (C) 2010 Google, Inc.
5  * Copyright (c) 2013, NVIDIA CORPORATION.  All rights reserved.
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/regulator/consumer.h>
26 #include <linux/mmc/host.h>
27 #include <linux/wl12xx.h>
28 #include <linux/platform_data/mmc-sdhci-tegra.h>
29
30 #include <asm/mach-types.h>
31 #include <mach/irqs.h>
32 #include <mach/gpio-tegra.h>
33
34 #include "tegra-board-id.h"
35 #include "gpio-names.h"
36 #include "board.h"
37 #include "board-dalmore.h"
38 #include "dvfs.h"
39 #include "iomap.h"
40
41 #define DALMORE_WLAN_PWR        TEGRA_GPIO_PCC5
42 #define DALMORE_WLAN_RST        TEGRA_GPIO_PX7
43 #define DALMORE_WLAN_WOW        TEGRA_GPIO_PU5
44 #define DALMORE_SD_CD           TEGRA_GPIO_PV2
45 #define DALMORE_SD_WP           TEGRA_GPIO_PQ4
46 static void (*wifi_status_cb)(int card_present, void *dev_id);
47 static void *wifi_status_cb_devid;
48 static int dalmore_wifi_status_register(void (*callback)(int , void *), void *);
49
50 static int dalmore_wifi_reset(int on);
51 static int dalmore_wifi_power(int on);
52 static int dalmore_wifi_set_carddetect(int val);
53
54 static struct wifi_platform_data dalmore_wifi_control = {
55         .set_power      = dalmore_wifi_power,
56         .set_reset      = dalmore_wifi_reset,
57         .set_carddetect = dalmore_wifi_set_carddetect,
58 };
59
60 static struct resource wifi_resource[] = {
61         [0] = {
62                 .name   = "bcm4329_wlan_irq",
63                 .flags  = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL
64                                 | IORESOURCE_IRQ_SHAREABLE,
65         },
66 };
67
68 static struct platform_device dalmore_wifi_device = {
69         .name           = "bcm4329_wlan",
70         .id             = 1,
71         .num_resources  = 1,
72         .resource       = wifi_resource,
73         .dev            = {
74                 .platform_data = &dalmore_wifi_control,
75         },
76 };
77
78 #ifdef CONFIG_MMC_EMBEDDED_SDIO
79 static struct embedded_sdio_data embedded_sdio_data0 = {
80         .cccr   = {
81                 .sdio_vsn       = 2,
82                 .multi_block    = 1,
83                 .low_speed      = 0,
84                 .wide_bus       = 0,
85                 .high_power     = 1,
86                 .high_speed     = 1,
87         },
88         .cis  = {
89                 .vendor  = 0x02d0,
90                 .device  = 0x4329,
91         },
92 };
93 #endif
94
95 struct tegra_sdhci_platform_data dalmore_tegra_sdhci_platform_data0 = {
96         .mmc_data = {
97                 .register_status_notify = dalmore_wifi_status_register,
98 #ifdef CONFIG_MMC_EMBEDDED_SDIO
99                 .embedded_sdio = &embedded_sdio_data0,
100 #endif
101                 .built_in = 0,
102                 .ocr_mask = MMC_OCR_1V8_MASK,
103         },
104 #ifndef CONFIG_MMC_EMBEDDED_SDIO
105         .pm_flags = MMC_PM_KEEP_POWER,
106 #endif
107         .cd_gpio = -1,
108         .wp_gpio = -1,
109         .power_gpio = -1,
110         .tap_delay = 0x2,
111         .trim_delay = 0x2,
112         .ddr_clk_limit = 41000000,
113         .max_clk_limit = 82000000,
114 /*FIXME: Enable UHS modes for WiFI */
115         .uhs_mask = MMC_UHS_MASK_DDR50 | MMC_UHS_MASK_SDR50 |
116                 MMC_UHS_MASK_SDR104 | MMC_UHS_MASK_SDR12 | MMC_UHS_MASK_SDR25,
117         .disable_clock_gate = true,
118 };
119
120 static struct resource sdhci_resource0[] = {
121         [0] = {
122                 .start  = INT_SDMMC1,
123                 .end    = INT_SDMMC1,
124                 .flags  = IORESOURCE_IRQ,
125         },
126         [1] = {
127                 .start  = TEGRA_SDMMC1_BASE,
128                 .end    = TEGRA_SDMMC1_BASE + TEGRA_SDMMC1_SIZE-1,
129                 .flags  = IORESOURCE_MEM,
130         },
131 };
132
133 static struct resource sdhci_resource2[] = {
134         [0] = {
135                 .start  = INT_SDMMC3,
136                 .end    = INT_SDMMC3,
137                 .flags  = IORESOURCE_IRQ,
138         },
139         [1] = {
140                 .start  = TEGRA_SDMMC3_BASE,
141                 .end    = TEGRA_SDMMC3_BASE + TEGRA_SDMMC3_SIZE-1,
142                 .flags  = IORESOURCE_MEM,
143         },
144 };
145
146 static struct resource sdhci_resource3[] = {
147         [0] = {
148                 .start  = INT_SDMMC4,
149                 .end    = INT_SDMMC4,
150                 .flags  = IORESOURCE_IRQ,
151         },
152         [1] = {
153                 .start  = TEGRA_SDMMC4_BASE,
154                 .end    = TEGRA_SDMMC4_BASE + TEGRA_SDMMC4_SIZE-1,
155                 .flags  = IORESOURCE_MEM,
156         },
157 };
158
159 static struct tegra_sdhci_platform_data tegra_sdhci_platform_data2 = {
160         .cd_gpio = DALMORE_SD_CD,
161         .wp_gpio = DALMORE_SD_WP,
162         .power_gpio = -1,
163         .tap_delay = 0x3,
164         .trim_delay = 0x3,
165         .ddr_clk_limit = 41000000,
166         .max_clk_limit = 82000000,
167         .uhs_mask = MMC_UHS_MASK_DDR50,
168         .power_off_rail = true,
169 };
170
171 static struct tegra_sdhci_platform_data tegra_sdhci_platform_data3 = {
172         .cd_gpio = -1,
173         .wp_gpio = -1,
174         .power_gpio = -1,
175         .is_8bit = 1,
176         .tap_delay = 0x5,
177         .trim_delay = 0xA,
178         .ddr_trim_delay = -1,
179         .ddr_clk_limit = 41000000,
180         .max_clk_limit = 156000000,
181         .mmc_data = {
182                 .built_in = 1,
183                 .ocr_mask = MMC_OCR_1V8_MASK,
184         }
185 };
186
187 static struct platform_device tegra_sdhci_device0 = {
188         .name           = "sdhci-tegra",
189         .id             = 0,
190         .resource       = sdhci_resource0,
191         .num_resources  = ARRAY_SIZE(sdhci_resource0),
192         .dev = {
193                 .platform_data = &dalmore_tegra_sdhci_platform_data0,
194         },
195 };
196
197 static struct platform_device tegra_sdhci_device2 = {
198         .name           = "sdhci-tegra",
199         .id             = 2,
200         .resource       = sdhci_resource2,
201         .num_resources  = ARRAY_SIZE(sdhci_resource2),
202         .dev = {
203                 .platform_data = &tegra_sdhci_platform_data2,
204         },
205 };
206
207 static struct platform_device tegra_sdhci_device3 = {
208         .name           = "sdhci-tegra",
209         .id             = 3,
210         .resource       = sdhci_resource3,
211         .num_resources  = ARRAY_SIZE(sdhci_resource3),
212         .dev = {
213                 .platform_data = &tegra_sdhci_platform_data3,
214         },
215 };
216
217 static int dalmore_wifi_status_register(
218                 void (*callback)(int card_present, void *dev_id),
219                 void *dev_id)
220 {
221         if (wifi_status_cb)
222                 return -EAGAIN;
223         wifi_status_cb = callback;
224         wifi_status_cb_devid = dev_id;
225         return 0;
226 }
227
228 static int dalmore_wifi_set_carddetect(int val)
229 {
230         pr_debug("%s: %d\n", __func__, val);
231         if (wifi_status_cb)
232                 wifi_status_cb(val, wifi_status_cb_devid);
233         else
234                 pr_warning("%s: Nobody to notify\n", __func__);
235         return 0;
236 }
237
238 static struct regulator *dalmore_vdd_com_3v3;
239 static struct regulator *dalmore_vddio_com_1v8;
240 #define DALMORE_VDD_WIFI_3V3 "avdd"
241 #define DALMORE_VDD_WIFI_1V8 "dvdd"
242
243 static int dalmore_wifi_regulator_enable(void)
244 {
245         int ret = 0;
246
247         /* Enable COM's vdd_com_3v3 regulator*/
248         if (IS_ERR_OR_NULL(dalmore_vdd_com_3v3)) {
249                 dalmore_vdd_com_3v3 = regulator_get(&dalmore_wifi_device.dev,
250                                                         DALMORE_VDD_WIFI_3V3);
251                 if (IS_ERR(dalmore_vdd_com_3v3)) {
252                         pr_err("Couldn't get regulator "
253                                 DALMORE_VDD_WIFI_3V3 "\n");
254                         return PTR_ERR(dalmore_vdd_com_3v3);
255                 }
256
257                 ret = regulator_enable(dalmore_vdd_com_3v3);
258                 if (ret < 0) {
259                         pr_err("Couldn't enable regulator "
260                                 DALMORE_VDD_WIFI_3V3 "\n");
261                         regulator_put(dalmore_vdd_com_3v3);
262                         dalmore_vdd_com_3v3 = NULL;
263                         return ret;
264                 }
265         }
266
267         /* Enable COM's vddio_com_1v8 regulator*/
268         if (IS_ERR_OR_NULL(dalmore_vddio_com_1v8)) {
269                 dalmore_vddio_com_1v8 = regulator_get(&dalmore_wifi_device.dev,
270                         DALMORE_VDD_WIFI_1V8);
271                 if (IS_ERR(dalmore_vddio_com_1v8)) {
272                         pr_err("Couldn't get regulator "
273                                 DALMORE_VDD_WIFI_1V8 "\n");
274                         regulator_disable(dalmore_vdd_com_3v3);
275
276                         regulator_put(dalmore_vdd_com_3v3);
277                         dalmore_vdd_com_3v3 = NULL;
278                         return PTR_ERR(dalmore_vddio_com_1v8);
279                 }
280
281                 ret = regulator_enable(dalmore_vddio_com_1v8);
282                 if (ret < 0) {
283                         pr_err("Couldn't enable regulator "
284                                 DALMORE_VDD_WIFI_1V8 "\n");
285                         regulator_put(dalmore_vddio_com_1v8);
286                         dalmore_vddio_com_1v8 = NULL;
287
288                         regulator_disable(dalmore_vdd_com_3v3);
289                         regulator_put(dalmore_vdd_com_3v3);
290                         dalmore_vdd_com_3v3 = NULL;
291                         return ret;
292                 }
293         }
294
295         return ret;
296 }
297
298 static void dalmore_wifi_regulator_disable(void)
299 {
300         /* Disable COM's vdd_com_3v3 regulator*/
301         if (!IS_ERR_OR_NULL(dalmore_vdd_com_3v3)) {
302                 regulator_disable(dalmore_vdd_com_3v3);
303                 regulator_put(dalmore_vdd_com_3v3);
304                 dalmore_vdd_com_3v3 = NULL;
305         }
306
307         /* Disable COM's vddio_com_1v8 regulator*/
308         if (!IS_ERR_OR_NULL(dalmore_vddio_com_1v8)) {
309                 regulator_disable(dalmore_vddio_com_1v8);
310                 regulator_put(dalmore_vddio_com_1v8);
311                 dalmore_vddio_com_1v8 = NULL;
312         }
313 }
314
315 static int dalmore_wifi_power(int on)
316 {
317         int ret = 0;
318
319         pr_debug("%s: %d\n", __func__, on);
320         /* Enable COM's regulators on wi-fi poer on*/
321         if (on == 1) {
322                 ret = dalmore_wifi_regulator_enable();
323                 if (ret < 0) {
324                         pr_err("Failed to enable COM regulators\n");
325                         return ret;
326                 }
327         }
328
329         gpio_set_value(DALMORE_WLAN_PWR, on);
330         mdelay(100);
331         gpio_set_value(DALMORE_WLAN_RST, on);
332         mdelay(200);
333
334         /* Disable COM's regulators on wi-fi poer off*/
335         if (on != 1) {
336                 pr_debug("Disabling COM regulators\n");
337                 dalmore_wifi_regulator_disable();
338         }
339
340         return ret;
341 }
342
343 static int dalmore_wifi_reset(int on)
344 {
345         pr_debug("%s: do nothing\n", __func__);
346         return 0;
347 }
348
349 static int __init dalmore_wifi_init(void)
350 {
351         int rc;
352
353         rc = gpio_request(DALMORE_WLAN_PWR, "wlan_power");
354         if (rc)
355                 pr_err("WLAN_PWR gpio request failed:%d\n", rc);
356         rc = gpio_request(DALMORE_WLAN_RST, "wlan_rst");
357         if (rc)
358                 pr_err("WLAN_RST gpio request failed:%d\n", rc);
359         rc = gpio_request(DALMORE_WLAN_WOW, "bcmsdh_sdmmc");
360         if (rc)
361                 pr_err("WLAN_WOW gpio request failed:%d\n", rc);
362
363         rc = gpio_direction_output(DALMORE_WLAN_PWR, 0);
364         if (rc)
365                 pr_err("WLAN_PWR gpio direction configuration failed:%d\n", rc);
366         gpio_direction_output(DALMORE_WLAN_RST, 0);
367         if (rc)
368                 pr_err("WLAN_RST gpio direction configuration failed:%d\n", rc);
369         rc = gpio_direction_input(DALMORE_WLAN_WOW);
370         if (rc)
371                 pr_err("WLAN_WOW gpio direction configuration failed:%d\n", rc);
372
373         wifi_resource[0].start = wifi_resource[0].end =
374                 gpio_to_irq(DALMORE_WLAN_WOW);
375
376         platform_device_register(&dalmore_wifi_device);
377         return 0;
378 }
379
380 #ifdef CONFIG_TEGRA_PREPOWER_WIFI
381 static int __init dalmore_wifi_prepower(void)
382 {
383         if (!machine_is_dalmore())
384                 return 0;
385
386         dalmore_wifi_power(1);
387
388         return 0;
389 }
390
391 subsys_initcall_sync(dalmore_wifi_prepower);
392 #endif
393
394 int __init dalmore_sdhci_init(void)
395 {
396         int nominal_core_mv;
397         int min_vcore_override_mv;
398         int boot_vcore_mv;
399         struct board_info board_info;
400
401         nominal_core_mv =
402                 tegra_dvfs_rail_get_nominal_millivolts(tegra_core_rail);
403         if (nominal_core_mv) {
404                 dalmore_tegra_sdhci_platform_data0.nominal_vcore_mv =
405                         nominal_core_mv;
406                 tegra_sdhci_platform_data2.nominal_vcore_mv = nominal_core_mv;
407                 tegra_sdhci_platform_data3.nominal_vcore_mv = nominal_core_mv;
408         }
409         min_vcore_override_mv =
410                 tegra_dvfs_rail_get_override_floor(tegra_core_rail);
411         if (min_vcore_override_mv) {
412                 dalmore_tegra_sdhci_platform_data0.min_vcore_override_mv =
413                         min_vcore_override_mv;
414                 tegra_sdhci_platform_data2.min_vcore_override_mv =
415                         min_vcore_override_mv;
416                 tegra_sdhci_platform_data3.min_vcore_override_mv =
417                         min_vcore_override_mv;
418         }
419         boot_vcore_mv = tegra_dvfs_rail_get_boot_level(tegra_core_rail);
420         if (boot_vcore_mv) {
421                 dalmore_tegra_sdhci_platform_data0.boot_vcore_mv =
422                         boot_vcore_mv;
423                 tegra_sdhci_platform_data2.boot_vcore_mv = boot_vcore_mv;
424                 tegra_sdhci_platform_data3.boot_vcore_mv = boot_vcore_mv;
425         }
426         if ((tegra_sdhci_platform_data3.uhs_mask & MMC_MASK_HS200)
427                 && (!(tegra_sdhci_platform_data3.uhs_mask &
428                 MMC_UHS_MASK_DDR50)))
429                 tegra_sdhci_platform_data3.trim_delay = 0;
430         tegra_get_board_info(&board_info);
431         if (board_info.fab == BOARD_FAB_A05) {
432                 tegra_sdhci_platform_data2.wp_gpio = -1;
433                 dalmore_tegra_sdhci_platform_data0.max_clk_limit = 156000000;
434                 tegra_sdhci_platform_data2.max_clk_limit = 156000000;
435         }
436         platform_device_register(&tegra_sdhci_device3);
437         platform_device_register(&tegra_sdhci_device2);
438         platform_device_register(&tegra_sdhci_device0);
439         dalmore_wifi_init();
440         return 0;
441 }