blob: 1a2aea98a2c8f6e44b2313e0a007f49f1ed7fff2 [file] [log] [blame]
David Collins8885f792017-01-26 14:36:34 -08001/* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
2 *
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)
37#define FLASH_LED_REG_LED_STATUS2(base) (base + 0x09)
38#define FLASH_LED_REG_INT_RT_STS(base) (base + 0x10)
39#define FLASH_LED_REG_SAFETY_TMR(base) (base + 0x40)
40#define FLASH_LED_REG_TGR_CURRENT(base) (base + 0x43)
41#define FLASH_LED_REG_MOD_CTRL(base) (base + 0x46)
42#define FLASH_LED_REG_IRES(base) (base + 0x47)
43#define FLASH_LED_REG_STROBE_CFG(base) (base + 0x48)
44#define FLASH_LED_REG_STROBE_CTRL(base) (base + 0x49)
45#define FLASH_LED_EN_LED_CTRL(base) (base + 0x4C)
46#define FLASH_LED_REG_HDRM_PRGM(base) (base + 0x4D)
47#define FLASH_LED_REG_HDRM_AUTO_MODE_CTRL(base) (base + 0x50)
48#define FLASH_LED_REG_WARMUP_DELAY(base) (base + 0x51)
49#define FLASH_LED_REG_ISC_DELAY(base) (base + 0x52)
50#define FLASH_LED_REG_THERMAL_RMP_DN_RATE(base) (base + 0x55)
51#define FLASH_LED_REG_THERMAL_THRSH1(base) (base + 0x56)
52#define FLASH_LED_REG_THERMAL_THRSH2(base) (base + 0x57)
53#define FLASH_LED_REG_THERMAL_THRSH3(base) (base + 0x58)
54#define FLASH_LED_REG_THERMAL_HYSTERESIS(base) (base + 0x59)
55#define FLASH_LED_REG_THERMAL_DEBOUNCE(base) (base + 0x5A)
56#define FLASH_LED_REG_VPH_DROOP_THRESHOLD(base) (base + 0x61)
57#define FLASH_LED_REG_VPH_DROOP_DEBOUNCE(base) (base + 0x62)
58#define FLASH_LED_REG_ILED_GRT_THRSH(base) (base + 0x67)
59#define FLASH_LED_REG_LED1N2_ICLAMP_LOW(base) (base + 0x68)
60#define FLASH_LED_REG_LED1N2_ICLAMP_MID(base) (base + 0x69)
61#define FLASH_LED_REG_LED3_ICLAMP_LOW(base) (base + 0x6A)
62#define FLASH_LED_REG_LED3_ICLAMP_MID(base) (base + 0x6B)
63#define FLASH_LED_REG_MITIGATION_SEL(base) (base + 0x6E)
64#define FLASH_LED_REG_MITIGATION_SW(base) (base + 0x6F)
65#define FLASH_LED_REG_LMH_LEVEL(base) (base + 0x70)
Subbaraman Narayanamurthy3f684b22017-03-21 20:49:54 -070066#define FLASH_LED_REG_MULTI_STROBE_CTRL(base) (base + 0x71)
67#define FLASH_LED_REG_LPG_INPUT_CTRL(base) (base + 0x72)
David Collins8885f792017-01-26 14:36:34 -080068#define FLASH_LED_REG_CURRENT_DERATE_EN(base) (base + 0x76)
69
70#define FLASH_LED_HDRM_VOL_MASK GENMASK(7, 4)
71#define FLASH_LED_CURRENT_MASK GENMASK(6, 0)
Subbaraman Narayanamurthy3f684b22017-03-21 20:49:54 -070072#define FLASH_LED_STROBE_MASK GENMASK(1, 0)
David Collins8885f792017-01-26 14:36:34 -080073#define FLASH_HW_STROBE_MASK GENMASK(2, 0)
74#define FLASH_LED_ISC_WARMUP_DELAY_MASK GENMASK(1, 0)
75#define FLASH_LED_CURRENT_DERATE_EN_MASK GENMASK(2, 0)
76#define FLASH_LED_VPH_DROOP_DEBOUNCE_MASK GENMASK(1, 0)
77#define FLASH_LED_CHGR_MITIGATION_SEL_MASK GENMASK(5, 4)
78#define FLASH_LED_LMH_MITIGATION_SEL_MASK GENMASK(1, 0)
79#define FLASH_LED_ILED_GRT_THRSH_MASK GENMASK(5, 0)
80#define FLASH_LED_LMH_LEVEL_MASK GENMASK(1, 0)
81#define FLASH_LED_VPH_DROOP_HYSTERESIS_MASK GENMASK(5, 4)
82#define FLASH_LED_VPH_DROOP_THRESHOLD_MASK GENMASK(2, 0)
83#define FLASH_LED_THERMAL_HYSTERESIS_MASK GENMASK(1, 0)
84#define FLASH_LED_THERMAL_DEBOUNCE_MASK GENMASK(1, 0)
85#define FLASH_LED_THERMAL_THRSH_MASK GENMASK(2, 0)
86#define FLASH_LED_MOD_CTRL_MASK BIT(7)
87#define FLASH_LED_HW_SW_STROBE_SEL_BIT BIT(2)
88#define FLASH_LED_VPH_DROOP_FAULT_MASK BIT(4)
89#define FLASH_LED_LMH_MITIGATION_EN_MASK BIT(0)
90#define FLASH_LED_CHGR_MITIGATION_EN_MASK BIT(4)
91#define THERMAL_OTST1_RAMP_CTRL_MASK BIT(7)
92#define THERMAL_OTST1_RAMP_CTRL_SHIFT 7
93#define THERMAL_DERATE_SLOW_SHIFT 4
94#define THERMAL_DERATE_SLOW_MASK GENMASK(6, 4)
95#define THERMAL_DERATE_FAST_MASK GENMASK(2, 0)
Subbaraman Narayanamurthy3f684b22017-03-21 20:49:54 -070096#define LED1N2_FLASH_ONCE_ONLY_BIT BIT(0)
97#define LED3_FLASH_ONCE_ONLY_BIT BIT(1)
98#define LPG_INPUT_SEL_BIT BIT(0)
David Collins8885f792017-01-26 14:36:34 -080099
100#define VPH_DROOP_DEBOUNCE_US_TO_VAL(val_us) (val_us / 8)
101#define VPH_DROOP_HYST_MV_TO_VAL(val_mv) (val_mv / 25)
102#define VPH_DROOP_THRESH_MV_TO_VAL(val_mv) ((val_mv / 100) - 25)
103#define VPH_DROOP_THRESH_VAL_TO_UV(val) ((val + 25) * 100000)
104#define MITIGATION_THRSH_MA_TO_VAL(val_ma) (val_ma / 100)
105#define CURRENT_MA_TO_REG_VAL(curr_ma, ires_ua) ((curr_ma * 1000) / ires_ua - 1)
106#define SAFETY_TMR_TO_REG_VAL(duration_ms) ((duration_ms / 10) - 1)
107#define THERMAL_HYST_TEMP_TO_VAL(val, divisor) (val / divisor)
108
109#define FLASH_LED_ISC_WARMUP_DELAY_SHIFT 6
110#define FLASH_LED_WARMUP_DELAY_DEFAULT 2
111#define FLASH_LED_ISC_DELAY_DEFAULT 3
112#define FLASH_LED_VPH_DROOP_DEBOUNCE_DEFAULT 2
113#define FLASH_LED_VPH_DROOP_HYST_SHIFT 4
114#define FLASH_LED_VPH_DROOP_HYST_DEFAULT 2
115#define FLASH_LED_VPH_DROOP_THRESH_DEFAULT 5
116#define FLASH_LED_DEBOUNCE_MAX 3
117#define FLASH_LED_HYSTERESIS_MAX 3
118#define FLASH_LED_VPH_DROOP_THRESH_MAX 7
119#define THERMAL_DERATE_SLOW_MAX 314592
120#define THERMAL_DERATE_FAST_MAX 512
121#define THERMAL_DEBOUNCE_TIME_MAX 64
122#define THERMAL_DERATE_HYSTERESIS_MAX 3
123#define FLASH_LED_THERMAL_THRSH_MIN 3
124#define FLASH_LED_THERMAL_THRSH_MAX 7
125#define FLASH_LED_THERMAL_OTST_LEVELS 3
126#define FLASH_LED_VLED_MAX_DEFAULT_UV 3500000
127#define FLASH_LED_IBATT_OCP_THRESH_DEFAULT_UA 4500000
128#define FLASH_LED_RPARA_DEFAULT_UOHM 0
129#define FLASH_LED_SAFETY_TMR_ENABLE BIT(7)
130#define FLASH_LED_LMH_LEVEL_DEFAULT 0
131#define FLASH_LED_LMH_MITIGATION_ENABLE 1
132#define FLASH_LED_LMH_MITIGATION_DISABLE 0
133#define FLASH_LED_CHGR_MITIGATION_ENABLE BIT(4)
134#define FLASH_LED_CHGR_MITIGATION_DISABLE 0
Ankit Sharmaa7153c32017-03-22 19:04:52 +0530135#define FLASH_LED_LMH_MITIGATION_SEL_DEFAULT 2
David Collins8885f792017-01-26 14:36:34 -0800136#define FLASH_LED_MITIGATION_SEL_MAX 2
137#define FLASH_LED_CHGR_MITIGATION_SEL_SHIFT 4
Ankit Sharmaa7153c32017-03-22 19:04:52 +0530138#define FLASH_LED_CHGR_MITIGATION_THRSH_DEFAULT 0xA
139#define FLASH_LED_CHGR_MITIGATION_THRSH_MAX 0x1F
David Collins8885f792017-01-26 14:36:34 -0800140#define FLASH_LED_LMH_OCV_THRESH_DEFAULT_UV 3700000
141#define FLASH_LED_LMH_RBATT_THRESH_DEFAULT_UOHM 400000
142#define FLASH_LED_IRES_BASE 3
143#define FLASH_LED_IRES_DIVISOR 2500
144#define FLASH_LED_IRES_MIN_UA 5000
145#define FLASH_LED_IRES_DEFAULT_UA 12500
146#define FLASH_LED_IRES_DEFAULT_VAL 0x00
147#define FLASH_LED_HDRM_VOL_SHIFT 4
148#define FLASH_LED_HDRM_VOL_DEFAULT_MV 0x80
149#define FLASH_LED_HDRM_VOL_HI_LO_WIN_DEFAULT_MV 0x04
150#define FLASH_LED_HDRM_VOL_BASE_MV 125
151#define FLASH_LED_HDRM_VOL_STEP_MV 25
152#define FLASH_LED_STROBE_CFG_DEFAULT 0x00
153#define FLASH_LED_HW_STROBE_OPTION_1 0x00
154#define FLASH_LED_HW_STROBE_OPTION_2 0x01
155#define FLASH_LED_HW_STROBE_OPTION_3 0x02
156#define FLASH_LED_ENABLE BIT(0)
157#define FLASH_LED_MOD_ENABLE BIT(7)
158#define FLASH_LED_DISABLE 0x00
159#define FLASH_LED_SAFETY_TMR_DISABLED 0x13
David Collins8885f792017-01-26 14:36:34 -0800160#define FLASH_LED_MAX_TOTAL_CURRENT_MA 3750
Kiran Gunda5cadca72017-07-26 14:37:52 +0530161#define FLASH_LED_IRES5P0_MAX_CURR_MA 640
162#define FLASH_LED_IRES7P5_MAX_CURR_MA 960
163#define FLASH_LED_IRES10P0_MAX_CURR_MA 1280
164#define FLASH_LED_IRES12P5_MAX_CURR_MA 1600
165#define MAX_IRES_LEVELS 4
David Collins8885f792017-01-26 14:36:34 -0800166
167/* notifier call chain for flash-led irqs */
168static ATOMIC_NOTIFIER_HEAD(irq_notifier_list);
169
Ankit Sharmaa7153c32017-03-22 19:04:52 +0530170enum flash_charger_mitigation {
171 FLASH_DISABLE_CHARGER_MITIGATION,
172 FLASH_HW_CHARGER_MITIGATION_BY_ILED_THRSHLD,
173 FLASH_SW_CHARGER_MITIGATION,
174};
175
David Collins8885f792017-01-26 14:36:34 -0800176enum flash_led_type {
177 FLASH_LED_TYPE_FLASH,
178 FLASH_LED_TYPE_TORCH,
179};
180
181enum {
182 LED1 = 0,
183 LED2,
184 LED3,
185};
186
Subbaraman Narayanamurthy3f684b22017-03-21 20:49:54 -0700187enum strobe_type {
188 SW_STROBE = 0,
189 HW_STROBE,
190 LPG_STROBE,
191};
192
David Collins8885f792017-01-26 14:36:34 -0800193/*
194 * Configurations for each individual LED
195 */
196struct flash_node_data {
197 struct platform_device *pdev;
198 struct led_classdev cdev;
Subbaraman Narayanamurthy58377f02017-03-21 20:38:43 -0700199 struct pinctrl *strobe_pinctrl;
David Collins8885f792017-01-26 14:36:34 -0800200 struct pinctrl_state *hw_strobe_state_active;
201 struct pinctrl_state *hw_strobe_state_suspend;
202 int hw_strobe_gpio;
203 int ires_ua;
Kiran Gunda5cadca72017-07-26 14:37:52 +0530204 int default_ires_ua;
David Collins8885f792017-01-26 14:36:34 -0800205 int max_current;
206 int current_ma;
Ankit Sharmaa7153c32017-03-22 19:04:52 +0530207 int prev_current_ma;
David Collins8885f792017-01-26 14:36:34 -0800208 u8 duration;
209 u8 id;
210 u8 type;
Kiran Gunda5cadca72017-07-26 14:37:52 +0530211 u8 ires_idx;
212 u8 default_ires_idx;
David Collins8885f792017-01-26 14:36:34 -0800213 u8 hdrm_val;
214 u8 current_reg_val;
Subbaraman Narayanamurthy3f684b22017-03-21 20:49:54 -0700215 u8 strobe_ctrl;
216 u8 strobe_sel;
David Collins8885f792017-01-26 14:36:34 -0800217 bool led_on;
218};
219
220
221struct flash_switch_data {
222 struct platform_device *pdev;
223 struct regulator *vreg;
Subbaraman Narayanamurthy58377f02017-03-21 20:38:43 -0700224 struct pinctrl *led_en_pinctrl;
225 struct pinctrl_state *gpio_state_active;
226 struct pinctrl_state *gpio_state_suspend;
David Collins8885f792017-01-26 14:36:34 -0800227 struct led_classdev cdev;
228 int led_mask;
229 bool regulator_on;
230 bool enabled;
231};
232
233/*
234 * Flash LED configuration read from device tree
235 */
236struct flash_led_platform_data {
237 struct pmic_revid_data *pmic_rev_id;
238 int *thermal_derate_current;
239 int all_ramp_up_done_irq;
240 int all_ramp_down_done_irq;
241 int led_fault_irq;
242 int ibatt_ocp_threshold_ua;
243 int vled_max_uv;
244 int rpara_uohm;
245 int lmh_rbatt_threshold_uohm;
246 int lmh_ocv_threshold_uv;
247 int thermal_derate_slow;
248 int thermal_derate_fast;
249 int thermal_hysteresis;
250 int thermal_debounce;
251 int thermal_thrsh1;
252 int thermal_thrsh2;
253 int thermal_thrsh3;
Subbaraman Narayanamurthy3f684b22017-03-21 20:49:54 -0700254 int hw_strobe_option;
David Collins8885f792017-01-26 14:36:34 -0800255 u32 led1n2_iclamp_low_ma;
256 u32 led1n2_iclamp_mid_ma;
257 u32 led3_iclamp_low_ma;
258 u32 led3_iclamp_mid_ma;
259 u8 isc_delay;
260 u8 warmup_delay;
261 u8 current_derate_en_cfg;
262 u8 vph_droop_threshold;
263 u8 vph_droop_hysteresis;
264 u8 vph_droop_debounce;
265 u8 lmh_mitigation_sel;
266 u8 chgr_mitigation_sel;
267 u8 lmh_level;
268 u8 iled_thrsh_val;
David Collins8885f792017-01-26 14:36:34 -0800269 bool hdrm_auto_mode_en;
270 bool thermal_derate_en;
271 bool otst_ramp_bkup_en;
272};
273
274/*
275 * Flash LED data structure containing flash LED attributes
276 */
277struct qpnp_flash_led {
278 struct flash_led_platform_data *pdata;
279 struct platform_device *pdev;
280 struct regmap *regmap;
281 struct flash_node_data *fnode;
282 struct flash_switch_data *snode;
283 struct power_supply *bms_psy;
284 struct notifier_block nb;
285 spinlock_t lock;
286 int num_fnodes;
287 int num_snodes;
288 int enable;
Ankit Sharmaa7153c32017-03-22 19:04:52 +0530289 int total_current_ma;
David Collins8885f792017-01-26 14:36:34 -0800290 u16 base;
291 bool trigger_lmh;
292 bool trigger_chgr;
293};
294
295static int thermal_derate_slow_table[] = {
296 128, 256, 512, 1024, 2048, 4096, 8192, 314592,
297};
298
299static int thermal_derate_fast_table[] = {
300 32, 64, 96, 128, 256, 384, 512,
301};
302
303static int otst1_threshold_table[] = {
304 85, 79, 73, 67, 109, 103, 97, 91,
305};
306
307static int otst2_threshold_table[] = {
308 110, 104, 98, 92, 134, 128, 122, 116,
309};
310
311static int otst3_threshold_table[] = {
312 125, 119, 113, 107, 149, 143, 137, 131,
313};
314
Kiran Gunda5cadca72017-07-26 14:37:52 +0530315static int max_ires_curr_ma_table[MAX_IRES_LEVELS] = {
316 FLASH_LED_IRES12P5_MAX_CURR_MA, FLASH_LED_IRES10P0_MAX_CURR_MA,
317 FLASH_LED_IRES7P5_MAX_CURR_MA, FLASH_LED_IRES5P0_MAX_CURR_MA
318};
319
David Collins8885f792017-01-26 14:36:34 -0800320static int qpnp_flash_led_read(struct qpnp_flash_led *led, u16 addr, u8 *data)
321{
322 int rc;
323 uint val;
324
325 rc = regmap_read(led->regmap, addr, &val);
326 if (rc < 0) {
327 pr_err("Unable to read from 0x%04X rc = %d\n", addr, rc);
328 return rc;
329 }
330
331 pr_debug("Read 0x%02X from addr 0x%04X\n", val, addr);
332 *data = (u8)val;
333 return 0;
334}
335
336static int qpnp_flash_led_write(struct qpnp_flash_led *led, u16 addr, u8 data)
337{
338 int rc;
339
340 rc = regmap_write(led->regmap, addr, data);
341 if (rc < 0) {
342 pr_err("Unable to write to 0x%04X rc = %d\n", addr, rc);
343 return rc;
344 }
345
346 pr_debug("Wrote 0x%02X to addr 0x%04X\n", data, addr);
347 return 0;
348}
349
350static int
351qpnp_flash_led_masked_read(struct qpnp_flash_led *led, u16 addr, u8 mask,
352 u8 *val)
353{
354 int rc;
355
356 rc = qpnp_flash_led_read(led, addr, val);
357 if (rc < 0)
358 return rc;
359
360 *val &= mask;
361 return rc;
362}
363
364static int
365qpnp_flash_led_masked_write(struct qpnp_flash_led *led, u16 addr, u8 mask,
366 u8 val)
367{
368 int rc;
369
370 rc = regmap_update_bits(led->regmap, addr, mask, val);
371 if (rc < 0)
372 pr_err("Unable to update bits from 0x%04X, rc = %d\n", addr,
373 rc);
374 else
375 pr_debug("Wrote 0x%02X to addr 0x%04X\n", val, addr);
376
377 return rc;
378}
379
380static enum
381led_brightness qpnp_flash_led_brightness_get(struct led_classdev *led_cdev)
382{
383 return led_cdev->brightness;
384}
385
386static int qpnp_flash_led_init_settings(struct qpnp_flash_led *led)
387{
388 int rc, i, addr_offset;
389 u8 val = 0, mask;
390
391 for (i = 0; i < led->num_fnodes; i++) {
392 addr_offset = led->fnode[i].id;
393 rc = qpnp_flash_led_write(led,
394 FLASH_LED_REG_HDRM_PRGM(led->base + addr_offset),
395 led->fnode[i].hdrm_val);
396 if (rc < 0)
397 return rc;
398
399 val |= 0x1 << led->fnode[i].id;
400 }
401
402 rc = qpnp_flash_led_write(led,
403 FLASH_LED_REG_HDRM_AUTO_MODE_CTRL(led->base),
404 val);
405 if (rc < 0)
406 return rc;
407
408 rc = qpnp_flash_led_masked_write(led,
409 FLASH_LED_REG_ISC_DELAY(led->base),
410 FLASH_LED_ISC_WARMUP_DELAY_MASK,
411 led->pdata->isc_delay);
412 if (rc < 0)
413 return rc;
414
415 rc = qpnp_flash_led_masked_write(led,
416 FLASH_LED_REG_WARMUP_DELAY(led->base),
417 FLASH_LED_ISC_WARMUP_DELAY_MASK,
418 led->pdata->warmup_delay);
419 if (rc < 0)
420 return rc;
421
422 rc = qpnp_flash_led_masked_write(led,
423 FLASH_LED_REG_CURRENT_DERATE_EN(led->base),
424 FLASH_LED_CURRENT_DERATE_EN_MASK,
425 led->pdata->current_derate_en_cfg);
426 if (rc < 0)
427 return rc;
428
429 val = (led->pdata->otst_ramp_bkup_en << THERMAL_OTST1_RAMP_CTRL_SHIFT);
430 mask = THERMAL_OTST1_RAMP_CTRL_MASK;
431 if (led->pdata->thermal_derate_slow >= 0) {
432 val |= (led->pdata->thermal_derate_slow <<
433 THERMAL_DERATE_SLOW_SHIFT);
434 mask |= THERMAL_DERATE_SLOW_MASK;
435 }
436
437 if (led->pdata->thermal_derate_fast >= 0) {
438 val |= led->pdata->thermal_derate_fast;
439 mask |= THERMAL_DERATE_FAST_MASK;
440 }
441
442 rc = qpnp_flash_led_masked_write(led,
443 FLASH_LED_REG_THERMAL_RMP_DN_RATE(led->base),
444 mask, val);
445 if (rc < 0)
446 return rc;
447
448 if (led->pdata->thermal_debounce >= 0) {
449 rc = qpnp_flash_led_masked_write(led,
450 FLASH_LED_REG_THERMAL_DEBOUNCE(led->base),
451 FLASH_LED_THERMAL_DEBOUNCE_MASK,
452 led->pdata->thermal_debounce);
453 if (rc < 0)
454 return rc;
455 }
456
457 if (led->pdata->thermal_hysteresis >= 0) {
458 rc = qpnp_flash_led_masked_write(led,
459 FLASH_LED_REG_THERMAL_HYSTERESIS(led->base),
460 FLASH_LED_THERMAL_HYSTERESIS_MASK,
461 led->pdata->thermal_hysteresis);
462 if (rc < 0)
463 return rc;
464 }
465
466 if (led->pdata->thermal_thrsh1 >= 0) {
467 rc = qpnp_flash_led_masked_write(led,
468 FLASH_LED_REG_THERMAL_THRSH1(led->base),
469 FLASH_LED_THERMAL_THRSH_MASK,
470 led->pdata->thermal_thrsh1);
471 if (rc < 0)
472 return rc;
473 }
474
475 if (led->pdata->thermal_thrsh2 >= 0) {
476 rc = qpnp_flash_led_masked_write(led,
477 FLASH_LED_REG_THERMAL_THRSH2(led->base),
478 FLASH_LED_THERMAL_THRSH_MASK,
479 led->pdata->thermal_thrsh2);
480 if (rc < 0)
481 return rc;
482 }
483
484 if (led->pdata->thermal_thrsh3 >= 0) {
485 rc = qpnp_flash_led_masked_write(led,
486 FLASH_LED_REG_THERMAL_THRSH3(led->base),
487 FLASH_LED_THERMAL_THRSH_MASK,
488 led->pdata->thermal_thrsh3);
489 if (rc < 0)
490 return rc;
491 }
492
493 rc = qpnp_flash_led_masked_write(led,
494 FLASH_LED_REG_VPH_DROOP_DEBOUNCE(led->base),
495 FLASH_LED_VPH_DROOP_DEBOUNCE_MASK,
496 led->pdata->vph_droop_debounce);
497 if (rc < 0)
498 return rc;
499
500 rc = qpnp_flash_led_masked_write(led,
501 FLASH_LED_REG_VPH_DROOP_THRESHOLD(led->base),
502 FLASH_LED_VPH_DROOP_THRESHOLD_MASK,
503 led->pdata->vph_droop_threshold);
504 if (rc < 0)
505 return rc;
506
507 rc = qpnp_flash_led_masked_write(led,
508 FLASH_LED_REG_VPH_DROOP_THRESHOLD(led->base),
509 FLASH_LED_VPH_DROOP_HYSTERESIS_MASK,
510 led->pdata->vph_droop_hysteresis);
511 if (rc < 0)
512 return rc;
513
514 rc = qpnp_flash_led_masked_write(led,
515 FLASH_LED_REG_MITIGATION_SEL(led->base),
516 FLASH_LED_LMH_MITIGATION_SEL_MASK,
517 led->pdata->lmh_mitigation_sel);
518 if (rc < 0)
519 return rc;
520
Ankit Sharmaa7153c32017-03-22 19:04:52 +0530521 val = led->pdata->chgr_mitigation_sel
522 << FLASH_LED_CHGR_MITIGATION_SEL_SHIFT;
David Collins8885f792017-01-26 14:36:34 -0800523 rc = qpnp_flash_led_masked_write(led,
524 FLASH_LED_REG_MITIGATION_SEL(led->base),
525 FLASH_LED_CHGR_MITIGATION_SEL_MASK,
Ankit Sharmaa7153c32017-03-22 19:04:52 +0530526 val);
David Collins8885f792017-01-26 14:36:34 -0800527 if (rc < 0)
528 return rc;
529
530 rc = qpnp_flash_led_masked_write(led,
531 FLASH_LED_REG_LMH_LEVEL(led->base),
532 FLASH_LED_LMH_LEVEL_MASK,
533 led->pdata->lmh_level);
534 if (rc < 0)
535 return rc;
536
537 rc = qpnp_flash_led_masked_write(led,
538 FLASH_LED_REG_ILED_GRT_THRSH(led->base),
539 FLASH_LED_ILED_GRT_THRSH_MASK,
540 led->pdata->iled_thrsh_val);
541 if (rc < 0)
542 return rc;
543
544 if (led->pdata->led1n2_iclamp_low_ma) {
545 val = CURRENT_MA_TO_REG_VAL(led->pdata->led1n2_iclamp_low_ma,
Subbaraman Narayanamurthy01c99612017-04-03 12:26:06 -0700546 led->fnode[LED1].ires_ua);
David Collins8885f792017-01-26 14:36:34 -0800547 rc = qpnp_flash_led_masked_write(led,
548 FLASH_LED_REG_LED1N2_ICLAMP_LOW(led->base),
549 FLASH_LED_CURRENT_MASK, val);
550 if (rc < 0)
551 return rc;
552 }
553
554 if (led->pdata->led1n2_iclamp_mid_ma) {
555 val = CURRENT_MA_TO_REG_VAL(led->pdata->led1n2_iclamp_mid_ma,
Subbaraman Narayanamurthy01c99612017-04-03 12:26:06 -0700556 led->fnode[LED1].ires_ua);
David Collins8885f792017-01-26 14:36:34 -0800557 rc = qpnp_flash_led_masked_write(led,
558 FLASH_LED_REG_LED1N2_ICLAMP_MID(led->base),
559 FLASH_LED_CURRENT_MASK, val);
560 if (rc < 0)
561 return rc;
562 }
563
564 if (led->pdata->led3_iclamp_low_ma) {
565 val = CURRENT_MA_TO_REG_VAL(led->pdata->led3_iclamp_low_ma,
Subbaraman Narayanamurthy01c99612017-04-03 12:26:06 -0700566 led->fnode[LED3].ires_ua);
David Collins8885f792017-01-26 14:36:34 -0800567 rc = qpnp_flash_led_masked_write(led,
568 FLASH_LED_REG_LED3_ICLAMP_LOW(led->base),
569 FLASH_LED_CURRENT_MASK, val);
570 if (rc < 0)
571 return rc;
572 }
573
574 if (led->pdata->led3_iclamp_mid_ma) {
575 val = CURRENT_MA_TO_REG_VAL(led->pdata->led3_iclamp_mid_ma,
Subbaraman Narayanamurthy01c99612017-04-03 12:26:06 -0700576 led->fnode[LED3].ires_ua);
David Collins8885f792017-01-26 14:36:34 -0800577 rc = qpnp_flash_led_masked_write(led,
578 FLASH_LED_REG_LED3_ICLAMP_MID(led->base),
579 FLASH_LED_CURRENT_MASK, val);
580 if (rc < 0)
581 return rc;
582 }
583
Subbaraman Narayanamurthy3f684b22017-03-21 20:49:54 -0700584 if (led->pdata->hw_strobe_option > 0) {
585 rc = qpnp_flash_led_masked_write(led,
586 FLASH_LED_REG_STROBE_CFG(led->base),
587 FLASH_LED_STROBE_MASK,
588 led->pdata->hw_strobe_option);
589 if (rc < 0)
590 return rc;
591 }
592
593 if (led->fnode[LED3].strobe_sel == LPG_STROBE) {
594 rc = qpnp_flash_led_masked_write(led,
595 FLASH_LED_REG_MULTI_STROBE_CTRL(led->base),
596 LED3_FLASH_ONCE_ONLY_BIT, 0);
597 if (rc < 0)
598 return rc;
599
600 rc = qpnp_flash_led_masked_write(led,
601 FLASH_LED_REG_LPG_INPUT_CTRL(led->base),
602 LPG_INPUT_SEL_BIT, LPG_INPUT_SEL_BIT);
603 if (rc < 0)
604 return rc;
605 }
David Collins8885f792017-01-26 14:36:34 -0800606 return 0;
607}
608
609static int qpnp_flash_led_hw_strobe_enable(struct flash_node_data *fnode,
610 int hw_strobe_option, bool on)
611{
612 int rc = 0;
613
614 /*
615 * If the LED controlled by this fnode is not GPIO controlled
616 * for the given strobe_option, return.
617 */
618 if (hw_strobe_option == FLASH_LED_HW_STROBE_OPTION_1)
619 return 0;
620 else if (hw_strobe_option == FLASH_LED_HW_STROBE_OPTION_2
621 && fnode->id != LED3)
622 return 0;
623 else if (hw_strobe_option == FLASH_LED_HW_STROBE_OPTION_3
624 && fnode->id == LED1)
625 return 0;
626
627 if (gpio_is_valid(fnode->hw_strobe_gpio)) {
628 gpio_set_value(fnode->hw_strobe_gpio, on ? 1 : 0);
Subbaraman Narayanamurthy58377f02017-03-21 20:38:43 -0700629 } else if (fnode->strobe_pinctrl && fnode->hw_strobe_state_active &&
David Collins8885f792017-01-26 14:36:34 -0800630 fnode->hw_strobe_state_suspend) {
Subbaraman Narayanamurthy58377f02017-03-21 20:38:43 -0700631 rc = pinctrl_select_state(fnode->strobe_pinctrl,
David Collins8885f792017-01-26 14:36:34 -0800632 on ? fnode->hw_strobe_state_active :
633 fnode->hw_strobe_state_suspend);
634 if (rc < 0) {
635 pr_err("failed to change hw strobe pin state\n");
636 return rc;
637 }
638 }
639
640 return rc;
641}
642
643static int qpnp_flash_led_regulator_enable(struct qpnp_flash_led *led,
644 struct flash_switch_data *snode, bool on)
645{
646 int rc = 0;
647
648 if (!snode || !snode->vreg)
649 return 0;
650
651 if (snode->regulator_on == on)
652 return 0;
653
654 if (on)
655 rc = regulator_enable(snode->vreg);
656 else
657 rc = regulator_disable(snode->vreg);
658
659 if (rc < 0) {
660 pr_err("regulator_%s failed, rc=%d\n",
661 on ? "enable" : "disable", rc);
662 return rc;
663 }
664
665 snode->regulator_on = on ? true : false;
666 return 0;
667}
668
669static int get_property_from_fg(struct qpnp_flash_led *led,
670 enum power_supply_property prop, int *val)
671{
672 int rc;
673 union power_supply_propval pval = {0, };
674
675 if (!led->bms_psy) {
676 pr_err("no bms psy found\n");
677 return -EINVAL;
678 }
679
680 rc = power_supply_get_property(led->bms_psy, prop, &pval);
681 if (rc) {
682 pr_err("bms psy doesn't support reading prop %d rc = %d\n",
683 prop, rc);
684 return rc;
685 }
686
687 *val = pval.intval;
688 return rc;
689}
690
691#define VOLTAGE_HDRM_DEFAULT_MV 350
692static int qpnp_flash_led_get_voltage_headroom(struct qpnp_flash_led *led)
693{
694 int i, voltage_hdrm_mv = 0, voltage_hdrm_max = 0;
695
696 for (i = 0; i < led->num_fnodes; i++) {
697 if (led->fnode[i].led_on) {
698 if (led->fnode[i].id < 2) {
699 if (led->fnode[i].current_ma < 750)
700 voltage_hdrm_mv = 125;
701 else if (led->fnode[i].current_ma < 1000)
702 voltage_hdrm_mv = 175;
703 else if (led->fnode[i].current_ma < 1250)
704 voltage_hdrm_mv = 250;
705 else
706 voltage_hdrm_mv = 350;
707 } else {
708 if (led->fnode[i].current_ma < 375)
709 voltage_hdrm_mv = 125;
710 else if (led->fnode[i].current_ma < 500)
711 voltage_hdrm_mv = 175;
712 else if (led->fnode[i].current_ma < 625)
713 voltage_hdrm_mv = 250;
714 else
715 voltage_hdrm_mv = 350;
716 }
717
718 voltage_hdrm_max = max(voltage_hdrm_max,
719 voltage_hdrm_mv);
720 }
721 }
722
723 if (!voltage_hdrm_max)
724 return VOLTAGE_HDRM_DEFAULT_MV;
725
726 return voltage_hdrm_max;
727}
728
729#define UCONV 1000000LL
730#define MCONV 1000LL
731#define FLASH_VDIP_MARGIN 50000
732#define BOB_EFFICIENCY 900LL
733#define VIN_FLASH_MIN_UV 3300000LL
Subbaraman Narayanamurthyd94945e2017-11-28 19:54:09 -0800734static int qpnp_flash_led_calc_max_current(struct qpnp_flash_led *led,
735 int *max_current)
David Collins8885f792017-01-26 14:36:34 -0800736{
Kyle Yan74fdd732017-03-22 13:37:08 -0700737 int ocv_uv, ibat_now, voltage_hdrm_mv, rc;
738 int rbatt_uohm = 0;
David Collins8885f792017-01-26 14:36:34 -0800739 int64_t ibat_flash_ua, avail_flash_ua, avail_flash_power_fw;
740 int64_t ibat_safe_ua, vin_flash_uv, vph_flash_uv, vph_flash_vdip;
741
742 /* RESISTANCE = esr_uohm + rslow_uohm */
743 rc = get_property_from_fg(led, POWER_SUPPLY_PROP_RESISTANCE,
744 &rbatt_uohm);
745 if (rc < 0) {
746 pr_err("bms psy does not support resistance, rc=%d\n", rc);
747 return rc;
748 }
749
750 /* If no battery is connected, return max possible flash current */
Subbaraman Narayanamurthyd94945e2017-11-28 19:54:09 -0800751 if (!rbatt_uohm) {
752 *max_current = FLASH_LED_MAX_TOTAL_CURRENT_MA;
753 return 0;
754 }
David Collins8885f792017-01-26 14:36:34 -0800755
756 rc = get_property_from_fg(led, POWER_SUPPLY_PROP_VOLTAGE_OCV, &ocv_uv);
757 if (rc < 0) {
758 pr_err("bms psy does not support OCV, rc=%d\n", rc);
759 return rc;
760 }
761
762 rc = get_property_from_fg(led, POWER_SUPPLY_PROP_CURRENT_NOW,
763 &ibat_now);
764 if (rc < 0) {
765 pr_err("bms psy does not support current, rc=%d\n", rc);
766 return rc;
767 }
768
769 rbatt_uohm += led->pdata->rpara_uohm;
770 voltage_hdrm_mv = qpnp_flash_led_get_voltage_headroom(led);
771 vph_flash_vdip =
772 VPH_DROOP_THRESH_VAL_TO_UV(led->pdata->vph_droop_threshold)
773 + FLASH_VDIP_MARGIN;
774
775 /* Check if LMH_MITIGATION needs to be triggered */
776 if (!led->trigger_lmh && (ocv_uv < led->pdata->lmh_ocv_threshold_uv ||
777 rbatt_uohm > led->pdata->lmh_rbatt_threshold_uohm)) {
778 led->trigger_lmh = true;
779 rc = qpnp_flash_led_masked_write(led,
780 FLASH_LED_REG_MITIGATION_SW(led->base),
781 FLASH_LED_LMH_MITIGATION_EN_MASK,
782 FLASH_LED_LMH_MITIGATION_ENABLE);
783 if (rc < 0) {
784 pr_err("trigger lmh mitigation failed, rc=%d\n", rc);
785 return rc;
786 }
787
788 /* Wait for LMH mitigation to take effect */
789 udelay(100);
790
Subbaraman Narayanamurthyd94945e2017-11-28 19:54:09 -0800791 return qpnp_flash_led_calc_max_current(led, max_current);
David Collins8885f792017-01-26 14:36:34 -0800792 }
793
794 /*
795 * Calculate the maximum current that can pulled out of the battery
796 * before the battery voltage dips below a safe threshold.
797 */
798 ibat_safe_ua = div_s64((ocv_uv - vph_flash_vdip) * UCONV,
799 rbatt_uohm);
800
801 if (ibat_safe_ua <= led->pdata->ibatt_ocp_threshold_ua) {
802 /*
803 * If the calculated current is below the OCP threshold, then
804 * use it as the possible flash current.
805 */
806 ibat_flash_ua = ibat_safe_ua - ibat_now;
807 vph_flash_uv = vph_flash_vdip;
808 } else {
809 /*
810 * If the calculated current is above the OCP threshold, then
811 * use the ocp threshold instead.
812 *
813 * Any higher current will be tripping the battery OCP.
814 */
815 ibat_flash_ua = led->pdata->ibatt_ocp_threshold_ua - ibat_now;
816 vph_flash_uv = ocv_uv - div64_s64((int64_t)rbatt_uohm
817 * led->pdata->ibatt_ocp_threshold_ua, UCONV);
818 }
819 /* Calculate the input voltage of the flash module. */
820 vin_flash_uv = max((led->pdata->vled_max_uv +
821 (voltage_hdrm_mv * MCONV)), VIN_FLASH_MIN_UV);
822 /* Calculate the available power for the flash module. */
823 avail_flash_power_fw = BOB_EFFICIENCY * vph_flash_uv * ibat_flash_ua;
824 /*
825 * Calculate the available amount of current the flash module can draw
826 * before collapsing the battery. (available power/ flash input voltage)
827 */
828 avail_flash_ua = div64_s64(avail_flash_power_fw, vin_flash_uv * MCONV);
829 pr_debug("avail_iflash=%lld, ocv=%d, ibat=%d, rbatt=%d, trigger_lmh=%d\n",
830 avail_flash_ua, ocv_uv, ibat_now, rbatt_uohm, led->trigger_lmh);
Subbaraman Narayanamurthyd94945e2017-11-28 19:54:09 -0800831 *max_current = min(FLASH_LED_MAX_TOTAL_CURRENT_MA,
David Collins8885f792017-01-26 14:36:34 -0800832 (int)(div64_s64(avail_flash_ua, MCONV)));
Subbaraman Narayanamurthyd94945e2017-11-28 19:54:09 -0800833 return 0;
David Collins8885f792017-01-26 14:36:34 -0800834}
835
Subbaraman Narayanamurthyd94945e2017-11-28 19:54:09 -0800836static int qpnp_flash_led_calc_thermal_current_lim(struct qpnp_flash_led *led,
837 int *thermal_current_lim)
David Collins8885f792017-01-26 14:36:34 -0800838{
David Collins8885f792017-01-26 14:36:34 -0800839 int rc;
840 u8 thermal_thrsh1, thermal_thrsh2, thermal_thrsh3, otst_status;
841
842 /* Store THERMAL_THRSHx register values */
843 rc = qpnp_flash_led_masked_read(led,
844 FLASH_LED_REG_THERMAL_THRSH1(led->base),
845 FLASH_LED_THERMAL_THRSH_MASK,
846 &thermal_thrsh1);
847 if (rc < 0)
848 return rc;
849
850 rc = qpnp_flash_led_masked_read(led,
851 FLASH_LED_REG_THERMAL_THRSH2(led->base),
852 FLASH_LED_THERMAL_THRSH_MASK,
853 &thermal_thrsh2);
854 if (rc < 0)
855 return rc;
856
857 rc = qpnp_flash_led_masked_read(led,
858 FLASH_LED_REG_THERMAL_THRSH3(led->base),
859 FLASH_LED_THERMAL_THRSH_MASK,
860 &thermal_thrsh3);
861 if (rc < 0)
862 return rc;
863
864 /* Lower THERMAL_THRSHx thresholds to minimum */
865 rc = qpnp_flash_led_masked_write(led,
866 FLASH_LED_REG_THERMAL_THRSH1(led->base),
867 FLASH_LED_THERMAL_THRSH_MASK,
868 FLASH_LED_THERMAL_THRSH_MIN);
869 if (rc < 0)
870 return rc;
871
872 rc = qpnp_flash_led_masked_write(led,
873 FLASH_LED_REG_THERMAL_THRSH2(led->base),
874 FLASH_LED_THERMAL_THRSH_MASK,
875 FLASH_LED_THERMAL_THRSH_MIN);
876 if (rc < 0)
877 return rc;
878
879 rc = qpnp_flash_led_masked_write(led,
880 FLASH_LED_REG_THERMAL_THRSH3(led->base),
881 FLASH_LED_THERMAL_THRSH_MASK,
882 FLASH_LED_THERMAL_THRSH_MIN);
883 if (rc < 0)
884 return rc;
885
886 /* Check THERMAL_OTST status */
887 rc = qpnp_flash_led_read(led,
888 FLASH_LED_REG_LED_STATUS2(led->base),
889 &otst_status);
890 if (rc < 0)
891 return rc;
892
893 /* Look up current limit based on THERMAL_OTST status */
894 if (otst_status)
Subbaraman Narayanamurthyd94945e2017-11-28 19:54:09 -0800895 *thermal_current_lim =
David Collins8885f792017-01-26 14:36:34 -0800896 led->pdata->thermal_derate_current[otst_status >> 1];
897
898 /* Restore THERMAL_THRESHx registers to original values */
899 rc = qpnp_flash_led_masked_write(led,
900 FLASH_LED_REG_THERMAL_THRSH1(led->base),
901 FLASH_LED_THERMAL_THRSH_MASK,
902 thermal_thrsh1);
903 if (rc < 0)
904 return rc;
905
906 rc = qpnp_flash_led_masked_write(led,
907 FLASH_LED_REG_THERMAL_THRSH2(led->base),
908 FLASH_LED_THERMAL_THRSH_MASK,
909 thermal_thrsh2);
910 if (rc < 0)
911 return rc;
912
913 rc = qpnp_flash_led_masked_write(led,
914 FLASH_LED_REG_THERMAL_THRSH3(led->base),
915 FLASH_LED_THERMAL_THRSH_MASK,
916 thermal_thrsh3);
917 if (rc < 0)
918 return rc;
919
Subbaraman Narayanamurthyd94945e2017-11-28 19:54:09 -0800920 return 0;
David Collins8885f792017-01-26 14:36:34 -0800921}
922
Subbaraman Narayanamurthyd94945e2017-11-28 19:54:09 -0800923static int qpnp_flash_led_get_max_avail_current(struct qpnp_flash_led *led,
924 int *max_avail_current)
David Collins8885f792017-01-26 14:36:34 -0800925{
Subbaraman Narayanamurthyd94945e2017-11-28 19:54:09 -0800926 int thermal_current_lim = 0, rc;
David Collins8885f792017-01-26 14:36:34 -0800927
928 led->trigger_lmh = false;
Subbaraman Narayanamurthyd94945e2017-11-28 19:54:09 -0800929 rc = qpnp_flash_led_calc_max_current(led, max_avail_current);
930 if (rc < 0) {
931 pr_err("Couldn't calculate max_avail_current, rc=%d\n", rc);
932 return rc;
933 }
934
935 if (led->pdata->thermal_derate_en) {
936 rc = qpnp_flash_led_calc_thermal_current_lim(led,
937 &thermal_current_lim);
938 if (rc < 0) {
939 pr_err("Couldn't calculate thermal_current_lim, rc=%d\n",
940 rc);
941 return rc;
942 }
943 }
David Collins8885f792017-01-26 14:36:34 -0800944
945 if (thermal_current_lim)
Subbaraman Narayanamurthyd94945e2017-11-28 19:54:09 -0800946 *max_avail_current = min(*max_avail_current,
947 thermal_current_lim);
David Collins8885f792017-01-26 14:36:34 -0800948
Subbaraman Narayanamurthyd94945e2017-11-28 19:54:09 -0800949 return 0;
David Collins8885f792017-01-26 14:36:34 -0800950}
951
Ankit Sharmaa7153c32017-03-22 19:04:52 +0530952static void qpnp_flash_led_aggregate_max_current(struct flash_node_data *fnode)
953{
954 struct qpnp_flash_led *led = dev_get_drvdata(&fnode->pdev->dev);
955
956 if (fnode->current_ma)
957 led->total_current_ma += fnode->current_ma
958 - fnode->prev_current_ma;
959 else
960 led->total_current_ma -= fnode->prev_current_ma;
961
962 fnode->prev_current_ma = fnode->current_ma;
963}
964
David Collins8885f792017-01-26 14:36:34 -0800965static void qpnp_flash_led_node_set(struct flash_node_data *fnode, int value)
966{
Kiran Gunda5cadca72017-07-26 14:37:52 +0530967 int i = 0;
David Collins8885f792017-01-26 14:36:34 -0800968 int prgm_current_ma = value;
Ankit Sharma8798ab12017-04-06 15:44:09 +0530969 int min_ma = fnode->ires_ua / 1000;
Ankit Sharmaa7153c32017-03-22 19:04:52 +0530970 struct qpnp_flash_led *led = dev_get_drvdata(&fnode->pdev->dev);
David Collins8885f792017-01-26 14:36:34 -0800971
972 if (value <= 0)
973 prgm_current_ma = 0;
Ankit Sharma8798ab12017-04-06 15:44:09 +0530974 else if (value < min_ma)
975 prgm_current_ma = min_ma;
David Collins8885f792017-01-26 14:36:34 -0800976
Kiran Gunda5cadca72017-07-26 14:37:52 +0530977 fnode->ires_idx = fnode->default_ires_idx;
978 fnode->ires_ua = fnode->default_ires_ua;
979
David Collins8885f792017-01-26 14:36:34 -0800980 prgm_current_ma = min(prgm_current_ma, fnode->max_current);
Kiran Gunda5cadca72017-07-26 14:37:52 +0530981 if (prgm_current_ma > max_ires_curr_ma_table[fnode->ires_idx]) {
982 /* find the matching ires */
983 for (i = MAX_IRES_LEVELS - 1; i >= 0; i--) {
984 if (prgm_current_ma <= max_ires_curr_ma_table[i]) {
985 fnode->ires_idx = i;
986 fnode->ires_ua = FLASH_LED_IRES_MIN_UA +
987 (FLASH_LED_IRES_BASE - fnode->ires_idx) *
988 FLASH_LED_IRES_DIVISOR;
989 break;
990 }
991 }
992 }
David Collins8885f792017-01-26 14:36:34 -0800993 fnode->current_ma = prgm_current_ma;
994 fnode->cdev.brightness = prgm_current_ma;
995 fnode->current_reg_val = CURRENT_MA_TO_REG_VAL(prgm_current_ma,
996 fnode->ires_ua);
997 fnode->led_on = prgm_current_ma != 0;
Ankit Sharmaa7153c32017-03-22 19:04:52 +0530998
999 if (led->pdata->chgr_mitigation_sel == FLASH_SW_CHARGER_MITIGATION) {
1000 qpnp_flash_led_aggregate_max_current(fnode);
1001 led->trigger_chgr = false;
1002 if (led->total_current_ma >= 1000)
1003 led->trigger_chgr = true;
1004 }
David Collins8885f792017-01-26 14:36:34 -08001005}
1006
1007static int qpnp_flash_led_switch_disable(struct flash_switch_data *snode)
1008{
1009 struct qpnp_flash_led *led = dev_get_drvdata(&snode->pdev->dev);
1010 int i, rc, addr_offset;
1011
1012 rc = qpnp_flash_led_masked_write(led,
1013 FLASH_LED_EN_LED_CTRL(led->base),
1014 snode->led_mask, FLASH_LED_DISABLE);
1015 if (rc < 0)
1016 return rc;
1017
1018 if (led->trigger_lmh) {
1019 rc = qpnp_flash_led_masked_write(led,
1020 FLASH_LED_REG_MITIGATION_SW(led->base),
1021 FLASH_LED_LMH_MITIGATION_EN_MASK,
1022 FLASH_LED_LMH_MITIGATION_DISABLE);
1023 if (rc < 0) {
1024 pr_err("disable lmh mitigation failed, rc=%d\n", rc);
1025 return rc;
1026 }
1027 }
1028
1029 if (!led->trigger_chgr) {
1030 rc = qpnp_flash_led_masked_write(led,
1031 FLASH_LED_REG_MITIGATION_SW(led->base),
1032 FLASH_LED_CHGR_MITIGATION_EN_MASK,
1033 FLASH_LED_CHGR_MITIGATION_DISABLE);
1034 if (rc < 0) {
1035 pr_err("disable chgr mitigation failed, rc=%d\n", rc);
1036 return rc;
1037 }
1038 }
1039
1040 led->enable--;
1041 if (led->enable == 0) {
1042 rc = qpnp_flash_led_masked_write(led,
1043 FLASH_LED_REG_MOD_CTRL(led->base),
1044 FLASH_LED_MOD_CTRL_MASK, FLASH_LED_DISABLE);
1045 if (rc < 0)
1046 return rc;
1047 }
1048
1049 for (i = 0; i < led->num_fnodes; i++) {
1050 if (!led->fnode[i].led_on ||
1051 !(snode->led_mask & BIT(led->fnode[i].id)))
1052 continue;
1053
1054 addr_offset = led->fnode[i].id;
1055 rc = qpnp_flash_led_masked_write(led,
1056 FLASH_LED_REG_TGR_CURRENT(led->base + addr_offset),
1057 FLASH_LED_CURRENT_MASK, 0);
1058 if (rc < 0)
1059 return rc;
1060
1061 led->fnode[i].led_on = false;
1062
Subbaraman Narayanamurthy3f684b22017-03-21 20:49:54 -07001063 if (led->fnode[i].strobe_sel == HW_STROBE) {
David Collins8885f792017-01-26 14:36:34 -08001064 rc = qpnp_flash_led_hw_strobe_enable(&led->fnode[i],
1065 led->pdata->hw_strobe_option, false);
1066 if (rc < 0) {
1067 pr_err("Unable to disable hw strobe, rc=%d\n",
1068 rc);
1069 return rc;
1070 }
1071 }
1072 }
1073
Subbaraman Narayanamurthy58377f02017-03-21 20:38:43 -07001074 if (snode->led_en_pinctrl) {
1075 pr_debug("Selecting suspend state for %s\n", snode->cdev.name);
1076 rc = pinctrl_select_state(snode->led_en_pinctrl,
1077 snode->gpio_state_suspend);
1078 if (rc < 0) {
1079 pr_err("failed to select pinctrl suspend state rc=%d\n",
1080 rc);
1081 return rc;
1082 }
1083 }
1084
David Collins8885f792017-01-26 14:36:34 -08001085 snode->enabled = false;
1086 return 0;
1087}
1088
1089static int qpnp_flash_led_switch_set(struct flash_switch_data *snode, bool on)
1090{
1091 struct qpnp_flash_led *led = dev_get_drvdata(&snode->pdev->dev);
1092 int rc, i, addr_offset;
1093 u8 val, mask;
1094
1095 if (snode->enabled == on) {
1096 pr_debug("Switch node is already %s!\n",
1097 on ? "enabled" : "disabled");
1098 return 0;
1099 }
1100
1101 if (!on) {
1102 rc = qpnp_flash_led_switch_disable(snode);
1103 return rc;
1104 }
1105
1106 /* Iterate over all leds for this switch node */
1107 val = 0;
1108 for (i = 0; i < led->num_fnodes; i++)
1109 if (snode->led_mask & BIT(led->fnode[i].id))
Kiran Gunda5cadca72017-07-26 14:37:52 +05301110 val |= led->fnode[i].ires_idx << (led->fnode[i].id * 2);
David Collins8885f792017-01-26 14:36:34 -08001111
1112 rc = qpnp_flash_led_masked_write(led, FLASH_LED_REG_IRES(led->base),
1113 FLASH_LED_CURRENT_MASK, val);
1114 if (rc < 0)
1115 return rc;
1116
David Collins8885f792017-01-26 14:36:34 -08001117 val = 0;
1118 for (i = 0; i < led->num_fnodes; i++) {
1119 if (!led->fnode[i].led_on ||
1120 !(snode->led_mask & BIT(led->fnode[i].id)))
1121 continue;
1122
1123 addr_offset = led->fnode[i].id;
Subbaraman Narayanamurthy3f684b22017-03-21 20:49:54 -07001124 if (led->fnode[i].strobe_sel == SW_STROBE)
David Collins8885f792017-01-26 14:36:34 -08001125 mask = FLASH_LED_HW_SW_STROBE_SEL_BIT;
Subbaraman Narayanamurthy3f684b22017-03-21 20:49:54 -07001126 else
1127 mask = FLASH_HW_STROBE_MASK;
David Collins8885f792017-01-26 14:36:34 -08001128 rc = qpnp_flash_led_masked_write(led,
1129 FLASH_LED_REG_STROBE_CTRL(led->base + addr_offset),
Subbaraman Narayanamurthy3f684b22017-03-21 20:49:54 -07001130 mask, led->fnode[i].strobe_ctrl);
David Collins8885f792017-01-26 14:36:34 -08001131 if (rc < 0)
1132 return rc;
1133
1134 rc = qpnp_flash_led_masked_write(led,
1135 FLASH_LED_REG_TGR_CURRENT(led->base + addr_offset),
1136 FLASH_LED_CURRENT_MASK, led->fnode[i].current_reg_val);
1137 if (rc < 0)
1138 return rc;
1139
1140 rc = qpnp_flash_led_write(led,
1141 FLASH_LED_REG_SAFETY_TMR(led->base + addr_offset),
1142 led->fnode[i].duration);
1143 if (rc < 0)
1144 return rc;
1145
1146 val |= FLASH_LED_ENABLE << led->fnode[i].id;
1147
Subbaraman Narayanamurthy3f684b22017-03-21 20:49:54 -07001148 if (led->fnode[i].strobe_sel == HW_STROBE) {
David Collins8885f792017-01-26 14:36:34 -08001149 rc = qpnp_flash_led_hw_strobe_enable(&led->fnode[i],
1150 led->pdata->hw_strobe_option, true);
1151 if (rc < 0) {
1152 pr_err("Unable to enable hw strobe rc=%d\n",
1153 rc);
1154 return rc;
1155 }
1156 }
1157 }
1158
Subbaraman Narayanamurthy58377f02017-03-21 20:38:43 -07001159 if (snode->led_en_pinctrl) {
1160 pr_debug("Selecting active state for %s\n", snode->cdev.name);
1161 rc = pinctrl_select_state(snode->led_en_pinctrl,
1162 snode->gpio_state_active);
1163 if (rc < 0) {
1164 pr_err("failed to select pinctrl active state rc=%d\n",
1165 rc);
1166 return rc;
1167 }
1168 }
1169
David Collins8885f792017-01-26 14:36:34 -08001170 if (led->enable == 0) {
1171 rc = qpnp_flash_led_masked_write(led,
1172 FLASH_LED_REG_MOD_CTRL(led->base),
1173 FLASH_LED_MOD_CTRL_MASK, FLASH_LED_MOD_ENABLE);
1174 if (rc < 0)
1175 return rc;
1176 }
1177 led->enable++;
1178
1179 if (led->trigger_lmh) {
1180 rc = qpnp_flash_led_masked_write(led,
1181 FLASH_LED_REG_MITIGATION_SW(led->base),
1182 FLASH_LED_LMH_MITIGATION_EN_MASK,
1183 FLASH_LED_LMH_MITIGATION_ENABLE);
1184 if (rc < 0) {
1185 pr_err("trigger lmh mitigation failed, rc=%d\n", rc);
1186 return rc;
1187 }
Subbaraman Narayanamurthyd02fbc92017-02-02 16:39:41 -08001188 /* Wait for LMH mitigation to take effect */
1189 udelay(500);
David Collins8885f792017-01-26 14:36:34 -08001190 }
1191
1192 if (led->trigger_chgr) {
1193 rc = qpnp_flash_led_masked_write(led,
1194 FLASH_LED_REG_MITIGATION_SW(led->base),
1195 FLASH_LED_CHGR_MITIGATION_EN_MASK,
1196 FLASH_LED_CHGR_MITIGATION_ENABLE);
1197 if (rc < 0) {
1198 pr_err("trigger chgr mitigation failed, rc=%d\n", rc);
1199 return rc;
1200 }
1201 }
1202
1203 rc = qpnp_flash_led_masked_write(led,
1204 FLASH_LED_EN_LED_CTRL(led->base),
1205 snode->led_mask, val);
1206 if (rc < 0)
1207 return rc;
1208
1209 snode->enabled = true;
1210 return 0;
1211}
1212
1213int qpnp_flash_led_prepare(struct led_trigger *trig, int options,
1214 int *max_current)
1215{
1216 struct led_classdev *led_cdev;
1217 struct flash_switch_data *snode;
1218 struct qpnp_flash_led *led;
1219 int rc;
1220
1221 if (!trig) {
1222 pr_err("Invalid led_trigger provided\n");
1223 return -EINVAL;
1224 }
1225
1226 led_cdev = trigger_to_lcdev(trig);
1227 if (!led_cdev) {
1228 pr_err("Invalid led_cdev in trigger %s\n", trig->name);
1229 return -EINVAL;
1230 }
1231
1232 snode = container_of(led_cdev, struct flash_switch_data, cdev);
1233 led = dev_get_drvdata(&snode->pdev->dev);
1234
1235 if (!(options & FLASH_LED_PREPARE_OPTIONS_MASK)) {
1236 pr_err("Invalid options %d\n", options);
1237 return -EINVAL;
1238 }
1239
1240 if (options & ENABLE_REGULATOR) {
1241 rc = qpnp_flash_led_regulator_enable(led, snode, true);
1242 if (rc < 0) {
1243 pr_err("enable regulator failed, rc=%d\n", rc);
1244 return rc;
1245 }
1246 }
1247
1248 if (options & DISABLE_REGULATOR) {
1249 rc = qpnp_flash_led_regulator_enable(led, snode, false);
1250 if (rc < 0) {
1251 pr_err("disable regulator failed, rc=%d\n", rc);
1252 return rc;
1253 }
1254 }
1255
1256 if (options & QUERY_MAX_CURRENT) {
Subbaraman Narayanamurthyd94945e2017-11-28 19:54:09 -08001257 rc = qpnp_flash_led_get_max_avail_current(led, max_current);
David Collins8885f792017-01-26 14:36:34 -08001258 if (rc < 0) {
1259 pr_err("query max current failed, rc=%d\n", rc);
1260 return rc;
1261 }
David Collins8885f792017-01-26 14:36:34 -08001262 }
1263
David Collins8885f792017-01-26 14:36:34 -08001264 return 0;
1265}
1266
1267static void qpnp_flash_led_brightness_set(struct led_classdev *led_cdev,
1268 enum led_brightness value)
1269{
1270 struct flash_node_data *fnode = NULL;
1271 struct flash_switch_data *snode = NULL;
1272 struct qpnp_flash_led *led = NULL;
1273 int rc;
1274
1275 /*
1276 * strncmp() must be used here since a prefix comparison is required
1277 * in order to support names like led:switch_0 and led:flash_1.
1278 */
1279 if (!strncmp(led_cdev->name, "led:switch", strlen("led:switch"))) {
1280 snode = container_of(led_cdev, struct flash_switch_data, cdev);
1281 led = dev_get_drvdata(&snode->pdev->dev);
1282 } else if (!strncmp(led_cdev->name, "led:flash", strlen("led:flash")) ||
1283 !strncmp(led_cdev->name, "led:torch",
1284 strlen("led:torch"))) {
1285 fnode = container_of(led_cdev, struct flash_node_data, cdev);
1286 led = dev_get_drvdata(&fnode->pdev->dev);
1287 }
1288
1289 if (!led) {
1290 pr_err("Failed to get flash driver data\n");
1291 return;
1292 }
1293
1294 spin_lock(&led->lock);
1295 if (snode) {
1296 rc = qpnp_flash_led_switch_set(snode, value > 0);
1297 if (rc < 0)
1298 pr_err("Failed to set flash LED switch rc=%d\n", rc);
1299 } else if (fnode) {
1300 qpnp_flash_led_node_set(fnode, value);
1301 }
1302
1303 spin_unlock(&led->lock);
1304}
1305
1306/* sysfs show function for flash_max_current */
1307static ssize_t qpnp_flash_led_max_current_show(struct device *dev,
1308 struct device_attribute *attr, char *buf)
1309{
Subbaraman Narayanamurthyd94945e2017-11-28 19:54:09 -08001310 int rc, max_current = 0;
David Collins8885f792017-01-26 14:36:34 -08001311 struct flash_switch_data *snode;
1312 struct qpnp_flash_led *led;
1313 struct led_classdev *led_cdev = dev_get_drvdata(dev);
1314
1315 snode = container_of(led_cdev, struct flash_switch_data, cdev);
1316 led = dev_get_drvdata(&snode->pdev->dev);
1317
Subbaraman Narayanamurthyd94945e2017-11-28 19:54:09 -08001318 rc = qpnp_flash_led_get_max_avail_current(led, &max_current);
David Collins8885f792017-01-26 14:36:34 -08001319 if (rc < 0)
1320 pr_err("query max current failed, rc=%d\n", rc);
1321
Subbaraman Narayanamurthyd94945e2017-11-28 19:54:09 -08001322 return snprintf(buf, PAGE_SIZE, "%d\n", max_current);
David Collins8885f792017-01-26 14:36:34 -08001323}
1324
1325/* sysfs attributes exported by flash_led */
1326static struct device_attribute qpnp_flash_led_attrs[] = {
1327 __ATTR(max_current, 0664, qpnp_flash_led_max_current_show, NULL),
1328};
1329
1330static int flash_led_psy_notifier_call(struct notifier_block *nb,
1331 unsigned long ev, void *v)
1332{
1333 struct power_supply *psy = v;
1334 struct qpnp_flash_led *led =
1335 container_of(nb, struct qpnp_flash_led, nb);
1336
1337 if (ev != PSY_EVENT_PROP_CHANGED)
1338 return NOTIFY_OK;
1339
1340 if (!strcmp(psy->desc->name, "bms")) {
1341 led->bms_psy = power_supply_get_by_name("bms");
1342 if (!led->bms_psy)
1343 pr_err("Failed to get bms power_supply\n");
1344 else
1345 power_supply_unreg_notifier(&led->nb);
1346 }
1347
1348 return NOTIFY_OK;
1349}
1350
1351static int flash_led_psy_register_notifier(struct qpnp_flash_led *led)
1352{
1353 int rc;
1354
1355 led->nb.notifier_call = flash_led_psy_notifier_call;
1356 rc = power_supply_reg_notifier(&led->nb);
1357 if (rc < 0) {
1358 pr_err("Couldn't register psy notifier, rc = %d\n", rc);
1359 return rc;
1360 }
1361
1362 return 0;
1363}
1364
1365/* irq handler */
1366static irqreturn_t qpnp_flash_led_irq_handler(int irq, void *_led)
1367{
1368 struct qpnp_flash_led *led = _led;
1369 enum flash_led_irq_type irq_type = INVALID_IRQ;
1370 int rc;
1371 u8 irq_status, led_status1, led_status2;
1372
1373 pr_debug("irq received, irq=%d\n", irq);
1374
1375 rc = qpnp_flash_led_read(led,
1376 FLASH_LED_REG_INT_RT_STS(led->base), &irq_status);
1377 if (rc < 0) {
1378 pr_err("Failed to read interrupt status reg, rc=%d\n", rc);
1379 goto exit;
1380 }
1381
1382 if (irq == led->pdata->all_ramp_up_done_irq)
1383 irq_type = ALL_RAMP_UP_DONE_IRQ;
1384 else if (irq == led->pdata->all_ramp_down_done_irq)
1385 irq_type = ALL_RAMP_DOWN_DONE_IRQ;
1386 else if (irq == led->pdata->led_fault_irq)
1387 irq_type = LED_FAULT_IRQ;
1388
1389 if (irq_type == ALL_RAMP_UP_DONE_IRQ)
1390 atomic_notifier_call_chain(&irq_notifier_list,
1391 irq_type, NULL);
1392
1393 if (irq_type == LED_FAULT_IRQ) {
1394 rc = qpnp_flash_led_read(led,
1395 FLASH_LED_REG_LED_STATUS1(led->base), &led_status1);
1396 if (rc < 0) {
1397 pr_err("Failed to read led_status1 reg, rc=%d\n", rc);
1398 goto exit;
1399 }
1400
1401 rc = qpnp_flash_led_read(led,
1402 FLASH_LED_REG_LED_STATUS2(led->base), &led_status2);
1403 if (rc < 0) {
1404 pr_err("Failed to read led_status2 reg, rc=%d\n", rc);
1405 goto exit;
1406 }
1407
1408 if (led_status1)
1409 pr_emerg("led short/open fault detected! led_status1=%x\n",
1410 led_status1);
1411
1412 if (led_status2 & FLASH_LED_VPH_DROOP_FAULT_MASK)
1413 pr_emerg("led vph_droop fault detected!\n");
1414 }
1415
1416 pr_debug("irq handled, irq_type=%x, irq_status=%x\n", irq_type,
1417 irq_status);
1418
1419exit:
1420 return IRQ_HANDLED;
1421}
1422
1423int qpnp_flash_led_register_irq_notifier(struct notifier_block *nb)
1424{
1425 return atomic_notifier_chain_register(&irq_notifier_list, nb);
1426}
1427
1428int qpnp_flash_led_unregister_irq_notifier(struct notifier_block *nb)
1429{
1430 return atomic_notifier_chain_unregister(&irq_notifier_list, nb);
1431}
1432
1433static int qpnp_flash_led_parse_each_led_dt(struct qpnp_flash_led *led,
1434 struct flash_node_data *fnode, struct device_node *node)
1435{
1436 const char *temp_string;
Ankit Sharma8798ab12017-04-06 15:44:09 +05301437 int rc, min_ma;
David Collins8885f792017-01-26 14:36:34 -08001438 u32 val;
Subbaraman Narayanamurthy3f684b22017-03-21 20:49:54 -07001439 bool hw_strobe = 0, edge_trigger = 0, active_high = 0;
David Collins8885f792017-01-26 14:36:34 -08001440
1441 fnode->pdev = led->pdev;
1442 fnode->cdev.brightness_set = qpnp_flash_led_brightness_set;
1443 fnode->cdev.brightness_get = qpnp_flash_led_brightness_get;
1444
1445 rc = of_property_read_string(node, "qcom,led-name", &fnode->cdev.name);
1446 if (rc < 0) {
1447 pr_err("Unable to read flash LED names\n");
1448 return rc;
1449 }
1450
1451 rc = of_property_read_string(node, "label", &temp_string);
1452 if (!rc) {
1453 if (!strcmp(temp_string, "flash")) {
1454 fnode->type = FLASH_LED_TYPE_FLASH;
1455 } else if (!strcmp(temp_string, "torch")) {
1456 fnode->type = FLASH_LED_TYPE_TORCH;
1457 } else {
1458 pr_err("Wrong flash LED type\n");
1459 return rc;
1460 }
1461 } else {
1462 pr_err("Unable to read flash LED label\n");
1463 return rc;
1464 }
1465
1466 rc = of_property_read_u32(node, "qcom,id", &val);
1467 if (!rc) {
1468 fnode->id = (u8)val;
1469 } else {
1470 pr_err("Unable to read flash LED ID\n");
1471 return rc;
1472 }
1473
1474 rc = of_property_read_string(node, "qcom,default-led-trigger",
1475 &fnode->cdev.default_trigger);
1476 if (rc < 0) {
1477 pr_err("Unable to read trigger name\n");
1478 return rc;
1479 }
1480
Kiran Gunda5cadca72017-07-26 14:37:52 +05301481 fnode->default_ires_ua = fnode->ires_ua = FLASH_LED_IRES_DEFAULT_UA;
1482 fnode->default_ires_idx = fnode->ires_idx = FLASH_LED_IRES_DEFAULT_VAL;
David Collins8885f792017-01-26 14:36:34 -08001483 rc = of_property_read_u32(node, "qcom,ires-ua", &val);
1484 if (!rc) {
Kiran Gunda5cadca72017-07-26 14:37:52 +05301485 fnode->default_ires_ua = fnode->ires_ua = val;
1486 fnode->default_ires_idx = fnode->ires_idx =
1487 FLASH_LED_IRES_BASE - (val - FLASH_LED_IRES_MIN_UA) /
1488 FLASH_LED_IRES_DIVISOR;
David Collins8885f792017-01-26 14:36:34 -08001489 } else if (rc != -EINVAL) {
1490 pr_err("Unable to read current resolution rc=%d\n", rc);
1491 return rc;
1492 }
1493
Ankit Sharma8798ab12017-04-06 15:44:09 +05301494 min_ma = fnode->ires_ua / 1000;
David Collins8885f792017-01-26 14:36:34 -08001495 rc = of_property_read_u32(node, "qcom,max-current", &val);
1496 if (!rc) {
Ankit Sharma8798ab12017-04-06 15:44:09 +05301497 if (val < min_ma)
1498 val = min_ma;
David Collins8885f792017-01-26 14:36:34 -08001499 fnode->max_current = val;
1500 fnode->cdev.max_brightness = val;
1501 } else {
1502 pr_err("Unable to read max current, rc=%d\n", rc);
1503 return rc;
1504 }
1505
1506 rc = of_property_read_u32(node, "qcom,current-ma", &val);
1507 if (!rc) {
Ankit Sharma8798ab12017-04-06 15:44:09 +05301508 if (val < min_ma || val > fnode->max_current)
David Collins8885f792017-01-26 14:36:34 -08001509 pr_warn("Invalid operational current specified, capping it\n");
Ankit Sharma8798ab12017-04-06 15:44:09 +05301510 if (val < min_ma)
1511 val = min_ma;
David Collins8885f792017-01-26 14:36:34 -08001512 if (val > fnode->max_current)
1513 val = fnode->max_current;
1514 fnode->current_ma = val;
1515 fnode->cdev.brightness = val;
1516 } else if (rc != -EINVAL) {
1517 pr_err("Unable to read operational current, rc=%d\n", rc);
1518 return rc;
1519 }
1520
1521 fnode->duration = FLASH_LED_SAFETY_TMR_DISABLED;
1522 rc = of_property_read_u32(node, "qcom,duration-ms", &val);
1523 if (!rc) {
1524 fnode->duration = (u8)(SAFETY_TMR_TO_REG_VAL(val) |
1525 FLASH_LED_SAFETY_TMR_ENABLE);
1526 } else if (rc == -EINVAL) {
1527 if (fnode->type == FLASH_LED_TYPE_FLASH) {
1528 pr_err("Timer duration is required for flash LED\n");
1529 return rc;
1530 }
1531 } else {
1532 pr_err("Unable to read timer duration\n");
1533 return rc;
1534 }
1535
1536 fnode->hdrm_val = FLASH_LED_HDRM_VOL_DEFAULT_MV;
1537 rc = of_property_read_u32(node, "qcom,hdrm-voltage-mv", &val);
1538 if (!rc) {
1539 val = (val - FLASH_LED_HDRM_VOL_BASE_MV) /
1540 FLASH_LED_HDRM_VOL_STEP_MV;
1541 fnode->hdrm_val = (val << FLASH_LED_HDRM_VOL_SHIFT) &
1542 FLASH_LED_HDRM_VOL_MASK;
1543 } else if (rc != -EINVAL) {
1544 pr_err("Unable to read headroom voltage\n");
1545 return rc;
1546 }
1547
1548 rc = of_property_read_u32(node, "qcom,hdrm-vol-hi-lo-win-mv", &val);
1549 if (!rc) {
1550 fnode->hdrm_val |= (val / FLASH_LED_HDRM_VOL_STEP_MV) &
1551 ~FLASH_LED_HDRM_VOL_MASK;
1552 } else if (rc == -EINVAL) {
1553 fnode->hdrm_val |= FLASH_LED_HDRM_VOL_HI_LO_WIN_DEFAULT_MV;
1554 } else {
1555 pr_err("Unable to read hdrm hi-lo window voltage\n");
1556 return rc;
1557 }
1558
Subbaraman Narayanamurthy3f684b22017-03-21 20:49:54 -07001559 fnode->strobe_sel = SW_STROBE;
1560 rc = of_property_read_u32(node, "qcom,strobe-sel", &val);
1561 if (rc < 0) {
1562 if (rc != -EINVAL) {
1563 pr_err("Unable to read qcom,strobe-sel property\n");
1564 return rc;
1565 }
1566 } else {
1567 if (val < SW_STROBE || val > LPG_STROBE) {
1568 pr_err("Incorrect strobe selection specified %d\n",
1569 val);
1570 return -EINVAL;
1571 }
1572 fnode->strobe_sel = (u8)val;
1573 }
1574
1575 /*
1576 * LPG strobe is allowed only for LED3 and HW strobe option should be
1577 * option 2 or 3.
1578 */
1579 if (fnode->strobe_sel == LPG_STROBE) {
1580 if (led->pdata->hw_strobe_option ==
1581 FLASH_LED_HW_STROBE_OPTION_1) {
1582 pr_err("Incorrect strobe option for LPG strobe\n");
1583 return -EINVAL;
1584 }
1585 if (fnode->id != LED3) {
1586 pr_err("Incorrect LED chosen for LPG strobe\n");
1587 return -EINVAL;
1588 }
1589 }
1590
1591 if (fnode->strobe_sel == HW_STROBE) {
David Collins8885f792017-01-26 14:36:34 -08001592 edge_trigger = of_property_read_bool(node,
1593 "qcom,hw-strobe-edge-trigger");
1594 active_high = !of_property_read_bool(node,
1595 "qcom,hw-strobe-active-low");
Subbaraman Narayanamurthy3f684b22017-03-21 20:49:54 -07001596 hw_strobe = 1;
1597 } else if (fnode->strobe_sel == LPG_STROBE) {
1598 /* LPG strobe requires level trigger and active high */
1599 edge_trigger = 0;
1600 active_high = 1;
1601 hw_strobe = 1;
David Collins8885f792017-01-26 14:36:34 -08001602 }
Subbaraman Narayanamurthy3f684b22017-03-21 20:49:54 -07001603 fnode->strobe_ctrl = (hw_strobe << 2) | (edge_trigger << 1) |
1604 active_high;
David Collins8885f792017-01-26 14:36:34 -08001605
Subbaraman Narayanamurthy58377f02017-03-21 20:38:43 -07001606 rc = led_classdev_register(&led->pdev->dev, &fnode->cdev);
1607 if (rc < 0) {
1608 pr_err("Unable to register led node %d\n", fnode->id);
1609 return rc;
1610 }
1611
1612 fnode->cdev.dev->of_node = node;
1613 fnode->strobe_pinctrl = devm_pinctrl_get(fnode->cdev.dev);
1614 if (IS_ERR_OR_NULL(fnode->strobe_pinctrl)) {
1615 pr_debug("No pinctrl defined for %s, err=%ld\n",
1616 fnode->cdev.name, PTR_ERR(fnode->strobe_pinctrl));
1617 fnode->strobe_pinctrl = NULL;
1618 }
1619
Subbaraman Narayanamurthy3f684b22017-03-21 20:49:54 -07001620 if (fnode->strobe_sel == HW_STROBE) {
David Collins8885f792017-01-26 14:36:34 -08001621 if (of_find_property(node, "qcom,hw-strobe-gpio", NULL)) {
1622 fnode->hw_strobe_gpio = of_get_named_gpio(node,
1623 "qcom,hw-strobe-gpio", 0);
1624 if (fnode->hw_strobe_gpio < 0) {
1625 pr_err("Invalid gpio specified\n");
1626 return fnode->hw_strobe_gpio;
1627 }
1628 gpio_direction_output(fnode->hw_strobe_gpio, 0);
Subbaraman Narayanamurthy58377f02017-03-21 20:38:43 -07001629 } else if (fnode->strobe_pinctrl) {
David Collins8885f792017-01-26 14:36:34 -08001630 fnode->hw_strobe_gpio = -1;
1631 fnode->hw_strobe_state_active =
Subbaraman Narayanamurthy58377f02017-03-21 20:38:43 -07001632 pinctrl_lookup_state(fnode->strobe_pinctrl,
1633 "strobe_enable");
David Collins8885f792017-01-26 14:36:34 -08001634 if (IS_ERR_OR_NULL(fnode->hw_strobe_state_active)) {
1635 pr_err("No active pin for hardware strobe, rc=%ld\n",
1636 PTR_ERR(fnode->hw_strobe_state_active));
1637 fnode->hw_strobe_state_active = NULL;
1638 }
1639
1640 fnode->hw_strobe_state_suspend =
Subbaraman Narayanamurthy58377f02017-03-21 20:38:43 -07001641 pinctrl_lookup_state(fnode->strobe_pinctrl,
1642 "strobe_disable");
David Collins8885f792017-01-26 14:36:34 -08001643 if (IS_ERR_OR_NULL(fnode->hw_strobe_state_suspend)) {
1644 pr_err("No suspend pin for hardware strobe, rc=%ld\n",
1645 PTR_ERR(fnode->hw_strobe_state_suspend)
1646 );
1647 fnode->hw_strobe_state_suspend = NULL;
1648 }
1649 }
1650 }
1651
David Collins8885f792017-01-26 14:36:34 -08001652 return 0;
1653}
1654
1655static int qpnp_flash_led_parse_and_register_switch(struct qpnp_flash_led *led,
1656 struct flash_switch_data *snode,
1657 struct device_node *node)
1658{
1659 int rc = 0, num;
1660 char reg_name[16], reg_sup_name[16];
1661
1662 rc = of_property_read_string(node, "qcom,led-name", &snode->cdev.name);
1663 if (rc < 0) {
1664 pr_err("Failed to read switch node name, rc=%d\n", rc);
1665 return rc;
1666 }
1667
1668 rc = sscanf(snode->cdev.name, "led:switch_%d", &num);
1669 if (!rc) {
1670 pr_err("No number for switch device?\n");
1671 return -EINVAL;
1672 }
1673
1674 rc = of_property_read_string(node, "qcom,default-led-trigger",
1675 &snode->cdev.default_trigger);
1676 if (rc < 0) {
1677 pr_err("Unable to read trigger name, rc=%d\n", rc);
1678 return rc;
1679 }
1680
1681 rc = of_property_read_u32(node, "qcom,led-mask", &snode->led_mask);
1682 if (rc < 0) {
1683 pr_err("Unable to read led mask rc=%d\n", rc);
1684 return rc;
1685 }
1686
1687 if (snode->led_mask < 1 || snode->led_mask > 7) {
1688 pr_err("Invalid value for led-mask\n");
1689 return -EINVAL;
1690 }
1691
1692 scnprintf(reg_name, sizeof(reg_name), "switch%d-supply", num);
1693 if (of_find_property(led->pdev->dev.of_node, reg_name, NULL)) {
1694 scnprintf(reg_sup_name, sizeof(reg_sup_name), "switch%d", num);
1695 snode->vreg = devm_regulator_get(&led->pdev->dev, reg_sup_name);
1696 if (IS_ERR_OR_NULL(snode->vreg)) {
1697 rc = PTR_ERR(snode->vreg);
1698 if (rc != -EPROBE_DEFER)
1699 pr_err("Failed to get regulator, rc=%d\n", rc);
1700 snode->vreg = NULL;
1701 return rc;
1702 }
1703 }
1704
1705 snode->pdev = led->pdev;
1706 snode->cdev.brightness_set = qpnp_flash_led_brightness_set;
1707 snode->cdev.brightness_get = qpnp_flash_led_brightness_get;
1708 snode->cdev.flags |= LED_KEEP_TRIGGER;
1709 rc = led_classdev_register(&led->pdev->dev, &snode->cdev);
1710 if (rc < 0) {
1711 pr_err("Unable to register led switch node\n");
1712 return rc;
1713 }
1714
1715 snode->cdev.dev->of_node = node;
Subbaraman Narayanamurthy58377f02017-03-21 20:38:43 -07001716
1717 snode->led_en_pinctrl = devm_pinctrl_get(snode->cdev.dev);
1718 if (IS_ERR_OR_NULL(snode->led_en_pinctrl)) {
1719 pr_debug("No pinctrl defined for %s, err=%ld\n",
1720 snode->cdev.name, PTR_ERR(snode->led_en_pinctrl));
1721 snode->led_en_pinctrl = NULL;
1722 }
1723
1724 if (snode->led_en_pinctrl) {
1725 snode->gpio_state_active =
1726 pinctrl_lookup_state(snode->led_en_pinctrl,
1727 "led_enable");
1728 if (IS_ERR_OR_NULL(snode->gpio_state_active)) {
1729 pr_err("Cannot lookup LED active state\n");
1730 devm_pinctrl_put(snode->led_en_pinctrl);
1731 snode->led_en_pinctrl = NULL;
1732 return PTR_ERR(snode->gpio_state_active);
1733 }
1734
1735 snode->gpio_state_suspend =
1736 pinctrl_lookup_state(snode->led_en_pinctrl,
1737 "led_disable");
1738 if (IS_ERR_OR_NULL(snode->gpio_state_suspend)) {
1739 pr_err("Cannot lookup LED disable state\n");
1740 devm_pinctrl_put(snode->led_en_pinctrl);
1741 snode->led_en_pinctrl = NULL;
1742 return PTR_ERR(snode->gpio_state_suspend);
1743 }
1744 }
1745
David Collins8885f792017-01-26 14:36:34 -08001746 return 0;
1747}
1748
1749static int get_code_from_table(int *table, int len, int value)
1750{
1751 int i;
1752
1753 for (i = 0; i < len; i++) {
1754 if (value == table[i])
1755 break;
1756 }
1757
1758 if (i == len) {
1759 pr_err("Couldn't find %d from table\n", value);
1760 return -ENODATA;
1761 }
1762
1763 return i;
1764}
1765
1766static int qpnp_flash_led_parse_common_dt(struct qpnp_flash_led *led,
1767 struct device_node *node)
1768{
1769 struct device_node *revid_node;
1770 int rc;
1771 u32 val;
1772 bool short_circuit_det, open_circuit_det, vph_droop_det;
1773
1774 revid_node = of_parse_phandle(node, "qcom,pmic-revid", 0);
1775 if (!revid_node) {
1776 pr_err("Missing qcom,pmic-revid property - driver failed\n");
1777 return -EINVAL;
1778 }
1779
1780 led->pdata->pmic_rev_id = get_revid_data(revid_node);
1781 if (IS_ERR_OR_NULL(led->pdata->pmic_rev_id)) {
1782 pr_err("Unable to get pmic_revid rc=%ld\n",
1783 PTR_ERR(led->pdata->pmic_rev_id));
1784 /*
1785 * the revid peripheral must be registered, any failure
1786 * here only indicates that the rev-id module has not
1787 * probed yet.
1788 */
1789 return -EPROBE_DEFER;
1790 }
1791
1792 pr_debug("PMIC subtype %d Digital major %d\n",
1793 led->pdata->pmic_rev_id->pmic_subtype,
1794 led->pdata->pmic_rev_id->rev4);
1795
1796 led->pdata->hdrm_auto_mode_en = of_property_read_bool(node,
1797 "qcom,hdrm-auto-mode");
1798
1799 led->pdata->isc_delay = FLASH_LED_ISC_DELAY_DEFAULT;
1800 rc = of_property_read_u32(node, "qcom,isc-delay-us", &val);
1801 if (!rc) {
1802 led->pdata->isc_delay =
1803 val >> FLASH_LED_ISC_WARMUP_DELAY_SHIFT;
1804 } else if (rc != -EINVAL) {
1805 pr_err("Unable to read ISC delay, rc=%d\n", rc);
1806 return rc;
1807 }
1808
1809 led->pdata->warmup_delay = FLASH_LED_WARMUP_DELAY_DEFAULT;
1810 rc = of_property_read_u32(node, "qcom,warmup-delay-us", &val);
1811 if (!rc) {
1812 led->pdata->warmup_delay =
1813 val >> FLASH_LED_ISC_WARMUP_DELAY_SHIFT;
1814 } else if (rc != -EINVAL) {
1815 pr_err("Unable to read WARMUP delay, rc=%d\n", rc);
1816 return rc;
1817 }
1818
1819 short_circuit_det =
1820 of_property_read_bool(node, "qcom,short-circuit-det");
1821 open_circuit_det = of_property_read_bool(node, "qcom,open-circuit-det");
1822 vph_droop_det = of_property_read_bool(node, "qcom,vph-droop-det");
1823 led->pdata->current_derate_en_cfg = (vph_droop_det << 2) |
1824 (open_circuit_det << 1) | short_circuit_det;
1825
1826 led->pdata->thermal_derate_en =
1827 of_property_read_bool(node, "qcom,thermal-derate-en");
1828
1829 if (led->pdata->thermal_derate_en) {
1830 led->pdata->thermal_derate_current =
1831 devm_kcalloc(&led->pdev->dev,
1832 FLASH_LED_THERMAL_OTST_LEVELS,
1833 sizeof(int), GFP_KERNEL);
1834 if (!led->pdata->thermal_derate_current)
1835 return -ENOMEM;
1836
1837 rc = of_property_read_u32_array(node,
1838 "qcom,thermal-derate-current",
1839 led->pdata->thermal_derate_current,
1840 FLASH_LED_THERMAL_OTST_LEVELS);
1841 if (rc < 0) {
1842 pr_err("Unable to read thermal current limits, rc=%d\n",
1843 rc);
1844 return rc;
1845 }
1846 }
1847
1848 led->pdata->otst_ramp_bkup_en =
1849 !of_property_read_bool(node, "qcom,otst-ramp-back-up-dis");
1850
1851 led->pdata->thermal_derate_slow = -EINVAL;
1852 rc = of_property_read_u32(node, "qcom,thermal-derate-slow", &val);
1853 if (!rc) {
1854 if (val < 0 || val > THERMAL_DERATE_SLOW_MAX) {
1855 pr_err("Invalid thermal_derate_slow %d\n", val);
1856 return -EINVAL;
1857 }
1858
1859 led->pdata->thermal_derate_slow =
1860 get_code_from_table(thermal_derate_slow_table,
1861 ARRAY_SIZE(thermal_derate_slow_table), val);
1862 } else if (rc != -EINVAL) {
1863 pr_err("Unable to read thermal derate slow, rc=%d\n", rc);
1864 return rc;
1865 }
1866
1867 led->pdata->thermal_derate_fast = -EINVAL;
1868 rc = of_property_read_u32(node, "qcom,thermal-derate-fast", &val);
1869 if (!rc) {
1870 if (val < 0 || val > THERMAL_DERATE_FAST_MAX) {
1871 pr_err("Invalid thermal_derate_fast %d\n", val);
1872 return -EINVAL;
1873 }
1874
1875 led->pdata->thermal_derate_fast =
1876 get_code_from_table(thermal_derate_fast_table,
1877 ARRAY_SIZE(thermal_derate_fast_table), val);
1878 } else if (rc != -EINVAL) {
1879 pr_err("Unable to read thermal derate fast, rc=%d\n", rc);
1880 return rc;
1881 }
1882
1883 led->pdata->thermal_debounce = -EINVAL;
1884 rc = of_property_read_u32(node, "qcom,thermal-debounce", &val);
1885 if (!rc) {
1886 if (val < 0 || val > THERMAL_DEBOUNCE_TIME_MAX) {
1887 pr_err("Invalid thermal_debounce %d\n", val);
1888 return -EINVAL;
1889 }
1890
1891 if (val >= 0 && val < 16)
1892 led->pdata->thermal_debounce = 0;
1893 else
1894 led->pdata->thermal_debounce = ilog2(val) - 3;
1895 } else if (rc != -EINVAL) {
1896 pr_err("Unable to read thermal debounce, rc=%d\n", rc);
1897 return rc;
1898 }
1899
1900 led->pdata->thermal_hysteresis = -EINVAL;
1901 rc = of_property_read_u32(node, "qcom,thermal-hysteresis", &val);
1902 if (!rc) {
1903 if (led->pdata->pmic_rev_id->pmic_subtype == PM660L_SUBTYPE)
1904 val = THERMAL_HYST_TEMP_TO_VAL(val, 20);
1905 else
1906 val = THERMAL_HYST_TEMP_TO_VAL(val, 15);
1907
1908 if (val < 0 || val > THERMAL_DERATE_HYSTERESIS_MAX) {
1909 pr_err("Invalid thermal_derate_hysteresis %d\n", val);
1910 return -EINVAL;
1911 }
1912
1913 led->pdata->thermal_hysteresis = val;
1914 } else if (rc != -EINVAL) {
1915 pr_err("Unable to read thermal hysteresis, rc=%d\n", rc);
1916 return rc;
1917 }
1918
1919 led->pdata->thermal_thrsh1 = -EINVAL;
1920 rc = of_property_read_u32(node, "qcom,thermal-thrsh1", &val);
1921 if (!rc) {
1922 led->pdata->thermal_thrsh1 =
1923 get_code_from_table(otst1_threshold_table,
1924 ARRAY_SIZE(otst1_threshold_table), val);
1925 } else if (rc != -EINVAL) {
1926 pr_err("Unable to read thermal thrsh1, rc=%d\n", rc);
1927 return rc;
1928 }
1929
1930 led->pdata->thermal_thrsh2 = -EINVAL;
1931 rc = of_property_read_u32(node, "qcom,thermal-thrsh2", &val);
1932 if (!rc) {
1933 led->pdata->thermal_thrsh2 =
1934 get_code_from_table(otst2_threshold_table,
1935 ARRAY_SIZE(otst2_threshold_table), val);
1936 } else if (rc != -EINVAL) {
1937 pr_err("Unable to read thermal thrsh2, rc=%d\n", rc);
1938 return rc;
1939 }
1940
1941 led->pdata->thermal_thrsh3 = -EINVAL;
1942 rc = of_property_read_u32(node, "qcom,thermal-thrsh3", &val);
1943 if (!rc) {
1944 led->pdata->thermal_thrsh3 =
1945 get_code_from_table(otst3_threshold_table,
1946 ARRAY_SIZE(otst3_threshold_table), val);
1947 } else if (rc != -EINVAL) {
1948 pr_err("Unable to read thermal thrsh3, rc=%d\n", rc);
1949 return rc;
1950 }
1951
1952 led->pdata->vph_droop_debounce = FLASH_LED_VPH_DROOP_DEBOUNCE_DEFAULT;
1953 rc = of_property_read_u32(node, "qcom,vph-droop-debounce-us", &val);
1954 if (!rc) {
1955 led->pdata->vph_droop_debounce =
1956 VPH_DROOP_DEBOUNCE_US_TO_VAL(val);
1957 } else if (rc != -EINVAL) {
1958 pr_err("Unable to read VPH droop debounce, rc=%d\n", rc);
1959 return rc;
1960 }
1961
1962 if (led->pdata->vph_droop_debounce > FLASH_LED_DEBOUNCE_MAX) {
1963 pr_err("Invalid VPH droop debounce specified\n");
1964 return -EINVAL;
1965 }
1966
1967 led->pdata->vph_droop_threshold = FLASH_LED_VPH_DROOP_THRESH_DEFAULT;
1968 rc = of_property_read_u32(node, "qcom,vph-droop-threshold-mv", &val);
1969 if (!rc) {
1970 led->pdata->vph_droop_threshold =
1971 VPH_DROOP_THRESH_MV_TO_VAL(val);
1972 } else if (rc != -EINVAL) {
1973 pr_err("Unable to read VPH droop threshold, rc=%d\n", rc);
1974 return rc;
1975 }
1976
1977 if (led->pdata->vph_droop_threshold > FLASH_LED_VPH_DROOP_THRESH_MAX) {
1978 pr_err("Invalid VPH droop threshold specified\n");
1979 return -EINVAL;
1980 }
1981
1982 led->pdata->vph_droop_hysteresis =
1983 FLASH_LED_VPH_DROOP_HYST_DEFAULT;
1984 rc = of_property_read_u32(node, "qcom,vph-droop-hysteresis-mv", &val);
1985 if (!rc) {
1986 led->pdata->vph_droop_hysteresis =
1987 VPH_DROOP_HYST_MV_TO_VAL(val);
1988 } else if (rc != -EINVAL) {
1989 pr_err("Unable to read VPH droop hysteresis, rc=%d\n", rc);
1990 return rc;
1991 }
1992
1993 if (led->pdata->vph_droop_hysteresis > FLASH_LED_HYSTERESIS_MAX) {
1994 pr_err("Invalid VPH droop hysteresis specified\n");
1995 return -EINVAL;
1996 }
1997
1998 led->pdata->vph_droop_hysteresis <<= FLASH_LED_VPH_DROOP_HYST_SHIFT;
1999
Subbaraman Narayanamurthy3f684b22017-03-21 20:49:54 -07002000 led->pdata->hw_strobe_option = -EINVAL;
David Collins8885f792017-01-26 14:36:34 -08002001 rc = of_property_read_u32(node, "qcom,hw-strobe-option", &val);
2002 if (!rc) {
Subbaraman Narayanamurthy3f684b22017-03-21 20:49:54 -07002003 led->pdata->hw_strobe_option = val;
David Collins8885f792017-01-26 14:36:34 -08002004 } else if (rc != -EINVAL) {
2005 pr_err("Unable to parse hw strobe option, rc=%d\n", rc);
2006 return rc;
2007 }
2008
2009 rc = of_property_read_u32(node, "qcom,led1n2-iclamp-low-ma", &val);
2010 if (!rc) {
2011 led->pdata->led1n2_iclamp_low_ma = val;
2012 } else if (rc != -EINVAL) {
2013 pr_err("Unable to read led1n2_iclamp_low current, rc=%d\n", rc);
2014 return rc;
2015 }
2016
2017 rc = of_property_read_u32(node, "qcom,led1n2-iclamp-mid-ma", &val);
2018 if (!rc) {
2019 led->pdata->led1n2_iclamp_mid_ma = val;
2020 } else if (rc != -EINVAL) {
2021 pr_err("Unable to read led1n2_iclamp_mid current, rc=%d\n", rc);
2022 return rc;
2023 }
2024
2025 rc = of_property_read_u32(node, "qcom,led3-iclamp-low-ma", &val);
2026 if (!rc) {
2027 led->pdata->led3_iclamp_low_ma = val;
2028 } else if (rc != -EINVAL) {
2029 pr_err("Unable to read led3_iclamp_low current, rc=%d\n", rc);
2030 return rc;
2031 }
2032
2033 rc = of_property_read_u32(node, "qcom,led3-iclamp-mid-ma", &val);
2034 if (!rc) {
2035 led->pdata->led3_iclamp_mid_ma = val;
2036 } else if (rc != -EINVAL) {
2037 pr_err("Unable to read led3_iclamp_mid current, rc=%d\n", rc);
2038 return rc;
2039 }
2040
2041 led->pdata->vled_max_uv = FLASH_LED_VLED_MAX_DEFAULT_UV;
2042 rc = of_property_read_u32(node, "qcom,vled-max-uv", &val);
2043 if (!rc) {
2044 led->pdata->vled_max_uv = val;
2045 } else if (rc != -EINVAL) {
2046 pr_err("Unable to parse vled_max voltage, rc=%d\n", rc);
2047 return rc;
2048 }
2049
2050 led->pdata->ibatt_ocp_threshold_ua =
2051 FLASH_LED_IBATT_OCP_THRESH_DEFAULT_UA;
2052 rc = of_property_read_u32(node, "qcom,ibatt-ocp-threshold-ua", &val);
2053 if (!rc) {
2054 led->pdata->ibatt_ocp_threshold_ua = val;
2055 } else if (rc != -EINVAL) {
2056 pr_err("Unable to parse ibatt_ocp threshold, rc=%d\n", rc);
2057 return rc;
2058 }
2059
2060 led->pdata->rpara_uohm = FLASH_LED_RPARA_DEFAULT_UOHM;
2061 rc = of_property_read_u32(node, "qcom,rparasitic-uohm", &val);
2062 if (!rc) {
2063 led->pdata->rpara_uohm = val;
2064 } else if (rc != -EINVAL) {
2065 pr_err("Unable to parse rparasitic, rc=%d\n", rc);
2066 return rc;
2067 }
2068
2069 led->pdata->lmh_ocv_threshold_uv =
2070 FLASH_LED_LMH_OCV_THRESH_DEFAULT_UV;
2071 rc = of_property_read_u32(node, "qcom,lmh-ocv-threshold-uv", &val);
2072 if (!rc) {
2073 led->pdata->lmh_ocv_threshold_uv = val;
2074 } else if (rc != -EINVAL) {
2075 pr_err("Unable to parse lmh ocv threshold, rc=%d\n", rc);
2076 return rc;
2077 }
2078
2079 led->pdata->lmh_rbatt_threshold_uohm =
2080 FLASH_LED_LMH_RBATT_THRESH_DEFAULT_UOHM;
2081 rc = of_property_read_u32(node, "qcom,lmh-rbatt-threshold-uohm", &val);
2082 if (!rc) {
2083 led->pdata->lmh_rbatt_threshold_uohm = val;
2084 } else if (rc != -EINVAL) {
2085 pr_err("Unable to parse lmh rbatt threshold, rc=%d\n", rc);
2086 return rc;
2087 }
2088
2089 led->pdata->lmh_level = FLASH_LED_LMH_LEVEL_DEFAULT;
2090 rc = of_property_read_u32(node, "qcom,lmh-level", &val);
2091 if (!rc) {
2092 led->pdata->lmh_level = val;
2093 } else if (rc != -EINVAL) {
2094 pr_err("Unable to parse lmh_level, rc=%d\n", rc);
2095 return rc;
2096 }
2097
Ankit Sharmaa7153c32017-03-22 19:04:52 +05302098 led->pdata->lmh_mitigation_sel = FLASH_LED_LMH_MITIGATION_SEL_DEFAULT;
David Collins8885f792017-01-26 14:36:34 -08002099 rc = of_property_read_u32(node, "qcom,lmh-mitigation-sel", &val);
2100 if (!rc) {
2101 led->pdata->lmh_mitigation_sel = val;
2102 } else if (rc != -EINVAL) {
2103 pr_err("Unable to parse lmh_mitigation_sel, rc=%d\n", rc);
2104 return rc;
2105 }
2106
2107 if (led->pdata->lmh_mitigation_sel > FLASH_LED_MITIGATION_SEL_MAX) {
2108 pr_err("Invalid lmh_mitigation_sel specified\n");
2109 return -EINVAL;
2110 }
2111
Ankit Sharmaa7153c32017-03-22 19:04:52 +05302112 led->pdata->chgr_mitigation_sel = FLASH_SW_CHARGER_MITIGATION;
David Collins8885f792017-01-26 14:36:34 -08002113 rc = of_property_read_u32(node, "qcom,chgr-mitigation-sel", &val);
2114 if (!rc) {
2115 led->pdata->chgr_mitigation_sel = val;
2116 } else if (rc != -EINVAL) {
2117 pr_err("Unable to parse chgr_mitigation_sel, rc=%d\n", rc);
2118 return rc;
2119 }
2120
2121 if (led->pdata->chgr_mitigation_sel > FLASH_LED_MITIGATION_SEL_MAX) {
2122 pr_err("Invalid chgr_mitigation_sel specified\n");
2123 return -EINVAL;
2124 }
2125
Ankit Sharmaa7153c32017-03-22 19:04:52 +05302126 led->pdata->iled_thrsh_val = FLASH_LED_CHGR_MITIGATION_THRSH_DEFAULT;
David Collins8885f792017-01-26 14:36:34 -08002127 rc = of_property_read_u32(node, "qcom,iled-thrsh-ma", &val);
2128 if (!rc) {
2129 led->pdata->iled_thrsh_val = MITIGATION_THRSH_MA_TO_VAL(val);
2130 } else if (rc != -EINVAL) {
2131 pr_err("Unable to parse iled_thrsh_val, rc=%d\n", rc);
2132 return rc;
2133 }
2134
Ankit Sharmaa7153c32017-03-22 19:04:52 +05302135 if (led->pdata->iled_thrsh_val > FLASH_LED_CHGR_MITIGATION_THRSH_MAX) {
David Collins8885f792017-01-26 14:36:34 -08002136 pr_err("Invalid iled_thrsh_val specified\n");
2137 return -EINVAL;
2138 }
2139
2140 led->pdata->all_ramp_up_done_irq =
2141 of_irq_get_byname(node, "all-ramp-up-done-irq");
2142 if (led->pdata->all_ramp_up_done_irq < 0)
2143 pr_debug("all-ramp-up-done-irq not used\n");
2144
2145 led->pdata->all_ramp_down_done_irq =
2146 of_irq_get_byname(node, "all-ramp-down-done-irq");
2147 if (led->pdata->all_ramp_down_done_irq < 0)
2148 pr_debug("all-ramp-down-done-irq not used\n");
2149
2150 led->pdata->led_fault_irq =
2151 of_irq_get_byname(node, "led-fault-irq");
2152 if (led->pdata->led_fault_irq < 0)
2153 pr_debug("led-fault-irq not used\n");
2154
2155 return 0;
2156}
2157
2158static int qpnp_flash_led_probe(struct platform_device *pdev)
2159{
2160 struct qpnp_flash_led *led;
2161 struct device_node *node, *temp;
2162 const char *temp_string;
2163 unsigned int base;
2164 int rc, i = 0, j = 0;
2165
2166 node = pdev->dev.of_node;
2167 if (!node) {
2168 pr_err("No flash LED nodes defined\n");
2169 return -ENODEV;
2170 }
2171
2172 rc = of_property_read_u32(node, "reg", &base);
2173 if (rc < 0) {
2174 pr_err("Couldn't find reg in node %s, rc = %d\n",
2175 node->full_name, rc);
2176 return rc;
2177 }
2178
2179 led = devm_kzalloc(&pdev->dev, sizeof(struct qpnp_flash_led),
2180 GFP_KERNEL);
2181 if (!led)
2182 return -ENOMEM;
2183
2184 led->regmap = dev_get_regmap(pdev->dev.parent, NULL);
2185 if (!led->regmap) {
2186 pr_err("Couldn't get parent's regmap\n");
2187 return -EINVAL;
2188 }
2189
2190 led->base = base;
2191 led->pdev = pdev;
2192 led->pdata = devm_kzalloc(&pdev->dev,
2193 sizeof(struct flash_led_platform_data), GFP_KERNEL);
2194 if (!led->pdata)
2195 return -ENOMEM;
2196
2197 rc = qpnp_flash_led_parse_common_dt(led, node);
2198 if (rc < 0) {
2199 pr_err("Failed to parse common flash LED device tree\n");
2200 return rc;
2201 }
2202
2203 for_each_available_child_of_node(node, temp) {
2204 rc = of_property_read_string(temp, "label", &temp_string);
2205 if (rc < 0) {
2206 pr_err("Failed to parse label, rc=%d\n", rc);
2207 return rc;
2208 }
2209
2210 if (!strcmp("switch", temp_string)) {
2211 led->num_snodes++;
2212 } else if (!strcmp("flash", temp_string) ||
2213 !strcmp("torch", temp_string)) {
2214 led->num_fnodes++;
2215 } else {
2216 pr_err("Invalid label for led node\n");
2217 return -EINVAL;
2218 }
2219 }
2220
2221 if (!led->num_fnodes) {
2222 pr_err("No LED nodes defined\n");
2223 return -ECHILD;
2224 }
2225
2226 led->fnode = devm_kcalloc(&pdev->dev, led->num_fnodes,
2227 sizeof(*led->fnode),
2228 GFP_KERNEL);
2229 if (!led->fnode)
2230 return -ENOMEM;
2231
2232 led->snode = devm_kcalloc(&pdev->dev, led->num_snodes,
2233 sizeof(*led->snode),
2234 GFP_KERNEL);
2235 if (!led->snode)
2236 return -ENOMEM;
2237
2238 temp = NULL;
2239 i = 0;
2240 j = 0;
2241 for_each_available_child_of_node(node, temp) {
2242 rc = of_property_read_string(temp, "label", &temp_string);
2243 if (rc < 0) {
2244 pr_err("Failed to parse label, rc=%d\n", rc);
2245 return rc;
2246 }
2247
2248 if (!strcmp("flash", temp_string) ||
2249 !strcmp("torch", temp_string)) {
2250 rc = qpnp_flash_led_parse_each_led_dt(led,
Subbaraman Narayanamurthy01c99612017-04-03 12:26:06 -07002251 &led->fnode[i], temp);
David Collins8885f792017-01-26 14:36:34 -08002252 if (rc < 0) {
2253 pr_err("Unable to parse flash node %d rc=%d\n",
2254 i, rc);
2255 goto error_led_register;
2256 }
Subbaraman Narayanamurthy01c99612017-04-03 12:26:06 -07002257 i++;
David Collins8885f792017-01-26 14:36:34 -08002258 }
2259
2260 if (!strcmp("switch", temp_string)) {
2261 rc = qpnp_flash_led_parse_and_register_switch(led,
Subbaraman Narayanamurthy01c99612017-04-03 12:26:06 -07002262 &led->snode[j], temp);
David Collins8885f792017-01-26 14:36:34 -08002263 if (rc < 0) {
2264 pr_err("Unable to parse and register switch node, rc=%d\n",
2265 rc);
2266 goto error_switch_register;
2267 }
Subbaraman Narayanamurthy01c99612017-04-03 12:26:06 -07002268 j++;
David Collins8885f792017-01-26 14:36:34 -08002269 }
2270 }
2271
2272 /* setup irqs */
2273 if (led->pdata->all_ramp_up_done_irq >= 0) {
2274 rc = devm_request_threaded_irq(&led->pdev->dev,
2275 led->pdata->all_ramp_up_done_irq,
2276 NULL, qpnp_flash_led_irq_handler,
2277 IRQF_ONESHOT,
2278 "qpnp_flash_led_all_ramp_up_done_irq", led);
2279 if (rc < 0) {
2280 pr_err("Unable to request all_ramp_up_done(%d) IRQ(err:%d)\n",
2281 led->pdata->all_ramp_up_done_irq, rc);
2282 goto error_switch_register;
2283 }
2284 }
2285
2286 if (led->pdata->all_ramp_down_done_irq >= 0) {
2287 rc = devm_request_threaded_irq(&led->pdev->dev,
2288 led->pdata->all_ramp_down_done_irq,
2289 NULL, qpnp_flash_led_irq_handler,
2290 IRQF_ONESHOT,
2291 "qpnp_flash_led_all_ramp_down_done_irq", led);
2292 if (rc < 0) {
2293 pr_err("Unable to request all_ramp_down_done(%d) IRQ(err:%d)\n",
2294 led->pdata->all_ramp_down_done_irq, rc);
2295 goto error_switch_register;
2296 }
2297 }
2298
2299 if (led->pdata->led_fault_irq >= 0) {
2300 rc = devm_request_threaded_irq(&led->pdev->dev,
2301 led->pdata->led_fault_irq,
2302 NULL, qpnp_flash_led_irq_handler,
2303 IRQF_ONESHOT,
2304 "qpnp_flash_led_fault_irq", led);
2305 if (rc < 0) {
2306 pr_err("Unable to request led_fault(%d) IRQ(err:%d)\n",
2307 led->pdata->led_fault_irq, rc);
2308 goto error_switch_register;
2309 }
2310 }
2311
2312 led->bms_psy = power_supply_get_by_name("bms");
2313 if (!led->bms_psy) {
2314 rc = flash_led_psy_register_notifier(led);
2315 if (rc < 0) {
2316 pr_err("Couldn't register psy notifier, rc = %d\n", rc);
2317 goto error_switch_register;
2318 }
2319 }
2320
2321 rc = qpnp_flash_led_init_settings(led);
2322 if (rc < 0) {
2323 pr_err("Failed to initialize flash LED, rc=%d\n", rc);
2324 goto unreg_notifier;
2325 }
2326
2327 for (i = 0; i < led->num_snodes; i++) {
2328 for (j = 0; j < ARRAY_SIZE(qpnp_flash_led_attrs); j++) {
2329 rc = sysfs_create_file(&led->snode[i].cdev.dev->kobj,
2330 &qpnp_flash_led_attrs[j].attr);
2331 if (rc < 0) {
2332 pr_err("sysfs creation failed, rc=%d\n", rc);
2333 goto sysfs_fail;
2334 }
2335 }
2336 }
2337
2338 spin_lock_init(&led->lock);
2339
2340 dev_set_drvdata(&pdev->dev, led);
2341
2342 return 0;
2343
2344sysfs_fail:
2345 for (--j; j >= 0; j--)
2346 sysfs_remove_file(&led->snode[i].cdev.dev->kobj,
2347 &qpnp_flash_led_attrs[j].attr);
2348
2349 for (--i; i >= 0; i--) {
2350 for (j = 0; j < ARRAY_SIZE(qpnp_flash_led_attrs); j++)
2351 sysfs_remove_file(&led->snode[i].cdev.dev->kobj,
2352 &qpnp_flash_led_attrs[j].attr);
2353 }
2354
2355 i = led->num_snodes;
2356unreg_notifier:
2357 power_supply_unreg_notifier(&led->nb);
2358error_switch_register:
2359 while (i > 0)
2360 led_classdev_unregister(&led->snode[--i].cdev);
2361 i = led->num_fnodes;
2362error_led_register:
2363 while (i > 0)
2364 led_classdev_unregister(&led->fnode[--i].cdev);
2365
2366 return rc;
2367}
2368
2369static int qpnp_flash_led_remove(struct platform_device *pdev)
2370{
2371 struct qpnp_flash_led *led = dev_get_drvdata(&pdev->dev);
2372 int i, j;
2373
2374 for (i = 0; i < led->num_snodes; i++) {
2375 for (j = 0; j < ARRAY_SIZE(qpnp_flash_led_attrs); j++)
2376 sysfs_remove_file(&led->snode[i].cdev.dev->kobj,
2377 &qpnp_flash_led_attrs[j].attr);
2378
2379 if (led->snode[i].regulator_on)
2380 qpnp_flash_led_regulator_enable(led,
2381 &led->snode[i], false);
2382 }
2383
2384 while (i > 0)
2385 led_classdev_unregister(&led->snode[--i].cdev);
2386
2387 i = led->num_fnodes;
2388 while (i > 0)
2389 led_classdev_unregister(&led->fnode[--i].cdev);
2390
2391 power_supply_unreg_notifier(&led->nb);
2392 return 0;
2393}
2394
2395const struct of_device_id qpnp_flash_led_match_table[] = {
2396 { .compatible = "qcom,qpnp-flash-led-v2",},
2397 { },
2398};
2399
2400static struct platform_driver qpnp_flash_led_driver = {
2401 .driver = {
2402 .name = "qcom,qpnp-flash-led-v2",
2403 .of_match_table = qpnp_flash_led_match_table,
2404 },
2405 .probe = qpnp_flash_led_probe,
2406 .remove = qpnp_flash_led_remove,
2407};
2408
2409static int __init qpnp_flash_led_init(void)
2410{
2411 return platform_driver_register(&qpnp_flash_led_driver);
2412}
2413late_initcall(qpnp_flash_led_init);
2414
2415static void __exit qpnp_flash_led_exit(void)
2416{
2417 platform_driver_unregister(&qpnp_flash_led_driver);
2418}
2419module_exit(qpnp_flash_led_exit);
2420
2421MODULE_DESCRIPTION("QPNP Flash LED driver v2");
2422MODULE_LICENSE("GPL v2");
2423MODULE_ALIAS("leds:leds-qpnp-flash-v2");