arm: tegra: enterprise: add I2C mux driver instance
Jihoon Bang [Tue, 27 Sep 2011 18:23:55 +0000 (11:23 -0700)]
Add I2C mux driver instance to support two rear sensors.
Add new GPIO pin to control reset for I2C mux.
If board doesn't have I2C mux, it falls back to previous I2C tree.

Bug 871860

Reviewed-on: http://git-master/r/54763
(cherry picked from commit c53f8fc9d5d05427684aafb4ad6552eb6cff7ff7)

Reviewed-on: http://git-master/r/55799
(cherry picked from commit c5fe68c1b4b1ed1e283526c8ac057efb3a2af5af)

Change-Id: I40a35cbd301e53a8d70700043142d5cac0655b5c
Reviewed-on: http://git-master/r/57414
Reviewed-by: Jihoon Bang <jbang@nvidia.com>
Tested-by: Jihoon Bang <jbang@nvidia.com>
Reviewed-by: Dan Willemsen <dwillemsen@nvidia.com>

Rebase-Id: Re59baf9b13c653c366f992913622d1a46c8aecde

arch/arm/mach-tegra/board-enterprise-pinmux.c
arch/arm/mach-tegra/board-enterprise-power.c
arch/arm/mach-tegra/board-enterprise-sensors.c
arch/arm/mach-tegra/board-enterprise.h

index 3d91cc7..44a33aa 100644 (file)
@@ -205,6 +205,7 @@ static __initdata struct tegra_pingroup_config enterprise_pinmux[] = {
        DEFAULT_PINMUX(LCD_D7,          RSVD1,           NORMAL,    NORMAL,     OUTPUT),
        DEFAULT_PINMUX(LCD_D8,          DISPLAYA,        NORMAL,    NORMAL,     INPUT),
        DEFAULT_PINMUX(LCD_D9,          DISPLAYA,        NORMAL,    NORMAL,     INPUT),
+       DEFAULT_PINMUX(LCD_D11,         DISPLAYA,        NORMAL,    NORMAL,     INPUT),
        DEFAULT_PINMUX(LCD_D12,         DISPLAYA,        NORMAL,    NORMAL,     INPUT),
        DEFAULT_PINMUX(LCD_D13,         DISPLAYA,        NORMAL,    NORMAL,     INPUT),
        DEFAULT_PINMUX(LCD_D14,         DISPLAYA,        NORMAL,    NORMAL,     INPUT),
@@ -381,7 +382,6 @@ static __initdata struct tegra_pingroup_config enterprise_unused_pinmux[] = {
        DEFAULT_PINMUX(LCD_HSYNC,       DISPLAYA,        PULL_DOWN,    TRISTATE,  OUTPUT),
        DEFAULT_PINMUX(LCD_VSYNC,       DISPLAYA,        PULL_DOWN,    TRISTATE,  OUTPUT),
        DEFAULT_PINMUX(LCD_D10,         DISPLAYA,        PULL_DOWN,    TRISTATE,  OUTPUT),
-       DEFAULT_PINMUX(LCD_D11,         DISPLAYA,        PULL_DOWN,    TRISTATE,  OUTPUT),
        DEFAULT_PINMUX(LCD_PWR0,        DISPLAYA,        PULL_DOWN,    TRISTATE,  OUTPUT),
        DEFAULT_PINMUX(LCD_SCK,        DISPLAYA,        PULL_DOWN,    TRISTATE,  OUTPUT),
        DEFAULT_PINMUX(LCD_SDOUT,       DISPLAYA,        PULL_DOWN,    TRISTATE,  OUTPUT),
@@ -459,7 +459,6 @@ static __initdata struct pin_info_low_power_mode enterprise_unused_gpio_pins[] =
        PIN_GPIO_LPM("LCD_HSYNC",    TEGRA_GPIO_PJ3,  0, 0),
        PIN_GPIO_LPM("LCD_VSYNC",    TEGRA_GPIO_PJ4,  0, 0),
        PIN_GPIO_LPM("LCD_D10",      TEGRA_GPIO_PF2,  0, 0),
-       PIN_GPIO_LPM("LCD_D12",      TEGRA_GPIO_PF3,  0, 0),
        PIN_GPIO_LPM("LCD_PWR0",     TEGRA_GPIO_PB2,  0, 0),
        PIN_GPIO_LPM("LCD_SCK",      TEGRA_GPIO_PZ4,  0, 0),
        PIN_GPIO_LPM("LCD_SDOUT",    TEGRA_GPIO_PN5,  0, 0),
index 4ccedb2..96f0403 100644 (file)
@@ -346,24 +346,38 @@ static struct regulator_consumer_supply gpio_switch_sdmmc3_vdd_sel_supply[] = {
 static int gpio_switch_sdmmc3_vdd_sel_voltages[] = {2850};
 
 /* LCD-D23 (GPIO M7) from T30*/
-/* 2-0036 is dev_name of ar0832 */
+/* 2-0036 is dev_name of ar0832 in Enterprise A01*/
+/* 2-0032 is alternative dev_name of ar0832 Enterprise A01*/
 /* 2-0010 is dev_name of ov9726 */
+/* 2-0070 is dev_name of PCA9546 in Enterprise A02*/
+/* 6-0036 is dev_name of ar0832 in Enterprise A02 */
+/* 7-0036 is dev_name of ar0832 in Enterprise A02 */
 static struct regulator_consumer_supply gpio_switch_cam_ldo_2v8_en_supply[] = {
        REGULATOR_SUPPLY("vaa", "2-0036"),
        REGULATOR_SUPPLY("vaa", "2-0032"),
        REGULATOR_SUPPLY("avdd", "2-0010"),
        REGULATOR_SUPPLY("vdd_2v8_cam", NULL),
+       REGULATOR_SUPPLY("vcc", "2-0070"),
+       REGULATOR_SUPPLY("vaa", "6-0036"),
+       REGULATOR_SUPPLY("vaa", "7-0036"),
 };
 static int gpio_switch_cam_ldo_2v8_en_voltages[] = {2800};
 
 /* LCD-D9 (GPIO F1) from T30*/
-/* 2-0036 is dev_name of ar0832 */
+/* 2-0036 is dev_name of ar0832 in Enterprise A01*/
+/* 2-0032 is alternative dev_name of ar0832 Enterprise A01*/
 /* 2-0010 is dev_name of ov9726 */
+/* 2-0070 is dev_name of PCA9546 in Enterprise A02*/
+/* 6-0036 is dev_name of ar0832 in Enterprise A02 */
+/* 7-0036 is dev_name of ar0832 in Enterprise A02 */
 static struct regulator_consumer_supply gpio_switch_cam_ldo_1v8_en_supply[] = {
        REGULATOR_SUPPLY("vdd", "2-0036"),
        REGULATOR_SUPPLY("vdd", "2-0032"),
        REGULATOR_SUPPLY("dovdd", "2-0010"),
        REGULATOR_SUPPLY("vdd_1v8_cam", NULL),
+       REGULATOR_SUPPLY("vcc_i2c", "2-0070"),
+       REGULATOR_SUPPLY("vdd", "6-0036"),
+       REGULATOR_SUPPLY("vdd", "7-0036"),
 };
 static int gpio_switch_cam_ldo_1v8_en_voltages[] = {1800};
 
index 2874971..c60f259 100644 (file)
@@ -33,6 +33,7 @@
 
 #include <linux/i2c.h>
 #include <linux/delay.h>
+#include <linux/i2c/pca954x.h>
 #include <linux/err.h>
 #include <linux/mpu.h>
 #include <linux/nct1008.h>
@@ -45,6 +46,7 @@
 #include "cpu-tegra.h"
 #include "gpio-names.h"
 #include "board-enterprise.h"
+#include "board.h"
 
 static struct nct1008_platform_data enterprise_nct1008_pdata = {
        .supported_hwrev = true,
@@ -280,6 +282,7 @@ static int enterprise_ar0832_ri_power_on(int is_stereo)
 {
        int ret = 0;
 
+       pr_info("%s: ++\n", __func__);
        ret = enterprise_cam_pwr(CAM_REAR_RIGHT, true);
 
        /* Release Reset */
@@ -394,26 +397,25 @@ static int enterprise_tps61050_pm(int pwr)
        pr_info("%s: ++%d\n", __func__, pwr);
        switch (pwr) {
        case TPS61050_PWR_OFF:
-               if (enterprise_flash_reg) {
+               if (enterprise_flash_reg)
                        regulator_disable(enterprise_flash_reg);
-                       regulator_put(enterprise_flash_reg);
-                       enterprise_flash_reg = NULL;
-               }
                break;
        case TPS61050_PWR_STDBY:
        case TPS61050_PWR_COMM:
        case TPS61050_PWR_ON:
-               enterprise_flash_reg = regulator_get(NULL, "vdd_1v8_cam");
-               if (IS_ERR_OR_NULL(enterprise_flash_reg)) {
-                       pr_err("%s: failed to get flash pwr\n", __func__);
-                       return PTR_ERR(enterprise_flash_reg);
+               if (!enterprise_flash_reg) {
+                       enterprise_flash_reg = regulator_get(NULL, "vdd_1v8_cam");
+                       if (IS_ERR_OR_NULL(enterprise_flash_reg)) {
+                               pr_err("%s: failed to get flash pwr\n", __func__);
+                               return PTR_ERR(enterprise_flash_reg);
+                       }
                }
                ret = regulator_enable(enterprise_flash_reg);
                if (ret) {
                        pr_err("%s: failed to enable flash pwr\n", __func__);
                        goto fail_regulator_flash_reg;
                }
-               enterprise_msleep(10);
+               enterprise_msleep(1);
                break;
        default:
                ret = -1;
@@ -447,6 +449,19 @@ static struct enterprise_cam_gpio enterprise_cam_gpio_data[] = {
        [3] = TEGRA_CAMERA_GPIO(CAM3_RST_L_GPIO, "cam3_rst_lo", 0),
        [4] = TEGRA_CAMERA_GPIO(CAM3_PWDN_GPIO, "cam3_pwdn", 1),
        [5] = TEGRA_CAMERA_GPIO(CAM_FLASH_EN_GPIO, "flash_en", 1),
+       [6] = TEGRA_CAMERA_GPIO(CAM_I2C_MUX_RST_EXP, "cam_i2c_mux_rst", 1),
+};
+
+static struct pca954x_platform_mode enterprise_pca954x_modes[] = {
+       { .adap_id = PCA954x_I2C_BUS0, .deselect_on_exit = true, },
+       { .adap_id = PCA954x_I2C_BUS1, .deselect_on_exit = true, },
+       { .adap_id = PCA954x_I2C_BUS2, .deselect_on_exit = true, },
+       { .adap_id = PCA954x_I2C_BUS3, .deselect_on_exit = true, },
+};
+
+static struct pca954x_platform_data enterprise_pca954x_data = {
+       .modes    = enterprise_pca954x_modes,
+       .num_modes      = ARRAY_SIZE(enterprise_pca954x_modes),
 };
 
 static struct ar0832_platform_data enterprise_ar0832_ri_data = {
@@ -474,6 +489,21 @@ static struct tps61050_platform_data enterprise_tps61050_data = {
        .gpio_sync      = NULL,
 };
 
+static const struct i2c_board_info enterprise_i2c2_boardinfo[] = {
+       {
+               I2C_BOARD_INFO("pca9546", 0x70),
+               .platform_data = &enterprise_pca954x_data,
+       },
+       {
+               I2C_BOARD_INFO("tps61050", 0x33),
+               .platform_data = &enterprise_tps61050_data,
+       },
+       {
+               I2C_BOARD_INFO("ov9726", OV9726_I2C_ADDR >> 1),
+               .platform_data = &enterprise_ov9726_data,
+       },
+};
+
 /*
  * Since ar0832 driver should support multiple devices, slave
  * address should be changed after it is open. Default slave
@@ -482,12 +512,12 @@ static struct tps61050_platform_data enterprise_tps61050_data = {
  */
 static struct i2c_board_info ar0832_i2c2_boardinfo[] = {
        {
-               /* 0x30: alternative slave address */
+               /* 0x36: alternative slave address */
                I2C_BOARD_INFO("ar0832", 0x36),
                .platform_data = &enterprise_ar0832_ri_data,
        },
        {
-               /* 0x31: alternative slave address */
+               /* 0x32: alternative slave address */
                I2C_BOARD_INFO("ar0832", 0x32),
                .platform_data = &enterprise_ar0832_le_data,
        },
@@ -501,13 +531,27 @@ static struct i2c_board_info ar0832_i2c2_boardinfo[] = {
        },
 };
 
+static struct i2c_board_info enterprise_i2c6_boardinfo[] = {
+       {
+               I2C_BOARD_INFO("ar0832", 0x36),
+               .platform_data = &enterprise_ar0832_le_data,
+       },
+};
+
+static struct i2c_board_info enterprise_i2c7_boardinfo[] = {
+       {
+               I2C_BOARD_INFO("ar0832", 0x36),
+               .platform_data = &enterprise_ar0832_ri_data,
+       },
+};
+
 static int enterprise_cam_init(void)
 {
        int ret;
        int i;
+       struct board_info bi;
 
        pr_info("%s:++\n", __func__);
-
        memset(ent_vicsi_pwr, 0, sizeof(ent_vicsi_pwr));
        for (i = 0; i < ARRAY_SIZE(enterprise_cam_gpio_data); i++) {
                ret = gpio_request(enterprise_cam_gpio_data[i].gpio,
@@ -523,8 +567,23 @@ static int enterprise_cam_init(void)
                tegra_gpio_enable(enterprise_cam_gpio_data[i].gpio);
        }
 
-       i2c_register_board_info(2, ar0832_i2c2_boardinfo,
-               ARRAY_SIZE(ar0832_i2c2_boardinfo));
+       tegra_get_board_info(&bi);
+
+       if (bi.fab == BOARD_FAB_A01)
+               i2c_register_board_info(2, ar0832_i2c2_boardinfo,
+                       ARRAY_SIZE(ar0832_i2c2_boardinfo));
+       else if (bi.fab == BOARD_FAB_A02) {
+               i2c_register_board_info(2, enterprise_i2c2_boardinfo,
+                       ARRAY_SIZE(enterprise_i2c2_boardinfo));
+               /*
+                * Right  camera is on PCA954x's I2C BUS1,
+                * Left camera is on BUS0
+                */
+               i2c_register_board_info(PCA954x_I2C_BUS0, enterprise_i2c6_boardinfo,
+                       ARRAY_SIZE(enterprise_i2c6_boardinfo));
+               i2c_register_board_info(PCA954x_I2C_BUS1, enterprise_i2c7_boardinfo,
+                       ARRAY_SIZE(enterprise_i2c7_boardinfo));
+       }
 
        return 0;
 
@@ -538,6 +597,7 @@ fail_free_gpio:
 int __init enterprise_sensors_init(void)
 {
        int ret;
+
        enterprise_isl_init();
        enterprise_nct1008_init();
        enterprise_mpuirq_init();
index 26e6320..dcc24a0 100644 (file)
 #include <mach/irqs.h>
 #include <linux/mfd/tps80031.h>
 
+/* Processor Board  ID */
+#define BOARD_E1205            0x0C05
+
+/* Board Fab version */
+#define BOARD_FAB_A00          0x0
+#define BOARD_FAB_A01          0x1
+#define BOARD_FAB_A02          0x2
+
 int enterprise_charge_init(void);
 int enterprise_sdhci_init(void);
 int enterprise_pinmux_init(void);
@@ -39,6 +47,13 @@ int enterprise_suspend_init(void);
 int enterprise_edp_init(void);
 void __init enterprise_tsensor_init(void);
 
+/* PCA954x I2C bus expander bus addresses */
+#define PCA954x_I2C_BUS_BASE   6
+#define PCA954x_I2C_BUS0       (PCA954x_I2C_BUS_BASE + 0)
+#define PCA954x_I2C_BUS1       (PCA954x_I2C_BUS_BASE + 1)
+#define PCA954x_I2C_BUS2       (PCA954x_I2C_BUS_BASE + 2)
+#define PCA954x_I2C_BUS3       (PCA954x_I2C_BUS_BASE + 3)
+
 /*****************External GPIO tables ******************/
 /* External peripheral gpio base. */
 #define ENT_TPS80031_GPIO_BASE    TEGRA_NR_GPIOS
@@ -58,9 +73,7 @@ void __init enterprise_tsensor_init(void);
 #define CAM_CSI_MUX_SEL_FRONT  0
 
 #define CAM1_RST_L_GPIO                TEGRA_GPIO_PM5 /*REAR RIGHT*/
-#define CAM1_PWDN_GPIO         TEGRA_GPIO_PF3 /*REAR RIGHT*/
 #define CAM2_RST_L_GPIO                TEGRA_GPIO_PF4 /*REAR LEFT*/
-#define CAM2_PWDN_GPIO         TEGRA_GPIO_PF2 /*REAR LEFT*/
 #define CAM3_RST_L_GPIO                TEGRA_GPIO_PM2 /*FRONT*/
 #define CAM3_RST_L_TRUE                0
 #define CAM3_RST_L_FALSE       1
@@ -70,6 +83,7 @@ void __init enterprise_tsensor_init(void);
 #define CAM_FLASH_EN_GPIO      TEGRA_GPIO_PBB3
 #define CAM_FLASH_MAX_TORCH_AMP        7
 #define CAM_FLASH_MAX_FLASH_AMP        7
+#define CAM_I2C_MUX_RST_EXP    TEGRA_GPIO_PF3 /*I2C Mux Reset*/
 
 /* Audio-related GPIOs */
 #define TEGRA_GPIO_HP_DET      TEGRA_GPIO_PW3