summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDevesh Jhunjhunwala <deveshj@codeaurora.org>2016-07-07 16:23:12 -0700
committerDevesh Jhunjhunwala <deveshj@codeaurora.org>2016-07-29 11:22:30 -0700
commitba678210c5b35cff1273ee629bf30f462d01a941 (patch)
tree5a14d1fe6ec386ad287d137fa1228e5b33109813
parenta0a1d3cd64973b7fe2c5c5ad99a3cfd9b0526d9a (diff)
leds: qpnp-flash-v2: Add support for droop and fault detection
Add support for configuring the following features available in flash LED: 1. VPH droop detection 2. Short circuit fault detection 3. Open circuit fault detection CRs-Fixed: 1024187 Change-Id: I982e51ba62f0a75d1dcd3ef30e5d1249c970ffde Signed-off-by: Devesh Jhunjhunwala <deveshj@codeaurora.org>
-rw-r--r--Documentation/devicetree/bindings/leds/leds-qpnp-flash-v2.txt18
-rw-r--r--drivers/leds/leds-qpnp-flash-v2.c156
2 files changed, 160 insertions, 14 deletions
diff --git a/Documentation/devicetree/bindings/leds/leds-qpnp-flash-v2.txt b/Documentation/devicetree/bindings/leds/leds-qpnp-flash-v2.txt
index 7b06a6bd896a..51bcb07cbb6e 100644
--- a/Documentation/devicetree/bindings/leds/leds-qpnp-flash-v2.txt
+++ b/Documentation/devicetree/bindings/leds/leds-qpnp-flash-v2.txt
@@ -16,8 +16,22 @@ Optional properties:
- interrupts : Specifies the interrupts associated with flash-led.
- interrupt-names : Specify the interrupt names associated with interrupts.
- qcom,hdrm-auto-mode : Boolean type to select headroom auto mode enabled or not
-- qcom,isc-delay : Integer type to specify short circuit delay. Valid values are 32, 64,
- 128, 192. Unit is us.
+- qcom,isc-delay-us : Integer type to specify short circuit delay. Valid values are 32, 64,
+ 128, 192. Unit is uS.
+- qcom,warmup-delay-us : Integer type to specify warm up delay. Valid values are 32, 64,
+ 128, 192. Unit is uS.
+- qcom,short-circuit-det : Boolean property which enables short circuit fault detection.
+- qcom,open-circuit-det : Boolean property which enables open circuit fault detection.
+- qcom,vph-droop-det : Boolean property which enables VPH droop detection.
+- qcom,vph-droop-hys-mv : Integer property to specify VPH droop hysteresis. It is only used if
+ qcom,vph-droop-det is specified. Valid values are 0, 25, 50 and 75.
+ Unit is mV.
+- qcom,vph-droop-thresh-mv : Integer property to specify VPH droop threshold. It is only used if
+ qcom,vph-droop-det is specified. Valid values are
+ 2500 to 3200 with step size of 100. Unit is mV.
+- qcom,vph-droop-debounce-us : Integer property to specify VPH droop debounce time. It is only used
+ if qcom,vph-droop-det is specified. Valid values are 0, 8, 16 and 26.
+ Unit is uS.
- qcom,hw-strobe-option : Integer type to specify hardware strobe option. Based on the specified
value, additional GPIO configuration may be required to provide strobing
support. Supported values are:
diff --git a/drivers/leds/leds-qpnp-flash-v2.c b/drivers/leds/leds-qpnp-flash-v2.c
index 3e5e10d29f0e..f2ff5f88908e 100644
--- a/drivers/leds/leds-qpnp-flash-v2.c
+++ b/drivers/leds/leds-qpnp-flash-v2.c
@@ -37,21 +37,39 @@
#define FLASH_LED_EN_LED_CTRL(base) (base + 0x4C)
#define FLASH_LED_REG_HDRM_PRGM(base) (base + 0x4D)
#define FLASH_LED_REG_HDRM_AUTO_MODE_CTRL(base) (base + 0x50)
+#define FLASH_LED_REG_WARMUP_DELAY(base) (base + 0x51)
#define FLASH_LED_REG_ISC_DELAY(base) (base + 0x52)
+#define FLASH_LED_REG_VPH_DROOP_THRESHOLD(base) (base + 0x61)
+#define FLASH_LED_REG_VPH_DROOP_DEBOUNCE(base) (base + 0x62)
+#define FLASH_LED_REG_CURRENT_DERATE_EN(base) (base + 0x76)
#define FLASH_LED_HDRM_MODE_PRGM_MASK GENMASK(7, 0)
#define FLASH_LED_HDRM_VOL_MASK GENMASK(7, 4)
#define FLASH_LED_CURRENT_MASK GENMASK(6, 0)
#define FLASH_LED_ENABLE_MASK GENMASK(2, 0)
#define FLASH_LED_SAFETY_TMR_MASK GENMASK(7, 0)
-#define FLASH_LED_ISC_DELAY_MASK GENMASK(1, 0)
#define FLASH_LED_INT_RT_STS_MASK GENMASK(7, 0)
+#define FLASH_LED_ISC_WARMUP_DELAY_MASK GENMASK(1, 0)
+#define FLASH_LED_CURRENT_DERATE_EN_MASK GENMASK(2, 0)
+#define FLASH_LED_VPH_DROOP_DEBOUNCE_MASK GENMASK(1, 0)
+#define FLASH_LED_VPH_DROOP_HYSTERESIS_MASK GENMASK(5, 4)
+#define FLASH_LED_VPH_DROOP_THRESHOLD_MASK GENMASK(2, 0)
#define FLASH_LED_MOD_CTRL_MASK BIT(7)
#define FLASH_LED_HW_SW_STROBE_SEL_MASK BIT(2)
-#define FLASH_LED_HEADROOM_AUTO_MODE_ENABLED true
-#define FLASH_LED_ISC_DELAY_SHIFT 6
-#define FLASH_LED_ISC_DELAY_DEFAULT_US 3
+#define VPH_DROOP_DEBOUNCE_US_TO_VAL(val_us) (val_us / 8)
+#define VPH_DROOP_HYST_MV_TO_VAL(val_mv) (val_mv / 25)
+#define VPH_DROOP_THRESH_MV_TO_VAL(val_mv) ((val_mv / 100) - 25)
+
+#define FLASH_LED_ISC_WARMUP_DELAY_SHIFT 6
+#define FLASH_LED_WARMUP_DELAY_DEFAULT 2
+#define FLASH_LED_ISC_DELAY_DEFAULT 3
+#define FLASH_LED_VPH_DROOP_DEBOUNCE_DEFAULT 2
+#define FLASH_LED_VPH_DROOP_HYST_DEFAULT 2
+#define FLASH_LED_VPH_DROOP_THRESH_DEFAULT 5
+#define FLASH_LED_VPH_DROOP_DEBOUNCE_MAX 3
+#define FLASH_LED_VPH_DROOP_HYST_MAX 3
+#define FLASH_LED_VPH_DROOP_THRESH_MAX 7
#define FLASH_LED_SAFETY_TMR_VAL_OFFSET 1
#define FLASH_LED_SAFETY_TMR_VAL_DIVISOR 10
#define FLASH_LED_SAFETY_TMR_ENABLE BIT(7)
@@ -136,7 +154,12 @@ struct flash_switch_data {
struct flash_led_platform_data {
int all_ramp_up_done_irq;
int all_ramp_down_done_irq;
- u8 isc_delay_us;
+ u8 isc_delay;
+ u8 warmup_delay;
+ u8 current_derate_en_cfg;
+ u8 vph_droop_threshold;
+ u8 vph_droop_hysteresis;
+ u8 vph_droop_debounce;
u8 hw_strobe_option;
bool hdrm_auto_mode_en;
};
@@ -223,7 +246,43 @@ static int qpnp_flash_led_init_settings(struct qpnp_flash_led *led)
rc = qpnp_flash_led_masked_write(led,
FLASH_LED_REG_ISC_DELAY(led->base),
- FLASH_LED_ISC_DELAY_MASK, led->pdata->isc_delay_us);
+ FLASH_LED_ISC_WARMUP_DELAY_MASK,
+ led->pdata->isc_delay);
+ if (rc < 0)
+ return rc;
+
+ rc = qpnp_flash_led_masked_write(led,
+ FLASH_LED_REG_WARMUP_DELAY(led->base),
+ FLASH_LED_ISC_WARMUP_DELAY_MASK,
+ led->pdata->warmup_delay);
+ if (rc < 0)
+ return rc;
+
+ rc = qpnp_flash_led_masked_write(led,
+ FLASH_LED_REG_CURRENT_DERATE_EN(led->base),
+ FLASH_LED_CURRENT_DERATE_EN_MASK,
+ led->pdata->current_derate_en_cfg);
+ if (rc < 0)
+ return rc;
+
+ rc = qpnp_flash_led_masked_write(led,
+ FLASH_LED_REG_VPH_DROOP_DEBOUNCE(led->base),
+ FLASH_LED_VPH_DROOP_DEBOUNCE_MASK,
+ led->pdata->vph_droop_debounce);
+ if (rc < 0)
+ return rc;
+
+ rc = qpnp_flash_led_masked_write(led,
+ FLASH_LED_REG_VPH_DROOP_THRESHOLD(led->base),
+ FLASH_LED_VPH_DROOP_THRESHOLD_MASK,
+ led->pdata->vph_droop_threshold);
+ if (rc < 0)
+ return rc;
+
+ rc = qpnp_flash_led_masked_write(led,
+ FLASH_LED_REG_VPH_DROOP_THRESHOLD(led->base),
+ FLASH_LED_VPH_DROOP_HYSTERESIS_MASK,
+ led->pdata->vph_droop_hysteresis);
if (rc < 0)
return rc;
@@ -980,25 +1039,98 @@ static int qpnp_flash_led_parse_common_dt(struct qpnp_flash_led *led,
{
int rc;
u32 val;
+ bool short_circuit_det, open_circuit_det, vph_droop_det;
- led->pdata->hdrm_auto_mode_en = FLASH_LED_HEADROOM_AUTO_MODE_ENABLED;
led->pdata->hdrm_auto_mode_en = of_property_read_bool(node,
"qcom,hdrm-auto-mode");
- led->pdata->isc_delay_us = FLASH_LED_ISC_DELAY_DEFAULT_US;
- rc = of_property_read_u32(node, "qcom,isc-delay", &val);
+ led->pdata->isc_delay = FLASH_LED_ISC_DELAY_DEFAULT;
+ rc = of_property_read_u32(node, "qcom,isc-delay-us", &val);
if (!rc) {
- led->pdata->isc_delay_us = val >> FLASH_LED_ISC_DELAY_SHIFT;
+ led->pdata->isc_delay =
+ val >> FLASH_LED_ISC_WARMUP_DELAY_SHIFT;
} else if (rc != -EINVAL) {
- dev_err(&led->pdev->dev, "Unable to read ISC delay\n");
+ dev_err(&led->pdev->dev,
+ "Unable to read ISC delay, rc=%d\n", rc);
return rc;
}
+ led->pdata->warmup_delay = FLASH_LED_WARMUP_DELAY_DEFAULT;
+ rc = of_property_read_u32(node, "qcom,warmup-delay-us", &val);
+ if (!rc) {
+ led->pdata->warmup_delay =
+ val >> FLASH_LED_ISC_WARMUP_DELAY_SHIFT;
+ } else if (rc != -EINVAL) {
+ dev_err(&led->pdev->dev,
+ "Unable to read WARMUP delay, rc=%d\n", rc);
+ return rc;
+ }
+
+ short_circuit_det =
+ of_property_read_bool(node, "qcom,short-circuit-det");
+ open_circuit_det = of_property_read_bool(node, "qcom,open-circuit-det");
+ vph_droop_det = of_property_read_bool(node, "qcom,vph-droop-det");
+ led->pdata->current_derate_en_cfg = (vph_droop_det << 2) |
+ (open_circuit_det << 1) | short_circuit_det;
+
+ led->pdata->vph_droop_debounce = FLASH_LED_VPH_DROOP_DEBOUNCE_DEFAULT;
+ rc = of_property_read_u32(node, "qcom,vph-droop-debounce-us", &val);
+ if (!rc) {
+ led->pdata->vph_droop_debounce =
+ VPH_DROOP_DEBOUNCE_US_TO_VAL(val);
+ } else if (rc != -EINVAL) {
+ dev_err(&led->pdev->dev,
+ "Unable to read VPH droop debounce, rc=%d\n", rc);
+ return rc;
+ }
+
+ if (led->pdata->vph_droop_debounce > FLASH_LED_VPH_DROOP_DEBOUNCE_MAX) {
+ dev_err(&led->pdev->dev,
+ "Invalid VPH droop debounce specified");
+ return -EINVAL;
+ }
+
+ led->pdata->vph_droop_threshold = FLASH_LED_VPH_DROOP_THRESH_DEFAULT;
+ rc = of_property_read_u32(node, "qcom,vph-droop-threshold-mv", &val);
+ if (!rc) {
+ led->pdata->vph_droop_threshold =
+ VPH_DROOP_THRESH_MV_TO_VAL(val);
+ } else if (rc != -EINVAL) {
+ dev_err(&led->pdev->dev,
+ "Unable to read VPH droop threshold, rc=%d\n", rc);
+ return rc;
+ }
+
+ if (led->pdata->vph_droop_threshold > FLASH_LED_VPH_DROOP_THRESH_MAX) {
+ dev_err(&led->pdev->dev,
+ "Invalid VPH droop threshold specified");
+ return -EINVAL;
+ }
+
+ led->pdata->vph_droop_hysteresis =
+ FLASH_LED_VPH_DROOP_HYST_DEFAULT;
+ rc = of_property_read_u32(node, "qcom,vph-droop-hysteresis-mv", &val);
+ if (!rc) {
+ led->pdata->vph_droop_hysteresis =
+ VPH_DROOP_HYST_MV_TO_VAL(val);
+ } else if (rc != -EINVAL) {
+ dev_err(&led->pdev->dev,
+ "Unable to read VPH droop hysteresis, rc=%d\n", rc);
+ return rc;
+ }
+
+ if (led->pdata->vph_droop_hysteresis > FLASH_LED_VPH_DROOP_HYST_MAX) {
+ dev_err(&led->pdev->dev,
+ "Invalid VPH droop hysteresis specified");
+ return -EINVAL;
+ }
+
rc = of_property_read_u32(node, "qcom,hw-strobe-option", &val);
if (!rc) {
led->pdata->hw_strobe_option = (u8)val;
} else if (rc != -EINVAL) {
- dev_err(&led->pdev->dev, "Unable to parse hw strobe option\n");
+ dev_err(&led->pdev->dev,
+ "Unable to parse hw strobe option, rc=%d\n", rc);
return rc;
}