blob: e94873c5252ef31a92591c8bf1368b930e140b57 [file] [log] [blame]
Harry Yang3b113a52016-12-08 12:37:40 -08001/* Copyright (c) 2016-2017 The Linux Foundation. All rights reserved.
Nicholas Troast96886052016-02-25 15:42:17 -08002 *
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
Nicholas Troastfd6729f2016-09-21 17:51:00 -070013#include <linux/debugfs.h>
Ashay Jaiswal82669ba2017-03-11 01:08:37 +053014#include <linux/delay.h>
Nicholas Troast96886052016-02-25 15:42:17 -080015#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>
Nicholas Troast96886052016-02-25 15:42:17 -080020#include <linux/of.h>
21#include <linux/of_irq.h>
Harry Yangf7251982016-09-16 11:14:49 -070022#include <linux/qpnp/qpnp-revid.h>
Nicholas Troast96886052016-02-25 15:42:17 -080023#include <linux/regulator/driver.h>
24#include <linux/regulator/of_regulator.h>
25#include <linux/regulator/machine.h>
26#include "smb-reg.h"
27#include "smb-lib.h"
Nicholas Troast47ae4612016-08-03 09:49:36 -070028#include "storm-watch.h"
Abhijeet Dharmapurikardd119c62017-03-20 15:54:59 -070029#include <linux/pmic-voter.h>
Nicholas Troast96886052016-02-25 15:42:17 -080030
Abhijeet Dharmapurikar5cf5faf2016-06-21 14:20:24 -070031#define SMB2_DEFAULT_WPWR_UW 8000000
Nicholas Troast96886052016-02-25 15:42:17 -080032
33static struct smb_params v1_params = {
Abhijeet Dharmapurikar5cf5faf2016-06-21 14:20:24 -070034 .fcc = {
Harry Yang1d1034c2016-06-15 12:09:42 -070035 .name = "fast charge current",
36 .reg = FAST_CHARGE_CURRENT_CFG_REG,
37 .min_u = 0,
38 .max_u = 4500000,
39 .step_u = 25000,
Nicholas Troast96886052016-02-25 15:42:17 -080040 },
Abhijeet Dharmapurikar5cf5faf2016-06-21 14:20:24 -070041 .fv = {
Harry Yang1d1034c2016-06-15 12:09:42 -070042 .name = "float voltage",
43 .reg = FLOAT_VOLTAGE_CFG_REG,
Harry Yangfe913842016-08-10 12:27:28 -070044 .min_u = 3487500,
45 .max_u = 4920000,
46 .step_u = 7500,
Nicholas Troast96886052016-02-25 15:42:17 -080047 },
Abhijeet Dharmapurikar5cf5faf2016-06-21 14:20:24 -070048 .usb_icl = {
Harry Yang1d1034c2016-06-15 12:09:42 -070049 .name = "usb input current limit",
50 .reg = USBIN_CURRENT_LIMIT_CFG_REG,
51 .min_u = 0,
Harry Yangfe913842016-08-10 12:27:28 -070052 .max_u = 4800000,
Harry Yang1d1034c2016-06-15 12:09:42 -070053 .step_u = 25000,
Nicholas Troast96886052016-02-25 15:42:17 -080054 },
Abhijeet Dharmapurikar5cf5faf2016-06-21 14:20:24 -070055 .icl_stat = {
Harry Yang1d1034c2016-06-15 12:09:42 -070056 .name = "input current limit status",
57 .reg = ICL_STATUS_REG,
58 .min_u = 0,
59 .max_u = 4800000,
60 .step_u = 25000,
61 },
Harry Yang360bd532016-09-26 11:03:22 -070062 .otg_cl = {
63 .name = "usb otg current limit",
64 .reg = OTG_CURRENT_LIMIT_CFG_REG,
65 .min_u = 250000,
66 .max_u = 2000000,
67 .step_u = 250000,
68 },
Abhijeet Dharmapurikar5cf5faf2016-06-21 14:20:24 -070069 .dc_icl = {
Harry Yang1d1034c2016-06-15 12:09:42 -070070 .name = "dc input current limit",
71 .reg = DCIN_CURRENT_LIMIT_CFG_REG,
72 .min_u = 0,
Abhijeet Dharmapurikar5cf5faf2016-06-21 14:20:24 -070073 .max_u = 6000000,
74 .step_u = 25000,
75 },
76 .dc_icl_pt_lv = {
77 .name = "dc icl PT <8V",
78 .reg = ZIN_ICL_PT_REG,
79 .min_u = 0,
80 .max_u = 3000000,
81 .step_u = 25000,
82 },
83 .dc_icl_pt_hv = {
84 .name = "dc icl PT >8V",
85 .reg = ZIN_ICL_PT_HV_REG,
86 .min_u = 0,
87 .max_u = 3000000,
88 .step_u = 25000,
89 },
90 .dc_icl_div2_lv = {
91 .name = "dc icl div2 <5.5V",
92 .reg = ZIN_ICL_LV_REG,
93 .min_u = 0,
94 .max_u = 3000000,
95 .step_u = 25000,
96 },
97 .dc_icl_div2_mid_lv = {
98 .name = "dc icl div2 5.5-6.5V",
99 .reg = ZIN_ICL_MID_LV_REG,
100 .min_u = 0,
101 .max_u = 3000000,
102 .step_u = 25000,
103 },
104 .dc_icl_div2_mid_hv = {
105 .name = "dc icl div2 6.5-8.0V",
106 .reg = ZIN_ICL_MID_HV_REG,
107 .min_u = 0,
108 .max_u = 3000000,
109 .step_u = 25000,
110 },
111 .dc_icl_div2_hv = {
112 .name = "dc icl div2 >8.0V",
113 .reg = ZIN_ICL_HV_REG,
114 .min_u = 0,
Harry Yang1d1034c2016-06-15 12:09:42 -0700115 .max_u = 3000000,
116 .step_u = 25000,
Nicholas Troast96886052016-02-25 15:42:17 -0800117 },
Abhijeet Dharmapurikar2644cd62016-07-20 16:54:55 -0700118 .jeita_cc_comp = {
119 .name = "jeita fcc reduction",
120 .reg = JEITA_CCCOMP_CFG_REG,
121 .min_u = 0,
122 .max_u = 1575000,
123 .step_u = 25000,
124 },
Harry Yangfe913842016-08-10 12:27:28 -0700125 .step_soc_threshold[0] = {
126 .name = "step charge soc threshold 1",
127 .reg = STEP_CHG_SOC_OR_BATT_V_TH1_REG,
128 .min_u = 0,
129 .max_u = 100,
130 .step_u = 1,
131 },
132 .step_soc_threshold[1] = {
133 .name = "step charge soc threshold 2",
134 .reg = STEP_CHG_SOC_OR_BATT_V_TH2_REG,
135 .min_u = 0,
136 .max_u = 100,
137 .step_u = 1,
138 },
139 .step_soc_threshold[2] = {
140 .name = "step charge soc threshold 3",
141 .reg = STEP_CHG_SOC_OR_BATT_V_TH3_REG,
142 .min_u = 0,
143 .max_u = 100,
144 .step_u = 1,
145 },
146 .step_soc_threshold[3] = {
147 .name = "step charge soc threshold 4",
148 .reg = STEP_CHG_SOC_OR_BATT_V_TH4_REG,
149 .min_u = 0,
150 .max_u = 100,
151 .step_u = 1,
152 },
153 .step_soc = {
154 .name = "step charge soc",
155 .reg = STEP_CHG_SOC_VBATT_V_REG,
156 .min_u = 0,
157 .max_u = 100,
158 .step_u = 1,
159 .set_proc = smblib_mapping_soc_from_field_value,
160 },
161 .step_cc_delta[0] = {
162 .name = "step charge current delta 1",
163 .reg = STEP_CHG_CURRENT_DELTA1_REG,
164 .min_u = 100000,
165 .max_u = 3200000,
166 .step_u = 100000,
167 .get_proc = smblib_mapping_cc_delta_to_field_value,
168 .set_proc = smblib_mapping_cc_delta_from_field_value,
169 },
170 .step_cc_delta[1] = {
171 .name = "step charge current delta 2",
172 .reg = STEP_CHG_CURRENT_DELTA2_REG,
173 .min_u = 100000,
174 .max_u = 3200000,
175 .step_u = 100000,
176 .get_proc = smblib_mapping_cc_delta_to_field_value,
177 .set_proc = smblib_mapping_cc_delta_from_field_value,
178 },
179 .step_cc_delta[2] = {
180 .name = "step charge current delta 3",
181 .reg = STEP_CHG_CURRENT_DELTA3_REG,
182 .min_u = 100000,
183 .max_u = 3200000,
184 .step_u = 100000,
185 .get_proc = smblib_mapping_cc_delta_to_field_value,
186 .set_proc = smblib_mapping_cc_delta_from_field_value,
187 },
188 .step_cc_delta[3] = {
189 .name = "step charge current delta 4",
190 .reg = STEP_CHG_CURRENT_DELTA4_REG,
191 .min_u = 100000,
192 .max_u = 3200000,
193 .step_u = 100000,
194 .get_proc = smblib_mapping_cc_delta_to_field_value,
195 .set_proc = smblib_mapping_cc_delta_from_field_value,
196 },
197 .step_cc_delta[4] = {
198 .name = "step charge current delta 5",
199 .reg = STEP_CHG_CURRENT_DELTA5_REG,
200 .min_u = 100000,
201 .max_u = 3200000,
202 .step_u = 100000,
203 .get_proc = smblib_mapping_cc_delta_to_field_value,
204 .set_proc = smblib_mapping_cc_delta_from_field_value,
205 },
Harry Yangcdad2bf2016-10-04 17:03:56 -0700206 .freq_buck = {
207 .name = "buck switching frequency",
208 .reg = CFG_BUCKBOOST_FREQ_SELECT_BUCK_REG,
209 .min_u = 600,
210 .max_u = 2000,
211 .step_u = 200,
212 },
Harry Yangd89ff1f2016-12-05 14:59:11 -0800213 .freq_boost = {
214 .name = "boost switching frequency",
215 .reg = CFG_BUCKBOOST_FREQ_SELECT_BOOST_REG,
216 .min_u = 600,
217 .max_u = 2000,
218 .step_u = 200,
219 },
Nicholas Troast96886052016-02-25 15:42:17 -0800220};
221
Anirudh Ghayal4da3df92017-01-25 18:55:57 +0530222static struct smb_params pm660_params = {
223 .freq_buck = {
224 .name = "buck switching frequency",
225 .reg = FREQ_CLK_DIV_REG,
226 .min_u = 600,
227 .max_u = 1600,
228 .set_proc = smblib_set_chg_freq,
229 },
230 .freq_boost = {
231 .name = "boost switching frequency",
232 .reg = FREQ_CLK_DIV_REG,
233 .min_u = 600,
234 .max_u = 1600,
235 .set_proc = smblib_set_chg_freq,
236 },
237};
238
Harry Yangfe913842016-08-10 12:27:28 -0700239#define STEP_CHARGING_MAX_STEPS 5
Nicholas Troast96886052016-02-25 15:42:17 -0800240struct smb_dt_props {
Abhijeet Dharmapurikar5cf5faf2016-06-21 14:20:24 -0700241 int usb_icl_ua;
242 int dc_icl_ua;
Harry Yangd89ff1f2016-12-05 14:59:11 -0800243 int boost_threshold_ua;
Abhijeet Dharmapurikar5cf5faf2016-06-21 14:20:24 -0700244 int wipower_max_uw;
Anirudh Ghayalca8ce4d2017-04-10 08:27:11 +0530245 int min_freq_khz;
246 int max_freq_khz;
Harry Yangfe913842016-08-10 12:27:28 -0700247 u32 step_soc_threshold[STEP_CHARGING_MAX_STEPS - 1];
248 s32 step_cc_delta[STEP_CHARGING_MAX_STEPS];
Harry Yangf7251982016-09-16 11:14:49 -0700249 struct device_node *revid_dev_node;
Nicholas Troast597acfe2016-07-20 16:03:15 -0700250 int float_option;
Subbaraman Narayanamurthy5c4f6de2016-11-02 15:25:32 -0700251 int chg_inhibit_thr_mv;
Subbaraman Narayanamurthy851f4172016-11-15 19:39:08 -0800252 bool no_battery;
Abhijeet Dharmapurikarf0b0a042016-10-10 16:43:43 -0700253 bool hvdcp_disable;
Subbaraman Narayanamurthy851f4172016-11-15 19:39:08 -0800254 bool auto_recharge_soc;
Nicholas Troast96886052016-02-25 15:42:17 -0800255};
256
257struct smb2 {
Nicholas Troastfd6729f2016-09-21 17:51:00 -0700258 struct smb_charger chg;
259 struct dentry *dfs_root;
260 struct smb_dt_props dt;
261 bool bad_part;
Nicholas Troast96886052016-02-25 15:42:17 -0800262};
263
264static int __debug_mask;
265module_param_named(
266 debug_mask, __debug_mask, int, 0600
267);
268
Ashay Jaiswal2f3b0c12017-06-14 16:04:45 +0530269static int __weak_chg_icl_ua = 500000;
270module_param_named(
271 weak_chg_icl_ua, __weak_chg_icl_ua, int, 0600);
272
Ashay Jaiswal1bf41332017-05-03 15:10:25 +0530273#define MICRO_1P5A 1500000
274#define MICRO_P1A 100000
275#define OTG_DEFAULT_DEGLITCH_TIME_MS 50
Nicholas Troast96886052016-02-25 15:42:17 -0800276static int smb2_parse_dt(struct smb2 *chip)
277{
278 struct smb_charger *chg = &chip->chg;
279 struct device_node *node = chg->dev->of_node;
Abhijeet Dharmapurikar99fb8942016-07-08 11:39:23 -0700280 int rc, byte_len;
Nicholas Troast96886052016-02-25 15:42:17 -0800281
282 if (!node) {
283 pr_err("device tree node missing\n");
284 return -EINVAL;
285 }
286
Harry Yangfe913842016-08-10 12:27:28 -0700287 chg->step_chg_enabled = true;
288
289 if (of_property_count_u32_elems(node, "qcom,step-soc-thresholds")
290 != STEP_CHARGING_MAX_STEPS - 1)
291 chg->step_chg_enabled = false;
292
293 rc = of_property_read_u32_array(node, "qcom,step-soc-thresholds",
294 chip->dt.step_soc_threshold,
295 STEP_CHARGING_MAX_STEPS - 1);
296 if (rc < 0)
297 chg->step_chg_enabled = false;
298
299 if (of_property_count_u32_elems(node, "qcom,step-current-deltas")
300 != STEP_CHARGING_MAX_STEPS)
301 chg->step_chg_enabled = false;
302
303 rc = of_property_read_u32_array(node, "qcom,step-current-deltas",
304 chip->dt.step_cc_delta,
305 STEP_CHARGING_MAX_STEPS);
306 if (rc < 0)
307 chg->step_chg_enabled = false;
308
Nicholas Troast2ebe6c52016-09-20 13:25:59 -0700309 chip->dt.no_battery = of_property_read_bool(node,
310 "qcom,batteryless-platform");
Nicholas Troast96886052016-02-25 15:42:17 -0800311
312 rc = of_property_read_u32(node,
Abhijeet Dharmapurikarc31b4ab2017-04-27 19:20:31 -0700313 "qcom,fcc-max-ua", &chg->batt_profile_fcc_ua);
Nicholas Troast96886052016-02-25 15:42:17 -0800314 if (rc < 0)
Abhijeet Dharmapurikarc31b4ab2017-04-27 19:20:31 -0700315 chg->batt_profile_fcc_ua = -EINVAL;
Nicholas Troast96886052016-02-25 15:42:17 -0800316
317 rc = of_property_read_u32(node,
Abhijeet Dharmapurikarc31b4ab2017-04-27 19:20:31 -0700318 "qcom,fv-max-uv", &chg->batt_profile_fv_uv);
Abhijeet Dharmapurikarf9805d42016-05-17 18:38:42 -0700319 if (rc < 0)
Abhijeet Dharmapurikarc31b4ab2017-04-27 19:20:31 -0700320 chg->batt_profile_fv_uv = -EINVAL;
Abhijeet Dharmapurikarf9805d42016-05-17 18:38:42 -0700321
322 rc = of_property_read_u32(node,
Nicholas Troast96886052016-02-25 15:42:17 -0800323 "qcom,usb-icl-ua", &chip->dt.usb_icl_ua);
324 if (rc < 0)
Nicholas Troast4f2d7962016-07-27 11:08:10 -0700325 chip->dt.usb_icl_ua = -EINVAL;
Nicholas Troast96886052016-02-25 15:42:17 -0800326
327 rc = of_property_read_u32(node,
Ashay Jaiswal7c241382017-03-06 15:26:38 +0530328 "qcom,otg-cl-ua", &chg->otg_cl_ua);
Harry Yang360bd532016-09-26 11:03:22 -0700329 if (rc < 0)
Ashay Jaiswal7c241382017-03-06 15:26:38 +0530330 chg->otg_cl_ua = MICRO_1P5A;
Harry Yang360bd532016-09-26 11:03:22 -0700331
332 rc = of_property_read_u32(node,
Nicholas Troast96886052016-02-25 15:42:17 -0800333 "qcom,dc-icl-ua", &chip->dt.dc_icl_ua);
334 if (rc < 0)
Nicholas Troast4f2d7962016-07-27 11:08:10 -0700335 chip->dt.dc_icl_ua = -EINVAL;
Nicholas Troast96886052016-02-25 15:42:17 -0800336
Harry Yangd89ff1f2016-12-05 14:59:11 -0800337 rc = of_property_read_u32(node,
338 "qcom,boost-threshold-ua",
339 &chip->dt.boost_threshold_ua);
340 if (rc < 0)
341 chip->dt.boost_threshold_ua = MICRO_P1A;
342
Anirudh Ghayalca8ce4d2017-04-10 08:27:11 +0530343 rc = of_property_read_u32(node,
344 "qcom,min-freq-khz",
345 &chip->dt.min_freq_khz);
346 if (rc < 0)
347 chip->dt.min_freq_khz = -EINVAL;
348
349 rc = of_property_read_u32(node,
350 "qcom,max-freq-khz",
351 &chip->dt.max_freq_khz);
352 if (rc < 0)
353 chip->dt.max_freq_khz = -EINVAL;
354
Vic Wei373e0272016-08-11 01:39:11 -0700355 rc = of_property_read_u32(node, "qcom,wipower-max-uw",
356 &chip->dt.wipower_max_uw);
Abhijeet Dharmapurikar5cf5faf2016-06-21 14:20:24 -0700357 if (rc < 0)
Vic Wei373e0272016-08-11 01:39:11 -0700358 chip->dt.wipower_max_uw = -EINVAL;
Abhijeet Dharmapurikar5cf5faf2016-06-21 14:20:24 -0700359
Abhijeet Dharmapurikar99fb8942016-07-08 11:39:23 -0700360 if (of_find_property(node, "qcom,thermal-mitigation", &byte_len)) {
361 chg->thermal_mitigation = devm_kzalloc(chg->dev, byte_len,
362 GFP_KERNEL);
363
364 if (chg->thermal_mitigation == NULL)
365 return -ENOMEM;
366
367 chg->thermal_levels = byte_len / sizeof(u32);
368 rc = of_property_read_u32_array(node,
369 "qcom,thermal-mitigation",
370 chg->thermal_mitigation,
371 chg->thermal_levels);
372 if (rc < 0) {
373 dev_err(chg->dev,
374 "Couldn't read threm limits rc = %d\n", rc);
375 return rc;
376 }
377 }
378
Nicholas Troast597acfe2016-07-20 16:03:15 -0700379 of_property_read_u32(node, "qcom,float-option", &chip->dt.float_option);
380 if (chip->dt.float_option < 0 || chip->dt.float_option > 4) {
381 pr_err("qcom,float-option is out of range [0, 4]\n");
382 return -EINVAL;
383 }
384
Abhijeet Dharmapurikarf0b0a042016-10-10 16:43:43 -0700385 chip->dt.hvdcp_disable = of_property_read_bool(node,
386 "qcom,hvdcp-disable");
387
Subbaraman Narayanamurthy5c4f6de2016-11-02 15:25:32 -0700388 of_property_read_u32(node, "qcom,chg-inhibit-threshold-mv",
389 &chip->dt.chg_inhibit_thr_mv);
390 if ((chip->dt.chg_inhibit_thr_mv < 0 ||
391 chip->dt.chg_inhibit_thr_mv > 300)) {
392 pr_err("qcom,chg-inhibit-threshold-mv is incorrect\n");
393 return -EINVAL;
394 }
395
Subbaraman Narayanamurthy851f4172016-11-15 19:39:08 -0800396 chip->dt.auto_recharge_soc = of_property_read_bool(node,
397 "qcom,auto-recharge-soc");
Ashay Jaiswal4aa2c0c2016-12-07 19:39:38 +0530398
399 chg->micro_usb_mode = of_property_read_bool(node, "qcom,micro-usb");
400
Abhijeet Dharmapurikar95670872017-02-09 22:55:51 +0530401 chg->dcp_icl_ua = chip->dt.usb_icl_ua;
402
Ashay Jaiswalda8669b2017-02-10 23:24:23 +0530403 chg->suspend_input_on_debug_batt = of_property_read_bool(node,
404 "qcom,suspend-input-on-debug-batt");
Ashay Jaiswal1bf41332017-05-03 15:10:25 +0530405
406 rc = of_property_read_u32(node, "qcom,otg-deglitch-time-ms",
407 &chg->otg_delay_ms);
408 if (rc < 0)
409 chg->otg_delay_ms = OTG_DEFAULT_DEGLITCH_TIME_MS;
410
Nicholas Troast96886052016-02-25 15:42:17 -0800411 return 0;
412}
413
414/************************
415 * USB PSY REGISTRATION *
416 ************************/
417
418static enum power_supply_property smb2_usb_props[] = {
419 POWER_SUPPLY_PROP_PRESENT,
420 POWER_SUPPLY_PROP_ONLINE,
421 POWER_SUPPLY_PROP_VOLTAGE_MIN,
422 POWER_SUPPLY_PROP_VOLTAGE_MAX,
423 POWER_SUPPLY_PROP_VOLTAGE_NOW,
Abhijeet Dharmapurikard92eca62016-10-07 19:04:33 -0700424 POWER_SUPPLY_PROP_PD_CURRENT_MAX,
Nicholas Troast96886052016-02-25 15:42:17 -0800425 POWER_SUPPLY_PROP_CURRENT_MAX,
426 POWER_SUPPLY_PROP_TYPE,
427 POWER_SUPPLY_PROP_TYPEC_MODE,
428 POWER_SUPPLY_PROP_TYPEC_POWER_ROLE,
429 POWER_SUPPLY_PROP_TYPEC_CC_ORIENTATION,
430 POWER_SUPPLY_PROP_PD_ALLOWED,
431 POWER_SUPPLY_PROP_PD_ACTIVE,
Nicholas Troast133a7f52016-06-29 13:48:20 -0700432 POWER_SUPPLY_PROP_INPUT_CURRENT_SETTLED,
Harry Yangba874ce2016-08-19 14:17:01 -0700433 POWER_SUPPLY_PROP_INPUT_CURRENT_NOW,
Harry Yangd89ff1f2016-12-05 14:59:11 -0800434 POWER_SUPPLY_PROP_BOOST_CURRENT,
Abhijeet Dharmapurikarb9598872016-10-17 16:58:58 -0700435 POWER_SUPPLY_PROP_PE_START,
Nicholas Troaste1b0c042017-02-09 10:05:03 -0800436 POWER_SUPPLY_PROP_CTM_CURRENT_MAX,
Abhijeet Dharmapurikarf59c8352017-03-23 14:04:05 -0700437 POWER_SUPPLY_PROP_HW_CURRENT_MAX,
Fenglin Wu80826e02017-04-25 21:45:08 +0800438 POWER_SUPPLY_PROP_REAL_TYPE,
Abhijeet Dharmapurikar255da952017-05-24 20:52:09 -0700439 POWER_SUPPLY_PROP_PR_SWAP,
Nicholas Troast96886052016-02-25 15:42:17 -0800440};
441
442static int smb2_usb_get_prop(struct power_supply *psy,
443 enum power_supply_property psp,
444 union power_supply_propval *val)
445{
446 struct smb2 *chip = power_supply_get_drvdata(psy);
447 struct smb_charger *chg = &chip->chg;
448 int rc = 0;
449
450 switch (psp) {
451 case POWER_SUPPLY_PROP_PRESENT:
452 if (chip->bad_part)
453 val->intval = 1;
454 else
455 rc = smblib_get_prop_usb_present(chg, val);
456 break;
457 case POWER_SUPPLY_PROP_ONLINE:
458 rc = smblib_get_prop_usb_online(chg, val);
Fenglin Wu80826e02017-04-25 21:45:08 +0800459 if (!val->intval)
460 break;
461
Nicholas Troaste1932e42017-04-12 12:38:18 -0700462 if ((chg->typec_mode == POWER_SUPPLY_TYPEC_SOURCE_DEFAULT ||
Fenglin Wu80826e02017-04-25 21:45:08 +0800463 chg->micro_usb_mode) &&
464 chg->real_charger_type == POWER_SUPPLY_TYPE_USB)
465 val->intval = 0;
466 else
467 val->intval = 1;
Fenglin Wubf25d392017-06-22 12:30:33 +0800468 if (chg->real_charger_type == POWER_SUPPLY_TYPE_UNKNOWN)
469 val->intval = 0;
Nicholas Troast96886052016-02-25 15:42:17 -0800470 break;
471 case POWER_SUPPLY_PROP_VOLTAGE_MIN:
472 val->intval = chg->voltage_min_uv;
473 break;
474 case POWER_SUPPLY_PROP_VOLTAGE_MAX:
475 val->intval = chg->voltage_max_uv;
476 break;
477 case POWER_SUPPLY_PROP_VOLTAGE_NOW:
478 rc = smblib_get_prop_usb_voltage_now(chg, val);
479 break;
Abhijeet Dharmapurikard92eca62016-10-07 19:04:33 -0700480 case POWER_SUPPLY_PROP_PD_CURRENT_MAX:
481 rc = smblib_get_prop_pd_current_max(chg, val);
482 break;
Nicholas Troast96886052016-02-25 15:42:17 -0800483 case POWER_SUPPLY_PROP_CURRENT_MAX:
484 rc = smblib_get_prop_usb_current_max(chg, val);
485 break;
486 case POWER_SUPPLY_PROP_TYPE:
Fenglin Wu80826e02017-04-25 21:45:08 +0800487 val->intval = POWER_SUPPLY_TYPE_USB_PD;
488 break;
489 case POWER_SUPPLY_PROP_REAL_TYPE:
Nicholas Troast96886052016-02-25 15:42:17 -0800490 if (chip->bad_part)
Fenglin Wu80826e02017-04-25 21:45:08 +0800491 val->intval = POWER_SUPPLY_TYPE_USB_PD;
Nicholas Troast96886052016-02-25 15:42:17 -0800492 else
Fenglin Wu80826e02017-04-25 21:45:08 +0800493 val->intval = chg->real_charger_type;
Nicholas Troast96886052016-02-25 15:42:17 -0800494 break;
495 case POWER_SUPPLY_PROP_TYPEC_MODE:
Ashay Jaiswal4aa2c0c2016-12-07 19:39:38 +0530496 if (chg->micro_usb_mode)
497 val->intval = POWER_SUPPLY_TYPEC_NONE;
498 else if (chip->bad_part)
Nicholas Troast96886052016-02-25 15:42:17 -0800499 val->intval = POWER_SUPPLY_TYPEC_SOURCE_DEFAULT;
500 else
Nicholas Troaste1932e42017-04-12 12:38:18 -0700501 val->intval = chg->typec_mode;
Nicholas Troast96886052016-02-25 15:42:17 -0800502 break;
503 case POWER_SUPPLY_PROP_TYPEC_POWER_ROLE:
Ashay Jaiswal4aa2c0c2016-12-07 19:39:38 +0530504 if (chg->micro_usb_mode)
505 val->intval = POWER_SUPPLY_TYPEC_PR_NONE;
506 else
507 rc = smblib_get_prop_typec_power_role(chg, val);
Nicholas Troast96886052016-02-25 15:42:17 -0800508 break;
509 case POWER_SUPPLY_PROP_TYPEC_CC_ORIENTATION:
Ashay Jaiswal4aa2c0c2016-12-07 19:39:38 +0530510 if (chg->micro_usb_mode)
511 val->intval = 0;
512 else
513 rc = smblib_get_prop_typec_cc_orientation(chg, val);
Nicholas Troast96886052016-02-25 15:42:17 -0800514 break;
515 case POWER_SUPPLY_PROP_PD_ALLOWED:
516 rc = smblib_get_prop_pd_allowed(chg, val);
517 break;
518 case POWER_SUPPLY_PROP_PD_ACTIVE:
519 val->intval = chg->pd_active;
520 break;
Nicholas Troast133a7f52016-06-29 13:48:20 -0700521 case POWER_SUPPLY_PROP_INPUT_CURRENT_SETTLED:
522 rc = smblib_get_prop_input_current_settled(chg, val);
523 break;
Harry Yangba874ce2016-08-19 14:17:01 -0700524 case POWER_SUPPLY_PROP_INPUT_CURRENT_NOW:
525 rc = smblib_get_prop_usb_current_now(chg, val);
526 break;
Harry Yangd89ff1f2016-12-05 14:59:11 -0800527 case POWER_SUPPLY_PROP_BOOST_CURRENT:
528 val->intval = chg->boost_current_ua;
529 break;
Abhijeet Dharmapurikarf8a7a4a2016-10-07 18:46:45 -0700530 case POWER_SUPPLY_PROP_PD_IN_HARD_RESET:
531 rc = smblib_get_prop_pd_in_hard_reset(chg, val);
532 break;
Abhijeet Dharmapurikard92eca62016-10-07 19:04:33 -0700533 case POWER_SUPPLY_PROP_PD_USB_SUSPEND_SUPPORTED:
534 val->intval = chg->system_suspend_supported;
535 break;
Abhijeet Dharmapurikarb9598872016-10-17 16:58:58 -0700536 case POWER_SUPPLY_PROP_PE_START:
537 rc = smblib_get_pe_start(chg, val);
538 break;
Nicholas Troaste1b0c042017-02-09 10:05:03 -0800539 case POWER_SUPPLY_PROP_CTM_CURRENT_MAX:
540 val->intval = get_client_vote(chg->usb_icl_votable, CTM_VOTER);
541 break;
Abhijeet Dharmapurikarf59c8352017-03-23 14:04:05 -0700542 case POWER_SUPPLY_PROP_HW_CURRENT_MAX:
543 rc = smblib_get_charge_current(chg, &val->intval);
544 break;
Abhijeet Dharmapurikar255da952017-05-24 20:52:09 -0700545 case POWER_SUPPLY_PROP_PR_SWAP:
546 rc = smblib_get_prop_pr_swap_in_progress(chg, val);
547 break;
Nicholas Troast96886052016-02-25 15:42:17 -0800548 default:
Abhijeet Dharmapurikara8bd6f02017-01-30 15:43:04 -0800549 pr_err("get prop %d is not supported in usb\n", psp);
Nicholas Troast96886052016-02-25 15:42:17 -0800550 rc = -EINVAL;
551 break;
552 }
Abhijeet Dharmapurikar773d4ab2016-09-09 12:00:19 -0700553 if (rc < 0) {
554 pr_debug("Couldn't get prop %d rc = %d\n", psp, rc);
555 return -ENODATA;
556 }
557 return 0;
Nicholas Troast96886052016-02-25 15:42:17 -0800558}
559
560static int smb2_usb_set_prop(struct power_supply *psy,
561 enum power_supply_property psp,
562 const union power_supply_propval *val)
563{
564 struct smb2 *chip = power_supply_get_drvdata(psy);
565 struct smb_charger *chg = &chip->chg;
566 int rc = 0;
567
Abhijeet Dharmapurikar11330d92017-04-17 12:15:19 -0700568 mutex_lock(&chg->lock);
569 if (!chg->typec_present) {
570 rc = -EINVAL;
571 goto unlock;
572 }
573
Nicholas Troast96886052016-02-25 15:42:17 -0800574 switch (psp) {
575 case POWER_SUPPLY_PROP_VOLTAGE_MIN:
576 rc = smblib_set_prop_usb_voltage_min(chg, val);
577 break;
578 case POWER_SUPPLY_PROP_VOLTAGE_MAX:
579 rc = smblib_set_prop_usb_voltage_max(chg, val);
580 break;
Abhijeet Dharmapurikard92eca62016-10-07 19:04:33 -0700581 case POWER_SUPPLY_PROP_PD_CURRENT_MAX:
582 rc = smblib_set_prop_pd_current_max(chg, val);
583 break;
Nicholas Troast96886052016-02-25 15:42:17 -0800584 case POWER_SUPPLY_PROP_CURRENT_MAX:
585 rc = smblib_set_prop_usb_current_max(chg, val);
586 break;
587 case POWER_SUPPLY_PROP_TYPEC_POWER_ROLE:
588 rc = smblib_set_prop_typec_power_role(chg, val);
589 break;
590 case POWER_SUPPLY_PROP_PD_ACTIVE:
591 rc = smblib_set_prop_pd_active(chg, val);
592 break;
Abhijeet Dharmapurikarf8a7a4a2016-10-07 18:46:45 -0700593 case POWER_SUPPLY_PROP_PD_IN_HARD_RESET:
594 rc = smblib_set_prop_pd_in_hard_reset(chg, val);
595 break;
Abhijeet Dharmapurikard92eca62016-10-07 19:04:33 -0700596 case POWER_SUPPLY_PROP_PD_USB_SUSPEND_SUPPORTED:
597 chg->system_suspend_supported = val->intval;
598 break;
Harry Yangd89ff1f2016-12-05 14:59:11 -0800599 case POWER_SUPPLY_PROP_BOOST_CURRENT:
600 rc = smblib_set_prop_boost_current(chg, val);
601 break;
Nicholas Troaste1b0c042017-02-09 10:05:03 -0800602 case POWER_SUPPLY_PROP_CTM_CURRENT_MAX:
603 rc = vote(chg->usb_icl_votable, CTM_VOTER,
604 val->intval >= 0, val->intval);
605 break;
Abhijeet Dharmapurikar255da952017-05-24 20:52:09 -0700606 case POWER_SUPPLY_PROP_PR_SWAP:
607 rc = smblib_set_prop_pr_swap_in_progress(chg, val);
608 break;
Nicholas Troast96886052016-02-25 15:42:17 -0800609 default:
610 pr_err("set prop %d is not supported\n", psp);
611 rc = -EINVAL;
612 break;
613 }
614
Abhijeet Dharmapurikar11330d92017-04-17 12:15:19 -0700615unlock:
616 mutex_unlock(&chg->lock);
Nicholas Troast96886052016-02-25 15:42:17 -0800617 return rc;
618}
619
620static int smb2_usb_prop_is_writeable(struct power_supply *psy,
621 enum power_supply_property psp)
622{
623 switch (psp) {
Fenglin Wue43f25b2017-02-09 09:33:19 +0800624 case POWER_SUPPLY_PROP_CURRENT_MAX:
Nicholas Troast96886052016-02-25 15:42:17 -0800625 case POWER_SUPPLY_PROP_TYPEC_POWER_ROLE:
Nicholas Troaste1b0c042017-02-09 10:05:03 -0800626 case POWER_SUPPLY_PROP_CTM_CURRENT_MAX:
Nicholas Troast96886052016-02-25 15:42:17 -0800627 return 1;
628 default:
629 break;
630 }
631
632 return 0;
633}
634
635static int smb2_init_usb_psy(struct smb2 *chip)
636{
637 struct power_supply_config usb_cfg = {};
638 struct smb_charger *chg = &chip->chg;
639
640 chg->usb_psy_desc.name = "usb";
Fenglin Wu80826e02017-04-25 21:45:08 +0800641 chg->usb_psy_desc.type = POWER_SUPPLY_TYPE_USB_PD;
Nicholas Troast96886052016-02-25 15:42:17 -0800642 chg->usb_psy_desc.properties = smb2_usb_props;
643 chg->usb_psy_desc.num_properties = ARRAY_SIZE(smb2_usb_props);
644 chg->usb_psy_desc.get_property = smb2_usb_get_prop;
645 chg->usb_psy_desc.set_property = smb2_usb_set_prop;
646 chg->usb_psy_desc.property_is_writeable = smb2_usb_prop_is_writeable;
647
648 usb_cfg.drv_data = chip;
649 usb_cfg.of_node = chg->dev->of_node;
Ashay Jaiswald1918f62017-04-27 17:16:26 +0530650 chg->usb_psy = power_supply_register(chg->dev,
Nicholas Troast96886052016-02-25 15:42:17 -0800651 &chg->usb_psy_desc,
652 &usb_cfg);
653 if (IS_ERR(chg->usb_psy)) {
654 pr_err("Couldn't register USB power supply\n");
655 return PTR_ERR(chg->usb_psy);
656 }
657
658 return 0;
659}
660
Fenglin Wu80826e02017-04-25 21:45:08 +0800661/********************************
662 * USB PC_PORT PSY REGISTRATION *
663 ********************************/
664static enum power_supply_property smb2_usb_port_props[] = {
665 POWER_SUPPLY_PROP_TYPE,
666 POWER_SUPPLY_PROP_ONLINE,
667};
668
669static int smb2_usb_port_get_prop(struct power_supply *psy,
670 enum power_supply_property psp,
671 union power_supply_propval *val)
672{
673 struct smb2 *chip = power_supply_get_drvdata(psy);
674 struct smb_charger *chg = &chip->chg;
675 int rc = 0;
676
677 switch (psp) {
678 case POWER_SUPPLY_PROP_TYPE:
679 val->intval = POWER_SUPPLY_TYPE_USB;
680 break;
681 case POWER_SUPPLY_PROP_ONLINE:
682 rc = smblib_get_prop_usb_online(chg, val);
683 if (!val->intval)
684 break;
685
Nicholas Troaste1932e42017-04-12 12:38:18 -0700686 if ((chg->typec_mode == POWER_SUPPLY_TYPEC_SOURCE_DEFAULT ||
Fenglin Wu80826e02017-04-25 21:45:08 +0800687 chg->micro_usb_mode) &&
688 chg->real_charger_type == POWER_SUPPLY_TYPE_USB)
689 val->intval = 1;
690 else
691 val->intval = 0;
692 break;
693 default:
694 pr_err_ratelimited("Get prop %d is not supported in pc_port\n",
695 psp);
696 return -EINVAL;
697 }
698
699 if (rc < 0) {
700 pr_debug("Couldn't get prop %d rc = %d\n", psp, rc);
701 return -ENODATA;
702 }
703
704 return 0;
705}
706
707static int smb2_usb_port_set_prop(struct power_supply *psy,
708 enum power_supply_property psp,
709 const union power_supply_propval *val)
710{
711 int rc = 0;
712
713 switch (psp) {
714 default:
715 pr_err_ratelimited("Set prop %d is not supported in pc_port\n",
716 psp);
717 rc = -EINVAL;
718 break;
719 }
720
721 return rc;
722}
723
724static const struct power_supply_desc usb_port_psy_desc = {
725 .name = "pc_port",
726 .type = POWER_SUPPLY_TYPE_USB,
727 .properties = smb2_usb_port_props,
728 .num_properties = ARRAY_SIZE(smb2_usb_port_props),
729 .get_property = smb2_usb_port_get_prop,
730 .set_property = smb2_usb_port_set_prop,
731};
732
733static int smb2_init_usb_port_psy(struct smb2 *chip)
734{
735 struct power_supply_config usb_port_cfg = {};
736 struct smb_charger *chg = &chip->chg;
737
738 usb_port_cfg.drv_data = chip;
739 usb_port_cfg.of_node = chg->dev->of_node;
740 chg->usb_port_psy = power_supply_register(chg->dev,
741 &usb_port_psy_desc,
742 &usb_port_cfg);
743 if (IS_ERR(chg->usb_port_psy)) {
744 pr_err("Couldn't register USB pc_port power supply\n");
745 return PTR_ERR(chg->usb_port_psy);
746 }
747
748 return 0;
749}
750
Abhijeet Dharmapurikara8bd6f02017-01-30 15:43:04 -0800751/*****************************
752 * USB MAIN PSY REGISTRATION *
753 *****************************/
754
755static enum power_supply_property smb2_usb_main_props[] = {
756 POWER_SUPPLY_PROP_VOLTAGE_MAX,
Abhijeet Dharmapurikara8bd6f02017-01-30 15:43:04 -0800757 POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX,
758 POWER_SUPPLY_PROP_TYPE,
759 POWER_SUPPLY_PROP_INPUT_CURRENT_SETTLED,
Fenglin Wuef4730e2017-01-11 18:16:25 +0800760 POWER_SUPPLY_PROP_INPUT_VOLTAGE_SETTLED,
Abhijeet Dharmapurikara8bd6f02017-01-30 15:43:04 -0800761 POWER_SUPPLY_PROP_FCC_DELTA,
Ashay Jaiswalae1586d2017-03-22 23:18:51 +0530762 POWER_SUPPLY_PROP_CURRENT_MAX,
Abhijeet Dharmapurikara8bd6f02017-01-30 15:43:04 -0800763 /*
764 * TODO move the TEMP and TEMP_MAX properties here,
765 * and update the thermal balancer to look here
766 */
767};
768
769static int smb2_usb_main_get_prop(struct power_supply *psy,
770 enum power_supply_property psp,
771 union power_supply_propval *val)
772{
773 struct smb2 *chip = power_supply_get_drvdata(psy);
774 struct smb_charger *chg = &chip->chg;
775 int rc = 0;
776
777 switch (psp) {
778 case POWER_SUPPLY_PROP_VOLTAGE_MAX:
779 rc = smblib_get_charge_param(chg, &chg->param.fv, &val->intval);
780 break;
Abhijeet Dharmapurikara8bd6f02017-01-30 15:43:04 -0800781 case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX:
782 rc = smblib_get_charge_param(chg, &chg->param.fcc,
783 &val->intval);
784 break;
785 case POWER_SUPPLY_PROP_TYPE:
786 val->intval = POWER_SUPPLY_TYPE_MAIN;
787 break;
788 case POWER_SUPPLY_PROP_INPUT_CURRENT_SETTLED:
789 rc = smblib_get_prop_input_current_settled(chg, val);
790 break;
Fenglin Wuef4730e2017-01-11 18:16:25 +0800791 case POWER_SUPPLY_PROP_INPUT_VOLTAGE_SETTLED:
792 rc = smblib_get_prop_input_voltage_settled(chg, val);
793 break;
Abhijeet Dharmapurikara8bd6f02017-01-30 15:43:04 -0800794 case POWER_SUPPLY_PROP_FCC_DELTA:
795 rc = smblib_get_prop_fcc_delta(chg, val);
796 break;
Ashay Jaiswalae1586d2017-03-22 23:18:51 +0530797 case POWER_SUPPLY_PROP_CURRENT_MAX:
Abhijeet Dharmapurikareecf5582017-04-24 13:33:07 -0700798 rc = smblib_get_icl_current(chg, &val->intval);
Ashay Jaiswalae1586d2017-03-22 23:18:51 +0530799 break;
Abhijeet Dharmapurikara8bd6f02017-01-30 15:43:04 -0800800 default:
Ashay Jaiswale1d12432017-02-08 09:58:31 +0530801 pr_debug("get prop %d is not supported in usb-main\n", psp);
Abhijeet Dharmapurikara8bd6f02017-01-30 15:43:04 -0800802 rc = -EINVAL;
803 break;
804 }
805 if (rc < 0) {
806 pr_debug("Couldn't get prop %d rc = %d\n", psp, rc);
807 return -ENODATA;
808 }
809 return 0;
810}
811
812static int smb2_usb_main_set_prop(struct power_supply *psy,
813 enum power_supply_property psp,
814 const union power_supply_propval *val)
815{
816 struct smb2 *chip = power_supply_get_drvdata(psy);
817 struct smb_charger *chg = &chip->chg;
818 int rc = 0;
819
820 switch (psp) {
821 case POWER_SUPPLY_PROP_VOLTAGE_MAX:
822 rc = smblib_set_charge_param(chg, &chg->param.fv, val->intval);
823 break;
Abhijeet Dharmapurikara8bd6f02017-01-30 15:43:04 -0800824 case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX:
825 rc = smblib_set_charge_param(chg, &chg->param.fcc, val->intval);
826 break;
Ashay Jaiswalae1586d2017-03-22 23:18:51 +0530827 case POWER_SUPPLY_PROP_CURRENT_MAX:
828 rc = smblib_set_icl_current(chg, val->intval);
829 break;
Abhijeet Dharmapurikara8bd6f02017-01-30 15:43:04 -0800830 default:
831 pr_err("set prop %d is not supported\n", psp);
832 rc = -EINVAL;
833 break;
834 }
835
836 return rc;
837}
838
839static const struct power_supply_desc usb_main_psy_desc = {
840 .name = "main",
841 .type = POWER_SUPPLY_TYPE_MAIN,
842 .properties = smb2_usb_main_props,
843 .num_properties = ARRAY_SIZE(smb2_usb_main_props),
844 .get_property = smb2_usb_main_get_prop,
845 .set_property = smb2_usb_main_set_prop,
846};
847
848static int smb2_init_usb_main_psy(struct smb2 *chip)
849{
850 struct power_supply_config usb_main_cfg = {};
851 struct smb_charger *chg = &chip->chg;
852
853 usb_main_cfg.drv_data = chip;
854 usb_main_cfg.of_node = chg->dev->of_node;
Ashay Jaiswald1918f62017-04-27 17:16:26 +0530855 chg->usb_main_psy = power_supply_register(chg->dev,
Abhijeet Dharmapurikara8bd6f02017-01-30 15:43:04 -0800856 &usb_main_psy_desc,
857 &usb_main_cfg);
858 if (IS_ERR(chg->usb_main_psy)) {
859 pr_err("Couldn't register USB main power supply\n");
860 return PTR_ERR(chg->usb_main_psy);
861 }
862
863 return 0;
864}
865
Nicholas Troast96886052016-02-25 15:42:17 -0800866/*************************
Harry Yangf3023592016-07-20 14:56:41 -0700867 * DC PSY REGISTRATION *
868 *************************/
869
870static enum power_supply_property smb2_dc_props[] = {
871 POWER_SUPPLY_PROP_PRESENT,
872 POWER_SUPPLY_PROP_ONLINE,
873 POWER_SUPPLY_PROP_CURRENT_MAX,
874};
875
876static int smb2_dc_get_prop(struct power_supply *psy,
877 enum power_supply_property psp,
878 union power_supply_propval *val)
879{
880 struct smb2 *chip = power_supply_get_drvdata(psy);
881 struct smb_charger *chg = &chip->chg;
882 int rc = 0;
883
884 switch (psp) {
885 case POWER_SUPPLY_PROP_PRESENT:
886 rc = smblib_get_prop_dc_present(chg, val);
887 break;
888 case POWER_SUPPLY_PROP_ONLINE:
889 rc = smblib_get_prop_dc_online(chg, val);
890 break;
891 case POWER_SUPPLY_PROP_CURRENT_MAX:
892 rc = smblib_get_prop_dc_current_max(chg, val);
893 break;
894 default:
895 return -EINVAL;
896 }
Abhijeet Dharmapurikar773d4ab2016-09-09 12:00:19 -0700897 if (rc < 0) {
898 pr_debug("Couldn't get prop %d rc = %d\n", psp, rc);
899 return -ENODATA;
900 }
901 return 0;
Harry Yangf3023592016-07-20 14:56:41 -0700902}
903
904static int smb2_dc_set_prop(struct power_supply *psy,
905 enum power_supply_property psp,
906 const union power_supply_propval *val)
907{
908 struct smb2 *chip = power_supply_get_drvdata(psy);
909 struct smb_charger *chg = &chip->chg;
910 int rc = 0;
911
912 switch (psp) {
913 case POWER_SUPPLY_PROP_CURRENT_MAX:
914 rc = smblib_set_prop_dc_current_max(chg, val);
915 break;
916 default:
917 return -EINVAL;
918 }
919
920 return rc;
921}
922
923static int smb2_dc_prop_is_writeable(struct power_supply *psy,
924 enum power_supply_property psp)
925{
926 int rc;
927
928 switch (psp) {
929 case POWER_SUPPLY_PROP_CURRENT_MAX:
930 rc = 1;
931 break;
932 default:
933 rc = 0;
934 break;
935 }
936
937 return rc;
938}
939
940static const struct power_supply_desc dc_psy_desc = {
941 .name = "dc",
942 .type = POWER_SUPPLY_TYPE_WIPOWER,
943 .properties = smb2_dc_props,
944 .num_properties = ARRAY_SIZE(smb2_dc_props),
945 .get_property = smb2_dc_get_prop,
946 .set_property = smb2_dc_set_prop,
947 .property_is_writeable = smb2_dc_prop_is_writeable,
948};
949
950static int smb2_init_dc_psy(struct smb2 *chip)
951{
952 struct power_supply_config dc_cfg = {};
953 struct smb_charger *chg = &chip->chg;
954
955 dc_cfg.drv_data = chip;
956 dc_cfg.of_node = chg->dev->of_node;
Ashay Jaiswald1918f62017-04-27 17:16:26 +0530957 chg->dc_psy = power_supply_register(chg->dev,
Harry Yangf3023592016-07-20 14:56:41 -0700958 &dc_psy_desc,
959 &dc_cfg);
960 if (IS_ERR(chg->dc_psy)) {
961 pr_err("Couldn't register USB power supply\n");
962 return PTR_ERR(chg->dc_psy);
963 }
964
965 return 0;
966}
967
968/*************************
Nicholas Troast96886052016-02-25 15:42:17 -0800969 * BATT PSY REGISTRATION *
970 *************************/
971
972static enum power_supply_property smb2_batt_props[] = {
973 POWER_SUPPLY_PROP_INPUT_SUSPEND,
974 POWER_SUPPLY_PROP_STATUS,
975 POWER_SUPPLY_PROP_HEALTH,
976 POWER_SUPPLY_PROP_PRESENT,
977 POWER_SUPPLY_PROP_CHARGE_TYPE,
978 POWER_SUPPLY_PROP_CAPACITY,
Harry Yangba874ce2016-08-19 14:17:01 -0700979 POWER_SUPPLY_PROP_CHARGER_TEMP,
980 POWER_SUPPLY_PROP_CHARGER_TEMP_MAX,
Abhijeet Dharmapurikar0e369002016-09-07 17:25:36 -0700981 POWER_SUPPLY_PROP_INPUT_CURRENT_LIMITED,
Nicholas Troast66b21d72016-09-20 15:33:20 -0700982 POWER_SUPPLY_PROP_VOLTAGE_NOW,
Harry Yang7e66f892016-10-14 09:31:15 -0700983 POWER_SUPPLY_PROP_VOLTAGE_MAX,
Harry Yangb93d8752017-02-21 13:10:00 -0800984 POWER_SUPPLY_PROP_VOLTAGE_QNOVO,
Nicholas Troast66b21d72016-09-20 15:33:20 -0700985 POWER_SUPPLY_PROP_CURRENT_NOW,
Harry Yangb93d8752017-02-21 13:10:00 -0800986 POWER_SUPPLY_PROP_CURRENT_QNOVO,
Harry Yang3fe0d2d2017-02-14 15:56:21 -0800987 POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX,
Nicholas Troast66b21d72016-09-20 15:33:20 -0700988 POWER_SUPPLY_PROP_TEMP,
989 POWER_SUPPLY_PROP_TECHNOLOGY,
Harry Yangbedee332016-08-31 16:14:29 -0700990 POWER_SUPPLY_PROP_STEP_CHARGING_ENABLED,
991 POWER_SUPPLY_PROP_STEP_CHARGING_STEP,
Subbaraman Narayanamurthy270a2652016-10-04 17:08:42 -0700992 POWER_SUPPLY_PROP_CHARGE_DONE,
Abhijeet Dharmapurikarc0b0f592016-10-14 10:55:42 -0700993 POWER_SUPPLY_PROP_PARALLEL_DISABLE,
Fenglin Wuedd70792016-11-22 13:16:19 +0800994 POWER_SUPPLY_PROP_SET_SHIP_MODE,
Nicholas Troast7fdbd2e2017-02-08 10:47:37 -0800995 POWER_SUPPLY_PROP_DIE_HEALTH,
Ashay Jaiswal6d308da2017-02-18 09:59:23 +0530996 POWER_SUPPLY_PROP_RERUN_AICL,
997 POWER_SUPPLY_PROP_DP_DM,
Abhijeet Dharmapurikaracf32002017-05-11 11:54:17 -0700998 POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT_MAX,
999 POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT,
Nicholas Troast96886052016-02-25 15:42:17 -08001000};
1001
1002static int smb2_batt_get_prop(struct power_supply *psy,
1003 enum power_supply_property psp,
1004 union power_supply_propval *val)
1005{
Nicholas Troast66b21d72016-09-20 15:33:20 -07001006 struct smb_charger *chg = power_supply_get_drvdata(psy);
Nicholas Troast2ebe6c52016-09-20 13:25:59 -07001007 int rc = 0;
Ashay Jaiswalb6f1ccb2017-03-10 10:13:00 +05301008 union power_supply_propval pval = {0, };
Nicholas Troast96886052016-02-25 15:42:17 -08001009
1010 switch (psp) {
1011 case POWER_SUPPLY_PROP_STATUS:
Harry Yangba874ce2016-08-19 14:17:01 -07001012 rc = smblib_get_prop_batt_status(chg, val);
Nicholas Troast96886052016-02-25 15:42:17 -08001013 break;
1014 case POWER_SUPPLY_PROP_HEALTH:
Harry Yangba874ce2016-08-19 14:17:01 -07001015 rc = smblib_get_prop_batt_health(chg, val);
Nicholas Troast96886052016-02-25 15:42:17 -08001016 break;
1017 case POWER_SUPPLY_PROP_PRESENT:
Harry Yangba874ce2016-08-19 14:17:01 -07001018 rc = smblib_get_prop_batt_present(chg, val);
Nicholas Troast96886052016-02-25 15:42:17 -08001019 break;
1020 case POWER_SUPPLY_PROP_INPUT_SUSPEND:
Harry Yangba874ce2016-08-19 14:17:01 -07001021 rc = smblib_get_prop_input_suspend(chg, val);
Nicholas Troast96886052016-02-25 15:42:17 -08001022 break;
1023 case POWER_SUPPLY_PROP_CHARGE_TYPE:
Harry Yangba874ce2016-08-19 14:17:01 -07001024 rc = smblib_get_prop_batt_charge_type(chg, val);
Nicholas Troast96886052016-02-25 15:42:17 -08001025 break;
1026 case POWER_SUPPLY_PROP_CAPACITY:
Harry Yangba874ce2016-08-19 14:17:01 -07001027 rc = smblib_get_prop_batt_capacity(chg, val);
Nicholas Troast96886052016-02-25 15:42:17 -08001028 break;
Abhijeet Dharmapurikaracf32002017-05-11 11:54:17 -07001029 case POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT:
Harry Yangba874ce2016-08-19 14:17:01 -07001030 rc = smblib_get_prop_system_temp_level(chg, val);
1031 break;
Abhijeet Dharmapurikaracf32002017-05-11 11:54:17 -07001032 case POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT_MAX:
1033 rc = smblib_get_prop_system_temp_level_max(chg, val);
1034 break;
Harry Yangba874ce2016-08-19 14:17:01 -07001035 case POWER_SUPPLY_PROP_CHARGER_TEMP:
Ashay Jaiswalb6f1ccb2017-03-10 10:13:00 +05301036 /* do not query RRADC if charger is not present */
1037 rc = smblib_get_prop_usb_present(chg, &pval);
1038 if (rc < 0)
1039 pr_err("Couldn't get usb present rc=%d\n", rc);
1040
1041 rc = -ENODATA;
1042 if (pval.intval)
1043 rc = smblib_get_prop_charger_temp(chg, val);
Harry Yangba874ce2016-08-19 14:17:01 -07001044 break;
1045 case POWER_SUPPLY_PROP_CHARGER_TEMP_MAX:
1046 rc = smblib_get_prop_charger_temp_max(chg, val);
Abhijeet Dharmapurikar99fb8942016-07-08 11:39:23 -07001047 break;
Abhijeet Dharmapurikar0e369002016-09-07 17:25:36 -07001048 case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMITED:
1049 rc = smblib_get_prop_input_current_limited(chg, val);
Abhijeet Dharmapurikar7ebf63c2016-10-18 10:37:23 -07001050 break;
Harry Yangbedee332016-08-31 16:14:29 -07001051 case POWER_SUPPLY_PROP_STEP_CHARGING_ENABLED:
1052 val->intval = chg->step_chg_enabled;
1053 break;
1054 case POWER_SUPPLY_PROP_STEP_CHARGING_STEP:
1055 rc = smblib_get_prop_step_chg_step(chg, val);
Abhijeet Dharmapurikar0e369002016-09-07 17:25:36 -07001056 break;
Nicholas Troast66b21d72016-09-20 15:33:20 -07001057 case POWER_SUPPLY_PROP_VOLTAGE_NOW:
1058 rc = smblib_get_prop_batt_voltage_now(chg, val);
1059 break;
Harry Yang7e66f892016-10-14 09:31:15 -07001060 case POWER_SUPPLY_PROP_VOLTAGE_MAX:
Abhijeet Dharmapurikar33d18462017-05-15 13:38:53 -07001061 val->intval = get_client_vote(chg->fv_votable,
1062 BATT_PROFILE_VOTER);
Harry Yang7e66f892016-10-14 09:31:15 -07001063 break;
Harry Yang40192cb2017-02-25 23:25:17 -08001064 case POWER_SUPPLY_PROP_CHARGE_QNOVO_ENABLE:
1065 rc = smblib_get_prop_charge_qnovo_enable(chg, val);
1066 break;
Harry Yang603e3802017-02-09 17:45:12 -08001067 case POWER_SUPPLY_PROP_VOLTAGE_QNOVO:
Abhijeet Dharmapurikarc31b4ab2017-04-27 19:20:31 -07001068 val->intval = get_client_vote_locked(chg->fv_votable,
1069 QNOVO_VOTER);
Harry Yang603e3802017-02-09 17:45:12 -08001070 break;
Nicholas Troast66b21d72016-09-20 15:33:20 -07001071 case POWER_SUPPLY_PROP_CURRENT_NOW:
1072 rc = smblib_get_prop_batt_current_now(chg, val);
1073 break;
Harry Yang603e3802017-02-09 17:45:12 -08001074 case POWER_SUPPLY_PROP_CURRENT_QNOVO:
Abhijeet Dharmapurikarc31b4ab2017-04-27 19:20:31 -07001075 val->intval = get_client_vote_locked(chg->fcc_votable,
1076 QNOVO_VOTER);
Harry Yang603e3802017-02-09 17:45:12 -08001077 break;
Harry Yang3fe0d2d2017-02-14 15:56:21 -08001078 case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX:
1079 val->intval = get_client_vote(chg->fcc_votable,
Abhijeet Dharmapurikar33d18462017-05-15 13:38:53 -07001080 BATT_PROFILE_VOTER);
Harry Yang3fe0d2d2017-02-14 15:56:21 -08001081 break;
Nicholas Troast66b21d72016-09-20 15:33:20 -07001082 case POWER_SUPPLY_PROP_TEMP:
1083 rc = smblib_get_prop_batt_temp(chg, val);
1084 break;
1085 case POWER_SUPPLY_PROP_TECHNOLOGY:
1086 val->intval = POWER_SUPPLY_TECHNOLOGY_LION;
1087 break;
Subbaraman Narayanamurthy270a2652016-10-04 17:08:42 -07001088 case POWER_SUPPLY_PROP_CHARGE_DONE:
Subbaraman Narayanamurthyb491d022016-10-10 20:22:48 -07001089 rc = smblib_get_prop_batt_charge_done(chg, val);
Subbaraman Narayanamurthy270a2652016-10-04 17:08:42 -07001090 break;
Abhijeet Dharmapurikarc0b0f592016-10-14 10:55:42 -07001091 case POWER_SUPPLY_PROP_PARALLEL_DISABLE:
1092 val->intval = get_client_vote(chg->pl_disable_votable,
1093 USER_VOTER);
1094 break;
Fenglin Wuedd70792016-11-22 13:16:19 +08001095 case POWER_SUPPLY_PROP_SET_SHIP_MODE:
1096 /* Not in ship mode as long as device is active */
1097 val->intval = 0;
1098 break;
Nicholas Troast7fdbd2e2017-02-08 10:47:37 -08001099 case POWER_SUPPLY_PROP_DIE_HEALTH:
1100 rc = smblib_get_prop_die_health(chg, val);
1101 break;
Ashay Jaiswal6d308da2017-02-18 09:59:23 +05301102 case POWER_SUPPLY_PROP_DP_DM:
1103 val->intval = chg->pulse_cnt;
1104 break;
1105 case POWER_SUPPLY_PROP_RERUN_AICL:
1106 val->intval = 0;
1107 break;
Nicholas Troast96886052016-02-25 15:42:17 -08001108 default:
Abhijeet Dharmapurikar99fb8942016-07-08 11:39:23 -07001109 pr_err("batt power supply prop %d not supported\n", psp);
Nicholas Troast96886052016-02-25 15:42:17 -08001110 return -EINVAL;
1111 }
Nicholas Troast66b21d72016-09-20 15:33:20 -07001112
Abhijeet Dharmapurikar773d4ab2016-09-09 12:00:19 -07001113 if (rc < 0) {
1114 pr_debug("Couldn't get prop %d rc = %d\n", psp, rc);
1115 return -ENODATA;
1116 }
Nicholas Troast66b21d72016-09-20 15:33:20 -07001117
Abhijeet Dharmapurikar773d4ab2016-09-09 12:00:19 -07001118 return 0;
Nicholas Troast96886052016-02-25 15:42:17 -08001119}
1120
1121static int smb2_batt_set_prop(struct power_supply *psy,
1122 enum power_supply_property prop,
1123 const union power_supply_propval *val)
1124{
Abhijeet Dharmapurikar99fb8942016-07-08 11:39:23 -07001125 int rc = 0;
Nicholas Troast96886052016-02-25 15:42:17 -08001126 struct smb_charger *chg = power_supply_get_drvdata(psy);
1127
1128 switch (prop) {
1129 case POWER_SUPPLY_PROP_INPUT_SUSPEND:
Abhijeet Dharmapurikar99fb8942016-07-08 11:39:23 -07001130 rc = smblib_set_prop_input_suspend(chg, val);
1131 break;
Abhijeet Dharmapurikaracf32002017-05-11 11:54:17 -07001132 case POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT:
Abhijeet Dharmapurikar99fb8942016-07-08 11:39:23 -07001133 rc = smblib_set_prop_system_temp_level(chg, val);
Nicholas Troast96886052016-02-25 15:42:17 -08001134 break;
Abhijeet Dharmapurikar9e7e48c2016-08-23 12:55:49 -07001135 case POWER_SUPPLY_PROP_CAPACITY:
1136 rc = smblib_set_prop_batt_capacity(chg, val);
1137 break;
Abhijeet Dharmapurikarc0b0f592016-10-14 10:55:42 -07001138 case POWER_SUPPLY_PROP_PARALLEL_DISABLE:
1139 vote(chg->pl_disable_votable, USER_VOTER, (bool)val->intval, 0);
1140 break;
Harry Yang7e66f892016-10-14 09:31:15 -07001141 case POWER_SUPPLY_PROP_VOLTAGE_MAX:
Abhijeet Dharmapurikarc31b4ab2017-04-27 19:20:31 -07001142 chg->batt_profile_fv_uv = val->intval;
1143 vote(chg->fv_votable, BATT_PROFILE_VOTER, true, val->intval);
Harry Yang7e66f892016-10-14 09:31:15 -07001144 break;
Harry Yang40192cb2017-02-25 23:25:17 -08001145 case POWER_SUPPLY_PROP_CHARGE_QNOVO_ENABLE:
1146 rc = smblib_set_prop_charge_qnovo_enable(chg, val);
1147 break;
Harry Yang603e3802017-02-09 17:45:12 -08001148 case POWER_SUPPLY_PROP_VOLTAGE_QNOVO:
Abhijeet Dharmapurikarc31b4ab2017-04-27 19:20:31 -07001149 if (val->intval == -EINVAL) {
1150 vote(chg->fv_votable, BATT_PROFILE_VOTER,
1151 true, chg->batt_profile_fv_uv);
1152 vote(chg->fv_votable, QNOVO_VOTER, false, 0);
1153 } else {
1154 vote(chg->fv_votable, QNOVO_VOTER, true, val->intval);
1155 vote(chg->fv_votable, BATT_PROFILE_VOTER, false, 0);
1156 }
Harry Yang603e3802017-02-09 17:45:12 -08001157 break;
1158 case POWER_SUPPLY_PROP_CURRENT_QNOVO:
Harry Yang67f19522017-03-23 22:40:31 -07001159 vote(chg->pl_disable_votable, PL_QNOVO_VOTER,
1160 val->intval != -EINVAL && val->intval < 2000000, 0);
Abhijeet Dharmapurikarc31b4ab2017-04-27 19:20:31 -07001161 if (val->intval == -EINVAL) {
1162 vote(chg->fcc_votable, BATT_PROFILE_VOTER,
1163 true, chg->batt_profile_fcc_ua);
1164 vote(chg->fcc_votable, QNOVO_VOTER, false, 0);
1165 } else {
1166 vote(chg->fcc_votable, QNOVO_VOTER, true, val->intval);
1167 vote(chg->fcc_votable, BATT_PROFILE_VOTER, false, 0);
1168 }
Harry Yang603e3802017-02-09 17:45:12 -08001169 break;
Harry Yang3fe0d2d2017-02-14 15:56:21 -08001170 case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX:
Abhijeet Dharmapurikarc31b4ab2017-04-27 19:20:31 -07001171 chg->batt_profile_fcc_ua = val->intval;
1172 vote(chg->fcc_votable, BATT_PROFILE_VOTER, true, val->intval);
Harry Yang3fe0d2d2017-02-14 15:56:21 -08001173 break;
Fenglin Wuedd70792016-11-22 13:16:19 +08001174 case POWER_SUPPLY_PROP_SET_SHIP_MODE:
1175 /* Not in ship mode as long as the device is active */
1176 if (!val->intval)
1177 break;
Abhijeet Dharmapurikare3d988a2017-02-23 18:38:20 -08001178 if (chg->pl.psy)
1179 power_supply_set_property(chg->pl.psy,
1180 POWER_SUPPLY_PROP_SET_SHIP_MODE, val);
Fenglin Wuedd70792016-11-22 13:16:19 +08001181 rc = smblib_set_prop_ship_mode(chg, val);
1182 break;
Ashay Jaiswal6d308da2017-02-18 09:59:23 +05301183 case POWER_SUPPLY_PROP_RERUN_AICL:
1184 rc = smblib_rerun_aicl(chg);
1185 break;
1186 case POWER_SUPPLY_PROP_DP_DM:
1187 rc = smblib_dp_dm(chg, val->intval);
1188 break;
Abhijeet Dharmapurikar2ec2a792017-05-01 20:00:25 -07001189 case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMITED:
1190 rc = smblib_set_prop_input_current_limited(chg, val);
1191 break;
Nicholas Troast96886052016-02-25 15:42:17 -08001192 default:
Abhijeet Dharmapurikar99fb8942016-07-08 11:39:23 -07001193 rc = -EINVAL;
Nicholas Troast96886052016-02-25 15:42:17 -08001194 }
1195
Abhijeet Dharmapurikar99fb8942016-07-08 11:39:23 -07001196 return rc;
Nicholas Troast96886052016-02-25 15:42:17 -08001197}
1198
1199static int smb2_batt_prop_is_writeable(struct power_supply *psy,
1200 enum power_supply_property psp)
1201{
1202 switch (psp) {
1203 case POWER_SUPPLY_PROP_INPUT_SUSPEND:
Abhijeet Dharmapurikar99fb8942016-07-08 11:39:23 -07001204 case POWER_SUPPLY_PROP_SYSTEM_TEMP_LEVEL:
Abhijeet Dharmapurikar9e7e48c2016-08-23 12:55:49 -07001205 case POWER_SUPPLY_PROP_CAPACITY:
Abhijeet Dharmapurikarc0b0f592016-10-14 10:55:42 -07001206 case POWER_SUPPLY_PROP_PARALLEL_DISABLE:
Ashay Jaiswal6d308da2017-02-18 09:59:23 +05301207 case POWER_SUPPLY_PROP_DP_DM:
1208 case POWER_SUPPLY_PROP_RERUN_AICL:
Abhijeet Dharmapurikar2ec2a792017-05-01 20:00:25 -07001209 case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMITED:
Nicholas Troast96886052016-02-25 15:42:17 -08001210 return 1;
1211 default:
1212 break;
1213 }
1214
1215 return 0;
1216}
1217
1218static const struct power_supply_desc batt_psy_desc = {
1219 .name = "battery",
1220 .type = POWER_SUPPLY_TYPE_BATTERY,
1221 .properties = smb2_batt_props,
1222 .num_properties = ARRAY_SIZE(smb2_batt_props),
1223 .get_property = smb2_batt_get_prop,
1224 .set_property = smb2_batt_set_prop,
1225 .property_is_writeable = smb2_batt_prop_is_writeable,
1226};
1227
1228static int smb2_init_batt_psy(struct smb2 *chip)
1229{
1230 struct power_supply_config batt_cfg = {};
1231 struct smb_charger *chg = &chip->chg;
1232 int rc = 0;
1233
1234 batt_cfg.drv_data = chg;
1235 batt_cfg.of_node = chg->dev->of_node;
Ashay Jaiswald1918f62017-04-27 17:16:26 +05301236 chg->batt_psy = power_supply_register(chg->dev,
Nicholas Troast96886052016-02-25 15:42:17 -08001237 &batt_psy_desc,
1238 &batt_cfg);
1239 if (IS_ERR(chg->batt_psy)) {
1240 pr_err("Couldn't register battery power supply\n");
1241 return PTR_ERR(chg->batt_psy);
1242 }
1243
1244 return rc;
1245}
1246
1247/******************************
1248 * VBUS REGULATOR REGISTRATION *
1249 ******************************/
1250
1251struct regulator_ops smb2_vbus_reg_ops = {
1252 .enable = smblib_vbus_regulator_enable,
1253 .disable = smblib_vbus_regulator_disable,
1254 .is_enabled = smblib_vbus_regulator_is_enabled,
1255};
1256
1257static int smb2_init_vbus_regulator(struct smb2 *chip)
1258{
1259 struct smb_charger *chg = &chip->chg;
1260 struct regulator_config cfg = {};
1261 int rc = 0;
1262
1263 chg->vbus_vreg = devm_kzalloc(chg->dev, sizeof(*chg->vbus_vreg),
1264 GFP_KERNEL);
1265 if (!chg->vbus_vreg)
1266 return -ENOMEM;
1267
1268 cfg.dev = chg->dev;
1269 cfg.driver_data = chip;
1270
1271 chg->vbus_vreg->rdesc.owner = THIS_MODULE;
1272 chg->vbus_vreg->rdesc.type = REGULATOR_VOLTAGE;
1273 chg->vbus_vreg->rdesc.ops = &smb2_vbus_reg_ops;
1274 chg->vbus_vreg->rdesc.of_match = "qcom,smb2-vbus";
1275 chg->vbus_vreg->rdesc.name = "qcom,smb2-vbus";
1276
1277 chg->vbus_vreg->rdev = devm_regulator_register(chg->dev,
1278 &chg->vbus_vreg->rdesc, &cfg);
1279 if (IS_ERR(chg->vbus_vreg->rdev)) {
1280 rc = PTR_ERR(chg->vbus_vreg->rdev);
1281 chg->vbus_vreg->rdev = NULL;
1282 if (rc != -EPROBE_DEFER)
1283 pr_err("Couldn't register VBUS regualtor rc=%d\n", rc);
1284 }
1285
1286 return rc;
1287}
1288
1289/******************************
1290 * VCONN REGULATOR REGISTRATION *
1291 ******************************/
1292
1293struct regulator_ops smb2_vconn_reg_ops = {
1294 .enable = smblib_vconn_regulator_enable,
1295 .disable = smblib_vconn_regulator_disable,
1296 .is_enabled = smblib_vconn_regulator_is_enabled,
1297};
1298
1299static int smb2_init_vconn_regulator(struct smb2 *chip)
1300{
1301 struct smb_charger *chg = &chip->chg;
1302 struct regulator_config cfg = {};
1303 int rc = 0;
1304
Ashay Jaiswal15edce42017-03-31 23:29:58 +05301305 if (chg->micro_usb_mode)
1306 return 0;
1307
Nicholas Troast96886052016-02-25 15:42:17 -08001308 chg->vconn_vreg = devm_kzalloc(chg->dev, sizeof(*chg->vconn_vreg),
1309 GFP_KERNEL);
1310 if (!chg->vconn_vreg)
1311 return -ENOMEM;
1312
1313 cfg.dev = chg->dev;
1314 cfg.driver_data = chip;
1315
1316 chg->vconn_vreg->rdesc.owner = THIS_MODULE;
1317 chg->vconn_vreg->rdesc.type = REGULATOR_VOLTAGE;
1318 chg->vconn_vreg->rdesc.ops = &smb2_vconn_reg_ops;
1319 chg->vconn_vreg->rdesc.of_match = "qcom,smb2-vconn";
1320 chg->vconn_vreg->rdesc.name = "qcom,smb2-vconn";
1321
1322 chg->vconn_vreg->rdev = devm_regulator_register(chg->dev,
1323 &chg->vconn_vreg->rdesc, &cfg);
1324 if (IS_ERR(chg->vconn_vreg->rdev)) {
1325 rc = PTR_ERR(chg->vconn_vreg->rdev);
1326 chg->vconn_vreg->rdev = NULL;
1327 if (rc != -EPROBE_DEFER)
1328 pr_err("Couldn't register VCONN regualtor rc=%d\n", rc);
1329 }
1330
1331 return rc;
1332}
1333
1334/***************************
1335 * HARDWARE INITIALIZATION *
1336 ***************************/
Harry Yangfe913842016-08-10 12:27:28 -07001337static int smb2_config_step_charging(struct smb2 *chip)
1338{
1339 struct smb_charger *chg = &chip->chg;
1340 int rc = 0;
1341 int i;
1342
1343 if (!chg->step_chg_enabled)
1344 return rc;
1345
1346 for (i = 0; i < STEP_CHARGING_MAX_STEPS - 1; i++) {
1347 rc = smblib_set_charge_param(chg,
1348 &chg->param.step_soc_threshold[i],
1349 chip->dt.step_soc_threshold[i]);
1350 if (rc < 0) {
1351 pr_err("Couldn't configure soc thresholds rc = %d\n",
1352 rc);
1353 goto err_out;
1354 }
1355 }
1356
1357 for (i = 0; i < STEP_CHARGING_MAX_STEPS; i++) {
1358 rc = smblib_set_charge_param(chg, &chg->param.step_cc_delta[i],
1359 chip->dt.step_cc_delta[i]);
1360 if (rc < 0) {
1361 pr_err("Couldn't configure cc delta rc = %d\n",
1362 rc);
1363 goto err_out;
1364 }
1365 }
1366
1367 rc = smblib_write(chg, STEP_CHG_UPDATE_REQUEST_TIMEOUT_CFG_REG,
1368 STEP_CHG_UPDATE_REQUEST_TIMEOUT_40S);
1369 if (rc < 0) {
1370 dev_err(chg->dev,
1371 "Couldn't configure soc request timeout reg rc=%d\n",
1372 rc);
1373 goto err_out;
1374 }
1375
1376 rc = smblib_write(chg, STEP_CHG_UPDATE_FAIL_TIMEOUT_CFG_REG,
1377 STEP_CHG_UPDATE_FAIL_TIMEOUT_120S);
1378 if (rc < 0) {
1379 dev_err(chg->dev,
1380 "Couldn't configure soc fail timeout reg rc=%d\n",
1381 rc);
1382 goto err_out;
1383 }
1384
1385 /*
1386 * enable step charging, source soc, standard mode, go to final
1387 * state in case of failure.
1388 */
1389 rc = smblib_write(chg, CHGR_STEP_CHG_MODE_CFG_REG,
1390 STEP_CHARGING_ENABLE_BIT |
1391 STEP_CHARGING_SOURCE_SELECT_BIT |
1392 STEP_CHARGING_SOC_FAIL_OPTION_BIT);
1393 if (rc < 0) {
1394 dev_err(chg->dev, "Couldn't configure charger rc=%d\n", rc);
1395 goto err_out;
1396 }
1397
1398 return 0;
1399err_out:
1400 chg->step_chg_enabled = false;
1401 return rc;
1402}
1403
Abhijeet Dharmapurikar5cf5faf2016-06-21 14:20:24 -07001404static int smb2_config_wipower_input_power(struct smb2 *chip, int uw)
1405{
1406 int rc;
1407 int ua;
1408 struct smb_charger *chg = &chip->chg;
1409 s64 nw = (s64)uw * 1000;
1410
Vic Wei373e0272016-08-11 01:39:11 -07001411 if (uw < 0)
1412 return 0;
1413
Abhijeet Dharmapurikar5cf5faf2016-06-21 14:20:24 -07001414 ua = div_s64(nw, ZIN_ICL_PT_MAX_MV);
1415 rc = smblib_set_charge_param(chg, &chg->param.dc_icl_pt_lv, ua);
1416 if (rc < 0) {
1417 pr_err("Couldn't configure dc_icl_pt_lv rc = %d\n", rc);
1418 return rc;
1419 }
1420
1421 ua = div_s64(nw, ZIN_ICL_PT_HV_MAX_MV);
1422 rc = smblib_set_charge_param(chg, &chg->param.dc_icl_pt_hv, ua);
1423 if (rc < 0) {
1424 pr_err("Couldn't configure dc_icl_pt_hv rc = %d\n", rc);
1425 return rc;
1426 }
1427
1428 ua = div_s64(nw, ZIN_ICL_LV_MAX_MV);
1429 rc = smblib_set_charge_param(chg, &chg->param.dc_icl_div2_lv, ua);
1430 if (rc < 0) {
1431 pr_err("Couldn't configure dc_icl_div2_lv rc = %d\n", rc);
1432 return rc;
1433 }
1434
1435 ua = div_s64(nw, ZIN_ICL_MID_LV_MAX_MV);
1436 rc = smblib_set_charge_param(chg, &chg->param.dc_icl_div2_mid_lv, ua);
1437 if (rc < 0) {
1438 pr_err("Couldn't configure dc_icl_div2_mid_lv rc = %d\n", rc);
1439 return rc;
1440 }
1441
1442 ua = div_s64(nw, ZIN_ICL_MID_HV_MAX_MV);
1443 rc = smblib_set_charge_param(chg, &chg->param.dc_icl_div2_mid_hv, ua);
1444 if (rc < 0) {
1445 pr_err("Couldn't configure dc_icl_div2_mid_hv rc = %d\n", rc);
1446 return rc;
1447 }
1448
1449 ua = div_s64(nw, ZIN_ICL_HV_MAX_MV);
1450 rc = smblib_set_charge_param(chg, &chg->param.dc_icl_div2_hv, ua);
1451 if (rc < 0) {
1452 pr_err("Couldn't configure dc_icl_div2_hv rc = %d\n", rc);
1453 return rc;
1454 }
1455
1456 return 0;
1457}
Nicholas Troast96886052016-02-25 15:42:17 -08001458
Ashay Jaiswal4aa2c0c2016-12-07 19:39:38 +05301459static int smb2_configure_typec(struct smb_charger *chg)
1460{
1461 int rc;
1462
1463 /*
1464 * trigger the usb-typec-change interrupt only when the CC state
1465 * changes
1466 */
1467 rc = smblib_write(chg, TYPE_C_INTRPT_ENB_REG,
1468 TYPEC_CCSTATE_CHANGE_INT_EN_BIT);
1469 if (rc < 0) {
1470 dev_err(chg->dev,
1471 "Couldn't configure Type-C interrupts rc=%d\n", rc);
1472 return rc;
1473 }
1474
Ashay Jaiswal4aa2c0c2016-12-07 19:39:38 +05301475 /*
1476 * disable Type-C factory mode and stay in Attached.SRC state when VCONN
1477 * over-current happens
1478 */
1479 rc = smblib_masked_write(chg, TYPE_C_CFG_REG,
1480 FACTORY_MODE_DETECTION_EN_BIT | VCONN_OC_CFG_BIT, 0);
1481 if (rc < 0) {
1482 dev_err(chg->dev, "Couldn't configure Type-C rc=%d\n", rc);
1483 return rc;
1484 }
1485
1486 /* increase VCONN softstart */
1487 rc = smblib_masked_write(chg, TYPE_C_CFG_2_REG,
1488 VCONN_SOFTSTART_CFG_MASK, VCONN_SOFTSTART_CFG_MASK);
1489 if (rc < 0) {
1490 dev_err(chg->dev, "Couldn't increase VCONN softstart rc=%d\n",
1491 rc);
1492 return rc;
1493 }
1494
Abhijeet Dharmapurikar3c93db32017-04-17 17:36:14 -07001495 /* disable try.SINK mode and legacy cable IRQs */
1496 rc = smblib_masked_write(chg, TYPE_C_CFG_3_REG, EN_TRYSINK_MODE_BIT |
1497 TYPEC_NONCOMPLIANT_LEGACY_CABLE_INT_EN_BIT |
1498 TYPEC_LEGACY_CABLE_INT_EN_BIT, 0);
Ashay Jaiswal4aa2c0c2016-12-07 19:39:38 +05301499 if (rc < 0) {
Abhijeet Dharmapurikar3c93db32017-04-17 17:36:14 -07001500 dev_err(chg->dev, "Couldn't set Type-C config rc=%d\n", rc);
Ashay Jaiswal4aa2c0c2016-12-07 19:39:38 +05301501 return rc;
1502 }
1503
Ashay Jaiswal4aa2c0c2016-12-07 19:39:38 +05301504 return rc;
1505}
1506
1507static int smb2_disable_typec(struct smb_charger *chg)
1508{
1509 int rc;
1510
Ashay Jaiswal82669ba2017-03-11 01:08:37 +05301511 /* Move to typeC mode */
Ashay Jaiswal15edce42017-03-31 23:29:58 +05301512 /* configure FSM in idle state and disable UFP_ENABLE bit */
Ashay Jaiswal4aa2c0c2016-12-07 19:39:38 +05301513 rc = smblib_masked_write(chg, TYPE_C_INTRPT_ENB_SOFTWARE_CTRL_REG,
Ashay Jaiswal15edce42017-03-31 23:29:58 +05301514 TYPEC_DISABLE_CMD_BIT | UFP_EN_CMD_BIT,
1515 TYPEC_DISABLE_CMD_BIT);
Ashay Jaiswal4aa2c0c2016-12-07 19:39:38 +05301516 if (rc < 0) {
1517 dev_err(chg->dev, "Couldn't put FSM in idle rc=%d\n", rc);
1518 return rc;
1519 }
1520
Ashay Jaiswal82669ba2017-03-11 01:08:37 +05301521 /* wait for FSM to enter idle state */
1522 msleep(200);
1523 /* configure TypeC mode */
1524 rc = smblib_masked_write(chg, TYPE_C_CFG_REG,
1525 TYPE_C_OR_U_USB_BIT, 0);
1526 if (rc < 0) {
1527 dev_err(chg->dev, "Couldn't enable micro USB mode rc=%d\n", rc);
1528 return rc;
1529 }
1530
1531 /* wait for mode change before enabling FSM */
1532 usleep_range(10000, 11000);
1533 /* release FSM from idle state */
1534 rc = smblib_masked_write(chg, TYPE_C_INTRPT_ENB_SOFTWARE_CTRL_REG,
1535 TYPEC_DISABLE_CMD_BIT, 0);
1536 if (rc < 0) {
1537 dev_err(chg->dev, "Couldn't release FSM rc=%d\n", rc);
1538 return rc;
1539 }
1540
1541 /* wait for FSM to start */
1542 msleep(100);
1543 /* move to uUSB mode */
1544 /* configure FSM in idle state */
1545 rc = smblib_masked_write(chg, TYPE_C_INTRPT_ENB_SOFTWARE_CTRL_REG,
1546 TYPEC_DISABLE_CMD_BIT, TYPEC_DISABLE_CMD_BIT);
1547 if (rc < 0) {
1548 dev_err(chg->dev, "Couldn't put FSM in idle rc=%d\n", rc);
1549 return rc;
1550 }
1551
1552 /* wait for FSM to enter idle state */
1553 msleep(200);
Ashay Jaiswal4aa2c0c2016-12-07 19:39:38 +05301554 /* configure micro USB mode */
1555 rc = smblib_masked_write(chg, TYPE_C_CFG_REG,
1556 TYPE_C_OR_U_USB_BIT, TYPE_C_OR_U_USB_BIT);
1557 if (rc < 0) {
1558 dev_err(chg->dev, "Couldn't enable micro USB mode rc=%d\n", rc);
1559 return rc;
1560 }
1561
Ashay Jaiswal82669ba2017-03-11 01:08:37 +05301562 /* wait for mode change before enabling FSM */
1563 usleep_range(10000, 11000);
Ashay Jaiswal4aa2c0c2016-12-07 19:39:38 +05301564 /* release FSM from idle state */
1565 rc = smblib_masked_write(chg, TYPE_C_INTRPT_ENB_SOFTWARE_CTRL_REG,
1566 TYPEC_DISABLE_CMD_BIT, 0);
1567 if (rc < 0) {
1568 dev_err(chg->dev, "Couldn't release FSM rc=%d\n", rc);
1569 return rc;
1570 }
1571
1572 return rc;
1573}
1574
Nicholas Troast96886052016-02-25 15:42:17 -08001575static int smb2_init_hw(struct smb2 *chip)
1576{
1577 struct smb_charger *chg = &chip->chg;
1578 int rc;
Nicholas Troast9b593632016-11-14 11:12:29 -08001579 u8 stat;
Nicholas Troast96886052016-02-25 15:42:17 -08001580
Nicholas Troast2ebe6c52016-09-20 13:25:59 -07001581 if (chip->dt.no_battery)
1582 chg->fake_capacity = 50;
1583
Abhijeet Dharmapurikarc31b4ab2017-04-27 19:20:31 -07001584 if (chg->batt_profile_fcc_ua < 0)
1585 smblib_get_charge_param(chg, &chg->param.fcc,
1586 &chg->batt_profile_fcc_ua);
Nicholas Troast4f2d7962016-07-27 11:08:10 -07001587
Abhijeet Dharmapurikarc31b4ab2017-04-27 19:20:31 -07001588 if (chg->batt_profile_fv_uv < 0)
1589 smblib_get_charge_param(chg, &chg->param.fv,
1590 &chg->batt_profile_fv_uv);
Nicholas Troast4f2d7962016-07-27 11:08:10 -07001591
Abhijeet Dharmapurikar7442e422017-02-08 13:35:14 -08001592 smblib_get_charge_param(chg, &chg->param.usb_icl,
1593 &chg->default_icl_ua);
Nicholas Troast4f2d7962016-07-27 11:08:10 -07001594 if (chip->dt.usb_icl_ua < 0)
Abhijeet Dharmapurikar7442e422017-02-08 13:35:14 -08001595 chip->dt.usb_icl_ua = chg->default_icl_ua;
Nicholas Troast4f2d7962016-07-27 11:08:10 -07001596
1597 if (chip->dt.dc_icl_ua < 0)
1598 smblib_get_charge_param(chg, &chg->param.dc_icl,
1599 &chip->dt.dc_icl_ua);
1600
Anirudh Ghayalca8ce4d2017-04-10 08:27:11 +05301601 if (chip->dt.min_freq_khz > 0) {
1602 chg->param.freq_buck.min_u = chip->dt.min_freq_khz;
1603 chg->param.freq_boost.min_u = chip->dt.min_freq_khz;
1604 }
1605
1606 if (chip->dt.max_freq_khz > 0) {
1607 chg->param.freq_buck.max_u = chip->dt.max_freq_khz;
1608 chg->param.freq_boost.max_u = chip->dt.max_freq_khz;
1609 }
1610
Nicholas Troastb11015f2017-01-17 17:56:45 -08001611 /* set a slower soft start setting for OTG */
1612 rc = smblib_masked_write(chg, DC_ENG_SSUPPLY_CFG2_REG,
1613 ENG_SSUPPLY_IVREF_OTG_SS_MASK, OTG_SS_SLOW);
1614 if (rc < 0) {
1615 pr_err("Couldn't set otg soft start rc=%d\n", rc);
1616 return rc;
1617 }
1618
1619 /* set OTG current limit */
1620 rc = smblib_set_charge_param(chg, &chg->param.otg_cl,
Ashay Jaiswal7c241382017-03-06 15:26:38 +05301621 (chg->wa_flags & OTG_WA) ?
1622 chg->param.otg_cl.min_u : chg->otg_cl_ua);
Nicholas Troastb11015f2017-01-17 17:56:45 -08001623 if (rc < 0) {
1624 pr_err("Couldn't set otg current limit rc=%d\n", rc);
1625 return rc;
1626 }
1627
Harry Yangd89ff1f2016-12-05 14:59:11 -08001628 chg->boost_threshold_ua = chip->dt.boost_threshold_ua;
Harry Yang360bd532016-09-26 11:03:22 -07001629
Nicholas Troast9b593632016-11-14 11:12:29 -08001630 rc = smblib_read(chg, APSD_RESULT_STATUS_REG, &stat);
1631 if (rc < 0) {
1632 pr_err("Couldn't read APSD_RESULT_STATUS rc=%d\n", rc);
1633 return rc;
1634 }
1635
Abhijeet Dharmapurikar9dd61292017-01-25 16:40:08 -08001636 smblib_rerun_apsd_if_required(chg);
1637
Nicholas Troast9b593632016-11-14 11:12:29 -08001638 /* clear the ICL override if it is set */
Abhijeet Dharmapurikar74021fc2017-02-06 18:39:19 -08001639 if (smblib_icl_override(chg, false) < 0) {
1640 pr_err("Couldn't disable ICL override rc=%d\n", rc);
1641 return rc;
Nicholas Troast9b593632016-11-14 11:12:29 -08001642 }
1643
Nicholas Troast96886052016-02-25 15:42:17 -08001644 /* votes must be cast before configuring software control */
Abhijeet Dharmapurikar5e0bfbe2017-02-12 19:16:15 -08001645 /* vote 0mA on usb_icl for non battery platforms */
1646 vote(chg->usb_icl_votable,
Nicholas Troast2ebe6c52016-09-20 13:25:59 -07001647 DEFAULT_VOTER, chip->dt.no_battery, 0);
Nicholas Troast96886052016-02-25 15:42:17 -08001648 vote(chg->dc_suspend_votable,
Nicholas Troast2ebe6c52016-09-20 13:25:59 -07001649 DEFAULT_VOTER, chip->dt.no_battery, 0);
Harry Yange0695172017-02-07 13:29:57 -08001650 vote(chg->fcc_votable,
Abhijeet Dharmapurikarc31b4ab2017-04-27 19:20:31 -07001651 BATT_PROFILE_VOTER, true, chg->batt_profile_fcc_ua);
Abhijeet Dharmapurikarf9805d42016-05-17 18:38:42 -07001652 vote(chg->fv_votable,
Abhijeet Dharmapurikarc31b4ab2017-04-27 19:20:31 -07001653 BATT_PROFILE_VOTER, true, chg->batt_profile_fv_uv);
Nicholas Troast96886052016-02-25 15:42:17 -08001654 vote(chg->dc_icl_votable,
1655 DEFAULT_VOTER, true, chip->dt.dc_icl_ua);
Ashay Jaiswal4aa2c0c2016-12-07 19:39:38 +05301656 vote(chg->hvdcp_disable_votable_indirect, PD_INACTIVE_VOTER,
Abhijeet Dharmapurikar716cd962016-10-14 12:50:37 -07001657 true, 0);
Abhijeet Dharmapurikar3c93db32017-04-17 17:36:14 -07001658 vote(chg->hvdcp_disable_votable_indirect, VBUS_CC_SHORT_VOTER,
1659 true, 0);
Abhijeet Dharmapurikar025e63a2017-02-24 14:06:22 -08001660 vote(chg->hvdcp_disable_votable_indirect, DEFAULT_VOTER,
1661 chip->dt.hvdcp_disable, 0);
Abhijeet Dharmapurikar4b13c6e2016-10-05 15:15:10 -07001662 vote(chg->pd_disallowed_votable_indirect, CC_DETACHED_VOTER,
1663 true, 0);
1664 vote(chg->pd_disallowed_votable_indirect, HVDCP_TIMEOUT_VOTER,
1665 true, 0);
Ashay Jaiswal4aa2c0c2016-12-07 19:39:38 +05301666 vote(chg->pd_disallowed_votable_indirect, MICRO_USB_VOTER,
1667 chg->micro_usb_mode, 0);
1668 vote(chg->hvdcp_enable_votable, MICRO_USB_VOTER,
1669 chg->micro_usb_mode, 0);
Nicholas Troast96886052016-02-25 15:42:17 -08001670
Ashay Jaiswal923e6f82017-02-06 23:31:29 +05301671 /*
1672 * AICL configuration:
1673 * start from min and AICL ADC disable
1674 */
1675 rc = smblib_masked_write(chg, USBIN_AICL_OPTIONS_CFG_REG,
1676 USBIN_AICL_START_AT_MAX_BIT
1677 | USBIN_AICL_ADC_EN_BIT, 0);
1678 if (rc < 0) {
1679 dev_err(chg->dev, "Couldn't configure AICL rc=%d\n", rc);
1680 return rc;
1681 }
1682
Subbaraman Narayanamurthy04d3e502016-10-05 15:22:04 -07001683 /* Configure charge enable for software control; active high */
Nicholas Troast96886052016-02-25 15:42:17 -08001684 rc = smblib_masked_write(chg, CHGR_CFG2_REG,
Nicholas Troastfb827ac42016-07-19 15:48:31 -07001685 CHG_EN_POLARITY_BIT |
Subbaraman Narayanamurthy04d3e502016-10-05 15:22:04 -07001686 CHG_EN_SRC_BIT, 0);
Nicholas Troast96886052016-02-25 15:42:17 -08001687 if (rc < 0) {
Nicholas Troastfb827ac42016-07-19 15:48:31 -07001688 dev_err(chg->dev, "Couldn't configure charger rc=%d\n", rc);
Nicholas Troast96886052016-02-25 15:42:17 -08001689 return rc;
1690 }
1691
1692 /* enable the charging path */
Abhijeet Dharmapurikaree54de02016-07-08 14:51:47 -07001693 rc = vote(chg->chg_disable_votable, DEFAULT_VOTER, false, 0);
Nicholas Troast96886052016-02-25 15:42:17 -08001694 if (rc < 0) {
1695 dev_err(chg->dev, "Couldn't enable charging rc=%d\n", rc);
1696 return rc;
1697 }
1698
Ashay Jaiswal4aa2c0c2016-12-07 19:39:38 +05301699 if (chg->micro_usb_mode)
1700 rc = smb2_disable_typec(chg);
1701 else
1702 rc = smb2_configure_typec(chg);
Nicholas Troast96886052016-02-25 15:42:17 -08001703 if (rc < 0) {
1704 dev_err(chg->dev,
1705 "Couldn't configure Type-C interrupts rc=%d\n", rc);
1706 return rc;
1707 }
1708
1709 /* configure VCONN for software control */
1710 rc = smblib_masked_write(chg, TYPE_C_INTRPT_ENB_SOFTWARE_CTRL_REG,
1711 VCONN_EN_SRC_BIT | VCONN_EN_VALUE_BIT,
1712 VCONN_EN_SRC_BIT);
1713 if (rc < 0) {
1714 dev_err(chg->dev,
1715 "Couldn't configure VCONN for SW control rc=%d\n", rc);
1716 return rc;
1717 }
1718
1719 /* configure VBUS for software control */
1720 rc = smblib_masked_write(chg, OTG_CFG_REG, OTG_EN_SRC_CFG_BIT, 0);
1721 if (rc < 0) {
1722 dev_err(chg->dev,
1723 "Couldn't configure VBUS for SW control rc=%d\n", rc);
1724 return rc;
1725 }
1726
Harry Yangfe913842016-08-10 12:27:28 -07001727 /* configure step charging */
1728 rc = smb2_config_step_charging(chip);
1729 if (rc < 0) {
1730 dev_err(chg->dev, "Couldn't configure step charging rc=%d\n",
1731 rc);
1732 return rc;
1733 }
1734
Abhijeet Dharmapurikar5cf5faf2016-06-21 14:20:24 -07001735 /* configure wipower watts */
1736 rc = smb2_config_wipower_input_power(chip, chip->dt.wipower_max_uw);
1737 if (rc < 0) {
1738 dev_err(chg->dev, "Couldn't configure wipower rc=%d\n", rc);
1739 return rc;
1740 }
1741
Nicholas Troastc8bc99f2016-11-14 11:22:17 -08001742 /* disable SW STAT override */
Harry Yangd57681c2016-08-29 11:46:43 -07001743 rc = smblib_masked_write(chg, STAT_CFG_REG,
Nicholas Troastc8bc99f2016-11-14 11:22:17 -08001744 STAT_SW_OVERRIDE_CFG_BIT, 0);
Harry Yangd57681c2016-08-29 11:46:43 -07001745 if (rc < 0) {
Nicholas Troastc8bc99f2016-11-14 11:22:17 -08001746 dev_err(chg->dev, "Couldn't disable SW STAT override rc=%d\n",
1747 rc);
Harry Yangd57681c2016-08-29 11:46:43 -07001748 return rc;
1749 }
1750
Ashay Jaiswald633b922017-03-21 22:46:06 +05301751 /* disable h/w autonomous parallel charging control */
1752 rc = smblib_masked_write(chg, MISC_CFG_REG,
1753 STAT_PARALLEL_1400MA_EN_CFG_BIT, 0);
1754 if (rc < 0) {
1755 dev_err(chg->dev,
1756 "Couldn't disable h/w autonomous parallel control rc=%d\n",
1757 rc);
1758 return rc;
1759 }
1760
Nicholas Troast597acfe2016-07-20 16:03:15 -07001761 /* configure float charger options */
1762 switch (chip->dt.float_option) {
1763 case 1:
1764 rc = smblib_masked_write(chg, USBIN_OPTIONS_2_CFG_REG,
1765 FLOAT_OPTIONS_MASK, 0);
1766 break;
1767 case 2:
1768 rc = smblib_masked_write(chg, USBIN_OPTIONS_2_CFG_REG,
1769 FLOAT_OPTIONS_MASK, FORCE_FLOAT_SDP_CFG_BIT);
1770 break;
1771 case 3:
1772 rc = smblib_masked_write(chg, USBIN_OPTIONS_2_CFG_REG,
1773 FLOAT_OPTIONS_MASK, FLOAT_DIS_CHGING_CFG_BIT);
1774 break;
1775 case 4:
1776 rc = smblib_masked_write(chg, USBIN_OPTIONS_2_CFG_REG,
1777 FLOAT_OPTIONS_MASK, SUSPEND_FLOAT_CFG_BIT);
1778 break;
1779 default:
1780 rc = 0;
1781 break;
1782 }
1783
1784 if (rc < 0) {
1785 dev_err(chg->dev, "Couldn't configure float charger options rc=%d\n",
1786 rc);
1787 return rc;
1788 }
1789
Subbaraman Narayanamurthy5c4f6de2016-11-02 15:25:32 -07001790 switch (chip->dt.chg_inhibit_thr_mv) {
1791 case 50:
1792 rc = smblib_masked_write(chg, CHARGE_INHIBIT_THRESHOLD_CFG_REG,
1793 CHARGE_INHIBIT_THRESHOLD_MASK,
1794 CHARGE_INHIBIT_THRESHOLD_50MV);
1795 break;
1796 case 100:
1797 rc = smblib_masked_write(chg, CHARGE_INHIBIT_THRESHOLD_CFG_REG,
1798 CHARGE_INHIBIT_THRESHOLD_MASK,
1799 CHARGE_INHIBIT_THRESHOLD_100MV);
1800 break;
1801 case 200:
1802 rc = smblib_masked_write(chg, CHARGE_INHIBIT_THRESHOLD_CFG_REG,
1803 CHARGE_INHIBIT_THRESHOLD_MASK,
1804 CHARGE_INHIBIT_THRESHOLD_200MV);
1805 break;
1806 case 300:
1807 rc = smblib_masked_write(chg, CHARGE_INHIBIT_THRESHOLD_CFG_REG,
1808 CHARGE_INHIBIT_THRESHOLD_MASK,
1809 CHARGE_INHIBIT_THRESHOLD_300MV);
1810 break;
1811 case 0:
1812 rc = smblib_masked_write(chg, CHGR_CFG2_REG,
1813 CHARGER_INHIBIT_BIT, 0);
1814 default:
1815 break;
1816 }
1817
1818 if (rc < 0) {
1819 dev_err(chg->dev, "Couldn't configure charge inhibit threshold rc=%d\n",
1820 rc);
1821 return rc;
1822 }
1823
Subbaraman Narayanamurthy851f4172016-11-15 19:39:08 -08001824 if (chip->dt.auto_recharge_soc) {
1825 rc = smblib_masked_write(chg, FG_UPDATE_CFG_2_SEL_REG,
1826 SOC_LT_CHG_RECHARGE_THRESH_SEL_BIT |
1827 VBT_LT_CHG_RECHARGE_THRESH_SEL_BIT,
1828 VBT_LT_CHG_RECHARGE_THRESH_SEL_BIT);
1829 if (rc < 0) {
1830 dev_err(chg->dev, "Couldn't configure FG_UPDATE_CFG2_SEL_REG rc=%d\n",
1831 rc);
1832 return rc;
1833 }
1834 } else {
1835 rc = smblib_masked_write(chg, FG_UPDATE_CFG_2_SEL_REG,
1836 SOC_LT_CHG_RECHARGE_THRESH_SEL_BIT |
1837 VBT_LT_CHG_RECHARGE_THRESH_SEL_BIT,
1838 SOC_LT_CHG_RECHARGE_THRESH_SEL_BIT);
1839 if (rc < 0) {
1840 dev_err(chg->dev, "Couldn't configure FG_UPDATE_CFG2_SEL_REG rc=%d\n",
1841 rc);
1842 return rc;
1843 }
1844 }
1845
Nicholas Troast96886052016-02-25 15:42:17 -08001846 return rc;
1847}
1848
Harry Yang4bf7d962017-03-13 16:51:43 -07001849static int smb2_post_init(struct smb2 *chip)
1850{
1851 struct smb_charger *chg = &chip->chg;
Ashay Jaiswal1d046d912017-06-21 14:11:41 +05301852 int rc;
1853
1854 /* configure power role for dual-role */
1855 rc = smblib_masked_write(chg, TYPE_C_INTRPT_ENB_SOFTWARE_CTRL_REG,
1856 TYPEC_POWER_ROLE_CMD_MASK, 0);
1857 if (rc < 0) {
1858 dev_err(chg->dev,
1859 "Couldn't configure power role for DRP rc=%d\n", rc);
1860 return rc;
1861 }
Harry Yang4bf7d962017-03-13 16:51:43 -07001862
1863 rerun_election(chg->usb_irq_enable_votable);
1864
1865 return 0;
1866}
1867
Anirudh Ghayal4da3df92017-01-25 18:55:57 +05301868static int smb2_chg_config_init(struct smb2 *chip)
Harry Yangf7251982016-09-16 11:14:49 -07001869{
Harry Yang1369b7a2016-09-27 15:59:50 -07001870 struct smb_charger *chg = &chip->chg;
Harry Yangf7251982016-09-16 11:14:49 -07001871 struct pmic_revid_data *pmic_rev_id;
1872 struct device_node *revid_dev_node;
1873
1874 revid_dev_node = of_parse_phandle(chip->chg.dev->of_node,
1875 "qcom,pmic-revid", 0);
1876 if (!revid_dev_node) {
1877 pr_err("Missing qcom,pmic-revid property\n");
1878 return -EINVAL;
1879 }
1880
1881 pmic_rev_id = get_revid_data(revid_dev_node);
1882 if (IS_ERR_OR_NULL(pmic_rev_id)) {
1883 /*
1884 * the revid peripheral must be registered, any failure
1885 * here only indicates that the rev-id module has not
1886 * probed yet.
1887 */
1888 return -EPROBE_DEFER;
1889 }
1890
1891 switch (pmic_rev_id->pmic_subtype) {
Harry Yang2452b272017-03-06 13:56:14 -08001892 case PMI8998_SUBTYPE:
Abhijeet Dharmapurikar7442e422017-02-08 13:35:14 -08001893 chip->chg.smb_version = PMI8998_SUBTYPE;
Ashay Jaiswal67ec7072017-02-16 14:14:58 +05301894 chip->chg.wa_flags |= BOOST_BACK_WA | QC_AUTH_INTERRUPT_WA_BIT;
Harry Yang2452b272017-03-06 13:56:14 -08001895 if (pmic_rev_id->rev4 == PMI8998_V1P1_REV4) /* PMI rev 1.1 */
Harry Yang1369b7a2016-09-27 15:59:50 -07001896 chg->wa_flags |= QC_CHARGER_DETECTION_WA_BIT;
Harry Yang2452b272017-03-06 13:56:14 -08001897 if (pmic_rev_id->rev4 == PMI8998_V2P0_REV4) /* PMI rev 2.0 */
Harry Yang755a34b2016-11-01 01:18:51 -07001898 chg->wa_flags |= TYPEC_CC2_REMOVAL_WA_BIT;
Anirudh Ghayal4da3df92017-01-25 18:55:57 +05301899 chg->chg_freq.freq_5V = 600;
1900 chg->chg_freq.freq_6V_8V = 800;
1901 chg->chg_freq.freq_9V = 1000;
1902 chg->chg_freq.freq_12V = 1200;
1903 chg->chg_freq.freq_removal = 1000;
1904 chg->chg_freq.freq_below_otg_threshold = 2000;
1905 chg->chg_freq.freq_above_otg_threshold = 800;
Harry Yangf7251982016-09-16 11:14:49 -07001906 break;
Harry Yange4e731b2017-03-06 14:35:09 -08001907 case PM660_SUBTYPE:
Abhijeet Dharmapurikar7442e422017-02-08 13:35:14 -08001908 chip->chg.smb_version = PM660_SUBTYPE;
Ashay Jaiswal7c241382017-03-06 15:26:38 +05301909 chip->chg.wa_flags |= BOOST_BACK_WA | OTG_WA;
Anirudh Ghayal4da3df92017-01-25 18:55:57 +05301910 chg->param.freq_buck = pm660_params.freq_buck;
1911 chg->param.freq_boost = pm660_params.freq_boost;
1912 chg->chg_freq.freq_5V = 600;
1913 chg->chg_freq.freq_6V_8V = 800;
1914 chg->chg_freq.freq_9V = 1050;
1915 chg->chg_freq.freq_12V = 1200;
1916 chg->chg_freq.freq_removal = 1050;
1917 chg->chg_freq.freq_below_otg_threshold = 1600;
1918 chg->chg_freq.freq_above_otg_threshold = 800;
Ashay Jaiswal7da65f22016-11-30 11:42:36 +05301919 break;
Harry Yangf7251982016-09-16 11:14:49 -07001920 default:
1921 pr_err("PMIC subtype %d not supported\n",
1922 pmic_rev_id->pmic_subtype);
1923 return -EINVAL;
1924 }
1925
1926 return 0;
1927}
1928
Nicholas Troast96886052016-02-25 15:42:17 -08001929/****************************
1930 * DETERMINE INITIAL STATUS *
1931 ****************************/
1932
1933static int smb2_determine_initial_status(struct smb2 *chip)
1934{
1935 struct smb_irq_data irq_data = {chip, "determine-initial-status"};
Ashay Jaiswal2fb369d2017-01-12 21:38:29 +05301936 struct smb_charger *chg = &chip->chg;
Nicholas Troast96886052016-02-25 15:42:17 -08001937
Ashay Jaiswal2fb369d2017-01-12 21:38:29 +05301938 if (chg->bms_psy)
1939 smblib_suspend_on_debug_battery(chg);
Nicholas Troast96886052016-02-25 15:42:17 -08001940 smblib_handle_usb_plugin(0, &irq_data);
1941 smblib_handle_usb_typec_change(0, &irq_data);
1942 smblib_handle_usb_source_change(0, &irq_data);
Harry Yang58a9e7a2016-06-23 14:54:43 -07001943 smblib_handle_chg_state_change(0, &irq_data);
1944 smblib_handle_icl_change(0, &irq_data);
Harry Yangfe913842016-08-10 12:27:28 -07001945 smblib_handle_step_chg_state_change(0, &irq_data);
1946 smblib_handle_step_chg_soc_update_request(0, &irq_data);
Nicholas Troast96886052016-02-25 15:42:17 -08001947
1948 return 0;
1949}
1950
1951/**************************
1952 * INTERRUPT REGISTRATION *
1953 **************************/
1954
Subbaraman Narayanamurthybbd7f452017-02-06 16:22:48 -08001955static struct smb_irq_info smb2_irqs[] = {
Nicholas Troast96886052016-02-25 15:42:17 -08001956/* CHARGER IRQs */
Subbaraman Narayanamurthybbd7f452017-02-06 16:22:48 -08001957 [CHG_ERROR_IRQ] = {
Nicholas Troast47ae4612016-08-03 09:49:36 -07001958 .name = "chg-error",
1959 .handler = smblib_handle_debug,
1960 },
Subbaraman Narayanamurthybbd7f452017-02-06 16:22:48 -08001961 [CHG_STATE_CHANGE_IRQ] = {
Nicholas Troast47ae4612016-08-03 09:49:36 -07001962 .name = "chg-state-change",
1963 .handler = smblib_handle_chg_state_change,
1964 .wake = true,
1965 },
Subbaraman Narayanamurthybbd7f452017-02-06 16:22:48 -08001966 [STEP_CHG_STATE_CHANGE_IRQ] = {
Nicholas Troast47ae4612016-08-03 09:49:36 -07001967 .name = "step-chg-state-change",
1968 .handler = smblib_handle_step_chg_state_change,
1969 .wake = true,
1970 },
Subbaraman Narayanamurthybbd7f452017-02-06 16:22:48 -08001971 [STEP_CHG_SOC_UPDATE_FAIL_IRQ] = {
Nicholas Troast47ae4612016-08-03 09:49:36 -07001972 .name = "step-chg-soc-update-fail",
1973 .handler = smblib_handle_step_chg_soc_update_fail,
1974 .wake = true,
1975 },
Subbaraman Narayanamurthybbd7f452017-02-06 16:22:48 -08001976 [STEP_CHG_SOC_UPDATE_REQ_IRQ] = {
Nicholas Troast47ae4612016-08-03 09:49:36 -07001977 .name = "step-chg-soc-update-request",
1978 .handler = smblib_handle_step_chg_soc_update_request,
1979 .wake = true,
1980 },
Nicholas Troast96886052016-02-25 15:42:17 -08001981/* OTG IRQs */
Subbaraman Narayanamurthybbd7f452017-02-06 16:22:48 -08001982 [OTG_FAIL_IRQ] = {
Nicholas Troast47ae4612016-08-03 09:49:36 -07001983 .name = "otg-fail",
1984 .handler = smblib_handle_debug,
1985 },
Subbaraman Narayanamurthybbd7f452017-02-06 16:22:48 -08001986 [OTG_OVERCURRENT_IRQ] = {
Nicholas Troast47ae4612016-08-03 09:49:36 -07001987 .name = "otg-overcurrent",
Nicholas Troast8995a702016-12-05 10:22:22 -08001988 .handler = smblib_handle_otg_overcurrent,
Nicholas Troast47ae4612016-08-03 09:49:36 -07001989 },
Subbaraman Narayanamurthybbd7f452017-02-06 16:22:48 -08001990 [OTG_OC_DIS_SW_STS_IRQ] = {
Nicholas Troast47ae4612016-08-03 09:49:36 -07001991 .name = "otg-oc-dis-sw-sts",
1992 .handler = smblib_handle_debug,
1993 },
Subbaraman Narayanamurthybbd7f452017-02-06 16:22:48 -08001994 [TESTMODE_CHANGE_DET_IRQ] = {
Nicholas Troast47ae4612016-08-03 09:49:36 -07001995 .name = "testmode-change-detect",
1996 .handler = smblib_handle_debug,
1997 },
Nicholas Troast96886052016-02-25 15:42:17 -08001998/* BATTERY IRQs */
Subbaraman Narayanamurthybbd7f452017-02-06 16:22:48 -08001999 [BATT_TEMP_IRQ] = {
Nicholas Troast47ae4612016-08-03 09:49:36 -07002000 .name = "bat-temp",
2001 .handler = smblib_handle_batt_temp_changed,
2002 },
Subbaraman Narayanamurthybbd7f452017-02-06 16:22:48 -08002003 [BATT_OCP_IRQ] = {
Nicholas Troast47ae4612016-08-03 09:49:36 -07002004 .name = "bat-ocp",
2005 .handler = smblib_handle_batt_psy_changed,
2006 },
Subbaraman Narayanamurthybbd7f452017-02-06 16:22:48 -08002007 [BATT_OV_IRQ] = {
Nicholas Troast47ae4612016-08-03 09:49:36 -07002008 .name = "bat-ov",
2009 .handler = smblib_handle_batt_psy_changed,
2010 },
Subbaraman Narayanamurthybbd7f452017-02-06 16:22:48 -08002011 [BATT_LOW_IRQ] = {
Nicholas Troast47ae4612016-08-03 09:49:36 -07002012 .name = "bat-low",
2013 .handler = smblib_handle_batt_psy_changed,
2014 },
Subbaraman Narayanamurthybbd7f452017-02-06 16:22:48 -08002015 [BATT_THERM_ID_MISS_IRQ] = {
Nicholas Troast47ae4612016-08-03 09:49:36 -07002016 .name = "bat-therm-or-id-missing",
2017 .handler = smblib_handle_batt_psy_changed,
2018 },
Subbaraman Narayanamurthybbd7f452017-02-06 16:22:48 -08002019 [BATT_TERM_MISS_IRQ] = {
Nicholas Troast47ae4612016-08-03 09:49:36 -07002020 .name = "bat-terminal-missing",
2021 .handler = smblib_handle_batt_psy_changed,
2022 },
Nicholas Troast96886052016-02-25 15:42:17 -08002023/* USB INPUT IRQs */
Subbaraman Narayanamurthybbd7f452017-02-06 16:22:48 -08002024 [USBIN_COLLAPSE_IRQ] = {
Nicholas Troast47ae4612016-08-03 09:49:36 -07002025 .name = "usbin-collapse",
2026 .handler = smblib_handle_debug,
2027 },
Subbaraman Narayanamurthybbd7f452017-02-06 16:22:48 -08002028 [USBIN_LT_3P6V_IRQ] = {
Nicholas Troast47ae4612016-08-03 09:49:36 -07002029 .name = "usbin-lt-3p6v",
2030 .handler = smblib_handle_debug,
2031 },
Subbaraman Narayanamurthybbd7f452017-02-06 16:22:48 -08002032 [USBIN_UV_IRQ] = {
Nicholas Troast47ae4612016-08-03 09:49:36 -07002033 .name = "usbin-uv",
Subbaraman Narayanamurthy09327482017-02-06 16:33:12 -08002034 .handler = smblib_handle_usbin_uv,
Nicholas Troast47ae4612016-08-03 09:49:36 -07002035 },
Subbaraman Narayanamurthybbd7f452017-02-06 16:22:48 -08002036 [USBIN_OV_IRQ] = {
Nicholas Troast47ae4612016-08-03 09:49:36 -07002037 .name = "usbin-ov",
2038 .handler = smblib_handle_debug,
2039 },
Subbaraman Narayanamurthybbd7f452017-02-06 16:22:48 -08002040 [USBIN_PLUGIN_IRQ] = {
Nicholas Troast47ae4612016-08-03 09:49:36 -07002041 .name = "usbin-plugin",
2042 .handler = smblib_handle_usb_plugin,
2043 .wake = true,
2044 },
Subbaraman Narayanamurthybbd7f452017-02-06 16:22:48 -08002045 [USBIN_SRC_CHANGE_IRQ] = {
Nicholas Troast47ae4612016-08-03 09:49:36 -07002046 .name = "usbin-src-change",
2047 .handler = smblib_handle_usb_source_change,
2048 .wake = true,
2049 },
Subbaraman Narayanamurthybbd7f452017-02-06 16:22:48 -08002050 [USBIN_ICL_CHANGE_IRQ] = {
Nicholas Troast47ae4612016-08-03 09:49:36 -07002051 .name = "usbin-icl-change",
2052 .handler = smblib_handle_icl_change,
2053 .wake = true,
2054 },
Subbaraman Narayanamurthybbd7f452017-02-06 16:22:48 -08002055 [TYPE_C_CHANGE_IRQ] = {
Nicholas Troast47ae4612016-08-03 09:49:36 -07002056 .name = "type-c-change",
2057 .handler = smblib_handle_usb_typec_change,
2058 .wake = true,
2059 },
Nicholas Troast96886052016-02-25 15:42:17 -08002060/* DC INPUT IRQs */
Subbaraman Narayanamurthybbd7f452017-02-06 16:22:48 -08002061 [DCIN_COLLAPSE_IRQ] = {
Nicholas Troast47ae4612016-08-03 09:49:36 -07002062 .name = "dcin-collapse",
2063 .handler = smblib_handle_debug,
2064 },
Subbaraman Narayanamurthybbd7f452017-02-06 16:22:48 -08002065 [DCIN_LT_3P6V_IRQ] = {
Nicholas Troast47ae4612016-08-03 09:49:36 -07002066 .name = "dcin-lt-3p6v",
2067 .handler = smblib_handle_debug,
2068 },
Subbaraman Narayanamurthybbd7f452017-02-06 16:22:48 -08002069 [DCIN_UV_IRQ] = {
Nicholas Troast47ae4612016-08-03 09:49:36 -07002070 .name = "dcin-uv",
2071 .handler = smblib_handle_debug,
2072 },
Subbaraman Narayanamurthybbd7f452017-02-06 16:22:48 -08002073 [DCIN_OV_IRQ] = {
Nicholas Troast47ae4612016-08-03 09:49:36 -07002074 .name = "dcin-ov",
2075 .handler = smblib_handle_debug,
2076 },
Subbaraman Narayanamurthybbd7f452017-02-06 16:22:48 -08002077 [DCIN_PLUGIN_IRQ] = {
Nicholas Troast47ae4612016-08-03 09:49:36 -07002078 .name = "dcin-plugin",
Abhijeet Dharmapurikar23916642016-10-03 10:38:50 -07002079 .handler = smblib_handle_dc_plugin,
2080 .wake = true,
Nicholas Troast47ae4612016-08-03 09:49:36 -07002081 },
Subbaraman Narayanamurthybbd7f452017-02-06 16:22:48 -08002082 [DIV2_EN_DG_IRQ] = {
Nicholas Troast47ae4612016-08-03 09:49:36 -07002083 .name = "div2-en-dg",
2084 .handler = smblib_handle_debug,
2085 },
Subbaraman Narayanamurthybbd7f452017-02-06 16:22:48 -08002086 [DCIN_ICL_CHANGE_IRQ] = {
Nicholas Troast47ae4612016-08-03 09:49:36 -07002087 .name = "dcin-icl-change",
2088 .handler = smblib_handle_debug,
2089 },
Nicholas Troast96886052016-02-25 15:42:17 -08002090/* MISCELLANEOUS IRQs */
Subbaraman Narayanamurthybbd7f452017-02-06 16:22:48 -08002091 [WDOG_SNARL_IRQ] = {
Nicholas Troast47ae4612016-08-03 09:49:36 -07002092 .name = "wdog-snarl",
2093 .handler = NULL,
2094 },
Subbaraman Narayanamurthybbd7f452017-02-06 16:22:48 -08002095 [WDOG_BARK_IRQ] = {
Nicholas Troast47ae4612016-08-03 09:49:36 -07002096 .name = "wdog-bark",
2097 .handler = NULL,
2098 },
Subbaraman Narayanamurthybbd7f452017-02-06 16:22:48 -08002099 [AICL_FAIL_IRQ] = {
Nicholas Troast47ae4612016-08-03 09:49:36 -07002100 .name = "aicl-fail",
2101 .handler = smblib_handle_debug,
2102 },
Subbaraman Narayanamurthybbd7f452017-02-06 16:22:48 -08002103 [AICL_DONE_IRQ] = {
Nicholas Troast47ae4612016-08-03 09:49:36 -07002104 .name = "aicl-done",
2105 .handler = smblib_handle_debug,
2106 },
Subbaraman Narayanamurthybbd7f452017-02-06 16:22:48 -08002107 [HIGH_DUTY_CYCLE_IRQ] = {
Nicholas Troast47ae4612016-08-03 09:49:36 -07002108 .name = "high-duty-cycle",
2109 .handler = smblib_handle_high_duty_cycle,
2110 .wake = true,
2111 },
Subbaraman Narayanamurthybbd7f452017-02-06 16:22:48 -08002112 [INPUT_CURRENT_LIMIT_IRQ] = {
Nicholas Troast47ae4612016-08-03 09:49:36 -07002113 .name = "input-current-limiting",
2114 .handler = smblib_handle_debug,
2115 },
Subbaraman Narayanamurthybbd7f452017-02-06 16:22:48 -08002116 [TEMPERATURE_CHANGE_IRQ] = {
Nicholas Troast47ae4612016-08-03 09:49:36 -07002117 .name = "temperature-change",
2118 .handler = smblib_handle_debug,
2119 },
Subbaraman Narayanamurthybbd7f452017-02-06 16:22:48 -08002120 [SWITCH_POWER_OK_IRQ] = {
Nicholas Troast47ae4612016-08-03 09:49:36 -07002121 .name = "switcher-power-ok",
Nicholas Troastabedaf72016-09-16 11:07:45 -07002122 .handler = smblib_handle_switcher_power_ok,
Ashay Jaiswal2f3b0c12017-06-14 16:04:45 +05302123 .storm_data = {true, 1000, 8},
Nicholas Troast47ae4612016-08-03 09:49:36 -07002124 },
Nicholas Troast96886052016-02-25 15:42:17 -08002125};
2126
2127static int smb2_get_irq_index_byname(const char *irq_name)
2128{
2129 int i;
2130
2131 for (i = 0; i < ARRAY_SIZE(smb2_irqs); i++) {
2132 if (strcmp(smb2_irqs[i].name, irq_name) == 0)
2133 return i;
2134 }
2135
2136 return -ENOENT;
2137}
2138
2139static int smb2_request_interrupt(struct smb2 *chip,
2140 struct device_node *node, const char *irq_name)
2141{
2142 struct smb_charger *chg = &chip->chg;
2143 int rc, irq, irq_index;
2144 struct smb_irq_data *irq_data;
2145
2146 irq = of_irq_get_byname(node, irq_name);
2147 if (irq < 0) {
2148 pr_err("Couldn't get irq %s byname\n", irq_name);
2149 return irq;
2150 }
2151
2152 irq_index = smb2_get_irq_index_byname(irq_name);
2153 if (irq_index < 0) {
2154 pr_err("%s is not a defined irq\n", irq_name);
2155 return irq_index;
2156 }
2157
Harry Yang03bc73b2016-06-23 17:37:21 -07002158 if (!smb2_irqs[irq_index].handler)
2159 return 0;
2160
Nicholas Troast96886052016-02-25 15:42:17 -08002161 irq_data = devm_kzalloc(chg->dev, sizeof(*irq_data), GFP_KERNEL);
2162 if (!irq_data)
2163 return -ENOMEM;
2164
2165 irq_data->parent_data = chip;
2166 irq_data->name = irq_name;
Nicholas Troast47ae4612016-08-03 09:49:36 -07002167 irq_data->storm_data = smb2_irqs[irq_index].storm_data;
Subbaraman Narayanamurthyaa414372017-02-06 16:04:32 -08002168 mutex_init(&irq_data->storm_data.storm_lock);
Nicholas Troast96886052016-02-25 15:42:17 -08002169
2170 rc = devm_request_threaded_irq(chg->dev, irq, NULL,
2171 smb2_irqs[irq_index].handler,
2172 IRQF_ONESHOT, irq_name, irq_data);
2173 if (rc < 0) {
2174 pr_err("Couldn't request irq %d\n", irq);
2175 return rc;
2176 }
2177
Nicholas Troast1ff4dc62016-06-16 12:28:39 -07002178 smb2_irqs[irq_index].irq = irq;
Subbaraman Narayanamurthybbd7f452017-02-06 16:22:48 -08002179 smb2_irqs[irq_index].irq_data = irq_data;
Nicholas Troast1ff4dc62016-06-16 12:28:39 -07002180 if (smb2_irqs[irq_index].wake)
2181 enable_irq_wake(irq);
2182
Nicholas Troast96886052016-02-25 15:42:17 -08002183 return rc;
2184}
2185
2186static int smb2_request_interrupts(struct smb2 *chip)
2187{
2188 struct smb_charger *chg = &chip->chg;
2189 struct device_node *node = chg->dev->of_node;
2190 struct device_node *child;
2191 int rc = 0;
2192 const char *name;
2193 struct property *prop;
2194
2195 for_each_available_child_of_node(node, child) {
2196 of_property_for_each_string(child, "interrupt-names",
2197 prop, name) {
2198 rc = smb2_request_interrupt(chip, child, name);
2199 if (rc < 0)
2200 return rc;
2201 }
2202 }
2203
2204 return rc;
2205}
2206
Ashay Jaiswald1918f62017-04-27 17:16:26 +05302207static void smb2_free_interrupts(struct smb_charger *chg)
2208{
2209 int i;
2210
2211 for (i = 0; i < ARRAY_SIZE(smb2_irqs); i++) {
2212 if (smb2_irqs[i].irq > 0) {
2213 if (smb2_irqs[i].wake)
2214 disable_irq_wake(smb2_irqs[i].irq);
2215
2216 devm_free_irq(chg->dev, smb2_irqs[i].irq,
2217 smb2_irqs[i].irq_data);
2218 }
2219 }
2220}
2221
Ashay Jaiswal21ae1572017-04-13 15:29:18 +05302222static void smb2_disable_interrupts(struct smb_charger *chg)
2223{
2224 int i;
2225
2226 for (i = 0; i < ARRAY_SIZE(smb2_irqs); i++) {
2227 if (smb2_irqs[i].irq > 0)
2228 disable_irq(smb2_irqs[i].irq);
2229 }
2230}
2231
Nicholas Troastfd6729f2016-09-21 17:51:00 -07002232#if defined(CONFIG_DEBUG_FS)
2233
2234static int force_batt_psy_update_write(void *data, u64 val)
2235{
2236 struct smb_charger *chg = data;
2237
2238 power_supply_changed(chg->batt_psy);
2239 return 0;
2240}
2241DEFINE_SIMPLE_ATTRIBUTE(force_batt_psy_update_ops, NULL,
2242 force_batt_psy_update_write, "0x%02llx\n");
2243
2244static int force_usb_psy_update_write(void *data, u64 val)
2245{
2246 struct smb_charger *chg = data;
2247
2248 power_supply_changed(chg->usb_psy);
2249 return 0;
2250}
2251DEFINE_SIMPLE_ATTRIBUTE(force_usb_psy_update_ops, NULL,
2252 force_usb_psy_update_write, "0x%02llx\n");
2253
2254static int force_dc_psy_update_write(void *data, u64 val)
2255{
2256 struct smb_charger *chg = data;
2257
2258 power_supply_changed(chg->dc_psy);
2259 return 0;
2260}
2261DEFINE_SIMPLE_ATTRIBUTE(force_dc_psy_update_ops, NULL,
2262 force_dc_psy_update_write, "0x%02llx\n");
2263
2264static void smb2_create_debugfs(struct smb2 *chip)
2265{
2266 struct dentry *file;
2267
2268 chip->dfs_root = debugfs_create_dir("charger", NULL);
2269 if (IS_ERR_OR_NULL(chip->dfs_root)) {
2270 pr_err("Couldn't create charger debugfs rc=%ld\n",
2271 (long)chip->dfs_root);
2272 return;
2273 }
2274
2275 file = debugfs_create_file("force_batt_psy_update", 0600,
2276 chip->dfs_root, chip, &force_batt_psy_update_ops);
2277 if (IS_ERR_OR_NULL(file))
2278 pr_err("Couldn't create force_batt_psy_update file rc=%ld\n",
2279 (long)file);
2280
2281 file = debugfs_create_file("force_usb_psy_update", 0600,
2282 chip->dfs_root, chip, &force_usb_psy_update_ops);
2283 if (IS_ERR_OR_NULL(file))
2284 pr_err("Couldn't create force_usb_psy_update file rc=%ld\n",
2285 (long)file);
2286
2287 file = debugfs_create_file("force_dc_psy_update", 0600,
2288 chip->dfs_root, chip, &force_dc_psy_update_ops);
2289 if (IS_ERR_OR_NULL(file))
2290 pr_err("Couldn't create force_dc_psy_update file rc=%ld\n",
2291 (long)file);
2292}
2293
2294#else
2295
2296static void smb2_create_debugfs(struct smb2 *chip)
2297{}
2298
2299#endif
Nicholas Troast96886052016-02-25 15:42:17 -08002300
2301static int smb2_probe(struct platform_device *pdev)
2302{
2303 struct smb2 *chip;
2304 struct smb_charger *chg;
2305 int rc = 0;
Abhijeet Dharmapurikar9dd61292017-01-25 16:40:08 -08002306 union power_supply_propval val;
2307 int usb_present, batt_present, batt_health, batt_charge_type;
Nicholas Troast96886052016-02-25 15:42:17 -08002308
2309 chip = devm_kzalloc(&pdev->dev, sizeof(*chip), GFP_KERNEL);
2310 if (!chip)
2311 return -ENOMEM;
2312
2313 chg = &chip->chg;
2314 chg->dev = &pdev->dev;
2315 chg->param = v1_params;
2316 chg->debug_mask = &__debug_mask;
Ashay Jaiswal2f3b0c12017-06-14 16:04:45 +05302317 chg->weak_chg_icl_ua = &__weak_chg_icl_ua;
Harry Yang1d1034c2016-06-15 12:09:42 -07002318 chg->mode = PARALLEL_MASTER;
Subbaraman Narayanamurthybbd7f452017-02-06 16:22:48 -08002319 chg->irq_info = smb2_irqs;
Abhijeet Dharmapurikar31b98f32016-10-14 12:25:23 -07002320 chg->name = "PMI";
Nicholas Troast96886052016-02-25 15:42:17 -08002321
2322 chg->regmap = dev_get_regmap(chg->dev->parent, NULL);
2323 if (!chg->regmap) {
2324 pr_err("parent regmap is missing\n");
2325 return -EINVAL;
2326 }
2327
Anirudh Ghayal4da3df92017-01-25 18:55:57 +05302328 rc = smb2_chg_config_init(chip);
Harry Yangf7251982016-09-16 11:14:49 -07002329 if (rc < 0) {
2330 if (rc != -EPROBE_DEFER)
Anirudh Ghayal4da3df92017-01-25 18:55:57 +05302331 pr_err("Couldn't setup chg_config rc=%d\n", rc);
Harry Yangf7251982016-09-16 11:14:49 -07002332 return rc;
2333 }
2334
Harry Yangba874ce2016-08-19 14:17:01 -07002335 rc = smblib_init(chg);
2336 if (rc < 0) {
2337 pr_err("Smblib_init failed rc=%d\n", rc);
2338 goto cleanup;
2339 }
Nicholas Troast96886052016-02-25 15:42:17 -08002340
2341 rc = smb2_parse_dt(chip);
2342 if (rc < 0) {
2343 pr_err("Couldn't parse device tree rc=%d\n", rc);
2344 goto cleanup;
2345 }
2346
2347 /* set driver data before resources request it */
2348 platform_set_drvdata(pdev, chip);
2349
2350 rc = smb2_init_vbus_regulator(chip);
2351 if (rc < 0) {
2352 pr_err("Couldn't initialize vbus regulator rc=%d\n",
2353 rc);
2354 goto cleanup;
2355 }
2356
2357 rc = smb2_init_vconn_regulator(chip);
2358 if (rc < 0) {
2359 pr_err("Couldn't initialize vconn regulator rc=%d\n",
Ashay Jaiswal15edce42017-03-31 23:29:58 +05302360 rc);
Nicholas Troast96886052016-02-25 15:42:17 -08002361 goto cleanup;
2362 }
2363
Ashay Jaiswal4aa2c0c2016-12-07 19:39:38 +05302364 /* extcon registration */
2365 chg->extcon = devm_extcon_dev_allocate(chg->dev, smblib_extcon_cable);
2366 if (IS_ERR(chg->extcon)) {
2367 rc = PTR_ERR(chg->extcon);
2368 dev_err(chg->dev, "failed to allocate extcon device rc=%d\n",
2369 rc);
2370 goto cleanup;
2371 }
2372
2373 rc = devm_extcon_dev_register(chg->dev, chg->extcon);
2374 if (rc < 0) {
2375 dev_err(chg->dev, "failed to register extcon device rc=%d\n",
2376 rc);
2377 goto cleanup;
2378 }
2379
Harry Yang752ecc12016-12-14 16:02:47 -08002380 rc = smb2_init_hw(chip);
2381 if (rc < 0) {
2382 pr_err("Couldn't initialize hardware rc=%d\n", rc);
2383 goto cleanup;
2384 }
2385
Harry Yangf3023592016-07-20 14:56:41 -07002386 rc = smb2_init_dc_psy(chip);
2387 if (rc < 0) {
2388 pr_err("Couldn't initialize dc psy rc=%d\n", rc);
2389 goto cleanup;
2390 }
2391
Nicholas Troast96886052016-02-25 15:42:17 -08002392 rc = smb2_init_usb_psy(chip);
2393 if (rc < 0) {
2394 pr_err("Couldn't initialize usb psy rc=%d\n", rc);
2395 goto cleanup;
2396 }
2397
Abhijeet Dharmapurikara8bd6f02017-01-30 15:43:04 -08002398 rc = smb2_init_usb_main_psy(chip);
Nicholas Troast96886052016-02-25 15:42:17 -08002399 if (rc < 0) {
Fenglin Wu80826e02017-04-25 21:45:08 +08002400 pr_err("Couldn't initialize usb main psy rc=%d\n", rc);
2401 goto cleanup;
2402 }
2403
2404 rc = smb2_init_usb_port_psy(chip);
2405 if (rc < 0) {
2406 pr_err("Couldn't initialize usb pc_port psy rc=%d\n", rc);
Abhijeet Dharmapurikara8bd6f02017-01-30 15:43:04 -08002407 goto cleanup;
Nicholas Troast96886052016-02-25 15:42:17 -08002408 }
2409
Nicholas Troast96886052016-02-25 15:42:17 -08002410 rc = smb2_init_batt_psy(chip);
2411 if (rc < 0) {
2412 pr_err("Couldn't initialize batt psy rc=%d\n", rc);
2413 goto cleanup;
2414 }
2415
Nicholas Troast96886052016-02-25 15:42:17 -08002416 rc = smb2_determine_initial_status(chip);
2417 if (rc < 0) {
2418 pr_err("Couldn't determine initial status rc=%d\n",
2419 rc);
2420 goto cleanup;
2421 }
2422
2423 rc = smb2_request_interrupts(chip);
2424 if (rc < 0) {
2425 pr_err("Couldn't request interrupts rc=%d\n", rc);
2426 goto cleanup;
2427 }
2428
Ashay Jaiswal1d046d912017-06-21 14:11:41 +05302429 rc = smb2_post_init(chip);
2430 if (rc < 0) {
2431 pr_err("Failed in post init rc=%d\n", rc);
2432 goto cleanup;
2433 }
Harry Yang4bf7d962017-03-13 16:51:43 -07002434
Nicholas Troastfd6729f2016-09-21 17:51:00 -07002435 smb2_create_debugfs(chip);
2436
Abhijeet Dharmapurikar9dd61292017-01-25 16:40:08 -08002437 rc = smblib_get_prop_usb_present(chg, &val);
2438 if (rc < 0) {
2439 pr_err("Couldn't get usb present rc=%d\n", rc);
2440 goto cleanup;
2441 }
2442 usb_present = val.intval;
2443
2444 rc = smblib_get_prop_batt_present(chg, &val);
2445 if (rc < 0) {
2446 pr_err("Couldn't get batt present rc=%d\n", rc);
2447 goto cleanup;
2448 }
2449 batt_present = val.intval;
2450
2451 rc = smblib_get_prop_batt_health(chg, &val);
2452 if (rc < 0) {
2453 pr_err("Couldn't get batt health rc=%d\n", rc);
Ashay Jaiswal9d808772017-04-10 11:36:30 +05302454 val.intval = POWER_SUPPLY_HEALTH_UNKNOWN;
Abhijeet Dharmapurikar9dd61292017-01-25 16:40:08 -08002455 }
2456 batt_health = val.intval;
2457
2458 rc = smblib_get_prop_batt_charge_type(chg, &val);
2459 if (rc < 0) {
2460 pr_err("Couldn't get batt charge type rc=%d\n", rc);
2461 goto cleanup;
2462 }
2463 batt_charge_type = val.intval;
2464
Ashay Jaiswalc0361672017-03-21 12:24:16 +05302465 device_init_wakeup(chg->dev, true);
2466
Abhijeet Dharmapurikar9dd61292017-01-25 16:40:08 -08002467 pr_info("QPNP SMB2 probed successfully usb:present=%d type=%d batt:present = %d health = %d charge = %d\n",
Fenglin Wu80826e02017-04-25 21:45:08 +08002468 usb_present, chg->real_charger_type,
Abhijeet Dharmapurikar9dd61292017-01-25 16:40:08 -08002469 batt_present, batt_health, batt_charge_type);
Nicholas Troast96886052016-02-25 15:42:17 -08002470 return rc;
2471
2472cleanup:
Ashay Jaiswald1918f62017-04-27 17:16:26 +05302473 smb2_free_interrupts(chg);
Nicholas Troast96886052016-02-25 15:42:17 -08002474 if (chg->batt_psy)
2475 power_supply_unregister(chg->batt_psy);
Ashay Jaiswald1918f62017-04-27 17:16:26 +05302476 if (chg->usb_main_psy)
2477 power_supply_unregister(chg->usb_main_psy);
2478 if (chg->usb_psy)
2479 power_supply_unregister(chg->usb_psy);
Fenglin Wu80826e02017-04-25 21:45:08 +08002480 if (chg->usb_port_psy)
2481 power_supply_unregister(chg->usb_port_psy);
Ashay Jaiswald1918f62017-04-27 17:16:26 +05302482 if (chg->dc_psy)
2483 power_supply_unregister(chg->dc_psy);
Nicholas Troast96886052016-02-25 15:42:17 -08002484 if (chg->vconn_vreg && chg->vconn_vreg->rdev)
Ashay Jaiswald1918f62017-04-27 17:16:26 +05302485 devm_regulator_unregister(chg->dev, chg->vconn_vreg->rdev);
Nicholas Troast96886052016-02-25 15:42:17 -08002486 if (chg->vbus_vreg && chg->vbus_vreg->rdev)
Ashay Jaiswald1918f62017-04-27 17:16:26 +05302487 devm_regulator_unregister(chg->dev, chg->vbus_vreg->rdev);
2488
2489 smblib_deinit(chg);
2490
Nicholas Troast96886052016-02-25 15:42:17 -08002491 platform_set_drvdata(pdev, NULL);
2492 return rc;
2493}
2494
2495static int smb2_remove(struct platform_device *pdev)
2496{
2497 struct smb2 *chip = platform_get_drvdata(pdev);
2498 struct smb_charger *chg = &chip->chg;
2499
2500 power_supply_unregister(chg->batt_psy);
2501 power_supply_unregister(chg->usb_psy);
Fenglin Wu80826e02017-04-25 21:45:08 +08002502 power_supply_unregister(chg->usb_port_psy);
Nicholas Troast96886052016-02-25 15:42:17 -08002503 regulator_unregister(chg->vconn_vreg->rdev);
2504 regulator_unregister(chg->vbus_vreg->rdev);
2505
2506 platform_set_drvdata(pdev, NULL);
2507 return 0;
2508}
2509
Nicholas Troasta0116842016-10-28 11:02:03 -07002510static void smb2_shutdown(struct platform_device *pdev)
2511{
2512 struct smb2 *chip = platform_get_drvdata(pdev);
2513 struct smb_charger *chg = &chip->chg;
2514
Ashay Jaiswal21ae1572017-04-13 15:29:18 +05302515 /* disable all interrupts */
2516 smb2_disable_interrupts(chg);
2517
Nicholas Troast0d7812c2016-11-21 16:36:05 -08002518 /* configure power role for UFP */
2519 smblib_masked_write(chg, TYPE_C_INTRPT_ENB_SOFTWARE_CTRL_REG,
2520 TYPEC_POWER_ROLE_CMD_MASK, UFP_EN_CMD_BIT);
2521
2522 /* force HVDCP to 5V */
Nicholas Troasta0116842016-10-28 11:02:03 -07002523 smblib_masked_write(chg, USBIN_OPTIONS_1_CFG_REG,
Nicholas Troast0d7812c2016-11-21 16:36:05 -08002524 HVDCP_AUTONOMOUS_MODE_EN_CFG_BIT, 0);
Nicholas Troasta0116842016-10-28 11:02:03 -07002525 smblib_write(chg, CMD_HVDCP_2_REG, FORCE_5V_BIT);
Abhijeet Dharmapurikar9dd61292017-01-25 16:40:08 -08002526
2527 /* force enable APSD */
2528 smblib_masked_write(chg, USBIN_OPTIONS_1_CFG_REG,
2529 AUTO_SRC_DETECT_BIT, AUTO_SRC_DETECT_BIT);
Nicholas Troasta0116842016-10-28 11:02:03 -07002530}
2531
Nicholas Troast96886052016-02-25 15:42:17 -08002532static const struct of_device_id match_table[] = {
2533 { .compatible = "qcom,qpnp-smb2", },
2534 { },
2535};
2536
2537static struct platform_driver smb2_driver = {
2538 .driver = {
2539 .name = "qcom,qpnp-smb2",
2540 .owner = THIS_MODULE,
2541 .of_match_table = match_table,
2542 },
2543 .probe = smb2_probe,
2544 .remove = smb2_remove,
Nicholas Troasta0116842016-10-28 11:02:03 -07002545 .shutdown = smb2_shutdown,
Nicholas Troast96886052016-02-25 15:42:17 -08002546};
2547module_platform_driver(smb2_driver);
2548
2549MODULE_DESCRIPTION("QPNP SMB2 Charger Driver");
2550MODULE_LICENSE("GPL v2");