blob: 2b66f1c18ad80a79de8a8c13560fdd9fc7564167 [file] [log] [blame]
Subbaraman Narayanamurthyaf8dcb42018-01-17 20:23:47 -08001/* Copyright (c) 2016-2018, The Linux Foundation. All rights reserved.
David Collins8885f792017-01-26 14:36:34 -08002 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 */
12
13#define pr_fmt(fmt) "flashv2: %s: " fmt, __func__
14
15#include <linux/module.h>
16#include <linux/init.h>
17#include <linux/kernel.h>
18#include <linux/errno.h>
19#include <linux/delay.h>
20#include <linux/slab.h>
21#include <linux/of.h>
22#include <linux/of_irq.h>
23#include <linux/of_gpio.h>
24#include <linux/gpio.h>
25#include <linux/regmap.h>
26#include <linux/power_supply.h>
27#include <linux/platform_device.h>
28#include <linux/interrupt.h>
29#include <linux/regulator/consumer.h>
30#include <linux/leds-qpnp-flash.h>
31#include <linux/leds-qpnp-flash-v2.h>
32#include <linux/qpnp/qpnp-revid.h>
33#include <linux/log2.h>
34#include "leds.h"
35
36#define FLASH_LED_REG_LED_STATUS1(base) (base + 0x08)
Kiran Gunda1c1e21c2017-12-15 09:55:03 +053037
David Collins8885f792017-01-26 14:36:34 -080038#define FLASH_LED_REG_LED_STATUS2(base) (base + 0x09)
Kiran Gunda1c1e21c2017-12-15 09:55:03 +053039#define FLASH_LED_VPH_DROOP_FAULT_MASK BIT(4)
40
David Collins8885f792017-01-26 14:36:34 -080041#define FLASH_LED_REG_INT_RT_STS(base) (base + 0x10)
Kiran Gunda1c1e21c2017-12-15 09:55:03 +053042
David Collins8885f792017-01-26 14:36:34 -080043#define FLASH_LED_REG_SAFETY_TMR(base) (base + 0x40)
Kiran Gunda1c1e21c2017-12-15 09:55:03 +053044#define FLASH_LED_SAFETY_TMR_ENABLE BIT(7)
45
David Collins8885f792017-01-26 14:36:34 -080046#define FLASH_LED_REG_TGR_CURRENT(base) (base + 0x43)
Kiran Gunda1c1e21c2017-12-15 09:55:03 +053047
David Collins8885f792017-01-26 14:36:34 -080048#define FLASH_LED_REG_MOD_CTRL(base) (base + 0x46)
Kiran Gunda1c1e21c2017-12-15 09:55:03 +053049#define FLASH_LED_MOD_CTRL_MASK BIT(7)
50#define FLASH_LED_MOD_ENABLE BIT(7)
51
David Collins8885f792017-01-26 14:36:34 -080052#define FLASH_LED_REG_IRES(base) (base + 0x47)
Kiran Gunda1c1e21c2017-12-15 09:55:03 +053053
David Collins8885f792017-01-26 14:36:34 -080054#define FLASH_LED_REG_STROBE_CFG(base) (base + 0x48)
Kiran Gunda1c1e21c2017-12-15 09:55:03 +053055#define FLASH_LED_STROBE_MASK GENMASK(1, 0)
56
David Collins8885f792017-01-26 14:36:34 -080057#define FLASH_LED_REG_STROBE_CTRL(base) (base + 0x49)
Kiran Gunda1c1e21c2017-12-15 09:55:03 +053058#define FLASH_LED_HW_SW_STROBE_SEL_BIT BIT(2)
59#define FLASH_HW_STROBE_MASK GENMASK(2, 0)
60
David Collins8885f792017-01-26 14:36:34 -080061#define FLASH_LED_EN_LED_CTRL(base) (base + 0x4C)
Kiran Gunda1c1e21c2017-12-15 09:55:03 +053062#define FLASH_LED_ENABLE BIT(0)
63
David Collins8885f792017-01-26 14:36:34 -080064#define FLASH_LED_REG_HDRM_PRGM(base) (base + 0x4D)
Kiran Gunda1c1e21c2017-12-15 09:55:03 +053065#define FLASH_LED_HDRM_VOL_MASK GENMASK(7, 4)
66#define FLASH_LED_HDRM_VOL_SHIFT 4
67
David Collins8885f792017-01-26 14:36:34 -080068#define FLASH_LED_REG_HDRM_AUTO_MODE_CTRL(base) (base + 0x50)
69#define FLASH_LED_REG_WARMUP_DELAY(base) (base + 0x51)
David Collins8885f792017-01-26 14:36:34 -080070
Kiran Gunda1c1e21c2017-12-15 09:55:03 +053071#define FLASH_LED_REG_ISC_DELAY(base) (base + 0x52)
David Collins8885f792017-01-26 14:36:34 -080072#define FLASH_LED_ISC_WARMUP_DELAY_MASK GENMASK(1, 0)
Kiran Gunda1c1e21c2017-12-15 09:55:03 +053073#define FLASH_LED_ISC_WARMUP_DELAY_SHIFT 6
74
75#define FLASH_LED_REG_THERMAL_RMP_DN_RATE(base) (base + 0x55)
David Collins8885f792017-01-26 14:36:34 -080076#define THERMAL_OTST1_RAMP_CTRL_MASK BIT(7)
77#define THERMAL_OTST1_RAMP_CTRL_SHIFT 7
78#define THERMAL_DERATE_SLOW_SHIFT 4
79#define THERMAL_DERATE_SLOW_MASK GENMASK(6, 4)
80#define THERMAL_DERATE_FAST_MASK GENMASK(2, 0)
Kiran Gunda1c1e21c2017-12-15 09:55:03 +053081
82#define FLASH_LED_REG_THERMAL_THRSH1(base) (base + 0x56)
83#define FLASH_LED_THERMAL_THRSH_MASK GENMASK(2, 0)
84
85#define FLASH_LED_REG_THERMAL_THRSH2(base) (base + 0x57)
86#define FLASH_LED_REG_THERMAL_THRSH3(base) (base + 0x58)
87
88#define FLASH_LED_REG_THERMAL_HYSTERESIS(base) (base + 0x59)
89#define FLASH_LED_THERMAL_HYSTERESIS_MASK GENMASK(1, 0)
90
91#define FLASH_LED_REG_THERMAL_DEBOUNCE(base) (base + 0x5A)
92#define FLASH_LED_THERMAL_DEBOUNCE_MASK GENMASK(1, 0)
93
94#define FLASH_LED_REG_VPH_DROOP_THRESHOLD(base) (base + 0x61)
95#define FLASH_LED_VPH_DROOP_HYSTERESIS_MASK GENMASK(5, 4)
96#define FLASH_LED_VPH_DROOP_THRESHOLD_MASK GENMASK(2, 0)
97#define FLASH_LED_VPH_DROOP_HYST_SHIFT 4
98
99#define FLASH_LED_REG_VPH_DROOP_DEBOUNCE(base) (base + 0x62)
100#define FLASH_LED_VPH_DROOP_DEBOUNCE_MASK GENMASK(1, 0)
101
102#define FLASH_LED_REG_ILED_GRT_THRSH(base) (base + 0x67)
103#define FLASH_LED_ILED_GRT_THRSH_MASK GENMASK(5, 0)
104
105#define FLASH_LED_REG_LED1N2_ICLAMP_LOW(base) (base + 0x68)
106#define FLASH_LED_REG_LED1N2_ICLAMP_MID(base) (base + 0x69)
107#define FLASH_LED_REG_LED3_ICLAMP_LOW(base) (base + 0x6A)
108
109#define FLASH_LED_REG_LED3_ICLAMP_MID(base) (base + 0x6B)
110#define FLASH_LED_CURRENT_MASK GENMASK(6, 0)
111
112#define FLASH_LED_REG_MITIGATION_SEL(base) (base + 0x6E)
113#define FLASH_LED_CHGR_MITIGATION_SEL_MASK GENMASK(5, 4)
114#define FLASH_LED_LMH_MITIGATION_SEL_MASK GENMASK(1, 0)
115
116#define FLASH_LED_REG_MITIGATION_SW(base) (base + 0x6F)
117#define FLASH_LED_LMH_MITIGATION_EN_MASK BIT(0)
118#define FLASH_LED_CHGR_MITIGATION_EN_MASK BIT(4)
119#define FLASH_LED_CHGR_MITIGATION_ENABLE BIT(4)
120
121#define FLASH_LED_REG_LMH_LEVEL(base) (base + 0x70)
122#define FLASH_LED_LMH_LEVEL_MASK GENMASK(1, 0)
123
124#define FLASH_LED_REG_MULTI_STROBE_CTRL(base) (base + 0x71)
Subbaraman Narayanamurthy3f684b22017-03-21 20:49:54 -0700125#define LED3_FLASH_ONCE_ONLY_BIT BIT(1)
Kiran Gundae7339962018-03-27 14:54:29 +0530126#define LED1N2_FLASH_ONCE_ONLY_BIT BIT(0)
Kiran Gunda1c1e21c2017-12-15 09:55:03 +0530127
128#define FLASH_LED_REG_LPG_INPUT_CTRL(base) (base + 0x72)
Subbaraman Narayanamurthy3f684b22017-03-21 20:49:54 -0700129#define LPG_INPUT_SEL_BIT BIT(0)
David Collins8885f792017-01-26 14:36:34 -0800130
Kiran Gunda1c1e21c2017-12-15 09:55:03 +0530131#define FLASH_LED_REG_CURRENT_DERATE_EN(base) (base + 0x76)
132#define FLASH_LED_CURRENT_DERATE_EN_MASK GENMASK(2, 0)
133
David Collins8885f792017-01-26 14:36:34 -0800134#define VPH_DROOP_DEBOUNCE_US_TO_VAL(val_us) (val_us / 8)
135#define VPH_DROOP_HYST_MV_TO_VAL(val_mv) (val_mv / 25)
David Collins8885f792017-01-26 14:36:34 -0800136#define VPH_DROOP_THRESH_VAL_TO_UV(val) ((val + 25) * 100000)
137#define MITIGATION_THRSH_MA_TO_VAL(val_ma) (val_ma / 100)
David Collins8885f792017-01-26 14:36:34 -0800138#define THERMAL_HYST_TEMP_TO_VAL(val, divisor) (val / divisor)
139
Kiran Gunda1c1e21c2017-12-15 09:55:03 +0530140#define FLASH_LED_WARMUP_DELAY_DEFAULT 2
141#define FLASH_LED_ISC_DELAY_DEFAULT 3
142#define FLASH_LED_VPH_DROOP_DEBOUNCE_DEFAULT 2
143#define FLASH_LED_VPH_DROOP_HYST_DEFAULT 2
144#define FLASH_LED_VPH_DROOP_THRESH_DEFAULT 5
145#define BHARGER_FLASH_LED_VPH_DROOP_THRESH_DEFAULT 7
146#define FLASH_LED_DEBOUNCE_MAX 3
147#define FLASH_LED_HYSTERESIS_MAX 3
148#define FLASH_LED_VPH_DROOP_THRESH_MAX 7
149#define THERMAL_DERATE_SLOW_MAX 314592
150#define THERMAL_DERATE_FAST_MAX 512
151#define THERMAL_DEBOUNCE_TIME_MAX 64
152#define THERMAL_DERATE_HYSTERESIS_MAX 3
153#define FLASH_LED_THERMAL_THRSH_MIN 3
154#define FLASH_LED_THERMAL_THRSH_MAX 7
155#define FLASH_LED_THERMAL_OTST_LEVELS 3
156#define FLASH_LED_VLED_MAX_DEFAULT_UV 3500000
157#define FLASH_LED_IBATT_OCP_THRESH_DEFAULT_UA 4500000
158#define FLASH_LED_RPARA_DEFAULT_UOHM 0
159#define FLASH_LED_LMH_LEVEL_DEFAULT 0
160#define FLASH_LED_LMH_MITIGATION_ENABLE 1
161#define FLASH_LED_LMH_MITIGATION_DISABLE 0
162#define FLASH_LED_CHGR_MITIGATION_DISABLE 0
163#define FLASH_LED_LMH_MITIGATION_SEL_DEFAULT 2
164#define FLASH_LED_MITIGATION_SEL_MAX 2
165#define FLASH_LED_CHGR_MITIGATION_SEL_SHIFT 4
166#define FLASH_LED_CHGR_MITIGATION_THRSH_DEFAULT 0xA
167#define FLASH_LED_CHGR_MITIGATION_THRSH_MAX 0x1F
168#define FLASH_LED_LMH_OCV_THRESH_DEFAULT_UV 3700000
169#define FLASH_LED_LMH_RBATT_THRESH_DEFAULT_UOHM 400000
170#define FLASH_LED_IRES_BASE 3
171#define FLASH_LED_IRES_DIVISOR 2500
172#define FLASH_LED_IRES_MIN_UA 5000
173#define FLASH_LED_IRES_DEFAULT_UA 12500
174#define FLASH_LED_IRES_DEFAULT_VAL 0x00
175#define FLASH_LED_HDRM_VOL_DEFAULT_MV 0x80
176#define FLASH_LED_HDRM_VOL_HI_LO_WIN_DEFAULT_MV 0x04
177#define FLASH_LED_HDRM_VOL_BASE_MV 125
178#define FLASH_LED_HDRM_VOL_STEP_MV 25
179#define FLASH_LED_STROBE_CFG_DEFAULT 0x00
180#define FLASH_LED_HW_STROBE_OPTION_1 0x00
181#define FLASH_LED_HW_STROBE_OPTION_2 0x01
182#define FLASH_LED_HW_STROBE_OPTION_3 0x02
183#define FLASH_LED_DISABLE 0x00
184#define FLASH_LED_SAFETY_TMR_DISABLED 0x13
185#define FLASH_LED_MAX_TOTAL_CURRENT_MA 3750
186#define FLASH_LED_IRES5P0_MAX_CURR_MA 640
187#define FLASH_LED_IRES7P5_MAX_CURR_MA 960
188#define FLASH_LED_IRES10P0_MAX_CURR_MA 1280
189#define FLASH_LED_IRES12P5_MAX_CURR_MA 1600
190#define MAX_IRES_LEVELS 4
191#define FLASH_BST_PWM_OVRHD_MIN_UV 300000
192#define FLASH_BST_PWM_OVRHD_MAX_UV 600000
David Collins8885f792017-01-26 14:36:34 -0800193
194/* notifier call chain for flash-led irqs */
195static ATOMIC_NOTIFIER_HEAD(irq_notifier_list);
196
Ankit Sharmaa7153c32017-03-22 19:04:52 +0530197enum flash_charger_mitigation {
198 FLASH_DISABLE_CHARGER_MITIGATION,
199 FLASH_HW_CHARGER_MITIGATION_BY_ILED_THRSHLD,
200 FLASH_SW_CHARGER_MITIGATION,
201};
202
David Collins8885f792017-01-26 14:36:34 -0800203enum flash_led_type {
Subbaraman Narayanamurthyd737fd52018-01-17 19:58:52 -0800204 FLASH_LED_TYPE_UNKNOWN,
David Collins8885f792017-01-26 14:36:34 -0800205 FLASH_LED_TYPE_FLASH,
206 FLASH_LED_TYPE_TORCH,
207};
208
209enum {
210 LED1 = 0,
211 LED2,
212 LED3,
213};
214
Subbaraman Narayanamurthy3f684b22017-03-21 20:49:54 -0700215enum strobe_type {
216 SW_STROBE = 0,
217 HW_STROBE,
218 LPG_STROBE,
219};
220
David Collins8885f792017-01-26 14:36:34 -0800221/*
222 * Configurations for each individual LED
223 */
224struct flash_node_data {
225 struct platform_device *pdev;
226 struct led_classdev cdev;
Subbaraman Narayanamurthy58377f02017-03-21 20:38:43 -0700227 struct pinctrl *strobe_pinctrl;
David Collins8885f792017-01-26 14:36:34 -0800228 struct pinctrl_state *hw_strobe_state_active;
229 struct pinctrl_state *hw_strobe_state_suspend;
230 int hw_strobe_gpio;
231 int ires_ua;
Kiran Gunda5cadca72017-07-26 14:37:52 +0530232 int default_ires_ua;
David Collins8885f792017-01-26 14:36:34 -0800233 int max_current;
234 int current_ma;
Ankit Sharmaa7153c32017-03-22 19:04:52 +0530235 int prev_current_ma;
David Collins8885f792017-01-26 14:36:34 -0800236 u8 duration;
237 u8 id;
Kiran Gunda5cadca72017-07-26 14:37:52 +0530238 u8 ires_idx;
239 u8 default_ires_idx;
David Collins8885f792017-01-26 14:36:34 -0800240 u8 hdrm_val;
241 u8 current_reg_val;
Subbaraman Narayanamurthy3f684b22017-03-21 20:49:54 -0700242 u8 strobe_ctrl;
243 u8 strobe_sel;
Subbaraman Narayanamurthyd737fd52018-01-17 19:58:52 -0800244 enum flash_led_type type;
David Collins8885f792017-01-26 14:36:34 -0800245 bool led_on;
246};
247
248
249struct flash_switch_data {
250 struct platform_device *pdev;
251 struct regulator *vreg;
Subbaraman Narayanamurthy58377f02017-03-21 20:38:43 -0700252 struct pinctrl *led_en_pinctrl;
253 struct pinctrl_state *gpio_state_active;
254 struct pinctrl_state *gpio_state_suspend;
David Collins8885f792017-01-26 14:36:34 -0800255 struct led_classdev cdev;
256 int led_mask;
257 bool regulator_on;
258 bool enabled;
Subbaraman Narayanamurthyd737fd52018-01-17 19:58:52 -0800259 bool symmetry_en;
David Collins8885f792017-01-26 14:36:34 -0800260};
261
262/*
263 * Flash LED configuration read from device tree
264 */
265struct flash_led_platform_data {
266 struct pmic_revid_data *pmic_rev_id;
267 int *thermal_derate_current;
268 int all_ramp_up_done_irq;
269 int all_ramp_down_done_irq;
270 int led_fault_irq;
271 int ibatt_ocp_threshold_ua;
272 int vled_max_uv;
273 int rpara_uohm;
274 int lmh_rbatt_threshold_uohm;
275 int lmh_ocv_threshold_uv;
276 int thermal_derate_slow;
277 int thermal_derate_fast;
278 int thermal_hysteresis;
279 int thermal_debounce;
280 int thermal_thrsh1;
281 int thermal_thrsh2;
282 int thermal_thrsh3;
Subbaraman Narayanamurthy3f684b22017-03-21 20:49:54 -0700283 int hw_strobe_option;
David Collins8885f792017-01-26 14:36:34 -0800284 u32 led1n2_iclamp_low_ma;
285 u32 led1n2_iclamp_mid_ma;
286 u32 led3_iclamp_low_ma;
287 u32 led3_iclamp_mid_ma;
Kiran Gunda1c1e21c2017-12-15 09:55:03 +0530288 u32 bst_pwm_ovrhd_uv;
David Collins8885f792017-01-26 14:36:34 -0800289 u8 isc_delay;
290 u8 warmup_delay;
291 u8 current_derate_en_cfg;
292 u8 vph_droop_threshold;
293 u8 vph_droop_hysteresis;
294 u8 vph_droop_debounce;
295 u8 lmh_mitigation_sel;
296 u8 chgr_mitigation_sel;
297 u8 lmh_level;
298 u8 iled_thrsh_val;
David Collins8885f792017-01-26 14:36:34 -0800299 bool hdrm_auto_mode_en;
300 bool thermal_derate_en;
301 bool otst_ramp_bkup_en;
302};
303
304/*
305 * Flash LED data structure containing flash LED attributes
306 */
307struct qpnp_flash_led {
308 struct flash_led_platform_data *pdata;
309 struct platform_device *pdev;
310 struct regmap *regmap;
311 struct flash_node_data *fnode;
312 struct flash_switch_data *snode;
313 struct power_supply *bms_psy;
Kiran Gunda1c1e21c2017-12-15 09:55:03 +0530314 struct power_supply *main_psy;
315 struct power_supply *usb_psy;
David Collins8885f792017-01-26 14:36:34 -0800316 struct notifier_block nb;
317 spinlock_t lock;
318 int num_fnodes;
319 int num_snodes;
320 int enable;
Ankit Sharmaa7153c32017-03-22 19:04:52 +0530321 int total_current_ma;
David Collins8885f792017-01-26 14:36:34 -0800322 u16 base;
323 bool trigger_lmh;
324 bool trigger_chgr;
325};
326
327static int thermal_derate_slow_table[] = {
328 128, 256, 512, 1024, 2048, 4096, 8192, 314592,
329};
330
331static int thermal_derate_fast_table[] = {
332 32, 64, 96, 128, 256, 384, 512,
333};
334
335static int otst1_threshold_table[] = {
336 85, 79, 73, 67, 109, 103, 97, 91,
337};
338
339static int otst2_threshold_table[] = {
340 110, 104, 98, 92, 134, 128, 122, 116,
341};
342
343static int otst3_threshold_table[] = {
344 125, 119, 113, 107, 149, 143, 137, 131,
345};
346
Kiran Gunda5cadca72017-07-26 14:37:52 +0530347static int max_ires_curr_ma_table[MAX_IRES_LEVELS] = {
348 FLASH_LED_IRES12P5_MAX_CURR_MA, FLASH_LED_IRES10P0_MAX_CURR_MA,
349 FLASH_LED_IRES7P5_MAX_CURR_MA, FLASH_LED_IRES5P0_MAX_CURR_MA
350};
351
Subbaraman Narayanamurthyaf8dcb42018-01-17 20:23:47 -0800352static inline int get_current_reg_code(int target_curr_ma, int ires_ua)
353{
354 if (!ires_ua || !target_curr_ma || (target_curr_ma < (ires_ua / 1000)))
355 return 0;
356
Subbaraman Narayanamurthyf8eb9d22018-04-16 14:00:12 -0700357 return DIV_ROUND_CLOSEST(target_curr_ma * 1000, ires_ua) - 1;
Subbaraman Narayanamurthyaf8dcb42018-01-17 20:23:47 -0800358}
359
David Collins8885f792017-01-26 14:36:34 -0800360static int qpnp_flash_led_read(struct qpnp_flash_led *led, u16 addr, u8 *data)
361{
362 int rc;
363 uint val;
364
365 rc = regmap_read(led->regmap, addr, &val);
366 if (rc < 0) {
367 pr_err("Unable to read from 0x%04X rc = %d\n", addr, rc);
368 return rc;
369 }
370
371 pr_debug("Read 0x%02X from addr 0x%04X\n", val, addr);
372 *data = (u8)val;
373 return 0;
374}
375
376static int qpnp_flash_led_write(struct qpnp_flash_led *led, u16 addr, u8 data)
377{
378 int rc;
379
380 rc = regmap_write(led->regmap, addr, data);
381 if (rc < 0) {
382 pr_err("Unable to write to 0x%04X rc = %d\n", addr, rc);
383 return rc;
384 }
385
386 pr_debug("Wrote 0x%02X to addr 0x%04X\n", data, addr);
387 return 0;
388}
389
390static int
391qpnp_flash_led_masked_read(struct qpnp_flash_led *led, u16 addr, u8 mask,
392 u8 *val)
393{
394 int rc;
395
396 rc = qpnp_flash_led_read(led, addr, val);
397 if (rc < 0)
398 return rc;
399
400 *val &= mask;
401 return rc;
402}
403
404static int
405qpnp_flash_led_masked_write(struct qpnp_flash_led *led, u16 addr, u8 mask,
406 u8 val)
407{
408 int rc;
409
410 rc = regmap_update_bits(led->regmap, addr, mask, val);
411 if (rc < 0)
412 pr_err("Unable to update bits from 0x%04X, rc = %d\n", addr,
413 rc);
414 else
415 pr_debug("Wrote 0x%02X to addr 0x%04X\n", val, addr);
416
417 return rc;
418}
419
420static enum
421led_brightness qpnp_flash_led_brightness_get(struct led_classdev *led_cdev)
422{
423 return led_cdev->brightness;
424}
425
426static int qpnp_flash_led_init_settings(struct qpnp_flash_led *led)
427{
428 int rc, i, addr_offset;
Kiran Gundae7339962018-03-27 14:54:29 +0530429 u8 val = 0, mask, strobe_mask = 0;
David Collins8885f792017-01-26 14:36:34 -0800430
431 for (i = 0; i < led->num_fnodes; i++) {
432 addr_offset = led->fnode[i].id;
433 rc = qpnp_flash_led_write(led,
434 FLASH_LED_REG_HDRM_PRGM(led->base + addr_offset),
435 led->fnode[i].hdrm_val);
436 if (rc < 0)
437 return rc;
438
439 val |= 0x1 << led->fnode[i].id;
Kiran Gundae7339962018-03-27 14:54:29 +0530440
441 if (led->fnode[i].strobe_sel == HW_STROBE) {
442 if (led->fnode[i].id == LED3)
443 strobe_mask |= LED3_FLASH_ONCE_ONLY_BIT;
444 else
445 strobe_mask |= LED1N2_FLASH_ONCE_ONLY_BIT;
446 }
447
448 if (led->fnode[i].id == LED3 &&
449 led->fnode[i].strobe_sel == LPG_STROBE)
450 strobe_mask |= LED3_FLASH_ONCE_ONLY_BIT;
451 }
452
453 rc = qpnp_flash_led_masked_write(led,
454 FLASH_LED_REG_MULTI_STROBE_CTRL(led->base),
455 strobe_mask, 0);
456 if (rc < 0)
457 return rc;
458
459 if (led->fnode[LED3].strobe_sel == LPG_STROBE) {
460 rc = qpnp_flash_led_masked_write(led,
461 FLASH_LED_REG_LPG_INPUT_CTRL(led->base),
462 LPG_INPUT_SEL_BIT, LPG_INPUT_SEL_BIT);
463 if (rc < 0)
464 return rc;
David Collins8885f792017-01-26 14:36:34 -0800465 }
466
467 rc = qpnp_flash_led_write(led,
468 FLASH_LED_REG_HDRM_AUTO_MODE_CTRL(led->base),
469 val);
470 if (rc < 0)
471 return rc;
472
473 rc = qpnp_flash_led_masked_write(led,
474 FLASH_LED_REG_ISC_DELAY(led->base),
475 FLASH_LED_ISC_WARMUP_DELAY_MASK,
476 led->pdata->isc_delay);
477 if (rc < 0)
478 return rc;
479
480 rc = qpnp_flash_led_masked_write(led,
481 FLASH_LED_REG_WARMUP_DELAY(led->base),
482 FLASH_LED_ISC_WARMUP_DELAY_MASK,
483 led->pdata->warmup_delay);
484 if (rc < 0)
485 return rc;
486
487 rc = qpnp_flash_led_masked_write(led,
488 FLASH_LED_REG_CURRENT_DERATE_EN(led->base),
489 FLASH_LED_CURRENT_DERATE_EN_MASK,
490 led->pdata->current_derate_en_cfg);
491 if (rc < 0)
492 return rc;
493
494 val = (led->pdata->otst_ramp_bkup_en << THERMAL_OTST1_RAMP_CTRL_SHIFT);
495 mask = THERMAL_OTST1_RAMP_CTRL_MASK;
496 if (led->pdata->thermal_derate_slow >= 0) {
497 val |= (led->pdata->thermal_derate_slow <<
498 THERMAL_DERATE_SLOW_SHIFT);
499 mask |= THERMAL_DERATE_SLOW_MASK;
500 }
501
502 if (led->pdata->thermal_derate_fast >= 0) {
503 val |= led->pdata->thermal_derate_fast;
504 mask |= THERMAL_DERATE_FAST_MASK;
505 }
506
507 rc = qpnp_flash_led_masked_write(led,
508 FLASH_LED_REG_THERMAL_RMP_DN_RATE(led->base),
509 mask, val);
510 if (rc < 0)
511 return rc;
512
513 if (led->pdata->thermal_debounce >= 0) {
514 rc = qpnp_flash_led_masked_write(led,
515 FLASH_LED_REG_THERMAL_DEBOUNCE(led->base),
516 FLASH_LED_THERMAL_DEBOUNCE_MASK,
517 led->pdata->thermal_debounce);
518 if (rc < 0)
519 return rc;
520 }
521
522 if (led->pdata->thermal_hysteresis >= 0) {
523 rc = qpnp_flash_led_masked_write(led,
524 FLASH_LED_REG_THERMAL_HYSTERESIS(led->base),
525 FLASH_LED_THERMAL_HYSTERESIS_MASK,
526 led->pdata->thermal_hysteresis);
527 if (rc < 0)
528 return rc;
529 }
530
531 if (led->pdata->thermal_thrsh1 >= 0) {
532 rc = qpnp_flash_led_masked_write(led,
533 FLASH_LED_REG_THERMAL_THRSH1(led->base),
534 FLASH_LED_THERMAL_THRSH_MASK,
535 led->pdata->thermal_thrsh1);
536 if (rc < 0)
537 return rc;
538 }
539
540 if (led->pdata->thermal_thrsh2 >= 0) {
541 rc = qpnp_flash_led_masked_write(led,
542 FLASH_LED_REG_THERMAL_THRSH2(led->base),
543 FLASH_LED_THERMAL_THRSH_MASK,
544 led->pdata->thermal_thrsh2);
545 if (rc < 0)
546 return rc;
547 }
548
549 if (led->pdata->thermal_thrsh3 >= 0) {
550 rc = qpnp_flash_led_masked_write(led,
551 FLASH_LED_REG_THERMAL_THRSH3(led->base),
552 FLASH_LED_THERMAL_THRSH_MASK,
553 led->pdata->thermal_thrsh3);
554 if (rc < 0)
555 return rc;
556 }
557
558 rc = qpnp_flash_led_masked_write(led,
559 FLASH_LED_REG_VPH_DROOP_DEBOUNCE(led->base),
560 FLASH_LED_VPH_DROOP_DEBOUNCE_MASK,
561 led->pdata->vph_droop_debounce);
562 if (rc < 0)
563 return rc;
564
565 rc = qpnp_flash_led_masked_write(led,
566 FLASH_LED_REG_VPH_DROOP_THRESHOLD(led->base),
567 FLASH_LED_VPH_DROOP_THRESHOLD_MASK,
568 led->pdata->vph_droop_threshold);
569 if (rc < 0)
570 return rc;
571
572 rc = qpnp_flash_led_masked_write(led,
573 FLASH_LED_REG_VPH_DROOP_THRESHOLD(led->base),
574 FLASH_LED_VPH_DROOP_HYSTERESIS_MASK,
575 led->pdata->vph_droop_hysteresis);
576 if (rc < 0)
577 return rc;
578
579 rc = qpnp_flash_led_masked_write(led,
580 FLASH_LED_REG_MITIGATION_SEL(led->base),
581 FLASH_LED_LMH_MITIGATION_SEL_MASK,
582 led->pdata->lmh_mitigation_sel);
583 if (rc < 0)
584 return rc;
585
Ankit Sharmaa7153c32017-03-22 19:04:52 +0530586 val = led->pdata->chgr_mitigation_sel
587 << FLASH_LED_CHGR_MITIGATION_SEL_SHIFT;
David Collins8885f792017-01-26 14:36:34 -0800588 rc = qpnp_flash_led_masked_write(led,
589 FLASH_LED_REG_MITIGATION_SEL(led->base),
590 FLASH_LED_CHGR_MITIGATION_SEL_MASK,
Ankit Sharmaa7153c32017-03-22 19:04:52 +0530591 val);
David Collins8885f792017-01-26 14:36:34 -0800592 if (rc < 0)
593 return rc;
594
595 rc = qpnp_flash_led_masked_write(led,
596 FLASH_LED_REG_LMH_LEVEL(led->base),
597 FLASH_LED_LMH_LEVEL_MASK,
598 led->pdata->lmh_level);
599 if (rc < 0)
600 return rc;
601
602 rc = qpnp_flash_led_masked_write(led,
603 FLASH_LED_REG_ILED_GRT_THRSH(led->base),
604 FLASH_LED_ILED_GRT_THRSH_MASK,
605 led->pdata->iled_thrsh_val);
606 if (rc < 0)
607 return rc;
608
609 if (led->pdata->led1n2_iclamp_low_ma) {
Subbaraman Narayanamurthyaf8dcb42018-01-17 20:23:47 -0800610 val = get_current_reg_code(led->pdata->led1n2_iclamp_low_ma,
Subbaraman Narayanamurthy01c99612017-04-03 12:26:06 -0700611 led->fnode[LED1].ires_ua);
David Collins8885f792017-01-26 14:36:34 -0800612 rc = qpnp_flash_led_masked_write(led,
613 FLASH_LED_REG_LED1N2_ICLAMP_LOW(led->base),
614 FLASH_LED_CURRENT_MASK, val);
615 if (rc < 0)
616 return rc;
617 }
618
619 if (led->pdata->led1n2_iclamp_mid_ma) {
Subbaraman Narayanamurthyaf8dcb42018-01-17 20:23:47 -0800620 val = get_current_reg_code(led->pdata->led1n2_iclamp_mid_ma,
Subbaraman Narayanamurthy01c99612017-04-03 12:26:06 -0700621 led->fnode[LED1].ires_ua);
David Collins8885f792017-01-26 14:36:34 -0800622 rc = qpnp_flash_led_masked_write(led,
623 FLASH_LED_REG_LED1N2_ICLAMP_MID(led->base),
624 FLASH_LED_CURRENT_MASK, val);
625 if (rc < 0)
626 return rc;
627 }
628
629 if (led->pdata->led3_iclamp_low_ma) {
Subbaraman Narayanamurthyaf8dcb42018-01-17 20:23:47 -0800630 val = get_current_reg_code(led->pdata->led3_iclamp_low_ma,
Subbaraman Narayanamurthy01c99612017-04-03 12:26:06 -0700631 led->fnode[LED3].ires_ua);
David Collins8885f792017-01-26 14:36:34 -0800632 rc = qpnp_flash_led_masked_write(led,
633 FLASH_LED_REG_LED3_ICLAMP_LOW(led->base),
634 FLASH_LED_CURRENT_MASK, val);
635 if (rc < 0)
636 return rc;
637 }
638
639 if (led->pdata->led3_iclamp_mid_ma) {
Subbaraman Narayanamurthyaf8dcb42018-01-17 20:23:47 -0800640 val = get_current_reg_code(led->pdata->led3_iclamp_mid_ma,
Subbaraman Narayanamurthy01c99612017-04-03 12:26:06 -0700641 led->fnode[LED3].ires_ua);
David Collins8885f792017-01-26 14:36:34 -0800642 rc = qpnp_flash_led_masked_write(led,
643 FLASH_LED_REG_LED3_ICLAMP_MID(led->base),
644 FLASH_LED_CURRENT_MASK, val);
645 if (rc < 0)
646 return rc;
647 }
648
Subbaraman Narayanamurthy3f684b22017-03-21 20:49:54 -0700649 if (led->pdata->hw_strobe_option > 0) {
650 rc = qpnp_flash_led_masked_write(led,
651 FLASH_LED_REG_STROBE_CFG(led->base),
652 FLASH_LED_STROBE_MASK,
653 led->pdata->hw_strobe_option);
654 if (rc < 0)
655 return rc;
656 }
657
David Collins8885f792017-01-26 14:36:34 -0800658 return 0;
659}
660
661static int qpnp_flash_led_hw_strobe_enable(struct flash_node_data *fnode,
662 int hw_strobe_option, bool on)
663{
664 int rc = 0;
665
666 /*
667 * If the LED controlled by this fnode is not GPIO controlled
668 * for the given strobe_option, return.
669 */
670 if (hw_strobe_option == FLASH_LED_HW_STROBE_OPTION_1)
671 return 0;
672 else if (hw_strobe_option == FLASH_LED_HW_STROBE_OPTION_2
673 && fnode->id != LED3)
674 return 0;
675 else if (hw_strobe_option == FLASH_LED_HW_STROBE_OPTION_3
676 && fnode->id == LED1)
677 return 0;
678
679 if (gpio_is_valid(fnode->hw_strobe_gpio)) {
680 gpio_set_value(fnode->hw_strobe_gpio, on ? 1 : 0);
Subbaraman Narayanamurthy58377f02017-03-21 20:38:43 -0700681 } else if (fnode->strobe_pinctrl && fnode->hw_strobe_state_active &&
David Collins8885f792017-01-26 14:36:34 -0800682 fnode->hw_strobe_state_suspend) {
Subbaraman Narayanamurthy58377f02017-03-21 20:38:43 -0700683 rc = pinctrl_select_state(fnode->strobe_pinctrl,
David Collins8885f792017-01-26 14:36:34 -0800684 on ? fnode->hw_strobe_state_active :
685 fnode->hw_strobe_state_suspend);
686 if (rc < 0) {
687 pr_err("failed to change hw strobe pin state\n");
688 return rc;
689 }
690 }
691
692 return rc;
693}
694
695static int qpnp_flash_led_regulator_enable(struct qpnp_flash_led *led,
696 struct flash_switch_data *snode, bool on)
697{
698 int rc = 0;
699
700 if (!snode || !snode->vreg)
701 return 0;
702
703 if (snode->regulator_on == on)
704 return 0;
705
706 if (on)
707 rc = regulator_enable(snode->vreg);
708 else
709 rc = regulator_disable(snode->vreg);
710
711 if (rc < 0) {
712 pr_err("regulator_%s failed, rc=%d\n",
713 on ? "enable" : "disable", rc);
714 return rc;
715 }
716
717 snode->regulator_on = on ? true : false;
718 return 0;
719}
720
721static int get_property_from_fg(struct qpnp_flash_led *led,
722 enum power_supply_property prop, int *val)
723{
724 int rc;
725 union power_supply_propval pval = {0, };
726
727 if (!led->bms_psy) {
728 pr_err("no bms psy found\n");
729 return -EINVAL;
730 }
731
732 rc = power_supply_get_property(led->bms_psy, prop, &pval);
733 if (rc) {
734 pr_err("bms psy doesn't support reading prop %d rc = %d\n",
735 prop, rc);
736 return rc;
737 }
738
739 *val = pval.intval;
740 return rc;
741}
742
Kiran Gunda1c1e21c2017-12-15 09:55:03 +0530743#define VOLTAGE_HDRM_DEFAULT_MV 350
744#define BHARGER_VOLTAGE_HDRM_DEFAULT_MV 400
745#define BHARGER_HEADROOM_OFFSET_MV 50
David Collins8885f792017-01-26 14:36:34 -0800746static int qpnp_flash_led_get_voltage_headroom(struct qpnp_flash_led *led)
747{
748 int i, voltage_hdrm_mv = 0, voltage_hdrm_max = 0;
Kiran Gunda1c1e21c2017-12-15 09:55:03 +0530749 u8 pmic_subtype = led->pdata->pmic_rev_id->pmic_subtype;
David Collins8885f792017-01-26 14:36:34 -0800750
751 for (i = 0; i < led->num_fnodes; i++) {
752 if (led->fnode[i].led_on) {
753 if (led->fnode[i].id < 2) {
754 if (led->fnode[i].current_ma < 750)
755 voltage_hdrm_mv = 125;
756 else if (led->fnode[i].current_ma < 1000)
757 voltage_hdrm_mv = 175;
758 else if (led->fnode[i].current_ma < 1250)
759 voltage_hdrm_mv = 250;
760 else
761 voltage_hdrm_mv = 350;
762 } else {
763 if (led->fnode[i].current_ma < 375)
764 voltage_hdrm_mv = 125;
765 else if (led->fnode[i].current_ma < 500)
766 voltage_hdrm_mv = 175;
767 else if (led->fnode[i].current_ma < 625)
768 voltage_hdrm_mv = 250;
769 else
770 voltage_hdrm_mv = 350;
771 }
772
Kiran Gunda1c1e21c2017-12-15 09:55:03 +0530773 if (pmic_subtype == PMI632_SUBTYPE)
774 voltage_hdrm_mv += BHARGER_HEADROOM_OFFSET_MV;
775
David Collins8885f792017-01-26 14:36:34 -0800776 voltage_hdrm_max = max(voltage_hdrm_max,
777 voltage_hdrm_mv);
778 }
779 }
780
781 if (!voltage_hdrm_max)
Kiran Gunda1c1e21c2017-12-15 09:55:03 +0530782 return (pmic_subtype == PMI632_SUBTYPE) ?
783 BHARGER_VOLTAGE_HDRM_DEFAULT_MV :
784 VOLTAGE_HDRM_DEFAULT_MV;
David Collins8885f792017-01-26 14:36:34 -0800785
786 return voltage_hdrm_max;
787}
788
789#define UCONV 1000000LL
790#define MCONV 1000LL
791#define FLASH_VDIP_MARGIN 50000
792#define BOB_EFFICIENCY 900LL
793#define VIN_FLASH_MIN_UV 3300000LL
Subbaraman Narayanamurthyd94945e2017-11-28 19:54:09 -0800794static int qpnp_flash_led_calc_max_current(struct qpnp_flash_led *led,
Kiran Gunda1c1e21c2017-12-15 09:55:03 +0530795 int *max_current)
David Collins8885f792017-01-26 14:36:34 -0800796{
Kyle Yan74fdd732017-03-22 13:37:08 -0700797 int ocv_uv, ibat_now, voltage_hdrm_mv, rc;
798 int rbatt_uohm = 0;
David Collins8885f792017-01-26 14:36:34 -0800799 int64_t ibat_flash_ua, avail_flash_ua, avail_flash_power_fw;
800 int64_t ibat_safe_ua, vin_flash_uv, vph_flash_uv, vph_flash_vdip;
801
802 /* RESISTANCE = esr_uohm + rslow_uohm */
803 rc = get_property_from_fg(led, POWER_SUPPLY_PROP_RESISTANCE,
804 &rbatt_uohm);
805 if (rc < 0) {
806 pr_err("bms psy does not support resistance, rc=%d\n", rc);
807 return rc;
808 }
809
810 /* If no battery is connected, return max possible flash current */
Subbaraman Narayanamurthyd94945e2017-11-28 19:54:09 -0800811 if (!rbatt_uohm) {
812 *max_current = FLASH_LED_MAX_TOTAL_CURRENT_MA;
813 return 0;
814 }
David Collins8885f792017-01-26 14:36:34 -0800815
816 rc = get_property_from_fg(led, POWER_SUPPLY_PROP_VOLTAGE_OCV, &ocv_uv);
817 if (rc < 0) {
818 pr_err("bms psy does not support OCV, rc=%d\n", rc);
819 return rc;
820 }
821
822 rc = get_property_from_fg(led, POWER_SUPPLY_PROP_CURRENT_NOW,
823 &ibat_now);
824 if (rc < 0) {
825 pr_err("bms psy does not support current, rc=%d\n", rc);
826 return rc;
827 }
828
829 rbatt_uohm += led->pdata->rpara_uohm;
830 voltage_hdrm_mv = qpnp_flash_led_get_voltage_headroom(led);
831 vph_flash_vdip =
832 VPH_DROOP_THRESH_VAL_TO_UV(led->pdata->vph_droop_threshold)
833 + FLASH_VDIP_MARGIN;
834
835 /* Check if LMH_MITIGATION needs to be triggered */
836 if (!led->trigger_lmh && (ocv_uv < led->pdata->lmh_ocv_threshold_uv ||
837 rbatt_uohm > led->pdata->lmh_rbatt_threshold_uohm)) {
838 led->trigger_lmh = true;
839 rc = qpnp_flash_led_masked_write(led,
840 FLASH_LED_REG_MITIGATION_SW(led->base),
841 FLASH_LED_LMH_MITIGATION_EN_MASK,
842 FLASH_LED_LMH_MITIGATION_ENABLE);
843 if (rc < 0) {
844 pr_err("trigger lmh mitigation failed, rc=%d\n", rc);
845 return rc;
846 }
847
848 /* Wait for LMH mitigation to take effect */
849 udelay(100);
850
Subbaraman Narayanamurthyd94945e2017-11-28 19:54:09 -0800851 return qpnp_flash_led_calc_max_current(led, max_current);
David Collins8885f792017-01-26 14:36:34 -0800852 }
853
854 /*
855 * Calculate the maximum current that can pulled out of the battery
856 * before the battery voltage dips below a safe threshold.
857 */
858 ibat_safe_ua = div_s64((ocv_uv - vph_flash_vdip) * UCONV,
859 rbatt_uohm);
860
861 if (ibat_safe_ua <= led->pdata->ibatt_ocp_threshold_ua) {
862 /*
863 * If the calculated current is below the OCP threshold, then
864 * use it as the possible flash current.
865 */
866 ibat_flash_ua = ibat_safe_ua - ibat_now;
867 vph_flash_uv = vph_flash_vdip;
868 } else {
869 /*
870 * If the calculated current is above the OCP threshold, then
871 * use the ocp threshold instead.
872 *
873 * Any higher current will be tripping the battery OCP.
874 */
875 ibat_flash_ua = led->pdata->ibatt_ocp_threshold_ua - ibat_now;
876 vph_flash_uv = ocv_uv - div64_s64((int64_t)rbatt_uohm
877 * led->pdata->ibatt_ocp_threshold_ua, UCONV);
878 }
879 /* Calculate the input voltage of the flash module. */
880 vin_flash_uv = max((led->pdata->vled_max_uv +
881 (voltage_hdrm_mv * MCONV)), VIN_FLASH_MIN_UV);
882 /* Calculate the available power for the flash module. */
883 avail_flash_power_fw = BOB_EFFICIENCY * vph_flash_uv * ibat_flash_ua;
884 /*
885 * Calculate the available amount of current the flash module can draw
886 * before collapsing the battery. (available power/ flash input voltage)
887 */
888 avail_flash_ua = div64_s64(avail_flash_power_fw, vin_flash_uv * MCONV);
889 pr_debug("avail_iflash=%lld, ocv=%d, ibat=%d, rbatt=%d, trigger_lmh=%d\n",
890 avail_flash_ua, ocv_uv, ibat_now, rbatt_uohm, led->trigger_lmh);
Subbaraman Narayanamurthyd94945e2017-11-28 19:54:09 -0800891 *max_current = min(FLASH_LED_MAX_TOTAL_CURRENT_MA,
David Collins8885f792017-01-26 14:36:34 -0800892 (int)(div64_s64(avail_flash_ua, MCONV)));
Subbaraman Narayanamurthyd94945e2017-11-28 19:54:09 -0800893 return 0;
David Collins8885f792017-01-26 14:36:34 -0800894}
895
Kiran Gunda1c1e21c2017-12-15 09:55:03 +0530896static int is_main_psy_available(struct qpnp_flash_led *led)
897{
898 if (!led->main_psy) {
899 led->main_psy = power_supply_get_by_name("main");
900 if (!led->main_psy) {
901 pr_err_ratelimited("Couldn't get main_psy\n");
902 return -ENODEV;
903 }
904 }
905
906 return 0;
907}
908
909static int is_usb_psy_available(struct qpnp_flash_led *led)
910{
911 if (!led->usb_psy) {
912 led->usb_psy = power_supply_get_by_name("usb");
913 if (!led->usb_psy) {
914 pr_err_ratelimited("Couldn't get usb_psy\n");
915 return -ENODEV;
916 }
917 }
918
919 return 0;
920}
921
922#define CHGBST_EFFICIENCY 800LL
923#define CHGBST_FLASH_VDIP_MARGIN 10000
924#define VIN_FLASH_UV 5000000
925#define BHARGER_FLASH_LED_MAX_TOTAL_CURRENT_MA 1500
926#define BHARGER_FLASH_LED_WITH_OTG_MAX_TOTAL_CURRENT_MA 1100
927static int qpnp_flash_led_calc_bharger_max_current(struct qpnp_flash_led *led,
928 int *max_current)
929{
930 union power_supply_propval pval = {0, };
931 int ocv_uv, ibat_now, voltage_hdrm_mv, flash_led_max_total_curr_ma, rc;
932 int rbatt_uohm = 0, usb_present, otg_enable;
933 int64_t ibat_flash_ua, avail_flash_ua, avail_flash_power_fw;
934 int64_t ibat_safe_ua, vin_flash_uv, vph_flash_uv, vph_flash_vdip;
935 int64_t bst_pwm_ovrhd_uv;
936
937 rc = is_usb_psy_available(led);
938 if (rc < 0)
939 return rc;
940
941 rc = power_supply_get_property(led->usb_psy, POWER_SUPPLY_PROP_SCOPE,
942 &pval);
943 if (rc < 0) {
944 pr_err("usb psy does not support usb present, rc=%d\n", rc);
945 return rc;
946 }
947 otg_enable = pval.intval;
948
949 /* RESISTANCE = esr_uohm + rslow_uohm */
950 rc = get_property_from_fg(led, POWER_SUPPLY_PROP_RESISTANCE,
951 &rbatt_uohm);
952 if (rc < 0) {
953 pr_err("bms psy does not support resistance, rc=%d\n", rc);
954 return rc;
955 }
956
957 /* If no battery is connected, return max possible flash current */
958 if (!rbatt_uohm) {
959 *max_current = (otg_enable == POWER_SUPPLY_SCOPE_SYSTEM) ?
960 BHARGER_FLASH_LED_WITH_OTG_MAX_TOTAL_CURRENT_MA :
961 BHARGER_FLASH_LED_MAX_TOTAL_CURRENT_MA;
962 return 0;
963 }
964
965 rc = get_property_from_fg(led, POWER_SUPPLY_PROP_VOLTAGE_OCV, &ocv_uv);
966 if (rc < 0) {
967 pr_err("bms psy does not support OCV, rc=%d\n", rc);
968 return rc;
969 }
970
971 rc = get_property_from_fg(led, POWER_SUPPLY_PROP_CURRENT_NOW,
972 &ibat_now);
973 if (rc < 0) {
974 pr_err("bms psy does not support current, rc=%d\n", rc);
975 return rc;
976 }
977
978 bst_pwm_ovrhd_uv = led->pdata->bst_pwm_ovrhd_uv;
979
980 rc = power_supply_get_property(led->usb_psy, POWER_SUPPLY_PROP_PRESENT,
981 &pval);
982 if (rc < 0) {
983 pr_err("usb psy does not support usb present, rc=%d\n", rc);
984 return rc;
985 }
986 usb_present = pval.intval;
987
988 rbatt_uohm += led->pdata->rpara_uohm;
989 voltage_hdrm_mv = qpnp_flash_led_get_voltage_headroom(led);
990 vph_flash_vdip =
991 VPH_DROOP_THRESH_VAL_TO_UV(led->pdata->vph_droop_threshold)
992 + CHGBST_FLASH_VDIP_MARGIN;
993
994 /* Check if LMH_MITIGATION needs to be triggered */
995 if (!led->trigger_lmh && (ocv_uv < led->pdata->lmh_ocv_threshold_uv ||
996 rbatt_uohm > led->pdata->lmh_rbatt_threshold_uohm)) {
997 led->trigger_lmh = true;
998 rc = qpnp_flash_led_masked_write(led,
999 FLASH_LED_REG_MITIGATION_SW(led->base),
1000 FLASH_LED_LMH_MITIGATION_EN_MASK,
1001 FLASH_LED_LMH_MITIGATION_ENABLE);
1002 if (rc < 0) {
1003 pr_err("trigger lmh mitigation failed, rc=%d\n", rc);
1004 return rc;
1005 }
1006
1007 /* Wait for LMH mitigation to take effect */
1008 udelay(100);
1009
1010 return qpnp_flash_led_calc_bharger_max_current(led,
1011 max_current);
1012 }
1013
1014 /*
1015 * Calculate the maximum current that can pulled out of the battery
1016 * before the battery voltage dips below a safe threshold.
1017 */
1018 ibat_safe_ua = div_s64((ocv_uv - vph_flash_vdip) * UCONV,
1019 rbatt_uohm);
1020
1021 if (ibat_safe_ua <= led->pdata->ibatt_ocp_threshold_ua) {
1022 /*
1023 * If the calculated current is below the OCP threshold, then
1024 * use it as the possible flash current.
1025 */
1026 ibat_flash_ua = ibat_safe_ua - ibat_now;
1027 vph_flash_uv = vph_flash_vdip;
1028 } else {
1029 /*
1030 * If the calculated current is above the OCP threshold, then
1031 * use the ocp threshold instead.
1032 *
1033 * Any higher current will be tripping the battery OCP.
1034 */
1035 ibat_flash_ua = led->pdata->ibatt_ocp_threshold_ua - ibat_now;
1036 vph_flash_uv = ocv_uv - div64_s64((int64_t)rbatt_uohm
1037 * led->pdata->ibatt_ocp_threshold_ua, UCONV);
1038 }
1039
1040 /* when USB is present or OTG is enabled, VIN_FLASH is always at 5V */
1041 if (usb_present || (otg_enable == POWER_SUPPLY_SCOPE_SYSTEM))
1042 vin_flash_uv = VIN_FLASH_UV;
1043 else
1044 /* Calculate the input voltage of the flash module. */
1045 vin_flash_uv = max((led->pdata->vled_max_uv +
1046 (voltage_hdrm_mv * MCONV)),
1047 vph_flash_uv + bst_pwm_ovrhd_uv);
1048
1049 /* Calculate the available power for the flash module. */
1050 avail_flash_power_fw = CHGBST_EFFICIENCY * vph_flash_uv * ibat_flash_ua;
1051 /*
1052 * Calculate the available amount of current the flash module can draw
1053 * before collapsing the battery. (available power/ flash input voltage)
1054 */
1055 avail_flash_ua = div64_s64(avail_flash_power_fw, vin_flash_uv * MCONV);
1056 flash_led_max_total_curr_ma = otg_enable ?
1057 BHARGER_FLASH_LED_WITH_OTG_MAX_TOTAL_CURRENT_MA :
1058 BHARGER_FLASH_LED_MAX_TOTAL_CURRENT_MA;
1059 *max_current = min(flash_led_max_total_curr_ma,
1060 (int)(div64_s64(avail_flash_ua, MCONV)));
1061
1062 pr_debug("avail_iflash=%lld, ocv=%d, ibat=%d, rbatt=%d, trigger_lmh=%d max_current=%lld usb_present=%d otg_enable=%d\n",
1063 avail_flash_ua, ocv_uv, ibat_now, rbatt_uohm, led->trigger_lmh,
1064 (*max_current * MCONV), usb_present, otg_enable);
1065 return 0;
1066}
1067
1068
Subbaraman Narayanamurthyd94945e2017-11-28 19:54:09 -08001069static int qpnp_flash_led_calc_thermal_current_lim(struct qpnp_flash_led *led,
Kiran Gunda1c1e21c2017-12-15 09:55:03 +05301070 int *thermal_current_lim)
David Collins8885f792017-01-26 14:36:34 -08001071{
David Collins8885f792017-01-26 14:36:34 -08001072 int rc;
1073 u8 thermal_thrsh1, thermal_thrsh2, thermal_thrsh3, otst_status;
1074
1075 /* Store THERMAL_THRSHx register values */
1076 rc = qpnp_flash_led_masked_read(led,
1077 FLASH_LED_REG_THERMAL_THRSH1(led->base),
1078 FLASH_LED_THERMAL_THRSH_MASK,
1079 &thermal_thrsh1);
1080 if (rc < 0)
1081 return rc;
1082
1083 rc = qpnp_flash_led_masked_read(led,
1084 FLASH_LED_REG_THERMAL_THRSH2(led->base),
1085 FLASH_LED_THERMAL_THRSH_MASK,
1086 &thermal_thrsh2);
1087 if (rc < 0)
1088 return rc;
1089
1090 rc = qpnp_flash_led_masked_read(led,
1091 FLASH_LED_REG_THERMAL_THRSH3(led->base),
1092 FLASH_LED_THERMAL_THRSH_MASK,
1093 &thermal_thrsh3);
1094 if (rc < 0)
1095 return rc;
1096
1097 /* Lower THERMAL_THRSHx thresholds to minimum */
1098 rc = qpnp_flash_led_masked_write(led,
1099 FLASH_LED_REG_THERMAL_THRSH1(led->base),
1100 FLASH_LED_THERMAL_THRSH_MASK,
1101 FLASH_LED_THERMAL_THRSH_MIN);
1102 if (rc < 0)
1103 return rc;
1104
1105 rc = qpnp_flash_led_masked_write(led,
1106 FLASH_LED_REG_THERMAL_THRSH2(led->base),
1107 FLASH_LED_THERMAL_THRSH_MASK,
1108 FLASH_LED_THERMAL_THRSH_MIN);
1109 if (rc < 0)
1110 return rc;
1111
1112 rc = qpnp_flash_led_masked_write(led,
1113 FLASH_LED_REG_THERMAL_THRSH3(led->base),
1114 FLASH_LED_THERMAL_THRSH_MASK,
1115 FLASH_LED_THERMAL_THRSH_MIN);
1116 if (rc < 0)
1117 return rc;
1118
1119 /* Check THERMAL_OTST status */
1120 rc = qpnp_flash_led_read(led,
1121 FLASH_LED_REG_LED_STATUS2(led->base),
1122 &otst_status);
1123 if (rc < 0)
1124 return rc;
1125
1126 /* Look up current limit based on THERMAL_OTST status */
1127 if (otst_status)
Subbaraman Narayanamurthyd94945e2017-11-28 19:54:09 -08001128 *thermal_current_lim =
David Collins8885f792017-01-26 14:36:34 -08001129 led->pdata->thermal_derate_current[otst_status >> 1];
1130
1131 /* Restore THERMAL_THRESHx registers to original values */
1132 rc = qpnp_flash_led_masked_write(led,
1133 FLASH_LED_REG_THERMAL_THRSH1(led->base),
1134 FLASH_LED_THERMAL_THRSH_MASK,
1135 thermal_thrsh1);
1136 if (rc < 0)
1137 return rc;
1138
1139 rc = qpnp_flash_led_masked_write(led,
1140 FLASH_LED_REG_THERMAL_THRSH2(led->base),
1141 FLASH_LED_THERMAL_THRSH_MASK,
1142 thermal_thrsh2);
1143 if (rc < 0)
1144 return rc;
1145
1146 rc = qpnp_flash_led_masked_write(led,
1147 FLASH_LED_REG_THERMAL_THRSH3(led->base),
1148 FLASH_LED_THERMAL_THRSH_MASK,
1149 thermal_thrsh3);
1150 if (rc < 0)
1151 return rc;
1152
Subbaraman Narayanamurthyd94945e2017-11-28 19:54:09 -08001153 return 0;
David Collins8885f792017-01-26 14:36:34 -08001154}
1155
Subbaraman Narayanamurthyd94945e2017-11-28 19:54:09 -08001156static int qpnp_flash_led_get_max_avail_current(struct qpnp_flash_led *led,
1157 int *max_avail_current)
David Collins8885f792017-01-26 14:36:34 -08001158{
Subbaraman Narayanamurthyd94945e2017-11-28 19:54:09 -08001159 int thermal_current_lim = 0, rc;
Kiran Gunda1c1e21c2017-12-15 09:55:03 +05301160 u8 pmic_subtype = led->pdata->pmic_rev_id->pmic_subtype;
David Collins8885f792017-01-26 14:36:34 -08001161
1162 led->trigger_lmh = false;
Kiran Gunda1c1e21c2017-12-15 09:55:03 +05301163
1164 if (pmic_subtype == PMI632_SUBTYPE)
1165 rc = qpnp_flash_led_calc_bharger_max_current(led,
1166 max_avail_current);
1167 else
1168 rc = qpnp_flash_led_calc_max_current(led, max_avail_current);
1169
Subbaraman Narayanamurthyd94945e2017-11-28 19:54:09 -08001170 if (rc < 0) {
1171 pr_err("Couldn't calculate max_avail_current, rc=%d\n", rc);
1172 return rc;
1173 }
1174
1175 if (led->pdata->thermal_derate_en) {
1176 rc = qpnp_flash_led_calc_thermal_current_lim(led,
1177 &thermal_current_lim);
1178 if (rc < 0) {
1179 pr_err("Couldn't calculate thermal_current_lim, rc=%d\n",
1180 rc);
1181 return rc;
1182 }
1183 }
David Collins8885f792017-01-26 14:36:34 -08001184
1185 if (thermal_current_lim)
Subbaraman Narayanamurthyd94945e2017-11-28 19:54:09 -08001186 *max_avail_current = min(*max_avail_current,
1187 thermal_current_lim);
David Collins8885f792017-01-26 14:36:34 -08001188
Subbaraman Narayanamurthyd94945e2017-11-28 19:54:09 -08001189 return 0;
David Collins8885f792017-01-26 14:36:34 -08001190}
1191
Ankit Sharmaa7153c32017-03-22 19:04:52 +05301192static void qpnp_flash_led_aggregate_max_current(struct flash_node_data *fnode)
1193{
1194 struct qpnp_flash_led *led = dev_get_drvdata(&fnode->pdev->dev);
1195
1196 if (fnode->current_ma)
1197 led->total_current_ma += fnode->current_ma
1198 - fnode->prev_current_ma;
1199 else
1200 led->total_current_ma -= fnode->prev_current_ma;
1201
1202 fnode->prev_current_ma = fnode->current_ma;
1203}
1204
David Collins8885f792017-01-26 14:36:34 -08001205static void qpnp_flash_led_node_set(struct flash_node_data *fnode, int value)
1206{
Kiran Gunda5cadca72017-07-26 14:37:52 +05301207 int i = 0;
David Collins8885f792017-01-26 14:36:34 -08001208 int prgm_current_ma = value;
Ankit Sharma8798ab12017-04-06 15:44:09 +05301209 int min_ma = fnode->ires_ua / 1000;
Ankit Sharmaa7153c32017-03-22 19:04:52 +05301210 struct qpnp_flash_led *led = dev_get_drvdata(&fnode->pdev->dev);
Kiran Gunda1c1e21c2017-12-15 09:55:03 +05301211 u8 pmic_subtype = led->pdata->pmic_rev_id->pmic_subtype;
David Collins8885f792017-01-26 14:36:34 -08001212
1213 if (value <= 0)
1214 prgm_current_ma = 0;
Ankit Sharma8798ab12017-04-06 15:44:09 +05301215 else if (value < min_ma)
1216 prgm_current_ma = min_ma;
David Collins8885f792017-01-26 14:36:34 -08001217
Kiran Gunda5cadca72017-07-26 14:37:52 +05301218 fnode->ires_idx = fnode->default_ires_idx;
1219 fnode->ires_ua = fnode->default_ires_ua;
1220
David Collins8885f792017-01-26 14:36:34 -08001221 prgm_current_ma = min(prgm_current_ma, fnode->max_current);
Kiran Gunda5cadca72017-07-26 14:37:52 +05301222 if (prgm_current_ma > max_ires_curr_ma_table[fnode->ires_idx]) {
1223 /* find the matching ires */
1224 for (i = MAX_IRES_LEVELS - 1; i >= 0; i--) {
1225 if (prgm_current_ma <= max_ires_curr_ma_table[i]) {
1226 fnode->ires_idx = i;
1227 fnode->ires_ua = FLASH_LED_IRES_MIN_UA +
1228 (FLASH_LED_IRES_BASE - fnode->ires_idx) *
1229 FLASH_LED_IRES_DIVISOR;
1230 break;
1231 }
1232 }
1233 }
David Collins8885f792017-01-26 14:36:34 -08001234 fnode->current_ma = prgm_current_ma;
1235 fnode->cdev.brightness = prgm_current_ma;
Subbaraman Narayanamurthyaf8dcb42018-01-17 20:23:47 -08001236 fnode->current_reg_val = get_current_reg_code(prgm_current_ma,
David Collins8885f792017-01-26 14:36:34 -08001237 fnode->ires_ua);
Subbaraman Narayanamurthy1b411f52018-03-06 16:01:26 -08001238 if (prgm_current_ma)
1239 fnode->led_on = true;
Ankit Sharmaa7153c32017-03-22 19:04:52 +05301240
Kiran Gunda1c1e21c2017-12-15 09:55:03 +05301241 if (pmic_subtype != PMI632_SUBTYPE &&
1242 led->pdata->chgr_mitigation_sel == FLASH_SW_CHARGER_MITIGATION) {
Ankit Sharmaa7153c32017-03-22 19:04:52 +05301243 qpnp_flash_led_aggregate_max_current(fnode);
1244 led->trigger_chgr = false;
1245 if (led->total_current_ma >= 1000)
1246 led->trigger_chgr = true;
1247 }
David Collins8885f792017-01-26 14:36:34 -08001248}
1249
1250static int qpnp_flash_led_switch_disable(struct flash_switch_data *snode)
1251{
1252 struct qpnp_flash_led *led = dev_get_drvdata(&snode->pdev->dev);
1253 int i, rc, addr_offset;
1254
1255 rc = qpnp_flash_led_masked_write(led,
1256 FLASH_LED_EN_LED_CTRL(led->base),
1257 snode->led_mask, FLASH_LED_DISABLE);
1258 if (rc < 0)
1259 return rc;
1260
1261 if (led->trigger_lmh) {
1262 rc = qpnp_flash_led_masked_write(led,
1263 FLASH_LED_REG_MITIGATION_SW(led->base),
1264 FLASH_LED_LMH_MITIGATION_EN_MASK,
1265 FLASH_LED_LMH_MITIGATION_DISABLE);
1266 if (rc < 0) {
1267 pr_err("disable lmh mitigation failed, rc=%d\n", rc);
1268 return rc;
1269 }
1270 }
1271
Kiran Gunda1c1e21c2017-12-15 09:55:03 +05301272 if (led->pdata->chgr_mitigation_sel && !led->trigger_chgr) {
David Collins8885f792017-01-26 14:36:34 -08001273 rc = qpnp_flash_led_masked_write(led,
1274 FLASH_LED_REG_MITIGATION_SW(led->base),
1275 FLASH_LED_CHGR_MITIGATION_EN_MASK,
1276 FLASH_LED_CHGR_MITIGATION_DISABLE);
1277 if (rc < 0) {
1278 pr_err("disable chgr mitigation failed, rc=%d\n", rc);
1279 return rc;
1280 }
1281 }
1282
1283 led->enable--;
1284 if (led->enable == 0) {
1285 rc = qpnp_flash_led_masked_write(led,
1286 FLASH_LED_REG_MOD_CTRL(led->base),
1287 FLASH_LED_MOD_CTRL_MASK, FLASH_LED_DISABLE);
1288 if (rc < 0)
1289 return rc;
1290 }
1291
1292 for (i = 0; i < led->num_fnodes; i++) {
1293 if (!led->fnode[i].led_on ||
1294 !(snode->led_mask & BIT(led->fnode[i].id)))
1295 continue;
1296
1297 addr_offset = led->fnode[i].id;
1298 rc = qpnp_flash_led_masked_write(led,
1299 FLASH_LED_REG_TGR_CURRENT(led->base + addr_offset),
1300 FLASH_LED_CURRENT_MASK, 0);
1301 if (rc < 0)
1302 return rc;
1303
1304 led->fnode[i].led_on = false;
1305
Subbaraman Narayanamurthy3f684b22017-03-21 20:49:54 -07001306 if (led->fnode[i].strobe_sel == HW_STROBE) {
David Collins8885f792017-01-26 14:36:34 -08001307 rc = qpnp_flash_led_hw_strobe_enable(&led->fnode[i],
1308 led->pdata->hw_strobe_option, false);
1309 if (rc < 0) {
1310 pr_err("Unable to disable hw strobe, rc=%d\n",
1311 rc);
1312 return rc;
1313 }
1314 }
1315 }
1316
Subbaraman Narayanamurthy58377f02017-03-21 20:38:43 -07001317 if (snode->led_en_pinctrl) {
1318 pr_debug("Selecting suspend state for %s\n", snode->cdev.name);
1319 rc = pinctrl_select_state(snode->led_en_pinctrl,
1320 snode->gpio_state_suspend);
1321 if (rc < 0) {
1322 pr_err("failed to select pinctrl suspend state rc=%d\n",
1323 rc);
1324 return rc;
1325 }
1326 }
1327
David Collins8885f792017-01-26 14:36:34 -08001328 snode->enabled = false;
1329 return 0;
1330}
1331
Subbaraman Narayanamurthyd737fd52018-01-17 19:58:52 -08001332static int qpnp_flash_led_symmetry_config(struct flash_switch_data *snode)
1333{
1334 struct qpnp_flash_led *led = dev_get_drvdata(&snode->pdev->dev);
1335 int i, total_curr_ma = 0, num_leds = 0, prgm_current_ma;
1336 enum flash_led_type type = FLASH_LED_TYPE_UNKNOWN;
1337
1338 for (i = 0; i < led->num_fnodes; i++) {
1339 if (snode->led_mask & BIT(led->fnode[i].id)) {
1340 if (led->fnode[i].type == FLASH_LED_TYPE_FLASH &&
1341 led->fnode[i].led_on)
1342 type = FLASH_LED_TYPE_FLASH;
1343
1344 if (led->fnode[i].type == FLASH_LED_TYPE_TORCH &&
1345 led->fnode[i].led_on)
1346 type = FLASH_LED_TYPE_TORCH;
1347 }
1348 }
1349
1350 if (type == FLASH_LED_TYPE_UNKNOWN) {
1351 pr_err("Incorrect type possibly because of no active LEDs\n");
1352 return -EINVAL;
1353 }
1354
1355 for (i = 0; i < led->num_fnodes; i++) {
1356 if ((snode->led_mask & BIT(led->fnode[i].id)) &&
1357 (led->fnode[i].type == type)) {
1358 total_curr_ma += led->fnode[i].current_ma;
1359 num_leds++;
1360 }
1361 }
1362
1363 if (num_leds > 0 && total_curr_ma > 0) {
1364 prgm_current_ma = total_curr_ma / num_leds;
1365 } else {
1366 pr_err("Incorrect configuration, num_leds: %d total_curr_ma: %d\n",
1367 num_leds, total_curr_ma);
1368 return -EINVAL;
1369 }
1370
1371 if (prgm_current_ma == 0) {
1372 pr_warn("prgm_curr_ma cannot be 0\n");
1373 return 0;
1374 }
1375
1376 pr_debug("num_leds: %d total: %d prgm_curr_ma: %d\n", num_leds,
1377 total_curr_ma, prgm_current_ma);
1378
1379 for (i = 0; i < led->num_fnodes; i++) {
1380 if (snode->led_mask & BIT(led->fnode[i].id) &&
1381 led->fnode[i].current_ma != prgm_current_ma &&
1382 led->fnode[i].type == type) {
1383 qpnp_flash_led_node_set(&led->fnode[i],
1384 prgm_current_ma);
1385 pr_debug("%s LED %d current: %d code: %d ires_ua: %d\n",
1386 (type == FLASH_LED_TYPE_FLASH) ?
1387 "flash" : "torch",
1388 led->fnode[i].id, prgm_current_ma,
1389 led->fnode[i].current_reg_val,
1390 led->fnode[i].ires_ua);
1391 }
1392 }
1393
1394 return 0;
1395}
1396
Kiran Gunda1c1e21c2017-12-15 09:55:03 +05301397#define FLASH_LED_MODULE_EN_TIME_MS 300
1398static int qpnp_flash_poll_vreg_ok(struct qpnp_flash_led *led)
1399{
1400 int rc, i;
1401 union power_supply_propval pval = {0, };
1402
1403 rc = is_main_psy_available(led);
1404 if (rc < 0)
1405 return rc;
1406
1407 for (i = 0; i < 60; i++) {
1408 /* wait for the flash vreg_ok to be set */
1409 mdelay(5);
1410
1411 rc = power_supply_get_property(led->main_psy,
1412 POWER_SUPPLY_PROP_FLASH_TRIGGER, &pval);
1413 if (rc < 0) {
1414 pr_err("main psy doesn't support reading prop %d rc = %d\n",
1415 POWER_SUPPLY_PROP_FLASH_TRIGGER, rc);
1416 return rc;
1417 }
1418
1419 if (pval.intval > 0) {
1420 pr_debug("Flash trigger set\n");
1421 break;
1422 }
1423
1424 if (pval.intval < 0) {
1425 pr_err("Error during flash trigger %d\n", pval.intval);
1426 return pval.intval;
1427 }
1428 }
1429
1430 if (!pval.intval) {
1431 pr_err("Failed to enable the module\n");
1432 return -ETIMEDOUT;
1433 }
1434
1435 return 0;
1436}
1437
David Collins8885f792017-01-26 14:36:34 -08001438static int qpnp_flash_led_switch_set(struct flash_switch_data *snode, bool on)
1439{
1440 struct qpnp_flash_led *led = dev_get_drvdata(&snode->pdev->dev);
Kiran Gunda1c1e21c2017-12-15 09:55:03 +05301441 u8 pmic_subtype = led->pdata->pmic_rev_id->pmic_subtype;
David Collins8885f792017-01-26 14:36:34 -08001442 int rc, i, addr_offset;
1443 u8 val, mask;
1444
1445 if (snode->enabled == on) {
1446 pr_debug("Switch node is already %s!\n",
1447 on ? "enabled" : "disabled");
1448 return 0;
1449 }
1450
1451 if (!on) {
1452 rc = qpnp_flash_led_switch_disable(snode);
1453 return rc;
1454 }
1455
Subbaraman Narayanamurthy411699a2018-01-15 12:40:49 -08001456 /* Iterate over all active leds for this switch node */
Subbaraman Narayanamurthyd737fd52018-01-17 19:58:52 -08001457 if (snode->symmetry_en) {
1458 rc = qpnp_flash_led_symmetry_config(snode);
1459 if (rc < 0) {
1460 pr_err("Failed to configure current symmetrically, rc=%d\n",
1461 rc);
1462 return rc;
1463 }
1464 }
1465
David Collins8885f792017-01-26 14:36:34 -08001466 val = 0;
1467 for (i = 0; i < led->num_fnodes; i++)
Subbaraman Narayanamurthy411699a2018-01-15 12:40:49 -08001468 if (led->fnode[i].led_on &&
1469 snode->led_mask & BIT(led->fnode[i].id))
Kiran Gunda5cadca72017-07-26 14:37:52 +05301470 val |= led->fnode[i].ires_idx << (led->fnode[i].id * 2);
David Collins8885f792017-01-26 14:36:34 -08001471
1472 rc = qpnp_flash_led_masked_write(led, FLASH_LED_REG_IRES(led->base),
1473 FLASH_LED_CURRENT_MASK, val);
1474 if (rc < 0)
1475 return rc;
1476
David Collins8885f792017-01-26 14:36:34 -08001477 val = 0;
1478 for (i = 0; i < led->num_fnodes; i++) {
1479 if (!led->fnode[i].led_on ||
1480 !(snode->led_mask & BIT(led->fnode[i].id)))
1481 continue;
1482
1483 addr_offset = led->fnode[i].id;
Subbaraman Narayanamurthy3f684b22017-03-21 20:49:54 -07001484 if (led->fnode[i].strobe_sel == SW_STROBE)
David Collins8885f792017-01-26 14:36:34 -08001485 mask = FLASH_LED_HW_SW_STROBE_SEL_BIT;
Subbaraman Narayanamurthy3f684b22017-03-21 20:49:54 -07001486 else
1487 mask = FLASH_HW_STROBE_MASK;
David Collins8885f792017-01-26 14:36:34 -08001488 rc = qpnp_flash_led_masked_write(led,
1489 FLASH_LED_REG_STROBE_CTRL(led->base + addr_offset),
Subbaraman Narayanamurthy3f684b22017-03-21 20:49:54 -07001490 mask, led->fnode[i].strobe_ctrl);
David Collins8885f792017-01-26 14:36:34 -08001491 if (rc < 0)
1492 return rc;
1493
1494 rc = qpnp_flash_led_masked_write(led,
1495 FLASH_LED_REG_TGR_CURRENT(led->base + addr_offset),
1496 FLASH_LED_CURRENT_MASK, led->fnode[i].current_reg_val);
1497 if (rc < 0)
1498 return rc;
1499
1500 rc = qpnp_flash_led_write(led,
1501 FLASH_LED_REG_SAFETY_TMR(led->base + addr_offset),
1502 led->fnode[i].duration);
1503 if (rc < 0)
1504 return rc;
1505
1506 val |= FLASH_LED_ENABLE << led->fnode[i].id;
1507
Subbaraman Narayanamurthy3f684b22017-03-21 20:49:54 -07001508 if (led->fnode[i].strobe_sel == HW_STROBE) {
David Collins8885f792017-01-26 14:36:34 -08001509 rc = qpnp_flash_led_hw_strobe_enable(&led->fnode[i],
1510 led->pdata->hw_strobe_option, true);
1511 if (rc < 0) {
1512 pr_err("Unable to enable hw strobe rc=%d\n",
1513 rc);
1514 return rc;
1515 }
1516 }
1517 }
1518
Subbaraman Narayanamurthy58377f02017-03-21 20:38:43 -07001519 if (snode->led_en_pinctrl) {
1520 pr_debug("Selecting active state for %s\n", snode->cdev.name);
1521 rc = pinctrl_select_state(snode->led_en_pinctrl,
1522 snode->gpio_state_active);
1523 if (rc < 0) {
1524 pr_err("failed to select pinctrl active state rc=%d\n",
1525 rc);
1526 return rc;
1527 }
1528 }
1529
David Collins8885f792017-01-26 14:36:34 -08001530 if (led->enable == 0) {
1531 rc = qpnp_flash_led_masked_write(led,
1532 FLASH_LED_REG_MOD_CTRL(led->base),
1533 FLASH_LED_MOD_CTRL_MASK, FLASH_LED_MOD_ENABLE);
1534 if (rc < 0)
1535 return rc;
Kiran Gunda1c1e21c2017-12-15 09:55:03 +05301536
1537 if (pmic_subtype == PMI632_SUBTYPE) {
1538 rc = qpnp_flash_poll_vreg_ok(led);
1539 if (rc < 0) {
1540 /* Disable the module */
1541 qpnp_flash_led_masked_write(led,
1542 FLASH_LED_REG_MOD_CTRL(led->base),
1543 FLASH_LED_MOD_CTRL_MASK,
1544 FLASH_LED_DISABLE);
1545
1546 return rc;
1547 }
1548 }
David Collins8885f792017-01-26 14:36:34 -08001549 }
1550 led->enable++;
1551
1552 if (led->trigger_lmh) {
1553 rc = qpnp_flash_led_masked_write(led,
1554 FLASH_LED_REG_MITIGATION_SW(led->base),
1555 FLASH_LED_LMH_MITIGATION_EN_MASK,
1556 FLASH_LED_LMH_MITIGATION_ENABLE);
1557 if (rc < 0) {
1558 pr_err("trigger lmh mitigation failed, rc=%d\n", rc);
1559 return rc;
1560 }
Subbaraman Narayanamurthyd02fbc92017-02-02 16:39:41 -08001561 /* Wait for LMH mitigation to take effect */
1562 udelay(500);
David Collins8885f792017-01-26 14:36:34 -08001563 }
1564
Kiran Gunda1c1e21c2017-12-15 09:55:03 +05301565 if (led->pdata->chgr_mitigation_sel && led->trigger_chgr) {
David Collins8885f792017-01-26 14:36:34 -08001566 rc = qpnp_flash_led_masked_write(led,
1567 FLASH_LED_REG_MITIGATION_SW(led->base),
1568 FLASH_LED_CHGR_MITIGATION_EN_MASK,
1569 FLASH_LED_CHGR_MITIGATION_ENABLE);
1570 if (rc < 0) {
1571 pr_err("trigger chgr mitigation failed, rc=%d\n", rc);
1572 return rc;
1573 }
1574 }
1575
1576 rc = qpnp_flash_led_masked_write(led,
1577 FLASH_LED_EN_LED_CTRL(led->base),
1578 snode->led_mask, val);
1579 if (rc < 0)
1580 return rc;
1581
1582 snode->enabled = true;
1583 return 0;
1584}
1585
Kiran Gunda1c1e21c2017-12-15 09:55:03 +05301586static int qpnp_flash_led_regulator_control(struct led_classdev *led_cdev,
1587 int options, int *max_current)
1588{
1589 int rc;
1590 u8 pmic_subtype;
1591 struct flash_switch_data *snode;
1592 struct qpnp_flash_led *led;
1593 union power_supply_propval ret = {0, };
1594
1595 snode = container_of(led_cdev, struct flash_switch_data, cdev);
1596 led = dev_get_drvdata(&snode->pdev->dev);
1597 pmic_subtype = led->pdata->pmic_rev_id->pmic_subtype;
1598
1599 if (pmic_subtype == PMI632_SUBTYPE) {
1600 rc = is_main_psy_available(led);
1601 if (rc < 0)
1602 return rc;
1603
1604 rc = is_usb_psy_available(led);
1605 if (rc < 0)
1606 return rc;
1607 }
1608
1609 if (!(options & FLASH_LED_PREPARE_OPTIONS_MASK)) {
1610 pr_err("Invalid options %d\n", options);
1611 return -EINVAL;
1612 }
1613
1614 if (options & ENABLE_REGULATOR) {
1615 if (pmic_subtype == PMI632_SUBTYPE) {
1616 ret.intval = 1;
1617 rc = power_supply_set_property(led->main_psy,
1618 POWER_SUPPLY_PROP_FLASH_ACTIVE,
1619 &ret);
1620 if (rc < 0) {
1621 pr_err("Failed to set FLASH_ACTIVE on charger rc=%d\n",
1622 rc);
1623 return rc;
1624 }
1625 pr_debug("FLASH_ACTIVE = 1\n");
1626 } else {
1627 rc = qpnp_flash_led_regulator_enable(led, snode, true);
1628 if (rc < 0) {
1629 pr_err("enable regulator failed, rc=%d\n", rc);
1630 return rc;
1631 }
1632 }
1633 }
1634
1635 if (options & DISABLE_REGULATOR) {
1636 if (pmic_subtype == PMI632_SUBTYPE) {
1637 ret.intval = 0;
1638 rc = power_supply_set_property(led->main_psy,
1639 POWER_SUPPLY_PROP_FLASH_ACTIVE,
1640 &ret);
1641 if (rc < 0) {
1642 pr_err("Failed to set FLASH_ACTIVE on charger rc=%d\n",
1643 rc);
1644 return rc;
1645 }
1646 pr_debug("FLASH_ACTIVE = 0\n");
1647 } else {
1648 rc = qpnp_flash_led_regulator_enable(led, snode, false);
1649 if (rc < 0) {
1650 pr_err("disable regulator failed, rc=%d\n", rc);
1651 return rc;
1652 }
1653 }
1654 }
1655
1656 if (options & QUERY_MAX_CURRENT) {
1657 rc = qpnp_flash_led_get_max_avail_current(led, max_current);
1658 if (rc < 0) {
1659 pr_err("query max current failed, rc=%d\n", rc);
1660 return rc;
1661 }
1662 }
1663
1664 return 0;
1665}
1666
Kiran Gundabf1e6c02018-01-17 17:50:20 +05301667static int qpnp_flash_led_prepare_v2(struct led_trigger *trig, int options,
David Collins8885f792017-01-26 14:36:34 -08001668 int *max_current)
1669{
1670 struct led_classdev *led_cdev;
David Collins8885f792017-01-26 14:36:34 -08001671 int rc;
1672
1673 if (!trig) {
1674 pr_err("Invalid led_trigger provided\n");
1675 return -EINVAL;
1676 }
1677
1678 led_cdev = trigger_to_lcdev(trig);
1679 if (!led_cdev) {
1680 pr_err("Invalid led_cdev in trigger %s\n", trig->name);
1681 return -EINVAL;
1682 }
1683
Kiran Gunda1c1e21c2017-12-15 09:55:03 +05301684 rc = qpnp_flash_led_regulator_control(led_cdev, options, max_current);
David Collins8885f792017-01-26 14:36:34 -08001685
Kiran Gunda1c1e21c2017-12-15 09:55:03 +05301686 return rc;
David Collins8885f792017-01-26 14:36:34 -08001687}
1688
1689static void qpnp_flash_led_brightness_set(struct led_classdev *led_cdev,
1690 enum led_brightness value)
1691{
1692 struct flash_node_data *fnode = NULL;
1693 struct flash_switch_data *snode = NULL;
1694 struct qpnp_flash_led *led = NULL;
1695 int rc;
1696
1697 /*
1698 * strncmp() must be used here since a prefix comparison is required
1699 * in order to support names like led:switch_0 and led:flash_1.
1700 */
1701 if (!strncmp(led_cdev->name, "led:switch", strlen("led:switch"))) {
1702 snode = container_of(led_cdev, struct flash_switch_data, cdev);
1703 led = dev_get_drvdata(&snode->pdev->dev);
1704 } else if (!strncmp(led_cdev->name, "led:flash", strlen("led:flash")) ||
1705 !strncmp(led_cdev->name, "led:torch",
1706 strlen("led:torch"))) {
1707 fnode = container_of(led_cdev, struct flash_node_data, cdev);
1708 led = dev_get_drvdata(&fnode->pdev->dev);
1709 }
1710
1711 if (!led) {
1712 pr_err("Failed to get flash driver data\n");
1713 return;
1714 }
1715
1716 spin_lock(&led->lock);
1717 if (snode) {
1718 rc = qpnp_flash_led_switch_set(snode, value > 0);
1719 if (rc < 0)
1720 pr_err("Failed to set flash LED switch rc=%d\n", rc);
1721 } else if (fnode) {
1722 qpnp_flash_led_node_set(fnode, value);
1723 }
1724
1725 spin_unlock(&led->lock);
1726}
1727
Kiran Gunda1c1e21c2017-12-15 09:55:03 +05301728static ssize_t qpnp_flash_led_prepare_store(struct device *dev,
1729 struct device_attribute *attr, const char *buf, size_t count)
1730{
1731 int rc, options, max_current;
1732 u32 val;
1733 struct led_classdev *led_cdev = dev_get_drvdata(dev);
1734
1735 rc = kstrtouint(buf, 0, &val);
1736 if (rc < 0)
1737 return rc;
1738
1739 if (val != 0 && val != 1)
1740 return count;
1741
1742 options = val ? ENABLE_REGULATOR : DISABLE_REGULATOR;
1743
1744 rc = qpnp_flash_led_regulator_control(led_cdev, options, &max_current);
1745 if (rc < 0)
1746 return rc;
1747
1748 return count;
1749}
1750
David Collins8885f792017-01-26 14:36:34 -08001751/* sysfs show function for flash_max_current */
1752static ssize_t qpnp_flash_led_max_current_show(struct device *dev,
1753 struct device_attribute *attr, char *buf)
1754{
Subbaraman Narayanamurthyd94945e2017-11-28 19:54:09 -08001755 int rc, max_current = 0;
David Collins8885f792017-01-26 14:36:34 -08001756 struct flash_switch_data *snode;
1757 struct qpnp_flash_led *led;
1758 struct led_classdev *led_cdev = dev_get_drvdata(dev);
1759
1760 snode = container_of(led_cdev, struct flash_switch_data, cdev);
1761 led = dev_get_drvdata(&snode->pdev->dev);
1762
Subbaraman Narayanamurthyd94945e2017-11-28 19:54:09 -08001763 rc = qpnp_flash_led_get_max_avail_current(led, &max_current);
David Collins8885f792017-01-26 14:36:34 -08001764 if (rc < 0)
1765 pr_err("query max current failed, rc=%d\n", rc);
1766
Subbaraman Narayanamurthyd94945e2017-11-28 19:54:09 -08001767 return snprintf(buf, PAGE_SIZE, "%d\n", max_current);
David Collins8885f792017-01-26 14:36:34 -08001768}
1769
1770/* sysfs attributes exported by flash_led */
1771static struct device_attribute qpnp_flash_led_attrs[] = {
1772 __ATTR(max_current, 0664, qpnp_flash_led_max_current_show, NULL),
Kiran Gunda1c1e21c2017-12-15 09:55:03 +05301773 __ATTR(enable, 0664, NULL, qpnp_flash_led_prepare_store),
David Collins8885f792017-01-26 14:36:34 -08001774};
1775
1776static int flash_led_psy_notifier_call(struct notifier_block *nb,
1777 unsigned long ev, void *v)
1778{
1779 struct power_supply *psy = v;
1780 struct qpnp_flash_led *led =
1781 container_of(nb, struct qpnp_flash_led, nb);
1782
1783 if (ev != PSY_EVENT_PROP_CHANGED)
1784 return NOTIFY_OK;
1785
1786 if (!strcmp(psy->desc->name, "bms")) {
1787 led->bms_psy = power_supply_get_by_name("bms");
1788 if (!led->bms_psy)
1789 pr_err("Failed to get bms power_supply\n");
1790 else
1791 power_supply_unreg_notifier(&led->nb);
1792 }
1793
1794 return NOTIFY_OK;
1795}
1796
1797static int flash_led_psy_register_notifier(struct qpnp_flash_led *led)
1798{
1799 int rc;
1800
1801 led->nb.notifier_call = flash_led_psy_notifier_call;
1802 rc = power_supply_reg_notifier(&led->nb);
1803 if (rc < 0) {
1804 pr_err("Couldn't register psy notifier, rc = %d\n", rc);
1805 return rc;
1806 }
1807
1808 return 0;
1809}
1810
1811/* irq handler */
1812static irqreturn_t qpnp_flash_led_irq_handler(int irq, void *_led)
1813{
1814 struct qpnp_flash_led *led = _led;
1815 enum flash_led_irq_type irq_type = INVALID_IRQ;
1816 int rc;
1817 u8 irq_status, led_status1, led_status2;
1818
1819 pr_debug("irq received, irq=%d\n", irq);
1820
1821 rc = qpnp_flash_led_read(led,
1822 FLASH_LED_REG_INT_RT_STS(led->base), &irq_status);
1823 if (rc < 0) {
1824 pr_err("Failed to read interrupt status reg, rc=%d\n", rc);
1825 goto exit;
1826 }
1827
1828 if (irq == led->pdata->all_ramp_up_done_irq)
1829 irq_type = ALL_RAMP_UP_DONE_IRQ;
1830 else if (irq == led->pdata->all_ramp_down_done_irq)
1831 irq_type = ALL_RAMP_DOWN_DONE_IRQ;
1832 else if (irq == led->pdata->led_fault_irq)
1833 irq_type = LED_FAULT_IRQ;
1834
1835 if (irq_type == ALL_RAMP_UP_DONE_IRQ)
1836 atomic_notifier_call_chain(&irq_notifier_list,
1837 irq_type, NULL);
1838
1839 if (irq_type == LED_FAULT_IRQ) {
1840 rc = qpnp_flash_led_read(led,
1841 FLASH_LED_REG_LED_STATUS1(led->base), &led_status1);
1842 if (rc < 0) {
1843 pr_err("Failed to read led_status1 reg, rc=%d\n", rc);
1844 goto exit;
1845 }
1846
1847 rc = qpnp_flash_led_read(led,
1848 FLASH_LED_REG_LED_STATUS2(led->base), &led_status2);
1849 if (rc < 0) {
1850 pr_err("Failed to read led_status2 reg, rc=%d\n", rc);
1851 goto exit;
1852 }
1853
1854 if (led_status1)
1855 pr_emerg("led short/open fault detected! led_status1=%x\n",
1856 led_status1);
1857
1858 if (led_status2 & FLASH_LED_VPH_DROOP_FAULT_MASK)
1859 pr_emerg("led vph_droop fault detected!\n");
1860 }
1861
1862 pr_debug("irq handled, irq_type=%x, irq_status=%x\n", irq_type,
1863 irq_status);
1864
1865exit:
1866 return IRQ_HANDLED;
1867}
1868
1869int qpnp_flash_led_register_irq_notifier(struct notifier_block *nb)
1870{
1871 return atomic_notifier_chain_register(&irq_notifier_list, nb);
1872}
1873
1874int qpnp_flash_led_unregister_irq_notifier(struct notifier_block *nb)
1875{
1876 return atomic_notifier_chain_unregister(&irq_notifier_list, nb);
1877}
1878
Subbaraman Narayanamurthyaf8dcb42018-01-17 20:23:47 -08001879static inline u8 get_safety_timer_code(u32 duration_ms)
1880{
1881 if (!duration_ms)
1882 return 0;
1883
1884 return (duration_ms / 10) - 1;
1885}
1886
1887static inline u8 get_vph_droop_thresh_code(u32 val_mv)
1888{
1889 if (!val_mv)
1890 return 0;
1891
1892 return (val_mv / 100) - 25;
1893}
1894
David Collins8885f792017-01-26 14:36:34 -08001895static int qpnp_flash_led_parse_each_led_dt(struct qpnp_flash_led *led,
1896 struct flash_node_data *fnode, struct device_node *node)
1897{
1898 const char *temp_string;
Ankit Sharma8798ab12017-04-06 15:44:09 +05301899 int rc, min_ma;
David Collins8885f792017-01-26 14:36:34 -08001900 u32 val;
Subbaraman Narayanamurthy3f684b22017-03-21 20:49:54 -07001901 bool hw_strobe = 0, edge_trigger = 0, active_high = 0;
Kiran Gunda1c1e21c2017-12-15 09:55:03 +05301902 u8 pmic_subtype = led->pdata->pmic_rev_id->pmic_subtype;
David Collins8885f792017-01-26 14:36:34 -08001903
1904 fnode->pdev = led->pdev;
1905 fnode->cdev.brightness_set = qpnp_flash_led_brightness_set;
1906 fnode->cdev.brightness_get = qpnp_flash_led_brightness_get;
1907
1908 rc = of_property_read_string(node, "qcom,led-name", &fnode->cdev.name);
1909 if (rc < 0) {
1910 pr_err("Unable to read flash LED names\n");
1911 return rc;
1912 }
1913
1914 rc = of_property_read_string(node, "label", &temp_string);
1915 if (!rc) {
1916 if (!strcmp(temp_string, "flash")) {
1917 fnode->type = FLASH_LED_TYPE_FLASH;
1918 } else if (!strcmp(temp_string, "torch")) {
1919 fnode->type = FLASH_LED_TYPE_TORCH;
1920 } else {
1921 pr_err("Wrong flash LED type\n");
1922 return rc;
1923 }
1924 } else {
1925 pr_err("Unable to read flash LED label\n");
1926 return rc;
1927 }
1928
1929 rc = of_property_read_u32(node, "qcom,id", &val);
1930 if (!rc) {
1931 fnode->id = (u8)val;
Kiran Gunda1c1e21c2017-12-15 09:55:03 +05301932
1933 if (pmic_subtype == PMI632_SUBTYPE && fnode->id > 1) {
1934 pr_err("Flash node id = %d not supported\n", fnode->id);
1935 return -EINVAL;
1936 }
David Collins8885f792017-01-26 14:36:34 -08001937 } else {
1938 pr_err("Unable to read flash LED ID\n");
1939 return rc;
1940 }
1941
1942 rc = of_property_read_string(node, "qcom,default-led-trigger",
1943 &fnode->cdev.default_trigger);
1944 if (rc < 0) {
1945 pr_err("Unable to read trigger name\n");
1946 return rc;
1947 }
1948
Kiran Gunda5cadca72017-07-26 14:37:52 +05301949 fnode->default_ires_ua = fnode->ires_ua = FLASH_LED_IRES_DEFAULT_UA;
1950 fnode->default_ires_idx = fnode->ires_idx = FLASH_LED_IRES_DEFAULT_VAL;
David Collins8885f792017-01-26 14:36:34 -08001951 rc = of_property_read_u32(node, "qcom,ires-ua", &val);
1952 if (!rc) {
Kiran Gunda5cadca72017-07-26 14:37:52 +05301953 fnode->default_ires_ua = fnode->ires_ua = val;
1954 fnode->default_ires_idx = fnode->ires_idx =
1955 FLASH_LED_IRES_BASE - (val - FLASH_LED_IRES_MIN_UA) /
1956 FLASH_LED_IRES_DIVISOR;
David Collins8885f792017-01-26 14:36:34 -08001957 } else if (rc != -EINVAL) {
1958 pr_err("Unable to read current resolution rc=%d\n", rc);
1959 return rc;
1960 }
1961
Ankit Sharma8798ab12017-04-06 15:44:09 +05301962 min_ma = fnode->ires_ua / 1000;
David Collins8885f792017-01-26 14:36:34 -08001963 rc = of_property_read_u32(node, "qcom,max-current", &val);
1964 if (!rc) {
Ankit Sharma8798ab12017-04-06 15:44:09 +05301965 if (val < min_ma)
1966 val = min_ma;
David Collins8885f792017-01-26 14:36:34 -08001967 fnode->max_current = val;
1968 fnode->cdev.max_brightness = val;
1969 } else {
1970 pr_err("Unable to read max current, rc=%d\n", rc);
1971 return rc;
1972 }
1973
1974 rc = of_property_read_u32(node, "qcom,current-ma", &val);
1975 if (!rc) {
Ankit Sharma8798ab12017-04-06 15:44:09 +05301976 if (val < min_ma || val > fnode->max_current)
David Collins8885f792017-01-26 14:36:34 -08001977 pr_warn("Invalid operational current specified, capping it\n");
Ankit Sharma8798ab12017-04-06 15:44:09 +05301978 if (val < min_ma)
1979 val = min_ma;
David Collins8885f792017-01-26 14:36:34 -08001980 if (val > fnode->max_current)
1981 val = fnode->max_current;
1982 fnode->current_ma = val;
1983 fnode->cdev.brightness = val;
1984 } else if (rc != -EINVAL) {
1985 pr_err("Unable to read operational current, rc=%d\n", rc);
1986 return rc;
1987 }
1988
1989 fnode->duration = FLASH_LED_SAFETY_TMR_DISABLED;
1990 rc = of_property_read_u32(node, "qcom,duration-ms", &val);
1991 if (!rc) {
Subbaraman Narayanamurthyaf8dcb42018-01-17 20:23:47 -08001992 fnode->duration = get_safety_timer_code(val);
1993 if (fnode->duration)
1994 fnode->duration |= FLASH_LED_SAFETY_TMR_ENABLE;
David Collins8885f792017-01-26 14:36:34 -08001995 } else if (rc == -EINVAL) {
1996 if (fnode->type == FLASH_LED_TYPE_FLASH) {
1997 pr_err("Timer duration is required for flash LED\n");
1998 return rc;
1999 }
2000 } else {
2001 pr_err("Unable to read timer duration\n");
2002 return rc;
2003 }
2004
2005 fnode->hdrm_val = FLASH_LED_HDRM_VOL_DEFAULT_MV;
2006 rc = of_property_read_u32(node, "qcom,hdrm-voltage-mv", &val);
2007 if (!rc) {
2008 val = (val - FLASH_LED_HDRM_VOL_BASE_MV) /
2009 FLASH_LED_HDRM_VOL_STEP_MV;
2010 fnode->hdrm_val = (val << FLASH_LED_HDRM_VOL_SHIFT) &
2011 FLASH_LED_HDRM_VOL_MASK;
2012 } else if (rc != -EINVAL) {
2013 pr_err("Unable to read headroom voltage\n");
2014 return rc;
2015 }
2016
2017 rc = of_property_read_u32(node, "qcom,hdrm-vol-hi-lo-win-mv", &val);
2018 if (!rc) {
2019 fnode->hdrm_val |= (val / FLASH_LED_HDRM_VOL_STEP_MV) &
2020 ~FLASH_LED_HDRM_VOL_MASK;
2021 } else if (rc == -EINVAL) {
2022 fnode->hdrm_val |= FLASH_LED_HDRM_VOL_HI_LO_WIN_DEFAULT_MV;
2023 } else {
2024 pr_err("Unable to read hdrm hi-lo window voltage\n");
2025 return rc;
2026 }
2027
Subbaraman Narayanamurthy3f684b22017-03-21 20:49:54 -07002028 fnode->strobe_sel = SW_STROBE;
2029 rc = of_property_read_u32(node, "qcom,strobe-sel", &val);
2030 if (rc < 0) {
2031 if (rc != -EINVAL) {
2032 pr_err("Unable to read qcom,strobe-sel property\n");
2033 return rc;
2034 }
2035 } else {
2036 if (val < SW_STROBE || val > LPG_STROBE) {
2037 pr_err("Incorrect strobe selection specified %d\n",
2038 val);
2039 return -EINVAL;
2040 }
2041 fnode->strobe_sel = (u8)val;
2042 }
2043
2044 /*
2045 * LPG strobe is allowed only for LED3 and HW strobe option should be
2046 * option 2 or 3.
2047 */
2048 if (fnode->strobe_sel == LPG_STROBE) {
2049 if (led->pdata->hw_strobe_option ==
2050 FLASH_LED_HW_STROBE_OPTION_1) {
2051 pr_err("Incorrect strobe option for LPG strobe\n");
2052 return -EINVAL;
2053 }
2054 if (fnode->id != LED3) {
2055 pr_err("Incorrect LED chosen for LPG strobe\n");
2056 return -EINVAL;
2057 }
2058 }
2059
2060 if (fnode->strobe_sel == HW_STROBE) {
David Collins8885f792017-01-26 14:36:34 -08002061 edge_trigger = of_property_read_bool(node,
2062 "qcom,hw-strobe-edge-trigger");
2063 active_high = !of_property_read_bool(node,
2064 "qcom,hw-strobe-active-low");
Subbaraman Narayanamurthy3f684b22017-03-21 20:49:54 -07002065 hw_strobe = 1;
2066 } else if (fnode->strobe_sel == LPG_STROBE) {
2067 /* LPG strobe requires level trigger and active high */
2068 edge_trigger = 0;
2069 active_high = 1;
2070 hw_strobe = 1;
David Collins8885f792017-01-26 14:36:34 -08002071 }
Subbaraman Narayanamurthy3f684b22017-03-21 20:49:54 -07002072 fnode->strobe_ctrl = (hw_strobe << 2) | (edge_trigger << 1) |
2073 active_high;
David Collins8885f792017-01-26 14:36:34 -08002074
Subbaraman Narayanamurthy58377f02017-03-21 20:38:43 -07002075 rc = led_classdev_register(&led->pdev->dev, &fnode->cdev);
2076 if (rc < 0) {
2077 pr_err("Unable to register led node %d\n", fnode->id);
2078 return rc;
2079 }
2080
2081 fnode->cdev.dev->of_node = node;
2082 fnode->strobe_pinctrl = devm_pinctrl_get(fnode->cdev.dev);
2083 if (IS_ERR_OR_NULL(fnode->strobe_pinctrl)) {
2084 pr_debug("No pinctrl defined for %s, err=%ld\n",
2085 fnode->cdev.name, PTR_ERR(fnode->strobe_pinctrl));
2086 fnode->strobe_pinctrl = NULL;
2087 }
2088
Subbaraman Narayanamurthy3f684b22017-03-21 20:49:54 -07002089 if (fnode->strobe_sel == HW_STROBE) {
David Collins8885f792017-01-26 14:36:34 -08002090 if (of_find_property(node, "qcom,hw-strobe-gpio", NULL)) {
2091 fnode->hw_strobe_gpio = of_get_named_gpio(node,
2092 "qcom,hw-strobe-gpio", 0);
2093 if (fnode->hw_strobe_gpio < 0) {
2094 pr_err("Invalid gpio specified\n");
2095 return fnode->hw_strobe_gpio;
2096 }
2097 gpio_direction_output(fnode->hw_strobe_gpio, 0);
Subbaraman Narayanamurthy58377f02017-03-21 20:38:43 -07002098 } else if (fnode->strobe_pinctrl) {
David Collins8885f792017-01-26 14:36:34 -08002099 fnode->hw_strobe_gpio = -1;
2100 fnode->hw_strobe_state_active =
Subbaraman Narayanamurthy58377f02017-03-21 20:38:43 -07002101 pinctrl_lookup_state(fnode->strobe_pinctrl,
2102 "strobe_enable");
David Collins8885f792017-01-26 14:36:34 -08002103 if (IS_ERR_OR_NULL(fnode->hw_strobe_state_active)) {
2104 pr_err("No active pin for hardware strobe, rc=%ld\n",
2105 PTR_ERR(fnode->hw_strobe_state_active));
2106 fnode->hw_strobe_state_active = NULL;
2107 }
2108
2109 fnode->hw_strobe_state_suspend =
Subbaraman Narayanamurthy58377f02017-03-21 20:38:43 -07002110 pinctrl_lookup_state(fnode->strobe_pinctrl,
2111 "strobe_disable");
David Collins8885f792017-01-26 14:36:34 -08002112 if (IS_ERR_OR_NULL(fnode->hw_strobe_state_suspend)) {
2113 pr_err("No suspend pin for hardware strobe, rc=%ld\n",
2114 PTR_ERR(fnode->hw_strobe_state_suspend)
2115 );
2116 fnode->hw_strobe_state_suspend = NULL;
2117 }
2118 }
2119 }
2120
David Collins8885f792017-01-26 14:36:34 -08002121 return 0;
2122}
2123
2124static int qpnp_flash_led_parse_and_register_switch(struct qpnp_flash_led *led,
2125 struct flash_switch_data *snode,
2126 struct device_node *node)
2127{
2128 int rc = 0, num;
2129 char reg_name[16], reg_sup_name[16];
2130
2131 rc = of_property_read_string(node, "qcom,led-name", &snode->cdev.name);
2132 if (rc < 0) {
2133 pr_err("Failed to read switch node name, rc=%d\n", rc);
2134 return rc;
2135 }
2136
2137 rc = sscanf(snode->cdev.name, "led:switch_%d", &num);
2138 if (!rc) {
2139 pr_err("No number for switch device?\n");
2140 return -EINVAL;
2141 }
2142
2143 rc = of_property_read_string(node, "qcom,default-led-trigger",
2144 &snode->cdev.default_trigger);
2145 if (rc < 0) {
2146 pr_err("Unable to read trigger name, rc=%d\n", rc);
2147 return rc;
2148 }
2149
2150 rc = of_property_read_u32(node, "qcom,led-mask", &snode->led_mask);
2151 if (rc < 0) {
2152 pr_err("Unable to read led mask rc=%d\n", rc);
2153 return rc;
2154 }
2155
Subbaraman Narayanamurthyd737fd52018-01-17 19:58:52 -08002156 snode->symmetry_en = of_property_read_bool(node, "qcom,symmetry-en");
2157
David Collins8885f792017-01-26 14:36:34 -08002158 if (snode->led_mask < 1 || snode->led_mask > 7) {
2159 pr_err("Invalid value for led-mask\n");
2160 return -EINVAL;
2161 }
2162
2163 scnprintf(reg_name, sizeof(reg_name), "switch%d-supply", num);
2164 if (of_find_property(led->pdev->dev.of_node, reg_name, NULL)) {
2165 scnprintf(reg_sup_name, sizeof(reg_sup_name), "switch%d", num);
2166 snode->vreg = devm_regulator_get(&led->pdev->dev, reg_sup_name);
2167 if (IS_ERR_OR_NULL(snode->vreg)) {
2168 rc = PTR_ERR(snode->vreg);
2169 if (rc != -EPROBE_DEFER)
2170 pr_err("Failed to get regulator, rc=%d\n", rc);
2171 snode->vreg = NULL;
2172 return rc;
2173 }
2174 }
2175
2176 snode->pdev = led->pdev;
2177 snode->cdev.brightness_set = qpnp_flash_led_brightness_set;
2178 snode->cdev.brightness_get = qpnp_flash_led_brightness_get;
2179 snode->cdev.flags |= LED_KEEP_TRIGGER;
2180 rc = led_classdev_register(&led->pdev->dev, &snode->cdev);
2181 if (rc < 0) {
2182 pr_err("Unable to register led switch node\n");
2183 return rc;
2184 }
2185
2186 snode->cdev.dev->of_node = node;
Subbaraman Narayanamurthy58377f02017-03-21 20:38:43 -07002187
2188 snode->led_en_pinctrl = devm_pinctrl_get(snode->cdev.dev);
2189 if (IS_ERR_OR_NULL(snode->led_en_pinctrl)) {
2190 pr_debug("No pinctrl defined for %s, err=%ld\n",
2191 snode->cdev.name, PTR_ERR(snode->led_en_pinctrl));
2192 snode->led_en_pinctrl = NULL;
2193 }
2194
2195 if (snode->led_en_pinctrl) {
2196 snode->gpio_state_active =
2197 pinctrl_lookup_state(snode->led_en_pinctrl,
2198 "led_enable");
2199 if (IS_ERR_OR_NULL(snode->gpio_state_active)) {
2200 pr_err("Cannot lookup LED active state\n");
2201 devm_pinctrl_put(snode->led_en_pinctrl);
2202 snode->led_en_pinctrl = NULL;
2203 return PTR_ERR(snode->gpio_state_active);
2204 }
2205
2206 snode->gpio_state_suspend =
2207 pinctrl_lookup_state(snode->led_en_pinctrl,
2208 "led_disable");
2209 if (IS_ERR_OR_NULL(snode->gpio_state_suspend)) {
2210 pr_err("Cannot lookup LED disable state\n");
2211 devm_pinctrl_put(snode->led_en_pinctrl);
2212 snode->led_en_pinctrl = NULL;
2213 return PTR_ERR(snode->gpio_state_suspend);
2214 }
2215 }
2216
David Collins8885f792017-01-26 14:36:34 -08002217 return 0;
2218}
2219
2220static int get_code_from_table(int *table, int len, int value)
2221{
2222 int i;
2223
2224 for (i = 0; i < len; i++) {
2225 if (value == table[i])
2226 break;
2227 }
2228
2229 if (i == len) {
2230 pr_err("Couldn't find %d from table\n", value);
2231 return -ENODATA;
2232 }
2233
2234 return i;
2235}
2236
2237static int qpnp_flash_led_parse_common_dt(struct qpnp_flash_led *led,
2238 struct device_node *node)
2239{
2240 struct device_node *revid_node;
2241 int rc;
2242 u32 val;
Kiran Gunda1c1e21c2017-12-15 09:55:03 +05302243 u8 pmic_subtype;
David Collins8885f792017-01-26 14:36:34 -08002244 bool short_circuit_det, open_circuit_det, vph_droop_det;
2245
2246 revid_node = of_parse_phandle(node, "qcom,pmic-revid", 0);
2247 if (!revid_node) {
2248 pr_err("Missing qcom,pmic-revid property - driver failed\n");
2249 return -EINVAL;
2250 }
2251
2252 led->pdata->pmic_rev_id = get_revid_data(revid_node);
2253 if (IS_ERR_OR_NULL(led->pdata->pmic_rev_id)) {
2254 pr_err("Unable to get pmic_revid rc=%ld\n",
2255 PTR_ERR(led->pdata->pmic_rev_id));
2256 /*
2257 * the revid peripheral must be registered, any failure
2258 * here only indicates that the rev-id module has not
2259 * probed yet.
2260 */
2261 return -EPROBE_DEFER;
2262 }
2263
Kiran Gunda1c1e21c2017-12-15 09:55:03 +05302264 pmic_subtype = led->pdata->pmic_rev_id->pmic_subtype;
David Collins8885f792017-01-26 14:36:34 -08002265 pr_debug("PMIC subtype %d Digital major %d\n",
2266 led->pdata->pmic_rev_id->pmic_subtype,
2267 led->pdata->pmic_rev_id->rev4);
David Collins8885f792017-01-26 14:36:34 -08002268 led->pdata->hdrm_auto_mode_en = of_property_read_bool(node,
2269 "qcom,hdrm-auto-mode");
2270
2271 led->pdata->isc_delay = FLASH_LED_ISC_DELAY_DEFAULT;
2272 rc = of_property_read_u32(node, "qcom,isc-delay-us", &val);
2273 if (!rc) {
2274 led->pdata->isc_delay =
2275 val >> FLASH_LED_ISC_WARMUP_DELAY_SHIFT;
2276 } else if (rc != -EINVAL) {
2277 pr_err("Unable to read ISC delay, rc=%d\n", rc);
2278 return rc;
2279 }
2280
2281 led->pdata->warmup_delay = FLASH_LED_WARMUP_DELAY_DEFAULT;
2282 rc = of_property_read_u32(node, "qcom,warmup-delay-us", &val);
2283 if (!rc) {
2284 led->pdata->warmup_delay =
2285 val >> FLASH_LED_ISC_WARMUP_DELAY_SHIFT;
2286 } else if (rc != -EINVAL) {
2287 pr_err("Unable to read WARMUP delay, rc=%d\n", rc);
2288 return rc;
2289 }
2290
2291 short_circuit_det =
2292 of_property_read_bool(node, "qcom,short-circuit-det");
2293 open_circuit_det = of_property_read_bool(node, "qcom,open-circuit-det");
2294 vph_droop_det = of_property_read_bool(node, "qcom,vph-droop-det");
2295 led->pdata->current_derate_en_cfg = (vph_droop_det << 2) |
2296 (open_circuit_det << 1) | short_circuit_det;
2297
2298 led->pdata->thermal_derate_en =
2299 of_property_read_bool(node, "qcom,thermal-derate-en");
2300
2301 if (led->pdata->thermal_derate_en) {
2302 led->pdata->thermal_derate_current =
2303 devm_kcalloc(&led->pdev->dev,
2304 FLASH_LED_THERMAL_OTST_LEVELS,
2305 sizeof(int), GFP_KERNEL);
2306 if (!led->pdata->thermal_derate_current)
2307 return -ENOMEM;
2308
2309 rc = of_property_read_u32_array(node,
2310 "qcom,thermal-derate-current",
2311 led->pdata->thermal_derate_current,
2312 FLASH_LED_THERMAL_OTST_LEVELS);
2313 if (rc < 0) {
2314 pr_err("Unable to read thermal current limits, rc=%d\n",
2315 rc);
2316 return rc;
2317 }
2318 }
2319
2320 led->pdata->otst_ramp_bkup_en =
2321 !of_property_read_bool(node, "qcom,otst-ramp-back-up-dis");
2322
2323 led->pdata->thermal_derate_slow = -EINVAL;
2324 rc = of_property_read_u32(node, "qcom,thermal-derate-slow", &val);
2325 if (!rc) {
2326 if (val < 0 || val > THERMAL_DERATE_SLOW_MAX) {
2327 pr_err("Invalid thermal_derate_slow %d\n", val);
2328 return -EINVAL;
2329 }
2330
2331 led->pdata->thermal_derate_slow =
2332 get_code_from_table(thermal_derate_slow_table,
2333 ARRAY_SIZE(thermal_derate_slow_table), val);
2334 } else if (rc != -EINVAL) {
2335 pr_err("Unable to read thermal derate slow, rc=%d\n", rc);
2336 return rc;
2337 }
2338
2339 led->pdata->thermal_derate_fast = -EINVAL;
2340 rc = of_property_read_u32(node, "qcom,thermal-derate-fast", &val);
2341 if (!rc) {
2342 if (val < 0 || val > THERMAL_DERATE_FAST_MAX) {
2343 pr_err("Invalid thermal_derate_fast %d\n", val);
2344 return -EINVAL;
2345 }
2346
2347 led->pdata->thermal_derate_fast =
2348 get_code_from_table(thermal_derate_fast_table,
2349 ARRAY_SIZE(thermal_derate_fast_table), val);
2350 } else if (rc != -EINVAL) {
2351 pr_err("Unable to read thermal derate fast, rc=%d\n", rc);
2352 return rc;
2353 }
2354
2355 led->pdata->thermal_debounce = -EINVAL;
2356 rc = of_property_read_u32(node, "qcom,thermal-debounce", &val);
2357 if (!rc) {
2358 if (val < 0 || val > THERMAL_DEBOUNCE_TIME_MAX) {
2359 pr_err("Invalid thermal_debounce %d\n", val);
2360 return -EINVAL;
2361 }
2362
2363 if (val >= 0 && val < 16)
2364 led->pdata->thermal_debounce = 0;
2365 else
2366 led->pdata->thermal_debounce = ilog2(val) - 3;
2367 } else if (rc != -EINVAL) {
2368 pr_err("Unable to read thermal debounce, rc=%d\n", rc);
2369 return rc;
2370 }
2371
2372 led->pdata->thermal_hysteresis = -EINVAL;
2373 rc = of_property_read_u32(node, "qcom,thermal-hysteresis", &val);
2374 if (!rc) {
Kiran Gunda1c1e21c2017-12-15 09:55:03 +05302375 if (pmic_subtype == PM660L_SUBTYPE)
David Collins8885f792017-01-26 14:36:34 -08002376 val = THERMAL_HYST_TEMP_TO_VAL(val, 20);
2377 else
2378 val = THERMAL_HYST_TEMP_TO_VAL(val, 15);
2379
2380 if (val < 0 || val > THERMAL_DERATE_HYSTERESIS_MAX) {
2381 pr_err("Invalid thermal_derate_hysteresis %d\n", val);
2382 return -EINVAL;
2383 }
2384
2385 led->pdata->thermal_hysteresis = val;
2386 } else if (rc != -EINVAL) {
2387 pr_err("Unable to read thermal hysteresis, rc=%d\n", rc);
2388 return rc;
2389 }
2390
2391 led->pdata->thermal_thrsh1 = -EINVAL;
2392 rc = of_property_read_u32(node, "qcom,thermal-thrsh1", &val);
2393 if (!rc) {
2394 led->pdata->thermal_thrsh1 =
2395 get_code_from_table(otst1_threshold_table,
2396 ARRAY_SIZE(otst1_threshold_table), val);
2397 } else if (rc != -EINVAL) {
2398 pr_err("Unable to read thermal thrsh1, rc=%d\n", rc);
2399 return rc;
2400 }
2401
2402 led->pdata->thermal_thrsh2 = -EINVAL;
2403 rc = of_property_read_u32(node, "qcom,thermal-thrsh2", &val);
2404 if (!rc) {
2405 led->pdata->thermal_thrsh2 =
2406 get_code_from_table(otst2_threshold_table,
2407 ARRAY_SIZE(otst2_threshold_table), val);
2408 } else if (rc != -EINVAL) {
2409 pr_err("Unable to read thermal thrsh2, rc=%d\n", rc);
2410 return rc;
2411 }
2412
2413 led->pdata->thermal_thrsh3 = -EINVAL;
2414 rc = of_property_read_u32(node, "qcom,thermal-thrsh3", &val);
2415 if (!rc) {
2416 led->pdata->thermal_thrsh3 =
2417 get_code_from_table(otst3_threshold_table,
2418 ARRAY_SIZE(otst3_threshold_table), val);
2419 } else if (rc != -EINVAL) {
2420 pr_err("Unable to read thermal thrsh3, rc=%d\n", rc);
2421 return rc;
2422 }
2423
2424 led->pdata->vph_droop_debounce = FLASH_LED_VPH_DROOP_DEBOUNCE_DEFAULT;
2425 rc = of_property_read_u32(node, "qcom,vph-droop-debounce-us", &val);
2426 if (!rc) {
2427 led->pdata->vph_droop_debounce =
2428 VPH_DROOP_DEBOUNCE_US_TO_VAL(val);
2429 } else if (rc != -EINVAL) {
2430 pr_err("Unable to read VPH droop debounce, rc=%d\n", rc);
2431 return rc;
2432 }
2433
2434 if (led->pdata->vph_droop_debounce > FLASH_LED_DEBOUNCE_MAX) {
2435 pr_err("Invalid VPH droop debounce specified\n");
2436 return -EINVAL;
2437 }
2438
Kiran Gunda1c1e21c2017-12-15 09:55:03 +05302439 if (pmic_subtype == PMI632_SUBTYPE)
2440 led->pdata->vph_droop_threshold =
2441 BHARGER_FLASH_LED_VPH_DROOP_THRESH_DEFAULT;
2442 else
2443 led->pdata->vph_droop_threshold =
2444 FLASH_LED_VPH_DROOP_THRESH_DEFAULT;
2445
David Collins8885f792017-01-26 14:36:34 -08002446 rc = of_property_read_u32(node, "qcom,vph-droop-threshold-mv", &val);
2447 if (!rc) {
2448 led->pdata->vph_droop_threshold =
Subbaraman Narayanamurthyaf8dcb42018-01-17 20:23:47 -08002449 get_vph_droop_thresh_code(val);
David Collins8885f792017-01-26 14:36:34 -08002450 } else if (rc != -EINVAL) {
2451 pr_err("Unable to read VPH droop threshold, rc=%d\n", rc);
2452 return rc;
2453 }
2454
2455 if (led->pdata->vph_droop_threshold > FLASH_LED_VPH_DROOP_THRESH_MAX) {
2456 pr_err("Invalid VPH droop threshold specified\n");
2457 return -EINVAL;
2458 }
2459
2460 led->pdata->vph_droop_hysteresis =
2461 FLASH_LED_VPH_DROOP_HYST_DEFAULT;
2462 rc = of_property_read_u32(node, "qcom,vph-droop-hysteresis-mv", &val);
2463 if (!rc) {
2464 led->pdata->vph_droop_hysteresis =
2465 VPH_DROOP_HYST_MV_TO_VAL(val);
2466 } else if (rc != -EINVAL) {
2467 pr_err("Unable to read VPH droop hysteresis, rc=%d\n", rc);
2468 return rc;
2469 }
2470
2471 if (led->pdata->vph_droop_hysteresis > FLASH_LED_HYSTERESIS_MAX) {
2472 pr_err("Invalid VPH droop hysteresis specified\n");
2473 return -EINVAL;
2474 }
2475
2476 led->pdata->vph_droop_hysteresis <<= FLASH_LED_VPH_DROOP_HYST_SHIFT;
2477
Subbaraman Narayanamurthy3f684b22017-03-21 20:49:54 -07002478 led->pdata->hw_strobe_option = -EINVAL;
David Collins8885f792017-01-26 14:36:34 -08002479 rc = of_property_read_u32(node, "qcom,hw-strobe-option", &val);
2480 if (!rc) {
Subbaraman Narayanamurthy3f684b22017-03-21 20:49:54 -07002481 led->pdata->hw_strobe_option = val;
David Collins8885f792017-01-26 14:36:34 -08002482 } else if (rc != -EINVAL) {
2483 pr_err("Unable to parse hw strobe option, rc=%d\n", rc);
2484 return rc;
2485 }
2486
2487 rc = of_property_read_u32(node, "qcom,led1n2-iclamp-low-ma", &val);
2488 if (!rc) {
2489 led->pdata->led1n2_iclamp_low_ma = val;
2490 } else if (rc != -EINVAL) {
2491 pr_err("Unable to read led1n2_iclamp_low current, rc=%d\n", rc);
2492 return rc;
2493 }
2494
2495 rc = of_property_read_u32(node, "qcom,led1n2-iclamp-mid-ma", &val);
2496 if (!rc) {
2497 led->pdata->led1n2_iclamp_mid_ma = val;
2498 } else if (rc != -EINVAL) {
2499 pr_err("Unable to read led1n2_iclamp_mid current, rc=%d\n", rc);
2500 return rc;
2501 }
2502
2503 rc = of_property_read_u32(node, "qcom,led3-iclamp-low-ma", &val);
2504 if (!rc) {
2505 led->pdata->led3_iclamp_low_ma = val;
2506 } else if (rc != -EINVAL) {
2507 pr_err("Unable to read led3_iclamp_low current, rc=%d\n", rc);
2508 return rc;
2509 }
2510
2511 rc = of_property_read_u32(node, "qcom,led3-iclamp-mid-ma", &val);
2512 if (!rc) {
2513 led->pdata->led3_iclamp_mid_ma = val;
2514 } else if (rc != -EINVAL) {
2515 pr_err("Unable to read led3_iclamp_mid current, rc=%d\n", rc);
2516 return rc;
2517 }
2518
2519 led->pdata->vled_max_uv = FLASH_LED_VLED_MAX_DEFAULT_UV;
2520 rc = of_property_read_u32(node, "qcom,vled-max-uv", &val);
2521 if (!rc) {
2522 led->pdata->vled_max_uv = val;
2523 } else if (rc != -EINVAL) {
2524 pr_err("Unable to parse vled_max voltage, rc=%d\n", rc);
2525 return rc;
2526 }
2527
2528 led->pdata->ibatt_ocp_threshold_ua =
2529 FLASH_LED_IBATT_OCP_THRESH_DEFAULT_UA;
2530 rc = of_property_read_u32(node, "qcom,ibatt-ocp-threshold-ua", &val);
2531 if (!rc) {
2532 led->pdata->ibatt_ocp_threshold_ua = val;
2533 } else if (rc != -EINVAL) {
2534 pr_err("Unable to parse ibatt_ocp threshold, rc=%d\n", rc);
2535 return rc;
2536 }
2537
2538 led->pdata->rpara_uohm = FLASH_LED_RPARA_DEFAULT_UOHM;
2539 rc = of_property_read_u32(node, "qcom,rparasitic-uohm", &val);
2540 if (!rc) {
2541 led->pdata->rpara_uohm = val;
2542 } else if (rc != -EINVAL) {
2543 pr_err("Unable to parse rparasitic, rc=%d\n", rc);
2544 return rc;
2545 }
2546
2547 led->pdata->lmh_ocv_threshold_uv =
2548 FLASH_LED_LMH_OCV_THRESH_DEFAULT_UV;
2549 rc = of_property_read_u32(node, "qcom,lmh-ocv-threshold-uv", &val);
2550 if (!rc) {
2551 led->pdata->lmh_ocv_threshold_uv = val;
2552 } else if (rc != -EINVAL) {
2553 pr_err("Unable to parse lmh ocv threshold, rc=%d\n", rc);
2554 return rc;
2555 }
2556
2557 led->pdata->lmh_rbatt_threshold_uohm =
2558 FLASH_LED_LMH_RBATT_THRESH_DEFAULT_UOHM;
2559 rc = of_property_read_u32(node, "qcom,lmh-rbatt-threshold-uohm", &val);
2560 if (!rc) {
2561 led->pdata->lmh_rbatt_threshold_uohm = val;
2562 } else if (rc != -EINVAL) {
2563 pr_err("Unable to parse lmh rbatt threshold, rc=%d\n", rc);
2564 return rc;
2565 }
2566
2567 led->pdata->lmh_level = FLASH_LED_LMH_LEVEL_DEFAULT;
2568 rc = of_property_read_u32(node, "qcom,lmh-level", &val);
2569 if (!rc) {
2570 led->pdata->lmh_level = val;
2571 } else if (rc != -EINVAL) {
2572 pr_err("Unable to parse lmh_level, rc=%d\n", rc);
2573 return rc;
2574 }
2575
Ankit Sharmaa7153c32017-03-22 19:04:52 +05302576 led->pdata->lmh_mitigation_sel = FLASH_LED_LMH_MITIGATION_SEL_DEFAULT;
David Collins8885f792017-01-26 14:36:34 -08002577 rc = of_property_read_u32(node, "qcom,lmh-mitigation-sel", &val);
2578 if (!rc) {
2579 led->pdata->lmh_mitigation_sel = val;
2580 } else if (rc != -EINVAL) {
2581 pr_err("Unable to parse lmh_mitigation_sel, rc=%d\n", rc);
2582 return rc;
2583 }
2584
2585 if (led->pdata->lmh_mitigation_sel > FLASH_LED_MITIGATION_SEL_MAX) {
2586 pr_err("Invalid lmh_mitigation_sel specified\n");
2587 return -EINVAL;
2588 }
2589
Kiran Gunda1c1e21c2017-12-15 09:55:03 +05302590 if (pmic_subtype == PMI632_SUBTYPE)
2591 led->pdata->chgr_mitigation_sel =
2592 FLASH_DISABLE_CHARGER_MITIGATION;
2593 else
2594 led->pdata->chgr_mitigation_sel = FLASH_SW_CHARGER_MITIGATION;
2595
David Collins8885f792017-01-26 14:36:34 -08002596 rc = of_property_read_u32(node, "qcom,chgr-mitigation-sel", &val);
2597 if (!rc) {
2598 led->pdata->chgr_mitigation_sel = val;
2599 } else if (rc != -EINVAL) {
2600 pr_err("Unable to parse chgr_mitigation_sel, rc=%d\n", rc);
2601 return rc;
2602 }
2603
2604 if (led->pdata->chgr_mitigation_sel > FLASH_LED_MITIGATION_SEL_MAX) {
2605 pr_err("Invalid chgr_mitigation_sel specified\n");
2606 return -EINVAL;
2607 }
2608
Ankit Sharmaa7153c32017-03-22 19:04:52 +05302609 led->pdata->iled_thrsh_val = FLASH_LED_CHGR_MITIGATION_THRSH_DEFAULT;
David Collins8885f792017-01-26 14:36:34 -08002610 rc = of_property_read_u32(node, "qcom,iled-thrsh-ma", &val);
2611 if (!rc) {
2612 led->pdata->iled_thrsh_val = MITIGATION_THRSH_MA_TO_VAL(val);
2613 } else if (rc != -EINVAL) {
2614 pr_err("Unable to parse iled_thrsh_val, rc=%d\n", rc);
2615 return rc;
2616 }
2617
Ankit Sharmaa7153c32017-03-22 19:04:52 +05302618 if (led->pdata->iled_thrsh_val > FLASH_LED_CHGR_MITIGATION_THRSH_MAX) {
David Collins8885f792017-01-26 14:36:34 -08002619 pr_err("Invalid iled_thrsh_val specified\n");
2620 return -EINVAL;
2621 }
2622
Kiran Gunda1c1e21c2017-12-15 09:55:03 +05302623 led->pdata->bst_pwm_ovrhd_uv = FLASH_BST_PWM_OVRHD_MIN_UV;
2624 rc = of_property_read_u32(node, "qcom,bst-pwm-ovrhd-uv", &val);
2625 if (!rc) {
2626 if (val >= FLASH_BST_PWM_OVRHD_MIN_UV &&
2627 val <= FLASH_BST_PWM_OVRHD_MAX_UV)
2628 led->pdata->bst_pwm_ovrhd_uv = val;
2629 }
2630
David Collins8885f792017-01-26 14:36:34 -08002631 led->pdata->all_ramp_up_done_irq =
2632 of_irq_get_byname(node, "all-ramp-up-done-irq");
2633 if (led->pdata->all_ramp_up_done_irq < 0)
2634 pr_debug("all-ramp-up-done-irq not used\n");
2635
2636 led->pdata->all_ramp_down_done_irq =
2637 of_irq_get_byname(node, "all-ramp-down-done-irq");
2638 if (led->pdata->all_ramp_down_done_irq < 0)
2639 pr_debug("all-ramp-down-done-irq not used\n");
2640
2641 led->pdata->led_fault_irq =
2642 of_irq_get_byname(node, "led-fault-irq");
2643 if (led->pdata->led_fault_irq < 0)
2644 pr_debug("led-fault-irq not used\n");
2645
2646 return 0;
2647}
2648
2649static int qpnp_flash_led_probe(struct platform_device *pdev)
2650{
2651 struct qpnp_flash_led *led;
2652 struct device_node *node, *temp;
2653 const char *temp_string;
2654 unsigned int base;
2655 int rc, i = 0, j = 0;
2656
2657 node = pdev->dev.of_node;
2658 if (!node) {
2659 pr_err("No flash LED nodes defined\n");
2660 return -ENODEV;
2661 }
2662
2663 rc = of_property_read_u32(node, "reg", &base);
2664 if (rc < 0) {
2665 pr_err("Couldn't find reg in node %s, rc = %d\n",
2666 node->full_name, rc);
2667 return rc;
2668 }
2669
2670 led = devm_kzalloc(&pdev->dev, sizeof(struct qpnp_flash_led),
2671 GFP_KERNEL);
2672 if (!led)
2673 return -ENOMEM;
2674
2675 led->regmap = dev_get_regmap(pdev->dev.parent, NULL);
2676 if (!led->regmap) {
2677 pr_err("Couldn't get parent's regmap\n");
2678 return -EINVAL;
2679 }
2680
2681 led->base = base;
2682 led->pdev = pdev;
2683 led->pdata = devm_kzalloc(&pdev->dev,
2684 sizeof(struct flash_led_platform_data), GFP_KERNEL);
2685 if (!led->pdata)
2686 return -ENOMEM;
2687
Kiran Gundabf1e6c02018-01-17 17:50:20 +05302688 qpnp_flash_led_prepare = qpnp_flash_led_prepare_v2;
David Collins8885f792017-01-26 14:36:34 -08002689 rc = qpnp_flash_led_parse_common_dt(led, node);
2690 if (rc < 0) {
2691 pr_err("Failed to parse common flash LED device tree\n");
2692 return rc;
2693 }
2694
2695 for_each_available_child_of_node(node, temp) {
2696 rc = of_property_read_string(temp, "label", &temp_string);
2697 if (rc < 0) {
2698 pr_err("Failed to parse label, rc=%d\n", rc);
2699 return rc;
2700 }
2701
2702 if (!strcmp("switch", temp_string)) {
2703 led->num_snodes++;
2704 } else if (!strcmp("flash", temp_string) ||
2705 !strcmp("torch", temp_string)) {
2706 led->num_fnodes++;
2707 } else {
2708 pr_err("Invalid label for led node\n");
2709 return -EINVAL;
2710 }
2711 }
2712
2713 if (!led->num_fnodes) {
2714 pr_err("No LED nodes defined\n");
2715 return -ECHILD;
2716 }
2717
2718 led->fnode = devm_kcalloc(&pdev->dev, led->num_fnodes,
2719 sizeof(*led->fnode),
2720 GFP_KERNEL);
2721 if (!led->fnode)
2722 return -ENOMEM;
2723
2724 led->snode = devm_kcalloc(&pdev->dev, led->num_snodes,
2725 sizeof(*led->snode),
2726 GFP_KERNEL);
2727 if (!led->snode)
2728 return -ENOMEM;
2729
2730 temp = NULL;
2731 i = 0;
2732 j = 0;
2733 for_each_available_child_of_node(node, temp) {
2734 rc = of_property_read_string(temp, "label", &temp_string);
2735 if (rc < 0) {
2736 pr_err("Failed to parse label, rc=%d\n", rc);
2737 return rc;
2738 }
2739
2740 if (!strcmp("flash", temp_string) ||
2741 !strcmp("torch", temp_string)) {
2742 rc = qpnp_flash_led_parse_each_led_dt(led,
Subbaraman Narayanamurthy01c99612017-04-03 12:26:06 -07002743 &led->fnode[i], temp);
David Collins8885f792017-01-26 14:36:34 -08002744 if (rc < 0) {
2745 pr_err("Unable to parse flash node %d rc=%d\n",
2746 i, rc);
2747 goto error_led_register;
2748 }
Subbaraman Narayanamurthy01c99612017-04-03 12:26:06 -07002749 i++;
David Collins8885f792017-01-26 14:36:34 -08002750 }
2751
2752 if (!strcmp("switch", temp_string)) {
2753 rc = qpnp_flash_led_parse_and_register_switch(led,
Subbaraman Narayanamurthy01c99612017-04-03 12:26:06 -07002754 &led->snode[j], temp);
David Collins8885f792017-01-26 14:36:34 -08002755 if (rc < 0) {
2756 pr_err("Unable to parse and register switch node, rc=%d\n",
2757 rc);
2758 goto error_switch_register;
2759 }
Subbaraman Narayanamurthy01c99612017-04-03 12:26:06 -07002760 j++;
David Collins8885f792017-01-26 14:36:34 -08002761 }
2762 }
2763
2764 /* setup irqs */
2765 if (led->pdata->all_ramp_up_done_irq >= 0) {
2766 rc = devm_request_threaded_irq(&led->pdev->dev,
2767 led->pdata->all_ramp_up_done_irq,
2768 NULL, qpnp_flash_led_irq_handler,
2769 IRQF_ONESHOT,
2770 "qpnp_flash_led_all_ramp_up_done_irq", led);
2771 if (rc < 0) {
2772 pr_err("Unable to request all_ramp_up_done(%d) IRQ(err:%d)\n",
2773 led->pdata->all_ramp_up_done_irq, rc);
2774 goto error_switch_register;
2775 }
2776 }
2777
2778 if (led->pdata->all_ramp_down_done_irq >= 0) {
2779 rc = devm_request_threaded_irq(&led->pdev->dev,
2780 led->pdata->all_ramp_down_done_irq,
2781 NULL, qpnp_flash_led_irq_handler,
2782 IRQF_ONESHOT,
2783 "qpnp_flash_led_all_ramp_down_done_irq", led);
2784 if (rc < 0) {
2785 pr_err("Unable to request all_ramp_down_done(%d) IRQ(err:%d)\n",
2786 led->pdata->all_ramp_down_done_irq, rc);
2787 goto error_switch_register;
2788 }
2789 }
2790
2791 if (led->pdata->led_fault_irq >= 0) {
2792 rc = devm_request_threaded_irq(&led->pdev->dev,
2793 led->pdata->led_fault_irq,
2794 NULL, qpnp_flash_led_irq_handler,
2795 IRQF_ONESHOT,
2796 "qpnp_flash_led_fault_irq", led);
2797 if (rc < 0) {
2798 pr_err("Unable to request led_fault(%d) IRQ(err:%d)\n",
2799 led->pdata->led_fault_irq, rc);
2800 goto error_switch_register;
2801 }
2802 }
2803
2804 led->bms_psy = power_supply_get_by_name("bms");
2805 if (!led->bms_psy) {
2806 rc = flash_led_psy_register_notifier(led);
2807 if (rc < 0) {
2808 pr_err("Couldn't register psy notifier, rc = %d\n", rc);
2809 goto error_switch_register;
2810 }
2811 }
2812
2813 rc = qpnp_flash_led_init_settings(led);
2814 if (rc < 0) {
2815 pr_err("Failed to initialize flash LED, rc=%d\n", rc);
2816 goto unreg_notifier;
2817 }
2818
2819 for (i = 0; i < led->num_snodes; i++) {
2820 for (j = 0; j < ARRAY_SIZE(qpnp_flash_led_attrs); j++) {
2821 rc = sysfs_create_file(&led->snode[i].cdev.dev->kobj,
2822 &qpnp_flash_led_attrs[j].attr);
2823 if (rc < 0) {
2824 pr_err("sysfs creation failed, rc=%d\n", rc);
2825 goto sysfs_fail;
2826 }
2827 }
2828 }
2829
2830 spin_lock_init(&led->lock);
2831
2832 dev_set_drvdata(&pdev->dev, led);
2833
2834 return 0;
2835
2836sysfs_fail:
2837 for (--j; j >= 0; j--)
2838 sysfs_remove_file(&led->snode[i].cdev.dev->kobj,
2839 &qpnp_flash_led_attrs[j].attr);
2840
2841 for (--i; i >= 0; i--) {
2842 for (j = 0; j < ARRAY_SIZE(qpnp_flash_led_attrs); j++)
2843 sysfs_remove_file(&led->snode[i].cdev.dev->kobj,
2844 &qpnp_flash_led_attrs[j].attr);
2845 }
2846
2847 i = led->num_snodes;
2848unreg_notifier:
2849 power_supply_unreg_notifier(&led->nb);
2850error_switch_register:
2851 while (i > 0)
2852 led_classdev_unregister(&led->snode[--i].cdev);
2853 i = led->num_fnodes;
2854error_led_register:
2855 while (i > 0)
2856 led_classdev_unregister(&led->fnode[--i].cdev);
2857
2858 return rc;
2859}
2860
2861static int qpnp_flash_led_remove(struct platform_device *pdev)
2862{
2863 struct qpnp_flash_led *led = dev_get_drvdata(&pdev->dev);
2864 int i, j;
2865
2866 for (i = 0; i < led->num_snodes; i++) {
2867 for (j = 0; j < ARRAY_SIZE(qpnp_flash_led_attrs); j++)
2868 sysfs_remove_file(&led->snode[i].cdev.dev->kobj,
2869 &qpnp_flash_led_attrs[j].attr);
2870
2871 if (led->snode[i].regulator_on)
2872 qpnp_flash_led_regulator_enable(led,
2873 &led->snode[i], false);
2874 }
2875
2876 while (i > 0)
2877 led_classdev_unregister(&led->snode[--i].cdev);
2878
2879 i = led->num_fnodes;
2880 while (i > 0)
2881 led_classdev_unregister(&led->fnode[--i].cdev);
2882
2883 power_supply_unreg_notifier(&led->nb);
2884 return 0;
2885}
2886
2887const struct of_device_id qpnp_flash_led_match_table[] = {
2888 { .compatible = "qcom,qpnp-flash-led-v2",},
2889 { },
2890};
2891
2892static struct platform_driver qpnp_flash_led_driver = {
2893 .driver = {
2894 .name = "qcom,qpnp-flash-led-v2",
2895 .of_match_table = qpnp_flash_led_match_table,
2896 },
2897 .probe = qpnp_flash_led_probe,
2898 .remove = qpnp_flash_led_remove,
2899};
2900
2901static int __init qpnp_flash_led_init(void)
2902{
2903 return platform_driver_register(&qpnp_flash_led_driver);
2904}
2905late_initcall(qpnp_flash_led_init);
2906
2907static void __exit qpnp_flash_led_exit(void)
2908{
2909 platform_driver_unregister(&qpnp_flash_led_driver);
2910}
2911module_exit(qpnp_flash_led_exit);
2912
2913MODULE_DESCRIPTION("QPNP Flash LED driver v2");
2914MODULE_LICENSE("GPL v2");
2915MODULE_ALIAS("leds:leds-qpnp-flash-v2");