/* 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 #include #include #include #include #if defined(CONFIG_TWL6030_GPADC) #include #elif defined(CONFIG_TWL4030_MADC) #include #else /* CONFIG_TWL6030_MADC */ #include #endif #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) { #if defined(CONFIG_TWL6030_GPADC) return twl6030_get_gpadc_conversion(GP2A_LIGHT_ADC_CHANNEL); #elif defined(CONFIG_TWL4030_MADC) return twl4030_get_madc_conversion(GP2A_LIGHT_ADC_CHANNEL); #else /* CONFIG_TWL6030_MADC */ return twl6030_get_madc_conversion(GP2A_LIGHT_ADC_CHANNEL); #endif } 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) { pr_info("HW %d", revision); if (revision >= 14) { rotcpy(mpu_data.orientation, orientation_back_left_90); rotcpy(mpu_data.accel.orientation, orientation_back); rotcpy(mpu_data.compass.orientation, orientation_back); } else 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)); }