blob: 2678a0054c731f937ac621f6ae3f4fcd2dc58a4f [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
161
162/* notifier call chain for flash-led irqs */
163static ATOMIC_NOTIFIER_HEAD(irq_notifier_list);
164
Ankit Sharmaa7153c32017-03-22 19:04:52 +0530165enum flash_charger_mitigation {
166 FLASH_DISABLE_CHARGER_MITIGATION,
167 FLASH_HW_CHARGER_MITIGATION_BY_ILED_THRSHLD,
168 FLASH_SW_CHARGER_MITIGATION,
169};
170
David Collins8885f792017-01-26 14:36:34 -0800171enum flash_led_type {
172 FLASH_LED_TYPE_FLASH,
173 FLASH_LED_TYPE_TORCH,
174};
175
176enum {
177 LED1 = 0,
178 LED2,
179 LED3,
180};
181
Subbaraman Narayanamurthy3f684b22017-03-21 20:49:54 -0700182enum strobe_type {
183 SW_STROBE = 0,
184 HW_STROBE,
185 LPG_STROBE,
186};
187
David Collins8885f792017-01-26 14:36:34 -0800188/*
189 * Configurations for each individual LED
190 */
191struct flash_node_data {
192 struct platform_device *pdev;
193 struct led_classdev cdev;
Subbaraman Narayanamurthy58377f02017-03-21 20:38:43 -0700194 struct pinctrl *strobe_pinctrl;
David Collins8885f792017-01-26 14:36:34 -0800195 struct pinctrl_state *hw_strobe_state_active;
196 struct pinctrl_state *hw_strobe_state_suspend;
197 int hw_strobe_gpio;
198 int ires_ua;
199 int max_current;
200 int current_ma;
Ankit Sharmaa7153c32017-03-22 19:04:52 +0530201 int prev_current_ma;
David Collins8885f792017-01-26 14:36:34 -0800202 u8 duration;
203 u8 id;
204 u8 type;
205 u8 ires;
206 u8 hdrm_val;
207 u8 current_reg_val;
Subbaraman Narayanamurthy3f684b22017-03-21 20:49:54 -0700208 u8 strobe_ctrl;
209 u8 strobe_sel;
David Collins8885f792017-01-26 14:36:34 -0800210 bool led_on;
211};
212
213
214struct flash_switch_data {
215 struct platform_device *pdev;
216 struct regulator *vreg;
Subbaraman Narayanamurthy58377f02017-03-21 20:38:43 -0700217 struct pinctrl *led_en_pinctrl;
218 struct pinctrl_state *gpio_state_active;
219 struct pinctrl_state *gpio_state_suspend;
David Collins8885f792017-01-26 14:36:34 -0800220 struct led_classdev cdev;
221 int led_mask;
222 bool regulator_on;
223 bool enabled;
224};
225
226/*
227 * Flash LED configuration read from device tree
228 */
229struct flash_led_platform_data {
230 struct pmic_revid_data *pmic_rev_id;
231 int *thermal_derate_current;
232 int all_ramp_up_done_irq;
233 int all_ramp_down_done_irq;
234 int led_fault_irq;
235 int ibatt_ocp_threshold_ua;
236 int vled_max_uv;
237 int rpara_uohm;
238 int lmh_rbatt_threshold_uohm;
239 int lmh_ocv_threshold_uv;
240 int thermal_derate_slow;
241 int thermal_derate_fast;
242 int thermal_hysteresis;
243 int thermal_debounce;
244 int thermal_thrsh1;
245 int thermal_thrsh2;
246 int thermal_thrsh3;
Subbaraman Narayanamurthy3f684b22017-03-21 20:49:54 -0700247 int hw_strobe_option;
David Collins8885f792017-01-26 14:36:34 -0800248 u32 led1n2_iclamp_low_ma;
249 u32 led1n2_iclamp_mid_ma;
250 u32 led3_iclamp_low_ma;
251 u32 led3_iclamp_mid_ma;
252 u8 isc_delay;
253 u8 warmup_delay;
254 u8 current_derate_en_cfg;
255 u8 vph_droop_threshold;
256 u8 vph_droop_hysteresis;
257 u8 vph_droop_debounce;
258 u8 lmh_mitigation_sel;
259 u8 chgr_mitigation_sel;
260 u8 lmh_level;
261 u8 iled_thrsh_val;
David Collins8885f792017-01-26 14:36:34 -0800262 bool hdrm_auto_mode_en;
263 bool thermal_derate_en;
264 bool otst_ramp_bkup_en;
265};
266
267/*
268 * Flash LED data structure containing flash LED attributes
269 */
270struct qpnp_flash_led {
271 struct flash_led_platform_data *pdata;
272 struct platform_device *pdev;
273 struct regmap *regmap;
274 struct flash_node_data *fnode;
275 struct flash_switch_data *snode;
276 struct power_supply *bms_psy;
277 struct notifier_block nb;
278 spinlock_t lock;
279 int num_fnodes;
280 int num_snodes;
281 int enable;
Ankit Sharmaa7153c32017-03-22 19:04:52 +0530282 int total_current_ma;
David Collins8885f792017-01-26 14:36:34 -0800283 u16 base;
284 bool trigger_lmh;
285 bool trigger_chgr;
286};
287
288static int thermal_derate_slow_table[] = {
289 128, 256, 512, 1024, 2048, 4096, 8192, 314592,
290};
291
292static int thermal_derate_fast_table[] = {
293 32, 64, 96, 128, 256, 384, 512,
294};
295
296static int otst1_threshold_table[] = {
297 85, 79, 73, 67, 109, 103, 97, 91,
298};
299
300static int otst2_threshold_table[] = {
301 110, 104, 98, 92, 134, 128, 122, 116,
302};
303
304static int otst3_threshold_table[] = {
305 125, 119, 113, 107, 149, 143, 137, 131,
306};
307
308static int qpnp_flash_led_read(struct qpnp_flash_led *led, u16 addr, u8 *data)
309{
310 int rc;
311 uint val;
312
313 rc = regmap_read(led->regmap, addr, &val);
314 if (rc < 0) {
315 pr_err("Unable to read from 0x%04X rc = %d\n", addr, rc);
316 return rc;
317 }
318
319 pr_debug("Read 0x%02X from addr 0x%04X\n", val, addr);
320 *data = (u8)val;
321 return 0;
322}
323
324static int qpnp_flash_led_write(struct qpnp_flash_led *led, u16 addr, u8 data)
325{
326 int rc;
327
328 rc = regmap_write(led->regmap, addr, data);
329 if (rc < 0) {
330 pr_err("Unable to write to 0x%04X rc = %d\n", addr, rc);
331 return rc;
332 }
333
334 pr_debug("Wrote 0x%02X to addr 0x%04X\n", data, addr);
335 return 0;
336}
337
338static int
339qpnp_flash_led_masked_read(struct qpnp_flash_led *led, u16 addr, u8 mask,
340 u8 *val)
341{
342 int rc;
343
344 rc = qpnp_flash_led_read(led, addr, val);
345 if (rc < 0)
346 return rc;
347
348 *val &= mask;
349 return rc;
350}
351
352static int
353qpnp_flash_led_masked_write(struct qpnp_flash_led *led, u16 addr, u8 mask,
354 u8 val)
355{
356 int rc;
357
358 rc = regmap_update_bits(led->regmap, addr, mask, val);
359 if (rc < 0)
360 pr_err("Unable to update bits from 0x%04X, rc = %d\n", addr,
361 rc);
362 else
363 pr_debug("Wrote 0x%02X to addr 0x%04X\n", val, addr);
364
365 return rc;
366}
367
368static enum
369led_brightness qpnp_flash_led_brightness_get(struct led_classdev *led_cdev)
370{
371 return led_cdev->brightness;
372}
373
374static int qpnp_flash_led_init_settings(struct qpnp_flash_led *led)
375{
376 int rc, i, addr_offset;
377 u8 val = 0, mask;
378
379 for (i = 0; i < led->num_fnodes; i++) {
380 addr_offset = led->fnode[i].id;
381 rc = qpnp_flash_led_write(led,
382 FLASH_LED_REG_HDRM_PRGM(led->base + addr_offset),
383 led->fnode[i].hdrm_val);
384 if (rc < 0)
385 return rc;
386
387 val |= 0x1 << led->fnode[i].id;
388 }
389
390 rc = qpnp_flash_led_write(led,
391 FLASH_LED_REG_HDRM_AUTO_MODE_CTRL(led->base),
392 val);
393 if (rc < 0)
394 return rc;
395
396 rc = qpnp_flash_led_masked_write(led,
397 FLASH_LED_REG_ISC_DELAY(led->base),
398 FLASH_LED_ISC_WARMUP_DELAY_MASK,
399 led->pdata->isc_delay);
400 if (rc < 0)
401 return rc;
402
403 rc = qpnp_flash_led_masked_write(led,
404 FLASH_LED_REG_WARMUP_DELAY(led->base),
405 FLASH_LED_ISC_WARMUP_DELAY_MASK,
406 led->pdata->warmup_delay);
407 if (rc < 0)
408 return rc;
409
410 rc = qpnp_flash_led_masked_write(led,
411 FLASH_LED_REG_CURRENT_DERATE_EN(led->base),
412 FLASH_LED_CURRENT_DERATE_EN_MASK,
413 led->pdata->current_derate_en_cfg);
414 if (rc < 0)
415 return rc;
416
417 val = (led->pdata->otst_ramp_bkup_en << THERMAL_OTST1_RAMP_CTRL_SHIFT);
418 mask = THERMAL_OTST1_RAMP_CTRL_MASK;
419 if (led->pdata->thermal_derate_slow >= 0) {
420 val |= (led->pdata->thermal_derate_slow <<
421 THERMAL_DERATE_SLOW_SHIFT);
422 mask |= THERMAL_DERATE_SLOW_MASK;
423 }
424
425 if (led->pdata->thermal_derate_fast >= 0) {
426 val |= led->pdata->thermal_derate_fast;
427 mask |= THERMAL_DERATE_FAST_MASK;
428 }
429
430 rc = qpnp_flash_led_masked_write(led,
431 FLASH_LED_REG_THERMAL_RMP_DN_RATE(led->base),
432 mask, val);
433 if (rc < 0)
434 return rc;
435
436 if (led->pdata->thermal_debounce >= 0) {
437 rc = qpnp_flash_led_masked_write(led,
438 FLASH_LED_REG_THERMAL_DEBOUNCE(led->base),
439 FLASH_LED_THERMAL_DEBOUNCE_MASK,
440 led->pdata->thermal_debounce);
441 if (rc < 0)
442 return rc;
443 }
444
445 if (led->pdata->thermal_hysteresis >= 0) {
446 rc = qpnp_flash_led_masked_write(led,
447 FLASH_LED_REG_THERMAL_HYSTERESIS(led->base),
448 FLASH_LED_THERMAL_HYSTERESIS_MASK,
449 led->pdata->thermal_hysteresis);
450 if (rc < 0)
451 return rc;
452 }
453
454 if (led->pdata->thermal_thrsh1 >= 0) {
455 rc = qpnp_flash_led_masked_write(led,
456 FLASH_LED_REG_THERMAL_THRSH1(led->base),
457 FLASH_LED_THERMAL_THRSH_MASK,
458 led->pdata->thermal_thrsh1);
459 if (rc < 0)
460 return rc;
461 }
462
463 if (led->pdata->thermal_thrsh2 >= 0) {
464 rc = qpnp_flash_led_masked_write(led,
465 FLASH_LED_REG_THERMAL_THRSH2(led->base),
466 FLASH_LED_THERMAL_THRSH_MASK,
467 led->pdata->thermal_thrsh2);
468 if (rc < 0)
469 return rc;
470 }
471
472 if (led->pdata->thermal_thrsh3 >= 0) {
473 rc = qpnp_flash_led_masked_write(led,
474 FLASH_LED_REG_THERMAL_THRSH3(led->base),
475 FLASH_LED_THERMAL_THRSH_MASK,
476 led->pdata->thermal_thrsh3);
477 if (rc < 0)
478 return rc;
479 }
480
481 rc = qpnp_flash_led_masked_write(led,
482 FLASH_LED_REG_VPH_DROOP_DEBOUNCE(led->base),
483 FLASH_LED_VPH_DROOP_DEBOUNCE_MASK,
484 led->pdata->vph_droop_debounce);
485 if (rc < 0)
486 return rc;
487
488 rc = qpnp_flash_led_masked_write(led,
489 FLASH_LED_REG_VPH_DROOP_THRESHOLD(led->base),
490 FLASH_LED_VPH_DROOP_THRESHOLD_MASK,
491 led->pdata->vph_droop_threshold);
492 if (rc < 0)
493 return rc;
494
495 rc = qpnp_flash_led_masked_write(led,
496 FLASH_LED_REG_VPH_DROOP_THRESHOLD(led->base),
497 FLASH_LED_VPH_DROOP_HYSTERESIS_MASK,
498 led->pdata->vph_droop_hysteresis);
499 if (rc < 0)
500 return rc;
501
502 rc = qpnp_flash_led_masked_write(led,
503 FLASH_LED_REG_MITIGATION_SEL(led->base),
504 FLASH_LED_LMH_MITIGATION_SEL_MASK,
505 led->pdata->lmh_mitigation_sel);
506 if (rc < 0)
507 return rc;
508
Ankit Sharmaa7153c32017-03-22 19:04:52 +0530509 val = led->pdata->chgr_mitigation_sel
510 << FLASH_LED_CHGR_MITIGATION_SEL_SHIFT;
David Collins8885f792017-01-26 14:36:34 -0800511 rc = qpnp_flash_led_masked_write(led,
512 FLASH_LED_REG_MITIGATION_SEL(led->base),
513 FLASH_LED_CHGR_MITIGATION_SEL_MASK,
Ankit Sharmaa7153c32017-03-22 19:04:52 +0530514 val);
David Collins8885f792017-01-26 14:36:34 -0800515 if (rc < 0)
516 return rc;
517
518 rc = qpnp_flash_led_masked_write(led,
519 FLASH_LED_REG_LMH_LEVEL(led->base),
520 FLASH_LED_LMH_LEVEL_MASK,
521 led->pdata->lmh_level);
522 if (rc < 0)
523 return rc;
524
525 rc = qpnp_flash_led_masked_write(led,
526 FLASH_LED_REG_ILED_GRT_THRSH(led->base),
527 FLASH_LED_ILED_GRT_THRSH_MASK,
528 led->pdata->iled_thrsh_val);
529 if (rc < 0)
530 return rc;
531
532 if (led->pdata->led1n2_iclamp_low_ma) {
533 val = CURRENT_MA_TO_REG_VAL(led->pdata->led1n2_iclamp_low_ma,
Subbaraman Narayanamurthy01c99612017-04-03 12:26:06 -0700534 led->fnode[LED1].ires_ua);
David Collins8885f792017-01-26 14:36:34 -0800535 rc = qpnp_flash_led_masked_write(led,
536 FLASH_LED_REG_LED1N2_ICLAMP_LOW(led->base),
537 FLASH_LED_CURRENT_MASK, val);
538 if (rc < 0)
539 return rc;
540 }
541
542 if (led->pdata->led1n2_iclamp_mid_ma) {
543 val = CURRENT_MA_TO_REG_VAL(led->pdata->led1n2_iclamp_mid_ma,
Subbaraman Narayanamurthy01c99612017-04-03 12:26:06 -0700544 led->fnode[LED1].ires_ua);
David Collins8885f792017-01-26 14:36:34 -0800545 rc = qpnp_flash_led_masked_write(led,
546 FLASH_LED_REG_LED1N2_ICLAMP_MID(led->base),
547 FLASH_LED_CURRENT_MASK, val);
548 if (rc < 0)
549 return rc;
550 }
551
552 if (led->pdata->led3_iclamp_low_ma) {
553 val = CURRENT_MA_TO_REG_VAL(led->pdata->led3_iclamp_low_ma,
Subbaraman Narayanamurthy01c99612017-04-03 12:26:06 -0700554 led->fnode[LED3].ires_ua);
David Collins8885f792017-01-26 14:36:34 -0800555 rc = qpnp_flash_led_masked_write(led,
556 FLASH_LED_REG_LED3_ICLAMP_LOW(led->base),
557 FLASH_LED_CURRENT_MASK, val);
558 if (rc < 0)
559 return rc;
560 }
561
562 if (led->pdata->led3_iclamp_mid_ma) {
563 val = CURRENT_MA_TO_REG_VAL(led->pdata->led3_iclamp_mid_ma,
Subbaraman Narayanamurthy01c99612017-04-03 12:26:06 -0700564 led->fnode[LED3].ires_ua);
David Collins8885f792017-01-26 14:36:34 -0800565 rc = qpnp_flash_led_masked_write(led,
566 FLASH_LED_REG_LED3_ICLAMP_MID(led->base),
567 FLASH_LED_CURRENT_MASK, val);
568 if (rc < 0)
569 return rc;
570 }
571
Subbaraman Narayanamurthy3f684b22017-03-21 20:49:54 -0700572 if (led->pdata->hw_strobe_option > 0) {
573 rc = qpnp_flash_led_masked_write(led,
574 FLASH_LED_REG_STROBE_CFG(led->base),
575 FLASH_LED_STROBE_MASK,
576 led->pdata->hw_strobe_option);
577 if (rc < 0)
578 return rc;
579 }
580
581 if (led->fnode[LED3].strobe_sel == LPG_STROBE) {
582 rc = qpnp_flash_led_masked_write(led,
583 FLASH_LED_REG_MULTI_STROBE_CTRL(led->base),
584 LED3_FLASH_ONCE_ONLY_BIT, 0);
585 if (rc < 0)
586 return rc;
587
588 rc = qpnp_flash_led_masked_write(led,
589 FLASH_LED_REG_LPG_INPUT_CTRL(led->base),
590 LPG_INPUT_SEL_BIT, LPG_INPUT_SEL_BIT);
591 if (rc < 0)
592 return rc;
593 }
David Collins8885f792017-01-26 14:36:34 -0800594 return 0;
595}
596
597static int qpnp_flash_led_hw_strobe_enable(struct flash_node_data *fnode,
598 int hw_strobe_option, bool on)
599{
600 int rc = 0;
601
602 /*
603 * If the LED controlled by this fnode is not GPIO controlled
604 * for the given strobe_option, return.
605 */
606 if (hw_strobe_option == FLASH_LED_HW_STROBE_OPTION_1)
607 return 0;
608 else if (hw_strobe_option == FLASH_LED_HW_STROBE_OPTION_2
609 && fnode->id != LED3)
610 return 0;
611 else if (hw_strobe_option == FLASH_LED_HW_STROBE_OPTION_3
612 && fnode->id == LED1)
613 return 0;
614
615 if (gpio_is_valid(fnode->hw_strobe_gpio)) {
616 gpio_set_value(fnode->hw_strobe_gpio, on ? 1 : 0);
Subbaraman Narayanamurthy58377f02017-03-21 20:38:43 -0700617 } else if (fnode->strobe_pinctrl && fnode->hw_strobe_state_active &&
David Collins8885f792017-01-26 14:36:34 -0800618 fnode->hw_strobe_state_suspend) {
Subbaraman Narayanamurthy58377f02017-03-21 20:38:43 -0700619 rc = pinctrl_select_state(fnode->strobe_pinctrl,
David Collins8885f792017-01-26 14:36:34 -0800620 on ? fnode->hw_strobe_state_active :
621 fnode->hw_strobe_state_suspend);
622 if (rc < 0) {
623 pr_err("failed to change hw strobe pin state\n");
624 return rc;
625 }
626 }
627
628 return rc;
629}
630
631static int qpnp_flash_led_regulator_enable(struct qpnp_flash_led *led,
632 struct flash_switch_data *snode, bool on)
633{
634 int rc = 0;
635
636 if (!snode || !snode->vreg)
637 return 0;
638
639 if (snode->regulator_on == on)
640 return 0;
641
642 if (on)
643 rc = regulator_enable(snode->vreg);
644 else
645 rc = regulator_disable(snode->vreg);
646
647 if (rc < 0) {
648 pr_err("regulator_%s failed, rc=%d\n",
649 on ? "enable" : "disable", rc);
650 return rc;
651 }
652
653 snode->regulator_on = on ? true : false;
654 return 0;
655}
656
657static int get_property_from_fg(struct qpnp_flash_led *led,
658 enum power_supply_property prop, int *val)
659{
660 int rc;
661 union power_supply_propval pval = {0, };
662
663 if (!led->bms_psy) {
664 pr_err("no bms psy found\n");
665 return -EINVAL;
666 }
667
668 rc = power_supply_get_property(led->bms_psy, prop, &pval);
669 if (rc) {
670 pr_err("bms psy doesn't support reading prop %d rc = %d\n",
671 prop, rc);
672 return rc;
673 }
674
675 *val = pval.intval;
676 return rc;
677}
678
679#define VOLTAGE_HDRM_DEFAULT_MV 350
680static int qpnp_flash_led_get_voltage_headroom(struct qpnp_flash_led *led)
681{
682 int i, voltage_hdrm_mv = 0, voltage_hdrm_max = 0;
683
684 for (i = 0; i < led->num_fnodes; i++) {
685 if (led->fnode[i].led_on) {
686 if (led->fnode[i].id < 2) {
687 if (led->fnode[i].current_ma < 750)
688 voltage_hdrm_mv = 125;
689 else if (led->fnode[i].current_ma < 1000)
690 voltage_hdrm_mv = 175;
691 else if (led->fnode[i].current_ma < 1250)
692 voltage_hdrm_mv = 250;
693 else
694 voltage_hdrm_mv = 350;
695 } else {
696 if (led->fnode[i].current_ma < 375)
697 voltage_hdrm_mv = 125;
698 else if (led->fnode[i].current_ma < 500)
699 voltage_hdrm_mv = 175;
700 else if (led->fnode[i].current_ma < 625)
701 voltage_hdrm_mv = 250;
702 else
703 voltage_hdrm_mv = 350;
704 }
705
706 voltage_hdrm_max = max(voltage_hdrm_max,
707 voltage_hdrm_mv);
708 }
709 }
710
711 if (!voltage_hdrm_max)
712 return VOLTAGE_HDRM_DEFAULT_MV;
713
714 return voltage_hdrm_max;
715}
716
717#define UCONV 1000000LL
718#define MCONV 1000LL
719#define FLASH_VDIP_MARGIN 50000
720#define BOB_EFFICIENCY 900LL
721#define VIN_FLASH_MIN_UV 3300000LL
722static int qpnp_flash_led_calc_max_current(struct qpnp_flash_led *led)
723{
Kyle Yan74fdd732017-03-22 13:37:08 -0700724 int ocv_uv, ibat_now, voltage_hdrm_mv, rc;
725 int rbatt_uohm = 0;
David Collins8885f792017-01-26 14:36:34 -0800726 int64_t ibat_flash_ua, avail_flash_ua, avail_flash_power_fw;
727 int64_t ibat_safe_ua, vin_flash_uv, vph_flash_uv, vph_flash_vdip;
728
729 /* RESISTANCE = esr_uohm + rslow_uohm */
730 rc = get_property_from_fg(led, POWER_SUPPLY_PROP_RESISTANCE,
731 &rbatt_uohm);
732 if (rc < 0) {
733 pr_err("bms psy does not support resistance, rc=%d\n", rc);
734 return rc;
735 }
736
737 /* If no battery is connected, return max possible flash current */
738 if (!rbatt_uohm)
739 return FLASH_LED_MAX_TOTAL_CURRENT_MA;
740
741 rc = get_property_from_fg(led, POWER_SUPPLY_PROP_VOLTAGE_OCV, &ocv_uv);
742 if (rc < 0) {
743 pr_err("bms psy does not support OCV, rc=%d\n", rc);
744 return rc;
745 }
746
747 rc = get_property_from_fg(led, POWER_SUPPLY_PROP_CURRENT_NOW,
748 &ibat_now);
749 if (rc < 0) {
750 pr_err("bms psy does not support current, rc=%d\n", rc);
751 return rc;
752 }
753
754 rbatt_uohm += led->pdata->rpara_uohm;
755 voltage_hdrm_mv = qpnp_flash_led_get_voltage_headroom(led);
756 vph_flash_vdip =
757 VPH_DROOP_THRESH_VAL_TO_UV(led->pdata->vph_droop_threshold)
758 + FLASH_VDIP_MARGIN;
759
760 /* Check if LMH_MITIGATION needs to be triggered */
761 if (!led->trigger_lmh && (ocv_uv < led->pdata->lmh_ocv_threshold_uv ||
762 rbatt_uohm > led->pdata->lmh_rbatt_threshold_uohm)) {
763 led->trigger_lmh = true;
764 rc = qpnp_flash_led_masked_write(led,
765 FLASH_LED_REG_MITIGATION_SW(led->base),
766 FLASH_LED_LMH_MITIGATION_EN_MASK,
767 FLASH_LED_LMH_MITIGATION_ENABLE);
768 if (rc < 0) {
769 pr_err("trigger lmh mitigation failed, rc=%d\n", rc);
770 return rc;
771 }
772
773 /* Wait for LMH mitigation to take effect */
774 udelay(100);
775
776 return qpnp_flash_led_calc_max_current(led);
777 }
778
779 /*
780 * Calculate the maximum current that can pulled out of the battery
781 * before the battery voltage dips below a safe threshold.
782 */
783 ibat_safe_ua = div_s64((ocv_uv - vph_flash_vdip) * UCONV,
784 rbatt_uohm);
785
786 if (ibat_safe_ua <= led->pdata->ibatt_ocp_threshold_ua) {
787 /*
788 * If the calculated current is below the OCP threshold, then
789 * use it as the possible flash current.
790 */
791 ibat_flash_ua = ibat_safe_ua - ibat_now;
792 vph_flash_uv = vph_flash_vdip;
793 } else {
794 /*
795 * If the calculated current is above the OCP threshold, then
796 * use the ocp threshold instead.
797 *
798 * Any higher current will be tripping the battery OCP.
799 */
800 ibat_flash_ua = led->pdata->ibatt_ocp_threshold_ua - ibat_now;
801 vph_flash_uv = ocv_uv - div64_s64((int64_t)rbatt_uohm
802 * led->pdata->ibatt_ocp_threshold_ua, UCONV);
803 }
804 /* Calculate the input voltage of the flash module. */
805 vin_flash_uv = max((led->pdata->vled_max_uv +
806 (voltage_hdrm_mv * MCONV)), VIN_FLASH_MIN_UV);
807 /* Calculate the available power for the flash module. */
808 avail_flash_power_fw = BOB_EFFICIENCY * vph_flash_uv * ibat_flash_ua;
809 /*
810 * Calculate the available amount of current the flash module can draw
811 * before collapsing the battery. (available power/ flash input voltage)
812 */
813 avail_flash_ua = div64_s64(avail_flash_power_fw, vin_flash_uv * MCONV);
814 pr_debug("avail_iflash=%lld, ocv=%d, ibat=%d, rbatt=%d, trigger_lmh=%d\n",
815 avail_flash_ua, ocv_uv, ibat_now, rbatt_uohm, led->trigger_lmh);
816 return min(FLASH_LED_MAX_TOTAL_CURRENT_MA,
817 (int)(div64_s64(avail_flash_ua, MCONV)));
818}
819
820static int qpnp_flash_led_calc_thermal_current_lim(struct qpnp_flash_led *led)
821{
822 int thermal_current_lim = 0;
823 int rc;
824 u8 thermal_thrsh1, thermal_thrsh2, thermal_thrsh3, otst_status;
825
826 /* Store THERMAL_THRSHx register values */
827 rc = qpnp_flash_led_masked_read(led,
828 FLASH_LED_REG_THERMAL_THRSH1(led->base),
829 FLASH_LED_THERMAL_THRSH_MASK,
830 &thermal_thrsh1);
831 if (rc < 0)
832 return rc;
833
834 rc = qpnp_flash_led_masked_read(led,
835 FLASH_LED_REG_THERMAL_THRSH2(led->base),
836 FLASH_LED_THERMAL_THRSH_MASK,
837 &thermal_thrsh2);
838 if (rc < 0)
839 return rc;
840
841 rc = qpnp_flash_led_masked_read(led,
842 FLASH_LED_REG_THERMAL_THRSH3(led->base),
843 FLASH_LED_THERMAL_THRSH_MASK,
844 &thermal_thrsh3);
845 if (rc < 0)
846 return rc;
847
848 /* Lower THERMAL_THRSHx thresholds to minimum */
849 rc = qpnp_flash_led_masked_write(led,
850 FLASH_LED_REG_THERMAL_THRSH1(led->base),
851 FLASH_LED_THERMAL_THRSH_MASK,
852 FLASH_LED_THERMAL_THRSH_MIN);
853 if (rc < 0)
854 return rc;
855
856 rc = qpnp_flash_led_masked_write(led,
857 FLASH_LED_REG_THERMAL_THRSH2(led->base),
858 FLASH_LED_THERMAL_THRSH_MASK,
859 FLASH_LED_THERMAL_THRSH_MIN);
860 if (rc < 0)
861 return rc;
862
863 rc = qpnp_flash_led_masked_write(led,
864 FLASH_LED_REG_THERMAL_THRSH3(led->base),
865 FLASH_LED_THERMAL_THRSH_MASK,
866 FLASH_LED_THERMAL_THRSH_MIN);
867 if (rc < 0)
868 return rc;
869
870 /* Check THERMAL_OTST status */
871 rc = qpnp_flash_led_read(led,
872 FLASH_LED_REG_LED_STATUS2(led->base),
873 &otst_status);
874 if (rc < 0)
875 return rc;
876
877 /* Look up current limit based on THERMAL_OTST status */
878 if (otst_status)
879 thermal_current_lim =
880 led->pdata->thermal_derate_current[otst_status >> 1];
881
882 /* Restore THERMAL_THRESHx registers to original values */
883 rc = qpnp_flash_led_masked_write(led,
884 FLASH_LED_REG_THERMAL_THRSH1(led->base),
885 FLASH_LED_THERMAL_THRSH_MASK,
886 thermal_thrsh1);
887 if (rc < 0)
888 return rc;
889
890 rc = qpnp_flash_led_masked_write(led,
891 FLASH_LED_REG_THERMAL_THRSH2(led->base),
892 FLASH_LED_THERMAL_THRSH_MASK,
893 thermal_thrsh2);
894 if (rc < 0)
895 return rc;
896
897 rc = qpnp_flash_led_masked_write(led,
898 FLASH_LED_REG_THERMAL_THRSH3(led->base),
899 FLASH_LED_THERMAL_THRSH_MASK,
900 thermal_thrsh3);
901 if (rc < 0)
902 return rc;
903
904 return thermal_current_lim;
905}
906
907static int qpnp_flash_led_get_max_avail_current(struct qpnp_flash_led *led)
908{
909 int max_avail_current, thermal_current_lim = 0;
910
911 led->trigger_lmh = false;
912 max_avail_current = qpnp_flash_led_calc_max_current(led);
913 if (led->pdata->thermal_derate_en)
914 thermal_current_lim =
915 qpnp_flash_led_calc_thermal_current_lim(led);
916
917 if (thermal_current_lim)
918 max_avail_current = min(max_avail_current, thermal_current_lim);
919
920 return max_avail_current;
921}
922
Ankit Sharmaa7153c32017-03-22 19:04:52 +0530923static void qpnp_flash_led_aggregate_max_current(struct flash_node_data *fnode)
924{
925 struct qpnp_flash_led *led = dev_get_drvdata(&fnode->pdev->dev);
926
927 if (fnode->current_ma)
928 led->total_current_ma += fnode->current_ma
929 - fnode->prev_current_ma;
930 else
931 led->total_current_ma -= fnode->prev_current_ma;
932
933 fnode->prev_current_ma = fnode->current_ma;
934}
935
David Collins8885f792017-01-26 14:36:34 -0800936static void qpnp_flash_led_node_set(struct flash_node_data *fnode, int value)
937{
938 int prgm_current_ma = value;
Ankit Sharma8798ab12017-04-06 15:44:09 +0530939 int min_ma = fnode->ires_ua / 1000;
Ankit Sharmaa7153c32017-03-22 19:04:52 +0530940 struct qpnp_flash_led *led = dev_get_drvdata(&fnode->pdev->dev);
David Collins8885f792017-01-26 14:36:34 -0800941
942 if (value <= 0)
943 prgm_current_ma = 0;
Ankit Sharma8798ab12017-04-06 15:44:09 +0530944 else if (value < min_ma)
945 prgm_current_ma = min_ma;
David Collins8885f792017-01-26 14:36:34 -0800946
947 prgm_current_ma = min(prgm_current_ma, fnode->max_current);
948 fnode->current_ma = prgm_current_ma;
949 fnode->cdev.brightness = prgm_current_ma;
950 fnode->current_reg_val = CURRENT_MA_TO_REG_VAL(prgm_current_ma,
951 fnode->ires_ua);
952 fnode->led_on = prgm_current_ma != 0;
Ankit Sharmaa7153c32017-03-22 19:04:52 +0530953
954 if (led->pdata->chgr_mitigation_sel == FLASH_SW_CHARGER_MITIGATION) {
955 qpnp_flash_led_aggregate_max_current(fnode);
956 led->trigger_chgr = false;
957 if (led->total_current_ma >= 1000)
958 led->trigger_chgr = true;
959 }
David Collins8885f792017-01-26 14:36:34 -0800960}
961
962static int qpnp_flash_led_switch_disable(struct flash_switch_data *snode)
963{
964 struct qpnp_flash_led *led = dev_get_drvdata(&snode->pdev->dev);
965 int i, rc, addr_offset;
966
967 rc = qpnp_flash_led_masked_write(led,
968 FLASH_LED_EN_LED_CTRL(led->base),
969 snode->led_mask, FLASH_LED_DISABLE);
970 if (rc < 0)
971 return rc;
972
973 if (led->trigger_lmh) {
974 rc = qpnp_flash_led_masked_write(led,
975 FLASH_LED_REG_MITIGATION_SW(led->base),
976 FLASH_LED_LMH_MITIGATION_EN_MASK,
977 FLASH_LED_LMH_MITIGATION_DISABLE);
978 if (rc < 0) {
979 pr_err("disable lmh mitigation failed, rc=%d\n", rc);
980 return rc;
981 }
982 }
983
984 if (!led->trigger_chgr) {
985 rc = qpnp_flash_led_masked_write(led,
986 FLASH_LED_REG_MITIGATION_SW(led->base),
987 FLASH_LED_CHGR_MITIGATION_EN_MASK,
988 FLASH_LED_CHGR_MITIGATION_DISABLE);
989 if (rc < 0) {
990 pr_err("disable chgr mitigation failed, rc=%d\n", rc);
991 return rc;
992 }
993 }
994
995 led->enable--;
996 if (led->enable == 0) {
997 rc = qpnp_flash_led_masked_write(led,
998 FLASH_LED_REG_MOD_CTRL(led->base),
999 FLASH_LED_MOD_CTRL_MASK, FLASH_LED_DISABLE);
1000 if (rc < 0)
1001 return rc;
1002 }
1003
1004 for (i = 0; i < led->num_fnodes; i++) {
1005 if (!led->fnode[i].led_on ||
1006 !(snode->led_mask & BIT(led->fnode[i].id)))
1007 continue;
1008
1009 addr_offset = led->fnode[i].id;
1010 rc = qpnp_flash_led_masked_write(led,
1011 FLASH_LED_REG_TGR_CURRENT(led->base + addr_offset),
1012 FLASH_LED_CURRENT_MASK, 0);
1013 if (rc < 0)
1014 return rc;
1015
1016 led->fnode[i].led_on = false;
1017
Subbaraman Narayanamurthy3f684b22017-03-21 20:49:54 -07001018 if (led->fnode[i].strobe_sel == HW_STROBE) {
David Collins8885f792017-01-26 14:36:34 -08001019 rc = qpnp_flash_led_hw_strobe_enable(&led->fnode[i],
1020 led->pdata->hw_strobe_option, false);
1021 if (rc < 0) {
1022 pr_err("Unable to disable hw strobe, rc=%d\n",
1023 rc);
1024 return rc;
1025 }
1026 }
1027 }
1028
Subbaraman Narayanamurthy58377f02017-03-21 20:38:43 -07001029 if (snode->led_en_pinctrl) {
1030 pr_debug("Selecting suspend state for %s\n", snode->cdev.name);
1031 rc = pinctrl_select_state(snode->led_en_pinctrl,
1032 snode->gpio_state_suspend);
1033 if (rc < 0) {
1034 pr_err("failed to select pinctrl suspend state rc=%d\n",
1035 rc);
1036 return rc;
1037 }
1038 }
1039
David Collins8885f792017-01-26 14:36:34 -08001040 snode->enabled = false;
1041 return 0;
1042}
1043
1044static int qpnp_flash_led_switch_set(struct flash_switch_data *snode, bool on)
1045{
1046 struct qpnp_flash_led *led = dev_get_drvdata(&snode->pdev->dev);
1047 int rc, i, addr_offset;
1048 u8 val, mask;
1049
1050 if (snode->enabled == on) {
1051 pr_debug("Switch node is already %s!\n",
1052 on ? "enabled" : "disabled");
1053 return 0;
1054 }
1055
1056 if (!on) {
1057 rc = qpnp_flash_led_switch_disable(snode);
1058 return rc;
1059 }
1060
1061 /* Iterate over all leds for this switch node */
1062 val = 0;
1063 for (i = 0; i < led->num_fnodes; i++)
1064 if (snode->led_mask & BIT(led->fnode[i].id))
1065 val |= led->fnode[i].ires << (led->fnode[i].id * 2);
1066
1067 rc = qpnp_flash_led_masked_write(led, FLASH_LED_REG_IRES(led->base),
1068 FLASH_LED_CURRENT_MASK, val);
1069 if (rc < 0)
1070 return rc;
1071
David Collins8885f792017-01-26 14:36:34 -08001072 val = 0;
1073 for (i = 0; i < led->num_fnodes; i++) {
1074 if (!led->fnode[i].led_on ||
1075 !(snode->led_mask & BIT(led->fnode[i].id)))
1076 continue;
1077
1078 addr_offset = led->fnode[i].id;
Subbaraman Narayanamurthy3f684b22017-03-21 20:49:54 -07001079 if (led->fnode[i].strobe_sel == SW_STROBE)
David Collins8885f792017-01-26 14:36:34 -08001080 mask = FLASH_LED_HW_SW_STROBE_SEL_BIT;
Subbaraman Narayanamurthy3f684b22017-03-21 20:49:54 -07001081 else
1082 mask = FLASH_HW_STROBE_MASK;
David Collins8885f792017-01-26 14:36:34 -08001083 rc = qpnp_flash_led_masked_write(led,
1084 FLASH_LED_REG_STROBE_CTRL(led->base + addr_offset),
Subbaraman Narayanamurthy3f684b22017-03-21 20:49:54 -07001085 mask, led->fnode[i].strobe_ctrl);
David Collins8885f792017-01-26 14:36:34 -08001086 if (rc < 0)
1087 return rc;
1088
1089 rc = qpnp_flash_led_masked_write(led,
1090 FLASH_LED_REG_TGR_CURRENT(led->base + addr_offset),
1091 FLASH_LED_CURRENT_MASK, led->fnode[i].current_reg_val);
1092 if (rc < 0)
1093 return rc;
1094
1095 rc = qpnp_flash_led_write(led,
1096 FLASH_LED_REG_SAFETY_TMR(led->base + addr_offset),
1097 led->fnode[i].duration);
1098 if (rc < 0)
1099 return rc;
1100
1101 val |= FLASH_LED_ENABLE << led->fnode[i].id;
1102
Subbaraman Narayanamurthy3f684b22017-03-21 20:49:54 -07001103 if (led->fnode[i].strobe_sel == HW_STROBE) {
David Collins8885f792017-01-26 14:36:34 -08001104 rc = qpnp_flash_led_hw_strobe_enable(&led->fnode[i],
1105 led->pdata->hw_strobe_option, true);
1106 if (rc < 0) {
1107 pr_err("Unable to enable hw strobe rc=%d\n",
1108 rc);
1109 return rc;
1110 }
1111 }
1112 }
1113
Subbaraman Narayanamurthy58377f02017-03-21 20:38:43 -07001114 if (snode->led_en_pinctrl) {
1115 pr_debug("Selecting active state for %s\n", snode->cdev.name);
1116 rc = pinctrl_select_state(snode->led_en_pinctrl,
1117 snode->gpio_state_active);
1118 if (rc < 0) {
1119 pr_err("failed to select pinctrl active state rc=%d\n",
1120 rc);
1121 return rc;
1122 }
1123 }
1124
David Collins8885f792017-01-26 14:36:34 -08001125 if (led->enable == 0) {
1126 rc = qpnp_flash_led_masked_write(led,
1127 FLASH_LED_REG_MOD_CTRL(led->base),
1128 FLASH_LED_MOD_CTRL_MASK, FLASH_LED_MOD_ENABLE);
1129 if (rc < 0)
1130 return rc;
1131 }
1132 led->enable++;
1133
1134 if (led->trigger_lmh) {
1135 rc = qpnp_flash_led_masked_write(led,
1136 FLASH_LED_REG_MITIGATION_SW(led->base),
1137 FLASH_LED_LMH_MITIGATION_EN_MASK,
1138 FLASH_LED_LMH_MITIGATION_ENABLE);
1139 if (rc < 0) {
1140 pr_err("trigger lmh mitigation failed, rc=%d\n", rc);
1141 return rc;
1142 }
Subbaraman Narayanamurthyd02fbc92017-02-02 16:39:41 -08001143 /* Wait for LMH mitigation to take effect */
1144 udelay(500);
David Collins8885f792017-01-26 14:36:34 -08001145 }
1146
1147 if (led->trigger_chgr) {
1148 rc = qpnp_flash_led_masked_write(led,
1149 FLASH_LED_REG_MITIGATION_SW(led->base),
1150 FLASH_LED_CHGR_MITIGATION_EN_MASK,
1151 FLASH_LED_CHGR_MITIGATION_ENABLE);
1152 if (rc < 0) {
1153 pr_err("trigger chgr mitigation failed, rc=%d\n", rc);
1154 return rc;
1155 }
1156 }
1157
1158 rc = qpnp_flash_led_masked_write(led,
1159 FLASH_LED_EN_LED_CTRL(led->base),
1160 snode->led_mask, val);
1161 if (rc < 0)
1162 return rc;
1163
1164 snode->enabled = true;
1165 return 0;
1166}
1167
1168int qpnp_flash_led_prepare(struct led_trigger *trig, int options,
1169 int *max_current)
1170{
1171 struct led_classdev *led_cdev;
1172 struct flash_switch_data *snode;
1173 struct qpnp_flash_led *led;
1174 int rc;
1175
1176 if (!trig) {
1177 pr_err("Invalid led_trigger provided\n");
1178 return -EINVAL;
1179 }
1180
1181 led_cdev = trigger_to_lcdev(trig);
1182 if (!led_cdev) {
1183 pr_err("Invalid led_cdev in trigger %s\n", trig->name);
1184 return -EINVAL;
1185 }
1186
1187 snode = container_of(led_cdev, struct flash_switch_data, cdev);
1188 led = dev_get_drvdata(&snode->pdev->dev);
1189
1190 if (!(options & FLASH_LED_PREPARE_OPTIONS_MASK)) {
1191 pr_err("Invalid options %d\n", options);
1192 return -EINVAL;
1193 }
1194
1195 if (options & ENABLE_REGULATOR) {
1196 rc = qpnp_flash_led_regulator_enable(led, snode, true);
1197 if (rc < 0) {
1198 pr_err("enable regulator failed, rc=%d\n", rc);
1199 return rc;
1200 }
1201 }
1202
1203 if (options & DISABLE_REGULATOR) {
1204 rc = qpnp_flash_led_regulator_enable(led, snode, false);
1205 if (rc < 0) {
1206 pr_err("disable regulator failed, rc=%d\n", rc);
1207 return rc;
1208 }
1209 }
1210
1211 if (options & QUERY_MAX_CURRENT) {
1212 rc = qpnp_flash_led_get_max_avail_current(led);
1213 if (rc < 0) {
1214 pr_err("query max current failed, rc=%d\n", rc);
1215 return rc;
1216 }
1217 *max_current = rc;
1218 }
1219
David Collins8885f792017-01-26 14:36:34 -08001220 return 0;
1221}
1222
1223static void qpnp_flash_led_brightness_set(struct led_classdev *led_cdev,
1224 enum led_brightness value)
1225{
1226 struct flash_node_data *fnode = NULL;
1227 struct flash_switch_data *snode = NULL;
1228 struct qpnp_flash_led *led = NULL;
1229 int rc;
1230
1231 /*
1232 * strncmp() must be used here since a prefix comparison is required
1233 * in order to support names like led:switch_0 and led:flash_1.
1234 */
1235 if (!strncmp(led_cdev->name, "led:switch", strlen("led:switch"))) {
1236 snode = container_of(led_cdev, struct flash_switch_data, cdev);
1237 led = dev_get_drvdata(&snode->pdev->dev);
1238 } else if (!strncmp(led_cdev->name, "led:flash", strlen("led:flash")) ||
1239 !strncmp(led_cdev->name, "led:torch",
1240 strlen("led:torch"))) {
1241 fnode = container_of(led_cdev, struct flash_node_data, cdev);
1242 led = dev_get_drvdata(&fnode->pdev->dev);
1243 }
1244
1245 if (!led) {
1246 pr_err("Failed to get flash driver data\n");
1247 return;
1248 }
1249
1250 spin_lock(&led->lock);
1251 if (snode) {
1252 rc = qpnp_flash_led_switch_set(snode, value > 0);
1253 if (rc < 0)
1254 pr_err("Failed to set flash LED switch rc=%d\n", rc);
1255 } else if (fnode) {
1256 qpnp_flash_led_node_set(fnode, value);
1257 }
1258
1259 spin_unlock(&led->lock);
1260}
1261
1262/* sysfs show function for flash_max_current */
1263static ssize_t qpnp_flash_led_max_current_show(struct device *dev,
1264 struct device_attribute *attr, char *buf)
1265{
1266 int rc;
1267 struct flash_switch_data *snode;
1268 struct qpnp_flash_led *led;
1269 struct led_classdev *led_cdev = dev_get_drvdata(dev);
1270
1271 snode = container_of(led_cdev, struct flash_switch_data, cdev);
1272 led = dev_get_drvdata(&snode->pdev->dev);
1273
1274 rc = qpnp_flash_led_get_max_avail_current(led);
1275 if (rc < 0)
1276 pr_err("query max current failed, rc=%d\n", rc);
1277
1278 return snprintf(buf, PAGE_SIZE, "%d\n", rc);
1279}
1280
1281/* sysfs attributes exported by flash_led */
1282static struct device_attribute qpnp_flash_led_attrs[] = {
1283 __ATTR(max_current, 0664, qpnp_flash_led_max_current_show, NULL),
1284};
1285
1286static int flash_led_psy_notifier_call(struct notifier_block *nb,
1287 unsigned long ev, void *v)
1288{
1289 struct power_supply *psy = v;
1290 struct qpnp_flash_led *led =
1291 container_of(nb, struct qpnp_flash_led, nb);
1292
1293 if (ev != PSY_EVENT_PROP_CHANGED)
1294 return NOTIFY_OK;
1295
1296 if (!strcmp(psy->desc->name, "bms")) {
1297 led->bms_psy = power_supply_get_by_name("bms");
1298 if (!led->bms_psy)
1299 pr_err("Failed to get bms power_supply\n");
1300 else
1301 power_supply_unreg_notifier(&led->nb);
1302 }
1303
1304 return NOTIFY_OK;
1305}
1306
1307static int flash_led_psy_register_notifier(struct qpnp_flash_led *led)
1308{
1309 int rc;
1310
1311 led->nb.notifier_call = flash_led_psy_notifier_call;
1312 rc = power_supply_reg_notifier(&led->nb);
1313 if (rc < 0) {
1314 pr_err("Couldn't register psy notifier, rc = %d\n", rc);
1315 return rc;
1316 }
1317
1318 return 0;
1319}
1320
1321/* irq handler */
1322static irqreturn_t qpnp_flash_led_irq_handler(int irq, void *_led)
1323{
1324 struct qpnp_flash_led *led = _led;
1325 enum flash_led_irq_type irq_type = INVALID_IRQ;
1326 int rc;
1327 u8 irq_status, led_status1, led_status2;
1328
1329 pr_debug("irq received, irq=%d\n", irq);
1330
1331 rc = qpnp_flash_led_read(led,
1332 FLASH_LED_REG_INT_RT_STS(led->base), &irq_status);
1333 if (rc < 0) {
1334 pr_err("Failed to read interrupt status reg, rc=%d\n", rc);
1335 goto exit;
1336 }
1337
1338 if (irq == led->pdata->all_ramp_up_done_irq)
1339 irq_type = ALL_RAMP_UP_DONE_IRQ;
1340 else if (irq == led->pdata->all_ramp_down_done_irq)
1341 irq_type = ALL_RAMP_DOWN_DONE_IRQ;
1342 else if (irq == led->pdata->led_fault_irq)
1343 irq_type = LED_FAULT_IRQ;
1344
1345 if (irq_type == ALL_RAMP_UP_DONE_IRQ)
1346 atomic_notifier_call_chain(&irq_notifier_list,
1347 irq_type, NULL);
1348
1349 if (irq_type == LED_FAULT_IRQ) {
1350 rc = qpnp_flash_led_read(led,
1351 FLASH_LED_REG_LED_STATUS1(led->base), &led_status1);
1352 if (rc < 0) {
1353 pr_err("Failed to read led_status1 reg, rc=%d\n", rc);
1354 goto exit;
1355 }
1356
1357 rc = qpnp_flash_led_read(led,
1358 FLASH_LED_REG_LED_STATUS2(led->base), &led_status2);
1359 if (rc < 0) {
1360 pr_err("Failed to read led_status2 reg, rc=%d\n", rc);
1361 goto exit;
1362 }
1363
1364 if (led_status1)
1365 pr_emerg("led short/open fault detected! led_status1=%x\n",
1366 led_status1);
1367
1368 if (led_status2 & FLASH_LED_VPH_DROOP_FAULT_MASK)
1369 pr_emerg("led vph_droop fault detected!\n");
1370 }
1371
1372 pr_debug("irq handled, irq_type=%x, irq_status=%x\n", irq_type,
1373 irq_status);
1374
1375exit:
1376 return IRQ_HANDLED;
1377}
1378
1379int qpnp_flash_led_register_irq_notifier(struct notifier_block *nb)
1380{
1381 return atomic_notifier_chain_register(&irq_notifier_list, nb);
1382}
1383
1384int qpnp_flash_led_unregister_irq_notifier(struct notifier_block *nb)
1385{
1386 return atomic_notifier_chain_unregister(&irq_notifier_list, nb);
1387}
1388
1389static int qpnp_flash_led_parse_each_led_dt(struct qpnp_flash_led *led,
1390 struct flash_node_data *fnode, struct device_node *node)
1391{
1392 const char *temp_string;
Ankit Sharma8798ab12017-04-06 15:44:09 +05301393 int rc, min_ma;
David Collins8885f792017-01-26 14:36:34 -08001394 u32 val;
Subbaraman Narayanamurthy3f684b22017-03-21 20:49:54 -07001395 bool hw_strobe = 0, edge_trigger = 0, active_high = 0;
David Collins8885f792017-01-26 14:36:34 -08001396
1397 fnode->pdev = led->pdev;
1398 fnode->cdev.brightness_set = qpnp_flash_led_brightness_set;
1399 fnode->cdev.brightness_get = qpnp_flash_led_brightness_get;
1400
1401 rc = of_property_read_string(node, "qcom,led-name", &fnode->cdev.name);
1402 if (rc < 0) {
1403 pr_err("Unable to read flash LED names\n");
1404 return rc;
1405 }
1406
1407 rc = of_property_read_string(node, "label", &temp_string);
1408 if (!rc) {
1409 if (!strcmp(temp_string, "flash")) {
1410 fnode->type = FLASH_LED_TYPE_FLASH;
1411 } else if (!strcmp(temp_string, "torch")) {
1412 fnode->type = FLASH_LED_TYPE_TORCH;
1413 } else {
1414 pr_err("Wrong flash LED type\n");
1415 return rc;
1416 }
1417 } else {
1418 pr_err("Unable to read flash LED label\n");
1419 return rc;
1420 }
1421
1422 rc = of_property_read_u32(node, "qcom,id", &val);
1423 if (!rc) {
1424 fnode->id = (u8)val;
1425 } else {
1426 pr_err("Unable to read flash LED ID\n");
1427 return rc;
1428 }
1429
1430 rc = of_property_read_string(node, "qcom,default-led-trigger",
1431 &fnode->cdev.default_trigger);
1432 if (rc < 0) {
1433 pr_err("Unable to read trigger name\n");
1434 return rc;
1435 }
1436
1437 fnode->ires_ua = FLASH_LED_IRES_DEFAULT_UA;
1438 fnode->ires = FLASH_LED_IRES_DEFAULT_VAL;
1439 rc = of_property_read_u32(node, "qcom,ires-ua", &val);
1440 if (!rc) {
1441 fnode->ires_ua = val;
1442 fnode->ires = FLASH_LED_IRES_BASE -
1443 (val - FLASH_LED_IRES_MIN_UA) / FLASH_LED_IRES_DIVISOR;
1444 } else if (rc != -EINVAL) {
1445 pr_err("Unable to read current resolution rc=%d\n", rc);
1446 return rc;
1447 }
1448
Ankit Sharma8798ab12017-04-06 15:44:09 +05301449 min_ma = fnode->ires_ua / 1000;
David Collins8885f792017-01-26 14:36:34 -08001450 rc = of_property_read_u32(node, "qcom,max-current", &val);
1451 if (!rc) {
Ankit Sharma8798ab12017-04-06 15:44:09 +05301452 if (val < min_ma)
1453 val = min_ma;
David Collins8885f792017-01-26 14:36:34 -08001454 fnode->max_current = val;
1455 fnode->cdev.max_brightness = val;
1456 } else {
1457 pr_err("Unable to read max current, rc=%d\n", rc);
1458 return rc;
1459 }
1460
1461 rc = of_property_read_u32(node, "qcom,current-ma", &val);
1462 if (!rc) {
Ankit Sharma8798ab12017-04-06 15:44:09 +05301463 if (val < min_ma || val > fnode->max_current)
David Collins8885f792017-01-26 14:36:34 -08001464 pr_warn("Invalid operational current specified, capping it\n");
Ankit Sharma8798ab12017-04-06 15:44:09 +05301465 if (val < min_ma)
1466 val = min_ma;
David Collins8885f792017-01-26 14:36:34 -08001467 if (val > fnode->max_current)
1468 val = fnode->max_current;
1469 fnode->current_ma = val;
1470 fnode->cdev.brightness = val;
1471 } else if (rc != -EINVAL) {
1472 pr_err("Unable to read operational current, rc=%d\n", rc);
1473 return rc;
1474 }
1475
1476 fnode->duration = FLASH_LED_SAFETY_TMR_DISABLED;
1477 rc = of_property_read_u32(node, "qcom,duration-ms", &val);
1478 if (!rc) {
1479 fnode->duration = (u8)(SAFETY_TMR_TO_REG_VAL(val) |
1480 FLASH_LED_SAFETY_TMR_ENABLE);
1481 } else if (rc == -EINVAL) {
1482 if (fnode->type == FLASH_LED_TYPE_FLASH) {
1483 pr_err("Timer duration is required for flash LED\n");
1484 return rc;
1485 }
1486 } else {
1487 pr_err("Unable to read timer duration\n");
1488 return rc;
1489 }
1490
1491 fnode->hdrm_val = FLASH_LED_HDRM_VOL_DEFAULT_MV;
1492 rc = of_property_read_u32(node, "qcom,hdrm-voltage-mv", &val);
1493 if (!rc) {
1494 val = (val - FLASH_LED_HDRM_VOL_BASE_MV) /
1495 FLASH_LED_HDRM_VOL_STEP_MV;
1496 fnode->hdrm_val = (val << FLASH_LED_HDRM_VOL_SHIFT) &
1497 FLASH_LED_HDRM_VOL_MASK;
1498 } else if (rc != -EINVAL) {
1499 pr_err("Unable to read headroom voltage\n");
1500 return rc;
1501 }
1502
1503 rc = of_property_read_u32(node, "qcom,hdrm-vol-hi-lo-win-mv", &val);
1504 if (!rc) {
1505 fnode->hdrm_val |= (val / FLASH_LED_HDRM_VOL_STEP_MV) &
1506 ~FLASH_LED_HDRM_VOL_MASK;
1507 } else if (rc == -EINVAL) {
1508 fnode->hdrm_val |= FLASH_LED_HDRM_VOL_HI_LO_WIN_DEFAULT_MV;
1509 } else {
1510 pr_err("Unable to read hdrm hi-lo window voltage\n");
1511 return rc;
1512 }
1513
Subbaraman Narayanamurthy3f684b22017-03-21 20:49:54 -07001514 fnode->strobe_sel = SW_STROBE;
1515 rc = of_property_read_u32(node, "qcom,strobe-sel", &val);
1516 if (rc < 0) {
1517 if (rc != -EINVAL) {
1518 pr_err("Unable to read qcom,strobe-sel property\n");
1519 return rc;
1520 }
1521 } else {
1522 if (val < SW_STROBE || val > LPG_STROBE) {
1523 pr_err("Incorrect strobe selection specified %d\n",
1524 val);
1525 return -EINVAL;
1526 }
1527 fnode->strobe_sel = (u8)val;
1528 }
1529
1530 /*
1531 * LPG strobe is allowed only for LED3 and HW strobe option should be
1532 * option 2 or 3.
1533 */
1534 if (fnode->strobe_sel == LPG_STROBE) {
1535 if (led->pdata->hw_strobe_option ==
1536 FLASH_LED_HW_STROBE_OPTION_1) {
1537 pr_err("Incorrect strobe option for LPG strobe\n");
1538 return -EINVAL;
1539 }
1540 if (fnode->id != LED3) {
1541 pr_err("Incorrect LED chosen for LPG strobe\n");
1542 return -EINVAL;
1543 }
1544 }
1545
1546 if (fnode->strobe_sel == HW_STROBE) {
David Collins8885f792017-01-26 14:36:34 -08001547 edge_trigger = of_property_read_bool(node,
1548 "qcom,hw-strobe-edge-trigger");
1549 active_high = !of_property_read_bool(node,
1550 "qcom,hw-strobe-active-low");
Subbaraman Narayanamurthy3f684b22017-03-21 20:49:54 -07001551 hw_strobe = 1;
1552 } else if (fnode->strobe_sel == LPG_STROBE) {
1553 /* LPG strobe requires level trigger and active high */
1554 edge_trigger = 0;
1555 active_high = 1;
1556 hw_strobe = 1;
David Collins8885f792017-01-26 14:36:34 -08001557 }
Subbaraman Narayanamurthy3f684b22017-03-21 20:49:54 -07001558 fnode->strobe_ctrl = (hw_strobe << 2) | (edge_trigger << 1) |
1559 active_high;
David Collins8885f792017-01-26 14:36:34 -08001560
Subbaraman Narayanamurthy58377f02017-03-21 20:38:43 -07001561 rc = led_classdev_register(&led->pdev->dev, &fnode->cdev);
1562 if (rc < 0) {
1563 pr_err("Unable to register led node %d\n", fnode->id);
1564 return rc;
1565 }
1566
1567 fnode->cdev.dev->of_node = node;
1568 fnode->strobe_pinctrl = devm_pinctrl_get(fnode->cdev.dev);
1569 if (IS_ERR_OR_NULL(fnode->strobe_pinctrl)) {
1570 pr_debug("No pinctrl defined for %s, err=%ld\n",
1571 fnode->cdev.name, PTR_ERR(fnode->strobe_pinctrl));
1572 fnode->strobe_pinctrl = NULL;
1573 }
1574
Subbaraman Narayanamurthy3f684b22017-03-21 20:49:54 -07001575 if (fnode->strobe_sel == HW_STROBE) {
David Collins8885f792017-01-26 14:36:34 -08001576 if (of_find_property(node, "qcom,hw-strobe-gpio", NULL)) {
1577 fnode->hw_strobe_gpio = of_get_named_gpio(node,
1578 "qcom,hw-strobe-gpio", 0);
1579 if (fnode->hw_strobe_gpio < 0) {
1580 pr_err("Invalid gpio specified\n");
1581 return fnode->hw_strobe_gpio;
1582 }
1583 gpio_direction_output(fnode->hw_strobe_gpio, 0);
Subbaraman Narayanamurthy58377f02017-03-21 20:38:43 -07001584 } else if (fnode->strobe_pinctrl) {
David Collins8885f792017-01-26 14:36:34 -08001585 fnode->hw_strobe_gpio = -1;
1586 fnode->hw_strobe_state_active =
Subbaraman Narayanamurthy58377f02017-03-21 20:38:43 -07001587 pinctrl_lookup_state(fnode->strobe_pinctrl,
1588 "strobe_enable");
David Collins8885f792017-01-26 14:36:34 -08001589 if (IS_ERR_OR_NULL(fnode->hw_strobe_state_active)) {
1590 pr_err("No active pin for hardware strobe, rc=%ld\n",
1591 PTR_ERR(fnode->hw_strobe_state_active));
1592 fnode->hw_strobe_state_active = NULL;
1593 }
1594
1595 fnode->hw_strobe_state_suspend =
Subbaraman Narayanamurthy58377f02017-03-21 20:38:43 -07001596 pinctrl_lookup_state(fnode->strobe_pinctrl,
1597 "strobe_disable");
David Collins8885f792017-01-26 14:36:34 -08001598 if (IS_ERR_OR_NULL(fnode->hw_strobe_state_suspend)) {
1599 pr_err("No suspend pin for hardware strobe, rc=%ld\n",
1600 PTR_ERR(fnode->hw_strobe_state_suspend)
1601 );
1602 fnode->hw_strobe_state_suspend = NULL;
1603 }
1604 }
1605 }
1606
David Collins8885f792017-01-26 14:36:34 -08001607 return 0;
1608}
1609
1610static int qpnp_flash_led_parse_and_register_switch(struct qpnp_flash_led *led,
1611 struct flash_switch_data *snode,
1612 struct device_node *node)
1613{
1614 int rc = 0, num;
1615 char reg_name[16], reg_sup_name[16];
1616
1617 rc = of_property_read_string(node, "qcom,led-name", &snode->cdev.name);
1618 if (rc < 0) {
1619 pr_err("Failed to read switch node name, rc=%d\n", rc);
1620 return rc;
1621 }
1622
1623 rc = sscanf(snode->cdev.name, "led:switch_%d", &num);
1624 if (!rc) {
1625 pr_err("No number for switch device?\n");
1626 return -EINVAL;
1627 }
1628
1629 rc = of_property_read_string(node, "qcom,default-led-trigger",
1630 &snode->cdev.default_trigger);
1631 if (rc < 0) {
1632 pr_err("Unable to read trigger name, rc=%d\n", rc);
1633 return rc;
1634 }
1635
1636 rc = of_property_read_u32(node, "qcom,led-mask", &snode->led_mask);
1637 if (rc < 0) {
1638 pr_err("Unable to read led mask rc=%d\n", rc);
1639 return rc;
1640 }
1641
1642 if (snode->led_mask < 1 || snode->led_mask > 7) {
1643 pr_err("Invalid value for led-mask\n");
1644 return -EINVAL;
1645 }
1646
1647 scnprintf(reg_name, sizeof(reg_name), "switch%d-supply", num);
1648 if (of_find_property(led->pdev->dev.of_node, reg_name, NULL)) {
1649 scnprintf(reg_sup_name, sizeof(reg_sup_name), "switch%d", num);
1650 snode->vreg = devm_regulator_get(&led->pdev->dev, reg_sup_name);
1651 if (IS_ERR_OR_NULL(snode->vreg)) {
1652 rc = PTR_ERR(snode->vreg);
1653 if (rc != -EPROBE_DEFER)
1654 pr_err("Failed to get regulator, rc=%d\n", rc);
1655 snode->vreg = NULL;
1656 return rc;
1657 }
1658 }
1659
1660 snode->pdev = led->pdev;
1661 snode->cdev.brightness_set = qpnp_flash_led_brightness_set;
1662 snode->cdev.brightness_get = qpnp_flash_led_brightness_get;
1663 snode->cdev.flags |= LED_KEEP_TRIGGER;
1664 rc = led_classdev_register(&led->pdev->dev, &snode->cdev);
1665 if (rc < 0) {
1666 pr_err("Unable to register led switch node\n");
1667 return rc;
1668 }
1669
1670 snode->cdev.dev->of_node = node;
Subbaraman Narayanamurthy58377f02017-03-21 20:38:43 -07001671
1672 snode->led_en_pinctrl = devm_pinctrl_get(snode->cdev.dev);
1673 if (IS_ERR_OR_NULL(snode->led_en_pinctrl)) {
1674 pr_debug("No pinctrl defined for %s, err=%ld\n",
1675 snode->cdev.name, PTR_ERR(snode->led_en_pinctrl));
1676 snode->led_en_pinctrl = NULL;
1677 }
1678
1679 if (snode->led_en_pinctrl) {
1680 snode->gpio_state_active =
1681 pinctrl_lookup_state(snode->led_en_pinctrl,
1682 "led_enable");
1683 if (IS_ERR_OR_NULL(snode->gpio_state_active)) {
1684 pr_err("Cannot lookup LED active state\n");
1685 devm_pinctrl_put(snode->led_en_pinctrl);
1686 snode->led_en_pinctrl = NULL;
1687 return PTR_ERR(snode->gpio_state_active);
1688 }
1689
1690 snode->gpio_state_suspend =
1691 pinctrl_lookup_state(snode->led_en_pinctrl,
1692 "led_disable");
1693 if (IS_ERR_OR_NULL(snode->gpio_state_suspend)) {
1694 pr_err("Cannot lookup LED disable state\n");
1695 devm_pinctrl_put(snode->led_en_pinctrl);
1696 snode->led_en_pinctrl = NULL;
1697 return PTR_ERR(snode->gpio_state_suspend);
1698 }
1699 }
1700
David Collins8885f792017-01-26 14:36:34 -08001701 return 0;
1702}
1703
1704static int get_code_from_table(int *table, int len, int value)
1705{
1706 int i;
1707
1708 for (i = 0; i < len; i++) {
1709 if (value == table[i])
1710 break;
1711 }
1712
1713 if (i == len) {
1714 pr_err("Couldn't find %d from table\n", value);
1715 return -ENODATA;
1716 }
1717
1718 return i;
1719}
1720
1721static int qpnp_flash_led_parse_common_dt(struct qpnp_flash_led *led,
1722 struct device_node *node)
1723{
1724 struct device_node *revid_node;
1725 int rc;
1726 u32 val;
1727 bool short_circuit_det, open_circuit_det, vph_droop_det;
1728
1729 revid_node = of_parse_phandle(node, "qcom,pmic-revid", 0);
1730 if (!revid_node) {
1731 pr_err("Missing qcom,pmic-revid property - driver failed\n");
1732 return -EINVAL;
1733 }
1734
1735 led->pdata->pmic_rev_id = get_revid_data(revid_node);
1736 if (IS_ERR_OR_NULL(led->pdata->pmic_rev_id)) {
1737 pr_err("Unable to get pmic_revid rc=%ld\n",
1738 PTR_ERR(led->pdata->pmic_rev_id));
1739 /*
1740 * the revid peripheral must be registered, any failure
1741 * here only indicates that the rev-id module has not
1742 * probed yet.
1743 */
1744 return -EPROBE_DEFER;
1745 }
1746
1747 pr_debug("PMIC subtype %d Digital major %d\n",
1748 led->pdata->pmic_rev_id->pmic_subtype,
1749 led->pdata->pmic_rev_id->rev4);
1750
1751 led->pdata->hdrm_auto_mode_en = of_property_read_bool(node,
1752 "qcom,hdrm-auto-mode");
1753
1754 led->pdata->isc_delay = FLASH_LED_ISC_DELAY_DEFAULT;
1755 rc = of_property_read_u32(node, "qcom,isc-delay-us", &val);
1756 if (!rc) {
1757 led->pdata->isc_delay =
1758 val >> FLASH_LED_ISC_WARMUP_DELAY_SHIFT;
1759 } else if (rc != -EINVAL) {
1760 pr_err("Unable to read ISC delay, rc=%d\n", rc);
1761 return rc;
1762 }
1763
1764 led->pdata->warmup_delay = FLASH_LED_WARMUP_DELAY_DEFAULT;
1765 rc = of_property_read_u32(node, "qcom,warmup-delay-us", &val);
1766 if (!rc) {
1767 led->pdata->warmup_delay =
1768 val >> FLASH_LED_ISC_WARMUP_DELAY_SHIFT;
1769 } else if (rc != -EINVAL) {
1770 pr_err("Unable to read WARMUP delay, rc=%d\n", rc);
1771 return rc;
1772 }
1773
1774 short_circuit_det =
1775 of_property_read_bool(node, "qcom,short-circuit-det");
1776 open_circuit_det = of_property_read_bool(node, "qcom,open-circuit-det");
1777 vph_droop_det = of_property_read_bool(node, "qcom,vph-droop-det");
1778 led->pdata->current_derate_en_cfg = (vph_droop_det << 2) |
1779 (open_circuit_det << 1) | short_circuit_det;
1780
1781 led->pdata->thermal_derate_en =
1782 of_property_read_bool(node, "qcom,thermal-derate-en");
1783
1784 if (led->pdata->thermal_derate_en) {
1785 led->pdata->thermal_derate_current =
1786 devm_kcalloc(&led->pdev->dev,
1787 FLASH_LED_THERMAL_OTST_LEVELS,
1788 sizeof(int), GFP_KERNEL);
1789 if (!led->pdata->thermal_derate_current)
1790 return -ENOMEM;
1791
1792 rc = of_property_read_u32_array(node,
1793 "qcom,thermal-derate-current",
1794 led->pdata->thermal_derate_current,
1795 FLASH_LED_THERMAL_OTST_LEVELS);
1796 if (rc < 0) {
1797 pr_err("Unable to read thermal current limits, rc=%d\n",
1798 rc);
1799 return rc;
1800 }
1801 }
1802
1803 led->pdata->otst_ramp_bkup_en =
1804 !of_property_read_bool(node, "qcom,otst-ramp-back-up-dis");
1805
1806 led->pdata->thermal_derate_slow = -EINVAL;
1807 rc = of_property_read_u32(node, "qcom,thermal-derate-slow", &val);
1808 if (!rc) {
1809 if (val < 0 || val > THERMAL_DERATE_SLOW_MAX) {
1810 pr_err("Invalid thermal_derate_slow %d\n", val);
1811 return -EINVAL;
1812 }
1813
1814 led->pdata->thermal_derate_slow =
1815 get_code_from_table(thermal_derate_slow_table,
1816 ARRAY_SIZE(thermal_derate_slow_table), val);
1817 } else if (rc != -EINVAL) {
1818 pr_err("Unable to read thermal derate slow, rc=%d\n", rc);
1819 return rc;
1820 }
1821
1822 led->pdata->thermal_derate_fast = -EINVAL;
1823 rc = of_property_read_u32(node, "qcom,thermal-derate-fast", &val);
1824 if (!rc) {
1825 if (val < 0 || val > THERMAL_DERATE_FAST_MAX) {
1826 pr_err("Invalid thermal_derate_fast %d\n", val);
1827 return -EINVAL;
1828 }
1829
1830 led->pdata->thermal_derate_fast =
1831 get_code_from_table(thermal_derate_fast_table,
1832 ARRAY_SIZE(thermal_derate_fast_table), val);
1833 } else if (rc != -EINVAL) {
1834 pr_err("Unable to read thermal derate fast, rc=%d\n", rc);
1835 return rc;
1836 }
1837
1838 led->pdata->thermal_debounce = -EINVAL;
1839 rc = of_property_read_u32(node, "qcom,thermal-debounce", &val);
1840 if (!rc) {
1841 if (val < 0 || val > THERMAL_DEBOUNCE_TIME_MAX) {
1842 pr_err("Invalid thermal_debounce %d\n", val);
1843 return -EINVAL;
1844 }
1845
1846 if (val >= 0 && val < 16)
1847 led->pdata->thermal_debounce = 0;
1848 else
1849 led->pdata->thermal_debounce = ilog2(val) - 3;
1850 } else if (rc != -EINVAL) {
1851 pr_err("Unable to read thermal debounce, rc=%d\n", rc);
1852 return rc;
1853 }
1854
1855 led->pdata->thermal_hysteresis = -EINVAL;
1856 rc = of_property_read_u32(node, "qcom,thermal-hysteresis", &val);
1857 if (!rc) {
1858 if (led->pdata->pmic_rev_id->pmic_subtype == PM660L_SUBTYPE)
1859 val = THERMAL_HYST_TEMP_TO_VAL(val, 20);
1860 else
1861 val = THERMAL_HYST_TEMP_TO_VAL(val, 15);
1862
1863 if (val < 0 || val > THERMAL_DERATE_HYSTERESIS_MAX) {
1864 pr_err("Invalid thermal_derate_hysteresis %d\n", val);
1865 return -EINVAL;
1866 }
1867
1868 led->pdata->thermal_hysteresis = val;
1869 } else if (rc != -EINVAL) {
1870 pr_err("Unable to read thermal hysteresis, rc=%d\n", rc);
1871 return rc;
1872 }
1873
1874 led->pdata->thermal_thrsh1 = -EINVAL;
1875 rc = of_property_read_u32(node, "qcom,thermal-thrsh1", &val);
1876 if (!rc) {
1877 led->pdata->thermal_thrsh1 =
1878 get_code_from_table(otst1_threshold_table,
1879 ARRAY_SIZE(otst1_threshold_table), val);
1880 } else if (rc != -EINVAL) {
1881 pr_err("Unable to read thermal thrsh1, rc=%d\n", rc);
1882 return rc;
1883 }
1884
1885 led->pdata->thermal_thrsh2 = -EINVAL;
1886 rc = of_property_read_u32(node, "qcom,thermal-thrsh2", &val);
1887 if (!rc) {
1888 led->pdata->thermal_thrsh2 =
1889 get_code_from_table(otst2_threshold_table,
1890 ARRAY_SIZE(otst2_threshold_table), val);
1891 } else if (rc != -EINVAL) {
1892 pr_err("Unable to read thermal thrsh2, rc=%d\n", rc);
1893 return rc;
1894 }
1895
1896 led->pdata->thermal_thrsh3 = -EINVAL;
1897 rc = of_property_read_u32(node, "qcom,thermal-thrsh3", &val);
1898 if (!rc) {
1899 led->pdata->thermal_thrsh3 =
1900 get_code_from_table(otst3_threshold_table,
1901 ARRAY_SIZE(otst3_threshold_table), val);
1902 } else if (rc != -EINVAL) {
1903 pr_err("Unable to read thermal thrsh3, rc=%d\n", rc);
1904 return rc;
1905 }
1906
1907 led->pdata->vph_droop_debounce = FLASH_LED_VPH_DROOP_DEBOUNCE_DEFAULT;
1908 rc = of_property_read_u32(node, "qcom,vph-droop-debounce-us", &val);
1909 if (!rc) {
1910 led->pdata->vph_droop_debounce =
1911 VPH_DROOP_DEBOUNCE_US_TO_VAL(val);
1912 } else if (rc != -EINVAL) {
1913 pr_err("Unable to read VPH droop debounce, rc=%d\n", rc);
1914 return rc;
1915 }
1916
1917 if (led->pdata->vph_droop_debounce > FLASH_LED_DEBOUNCE_MAX) {
1918 pr_err("Invalid VPH droop debounce specified\n");
1919 return -EINVAL;
1920 }
1921
1922 led->pdata->vph_droop_threshold = FLASH_LED_VPH_DROOP_THRESH_DEFAULT;
1923 rc = of_property_read_u32(node, "qcom,vph-droop-threshold-mv", &val);
1924 if (!rc) {
1925 led->pdata->vph_droop_threshold =
1926 VPH_DROOP_THRESH_MV_TO_VAL(val);
1927 } else if (rc != -EINVAL) {
1928 pr_err("Unable to read VPH droop threshold, rc=%d\n", rc);
1929 return rc;
1930 }
1931
1932 if (led->pdata->vph_droop_threshold > FLASH_LED_VPH_DROOP_THRESH_MAX) {
1933 pr_err("Invalid VPH droop threshold specified\n");
1934 return -EINVAL;
1935 }
1936
1937 led->pdata->vph_droop_hysteresis =
1938 FLASH_LED_VPH_DROOP_HYST_DEFAULT;
1939 rc = of_property_read_u32(node, "qcom,vph-droop-hysteresis-mv", &val);
1940 if (!rc) {
1941 led->pdata->vph_droop_hysteresis =
1942 VPH_DROOP_HYST_MV_TO_VAL(val);
1943 } else if (rc != -EINVAL) {
1944 pr_err("Unable to read VPH droop hysteresis, rc=%d\n", rc);
1945 return rc;
1946 }
1947
1948 if (led->pdata->vph_droop_hysteresis > FLASH_LED_HYSTERESIS_MAX) {
1949 pr_err("Invalid VPH droop hysteresis specified\n");
1950 return -EINVAL;
1951 }
1952
1953 led->pdata->vph_droop_hysteresis <<= FLASH_LED_VPH_DROOP_HYST_SHIFT;
1954
Subbaraman Narayanamurthy3f684b22017-03-21 20:49:54 -07001955 led->pdata->hw_strobe_option = -EINVAL;
David Collins8885f792017-01-26 14:36:34 -08001956 rc = of_property_read_u32(node, "qcom,hw-strobe-option", &val);
1957 if (!rc) {
Subbaraman Narayanamurthy3f684b22017-03-21 20:49:54 -07001958 led->pdata->hw_strobe_option = val;
David Collins8885f792017-01-26 14:36:34 -08001959 } else if (rc != -EINVAL) {
1960 pr_err("Unable to parse hw strobe option, rc=%d\n", rc);
1961 return rc;
1962 }
1963
1964 rc = of_property_read_u32(node, "qcom,led1n2-iclamp-low-ma", &val);
1965 if (!rc) {
1966 led->pdata->led1n2_iclamp_low_ma = val;
1967 } else if (rc != -EINVAL) {
1968 pr_err("Unable to read led1n2_iclamp_low current, rc=%d\n", rc);
1969 return rc;
1970 }
1971
1972 rc = of_property_read_u32(node, "qcom,led1n2-iclamp-mid-ma", &val);
1973 if (!rc) {
1974 led->pdata->led1n2_iclamp_mid_ma = val;
1975 } else if (rc != -EINVAL) {
1976 pr_err("Unable to read led1n2_iclamp_mid current, rc=%d\n", rc);
1977 return rc;
1978 }
1979
1980 rc = of_property_read_u32(node, "qcom,led3-iclamp-low-ma", &val);
1981 if (!rc) {
1982 led->pdata->led3_iclamp_low_ma = val;
1983 } else if (rc != -EINVAL) {
1984 pr_err("Unable to read led3_iclamp_low current, rc=%d\n", rc);
1985 return rc;
1986 }
1987
1988 rc = of_property_read_u32(node, "qcom,led3-iclamp-mid-ma", &val);
1989 if (!rc) {
1990 led->pdata->led3_iclamp_mid_ma = val;
1991 } else if (rc != -EINVAL) {
1992 pr_err("Unable to read led3_iclamp_mid current, rc=%d\n", rc);
1993 return rc;
1994 }
1995
1996 led->pdata->vled_max_uv = FLASH_LED_VLED_MAX_DEFAULT_UV;
1997 rc = of_property_read_u32(node, "qcom,vled-max-uv", &val);
1998 if (!rc) {
1999 led->pdata->vled_max_uv = val;
2000 } else if (rc != -EINVAL) {
2001 pr_err("Unable to parse vled_max voltage, rc=%d\n", rc);
2002 return rc;
2003 }
2004
2005 led->pdata->ibatt_ocp_threshold_ua =
2006 FLASH_LED_IBATT_OCP_THRESH_DEFAULT_UA;
2007 rc = of_property_read_u32(node, "qcom,ibatt-ocp-threshold-ua", &val);
2008 if (!rc) {
2009 led->pdata->ibatt_ocp_threshold_ua = val;
2010 } else if (rc != -EINVAL) {
2011 pr_err("Unable to parse ibatt_ocp threshold, rc=%d\n", rc);
2012 return rc;
2013 }
2014
2015 led->pdata->rpara_uohm = FLASH_LED_RPARA_DEFAULT_UOHM;
2016 rc = of_property_read_u32(node, "qcom,rparasitic-uohm", &val);
2017 if (!rc) {
2018 led->pdata->rpara_uohm = val;
2019 } else if (rc != -EINVAL) {
2020 pr_err("Unable to parse rparasitic, rc=%d\n", rc);
2021 return rc;
2022 }
2023
2024 led->pdata->lmh_ocv_threshold_uv =
2025 FLASH_LED_LMH_OCV_THRESH_DEFAULT_UV;
2026 rc = of_property_read_u32(node, "qcom,lmh-ocv-threshold-uv", &val);
2027 if (!rc) {
2028 led->pdata->lmh_ocv_threshold_uv = val;
2029 } else if (rc != -EINVAL) {
2030 pr_err("Unable to parse lmh ocv threshold, rc=%d\n", rc);
2031 return rc;
2032 }
2033
2034 led->pdata->lmh_rbatt_threshold_uohm =
2035 FLASH_LED_LMH_RBATT_THRESH_DEFAULT_UOHM;
2036 rc = of_property_read_u32(node, "qcom,lmh-rbatt-threshold-uohm", &val);
2037 if (!rc) {
2038 led->pdata->lmh_rbatt_threshold_uohm = val;
2039 } else if (rc != -EINVAL) {
2040 pr_err("Unable to parse lmh rbatt threshold, rc=%d\n", rc);
2041 return rc;
2042 }
2043
2044 led->pdata->lmh_level = FLASH_LED_LMH_LEVEL_DEFAULT;
2045 rc = of_property_read_u32(node, "qcom,lmh-level", &val);
2046 if (!rc) {
2047 led->pdata->lmh_level = val;
2048 } else if (rc != -EINVAL) {
2049 pr_err("Unable to parse lmh_level, rc=%d\n", rc);
2050 return rc;
2051 }
2052
Ankit Sharmaa7153c32017-03-22 19:04:52 +05302053 led->pdata->lmh_mitigation_sel = FLASH_LED_LMH_MITIGATION_SEL_DEFAULT;
David Collins8885f792017-01-26 14:36:34 -08002054 rc = of_property_read_u32(node, "qcom,lmh-mitigation-sel", &val);
2055 if (!rc) {
2056 led->pdata->lmh_mitigation_sel = val;
2057 } else if (rc != -EINVAL) {
2058 pr_err("Unable to parse lmh_mitigation_sel, rc=%d\n", rc);
2059 return rc;
2060 }
2061
2062 if (led->pdata->lmh_mitigation_sel > FLASH_LED_MITIGATION_SEL_MAX) {
2063 pr_err("Invalid lmh_mitigation_sel specified\n");
2064 return -EINVAL;
2065 }
2066
Ankit Sharmaa7153c32017-03-22 19:04:52 +05302067 led->pdata->chgr_mitigation_sel = FLASH_SW_CHARGER_MITIGATION;
David Collins8885f792017-01-26 14:36:34 -08002068 rc = of_property_read_u32(node, "qcom,chgr-mitigation-sel", &val);
2069 if (!rc) {
2070 led->pdata->chgr_mitigation_sel = val;
2071 } else if (rc != -EINVAL) {
2072 pr_err("Unable to parse chgr_mitigation_sel, rc=%d\n", rc);
2073 return rc;
2074 }
2075
2076 if (led->pdata->chgr_mitigation_sel > FLASH_LED_MITIGATION_SEL_MAX) {
2077 pr_err("Invalid chgr_mitigation_sel specified\n");
2078 return -EINVAL;
2079 }
2080
Ankit Sharmaa7153c32017-03-22 19:04:52 +05302081 led->pdata->iled_thrsh_val = FLASH_LED_CHGR_MITIGATION_THRSH_DEFAULT;
David Collins8885f792017-01-26 14:36:34 -08002082 rc = of_property_read_u32(node, "qcom,iled-thrsh-ma", &val);
2083 if (!rc) {
2084 led->pdata->iled_thrsh_val = MITIGATION_THRSH_MA_TO_VAL(val);
2085 } else if (rc != -EINVAL) {
2086 pr_err("Unable to parse iled_thrsh_val, rc=%d\n", rc);
2087 return rc;
2088 }
2089
Ankit Sharmaa7153c32017-03-22 19:04:52 +05302090 if (led->pdata->iled_thrsh_val > FLASH_LED_CHGR_MITIGATION_THRSH_MAX) {
David Collins8885f792017-01-26 14:36:34 -08002091 pr_err("Invalid iled_thrsh_val specified\n");
2092 return -EINVAL;
2093 }
2094
2095 led->pdata->all_ramp_up_done_irq =
2096 of_irq_get_byname(node, "all-ramp-up-done-irq");
2097 if (led->pdata->all_ramp_up_done_irq < 0)
2098 pr_debug("all-ramp-up-done-irq not used\n");
2099
2100 led->pdata->all_ramp_down_done_irq =
2101 of_irq_get_byname(node, "all-ramp-down-done-irq");
2102 if (led->pdata->all_ramp_down_done_irq < 0)
2103 pr_debug("all-ramp-down-done-irq not used\n");
2104
2105 led->pdata->led_fault_irq =
2106 of_irq_get_byname(node, "led-fault-irq");
2107 if (led->pdata->led_fault_irq < 0)
2108 pr_debug("led-fault-irq not used\n");
2109
2110 return 0;
2111}
2112
2113static int qpnp_flash_led_probe(struct platform_device *pdev)
2114{
2115 struct qpnp_flash_led *led;
2116 struct device_node *node, *temp;
2117 const char *temp_string;
2118 unsigned int base;
2119 int rc, i = 0, j = 0;
2120
2121 node = pdev->dev.of_node;
2122 if (!node) {
2123 pr_err("No flash LED nodes defined\n");
2124 return -ENODEV;
2125 }
2126
2127 rc = of_property_read_u32(node, "reg", &base);
2128 if (rc < 0) {
2129 pr_err("Couldn't find reg in node %s, rc = %d\n",
2130 node->full_name, rc);
2131 return rc;
2132 }
2133
2134 led = devm_kzalloc(&pdev->dev, sizeof(struct qpnp_flash_led),
2135 GFP_KERNEL);
2136 if (!led)
2137 return -ENOMEM;
2138
2139 led->regmap = dev_get_regmap(pdev->dev.parent, NULL);
2140 if (!led->regmap) {
2141 pr_err("Couldn't get parent's regmap\n");
2142 return -EINVAL;
2143 }
2144
2145 led->base = base;
2146 led->pdev = pdev;
2147 led->pdata = devm_kzalloc(&pdev->dev,
2148 sizeof(struct flash_led_platform_data), GFP_KERNEL);
2149 if (!led->pdata)
2150 return -ENOMEM;
2151
2152 rc = qpnp_flash_led_parse_common_dt(led, node);
2153 if (rc < 0) {
2154 pr_err("Failed to parse common flash LED device tree\n");
2155 return rc;
2156 }
2157
2158 for_each_available_child_of_node(node, temp) {
2159 rc = of_property_read_string(temp, "label", &temp_string);
2160 if (rc < 0) {
2161 pr_err("Failed to parse label, rc=%d\n", rc);
2162 return rc;
2163 }
2164
2165 if (!strcmp("switch", temp_string)) {
2166 led->num_snodes++;
2167 } else if (!strcmp("flash", temp_string) ||
2168 !strcmp("torch", temp_string)) {
2169 led->num_fnodes++;
2170 } else {
2171 pr_err("Invalid label for led node\n");
2172 return -EINVAL;
2173 }
2174 }
2175
2176 if (!led->num_fnodes) {
2177 pr_err("No LED nodes defined\n");
2178 return -ECHILD;
2179 }
2180
2181 led->fnode = devm_kcalloc(&pdev->dev, led->num_fnodes,
2182 sizeof(*led->fnode),
2183 GFP_KERNEL);
2184 if (!led->fnode)
2185 return -ENOMEM;
2186
2187 led->snode = devm_kcalloc(&pdev->dev, led->num_snodes,
2188 sizeof(*led->snode),
2189 GFP_KERNEL);
2190 if (!led->snode)
2191 return -ENOMEM;
2192
2193 temp = NULL;
2194 i = 0;
2195 j = 0;
2196 for_each_available_child_of_node(node, temp) {
2197 rc = of_property_read_string(temp, "label", &temp_string);
2198 if (rc < 0) {
2199 pr_err("Failed to parse label, rc=%d\n", rc);
2200 return rc;
2201 }
2202
2203 if (!strcmp("flash", temp_string) ||
2204 !strcmp("torch", temp_string)) {
2205 rc = qpnp_flash_led_parse_each_led_dt(led,
Subbaraman Narayanamurthy01c99612017-04-03 12:26:06 -07002206 &led->fnode[i], temp);
David Collins8885f792017-01-26 14:36:34 -08002207 if (rc < 0) {
2208 pr_err("Unable to parse flash node %d rc=%d\n",
2209 i, rc);
2210 goto error_led_register;
2211 }
Subbaraman Narayanamurthy01c99612017-04-03 12:26:06 -07002212 i++;
David Collins8885f792017-01-26 14:36:34 -08002213 }
2214
2215 if (!strcmp("switch", temp_string)) {
2216 rc = qpnp_flash_led_parse_and_register_switch(led,
Subbaraman Narayanamurthy01c99612017-04-03 12:26:06 -07002217 &led->snode[j], temp);
David Collins8885f792017-01-26 14:36:34 -08002218 if (rc < 0) {
2219 pr_err("Unable to parse and register switch node, rc=%d\n",
2220 rc);
2221 goto error_switch_register;
2222 }
Subbaraman Narayanamurthy01c99612017-04-03 12:26:06 -07002223 j++;
David Collins8885f792017-01-26 14:36:34 -08002224 }
2225 }
2226
2227 /* setup irqs */
2228 if (led->pdata->all_ramp_up_done_irq >= 0) {
2229 rc = devm_request_threaded_irq(&led->pdev->dev,
2230 led->pdata->all_ramp_up_done_irq,
2231 NULL, qpnp_flash_led_irq_handler,
2232 IRQF_ONESHOT,
2233 "qpnp_flash_led_all_ramp_up_done_irq", led);
2234 if (rc < 0) {
2235 pr_err("Unable to request all_ramp_up_done(%d) IRQ(err:%d)\n",
2236 led->pdata->all_ramp_up_done_irq, rc);
2237 goto error_switch_register;
2238 }
2239 }
2240
2241 if (led->pdata->all_ramp_down_done_irq >= 0) {
2242 rc = devm_request_threaded_irq(&led->pdev->dev,
2243 led->pdata->all_ramp_down_done_irq,
2244 NULL, qpnp_flash_led_irq_handler,
2245 IRQF_ONESHOT,
2246 "qpnp_flash_led_all_ramp_down_done_irq", led);
2247 if (rc < 0) {
2248 pr_err("Unable to request all_ramp_down_done(%d) IRQ(err:%d)\n",
2249 led->pdata->all_ramp_down_done_irq, rc);
2250 goto error_switch_register;
2251 }
2252 }
2253
2254 if (led->pdata->led_fault_irq >= 0) {
2255 rc = devm_request_threaded_irq(&led->pdev->dev,
2256 led->pdata->led_fault_irq,
2257 NULL, qpnp_flash_led_irq_handler,
2258 IRQF_ONESHOT,
2259 "qpnp_flash_led_fault_irq", led);
2260 if (rc < 0) {
2261 pr_err("Unable to request led_fault(%d) IRQ(err:%d)\n",
2262 led->pdata->led_fault_irq, rc);
2263 goto error_switch_register;
2264 }
2265 }
2266
2267 led->bms_psy = power_supply_get_by_name("bms");
2268 if (!led->bms_psy) {
2269 rc = flash_led_psy_register_notifier(led);
2270 if (rc < 0) {
2271 pr_err("Couldn't register psy notifier, rc = %d\n", rc);
2272 goto error_switch_register;
2273 }
2274 }
2275
2276 rc = qpnp_flash_led_init_settings(led);
2277 if (rc < 0) {
2278 pr_err("Failed to initialize flash LED, rc=%d\n", rc);
2279 goto unreg_notifier;
2280 }
2281
2282 for (i = 0; i < led->num_snodes; i++) {
2283 for (j = 0; j < ARRAY_SIZE(qpnp_flash_led_attrs); j++) {
2284 rc = sysfs_create_file(&led->snode[i].cdev.dev->kobj,
2285 &qpnp_flash_led_attrs[j].attr);
2286 if (rc < 0) {
2287 pr_err("sysfs creation failed, rc=%d\n", rc);
2288 goto sysfs_fail;
2289 }
2290 }
2291 }
2292
2293 spin_lock_init(&led->lock);
2294
2295 dev_set_drvdata(&pdev->dev, led);
2296
2297 return 0;
2298
2299sysfs_fail:
2300 for (--j; j >= 0; j--)
2301 sysfs_remove_file(&led->snode[i].cdev.dev->kobj,
2302 &qpnp_flash_led_attrs[j].attr);
2303
2304 for (--i; i >= 0; i--) {
2305 for (j = 0; j < ARRAY_SIZE(qpnp_flash_led_attrs); j++)
2306 sysfs_remove_file(&led->snode[i].cdev.dev->kobj,
2307 &qpnp_flash_led_attrs[j].attr);
2308 }
2309
2310 i = led->num_snodes;
2311unreg_notifier:
2312 power_supply_unreg_notifier(&led->nb);
2313error_switch_register:
2314 while (i > 0)
2315 led_classdev_unregister(&led->snode[--i].cdev);
2316 i = led->num_fnodes;
2317error_led_register:
2318 while (i > 0)
2319 led_classdev_unregister(&led->fnode[--i].cdev);
2320
2321 return rc;
2322}
2323
2324static int qpnp_flash_led_remove(struct platform_device *pdev)
2325{
2326 struct qpnp_flash_led *led = dev_get_drvdata(&pdev->dev);
2327 int i, j;
2328
2329 for (i = 0; i < led->num_snodes; i++) {
2330 for (j = 0; j < ARRAY_SIZE(qpnp_flash_led_attrs); j++)
2331 sysfs_remove_file(&led->snode[i].cdev.dev->kobj,
2332 &qpnp_flash_led_attrs[j].attr);
2333
2334 if (led->snode[i].regulator_on)
2335 qpnp_flash_led_regulator_enable(led,
2336 &led->snode[i], false);
2337 }
2338
2339 while (i > 0)
2340 led_classdev_unregister(&led->snode[--i].cdev);
2341
2342 i = led->num_fnodes;
2343 while (i > 0)
2344 led_classdev_unregister(&led->fnode[--i].cdev);
2345
2346 power_supply_unreg_notifier(&led->nb);
2347 return 0;
2348}
2349
2350const struct of_device_id qpnp_flash_led_match_table[] = {
2351 { .compatible = "qcom,qpnp-flash-led-v2",},
2352 { },
2353};
2354
2355static struct platform_driver qpnp_flash_led_driver = {
2356 .driver = {
2357 .name = "qcom,qpnp-flash-led-v2",
2358 .of_match_table = qpnp_flash_led_match_table,
2359 },
2360 .probe = qpnp_flash_led_probe,
2361 .remove = qpnp_flash_led_remove,
2362};
2363
2364static int __init qpnp_flash_led_init(void)
2365{
2366 return platform_driver_register(&qpnp_flash_led_driver);
2367}
2368late_initcall(qpnp_flash_led_init);
2369
2370static void __exit qpnp_flash_led_exit(void)
2371{
2372 platform_driver_unregister(&qpnp_flash_led_driver);
2373}
2374module_exit(qpnp_flash_led_exit);
2375
2376MODULE_DESCRIPTION("QPNP Flash LED driver v2");
2377MODULE_LICENSE("GPL v2");
2378MODULE_ALIAS("leds:leds-qpnp-flash-v2");