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