aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-omap2/board-tuna-sensors.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/mach-omap2/board-tuna-sensors.c')
-rwxr-xr-xarch/arm/mach-omap2/board-tuna-sensors.c212
1 files changed, 212 insertions, 0 deletions
diff --git a/arch/arm/mach-omap2/board-tuna-sensors.c b/arch/arm/mach-omap2/board-tuna-sensors.c
new file mode 100755
index 0000000..f818aad
--- /dev/null
+++ b/arch/arm/mach-omap2/board-tuna-sensors.c
@@ -0,0 +1,212 @@
+/* Sensor support for Samsung Tuna Board.
+ *
+ * Copyright (C) 2011 Google, Inc.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that 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.
+ */
+
+#include <linux/kernel.h>
+#include <linux/gpio.h>
+#include <linux/i2c.h>
+#include <linux/mpu.h>
+#include <linux/gp2a.h>
+#include <linux/i2c/twl6030-madc.h>
+
+#include "mux.h"
+#include "board-tuna.h"
+
+#define GPIO_GYRO_INT 45
+#define GPIO_ACC_INT 122
+#define GPIO_MAG_INT 176
+#define GPIO_PS_ON 25
+#define GPIO_PS_VOUT 21
+#define GPIO_MSENSE_IRQ 157
+
+#define GP2A_LIGHT_ADC_CHANNEL 4
+
+static int gp2a_light_adc_value(void)
+{
+ return twl6030_get_madc_conversion(GP2A_LIGHT_ADC_CHANNEL);
+}
+
+static void gp2a_power(bool on)
+{
+ /* this controls the power supply rail to the gp2a IC */
+ gpio_set_value(GPIO_PS_ON, on);
+}
+
+static void gp2a_gpio_init(void)
+{
+ int ret = gpio_request(GPIO_PS_ON, "gp2a_power_supply_on");
+ if (ret) {
+ pr_err("%s Failed to request gpio gp2a power supply\n",
+ __func__);
+ return;
+ }
+ /* set power pin to output, initially powered off*/
+ ret = gpio_direction_output(GPIO_PS_ON, 0);
+ if (ret) {
+ pr_err("%s Failed in gpio_direction_output, value 0 with error %d\n",
+ __func__, ret);
+ }
+}
+
+static s8 orientation_back[] = {
+ -1, 0, 0,
+ 0, 1, 0,
+ 0, 0, -1,
+};
+
+static s8 orientation_back_right_90[] = {
+ 0, -1, 0,
+ -1, 0, 0,
+ 0, 0, -1,
+};
+
+static s8 orientation_back_left_90[] = {
+ 0, 1, 0,
+ 1, 0, 0,
+ 0, 0, -1,
+};
+
+static s8 orientation_back_180[] = {
+ 1, 0, 0,
+ 0, -1, 0,
+ 0, 0, -1,
+};
+
+/*
+ * A correction matrix for YAS530
+ * which takes care of soft iron effect in TORO
+ */
+static s32 compass_correction_matrix_toro[] = {
+ 1072, -51, -22,
+ -30, 910, -4,
+ -23, -63, 1024,
+};
+
+static void rotcpy(s8 dst[3 * 3], const s8 src[3 * 3])
+{
+ memcpy(dst, src, 3 * 3);
+}
+
+static struct mpu_platform_data mpu_data = {
+ .int_config = 0x10,
+ .orientation = { 1, 0, 0,
+ 0, 1, 0,
+ 0, 0, 1 },
+ /* accel */
+ .accel = {
+ .irq = OMAP_GPIO_IRQ(GPIO_ACC_INT),
+ .adapt_num = 4,
+ .bus = EXT_SLAVE_BUS_SECONDARY,
+ .address = 0x18,
+ .orientation = { 1, 0, 0,
+ 0, 1, 0,
+ 0, 0, 1 },
+ },
+ /* compass */
+ .compass = {
+ .irq = OMAP_GPIO_IRQ(GPIO_MAG_INT),
+ .adapt_num = 4,
+ .bus = EXT_SLAVE_BUS_PRIMARY,
+ .address = 0x2E,
+ .orientation = { 1, 0, 0,
+ 0, 1, 0,
+ 0, 0, 1 },
+ },
+};
+
+static struct gp2a_platform_data gp2a_pdata = {
+ .power = gp2a_power,
+ .p_out = GPIO_PS_VOUT,
+ .light_adc_value = gp2a_light_adc_value,
+};
+
+static struct i2c_board_info __initdata tuna_sensors_i2c4_boardinfo[] = {
+ {
+ I2C_BOARD_INFO("mpu3050", 0x68),
+ .irq = OMAP_GPIO_IRQ(GPIO_GYRO_INT),
+ .platform_data = &mpu_data,
+ },
+ {
+ I2C_BOARD_INFO("bma250", 0x18),
+ .irq = OMAP_GPIO_IRQ(GPIO_ACC_INT),
+ .platform_data = &mpu_data.accel,
+ },
+ {
+ I2C_BOARD_INFO("yas530", 0x2e),
+ .irq = OMAP_GPIO_IRQ(GPIO_MAG_INT),
+ .platform_data = &mpu_data.compass,
+ },
+ {
+ I2C_BOARD_INFO("gp2a", 0x44),
+ .platform_data = &gp2a_pdata,
+ },
+ {
+ I2C_BOARD_INFO("bmp180", 0x77),
+ },
+};
+
+static void omap4_tuna_fixup_orientations_maguro(int revision)
+{
+ if (revision >= 3) {
+ rotcpy(mpu_data.orientation, orientation_back_right_90);
+ rotcpy(mpu_data.accel.orientation, orientation_back_left_90);
+ } else if (revision >= 2) {
+ rotcpy(mpu_data.orientation, orientation_back_right_90);
+ rotcpy(mpu_data.accel.orientation, orientation_back_180);
+ } else if (revision == 1) {
+ rotcpy(mpu_data.accel.orientation, orientation_back_left_90);
+ }
+}
+
+static void omap4_tuna_fixup_orientations_toro(int revision)
+{
+ if (revision >= 2) {
+ rotcpy(mpu_data.orientation, orientation_back_left_90);
+ rotcpy(mpu_data.accel.orientation, orientation_back);
+ rotcpy(mpu_data.compass.orientation, orientation_back_180);
+ } else if (revision >= 1) {
+ rotcpy(mpu_data.orientation, orientation_back_left_90);
+ rotcpy(mpu_data.accel.orientation, orientation_back_180);
+ rotcpy(mpu_data.compass.orientation, orientation_back_left_90);
+ }
+}
+
+void __init omap4_tuna_sensors_init(void)
+{
+ omap_mux_init_gpio(GPIO_GYRO_INT, OMAP_PIN_INPUT);
+ omap_mux_init_gpio(GPIO_ACC_INT, OMAP_PIN_INPUT);
+ omap_mux_init_gpio(GPIO_MAG_INT, OMAP_PIN_INPUT);
+ omap_mux_init_gpio(GPIO_PS_ON, OMAP_PIN_OUTPUT);
+ omap_mux_init_gpio(GPIO_PS_VOUT, OMAP_WAKEUP_EN | OMAP_PIN_INPUT);
+
+ gpio_request(GPIO_GYRO_INT, "GYRO_INT");
+ gpio_direction_input(GPIO_GYRO_INT);
+ gpio_request(GPIO_ACC_INT, "ACC_INT");
+ gpio_direction_input(GPIO_ACC_INT);
+ gpio_request(GPIO_MAG_INT, "MAG_INT");
+ gpio_direction_input(GPIO_MAG_INT);
+ gpio_request(GPIO_MSENSE_IRQ, "MSENSE_IRQ");
+ gpio_direction_output(GPIO_MSENSE_IRQ, 1);
+ /* optical sensor */
+ gp2a_gpio_init();
+
+ if (omap4_tuna_get_type() == TUNA_TYPE_MAGURO) {
+ omap4_tuna_fixup_orientations_maguro(omap4_tuna_get_revision());
+ } else if (omap4_tuna_get_type() == TUNA_TYPE_TORO) {
+ omap4_tuna_fixup_orientations_toro(omap4_tuna_get_revision());
+ mpu_data.compass.private_data = compass_correction_matrix_toro;
+ }
+
+ i2c_register_board_info(4, tuna_sensors_i2c4_boardinfo,
+ ARRAY_SIZE(tuna_sensors_i2c4_boardinfo));
+}