aboutsummaryrefslogtreecommitdiff
path: root/drivers/input/misc
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2015-09-04 12:02:11 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2015-09-04 12:02:11 -0700
commit51e771c0d25b43d0f12b2c7c01939942becbbe28 (patch)
treedf82af16b012c452c1457f431e57d47c8c2bacd2 /drivers/input/misc
parentabebcdfb64f1b39eeeb14282d9cd4aad1ed86f8d (diff)
parent01b944fe1cd4e21a2a9ed51adbdbafe2d5e905ba (diff)
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input
Pull input subsystem updates from Dmitry Torokhov: "Drivers, drivers, drivers... No interesting input core changes this time" * 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input: (74 commits) Input: elan_i2c - use iap_version to get firmware information Input: max8997_haptic - fix module alias Input: elan_i2c - fix typos for validpage_count Input: psmouse - add small delay for IBM trackpoint pass-through mode Input: synaptics - fix handling of disabling gesture mode Input: elan_i2c - enable ELAN0100 acpi panels Input: gpio-keys - report error when disabling unsupported key Input: sur40 - fix error return code Input: sentelic - silence some underflow warnings Input: zhenhua - switch to using bitrev8() Input: cros_ec_keyb - replace KEYBOARD_CROS_EC dependency Input: cap11xx - add LED support Input: elants_i2c - fix for devm_gpiod_get API change Input: elan_i2c - enable asynchronous probing Input: elants_i2c - enable asynchronous probing Input: elants_i2c - wire up regulator support Input: do not emit unneeded EV_SYN when suspending Input: elants_i2c - disable idle mode before updating firmware MAINTAINERS: Add maintainer for atmel_mxt_ts Input: atmel_mxt_ts - remove warning on zero T44 count ...
Diffstat (limited to 'drivers/input/misc')
-rw-r--r--drivers/input/misc/Kconfig11
-rw-r--r--drivers/input/misc/adxl34x-i2c.c1
-rw-r--r--drivers/input/misc/arizona-haptics.c26
-rw-r--r--drivers/input/misc/bma150.c8
-rw-r--r--drivers/input/misc/cma3000_d0x_i2c.c1
-rw-r--r--drivers/input/misc/drv260x.c3
-rw-r--r--drivers/input/misc/drv2665.c3
-rw-r--r--drivers/input/misc/drv2667.c3
-rw-r--r--drivers/input/misc/gp2ap002a00f.c2
-rw-r--r--drivers/input/misc/kxtj9.c1
-rw-r--r--drivers/input/misc/max8997_haptic.c3
-rw-r--r--drivers/input/misc/mpu3050.c1
-rw-r--r--drivers/input/misc/pcf8574_keypad.c1
-rw-r--r--drivers/input/misc/pmic8xxx-pwrkey.c268
-rw-r--r--drivers/input/misc/uinput.c6
15 files changed, 286 insertions, 52 deletions
diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig
index c41dec819cdf..906dd1b25e41 100644
--- a/drivers/input/misc/Kconfig
+++ b/drivers/input/misc/Kconfig
@@ -247,7 +247,7 @@ config INPUT_APANEL
config INPUT_GP2A
tristate "Sharp GP2AP002A00F I2C Proximity/Opto sensor driver"
depends on I2C
- depends on GPIOLIB
+ depends on GPIOLIB || COMPILE_TEST
help
Say Y here if you have a Sharp GP2AP002A00F proximity/als combo-chip
hooked to an I2C bus.
@@ -257,7 +257,7 @@ config INPUT_GP2A
config INPUT_GPIO_BEEPER
tristate "Generic GPIO Beeper support"
- depends on GPIOLIB
+ depends on GPIOLIB || COMPILE_TEST
help
Say Y here if you have a beeper connected to a GPIO pin.
@@ -266,7 +266,7 @@ config INPUT_GPIO_BEEPER
config INPUT_GPIO_TILT_POLLED
tristate "Polled GPIO tilt switch"
- depends on GPIOLIB
+ depends on GPIOLIB || COMPILE_TEST
select INPUT_POLLDEV
help
This driver implements support for tilt switches connected
@@ -557,7 +557,7 @@ config INPUT_PWM_BEEPER
config INPUT_GPIO_ROTARY_ENCODER
tristate "Rotary encoders connected to GPIO pins"
- depends on GPIOLIB
+ depends on GPIOLIB || COMPILE_TEST
help
Say Y here to add support for rotary encoders connected to GPIO lines.
Check file:Documentation/input/rotary-encoder.txt for more
@@ -764,7 +764,8 @@ config INPUT_SOC_BUTTON_ARRAY
config INPUT_DRV260X_HAPTICS
tristate "TI DRV260X haptics support"
- depends on INPUT && I2C && GPIOLIB
+ depends on INPUT && I2C
+ depends on GPIOLIB || COMPILE_TEST
select INPUT_FF_MEMLESS
select REGMAP_I2C
help
diff --git a/drivers/input/misc/adxl34x-i2c.c b/drivers/input/misc/adxl34x-i2c.c
index bdb5d03b296e..a8b0a2eec344 100644
--- a/drivers/input/misc/adxl34x-i2c.c
+++ b/drivers/input/misc/adxl34x-i2c.c
@@ -158,7 +158,6 @@ MODULE_DEVICE_TABLE(of, adxl34x_of_id);
static struct i2c_driver adxl34x_driver = {
.driver = {
.name = "adxl34x",
- .owner = THIS_MODULE,
.pm = &adxl34x_i2c_pm,
.of_match_table = of_match_ptr(adxl34x_of_id),
},
diff --git a/drivers/input/misc/arizona-haptics.c b/drivers/input/misc/arizona-haptics.c
index 4dbbed74c9e4..4bf678541496 100644
--- a/drivers/input/misc/arizona-haptics.c
+++ b/drivers/input/misc/arizona-haptics.c
@@ -170,8 +170,8 @@ static int arizona_haptics_probe(struct platform_device *pdev)
INIT_WORK(&haptics->work, arizona_haptics_work);
- haptics->input_dev = input_allocate_device();
- if (haptics->input_dev == NULL) {
+ haptics->input_dev = devm_input_allocate_device(&pdev->dev);
+ if (!haptics->input_dev) {
dev_err(arizona->dev, "Failed to allocate input device\n");
return -ENOMEM;
}
@@ -188,41 +188,23 @@ static int arizona_haptics_probe(struct platform_device *pdev)
if (ret < 0) {
dev_err(arizona->dev, "input_ff_create_memless() failed: %d\n",
ret);
- goto err_ialloc;
+ return ret;
}
ret = input_register_device(haptics->input_dev);
if (ret < 0) {
dev_err(arizona->dev, "couldn't register input device: %d\n",
ret);
- goto err_iff;
+ return ret;
}
platform_set_drvdata(pdev, haptics);
return 0;
-
-err_iff:
- if (haptics->input_dev)
- input_ff_destroy(haptics->input_dev);
-err_ialloc:
- input_free_device(haptics->input_dev);
-
- return ret;
-}
-
-static int arizona_haptics_remove(struct platform_device *pdev)
-{
- struct arizona_haptics *haptics = platform_get_drvdata(pdev);
-
- input_unregister_device(haptics->input_dev);
-
- return 0;
}
static struct platform_driver arizona_haptics_driver = {
.probe = arizona_haptics_probe,
- .remove = arizona_haptics_remove,
.driver = {
.name = "arizona-haptics",
},
diff --git a/drivers/input/misc/bma150.c b/drivers/input/misc/bma150.c
index b36831c828d3..1d0e61d7c131 100644
--- a/drivers/input/misc/bma150.c
+++ b/drivers/input/misc/bma150.c
@@ -333,10 +333,9 @@ static void bma150_report_xyz(struct bma150_data *bma150)
y = ((0xc0 & data[2]) >> 6) | (data[3] << 2);
z = ((0xc0 & data[4]) >> 6) | (data[5] << 2);
- /* sign extension */
- x = (s16) (x << 6) >> 6;
- y = (s16) (y << 6) >> 6;
- z = (s16) (z << 6) >> 6;
+ x = sign_extend32(x, 9);
+ y = sign_extend32(y, 9);
+ z = sign_extend32(z, 9);
input_report_abs(bma150->input, ABS_X, x);
input_report_abs(bma150->input, ABS_Y, y);
@@ -654,7 +653,6 @@ MODULE_DEVICE_TABLE(i2c, bma150_id);
static struct i2c_driver bma150_driver = {
.driver = {
- .owner = THIS_MODULE,
.name = BMA150_DRIVER,
.pm = &bma150_pm,
},
diff --git a/drivers/input/misc/cma3000_d0x_i2c.c b/drivers/input/misc/cma3000_d0x_i2c.c
index 4fdef98ceb56..c7021916b64b 100644
--- a/drivers/input/misc/cma3000_d0x_i2c.c
+++ b/drivers/input/misc/cma3000_d0x_i2c.c
@@ -118,7 +118,6 @@ static struct i2c_driver cma3000_i2c_driver = {
.id_table = cma3000_i2c_id,
.driver = {
.name = "cma3000_i2c_accl",
- .owner = THIS_MODULE,
#ifdef CONFIG_PM
.pm = &cma3000_i2c_pm_ops,
#endif
diff --git a/drivers/input/misc/drv260x.c b/drivers/input/misc/drv260x.c
index f5c9cf2f4073..2adfd86c869a 100644
--- a/drivers/input/misc/drv260x.c
+++ b/drivers/input/misc/drv260x.c
@@ -204,7 +204,7 @@ struct drv260x_data {
int overdrive_voltage;
};
-static struct reg_default drv260x_reg_defs[] = {
+static const struct reg_default drv260x_reg_defs[] = {
{ DRV260X_STATUS, 0xe0 },
{ DRV260X_MODE, 0x40 },
{ DRV260X_RT_PB_IN, 0x00 },
@@ -720,7 +720,6 @@ static struct i2c_driver drv260x_driver = {
.probe = drv260x_probe,
.driver = {
.name = "drv260x-haptics",
- .owner = THIS_MODULE,
.of_match_table = of_match_ptr(drv260x_of_match),
.pm = &drv260x_pm_ops,
},
diff --git a/drivers/input/misc/drv2665.c b/drivers/input/misc/drv2665.c
index 924456e3ca75..ef9bc12b3be3 100644
--- a/drivers/input/misc/drv2665.c
+++ b/drivers/input/misc/drv2665.c
@@ -74,7 +74,7 @@ static const u8 drv2665_sine_wave_form[] = {
0x9b, 0x9f, 0xa5, 0xad, 0xb8, 0xc4, 0xd2, 0xe0, 0xf0, 0x00,
};
-static struct reg_default drv2665_reg_defs[] = {
+static const struct reg_default drv2665_reg_defs[] = {
{ DRV2665_STATUS, 0x02 },
{ DRV2665_CTRL_1, 0x28 },
{ DRV2665_CTRL_2, 0x40 },
@@ -309,7 +309,6 @@ static struct i2c_driver drv2665_driver = {
.probe = drv2665_probe,
.driver = {
.name = "drv2665-haptics",
- .owner = THIS_MODULE,
.of_match_table = of_match_ptr(drv2665_of_match),
.pm = &drv2665_pm_ops,
},
diff --git a/drivers/input/misc/drv2667.c b/drivers/input/misc/drv2667.c
index 047136aa646f..d5ba7481328c 100644
--- a/drivers/input/misc/drv2667.c
+++ b/drivers/input/misc/drv2667.c
@@ -116,7 +116,7 @@ struct drv2667_data {
u32 frequency;
};
-static struct reg_default drv2667_reg_defs[] = {
+static const struct reg_default drv2667_reg_defs[] = {
{ DRV2667_STATUS, 0x02 },
{ DRV2667_CTRL_1, 0x28 },
{ DRV2667_CTRL_2, 0x40 },
@@ -484,7 +484,6 @@ static struct i2c_driver drv2667_driver = {
.probe = drv2667_probe,
.driver = {
.name = "drv2667-haptics",
- .owner = THIS_MODULE,
.of_match_table = of_match_ptr(drv2667_of_match),
.pm = &drv2667_pm_ops,
},
diff --git a/drivers/input/misc/gp2ap002a00f.c b/drivers/input/misc/gp2ap002a00f.c
index 0ac176d66a6f..3bfdfcc20485 100644
--- a/drivers/input/misc/gp2ap002a00f.c
+++ b/drivers/input/misc/gp2ap002a00f.c
@@ -267,11 +267,11 @@ static const struct i2c_device_id gp2a_i2c_id[] = {
{ GP2A_I2C_NAME, 0 },
{ }
};
+MODULE_DEVICE_TABLE(i2c, gp2a_i2c_id);
static struct i2c_driver gp2a_i2c_driver = {
.driver = {
.name = GP2A_I2C_NAME,
- .owner = THIS_MODULE,
.pm = &gp2a_pm,
},
.probe = gp2a_probe,
diff --git a/drivers/input/misc/kxtj9.c b/drivers/input/misc/kxtj9.c
index 6e29349da537..e058d711256a 100644
--- a/drivers/input/misc/kxtj9.c
+++ b/drivers/input/misc/kxtj9.c
@@ -658,7 +658,6 @@ MODULE_DEVICE_TABLE(i2c, kxtj9_id);
static struct i2c_driver kxtj9_driver = {
.driver = {
.name = NAME,
- .owner = THIS_MODULE,
.pm = &kxtj9_pm_ops,
},
.probe = kxtj9_probe,
diff --git a/drivers/input/misc/max8997_haptic.c b/drivers/input/misc/max8997_haptic.c
index d0f687281339..a806ba3818f7 100644
--- a/drivers/input/misc/max8997_haptic.c
+++ b/drivers/input/misc/max8997_haptic.c
@@ -394,7 +394,7 @@ static const struct platform_device_id max8997_haptic_id[] = {
{ "max8997-haptic", 0 },
{ },
};
-MODULE_DEVICE_TABLE(i2c, max8997_haptic_id);
+MODULE_DEVICE_TABLE(platform, max8997_haptic_id);
static struct platform_driver max8997_haptic_driver = {
.driver = {
@@ -407,7 +407,6 @@ static struct platform_driver max8997_haptic_driver = {
};
module_platform_driver(max8997_haptic_driver);
-MODULE_ALIAS("platform:max8997-haptic");
MODULE_AUTHOR("Donggeun Kim <dg77.kim@samsung.com>");
MODULE_DESCRIPTION("max8997_haptic driver");
MODULE_LICENSE("GPL");
diff --git a/drivers/input/misc/mpu3050.c b/drivers/input/misc/mpu3050.c
index 5e5051351c3a..f088db31cfc7 100644
--- a/drivers/input/misc/mpu3050.c
+++ b/drivers/input/misc/mpu3050.c
@@ -466,7 +466,6 @@ MODULE_DEVICE_TABLE(of, mpu3050_of_match);
static struct i2c_driver mpu3050_i2c_driver = {
.driver = {
.name = "mpu3050",
- .owner = THIS_MODULE,
.pm = &mpu3050_pm,
.of_match_table = mpu3050_of_match,
},
diff --git a/drivers/input/misc/pcf8574_keypad.c b/drivers/input/misc/pcf8574_keypad.c
index 97f711a7bd20..4abdf1efb3e0 100644
--- a/drivers/input/misc/pcf8574_keypad.c
+++ b/drivers/input/misc/pcf8574_keypad.c
@@ -208,7 +208,6 @@ MODULE_DEVICE_TABLE(i2c, pcf8574_kp_id);
static struct i2c_driver pcf8574_kp_driver = {
.driver = {
.name = DRV_NAME,
- .owner = THIS_MODULE,
#ifdef CONFIG_PM
.pm = &pcf8574_kp_pm_ops,
#endif
diff --git a/drivers/input/misc/pmic8xxx-pwrkey.c b/drivers/input/misc/pmic8xxx-pwrkey.c
index c4ca20e63221..3f02e0e03d12 100644
--- a/drivers/input/misc/pmic8xxx-pwrkey.c
+++ b/drivers/input/misc/pmic8xxx-pwrkey.c
@@ -20,17 +20,72 @@
#include <linux/regmap.h>
#include <linux/log2.h>
#include <linux/of.h>
+#include <linux/of_device.h>
#define PON_CNTL_1 0x1C
#define PON_CNTL_PULL_UP BIT(7)
#define PON_CNTL_TRIG_DELAY_MASK (0x7)
+#define PON_CNTL_1_PULL_UP_EN 0xe0
+#define PON_CNTL_1_USB_PWR_EN 0x10
+#define PON_CNTL_1_WD_EN_RESET 0x08
+
+#define PM8058_SLEEP_CTRL 0x02b
+#define PM8921_SLEEP_CTRL 0x10a
+
+#define SLEEP_CTRL_SMPL_EN_RESET 0x04
+
+/* Regulator master enable addresses */
+#define REG_PM8058_VREG_EN_MSM 0x018
+#define REG_PM8058_VREG_EN_GRP_5_4 0x1c8
+
+/* Regulator control registers for shutdown/reset */
+#define PM8058_S0_CTRL 0x004
+#define PM8058_S1_CTRL 0x005
+#define PM8058_S3_CTRL 0x111
+#define PM8058_L21_CTRL 0x120
+#define PM8058_L22_CTRL 0x121
+
+#define PM8058_REGULATOR_ENABLE_MASK 0x80
+#define PM8058_REGULATOR_ENABLE 0x80
+#define PM8058_REGULATOR_DISABLE 0x00
+#define PM8058_REGULATOR_PULL_DOWN_MASK 0x40
+#define PM8058_REGULATOR_PULL_DOWN_EN 0x40
+
+/* Buck CTRL register */
+#define PM8058_SMPS_LEGACY_VREF_SEL 0x20
+#define PM8058_SMPS_LEGACY_VPROG_MASK 0x1f
+#define PM8058_SMPS_ADVANCED_BAND_MASK 0xC0
+#define PM8058_SMPS_ADVANCED_BAND_SHIFT 6
+#define PM8058_SMPS_ADVANCED_VPROG_MASK 0x3f
+
+/* Buck TEST2 registers for shutdown/reset */
+#define PM8058_S0_TEST2 0x084
+#define PM8058_S1_TEST2 0x085
+#define PM8058_S3_TEST2 0x11a
+
+#define PM8058_REGULATOR_BANK_WRITE 0x80
+#define PM8058_REGULATOR_BANK_MASK 0x70
+#define PM8058_REGULATOR_BANK_SHIFT 4
+#define PM8058_REGULATOR_BANK_SEL(n) ((n) << PM8058_REGULATOR_BANK_SHIFT)
+
+/* Buck TEST2 register bank 1 */
+#define PM8058_SMPS_LEGACY_VLOW_SEL 0x01
+
+/* Buck TEST2 register bank 7 */
+#define PM8058_SMPS_ADVANCED_MODE_MASK 0x02
+#define PM8058_SMPS_ADVANCED_MODE 0x02
+#define PM8058_SMPS_LEGACY_MODE 0x00
/**
* struct pmic8xxx_pwrkey - pmic8xxx pwrkey information
* @key_press_irq: key press irq number
+ * @regmap: device regmap
+ * @shutdown_fn: shutdown configuration function
*/
struct pmic8xxx_pwrkey {
int key_press_irq;
+ struct regmap *regmap;
+ int (*shutdown_fn)(struct pmic8xxx_pwrkey *, bool);
};
static irqreturn_t pwrkey_press_irq(int irq, void *_pwr)
@@ -76,6 +131,212 @@ static int __maybe_unused pmic8xxx_pwrkey_resume(struct device *dev)
static SIMPLE_DEV_PM_OPS(pm8xxx_pwr_key_pm_ops,
pmic8xxx_pwrkey_suspend, pmic8xxx_pwrkey_resume);
+static void pmic8xxx_pwrkey_shutdown(struct platform_device *pdev)
+{
+ struct pmic8xxx_pwrkey *pwrkey = platform_get_drvdata(pdev);
+ int error;
+ u8 mask, val;
+ bool reset = system_state == SYSTEM_RESTART;
+
+ if (pwrkey->shutdown_fn) {
+ error = pwrkey->shutdown_fn(pwrkey, reset);
+ if (error)
+ return;
+ }
+
+ /*
+ * Select action to perform (reset or shutdown) when PS_HOLD goes low.
+ * Also ensure that KPD, CBL0, and CBL1 pull ups are enabled and that
+ * USB charging is enabled.
+ */
+ mask = PON_CNTL_1_PULL_UP_EN | PON_CNTL_1_USB_PWR_EN;
+ mask |= PON_CNTL_1_WD_EN_RESET;
+ val = mask;
+ if (!reset)
+ val &= ~PON_CNTL_1_WD_EN_RESET;
+
+ regmap_update_bits(pwrkey->regmap, PON_CNTL_1, mask, val);
+}
+
+/*
+ * Set an SMPS regulator to be disabled in its CTRL register, but enabled
+ * in the master enable register. Also set it's pull down enable bit.
+ * Take care to make sure that the output voltage doesn't change if switching
+ * from advanced mode to legacy mode.
+ */
+static int pm8058_disable_smps_locally_set_pull_down(struct regmap *regmap,
+ u16 ctrl_addr, u16 test2_addr, u16 master_enable_addr,
+ u8 master_enable_bit)
+{
+ int error;
+ u8 vref_sel, vlow_sel, band, vprog, bank;
+ unsigned int reg;
+
+ bank = PM8058_REGULATOR_BANK_SEL(7);
+ error = regmap_write(regmap, test2_addr, bank);
+ if (error)
+ return error;
+
+ error = regmap_read(regmap, test2_addr, &reg);
+ if (error)
+ return error;
+
+ reg &= PM8058_SMPS_ADVANCED_MODE_MASK;
+ /* Check if in advanced mode. */
+ if (reg == PM8058_SMPS_ADVANCED_MODE) {
+ /* Determine current output voltage. */
+ error = regmap_read(regmap, ctrl_addr, &reg);
+ if (error)
+ return error;
+
+ band = reg & PM8058_SMPS_ADVANCED_BAND_MASK;
+ band >>= PM8058_SMPS_ADVANCED_BAND_SHIFT;
+ switch (band) {
+ case 3:
+ vref_sel = 0;
+ vlow_sel = 0;
+ break;
+ case 2:
+ vref_sel = PM8058_SMPS_LEGACY_VREF_SEL;
+ vlow_sel = 0;
+ break;
+ case 1:
+ vref_sel = PM8058_SMPS_LEGACY_VREF_SEL;
+ vlow_sel = PM8058_SMPS_LEGACY_VLOW_SEL;
+ break;
+ default:
+ pr_err("%s: regulator already disabled\n", __func__);
+ return -EPERM;
+ }
+ vprog = reg & PM8058_SMPS_ADVANCED_VPROG_MASK;
+ /* Round up if fine step is in use. */
+ vprog = (vprog + 1) >> 1;
+ if (vprog > PM8058_SMPS_LEGACY_VPROG_MASK)
+ vprog = PM8058_SMPS_LEGACY_VPROG_MASK;
+
+ /* Set VLOW_SEL bit. */
+ bank = PM8058_REGULATOR_BANK_SEL(1);
+ error = regmap_write(regmap, test2_addr, bank);
+ if (error)
+ return error;
+
+ error = regmap_update_bits(regmap, test2_addr,
+ PM8058_REGULATOR_BANK_WRITE | PM8058_REGULATOR_BANK_MASK
+ | PM8058_SMPS_LEGACY_VLOW_SEL,
+ PM8058_REGULATOR_BANK_WRITE |
+ PM8058_REGULATOR_BANK_SEL(1) | vlow_sel);
+ if (error)
+ return error;
+
+ /* Switch to legacy mode */
+ bank = PM8058_REGULATOR_BANK_SEL(7);
+ error = regmap_write(regmap, test2_addr, bank);
+ if (error)
+ return error;
+
+ error = regmap_update_bits(regmap, test2_addr,
+ PM8058_REGULATOR_BANK_WRITE |
+ PM8058_REGULATOR_BANK_MASK |
+ PM8058_SMPS_ADVANCED_MODE_MASK,
+ PM8058_REGULATOR_BANK_WRITE |
+ PM8058_REGULATOR_BANK_SEL(7) |
+ PM8058_SMPS_LEGACY_MODE);
+ if (error)
+ return error;
+
+ /* Enable locally, enable pull down, keep voltage the same. */
+ error = regmap_update_bits(regmap, ctrl_addr,
+ PM8058_REGULATOR_ENABLE_MASK |
+ PM8058_REGULATOR_PULL_DOWN_MASK |
+ PM8058_SMPS_LEGACY_VREF_SEL |
+ PM8058_SMPS_LEGACY_VPROG_MASK,
+ PM8058_REGULATOR_ENABLE | PM8058_REGULATOR_PULL_DOWN_EN
+ | vref_sel | vprog);
+ if (error)
+ return error;
+ }
+
+ /* Enable in master control register. */
+ error = regmap_update_bits(regmap, master_enable_addr,
+ master_enable_bit, master_enable_bit);
+ if (error)
+ return error;
+
+ /* Disable locally and enable pull down. */
+ return regmap_update_bits(regmap, ctrl_addr,
+ PM8058_REGULATOR_ENABLE_MASK | PM8058_REGULATOR_PULL_DOWN_MASK,
+ PM8058_REGULATOR_DISABLE | PM8058_REGULATOR_PULL_DOWN_EN);
+}
+
+static int pm8058_disable_ldo_locally_set_pull_down(struct regmap *regmap,
+ u16 ctrl_addr, u16 master_enable_addr, u8 master_enable_bit)
+{
+ int error;
+
+ /* Enable LDO in master control register. */
+ error = regmap_update_bits(regmap, master_enable_addr,
+ master_enable_bit, master_enable_bit);
+ if (error)
+ return error;
+
+ /* Disable LDO in CTRL register and set pull down */
+ return regmap_update_bits(regmap, ctrl_addr,
+ PM8058_REGULATOR_ENABLE_MASK | PM8058_REGULATOR_PULL_DOWN_MASK,
+ PM8058_REGULATOR_DISABLE | PM8058_REGULATOR_PULL_DOWN_EN);
+}
+
+static int pm8058_pwrkey_shutdown(struct pmic8xxx_pwrkey *pwrkey, bool reset)
+{
+ int error;
+ struct regmap *regmap = pwrkey->regmap;
+ u8 mask, val;
+
+ /* When shutting down, enable active pulldowns on important rails. */
+ if (!reset) {
+ /* Disable SMPS's 0,1,3 locally and set pulldown enable bits. */
+ pm8058_disable_smps_locally_set_pull_down(regmap,
+ PM8058_S0_CTRL, PM8058_S0_TEST2,
+ REG_PM8058_VREG_EN_MSM, BIT(7));
+ pm8058_disable_smps_locally_set_pull_down(regmap,
+ PM8058_S1_CTRL, PM8058_S1_TEST2,
+ REG_PM8058_VREG_EN_MSM, BIT(6));
+ pm8058_disable_smps_locally_set_pull_down(regmap,
+ PM8058_S3_CTRL, PM8058_S3_TEST2,
+ REG_PM8058_VREG_EN_GRP_5_4, BIT(7) | BIT(4));
+ /* Disable LDO 21 locally and set pulldown enable bit. */
+ pm8058_disable_ldo_locally_set_pull_down(regmap,
+ PM8058_L21_CTRL, REG_PM8058_VREG_EN_GRP_5_4,
+ BIT(1));
+ }
+
+ /*
+ * Fix-up: Set regulator LDO22 to 1.225 V in high power mode. Leave its
+ * pull-down state intact. This ensures a safe shutdown.
+ */
+ error = regmap_update_bits(regmap, PM8058_L22_CTRL, 0xbf, 0x93);
+ if (error)
+ return error;
+
+ /* Enable SMPL if resetting is desired */
+ mask = SLEEP_CTRL_SMPL_EN_RESET;
+ val = 0;
+ if (reset)
+ val = mask;
+ return regmap_update_bits(regmap, PM8058_SLEEP_CTRL, mask, val);
+}
+
+static int pm8921_pwrkey_shutdown(struct pmic8xxx_pwrkey *pwrkey, bool reset)
+{
+ struct regmap *regmap = pwrkey->regmap;
+ u8 mask = SLEEP_CTRL_SMPL_EN_RESET;
+ u8 val = 0;
+
+ /* Enable SMPL if resetting is desired */
+ if (reset)
+ val = mask;
+ return regmap_update_bits(regmap, PM8921_SLEEP_CTRL, mask, val);
+}
+
static int pmic8xxx_pwrkey_probe(struct platform_device *pdev)
{
struct input_dev *pwr;
@@ -109,6 +370,8 @@ static int pmic8xxx_pwrkey_probe(struct platform_device *pdev)
if (!pwrkey)
return -ENOMEM;
+ pwrkey->shutdown_fn = of_device_get_match_data(&pdev->dev);
+ pwrkey->regmap = regmap;
pwrkey->key_press_irq = key_press_irq;
pwr = devm_input_allocate_device(&pdev->dev);
@@ -182,8 +445,8 @@ static int pmic8xxx_pwrkey_remove(struct platform_device *pdev)
}
static const struct of_device_id pm8xxx_pwr_key_id_table[] = {
- { .compatible = "qcom,pm8058-pwrkey" },
- { .compatible = "qcom,pm8921-pwrkey" },
+ { .compatible = "qcom,pm8058-pwrkey", .data = &pm8058_pwrkey_shutdown },
+ { .compatible = "qcom,pm8921-pwrkey", .data = &pm8921_pwrkey_shutdown },
{ }
};
MODULE_DEVICE_TABLE(of, pm8xxx_pwr_key_id_table);
@@ -191,6 +454,7 @@ MODULE_DEVICE_TABLE(of, pm8xxx_pwr_key_id_table);
static struct platform_driver pmic8xxx_pwrkey_driver = {
.probe = pmic8xxx_pwrkey_probe,
.remove = pmic8xxx_pwrkey_remove,
+ .shutdown = pmic8xxx_pwrkey_shutdown,
.driver = {
.name = "pm8xxx-pwrkey",
.pm = &pm8xxx_pwr_key_pm_ops,
diff --git a/drivers/input/misc/uinput.c b/drivers/input/misc/uinput.c
index 421e29e4cd81..345df9b03aed 100644
--- a/drivers/input/misc/uinput.c
+++ b/drivers/input/misc/uinput.c
@@ -320,10 +320,8 @@ static int uinput_validate_absbits(struct input_dev *dev)
* Check if absmin/absmax/absfuzz/absflat are sane.
*/
- for (cnt = 0; cnt < ABS_CNT; cnt++) {
+ for_each_set_bit(cnt, dev->absbit, ABS_CNT) {
int min, max;
- if (!test_bit(cnt, dev->absbit))
- continue;
min = input_abs_get_min(dev, cnt);
max = input_abs_get_max(dev, cnt);
@@ -416,7 +414,7 @@ static int uinput_setup_device(struct uinput_device *udev,
dev->id.product = user_dev->id.product;
dev->id.version = user_dev->id.version;
- for (i = 0; i < ABS_CNT; i++) {
+ for_each_set_bit(i, dev->absbit, ABS_CNT) {
input_abs_set_max(dev, i, user_dev->absmax[i]);
input_abs_set_min(dev, i, user_dev->absmin[i]);
input_abs_set_fuzz(dev, i, user_dev->absfuzz[i]);