blob: 4239cb73d250229050a0c7bbb2aa2a7aacd4a58a [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;
213};
214
215struct smb5 {
216 struct smb_charger chg;
217 struct dentry *dfs_root;
218 struct smb_dt_props dt;
219};
220
221static int __debug_mask;
222module_param_named(
223 debug_mask, __debug_mask, int, 0600
224);
225
Harry Yang6afaea22018-03-26 19:11:07 -0700226static int __pd_disabled;
227module_param_named(
228 pd_disabled, __pd_disabled, int, 0600
229);
230
Harry Yang4b7db0f2017-11-27 10:50:44 -0800231static int __weak_chg_icl_ua = 500000;
232module_param_named(
233 weak_chg_icl_ua, __weak_chg_icl_ua, int, 0600
234);
235
Ashay Jaiswal20688262018-04-25 11:45:34 +0530236enum {
237 USBIN_CURRENT,
238 USBIN_VOLTAGE,
239};
240
Ashay Jaiswal0de6fb92018-06-12 17:23:45 +0530241enum {
242 BAT_THERM = 0,
243 MISC_THERM,
244 CONN_THERM,
245 SMB_THERM,
246};
247
Ashay Jaiswala9e10912018-02-02 14:03:35 +0530248#define PMI632_MAX_ICL_UA 3000000
249static int smb5_chg_config_init(struct smb5 *chip)
250{
251 struct smb_charger *chg = &chip->chg;
252 struct pmic_revid_data *pmic_rev_id;
253 struct device_node *revid_dev_node;
254 int rc = 0;
255
256 revid_dev_node = of_parse_phandle(chip->chg.dev->of_node,
257 "qcom,pmic-revid", 0);
258 if (!revid_dev_node) {
259 pr_err("Missing qcom,pmic-revid property\n");
260 return -EINVAL;
261 }
262
263 pmic_rev_id = get_revid_data(revid_dev_node);
264 if (IS_ERR_OR_NULL(pmic_rev_id)) {
265 /*
266 * the revid peripheral must be registered, any failure
267 * here only indicates that the rev-id module has not
268 * probed yet.
269 */
270 rc = -EPROBE_DEFER;
271 goto out;
272 }
273
274 switch (pmic_rev_id->pmic_subtype) {
275 case PM855B_SUBTYPE:
276 chip->chg.smb_version = PM855B_SUBTYPE;
Harry Yangf7b89902018-03-13 22:37:53 -0700277 chg->param = smb5_pm855b_params;
Ashay Jaiswala9e10912018-02-02 14:03:35 +0530278 chg->name = "pm855b_charger";
279 break;
280 case PMI632_SUBTYPE:
281 chip->chg.smb_version = PMI632_SUBTYPE;
Ashay Jaiswale0b3c472018-06-20 23:39:41 +0530282 chg->wa_flags |= WEAK_ADAPTER_WA;
Ashay Jaiswala9e10912018-02-02 14:03:35 +0530283 chg->param = smb5_pmi632_params;
284 chg->use_extcon = true;
285 chg->name = "pmi632_charger";
Ashay Jaiswalc96380de2018-05-16 12:02:36 +0530286 /* PMI632 does not support PD */
Ashay Jaiswalf2ca7092018-05-22 21:33:15 +0530287 chg->pd_not_supported = true;
Ashay Jaiswala9e10912018-02-02 14:03:35 +0530288 chg->hw_max_icl_ua =
289 (chip->dt.usb_icl_ua > 0) ? chip->dt.usb_icl_ua
290 : PMI632_MAX_ICL_UA;
291 chg->chg_freq.freq_5V = 600;
292 chg->chg_freq.freq_6V_8V = 800;
293 chg->chg_freq.freq_9V = 1050;
294 chg->chg_freq.freq_removal = 1050;
295 chg->chg_freq.freq_below_otg_threshold = 800;
296 chg->chg_freq.freq_above_otg_threshold = 800;
297 break;
298 default:
299 pr_err("PMIC subtype %d not supported\n",
300 pmic_rev_id->pmic_subtype);
301 rc = -EINVAL;
302 }
303
304out:
305 of_node_put(revid_dev_node);
306 return rc;
307}
308
Ashay Jaiswal0de6fb92018-06-12 17:23:45 +0530309#define PULL_NO_PULL 0
310#define PULL_30K 30
311#define PULL_100K 100
312#define PULL_400K 400
313static int get_valid_pullup(int pull_up)
314{
315 int pull;
316
317 /* pull up can only be 0/30K/100K/400K) */
318 switch (pull_up) {
319 case PULL_NO_PULL:
320 pull = INTERNAL_PULL_NO_PULL;
321 break;
322 case PULL_30K:
323 pull = INTERNAL_PULL_30K_PULL;
324 break;
325 case PULL_100K:
326 pull = INTERNAL_PULL_100K_PULL;
327 break;
328 case PULL_400K:
329 pull = INTERNAL_PULL_400K_PULL;
330 break;
331 default:
332 pull = INTERNAL_PULL_100K_PULL;
333 }
334
335 return pull;
336}
337
338#define INTERNAL_PULL_UP_MASK 0x3
339static int smb5_configure_internal_pull(struct smb_charger *chg, int type,
340 int pull)
341{
342 int rc;
343 int shift = type * 2;
344 u8 mask = INTERNAL_PULL_UP_MASK << shift;
345 u8 val = pull << shift;
346
347 rc = smblib_masked_write(chg, BATIF_ADC_INTERNAL_PULL_UP_REG,
348 mask, val);
349 if (rc < 0)
350 dev_err(chg->dev,
351 "Couldn't configure ADC pull-up reg rc=%d\n", rc);
352
353 return rc;
354}
355
Harry Yang4b7db0f2017-11-27 10:50:44 -0800356#define MICRO_1P5A 1500000
Ashay Jaiswalb2b06fe2018-06-07 18:35:21 +0530357#define MICRO_1PA 1000000
Harry Yang4b7db0f2017-11-27 10:50:44 -0800358#define MICRO_P1A 100000
359#define OTG_DEFAULT_DEGLITCH_TIME_MS 50
360#define MIN_WD_BARK_TIME 16
361#define DEFAULT_WD_BARK_TIME 64
362#define BITE_WDOG_TIMEOUT_8S 0x3
363#define BARK_WDOG_TIMEOUT_MASK GENMASK(3, 2)
364#define BARK_WDOG_TIMEOUT_SHIFT 2
365static int smb5_parse_dt(struct smb5 *chip)
366{
367 struct smb_charger *chg = &chip->chg;
368 struct device_node *node = chg->dev->of_node;
369 int rc, byte_len;
370
371 if (!node) {
372 pr_err("device tree node missing\n");
373 return -EINVAL;
374 }
375
376 chg->step_chg_enabled = of_property_read_bool(node,
377 "qcom,step-charging-enable");
378
379 chg->sw_jeita_enabled = of_property_read_bool(node,
380 "qcom,sw-jeita-enable");
381
382 rc = of_property_read_u32(node, "qcom,wd-bark-time-secs",
383 &chip->dt.wd_bark_time);
384 if (rc < 0 || chip->dt.wd_bark_time < MIN_WD_BARK_TIME)
385 chip->dt.wd_bark_time = DEFAULT_WD_BARK_TIME;
386
387 chip->dt.no_battery = of_property_read_bool(node,
388 "qcom,batteryless-platform");
389
390 rc = of_property_read_u32(node,
391 "qcom,fcc-max-ua", &chip->dt.batt_profile_fcc_ua);
392 if (rc < 0)
393 chip->dt.batt_profile_fcc_ua = -EINVAL;
394
395 rc = of_property_read_u32(node,
396 "qcom,fv-max-uv", &chip->dt.batt_profile_fv_uv);
397 if (rc < 0)
398 chip->dt.batt_profile_fv_uv = -EINVAL;
399
400 rc = of_property_read_u32(node,
401 "qcom,usb-icl-ua", &chip->dt.usb_icl_ua);
402 if (rc < 0)
403 chip->dt.usb_icl_ua = -EINVAL;
404
405 rc = of_property_read_u32(node,
406 "qcom,otg-cl-ua", &chg->otg_cl_ua);
407 if (rc < 0)
Ashay Jaiswalb2b06fe2018-06-07 18:35:21 +0530408 chg->otg_cl_ua = (chip->chg.smb_version == PMI632_SUBTYPE) ?
409 MICRO_1PA : MICRO_1P5A;
Harry Yang4b7db0f2017-11-27 10:50:44 -0800410
411 if (of_find_property(node, "qcom,thermal-mitigation", &byte_len)) {
412 chg->thermal_mitigation = devm_kzalloc(chg->dev, byte_len,
413 GFP_KERNEL);
414
415 if (chg->thermal_mitigation == NULL)
416 return -ENOMEM;
417
418 chg->thermal_levels = byte_len / sizeof(u32);
419 rc = of_property_read_u32_array(node,
420 "qcom,thermal-mitigation",
421 chg->thermal_mitigation,
422 chg->thermal_levels);
423 if (rc < 0) {
424 dev_err(chg->dev,
425 "Couldn't read threm limits rc = %d\n", rc);
426 return rc;
427 }
428 }
429
430 rc = of_property_read_u32(node, "qcom,float-option",
431 &chip->dt.float_option);
432 if (!rc && (chip->dt.float_option < 0 || chip->dt.float_option > 4)) {
433 pr_err("qcom,float-option is out of range [0, 4]\n");
434 return -EINVAL;
435 }
436
437 chip->dt.hvdcp_disable = of_property_read_bool(node,
438 "qcom,hvdcp-disable");
439
440
441 rc = of_property_read_u32(node, "qcom,chg-inhibit-threshold-mv",
442 &chip->dt.chg_inhibit_thr_mv);
443 if (!rc && (chip->dt.chg_inhibit_thr_mv < 0 ||
444 chip->dt.chg_inhibit_thr_mv > 300)) {
445 pr_err("qcom,chg-inhibit-threshold-mv is incorrect\n");
446 return -EINVAL;
447 }
448
Anirudh Ghayal1380d312018-02-23 00:01:43 +0530449 chip->dt.auto_recharge_soc = -EINVAL;
450 rc = of_property_read_u32(node, "qcom,auto-recharge-soc",
451 &chip->dt.auto_recharge_soc);
452 if (!rc && (chip->dt.auto_recharge_soc < 0 ||
453 chip->dt.auto_recharge_soc > 100)) {
454 pr_err("qcom,auto-recharge-soc is incorrect\n");
455 return -EINVAL;
456 }
457 chg->auto_recharge_soc = chip->dt.auto_recharge_soc;
458
459 chip->dt.auto_recharge_vbat_mv = -EINVAL;
460 rc = of_property_read_u32(node, "qcom,auto-recharge-vbat-mv",
461 &chip->dt.auto_recharge_vbat_mv);
462 if (!rc && (chip->dt.auto_recharge_vbat_mv < 0)) {
463 pr_err("qcom,auto-recharge-vbat-mv is incorrect\n");
464 return -EINVAL;
465 }
Harry Yang4b7db0f2017-11-27 10:50:44 -0800466
Harry Yang4b7db0f2017-11-27 10:50:44 -0800467 chg->dcp_icl_ua = chip->dt.usb_icl_ua;
468
469 chg->suspend_input_on_debug_batt = of_property_read_bool(node,
470 "qcom,suspend-input-on-debug-batt");
471
472 rc = of_property_read_u32(node, "qcom,otg-deglitch-time-ms",
473 &chg->otg_delay_ms);
474 if (rc < 0)
475 chg->otg_delay_ms = OTG_DEFAULT_DEGLITCH_TIME_MS;
476
Ashay Jaiswal0de6fb92018-06-12 17:23:45 +0530477 chg->hw_die_temp_mitigation = of_property_read_bool(node,
478 "qcom,hw-die-temp-mitigation");
479
480 chg->hw_connector_mitigation = of_property_read_bool(node,
481 "qcom,hw-connector-mitigation");
482
483 chg->connector_pull_up = -EINVAL;
484 of_property_read_u32(node, "qcom,connector-internal-pull-kohm",
485 &chg->connector_pull_up);
486
Harry Yang4b7db0f2017-11-27 10:50:44 -0800487 return 0;
488}
489
Ashay Jaiswal20688262018-04-25 11:45:34 +0530490static int smb5_get_adc_data(struct smb_charger *chg, int channel,
491 union power_supply_propval *val)
492{
Anirudh Ghayal75f8f812018-07-09 16:48:47 +0530493 int rc = 0;
Ashay Jaiswal20688262018-04-25 11:45:34 +0530494 struct qpnp_vadc_result result;
Ashay Jaiswalb50706d2018-06-28 19:37:31 +0530495 u8 reg;
Ashay Jaiswal20688262018-04-25 11:45:34 +0530496
497 if (!chg->vadc_dev) {
498 if (of_find_property(chg->dev->of_node, "qcom,chg-vadc",
499 NULL)) {
500 chg->vadc_dev = qpnp_get_vadc(chg->dev, "chg");
501 if (IS_ERR(chg->vadc_dev)) {
502 rc = PTR_ERR(chg->vadc_dev);
503 if (rc != -EPROBE_DEFER)
504 pr_debug("Failed to find VADC node, rc=%d\n",
505 rc);
506 else
507 chg->vadc_dev = NULL;
508
509 return rc;
510 }
511 } else {
512 return -ENODATA;
513 }
514 }
515
516 if (IS_ERR(chg->vadc_dev))
517 return PTR_ERR(chg->vadc_dev);
518
Anirudh Ghayal75f8f812018-07-09 16:48:47 +0530519 mutex_lock(&chg->vadc_lock);
520
Ashay Jaiswal20688262018-04-25 11:45:34 +0530521 switch (channel) {
522 case USBIN_VOLTAGE:
Ashay Jaiswalb50706d2018-06-28 19:37:31 +0530523 /* Store ADC channel config */
524 rc = smblib_read(chg, BATIF_ADC_CHANNEL_EN_REG, &reg);
525 if (rc < 0) {
526 dev_err(chg->dev,
527 "Couldn't read ADC config rc=%d\n", rc);
Anirudh Ghayal75f8f812018-07-09 16:48:47 +0530528 goto done;
Ashay Jaiswalb50706d2018-06-28 19:37:31 +0530529 }
530
531 /* Disable all ADC channels except IBAT channel */
532 rc = smblib_write(chg, BATIF_ADC_CHANNEL_EN_REG,
533 IBATT_CHANNEL_EN_BIT);
534 if (rc < 0) {
535 dev_err(chg->dev,
536 "Couldn't write ADC config rc=%d\n", rc);
Anirudh Ghayal75f8f812018-07-09 16:48:47 +0530537 goto done;
Ashay Jaiswalb50706d2018-06-28 19:37:31 +0530538 }
539
Ashay Jaiswal20688262018-04-25 11:45:34 +0530540 rc = qpnp_vadc_read(chg->vadc_dev, VADC_USB_IN_V_DIV_16_PM5,
541 &result);
Anirudh Ghayal75f8f812018-07-09 16:48:47 +0530542 if (rc < 0)
Ashay Jaiswal20688262018-04-25 11:45:34 +0530543 pr_err("Failed to read USBIN_V over vadc, rc=%d\n", rc);
Anirudh Ghayal75f8f812018-07-09 16:48:47 +0530544 else
545 val->intval = result.physical;
Ashay Jaiswalb50706d2018-06-28 19:37:31 +0530546
Ashay Jaiswalb50706d2018-06-28 19:37:31 +0530547 /* Restore ADC channel config */
Anirudh Ghayal75f8f812018-07-09 16:48:47 +0530548 rc |= smblib_write(chg, BATIF_ADC_CHANNEL_EN_REG, reg);
549 if (rc < 0)
Ashay Jaiswalb50706d2018-06-28 19:37:31 +0530550 dev_err(chg->dev,
551 "Couldn't write ADC config rc=%d\n", rc);
Anirudh Ghayal75f8f812018-07-09 16:48:47 +0530552
Ashay Jaiswal20688262018-04-25 11:45:34 +0530553 break;
554 case USBIN_CURRENT:
555 rc = qpnp_vadc_read(chg->vadc_dev, VADC_USB_IN_I_PM5, &result);
556 if (rc < 0) {
557 pr_err("Failed to read USBIN_I over vadc, rc=%d\n", rc);
Anirudh Ghayal75f8f812018-07-09 16:48:47 +0530558 goto done;
Ashay Jaiswal20688262018-04-25 11:45:34 +0530559 }
560 val->intval = result.physical;
561 break;
562 default:
563 pr_debug("Invalid channel\n");
Anirudh Ghayal75f8f812018-07-09 16:48:47 +0530564 rc = -EINVAL;
565 break;
Ashay Jaiswal20688262018-04-25 11:45:34 +0530566 }
567
Anirudh Ghayal75f8f812018-07-09 16:48:47 +0530568done:
569 mutex_unlock(&chg->vadc_lock);
570 return rc;
Ashay Jaiswal20688262018-04-25 11:45:34 +0530571}
572
573
Harry Yang4b7db0f2017-11-27 10:50:44 -0800574/************************
575 * USB PSY REGISTRATION *
576 ************************/
577static enum power_supply_property smb5_usb_props[] = {
578 POWER_SUPPLY_PROP_PRESENT,
579 POWER_SUPPLY_PROP_ONLINE,
580 POWER_SUPPLY_PROP_PD_CURRENT_MAX,
581 POWER_SUPPLY_PROP_CURRENT_MAX,
582 POWER_SUPPLY_PROP_TYPE,
583 POWER_SUPPLY_PROP_TYPEC_MODE,
584 POWER_SUPPLY_PROP_TYPEC_POWER_ROLE,
585 POWER_SUPPLY_PROP_TYPEC_CC_ORIENTATION,
Harry Yang4b7db0f2017-11-27 10:50:44 -0800586 POWER_SUPPLY_PROP_PD_ACTIVE,
587 POWER_SUPPLY_PROP_INPUT_CURRENT_SETTLED,
588 POWER_SUPPLY_PROP_INPUT_CURRENT_NOW,
589 POWER_SUPPLY_PROP_BOOST_CURRENT,
590 POWER_SUPPLY_PROP_PE_START,
591 POWER_SUPPLY_PROP_CTM_CURRENT_MAX,
592 POWER_SUPPLY_PROP_HW_CURRENT_MAX,
593 POWER_SUPPLY_PROP_REAL_TYPE,
594 POWER_SUPPLY_PROP_PR_SWAP,
595 POWER_SUPPLY_PROP_PD_VOLTAGE_MAX,
596 POWER_SUPPLY_PROP_PD_VOLTAGE_MIN,
597 POWER_SUPPLY_PROP_SDP_CURRENT_MAX,
Ashay Jaiswala9e10912018-02-02 14:03:35 +0530598 POWER_SUPPLY_PROP_CONNECTOR_TYPE,
Ashay Jaiswal1f71b412017-10-31 14:33:27 +0530599 POWER_SUPPLY_PROP_VOLTAGE_MAX,
Umang Agrawal9fb865a2018-06-25 16:24:00 +0530600 POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN,
Ashay Jaiswal09feab82018-02-12 12:33:18 +0530601 POWER_SUPPLY_PROP_SCOPE,
Ashay Jaiswal20688262018-04-25 11:45:34 +0530602 POWER_SUPPLY_PROP_VOLTAGE_NOW,
Ashay Jaiswal4d334f42018-04-25 10:58:49 +0530603 POWER_SUPPLY_PROP_HVDCP_OPTI_ALLOWED,
Ashay Jaiswal0de6fb92018-06-12 17:23:45 +0530604 POWER_SUPPLY_PROP_QC_OPTI_DISABLE,
Harry Yang4b7db0f2017-11-27 10:50:44 -0800605};
606
607static int smb5_usb_get_prop(struct power_supply *psy,
608 enum power_supply_property psp,
609 union power_supply_propval *val)
610{
611 struct smb5 *chip = power_supply_get_drvdata(psy);
612 struct smb_charger *chg = &chip->chg;
Ashay Jaiswal09feab82018-02-12 12:33:18 +0530613 union power_supply_propval pval;
Harry Yang4b7db0f2017-11-27 10:50:44 -0800614 int rc = 0;
615
616 switch (psp) {
617 case POWER_SUPPLY_PROP_PRESENT:
618 rc = smblib_get_prop_usb_present(chg, val);
619 break;
620 case POWER_SUPPLY_PROP_ONLINE:
621 rc = smblib_get_prop_usb_online(chg, val);
622 if (!val->intval)
623 break;
624
Ashay Jaiswala9e10912018-02-02 14:03:35 +0530625 if (((chg->typec_mode == POWER_SUPPLY_TYPEC_SOURCE_DEFAULT) ||
626 (chg->connector_type == POWER_SUPPLY_CONNECTOR_MICRO_USB))
627 && (chg->real_charger_type == POWER_SUPPLY_TYPE_USB))
Harry Yang4b7db0f2017-11-27 10:50:44 -0800628 val->intval = 0;
629 else
630 val->intval = 1;
Ashay Jaiswala9e10912018-02-02 14:03:35 +0530631
Harry Yang4b7db0f2017-11-27 10:50:44 -0800632 if (chg->real_charger_type == POWER_SUPPLY_TYPE_UNKNOWN)
633 val->intval = 0;
634 break;
635 case POWER_SUPPLY_PROP_VOLTAGE_MAX:
636 rc = smblib_get_prop_usb_voltage_max(chg, val);
637 break;
Umang Agrawal9fb865a2018-06-25 16:24:00 +0530638 case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN:
639 rc = smblib_get_prop_usb_voltage_max_design(chg, val);
640 break;
Harry Yang4b7db0f2017-11-27 10:50:44 -0800641 case POWER_SUPPLY_PROP_PD_CURRENT_MAX:
642 val->intval = get_client_vote(chg->usb_icl_votable, PD_VOTER);
643 break;
644 case POWER_SUPPLY_PROP_CURRENT_MAX:
645 rc = smblib_get_prop_input_current_settled(chg, val);
646 break;
647 case POWER_SUPPLY_PROP_TYPE:
648 val->intval = POWER_SUPPLY_TYPE_USB_PD;
649 break;
650 case POWER_SUPPLY_PROP_REAL_TYPE:
651 val->intval = chg->real_charger_type;
652 break;
653 case POWER_SUPPLY_PROP_TYPEC_MODE:
Ashay Jaiswala9e10912018-02-02 14:03:35 +0530654 if (chg->connector_type == POWER_SUPPLY_CONNECTOR_MICRO_USB)
Harry Yang4b7db0f2017-11-27 10:50:44 -0800655 val->intval = POWER_SUPPLY_TYPEC_NONE;
656 else
657 val->intval = chg->typec_mode;
658 break;
659 case POWER_SUPPLY_PROP_TYPEC_POWER_ROLE:
Ashay Jaiswala9e10912018-02-02 14:03:35 +0530660 if (chg->connector_type == POWER_SUPPLY_CONNECTOR_MICRO_USB)
Harry Yang4b7db0f2017-11-27 10:50:44 -0800661 val->intval = POWER_SUPPLY_TYPEC_PR_NONE;
662 else
663 rc = smblib_get_prop_typec_power_role(chg, val);
664 break;
665 case POWER_SUPPLY_PROP_TYPEC_CC_ORIENTATION:
Ashay Jaiswala9e10912018-02-02 14:03:35 +0530666 if (chg->connector_type == POWER_SUPPLY_CONNECTOR_MICRO_USB)
Harry Yang4b7db0f2017-11-27 10:50:44 -0800667 val->intval = 0;
668 else
669 rc = smblib_get_prop_typec_cc_orientation(chg, val);
670 break;
Harry Yang4b7db0f2017-11-27 10:50:44 -0800671 case POWER_SUPPLY_PROP_PD_ACTIVE:
672 val->intval = chg->pd_active;
673 break;
674 case POWER_SUPPLY_PROP_INPUT_CURRENT_SETTLED:
675 rc = smblib_get_prop_input_current_settled(chg, val);
676 break;
677 case POWER_SUPPLY_PROP_BOOST_CURRENT:
678 val->intval = chg->boost_current_ua;
679 break;
680 case POWER_SUPPLY_PROP_PD_IN_HARD_RESET:
681 rc = smblib_get_prop_pd_in_hard_reset(chg, val);
682 break;
683 case POWER_SUPPLY_PROP_PD_USB_SUSPEND_SUPPORTED:
684 val->intval = chg->system_suspend_supported;
685 break;
686 case POWER_SUPPLY_PROP_PE_START:
687 rc = smblib_get_pe_start(chg, val);
688 break;
689 case POWER_SUPPLY_PROP_CTM_CURRENT_MAX:
690 val->intval = get_client_vote(chg->usb_icl_votable, CTM_VOTER);
691 break;
692 case POWER_SUPPLY_PROP_HW_CURRENT_MAX:
693 rc = smblib_get_charge_current(chg, &val->intval);
694 break;
695 case POWER_SUPPLY_PROP_PR_SWAP:
696 rc = smblib_get_prop_pr_swap_in_progress(chg, val);
697 break;
698 case POWER_SUPPLY_PROP_PD_VOLTAGE_MAX:
699 val->intval = chg->voltage_max_uv;
700 break;
701 case POWER_SUPPLY_PROP_PD_VOLTAGE_MIN:
702 val->intval = chg->voltage_min_uv;
703 break;
704 case POWER_SUPPLY_PROP_SDP_CURRENT_MAX:
705 val->intval = get_client_vote(chg->usb_icl_votable,
706 USB_PSY_VOTER);
707 break;
Ashay Jaiswala9e10912018-02-02 14:03:35 +0530708 case POWER_SUPPLY_PROP_CONNECTOR_TYPE:
709 val->intval = chg->connector_type;
710 break;
Ashay Jaiswal09feab82018-02-12 12:33:18 +0530711 case POWER_SUPPLY_PROP_SCOPE:
712 val->intval = POWER_SUPPLY_SCOPE_UNKNOWN;
713 rc = smblib_get_prop_usb_present(chg, &pval);
714 if (rc < 0)
715 break;
716 val->intval = pval.intval ? POWER_SUPPLY_SCOPE_DEVICE
717 : chg->otg_present ? POWER_SUPPLY_SCOPE_SYSTEM
718 : POWER_SUPPLY_SCOPE_UNKNOWN;
719 break;
Ashay Jaiswal20688262018-04-25 11:45:34 +0530720 case POWER_SUPPLY_PROP_INPUT_CURRENT_NOW:
721 rc = smblib_get_prop_usb_present(chg, &pval);
722 if (rc < 0 || !pval.intval) {
723 val->intval = 0;
724 return rc;
725 }
726 if (chg->smb_version == PMI632_SUBTYPE)
727 rc = smb5_get_adc_data(chg, USBIN_CURRENT, val);
728 break;
729 case POWER_SUPPLY_PROP_VOLTAGE_NOW:
730 if (chg->smb_version == PMI632_SUBTYPE)
731 rc = smb5_get_adc_data(chg, USBIN_VOLTAGE, val);
732 break;
Ashay Jaiswal4d334f42018-04-25 10:58:49 +0530733 case POWER_SUPPLY_PROP_HVDCP_OPTI_ALLOWED:
734 val->intval = !chg->flash_active;
735 break;
Ashay Jaiswal0de6fb92018-06-12 17:23:45 +0530736 case POWER_SUPPLY_PROP_QC_OPTI_DISABLE:
737 if (chg->hw_die_temp_mitigation)
738 val->intval = POWER_SUPPLY_QC_THERMAL_BALANCE_DISABLE
739 | POWER_SUPPLY_QC_INOV_THERMAL_DISABLE;
740 if (chg->hw_connector_mitigation)
741 val->intval |= POWER_SUPPLY_QC_CTM_DISABLE;
742 break;
Harry Yang4b7db0f2017-11-27 10:50:44 -0800743 default:
744 pr_err("get prop %d is not supported in usb\n", psp);
745 rc = -EINVAL;
746 break;
747 }
748
749 if (rc < 0) {
750 pr_debug("Couldn't get prop %d rc = %d\n", psp, rc);
751 return -ENODATA;
752 }
753
754 return 0;
755}
756
757static int smb5_usb_set_prop(struct power_supply *psy,
758 enum power_supply_property psp,
759 const union power_supply_propval *val)
760{
761 struct smb5 *chip = power_supply_get_drvdata(psy);
762 struct smb_charger *chg = &chip->chg;
763 int rc = 0;
764
Harry Yang4b7db0f2017-11-27 10:50:44 -0800765 switch (psp) {
766 case POWER_SUPPLY_PROP_PD_CURRENT_MAX:
767 rc = smblib_set_prop_pd_current_max(chg, val);
768 break;
769 case POWER_SUPPLY_PROP_TYPEC_POWER_ROLE:
770 rc = smblib_set_prop_typec_power_role(chg, val);
771 break;
772 case POWER_SUPPLY_PROP_PD_ACTIVE:
773 rc = smblib_set_prop_pd_active(chg, val);
774 break;
775 case POWER_SUPPLY_PROP_PD_IN_HARD_RESET:
776 rc = smblib_set_prop_pd_in_hard_reset(chg, val);
777 break;
778 case POWER_SUPPLY_PROP_PD_USB_SUSPEND_SUPPORTED:
779 chg->system_suspend_supported = val->intval;
780 break;
781 case POWER_SUPPLY_PROP_BOOST_CURRENT:
782 rc = smblib_set_prop_boost_current(chg, val);
783 break;
784 case POWER_SUPPLY_PROP_CTM_CURRENT_MAX:
785 rc = vote(chg->usb_icl_votable, CTM_VOTER,
786 val->intval >= 0, val->intval);
787 break;
788 case POWER_SUPPLY_PROP_PR_SWAP:
789 rc = smblib_set_prop_pr_swap_in_progress(chg, val);
790 break;
791 case POWER_SUPPLY_PROP_PD_VOLTAGE_MAX:
792 rc = smblib_set_prop_pd_voltage_max(chg, val);
793 break;
794 case POWER_SUPPLY_PROP_PD_VOLTAGE_MIN:
795 rc = smblib_set_prop_pd_voltage_min(chg, val);
796 break;
797 case POWER_SUPPLY_PROP_SDP_CURRENT_MAX:
798 rc = smblib_set_prop_sdp_current_max(chg, val);
799 break;
800 default:
801 pr_err("set prop %d is not supported\n", psp);
802 rc = -EINVAL;
803 break;
804 }
805
Harry Yang4b7db0f2017-11-27 10:50:44 -0800806 return rc;
807}
808
809static int smb5_usb_prop_is_writeable(struct power_supply *psy,
810 enum power_supply_property psp)
811{
812 switch (psp) {
813 case POWER_SUPPLY_PROP_CTM_CURRENT_MAX:
814 return 1;
815 default:
816 break;
817 }
818
819 return 0;
820}
821
822static const struct power_supply_desc usb_psy_desc = {
823 .name = "usb",
824 .type = POWER_SUPPLY_TYPE_USB_PD,
825 .properties = smb5_usb_props,
826 .num_properties = ARRAY_SIZE(smb5_usb_props),
827 .get_property = smb5_usb_get_prop,
828 .set_property = smb5_usb_set_prop,
829 .property_is_writeable = smb5_usb_prop_is_writeable,
830};
831
832static int smb5_init_usb_psy(struct smb5 *chip)
833{
834 struct power_supply_config usb_cfg = {};
835 struct smb_charger *chg = &chip->chg;
836
837 usb_cfg.drv_data = chip;
838 usb_cfg.of_node = chg->dev->of_node;
839 chg->usb_psy = devm_power_supply_register(chg->dev,
840 &usb_psy_desc,
841 &usb_cfg);
842 if (IS_ERR(chg->usb_psy)) {
843 pr_err("Couldn't register USB power supply\n");
844 return PTR_ERR(chg->usb_psy);
845 }
846
847 return 0;
848}
849
850/********************************
851 * USB PC_PORT PSY REGISTRATION *
852 ********************************/
853static enum power_supply_property smb5_usb_port_props[] = {
854 POWER_SUPPLY_PROP_TYPE,
855 POWER_SUPPLY_PROP_ONLINE,
856 POWER_SUPPLY_PROP_VOLTAGE_MAX,
857 POWER_SUPPLY_PROP_CURRENT_MAX,
858};
859
860static int smb5_usb_port_get_prop(struct power_supply *psy,
861 enum power_supply_property psp,
862 union power_supply_propval *val)
863{
864 struct smb5 *chip = power_supply_get_drvdata(psy);
865 struct smb_charger *chg = &chip->chg;
866 int rc = 0;
867
868 switch (psp) {
869 case POWER_SUPPLY_PROP_TYPE:
870 val->intval = POWER_SUPPLY_TYPE_USB;
871 break;
872 case POWER_SUPPLY_PROP_ONLINE:
873 rc = smblib_get_prop_usb_online(chg, val);
874 if (!val->intval)
875 break;
876
Ashay Jaiswala9e10912018-02-02 14:03:35 +0530877 if (((chg->typec_mode == POWER_SUPPLY_TYPEC_SOURCE_DEFAULT) ||
878 (chg->connector_type == POWER_SUPPLY_CONNECTOR_MICRO_USB))
879 && (chg->real_charger_type == POWER_SUPPLY_TYPE_USB))
Harry Yang4b7db0f2017-11-27 10:50:44 -0800880 val->intval = 1;
881 else
882 val->intval = 0;
883 break;
884 case POWER_SUPPLY_PROP_VOLTAGE_MAX:
885 val->intval = 5000000;
886 break;
887 case POWER_SUPPLY_PROP_CURRENT_MAX:
888 rc = smblib_get_prop_input_current_settled(chg, val);
889 break;
890 default:
891 pr_err_ratelimited("Get prop %d is not supported in pc_port\n",
892 psp);
893 return -EINVAL;
894 }
895
896 if (rc < 0) {
897 pr_debug("Couldn't get prop %d rc = %d\n", psp, rc);
898 return -ENODATA;
899 }
900
901 return 0;
902}
903
904static int smb5_usb_port_set_prop(struct power_supply *psy,
905 enum power_supply_property psp,
906 const union power_supply_propval *val)
907{
908 int rc = 0;
909
910 switch (psp) {
911 default:
912 pr_err_ratelimited("Set prop %d is not supported in pc_port\n",
913 psp);
914 rc = -EINVAL;
915 break;
916 }
917
918 return rc;
919}
920
921static const struct power_supply_desc usb_port_psy_desc = {
922 .name = "pc_port",
923 .type = POWER_SUPPLY_TYPE_USB,
924 .properties = smb5_usb_port_props,
925 .num_properties = ARRAY_SIZE(smb5_usb_port_props),
926 .get_property = smb5_usb_port_get_prop,
927 .set_property = smb5_usb_port_set_prop,
928};
929
930static int smb5_init_usb_port_psy(struct smb5 *chip)
931{
932 struct power_supply_config usb_port_cfg = {};
933 struct smb_charger *chg = &chip->chg;
934
935 usb_port_cfg.drv_data = chip;
936 usb_port_cfg.of_node = chg->dev->of_node;
937 chg->usb_port_psy = devm_power_supply_register(chg->dev,
938 &usb_port_psy_desc,
939 &usb_port_cfg);
940 if (IS_ERR(chg->usb_port_psy)) {
941 pr_err("Couldn't register USB pc_port power supply\n");
942 return PTR_ERR(chg->usb_port_psy);
943 }
944
945 return 0;
946}
947
948/*****************************
949 * USB MAIN PSY REGISTRATION *
950 *****************************/
951
952static enum power_supply_property smb5_usb_main_props[] = {
953 POWER_SUPPLY_PROP_VOLTAGE_MAX,
954 POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX,
955 POWER_SUPPLY_PROP_TYPE,
956 POWER_SUPPLY_PROP_INPUT_CURRENT_SETTLED,
957 POWER_SUPPLY_PROP_INPUT_VOLTAGE_SETTLED,
958 POWER_SUPPLY_PROP_FCC_DELTA,
959 POWER_SUPPLY_PROP_CURRENT_MAX,
Ashay Jaiswal09feab82018-02-12 12:33:18 +0530960 POWER_SUPPLY_PROP_FLASH_ACTIVE,
961 POWER_SUPPLY_PROP_FLASH_TRIGGER,
Harry Yang4b7db0f2017-11-27 10:50:44 -0800962};
963
964static int smb5_usb_main_get_prop(struct power_supply *psy,
965 enum power_supply_property psp,
966 union power_supply_propval *val)
967{
968 struct smb5 *chip = power_supply_get_drvdata(psy);
969 struct smb_charger *chg = &chip->chg;
970 int rc = 0;
971
972 switch (psp) {
973 case POWER_SUPPLY_PROP_VOLTAGE_MAX:
974 rc = smblib_get_charge_param(chg, &chg->param.fv, &val->intval);
975 break;
976 case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX:
977 rc = smblib_get_charge_param(chg, &chg->param.fcc,
978 &val->intval);
979 break;
980 case POWER_SUPPLY_PROP_TYPE:
981 val->intval = POWER_SUPPLY_TYPE_MAIN;
982 break;
983 case POWER_SUPPLY_PROP_INPUT_CURRENT_SETTLED:
984 rc = smblib_get_prop_input_current_settled(chg, val);
985 break;
986 case POWER_SUPPLY_PROP_INPUT_VOLTAGE_SETTLED:
987 rc = smblib_get_prop_input_voltage_settled(chg, val);
988 break;
989 case POWER_SUPPLY_PROP_FCC_DELTA:
990 rc = smblib_get_prop_fcc_delta(chg, val);
991 break;
992 case POWER_SUPPLY_PROP_CURRENT_MAX:
993 rc = smblib_get_icl_current(chg, &val->intval);
994 break;
Ashay Jaiswal09feab82018-02-12 12:33:18 +0530995 case POWER_SUPPLY_PROP_FLASH_ACTIVE:
996 val->intval = chg->flash_active;
997 break;
998 case POWER_SUPPLY_PROP_FLASH_TRIGGER:
999 rc = schgm_flash_get_vreg_ok(chg, &val->intval);
1000 break;
Harry Yang4b7db0f2017-11-27 10:50:44 -08001001 default:
1002 pr_debug("get prop %d is not supported in usb-main\n", psp);
1003 rc = -EINVAL;
1004 break;
1005 }
1006 if (rc < 0) {
1007 pr_debug("Couldn't get prop %d rc = %d\n", psp, rc);
1008 return -ENODATA;
1009 }
1010
1011 return 0;
1012}
1013
1014static int smb5_usb_main_set_prop(struct power_supply *psy,
1015 enum power_supply_property psp,
1016 const union power_supply_propval *val)
1017{
1018 struct smb5 *chip = power_supply_get_drvdata(psy);
1019 struct smb_charger *chg = &chip->chg;
Ashay Jaiswal4d334f42018-04-25 10:58:49 +05301020 union power_supply_propval pval = {0, };
Harry Yang4b7db0f2017-11-27 10:50:44 -08001021 int rc = 0;
1022
1023 switch (psp) {
1024 case POWER_SUPPLY_PROP_VOLTAGE_MAX:
1025 rc = smblib_set_charge_param(chg, &chg->param.fv, val->intval);
1026 break;
1027 case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX:
1028 rc = smblib_set_charge_param(chg, &chg->param.fcc, val->intval);
1029 break;
1030 case POWER_SUPPLY_PROP_CURRENT_MAX:
1031 rc = smblib_set_icl_current(chg, val->intval);
1032 break;
Ashay Jaiswal09feab82018-02-12 12:33:18 +05301033 case POWER_SUPPLY_PROP_FLASH_ACTIVE:
Ashay Jaiswal4d334f42018-04-25 10:58:49 +05301034 if ((chg->smb_version == PMI632_SUBTYPE)
1035 && (chg->flash_active != val->intval)) {
1036 chg->flash_active = val->intval;
1037
1038 rc = smblib_get_prop_usb_present(chg, &pval);
1039 if (rc < 0)
1040 pr_err("Failed to get USB preset status rc=%d\n",
1041 rc);
1042 if (pval.intval) {
1043 rc = smblib_force_vbus_voltage(chg,
1044 chg->flash_active ? FORCE_5V_BIT
1045 : IDLE_BIT);
1046 if (rc < 0)
1047 pr_err("Failed to force 5V\n");
1048 else
1049 chg->pulse_cnt = 0;
Anirudh Ghayal4d5cddc2018-06-28 15:19:39 +05301050 } else {
1051 /* USB absent & flash not-active - vote 100mA */
1052 vote(chg->usb_icl_votable, SW_ICL_MAX_VOTER,
1053 true, SDP_100_MA);
Ashay Jaiswal4d334f42018-04-25 10:58:49 +05301054 }
1055
1056 pr_debug("flash active VBUS 5V restriction %s\n",
1057 chg->flash_active ? "applied" : "removed");
1058
1059 /* Update userspace */
1060 if (chg->batt_psy)
1061 power_supply_changed(chg->batt_psy);
1062 }
Ashay Jaiswal09feab82018-02-12 12:33:18 +05301063 break;
Harry Yang4b7db0f2017-11-27 10:50:44 -08001064 default:
1065 pr_err("set prop %d is not supported\n", psp);
1066 rc = -EINVAL;
1067 break;
1068 }
1069
1070 return rc;
1071}
1072
1073static const struct power_supply_desc usb_main_psy_desc = {
1074 .name = "main",
1075 .type = POWER_SUPPLY_TYPE_MAIN,
1076 .properties = smb5_usb_main_props,
1077 .num_properties = ARRAY_SIZE(smb5_usb_main_props),
1078 .get_property = smb5_usb_main_get_prop,
1079 .set_property = smb5_usb_main_set_prop,
1080};
1081
1082static int smb5_init_usb_main_psy(struct smb5 *chip)
1083{
1084 struct power_supply_config usb_main_cfg = {};
1085 struct smb_charger *chg = &chip->chg;
1086
1087 usb_main_cfg.drv_data = chip;
1088 usb_main_cfg.of_node = chg->dev->of_node;
1089 chg->usb_main_psy = devm_power_supply_register(chg->dev,
1090 &usb_main_psy_desc,
1091 &usb_main_cfg);
1092 if (IS_ERR(chg->usb_main_psy)) {
1093 pr_err("Couldn't register USB main power supply\n");
1094 return PTR_ERR(chg->usb_main_psy);
1095 }
1096
1097 return 0;
1098}
1099
1100/*************************
1101 * DC PSY REGISTRATION *
1102 *************************/
1103
1104static enum power_supply_property smb5_dc_props[] = {
1105 POWER_SUPPLY_PROP_INPUT_SUSPEND,
1106 POWER_SUPPLY_PROP_PRESENT,
1107 POWER_SUPPLY_PROP_ONLINE,
1108 POWER_SUPPLY_PROP_REAL_TYPE,
1109};
1110
1111static int smb5_dc_get_prop(struct power_supply *psy,
1112 enum power_supply_property psp,
1113 union power_supply_propval *val)
1114{
1115 struct smb5 *chip = power_supply_get_drvdata(psy);
1116 struct smb_charger *chg = &chip->chg;
1117 int rc = 0;
1118
1119 switch (psp) {
1120 case POWER_SUPPLY_PROP_INPUT_SUSPEND:
1121 val->intval = get_effective_result(chg->dc_suspend_votable);
1122 break;
1123 case POWER_SUPPLY_PROP_PRESENT:
1124 rc = smblib_get_prop_dc_present(chg, val);
1125 break;
1126 case POWER_SUPPLY_PROP_ONLINE:
1127 rc = smblib_get_prop_dc_online(chg, val);
1128 break;
1129 case POWER_SUPPLY_PROP_REAL_TYPE:
1130 val->intval = POWER_SUPPLY_TYPE_WIPOWER;
1131 break;
1132 default:
1133 return -EINVAL;
1134 }
1135 if (rc < 0) {
1136 pr_debug("Couldn't get prop %d rc = %d\n", psp, rc);
1137 return -ENODATA;
1138 }
1139 return 0;
1140}
1141
1142static int smb5_dc_set_prop(struct power_supply *psy,
1143 enum power_supply_property psp,
1144 const union power_supply_propval *val)
1145{
1146 struct smb5 *chip = power_supply_get_drvdata(psy);
1147 struct smb_charger *chg = &chip->chg;
1148 int rc = 0;
1149
1150 switch (psp) {
1151 case POWER_SUPPLY_PROP_INPUT_SUSPEND:
1152 rc = vote(chg->dc_suspend_votable, WBC_VOTER,
1153 (bool)val->intval, 0);
1154 break;
1155 default:
1156 return -EINVAL;
1157 }
1158
1159 return rc;
1160}
1161
1162static int smb5_dc_prop_is_writeable(struct power_supply *psy,
1163 enum power_supply_property psp)
1164{
1165 int rc;
1166
1167 switch (psp) {
1168 default:
1169 rc = 0;
1170 break;
1171 }
1172
1173 return rc;
1174}
1175
1176static const struct power_supply_desc dc_psy_desc = {
1177 .name = "dc",
1178 .type = POWER_SUPPLY_TYPE_WIRELESS,
1179 .properties = smb5_dc_props,
1180 .num_properties = ARRAY_SIZE(smb5_dc_props),
1181 .get_property = smb5_dc_get_prop,
1182 .set_property = smb5_dc_set_prop,
1183 .property_is_writeable = smb5_dc_prop_is_writeable,
1184};
1185
1186static int smb5_init_dc_psy(struct smb5 *chip)
1187{
1188 struct power_supply_config dc_cfg = {};
1189 struct smb_charger *chg = &chip->chg;
1190
1191 dc_cfg.drv_data = chip;
1192 dc_cfg.of_node = chg->dev->of_node;
1193 chg->dc_psy = devm_power_supply_register(chg->dev,
1194 &dc_psy_desc,
1195 &dc_cfg);
1196 if (IS_ERR(chg->dc_psy)) {
1197 pr_err("Couldn't register USB power supply\n");
1198 return PTR_ERR(chg->dc_psy);
1199 }
1200
1201 return 0;
1202}
1203
1204/*************************
1205 * BATT PSY REGISTRATION *
1206 *************************/
1207static enum power_supply_property smb5_batt_props[] = {
1208 POWER_SUPPLY_PROP_INPUT_SUSPEND,
Anirudh Ghayaldfdb8412018-04-21 10:37:18 +05301209 POWER_SUPPLY_PROP_BATTERY_CHARGING_ENABLED,
Harry Yang4b7db0f2017-11-27 10:50:44 -08001210 POWER_SUPPLY_PROP_STATUS,
1211 POWER_SUPPLY_PROP_HEALTH,
1212 POWER_SUPPLY_PROP_PRESENT,
1213 POWER_SUPPLY_PROP_CHARGE_TYPE,
1214 POWER_SUPPLY_PROP_CAPACITY,
1215 POWER_SUPPLY_PROP_INPUT_CURRENT_LIMITED,
1216 POWER_SUPPLY_PROP_VOLTAGE_NOW,
1217 POWER_SUPPLY_PROP_VOLTAGE_MAX,
1218 POWER_SUPPLY_PROP_CURRENT_NOW,
1219 POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX,
1220 POWER_SUPPLY_PROP_TEMP,
1221 POWER_SUPPLY_PROP_TECHNOLOGY,
1222 POWER_SUPPLY_PROP_STEP_CHARGING_ENABLED,
1223 POWER_SUPPLY_PROP_SW_JEITA_ENABLED,
1224 POWER_SUPPLY_PROP_CHARGE_DONE,
1225 POWER_SUPPLY_PROP_PARALLEL_DISABLE,
1226 POWER_SUPPLY_PROP_SET_SHIP_MODE,
1227 POWER_SUPPLY_PROP_DIE_HEALTH,
1228 POWER_SUPPLY_PROP_RERUN_AICL,
1229 POWER_SUPPLY_PROP_DP_DM,
1230 POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT_MAX,
1231 POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT,
1232 POWER_SUPPLY_PROP_CHARGE_COUNTER,
Subbaraman Narayanamurthyc4feb892018-05-07 18:43:45 -07001233 POWER_SUPPLY_PROP_CYCLE_COUNT,
Anirudh Ghayal1380d312018-02-23 00:01:43 +05301234 POWER_SUPPLY_PROP_RECHARGE_SOC,
Harry Yang4b7db0f2017-11-27 10:50:44 -08001235};
1236
1237static int smb5_batt_get_prop(struct power_supply *psy,
1238 enum power_supply_property psp,
1239 union power_supply_propval *val)
1240{
1241 struct smb_charger *chg = power_supply_get_drvdata(psy);
1242 int rc = 0;
1243
1244 switch (psp) {
1245 case POWER_SUPPLY_PROP_STATUS:
1246 rc = smblib_get_prop_batt_status(chg, val);
1247 break;
1248 case POWER_SUPPLY_PROP_HEALTH:
1249 rc = smblib_get_prop_batt_health(chg, val);
1250 break;
1251 case POWER_SUPPLY_PROP_PRESENT:
1252 rc = smblib_get_prop_batt_present(chg, val);
1253 break;
1254 case POWER_SUPPLY_PROP_INPUT_SUSPEND:
1255 rc = smblib_get_prop_input_suspend(chg, val);
1256 break;
Anirudh Ghayaldfdb8412018-04-21 10:37:18 +05301257 case POWER_SUPPLY_PROP_BATTERY_CHARGING_ENABLED:
1258 val->intval = !get_client_vote(chg->chg_disable_votable,
1259 USER_VOTER);
1260 break;
Harry Yang4b7db0f2017-11-27 10:50:44 -08001261 case POWER_SUPPLY_PROP_CHARGE_TYPE:
1262 rc = smblib_get_prop_batt_charge_type(chg, val);
1263 break;
1264 case POWER_SUPPLY_PROP_CAPACITY:
1265 rc = smblib_get_prop_batt_capacity(chg, val);
1266 break;
1267 case POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT:
1268 rc = smblib_get_prop_system_temp_level(chg, val);
1269 break;
1270 case POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT_MAX:
1271 rc = smblib_get_prop_system_temp_level_max(chg, val);
1272 break;
1273 case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMITED:
1274 rc = smblib_get_prop_input_current_limited(chg, val);
1275 break;
1276 case POWER_SUPPLY_PROP_STEP_CHARGING_ENABLED:
1277 val->intval = chg->step_chg_enabled;
1278 break;
1279 case POWER_SUPPLY_PROP_SW_JEITA_ENABLED:
1280 val->intval = chg->sw_jeita_enabled;
1281 break;
1282 case POWER_SUPPLY_PROP_VOLTAGE_NOW:
1283 rc = smblib_get_prop_batt_voltage_now(chg, val);
1284 break;
1285 case POWER_SUPPLY_PROP_VOLTAGE_MAX:
1286 val->intval = get_client_vote(chg->fv_votable,
1287 BATT_PROFILE_VOTER);
1288 break;
1289 case POWER_SUPPLY_PROP_CURRENT_NOW:
1290 rc = smblib_get_prop_batt_current_now(chg, val);
1291 break;
1292 case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX:
1293 val->intval = get_client_vote(chg->fcc_votable,
1294 BATT_PROFILE_VOTER);
1295 break;
1296 case POWER_SUPPLY_PROP_TEMP:
1297 rc = smblib_get_prop_batt_temp(chg, val);
1298 break;
1299 case POWER_SUPPLY_PROP_TECHNOLOGY:
1300 val->intval = POWER_SUPPLY_TECHNOLOGY_LION;
1301 break;
1302 case POWER_SUPPLY_PROP_CHARGE_DONE:
1303 rc = smblib_get_prop_batt_charge_done(chg, val);
1304 break;
1305 case POWER_SUPPLY_PROP_PARALLEL_DISABLE:
1306 val->intval = get_client_vote(chg->pl_disable_votable,
1307 USER_VOTER);
1308 break;
1309 case POWER_SUPPLY_PROP_SET_SHIP_MODE:
1310 /* Not in ship mode as long as device is active */
1311 val->intval = 0;
1312 break;
1313 case POWER_SUPPLY_PROP_DIE_HEALTH:
1314 if (chg->die_health == -EINVAL)
1315 rc = smblib_get_prop_die_health(chg, val);
1316 else
1317 val->intval = chg->die_health;
1318 break;
1319 case POWER_SUPPLY_PROP_DP_DM:
1320 val->intval = chg->pulse_cnt;
1321 break;
1322 case POWER_SUPPLY_PROP_RERUN_AICL:
1323 val->intval = 0;
1324 break;
1325 case POWER_SUPPLY_PROP_CHARGE_COUNTER:
1326 rc = smblib_get_prop_batt_charge_counter(chg, val);
1327 break;
Subbaraman Narayanamurthyc4feb892018-05-07 18:43:45 -07001328 case POWER_SUPPLY_PROP_CYCLE_COUNT:
1329 rc = smblib_get_prop_batt_cycle_count(chg, val);
1330 break;
Anirudh Ghayal1380d312018-02-23 00:01:43 +05301331 case POWER_SUPPLY_PROP_RECHARGE_SOC:
1332 val->intval = chg->auto_recharge_soc;
1333 break;
Harry Yang4b7db0f2017-11-27 10:50:44 -08001334 default:
1335 pr_err("batt power supply prop %d not supported\n", psp);
1336 return -EINVAL;
1337 }
1338
1339 if (rc < 0) {
1340 pr_debug("Couldn't get prop %d rc = %d\n", psp, rc);
1341 return -ENODATA;
1342 }
1343
1344 return 0;
1345}
1346
1347static int smb5_batt_set_prop(struct power_supply *psy,
1348 enum power_supply_property prop,
1349 const union power_supply_propval *val)
1350{
1351 int rc = 0;
1352 struct smb_charger *chg = power_supply_get_drvdata(psy);
Ashay Jaiswala55b7ed2018-03-23 17:23:48 +05301353 bool enable;
Harry Yang4b7db0f2017-11-27 10:50:44 -08001354
1355 switch (prop) {
1356 case POWER_SUPPLY_PROP_STATUS:
1357 rc = smblib_set_prop_batt_status(chg, val);
1358 break;
1359 case POWER_SUPPLY_PROP_INPUT_SUSPEND:
1360 rc = smblib_set_prop_input_suspend(chg, val);
1361 break;
Anirudh Ghayaldfdb8412018-04-21 10:37:18 +05301362 case POWER_SUPPLY_PROP_BATTERY_CHARGING_ENABLED:
1363 vote(chg->chg_disable_votable, USER_VOTER, !val->intval, 0);
1364 break;
Harry Yang4b7db0f2017-11-27 10:50:44 -08001365 case POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT:
1366 rc = smblib_set_prop_system_temp_level(chg, val);
1367 break;
1368 case POWER_SUPPLY_PROP_CAPACITY:
1369 rc = smblib_set_prop_batt_capacity(chg, val);
1370 break;
1371 case POWER_SUPPLY_PROP_PARALLEL_DISABLE:
1372 vote(chg->pl_disable_votable, USER_VOTER, (bool)val->intval, 0);
1373 break;
1374 case POWER_SUPPLY_PROP_VOLTAGE_MAX:
1375 chg->batt_profile_fv_uv = val->intval;
1376 vote(chg->fv_votable, BATT_PROFILE_VOTER, true, val->intval);
1377 break;
1378 case POWER_SUPPLY_PROP_STEP_CHARGING_ENABLED:
Ashay Jaiswala55b7ed2018-03-23 17:23:48 +05301379 enable = !!val->intval || chg->sw_jeita_enabled;
1380 rc = smblib_configure_wdog(chg, enable);
1381 if (rc == 0)
1382 chg->step_chg_enabled = !!val->intval;
Harry Yang4b7db0f2017-11-27 10:50:44 -08001383 break;
1384 case POWER_SUPPLY_PROP_SW_JEITA_ENABLED:
1385 if (chg->sw_jeita_enabled != (!!val->intval)) {
1386 rc = smblib_disable_hw_jeita(chg, !!val->intval);
Ashay Jaiswala55b7ed2018-03-23 17:23:48 +05301387 enable = !!val->intval || chg->step_chg_enabled;
1388 rc |= smblib_configure_wdog(chg, enable);
Harry Yang4b7db0f2017-11-27 10:50:44 -08001389 if (rc == 0)
1390 chg->sw_jeita_enabled = !!val->intval;
1391 }
1392 break;
1393 case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX:
1394 chg->batt_profile_fcc_ua = val->intval;
1395 vote(chg->fcc_votable, BATT_PROFILE_VOTER, true, val->intval);
1396 break;
1397 case POWER_SUPPLY_PROP_SET_SHIP_MODE:
1398 /* Not in ship mode as long as the device is active */
1399 if (!val->intval)
1400 break;
1401 if (chg->pl.psy)
1402 power_supply_set_property(chg->pl.psy,
1403 POWER_SUPPLY_PROP_SET_SHIP_MODE, val);
1404 rc = smblib_set_prop_ship_mode(chg, val);
1405 break;
1406 case POWER_SUPPLY_PROP_RERUN_AICL:
Ashay Jaiswale0b3c472018-06-20 23:39:41 +05301407 rc = smblib_run_aicl(chg, RERUN_AICL);
Harry Yang4b7db0f2017-11-27 10:50:44 -08001408 break;
1409 case POWER_SUPPLY_PROP_DP_DM:
Ashay Jaiswal4d334f42018-04-25 10:58:49 +05301410 if (!chg->flash_active)
1411 rc = smblib_dp_dm(chg, val->intval);
Harry Yang4b7db0f2017-11-27 10:50:44 -08001412 break;
1413 case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMITED:
1414 rc = smblib_set_prop_input_current_limited(chg, val);
1415 break;
1416 case POWER_SUPPLY_PROP_DIE_HEALTH:
1417 chg->die_health = val->intval;
1418 power_supply_changed(chg->batt_psy);
1419 break;
Anirudh Ghayaldfdb8412018-04-21 10:37:18 +05301420 case POWER_SUPPLY_PROP_RECHARGE_SOC:
1421 if (chg->smb_version == PMI632_SUBTYPE) {
1422 /* toggle charging to force recharge */
1423 vote(chg->chg_disable_votable, FORCE_RECHARGE_VOTER,
1424 true, 0);
1425 /* charge disable delay */
1426 msleep(50);
1427 vote(chg->chg_disable_votable, FORCE_RECHARGE_VOTER,
1428 false, 0);
1429 }
1430 break;
Harry Yang4b7db0f2017-11-27 10:50:44 -08001431 default:
1432 rc = -EINVAL;
1433 }
1434
1435 return rc;
1436}
1437
1438static int smb5_batt_prop_is_writeable(struct power_supply *psy,
1439 enum power_supply_property psp)
1440{
1441 switch (psp) {
1442 case POWER_SUPPLY_PROP_STATUS:
1443 case POWER_SUPPLY_PROP_INPUT_SUSPEND:
1444 case POWER_SUPPLY_PROP_SYSTEM_TEMP_LEVEL:
1445 case POWER_SUPPLY_PROP_CAPACITY:
1446 case POWER_SUPPLY_PROP_PARALLEL_DISABLE:
1447 case POWER_SUPPLY_PROP_DP_DM:
1448 case POWER_SUPPLY_PROP_RERUN_AICL:
1449 case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMITED:
1450 case POWER_SUPPLY_PROP_STEP_CHARGING_ENABLED:
1451 case POWER_SUPPLY_PROP_SW_JEITA_ENABLED:
1452 case POWER_SUPPLY_PROP_DIE_HEALTH:
Anirudh Ghayaldfdb8412018-04-21 10:37:18 +05301453 case POWER_SUPPLY_PROP_BATTERY_CHARGING_ENABLED:
Harry Yang4b7db0f2017-11-27 10:50:44 -08001454 return 1;
1455 default:
1456 break;
1457 }
1458
1459 return 0;
1460}
1461
1462static const struct power_supply_desc batt_psy_desc = {
1463 .name = "battery",
1464 .type = POWER_SUPPLY_TYPE_BATTERY,
1465 .properties = smb5_batt_props,
1466 .num_properties = ARRAY_SIZE(smb5_batt_props),
1467 .get_property = smb5_batt_get_prop,
1468 .set_property = smb5_batt_set_prop,
1469 .property_is_writeable = smb5_batt_prop_is_writeable,
1470};
1471
1472static int smb5_init_batt_psy(struct smb5 *chip)
1473{
1474 struct power_supply_config batt_cfg = {};
1475 struct smb_charger *chg = &chip->chg;
1476 int rc = 0;
1477
1478 batt_cfg.drv_data = chg;
1479 batt_cfg.of_node = chg->dev->of_node;
1480 chg->batt_psy = devm_power_supply_register(chg->dev,
1481 &batt_psy_desc,
1482 &batt_cfg);
1483 if (IS_ERR(chg->batt_psy)) {
1484 pr_err("Couldn't register battery power supply\n");
1485 return PTR_ERR(chg->batt_psy);
1486 }
1487
1488 return rc;
1489}
1490
1491/******************************
1492 * VBUS REGULATOR REGISTRATION *
1493 ******************************/
1494
1495static struct regulator_ops smb5_vbus_reg_ops = {
1496 .enable = smblib_vbus_regulator_enable,
1497 .disable = smblib_vbus_regulator_disable,
1498 .is_enabled = smblib_vbus_regulator_is_enabled,
1499};
1500
1501static int smb5_init_vbus_regulator(struct smb5 *chip)
1502{
1503 struct smb_charger *chg = &chip->chg;
1504 struct regulator_config cfg = {};
1505 int rc = 0;
1506
1507 chg->vbus_vreg = devm_kzalloc(chg->dev, sizeof(*chg->vbus_vreg),
1508 GFP_KERNEL);
1509 if (!chg->vbus_vreg)
1510 return -ENOMEM;
1511
1512 cfg.dev = chg->dev;
1513 cfg.driver_data = chip;
1514
1515 chg->vbus_vreg->rdesc.owner = THIS_MODULE;
1516 chg->vbus_vreg->rdesc.type = REGULATOR_VOLTAGE;
1517 chg->vbus_vreg->rdesc.ops = &smb5_vbus_reg_ops;
1518 chg->vbus_vreg->rdesc.of_match = "qcom,smb5-vbus";
1519 chg->vbus_vreg->rdesc.name = "qcom,smb5-vbus";
1520
1521 chg->vbus_vreg->rdev = devm_regulator_register(chg->dev,
1522 &chg->vbus_vreg->rdesc, &cfg);
1523 if (IS_ERR(chg->vbus_vreg->rdev)) {
1524 rc = PTR_ERR(chg->vbus_vreg->rdev);
1525 chg->vbus_vreg->rdev = NULL;
1526 if (rc != -EPROBE_DEFER)
1527 pr_err("Couldn't register VBUS regulator rc=%d\n", rc);
1528 }
1529
1530 return rc;
1531}
1532
1533/******************************
1534 * VCONN REGULATOR REGISTRATION *
1535 ******************************/
1536
1537static struct regulator_ops smb5_vconn_reg_ops = {
1538 .enable = smblib_vconn_regulator_enable,
1539 .disable = smblib_vconn_regulator_disable,
1540 .is_enabled = smblib_vconn_regulator_is_enabled,
1541};
1542
1543static int smb5_init_vconn_regulator(struct smb5 *chip)
1544{
1545 struct smb_charger *chg = &chip->chg;
1546 struct regulator_config cfg = {};
1547 int rc = 0;
1548
Ashay Jaiswala9e10912018-02-02 14:03:35 +05301549 if (chg->connector_type == POWER_SUPPLY_CONNECTOR_MICRO_USB)
Harry Yang4b7db0f2017-11-27 10:50:44 -08001550 return 0;
1551
1552 chg->vconn_vreg = devm_kzalloc(chg->dev, sizeof(*chg->vconn_vreg),
1553 GFP_KERNEL);
1554 if (!chg->vconn_vreg)
1555 return -ENOMEM;
1556
1557 cfg.dev = chg->dev;
1558 cfg.driver_data = chip;
1559
1560 chg->vconn_vreg->rdesc.owner = THIS_MODULE;
1561 chg->vconn_vreg->rdesc.type = REGULATOR_VOLTAGE;
1562 chg->vconn_vreg->rdesc.ops = &smb5_vconn_reg_ops;
1563 chg->vconn_vreg->rdesc.of_match = "qcom,smb5-vconn";
1564 chg->vconn_vreg->rdesc.name = "qcom,smb5-vconn";
1565
1566 chg->vconn_vreg->rdev = devm_regulator_register(chg->dev,
1567 &chg->vconn_vreg->rdesc, &cfg);
1568 if (IS_ERR(chg->vconn_vreg->rdev)) {
1569 rc = PTR_ERR(chg->vconn_vreg->rdev);
1570 chg->vconn_vreg->rdev = NULL;
1571 if (rc != -EPROBE_DEFER)
1572 pr_err("Couldn't register VCONN regulator rc=%d\n", rc);
1573 }
1574
1575 return rc;
1576}
1577
1578/***************************
1579 * HARDWARE INITIALIZATION *
1580 ***************************/
1581static int smb5_configure_typec(struct smb_charger *chg)
1582{
1583 int rc;
Ashay Jaiswal91d63f42018-05-16 11:30:40 +05301584 u8 val = 0;
1585
1586 rc = smblib_read(chg, LEGACY_CABLE_STATUS_REG, &val);
1587 if (rc < 0) {
1588 dev_err(chg->dev, "Couldn't read Legacy status rc=%d\n", rc);
1589 return rc;
1590 }
1591 /*
1592 * If Legacy cable is detected re-trigger Legacy detection
1593 * by disabling/enabling typeC mode.
1594 */
1595 if (val & TYPEC_LEGACY_CABLE_STATUS_BIT) {
1596 rc = smblib_masked_write(chg, TYPE_C_MODE_CFG_REG,
1597 TYPEC_DISABLE_CMD_BIT, TYPEC_DISABLE_CMD_BIT);
1598 if (rc < 0) {
1599 dev_err(chg->dev, "Couldn't disable TYPEC rc=%d\n", rc);
1600 return rc;
1601 }
1602
1603 /* delay before enabling typeC */
1604 msleep(500);
1605
1606 rc = smblib_masked_write(chg, TYPE_C_MODE_CFG_REG,
1607 TYPEC_DISABLE_CMD_BIT, 0);
1608 if (rc < 0) {
1609 dev_err(chg->dev, "Couldn't enable TYPEC rc=%d\n", rc);
1610 return rc;
1611 }
1612 }
Harry Yang4b7db0f2017-11-27 10:50:44 -08001613
Harry Yang6afaea22018-03-26 19:11:07 -07001614 /* disable apsd */
Ashay Jaiswalc96380de2018-05-16 12:02:36 +05301615 rc = smblib_configure_hvdcp_apsd(chg, false);
Harry Yang6afaea22018-03-26 19:11:07 -07001616 if (rc < 0) {
1617 dev_err(chg->dev, "Couldn't disable APSD rc=%d\n", rc);
1618 return rc;
1619 }
1620
Harry Yang4b7db0f2017-11-27 10:50:44 -08001621 rc = smblib_write(chg, TYPE_C_INTERRUPT_EN_CFG_1_REG,
1622 TYPEC_CCOUT_DETACH_INT_EN_BIT |
1623 TYPEC_CCOUT_ATTACH_INT_EN_BIT);
1624 if (rc < 0) {
1625 dev_err(chg->dev,
1626 "Couldn't configure Type-C interrupts rc=%d\n", rc);
1627 return rc;
1628 }
1629
1630 rc = smblib_write(chg, TYPE_C_INTERRUPT_EN_CFG_2_REG,
Harry Yang4b7db0f2017-11-27 10:50:44 -08001631 TYPEC_WATER_DETECTION_INT_EN_BIT);
1632 if (rc < 0) {
1633 dev_err(chg->dev,
1634 "Couldn't configure Type-C interrupts rc=%d\n", rc);
1635 return rc;
1636 }
1637
Harry Yang423d5c32018-05-30 15:49:04 -07001638 rc = smblib_masked_write(chg, TYPE_C_MODE_CFG_REG,
1639 EN_TRY_SNK_BIT, EN_TRY_SNK_BIT);
1640 if (rc < 0) {
1641 dev_err(chg->dev,
1642 "Couldn't enable try.snk rc=%d\n", rc);
1643 return rc;
1644 }
1645
Ashay Jaiswald5022b62018-05-27 19:21:11 +05301646 /* Keep VCONN in h/w controlled mode for PMI632 */
1647 if (chg->smb_version != PMI632_SUBTYPE) {
1648 /* configure VCONN for software control */
1649 rc = smblib_masked_write(chg, TYPE_C_VCONN_CONTROL_REG,
Harry Yang4b7db0f2017-11-27 10:50:44 -08001650 VCONN_EN_SRC_BIT | VCONN_EN_VALUE_BIT,
1651 VCONN_EN_SRC_BIT);
Ashay Jaiswald5022b62018-05-27 19:21:11 +05301652 if (rc < 0) {
1653 dev_err(chg->dev,
1654 "Couldn't configure VCONN for SW control rc=%d\n",
1655 rc);
1656 return rc;
1657 }
Harry Yang4b7db0f2017-11-27 10:50:44 -08001658 }
1659
1660 return rc;
1661}
1662
1663static int smb5_configure_micro_usb(struct smb_charger *chg)
1664{
1665 int rc;
1666
Ashay Jaiswala9e10912018-02-02 14:03:35 +05301667 rc = smblib_masked_write(chg, TYPE_C_INTERRUPT_EN_CFG_2_REG,
1668 MICRO_USB_STATE_CHANGE_INT_EN_BIT,
1669 MICRO_USB_STATE_CHANGE_INT_EN_BIT);
1670 if (rc < 0) {
1671 dev_err(chg->dev,
1672 "Couldn't configure Type-C interrupts rc=%d\n", rc);
1673 return rc;
1674 }
1675
Harry Yang4b7db0f2017-11-27 10:50:44 -08001676 return rc;
1677}
1678
Ashay Jaiswal0de6fb92018-06-12 17:23:45 +05301679static int smb5_configure_mitigation(struct smb_charger *chg)
1680{
1681 int rc;
1682 u8 chan = 0;
1683
1684 if (!chg->hw_die_temp_mitigation && !chg->hw_connector_mitigation)
1685 return 0;
1686
1687 if (chg->hw_die_temp_mitigation) {
1688 rc = smblib_write(chg, MISC_THERMREG_SRC_CFG_REG,
1689 THERMREG_CONNECTOR_ADC_SRC_EN_BIT
1690 | THERMREG_DIE_ADC_SRC_EN_BIT
1691 | THERMREG_DIE_CMP_SRC_EN_BIT);
1692 if (rc < 0) {
1693 dev_err(chg->dev,
1694 "Couldn't configure THERM_SRC reg rc=%d\n", rc);
1695 return rc;
1696 };
1697
1698 chan = DIE_TEMP_CHANNEL_EN_BIT;
1699 }
1700
1701 if (chg->hw_connector_mitigation)
1702 chan |= CONN_THM_CHANNEL_EN_BIT;
1703
1704 rc = smblib_masked_write(chg, BATIF_ADC_CHANNEL_EN_REG,
1705 CONN_THM_CHANNEL_EN_BIT | DIE_TEMP_CHANNEL_EN_BIT,
1706 chan);
1707 if (rc < 0) {
Ashay Jaiswalb50706d2018-06-28 19:37:31 +05301708 dev_err(chg->dev, "Couldn't enable ADC channel rc=%d\n", rc);
Ashay Jaiswal0de6fb92018-06-12 17:23:45 +05301709 return rc;
1710 }
1711
1712 return 0;
1713}
1714
Harry Yang4b7db0f2017-11-27 10:50:44 -08001715static int smb5_init_hw(struct smb5 *chip)
1716{
1717 struct smb_charger *chg = &chip->chg;
Ashay Jaiswala9e10912018-02-02 14:03:35 +05301718 int rc, type = 0;
1719 u8 val = 0;
Harry Yang4b7db0f2017-11-27 10:50:44 -08001720
1721 if (chip->dt.no_battery)
1722 chg->fake_capacity = 50;
1723
1724 if (chip->dt.batt_profile_fcc_ua < 0)
1725 smblib_get_charge_param(chg, &chg->param.fcc,
1726 &chg->batt_profile_fcc_ua);
1727
1728 if (chip->dt.batt_profile_fv_uv < 0)
1729 smblib_get_charge_param(chg, &chg->param.fv,
1730 &chg->batt_profile_fv_uv);
1731
1732 smblib_get_charge_param(chg, &chg->param.usb_icl,
1733 &chg->default_icl_ua);
Ashay Jaiswale0b3c472018-06-20 23:39:41 +05301734 smblib_get_charge_param(chg, &chg->param.aicl_5v_threshold,
1735 &chg->default_aicl_5v_threshold_mv);
1736 chg->aicl_5v_threshold_mv = chg->default_aicl_5v_threshold_mv;
1737 smblib_get_charge_param(chg, &chg->param.aicl_cont_threshold,
1738 &chg->default_aicl_cont_threshold_mv);
1739 chg->aicl_cont_threshold_mv = chg->default_aicl_cont_threshold_mv;
Ashay Jaiswala9e10912018-02-02 14:03:35 +05301740
1741 /* Use SW based VBUS control, disable HW autonomous mode */
Ashay Jaiswala9e10912018-02-02 14:03:35 +05301742 rc = smblib_masked_write(chg, USBIN_OPTIONS_1_CFG_REG,
1743 HVDCP_AUTH_ALG_EN_CFG_BIT | HVDCP_AUTONOMOUS_MODE_EN_CFG_BIT,
1744 HVDCP_AUTH_ALG_EN_CFG_BIT);
1745 if (rc < 0) {
1746 dev_err(chg->dev, "Couldn't configure HVDCP rc=%d\n", rc);
1747 return rc;
1748 }
1749
1750 /*
1751 * PMI632 can have the connector type defined by a dedicated register
1752 * TYPEC_MICRO_USB_MODE_REG or by a common TYPEC_U_USB_CFG_REG.
1753 */
1754 if (chg->smb_version == PMI632_SUBTYPE) {
1755 rc = smblib_read(chg, TYPEC_MICRO_USB_MODE_REG, &val);
1756 if (rc < 0) {
1757 dev_err(chg->dev, "Couldn't read USB mode rc=%d\n", rc);
1758 return rc;
1759 }
1760 type = !!(val & MICRO_USB_MODE_ONLY_BIT);
1761 }
1762
1763 /*
1764 * If TYPEC_MICRO_USB_MODE_REG is not set and for all non-PMI632
1765 * check the connector type using TYPEC_U_USB_CFG_REG.
1766 */
1767 if (!type) {
1768 rc = smblib_read(chg, TYPEC_U_USB_CFG_REG, &val);
1769 if (rc < 0) {
1770 dev_err(chg->dev, "Couldn't read U_USB config rc=%d\n",
1771 rc);
1772 return rc;
1773 }
1774
1775 type = !!(val & EN_MICRO_USB_MODE_BIT);
1776 }
1777
Ashay Jaiswala9e10912018-02-02 14:03:35 +05301778 pr_debug("Connector type=%s\n", type ? "Micro USB" : "TypeC");
1779
Harry Yang6afaea22018-03-26 19:11:07 -07001780 if (type) {
1781 chg->connector_type = POWER_SUPPLY_CONNECTOR_MICRO_USB;
Harry Yang6afaea22018-03-26 19:11:07 -07001782 rc = smb5_configure_micro_usb(chg);
1783 } else {
1784 chg->connector_type = POWER_SUPPLY_CONNECTOR_TYPEC;
1785 rc = smb5_configure_typec(chg);
1786 }
1787 if (rc < 0) {
1788 dev_err(chg->dev,
1789 "Couldn't configure TypeC/micro-USB mode rc=%d\n", rc);
1790 return rc;
1791 }
1792
Ashay Jaiswal09feab82018-02-12 12:33:18 +05301793 /*
1794 * PMI632 based hw init:
Ashay Jaiswal6f70a512018-05-11 17:25:58 +05301795 * - Enable STAT pin function on SMB_EN
Ashay Jaiswalc96380de2018-05-16 12:02:36 +05301796 * - Rerun APSD to ensure proper charger detection if device
1797 * boots with charger connected.
Ashay Jaiswal09feab82018-02-12 12:33:18 +05301798 * - Initialize flash module for PMI632
1799 */
Ashay Jaiswalc96380de2018-05-16 12:02:36 +05301800 if (chg->smb_version == PMI632_SUBTYPE) {
Ashay Jaiswal6f70a512018-05-11 17:25:58 +05301801 rc = smblib_masked_write(chg, MISC_SMB_EN_CMD_REG,
1802 EN_STAT_CMD_BIT, EN_STAT_CMD_BIT);
1803 if (rc < 0) {
1804 dev_err(chg->dev, "Couldn't configure SMB_EN rc=%d\n",
1805 rc);
1806 return rc;
1807 }
1808
Ashay Jaiswal09feab82018-02-12 12:33:18 +05301809 schgm_flash_init(chg);
Ashay Jaiswalc96380de2018-05-16 12:02:36 +05301810 smblib_rerun_apsd_if_required(chg);
1811 }
Ashay Jaiswal09feab82018-02-12 12:33:18 +05301812
Ashay Jaiswalcbdf2e82018-05-27 23:59:01 +05301813 /* clear the ICL override if it is set */
1814 rc = smblib_icl_override(chg, false);
1815 if (rc < 0) {
1816 pr_err("Couldn't disable ICL override rc=%d\n", rc);
1817 return rc;
1818 }
1819
Ashay Jaiswalb2b06fe2018-06-07 18:35:21 +05301820 /* set OTG current limit */
1821 rc = smblib_set_charge_param(chg, &chg->param.otg_cl, chg->otg_cl_ua);
1822 if (rc < 0) {
1823 pr_err("Couldn't set otg current limit rc=%d\n", rc);
1824 return rc;
1825 }
1826
Ashay Jaiswal0de6fb92018-06-12 17:23:45 +05301827 /* configure temperature mitigation */
1828 rc = smb5_configure_mitigation(chg);
1829 if (rc < 0) {
1830 dev_err(chg->dev, "Couldn't configure mitigation rc=%d\n", rc);
1831 return rc;
1832 }
1833
Harry Yang4b7db0f2017-11-27 10:50:44 -08001834 /* vote 0mA on usb_icl for non battery platforms */
1835 vote(chg->usb_icl_votable,
1836 DEFAULT_VOTER, chip->dt.no_battery, 0);
1837 vote(chg->dc_suspend_votable,
1838 DEFAULT_VOTER, chip->dt.no_battery, 0);
1839 vote(chg->fcc_votable, HW_LIMIT_VOTER,
1840 chip->dt.batt_profile_fcc_ua > 0, chip->dt.batt_profile_fcc_ua);
1841 vote(chg->fv_votable, HW_LIMIT_VOTER,
1842 chip->dt.batt_profile_fv_uv > 0, chip->dt.batt_profile_fv_uv);
1843 vote(chg->fcc_votable,
Ashay Jaiswala9e10912018-02-02 14:03:35 +05301844 BATT_PROFILE_VOTER, chg->batt_profile_fcc_ua > 0,
1845 chg->batt_profile_fcc_ua);
Harry Yang4b7db0f2017-11-27 10:50:44 -08001846 vote(chg->fv_votable,
Ashay Jaiswala9e10912018-02-02 14:03:35 +05301847 BATT_PROFILE_VOTER, chg->batt_profile_fv_uv > 0,
1848 chg->batt_profile_fv_uv);
Ashay Jaiswala9e10912018-02-02 14:03:35 +05301849
1850 /* Some h/w limit maximum supported ICL */
1851 vote(chg->usb_icl_votable, HW_LIMIT_VOTER,
1852 chg->hw_max_icl_ua > 0, chg->hw_max_icl_ua);
Harry Yang4b7db0f2017-11-27 10:50:44 -08001853
1854 /*
1855 * AICL configuration:
Ashay Jaiswalc96380de2018-05-16 12:02:36 +05301856 * AICL ADC disable
Harry Yang4b7db0f2017-11-27 10:50:44 -08001857 */
Ashay Jaiswalc96380de2018-05-16 12:02:36 +05301858 if (chg->smb_version != PMI632_SUBTYPE) {
1859 rc = smblib_masked_write(chg, USBIN_AICL_OPTIONS_CFG_REG,
Harry Yang4b7db0f2017-11-27 10:50:44 -08001860 USBIN_AICL_ADC_EN_BIT, 0);
Ashay Jaiswalc96380de2018-05-16 12:02:36 +05301861 if (rc < 0) {
1862 dev_err(chg->dev, "Couldn't config AICL rc=%d\n", rc);
1863 return rc;
1864 }
Harry Yang4b7db0f2017-11-27 10:50:44 -08001865 }
1866
1867 /* enable the charging path */
1868 rc = vote(chg->chg_disable_votable, DEFAULT_VOTER, false, 0);
1869 if (rc < 0) {
1870 dev_err(chg->dev, "Couldn't enable charging rc=%d\n", rc);
1871 return rc;
1872 }
1873
Harry Yang4b7db0f2017-11-27 10:50:44 -08001874 /* configure VBUS for software control */
1875 rc = smblib_masked_write(chg, DCDC_OTG_CFG_REG, OTG_EN_SRC_CFG_BIT, 0);
1876 if (rc < 0) {
1877 dev_err(chg->dev,
1878 "Couldn't configure VBUS for SW control rc=%d\n", rc);
1879 return rc;
1880 }
1881
Ashay Jaiswala55b7ed2018-03-23 17:23:48 +05301882 /*
1883 * configure the one time watchdong periodic interval and
1884 * disable "watchdog bite disable charging".
1885 */
Harry Yang4b7db0f2017-11-27 10:50:44 -08001886 val = (ilog2(chip->dt.wd_bark_time / 16) << BARK_WDOG_TIMEOUT_SHIFT)
1887 & BARK_WDOG_TIMEOUT_MASK;
1888 val |= BITE_WDOG_TIMEOUT_8S;
1889 rc = smblib_masked_write(chg, SNARL_BARK_BITE_WD_CFG_REG,
1890 BITE_WDOG_DISABLE_CHARGING_CFG_BIT |
1891 BARK_WDOG_TIMEOUT_MASK | BITE_WDOG_TIMEOUT_MASK,
1892 val);
1893 if (rc < 0) {
1894 pr_err("Couldn't configue WD config rc=%d\n", rc);
1895 return rc;
1896 }
1897
Harry Yang4b7db0f2017-11-27 10:50:44 -08001898 /* configure float charger options */
1899 switch (chip->dt.float_option) {
1900 case FLOAT_DCP:
1901 rc = smblib_masked_write(chg, USBIN_OPTIONS_2_CFG_REG,
1902 FLOAT_OPTIONS_MASK, 0);
1903 break;
1904 case FLOAT_SDP:
1905 rc = smblib_masked_write(chg, USBIN_OPTIONS_2_CFG_REG,
1906 FLOAT_OPTIONS_MASK, FORCE_FLOAT_SDP_CFG_BIT);
1907 break;
1908 case DISABLE_CHARGING:
1909 rc = smblib_masked_write(chg, USBIN_OPTIONS_2_CFG_REG,
1910 FLOAT_OPTIONS_MASK, FLOAT_DIS_CHGING_CFG_BIT);
1911 break;
1912 case SUSPEND_INPUT:
1913 rc = smblib_masked_write(chg, USBIN_OPTIONS_2_CFG_REG,
1914 FLOAT_OPTIONS_MASK, SUSPEND_FLOAT_CFG_BIT);
1915 break;
1916 default:
1917 rc = 0;
1918 break;
1919 }
1920
1921 if (rc < 0) {
1922 dev_err(chg->dev, "Couldn't configure float charger options rc=%d\n",
1923 rc);
1924 return rc;
1925 }
1926
1927 rc = smblib_read(chg, USBIN_OPTIONS_2_CFG_REG, &chg->float_cfg);
1928 if (rc < 0) {
1929 dev_err(chg->dev, "Couldn't read float charger options rc=%d\n",
1930 rc);
1931 return rc;
1932 }
1933
1934 switch (chip->dt.chg_inhibit_thr_mv) {
1935 case 50:
1936 rc = smblib_masked_write(chg, CHARGE_INHIBIT_THRESHOLD_CFG_REG,
1937 CHARGE_INHIBIT_THRESHOLD_MASK,
1938 INHIBIT_ANALOG_VFLT_MINUS_50MV);
1939 break;
1940 case 100:
1941 rc = smblib_masked_write(chg, CHARGE_INHIBIT_THRESHOLD_CFG_REG,
1942 CHARGE_INHIBIT_THRESHOLD_MASK,
1943 INHIBIT_ANALOG_VFLT_MINUS_100MV);
1944 break;
1945 case 200:
1946 rc = smblib_masked_write(chg, CHARGE_INHIBIT_THRESHOLD_CFG_REG,
1947 CHARGE_INHIBIT_THRESHOLD_MASK,
1948 INHIBIT_ANALOG_VFLT_MINUS_200MV);
1949 break;
1950 case 300:
1951 rc = smblib_masked_write(chg, CHARGE_INHIBIT_THRESHOLD_CFG_REG,
1952 CHARGE_INHIBIT_THRESHOLD_MASK,
1953 INHIBIT_ANALOG_VFLT_MINUS_300MV);
1954 break;
1955 case 0:
1956 rc = smblib_masked_write(chg, CHGR_CFG2_REG,
1957 CHARGER_INHIBIT_BIT, 0);
1958 default:
1959 break;
1960 }
1961
1962 if (rc < 0) {
1963 dev_err(chg->dev, "Couldn't configure charge inhibit threshold rc=%d\n",
1964 rc);
1965 return rc;
1966 }
1967
Anirudh Ghayal1380d312018-02-23 00:01:43 +05301968 rc = smblib_masked_write(chg, CHGR_CFG2_REG, RECHG_MASK,
1969 (chip->dt.auto_recharge_vbat_mv != -EINVAL) ?
1970 VBAT_BASED_RECHG_BIT : 0);
Harry Yang4b7db0f2017-11-27 10:50:44 -08001971 if (rc < 0) {
Anirudh Ghayal1380d312018-02-23 00:01:43 +05301972 dev_err(chg->dev, "Couldn't configure VBAT-rechg CHG_CFG2_REG rc=%d\n",
Harry Yang4b7db0f2017-11-27 10:50:44 -08001973 rc);
1974 return rc;
1975 }
1976
Anirudh Ghayal1380d312018-02-23 00:01:43 +05301977 /* program the auto-recharge VBAT threshold */
1978 if (chip->dt.auto_recharge_vbat_mv != -EINVAL) {
1979 u32 temp = VBAT_TO_VRAW_ADC(chip->dt.auto_recharge_vbat_mv);
1980
1981 temp = ((temp & 0xFF00) >> 8) | ((temp & 0xFF) << 8);
1982 rc = smblib_batch_write(chg,
1983 CHGR_ADC_RECHARGE_THRESHOLD_MSB_REG, (u8 *)&temp, 2);
1984 if (rc < 0) {
1985 dev_err(chg->dev, "Couldn't configure ADC_RECHARGE_THRESHOLD REG rc=%d\n",
1986 rc);
1987 return rc;
1988 }
1989 /* Program the sample count for VBAT based recharge to 3 */
1990 rc = smblib_masked_write(chg, CHGR_NO_SAMPLE_TERM_RCHG_CFG_REG,
1991 NO_OF_SAMPLE_FOR_RCHG,
1992 2 << NO_OF_SAMPLE_FOR_RCHG_SHIFT);
1993 if (rc < 0) {
1994 dev_err(chg->dev, "Couldn't configure CHGR_NO_SAMPLE_FOR_TERM_RCHG_CFG rc=%d\n",
1995 rc);
1996 return rc;
1997 }
1998 }
1999
2000 rc = smblib_masked_write(chg, CHGR_CFG2_REG, RECHG_MASK,
2001 (chip->dt.auto_recharge_soc != -EINVAL) ?
2002 SOC_BASED_RECHG_BIT : VBAT_BASED_RECHG_BIT);
2003 if (rc < 0) {
2004 dev_err(chg->dev, "Couldn't configure SOC-rechg CHG_CFG2_REG rc=%d\n",
2005 rc);
2006 return rc;
2007 }
2008
2009 /* program the auto-recharge threshold */
2010 if (chip->dt.auto_recharge_soc != -EINVAL) {
2011 rc = smblib_write(chg, CHARGE_RCHG_SOC_THRESHOLD_CFG_REG,
2012 (chip->dt.auto_recharge_soc * 255) / 100);
2013 if (rc < 0) {
2014 dev_err(chg->dev, "Couldn't configure CHG_RCHG_SOC_REG rc=%d\n",
2015 rc);
2016 return rc;
2017 }
2018 /* Program the sample count for SOC based recharge to 1 */
2019 rc = smblib_masked_write(chg, CHGR_NO_SAMPLE_TERM_RCHG_CFG_REG,
2020 NO_OF_SAMPLE_FOR_RCHG, 0);
2021 if (rc < 0) {
2022 dev_err(chg->dev, "Couldn't configure CHGR_NO_SAMPLE_FOR_TERM_RCHG_CFG rc=%d\n",
2023 rc);
2024 return rc;
2025 }
2026 }
2027
Harry Yang4b7db0f2017-11-27 10:50:44 -08002028 if (chg->sw_jeita_enabled) {
2029 rc = smblib_disable_hw_jeita(chg, true);
2030 if (rc < 0) {
2031 dev_err(chg->dev, "Couldn't set hw jeita rc=%d\n", rc);
2032 return rc;
2033 }
2034 }
2035
Ashay Jaiswala55b7ed2018-03-23 17:23:48 +05302036 rc = smblib_configure_wdog(chg,
2037 chg->step_chg_enabled || chg->sw_jeita_enabled);
2038 if (rc < 0) {
2039 dev_err(chg->dev, "Couldn't configure watchdog rc=%d\n",
2040 rc);
2041 return rc;
2042 }
2043
Ashay Jaiswal0de6fb92018-06-12 17:23:45 +05302044 if (chg->connector_pull_up != -EINVAL) {
2045 rc = smb5_configure_internal_pull(chg, CONN_THERM,
2046 get_valid_pullup(chg->connector_pull_up));
2047 if (rc < 0) {
2048 dev_err(chg->dev,
2049 "Couldn't configure CONN_THERM pull-up rc=%d\n",
2050 rc);
2051 return rc;
2052 }
2053 }
2054
Harry Yang4b7db0f2017-11-27 10:50:44 -08002055 return rc;
2056}
2057
2058static int smb5_post_init(struct smb5 *chip)
2059{
2060 struct smb_charger *chg = &chip->chg;
2061 union power_supply_propval pval;
2062 int rc;
2063
2064 /*
2065 * In case the usb path is suspended, we would have missed disabling
2066 * the icl change interrupt because the interrupt could have been
2067 * not requested
2068 */
2069 rerun_election(chg->usb_icl_votable);
2070
2071 /* configure power role for dual-role */
2072 pval.intval = POWER_SUPPLY_TYPEC_PR_DUAL;
2073 rc = smblib_set_prop_typec_power_role(chg, &pval);
2074 if (rc < 0) {
Ashay Jaiswala9e10912018-02-02 14:03:35 +05302075 dev_err(chg->dev, "Couldn't configure DRP role rc=%d\n",
2076 rc);
Harry Yang4b7db0f2017-11-27 10:50:44 -08002077 return rc;
2078 }
2079
2080 rerun_election(chg->usb_irq_enable_votable);
2081
2082 return 0;
2083}
2084
2085/****************************
2086 * DETERMINE INITIAL STATUS *
2087 ****************************/
2088
2089static int smb5_determine_initial_status(struct smb5 *chip)
2090{
2091 struct smb_irq_data irq_data = {chip, "determine-initial-status"};
2092 struct smb_charger *chg = &chip->chg;
Harry Yang6afaea22018-03-26 19:11:07 -07002093 union power_supply_propval val;
2094 int rc;
2095
2096 rc = smblib_get_prop_usb_present(chg, &val);
2097 if (rc < 0) {
2098 pr_err("Couldn't get usb present rc=%d\n", rc);
2099 return rc;
2100 }
2101 chg->early_usb_attach = val.intval;
Harry Yang4b7db0f2017-11-27 10:50:44 -08002102
2103 if (chg->bms_psy)
2104 smblib_suspend_on_debug_battery(chg);
Ashay Jaiswala9e10912018-02-02 14:03:35 +05302105
Harry Yang4b7db0f2017-11-27 10:50:44 -08002106 usb_plugin_irq_handler(0, &irq_data);
Harry Yang6afaea22018-03-26 19:11:07 -07002107 typec_attach_detach_irq_handler(0, &irq_data);
Harry Yang4b7db0f2017-11-27 10:50:44 -08002108 typec_state_change_irq_handler(0, &irq_data);
2109 usb_source_change_irq_handler(0, &irq_data);
2110 chg_state_change_irq_handler(0, &irq_data);
2111 icl_change_irq_handler(0, &irq_data);
2112 batt_temp_changed_irq_handler(0, &irq_data);
2113 wdog_bark_irq_handler(0, &irq_data);
Ashay Jaiswala9e10912018-02-02 14:03:35 +05302114 typec_or_rid_detection_change_irq_handler(0, &irq_data);
Harry Yang4b7db0f2017-11-27 10:50:44 -08002115
2116 return 0;
2117}
2118
2119/**************************
2120 * INTERRUPT REGISTRATION *
2121 **************************/
2122
2123static struct smb_irq_info smb5_irqs[] = {
2124 /* CHARGER IRQs */
2125 [CHGR_ERROR_IRQ] = {
2126 .name = "chgr-error",
2127 .handler = default_irq_handler,
2128 },
2129 [CHG_STATE_CHANGE_IRQ] = {
2130 .name = "chg-state-change",
2131 .handler = chg_state_change_irq_handler,
Ashay Jaiswal48015c32018-03-07 18:25:43 +05302132 .wake = true,
Harry Yang4b7db0f2017-11-27 10:50:44 -08002133 },
2134 [STEP_CHG_STATE_CHANGE_IRQ] = {
2135 .name = "step-chg-state-change",
Harry Yang4b7db0f2017-11-27 10:50:44 -08002136 },
2137 [STEP_CHG_SOC_UPDATE_FAIL_IRQ] = {
2138 .name = "step-chg-soc-update-fail",
Harry Yang4b7db0f2017-11-27 10:50:44 -08002139 },
2140 [STEP_CHG_SOC_UPDATE_REQ_IRQ] = {
2141 .name = "step-chg-soc-update-req",
Harry Yang4b7db0f2017-11-27 10:50:44 -08002142 },
2143 [FG_FVCAL_QUALIFIED_IRQ] = {
2144 .name = "fg-fvcal-qualified",
Harry Yang4b7db0f2017-11-27 10:50:44 -08002145 },
2146 [VPH_ALARM_IRQ] = {
2147 .name = "vph-alarm",
Harry Yang4b7db0f2017-11-27 10:50:44 -08002148 },
2149 [VPH_DROP_PRECHG_IRQ] = {
2150 .name = "vph-drop-prechg",
Harry Yang4b7db0f2017-11-27 10:50:44 -08002151 },
2152 /* DCDC IRQs */
2153 [OTG_FAIL_IRQ] = {
2154 .name = "otg-fail",
2155 .handler = default_irq_handler,
2156 },
2157 [OTG_OC_DISABLE_SW_IRQ] = {
2158 .name = "otg-oc-disable-sw",
Harry Yang4b7db0f2017-11-27 10:50:44 -08002159 },
2160 [OTG_OC_HICCUP_IRQ] = {
2161 .name = "otg-oc-hiccup",
Harry Yang4b7db0f2017-11-27 10:50:44 -08002162 },
2163 [BSM_ACTIVE_IRQ] = {
2164 .name = "bsm-active",
Harry Yang4b7db0f2017-11-27 10:50:44 -08002165 },
2166 [HIGH_DUTY_CYCLE_IRQ] = {
2167 .name = "high-duty-cycle",
2168 .handler = high_duty_cycle_irq_handler,
Ashay Jaiswal48015c32018-03-07 18:25:43 +05302169 .wake = true,
Harry Yang4b7db0f2017-11-27 10:50:44 -08002170 },
2171 [INPUT_CURRENT_LIMITING_IRQ] = {
2172 .name = "input-current-limiting",
2173 .handler = default_irq_handler,
2174 },
2175 [CONCURRENT_MODE_DISABLE_IRQ] = {
2176 .name = "concurrent-mode-disable",
Harry Yang4b7db0f2017-11-27 10:50:44 -08002177 },
2178 [SWITCHER_POWER_OK_IRQ] = {
2179 .name = "switcher-power-ok",
2180 .handler = switcher_power_ok_irq_handler,
2181 },
2182 /* BATTERY IRQs */
2183 [BAT_TEMP_IRQ] = {
2184 .name = "bat-temp",
2185 .handler = batt_temp_changed_irq_handler,
Ashay Jaiswal48015c32018-03-07 18:25:43 +05302186 .wake = true,
Harry Yang4b7db0f2017-11-27 10:50:44 -08002187 },
2188 [ALL_CHNL_CONV_DONE_IRQ] = {
2189 .name = "all-chnl-conv-done",
Harry Yang4b7db0f2017-11-27 10:50:44 -08002190 },
2191 [BAT_OV_IRQ] = {
2192 .name = "bat-ov",
2193 .handler = batt_psy_changed_irq_handler,
2194 },
2195 [BAT_LOW_IRQ] = {
2196 .name = "bat-low",
2197 .handler = batt_psy_changed_irq_handler,
2198 },
2199 [BAT_THERM_OR_ID_MISSING_IRQ] = {
2200 .name = "bat-therm-or-id-missing",
2201 .handler = batt_psy_changed_irq_handler,
2202 },
2203 [BAT_TERMINAL_MISSING_IRQ] = {
2204 .name = "bat-terminal-missing",
2205 .handler = batt_psy_changed_irq_handler,
2206 },
2207 [BUCK_OC_IRQ] = {
2208 .name = "buck-oc",
Harry Yang4b7db0f2017-11-27 10:50:44 -08002209 },
2210 [VPH_OV_IRQ] = {
2211 .name = "vph-ov",
Harry Yang4b7db0f2017-11-27 10:50:44 -08002212 },
2213 /* USB INPUT IRQs */
2214 [USBIN_COLLAPSE_IRQ] = {
2215 .name = "usbin-collapse",
2216 .handler = default_irq_handler,
2217 },
2218 [USBIN_VASHDN_IRQ] = {
2219 .name = "usbin-vashdn",
2220 .handler = default_irq_handler,
2221 },
2222 [USBIN_UV_IRQ] = {
2223 .name = "usbin-uv",
2224 .handler = usbin_uv_irq_handler,
Ashay Jaiswale0b3c472018-06-20 23:39:41 +05302225 .wake = true,
2226 .storm_data = {true, 3000, 5},
Harry Yang4b7db0f2017-11-27 10:50:44 -08002227 },
2228 [USBIN_OV_IRQ] = {
2229 .name = "usbin-ov",
2230 .handler = default_irq_handler,
2231 },
2232 [USBIN_PLUGIN_IRQ] = {
2233 .name = "usbin-plugin",
2234 .handler = usb_plugin_irq_handler,
Ashay Jaiswal48015c32018-03-07 18:25:43 +05302235 .wake = true,
Harry Yang4b7db0f2017-11-27 10:50:44 -08002236 },
2237 [USBIN_REVI_CHANGE_IRQ] = {
2238 .name = "usbin-revi-change",
Harry Yang4b7db0f2017-11-27 10:50:44 -08002239 },
2240 [USBIN_SRC_CHANGE_IRQ] = {
2241 .name = "usbin-src-change",
2242 .handler = usb_source_change_irq_handler,
Ashay Jaiswal48015c32018-03-07 18:25:43 +05302243 .wake = true,
Harry Yang4b7db0f2017-11-27 10:50:44 -08002244 },
2245 [USBIN_ICL_CHANGE_IRQ] = {
2246 .name = "usbin-icl-change",
2247 .handler = icl_change_irq_handler,
Ashay Jaiswal48015c32018-03-07 18:25:43 +05302248 .wake = true,
Harry Yang4b7db0f2017-11-27 10:50:44 -08002249 },
2250 /* DC INPUT IRQs */
2251 [DCIN_VASHDN_IRQ] = {
2252 .name = "dcin-vashdn",
Harry Yang4b7db0f2017-11-27 10:50:44 -08002253 },
2254 [DCIN_UV_IRQ] = {
2255 .name = "dcin-uv",
2256 .handler = default_irq_handler,
2257 },
2258 [DCIN_OV_IRQ] = {
2259 .name = "dcin-ov",
2260 .handler = default_irq_handler,
2261 },
2262 [DCIN_PLUGIN_IRQ] = {
2263 .name = "dcin-plugin",
2264 .handler = dc_plugin_irq_handler,
2265 .wake = true,
2266 },
2267 [DCIN_REVI_IRQ] = {
2268 .name = "dcin-revi",
Harry Yang4b7db0f2017-11-27 10:50:44 -08002269 },
2270 [DCIN_PON_IRQ] = {
2271 .name = "dcin-pon",
2272 .handler = default_irq_handler,
2273 },
2274 [DCIN_EN_IRQ] = {
2275 .name = "dcin-en",
2276 .handler = default_irq_handler,
2277 },
2278 /* TYPEC IRQs */
2279 [TYPEC_OR_RID_DETECTION_CHANGE_IRQ] = {
2280 .name = "typec-or-rid-detect-change",
Ashay Jaiswala9e10912018-02-02 14:03:35 +05302281 .handler = typec_or_rid_detection_change_irq_handler,
Ashay Jaiswal48015c32018-03-07 18:25:43 +05302282 .wake = true,
Harry Yang4b7db0f2017-11-27 10:50:44 -08002283 },
2284 [TYPEC_VPD_DETECT_IRQ] = {
2285 .name = "typec-vpd-detect",
Harry Yang4b7db0f2017-11-27 10:50:44 -08002286 },
2287 [TYPEC_CC_STATE_CHANGE_IRQ] = {
2288 .name = "typec-cc-state-change",
2289 .handler = typec_state_change_irq_handler,
Ashay Jaiswal48015c32018-03-07 18:25:43 +05302290 .wake = true,
Harry Yang4b7db0f2017-11-27 10:50:44 -08002291 },
2292 [TYPEC_VCONN_OC_IRQ] = {
2293 .name = "typec-vconn-oc",
2294 .handler = default_irq_handler,
2295 },
2296 [TYPEC_VBUS_CHANGE_IRQ] = {
2297 .name = "typec-vbus-change",
Harry Yang4b7db0f2017-11-27 10:50:44 -08002298 },
2299 [TYPEC_ATTACH_DETACH_IRQ] = {
2300 .name = "typec-attach-detach",
Harry Yang6afaea22018-03-26 19:11:07 -07002301 .handler = typec_attach_detach_irq_handler,
Harry Yang4b7db0f2017-11-27 10:50:44 -08002302 },
2303 [TYPEC_LEGACY_CABLE_DETECT_IRQ] = {
2304 .name = "typec-legacy-cable-detect",
2305 .handler = default_irq_handler,
2306 },
2307 [TYPEC_TRY_SNK_SRC_DETECT_IRQ] = {
2308 .name = "typec-try-snk-src-detect",
Harry Yang4b7db0f2017-11-27 10:50:44 -08002309 },
2310 /* MISCELLANEOUS IRQs */
2311 [WDOG_SNARL_IRQ] = {
2312 .name = "wdog-snarl",
Harry Yang4b7db0f2017-11-27 10:50:44 -08002313 },
2314 [WDOG_BARK_IRQ] = {
2315 .name = "wdog-bark",
2316 .handler = wdog_bark_irq_handler,
Ashay Jaiswala55b7ed2018-03-23 17:23:48 +05302317 .wake = true,
Harry Yang4b7db0f2017-11-27 10:50:44 -08002318 },
2319 [AICL_FAIL_IRQ] = {
2320 .name = "aicl-fail",
Harry Yang4b7db0f2017-11-27 10:50:44 -08002321 },
2322 [AICL_DONE_IRQ] = {
2323 .name = "aicl-done",
2324 .handler = default_irq_handler,
2325 },
2326 [SMB_EN_IRQ] = {
2327 .name = "smb-en",
Harry Yang4b7db0f2017-11-27 10:50:44 -08002328 },
2329 [IMP_TRIGGER_IRQ] = {
2330 .name = "imp-trigger",
Harry Yang4b7db0f2017-11-27 10:50:44 -08002331 },
2332 [TEMP_CHANGE_IRQ] = {
2333 .name = "temp-change",
Harry Yang4b7db0f2017-11-27 10:50:44 -08002334 },
2335 [TEMP_CHANGE_SMB_IRQ] = {
2336 .name = "temp-change-smb",
Harry Yang4b7db0f2017-11-27 10:50:44 -08002337 },
Ashay Jaiswal09feab82018-02-12 12:33:18 +05302338 /* FLASH */
2339 [VREG_OK_IRQ] = {
2340 .name = "vreg-ok",
Ashay Jaiswal09feab82018-02-12 12:33:18 +05302341 },
2342 [ILIM_S2_IRQ] = {
2343 .name = "ilim2-s2",
2344 .handler = schgm_flash_ilim2_irq_handler,
2345 },
2346 [ILIM_S1_IRQ] = {
2347 .name = "ilim1-s1",
Ashay Jaiswal09feab82018-02-12 12:33:18 +05302348 },
2349 [VOUT_DOWN_IRQ] = {
2350 .name = "vout-down",
Ashay Jaiswal09feab82018-02-12 12:33:18 +05302351 },
2352 [VOUT_UP_IRQ] = {
2353 .name = "vout-up",
Ashay Jaiswal09feab82018-02-12 12:33:18 +05302354 },
2355 [FLASH_STATE_CHANGE_IRQ] = {
2356 .name = "flash-state-change",
2357 .handler = schgm_flash_state_change_irq_handler,
2358 },
2359 [TORCH_REQ_IRQ] = {
2360 .name = "torch-req",
Ashay Jaiswal09feab82018-02-12 12:33:18 +05302361 },
2362 [FLASH_EN_IRQ] = {
2363 .name = "flash-en",
Ashay Jaiswal09feab82018-02-12 12:33:18 +05302364 },
Harry Yang4b7db0f2017-11-27 10:50:44 -08002365};
2366
2367static int smb5_get_irq_index_byname(const char *irq_name)
2368{
2369 int i;
2370
2371 for (i = 0; i < ARRAY_SIZE(smb5_irqs); i++) {
2372 if (strcmp(smb5_irqs[i].name, irq_name) == 0)
2373 return i;
2374 }
2375
2376 return -ENOENT;
2377}
2378
2379static int smb5_request_interrupt(struct smb5 *chip,
2380 struct device_node *node, const char *irq_name)
2381{
2382 struct smb_charger *chg = &chip->chg;
2383 int rc, irq, irq_index;
2384 struct smb_irq_data *irq_data;
2385
2386 irq = of_irq_get_byname(node, irq_name);
2387 if (irq < 0) {
2388 pr_err("Couldn't get irq %s byname\n", irq_name);
2389 return irq;
2390 }
2391
2392 irq_index = smb5_get_irq_index_byname(irq_name);
2393 if (irq_index < 0) {
2394 pr_err("%s is not a defined irq\n", irq_name);
2395 return irq_index;
2396 }
2397
2398 if (!smb5_irqs[irq_index].handler)
2399 return 0;
2400
2401 irq_data = devm_kzalloc(chg->dev, sizeof(*irq_data), GFP_KERNEL);
2402 if (!irq_data)
2403 return -ENOMEM;
2404
2405 irq_data->parent_data = chip;
2406 irq_data->name = irq_name;
2407 irq_data->storm_data = smb5_irqs[irq_index].storm_data;
2408 mutex_init(&irq_data->storm_data.storm_lock);
2409
2410 rc = devm_request_threaded_irq(chg->dev, irq, NULL,
2411 smb5_irqs[irq_index].handler,
2412 IRQF_ONESHOT, irq_name, irq_data);
2413 if (rc < 0) {
2414 pr_err("Couldn't request irq %d\n", irq);
2415 return rc;
2416 }
2417
2418 smb5_irqs[irq_index].irq = irq;
2419 smb5_irqs[irq_index].irq_data = irq_data;
2420 if (smb5_irqs[irq_index].wake)
2421 enable_irq_wake(irq);
2422
2423 return rc;
2424}
2425
2426static int smb5_request_interrupts(struct smb5 *chip)
2427{
2428 struct smb_charger *chg = &chip->chg;
2429 struct device_node *node = chg->dev->of_node;
2430 struct device_node *child;
2431 int rc = 0;
2432 const char *name;
2433 struct property *prop;
2434
2435 for_each_available_child_of_node(node, child) {
2436 of_property_for_each_string(child, "interrupt-names",
2437 prop, name) {
2438 rc = smb5_request_interrupt(chip, child, name);
2439 if (rc < 0)
2440 return rc;
2441 }
2442 }
2443 if (chg->irq_info[USBIN_ICL_CHANGE_IRQ].irq)
2444 chg->usb_icl_change_irq_enabled = true;
2445
2446 return rc;
2447}
2448
2449static void smb5_free_interrupts(struct smb_charger *chg)
2450{
2451 int i;
2452
2453 for (i = 0; i < ARRAY_SIZE(smb5_irqs); i++) {
2454 if (smb5_irqs[i].irq > 0) {
2455 if (smb5_irqs[i].wake)
2456 disable_irq_wake(smb5_irqs[i].irq);
2457
2458 devm_free_irq(chg->dev, smb5_irqs[i].irq,
2459 smb5_irqs[i].irq_data);
2460 }
2461 }
2462}
2463
2464static void smb5_disable_interrupts(struct smb_charger *chg)
2465{
2466 int i;
2467
2468 for (i = 0; i < ARRAY_SIZE(smb5_irqs); i++) {
2469 if (smb5_irqs[i].irq > 0)
2470 disable_irq(smb5_irqs[i].irq);
2471 }
2472}
2473
2474#if defined(CONFIG_DEBUG_FS)
2475
2476static int force_batt_psy_update_write(void *data, u64 val)
2477{
2478 struct smb_charger *chg = data;
2479
2480 power_supply_changed(chg->batt_psy);
2481 return 0;
2482}
2483DEFINE_SIMPLE_ATTRIBUTE(force_batt_psy_update_ops, NULL,
2484 force_batt_psy_update_write, "0x%02llx\n");
2485
2486static int force_usb_psy_update_write(void *data, u64 val)
2487{
2488 struct smb_charger *chg = data;
2489
2490 power_supply_changed(chg->usb_psy);
2491 return 0;
2492}
2493DEFINE_SIMPLE_ATTRIBUTE(force_usb_psy_update_ops, NULL,
2494 force_usb_psy_update_write, "0x%02llx\n");
2495
2496static int force_dc_psy_update_write(void *data, u64 val)
2497{
2498 struct smb_charger *chg = data;
2499
2500 power_supply_changed(chg->dc_psy);
2501 return 0;
2502}
2503DEFINE_SIMPLE_ATTRIBUTE(force_dc_psy_update_ops, NULL,
2504 force_dc_psy_update_write, "0x%02llx\n");
2505
2506static void smb5_create_debugfs(struct smb5 *chip)
2507{
2508 struct dentry *file;
2509
2510 chip->dfs_root = debugfs_create_dir("charger", NULL);
2511 if (IS_ERR_OR_NULL(chip->dfs_root)) {
2512 pr_err("Couldn't create charger debugfs rc=%ld\n",
2513 (long)chip->dfs_root);
2514 return;
2515 }
2516
2517 file = debugfs_create_file("force_batt_psy_update", 0600,
2518 chip->dfs_root, chip, &force_batt_psy_update_ops);
2519 if (IS_ERR_OR_NULL(file))
2520 pr_err("Couldn't create force_batt_psy_update file rc=%ld\n",
2521 (long)file);
2522
2523 file = debugfs_create_file("force_usb_psy_update", 0600,
2524 chip->dfs_root, chip, &force_usb_psy_update_ops);
2525 if (IS_ERR_OR_NULL(file))
2526 pr_err("Couldn't create force_usb_psy_update file rc=%ld\n",
2527 (long)file);
2528
2529 file = debugfs_create_file("force_dc_psy_update", 0600,
2530 chip->dfs_root, chip, &force_dc_psy_update_ops);
2531 if (IS_ERR_OR_NULL(file))
2532 pr_err("Couldn't create force_dc_psy_update file rc=%ld\n",
2533 (long)file);
2534}
2535
2536#else
2537
2538static void smb5_create_debugfs(struct smb5 *chip)
2539{}
2540
2541#endif
2542
2543static int smb5_show_charger_status(struct smb5 *chip)
2544{
2545 struct smb_charger *chg = &chip->chg;
2546 union power_supply_propval val;
2547 int usb_present, batt_present, batt_health, batt_charge_type;
2548 int rc;
2549
2550 rc = smblib_get_prop_usb_present(chg, &val);
2551 if (rc < 0) {
2552 pr_err("Couldn't get usb present rc=%d\n", rc);
2553 return rc;
2554 }
2555 usb_present = val.intval;
2556
2557 rc = smblib_get_prop_batt_present(chg, &val);
2558 if (rc < 0) {
2559 pr_err("Couldn't get batt present rc=%d\n", rc);
2560 return rc;
2561 }
2562 batt_present = val.intval;
2563
2564 rc = smblib_get_prop_batt_health(chg, &val);
2565 if (rc < 0) {
2566 pr_err("Couldn't get batt health rc=%d\n", rc);
2567 val.intval = POWER_SUPPLY_HEALTH_UNKNOWN;
2568 }
2569 batt_health = val.intval;
2570
2571 rc = smblib_get_prop_batt_charge_type(chg, &val);
2572 if (rc < 0) {
2573 pr_err("Couldn't get batt charge type rc=%d\n", rc);
2574 return rc;
2575 }
2576 batt_charge_type = val.intval;
2577
2578 pr_info("SMB5 status - usb:present=%d type=%d batt:present = %d health = %d charge = %d\n",
2579 usb_present, chg->real_charger_type,
2580 batt_present, batt_health, batt_charge_type);
2581 return rc;
2582}
2583
2584static int smb5_probe(struct platform_device *pdev)
2585{
2586 struct smb5 *chip;
2587 struct smb_charger *chg;
2588 int rc = 0;
2589
2590 chip = devm_kzalloc(&pdev->dev, sizeof(*chip), GFP_KERNEL);
2591 if (!chip)
2592 return -ENOMEM;
2593
2594 chg = &chip->chg;
2595 chg->dev = &pdev->dev;
Harry Yang4b7db0f2017-11-27 10:50:44 -08002596 chg->debug_mask = &__debug_mask;
Harry Yang6afaea22018-03-26 19:11:07 -07002597 chg->pd_disabled = &__pd_disabled;
Harry Yang4b7db0f2017-11-27 10:50:44 -08002598 chg->weak_chg_icl_ua = &__weak_chg_icl_ua;
2599 chg->mode = PARALLEL_MASTER;
2600 chg->irq_info = smb5_irqs;
2601 chg->die_health = -EINVAL;
Ashay Jaiswala9e10912018-02-02 14:03:35 +05302602 chg->otg_present = false;
Anirudh Ghayal75f8f812018-07-09 16:48:47 +05302603 mutex_init(&chg->vadc_lock);
Harry Yang4b7db0f2017-11-27 10:50:44 -08002604
2605 chg->regmap = dev_get_regmap(chg->dev->parent, NULL);
2606 if (!chg->regmap) {
2607 pr_err("parent regmap is missing\n");
2608 return -EINVAL;
2609 }
2610
Ashay Jaiswala9e10912018-02-02 14:03:35 +05302611 rc = smb5_chg_config_init(chip);
2612 if (rc < 0) {
2613 if (rc != -EPROBE_DEFER)
2614 pr_err("Couldn't setup chg_config rc=%d\n", rc);
2615 return rc;
Harry Yang4b7db0f2017-11-27 10:50:44 -08002616 }
2617
Ashay Jaiswalb2b06fe2018-06-07 18:35:21 +05302618 rc = smb5_parse_dt(chip);
2619 if (rc < 0) {
2620 pr_err("Couldn't parse device tree rc=%d\n", rc);
2621 return rc;
2622 }
2623
Harry Yang4b7db0f2017-11-27 10:50:44 -08002624 rc = smblib_init(chg);
2625 if (rc < 0) {
2626 pr_err("Smblib_init failed rc=%d\n", rc);
Ashay Jaiswala9e10912018-02-02 14:03:35 +05302627 return rc;
Harry Yang4b7db0f2017-11-27 10:50:44 -08002628 }
2629
2630 /* set driver data before resources request it */
2631 platform_set_drvdata(pdev, chip);
2632
2633 rc = smb5_init_vbus_regulator(chip);
2634 if (rc < 0) {
2635 pr_err("Couldn't initialize vbus regulator rc=%d\n",
2636 rc);
2637 goto cleanup;
2638 }
2639
2640 rc = smb5_init_vconn_regulator(chip);
2641 if (rc < 0) {
2642 pr_err("Couldn't initialize vconn regulator rc=%d\n",
2643 rc);
2644 goto cleanup;
2645 }
2646
2647 /* extcon registration */
2648 chg->extcon = devm_extcon_dev_allocate(chg->dev, smblib_extcon_cable);
2649 if (IS_ERR(chg->extcon)) {
2650 rc = PTR_ERR(chg->extcon);
2651 dev_err(chg->dev, "failed to allocate extcon device rc=%d\n",
2652 rc);
2653 goto cleanup;
2654 }
2655
2656 rc = devm_extcon_dev_register(chg->dev, chg->extcon);
2657 if (rc < 0) {
2658 dev_err(chg->dev, "failed to register extcon device rc=%d\n",
2659 rc);
2660 goto cleanup;
2661 }
2662
2663 rc = smb5_init_hw(chip);
2664 if (rc < 0) {
2665 pr_err("Couldn't initialize hardware rc=%d\n", rc);
2666 goto cleanup;
2667 }
2668
Ashay Jaiswala9e10912018-02-02 14:03:35 +05302669 if (chg->smb_version == PM855B_SUBTYPE) {
2670 rc = smb5_init_dc_psy(chip);
2671 if (rc < 0) {
2672 pr_err("Couldn't initialize dc psy rc=%d\n", rc);
2673 goto cleanup;
2674 }
Harry Yang4b7db0f2017-11-27 10:50:44 -08002675 }
2676
2677 rc = smb5_init_usb_psy(chip);
2678 if (rc < 0) {
2679 pr_err("Couldn't initialize usb psy rc=%d\n", rc);
2680 goto cleanup;
2681 }
2682
2683 rc = smb5_init_usb_main_psy(chip);
2684 if (rc < 0) {
2685 pr_err("Couldn't initialize usb main psy rc=%d\n", rc);
2686 goto cleanup;
2687 }
2688
2689 rc = smb5_init_usb_port_psy(chip);
2690 if (rc < 0) {
2691 pr_err("Couldn't initialize usb pc_port psy rc=%d\n", rc);
2692 goto cleanup;
2693 }
2694
2695 rc = smb5_init_batt_psy(chip);
2696 if (rc < 0) {
2697 pr_err("Couldn't initialize batt psy rc=%d\n", rc);
2698 goto cleanup;
2699 }
2700
2701 rc = smb5_determine_initial_status(chip);
2702 if (rc < 0) {
2703 pr_err("Couldn't determine initial status rc=%d\n",
2704 rc);
2705 goto cleanup;
2706 }
2707
2708 rc = smb5_request_interrupts(chip);
2709 if (rc < 0) {
2710 pr_err("Couldn't request interrupts rc=%d\n", rc);
2711 goto cleanup;
2712 }
2713
2714 rc = smb5_post_init(chip);
2715 if (rc < 0) {
2716 pr_err("Failed in post init rc=%d\n", rc);
Ashay Jaiswala9e10912018-02-02 14:03:35 +05302717 goto free_irq;
Harry Yang4b7db0f2017-11-27 10:50:44 -08002718 }
2719
2720 smb5_create_debugfs(chip);
2721
2722 rc = smb5_show_charger_status(chip);
2723 if (rc < 0) {
2724 pr_err("Failed in getting charger status rc=%d\n", rc);
Ashay Jaiswala9e10912018-02-02 14:03:35 +05302725 goto free_irq;
Harry Yang4b7db0f2017-11-27 10:50:44 -08002726 }
2727
2728 device_init_wakeup(chg->dev, true);
2729
2730 pr_info("QPNP SMB5 probed successfully\n");
2731
2732 return rc;
2733
Ashay Jaiswala9e10912018-02-02 14:03:35 +05302734free_irq:
Harry Yang4b7db0f2017-11-27 10:50:44 -08002735 smb5_free_interrupts(chg);
Ashay Jaiswala9e10912018-02-02 14:03:35 +05302736cleanup:
Harry Yang4b7db0f2017-11-27 10:50:44 -08002737 smblib_deinit(chg);
2738 platform_set_drvdata(pdev, NULL);
2739
2740 return rc;
2741}
2742
2743static int smb5_remove(struct platform_device *pdev)
2744{
2745 struct smb5 *chip = platform_get_drvdata(pdev);
2746 struct smb_charger *chg = &chip->chg;
2747
Harry Yang6afaea22018-03-26 19:11:07 -07002748 /* force enable APSD */
2749 smblib_masked_write(chg, USBIN_OPTIONS_1_CFG_REG,
2750 BC1P2_SRC_DETECT_BIT, BC1P2_SRC_DETECT_BIT);
2751
Harry Yang4b7db0f2017-11-27 10:50:44 -08002752 smb5_free_interrupts(chg);
2753 smblib_deinit(chg);
2754 platform_set_drvdata(pdev, NULL);
2755 return 0;
2756}
2757
2758static void smb5_shutdown(struct platform_device *pdev)
2759{
2760 struct smb5 *chip = platform_get_drvdata(pdev);
2761 struct smb_charger *chg = &chip->chg;
2762
2763 /* disable all interrupts */
2764 smb5_disable_interrupts(chg);
2765
2766 /* configure power role for UFP */
Ashay Jaiswala9e10912018-02-02 14:03:35 +05302767 if (chg->connector_type == POWER_SUPPLY_CONNECTOR_TYPEC)
Harry Yang4b7db0f2017-11-27 10:50:44 -08002768 smblib_masked_write(chg, TYPE_C_MODE_CFG_REG,
2769 TYPEC_POWER_ROLE_CMD_MASK, EN_SNK_ONLY_BIT);
2770
2771 /* force HVDCP to 5V */
2772 smblib_masked_write(chg, USBIN_OPTIONS_1_CFG_REG,
2773 HVDCP_AUTONOMOUS_MODE_EN_CFG_BIT, 0);
2774 smblib_write(chg, CMD_HVDCP_2_REG, FORCE_5V_BIT);
2775
2776 /* force enable APSD */
2777 smblib_masked_write(chg, USBIN_OPTIONS_1_CFG_REG,
2778 BC1P2_SRC_DETECT_BIT, BC1P2_SRC_DETECT_BIT);
2779}
2780
2781static const struct of_device_id match_table[] = {
2782 { .compatible = "qcom,qpnp-smb5", },
2783 { },
2784};
2785
2786static struct platform_driver smb5_driver = {
2787 .driver = {
2788 .name = "qcom,qpnp-smb5",
2789 .owner = THIS_MODULE,
2790 .of_match_table = match_table,
2791 },
2792 .probe = smb5_probe,
2793 .remove = smb5_remove,
2794 .shutdown = smb5_shutdown,
2795};
2796module_platform_driver(smb5_driver);
2797
2798MODULE_DESCRIPTION("QPNP SMB5 Charger Driver");
2799MODULE_LICENSE("GPL v2");