blob: 12fdd0603cbf4628847ac9b4822f3df5b8fb4899 [file] [log] [blame]
David Collins8885f792017-01-26 14:36:34 -08001/*
Kiran Gundac390a892019-01-23 13:12:06 +05302 * Copyright (c) 2016-2019, The Linux Foundation. All rights reserved.
David Collins8885f792017-01-26 14:36:34 -08003 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 and
6 * only version 2 as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 */
13
14#define pr_fmt(fmt) "LCDB: %s: " fmt, __func__
jialongjhan7dfbf872020-04-21 20:24:23 +080015//[Arima][8901][Jialongjhan]Add delay time between VSN and VSP 20191104 Start
16#define LCDB_PWRUP_PWRDN_CTL_REG 0x66
17//[Arima][8901][Jialongjhan]Add delay time between VSN and VSP 20191104 End
David Collins8885f792017-01-26 14:36:34 -080018
19#include <linux/delay.h>
20#include <linux/device.h>
21#include <linux/interrupt.h>
Anirudh Ghayal264f9272017-03-05 22:34:37 +053022#include <linux/ktime.h>
David Collins8885f792017-01-26 14:36:34 -080023#include <linux/module.h>
24#include <linux/of_irq.h>
25#include <linux/platform_device.h>
26#include <linux/regmap.h>
27#include <linux/regulator/driver.h>
28#include <linux/regulator/of_regulator.h>
29#include <linux/regulator/machine.h>
Anirudh Ghayal968862c2017-03-31 15:34:05 +053030#include <linux/qpnp/qpnp-revid.h>
David Collins8885f792017-01-26 14:36:34 -080031
32#define QPNP_LCDB_REGULATOR_DRIVER_NAME "qcom,qpnp-lcdb-regulator"
33
34/* LCDB */
35#define LCDB_STS1_REG 0x08
36
37#define INT_RT_STATUS_REG 0x10
38#define VREG_OK_RT_STS_BIT BIT(0)
Anirudh Ghayal264f9272017-03-05 22:34:37 +053039#define SC_ERROR_RT_STS_BIT BIT(1)
40
41#define LCDB_STS3_REG 0x0A
42#define LDO_VREG_OK_BIT BIT(7)
43
44#define LCDB_STS4_REG 0x0B
45#define NCP_VREG_OK_BIT BIT(7)
David Collins8885f792017-01-26 14:36:34 -080046
47#define LCDB_AUTO_TOUCH_WAKE_CTL_REG 0x40
48#define EN_AUTO_TOUCH_WAKE_BIT BIT(7)
49#define ATTW_TOFF_TIME_MASK GENMASK(3, 2)
50#define ATTW_TON_TIME_MASK GENMASK(1, 0)
51#define ATTW_TOFF_TIME_SHIFT 2
52#define ATTW_MIN_MS 4
53#define ATTW_MAX_MS 32
54
55#define LCDB_BST_OUTPUT_VOLTAGE_REG 0x41
Kiran Gunda414471a2017-12-07 12:50:51 +053056#define PM660_BST_OUTPUT_VOLTAGE_MASK GENMASK(4, 0)
57#define BST_OUTPUT_VOLTAGE_MASK GENMASK(5, 0)
David Collins8885f792017-01-26 14:36:34 -080058
59#define LCDB_MODULE_RDY_REG 0x45
60#define MODULE_RDY_BIT BIT(7)
61
62#define LCDB_ENABLE_CTL1_REG 0x46
63#define MODULE_EN_BIT BIT(7)
64#define HWEN_RDY_BIT BIT(6)
65
66/* BST */
67#define LCDB_BST_PD_CTL_REG 0x47
68#define BOOST_DIS_PULLDOWN_BIT BIT(1)
69#define BOOST_PD_STRENGTH_BIT BIT(0)
70
71#define LCDB_BST_ILIM_CTL_REG 0x4B
72#define EN_BST_ILIM_BIT BIT(7)
73#define SET_BST_ILIM_MASK GENMASK(2, 0)
74#define MIN_BST_ILIM_MA 200
75#define MAX_BST_ILIM_MA 1600
76
77#define LCDB_PS_CTL_REG 0x50
78#define EN_PS_BIT BIT(7)
Kiran Gunda414471a2017-12-07 12:50:51 +053079#define PM660_PS_THRESH_MASK GENMASK(1, 0)
80#define PS_THRESH_MASK GENMASK(2, 0)
David Collins8885f792017-01-26 14:36:34 -080081#define MIN_BST_PS_MA 50
82#define MAX_BST_PS_MA 80
83
84#define LCDB_RDSON_MGMNT_REG 0x53
85#define NFET_SW_SIZE_MASK GENMASK(3, 2)
86#define NFET_SW_SIZE_SHIFT 2
87#define PFET_SW_SIZE_MASK GENMASK(1, 0)
88
89#define LCDB_BST_VREG_OK_CTL_REG 0x55
90#define BST_VREG_OK_DEB_MASK GENMASK(1, 0)
91
Kiran Gunda414471a2017-12-07 12:50:51 +053092#define LCDB_BST_SS_CTL_REG 0x5B
93#define BST_SS_TIME_MASK GENMASK(1, 0)
94#define BST_PRECHG_SHORT_ALARM_SHIFT 2
95#define BST_PRECHARGE_DONE_DEB_BIT BIT(4)
96#define BST_SS_TIME_OVERRIDE_SHIFT 5
97
98#define BST_SS_TIME_OVERRIDE_0MS 0
99#define BST_SS_TIME_OVERRIDE_0P5_MS 1
100#define BST_SS_TIME_OVERRIDE_1MS 2
101#define BST_SS_TIME_OVERRIDE_2MS 3
102
103#define EN_BST_PRECHG_SHORT_ALARM 0
104#define DIS_BST_PRECHG_SHORT_ALARM 1
105
David Collins8885f792017-01-26 14:36:34 -0800106#define LCDB_SOFT_START_CTL_REG 0x5F
107
108#define LCDB_MISC_CTL_REG 0x60
109#define AUTO_GM_EN_BIT BIT(4)
110#define EN_TOUCH_WAKE_BIT BIT(3)
111#define DIS_SCP_BIT BIT(0)
112
113#define LCDB_PFM_CTL_REG 0x62
114#define EN_PFM_BIT BIT(7)
115#define BYP_BST_SOFT_START_COMP_BIT BIT(0)
116#define PFM_HYSTERESIS_SHIFT 4
117#define PFM_CURRENT_SHIFT 2
118
119#define LCDB_PWRUP_PWRDN_CTL_REG 0x66
Kiran Gundac390a892019-01-23 13:12:06 +0530120#define PWRUP_DELAY_MASK GENAMSK(3, 2)
121#define PWRDN_DELAY_MASK GENMASK(1, 0)
122#define PWRDN_DELAY_MIN_MS 0
123#define PWRDN_DELAY_MAX_MS 8
David Collins8885f792017-01-26 14:36:34 -0800124
125/* LDO */
126#define LCDB_LDO_OUTPUT_VOLTAGE_REG 0x71
127#define SET_OUTPUT_VOLTAGE_MASK GENMASK(4, 0)
128
129#define LCDB_LDO_VREG_OK_CTL_REG 0x75
130#define VREG_OK_DEB_MASK GENMASK(1, 0)
131
132#define LCDB_LDO_PD_CTL_REG 0x77
133#define LDO_DIS_PULLDOWN_BIT BIT(1)
134#define LDO_PD_STRENGTH_BIT BIT(0)
135
Kiran Gundac390a892019-01-23 13:12:06 +0530136#define LCDB_LDO_FORCE_PD_CTL_REG 0x79
137#define LDO_FORCE_PD_EN_BIT BIT(0)
138#define LDO_FORCE_PD_MODE BIT(7)
139
David Collins8885f792017-01-26 14:36:34 -0800140#define LCDB_LDO_ILIM_CTL1_REG 0x7B
141#define EN_LDO_ILIM_BIT BIT(7)
142#define SET_LDO_ILIM_MASK GENMASK(2, 0)
143#define MIN_LDO_ILIM_MA 110
144#define MAX_LDO_ILIM_MA 460
145#define LDO_ILIM_STEP_MA 50
146
147#define LCDB_LDO_ILIM_CTL2_REG 0x7C
148
149#define LCDB_LDO_SOFT_START_CTL_REG 0x7F
150#define SOFT_START_MASK GENMASK(1, 0)
151
152/* NCP */
153#define LCDB_NCP_OUTPUT_VOLTAGE_REG 0x81
154
155#define LCDB_NCP_VREG_OK_CTL_REG 0x85
156
157#define LCDB_NCP_PD_CTL_REG 0x87
158#define NCP_DIS_PULLDOWN_BIT BIT(1)
159#define NCP_PD_STRENGTH_BIT BIT(0)
160
161#define LCDB_NCP_ILIM_CTL1_REG 0x8B
162#define EN_NCP_ILIM_BIT BIT(7)
163#define SET_NCP_ILIM_MASK GENMASK(1, 0)
164#define MIN_NCP_ILIM_MA 260
165#define MAX_NCP_ILIM_MA 810
166
167#define LCDB_NCP_ILIM_CTL2_REG 0x8C
168
169#define LCDB_NCP_SOFT_START_CTL_REG 0x8F
170
171/* common for BST/NCP/LDO */
172#define MIN_DBC_US 2
173#define MAX_DBC_US 32
174
175#define MIN_SOFT_START_US 0
176#define MAX_SOFT_START_US 2000
177
Kiran Gunda414471a2017-12-07 12:50:51 +0530178#define PM660_BST_HEADROOM_DEFAULT_MV 200
179#define BST_HEADROOM_DEFAULT_MV 150
Kiran Gundabcfca132017-08-08 16:58:47 +0530180
Kiran Gundadf7fa662018-06-11 12:41:51 +0530181#define PMIC5_LCDB_OFF_ON_DELAY_US 20000
182
David Collins8885f792017-01-26 14:36:34 -0800183struct ldo_regulator {
184 struct regulator_desc rdesc;
185 struct regulator_dev *rdev;
186 struct device_node *node;
187
188 /* LDO DT params */
189 int pd;
190 int pd_strength;
191 int ilim_ma;
192 int soft_start_us;
193 int vreg_ok_dbc_us;
194 int voltage_mv;
Kiran Gunda08368b32018-09-10 18:04:43 +0530195 int prev_voltage_mv;
David Collins8885f792017-01-26 14:36:34 -0800196};
197
198struct ncp_regulator {
199 struct regulator_desc rdesc;
200 struct regulator_dev *rdev;
201 struct device_node *node;
202
203 /* NCP DT params */
204 int pd;
205 int pd_strength;
206 int ilim_ma;
207 int soft_start_us;
208 int vreg_ok_dbc_us;
209 int voltage_mv;
Kiran Gunda08368b32018-09-10 18:04:43 +0530210 int prev_voltage_mv;
David Collins8885f792017-01-26 14:36:34 -0800211};
212
213struct bst_params {
214 struct device_node *node;
215
216 /* BST DT params */
217 int pd;
218 int pd_strength;
219 int ilim_ma;
220 int ps;
221 int ps_threshold;
222 int soft_start_us;
223 int vreg_ok_dbc_us;
224 int voltage_mv;
Kiran Gundabcfca132017-08-08 16:58:47 +0530225 u16 headroom_mv;
David Collins8885f792017-01-26 14:36:34 -0800226};
227
228struct qpnp_lcdb {
229 struct device *dev;
230 struct platform_device *pdev;
231 struct regmap *regmap;
Kavya Nunna80bc1502018-10-01 14:50:23 +0530232 struct class lcdb_class;
Anirudh Ghayal968862c2017-03-31 15:34:05 +0530233 struct pmic_revid_data *pmic_rev_id;
David Collins8885f792017-01-26 14:36:34 -0800234 u32 base;
Kiran Gundaa7228922018-06-27 11:14:21 +0530235 u32 wa_flags;
Anirudh Ghayal264f9272017-03-05 22:34:37 +0530236 int sc_irq;
Kiran Gundac390a892019-01-23 13:12:06 +0530237 int pwrdn_delay_ms;
David Collins8885f792017-01-26 14:36:34 -0800238
239 /* TTW params */
240 bool ttw_enable;
241 bool ttw_mode_sw;
242
243 /* status parameters */
244 bool lcdb_enabled;
245 bool settings_saved;
Anirudh Ghayal264f9272017-03-05 22:34:37 +0530246 bool lcdb_sc_disable;
Kavya Nunna80bc1502018-10-01 14:50:23 +0530247 bool secure_mode;
Kiran Gunda08368b32018-09-10 18:04:43 +0530248 bool voltage_step_ramp;
Anirudh Ghayal264f9272017-03-05 22:34:37 +0530249 int sc_count;
250 ktime_t sc_module_enable_time;
David Collins8885f792017-01-26 14:36:34 -0800251
252 struct mutex lcdb_mutex;
253 struct mutex read_write_mutex;
254 struct bst_params bst;
255 struct ldo_regulator ldo;
256 struct ncp_regulator ncp;
257};
258
259struct settings {
260 u16 address;
261 u8 value;
262 bool sec_access;
Kiran Gunda414471a2017-12-07 12:50:51 +0530263 bool valid;
David Collins8885f792017-01-26 14:36:34 -0800264};
265
266enum lcdb_module {
267 LDO,
268 NCP,
269 BST,
Kiran Gunda08368b32018-09-10 18:04:43 +0530270 LDO_NCP,
David Collins8885f792017-01-26 14:36:34 -0800271};
272
273enum pfm_hysteresis {
274 PFM_HYST_15MV,
275 PFM_HYST_25MV,
276 PFM_HYST_35MV,
277 PFM_HYST_45MV,
278};
279
280enum pfm_peak_current {
281 PFM_PEAK_CURRENT_300MA,
282 PFM_PEAK_CURRENT_400MA,
283 PFM_PEAK_CURRENT_500MA,
284 PFM_PEAK_CURRENT_600MA,
285};
286
287enum rdson_fet_size {
288 RDSON_QUARTER,
289 RDSON_HALF,
290 RDSON_THREE_FOURTH,
291 RDSON_FULLSIZE,
292};
293
294enum lcdb_settings_index {
295 LCDB_BST_PD_CTL = 0,
296 LCDB_RDSON_MGMNT,
297 LCDB_MISC_CTL,
298 LCDB_SOFT_START_CTL,
299 LCDB_PFM_CTL,
300 LCDB_PWRUP_PWRDN_CTL,
301 LCDB_LDO_PD_CTL,
302 LCDB_LDO_SOFT_START_CTL,
303 LCDB_NCP_PD_CTL,
304 LCDB_NCP_SOFT_START_CTL,
Kiran Gunda414471a2017-12-07 12:50:51 +0530305 LCDB_BST_SS_CTL,
306 LCDB_LDO_VREG_OK_CTL,
David Collins8885f792017-01-26 14:36:34 -0800307 LCDB_SETTING_MAX,
308};
309
Kiran Gundaa7228922018-06-27 11:14:21 +0530310enum lcdb_wa_flags {
311 NCP_SCP_DISABLE_WA = BIT(0),
Kiran Gundac390a892019-01-23 13:12:06 +0530312 FORCE_PD_ENABLE_WA = BIT(1),
Kiran Gundaa7228922018-06-27 11:14:21 +0530313};
314
David Collins8885f792017-01-26 14:36:34 -0800315static u32 soft_start_us[] = {
316 0,
317 500,
318 1000,
319 2000,
320};
321
322static u32 dbc_us[] = {
323 2,
324 4,
325 16,
326 32,
327};
328
329static u32 ncp_ilim_ma[] = {
330 260,
331 460,
332 640,
333 810,
334};
335
Kiran Gundac390a892019-01-23 13:12:06 +0530336static const u32 pwrup_pwrdn_ms[] = {
337 0,
338 1,
339 4,
340 8,
341};
342
Kiran Gunda414471a2017-12-07 12:50:51 +0530343#define SETTING(_id, _sec_access, _valid) \
David Collins8885f792017-01-26 14:36:34 -0800344 [_id] = { \
345 .address = _id##_REG, \
346 .sec_access = _sec_access, \
Kiran Gunda414471a2017-12-07 12:50:51 +0530347 .valid = _valid \
David Collins8885f792017-01-26 14:36:34 -0800348 } \
349
Kiran Gunda08368b32018-09-10 18:04:43 +0530350static int qpnp_lcdb_set_voltage_step(struct qpnp_lcdb *lcdb,
351 int voltage_start_mv, u8 type);
352
353static int qpnp_lcdb_set_voltage(struct qpnp_lcdb *lcdb,
354 int voltage_mv, u8 type);
355
David Collins8885f792017-01-26 14:36:34 -0800356static bool is_between(int value, int min, int max)
357{
358 if (value < min || value > max)
359 return false;
360 return true;
361}
362
363static int qpnp_lcdb_read(struct qpnp_lcdb *lcdb,
364 u16 addr, u8 *value, u8 count)
365{
366 int rc = 0;
367
368 mutex_lock(&lcdb->read_write_mutex);
369 rc = regmap_bulk_read(lcdb->regmap, addr, value, count);
370 if (rc < 0)
371 pr_err("Failed to read from addr=0x%02x rc=%d\n", addr, rc);
372 mutex_unlock(&lcdb->read_write_mutex);
373
374 return rc;
375}
376
377static int qpnp_lcdb_write(struct qpnp_lcdb *lcdb,
378 u16 addr, u8 *value, u8 count)
379{
380 int rc;
381
382 mutex_lock(&lcdb->read_write_mutex);
383 rc = regmap_bulk_write(lcdb->regmap, addr, value, count);
384 if (rc < 0)
385 pr_err("Failed to write to addr=0x%02x rc=%d\n", addr, rc);
386 mutex_unlock(&lcdb->read_write_mutex);
387
388 return rc;
389}
390
391#define SEC_ADDRESS_REG 0xD0
392#define SECURE_UNLOCK_VALUE 0xA5
393static int qpnp_lcdb_secure_write(struct qpnp_lcdb *lcdb,
394 u16 addr, u8 value)
395{
396 int rc;
397 u8 val = SECURE_UNLOCK_VALUE;
Kiran Gunda414471a2017-12-07 12:50:51 +0530398 u8 pmic_subtype = lcdb->pmic_rev_id->pmic_subtype;
David Collins8885f792017-01-26 14:36:34 -0800399
400 mutex_lock(&lcdb->read_write_mutex);
Kiran Gunda414471a2017-12-07 12:50:51 +0530401 if (pmic_subtype == PM660L_SUBTYPE) {
402 rc = regmap_write(lcdb->regmap, lcdb->base + SEC_ADDRESS_REG,
403 val);
404 if (rc < 0) {
405 pr_err("Failed to unlock register rc=%d\n", rc);
406 goto fail_write;
407 }
David Collins8885f792017-01-26 14:36:34 -0800408 }
409 rc = regmap_write(lcdb->regmap, addr, value);
410 if (rc < 0)
411 pr_err("Failed to write to addr=0x%02x rc=%d\n", addr, rc);
412
413fail_write:
414 mutex_unlock(&lcdb->read_write_mutex);
415 return rc;
416}
417
418static int qpnp_lcdb_masked_write(struct qpnp_lcdb *lcdb,
419 u16 addr, u8 mask, u8 value)
420{
421 int rc = 0;
422
423 mutex_lock(&lcdb->read_write_mutex);
424 rc = regmap_update_bits(lcdb->regmap, addr, mask, value);
425 if (rc < 0)
426 pr_err("Failed to write addr=0x%02x value=0x%02x rc=%d\n",
427 addr, value, rc);
428 mutex_unlock(&lcdb->read_write_mutex);
429
430 return rc;
431}
432
433static bool is_lcdb_enabled(struct qpnp_lcdb *lcdb)
434{
435 int rc;
436 u8 val = 0;
437
438 rc = qpnp_lcdb_read(lcdb, lcdb->base + LCDB_ENABLE_CTL1_REG, &val, 1);
439 if (rc < 0)
440 pr_err("Failed to read ENABLE_CTL1 rc=%d\n", rc);
441
442 return rc ? false : !!(val & MODULE_EN_BIT);
443}
444
445static int dump_status_registers(struct qpnp_lcdb *lcdb)
446{
447 int rc = 0;
448 u8 sts[6] = {0};
449
450 rc = qpnp_lcdb_write(lcdb, lcdb->base + LCDB_STS1_REG, &sts[0], 6);
451 if (rc < 0) {
452 pr_err("Failed to write to STS registers rc=%d\n", rc);
453 } else {
454 rc = qpnp_lcdb_read(lcdb, lcdb->base + LCDB_STS1_REG, sts, 6);
455 if (rc < 0)
456 pr_err("Failed to read lcdb status rc=%d\n", rc);
457 else
458 pr_err("STS1=0x%02x STS2=0x%02x STS3=0x%02x STS4=0x%02x STS5=0x%02x, STS6=0x%02x\n",
459 sts[0], sts[1], sts[2], sts[3], sts[4], sts[5]);
460 }
461
462 return rc;
463}
464
Kiran Gunda414471a2017-12-07 12:50:51 +0530465static struct settings lcdb_settings_pm660l[] = {
466 SETTING(LCDB_BST_PD_CTL, false, true),
467 SETTING(LCDB_RDSON_MGMNT, false, true),
468 SETTING(LCDB_MISC_CTL, false, true),
469 SETTING(LCDB_SOFT_START_CTL, false, true),
470 SETTING(LCDB_PFM_CTL, false, true),
471 SETTING(LCDB_PWRUP_PWRDN_CTL, true, true),
472 SETTING(LCDB_LDO_PD_CTL, false, true),
473 SETTING(LCDB_LDO_SOFT_START_CTL, false, true),
474 SETTING(LCDB_NCP_PD_CTL, false, true),
475 SETTING(LCDB_NCP_SOFT_START_CTL, false, true),
476 SETTING(LCDB_BST_SS_CTL, false, false),
477 SETTING(LCDB_LDO_VREG_OK_CTL, false, false),
478};
479
480/* For PMICs like pmi632/pm855L */
David Collins8885f792017-01-26 14:36:34 -0800481static struct settings lcdb_settings[] = {
Kiran Gunda414471a2017-12-07 12:50:51 +0530482 SETTING(LCDB_BST_PD_CTL, false, true),
483 SETTING(LCDB_RDSON_MGMNT, false, false),
484 SETTING(LCDB_MISC_CTL, false, false),
485 SETTING(LCDB_SOFT_START_CTL, false, false),
486 SETTING(LCDB_PFM_CTL, false, false),
487 SETTING(LCDB_PWRUP_PWRDN_CTL, false, true),
488 SETTING(LCDB_LDO_PD_CTL, false, true),
489 SETTING(LCDB_LDO_SOFT_START_CTL, false, true),
490 SETTING(LCDB_NCP_PD_CTL, false, true),
491 SETTING(LCDB_NCP_SOFT_START_CTL, false, true),
492 SETTING(LCDB_BST_SS_CTL, false, true),
493 SETTING(LCDB_LDO_VREG_OK_CTL, false, true),
David Collins8885f792017-01-26 14:36:34 -0800494};
495
496static int qpnp_lcdb_save_settings(struct qpnp_lcdb *lcdb)
497{
Kiran Gunda414471a2017-12-07 12:50:51 +0530498 int i, size, rc = 0;
499 struct settings *setting;
500 u16 pmic_subtype = lcdb->pmic_rev_id->pmic_subtype;
David Collins8885f792017-01-26 14:36:34 -0800501
Kiran Gunda414471a2017-12-07 12:50:51 +0530502 if (pmic_subtype == PM660L_SUBTYPE) {
503 setting = lcdb_settings_pm660l;
504 size = ARRAY_SIZE(lcdb_settings_pm660l);
505 } else {
506 setting = lcdb_settings;
507 size = ARRAY_SIZE(lcdb_settings);
508 }
509
510 for (i = 0; i < size; i++) {
511 if (setting[i].valid) {
512 rc = qpnp_lcdb_read(lcdb, lcdb->base +
513 setting[i].address,
514 &setting[i].value, 1);
515 if (rc < 0) {
516 pr_err("Failed to read lcdb register address=%x\n",
517 setting[i].address);
518 return rc;
519 }
David Collins8885f792017-01-26 14:36:34 -0800520 }
521 }
522
Kiran Gunda414471a2017-12-07 12:50:51 +0530523 return 0;
David Collins8885f792017-01-26 14:36:34 -0800524}
525
526static int qpnp_lcdb_restore_settings(struct qpnp_lcdb *lcdb)
527{
Kiran Gunda414471a2017-12-07 12:50:51 +0530528 int i, size, rc = 0;
529 struct settings *setting;
530 u16 pmic_subtype = lcdb->pmic_rev_id->pmic_subtype;
David Collins8885f792017-01-26 14:36:34 -0800531
Kiran Gunda414471a2017-12-07 12:50:51 +0530532 if (pmic_subtype == PM660L_SUBTYPE) {
533 setting = lcdb_settings_pm660l;
534 size = ARRAY_SIZE(lcdb_settings_pm660l);
535 } else {
536 setting = lcdb_settings;
537 size = ARRAY_SIZE(lcdb_settings);
538 }
539
540 for (i = 0; i < size; i++) {
541 if (setting[i].valid) {
542 if (setting[i].sec_access)
543 rc = qpnp_lcdb_secure_write(lcdb, lcdb->base +
544 setting[i].address,
545 setting[i].value);
546 else
547 rc = qpnp_lcdb_write(lcdb, lcdb->base +
548 setting[i].address,
549 &setting[i].value, 1);
550 if (rc < 0) {
551 pr_err("Failed to write register address=%x\n",
552 setting[i].address);
553 return rc;
554 }
David Collins8885f792017-01-26 14:36:34 -0800555 }
556 }
557
Kiran Gunda414471a2017-12-07 12:50:51 +0530558 return 0;
559}
560
561static int qpnp_lcdb_ttw_enter(struct qpnp_lcdb *lcdb)
562{
563 int rc;
564 u8 val;
565
566 if (!lcdb->settings_saved) {
567 rc = qpnp_lcdb_save_settings(lcdb);
568 if (rc < 0) {
569 pr_err("Failed to save LCDB settings rc=%d\n", rc);
570 return rc;
571 }
572 lcdb->settings_saved = true;
573 }
574
575 val = HWEN_RDY_BIT;
576 rc = qpnp_lcdb_write(lcdb, lcdb->base + LCDB_ENABLE_CTL1_REG,
577 &val, 1);
578 if (rc < 0) {
579 pr_err("Failed to hw_enable lcdb rc= %d\n", rc);
580 return rc;
581 }
582
583 val = (BST_SS_TIME_OVERRIDE_1MS << BST_SS_TIME_OVERRIDE_SHIFT) |
584 (DIS_BST_PRECHG_SHORT_ALARM << BST_PRECHG_SHORT_ALARM_SHIFT);
585 rc = qpnp_lcdb_write(lcdb, lcdb->base + LCDB_BST_SS_CTL_REG, &val, 1);
586 if (rc < 0)
587 return rc;
588
589 val = 0;
590 rc = qpnp_lcdb_write(lcdb, lcdb->base + LCDB_LDO_SOFT_START_CTL_REG,
591 &val, 1);
592 if (rc < 0)
593 return rc;
594
595 val = 0;
596 rc = qpnp_lcdb_write(lcdb, lcdb->base + LCDB_NCP_SOFT_START_CTL_REG,
597 &val, 1);
598 if (rc < 0)
599 return rc;
600
601 val = BOOST_DIS_PULLDOWN_BIT | BOOST_PD_STRENGTH_BIT;
602 rc = qpnp_lcdb_write(lcdb, lcdb->base + LCDB_BST_PD_CTL_REG,
603 &val, 1);
604 if (rc < 0)
605 return rc;
606
607 val = LDO_DIS_PULLDOWN_BIT | LDO_PD_STRENGTH_BIT;
608 rc = qpnp_lcdb_write(lcdb, lcdb->base + LCDB_LDO_PD_CTL_REG,
609 &val, 1);
610 if (rc < 0)
611 return rc;
612
613 val = NCP_DIS_PULLDOWN_BIT | NCP_PD_STRENGTH_BIT;
614 rc = qpnp_lcdb_write(lcdb, lcdb->base + LCDB_NCP_PD_CTL_REG,
615 &val, 1);
616 if (rc < 0)
617 return rc;
618
619 val = 0;
620 rc = qpnp_lcdb_write(lcdb, lcdb->base + LCDB_PWRUP_PWRDN_CTL_REG,
621 &val, 1);
622 if (rc < 0)
623 return rc;
624
625 val = 0;
626 rc = qpnp_lcdb_write(lcdb, lcdb->base + LCDB_BST_VREG_OK_CTL_REG,
627 &val, 1);
628
David Collins8885f792017-01-26 14:36:34 -0800629 return rc;
630}
631
Kiran Gunda414471a2017-12-07 12:50:51 +0530632static int qpnp_lcdb_ttw_enter_pm660l(struct qpnp_lcdb *lcdb)
David Collins8885f792017-01-26 14:36:34 -0800633{
634 int rc;
635 u8 val;
636
637 if (!lcdb->settings_saved) {
638 rc = qpnp_lcdb_save_settings(lcdb);
639 if (rc < 0) {
640 pr_err("Failed to save LCDB settings rc=%d\n", rc);
641 return rc;
642 }
643 lcdb->settings_saved = true;
644 }
645
646 val = BOOST_DIS_PULLDOWN_BIT;
647 rc = qpnp_lcdb_write(lcdb, lcdb->base + LCDB_BST_PD_CTL_REG,
648 &val, 1);
649 if (rc < 0) {
650 pr_err("Failed to set BST PD rc=%d\n", rc);
651 return rc;
652 }
653
654 val = (RDSON_HALF << NFET_SW_SIZE_SHIFT) | RDSON_HALF;
655 rc = qpnp_lcdb_write(lcdb, lcdb->base + LCDB_RDSON_MGMNT_REG,
656 &val, 1);
657 if (rc < 0) {
658 pr_err("Failed to set RDSON MGMT rc=%d\n", rc);
659 return rc;
660 }
661
662 val = AUTO_GM_EN_BIT | EN_TOUCH_WAKE_BIT | DIS_SCP_BIT;
663 rc = qpnp_lcdb_write(lcdb, lcdb->base + LCDB_MISC_CTL_REG,
664 &val, 1);
665 if (rc < 0) {
666 pr_err("Failed to set MISC CTL rc=%d\n", rc);
667 return rc;
668 }
669
670 val = 0;
671 rc = qpnp_lcdb_write(lcdb, lcdb->base + LCDB_SOFT_START_CTL_REG,
Kiran Gunda414471a2017-12-07 12:50:51 +0530672 &val, 1);
David Collins8885f792017-01-26 14:36:34 -0800673 if (rc < 0) {
674 pr_err("Failed to set LCDB_SOFT_START rc=%d\n", rc);
675 return rc;
676 }
677
678 val = EN_PFM_BIT | (PFM_HYST_25MV << PFM_HYSTERESIS_SHIFT) |
679 (PFM_PEAK_CURRENT_400MA << PFM_CURRENT_SHIFT) |
680 BYP_BST_SOFT_START_COMP_BIT;
681 rc = qpnp_lcdb_write(lcdb, lcdb->base + LCDB_PFM_CTL_REG,
682 &val, 1);
683 if (rc < 0) {
684 pr_err("Failed to set PFM_CTL rc=%d\n", rc);
685 return rc;
686 }
687
688 val = 0;
689 rc = qpnp_lcdb_secure_write(lcdb, lcdb->base + LCDB_PWRUP_PWRDN_CTL_REG,
690 val);
691 if (rc < 0) {
692 pr_err("Failed to set PWRUP_PWRDN_CTL rc=%d\n", rc);
693 return rc;
694 }
695
696 val = LDO_DIS_PULLDOWN_BIT;
697 rc = qpnp_lcdb_write(lcdb, lcdb->base + LCDB_LDO_PD_CTL_REG,
698 &val, 1);
699 if (rc < 0) {
700 pr_err("Failed to set LDO_PD_CTL rc=%d\n", rc);
701 return rc;
702 }
703
704 val = 0;
705 rc = qpnp_lcdb_write(lcdb, lcdb->base + LCDB_LDO_SOFT_START_CTL_REG,
706 &val, 1);
707 if (rc < 0) {
708 pr_err("Failed to set LDO_SOFT_START rc=%d\n", rc);
709 return rc;
710 }
711
712 val = NCP_DIS_PULLDOWN_BIT;
713 rc = qpnp_lcdb_write(lcdb, lcdb->base + LCDB_NCP_PD_CTL_REG,
714 &val, 1);
715 if (rc < 0) {
716 pr_err("Failed to set NCP_PD_CTL rc=%d\n", rc);
717 return rc;
718 }
719
720 val = 0;
721 rc = qpnp_lcdb_write(lcdb, lcdb->base + LCDB_NCP_SOFT_START_CTL_REG,
722 &val, 1);
723 if (rc < 0) {
724 pr_err("Failed to set NCP_SOFT_START rc=%d\n", rc);
725 return rc;
726 }
727
728 if (lcdb->ttw_mode_sw) {
729 rc = qpnp_lcdb_masked_write(lcdb, lcdb->base +
730 LCDB_AUTO_TOUCH_WAKE_CTL_REG,
731 EN_AUTO_TOUCH_WAKE_BIT,
732 EN_AUTO_TOUCH_WAKE_BIT);
733 if (rc < 0)
734 pr_err("Failed to enable auto(sw) TTW\n rc = %d\n", rc);
735 } else {
736 val = HWEN_RDY_BIT;
737 rc = qpnp_lcdb_write(lcdb, lcdb->base + LCDB_ENABLE_CTL1_REG,
738 &val, 1);
739 if (rc < 0)
740 pr_err("Failed to hw_enable lcdb rc= %d\n", rc);
741 }
742
743 return rc;
744}
745
746static int qpnp_lcdb_ttw_exit(struct qpnp_lcdb *lcdb)
747{
748 int rc;
749
750 if (lcdb->settings_saved) {
751 rc = qpnp_lcdb_restore_settings(lcdb);
752 if (rc < 0) {
753 pr_err("Failed to restore lcdb settings rc=%d\n", rc);
754 return rc;
755 }
756 lcdb->settings_saved = false;
757 }
758
759 return 0;
760}
761
Anirudh Ghayal968862c2017-03-31 15:34:05 +0530762static int qpnp_lcdb_enable_wa(struct qpnp_lcdb *lcdb)
763{
764 int rc;
765 u8 val = 0;
766
767 /* required only for PM660L */
768 if (lcdb->pmic_rev_id->pmic_subtype != PM660L_SUBTYPE)
769 return 0;
770
771 val = MODULE_EN_BIT;
772 rc = qpnp_lcdb_write(lcdb, lcdb->base + LCDB_ENABLE_CTL1_REG,
773 &val, 1);
774 if (rc < 0) {
775 pr_err("Failed to enable lcdb rc= %d\n", rc);
776 return rc;
777 }
778
779 val = 0;
780 rc = qpnp_lcdb_write(lcdb, lcdb->base + LCDB_ENABLE_CTL1_REG,
781 &val, 1);
782 if (rc < 0) {
783 pr_err("Failed to disable lcdb rc= %d\n", rc);
784 return rc;
785 }
786
Kiran Gundaa7228922018-06-27 11:14:21 +0530787 if (lcdb->wa_flags & NCP_SCP_DISABLE_WA) {
Anirudh Ghayal968862c2017-03-31 15:34:05 +0530788 /*
789 * delay to make sure that the MID pin – ie the
790 * output of the LCDB boost – returns to 0V
791 * after the module is disabled
792 */
793 usleep_range(10000, 10100);
794
795 rc = qpnp_lcdb_masked_write(lcdb,
796 lcdb->base + LCDB_MISC_CTL_REG,
797 DIS_SCP_BIT, DIS_SCP_BIT);
798 if (rc < 0) {
799 pr_err("Failed to disable SC rc=%d\n", rc);
800 return rc;
801 }
802 /* delay for SC-disable to take effect */
803 usleep_range(1000, 1100);
804
805 rc = qpnp_lcdb_masked_write(lcdb,
806 lcdb->base + LCDB_MISC_CTL_REG,
807 DIS_SCP_BIT, 0);
808 if (rc < 0) {
809 pr_err("Failed to enable SC rc=%d\n", rc);
810 return rc;
811 }
812 /* delay for SC-enable to take effect */
813 usleep_range(1000, 1100);
814 }
815
816 return 0;
817}
818
Kiran Gunda08368b32018-09-10 18:04:43 +0530819#define VOLTAGE_START_MV 4500
820#define VOLTAGE_STEP_MV 500
821
David Collins8885f792017-01-26 14:36:34 -0800822static int qpnp_lcdb_enable(struct qpnp_lcdb *lcdb)
823{
824 int rc = 0, timeout, delay;
Kiran Gunda08368b32018-09-10 18:04:43 +0530825 int voltage_mv = VOLTAGE_START_MV;
David Collins8885f792017-01-26 14:36:34 -0800826 u8 val = 0;
827
Anirudh Ghayal264f9272017-03-05 22:34:37 +0530828 if (lcdb->lcdb_enabled || lcdb->lcdb_sc_disable) {
829 pr_debug("lcdb_enabled=%d lcdb_sc_disable=%d\n",
830 lcdb->lcdb_enabled, lcdb->lcdb_sc_disable);
David Collins8885f792017-01-26 14:36:34 -0800831 return 0;
Anirudh Ghayal264f9272017-03-05 22:34:37 +0530832 }
David Collins8885f792017-01-26 14:36:34 -0800833
834 if (lcdb->ttw_enable) {
835 rc = qpnp_lcdb_ttw_exit(lcdb);
836 if (rc < 0) {
837 pr_err("Failed to exit TTW mode rc=%d\n", rc);
838 return rc;
839 }
840 }
841
Anirudh Ghayal968862c2017-03-31 15:34:05 +0530842 rc = qpnp_lcdb_enable_wa(lcdb);
843 if (rc < 0) {
844 pr_err("Failed to execute enable_wa rc=%d\n", rc);
845 return rc;
846 }
847
Kiran Gunda08368b32018-09-10 18:04:43 +0530848 if (lcdb->voltage_step_ramp) {
849 if (lcdb->ldo.voltage_mv < VOLTAGE_START_MV)
850 voltage_mv = lcdb->ldo.voltage_mv;
851
852 rc = qpnp_lcdb_set_voltage(lcdb, voltage_mv, LDO);
853 if (rc < 0)
854 return rc;
855
856 if (lcdb->ncp.voltage_mv < VOLTAGE_START_MV)
857 voltage_mv = lcdb->ncp.voltage_mv;
858
859 rc = qpnp_lcdb_set_voltage(lcdb, voltage_mv, NCP);
860 if (rc < 0)
861 return rc;
862 }
863
David Collins8885f792017-01-26 14:36:34 -0800864 val = MODULE_EN_BIT;
865 rc = qpnp_lcdb_write(lcdb, lcdb->base + LCDB_ENABLE_CTL1_REG,
866 &val, 1);
867 if (rc < 0) {
Anirudh Ghayal968862c2017-03-31 15:34:05 +0530868 pr_err("Failed to disable lcdb rc= %d\n", rc);
David Collins8885f792017-01-26 14:36:34 -0800869 goto fail_enable;
870 }
871
872 /* poll for vreg_ok */
873 timeout = 10;
874 delay = lcdb->bst.soft_start_us + lcdb->ldo.soft_start_us +
875 lcdb->ncp.soft_start_us;
876 delay += lcdb->bst.vreg_ok_dbc_us + lcdb->ldo.vreg_ok_dbc_us +
877 lcdb->ncp.vreg_ok_dbc_us;
878 while (timeout--) {
879 rc = qpnp_lcdb_read(lcdb, lcdb->base + INT_RT_STATUS_REG,
880 &val, 1);
881 if (rc < 0) {
882 pr_err("Failed to poll for vreg-ok status rc=%d\n", rc);
883 break;
884 }
885 if (val & VREG_OK_RT_STS_BIT)
886 break;
887
888 usleep_range(delay, delay + 100);
889 }
890
891 if (rc || !timeout) {
892 if (!timeout) {
893 pr_err("lcdb-vreg-ok status failed to change\n");
894 rc = -ETIMEDOUT;
895 }
896 goto fail_enable;
897 }
898
899 lcdb->lcdb_enabled = true;
Kiran Gunda08368b32018-09-10 18:04:43 +0530900 if (lcdb->voltage_step_ramp) {
901 usleep_range(10000, 11000);
902 rc = qpnp_lcdb_set_voltage_step(lcdb,
903 voltage_mv + VOLTAGE_STEP_MV,
904 LDO_NCP);
905 if (rc < 0) {
906 pr_err("Failed to set LCDB voltage rc=%d\n", rc);
907 return rc;
908 }
909 }
910
David Collins8885f792017-01-26 14:36:34 -0800911 pr_debug("lcdb enabled successfully!\n");
912
913 return 0;
914
915fail_enable:
916 dump_status_registers(lcdb);
917 pr_err("Failed to enable lcdb rc=%d\n", rc);
918 return rc;
919}
920
921static int qpnp_lcdb_disable(struct qpnp_lcdb *lcdb)
922{
923 int rc = 0;
924 u8 val;
Kiran Gunda414471a2017-12-07 12:50:51 +0530925 u16 pmic_subtype = lcdb->pmic_rev_id->pmic_subtype;
David Collins8885f792017-01-26 14:36:34 -0800926
927 if (!lcdb->lcdb_enabled)
928 return 0;
929
930 if (lcdb->ttw_enable) {
Kiran Gunda414471a2017-12-07 12:50:51 +0530931 if (pmic_subtype == PM660L_SUBTYPE)
932 rc = qpnp_lcdb_ttw_enter_pm660l(lcdb);
933 else
934 rc = qpnp_lcdb_ttw_enter(lcdb);
935
David Collins8885f792017-01-26 14:36:34 -0800936 if (rc < 0) {
937 pr_err("Failed to enable TTW mode rc=%d\n", rc);
938 return rc;
939 }
940 lcdb->lcdb_enabled = false;
941
942 return 0;
943 }
944
Kiran Gundac390a892019-01-23 13:12:06 +0530945 if (lcdb->wa_flags & FORCE_PD_ENABLE_WA) {
946 /*
947 * force pull-down to enable quick discharge after
948 * turning off
949 */
950 val = LDO_FORCE_PD_EN_BIT | LDO_FORCE_PD_MODE;
951 rc = qpnp_lcdb_write(lcdb, lcdb->base +
952 LCDB_LDO_FORCE_PD_CTL_REG, &val, 1);
953 if (rc < 0)
954 return rc;
955 }
956
David Collins8885f792017-01-26 14:36:34 -0800957 val = 0;
958 rc = qpnp_lcdb_write(lcdb, lcdb->base + LCDB_ENABLE_CTL1_REG,
959 &val, 1);
960 if (rc < 0)
961 pr_err("Failed to disable lcdb rc= %d\n", rc);
962 else
963 lcdb->lcdb_enabled = false;
964
Kiran Gundac390a892019-01-23 13:12:06 +0530965 if (lcdb->wa_flags & FORCE_PD_ENABLE_WA) {
966 /* wait for 10 msec after module disable for LDO to discharge */
967 usleep_range(10000, 11000);
968
969 val = 0;
970 rc = qpnp_lcdb_write(lcdb, lcdb->base +
971 LCDB_LDO_FORCE_PD_CTL_REG, &val, 1);
972 if (rc < 0)
973 return rc;
974 }
975
David Collins8885f792017-01-26 14:36:34 -0800976 return rc;
977}
978
Anirudh Ghayal264f9272017-03-05 22:34:37 +0530979#define LCDB_SC_RESET_CNT_DLY_US 1000000
980#define LCDB_SC_CNT_MAX 10
981static int qpnp_lcdb_handle_sc_event(struct qpnp_lcdb *lcdb)
982{
983 int rc = 0;
984 s64 elapsed_time_us;
985
986 mutex_lock(&lcdb->lcdb_mutex);
987 rc = qpnp_lcdb_disable(lcdb);
988 if (rc < 0) {
989 pr_err("Failed to disable lcdb rc=%d\n", rc);
990 goto unlock_mutex;
991 }
992
993 /* Check if the SC re-occurred immediately */
994 elapsed_time_us = ktime_us_delta(ktime_get(),
995 lcdb->sc_module_enable_time);
996 if (elapsed_time_us > LCDB_SC_RESET_CNT_DLY_US) {
997 lcdb->sc_count = 0;
998 } else if (lcdb->sc_count > LCDB_SC_CNT_MAX) {
999 pr_err("SC trigged %d times, disabling LCDB forever!\n",
1000 lcdb->sc_count);
1001 lcdb->lcdb_sc_disable = true;
1002 goto unlock_mutex;
1003 }
1004 lcdb->sc_count++;
1005 lcdb->sc_module_enable_time = ktime_get();
1006
1007 /* delay for SC to clear */
1008 usleep_range(10000, 10100);
1009
1010 rc = qpnp_lcdb_enable(lcdb);
1011 if (rc < 0)
1012 pr_err("Failed to enable lcdb rc=%d\n", rc);
1013
1014unlock_mutex:
1015 mutex_unlock(&lcdb->lcdb_mutex);
1016 return rc;
1017}
1018
1019static irqreturn_t qpnp_lcdb_sc_irq_handler(int irq, void *data)
1020{
1021 struct qpnp_lcdb *lcdb = data;
1022 int rc;
1023 u8 val, val2[2] = {0};
1024
1025 rc = qpnp_lcdb_read(lcdb, lcdb->base + INT_RT_STATUS_REG, &val, 1);
1026 if (rc < 0)
1027 goto irq_handled;
1028
1029 if (val & SC_ERROR_RT_STS_BIT) {
1030 rc = qpnp_lcdb_read(lcdb,
1031 lcdb->base + LCDB_MISC_CTL_REG, &val, 1);
1032 if (rc < 0)
1033 goto irq_handled;
1034
1035 if (val & EN_TOUCH_WAKE_BIT) {
1036 /* blanking time */
1037 usleep_range(300, 310);
1038 /*
1039 * The status registers need to written with any value
1040 * before reading
1041 */
1042 rc = qpnp_lcdb_write(lcdb,
1043 lcdb->base + LCDB_STS3_REG, val2, 2);
1044 if (rc < 0)
1045 goto irq_handled;
1046
1047 rc = qpnp_lcdb_read(lcdb,
1048 lcdb->base + LCDB_STS3_REG, val2, 2);
1049 if (rc < 0)
1050 goto irq_handled;
1051
1052 if (!(val2[0] & LDO_VREG_OK_BIT) ||
1053 !(val2[1] & NCP_VREG_OK_BIT)) {
1054 rc = qpnp_lcdb_handle_sc_event(lcdb);
1055 if (rc < 0) {
1056 pr_err("Failed to handle SC rc=%d\n",
1057 rc);
1058 goto irq_handled;
1059 }
1060 }
1061 } else {
1062 /* blanking time */
1063 usleep_range(2000, 2100);
1064 /* Read the SC status again to confirm true SC */
1065 rc = qpnp_lcdb_read(lcdb,
1066 lcdb->base + INT_RT_STATUS_REG, &val, 1);
1067 if (rc < 0)
1068 goto irq_handled;
1069
1070 if (val & SC_ERROR_RT_STS_BIT) {
1071 rc = qpnp_lcdb_handle_sc_event(lcdb);
1072 if (rc < 0) {
1073 pr_err("Failed to handle SC rc=%d\n",
1074 rc);
1075 goto irq_handled;
1076 }
1077 }
1078 }
1079 }
1080irq_handled:
1081 return IRQ_HANDLED;
1082}
1083
David Collins8885f792017-01-26 14:36:34 -08001084#define MIN_BST_VOLTAGE_MV 4700
Subbaraman Narayanamurthy841eb432018-04-10 13:20:56 -07001085#define PM660_MAX_BST_VOLTAGE_MV 6250
1086#define MAX_BST_VOLTAGE_MV 6275
David Collins8885f792017-01-26 14:36:34 -08001087#define MIN_VOLTAGE_MV 4000
1088#define MAX_VOLTAGE_MV 6000
1089#define VOLTAGE_MIN_STEP_100_MV 4000
1090#define VOLTAGE_MIN_STEP_50_MV 4950
1091#define VOLTAGE_STEP_100_MV 100
1092#define VOLTAGE_STEP_50_MV 50
Kiran Gundaa5a1cb12018-03-05 12:57:59 +05301093#define VOLTAGE_STEP_25_MV 25
David Collins8885f792017-01-26 14:36:34 -08001094#define VOLTAGE_STEP_50MV_OFFSET 0xA
1095static int qpnp_lcdb_set_bst_voltage(struct qpnp_lcdb *lcdb,
Kiran Gundabcfca132017-08-08 16:58:47 +05301096 int voltage_mv, u8 type)
David Collins8885f792017-01-26 14:36:34 -08001097{
1098 int rc = 0;
Kiran Gundaa5a1cb12018-03-05 12:57:59 +05301099 u8 val, voltage_step, mask = 0;
Kiran Gundabcfca132017-08-08 16:58:47 +05301100 int bst_voltage_mv;
Kiran Gunda414471a2017-12-07 12:50:51 +05301101 u16 pmic_subtype = lcdb->pmic_rev_id->pmic_subtype;
Kiran Gundabcfca132017-08-08 16:58:47 +05301102 struct ldo_regulator *ldo = &lcdb->ldo;
1103 struct ncp_regulator *ncp = &lcdb->ncp;
1104 struct bst_params *bst = &lcdb->bst;
David Collins8885f792017-01-26 14:36:34 -08001105
Kiran Gundabcfca132017-08-08 16:58:47 +05301106 /* Vout_Boost = headroom_mv + max( Vout_LDO, abs (Vout_NCP)) */
1107 bst_voltage_mv = max(voltage_mv, max(ldo->voltage_mv, ncp->voltage_mv));
1108 bst_voltage_mv += bst->headroom_mv;
David Collins8885f792017-01-26 14:36:34 -08001109
Kiran Gundabcfca132017-08-08 16:58:47 +05301110 if (bst_voltage_mv < MIN_BST_VOLTAGE_MV)
1111 bst_voltage_mv = MIN_BST_VOLTAGE_MV;
Subbaraman Narayanamurthy841eb432018-04-10 13:20:56 -07001112
1113 if (pmic_subtype == PM660L_SUBTYPE) {
1114 if (bst_voltage_mv > PM660_MAX_BST_VOLTAGE_MV)
1115 bst_voltage_mv = PM660_MAX_BST_VOLTAGE_MV;
1116 } else {
1117 if (bst_voltage_mv > MAX_BST_VOLTAGE_MV)
1118 bst_voltage_mv = MAX_BST_VOLTAGE_MV;
1119 }
David Collins8885f792017-01-26 14:36:34 -08001120
Kiran Gundabcfca132017-08-08 16:58:47 +05301121 if (bst_voltage_mv != bst->voltage_mv) {
Kiran Gundaa5a1cb12018-03-05 12:57:59 +05301122 if (pmic_subtype == PM660L_SUBTYPE) {
1123 mask = PM660_BST_OUTPUT_VOLTAGE_MASK;
1124 voltage_step = VOLTAGE_STEP_50_MV;
1125 } else {
1126 mask = BST_OUTPUT_VOLTAGE_MASK;
1127 voltage_step = VOLTAGE_STEP_25_MV;
1128 }
1129
Kiran Gundabcfca132017-08-08 16:58:47 +05301130 val = DIV_ROUND_UP(bst_voltage_mv - MIN_BST_VOLTAGE_MV,
Kiran Gundaa5a1cb12018-03-05 12:57:59 +05301131 voltage_step);
Kiran Gundabcfca132017-08-08 16:58:47 +05301132 rc = qpnp_lcdb_masked_write(lcdb, lcdb->base +
1133 LCDB_BST_OUTPUT_VOLTAGE_REG,
Kiran Gunda414471a2017-12-07 12:50:51 +05301134 mask, val);
Kiran Gundabcfca132017-08-08 16:58:47 +05301135 if (rc < 0) {
1136 pr_err("Failed to set boost voltage %d mv rc=%d\n",
1137 bst_voltage_mv, rc);
1138 } else {
1139 pr_debug("Boost voltage set = %d mv (0x%02x = 0x%02x)\n",
1140 bst_voltage_mv, LCDB_BST_OUTPUT_VOLTAGE_REG, val);
1141 bst->voltage_mv = bst_voltage_mv;
1142 }
1143 }
David Collins8885f792017-01-26 14:36:34 -08001144
1145 return rc;
1146}
1147
1148static int qpnp_lcdb_get_bst_voltage(struct qpnp_lcdb *lcdb,
1149 int *voltage_mv)
1150{
1151 int rc;
Kiran Gundaa5a1cb12018-03-05 12:57:59 +05301152 u8 val, voltage_step, mask = 0;
Kiran Gunda414471a2017-12-07 12:50:51 +05301153 u16 pmic_subtype = lcdb->pmic_rev_id->pmic_subtype;
David Collins8885f792017-01-26 14:36:34 -08001154
1155 rc = qpnp_lcdb_read(lcdb, lcdb->base + LCDB_BST_OUTPUT_VOLTAGE_REG,
1156 &val, 1);
1157 if (rc < 0) {
1158 pr_err("Failed to reat BST voltage rc=%d\n", rc);
1159 return rc;
1160 }
1161
Kiran Gundaa5a1cb12018-03-05 12:57:59 +05301162 if (pmic_subtype == PM660L_SUBTYPE) {
1163 mask = PM660_BST_OUTPUT_VOLTAGE_MASK;
1164 voltage_step = VOLTAGE_STEP_50_MV;
1165 } else {
1166 mask = BST_OUTPUT_VOLTAGE_MASK;
1167 voltage_step = VOLTAGE_STEP_25_MV;
1168 }
1169
Kiran Gunda414471a2017-12-07 12:50:51 +05301170 val &= mask;
Kiran Gundaa5a1cb12018-03-05 12:57:59 +05301171 *voltage_mv = (val * voltage_step) + MIN_BST_VOLTAGE_MV;
David Collins8885f792017-01-26 14:36:34 -08001172
1173 return 0;
1174}
1175
1176static int qpnp_lcdb_set_voltage(struct qpnp_lcdb *lcdb,
1177 int voltage_mv, u8 type)
1178{
1179 int rc = 0;
1180 u16 offset = LCDB_LDO_OUTPUT_VOLTAGE_REG;
1181 u8 val = 0;
1182
David Collins8885f792017-01-26 14:36:34 -08001183 if (!is_between(voltage_mv, MIN_VOLTAGE_MV, MAX_VOLTAGE_MV)) {
1184 pr_err("Invalid voltage %dmv (min=%d max=%d)\n",
1185 voltage_mv, MIN_VOLTAGE_MV, MAX_VOLTAGE_MV);
1186 return -EINVAL;
1187 }
1188
Kiran Gundabcfca132017-08-08 16:58:47 +05301189 rc = qpnp_lcdb_set_bst_voltage(lcdb, voltage_mv, type);
1190 if (rc < 0) {
1191 pr_err("Failed to set boost voltage rc=%d\n", rc);
1192 return rc;
David Collins8885f792017-01-26 14:36:34 -08001193 }
1194
1195 /* Below logic is only valid for LDO and NCP type */
1196 if (voltage_mv < VOLTAGE_MIN_STEP_50_MV) {
1197 val = DIV_ROUND_UP(voltage_mv - VOLTAGE_MIN_STEP_100_MV,
1198 VOLTAGE_STEP_100_MV);
1199 } else {
1200 val = DIV_ROUND_UP(voltage_mv - VOLTAGE_MIN_STEP_50_MV,
1201 VOLTAGE_STEP_50_MV);
1202 val += VOLTAGE_STEP_50MV_OFFSET;
1203 }
1204
Kiran Gundabcfca132017-08-08 16:58:47 +05301205 if (type == NCP)
1206 offset = LCDB_NCP_OUTPUT_VOLTAGE_REG;
1207
David Collins8885f792017-01-26 14:36:34 -08001208 rc = qpnp_lcdb_masked_write(lcdb, lcdb->base + offset,
1209 SET_OUTPUT_VOLTAGE_MASK, val);
1210 if (rc < 0)
1211 pr_err("Failed to set output voltage %d mv for %s rc=%d\n",
1212 voltage_mv, (type == LDO) ? "LDO" : "NCP", rc);
1213 else
1214 pr_debug("%s voltage set = %d mv (0x%02x = 0x%02x)\n",
1215 (type == LDO) ? "LDO" : "NCP", voltage_mv, offset, val);
1216
1217 return rc;
1218}
1219
Kiran Gunda08368b32018-09-10 18:04:43 +05301220static int qpnp_lcdb_set_voltage_step(struct qpnp_lcdb *lcdb,
1221 int voltage_start_mv, u8 type)
1222{
1223 int i, ldo_voltage, ncp_voltage, voltage, rc = 0;
1224
1225 for (i = voltage_start_mv; i <= (MAX_VOLTAGE_MV + VOLTAGE_STEP_MV);
1226 i += VOLTAGE_STEP_MV) {
1227
1228 ldo_voltage = (lcdb->ldo.voltage_mv < i) ?
1229 lcdb->ldo.voltage_mv : i;
1230
1231 ncp_voltage = (lcdb->ncp.voltage_mv < i) ?
1232 lcdb->ncp.voltage_mv : i;
1233 if (type == LDO_NCP) {
1234 rc = qpnp_lcdb_set_voltage(lcdb, ldo_voltage, LDO);
1235 if (rc < 0)
1236 return rc;
1237
1238 rc = qpnp_lcdb_set_voltage(lcdb, ncp_voltage, NCP);
1239 if (rc < 0)
1240 return rc;
1241
1242 pr_debug(" LDO voltage step %d NCP voltage step %d\n",
1243 ldo_voltage, ncp_voltage);
1244
1245 if ((i >= lcdb->ncp.voltage_mv) &&
1246 (i >= lcdb->ldo.voltage_mv))
1247 break;
1248 } else {
1249 voltage = (type == LDO) ? ldo_voltage : ncp_voltage;
1250 rc = qpnp_lcdb_set_voltage(lcdb, voltage, type);
1251 if (rc < 0)
1252 return rc;
1253
1254 pr_debug("%s voltage step %d\n",
1255 (type == LDO) ? "LDO" : "NCP", voltage);
1256 if ((type == LDO) && (i >= lcdb->ldo.voltage_mv))
1257 break;
1258
1259 if ((type == NCP) && (i >= lcdb->ncp.voltage_mv))
1260 break;
1261
1262 }
1263
1264 usleep_range(1000, 1100);
1265 }
1266
1267 return rc;
1268}
1269
David Collins8885f792017-01-26 14:36:34 -08001270static int qpnp_lcdb_get_voltage(struct qpnp_lcdb *lcdb,
1271 u32 *voltage_mv, u8 type)
1272{
1273 int rc = 0;
1274 u16 offset = LCDB_LDO_OUTPUT_VOLTAGE_REG;
1275 u8 val = 0;
1276
1277 if (type == BST)
1278 return qpnp_lcdb_get_bst_voltage(lcdb, voltage_mv);
1279
1280 if (type == NCP)
1281 offset = LCDB_NCP_OUTPUT_VOLTAGE_REG;
1282
1283 rc = qpnp_lcdb_read(lcdb, lcdb->base + offset, &val, 1);
1284 if (rc < 0) {
1285 pr_err("Failed to read %s volatge rc=%d\n",
1286 (type == LDO) ? "LDO" : "NCP", rc);
1287 return rc;
1288 }
1289
Kiran Gunda9c40b582018-09-10 12:16:41 +05301290 val &= SET_OUTPUT_VOLTAGE_MASK;
David Collins8885f792017-01-26 14:36:34 -08001291 if (val < VOLTAGE_STEP_50MV_OFFSET) {
1292 *voltage_mv = VOLTAGE_MIN_STEP_100_MV +
1293 (val * VOLTAGE_STEP_100_MV);
1294 } else {
1295 *voltage_mv = VOLTAGE_MIN_STEP_50_MV +
1296 ((val - VOLTAGE_STEP_50MV_OFFSET) * VOLTAGE_STEP_50_MV);
1297 }
1298
1299 if (!rc)
1300 pr_debug("%s voltage read-back = %d mv (0x%02x = 0x%02x)\n",
1301 (type == LDO) ? "LDO" : "NCP",
1302 *voltage_mv, offset, val);
1303
1304 return rc;
1305}
1306
1307static int qpnp_lcdb_set_soft_start(struct qpnp_lcdb *lcdb,
1308 u32 ss_us, u8 type)
1309{
1310 int rc = 0, i = 0;
1311 u16 offset = LCDB_LDO_SOFT_START_CTL_REG;
1312 u8 val = 0;
1313
1314 if (type == NCP)
1315 offset = LCDB_NCP_SOFT_START_CTL_REG;
1316
1317 if (!is_between(ss_us, MIN_SOFT_START_US, MAX_SOFT_START_US)) {
1318 pr_err("Invalid soft_start_us %d (min=%d max=%d)\n",
1319 ss_us, MIN_SOFT_START_US, MAX_SOFT_START_US);
1320 return -EINVAL;
1321 }
1322
1323 i = 0;
1324 while (ss_us > soft_start_us[i])
1325 i++;
1326 val = ((i == 0) ? 0 : i - 1) & SOFT_START_MASK;
1327
1328 rc = qpnp_lcdb_masked_write(lcdb,
1329 lcdb->base + offset, SOFT_START_MASK, val);
1330 if (rc < 0)
1331 pr_err("Failed to write %s soft-start time %d rc=%d",
1332 (type == LDO) ? "LDO" : "NCP", soft_start_us[i], rc);
1333
1334 return rc;
1335}
1336
1337static int qpnp_lcdb_ldo_regulator_enable(struct regulator_dev *rdev)
1338{
1339 int rc = 0;
1340 struct qpnp_lcdb *lcdb = rdev_get_drvdata(rdev);
1341
Kavya Nunna80bc1502018-10-01 14:50:23 +05301342 if (lcdb->secure_mode)
1343 return 0;
1344
David Collins8885f792017-01-26 14:36:34 -08001345 mutex_lock(&lcdb->lcdb_mutex);
1346 rc = qpnp_lcdb_enable(lcdb);
1347 if (rc < 0)
1348 pr_err("Failed to enable lcdb rc=%d\n", rc);
1349 mutex_unlock(&lcdb->lcdb_mutex);
1350
1351 return rc;
1352}
1353
1354static int qpnp_lcdb_ldo_regulator_disable(struct regulator_dev *rdev)
1355{
1356 int rc = 0;
1357 struct qpnp_lcdb *lcdb = rdev_get_drvdata(rdev);
1358
Kavya Nunna80bc1502018-10-01 14:50:23 +05301359 if (lcdb->secure_mode)
1360 return 0;
1361
David Collins8885f792017-01-26 14:36:34 -08001362 mutex_lock(&lcdb->lcdb_mutex);
1363 rc = qpnp_lcdb_disable(lcdb);
1364 if (rc < 0)
1365 pr_err("Failed to disable lcdb rc=%d\n", rc);
1366 mutex_unlock(&lcdb->lcdb_mutex);
1367
1368 return rc;
1369}
1370
1371static int qpnp_lcdb_ldo_regulator_is_enabled(struct regulator_dev *rdev)
1372{
1373 struct qpnp_lcdb *lcdb = rdev_get_drvdata(rdev);
1374
1375 return lcdb->lcdb_enabled;
1376}
1377
1378static int qpnp_lcdb_ldo_regulator_set_voltage(struct regulator_dev *rdev,
1379 int min_uV, int max_uV, unsigned int *selector)
1380{
1381 int rc = 0;
1382 struct qpnp_lcdb *lcdb = rdev_get_drvdata(rdev);
1383
Kavya Nunna80bc1502018-10-01 14:50:23 +05301384 if (lcdb->secure_mode)
1385 return 0;
1386
Kiran Gunda08368b32018-09-10 18:04:43 +05301387 lcdb->ldo.voltage_mv = min_uV / 1000;
1388 if (lcdb->voltage_step_ramp)
1389 rc = qpnp_lcdb_set_voltage_step(lcdb,
1390 lcdb->ldo.prev_voltage_mv + VOLTAGE_STEP_MV, LDO);
1391 else
1392 rc = qpnp_lcdb_set_voltage(lcdb, lcdb->ldo.voltage_mv, LDO);
1393
David Collins8885f792017-01-26 14:36:34 -08001394 if (rc < 0)
1395 pr_err("Failed to set LDO voltage rc=%c\n", rc);
Kiran Gundabcfca132017-08-08 16:58:47 +05301396 else
Kiran Gunda08368b32018-09-10 18:04:43 +05301397 lcdb->ldo.prev_voltage_mv = lcdb->ldo.voltage_mv;
David Collins8885f792017-01-26 14:36:34 -08001398
1399 return rc;
1400}
1401
1402static int qpnp_lcdb_ldo_regulator_get_voltage(struct regulator_dev *rdev)
1403{
1404 int rc = 0;
1405 u32 voltage_mv = 0;
1406 struct qpnp_lcdb *lcdb = rdev_get_drvdata(rdev);
1407
1408 rc = qpnp_lcdb_get_voltage(lcdb, &voltage_mv, LDO);
1409 if (rc < 0) {
1410 pr_err("Failed to get ldo voltage rc=%d\n", rc);
1411 return rc;
1412 }
1413
1414 return voltage_mv * 1000;
1415}
1416
1417static struct regulator_ops qpnp_lcdb_ldo_ops = {
1418 .enable = qpnp_lcdb_ldo_regulator_enable,
1419 .disable = qpnp_lcdb_ldo_regulator_disable,
1420 .is_enabled = qpnp_lcdb_ldo_regulator_is_enabled,
1421 .set_voltage = qpnp_lcdb_ldo_regulator_set_voltage,
1422 .get_voltage = qpnp_lcdb_ldo_regulator_get_voltage,
1423};
1424
1425static int qpnp_lcdb_ncp_regulator_enable(struct regulator_dev *rdev)
1426{
1427 int rc = 0;
1428 struct qpnp_lcdb *lcdb = rdev_get_drvdata(rdev);
1429
Kavya Nunna80bc1502018-10-01 14:50:23 +05301430 if (lcdb->secure_mode)
1431 return 0;
1432
David Collins8885f792017-01-26 14:36:34 -08001433 mutex_lock(&lcdb->lcdb_mutex);
1434 rc = qpnp_lcdb_enable(lcdb);
1435 if (rc < 0)
1436 pr_err("Failed to enable lcdb rc=%d\n", rc);
1437 mutex_unlock(&lcdb->lcdb_mutex);
1438
1439 return rc;
1440}
1441
1442static int qpnp_lcdb_ncp_regulator_disable(struct regulator_dev *rdev)
1443{
1444 int rc = 0;
1445 struct qpnp_lcdb *lcdb = rdev_get_drvdata(rdev);
1446
Kavya Nunna80bc1502018-10-01 14:50:23 +05301447 if (lcdb->secure_mode)
1448 return 0;
1449
David Collins8885f792017-01-26 14:36:34 -08001450 mutex_lock(&lcdb->lcdb_mutex);
1451 rc = qpnp_lcdb_disable(lcdb);
1452 if (rc < 0)
1453 pr_err("Failed to disable lcdb rc=%d\n", rc);
1454 mutex_unlock(&lcdb->lcdb_mutex);
1455
1456 return rc;
1457}
1458
1459static int qpnp_lcdb_ncp_regulator_is_enabled(struct regulator_dev *rdev)
1460{
1461 struct qpnp_lcdb *lcdb = rdev_get_drvdata(rdev);
1462
1463 return lcdb->lcdb_enabled;
1464}
1465
1466static int qpnp_lcdb_ncp_regulator_set_voltage(struct regulator_dev *rdev,
1467 int min_uV, int max_uV, unsigned int *selector)
1468{
1469 int rc = 0;
1470 struct qpnp_lcdb *lcdb = rdev_get_drvdata(rdev);
1471
Kavya Nunna80bc1502018-10-01 14:50:23 +05301472 if (lcdb->secure_mode)
1473 return 0;
1474
Kiran Gunda08368b32018-09-10 18:04:43 +05301475 lcdb->ncp.voltage_mv = min_uV / 1000;
1476 if (lcdb->voltage_step_ramp)
1477 rc = qpnp_lcdb_set_voltage_step(lcdb,
1478 lcdb->ncp.prev_voltage_mv + VOLTAGE_STEP_MV, NCP);
Kiran Gundabcfca132017-08-08 16:58:47 +05301479 else
Kiran Gunda08368b32018-09-10 18:04:43 +05301480 rc = qpnp_lcdb_set_voltage(lcdb, lcdb->ncp.voltage_mv, NCP);
1481
1482 if (rc < 0)
1483 pr_err("Failed to set NCP voltage rc=%c\n", rc);
1484 else
1485 lcdb->ncp.prev_voltage_mv = lcdb->ncp.voltage_mv;
David Collins8885f792017-01-26 14:36:34 -08001486
1487 return rc;
1488}
1489
1490static int qpnp_lcdb_ncp_regulator_get_voltage(struct regulator_dev *rdev)
1491{
1492 int rc;
1493 u32 voltage_mv = 0;
1494 struct qpnp_lcdb *lcdb = rdev_get_drvdata(rdev);
1495
1496 rc = qpnp_lcdb_get_voltage(lcdb, &voltage_mv, NCP);
1497 if (rc < 0) {
1498 pr_err("Failed to get ncp voltage rc=%d\n", rc);
1499 return rc;
1500 }
1501
1502 return voltage_mv * 1000;
1503}
1504
1505static struct regulator_ops qpnp_lcdb_ncp_ops = {
1506 .enable = qpnp_lcdb_ncp_regulator_enable,
1507 .disable = qpnp_lcdb_ncp_regulator_disable,
1508 .is_enabled = qpnp_lcdb_ncp_regulator_is_enabled,
1509 .set_voltage = qpnp_lcdb_ncp_regulator_set_voltage,
1510 .get_voltage = qpnp_lcdb_ncp_regulator_get_voltage,
1511};
1512
1513static int qpnp_lcdb_regulator_register(struct qpnp_lcdb *lcdb, u8 type)
1514{
Kiran Gundadf7fa662018-06-11 12:41:51 +05301515 int rc = 0, off_on_delay = 0;
David Collins8885f792017-01-26 14:36:34 -08001516 struct regulator_init_data *init_data;
1517 struct regulator_config cfg = {};
1518 struct regulator_desc *rdesc;
1519 struct regulator_dev *rdev;
1520 struct device_node *node;
1521
Kiran Gundadf7fa662018-06-11 12:41:51 +05301522 if (lcdb->pmic_rev_id->pmic_subtype != PM660L_SUBTYPE)
1523 off_on_delay = PMIC5_LCDB_OFF_ON_DELAY_US;
1524
David Collins8885f792017-01-26 14:36:34 -08001525 if (type == LDO) {
1526 node = lcdb->ldo.node;
1527 rdesc = &lcdb->ldo.rdesc;
1528 rdesc->ops = &qpnp_lcdb_ldo_ops;
Kiran Gundadf7fa662018-06-11 12:41:51 +05301529 rdesc->off_on_delay = off_on_delay;
David Collins8885f792017-01-26 14:36:34 -08001530 rdev = lcdb->ldo.rdev;
1531 } else if (type == NCP) {
1532 node = lcdb->ncp.node;
1533 rdesc = &lcdb->ncp.rdesc;
1534 rdesc->ops = &qpnp_lcdb_ncp_ops;
Kiran Gundadf7fa662018-06-11 12:41:51 +05301535 rdesc->off_on_delay = off_on_delay;
David Collins8885f792017-01-26 14:36:34 -08001536 rdev = lcdb->ncp.rdev;
1537 } else {
1538 pr_err("Invalid regulator type %d\n", type);
1539 return -EINVAL;
1540 }
1541
1542 init_data = of_get_regulator_init_data(lcdb->dev, node, rdesc);
1543 if (!init_data) {
1544 pr_err("Failed to get regulator_init_data for %s\n",
1545 (type == LDO) ? "LDO" : "NCP");
1546 return -ENOMEM;
1547 }
1548
1549 if (init_data->constraints.name) {
1550 rdesc->owner = THIS_MODULE;
1551 rdesc->type = REGULATOR_VOLTAGE;
1552 rdesc->name = init_data->constraints.name;
1553
1554 cfg.dev = lcdb->dev;
1555 cfg.init_data = init_data;
1556 cfg.driver_data = lcdb;
1557 cfg.of_node = node;
1558
1559 if (of_get_property(lcdb->dev->of_node, "parent-supply", NULL))
1560 init_data->supply_regulator = "parent";
1561
1562 init_data->constraints.valid_ops_mask
1563 |= REGULATOR_CHANGE_VOLTAGE
1564 | REGULATOR_CHANGE_STATUS;
1565
1566 rdev = devm_regulator_register(lcdb->dev, rdesc, &cfg);
1567 if (IS_ERR(rdev)) {
1568 rc = PTR_ERR(rdev);
1569 rdev = NULL;
1570 pr_err("Failed to register lcdb_%s regulator rc = %d\n",
1571 (type == LDO) ? "LDO" : "NCP", rc);
1572 return rc;
1573 }
1574 } else {
1575 pr_err("%s_regulator name missing\n",
1576 (type == LDO) ? "LDO" : "NCP");
1577 return -EINVAL;
1578 }
1579
1580 return rc;
1581}
1582
1583static int qpnp_lcdb_parse_ttw(struct qpnp_lcdb *lcdb)
1584{
1585 int rc = 0;
1586 u32 temp;
1587 u8 val = 0;
1588 struct device_node *node = lcdb->dev->of_node;
1589
1590 if (of_property_read_bool(node, "qcom,ttw-mode-sw")) {
1591 lcdb->ttw_mode_sw = true;
1592 rc = of_property_read_u32(node, "qcom,attw-toff-ms", &temp);
1593 if (!rc) {
1594 if (!is_between(temp, ATTW_MIN_MS, ATTW_MAX_MS)) {
1595 pr_err("Invalid TOFF val %d (min=%d max=%d)\n",
1596 temp, ATTW_MIN_MS, ATTW_MAX_MS);
1597 return -EINVAL;
1598 }
1599 val = ilog2(temp / 4) << ATTW_TOFF_TIME_SHIFT;
1600 } else {
1601 pr_err("qcom,attw-toff-ms not specified for TTW SW mode\n");
1602 return rc;
1603 }
1604
1605 rc = of_property_read_u32(node, "qcom,attw-ton-ms", &temp);
1606 if (!rc) {
1607 if (!is_between(temp, ATTW_MIN_MS, ATTW_MAX_MS)) {
1608 pr_err("Invalid TON value %d (min=%d max=%d)\n",
1609 temp, ATTW_MIN_MS, ATTW_MAX_MS);
1610 return -EINVAL;
1611 }
1612 val |= ilog2(temp / 4);
1613 } else {
1614 pr_err("qcom,attw-ton-ms not specified for TTW SW mode\n");
1615 return rc;
1616 }
1617 rc = qpnp_lcdb_masked_write(lcdb, lcdb->base +
1618 LCDB_AUTO_TOUCH_WAKE_CTL_REG,
1619 ATTW_TON_TIME_MASK | ATTW_TOFF_TIME_MASK, val);
1620 if (rc < 0) {
1621 pr_err("Failed to write ATTW ON/OFF rc=%d\n", rc);
1622 return rc;
1623 }
1624 }
1625
1626 return 0;
1627}
1628
1629static int qpnp_lcdb_ldo_dt_init(struct qpnp_lcdb *lcdb)
1630{
1631 int rc = 0;
1632 struct device_node *node = lcdb->ldo.node;
1633
1634 /* LDO output voltage */
1635 lcdb->ldo.voltage_mv = -EINVAL;
1636 rc = of_property_read_u32(node, "qcom,ldo-voltage-mv",
1637 &lcdb->ldo.voltage_mv);
1638 if (!rc && !is_between(lcdb->ldo.voltage_mv, MIN_VOLTAGE_MV,
1639 MAX_VOLTAGE_MV)) {
1640 pr_err("Invalid LDO voltage %dmv (min=%d max=%d)\n",
1641 lcdb->ldo.voltage_mv, MIN_VOLTAGE_MV, MAX_VOLTAGE_MV);
1642 return -EINVAL;
1643 }
1644
1645 /* LDO PD configuration */
1646 lcdb->ldo.pd = -EINVAL;
1647 of_property_read_u32(node, "qcom,ldo-pd", &lcdb->ldo.pd);
1648
1649 lcdb->ldo.pd_strength = -EINVAL;
1650 of_property_read_u32(node, "qcom,ldo-pd-strength",
1651 &lcdb->ldo.pd_strength);
1652
1653 /* LDO ILIM configuration */
1654 lcdb->ldo.ilim_ma = -EINVAL;
1655 rc = of_property_read_u32(node, "qcom,ldo-ilim-ma", &lcdb->ldo.ilim_ma);
1656 if (!rc && !is_between(lcdb->ldo.ilim_ma, MIN_LDO_ILIM_MA,
1657 MAX_LDO_ILIM_MA)) {
1658 pr_err("Invalid ilim_ma %d (min=%d, max=%d)\n",
1659 lcdb->ldo.ilim_ma, MIN_LDO_ILIM_MA,
1660 MAX_LDO_ILIM_MA);
1661 return -EINVAL;
1662 }
1663
1664 /* LDO soft-start (SS) configuration */
1665 lcdb->ldo.soft_start_us = -EINVAL;
1666 of_property_read_u32(node, "qcom,ldo-soft-start-us",
1667 &lcdb->ldo.soft_start_us);
1668
1669 return 0;
1670}
1671
1672static int qpnp_lcdb_ncp_dt_init(struct qpnp_lcdb *lcdb)
1673{
1674 int rc = 0;
1675 struct device_node *node = lcdb->ncp.node;
1676
1677 /* NCP output voltage */
1678 lcdb->ncp.voltage_mv = -EINVAL;
1679 rc = of_property_read_u32(node, "qcom,ncp-voltage-mv",
1680 &lcdb->ncp.voltage_mv);
1681 if (!rc && !is_between(lcdb->ncp.voltage_mv, MIN_VOLTAGE_MV,
1682 MAX_VOLTAGE_MV)) {
1683 pr_err("Invalid NCP voltage %dmv (min=%d max=%d)\n",
1684 lcdb->ldo.voltage_mv, MIN_VOLTAGE_MV, MAX_VOLTAGE_MV);
1685 return -EINVAL;
1686 }
1687
1688 /* NCP PD configuration */
1689 lcdb->ncp.pd = -EINVAL;
1690 of_property_read_u32(node, "qcom,ncp-pd", &lcdb->ncp.pd);
1691
1692 lcdb->ncp.pd_strength = -EINVAL;
1693 of_property_read_u32(node, "qcom,ncp-pd-strength",
1694 &lcdb->ncp.pd_strength);
1695
1696 /* NCP ILIM configuration */
1697 lcdb->ncp.ilim_ma = -EINVAL;
1698 rc = of_property_read_u32(node, "qcom,ncp-ilim-ma", &lcdb->ncp.ilim_ma);
1699 if (!rc && !is_between(lcdb->ncp.ilim_ma, MIN_NCP_ILIM_MA,
1700 MAX_NCP_ILIM_MA)) {
1701 pr_err("Invalid ilim_ma %d (min=%d, max=%d)\n",
1702 lcdb->ncp.ilim_ma, MIN_NCP_ILIM_MA, MAX_NCP_ILIM_MA);
1703 return -EINVAL;
1704 }
1705
1706 /* NCP soft-start (SS) configuration */
1707 lcdb->ncp.soft_start_us = -EINVAL;
1708 of_property_read_u32(node, "qcom,ncp-soft-start-us",
1709 &lcdb->ncp.soft_start_us);
1710
1711 return 0;
1712}
1713
1714static int qpnp_lcdb_bst_dt_init(struct qpnp_lcdb *lcdb)
1715{
1716 int rc = 0;
1717 struct device_node *node = lcdb->bst.node;
Kiran Gunda414471a2017-12-07 12:50:51 +05301718 u16 pmic_subtype = lcdb->pmic_rev_id->pmic_subtype;
1719 u16 default_headroom_mv;
David Collins8885f792017-01-26 14:36:34 -08001720
1721 /* Boost PD configuration */
1722 lcdb->bst.pd = -EINVAL;
1723 of_property_read_u32(node, "qcom,bst-pd", &lcdb->bst.pd);
1724
1725 lcdb->bst.pd_strength = -EINVAL;
1726 of_property_read_u32(node, "qcom,bst-pd-strength",
1727 &lcdb->bst.pd_strength);
1728
1729 /* Boost ILIM */
1730 lcdb->bst.ilim_ma = -EINVAL;
1731 rc = of_property_read_u32(node, "qcom,bst-ilim-ma", &lcdb->bst.ilim_ma);
1732 if (!rc && !is_between(lcdb->bst.ilim_ma, MIN_BST_ILIM_MA,
1733 MAX_BST_ILIM_MA)) {
1734 pr_err("Invalid ilim_ma %d (min=%d, max=%d)\n",
1735 lcdb->bst.ilim_ma, MIN_BST_ILIM_MA, MAX_BST_ILIM_MA);
1736 return -EINVAL;
1737 }
1738
1739 /* Boost PS configuration */
1740 lcdb->bst.ps = -EINVAL;
1741 of_property_read_u32(node, "qcom,bst-ps", &lcdb->bst.ps);
1742
1743 lcdb->bst.ps_threshold = -EINVAL;
1744 rc = of_property_read_u32(node, "qcom,bst-ps-threshold-ma",
1745 &lcdb->bst.ps_threshold);
1746 if (!rc && !is_between(lcdb->bst.ps_threshold,
1747 MIN_BST_PS_MA, MAX_BST_PS_MA)) {
1748 pr_err("Invalid bst ps_threshold %d (min=%d, max=%d)\n",
1749 lcdb->bst.ps_threshold, MIN_BST_PS_MA, MAX_BST_PS_MA);
1750 return -EINVAL;
1751 }
1752
Kiran Gunda414471a2017-12-07 12:50:51 +05301753 default_headroom_mv = (pmic_subtype == PM660L_SUBTYPE) ?
1754 PM660_BST_HEADROOM_DEFAULT_MV :
1755 BST_HEADROOM_DEFAULT_MV;
Kiran Gundabcfca132017-08-08 16:58:47 +05301756 /* Boost head room configuration */
1757 of_property_read_u16(node, "qcom,bst-headroom-mv",
1758 &lcdb->bst.headroom_mv);
Kiran Gunda414471a2017-12-07 12:50:51 +05301759 if (lcdb->bst.headroom_mv < default_headroom_mv)
1760 lcdb->bst.headroom_mv = default_headroom_mv;
Kiran Gundabcfca132017-08-08 16:58:47 +05301761
David Collins8885f792017-01-26 14:36:34 -08001762 return 0;
1763}
1764
1765static int qpnp_lcdb_init_ldo(struct qpnp_lcdb *lcdb)
1766{
1767 int rc = 0, ilim_ma;
1768 u8 val = 0;
1769
1770 /* configure parameters only if LCDB is disabled */
1771 if (!is_lcdb_enabled(lcdb)) {
1772 if (lcdb->ldo.voltage_mv != -EINVAL) {
1773 rc = qpnp_lcdb_set_voltage(lcdb,
1774 lcdb->ldo.voltage_mv, LDO);
1775 if (rc < 0) {
1776 pr_err("Failed to set voltage rc=%d\n", rc);
1777 return rc;
1778 }
1779 }
1780
1781 if (lcdb->ldo.pd != -EINVAL) {
1782 rc = qpnp_lcdb_masked_write(lcdb, lcdb->base +
1783 LCDB_LDO_PD_CTL_REG, LDO_DIS_PULLDOWN_BIT,
1784 lcdb->ldo.pd ? 0 : LDO_DIS_PULLDOWN_BIT);
1785 if (rc < 0) {
1786 pr_err("Failed to configure LDO PD rc=%d\n",
1787 rc);
1788 return rc;
1789 }
1790 }
1791
1792 if (lcdb->ldo.pd_strength != -EINVAL) {
1793 rc = qpnp_lcdb_masked_write(lcdb, lcdb->base +
1794 LCDB_LDO_PD_CTL_REG, LDO_PD_STRENGTH_BIT,
1795 lcdb->ldo.pd_strength ?
1796 LDO_PD_STRENGTH_BIT : 0);
1797 if (rc < 0) {
1798 pr_err("Failed to configure LDO PD strength %s rc=%d",
1799 lcdb->ldo.pd_strength ?
1800 "(strong)" : "(weak)", rc);
1801 return rc;
1802 }
1803 }
1804
1805 if (lcdb->ldo.ilim_ma != -EINVAL) {
1806 ilim_ma = lcdb->ldo.ilim_ma - MIN_LDO_ILIM_MA;
1807 ilim_ma /= LDO_ILIM_STEP_MA;
1808 val = (ilim_ma & SET_LDO_ILIM_MASK) | EN_LDO_ILIM_BIT;
1809 rc = qpnp_lcdb_masked_write(lcdb, lcdb->base +
1810 LCDB_LDO_ILIM_CTL1_REG,
1811 SET_LDO_ILIM_MASK | EN_LDO_ILIM_BIT,
1812 val);
1813 if (rc < 0) {
1814 pr_err("Failed to configure LDO ilim_ma (CTL1=%d) rc=%d",
1815 val, rc);
1816 return rc;
1817 }
1818
1819 val = ilim_ma & SET_LDO_ILIM_MASK;
1820 rc = qpnp_lcdb_masked_write(lcdb,
1821 lcdb->base + LCDB_LDO_ILIM_CTL2_REG,
1822 SET_LDO_ILIM_MASK, val);
1823 if (rc < 0) {
1824 pr_err("Failed to configure LDO ilim_ma (CTL2=%d) rc=%d",
1825 val, rc);
1826 return rc;
1827 }
1828 }
1829
1830 if (lcdb->ldo.soft_start_us != -EINVAL) {
1831 rc = qpnp_lcdb_set_soft_start(lcdb,
1832 lcdb->ldo.soft_start_us, LDO);
1833 if (rc < 0) {
1834 pr_err("Failed to set LDO soft_start rc=%d\n",
1835 rc);
1836 return rc;
1837 }
1838 }
1839 }
1840
1841 rc = qpnp_lcdb_get_voltage(lcdb, &lcdb->ldo.voltage_mv, LDO);
1842 if (rc < 0) {
1843 pr_err("Failed to get LDO volatge rc=%d\n", rc);
1844 return rc;
1845 }
1846
Kiran Gunda08368b32018-09-10 18:04:43 +05301847 lcdb->ldo.prev_voltage_mv = lcdb->ldo.voltage_mv;
1848
David Collins8885f792017-01-26 14:36:34 -08001849 rc = qpnp_lcdb_read(lcdb, lcdb->base +
1850 LCDB_LDO_VREG_OK_CTL_REG, &val, 1);
1851 if (rc < 0) {
1852 pr_err("Failed to read ldo_vreg_ok rc=%d\n", rc);
1853 return rc;
1854 }
1855 lcdb->ldo.vreg_ok_dbc_us = dbc_us[val & VREG_OK_DEB_MASK];
1856
1857 rc = qpnp_lcdb_read(lcdb, lcdb->base +
1858 LCDB_LDO_SOFT_START_CTL_REG, &val, 1);
1859 if (rc < 0) {
1860 pr_err("Failed to read ldo_soft_start_ctl rc=%d\n", rc);
1861 return rc;
1862 }
1863 lcdb->ldo.soft_start_us = soft_start_us[val & SOFT_START_MASK];
1864
1865 rc = qpnp_lcdb_regulator_register(lcdb, LDO);
1866 if (rc < 0)
1867 pr_err("Failed to register ldo rc=%d\n", rc);
1868
1869 return rc;
1870}
1871
1872static int qpnp_lcdb_init_ncp(struct qpnp_lcdb *lcdb)
1873{
1874 int rc = 0, i = 0;
1875 u8 val = 0;
1876
1877 /* configure parameters only if LCDB is disabled */
1878 if (!is_lcdb_enabled(lcdb)) {
1879 if (lcdb->ncp.voltage_mv != -EINVAL) {
1880 rc = qpnp_lcdb_set_voltage(lcdb,
1881 lcdb->ncp.voltage_mv, NCP);
1882 if (rc < 0) {
1883 pr_err("Failed to set voltage rc=%d\n", rc);
1884 return rc;
1885 }
1886 }
1887
1888 if (lcdb->ncp.pd != -EINVAL) {
1889 rc = qpnp_lcdb_masked_write(lcdb, lcdb->base +
1890 LCDB_NCP_PD_CTL_REG, NCP_DIS_PULLDOWN_BIT,
1891 lcdb->ncp.pd ? 0 : NCP_DIS_PULLDOWN_BIT);
1892 if (rc < 0) {
1893 pr_err("Failed to configure NCP PD rc=%d\n",
1894 rc);
1895 return rc;
1896 }
1897 }
1898
1899 if (lcdb->ncp.pd_strength != -EINVAL) {
1900 rc = qpnp_lcdb_masked_write(lcdb, lcdb->base +
1901 LCDB_NCP_PD_CTL_REG, NCP_PD_STRENGTH_BIT,
1902 lcdb->ncp.pd_strength ?
1903 NCP_PD_STRENGTH_BIT : 0);
1904 if (rc < 0) {
1905 pr_err("Failed to configure NCP PD strength %s rc=%d",
1906 lcdb->ncp.pd_strength ?
1907 "(strong)" : "(weak)", rc);
1908 return rc;
1909 }
1910 }
1911
1912 if (lcdb->ncp.ilim_ma != -EINVAL) {
1913 while (lcdb->ncp.ilim_ma > ncp_ilim_ma[i])
1914 i++;
1915 val = (i == 0) ? 0 : i - 1;
1916 val = (lcdb->ncp.ilim_ma & SET_NCP_ILIM_MASK) |
1917 EN_NCP_ILIM_BIT;
1918 rc = qpnp_lcdb_masked_write(lcdb, lcdb->base +
1919 LCDB_NCP_ILIM_CTL1_REG,
1920 SET_NCP_ILIM_MASK | EN_NCP_ILIM_BIT, val);
1921 if (rc < 0) {
1922 pr_err("Failed to configure NCP ilim_ma (CTL1=%d) rc=%d",
1923 val, rc);
1924 return rc;
1925 }
1926 val = lcdb->ncp.ilim_ma & SET_NCP_ILIM_MASK;
1927 rc = qpnp_lcdb_masked_write(lcdb,
1928 lcdb->base + LCDB_NCP_ILIM_CTL2_REG,
1929 SET_NCP_ILIM_MASK, val);
1930 if (rc < 0) {
1931 pr_err("Failed to configure NCP ilim_ma (CTL2=%d) rc=%d",
1932 val, rc);
1933 return rc;
1934 }
1935 }
1936
1937 if (lcdb->ncp.soft_start_us != -EINVAL) {
1938 rc = qpnp_lcdb_set_soft_start(lcdb,
1939 lcdb->ncp.soft_start_us, NCP);
1940 if (rc < 0) {
1941 pr_err("Failed to set NCP soft_start rc=%d\n",
1942 rc);
1943 return rc;
1944 }
1945 }
1946 }
1947
1948 rc = qpnp_lcdb_get_voltage(lcdb, &lcdb->ncp.voltage_mv, NCP);
1949 if (rc < 0) {
1950 pr_err("Failed to get NCP volatge rc=%d\n", rc);
1951 return rc;
1952 }
1953
Kiran Gunda08368b32018-09-10 18:04:43 +05301954 lcdb->ncp.prev_voltage_mv = lcdb->ncp.voltage_mv;
1955
David Collins8885f792017-01-26 14:36:34 -08001956 rc = qpnp_lcdb_read(lcdb, lcdb->base +
1957 LCDB_NCP_VREG_OK_CTL_REG, &val, 1);
1958 if (rc < 0) {
1959 pr_err("Failed to read ncp_vreg_ok rc=%d\n", rc);
1960 return rc;
1961 }
1962 lcdb->ncp.vreg_ok_dbc_us = dbc_us[val & VREG_OK_DEB_MASK];
1963
1964 rc = qpnp_lcdb_read(lcdb, lcdb->base +
1965 LCDB_NCP_SOFT_START_CTL_REG, &val, 1);
1966 if (rc < 0) {
1967 pr_err("Failed to read ncp_soft_start_ctl rc=%d\n", rc);
1968 return rc;
1969 }
1970 lcdb->ncp.soft_start_us = soft_start_us[val & SOFT_START_MASK];
1971
1972 rc = qpnp_lcdb_regulator_register(lcdb, NCP);
1973 if (rc < 0)
1974 pr_err("Failed to register NCP rc=%d\n", rc);
1975
1976 return rc;
1977}
1978
1979static int qpnp_lcdb_init_bst(struct qpnp_lcdb *lcdb)
1980{
1981 int rc = 0;
Kiran Gunda414471a2017-12-07 12:50:51 +05301982 u8 val, mask = 0;
1983 u16 pmic_subtype = lcdb->pmic_rev_id->pmic_subtype;
David Collins8885f792017-01-26 14:36:34 -08001984
1985 /* configure parameters only if LCDB is disabled */
1986 if (!is_lcdb_enabled(lcdb)) {
1987 if (lcdb->bst.pd != -EINVAL) {
1988 rc = qpnp_lcdb_masked_write(lcdb, lcdb->base +
1989 LCDB_BST_PD_CTL_REG, BOOST_DIS_PULLDOWN_BIT,
1990 lcdb->bst.pd ? 0 : BOOST_DIS_PULLDOWN_BIT);
1991 if (rc < 0) {
1992 pr_err("Failed to configure BST PD rc=%d\n",
1993 rc);
1994 return rc;
1995 }
1996 }
1997
1998 if (lcdb->bst.pd_strength != -EINVAL) {
1999 rc = qpnp_lcdb_masked_write(lcdb, lcdb->base +
Kiran Gunda64a1d802018-09-07 18:06:44 +05302000 LCDB_BST_PD_CTL_REG, BOOST_PD_STRENGTH_BIT,
David Collins8885f792017-01-26 14:36:34 -08002001 lcdb->bst.pd_strength ?
2002 BOOST_PD_STRENGTH_BIT : 0);
2003 if (rc < 0) {
2004 pr_err("Failed to configure NCP PD strength %s rc=%d",
2005 lcdb->bst.pd_strength ?
2006 "(strong)" : "(weak)", rc);
2007 return rc;
2008 }
2009 }
2010
2011 if (lcdb->bst.ilim_ma != -EINVAL) {
2012 val = (lcdb->bst.ilim_ma / MIN_BST_ILIM_MA) - 1;
2013 val = (lcdb->bst.ilim_ma & SET_BST_ILIM_MASK) |
2014 EN_BST_ILIM_BIT;
2015 rc = qpnp_lcdb_masked_write(lcdb, lcdb->base +
2016 LCDB_BST_ILIM_CTL_REG,
2017 SET_BST_ILIM_MASK | EN_BST_ILIM_BIT, val);
2018 if (rc < 0) {
2019 pr_err("Failed to configure BST ilim_ma rc=%d",
2020 rc);
2021 return rc;
2022 }
2023 }
2024
2025 if (lcdb->bst.ps != -EINVAL) {
2026 rc = qpnp_lcdb_masked_write(lcdb, lcdb->base +
2027 LCDB_PS_CTL_REG, EN_PS_BIT,
Kiran Gunda51cbdc02019-10-23 19:29:15 +05302028 lcdb->bst.ps ? EN_PS_BIT : 0);
David Collins8885f792017-01-26 14:36:34 -08002029 if (rc < 0) {
2030 pr_err("Failed to disable BST PS rc=%d", rc);
2031 return rc;
2032 }
2033 }
2034
2035 if (lcdb->bst.ps_threshold != -EINVAL) {
Kiran Gunda414471a2017-12-07 12:50:51 +05302036 mask = (pmic_subtype == PM660L_SUBTYPE) ?
2037 PM660_PS_THRESH_MASK : PS_THRESH_MASK;
David Collins8885f792017-01-26 14:36:34 -08002038 val = (lcdb->bst.ps_threshold - MIN_BST_PS_MA) / 10;
Kiran Gunda414471a2017-12-07 12:50:51 +05302039 val = (lcdb->bst.ps_threshold & mask) | EN_PS_BIT;
David Collins8885f792017-01-26 14:36:34 -08002040 rc = qpnp_lcdb_masked_write(lcdb, lcdb->base +
2041 LCDB_PS_CTL_REG,
Kiran Gunda414471a2017-12-07 12:50:51 +05302042 mask | EN_PS_BIT, val);
David Collins8885f792017-01-26 14:36:34 -08002043 if (rc < 0) {
2044 pr_err("Failed to configure BST PS threshold rc=%d",
2045 rc);
2046 return rc;
2047 }
2048 }
2049 }
2050
2051 rc = qpnp_lcdb_get_voltage(lcdb, &lcdb->bst.voltage_mv, BST);
2052 if (rc < 0) {
2053 pr_err("Failed to get BST volatge rc=%d\n", rc);
2054 return rc;
2055 }
2056
2057 rc = qpnp_lcdb_read(lcdb, lcdb->base +
2058 LCDB_BST_VREG_OK_CTL_REG, &val, 1);
2059 if (rc < 0) {
2060 pr_err("Failed to read bst_vreg_ok rc=%d\n", rc);
2061 return rc;
2062 }
2063 lcdb->bst.vreg_ok_dbc_us = dbc_us[val & VREG_OK_DEB_MASK];
2064
Kiran Gunda414471a2017-12-07 12:50:51 +05302065 if (pmic_subtype == PM660L_SUBTYPE) {
2066 rc = qpnp_lcdb_read(lcdb, lcdb->base +
2067 LCDB_SOFT_START_CTL_REG, &val, 1);
2068 if (rc < 0) {
2069 pr_err("Failed to read lcdb_soft_start_ctl rc=%d\n",
2070 rc);
2071 return rc;
2072 }
2073 lcdb->bst.soft_start_us = (val & SOFT_START_MASK) * 200 + 200;
Subbaraman Narayanamurthy841eb432018-04-10 13:20:56 -07002074 if (!lcdb->bst.headroom_mv)
2075 lcdb->bst.headroom_mv = PM660_BST_HEADROOM_DEFAULT_MV;
Kiran Gunda414471a2017-12-07 12:50:51 +05302076 } else {
2077 rc = qpnp_lcdb_read(lcdb, lcdb->base +
2078 LCDB_BST_SS_CTL_REG, &val, 1);
2079 if (rc < 0) {
2080 pr_err("Failed to read bst_soft_start_ctl rc=%d\n", rc);
2081 return rc;
2082 }
2083 lcdb->bst.soft_start_us = soft_start_us[val & SOFT_START_MASK];
Subbaraman Narayanamurthy841eb432018-04-10 13:20:56 -07002084 if (!lcdb->bst.headroom_mv)
2085 lcdb->bst.headroom_mv = BST_HEADROOM_DEFAULT_MV;
David Collins8885f792017-01-26 14:36:34 -08002086 }
Kiran Gundabcfca132017-08-08 16:58:47 +05302087
David Collins8885f792017-01-26 14:36:34 -08002088 return 0;
2089}
2090
Kiran Gundaa7228922018-06-27 11:14:21 +05302091static void qpnp_lcdb_pmic_config(struct qpnp_lcdb *lcdb)
2092{
2093 switch (lcdb->pmic_rev_id->pmic_subtype) {
2094 case PM660L_SUBTYPE:
2095 if (lcdb->pmic_rev_id->rev4 < PM660L_V2P0_REV4)
2096 lcdb->wa_flags |= NCP_SCP_DISABLE_WA;
2097 break;
Kiran Gundac390a892019-01-23 13:12:06 +05302098 case PMI632_SUBTYPE:
2099 case PM855L_SUBTYPE:
2100 lcdb->wa_flags |= FORCE_PD_ENABLE_WA;
2101 break;
Kiran Gundaa7228922018-06-27 11:14:21 +05302102 default:
2103 break;
2104 }
2105
2106 pr_debug("LCDB wa_flags = 0x%2x\n", lcdb->wa_flags);
2107}
2108
David Collins8885f792017-01-26 14:36:34 -08002109static int qpnp_lcdb_hw_init(struct qpnp_lcdb *lcdb)
2110{
2111 int rc = 0;
2112 u8 val = 0;
2113
Kiran Gundaa7228922018-06-27 11:14:21 +05302114 qpnp_lcdb_pmic_config(lcdb);
2115
Kiran Gundac390a892019-01-23 13:12:06 +05302116 if (lcdb->pwrdn_delay_ms != -EINVAL) {
2117 rc = qpnp_lcdb_masked_write(lcdb, lcdb->base +
2118 LCDB_PWRUP_PWRDN_CTL_REG,
2119 PWRDN_DELAY_MASK,
2120 lcdb->pwrdn_delay_ms);
2121 if (rc < 0)
2122 return rc;
2123 }
2124
David Collins8885f792017-01-26 14:36:34 -08002125 rc = qpnp_lcdb_init_bst(lcdb);
2126 if (rc < 0) {
2127 pr_err("Failed to initialize BOOST rc=%d\n", rc);
2128 return rc;
2129 }
2130
2131 rc = qpnp_lcdb_init_ldo(lcdb);
2132 if (rc < 0) {
2133 pr_err("Failed to initialize LDO rc=%d\n", rc);
2134 return rc;
2135 }
2136
2137 rc = qpnp_lcdb_init_ncp(lcdb);
2138 if (rc < 0) {
2139 pr_err("Failed to initialize NCP rc=%d\n", rc);
2140 return rc;
2141 }
2142
Kiran Gundaa7228922018-06-27 11:14:21 +05302143 if (lcdb->sc_irq >= 0 && !(lcdb->wa_flags & NCP_SCP_DISABLE_WA)) {
Anirudh Ghayal264f9272017-03-05 22:34:37 +05302144 lcdb->sc_count = 0;
Kavya Nunna80bc1502018-10-01 14:50:23 +05302145 irq_set_status_flags(lcdb->sc_irq,
2146 IRQ_DISABLE_UNLAZY);
Anirudh Ghayal264f9272017-03-05 22:34:37 +05302147 rc = devm_request_threaded_irq(lcdb->dev, lcdb->sc_irq,
2148 NULL, qpnp_lcdb_sc_irq_handler, IRQF_ONESHOT,
2149 "qpnp_lcdb_sc_irq", lcdb);
2150 if (rc < 0) {
2151 pr_err("Unable to request sc(%d) irq rc=%d\n",
2152 lcdb->sc_irq, rc);
2153 return rc;
2154 }
2155 }
2156
David Collins8885f792017-01-26 14:36:34 -08002157 if (!is_lcdb_enabled(lcdb)) {
2158 rc = qpnp_lcdb_read(lcdb, lcdb->base +
2159 LCDB_MODULE_RDY_REG, &val, 1);
2160 if (rc < 0) {
2161 pr_err("Failed to read MODULE_RDY rc=%d\n", rc);
2162 return rc;
2163 }
2164 if (!(val & MODULE_RDY_BIT)) {
2165 rc = qpnp_lcdb_masked_write(lcdb, lcdb->base +
2166 LCDB_MODULE_RDY_REG, MODULE_RDY_BIT,
2167 MODULE_RDY_BIT);
2168 if (rc < 0) {
2169 pr_err("Failed to set MODULE RDY rc=%d\n", rc);
2170 return rc;
2171 }
2172 }
2173 } else {
2174 /* module already enabled */
2175 lcdb->lcdb_enabled = true;
2176 }
2177
2178 return 0;
2179}
2180
2181static int qpnp_lcdb_parse_dt(struct qpnp_lcdb *lcdb)
2182{
Kiran Gundac390a892019-01-23 13:12:06 +05302183 int rc = 0, i = 0;
2184 u32 tmp;
David Collins8885f792017-01-26 14:36:34 -08002185 const char *label;
Anirudh Ghayal968862c2017-03-31 15:34:05 +05302186 struct device_node *revid_dev_node, *temp, *node = lcdb->dev->of_node;
David Collins8885f792017-01-26 14:36:34 -08002187
Anirudh Ghayal968862c2017-03-31 15:34:05 +05302188 revid_dev_node = of_parse_phandle(node, "qcom,pmic-revid", 0);
2189 if (!revid_dev_node) {
2190 pr_err("Missing qcom,pmic-revid property - fail driver\n");
2191 return -EINVAL;
2192 }
2193
2194 lcdb->pmic_rev_id = get_revid_data(revid_dev_node);
2195 if (IS_ERR(lcdb->pmic_rev_id)) {
2196 pr_debug("Unable to get revid data\n");
2197 /*
2198 * revid should to be defined, return -EPROBE_DEFER
2199 * until the revid module registers.
2200 */
2201 of_node_put(revid_dev_node);
2202 return -EPROBE_DEFER;
2203 }
2204
2205 of_node_put(revid_dev_node);
Kiran Gunda08368b32018-09-10 18:04:43 +05302206
David Collins8885f792017-01-26 14:36:34 -08002207 for_each_available_child_of_node(node, temp) {
2208 rc = of_property_read_string(temp, "label", &label);
2209 if (rc < 0) {
2210 pr_err("Failed to read label rc=%d\n", rc);
2211 return rc;
2212 }
2213
2214 if (!strcmp(label, "ldo")) {
2215 lcdb->ldo.node = temp;
2216 rc = qpnp_lcdb_ldo_dt_init(lcdb);
2217 } else if (!strcmp(label, "ncp")) {
2218 lcdb->ncp.node = temp;
2219 rc = qpnp_lcdb_ncp_dt_init(lcdb);
2220 } else if (!strcmp(label, "bst")) {
2221 lcdb->bst.node = temp;
2222 rc = qpnp_lcdb_bst_dt_init(lcdb);
2223 } else {
2224 pr_err("Failed to identify label %s\n", label);
2225 return -EINVAL;
2226 }
2227 if (rc < 0) {
2228 pr_err("Failed to register %s module\n", label);
2229 return rc;
2230 }
2231 }
2232
David Collins8885f792017-01-26 14:36:34 -08002233 if (of_property_read_bool(node, "qcom,ttw-enable")) {
2234 rc = qpnp_lcdb_parse_ttw(lcdb);
2235 if (rc < 0) {
2236 pr_err("Failed to parse ttw-params rc=%d\n", rc);
2237 return rc;
2238 }
2239 lcdb->ttw_enable = true;
2240 }
2241
Anirudh Ghayal264f9272017-03-05 22:34:37 +05302242 lcdb->sc_irq = platform_get_irq_byname(lcdb->pdev, "sc-irq");
2243 if (lcdb->sc_irq < 0)
2244 pr_debug("sc irq is not defined\n");
2245
Kiran Gunda08368b32018-09-10 18:04:43 +05302246 lcdb->voltage_step_ramp =
2247 of_property_read_bool(node, "qcom,voltage-step-ramp");
2248
Kiran Gundac390a892019-01-23 13:12:06 +05302249 lcdb->pwrdn_delay_ms = -EINVAL;
2250 rc = of_property_read_u32(node, "qcom,pwrdn-delay-ms", &tmp);
2251 if (!rc) {
2252 if (!is_between(tmp, PWRDN_DELAY_MIN_MS, PWRDN_DELAY_MAX_MS)) {
2253 pr_err("Invalid PWRDN_DLY val %d (min=%d max=%d)\n",
2254 tmp, PWRDN_DELAY_MIN_MS, PWRDN_DELAY_MAX_MS);
2255 return -EINVAL;
2256 }
2257
2258 for (i = 0; i < ARRAY_SIZE(pwrup_pwrdn_ms); i++) {
2259 if (tmp == pwrup_pwrdn_ms[i]) {
2260 lcdb->pwrdn_delay_ms = i;
2261 break;
2262 }
2263 }
2264 }
2265
2266 return 0;
David Collins8885f792017-01-26 14:36:34 -08002267}
2268
Kavya Nunna80bc1502018-10-01 14:50:23 +05302269static ssize_t qpnp_lcdb_irq_control(struct class *c,
2270 struct class_attribute *attr,
2271 const char *buf, size_t count)
2272{
2273 struct qpnp_lcdb *lcdb = container_of(c, struct qpnp_lcdb,
2274 lcdb_class);
2275 int val, rc;
2276
2277 rc = kstrtouint(buf, 0, &val);
2278
2279 if (rc < 0)
2280 return rc;
2281
2282 if (val != 0 && val != 1)
2283 return count;
2284
2285 if (val == 1 && !lcdb->secure_mode) {
2286 if (lcdb->sc_irq > 0)
2287 disable_irq(lcdb->sc_irq);
2288
2289 lcdb->secure_mode = true;
2290 } else if (val == 0 && lcdb->secure_mode) {
2291
2292 if (lcdb->sc_irq > 0)
2293 enable_irq(lcdb->sc_irq);
2294
2295 lcdb->secure_mode = false;
2296 }
2297
2298 return count;
2299}
2300
2301static struct class_attribute lcdb_attributes[] = {
2302 [0] = __ATTR(secure_mode, 0664, NULL,
2303 qpnp_lcdb_irq_control),
2304 __ATTR_NULL,
2305};
2306
David Collins8885f792017-01-26 14:36:34 -08002307static int qpnp_lcdb_regulator_probe(struct platform_device *pdev)
2308{
2309 int rc;
2310 struct device_node *node;
2311 struct qpnp_lcdb *lcdb;
jialongjhan7dfbf872020-04-21 20:24:23 +08002312 //[Arima][8901][Jialongjhan]Add delay time between VSN and VSP 20191104 Start
2313 u8 val = 0xF; // 0xF==1111==VSN delay 8ms; VSP delay 8ms
2314 //[Arima][8901][Jialongjhan]Add delay time between VSN and VSP 20191104 End
David Collins8885f792017-01-26 14:36:34 -08002315
2316 node = pdev->dev.of_node;
2317 if (!node) {
2318 pr_err("No nodes defined\n");
2319 return -ENODEV;
2320 }
2321
2322 lcdb = devm_kzalloc(&pdev->dev, sizeof(*lcdb), GFP_KERNEL);
2323 if (!lcdb)
2324 return -ENOMEM;
2325
2326 rc = of_property_read_u32(node, "reg", &lcdb->base);
2327 if (rc < 0) {
2328 pr_err("Failed to find reg node rc=%d\n", rc);
2329 return rc;
2330 }
2331
2332 lcdb->regmap = dev_get_regmap(pdev->dev.parent, NULL);
2333 if (!lcdb->regmap) {
2334 pr_err("Failed to get the regmap handle rc=%d\n", rc);
2335 return -EINVAL;
2336 }
2337
2338 lcdb->dev = &pdev->dev;
2339 lcdb->pdev = pdev;
2340 mutex_init(&lcdb->lcdb_mutex);
2341 mutex_init(&lcdb->read_write_mutex);
2342
2343 rc = qpnp_lcdb_parse_dt(lcdb);
2344 if (rc < 0) {
2345 pr_err("Failed to parse dt rc=%d\n", rc);
2346 return rc;
2347 }
2348
Kavya Nunna80bc1502018-10-01 14:50:23 +05302349 lcdb->lcdb_class.name = "lcd_bias";
2350 lcdb->lcdb_class.owner = THIS_MODULE;
2351 lcdb->lcdb_class.class_attrs = lcdb_attributes;
2352
2353 rc = class_register(&lcdb->lcdb_class);
2354 if (rc < 0) {
2355 pr_err("Failed to register lcdb class rc = %d\n", rc);
2356 return rc;
2357 }
2358
David Collins8885f792017-01-26 14:36:34 -08002359 rc = qpnp_lcdb_hw_init(lcdb);
2360 if (rc < 0)
2361 pr_err("Failed to initialize LCDB module rc=%d\n", rc);
2362 else
2363 pr_info("LCDB module successfully registered! lcdb_en=%d ldo_voltage=%dmV ncp_voltage=%dmV bst_voltage=%dmV\n",
2364 lcdb->lcdb_enabled, lcdb->ldo.voltage_mv,
2365 lcdb->ncp.voltage_mv, lcdb->bst.voltage_mv);
2366
jialongjhan7dfbf872020-04-21 20:24:23 +08002367 //[Arima][8901][Jialongjhan]Add delay time between VSN and VSP 20191104 Start
2368 rc = qpnp_lcdb_write(lcdb, lcdb->base + LCDB_PWRUP_PWRDN_CTL_REG , &val, 1);
2369 //[Arima][8901][Jialongjhan]Add delay time between VSN and VSP 20191104 End
2370
David Collins8885f792017-01-26 14:36:34 -08002371 return rc;
2372}
2373
2374static int qpnp_lcdb_regulator_remove(struct platform_device *pdev)
2375{
2376 struct qpnp_lcdb *lcdb = dev_get_drvdata(&pdev->dev);
2377
2378 mutex_destroy(&lcdb->lcdb_mutex);
2379 mutex_destroy(&lcdb->read_write_mutex);
2380
2381 return 0;
2382}
2383
2384static const struct of_device_id lcdb_match_table[] = {
2385 { .compatible = QPNP_LCDB_REGULATOR_DRIVER_NAME, },
2386 { },
2387};
2388
2389static struct platform_driver qpnp_lcdb_regulator_driver = {
2390 .driver = {
2391 .name = QPNP_LCDB_REGULATOR_DRIVER_NAME,
2392 .of_match_table = lcdb_match_table,
2393 },
2394 .probe = qpnp_lcdb_regulator_probe,
2395 .remove = qpnp_lcdb_regulator_remove,
2396};
2397
2398static int __init qpnp_lcdb_regulator_init(void)
2399{
2400 return platform_driver_register(&qpnp_lcdb_regulator_driver);
2401}
2402arch_initcall(qpnp_lcdb_regulator_init);
2403
2404static void __exit qpnp_lcdb_regulator_exit(void)
2405{
2406 platform_driver_unregister(&qpnp_lcdb_regulator_driver);
2407}
2408module_exit(qpnp_lcdb_regulator_exit);
2409
2410MODULE_DESCRIPTION("QPNP LCDB regulator driver");
2411MODULE_LICENSE("GPL v2");