diff options
Diffstat (limited to 'arch/arm/mach-omap2/board-tuna-sensors.c')
-rwxr-xr-x | arch/arm/mach-omap2/board-tuna-sensors.c | 212 |
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)); +} |