diff options
author | Philippe Langlais <philippe.langlais@linaro.org> | 2012-02-15 11:15:20 +0100 |
---|---|---|
committer | Philippe Langlais <philippe.langlais@linaro.org> | 2012-02-15 11:15:20 +0100 |
commit | 3ccc59a697081a8af8a130d05fc4655445ab5b48 (patch) | |
tree | b7af9041482f79bf19a0a6fdef0410b115dc8f60 | |
parent | 7f2f7c67ab6ce79ec76c2def9a322d2badb45df0 (diff) | |
parent | 3e18d1bb698aa4e992e548007c2ca050aeedb2e5 (diff) |
Merge branch 'stable-linux-ux500-3.2' into stable-android-ux500-3.2
Conflicts:
arch/arm/mach-ux500/board-mop500-pins.c
-rwxr-xr-x | arch/arm/configs/u8500_defconfig | 4 | ||||
-rw-r--r-- | arch/arm/mach-ux500/Kconfig | 11 | ||||
-rw-r--r-- | arch/arm/mach-ux500/Makefile | 1 | ||||
-rwxr-xr-x | arch/arm/mach-ux500/board-mop500-cyttsp.c | 56 | ||||
-rw-r--r-- | arch/arm/mach-ux500/board-mop500-pins.c | 44 | ||||
-rw-r--r-- | arch/arm/mach-ux500/board-mop500-sensors.c | 33 | ||||
-rw-r--r-- | arch/arm/mach-ux500/board-mop500-u8500uib.c | 10 | ||||
-rw-r--r-- | arch/arm/mach-ux500/board-mop500-uib.c | 102 | ||||
-rw-r--r-- | arch/arm/mach-ux500/board-mop500.c | 94 | ||||
-rw-r--r-- | arch/arm/mach-ux500/include/mach/sensors1p.h | 24 | ||||
-rw-r--r-- | arch/arm/mach-ux500/pm/context_arm.S | 50 | ||||
-rw-r--r-- | arch/arm/mach-ux500/sensors1p.c | 298 | ||||
-rw-r--r-- | drivers/hwmon/l3g4200d.c | 22 | ||||
-rw-r--r-- | drivers/hwmon/lsm303dlh_a.c | 27 | ||||
-rw-r--r-- | drivers/hwmon/lsm303dlh_m.c | 40 | ||||
-rw-r--r-- | drivers/hwmon/lsm303dlhc_a.c | 18 | ||||
-rw-r--r-- | drivers/input/keyboard/gpio_keys.c | 13 | ||||
-rw-r--r-- | drivers/input/misc/Kconfig | 9 | ||||
-rw-r--r-- | drivers/input/misc/lps001wp_prs.c | 389 | ||||
-rw-r--r-- | drivers/misc/bh1780gli.c | 12 | ||||
-rw-r--r-- | include/linux/lsm303dlh.h | 2 |
21 files changed, 662 insertions, 597 deletions
diff --git a/arch/arm/configs/u8500_defconfig b/arch/arm/configs/u8500_defconfig index 491b7b932cc..16fc7d572a4 100755 --- a/arch/arm/configs/u8500_defconfig +++ b/arch/arm/configs/u8500_defconfig @@ -30,6 +30,7 @@ CONFIG_DISPLAY_GENERIC_DSI_PRIMARY_VSYNC=y CONFIG_DISPLAY_SONY_ACX424AKP_DSI_PRIMARY=y CONFIG_DISPLAY_AV8100_TERTIARY=y CONFIG_DISPLAY_AV8100_TRIPPLE_BUFFER=y +CONFIG_UX500_GPIO_KEYS=y CONFIG_UX500_SUSPEND=y CONFIG_UX500_SUSPEND_STANDBY=y CONFIG_UX500_SUSPEND_MEM=y @@ -172,6 +173,7 @@ CONFIG_POWER_SUPPLY=y CONFIG_AB8500_BM=y CONFIG_SENSORS_AB8500=y CONFIG_SENSORS_LSM303DLH=y +CONFIG_SENSORS_LSM303DLHC=y CONFIG_SENSORS_L3G4200D=y CONFIG_WATCHDOG=y CONFIG_U8500_WATCHDOG_DEBUG=y @@ -223,7 +225,7 @@ CONFIG_USB_STORAGE=y CONFIG_USB_LIBUSUAL=y CONFIG_USB_GADGET=y CONFIG_USB_GADGET_VBUS_DRAW=500 -CONFIG_USB_GADGET_MUSB_HDRC=m +CONFIG_USB_GADGET_MUSB_HDRC=y CONFIG_USB_ZERO=m CONFIG_USB_ETH=m CONFIG_USB_FILE_STORAGE=m diff --git a/arch/arm/mach-ux500/Kconfig b/arch/arm/mach-ux500/Kconfig index 92a85c202e6..d26d035bedc 100644 --- a/arch/arm/mach-ux500/Kconfig +++ b/arch/arm/mach-ux500/Kconfig @@ -80,12 +80,11 @@ config UX500_DEBUG_UART Choose the UART on which kernel low-level debug messages should be output. -config SENSORS1P_MOP - tristate "HAL and Proximity sensors support" - depends on REGULATOR && (GPIO_STMPE2401 || GPIO_TC35892) - help - Add support for Osram's SFH7741 Proximity Sensor and Samsumg - HED54XXU11 HAL Switch +config UX500_GPIO_KEYS + bool "Use gpio-keys for proximity and hal sensors" + depends on KEYBOARD_GPIO + help + Add proximity and hal sensors as a gpio keyboard. config U5500_MODEM_IRQ bool "Modem IRQ support" diff --git a/arch/arm/mach-ux500/Makefile b/arch/arm/mach-ux500/Makefile index 70c483b9dd8..625d22081ce 100644 --- a/arch/arm/mach-ux500/Makefile +++ b/arch/arm/mach-ux500/Makefile @@ -24,7 +24,6 @@ obj-$(CONFIG_MACH_U8500) += board-mop500.o board-mop500-sdi.o \ board-mop500-u8500uib.o board-mop500-pins.o \ board-mop500-bm.o \ board-pins-sleep-force.o -obj-$(CONFIG_SENSORS1P_MOP) += sensors1p.o obj-$(CONFIG_MACH_U5500) += board-u5500.o board-u5500-sdi.o \ board-u5500-regulators.o \ board-u5500-pins.o diff --git a/arch/arm/mach-ux500/board-mop500-cyttsp.c b/arch/arm/mach-ux500/board-mop500-cyttsp.c index 2aa27ea9b1f..ca33dfd86ab 100755 --- a/arch/arm/mach-ux500/board-mop500-cyttsp.c +++ b/arch/arm/mach-ux500/board-mop500-cyttsp.c @@ -15,16 +15,60 @@ #include <linux/mfd/tc3589x.h> #include <linux/mfd/dbx500-prcmu.h> #include <linux/amba/pl022.h> +#include <linux/lsm303dlh.h> +#include <linux/l3g4200d.h> #include <plat/pincfg.h> #include <mach/hardware.h> #include <mach/irqs.h> #include <mach/irqs-db8500.h> +#include <asm/mach-types.h> #include "pins-db8500.h" #include "board-mop500.h" #include "devices-db8500.h" #define NUM_SSP_CLIENTS 10 +/* + * LSM303DLH accelerometer + magnetometer & L3G4200D Gyroscope sensors + */ +static struct lsm303dlh_platform_data __initdata lsm303dlh_pdata_u8500_r3 = { + .name_a = "lsm303dlh.0", + .name_m = "lsm303dlh.1", + .axis_map_x = 1, + .axis_map_y = 0, + .axis_map_z = 2, + .negative_x = 0, + .negative_y = 0, + .negative_z = 1, +}; + +static struct l3g4200d_gyr_platform_data __initdata l3g4200d_pdata_u8500_r3 = { + .name_gyr = "l3g4200d", + .axis_map_x = 0, + .axis_map_y = 1, + .axis_map_z = 2, + .negative_x = 1, + .negative_y = 0, + .negative_z = 1, +}; +static struct i2c_board_info __initdata mop500_i2c2_devices_u8500_r3[] = { + { + /* LSM303DLH Accelerometer */ + I2C_BOARD_INFO("lsm303dlhc_a", 0x19), + .platform_data = &lsm303dlh_pdata_u8500_r3, + }, + { + /* LSM303DLH Magnetometer */ + I2C_BOARD_INFO("lsm303dlh_m", 0x1E), + .platform_data = &lsm303dlh_pdata_u8500_r3, + }, + { + /* L3G4200D Gyroscope */ + I2C_BOARD_INFO("l3g4200d", 0x68), + .platform_data = &l3g4200d_pdata_u8500_r3, + }, +}; + /* cyttsp_gpio_board_init : configures the touch panel. */ static int cyttsp_plat_init(int on) { @@ -219,8 +263,20 @@ void __init mop500_u8500uib_r3_init(void) mop500_cyttsp_init(); db8500_add_spi2(&mop500_spi2_data); nmk_config_pin((GPIO64_GPIO | PIN_INPUT_PULLUP), false); + if (machine_is_hrefv60()) { + lsm303dlh_pdata_u8500_r3.irq_a1 = HREFV60_ACCEL_INT1_GPIO; + lsm303dlh_pdata_u8500_r3.irq_a2 = HREFV60_ACCEL_INT2_GPIO; + lsm303dlh_pdata_u8500_r3.irq_m = HREFV60_MAGNET_DRDY_GPIO; + } else { + lsm303dlh_pdata_u8500_r3.irq_a1 = GPIO_ACCEL_INT1; + lsm303dlh_pdata_u8500_r3.irq_a2 = GPIO_ACCEL_INT2; + lsm303dlh_pdata_u8500_r3.irq_m = GPIO_MAGNET_DRDY; + } mop500_uib_i2c_add(0, mop500_i2c0_devices_u8500, ARRAY_SIZE(mop500_i2c0_devices_u8500)); mop500_uib_i2c_add(0, mop500_i2c0_devices_u8500, ARRAY_SIZE(mop500_i2c0_devices_u8500)); + + mop500_uib_i2c_add(2, mop500_i2c2_devices_u8500_r3, + ARRAY_SIZE(mop500_i2c2_devices_u8500_r3)); } diff --git a/arch/arm/mach-ux500/board-mop500-pins.c b/arch/arm/mach-ux500/board-mop500-pins.c index da171115533..96f7b084c73 100644 --- a/arch/arm/mach-ux500/board-mop500-pins.c +++ b/arch/arm/mach-ux500/board-mop500-pins.c @@ -17,7 +17,7 @@ #include "pins-db8500.h" #include "pins.h" - +#include "board-mop500.h" #include "board-pins-sleep-force.h" enum custom_pin_cfg_t { @@ -160,9 +160,6 @@ static pin_cfg_t hrefv60_pins[] = { /* DiPro Sensor Interface */ GPIO139_GPIO | PIN_INPUT_PULLUP, /* DIPRO_INT */ - /* HAL SWITCH INTERFACE */ - GPIO145_GPIO | PIN_INPUT_PULLDOWN,/* HAL_SW */ - /* Audio Amplifier Interface */ GPIO149_GPIO | PIN_OUTPUT_HIGH, /* VAUDIO_HF_EN, enable MAX8968 */ @@ -176,9 +173,6 @@ static pin_cfg_t hrefv60_pins[] = { GPIO82_GPIO | PIN_INPUT_PULLUP, /* ACC_INT1 */ GPIO83_GPIO | PIN_INPUT_PULLUP, /* ACC_INT2 */ - /* Proximity Sensor */ - GPIO217_GPIO | PIN_INPUT_PULLUP, - /* SD card detect */ GPIO95_GPIO | PIN_INPUT_PULLUP, }; @@ -411,7 +405,21 @@ static UX500_PINS(mop500_pins_spi2, GPIO217_SPI2_CLK | PIN_OUTPUT_LOW, ); -static struct ux500_pin_lookup mop500_pins[] = { +static UX500_PINS(mop500_pins_sensors1p, + GPIO217_GPIO| PIN_INPUT_PULLUP | + PIN_SLPM_GPIO | PIN_SLPM_INPUT_NOPULL, + GPIO145_GPIO | PIN_INPUT_PULLDOWN | + PIN_SLPM_GPIO | PIN_SLPM_INPUT_NOPULL, + GPIO139_GPIO | PIN_INPUT_PULLUP | + PIN_SLPM_GPIO | PIN_SLPM_INPUT_NOPULL, +); + +static UX500_PINS(mop500_pins_sensors1p_old, + PIN_CFG_INPUT(GPIO_PROX_SENSOR, GPIO, NOPULL), + PIN_CFG_INPUT(GPIO_HAL_SENSOR, GPIO, NOPULL), +); + +static struct ux500_pin_lookup mop500_runtime_pins[] = { PIN_LOOKUP("mcde-dpi", &mop500_pins_mcde_dpi), PIN_LOOKUP("mcde-tvout", &mop500_pins_mcde_tvout), PIN_LOOKUP("av8100-hdmi", &mop500_pins_mcde_hdmi), @@ -427,6 +435,14 @@ static struct ux500_pin_lookup mop500_pins[] = { PIN_LOOKUP("spi2", &mop500_pins_spi2), }; +static struct ux500_pin_lookup mop500_runtime_pins_v60[] = { + PIN_LOOKUP("gpio-keys.0", &mop500_pins_sensors1p), +}; + +static struct ux500_pin_lookup mop500_runtime_pins_old[] = { + PIN_LOOKUP("gpio-keys.0", &mop500_pins_sensors1p_old), +}; + static struct ux500_pin_lookup mop500_ske_pins[] = { PIN_LOOKUP("ske", &mop500_pins_ske), }; @@ -641,7 +657,9 @@ static pin_cfg_t mop500_pins_common_power_save_bank4[] = { GPIO143_GPIO | PIN_SLPM_OUTPUT_LOW | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, GPIO144_GPIO | PIN_SLPM_OUTPUT_HIGH | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + /* 145 - HAL sensor (on v60 and later) */ GPIO145_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO146_GPIO | PIN_SLPM_OUTPUT_LOW | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, GPIO147_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, @@ -769,7 +787,9 @@ static pin_cfg_t mop500_pins_common_power_save_bank6_href60[] = { GPIO215_GPIO | PIN_SLPM_OUTPUT_LOW | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, GPIO216_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + /* 217 - Proximity */ GPIO217_GPIO | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO218_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, GPIO219_GPIO | PIN_SLPM_OUTPUT_LOW | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, @@ -932,8 +952,9 @@ void __init mop500_pins_init(void) nmk_config_pins(mop500_pins_common, ARRAY_SIZE(mop500_pins_common)); - ux500_pins_add(mop500_pins, ARRAY_SIZE(mop500_pins)); + ux500_pins_add(mop500_runtime_pins, ARRAY_SIZE(mop500_runtime_pins)); ux500_pins_add(mop500_ske_pins, ARRAY_SIZE(mop500_ske_pins)); + ux500_pins_add(mop500_runtime_pins_old, ARRAY_SIZE(mop500_runtime_pins_old)); switch (pinsfor) { case PINS_FOR_U9500: @@ -958,7 +979,7 @@ void __init snowball_pins_init(void) nmk_config_pins(mop500_pins_common, ARRAY_SIZE(mop500_pins_common)); - ux500_pins_add(mop500_pins, ARRAY_SIZE(mop500_pins)); + ux500_pins_add(mop500_runtime_pins, ARRAY_SIZE(mop500_runtime_pins)); nmk_config_pins(u8500_pins, ARRAY_SIZE(u8500_pins)); @@ -974,8 +995,9 @@ void __init hrefv60_pins_init(void) nmk_config_pins(mop500_pins_common, ARRAY_SIZE(mop500_pins_common)); - ux500_pins_add(mop500_pins, ARRAY_SIZE(mop500_pins)); + ux500_pins_add(mop500_runtime_pins, ARRAY_SIZE(mop500_runtime_pins)); ux500_pins_add(mop500_ske_pins, ARRAY_SIZE(mop500_ske_pins)); + ux500_pins_add(mop500_runtime_pins_v60, ARRAY_SIZE(mop500_runtime_pins_v60)); nmk_config_pins(hrefv60_pins, ARRAY_SIZE(hrefv60_pins)); diff --git a/arch/arm/mach-ux500/board-mop500-sensors.c b/arch/arm/mach-ux500/board-mop500-sensors.c index bc08e332699..5ee7fec5357 100644 --- a/arch/arm/mach-ux500/board-mop500-sensors.c +++ b/arch/arm/mach-ux500/board-mop500-sensors.c @@ -80,7 +80,7 @@ static struct i2c_board_info __initdata mop500_2_i2c2_devices[] = { static struct i2c_board_info __initdata snowball_i2c2_devices[] = { { /* LSM303DLH Accelerometer */ - I2C_BOARD_INFO("lsm303dlh_a", 0x19), + I2C_BOARD_INFO("lsm303dlhc_a", 0x19), .platform_data = &lsm303dlh_pdata, }, }; @@ -121,6 +121,7 @@ void mop500_sensors_i2c_add(int busnum, struct i2c_board_info const *info, void mop500_sensors_probe_add_lsm303dlh_a(void) { static const int busnum = 2; + int status; struct i2c_adapter *adap; struct i2c_client *client; static const unsigned short i2c_addr_list[] = { @@ -130,6 +131,7 @@ void mop500_sensors_probe_add_lsm303dlh_a(void) I2C_BOARD_INFO("lsm303dlh_a", 0), .platform_data = &lsm303dlh_pdata, }; + union i2c_smbus_data data; adap = i2c_get_adapter(busnum); if (!adap) { @@ -143,6 +145,23 @@ void mop500_sensors_probe_add_lsm303dlh_a(void) pr_err(__FILE__ ": failed to register %s to i2c%d\n", i2c_info.type, busnum); + /* driver is different for LSM3030DLH(0x18) and LSM303DLHC(0x19)*/ + if (i2c_info.addr == 0x19) { + snprintf(i2c_info.type, sizeof(i2c_info.type), "lsm303dlhc_a"); + } + /* + * From the i2c_new_probed_device() function we will come to know + * the adress of the device, so read 0x0F register to get chipID. + * This chipID is used in magnetometer driver to invet co-ordinates. + */ + status = i2c_smbus_xfer(adap, i2c_info.addr , 0 , + I2C_SMBUS_READ, 0x0F , + I2C_SMBUS_BYTE_DATA, &data); + if (status < 0) { + pr_err(__FILE__ ": failed to read 0x0F register\n"); + } + else + lsm303dlh_pdata.chip_id = data.byte; i2c_put_adapter(adap); } @@ -166,20 +185,24 @@ static int __init mop500_sensors_init(void) lsm303dlh_pdata.irq_m = GPIO_MAGNET_DRDY; } - mop500_sensors_i2c_add(2, mop500_i2c2_devices, - ARRAY_SIZE(mop500_i2c2_devices)); - if (machine_is_snowball()) { if (cpu_is_u8500v21()) /* This is ugly but we cant know what address * to use */ mop500_sensors_probe_add_lsm303dlh_a(); - else /* Add the accelerometer with new addr */ + else { + /* Add the accelerometer with new addr */ mop500_sensors_i2c_add(2, snowball_i2c2_devices, ARRAY_SIZE(snowball_i2c2_devices)); + /* For 0x19 accelerometer chip_id is 51*/ + lsm303dlh_pdata.chip_id = 51; + } } else /* none snowball have the old addr */ mop500_sensors_i2c_add(2, mop500_2_i2c2_devices, ARRAY_SIZE(mop500_2_i2c2_devices)); + + mop500_sensors_i2c_add(2, mop500_i2c2_devices, + ARRAY_SIZE(mop500_i2c2_devices)); return 0; } diff --git a/arch/arm/mach-ux500/board-mop500-u8500uib.c b/arch/arm/mach-ux500/board-mop500-u8500uib.c index 20763004c4a..1399c1bcde4 100644 --- a/arch/arm/mach-ux500/board-mop500-u8500uib.c +++ b/arch/arm/mach-ux500/board-mop500-u8500uib.c @@ -42,8 +42,8 @@ static struct lsm303dlh_platform_data __initdata lsm303dlh_pdata_u8500 = { .axis_map_x = 1, .axis_map_y = 0, .axis_map_z = 2, - .negative_x = 1, - .negative_y = 1, + .negative_x = 0, + .negative_y = 0, .negative_z = 1, }; #endif @@ -51,10 +51,10 @@ static struct lsm303dlh_platform_data __initdata lsm303dlh_pdata_u8500 = { #ifdef CONFIG_SENSORS_L3G4200D static struct l3g4200d_gyr_platform_data __initdata l3g4200d_pdata_u8500 = { .name_gyr = "l3g4200d", - .axis_map_x = 1, - .axis_map_y = 0, + .axis_map_x = 0, + .axis_map_y = 1, .axis_map_z = 2, - .negative_x = 0, + .negative_x = 1, .negative_y = 0, .negative_z = 1, }; diff --git a/arch/arm/mach-ux500/board-mop500-uib.c b/arch/arm/mach-ux500/board-mop500-uib.c index 8679b15643c..6dc77d42d86 100644 --- a/arch/arm/mach-ux500/board-mop500-uib.c +++ b/arch/arm/mach-ux500/board-mop500-uib.c @@ -11,9 +11,14 @@ #include <linux/kernel.h> #include <linux/init.h> #include <linux/i2c.h> -#include <mach/hardware.h> #include <asm/mach-types.h> +#include <linux/platform_device.h> +#include <linux/input.h> +#include <linux/gpio_keys.h> +#include <linux/regulator/consumer.h> +#include <mach/hardware.h> +#include "pins.h" #include "board-mop500.h" enum mop500_uib { @@ -129,6 +134,97 @@ int uib_is_u8500uibr3(void) return (type_of_uib == U8500UIB_R3); } + +#ifdef CONFIG_UX500_GPIO_KEYS +static struct gpio_keys_button mop500_gpio_keys[] = { + { + .desc = "SFH7741 Proximity Sensor", + .type = EV_SW, + .code = SW_FRONT_PROXIMITY, + .active_low = 0, + .can_disable = 1, + }, + { + .desc = "HED54XXU11 Hall Effect Sensor", + .type = EV_SW, + .code = SW_LID, /* FIXME arbitrary usage */ + .active_low = 0, + .can_disable = 1, + } +}; + +static struct regulator *gpio_keys_regulator; +static int mop500_gpio_keys_activate(struct device *dev); +static void mop500_gpio_keys_deactivate(struct device *dev); + +static struct gpio_keys_platform_data mop500_gpio_keys_data = { + .buttons = mop500_gpio_keys, + .nbuttons = ARRAY_SIZE(mop500_gpio_keys), + .enable = mop500_gpio_keys_activate, + .disable = mop500_gpio_keys_deactivate, +}; + +static struct platform_device mop500_gpio_keys_device = { + .name = "gpio-keys", + .id = 0, + .dev = { + .platform_data = &mop500_gpio_keys_data, + }, +}; + +static int mop500_gpio_keys_activate(struct device *dev) +{ + gpio_keys_regulator = regulator_get(&mop500_gpio_keys_device.dev, + "vcc"); + if (IS_ERR(gpio_keys_regulator)) { + dev_err(&mop500_gpio_keys_device.dev, "no regulator\n"); + return PTR_ERR(gpio_keys_regulator); + } + regulator_enable(gpio_keys_regulator); + + /* + * Please be aware that the start-up time of the SFH7741 is + * 120 ms and during that time the output is undefined. + */ + + return 0; +} + +static void mop500_gpio_keys_deactivate(struct device *dev) +{ + if (!IS_ERR(gpio_keys_regulator)) { + regulator_disable(gpio_keys_regulator); + regulator_put(gpio_keys_regulator); + } +} + +static __init void mop500_gpio_keys_init(void) +{ + struct ux500_pins *gpio_keys_pins = ux500_pins_get("gpio-keys.0"); + + if (gpio_keys_pins == NULL) { + pr_err("gpio_keys: Fail to get pins\n"); + return; + } + + ux500_pins_enable(gpio_keys_pins); + if (type_of_uib == U8500UIB_R3) + mop500_gpio_keys[0].gpio = PIN_NUM(gpio_keys_pins->cfg[2]); + else + mop500_gpio_keys[0].gpio = PIN_NUM(gpio_keys_pins->cfg[0]); + mop500_gpio_keys[1].gpio = PIN_NUM(gpio_keys_pins->cfg[1]); +} +#else +static inline void mop500_gpio_keys_init(void) { } +#endif + +/* add any platform devices here - TODO */ +static struct platform_device *mop500_uib_platform_devs[] __initdata = { +#ifdef CONFIG_UX500_GPIO_KEYS + &mop500_gpio_keys_device, +#endif +}; + /* * Detect the UIB attached based on the presence or absence of i2c devices. */ @@ -177,7 +273,9 @@ static int __init mop500_uib_init(void) uib = &mop500_uibs[STUIB]; } __mop500_uib_init(uib, "detected"); - + mop500_gpio_keys_init(); + platform_add_devices(mop500_uib_platform_devs, + ARRAY_SIZE(mop500_uib_platform_devs)); return 0; } diff --git a/arch/arm/mach-ux500/board-mop500.c b/arch/arm/mach-ux500/board-mop500.c index ca1677e8b3e..1200db26f75 100644 --- a/arch/arm/mach-ux500/board-mop500.c +++ b/arch/arm/mach-ux500/board-mop500.c @@ -52,7 +52,6 @@ #include <mach/hardware.h> #include <mach/setup.h> #include <mach/devices.h> -#include <mach/sensors1p.h> #ifdef CONFIG_INPUT_AB8500_ACCDET #include <mach/abx500-accdet.h> #endif @@ -654,42 +653,6 @@ static void __init mop500_i2c_init(void) db8500_add_i2c3(&u8500_i2c3_data); } -static struct gpio_keys_button mop500_gpio_keys[] = { - { - .desc = "SFH7741 Proximity Sensor", - .type = EV_SW, - .code = SW_FRONT_PROXIMITY, - .active_low = 0, - .can_disable = 1, - }, - { - .desc = "HED54XXU11 Hall Effect Sensor", - .type = EV_SW, - .code = SW_LID, /* FIXME arbitrary usage */ - .active_low = 0, - .can_disable = 1, - } -}; - -static struct regulator *sensors1p_regulator; -static int mop500_sensors1p_activate(struct device *dev); -static void mop500_sensors1p_deactivate(struct device *dev); - -static struct gpio_keys_platform_data mop500_gpio_keys_data = { - .buttons = mop500_gpio_keys, - .nbuttons = ARRAY_SIZE(mop500_gpio_keys), - .enable = mop500_sensors1p_activate, - .disable = mop500_sensors1p_deactivate, -}; - -static struct platform_device mop500_gpio_keys_device = { - .name = "gpio-keys", - .id = 0, - .dev = { - .platform_data = &mop500_gpio_keys_data, - }, -}; - #ifdef CONFIG_REGULATOR_FIXED_VOLTAGE static struct platform_device snowball_gpio_wlan_vbat_regulator_device = { .name = "reg-fixed-voltage", @@ -708,24 +671,6 @@ static struct platform_device snowball_gpio_en_3v3_regulator_device = { }; #endif -static int mop500_sensors1p_activate(struct device *dev) -{ - sensors1p_regulator = regulator_get(&mop500_gpio_keys_device.dev, - "vcc"); - if (IS_ERR(sensors1p_regulator)) { - dev_err(&mop500_gpio_keys_device.dev, "no regulator\n"); - return PTR_ERR(sensors1p_regulator); - } - regulator_enable(sensors1p_regulator); - return 0; -} - -static void mop500_sensors1p_deactivate(struct device *dev) -{ - regulator_disable(sensors1p_regulator); - regulator_put(sensors1p_regulator); -} - #ifdef CONFIG_LEDS_PWM static struct led_pwm pwm_leds_data[] = { [0] = { @@ -873,30 +818,6 @@ struct platform_device u8500_sim_detect_device = { }; #endif -#ifdef CONFIG_SENSORS1P_MOP -static struct sensors1p_config sensors1p_config = { - /* SFH7741 */ - .proximity = { - .pin = EGPIO_PIN_7, - .startup_time = 120, /* ms */ - .regulator = "v-proximity", - }, - /* HED54XXU11 */ - .hal = { - .pin = EGPIO_PIN_8, - .startup_time = 100, /* Actually, I have no clue. */ - .regulator = "v-hal", - }, -}; - -struct platform_device sensors1p_device = { - .name = "sensors1p", - .dev = { - .platform_data = (void *)&sensors1p_config, - }, -}; -#endif - #ifdef CONFIG_CRYPTO_DEV_UX500 static struct cryp_platform_data u8500_cryp1_platform_data = { .mem_to_engine = { @@ -937,9 +858,6 @@ static struct hash_platform_data u8500_hash1_platform_data = { /* add any platform devices here - TODO */ static struct platform_device *mop500_platform_devs[] __initdata = { -#ifdef CONFIG_SENSORS1P_MOP - &sensors1p_device, -#endif #ifdef CONFIG_U8500_SIM_DETECT &u8500_sim_detect_device, #endif @@ -957,7 +875,6 @@ static struct platform_device *mop500_platform_devs[] __initdata = { #ifdef CONFIG_STE_TRACE_MODEM &u8500_trace_modem, #endif - &mop500_gpio_keys_device, #ifdef CONFIG_LEDS_PWM &ux500_leds_device, #endif @@ -1209,9 +1126,6 @@ static struct platform_device *snowball_platform_devs[] __initdata = { static void __init mop500_init_machine(void) { - mop500_gpio_keys[0].gpio = GPIO_PROX_SENSOR; - mop500_gpio_keys[1].gpio = GPIO_HAL_SENSOR; - u8500_init_devices(); mop500_pins_init(); @@ -1290,14 +1204,6 @@ static void __init snowball_init_machine(void) static void __init hrefv60_init_machine(void) { - /* - * The HREFv60 board removed a GPIO expander and routed - * all these GPIO pins to the internal GPIO controller - * instead. - */ - mop500_gpio_keys[0].gpio = HREFV60_PROX_SENSE_GPIO; - mop500_gpio_keys[1].gpio = HREFV60_HAL_SW_GPIO; - #ifdef CONFIG_INPUT_AB8500_ACCDET /* * On boards hrefpv60 and later, the accessory insertion/removal, diff --git a/arch/arm/mach-ux500/include/mach/sensors1p.h b/arch/arm/mach-ux500/include/mach/sensors1p.h deleted file mode 100644 index 544e1d8bab5..00000000000 --- a/arch/arm/mach-ux500/include/mach/sensors1p.h +++ /dev/null @@ -1,24 +0,0 @@ - -/* - * Copyright (C) 2009-2010 ST-Ericsson AB - * License terms: GNU General Public License (GPL) version 2 - * Header file for 1 pin gpio sensors; - * Author: Jonas Aaberg <jonas.aberg@stericsson.com> - * - */ - -#ifndef __ASM_ARCH_SFH7741_H -#define __ASM_ARCH_SFH7741_H - -struct sensor_config { - int pin; - int startup_time; /* in ms */ - char regulator[32]; -}; - -struct sensors1p_config { - struct sensor_config hal; - struct sensor_config proximity; -}; - -#endif diff --git a/arch/arm/mach-ux500/pm/context_arm.S b/arch/arm/mach-ux500/pm/context_arm.S index 55e2accc85f..edb894d6a35 100644 --- a/arch/arm/mach-ux500/pm/context_arm.S +++ b/arch/arm/mach-ux500/pm/context_arm.S @@ -46,10 +46,12 @@ ENTRY(context_save_arm_registers) stmfd sp!, {r1, r2, r3, lr} @ Save on stack ldr r1, [r0] @ Read backup stack pointer - stmia r1, {sp, lr}^ @ Store user mode sp and lr +ARM( stmia r1, {sp, lr}^ ) @ Store user mode sp and lr @ registers - add r1, r1, #8 @ Update backup pointer (not +ARM( add r1, r1, #8 ) @ Update backup pointer (not @ done in previous instruction) +THUMB( str sp, [r1], #+4 ) +THUMB( str lr, [r1], #+4 ) mrs r2, cpsr @ Get CPSR SAVE_AND_INCREMENT r2 r1 @ Save CPSR register @@ -67,23 +69,32 @@ ENTRY(context_save_arm_registers) orr r3, r2, #0x11 @ Save FIQ mode registers msr cpsr_cxsf, r3 mrs r3, spsr - stmia r1!, {r3, r8-r14} +ARM( stmia r1!, {r3, r8-r14} ) +THUMB( stmia r1!, {r3, r8-r12, r14} ) +THUMB( str r13, [r1], #+4 ) + orr r3, r2, #0x12 @ Save IRQ mode registers msr cpsr_cxsf, r3 mrs r3, spsr - stmia r1!, {r3, r13, r14} +ARM( stmia r1!, {r3, r13, r14} ) +THUMB( stmia r1!, {r3, r14} ) +THUMB( str r13, [r1], #+4 ) orr r3, r2, #0x17 @ Save abort mode registers + @ common mode registers msr cpsr_cxsf, r3 mrs r3, spsr - stmia r1!, {r3, r13, r14} +ARM( stmia r1!, {r3, r13, r14} ) +THUMB( stmia r1!, {r3, r14} ) +THUMB( str r13, [r1], #+4 ) orr r3, r2, #0x1B @ Save undef mode registers msr cpsr_cxsf, r3 mrs r3, spsr - stmia r1!, {r3, r13, r14} +ARM( stmia r1!, {r3, r13, r14} ) +THUMB( stmia r1!, {r3, r14} ) +THUMB( str r13, [r1], #+4 ) orr r3, r2, #0x13 @ Return to supervisor mode msr cpsr_cxsf, r3 @@ -120,30 +131,41 @@ ENTRY(context_restore_arm_registers) orr r3, r2, #0x1b @ Restore undef mode registers msr cpsr_cxsf, r3 - ldmdb r1!, {r3, r13, r14} +ARM( ldmdb r1!, {r3, r13, r14} ) +THUMB( ldr r13, [r1], #-4 ) +THUMB( ldmdb r1!, {r3, r14} ) msr spsr_cxsf, r3 orr r3, r2, #0x17 @ Restore abort mode registers msr cpsr_cxsf, r3 - ldmdb r1!, {r3, r13, r14} +ARM( ldmdb r1!, {r3, r13, r14} ) +THUMB( ldr r13, [r1], #-4 ) +THUMB( ldmdb r1!, {r3, r14} ) msr spsr_cxsf, r3 orr r3, r2, #0x12 @ Restore IRQ mode registers msr cpsr_cxsf, r3 - ldmdb r1!, {r3, r13, r14} +ARM( ldmdb r1!, {r3, r13, r14} ) +THUMB( ldr r13, [r1], #-4 ) +THUMB( ldmdb r1!, {r3, r14} ) msr spsr_cxsf, r3 orr r3, r2, #0x11 @ Restore FIQ mode registers msr cpsr_cxsf, r3 - ldmdb r1!, {r3, r8-r14} +ARM( ldmdb r1!, {r3, r8-r14} ) +THUMB( ldr r13, [r1], #-4 ) +THUMB( ldmdb r1!, {r3, r8-r12, r14} ) + msr spsr_cxsf, r3 DECREMENT_AND_RESTORE r1 r3 @ Restore cpsr register msr cpsr_cxsf, r3 - ldmdb r1, {sp, lr}^ @ Restore sp and lr registers - sub r1, r1, #8 @ Update backup pointer (not +ARM( ldmdb r1, {sp, lr}^ ) @ Restore sp and lr registers +ARM( sub r1, r1, #8 ) @ Update backup pointer (not @ done in previous instruction) +THUMB( ldr lr, [r1], #-4 ) +THUMB( ldr sp, [r1], #-4 ) str r1, [r0] @ Write backup stack pointer ldmfd sp!, {r1, r2, r3, pc} @ Restore registers and return @@ -312,7 +334,9 @@ wayLoopL1clean: lineLoopL1clean: mov r2, r1, lsl #30 @ TODO: OK to hard-code @ SoC-specific L1 cache details? - add r2, r0, lsl #5 + mov r3, r0, lsl #5 + add r2, r3 +@ add r2, r0, lsl #5 mcr p15, 0, r2, c7, c10, 2 @ Clean cache by set/way add r0, r0, #1 cmp r0, #256 @ TODO: Ok with hard-coded diff --git a/arch/arm/mach-ux500/sensors1p.c b/arch/arm/mach-ux500/sensors1p.c deleted file mode 100644 index e7f4642b1d9..00000000000 --- a/arch/arm/mach-ux500/sensors1p.c +++ /dev/null @@ -1,298 +0,0 @@ - -/* - * Copyright (C) 2009-2010 ST-Ericsson AB - * License terms: GNU General Public License (GPL) version 2 - * Simple userspace interface for - * Proximity Sensor Osram SFH 7741 and HAL switch Samsung HED54XXU11 - * Author: Jonas Aaberg <jonas.aberg@stericsson.com> - * - * This driver is only there for making Android happy. It is not ment - * for mainline. - */ - - -#include <linux/platform_device.h> -#include <linux/sysfs.h> -#include <linux/gpio.h> -#include <linux/delay.h> -#include <linux/jiffies.h> -#include <linux/slab.h> -#include <linux/regulator/consumer.h> -#include <linux/err.h> - -#include <mach/sensors1p.h> - -struct sensor { - struct regulator *regulator; - int pin; - int startup_time; - int active; - u64 when_enabled; -}; - -struct sensors1p { - struct sensor hal; - struct sensor proximity; -}; - -static int sensors1p_power_write(struct device *dev, - struct sensor *s, const char *buf) -{ - int val; - - if (sscanf(buf, "%d", &val) != 1) - return -EINVAL; - - if (val != 0 && val != 1) - return -EINVAL; - - if (val != s->active) { - if (val) { - regulator_enable(s->regulator); - s->when_enabled = get_jiffies_64() + - msecs_to_jiffies(s->startup_time); - } else - regulator_disable(s->regulator); - } - s->active = val; - - return strnlen(buf, PAGE_SIZE); - -} - -static ssize_t sensors1p_sysfs_hal_active_set(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - - - struct sensors1p *s = platform_get_drvdata(container_of(dev, - struct platform_device, - dev)); - return sensors1p_power_write(dev, &s->hal, buf); - -} - -static ssize_t sensors1p_sysfs_proximity_active_set(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t count) -{ - - - struct sensors1p *s = platform_get_drvdata(container_of(dev, - struct platform_device, - dev)); - return sensors1p_power_write(dev, &s->proximity, buf); - -} - -static ssize_t sensors1p_sysfs_hal_active_get(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct sensors1p *s = platform_get_drvdata(container_of(dev, - struct platform_device, - dev)); - return sprintf(buf, "%d", s->hal.active); -} - -static ssize_t sensors1p_sysfs_proximity_active_get(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct sensors1p *s = platform_get_drvdata(container_of(dev, - struct platform_device, - dev)); - return sprintf(buf, "%d", s->proximity.active); -} - -static int sensors1p_read(struct device *dev, struct sensor *s, char *buf) -{ - int ret; - - if (!s->active) - return -EINVAL; - - /* Only wait if read() is called before the sensor is up and running - * Since jiffies wraps, always sleep maximum time. - */ - if (time_before64(get_jiffies_64(), s->when_enabled)) - mdelay(s->startup_time); - - /* For some odd reason, setting direction in the probe function fails */ - ret = gpio_direction_input(s->pin); - - if (ret) - dev_err(dev, "Failed to set GPIO pin %d to input.\n", s->pin); - else - ret = gpio_get_value(s->pin); - - return sprintf(buf, "%d", ret); -} - -static ssize_t sensors1p_sysfs_hal_show(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct sensors1p *s = platform_get_drvdata(container_of(dev, - struct platform_device, - dev)); - return sensors1p_read(dev, &s->hal, buf); -} - -static ssize_t sensors1p_sysfs_proximity_show(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct sensors1p *s = platform_get_drvdata(container_of(dev, - struct platform_device, - dev)); - return sensors1p_read(dev, &s->proximity, buf); -} - -static DEVICE_ATTR(proximity_activate, 0666, - sensors1p_sysfs_proximity_active_get, - sensors1p_sysfs_proximity_active_set); -static DEVICE_ATTR(hal_activate, 0666, - sensors1p_sysfs_hal_active_get, - sensors1p_sysfs_hal_active_set); -static DEVICE_ATTR(proximity, 0444, sensors1p_sysfs_proximity_show, NULL); -static DEVICE_ATTR(hal, 0444, sensors1p_sysfs_hal_show, NULL); - -static struct attribute *sensors1p_attrs[] = { - &dev_attr_proximity_activate.attr, - &dev_attr_hal_activate.attr, - &dev_attr_proximity.attr, - &dev_attr_hal.attr, - NULL, -}; - -static struct attribute_group sensors1p_attr_group = { - .name = NULL, - .attrs = sensors1p_attrs, -}; - -static int __init sensors1p_probe(struct platform_device *pdev) -{ - int err = -EINVAL; - struct sensors1p_config *c; - struct sensors1p *s = NULL; - - if (!pdev) - goto out; - - c = pdev->dev.platform_data; - - if (c == NULL) { - dev_err(&pdev->dev, "Error: Missconfigured.\n"); - goto out; - } - - s = kzalloc(sizeof(struct sensors1p), GFP_KERNEL); - - if (s == NULL) { - dev_err(&pdev->dev, - "Could not allocate struct memory!\n"); - err = -ENOMEM; - goto out; - } - - s->hal.pin = c->hal.pin; - err = gpio_request(c->hal.pin, "hal sensor"); - if (err < 0) { - dev_err(&pdev->dev, "gpio_request failed with err: %d", err); - goto err_hal_gpio; - } - - s->proximity.pin = c->proximity.pin; - err = gpio_request(c->proximity.pin, "proximity sensor"); - if (err < 0) { - dev_err(&pdev->dev, "gpio_request failed with err: %d", err); - goto err_proximity_gpio; - } - - s->hal.startup_time = c->hal.startup_time; - s->proximity.startup_time = c->proximity.startup_time; - - - s->hal.regulator = regulator_get(&pdev->dev, c->hal.regulator); - - if (IS_ERR(s->hal.regulator)) { - dev_err(&pdev->dev, "regulator_get(\"%s\") failed.\n", - c->hal.regulator); - err = PTR_ERR(s->hal.regulator); - goto err_hal_reg; - } - s->proximity.regulator = regulator_get(&pdev->dev, - c->proximity.regulator); - - if (IS_ERR(s->proximity.regulator)) { - dev_err(&pdev->dev, "regulator_get(\"%s\") failed.\n", - c->proximity.regulator); - err = PTR_ERR(s->proximity.regulator); - goto err_proximity_reg; - } - - err = sysfs_create_group(&pdev->dev.kobj, &sensors1p_attr_group); - - if (err) { - dev_err(&pdev->dev, "Failed to create sysfs entries.\n"); - goto err_sysfs; - } - - platform_set_drvdata(pdev, s); - - return 0; - -err_sysfs: - regulator_put(s->proximity.regulator); -err_proximity_reg: - regulator_put(s->hal.regulator); -err_hal_reg: - gpio_free(s->proximity.pin); -err_proximity_gpio: - gpio_free(s->hal.pin); -err_hal_gpio: - kfree(s); -out: - return err; -} - -static int __exit sensors1p_remove(struct platform_device *pdev) -{ - struct sensors1p *s = platform_get_drvdata(pdev); - - sysfs_remove_group(&pdev->dev.kobj, &sensors1p_attr_group); - gpio_free(s->hal.pin); - gpio_free(s->proximity.pin); - regulator_put(s->hal.regulator); - regulator_put(s->proximity.regulator); - kfree(s); - return 0; -} - -static struct platform_driver sensors1p_driver = { - .remove = __exit_p(sensors1p_remove), - .driver = { - .name = "sensors1p", - .owner = THIS_MODULE, - }, -}; - -static int __init sensors1p_init(void) -{ - return platform_driver_probe(&sensors1p_driver, sensors1p_probe); -} - -static void __exit sensors1p_exit(void) -{ - platform_driver_unregister(&sensors1p_driver); -} - -late_initcall(sensors1p_init); -module_exit(sensors1p_exit); - -MODULE_AUTHOR("Jonas Aaberg <jonas.aberg@stericsson.com>"); -MODULE_DESCRIPTION("One pin gpio sensors driver (Proximity+HAL)"); -MODULE_LICENSE("GPLv2"); diff --git a/drivers/hwmon/l3g4200d.c b/drivers/hwmon/l3g4200d.c index fcac3afc044..c07baa09595 100644 --- a/drivers/hwmon/l3g4200d.c +++ b/drivers/hwmon/l3g4200d.c @@ -30,6 +30,7 @@ #define CTRL_REG3 0x22 /* CTRL_REG3 */ #define CTRL_REG4 0x23 /* CTRL_REG4 */ #define CTRL_REG5 0x24 /* CTRL_REG5 */ +#define OUT_TEMP 0x26 /* OUT_TEMP */ #define AXISDATA_REG 0x28 @@ -401,6 +402,24 @@ static ssize_t l3g4200d_store_powermode(struct device *dev, return count; } +static ssize_t l3g4200d_show_gyrotemp(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct platform_device *pdev = to_platform_device(dev); + struct l3g4200d_data *ddata = platform_get_drvdata(pdev); + int ret; + + if (ddata->powermode == PM_OFF || + ddata->device_status == DEVICE_SUSPENDED) + return -EINVAL; + + ret = l3g4200d_read(ddata, OUT_TEMP, "OUT_TEMP"); + if (ret < 0) + return ret; + + return sprintf(buf, "%d\n", ret); +} + static DEVICE_ATTR(gyrodata, S_IRUGO, l3g4200d_show_gyrodata, NULL); static DEVICE_ATTR(range, S_IRUGO | S_IWUGO, @@ -412,11 +431,14 @@ static DEVICE_ATTR(datarate, S_IRUGO | S_IWUGO, static DEVICE_ATTR(powermode, S_IRUGO | S_IWUGO, l3g4200d_show_powermode, l3g4200d_store_powermode); +static DEVICE_ATTR(gyrotemp, S_IRUGO, l3g4200d_show_gyrotemp, NULL); + static struct attribute *l3g4200d_attributes[] = { &dev_attr_gyrodata.attr, &dev_attr_range.attr, &dev_attr_datarate.attr, &dev_attr_powermode.attr, + &dev_attr_gyrotemp.attr, NULL }; diff --git a/drivers/hwmon/lsm303dlh_a.c b/drivers/hwmon/lsm303dlh_a.c index 65e92dfb0ff..ec7b5fbc803 100644 --- a/drivers/hwmon/lsm303dlh_a.c +++ b/drivers/hwmon/lsm303dlh_a.c @@ -38,6 +38,9 @@ #endif #include <linux/lsm303dlh.h> +#ifdef CONFIG_HAS_EARLYSUSPEND +#include <linux/earlysuspend.h> +#endif #include <linux/regulator/consumer.h> /* lsm303dlh accelerometer registers */ @@ -198,6 +201,9 @@ struct lsm303dlh_a_data { unsigned char interrupt_configure[2]; unsigned char interrupt_duration[2]; unsigned char interrupt_threshold[2]; +#ifdef CONFIG_HAS_EARLYSUSPEND + struct early_suspend early_suspend; +#endif int device_status; int id; }; @@ -288,6 +294,7 @@ static int lsm303dlh_a_restore(struct lsm303dlh_a_data *ddata) if (ddata->regulator) regulator_enable(ddata->regulator); + /* BDU should be enabled by default/recommened */ reg = ddata->range; reg |= LSM303DLH_A_CR4_BDU_MASK; @@ -762,6 +769,7 @@ static ssize_t lsm303dlh_a_store_range(struct device *dev, ddata->shift_adjust = SHIFT_ADJ_8G; break; default: + mutex_unlock(&ddata->lock); return -EINVAL; } @@ -835,10 +843,15 @@ static ssize_t lsm303dlh_a_store_mode(struct device *dev, data = lsm303dlh_a_read(ddata, CTRL_REG1, "CTRL_REG1"); + /* + * If chip doesn't get reset during suspend/resume, + * x,y and z axis bits are getting cleared,so set + * these bits to get x,y,z axis data. + */ + data |= LSM303DLH_A_CR1_AXIS_ENABLE; data &= ~LSM303DLH_A_CR1_PM_MASK; ddata->mode = val; - data |= ((val << LSM303DLH_A_CR1_PM_BIT) & LSM303DLH_A_CR1_PM_MASK); error = lsm303dlh_a_write(ddata, CTRL_REG1, data, "CTRL_REG1"); @@ -1094,6 +1107,12 @@ static int __devinit lsm303dlh_a_probe(struct i2c_client *client, } if (ddata->regulator) { + /* + * 0.83 milliamps typical with magnetic sensor setting ODR = + * 7.5 Hz, Accelerometer sensor ODR = 50 Hz. Double for + * safety. + */ + regulator_set_optimum_mode(ddata->regulator, 830 * 2); regulator_enable(ddata->regulator); ddata->device_status = DEVICE_ON; } @@ -1327,9 +1346,9 @@ static struct i2c_driver lsm303dlh_a_driver = { .id_table = lsm303dlh_a_id, .driver = { .name = "lsm303dlh_a", - #if (!defined(CONFIG_HAS_EARLYSUSPEND) && defined(CONFIG_PM)) - .pm = &lsm303dlh_a_dev_pm_ops, - #endif +#if (!defined(CONFIG_HAS_EARLYSUSPEND) && defined(CONFIG_PM)) + .pm = &lsm303dlh_a_dev_pm_ops, +#endif }, }; diff --git a/drivers/hwmon/lsm303dlh_m.c b/drivers/hwmon/lsm303dlh_m.c index 98704dc5a0b..af486d23ee1 100644 --- a/drivers/hwmon/lsm303dlh_m.c +++ b/drivers/hwmon/lsm303dlh_m.c @@ -39,6 +39,9 @@ #include <linux/lsm303dlh.h> #include <linux/regulator/consumer.h> +#ifdef CONFIG_HAS_EARLYSUSPEND +#include <linux/earlysuspend.h> +#endif #include <linux/kernel.h> /* lsm303dlh magnetometer registers */ @@ -130,6 +133,9 @@ #define DEVICE_ON 1 #define DEVICE_SUSPENDED 2 +/* device CHIP ID defines */ +#define LSM303DLHC_CHIP_ID 51 + /** * struct lsm303dlh_m_data - data structure used by lsm303dlh_m driver * @client: i2c client @@ -161,6 +167,9 @@ struct lsm303dlh_m_data { unsigned char mode; unsigned char rate; unsigned char range; +#ifdef CONFIG_HAS_EARLYSUSPEND + struct early_suspend early_suspend; +#endif int device_status; }; @@ -334,16 +343,16 @@ static int lsm303dlh_m_xyz_read(struct lsm303dlh_m_data *ddata) ddata->data[2] = (short) (((xyz_data[4]) << 8) | xyz_data[5]); -#ifdef SENSORS_LSM303DLHC - /* - * the out registers are in x, z and y order - * so swap y and z values - */ - temp = ddata->data[1]; - ddata->data[1] = ddata->data[2]; - ddata->data[2] = temp; -#endif - + /* check if chip is DHLC */ + if (ddata->pdata.chip_id == LSM303DLHC_CHIP_ID) { + /* + * the out registers are in x, z and y order + * so swap y and z values + */ + temp = ddata->data[1]; + ddata->data[1] = ddata->data[2]; + ddata->data[2] = temp; + } /* taking orientation of x,y,z axis into account*/ ddata->data[ddata->pdata.axis_map_x] = ddata->pdata.negative_x ? @@ -516,6 +525,7 @@ static ssize_t lsm303dlh_m_store_range(struct device *dev, z_gain = Z_GAIN_8_1; break; default: + mutex_unlock(&ddata->lock); return -EINVAL; } @@ -690,6 +700,12 @@ static int __devinit lsm303dlh_m_probe(struct i2c_client *client, } if (ddata->regulator) { + /* + * 0.83 milliamps typical with magnetic sensor setting ODR = + * 7.5 Hz, Accelerometer sensor ODR = 50 Hz. Double for + * safety. + */ + regulator_set_optimum_mode(ddata->regulator, 830 * 2); regulator_enable(ddata->regulator); ddata->device_status = DEVICE_ON; } @@ -884,9 +900,9 @@ static struct i2c_driver lsm303dlh_m_driver = { .id_table = lsm303dlh_m_id, .driver = { .name = "lsm303dlh_m", - #if (!defined(CONFIG_HAS_EARLYSUSPEND) && defined(CONFIG_PM)) +#if (!defined(CONFIG_HAS_EARLYSUSPEND) && defined(CONFIG_PM)) .pm = &lsm303dlh_m_dev_pm_ops, - #endif +#endif }, }; diff --git a/drivers/hwmon/lsm303dlhc_a.c b/drivers/hwmon/lsm303dlhc_a.c index 17c74595ff2..7d34e76731d 100644 --- a/drivers/hwmon/lsm303dlhc_a.c +++ b/drivers/hwmon/lsm303dlhc_a.c @@ -6,6 +6,7 @@ * Licence terms: GNU General Public Licence (GPL) version 2 */ +#include <linux/module.h> #include <linux/i2c.h> #include <linux/mutex.h> #include <linux/slab.h> @@ -314,8 +315,10 @@ static ssize_t lsm303dlhc_a_store_range(struct device *dev, error = lsm303dlhc_a_write(ddata, CTRL_REG4, ddata->range, "CTRL_REG4"); - if (error < 0) + if (error < 0) { + mutex_unlock(&ddata->lock); return error; + } switch (val) { case LSM303DLHC_A_RANGE_2G: @@ -331,6 +334,7 @@ static ssize_t lsm303dlhc_a_store_range(struct device *dev, ddata->shift_adjust = SHIFT_ADJ_16G; break; default: + mutex_unlock(&ddata->lock); return -EINVAL; } @@ -400,6 +404,13 @@ static ssize_t lsm303dlhc_a_store_mode(struct device *dev, data = lsm303dlhc_a_read(ddata, CTRL_REG1, "CTRL_REG1"); + /* + * If chip doesn't get reset during suspend/resume, + * x,y and z axis bits are getting cleared,so set + * these bits to get x,y,z data. + */ + data |= LSM303DLHC_A_CR1_AXIS_ENABLE; + data &= ~LSM303DLHC_A_CR1_MODE_MASK; ddata->mode = val; @@ -518,6 +529,11 @@ static int __devinit lsm303dlhc_a_probe(struct i2c_client *client, } if (adata->regulator) { + /* + * 130 microamps typical with magnetic sensor setting ODR = 7.5 + * Hz, Accelerometer sensor ODR = 50 Hz. Double for safety. + */ + regulator_set_optimum_mode(adata->regulator, 130 * 2); regulator_enable(adata->regulator); adata->device_status = DEVICE_ON; } diff --git a/drivers/input/keyboard/gpio_keys.c b/drivers/input/keyboard/gpio_keys.c index ed1ed469d08..523ef6cd03c 100644 --- a/drivers/input/keyboard/gpio_keys.c +++ b/drivers/input/keyboard/gpio_keys.c @@ -42,6 +42,8 @@ struct gpio_keys_drvdata { struct input_dev *input; struct mutex disable_lock; unsigned int n_buttons; + bool enabled; + bool enable_after_suspend; int (*enable)(struct device *dev); void (*disable)(struct device *dev); struct gpio_button_data data[0]; @@ -437,6 +439,7 @@ static int gpio_keys_open(struct input_dev *input) { struct gpio_keys_drvdata *ddata = input_get_drvdata(input); + ddata->enabled = true; return ddata->enable ? ddata->enable(input->dev.parent) : 0; } @@ -446,6 +449,7 @@ static void gpio_keys_close(struct input_dev *input) if (ddata->disable) ddata->disable(input->dev.parent); + ddata->enabled = false; } /* @@ -578,6 +582,7 @@ static int __devinit gpio_keys_probe(struct platform_device *pdev) ddata->n_buttons = pdata->nbuttons; ddata->enable = pdata->enable; ddata->disable = pdata->disable; + ddata->enabled = false; mutex_init(&ddata->disable_lock); platform_set_drvdata(pdev, ddata); @@ -709,6 +714,10 @@ static int gpio_keys_suspend(struct device *dev) enable_irq_wake(irq); } } + } else { + ddata->enable_after_suspend = ddata->enabled; + if (ddata->enabled) + gpio_keys_close(ddata->input); } return 0; @@ -729,6 +738,10 @@ static int gpio_keys_resume(struct device *dev) gpio_keys_report_event(&ddata->data[i]); } + + if (!device_may_wakeup(dev) && ddata->enable_after_suspend) + gpio_keys_open(ddata->input); + input_sync(ddata->input); return 0; diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig index 8a70b56ae87..8b6dc6b9b1a 100644 --- a/drivers/input/misc/Kconfig +++ b/drivers/input/misc/Kconfig @@ -307,6 +307,15 @@ config INPUT_LPS001WP This is a pressure sensor connected to I2C, mounted on the snowball and other ST-E boards +config LPS001WP_INPUT_DEVICE + bool "ST LPS001WP INPUT DEVICE" + depends on INPUT_LPS001WP + default n + help + This driver allows device to be used as an input device + need to be enabled only when input device support + is required. + config INPUT_POWERMATE tristate "Griffin PowerMate and Contour Jog support" depends on USB_ARCH_HAS_HCD diff --git a/drivers/input/misc/lps001wp_prs.c b/drivers/input/misc/lps001wp_prs.c index cb60762ac61..1618dfaa16f 100644 --- a/drivers/input/misc/lps001wp_prs.c +++ b/drivers/input/misc/lps001wp_prs.c @@ -49,12 +49,12 @@ #include <linux/regulator/consumer.h> #include <linux/input/lps001wp.h> - - +#ifdef CONFIG_HAS_EARLYSUSPEND +#include <linux/earlysuspend.h> +#endif #define DEBUG 1 - #define PR_ABS_MAX 0xffff #define PR_ABS_MIN 0x0000 #define PR_DLT_MAX 0x7ffff @@ -68,7 +68,7 @@ #define OUTDATA_REG 0x28 -#define INDATA_REG 0X30 +#define REF_PRESS_REG 0X30 #define WHOAMI_LPS001WP_PRS 0xBA /* Expctd content for WAI */ @@ -83,7 +83,7 @@ #define PRESS_OUT_L OUTDATA_REG -#define REF_P_L INDATA_REG /* pressure reference */ +#define REF_P_L REF_PRESS_REG /* pressure reference */ #define REF_P_H 0x31 /* pressure reference */ #define THS_P_L 0x32 /* pressure threshold */ #define THS_P_H 0x33 /* pressure threshold */ @@ -97,9 +97,8 @@ /* Barometer and Termometer output data rate ODR */ #define LPS001WP_PRS_ODR_MASK 0x30 /* Mask to access odr bits only */ #define LPS001WP_PRS_ODR_7_1 0x00 /* 7Hz baro and 1Hz term ODR */ -#define LPS001WP_PRS_ODR_7_7 0x01 /* 7Hz baro and 7Hz term ODR */ -#define LPS001WP_PRS_ODR_12_12 0x11 /* 12.5Hz baro and 12.5Hz term ODR */ - +#define LPS001WP_PRS_ODR_7_7 0x10 /* 7Hz baro and 7Hz term ODR */ +#define LPS001WP_PRS_ODR_12_12 0x30 /* 12.5Hz baro and 12.5Hz term ODR */ #define LPS001WP_PRS_ENABLE_MASK 0x40 /* */ #define LPS001WP_PRS_DIFF_MASK 0x08 @@ -145,14 +144,36 @@ static const struct { {1000, LPS001WP_PRS_ODR_7_1 }, }; +/** + * struct lps001wp_prs_data - data structure used by lps001wp_prs driver + * @client: i2c client + * @pdata: lsm303dlh platform data + * @lock: mutex lock for sysfs operations + * @input_work: work queue to read sensor data + * @input_dev: input device + * @regulator: regulator + * @early_suspend: early suspend structure + * @hw_initialized: saves hw initialisation status + * @hw_working: saves hw status + * @diff_enabled: store value of diff enable + * @lpowmode_enabled: flag to set lowpower mode + * @enabled: to store mode of device + * @on_before_suspend: to store status of device during suspend + * @resume_state:store regester values + * @reg_addr: stores reg address to debug + */ struct lps001wp_prs_data { struct i2c_client *client; struct lps001wp_prs_platform_data *pdata; struct mutex lock; +#ifdef CONFIG_LPS001WP_INPUT_DEVICE struct delayed_work input_work; - struct input_dev *input_dev; +#endif +#ifdef CONFIG_HAS_EARLYSUSPEND + struct early_suspend early_suspend; +#endif int hw_initialized; /* hw_working=-1 means not tested yet */ @@ -178,6 +199,11 @@ struct outputdata { s16 deltapress; }; +#ifdef CONFIG_HAS_EARLYSUSPEND +static void lps001wp_prs_early_suspend(struct early_suspend *data); +static void lps001wp_prs_late_resume(struct early_suspend *data); +#endif + static int lps001wp_prs_i2c_read(struct lps001wp_prs_data *prs, u8 *buf, int len) @@ -246,30 +272,10 @@ static int lps001wp_prs_i2c_write(struct lps001wp_prs_data *prs, return err; } -static int lps001wp_prs_i2c_update(struct lps001wp_prs_data *prs, - u8 reg_address, u8 mask, u8 new_bit_values) -{ - int err = -1; - u8 rdbuf[1] = { reg_address }; - u8 wrbuf[2] = { reg_address , 0x00 }; - - u8 init_val; - u8 updated_val; - err = lps001wp_prs_i2c_read(prs, rdbuf, 1); - if (!(err < 0)) { - init_val = rdbuf[0]; - updated_val = ((mask & new_bit_values) | ((~mask) & init_val)); - wrbuf[1] = updated_val; - err = lps001wp_prs_i2c_write(prs, wrbuf, 2); - } - return err; -} -/* */ - static int lps001wp_prs_register_write(struct lps001wp_prs_data *prs, u8 *buf, u8 reg_address, u8 new_value) { - int err = -1; + int err = -EINVAL; /* Sets configuration register at reg_address * NOTE: this is a straight overwrite */ @@ -285,7 +291,7 @@ static int lps001wp_prs_register_read(struct lps001wp_prs_data *prs, u8 *buf, u8 reg_address) { - int err = -1; + int err = -EINVAL; buf[0] = (reg_address); err = lps001wp_prs_i2c_read(prs, buf, 1); @@ -295,7 +301,7 @@ static int lps001wp_prs_register_read(struct lps001wp_prs_data *prs, u8 *buf, static int lps001wp_prs_register_update(struct lps001wp_prs_data *prs, u8 *buf, u8 reg_address, u8 mask, u8 new_bit_values) { - int err = -1; + int err = -EINVAL; u8 init_val; u8 updated_val; err = lps001wp_prs_register_read(prs, buf, reg_address); @@ -313,10 +319,11 @@ static int lps001wp_prs_register_update(struct lps001wp_prs_data *prs, u8 *buf, static int lps001wp_prs_hw_init(struct lps001wp_prs_data *prs) { - int err = -1; + int err = -EINVAL; u8 buf[6]; - printk(KERN_DEBUG "%s: hw init start\n", LPS001WP_PRS_DEV_NAME); + dev_dbg(&prs->client->dev, "%s: hw init start\n", + LPS001WP_PRS_DEV_NAME); buf[0] = WHO_AM_I; err = lps001wp_prs_i2c_read(prs, buf, 1); @@ -325,12 +332,12 @@ static int lps001wp_prs_hw_init(struct lps001wp_prs_data *prs) else prs->hw_working = 1; if (buf[0] != WHOAMI_LPS001WP_PRS) { - err = -1; /* TODO:choose the right coded error */ + err = -EINVAL; /* TODO:choose the right coded error */ goto error_unknown_device; } - buf[0] = (I2C_AUTO_INCREMENT | INDATA_REG); + buf[0] = (I2C_AUTO_INCREMENT | REF_PRESS_REG); buf[1] = prs->resume_state[RES_REF_P_L]; buf[2] = prs->resume_state[RES_REF_P_H]; buf[3] = prs->resume_state[RES_THS_P_L]; @@ -355,7 +362,7 @@ static int lps001wp_prs_hw_init(struct lps001wp_prs_data *prs) prs->hw_initialized = 1; - printk(KERN_DEBUG "%s: hw init done\n", LPS001WP_PRS_DEV_NAME); + dev_dbg(&prs->client->dev, "%s: hw init done\n", LPS001WP_PRS_DEV_NAME); return 0; error_firstread: @@ -398,7 +405,7 @@ static void lps001wp_prs_device_power_off(struct lps001wp_prs_data *prs) static int lps001wp_prs_device_power_on(struct lps001wp_prs_data *prs) { - int err = -1; + int err = -EINVAL; /* get the regulator the first time */ if (!prs->regulator) { @@ -432,7 +439,7 @@ static int lps001wp_prs_device_power_on(struct lps001wp_prs_data *prs) int lps001wp_prs_update_odr(struct lps001wp_prs_data *prs, int poll_interval_ms) { - int err = -1; + int err = -EINVAL; int i; u8 buf[2]; @@ -483,12 +490,17 @@ error: static int lps001wp_prs_set_press_reference(struct lps001wp_prs_data *prs, u16 new_reference) { - int err = -1; + int err = -EINVAL; u8 const reg_addressL = REF_P_L; u8 const reg_addressH = REF_P_H; u8 bit_valuesL, bit_valuesH; u8 buf[2]; - + /* + * We need to set new configurations, only if device + * is currently enabled + */ + if (!atomic_read(&prs->enabled)) + return err; bit_valuesL = (u8) (new_reference & 0x00FF); bit_valuesH = (u8)((new_reference & 0xFF00) >> 8); @@ -511,12 +523,17 @@ static int lps001wp_prs_set_press_reference(struct lps001wp_prs_data *prs, static int lps001wp_prs_get_press_reference(struct lps001wp_prs_data *prs, u16 *buf16) { - int err = -1; + int err = -EINVAL; u8 bit_valuesL, bit_valuesH; u8 buf[2] = {0}; u16 temp = 0; - + /* + * We need to read configurations, only if device + * is currently enabled + */ + if (!atomic_read(&prs->enabled)) + return err; err = lps001wp_prs_register_read(prs, buf, REF_P_L); if (err < 0) return err; @@ -534,11 +551,17 @@ static int lps001wp_prs_get_press_reference(struct lps001wp_prs_data *prs, static int lps001wp_prs_lpow_manage(struct lps001wp_prs_data *prs, u8 control) { - int err = -1; + int err = -EINVAL; u8 buf[2] = {0x00, 0x00}; u8 const mask = LPS001WP_PRS_LPOW_MASK; u8 bit_values = LPS001WP_PRS_LPOW_OFF; + /* + * We need to set new configurations, only if device + * is currently enabled + */ + if (!atomic_read(&prs->enabled)) + return err; if (control >= LPS001WP_PRS_LPOWER_EN) { bit_values = LPS001WP_PRS_LPOW_ON; } @@ -559,11 +582,17 @@ static int lps001wp_prs_lpow_manage(struct lps001wp_prs_data *prs, u8 control) static int lps001wp_prs_diffen_manage(struct lps001wp_prs_data *prs, u8 control) { - int err = -1; + int err = -EINVAL; u8 buf[2] = {0x00, 0x00}; u8 const mask = LPS001WP_PRS_DIFF_MASK; u8 bit_values = LPS001WP_PRS_DIFF_OFF; + /* + * We need to set new configurations, only if device + * is currently enabled + */ + if (!atomic_read(&prs->enabled)) + return err; if (control >= LPS001WP_PRS_DIFF_ENABLE) { bit_values = LPS001WP_PRS_DIFF_ON; } @@ -586,7 +615,7 @@ static int lps001wp_prs_diffen_manage(struct lps001wp_prs_data *prs, u8 control) static int lps001wp_prs_get_presstemp_data(struct lps001wp_prs_data *prs, struct outputdata *out) { - int err = -1; + int err = -EINVAL; /* Data bytes from hardware PRESS_OUT_L, PRESS_OUT_H, * TEMP_OUT_L, TEMP_OUT_H, * DELTA_L, DELTA_H */ @@ -609,8 +638,8 @@ static int lps001wp_prs_get_presstemp_data(struct lps001wp_prs_data *prs, abspr = ((((u16) prs_data[1] << 8) | ((u16) prs_data[0]))); temperature = ((s16) (((u16) prs_data[3] << 8) | ((u16)prs_data[2]))); - out->abspress = abspr; - out->temperature = temperature; + out->abspress = (abspr >> SENSITIVITY_P_SHIFT); + out->temperature = (temperature >> SENSITIVITY_T_SHIFT); deltapr = ((s16) (((u16) prs_data[5] << 8) | ((u16)prs_data[4]))); out->deltapress = deltapr; @@ -618,6 +647,7 @@ static int lps001wp_prs_get_presstemp_data(struct lps001wp_prs_data *prs, return err; } +#ifdef CONFIG_LPS001WP_INPUT_DEVICE static void lps001wp_prs_report_values(struct lps001wp_prs_data *prs, struct outputdata *out) { @@ -626,19 +656,24 @@ static void lps001wp_prs_report_values(struct lps001wp_prs_data *prs, input_report_abs(prs->input_dev, ABS_DLTPR, out->deltapress); input_sync(prs->input_dev); } +#endif static int lps001wp_prs_enable(struct lps001wp_prs_data *prs) { int err; if (!atomic_cmpxchg(&prs->enabled, 0, 1)) { + if (prs->regulator) + regulator_enable(prs->regulator); err = lps001wp_prs_device_power_on(prs); if (err < 0) { atomic_set(&prs->enabled, 0); return err; } +#ifdef CONFIG_LPS001WP_INPUT_DEVICE schedule_delayed_work(&prs->input_work, msecs_to_jiffies(prs->pdata->poll_interval)); +#endif } return 0; @@ -647,44 +682,17 @@ static int lps001wp_prs_enable(struct lps001wp_prs_data *prs) static int lps001wp_prs_disable(struct lps001wp_prs_data *prs) { if (atomic_cmpxchg(&prs->enabled, 1, 0)) { +#ifdef CONFIG_LPS001WP_INPUT_DEVICE cancel_delayed_work_sync(&prs->input_work); +#endif lps001wp_prs_device_power_off(prs); + if (prs->regulator) + regulator_disable(prs->regulator); } return 0; } -static ssize_t read_single_reg(struct device *dev, char *buf, u8 reg) -{ - ssize_t ret; - struct lps001wp_prs_data *prs = dev_get_drvdata(dev); - int rc = 0; - - u8 data = reg; - rc = lps001wp_prs_i2c_read(prs, &data, 1); - /*TODO: error need to be managed */ - ret = sprintf(buf, "0x%02x\n", data); - return ret; - -} - -static int write_reg(struct device *dev, const char *buf, u8 reg) -{ - int rc = 0; - struct lps001wp_prs_data *prs = dev_get_drvdata(dev); - u8 x[2]; - unsigned long val; - - if (strict_strtoul(buf, 16, &val)) - return -EINVAL; - - x[0] = reg; - x[1] = val; - rc = lps001wp_prs_i2c_write(prs, x, 1); - /*TODO: error need to be managed */ - return rc; -} - static ssize_t attr_get_polling_rate(struct device *dev, struct device_attribute *attr, char *buf) @@ -703,6 +711,7 @@ static ssize_t attr_set_polling_rate(struct device *dev, { struct lps001wp_prs_data *prs = dev_get_drvdata(dev); unsigned long interval_ms; + int err = -EINVAL; if (strict_strtoul(buf, 10, &interval_ms)) return -EINVAL; @@ -710,7 +719,12 @@ static ssize_t attr_set_polling_rate(struct device *dev, return -EINVAL; mutex_lock(&prs->lock); prs->pdata->poll_interval = interval_ms; - lps001wp_prs_update_odr(prs, interval_ms); + err = lps001wp_prs_update_odr(prs, interval_ms); + if (err < 0) { + dev_err(&prs->client->dev, "failed to update odr %ld\n", + interval_ms); + size = err; + } mutex_unlock(&prs->lock); return size; } @@ -733,12 +747,18 @@ static ssize_t attr_set_diff_enable(struct device *dev, { struct lps001wp_prs_data *prs = dev_get_drvdata(dev); unsigned long val; + int err = -EINVAL; if (strict_strtoul(buf, 10, &val)) return -EINVAL; mutex_lock(&prs->lock); - lps001wp_prs_diffen_manage(prs, (u8) val); + err = lps001wp_prs_diffen_manage(prs, (u8) val); + if (err < 0) { + dev_err(&prs->client->dev, "failed to diff enable %ld\n", val); + mutex_unlock(&prs->lock); + return err; + } mutex_unlock(&prs->lock); return size; } @@ -772,15 +792,17 @@ static ssize_t attr_set_enable(struct device *dev, static ssize_t attr_get_press_ref(struct device *dev, struct device_attribute *attr, char *buf) { - int err = -1; + int err = -EINVAL; struct lps001wp_prs_data *prs = dev_get_drvdata(dev); u16 val = 0; mutex_lock(&prs->lock); err = lps001wp_prs_get_press_reference(prs, &val); mutex_unlock(&prs->lock); - if (err < 0) + if (err < 0) { + dev_err(&prs->client->dev, "failed to get ref press\n"); return err; + } return sprintf(buf, "%d\n", val); } @@ -789,7 +811,7 @@ static ssize_t attr_set_press_ref(struct device *dev, struct device_attribute *attr, const char *buf, size_t size) { - int err = -1; + int err = -EINVAL; struct lps001wp_prs_data *prs = dev_get_drvdata(dev); unsigned long val = 0; @@ -802,8 +824,11 @@ static ssize_t attr_set_press_ref(struct device *dev, mutex_lock(&prs->lock); err = lps001wp_prs_set_press_reference(prs, val); mutex_unlock(&prs->lock); - if (err < 0) + if (err < 0) { + dev_err(&prs->client->dev, "failed to set ref press %ld\n", + val); return err; + } return size; } @@ -823,7 +848,7 @@ static ssize_t attr_set_lowpowmode(struct device *dev, struct device_attribute *attr, const char *buf, size_t size) { - int err = -1; + int err = -EINVAL; struct lps001wp_prs_data *prs = dev_get_drvdata(dev); unsigned long val; @@ -833,12 +858,86 @@ static ssize_t attr_set_lowpowmode(struct device *dev, mutex_lock(&prs->lock); err = lps001wp_prs_lpow_manage(prs, (u8) val); mutex_unlock(&prs->lock); - if (err < 0) + if (err < 0) { + dev_err(&prs->client->dev, "failed to set low powermode\n"); return err; + } return size; } +static ssize_t lps001wp_prs_get_press_data(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct lps001wp_prs_data *prs = dev_get_drvdata(dev); + struct outputdata out; + int err = -EINVAL; + mutex_lock(&prs->lock); + /* + * If device is currently enabled, we need to read + * data from it. + */ + if (!atomic_read(&prs->enabled)) + goto out; + err = lps001wp_prs_get_presstemp_data(prs, &out); + if (err < 0) { + dev_err(&prs->client->dev, "get_pressure_data failed\n"); + goto out; + } + mutex_unlock(&prs->lock); + return sprintf(buf, "%d", out.abspress); +out: + mutex_unlock(&prs->lock); + return err; +} +static ssize_t lps001wp_prs_get_deltapr_data(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct lps001wp_prs_data *prs = dev_get_drvdata(dev); + struct outputdata out; + int err = -EINVAL; + mutex_lock(&prs->lock); + /* + * If device is currently enabled, we need to read + * data from it. + */ + if (!atomic_read(&prs->enabled)) { + mutex_unlock(&prs->lock); + return err; + } + err = lps001wp_prs_get_presstemp_data(prs, &out); + if (err < 0) { + dev_err(&prs->client->dev, "get_deltapress_data failed\n"); + mutex_unlock(&prs->lock); + return err; + } + mutex_unlock(&prs->lock); + return sprintf(buf, "%d", out.deltapress); +} +static ssize_t lps001wp_prs_get_temp_data(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct lps001wp_prs_data *prs = dev_get_drvdata(dev); + struct outputdata out; + int err = -EINVAL; + mutex_lock(&prs->lock); + /* + * If device is currently enabled, we need to read + * data from it. + */ + if (!atomic_read(&prs->enabled)) { + mutex_unlock(&prs->lock); + return err; + } + err = lps001wp_prs_get_presstemp_data(prs, &out); + if (err < 0) { + dev_err(&prs->client->dev, "get_temperature_data failed\n"); + mutex_unlock(&prs->lock); + return err; + } + mutex_unlock(&prs->lock); + return sprintf(buf, "%d", out.temperature); +} #ifdef DEBUG static ssize_t attr_reg_set(struct device *dev, struct device_attribute *attr, const char *buf, size_t size) @@ -893,14 +992,21 @@ static ssize_t attr_addr_set(struct device *dev, struct device_attribute *attr, static struct device_attribute attributes[] = { - __ATTR(pollrate_ms, 0664, attr_get_polling_rate, attr_set_polling_rate), - __ATTR(enable, 0664, attr_get_enable, attr_set_enable), - __ATTR(diff_enable, 0664, attr_get_diff_enable, attr_set_diff_enable), - __ATTR(press_reference, 0664, attr_get_press_ref, attr_set_press_ref), - __ATTR(lowpow_enable, 0664, attr_get_lowpowmode, attr_set_lowpowmode), + __ATTR(pollrate_ms, S_IWUSR | S_IRUGO, attr_get_polling_rate, + attr_set_polling_rate), + __ATTR(enable, S_IWUSR | S_IRUGO, attr_get_enable, attr_set_enable), + __ATTR(diff_enable, S_IWUSR | S_IRUGO, attr_get_diff_enable, + attr_set_diff_enable), + __ATTR(press_reference, S_IWUSR | S_IRUGO, attr_get_press_ref, + attr_set_press_ref), + __ATTR(lowpow_enable, S_IWUSR | S_IRUGO, attr_get_lowpowmode, + attr_set_lowpowmode), + __ATTR(press_data, S_IRUGO, lps001wp_prs_get_press_data, NULL), + __ATTR(temp_data, S_IRUGO, lps001wp_prs_get_temp_data, NULL), + __ATTR(deltapr_data, S_IRUGO, lps001wp_prs_get_deltapr_data, NULL), #ifdef DEBUG - __ATTR(reg_value, 0664, attr_reg_get, attr_reg_set), - __ATTR(reg_addr, 0220, NULL, attr_addr_set), + __ATTR(reg_value, S_IWUSR | S_IRUGO, attr_reg_get, attr_reg_set), + __ATTR(reg_addr, S_IWUSR, NULL, attr_addr_set), #endif }; @@ -927,7 +1033,7 @@ static int remove_sysfs_interfaces(struct device *dev) return 0; } - +#ifdef CONFIG_LPS001WP_INPUT_DEVICE static void lps001wp_prs_input_work_func(struct work_struct *work) { struct lps001wp_prs_data *prs; @@ -964,7 +1070,7 @@ void lps001wp_prs_input_close(struct input_dev *dev) lps001wp_prs_disable(prs); } - +#endif static int lps001wp_prs_validate_pdata(struct lps001wp_prs_data *prs) { @@ -979,11 +1085,10 @@ static int lps001wp_prs_validate_pdata(struct lps001wp_prs_data *prs) return 0; } - +#ifdef CONFIG_LPS001WP_INPUT_DEVICE static int lps001wp_prs_input_init(struct lps001wp_prs_data *prs) { int err; - INIT_DELAYED_WORK(&prs->input_work, lps001wp_prs_input_work_func); prs->input_dev = input_allocate_device(); if (!prs->input_dev) { @@ -1033,12 +1138,12 @@ static void lps001wp_prs_input_cleanup(struct lps001wp_prs_data *prs) input_unregister_device(prs->input_dev); input_free_device(prs->input_dev); } - +#endif static int lps001wp_prs_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct lps001wp_prs_data *prs; - int err = -1; + int err = -EINVAL; int tempvalue; pr_info("%s: probe start.\n", LPS001WP_PRS_DEV_NAME); @@ -1088,23 +1193,31 @@ static int lps001wp_prs_probe(struct i2c_client *client, prs->client = client; i2c_set_clientdata(client, prs); + prs->regulator = regulator_get(&client->dev, "vdd"); + if (IS_ERR(prs->regulator)) { + dev_err(&client->dev, "failed to get regulator\n"); + err = PTR_ERR(prs->regulator); + prs->regulator = NULL; + } + if (prs->regulator) + regulator_enable(prs->regulator); if (i2c_smbus_read_byte(client) < 0) { - printk(KERN_ERR "i2c_smbus_read_byte error!!\n"); + dev_err(&client->dev, "i2c_smbus_read_byte error!!\n"); goto err_mutexunlockfreedata; } else { - printk(KERN_DEBUG "%s Device detected!\n", + dev_dbg(&client->dev, "%s Device detected!\n", LPS001WP_PRS_DEV_NAME); } /* read chip id */ tempvalue = i2c_smbus_read_word_data(client, WHO_AM_I); if ((tempvalue & 0x00FF) == WHOAMI_LPS001WP_PRS) { - printk(KERN_DEBUG "%s I2C driver registered!\n", + dev_dbg(&client->dev, "%s I2C driver registered!\n", LPS001WP_PRS_DEV_NAME); } else { prs->client = NULL; - printk(KERN_DEBUG "I2C driver not registered!" + dev_dbg(&client->dev, "I2C driver not registered!" " Device unknown\n"); goto err_mutexunlockfreedata; } @@ -1163,13 +1276,13 @@ static int lps001wp_prs_probe(struct i2c_client *client, dev_err(&client->dev, "update_odr failed\n"); goto err_power_off; } - +#ifdef CONFIG_LPS001WP_INPUT_DEVICE err = lps001wp_prs_input_init(prs); if (err < 0) { dev_err(&client->dev, "input init failed\n"); goto err_power_off; } - +#endif err = create_sysfs_interfaces(&client->dev); if (err < 0) { @@ -1177,10 +1290,20 @@ static int lps001wp_prs_probe(struct i2c_client *client, "device LPS001WP_PRS_DEV_NAME sysfs register failed\n"); goto err_input_cleanup; } +#ifdef CONFIG_HAS_EARLYSUSPEND + prs->early_suspend.level = + EARLY_SUSPEND_LEVEL_BLANK_SCREEN + 1; + prs->early_suspend.suspend = lps001wp_prs_early_suspend; + prs->early_suspend.resume = lps001wp_prs_late_resume; + register_early_suspend(&prs->early_suspend); +#endif lps001wp_prs_device_power_off(prs); + if (prs->regulator) + regulator_disable(prs->regulator); + /* As default, do not report information */ atomic_set(&prs->enabled, 0); @@ -1196,7 +1319,9 @@ remove_sysfs_int: remove_sysfs_interfaces(&client->dev); */ err_input_cleanup: +#ifdef CONFIG_LPS001WP_INPUT_DEVICE lps001wp_prs_input_cleanup(prs); +#endif err_power_off: lps001wp_prs_device_power_off(prs); err2: @@ -1207,10 +1332,15 @@ exit_kfree_pdata: err_mutexunlockfreedata: mutex_unlock(&prs->lock); + if (prs->regulator) { + regulator_disable(prs->regulator); + regulator_put(prs->regulator); + } kfree(prs); exit_alloc_data_failed: exit_check_functionality_failed: - printk(KERN_ERR "%s: Driver Init failed\n", LPS001WP_PRS_DEV_NAME); + dev_err(&client->dev, "%s: Driver Init failed\n", + LPS001WP_PRS_DEV_NAME); return err; } @@ -1218,9 +1348,17 @@ static int __devexit lps001wp_prs_remove(struct i2c_client *client) { struct lps001wp_prs_data *prs = i2c_get_clientdata(client); +#ifdef CONFIG_LPS001WP_INPUT_DEVICE lps001wp_prs_input_cleanup(prs); +#endif lps001wp_prs_device_power_off(prs); remove_sysfs_interfaces(&client->dev); + if (prs->regulator) { + /* Disable the regulator if device is enabled. */ + if (atomic_read(&prs->enabled)) + regulator_disable(prs->regulator); + regulator_put(prs->regulator); + } if (prs->pdata->exit) prs->pdata->exit(); @@ -1233,24 +1371,44 @@ static int __devexit lps001wp_prs_remove(struct i2c_client *client) return 0; } - -static int lps001wp_prs_resume(struct i2c_client *client) +#if (!defined(CONFIG_HAS_EARLYSUSPEND) && defined(CONFIG_PM)) +static int lps001wp_prs_resume(struct device *dev) { - struct lps001wp_prs_data *prs = i2c_get_clientdata(client); + struct lps001wp_prs_data *prs = dev_get_drvdata(dev); if (prs->on_before_suspend) return lps001wp_prs_enable(prs); return 0; } -static int lps001wp_prs_suspend(struct i2c_client *client, pm_message_t mesg) +static int lps001wp_prs_suspend(struct device *dev) { - struct lps001wp_prs_data *prs = i2c_get_clientdata(client); - + struct lps001wp_prs_data *prs = dev_get_drvdata(dev); prs->on_before_suspend = atomic_read(&prs->enabled); return lps001wp_prs_disable(prs); } +static const struct dev_pm_ops lps001wp_prs_dev_pm_ops = { + .suspend = lps001wp_prs_suspend, + .resume = lps001wp_prs_resume, +}; +#else +static void lps001wp_prs_early_suspend(struct early_suspend *data) +{ + struct lps001wp_prs_data *prs = + container_of(data, struct lps001wp_prs_data, early_suspend); + prs->on_before_suspend = atomic_read(&prs->enabled); + lps001wp_prs_disable(prs); +} + +static void lps001wp_prs_late_resume(struct early_suspend *data) +{ + struct lps001wp_prs_data *prs = + container_of(data, struct lps001wp_prs_data, early_suspend); + if (prs->on_before_suspend) + lps001wp_prs_enable(prs); +} +#endif static const struct i2c_device_id lps001wp_prs_id[] = { { LPS001WP_PRS_DEV_NAME, 0}, { },}; @@ -1260,12 +1418,13 @@ static struct i2c_driver lps001wp_prs_driver = { .driver = { .name = LPS001WP_PRS_DEV_NAME, .owner = THIS_MODULE, +#if (!defined(CONFIG_HAS_EARLYSUSPEND) && defined(CONFIG_PM)) + .pm = &lps001wp_prs_dev_pm_ops, +#endif }, .probe = lps001wp_prs_probe, .remove = __devexit_p(lps001wp_prs_remove), .id_table = lps001wp_prs_id, - .resume = lps001wp_prs_resume, - .suspend = lps001wp_prs_suspend, }; static int __init lps001wp_prs_init(void) diff --git a/drivers/misc/bh1780gli.c b/drivers/misc/bh1780gli.c index ec303edd94a..3dbbf52a126 100644 --- a/drivers/misc/bh1780gli.c +++ b/drivers/misc/bh1780gli.c @@ -146,7 +146,7 @@ static ssize_t bh1780_store_power_state(struct device *dev, if (val == BH1780_POFF) regulator_disable(ddata->regulator); - msleep(BH1780_PON_DELAY); + mdelay(BH1780_PON_DELAY); ddata->power_state = val; mutex_unlock(&ddata->lock); @@ -202,7 +202,7 @@ static int __devinit bh1780_probe(struct i2c_client *client, ret = bh1780_read(ddata, BH1780_REG_PARTID, "PART ID"); if (ret < 0) { dev_err(&client->dev, "failed to read part ID\n"); - goto put_regulator; + goto disable_regulator; } #ifdef CONFIG_HAS_EARLYSUSPEND ddata->early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN + 1; @@ -220,13 +220,15 @@ static int __devinit bh1780_probe(struct i2c_client *client, mutex_init(&ddata->lock); ret = sysfs_create_group(&client->dev.kobj, &bh1780_attr_group); - if (ret) + if (ret) { + dev_err(&client->dev, "failed to create sysfs group\n"); goto put_regulator; + } return 0; - -put_regulator: +disable_regulator: regulator_disable(ddata->regulator); +put_regulator: regulator_put(ddata->regulator); free_ddata: kfree(ddata); diff --git a/include/linux/lsm303dlh.h b/include/linux/lsm303dlh.h index ad369b1fbd5..a565faa79ba 100644 --- a/include/linux/lsm303dlh.h +++ b/include/linux/lsm303dlh.h @@ -42,6 +42,7 @@ * @negative_x: x axis is orientation, 0 or 1 * @negative_y: y axis is orientation, 0 or 1 * @negative_z: z axis is orientation, 0 or 1 + * @chip_id: to store ID of the LSM chip */ struct lsm303dlh_platform_data { const char *name_a; @@ -55,6 +56,7 @@ struct lsm303dlh_platform_data { u8 negative_x; u8 negative_y; u8 negative_z; + u32 chip_id; }; #endif /* __KERNEL__ */ |