diff --git a/drivers/leds/leds-qpnp-flash-v2.c b/drivers/leds/leds-qpnp-flash-v2.c index de5c61418d07..1a6cad946a25 100644 --- a/drivers/leds/leds-qpnp-flash-v2.c +++ b/drivers/leds/leds-qpnp-flash-v2.c @@ -127,11 +127,11 @@ #define FLASH_LED_LMH_MITIGATION_DISABLE 0 #define FLASH_LED_CHGR_MITIGATION_ENABLE BIT(4) #define FLASH_LED_CHGR_MITIGATION_DISABLE 0 -#define FLASH_LED_MITIGATION_SEL_DEFAULT 2 +#define FLASH_LED_LMH_MITIGATION_SEL_DEFAULT 2 #define FLASH_LED_MITIGATION_SEL_MAX 2 #define FLASH_LED_CHGR_MITIGATION_SEL_SHIFT 4 -#define FLASH_LED_MITIGATION_THRSH_DEFAULT 0xA -#define FLASH_LED_MITIGATION_THRSH_MAX 0x1F +#define FLASH_LED_CHGR_MITIGATION_THRSH_DEFAULT 0xA +#define FLASH_LED_CHGR_MITIGATION_THRSH_MAX 0x1F #define FLASH_LED_LMH_OCV_THRESH_DEFAULT_UV 3700000 #define FLASH_LED_LMH_RBATT_THRESH_DEFAULT_UOHM 400000 #define FLASH_LED_IRES_BASE 3 @@ -157,6 +157,12 @@ /* notifier call chain for flash-led irqs */ static ATOMIC_NOTIFIER_HEAD(irq_notifier_list); +enum flash_charger_mitigation { + FLASH_DISABLE_CHARGER_MITIGATION, + FLASH_HW_CHARGER_MITIGATION_BY_ILED_THRSHLD, + FLASH_SW_CHARGER_MITIGATION, +}; + enum flash_led_type { FLASH_LED_TYPE_FLASH, FLASH_LED_TYPE_TORCH, @@ -181,6 +187,7 @@ struct flash_node_data { int ires_ua; int max_current; int current_ma; + int prev_current_ma; u8 duration; u8 id; u8 type; @@ -260,6 +267,7 @@ struct qpnp_flash_led { int num_fnodes; int num_snodes; int enable; + int total_current_ma; u16 base; bool trigger_lmh; bool trigger_chgr; @@ -486,10 +494,12 @@ static int qpnp_flash_led_init_settings(struct qpnp_flash_led *led) if (rc < 0) return rc; + val = led->pdata->chgr_mitigation_sel + << FLASH_LED_CHGR_MITIGATION_SEL_SHIFT; rc = qpnp_flash_led_masked_write(led, FLASH_LED_REG_MITIGATION_SEL(led->base), FLASH_LED_CHGR_MITIGATION_SEL_MASK, - led->pdata->chgr_mitigation_sel); + val); if (rc < 0) return rc; @@ -875,10 +885,24 @@ static int qpnp_flash_led_get_max_avail_current(struct qpnp_flash_led *led) return max_avail_current; } +static void qpnp_flash_led_aggregate_max_current(struct flash_node_data *fnode) +{ + struct qpnp_flash_led *led = dev_get_drvdata(&fnode->pdev->dev); + + if (fnode->current_ma) + led->total_current_ma += fnode->current_ma + - fnode->prev_current_ma; + else + led->total_current_ma -= fnode->prev_current_ma; + + fnode->prev_current_ma = fnode->current_ma; +} + static void qpnp_flash_led_node_set(struct flash_node_data *fnode, int value) { int prgm_current_ma = value; int min_ma = fnode->ires_ua / 1000; + struct qpnp_flash_led *led = dev_get_drvdata(&fnode->pdev->dev); if (value <= 0) prgm_current_ma = 0; @@ -891,6 +915,13 @@ static void qpnp_flash_led_node_set(struct flash_node_data *fnode, int value) fnode->current_reg_val = CURRENT_MA_TO_REG_VAL(prgm_current_ma, fnode->ires_ua); fnode->led_on = prgm_current_ma != 0; + + if (led->pdata->chgr_mitigation_sel == FLASH_SW_CHARGER_MITIGATION) { + qpnp_flash_led_aggregate_max_current(fnode); + led->trigger_chgr = false; + if (led->total_current_ma >= 1000) + led->trigger_chgr = true; + } } static int qpnp_flash_led_switch_disable(struct flash_switch_data *snode) @@ -1158,10 +1189,6 @@ int qpnp_flash_led_prepare(struct led_trigger *trig, int options, *max_current = rc; } - led->trigger_chgr = false; - if (options & PRE_FLASH) - led->trigger_chgr = true; - return 0; } @@ -1956,7 +1983,7 @@ static int qpnp_flash_led_parse_common_dt(struct qpnp_flash_led *led, return rc; } - led->pdata->lmh_mitigation_sel = FLASH_LED_MITIGATION_SEL_DEFAULT; + led->pdata->lmh_mitigation_sel = FLASH_LED_LMH_MITIGATION_SEL_DEFAULT; rc = of_property_read_u32(node, "qcom,lmh-mitigation-sel", &val); if (!rc) { led->pdata->lmh_mitigation_sel = val; @@ -1970,7 +1997,7 @@ static int qpnp_flash_led_parse_common_dt(struct qpnp_flash_led *led, return -EINVAL; } - led->pdata->chgr_mitigation_sel = FLASH_LED_MITIGATION_SEL_DEFAULT; + led->pdata->chgr_mitigation_sel = FLASH_SW_CHARGER_MITIGATION; rc = of_property_read_u32(node, "qcom,chgr-mitigation-sel", &val); if (!rc) { led->pdata->chgr_mitigation_sel = val; @@ -1984,9 +2011,7 @@ static int qpnp_flash_led_parse_common_dt(struct qpnp_flash_led *led, return -EINVAL; } - led->pdata->chgr_mitigation_sel <<= FLASH_LED_CHGR_MITIGATION_SEL_SHIFT; - - led->pdata->iled_thrsh_val = FLASH_LED_MITIGATION_THRSH_DEFAULT; + led->pdata->iled_thrsh_val = FLASH_LED_CHGR_MITIGATION_THRSH_DEFAULT; rc = of_property_read_u32(node, "qcom,iled-thrsh-ma", &val); if (!rc) { led->pdata->iled_thrsh_val = MITIGATION_THRSH_MA_TO_VAL(val); @@ -1995,7 +2020,7 @@ static int qpnp_flash_led_parse_common_dt(struct qpnp_flash_led *led, return rc; } - if (led->pdata->iled_thrsh_val > FLASH_LED_MITIGATION_THRSH_MAX) { + if (led->pdata->iled_thrsh_val > FLASH_LED_CHGR_MITIGATION_THRSH_MAX) { pr_err("Invalid iled_thrsh_val specified\n"); return -EINVAL; } diff --git a/include/linux/leds-qpnp-flash.h b/include/linux/leds-qpnp-flash.h index 4b5a339970fa..1fe6e1709fa6 100644 --- a/include/linux/leds-qpnp-flash.h +++ b/include/linux/leds-qpnp-flash.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -18,7 +18,6 @@ #define ENABLE_REGULATOR BIT(0) #define DISABLE_REGULATOR BIT(1) #define QUERY_MAX_CURRENT BIT(2) -#define PRE_FLASH BIT(3) #define FLASH_LED_PREPARE_OPTIONS_MASK GENMASK(3, 0)