summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMathieu J. Poirier <mathieu.poirier@linaro.org>2012-02-15 21:20:55 +0000
committerMathieu J. Poirier <mathieu.poirier@linaro.org>2012-02-15 21:20:55 +0000
commitb7c98d59bf292d705ef701c910477d6330c7f002 (patch)
treee34683f7b28e600162daa2b5de7bf3dbeb891544
parent2ba1e41d4029b4af0f5478c796e8dffd29c5c3b4 (diff)
parent530ef7071390c979aec61a1ce01122cc192d9499 (diff)
Merge branch 'stable-android-ux500-3.1-mali-v9' of git://igloocommunity.org/git/kernel/igloo-kernel into igloocommunity.org#git/kernel/igloo-kernel/stable-android-ux500-3.1-mali-v9
-rw-r--r--arch/arm/configs/u8500_android_defconfig2
-rwxr-xr-xarch/arm/configs/u8500_defconfig2
-rw-r--r--arch/arm/mach-ux500/Kconfig11
-rw-r--r--arch/arm/mach-ux500/Makefile1
-rwxr-xr-xarch/arm/mach-ux500/board-mop500-cyttsp.c56
-rw-r--r--arch/arm/mach-ux500/board-mop500-pins.c45
-rw-r--r--arch/arm/mach-ux500/board-mop500-sensors.c33
-rw-r--r--arch/arm/mach-ux500/board-mop500-u8500uib.c10
-rw-r--r--arch/arm/mach-ux500/board-mop500-uib.c102
-rw-r--r--arch/arm/mach-ux500/board-mop500.c102
-rw-r--r--arch/arm/mach-ux500/include/mach/sensors1p.h24
-rw-r--r--arch/arm/mach-ux500/sensors1p.c298
-rw-r--r--drivers/hwmon/l3g4200d.c22
-rw-r--r--drivers/hwmon/lsm303dlh_a.c17
-rw-r--r--drivers/hwmon/lsm303dlh_m.c32
-rw-r--r--drivers/hwmon/lsm303dlhc_a.c17
-rw-r--r--drivers/input/keyboard/gpio_keys.c13
-rw-r--r--drivers/input/misc/Kconfig9
-rw-r--r--drivers/input/misc/lps001wp_prs.c386
-rw-r--r--drivers/misc/bh1780gli.c12
-rw-r--r--include/linux/lsm303dlh.h2
21 files changed, 615 insertions, 581 deletions
diff --git a/arch/arm/configs/u8500_android_defconfig b/arch/arm/configs/u8500_android_defconfig
index 414777e6938..c6b1f8f2ed8 100644
--- a/arch/arm/configs/u8500_android_defconfig
+++ b/arch/arm/configs/u8500_android_defconfig
@@ -241,6 +241,8 @@ CONFIG_GPIO_AB8500=y
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_THERMAL=y
CONFIG_WATCHDOG=y
diff --git a/arch/arm/configs/u8500_defconfig b/arch/arm/configs/u8500_defconfig
index 661e8e469be..fde66da239b 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
@@ -173,6 +174,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
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 128377f4078..b3d5f1e991b 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 276305ebb33..655dbcbe7cf 100644
--- a/arch/arm/mach-ux500/board-mop500-pins.c
+++ b/arch/arm/mach-ux500/board-mop500-pins.c
@@ -19,7 +19,7 @@
#include "pins-db8500.h"
#include "pins.h"
-
+#include "board-mop500.h"
#include "board-pins-sleep-force.h"
enum custom_pin_cfg_t {
@@ -162,9 +162,6 @@ static pin_cfg_t mop500_pins_hrefv60[] = {
/* 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 */
@@ -178,9 +175,6 @@ static pin_cfg_t mop500_pins_hrefv60[] = {
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,
};
@@ -420,7 +414,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),
@@ -437,6 +445,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),
+};
+
/*
* Sleep pin configuration for u8500 platform.
* If another HW is used the GPIO's must be configured
@@ -647,7 +663,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,
@@ -775,7 +793,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,
@@ -938,7 +958,14 @@ 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));
+
+ if (machine_is_hrefv60())
+ ux500_pins_add(mop500_runtime_pins_v60,
+ ARRAY_SIZE(mop500_runtime_pins_v60));
+ else
+ ux500_pins_add(mop500_runtime_pins_old,
+ ARRAY_SIZE(mop500_runtime_pins_old));
switch (pinsfor) {
case PINS_FOR_U9500:
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 41eea4a79c8..33b971d2f60 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 b8855d6790c..5780692b9bd 100644
--- a/arch/arm/mach-ux500/board-mop500.c
+++ b/arch/arm/mach-ux500/board-mop500.c
@@ -51,7 +51,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
@@ -648,42 +647,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",
@@ -702,24 +665,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] = {
@@ -867,30 +812,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 = {
@@ -931,9 +852,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
@@ -951,7 +869,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
@@ -1219,20 +1136,6 @@ static void accessory_detect_config(void)
static void __init mop500_init_machine(void)
{
- /*
- * The HREFv60 board removed a GPIO expander and routed
- * all these GPIO pins to the internal GPIO controller
- * instead.
- */
- if (!machine_is_snowball()) {
- if (machine_is_hrefv60()) {
- mop500_gpio_keys[0].gpio = HREFV60_PROX_SENSE_GPIO;
- mop500_gpio_keys[1].gpio = HREFV60_HAL_SW_GPIO;
- } else {
- mop500_gpio_keys[0].gpio = GPIO_PROX_SENSOR;
- mop500_gpio_keys[1].gpio = GPIO_HAL_SENSOR;
- }
- }
accessory_detect_config();
@@ -1249,12 +1152,13 @@ static void __init mop500_init_machine(void)
ARRAY_SIZE(u8500_hsi_devices));
#endif
- if (machine_is_snowball())
+ if (machine_is_snowball()) {
platform_add_devices(snowball_platform_devs,
ARRAY_SIZE(snowball_platform_devs));
- else
+ } else {
platform_add_devices(mop500_platform_devs,
ARRAY_SIZE(mop500_platform_devs));
+ }
mop500_i2c_init();
mop500_sdi_init();
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/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 39a4e32ee2b..b341ab0907c 100644
--- a/drivers/hwmon/l3g4200d.c
+++ b/drivers/hwmon/l3g4200d.c
@@ -29,6 +29,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
@@ -400,6 +401,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,
@@ -411,11 +430,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 d3c30bc49e0..cda627b3398 100644
--- a/drivers/hwmon/lsm303dlh_a.c
+++ b/drivers/hwmon/lsm303dlh_a.c
@@ -37,6 +37,7 @@
#endif
#include <linux/lsm303dlh.h>
+#include <linux/earlysuspend.h>
#include <linux/regulator/consumer.h>
/* lsm303dlh accelerometer registers */
@@ -197,6 +198,7 @@ struct lsm303dlh_a_data {
unsigned char interrupt_configure[2];
unsigned char interrupt_duration[2];
unsigned char interrupt_threshold[2];
+ struct early_suspend early_suspend;
int device_status;
int id;
};
@@ -287,6 +289,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;
@@ -761,6 +764,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;
}
@@ -834,10 +838,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");
@@ -1093,6 +1102,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;
}
diff --git a/drivers/hwmon/lsm303dlh_m.c b/drivers/hwmon/lsm303dlh_m.c
index aa43d055e67..ff7cfa428ea 100644
--- a/drivers/hwmon/lsm303dlh_m.c
+++ b/drivers/hwmon/lsm303dlh_m.c
@@ -38,6 +38,7 @@
#include <linux/lsm303dlh.h>
#include <linux/regulator/consumer.h>
+#include <linux/earlysuspend.h>
#include <linux/kernel.h>
/* lsm303dlh magnetometer registers */
@@ -129,6 +130,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
@@ -160,6 +164,7 @@ struct lsm303dlh_m_data {
unsigned char mode;
unsigned char rate;
unsigned char range;
+ struct early_suspend early_suspend;
int device_status;
};
@@ -333,16 +338,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 ?
@@ -515,6 +520,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;
}
@@ -689,6 +695,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;
}
diff --git a/drivers/hwmon/lsm303dlhc_a.c b/drivers/hwmon/lsm303dlhc_a.c
index 17c74595ff2..8b7e2fe37b9 100644
--- a/drivers/hwmon/lsm303dlhc_a.c
+++ b/drivers/hwmon/lsm303dlhc_a.c
@@ -314,8 +314,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 +333,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 +403,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 +528,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 67df91af842..3181353d17d 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;
}
/*
@@ -576,6 +580,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);
@@ -707,6 +712,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;
@@ -727,6 +736,10 @@ static int gpio_keys_resume(struct device *dev)
gpio_keys_report_event(&ddata->data[i]);
}
+
+ if (!device_may_wakeup(&pdev->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 bfa6fbe732e..c55e03eeed2 100644
--- a/drivers/input/misc/Kconfig
+++ b/drivers/input/misc/Kconfig
@@ -279,6 +279,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..4b8a7368768 100644
--- a/drivers/input/misc/lps001wp_prs.c
+++ b/drivers/input/misc/lps001wp_prs.c
@@ -49,12 +49,10 @@
#include <linux/regulator/consumer.h>
#include <linux/input/lps001wp.h>
-
-
+#include <linux/earlysuspend.h>
#define DEBUG 1
-
#define PR_ABS_MAX 0xffff
#define PR_ABS_MIN 0x0000
#define PR_DLT_MAX 0x7ffff
@@ -68,7 +66,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 +81,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 +95,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 +142,35 @@ 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
+ struct regulator *regulator;
+ struct early_suspend early_suspend;
int hw_initialized;
/* hw_working=-1 means not tested yet */
@@ -178,6 +196,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 +269,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 +288,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 +298,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 +316,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 +329,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 +359,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 +402,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 +436,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 +487,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 +520,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 +548,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 +579,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 +612,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 +635,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 +644,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 +653,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 +679,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 +708,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 +716,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 +744,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 +789,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 +808,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 +821,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 +845,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 +855,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 +989,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 +1030,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 +1067,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 +1082,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 +1135,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 +1190,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 +1273,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 +1287,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 +1316,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 +1329,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 +1345,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 +1368,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}, { },};
@@ -1264,8 +1419,9 @@ static struct i2c_driver lps001wp_prs_driver = {
.probe = lps001wp_prs_probe,
.remove = __devexit_p(lps001wp_prs_remove),
.id_table = lps001wp_prs_id,
- .resume = lps001wp_prs_resume,
- .suspend = lps001wp_prs_suspend,
+ #if (!defined(CONFIG_HAS_EARLYSUSPEND) && defined(CONFIG_PM))
+ .pm = &lps001wp_prs_dev_pm_ops,
+ #endif
};
static int __init lps001wp_prs_init(void)
diff --git a/drivers/misc/bh1780gli.c b/drivers/misc/bh1780gli.c
index 060441599cb..b08b271bf28 100644
--- a/drivers/misc/bh1780gli.c
+++ b/drivers/misc/bh1780gli.c
@@ -145,7 +145,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);
@@ -201,7 +201,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;
@@ -219,13 +219,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__ */