summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Documentation/devicetree/bindings/input/qpnp-power-on.txt2
-rw-r--r--arch/arm/boot/dts/qcom/msm-pm660.dtsi1
-rw-r--r--drivers/input/misc/qpnp-power-on.c61
3 files changed, 60 insertions, 4 deletions
diff --git a/Documentation/devicetree/bindings/input/qpnp-power-on.txt b/Documentation/devicetree/bindings/input/qpnp-power-on.txt
index a596aa1c595d..c2550e6fe26c 100644
--- a/Documentation/devicetree/bindings/input/qpnp-power-on.txt
+++ b/Documentation/devicetree/bindings/input/qpnp-power-on.txt
@@ -82,6 +82,8 @@ Optional properties:
- qcom,shutdown-poweroff-type Same description as qcom,warm-reset-poweroff-
type but this applies for the system shutdown
case.
+- qcom,kpdpwr-sw-debounce Boolean property to enable the debounce logic
+ on the KPDPWR_N rising edge.
All the below properties are in the sub-node section (properties of the child
diff --git a/arch/arm/boot/dts/qcom/msm-pm660.dtsi b/arch/arm/boot/dts/qcom/msm-pm660.dtsi
index f20238123bca..9bdaedd72585 100644
--- a/arch/arm/boot/dts/qcom/msm-pm660.dtsi
+++ b/arch/arm/boot/dts/qcom/msm-pm660.dtsi
@@ -41,6 +41,7 @@
interrupt-names = "kpdpwr", "resin",
"resin-bark", "kpdpwr-resin-bark";
qcom,pon-dbc-delay = <15625>;
+ qcom,kpdpwr-sw-debounce;
qcom,system-reset;
qcom,store-hard-reset-reason;
diff --git a/drivers/input/misc/qpnp-power-on.c b/drivers/input/misc/qpnp-power-on.c
index add11d47ea2f..339f94c072f4 100644
--- a/drivers/input/misc/qpnp-power-on.c
+++ b/drivers/input/misc/qpnp-power-on.c
@@ -207,7 +207,7 @@ struct qpnp_pon {
int pon_power_off_reason;
int num_pon_reg;
int num_pon_config;
- u32 dbc;
+ u32 dbc_time_us;
u32 uvlo;
int warm_reset_poff_type;
int hard_reset_poff_type;
@@ -219,6 +219,8 @@ struct qpnp_pon {
u8 warm_reset_reason2;
bool is_spon;
bool store_hard_reset_reason;
+ bool kpdpwr_dbc_enable;
+ ktime_t kpdpwr_last_release_time;
};
static int pon_ship_mode_en;
@@ -381,7 +383,7 @@ static int qpnp_pon_set_dbc(struct qpnp_pon *pon, u32 delay)
int rc = 0;
u32 val;
- if (delay == pon->dbc)
+ if (delay == pon->dbc_time_us)
goto out;
if (pon->pon_input)
@@ -409,7 +411,7 @@ static int qpnp_pon_set_dbc(struct qpnp_pon *pon, u32 delay)
goto unlock;
}
- pon->dbc = delay;
+ pon->dbc_time_us = delay;
unlock:
if (pon->pon_input)
@@ -418,12 +420,34 @@ out:
return rc;
}
+static int qpnp_pon_get_dbc(struct qpnp_pon *pon, u32 *delay)
+{
+ int rc;
+ unsigned int val;
+
+ rc = regmap_read(pon->regmap, QPNP_PON_DBC_CTL(pon), &val);
+ if (rc) {
+ pr_err("Unable to read pon_dbc_ctl rc=%d\n", rc);
+ return rc;
+ }
+ val &= QPNP_PON_DBC_DELAY_MASK(pon);
+
+ if (is_pon_gen2(pon))
+ *delay = USEC_PER_SEC /
+ (1 << (QPNP_PON_GEN2_DELAY_BIT_SHIFT - val));
+ else
+ *delay = USEC_PER_SEC /
+ (1 << (QPNP_PON_DELAY_BIT_SHIFT - val));
+
+ return rc;
+}
+
static ssize_t qpnp_pon_dbc_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct qpnp_pon *pon = dev_get_drvdata(dev);
- return snprintf(buf, QPNP_PON_BUFFER_SIZE, "%d\n", pon->dbc);
+ return snprintf(buf, QPNP_PON_BUFFER_SIZE, "%d\n", pon->dbc_time_us);
}
static ssize_t qpnp_pon_dbc_store(struct device *dev,
@@ -777,6 +801,7 @@ qpnp_pon_input_dispatch(struct qpnp_pon *pon, u32 pon_type)
u8 pon_rt_bit = 0;
u32 key_status;
uint pon_rt_sts;
+ u64 elapsed_us;
cfg = qpnp_get_cfg(pon, pon_type);
if (!cfg)
@@ -786,6 +811,15 @@ qpnp_pon_input_dispatch(struct qpnp_pon *pon, u32 pon_type)
if (!cfg->key_code)
return 0;
+ if (pon->kpdpwr_dbc_enable && cfg->pon_type == PON_KPDPWR) {
+ elapsed_us = ktime_us_delta(ktime_get(),
+ pon->kpdpwr_last_release_time);
+ if (elapsed_us < pon->dbc_time_us) {
+ pr_debug("Ignoring kpdpwr event - within debounce time\n");
+ return 0;
+ }
+ }
+
/* check the RT status to get the current status of the line */
rc = regmap_read(pon->regmap, QPNP_PON_RT_STS(pon), &pon_rt_sts);
if (rc) {
@@ -814,6 +848,11 @@ qpnp_pon_input_dispatch(struct qpnp_pon *pon, u32 pon_type)
cfg->key_code, pon_rt_sts);
key_status = pon_rt_sts & pon_rt_bit;
+ if (pon->kpdpwr_dbc_enable && cfg->pon_type == PON_KPDPWR) {
+ if (!key_status)
+ pon->kpdpwr_last_release_time = ktime_get();
+ }
+
/*
* simulate press event in case release event occurred
* without a press event
@@ -2233,8 +2272,22 @@ static int qpnp_pon_probe(struct platform_device *pdev)
}
} else {
rc = qpnp_pon_set_dbc(pon, delay);
+ if (rc) {
+ dev_err(&pdev->dev,
+ "Unable to set PON debounce delay rc=%d\n", rc);
+ return rc;
+ }
+ }
+ rc = qpnp_pon_get_dbc(pon, &pon->dbc_time_us);
+ if (rc) {
+ dev_err(&pdev->dev,
+ "Unable to get PON debounce delay rc=%d\n", rc);
+ return rc;
}
+ pon->kpdpwr_dbc_enable = of_property_read_bool(pon->pdev->dev.of_node,
+ "qcom,kpdpwr-sw-debounce");
+
rc = of_property_read_u32(pon->pdev->dev.of_node,
"qcom,warm-reset-poweroff-type",
&pon->warm_reset_poff_type);