blob: 759d8531114c69a9bb27d03a30d99c3861ca8376 [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 Gunda1c1e21c2017-12-15 09:55:03 +0530126
127#define FLASH_LED_REG_LPG_INPUT_CTRL(base) (base + 0x72)
Subbaraman Narayanamurthy3f684b22017-03-21 20:49:54 -0700128#define LPG_INPUT_SEL_BIT BIT(0)
David Collins8885f792017-01-26 14:36:34 -0800129
Kiran Gunda1c1e21c2017-12-15 09:55:03 +0530130#define FLASH_LED_REG_CURRENT_DERATE_EN(base) (base + 0x76)
131#define FLASH_LED_CURRENT_DERATE_EN_MASK GENMASK(2, 0)
132
David Collins8885f792017-01-26 14:36:34 -0800133#define VPH_DROOP_DEBOUNCE_US_TO_VAL(val_us) (val_us / 8)
134#define VPH_DROOP_HYST_MV_TO_VAL(val_mv) (val_mv / 25)
David Collins8885f792017-01-26 14:36:34 -0800135#define VPH_DROOP_THRESH_VAL_TO_UV(val) ((val + 25) * 100000)
136#define MITIGATION_THRSH_MA_TO_VAL(val_ma) (val_ma / 100)
David Collins8885f792017-01-26 14:36:34 -0800137#define THERMAL_HYST_TEMP_TO_VAL(val, divisor) (val / divisor)
138
Kiran Gunda1c1e21c2017-12-15 09:55:03 +0530139#define FLASH_LED_WARMUP_DELAY_DEFAULT 2
140#define FLASH_LED_ISC_DELAY_DEFAULT 3
141#define FLASH_LED_VPH_DROOP_DEBOUNCE_DEFAULT 2
142#define FLASH_LED_VPH_DROOP_HYST_DEFAULT 2
143#define FLASH_LED_VPH_DROOP_THRESH_DEFAULT 5
144#define BHARGER_FLASH_LED_VPH_DROOP_THRESH_DEFAULT 7
145#define FLASH_LED_DEBOUNCE_MAX 3
146#define FLASH_LED_HYSTERESIS_MAX 3
147#define FLASH_LED_VPH_DROOP_THRESH_MAX 7
148#define THERMAL_DERATE_SLOW_MAX 314592
149#define THERMAL_DERATE_FAST_MAX 512
150#define THERMAL_DEBOUNCE_TIME_MAX 64
151#define THERMAL_DERATE_HYSTERESIS_MAX 3
152#define FLASH_LED_THERMAL_THRSH_MIN 3
153#define FLASH_LED_THERMAL_THRSH_MAX 7
154#define FLASH_LED_THERMAL_OTST_LEVELS 3
155#define FLASH_LED_VLED_MAX_DEFAULT_UV 3500000
156#define FLASH_LED_IBATT_OCP_THRESH_DEFAULT_UA 4500000
157#define FLASH_LED_RPARA_DEFAULT_UOHM 0
158#define FLASH_LED_LMH_LEVEL_DEFAULT 0
159#define FLASH_LED_LMH_MITIGATION_ENABLE 1
160#define FLASH_LED_LMH_MITIGATION_DISABLE 0
161#define FLASH_LED_CHGR_MITIGATION_DISABLE 0
162#define FLASH_LED_LMH_MITIGATION_SEL_DEFAULT 2
163#define FLASH_LED_MITIGATION_SEL_MAX 2
164#define FLASH_LED_CHGR_MITIGATION_SEL_SHIFT 4
165#define FLASH_LED_CHGR_MITIGATION_THRSH_DEFAULT 0xA
166#define FLASH_LED_CHGR_MITIGATION_THRSH_MAX 0x1F
167#define FLASH_LED_LMH_OCV_THRESH_DEFAULT_UV 3700000
168#define FLASH_LED_LMH_RBATT_THRESH_DEFAULT_UOHM 400000
169#define FLASH_LED_IRES_BASE 3
170#define FLASH_LED_IRES_DIVISOR 2500
171#define FLASH_LED_IRES_MIN_UA 5000
172#define FLASH_LED_IRES_DEFAULT_UA 12500
173#define FLASH_LED_IRES_DEFAULT_VAL 0x00
174#define FLASH_LED_HDRM_VOL_DEFAULT_MV 0x80
175#define FLASH_LED_HDRM_VOL_HI_LO_WIN_DEFAULT_MV 0x04
176#define FLASH_LED_HDRM_VOL_BASE_MV 125
177#define FLASH_LED_HDRM_VOL_STEP_MV 25
178#define FLASH_LED_STROBE_CFG_DEFAULT 0x00
179#define FLASH_LED_HW_STROBE_OPTION_1 0x00
180#define FLASH_LED_HW_STROBE_OPTION_2 0x01
181#define FLASH_LED_HW_STROBE_OPTION_3 0x02
182#define FLASH_LED_DISABLE 0x00
183#define FLASH_LED_SAFETY_TMR_DISABLED 0x13
184#define FLASH_LED_MAX_TOTAL_CURRENT_MA 3750
185#define FLASH_LED_IRES5P0_MAX_CURR_MA 640
186#define FLASH_LED_IRES7P5_MAX_CURR_MA 960
187#define FLASH_LED_IRES10P0_MAX_CURR_MA 1280
188#define FLASH_LED_IRES12P5_MAX_CURR_MA 1600
189#define MAX_IRES_LEVELS 4
190#define FLASH_BST_PWM_OVRHD_MIN_UV 300000
191#define FLASH_BST_PWM_OVRHD_MAX_UV 600000
David Collins8885f792017-01-26 14:36:34 -0800192
193/* notifier call chain for flash-led irqs */
194static ATOMIC_NOTIFIER_HEAD(irq_notifier_list);
195
Ankit Sharmaa7153c32017-03-22 19:04:52 +0530196enum flash_charger_mitigation {
197 FLASH_DISABLE_CHARGER_MITIGATION,
198 FLASH_HW_CHARGER_MITIGATION_BY_ILED_THRSHLD,
199 FLASH_SW_CHARGER_MITIGATION,
200};
201
David Collins8885f792017-01-26 14:36:34 -0800202enum flash_led_type {
Subbaraman Narayanamurthyd737fd52018-01-17 19:58:52 -0800203 FLASH_LED_TYPE_UNKNOWN,
David Collins8885f792017-01-26 14:36:34 -0800204 FLASH_LED_TYPE_FLASH,
205 FLASH_LED_TYPE_TORCH,
206};
207
208enum {
209 LED1 = 0,
210 LED2,
211 LED3,
212};
213
Subbaraman Narayanamurthy3f684b22017-03-21 20:49:54 -0700214enum strobe_type {
215 SW_STROBE = 0,
216 HW_STROBE,
217 LPG_STROBE,
218};
219
David Collins8885f792017-01-26 14:36:34 -0800220/*
221 * Configurations for each individual LED
222 */
223struct flash_node_data {
224 struct platform_device *pdev;
225 struct led_classdev cdev;
Subbaraman Narayanamurthy58377f02017-03-21 20:38:43 -0700226 struct pinctrl *strobe_pinctrl;
David Collins8885f792017-01-26 14:36:34 -0800227 struct pinctrl_state *hw_strobe_state_active;
228 struct pinctrl_state *hw_strobe_state_suspend;
229 int hw_strobe_gpio;
230 int ires_ua;
Kiran Gunda5cadca72017-07-26 14:37:52 +0530231 int default_ires_ua;
David Collins8885f792017-01-26 14:36:34 -0800232 int max_current;
233 int current_ma;
Ankit Sharmaa7153c32017-03-22 19:04:52 +0530234 int prev_current_ma;
David Collins8885f792017-01-26 14:36:34 -0800235 u8 duration;
236 u8 id;
Kiran Gunda5cadca72017-07-26 14:37:52 +0530237 u8 ires_idx;
238 u8 default_ires_idx;
David Collins8885f792017-01-26 14:36:34 -0800239 u8 hdrm_val;
240 u8 current_reg_val;
Subbaraman Narayanamurthy3f684b22017-03-21 20:49:54 -0700241 u8 strobe_ctrl;
242 u8 strobe_sel;
Subbaraman Narayanamurthyd737fd52018-01-17 19:58:52 -0800243 enum flash_led_type type;
David Collins8885f792017-01-26 14:36:34 -0800244 bool led_on;
245};
246
247
248struct flash_switch_data {
249 struct platform_device *pdev;
250 struct regulator *vreg;
Subbaraman Narayanamurthy58377f02017-03-21 20:38:43 -0700251 struct pinctrl *led_en_pinctrl;
252 struct pinctrl_state *gpio_state_active;
253 struct pinctrl_state *gpio_state_suspend;
David Collins8885f792017-01-26 14:36:34 -0800254 struct led_classdev cdev;
255 int led_mask;
256 bool regulator_on;
257 bool enabled;
Subbaraman Narayanamurthyd737fd52018-01-17 19:58:52 -0800258 bool symmetry_en;
David Collins8885f792017-01-26 14:36:34 -0800259};
260
261/*
262 * Flash LED configuration read from device tree
263 */
264struct flash_led_platform_data {
265 struct pmic_revid_data *pmic_rev_id;
266 int *thermal_derate_current;
267 int all_ramp_up_done_irq;
268 int all_ramp_down_done_irq;
269 int led_fault_irq;
270 int ibatt_ocp_threshold_ua;
271 int vled_max_uv;
272 int rpara_uohm;
273 int lmh_rbatt_threshold_uohm;
274 int lmh_ocv_threshold_uv;
275 int thermal_derate_slow;
276 int thermal_derate_fast;
277 int thermal_hysteresis;
278 int thermal_debounce;
279 int thermal_thrsh1;
280 int thermal_thrsh2;
281 int thermal_thrsh3;
Subbaraman Narayanamurthy3f684b22017-03-21 20:49:54 -0700282 int hw_strobe_option;
David Collins8885f792017-01-26 14:36:34 -0800283 u32 led1n2_iclamp_low_ma;
284 u32 led1n2_iclamp_mid_ma;
285 u32 led3_iclamp_low_ma;
286 u32 led3_iclamp_mid_ma;
Kiran Gunda1c1e21c2017-12-15 09:55:03 +0530287 u32 bst_pwm_ovrhd_uv;
David Collins8885f792017-01-26 14:36:34 -0800288 u8 isc_delay;
289 u8 warmup_delay;
290 u8 current_derate_en_cfg;
291 u8 vph_droop_threshold;
292 u8 vph_droop_hysteresis;
293 u8 vph_droop_debounce;
294 u8 lmh_mitigation_sel;
295 u8 chgr_mitigation_sel;
296 u8 lmh_level;
297 u8 iled_thrsh_val;
David Collins8885f792017-01-26 14:36:34 -0800298 bool hdrm_auto_mode_en;
299 bool thermal_derate_en;
300 bool otst_ramp_bkup_en;
301};
302
303/*
304 * Flash LED data structure containing flash LED attributes
305 */
306struct qpnp_flash_led {
307 struct flash_led_platform_data *pdata;
308 struct platform_device *pdev;
309 struct regmap *regmap;
310 struct flash_node_data *fnode;
311 struct flash_switch_data *snode;
312 struct power_supply *bms_psy;
Kiran Gunda1c1e21c2017-12-15 09:55:03 +0530313 struct power_supply *main_psy;
314 struct power_supply *usb_psy;
David Collins8885f792017-01-26 14:36:34 -0800315 struct notifier_block nb;
316 spinlock_t lock;
317 int num_fnodes;
318 int num_snodes;
319 int enable;
Ankit Sharmaa7153c32017-03-22 19:04:52 +0530320 int total_current_ma;
David Collins8885f792017-01-26 14:36:34 -0800321 u16 base;
322 bool trigger_lmh;
323 bool trigger_chgr;
324};
325
326static int thermal_derate_slow_table[] = {
327 128, 256, 512, 1024, 2048, 4096, 8192, 314592,
328};
329
330static int thermal_derate_fast_table[] = {
331 32, 64, 96, 128, 256, 384, 512,
332};
333
334static int otst1_threshold_table[] = {
335 85, 79, 73, 67, 109, 103, 97, 91,
336};
337
338static int otst2_threshold_table[] = {
339 110, 104, 98, 92, 134, 128, 122, 116,
340};
341
342static int otst3_threshold_table[] = {
343 125, 119, 113, 107, 149, 143, 137, 131,
344};
345
Kiran Gunda5cadca72017-07-26 14:37:52 +0530346static int max_ires_curr_ma_table[MAX_IRES_LEVELS] = {
347 FLASH_LED_IRES12P5_MAX_CURR_MA, FLASH_LED_IRES10P0_MAX_CURR_MA,
348 FLASH_LED_IRES7P5_MAX_CURR_MA, FLASH_LED_IRES5P0_MAX_CURR_MA
349};
350
Subbaraman Narayanamurthyaf8dcb42018-01-17 20:23:47 -0800351static inline int get_current_reg_code(int target_curr_ma, int ires_ua)
352{
353 if (!ires_ua || !target_curr_ma || (target_curr_ma < (ires_ua / 1000)))
354 return 0;
355
Subbaraman Narayanamurthyf8eb9d22018-04-16 14:00:12 -0700356 return DIV_ROUND_CLOSEST(target_curr_ma * 1000, ires_ua) - 1;
Subbaraman Narayanamurthyaf8dcb42018-01-17 20:23:47 -0800357}
358
David Collins8885f792017-01-26 14:36:34 -0800359static int qpnp_flash_led_read(struct qpnp_flash_led *led, u16 addr, u8 *data)
360{
361 int rc;
362 uint val;
363
364 rc = regmap_read(led->regmap, addr, &val);
365 if (rc < 0) {
366 pr_err("Unable to read from 0x%04X rc = %d\n", addr, rc);
367 return rc;
368 }
369
370 pr_debug("Read 0x%02X from addr 0x%04X\n", val, addr);
371 *data = (u8)val;
372 return 0;
373}
374
375static int qpnp_flash_led_write(struct qpnp_flash_led *led, u16 addr, u8 data)
376{
377 int rc;
378
379 rc = regmap_write(led->regmap, addr, data);
380 if (rc < 0) {
381 pr_err("Unable to write to 0x%04X rc = %d\n", addr, rc);
382 return rc;
383 }
384
385 pr_debug("Wrote 0x%02X to addr 0x%04X\n", data, addr);
386 return 0;
387}
388
389static int
390qpnp_flash_led_masked_read(struct qpnp_flash_led *led, u16 addr, u8 mask,
391 u8 *val)
392{
393 int rc;
394
395 rc = qpnp_flash_led_read(led, addr, val);
396 if (rc < 0)
397 return rc;
398
399 *val &= mask;
400 return rc;
401}
402
403static int
404qpnp_flash_led_masked_write(struct qpnp_flash_led *led, u16 addr, u8 mask,
405 u8 val)
406{
407 int rc;
408
409 rc = regmap_update_bits(led->regmap, addr, mask, val);
410 if (rc < 0)
411 pr_err("Unable to update bits from 0x%04X, rc = %d\n", addr,
412 rc);
413 else
414 pr_debug("Wrote 0x%02X to addr 0x%04X\n", val, addr);
415
416 return rc;
417}
418
419static enum
420led_brightness qpnp_flash_led_brightness_get(struct led_classdev *led_cdev)
421{
422 return led_cdev->brightness;
423}
424
425static int qpnp_flash_led_init_settings(struct qpnp_flash_led *led)
426{
427 int rc, i, addr_offset;
428 u8 val = 0, mask;
429
430 for (i = 0; i < led->num_fnodes; i++) {
431 addr_offset = led->fnode[i].id;
432 rc = qpnp_flash_led_write(led,
433 FLASH_LED_REG_HDRM_PRGM(led->base + addr_offset),
434 led->fnode[i].hdrm_val);
435 if (rc < 0)
436 return rc;
437
438 val |= 0x1 << led->fnode[i].id;
439 }
440
441 rc = qpnp_flash_led_write(led,
442 FLASH_LED_REG_HDRM_AUTO_MODE_CTRL(led->base),
443 val);
444 if (rc < 0)
445 return rc;
446
447 rc = qpnp_flash_led_masked_write(led,
448 FLASH_LED_REG_ISC_DELAY(led->base),
449 FLASH_LED_ISC_WARMUP_DELAY_MASK,
450 led->pdata->isc_delay);
451 if (rc < 0)
452 return rc;
453
454 rc = qpnp_flash_led_masked_write(led,
455 FLASH_LED_REG_WARMUP_DELAY(led->base),
456 FLASH_LED_ISC_WARMUP_DELAY_MASK,
457 led->pdata->warmup_delay);
458 if (rc < 0)
459 return rc;
460
461 rc = qpnp_flash_led_masked_write(led,
462 FLASH_LED_REG_CURRENT_DERATE_EN(led->base),
463 FLASH_LED_CURRENT_DERATE_EN_MASK,
464 led->pdata->current_derate_en_cfg);
465 if (rc < 0)
466 return rc;
467
468 val = (led->pdata->otst_ramp_bkup_en << THERMAL_OTST1_RAMP_CTRL_SHIFT);
469 mask = THERMAL_OTST1_RAMP_CTRL_MASK;
470 if (led->pdata->thermal_derate_slow >= 0) {
471 val |= (led->pdata->thermal_derate_slow <<
472 THERMAL_DERATE_SLOW_SHIFT);
473 mask |= THERMAL_DERATE_SLOW_MASK;
474 }
475
476 if (led->pdata->thermal_derate_fast >= 0) {
477 val |= led->pdata->thermal_derate_fast;
478 mask |= THERMAL_DERATE_FAST_MASK;
479 }
480
481 rc = qpnp_flash_led_masked_write(led,
482 FLASH_LED_REG_THERMAL_RMP_DN_RATE(led->base),
483 mask, val);
484 if (rc < 0)
485 return rc;
486
487 if (led->pdata->thermal_debounce >= 0) {
488 rc = qpnp_flash_led_masked_write(led,
489 FLASH_LED_REG_THERMAL_DEBOUNCE(led->base),
490 FLASH_LED_THERMAL_DEBOUNCE_MASK,
491 led->pdata->thermal_debounce);
492 if (rc < 0)
493 return rc;
494 }
495
496 if (led->pdata->thermal_hysteresis >= 0) {
497 rc = qpnp_flash_led_masked_write(led,
498 FLASH_LED_REG_THERMAL_HYSTERESIS(led->base),
499 FLASH_LED_THERMAL_HYSTERESIS_MASK,
500 led->pdata->thermal_hysteresis);
501 if (rc < 0)
502 return rc;
503 }
504
505 if (led->pdata->thermal_thrsh1 >= 0) {
506 rc = qpnp_flash_led_masked_write(led,
507 FLASH_LED_REG_THERMAL_THRSH1(led->base),
508 FLASH_LED_THERMAL_THRSH_MASK,
509 led->pdata->thermal_thrsh1);
510 if (rc < 0)
511 return rc;
512 }
513
514 if (led->pdata->thermal_thrsh2 >= 0) {
515 rc = qpnp_flash_led_masked_write(led,
516 FLASH_LED_REG_THERMAL_THRSH2(led->base),
517 FLASH_LED_THERMAL_THRSH_MASK,
518 led->pdata->thermal_thrsh2);
519 if (rc < 0)
520 return rc;
521 }
522
523 if (led->pdata->thermal_thrsh3 >= 0) {
524 rc = qpnp_flash_led_masked_write(led,
525 FLASH_LED_REG_THERMAL_THRSH3(led->base),
526 FLASH_LED_THERMAL_THRSH_MASK,
527 led->pdata->thermal_thrsh3);
528 if (rc < 0)
529 return rc;
530 }
531
532 rc = qpnp_flash_led_masked_write(led,
533 FLASH_LED_REG_VPH_DROOP_DEBOUNCE(led->base),
534 FLASH_LED_VPH_DROOP_DEBOUNCE_MASK,
535 led->pdata->vph_droop_debounce);
536 if (rc < 0)
537 return rc;
538
539 rc = qpnp_flash_led_masked_write(led,
540 FLASH_LED_REG_VPH_DROOP_THRESHOLD(led->base),
541 FLASH_LED_VPH_DROOP_THRESHOLD_MASK,
542 led->pdata->vph_droop_threshold);
543 if (rc < 0)
544 return rc;
545
546 rc = qpnp_flash_led_masked_write(led,
547 FLASH_LED_REG_VPH_DROOP_THRESHOLD(led->base),
548 FLASH_LED_VPH_DROOP_HYSTERESIS_MASK,
549 led->pdata->vph_droop_hysteresis);
550 if (rc < 0)
551 return rc;
552
553 rc = qpnp_flash_led_masked_write(led,
554 FLASH_LED_REG_MITIGATION_SEL(led->base),
555 FLASH_LED_LMH_MITIGATION_SEL_MASK,
556 led->pdata->lmh_mitigation_sel);
557 if (rc < 0)
558 return rc;
559
Ankit Sharmaa7153c32017-03-22 19:04:52 +0530560 val = led->pdata->chgr_mitigation_sel
561 << FLASH_LED_CHGR_MITIGATION_SEL_SHIFT;
David Collins8885f792017-01-26 14:36:34 -0800562 rc = qpnp_flash_led_masked_write(led,
563 FLASH_LED_REG_MITIGATION_SEL(led->base),
564 FLASH_LED_CHGR_MITIGATION_SEL_MASK,
Ankit Sharmaa7153c32017-03-22 19:04:52 +0530565 val);
David Collins8885f792017-01-26 14:36:34 -0800566 if (rc < 0)
567 return rc;
568
569 rc = qpnp_flash_led_masked_write(led,
570 FLASH_LED_REG_LMH_LEVEL(led->base),
571 FLASH_LED_LMH_LEVEL_MASK,
572 led->pdata->lmh_level);
573 if (rc < 0)
574 return rc;
575
576 rc = qpnp_flash_led_masked_write(led,
577 FLASH_LED_REG_ILED_GRT_THRSH(led->base),
578 FLASH_LED_ILED_GRT_THRSH_MASK,
579 led->pdata->iled_thrsh_val);
580 if (rc < 0)
581 return rc;
582
583 if (led->pdata->led1n2_iclamp_low_ma) {
Subbaraman Narayanamurthyaf8dcb42018-01-17 20:23:47 -0800584 val = get_current_reg_code(led->pdata->led1n2_iclamp_low_ma,
Subbaraman Narayanamurthy01c99612017-04-03 12:26:06 -0700585 led->fnode[LED1].ires_ua);
David Collins8885f792017-01-26 14:36:34 -0800586 rc = qpnp_flash_led_masked_write(led,
587 FLASH_LED_REG_LED1N2_ICLAMP_LOW(led->base),
588 FLASH_LED_CURRENT_MASK, val);
589 if (rc < 0)
590 return rc;
591 }
592
593 if (led->pdata->led1n2_iclamp_mid_ma) {
Subbaraman Narayanamurthyaf8dcb42018-01-17 20:23:47 -0800594 val = get_current_reg_code(led->pdata->led1n2_iclamp_mid_ma,
Subbaraman Narayanamurthy01c99612017-04-03 12:26:06 -0700595 led->fnode[LED1].ires_ua);
David Collins8885f792017-01-26 14:36:34 -0800596 rc = qpnp_flash_led_masked_write(led,
597 FLASH_LED_REG_LED1N2_ICLAMP_MID(led->base),
598 FLASH_LED_CURRENT_MASK, val);
599 if (rc < 0)
600 return rc;
601 }
602
603 if (led->pdata->led3_iclamp_low_ma) {
Subbaraman Narayanamurthyaf8dcb42018-01-17 20:23:47 -0800604 val = get_current_reg_code(led->pdata->led3_iclamp_low_ma,
Subbaraman Narayanamurthy01c99612017-04-03 12:26:06 -0700605 led->fnode[LED3].ires_ua);
David Collins8885f792017-01-26 14:36:34 -0800606 rc = qpnp_flash_led_masked_write(led,
607 FLASH_LED_REG_LED3_ICLAMP_LOW(led->base),
608 FLASH_LED_CURRENT_MASK, val);
609 if (rc < 0)
610 return rc;
611 }
612
613 if (led->pdata->led3_iclamp_mid_ma) {
Subbaraman Narayanamurthyaf8dcb42018-01-17 20:23:47 -0800614 val = get_current_reg_code(led->pdata->led3_iclamp_mid_ma,
Subbaraman Narayanamurthy01c99612017-04-03 12:26:06 -0700615 led->fnode[LED3].ires_ua);
David Collins8885f792017-01-26 14:36:34 -0800616 rc = qpnp_flash_led_masked_write(led,
617 FLASH_LED_REG_LED3_ICLAMP_MID(led->base),
618 FLASH_LED_CURRENT_MASK, val);
619 if (rc < 0)
620 return rc;
621 }
622
Subbaraman Narayanamurthy3f684b22017-03-21 20:49:54 -0700623 if (led->pdata->hw_strobe_option > 0) {
624 rc = qpnp_flash_led_masked_write(led,
625 FLASH_LED_REG_STROBE_CFG(led->base),
626 FLASH_LED_STROBE_MASK,
627 led->pdata->hw_strobe_option);
628 if (rc < 0)
629 return rc;
630 }
631
632 if (led->fnode[LED3].strobe_sel == LPG_STROBE) {
633 rc = qpnp_flash_led_masked_write(led,
634 FLASH_LED_REG_MULTI_STROBE_CTRL(led->base),
635 LED3_FLASH_ONCE_ONLY_BIT, 0);
636 if (rc < 0)
637 return rc;
638
639 rc = qpnp_flash_led_masked_write(led,
640 FLASH_LED_REG_LPG_INPUT_CTRL(led->base),
641 LPG_INPUT_SEL_BIT, LPG_INPUT_SEL_BIT);
642 if (rc < 0)
643 return rc;
644 }
David Collins8885f792017-01-26 14:36:34 -0800645 return 0;
646}
647
648static int qpnp_flash_led_hw_strobe_enable(struct flash_node_data *fnode,
649 int hw_strobe_option, bool on)
650{
651 int rc = 0;
652
653 /*
654 * If the LED controlled by this fnode is not GPIO controlled
655 * for the given strobe_option, return.
656 */
657 if (hw_strobe_option == FLASH_LED_HW_STROBE_OPTION_1)
658 return 0;
659 else if (hw_strobe_option == FLASH_LED_HW_STROBE_OPTION_2
660 && fnode->id != LED3)
661 return 0;
662 else if (hw_strobe_option == FLASH_LED_HW_STROBE_OPTION_3
663 && fnode->id == LED1)
664 return 0;
665
666 if (gpio_is_valid(fnode->hw_strobe_gpio)) {
667 gpio_set_value(fnode->hw_strobe_gpio, on ? 1 : 0);
Subbaraman Narayanamurthy58377f02017-03-21 20:38:43 -0700668 } else if (fnode->strobe_pinctrl && fnode->hw_strobe_state_active &&
David Collins8885f792017-01-26 14:36:34 -0800669 fnode->hw_strobe_state_suspend) {
Subbaraman Narayanamurthy58377f02017-03-21 20:38:43 -0700670 rc = pinctrl_select_state(fnode->strobe_pinctrl,
David Collins8885f792017-01-26 14:36:34 -0800671 on ? fnode->hw_strobe_state_active :
672 fnode->hw_strobe_state_suspend);
673 if (rc < 0) {
674 pr_err("failed to change hw strobe pin state\n");
675 return rc;
676 }
677 }
678
679 return rc;
680}
681
682static int qpnp_flash_led_regulator_enable(struct qpnp_flash_led *led,
683 struct flash_switch_data *snode, bool on)
684{
685 int rc = 0;
686
687 if (!snode || !snode->vreg)
688 return 0;
689
690 if (snode->regulator_on == on)
691 return 0;
692
693 if (on)
694 rc = regulator_enable(snode->vreg);
695 else
696 rc = regulator_disable(snode->vreg);
697
698 if (rc < 0) {
699 pr_err("regulator_%s failed, rc=%d\n",
700 on ? "enable" : "disable", rc);
701 return rc;
702 }
703
704 snode->regulator_on = on ? true : false;
705 return 0;
706}
707
708static int get_property_from_fg(struct qpnp_flash_led *led,
709 enum power_supply_property prop, int *val)
710{
711 int rc;
712 union power_supply_propval pval = {0, };
713
714 if (!led->bms_psy) {
715 pr_err("no bms psy found\n");
716 return -EINVAL;
717 }
718
719 rc = power_supply_get_property(led->bms_psy, prop, &pval);
720 if (rc) {
721 pr_err("bms psy doesn't support reading prop %d rc = %d\n",
722 prop, rc);
723 return rc;
724 }
725
726 *val = pval.intval;
727 return rc;
728}
729
Kiran Gunda1c1e21c2017-12-15 09:55:03 +0530730#define VOLTAGE_HDRM_DEFAULT_MV 350
731#define BHARGER_VOLTAGE_HDRM_DEFAULT_MV 400
732#define BHARGER_HEADROOM_OFFSET_MV 50
David Collins8885f792017-01-26 14:36:34 -0800733static int qpnp_flash_led_get_voltage_headroom(struct qpnp_flash_led *led)
734{
735 int i, voltage_hdrm_mv = 0, voltage_hdrm_max = 0;
Kiran Gunda1c1e21c2017-12-15 09:55:03 +0530736 u8 pmic_subtype = led->pdata->pmic_rev_id->pmic_subtype;
David Collins8885f792017-01-26 14:36:34 -0800737
738 for (i = 0; i < led->num_fnodes; i++) {
739 if (led->fnode[i].led_on) {
740 if (led->fnode[i].id < 2) {
741 if (led->fnode[i].current_ma < 750)
742 voltage_hdrm_mv = 125;
743 else if (led->fnode[i].current_ma < 1000)
744 voltage_hdrm_mv = 175;
745 else if (led->fnode[i].current_ma < 1250)
746 voltage_hdrm_mv = 250;
747 else
748 voltage_hdrm_mv = 350;
749 } else {
750 if (led->fnode[i].current_ma < 375)
751 voltage_hdrm_mv = 125;
752 else if (led->fnode[i].current_ma < 500)
753 voltage_hdrm_mv = 175;
754 else if (led->fnode[i].current_ma < 625)
755 voltage_hdrm_mv = 250;
756 else
757 voltage_hdrm_mv = 350;
758 }
759
Kiran Gunda1c1e21c2017-12-15 09:55:03 +0530760 if (pmic_subtype == PMI632_SUBTYPE)
761 voltage_hdrm_mv += BHARGER_HEADROOM_OFFSET_MV;
762
David Collins8885f792017-01-26 14:36:34 -0800763 voltage_hdrm_max = max(voltage_hdrm_max,
764 voltage_hdrm_mv);
765 }
766 }
767
768 if (!voltage_hdrm_max)
Kiran Gunda1c1e21c2017-12-15 09:55:03 +0530769 return (pmic_subtype == PMI632_SUBTYPE) ?
770 BHARGER_VOLTAGE_HDRM_DEFAULT_MV :
771 VOLTAGE_HDRM_DEFAULT_MV;
David Collins8885f792017-01-26 14:36:34 -0800772
773 return voltage_hdrm_max;
774}
775
776#define UCONV 1000000LL
777#define MCONV 1000LL
778#define FLASH_VDIP_MARGIN 50000
779#define BOB_EFFICIENCY 900LL
780#define VIN_FLASH_MIN_UV 3300000LL
Subbaraman Narayanamurthyd94945e2017-11-28 19:54:09 -0800781static int qpnp_flash_led_calc_max_current(struct qpnp_flash_led *led,
Kiran Gunda1c1e21c2017-12-15 09:55:03 +0530782 int *max_current)
David Collins8885f792017-01-26 14:36:34 -0800783{
Kyle Yan74fdd732017-03-22 13:37:08 -0700784 int ocv_uv, ibat_now, voltage_hdrm_mv, rc;
785 int rbatt_uohm = 0;
David Collins8885f792017-01-26 14:36:34 -0800786 int64_t ibat_flash_ua, avail_flash_ua, avail_flash_power_fw;
787 int64_t ibat_safe_ua, vin_flash_uv, vph_flash_uv, vph_flash_vdip;
788
789 /* RESISTANCE = esr_uohm + rslow_uohm */
790 rc = get_property_from_fg(led, POWER_SUPPLY_PROP_RESISTANCE,
791 &rbatt_uohm);
792 if (rc < 0) {
793 pr_err("bms psy does not support resistance, rc=%d\n", rc);
794 return rc;
795 }
796
797 /* If no battery is connected, return max possible flash current */
Subbaraman Narayanamurthyd94945e2017-11-28 19:54:09 -0800798 if (!rbatt_uohm) {
799 *max_current = FLASH_LED_MAX_TOTAL_CURRENT_MA;
800 return 0;
801 }
David Collins8885f792017-01-26 14:36:34 -0800802
803 rc = get_property_from_fg(led, POWER_SUPPLY_PROP_VOLTAGE_OCV, &ocv_uv);
804 if (rc < 0) {
805 pr_err("bms psy does not support OCV, rc=%d\n", rc);
806 return rc;
807 }
808
809 rc = get_property_from_fg(led, POWER_SUPPLY_PROP_CURRENT_NOW,
810 &ibat_now);
811 if (rc < 0) {
812 pr_err("bms psy does not support current, rc=%d\n", rc);
813 return rc;
814 }
815
816 rbatt_uohm += led->pdata->rpara_uohm;
817 voltage_hdrm_mv = qpnp_flash_led_get_voltage_headroom(led);
818 vph_flash_vdip =
819 VPH_DROOP_THRESH_VAL_TO_UV(led->pdata->vph_droop_threshold)
820 + FLASH_VDIP_MARGIN;
821
822 /* Check if LMH_MITIGATION needs to be triggered */
823 if (!led->trigger_lmh && (ocv_uv < led->pdata->lmh_ocv_threshold_uv ||
824 rbatt_uohm > led->pdata->lmh_rbatt_threshold_uohm)) {
825 led->trigger_lmh = true;
826 rc = qpnp_flash_led_masked_write(led,
827 FLASH_LED_REG_MITIGATION_SW(led->base),
828 FLASH_LED_LMH_MITIGATION_EN_MASK,
829 FLASH_LED_LMH_MITIGATION_ENABLE);
830 if (rc < 0) {
831 pr_err("trigger lmh mitigation failed, rc=%d\n", rc);
832 return rc;
833 }
834
835 /* Wait for LMH mitigation to take effect */
836 udelay(100);
837
Subbaraman Narayanamurthyd94945e2017-11-28 19:54:09 -0800838 return qpnp_flash_led_calc_max_current(led, max_current);
David Collins8885f792017-01-26 14:36:34 -0800839 }
840
841 /*
842 * Calculate the maximum current that can pulled out of the battery
843 * before the battery voltage dips below a safe threshold.
844 */
845 ibat_safe_ua = div_s64((ocv_uv - vph_flash_vdip) * UCONV,
846 rbatt_uohm);
847
848 if (ibat_safe_ua <= led->pdata->ibatt_ocp_threshold_ua) {
849 /*
850 * If the calculated current is below the OCP threshold, then
851 * use it as the possible flash current.
852 */
853 ibat_flash_ua = ibat_safe_ua - ibat_now;
854 vph_flash_uv = vph_flash_vdip;
855 } else {
856 /*
857 * If the calculated current is above the OCP threshold, then
858 * use the ocp threshold instead.
859 *
860 * Any higher current will be tripping the battery OCP.
861 */
862 ibat_flash_ua = led->pdata->ibatt_ocp_threshold_ua - ibat_now;
863 vph_flash_uv = ocv_uv - div64_s64((int64_t)rbatt_uohm
864 * led->pdata->ibatt_ocp_threshold_ua, UCONV);
865 }
866 /* Calculate the input voltage of the flash module. */
867 vin_flash_uv = max((led->pdata->vled_max_uv +
868 (voltage_hdrm_mv * MCONV)), VIN_FLASH_MIN_UV);
869 /* Calculate the available power for the flash module. */
870 avail_flash_power_fw = BOB_EFFICIENCY * vph_flash_uv * ibat_flash_ua;
871 /*
872 * Calculate the available amount of current the flash module can draw
873 * before collapsing the battery. (available power/ flash input voltage)
874 */
875 avail_flash_ua = div64_s64(avail_flash_power_fw, vin_flash_uv * MCONV);
876 pr_debug("avail_iflash=%lld, ocv=%d, ibat=%d, rbatt=%d, trigger_lmh=%d\n",
877 avail_flash_ua, ocv_uv, ibat_now, rbatt_uohm, led->trigger_lmh);
Subbaraman Narayanamurthyd94945e2017-11-28 19:54:09 -0800878 *max_current = min(FLASH_LED_MAX_TOTAL_CURRENT_MA,
David Collins8885f792017-01-26 14:36:34 -0800879 (int)(div64_s64(avail_flash_ua, MCONV)));
Subbaraman Narayanamurthyd94945e2017-11-28 19:54:09 -0800880 return 0;
David Collins8885f792017-01-26 14:36:34 -0800881}
882
Kiran Gunda1c1e21c2017-12-15 09:55:03 +0530883static int is_main_psy_available(struct qpnp_flash_led *led)
884{
885 if (!led->main_psy) {
886 led->main_psy = power_supply_get_by_name("main");
887 if (!led->main_psy) {
888 pr_err_ratelimited("Couldn't get main_psy\n");
889 return -ENODEV;
890 }
891 }
892
893 return 0;
894}
895
896static int is_usb_psy_available(struct qpnp_flash_led *led)
897{
898 if (!led->usb_psy) {
899 led->usb_psy = power_supply_get_by_name("usb");
900 if (!led->usb_psy) {
901 pr_err_ratelimited("Couldn't get usb_psy\n");
902 return -ENODEV;
903 }
904 }
905
906 return 0;
907}
908
909#define CHGBST_EFFICIENCY 800LL
910#define CHGBST_FLASH_VDIP_MARGIN 10000
911#define VIN_FLASH_UV 5000000
912#define BHARGER_FLASH_LED_MAX_TOTAL_CURRENT_MA 1500
913#define BHARGER_FLASH_LED_WITH_OTG_MAX_TOTAL_CURRENT_MA 1100
914static int qpnp_flash_led_calc_bharger_max_current(struct qpnp_flash_led *led,
915 int *max_current)
916{
917 union power_supply_propval pval = {0, };
918 int ocv_uv, ibat_now, voltage_hdrm_mv, flash_led_max_total_curr_ma, rc;
919 int rbatt_uohm = 0, usb_present, otg_enable;
920 int64_t ibat_flash_ua, avail_flash_ua, avail_flash_power_fw;
921 int64_t ibat_safe_ua, vin_flash_uv, vph_flash_uv, vph_flash_vdip;
922 int64_t bst_pwm_ovrhd_uv;
923
924 rc = is_usb_psy_available(led);
925 if (rc < 0)
926 return rc;
927
928 rc = power_supply_get_property(led->usb_psy, POWER_SUPPLY_PROP_SCOPE,
929 &pval);
930 if (rc < 0) {
931 pr_err("usb psy does not support usb present, rc=%d\n", rc);
932 return rc;
933 }
934 otg_enable = pval.intval;
935
936 /* RESISTANCE = esr_uohm + rslow_uohm */
937 rc = get_property_from_fg(led, POWER_SUPPLY_PROP_RESISTANCE,
938 &rbatt_uohm);
939 if (rc < 0) {
940 pr_err("bms psy does not support resistance, rc=%d\n", rc);
941 return rc;
942 }
943
944 /* If no battery is connected, return max possible flash current */
945 if (!rbatt_uohm) {
946 *max_current = (otg_enable == POWER_SUPPLY_SCOPE_SYSTEM) ?
947 BHARGER_FLASH_LED_WITH_OTG_MAX_TOTAL_CURRENT_MA :
948 BHARGER_FLASH_LED_MAX_TOTAL_CURRENT_MA;
949 return 0;
950 }
951
952 rc = get_property_from_fg(led, POWER_SUPPLY_PROP_VOLTAGE_OCV, &ocv_uv);
953 if (rc < 0) {
954 pr_err("bms psy does not support OCV, rc=%d\n", rc);
955 return rc;
956 }
957
958 rc = get_property_from_fg(led, POWER_SUPPLY_PROP_CURRENT_NOW,
959 &ibat_now);
960 if (rc < 0) {
961 pr_err("bms psy does not support current, rc=%d\n", rc);
962 return rc;
963 }
964
965 bst_pwm_ovrhd_uv = led->pdata->bst_pwm_ovrhd_uv;
966
967 rc = power_supply_get_property(led->usb_psy, POWER_SUPPLY_PROP_PRESENT,
968 &pval);
969 if (rc < 0) {
970 pr_err("usb psy does not support usb present, rc=%d\n", rc);
971 return rc;
972 }
973 usb_present = pval.intval;
974
975 rbatt_uohm += led->pdata->rpara_uohm;
976 voltage_hdrm_mv = qpnp_flash_led_get_voltage_headroom(led);
977 vph_flash_vdip =
978 VPH_DROOP_THRESH_VAL_TO_UV(led->pdata->vph_droop_threshold)
979 + CHGBST_FLASH_VDIP_MARGIN;
980
981 /* Check if LMH_MITIGATION needs to be triggered */
982 if (!led->trigger_lmh && (ocv_uv < led->pdata->lmh_ocv_threshold_uv ||
983 rbatt_uohm > led->pdata->lmh_rbatt_threshold_uohm)) {
984 led->trigger_lmh = true;
985 rc = qpnp_flash_led_masked_write(led,
986 FLASH_LED_REG_MITIGATION_SW(led->base),
987 FLASH_LED_LMH_MITIGATION_EN_MASK,
988 FLASH_LED_LMH_MITIGATION_ENABLE);
989 if (rc < 0) {
990 pr_err("trigger lmh mitigation failed, rc=%d\n", rc);
991 return rc;
992 }
993
994 /* Wait for LMH mitigation to take effect */
995 udelay(100);
996
997 return qpnp_flash_led_calc_bharger_max_current(led,
998 max_current);
999 }
1000
1001 /*
1002 * Calculate the maximum current that can pulled out of the battery
1003 * before the battery voltage dips below a safe threshold.
1004 */
1005 ibat_safe_ua = div_s64((ocv_uv - vph_flash_vdip) * UCONV,
1006 rbatt_uohm);
1007
1008 if (ibat_safe_ua <= led->pdata->ibatt_ocp_threshold_ua) {
1009 /*
1010 * If the calculated current is below the OCP threshold, then
1011 * use it as the possible flash current.
1012 */
1013 ibat_flash_ua = ibat_safe_ua - ibat_now;
1014 vph_flash_uv = vph_flash_vdip;
1015 } else {
1016 /*
1017 * If the calculated current is above the OCP threshold, then
1018 * use the ocp threshold instead.
1019 *
1020 * Any higher current will be tripping the battery OCP.
1021 */
1022 ibat_flash_ua = led->pdata->ibatt_ocp_threshold_ua - ibat_now;
1023 vph_flash_uv = ocv_uv - div64_s64((int64_t)rbatt_uohm
1024 * led->pdata->ibatt_ocp_threshold_ua, UCONV);
1025 }
1026
1027 /* when USB is present or OTG is enabled, VIN_FLASH is always at 5V */
1028 if (usb_present || (otg_enable == POWER_SUPPLY_SCOPE_SYSTEM))
1029 vin_flash_uv = VIN_FLASH_UV;
1030 else
1031 /* Calculate the input voltage of the flash module. */
1032 vin_flash_uv = max((led->pdata->vled_max_uv +
1033 (voltage_hdrm_mv * MCONV)),
1034 vph_flash_uv + bst_pwm_ovrhd_uv);
1035
1036 /* Calculate the available power for the flash module. */
1037 avail_flash_power_fw = CHGBST_EFFICIENCY * vph_flash_uv * ibat_flash_ua;
1038 /*
1039 * Calculate the available amount of current the flash module can draw
1040 * before collapsing the battery. (available power/ flash input voltage)
1041 */
1042 avail_flash_ua = div64_s64(avail_flash_power_fw, vin_flash_uv * MCONV);
1043 flash_led_max_total_curr_ma = otg_enable ?
1044 BHARGER_FLASH_LED_WITH_OTG_MAX_TOTAL_CURRENT_MA :
1045 BHARGER_FLASH_LED_MAX_TOTAL_CURRENT_MA;
1046 *max_current = min(flash_led_max_total_curr_ma,
1047 (int)(div64_s64(avail_flash_ua, MCONV)));
1048
1049 pr_debug("avail_iflash=%lld, ocv=%d, ibat=%d, rbatt=%d, trigger_lmh=%d max_current=%lld usb_present=%d otg_enable=%d\n",
1050 avail_flash_ua, ocv_uv, ibat_now, rbatt_uohm, led->trigger_lmh,
1051 (*max_current * MCONV), usb_present, otg_enable);
1052 return 0;
1053}
1054
1055
Subbaraman Narayanamurthyd94945e2017-11-28 19:54:09 -08001056static int qpnp_flash_led_calc_thermal_current_lim(struct qpnp_flash_led *led,
Kiran Gunda1c1e21c2017-12-15 09:55:03 +05301057 int *thermal_current_lim)
David Collins8885f792017-01-26 14:36:34 -08001058{
David Collins8885f792017-01-26 14:36:34 -08001059 int rc;
1060 u8 thermal_thrsh1, thermal_thrsh2, thermal_thrsh3, otst_status;
1061
1062 /* Store THERMAL_THRSHx register values */
1063 rc = qpnp_flash_led_masked_read(led,
1064 FLASH_LED_REG_THERMAL_THRSH1(led->base),
1065 FLASH_LED_THERMAL_THRSH_MASK,
1066 &thermal_thrsh1);
1067 if (rc < 0)
1068 return rc;
1069
1070 rc = qpnp_flash_led_masked_read(led,
1071 FLASH_LED_REG_THERMAL_THRSH2(led->base),
1072 FLASH_LED_THERMAL_THRSH_MASK,
1073 &thermal_thrsh2);
1074 if (rc < 0)
1075 return rc;
1076
1077 rc = qpnp_flash_led_masked_read(led,
1078 FLASH_LED_REG_THERMAL_THRSH3(led->base),
1079 FLASH_LED_THERMAL_THRSH_MASK,
1080 &thermal_thrsh3);
1081 if (rc < 0)
1082 return rc;
1083
1084 /* Lower THERMAL_THRSHx thresholds to minimum */
1085 rc = qpnp_flash_led_masked_write(led,
1086 FLASH_LED_REG_THERMAL_THRSH1(led->base),
1087 FLASH_LED_THERMAL_THRSH_MASK,
1088 FLASH_LED_THERMAL_THRSH_MIN);
1089 if (rc < 0)
1090 return rc;
1091
1092 rc = qpnp_flash_led_masked_write(led,
1093 FLASH_LED_REG_THERMAL_THRSH2(led->base),
1094 FLASH_LED_THERMAL_THRSH_MASK,
1095 FLASH_LED_THERMAL_THRSH_MIN);
1096 if (rc < 0)
1097 return rc;
1098
1099 rc = qpnp_flash_led_masked_write(led,
1100 FLASH_LED_REG_THERMAL_THRSH3(led->base),
1101 FLASH_LED_THERMAL_THRSH_MASK,
1102 FLASH_LED_THERMAL_THRSH_MIN);
1103 if (rc < 0)
1104 return rc;
1105
1106 /* Check THERMAL_OTST status */
1107 rc = qpnp_flash_led_read(led,
1108 FLASH_LED_REG_LED_STATUS2(led->base),
1109 &otst_status);
1110 if (rc < 0)
1111 return rc;
1112
1113 /* Look up current limit based on THERMAL_OTST status */
1114 if (otst_status)
Subbaraman Narayanamurthyd94945e2017-11-28 19:54:09 -08001115 *thermal_current_lim =
David Collins8885f792017-01-26 14:36:34 -08001116 led->pdata->thermal_derate_current[otst_status >> 1];
1117
1118 /* Restore THERMAL_THRESHx registers to original values */
1119 rc = qpnp_flash_led_masked_write(led,
1120 FLASH_LED_REG_THERMAL_THRSH1(led->base),
1121 FLASH_LED_THERMAL_THRSH_MASK,
1122 thermal_thrsh1);
1123 if (rc < 0)
1124 return rc;
1125
1126 rc = qpnp_flash_led_masked_write(led,
1127 FLASH_LED_REG_THERMAL_THRSH2(led->base),
1128 FLASH_LED_THERMAL_THRSH_MASK,
1129 thermal_thrsh2);
1130 if (rc < 0)
1131 return rc;
1132
1133 rc = qpnp_flash_led_masked_write(led,
1134 FLASH_LED_REG_THERMAL_THRSH3(led->base),
1135 FLASH_LED_THERMAL_THRSH_MASK,
1136 thermal_thrsh3);
1137 if (rc < 0)
1138 return rc;
1139
Subbaraman Narayanamurthyd94945e2017-11-28 19:54:09 -08001140 return 0;
David Collins8885f792017-01-26 14:36:34 -08001141}
1142
Subbaraman Narayanamurthyd94945e2017-11-28 19:54:09 -08001143static int qpnp_flash_led_get_max_avail_current(struct qpnp_flash_led *led,
1144 int *max_avail_current)
David Collins8885f792017-01-26 14:36:34 -08001145{
Subbaraman Narayanamurthyd94945e2017-11-28 19:54:09 -08001146 int thermal_current_lim = 0, rc;
Kiran Gunda1c1e21c2017-12-15 09:55:03 +05301147 u8 pmic_subtype = led->pdata->pmic_rev_id->pmic_subtype;
David Collins8885f792017-01-26 14:36:34 -08001148
1149 led->trigger_lmh = false;
Kiran Gunda1c1e21c2017-12-15 09:55:03 +05301150
1151 if (pmic_subtype == PMI632_SUBTYPE)
1152 rc = qpnp_flash_led_calc_bharger_max_current(led,
1153 max_avail_current);
1154 else
1155 rc = qpnp_flash_led_calc_max_current(led, max_avail_current);
1156
Subbaraman Narayanamurthyd94945e2017-11-28 19:54:09 -08001157 if (rc < 0) {
1158 pr_err("Couldn't calculate max_avail_current, rc=%d\n", rc);
1159 return rc;
1160 }
1161
1162 if (led->pdata->thermal_derate_en) {
1163 rc = qpnp_flash_led_calc_thermal_current_lim(led,
1164 &thermal_current_lim);
1165 if (rc < 0) {
1166 pr_err("Couldn't calculate thermal_current_lim, rc=%d\n",
1167 rc);
1168 return rc;
1169 }
1170 }
David Collins8885f792017-01-26 14:36:34 -08001171
1172 if (thermal_current_lim)
Subbaraman Narayanamurthyd94945e2017-11-28 19:54:09 -08001173 *max_avail_current = min(*max_avail_current,
1174 thermal_current_lim);
David Collins8885f792017-01-26 14:36:34 -08001175
Subbaraman Narayanamurthyd94945e2017-11-28 19:54:09 -08001176 return 0;
David Collins8885f792017-01-26 14:36:34 -08001177}
1178
Ankit Sharmaa7153c32017-03-22 19:04:52 +05301179static void qpnp_flash_led_aggregate_max_current(struct flash_node_data *fnode)
1180{
1181 struct qpnp_flash_led *led = dev_get_drvdata(&fnode->pdev->dev);
1182
1183 if (fnode->current_ma)
1184 led->total_current_ma += fnode->current_ma
1185 - fnode->prev_current_ma;
1186 else
1187 led->total_current_ma -= fnode->prev_current_ma;
1188
1189 fnode->prev_current_ma = fnode->current_ma;
1190}
1191
David Collins8885f792017-01-26 14:36:34 -08001192static void qpnp_flash_led_node_set(struct flash_node_data *fnode, int value)
1193{
Kiran Gunda5cadca72017-07-26 14:37:52 +05301194 int i = 0;
David Collins8885f792017-01-26 14:36:34 -08001195 int prgm_current_ma = value;
Ankit Sharma8798ab12017-04-06 15:44:09 +05301196 int min_ma = fnode->ires_ua / 1000;
Ankit Sharmaa7153c32017-03-22 19:04:52 +05301197 struct qpnp_flash_led *led = dev_get_drvdata(&fnode->pdev->dev);
Kiran Gunda1c1e21c2017-12-15 09:55:03 +05301198 u8 pmic_subtype = led->pdata->pmic_rev_id->pmic_subtype;
David Collins8885f792017-01-26 14:36:34 -08001199
1200 if (value <= 0)
1201 prgm_current_ma = 0;
Ankit Sharma8798ab12017-04-06 15:44:09 +05301202 else if (value < min_ma)
1203 prgm_current_ma = min_ma;
David Collins8885f792017-01-26 14:36:34 -08001204
Kiran Gunda5cadca72017-07-26 14:37:52 +05301205 fnode->ires_idx = fnode->default_ires_idx;
1206 fnode->ires_ua = fnode->default_ires_ua;
1207
David Collins8885f792017-01-26 14:36:34 -08001208 prgm_current_ma = min(prgm_current_ma, fnode->max_current);
Kiran Gunda5cadca72017-07-26 14:37:52 +05301209 if (prgm_current_ma > max_ires_curr_ma_table[fnode->ires_idx]) {
1210 /* find the matching ires */
1211 for (i = MAX_IRES_LEVELS - 1; i >= 0; i--) {
1212 if (prgm_current_ma <= max_ires_curr_ma_table[i]) {
1213 fnode->ires_idx = i;
1214 fnode->ires_ua = FLASH_LED_IRES_MIN_UA +
1215 (FLASH_LED_IRES_BASE - fnode->ires_idx) *
1216 FLASH_LED_IRES_DIVISOR;
1217 break;
1218 }
1219 }
1220 }
David Collins8885f792017-01-26 14:36:34 -08001221 fnode->current_ma = prgm_current_ma;
1222 fnode->cdev.brightness = prgm_current_ma;
Subbaraman Narayanamurthyaf8dcb42018-01-17 20:23:47 -08001223 fnode->current_reg_val = get_current_reg_code(prgm_current_ma,
David Collins8885f792017-01-26 14:36:34 -08001224 fnode->ires_ua);
Subbaraman Narayanamurthy1b411f52018-03-06 16:01:26 -08001225 if (prgm_current_ma)
1226 fnode->led_on = true;
Ankit Sharmaa7153c32017-03-22 19:04:52 +05301227
Kiran Gunda1c1e21c2017-12-15 09:55:03 +05301228 if (pmic_subtype != PMI632_SUBTYPE &&
1229 led->pdata->chgr_mitigation_sel == FLASH_SW_CHARGER_MITIGATION) {
Ankit Sharmaa7153c32017-03-22 19:04:52 +05301230 qpnp_flash_led_aggregate_max_current(fnode);
1231 led->trigger_chgr = false;
1232 if (led->total_current_ma >= 1000)
1233 led->trigger_chgr = true;
1234 }
David Collins8885f792017-01-26 14:36:34 -08001235}
1236
1237static int qpnp_flash_led_switch_disable(struct flash_switch_data *snode)
1238{
1239 struct qpnp_flash_led *led = dev_get_drvdata(&snode->pdev->dev);
1240 int i, rc, addr_offset;
1241
1242 rc = qpnp_flash_led_masked_write(led,
1243 FLASH_LED_EN_LED_CTRL(led->base),
1244 snode->led_mask, FLASH_LED_DISABLE);
1245 if (rc < 0)
1246 return rc;
1247
1248 if (led->trigger_lmh) {
1249 rc = qpnp_flash_led_masked_write(led,
1250 FLASH_LED_REG_MITIGATION_SW(led->base),
1251 FLASH_LED_LMH_MITIGATION_EN_MASK,
1252 FLASH_LED_LMH_MITIGATION_DISABLE);
1253 if (rc < 0) {
1254 pr_err("disable lmh mitigation failed, rc=%d\n", rc);
1255 return rc;
1256 }
1257 }
1258
Kiran Gunda1c1e21c2017-12-15 09:55:03 +05301259 if (led->pdata->chgr_mitigation_sel && !led->trigger_chgr) {
David Collins8885f792017-01-26 14:36:34 -08001260 rc = qpnp_flash_led_masked_write(led,
1261 FLASH_LED_REG_MITIGATION_SW(led->base),
1262 FLASH_LED_CHGR_MITIGATION_EN_MASK,
1263 FLASH_LED_CHGR_MITIGATION_DISABLE);
1264 if (rc < 0) {
1265 pr_err("disable chgr mitigation failed, rc=%d\n", rc);
1266 return rc;
1267 }
1268 }
1269
1270 led->enable--;
1271 if (led->enable == 0) {
1272 rc = qpnp_flash_led_masked_write(led,
1273 FLASH_LED_REG_MOD_CTRL(led->base),
1274 FLASH_LED_MOD_CTRL_MASK, FLASH_LED_DISABLE);
1275 if (rc < 0)
1276 return rc;
1277 }
1278
1279 for (i = 0; i < led->num_fnodes; i++) {
1280 if (!led->fnode[i].led_on ||
1281 !(snode->led_mask & BIT(led->fnode[i].id)))
1282 continue;
1283
1284 addr_offset = led->fnode[i].id;
1285 rc = qpnp_flash_led_masked_write(led,
1286 FLASH_LED_REG_TGR_CURRENT(led->base + addr_offset),
1287 FLASH_LED_CURRENT_MASK, 0);
1288 if (rc < 0)
1289 return rc;
1290
1291 led->fnode[i].led_on = false;
1292
Subbaraman Narayanamurthy3f684b22017-03-21 20:49:54 -07001293 if (led->fnode[i].strobe_sel == HW_STROBE) {
David Collins8885f792017-01-26 14:36:34 -08001294 rc = qpnp_flash_led_hw_strobe_enable(&led->fnode[i],
1295 led->pdata->hw_strobe_option, false);
1296 if (rc < 0) {
1297 pr_err("Unable to disable hw strobe, rc=%d\n",
1298 rc);
1299 return rc;
1300 }
1301 }
1302 }
1303
Subbaraman Narayanamurthy58377f02017-03-21 20:38:43 -07001304 if (snode->led_en_pinctrl) {
1305 pr_debug("Selecting suspend state for %s\n", snode->cdev.name);
1306 rc = pinctrl_select_state(snode->led_en_pinctrl,
1307 snode->gpio_state_suspend);
1308 if (rc < 0) {
1309 pr_err("failed to select pinctrl suspend state rc=%d\n",
1310 rc);
1311 return rc;
1312 }
1313 }
1314
David Collins8885f792017-01-26 14:36:34 -08001315 snode->enabled = false;
1316 return 0;
1317}
1318
Subbaraman Narayanamurthyd737fd52018-01-17 19:58:52 -08001319static int qpnp_flash_led_symmetry_config(struct flash_switch_data *snode)
1320{
1321 struct qpnp_flash_led *led = dev_get_drvdata(&snode->pdev->dev);
1322 int i, total_curr_ma = 0, num_leds = 0, prgm_current_ma;
1323 enum flash_led_type type = FLASH_LED_TYPE_UNKNOWN;
1324
1325 for (i = 0; i < led->num_fnodes; i++) {
1326 if (snode->led_mask & BIT(led->fnode[i].id)) {
1327 if (led->fnode[i].type == FLASH_LED_TYPE_FLASH &&
1328 led->fnode[i].led_on)
1329 type = FLASH_LED_TYPE_FLASH;
1330
1331 if (led->fnode[i].type == FLASH_LED_TYPE_TORCH &&
1332 led->fnode[i].led_on)
1333 type = FLASH_LED_TYPE_TORCH;
1334 }
1335 }
1336
1337 if (type == FLASH_LED_TYPE_UNKNOWN) {
1338 pr_err("Incorrect type possibly because of no active LEDs\n");
1339 return -EINVAL;
1340 }
1341
1342 for (i = 0; i < led->num_fnodes; i++) {
1343 if ((snode->led_mask & BIT(led->fnode[i].id)) &&
1344 (led->fnode[i].type == type)) {
1345 total_curr_ma += led->fnode[i].current_ma;
1346 num_leds++;
1347 }
1348 }
1349
1350 if (num_leds > 0 && total_curr_ma > 0) {
1351 prgm_current_ma = total_curr_ma / num_leds;
1352 } else {
1353 pr_err("Incorrect configuration, num_leds: %d total_curr_ma: %d\n",
1354 num_leds, total_curr_ma);
1355 return -EINVAL;
1356 }
1357
1358 if (prgm_current_ma == 0) {
1359 pr_warn("prgm_curr_ma cannot be 0\n");
1360 return 0;
1361 }
1362
1363 pr_debug("num_leds: %d total: %d prgm_curr_ma: %d\n", num_leds,
1364 total_curr_ma, prgm_current_ma);
1365
1366 for (i = 0; i < led->num_fnodes; i++) {
1367 if (snode->led_mask & BIT(led->fnode[i].id) &&
1368 led->fnode[i].current_ma != prgm_current_ma &&
1369 led->fnode[i].type == type) {
1370 qpnp_flash_led_node_set(&led->fnode[i],
1371 prgm_current_ma);
1372 pr_debug("%s LED %d current: %d code: %d ires_ua: %d\n",
1373 (type == FLASH_LED_TYPE_FLASH) ?
1374 "flash" : "torch",
1375 led->fnode[i].id, prgm_current_ma,
1376 led->fnode[i].current_reg_val,
1377 led->fnode[i].ires_ua);
1378 }
1379 }
1380
1381 return 0;
1382}
1383
Kiran Gunda1c1e21c2017-12-15 09:55:03 +05301384#define FLASH_LED_MODULE_EN_TIME_MS 300
1385static int qpnp_flash_poll_vreg_ok(struct qpnp_flash_led *led)
1386{
1387 int rc, i;
1388 union power_supply_propval pval = {0, };
1389
1390 rc = is_main_psy_available(led);
1391 if (rc < 0)
1392 return rc;
1393
1394 for (i = 0; i < 60; i++) {
1395 /* wait for the flash vreg_ok to be set */
1396 mdelay(5);
1397
1398 rc = power_supply_get_property(led->main_psy,
1399 POWER_SUPPLY_PROP_FLASH_TRIGGER, &pval);
1400 if (rc < 0) {
1401 pr_err("main psy doesn't support reading prop %d rc = %d\n",
1402 POWER_SUPPLY_PROP_FLASH_TRIGGER, rc);
1403 return rc;
1404 }
1405
1406 if (pval.intval > 0) {
1407 pr_debug("Flash trigger set\n");
1408 break;
1409 }
1410
1411 if (pval.intval < 0) {
1412 pr_err("Error during flash trigger %d\n", pval.intval);
1413 return pval.intval;
1414 }
1415 }
1416
1417 if (!pval.intval) {
1418 pr_err("Failed to enable the module\n");
1419 return -ETIMEDOUT;
1420 }
1421
1422 return 0;
1423}
1424
David Collins8885f792017-01-26 14:36:34 -08001425static int qpnp_flash_led_switch_set(struct flash_switch_data *snode, bool on)
1426{
1427 struct qpnp_flash_led *led = dev_get_drvdata(&snode->pdev->dev);
Kiran Gunda1c1e21c2017-12-15 09:55:03 +05301428 u8 pmic_subtype = led->pdata->pmic_rev_id->pmic_subtype;
David Collins8885f792017-01-26 14:36:34 -08001429 int rc, i, addr_offset;
1430 u8 val, mask;
1431
1432 if (snode->enabled == on) {
1433 pr_debug("Switch node is already %s!\n",
1434 on ? "enabled" : "disabled");
1435 return 0;
1436 }
1437
1438 if (!on) {
1439 rc = qpnp_flash_led_switch_disable(snode);
1440 return rc;
1441 }
1442
Subbaraman Narayanamurthy411699a2018-01-15 12:40:49 -08001443 /* Iterate over all active leds for this switch node */
Subbaraman Narayanamurthyd737fd52018-01-17 19:58:52 -08001444 if (snode->symmetry_en) {
1445 rc = qpnp_flash_led_symmetry_config(snode);
1446 if (rc < 0) {
1447 pr_err("Failed to configure current symmetrically, rc=%d\n",
1448 rc);
1449 return rc;
1450 }
1451 }
1452
David Collins8885f792017-01-26 14:36:34 -08001453 val = 0;
1454 for (i = 0; i < led->num_fnodes; i++)
Subbaraman Narayanamurthy411699a2018-01-15 12:40:49 -08001455 if (led->fnode[i].led_on &&
1456 snode->led_mask & BIT(led->fnode[i].id))
Kiran Gunda5cadca72017-07-26 14:37:52 +05301457 val |= led->fnode[i].ires_idx << (led->fnode[i].id * 2);
David Collins8885f792017-01-26 14:36:34 -08001458
1459 rc = qpnp_flash_led_masked_write(led, FLASH_LED_REG_IRES(led->base),
1460 FLASH_LED_CURRENT_MASK, val);
1461 if (rc < 0)
1462 return rc;
1463
David Collins8885f792017-01-26 14:36:34 -08001464 val = 0;
1465 for (i = 0; i < led->num_fnodes; i++) {
1466 if (!led->fnode[i].led_on ||
1467 !(snode->led_mask & BIT(led->fnode[i].id)))
1468 continue;
1469
1470 addr_offset = led->fnode[i].id;
Subbaraman Narayanamurthy3f684b22017-03-21 20:49:54 -07001471 if (led->fnode[i].strobe_sel == SW_STROBE)
David Collins8885f792017-01-26 14:36:34 -08001472 mask = FLASH_LED_HW_SW_STROBE_SEL_BIT;
Subbaraman Narayanamurthy3f684b22017-03-21 20:49:54 -07001473 else
1474 mask = FLASH_HW_STROBE_MASK;
David Collins8885f792017-01-26 14:36:34 -08001475 rc = qpnp_flash_led_masked_write(led,
1476 FLASH_LED_REG_STROBE_CTRL(led->base + addr_offset),
Subbaraman Narayanamurthy3f684b22017-03-21 20:49:54 -07001477 mask, led->fnode[i].strobe_ctrl);
David Collins8885f792017-01-26 14:36:34 -08001478 if (rc < 0)
1479 return rc;
1480
1481 rc = qpnp_flash_led_masked_write(led,
1482 FLASH_LED_REG_TGR_CURRENT(led->base + addr_offset),
1483 FLASH_LED_CURRENT_MASK, led->fnode[i].current_reg_val);
1484 if (rc < 0)
1485 return rc;
1486
1487 rc = qpnp_flash_led_write(led,
1488 FLASH_LED_REG_SAFETY_TMR(led->base + addr_offset),
1489 led->fnode[i].duration);
1490 if (rc < 0)
1491 return rc;
1492
1493 val |= FLASH_LED_ENABLE << led->fnode[i].id;
1494
Subbaraman Narayanamurthy3f684b22017-03-21 20:49:54 -07001495 if (led->fnode[i].strobe_sel == HW_STROBE) {
David Collins8885f792017-01-26 14:36:34 -08001496 rc = qpnp_flash_led_hw_strobe_enable(&led->fnode[i],
1497 led->pdata->hw_strobe_option, true);
1498 if (rc < 0) {
1499 pr_err("Unable to enable hw strobe rc=%d\n",
1500 rc);
1501 return rc;
1502 }
1503 }
1504 }
1505
Subbaraman Narayanamurthy58377f02017-03-21 20:38:43 -07001506 if (snode->led_en_pinctrl) {
1507 pr_debug("Selecting active state for %s\n", snode->cdev.name);
1508 rc = pinctrl_select_state(snode->led_en_pinctrl,
1509 snode->gpio_state_active);
1510 if (rc < 0) {
1511 pr_err("failed to select pinctrl active state rc=%d\n",
1512 rc);
1513 return rc;
1514 }
1515 }
1516
David Collins8885f792017-01-26 14:36:34 -08001517 if (led->enable == 0) {
1518 rc = qpnp_flash_led_masked_write(led,
1519 FLASH_LED_REG_MOD_CTRL(led->base),
1520 FLASH_LED_MOD_CTRL_MASK, FLASH_LED_MOD_ENABLE);
1521 if (rc < 0)
1522 return rc;
Kiran Gunda1c1e21c2017-12-15 09:55:03 +05301523
1524 if (pmic_subtype == PMI632_SUBTYPE) {
1525 rc = qpnp_flash_poll_vreg_ok(led);
1526 if (rc < 0) {
1527 /* Disable the module */
1528 qpnp_flash_led_masked_write(led,
1529 FLASH_LED_REG_MOD_CTRL(led->base),
1530 FLASH_LED_MOD_CTRL_MASK,
1531 FLASH_LED_DISABLE);
1532
1533 return rc;
1534 }
1535 }
David Collins8885f792017-01-26 14:36:34 -08001536 }
1537 led->enable++;
1538
1539 if (led->trigger_lmh) {
1540 rc = qpnp_flash_led_masked_write(led,
1541 FLASH_LED_REG_MITIGATION_SW(led->base),
1542 FLASH_LED_LMH_MITIGATION_EN_MASK,
1543 FLASH_LED_LMH_MITIGATION_ENABLE);
1544 if (rc < 0) {
1545 pr_err("trigger lmh mitigation failed, rc=%d\n", rc);
1546 return rc;
1547 }
Subbaraman Narayanamurthyd02fbc92017-02-02 16:39:41 -08001548 /* Wait for LMH mitigation to take effect */
1549 udelay(500);
David Collins8885f792017-01-26 14:36:34 -08001550 }
1551
Kiran Gunda1c1e21c2017-12-15 09:55:03 +05301552 if (led->pdata->chgr_mitigation_sel && led->trigger_chgr) {
David Collins8885f792017-01-26 14:36:34 -08001553 rc = qpnp_flash_led_masked_write(led,
1554 FLASH_LED_REG_MITIGATION_SW(led->base),
1555 FLASH_LED_CHGR_MITIGATION_EN_MASK,
1556 FLASH_LED_CHGR_MITIGATION_ENABLE);
1557 if (rc < 0) {
1558 pr_err("trigger chgr mitigation failed, rc=%d\n", rc);
1559 return rc;
1560 }
1561 }
1562
1563 rc = qpnp_flash_led_masked_write(led,
1564 FLASH_LED_EN_LED_CTRL(led->base),
1565 snode->led_mask, val);
1566 if (rc < 0)
1567 return rc;
1568
1569 snode->enabled = true;
1570 return 0;
1571}
1572
Kiran Gunda1c1e21c2017-12-15 09:55:03 +05301573static int qpnp_flash_led_regulator_control(struct led_classdev *led_cdev,
1574 int options, int *max_current)
1575{
1576 int rc;
1577 u8 pmic_subtype;
1578 struct flash_switch_data *snode;
1579 struct qpnp_flash_led *led;
1580 union power_supply_propval ret = {0, };
1581
1582 snode = container_of(led_cdev, struct flash_switch_data, cdev);
1583 led = dev_get_drvdata(&snode->pdev->dev);
1584 pmic_subtype = led->pdata->pmic_rev_id->pmic_subtype;
1585
1586 if (pmic_subtype == PMI632_SUBTYPE) {
1587 rc = is_main_psy_available(led);
1588 if (rc < 0)
1589 return rc;
1590
1591 rc = is_usb_psy_available(led);
1592 if (rc < 0)
1593 return rc;
1594 }
1595
1596 if (!(options & FLASH_LED_PREPARE_OPTIONS_MASK)) {
1597 pr_err("Invalid options %d\n", options);
1598 return -EINVAL;
1599 }
1600
1601 if (options & ENABLE_REGULATOR) {
1602 if (pmic_subtype == PMI632_SUBTYPE) {
1603 ret.intval = 1;
1604 rc = power_supply_set_property(led->main_psy,
1605 POWER_SUPPLY_PROP_FLASH_ACTIVE,
1606 &ret);
1607 if (rc < 0) {
1608 pr_err("Failed to set FLASH_ACTIVE on charger rc=%d\n",
1609 rc);
1610 return rc;
1611 }
1612 pr_debug("FLASH_ACTIVE = 1\n");
1613 } else {
1614 rc = qpnp_flash_led_regulator_enable(led, snode, true);
1615 if (rc < 0) {
1616 pr_err("enable regulator failed, rc=%d\n", rc);
1617 return rc;
1618 }
1619 }
1620 }
1621
1622 if (options & DISABLE_REGULATOR) {
1623 if (pmic_subtype == PMI632_SUBTYPE) {
1624 ret.intval = 0;
1625 rc = power_supply_set_property(led->main_psy,
1626 POWER_SUPPLY_PROP_FLASH_ACTIVE,
1627 &ret);
1628 if (rc < 0) {
1629 pr_err("Failed to set FLASH_ACTIVE on charger rc=%d\n",
1630 rc);
1631 return rc;
1632 }
1633 pr_debug("FLASH_ACTIVE = 0\n");
1634 } else {
1635 rc = qpnp_flash_led_regulator_enable(led, snode, false);
1636 if (rc < 0) {
1637 pr_err("disable regulator failed, rc=%d\n", rc);
1638 return rc;
1639 }
1640 }
1641 }
1642
1643 if (options & QUERY_MAX_CURRENT) {
1644 rc = qpnp_flash_led_get_max_avail_current(led, max_current);
1645 if (rc < 0) {
1646 pr_err("query max current failed, rc=%d\n", rc);
1647 return rc;
1648 }
1649 }
1650
1651 return 0;
1652}
1653
Kiran Gundabf1e6c02018-01-17 17:50:20 +05301654static int qpnp_flash_led_prepare_v2(struct led_trigger *trig, int options,
David Collins8885f792017-01-26 14:36:34 -08001655 int *max_current)
1656{
1657 struct led_classdev *led_cdev;
David Collins8885f792017-01-26 14:36:34 -08001658 int rc;
1659
1660 if (!trig) {
1661 pr_err("Invalid led_trigger provided\n");
1662 return -EINVAL;
1663 }
1664
1665 led_cdev = trigger_to_lcdev(trig);
1666 if (!led_cdev) {
1667 pr_err("Invalid led_cdev in trigger %s\n", trig->name);
1668 return -EINVAL;
1669 }
1670
Kiran Gunda1c1e21c2017-12-15 09:55:03 +05301671 rc = qpnp_flash_led_regulator_control(led_cdev, options, max_current);
David Collins8885f792017-01-26 14:36:34 -08001672
Kiran Gunda1c1e21c2017-12-15 09:55:03 +05301673 return rc;
David Collins8885f792017-01-26 14:36:34 -08001674}
1675
1676static void qpnp_flash_led_brightness_set(struct led_classdev *led_cdev,
1677 enum led_brightness value)
1678{
1679 struct flash_node_data *fnode = NULL;
1680 struct flash_switch_data *snode = NULL;
1681 struct qpnp_flash_led *led = NULL;
1682 int rc;
1683
1684 /*
1685 * strncmp() must be used here since a prefix comparison is required
1686 * in order to support names like led:switch_0 and led:flash_1.
1687 */
1688 if (!strncmp(led_cdev->name, "led:switch", strlen("led:switch"))) {
1689 snode = container_of(led_cdev, struct flash_switch_data, cdev);
1690 led = dev_get_drvdata(&snode->pdev->dev);
1691 } else if (!strncmp(led_cdev->name, "led:flash", strlen("led:flash")) ||
1692 !strncmp(led_cdev->name, "led:torch",
1693 strlen("led:torch"))) {
1694 fnode = container_of(led_cdev, struct flash_node_data, cdev);
1695 led = dev_get_drvdata(&fnode->pdev->dev);
1696 }
1697
1698 if (!led) {
1699 pr_err("Failed to get flash driver data\n");
1700 return;
1701 }
1702
1703 spin_lock(&led->lock);
1704 if (snode) {
1705 rc = qpnp_flash_led_switch_set(snode, value > 0);
1706 if (rc < 0)
1707 pr_err("Failed to set flash LED switch rc=%d\n", rc);
1708 } else if (fnode) {
1709 qpnp_flash_led_node_set(fnode, value);
1710 }
1711
1712 spin_unlock(&led->lock);
1713}
1714
Kiran Gunda1c1e21c2017-12-15 09:55:03 +05301715static ssize_t qpnp_flash_led_prepare_store(struct device *dev,
1716 struct device_attribute *attr, const char *buf, size_t count)
1717{
1718 int rc, options, max_current;
1719 u32 val;
1720 struct led_classdev *led_cdev = dev_get_drvdata(dev);
1721
1722 rc = kstrtouint(buf, 0, &val);
1723 if (rc < 0)
1724 return rc;
1725
1726 if (val != 0 && val != 1)
1727 return count;
1728
1729 options = val ? ENABLE_REGULATOR : DISABLE_REGULATOR;
1730
1731 rc = qpnp_flash_led_regulator_control(led_cdev, options, &max_current);
1732 if (rc < 0)
1733 return rc;
1734
1735 return count;
1736}
1737
David Collins8885f792017-01-26 14:36:34 -08001738/* sysfs show function for flash_max_current */
1739static ssize_t qpnp_flash_led_max_current_show(struct device *dev,
1740 struct device_attribute *attr, char *buf)
1741{
Subbaraman Narayanamurthyd94945e2017-11-28 19:54:09 -08001742 int rc, max_current = 0;
David Collins8885f792017-01-26 14:36:34 -08001743 struct flash_switch_data *snode;
1744 struct qpnp_flash_led *led;
1745 struct led_classdev *led_cdev = dev_get_drvdata(dev);
1746
1747 snode = container_of(led_cdev, struct flash_switch_data, cdev);
1748 led = dev_get_drvdata(&snode->pdev->dev);
1749
Subbaraman Narayanamurthyd94945e2017-11-28 19:54:09 -08001750 rc = qpnp_flash_led_get_max_avail_current(led, &max_current);
David Collins8885f792017-01-26 14:36:34 -08001751 if (rc < 0)
1752 pr_err("query max current failed, rc=%d\n", rc);
1753
Subbaraman Narayanamurthyd94945e2017-11-28 19:54:09 -08001754 return snprintf(buf, PAGE_SIZE, "%d\n", max_current);
David Collins8885f792017-01-26 14:36:34 -08001755}
1756
1757/* sysfs attributes exported by flash_led */
1758static struct device_attribute qpnp_flash_led_attrs[] = {
1759 __ATTR(max_current, 0664, qpnp_flash_led_max_current_show, NULL),
Kiran Gunda1c1e21c2017-12-15 09:55:03 +05301760 __ATTR(enable, 0664, NULL, qpnp_flash_led_prepare_store),
David Collins8885f792017-01-26 14:36:34 -08001761};
1762
1763static int flash_led_psy_notifier_call(struct notifier_block *nb,
1764 unsigned long ev, void *v)
1765{
1766 struct power_supply *psy = v;
1767 struct qpnp_flash_led *led =
1768 container_of(nb, struct qpnp_flash_led, nb);
1769
1770 if (ev != PSY_EVENT_PROP_CHANGED)
1771 return NOTIFY_OK;
1772
1773 if (!strcmp(psy->desc->name, "bms")) {
1774 led->bms_psy = power_supply_get_by_name("bms");
1775 if (!led->bms_psy)
1776 pr_err("Failed to get bms power_supply\n");
1777 else
1778 power_supply_unreg_notifier(&led->nb);
1779 }
1780
1781 return NOTIFY_OK;
1782}
1783
1784static int flash_led_psy_register_notifier(struct qpnp_flash_led *led)
1785{
1786 int rc;
1787
1788 led->nb.notifier_call = flash_led_psy_notifier_call;
1789 rc = power_supply_reg_notifier(&led->nb);
1790 if (rc < 0) {
1791 pr_err("Couldn't register psy notifier, rc = %d\n", rc);
1792 return rc;
1793 }
1794
1795 return 0;
1796}
1797
1798/* irq handler */
1799static irqreturn_t qpnp_flash_led_irq_handler(int irq, void *_led)
1800{
1801 struct qpnp_flash_led *led = _led;
1802 enum flash_led_irq_type irq_type = INVALID_IRQ;
1803 int rc;
1804 u8 irq_status, led_status1, led_status2;
1805
1806 pr_debug("irq received, irq=%d\n", irq);
1807
1808 rc = qpnp_flash_led_read(led,
1809 FLASH_LED_REG_INT_RT_STS(led->base), &irq_status);
1810 if (rc < 0) {
1811 pr_err("Failed to read interrupt status reg, rc=%d\n", rc);
1812 goto exit;
1813 }
1814
1815 if (irq == led->pdata->all_ramp_up_done_irq)
1816 irq_type = ALL_RAMP_UP_DONE_IRQ;
1817 else if (irq == led->pdata->all_ramp_down_done_irq)
1818 irq_type = ALL_RAMP_DOWN_DONE_IRQ;
1819 else if (irq == led->pdata->led_fault_irq)
1820 irq_type = LED_FAULT_IRQ;
1821
1822 if (irq_type == ALL_RAMP_UP_DONE_IRQ)
1823 atomic_notifier_call_chain(&irq_notifier_list,
1824 irq_type, NULL);
1825
1826 if (irq_type == LED_FAULT_IRQ) {
1827 rc = qpnp_flash_led_read(led,
1828 FLASH_LED_REG_LED_STATUS1(led->base), &led_status1);
1829 if (rc < 0) {
1830 pr_err("Failed to read led_status1 reg, rc=%d\n", rc);
1831 goto exit;
1832 }
1833
1834 rc = qpnp_flash_led_read(led,
1835 FLASH_LED_REG_LED_STATUS2(led->base), &led_status2);
1836 if (rc < 0) {
1837 pr_err("Failed to read led_status2 reg, rc=%d\n", rc);
1838 goto exit;
1839 }
1840
1841 if (led_status1)
1842 pr_emerg("led short/open fault detected! led_status1=%x\n",
1843 led_status1);
1844
1845 if (led_status2 & FLASH_LED_VPH_DROOP_FAULT_MASK)
1846 pr_emerg("led vph_droop fault detected!\n");
1847 }
1848
1849 pr_debug("irq handled, irq_type=%x, irq_status=%x\n", irq_type,
1850 irq_status);
1851
1852exit:
1853 return IRQ_HANDLED;
1854}
1855
1856int qpnp_flash_led_register_irq_notifier(struct notifier_block *nb)
1857{
1858 return atomic_notifier_chain_register(&irq_notifier_list, nb);
1859}
1860
1861int qpnp_flash_led_unregister_irq_notifier(struct notifier_block *nb)
1862{
1863 return atomic_notifier_chain_unregister(&irq_notifier_list, nb);
1864}
1865
Subbaraman Narayanamurthyaf8dcb42018-01-17 20:23:47 -08001866static inline u8 get_safety_timer_code(u32 duration_ms)
1867{
1868 if (!duration_ms)
1869 return 0;
1870
1871 return (duration_ms / 10) - 1;
1872}
1873
1874static inline u8 get_vph_droop_thresh_code(u32 val_mv)
1875{
1876 if (!val_mv)
1877 return 0;
1878
1879 return (val_mv / 100) - 25;
1880}
1881
David Collins8885f792017-01-26 14:36:34 -08001882static int qpnp_flash_led_parse_each_led_dt(struct qpnp_flash_led *led,
1883 struct flash_node_data *fnode, struct device_node *node)
1884{
1885 const char *temp_string;
Ankit Sharma8798ab12017-04-06 15:44:09 +05301886 int rc, min_ma;
David Collins8885f792017-01-26 14:36:34 -08001887 u32 val;
Subbaraman Narayanamurthy3f684b22017-03-21 20:49:54 -07001888 bool hw_strobe = 0, edge_trigger = 0, active_high = 0;
Kiran Gunda1c1e21c2017-12-15 09:55:03 +05301889 u8 pmic_subtype = led->pdata->pmic_rev_id->pmic_subtype;
David Collins8885f792017-01-26 14:36:34 -08001890
1891 fnode->pdev = led->pdev;
1892 fnode->cdev.brightness_set = qpnp_flash_led_brightness_set;
1893 fnode->cdev.brightness_get = qpnp_flash_led_brightness_get;
1894
1895 rc = of_property_read_string(node, "qcom,led-name", &fnode->cdev.name);
1896 if (rc < 0) {
1897 pr_err("Unable to read flash LED names\n");
1898 return rc;
1899 }
1900
1901 rc = of_property_read_string(node, "label", &temp_string);
1902 if (!rc) {
1903 if (!strcmp(temp_string, "flash")) {
1904 fnode->type = FLASH_LED_TYPE_FLASH;
1905 } else if (!strcmp(temp_string, "torch")) {
1906 fnode->type = FLASH_LED_TYPE_TORCH;
1907 } else {
1908 pr_err("Wrong flash LED type\n");
1909 return rc;
1910 }
1911 } else {
1912 pr_err("Unable to read flash LED label\n");
1913 return rc;
1914 }
1915
1916 rc = of_property_read_u32(node, "qcom,id", &val);
1917 if (!rc) {
1918 fnode->id = (u8)val;
Kiran Gunda1c1e21c2017-12-15 09:55:03 +05301919
1920 if (pmic_subtype == PMI632_SUBTYPE && fnode->id > 1) {
1921 pr_err("Flash node id = %d not supported\n", fnode->id);
1922 return -EINVAL;
1923 }
David Collins8885f792017-01-26 14:36:34 -08001924 } else {
1925 pr_err("Unable to read flash LED ID\n");
1926 return rc;
1927 }
1928
1929 rc = of_property_read_string(node, "qcom,default-led-trigger",
1930 &fnode->cdev.default_trigger);
1931 if (rc < 0) {
1932 pr_err("Unable to read trigger name\n");
1933 return rc;
1934 }
1935
Kiran Gunda5cadca72017-07-26 14:37:52 +05301936 fnode->default_ires_ua = fnode->ires_ua = FLASH_LED_IRES_DEFAULT_UA;
1937 fnode->default_ires_idx = fnode->ires_idx = FLASH_LED_IRES_DEFAULT_VAL;
David Collins8885f792017-01-26 14:36:34 -08001938 rc = of_property_read_u32(node, "qcom,ires-ua", &val);
1939 if (!rc) {
Kiran Gunda5cadca72017-07-26 14:37:52 +05301940 fnode->default_ires_ua = fnode->ires_ua = val;
1941 fnode->default_ires_idx = fnode->ires_idx =
1942 FLASH_LED_IRES_BASE - (val - FLASH_LED_IRES_MIN_UA) /
1943 FLASH_LED_IRES_DIVISOR;
David Collins8885f792017-01-26 14:36:34 -08001944 } else if (rc != -EINVAL) {
1945 pr_err("Unable to read current resolution rc=%d\n", rc);
1946 return rc;
1947 }
1948
Ankit Sharma8798ab12017-04-06 15:44:09 +05301949 min_ma = fnode->ires_ua / 1000;
David Collins8885f792017-01-26 14:36:34 -08001950 rc = of_property_read_u32(node, "qcom,max-current", &val);
1951 if (!rc) {
Ankit Sharma8798ab12017-04-06 15:44:09 +05301952 if (val < min_ma)
1953 val = min_ma;
David Collins8885f792017-01-26 14:36:34 -08001954 fnode->max_current = val;
1955 fnode->cdev.max_brightness = val;
1956 } else {
1957 pr_err("Unable to read max current, rc=%d\n", rc);
1958 return rc;
1959 }
1960
1961 rc = of_property_read_u32(node, "qcom,current-ma", &val);
1962 if (!rc) {
Ankit Sharma8798ab12017-04-06 15:44:09 +05301963 if (val < min_ma || val > fnode->max_current)
David Collins8885f792017-01-26 14:36:34 -08001964 pr_warn("Invalid operational current specified, capping it\n");
Ankit Sharma8798ab12017-04-06 15:44:09 +05301965 if (val < min_ma)
1966 val = min_ma;
David Collins8885f792017-01-26 14:36:34 -08001967 if (val > fnode->max_current)
1968 val = fnode->max_current;
1969 fnode->current_ma = val;
1970 fnode->cdev.brightness = val;
1971 } else if (rc != -EINVAL) {
1972 pr_err("Unable to read operational current, rc=%d\n", rc);
1973 return rc;
1974 }
1975
1976 fnode->duration = FLASH_LED_SAFETY_TMR_DISABLED;
1977 rc = of_property_read_u32(node, "qcom,duration-ms", &val);
1978 if (!rc) {
Subbaraman Narayanamurthyaf8dcb42018-01-17 20:23:47 -08001979 fnode->duration = get_safety_timer_code(val);
1980 if (fnode->duration)
1981 fnode->duration |= FLASH_LED_SAFETY_TMR_ENABLE;
David Collins8885f792017-01-26 14:36:34 -08001982 } else if (rc == -EINVAL) {
1983 if (fnode->type == FLASH_LED_TYPE_FLASH) {
1984 pr_err("Timer duration is required for flash LED\n");
1985 return rc;
1986 }
1987 } else {
1988 pr_err("Unable to read timer duration\n");
1989 return rc;
1990 }
1991
1992 fnode->hdrm_val = FLASH_LED_HDRM_VOL_DEFAULT_MV;
1993 rc = of_property_read_u32(node, "qcom,hdrm-voltage-mv", &val);
1994 if (!rc) {
1995 val = (val - FLASH_LED_HDRM_VOL_BASE_MV) /
1996 FLASH_LED_HDRM_VOL_STEP_MV;
1997 fnode->hdrm_val = (val << FLASH_LED_HDRM_VOL_SHIFT) &
1998 FLASH_LED_HDRM_VOL_MASK;
1999 } else if (rc != -EINVAL) {
2000 pr_err("Unable to read headroom voltage\n");
2001 return rc;
2002 }
2003
2004 rc = of_property_read_u32(node, "qcom,hdrm-vol-hi-lo-win-mv", &val);
2005 if (!rc) {
2006 fnode->hdrm_val |= (val / FLASH_LED_HDRM_VOL_STEP_MV) &
2007 ~FLASH_LED_HDRM_VOL_MASK;
2008 } else if (rc == -EINVAL) {
2009 fnode->hdrm_val |= FLASH_LED_HDRM_VOL_HI_LO_WIN_DEFAULT_MV;
2010 } else {
2011 pr_err("Unable to read hdrm hi-lo window voltage\n");
2012 return rc;
2013 }
2014
Subbaraman Narayanamurthy3f684b22017-03-21 20:49:54 -07002015 fnode->strobe_sel = SW_STROBE;
2016 rc = of_property_read_u32(node, "qcom,strobe-sel", &val);
2017 if (rc < 0) {
2018 if (rc != -EINVAL) {
2019 pr_err("Unable to read qcom,strobe-sel property\n");
2020 return rc;
2021 }
2022 } else {
2023 if (val < SW_STROBE || val > LPG_STROBE) {
2024 pr_err("Incorrect strobe selection specified %d\n",
2025 val);
2026 return -EINVAL;
2027 }
2028 fnode->strobe_sel = (u8)val;
2029 }
2030
2031 /*
2032 * LPG strobe is allowed only for LED3 and HW strobe option should be
2033 * option 2 or 3.
2034 */
2035 if (fnode->strobe_sel == LPG_STROBE) {
2036 if (led->pdata->hw_strobe_option ==
2037 FLASH_LED_HW_STROBE_OPTION_1) {
2038 pr_err("Incorrect strobe option for LPG strobe\n");
2039 return -EINVAL;
2040 }
2041 if (fnode->id != LED3) {
2042 pr_err("Incorrect LED chosen for LPG strobe\n");
2043 return -EINVAL;
2044 }
2045 }
2046
2047 if (fnode->strobe_sel == HW_STROBE) {
David Collins8885f792017-01-26 14:36:34 -08002048 edge_trigger = of_property_read_bool(node,
2049 "qcom,hw-strobe-edge-trigger");
2050 active_high = !of_property_read_bool(node,
2051 "qcom,hw-strobe-active-low");
Subbaraman Narayanamurthy3f684b22017-03-21 20:49:54 -07002052 hw_strobe = 1;
2053 } else if (fnode->strobe_sel == LPG_STROBE) {
2054 /* LPG strobe requires level trigger and active high */
2055 edge_trigger = 0;
2056 active_high = 1;
2057 hw_strobe = 1;
David Collins8885f792017-01-26 14:36:34 -08002058 }
Subbaraman Narayanamurthy3f684b22017-03-21 20:49:54 -07002059 fnode->strobe_ctrl = (hw_strobe << 2) | (edge_trigger << 1) |
2060 active_high;
David Collins8885f792017-01-26 14:36:34 -08002061
Subbaraman Narayanamurthy58377f02017-03-21 20:38:43 -07002062 rc = led_classdev_register(&led->pdev->dev, &fnode->cdev);
2063 if (rc < 0) {
2064 pr_err("Unable to register led node %d\n", fnode->id);
2065 return rc;
2066 }
2067
2068 fnode->cdev.dev->of_node = node;
2069 fnode->strobe_pinctrl = devm_pinctrl_get(fnode->cdev.dev);
2070 if (IS_ERR_OR_NULL(fnode->strobe_pinctrl)) {
2071 pr_debug("No pinctrl defined for %s, err=%ld\n",
2072 fnode->cdev.name, PTR_ERR(fnode->strobe_pinctrl));
2073 fnode->strobe_pinctrl = NULL;
2074 }
2075
Subbaraman Narayanamurthy3f684b22017-03-21 20:49:54 -07002076 if (fnode->strobe_sel == HW_STROBE) {
David Collins8885f792017-01-26 14:36:34 -08002077 if (of_find_property(node, "qcom,hw-strobe-gpio", NULL)) {
2078 fnode->hw_strobe_gpio = of_get_named_gpio(node,
2079 "qcom,hw-strobe-gpio", 0);
2080 if (fnode->hw_strobe_gpio < 0) {
2081 pr_err("Invalid gpio specified\n");
2082 return fnode->hw_strobe_gpio;
2083 }
2084 gpio_direction_output(fnode->hw_strobe_gpio, 0);
Subbaraman Narayanamurthy58377f02017-03-21 20:38:43 -07002085 } else if (fnode->strobe_pinctrl) {
David Collins8885f792017-01-26 14:36:34 -08002086 fnode->hw_strobe_gpio = -1;
2087 fnode->hw_strobe_state_active =
Subbaraman Narayanamurthy58377f02017-03-21 20:38:43 -07002088 pinctrl_lookup_state(fnode->strobe_pinctrl,
2089 "strobe_enable");
David Collins8885f792017-01-26 14:36:34 -08002090 if (IS_ERR_OR_NULL(fnode->hw_strobe_state_active)) {
2091 pr_err("No active pin for hardware strobe, rc=%ld\n",
2092 PTR_ERR(fnode->hw_strobe_state_active));
2093 fnode->hw_strobe_state_active = NULL;
2094 }
2095
2096 fnode->hw_strobe_state_suspend =
Subbaraman Narayanamurthy58377f02017-03-21 20:38:43 -07002097 pinctrl_lookup_state(fnode->strobe_pinctrl,
2098 "strobe_disable");
David Collins8885f792017-01-26 14:36:34 -08002099 if (IS_ERR_OR_NULL(fnode->hw_strobe_state_suspend)) {
2100 pr_err("No suspend pin for hardware strobe, rc=%ld\n",
2101 PTR_ERR(fnode->hw_strobe_state_suspend)
2102 );
2103 fnode->hw_strobe_state_suspend = NULL;
2104 }
2105 }
2106 }
2107
David Collins8885f792017-01-26 14:36:34 -08002108 return 0;
2109}
2110
2111static int qpnp_flash_led_parse_and_register_switch(struct qpnp_flash_led *led,
2112 struct flash_switch_data *snode,
2113 struct device_node *node)
2114{
2115 int rc = 0, num;
2116 char reg_name[16], reg_sup_name[16];
2117
2118 rc = of_property_read_string(node, "qcom,led-name", &snode->cdev.name);
2119 if (rc < 0) {
2120 pr_err("Failed to read switch node name, rc=%d\n", rc);
2121 return rc;
2122 }
2123
2124 rc = sscanf(snode->cdev.name, "led:switch_%d", &num);
2125 if (!rc) {
2126 pr_err("No number for switch device?\n");
2127 return -EINVAL;
2128 }
2129
2130 rc = of_property_read_string(node, "qcom,default-led-trigger",
2131 &snode->cdev.default_trigger);
2132 if (rc < 0) {
2133 pr_err("Unable to read trigger name, rc=%d\n", rc);
2134 return rc;
2135 }
2136
2137 rc = of_property_read_u32(node, "qcom,led-mask", &snode->led_mask);
2138 if (rc < 0) {
2139 pr_err("Unable to read led mask rc=%d\n", rc);
2140 return rc;
2141 }
2142
Subbaraman Narayanamurthyd737fd52018-01-17 19:58:52 -08002143 snode->symmetry_en = of_property_read_bool(node, "qcom,symmetry-en");
2144
David Collins8885f792017-01-26 14:36:34 -08002145 if (snode->led_mask < 1 || snode->led_mask > 7) {
2146 pr_err("Invalid value for led-mask\n");
2147 return -EINVAL;
2148 }
2149
2150 scnprintf(reg_name, sizeof(reg_name), "switch%d-supply", num);
2151 if (of_find_property(led->pdev->dev.of_node, reg_name, NULL)) {
2152 scnprintf(reg_sup_name, sizeof(reg_sup_name), "switch%d", num);
2153 snode->vreg = devm_regulator_get(&led->pdev->dev, reg_sup_name);
2154 if (IS_ERR_OR_NULL(snode->vreg)) {
2155 rc = PTR_ERR(snode->vreg);
2156 if (rc != -EPROBE_DEFER)
2157 pr_err("Failed to get regulator, rc=%d\n", rc);
2158 snode->vreg = NULL;
2159 return rc;
2160 }
2161 }
2162
2163 snode->pdev = led->pdev;
2164 snode->cdev.brightness_set = qpnp_flash_led_brightness_set;
2165 snode->cdev.brightness_get = qpnp_flash_led_brightness_get;
2166 snode->cdev.flags |= LED_KEEP_TRIGGER;
2167 rc = led_classdev_register(&led->pdev->dev, &snode->cdev);
2168 if (rc < 0) {
2169 pr_err("Unable to register led switch node\n");
2170 return rc;
2171 }
2172
2173 snode->cdev.dev->of_node = node;
Subbaraman Narayanamurthy58377f02017-03-21 20:38:43 -07002174
2175 snode->led_en_pinctrl = devm_pinctrl_get(snode->cdev.dev);
2176 if (IS_ERR_OR_NULL(snode->led_en_pinctrl)) {
2177 pr_debug("No pinctrl defined for %s, err=%ld\n",
2178 snode->cdev.name, PTR_ERR(snode->led_en_pinctrl));
2179 snode->led_en_pinctrl = NULL;
2180 }
2181
2182 if (snode->led_en_pinctrl) {
2183 snode->gpio_state_active =
2184 pinctrl_lookup_state(snode->led_en_pinctrl,
2185 "led_enable");
2186 if (IS_ERR_OR_NULL(snode->gpio_state_active)) {
2187 pr_err("Cannot lookup LED active state\n");
2188 devm_pinctrl_put(snode->led_en_pinctrl);
2189 snode->led_en_pinctrl = NULL;
2190 return PTR_ERR(snode->gpio_state_active);
2191 }
2192
2193 snode->gpio_state_suspend =
2194 pinctrl_lookup_state(snode->led_en_pinctrl,
2195 "led_disable");
2196 if (IS_ERR_OR_NULL(snode->gpio_state_suspend)) {
2197 pr_err("Cannot lookup LED disable state\n");
2198 devm_pinctrl_put(snode->led_en_pinctrl);
2199 snode->led_en_pinctrl = NULL;
2200 return PTR_ERR(snode->gpio_state_suspend);
2201 }
2202 }
2203
David Collins8885f792017-01-26 14:36:34 -08002204 return 0;
2205}
2206
2207static int get_code_from_table(int *table, int len, int value)
2208{
2209 int i;
2210
2211 for (i = 0; i < len; i++) {
2212 if (value == table[i])
2213 break;
2214 }
2215
2216 if (i == len) {
2217 pr_err("Couldn't find %d from table\n", value);
2218 return -ENODATA;
2219 }
2220
2221 return i;
2222}
2223
2224static int qpnp_flash_led_parse_common_dt(struct qpnp_flash_led *led,
2225 struct device_node *node)
2226{
2227 struct device_node *revid_node;
2228 int rc;
2229 u32 val;
Kiran Gunda1c1e21c2017-12-15 09:55:03 +05302230 u8 pmic_subtype;
David Collins8885f792017-01-26 14:36:34 -08002231 bool short_circuit_det, open_circuit_det, vph_droop_det;
2232
2233 revid_node = of_parse_phandle(node, "qcom,pmic-revid", 0);
2234 if (!revid_node) {
2235 pr_err("Missing qcom,pmic-revid property - driver failed\n");
2236 return -EINVAL;
2237 }
2238
2239 led->pdata->pmic_rev_id = get_revid_data(revid_node);
2240 if (IS_ERR_OR_NULL(led->pdata->pmic_rev_id)) {
2241 pr_err("Unable to get pmic_revid rc=%ld\n",
2242 PTR_ERR(led->pdata->pmic_rev_id));
2243 /*
2244 * the revid peripheral must be registered, any failure
2245 * here only indicates that the rev-id module has not
2246 * probed yet.
2247 */
2248 return -EPROBE_DEFER;
2249 }
2250
Kiran Gunda1c1e21c2017-12-15 09:55:03 +05302251 pmic_subtype = led->pdata->pmic_rev_id->pmic_subtype;
David Collins8885f792017-01-26 14:36:34 -08002252 pr_debug("PMIC subtype %d Digital major %d\n",
2253 led->pdata->pmic_rev_id->pmic_subtype,
2254 led->pdata->pmic_rev_id->rev4);
David Collins8885f792017-01-26 14:36:34 -08002255 led->pdata->hdrm_auto_mode_en = of_property_read_bool(node,
2256 "qcom,hdrm-auto-mode");
2257
2258 led->pdata->isc_delay = FLASH_LED_ISC_DELAY_DEFAULT;
2259 rc = of_property_read_u32(node, "qcom,isc-delay-us", &val);
2260 if (!rc) {
2261 led->pdata->isc_delay =
2262 val >> FLASH_LED_ISC_WARMUP_DELAY_SHIFT;
2263 } else if (rc != -EINVAL) {
2264 pr_err("Unable to read ISC delay, rc=%d\n", rc);
2265 return rc;
2266 }
2267
2268 led->pdata->warmup_delay = FLASH_LED_WARMUP_DELAY_DEFAULT;
2269 rc = of_property_read_u32(node, "qcom,warmup-delay-us", &val);
2270 if (!rc) {
2271 led->pdata->warmup_delay =
2272 val >> FLASH_LED_ISC_WARMUP_DELAY_SHIFT;
2273 } else if (rc != -EINVAL) {
2274 pr_err("Unable to read WARMUP delay, rc=%d\n", rc);
2275 return rc;
2276 }
2277
2278 short_circuit_det =
2279 of_property_read_bool(node, "qcom,short-circuit-det");
2280 open_circuit_det = of_property_read_bool(node, "qcom,open-circuit-det");
2281 vph_droop_det = of_property_read_bool(node, "qcom,vph-droop-det");
2282 led->pdata->current_derate_en_cfg = (vph_droop_det << 2) |
2283 (open_circuit_det << 1) | short_circuit_det;
2284
2285 led->pdata->thermal_derate_en =
2286 of_property_read_bool(node, "qcom,thermal-derate-en");
2287
2288 if (led->pdata->thermal_derate_en) {
2289 led->pdata->thermal_derate_current =
2290 devm_kcalloc(&led->pdev->dev,
2291 FLASH_LED_THERMAL_OTST_LEVELS,
2292 sizeof(int), GFP_KERNEL);
2293 if (!led->pdata->thermal_derate_current)
2294 return -ENOMEM;
2295
2296 rc = of_property_read_u32_array(node,
2297 "qcom,thermal-derate-current",
2298 led->pdata->thermal_derate_current,
2299 FLASH_LED_THERMAL_OTST_LEVELS);
2300 if (rc < 0) {
2301 pr_err("Unable to read thermal current limits, rc=%d\n",
2302 rc);
2303 return rc;
2304 }
2305 }
2306
2307 led->pdata->otst_ramp_bkup_en =
2308 !of_property_read_bool(node, "qcom,otst-ramp-back-up-dis");
2309
2310 led->pdata->thermal_derate_slow = -EINVAL;
2311 rc = of_property_read_u32(node, "qcom,thermal-derate-slow", &val);
2312 if (!rc) {
2313 if (val < 0 || val > THERMAL_DERATE_SLOW_MAX) {
2314 pr_err("Invalid thermal_derate_slow %d\n", val);
2315 return -EINVAL;
2316 }
2317
2318 led->pdata->thermal_derate_slow =
2319 get_code_from_table(thermal_derate_slow_table,
2320 ARRAY_SIZE(thermal_derate_slow_table), val);
2321 } else if (rc != -EINVAL) {
2322 pr_err("Unable to read thermal derate slow, rc=%d\n", rc);
2323 return rc;
2324 }
2325
2326 led->pdata->thermal_derate_fast = -EINVAL;
2327 rc = of_property_read_u32(node, "qcom,thermal-derate-fast", &val);
2328 if (!rc) {
2329 if (val < 0 || val > THERMAL_DERATE_FAST_MAX) {
2330 pr_err("Invalid thermal_derate_fast %d\n", val);
2331 return -EINVAL;
2332 }
2333
2334 led->pdata->thermal_derate_fast =
2335 get_code_from_table(thermal_derate_fast_table,
2336 ARRAY_SIZE(thermal_derate_fast_table), val);
2337 } else if (rc != -EINVAL) {
2338 pr_err("Unable to read thermal derate fast, rc=%d\n", rc);
2339 return rc;
2340 }
2341
2342 led->pdata->thermal_debounce = -EINVAL;
2343 rc = of_property_read_u32(node, "qcom,thermal-debounce", &val);
2344 if (!rc) {
2345 if (val < 0 || val > THERMAL_DEBOUNCE_TIME_MAX) {
2346 pr_err("Invalid thermal_debounce %d\n", val);
2347 return -EINVAL;
2348 }
2349
2350 if (val >= 0 && val < 16)
2351 led->pdata->thermal_debounce = 0;
2352 else
2353 led->pdata->thermal_debounce = ilog2(val) - 3;
2354 } else if (rc != -EINVAL) {
2355 pr_err("Unable to read thermal debounce, rc=%d\n", rc);
2356 return rc;
2357 }
2358
2359 led->pdata->thermal_hysteresis = -EINVAL;
2360 rc = of_property_read_u32(node, "qcom,thermal-hysteresis", &val);
2361 if (!rc) {
Kiran Gunda1c1e21c2017-12-15 09:55:03 +05302362 if (pmic_subtype == PM660L_SUBTYPE)
David Collins8885f792017-01-26 14:36:34 -08002363 val = THERMAL_HYST_TEMP_TO_VAL(val, 20);
2364 else
2365 val = THERMAL_HYST_TEMP_TO_VAL(val, 15);
2366
2367 if (val < 0 || val > THERMAL_DERATE_HYSTERESIS_MAX) {
2368 pr_err("Invalid thermal_derate_hysteresis %d\n", val);
2369 return -EINVAL;
2370 }
2371
2372 led->pdata->thermal_hysteresis = val;
2373 } else if (rc != -EINVAL) {
2374 pr_err("Unable to read thermal hysteresis, rc=%d\n", rc);
2375 return rc;
2376 }
2377
2378 led->pdata->thermal_thrsh1 = -EINVAL;
2379 rc = of_property_read_u32(node, "qcom,thermal-thrsh1", &val);
2380 if (!rc) {
2381 led->pdata->thermal_thrsh1 =
2382 get_code_from_table(otst1_threshold_table,
2383 ARRAY_SIZE(otst1_threshold_table), val);
2384 } else if (rc != -EINVAL) {
2385 pr_err("Unable to read thermal thrsh1, rc=%d\n", rc);
2386 return rc;
2387 }
2388
2389 led->pdata->thermal_thrsh2 = -EINVAL;
2390 rc = of_property_read_u32(node, "qcom,thermal-thrsh2", &val);
2391 if (!rc) {
2392 led->pdata->thermal_thrsh2 =
2393 get_code_from_table(otst2_threshold_table,
2394 ARRAY_SIZE(otst2_threshold_table), val);
2395 } else if (rc != -EINVAL) {
2396 pr_err("Unable to read thermal thrsh2, rc=%d\n", rc);
2397 return rc;
2398 }
2399
2400 led->pdata->thermal_thrsh3 = -EINVAL;
2401 rc = of_property_read_u32(node, "qcom,thermal-thrsh3", &val);
2402 if (!rc) {
2403 led->pdata->thermal_thrsh3 =
2404 get_code_from_table(otst3_threshold_table,
2405 ARRAY_SIZE(otst3_threshold_table), val);
2406 } else if (rc != -EINVAL) {
2407 pr_err("Unable to read thermal thrsh3, rc=%d\n", rc);
2408 return rc;
2409 }
2410
2411 led->pdata->vph_droop_debounce = FLASH_LED_VPH_DROOP_DEBOUNCE_DEFAULT;
2412 rc = of_property_read_u32(node, "qcom,vph-droop-debounce-us", &val);
2413 if (!rc) {
2414 led->pdata->vph_droop_debounce =
2415 VPH_DROOP_DEBOUNCE_US_TO_VAL(val);
2416 } else if (rc != -EINVAL) {
2417 pr_err("Unable to read VPH droop debounce, rc=%d\n", rc);
2418 return rc;
2419 }
2420
2421 if (led->pdata->vph_droop_debounce > FLASH_LED_DEBOUNCE_MAX) {
2422 pr_err("Invalid VPH droop debounce specified\n");
2423 return -EINVAL;
2424 }
2425
Kiran Gunda1c1e21c2017-12-15 09:55:03 +05302426 if (pmic_subtype == PMI632_SUBTYPE)
2427 led->pdata->vph_droop_threshold =
2428 BHARGER_FLASH_LED_VPH_DROOP_THRESH_DEFAULT;
2429 else
2430 led->pdata->vph_droop_threshold =
2431 FLASH_LED_VPH_DROOP_THRESH_DEFAULT;
2432
David Collins8885f792017-01-26 14:36:34 -08002433 rc = of_property_read_u32(node, "qcom,vph-droop-threshold-mv", &val);
2434 if (!rc) {
2435 led->pdata->vph_droop_threshold =
Subbaraman Narayanamurthyaf8dcb42018-01-17 20:23:47 -08002436 get_vph_droop_thresh_code(val);
David Collins8885f792017-01-26 14:36:34 -08002437 } else if (rc != -EINVAL) {
2438 pr_err("Unable to read VPH droop threshold, rc=%d\n", rc);
2439 return rc;
2440 }
2441
2442 if (led->pdata->vph_droop_threshold > FLASH_LED_VPH_DROOP_THRESH_MAX) {
2443 pr_err("Invalid VPH droop threshold specified\n");
2444 return -EINVAL;
2445 }
2446
2447 led->pdata->vph_droop_hysteresis =
2448 FLASH_LED_VPH_DROOP_HYST_DEFAULT;
2449 rc = of_property_read_u32(node, "qcom,vph-droop-hysteresis-mv", &val);
2450 if (!rc) {
2451 led->pdata->vph_droop_hysteresis =
2452 VPH_DROOP_HYST_MV_TO_VAL(val);
2453 } else if (rc != -EINVAL) {
2454 pr_err("Unable to read VPH droop hysteresis, rc=%d\n", rc);
2455 return rc;
2456 }
2457
2458 if (led->pdata->vph_droop_hysteresis > FLASH_LED_HYSTERESIS_MAX) {
2459 pr_err("Invalid VPH droop hysteresis specified\n");
2460 return -EINVAL;
2461 }
2462
2463 led->pdata->vph_droop_hysteresis <<= FLASH_LED_VPH_DROOP_HYST_SHIFT;
2464
Subbaraman Narayanamurthy3f684b22017-03-21 20:49:54 -07002465 led->pdata->hw_strobe_option = -EINVAL;
David Collins8885f792017-01-26 14:36:34 -08002466 rc = of_property_read_u32(node, "qcom,hw-strobe-option", &val);
2467 if (!rc) {
Subbaraman Narayanamurthy3f684b22017-03-21 20:49:54 -07002468 led->pdata->hw_strobe_option = val;
David Collins8885f792017-01-26 14:36:34 -08002469 } else if (rc != -EINVAL) {
2470 pr_err("Unable to parse hw strobe option, rc=%d\n", rc);
2471 return rc;
2472 }
2473
2474 rc = of_property_read_u32(node, "qcom,led1n2-iclamp-low-ma", &val);
2475 if (!rc) {
2476 led->pdata->led1n2_iclamp_low_ma = val;
2477 } else if (rc != -EINVAL) {
2478 pr_err("Unable to read led1n2_iclamp_low current, rc=%d\n", rc);
2479 return rc;
2480 }
2481
2482 rc = of_property_read_u32(node, "qcom,led1n2-iclamp-mid-ma", &val);
2483 if (!rc) {
2484 led->pdata->led1n2_iclamp_mid_ma = val;
2485 } else if (rc != -EINVAL) {
2486 pr_err("Unable to read led1n2_iclamp_mid current, rc=%d\n", rc);
2487 return rc;
2488 }
2489
2490 rc = of_property_read_u32(node, "qcom,led3-iclamp-low-ma", &val);
2491 if (!rc) {
2492 led->pdata->led3_iclamp_low_ma = val;
2493 } else if (rc != -EINVAL) {
2494 pr_err("Unable to read led3_iclamp_low current, rc=%d\n", rc);
2495 return rc;
2496 }
2497
2498 rc = of_property_read_u32(node, "qcom,led3-iclamp-mid-ma", &val);
2499 if (!rc) {
2500 led->pdata->led3_iclamp_mid_ma = val;
2501 } else if (rc != -EINVAL) {
2502 pr_err("Unable to read led3_iclamp_mid current, rc=%d\n", rc);
2503 return rc;
2504 }
2505
2506 led->pdata->vled_max_uv = FLASH_LED_VLED_MAX_DEFAULT_UV;
2507 rc = of_property_read_u32(node, "qcom,vled-max-uv", &val);
2508 if (!rc) {
2509 led->pdata->vled_max_uv = val;
2510 } else if (rc != -EINVAL) {
2511 pr_err("Unable to parse vled_max voltage, rc=%d\n", rc);
2512 return rc;
2513 }
2514
2515 led->pdata->ibatt_ocp_threshold_ua =
2516 FLASH_LED_IBATT_OCP_THRESH_DEFAULT_UA;
2517 rc = of_property_read_u32(node, "qcom,ibatt-ocp-threshold-ua", &val);
2518 if (!rc) {
2519 led->pdata->ibatt_ocp_threshold_ua = val;
2520 } else if (rc != -EINVAL) {
2521 pr_err("Unable to parse ibatt_ocp threshold, rc=%d\n", rc);
2522 return rc;
2523 }
2524
2525 led->pdata->rpara_uohm = FLASH_LED_RPARA_DEFAULT_UOHM;
2526 rc = of_property_read_u32(node, "qcom,rparasitic-uohm", &val);
2527 if (!rc) {
2528 led->pdata->rpara_uohm = val;
2529 } else if (rc != -EINVAL) {
2530 pr_err("Unable to parse rparasitic, rc=%d\n", rc);
2531 return rc;
2532 }
2533
2534 led->pdata->lmh_ocv_threshold_uv =
2535 FLASH_LED_LMH_OCV_THRESH_DEFAULT_UV;
2536 rc = of_property_read_u32(node, "qcom,lmh-ocv-threshold-uv", &val);
2537 if (!rc) {
2538 led->pdata->lmh_ocv_threshold_uv = val;
2539 } else if (rc != -EINVAL) {
2540 pr_err("Unable to parse lmh ocv threshold, rc=%d\n", rc);
2541 return rc;
2542 }
2543
2544 led->pdata->lmh_rbatt_threshold_uohm =
2545 FLASH_LED_LMH_RBATT_THRESH_DEFAULT_UOHM;
2546 rc = of_property_read_u32(node, "qcom,lmh-rbatt-threshold-uohm", &val);
2547 if (!rc) {
2548 led->pdata->lmh_rbatt_threshold_uohm = val;
2549 } else if (rc != -EINVAL) {
2550 pr_err("Unable to parse lmh rbatt threshold, rc=%d\n", rc);
2551 return rc;
2552 }
2553
2554 led->pdata->lmh_level = FLASH_LED_LMH_LEVEL_DEFAULT;
2555 rc = of_property_read_u32(node, "qcom,lmh-level", &val);
2556 if (!rc) {
2557 led->pdata->lmh_level = val;
2558 } else if (rc != -EINVAL) {
2559 pr_err("Unable to parse lmh_level, rc=%d\n", rc);
2560 return rc;
2561 }
2562
Ankit Sharmaa7153c32017-03-22 19:04:52 +05302563 led->pdata->lmh_mitigation_sel = FLASH_LED_LMH_MITIGATION_SEL_DEFAULT;
David Collins8885f792017-01-26 14:36:34 -08002564 rc = of_property_read_u32(node, "qcom,lmh-mitigation-sel", &val);
2565 if (!rc) {
2566 led->pdata->lmh_mitigation_sel = val;
2567 } else if (rc != -EINVAL) {
2568 pr_err("Unable to parse lmh_mitigation_sel, rc=%d\n", rc);
2569 return rc;
2570 }
2571
2572 if (led->pdata->lmh_mitigation_sel > FLASH_LED_MITIGATION_SEL_MAX) {
2573 pr_err("Invalid lmh_mitigation_sel specified\n");
2574 return -EINVAL;
2575 }
2576
Kiran Gunda1c1e21c2017-12-15 09:55:03 +05302577 if (pmic_subtype == PMI632_SUBTYPE)
2578 led->pdata->chgr_mitigation_sel =
2579 FLASH_DISABLE_CHARGER_MITIGATION;
2580 else
2581 led->pdata->chgr_mitigation_sel = FLASH_SW_CHARGER_MITIGATION;
2582
David Collins8885f792017-01-26 14:36:34 -08002583 rc = of_property_read_u32(node, "qcom,chgr-mitigation-sel", &val);
2584 if (!rc) {
2585 led->pdata->chgr_mitigation_sel = val;
2586 } else if (rc != -EINVAL) {
2587 pr_err("Unable to parse chgr_mitigation_sel, rc=%d\n", rc);
2588 return rc;
2589 }
2590
2591 if (led->pdata->chgr_mitigation_sel > FLASH_LED_MITIGATION_SEL_MAX) {
2592 pr_err("Invalid chgr_mitigation_sel specified\n");
2593 return -EINVAL;
2594 }
2595
Ankit Sharmaa7153c32017-03-22 19:04:52 +05302596 led->pdata->iled_thrsh_val = FLASH_LED_CHGR_MITIGATION_THRSH_DEFAULT;
David Collins8885f792017-01-26 14:36:34 -08002597 rc = of_property_read_u32(node, "qcom,iled-thrsh-ma", &val);
2598 if (!rc) {
2599 led->pdata->iled_thrsh_val = MITIGATION_THRSH_MA_TO_VAL(val);
2600 } else if (rc != -EINVAL) {
2601 pr_err("Unable to parse iled_thrsh_val, rc=%d\n", rc);
2602 return rc;
2603 }
2604
Ankit Sharmaa7153c32017-03-22 19:04:52 +05302605 if (led->pdata->iled_thrsh_val > FLASH_LED_CHGR_MITIGATION_THRSH_MAX) {
David Collins8885f792017-01-26 14:36:34 -08002606 pr_err("Invalid iled_thrsh_val specified\n");
2607 return -EINVAL;
2608 }
2609
Kiran Gunda1c1e21c2017-12-15 09:55:03 +05302610 led->pdata->bst_pwm_ovrhd_uv = FLASH_BST_PWM_OVRHD_MIN_UV;
2611 rc = of_property_read_u32(node, "qcom,bst-pwm-ovrhd-uv", &val);
2612 if (!rc) {
2613 if (val >= FLASH_BST_PWM_OVRHD_MIN_UV &&
2614 val <= FLASH_BST_PWM_OVRHD_MAX_UV)
2615 led->pdata->bst_pwm_ovrhd_uv = val;
2616 }
2617
David Collins8885f792017-01-26 14:36:34 -08002618 led->pdata->all_ramp_up_done_irq =
2619 of_irq_get_byname(node, "all-ramp-up-done-irq");
2620 if (led->pdata->all_ramp_up_done_irq < 0)
2621 pr_debug("all-ramp-up-done-irq not used\n");
2622
2623 led->pdata->all_ramp_down_done_irq =
2624 of_irq_get_byname(node, "all-ramp-down-done-irq");
2625 if (led->pdata->all_ramp_down_done_irq < 0)
2626 pr_debug("all-ramp-down-done-irq not used\n");
2627
2628 led->pdata->led_fault_irq =
2629 of_irq_get_byname(node, "led-fault-irq");
2630 if (led->pdata->led_fault_irq < 0)
2631 pr_debug("led-fault-irq not used\n");
2632
2633 return 0;
2634}
2635
2636static int qpnp_flash_led_probe(struct platform_device *pdev)
2637{
2638 struct qpnp_flash_led *led;
2639 struct device_node *node, *temp;
2640 const char *temp_string;
2641 unsigned int base;
2642 int rc, i = 0, j = 0;
2643
2644 node = pdev->dev.of_node;
2645 if (!node) {
2646 pr_err("No flash LED nodes defined\n");
2647 return -ENODEV;
2648 }
2649
2650 rc = of_property_read_u32(node, "reg", &base);
2651 if (rc < 0) {
2652 pr_err("Couldn't find reg in node %s, rc = %d\n",
2653 node->full_name, rc);
2654 return rc;
2655 }
2656
2657 led = devm_kzalloc(&pdev->dev, sizeof(struct qpnp_flash_led),
2658 GFP_KERNEL);
2659 if (!led)
2660 return -ENOMEM;
2661
2662 led->regmap = dev_get_regmap(pdev->dev.parent, NULL);
2663 if (!led->regmap) {
2664 pr_err("Couldn't get parent's regmap\n");
2665 return -EINVAL;
2666 }
2667
2668 led->base = base;
2669 led->pdev = pdev;
2670 led->pdata = devm_kzalloc(&pdev->dev,
2671 sizeof(struct flash_led_platform_data), GFP_KERNEL);
2672 if (!led->pdata)
2673 return -ENOMEM;
2674
Kiran Gundabf1e6c02018-01-17 17:50:20 +05302675 qpnp_flash_led_prepare = qpnp_flash_led_prepare_v2;
David Collins8885f792017-01-26 14:36:34 -08002676 rc = qpnp_flash_led_parse_common_dt(led, node);
2677 if (rc < 0) {
2678 pr_err("Failed to parse common flash LED device tree\n");
2679 return rc;
2680 }
2681
2682 for_each_available_child_of_node(node, temp) {
2683 rc = of_property_read_string(temp, "label", &temp_string);
2684 if (rc < 0) {
2685 pr_err("Failed to parse label, rc=%d\n", rc);
2686 return rc;
2687 }
2688
2689 if (!strcmp("switch", temp_string)) {
2690 led->num_snodes++;
2691 } else if (!strcmp("flash", temp_string) ||
2692 !strcmp("torch", temp_string)) {
2693 led->num_fnodes++;
2694 } else {
2695 pr_err("Invalid label for led node\n");
2696 return -EINVAL;
2697 }
2698 }
2699
2700 if (!led->num_fnodes) {
2701 pr_err("No LED nodes defined\n");
2702 return -ECHILD;
2703 }
2704
2705 led->fnode = devm_kcalloc(&pdev->dev, led->num_fnodes,
2706 sizeof(*led->fnode),
2707 GFP_KERNEL);
2708 if (!led->fnode)
2709 return -ENOMEM;
2710
2711 led->snode = devm_kcalloc(&pdev->dev, led->num_snodes,
2712 sizeof(*led->snode),
2713 GFP_KERNEL);
2714 if (!led->snode)
2715 return -ENOMEM;
2716
2717 temp = NULL;
2718 i = 0;
2719 j = 0;
2720 for_each_available_child_of_node(node, temp) {
2721 rc = of_property_read_string(temp, "label", &temp_string);
2722 if (rc < 0) {
2723 pr_err("Failed to parse label, rc=%d\n", rc);
2724 return rc;
2725 }
2726
2727 if (!strcmp("flash", temp_string) ||
2728 !strcmp("torch", temp_string)) {
2729 rc = qpnp_flash_led_parse_each_led_dt(led,
Subbaraman Narayanamurthy01c99612017-04-03 12:26:06 -07002730 &led->fnode[i], temp);
David Collins8885f792017-01-26 14:36:34 -08002731 if (rc < 0) {
2732 pr_err("Unable to parse flash node %d rc=%d\n",
2733 i, rc);
2734 goto error_led_register;
2735 }
Subbaraman Narayanamurthy01c99612017-04-03 12:26:06 -07002736 i++;
David Collins8885f792017-01-26 14:36:34 -08002737 }
2738
2739 if (!strcmp("switch", temp_string)) {
2740 rc = qpnp_flash_led_parse_and_register_switch(led,
Subbaraman Narayanamurthy01c99612017-04-03 12:26:06 -07002741 &led->snode[j], temp);
David Collins8885f792017-01-26 14:36:34 -08002742 if (rc < 0) {
2743 pr_err("Unable to parse and register switch node, rc=%d\n",
2744 rc);
2745 goto error_switch_register;
2746 }
Subbaraman Narayanamurthy01c99612017-04-03 12:26:06 -07002747 j++;
David Collins8885f792017-01-26 14:36:34 -08002748 }
2749 }
2750
2751 /* setup irqs */
2752 if (led->pdata->all_ramp_up_done_irq >= 0) {
2753 rc = devm_request_threaded_irq(&led->pdev->dev,
2754 led->pdata->all_ramp_up_done_irq,
2755 NULL, qpnp_flash_led_irq_handler,
2756 IRQF_ONESHOT,
2757 "qpnp_flash_led_all_ramp_up_done_irq", led);
2758 if (rc < 0) {
2759 pr_err("Unable to request all_ramp_up_done(%d) IRQ(err:%d)\n",
2760 led->pdata->all_ramp_up_done_irq, rc);
2761 goto error_switch_register;
2762 }
2763 }
2764
2765 if (led->pdata->all_ramp_down_done_irq >= 0) {
2766 rc = devm_request_threaded_irq(&led->pdev->dev,
2767 led->pdata->all_ramp_down_done_irq,
2768 NULL, qpnp_flash_led_irq_handler,
2769 IRQF_ONESHOT,
2770 "qpnp_flash_led_all_ramp_down_done_irq", led);
2771 if (rc < 0) {
2772 pr_err("Unable to request all_ramp_down_done(%d) IRQ(err:%d)\n",
2773 led->pdata->all_ramp_down_done_irq, rc);
2774 goto error_switch_register;
2775 }
2776 }
2777
2778 if (led->pdata->led_fault_irq >= 0) {
2779 rc = devm_request_threaded_irq(&led->pdev->dev,
2780 led->pdata->led_fault_irq,
2781 NULL, qpnp_flash_led_irq_handler,
2782 IRQF_ONESHOT,
2783 "qpnp_flash_led_fault_irq", led);
2784 if (rc < 0) {
2785 pr_err("Unable to request led_fault(%d) IRQ(err:%d)\n",
2786 led->pdata->led_fault_irq, rc);
2787 goto error_switch_register;
2788 }
2789 }
2790
2791 led->bms_psy = power_supply_get_by_name("bms");
2792 if (!led->bms_psy) {
2793 rc = flash_led_psy_register_notifier(led);
2794 if (rc < 0) {
2795 pr_err("Couldn't register psy notifier, rc = %d\n", rc);
2796 goto error_switch_register;
2797 }
2798 }
2799
2800 rc = qpnp_flash_led_init_settings(led);
2801 if (rc < 0) {
2802 pr_err("Failed to initialize flash LED, rc=%d\n", rc);
2803 goto unreg_notifier;
2804 }
2805
2806 for (i = 0; i < led->num_snodes; i++) {
2807 for (j = 0; j < ARRAY_SIZE(qpnp_flash_led_attrs); j++) {
2808 rc = sysfs_create_file(&led->snode[i].cdev.dev->kobj,
2809 &qpnp_flash_led_attrs[j].attr);
2810 if (rc < 0) {
2811 pr_err("sysfs creation failed, rc=%d\n", rc);
2812 goto sysfs_fail;
2813 }
2814 }
2815 }
2816
2817 spin_lock_init(&led->lock);
2818
2819 dev_set_drvdata(&pdev->dev, led);
2820
2821 return 0;
2822
2823sysfs_fail:
2824 for (--j; j >= 0; j--)
2825 sysfs_remove_file(&led->snode[i].cdev.dev->kobj,
2826 &qpnp_flash_led_attrs[j].attr);
2827
2828 for (--i; i >= 0; i--) {
2829 for (j = 0; j < ARRAY_SIZE(qpnp_flash_led_attrs); j++)
2830 sysfs_remove_file(&led->snode[i].cdev.dev->kobj,
2831 &qpnp_flash_led_attrs[j].attr);
2832 }
2833
2834 i = led->num_snodes;
2835unreg_notifier:
2836 power_supply_unreg_notifier(&led->nb);
2837error_switch_register:
2838 while (i > 0)
2839 led_classdev_unregister(&led->snode[--i].cdev);
2840 i = led->num_fnodes;
2841error_led_register:
2842 while (i > 0)
2843 led_classdev_unregister(&led->fnode[--i].cdev);
2844
2845 return rc;
2846}
2847
2848static int qpnp_flash_led_remove(struct platform_device *pdev)
2849{
2850 struct qpnp_flash_led *led = dev_get_drvdata(&pdev->dev);
2851 int i, j;
2852
2853 for (i = 0; i < led->num_snodes; i++) {
2854 for (j = 0; j < ARRAY_SIZE(qpnp_flash_led_attrs); j++)
2855 sysfs_remove_file(&led->snode[i].cdev.dev->kobj,
2856 &qpnp_flash_led_attrs[j].attr);
2857
2858 if (led->snode[i].regulator_on)
2859 qpnp_flash_led_regulator_enable(led,
2860 &led->snode[i], false);
2861 }
2862
2863 while (i > 0)
2864 led_classdev_unregister(&led->snode[--i].cdev);
2865
2866 i = led->num_fnodes;
2867 while (i > 0)
2868 led_classdev_unregister(&led->fnode[--i].cdev);
2869
2870 power_supply_unreg_notifier(&led->nb);
2871 return 0;
2872}
2873
2874const struct of_device_id qpnp_flash_led_match_table[] = {
2875 { .compatible = "qcom,qpnp-flash-led-v2",},
2876 { },
2877};
2878
2879static struct platform_driver qpnp_flash_led_driver = {
2880 .driver = {
2881 .name = "qcom,qpnp-flash-led-v2",
2882 .of_match_table = qpnp_flash_led_match_table,
2883 },
2884 .probe = qpnp_flash_led_probe,
2885 .remove = qpnp_flash_led_remove,
2886};
2887
2888static int __init qpnp_flash_led_init(void)
2889{
2890 return platform_driver_register(&qpnp_flash_led_driver);
2891}
2892late_initcall(qpnp_flash_led_init);
2893
2894static void __exit qpnp_flash_led_exit(void)
2895{
2896 platform_driver_unregister(&qpnp_flash_led_driver);
2897}
2898module_exit(qpnp_flash_led_exit);
2899
2900MODULE_DESCRIPTION("QPNP Flash LED driver v2");
2901MODULE_LICENSE("GPL v2");
2902MODULE_ALIAS("leds:leds-qpnp-flash-v2");