Merge commit 'v2.6.37-rc2' into sched/core
[pandora-kernel.git] / arch / arm / mach-omap2 / board-igep0020.c
index b62a68b..5e035a5 100644 (file)
@@ -20,6 +20,7 @@
 
 #include <linux/regulator/machine.h>
 #include <linux/i2c/twl.h>
+#include <linux/mmc/host.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #define IGEP2_SMSC911X_CS       5
 #define IGEP2_SMSC911X_GPIO     176
 #define IGEP2_GPIO_USBH_NRESET  24
-#define IGEP2_GPIO_LED0_GREEN  26
-#define IGEP2_GPIO_LED0_RED    27
-#define IGEP2_GPIO_LED1_RED    28
-#define IGEP2_GPIO_DVI_PUP     170
-#define IGEP2_GPIO_WIFI_NPD    94
-#define IGEP2_GPIO_WIFI_NRESET         95
+#define IGEP2_GPIO_LED0_GREEN   26
+#define IGEP2_GPIO_LED0_RED     27
+#define IGEP2_GPIO_LED1_RED     28
+#define IGEP2_GPIO_DVI_PUP      170
+
+#define IGEP2_RB_GPIO_WIFI_NPD     94
+#define IGEP2_RB_GPIO_WIFI_NRESET  95
+#define IGEP2_RB_GPIO_BT_NRESET    137
+#define IGEP2_RC_GPIO_WIFI_NPD     138
+#define IGEP2_RC_GPIO_WIFI_NRESET  139
+#define IGEP2_RC_GPIO_BT_NRESET    137
+
+/*
+ * IGEP2 Hardware Revision Table
+ *
+ *  --------------------------------------------------------------------------
+ * | Id. | Hw Rev.            | HW0 (28) | WIFI_NPD | WIFI_NRESET | BT_NRESET |
+ *  --------------------------------------------------------------------------
+ * |  0  | B                  |   high   |  gpio94  |   gpio95    |     -     |
+ * |  0  | B/C (B-compatible) |   high   |  gpio94  |   gpio95    |  gpio137  |
+ * |  1  | C                  |   low    |  gpio138 |   gpio139   |  gpio137  |
+ *  --------------------------------------------------------------------------
+ */
+
+#define IGEP2_BOARD_HWREV_B    0
+#define IGEP2_BOARD_HWREV_C    1
+
+static u8 hwrev;
+
+static void __init igep2_get_revision(void)
+{
+       u8 ret;
+
+       omap_mux_init_gpio(IGEP2_GPIO_LED1_RED, OMAP_PIN_INPUT);
+
+       if ((gpio_request(IGEP2_GPIO_LED1_RED, "GPIO_HW0_REV") == 0) &&
+           (gpio_direction_input(IGEP2_GPIO_LED1_RED) == 0)) {
+               ret = gpio_get_value(IGEP2_GPIO_LED1_RED);
+               if (ret == 0) {
+                       pr_info("IGEP2: Hardware Revision C (B-NON compatible)\n");
+                       hwrev = IGEP2_BOARD_HWREV_C;
+               } else if (ret ==  1) {
+                       pr_info("IGEP2: Hardware Revision B/C (B compatible)\n");
+                       hwrev = IGEP2_BOARD_HWREV_B;
+               } else {
+                       pr_err("IGEP2: Unknown Hardware Revision\n");
+                       hwrev = -1;
+               }
+       } else {
+               pr_warning("IGEP2: Could not obtain gpio GPIO_HW0_REV\n");
+               pr_err("IGEP2: Unknown Hardware Revision\n");
+       }
+
+       gpio_free(IGEP2_GPIO_LED1_RED);
+}
 
 #if defined(CONFIG_MTD_ONENAND_OMAP2) || \
        defined(CONFIG_MTD_ONENAND_OMAP2_MODULE)
@@ -107,7 +157,7 @@ static struct platform_device igep2_onenand_device = {
        },
 };
 
-void __init igep2_flash_init(void)
+static void __init igep2_flash_init(void)
 {
        u8              cs = 0;
        u8              onenandcs = GPMC_CS_NUM + 1;
@@ -141,7 +191,7 @@ void __init igep2_flash_init(void)
 }
 
 #else
-void __init igep2_flash_init(void) {}
+static void __init igep2_flash_init(void) {}
 #endif
 
 #if defined(CONFIG_SMSC911X) || defined(CONFIG_SMSC911X_MODULE)
@@ -211,10 +261,6 @@ static struct regulator_consumer_supply igep2_vmmc1_supply = {
        .supply         = "vmmc",
 };
 
-static struct regulator_consumer_supply igep2_vmmc2_supply = {
-       .supply         = "vmmc",
-};
-
 /* VMMC1 for OMAP VDD_MMC1 (i/o) and MMC1 card */
 static struct regulator_init_data igep2_vmmc1 = {
        .constraints = {
@@ -230,37 +276,95 @@ static struct regulator_init_data igep2_vmmc1 = {
        .consumer_supplies      = &igep2_vmmc1_supply,
 };
 
-/* VMMC2 for OMAP VDD_MMC2 (i/o) and MMC2 WIFI */
-static struct regulator_init_data igep2_vmmc2 = {
-       .constraints = {
-               .min_uV                 = 1850000,
-               .max_uV                 = 3150000,
-               .valid_modes_mask       = REGULATOR_MODE_NORMAL
-                                       | REGULATOR_MODE_STANDBY,
-               .valid_ops_mask         = REGULATOR_CHANGE_VOLTAGE
-                                       | REGULATOR_CHANGE_MODE
-                                       | REGULATOR_CHANGE_STATUS,
-       },
-       .num_consumer_supplies  = 1,
-       .consumer_supplies      = &igep2_vmmc2_supply,
-};
-
 static struct omap2_hsmmc_info mmc[] = {
        {
                .mmc            = 1,
-               .wires          = 4,
+               .caps           = MMC_CAP_4_BIT_DATA,
                .gpio_cd        = -EINVAL,
                .gpio_wp        = -EINVAL,
        },
+#if defined(CONFIG_LIBERTAS_SDIO) || defined(CONFIG_LIBERTAS_SDIO_MODULE)
        {
                .mmc            = 2,
-               .wires          = 4,
+               .caps           = MMC_CAP_4_BIT_DATA,
                .gpio_cd        = -EINVAL,
                .gpio_wp        = -EINVAL,
        },
+#endif
        {}      /* Terminator */
 };
 
+#if defined(CONFIG_LEDS_GPIO) || defined(CONFIG_LEDS_GPIO_MODULE)
+#include <linux/leds.h>
+
+static struct gpio_led igep2_gpio_leds[] = {
+       [0] = {
+               .name                   = "gpio-led:red:d0",
+               .gpio                   = IGEP2_GPIO_LED0_RED,
+               .default_trigger        = "default-off"
+       },
+       [1] = {
+               .name                   = "gpio-led:green:d0",
+               .gpio                   = IGEP2_GPIO_LED0_GREEN,
+               .default_trigger        = "default-off",
+       },
+       [2] = {
+               .name                   = "gpio-led:red:d1",
+               .gpio                   = IGEP2_GPIO_LED1_RED,
+               .default_trigger        = "default-off",
+       },
+       [3] = {
+               .name                   = "gpio-led:green:d1",
+               .default_trigger        = "heartbeat",
+               .gpio                   = -EINVAL, /* gets replaced */
+       },
+};
+
+static struct gpio_led_platform_data igep2_led_pdata = {
+       .leds           = igep2_gpio_leds,
+       .num_leds       = ARRAY_SIZE(igep2_gpio_leds),
+};
+
+static struct platform_device igep2_led_device = {
+        .name   = "leds-gpio",
+        .id     = -1,
+        .dev    = {
+                .platform_data  =  &igep2_led_pdata,
+       },
+};
+
+static void __init igep2_leds_init(void)
+{
+       platform_device_register(&igep2_led_device);
+}
+
+#else
+static inline void igep2_leds_init(void)
+{
+       if ((gpio_request(IGEP2_GPIO_LED0_RED, "gpio-led:red:d0") == 0) &&
+           (gpio_direction_output(IGEP2_GPIO_LED0_RED, 1) == 0)) {
+               gpio_export(IGEP2_GPIO_LED0_RED, 0);
+               gpio_set_value(IGEP2_GPIO_LED0_RED, 0);
+       } else
+               pr_warning("IGEP v2: Could not obtain gpio GPIO_LED0_RED\n");
+
+       if ((gpio_request(IGEP2_GPIO_LED0_GREEN, "gpio-led:green:d0") == 0) &&
+           (gpio_direction_output(IGEP2_GPIO_LED0_GREEN, 1) == 0)) {
+               gpio_export(IGEP2_GPIO_LED0_GREEN, 0);
+               gpio_set_value(IGEP2_GPIO_LED0_GREEN, 0);
+       } else
+               pr_warning("IGEP v2: Could not obtain gpio GPIO_LED0_GREEN\n");
+
+       if ((gpio_request(IGEP2_GPIO_LED1_RED, "gpio-led:red:d1") == 0) &&
+           (gpio_direction_output(IGEP2_GPIO_LED1_RED, 1) == 0)) {
+               gpio_export(IGEP2_GPIO_LED1_RED, 0);
+               gpio_set_value(IGEP2_GPIO_LED1_RED, 0);
+       } else
+               pr_warning("IGEP v2: Could not obtain gpio GPIO_LED1_RED\n");
+
+}
+#endif
+
 static int igep2_twl_gpio_setup(struct device *dev,
                unsigned gpio, unsigned ngpio)
 {
@@ -268,20 +372,48 @@ static int igep2_twl_gpio_setup(struct device *dev,
        mmc[0].gpio_cd = gpio + 0;
        omap2_hsmmc_init(mmc);
 
-       /* link regulators to MMC adapters ... we "know" the
+       /*
+        * link regulators to MMC adapters ... we "know" the
         * regulators will be set up only *after* we return.
-       */
+        */
        igep2_vmmc1_supply.dev = mmc[0].dev;
-       igep2_vmmc2_supply.dev = mmc[1].dev;
+
+       /*
+        * REVISIT: need ehci-omap hooks for external VBUS
+        * power switch and overcurrent detect
+        */
+       if ((gpio_request(gpio + 1, "GPIO_EHCI_NOC") < 0) ||
+           (gpio_direction_input(gpio + 1) < 0))
+               pr_err("IGEP2: Could not obtain gpio for EHCI NOC");
+
+       /*
+        * TWL4030_GPIO_MAX + 0 == ledA, GPIO_USBH_CPEN
+        * (out, active low)
+        */
+       if ((gpio_request(gpio + TWL4030_GPIO_MAX, "GPIO_USBH_CPEN") < 0) ||
+           (gpio_direction_output(gpio + TWL4030_GPIO_MAX, 0) < 0))
+               pr_err("IGEP2: Could not obtain gpio for USBH_CPEN");
+
+       /* TWL4030_GPIO_MAX + 1 == ledB (out, active low LED) */
+#if !defined(CONFIG_LEDS_GPIO) && !defined(CONFIG_LEDS_GPIO_MODULE)
+       if ((gpio_request(gpio+TWL4030_GPIO_MAX+1, "gpio-led:green:d1") == 0)
+           && (gpio_direction_output(gpio + TWL4030_GPIO_MAX + 1, 1) == 0)) {
+               gpio_export(gpio + TWL4030_GPIO_MAX + 1, 0);
+               gpio_set_value(gpio + TWL4030_GPIO_MAX + 1, 0);
+       } else
+               pr_warning("IGEP v2: Could not obtain gpio GPIO_LED1_GREEN\n");
+#else
+       igep2_gpio_leds[3].gpio = gpio + TWL4030_GPIO_MAX + 1;
+#endif
 
        return 0;
 };
 
-static struct twl4030_gpio_platform_data igep2_gpio_data = {
+static struct twl4030_gpio_platform_data igep2_twl4030_gpio_pdata = {
        .gpio_base      = OMAP_MAX_GPIO_LINES,
        .irq_base       = TWL4030_GPIO_IRQ_BASE,
        .irq_end        = TWL4030_GPIO_IRQ_END,
-       .use_leds       = false,
+       .use_leds       = true,
        .setup          = igep2_twl_gpio_setup,
 };
 
@@ -355,47 +487,6 @@ static void __init igep2_display_init(void)
                pr_err("IGEP v2: Could not obtain gpio GPIO_DVI_PUP\n");
 }
 
-#if defined(CONFIG_LEDS_GPIO) || defined(CONFIG_LEDS_GPIO_MODULE)
-#include <linux/leds.h>
-
-static struct gpio_led igep2_gpio_leds[] = {
-       {
-               .name = "led0:red",
-               .gpio = IGEP2_GPIO_LED0_RED,
-       },
-       {
-               .name = "led0:green",
-               .default_trigger = "heartbeat",
-               .gpio = IGEP2_GPIO_LED0_GREEN,
-       },
-       {
-               .name = "led1:red",
-               .gpio = IGEP2_GPIO_LED1_RED,
-       },
-};
-
-static struct gpio_led_platform_data igep2_led_pdata = {
-       .leds           = igep2_gpio_leds,
-       .num_leds       = ARRAY_SIZE(igep2_gpio_leds),
-};
-
-static struct platform_device igep2_led_device = {
-        .name   = "leds-gpio",
-        .id     = -1,
-        .dev    = {
-                .platform_data  =  &igep2_led_pdata,
-       },
-};
-
-static void __init igep2_init_led(void)
-{
-       platform_device_register(&igep2_led_device);
-}
-
-#else
-static inline void igep2_init_led(void) {}
-#endif
-
 static struct platform_device *igep2_devices[] __initdata = {
        &igep2_dss_device,
 };
@@ -425,14 +516,13 @@ static struct twl4030_platform_data igep2_twldata = {
        /* platform_data for children goes here */
        .usb            = &igep2_usb_data,
        .codec          = &igep2_codec_data,
-       .gpio           = &igep2_gpio_data,
+       .gpio           = &igep2_twl4030_gpio_pdata,
        .vmmc1          = &igep2_vmmc1,
-       .vmmc2          = &igep2_vmmc2,
        .vpll2          = &igep2_vpll2,
 
 };
 
-static struct i2c_board_info __initdata igep2_i2c_boardinfo[] = {
+static struct i2c_board_info __initdata igep2_i2c1_boardinfo[] = {
        {
                I2C_BOARD_INFO("twl4030", 0x48),
                .flags          = I2C_CLIENT_WAKE,
@@ -441,14 +531,29 @@ static struct i2c_board_info __initdata igep2_i2c_boardinfo[] = {
        },
 };
 
-static int __init igep2_i2c_init(void)
+static struct i2c_board_info __initdata igep2_i2c3_boardinfo[] = {
+       {
+               I2C_BOARD_INFO("eeprom", 0x50),
+       },
+};
+
+static void __init igep2_i2c_init(void)
 {
-       omap_register_i2c_bus(1, 2600, igep2_i2c_boardinfo,
-                       ARRAY_SIZE(igep2_i2c_boardinfo));
-       /* Bus 3 is attached to the DVI port where devices like the pico DLP
-        * projector don't work reliably with 400kHz */
-       omap_register_i2c_bus(3, 100, NULL, 0);
-       return 0;
+       int ret;
+
+       ret = omap_register_i2c_bus(1, 2600, igep2_i2c1_boardinfo,
+               ARRAY_SIZE(igep2_i2c1_boardinfo));
+       if (ret)
+               pr_warning("IGEP2: Could not register I2C1 bus (%d)\n", ret);
+
+       /*
+        * Bus 3 is attached to the DVI port where devices like the pico DLP
+        * projector don't work reliably with 400kHz
+        */
+       ret = omap_register_i2c_bus(3, 100, igep2_i2c3_boardinfo,
+               ARRAY_SIZE(igep2_i2c3_boardinfo));
+       if (ret)
+               pr_warning("IGEP2: Could not register I2C3 bus (%d)\n", ret);
 }
 
 static struct omap_musb_board_data musb_board_data = {
@@ -476,9 +581,57 @@ static struct omap_board_mux board_mux[] __initdata = {
 #define board_mux      NULL
 #endif
 
+#if defined(CONFIG_LIBERTAS_SDIO) || defined(CONFIG_LIBERTAS_SDIO_MODULE)
+
+static void __init igep2_wlan_bt_init(void)
+{
+       unsigned npd, wreset, btreset;
+
+       /* GPIO's for WLAN-BT combo depends on hardware revision */
+       if (hwrev == IGEP2_BOARD_HWREV_B) {
+               npd = IGEP2_RB_GPIO_WIFI_NPD;
+               wreset = IGEP2_RB_GPIO_WIFI_NRESET;
+               btreset = IGEP2_RB_GPIO_BT_NRESET;
+       } else if (hwrev == IGEP2_BOARD_HWREV_C) {
+               npd = IGEP2_RC_GPIO_WIFI_NPD;
+               wreset = IGEP2_RC_GPIO_WIFI_NRESET;
+               btreset = IGEP2_RC_GPIO_BT_NRESET;
+       } else
+               return;
+
+       /* Set GPIO's for  WLAN-BT combo module */
+       if ((gpio_request(npd, "GPIO_WIFI_NPD") == 0) &&
+           (gpio_direction_output(npd, 1) == 0)) {
+               gpio_export(npd, 0);
+       } else
+               pr_warning("IGEP2: Could not obtain gpio GPIO_WIFI_NPD\n");
+
+       if ((gpio_request(wreset, "GPIO_WIFI_NRESET") == 0) &&
+           (gpio_direction_output(wreset, 1) == 0)) {
+               gpio_export(wreset, 0);
+               gpio_set_value(wreset, 0);
+               udelay(10);
+               gpio_set_value(wreset, 1);
+       } else
+               pr_warning("IGEP2: Could not obtain gpio GPIO_WIFI_NRESET\n");
+
+       if ((gpio_request(btreset, "GPIO_BT_NRESET") == 0) &&
+           (gpio_direction_output(btreset, 1) == 0)) {
+               gpio_export(btreset, 0);
+       } else
+               pr_warning("IGEP2: Could not obtain gpio GPIO_BT_NRESET\n");
+}
+#else
+static inline void __init igep2_wlan_bt_init(void) { }
+#endif
+
 static void __init igep2_init(void)
 {
        omap3_mux_init(board_mux, OMAP_PACKAGE_CBB);
+
+       /* Get IGEP2 hardware revision */
+       igep2_get_revision();
+       /* Register I2C busses and drivers */
        igep2_i2c_init();
        platform_add_devices(igep2_devices, ARRAY_SIZE(igep2_devices));
        omap_serial_init();
@@ -486,50 +639,16 @@ static void __init igep2_init(void)
        usb_ehci_init(&ehci_pdata);
 
        igep2_flash_init();
-       igep2_init_led();
+       igep2_leds_init();
        igep2_display_init();
        igep2_init_smsc911x();
 
-       /* GPIO userspace leds */
-#if !defined(CONFIG_LEDS_GPIO) && !defined(CONFIG_LEDS_GPIO_MODULE)
-       if ((gpio_request(IGEP2_GPIO_LED0_RED, "led0:red") == 0) &&
-           (gpio_direction_output(IGEP2_GPIO_LED0_RED, 1) == 0)) {
-               gpio_export(IGEP2_GPIO_LED0_RED, 0);
-               gpio_set_value(IGEP2_GPIO_LED0_RED, 0);
-       } else
-               pr_warning("IGEP v2: Could not obtain gpio GPIO_LED0_RED\n");
-
-       if ((gpio_request(IGEP2_GPIO_LED0_GREEN, "led0:green") == 0) &&
-           (gpio_direction_output(IGEP2_GPIO_LED0_GREEN, 1) == 0)) {
-               gpio_export(IGEP2_GPIO_LED0_GREEN, 0);
-               gpio_set_value(IGEP2_GPIO_LED0_GREEN, 0);
-       } else
-               pr_warning("IGEP v2: Could not obtain gpio GPIO_LED0_GREEN\n");
-
-       if ((gpio_request(IGEP2_GPIO_LED1_RED, "led1:red") == 0) &&
-           (gpio_direction_output(IGEP2_GPIO_LED1_RED, 1) == 0)) {
-               gpio_export(IGEP2_GPIO_LED1_RED, 0);
-               gpio_set_value(IGEP2_GPIO_LED1_RED, 0);
-       } else
-               pr_warning("IGEP v2: Could not obtain gpio GPIO_LED1_RED\n");
-#endif
-
-       /* GPIO W-LAN + Bluetooth combo module */
-       if ((gpio_request(IGEP2_GPIO_WIFI_NPD, "GPIO_WIFI_NPD") == 0) &&
-           (gpio_direction_output(IGEP2_GPIO_WIFI_NPD, 1) == 0)) {
-               gpio_export(IGEP2_GPIO_WIFI_NPD, 0);
-/*             gpio_set_value(IGEP2_GPIO_WIFI_NPD, 0); */
-       } else
-               pr_warning("IGEP v2: Could not obtain gpio GPIO_WIFI_NPD\n");
+       /*
+        * WLAN-BT combo module from MuRata wich has a Marvell WLAN
+        * (88W8686) + CSR Bluetooth chipset. Uses SDIO interface.
+        */
+       igep2_wlan_bt_init();
 
-       if ((gpio_request(IGEP2_GPIO_WIFI_NRESET, "GPIO_WIFI_NRESET") == 0) &&
-           (gpio_direction_output(IGEP2_GPIO_WIFI_NRESET, 1) == 0)) {
-               gpio_export(IGEP2_GPIO_WIFI_NRESET, 0);
-               gpio_set_value(IGEP2_GPIO_WIFI_NRESET, 0);
-               udelay(10);
-               gpio_set_value(IGEP2_GPIO_WIFI_NRESET, 1);
-       } else
-               pr_warning("IGEP v2: Could not obtain gpio GPIO_WIFI_NRESET\n");
 }
 
 MACHINE_START(IGEP0020, "IGEP v2 board")