summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPhilippe Langlais <philippe.langlais@linaro.org>2012-02-15 11:15:01 +0100
committerPhilippe Langlais <philippe.langlais@linaro.org>2012-02-15 11:15:01 +0100
commit936d2759f1fe0238b3544ee3e62fdfdca4da29ec (patch)
tree35629b48ebdf9e2173a2a605e36d6d6a176a8643
parent82280adb1342204e0ec1f85e22b4c74a1bc6d696 (diff)
parent3e18d1bb698aa4e992e548007c2ca050aeedb2e5 (diff)
Merge branch 'stable-linux-ux500-3.2' into stable-ubuntu-ux500-3.2
Conflicts: arch/arm/mach-ux500/board-mop500-pins.c
-rwxr-xr-xarch/arm/configs/u8500_defconfig4
-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.c44
-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.c94
-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.c27
-rw-r--r--drivers/hwmon/lsm303dlh_m.c40
-rw-r--r--drivers/hwmon/lsm303dlhc_a.c18
-rw-r--r--drivers/input/keyboard/gpio_keys.c13
-rw-r--r--drivers/input/misc/Kconfig9
-rw-r--r--drivers/input/misc/lps001wp_prs.c389
-rw-r--r--drivers/misc/bh1780gli.c12
-rw-r--r--include/linux/lsm303dlh.h2
20 files changed, 625 insertions, 584 deletions
diff --git a/arch/arm/configs/u8500_defconfig b/arch/arm/configs/u8500_defconfig
index 90f9654b654..e929c8d2462 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/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 149c23a5805..80e3fe2b914 100644
--- a/drivers/input/misc/Kconfig
+++ b/drivers/input/misc/Kconfig
@@ -296,6 +296,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__ */