arm: tegra: add sdhci device registration for ardbeg
Mitch Luban [Fri, 12 Apr 2013 16:24:36 +0000 (09:24 -0700)]
Bug 1257423

Change-Id: Id3d2bbbb7eccf13ff5269848f5fdaaa8b30c980f
Signed-off-by: Mitch Luban <mluban@nvidia.com>
Reviewed-on: http://git-master/r/218983
Reviewed-by: Automatic_Commit_Validation_User
Reviewed-by: Chao Xu <cxu@nvidia.com>

arch/arm/mach-tegra/Makefile
arch/arm/mach-tegra/board-ardbeg-sdhci.c [new file with mode: 0644]
arch/arm/mach-tegra/board-ardbeg.c
arch/arm/mach-tegra/board-ardbeg.h

index bb396e2..07a2425 100644 (file)
@@ -262,6 +262,7 @@ obj-${CONFIG_MACH_TEGRA_PLUTO}          += panel-s-1080p-5.o
 
 obj-${CONFIG_MACH_ARDBEG}               += board-ardbeg.o
 obj-${CONFIG_MACH_ARDBEG}               += board-ardbeg-kbc.o
+obj-${CONFIG_MACH_ARDBEG}               += board-ardbeg-sdhci.o
 obj-${CONFIG_MACH_ARDBEG}               += board-ardbeg-panel.o
 obj-${CONFIG_MACH_ARDBEG}               += board-ardbeg-pinmux.o
 obj-${CONFIG_MACH_ARDBEG}               += panel-a-1080p-11-6.o
diff --git a/arch/arm/mach-tegra/board-ardbeg-sdhci.c b/arch/arm/mach-tegra/board-ardbeg-sdhci.c
new file mode 100644 (file)
index 0000000..e2fd97d
--- /dev/null
@@ -0,0 +1,296 @@
+/*
+ * arch/arm/mach-tegra/board-ardbeg-sdhci.c
+ *
+ * Copyright (c) 2013, NVIDIA CORPORATION.  All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/resource.h>
+#include <linux/platform_device.h>
+#include <linux/wlan_plat.h>
+#include <linux/delay.h>
+#include <linux/gpio.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/mmc/host.h>
+#include <linux/wl12xx.h>
+#include <linux/platform_data/mmc-sdhci-tegra.h>
+#include <linux/mfd/max77660/max77660-core.h>
+
+#include <asm/mach-types.h>
+#include <mach/irqs.h>
+#include <mach/gpio-tegra.h>
+
+#include "gpio-names.h"
+#include "board.h"
+#include "board-ardbeg.h"
+#include "iomap.h"
+
+#ifdef CONFIG_ARCH_TEGRA_11x_SOC
+#define ARDBEG_WLAN_PWR        TEGRA_GPIO_PCC5
+#define ARDBEG_WLAN_WOW        TEGRA_GPIO_PU5
+#else
+/* FIXME: update GPIO's for 124 */
+#define ARDBEG_WLAN_PWR  TEGRA_GPIO_PL7
+#define ARDBEG_WLAN_WOW  TEGRA_GPIO_PO2
+#endif
+
+#define ARDBEG_SD_CD   (MAX77660_GPIO_BASE + MAX77660_GPIO9)
+
+static void (*wifi_status_cb)(int card_present, void *dev_id);
+static void *wifi_status_cb_devid;
+static int ardbeg_wifi_status_register(void (*callback)(int , void *), void *);
+
+static int ardbeg_wifi_reset(int on);
+static int ardbeg_wifi_power(int on);
+static int ardbeg_wifi_set_carddetect(int val);
+
+static struct wifi_platform_data ardbeg_wifi_control = {
+       .set_power      = ardbeg_wifi_power,
+       .set_reset      = ardbeg_wifi_reset,
+       .set_carddetect = ardbeg_wifi_set_carddetect,
+};
+
+static struct resource wifi_resource[] = {
+       [0] = {
+               .name   = "bcm4329_wlan_irq",
+               .flags  = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL
+                               | IORESOURCE_IRQ_SHAREABLE,
+       },
+};
+
+static struct platform_device ardbeg_wifi_device = {
+       .name           = "bcm4329_wlan",
+       .id             = 1,
+       .num_resources  = 1,
+       .resource       = wifi_resource,
+       .dev            = {
+               .platform_data = &ardbeg_wifi_control,
+       },
+};
+
+static struct resource sdhci_resource0[] = {
+       [0] = {
+               .start  = INT_SDMMC1,
+               .end    = INT_SDMMC1,
+               .flags  = IORESOURCE_IRQ,
+       },
+       [1] = {
+               .start  = TEGRA_SDMMC1_BASE,
+               .end    = TEGRA_SDMMC1_BASE + TEGRA_SDMMC1_SIZE-1,
+               .flags  = IORESOURCE_MEM,
+       },
+};
+
+static struct resource sdhci_resource2[] = {
+       [0] = {
+               .start  = INT_SDMMC3,
+               .end    = INT_SDMMC3,
+               .flags  = IORESOURCE_IRQ,
+       },
+       [1] = {
+               .start  = TEGRA_SDMMC3_BASE,
+               .end    = TEGRA_SDMMC3_BASE + TEGRA_SDMMC3_SIZE-1,
+               .flags  = IORESOURCE_MEM,
+       },
+};
+
+static struct resource sdhci_resource3[] = {
+       [0] = {
+               .start  = INT_SDMMC4,
+               .end    = INT_SDMMC4,
+               .flags  = IORESOURCE_IRQ,
+       },
+       [1] = {
+               .start  = TEGRA_SDMMC4_BASE,
+               .end    = TEGRA_SDMMC4_BASE + TEGRA_SDMMC4_SIZE-1,
+               .flags  = IORESOURCE_MEM,
+       },
+};
+
+#ifdef CONFIG_MMC_EMBEDDED_SDIO
+static struct embedded_sdio_data embedded_sdio_data0 = {
+       .cccr   = {
+               .sdio_vsn       = 2,
+               .multi_block    = 1,
+               .low_speed      = 0,
+               .wide_bus       = 0,
+               .high_power     = 1,
+               .high_speed     = 1,
+       },
+       .cis  = {
+               .vendor  = 0x02d0,
+               .device  = 0x4329,
+       },
+};
+#endif
+
+static struct tegra_sdhci_platform_data tegra_sdhci_platform_data0 = {
+       .mmc_data = {
+               .register_status_notify = ardbeg_wifi_status_register,
+#ifdef CONFIG_MMC_EMBEDDED_SDIO
+               .embedded_sdio = &embedded_sdio_data0,
+#endif
+               .built_in = 0,
+               .ocr_mask = MMC_OCR_1V8_MASK,
+       },
+#ifndef CONFIG_MMC_EMBEDDED_SDIO
+       .pm_flags = MMC_PM_KEEP_POWER,
+#endif
+       .cd_gpio = -1,
+       .wp_gpio = -1,
+       .power_gpio = -1,
+       .tap_delay = 0x3,
+       .trim_delay = 0xA,
+       .ddr_clk_limit = 41000000,
+       /* FIXME remove uhs_mask for T148 silicon */
+       .uhs_mask = MMC_UHS_MASK_SDR104 |
+               MMC_UHS_MASK_DDR50,
+};
+
+static struct tegra_sdhci_platform_data tegra_sdhci_platform_data2 = {
+       .cd_gpio = -1,
+       .wp_gpio = -1,
+       .power_gpio = -1,
+/*     .max_clk = 12000000, */
+};
+
+static struct tegra_sdhci_platform_data tegra_sdhci_platform_data3 = {
+       .cd_gpio = -1,
+       .wp_gpio = -1,
+       .power_gpio = -1,
+       .is_8bit = 1,
+       .mmc_data = {
+               .built_in = 1,
+               .ocr_mask = MMC_OCR_1V8_MASK,
+       }
+/*     .max_clk = 12000000, */
+};
+
+static struct platform_device tegra_sdhci_device0 = {
+       .name           = "sdhci-tegra",
+       .id             = 0,
+       .resource       = sdhci_resource0,
+       .num_resources  = ARRAY_SIZE(sdhci_resource0),
+       .dev = {
+               .platform_data = &tegra_sdhci_platform_data0,
+       },
+};
+
+static struct platform_device tegra_sdhci_device2 = {
+       .name           = "sdhci-tegra",
+       .id             = 2,
+       .resource       = sdhci_resource2,
+       .num_resources  = ARRAY_SIZE(sdhci_resource2),
+       .dev = {
+               .platform_data = &tegra_sdhci_platform_data2,
+       },
+};
+
+static struct platform_device tegra_sdhci_device3 = {
+       .name           = "sdhci-tegra",
+       .id             = 3,
+       .resource       = sdhci_resource3,
+       .num_resources  = ARRAY_SIZE(sdhci_resource3),
+       .dev = {
+               .platform_data = &tegra_sdhci_platform_data3,
+       },
+};
+
+static int ardbeg_wifi_status_register(
+               void (*callback)(int card_present, void *dev_id),
+               void *dev_id)
+{
+       if (wifi_status_cb)
+               return -EAGAIN;
+       wifi_status_cb = callback;
+       wifi_status_cb_devid = dev_id;
+       return 0;
+}
+
+static int ardbeg_wifi_set_carddetect(int val)
+{
+       pr_debug("%s: %d\n", __func__, val);
+       if (wifi_status_cb)
+               wifi_status_cb(val, wifi_status_cb_devid);
+       else
+               pr_warn("%s: Nobody to notify\n", __func__);
+       return 0;
+}
+
+static int ardbeg_wifi_power(int on)
+{
+       pr_err("%s: %d\n", __func__, on);
+
+       gpio_set_value(ARDBEG_WLAN_PWR, on);
+       mdelay(100);
+
+       return 0;
+}
+
+static int ardbeg_wifi_reset(int on)
+{
+       pr_debug("%s: do nothing\n", __func__);
+       return 0;
+}
+
+static int __init ardbeg_wifi_init(void)
+{
+       int rc;
+
+       rc = gpio_request(ARDBEG_WLAN_PWR, "wlan_power");
+       if (rc)
+               pr_err("WLAN_PWR gpio request failed:%d\n", rc);
+       rc = gpio_request(ARDBEG_WLAN_WOW, "bcmsdh_sdmmc");
+       if (rc)
+               pr_err("WLAN_WOW gpio request failed:%d\n", rc);
+
+       rc = gpio_direction_output(ARDBEG_WLAN_PWR, 0);
+       if (rc)
+               pr_err("WLAN_PWR gpio direction configuration failed:%d\n", rc);
+       rc = gpio_direction_input(ARDBEG_WLAN_WOW);
+       if (rc)
+               pr_err("WLAN_WOW gpio direction configuration failed:%d\n", rc);
+
+       wifi_resource[0].start = wifi_resource[0].end =
+               gpio_to_irq(ARDBEG_WLAN_WOW);
+
+       platform_device_register(&ardbeg_wifi_device);
+       return 0;
+}
+
+#ifdef CONFIG_TEGRA_PREPOWER_WIFI
+static int __init ardbeg_wifi_prepower(void)
+{
+       if (!of_machine_is_compatible("nvidia,ardbeg"))
+               return 0;
+       ardbeg_wifi_power(1);
+
+       return 0;
+}
+
+subsys_initcall_sync(ardbeg_wifi_prepower);
+#endif
+
+int __init ardbeg_sdhci_init(void)
+{
+       platform_device_register(&tegra_sdhci_device3);
+       platform_device_register(&tegra_sdhci_device2);
+
+       /* Disable SDMMC1 and WiFi
+        * platform_device_register(&tegra_sdhci_device0);
+        * ardbeg_wifi_init();
+        */
+       return 0;
+}
index 73b10db..714b255 100644 (file)
@@ -102,6 +102,7 @@ static void __init tegra_ardbeg_init(void)
        ardbeg_pinmux_init();
        tegra_soc_device_init("ardbeg");
        ardbeg_kbc_init();
+       ardbeg_sdhci_init();
        ardbeg_panel_init();
        platform_add_devices(ardbeg_devices, ARRAY_SIZE(ardbeg_devices));
 }
index a1969c6..d51ed9f 100644 (file)
@@ -26,5 +26,6 @@
 int ardbeg_pinmux_init(void);
 int ardbeg_panel_init(void);
 int ardbeg_kbc_init(void);
+int ardbeg_sdhci_init(void);
 
 #endif