blob: 0a2d0f59f1036b71907852e0fa22a173c5ecf9ea [file] [log] [blame]
Harry Yang4b7db0f2017-11-27 10:50:44 -08001/* Copyright (c) 2018 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#include <linux/debugfs.h>
14#include <linux/delay.h>
15#include <linux/device.h>
16#include <linux/module.h>
17#include <linux/platform_device.h>
18#include <linux/regmap.h>
19#include <linux/power_supply.h>
20#include <linux/of.h>
21#include <linux/of_irq.h>
22#include <linux/log2.h>
23#include <linux/qpnp/qpnp-revid.h>
24#include <linux/regulator/driver.h>
25#include <linux/regulator/of_regulator.h>
26#include <linux/regulator/machine.h>
27#include <linux/pmic-voter.h>
Ashay Jaiswal20688262018-04-25 11:45:34 +053028#include <linux/qpnp/qpnp-adc.h>
Harry Yang4b7db0f2017-11-27 10:50:44 -080029#include "smb5-reg.h"
30#include "smb5-lib.h"
Ashay Jaiswal09feab82018-02-12 12:33:18 +053031#include "schgm-flash.h"
Harry Yang4b7db0f2017-11-27 10:50:44 -080032
Ashay Jaiswala9e10912018-02-02 14:03:35 +053033static struct smb_params smb5_pmi632_params = {
34 .fcc = {
35 .name = "fast charge current",
36 .reg = CHGR_FAST_CHARGE_CURRENT_CFG_REG,
37 .min_u = 0,
38 .max_u = 3000000,
39 .step_u = 50000,
40 },
41 .fv = {
42 .name = "float voltage",
43 .reg = CHGR_FLOAT_VOLTAGE_CFG_REG,
44 .min_u = 3600000,
45 .max_u = 4800000,
46 .step_u = 10000,
47 },
48 .usb_icl = {
49 .name = "usb input current limit",
50 .reg = USBIN_CURRENT_LIMIT_CFG_REG,
51 .min_u = 0,
52 .max_u = 3000000,
53 .step_u = 50000,
54 },
Harry Yangf7b89902018-03-13 22:37:53 -070055 .icl_max_stat = {
56 .name = "dcdc icl max status",
57 .reg = ICL_MAX_STATUS_REG,
58 .min_u = 0,
59 .max_u = 3000000,
60 .step_u = 50000,
61 },
Ashay Jaiswala9e10912018-02-02 14:03:35 +053062 .icl_stat = {
63 .name = "input current limit status",
Ashay Jaiswal0de6fb92018-06-12 17:23:45 +053064 .reg = ICL_STATUS_REG,
Ashay Jaiswala9e10912018-02-02 14:03:35 +053065 .min_u = 0,
66 .max_u = 3000000,
67 .step_u = 50000,
68 },
69 .otg_cl = {
70 .name = "usb otg current limit",
71 .reg = DCDC_OTG_CURRENT_LIMIT_CFG_REG,
72 .min_u = 500000,
73 .max_u = 1000000,
74 .step_u = 250000,
75 },
76 .jeita_cc_comp_hot = {
77 .name = "jeita fcc reduction",
78 .reg = JEITA_CCCOMP_CFG_HOT_REG,
79 .min_u = 0,
80 .max_u = 1575000,
81 .step_u = 25000,
82 },
83 .jeita_cc_comp_cold = {
84 .name = "jeita fcc reduction",
85 .reg = JEITA_CCCOMP_CFG_COLD_REG,
86 .min_u = 0,
87 .max_u = 1575000,
88 .step_u = 25000,
89 },
90 .freq_switcher = {
91 .name = "switching frequency",
92 .reg = DCDC_FSW_SEL_REG,
93 .min_u = 600,
94 .max_u = 1200,
95 .step_u = 400,
96 .set_proc = smblib_set_chg_freq,
97 },
Ashay Jaiswale0b3c472018-06-20 23:39:41 +053098 .aicl_5v_threshold = {
99 .name = "AICL 5V threshold",
100 .reg = USBIN_5V_AICL_THRESHOLD_REG,
101 .min_u = 4000,
102 .max_u = 4700,
103 .step_u = 100,
104 },
105 .aicl_cont_threshold = {
106 .name = "AICL CONT threshold",
107 .reg = USBIN_CONT_AICL_THRESHOLD_REG,
108 .min_u = 4000,
109 .max_u = 8800,
110 .step_u = 100,
111 .get_proc = smblib_get_aicl_cont_threshold,
112 .set_proc = smblib_set_aicl_cont_threshold,
113 },
Ashay Jaiswala9e10912018-02-02 14:03:35 +0530114};
115
Harry Yangf7b89902018-03-13 22:37:53 -0700116static struct smb_params smb5_pm855b_params = {
Harry Yang4b7db0f2017-11-27 10:50:44 -0800117 .fcc = {
118 .name = "fast charge current",
119 .reg = CHGR_FAST_CHARGE_CURRENT_CFG_REG,
120 .min_u = 0,
121 .max_u = 8000000,
122 .step_u = 25000,
123 },
124 .fv = {
125 .name = "float voltage",
126 .reg = CHGR_FLOAT_VOLTAGE_CFG_REG,
127 .min_u = 3600000,
128 .max_u = 4790000,
129 .step_u = 10000,
130 },
131 .usb_icl = {
132 .name = "usb input current limit",
133 .reg = USBIN_CURRENT_LIMIT_CFG_REG,
134 .min_u = 0,
135 .max_u = 5000000,
136 .step_u = 50000,
137 },
Harry Yangf7b89902018-03-13 22:37:53 -0700138 .icl_max_stat = {
139 .name = "dcdc icl max status",
140 .reg = ICL_MAX_STATUS_REG,
141 .min_u = 0,
142 .max_u = 5000000,
143 .step_u = 50000,
144 },
Harry Yang4b7db0f2017-11-27 10:50:44 -0800145 .icl_stat = {
Harry Yangf7b89902018-03-13 22:37:53 -0700146 .name = "aicl icl status",
Harry Yang4b7db0f2017-11-27 10:50:44 -0800147 .reg = AICL_ICL_STATUS_REG,
148 .min_u = 0,
149 .max_u = 5000000,
150 .step_u = 50000,
151 },
152 .otg_cl = {
153 .name = "usb otg current limit",
154 .reg = DCDC_OTG_CURRENT_LIMIT_CFG_REG,
155 .min_u = 500000,
156 .max_u = 3000000,
157 .step_u = 500000,
158 },
159 .jeita_cc_comp_hot = {
160 .name = "jeita fcc reduction",
161 .reg = JEITA_CCCOMP_CFG_HOT_REG,
162 .min_u = 0,
163 .max_u = 8000000,
164 .step_u = 25000,
165 .set_proc = NULL,
166 },
167 .jeita_cc_comp_cold = {
168 .name = "jeita fcc reduction",
169 .reg = JEITA_CCCOMP_CFG_COLD_REG,
170 .min_u = 0,
171 .max_u = 8000000,
172 .step_u = 25000,
173 .set_proc = NULL,
174 },
175 .freq_switcher = {
176 .name = "switching frequency",
177 .reg = DCDC_FSW_SEL_REG,
178 .min_u = 1200,
179 .max_u = 2400,
180 .step_u = 400,
181 .set_proc = NULL,
182 },
Ashay Jaiswale0b3c472018-06-20 23:39:41 +0530183 .aicl_5v_threshold = {
184 .name = "AICL 5V threshold",
185 .reg = USBIN_5V_AICL_THRESHOLD_REG,
186 .min_u = 4000,
187 .max_u = 4700,
188 .step_u = 100,
189 },
190 .aicl_cont_threshold = {
191 .name = "AICL CONT threshold",
192 .reg = USBIN_CONT_AICL_THRESHOLD_REG,
193 .min_u = 4000,
194 .max_u = 1180,
195 .step_u = 100,
196 .get_proc = smblib_get_aicl_cont_threshold,
197 .set_proc = smblib_set_aicl_cont_threshold,
198 },
Harry Yang4b7db0f2017-11-27 10:50:44 -0800199};
200
201struct smb_dt_props {
202 int usb_icl_ua;
203 struct device_node *revid_dev_node;
204 enum float_options float_option;
205 int chg_inhibit_thr_mv;
206 bool no_battery;
207 bool hvdcp_disable;
Anirudh Ghayal1380d312018-02-23 00:01:43 +0530208 int auto_recharge_soc;
209 int auto_recharge_vbat_mv;
Harry Yang4b7db0f2017-11-27 10:50:44 -0800210 int wd_bark_time;
211 int batt_profile_fcc_ua;
212 int batt_profile_fv_uv;
Guru Das Srinagesh3ca14372018-06-01 11:30:56 -0700213 int term_current_src;
214 int term_current_thresh_hi_ma;
215 int term_current_thresh_lo_ma;
Harry Yang4b7db0f2017-11-27 10:50:44 -0800216};
217
218struct smb5 {
219 struct smb_charger chg;
220 struct dentry *dfs_root;
221 struct smb_dt_props dt;
222};
223
224static int __debug_mask;
225module_param_named(
226 debug_mask, __debug_mask, int, 0600
227);
228
Harry Yang6afaea22018-03-26 19:11:07 -0700229static int __pd_disabled;
230module_param_named(
231 pd_disabled, __pd_disabled, int, 0600
232);
233
Harry Yang4b7db0f2017-11-27 10:50:44 -0800234static int __weak_chg_icl_ua = 500000;
235module_param_named(
236 weak_chg_icl_ua, __weak_chg_icl_ua, int, 0600
237);
238
Ashay Jaiswal20688262018-04-25 11:45:34 +0530239enum {
240 USBIN_CURRENT,
241 USBIN_VOLTAGE,
242};
243
Ashay Jaiswal0de6fb92018-06-12 17:23:45 +0530244enum {
245 BAT_THERM = 0,
246 MISC_THERM,
247 CONN_THERM,
248 SMB_THERM,
249};
250
Ashay Jaiswala9e10912018-02-02 14:03:35 +0530251#define PMI632_MAX_ICL_UA 3000000
252static int smb5_chg_config_init(struct smb5 *chip)
253{
254 struct smb_charger *chg = &chip->chg;
255 struct pmic_revid_data *pmic_rev_id;
256 struct device_node *revid_dev_node;
257 int rc = 0;
258
259 revid_dev_node = of_parse_phandle(chip->chg.dev->of_node,
260 "qcom,pmic-revid", 0);
261 if (!revid_dev_node) {
262 pr_err("Missing qcom,pmic-revid property\n");
263 return -EINVAL;
264 }
265
266 pmic_rev_id = get_revid_data(revid_dev_node);
267 if (IS_ERR_OR_NULL(pmic_rev_id)) {
268 /*
269 * the revid peripheral must be registered, any failure
270 * here only indicates that the rev-id module has not
271 * probed yet.
272 */
273 rc = -EPROBE_DEFER;
274 goto out;
275 }
276
277 switch (pmic_rev_id->pmic_subtype) {
278 case PM855B_SUBTYPE:
279 chip->chg.smb_version = PM855B_SUBTYPE;
Harry Yangf7b89902018-03-13 22:37:53 -0700280 chg->param = smb5_pm855b_params;
Ashay Jaiswala9e10912018-02-02 14:03:35 +0530281 chg->name = "pm855b_charger";
282 break;
283 case PMI632_SUBTYPE:
284 chip->chg.smb_version = PMI632_SUBTYPE;
Umang Agrawal37092142019-01-03 17:08:43 +0530285 chg->wa_flags |= WEAK_ADAPTER_WA | USBIN_OV_WA |
286 CHG_TERMINATION_WA;
Umang Agrawal461e9ea2018-07-05 18:50:13 +0530287 if (pmic_rev_id->rev4 >= 2)
288 chg->wa_flags |= MOISTURE_PROTECTION_WA;
Ashay Jaiswala9e10912018-02-02 14:03:35 +0530289 chg->param = smb5_pmi632_params;
290 chg->use_extcon = true;
291 chg->name = "pmi632_charger";
Ashay Jaiswalc96380de2018-05-16 12:02:36 +0530292 /* PMI632 does not support PD */
Ashay Jaiswalf2ca7092018-05-22 21:33:15 +0530293 chg->pd_not_supported = true;
Ashay Jaiswala9e10912018-02-02 14:03:35 +0530294 chg->hw_max_icl_ua =
295 (chip->dt.usb_icl_ua > 0) ? chip->dt.usb_icl_ua
296 : PMI632_MAX_ICL_UA;
297 chg->chg_freq.freq_5V = 600;
298 chg->chg_freq.freq_6V_8V = 800;
299 chg->chg_freq.freq_9V = 1050;
300 chg->chg_freq.freq_removal = 1050;
301 chg->chg_freq.freq_below_otg_threshold = 800;
302 chg->chg_freq.freq_above_otg_threshold = 800;
303 break;
304 default:
305 pr_err("PMIC subtype %d not supported\n",
306 pmic_rev_id->pmic_subtype);
307 rc = -EINVAL;
308 }
309
310out:
311 of_node_put(revid_dev_node);
312 return rc;
313}
314
Ashay Jaiswal0de6fb92018-06-12 17:23:45 +0530315#define PULL_NO_PULL 0
316#define PULL_30K 30
317#define PULL_100K 100
318#define PULL_400K 400
319static int get_valid_pullup(int pull_up)
320{
321 int pull;
322
323 /* pull up can only be 0/30K/100K/400K) */
324 switch (pull_up) {
325 case PULL_NO_PULL:
326 pull = INTERNAL_PULL_NO_PULL;
327 break;
328 case PULL_30K:
329 pull = INTERNAL_PULL_30K_PULL;
330 break;
331 case PULL_100K:
332 pull = INTERNAL_PULL_100K_PULL;
333 break;
334 case PULL_400K:
335 pull = INTERNAL_PULL_400K_PULL;
336 break;
337 default:
338 pull = INTERNAL_PULL_100K_PULL;
339 }
340
341 return pull;
342}
343
344#define INTERNAL_PULL_UP_MASK 0x3
345static int smb5_configure_internal_pull(struct smb_charger *chg, int type,
346 int pull)
347{
348 int rc;
349 int shift = type * 2;
350 u8 mask = INTERNAL_PULL_UP_MASK << shift;
351 u8 val = pull << shift;
352
353 rc = smblib_masked_write(chg, BATIF_ADC_INTERNAL_PULL_UP_REG,
354 mask, val);
355 if (rc < 0)
356 dev_err(chg->dev,
357 "Couldn't configure ADC pull-up reg rc=%d\n", rc);
358
359 return rc;
360}
361
Harry Yang4b7db0f2017-11-27 10:50:44 -0800362#define MICRO_1P5A 1500000
Ashay Jaiswalb2b06fe2018-06-07 18:35:21 +0530363#define MICRO_1PA 1000000
Harry Yang4b7db0f2017-11-27 10:50:44 -0800364#define MICRO_P1A 100000
365#define OTG_DEFAULT_DEGLITCH_TIME_MS 50
366#define MIN_WD_BARK_TIME 16
367#define DEFAULT_WD_BARK_TIME 64
368#define BITE_WDOG_TIMEOUT_8S 0x3
369#define BARK_WDOG_TIMEOUT_MASK GENMASK(3, 2)
370#define BARK_WDOG_TIMEOUT_SHIFT 2
371static int smb5_parse_dt(struct smb5 *chip)
372{
373 struct smb_charger *chg = &chip->chg;
374 struct device_node *node = chg->dev->of_node;
375 int rc, byte_len;
376
377 if (!node) {
378 pr_err("device tree node missing\n");
379 return -EINVAL;
380 }
381
382 chg->step_chg_enabled = of_property_read_bool(node,
383 "qcom,step-charging-enable");
384
385 chg->sw_jeita_enabled = of_property_read_bool(node,
386 "qcom,sw-jeita-enable");
387
388 rc = of_property_read_u32(node, "qcom,wd-bark-time-secs",
389 &chip->dt.wd_bark_time);
390 if (rc < 0 || chip->dt.wd_bark_time < MIN_WD_BARK_TIME)
391 chip->dt.wd_bark_time = DEFAULT_WD_BARK_TIME;
392
393 chip->dt.no_battery = of_property_read_bool(node,
394 "qcom,batteryless-platform");
395
396 rc = of_property_read_u32(node,
397 "qcom,fcc-max-ua", &chip->dt.batt_profile_fcc_ua);
398 if (rc < 0)
399 chip->dt.batt_profile_fcc_ua = -EINVAL;
400
401 rc = of_property_read_u32(node,
402 "qcom,fv-max-uv", &chip->dt.batt_profile_fv_uv);
403 if (rc < 0)
404 chip->dt.batt_profile_fv_uv = -EINVAL;
405
406 rc = of_property_read_u32(node,
407 "qcom,usb-icl-ua", &chip->dt.usb_icl_ua);
408 if (rc < 0)
409 chip->dt.usb_icl_ua = -EINVAL;
410
411 rc = of_property_read_u32(node,
412 "qcom,otg-cl-ua", &chg->otg_cl_ua);
413 if (rc < 0)
Ashay Jaiswalb2b06fe2018-06-07 18:35:21 +0530414 chg->otg_cl_ua = (chip->chg.smb_version == PMI632_SUBTYPE) ?
415 MICRO_1PA : MICRO_1P5A;
Harry Yang4b7db0f2017-11-27 10:50:44 -0800416
Guru Das Srinagesh3ca14372018-06-01 11:30:56 -0700417 rc = of_property_read_u32(node, "qcom,chg-term-src",
418 &chip->dt.term_current_src);
419 if (rc < 0)
420 chip->dt.term_current_src = ITERM_SRC_UNSPECIFIED;
421
422 rc = of_property_read_u32(node, "qcom,chg-term-current-ma",
423 &chip->dt.term_current_thresh_hi_ma);
424
425 if (chip->dt.term_current_src == ITERM_SRC_ADC)
426 rc = of_property_read_u32(node, "qcom,chg-term-base-current-ma",
427 &chip->dt.term_current_thresh_lo_ma);
428
Harry Yang4b7db0f2017-11-27 10:50:44 -0800429 if (of_find_property(node, "qcom,thermal-mitigation", &byte_len)) {
430 chg->thermal_mitigation = devm_kzalloc(chg->dev, byte_len,
431 GFP_KERNEL);
432
433 if (chg->thermal_mitigation == NULL)
434 return -ENOMEM;
435
436 chg->thermal_levels = byte_len / sizeof(u32);
437 rc = of_property_read_u32_array(node,
438 "qcom,thermal-mitigation",
439 chg->thermal_mitigation,
440 chg->thermal_levels);
441 if (rc < 0) {
442 dev_err(chg->dev,
443 "Couldn't read threm limits rc = %d\n", rc);
444 return rc;
445 }
446 }
447
448 rc = of_property_read_u32(node, "qcom,float-option",
449 &chip->dt.float_option);
450 if (!rc && (chip->dt.float_option < 0 || chip->dt.float_option > 4)) {
451 pr_err("qcom,float-option is out of range [0, 4]\n");
452 return -EINVAL;
453 }
454
455 chip->dt.hvdcp_disable = of_property_read_bool(node,
456 "qcom,hvdcp-disable");
457
458
459 rc = of_property_read_u32(node, "qcom,chg-inhibit-threshold-mv",
460 &chip->dt.chg_inhibit_thr_mv);
461 if (!rc && (chip->dt.chg_inhibit_thr_mv < 0 ||
462 chip->dt.chg_inhibit_thr_mv > 300)) {
463 pr_err("qcom,chg-inhibit-threshold-mv is incorrect\n");
464 return -EINVAL;
465 }
466
Anirudh Ghayal1380d312018-02-23 00:01:43 +0530467 chip->dt.auto_recharge_soc = -EINVAL;
468 rc = of_property_read_u32(node, "qcom,auto-recharge-soc",
469 &chip->dt.auto_recharge_soc);
470 if (!rc && (chip->dt.auto_recharge_soc < 0 ||
471 chip->dt.auto_recharge_soc > 100)) {
472 pr_err("qcom,auto-recharge-soc is incorrect\n");
473 return -EINVAL;
474 }
475 chg->auto_recharge_soc = chip->dt.auto_recharge_soc;
476
477 chip->dt.auto_recharge_vbat_mv = -EINVAL;
478 rc = of_property_read_u32(node, "qcom,auto-recharge-vbat-mv",
479 &chip->dt.auto_recharge_vbat_mv);
480 if (!rc && (chip->dt.auto_recharge_vbat_mv < 0)) {
481 pr_err("qcom,auto-recharge-vbat-mv is incorrect\n");
482 return -EINVAL;
483 }
Harry Yang4b7db0f2017-11-27 10:50:44 -0800484
Harry Yang4b7db0f2017-11-27 10:50:44 -0800485 chg->dcp_icl_ua = chip->dt.usb_icl_ua;
486
487 chg->suspend_input_on_debug_batt = of_property_read_bool(node,
488 "qcom,suspend-input-on-debug-batt");
489
490 rc = of_property_read_u32(node, "qcom,otg-deglitch-time-ms",
491 &chg->otg_delay_ms);
492 if (rc < 0)
493 chg->otg_delay_ms = OTG_DEFAULT_DEGLITCH_TIME_MS;
494
Ashay Jaiswal0de6fb92018-06-12 17:23:45 +0530495 chg->hw_die_temp_mitigation = of_property_read_bool(node,
496 "qcom,hw-die-temp-mitigation");
497
498 chg->hw_connector_mitigation = of_property_read_bool(node,
499 "qcom,hw-connector-mitigation");
500
501 chg->connector_pull_up = -EINVAL;
502 of_property_read_u32(node, "qcom,connector-internal-pull-kohm",
503 &chg->connector_pull_up);
504
Umang Agrawal461e9ea2018-07-05 18:50:13 +0530505 chg->moisture_protection_enabled = of_property_read_bool(node,
506 "qcom,moisture-protection-enable");
507
Umang Agrawal238086f2018-05-28 12:29:31 +0530508 chg->fcc_stepper_enable = of_property_read_bool(node,
509 "qcom,fcc-stepping-enable");
510
Harry Yang4b7db0f2017-11-27 10:50:44 -0800511 return 0;
512}
513
Ashay Jaiswal20688262018-04-25 11:45:34 +0530514static int smb5_get_adc_data(struct smb_charger *chg, int channel,
515 union power_supply_propval *val)
516{
Anirudh Ghayal75f8f812018-07-09 16:48:47 +0530517 int rc = 0;
Ashay Jaiswal20688262018-04-25 11:45:34 +0530518 struct qpnp_vadc_result result;
Ashay Jaiswalb50706d2018-06-28 19:37:31 +0530519 u8 reg;
Ashay Jaiswal20688262018-04-25 11:45:34 +0530520
521 if (!chg->vadc_dev) {
522 if (of_find_property(chg->dev->of_node, "qcom,chg-vadc",
523 NULL)) {
524 chg->vadc_dev = qpnp_get_vadc(chg->dev, "chg");
525 if (IS_ERR(chg->vadc_dev)) {
526 rc = PTR_ERR(chg->vadc_dev);
527 if (rc != -EPROBE_DEFER)
528 pr_debug("Failed to find VADC node, rc=%d\n",
529 rc);
530 else
531 chg->vadc_dev = NULL;
532
533 return rc;
534 }
535 } else {
536 return -ENODATA;
537 }
538 }
539
540 if (IS_ERR(chg->vadc_dev))
541 return PTR_ERR(chg->vadc_dev);
542
Anirudh Ghayal75f8f812018-07-09 16:48:47 +0530543 mutex_lock(&chg->vadc_lock);
544
Ashay Jaiswal20688262018-04-25 11:45:34 +0530545 switch (channel) {
546 case USBIN_VOLTAGE:
Ashay Jaiswalb50706d2018-06-28 19:37:31 +0530547 /* Store ADC channel config */
548 rc = smblib_read(chg, BATIF_ADC_CHANNEL_EN_REG, &reg);
549 if (rc < 0) {
550 dev_err(chg->dev,
551 "Couldn't read ADC config rc=%d\n", rc);
Anirudh Ghayal75f8f812018-07-09 16:48:47 +0530552 goto done;
Ashay Jaiswalb50706d2018-06-28 19:37:31 +0530553 }
554
555 /* Disable all ADC channels except IBAT channel */
556 rc = smblib_write(chg, BATIF_ADC_CHANNEL_EN_REG,
557 IBATT_CHANNEL_EN_BIT);
558 if (rc < 0) {
559 dev_err(chg->dev,
560 "Couldn't write ADC config rc=%d\n", rc);
Anirudh Ghayal75f8f812018-07-09 16:48:47 +0530561 goto done;
Ashay Jaiswalb50706d2018-06-28 19:37:31 +0530562 }
563
Ashay Jaiswal20688262018-04-25 11:45:34 +0530564 rc = qpnp_vadc_read(chg->vadc_dev, VADC_USB_IN_V_DIV_16_PM5,
565 &result);
Anirudh Ghayal75f8f812018-07-09 16:48:47 +0530566 if (rc < 0)
Ashay Jaiswal20688262018-04-25 11:45:34 +0530567 pr_err("Failed to read USBIN_V over vadc, rc=%d\n", rc);
Anirudh Ghayal75f8f812018-07-09 16:48:47 +0530568 else
569 val->intval = result.physical;
Ashay Jaiswalb50706d2018-06-28 19:37:31 +0530570
Ashay Jaiswalb50706d2018-06-28 19:37:31 +0530571 /* Restore ADC channel config */
Anirudh Ghayal75f8f812018-07-09 16:48:47 +0530572 rc |= smblib_write(chg, BATIF_ADC_CHANNEL_EN_REG, reg);
573 if (rc < 0)
Ashay Jaiswalb50706d2018-06-28 19:37:31 +0530574 dev_err(chg->dev,
575 "Couldn't write ADC config rc=%d\n", rc);
Anirudh Ghayal75f8f812018-07-09 16:48:47 +0530576
Ashay Jaiswal20688262018-04-25 11:45:34 +0530577 break;
578 case USBIN_CURRENT:
579 rc = qpnp_vadc_read(chg->vadc_dev, VADC_USB_IN_I_PM5, &result);
580 if (rc < 0) {
581 pr_err("Failed to read USBIN_I over vadc, rc=%d\n", rc);
Anirudh Ghayal75f8f812018-07-09 16:48:47 +0530582 goto done;
Ashay Jaiswal20688262018-04-25 11:45:34 +0530583 }
584 val->intval = result.physical;
585 break;
586 default:
587 pr_debug("Invalid channel\n");
Anirudh Ghayal75f8f812018-07-09 16:48:47 +0530588 rc = -EINVAL;
589 break;
Ashay Jaiswal20688262018-04-25 11:45:34 +0530590 }
591
Anirudh Ghayal75f8f812018-07-09 16:48:47 +0530592done:
593 mutex_unlock(&chg->vadc_lock);
594 return rc;
Ashay Jaiswal20688262018-04-25 11:45:34 +0530595}
596
597
Harry Yang4b7db0f2017-11-27 10:50:44 -0800598/************************
599 * USB PSY REGISTRATION *
600 ************************/
601static enum power_supply_property smb5_usb_props[] = {
602 POWER_SUPPLY_PROP_PRESENT,
603 POWER_SUPPLY_PROP_ONLINE,
604 POWER_SUPPLY_PROP_PD_CURRENT_MAX,
605 POWER_SUPPLY_PROP_CURRENT_MAX,
606 POWER_SUPPLY_PROP_TYPE,
607 POWER_SUPPLY_PROP_TYPEC_MODE,
608 POWER_SUPPLY_PROP_TYPEC_POWER_ROLE,
609 POWER_SUPPLY_PROP_TYPEC_CC_ORIENTATION,
Harry Yang4b7db0f2017-11-27 10:50:44 -0800610 POWER_SUPPLY_PROP_PD_ACTIVE,
611 POWER_SUPPLY_PROP_INPUT_CURRENT_SETTLED,
612 POWER_SUPPLY_PROP_INPUT_CURRENT_NOW,
613 POWER_SUPPLY_PROP_BOOST_CURRENT,
614 POWER_SUPPLY_PROP_PE_START,
615 POWER_SUPPLY_PROP_CTM_CURRENT_MAX,
616 POWER_SUPPLY_PROP_HW_CURRENT_MAX,
617 POWER_SUPPLY_PROP_REAL_TYPE,
618 POWER_SUPPLY_PROP_PR_SWAP,
619 POWER_SUPPLY_PROP_PD_VOLTAGE_MAX,
620 POWER_SUPPLY_PROP_PD_VOLTAGE_MIN,
621 POWER_SUPPLY_PROP_SDP_CURRENT_MAX,
Ashay Jaiswala9e10912018-02-02 14:03:35 +0530622 POWER_SUPPLY_PROP_CONNECTOR_TYPE,
Ashay Jaiswal1f71b412017-10-31 14:33:27 +0530623 POWER_SUPPLY_PROP_VOLTAGE_MAX,
Umang Agrawal9fb865a2018-06-25 16:24:00 +0530624 POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN,
Ashay Jaiswal09feab82018-02-12 12:33:18 +0530625 POWER_SUPPLY_PROP_SCOPE,
Ashay Jaiswal20688262018-04-25 11:45:34 +0530626 POWER_SUPPLY_PROP_VOLTAGE_NOW,
Ashay Jaiswal4d334f42018-04-25 10:58:49 +0530627 POWER_SUPPLY_PROP_HVDCP_OPTI_ALLOWED,
Ashay Jaiswal0de6fb92018-06-12 17:23:45 +0530628 POWER_SUPPLY_PROP_QC_OPTI_DISABLE,
Umang Agrawal461e9ea2018-07-05 18:50:13 +0530629 POWER_SUPPLY_PROP_MOISTURE_DETECTED,
Harry Yang4b7db0f2017-11-27 10:50:44 -0800630};
631
632static int smb5_usb_get_prop(struct power_supply *psy,
633 enum power_supply_property psp,
634 union power_supply_propval *val)
635{
636 struct smb5 *chip = power_supply_get_drvdata(psy);
637 struct smb_charger *chg = &chip->chg;
Ashay Jaiswal09feab82018-02-12 12:33:18 +0530638 union power_supply_propval pval;
Harry Yang4b7db0f2017-11-27 10:50:44 -0800639 int rc = 0;
640
641 switch (psp) {
642 case POWER_SUPPLY_PROP_PRESENT:
643 rc = smblib_get_prop_usb_present(chg, val);
644 break;
645 case POWER_SUPPLY_PROP_ONLINE:
646 rc = smblib_get_prop_usb_online(chg, val);
647 if (!val->intval)
648 break;
649
Ashay Jaiswala9e10912018-02-02 14:03:35 +0530650 if (((chg->typec_mode == POWER_SUPPLY_TYPEC_SOURCE_DEFAULT) ||
651 (chg->connector_type == POWER_SUPPLY_CONNECTOR_MICRO_USB))
652 && (chg->real_charger_type == POWER_SUPPLY_TYPE_USB))
Harry Yang4b7db0f2017-11-27 10:50:44 -0800653 val->intval = 0;
654 else
655 val->intval = 1;
Ashay Jaiswala9e10912018-02-02 14:03:35 +0530656
Harry Yang4b7db0f2017-11-27 10:50:44 -0800657 if (chg->real_charger_type == POWER_SUPPLY_TYPE_UNKNOWN)
658 val->intval = 0;
659 break;
660 case POWER_SUPPLY_PROP_VOLTAGE_MAX:
661 rc = smblib_get_prop_usb_voltage_max(chg, val);
662 break;
Umang Agrawal9fb865a2018-06-25 16:24:00 +0530663 case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN:
664 rc = smblib_get_prop_usb_voltage_max_design(chg, val);
665 break;
Harry Yang4b7db0f2017-11-27 10:50:44 -0800666 case POWER_SUPPLY_PROP_PD_CURRENT_MAX:
667 val->intval = get_client_vote(chg->usb_icl_votable, PD_VOTER);
668 break;
669 case POWER_SUPPLY_PROP_CURRENT_MAX:
670 rc = smblib_get_prop_input_current_settled(chg, val);
671 break;
672 case POWER_SUPPLY_PROP_TYPE:
673 val->intval = POWER_SUPPLY_TYPE_USB_PD;
674 break;
675 case POWER_SUPPLY_PROP_REAL_TYPE:
676 val->intval = chg->real_charger_type;
677 break;
678 case POWER_SUPPLY_PROP_TYPEC_MODE:
Ashay Jaiswala9e10912018-02-02 14:03:35 +0530679 if (chg->connector_type == POWER_SUPPLY_CONNECTOR_MICRO_USB)
Harry Yang4b7db0f2017-11-27 10:50:44 -0800680 val->intval = POWER_SUPPLY_TYPEC_NONE;
681 else
682 val->intval = chg->typec_mode;
683 break;
684 case POWER_SUPPLY_PROP_TYPEC_POWER_ROLE:
Ashay Jaiswala9e10912018-02-02 14:03:35 +0530685 if (chg->connector_type == POWER_SUPPLY_CONNECTOR_MICRO_USB)
Harry Yang4b7db0f2017-11-27 10:50:44 -0800686 val->intval = POWER_SUPPLY_TYPEC_PR_NONE;
687 else
688 rc = smblib_get_prop_typec_power_role(chg, val);
689 break;
690 case POWER_SUPPLY_PROP_TYPEC_CC_ORIENTATION:
Ashay Jaiswala9e10912018-02-02 14:03:35 +0530691 if (chg->connector_type == POWER_SUPPLY_CONNECTOR_MICRO_USB)
Harry Yang4b7db0f2017-11-27 10:50:44 -0800692 val->intval = 0;
693 else
694 rc = smblib_get_prop_typec_cc_orientation(chg, val);
695 break;
Harry Yang4b7db0f2017-11-27 10:50:44 -0800696 case POWER_SUPPLY_PROP_PD_ACTIVE:
697 val->intval = chg->pd_active;
698 break;
699 case POWER_SUPPLY_PROP_INPUT_CURRENT_SETTLED:
700 rc = smblib_get_prop_input_current_settled(chg, val);
701 break;
702 case POWER_SUPPLY_PROP_BOOST_CURRENT:
703 val->intval = chg->boost_current_ua;
704 break;
705 case POWER_SUPPLY_PROP_PD_IN_HARD_RESET:
706 rc = smblib_get_prop_pd_in_hard_reset(chg, val);
707 break;
708 case POWER_SUPPLY_PROP_PD_USB_SUSPEND_SUPPORTED:
709 val->intval = chg->system_suspend_supported;
710 break;
711 case POWER_SUPPLY_PROP_PE_START:
712 rc = smblib_get_pe_start(chg, val);
713 break;
714 case POWER_SUPPLY_PROP_CTM_CURRENT_MAX:
715 val->intval = get_client_vote(chg->usb_icl_votable, CTM_VOTER);
716 break;
717 case POWER_SUPPLY_PROP_HW_CURRENT_MAX:
718 rc = smblib_get_charge_current(chg, &val->intval);
719 break;
720 case POWER_SUPPLY_PROP_PR_SWAP:
721 rc = smblib_get_prop_pr_swap_in_progress(chg, val);
722 break;
723 case POWER_SUPPLY_PROP_PD_VOLTAGE_MAX:
724 val->intval = chg->voltage_max_uv;
725 break;
726 case POWER_SUPPLY_PROP_PD_VOLTAGE_MIN:
727 val->intval = chg->voltage_min_uv;
728 break;
729 case POWER_SUPPLY_PROP_SDP_CURRENT_MAX:
730 val->intval = get_client_vote(chg->usb_icl_votable,
731 USB_PSY_VOTER);
732 break;
Ashay Jaiswala9e10912018-02-02 14:03:35 +0530733 case POWER_SUPPLY_PROP_CONNECTOR_TYPE:
734 val->intval = chg->connector_type;
735 break;
Ashay Jaiswal09feab82018-02-12 12:33:18 +0530736 case POWER_SUPPLY_PROP_SCOPE:
737 val->intval = POWER_SUPPLY_SCOPE_UNKNOWN;
738 rc = smblib_get_prop_usb_present(chg, &pval);
739 if (rc < 0)
740 break;
741 val->intval = pval.intval ? POWER_SUPPLY_SCOPE_DEVICE
742 : chg->otg_present ? POWER_SUPPLY_SCOPE_SYSTEM
743 : POWER_SUPPLY_SCOPE_UNKNOWN;
744 break;
Ashay Jaiswal20688262018-04-25 11:45:34 +0530745 case POWER_SUPPLY_PROP_INPUT_CURRENT_NOW:
746 rc = smblib_get_prop_usb_present(chg, &pval);
747 if (rc < 0 || !pval.intval) {
748 val->intval = 0;
749 return rc;
750 }
751 if (chg->smb_version == PMI632_SUBTYPE)
752 rc = smb5_get_adc_data(chg, USBIN_CURRENT, val);
753 break;
754 case POWER_SUPPLY_PROP_VOLTAGE_NOW:
755 if (chg->smb_version == PMI632_SUBTYPE)
756 rc = smb5_get_adc_data(chg, USBIN_VOLTAGE, val);
757 break;
Ashay Jaiswal4d334f42018-04-25 10:58:49 +0530758 case POWER_SUPPLY_PROP_HVDCP_OPTI_ALLOWED:
759 val->intval = !chg->flash_active;
760 break;
Ashay Jaiswal0de6fb92018-06-12 17:23:45 +0530761 case POWER_SUPPLY_PROP_QC_OPTI_DISABLE:
762 if (chg->hw_die_temp_mitigation)
763 val->intval = POWER_SUPPLY_QC_THERMAL_BALANCE_DISABLE
764 | POWER_SUPPLY_QC_INOV_THERMAL_DISABLE;
765 if (chg->hw_connector_mitigation)
766 val->intval |= POWER_SUPPLY_QC_CTM_DISABLE;
767 break;
Umang Agrawal461e9ea2018-07-05 18:50:13 +0530768 case POWER_SUPPLY_PROP_MOISTURE_DETECTED:
769 val->intval = chg->moisture_present;
770 break;
Harry Yang4b7db0f2017-11-27 10:50:44 -0800771 default:
772 pr_err("get prop %d is not supported in usb\n", psp);
773 rc = -EINVAL;
774 break;
775 }
776
777 if (rc < 0) {
778 pr_debug("Couldn't get prop %d rc = %d\n", psp, rc);
779 return -ENODATA;
780 }
781
782 return 0;
783}
784
785static int smb5_usb_set_prop(struct power_supply *psy,
786 enum power_supply_property psp,
787 const union power_supply_propval *val)
788{
789 struct smb5 *chip = power_supply_get_drvdata(psy);
790 struct smb_charger *chg = &chip->chg;
791 int rc = 0;
792
Harry Yang4b7db0f2017-11-27 10:50:44 -0800793 switch (psp) {
794 case POWER_SUPPLY_PROP_PD_CURRENT_MAX:
795 rc = smblib_set_prop_pd_current_max(chg, val);
796 break;
797 case POWER_SUPPLY_PROP_TYPEC_POWER_ROLE:
798 rc = smblib_set_prop_typec_power_role(chg, val);
799 break;
800 case POWER_SUPPLY_PROP_PD_ACTIVE:
801 rc = smblib_set_prop_pd_active(chg, val);
802 break;
803 case POWER_SUPPLY_PROP_PD_IN_HARD_RESET:
804 rc = smblib_set_prop_pd_in_hard_reset(chg, val);
805 break;
806 case POWER_SUPPLY_PROP_PD_USB_SUSPEND_SUPPORTED:
807 chg->system_suspend_supported = val->intval;
808 break;
809 case POWER_SUPPLY_PROP_BOOST_CURRENT:
810 rc = smblib_set_prop_boost_current(chg, val);
811 break;
812 case POWER_SUPPLY_PROP_CTM_CURRENT_MAX:
813 rc = vote(chg->usb_icl_votable, CTM_VOTER,
814 val->intval >= 0, val->intval);
815 break;
816 case POWER_SUPPLY_PROP_PR_SWAP:
817 rc = smblib_set_prop_pr_swap_in_progress(chg, val);
818 break;
819 case POWER_SUPPLY_PROP_PD_VOLTAGE_MAX:
820 rc = smblib_set_prop_pd_voltage_max(chg, val);
821 break;
822 case POWER_SUPPLY_PROP_PD_VOLTAGE_MIN:
823 rc = smblib_set_prop_pd_voltage_min(chg, val);
824 break;
825 case POWER_SUPPLY_PROP_SDP_CURRENT_MAX:
826 rc = smblib_set_prop_sdp_current_max(chg, val);
827 break;
828 default:
829 pr_err("set prop %d is not supported\n", psp);
830 rc = -EINVAL;
831 break;
832 }
833
Harry Yang4b7db0f2017-11-27 10:50:44 -0800834 return rc;
835}
836
837static int smb5_usb_prop_is_writeable(struct power_supply *psy,
838 enum power_supply_property psp)
839{
840 switch (psp) {
841 case POWER_SUPPLY_PROP_CTM_CURRENT_MAX:
842 return 1;
843 default:
844 break;
845 }
846
847 return 0;
848}
849
850static const struct power_supply_desc usb_psy_desc = {
851 .name = "usb",
852 .type = POWER_SUPPLY_TYPE_USB_PD,
853 .properties = smb5_usb_props,
854 .num_properties = ARRAY_SIZE(smb5_usb_props),
855 .get_property = smb5_usb_get_prop,
856 .set_property = smb5_usb_set_prop,
857 .property_is_writeable = smb5_usb_prop_is_writeable,
858};
859
860static int smb5_init_usb_psy(struct smb5 *chip)
861{
862 struct power_supply_config usb_cfg = {};
863 struct smb_charger *chg = &chip->chg;
864
865 usb_cfg.drv_data = chip;
866 usb_cfg.of_node = chg->dev->of_node;
867 chg->usb_psy = devm_power_supply_register(chg->dev,
868 &usb_psy_desc,
869 &usb_cfg);
870 if (IS_ERR(chg->usb_psy)) {
871 pr_err("Couldn't register USB power supply\n");
872 return PTR_ERR(chg->usb_psy);
873 }
874
875 return 0;
876}
877
878/********************************
879 * USB PC_PORT PSY REGISTRATION *
880 ********************************/
881static enum power_supply_property smb5_usb_port_props[] = {
882 POWER_SUPPLY_PROP_TYPE,
883 POWER_SUPPLY_PROP_ONLINE,
884 POWER_SUPPLY_PROP_VOLTAGE_MAX,
885 POWER_SUPPLY_PROP_CURRENT_MAX,
886};
887
888static int smb5_usb_port_get_prop(struct power_supply *psy,
889 enum power_supply_property psp,
890 union power_supply_propval *val)
891{
892 struct smb5 *chip = power_supply_get_drvdata(psy);
893 struct smb_charger *chg = &chip->chg;
894 int rc = 0;
895
896 switch (psp) {
897 case POWER_SUPPLY_PROP_TYPE:
898 val->intval = POWER_SUPPLY_TYPE_USB;
899 break;
900 case POWER_SUPPLY_PROP_ONLINE:
901 rc = smblib_get_prop_usb_online(chg, val);
902 if (!val->intval)
903 break;
904
Ashay Jaiswala9e10912018-02-02 14:03:35 +0530905 if (((chg->typec_mode == POWER_SUPPLY_TYPEC_SOURCE_DEFAULT) ||
906 (chg->connector_type == POWER_SUPPLY_CONNECTOR_MICRO_USB))
907 && (chg->real_charger_type == POWER_SUPPLY_TYPE_USB))
Harry Yang4b7db0f2017-11-27 10:50:44 -0800908 val->intval = 1;
909 else
910 val->intval = 0;
911 break;
912 case POWER_SUPPLY_PROP_VOLTAGE_MAX:
913 val->intval = 5000000;
914 break;
915 case POWER_SUPPLY_PROP_CURRENT_MAX:
916 rc = smblib_get_prop_input_current_settled(chg, val);
917 break;
918 default:
919 pr_err_ratelimited("Get prop %d is not supported in pc_port\n",
920 psp);
921 return -EINVAL;
922 }
923
924 if (rc < 0) {
925 pr_debug("Couldn't get prop %d rc = %d\n", psp, rc);
926 return -ENODATA;
927 }
928
929 return 0;
930}
931
932static int smb5_usb_port_set_prop(struct power_supply *psy,
933 enum power_supply_property psp,
934 const union power_supply_propval *val)
935{
936 int rc = 0;
937
938 switch (psp) {
939 default:
940 pr_err_ratelimited("Set prop %d is not supported in pc_port\n",
941 psp);
942 rc = -EINVAL;
943 break;
944 }
945
946 return rc;
947}
948
949static const struct power_supply_desc usb_port_psy_desc = {
950 .name = "pc_port",
951 .type = POWER_SUPPLY_TYPE_USB,
952 .properties = smb5_usb_port_props,
953 .num_properties = ARRAY_SIZE(smb5_usb_port_props),
954 .get_property = smb5_usb_port_get_prop,
955 .set_property = smb5_usb_port_set_prop,
956};
957
958static int smb5_init_usb_port_psy(struct smb5 *chip)
959{
960 struct power_supply_config usb_port_cfg = {};
961 struct smb_charger *chg = &chip->chg;
962
963 usb_port_cfg.drv_data = chip;
964 usb_port_cfg.of_node = chg->dev->of_node;
965 chg->usb_port_psy = devm_power_supply_register(chg->dev,
966 &usb_port_psy_desc,
967 &usb_port_cfg);
968 if (IS_ERR(chg->usb_port_psy)) {
969 pr_err("Couldn't register USB pc_port power supply\n");
970 return PTR_ERR(chg->usb_port_psy);
971 }
972
973 return 0;
974}
975
976/*****************************
977 * USB MAIN PSY REGISTRATION *
978 *****************************/
979
980static enum power_supply_property smb5_usb_main_props[] = {
981 POWER_SUPPLY_PROP_VOLTAGE_MAX,
982 POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX,
983 POWER_SUPPLY_PROP_TYPE,
984 POWER_SUPPLY_PROP_INPUT_CURRENT_SETTLED,
985 POWER_SUPPLY_PROP_INPUT_VOLTAGE_SETTLED,
986 POWER_SUPPLY_PROP_FCC_DELTA,
987 POWER_SUPPLY_PROP_CURRENT_MAX,
Ashay Jaiswal09feab82018-02-12 12:33:18 +0530988 POWER_SUPPLY_PROP_FLASH_ACTIVE,
989 POWER_SUPPLY_PROP_FLASH_TRIGGER,
Harry Yang4b7db0f2017-11-27 10:50:44 -0800990};
991
992static int smb5_usb_main_get_prop(struct power_supply *psy,
993 enum power_supply_property psp,
994 union power_supply_propval *val)
995{
996 struct smb5 *chip = power_supply_get_drvdata(psy);
997 struct smb_charger *chg = &chip->chg;
998 int rc = 0;
999
1000 switch (psp) {
1001 case POWER_SUPPLY_PROP_VOLTAGE_MAX:
1002 rc = smblib_get_charge_param(chg, &chg->param.fv, &val->intval);
1003 break;
1004 case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX:
1005 rc = smblib_get_charge_param(chg, &chg->param.fcc,
1006 &val->intval);
1007 break;
1008 case POWER_SUPPLY_PROP_TYPE:
1009 val->intval = POWER_SUPPLY_TYPE_MAIN;
1010 break;
1011 case POWER_SUPPLY_PROP_INPUT_CURRENT_SETTLED:
1012 rc = smblib_get_prop_input_current_settled(chg, val);
1013 break;
1014 case POWER_SUPPLY_PROP_INPUT_VOLTAGE_SETTLED:
1015 rc = smblib_get_prop_input_voltage_settled(chg, val);
1016 break;
1017 case POWER_SUPPLY_PROP_FCC_DELTA:
1018 rc = smblib_get_prop_fcc_delta(chg, val);
1019 break;
1020 case POWER_SUPPLY_PROP_CURRENT_MAX:
1021 rc = smblib_get_icl_current(chg, &val->intval);
1022 break;
Ashay Jaiswal09feab82018-02-12 12:33:18 +05301023 case POWER_SUPPLY_PROP_FLASH_ACTIVE:
1024 val->intval = chg->flash_active;
1025 break;
1026 case POWER_SUPPLY_PROP_FLASH_TRIGGER:
1027 rc = schgm_flash_get_vreg_ok(chg, &val->intval);
1028 break;
Harry Yang4b7db0f2017-11-27 10:50:44 -08001029 default:
1030 pr_debug("get prop %d is not supported in usb-main\n", psp);
1031 rc = -EINVAL;
1032 break;
1033 }
1034 if (rc < 0) {
1035 pr_debug("Couldn't get prop %d rc = %d\n", psp, rc);
1036 return -ENODATA;
1037 }
1038
1039 return 0;
1040}
1041
1042static int smb5_usb_main_set_prop(struct power_supply *psy,
1043 enum power_supply_property psp,
1044 const union power_supply_propval *val)
1045{
1046 struct smb5 *chip = power_supply_get_drvdata(psy);
1047 struct smb_charger *chg = &chip->chg;
Ashay Jaiswal4d334f42018-04-25 10:58:49 +05301048 union power_supply_propval pval = {0, };
Harry Yang4b7db0f2017-11-27 10:50:44 -08001049 int rc = 0;
1050
1051 switch (psp) {
1052 case POWER_SUPPLY_PROP_VOLTAGE_MAX:
1053 rc = smblib_set_charge_param(chg, &chg->param.fv, val->intval);
1054 break;
1055 case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX:
1056 rc = smblib_set_charge_param(chg, &chg->param.fcc, val->intval);
1057 break;
1058 case POWER_SUPPLY_PROP_CURRENT_MAX:
1059 rc = smblib_set_icl_current(chg, val->intval);
1060 break;
Ashay Jaiswal09feab82018-02-12 12:33:18 +05301061 case POWER_SUPPLY_PROP_FLASH_ACTIVE:
Ashay Jaiswal4d334f42018-04-25 10:58:49 +05301062 if ((chg->smb_version == PMI632_SUBTYPE)
1063 && (chg->flash_active != val->intval)) {
1064 chg->flash_active = val->intval;
1065
1066 rc = smblib_get_prop_usb_present(chg, &pval);
1067 if (rc < 0)
1068 pr_err("Failed to get USB preset status rc=%d\n",
1069 rc);
1070 if (pval.intval) {
1071 rc = smblib_force_vbus_voltage(chg,
1072 chg->flash_active ? FORCE_5V_BIT
1073 : IDLE_BIT);
1074 if (rc < 0)
1075 pr_err("Failed to force 5V\n");
1076 else
1077 chg->pulse_cnt = 0;
Anirudh Ghayal4d5cddc2018-06-28 15:19:39 +05301078 } else {
1079 /* USB absent & flash not-active - vote 100mA */
1080 vote(chg->usb_icl_votable, SW_ICL_MAX_VOTER,
1081 true, SDP_100_MA);
Ashay Jaiswal4d334f42018-04-25 10:58:49 +05301082 }
1083
1084 pr_debug("flash active VBUS 5V restriction %s\n",
1085 chg->flash_active ? "applied" : "removed");
1086
1087 /* Update userspace */
1088 if (chg->batt_psy)
1089 power_supply_changed(chg->batt_psy);
1090 }
Ashay Jaiswal09feab82018-02-12 12:33:18 +05301091 break;
Harry Yang4b7db0f2017-11-27 10:50:44 -08001092 default:
1093 pr_err("set prop %d is not supported\n", psp);
1094 rc = -EINVAL;
1095 break;
1096 }
1097
1098 return rc;
1099}
1100
1101static const struct power_supply_desc usb_main_psy_desc = {
1102 .name = "main",
1103 .type = POWER_SUPPLY_TYPE_MAIN,
1104 .properties = smb5_usb_main_props,
1105 .num_properties = ARRAY_SIZE(smb5_usb_main_props),
1106 .get_property = smb5_usb_main_get_prop,
1107 .set_property = smb5_usb_main_set_prop,
1108};
1109
1110static int smb5_init_usb_main_psy(struct smb5 *chip)
1111{
1112 struct power_supply_config usb_main_cfg = {};
1113 struct smb_charger *chg = &chip->chg;
1114
1115 usb_main_cfg.drv_data = chip;
1116 usb_main_cfg.of_node = chg->dev->of_node;
1117 chg->usb_main_psy = devm_power_supply_register(chg->dev,
1118 &usb_main_psy_desc,
1119 &usb_main_cfg);
1120 if (IS_ERR(chg->usb_main_psy)) {
1121 pr_err("Couldn't register USB main power supply\n");
1122 return PTR_ERR(chg->usb_main_psy);
1123 }
1124
1125 return 0;
1126}
1127
1128/*************************
1129 * DC PSY REGISTRATION *
1130 *************************/
1131
1132static enum power_supply_property smb5_dc_props[] = {
1133 POWER_SUPPLY_PROP_INPUT_SUSPEND,
1134 POWER_SUPPLY_PROP_PRESENT,
1135 POWER_SUPPLY_PROP_ONLINE,
1136 POWER_SUPPLY_PROP_REAL_TYPE,
1137};
1138
1139static int smb5_dc_get_prop(struct power_supply *psy,
1140 enum power_supply_property psp,
1141 union power_supply_propval *val)
1142{
1143 struct smb5 *chip = power_supply_get_drvdata(psy);
1144 struct smb_charger *chg = &chip->chg;
1145 int rc = 0;
1146
1147 switch (psp) {
1148 case POWER_SUPPLY_PROP_INPUT_SUSPEND:
1149 val->intval = get_effective_result(chg->dc_suspend_votable);
1150 break;
1151 case POWER_SUPPLY_PROP_PRESENT:
1152 rc = smblib_get_prop_dc_present(chg, val);
1153 break;
1154 case POWER_SUPPLY_PROP_ONLINE:
1155 rc = smblib_get_prop_dc_online(chg, val);
1156 break;
1157 case POWER_SUPPLY_PROP_REAL_TYPE:
1158 val->intval = POWER_SUPPLY_TYPE_WIPOWER;
1159 break;
1160 default:
1161 return -EINVAL;
1162 }
1163 if (rc < 0) {
1164 pr_debug("Couldn't get prop %d rc = %d\n", psp, rc);
1165 return -ENODATA;
1166 }
1167 return 0;
1168}
1169
1170static int smb5_dc_set_prop(struct power_supply *psy,
1171 enum power_supply_property psp,
1172 const union power_supply_propval *val)
1173{
1174 struct smb5 *chip = power_supply_get_drvdata(psy);
1175 struct smb_charger *chg = &chip->chg;
1176 int rc = 0;
1177
1178 switch (psp) {
1179 case POWER_SUPPLY_PROP_INPUT_SUSPEND:
1180 rc = vote(chg->dc_suspend_votable, WBC_VOTER,
1181 (bool)val->intval, 0);
1182 break;
1183 default:
1184 return -EINVAL;
1185 }
1186
1187 return rc;
1188}
1189
1190static int smb5_dc_prop_is_writeable(struct power_supply *psy,
1191 enum power_supply_property psp)
1192{
1193 int rc;
1194
1195 switch (psp) {
1196 default:
1197 rc = 0;
1198 break;
1199 }
1200
1201 return rc;
1202}
1203
1204static const struct power_supply_desc dc_psy_desc = {
1205 .name = "dc",
1206 .type = POWER_SUPPLY_TYPE_WIRELESS,
1207 .properties = smb5_dc_props,
1208 .num_properties = ARRAY_SIZE(smb5_dc_props),
1209 .get_property = smb5_dc_get_prop,
1210 .set_property = smb5_dc_set_prop,
1211 .property_is_writeable = smb5_dc_prop_is_writeable,
1212};
1213
1214static int smb5_init_dc_psy(struct smb5 *chip)
1215{
1216 struct power_supply_config dc_cfg = {};
1217 struct smb_charger *chg = &chip->chg;
1218
1219 dc_cfg.drv_data = chip;
1220 dc_cfg.of_node = chg->dev->of_node;
1221 chg->dc_psy = devm_power_supply_register(chg->dev,
1222 &dc_psy_desc,
1223 &dc_cfg);
1224 if (IS_ERR(chg->dc_psy)) {
1225 pr_err("Couldn't register USB power supply\n");
1226 return PTR_ERR(chg->dc_psy);
1227 }
1228
1229 return 0;
1230}
1231
1232/*************************
1233 * BATT PSY REGISTRATION *
1234 *************************/
1235static enum power_supply_property smb5_batt_props[] = {
1236 POWER_SUPPLY_PROP_INPUT_SUSPEND,
Anirudh Ghayaldfdb8412018-04-21 10:37:18 +05301237 POWER_SUPPLY_PROP_BATTERY_CHARGING_ENABLED,
Harry Yang4b7db0f2017-11-27 10:50:44 -08001238 POWER_SUPPLY_PROP_STATUS,
1239 POWER_SUPPLY_PROP_HEALTH,
1240 POWER_SUPPLY_PROP_PRESENT,
1241 POWER_SUPPLY_PROP_CHARGE_TYPE,
1242 POWER_SUPPLY_PROP_CAPACITY,
1243 POWER_SUPPLY_PROP_INPUT_CURRENT_LIMITED,
1244 POWER_SUPPLY_PROP_VOLTAGE_NOW,
1245 POWER_SUPPLY_PROP_VOLTAGE_MAX,
1246 POWER_SUPPLY_PROP_CURRENT_NOW,
1247 POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX,
Guru Das Srinagesh3ca14372018-06-01 11:30:56 -07001248 POWER_SUPPLY_PROP_CHARGE_TERM_CURRENT,
Harry Yang4b7db0f2017-11-27 10:50:44 -08001249 POWER_SUPPLY_PROP_TEMP,
1250 POWER_SUPPLY_PROP_TECHNOLOGY,
1251 POWER_SUPPLY_PROP_STEP_CHARGING_ENABLED,
1252 POWER_SUPPLY_PROP_SW_JEITA_ENABLED,
1253 POWER_SUPPLY_PROP_CHARGE_DONE,
1254 POWER_SUPPLY_PROP_PARALLEL_DISABLE,
1255 POWER_SUPPLY_PROP_SET_SHIP_MODE,
1256 POWER_SUPPLY_PROP_DIE_HEALTH,
1257 POWER_SUPPLY_PROP_RERUN_AICL,
1258 POWER_SUPPLY_PROP_DP_DM,
1259 POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT_MAX,
1260 POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT,
1261 POWER_SUPPLY_PROP_CHARGE_COUNTER,
Subbaraman Narayanamurthyc4feb892018-05-07 18:43:45 -07001262 POWER_SUPPLY_PROP_CYCLE_COUNT,
Anirudh Ghayal1380d312018-02-23 00:01:43 +05301263 POWER_SUPPLY_PROP_RECHARGE_SOC,
Ashay Jaiswal5c5ba272018-07-23 14:54:20 +05301264 POWER_SUPPLY_PROP_CHARGE_FULL,
Umang Agrawal238086f2018-05-28 12:29:31 +05301265 POWER_SUPPLY_PROP_FCC_STEPPER_ENABLE,
Harry Yang4b7db0f2017-11-27 10:50:44 -08001266};
1267
Ashay Jaiswald802c3d2018-07-25 14:55:10 +05301268#define ITERM_SCALING_FACTOR_PMI632 1525
1269#define ITERM_SCALING_FACTOR_PM855B 3050
1270static int smb5_get_prop_batt_iterm(struct smb_charger *chg,
1271 union power_supply_propval *val)
1272{
1273 int rc, temp, scaling_factor;
1274 u8 stat, buf[2];
1275
1276 /*
1277 * Currently, only ADC comparator-based termination is supported,
1278 * hence read only the threshold corresponding to ADC source.
1279 * Proceed only if CHGR_ITERM_USE_ANALOG_BIT is 0.
1280 */
1281 rc = smblib_read(chg, CHGR_ENG_CHARGING_CFG_REG, &stat);
1282 if (rc < 0) {
1283 pr_err("Couldn't read CHGR_ENG_CHARGING_CFG_REG rc=%d\n", rc);
1284 return rc;
1285 }
1286
1287 if (stat & CHGR_ITERM_USE_ANALOG_BIT) {
1288 val->intval = -EINVAL;
1289 return 0;
1290 }
1291
1292 rc = smblib_batch_read(chg, CHGR_ADC_ITERM_UP_THD_MSB_REG, buf, 2);
1293
1294 if (rc < 0) {
1295 pr_err("Couldn't read CHGR_ADC_ITERM_UP_THD_MSB_REG rc=%d\n",
1296 rc);
1297 return rc;
1298 }
1299
1300 temp = buf[1] | (buf[0] << 8);
1301 temp = sign_extend32(temp, 15);
1302
1303 if (chg->smb_version == PMI632_SUBTYPE)
1304 scaling_factor = ITERM_SCALING_FACTOR_PMI632;
1305 else
1306 scaling_factor = ITERM_SCALING_FACTOR_PM855B;
1307
1308 temp = div_s64(temp * scaling_factor, 10000);
1309 val->intval = temp;
1310
1311 return rc;
1312}
1313
Harry Yang4b7db0f2017-11-27 10:50:44 -08001314static int smb5_batt_get_prop(struct power_supply *psy,
1315 enum power_supply_property psp,
1316 union power_supply_propval *val)
1317{
1318 struct smb_charger *chg = power_supply_get_drvdata(psy);
1319 int rc = 0;
1320
1321 switch (psp) {
1322 case POWER_SUPPLY_PROP_STATUS:
1323 rc = smblib_get_prop_batt_status(chg, val);
1324 break;
1325 case POWER_SUPPLY_PROP_HEALTH:
1326 rc = smblib_get_prop_batt_health(chg, val);
1327 break;
1328 case POWER_SUPPLY_PROP_PRESENT:
1329 rc = smblib_get_prop_batt_present(chg, val);
1330 break;
1331 case POWER_SUPPLY_PROP_INPUT_SUSPEND:
1332 rc = smblib_get_prop_input_suspend(chg, val);
1333 break;
Anirudh Ghayaldfdb8412018-04-21 10:37:18 +05301334 case POWER_SUPPLY_PROP_BATTERY_CHARGING_ENABLED:
1335 val->intval = !get_client_vote(chg->chg_disable_votable,
1336 USER_VOTER);
1337 break;
Harry Yang4b7db0f2017-11-27 10:50:44 -08001338 case POWER_SUPPLY_PROP_CHARGE_TYPE:
1339 rc = smblib_get_prop_batt_charge_type(chg, val);
1340 break;
1341 case POWER_SUPPLY_PROP_CAPACITY:
1342 rc = smblib_get_prop_batt_capacity(chg, val);
1343 break;
1344 case POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT:
1345 rc = smblib_get_prop_system_temp_level(chg, val);
1346 break;
1347 case POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT_MAX:
1348 rc = smblib_get_prop_system_temp_level_max(chg, val);
1349 break;
1350 case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMITED:
1351 rc = smblib_get_prop_input_current_limited(chg, val);
1352 break;
1353 case POWER_SUPPLY_PROP_STEP_CHARGING_ENABLED:
1354 val->intval = chg->step_chg_enabled;
1355 break;
1356 case POWER_SUPPLY_PROP_SW_JEITA_ENABLED:
1357 val->intval = chg->sw_jeita_enabled;
1358 break;
1359 case POWER_SUPPLY_PROP_VOLTAGE_NOW:
Ashay Jaiswal5c5ba272018-07-23 14:54:20 +05301360 rc = smblib_get_prop_from_bms(chg,
1361 POWER_SUPPLY_PROP_VOLTAGE_NOW, val);
Harry Yang4b7db0f2017-11-27 10:50:44 -08001362 break;
1363 case POWER_SUPPLY_PROP_VOLTAGE_MAX:
1364 val->intval = get_client_vote(chg->fv_votable,
1365 BATT_PROFILE_VOTER);
1366 break;
1367 case POWER_SUPPLY_PROP_CURRENT_NOW:
Ashay Jaiswal5c5ba272018-07-23 14:54:20 +05301368 rc = smblib_get_prop_from_bms(chg,
1369 POWER_SUPPLY_PROP_CURRENT_NOW, val);
Anirudh Ghayal87ae1f72018-11-12 17:02:21 +05301370 if (!rc)
1371 val->intval *= (-1);
Harry Yang4b7db0f2017-11-27 10:50:44 -08001372 break;
1373 case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX:
1374 val->intval = get_client_vote(chg->fcc_votable,
1375 BATT_PROFILE_VOTER);
1376 break;
Guru Das Srinagesh3ca14372018-06-01 11:30:56 -07001377 case POWER_SUPPLY_PROP_CHARGE_TERM_CURRENT:
Ashay Jaiswald802c3d2018-07-25 14:55:10 +05301378 rc = smb5_get_prop_batt_iterm(chg, val);
Guru Das Srinagesh3ca14372018-06-01 11:30:56 -07001379 break;
Harry Yang4b7db0f2017-11-27 10:50:44 -08001380 case POWER_SUPPLY_PROP_TEMP:
Ashay Jaiswal5c5ba272018-07-23 14:54:20 +05301381 rc = smblib_get_prop_from_bms(chg, POWER_SUPPLY_PROP_TEMP, val);
Harry Yang4b7db0f2017-11-27 10:50:44 -08001382 break;
1383 case POWER_SUPPLY_PROP_TECHNOLOGY:
1384 val->intval = POWER_SUPPLY_TECHNOLOGY_LION;
1385 break;
1386 case POWER_SUPPLY_PROP_CHARGE_DONE:
1387 rc = smblib_get_prop_batt_charge_done(chg, val);
1388 break;
1389 case POWER_SUPPLY_PROP_PARALLEL_DISABLE:
1390 val->intval = get_client_vote(chg->pl_disable_votable,
1391 USER_VOTER);
1392 break;
1393 case POWER_SUPPLY_PROP_SET_SHIP_MODE:
1394 /* Not in ship mode as long as device is active */
1395 val->intval = 0;
1396 break;
1397 case POWER_SUPPLY_PROP_DIE_HEALTH:
1398 if (chg->die_health == -EINVAL)
1399 rc = smblib_get_prop_die_health(chg, val);
1400 else
1401 val->intval = chg->die_health;
1402 break;
1403 case POWER_SUPPLY_PROP_DP_DM:
1404 val->intval = chg->pulse_cnt;
1405 break;
1406 case POWER_SUPPLY_PROP_RERUN_AICL:
1407 val->intval = 0;
1408 break;
1409 case POWER_SUPPLY_PROP_CHARGE_COUNTER:
Ashay Jaiswal5c5ba272018-07-23 14:54:20 +05301410 rc = smblib_get_prop_from_bms(chg,
1411 POWER_SUPPLY_PROP_CHARGE_COUNTER, val);
Harry Yang4b7db0f2017-11-27 10:50:44 -08001412 break;
Subbaraman Narayanamurthyc4feb892018-05-07 18:43:45 -07001413 case POWER_SUPPLY_PROP_CYCLE_COUNT:
Ashay Jaiswal5c5ba272018-07-23 14:54:20 +05301414 rc = smblib_get_prop_from_bms(chg,
1415 POWER_SUPPLY_PROP_CYCLE_COUNT, val);
Subbaraman Narayanamurthyc4feb892018-05-07 18:43:45 -07001416 break;
Anirudh Ghayal1380d312018-02-23 00:01:43 +05301417 case POWER_SUPPLY_PROP_RECHARGE_SOC:
1418 val->intval = chg->auto_recharge_soc;
1419 break;
Ashay Jaiswal5c5ba272018-07-23 14:54:20 +05301420 case POWER_SUPPLY_PROP_CHARGE_FULL:
1421 rc = smblib_get_prop_from_bms(chg,
1422 POWER_SUPPLY_PROP_CHARGE_FULL, val);
1423 break;
Umang Agrawal238086f2018-05-28 12:29:31 +05301424 case POWER_SUPPLY_PROP_FCC_STEPPER_ENABLE:
1425 val->intval = chg->fcc_stepper_enable;
1426 break;
Harry Yang4b7db0f2017-11-27 10:50:44 -08001427 default:
1428 pr_err("batt power supply prop %d not supported\n", psp);
1429 return -EINVAL;
1430 }
1431
1432 if (rc < 0) {
1433 pr_debug("Couldn't get prop %d rc = %d\n", psp, rc);
1434 return -ENODATA;
1435 }
1436
1437 return 0;
1438}
1439
1440static int smb5_batt_set_prop(struct power_supply *psy,
1441 enum power_supply_property prop,
1442 const union power_supply_propval *val)
1443{
1444 int rc = 0;
1445 struct smb_charger *chg = power_supply_get_drvdata(psy);
Ashay Jaiswala55b7ed2018-03-23 17:23:48 +05301446 bool enable;
Harry Yang4b7db0f2017-11-27 10:50:44 -08001447
1448 switch (prop) {
1449 case POWER_SUPPLY_PROP_STATUS:
1450 rc = smblib_set_prop_batt_status(chg, val);
1451 break;
1452 case POWER_SUPPLY_PROP_INPUT_SUSPEND:
1453 rc = smblib_set_prop_input_suspend(chg, val);
1454 break;
Anirudh Ghayaldfdb8412018-04-21 10:37:18 +05301455 case POWER_SUPPLY_PROP_BATTERY_CHARGING_ENABLED:
1456 vote(chg->chg_disable_votable, USER_VOTER, !val->intval, 0);
1457 break;
Harry Yang4b7db0f2017-11-27 10:50:44 -08001458 case POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT:
1459 rc = smblib_set_prop_system_temp_level(chg, val);
1460 break;
1461 case POWER_SUPPLY_PROP_CAPACITY:
1462 rc = smblib_set_prop_batt_capacity(chg, val);
1463 break;
1464 case POWER_SUPPLY_PROP_PARALLEL_DISABLE:
1465 vote(chg->pl_disable_votable, USER_VOTER, (bool)val->intval, 0);
1466 break;
1467 case POWER_SUPPLY_PROP_VOLTAGE_MAX:
1468 chg->batt_profile_fv_uv = val->intval;
1469 vote(chg->fv_votable, BATT_PROFILE_VOTER, true, val->intval);
1470 break;
1471 case POWER_SUPPLY_PROP_STEP_CHARGING_ENABLED:
Ashay Jaiswala55b7ed2018-03-23 17:23:48 +05301472 enable = !!val->intval || chg->sw_jeita_enabled;
1473 rc = smblib_configure_wdog(chg, enable);
1474 if (rc == 0)
1475 chg->step_chg_enabled = !!val->intval;
Harry Yang4b7db0f2017-11-27 10:50:44 -08001476 break;
1477 case POWER_SUPPLY_PROP_SW_JEITA_ENABLED:
1478 if (chg->sw_jeita_enabled != (!!val->intval)) {
1479 rc = smblib_disable_hw_jeita(chg, !!val->intval);
Ashay Jaiswala55b7ed2018-03-23 17:23:48 +05301480 enable = !!val->intval || chg->step_chg_enabled;
1481 rc |= smblib_configure_wdog(chg, enable);
Harry Yang4b7db0f2017-11-27 10:50:44 -08001482 if (rc == 0)
1483 chg->sw_jeita_enabled = !!val->intval;
1484 }
1485 break;
1486 case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX:
1487 chg->batt_profile_fcc_ua = val->intval;
1488 vote(chg->fcc_votable, BATT_PROFILE_VOTER, true, val->intval);
1489 break;
1490 case POWER_SUPPLY_PROP_SET_SHIP_MODE:
1491 /* Not in ship mode as long as the device is active */
1492 if (!val->intval)
1493 break;
1494 if (chg->pl.psy)
1495 power_supply_set_property(chg->pl.psy,
1496 POWER_SUPPLY_PROP_SET_SHIP_MODE, val);
1497 rc = smblib_set_prop_ship_mode(chg, val);
1498 break;
1499 case POWER_SUPPLY_PROP_RERUN_AICL:
Ashay Jaiswale0b3c472018-06-20 23:39:41 +05301500 rc = smblib_run_aicl(chg, RERUN_AICL);
Harry Yang4b7db0f2017-11-27 10:50:44 -08001501 break;
1502 case POWER_SUPPLY_PROP_DP_DM:
Ashay Jaiswal4d334f42018-04-25 10:58:49 +05301503 if (!chg->flash_active)
1504 rc = smblib_dp_dm(chg, val->intval);
Harry Yang4b7db0f2017-11-27 10:50:44 -08001505 break;
1506 case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMITED:
1507 rc = smblib_set_prop_input_current_limited(chg, val);
1508 break;
1509 case POWER_SUPPLY_PROP_DIE_HEALTH:
1510 chg->die_health = val->intval;
1511 power_supply_changed(chg->batt_psy);
1512 break;
Anirudh Ghayaldfdb8412018-04-21 10:37:18 +05301513 case POWER_SUPPLY_PROP_RECHARGE_SOC:
1514 if (chg->smb_version == PMI632_SUBTYPE) {
1515 /* toggle charging to force recharge */
1516 vote(chg->chg_disable_votable, FORCE_RECHARGE_VOTER,
1517 true, 0);
1518 /* charge disable delay */
1519 msleep(50);
1520 vote(chg->chg_disable_votable, FORCE_RECHARGE_VOTER,
1521 false, 0);
1522 }
1523 break;
Harry Yang4b7db0f2017-11-27 10:50:44 -08001524 default:
1525 rc = -EINVAL;
1526 }
1527
1528 return rc;
1529}
1530
1531static int smb5_batt_prop_is_writeable(struct power_supply *psy,
1532 enum power_supply_property psp)
1533{
1534 switch (psp) {
1535 case POWER_SUPPLY_PROP_STATUS:
1536 case POWER_SUPPLY_PROP_INPUT_SUSPEND:
1537 case POWER_SUPPLY_PROP_SYSTEM_TEMP_LEVEL:
1538 case POWER_SUPPLY_PROP_CAPACITY:
1539 case POWER_SUPPLY_PROP_PARALLEL_DISABLE:
1540 case POWER_SUPPLY_PROP_DP_DM:
1541 case POWER_SUPPLY_PROP_RERUN_AICL:
1542 case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMITED:
1543 case POWER_SUPPLY_PROP_STEP_CHARGING_ENABLED:
1544 case POWER_SUPPLY_PROP_SW_JEITA_ENABLED:
1545 case POWER_SUPPLY_PROP_DIE_HEALTH:
Anirudh Ghayaldfdb8412018-04-21 10:37:18 +05301546 case POWER_SUPPLY_PROP_BATTERY_CHARGING_ENABLED:
Harry Yang4b7db0f2017-11-27 10:50:44 -08001547 return 1;
1548 default:
1549 break;
1550 }
1551
1552 return 0;
1553}
1554
1555static const struct power_supply_desc batt_psy_desc = {
1556 .name = "battery",
1557 .type = POWER_SUPPLY_TYPE_BATTERY,
1558 .properties = smb5_batt_props,
1559 .num_properties = ARRAY_SIZE(smb5_batt_props),
1560 .get_property = smb5_batt_get_prop,
1561 .set_property = smb5_batt_set_prop,
1562 .property_is_writeable = smb5_batt_prop_is_writeable,
1563};
1564
1565static int smb5_init_batt_psy(struct smb5 *chip)
1566{
1567 struct power_supply_config batt_cfg = {};
1568 struct smb_charger *chg = &chip->chg;
1569 int rc = 0;
1570
1571 batt_cfg.drv_data = chg;
1572 batt_cfg.of_node = chg->dev->of_node;
1573 chg->batt_psy = devm_power_supply_register(chg->dev,
1574 &batt_psy_desc,
1575 &batt_cfg);
1576 if (IS_ERR(chg->batt_psy)) {
1577 pr_err("Couldn't register battery power supply\n");
1578 return PTR_ERR(chg->batt_psy);
1579 }
1580
1581 return rc;
1582}
1583
1584/******************************
1585 * VBUS REGULATOR REGISTRATION *
1586 ******************************/
1587
1588static struct regulator_ops smb5_vbus_reg_ops = {
1589 .enable = smblib_vbus_regulator_enable,
1590 .disable = smblib_vbus_regulator_disable,
1591 .is_enabled = smblib_vbus_regulator_is_enabled,
1592};
1593
1594static int smb5_init_vbus_regulator(struct smb5 *chip)
1595{
1596 struct smb_charger *chg = &chip->chg;
1597 struct regulator_config cfg = {};
1598 int rc = 0;
1599
1600 chg->vbus_vreg = devm_kzalloc(chg->dev, sizeof(*chg->vbus_vreg),
1601 GFP_KERNEL);
1602 if (!chg->vbus_vreg)
1603 return -ENOMEM;
1604
1605 cfg.dev = chg->dev;
1606 cfg.driver_data = chip;
1607
1608 chg->vbus_vreg->rdesc.owner = THIS_MODULE;
1609 chg->vbus_vreg->rdesc.type = REGULATOR_VOLTAGE;
1610 chg->vbus_vreg->rdesc.ops = &smb5_vbus_reg_ops;
1611 chg->vbus_vreg->rdesc.of_match = "qcom,smb5-vbus";
1612 chg->vbus_vreg->rdesc.name = "qcom,smb5-vbus";
1613
1614 chg->vbus_vreg->rdev = devm_regulator_register(chg->dev,
1615 &chg->vbus_vreg->rdesc, &cfg);
1616 if (IS_ERR(chg->vbus_vreg->rdev)) {
1617 rc = PTR_ERR(chg->vbus_vreg->rdev);
1618 chg->vbus_vreg->rdev = NULL;
1619 if (rc != -EPROBE_DEFER)
1620 pr_err("Couldn't register VBUS regulator rc=%d\n", rc);
1621 }
1622
1623 return rc;
1624}
1625
1626/******************************
1627 * VCONN REGULATOR REGISTRATION *
1628 ******************************/
1629
1630static struct regulator_ops smb5_vconn_reg_ops = {
1631 .enable = smblib_vconn_regulator_enable,
1632 .disable = smblib_vconn_regulator_disable,
1633 .is_enabled = smblib_vconn_regulator_is_enabled,
1634};
1635
1636static int smb5_init_vconn_regulator(struct smb5 *chip)
1637{
1638 struct smb_charger *chg = &chip->chg;
1639 struct regulator_config cfg = {};
1640 int rc = 0;
1641
Ashay Jaiswala9e10912018-02-02 14:03:35 +05301642 if (chg->connector_type == POWER_SUPPLY_CONNECTOR_MICRO_USB)
Harry Yang4b7db0f2017-11-27 10:50:44 -08001643 return 0;
1644
1645 chg->vconn_vreg = devm_kzalloc(chg->dev, sizeof(*chg->vconn_vreg),
1646 GFP_KERNEL);
1647 if (!chg->vconn_vreg)
1648 return -ENOMEM;
1649
1650 cfg.dev = chg->dev;
1651 cfg.driver_data = chip;
1652
1653 chg->vconn_vreg->rdesc.owner = THIS_MODULE;
1654 chg->vconn_vreg->rdesc.type = REGULATOR_VOLTAGE;
1655 chg->vconn_vreg->rdesc.ops = &smb5_vconn_reg_ops;
1656 chg->vconn_vreg->rdesc.of_match = "qcom,smb5-vconn";
1657 chg->vconn_vreg->rdesc.name = "qcom,smb5-vconn";
1658
1659 chg->vconn_vreg->rdev = devm_regulator_register(chg->dev,
1660 &chg->vconn_vreg->rdesc, &cfg);
1661 if (IS_ERR(chg->vconn_vreg->rdev)) {
1662 rc = PTR_ERR(chg->vconn_vreg->rdev);
1663 chg->vconn_vreg->rdev = NULL;
1664 if (rc != -EPROBE_DEFER)
1665 pr_err("Couldn't register VCONN regulator rc=%d\n", rc);
1666 }
1667
1668 return rc;
1669}
1670
1671/***************************
1672 * HARDWARE INITIALIZATION *
1673 ***************************/
jessicatseng7db9b542018-11-27 16:14:44 +08001674//<2018/11/27-JessicaTseng, Qualcomm's patch is to fix current consumption
Harry Yang4b7db0f2017-11-27 10:50:44 -08001675static int smb5_configure_typec(struct smb_charger *chg)
1676{
1677 int rc;
jessicatseng7db9b542018-11-27 16:14:44 +08001678 u8 val = 0, rid_int_src = 0;
Ashay Jaiswal91d63f42018-05-16 11:30:40 +05301679
1680 rc = smblib_read(chg, LEGACY_CABLE_STATUS_REG, &val);
1681 if (rc < 0) {
1682 dev_err(chg->dev, "Couldn't read Legacy status rc=%d\n", rc);
1683 return rc;
1684 }
1685 /*
1686 * If Legacy cable is detected re-trigger Legacy detection
1687 * by disabling/enabling typeC mode.
1688 */
1689 if (val & TYPEC_LEGACY_CABLE_STATUS_BIT) {
1690 rc = smblib_masked_write(chg, TYPE_C_MODE_CFG_REG,
1691 TYPEC_DISABLE_CMD_BIT, TYPEC_DISABLE_CMD_BIT);
1692 if (rc < 0) {
1693 dev_err(chg->dev, "Couldn't disable TYPEC rc=%d\n", rc);
1694 return rc;
1695 }
1696
1697 /* delay before enabling typeC */
1698 msleep(500);
1699
1700 rc = smblib_masked_write(chg, TYPE_C_MODE_CFG_REG,
1701 TYPEC_DISABLE_CMD_BIT, 0);
1702 if (rc < 0) {
1703 dev_err(chg->dev, "Couldn't enable TYPEC rc=%d\n", rc);
1704 return rc;
1705 }
1706 }
Harry Yang4b7db0f2017-11-27 10:50:44 -08001707
Harry Yang6afaea22018-03-26 19:11:07 -07001708 /* disable apsd */
Ashay Jaiswalc96380de2018-05-16 12:02:36 +05301709 rc = smblib_configure_hvdcp_apsd(chg, false);
Harry Yang6afaea22018-03-26 19:11:07 -07001710 if (rc < 0) {
1711 dev_err(chg->dev, "Couldn't disable APSD rc=%d\n", rc);
1712 return rc;
1713 }
1714
Harry Yang4b7db0f2017-11-27 10:50:44 -08001715 rc = smblib_write(chg, TYPE_C_INTERRUPT_EN_CFG_1_REG,
1716 TYPEC_CCOUT_DETACH_INT_EN_BIT |
1717 TYPEC_CCOUT_ATTACH_INT_EN_BIT);
1718 if (rc < 0) {
1719 dev_err(chg->dev,
1720 "Couldn't configure Type-C interrupts rc=%d\n", rc);
1721 return rc;
1722 }
1723
Harry Yang423d5c32018-05-30 15:49:04 -07001724 rc = smblib_masked_write(chg, TYPE_C_MODE_CFG_REG,
1725 EN_TRY_SNK_BIT, EN_TRY_SNK_BIT);
1726 if (rc < 0) {
1727 dev_err(chg->dev,
1728 "Couldn't enable try.snk rc=%d\n", rc);
1729 return rc;
1730 }
1731
Ashay Jaiswald5022b62018-05-27 19:21:11 +05301732 /* Keep VCONN in h/w controlled mode for PMI632 */
1733 if (chg->smb_version != PMI632_SUBTYPE) {
1734 /* configure VCONN for software control */
1735 rc = smblib_masked_write(chg, TYPE_C_VCONN_CONTROL_REG,
Harry Yang4b7db0f2017-11-27 10:50:44 -08001736 VCONN_EN_SRC_BIT | VCONN_EN_VALUE_BIT,
1737 VCONN_EN_SRC_BIT);
Ashay Jaiswald5022b62018-05-27 19:21:11 +05301738 if (rc < 0) {
1739 dev_err(chg->dev,
1740 "Couldn't configure VCONN for SW control rc=%d\n",
1741 rc);
1742 return rc;
1743 }
jessicatseng7db9b542018-11-27 16:14:44 +08001744
1745 /* Enable Water detection rid source interrupt */
1746 rid_int_src |= TYPEC_WATER_DETECTION_INT_EN_BIT;
1747 }
1748
1749 /* Disable rid source interrupts which are not required. */
1750 rc = smblib_write(chg, TYPE_C_INTERRUPT_EN_CFG_2_REG, rid_int_src);
1751 if (rc < 0) {
1752 dev_err(chg->dev, "Couldn't configure Type-C interrupts rc=%d\n", rc);
1753 return rc;
Harry Yang4b7db0f2017-11-27 10:50:44 -08001754 }
1755
Umang Agrawalc1bb1382018-09-17 15:36:43 +05301756 /* Disable TypeC and RID change source interrupts */
1757 rc = smblib_write(chg, TYPE_C_INTERRUPT_EN_CFG_2_REG, 0);
1758 if (rc < 0) {
1759 dev_err(chg->dev,
1760 "Couldn't configure Type-C interrupts rc=%d\n", rc);
1761 return rc;
1762 }
1763
Harry Yang4b7db0f2017-11-27 10:50:44 -08001764 return rc;
1765}
jessicatseng7db9b542018-11-27 16:14:44 +08001766//>2018/11/27-JessicaTseng
Harry Yang4b7db0f2017-11-27 10:50:44 -08001767
1768static int smb5_configure_micro_usb(struct smb_charger *chg)
1769{
1770 int rc;
1771
Ashay Jaiswala9e10912018-02-02 14:03:35 +05301772 rc = smblib_masked_write(chg, TYPE_C_INTERRUPT_EN_CFG_2_REG,
1773 MICRO_USB_STATE_CHANGE_INT_EN_BIT,
1774 MICRO_USB_STATE_CHANGE_INT_EN_BIT);
1775 if (rc < 0) {
1776 dev_err(chg->dev,
1777 "Couldn't configure Type-C interrupts rc=%d\n", rc);
1778 return rc;
1779 }
1780
Umang Agrawal461e9ea2018-07-05 18:50:13 +05301781 if (chg->moisture_protection_enabled &&
1782 (chg->wa_flags & MOISTURE_PROTECTION_WA)) {
1783 /* Enable moisture detection interrupt */
1784 rc = smblib_masked_write(chg, TYPE_C_INTERRUPT_EN_CFG_2_REG,
1785 TYPEC_WATER_DETECTION_INT_EN_BIT,
1786 TYPEC_WATER_DETECTION_INT_EN_BIT);
1787 if (rc < 0) {
1788 dev_err(chg->dev, "Couldn't enable moisture detection interrupt rc=%d\n",
1789 rc);
1790 return rc;
1791 }
1792
1793 /* Enable uUSB factory mode */
1794 rc = smblib_masked_write(chg, TYPEC_U_USB_CFG_REG,
1795 EN_MICRO_USB_FACTORY_MODE_BIT,
1796 EN_MICRO_USB_FACTORY_MODE_BIT);
1797 if (rc < 0) {
1798 dev_err(chg->dev, "Couldn't enable uUSB factory mode c=%d\n",
1799 rc);
1800 return rc;
1801 }
1802
1803 /* Disable periodic monitoring of CC_ID pin */
1804 rc = smblib_write(chg, TYPEC_U_USB_WATER_PROTECTION_CFG_REG, 0);
1805 if (rc < 0) {
1806 dev_err(chg->dev, "Couldn't disable periodic monitoring of CC_ID rc=%d\n",
1807 rc);
1808 return rc;
1809 }
1810 }
1811
Harry Yang4b7db0f2017-11-27 10:50:44 -08001812 return rc;
1813}
1814
Ashay Jaiswal0de6fb92018-06-12 17:23:45 +05301815static int smb5_configure_mitigation(struct smb_charger *chg)
1816{
1817 int rc;
Ashay Jaiswal40b66272018-09-03 16:08:54 +05301818 u8 chan = 0, src_cfg = 0;
Ashay Jaiswal0de6fb92018-06-12 17:23:45 +05301819
1820 if (!chg->hw_die_temp_mitigation && !chg->hw_connector_mitigation)
1821 return 0;
1822
1823 if (chg->hw_die_temp_mitigation) {
Ashay Jaiswal0de6fb92018-06-12 17:23:45 +05301824 chan = DIE_TEMP_CHANNEL_EN_BIT;
Ashay Jaiswal40b66272018-09-03 16:08:54 +05301825 src_cfg = THERMREG_DIE_ADC_SRC_EN_BIT
1826 | THERMREG_DIE_CMP_SRC_EN_BIT;
Ashay Jaiswal0de6fb92018-06-12 17:23:45 +05301827 }
1828
Ashay Jaiswal40b66272018-09-03 16:08:54 +05301829 if (chg->hw_connector_mitigation) {
Ashay Jaiswal0de6fb92018-06-12 17:23:45 +05301830 chan |= CONN_THM_CHANNEL_EN_BIT;
Ashay Jaiswal40b66272018-09-03 16:08:54 +05301831 src_cfg |= THERMREG_CONNECTOR_ADC_SRC_EN_BIT;
1832 }
1833
1834 rc = smblib_masked_write(chg, MISC_THERMREG_SRC_CFG_REG,
1835 THERMREG_SW_ICL_ADJUST_BIT | THERMREG_DIE_ADC_SRC_EN_BIT
1836 | THERMREG_DIE_CMP_SRC_EN_BIT
1837 | THERMREG_CONNECTOR_ADC_SRC_EN_BIT, src_cfg);
1838 if (rc < 0) {
1839 dev_err(chg->dev,
1840 "Couldn't configure THERM_SRC reg rc=%d\n", rc);
1841 return rc;
1842 };
Ashay Jaiswal0de6fb92018-06-12 17:23:45 +05301843
1844 rc = smblib_masked_write(chg, BATIF_ADC_CHANNEL_EN_REG,
1845 CONN_THM_CHANNEL_EN_BIT | DIE_TEMP_CHANNEL_EN_BIT,
1846 chan);
1847 if (rc < 0) {
Ashay Jaiswalb50706d2018-06-28 19:37:31 +05301848 dev_err(chg->dev, "Couldn't enable ADC channel rc=%d\n", rc);
Ashay Jaiswal0de6fb92018-06-12 17:23:45 +05301849 return rc;
1850 }
1851
1852 return 0;
1853}
1854
Ashay Jaiswald802c3d2018-07-25 14:55:10 +05301855#define RAW_TERM_CURR(conv_factor, scaled_ma) \
1856 div_s64((int64_t)scaled_ma * 10000, conv_factor)
1857#define ITERM_LIMITS_PMI632_MA 5000
1858#define ITERM_LIMITS_PM855B_MA 10000
Guru Das Srinagesh3ca14372018-06-01 11:30:56 -07001859static int smb5_configure_iterm_thresholds_adc(struct smb5 *chip)
1860{
Guru Das Srinagesh31b2bb02018-06-20 15:44:03 -07001861 u8 *buf;
Guru Das Srinagesh3ca14372018-06-01 11:30:56 -07001862 int rc = 0;
Ashay Jaiswald802c3d2018-07-25 14:55:10 +05301863 int raw_hi_thresh, raw_lo_thresh, max_limit_ma, scaling_factor;
Guru Das Srinagesh3ca14372018-06-01 11:30:56 -07001864 struct smb_charger *chg = &chip->chg;
1865
Ashay Jaiswald802c3d2018-07-25 14:55:10 +05301866 if (chip->chg.smb_version == PMI632_SUBTYPE) {
1867 scaling_factor = ITERM_SCALING_FACTOR_PMI632;
1868 max_limit_ma = ITERM_LIMITS_PMI632_MA;
1869 } else {
1870 scaling_factor = ITERM_SCALING_FACTOR_PM855B;
1871 max_limit_ma = ITERM_LIMITS_PM855B_MA;
1872 }
1873
1874 if (chip->dt.term_current_thresh_hi_ma < (-1 * max_limit_ma)
1875 || chip->dt.term_current_thresh_hi_ma > max_limit_ma
1876 || chip->dt.term_current_thresh_lo_ma < (-1 * max_limit_ma)
1877 || chip->dt.term_current_thresh_lo_ma > max_limit_ma) {
Guru Das Srinagesh3ca14372018-06-01 11:30:56 -07001878 dev_err(chg->dev, "ITERM threshold out of range rc=%d\n", rc);
1879 return -EINVAL;
1880 }
1881
1882 /*
1883 * Conversion:
Ashay Jaiswald802c3d2018-07-25 14:55:10 +05301884 * raw (A) = (scaled_mA * (10000) / conv_factor)
Guru Das Srinagesh31b2bb02018-06-20 15:44:03 -07001885 * Note: raw needs to be converted to big-endian format.
Guru Das Srinagesh3ca14372018-06-01 11:30:56 -07001886 */
1887
1888 if (chip->dt.term_current_thresh_hi_ma) {
Ashay Jaiswald802c3d2018-07-25 14:55:10 +05301889 raw_hi_thresh = RAW_TERM_CURR(scaling_factor,
1890 chip->dt.term_current_thresh_hi_ma);
Guru Das Srinagesh3ca14372018-06-01 11:30:56 -07001891 raw_hi_thresh = sign_extend32(raw_hi_thresh, 15);
Guru Das Srinagesh31b2bb02018-06-20 15:44:03 -07001892 buf = (u8 *)&raw_hi_thresh;
1893 raw_hi_thresh = buf[1] | (buf[0] << 8);
Guru Das Srinagesh3ca14372018-06-01 11:30:56 -07001894
1895 rc = smblib_batch_write(chg, CHGR_ADC_ITERM_UP_THD_MSB_REG,
1896 (u8 *)&raw_hi_thresh, 2);
1897 if (rc < 0) {
1898 dev_err(chg->dev, "Couldn't configure ITERM threshold HIGH rc=%d\n",
1899 rc);
1900 return rc;
1901 }
1902 }
1903
1904 if (chip->dt.term_current_thresh_lo_ma) {
Ashay Jaiswald802c3d2018-07-25 14:55:10 +05301905 raw_lo_thresh = RAW_TERM_CURR(scaling_factor,
1906 chip->dt.term_current_thresh_lo_ma);
Guru Das Srinagesh3ca14372018-06-01 11:30:56 -07001907 raw_lo_thresh = sign_extend32(raw_lo_thresh, 15);
Guru Das Srinagesh31b2bb02018-06-20 15:44:03 -07001908 buf = (u8 *)&raw_lo_thresh;
1909 raw_lo_thresh = buf[1] | (buf[0] << 8);
Guru Das Srinagesh3ca14372018-06-01 11:30:56 -07001910
1911 rc = smblib_batch_write(chg, CHGR_ADC_ITERM_LO_THD_MSB_REG,
1912 (u8 *)&raw_lo_thresh, 2);
1913 if (rc < 0) {
1914 dev_err(chg->dev, "Couldn't configure ITERM threshold LOW rc=%d\n",
1915 rc);
1916 return rc;
1917 }
1918 }
1919
1920 return rc;
1921}
1922
1923static int smb5_configure_iterm_thresholds(struct smb5 *chip)
1924{
1925 int rc = 0;
1926
1927 switch (chip->dt.term_current_src) {
1928 case ITERM_SRC_ADC:
1929 rc = smb5_configure_iterm_thresholds_adc(chip);
1930 break;
1931 default:
1932 break;
1933 }
1934
1935 return rc;
1936}
1937
Harry Yang4b7db0f2017-11-27 10:50:44 -08001938static int smb5_init_hw(struct smb5 *chip)
1939{
1940 struct smb_charger *chg = &chip->chg;
Ashay Jaiswala9e10912018-02-02 14:03:35 +05301941 int rc, type = 0;
1942 u8 val = 0;
Harry Yang4b7db0f2017-11-27 10:50:44 -08001943
1944 if (chip->dt.no_battery)
1945 chg->fake_capacity = 50;
1946
1947 if (chip->dt.batt_profile_fcc_ua < 0)
1948 smblib_get_charge_param(chg, &chg->param.fcc,
1949 &chg->batt_profile_fcc_ua);
1950
1951 if (chip->dt.batt_profile_fv_uv < 0)
1952 smblib_get_charge_param(chg, &chg->param.fv,
1953 &chg->batt_profile_fv_uv);
1954
1955 smblib_get_charge_param(chg, &chg->param.usb_icl,
1956 &chg->default_icl_ua);
Ashay Jaiswale0b3c472018-06-20 23:39:41 +05301957 smblib_get_charge_param(chg, &chg->param.aicl_5v_threshold,
1958 &chg->default_aicl_5v_threshold_mv);
1959 chg->aicl_5v_threshold_mv = chg->default_aicl_5v_threshold_mv;
1960 smblib_get_charge_param(chg, &chg->param.aicl_cont_threshold,
1961 &chg->default_aicl_cont_threshold_mv);
1962 chg->aicl_cont_threshold_mv = chg->default_aicl_cont_threshold_mv;
Ashay Jaiswala9e10912018-02-02 14:03:35 +05301963
1964 /* Use SW based VBUS control, disable HW autonomous mode */
Ashay Jaiswala9e10912018-02-02 14:03:35 +05301965 rc = smblib_masked_write(chg, USBIN_OPTIONS_1_CFG_REG,
1966 HVDCP_AUTH_ALG_EN_CFG_BIT | HVDCP_AUTONOMOUS_MODE_EN_CFG_BIT,
1967 HVDCP_AUTH_ALG_EN_CFG_BIT);
1968 if (rc < 0) {
1969 dev_err(chg->dev, "Couldn't configure HVDCP rc=%d\n", rc);
1970 return rc;
1971 }
1972
1973 /*
1974 * PMI632 can have the connector type defined by a dedicated register
1975 * TYPEC_MICRO_USB_MODE_REG or by a common TYPEC_U_USB_CFG_REG.
1976 */
1977 if (chg->smb_version == PMI632_SUBTYPE) {
1978 rc = smblib_read(chg, TYPEC_MICRO_USB_MODE_REG, &val);
1979 if (rc < 0) {
1980 dev_err(chg->dev, "Couldn't read USB mode rc=%d\n", rc);
1981 return rc;
1982 }
1983 type = !!(val & MICRO_USB_MODE_ONLY_BIT);
1984 }
1985
1986 /*
1987 * If TYPEC_MICRO_USB_MODE_REG is not set and for all non-PMI632
1988 * check the connector type using TYPEC_U_USB_CFG_REG.
1989 */
1990 if (!type) {
1991 rc = smblib_read(chg, TYPEC_U_USB_CFG_REG, &val);
1992 if (rc < 0) {
1993 dev_err(chg->dev, "Couldn't read U_USB config rc=%d\n",
1994 rc);
1995 return rc;
1996 }
1997
1998 type = !!(val & EN_MICRO_USB_MODE_BIT);
1999 }
2000
Ashay Jaiswala9e10912018-02-02 14:03:35 +05302001 pr_debug("Connector type=%s\n", type ? "Micro USB" : "TypeC");
2002
Harry Yang6afaea22018-03-26 19:11:07 -07002003 if (type) {
2004 chg->connector_type = POWER_SUPPLY_CONNECTOR_MICRO_USB;
Harry Yang6afaea22018-03-26 19:11:07 -07002005 rc = smb5_configure_micro_usb(chg);
2006 } else {
2007 chg->connector_type = POWER_SUPPLY_CONNECTOR_TYPEC;
2008 rc = smb5_configure_typec(chg);
2009 }
2010 if (rc < 0) {
2011 dev_err(chg->dev,
2012 "Couldn't configure TypeC/micro-USB mode rc=%d\n", rc);
2013 return rc;
2014 }
2015
Ashay Jaiswal09feab82018-02-12 12:33:18 +05302016 /*
2017 * PMI632 based hw init:
Ashay Jaiswal6f70a512018-05-11 17:25:58 +05302018 * - Enable STAT pin function on SMB_EN
Ashay Jaiswalc96380de2018-05-16 12:02:36 +05302019 * - Rerun APSD to ensure proper charger detection if device
2020 * boots with charger connected.
Ashay Jaiswal09feab82018-02-12 12:33:18 +05302021 * - Initialize flash module for PMI632
2022 */
Ashay Jaiswalc96380de2018-05-16 12:02:36 +05302023 if (chg->smb_version == PMI632_SUBTYPE) {
Ashay Jaiswal6f70a512018-05-11 17:25:58 +05302024 rc = smblib_masked_write(chg, MISC_SMB_EN_CMD_REG,
2025 EN_STAT_CMD_BIT, EN_STAT_CMD_BIT);
2026 if (rc < 0) {
2027 dev_err(chg->dev, "Couldn't configure SMB_EN rc=%d\n",
2028 rc);
2029 return rc;
2030 }
2031
Ashay Jaiswal09feab82018-02-12 12:33:18 +05302032 schgm_flash_init(chg);
Ashay Jaiswalc96380de2018-05-16 12:02:36 +05302033 smblib_rerun_apsd_if_required(chg);
2034 }
Ashay Jaiswal09feab82018-02-12 12:33:18 +05302035
Ashay Jaiswalcbdf2e82018-05-27 23:59:01 +05302036 /* clear the ICL override if it is set */
2037 rc = smblib_icl_override(chg, false);
2038 if (rc < 0) {
2039 pr_err("Couldn't disable ICL override rc=%d\n", rc);
2040 return rc;
2041 }
2042
Ashay Jaiswalb2b06fe2018-06-07 18:35:21 +05302043 /* set OTG current limit */
2044 rc = smblib_set_charge_param(chg, &chg->param.otg_cl, chg->otg_cl_ua);
2045 if (rc < 0) {
2046 pr_err("Couldn't set otg current limit rc=%d\n", rc);
2047 return rc;
2048 }
2049
Ashay Jaiswal0de6fb92018-06-12 17:23:45 +05302050 /* configure temperature mitigation */
2051 rc = smb5_configure_mitigation(chg);
2052 if (rc < 0) {
2053 dev_err(chg->dev, "Couldn't configure mitigation rc=%d\n", rc);
2054 return rc;
2055 }
2056
Harry Yang4b7db0f2017-11-27 10:50:44 -08002057 /* vote 0mA on usb_icl for non battery platforms */
2058 vote(chg->usb_icl_votable,
2059 DEFAULT_VOTER, chip->dt.no_battery, 0);
2060 vote(chg->dc_suspend_votable,
2061 DEFAULT_VOTER, chip->dt.no_battery, 0);
2062 vote(chg->fcc_votable, HW_LIMIT_VOTER,
2063 chip->dt.batt_profile_fcc_ua > 0, chip->dt.batt_profile_fcc_ua);
2064 vote(chg->fv_votable, HW_LIMIT_VOTER,
2065 chip->dt.batt_profile_fv_uv > 0, chip->dt.batt_profile_fv_uv);
2066 vote(chg->fcc_votable,
Ashay Jaiswala9e10912018-02-02 14:03:35 +05302067 BATT_PROFILE_VOTER, chg->batt_profile_fcc_ua > 0,
2068 chg->batt_profile_fcc_ua);
Harry Yang4b7db0f2017-11-27 10:50:44 -08002069 vote(chg->fv_votable,
Ashay Jaiswala9e10912018-02-02 14:03:35 +05302070 BATT_PROFILE_VOTER, chg->batt_profile_fv_uv > 0,
2071 chg->batt_profile_fv_uv);
Ashay Jaiswala9e10912018-02-02 14:03:35 +05302072
2073 /* Some h/w limit maximum supported ICL */
2074 vote(chg->usb_icl_votable, HW_LIMIT_VOTER,
2075 chg->hw_max_icl_ua > 0, chg->hw_max_icl_ua);
Harry Yang4b7db0f2017-11-27 10:50:44 -08002076
2077 /*
2078 * AICL configuration:
Ashay Jaiswalc96380de2018-05-16 12:02:36 +05302079 * AICL ADC disable
Harry Yang4b7db0f2017-11-27 10:50:44 -08002080 */
Ashay Jaiswalc96380de2018-05-16 12:02:36 +05302081 if (chg->smb_version != PMI632_SUBTYPE) {
2082 rc = smblib_masked_write(chg, USBIN_AICL_OPTIONS_CFG_REG,
Harry Yang4b7db0f2017-11-27 10:50:44 -08002083 USBIN_AICL_ADC_EN_BIT, 0);
Ashay Jaiswalc96380de2018-05-16 12:02:36 +05302084 if (rc < 0) {
2085 dev_err(chg->dev, "Couldn't config AICL rc=%d\n", rc);
2086 return rc;
2087 }
Harry Yang4b7db0f2017-11-27 10:50:44 -08002088 }
2089
jessicatseng18afffd2020-05-08 17:36:49 +08002090//<2020/05/07-JessicaTseng, Enable AICL rerun periodically
2091 /* AICL PERIODIC RERUN ENABLE*/
2092 rc = smblib_write(chg, USBIN_AICL_OPTIONS_CFG_REG, 0xD4);
2093 if (rc < 0) {
2094 dev_err(chg->dev, "Couldn't config RERUN AICL ENABLE rc=%d\n", rc);
2095 return rc;
2096 }
2097//>2020/05/07-JessicaTseng
2098
Harry Yang4b7db0f2017-11-27 10:50:44 -08002099 /* enable the charging path */
2100 rc = vote(chg->chg_disable_votable, DEFAULT_VOTER, false, 0);
2101 if (rc < 0) {
2102 dev_err(chg->dev, "Couldn't enable charging rc=%d\n", rc);
2103 return rc;
2104 }
2105
Harry Yang4b7db0f2017-11-27 10:50:44 -08002106 /* configure VBUS for software control */
2107 rc = smblib_masked_write(chg, DCDC_OTG_CFG_REG, OTG_EN_SRC_CFG_BIT, 0);
2108 if (rc < 0) {
2109 dev_err(chg->dev,
2110 "Couldn't configure VBUS for SW control rc=%d\n", rc);
2111 return rc;
2112 }
2113
Ashay Jaiswala55b7ed2018-03-23 17:23:48 +05302114 /*
2115 * configure the one time watchdong periodic interval and
2116 * disable "watchdog bite disable charging".
2117 */
Harry Yang4b7db0f2017-11-27 10:50:44 -08002118 val = (ilog2(chip->dt.wd_bark_time / 16) << BARK_WDOG_TIMEOUT_SHIFT)
2119 & BARK_WDOG_TIMEOUT_MASK;
2120 val |= BITE_WDOG_TIMEOUT_8S;
2121 rc = smblib_masked_write(chg, SNARL_BARK_BITE_WD_CFG_REG,
2122 BITE_WDOG_DISABLE_CHARGING_CFG_BIT |
2123 BARK_WDOG_TIMEOUT_MASK | BITE_WDOG_TIMEOUT_MASK,
2124 val);
2125 if (rc < 0) {
2126 pr_err("Couldn't configue WD config rc=%d\n", rc);
2127 return rc;
2128 }
2129
Guru Das Srinagesh3ca14372018-06-01 11:30:56 -07002130 /* set termination current threshold values */
2131 rc = smb5_configure_iterm_thresholds(chip);
2132 if (rc < 0) {
2133 pr_err("Couldn't configure ITERM thresholds rc=%d\n",
2134 rc);
2135 return rc;
2136 }
2137
Harry Yang4b7db0f2017-11-27 10:50:44 -08002138 /* configure float charger options */
2139 switch (chip->dt.float_option) {
2140 case FLOAT_DCP:
2141 rc = smblib_masked_write(chg, USBIN_OPTIONS_2_CFG_REG,
2142 FLOAT_OPTIONS_MASK, 0);
2143 break;
2144 case FLOAT_SDP:
2145 rc = smblib_masked_write(chg, USBIN_OPTIONS_2_CFG_REG,
2146 FLOAT_OPTIONS_MASK, FORCE_FLOAT_SDP_CFG_BIT);
2147 break;
2148 case DISABLE_CHARGING:
2149 rc = smblib_masked_write(chg, USBIN_OPTIONS_2_CFG_REG,
2150 FLOAT_OPTIONS_MASK, FLOAT_DIS_CHGING_CFG_BIT);
2151 break;
2152 case SUSPEND_INPUT:
2153 rc = smblib_masked_write(chg, USBIN_OPTIONS_2_CFG_REG,
2154 FLOAT_OPTIONS_MASK, SUSPEND_FLOAT_CFG_BIT);
2155 break;
2156 default:
2157 rc = 0;
2158 break;
2159 }
2160
2161 if (rc < 0) {
2162 dev_err(chg->dev, "Couldn't configure float charger options rc=%d\n",
2163 rc);
2164 return rc;
2165 }
2166
2167 rc = smblib_read(chg, USBIN_OPTIONS_2_CFG_REG, &chg->float_cfg);
2168 if (rc < 0) {
2169 dev_err(chg->dev, "Couldn't read float charger options rc=%d\n",
2170 rc);
2171 return rc;
2172 }
2173
2174 switch (chip->dt.chg_inhibit_thr_mv) {
2175 case 50:
2176 rc = smblib_masked_write(chg, CHARGE_INHIBIT_THRESHOLD_CFG_REG,
2177 CHARGE_INHIBIT_THRESHOLD_MASK,
2178 INHIBIT_ANALOG_VFLT_MINUS_50MV);
2179 break;
2180 case 100:
2181 rc = smblib_masked_write(chg, CHARGE_INHIBIT_THRESHOLD_CFG_REG,
2182 CHARGE_INHIBIT_THRESHOLD_MASK,
2183 INHIBIT_ANALOG_VFLT_MINUS_100MV);
2184 break;
2185 case 200:
2186 rc = smblib_masked_write(chg, CHARGE_INHIBIT_THRESHOLD_CFG_REG,
2187 CHARGE_INHIBIT_THRESHOLD_MASK,
2188 INHIBIT_ANALOG_VFLT_MINUS_200MV);
2189 break;
2190 case 300:
2191 rc = smblib_masked_write(chg, CHARGE_INHIBIT_THRESHOLD_CFG_REG,
2192 CHARGE_INHIBIT_THRESHOLD_MASK,
2193 INHIBIT_ANALOG_VFLT_MINUS_300MV);
2194 break;
2195 case 0:
2196 rc = smblib_masked_write(chg, CHGR_CFG2_REG,
2197 CHARGER_INHIBIT_BIT, 0);
2198 default:
2199 break;
2200 }
2201
2202 if (rc < 0) {
2203 dev_err(chg->dev, "Couldn't configure charge inhibit threshold rc=%d\n",
2204 rc);
2205 return rc;
2206 }
2207
Anirudh Ghayal1380d312018-02-23 00:01:43 +05302208 rc = smblib_masked_write(chg, CHGR_CFG2_REG, RECHG_MASK,
2209 (chip->dt.auto_recharge_vbat_mv != -EINVAL) ?
2210 VBAT_BASED_RECHG_BIT : 0);
Harry Yang4b7db0f2017-11-27 10:50:44 -08002211 if (rc < 0) {
Anirudh Ghayal1380d312018-02-23 00:01:43 +05302212 dev_err(chg->dev, "Couldn't configure VBAT-rechg CHG_CFG2_REG rc=%d\n",
Harry Yang4b7db0f2017-11-27 10:50:44 -08002213 rc);
2214 return rc;
2215 }
2216
Anirudh Ghayal1380d312018-02-23 00:01:43 +05302217 /* program the auto-recharge VBAT threshold */
2218 if (chip->dt.auto_recharge_vbat_mv != -EINVAL) {
2219 u32 temp = VBAT_TO_VRAW_ADC(chip->dt.auto_recharge_vbat_mv);
2220
2221 temp = ((temp & 0xFF00) >> 8) | ((temp & 0xFF) << 8);
2222 rc = smblib_batch_write(chg,
2223 CHGR_ADC_RECHARGE_THRESHOLD_MSB_REG, (u8 *)&temp, 2);
2224 if (rc < 0) {
2225 dev_err(chg->dev, "Couldn't configure ADC_RECHARGE_THRESHOLD REG rc=%d\n",
2226 rc);
2227 return rc;
2228 }
2229 /* Program the sample count for VBAT based recharge to 3 */
2230 rc = smblib_masked_write(chg, CHGR_NO_SAMPLE_TERM_RCHG_CFG_REG,
2231 NO_OF_SAMPLE_FOR_RCHG,
2232 2 << NO_OF_SAMPLE_FOR_RCHG_SHIFT);
2233 if (rc < 0) {
2234 dev_err(chg->dev, "Couldn't configure CHGR_NO_SAMPLE_FOR_TERM_RCHG_CFG rc=%d\n",
2235 rc);
2236 return rc;
2237 }
2238 }
2239
2240 rc = smblib_masked_write(chg, CHGR_CFG2_REG, RECHG_MASK,
2241 (chip->dt.auto_recharge_soc != -EINVAL) ?
2242 SOC_BASED_RECHG_BIT : VBAT_BASED_RECHG_BIT);
2243 if (rc < 0) {
2244 dev_err(chg->dev, "Couldn't configure SOC-rechg CHG_CFG2_REG rc=%d\n",
2245 rc);
2246 return rc;
2247 }
2248
2249 /* program the auto-recharge threshold */
2250 if (chip->dt.auto_recharge_soc != -EINVAL) {
2251 rc = smblib_write(chg, CHARGE_RCHG_SOC_THRESHOLD_CFG_REG,
2252 (chip->dt.auto_recharge_soc * 255) / 100);
2253 if (rc < 0) {
2254 dev_err(chg->dev, "Couldn't configure CHG_RCHG_SOC_REG rc=%d\n",
2255 rc);
2256 return rc;
2257 }
2258 /* Program the sample count for SOC based recharge to 1 */
2259 rc = smblib_masked_write(chg, CHGR_NO_SAMPLE_TERM_RCHG_CFG_REG,
2260 NO_OF_SAMPLE_FOR_RCHG, 0);
2261 if (rc < 0) {
2262 dev_err(chg->dev, "Couldn't configure CHGR_NO_SAMPLE_FOR_TERM_RCHG_CFG rc=%d\n",
2263 rc);
2264 return rc;
2265 }
2266 }
2267
Harry Yang4b7db0f2017-11-27 10:50:44 -08002268 if (chg->sw_jeita_enabled) {
2269 rc = smblib_disable_hw_jeita(chg, true);
2270 if (rc < 0) {
2271 dev_err(chg->dev, "Couldn't set hw jeita rc=%d\n", rc);
2272 return rc;
2273 }
2274 }
2275
Ashay Jaiswala55b7ed2018-03-23 17:23:48 +05302276 rc = smblib_configure_wdog(chg,
2277 chg->step_chg_enabled || chg->sw_jeita_enabled);
2278 if (rc < 0) {
2279 dev_err(chg->dev, "Couldn't configure watchdog rc=%d\n",
2280 rc);
2281 return rc;
2282 }
2283
Ashay Jaiswal0de6fb92018-06-12 17:23:45 +05302284 if (chg->connector_pull_up != -EINVAL) {
2285 rc = smb5_configure_internal_pull(chg, CONN_THERM,
2286 get_valid_pullup(chg->connector_pull_up));
2287 if (rc < 0) {
2288 dev_err(chg->dev,
2289 "Couldn't configure CONN_THERM pull-up rc=%d\n",
2290 rc);
2291 return rc;
2292 }
2293 }
2294
Harry Yang4b7db0f2017-11-27 10:50:44 -08002295 return rc;
2296}
2297
2298static int smb5_post_init(struct smb5 *chip)
2299{
2300 struct smb_charger *chg = &chip->chg;
2301 union power_supply_propval pval;
2302 int rc;
2303
2304 /*
2305 * In case the usb path is suspended, we would have missed disabling
2306 * the icl change interrupt because the interrupt could have been
2307 * not requested
2308 */
2309 rerun_election(chg->usb_icl_votable);
2310
2311 /* configure power role for dual-role */
2312 pval.intval = POWER_SUPPLY_TYPEC_PR_DUAL;
2313 rc = smblib_set_prop_typec_power_role(chg, &pval);
2314 if (rc < 0) {
Ashay Jaiswala9e10912018-02-02 14:03:35 +05302315 dev_err(chg->dev, "Couldn't configure DRP role rc=%d\n",
2316 rc);
Harry Yang4b7db0f2017-11-27 10:50:44 -08002317 return rc;
2318 }
2319
2320 rerun_election(chg->usb_irq_enable_votable);
2321
2322 return 0;
2323}
2324
2325/****************************
2326 * DETERMINE INITIAL STATUS *
2327 ****************************/
2328
2329static int smb5_determine_initial_status(struct smb5 *chip)
2330{
2331 struct smb_irq_data irq_data = {chip, "determine-initial-status"};
2332 struct smb_charger *chg = &chip->chg;
Harry Yang6afaea22018-03-26 19:11:07 -07002333 union power_supply_propval val;
2334 int rc;
2335
2336 rc = smblib_get_prop_usb_present(chg, &val);
2337 if (rc < 0) {
2338 pr_err("Couldn't get usb present rc=%d\n", rc);
2339 return rc;
2340 }
2341 chg->early_usb_attach = val.intval;
Harry Yang4b7db0f2017-11-27 10:50:44 -08002342
2343 if (chg->bms_psy)
2344 smblib_suspend_on_debug_battery(chg);
Ashay Jaiswala9e10912018-02-02 14:03:35 +05302345
Harry Yang4b7db0f2017-11-27 10:50:44 -08002346 usb_plugin_irq_handler(0, &irq_data);
Harry Yang6afaea22018-03-26 19:11:07 -07002347 typec_attach_detach_irq_handler(0, &irq_data);
Harry Yang4b7db0f2017-11-27 10:50:44 -08002348 typec_state_change_irq_handler(0, &irq_data);
2349 usb_source_change_irq_handler(0, &irq_data);
2350 chg_state_change_irq_handler(0, &irq_data);
2351 icl_change_irq_handler(0, &irq_data);
2352 batt_temp_changed_irq_handler(0, &irq_data);
2353 wdog_bark_irq_handler(0, &irq_data);
Ashay Jaiswala9e10912018-02-02 14:03:35 +05302354 typec_or_rid_detection_change_irq_handler(0, &irq_data);
Harry Yang4b7db0f2017-11-27 10:50:44 -08002355
2356 return 0;
2357}
2358
2359/**************************
2360 * INTERRUPT REGISTRATION *
2361 **************************/
2362
2363static struct smb_irq_info smb5_irqs[] = {
2364 /* CHARGER IRQs */
2365 [CHGR_ERROR_IRQ] = {
2366 .name = "chgr-error",
2367 .handler = default_irq_handler,
2368 },
2369 [CHG_STATE_CHANGE_IRQ] = {
2370 .name = "chg-state-change",
2371 .handler = chg_state_change_irq_handler,
Ashay Jaiswal48015c32018-03-07 18:25:43 +05302372 .wake = true,
Harry Yang4b7db0f2017-11-27 10:50:44 -08002373 },
2374 [STEP_CHG_STATE_CHANGE_IRQ] = {
2375 .name = "step-chg-state-change",
Harry Yang4b7db0f2017-11-27 10:50:44 -08002376 },
2377 [STEP_CHG_SOC_UPDATE_FAIL_IRQ] = {
2378 .name = "step-chg-soc-update-fail",
Harry Yang4b7db0f2017-11-27 10:50:44 -08002379 },
2380 [STEP_CHG_SOC_UPDATE_REQ_IRQ] = {
2381 .name = "step-chg-soc-update-req",
Harry Yang4b7db0f2017-11-27 10:50:44 -08002382 },
2383 [FG_FVCAL_QUALIFIED_IRQ] = {
2384 .name = "fg-fvcal-qualified",
Harry Yang4b7db0f2017-11-27 10:50:44 -08002385 },
2386 [VPH_ALARM_IRQ] = {
2387 .name = "vph-alarm",
Harry Yang4b7db0f2017-11-27 10:50:44 -08002388 },
2389 [VPH_DROP_PRECHG_IRQ] = {
2390 .name = "vph-drop-prechg",
Harry Yang4b7db0f2017-11-27 10:50:44 -08002391 },
2392 /* DCDC IRQs */
2393 [OTG_FAIL_IRQ] = {
2394 .name = "otg-fail",
2395 .handler = default_irq_handler,
2396 },
2397 [OTG_OC_DISABLE_SW_IRQ] = {
2398 .name = "otg-oc-disable-sw",
Harry Yang4b7db0f2017-11-27 10:50:44 -08002399 },
2400 [OTG_OC_HICCUP_IRQ] = {
2401 .name = "otg-oc-hiccup",
Harry Yang4b7db0f2017-11-27 10:50:44 -08002402 },
2403 [BSM_ACTIVE_IRQ] = {
2404 .name = "bsm-active",
Harry Yang4b7db0f2017-11-27 10:50:44 -08002405 },
2406 [HIGH_DUTY_CYCLE_IRQ] = {
2407 .name = "high-duty-cycle",
2408 .handler = high_duty_cycle_irq_handler,
Ashay Jaiswal48015c32018-03-07 18:25:43 +05302409 .wake = true,
Harry Yang4b7db0f2017-11-27 10:50:44 -08002410 },
2411 [INPUT_CURRENT_LIMITING_IRQ] = {
2412 .name = "input-current-limiting",
2413 .handler = default_irq_handler,
2414 },
2415 [CONCURRENT_MODE_DISABLE_IRQ] = {
2416 .name = "concurrent-mode-disable",
Harry Yang4b7db0f2017-11-27 10:50:44 -08002417 },
2418 [SWITCHER_POWER_OK_IRQ] = {
2419 .name = "switcher-power-ok",
2420 .handler = switcher_power_ok_irq_handler,
2421 },
2422 /* BATTERY IRQs */
2423 [BAT_TEMP_IRQ] = {
2424 .name = "bat-temp",
2425 .handler = batt_temp_changed_irq_handler,
Ashay Jaiswal48015c32018-03-07 18:25:43 +05302426 .wake = true,
Harry Yang4b7db0f2017-11-27 10:50:44 -08002427 },
2428 [ALL_CHNL_CONV_DONE_IRQ] = {
2429 .name = "all-chnl-conv-done",
Harry Yang4b7db0f2017-11-27 10:50:44 -08002430 },
2431 [BAT_OV_IRQ] = {
2432 .name = "bat-ov",
2433 .handler = batt_psy_changed_irq_handler,
2434 },
2435 [BAT_LOW_IRQ] = {
2436 .name = "bat-low",
2437 .handler = batt_psy_changed_irq_handler,
2438 },
2439 [BAT_THERM_OR_ID_MISSING_IRQ] = {
2440 .name = "bat-therm-or-id-missing",
2441 .handler = batt_psy_changed_irq_handler,
2442 },
2443 [BAT_TERMINAL_MISSING_IRQ] = {
2444 .name = "bat-terminal-missing",
2445 .handler = batt_psy_changed_irq_handler,
2446 },
2447 [BUCK_OC_IRQ] = {
2448 .name = "buck-oc",
Harry Yang4b7db0f2017-11-27 10:50:44 -08002449 },
2450 [VPH_OV_IRQ] = {
2451 .name = "vph-ov",
Harry Yang4b7db0f2017-11-27 10:50:44 -08002452 },
2453 /* USB INPUT IRQs */
2454 [USBIN_COLLAPSE_IRQ] = {
2455 .name = "usbin-collapse",
2456 .handler = default_irq_handler,
2457 },
2458 [USBIN_VASHDN_IRQ] = {
2459 .name = "usbin-vashdn",
2460 .handler = default_irq_handler,
2461 },
2462 [USBIN_UV_IRQ] = {
2463 .name = "usbin-uv",
2464 .handler = usbin_uv_irq_handler,
Ashay Jaiswale0b3c472018-06-20 23:39:41 +05302465 .wake = true,
2466 .storm_data = {true, 3000, 5},
Harry Yang4b7db0f2017-11-27 10:50:44 -08002467 },
2468 [USBIN_OV_IRQ] = {
2469 .name = "usbin-ov",
Ashay Jaiswal43107092018-08-20 18:59:28 +05302470 .handler = usbin_ov_irq_handler,
Harry Yang4b7db0f2017-11-27 10:50:44 -08002471 },
2472 [USBIN_PLUGIN_IRQ] = {
2473 .name = "usbin-plugin",
2474 .handler = usb_plugin_irq_handler,
Ashay Jaiswal48015c32018-03-07 18:25:43 +05302475 .wake = true,
Harry Yang4b7db0f2017-11-27 10:50:44 -08002476 },
2477 [USBIN_REVI_CHANGE_IRQ] = {
2478 .name = "usbin-revi-change",
Harry Yang4b7db0f2017-11-27 10:50:44 -08002479 },
2480 [USBIN_SRC_CHANGE_IRQ] = {
2481 .name = "usbin-src-change",
2482 .handler = usb_source_change_irq_handler,
Ashay Jaiswal48015c32018-03-07 18:25:43 +05302483 .wake = true,
Harry Yang4b7db0f2017-11-27 10:50:44 -08002484 },
2485 [USBIN_ICL_CHANGE_IRQ] = {
2486 .name = "usbin-icl-change",
2487 .handler = icl_change_irq_handler,
Ashay Jaiswal48015c32018-03-07 18:25:43 +05302488 .wake = true,
Harry Yang4b7db0f2017-11-27 10:50:44 -08002489 },
2490 /* DC INPUT IRQs */
2491 [DCIN_VASHDN_IRQ] = {
2492 .name = "dcin-vashdn",
Harry Yang4b7db0f2017-11-27 10:50:44 -08002493 },
2494 [DCIN_UV_IRQ] = {
2495 .name = "dcin-uv",
2496 .handler = default_irq_handler,
2497 },
2498 [DCIN_OV_IRQ] = {
2499 .name = "dcin-ov",
2500 .handler = default_irq_handler,
2501 },
2502 [DCIN_PLUGIN_IRQ] = {
2503 .name = "dcin-plugin",
2504 .handler = dc_plugin_irq_handler,
2505 .wake = true,
2506 },
2507 [DCIN_REVI_IRQ] = {
2508 .name = "dcin-revi",
Harry Yang4b7db0f2017-11-27 10:50:44 -08002509 },
2510 [DCIN_PON_IRQ] = {
2511 .name = "dcin-pon",
2512 .handler = default_irq_handler,
2513 },
2514 [DCIN_EN_IRQ] = {
2515 .name = "dcin-en",
2516 .handler = default_irq_handler,
2517 },
2518 /* TYPEC IRQs */
2519 [TYPEC_OR_RID_DETECTION_CHANGE_IRQ] = {
2520 .name = "typec-or-rid-detect-change",
Ashay Jaiswala9e10912018-02-02 14:03:35 +05302521 .handler = typec_or_rid_detection_change_irq_handler,
Ashay Jaiswal48015c32018-03-07 18:25:43 +05302522 .wake = true,
Harry Yang4b7db0f2017-11-27 10:50:44 -08002523 },
2524 [TYPEC_VPD_DETECT_IRQ] = {
2525 .name = "typec-vpd-detect",
Harry Yang4b7db0f2017-11-27 10:50:44 -08002526 },
2527 [TYPEC_CC_STATE_CHANGE_IRQ] = {
2528 .name = "typec-cc-state-change",
2529 .handler = typec_state_change_irq_handler,
Ashay Jaiswal48015c32018-03-07 18:25:43 +05302530 .wake = true,
Harry Yang4b7db0f2017-11-27 10:50:44 -08002531 },
2532 [TYPEC_VCONN_OC_IRQ] = {
2533 .name = "typec-vconn-oc",
2534 .handler = default_irq_handler,
2535 },
2536 [TYPEC_VBUS_CHANGE_IRQ] = {
2537 .name = "typec-vbus-change",
Harry Yang4b7db0f2017-11-27 10:50:44 -08002538 },
2539 [TYPEC_ATTACH_DETACH_IRQ] = {
2540 .name = "typec-attach-detach",
Harry Yang6afaea22018-03-26 19:11:07 -07002541 .handler = typec_attach_detach_irq_handler,
Guru Das Srinageshdcd65ed2018-08-14 15:39:35 +05302542 .wake = true,
Harry Yang4b7db0f2017-11-27 10:50:44 -08002543 },
2544 [TYPEC_LEGACY_CABLE_DETECT_IRQ] = {
2545 .name = "typec-legacy-cable-detect",
2546 .handler = default_irq_handler,
2547 },
2548 [TYPEC_TRY_SNK_SRC_DETECT_IRQ] = {
2549 .name = "typec-try-snk-src-detect",
Harry Yang4b7db0f2017-11-27 10:50:44 -08002550 },
2551 /* MISCELLANEOUS IRQs */
2552 [WDOG_SNARL_IRQ] = {
2553 .name = "wdog-snarl",
Harry Yang4b7db0f2017-11-27 10:50:44 -08002554 },
2555 [WDOG_BARK_IRQ] = {
2556 .name = "wdog-bark",
2557 .handler = wdog_bark_irq_handler,
Ashay Jaiswala55b7ed2018-03-23 17:23:48 +05302558 .wake = true,
Harry Yang4b7db0f2017-11-27 10:50:44 -08002559 },
2560 [AICL_FAIL_IRQ] = {
2561 .name = "aicl-fail",
Harry Yang4b7db0f2017-11-27 10:50:44 -08002562 },
2563 [AICL_DONE_IRQ] = {
2564 .name = "aicl-done",
2565 .handler = default_irq_handler,
2566 },
2567 [SMB_EN_IRQ] = {
2568 .name = "smb-en",
Harry Yang4b7db0f2017-11-27 10:50:44 -08002569 },
2570 [IMP_TRIGGER_IRQ] = {
2571 .name = "imp-trigger",
Harry Yang4b7db0f2017-11-27 10:50:44 -08002572 },
2573 [TEMP_CHANGE_IRQ] = {
2574 .name = "temp-change",
Harry Yang4b7db0f2017-11-27 10:50:44 -08002575 },
2576 [TEMP_CHANGE_SMB_IRQ] = {
2577 .name = "temp-change-smb",
Harry Yang4b7db0f2017-11-27 10:50:44 -08002578 },
Ashay Jaiswal09feab82018-02-12 12:33:18 +05302579 /* FLASH */
2580 [VREG_OK_IRQ] = {
2581 .name = "vreg-ok",
Ashay Jaiswal09feab82018-02-12 12:33:18 +05302582 },
2583 [ILIM_S2_IRQ] = {
2584 .name = "ilim2-s2",
2585 .handler = schgm_flash_ilim2_irq_handler,
2586 },
2587 [ILIM_S1_IRQ] = {
2588 .name = "ilim1-s1",
Ashay Jaiswal09feab82018-02-12 12:33:18 +05302589 },
2590 [VOUT_DOWN_IRQ] = {
2591 .name = "vout-down",
Ashay Jaiswal09feab82018-02-12 12:33:18 +05302592 },
2593 [VOUT_UP_IRQ] = {
2594 .name = "vout-up",
Ashay Jaiswal09feab82018-02-12 12:33:18 +05302595 },
2596 [FLASH_STATE_CHANGE_IRQ] = {
2597 .name = "flash-state-change",
2598 .handler = schgm_flash_state_change_irq_handler,
2599 },
2600 [TORCH_REQ_IRQ] = {
2601 .name = "torch-req",
Ashay Jaiswal09feab82018-02-12 12:33:18 +05302602 },
2603 [FLASH_EN_IRQ] = {
2604 .name = "flash-en",
Ashay Jaiswal09feab82018-02-12 12:33:18 +05302605 },
Harry Yang4b7db0f2017-11-27 10:50:44 -08002606};
2607
2608static int smb5_get_irq_index_byname(const char *irq_name)
2609{
2610 int i;
2611
2612 for (i = 0; i < ARRAY_SIZE(smb5_irqs); i++) {
2613 if (strcmp(smb5_irqs[i].name, irq_name) == 0)
2614 return i;
2615 }
2616
2617 return -ENOENT;
2618}
2619
2620static int smb5_request_interrupt(struct smb5 *chip,
2621 struct device_node *node, const char *irq_name)
2622{
2623 struct smb_charger *chg = &chip->chg;
2624 int rc, irq, irq_index;
2625 struct smb_irq_data *irq_data;
2626
2627 irq = of_irq_get_byname(node, irq_name);
2628 if (irq < 0) {
2629 pr_err("Couldn't get irq %s byname\n", irq_name);
2630 return irq;
2631 }
2632
2633 irq_index = smb5_get_irq_index_byname(irq_name);
2634 if (irq_index < 0) {
2635 pr_err("%s is not a defined irq\n", irq_name);
2636 return irq_index;
2637 }
2638
2639 if (!smb5_irqs[irq_index].handler)
2640 return 0;
2641
2642 irq_data = devm_kzalloc(chg->dev, sizeof(*irq_data), GFP_KERNEL);
2643 if (!irq_data)
2644 return -ENOMEM;
2645
2646 irq_data->parent_data = chip;
2647 irq_data->name = irq_name;
2648 irq_data->storm_data = smb5_irqs[irq_index].storm_data;
2649 mutex_init(&irq_data->storm_data.storm_lock);
2650
2651 rc = devm_request_threaded_irq(chg->dev, irq, NULL,
2652 smb5_irqs[irq_index].handler,
2653 IRQF_ONESHOT, irq_name, irq_data);
2654 if (rc < 0) {
2655 pr_err("Couldn't request irq %d\n", irq);
2656 return rc;
2657 }
2658
2659 smb5_irqs[irq_index].irq = irq;
2660 smb5_irqs[irq_index].irq_data = irq_data;
2661 if (smb5_irqs[irq_index].wake)
2662 enable_irq_wake(irq);
2663
2664 return rc;
2665}
2666
2667static int smb5_request_interrupts(struct smb5 *chip)
2668{
2669 struct smb_charger *chg = &chip->chg;
2670 struct device_node *node = chg->dev->of_node;
2671 struct device_node *child;
2672 int rc = 0;
2673 const char *name;
2674 struct property *prop;
2675
2676 for_each_available_child_of_node(node, child) {
2677 of_property_for_each_string(child, "interrupt-names",
2678 prop, name) {
2679 rc = smb5_request_interrupt(chip, child, name);
2680 if (rc < 0)
2681 return rc;
2682 }
2683 }
2684 if (chg->irq_info[USBIN_ICL_CHANGE_IRQ].irq)
2685 chg->usb_icl_change_irq_enabled = true;
2686
2687 return rc;
2688}
2689
2690static void smb5_free_interrupts(struct smb_charger *chg)
2691{
2692 int i;
2693
2694 for (i = 0; i < ARRAY_SIZE(smb5_irqs); i++) {
2695 if (smb5_irqs[i].irq > 0) {
2696 if (smb5_irqs[i].wake)
2697 disable_irq_wake(smb5_irqs[i].irq);
2698
2699 devm_free_irq(chg->dev, smb5_irqs[i].irq,
2700 smb5_irqs[i].irq_data);
2701 }
2702 }
2703}
2704
2705static void smb5_disable_interrupts(struct smb_charger *chg)
2706{
2707 int i;
2708
2709 for (i = 0; i < ARRAY_SIZE(smb5_irqs); i++) {
2710 if (smb5_irqs[i].irq > 0)
2711 disable_irq(smb5_irqs[i].irq);
2712 }
2713}
2714
2715#if defined(CONFIG_DEBUG_FS)
2716
2717static int force_batt_psy_update_write(void *data, u64 val)
2718{
2719 struct smb_charger *chg = data;
2720
2721 power_supply_changed(chg->batt_psy);
2722 return 0;
2723}
2724DEFINE_SIMPLE_ATTRIBUTE(force_batt_psy_update_ops, NULL,
2725 force_batt_psy_update_write, "0x%02llx\n");
2726
2727static int force_usb_psy_update_write(void *data, u64 val)
2728{
2729 struct smb_charger *chg = data;
2730
2731 power_supply_changed(chg->usb_psy);
2732 return 0;
2733}
2734DEFINE_SIMPLE_ATTRIBUTE(force_usb_psy_update_ops, NULL,
2735 force_usb_psy_update_write, "0x%02llx\n");
2736
2737static int force_dc_psy_update_write(void *data, u64 val)
2738{
2739 struct smb_charger *chg = data;
2740
2741 power_supply_changed(chg->dc_psy);
2742 return 0;
2743}
2744DEFINE_SIMPLE_ATTRIBUTE(force_dc_psy_update_ops, NULL,
2745 force_dc_psy_update_write, "0x%02llx\n");
2746
2747static void smb5_create_debugfs(struct smb5 *chip)
2748{
2749 struct dentry *file;
2750
2751 chip->dfs_root = debugfs_create_dir("charger", NULL);
2752 if (IS_ERR_OR_NULL(chip->dfs_root)) {
2753 pr_err("Couldn't create charger debugfs rc=%ld\n",
2754 (long)chip->dfs_root);
2755 return;
2756 }
2757
2758 file = debugfs_create_file("force_batt_psy_update", 0600,
2759 chip->dfs_root, chip, &force_batt_psy_update_ops);
2760 if (IS_ERR_OR_NULL(file))
2761 pr_err("Couldn't create force_batt_psy_update file rc=%ld\n",
2762 (long)file);
2763
2764 file = debugfs_create_file("force_usb_psy_update", 0600,
2765 chip->dfs_root, chip, &force_usb_psy_update_ops);
2766 if (IS_ERR_OR_NULL(file))
2767 pr_err("Couldn't create force_usb_psy_update file rc=%ld\n",
2768 (long)file);
2769
2770 file = debugfs_create_file("force_dc_psy_update", 0600,
2771 chip->dfs_root, chip, &force_dc_psy_update_ops);
2772 if (IS_ERR_OR_NULL(file))
2773 pr_err("Couldn't create force_dc_psy_update file rc=%ld\n",
2774 (long)file);
2775}
2776
2777#else
2778
2779static void smb5_create_debugfs(struct smb5 *chip)
2780{}
2781
2782#endif
2783
2784static int smb5_show_charger_status(struct smb5 *chip)
2785{
2786 struct smb_charger *chg = &chip->chg;
2787 union power_supply_propval val;
2788 int usb_present, batt_present, batt_health, batt_charge_type;
2789 int rc;
2790
2791 rc = smblib_get_prop_usb_present(chg, &val);
2792 if (rc < 0) {
2793 pr_err("Couldn't get usb present rc=%d\n", rc);
2794 return rc;
2795 }
2796 usb_present = val.intval;
2797
2798 rc = smblib_get_prop_batt_present(chg, &val);
2799 if (rc < 0) {
2800 pr_err("Couldn't get batt present rc=%d\n", rc);
2801 return rc;
2802 }
2803 batt_present = val.intval;
2804
2805 rc = smblib_get_prop_batt_health(chg, &val);
2806 if (rc < 0) {
2807 pr_err("Couldn't get batt health rc=%d\n", rc);
2808 val.intval = POWER_SUPPLY_HEALTH_UNKNOWN;
2809 }
2810 batt_health = val.intval;
2811
2812 rc = smblib_get_prop_batt_charge_type(chg, &val);
2813 if (rc < 0) {
2814 pr_err("Couldn't get batt charge type rc=%d\n", rc);
2815 return rc;
2816 }
2817 batt_charge_type = val.intval;
2818
2819 pr_info("SMB5 status - usb:present=%d type=%d batt:present = %d health = %d charge = %d\n",
2820 usb_present, chg->real_charger_type,
2821 batt_present, batt_health, batt_charge_type);
2822 return rc;
2823}
2824
2825static int smb5_probe(struct platform_device *pdev)
2826{
2827 struct smb5 *chip;
2828 struct smb_charger *chg;
2829 int rc = 0;
2830
2831 chip = devm_kzalloc(&pdev->dev, sizeof(*chip), GFP_KERNEL);
2832 if (!chip)
2833 return -ENOMEM;
2834
2835 chg = &chip->chg;
2836 chg->dev = &pdev->dev;
Harry Yang4b7db0f2017-11-27 10:50:44 -08002837 chg->debug_mask = &__debug_mask;
Harry Yang6afaea22018-03-26 19:11:07 -07002838 chg->pd_disabled = &__pd_disabled;
Harry Yang4b7db0f2017-11-27 10:50:44 -08002839 chg->weak_chg_icl_ua = &__weak_chg_icl_ua;
2840 chg->mode = PARALLEL_MASTER;
2841 chg->irq_info = smb5_irqs;
2842 chg->die_health = -EINVAL;
Ashay Jaiswala9e10912018-02-02 14:03:35 +05302843 chg->otg_present = false;
Anirudh Ghayal75f8f812018-07-09 16:48:47 +05302844 mutex_init(&chg->vadc_lock);
Harry Yang4b7db0f2017-11-27 10:50:44 -08002845
2846 chg->regmap = dev_get_regmap(chg->dev->parent, NULL);
2847 if (!chg->regmap) {
2848 pr_err("parent regmap is missing\n");
2849 return -EINVAL;
2850 }
2851
Ashay Jaiswala9e10912018-02-02 14:03:35 +05302852 rc = smb5_chg_config_init(chip);
2853 if (rc < 0) {
2854 if (rc != -EPROBE_DEFER)
2855 pr_err("Couldn't setup chg_config rc=%d\n", rc);
2856 return rc;
Harry Yang4b7db0f2017-11-27 10:50:44 -08002857 }
2858
Ashay Jaiswalb2b06fe2018-06-07 18:35:21 +05302859 rc = smb5_parse_dt(chip);
2860 if (rc < 0) {
2861 pr_err("Couldn't parse device tree rc=%d\n", rc);
2862 return rc;
2863 }
2864
Harry Yang4b7db0f2017-11-27 10:50:44 -08002865 rc = smblib_init(chg);
2866 if (rc < 0) {
2867 pr_err("Smblib_init failed rc=%d\n", rc);
Ashay Jaiswala9e10912018-02-02 14:03:35 +05302868 return rc;
Harry Yang4b7db0f2017-11-27 10:50:44 -08002869 }
2870
2871 /* set driver data before resources request it */
2872 platform_set_drvdata(pdev, chip);
2873
2874 rc = smb5_init_vbus_regulator(chip);
2875 if (rc < 0) {
2876 pr_err("Couldn't initialize vbus regulator rc=%d\n",
2877 rc);
2878 goto cleanup;
2879 }
2880
2881 rc = smb5_init_vconn_regulator(chip);
2882 if (rc < 0) {
2883 pr_err("Couldn't initialize vconn regulator rc=%d\n",
2884 rc);
2885 goto cleanup;
2886 }
2887
2888 /* extcon registration */
2889 chg->extcon = devm_extcon_dev_allocate(chg->dev, smblib_extcon_cable);
2890 if (IS_ERR(chg->extcon)) {
2891 rc = PTR_ERR(chg->extcon);
2892 dev_err(chg->dev, "failed to allocate extcon device rc=%d\n",
2893 rc);
2894 goto cleanup;
2895 }
2896
2897 rc = devm_extcon_dev_register(chg->dev, chg->extcon);
2898 if (rc < 0) {
2899 dev_err(chg->dev, "failed to register extcon device rc=%d\n",
2900 rc);
2901 goto cleanup;
2902 }
2903
2904 rc = smb5_init_hw(chip);
2905 if (rc < 0) {
2906 pr_err("Couldn't initialize hardware rc=%d\n", rc);
2907 goto cleanup;
2908 }
2909
Ashay Jaiswala9e10912018-02-02 14:03:35 +05302910 if (chg->smb_version == PM855B_SUBTYPE) {
2911 rc = smb5_init_dc_psy(chip);
2912 if (rc < 0) {
2913 pr_err("Couldn't initialize dc psy rc=%d\n", rc);
2914 goto cleanup;
2915 }
Harry Yang4b7db0f2017-11-27 10:50:44 -08002916 }
2917
2918 rc = smb5_init_usb_psy(chip);
2919 if (rc < 0) {
2920 pr_err("Couldn't initialize usb psy rc=%d\n", rc);
2921 goto cleanup;
2922 }
2923
2924 rc = smb5_init_usb_main_psy(chip);
2925 if (rc < 0) {
2926 pr_err("Couldn't initialize usb main psy rc=%d\n", rc);
2927 goto cleanup;
2928 }
2929
2930 rc = smb5_init_usb_port_psy(chip);
2931 if (rc < 0) {
2932 pr_err("Couldn't initialize usb pc_port psy rc=%d\n", rc);
2933 goto cleanup;
2934 }
2935
2936 rc = smb5_init_batt_psy(chip);
2937 if (rc < 0) {
2938 pr_err("Couldn't initialize batt psy rc=%d\n", rc);
2939 goto cleanup;
2940 }
2941
2942 rc = smb5_determine_initial_status(chip);
2943 if (rc < 0) {
2944 pr_err("Couldn't determine initial status rc=%d\n",
2945 rc);
2946 goto cleanup;
2947 }
2948
2949 rc = smb5_request_interrupts(chip);
2950 if (rc < 0) {
2951 pr_err("Couldn't request interrupts rc=%d\n", rc);
2952 goto cleanup;
2953 }
2954
2955 rc = smb5_post_init(chip);
2956 if (rc < 0) {
2957 pr_err("Failed in post init rc=%d\n", rc);
Ashay Jaiswala9e10912018-02-02 14:03:35 +05302958 goto free_irq;
Harry Yang4b7db0f2017-11-27 10:50:44 -08002959 }
2960
2961 smb5_create_debugfs(chip);
2962
2963 rc = smb5_show_charger_status(chip);
2964 if (rc < 0) {
2965 pr_err("Failed in getting charger status rc=%d\n", rc);
Ashay Jaiswala9e10912018-02-02 14:03:35 +05302966 goto free_irq;
Harry Yang4b7db0f2017-11-27 10:50:44 -08002967 }
2968
2969 device_init_wakeup(chg->dev, true);
2970
2971 pr_info("QPNP SMB5 probed successfully\n");
2972
2973 return rc;
2974
Ashay Jaiswala9e10912018-02-02 14:03:35 +05302975free_irq:
Harry Yang4b7db0f2017-11-27 10:50:44 -08002976 smb5_free_interrupts(chg);
Ashay Jaiswala9e10912018-02-02 14:03:35 +05302977cleanup:
Harry Yang4b7db0f2017-11-27 10:50:44 -08002978 smblib_deinit(chg);
2979 platform_set_drvdata(pdev, NULL);
2980
2981 return rc;
2982}
2983
2984static int smb5_remove(struct platform_device *pdev)
2985{
2986 struct smb5 *chip = platform_get_drvdata(pdev);
2987 struct smb_charger *chg = &chip->chg;
2988
Harry Yang6afaea22018-03-26 19:11:07 -07002989 /* force enable APSD */
2990 smblib_masked_write(chg, USBIN_OPTIONS_1_CFG_REG,
2991 BC1P2_SRC_DETECT_BIT, BC1P2_SRC_DETECT_BIT);
2992
Harry Yang4b7db0f2017-11-27 10:50:44 -08002993 smb5_free_interrupts(chg);
2994 smblib_deinit(chg);
2995 platform_set_drvdata(pdev, NULL);
2996 return 0;
2997}
2998
2999static void smb5_shutdown(struct platform_device *pdev)
3000{
3001 struct smb5 *chip = platform_get_drvdata(pdev);
3002 struct smb_charger *chg = &chip->chg;
3003
3004 /* disable all interrupts */
3005 smb5_disable_interrupts(chg);
3006
3007 /* configure power role for UFP */
Ashay Jaiswala9e10912018-02-02 14:03:35 +05303008 if (chg->connector_type == POWER_SUPPLY_CONNECTOR_TYPEC)
Harry Yang4b7db0f2017-11-27 10:50:44 -08003009 smblib_masked_write(chg, TYPE_C_MODE_CFG_REG,
3010 TYPEC_POWER_ROLE_CMD_MASK, EN_SNK_ONLY_BIT);
3011
3012 /* force HVDCP to 5V */
3013 smblib_masked_write(chg, USBIN_OPTIONS_1_CFG_REG,
3014 HVDCP_AUTONOMOUS_MODE_EN_CFG_BIT, 0);
3015 smblib_write(chg, CMD_HVDCP_2_REG, FORCE_5V_BIT);
3016
3017 /* force enable APSD */
3018 smblib_masked_write(chg, USBIN_OPTIONS_1_CFG_REG,
3019 BC1P2_SRC_DETECT_BIT, BC1P2_SRC_DETECT_BIT);
3020}
3021
3022static const struct of_device_id match_table[] = {
3023 { .compatible = "qcom,qpnp-smb5", },
3024 { },
3025};
3026
3027static struct platform_driver smb5_driver = {
3028 .driver = {
3029 .name = "qcom,qpnp-smb5",
3030 .owner = THIS_MODULE,
3031 .of_match_table = match_table,
3032 },
3033 .probe = smb5_probe,
3034 .remove = smb5_remove,
3035 .shutdown = smb5_shutdown,
3036};
3037module_platform_driver(smb5_driver);
3038
3039MODULE_DESCRIPTION("QPNP SMB5 Charger Driver");
3040MODULE_LICENSE("GPL v2");