ARM: tegra: power: Set cpu_pwr_off timer to 200us for PMIC
[linux-2.6.git] / arch / arm / mach-tegra / board-cardhu-power.c
index bcd3a17..e982514 100644 (file)
 #include <linux/gpio.h>
 #include <mach/suspend.h>
 #include <linux/io.h>
-#include <linux/gpio-switch-regulator.h>
+#include <linux/regulator/gpio-switch-regulator.h>
+#include <linux/regulator/tps6591x-regulator.h>
 
 #include <mach/iomap.h>
 #include <mach/irqs.h>
+#include <mach/pinmux.h>
 
 #include "gpio-names.h"
+#include "board.h"
 #include "board-cardhu.h"
 #include "power.h"
 #include "wakeups-t3.h"
 
-#ifdef CONFIG_MFD_TPS6591X
+#define PMC_CTRL               0x0
+#define PMC_CTRL_INTR_LOW      (1 << 17)
+
 static struct regulator_consumer_supply tps6591x_vdd1_supply[] = {
        REGULATOR_SUPPLY("vdd_core", NULL),
        REGULATOR_SUPPLY("en_vddio_ddr_1v2", NULL),
@@ -98,17 +103,27 @@ static struct regulator_consumer_supply tps6591x_ldo2_supply[] = {
        REGULATOR_SUPPLY("avdd_plle", NULL),
 };
 
-static struct regulator_consumer_supply tps6591x_ldo3_supply[] = {
+static struct regulator_consumer_supply tps6591x_ldo3_supply_e118x[] = {
        REGULATOR_SUPPLY("vddio_sdmmc1", NULL),
 };
 
+static struct regulator_consumer_supply tps6591x_ldo3_supply_e1198[] = {
+       REGULATOR_SUPPLY("unused_rail_ldo3", NULL),
+};
+
 static struct regulator_consumer_supply tps6591x_ldo4_supply[] = {
        REGULATOR_SUPPLY("vdd_rtc", NULL),
 };
 
-static struct regulator_consumer_supply tps6591x_ldo5_supply[] = {
+static struct regulator_consumer_supply tps6591x_ldo5_supply_e118x[] = {
+       REGULATOR_SUPPLY("avdd_vdac", NULL),
+};
+
+static struct regulator_consumer_supply tps6591x_ldo5_supply_e1198[] = {
        REGULATOR_SUPPLY("avdd_vdac", NULL),
+       REGULATOR_SUPPLY("vddio_sdmmc1", NULL),
 };
+
 static struct regulator_consumer_supply tps6591x_ldo6_supply[] = {
        REGULATOR_SUPPLY("avdd_dsi_csi", NULL),
 };
@@ -124,91 +139,172 @@ static struct regulator_consumer_supply tps6591x_ldo8_supply[] = {
        REGULATOR_SUPPLY("vdd_ddr_hs", NULL),
 };
 
-#define REGULATOR_INIT(_id, _minmv, _maxmv)                            \
+#define TPS_PDATA_INIT_SUPPLY(_id, _minmv, _maxmv, _supply_reg, _always_on, \
+       _boot_on, _apply_uv, _init_uV, _init_enable, _init_apply, _ectrl) \
+       static struct tps6591x_regulator_platform_data pdata_##_id =    \
        {                                                               \
-               .constraints = {                                        \
-                       .min_uV = (_minmv)*1000,                        \
-                       .max_uV = (_maxmv)*1000,                        \
-                       .valid_modes_mask = (REGULATOR_MODE_NORMAL |    \
-                                            REGULATOR_MODE_STANDBY),   \
-                       .valid_ops_mask = (REGULATOR_CHANGE_MODE |      \
-                                          REGULATOR_CHANGE_STATUS |    \
-                                          REGULATOR_CHANGE_VOLTAGE),   \
+               .regulator = {                                          \
+                       .constraints = {                                \
+                               .min_uV = (_minmv)*1000,                \
+                               .max_uV = (_maxmv)*1000,                \
+                               .valid_modes_mask = (REGULATOR_MODE_NORMAL |  \
+                                                    REGULATOR_MODE_STANDBY), \
+                               .valid_ops_mask = (REGULATOR_CHANGE_MODE |    \
+                                                  REGULATOR_CHANGE_STATUS |  \
+                                                  REGULATOR_CHANGE_VOLTAGE), \
+                               .always_on = _always_on,                \
+                               .boot_on = _boot_on,                    \
+                               .apply_uV = _apply_uv,                  \
+                       },                                              \
+                       .num_consumer_supplies =                        \
+                               ARRAY_SIZE(tps6591x_##_id##_supply),    \
+                       .consumer_supplies = tps6591x_##_id##_supply,   \
+                       .supply_regulator = tps6591x_rails(_supply_reg), \
                },                                                      \
-               .num_consumer_supplies = ARRAY_SIZE(tps6591x_##_id##_supply),\
-               .consumer_supplies = tps6591x_##_id##_supply,           \
+               .init_uV =  _init_uV * 1000,                            \
+               .init_enable = _init_enable,                            \
+               .init_apply = _init_apply,                              \
+               .ectrl = _ectrl                                         \
        }
 
-#define REGULATOR_INIT_SUPPLY(_id, _minmv, _maxmv, _supply_reg)                \
+#define TPS_PDATA_INIT(_id, _minmv, _maxmv, _supply_reg, _always_on,   \
+       _boot_on, _apply_uv, _init_uV, _init_enable, _init_apply, _ectrl) \
+       static struct tps6591x_regulator_platform_data pdata_##_id =    \
        {                                                               \
-               .constraints = {                                        \
-                       .min_uV = (_minmv)*1000,                        \
-                       .max_uV = (_maxmv)*1000,                        \
-                       .valid_modes_mask = (REGULATOR_MODE_NORMAL |    \
-                                            REGULATOR_MODE_STANDBY),   \
-                       .valid_ops_mask = (REGULATOR_CHANGE_MODE |      \
-                                          REGULATOR_CHANGE_STATUS |    \
-                                          REGULATOR_CHANGE_VOLTAGE),   \
+               .regulator = {                                          \
+                       .constraints = {                                \
+                               .min_uV = (_minmv)*1000,                \
+                               .max_uV = (_maxmv)*1000,                \
+                               .valid_modes_mask = (REGULATOR_MODE_NORMAL |  \
+                                                    REGULATOR_MODE_STANDBY), \
+                               .valid_ops_mask = (REGULATOR_CHANGE_MODE |    \
+                                                  REGULATOR_CHANGE_STATUS |  \
+                                                  REGULATOR_CHANGE_VOLTAGE), \
+                               .always_on = _always_on,                \
+                               .boot_on = _boot_on,                    \
+                               .apply_uV = _apply_uv,                  \
+                       },                                              \
+                       .num_consumer_supplies =                        \
+                               ARRAY_SIZE(tps6591x_##_id##_supply),    \
+                       .consumer_supplies = tps6591x_##_id##_supply,   \
                },                                                      \
-               .num_consumer_supplies = ARRAY_SIZE(tps6591x_##_id##_supply),\
-               .consumer_supplies = tps6591x_##_id##_supply,           \
-               .supply_regulator = tps6591x_rails(_supply_reg),        \
+               .init_uV =  _init_uV * 1000,                            \
+               .init_enable = _init_enable,                            \
+               .init_apply = _init_apply,                              \
+               .ectrl = _ectrl                                         \
        }
 
-static struct regulator_init_data vdd1_data = REGULATOR_INIT(vdd1, 600, 1500);
-static struct regulator_init_data vdd2_data = REGULATOR_INIT(vdd2, 600, 1500);
-static struct regulator_init_data vddctrl_data = REGULATOR_INIT(vddctrl, 600,
-                                               1400);
-static struct regulator_init_data vio_data = REGULATOR_INIT(vio, 1500, 3300);
-static struct regulator_init_data ldo1_data = REGULATOR_INIT_SUPPLY(ldo1,
-                                               1000, 3300, VDD_2);
-static struct regulator_init_data ldo2_data = REGULATOR_INIT_SUPPLY(ldo2,
-                                               1000, 3300, VDD_2);
-static struct regulator_init_data ldo3_data = REGULATOR_INIT(ldo3, 1000, 3300);
-static struct regulator_init_data ldo4_data = REGULATOR_INIT(ldo4, 1000, 3300);
-static struct regulator_init_data ldo5_data = REGULATOR_INIT(ldo5, 1000, 3300);
-static struct regulator_init_data ldo6_data = REGULATOR_INIT_SUPPLY(ldo6,
-                                               1000, 3300, VIO);
-static struct regulator_init_data ldo7_data = REGULATOR_INIT_SUPPLY(ldo7,
-                                               1000, 3300, VIO);
-static struct regulator_init_data ldo8_data = REGULATOR_INIT_SUPPLY(ldo8,
-                                               1000, 3300, VIO);
+#define TPS_PDATA_INIT_BOARD(_id, _board, _minmv, _maxmv, _supply_reg, _always_on,     \
+       _boot_on, _apply_uv, _init_uV, _init_enable, _init_apply, _ectrl) \
+       static struct tps6591x_regulator_platform_data pdata_##_id##_##_board = \
+       {                                                               \
+               .regulator = {                                          \
+                       .constraints = {                                \
+                               .min_uV = (_minmv)*1000,                \
+                               .max_uV = (_maxmv)*1000,                \
+                               .valid_modes_mask = (REGULATOR_MODE_NORMAL |  \
+                                                    REGULATOR_MODE_STANDBY), \
+                               .valid_ops_mask = (REGULATOR_CHANGE_MODE |    \
+                                                  REGULATOR_CHANGE_STATUS |  \
+                                                  REGULATOR_CHANGE_VOLTAGE), \
+                               .always_on = _always_on,                \
+                               .boot_on = _boot_on,                    \
+                               .apply_uV = _apply_uv,                  \
+                       },                                              \
+                       .num_consumer_supplies =                        \
+                               ARRAY_SIZE(tps6591x_##_id##_supply##_##_board),  \
+                       .consumer_supplies = tps6591x_##_id##_supply##_##_board, \
+               },                                                      \
+               .init_uV =  _init_uV * 1000,                            \
+               .init_enable = _init_enable,                            \
+               .init_apply = _init_apply,                              \
+               .ectrl = _ectrl                                         \
+       }
 
+TPS_PDATA_INIT(vdd1,    600, 1500, 0, 1, 1, 0, -1, 0, 0, 0);
+TPS_PDATA_INIT(vdd2,    600, 1500, 0, 1, 1, 0, -1, 0, 0, 0);
+TPS_PDATA_INIT(vddctrl, 600, 1400, 0, 1, 1, 0, -1, 0, 0, EXT_CTRL_EN1);
+TPS_PDATA_INIT(vio,    1500, 3300, 0, 1, 1, 0, -1, 0, 0, 0);
+
+TPS_PDATA_INIT_SUPPLY(ldo1, 1000, 3300, VDD_2, 0, 0, 0, -1, 0, 0, 0);
+TPS_PDATA_INIT_SUPPLY(ldo2, 1000, 3300, VDD_2, 0, 0, 0, -1, 0, 0, 0);
+
+TPS_PDATA_INIT_BOARD(ldo3, e118x, 1000, 3300, 0, 0, 0, 0, -1, 0, 0, 0);
+TPS_PDATA_INIT_BOARD(ldo3, e1198, 1000, 3300, 0, 0, 0, 0, -1, 0, 0, 0);
+TPS_PDATA_INIT(ldo4, 1000, 3300, 0, 0, 0, 0, -1, 0, 0, 0);
+TPS_PDATA_INIT_BOARD(ldo5, e118x, 1000, 3300, 0, 0, 0, 0, -1, 0, 0, 0);
+TPS_PDATA_INIT_BOARD(ldo5, e1198, 1000, 3300, 0, 0, 0, 0, -1, 0, 0, 0);
+
+TPS_PDATA_INIT_SUPPLY(ldo6, 1000, 3300, VIO, 0, 0, 0, -1, 0, 0, 0);
+TPS_PDATA_INIT_SUPPLY(ldo7, 1000, 3300, VIO, 0, 0, 0, -1, 0, 0, 0);
+TPS_PDATA_INIT_SUPPLY(ldo8, 1000, 3300, VIO, 0, 0, 0, -1, 0, 0, 0);
+
+#if defined(CONFIG_RTC_DRV_TPS6591x)
 static struct tps6591x_rtc_platform_data rtc_data = {
        .irq = TEGRA_NR_IRQS + TPS6591X_INT_RTC_ALARM,
+       .time = {
+               .tm_year = 2000,
+               .tm_mon = 0,
+               .tm_mday = 1,
+               .tm_hour = 0,
+               .tm_min = 0,
+               .tm_sec = 0,
+       },
 };
 
-#define TPS_REG(_id, _data)                    \
-       {                                       \
-               .id     = TPS6591X_ID_##_id,    \
-               .name   = "tps6591x-regulator", \
-               .platform_data  = _data,        \
+#define TPS_RTC_REG()                          \
+       {                                               \
+               .id     = 0,            \
+               .name   = "rtc_tps6591x",       \
+               .platform_data = &rtc_data,     \
        }
+#endif
 
-static struct tps6591x_subdev_info tps_devs[] = {
-       TPS_REG(VIO, &vio_data),
-       TPS_REG(VDD_1, &vdd1_data),
-       TPS_REG(VDD_2, &vdd2_data),
-       TPS_REG(VDDCTRL, &vddctrl_data),
-       TPS_REG(LDO_1, &ldo1_data),
-       TPS_REG(LDO_2, &ldo2_data),
-       TPS_REG(LDO_3, &ldo3_data),
-       TPS_REG(LDO_4, &ldo4_data),
-       TPS_REG(LDO_5, &ldo5_data),
-       TPS_REG(LDO_6, &ldo6_data),
-       TPS_REG(LDO_7, &ldo7_data),
-       TPS_REG(LDO_8, &ldo8_data),
-       {
-               .id     = 0,
-               .name   = "tps6591x-rtc",
-               .platform_data = &rtc_data,
-       },
+#define TPS_REG(_id, _data)                            \
+       {                                               \
+               .id     = TPS6591X_ID_##_id,            \
+               .name   = "tps6591x-regulator",         \
+               .platform_data  = &pdata_##_data,       \
+       }
+
+static struct tps6591x_subdev_info tps_devs_e118x[] = {
+       TPS_REG(VIO, vio),
+       TPS_REG(VDD_1, vdd1),
+       TPS_REG(VDD_2, vdd2),
+       TPS_REG(VDDCTRL, vddctrl),
+       TPS_REG(LDO_1, ldo1),
+       TPS_REG(LDO_2, ldo2),
+       TPS_REG(LDO_3, ldo3_e118x),
+       TPS_REG(LDO_4, ldo4),
+       TPS_REG(LDO_5, ldo5_e118x),
+       TPS_REG(LDO_6, ldo6),
+       TPS_REG(LDO_7, ldo7),
+       TPS_REG(LDO_8, ldo8),
+#if defined(CONFIG_RTC_DRV_TPS6591x)
+       TPS_RTC_REG(),
+#endif
+};
+
+static struct tps6591x_subdev_info tps_devs_e1198[] = {
+       TPS_REG(VIO, vio),
+       TPS_REG(VDD_1, vdd1),
+       TPS_REG(VDD_2, vdd2),
+       TPS_REG(VDDCTRL, vddctrl),
+       TPS_REG(LDO_1, ldo1),
+       TPS_REG(LDO_2, ldo2),
+       TPS_REG(LDO_3, ldo3_e1198),
+       TPS_REG(LDO_4, ldo4),
+       TPS_REG(LDO_5, ldo5_e1198),
+       TPS_REG(LDO_6, ldo6),
+       TPS_REG(LDO_7, ldo7),
+       TPS_REG(LDO_8, ldo8),
+#if defined(CONFIG_RTC_DRV_TPS6591x)
+       TPS_RTC_REG(),
+#endif
 };
 
 static struct tps6591x_platform_data tps_platform = {
-       .irq_base       = TEGRA_NR_IRQS,
-       .num_subdevs    = ARRAY_SIZE(tps_devs),
-       .subdevs        = tps_devs,
+       .irq_base       = TPS6591X_IRQ_BASE,
        .gpio_base      = TPS6591X_GPIO_BASE,
 };
 
@@ -222,17 +318,27 @@ static struct i2c_board_info __initdata cardhu_regulators[] = {
 
 int __init cardhu_regulator_init(void)
 {
+       struct board_info board_info;
+       void __iomem *pmc = IO_ADDRESS(TEGRA_PMC_BASE);
+       u32 pmc_ctrl;
+       /* configure the power management controller to trigger PMU
+        * interrupts when low */
+       pmc_ctrl = readl(pmc + PMC_CTRL);
+       writel(pmc_ctrl | PMC_CTRL_INTR_LOW, pmc + PMC_CTRL);
+
+       tegra_get_board_info(&board_info);
+       if ((board_info.board_id == BOARD_E1198) ||
+               (board_info.board_id == BOARD_E1291)) {
+               tps_platform.num_subdevs = ARRAY_SIZE(tps_devs_e1198);
+               tps_platform.subdevs = tps_devs_e1198;
+       } else {
+               tps_platform.num_subdevs = ARRAY_SIZE(tps_devs_e118x);
+               tps_platform.subdevs = tps_devs_e118x;
+       }
+
        i2c_register_board_info(4, cardhu_regulators, 1);
        return 0;
 }
-#else
-int __init cardhu_regulator_init(void)
-{
-       return 0;
-}
-#endif
-
-#ifdef CONFIG_REGULATOR_GPIO_SWITCH
 
 /* EN_5V_CP from PMU GP0 */
 static struct regulator_consumer_supply gpio_switch_en_5v_cp_supply[] = {
@@ -263,7 +369,7 @@ static struct regulator_consumer_supply gpio_switch_en_3v3_sys_supply[] = {
        REGULATOR_SUPPLY("vcom_3v3", NULL),
        REGULATOR_SUPPLY("vdd_3v3", NULL),
        REGULATOR_SUPPLY("vcore_mmc", NULL),
-       REGULATOR_SUPPLY("vddo_pex_ctl", NULL),
+       REGULATOR_SUPPLY("vddio_pex_ctl", NULL),
        REGULATOR_SUPPLY("hvdd_pex", NULL),
        REGULATOR_SUPPLY("avdd_hdmi", NULL),
        REGULATOR_SUPPLY("vpp_fuse", NULL),
@@ -291,16 +397,36 @@ static struct regulator_consumer_supply gpio_switch_en_3v3_sys_supply[] = {
        REGULATOR_SUPPLY("vcom_pa", NULL),
        REGULATOR_SUPPLY("vdd_3v3_devices", NULL),
        REGULATOR_SUPPLY("vdd_3v3_dock", NULL),
+       REGULATOR_SUPPLY("vdd_3v3_edid", NULL),
+       REGULATOR_SUPPLY("vdd_3v3_hdmi_cec", NULL),
+       REGULATOR_SUPPLY("vdd_3v3_gmi", NULL),
+       REGULATOR_SUPPLY("vdd_3v3_spk_amp", NULL),
+       REGULATOR_SUPPLY("vdd_3v3_sensor", NULL),
+       REGULATOR_SUPPLY("vdd_3v3_cam", NULL),
+       REGULATOR_SUPPLY("vdd_3v3_als", NULL),
        REGULATOR_SUPPLY("debug_cons", NULL),
 };
 static int gpio_switch_en_3v3_sys_voltages[] = { 3300};
 
-/* EN_VDD_BL from AP GPIO GMI_CS2  K03 */
+/* DIS_5V_SWITCH from AP SPI2_SCK X02 */
+static struct regulator_consumer_supply gpio_switch_dis_5v_switch_supply[] = {
+       REGULATOR_SUPPLY("master_5v_switch", NULL),
+};
+static int gpio_switch_dis_5v_switch_voltages[] = { 5000};
+
+/* EN_VDD_BL */
 static struct regulator_consumer_supply gpio_switch_en_vdd_bl_supply[] = {
        REGULATOR_SUPPLY("vdd_backlight", NULL),
+       REGULATOR_SUPPLY("vdd_backlight1", NULL),
 };
 static int gpio_switch_en_vdd_bl_voltages[] = { 5000};
 
+/* EN_VDD_BL2 (E1291-A03) from AP PEX_L0_PRSNT_N DD.00 */
+static struct regulator_consumer_supply gpio_switch_en_vdd_bl2_supply[] = {
+       REGULATOR_SUPPLY("vdd_backlight2", NULL),
+};
+static int gpio_switch_en_vdd_bl2_voltages[] = { 5000};
+
 /* EN_3V3_MODEM from AP GPIO VI_VSYNCH D06*/
 static struct regulator_consumer_supply gpio_switch_en_3v3_modem_supply[] = {
        REGULATOR_SUPPLY("vdd_3v3_mini_card", NULL),
@@ -308,13 +434,13 @@ static struct regulator_consumer_supply gpio_switch_en_3v3_modem_supply[] = {
 };
 static int gpio_switch_en_3v3_modem_voltages[] = { 3300};
 
-/* EN_USB1_VBUS_OC from AP GPIO GMI_RST I04*/
+/* EN_USB1_VBUS_OC*/
 static struct regulator_consumer_supply gpio_switch_en_usb1_vbus_oc_supply[] = {
        REGULATOR_SUPPLY("vdd_vbus_micro_usb", NULL),
 };
 static int gpio_switch_en_usb1_vbus_oc_voltages[] = { 5000};
 
-/*EN_USB3_VBUS_OC from AP GPIO GMI_AD15 H07*/
+/*EN_USB3_VBUS_OC*/
 static struct regulator_consumer_supply gpio_switch_en_usb3_vbus_oc_supply[] = {
        REGULATOR_SUPPLY("vdd_vbus_typea_usb", NULL),
 };
@@ -332,6 +458,18 @@ static struct regulator_consumer_supply gpio_switch_en_vdd_pnl1_supply[] = {
 };
 static int gpio_switch_en_vdd_pnl1_voltages[] = { 3300};
 
+/* CAM1_LDO_EN from AP GPIO KB_ROW6 R06*/
+static struct regulator_consumer_supply gpio_switch_cam1_ldo_en_supply[] = {
+       REGULATOR_SUPPLY("vdd_2v8_cam1", NULL),
+};
+static int gpio_switch_cam1_ldo_en_voltages[] = { 2800};
+
+/* CAM2_LDO_EN from AP GPIO KB_ROW7 R07*/
+static struct regulator_consumer_supply gpio_switch_cam2_ldo_en_supply[] = {
+       REGULATOR_SUPPLY("vdd_2v8_cam2", NULL),
+};
+static int gpio_switch_cam2_ldo_en_voltages[] = { 2800};
+
 /* CAM3_LDO_EN from AP GPIO KB_ROW8 S00*/
 static struct regulator_consumer_supply gpio_switch_cam3_ldo_en_supply[] = {
        REGULATOR_SUPPLY("vdd_cam3", NULL),
@@ -340,7 +478,7 @@ static int gpio_switch_cam3_ldo_en_voltages[] = { 3300};
 
 /* EN_VDD_COM from AP GPIO SDMMC3_DAT5 D00*/
 static struct regulator_consumer_supply gpio_switch_en_vdd_com_supply[] = {
-       REGULATOR_SUPPLY("vdd_cwcom_bd", NULL),
+       REGULATOR_SUPPLY("vdd_com_bd", NULL),
 };
 static int gpio_switch_en_vdd_com_voltages[] = { 3300};
 
@@ -376,14 +514,54 @@ static struct regulator_consumer_supply gpio_switch_en_1v8_cam_supply[] = {
 };
 static int gpio_switch_en_1v8_cam_voltages[] = { 1800};
 
-/* Macro for defining gpio switch regulator platform data and device */
-#define GPIO_REGULATOR_PINIT(_id, _name, _input_supply, _gpio_nr, _active_low, _init_state) \
-       static struct gpio_switch_regulator_platform_data               \
-                               gpio_switch_regulator_##_name##_pdata = { \
+static struct regulator_consumer_supply gpio_switch_en_vbrtr_supply[] = {
+       REGULATOR_SUPPLY("vdd_vbrtr", NULL),
+};
+static int gpio_switch_en_vbrtr_voltages[] = { 3300};
+
+static int enable_load_switch_rail(
+               struct gpio_switch_regulator_subdev_data *psubdev_data)
+{
+       int ret;
+
+       if (psubdev_data->pin_group <= 0)
+               return -EINVAL;
+
+       /* Tristate and make pin as input*/
+       ret = tegra_pinmux_set_tristate(psubdev_data->pin_group,
+                                               TEGRA_TRI_TRISTATE);
+       if (ret < 0)
+               return ret;
+       return gpio_direction_input(psubdev_data->gpio_nr);
+}
+
+static int disable_load_switch_rail(
+               struct gpio_switch_regulator_subdev_data *psubdev_data)
+{
+       int ret;
+
+       if (psubdev_data->pin_group <= 0)
+               return -EINVAL;
+
+       /* Un-tristate and driver low */
+       ret = tegra_pinmux_set_tristate(psubdev_data->pin_group,
+                                               TEGRA_TRI_NORMAL);
+       if (ret < 0)
+               return ret;
+       return gpio_direction_output(psubdev_data->gpio_nr, 0);
+}
+
+
+/* Macro for defining gpio switch regulator sub device data */
+#define GREG_INIT(_id, _var, _name, _input_supply, _gpio_nr, _active_low, \
+                       _init_state, _pg, _enable, _disable)            \
+       static struct gpio_switch_regulator_subdev_data gpio_pdata_##_var =  \
+       {                                                               \
                .regulator_name = "gpio-switch-"#_name,                 \
                .input_supply   = _input_supply,                        \
                .id             = _id,                                  \
                .gpio_nr        = _gpio_nr,                             \
+               .pin_group      = _pg,                                  \
                .active_low     = _active_low,                          \
                .init_state     = _init_state,                          \
                .voltages       = gpio_switch_##_name##_voltages,       \
@@ -398,98 +576,233 @@ static int gpio_switch_en_1v8_cam_voltages[] = { 1800};
                                           REGULATOR_CHANGE_STATUS |    \
                                           REGULATOR_CHANGE_VOLTAGE),   \
                },                                                      \
-       };                                                              \
-                                                                       \
-       static struct platform_device gpio_switch_regulator_##_name = { \
-               .name = "gpio-switch-regulator",                        \
-               .id   = _id,                                            \
-               .dev  = {                                               \
-                    .platform_data = &gpio_switch_regulator_##_name##_pdata,\
-               },                                                      \
-       };
-
-/* Gpio switch regulator platform data */
-GPIO_REGULATOR_PINIT(0, en_5v_cp,   NULL, TPS6591X_GPIO_GP0, false, 0)
-GPIO_REGULATOR_PINIT(1, en_5v0,     NULL, TPS6591X_GPIO_GP2, false, 0)
-GPIO_REGULATOR_PINIT(2, en_ddr,     NULL, TPS6591X_GPIO_GP6, false, 0)
-GPIO_REGULATOR_PINIT(3, en_3v3_sys, NULL, TPS6591X_GPIO_GP7, false, 0)
-
-GPIO_REGULATOR_PINIT(4, en_vdd_bl,       NULL,          TEGRA_GPIO_PK3, false, 1)
-GPIO_REGULATOR_PINIT(5, en_3v3_modem,    NULL,          TEGRA_GPIO_PD6, false, 0)
-GPIO_REGULATOR_PINIT(6, en_usb1_vbus_oc, "vdd_5v0_sys", TEGRA_GPIO_PI4, false, 0)
-GPIO_REGULATOR_PINIT(7, en_usb3_vbus_oc, "vdd_5v0_sys", TEGRA_GPIO_PH7, false, 0)
-GPIO_REGULATOR_PINIT(8, en_vddio_vid_oc, "vdd_5v0_sys", TEGRA_GPIO_PT0, false, 0)
-
-GPIO_REGULATOR_PINIT(9, en_vdd_pnl1, "vdd_3v3_devices", TEGRA_GPIO_PL4, false, 1)
-GPIO_REGULATOR_PINIT(10, cam3_ldo_en, "vdd_3v3_devices", TEGRA_GPIO_PS0, false, 0)
-GPIO_REGULATOR_PINIT(11, en_vdd_com,  "vdd_3v3_devices", TEGRA_GPIO_PD0, false, 0)
-GPIO_REGULATOR_PINIT(12, en_3v3_fuse, "vdd_3v3_devices", TEGRA_GPIO_PL6, false, 0)
-GPIO_REGULATOR_PINIT(13, en_3v3_emmc, "vdd_3v3_devices", TEGRA_GPIO_PD1, false, 1)
-GPIO_REGULATOR_PINIT(14, en_vdd_sdmmc1, "vdd_3v3_devices", TEGRA_GPIO_PD7, false, 1)
-GPIO_REGULATOR_PINIT(15, en_3v3_pex_hvdd, "vdd_3v3_devices",
-                                                       TEGRA_GPIO_PL7, false, 0)
-
-GPIO_REGULATOR_PINIT(16, en_1v8_cam,  "vdd_gen1v8", TEGRA_GPIO_PBB4, false, 0)
-
-static struct platform_device *gpio_switch_regulator_devices[] __initdata = {
-       &gpio_switch_regulator_en_5v_cp,
-       &gpio_switch_regulator_en_5v0,
-       &gpio_switch_regulator_en_ddr,
-       &gpio_switch_regulator_en_3v3_sys,
-       &gpio_switch_regulator_en_vdd_bl,
-       &gpio_switch_regulator_en_3v3_modem,
-       &gpio_switch_regulator_en_usb1_vbus_oc,
-       &gpio_switch_regulator_en_usb3_vbus_oc,
-       &gpio_switch_regulator_en_vddio_vid_oc,
-       &gpio_switch_regulator_en_vdd_pnl1,
-       &gpio_switch_regulator_cam3_ldo_en,
-       &gpio_switch_regulator_en_vdd_com,
-       &gpio_switch_regulator_en_3v3_fuse,
-       &gpio_switch_regulator_en_3v3_emmc,
-       &gpio_switch_regulator_en_vdd_sdmmc1,
-       &gpio_switch_regulator_en_3v3_pex_hvdd,
-       &gpio_switch_regulator_en_1v8_cam,
+               .enable_rail = _enable,                                 \
+               .disable_rail = _disable,                               \
+       }
+
+/* common to all boards */
+GREG_INIT(0, en_5v_cp,         en_5v_cp,       NULL,                   TPS6591X_GPIO_GP0,      false,  0,      0,      0,      0);
+GREG_INIT(1, en_5v0,           en_5v0,         NULL,                   TPS6591X_GPIO_GP2,      false,  0,      0,      0,      0);
+GREG_INIT(2, en_ddr,           en_ddr,         NULL,                   TPS6591X_GPIO_GP6,      false,  0,      0,      0,      0);
+GREG_INIT(3, en_3v3_sys,       en_3v3_sys,     NULL,                   TPS6591X_GPIO_GP7,      false,  0,      0,      0,      0);
+GREG_INIT(4, en_vdd_bl,                en_vdd_bl,      NULL,                   TEGRA_GPIO_PK3,         false,  1,      0,      0,      0);
+GREG_INIT(5, en_3v3_modem,     en_3v3_modem,   NULL,                   TEGRA_GPIO_PD6,         false,  1,      0,      0,      0);
+GREG_INIT(6, en_vdd_pnl1,      en_vdd_pnl1,    "vdd_3v3_devices",      TEGRA_GPIO_PL4,         false,  1,      0,      0,      0);
+GREG_INIT(7, cam3_ldo_en,      cam3_ldo_en,    "vdd_3v3_devices",      TEGRA_GPIO_PS0,         false,  0,      0,      0,      0);
+GREG_INIT(8, en_vdd_com,       en_vdd_com,     "vdd_3v3_devices",      TEGRA_GPIO_PD0,         false,  1,      0,      0,      0);
+GREG_INIT(9, en_3v3_fuse,      en_3v3_fuse,    "vdd_3v3_devices",      TEGRA_GPIO_PL6,         false,  0,      0,      0,      0);
+GREG_INIT(10, en_3v3_emmc,     en_3v3_emmc,    "vdd_3v3_devices",      TEGRA_GPIO_PD1,         false,  1,      0,      0,      0);
+GREG_INIT(11, en_vdd_sdmmc1,   en_vdd_sdmmc1,  "vdd_3v3_devices",      TEGRA_GPIO_PD7,         false,  1,      0,      0,      0);
+GREG_INIT(12, en_3v3_pex_hvdd, en_3v3_pex_hvdd, "vdd_3v3_devices",     TEGRA_GPIO_PL7,         false,  0,      0,      0,      0);
+GREG_INIT(13, en_1v8_cam,      en_1v8_cam,     "vdd_gen1v8",           TEGRA_GPIO_PBB4,        false,  0,      0,      0,      0);
+
+/* Specific to E1187/E1186 */
+GREG_INIT(14, dis_5v_switch_e118x,     dis_5v_switch,          "vdd_5v0_sys",
+               TEGRA_GPIO_PX2,         true,   0,      0,      0,      0);
+GREG_INIT(15, en_usb1_vbus_oc_e118x,   en_usb1_vbus_oc,        "master_5v_switch",
+               TEGRA_GPIO_PI4,         false,  0,      TEGRA_PINGROUP_GMI_RST_N,
+               enable_load_switch_rail, disable_load_switch_rail);
+GREG_INIT(16, en_usb3_vbus_oc_e118x,   en_usb3_vbus_oc,        "master_5v_switch",
+               TEGRA_GPIO_PH7,         false,  0,      TEGRA_PINGROUP_GMI_AD15,
+               enable_load_switch_rail, disable_load_switch_rail);
+GREG_INIT(17, en_vddio_vid_oc_e118x,   en_vddio_vid_oc,        "master_5v_switch",
+               TEGRA_GPIO_PT0,         false,  0,      TEGRA_PINGROUP_VI_PCLK,
+               enable_load_switch_rail, disable_load_switch_rail);
+
+/* E1198/E1291 specific  fab < A03 */
+GREG_INIT(15, en_usb1_vbus_oc,                 en_usb1_vbus_oc,        "vdd_5v0_sys",
+               TEGRA_GPIO_PI4,         false,  0,      TEGRA_PINGROUP_GMI_RST_N,
+               enable_load_switch_rail, disable_load_switch_rail);
+GREG_INIT(16, en_usb3_vbus_oc,         en_usb3_vbus_oc,        "vdd_5v0_sys",
+               TEGRA_GPIO_PH7,         false,  0,      TEGRA_PINGROUP_GMI_AD15,
+               enable_load_switch_rail, disable_load_switch_rail);
+
+/* E1198/E1291 specific  fab >= A03 */
+GREG_INIT(15, en_usb1_vbus_oc_a03,             en_usb1_vbus_oc,        "vdd_5v0_sys",
+               TEGRA_GPIO_PDD6,                false,  0,      TEGRA_PINGROUP_PEX_L1_CLKREQ_N,
+               enable_load_switch_rail, disable_load_switch_rail);
+GREG_INIT(16, en_usb3_vbus_oc_a03,             en_usb3_vbus_oc,        "vdd_5v0_sys",
+               TEGRA_GPIO_PDD4,                false,  0,      TEGRA_PINGROUP_PEX_L1_PRSNT_N,
+               enable_load_switch_rail, disable_load_switch_rail);
+
+/* E1198/E1291 specific */
+GREG_INIT(17, en_vddio_vid_oc,         en_vddio_vid_oc,        "vdd_5v0_sys",
+               TEGRA_GPIO_PT0,         false,  0,      TEGRA_PINGROUP_VI_PCLK,
+               enable_load_switch_rail, disable_load_switch_rail);
+
+/* E1198/E1291 specific*/
+GREG_INIT(18, cam1_ldo_en,     cam1_ldo_en,            "vdd_3v3_cam",  TEGRA_GPIO_PR6,         false,  0,      0,      0,      0);
+GREG_INIT(19, cam2_ldo_en,     cam2_ldo_en,            "vdd_3v3_cam",  TEGRA_GPIO_PR7,         false,  0,      0,      0,      0);
+
+/* E1291 A03 specific */
+GREG_INIT(20, en_vdd_bl1_a03,  en_vdd_bl,      NULL,           TEGRA_GPIO_PDD2,        false,  1,      0,      0,      0);
+GREG_INIT(21, en_vdd_bl2_a03,  en_vdd_bl2,     NULL,           TEGRA_GPIO_PDD0,        false,  1,      0,      0,      0);
+
+GREG_INIT(22, en_vbrtr,        en_vbrtr, "vdd_3v3_devices",    PMU_TCA6416_GPIO_PORT12,                false,  0,      0,      0,      0);
+
+#define ADD_GPIO_REG(_name) &gpio_pdata_##_name
+#define COMMON_GPIO_REG \
+       ADD_GPIO_REG(en_5v_cp),                 \
+       ADD_GPIO_REG(en_5v0),                   \
+       ADD_GPIO_REG(en_ddr),                   \
+       ADD_GPIO_REG(en_3v3_sys),               \
+       ADD_GPIO_REG(en_3v3_modem),             \
+       ADD_GPIO_REG(en_vdd_pnl1),              \
+       ADD_GPIO_REG(cam3_ldo_en),              \
+       ADD_GPIO_REG(en_vdd_com),               \
+       ADD_GPIO_REG(en_3v3_fuse),              \
+       ADD_GPIO_REG(en_3v3_emmc),              \
+       ADD_GPIO_REG(en_vdd_sdmmc1),            \
+       ADD_GPIO_REG(en_3v3_pex_hvdd),          \
+       ADD_GPIO_REG(en_1v8_cam),
+
+#define E118x_GPIO_REG \
+       ADD_GPIO_REG(en_vdd_bl),                \
+       ADD_GPIO_REG(dis_5v_switch_e118x),      \
+       ADD_GPIO_REG(en_usb1_vbus_oc_e118x),    \
+       ADD_GPIO_REG(en_usb3_vbus_oc_e118x),    \
+       ADD_GPIO_REG(en_vddio_vid_oc_e118x), \
+       ADD_GPIO_REG(en_vbrtr),
+
+#define E1198_GPIO_REG \
+       ADD_GPIO_REG(en_vddio_vid_oc),          \
+       ADD_GPIO_REG(cam1_ldo_en),              \
+       ADD_GPIO_REG(cam2_ldo_en),
+
+#define E1291_1198_A00_GPIO_REG        \
+       ADD_GPIO_REG(en_usb1_vbus_oc),          \
+       ADD_GPIO_REG(en_usb3_vbus_oc),          \
+       ADD_GPIO_REG(en_vdd_bl),
+
+#define E1291_A03_GPIO_REG     \
+       ADD_GPIO_REG(en_usb1_vbus_oc_a03),              \
+       ADD_GPIO_REG(en_usb3_vbus_oc_a03),              \
+       ADD_GPIO_REG(en_vdd_bl1_a03), \
+       ADD_GPIO_REG(en_vdd_bl2_a03),
+
+/* Gpio switch regulator platform data  for E1186/E1187*/
+
+/* Gpio switch regulator platform data  for E1186/E1187*/
+static struct gpio_switch_regulator_subdev_data *gswitch_subdevs_e118x[] = {
+       COMMON_GPIO_REG
+       E118x_GPIO_REG
+};
+
+/* Gpio switch regulator platform data for E1198 and E1291*/
+static struct gpio_switch_regulator_subdev_data *gswitch_subdevs_e1198[] = {
+       COMMON_GPIO_REG
+       E1291_1198_A00_GPIO_REG
+       E1198_GPIO_REG
+};
+
+/* Gpio switch regulator platform data for E1291 A03*/
+static struct gpio_switch_regulator_subdev_data *gswitch_subdevs_e1291_a03[] = {
+       COMMON_GPIO_REG
+       E1291_A03_GPIO_REG
+       E1198_GPIO_REG
+};
+
+static struct gpio_switch_regulator_platform_data  gswitch_pdata;
+static struct platform_device gswitch_regulator_pdata = {
+       .name = "gpio-switch-regulator",
+       .id   = -1,
+       .dev  = {
+            .platform_data = &gswitch_pdata,
+       },
 };
 
 int __init cardhu_gpio_switch_regulator_init(void)
 {
        int i;
-       struct gpio_switch_regulator_platform_data *pdata;
-       for (i = 0; i < ARRAY_SIZE(gpio_switch_regulator_devices); ++i) {
-               pdata = gpio_switch_regulator_devices[i]->dev.platform_data;
-               if (pdata->gpio_nr <= TEGRA_NR_GPIOS)
-                       tegra_gpio_enable(pdata->gpio_nr);
+       struct board_info board_info;
+       tegra_get_board_info(&board_info);
+       switch (board_info.board_id) {
+       case BOARD_E1198:
+               gswitch_pdata.num_subdevs = ARRAY_SIZE(gswitch_subdevs_e1198);
+               gswitch_pdata.subdevs = gswitch_subdevs_e1198;
+               break;
+       case BOARD_E1291:
+               if (board_info.fab >= 0x3) {
+                       gswitch_pdata.num_subdevs =
+                                       ARRAY_SIZE(gswitch_subdevs_e1291_a03);
+                       gswitch_pdata.subdevs = gswitch_subdevs_e1291_a03;
+                       break;
+               }
+               gswitch_pdata.num_subdevs = ARRAY_SIZE(gswitch_subdevs_e1198);
+               gswitch_pdata.subdevs = gswitch_subdevs_e1198;
+               break;
+       default:
+               gswitch_pdata.num_subdevs = ARRAY_SIZE(gswitch_subdevs_e118x);
+               gswitch_pdata.subdevs = gswitch_subdevs_e118x;
+               break;
        }
 
-       platform_add_devices(gpio_switch_regulator_devices,
-                               ARRAY_SIZE(gpio_switch_regulator_devices));
-       return 0;
-}
-#else
-int __init cardhu_gpio_switch_regulator_init(void)
-{
-       return 0;
+       for (i = 0; i < gswitch_pdata.num_subdevs; ++i) {
+               struct gpio_switch_regulator_subdev_data *gswitch_data = gswitch_pdata.subdevs[i];
+               if (gswitch_data->gpio_nr <= TEGRA_NR_GPIOS)
+                       tegra_gpio_enable(gswitch_data->gpio_nr);
+       }
+
+       return platform_device_register(&gswitch_regulator_pdata);
 }
-#endif
 
 static struct tegra_suspend_platform_data cardhu_suspend_data = {
        .cpu_timer      = 2000,
-       .cpu_off_timer  = 0,
-       .suspend_mode   = TEGRA_SUSPEND_NONE,
+       .cpu_off_timer  = 200,
+       .suspend_mode   = TEGRA_SUSPEND_LP1,
        .core_timer     = 0x7e7e,
        .core_off_timer = 0,
        .separate_req   = true,
        .corereq_high   = false,
        .sysclkreq_high = true,
-       .wake_enb       = 0,
-       .wake_high      = 0,
-       .wake_low       = 0,
+       .wake_enb       = TEGRA_WAKE_GPIO_PV0 | TEGRA_WAKE_PWR_INT | TEGRA_WAKE_RTC_ALARM,
+       .wake_high      = TEGRA_WAKE_RTC_ALARM,
+       .wake_low       = TEGRA_WAKE_GPIO_PV0 | TEGRA_WAKE_PWR_INT,
        .wake_any       = 0,
+       .cpu_lp2_min_residency = 2000,
 };
 
 int __init cardhu_suspend_init(void)
 {
+       struct board_info board_info;
+
+       tegra_get_board_info(&board_info);
+       switch (board_info.board_id) {
+       case BOARD_E1291:
+               /* CORE_PWR_REQ to be high for E1291-A03 */
+               if (board_info.fab == 0x3)
+                       cardhu_suspend_data.corereq_high = true;
+               break;
+       case BOARD_E1198:
+               break;
+       case BOARD_PM269:
+       case BOARD_E1187:
+       case BOARD_E1186:
+               cardhu_suspend_data.cpu_timer = 5000;
+               cardhu_suspend_data.cpu_off_timer = 5000;
+               break;
+       default:
+               break;
+       }
+
        tegra_init_suspend(&cardhu_suspend_data);
        return 0;
+}
+
+static void cardhu_power_off(void)
+{
+       int ret;
+       pr_err("cardhu: Powering off the device\n");
+       ret = tps6591x_power_off();
+       if (ret)
+               pr_err("cardhu: failed to power off\n");
 
+       while(1);
 }
+
+int __init cardhu_power_off_init(void)
+{
+       pm_power_off = cardhu_power_off;
+       return 0;
+}
+