ARM: tegra: fix regulator_get() return value check
[linux-3.10.git] / arch / arm / mach-tegra / board-loki-sdhci.c
1 /*
2  * arch/arm/mach-tegra/board-loki-sdhci.c
3  *
4  * Copyright (c) 2013, NVIDIA CORPORATION.  All rights reserved.
5  *
6  * This program is free software; you can redistribute it and/or modify it
7  * under the terms and conditions of the GNU General Public License,
8  * version 2, as published by the Free Software Foundation.
9  *
10  * This program is distributed in the hope it will be useful, but WITHOUT
11  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
13  * more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
17  */
18
19 #include <linux/resource.h>
20 #include <linux/platform_device.h>
21 #include <linux/wlan_plat.h>
22 #include <linux/fs.h>
23 #include <linux/delay.h>
24 #include <linux/gpio.h>
25 #include <linux/clk.h>
26 #include <linux/err.h>
27 #include <linux/mmc/host.h>
28 #include <linux/wl12xx.h>
29 #include <linux/platform_data/mmc-sdhci-tegra.h>
30 #include <linux/mfd/max77660/max77660-core.h>
31
32 #include <asm/mach-types.h>
33 #include <mach/irqs.h>
34 #include <mach/gpio-tegra.h>
35
36 #include "gpio-names.h"
37 #include "board.h"
38 #include "board-loki.h"
39 #include "iomap.h"
40 #include "dvfs.h"
41
42 #define LOKI_WLAN_RST   TEGRA_GPIO_PR3
43 #define LOKI_WLAN_PWR   TEGRA_GPIO_PCC5
44 #define LOKI_WLAN_WOW   TEGRA_GPIO_PU5
45
46 #define LOKI_SD_CD      TEGRA_GPIO_PV2
47
48 static void (*wifi_status_cb)(int card_present, void *dev_id);
49 static void *wifi_status_cb_devid;
50 static int loki_wifi_status_register(void (*callback)(int , void *), void *);
51
52 static int loki_wifi_reset(int on);
53 static int loki_wifi_power(int on);
54 static int loki_wifi_set_carddetect(int val);
55 static int loki_wifi_get_mac_addr(unsigned char *buf);
56
57 static struct wifi_platform_data loki_wifi_control = {
58         .set_power      = loki_wifi_power,
59         .set_reset      = loki_wifi_reset,
60         .set_carddetect = loki_wifi_set_carddetect,
61         .get_mac_addr   = loki_wifi_get_mac_addr,
62 };
63
64 static struct resource wifi_resource[] = {
65         [0] = {
66                 .name   = "bcm4329_wlan_irq",
67                 .flags  = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL
68                                 | IORESOURCE_IRQ_SHAREABLE,
69         },
70 };
71
72 static struct platform_device loki_wifi_device = {
73         .name           = "bcm4329_wlan",
74         .id             = 1,
75         .num_resources  = 1,
76         .resource       = wifi_resource,
77         .dev            = {
78                 .platform_data = &loki_wifi_control,
79         },
80 };
81
82 static struct resource sdhci_resource0[] = {
83         [0] = {
84                 .start  = INT_SDMMC1,
85                 .end    = INT_SDMMC1,
86                 .flags  = IORESOURCE_IRQ,
87         },
88         [1] = {
89                 .start  = TEGRA_SDMMC1_BASE,
90                 .end    = TEGRA_SDMMC1_BASE + TEGRA_SDMMC1_SIZE-1,
91                 .flags  = IORESOURCE_MEM,
92         },
93 };
94
95 static struct resource sdhci_resource2[] = {
96         [0] = {
97                 .start  = INT_SDMMC3,
98                 .end    = INT_SDMMC3,
99                 .flags  = IORESOURCE_IRQ,
100         },
101         [1] = {
102                 .start  = TEGRA_SDMMC3_BASE,
103                 .end    = TEGRA_SDMMC3_BASE + TEGRA_SDMMC3_SIZE-1,
104                 .flags  = IORESOURCE_MEM,
105         },
106 };
107
108 static struct resource sdhci_resource3[] = {
109         [0] = {
110                 .start  = INT_SDMMC4,
111                 .end    = INT_SDMMC4,
112                 .flags  = IORESOURCE_IRQ,
113         },
114         [1] = {
115                 .start  = TEGRA_SDMMC4_BASE,
116                 .end    = TEGRA_SDMMC4_BASE + TEGRA_SDMMC4_SIZE-1,
117                 .flags  = IORESOURCE_MEM,
118         },
119 };
120
121 #ifdef CONFIG_MMC_EMBEDDED_SDIO
122 static struct embedded_sdio_data embedded_sdio_data0 = {
123         .cccr   = {
124                 .sdio_vsn       = 2,
125                 .multi_block    = 1,
126                 .low_speed      = 0,
127                 .wide_bus       = 0,
128                 .high_power     = 1,
129                 .high_speed     = 1,
130         },
131         .cis  = {
132                 .vendor  = 0x02d0,
133                 .device  = 0x4329,
134         },
135 };
136 #endif
137
138 static struct tegra_sdhci_platform_data tegra_sdhci_platform_data0 = {
139         .mmc_data = {
140                 .register_status_notify = loki_wifi_status_register,
141 #ifdef CONFIG_MMC_EMBEDDED_SDIO
142                 .embedded_sdio = &embedded_sdio_data0,
143 #endif
144                 .built_in = 0,
145                 .ocr_mask = MMC_OCR_1V8_MASK,
146         },
147         .cd_gpio = -1,
148         .wp_gpio = -1,
149         .power_gpio = -1,
150         .tap_delay = 0,
151         .trim_delay = 0x2,
152         .ddr_clk_limit = 41000000,
153         .uhs_mask = MMC_UHS_MASK_DDR50 | MMC_UHS_MASK_SDR50,
154         .calib_3v3_offsets = 0x7676,
155         .calib_1v8_offsets = 0x7676,
156 };
157
158 static struct tegra_sdhci_platform_data tegra_sdhci_platform_data2 = {
159         .cd_gpio = LOKI_SD_CD,
160         .wp_gpio = -1,
161         .power_gpio = -1,
162         .tap_delay = 0,
163         .trim_delay = 0x3,
164         .uhs_mask = MMC_UHS_MASK_DDR50 | MMC_UHS_MASK_SDR50,
165         .max_clk_limit = 204000000,
166         .calib_3v3_offsets = 0x7676,
167         .calib_1v8_offsets = 0x7676,
168 };
169
170 static struct tegra_sdhci_platform_data tegra_sdhci_platform_data3 = {
171         .cd_gpio = -1,
172         .wp_gpio = -1,
173         .power_gpio = -1,
174         .is_8bit = 1,
175         .tap_delay = 0x4,
176         .trim_delay = 0x4,
177         .ddr_trim_delay = 0x0,
178         .mmc_data = {
179                 .built_in = 1,
180                 .ocr_mask = MMC_OCR_1V8_MASK,
181         },
182         .ddr_clk_limit = 51000000,
183         .max_clk_limit = 200000000,
184         .calib_3v3_offsets = 0x0202,
185         .calib_1v8_offsets = 0x0202,
186 };
187
188 static struct platform_device tegra_sdhci_device0 = {
189         .name           = "sdhci-tegra",
190         .id             = 0,
191         .resource       = sdhci_resource0,
192         .num_resources  = ARRAY_SIZE(sdhci_resource0),
193         .dev = {
194                 .platform_data = &tegra_sdhci_platform_data0,
195         },
196 };
197
198 static struct platform_device tegra_sdhci_device2 = {
199         .name           = "sdhci-tegra",
200         .id             = 2,
201         .resource       = sdhci_resource2,
202         .num_resources  = ARRAY_SIZE(sdhci_resource2),
203         .dev = {
204                 .platform_data = &tegra_sdhci_platform_data2,
205         },
206 };
207
208 static struct platform_device tegra_sdhci_device3 = {
209         .name           = "sdhci-tegra",
210         .id             = 3,
211         .resource       = sdhci_resource3,
212         .num_resources  = ARRAY_SIZE(sdhci_resource3),
213         .dev = {
214                 .platform_data = &tegra_sdhci_platform_data3,
215         },
216 };
217
218 static int loki_wifi_status_register(
219                 void (*callback)(int card_present, void *dev_id),
220                 void *dev_id)
221 {
222         if (wifi_status_cb)
223                 return -EAGAIN;
224         wifi_status_cb = callback;
225         wifi_status_cb_devid = dev_id;
226         return 0;
227 }
228
229 static int loki_wifi_set_carddetect(int val)
230 {
231         pr_debug("%s: %d\n", __func__, val);
232         if (wifi_status_cb)
233                 wifi_status_cb(val, wifi_status_cb_devid);
234         else
235                 pr_warn("%s: Nobody to notify\n", __func__);
236         return 0;
237 }
238
239 static struct regulator *loki_vdd_com_3v3;
240 static struct regulator *loki_vddio_com_1v8;
241
242 #define LOKI_VDD_WIFI_3V3 "avdd"
243 #define LOKI_VDD_WIFI_1V8 "dvdd"
244
245 static int loki_wifi_regulator_enable(void)
246 {
247         int ret = 0;
248
249         /* Enable COM's vdd_com_3v3 regulator*/
250         if (IS_ERR_OR_NULL(loki_vdd_com_3v3)) {
251                 loki_vdd_com_3v3 = regulator_get(&loki_wifi_device.dev,
252                                         LOKI_VDD_WIFI_3V3);
253                 if (IS_ERR(loki_vdd_com_3v3)) {
254                         pr_err("Couldn't get regulator "
255                                 LOKI_VDD_WIFI_3V3 "\n");
256                         return PTR_ERR(loki_vdd_com_3v3);
257                 }
258
259                 ret = regulator_enable(loki_vdd_com_3v3);
260                 if (ret < 0) {
261                         pr_err("Couldn't enable regulator "
262                                 LOKI_VDD_WIFI_3V3 "\n");
263                         regulator_put(loki_vdd_com_3v3);
264                         loki_vdd_com_3v3 = NULL;
265                         return ret;
266                 }
267         }
268
269         /* Enable COM's vddio_com_1v8 regulator*/
270         if (IS_ERR_OR_NULL(loki_vddio_com_1v8)) {
271                 loki_vddio_com_1v8 = regulator_get(&loki_wifi_device.dev,
272                         LOKI_VDD_WIFI_1V8);
273                 if (IS_ERR(loki_vddio_com_1v8)) {
274                         pr_err("Couldn't get regulator "
275                                 LOKI_VDD_WIFI_1V8 "\n");
276                         regulator_disable(loki_vdd_com_3v3);
277
278                         regulator_put(loki_vdd_com_3v3);
279                         loki_vdd_com_3v3 = NULL;
280                         return PTR_ERR(loki_vddio_com_1v8);
281                 }
282
283                 ret = regulator_enable(loki_vddio_com_1v8);
284                 if (ret < 0) {
285                         pr_err("Couldn't enable regulator "
286                                 LOKI_VDD_WIFI_1V8 "\n");
287                         regulator_put(loki_vddio_com_1v8);
288                         loki_vddio_com_1v8 = NULL;
289
290                         regulator_disable(loki_vdd_com_3v3);
291                         regulator_put(loki_vdd_com_3v3);
292                         loki_vdd_com_3v3 = NULL;
293                         return ret;
294                 }
295         }
296
297         return ret;
298 }
299
300 static void loki_wifi_regulator_disable(void)
301 {
302         /* Disable COM's vdd_com_3v3 regulator*/
303         if (!IS_ERR_OR_NULL(loki_vdd_com_3v3)) {
304                 regulator_disable(loki_vdd_com_3v3);
305                 regulator_put(loki_vdd_com_3v3);
306                 loki_vdd_com_3v3 = NULL;
307         }
308
309         /* Disable COM's vddio_com_1v8 regulator*/
310         if (!IS_ERR_OR_NULL(loki_vddio_com_1v8)) {
311                 regulator_disable(loki_vddio_com_1v8);
312                 regulator_put(loki_vddio_com_1v8);
313                 loki_vddio_com_1v8 = NULL;
314         }
315 }
316
317 static int loki_wifi_power(int on)
318 {
319         int ret = 0;
320
321         pr_err("%s: %d\n", __func__, on);
322
323         /* Enable COM's regulators on wi-fi poer on*/
324         if (on == 1) {
325                 ret = loki_wifi_regulator_enable();
326                 if (ret < 0) {
327                         pr_err("Failed to enable COM regulators\n");
328                         return ret;
329                 }
330         }
331
332         gpio_set_value(LOKI_WLAN_PWR, on);
333         gpio_set_value(LOKI_WLAN_RST, on);
334         mdelay(100);
335
336         /* Disable COM's regulators on wi-fi poer off*/
337         if (on != 1) {
338                 pr_debug("Disabling COM regulators\n");
339                 loki_wifi_regulator_disable();
340         }
341
342         return 0;
343 }
344
345 static int loki_wifi_reset(int on)
346 {
347         pr_debug("%s: do nothing\n", __func__);
348         return 0;
349 }
350
351 #define LOKI_WIFI_MAC_ADDR_FILE "/mnt/factory/wifi/wifi_mac.txt"
352
353 static int loki_wifi_get_mac_addr(unsigned char *buf)
354 {
355         struct file *fp;
356         int rdlen;
357         char str[32];
358         int mac[6];
359         int ret = 0;
360
361         pr_debug("%s\n", __func__);
362
363         /* open wifi mac address file */
364         fp = filp_open(LOKI_WIFI_MAC_ADDR_FILE, O_RDONLY, 0);
365         if (IS_ERR(fp)) {
366                 pr_err("%s: cannot open %s\n",
367                         __func__, LOKI_WIFI_MAC_ADDR_FILE);
368                 return -ENOENT;
369         }
370
371         /* read wifi mac address file */
372         memset(str, 0, sizeof(str));
373         rdlen = kernel_read(fp, fp->f_pos, str, 17);
374         if (rdlen > 0)
375                 fp->f_pos += rdlen;
376         if (rdlen != 17) {
377                 pr_err("%s: bad mac address file"
378                         " - len %d < 17",
379                         __func__, rdlen);
380                 ret = -ENOENT;
381         } else if (sscanf(str, "%x:%x:%x:%x:%x:%x",
382                 &mac[0], &mac[1], &mac[2], &mac[3], &mac[4], &mac[5]) != 6) {
383                 pr_err("%s: bad mac address file"
384                         " - must contain xx:xx:xx:xx:xx:xx\n",
385                         __func__);
386                 ret = -ENOENT;
387         } else {
388                 pr_info("%s: using wifi mac %02x:%02x:%02x:%02x:%02x:%02x\n",
389                         __func__,
390                         mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
391                 buf[0] = (unsigned char) mac[0];
392                 buf[1] = (unsigned char) mac[1];
393                 buf[2] = (unsigned char) mac[2];
394                 buf[3] = (unsigned char) mac[3];
395                 buf[4] = (unsigned char) mac[4];
396                 buf[5] = (unsigned char) mac[5];
397         }
398
399         /* close wifi mac address file */
400         filp_close(fp, NULL);
401
402         return ret;
403 }
404
405 static int __init loki_wifi_init(void)
406 {
407         int rc;
408
409         rc = gpio_request(LOKI_WLAN_PWR, "wlan_power");
410         if (rc)
411                 pr_err("WLAN_PWR gpio request failed:%d\n", rc);
412         rc = gpio_request(LOKI_WLAN_RST, "wlan_rst");
413         if (rc)
414                 pr_err("WLAN_RST gpio request failed:%d\n", rc);
415         rc = gpio_request(LOKI_WLAN_WOW, "bcmsdh_sdmmc");
416         if (rc)
417                 pr_err("WLAN_WOW gpio request failed:%d\n", rc);
418
419         rc = gpio_direction_output(LOKI_WLAN_PWR, 0);
420         if (rc)
421                 pr_err("WLAN_PWR gpio direction configuration failed:%d\n", rc);
422         rc = gpio_direction_output(LOKI_WLAN_RST, 0);
423         if (rc)
424                 pr_err("WLAN_RST gpio direction configuration failed:%d\n", rc);
425
426         rc = gpio_direction_input(LOKI_WLAN_WOW);
427         if (rc)
428                 pr_err("WLAN_WOW gpio direction configuration failed:%d\n", rc);
429
430         wifi_resource[0].start = wifi_resource[0].end =
431                 gpio_to_irq(LOKI_WLAN_WOW);
432
433         platform_device_register(&loki_wifi_device);
434         return 0;
435 }
436
437 #ifdef CONFIG_TEGRA_PREPOWER_WIFI
438 static int __init loki_wifi_prepower(void)
439 {
440         if (!of_machine_is_compatible("nvidia,loki"))
441                 return 0;
442         loki_wifi_power(1);
443
444         return 0;
445 }
446
447 subsys_initcall_sync(loki_wifi_prepower);
448 #endif
449
450 int __init loki_sdhci_init(void)
451 {
452         int nominal_core_mv;
453         int min_vcore_override_mv;
454         int boot_vcore_mv;
455
456         nominal_core_mv =
457                 tegra_dvfs_rail_get_nominal_millivolts(tegra_core_rail);
458         if (nominal_core_mv) {
459                 tegra_sdhci_platform_data0.nominal_vcore_mv = nominal_core_mv;
460                 tegra_sdhci_platform_data2.nominal_vcore_mv = nominal_core_mv;
461                 tegra_sdhci_platform_data3.nominal_vcore_mv = nominal_core_mv;
462         }
463         min_vcore_override_mv =
464                 tegra_dvfs_rail_get_override_floor(tegra_core_rail);
465         if (min_vcore_override_mv) {
466                 tegra_sdhci_platform_data0.min_vcore_override_mv =
467                         min_vcore_override_mv;
468                 tegra_sdhci_platform_data2.min_vcore_override_mv =
469                         min_vcore_override_mv;
470                 tegra_sdhci_platform_data3.min_vcore_override_mv =
471                         min_vcore_override_mv;
472         }
473         boot_vcore_mv = tegra_dvfs_rail_get_boot_level(tegra_core_rail);
474         if (boot_vcore_mv) {
475                 tegra_sdhci_platform_data0.boot_vcore_mv = boot_vcore_mv;
476                 tegra_sdhci_platform_data2.boot_vcore_mv = boot_vcore_mv;
477                 tegra_sdhci_platform_data3.boot_vcore_mv = boot_vcore_mv;
478         }
479
480         tegra_sdhci_platform_data0.max_clk_limit = 204000000;
481
482         platform_device_register(&tegra_sdhci_device3);
483         platform_device_register(&tegra_sdhci_device2);
484         platform_device_register(&tegra_sdhci_device0);
485         loki_wifi_init();
486
487         return 0;
488 }