Merge "ARM: dts: msm: Specify the WLED interrupts properly for pmi8998/pm2falcon"

This commit is contained in:
Linux Build Service Account 2016-12-09 19:59:05 -08:00 committed by Gerrit - the friendly Code Review server
commit a541a81870
3 changed files with 61 additions and 63 deletions

View file

@ -222,15 +222,12 @@
pm2falcon_wled: qcom,leds@d800 { pm2falcon_wled: qcom,leds@d800 {
compatible = "qcom,qpnp-wled"; compatible = "qcom,qpnp-wled";
reg = <0xd800 0x100>, reg = <0xd800 0x100>,
<0xd900 0x100>, <0xd900 0x100>;
<0xdc00 0x100>,
<0xde00 0x100>;
reg-names = "qpnp-wled-ctrl-base", reg-names = "qpnp-wled-ctrl-base",
"qpnp-wled-sink-base", "qpnp-wled-sink-base";
"qpnp-wled-ibb-base", interrupts = <0x3 0xd8 0x1 IRQ_TYPE_EDGE_BOTH>,
"qpnp-wled-lab-base"; <0x3 0xd8 0x2 IRQ_TYPE_EDGE_BOTH>;
interrupts = <0x3 0xd8 0x2>; interrupt-names = "ovp-irq", "sc-irq";
interrupt-names = "sc-irq";
linux,name = "wled"; linux,name = "wled";
linux,default-trigger = "bkl-trigger"; linux,default-trigger = "bkl-trigger";
qcom,fdbk-output = "auto"; qcom,fdbk-output = "auto";

View file

@ -585,16 +585,12 @@
pmi8998_wled: qcom,leds@d800 { pmi8998_wled: qcom,leds@d800 {
compatible = "qcom,qpnp-wled"; compatible = "qcom,qpnp-wled";
reg = <0xd800 0x100>, reg = <0xd800 0x100>,
<0xd900 0x100>, <0xd900 0x100>;
<0xdc00 0x100>,
<0xde00 0x100>;
reg-names = "qpnp-wled-ctrl-base", reg-names = "qpnp-wled-ctrl-base",
"qpnp-wled-sink-base", "qpnp-wled-sink-base";
"qpnp-wled-ibb-base", interrupts = <0x3 0xd8 0x1 IRQ_TYPE_EDGE_BOTH>,
"qpnp-wled-lab-base"; <0x3 0xd8 0x2 IRQ_TYPE_EDGE_BOTH>;
interrupts = <0x3 0xd8 0x2>; interrupt-names = "ovp-irq", "sc-irq";
interrupt-names = "sc-irq";
status = "okay";
linux,name = "wled"; linux,name = "wled";
linux,default-trigger = "bkl-trigger"; linux,default-trigger = "bkl-trigger";
qcom,fdbk-output = "auto"; qcom,fdbk-output = "auto";
@ -614,6 +610,7 @@
qcom,en-ext-pfet-sc-pro; qcom,en-ext-pfet-sc-pro;
qcom,pmic-revid = <&pmi8998_revid>; qcom,pmic-revid = <&pmi8998_revid>;
qcom,loop-auto-gm-en; qcom,loop-auto-gm-en;
status = "okay";
}; };
pmi8998_haptics: qcom,haptic@c000 { pmi8998_haptics: qcom,haptic@c000 {

View file

@ -27,17 +27,12 @@
#include <linux/leds-qpnp-wled.h> #include <linux/leds-qpnp-wled.h>
#include <linux/qpnp/qpnp-revid.h> #include <linux/qpnp/qpnp-revid.h>
#define QPNP_IRQ_FLAGS (IRQF_TRIGGER_RISING | \
IRQF_TRIGGER_FALLING | \
IRQF_ONESHOT)
/* base addresses */ /* base addresses */
#define QPNP_WLED_CTRL_BASE "qpnp-wled-ctrl-base" #define QPNP_WLED_CTRL_BASE "qpnp-wled-ctrl-base"
#define QPNP_WLED_SINK_BASE "qpnp-wled-sink-base" #define QPNP_WLED_SINK_BASE "qpnp-wled-sink-base"
/* ctrl registers */ /* ctrl registers */
#define QPNP_WLED_INT_EN_SET(b) (b + 0x15) #define QPNP_WLED_FAULT_STATUS(b) (b + 0x08)
#define QPNP_WLED_INT_EN_CLR(b) (b + 0x16)
#define QPNP_WLED_EN_REG(b) (b + 0x46) #define QPNP_WLED_EN_REG(b) (b + 0x46)
#define QPNP_WLED_FDBK_OP_REG(b) (b + 0x48) #define QPNP_WLED_FDBK_OP_REG(b) (b + 0x48)
#define QPNP_WLED_VREF_REG(b) (b + 0x49) #define QPNP_WLED_VREF_REG(b) (b + 0x49)
@ -114,8 +109,6 @@
#define QPNP_WLED_SWITCH_FREQ_OVERWRITE 0x80 #define QPNP_WLED_SWITCH_FREQ_OVERWRITE 0x80
#define QPNP_WLED_OVP_MASK GENMASK(1, 0) #define QPNP_WLED_OVP_MASK GENMASK(1, 0)
#define QPNP_WLED_TEST4_EN_VREF_UP 0x32 #define QPNP_WLED_TEST4_EN_VREF_UP 0x32
#define QPNP_WLED_INT_EN_SET_OVP_EN 0x02
#define QPNP_WLED_OVP_FLT_SLEEP_US 10
#define QPNP_WLED_TEST4_EN_IIND_UP 0x1 #define QPNP_WLED_TEST4_EN_IIND_UP 0x1
/* sink registers */ /* sink registers */
@ -183,7 +176,7 @@
#define QPNP_WLED_MODULE_EN_REG(b) (b + 0x46) #define QPNP_WLED_MODULE_EN_REG(b) (b + 0x46)
#define QPNP_WLED_MODULE_RDY_MASK 0x7F #define QPNP_WLED_MODULE_RDY_MASK 0x7F
#define QPNP_WLED_MODULE_RDY_SHIFT 7 #define QPNP_WLED_MODULE_RDY_SHIFT 7
#define QPNP_WLED_MODULE_EN_MASK 0x7F #define QPNP_WLED_MODULE_EN_MASK BIT(7)
#define QPNP_WLED_MODULE_EN_SHIFT 7 #define QPNP_WLED_MODULE_EN_SHIFT 7
#define QPNP_WLED_DISP_SEL_MASK 0x7F #define QPNP_WLED_DISP_SEL_MASK 0x7F
#define QPNP_WLED_DISP_SEL_SHIFT 7 #define QPNP_WLED_DISP_SEL_SHIFT 7
@ -386,6 +379,7 @@ struct qpnp_wled {
bool disp_type_amoled; bool disp_type_amoled;
bool en_ext_pfet_sc_pro; bool en_ext_pfet_sc_pro;
bool prev_state; bool prev_state;
bool ovp_irq_disabled;
}; };
/* helper to read a pmic register */ /* helper to read a pmic register */
@ -533,34 +527,29 @@ static int qpnp_wled_module_en(struct qpnp_wled *wled,
u16 base_addr, bool state) u16 base_addr, bool state)
{ {
int rc; int rc;
u8 reg;
/* disable OVP fault interrupt */ rc = qpnp_wled_masked_write_reg(wled,
if (state) { QPNP_WLED_MODULE_EN_REG(base_addr),
reg = QPNP_WLED_INT_EN_SET_OVP_EN; QPNP_WLED_MODULE_EN_MASK,
rc = qpnp_wled_write_reg(wled, QPNP_WLED_INT_EN_CLR(base_addr), state << QPNP_WLED_MODULE_EN_SHIFT);
reg);
if (rc)
return rc;
}
rc = qpnp_wled_read_reg(wled, QPNP_WLED_MODULE_EN_REG(base_addr), &reg);
if (rc < 0) if (rc < 0)
return rc; return rc;
reg &= QPNP_WLED_MODULE_EN_MASK;
reg |= (state << QPNP_WLED_MODULE_EN_SHIFT);
rc = qpnp_wled_write_reg(wled, QPNP_WLED_MODULE_EN_REG(base_addr), reg);
if (rc)
return rc;
/* enable OVP fault interrupt */ if (wled->ovp_irq > 0) {
if (state && (wled->ovp_irq > 0)) { if (state && wled->ovp_irq_disabled) {
udelay(QPNP_WLED_OVP_FLT_SLEEP_US); /*
reg = QPNP_WLED_INT_EN_SET_OVP_EN; * Wait for at least 10ms before enabling OVP fault
rc = qpnp_wled_write_reg(wled, QPNP_WLED_INT_EN_SET(base_addr), * interrupt after enabling the module so that soft
reg); * start is completed. Keep OVP interrupt disabled
if (rc) * when the module is disabled.
return rc; */
usleep_range(10000, 11000);
enable_irq(wled->ovp_irq);
wled->ovp_irq_disabled = false;
} else if (!state && !wled->ovp_irq_disabled) {
disable_irq(wled->ovp_irq);
wled->ovp_irq_disabled = true;
}
} }
return 0; return 0;
@ -1027,26 +1016,44 @@ static int qpnp_wled_set_disp(struct qpnp_wled *wled, u16 base_addr)
} }
/* ovp irq handler */ /* ovp irq handler */
static irqreturn_t qpnp_wled_ovp_irq(int irq, void *_wled) static irqreturn_t qpnp_wled_ovp_irq_handler(int irq, void *_wled)
{ {
struct qpnp_wled *wled = _wled; struct qpnp_wled *wled = _wled;
int rc;
u8 val;
dev_dbg(&wled->pdev->dev, "ovp detected\n"); rc = qpnp_wled_read_reg(wled,
QPNP_WLED_FAULT_STATUS(wled->ctrl_base), &val);
if (rc < 0) {
pr_err("Error in reading WLED_FAULT_STATUS rc=%d\n", rc);
return IRQ_HANDLED;
}
pr_err("WLED OVP fault detected, fault_status= %x\n", val);
return IRQ_HANDLED; return IRQ_HANDLED;
} }
/* short circuit irq handler */ /* short circuit irq handler */
static irqreturn_t qpnp_wled_sc_irq(int irq, void *_wled) static irqreturn_t qpnp_wled_sc_irq_handler(int irq, void *_wled)
{ {
struct qpnp_wled *wled = _wled; struct qpnp_wled *wled = _wled;
int rc;
u8 val;
dev_err(&wled->pdev->dev, rc = qpnp_wled_read_reg(wled,
"Short circuit detected %d times\n", ++wled->sc_cnt); QPNP_WLED_FAULT_STATUS(wled->ctrl_base), &val);
if (rc < 0) {
pr_err("Error in reading WLED_FAULT_STATUS rc=%d\n", rc);
return IRQ_HANDLED;
}
pr_err("WLED short circuit detected %d times fault_status=%x\n",
++wled->sc_cnt, val);
mutex_lock(&wled->lock);
qpnp_wled_module_en(wled, wled->ctrl_base, false); qpnp_wled_module_en(wled, wled->ctrl_base, false);
msleep(QPNP_WLED_SC_DLY_MS); msleep(QPNP_WLED_SC_DLY_MS);
qpnp_wled_module_en(wled, wled->ctrl_base, true); qpnp_wled_module_en(wled, wled->ctrl_base, true);
mutex_unlock(&wled->lock);
return IRQ_HANDLED; return IRQ_HANDLED;
} }
@ -1625,11 +1632,9 @@ static int qpnp_wled_config(struct qpnp_wled *wled)
/* setup ovp and sc irqs */ /* setup ovp and sc irqs */
if (wled->ovp_irq >= 0) { if (wled->ovp_irq >= 0) {
rc = devm_request_threaded_irq(&wled->pdev->dev, rc = devm_request_threaded_irq(&wled->pdev->dev, wled->ovp_irq,
wled->ovp_irq, NULL, qpnp_wled_ovp_irq_handler, IRQF_ONESHOT,
NULL, qpnp_wled_ovp_irq, "qpnp_wled_ovp_irq", wled);
QPNP_IRQ_FLAGS,
"qpnp_wled_ovp_irq", wled);
if (rc < 0) { if (rc < 0) {
dev_err(&wled->pdev->dev, dev_err(&wled->pdev->dev,
"Unable to request ovp(%d) IRQ(err:%d)\n", "Unable to request ovp(%d) IRQ(err:%d)\n",
@ -1641,9 +1646,8 @@ static int qpnp_wled_config(struct qpnp_wled *wled)
if (wled->sc_irq >= 0) { if (wled->sc_irq >= 0) {
wled->sc_cnt = 0; wled->sc_cnt = 0;
rc = devm_request_threaded_irq(&wled->pdev->dev, wled->sc_irq, rc = devm_request_threaded_irq(&wled->pdev->dev, wled->sc_irq,
NULL, qpnp_wled_sc_irq, NULL, qpnp_wled_sc_irq_handler, IRQF_ONESHOT,
QPNP_IRQ_FLAGS, "qpnp_wled_sc_irq", wled);
"qpnp_wled_sc_irq", wled);
if (rc < 0) { if (rc < 0) {
dev_err(&wled->pdev->dev, dev_err(&wled->pdev->dev,
"Unable to request sc(%d) IRQ(err:%d)\n", "Unable to request sc(%d) IRQ(err:%d)\n",