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