Merge "ARM: dts: msm: Enable Short-Circuit (SC) interrupt for LCDB on PM660L"

This commit is contained in:
Linux Build Service Account 2017-03-08 06:51:04 -08:00 committed by Gerrit - the friendly Code Review server
commit bfc0e4b108
2 changed files with 140 additions and 1 deletions

View file

@ -394,6 +394,9 @@
#address-cells = <1>;
#size-cells = <1>;
reg = <0xec00 0x100>;
interrupts = <0x3 0xec 0x1 IRQ_TYPE_EDGE_RISING>;
interrupt-names = "sc-irq";
qcom,force-module-reenable;
lcdb_ldo_vreg: ldo {

View file

@ -16,6 +16,7 @@
#include <linux/delay.h>
#include <linux/device.h>
#include <linux/interrupt.h>
#include <linux/ktime.h>
#include <linux/module.h>
#include <linux/of_irq.h>
#include <linux/platform_device.h>
@ -31,6 +32,13 @@
#define INT_RT_STATUS_REG 0x10
#define VREG_OK_RT_STS_BIT BIT(0)
#define SC_ERROR_RT_STS_BIT BIT(1)
#define LCDB_STS3_REG 0x0A
#define LDO_VREG_OK_BIT BIT(7)
#define LCDB_STS4_REG 0x0B
#define NCP_VREG_OK_BIT BIT(7)
#define LCDB_AUTO_TOUCH_WAKE_CTL_REG 0x40
#define EN_AUTO_TOUCH_WAKE_BIT BIT(7)
@ -185,6 +193,7 @@ struct qpnp_lcdb {
struct platform_device *pdev;
struct regmap *regmap;
u32 base;
int sc_irq;
/* TTW params */
bool ttw_enable;
@ -196,6 +205,9 @@ struct qpnp_lcdb {
/* status parameters */
bool lcdb_enabled;
bool settings_saved;
bool lcdb_sc_disable;
int sc_count;
ktime_t sc_module_enable_time;
struct mutex lcdb_mutex;
struct mutex read_write_mutex;
@ -572,8 +584,11 @@ static int qpnp_lcdb_enable(struct qpnp_lcdb *lcdb)
int rc = 0, timeout, delay;
u8 val = 0;
if (lcdb->lcdb_enabled)
if (lcdb->lcdb_enabled || lcdb->lcdb_sc_disable) {
pr_debug("lcdb_enabled=%d lcdb_sc_disable=%d\n",
lcdb->lcdb_enabled, lcdb->lcdb_sc_disable);
return 0;
}
if (lcdb->ttw_enable) {
rc = qpnp_lcdb_ttw_exit(lcdb);
@ -676,6 +691,111 @@ static int qpnp_lcdb_disable(struct qpnp_lcdb *lcdb)
return rc;
}
#define LCDB_SC_RESET_CNT_DLY_US 1000000
#define LCDB_SC_CNT_MAX 10
static int qpnp_lcdb_handle_sc_event(struct qpnp_lcdb *lcdb)
{
int rc = 0;
s64 elapsed_time_us;
mutex_lock(&lcdb->lcdb_mutex);
rc = qpnp_lcdb_disable(lcdb);
if (rc < 0) {
pr_err("Failed to disable lcdb rc=%d\n", rc);
goto unlock_mutex;
}
/* Check if the SC re-occurred immediately */
elapsed_time_us = ktime_us_delta(ktime_get(),
lcdb->sc_module_enable_time);
if (elapsed_time_us > LCDB_SC_RESET_CNT_DLY_US) {
lcdb->sc_count = 0;
} else if (lcdb->sc_count > LCDB_SC_CNT_MAX) {
pr_err("SC trigged %d times, disabling LCDB forever!\n",
lcdb->sc_count);
lcdb->lcdb_sc_disable = true;
goto unlock_mutex;
}
lcdb->sc_count++;
lcdb->sc_module_enable_time = ktime_get();
/* delay for SC to clear */
usleep_range(10000, 10100);
rc = qpnp_lcdb_enable(lcdb);
if (rc < 0)
pr_err("Failed to enable lcdb rc=%d\n", rc);
unlock_mutex:
mutex_unlock(&lcdb->lcdb_mutex);
return rc;
}
static irqreturn_t qpnp_lcdb_sc_irq_handler(int irq, void *data)
{
struct qpnp_lcdb *lcdb = data;
int rc;
u8 val, val2[2] = {0};
rc = qpnp_lcdb_read(lcdb, lcdb->base + INT_RT_STATUS_REG, &val, 1);
if (rc < 0)
goto irq_handled;
if (val & SC_ERROR_RT_STS_BIT) {
rc = qpnp_lcdb_read(lcdb,
lcdb->base + LCDB_MISC_CTL_REG, &val, 1);
if (rc < 0)
goto irq_handled;
if (val & EN_TOUCH_WAKE_BIT) {
/* blanking time */
usleep_range(300, 310);
/*
* The status registers need to written with any value
* before reading
*/
rc = qpnp_lcdb_write(lcdb,
lcdb->base + LCDB_STS3_REG, val2, 2);
if (rc < 0)
goto irq_handled;
rc = qpnp_lcdb_read(lcdb,
lcdb->base + LCDB_STS3_REG, val2, 2);
if (rc < 0)
goto irq_handled;
if (!(val2[0] & LDO_VREG_OK_BIT) ||
!(val2[1] & NCP_VREG_OK_BIT)) {
rc = qpnp_lcdb_handle_sc_event(lcdb);
if (rc < 0) {
pr_err("Failed to handle SC rc=%d\n",
rc);
goto irq_handled;
}
}
} else {
/* blanking time */
usleep_range(2000, 2100);
/* Read the SC status again to confirm true SC */
rc = qpnp_lcdb_read(lcdb,
lcdb->base + INT_RT_STATUS_REG, &val, 1);
if (rc < 0)
goto irq_handled;
if (val & SC_ERROR_RT_STS_BIT) {
rc = qpnp_lcdb_handle_sc_event(lcdb);
if (rc < 0) {
pr_err("Failed to handle SC rc=%d\n",
rc);
goto irq_handled;
}
}
}
}
irq_handled:
return IRQ_HANDLED;
}
#define MIN_BST_VOLTAGE_MV 4700
#define MAX_BST_VOLTAGE_MV 6250
#define MIN_VOLTAGE_MV 4000
@ -1554,6 +1674,18 @@ static int qpnp_lcdb_hw_init(struct qpnp_lcdb *lcdb)
return rc;
}
if (lcdb->sc_irq >= 0) {
lcdb->sc_count = 0;
rc = devm_request_threaded_irq(lcdb->dev, lcdb->sc_irq,
NULL, qpnp_lcdb_sc_irq_handler, IRQF_ONESHOT,
"qpnp_lcdb_sc_irq", lcdb);
if (rc < 0) {
pr_err("Unable to request sc(%d) irq rc=%d\n",
lcdb->sc_irq, rc);
return rc;
}
}
if (!is_lcdb_enabled(lcdb)) {
rc = qpnp_lcdb_read(lcdb, lcdb->base +
LCDB_MODULE_RDY_REG, &val, 1);
@ -1622,6 +1754,10 @@ static int qpnp_lcdb_parse_dt(struct qpnp_lcdb *lcdb)
lcdb->ttw_enable = true;
}
lcdb->sc_irq = platform_get_irq_byname(lcdb->pdev, "sc-irq");
if (lcdb->sc_irq < 0)
pr_debug("sc irq is not defined\n");
return rc;
}