blob: 2a997ddf60f63a5cf6e9986a2f31d60ad2fa8473 [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{
Ashay Jaiswalb50706d2018-06-28 19:37:31 +0530493 int rc, ret = 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
519 switch (channel) {
520 case USBIN_VOLTAGE:
Ashay Jaiswalb50706d2018-06-28 19:37:31 +0530521 /* Store ADC channel config */
522 rc = smblib_read(chg, BATIF_ADC_CHANNEL_EN_REG, &reg);
523 if (rc < 0) {
524 dev_err(chg->dev,
525 "Couldn't read ADC config rc=%d\n", rc);
526 return rc;
527 }
528
529 /* Disable all ADC channels except IBAT channel */
530 rc = smblib_write(chg, BATIF_ADC_CHANNEL_EN_REG,
531 IBATT_CHANNEL_EN_BIT);
532 if (rc < 0) {
533 dev_err(chg->dev,
534 "Couldn't write ADC config rc=%d\n", rc);
535 return rc;
536 }
537
Ashay Jaiswal20688262018-04-25 11:45:34 +0530538 rc = qpnp_vadc_read(chg->vadc_dev, VADC_USB_IN_V_DIV_16_PM5,
539 &result);
540 if (rc < 0) {
541 pr_err("Failed to read USBIN_V over vadc, rc=%d\n", rc);
Ashay Jaiswalb50706d2018-06-28 19:37:31 +0530542 ret = rc;
543 goto restore;
Ashay Jaiswal20688262018-04-25 11:45:34 +0530544 }
545 val->intval = result.physical;
Ashay Jaiswalb50706d2018-06-28 19:37:31 +0530546
547restore:
548 /* Restore ADC channel config */
549 rc = smblib_write(chg, BATIF_ADC_CHANNEL_EN_REG, reg);
550 if (rc < 0) {
551 dev_err(chg->dev,
552 "Couldn't write ADC config rc=%d\n", rc);
553 return rc;
554 }
555 /* If ADC read failed return ADC error */
556 if (ret < 0)
557 rc = ret;
Ashay Jaiswal20688262018-04-25 11:45:34 +0530558 break;
559 case USBIN_CURRENT:
560 rc = qpnp_vadc_read(chg->vadc_dev, VADC_USB_IN_I_PM5, &result);
561 if (rc < 0) {
562 pr_err("Failed to read USBIN_I over vadc, rc=%d\n", rc);
563 return rc;
564 }
565 val->intval = result.physical;
566 break;
567 default:
568 pr_debug("Invalid channel\n");
569 return -EINVAL;
570 }
571
572 return 0;
573}
574
575
Harry Yang4b7db0f2017-11-27 10:50:44 -0800576/************************
577 * USB PSY REGISTRATION *
578 ************************/
579static enum power_supply_property smb5_usb_props[] = {
580 POWER_SUPPLY_PROP_PRESENT,
581 POWER_SUPPLY_PROP_ONLINE,
582 POWER_SUPPLY_PROP_PD_CURRENT_MAX,
583 POWER_SUPPLY_PROP_CURRENT_MAX,
584 POWER_SUPPLY_PROP_TYPE,
585 POWER_SUPPLY_PROP_TYPEC_MODE,
586 POWER_SUPPLY_PROP_TYPEC_POWER_ROLE,
587 POWER_SUPPLY_PROP_TYPEC_CC_ORIENTATION,
Harry Yang4b7db0f2017-11-27 10:50:44 -0800588 POWER_SUPPLY_PROP_PD_ACTIVE,
589 POWER_SUPPLY_PROP_INPUT_CURRENT_SETTLED,
590 POWER_SUPPLY_PROP_INPUT_CURRENT_NOW,
591 POWER_SUPPLY_PROP_BOOST_CURRENT,
592 POWER_SUPPLY_PROP_PE_START,
593 POWER_SUPPLY_PROP_CTM_CURRENT_MAX,
594 POWER_SUPPLY_PROP_HW_CURRENT_MAX,
595 POWER_SUPPLY_PROP_REAL_TYPE,
596 POWER_SUPPLY_PROP_PR_SWAP,
597 POWER_SUPPLY_PROP_PD_VOLTAGE_MAX,
598 POWER_SUPPLY_PROP_PD_VOLTAGE_MIN,
599 POWER_SUPPLY_PROP_SDP_CURRENT_MAX,
Ashay Jaiswala9e10912018-02-02 14:03:35 +0530600 POWER_SUPPLY_PROP_CONNECTOR_TYPE,
Ashay Jaiswal1f71b412017-10-31 14:33:27 +0530601 POWER_SUPPLY_PROP_VOLTAGE_MAX,
Umang Agrawal9fb865a2018-06-25 16:24:00 +0530602 POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN,
Ashay Jaiswal09feab82018-02-12 12:33:18 +0530603 POWER_SUPPLY_PROP_SCOPE,
Ashay Jaiswal20688262018-04-25 11:45:34 +0530604 POWER_SUPPLY_PROP_VOLTAGE_NOW,
Ashay Jaiswal4d334f42018-04-25 10:58:49 +0530605 POWER_SUPPLY_PROP_HVDCP_OPTI_ALLOWED,
Ashay Jaiswal0de6fb92018-06-12 17:23:45 +0530606 POWER_SUPPLY_PROP_QC_OPTI_DISABLE,
Harry Yang4b7db0f2017-11-27 10:50:44 -0800607};
608
609static int smb5_usb_get_prop(struct power_supply *psy,
610 enum power_supply_property psp,
611 union power_supply_propval *val)
612{
613 struct smb5 *chip = power_supply_get_drvdata(psy);
614 struct smb_charger *chg = &chip->chg;
Ashay Jaiswal09feab82018-02-12 12:33:18 +0530615 union power_supply_propval pval;
Harry Yang4b7db0f2017-11-27 10:50:44 -0800616 int rc = 0;
617
618 switch (psp) {
619 case POWER_SUPPLY_PROP_PRESENT:
620 rc = smblib_get_prop_usb_present(chg, val);
621 break;
622 case POWER_SUPPLY_PROP_ONLINE:
623 rc = smblib_get_prop_usb_online(chg, val);
624 if (!val->intval)
625 break;
626
Ashay Jaiswala9e10912018-02-02 14:03:35 +0530627 if (((chg->typec_mode == POWER_SUPPLY_TYPEC_SOURCE_DEFAULT) ||
628 (chg->connector_type == POWER_SUPPLY_CONNECTOR_MICRO_USB))
629 && (chg->real_charger_type == POWER_SUPPLY_TYPE_USB))
Harry Yang4b7db0f2017-11-27 10:50:44 -0800630 val->intval = 0;
631 else
632 val->intval = 1;
Ashay Jaiswala9e10912018-02-02 14:03:35 +0530633
Harry Yang4b7db0f2017-11-27 10:50:44 -0800634 if (chg->real_charger_type == POWER_SUPPLY_TYPE_UNKNOWN)
635 val->intval = 0;
636 break;
637 case POWER_SUPPLY_PROP_VOLTAGE_MAX:
638 rc = smblib_get_prop_usb_voltage_max(chg, val);
639 break;
Umang Agrawal9fb865a2018-06-25 16:24:00 +0530640 case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN:
641 rc = smblib_get_prop_usb_voltage_max_design(chg, val);
642 break;
Harry Yang4b7db0f2017-11-27 10:50:44 -0800643 case POWER_SUPPLY_PROP_PD_CURRENT_MAX:
644 val->intval = get_client_vote(chg->usb_icl_votable, PD_VOTER);
645 break;
646 case POWER_SUPPLY_PROP_CURRENT_MAX:
647 rc = smblib_get_prop_input_current_settled(chg, val);
648 break;
649 case POWER_SUPPLY_PROP_TYPE:
650 val->intval = POWER_SUPPLY_TYPE_USB_PD;
651 break;
652 case POWER_SUPPLY_PROP_REAL_TYPE:
653 val->intval = chg->real_charger_type;
654 break;
655 case POWER_SUPPLY_PROP_TYPEC_MODE:
Ashay Jaiswala9e10912018-02-02 14:03:35 +0530656 if (chg->connector_type == POWER_SUPPLY_CONNECTOR_MICRO_USB)
Harry Yang4b7db0f2017-11-27 10:50:44 -0800657 val->intval = POWER_SUPPLY_TYPEC_NONE;
658 else
659 val->intval = chg->typec_mode;
660 break;
661 case POWER_SUPPLY_PROP_TYPEC_POWER_ROLE:
Ashay Jaiswala9e10912018-02-02 14:03:35 +0530662 if (chg->connector_type == POWER_SUPPLY_CONNECTOR_MICRO_USB)
Harry Yang4b7db0f2017-11-27 10:50:44 -0800663 val->intval = POWER_SUPPLY_TYPEC_PR_NONE;
664 else
665 rc = smblib_get_prop_typec_power_role(chg, val);
666 break;
667 case POWER_SUPPLY_PROP_TYPEC_CC_ORIENTATION:
Ashay Jaiswala9e10912018-02-02 14:03:35 +0530668 if (chg->connector_type == POWER_SUPPLY_CONNECTOR_MICRO_USB)
Harry Yang4b7db0f2017-11-27 10:50:44 -0800669 val->intval = 0;
670 else
671 rc = smblib_get_prop_typec_cc_orientation(chg, val);
672 break;
Harry Yang4b7db0f2017-11-27 10:50:44 -0800673 case POWER_SUPPLY_PROP_PD_ACTIVE:
674 val->intval = chg->pd_active;
675 break;
676 case POWER_SUPPLY_PROP_INPUT_CURRENT_SETTLED:
677 rc = smblib_get_prop_input_current_settled(chg, val);
678 break;
679 case POWER_SUPPLY_PROP_BOOST_CURRENT:
680 val->intval = chg->boost_current_ua;
681 break;
682 case POWER_SUPPLY_PROP_PD_IN_HARD_RESET:
683 rc = smblib_get_prop_pd_in_hard_reset(chg, val);
684 break;
685 case POWER_SUPPLY_PROP_PD_USB_SUSPEND_SUPPORTED:
686 val->intval = chg->system_suspend_supported;
687 break;
688 case POWER_SUPPLY_PROP_PE_START:
689 rc = smblib_get_pe_start(chg, val);
690 break;
691 case POWER_SUPPLY_PROP_CTM_CURRENT_MAX:
692 val->intval = get_client_vote(chg->usb_icl_votable, CTM_VOTER);
693 break;
694 case POWER_SUPPLY_PROP_HW_CURRENT_MAX:
695 rc = smblib_get_charge_current(chg, &val->intval);
696 break;
697 case POWER_SUPPLY_PROP_PR_SWAP:
698 rc = smblib_get_prop_pr_swap_in_progress(chg, val);
699 break;
700 case POWER_SUPPLY_PROP_PD_VOLTAGE_MAX:
701 val->intval = chg->voltage_max_uv;
702 break;
703 case POWER_SUPPLY_PROP_PD_VOLTAGE_MIN:
704 val->intval = chg->voltage_min_uv;
705 break;
706 case POWER_SUPPLY_PROP_SDP_CURRENT_MAX:
707 val->intval = get_client_vote(chg->usb_icl_votable,
708 USB_PSY_VOTER);
709 break;
Ashay Jaiswala9e10912018-02-02 14:03:35 +0530710 case POWER_SUPPLY_PROP_CONNECTOR_TYPE:
711 val->intval = chg->connector_type;
712 break;
Ashay Jaiswal09feab82018-02-12 12:33:18 +0530713 case POWER_SUPPLY_PROP_SCOPE:
714 val->intval = POWER_SUPPLY_SCOPE_UNKNOWN;
715 rc = smblib_get_prop_usb_present(chg, &pval);
716 if (rc < 0)
717 break;
718 val->intval = pval.intval ? POWER_SUPPLY_SCOPE_DEVICE
719 : chg->otg_present ? POWER_SUPPLY_SCOPE_SYSTEM
720 : POWER_SUPPLY_SCOPE_UNKNOWN;
721 break;
Ashay Jaiswal20688262018-04-25 11:45:34 +0530722 case POWER_SUPPLY_PROP_INPUT_CURRENT_NOW:
723 rc = smblib_get_prop_usb_present(chg, &pval);
724 if (rc < 0 || !pval.intval) {
725 val->intval = 0;
726 return rc;
727 }
728 if (chg->smb_version == PMI632_SUBTYPE)
729 rc = smb5_get_adc_data(chg, USBIN_CURRENT, val);
730 break;
731 case POWER_SUPPLY_PROP_VOLTAGE_NOW:
732 if (chg->smb_version == PMI632_SUBTYPE)
733 rc = smb5_get_adc_data(chg, USBIN_VOLTAGE, val);
734 break;
Ashay Jaiswal4d334f42018-04-25 10:58:49 +0530735 case POWER_SUPPLY_PROP_HVDCP_OPTI_ALLOWED:
736 val->intval = !chg->flash_active;
737 break;
Ashay Jaiswal0de6fb92018-06-12 17:23:45 +0530738 case POWER_SUPPLY_PROP_QC_OPTI_DISABLE:
739 if (chg->hw_die_temp_mitigation)
740 val->intval = POWER_SUPPLY_QC_THERMAL_BALANCE_DISABLE
741 | POWER_SUPPLY_QC_INOV_THERMAL_DISABLE;
742 if (chg->hw_connector_mitigation)
743 val->intval |= POWER_SUPPLY_QC_CTM_DISABLE;
744 break;
Harry Yang4b7db0f2017-11-27 10:50:44 -0800745 default:
746 pr_err("get prop %d is not supported in usb\n", psp);
747 rc = -EINVAL;
748 break;
749 }
750
751 if (rc < 0) {
752 pr_debug("Couldn't get prop %d rc = %d\n", psp, rc);
753 return -ENODATA;
754 }
755
756 return 0;
757}
758
759static int smb5_usb_set_prop(struct power_supply *psy,
760 enum power_supply_property psp,
761 const union power_supply_propval *val)
762{
763 struct smb5 *chip = power_supply_get_drvdata(psy);
764 struct smb_charger *chg = &chip->chg;
765 int rc = 0;
766
Harry Yang4b7db0f2017-11-27 10:50:44 -0800767 switch (psp) {
768 case POWER_SUPPLY_PROP_PD_CURRENT_MAX:
769 rc = smblib_set_prop_pd_current_max(chg, val);
770 break;
771 case POWER_SUPPLY_PROP_TYPEC_POWER_ROLE:
772 rc = smblib_set_prop_typec_power_role(chg, val);
773 break;
774 case POWER_SUPPLY_PROP_PD_ACTIVE:
775 rc = smblib_set_prop_pd_active(chg, val);
776 break;
777 case POWER_SUPPLY_PROP_PD_IN_HARD_RESET:
778 rc = smblib_set_prop_pd_in_hard_reset(chg, val);
779 break;
780 case POWER_SUPPLY_PROP_PD_USB_SUSPEND_SUPPORTED:
781 chg->system_suspend_supported = val->intval;
782 break;
783 case POWER_SUPPLY_PROP_BOOST_CURRENT:
784 rc = smblib_set_prop_boost_current(chg, val);
785 break;
786 case POWER_SUPPLY_PROP_CTM_CURRENT_MAX:
787 rc = vote(chg->usb_icl_votable, CTM_VOTER,
788 val->intval >= 0, val->intval);
789 break;
790 case POWER_SUPPLY_PROP_PR_SWAP:
791 rc = smblib_set_prop_pr_swap_in_progress(chg, val);
792 break;
793 case POWER_SUPPLY_PROP_PD_VOLTAGE_MAX:
794 rc = smblib_set_prop_pd_voltage_max(chg, val);
795 break;
796 case POWER_SUPPLY_PROP_PD_VOLTAGE_MIN:
797 rc = smblib_set_prop_pd_voltage_min(chg, val);
798 break;
799 case POWER_SUPPLY_PROP_SDP_CURRENT_MAX:
800 rc = smblib_set_prop_sdp_current_max(chg, val);
801 break;
802 default:
803 pr_err("set prop %d is not supported\n", psp);
804 rc = -EINVAL;
805 break;
806 }
807
Harry Yang4b7db0f2017-11-27 10:50:44 -0800808 return rc;
809}
810
811static int smb5_usb_prop_is_writeable(struct power_supply *psy,
812 enum power_supply_property psp)
813{
814 switch (psp) {
815 case POWER_SUPPLY_PROP_CTM_CURRENT_MAX:
816 return 1;
817 default:
818 break;
819 }
820
821 return 0;
822}
823
824static const struct power_supply_desc usb_psy_desc = {
825 .name = "usb",
826 .type = POWER_SUPPLY_TYPE_USB_PD,
827 .properties = smb5_usb_props,
828 .num_properties = ARRAY_SIZE(smb5_usb_props),
829 .get_property = smb5_usb_get_prop,
830 .set_property = smb5_usb_set_prop,
831 .property_is_writeable = smb5_usb_prop_is_writeable,
832};
833
834static int smb5_init_usb_psy(struct smb5 *chip)
835{
836 struct power_supply_config usb_cfg = {};
837 struct smb_charger *chg = &chip->chg;
838
839 usb_cfg.drv_data = chip;
840 usb_cfg.of_node = chg->dev->of_node;
841 chg->usb_psy = devm_power_supply_register(chg->dev,
842 &usb_psy_desc,
843 &usb_cfg);
844 if (IS_ERR(chg->usb_psy)) {
845 pr_err("Couldn't register USB power supply\n");
846 return PTR_ERR(chg->usb_psy);
847 }
848
849 return 0;
850}
851
852/********************************
853 * USB PC_PORT PSY REGISTRATION *
854 ********************************/
855static enum power_supply_property smb5_usb_port_props[] = {
856 POWER_SUPPLY_PROP_TYPE,
857 POWER_SUPPLY_PROP_ONLINE,
858 POWER_SUPPLY_PROP_VOLTAGE_MAX,
859 POWER_SUPPLY_PROP_CURRENT_MAX,
860};
861
862static int smb5_usb_port_get_prop(struct power_supply *psy,
863 enum power_supply_property psp,
864 union power_supply_propval *val)
865{
866 struct smb5 *chip = power_supply_get_drvdata(psy);
867 struct smb_charger *chg = &chip->chg;
868 int rc = 0;
869
870 switch (psp) {
871 case POWER_SUPPLY_PROP_TYPE:
872 val->intval = POWER_SUPPLY_TYPE_USB;
873 break;
874 case POWER_SUPPLY_PROP_ONLINE:
875 rc = smblib_get_prop_usb_online(chg, val);
876 if (!val->intval)
877 break;
878
Ashay Jaiswala9e10912018-02-02 14:03:35 +0530879 if (((chg->typec_mode == POWER_SUPPLY_TYPEC_SOURCE_DEFAULT) ||
880 (chg->connector_type == POWER_SUPPLY_CONNECTOR_MICRO_USB))
881 && (chg->real_charger_type == POWER_SUPPLY_TYPE_USB))
Harry Yang4b7db0f2017-11-27 10:50:44 -0800882 val->intval = 1;
883 else
884 val->intval = 0;
885 break;
886 case POWER_SUPPLY_PROP_VOLTAGE_MAX:
887 val->intval = 5000000;
888 break;
889 case POWER_SUPPLY_PROP_CURRENT_MAX:
890 rc = smblib_get_prop_input_current_settled(chg, val);
891 break;
892 default:
893 pr_err_ratelimited("Get prop %d is not supported in pc_port\n",
894 psp);
895 return -EINVAL;
896 }
897
898 if (rc < 0) {
899 pr_debug("Couldn't get prop %d rc = %d\n", psp, rc);
900 return -ENODATA;
901 }
902
903 return 0;
904}
905
906static int smb5_usb_port_set_prop(struct power_supply *psy,
907 enum power_supply_property psp,
908 const union power_supply_propval *val)
909{
910 int rc = 0;
911
912 switch (psp) {
913 default:
914 pr_err_ratelimited("Set prop %d is not supported in pc_port\n",
915 psp);
916 rc = -EINVAL;
917 break;
918 }
919
920 return rc;
921}
922
923static const struct power_supply_desc usb_port_psy_desc = {
924 .name = "pc_port",
925 .type = POWER_SUPPLY_TYPE_USB,
926 .properties = smb5_usb_port_props,
927 .num_properties = ARRAY_SIZE(smb5_usb_port_props),
928 .get_property = smb5_usb_port_get_prop,
929 .set_property = smb5_usb_port_set_prop,
930};
931
932static int smb5_init_usb_port_psy(struct smb5 *chip)
933{
934 struct power_supply_config usb_port_cfg = {};
935 struct smb_charger *chg = &chip->chg;
936
937 usb_port_cfg.drv_data = chip;
938 usb_port_cfg.of_node = chg->dev->of_node;
939 chg->usb_port_psy = devm_power_supply_register(chg->dev,
940 &usb_port_psy_desc,
941 &usb_port_cfg);
942 if (IS_ERR(chg->usb_port_psy)) {
943 pr_err("Couldn't register USB pc_port power supply\n");
944 return PTR_ERR(chg->usb_port_psy);
945 }
946
947 return 0;
948}
949
950/*****************************
951 * USB MAIN PSY REGISTRATION *
952 *****************************/
953
954static enum power_supply_property smb5_usb_main_props[] = {
955 POWER_SUPPLY_PROP_VOLTAGE_MAX,
956 POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX,
957 POWER_SUPPLY_PROP_TYPE,
958 POWER_SUPPLY_PROP_INPUT_CURRENT_SETTLED,
959 POWER_SUPPLY_PROP_INPUT_VOLTAGE_SETTLED,
960 POWER_SUPPLY_PROP_FCC_DELTA,
961 POWER_SUPPLY_PROP_CURRENT_MAX,
Ashay Jaiswal09feab82018-02-12 12:33:18 +0530962 POWER_SUPPLY_PROP_FLASH_ACTIVE,
963 POWER_SUPPLY_PROP_FLASH_TRIGGER,
Harry Yang4b7db0f2017-11-27 10:50:44 -0800964};
965
966static int smb5_usb_main_get_prop(struct power_supply *psy,
967 enum power_supply_property psp,
968 union power_supply_propval *val)
969{
970 struct smb5 *chip = power_supply_get_drvdata(psy);
971 struct smb_charger *chg = &chip->chg;
972 int rc = 0;
973
974 switch (psp) {
975 case POWER_SUPPLY_PROP_VOLTAGE_MAX:
976 rc = smblib_get_charge_param(chg, &chg->param.fv, &val->intval);
977 break;
978 case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX:
979 rc = smblib_get_charge_param(chg, &chg->param.fcc,
980 &val->intval);
981 break;
982 case POWER_SUPPLY_PROP_TYPE:
983 val->intval = POWER_SUPPLY_TYPE_MAIN;
984 break;
985 case POWER_SUPPLY_PROP_INPUT_CURRENT_SETTLED:
986 rc = smblib_get_prop_input_current_settled(chg, val);
987 break;
988 case POWER_SUPPLY_PROP_INPUT_VOLTAGE_SETTLED:
989 rc = smblib_get_prop_input_voltage_settled(chg, val);
990 break;
991 case POWER_SUPPLY_PROP_FCC_DELTA:
992 rc = smblib_get_prop_fcc_delta(chg, val);
993 break;
994 case POWER_SUPPLY_PROP_CURRENT_MAX:
995 rc = smblib_get_icl_current(chg, &val->intval);
996 break;
Ashay Jaiswal09feab82018-02-12 12:33:18 +0530997 case POWER_SUPPLY_PROP_FLASH_ACTIVE:
998 val->intval = chg->flash_active;
999 break;
1000 case POWER_SUPPLY_PROP_FLASH_TRIGGER:
1001 rc = schgm_flash_get_vreg_ok(chg, &val->intval);
1002 break;
Harry Yang4b7db0f2017-11-27 10:50:44 -08001003 default:
1004 pr_debug("get prop %d is not supported in usb-main\n", psp);
1005 rc = -EINVAL;
1006 break;
1007 }
1008 if (rc < 0) {
1009 pr_debug("Couldn't get prop %d rc = %d\n", psp, rc);
1010 return -ENODATA;
1011 }
1012
1013 return 0;
1014}
1015
1016static int smb5_usb_main_set_prop(struct power_supply *psy,
1017 enum power_supply_property psp,
1018 const union power_supply_propval *val)
1019{
1020 struct smb5 *chip = power_supply_get_drvdata(psy);
1021 struct smb_charger *chg = &chip->chg;
Ashay Jaiswal4d334f42018-04-25 10:58:49 +05301022 union power_supply_propval pval = {0, };
Harry Yang4b7db0f2017-11-27 10:50:44 -08001023 int rc = 0;
1024
1025 switch (psp) {
1026 case POWER_SUPPLY_PROP_VOLTAGE_MAX:
1027 rc = smblib_set_charge_param(chg, &chg->param.fv, val->intval);
1028 break;
1029 case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX:
1030 rc = smblib_set_charge_param(chg, &chg->param.fcc, val->intval);
1031 break;
1032 case POWER_SUPPLY_PROP_CURRENT_MAX:
1033 rc = smblib_set_icl_current(chg, val->intval);
1034 break;
Ashay Jaiswal09feab82018-02-12 12:33:18 +05301035 case POWER_SUPPLY_PROP_FLASH_ACTIVE:
Ashay Jaiswal4d334f42018-04-25 10:58:49 +05301036 if ((chg->smb_version == PMI632_SUBTYPE)
1037 && (chg->flash_active != val->intval)) {
1038 chg->flash_active = val->intval;
1039
1040 rc = smblib_get_prop_usb_present(chg, &pval);
1041 if (rc < 0)
1042 pr_err("Failed to get USB preset status rc=%d\n",
1043 rc);
1044 if (pval.intval) {
1045 rc = smblib_force_vbus_voltage(chg,
1046 chg->flash_active ? FORCE_5V_BIT
1047 : IDLE_BIT);
1048 if (rc < 0)
1049 pr_err("Failed to force 5V\n");
1050 else
1051 chg->pulse_cnt = 0;
Anirudh Ghayal4d5cddc2018-06-28 15:19:39 +05301052 } else {
1053 /* USB absent & flash not-active - vote 100mA */
1054 vote(chg->usb_icl_votable, SW_ICL_MAX_VOTER,
1055 true, SDP_100_MA);
Ashay Jaiswal4d334f42018-04-25 10:58:49 +05301056 }
1057
1058 pr_debug("flash active VBUS 5V restriction %s\n",
1059 chg->flash_active ? "applied" : "removed");
1060
1061 /* Update userspace */
1062 if (chg->batt_psy)
1063 power_supply_changed(chg->batt_psy);
1064 }
Ashay Jaiswal09feab82018-02-12 12:33:18 +05301065 break;
Harry Yang4b7db0f2017-11-27 10:50:44 -08001066 default:
1067 pr_err("set prop %d is not supported\n", psp);
1068 rc = -EINVAL;
1069 break;
1070 }
1071
1072 return rc;
1073}
1074
1075static const struct power_supply_desc usb_main_psy_desc = {
1076 .name = "main",
1077 .type = POWER_SUPPLY_TYPE_MAIN,
1078 .properties = smb5_usb_main_props,
1079 .num_properties = ARRAY_SIZE(smb5_usb_main_props),
1080 .get_property = smb5_usb_main_get_prop,
1081 .set_property = smb5_usb_main_set_prop,
1082};
1083
1084static int smb5_init_usb_main_psy(struct smb5 *chip)
1085{
1086 struct power_supply_config usb_main_cfg = {};
1087 struct smb_charger *chg = &chip->chg;
1088
1089 usb_main_cfg.drv_data = chip;
1090 usb_main_cfg.of_node = chg->dev->of_node;
1091 chg->usb_main_psy = devm_power_supply_register(chg->dev,
1092 &usb_main_psy_desc,
1093 &usb_main_cfg);
1094 if (IS_ERR(chg->usb_main_psy)) {
1095 pr_err("Couldn't register USB main power supply\n");
1096 return PTR_ERR(chg->usb_main_psy);
1097 }
1098
1099 return 0;
1100}
1101
1102/*************************
1103 * DC PSY REGISTRATION *
1104 *************************/
1105
1106static enum power_supply_property smb5_dc_props[] = {
1107 POWER_SUPPLY_PROP_INPUT_SUSPEND,
1108 POWER_SUPPLY_PROP_PRESENT,
1109 POWER_SUPPLY_PROP_ONLINE,
1110 POWER_SUPPLY_PROP_REAL_TYPE,
1111};
1112
1113static int smb5_dc_get_prop(struct power_supply *psy,
1114 enum power_supply_property psp,
1115 union power_supply_propval *val)
1116{
1117 struct smb5 *chip = power_supply_get_drvdata(psy);
1118 struct smb_charger *chg = &chip->chg;
1119 int rc = 0;
1120
1121 switch (psp) {
1122 case POWER_SUPPLY_PROP_INPUT_SUSPEND:
1123 val->intval = get_effective_result(chg->dc_suspend_votable);
1124 break;
1125 case POWER_SUPPLY_PROP_PRESENT:
1126 rc = smblib_get_prop_dc_present(chg, val);
1127 break;
1128 case POWER_SUPPLY_PROP_ONLINE:
1129 rc = smblib_get_prop_dc_online(chg, val);
1130 break;
1131 case POWER_SUPPLY_PROP_REAL_TYPE:
1132 val->intval = POWER_SUPPLY_TYPE_WIPOWER;
1133 break;
1134 default:
1135 return -EINVAL;
1136 }
1137 if (rc < 0) {
1138 pr_debug("Couldn't get prop %d rc = %d\n", psp, rc);
1139 return -ENODATA;
1140 }
1141 return 0;
1142}
1143
1144static int smb5_dc_set_prop(struct power_supply *psy,
1145 enum power_supply_property psp,
1146 const union power_supply_propval *val)
1147{
1148 struct smb5 *chip = power_supply_get_drvdata(psy);
1149 struct smb_charger *chg = &chip->chg;
1150 int rc = 0;
1151
1152 switch (psp) {
1153 case POWER_SUPPLY_PROP_INPUT_SUSPEND:
1154 rc = vote(chg->dc_suspend_votable, WBC_VOTER,
1155 (bool)val->intval, 0);
1156 break;
1157 default:
1158 return -EINVAL;
1159 }
1160
1161 return rc;
1162}
1163
1164static int smb5_dc_prop_is_writeable(struct power_supply *psy,
1165 enum power_supply_property psp)
1166{
1167 int rc;
1168
1169 switch (psp) {
1170 default:
1171 rc = 0;
1172 break;
1173 }
1174
1175 return rc;
1176}
1177
1178static const struct power_supply_desc dc_psy_desc = {
1179 .name = "dc",
1180 .type = POWER_SUPPLY_TYPE_WIRELESS,
1181 .properties = smb5_dc_props,
1182 .num_properties = ARRAY_SIZE(smb5_dc_props),
1183 .get_property = smb5_dc_get_prop,
1184 .set_property = smb5_dc_set_prop,
1185 .property_is_writeable = smb5_dc_prop_is_writeable,
1186};
1187
1188static int smb5_init_dc_psy(struct smb5 *chip)
1189{
1190 struct power_supply_config dc_cfg = {};
1191 struct smb_charger *chg = &chip->chg;
1192
1193 dc_cfg.drv_data = chip;
1194 dc_cfg.of_node = chg->dev->of_node;
1195 chg->dc_psy = devm_power_supply_register(chg->dev,
1196 &dc_psy_desc,
1197 &dc_cfg);
1198 if (IS_ERR(chg->dc_psy)) {
1199 pr_err("Couldn't register USB power supply\n");
1200 return PTR_ERR(chg->dc_psy);
1201 }
1202
1203 return 0;
1204}
1205
1206/*************************
1207 * BATT PSY REGISTRATION *
1208 *************************/
1209static enum power_supply_property smb5_batt_props[] = {
1210 POWER_SUPPLY_PROP_INPUT_SUSPEND,
Anirudh Ghayaldfdb8412018-04-21 10:37:18 +05301211 POWER_SUPPLY_PROP_BATTERY_CHARGING_ENABLED,
Harry Yang4b7db0f2017-11-27 10:50:44 -08001212 POWER_SUPPLY_PROP_STATUS,
1213 POWER_SUPPLY_PROP_HEALTH,
1214 POWER_SUPPLY_PROP_PRESENT,
1215 POWER_SUPPLY_PROP_CHARGE_TYPE,
1216 POWER_SUPPLY_PROP_CAPACITY,
1217 POWER_SUPPLY_PROP_INPUT_CURRENT_LIMITED,
1218 POWER_SUPPLY_PROP_VOLTAGE_NOW,
1219 POWER_SUPPLY_PROP_VOLTAGE_MAX,
1220 POWER_SUPPLY_PROP_CURRENT_NOW,
1221 POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX,
1222 POWER_SUPPLY_PROP_TEMP,
1223 POWER_SUPPLY_PROP_TECHNOLOGY,
1224 POWER_SUPPLY_PROP_STEP_CHARGING_ENABLED,
1225 POWER_SUPPLY_PROP_SW_JEITA_ENABLED,
1226 POWER_SUPPLY_PROP_CHARGE_DONE,
1227 POWER_SUPPLY_PROP_PARALLEL_DISABLE,
1228 POWER_SUPPLY_PROP_SET_SHIP_MODE,
1229 POWER_SUPPLY_PROP_DIE_HEALTH,
1230 POWER_SUPPLY_PROP_RERUN_AICL,
1231 POWER_SUPPLY_PROP_DP_DM,
1232 POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT_MAX,
1233 POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT,
1234 POWER_SUPPLY_PROP_CHARGE_COUNTER,
Subbaraman Narayanamurthyc4feb892018-05-07 18:43:45 -07001235 POWER_SUPPLY_PROP_CYCLE_COUNT,
Anirudh Ghayal1380d312018-02-23 00:01:43 +05301236 POWER_SUPPLY_PROP_RECHARGE_SOC,
Harry Yang4b7db0f2017-11-27 10:50:44 -08001237};
1238
1239static int smb5_batt_get_prop(struct power_supply *psy,
1240 enum power_supply_property psp,
1241 union power_supply_propval *val)
1242{
1243 struct smb_charger *chg = power_supply_get_drvdata(psy);
1244 int rc = 0;
1245
1246 switch (psp) {
1247 case POWER_SUPPLY_PROP_STATUS:
1248 rc = smblib_get_prop_batt_status(chg, val);
1249 break;
1250 case POWER_SUPPLY_PROP_HEALTH:
1251 rc = smblib_get_prop_batt_health(chg, val);
1252 break;
1253 case POWER_SUPPLY_PROP_PRESENT:
1254 rc = smblib_get_prop_batt_present(chg, val);
1255 break;
1256 case POWER_SUPPLY_PROP_INPUT_SUSPEND:
1257 rc = smblib_get_prop_input_suspend(chg, val);
1258 break;
Anirudh Ghayaldfdb8412018-04-21 10:37:18 +05301259 case POWER_SUPPLY_PROP_BATTERY_CHARGING_ENABLED:
1260 val->intval = !get_client_vote(chg->chg_disable_votable,
1261 USER_VOTER);
1262 break;
Harry Yang4b7db0f2017-11-27 10:50:44 -08001263 case POWER_SUPPLY_PROP_CHARGE_TYPE:
1264 rc = smblib_get_prop_batt_charge_type(chg, val);
1265 break;
1266 case POWER_SUPPLY_PROP_CAPACITY:
1267 rc = smblib_get_prop_batt_capacity(chg, val);
1268 break;
1269 case POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT:
1270 rc = smblib_get_prop_system_temp_level(chg, val);
1271 break;
1272 case POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT_MAX:
1273 rc = smblib_get_prop_system_temp_level_max(chg, val);
1274 break;
1275 case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMITED:
1276 rc = smblib_get_prop_input_current_limited(chg, val);
1277 break;
1278 case POWER_SUPPLY_PROP_STEP_CHARGING_ENABLED:
1279 val->intval = chg->step_chg_enabled;
1280 break;
1281 case POWER_SUPPLY_PROP_SW_JEITA_ENABLED:
1282 val->intval = chg->sw_jeita_enabled;
1283 break;
1284 case POWER_SUPPLY_PROP_VOLTAGE_NOW:
1285 rc = smblib_get_prop_batt_voltage_now(chg, val);
1286 break;
1287 case POWER_SUPPLY_PROP_VOLTAGE_MAX:
1288 val->intval = get_client_vote(chg->fv_votable,
1289 BATT_PROFILE_VOTER);
1290 break;
1291 case POWER_SUPPLY_PROP_CURRENT_NOW:
1292 rc = smblib_get_prop_batt_current_now(chg, val);
1293 break;
1294 case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX:
1295 val->intval = get_client_vote(chg->fcc_votable,
1296 BATT_PROFILE_VOTER);
1297 break;
1298 case POWER_SUPPLY_PROP_TEMP:
1299 rc = smblib_get_prop_batt_temp(chg, val);
1300 break;
1301 case POWER_SUPPLY_PROP_TECHNOLOGY:
1302 val->intval = POWER_SUPPLY_TECHNOLOGY_LION;
1303 break;
1304 case POWER_SUPPLY_PROP_CHARGE_DONE:
1305 rc = smblib_get_prop_batt_charge_done(chg, val);
1306 break;
1307 case POWER_SUPPLY_PROP_PARALLEL_DISABLE:
1308 val->intval = get_client_vote(chg->pl_disable_votable,
1309 USER_VOTER);
1310 break;
1311 case POWER_SUPPLY_PROP_SET_SHIP_MODE:
1312 /* Not in ship mode as long as device is active */
1313 val->intval = 0;
1314 break;
1315 case POWER_SUPPLY_PROP_DIE_HEALTH:
1316 if (chg->die_health == -EINVAL)
1317 rc = smblib_get_prop_die_health(chg, val);
1318 else
1319 val->intval = chg->die_health;
1320 break;
1321 case POWER_SUPPLY_PROP_DP_DM:
1322 val->intval = chg->pulse_cnt;
1323 break;
1324 case POWER_SUPPLY_PROP_RERUN_AICL:
1325 val->intval = 0;
1326 break;
1327 case POWER_SUPPLY_PROP_CHARGE_COUNTER:
1328 rc = smblib_get_prop_batt_charge_counter(chg, val);
1329 break;
Subbaraman Narayanamurthyc4feb892018-05-07 18:43:45 -07001330 case POWER_SUPPLY_PROP_CYCLE_COUNT:
1331 rc = smblib_get_prop_batt_cycle_count(chg, val);
1332 break;
Anirudh Ghayal1380d312018-02-23 00:01:43 +05301333 case POWER_SUPPLY_PROP_RECHARGE_SOC:
1334 val->intval = chg->auto_recharge_soc;
1335 break;
Harry Yang4b7db0f2017-11-27 10:50:44 -08001336 default:
1337 pr_err("batt power supply prop %d not supported\n", psp);
1338 return -EINVAL;
1339 }
1340
1341 if (rc < 0) {
1342 pr_debug("Couldn't get prop %d rc = %d\n", psp, rc);
1343 return -ENODATA;
1344 }
1345
1346 return 0;
1347}
1348
1349static int smb5_batt_set_prop(struct power_supply *psy,
1350 enum power_supply_property prop,
1351 const union power_supply_propval *val)
1352{
1353 int rc = 0;
1354 struct smb_charger *chg = power_supply_get_drvdata(psy);
Ashay Jaiswala55b7ed2018-03-23 17:23:48 +05301355 bool enable;
Harry Yang4b7db0f2017-11-27 10:50:44 -08001356
1357 switch (prop) {
1358 case POWER_SUPPLY_PROP_STATUS:
1359 rc = smblib_set_prop_batt_status(chg, val);
1360 break;
1361 case POWER_SUPPLY_PROP_INPUT_SUSPEND:
1362 rc = smblib_set_prop_input_suspend(chg, val);
1363 break;
Anirudh Ghayaldfdb8412018-04-21 10:37:18 +05301364 case POWER_SUPPLY_PROP_BATTERY_CHARGING_ENABLED:
1365 vote(chg->chg_disable_votable, USER_VOTER, !val->intval, 0);
1366 break;
Harry Yang4b7db0f2017-11-27 10:50:44 -08001367 case POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT:
1368 rc = smblib_set_prop_system_temp_level(chg, val);
1369 break;
1370 case POWER_SUPPLY_PROP_CAPACITY:
1371 rc = smblib_set_prop_batt_capacity(chg, val);
1372 break;
1373 case POWER_SUPPLY_PROP_PARALLEL_DISABLE:
1374 vote(chg->pl_disable_votable, USER_VOTER, (bool)val->intval, 0);
1375 break;
1376 case POWER_SUPPLY_PROP_VOLTAGE_MAX:
1377 chg->batt_profile_fv_uv = val->intval;
1378 vote(chg->fv_votable, BATT_PROFILE_VOTER, true, val->intval);
1379 break;
1380 case POWER_SUPPLY_PROP_STEP_CHARGING_ENABLED:
Ashay Jaiswala55b7ed2018-03-23 17:23:48 +05301381 enable = !!val->intval || chg->sw_jeita_enabled;
1382 rc = smblib_configure_wdog(chg, enable);
1383 if (rc == 0)
1384 chg->step_chg_enabled = !!val->intval;
Harry Yang4b7db0f2017-11-27 10:50:44 -08001385 break;
1386 case POWER_SUPPLY_PROP_SW_JEITA_ENABLED:
1387 if (chg->sw_jeita_enabled != (!!val->intval)) {
1388 rc = smblib_disable_hw_jeita(chg, !!val->intval);
Ashay Jaiswala55b7ed2018-03-23 17:23:48 +05301389 enable = !!val->intval || chg->step_chg_enabled;
1390 rc |= smblib_configure_wdog(chg, enable);
Harry Yang4b7db0f2017-11-27 10:50:44 -08001391 if (rc == 0)
1392 chg->sw_jeita_enabled = !!val->intval;
1393 }
1394 break;
1395 case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX:
1396 chg->batt_profile_fcc_ua = val->intval;
1397 vote(chg->fcc_votable, BATT_PROFILE_VOTER, true, val->intval);
1398 break;
1399 case POWER_SUPPLY_PROP_SET_SHIP_MODE:
1400 /* Not in ship mode as long as the device is active */
1401 if (!val->intval)
1402 break;
1403 if (chg->pl.psy)
1404 power_supply_set_property(chg->pl.psy,
1405 POWER_SUPPLY_PROP_SET_SHIP_MODE, val);
1406 rc = smblib_set_prop_ship_mode(chg, val);
1407 break;
1408 case POWER_SUPPLY_PROP_RERUN_AICL:
Ashay Jaiswale0b3c472018-06-20 23:39:41 +05301409 rc = smblib_run_aicl(chg, RERUN_AICL);
Harry Yang4b7db0f2017-11-27 10:50:44 -08001410 break;
1411 case POWER_SUPPLY_PROP_DP_DM:
Ashay Jaiswal4d334f42018-04-25 10:58:49 +05301412 if (!chg->flash_active)
1413 rc = smblib_dp_dm(chg, val->intval);
Harry Yang4b7db0f2017-11-27 10:50:44 -08001414 break;
1415 case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMITED:
1416 rc = smblib_set_prop_input_current_limited(chg, val);
1417 break;
1418 case POWER_SUPPLY_PROP_DIE_HEALTH:
1419 chg->die_health = val->intval;
1420 power_supply_changed(chg->batt_psy);
1421 break;
Anirudh Ghayaldfdb8412018-04-21 10:37:18 +05301422 case POWER_SUPPLY_PROP_RECHARGE_SOC:
1423 if (chg->smb_version == PMI632_SUBTYPE) {
1424 /* toggle charging to force recharge */
1425 vote(chg->chg_disable_votable, FORCE_RECHARGE_VOTER,
1426 true, 0);
1427 /* charge disable delay */
1428 msleep(50);
1429 vote(chg->chg_disable_votable, FORCE_RECHARGE_VOTER,
1430 false, 0);
1431 }
1432 break;
Harry Yang4b7db0f2017-11-27 10:50:44 -08001433 default:
1434 rc = -EINVAL;
1435 }
1436
1437 return rc;
1438}
1439
1440static int smb5_batt_prop_is_writeable(struct power_supply *psy,
1441 enum power_supply_property psp)
1442{
1443 switch (psp) {
1444 case POWER_SUPPLY_PROP_STATUS:
1445 case POWER_SUPPLY_PROP_INPUT_SUSPEND:
1446 case POWER_SUPPLY_PROP_SYSTEM_TEMP_LEVEL:
1447 case POWER_SUPPLY_PROP_CAPACITY:
1448 case POWER_SUPPLY_PROP_PARALLEL_DISABLE:
1449 case POWER_SUPPLY_PROP_DP_DM:
1450 case POWER_SUPPLY_PROP_RERUN_AICL:
1451 case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMITED:
1452 case POWER_SUPPLY_PROP_STEP_CHARGING_ENABLED:
1453 case POWER_SUPPLY_PROP_SW_JEITA_ENABLED:
1454 case POWER_SUPPLY_PROP_DIE_HEALTH:
Anirudh Ghayaldfdb8412018-04-21 10:37:18 +05301455 case POWER_SUPPLY_PROP_BATTERY_CHARGING_ENABLED:
Harry Yang4b7db0f2017-11-27 10:50:44 -08001456 return 1;
1457 default:
1458 break;
1459 }
1460
1461 return 0;
1462}
1463
1464static const struct power_supply_desc batt_psy_desc = {
1465 .name = "battery",
1466 .type = POWER_SUPPLY_TYPE_BATTERY,
1467 .properties = smb5_batt_props,
1468 .num_properties = ARRAY_SIZE(smb5_batt_props),
1469 .get_property = smb5_batt_get_prop,
1470 .set_property = smb5_batt_set_prop,
1471 .property_is_writeable = smb5_batt_prop_is_writeable,
1472};
1473
1474static int smb5_init_batt_psy(struct smb5 *chip)
1475{
1476 struct power_supply_config batt_cfg = {};
1477 struct smb_charger *chg = &chip->chg;
1478 int rc = 0;
1479
1480 batt_cfg.drv_data = chg;
1481 batt_cfg.of_node = chg->dev->of_node;
1482 chg->batt_psy = devm_power_supply_register(chg->dev,
1483 &batt_psy_desc,
1484 &batt_cfg);
1485 if (IS_ERR(chg->batt_psy)) {
1486 pr_err("Couldn't register battery power supply\n");
1487 return PTR_ERR(chg->batt_psy);
1488 }
1489
1490 return rc;
1491}
1492
1493/******************************
1494 * VBUS REGULATOR REGISTRATION *
1495 ******************************/
1496
1497static struct regulator_ops smb5_vbus_reg_ops = {
1498 .enable = smblib_vbus_regulator_enable,
1499 .disable = smblib_vbus_regulator_disable,
1500 .is_enabled = smblib_vbus_regulator_is_enabled,
1501};
1502
1503static int smb5_init_vbus_regulator(struct smb5 *chip)
1504{
1505 struct smb_charger *chg = &chip->chg;
1506 struct regulator_config cfg = {};
1507 int rc = 0;
1508
1509 chg->vbus_vreg = devm_kzalloc(chg->dev, sizeof(*chg->vbus_vreg),
1510 GFP_KERNEL);
1511 if (!chg->vbus_vreg)
1512 return -ENOMEM;
1513
1514 cfg.dev = chg->dev;
1515 cfg.driver_data = chip;
1516
1517 chg->vbus_vreg->rdesc.owner = THIS_MODULE;
1518 chg->vbus_vreg->rdesc.type = REGULATOR_VOLTAGE;
1519 chg->vbus_vreg->rdesc.ops = &smb5_vbus_reg_ops;
1520 chg->vbus_vreg->rdesc.of_match = "qcom,smb5-vbus";
1521 chg->vbus_vreg->rdesc.name = "qcom,smb5-vbus";
1522
1523 chg->vbus_vreg->rdev = devm_regulator_register(chg->dev,
1524 &chg->vbus_vreg->rdesc, &cfg);
1525 if (IS_ERR(chg->vbus_vreg->rdev)) {
1526 rc = PTR_ERR(chg->vbus_vreg->rdev);
1527 chg->vbus_vreg->rdev = NULL;
1528 if (rc != -EPROBE_DEFER)
1529 pr_err("Couldn't register VBUS regulator rc=%d\n", rc);
1530 }
1531
1532 return rc;
1533}
1534
1535/******************************
1536 * VCONN REGULATOR REGISTRATION *
1537 ******************************/
1538
1539static struct regulator_ops smb5_vconn_reg_ops = {
1540 .enable = smblib_vconn_regulator_enable,
1541 .disable = smblib_vconn_regulator_disable,
1542 .is_enabled = smblib_vconn_regulator_is_enabled,
1543};
1544
1545static int smb5_init_vconn_regulator(struct smb5 *chip)
1546{
1547 struct smb_charger *chg = &chip->chg;
1548 struct regulator_config cfg = {};
1549 int rc = 0;
1550
Ashay Jaiswala9e10912018-02-02 14:03:35 +05301551 if (chg->connector_type == POWER_SUPPLY_CONNECTOR_MICRO_USB)
Harry Yang4b7db0f2017-11-27 10:50:44 -08001552 return 0;
1553
1554 chg->vconn_vreg = devm_kzalloc(chg->dev, sizeof(*chg->vconn_vreg),
1555 GFP_KERNEL);
1556 if (!chg->vconn_vreg)
1557 return -ENOMEM;
1558
1559 cfg.dev = chg->dev;
1560 cfg.driver_data = chip;
1561
1562 chg->vconn_vreg->rdesc.owner = THIS_MODULE;
1563 chg->vconn_vreg->rdesc.type = REGULATOR_VOLTAGE;
1564 chg->vconn_vreg->rdesc.ops = &smb5_vconn_reg_ops;
1565 chg->vconn_vreg->rdesc.of_match = "qcom,smb5-vconn";
1566 chg->vconn_vreg->rdesc.name = "qcom,smb5-vconn";
1567
1568 chg->vconn_vreg->rdev = devm_regulator_register(chg->dev,
1569 &chg->vconn_vreg->rdesc, &cfg);
1570 if (IS_ERR(chg->vconn_vreg->rdev)) {
1571 rc = PTR_ERR(chg->vconn_vreg->rdev);
1572 chg->vconn_vreg->rdev = NULL;
1573 if (rc != -EPROBE_DEFER)
1574 pr_err("Couldn't register VCONN regulator rc=%d\n", rc);
1575 }
1576
1577 return rc;
1578}
1579
1580/***************************
1581 * HARDWARE INITIALIZATION *
1582 ***************************/
1583static int smb5_configure_typec(struct smb_charger *chg)
1584{
1585 int rc;
Ashay Jaiswal91d63f42018-05-16 11:30:40 +05301586 u8 val = 0;
1587
1588 rc = smblib_read(chg, LEGACY_CABLE_STATUS_REG, &val);
1589 if (rc < 0) {
1590 dev_err(chg->dev, "Couldn't read Legacy status rc=%d\n", rc);
1591 return rc;
1592 }
1593 /*
1594 * If Legacy cable is detected re-trigger Legacy detection
1595 * by disabling/enabling typeC mode.
1596 */
1597 if (val & TYPEC_LEGACY_CABLE_STATUS_BIT) {
1598 rc = smblib_masked_write(chg, TYPE_C_MODE_CFG_REG,
1599 TYPEC_DISABLE_CMD_BIT, TYPEC_DISABLE_CMD_BIT);
1600 if (rc < 0) {
1601 dev_err(chg->dev, "Couldn't disable TYPEC rc=%d\n", rc);
1602 return rc;
1603 }
1604
1605 /* delay before enabling typeC */
1606 msleep(500);
1607
1608 rc = smblib_masked_write(chg, TYPE_C_MODE_CFG_REG,
1609 TYPEC_DISABLE_CMD_BIT, 0);
1610 if (rc < 0) {
1611 dev_err(chg->dev, "Couldn't enable TYPEC rc=%d\n", rc);
1612 return rc;
1613 }
1614 }
Harry Yang4b7db0f2017-11-27 10:50:44 -08001615
Harry Yang6afaea22018-03-26 19:11:07 -07001616 /* disable apsd */
Ashay Jaiswalc96380de2018-05-16 12:02:36 +05301617 rc = smblib_configure_hvdcp_apsd(chg, false);
Harry Yang6afaea22018-03-26 19:11:07 -07001618 if (rc < 0) {
1619 dev_err(chg->dev, "Couldn't disable APSD rc=%d\n", rc);
1620 return rc;
1621 }
1622
Harry Yang4b7db0f2017-11-27 10:50:44 -08001623 rc = smblib_write(chg, TYPE_C_INTERRUPT_EN_CFG_1_REG,
1624 TYPEC_CCOUT_DETACH_INT_EN_BIT |
1625 TYPEC_CCOUT_ATTACH_INT_EN_BIT);
1626 if (rc < 0) {
1627 dev_err(chg->dev,
1628 "Couldn't configure Type-C interrupts rc=%d\n", rc);
1629 return rc;
1630 }
1631
1632 rc = smblib_write(chg, TYPE_C_INTERRUPT_EN_CFG_2_REG,
Harry Yang4b7db0f2017-11-27 10:50:44 -08001633 TYPEC_WATER_DETECTION_INT_EN_BIT);
1634 if (rc < 0) {
1635 dev_err(chg->dev,
1636 "Couldn't configure Type-C interrupts rc=%d\n", rc);
1637 return rc;
1638 }
1639
Harry Yang423d5c32018-05-30 15:49:04 -07001640 rc = smblib_masked_write(chg, TYPE_C_MODE_CFG_REG,
1641 EN_TRY_SNK_BIT, EN_TRY_SNK_BIT);
1642 if (rc < 0) {
1643 dev_err(chg->dev,
1644 "Couldn't enable try.snk rc=%d\n", rc);
1645 return rc;
1646 }
1647
Ashay Jaiswald5022b62018-05-27 19:21:11 +05301648 /* Keep VCONN in h/w controlled mode for PMI632 */
1649 if (chg->smb_version != PMI632_SUBTYPE) {
1650 /* configure VCONN for software control */
1651 rc = smblib_masked_write(chg, TYPE_C_VCONN_CONTROL_REG,
Harry Yang4b7db0f2017-11-27 10:50:44 -08001652 VCONN_EN_SRC_BIT | VCONN_EN_VALUE_BIT,
1653 VCONN_EN_SRC_BIT);
Ashay Jaiswald5022b62018-05-27 19:21:11 +05301654 if (rc < 0) {
1655 dev_err(chg->dev,
1656 "Couldn't configure VCONN for SW control rc=%d\n",
1657 rc);
1658 return rc;
1659 }
Harry Yang4b7db0f2017-11-27 10:50:44 -08001660 }
1661
1662 return rc;
1663}
1664
1665static int smb5_configure_micro_usb(struct smb_charger *chg)
1666{
1667 int rc;
1668
Ashay Jaiswala9e10912018-02-02 14:03:35 +05301669 rc = smblib_masked_write(chg, TYPE_C_INTERRUPT_EN_CFG_2_REG,
1670 MICRO_USB_STATE_CHANGE_INT_EN_BIT,
1671 MICRO_USB_STATE_CHANGE_INT_EN_BIT);
1672 if (rc < 0) {
1673 dev_err(chg->dev,
1674 "Couldn't configure Type-C interrupts rc=%d\n", rc);
1675 return rc;
1676 }
1677
Harry Yang4b7db0f2017-11-27 10:50:44 -08001678 return rc;
1679}
1680
Ashay Jaiswal0de6fb92018-06-12 17:23:45 +05301681static int smb5_configure_mitigation(struct smb_charger *chg)
1682{
1683 int rc;
1684 u8 chan = 0;
1685
1686 if (!chg->hw_die_temp_mitigation && !chg->hw_connector_mitigation)
1687 return 0;
1688
1689 if (chg->hw_die_temp_mitigation) {
1690 rc = smblib_write(chg, MISC_THERMREG_SRC_CFG_REG,
1691 THERMREG_CONNECTOR_ADC_SRC_EN_BIT
1692 | THERMREG_DIE_ADC_SRC_EN_BIT
1693 | THERMREG_DIE_CMP_SRC_EN_BIT);
1694 if (rc < 0) {
1695 dev_err(chg->dev,
1696 "Couldn't configure THERM_SRC reg rc=%d\n", rc);
1697 return rc;
1698 };
1699
1700 chan = DIE_TEMP_CHANNEL_EN_BIT;
1701 }
1702
1703 if (chg->hw_connector_mitigation)
1704 chan |= CONN_THM_CHANNEL_EN_BIT;
1705
1706 rc = smblib_masked_write(chg, BATIF_ADC_CHANNEL_EN_REG,
1707 CONN_THM_CHANNEL_EN_BIT | DIE_TEMP_CHANNEL_EN_BIT,
1708 chan);
1709 if (rc < 0) {
Ashay Jaiswalb50706d2018-06-28 19:37:31 +05301710 dev_err(chg->dev, "Couldn't enable ADC channel rc=%d\n", rc);
Ashay Jaiswal0de6fb92018-06-12 17:23:45 +05301711 return rc;
1712 }
1713
1714 return 0;
1715}
1716
Harry Yang4b7db0f2017-11-27 10:50:44 -08001717static int smb5_init_hw(struct smb5 *chip)
1718{
1719 struct smb_charger *chg = &chip->chg;
Ashay Jaiswala9e10912018-02-02 14:03:35 +05301720 int rc, type = 0;
1721 u8 val = 0;
Harry Yang4b7db0f2017-11-27 10:50:44 -08001722
1723 if (chip->dt.no_battery)
1724 chg->fake_capacity = 50;
1725
1726 if (chip->dt.batt_profile_fcc_ua < 0)
1727 smblib_get_charge_param(chg, &chg->param.fcc,
1728 &chg->batt_profile_fcc_ua);
1729
1730 if (chip->dt.batt_profile_fv_uv < 0)
1731 smblib_get_charge_param(chg, &chg->param.fv,
1732 &chg->batt_profile_fv_uv);
1733
1734 smblib_get_charge_param(chg, &chg->param.usb_icl,
1735 &chg->default_icl_ua);
Ashay Jaiswale0b3c472018-06-20 23:39:41 +05301736 smblib_get_charge_param(chg, &chg->param.aicl_5v_threshold,
1737 &chg->default_aicl_5v_threshold_mv);
1738 chg->aicl_5v_threshold_mv = chg->default_aicl_5v_threshold_mv;
1739 smblib_get_charge_param(chg, &chg->param.aicl_cont_threshold,
1740 &chg->default_aicl_cont_threshold_mv);
1741 chg->aicl_cont_threshold_mv = chg->default_aicl_cont_threshold_mv;
Ashay Jaiswala9e10912018-02-02 14:03:35 +05301742
1743 /* Use SW based VBUS control, disable HW autonomous mode */
Ashay Jaiswala9e10912018-02-02 14:03:35 +05301744 rc = smblib_masked_write(chg, USBIN_OPTIONS_1_CFG_REG,
1745 HVDCP_AUTH_ALG_EN_CFG_BIT | HVDCP_AUTONOMOUS_MODE_EN_CFG_BIT,
1746 HVDCP_AUTH_ALG_EN_CFG_BIT);
1747 if (rc < 0) {
1748 dev_err(chg->dev, "Couldn't configure HVDCP rc=%d\n", rc);
1749 return rc;
1750 }
1751
1752 /*
1753 * PMI632 can have the connector type defined by a dedicated register
1754 * TYPEC_MICRO_USB_MODE_REG or by a common TYPEC_U_USB_CFG_REG.
1755 */
1756 if (chg->smb_version == PMI632_SUBTYPE) {
1757 rc = smblib_read(chg, TYPEC_MICRO_USB_MODE_REG, &val);
1758 if (rc < 0) {
1759 dev_err(chg->dev, "Couldn't read USB mode rc=%d\n", rc);
1760 return rc;
1761 }
1762 type = !!(val & MICRO_USB_MODE_ONLY_BIT);
1763 }
1764
1765 /*
1766 * If TYPEC_MICRO_USB_MODE_REG is not set and for all non-PMI632
1767 * check the connector type using TYPEC_U_USB_CFG_REG.
1768 */
1769 if (!type) {
1770 rc = smblib_read(chg, TYPEC_U_USB_CFG_REG, &val);
1771 if (rc < 0) {
1772 dev_err(chg->dev, "Couldn't read U_USB config rc=%d\n",
1773 rc);
1774 return rc;
1775 }
1776
1777 type = !!(val & EN_MICRO_USB_MODE_BIT);
1778 }
1779
Ashay Jaiswala9e10912018-02-02 14:03:35 +05301780 pr_debug("Connector type=%s\n", type ? "Micro USB" : "TypeC");
1781
Harry Yang6afaea22018-03-26 19:11:07 -07001782 if (type) {
1783 chg->connector_type = POWER_SUPPLY_CONNECTOR_MICRO_USB;
Harry Yang6afaea22018-03-26 19:11:07 -07001784 rc = smb5_configure_micro_usb(chg);
1785 } else {
1786 chg->connector_type = POWER_SUPPLY_CONNECTOR_TYPEC;
1787 rc = smb5_configure_typec(chg);
1788 }
1789 if (rc < 0) {
1790 dev_err(chg->dev,
1791 "Couldn't configure TypeC/micro-USB mode rc=%d\n", rc);
1792 return rc;
1793 }
1794
Ashay Jaiswal09feab82018-02-12 12:33:18 +05301795 /*
1796 * PMI632 based hw init:
Ashay Jaiswal6f70a512018-05-11 17:25:58 +05301797 * - Enable STAT pin function on SMB_EN
Ashay Jaiswalc96380de2018-05-16 12:02:36 +05301798 * - Rerun APSD to ensure proper charger detection if device
1799 * boots with charger connected.
Ashay Jaiswal09feab82018-02-12 12:33:18 +05301800 * - Initialize flash module for PMI632
1801 */
Ashay Jaiswalc96380de2018-05-16 12:02:36 +05301802 if (chg->smb_version == PMI632_SUBTYPE) {
Ashay Jaiswal6f70a512018-05-11 17:25:58 +05301803 rc = smblib_masked_write(chg, MISC_SMB_EN_CMD_REG,
1804 EN_STAT_CMD_BIT, EN_STAT_CMD_BIT);
1805 if (rc < 0) {
1806 dev_err(chg->dev, "Couldn't configure SMB_EN rc=%d\n",
1807 rc);
1808 return rc;
1809 }
1810
Ashay Jaiswal09feab82018-02-12 12:33:18 +05301811 schgm_flash_init(chg);
Ashay Jaiswalc96380de2018-05-16 12:02:36 +05301812 smblib_rerun_apsd_if_required(chg);
1813 }
Ashay Jaiswal09feab82018-02-12 12:33:18 +05301814
Ashay Jaiswalcbdf2e82018-05-27 23:59:01 +05301815 /* clear the ICL override if it is set */
1816 rc = smblib_icl_override(chg, false);
1817 if (rc < 0) {
1818 pr_err("Couldn't disable ICL override rc=%d\n", rc);
1819 return rc;
1820 }
1821
Ashay Jaiswalb2b06fe2018-06-07 18:35:21 +05301822 /* set OTG current limit */
1823 rc = smblib_set_charge_param(chg, &chg->param.otg_cl, chg->otg_cl_ua);
1824 if (rc < 0) {
1825 pr_err("Couldn't set otg current limit rc=%d\n", rc);
1826 return rc;
1827 }
1828
Ashay Jaiswal0de6fb92018-06-12 17:23:45 +05301829 /* configure temperature mitigation */
1830 rc = smb5_configure_mitigation(chg);
1831 if (rc < 0) {
1832 dev_err(chg->dev, "Couldn't configure mitigation rc=%d\n", rc);
1833 return rc;
1834 }
1835
Harry Yang4b7db0f2017-11-27 10:50:44 -08001836 /* vote 0mA on usb_icl for non battery platforms */
1837 vote(chg->usb_icl_votable,
1838 DEFAULT_VOTER, chip->dt.no_battery, 0);
1839 vote(chg->dc_suspend_votable,
1840 DEFAULT_VOTER, chip->dt.no_battery, 0);
1841 vote(chg->fcc_votable, HW_LIMIT_VOTER,
1842 chip->dt.batt_profile_fcc_ua > 0, chip->dt.batt_profile_fcc_ua);
1843 vote(chg->fv_votable, HW_LIMIT_VOTER,
1844 chip->dt.batt_profile_fv_uv > 0, chip->dt.batt_profile_fv_uv);
1845 vote(chg->fcc_votable,
Ashay Jaiswala9e10912018-02-02 14:03:35 +05301846 BATT_PROFILE_VOTER, chg->batt_profile_fcc_ua > 0,
1847 chg->batt_profile_fcc_ua);
Harry Yang4b7db0f2017-11-27 10:50:44 -08001848 vote(chg->fv_votable,
Ashay Jaiswala9e10912018-02-02 14:03:35 +05301849 BATT_PROFILE_VOTER, chg->batt_profile_fv_uv > 0,
1850 chg->batt_profile_fv_uv);
Ashay Jaiswala9e10912018-02-02 14:03:35 +05301851
1852 /* Some h/w limit maximum supported ICL */
1853 vote(chg->usb_icl_votable, HW_LIMIT_VOTER,
1854 chg->hw_max_icl_ua > 0, chg->hw_max_icl_ua);
Harry Yang4b7db0f2017-11-27 10:50:44 -08001855
1856 /*
1857 * AICL configuration:
Ashay Jaiswalc96380de2018-05-16 12:02:36 +05301858 * AICL ADC disable
Harry Yang4b7db0f2017-11-27 10:50:44 -08001859 */
Ashay Jaiswalc96380de2018-05-16 12:02:36 +05301860 if (chg->smb_version != PMI632_SUBTYPE) {
1861 rc = smblib_masked_write(chg, USBIN_AICL_OPTIONS_CFG_REG,
Harry Yang4b7db0f2017-11-27 10:50:44 -08001862 USBIN_AICL_ADC_EN_BIT, 0);
Ashay Jaiswalc96380de2018-05-16 12:02:36 +05301863 if (rc < 0) {
1864 dev_err(chg->dev, "Couldn't config AICL rc=%d\n", rc);
1865 return rc;
1866 }
Harry Yang4b7db0f2017-11-27 10:50:44 -08001867 }
1868
1869 /* enable the charging path */
1870 rc = vote(chg->chg_disable_votable, DEFAULT_VOTER, false, 0);
1871 if (rc < 0) {
1872 dev_err(chg->dev, "Couldn't enable charging rc=%d\n", rc);
1873 return rc;
1874 }
1875
Harry Yang4b7db0f2017-11-27 10:50:44 -08001876 /* configure VBUS for software control */
1877 rc = smblib_masked_write(chg, DCDC_OTG_CFG_REG, OTG_EN_SRC_CFG_BIT, 0);
1878 if (rc < 0) {
1879 dev_err(chg->dev,
1880 "Couldn't configure VBUS for SW control rc=%d\n", rc);
1881 return rc;
1882 }
1883
Ashay Jaiswala55b7ed2018-03-23 17:23:48 +05301884 /*
1885 * configure the one time watchdong periodic interval and
1886 * disable "watchdog bite disable charging".
1887 */
Harry Yang4b7db0f2017-11-27 10:50:44 -08001888 val = (ilog2(chip->dt.wd_bark_time / 16) << BARK_WDOG_TIMEOUT_SHIFT)
1889 & BARK_WDOG_TIMEOUT_MASK;
1890 val |= BITE_WDOG_TIMEOUT_8S;
1891 rc = smblib_masked_write(chg, SNARL_BARK_BITE_WD_CFG_REG,
1892 BITE_WDOG_DISABLE_CHARGING_CFG_BIT |
1893 BARK_WDOG_TIMEOUT_MASK | BITE_WDOG_TIMEOUT_MASK,
1894 val);
1895 if (rc < 0) {
1896 pr_err("Couldn't configue WD config rc=%d\n", rc);
1897 return rc;
1898 }
1899
Harry Yang4b7db0f2017-11-27 10:50:44 -08001900 /* configure float charger options */
1901 switch (chip->dt.float_option) {
1902 case FLOAT_DCP:
1903 rc = smblib_masked_write(chg, USBIN_OPTIONS_2_CFG_REG,
1904 FLOAT_OPTIONS_MASK, 0);
1905 break;
1906 case FLOAT_SDP:
1907 rc = smblib_masked_write(chg, USBIN_OPTIONS_2_CFG_REG,
1908 FLOAT_OPTIONS_MASK, FORCE_FLOAT_SDP_CFG_BIT);
1909 break;
1910 case DISABLE_CHARGING:
1911 rc = smblib_masked_write(chg, USBIN_OPTIONS_2_CFG_REG,
1912 FLOAT_OPTIONS_MASK, FLOAT_DIS_CHGING_CFG_BIT);
1913 break;
1914 case SUSPEND_INPUT:
1915 rc = smblib_masked_write(chg, USBIN_OPTIONS_2_CFG_REG,
1916 FLOAT_OPTIONS_MASK, SUSPEND_FLOAT_CFG_BIT);
1917 break;
1918 default:
1919 rc = 0;
1920 break;
1921 }
1922
1923 if (rc < 0) {
1924 dev_err(chg->dev, "Couldn't configure float charger options rc=%d\n",
1925 rc);
1926 return rc;
1927 }
1928
1929 rc = smblib_read(chg, USBIN_OPTIONS_2_CFG_REG, &chg->float_cfg);
1930 if (rc < 0) {
1931 dev_err(chg->dev, "Couldn't read float charger options rc=%d\n",
1932 rc);
1933 return rc;
1934 }
1935
1936 switch (chip->dt.chg_inhibit_thr_mv) {
1937 case 50:
1938 rc = smblib_masked_write(chg, CHARGE_INHIBIT_THRESHOLD_CFG_REG,
1939 CHARGE_INHIBIT_THRESHOLD_MASK,
1940 INHIBIT_ANALOG_VFLT_MINUS_50MV);
1941 break;
1942 case 100:
1943 rc = smblib_masked_write(chg, CHARGE_INHIBIT_THRESHOLD_CFG_REG,
1944 CHARGE_INHIBIT_THRESHOLD_MASK,
1945 INHIBIT_ANALOG_VFLT_MINUS_100MV);
1946 break;
1947 case 200:
1948 rc = smblib_masked_write(chg, CHARGE_INHIBIT_THRESHOLD_CFG_REG,
1949 CHARGE_INHIBIT_THRESHOLD_MASK,
1950 INHIBIT_ANALOG_VFLT_MINUS_200MV);
1951 break;
1952 case 300:
1953 rc = smblib_masked_write(chg, CHARGE_INHIBIT_THRESHOLD_CFG_REG,
1954 CHARGE_INHIBIT_THRESHOLD_MASK,
1955 INHIBIT_ANALOG_VFLT_MINUS_300MV);
1956 break;
1957 case 0:
1958 rc = smblib_masked_write(chg, CHGR_CFG2_REG,
1959 CHARGER_INHIBIT_BIT, 0);
1960 default:
1961 break;
1962 }
1963
1964 if (rc < 0) {
1965 dev_err(chg->dev, "Couldn't configure charge inhibit threshold rc=%d\n",
1966 rc);
1967 return rc;
1968 }
1969
Anirudh Ghayal1380d312018-02-23 00:01:43 +05301970 rc = smblib_masked_write(chg, CHGR_CFG2_REG, RECHG_MASK,
1971 (chip->dt.auto_recharge_vbat_mv != -EINVAL) ?
1972 VBAT_BASED_RECHG_BIT : 0);
Harry Yang4b7db0f2017-11-27 10:50:44 -08001973 if (rc < 0) {
Anirudh Ghayal1380d312018-02-23 00:01:43 +05301974 dev_err(chg->dev, "Couldn't configure VBAT-rechg CHG_CFG2_REG rc=%d\n",
Harry Yang4b7db0f2017-11-27 10:50:44 -08001975 rc);
1976 return rc;
1977 }
1978
Anirudh Ghayal1380d312018-02-23 00:01:43 +05301979 /* program the auto-recharge VBAT threshold */
1980 if (chip->dt.auto_recharge_vbat_mv != -EINVAL) {
1981 u32 temp = VBAT_TO_VRAW_ADC(chip->dt.auto_recharge_vbat_mv);
1982
1983 temp = ((temp & 0xFF00) >> 8) | ((temp & 0xFF) << 8);
1984 rc = smblib_batch_write(chg,
1985 CHGR_ADC_RECHARGE_THRESHOLD_MSB_REG, (u8 *)&temp, 2);
1986 if (rc < 0) {
1987 dev_err(chg->dev, "Couldn't configure ADC_RECHARGE_THRESHOLD REG rc=%d\n",
1988 rc);
1989 return rc;
1990 }
1991 /* Program the sample count for VBAT based recharge to 3 */
1992 rc = smblib_masked_write(chg, CHGR_NO_SAMPLE_TERM_RCHG_CFG_REG,
1993 NO_OF_SAMPLE_FOR_RCHG,
1994 2 << NO_OF_SAMPLE_FOR_RCHG_SHIFT);
1995 if (rc < 0) {
1996 dev_err(chg->dev, "Couldn't configure CHGR_NO_SAMPLE_FOR_TERM_RCHG_CFG rc=%d\n",
1997 rc);
1998 return rc;
1999 }
2000 }
2001
2002 rc = smblib_masked_write(chg, CHGR_CFG2_REG, RECHG_MASK,
2003 (chip->dt.auto_recharge_soc != -EINVAL) ?
2004 SOC_BASED_RECHG_BIT : VBAT_BASED_RECHG_BIT);
2005 if (rc < 0) {
2006 dev_err(chg->dev, "Couldn't configure SOC-rechg CHG_CFG2_REG rc=%d\n",
2007 rc);
2008 return rc;
2009 }
2010
2011 /* program the auto-recharge threshold */
2012 if (chip->dt.auto_recharge_soc != -EINVAL) {
2013 rc = smblib_write(chg, CHARGE_RCHG_SOC_THRESHOLD_CFG_REG,
2014 (chip->dt.auto_recharge_soc * 255) / 100);
2015 if (rc < 0) {
2016 dev_err(chg->dev, "Couldn't configure CHG_RCHG_SOC_REG rc=%d\n",
2017 rc);
2018 return rc;
2019 }
2020 /* Program the sample count for SOC based recharge to 1 */
2021 rc = smblib_masked_write(chg, CHGR_NO_SAMPLE_TERM_RCHG_CFG_REG,
2022 NO_OF_SAMPLE_FOR_RCHG, 0);
2023 if (rc < 0) {
2024 dev_err(chg->dev, "Couldn't configure CHGR_NO_SAMPLE_FOR_TERM_RCHG_CFG rc=%d\n",
2025 rc);
2026 return rc;
2027 }
2028 }
2029
Harry Yang4b7db0f2017-11-27 10:50:44 -08002030 if (chg->sw_jeita_enabled) {
2031 rc = smblib_disable_hw_jeita(chg, true);
2032 if (rc < 0) {
2033 dev_err(chg->dev, "Couldn't set hw jeita rc=%d\n", rc);
2034 return rc;
2035 }
2036 }
2037
Ashay Jaiswala55b7ed2018-03-23 17:23:48 +05302038 rc = smblib_configure_wdog(chg,
2039 chg->step_chg_enabled || chg->sw_jeita_enabled);
2040 if (rc < 0) {
2041 dev_err(chg->dev, "Couldn't configure watchdog rc=%d\n",
2042 rc);
2043 return rc;
2044 }
2045
Ashay Jaiswal0de6fb92018-06-12 17:23:45 +05302046 if (chg->connector_pull_up != -EINVAL) {
2047 rc = smb5_configure_internal_pull(chg, CONN_THERM,
2048 get_valid_pullup(chg->connector_pull_up));
2049 if (rc < 0) {
2050 dev_err(chg->dev,
2051 "Couldn't configure CONN_THERM pull-up rc=%d\n",
2052 rc);
2053 return rc;
2054 }
2055 }
2056
Harry Yang4b7db0f2017-11-27 10:50:44 -08002057 return rc;
2058}
2059
2060static int smb5_post_init(struct smb5 *chip)
2061{
2062 struct smb_charger *chg = &chip->chg;
2063 union power_supply_propval pval;
2064 int rc;
2065
2066 /*
2067 * In case the usb path is suspended, we would have missed disabling
2068 * the icl change interrupt because the interrupt could have been
2069 * not requested
2070 */
2071 rerun_election(chg->usb_icl_votable);
2072
2073 /* configure power role for dual-role */
2074 pval.intval = POWER_SUPPLY_TYPEC_PR_DUAL;
2075 rc = smblib_set_prop_typec_power_role(chg, &pval);
2076 if (rc < 0) {
Ashay Jaiswala9e10912018-02-02 14:03:35 +05302077 dev_err(chg->dev, "Couldn't configure DRP role rc=%d\n",
2078 rc);
Harry Yang4b7db0f2017-11-27 10:50:44 -08002079 return rc;
2080 }
2081
2082 rerun_election(chg->usb_irq_enable_votable);
2083
2084 return 0;
2085}
2086
2087/****************************
2088 * DETERMINE INITIAL STATUS *
2089 ****************************/
2090
2091static int smb5_determine_initial_status(struct smb5 *chip)
2092{
2093 struct smb_irq_data irq_data = {chip, "determine-initial-status"};
2094 struct smb_charger *chg = &chip->chg;
Harry Yang6afaea22018-03-26 19:11:07 -07002095 union power_supply_propval val;
2096 int rc;
2097
2098 rc = smblib_get_prop_usb_present(chg, &val);
2099 if (rc < 0) {
2100 pr_err("Couldn't get usb present rc=%d\n", rc);
2101 return rc;
2102 }
2103 chg->early_usb_attach = val.intval;
Harry Yang4b7db0f2017-11-27 10:50:44 -08002104
2105 if (chg->bms_psy)
2106 smblib_suspend_on_debug_battery(chg);
Ashay Jaiswala9e10912018-02-02 14:03:35 +05302107
Harry Yang4b7db0f2017-11-27 10:50:44 -08002108 usb_plugin_irq_handler(0, &irq_data);
Harry Yang6afaea22018-03-26 19:11:07 -07002109 typec_attach_detach_irq_handler(0, &irq_data);
Harry Yang4b7db0f2017-11-27 10:50:44 -08002110 typec_state_change_irq_handler(0, &irq_data);
2111 usb_source_change_irq_handler(0, &irq_data);
2112 chg_state_change_irq_handler(0, &irq_data);
2113 icl_change_irq_handler(0, &irq_data);
2114 batt_temp_changed_irq_handler(0, &irq_data);
2115 wdog_bark_irq_handler(0, &irq_data);
Ashay Jaiswala9e10912018-02-02 14:03:35 +05302116 typec_or_rid_detection_change_irq_handler(0, &irq_data);
Harry Yang4b7db0f2017-11-27 10:50:44 -08002117
2118 return 0;
2119}
2120
2121/**************************
2122 * INTERRUPT REGISTRATION *
2123 **************************/
2124
2125static struct smb_irq_info smb5_irqs[] = {
2126 /* CHARGER IRQs */
2127 [CHGR_ERROR_IRQ] = {
2128 .name = "chgr-error",
2129 .handler = default_irq_handler,
2130 },
2131 [CHG_STATE_CHANGE_IRQ] = {
2132 .name = "chg-state-change",
2133 .handler = chg_state_change_irq_handler,
Ashay Jaiswal48015c32018-03-07 18:25:43 +05302134 .wake = true,
Harry Yang4b7db0f2017-11-27 10:50:44 -08002135 },
2136 [STEP_CHG_STATE_CHANGE_IRQ] = {
2137 .name = "step-chg-state-change",
Harry Yang4b7db0f2017-11-27 10:50:44 -08002138 },
2139 [STEP_CHG_SOC_UPDATE_FAIL_IRQ] = {
2140 .name = "step-chg-soc-update-fail",
Harry Yang4b7db0f2017-11-27 10:50:44 -08002141 },
2142 [STEP_CHG_SOC_UPDATE_REQ_IRQ] = {
2143 .name = "step-chg-soc-update-req",
Harry Yang4b7db0f2017-11-27 10:50:44 -08002144 },
2145 [FG_FVCAL_QUALIFIED_IRQ] = {
2146 .name = "fg-fvcal-qualified",
Harry Yang4b7db0f2017-11-27 10:50:44 -08002147 },
2148 [VPH_ALARM_IRQ] = {
2149 .name = "vph-alarm",
Harry Yang4b7db0f2017-11-27 10:50:44 -08002150 },
2151 [VPH_DROP_PRECHG_IRQ] = {
2152 .name = "vph-drop-prechg",
Harry Yang4b7db0f2017-11-27 10:50:44 -08002153 },
2154 /* DCDC IRQs */
2155 [OTG_FAIL_IRQ] = {
2156 .name = "otg-fail",
2157 .handler = default_irq_handler,
2158 },
2159 [OTG_OC_DISABLE_SW_IRQ] = {
2160 .name = "otg-oc-disable-sw",
Harry Yang4b7db0f2017-11-27 10:50:44 -08002161 },
2162 [OTG_OC_HICCUP_IRQ] = {
2163 .name = "otg-oc-hiccup",
Harry Yang4b7db0f2017-11-27 10:50:44 -08002164 },
2165 [BSM_ACTIVE_IRQ] = {
2166 .name = "bsm-active",
Harry Yang4b7db0f2017-11-27 10:50:44 -08002167 },
2168 [HIGH_DUTY_CYCLE_IRQ] = {
2169 .name = "high-duty-cycle",
2170 .handler = high_duty_cycle_irq_handler,
Ashay Jaiswal48015c32018-03-07 18:25:43 +05302171 .wake = true,
Harry Yang4b7db0f2017-11-27 10:50:44 -08002172 },
2173 [INPUT_CURRENT_LIMITING_IRQ] = {
2174 .name = "input-current-limiting",
2175 .handler = default_irq_handler,
2176 },
2177 [CONCURRENT_MODE_DISABLE_IRQ] = {
2178 .name = "concurrent-mode-disable",
Harry Yang4b7db0f2017-11-27 10:50:44 -08002179 },
2180 [SWITCHER_POWER_OK_IRQ] = {
2181 .name = "switcher-power-ok",
2182 .handler = switcher_power_ok_irq_handler,
2183 },
2184 /* BATTERY IRQs */
2185 [BAT_TEMP_IRQ] = {
2186 .name = "bat-temp",
2187 .handler = batt_temp_changed_irq_handler,
Ashay Jaiswal48015c32018-03-07 18:25:43 +05302188 .wake = true,
Harry Yang4b7db0f2017-11-27 10:50:44 -08002189 },
2190 [ALL_CHNL_CONV_DONE_IRQ] = {
2191 .name = "all-chnl-conv-done",
Harry Yang4b7db0f2017-11-27 10:50:44 -08002192 },
2193 [BAT_OV_IRQ] = {
2194 .name = "bat-ov",
2195 .handler = batt_psy_changed_irq_handler,
2196 },
2197 [BAT_LOW_IRQ] = {
2198 .name = "bat-low",
2199 .handler = batt_psy_changed_irq_handler,
2200 },
2201 [BAT_THERM_OR_ID_MISSING_IRQ] = {
2202 .name = "bat-therm-or-id-missing",
2203 .handler = batt_psy_changed_irq_handler,
2204 },
2205 [BAT_TERMINAL_MISSING_IRQ] = {
2206 .name = "bat-terminal-missing",
2207 .handler = batt_psy_changed_irq_handler,
2208 },
2209 [BUCK_OC_IRQ] = {
2210 .name = "buck-oc",
Harry Yang4b7db0f2017-11-27 10:50:44 -08002211 },
2212 [VPH_OV_IRQ] = {
2213 .name = "vph-ov",
Harry Yang4b7db0f2017-11-27 10:50:44 -08002214 },
2215 /* USB INPUT IRQs */
2216 [USBIN_COLLAPSE_IRQ] = {
2217 .name = "usbin-collapse",
2218 .handler = default_irq_handler,
2219 },
2220 [USBIN_VASHDN_IRQ] = {
2221 .name = "usbin-vashdn",
2222 .handler = default_irq_handler,
2223 },
2224 [USBIN_UV_IRQ] = {
2225 .name = "usbin-uv",
2226 .handler = usbin_uv_irq_handler,
Ashay Jaiswale0b3c472018-06-20 23:39:41 +05302227 .wake = true,
2228 .storm_data = {true, 3000, 5},
Harry Yang4b7db0f2017-11-27 10:50:44 -08002229 },
2230 [USBIN_OV_IRQ] = {
2231 .name = "usbin-ov",
2232 .handler = default_irq_handler,
2233 },
2234 [USBIN_PLUGIN_IRQ] = {
2235 .name = "usbin-plugin",
2236 .handler = usb_plugin_irq_handler,
Ashay Jaiswal48015c32018-03-07 18:25:43 +05302237 .wake = true,
Harry Yang4b7db0f2017-11-27 10:50:44 -08002238 },
2239 [USBIN_REVI_CHANGE_IRQ] = {
2240 .name = "usbin-revi-change",
Harry Yang4b7db0f2017-11-27 10:50:44 -08002241 },
2242 [USBIN_SRC_CHANGE_IRQ] = {
2243 .name = "usbin-src-change",
2244 .handler = usb_source_change_irq_handler,
Ashay Jaiswal48015c32018-03-07 18:25:43 +05302245 .wake = true,
Harry Yang4b7db0f2017-11-27 10:50:44 -08002246 },
2247 [USBIN_ICL_CHANGE_IRQ] = {
2248 .name = "usbin-icl-change",
2249 .handler = icl_change_irq_handler,
Ashay Jaiswal48015c32018-03-07 18:25:43 +05302250 .wake = true,
Harry Yang4b7db0f2017-11-27 10:50:44 -08002251 },
2252 /* DC INPUT IRQs */
2253 [DCIN_VASHDN_IRQ] = {
2254 .name = "dcin-vashdn",
Harry Yang4b7db0f2017-11-27 10:50:44 -08002255 },
2256 [DCIN_UV_IRQ] = {
2257 .name = "dcin-uv",
2258 .handler = default_irq_handler,
2259 },
2260 [DCIN_OV_IRQ] = {
2261 .name = "dcin-ov",
2262 .handler = default_irq_handler,
2263 },
2264 [DCIN_PLUGIN_IRQ] = {
2265 .name = "dcin-plugin",
2266 .handler = dc_plugin_irq_handler,
2267 .wake = true,
2268 },
2269 [DCIN_REVI_IRQ] = {
2270 .name = "dcin-revi",
Harry Yang4b7db0f2017-11-27 10:50:44 -08002271 },
2272 [DCIN_PON_IRQ] = {
2273 .name = "dcin-pon",
2274 .handler = default_irq_handler,
2275 },
2276 [DCIN_EN_IRQ] = {
2277 .name = "dcin-en",
2278 .handler = default_irq_handler,
2279 },
2280 /* TYPEC IRQs */
2281 [TYPEC_OR_RID_DETECTION_CHANGE_IRQ] = {
2282 .name = "typec-or-rid-detect-change",
Ashay Jaiswala9e10912018-02-02 14:03:35 +05302283 .handler = typec_or_rid_detection_change_irq_handler,
Ashay Jaiswal48015c32018-03-07 18:25:43 +05302284 .wake = true,
Harry Yang4b7db0f2017-11-27 10:50:44 -08002285 },
2286 [TYPEC_VPD_DETECT_IRQ] = {
2287 .name = "typec-vpd-detect",
Harry Yang4b7db0f2017-11-27 10:50:44 -08002288 },
2289 [TYPEC_CC_STATE_CHANGE_IRQ] = {
2290 .name = "typec-cc-state-change",
2291 .handler = typec_state_change_irq_handler,
Ashay Jaiswal48015c32018-03-07 18:25:43 +05302292 .wake = true,
Harry Yang4b7db0f2017-11-27 10:50:44 -08002293 },
2294 [TYPEC_VCONN_OC_IRQ] = {
2295 .name = "typec-vconn-oc",
2296 .handler = default_irq_handler,
2297 },
2298 [TYPEC_VBUS_CHANGE_IRQ] = {
2299 .name = "typec-vbus-change",
Harry Yang4b7db0f2017-11-27 10:50:44 -08002300 },
2301 [TYPEC_ATTACH_DETACH_IRQ] = {
2302 .name = "typec-attach-detach",
Harry Yang6afaea22018-03-26 19:11:07 -07002303 .handler = typec_attach_detach_irq_handler,
Harry Yang4b7db0f2017-11-27 10:50:44 -08002304 },
2305 [TYPEC_LEGACY_CABLE_DETECT_IRQ] = {
2306 .name = "typec-legacy-cable-detect",
2307 .handler = default_irq_handler,
2308 },
2309 [TYPEC_TRY_SNK_SRC_DETECT_IRQ] = {
2310 .name = "typec-try-snk-src-detect",
Harry Yang4b7db0f2017-11-27 10:50:44 -08002311 },
2312 /* MISCELLANEOUS IRQs */
2313 [WDOG_SNARL_IRQ] = {
2314 .name = "wdog-snarl",
Harry Yang4b7db0f2017-11-27 10:50:44 -08002315 },
2316 [WDOG_BARK_IRQ] = {
2317 .name = "wdog-bark",
2318 .handler = wdog_bark_irq_handler,
Ashay Jaiswala55b7ed2018-03-23 17:23:48 +05302319 .wake = true,
Harry Yang4b7db0f2017-11-27 10:50:44 -08002320 },
2321 [AICL_FAIL_IRQ] = {
2322 .name = "aicl-fail",
Harry Yang4b7db0f2017-11-27 10:50:44 -08002323 },
2324 [AICL_DONE_IRQ] = {
2325 .name = "aicl-done",
2326 .handler = default_irq_handler,
2327 },
2328 [SMB_EN_IRQ] = {
2329 .name = "smb-en",
Harry Yang4b7db0f2017-11-27 10:50:44 -08002330 },
2331 [IMP_TRIGGER_IRQ] = {
2332 .name = "imp-trigger",
Harry Yang4b7db0f2017-11-27 10:50:44 -08002333 },
2334 [TEMP_CHANGE_IRQ] = {
2335 .name = "temp-change",
Harry Yang4b7db0f2017-11-27 10:50:44 -08002336 },
2337 [TEMP_CHANGE_SMB_IRQ] = {
2338 .name = "temp-change-smb",
Harry Yang4b7db0f2017-11-27 10:50:44 -08002339 },
Ashay Jaiswal09feab82018-02-12 12:33:18 +05302340 /* FLASH */
2341 [VREG_OK_IRQ] = {
2342 .name = "vreg-ok",
Ashay Jaiswal09feab82018-02-12 12:33:18 +05302343 },
2344 [ILIM_S2_IRQ] = {
2345 .name = "ilim2-s2",
2346 .handler = schgm_flash_ilim2_irq_handler,
2347 },
2348 [ILIM_S1_IRQ] = {
2349 .name = "ilim1-s1",
Ashay Jaiswal09feab82018-02-12 12:33:18 +05302350 },
2351 [VOUT_DOWN_IRQ] = {
2352 .name = "vout-down",
Ashay Jaiswal09feab82018-02-12 12:33:18 +05302353 },
2354 [VOUT_UP_IRQ] = {
2355 .name = "vout-up",
Ashay Jaiswal09feab82018-02-12 12:33:18 +05302356 },
2357 [FLASH_STATE_CHANGE_IRQ] = {
2358 .name = "flash-state-change",
2359 .handler = schgm_flash_state_change_irq_handler,
2360 },
2361 [TORCH_REQ_IRQ] = {
2362 .name = "torch-req",
Ashay Jaiswal09feab82018-02-12 12:33:18 +05302363 },
2364 [FLASH_EN_IRQ] = {
2365 .name = "flash-en",
Ashay Jaiswal09feab82018-02-12 12:33:18 +05302366 },
Harry Yang4b7db0f2017-11-27 10:50:44 -08002367};
2368
2369static int smb5_get_irq_index_byname(const char *irq_name)
2370{
2371 int i;
2372
2373 for (i = 0; i < ARRAY_SIZE(smb5_irqs); i++) {
2374 if (strcmp(smb5_irqs[i].name, irq_name) == 0)
2375 return i;
2376 }
2377
2378 return -ENOENT;
2379}
2380
2381static int smb5_request_interrupt(struct smb5 *chip,
2382 struct device_node *node, const char *irq_name)
2383{
2384 struct smb_charger *chg = &chip->chg;
2385 int rc, irq, irq_index;
2386 struct smb_irq_data *irq_data;
2387
2388 irq = of_irq_get_byname(node, irq_name);
2389 if (irq < 0) {
2390 pr_err("Couldn't get irq %s byname\n", irq_name);
2391 return irq;
2392 }
2393
2394 irq_index = smb5_get_irq_index_byname(irq_name);
2395 if (irq_index < 0) {
2396 pr_err("%s is not a defined irq\n", irq_name);
2397 return irq_index;
2398 }
2399
2400 if (!smb5_irqs[irq_index].handler)
2401 return 0;
2402
2403 irq_data = devm_kzalloc(chg->dev, sizeof(*irq_data), GFP_KERNEL);
2404 if (!irq_data)
2405 return -ENOMEM;
2406
2407 irq_data->parent_data = chip;
2408 irq_data->name = irq_name;
2409 irq_data->storm_data = smb5_irqs[irq_index].storm_data;
2410 mutex_init(&irq_data->storm_data.storm_lock);
2411
2412 rc = devm_request_threaded_irq(chg->dev, irq, NULL,
2413 smb5_irqs[irq_index].handler,
2414 IRQF_ONESHOT, irq_name, irq_data);
2415 if (rc < 0) {
2416 pr_err("Couldn't request irq %d\n", irq);
2417 return rc;
2418 }
2419
2420 smb5_irqs[irq_index].irq = irq;
2421 smb5_irqs[irq_index].irq_data = irq_data;
2422 if (smb5_irqs[irq_index].wake)
2423 enable_irq_wake(irq);
2424
2425 return rc;
2426}
2427
2428static int smb5_request_interrupts(struct smb5 *chip)
2429{
2430 struct smb_charger *chg = &chip->chg;
2431 struct device_node *node = chg->dev->of_node;
2432 struct device_node *child;
2433 int rc = 0;
2434 const char *name;
2435 struct property *prop;
2436
2437 for_each_available_child_of_node(node, child) {
2438 of_property_for_each_string(child, "interrupt-names",
2439 prop, name) {
2440 rc = smb5_request_interrupt(chip, child, name);
2441 if (rc < 0)
2442 return rc;
2443 }
2444 }
2445 if (chg->irq_info[USBIN_ICL_CHANGE_IRQ].irq)
2446 chg->usb_icl_change_irq_enabled = true;
2447
2448 return rc;
2449}
2450
2451static void smb5_free_interrupts(struct smb_charger *chg)
2452{
2453 int i;
2454
2455 for (i = 0; i < ARRAY_SIZE(smb5_irqs); i++) {
2456 if (smb5_irqs[i].irq > 0) {
2457 if (smb5_irqs[i].wake)
2458 disable_irq_wake(smb5_irqs[i].irq);
2459
2460 devm_free_irq(chg->dev, smb5_irqs[i].irq,
2461 smb5_irqs[i].irq_data);
2462 }
2463 }
2464}
2465
2466static void smb5_disable_interrupts(struct smb_charger *chg)
2467{
2468 int i;
2469
2470 for (i = 0; i < ARRAY_SIZE(smb5_irqs); i++) {
2471 if (smb5_irqs[i].irq > 0)
2472 disable_irq(smb5_irqs[i].irq);
2473 }
2474}
2475
2476#if defined(CONFIG_DEBUG_FS)
2477
2478static int force_batt_psy_update_write(void *data, u64 val)
2479{
2480 struct smb_charger *chg = data;
2481
2482 power_supply_changed(chg->batt_psy);
2483 return 0;
2484}
2485DEFINE_SIMPLE_ATTRIBUTE(force_batt_psy_update_ops, NULL,
2486 force_batt_psy_update_write, "0x%02llx\n");
2487
2488static int force_usb_psy_update_write(void *data, u64 val)
2489{
2490 struct smb_charger *chg = data;
2491
2492 power_supply_changed(chg->usb_psy);
2493 return 0;
2494}
2495DEFINE_SIMPLE_ATTRIBUTE(force_usb_psy_update_ops, NULL,
2496 force_usb_psy_update_write, "0x%02llx\n");
2497
2498static int force_dc_psy_update_write(void *data, u64 val)
2499{
2500 struct smb_charger *chg = data;
2501
2502 power_supply_changed(chg->dc_psy);
2503 return 0;
2504}
2505DEFINE_SIMPLE_ATTRIBUTE(force_dc_psy_update_ops, NULL,
2506 force_dc_psy_update_write, "0x%02llx\n");
2507
2508static void smb5_create_debugfs(struct smb5 *chip)
2509{
2510 struct dentry *file;
2511
2512 chip->dfs_root = debugfs_create_dir("charger", NULL);
2513 if (IS_ERR_OR_NULL(chip->dfs_root)) {
2514 pr_err("Couldn't create charger debugfs rc=%ld\n",
2515 (long)chip->dfs_root);
2516 return;
2517 }
2518
2519 file = debugfs_create_file("force_batt_psy_update", 0600,
2520 chip->dfs_root, chip, &force_batt_psy_update_ops);
2521 if (IS_ERR_OR_NULL(file))
2522 pr_err("Couldn't create force_batt_psy_update file rc=%ld\n",
2523 (long)file);
2524
2525 file = debugfs_create_file("force_usb_psy_update", 0600,
2526 chip->dfs_root, chip, &force_usb_psy_update_ops);
2527 if (IS_ERR_OR_NULL(file))
2528 pr_err("Couldn't create force_usb_psy_update file rc=%ld\n",
2529 (long)file);
2530
2531 file = debugfs_create_file("force_dc_psy_update", 0600,
2532 chip->dfs_root, chip, &force_dc_psy_update_ops);
2533 if (IS_ERR_OR_NULL(file))
2534 pr_err("Couldn't create force_dc_psy_update file rc=%ld\n",
2535 (long)file);
2536}
2537
2538#else
2539
2540static void smb5_create_debugfs(struct smb5 *chip)
2541{}
2542
2543#endif
2544
2545static int smb5_show_charger_status(struct smb5 *chip)
2546{
2547 struct smb_charger *chg = &chip->chg;
2548 union power_supply_propval val;
2549 int usb_present, batt_present, batt_health, batt_charge_type;
2550 int rc;
2551
2552 rc = smblib_get_prop_usb_present(chg, &val);
2553 if (rc < 0) {
2554 pr_err("Couldn't get usb present rc=%d\n", rc);
2555 return rc;
2556 }
2557 usb_present = val.intval;
2558
2559 rc = smblib_get_prop_batt_present(chg, &val);
2560 if (rc < 0) {
2561 pr_err("Couldn't get batt present rc=%d\n", rc);
2562 return rc;
2563 }
2564 batt_present = val.intval;
2565
2566 rc = smblib_get_prop_batt_health(chg, &val);
2567 if (rc < 0) {
2568 pr_err("Couldn't get batt health rc=%d\n", rc);
2569 val.intval = POWER_SUPPLY_HEALTH_UNKNOWN;
2570 }
2571 batt_health = val.intval;
2572
2573 rc = smblib_get_prop_batt_charge_type(chg, &val);
2574 if (rc < 0) {
2575 pr_err("Couldn't get batt charge type rc=%d\n", rc);
2576 return rc;
2577 }
2578 batt_charge_type = val.intval;
2579
2580 pr_info("SMB5 status - usb:present=%d type=%d batt:present = %d health = %d charge = %d\n",
2581 usb_present, chg->real_charger_type,
2582 batt_present, batt_health, batt_charge_type);
2583 return rc;
2584}
2585
2586static int smb5_probe(struct platform_device *pdev)
2587{
2588 struct smb5 *chip;
2589 struct smb_charger *chg;
2590 int rc = 0;
2591
2592 chip = devm_kzalloc(&pdev->dev, sizeof(*chip), GFP_KERNEL);
2593 if (!chip)
2594 return -ENOMEM;
2595
2596 chg = &chip->chg;
2597 chg->dev = &pdev->dev;
Harry Yang4b7db0f2017-11-27 10:50:44 -08002598 chg->debug_mask = &__debug_mask;
Harry Yang6afaea22018-03-26 19:11:07 -07002599 chg->pd_disabled = &__pd_disabled;
Harry Yang4b7db0f2017-11-27 10:50:44 -08002600 chg->weak_chg_icl_ua = &__weak_chg_icl_ua;
2601 chg->mode = PARALLEL_MASTER;
2602 chg->irq_info = smb5_irqs;
2603 chg->die_health = -EINVAL;
Ashay Jaiswala9e10912018-02-02 14:03:35 +05302604 chg->otg_present = false;
Harry Yang4b7db0f2017-11-27 10:50:44 -08002605
2606 chg->regmap = dev_get_regmap(chg->dev->parent, NULL);
2607 if (!chg->regmap) {
2608 pr_err("parent regmap is missing\n");
2609 return -EINVAL;
2610 }
2611
Ashay Jaiswala9e10912018-02-02 14:03:35 +05302612 rc = smb5_chg_config_init(chip);
2613 if (rc < 0) {
2614 if (rc != -EPROBE_DEFER)
2615 pr_err("Couldn't setup chg_config rc=%d\n", rc);
2616 return rc;
Harry Yang4b7db0f2017-11-27 10:50:44 -08002617 }
2618
Ashay Jaiswalb2b06fe2018-06-07 18:35:21 +05302619 rc = smb5_parse_dt(chip);
2620 if (rc < 0) {
2621 pr_err("Couldn't parse device tree rc=%d\n", rc);
2622 return rc;
2623 }
2624
Harry Yang4b7db0f2017-11-27 10:50:44 -08002625 rc = smblib_init(chg);
2626 if (rc < 0) {
2627 pr_err("Smblib_init failed rc=%d\n", rc);
Ashay Jaiswala9e10912018-02-02 14:03:35 +05302628 return rc;
Harry Yang4b7db0f2017-11-27 10:50:44 -08002629 }
2630
2631 /* set driver data before resources request it */
2632 platform_set_drvdata(pdev, chip);
2633
2634 rc = smb5_init_vbus_regulator(chip);
2635 if (rc < 0) {
2636 pr_err("Couldn't initialize vbus regulator rc=%d\n",
2637 rc);
2638 goto cleanup;
2639 }
2640
2641 rc = smb5_init_vconn_regulator(chip);
2642 if (rc < 0) {
2643 pr_err("Couldn't initialize vconn regulator rc=%d\n",
2644 rc);
2645 goto cleanup;
2646 }
2647
2648 /* extcon registration */
2649 chg->extcon = devm_extcon_dev_allocate(chg->dev, smblib_extcon_cable);
2650 if (IS_ERR(chg->extcon)) {
2651 rc = PTR_ERR(chg->extcon);
2652 dev_err(chg->dev, "failed to allocate extcon device rc=%d\n",
2653 rc);
2654 goto cleanup;
2655 }
2656
2657 rc = devm_extcon_dev_register(chg->dev, chg->extcon);
2658 if (rc < 0) {
2659 dev_err(chg->dev, "failed to register extcon device rc=%d\n",
2660 rc);
2661 goto cleanup;
2662 }
2663
2664 rc = smb5_init_hw(chip);
2665 if (rc < 0) {
2666 pr_err("Couldn't initialize hardware rc=%d\n", rc);
2667 goto cleanup;
2668 }
2669
Ashay Jaiswala9e10912018-02-02 14:03:35 +05302670 if (chg->smb_version == PM855B_SUBTYPE) {
2671 rc = smb5_init_dc_psy(chip);
2672 if (rc < 0) {
2673 pr_err("Couldn't initialize dc psy rc=%d\n", rc);
2674 goto cleanup;
2675 }
Harry Yang4b7db0f2017-11-27 10:50:44 -08002676 }
2677
2678 rc = smb5_init_usb_psy(chip);
2679 if (rc < 0) {
2680 pr_err("Couldn't initialize usb psy rc=%d\n", rc);
2681 goto cleanup;
2682 }
2683
2684 rc = smb5_init_usb_main_psy(chip);
2685 if (rc < 0) {
2686 pr_err("Couldn't initialize usb main psy rc=%d\n", rc);
2687 goto cleanup;
2688 }
2689
2690 rc = smb5_init_usb_port_psy(chip);
2691 if (rc < 0) {
2692 pr_err("Couldn't initialize usb pc_port psy rc=%d\n", rc);
2693 goto cleanup;
2694 }
2695
2696 rc = smb5_init_batt_psy(chip);
2697 if (rc < 0) {
2698 pr_err("Couldn't initialize batt psy rc=%d\n", rc);
2699 goto cleanup;
2700 }
2701
2702 rc = smb5_determine_initial_status(chip);
2703 if (rc < 0) {
2704 pr_err("Couldn't determine initial status rc=%d\n",
2705 rc);
2706 goto cleanup;
2707 }
2708
2709 rc = smb5_request_interrupts(chip);
2710 if (rc < 0) {
2711 pr_err("Couldn't request interrupts rc=%d\n", rc);
2712 goto cleanup;
2713 }
2714
2715 rc = smb5_post_init(chip);
2716 if (rc < 0) {
2717 pr_err("Failed in post init rc=%d\n", rc);
Ashay Jaiswala9e10912018-02-02 14:03:35 +05302718 goto free_irq;
Harry Yang4b7db0f2017-11-27 10:50:44 -08002719 }
2720
2721 smb5_create_debugfs(chip);
2722
2723 rc = smb5_show_charger_status(chip);
2724 if (rc < 0) {
2725 pr_err("Failed in getting charger status rc=%d\n", rc);
Ashay Jaiswala9e10912018-02-02 14:03:35 +05302726 goto free_irq;
Harry Yang4b7db0f2017-11-27 10:50:44 -08002727 }
2728
2729 device_init_wakeup(chg->dev, true);
2730
2731 pr_info("QPNP SMB5 probed successfully\n");
2732
2733 return rc;
2734
Ashay Jaiswala9e10912018-02-02 14:03:35 +05302735free_irq:
Harry Yang4b7db0f2017-11-27 10:50:44 -08002736 smb5_free_interrupts(chg);
Ashay Jaiswala9e10912018-02-02 14:03:35 +05302737cleanup:
Harry Yang4b7db0f2017-11-27 10:50:44 -08002738 smblib_deinit(chg);
2739 platform_set_drvdata(pdev, NULL);
2740
2741 return rc;
2742}
2743
2744static int smb5_remove(struct platform_device *pdev)
2745{
2746 struct smb5 *chip = platform_get_drvdata(pdev);
2747 struct smb_charger *chg = &chip->chg;
2748
Harry Yang6afaea22018-03-26 19:11:07 -07002749 /* force enable APSD */
2750 smblib_masked_write(chg, USBIN_OPTIONS_1_CFG_REG,
2751 BC1P2_SRC_DETECT_BIT, BC1P2_SRC_DETECT_BIT);
2752
Harry Yang4b7db0f2017-11-27 10:50:44 -08002753 smb5_free_interrupts(chg);
2754 smblib_deinit(chg);
2755 platform_set_drvdata(pdev, NULL);
2756 return 0;
2757}
2758
2759static void smb5_shutdown(struct platform_device *pdev)
2760{
2761 struct smb5 *chip = platform_get_drvdata(pdev);
2762 struct smb_charger *chg = &chip->chg;
2763
2764 /* disable all interrupts */
2765 smb5_disable_interrupts(chg);
2766
2767 /* configure power role for UFP */
Ashay Jaiswala9e10912018-02-02 14:03:35 +05302768 if (chg->connector_type == POWER_SUPPLY_CONNECTOR_TYPEC)
Harry Yang4b7db0f2017-11-27 10:50:44 -08002769 smblib_masked_write(chg, TYPE_C_MODE_CFG_REG,
2770 TYPEC_POWER_ROLE_CMD_MASK, EN_SNK_ONLY_BIT);
2771
2772 /* force HVDCP to 5V */
2773 smblib_masked_write(chg, USBIN_OPTIONS_1_CFG_REG,
2774 HVDCP_AUTONOMOUS_MODE_EN_CFG_BIT, 0);
2775 smblib_write(chg, CMD_HVDCP_2_REG, FORCE_5V_BIT);
2776
2777 /* force enable APSD */
2778 smblib_masked_write(chg, USBIN_OPTIONS_1_CFG_REG,
2779 BC1P2_SRC_DETECT_BIT, BC1P2_SRC_DETECT_BIT);
2780}
2781
2782static const struct of_device_id match_table[] = {
2783 { .compatible = "qcom,qpnp-smb5", },
2784 { },
2785};
2786
2787static struct platform_driver smb5_driver = {
2788 .driver = {
2789 .name = "qcom,qpnp-smb5",
2790 .owner = THIS_MODULE,
2791 .of_match_table = match_table,
2792 },
2793 .probe = smb5_probe,
2794 .remove = smb5_remove,
2795 .shutdown = smb5_shutdown,
2796};
2797module_platform_driver(smb5_driver);
2798
2799MODULE_DESCRIPTION("QPNP SMB5 Charger Driver");
2800MODULE_LICENSE("GPL v2");