blob: 5bd52e483a79adb6f629a3962500a9a27b9bfb07 [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
734static int qpnp_flash_led_calc_max_current(struct qpnp_flash_led *led)
735{
Kyle Yan74fdd732017-03-22 13:37:08 -0700736 int ocv_uv, ibat_now, voltage_hdrm_mv, rc;
737 int rbatt_uohm = 0;
David Collins8885f792017-01-26 14:36:34 -0800738 int64_t ibat_flash_ua, avail_flash_ua, avail_flash_power_fw;
739 int64_t ibat_safe_ua, vin_flash_uv, vph_flash_uv, vph_flash_vdip;
740
741 /* RESISTANCE = esr_uohm + rslow_uohm */
742 rc = get_property_from_fg(led, POWER_SUPPLY_PROP_RESISTANCE,
743 &rbatt_uohm);
744 if (rc < 0) {
745 pr_err("bms psy does not support resistance, rc=%d\n", rc);
746 return rc;
747 }
748
749 /* If no battery is connected, return max possible flash current */
750 if (!rbatt_uohm)
751 return FLASH_LED_MAX_TOTAL_CURRENT_MA;
752
753 rc = get_property_from_fg(led, POWER_SUPPLY_PROP_VOLTAGE_OCV, &ocv_uv);
754 if (rc < 0) {
755 pr_err("bms psy does not support OCV, rc=%d\n", rc);
756 return rc;
757 }
758
759 rc = get_property_from_fg(led, POWER_SUPPLY_PROP_CURRENT_NOW,
760 &ibat_now);
761 if (rc < 0) {
762 pr_err("bms psy does not support current, rc=%d\n", rc);
763 return rc;
764 }
765
766 rbatt_uohm += led->pdata->rpara_uohm;
767 voltage_hdrm_mv = qpnp_flash_led_get_voltage_headroom(led);
768 vph_flash_vdip =
769 VPH_DROOP_THRESH_VAL_TO_UV(led->pdata->vph_droop_threshold)
770 + FLASH_VDIP_MARGIN;
771
772 /* Check if LMH_MITIGATION needs to be triggered */
773 if (!led->trigger_lmh && (ocv_uv < led->pdata->lmh_ocv_threshold_uv ||
774 rbatt_uohm > led->pdata->lmh_rbatt_threshold_uohm)) {
775 led->trigger_lmh = true;
776 rc = qpnp_flash_led_masked_write(led,
777 FLASH_LED_REG_MITIGATION_SW(led->base),
778 FLASH_LED_LMH_MITIGATION_EN_MASK,
779 FLASH_LED_LMH_MITIGATION_ENABLE);
780 if (rc < 0) {
781 pr_err("trigger lmh mitigation failed, rc=%d\n", rc);
782 return rc;
783 }
784
785 /* Wait for LMH mitigation to take effect */
786 udelay(100);
787
788 return qpnp_flash_led_calc_max_current(led);
789 }
790
791 /*
792 * Calculate the maximum current that can pulled out of the battery
793 * before the battery voltage dips below a safe threshold.
794 */
795 ibat_safe_ua = div_s64((ocv_uv - vph_flash_vdip) * UCONV,
796 rbatt_uohm);
797
798 if (ibat_safe_ua <= led->pdata->ibatt_ocp_threshold_ua) {
799 /*
800 * If the calculated current is below the OCP threshold, then
801 * use it as the possible flash current.
802 */
803 ibat_flash_ua = ibat_safe_ua - ibat_now;
804 vph_flash_uv = vph_flash_vdip;
805 } else {
806 /*
807 * If the calculated current is above the OCP threshold, then
808 * use the ocp threshold instead.
809 *
810 * Any higher current will be tripping the battery OCP.
811 */
812 ibat_flash_ua = led->pdata->ibatt_ocp_threshold_ua - ibat_now;
813 vph_flash_uv = ocv_uv - div64_s64((int64_t)rbatt_uohm
814 * led->pdata->ibatt_ocp_threshold_ua, UCONV);
815 }
816 /* Calculate the input voltage of the flash module. */
817 vin_flash_uv = max((led->pdata->vled_max_uv +
818 (voltage_hdrm_mv * MCONV)), VIN_FLASH_MIN_UV);
819 /* Calculate the available power for the flash module. */
820 avail_flash_power_fw = BOB_EFFICIENCY * vph_flash_uv * ibat_flash_ua;
821 /*
822 * Calculate the available amount of current the flash module can draw
823 * before collapsing the battery. (available power/ flash input voltage)
824 */
825 avail_flash_ua = div64_s64(avail_flash_power_fw, vin_flash_uv * MCONV);
826 pr_debug("avail_iflash=%lld, ocv=%d, ibat=%d, rbatt=%d, trigger_lmh=%d\n",
827 avail_flash_ua, ocv_uv, ibat_now, rbatt_uohm, led->trigger_lmh);
828 return min(FLASH_LED_MAX_TOTAL_CURRENT_MA,
829 (int)(div64_s64(avail_flash_ua, MCONV)));
830}
831
832static int qpnp_flash_led_calc_thermal_current_lim(struct qpnp_flash_led *led)
833{
834 int thermal_current_lim = 0;
835 int rc;
836 u8 thermal_thrsh1, thermal_thrsh2, thermal_thrsh3, otst_status;
837
838 /* Store THERMAL_THRSHx register values */
839 rc = qpnp_flash_led_masked_read(led,
840 FLASH_LED_REG_THERMAL_THRSH1(led->base),
841 FLASH_LED_THERMAL_THRSH_MASK,
842 &thermal_thrsh1);
843 if (rc < 0)
844 return rc;
845
846 rc = qpnp_flash_led_masked_read(led,
847 FLASH_LED_REG_THERMAL_THRSH2(led->base),
848 FLASH_LED_THERMAL_THRSH_MASK,
849 &thermal_thrsh2);
850 if (rc < 0)
851 return rc;
852
853 rc = qpnp_flash_led_masked_read(led,
854 FLASH_LED_REG_THERMAL_THRSH3(led->base),
855 FLASH_LED_THERMAL_THRSH_MASK,
856 &thermal_thrsh3);
857 if (rc < 0)
858 return rc;
859
860 /* Lower THERMAL_THRSHx thresholds to minimum */
861 rc = qpnp_flash_led_masked_write(led,
862 FLASH_LED_REG_THERMAL_THRSH1(led->base),
863 FLASH_LED_THERMAL_THRSH_MASK,
864 FLASH_LED_THERMAL_THRSH_MIN);
865 if (rc < 0)
866 return rc;
867
868 rc = qpnp_flash_led_masked_write(led,
869 FLASH_LED_REG_THERMAL_THRSH2(led->base),
870 FLASH_LED_THERMAL_THRSH_MASK,
871 FLASH_LED_THERMAL_THRSH_MIN);
872 if (rc < 0)
873 return rc;
874
875 rc = qpnp_flash_led_masked_write(led,
876 FLASH_LED_REG_THERMAL_THRSH3(led->base),
877 FLASH_LED_THERMAL_THRSH_MASK,
878 FLASH_LED_THERMAL_THRSH_MIN);
879 if (rc < 0)
880 return rc;
881
882 /* Check THERMAL_OTST status */
883 rc = qpnp_flash_led_read(led,
884 FLASH_LED_REG_LED_STATUS2(led->base),
885 &otst_status);
886 if (rc < 0)
887 return rc;
888
889 /* Look up current limit based on THERMAL_OTST status */
890 if (otst_status)
891 thermal_current_lim =
892 led->pdata->thermal_derate_current[otst_status >> 1];
893
894 /* Restore THERMAL_THRESHx registers to original values */
895 rc = qpnp_flash_led_masked_write(led,
896 FLASH_LED_REG_THERMAL_THRSH1(led->base),
897 FLASH_LED_THERMAL_THRSH_MASK,
898 thermal_thrsh1);
899 if (rc < 0)
900 return rc;
901
902 rc = qpnp_flash_led_masked_write(led,
903 FLASH_LED_REG_THERMAL_THRSH2(led->base),
904 FLASH_LED_THERMAL_THRSH_MASK,
905 thermal_thrsh2);
906 if (rc < 0)
907 return rc;
908
909 rc = qpnp_flash_led_masked_write(led,
910 FLASH_LED_REG_THERMAL_THRSH3(led->base),
911 FLASH_LED_THERMAL_THRSH_MASK,
912 thermal_thrsh3);
913 if (rc < 0)
914 return rc;
915
916 return thermal_current_lim;
917}
918
919static int qpnp_flash_led_get_max_avail_current(struct qpnp_flash_led *led)
920{
921 int max_avail_current, thermal_current_lim = 0;
922
923 led->trigger_lmh = false;
924 max_avail_current = qpnp_flash_led_calc_max_current(led);
925 if (led->pdata->thermal_derate_en)
926 thermal_current_lim =
927 qpnp_flash_led_calc_thermal_current_lim(led);
928
929 if (thermal_current_lim)
930 max_avail_current = min(max_avail_current, thermal_current_lim);
931
932 return max_avail_current;
933}
934
Ankit Sharmaa7153c32017-03-22 19:04:52 +0530935static void qpnp_flash_led_aggregate_max_current(struct flash_node_data *fnode)
936{
937 struct qpnp_flash_led *led = dev_get_drvdata(&fnode->pdev->dev);
938
939 if (fnode->current_ma)
940 led->total_current_ma += fnode->current_ma
941 - fnode->prev_current_ma;
942 else
943 led->total_current_ma -= fnode->prev_current_ma;
944
945 fnode->prev_current_ma = fnode->current_ma;
946}
947
David Collins8885f792017-01-26 14:36:34 -0800948static void qpnp_flash_led_node_set(struct flash_node_data *fnode, int value)
949{
Kiran Gunda5cadca72017-07-26 14:37:52 +0530950 int i = 0;
David Collins8885f792017-01-26 14:36:34 -0800951 int prgm_current_ma = value;
Ankit Sharma8798ab12017-04-06 15:44:09 +0530952 int min_ma = fnode->ires_ua / 1000;
Ankit Sharmaa7153c32017-03-22 19:04:52 +0530953 struct qpnp_flash_led *led = dev_get_drvdata(&fnode->pdev->dev);
David Collins8885f792017-01-26 14:36:34 -0800954
955 if (value <= 0)
956 prgm_current_ma = 0;
Ankit Sharma8798ab12017-04-06 15:44:09 +0530957 else if (value < min_ma)
958 prgm_current_ma = min_ma;
David Collins8885f792017-01-26 14:36:34 -0800959
Kiran Gunda5cadca72017-07-26 14:37:52 +0530960 fnode->ires_idx = fnode->default_ires_idx;
961 fnode->ires_ua = fnode->default_ires_ua;
962
David Collins8885f792017-01-26 14:36:34 -0800963 prgm_current_ma = min(prgm_current_ma, fnode->max_current);
Kiran Gunda5cadca72017-07-26 14:37:52 +0530964 if (prgm_current_ma > max_ires_curr_ma_table[fnode->ires_idx]) {
965 /* find the matching ires */
966 for (i = MAX_IRES_LEVELS - 1; i >= 0; i--) {
967 if (prgm_current_ma <= max_ires_curr_ma_table[i]) {
968 fnode->ires_idx = i;
969 fnode->ires_ua = FLASH_LED_IRES_MIN_UA +
970 (FLASH_LED_IRES_BASE - fnode->ires_idx) *
971 FLASH_LED_IRES_DIVISOR;
972 break;
973 }
974 }
975 }
David Collins8885f792017-01-26 14:36:34 -0800976 fnode->current_ma = prgm_current_ma;
977 fnode->cdev.brightness = prgm_current_ma;
978 fnode->current_reg_val = CURRENT_MA_TO_REG_VAL(prgm_current_ma,
979 fnode->ires_ua);
980 fnode->led_on = prgm_current_ma != 0;
Ankit Sharmaa7153c32017-03-22 19:04:52 +0530981
982 if (led->pdata->chgr_mitigation_sel == FLASH_SW_CHARGER_MITIGATION) {
983 qpnp_flash_led_aggregate_max_current(fnode);
984 led->trigger_chgr = false;
985 if (led->total_current_ma >= 1000)
986 led->trigger_chgr = true;
987 }
David Collins8885f792017-01-26 14:36:34 -0800988}
989
990static int qpnp_flash_led_switch_disable(struct flash_switch_data *snode)
991{
992 struct qpnp_flash_led *led = dev_get_drvdata(&snode->pdev->dev);
993 int i, rc, addr_offset;
994
995 rc = qpnp_flash_led_masked_write(led,
996 FLASH_LED_EN_LED_CTRL(led->base),
997 snode->led_mask, FLASH_LED_DISABLE);
998 if (rc < 0)
999 return rc;
1000
1001 if (led->trigger_lmh) {
1002 rc = qpnp_flash_led_masked_write(led,
1003 FLASH_LED_REG_MITIGATION_SW(led->base),
1004 FLASH_LED_LMH_MITIGATION_EN_MASK,
1005 FLASH_LED_LMH_MITIGATION_DISABLE);
1006 if (rc < 0) {
1007 pr_err("disable lmh mitigation failed, rc=%d\n", rc);
1008 return rc;
1009 }
1010 }
1011
1012 if (!led->trigger_chgr) {
1013 rc = qpnp_flash_led_masked_write(led,
1014 FLASH_LED_REG_MITIGATION_SW(led->base),
1015 FLASH_LED_CHGR_MITIGATION_EN_MASK,
1016 FLASH_LED_CHGR_MITIGATION_DISABLE);
1017 if (rc < 0) {
1018 pr_err("disable chgr mitigation failed, rc=%d\n", rc);
1019 return rc;
1020 }
1021 }
1022
1023 led->enable--;
1024 if (led->enable == 0) {
1025 rc = qpnp_flash_led_masked_write(led,
1026 FLASH_LED_REG_MOD_CTRL(led->base),
1027 FLASH_LED_MOD_CTRL_MASK, FLASH_LED_DISABLE);
1028 if (rc < 0)
1029 return rc;
1030 }
1031
1032 for (i = 0; i < led->num_fnodes; i++) {
1033 if (!led->fnode[i].led_on ||
1034 !(snode->led_mask & BIT(led->fnode[i].id)))
1035 continue;
1036
1037 addr_offset = led->fnode[i].id;
1038 rc = qpnp_flash_led_masked_write(led,
1039 FLASH_LED_REG_TGR_CURRENT(led->base + addr_offset),
1040 FLASH_LED_CURRENT_MASK, 0);
1041 if (rc < 0)
1042 return rc;
1043
1044 led->fnode[i].led_on = false;
1045
Subbaraman Narayanamurthy3f684b22017-03-21 20:49:54 -07001046 if (led->fnode[i].strobe_sel == HW_STROBE) {
David Collins8885f792017-01-26 14:36:34 -08001047 rc = qpnp_flash_led_hw_strobe_enable(&led->fnode[i],
1048 led->pdata->hw_strobe_option, false);
1049 if (rc < 0) {
1050 pr_err("Unable to disable hw strobe, rc=%d\n",
1051 rc);
1052 return rc;
1053 }
1054 }
1055 }
1056
Subbaraman Narayanamurthy58377f02017-03-21 20:38:43 -07001057 if (snode->led_en_pinctrl) {
1058 pr_debug("Selecting suspend state for %s\n", snode->cdev.name);
1059 rc = pinctrl_select_state(snode->led_en_pinctrl,
1060 snode->gpio_state_suspend);
1061 if (rc < 0) {
1062 pr_err("failed to select pinctrl suspend state rc=%d\n",
1063 rc);
1064 return rc;
1065 }
1066 }
1067
David Collins8885f792017-01-26 14:36:34 -08001068 snode->enabled = false;
1069 return 0;
1070}
1071
1072static int qpnp_flash_led_switch_set(struct flash_switch_data *snode, bool on)
1073{
1074 struct qpnp_flash_led *led = dev_get_drvdata(&snode->pdev->dev);
1075 int rc, i, addr_offset;
1076 u8 val, mask;
1077
1078 if (snode->enabled == on) {
1079 pr_debug("Switch node is already %s!\n",
1080 on ? "enabled" : "disabled");
1081 return 0;
1082 }
1083
1084 if (!on) {
1085 rc = qpnp_flash_led_switch_disable(snode);
1086 return rc;
1087 }
1088
1089 /* Iterate over all leds for this switch node */
1090 val = 0;
1091 for (i = 0; i < led->num_fnodes; i++)
1092 if (snode->led_mask & BIT(led->fnode[i].id))
Kiran Gunda5cadca72017-07-26 14:37:52 +05301093 val |= led->fnode[i].ires_idx << (led->fnode[i].id * 2);
David Collins8885f792017-01-26 14:36:34 -08001094
1095 rc = qpnp_flash_led_masked_write(led, FLASH_LED_REG_IRES(led->base),
1096 FLASH_LED_CURRENT_MASK, val);
1097 if (rc < 0)
1098 return rc;
1099
David Collins8885f792017-01-26 14:36:34 -08001100 val = 0;
1101 for (i = 0; i < led->num_fnodes; i++) {
1102 if (!led->fnode[i].led_on ||
1103 !(snode->led_mask & BIT(led->fnode[i].id)))
1104 continue;
1105
1106 addr_offset = led->fnode[i].id;
Subbaraman Narayanamurthy3f684b22017-03-21 20:49:54 -07001107 if (led->fnode[i].strobe_sel == SW_STROBE)
David Collins8885f792017-01-26 14:36:34 -08001108 mask = FLASH_LED_HW_SW_STROBE_SEL_BIT;
Subbaraman Narayanamurthy3f684b22017-03-21 20:49:54 -07001109 else
1110 mask = FLASH_HW_STROBE_MASK;
David Collins8885f792017-01-26 14:36:34 -08001111 rc = qpnp_flash_led_masked_write(led,
1112 FLASH_LED_REG_STROBE_CTRL(led->base + addr_offset),
Subbaraman Narayanamurthy3f684b22017-03-21 20:49:54 -07001113 mask, led->fnode[i].strobe_ctrl);
David Collins8885f792017-01-26 14:36:34 -08001114 if (rc < 0)
1115 return rc;
1116
1117 rc = qpnp_flash_led_masked_write(led,
1118 FLASH_LED_REG_TGR_CURRENT(led->base + addr_offset),
1119 FLASH_LED_CURRENT_MASK, led->fnode[i].current_reg_val);
1120 if (rc < 0)
1121 return rc;
1122
1123 rc = qpnp_flash_led_write(led,
1124 FLASH_LED_REG_SAFETY_TMR(led->base + addr_offset),
1125 led->fnode[i].duration);
1126 if (rc < 0)
1127 return rc;
1128
1129 val |= FLASH_LED_ENABLE << led->fnode[i].id;
1130
Subbaraman Narayanamurthy3f684b22017-03-21 20:49:54 -07001131 if (led->fnode[i].strobe_sel == HW_STROBE) {
David Collins8885f792017-01-26 14:36:34 -08001132 rc = qpnp_flash_led_hw_strobe_enable(&led->fnode[i],
1133 led->pdata->hw_strobe_option, true);
1134 if (rc < 0) {
1135 pr_err("Unable to enable hw strobe rc=%d\n",
1136 rc);
1137 return rc;
1138 }
1139 }
1140 }
1141
Subbaraman Narayanamurthy58377f02017-03-21 20:38:43 -07001142 if (snode->led_en_pinctrl) {
1143 pr_debug("Selecting active state for %s\n", snode->cdev.name);
1144 rc = pinctrl_select_state(snode->led_en_pinctrl,
1145 snode->gpio_state_active);
1146 if (rc < 0) {
1147 pr_err("failed to select pinctrl active state rc=%d\n",
1148 rc);
1149 return rc;
1150 }
1151 }
1152
David Collins8885f792017-01-26 14:36:34 -08001153 if (led->enable == 0) {
1154 rc = qpnp_flash_led_masked_write(led,
1155 FLASH_LED_REG_MOD_CTRL(led->base),
1156 FLASH_LED_MOD_CTRL_MASK, FLASH_LED_MOD_ENABLE);
1157 if (rc < 0)
1158 return rc;
1159 }
1160 led->enable++;
1161
1162 if (led->trigger_lmh) {
1163 rc = qpnp_flash_led_masked_write(led,
1164 FLASH_LED_REG_MITIGATION_SW(led->base),
1165 FLASH_LED_LMH_MITIGATION_EN_MASK,
1166 FLASH_LED_LMH_MITIGATION_ENABLE);
1167 if (rc < 0) {
1168 pr_err("trigger lmh mitigation failed, rc=%d\n", rc);
1169 return rc;
1170 }
Subbaraman Narayanamurthyd02fbc92017-02-02 16:39:41 -08001171 /* Wait for LMH mitigation to take effect */
1172 udelay(500);
David Collins8885f792017-01-26 14:36:34 -08001173 }
1174
1175 if (led->trigger_chgr) {
1176 rc = qpnp_flash_led_masked_write(led,
1177 FLASH_LED_REG_MITIGATION_SW(led->base),
1178 FLASH_LED_CHGR_MITIGATION_EN_MASK,
1179 FLASH_LED_CHGR_MITIGATION_ENABLE);
1180 if (rc < 0) {
1181 pr_err("trigger chgr mitigation failed, rc=%d\n", rc);
1182 return rc;
1183 }
1184 }
1185
1186 rc = qpnp_flash_led_masked_write(led,
1187 FLASH_LED_EN_LED_CTRL(led->base),
1188 snode->led_mask, val);
1189 if (rc < 0)
1190 return rc;
1191
1192 snode->enabled = true;
1193 return 0;
1194}
1195
1196int qpnp_flash_led_prepare(struct led_trigger *trig, int options,
1197 int *max_current)
1198{
1199 struct led_classdev *led_cdev;
1200 struct flash_switch_data *snode;
1201 struct qpnp_flash_led *led;
1202 int rc;
1203
1204 if (!trig) {
1205 pr_err("Invalid led_trigger provided\n");
1206 return -EINVAL;
1207 }
1208
1209 led_cdev = trigger_to_lcdev(trig);
1210 if (!led_cdev) {
1211 pr_err("Invalid led_cdev in trigger %s\n", trig->name);
1212 return -EINVAL;
1213 }
1214
1215 snode = container_of(led_cdev, struct flash_switch_data, cdev);
1216 led = dev_get_drvdata(&snode->pdev->dev);
1217
1218 if (!(options & FLASH_LED_PREPARE_OPTIONS_MASK)) {
1219 pr_err("Invalid options %d\n", options);
1220 return -EINVAL;
1221 }
1222
1223 if (options & ENABLE_REGULATOR) {
1224 rc = qpnp_flash_led_regulator_enable(led, snode, true);
1225 if (rc < 0) {
1226 pr_err("enable regulator failed, rc=%d\n", rc);
1227 return rc;
1228 }
1229 }
1230
1231 if (options & DISABLE_REGULATOR) {
1232 rc = qpnp_flash_led_regulator_enable(led, snode, false);
1233 if (rc < 0) {
1234 pr_err("disable regulator failed, rc=%d\n", rc);
1235 return rc;
1236 }
1237 }
1238
1239 if (options & QUERY_MAX_CURRENT) {
1240 rc = qpnp_flash_led_get_max_avail_current(led);
1241 if (rc < 0) {
1242 pr_err("query max current failed, rc=%d\n", rc);
1243 return rc;
1244 }
1245 *max_current = rc;
1246 }
1247
David Collins8885f792017-01-26 14:36:34 -08001248 return 0;
1249}
1250
1251static void qpnp_flash_led_brightness_set(struct led_classdev *led_cdev,
1252 enum led_brightness value)
1253{
1254 struct flash_node_data *fnode = NULL;
1255 struct flash_switch_data *snode = NULL;
1256 struct qpnp_flash_led *led = NULL;
1257 int rc;
1258
1259 /*
1260 * strncmp() must be used here since a prefix comparison is required
1261 * in order to support names like led:switch_0 and led:flash_1.
1262 */
1263 if (!strncmp(led_cdev->name, "led:switch", strlen("led:switch"))) {
1264 snode = container_of(led_cdev, struct flash_switch_data, cdev);
1265 led = dev_get_drvdata(&snode->pdev->dev);
1266 } else if (!strncmp(led_cdev->name, "led:flash", strlen("led:flash")) ||
1267 !strncmp(led_cdev->name, "led:torch",
1268 strlen("led:torch"))) {
1269 fnode = container_of(led_cdev, struct flash_node_data, cdev);
1270 led = dev_get_drvdata(&fnode->pdev->dev);
1271 }
1272
1273 if (!led) {
1274 pr_err("Failed to get flash driver data\n");
1275 return;
1276 }
1277
1278 spin_lock(&led->lock);
1279 if (snode) {
1280 rc = qpnp_flash_led_switch_set(snode, value > 0);
1281 if (rc < 0)
1282 pr_err("Failed to set flash LED switch rc=%d\n", rc);
1283 } else if (fnode) {
1284 qpnp_flash_led_node_set(fnode, value);
1285 }
1286
1287 spin_unlock(&led->lock);
1288}
1289
1290/* sysfs show function for flash_max_current */
1291static ssize_t qpnp_flash_led_max_current_show(struct device *dev,
1292 struct device_attribute *attr, char *buf)
1293{
1294 int rc;
1295 struct flash_switch_data *snode;
1296 struct qpnp_flash_led *led;
1297 struct led_classdev *led_cdev = dev_get_drvdata(dev);
1298
1299 snode = container_of(led_cdev, struct flash_switch_data, cdev);
1300 led = dev_get_drvdata(&snode->pdev->dev);
1301
1302 rc = qpnp_flash_led_get_max_avail_current(led);
1303 if (rc < 0)
1304 pr_err("query max current failed, rc=%d\n", rc);
1305
1306 return snprintf(buf, PAGE_SIZE, "%d\n", rc);
1307}
1308
1309/* sysfs attributes exported by flash_led */
1310static struct device_attribute qpnp_flash_led_attrs[] = {
1311 __ATTR(max_current, 0664, qpnp_flash_led_max_current_show, NULL),
1312};
1313
1314static int flash_led_psy_notifier_call(struct notifier_block *nb,
1315 unsigned long ev, void *v)
1316{
1317 struct power_supply *psy = v;
1318 struct qpnp_flash_led *led =
1319 container_of(nb, struct qpnp_flash_led, nb);
1320
1321 if (ev != PSY_EVENT_PROP_CHANGED)
1322 return NOTIFY_OK;
1323
1324 if (!strcmp(psy->desc->name, "bms")) {
1325 led->bms_psy = power_supply_get_by_name("bms");
1326 if (!led->bms_psy)
1327 pr_err("Failed to get bms power_supply\n");
1328 else
1329 power_supply_unreg_notifier(&led->nb);
1330 }
1331
1332 return NOTIFY_OK;
1333}
1334
1335static int flash_led_psy_register_notifier(struct qpnp_flash_led *led)
1336{
1337 int rc;
1338
1339 led->nb.notifier_call = flash_led_psy_notifier_call;
1340 rc = power_supply_reg_notifier(&led->nb);
1341 if (rc < 0) {
1342 pr_err("Couldn't register psy notifier, rc = %d\n", rc);
1343 return rc;
1344 }
1345
1346 return 0;
1347}
1348
1349/* irq handler */
1350static irqreturn_t qpnp_flash_led_irq_handler(int irq, void *_led)
1351{
1352 struct qpnp_flash_led *led = _led;
1353 enum flash_led_irq_type irq_type = INVALID_IRQ;
1354 int rc;
1355 u8 irq_status, led_status1, led_status2;
1356
1357 pr_debug("irq received, irq=%d\n", irq);
1358
1359 rc = qpnp_flash_led_read(led,
1360 FLASH_LED_REG_INT_RT_STS(led->base), &irq_status);
1361 if (rc < 0) {
1362 pr_err("Failed to read interrupt status reg, rc=%d\n", rc);
1363 goto exit;
1364 }
1365
1366 if (irq == led->pdata->all_ramp_up_done_irq)
1367 irq_type = ALL_RAMP_UP_DONE_IRQ;
1368 else if (irq == led->pdata->all_ramp_down_done_irq)
1369 irq_type = ALL_RAMP_DOWN_DONE_IRQ;
1370 else if (irq == led->pdata->led_fault_irq)
1371 irq_type = LED_FAULT_IRQ;
1372
1373 if (irq_type == ALL_RAMP_UP_DONE_IRQ)
1374 atomic_notifier_call_chain(&irq_notifier_list,
1375 irq_type, NULL);
1376
1377 if (irq_type == LED_FAULT_IRQ) {
1378 rc = qpnp_flash_led_read(led,
1379 FLASH_LED_REG_LED_STATUS1(led->base), &led_status1);
1380 if (rc < 0) {
1381 pr_err("Failed to read led_status1 reg, rc=%d\n", rc);
1382 goto exit;
1383 }
1384
1385 rc = qpnp_flash_led_read(led,
1386 FLASH_LED_REG_LED_STATUS2(led->base), &led_status2);
1387 if (rc < 0) {
1388 pr_err("Failed to read led_status2 reg, rc=%d\n", rc);
1389 goto exit;
1390 }
1391
1392 if (led_status1)
1393 pr_emerg("led short/open fault detected! led_status1=%x\n",
1394 led_status1);
1395
1396 if (led_status2 & FLASH_LED_VPH_DROOP_FAULT_MASK)
1397 pr_emerg("led vph_droop fault detected!\n");
1398 }
1399
1400 pr_debug("irq handled, irq_type=%x, irq_status=%x\n", irq_type,
1401 irq_status);
1402
1403exit:
1404 return IRQ_HANDLED;
1405}
1406
1407int qpnp_flash_led_register_irq_notifier(struct notifier_block *nb)
1408{
1409 return atomic_notifier_chain_register(&irq_notifier_list, nb);
1410}
1411
1412int qpnp_flash_led_unregister_irq_notifier(struct notifier_block *nb)
1413{
1414 return atomic_notifier_chain_unregister(&irq_notifier_list, nb);
1415}
1416
1417static int qpnp_flash_led_parse_each_led_dt(struct qpnp_flash_led *led,
1418 struct flash_node_data *fnode, struct device_node *node)
1419{
1420 const char *temp_string;
Ankit Sharma8798ab12017-04-06 15:44:09 +05301421 int rc, min_ma;
David Collins8885f792017-01-26 14:36:34 -08001422 u32 val;
Subbaraman Narayanamurthy3f684b22017-03-21 20:49:54 -07001423 bool hw_strobe = 0, edge_trigger = 0, active_high = 0;
David Collins8885f792017-01-26 14:36:34 -08001424
1425 fnode->pdev = led->pdev;
1426 fnode->cdev.brightness_set = qpnp_flash_led_brightness_set;
1427 fnode->cdev.brightness_get = qpnp_flash_led_brightness_get;
1428
1429 rc = of_property_read_string(node, "qcom,led-name", &fnode->cdev.name);
1430 if (rc < 0) {
1431 pr_err("Unable to read flash LED names\n");
1432 return rc;
1433 }
1434
1435 rc = of_property_read_string(node, "label", &temp_string);
1436 if (!rc) {
1437 if (!strcmp(temp_string, "flash")) {
1438 fnode->type = FLASH_LED_TYPE_FLASH;
1439 } else if (!strcmp(temp_string, "torch")) {
1440 fnode->type = FLASH_LED_TYPE_TORCH;
1441 } else {
1442 pr_err("Wrong flash LED type\n");
1443 return rc;
1444 }
1445 } else {
1446 pr_err("Unable to read flash LED label\n");
1447 return rc;
1448 }
1449
1450 rc = of_property_read_u32(node, "qcom,id", &val);
1451 if (!rc) {
1452 fnode->id = (u8)val;
1453 } else {
1454 pr_err("Unable to read flash LED ID\n");
1455 return rc;
1456 }
1457
1458 rc = of_property_read_string(node, "qcom,default-led-trigger",
1459 &fnode->cdev.default_trigger);
1460 if (rc < 0) {
1461 pr_err("Unable to read trigger name\n");
1462 return rc;
1463 }
1464
Kiran Gunda5cadca72017-07-26 14:37:52 +05301465 fnode->default_ires_ua = fnode->ires_ua = FLASH_LED_IRES_DEFAULT_UA;
1466 fnode->default_ires_idx = fnode->ires_idx = FLASH_LED_IRES_DEFAULT_VAL;
David Collins8885f792017-01-26 14:36:34 -08001467 rc = of_property_read_u32(node, "qcom,ires-ua", &val);
1468 if (!rc) {
Kiran Gunda5cadca72017-07-26 14:37:52 +05301469 fnode->default_ires_ua = fnode->ires_ua = val;
1470 fnode->default_ires_idx = fnode->ires_idx =
1471 FLASH_LED_IRES_BASE - (val - FLASH_LED_IRES_MIN_UA) /
1472 FLASH_LED_IRES_DIVISOR;
David Collins8885f792017-01-26 14:36:34 -08001473 } else if (rc != -EINVAL) {
1474 pr_err("Unable to read current resolution rc=%d\n", rc);
1475 return rc;
1476 }
1477
Ankit Sharma8798ab12017-04-06 15:44:09 +05301478 min_ma = fnode->ires_ua / 1000;
David Collins8885f792017-01-26 14:36:34 -08001479 rc = of_property_read_u32(node, "qcom,max-current", &val);
1480 if (!rc) {
Ankit Sharma8798ab12017-04-06 15:44:09 +05301481 if (val < min_ma)
1482 val = min_ma;
David Collins8885f792017-01-26 14:36:34 -08001483 fnode->max_current = val;
1484 fnode->cdev.max_brightness = val;
1485 } else {
1486 pr_err("Unable to read max current, rc=%d\n", rc);
1487 return rc;
1488 }
1489
1490 rc = of_property_read_u32(node, "qcom,current-ma", &val);
1491 if (!rc) {
Ankit Sharma8798ab12017-04-06 15:44:09 +05301492 if (val < min_ma || val > fnode->max_current)
David Collins8885f792017-01-26 14:36:34 -08001493 pr_warn("Invalid operational current specified, capping it\n");
Ankit Sharma8798ab12017-04-06 15:44:09 +05301494 if (val < min_ma)
1495 val = min_ma;
David Collins8885f792017-01-26 14:36:34 -08001496 if (val > fnode->max_current)
1497 val = fnode->max_current;
1498 fnode->current_ma = val;
1499 fnode->cdev.brightness = val;
1500 } else if (rc != -EINVAL) {
1501 pr_err("Unable to read operational current, rc=%d\n", rc);
1502 return rc;
1503 }
1504
1505 fnode->duration = FLASH_LED_SAFETY_TMR_DISABLED;
1506 rc = of_property_read_u32(node, "qcom,duration-ms", &val);
1507 if (!rc) {
1508 fnode->duration = (u8)(SAFETY_TMR_TO_REG_VAL(val) |
1509 FLASH_LED_SAFETY_TMR_ENABLE);
1510 } else if (rc == -EINVAL) {
1511 if (fnode->type == FLASH_LED_TYPE_FLASH) {
1512 pr_err("Timer duration is required for flash LED\n");
1513 return rc;
1514 }
1515 } else {
1516 pr_err("Unable to read timer duration\n");
1517 return rc;
1518 }
1519
1520 fnode->hdrm_val = FLASH_LED_HDRM_VOL_DEFAULT_MV;
1521 rc = of_property_read_u32(node, "qcom,hdrm-voltage-mv", &val);
1522 if (!rc) {
1523 val = (val - FLASH_LED_HDRM_VOL_BASE_MV) /
1524 FLASH_LED_HDRM_VOL_STEP_MV;
1525 fnode->hdrm_val = (val << FLASH_LED_HDRM_VOL_SHIFT) &
1526 FLASH_LED_HDRM_VOL_MASK;
1527 } else if (rc != -EINVAL) {
1528 pr_err("Unable to read headroom voltage\n");
1529 return rc;
1530 }
1531
1532 rc = of_property_read_u32(node, "qcom,hdrm-vol-hi-lo-win-mv", &val);
1533 if (!rc) {
1534 fnode->hdrm_val |= (val / FLASH_LED_HDRM_VOL_STEP_MV) &
1535 ~FLASH_LED_HDRM_VOL_MASK;
1536 } else if (rc == -EINVAL) {
1537 fnode->hdrm_val |= FLASH_LED_HDRM_VOL_HI_LO_WIN_DEFAULT_MV;
1538 } else {
1539 pr_err("Unable to read hdrm hi-lo window voltage\n");
1540 return rc;
1541 }
1542
Subbaraman Narayanamurthy3f684b22017-03-21 20:49:54 -07001543 fnode->strobe_sel = SW_STROBE;
1544 rc = of_property_read_u32(node, "qcom,strobe-sel", &val);
1545 if (rc < 0) {
1546 if (rc != -EINVAL) {
1547 pr_err("Unable to read qcom,strobe-sel property\n");
1548 return rc;
1549 }
1550 } else {
1551 if (val < SW_STROBE || val > LPG_STROBE) {
1552 pr_err("Incorrect strobe selection specified %d\n",
1553 val);
1554 return -EINVAL;
1555 }
1556 fnode->strobe_sel = (u8)val;
1557 }
1558
1559 /*
1560 * LPG strobe is allowed only for LED3 and HW strobe option should be
1561 * option 2 or 3.
1562 */
1563 if (fnode->strobe_sel == LPG_STROBE) {
1564 if (led->pdata->hw_strobe_option ==
1565 FLASH_LED_HW_STROBE_OPTION_1) {
1566 pr_err("Incorrect strobe option for LPG strobe\n");
1567 return -EINVAL;
1568 }
1569 if (fnode->id != LED3) {
1570 pr_err("Incorrect LED chosen for LPG strobe\n");
1571 return -EINVAL;
1572 }
1573 }
1574
1575 if (fnode->strobe_sel == HW_STROBE) {
David Collins8885f792017-01-26 14:36:34 -08001576 edge_trigger = of_property_read_bool(node,
1577 "qcom,hw-strobe-edge-trigger");
1578 active_high = !of_property_read_bool(node,
1579 "qcom,hw-strobe-active-low");
Subbaraman Narayanamurthy3f684b22017-03-21 20:49:54 -07001580 hw_strobe = 1;
1581 } else if (fnode->strobe_sel == LPG_STROBE) {
1582 /* LPG strobe requires level trigger and active high */
1583 edge_trigger = 0;
1584 active_high = 1;
1585 hw_strobe = 1;
David Collins8885f792017-01-26 14:36:34 -08001586 }
Subbaraman Narayanamurthy3f684b22017-03-21 20:49:54 -07001587 fnode->strobe_ctrl = (hw_strobe << 2) | (edge_trigger << 1) |
1588 active_high;
David Collins8885f792017-01-26 14:36:34 -08001589
Subbaraman Narayanamurthy58377f02017-03-21 20:38:43 -07001590 rc = led_classdev_register(&led->pdev->dev, &fnode->cdev);
1591 if (rc < 0) {
1592 pr_err("Unable to register led node %d\n", fnode->id);
1593 return rc;
1594 }
1595
1596 fnode->cdev.dev->of_node = node;
1597 fnode->strobe_pinctrl = devm_pinctrl_get(fnode->cdev.dev);
1598 if (IS_ERR_OR_NULL(fnode->strobe_pinctrl)) {
1599 pr_debug("No pinctrl defined for %s, err=%ld\n",
1600 fnode->cdev.name, PTR_ERR(fnode->strobe_pinctrl));
1601 fnode->strobe_pinctrl = NULL;
1602 }
1603
Subbaraman Narayanamurthy3f684b22017-03-21 20:49:54 -07001604 if (fnode->strobe_sel == HW_STROBE) {
David Collins8885f792017-01-26 14:36:34 -08001605 if (of_find_property(node, "qcom,hw-strobe-gpio", NULL)) {
1606 fnode->hw_strobe_gpio = of_get_named_gpio(node,
1607 "qcom,hw-strobe-gpio", 0);
1608 if (fnode->hw_strobe_gpio < 0) {
1609 pr_err("Invalid gpio specified\n");
1610 return fnode->hw_strobe_gpio;
1611 }
1612 gpio_direction_output(fnode->hw_strobe_gpio, 0);
Subbaraman Narayanamurthy58377f02017-03-21 20:38:43 -07001613 } else if (fnode->strobe_pinctrl) {
David Collins8885f792017-01-26 14:36:34 -08001614 fnode->hw_strobe_gpio = -1;
1615 fnode->hw_strobe_state_active =
Subbaraman Narayanamurthy58377f02017-03-21 20:38:43 -07001616 pinctrl_lookup_state(fnode->strobe_pinctrl,
1617 "strobe_enable");
David Collins8885f792017-01-26 14:36:34 -08001618 if (IS_ERR_OR_NULL(fnode->hw_strobe_state_active)) {
1619 pr_err("No active pin for hardware strobe, rc=%ld\n",
1620 PTR_ERR(fnode->hw_strobe_state_active));
1621 fnode->hw_strobe_state_active = NULL;
1622 }
1623
1624 fnode->hw_strobe_state_suspend =
Subbaraman Narayanamurthy58377f02017-03-21 20:38:43 -07001625 pinctrl_lookup_state(fnode->strobe_pinctrl,
1626 "strobe_disable");
David Collins8885f792017-01-26 14:36:34 -08001627 if (IS_ERR_OR_NULL(fnode->hw_strobe_state_suspend)) {
1628 pr_err("No suspend pin for hardware strobe, rc=%ld\n",
1629 PTR_ERR(fnode->hw_strobe_state_suspend)
1630 );
1631 fnode->hw_strobe_state_suspend = NULL;
1632 }
1633 }
1634 }
1635
David Collins8885f792017-01-26 14:36:34 -08001636 return 0;
1637}
1638
1639static int qpnp_flash_led_parse_and_register_switch(struct qpnp_flash_led *led,
1640 struct flash_switch_data *snode,
1641 struct device_node *node)
1642{
1643 int rc = 0, num;
1644 char reg_name[16], reg_sup_name[16];
1645
1646 rc = of_property_read_string(node, "qcom,led-name", &snode->cdev.name);
1647 if (rc < 0) {
1648 pr_err("Failed to read switch node name, rc=%d\n", rc);
1649 return rc;
1650 }
1651
1652 rc = sscanf(snode->cdev.name, "led:switch_%d", &num);
1653 if (!rc) {
1654 pr_err("No number for switch device?\n");
1655 return -EINVAL;
1656 }
1657
1658 rc = of_property_read_string(node, "qcom,default-led-trigger",
1659 &snode->cdev.default_trigger);
1660 if (rc < 0) {
1661 pr_err("Unable to read trigger name, rc=%d\n", rc);
1662 return rc;
1663 }
1664
1665 rc = of_property_read_u32(node, "qcom,led-mask", &snode->led_mask);
1666 if (rc < 0) {
1667 pr_err("Unable to read led mask rc=%d\n", rc);
1668 return rc;
1669 }
1670
1671 if (snode->led_mask < 1 || snode->led_mask > 7) {
1672 pr_err("Invalid value for led-mask\n");
1673 return -EINVAL;
1674 }
1675
1676 scnprintf(reg_name, sizeof(reg_name), "switch%d-supply", num);
1677 if (of_find_property(led->pdev->dev.of_node, reg_name, NULL)) {
1678 scnprintf(reg_sup_name, sizeof(reg_sup_name), "switch%d", num);
1679 snode->vreg = devm_regulator_get(&led->pdev->dev, reg_sup_name);
1680 if (IS_ERR_OR_NULL(snode->vreg)) {
1681 rc = PTR_ERR(snode->vreg);
1682 if (rc != -EPROBE_DEFER)
1683 pr_err("Failed to get regulator, rc=%d\n", rc);
1684 snode->vreg = NULL;
1685 return rc;
1686 }
1687 }
1688
1689 snode->pdev = led->pdev;
1690 snode->cdev.brightness_set = qpnp_flash_led_brightness_set;
1691 snode->cdev.brightness_get = qpnp_flash_led_brightness_get;
1692 snode->cdev.flags |= LED_KEEP_TRIGGER;
1693 rc = led_classdev_register(&led->pdev->dev, &snode->cdev);
1694 if (rc < 0) {
1695 pr_err("Unable to register led switch node\n");
1696 return rc;
1697 }
1698
1699 snode->cdev.dev->of_node = node;
Subbaraman Narayanamurthy58377f02017-03-21 20:38:43 -07001700
1701 snode->led_en_pinctrl = devm_pinctrl_get(snode->cdev.dev);
1702 if (IS_ERR_OR_NULL(snode->led_en_pinctrl)) {
1703 pr_debug("No pinctrl defined for %s, err=%ld\n",
1704 snode->cdev.name, PTR_ERR(snode->led_en_pinctrl));
1705 snode->led_en_pinctrl = NULL;
1706 }
1707
1708 if (snode->led_en_pinctrl) {
1709 snode->gpio_state_active =
1710 pinctrl_lookup_state(snode->led_en_pinctrl,
1711 "led_enable");
1712 if (IS_ERR_OR_NULL(snode->gpio_state_active)) {
1713 pr_err("Cannot lookup LED active state\n");
1714 devm_pinctrl_put(snode->led_en_pinctrl);
1715 snode->led_en_pinctrl = NULL;
1716 return PTR_ERR(snode->gpio_state_active);
1717 }
1718
1719 snode->gpio_state_suspend =
1720 pinctrl_lookup_state(snode->led_en_pinctrl,
1721 "led_disable");
1722 if (IS_ERR_OR_NULL(snode->gpio_state_suspend)) {
1723 pr_err("Cannot lookup LED disable state\n");
1724 devm_pinctrl_put(snode->led_en_pinctrl);
1725 snode->led_en_pinctrl = NULL;
1726 return PTR_ERR(snode->gpio_state_suspend);
1727 }
1728 }
1729
David Collins8885f792017-01-26 14:36:34 -08001730 return 0;
1731}
1732
1733static int get_code_from_table(int *table, int len, int value)
1734{
1735 int i;
1736
1737 for (i = 0; i < len; i++) {
1738 if (value == table[i])
1739 break;
1740 }
1741
1742 if (i == len) {
1743 pr_err("Couldn't find %d from table\n", value);
1744 return -ENODATA;
1745 }
1746
1747 return i;
1748}
1749
1750static int qpnp_flash_led_parse_common_dt(struct qpnp_flash_led *led,
1751 struct device_node *node)
1752{
1753 struct device_node *revid_node;
1754 int rc;
1755 u32 val;
1756 bool short_circuit_det, open_circuit_det, vph_droop_det;
1757
1758 revid_node = of_parse_phandle(node, "qcom,pmic-revid", 0);
1759 if (!revid_node) {
1760 pr_err("Missing qcom,pmic-revid property - driver failed\n");
1761 return -EINVAL;
1762 }
1763
1764 led->pdata->pmic_rev_id = get_revid_data(revid_node);
1765 if (IS_ERR_OR_NULL(led->pdata->pmic_rev_id)) {
1766 pr_err("Unable to get pmic_revid rc=%ld\n",
1767 PTR_ERR(led->pdata->pmic_rev_id));
1768 /*
1769 * the revid peripheral must be registered, any failure
1770 * here only indicates that the rev-id module has not
1771 * probed yet.
1772 */
1773 return -EPROBE_DEFER;
1774 }
1775
1776 pr_debug("PMIC subtype %d Digital major %d\n",
1777 led->pdata->pmic_rev_id->pmic_subtype,
1778 led->pdata->pmic_rev_id->rev4);
1779
1780 led->pdata->hdrm_auto_mode_en = of_property_read_bool(node,
1781 "qcom,hdrm-auto-mode");
1782
1783 led->pdata->isc_delay = FLASH_LED_ISC_DELAY_DEFAULT;
1784 rc = of_property_read_u32(node, "qcom,isc-delay-us", &val);
1785 if (!rc) {
1786 led->pdata->isc_delay =
1787 val >> FLASH_LED_ISC_WARMUP_DELAY_SHIFT;
1788 } else if (rc != -EINVAL) {
1789 pr_err("Unable to read ISC delay, rc=%d\n", rc);
1790 return rc;
1791 }
1792
1793 led->pdata->warmup_delay = FLASH_LED_WARMUP_DELAY_DEFAULT;
1794 rc = of_property_read_u32(node, "qcom,warmup-delay-us", &val);
1795 if (!rc) {
1796 led->pdata->warmup_delay =
1797 val >> FLASH_LED_ISC_WARMUP_DELAY_SHIFT;
1798 } else if (rc != -EINVAL) {
1799 pr_err("Unable to read WARMUP delay, rc=%d\n", rc);
1800 return rc;
1801 }
1802
1803 short_circuit_det =
1804 of_property_read_bool(node, "qcom,short-circuit-det");
1805 open_circuit_det = of_property_read_bool(node, "qcom,open-circuit-det");
1806 vph_droop_det = of_property_read_bool(node, "qcom,vph-droop-det");
1807 led->pdata->current_derate_en_cfg = (vph_droop_det << 2) |
1808 (open_circuit_det << 1) | short_circuit_det;
1809
1810 led->pdata->thermal_derate_en =
1811 of_property_read_bool(node, "qcom,thermal-derate-en");
1812
1813 if (led->pdata->thermal_derate_en) {
1814 led->pdata->thermal_derate_current =
1815 devm_kcalloc(&led->pdev->dev,
1816 FLASH_LED_THERMAL_OTST_LEVELS,
1817 sizeof(int), GFP_KERNEL);
1818 if (!led->pdata->thermal_derate_current)
1819 return -ENOMEM;
1820
1821 rc = of_property_read_u32_array(node,
1822 "qcom,thermal-derate-current",
1823 led->pdata->thermal_derate_current,
1824 FLASH_LED_THERMAL_OTST_LEVELS);
1825 if (rc < 0) {
1826 pr_err("Unable to read thermal current limits, rc=%d\n",
1827 rc);
1828 return rc;
1829 }
1830 }
1831
1832 led->pdata->otst_ramp_bkup_en =
1833 !of_property_read_bool(node, "qcom,otst-ramp-back-up-dis");
1834
1835 led->pdata->thermal_derate_slow = -EINVAL;
1836 rc = of_property_read_u32(node, "qcom,thermal-derate-slow", &val);
1837 if (!rc) {
1838 if (val < 0 || val > THERMAL_DERATE_SLOW_MAX) {
1839 pr_err("Invalid thermal_derate_slow %d\n", val);
1840 return -EINVAL;
1841 }
1842
1843 led->pdata->thermal_derate_slow =
1844 get_code_from_table(thermal_derate_slow_table,
1845 ARRAY_SIZE(thermal_derate_slow_table), val);
1846 } else if (rc != -EINVAL) {
1847 pr_err("Unable to read thermal derate slow, rc=%d\n", rc);
1848 return rc;
1849 }
1850
1851 led->pdata->thermal_derate_fast = -EINVAL;
1852 rc = of_property_read_u32(node, "qcom,thermal-derate-fast", &val);
1853 if (!rc) {
1854 if (val < 0 || val > THERMAL_DERATE_FAST_MAX) {
1855 pr_err("Invalid thermal_derate_fast %d\n", val);
1856 return -EINVAL;
1857 }
1858
1859 led->pdata->thermal_derate_fast =
1860 get_code_from_table(thermal_derate_fast_table,
1861 ARRAY_SIZE(thermal_derate_fast_table), val);
1862 } else if (rc != -EINVAL) {
1863 pr_err("Unable to read thermal derate fast, rc=%d\n", rc);
1864 return rc;
1865 }
1866
1867 led->pdata->thermal_debounce = -EINVAL;
1868 rc = of_property_read_u32(node, "qcom,thermal-debounce", &val);
1869 if (!rc) {
1870 if (val < 0 || val > THERMAL_DEBOUNCE_TIME_MAX) {
1871 pr_err("Invalid thermal_debounce %d\n", val);
1872 return -EINVAL;
1873 }
1874
1875 if (val >= 0 && val < 16)
1876 led->pdata->thermal_debounce = 0;
1877 else
1878 led->pdata->thermal_debounce = ilog2(val) - 3;
1879 } else if (rc != -EINVAL) {
1880 pr_err("Unable to read thermal debounce, rc=%d\n", rc);
1881 return rc;
1882 }
1883
1884 led->pdata->thermal_hysteresis = -EINVAL;
1885 rc = of_property_read_u32(node, "qcom,thermal-hysteresis", &val);
1886 if (!rc) {
1887 if (led->pdata->pmic_rev_id->pmic_subtype == PM660L_SUBTYPE)
1888 val = THERMAL_HYST_TEMP_TO_VAL(val, 20);
1889 else
1890 val = THERMAL_HYST_TEMP_TO_VAL(val, 15);
1891
1892 if (val < 0 || val > THERMAL_DERATE_HYSTERESIS_MAX) {
1893 pr_err("Invalid thermal_derate_hysteresis %d\n", val);
1894 return -EINVAL;
1895 }
1896
1897 led->pdata->thermal_hysteresis = val;
1898 } else if (rc != -EINVAL) {
1899 pr_err("Unable to read thermal hysteresis, rc=%d\n", rc);
1900 return rc;
1901 }
1902
1903 led->pdata->thermal_thrsh1 = -EINVAL;
1904 rc = of_property_read_u32(node, "qcom,thermal-thrsh1", &val);
1905 if (!rc) {
1906 led->pdata->thermal_thrsh1 =
1907 get_code_from_table(otst1_threshold_table,
1908 ARRAY_SIZE(otst1_threshold_table), val);
1909 } else if (rc != -EINVAL) {
1910 pr_err("Unable to read thermal thrsh1, rc=%d\n", rc);
1911 return rc;
1912 }
1913
1914 led->pdata->thermal_thrsh2 = -EINVAL;
1915 rc = of_property_read_u32(node, "qcom,thermal-thrsh2", &val);
1916 if (!rc) {
1917 led->pdata->thermal_thrsh2 =
1918 get_code_from_table(otst2_threshold_table,
1919 ARRAY_SIZE(otst2_threshold_table), val);
1920 } else if (rc != -EINVAL) {
1921 pr_err("Unable to read thermal thrsh2, rc=%d\n", rc);
1922 return rc;
1923 }
1924
1925 led->pdata->thermal_thrsh3 = -EINVAL;
1926 rc = of_property_read_u32(node, "qcom,thermal-thrsh3", &val);
1927 if (!rc) {
1928 led->pdata->thermal_thrsh3 =
1929 get_code_from_table(otst3_threshold_table,
1930 ARRAY_SIZE(otst3_threshold_table), val);
1931 } else if (rc != -EINVAL) {
1932 pr_err("Unable to read thermal thrsh3, rc=%d\n", rc);
1933 return rc;
1934 }
1935
1936 led->pdata->vph_droop_debounce = FLASH_LED_VPH_DROOP_DEBOUNCE_DEFAULT;
1937 rc = of_property_read_u32(node, "qcom,vph-droop-debounce-us", &val);
1938 if (!rc) {
1939 led->pdata->vph_droop_debounce =
1940 VPH_DROOP_DEBOUNCE_US_TO_VAL(val);
1941 } else if (rc != -EINVAL) {
1942 pr_err("Unable to read VPH droop debounce, rc=%d\n", rc);
1943 return rc;
1944 }
1945
1946 if (led->pdata->vph_droop_debounce > FLASH_LED_DEBOUNCE_MAX) {
1947 pr_err("Invalid VPH droop debounce specified\n");
1948 return -EINVAL;
1949 }
1950
1951 led->pdata->vph_droop_threshold = FLASH_LED_VPH_DROOP_THRESH_DEFAULT;
1952 rc = of_property_read_u32(node, "qcom,vph-droop-threshold-mv", &val);
1953 if (!rc) {
1954 led->pdata->vph_droop_threshold =
1955 VPH_DROOP_THRESH_MV_TO_VAL(val);
1956 } else if (rc != -EINVAL) {
1957 pr_err("Unable to read VPH droop threshold, rc=%d\n", rc);
1958 return rc;
1959 }
1960
1961 if (led->pdata->vph_droop_threshold > FLASH_LED_VPH_DROOP_THRESH_MAX) {
1962 pr_err("Invalid VPH droop threshold specified\n");
1963 return -EINVAL;
1964 }
1965
1966 led->pdata->vph_droop_hysteresis =
1967 FLASH_LED_VPH_DROOP_HYST_DEFAULT;
1968 rc = of_property_read_u32(node, "qcom,vph-droop-hysteresis-mv", &val);
1969 if (!rc) {
1970 led->pdata->vph_droop_hysteresis =
1971 VPH_DROOP_HYST_MV_TO_VAL(val);
1972 } else if (rc != -EINVAL) {
1973 pr_err("Unable to read VPH droop hysteresis, rc=%d\n", rc);
1974 return rc;
1975 }
1976
1977 if (led->pdata->vph_droop_hysteresis > FLASH_LED_HYSTERESIS_MAX) {
1978 pr_err("Invalid VPH droop hysteresis specified\n");
1979 return -EINVAL;
1980 }
1981
1982 led->pdata->vph_droop_hysteresis <<= FLASH_LED_VPH_DROOP_HYST_SHIFT;
1983
Subbaraman Narayanamurthy3f684b22017-03-21 20:49:54 -07001984 led->pdata->hw_strobe_option = -EINVAL;
David Collins8885f792017-01-26 14:36:34 -08001985 rc = of_property_read_u32(node, "qcom,hw-strobe-option", &val);
1986 if (!rc) {
Subbaraman Narayanamurthy3f684b22017-03-21 20:49:54 -07001987 led->pdata->hw_strobe_option = val;
David Collins8885f792017-01-26 14:36:34 -08001988 } else if (rc != -EINVAL) {
1989 pr_err("Unable to parse hw strobe option, rc=%d\n", rc);
1990 return rc;
1991 }
1992
1993 rc = of_property_read_u32(node, "qcom,led1n2-iclamp-low-ma", &val);
1994 if (!rc) {
1995 led->pdata->led1n2_iclamp_low_ma = val;
1996 } else if (rc != -EINVAL) {
1997 pr_err("Unable to read led1n2_iclamp_low current, rc=%d\n", rc);
1998 return rc;
1999 }
2000
2001 rc = of_property_read_u32(node, "qcom,led1n2-iclamp-mid-ma", &val);
2002 if (!rc) {
2003 led->pdata->led1n2_iclamp_mid_ma = val;
2004 } else if (rc != -EINVAL) {
2005 pr_err("Unable to read led1n2_iclamp_mid current, rc=%d\n", rc);
2006 return rc;
2007 }
2008
2009 rc = of_property_read_u32(node, "qcom,led3-iclamp-low-ma", &val);
2010 if (!rc) {
2011 led->pdata->led3_iclamp_low_ma = val;
2012 } else if (rc != -EINVAL) {
2013 pr_err("Unable to read led3_iclamp_low current, rc=%d\n", rc);
2014 return rc;
2015 }
2016
2017 rc = of_property_read_u32(node, "qcom,led3-iclamp-mid-ma", &val);
2018 if (!rc) {
2019 led->pdata->led3_iclamp_mid_ma = val;
2020 } else if (rc != -EINVAL) {
2021 pr_err("Unable to read led3_iclamp_mid current, rc=%d\n", rc);
2022 return rc;
2023 }
2024
2025 led->pdata->vled_max_uv = FLASH_LED_VLED_MAX_DEFAULT_UV;
2026 rc = of_property_read_u32(node, "qcom,vled-max-uv", &val);
2027 if (!rc) {
2028 led->pdata->vled_max_uv = val;
2029 } else if (rc != -EINVAL) {
2030 pr_err("Unable to parse vled_max voltage, rc=%d\n", rc);
2031 return rc;
2032 }
2033
2034 led->pdata->ibatt_ocp_threshold_ua =
2035 FLASH_LED_IBATT_OCP_THRESH_DEFAULT_UA;
2036 rc = of_property_read_u32(node, "qcom,ibatt-ocp-threshold-ua", &val);
2037 if (!rc) {
2038 led->pdata->ibatt_ocp_threshold_ua = val;
2039 } else if (rc != -EINVAL) {
2040 pr_err("Unable to parse ibatt_ocp threshold, rc=%d\n", rc);
2041 return rc;
2042 }
2043
2044 led->pdata->rpara_uohm = FLASH_LED_RPARA_DEFAULT_UOHM;
2045 rc = of_property_read_u32(node, "qcom,rparasitic-uohm", &val);
2046 if (!rc) {
2047 led->pdata->rpara_uohm = val;
2048 } else if (rc != -EINVAL) {
2049 pr_err("Unable to parse rparasitic, rc=%d\n", rc);
2050 return rc;
2051 }
2052
2053 led->pdata->lmh_ocv_threshold_uv =
2054 FLASH_LED_LMH_OCV_THRESH_DEFAULT_UV;
2055 rc = of_property_read_u32(node, "qcom,lmh-ocv-threshold-uv", &val);
2056 if (!rc) {
2057 led->pdata->lmh_ocv_threshold_uv = val;
2058 } else if (rc != -EINVAL) {
2059 pr_err("Unable to parse lmh ocv threshold, rc=%d\n", rc);
2060 return rc;
2061 }
2062
2063 led->pdata->lmh_rbatt_threshold_uohm =
2064 FLASH_LED_LMH_RBATT_THRESH_DEFAULT_UOHM;
2065 rc = of_property_read_u32(node, "qcom,lmh-rbatt-threshold-uohm", &val);
2066 if (!rc) {
2067 led->pdata->lmh_rbatt_threshold_uohm = val;
2068 } else if (rc != -EINVAL) {
2069 pr_err("Unable to parse lmh rbatt threshold, rc=%d\n", rc);
2070 return rc;
2071 }
2072
2073 led->pdata->lmh_level = FLASH_LED_LMH_LEVEL_DEFAULT;
2074 rc = of_property_read_u32(node, "qcom,lmh-level", &val);
2075 if (!rc) {
2076 led->pdata->lmh_level = val;
2077 } else if (rc != -EINVAL) {
2078 pr_err("Unable to parse lmh_level, rc=%d\n", rc);
2079 return rc;
2080 }
2081
Ankit Sharmaa7153c32017-03-22 19:04:52 +05302082 led->pdata->lmh_mitigation_sel = FLASH_LED_LMH_MITIGATION_SEL_DEFAULT;
David Collins8885f792017-01-26 14:36:34 -08002083 rc = of_property_read_u32(node, "qcom,lmh-mitigation-sel", &val);
2084 if (!rc) {
2085 led->pdata->lmh_mitigation_sel = val;
2086 } else if (rc != -EINVAL) {
2087 pr_err("Unable to parse lmh_mitigation_sel, rc=%d\n", rc);
2088 return rc;
2089 }
2090
2091 if (led->pdata->lmh_mitigation_sel > FLASH_LED_MITIGATION_SEL_MAX) {
2092 pr_err("Invalid lmh_mitigation_sel specified\n");
2093 return -EINVAL;
2094 }
2095
Ankit Sharmaa7153c32017-03-22 19:04:52 +05302096 led->pdata->chgr_mitigation_sel = FLASH_SW_CHARGER_MITIGATION;
David Collins8885f792017-01-26 14:36:34 -08002097 rc = of_property_read_u32(node, "qcom,chgr-mitigation-sel", &val);
2098 if (!rc) {
2099 led->pdata->chgr_mitigation_sel = val;
2100 } else if (rc != -EINVAL) {
2101 pr_err("Unable to parse chgr_mitigation_sel, rc=%d\n", rc);
2102 return rc;
2103 }
2104
2105 if (led->pdata->chgr_mitigation_sel > FLASH_LED_MITIGATION_SEL_MAX) {
2106 pr_err("Invalid chgr_mitigation_sel specified\n");
2107 return -EINVAL;
2108 }
2109
Ankit Sharmaa7153c32017-03-22 19:04:52 +05302110 led->pdata->iled_thrsh_val = FLASH_LED_CHGR_MITIGATION_THRSH_DEFAULT;
David Collins8885f792017-01-26 14:36:34 -08002111 rc = of_property_read_u32(node, "qcom,iled-thrsh-ma", &val);
2112 if (!rc) {
2113 led->pdata->iled_thrsh_val = MITIGATION_THRSH_MA_TO_VAL(val);
2114 } else if (rc != -EINVAL) {
2115 pr_err("Unable to parse iled_thrsh_val, rc=%d\n", rc);
2116 return rc;
2117 }
2118
Ankit Sharmaa7153c32017-03-22 19:04:52 +05302119 if (led->pdata->iled_thrsh_val > FLASH_LED_CHGR_MITIGATION_THRSH_MAX) {
David Collins8885f792017-01-26 14:36:34 -08002120 pr_err("Invalid iled_thrsh_val specified\n");
2121 return -EINVAL;
2122 }
2123
2124 led->pdata->all_ramp_up_done_irq =
2125 of_irq_get_byname(node, "all-ramp-up-done-irq");
2126 if (led->pdata->all_ramp_up_done_irq < 0)
2127 pr_debug("all-ramp-up-done-irq not used\n");
2128
2129 led->pdata->all_ramp_down_done_irq =
2130 of_irq_get_byname(node, "all-ramp-down-done-irq");
2131 if (led->pdata->all_ramp_down_done_irq < 0)
2132 pr_debug("all-ramp-down-done-irq not used\n");
2133
2134 led->pdata->led_fault_irq =
2135 of_irq_get_byname(node, "led-fault-irq");
2136 if (led->pdata->led_fault_irq < 0)
2137 pr_debug("led-fault-irq not used\n");
2138
2139 return 0;
2140}
2141
2142static int qpnp_flash_led_probe(struct platform_device *pdev)
2143{
2144 struct qpnp_flash_led *led;
2145 struct device_node *node, *temp;
2146 const char *temp_string;
2147 unsigned int base;
2148 int rc, i = 0, j = 0;
2149
2150 node = pdev->dev.of_node;
2151 if (!node) {
2152 pr_err("No flash LED nodes defined\n");
2153 return -ENODEV;
2154 }
2155
2156 rc = of_property_read_u32(node, "reg", &base);
2157 if (rc < 0) {
2158 pr_err("Couldn't find reg in node %s, rc = %d\n",
2159 node->full_name, rc);
2160 return rc;
2161 }
2162
2163 led = devm_kzalloc(&pdev->dev, sizeof(struct qpnp_flash_led),
2164 GFP_KERNEL);
2165 if (!led)
2166 return -ENOMEM;
2167
2168 led->regmap = dev_get_regmap(pdev->dev.parent, NULL);
2169 if (!led->regmap) {
2170 pr_err("Couldn't get parent's regmap\n");
2171 return -EINVAL;
2172 }
2173
2174 led->base = base;
2175 led->pdev = pdev;
2176 led->pdata = devm_kzalloc(&pdev->dev,
2177 sizeof(struct flash_led_platform_data), GFP_KERNEL);
2178 if (!led->pdata)
2179 return -ENOMEM;
2180
2181 rc = qpnp_flash_led_parse_common_dt(led, node);
2182 if (rc < 0) {
2183 pr_err("Failed to parse common flash LED device tree\n");
2184 return rc;
2185 }
2186
2187 for_each_available_child_of_node(node, temp) {
2188 rc = of_property_read_string(temp, "label", &temp_string);
2189 if (rc < 0) {
2190 pr_err("Failed to parse label, rc=%d\n", rc);
2191 return rc;
2192 }
2193
2194 if (!strcmp("switch", temp_string)) {
2195 led->num_snodes++;
2196 } else if (!strcmp("flash", temp_string) ||
2197 !strcmp("torch", temp_string)) {
2198 led->num_fnodes++;
2199 } else {
2200 pr_err("Invalid label for led node\n");
2201 return -EINVAL;
2202 }
2203 }
2204
2205 if (!led->num_fnodes) {
2206 pr_err("No LED nodes defined\n");
2207 return -ECHILD;
2208 }
2209
2210 led->fnode = devm_kcalloc(&pdev->dev, led->num_fnodes,
2211 sizeof(*led->fnode),
2212 GFP_KERNEL);
2213 if (!led->fnode)
2214 return -ENOMEM;
2215
2216 led->snode = devm_kcalloc(&pdev->dev, led->num_snodes,
2217 sizeof(*led->snode),
2218 GFP_KERNEL);
2219 if (!led->snode)
2220 return -ENOMEM;
2221
2222 temp = NULL;
2223 i = 0;
2224 j = 0;
2225 for_each_available_child_of_node(node, temp) {
2226 rc = of_property_read_string(temp, "label", &temp_string);
2227 if (rc < 0) {
2228 pr_err("Failed to parse label, rc=%d\n", rc);
2229 return rc;
2230 }
2231
2232 if (!strcmp("flash", temp_string) ||
2233 !strcmp("torch", temp_string)) {
2234 rc = qpnp_flash_led_parse_each_led_dt(led,
Subbaraman Narayanamurthy01c99612017-04-03 12:26:06 -07002235 &led->fnode[i], temp);
David Collins8885f792017-01-26 14:36:34 -08002236 if (rc < 0) {
2237 pr_err("Unable to parse flash node %d rc=%d\n",
2238 i, rc);
2239 goto error_led_register;
2240 }
Subbaraman Narayanamurthy01c99612017-04-03 12:26:06 -07002241 i++;
David Collins8885f792017-01-26 14:36:34 -08002242 }
2243
2244 if (!strcmp("switch", temp_string)) {
2245 rc = qpnp_flash_led_parse_and_register_switch(led,
Subbaraman Narayanamurthy01c99612017-04-03 12:26:06 -07002246 &led->snode[j], temp);
David Collins8885f792017-01-26 14:36:34 -08002247 if (rc < 0) {
2248 pr_err("Unable to parse and register switch node, rc=%d\n",
2249 rc);
2250 goto error_switch_register;
2251 }
Subbaraman Narayanamurthy01c99612017-04-03 12:26:06 -07002252 j++;
David Collins8885f792017-01-26 14:36:34 -08002253 }
2254 }
2255
2256 /* setup irqs */
2257 if (led->pdata->all_ramp_up_done_irq >= 0) {
2258 rc = devm_request_threaded_irq(&led->pdev->dev,
2259 led->pdata->all_ramp_up_done_irq,
2260 NULL, qpnp_flash_led_irq_handler,
2261 IRQF_ONESHOT,
2262 "qpnp_flash_led_all_ramp_up_done_irq", led);
2263 if (rc < 0) {
2264 pr_err("Unable to request all_ramp_up_done(%d) IRQ(err:%d)\n",
2265 led->pdata->all_ramp_up_done_irq, rc);
2266 goto error_switch_register;
2267 }
2268 }
2269
2270 if (led->pdata->all_ramp_down_done_irq >= 0) {
2271 rc = devm_request_threaded_irq(&led->pdev->dev,
2272 led->pdata->all_ramp_down_done_irq,
2273 NULL, qpnp_flash_led_irq_handler,
2274 IRQF_ONESHOT,
2275 "qpnp_flash_led_all_ramp_down_done_irq", led);
2276 if (rc < 0) {
2277 pr_err("Unable to request all_ramp_down_done(%d) IRQ(err:%d)\n",
2278 led->pdata->all_ramp_down_done_irq, rc);
2279 goto error_switch_register;
2280 }
2281 }
2282
2283 if (led->pdata->led_fault_irq >= 0) {
2284 rc = devm_request_threaded_irq(&led->pdev->dev,
2285 led->pdata->led_fault_irq,
2286 NULL, qpnp_flash_led_irq_handler,
2287 IRQF_ONESHOT,
2288 "qpnp_flash_led_fault_irq", led);
2289 if (rc < 0) {
2290 pr_err("Unable to request led_fault(%d) IRQ(err:%d)\n",
2291 led->pdata->led_fault_irq, rc);
2292 goto error_switch_register;
2293 }
2294 }
2295
2296 led->bms_psy = power_supply_get_by_name("bms");
2297 if (!led->bms_psy) {
2298 rc = flash_led_psy_register_notifier(led);
2299 if (rc < 0) {
2300 pr_err("Couldn't register psy notifier, rc = %d\n", rc);
2301 goto error_switch_register;
2302 }
2303 }
2304
2305 rc = qpnp_flash_led_init_settings(led);
2306 if (rc < 0) {
2307 pr_err("Failed to initialize flash LED, rc=%d\n", rc);
2308 goto unreg_notifier;
2309 }
2310
2311 for (i = 0; i < led->num_snodes; i++) {
2312 for (j = 0; j < ARRAY_SIZE(qpnp_flash_led_attrs); j++) {
2313 rc = sysfs_create_file(&led->snode[i].cdev.dev->kobj,
2314 &qpnp_flash_led_attrs[j].attr);
2315 if (rc < 0) {
2316 pr_err("sysfs creation failed, rc=%d\n", rc);
2317 goto sysfs_fail;
2318 }
2319 }
2320 }
2321
2322 spin_lock_init(&led->lock);
2323
2324 dev_set_drvdata(&pdev->dev, led);
2325
2326 return 0;
2327
2328sysfs_fail:
2329 for (--j; j >= 0; j--)
2330 sysfs_remove_file(&led->snode[i].cdev.dev->kobj,
2331 &qpnp_flash_led_attrs[j].attr);
2332
2333 for (--i; i >= 0; i--) {
2334 for (j = 0; j < ARRAY_SIZE(qpnp_flash_led_attrs); j++)
2335 sysfs_remove_file(&led->snode[i].cdev.dev->kobj,
2336 &qpnp_flash_led_attrs[j].attr);
2337 }
2338
2339 i = led->num_snodes;
2340unreg_notifier:
2341 power_supply_unreg_notifier(&led->nb);
2342error_switch_register:
2343 while (i > 0)
2344 led_classdev_unregister(&led->snode[--i].cdev);
2345 i = led->num_fnodes;
2346error_led_register:
2347 while (i > 0)
2348 led_classdev_unregister(&led->fnode[--i].cdev);
2349
2350 return rc;
2351}
2352
2353static int qpnp_flash_led_remove(struct platform_device *pdev)
2354{
2355 struct qpnp_flash_led *led = dev_get_drvdata(&pdev->dev);
2356 int i, j;
2357
2358 for (i = 0; i < led->num_snodes; i++) {
2359 for (j = 0; j < ARRAY_SIZE(qpnp_flash_led_attrs); j++)
2360 sysfs_remove_file(&led->snode[i].cdev.dev->kobj,
2361 &qpnp_flash_led_attrs[j].attr);
2362
2363 if (led->snode[i].regulator_on)
2364 qpnp_flash_led_regulator_enable(led,
2365 &led->snode[i], false);
2366 }
2367
2368 while (i > 0)
2369 led_classdev_unregister(&led->snode[--i].cdev);
2370
2371 i = led->num_fnodes;
2372 while (i > 0)
2373 led_classdev_unregister(&led->fnode[--i].cdev);
2374
2375 power_supply_unreg_notifier(&led->nb);
2376 return 0;
2377}
2378
2379const struct of_device_id qpnp_flash_led_match_table[] = {
2380 { .compatible = "qcom,qpnp-flash-led-v2",},
2381 { },
2382};
2383
2384static struct platform_driver qpnp_flash_led_driver = {
2385 .driver = {
2386 .name = "qcom,qpnp-flash-led-v2",
2387 .of_match_table = qpnp_flash_led_match_table,
2388 },
2389 .probe = qpnp_flash_led_probe,
2390 .remove = qpnp_flash_led_remove,
2391};
2392
2393static int __init qpnp_flash_led_init(void)
2394{
2395 return platform_driver_register(&qpnp_flash_led_driver);
2396}
2397late_initcall(qpnp_flash_led_init);
2398
2399static void __exit qpnp_flash_led_exit(void)
2400{
2401 platform_driver_unregister(&qpnp_flash_led_driver);
2402}
2403module_exit(qpnp_flash_led_exit);
2404
2405MODULE_DESCRIPTION("QPNP Flash LED driver v2");
2406MODULE_LICENSE("GPL v2");
2407MODULE_ALIAS("leds:leds-qpnp-flash-v2");