blob: ab4990aeb4194e9167ee0eb197eb8f2ea7fdc9bf [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 },
98};
99
Harry Yangf7b89902018-03-13 22:37:53 -0700100static struct smb_params smb5_pm855b_params = {
Harry Yang4b7db0f2017-11-27 10:50:44 -0800101 .fcc = {
102 .name = "fast charge current",
103 .reg = CHGR_FAST_CHARGE_CURRENT_CFG_REG,
104 .min_u = 0,
105 .max_u = 8000000,
106 .step_u = 25000,
107 },
108 .fv = {
109 .name = "float voltage",
110 .reg = CHGR_FLOAT_VOLTAGE_CFG_REG,
111 .min_u = 3600000,
112 .max_u = 4790000,
113 .step_u = 10000,
114 },
115 .usb_icl = {
116 .name = "usb input current limit",
117 .reg = USBIN_CURRENT_LIMIT_CFG_REG,
118 .min_u = 0,
119 .max_u = 5000000,
120 .step_u = 50000,
121 },
Harry Yangf7b89902018-03-13 22:37:53 -0700122 .icl_max_stat = {
123 .name = "dcdc icl max status",
124 .reg = ICL_MAX_STATUS_REG,
125 .min_u = 0,
126 .max_u = 5000000,
127 .step_u = 50000,
128 },
Harry Yang4b7db0f2017-11-27 10:50:44 -0800129 .icl_stat = {
Harry Yangf7b89902018-03-13 22:37:53 -0700130 .name = "aicl icl status",
Harry Yang4b7db0f2017-11-27 10:50:44 -0800131 .reg = AICL_ICL_STATUS_REG,
132 .min_u = 0,
133 .max_u = 5000000,
134 .step_u = 50000,
135 },
136 .otg_cl = {
137 .name = "usb otg current limit",
138 .reg = DCDC_OTG_CURRENT_LIMIT_CFG_REG,
139 .min_u = 500000,
140 .max_u = 3000000,
141 .step_u = 500000,
142 },
143 .jeita_cc_comp_hot = {
144 .name = "jeita fcc reduction",
145 .reg = JEITA_CCCOMP_CFG_HOT_REG,
146 .min_u = 0,
147 .max_u = 8000000,
148 .step_u = 25000,
149 .set_proc = NULL,
150 },
151 .jeita_cc_comp_cold = {
152 .name = "jeita fcc reduction",
153 .reg = JEITA_CCCOMP_CFG_COLD_REG,
154 .min_u = 0,
155 .max_u = 8000000,
156 .step_u = 25000,
157 .set_proc = NULL,
158 },
159 .freq_switcher = {
160 .name = "switching frequency",
161 .reg = DCDC_FSW_SEL_REG,
162 .min_u = 1200,
163 .max_u = 2400,
164 .step_u = 400,
165 .set_proc = NULL,
166 },
167};
168
169struct smb_dt_props {
170 int usb_icl_ua;
171 struct device_node *revid_dev_node;
172 enum float_options float_option;
173 int chg_inhibit_thr_mv;
174 bool no_battery;
175 bool hvdcp_disable;
Anirudh Ghayal1380d312018-02-23 00:01:43 +0530176 int auto_recharge_soc;
177 int auto_recharge_vbat_mv;
Harry Yang4b7db0f2017-11-27 10:50:44 -0800178 int wd_bark_time;
179 int batt_profile_fcc_ua;
180 int batt_profile_fv_uv;
181};
182
183struct smb5 {
184 struct smb_charger chg;
185 struct dentry *dfs_root;
186 struct smb_dt_props dt;
187};
188
189static int __debug_mask;
190module_param_named(
191 debug_mask, __debug_mask, int, 0600
192);
193
Harry Yang6afaea22018-03-26 19:11:07 -0700194static int __pd_disabled;
195module_param_named(
196 pd_disabled, __pd_disabled, int, 0600
197);
198
Harry Yang4b7db0f2017-11-27 10:50:44 -0800199static int __weak_chg_icl_ua = 500000;
200module_param_named(
201 weak_chg_icl_ua, __weak_chg_icl_ua, int, 0600
202);
203
Ashay Jaiswal20688262018-04-25 11:45:34 +0530204enum {
205 USBIN_CURRENT,
206 USBIN_VOLTAGE,
207};
208
Ashay Jaiswal0de6fb92018-06-12 17:23:45 +0530209enum {
210 BAT_THERM = 0,
211 MISC_THERM,
212 CONN_THERM,
213 SMB_THERM,
214};
215
Ashay Jaiswala9e10912018-02-02 14:03:35 +0530216#define PMI632_MAX_ICL_UA 3000000
217static int smb5_chg_config_init(struct smb5 *chip)
218{
219 struct smb_charger *chg = &chip->chg;
220 struct pmic_revid_data *pmic_rev_id;
221 struct device_node *revid_dev_node;
222 int rc = 0;
223
224 revid_dev_node = of_parse_phandle(chip->chg.dev->of_node,
225 "qcom,pmic-revid", 0);
226 if (!revid_dev_node) {
227 pr_err("Missing qcom,pmic-revid property\n");
228 return -EINVAL;
229 }
230
231 pmic_rev_id = get_revid_data(revid_dev_node);
232 if (IS_ERR_OR_NULL(pmic_rev_id)) {
233 /*
234 * the revid peripheral must be registered, any failure
235 * here only indicates that the rev-id module has not
236 * probed yet.
237 */
238 rc = -EPROBE_DEFER;
239 goto out;
240 }
241
242 switch (pmic_rev_id->pmic_subtype) {
243 case PM855B_SUBTYPE:
244 chip->chg.smb_version = PM855B_SUBTYPE;
Harry Yangf7b89902018-03-13 22:37:53 -0700245 chg->param = smb5_pm855b_params;
Ashay Jaiswala9e10912018-02-02 14:03:35 +0530246 chg->name = "pm855b_charger";
247 break;
248 case PMI632_SUBTYPE:
249 chip->chg.smb_version = PMI632_SUBTYPE;
250 chg->param = smb5_pmi632_params;
251 chg->use_extcon = true;
252 chg->name = "pmi632_charger";
Ashay Jaiswalc96380de2018-05-16 12:02:36 +0530253 /* PMI632 does not support PD */
Ashay Jaiswalf2ca7092018-05-22 21:33:15 +0530254 chg->pd_not_supported = true;
Ashay Jaiswala9e10912018-02-02 14:03:35 +0530255 chg->hw_max_icl_ua =
256 (chip->dt.usb_icl_ua > 0) ? chip->dt.usb_icl_ua
257 : PMI632_MAX_ICL_UA;
258 chg->chg_freq.freq_5V = 600;
259 chg->chg_freq.freq_6V_8V = 800;
260 chg->chg_freq.freq_9V = 1050;
261 chg->chg_freq.freq_removal = 1050;
262 chg->chg_freq.freq_below_otg_threshold = 800;
263 chg->chg_freq.freq_above_otg_threshold = 800;
264 break;
265 default:
266 pr_err("PMIC subtype %d not supported\n",
267 pmic_rev_id->pmic_subtype);
268 rc = -EINVAL;
269 }
270
271out:
272 of_node_put(revid_dev_node);
273 return rc;
274}
275
Ashay Jaiswal0de6fb92018-06-12 17:23:45 +0530276#define PULL_NO_PULL 0
277#define PULL_30K 30
278#define PULL_100K 100
279#define PULL_400K 400
280static int get_valid_pullup(int pull_up)
281{
282 int pull;
283
284 /* pull up can only be 0/30K/100K/400K) */
285 switch (pull_up) {
286 case PULL_NO_PULL:
287 pull = INTERNAL_PULL_NO_PULL;
288 break;
289 case PULL_30K:
290 pull = INTERNAL_PULL_30K_PULL;
291 break;
292 case PULL_100K:
293 pull = INTERNAL_PULL_100K_PULL;
294 break;
295 case PULL_400K:
296 pull = INTERNAL_PULL_400K_PULL;
297 break;
298 default:
299 pull = INTERNAL_PULL_100K_PULL;
300 }
301
302 return pull;
303}
304
305#define INTERNAL_PULL_UP_MASK 0x3
306static int smb5_configure_internal_pull(struct smb_charger *chg, int type,
307 int pull)
308{
309 int rc;
310 int shift = type * 2;
311 u8 mask = INTERNAL_PULL_UP_MASK << shift;
312 u8 val = pull << shift;
313
314 rc = smblib_masked_write(chg, BATIF_ADC_INTERNAL_PULL_UP_REG,
315 mask, val);
316 if (rc < 0)
317 dev_err(chg->dev,
318 "Couldn't configure ADC pull-up reg rc=%d\n", rc);
319
320 return rc;
321}
322
Harry Yang4b7db0f2017-11-27 10:50:44 -0800323#define MICRO_1P5A 1500000
Ashay Jaiswalb2b06fe2018-06-07 18:35:21 +0530324#define MICRO_1PA 1000000
Harry Yang4b7db0f2017-11-27 10:50:44 -0800325#define MICRO_P1A 100000
326#define OTG_DEFAULT_DEGLITCH_TIME_MS 50
327#define MIN_WD_BARK_TIME 16
328#define DEFAULT_WD_BARK_TIME 64
329#define BITE_WDOG_TIMEOUT_8S 0x3
330#define BARK_WDOG_TIMEOUT_MASK GENMASK(3, 2)
331#define BARK_WDOG_TIMEOUT_SHIFT 2
332static int smb5_parse_dt(struct smb5 *chip)
333{
334 struct smb_charger *chg = &chip->chg;
335 struct device_node *node = chg->dev->of_node;
336 int rc, byte_len;
337
338 if (!node) {
339 pr_err("device tree node missing\n");
340 return -EINVAL;
341 }
342
343 chg->step_chg_enabled = of_property_read_bool(node,
344 "qcom,step-charging-enable");
345
346 chg->sw_jeita_enabled = of_property_read_bool(node,
347 "qcom,sw-jeita-enable");
348
349 rc = of_property_read_u32(node, "qcom,wd-bark-time-secs",
350 &chip->dt.wd_bark_time);
351 if (rc < 0 || chip->dt.wd_bark_time < MIN_WD_BARK_TIME)
352 chip->dt.wd_bark_time = DEFAULT_WD_BARK_TIME;
353
354 chip->dt.no_battery = of_property_read_bool(node,
355 "qcom,batteryless-platform");
356
357 rc = of_property_read_u32(node,
358 "qcom,fcc-max-ua", &chip->dt.batt_profile_fcc_ua);
359 if (rc < 0)
360 chip->dt.batt_profile_fcc_ua = -EINVAL;
361
362 rc = of_property_read_u32(node,
363 "qcom,fv-max-uv", &chip->dt.batt_profile_fv_uv);
364 if (rc < 0)
365 chip->dt.batt_profile_fv_uv = -EINVAL;
366
367 rc = of_property_read_u32(node,
368 "qcom,usb-icl-ua", &chip->dt.usb_icl_ua);
369 if (rc < 0)
370 chip->dt.usb_icl_ua = -EINVAL;
371
372 rc = of_property_read_u32(node,
373 "qcom,otg-cl-ua", &chg->otg_cl_ua);
374 if (rc < 0)
Ashay Jaiswalb2b06fe2018-06-07 18:35:21 +0530375 chg->otg_cl_ua = (chip->chg.smb_version == PMI632_SUBTYPE) ?
376 MICRO_1PA : MICRO_1P5A;
Harry Yang4b7db0f2017-11-27 10:50:44 -0800377
378 if (of_find_property(node, "qcom,thermal-mitigation", &byte_len)) {
379 chg->thermal_mitigation = devm_kzalloc(chg->dev, byte_len,
380 GFP_KERNEL);
381
382 if (chg->thermal_mitigation == NULL)
383 return -ENOMEM;
384
385 chg->thermal_levels = byte_len / sizeof(u32);
386 rc = of_property_read_u32_array(node,
387 "qcom,thermal-mitigation",
388 chg->thermal_mitigation,
389 chg->thermal_levels);
390 if (rc < 0) {
391 dev_err(chg->dev,
392 "Couldn't read threm limits rc = %d\n", rc);
393 return rc;
394 }
395 }
396
397 rc = of_property_read_u32(node, "qcom,float-option",
398 &chip->dt.float_option);
399 if (!rc && (chip->dt.float_option < 0 || chip->dt.float_option > 4)) {
400 pr_err("qcom,float-option is out of range [0, 4]\n");
401 return -EINVAL;
402 }
403
404 chip->dt.hvdcp_disable = of_property_read_bool(node,
405 "qcom,hvdcp-disable");
406
407
408 rc = of_property_read_u32(node, "qcom,chg-inhibit-threshold-mv",
409 &chip->dt.chg_inhibit_thr_mv);
410 if (!rc && (chip->dt.chg_inhibit_thr_mv < 0 ||
411 chip->dt.chg_inhibit_thr_mv > 300)) {
412 pr_err("qcom,chg-inhibit-threshold-mv is incorrect\n");
413 return -EINVAL;
414 }
415
Anirudh Ghayal1380d312018-02-23 00:01:43 +0530416 chip->dt.auto_recharge_soc = -EINVAL;
417 rc = of_property_read_u32(node, "qcom,auto-recharge-soc",
418 &chip->dt.auto_recharge_soc);
419 if (!rc && (chip->dt.auto_recharge_soc < 0 ||
420 chip->dt.auto_recharge_soc > 100)) {
421 pr_err("qcom,auto-recharge-soc is incorrect\n");
422 return -EINVAL;
423 }
424 chg->auto_recharge_soc = chip->dt.auto_recharge_soc;
425
426 chip->dt.auto_recharge_vbat_mv = -EINVAL;
427 rc = of_property_read_u32(node, "qcom,auto-recharge-vbat-mv",
428 &chip->dt.auto_recharge_vbat_mv);
429 if (!rc && (chip->dt.auto_recharge_vbat_mv < 0)) {
430 pr_err("qcom,auto-recharge-vbat-mv is incorrect\n");
431 return -EINVAL;
432 }
Harry Yang4b7db0f2017-11-27 10:50:44 -0800433
Harry Yang4b7db0f2017-11-27 10:50:44 -0800434 chg->dcp_icl_ua = chip->dt.usb_icl_ua;
435
436 chg->suspend_input_on_debug_batt = of_property_read_bool(node,
437 "qcom,suspend-input-on-debug-batt");
438
439 rc = of_property_read_u32(node, "qcom,otg-deglitch-time-ms",
440 &chg->otg_delay_ms);
441 if (rc < 0)
442 chg->otg_delay_ms = OTG_DEFAULT_DEGLITCH_TIME_MS;
443
Ashay Jaiswal0de6fb92018-06-12 17:23:45 +0530444 chg->hw_die_temp_mitigation = of_property_read_bool(node,
445 "qcom,hw-die-temp-mitigation");
446
447 chg->hw_connector_mitigation = of_property_read_bool(node,
448 "qcom,hw-connector-mitigation");
449
450 chg->connector_pull_up = -EINVAL;
451 of_property_read_u32(node, "qcom,connector-internal-pull-kohm",
452 &chg->connector_pull_up);
453
Harry Yang4b7db0f2017-11-27 10:50:44 -0800454 return 0;
455}
456
Ashay Jaiswal20688262018-04-25 11:45:34 +0530457static int smb5_get_adc_data(struct smb_charger *chg, int channel,
458 union power_supply_propval *val)
459{
460 int rc;
461 struct qpnp_vadc_result result;
462
463 if (!chg->vadc_dev) {
464 if (of_find_property(chg->dev->of_node, "qcom,chg-vadc",
465 NULL)) {
466 chg->vadc_dev = qpnp_get_vadc(chg->dev, "chg");
467 if (IS_ERR(chg->vadc_dev)) {
468 rc = PTR_ERR(chg->vadc_dev);
469 if (rc != -EPROBE_DEFER)
470 pr_debug("Failed to find VADC node, rc=%d\n",
471 rc);
472 else
473 chg->vadc_dev = NULL;
474
475 return rc;
476 }
477 } else {
478 return -ENODATA;
479 }
480 }
481
482 if (IS_ERR(chg->vadc_dev))
483 return PTR_ERR(chg->vadc_dev);
484
485 switch (channel) {
486 case USBIN_VOLTAGE:
487 rc = qpnp_vadc_read(chg->vadc_dev, VADC_USB_IN_V_DIV_16_PM5,
488 &result);
489 if (rc < 0) {
490 pr_err("Failed to read USBIN_V over vadc, rc=%d\n", rc);
491 return rc;
492 }
493 val->intval = result.physical;
494 break;
495 case USBIN_CURRENT:
496 rc = qpnp_vadc_read(chg->vadc_dev, VADC_USB_IN_I_PM5, &result);
497 if (rc < 0) {
498 pr_err("Failed to read USBIN_I over vadc, rc=%d\n", rc);
499 return rc;
500 }
501 val->intval = result.physical;
502 break;
503 default:
504 pr_debug("Invalid channel\n");
505 return -EINVAL;
506 }
507
508 return 0;
509}
510
511
Harry Yang4b7db0f2017-11-27 10:50:44 -0800512/************************
513 * USB PSY REGISTRATION *
514 ************************/
515static enum power_supply_property smb5_usb_props[] = {
516 POWER_SUPPLY_PROP_PRESENT,
517 POWER_SUPPLY_PROP_ONLINE,
518 POWER_SUPPLY_PROP_PD_CURRENT_MAX,
519 POWER_SUPPLY_PROP_CURRENT_MAX,
520 POWER_SUPPLY_PROP_TYPE,
521 POWER_SUPPLY_PROP_TYPEC_MODE,
522 POWER_SUPPLY_PROP_TYPEC_POWER_ROLE,
523 POWER_SUPPLY_PROP_TYPEC_CC_ORIENTATION,
Harry Yang4b7db0f2017-11-27 10:50:44 -0800524 POWER_SUPPLY_PROP_PD_ACTIVE,
525 POWER_SUPPLY_PROP_INPUT_CURRENT_SETTLED,
526 POWER_SUPPLY_PROP_INPUT_CURRENT_NOW,
527 POWER_SUPPLY_PROP_BOOST_CURRENT,
528 POWER_SUPPLY_PROP_PE_START,
529 POWER_SUPPLY_PROP_CTM_CURRENT_MAX,
530 POWER_SUPPLY_PROP_HW_CURRENT_MAX,
531 POWER_SUPPLY_PROP_REAL_TYPE,
532 POWER_SUPPLY_PROP_PR_SWAP,
533 POWER_SUPPLY_PROP_PD_VOLTAGE_MAX,
534 POWER_SUPPLY_PROP_PD_VOLTAGE_MIN,
535 POWER_SUPPLY_PROP_SDP_CURRENT_MAX,
Ashay Jaiswala9e10912018-02-02 14:03:35 +0530536 POWER_SUPPLY_PROP_CONNECTOR_TYPE,
Ashay Jaiswal1f71b412017-10-31 14:33:27 +0530537 POWER_SUPPLY_PROP_VOLTAGE_MAX,
Umang Agrawal9fb865a2018-06-25 16:24:00 +0530538 POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN,
Ashay Jaiswal09feab82018-02-12 12:33:18 +0530539 POWER_SUPPLY_PROP_SCOPE,
Ashay Jaiswal20688262018-04-25 11:45:34 +0530540 POWER_SUPPLY_PROP_VOLTAGE_NOW,
Ashay Jaiswal4d334f42018-04-25 10:58:49 +0530541 POWER_SUPPLY_PROP_HVDCP_OPTI_ALLOWED,
Ashay Jaiswal0de6fb92018-06-12 17:23:45 +0530542 POWER_SUPPLY_PROP_QC_OPTI_DISABLE,
Harry Yang4b7db0f2017-11-27 10:50:44 -0800543};
544
545static int smb5_usb_get_prop(struct power_supply *psy,
546 enum power_supply_property psp,
547 union power_supply_propval *val)
548{
549 struct smb5 *chip = power_supply_get_drvdata(psy);
550 struct smb_charger *chg = &chip->chg;
Ashay Jaiswal09feab82018-02-12 12:33:18 +0530551 union power_supply_propval pval;
Harry Yang4b7db0f2017-11-27 10:50:44 -0800552 int rc = 0;
553
554 switch (psp) {
555 case POWER_SUPPLY_PROP_PRESENT:
556 rc = smblib_get_prop_usb_present(chg, val);
557 break;
558 case POWER_SUPPLY_PROP_ONLINE:
559 rc = smblib_get_prop_usb_online(chg, val);
560 if (!val->intval)
561 break;
562
Ashay Jaiswala9e10912018-02-02 14:03:35 +0530563 if (((chg->typec_mode == POWER_SUPPLY_TYPEC_SOURCE_DEFAULT) ||
564 (chg->connector_type == POWER_SUPPLY_CONNECTOR_MICRO_USB))
565 && (chg->real_charger_type == POWER_SUPPLY_TYPE_USB))
Harry Yang4b7db0f2017-11-27 10:50:44 -0800566 val->intval = 0;
567 else
568 val->intval = 1;
Ashay Jaiswala9e10912018-02-02 14:03:35 +0530569
Harry Yang4b7db0f2017-11-27 10:50:44 -0800570 if (chg->real_charger_type == POWER_SUPPLY_TYPE_UNKNOWN)
571 val->intval = 0;
572 break;
573 case POWER_SUPPLY_PROP_VOLTAGE_MAX:
574 rc = smblib_get_prop_usb_voltage_max(chg, val);
575 break;
Umang Agrawal9fb865a2018-06-25 16:24:00 +0530576 case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN:
577 rc = smblib_get_prop_usb_voltage_max_design(chg, val);
578 break;
Harry Yang4b7db0f2017-11-27 10:50:44 -0800579 case POWER_SUPPLY_PROP_PD_CURRENT_MAX:
580 val->intval = get_client_vote(chg->usb_icl_votable, PD_VOTER);
581 break;
582 case POWER_SUPPLY_PROP_CURRENT_MAX:
583 rc = smblib_get_prop_input_current_settled(chg, val);
584 break;
585 case POWER_SUPPLY_PROP_TYPE:
586 val->intval = POWER_SUPPLY_TYPE_USB_PD;
587 break;
588 case POWER_SUPPLY_PROP_REAL_TYPE:
589 val->intval = chg->real_charger_type;
590 break;
591 case POWER_SUPPLY_PROP_TYPEC_MODE:
Ashay Jaiswala9e10912018-02-02 14:03:35 +0530592 if (chg->connector_type == POWER_SUPPLY_CONNECTOR_MICRO_USB)
Harry Yang4b7db0f2017-11-27 10:50:44 -0800593 val->intval = POWER_SUPPLY_TYPEC_NONE;
594 else
595 val->intval = chg->typec_mode;
596 break;
597 case POWER_SUPPLY_PROP_TYPEC_POWER_ROLE:
Ashay Jaiswala9e10912018-02-02 14:03:35 +0530598 if (chg->connector_type == POWER_SUPPLY_CONNECTOR_MICRO_USB)
Harry Yang4b7db0f2017-11-27 10:50:44 -0800599 val->intval = POWER_SUPPLY_TYPEC_PR_NONE;
600 else
601 rc = smblib_get_prop_typec_power_role(chg, val);
602 break;
603 case POWER_SUPPLY_PROP_TYPEC_CC_ORIENTATION:
Ashay Jaiswala9e10912018-02-02 14:03:35 +0530604 if (chg->connector_type == POWER_SUPPLY_CONNECTOR_MICRO_USB)
Harry Yang4b7db0f2017-11-27 10:50:44 -0800605 val->intval = 0;
606 else
607 rc = smblib_get_prop_typec_cc_orientation(chg, val);
608 break;
Harry Yang4b7db0f2017-11-27 10:50:44 -0800609 case POWER_SUPPLY_PROP_PD_ACTIVE:
610 val->intval = chg->pd_active;
611 break;
612 case POWER_SUPPLY_PROP_INPUT_CURRENT_SETTLED:
613 rc = smblib_get_prop_input_current_settled(chg, val);
614 break;
615 case POWER_SUPPLY_PROP_BOOST_CURRENT:
616 val->intval = chg->boost_current_ua;
617 break;
618 case POWER_SUPPLY_PROP_PD_IN_HARD_RESET:
619 rc = smblib_get_prop_pd_in_hard_reset(chg, val);
620 break;
621 case POWER_SUPPLY_PROP_PD_USB_SUSPEND_SUPPORTED:
622 val->intval = chg->system_suspend_supported;
623 break;
624 case POWER_SUPPLY_PROP_PE_START:
625 rc = smblib_get_pe_start(chg, val);
626 break;
627 case POWER_SUPPLY_PROP_CTM_CURRENT_MAX:
628 val->intval = get_client_vote(chg->usb_icl_votable, CTM_VOTER);
629 break;
630 case POWER_SUPPLY_PROP_HW_CURRENT_MAX:
631 rc = smblib_get_charge_current(chg, &val->intval);
632 break;
633 case POWER_SUPPLY_PROP_PR_SWAP:
634 rc = smblib_get_prop_pr_swap_in_progress(chg, val);
635 break;
636 case POWER_SUPPLY_PROP_PD_VOLTAGE_MAX:
637 val->intval = chg->voltage_max_uv;
638 break;
639 case POWER_SUPPLY_PROP_PD_VOLTAGE_MIN:
640 val->intval = chg->voltage_min_uv;
641 break;
642 case POWER_SUPPLY_PROP_SDP_CURRENT_MAX:
643 val->intval = get_client_vote(chg->usb_icl_votable,
644 USB_PSY_VOTER);
645 break;
Ashay Jaiswala9e10912018-02-02 14:03:35 +0530646 case POWER_SUPPLY_PROP_CONNECTOR_TYPE:
647 val->intval = chg->connector_type;
648 break;
Ashay Jaiswal09feab82018-02-12 12:33:18 +0530649 case POWER_SUPPLY_PROP_SCOPE:
650 val->intval = POWER_SUPPLY_SCOPE_UNKNOWN;
651 rc = smblib_get_prop_usb_present(chg, &pval);
652 if (rc < 0)
653 break;
654 val->intval = pval.intval ? POWER_SUPPLY_SCOPE_DEVICE
655 : chg->otg_present ? POWER_SUPPLY_SCOPE_SYSTEM
656 : POWER_SUPPLY_SCOPE_UNKNOWN;
657 break;
Ashay Jaiswal20688262018-04-25 11:45:34 +0530658 case POWER_SUPPLY_PROP_INPUT_CURRENT_NOW:
659 rc = smblib_get_prop_usb_present(chg, &pval);
660 if (rc < 0 || !pval.intval) {
661 val->intval = 0;
662 return rc;
663 }
664 if (chg->smb_version == PMI632_SUBTYPE)
665 rc = smb5_get_adc_data(chg, USBIN_CURRENT, val);
666 break;
667 case POWER_SUPPLY_PROP_VOLTAGE_NOW:
668 if (chg->smb_version == PMI632_SUBTYPE)
669 rc = smb5_get_adc_data(chg, USBIN_VOLTAGE, val);
670 break;
Ashay Jaiswal4d334f42018-04-25 10:58:49 +0530671 case POWER_SUPPLY_PROP_HVDCP_OPTI_ALLOWED:
672 val->intval = !chg->flash_active;
673 break;
Ashay Jaiswal0de6fb92018-06-12 17:23:45 +0530674 case POWER_SUPPLY_PROP_QC_OPTI_DISABLE:
675 if (chg->hw_die_temp_mitigation)
676 val->intval = POWER_SUPPLY_QC_THERMAL_BALANCE_DISABLE
677 | POWER_SUPPLY_QC_INOV_THERMAL_DISABLE;
678 if (chg->hw_connector_mitigation)
679 val->intval |= POWER_SUPPLY_QC_CTM_DISABLE;
680 break;
Harry Yang4b7db0f2017-11-27 10:50:44 -0800681 default:
682 pr_err("get prop %d is not supported in usb\n", psp);
683 rc = -EINVAL;
684 break;
685 }
686
687 if (rc < 0) {
688 pr_debug("Couldn't get prop %d rc = %d\n", psp, rc);
689 return -ENODATA;
690 }
691
692 return 0;
693}
694
695static int smb5_usb_set_prop(struct power_supply *psy,
696 enum power_supply_property psp,
697 const union power_supply_propval *val)
698{
699 struct smb5 *chip = power_supply_get_drvdata(psy);
700 struct smb_charger *chg = &chip->chg;
701 int rc = 0;
702
Harry Yang4b7db0f2017-11-27 10:50:44 -0800703 switch (psp) {
704 case POWER_SUPPLY_PROP_PD_CURRENT_MAX:
705 rc = smblib_set_prop_pd_current_max(chg, val);
706 break;
707 case POWER_SUPPLY_PROP_TYPEC_POWER_ROLE:
708 rc = smblib_set_prop_typec_power_role(chg, val);
709 break;
710 case POWER_SUPPLY_PROP_PD_ACTIVE:
711 rc = smblib_set_prop_pd_active(chg, val);
712 break;
713 case POWER_SUPPLY_PROP_PD_IN_HARD_RESET:
714 rc = smblib_set_prop_pd_in_hard_reset(chg, val);
715 break;
716 case POWER_SUPPLY_PROP_PD_USB_SUSPEND_SUPPORTED:
717 chg->system_suspend_supported = val->intval;
718 break;
719 case POWER_SUPPLY_PROP_BOOST_CURRENT:
720 rc = smblib_set_prop_boost_current(chg, val);
721 break;
722 case POWER_SUPPLY_PROP_CTM_CURRENT_MAX:
723 rc = vote(chg->usb_icl_votable, CTM_VOTER,
724 val->intval >= 0, val->intval);
725 break;
726 case POWER_SUPPLY_PROP_PR_SWAP:
727 rc = smblib_set_prop_pr_swap_in_progress(chg, val);
728 break;
729 case POWER_SUPPLY_PROP_PD_VOLTAGE_MAX:
730 rc = smblib_set_prop_pd_voltage_max(chg, val);
731 break;
732 case POWER_SUPPLY_PROP_PD_VOLTAGE_MIN:
733 rc = smblib_set_prop_pd_voltage_min(chg, val);
734 break;
735 case POWER_SUPPLY_PROP_SDP_CURRENT_MAX:
736 rc = smblib_set_prop_sdp_current_max(chg, val);
737 break;
738 default:
739 pr_err("set prop %d is not supported\n", psp);
740 rc = -EINVAL;
741 break;
742 }
743
Harry Yang4b7db0f2017-11-27 10:50:44 -0800744 return rc;
745}
746
747static int smb5_usb_prop_is_writeable(struct power_supply *psy,
748 enum power_supply_property psp)
749{
750 switch (psp) {
751 case POWER_SUPPLY_PROP_CTM_CURRENT_MAX:
752 return 1;
753 default:
754 break;
755 }
756
757 return 0;
758}
759
760static const struct power_supply_desc usb_psy_desc = {
761 .name = "usb",
762 .type = POWER_SUPPLY_TYPE_USB_PD,
763 .properties = smb5_usb_props,
764 .num_properties = ARRAY_SIZE(smb5_usb_props),
765 .get_property = smb5_usb_get_prop,
766 .set_property = smb5_usb_set_prop,
767 .property_is_writeable = smb5_usb_prop_is_writeable,
768};
769
770static int smb5_init_usb_psy(struct smb5 *chip)
771{
772 struct power_supply_config usb_cfg = {};
773 struct smb_charger *chg = &chip->chg;
774
775 usb_cfg.drv_data = chip;
776 usb_cfg.of_node = chg->dev->of_node;
777 chg->usb_psy = devm_power_supply_register(chg->dev,
778 &usb_psy_desc,
779 &usb_cfg);
780 if (IS_ERR(chg->usb_psy)) {
781 pr_err("Couldn't register USB power supply\n");
782 return PTR_ERR(chg->usb_psy);
783 }
784
785 return 0;
786}
787
788/********************************
789 * USB PC_PORT PSY REGISTRATION *
790 ********************************/
791static enum power_supply_property smb5_usb_port_props[] = {
792 POWER_SUPPLY_PROP_TYPE,
793 POWER_SUPPLY_PROP_ONLINE,
794 POWER_SUPPLY_PROP_VOLTAGE_MAX,
795 POWER_SUPPLY_PROP_CURRENT_MAX,
796};
797
798static int smb5_usb_port_get_prop(struct power_supply *psy,
799 enum power_supply_property psp,
800 union power_supply_propval *val)
801{
802 struct smb5 *chip = power_supply_get_drvdata(psy);
803 struct smb_charger *chg = &chip->chg;
804 int rc = 0;
805
806 switch (psp) {
807 case POWER_SUPPLY_PROP_TYPE:
808 val->intval = POWER_SUPPLY_TYPE_USB;
809 break;
810 case POWER_SUPPLY_PROP_ONLINE:
811 rc = smblib_get_prop_usb_online(chg, val);
812 if (!val->intval)
813 break;
814
Ashay Jaiswala9e10912018-02-02 14:03:35 +0530815 if (((chg->typec_mode == POWER_SUPPLY_TYPEC_SOURCE_DEFAULT) ||
816 (chg->connector_type == POWER_SUPPLY_CONNECTOR_MICRO_USB))
817 && (chg->real_charger_type == POWER_SUPPLY_TYPE_USB))
Harry Yang4b7db0f2017-11-27 10:50:44 -0800818 val->intval = 1;
819 else
820 val->intval = 0;
821 break;
822 case POWER_SUPPLY_PROP_VOLTAGE_MAX:
823 val->intval = 5000000;
824 break;
825 case POWER_SUPPLY_PROP_CURRENT_MAX:
826 rc = smblib_get_prop_input_current_settled(chg, val);
827 break;
828 default:
829 pr_err_ratelimited("Get prop %d is not supported in pc_port\n",
830 psp);
831 return -EINVAL;
832 }
833
834 if (rc < 0) {
835 pr_debug("Couldn't get prop %d rc = %d\n", psp, rc);
836 return -ENODATA;
837 }
838
839 return 0;
840}
841
842static int smb5_usb_port_set_prop(struct power_supply *psy,
843 enum power_supply_property psp,
844 const union power_supply_propval *val)
845{
846 int rc = 0;
847
848 switch (psp) {
849 default:
850 pr_err_ratelimited("Set prop %d is not supported in pc_port\n",
851 psp);
852 rc = -EINVAL;
853 break;
854 }
855
856 return rc;
857}
858
859static const struct power_supply_desc usb_port_psy_desc = {
860 .name = "pc_port",
861 .type = POWER_SUPPLY_TYPE_USB,
862 .properties = smb5_usb_port_props,
863 .num_properties = ARRAY_SIZE(smb5_usb_port_props),
864 .get_property = smb5_usb_port_get_prop,
865 .set_property = smb5_usb_port_set_prop,
866};
867
868static int smb5_init_usb_port_psy(struct smb5 *chip)
869{
870 struct power_supply_config usb_port_cfg = {};
871 struct smb_charger *chg = &chip->chg;
872
873 usb_port_cfg.drv_data = chip;
874 usb_port_cfg.of_node = chg->dev->of_node;
875 chg->usb_port_psy = devm_power_supply_register(chg->dev,
876 &usb_port_psy_desc,
877 &usb_port_cfg);
878 if (IS_ERR(chg->usb_port_psy)) {
879 pr_err("Couldn't register USB pc_port power supply\n");
880 return PTR_ERR(chg->usb_port_psy);
881 }
882
883 return 0;
884}
885
886/*****************************
887 * USB MAIN PSY REGISTRATION *
888 *****************************/
889
890static enum power_supply_property smb5_usb_main_props[] = {
891 POWER_SUPPLY_PROP_VOLTAGE_MAX,
892 POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX,
893 POWER_SUPPLY_PROP_TYPE,
894 POWER_SUPPLY_PROP_INPUT_CURRENT_SETTLED,
895 POWER_SUPPLY_PROP_INPUT_VOLTAGE_SETTLED,
896 POWER_SUPPLY_PROP_FCC_DELTA,
897 POWER_SUPPLY_PROP_CURRENT_MAX,
Ashay Jaiswal09feab82018-02-12 12:33:18 +0530898 POWER_SUPPLY_PROP_FLASH_ACTIVE,
899 POWER_SUPPLY_PROP_FLASH_TRIGGER,
Harry Yang4b7db0f2017-11-27 10:50:44 -0800900};
901
902static int smb5_usb_main_get_prop(struct power_supply *psy,
903 enum power_supply_property psp,
904 union power_supply_propval *val)
905{
906 struct smb5 *chip = power_supply_get_drvdata(psy);
907 struct smb_charger *chg = &chip->chg;
908 int rc = 0;
909
910 switch (psp) {
911 case POWER_SUPPLY_PROP_VOLTAGE_MAX:
912 rc = smblib_get_charge_param(chg, &chg->param.fv, &val->intval);
913 break;
914 case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX:
915 rc = smblib_get_charge_param(chg, &chg->param.fcc,
916 &val->intval);
917 break;
918 case POWER_SUPPLY_PROP_TYPE:
919 val->intval = POWER_SUPPLY_TYPE_MAIN;
920 break;
921 case POWER_SUPPLY_PROP_INPUT_CURRENT_SETTLED:
922 rc = smblib_get_prop_input_current_settled(chg, val);
923 break;
924 case POWER_SUPPLY_PROP_INPUT_VOLTAGE_SETTLED:
925 rc = smblib_get_prop_input_voltage_settled(chg, val);
926 break;
927 case POWER_SUPPLY_PROP_FCC_DELTA:
928 rc = smblib_get_prop_fcc_delta(chg, val);
929 break;
930 case POWER_SUPPLY_PROP_CURRENT_MAX:
931 rc = smblib_get_icl_current(chg, &val->intval);
932 break;
Ashay Jaiswal09feab82018-02-12 12:33:18 +0530933 case POWER_SUPPLY_PROP_FLASH_ACTIVE:
934 val->intval = chg->flash_active;
935 break;
936 case POWER_SUPPLY_PROP_FLASH_TRIGGER:
937 rc = schgm_flash_get_vreg_ok(chg, &val->intval);
938 break;
Harry Yang4b7db0f2017-11-27 10:50:44 -0800939 default:
940 pr_debug("get prop %d is not supported in usb-main\n", psp);
941 rc = -EINVAL;
942 break;
943 }
944 if (rc < 0) {
945 pr_debug("Couldn't get prop %d rc = %d\n", psp, rc);
946 return -ENODATA;
947 }
948
949 return 0;
950}
951
952static int smb5_usb_main_set_prop(struct power_supply *psy,
953 enum power_supply_property psp,
954 const union power_supply_propval *val)
955{
956 struct smb5 *chip = power_supply_get_drvdata(psy);
957 struct smb_charger *chg = &chip->chg;
Ashay Jaiswal4d334f42018-04-25 10:58:49 +0530958 union power_supply_propval pval = {0, };
Harry Yang4b7db0f2017-11-27 10:50:44 -0800959 int rc = 0;
960
961 switch (psp) {
962 case POWER_SUPPLY_PROP_VOLTAGE_MAX:
963 rc = smblib_set_charge_param(chg, &chg->param.fv, val->intval);
964 break;
965 case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX:
966 rc = smblib_set_charge_param(chg, &chg->param.fcc, val->intval);
967 break;
968 case POWER_SUPPLY_PROP_CURRENT_MAX:
969 rc = smblib_set_icl_current(chg, val->intval);
970 break;
Ashay Jaiswal09feab82018-02-12 12:33:18 +0530971 case POWER_SUPPLY_PROP_FLASH_ACTIVE:
Ashay Jaiswal4d334f42018-04-25 10:58:49 +0530972 if ((chg->smb_version == PMI632_SUBTYPE)
973 && (chg->flash_active != val->intval)) {
974 chg->flash_active = val->intval;
975
976 rc = smblib_get_prop_usb_present(chg, &pval);
977 if (rc < 0)
978 pr_err("Failed to get USB preset status rc=%d\n",
979 rc);
980 if (pval.intval) {
981 rc = smblib_force_vbus_voltage(chg,
982 chg->flash_active ? FORCE_5V_BIT
983 : IDLE_BIT);
984 if (rc < 0)
985 pr_err("Failed to force 5V\n");
986 else
987 chg->pulse_cnt = 0;
Anirudh Ghayal4d5cddc2018-06-28 15:19:39 +0530988 } else {
989 /* USB absent & flash not-active - vote 100mA */
990 vote(chg->usb_icl_votable, SW_ICL_MAX_VOTER,
991 true, SDP_100_MA);
Ashay Jaiswal4d334f42018-04-25 10:58:49 +0530992 }
993
994 pr_debug("flash active VBUS 5V restriction %s\n",
995 chg->flash_active ? "applied" : "removed");
996
997 /* Update userspace */
998 if (chg->batt_psy)
999 power_supply_changed(chg->batt_psy);
1000 }
Ashay Jaiswal09feab82018-02-12 12:33:18 +05301001 break;
Harry Yang4b7db0f2017-11-27 10:50:44 -08001002 default:
1003 pr_err("set prop %d is not supported\n", psp);
1004 rc = -EINVAL;
1005 break;
1006 }
1007
1008 return rc;
1009}
1010
1011static const struct power_supply_desc usb_main_psy_desc = {
1012 .name = "main",
1013 .type = POWER_SUPPLY_TYPE_MAIN,
1014 .properties = smb5_usb_main_props,
1015 .num_properties = ARRAY_SIZE(smb5_usb_main_props),
1016 .get_property = smb5_usb_main_get_prop,
1017 .set_property = smb5_usb_main_set_prop,
1018};
1019
1020static int smb5_init_usb_main_psy(struct smb5 *chip)
1021{
1022 struct power_supply_config usb_main_cfg = {};
1023 struct smb_charger *chg = &chip->chg;
1024
1025 usb_main_cfg.drv_data = chip;
1026 usb_main_cfg.of_node = chg->dev->of_node;
1027 chg->usb_main_psy = devm_power_supply_register(chg->dev,
1028 &usb_main_psy_desc,
1029 &usb_main_cfg);
1030 if (IS_ERR(chg->usb_main_psy)) {
1031 pr_err("Couldn't register USB main power supply\n");
1032 return PTR_ERR(chg->usb_main_psy);
1033 }
1034
1035 return 0;
1036}
1037
1038/*************************
1039 * DC PSY REGISTRATION *
1040 *************************/
1041
1042static enum power_supply_property smb5_dc_props[] = {
1043 POWER_SUPPLY_PROP_INPUT_SUSPEND,
1044 POWER_SUPPLY_PROP_PRESENT,
1045 POWER_SUPPLY_PROP_ONLINE,
1046 POWER_SUPPLY_PROP_REAL_TYPE,
1047};
1048
1049static int smb5_dc_get_prop(struct power_supply *psy,
1050 enum power_supply_property psp,
1051 union power_supply_propval *val)
1052{
1053 struct smb5 *chip = power_supply_get_drvdata(psy);
1054 struct smb_charger *chg = &chip->chg;
1055 int rc = 0;
1056
1057 switch (psp) {
1058 case POWER_SUPPLY_PROP_INPUT_SUSPEND:
1059 val->intval = get_effective_result(chg->dc_suspend_votable);
1060 break;
1061 case POWER_SUPPLY_PROP_PRESENT:
1062 rc = smblib_get_prop_dc_present(chg, val);
1063 break;
1064 case POWER_SUPPLY_PROP_ONLINE:
1065 rc = smblib_get_prop_dc_online(chg, val);
1066 break;
1067 case POWER_SUPPLY_PROP_REAL_TYPE:
1068 val->intval = POWER_SUPPLY_TYPE_WIPOWER;
1069 break;
1070 default:
1071 return -EINVAL;
1072 }
1073 if (rc < 0) {
1074 pr_debug("Couldn't get prop %d rc = %d\n", psp, rc);
1075 return -ENODATA;
1076 }
1077 return 0;
1078}
1079
1080static int smb5_dc_set_prop(struct power_supply *psy,
1081 enum power_supply_property psp,
1082 const union power_supply_propval *val)
1083{
1084 struct smb5 *chip = power_supply_get_drvdata(psy);
1085 struct smb_charger *chg = &chip->chg;
1086 int rc = 0;
1087
1088 switch (psp) {
1089 case POWER_SUPPLY_PROP_INPUT_SUSPEND:
1090 rc = vote(chg->dc_suspend_votable, WBC_VOTER,
1091 (bool)val->intval, 0);
1092 break;
1093 default:
1094 return -EINVAL;
1095 }
1096
1097 return rc;
1098}
1099
1100static int smb5_dc_prop_is_writeable(struct power_supply *psy,
1101 enum power_supply_property psp)
1102{
1103 int rc;
1104
1105 switch (psp) {
1106 default:
1107 rc = 0;
1108 break;
1109 }
1110
1111 return rc;
1112}
1113
1114static const struct power_supply_desc dc_psy_desc = {
1115 .name = "dc",
1116 .type = POWER_SUPPLY_TYPE_WIRELESS,
1117 .properties = smb5_dc_props,
1118 .num_properties = ARRAY_SIZE(smb5_dc_props),
1119 .get_property = smb5_dc_get_prop,
1120 .set_property = smb5_dc_set_prop,
1121 .property_is_writeable = smb5_dc_prop_is_writeable,
1122};
1123
1124static int smb5_init_dc_psy(struct smb5 *chip)
1125{
1126 struct power_supply_config dc_cfg = {};
1127 struct smb_charger *chg = &chip->chg;
1128
1129 dc_cfg.drv_data = chip;
1130 dc_cfg.of_node = chg->dev->of_node;
1131 chg->dc_psy = devm_power_supply_register(chg->dev,
1132 &dc_psy_desc,
1133 &dc_cfg);
1134 if (IS_ERR(chg->dc_psy)) {
1135 pr_err("Couldn't register USB power supply\n");
1136 return PTR_ERR(chg->dc_psy);
1137 }
1138
1139 return 0;
1140}
1141
1142/*************************
1143 * BATT PSY REGISTRATION *
1144 *************************/
1145static enum power_supply_property smb5_batt_props[] = {
1146 POWER_SUPPLY_PROP_INPUT_SUSPEND,
Anirudh Ghayaldfdb8412018-04-21 10:37:18 +05301147 POWER_SUPPLY_PROP_BATTERY_CHARGING_ENABLED,
Harry Yang4b7db0f2017-11-27 10:50:44 -08001148 POWER_SUPPLY_PROP_STATUS,
1149 POWER_SUPPLY_PROP_HEALTH,
1150 POWER_SUPPLY_PROP_PRESENT,
1151 POWER_SUPPLY_PROP_CHARGE_TYPE,
1152 POWER_SUPPLY_PROP_CAPACITY,
1153 POWER_SUPPLY_PROP_INPUT_CURRENT_LIMITED,
1154 POWER_SUPPLY_PROP_VOLTAGE_NOW,
1155 POWER_SUPPLY_PROP_VOLTAGE_MAX,
1156 POWER_SUPPLY_PROP_CURRENT_NOW,
1157 POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX,
1158 POWER_SUPPLY_PROP_TEMP,
1159 POWER_SUPPLY_PROP_TECHNOLOGY,
1160 POWER_SUPPLY_PROP_STEP_CHARGING_ENABLED,
1161 POWER_SUPPLY_PROP_SW_JEITA_ENABLED,
1162 POWER_SUPPLY_PROP_CHARGE_DONE,
1163 POWER_SUPPLY_PROP_PARALLEL_DISABLE,
1164 POWER_SUPPLY_PROP_SET_SHIP_MODE,
1165 POWER_SUPPLY_PROP_DIE_HEALTH,
1166 POWER_SUPPLY_PROP_RERUN_AICL,
1167 POWER_SUPPLY_PROP_DP_DM,
1168 POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT_MAX,
1169 POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT,
1170 POWER_SUPPLY_PROP_CHARGE_COUNTER,
Subbaraman Narayanamurthyc4feb892018-05-07 18:43:45 -07001171 POWER_SUPPLY_PROP_CYCLE_COUNT,
Anirudh Ghayal1380d312018-02-23 00:01:43 +05301172 POWER_SUPPLY_PROP_RECHARGE_SOC,
Harry Yang4b7db0f2017-11-27 10:50:44 -08001173};
1174
1175static int smb5_batt_get_prop(struct power_supply *psy,
1176 enum power_supply_property psp,
1177 union power_supply_propval *val)
1178{
1179 struct smb_charger *chg = power_supply_get_drvdata(psy);
1180 int rc = 0;
1181
1182 switch (psp) {
1183 case POWER_SUPPLY_PROP_STATUS:
1184 rc = smblib_get_prop_batt_status(chg, val);
1185 break;
1186 case POWER_SUPPLY_PROP_HEALTH:
1187 rc = smblib_get_prop_batt_health(chg, val);
1188 break;
1189 case POWER_SUPPLY_PROP_PRESENT:
1190 rc = smblib_get_prop_batt_present(chg, val);
1191 break;
1192 case POWER_SUPPLY_PROP_INPUT_SUSPEND:
1193 rc = smblib_get_prop_input_suspend(chg, val);
1194 break;
Anirudh Ghayaldfdb8412018-04-21 10:37:18 +05301195 case POWER_SUPPLY_PROP_BATTERY_CHARGING_ENABLED:
1196 val->intval = !get_client_vote(chg->chg_disable_votable,
1197 USER_VOTER);
1198 break;
Harry Yang4b7db0f2017-11-27 10:50:44 -08001199 case POWER_SUPPLY_PROP_CHARGE_TYPE:
1200 rc = smblib_get_prop_batt_charge_type(chg, val);
1201 break;
1202 case POWER_SUPPLY_PROP_CAPACITY:
1203 rc = smblib_get_prop_batt_capacity(chg, val);
1204 break;
1205 case POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT:
1206 rc = smblib_get_prop_system_temp_level(chg, val);
1207 break;
1208 case POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT_MAX:
1209 rc = smblib_get_prop_system_temp_level_max(chg, val);
1210 break;
1211 case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMITED:
1212 rc = smblib_get_prop_input_current_limited(chg, val);
1213 break;
1214 case POWER_SUPPLY_PROP_STEP_CHARGING_ENABLED:
1215 val->intval = chg->step_chg_enabled;
1216 break;
1217 case POWER_SUPPLY_PROP_SW_JEITA_ENABLED:
1218 val->intval = chg->sw_jeita_enabled;
1219 break;
1220 case POWER_SUPPLY_PROP_VOLTAGE_NOW:
1221 rc = smblib_get_prop_batt_voltage_now(chg, val);
1222 break;
1223 case POWER_SUPPLY_PROP_VOLTAGE_MAX:
1224 val->intval = get_client_vote(chg->fv_votable,
1225 BATT_PROFILE_VOTER);
1226 break;
1227 case POWER_SUPPLY_PROP_CURRENT_NOW:
1228 rc = smblib_get_prop_batt_current_now(chg, val);
1229 break;
1230 case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX:
1231 val->intval = get_client_vote(chg->fcc_votable,
1232 BATT_PROFILE_VOTER);
1233 break;
1234 case POWER_SUPPLY_PROP_TEMP:
1235 rc = smblib_get_prop_batt_temp(chg, val);
1236 break;
1237 case POWER_SUPPLY_PROP_TECHNOLOGY:
1238 val->intval = POWER_SUPPLY_TECHNOLOGY_LION;
1239 break;
1240 case POWER_SUPPLY_PROP_CHARGE_DONE:
1241 rc = smblib_get_prop_batt_charge_done(chg, val);
1242 break;
1243 case POWER_SUPPLY_PROP_PARALLEL_DISABLE:
1244 val->intval = get_client_vote(chg->pl_disable_votable,
1245 USER_VOTER);
1246 break;
1247 case POWER_SUPPLY_PROP_SET_SHIP_MODE:
1248 /* Not in ship mode as long as device is active */
1249 val->intval = 0;
1250 break;
1251 case POWER_SUPPLY_PROP_DIE_HEALTH:
1252 if (chg->die_health == -EINVAL)
1253 rc = smblib_get_prop_die_health(chg, val);
1254 else
1255 val->intval = chg->die_health;
1256 break;
1257 case POWER_SUPPLY_PROP_DP_DM:
1258 val->intval = chg->pulse_cnt;
1259 break;
1260 case POWER_SUPPLY_PROP_RERUN_AICL:
1261 val->intval = 0;
1262 break;
1263 case POWER_SUPPLY_PROP_CHARGE_COUNTER:
1264 rc = smblib_get_prop_batt_charge_counter(chg, val);
1265 break;
Subbaraman Narayanamurthyc4feb892018-05-07 18:43:45 -07001266 case POWER_SUPPLY_PROP_CYCLE_COUNT:
1267 rc = smblib_get_prop_batt_cycle_count(chg, val);
1268 break;
Anirudh Ghayal1380d312018-02-23 00:01:43 +05301269 case POWER_SUPPLY_PROP_RECHARGE_SOC:
1270 val->intval = chg->auto_recharge_soc;
1271 break;
Harry Yang4b7db0f2017-11-27 10:50:44 -08001272 default:
1273 pr_err("batt power supply prop %d not supported\n", psp);
1274 return -EINVAL;
1275 }
1276
1277 if (rc < 0) {
1278 pr_debug("Couldn't get prop %d rc = %d\n", psp, rc);
1279 return -ENODATA;
1280 }
1281
1282 return 0;
1283}
1284
1285static int smb5_batt_set_prop(struct power_supply *psy,
1286 enum power_supply_property prop,
1287 const union power_supply_propval *val)
1288{
1289 int rc = 0;
1290 struct smb_charger *chg = power_supply_get_drvdata(psy);
Ashay Jaiswala55b7ed2018-03-23 17:23:48 +05301291 bool enable;
Harry Yang4b7db0f2017-11-27 10:50:44 -08001292
1293 switch (prop) {
1294 case POWER_SUPPLY_PROP_STATUS:
1295 rc = smblib_set_prop_batt_status(chg, val);
1296 break;
1297 case POWER_SUPPLY_PROP_INPUT_SUSPEND:
1298 rc = smblib_set_prop_input_suspend(chg, val);
1299 break;
Anirudh Ghayaldfdb8412018-04-21 10:37:18 +05301300 case POWER_SUPPLY_PROP_BATTERY_CHARGING_ENABLED:
1301 vote(chg->chg_disable_votable, USER_VOTER, !val->intval, 0);
1302 break;
Harry Yang4b7db0f2017-11-27 10:50:44 -08001303 case POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT:
1304 rc = smblib_set_prop_system_temp_level(chg, val);
1305 break;
1306 case POWER_SUPPLY_PROP_CAPACITY:
1307 rc = smblib_set_prop_batt_capacity(chg, val);
1308 break;
1309 case POWER_SUPPLY_PROP_PARALLEL_DISABLE:
1310 vote(chg->pl_disable_votable, USER_VOTER, (bool)val->intval, 0);
1311 break;
1312 case POWER_SUPPLY_PROP_VOLTAGE_MAX:
1313 chg->batt_profile_fv_uv = val->intval;
1314 vote(chg->fv_votable, BATT_PROFILE_VOTER, true, val->intval);
1315 break;
1316 case POWER_SUPPLY_PROP_STEP_CHARGING_ENABLED:
Ashay Jaiswala55b7ed2018-03-23 17:23:48 +05301317 enable = !!val->intval || chg->sw_jeita_enabled;
1318 rc = smblib_configure_wdog(chg, enable);
1319 if (rc == 0)
1320 chg->step_chg_enabled = !!val->intval;
Harry Yang4b7db0f2017-11-27 10:50:44 -08001321 break;
1322 case POWER_SUPPLY_PROP_SW_JEITA_ENABLED:
1323 if (chg->sw_jeita_enabled != (!!val->intval)) {
1324 rc = smblib_disable_hw_jeita(chg, !!val->intval);
Ashay Jaiswala55b7ed2018-03-23 17:23:48 +05301325 enable = !!val->intval || chg->step_chg_enabled;
1326 rc |= smblib_configure_wdog(chg, enable);
Harry Yang4b7db0f2017-11-27 10:50:44 -08001327 if (rc == 0)
1328 chg->sw_jeita_enabled = !!val->intval;
1329 }
1330 break;
1331 case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX:
1332 chg->batt_profile_fcc_ua = val->intval;
1333 vote(chg->fcc_votable, BATT_PROFILE_VOTER, true, val->intval);
1334 break;
1335 case POWER_SUPPLY_PROP_SET_SHIP_MODE:
1336 /* Not in ship mode as long as the device is active */
1337 if (!val->intval)
1338 break;
1339 if (chg->pl.psy)
1340 power_supply_set_property(chg->pl.psy,
1341 POWER_SUPPLY_PROP_SET_SHIP_MODE, val);
1342 rc = smblib_set_prop_ship_mode(chg, val);
1343 break;
1344 case POWER_SUPPLY_PROP_RERUN_AICL:
1345 rc = smblib_rerun_aicl(chg);
1346 break;
1347 case POWER_SUPPLY_PROP_DP_DM:
Ashay Jaiswal4d334f42018-04-25 10:58:49 +05301348 if (!chg->flash_active)
1349 rc = smblib_dp_dm(chg, val->intval);
Harry Yang4b7db0f2017-11-27 10:50:44 -08001350 break;
1351 case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMITED:
1352 rc = smblib_set_prop_input_current_limited(chg, val);
1353 break;
1354 case POWER_SUPPLY_PROP_DIE_HEALTH:
1355 chg->die_health = val->intval;
1356 power_supply_changed(chg->batt_psy);
1357 break;
Anirudh Ghayaldfdb8412018-04-21 10:37:18 +05301358 case POWER_SUPPLY_PROP_RECHARGE_SOC:
1359 if (chg->smb_version == PMI632_SUBTYPE) {
1360 /* toggle charging to force recharge */
1361 vote(chg->chg_disable_votable, FORCE_RECHARGE_VOTER,
1362 true, 0);
1363 /* charge disable delay */
1364 msleep(50);
1365 vote(chg->chg_disable_votable, FORCE_RECHARGE_VOTER,
1366 false, 0);
1367 }
1368 break;
Harry Yang4b7db0f2017-11-27 10:50:44 -08001369 default:
1370 rc = -EINVAL;
1371 }
1372
1373 return rc;
1374}
1375
1376static int smb5_batt_prop_is_writeable(struct power_supply *psy,
1377 enum power_supply_property psp)
1378{
1379 switch (psp) {
1380 case POWER_SUPPLY_PROP_STATUS:
1381 case POWER_SUPPLY_PROP_INPUT_SUSPEND:
1382 case POWER_SUPPLY_PROP_SYSTEM_TEMP_LEVEL:
1383 case POWER_SUPPLY_PROP_CAPACITY:
1384 case POWER_SUPPLY_PROP_PARALLEL_DISABLE:
1385 case POWER_SUPPLY_PROP_DP_DM:
1386 case POWER_SUPPLY_PROP_RERUN_AICL:
1387 case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMITED:
1388 case POWER_SUPPLY_PROP_STEP_CHARGING_ENABLED:
1389 case POWER_SUPPLY_PROP_SW_JEITA_ENABLED:
1390 case POWER_SUPPLY_PROP_DIE_HEALTH:
Anirudh Ghayaldfdb8412018-04-21 10:37:18 +05301391 case POWER_SUPPLY_PROP_BATTERY_CHARGING_ENABLED:
Harry Yang4b7db0f2017-11-27 10:50:44 -08001392 return 1;
1393 default:
1394 break;
1395 }
1396
1397 return 0;
1398}
1399
1400static const struct power_supply_desc batt_psy_desc = {
1401 .name = "battery",
1402 .type = POWER_SUPPLY_TYPE_BATTERY,
1403 .properties = smb5_batt_props,
1404 .num_properties = ARRAY_SIZE(smb5_batt_props),
1405 .get_property = smb5_batt_get_prop,
1406 .set_property = smb5_batt_set_prop,
1407 .property_is_writeable = smb5_batt_prop_is_writeable,
1408};
1409
1410static int smb5_init_batt_psy(struct smb5 *chip)
1411{
1412 struct power_supply_config batt_cfg = {};
1413 struct smb_charger *chg = &chip->chg;
1414 int rc = 0;
1415
1416 batt_cfg.drv_data = chg;
1417 batt_cfg.of_node = chg->dev->of_node;
1418 chg->batt_psy = devm_power_supply_register(chg->dev,
1419 &batt_psy_desc,
1420 &batt_cfg);
1421 if (IS_ERR(chg->batt_psy)) {
1422 pr_err("Couldn't register battery power supply\n");
1423 return PTR_ERR(chg->batt_psy);
1424 }
1425
1426 return rc;
1427}
1428
1429/******************************
1430 * VBUS REGULATOR REGISTRATION *
1431 ******************************/
1432
1433static struct regulator_ops smb5_vbus_reg_ops = {
1434 .enable = smblib_vbus_regulator_enable,
1435 .disable = smblib_vbus_regulator_disable,
1436 .is_enabled = smblib_vbus_regulator_is_enabled,
1437};
1438
1439static int smb5_init_vbus_regulator(struct smb5 *chip)
1440{
1441 struct smb_charger *chg = &chip->chg;
1442 struct regulator_config cfg = {};
1443 int rc = 0;
1444
1445 chg->vbus_vreg = devm_kzalloc(chg->dev, sizeof(*chg->vbus_vreg),
1446 GFP_KERNEL);
1447 if (!chg->vbus_vreg)
1448 return -ENOMEM;
1449
1450 cfg.dev = chg->dev;
1451 cfg.driver_data = chip;
1452
1453 chg->vbus_vreg->rdesc.owner = THIS_MODULE;
1454 chg->vbus_vreg->rdesc.type = REGULATOR_VOLTAGE;
1455 chg->vbus_vreg->rdesc.ops = &smb5_vbus_reg_ops;
1456 chg->vbus_vreg->rdesc.of_match = "qcom,smb5-vbus";
1457 chg->vbus_vreg->rdesc.name = "qcom,smb5-vbus";
1458
1459 chg->vbus_vreg->rdev = devm_regulator_register(chg->dev,
1460 &chg->vbus_vreg->rdesc, &cfg);
1461 if (IS_ERR(chg->vbus_vreg->rdev)) {
1462 rc = PTR_ERR(chg->vbus_vreg->rdev);
1463 chg->vbus_vreg->rdev = NULL;
1464 if (rc != -EPROBE_DEFER)
1465 pr_err("Couldn't register VBUS regulator rc=%d\n", rc);
1466 }
1467
1468 return rc;
1469}
1470
1471/******************************
1472 * VCONN REGULATOR REGISTRATION *
1473 ******************************/
1474
1475static struct regulator_ops smb5_vconn_reg_ops = {
1476 .enable = smblib_vconn_regulator_enable,
1477 .disable = smblib_vconn_regulator_disable,
1478 .is_enabled = smblib_vconn_regulator_is_enabled,
1479};
1480
1481static int smb5_init_vconn_regulator(struct smb5 *chip)
1482{
1483 struct smb_charger *chg = &chip->chg;
1484 struct regulator_config cfg = {};
1485 int rc = 0;
1486
Ashay Jaiswala9e10912018-02-02 14:03:35 +05301487 if (chg->connector_type == POWER_SUPPLY_CONNECTOR_MICRO_USB)
Harry Yang4b7db0f2017-11-27 10:50:44 -08001488 return 0;
1489
1490 chg->vconn_vreg = devm_kzalloc(chg->dev, sizeof(*chg->vconn_vreg),
1491 GFP_KERNEL);
1492 if (!chg->vconn_vreg)
1493 return -ENOMEM;
1494
1495 cfg.dev = chg->dev;
1496 cfg.driver_data = chip;
1497
1498 chg->vconn_vreg->rdesc.owner = THIS_MODULE;
1499 chg->vconn_vreg->rdesc.type = REGULATOR_VOLTAGE;
1500 chg->vconn_vreg->rdesc.ops = &smb5_vconn_reg_ops;
1501 chg->vconn_vreg->rdesc.of_match = "qcom,smb5-vconn";
1502 chg->vconn_vreg->rdesc.name = "qcom,smb5-vconn";
1503
1504 chg->vconn_vreg->rdev = devm_regulator_register(chg->dev,
1505 &chg->vconn_vreg->rdesc, &cfg);
1506 if (IS_ERR(chg->vconn_vreg->rdev)) {
1507 rc = PTR_ERR(chg->vconn_vreg->rdev);
1508 chg->vconn_vreg->rdev = NULL;
1509 if (rc != -EPROBE_DEFER)
1510 pr_err("Couldn't register VCONN regulator rc=%d\n", rc);
1511 }
1512
1513 return rc;
1514}
1515
1516/***************************
1517 * HARDWARE INITIALIZATION *
1518 ***************************/
1519static int smb5_configure_typec(struct smb_charger *chg)
1520{
1521 int rc;
Ashay Jaiswal91d63f42018-05-16 11:30:40 +05301522 u8 val = 0;
1523
1524 rc = smblib_read(chg, LEGACY_CABLE_STATUS_REG, &val);
1525 if (rc < 0) {
1526 dev_err(chg->dev, "Couldn't read Legacy status rc=%d\n", rc);
1527 return rc;
1528 }
1529 /*
1530 * If Legacy cable is detected re-trigger Legacy detection
1531 * by disabling/enabling typeC mode.
1532 */
1533 if (val & TYPEC_LEGACY_CABLE_STATUS_BIT) {
1534 rc = smblib_masked_write(chg, TYPE_C_MODE_CFG_REG,
1535 TYPEC_DISABLE_CMD_BIT, TYPEC_DISABLE_CMD_BIT);
1536 if (rc < 0) {
1537 dev_err(chg->dev, "Couldn't disable TYPEC rc=%d\n", rc);
1538 return rc;
1539 }
1540
1541 /* delay before enabling typeC */
1542 msleep(500);
1543
1544 rc = smblib_masked_write(chg, TYPE_C_MODE_CFG_REG,
1545 TYPEC_DISABLE_CMD_BIT, 0);
1546 if (rc < 0) {
1547 dev_err(chg->dev, "Couldn't enable TYPEC rc=%d\n", rc);
1548 return rc;
1549 }
1550 }
Harry Yang4b7db0f2017-11-27 10:50:44 -08001551
Harry Yang6afaea22018-03-26 19:11:07 -07001552 /* disable apsd */
Ashay Jaiswalc96380de2018-05-16 12:02:36 +05301553 rc = smblib_configure_hvdcp_apsd(chg, false);
Harry Yang6afaea22018-03-26 19:11:07 -07001554 if (rc < 0) {
1555 dev_err(chg->dev, "Couldn't disable APSD rc=%d\n", rc);
1556 return rc;
1557 }
1558
Harry Yang4b7db0f2017-11-27 10:50:44 -08001559 rc = smblib_write(chg, TYPE_C_INTERRUPT_EN_CFG_1_REG,
1560 TYPEC_CCOUT_DETACH_INT_EN_BIT |
1561 TYPEC_CCOUT_ATTACH_INT_EN_BIT);
1562 if (rc < 0) {
1563 dev_err(chg->dev,
1564 "Couldn't configure Type-C interrupts rc=%d\n", rc);
1565 return rc;
1566 }
1567
1568 rc = smblib_write(chg, TYPE_C_INTERRUPT_EN_CFG_2_REG,
Harry Yang4b7db0f2017-11-27 10:50:44 -08001569 TYPEC_WATER_DETECTION_INT_EN_BIT);
1570 if (rc < 0) {
1571 dev_err(chg->dev,
1572 "Couldn't configure Type-C interrupts rc=%d\n", rc);
1573 return rc;
1574 }
1575
Harry Yang423d5c32018-05-30 15:49:04 -07001576 rc = smblib_masked_write(chg, TYPE_C_MODE_CFG_REG,
1577 EN_TRY_SNK_BIT, EN_TRY_SNK_BIT);
1578 if (rc < 0) {
1579 dev_err(chg->dev,
1580 "Couldn't enable try.snk rc=%d\n", rc);
1581 return rc;
1582 }
1583
Ashay Jaiswald5022b62018-05-27 19:21:11 +05301584 /* Keep VCONN in h/w controlled mode for PMI632 */
1585 if (chg->smb_version != PMI632_SUBTYPE) {
1586 /* configure VCONN for software control */
1587 rc = smblib_masked_write(chg, TYPE_C_VCONN_CONTROL_REG,
Harry Yang4b7db0f2017-11-27 10:50:44 -08001588 VCONN_EN_SRC_BIT | VCONN_EN_VALUE_BIT,
1589 VCONN_EN_SRC_BIT);
Ashay Jaiswald5022b62018-05-27 19:21:11 +05301590 if (rc < 0) {
1591 dev_err(chg->dev,
1592 "Couldn't configure VCONN for SW control rc=%d\n",
1593 rc);
1594 return rc;
1595 }
Harry Yang4b7db0f2017-11-27 10:50:44 -08001596 }
1597
1598 return rc;
1599}
1600
1601static int smb5_configure_micro_usb(struct smb_charger *chg)
1602{
1603 int rc;
1604
Ashay Jaiswala9e10912018-02-02 14:03:35 +05301605 rc = smblib_masked_write(chg, TYPE_C_INTERRUPT_EN_CFG_2_REG,
1606 MICRO_USB_STATE_CHANGE_INT_EN_BIT,
1607 MICRO_USB_STATE_CHANGE_INT_EN_BIT);
1608 if (rc < 0) {
1609 dev_err(chg->dev,
1610 "Couldn't configure Type-C interrupts rc=%d\n", rc);
1611 return rc;
1612 }
1613
Harry Yang4b7db0f2017-11-27 10:50:44 -08001614 return rc;
1615}
1616
Ashay Jaiswal0de6fb92018-06-12 17:23:45 +05301617static int smb5_configure_mitigation(struct smb_charger *chg)
1618{
1619 int rc;
1620 u8 chan = 0;
1621
1622 if (!chg->hw_die_temp_mitigation && !chg->hw_connector_mitigation)
1623 return 0;
1624
1625 if (chg->hw_die_temp_mitigation) {
1626 rc = smblib_write(chg, MISC_THERMREG_SRC_CFG_REG,
1627 THERMREG_CONNECTOR_ADC_SRC_EN_BIT
1628 | THERMREG_DIE_ADC_SRC_EN_BIT
1629 | THERMREG_DIE_CMP_SRC_EN_BIT);
1630 if (rc < 0) {
1631 dev_err(chg->dev,
1632 "Couldn't configure THERM_SRC reg rc=%d\n", rc);
1633 return rc;
1634 };
1635
1636 chan = DIE_TEMP_CHANNEL_EN_BIT;
1637 }
1638
1639 if (chg->hw_connector_mitigation)
1640 chan |= CONN_THM_CHANNEL_EN_BIT;
1641
1642 rc = smblib_masked_write(chg, BATIF_ADC_CHANNEL_EN_REG,
1643 CONN_THM_CHANNEL_EN_BIT | DIE_TEMP_CHANNEL_EN_BIT,
1644 chan);
1645 if (rc < 0) {
1646 dev_err(chg->dev, "Couldn't enable ADC channelrc=%d\n", rc);
1647 return rc;
1648 }
1649
1650 return 0;
1651}
1652
Harry Yang4b7db0f2017-11-27 10:50:44 -08001653static int smb5_init_hw(struct smb5 *chip)
1654{
1655 struct smb_charger *chg = &chip->chg;
Ashay Jaiswala9e10912018-02-02 14:03:35 +05301656 int rc, type = 0;
1657 u8 val = 0;
Harry Yang4b7db0f2017-11-27 10:50:44 -08001658
1659 if (chip->dt.no_battery)
1660 chg->fake_capacity = 50;
1661
1662 if (chip->dt.batt_profile_fcc_ua < 0)
1663 smblib_get_charge_param(chg, &chg->param.fcc,
1664 &chg->batt_profile_fcc_ua);
1665
1666 if (chip->dt.batt_profile_fv_uv < 0)
1667 smblib_get_charge_param(chg, &chg->param.fv,
1668 &chg->batt_profile_fv_uv);
1669
1670 smblib_get_charge_param(chg, &chg->param.usb_icl,
1671 &chg->default_icl_ua);
Ashay Jaiswala9e10912018-02-02 14:03:35 +05301672
1673 /* Use SW based VBUS control, disable HW autonomous mode */
Ashay Jaiswala9e10912018-02-02 14:03:35 +05301674 rc = smblib_masked_write(chg, USBIN_OPTIONS_1_CFG_REG,
1675 HVDCP_AUTH_ALG_EN_CFG_BIT | HVDCP_AUTONOMOUS_MODE_EN_CFG_BIT,
1676 HVDCP_AUTH_ALG_EN_CFG_BIT);
1677 if (rc < 0) {
1678 dev_err(chg->dev, "Couldn't configure HVDCP rc=%d\n", rc);
1679 return rc;
1680 }
1681
1682 /*
1683 * PMI632 can have the connector type defined by a dedicated register
1684 * TYPEC_MICRO_USB_MODE_REG or by a common TYPEC_U_USB_CFG_REG.
1685 */
1686 if (chg->smb_version == PMI632_SUBTYPE) {
1687 rc = smblib_read(chg, TYPEC_MICRO_USB_MODE_REG, &val);
1688 if (rc < 0) {
1689 dev_err(chg->dev, "Couldn't read USB mode rc=%d\n", rc);
1690 return rc;
1691 }
1692 type = !!(val & MICRO_USB_MODE_ONLY_BIT);
1693 }
1694
1695 /*
1696 * If TYPEC_MICRO_USB_MODE_REG is not set and for all non-PMI632
1697 * check the connector type using TYPEC_U_USB_CFG_REG.
1698 */
1699 if (!type) {
1700 rc = smblib_read(chg, TYPEC_U_USB_CFG_REG, &val);
1701 if (rc < 0) {
1702 dev_err(chg->dev, "Couldn't read U_USB config rc=%d\n",
1703 rc);
1704 return rc;
1705 }
1706
1707 type = !!(val & EN_MICRO_USB_MODE_BIT);
1708 }
1709
Ashay Jaiswala9e10912018-02-02 14:03:35 +05301710 pr_debug("Connector type=%s\n", type ? "Micro USB" : "TypeC");
1711
Harry Yang6afaea22018-03-26 19:11:07 -07001712 if (type) {
1713 chg->connector_type = POWER_SUPPLY_CONNECTOR_MICRO_USB;
Harry Yang6afaea22018-03-26 19:11:07 -07001714 rc = smb5_configure_micro_usb(chg);
1715 } else {
1716 chg->connector_type = POWER_SUPPLY_CONNECTOR_TYPEC;
1717 rc = smb5_configure_typec(chg);
1718 }
1719 if (rc < 0) {
1720 dev_err(chg->dev,
1721 "Couldn't configure TypeC/micro-USB mode rc=%d\n", rc);
1722 return rc;
1723 }
1724
Ashay Jaiswal09feab82018-02-12 12:33:18 +05301725 /*
1726 * PMI632 based hw init:
Ashay Jaiswal6f70a512018-05-11 17:25:58 +05301727 * - Enable STAT pin function on SMB_EN
Ashay Jaiswalc96380de2018-05-16 12:02:36 +05301728 * - Rerun APSD to ensure proper charger detection if device
1729 * boots with charger connected.
Ashay Jaiswal09feab82018-02-12 12:33:18 +05301730 * - Initialize flash module for PMI632
1731 */
Ashay Jaiswalc96380de2018-05-16 12:02:36 +05301732 if (chg->smb_version == PMI632_SUBTYPE) {
Ashay Jaiswal6f70a512018-05-11 17:25:58 +05301733 rc = smblib_masked_write(chg, MISC_SMB_EN_CMD_REG,
1734 EN_STAT_CMD_BIT, EN_STAT_CMD_BIT);
1735 if (rc < 0) {
1736 dev_err(chg->dev, "Couldn't configure SMB_EN rc=%d\n",
1737 rc);
1738 return rc;
1739 }
1740
Ashay Jaiswal09feab82018-02-12 12:33:18 +05301741 schgm_flash_init(chg);
Ashay Jaiswalc96380de2018-05-16 12:02:36 +05301742 smblib_rerun_apsd_if_required(chg);
1743 }
Ashay Jaiswal09feab82018-02-12 12:33:18 +05301744
Ashay Jaiswalcbdf2e82018-05-27 23:59:01 +05301745 /* clear the ICL override if it is set */
1746 rc = smblib_icl_override(chg, false);
1747 if (rc < 0) {
1748 pr_err("Couldn't disable ICL override rc=%d\n", rc);
1749 return rc;
1750 }
1751
Ashay Jaiswalb2b06fe2018-06-07 18:35:21 +05301752 /* set OTG current limit */
1753 rc = smblib_set_charge_param(chg, &chg->param.otg_cl, chg->otg_cl_ua);
1754 if (rc < 0) {
1755 pr_err("Couldn't set otg current limit rc=%d\n", rc);
1756 return rc;
1757 }
1758
Ashay Jaiswal0de6fb92018-06-12 17:23:45 +05301759 /* configure temperature mitigation */
1760 rc = smb5_configure_mitigation(chg);
1761 if (rc < 0) {
1762 dev_err(chg->dev, "Couldn't configure mitigation rc=%d\n", rc);
1763 return rc;
1764 }
1765
Harry Yang4b7db0f2017-11-27 10:50:44 -08001766 /* vote 0mA on usb_icl for non battery platforms */
1767 vote(chg->usb_icl_votable,
1768 DEFAULT_VOTER, chip->dt.no_battery, 0);
1769 vote(chg->dc_suspend_votable,
1770 DEFAULT_VOTER, chip->dt.no_battery, 0);
1771 vote(chg->fcc_votable, HW_LIMIT_VOTER,
1772 chip->dt.batt_profile_fcc_ua > 0, chip->dt.batt_profile_fcc_ua);
1773 vote(chg->fv_votable, HW_LIMIT_VOTER,
1774 chip->dt.batt_profile_fv_uv > 0, chip->dt.batt_profile_fv_uv);
1775 vote(chg->fcc_votable,
Ashay Jaiswala9e10912018-02-02 14:03:35 +05301776 BATT_PROFILE_VOTER, chg->batt_profile_fcc_ua > 0,
1777 chg->batt_profile_fcc_ua);
Harry Yang4b7db0f2017-11-27 10:50:44 -08001778 vote(chg->fv_votable,
Ashay Jaiswala9e10912018-02-02 14:03:35 +05301779 BATT_PROFILE_VOTER, chg->batt_profile_fv_uv > 0,
1780 chg->batt_profile_fv_uv);
Ashay Jaiswala9e10912018-02-02 14:03:35 +05301781
1782 /* Some h/w limit maximum supported ICL */
1783 vote(chg->usb_icl_votable, HW_LIMIT_VOTER,
1784 chg->hw_max_icl_ua > 0, chg->hw_max_icl_ua);
Harry Yang4b7db0f2017-11-27 10:50:44 -08001785
1786 /*
1787 * AICL configuration:
Ashay Jaiswalc96380de2018-05-16 12:02:36 +05301788 * AICL ADC disable
Harry Yang4b7db0f2017-11-27 10:50:44 -08001789 */
Ashay Jaiswalc96380de2018-05-16 12:02:36 +05301790 if (chg->smb_version != PMI632_SUBTYPE) {
1791 rc = smblib_masked_write(chg, USBIN_AICL_OPTIONS_CFG_REG,
Harry Yang4b7db0f2017-11-27 10:50:44 -08001792 USBIN_AICL_ADC_EN_BIT, 0);
Ashay Jaiswalc96380de2018-05-16 12:02:36 +05301793 if (rc < 0) {
1794 dev_err(chg->dev, "Couldn't config AICL rc=%d\n", rc);
1795 return rc;
1796 }
Harry Yang4b7db0f2017-11-27 10:50:44 -08001797 }
1798
1799 /* enable the charging path */
1800 rc = vote(chg->chg_disable_votable, DEFAULT_VOTER, false, 0);
1801 if (rc < 0) {
1802 dev_err(chg->dev, "Couldn't enable charging rc=%d\n", rc);
1803 return rc;
1804 }
1805
Harry Yang4b7db0f2017-11-27 10:50:44 -08001806 /* configure VBUS for software control */
1807 rc = smblib_masked_write(chg, DCDC_OTG_CFG_REG, OTG_EN_SRC_CFG_BIT, 0);
1808 if (rc < 0) {
1809 dev_err(chg->dev,
1810 "Couldn't configure VBUS for SW control rc=%d\n", rc);
1811 return rc;
1812 }
1813
Ashay Jaiswala55b7ed2018-03-23 17:23:48 +05301814 /*
1815 * configure the one time watchdong periodic interval and
1816 * disable "watchdog bite disable charging".
1817 */
Harry Yang4b7db0f2017-11-27 10:50:44 -08001818 val = (ilog2(chip->dt.wd_bark_time / 16) << BARK_WDOG_TIMEOUT_SHIFT)
1819 & BARK_WDOG_TIMEOUT_MASK;
1820 val |= BITE_WDOG_TIMEOUT_8S;
1821 rc = smblib_masked_write(chg, SNARL_BARK_BITE_WD_CFG_REG,
1822 BITE_WDOG_DISABLE_CHARGING_CFG_BIT |
1823 BARK_WDOG_TIMEOUT_MASK | BITE_WDOG_TIMEOUT_MASK,
1824 val);
1825 if (rc < 0) {
1826 pr_err("Couldn't configue WD config rc=%d\n", rc);
1827 return rc;
1828 }
1829
Harry Yang4b7db0f2017-11-27 10:50:44 -08001830 /* configure float charger options */
1831 switch (chip->dt.float_option) {
1832 case FLOAT_DCP:
1833 rc = smblib_masked_write(chg, USBIN_OPTIONS_2_CFG_REG,
1834 FLOAT_OPTIONS_MASK, 0);
1835 break;
1836 case FLOAT_SDP:
1837 rc = smblib_masked_write(chg, USBIN_OPTIONS_2_CFG_REG,
1838 FLOAT_OPTIONS_MASK, FORCE_FLOAT_SDP_CFG_BIT);
1839 break;
1840 case DISABLE_CHARGING:
1841 rc = smblib_masked_write(chg, USBIN_OPTIONS_2_CFG_REG,
1842 FLOAT_OPTIONS_MASK, FLOAT_DIS_CHGING_CFG_BIT);
1843 break;
1844 case SUSPEND_INPUT:
1845 rc = smblib_masked_write(chg, USBIN_OPTIONS_2_CFG_REG,
1846 FLOAT_OPTIONS_MASK, SUSPEND_FLOAT_CFG_BIT);
1847 break;
1848 default:
1849 rc = 0;
1850 break;
1851 }
1852
1853 if (rc < 0) {
1854 dev_err(chg->dev, "Couldn't configure float charger options rc=%d\n",
1855 rc);
1856 return rc;
1857 }
1858
1859 rc = smblib_read(chg, USBIN_OPTIONS_2_CFG_REG, &chg->float_cfg);
1860 if (rc < 0) {
1861 dev_err(chg->dev, "Couldn't read float charger options rc=%d\n",
1862 rc);
1863 return rc;
1864 }
1865
1866 switch (chip->dt.chg_inhibit_thr_mv) {
1867 case 50:
1868 rc = smblib_masked_write(chg, CHARGE_INHIBIT_THRESHOLD_CFG_REG,
1869 CHARGE_INHIBIT_THRESHOLD_MASK,
1870 INHIBIT_ANALOG_VFLT_MINUS_50MV);
1871 break;
1872 case 100:
1873 rc = smblib_masked_write(chg, CHARGE_INHIBIT_THRESHOLD_CFG_REG,
1874 CHARGE_INHIBIT_THRESHOLD_MASK,
1875 INHIBIT_ANALOG_VFLT_MINUS_100MV);
1876 break;
1877 case 200:
1878 rc = smblib_masked_write(chg, CHARGE_INHIBIT_THRESHOLD_CFG_REG,
1879 CHARGE_INHIBIT_THRESHOLD_MASK,
1880 INHIBIT_ANALOG_VFLT_MINUS_200MV);
1881 break;
1882 case 300:
1883 rc = smblib_masked_write(chg, CHARGE_INHIBIT_THRESHOLD_CFG_REG,
1884 CHARGE_INHIBIT_THRESHOLD_MASK,
1885 INHIBIT_ANALOG_VFLT_MINUS_300MV);
1886 break;
1887 case 0:
1888 rc = smblib_masked_write(chg, CHGR_CFG2_REG,
1889 CHARGER_INHIBIT_BIT, 0);
1890 default:
1891 break;
1892 }
1893
1894 if (rc < 0) {
1895 dev_err(chg->dev, "Couldn't configure charge inhibit threshold rc=%d\n",
1896 rc);
1897 return rc;
1898 }
1899
Anirudh Ghayal1380d312018-02-23 00:01:43 +05301900 rc = smblib_masked_write(chg, CHGR_CFG2_REG, RECHG_MASK,
1901 (chip->dt.auto_recharge_vbat_mv != -EINVAL) ?
1902 VBAT_BASED_RECHG_BIT : 0);
Harry Yang4b7db0f2017-11-27 10:50:44 -08001903 if (rc < 0) {
Anirudh Ghayal1380d312018-02-23 00:01:43 +05301904 dev_err(chg->dev, "Couldn't configure VBAT-rechg CHG_CFG2_REG rc=%d\n",
Harry Yang4b7db0f2017-11-27 10:50:44 -08001905 rc);
1906 return rc;
1907 }
1908
Anirudh Ghayal1380d312018-02-23 00:01:43 +05301909 /* program the auto-recharge VBAT threshold */
1910 if (chip->dt.auto_recharge_vbat_mv != -EINVAL) {
1911 u32 temp = VBAT_TO_VRAW_ADC(chip->dt.auto_recharge_vbat_mv);
1912
1913 temp = ((temp & 0xFF00) >> 8) | ((temp & 0xFF) << 8);
1914 rc = smblib_batch_write(chg,
1915 CHGR_ADC_RECHARGE_THRESHOLD_MSB_REG, (u8 *)&temp, 2);
1916 if (rc < 0) {
1917 dev_err(chg->dev, "Couldn't configure ADC_RECHARGE_THRESHOLD REG rc=%d\n",
1918 rc);
1919 return rc;
1920 }
1921 /* Program the sample count for VBAT based recharge to 3 */
1922 rc = smblib_masked_write(chg, CHGR_NO_SAMPLE_TERM_RCHG_CFG_REG,
1923 NO_OF_SAMPLE_FOR_RCHG,
1924 2 << NO_OF_SAMPLE_FOR_RCHG_SHIFT);
1925 if (rc < 0) {
1926 dev_err(chg->dev, "Couldn't configure CHGR_NO_SAMPLE_FOR_TERM_RCHG_CFG rc=%d\n",
1927 rc);
1928 return rc;
1929 }
1930 }
1931
1932 rc = smblib_masked_write(chg, CHGR_CFG2_REG, RECHG_MASK,
1933 (chip->dt.auto_recharge_soc != -EINVAL) ?
1934 SOC_BASED_RECHG_BIT : VBAT_BASED_RECHG_BIT);
1935 if (rc < 0) {
1936 dev_err(chg->dev, "Couldn't configure SOC-rechg CHG_CFG2_REG rc=%d\n",
1937 rc);
1938 return rc;
1939 }
1940
1941 /* program the auto-recharge threshold */
1942 if (chip->dt.auto_recharge_soc != -EINVAL) {
1943 rc = smblib_write(chg, CHARGE_RCHG_SOC_THRESHOLD_CFG_REG,
1944 (chip->dt.auto_recharge_soc * 255) / 100);
1945 if (rc < 0) {
1946 dev_err(chg->dev, "Couldn't configure CHG_RCHG_SOC_REG rc=%d\n",
1947 rc);
1948 return rc;
1949 }
1950 /* Program the sample count for SOC based recharge to 1 */
1951 rc = smblib_masked_write(chg, CHGR_NO_SAMPLE_TERM_RCHG_CFG_REG,
1952 NO_OF_SAMPLE_FOR_RCHG, 0);
1953 if (rc < 0) {
1954 dev_err(chg->dev, "Couldn't configure CHGR_NO_SAMPLE_FOR_TERM_RCHG_CFG rc=%d\n",
1955 rc);
1956 return rc;
1957 }
1958 }
1959
Harry Yang4b7db0f2017-11-27 10:50:44 -08001960 if (chg->sw_jeita_enabled) {
1961 rc = smblib_disable_hw_jeita(chg, true);
1962 if (rc < 0) {
1963 dev_err(chg->dev, "Couldn't set hw jeita rc=%d\n", rc);
1964 return rc;
1965 }
1966 }
1967
Ashay Jaiswala55b7ed2018-03-23 17:23:48 +05301968 rc = smblib_configure_wdog(chg,
1969 chg->step_chg_enabled || chg->sw_jeita_enabled);
1970 if (rc < 0) {
1971 dev_err(chg->dev, "Couldn't configure watchdog rc=%d\n",
1972 rc);
1973 return rc;
1974 }
1975
Ashay Jaiswal0de6fb92018-06-12 17:23:45 +05301976 if (chg->connector_pull_up != -EINVAL) {
1977 rc = smb5_configure_internal_pull(chg, CONN_THERM,
1978 get_valid_pullup(chg->connector_pull_up));
1979 if (rc < 0) {
1980 dev_err(chg->dev,
1981 "Couldn't configure CONN_THERM pull-up rc=%d\n",
1982 rc);
1983 return rc;
1984 }
1985 }
1986
Harry Yang4b7db0f2017-11-27 10:50:44 -08001987 return rc;
1988}
1989
1990static int smb5_post_init(struct smb5 *chip)
1991{
1992 struct smb_charger *chg = &chip->chg;
1993 union power_supply_propval pval;
1994 int rc;
1995
1996 /*
1997 * In case the usb path is suspended, we would have missed disabling
1998 * the icl change interrupt because the interrupt could have been
1999 * not requested
2000 */
2001 rerun_election(chg->usb_icl_votable);
2002
2003 /* configure power role for dual-role */
2004 pval.intval = POWER_SUPPLY_TYPEC_PR_DUAL;
2005 rc = smblib_set_prop_typec_power_role(chg, &pval);
2006 if (rc < 0) {
Ashay Jaiswala9e10912018-02-02 14:03:35 +05302007 dev_err(chg->dev, "Couldn't configure DRP role rc=%d\n",
2008 rc);
Harry Yang4b7db0f2017-11-27 10:50:44 -08002009 return rc;
2010 }
2011
2012 rerun_election(chg->usb_irq_enable_votable);
2013
2014 return 0;
2015}
2016
2017/****************************
2018 * DETERMINE INITIAL STATUS *
2019 ****************************/
2020
2021static int smb5_determine_initial_status(struct smb5 *chip)
2022{
2023 struct smb_irq_data irq_data = {chip, "determine-initial-status"};
2024 struct smb_charger *chg = &chip->chg;
Harry Yang6afaea22018-03-26 19:11:07 -07002025 union power_supply_propval val;
2026 int rc;
2027
2028 rc = smblib_get_prop_usb_present(chg, &val);
2029 if (rc < 0) {
2030 pr_err("Couldn't get usb present rc=%d\n", rc);
2031 return rc;
2032 }
2033 chg->early_usb_attach = val.intval;
Harry Yang4b7db0f2017-11-27 10:50:44 -08002034
2035 if (chg->bms_psy)
2036 smblib_suspend_on_debug_battery(chg);
Ashay Jaiswala9e10912018-02-02 14:03:35 +05302037
Harry Yang4b7db0f2017-11-27 10:50:44 -08002038 usb_plugin_irq_handler(0, &irq_data);
Harry Yang6afaea22018-03-26 19:11:07 -07002039 typec_attach_detach_irq_handler(0, &irq_data);
Harry Yang4b7db0f2017-11-27 10:50:44 -08002040 typec_state_change_irq_handler(0, &irq_data);
2041 usb_source_change_irq_handler(0, &irq_data);
2042 chg_state_change_irq_handler(0, &irq_data);
2043 icl_change_irq_handler(0, &irq_data);
2044 batt_temp_changed_irq_handler(0, &irq_data);
2045 wdog_bark_irq_handler(0, &irq_data);
Ashay Jaiswala9e10912018-02-02 14:03:35 +05302046 typec_or_rid_detection_change_irq_handler(0, &irq_data);
Harry Yang4b7db0f2017-11-27 10:50:44 -08002047
2048 return 0;
2049}
2050
2051/**************************
2052 * INTERRUPT REGISTRATION *
2053 **************************/
2054
2055static struct smb_irq_info smb5_irqs[] = {
2056 /* CHARGER IRQs */
2057 [CHGR_ERROR_IRQ] = {
2058 .name = "chgr-error",
2059 .handler = default_irq_handler,
2060 },
2061 [CHG_STATE_CHANGE_IRQ] = {
2062 .name = "chg-state-change",
2063 .handler = chg_state_change_irq_handler,
Ashay Jaiswal48015c32018-03-07 18:25:43 +05302064 .wake = true,
Harry Yang4b7db0f2017-11-27 10:50:44 -08002065 },
2066 [STEP_CHG_STATE_CHANGE_IRQ] = {
2067 .name = "step-chg-state-change",
Harry Yang4b7db0f2017-11-27 10:50:44 -08002068 },
2069 [STEP_CHG_SOC_UPDATE_FAIL_IRQ] = {
2070 .name = "step-chg-soc-update-fail",
Harry Yang4b7db0f2017-11-27 10:50:44 -08002071 },
2072 [STEP_CHG_SOC_UPDATE_REQ_IRQ] = {
2073 .name = "step-chg-soc-update-req",
Harry Yang4b7db0f2017-11-27 10:50:44 -08002074 },
2075 [FG_FVCAL_QUALIFIED_IRQ] = {
2076 .name = "fg-fvcal-qualified",
Harry Yang4b7db0f2017-11-27 10:50:44 -08002077 },
2078 [VPH_ALARM_IRQ] = {
2079 .name = "vph-alarm",
Harry Yang4b7db0f2017-11-27 10:50:44 -08002080 },
2081 [VPH_DROP_PRECHG_IRQ] = {
2082 .name = "vph-drop-prechg",
Harry Yang4b7db0f2017-11-27 10:50:44 -08002083 },
2084 /* DCDC IRQs */
2085 [OTG_FAIL_IRQ] = {
2086 .name = "otg-fail",
2087 .handler = default_irq_handler,
2088 },
2089 [OTG_OC_DISABLE_SW_IRQ] = {
2090 .name = "otg-oc-disable-sw",
Harry Yang4b7db0f2017-11-27 10:50:44 -08002091 },
2092 [OTG_OC_HICCUP_IRQ] = {
2093 .name = "otg-oc-hiccup",
Harry Yang4b7db0f2017-11-27 10:50:44 -08002094 },
2095 [BSM_ACTIVE_IRQ] = {
2096 .name = "bsm-active",
Harry Yang4b7db0f2017-11-27 10:50:44 -08002097 },
2098 [HIGH_DUTY_CYCLE_IRQ] = {
2099 .name = "high-duty-cycle",
2100 .handler = high_duty_cycle_irq_handler,
Ashay Jaiswal48015c32018-03-07 18:25:43 +05302101 .wake = true,
Harry Yang4b7db0f2017-11-27 10:50:44 -08002102 },
2103 [INPUT_CURRENT_LIMITING_IRQ] = {
2104 .name = "input-current-limiting",
2105 .handler = default_irq_handler,
2106 },
2107 [CONCURRENT_MODE_DISABLE_IRQ] = {
2108 .name = "concurrent-mode-disable",
Harry Yang4b7db0f2017-11-27 10:50:44 -08002109 },
2110 [SWITCHER_POWER_OK_IRQ] = {
2111 .name = "switcher-power-ok",
2112 .handler = switcher_power_ok_irq_handler,
2113 },
2114 /* BATTERY IRQs */
2115 [BAT_TEMP_IRQ] = {
2116 .name = "bat-temp",
2117 .handler = batt_temp_changed_irq_handler,
Ashay Jaiswal48015c32018-03-07 18:25:43 +05302118 .wake = true,
Harry Yang4b7db0f2017-11-27 10:50:44 -08002119 },
2120 [ALL_CHNL_CONV_DONE_IRQ] = {
2121 .name = "all-chnl-conv-done",
Harry Yang4b7db0f2017-11-27 10:50:44 -08002122 },
2123 [BAT_OV_IRQ] = {
2124 .name = "bat-ov",
2125 .handler = batt_psy_changed_irq_handler,
2126 },
2127 [BAT_LOW_IRQ] = {
2128 .name = "bat-low",
2129 .handler = batt_psy_changed_irq_handler,
2130 },
2131 [BAT_THERM_OR_ID_MISSING_IRQ] = {
2132 .name = "bat-therm-or-id-missing",
2133 .handler = batt_psy_changed_irq_handler,
2134 },
2135 [BAT_TERMINAL_MISSING_IRQ] = {
2136 .name = "bat-terminal-missing",
2137 .handler = batt_psy_changed_irq_handler,
2138 },
2139 [BUCK_OC_IRQ] = {
2140 .name = "buck-oc",
Harry Yang4b7db0f2017-11-27 10:50:44 -08002141 },
2142 [VPH_OV_IRQ] = {
2143 .name = "vph-ov",
Harry Yang4b7db0f2017-11-27 10:50:44 -08002144 },
2145 /* USB INPUT IRQs */
2146 [USBIN_COLLAPSE_IRQ] = {
2147 .name = "usbin-collapse",
2148 .handler = default_irq_handler,
2149 },
2150 [USBIN_VASHDN_IRQ] = {
2151 .name = "usbin-vashdn",
2152 .handler = default_irq_handler,
2153 },
2154 [USBIN_UV_IRQ] = {
2155 .name = "usbin-uv",
2156 .handler = usbin_uv_irq_handler,
2157 },
2158 [USBIN_OV_IRQ] = {
2159 .name = "usbin-ov",
2160 .handler = default_irq_handler,
2161 },
2162 [USBIN_PLUGIN_IRQ] = {
2163 .name = "usbin-plugin",
2164 .handler = usb_plugin_irq_handler,
Ashay Jaiswal48015c32018-03-07 18:25:43 +05302165 .wake = true,
Harry Yang4b7db0f2017-11-27 10:50:44 -08002166 },
2167 [USBIN_REVI_CHANGE_IRQ] = {
2168 .name = "usbin-revi-change",
Harry Yang4b7db0f2017-11-27 10:50:44 -08002169 },
2170 [USBIN_SRC_CHANGE_IRQ] = {
2171 .name = "usbin-src-change",
2172 .handler = usb_source_change_irq_handler,
Ashay Jaiswal48015c32018-03-07 18:25:43 +05302173 .wake = true,
Harry Yang4b7db0f2017-11-27 10:50:44 -08002174 },
2175 [USBIN_ICL_CHANGE_IRQ] = {
2176 .name = "usbin-icl-change",
2177 .handler = icl_change_irq_handler,
Ashay Jaiswal48015c32018-03-07 18:25:43 +05302178 .wake = true,
Harry Yang4b7db0f2017-11-27 10:50:44 -08002179 },
2180 /* DC INPUT IRQs */
2181 [DCIN_VASHDN_IRQ] = {
2182 .name = "dcin-vashdn",
Harry Yang4b7db0f2017-11-27 10:50:44 -08002183 },
2184 [DCIN_UV_IRQ] = {
2185 .name = "dcin-uv",
2186 .handler = default_irq_handler,
2187 },
2188 [DCIN_OV_IRQ] = {
2189 .name = "dcin-ov",
2190 .handler = default_irq_handler,
2191 },
2192 [DCIN_PLUGIN_IRQ] = {
2193 .name = "dcin-plugin",
2194 .handler = dc_plugin_irq_handler,
2195 .wake = true,
2196 },
2197 [DCIN_REVI_IRQ] = {
2198 .name = "dcin-revi",
Harry Yang4b7db0f2017-11-27 10:50:44 -08002199 },
2200 [DCIN_PON_IRQ] = {
2201 .name = "dcin-pon",
2202 .handler = default_irq_handler,
2203 },
2204 [DCIN_EN_IRQ] = {
2205 .name = "dcin-en",
2206 .handler = default_irq_handler,
2207 },
2208 /* TYPEC IRQs */
2209 [TYPEC_OR_RID_DETECTION_CHANGE_IRQ] = {
2210 .name = "typec-or-rid-detect-change",
Ashay Jaiswala9e10912018-02-02 14:03:35 +05302211 .handler = typec_or_rid_detection_change_irq_handler,
Ashay Jaiswal48015c32018-03-07 18:25:43 +05302212 .wake = true,
Harry Yang4b7db0f2017-11-27 10:50:44 -08002213 },
2214 [TYPEC_VPD_DETECT_IRQ] = {
2215 .name = "typec-vpd-detect",
Harry Yang4b7db0f2017-11-27 10:50:44 -08002216 },
2217 [TYPEC_CC_STATE_CHANGE_IRQ] = {
2218 .name = "typec-cc-state-change",
2219 .handler = typec_state_change_irq_handler,
Ashay Jaiswal48015c32018-03-07 18:25:43 +05302220 .wake = true,
Harry Yang4b7db0f2017-11-27 10:50:44 -08002221 },
2222 [TYPEC_VCONN_OC_IRQ] = {
2223 .name = "typec-vconn-oc",
2224 .handler = default_irq_handler,
2225 },
2226 [TYPEC_VBUS_CHANGE_IRQ] = {
2227 .name = "typec-vbus-change",
Harry Yang4b7db0f2017-11-27 10:50:44 -08002228 },
2229 [TYPEC_ATTACH_DETACH_IRQ] = {
2230 .name = "typec-attach-detach",
Harry Yang6afaea22018-03-26 19:11:07 -07002231 .handler = typec_attach_detach_irq_handler,
Harry Yang4b7db0f2017-11-27 10:50:44 -08002232 },
2233 [TYPEC_LEGACY_CABLE_DETECT_IRQ] = {
2234 .name = "typec-legacy-cable-detect",
2235 .handler = default_irq_handler,
2236 },
2237 [TYPEC_TRY_SNK_SRC_DETECT_IRQ] = {
2238 .name = "typec-try-snk-src-detect",
Harry Yang4b7db0f2017-11-27 10:50:44 -08002239 },
2240 /* MISCELLANEOUS IRQs */
2241 [WDOG_SNARL_IRQ] = {
2242 .name = "wdog-snarl",
Harry Yang4b7db0f2017-11-27 10:50:44 -08002243 },
2244 [WDOG_BARK_IRQ] = {
2245 .name = "wdog-bark",
2246 .handler = wdog_bark_irq_handler,
Ashay Jaiswala55b7ed2018-03-23 17:23:48 +05302247 .wake = true,
Harry Yang4b7db0f2017-11-27 10:50:44 -08002248 },
2249 [AICL_FAIL_IRQ] = {
2250 .name = "aicl-fail",
Harry Yang4b7db0f2017-11-27 10:50:44 -08002251 },
2252 [AICL_DONE_IRQ] = {
2253 .name = "aicl-done",
2254 .handler = default_irq_handler,
2255 },
2256 [SMB_EN_IRQ] = {
2257 .name = "smb-en",
Harry Yang4b7db0f2017-11-27 10:50:44 -08002258 },
2259 [IMP_TRIGGER_IRQ] = {
2260 .name = "imp-trigger",
Harry Yang4b7db0f2017-11-27 10:50:44 -08002261 },
2262 [TEMP_CHANGE_IRQ] = {
2263 .name = "temp-change",
Harry Yang4b7db0f2017-11-27 10:50:44 -08002264 },
2265 [TEMP_CHANGE_SMB_IRQ] = {
2266 .name = "temp-change-smb",
Harry Yang4b7db0f2017-11-27 10:50:44 -08002267 },
Ashay Jaiswal09feab82018-02-12 12:33:18 +05302268 /* FLASH */
2269 [VREG_OK_IRQ] = {
2270 .name = "vreg-ok",
Ashay Jaiswal09feab82018-02-12 12:33:18 +05302271 },
2272 [ILIM_S2_IRQ] = {
2273 .name = "ilim2-s2",
2274 .handler = schgm_flash_ilim2_irq_handler,
2275 },
2276 [ILIM_S1_IRQ] = {
2277 .name = "ilim1-s1",
Ashay Jaiswal09feab82018-02-12 12:33:18 +05302278 },
2279 [VOUT_DOWN_IRQ] = {
2280 .name = "vout-down",
Ashay Jaiswal09feab82018-02-12 12:33:18 +05302281 },
2282 [VOUT_UP_IRQ] = {
2283 .name = "vout-up",
Ashay Jaiswal09feab82018-02-12 12:33:18 +05302284 },
2285 [FLASH_STATE_CHANGE_IRQ] = {
2286 .name = "flash-state-change",
2287 .handler = schgm_flash_state_change_irq_handler,
2288 },
2289 [TORCH_REQ_IRQ] = {
2290 .name = "torch-req",
Ashay Jaiswal09feab82018-02-12 12:33:18 +05302291 },
2292 [FLASH_EN_IRQ] = {
2293 .name = "flash-en",
Ashay Jaiswal09feab82018-02-12 12:33:18 +05302294 },
Harry Yang4b7db0f2017-11-27 10:50:44 -08002295};
2296
2297static int smb5_get_irq_index_byname(const char *irq_name)
2298{
2299 int i;
2300
2301 for (i = 0; i < ARRAY_SIZE(smb5_irqs); i++) {
2302 if (strcmp(smb5_irqs[i].name, irq_name) == 0)
2303 return i;
2304 }
2305
2306 return -ENOENT;
2307}
2308
2309static int smb5_request_interrupt(struct smb5 *chip,
2310 struct device_node *node, const char *irq_name)
2311{
2312 struct smb_charger *chg = &chip->chg;
2313 int rc, irq, irq_index;
2314 struct smb_irq_data *irq_data;
2315
2316 irq = of_irq_get_byname(node, irq_name);
2317 if (irq < 0) {
2318 pr_err("Couldn't get irq %s byname\n", irq_name);
2319 return irq;
2320 }
2321
2322 irq_index = smb5_get_irq_index_byname(irq_name);
2323 if (irq_index < 0) {
2324 pr_err("%s is not a defined irq\n", irq_name);
2325 return irq_index;
2326 }
2327
2328 if (!smb5_irqs[irq_index].handler)
2329 return 0;
2330
2331 irq_data = devm_kzalloc(chg->dev, sizeof(*irq_data), GFP_KERNEL);
2332 if (!irq_data)
2333 return -ENOMEM;
2334
2335 irq_data->parent_data = chip;
2336 irq_data->name = irq_name;
2337 irq_data->storm_data = smb5_irqs[irq_index].storm_data;
2338 mutex_init(&irq_data->storm_data.storm_lock);
2339
2340 rc = devm_request_threaded_irq(chg->dev, irq, NULL,
2341 smb5_irqs[irq_index].handler,
2342 IRQF_ONESHOT, irq_name, irq_data);
2343 if (rc < 0) {
2344 pr_err("Couldn't request irq %d\n", irq);
2345 return rc;
2346 }
2347
2348 smb5_irqs[irq_index].irq = irq;
2349 smb5_irqs[irq_index].irq_data = irq_data;
2350 if (smb5_irqs[irq_index].wake)
2351 enable_irq_wake(irq);
2352
2353 return rc;
2354}
2355
2356static int smb5_request_interrupts(struct smb5 *chip)
2357{
2358 struct smb_charger *chg = &chip->chg;
2359 struct device_node *node = chg->dev->of_node;
2360 struct device_node *child;
2361 int rc = 0;
2362 const char *name;
2363 struct property *prop;
2364
2365 for_each_available_child_of_node(node, child) {
2366 of_property_for_each_string(child, "interrupt-names",
2367 prop, name) {
2368 rc = smb5_request_interrupt(chip, child, name);
2369 if (rc < 0)
2370 return rc;
2371 }
2372 }
2373 if (chg->irq_info[USBIN_ICL_CHANGE_IRQ].irq)
2374 chg->usb_icl_change_irq_enabled = true;
2375
2376 return rc;
2377}
2378
2379static void smb5_free_interrupts(struct smb_charger *chg)
2380{
2381 int i;
2382
2383 for (i = 0; i < ARRAY_SIZE(smb5_irqs); i++) {
2384 if (smb5_irqs[i].irq > 0) {
2385 if (smb5_irqs[i].wake)
2386 disable_irq_wake(smb5_irqs[i].irq);
2387
2388 devm_free_irq(chg->dev, smb5_irqs[i].irq,
2389 smb5_irqs[i].irq_data);
2390 }
2391 }
2392}
2393
2394static void smb5_disable_interrupts(struct smb_charger *chg)
2395{
2396 int i;
2397
2398 for (i = 0; i < ARRAY_SIZE(smb5_irqs); i++) {
2399 if (smb5_irqs[i].irq > 0)
2400 disable_irq(smb5_irqs[i].irq);
2401 }
2402}
2403
2404#if defined(CONFIG_DEBUG_FS)
2405
2406static int force_batt_psy_update_write(void *data, u64 val)
2407{
2408 struct smb_charger *chg = data;
2409
2410 power_supply_changed(chg->batt_psy);
2411 return 0;
2412}
2413DEFINE_SIMPLE_ATTRIBUTE(force_batt_psy_update_ops, NULL,
2414 force_batt_psy_update_write, "0x%02llx\n");
2415
2416static int force_usb_psy_update_write(void *data, u64 val)
2417{
2418 struct smb_charger *chg = data;
2419
2420 power_supply_changed(chg->usb_psy);
2421 return 0;
2422}
2423DEFINE_SIMPLE_ATTRIBUTE(force_usb_psy_update_ops, NULL,
2424 force_usb_psy_update_write, "0x%02llx\n");
2425
2426static int force_dc_psy_update_write(void *data, u64 val)
2427{
2428 struct smb_charger *chg = data;
2429
2430 power_supply_changed(chg->dc_psy);
2431 return 0;
2432}
2433DEFINE_SIMPLE_ATTRIBUTE(force_dc_psy_update_ops, NULL,
2434 force_dc_psy_update_write, "0x%02llx\n");
2435
2436static void smb5_create_debugfs(struct smb5 *chip)
2437{
2438 struct dentry *file;
2439
2440 chip->dfs_root = debugfs_create_dir("charger", NULL);
2441 if (IS_ERR_OR_NULL(chip->dfs_root)) {
2442 pr_err("Couldn't create charger debugfs rc=%ld\n",
2443 (long)chip->dfs_root);
2444 return;
2445 }
2446
2447 file = debugfs_create_file("force_batt_psy_update", 0600,
2448 chip->dfs_root, chip, &force_batt_psy_update_ops);
2449 if (IS_ERR_OR_NULL(file))
2450 pr_err("Couldn't create force_batt_psy_update file rc=%ld\n",
2451 (long)file);
2452
2453 file = debugfs_create_file("force_usb_psy_update", 0600,
2454 chip->dfs_root, chip, &force_usb_psy_update_ops);
2455 if (IS_ERR_OR_NULL(file))
2456 pr_err("Couldn't create force_usb_psy_update file rc=%ld\n",
2457 (long)file);
2458
2459 file = debugfs_create_file("force_dc_psy_update", 0600,
2460 chip->dfs_root, chip, &force_dc_psy_update_ops);
2461 if (IS_ERR_OR_NULL(file))
2462 pr_err("Couldn't create force_dc_psy_update file rc=%ld\n",
2463 (long)file);
2464}
2465
2466#else
2467
2468static void smb5_create_debugfs(struct smb5 *chip)
2469{}
2470
2471#endif
2472
2473static int smb5_show_charger_status(struct smb5 *chip)
2474{
2475 struct smb_charger *chg = &chip->chg;
2476 union power_supply_propval val;
2477 int usb_present, batt_present, batt_health, batt_charge_type;
2478 int rc;
2479
2480 rc = smblib_get_prop_usb_present(chg, &val);
2481 if (rc < 0) {
2482 pr_err("Couldn't get usb present rc=%d\n", rc);
2483 return rc;
2484 }
2485 usb_present = val.intval;
2486
2487 rc = smblib_get_prop_batt_present(chg, &val);
2488 if (rc < 0) {
2489 pr_err("Couldn't get batt present rc=%d\n", rc);
2490 return rc;
2491 }
2492 batt_present = val.intval;
2493
2494 rc = smblib_get_prop_batt_health(chg, &val);
2495 if (rc < 0) {
2496 pr_err("Couldn't get batt health rc=%d\n", rc);
2497 val.intval = POWER_SUPPLY_HEALTH_UNKNOWN;
2498 }
2499 batt_health = val.intval;
2500
2501 rc = smblib_get_prop_batt_charge_type(chg, &val);
2502 if (rc < 0) {
2503 pr_err("Couldn't get batt charge type rc=%d\n", rc);
2504 return rc;
2505 }
2506 batt_charge_type = val.intval;
2507
2508 pr_info("SMB5 status - usb:present=%d type=%d batt:present = %d health = %d charge = %d\n",
2509 usb_present, chg->real_charger_type,
2510 batt_present, batt_health, batt_charge_type);
2511 return rc;
2512}
2513
2514static int smb5_probe(struct platform_device *pdev)
2515{
2516 struct smb5 *chip;
2517 struct smb_charger *chg;
2518 int rc = 0;
2519
2520 chip = devm_kzalloc(&pdev->dev, sizeof(*chip), GFP_KERNEL);
2521 if (!chip)
2522 return -ENOMEM;
2523
2524 chg = &chip->chg;
2525 chg->dev = &pdev->dev;
Harry Yang4b7db0f2017-11-27 10:50:44 -08002526 chg->debug_mask = &__debug_mask;
Harry Yang6afaea22018-03-26 19:11:07 -07002527 chg->pd_disabled = &__pd_disabled;
Harry Yang4b7db0f2017-11-27 10:50:44 -08002528 chg->weak_chg_icl_ua = &__weak_chg_icl_ua;
2529 chg->mode = PARALLEL_MASTER;
2530 chg->irq_info = smb5_irqs;
2531 chg->die_health = -EINVAL;
Ashay Jaiswala9e10912018-02-02 14:03:35 +05302532 chg->otg_present = false;
Harry Yang4b7db0f2017-11-27 10:50:44 -08002533
2534 chg->regmap = dev_get_regmap(chg->dev->parent, NULL);
2535 if (!chg->regmap) {
2536 pr_err("parent regmap is missing\n");
2537 return -EINVAL;
2538 }
2539
Ashay Jaiswala9e10912018-02-02 14:03:35 +05302540 rc = smb5_chg_config_init(chip);
2541 if (rc < 0) {
2542 if (rc != -EPROBE_DEFER)
2543 pr_err("Couldn't setup chg_config rc=%d\n", rc);
2544 return rc;
Harry Yang4b7db0f2017-11-27 10:50:44 -08002545 }
2546
Ashay Jaiswalb2b06fe2018-06-07 18:35:21 +05302547 rc = smb5_parse_dt(chip);
2548 if (rc < 0) {
2549 pr_err("Couldn't parse device tree rc=%d\n", rc);
2550 return rc;
2551 }
2552
Harry Yang4b7db0f2017-11-27 10:50:44 -08002553 rc = smblib_init(chg);
2554 if (rc < 0) {
2555 pr_err("Smblib_init failed rc=%d\n", rc);
Ashay Jaiswala9e10912018-02-02 14:03:35 +05302556 return rc;
Harry Yang4b7db0f2017-11-27 10:50:44 -08002557 }
2558
2559 /* set driver data before resources request it */
2560 platform_set_drvdata(pdev, chip);
2561
2562 rc = smb5_init_vbus_regulator(chip);
2563 if (rc < 0) {
2564 pr_err("Couldn't initialize vbus regulator rc=%d\n",
2565 rc);
2566 goto cleanup;
2567 }
2568
2569 rc = smb5_init_vconn_regulator(chip);
2570 if (rc < 0) {
2571 pr_err("Couldn't initialize vconn regulator rc=%d\n",
2572 rc);
2573 goto cleanup;
2574 }
2575
2576 /* extcon registration */
2577 chg->extcon = devm_extcon_dev_allocate(chg->dev, smblib_extcon_cable);
2578 if (IS_ERR(chg->extcon)) {
2579 rc = PTR_ERR(chg->extcon);
2580 dev_err(chg->dev, "failed to allocate extcon device rc=%d\n",
2581 rc);
2582 goto cleanup;
2583 }
2584
2585 rc = devm_extcon_dev_register(chg->dev, chg->extcon);
2586 if (rc < 0) {
2587 dev_err(chg->dev, "failed to register extcon device rc=%d\n",
2588 rc);
2589 goto cleanup;
2590 }
2591
2592 rc = smb5_init_hw(chip);
2593 if (rc < 0) {
2594 pr_err("Couldn't initialize hardware rc=%d\n", rc);
2595 goto cleanup;
2596 }
2597
Ashay Jaiswala9e10912018-02-02 14:03:35 +05302598 if (chg->smb_version == PM855B_SUBTYPE) {
2599 rc = smb5_init_dc_psy(chip);
2600 if (rc < 0) {
2601 pr_err("Couldn't initialize dc psy rc=%d\n", rc);
2602 goto cleanup;
2603 }
Harry Yang4b7db0f2017-11-27 10:50:44 -08002604 }
2605
2606 rc = smb5_init_usb_psy(chip);
2607 if (rc < 0) {
2608 pr_err("Couldn't initialize usb psy rc=%d\n", rc);
2609 goto cleanup;
2610 }
2611
2612 rc = smb5_init_usb_main_psy(chip);
2613 if (rc < 0) {
2614 pr_err("Couldn't initialize usb main psy rc=%d\n", rc);
2615 goto cleanup;
2616 }
2617
2618 rc = smb5_init_usb_port_psy(chip);
2619 if (rc < 0) {
2620 pr_err("Couldn't initialize usb pc_port psy rc=%d\n", rc);
2621 goto cleanup;
2622 }
2623
2624 rc = smb5_init_batt_psy(chip);
2625 if (rc < 0) {
2626 pr_err("Couldn't initialize batt psy rc=%d\n", rc);
2627 goto cleanup;
2628 }
2629
2630 rc = smb5_determine_initial_status(chip);
2631 if (rc < 0) {
2632 pr_err("Couldn't determine initial status rc=%d\n",
2633 rc);
2634 goto cleanup;
2635 }
2636
2637 rc = smb5_request_interrupts(chip);
2638 if (rc < 0) {
2639 pr_err("Couldn't request interrupts rc=%d\n", rc);
2640 goto cleanup;
2641 }
2642
2643 rc = smb5_post_init(chip);
2644 if (rc < 0) {
2645 pr_err("Failed in post init rc=%d\n", rc);
Ashay Jaiswala9e10912018-02-02 14:03:35 +05302646 goto free_irq;
Harry Yang4b7db0f2017-11-27 10:50:44 -08002647 }
2648
2649 smb5_create_debugfs(chip);
2650
2651 rc = smb5_show_charger_status(chip);
2652 if (rc < 0) {
2653 pr_err("Failed in getting charger status rc=%d\n", rc);
Ashay Jaiswala9e10912018-02-02 14:03:35 +05302654 goto free_irq;
Harry Yang4b7db0f2017-11-27 10:50:44 -08002655 }
2656
2657 device_init_wakeup(chg->dev, true);
2658
2659 pr_info("QPNP SMB5 probed successfully\n");
2660
2661 return rc;
2662
Ashay Jaiswala9e10912018-02-02 14:03:35 +05302663free_irq:
Harry Yang4b7db0f2017-11-27 10:50:44 -08002664 smb5_free_interrupts(chg);
Ashay Jaiswala9e10912018-02-02 14:03:35 +05302665cleanup:
Harry Yang4b7db0f2017-11-27 10:50:44 -08002666 smblib_deinit(chg);
2667 platform_set_drvdata(pdev, NULL);
2668
2669 return rc;
2670}
2671
2672static int smb5_remove(struct platform_device *pdev)
2673{
2674 struct smb5 *chip = platform_get_drvdata(pdev);
2675 struct smb_charger *chg = &chip->chg;
2676
Harry Yang6afaea22018-03-26 19:11:07 -07002677 /* force enable APSD */
2678 smblib_masked_write(chg, USBIN_OPTIONS_1_CFG_REG,
2679 BC1P2_SRC_DETECT_BIT, BC1P2_SRC_DETECT_BIT);
2680
Harry Yang4b7db0f2017-11-27 10:50:44 -08002681 smb5_free_interrupts(chg);
2682 smblib_deinit(chg);
2683 platform_set_drvdata(pdev, NULL);
2684 return 0;
2685}
2686
2687static void smb5_shutdown(struct platform_device *pdev)
2688{
2689 struct smb5 *chip = platform_get_drvdata(pdev);
2690 struct smb_charger *chg = &chip->chg;
2691
2692 /* disable all interrupts */
2693 smb5_disable_interrupts(chg);
2694
2695 /* configure power role for UFP */
Ashay Jaiswala9e10912018-02-02 14:03:35 +05302696 if (chg->connector_type == POWER_SUPPLY_CONNECTOR_TYPEC)
Harry Yang4b7db0f2017-11-27 10:50:44 -08002697 smblib_masked_write(chg, TYPE_C_MODE_CFG_REG,
2698 TYPEC_POWER_ROLE_CMD_MASK, EN_SNK_ONLY_BIT);
2699
2700 /* force HVDCP to 5V */
2701 smblib_masked_write(chg, USBIN_OPTIONS_1_CFG_REG,
2702 HVDCP_AUTONOMOUS_MODE_EN_CFG_BIT, 0);
2703 smblib_write(chg, CMD_HVDCP_2_REG, FORCE_5V_BIT);
2704
2705 /* force enable APSD */
2706 smblib_masked_write(chg, USBIN_OPTIONS_1_CFG_REG,
2707 BC1P2_SRC_DETECT_BIT, BC1P2_SRC_DETECT_BIT);
2708}
2709
2710static const struct of_device_id match_table[] = {
2711 { .compatible = "qcom,qpnp-smb5", },
2712 { },
2713};
2714
2715static struct platform_driver smb5_driver = {
2716 .driver = {
2717 .name = "qcom,qpnp-smb5",
2718 .owner = THIS_MODULE,
2719 .of_match_table = match_table,
2720 },
2721 .probe = smb5_probe,
2722 .remove = smb5_remove,
2723 .shutdown = smb5_shutdown,
2724};
2725module_platform_driver(smb5_driver);
2726
2727MODULE_DESCRIPTION("QPNP SMB5 Charger Driver");
2728MODULE_LICENSE("GPL v2");