msm: 8064: Configure SX1509 gpio expander chip
On MPQ variants of 8064, the gpio expander chip SX1509
is used via i2c bus to provid various functionalities such
as voltage regulators, AVC tuners, external keyboard, etc.
Add the platform data for the available expander chips,
initialize them, and enable the i2c bus.
While at it, fix the EPM expander values.
Change-Id: Id9efbfcde10515b24143e2b0d6978ff5a0794cac
Signed-off-by: Jay Chokshi <jchokshi@codeaurora.org>
diff --git a/arch/arm/mach-msm/board-8064.c b/arch/arm/mach-msm/board-8064.c
index 7b8e7c1..73b2e54 100644
--- a/arch/arm/mach-msm/board-8064.c
+++ b/arch/arm/mach-msm/board-8064.c
@@ -32,6 +32,7 @@
#include <linux/i2c/isa1200.h>
#include <linux/gpio_keys.h>
#include <linux/epm_adc.h>
+#include <linux/i2c/sx150x.h>
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
#include <asm/hardware/gic.h>
@@ -97,14 +98,6 @@
#define MSM_ION_HEAP_NUM 1
#endif
-#define GPIO_EXPANDER_IRQ_BASE (PM8821_IRQ_BASE + PM8821_NR_IRQS)
-#define GPIO_EXPANDER_GPIO_BASE (PM8821_MPP_BASE + PM8821_NR_MPPS)
-#define GPIO_EPM_EXPANDER_BASE GPIO_EXPANDER_GPIO_BASE
-
-enum {
- SX150X_EPM,
-};
-
#ifdef CONFIG_KERNEL_PMEM_EBI_REGION
static unsigned pmem_kernel_ebi1_size = MSM_PMEM_KERNEL_EBI1_SIZE;
static int __init pmem_kernel_ebi1_size_setup(char *p)
@@ -2205,6 +2198,9 @@
#define I2C_RUMI (1 << 2)
#define I2C_SIM (1 << 3)
#define I2C_LIQUID (1 << 4)
+#define I2C_MPQ_CDP BIT(5)
+#define I2C_MPQ_HRD BIT(6)
+#define I2C_MPQ_DTV BIT(7)
struct i2c_registry {
u8 machs;
@@ -2240,6 +2236,75 @@
},
};
+struct sx150x_platform_data mpq8064_sx150x_pdata[] = {
+ [SX150X_EXP1] = {
+ .gpio_base = SX150X_EXP1_GPIO_BASE,
+ .oscio_is_gpo = false,
+ .io_pullup_ena = 0x0,
+ .io_pulldn_ena = 0x0,
+ .io_open_drain_ena = 0x0,
+ .io_polarity = 0,
+ .irq_summary = -1,
+ },
+ [SX150X_EXP2] = {
+ .gpio_base = SX150X_EXP2_GPIO_BASE,
+ .oscio_is_gpo = false,
+ .io_pullup_ena = 0x0,
+ .io_pulldn_ena = 0x0,
+ .io_open_drain_ena = 0x0,
+ .io_polarity = 0,
+ .irq_summary = -1,
+ },
+ [SX150X_EXP3] = {
+ .gpio_base = SX150X_EXP3_GPIO_BASE,
+ .oscio_is_gpo = false,
+ .io_pullup_ena = 0x0,
+ .io_pulldn_ena = 0x0,
+ .io_open_drain_ena = 0x0,
+ .io_polarity = 0,
+ .irq_summary = -1,
+ },
+ [SX150X_EXP4] = {
+ .gpio_base = SX150X_EXP4_GPIO_BASE,
+ .oscio_is_gpo = false,
+ .io_pullup_ena = 0x0,
+ .io_pulldn_ena = 0x0,
+ .io_open_drain_ena = 0x0,
+ .io_polarity = 0,
+ .irq_summary = -1,
+ },
+};
+
+static struct i2c_board_info sx150x_gpio_exp_info[] = {
+ {
+ I2C_BOARD_INFO("sx1509q", 0x70),
+ .platform_data = &mpq8064_sx150x_pdata[SX150X_EXP1],
+ },
+ {
+ I2C_BOARD_INFO("sx1508q", 0x23),
+ .platform_data = &mpq8064_sx150x_pdata[SX150X_EXP2],
+ },
+ {
+ I2C_BOARD_INFO("sx1508q", 0x22),
+ .platform_data = &mpq8064_sx150x_pdata[SX150X_EXP3],
+ },
+ {
+ I2C_BOARD_INFO("sx1509q", 0x3E),
+ .platform_data = &mpq8064_sx150x_pdata[SX150X_EXP4],
+ },
+};
+
+#define MPQ8064_I2C_GSBI5_BUS_ID 5
+
+static struct i2c_registry mpq8064_i2c_devices[] __initdata = {
+ {
+ I2C_MPQ_CDP,
+ MPQ8064_I2C_GSBI5_BUS_ID,
+ sx150x_gpio_exp_info,
+ ARRAY_SIZE(sx150x_gpio_exp_info),
+ },
+};
+
static void __init register_i2c_devices(void)
{
u8 mach_mask = 0;
@@ -2264,6 +2329,8 @@
mach_mask = I2C_RUMI;
else if (machine_is_apq8064_sim())
mach_mask = I2C_SIM;
+ else if (PLATFORM_IS_MPQ8064())
+ mach_mask = I2C_MPQ_CDP;
else
pr_err("unmatched machine ID in register_i2c_devices\n");
@@ -2280,6 +2347,14 @@
apq8064_camera_i2c_devices.info,
apq8064_camera_i2c_devices.len);
#endif
+
+ for (i = 0; i < ARRAY_SIZE(mpq8064_i2c_devices); ++i) {
+ if (mpq8064_i2c_devices[i].machs & mach_mask)
+ i2c_register_board_info(
+ mpq8064_i2c_devices[i].bus,
+ mpq8064_i2c_devices[i].info,
+ mpq8064_i2c_devices[i].len);
+ }
}
static void enable_ddr3_regulator(void)
@@ -2296,6 +2371,19 @@
}
}
+static void enable_avc_i2c_bus(void)
+{
+ int avc_i2c_en_mpp = PM8921_MPP_PM_TO_SYS(8);
+ int rc;
+
+ rc = gpio_request(avc_i2c_en_mpp, "avc_i2c_en");
+ if (rc)
+ pr_err("request for avc_i2c_en mpp failed,"
+ "rc=%d\n", rc);
+ else
+ gpio_set_value_cansleep(avc_i2c_en_mpp, 1);
+}
+
static void __init apq8064_common_init(void)
{
msm_tsens_early_init(&apq_tsens_pdata);
@@ -2380,6 +2468,7 @@
apq8064_common_init();
if (machine_is_mpq8064_cdp() || machine_is_mpq8064_hrd() ||
machine_is_mpq8064_dtv()) {
+ enable_avc_i2c_bus();
platform_add_devices(mpq_devices, ARRAY_SIZE(mpq_devices));
} else {
ethernet_init();