blob: 72f961b37e72b63520245150d12d80c4549e9965 [file] [log] [blame]
Nicholas Troast96886052016-02-25 15:42:17 -08001/* Copyright (c) 2016 The Linux Foundation. All rights reserved.
2 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 */
12
Nicholas Troastfd6729f2016-09-21 17:51:00 -070013#include <linux/debugfs.h>
Nicholas Troast96886052016-02-25 15:42:17 -080014#include <linux/device.h>
15#include <linux/module.h>
16#include <linux/platform_device.h>
17#include <linux/regmap.h>
18#include <linux/power_supply.h>
19#include <linux/interrupt.h>
20#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"
Nicholas Troast96886052016-02-25 15:42:17 -080029#include "pmic-voter.h"
30
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 },
Nicholas Troast96886052016-02-25 15:42:17 -0800213};
214
Harry Yangfe913842016-08-10 12:27:28 -0700215#define STEP_CHARGING_MAX_STEPS 5
Nicholas Troast96886052016-02-25 15:42:17 -0800216struct smb_dt_props {
Nicholas Troast2ebe6c52016-09-20 13:25:59 -0700217 bool no_battery;
Abhijeet Dharmapurikar5cf5faf2016-06-21 14:20:24 -0700218 int fcc_ua;
219 int usb_icl_ua;
Harry Yang360bd532016-09-26 11:03:22 -0700220 int otg_cl_ua;
Abhijeet Dharmapurikar5cf5faf2016-06-21 14:20:24 -0700221 int dc_icl_ua;
222 int fv_uv;
223 int wipower_max_uw;
Harry Yangfe913842016-08-10 12:27:28 -0700224 u32 step_soc_threshold[STEP_CHARGING_MAX_STEPS - 1];
225 s32 step_cc_delta[STEP_CHARGING_MAX_STEPS];
Harry Yangf7251982016-09-16 11:14:49 -0700226 struct device_node *revid_dev_node;
Nicholas Troast597acfe2016-07-20 16:03:15 -0700227 int float_option;
Abhijeet Dharmapurikarf0b0a042016-10-10 16:43:43 -0700228 bool hvdcp_disable;
Nicholas Troast96886052016-02-25 15:42:17 -0800229};
230
231struct smb2 {
Nicholas Troastfd6729f2016-09-21 17:51:00 -0700232 struct smb_charger chg;
233 struct dentry *dfs_root;
234 struct smb_dt_props dt;
235 bool bad_part;
Nicholas Troast96886052016-02-25 15:42:17 -0800236};
237
238static int __debug_mask;
239module_param_named(
240 debug_mask, __debug_mask, int, 0600
241);
242
Harry Yang360bd532016-09-26 11:03:22 -0700243#define MICRO_1P5A 1500000
Nicholas Troast96886052016-02-25 15:42:17 -0800244static int smb2_parse_dt(struct smb2 *chip)
245{
246 struct smb_charger *chg = &chip->chg;
247 struct device_node *node = chg->dev->of_node;
Abhijeet Dharmapurikar99fb8942016-07-08 11:39:23 -0700248 int rc, byte_len;
Nicholas Troast96886052016-02-25 15:42:17 -0800249
250 if (!node) {
251 pr_err("device tree node missing\n");
252 return -EINVAL;
253 }
254
Harry Yangfe913842016-08-10 12:27:28 -0700255 chg->step_chg_enabled = true;
256
257 if (of_property_count_u32_elems(node, "qcom,step-soc-thresholds")
258 != STEP_CHARGING_MAX_STEPS - 1)
259 chg->step_chg_enabled = false;
260
261 rc = of_property_read_u32_array(node, "qcom,step-soc-thresholds",
262 chip->dt.step_soc_threshold,
263 STEP_CHARGING_MAX_STEPS - 1);
264 if (rc < 0)
265 chg->step_chg_enabled = false;
266
267 if (of_property_count_u32_elems(node, "qcom,step-current-deltas")
268 != STEP_CHARGING_MAX_STEPS)
269 chg->step_chg_enabled = false;
270
271 rc = of_property_read_u32_array(node, "qcom,step-current-deltas",
272 chip->dt.step_cc_delta,
273 STEP_CHARGING_MAX_STEPS);
274 if (rc < 0)
275 chg->step_chg_enabled = false;
276
Nicholas Troast2ebe6c52016-09-20 13:25:59 -0700277 chip->dt.no_battery = of_property_read_bool(node,
278 "qcom,batteryless-platform");
Nicholas Troast96886052016-02-25 15:42:17 -0800279
280 rc = of_property_read_u32(node,
281 "qcom,fcc-max-ua", &chip->dt.fcc_ua);
282 if (rc < 0)
Nicholas Troast4f2d7962016-07-27 11:08:10 -0700283 chip->dt.fcc_ua = -EINVAL;
Nicholas Troast96886052016-02-25 15:42:17 -0800284
285 rc = of_property_read_u32(node,
Abhijeet Dharmapurikarf9805d42016-05-17 18:38:42 -0700286 "qcom,fv-max-uv", &chip->dt.fv_uv);
287 if (rc < 0)
Nicholas Troast4f2d7962016-07-27 11:08:10 -0700288 chip->dt.fv_uv = -EINVAL;
Abhijeet Dharmapurikarf9805d42016-05-17 18:38:42 -0700289
290 rc = of_property_read_u32(node,
Nicholas Troast96886052016-02-25 15:42:17 -0800291 "qcom,usb-icl-ua", &chip->dt.usb_icl_ua);
292 if (rc < 0)
Nicholas Troast4f2d7962016-07-27 11:08:10 -0700293 chip->dt.usb_icl_ua = -EINVAL;
Nicholas Troast96886052016-02-25 15:42:17 -0800294
295 rc = of_property_read_u32(node,
Harry Yang360bd532016-09-26 11:03:22 -0700296 "qcom,otg-cl-ua", &chip->dt.otg_cl_ua);
297 if (rc < 0)
298 chip->dt.otg_cl_ua = MICRO_1P5A;
299
300 rc = of_property_read_u32(node,
Nicholas Troast96886052016-02-25 15:42:17 -0800301 "qcom,dc-icl-ua", &chip->dt.dc_icl_ua);
302 if (rc < 0)
Nicholas Troast4f2d7962016-07-27 11:08:10 -0700303 chip->dt.dc_icl_ua = -EINVAL;
Nicholas Troast96886052016-02-25 15:42:17 -0800304
Vic Wei373e0272016-08-11 01:39:11 -0700305 rc = of_property_read_u32(node, "qcom,wipower-max-uw",
306 &chip->dt.wipower_max_uw);
Abhijeet Dharmapurikar5cf5faf2016-06-21 14:20:24 -0700307 if (rc < 0)
Vic Wei373e0272016-08-11 01:39:11 -0700308 chip->dt.wipower_max_uw = -EINVAL;
Abhijeet Dharmapurikar5cf5faf2016-06-21 14:20:24 -0700309
Abhijeet Dharmapurikar99fb8942016-07-08 11:39:23 -0700310 if (of_find_property(node, "qcom,thermal-mitigation", &byte_len)) {
311 chg->thermal_mitigation = devm_kzalloc(chg->dev, byte_len,
312 GFP_KERNEL);
313
314 if (chg->thermal_mitigation == NULL)
315 return -ENOMEM;
316
317 chg->thermal_levels = byte_len / sizeof(u32);
318 rc = of_property_read_u32_array(node,
319 "qcom,thermal-mitigation",
320 chg->thermal_mitigation,
321 chg->thermal_levels);
322 if (rc < 0) {
323 dev_err(chg->dev,
324 "Couldn't read threm limits rc = %d\n", rc);
325 return rc;
326 }
327 }
328
Nicholas Troast597acfe2016-07-20 16:03:15 -0700329 of_property_read_u32(node, "qcom,float-option", &chip->dt.float_option);
330 if (chip->dt.float_option < 0 || chip->dt.float_option > 4) {
331 pr_err("qcom,float-option is out of range [0, 4]\n");
332 return -EINVAL;
333 }
334
Abhijeet Dharmapurikarf0b0a042016-10-10 16:43:43 -0700335 chip->dt.hvdcp_disable = of_property_read_bool(node,
336 "qcom,hvdcp-disable");
337
Nicholas Troast96886052016-02-25 15:42:17 -0800338 return 0;
339}
340
341/************************
342 * USB PSY REGISTRATION *
343 ************************/
344
345static enum power_supply_property smb2_usb_props[] = {
346 POWER_SUPPLY_PROP_PRESENT,
347 POWER_SUPPLY_PROP_ONLINE,
348 POWER_SUPPLY_PROP_VOLTAGE_MIN,
349 POWER_SUPPLY_PROP_VOLTAGE_MAX,
350 POWER_SUPPLY_PROP_VOLTAGE_NOW,
Abhijeet Dharmapurikard92eca62016-10-07 19:04:33 -0700351 POWER_SUPPLY_PROP_PD_CURRENT_MAX,
Nicholas Troast96886052016-02-25 15:42:17 -0800352 POWER_SUPPLY_PROP_CURRENT_MAX,
353 POWER_SUPPLY_PROP_TYPE,
354 POWER_SUPPLY_PROP_TYPEC_MODE,
355 POWER_SUPPLY_PROP_TYPEC_POWER_ROLE,
356 POWER_SUPPLY_PROP_TYPEC_CC_ORIENTATION,
357 POWER_SUPPLY_PROP_PD_ALLOWED,
358 POWER_SUPPLY_PROP_PD_ACTIVE,
Nicholas Troast133a7f52016-06-29 13:48:20 -0700359 POWER_SUPPLY_PROP_INPUT_CURRENT_SETTLED,
Harry Yangba874ce2016-08-19 14:17:01 -0700360 POWER_SUPPLY_PROP_INPUT_CURRENT_NOW,
Abhijeet Dharmapurikarb9598872016-10-17 16:58:58 -0700361 POWER_SUPPLY_PROP_PE_START,
Nicholas Troast96886052016-02-25 15:42:17 -0800362};
363
364static int smb2_usb_get_prop(struct power_supply *psy,
365 enum power_supply_property psp,
366 union power_supply_propval *val)
367{
368 struct smb2 *chip = power_supply_get_drvdata(psy);
369 struct smb_charger *chg = &chip->chg;
370 int rc = 0;
371
372 switch (psp) {
373 case POWER_SUPPLY_PROP_PRESENT:
374 if (chip->bad_part)
375 val->intval = 1;
376 else
377 rc = smblib_get_prop_usb_present(chg, val);
378 break;
379 case POWER_SUPPLY_PROP_ONLINE:
380 rc = smblib_get_prop_usb_online(chg, val);
381 break;
382 case POWER_SUPPLY_PROP_VOLTAGE_MIN:
383 val->intval = chg->voltage_min_uv;
384 break;
385 case POWER_SUPPLY_PROP_VOLTAGE_MAX:
386 val->intval = chg->voltage_max_uv;
387 break;
388 case POWER_SUPPLY_PROP_VOLTAGE_NOW:
389 rc = smblib_get_prop_usb_voltage_now(chg, val);
390 break;
Abhijeet Dharmapurikard92eca62016-10-07 19:04:33 -0700391 case POWER_SUPPLY_PROP_PD_CURRENT_MAX:
392 rc = smblib_get_prop_pd_current_max(chg, val);
393 break;
Nicholas Troast96886052016-02-25 15:42:17 -0800394 case POWER_SUPPLY_PROP_CURRENT_MAX:
395 rc = smblib_get_prop_usb_current_max(chg, val);
396 break;
397 case POWER_SUPPLY_PROP_TYPE:
398 if (chip->bad_part)
399 val->intval = POWER_SUPPLY_TYPE_USB;
400 else
401 val->intval = chg->usb_psy_desc.type;
402 break;
403 case POWER_SUPPLY_PROP_TYPEC_MODE:
404 if (chip->bad_part)
405 val->intval = POWER_SUPPLY_TYPEC_SOURCE_DEFAULT;
406 else
407 rc = smblib_get_prop_typec_mode(chg, val);
408 break;
409 case POWER_SUPPLY_PROP_TYPEC_POWER_ROLE:
410 rc = smblib_get_prop_typec_power_role(chg, val);
411 break;
412 case POWER_SUPPLY_PROP_TYPEC_CC_ORIENTATION:
413 rc = smblib_get_prop_typec_cc_orientation(chg, val);
414 break;
415 case POWER_SUPPLY_PROP_PD_ALLOWED:
416 rc = smblib_get_prop_pd_allowed(chg, val);
417 break;
418 case POWER_SUPPLY_PROP_PD_ACTIVE:
419 val->intval = chg->pd_active;
420 break;
Nicholas Troast133a7f52016-06-29 13:48:20 -0700421 case POWER_SUPPLY_PROP_INPUT_CURRENT_SETTLED:
422 rc = smblib_get_prop_input_current_settled(chg, val);
423 break;
Harry Yangba874ce2016-08-19 14:17:01 -0700424 case POWER_SUPPLY_PROP_INPUT_CURRENT_NOW:
425 rc = smblib_get_prop_usb_current_now(chg, val);
426 break;
Abhijeet Dharmapurikarf8a7a4a2016-10-07 18:46:45 -0700427 case POWER_SUPPLY_PROP_PD_IN_HARD_RESET:
428 rc = smblib_get_prop_pd_in_hard_reset(chg, val);
429 break;
Abhijeet Dharmapurikard92eca62016-10-07 19:04:33 -0700430 case POWER_SUPPLY_PROP_PD_USB_SUSPEND_SUPPORTED:
431 val->intval = chg->system_suspend_supported;
432 break;
Abhijeet Dharmapurikarb9598872016-10-17 16:58:58 -0700433 case POWER_SUPPLY_PROP_PE_START:
434 rc = smblib_get_pe_start(chg, val);
435 break;
Nicholas Troast96886052016-02-25 15:42:17 -0800436 default:
437 pr_err("get prop %d is not supported\n", psp);
438 rc = -EINVAL;
439 break;
440 }
Abhijeet Dharmapurikar773d4ab2016-09-09 12:00:19 -0700441 if (rc < 0) {
442 pr_debug("Couldn't get prop %d rc = %d\n", psp, rc);
443 return -ENODATA;
444 }
445 return 0;
Nicholas Troast96886052016-02-25 15:42:17 -0800446}
447
448static int smb2_usb_set_prop(struct power_supply *psy,
449 enum power_supply_property psp,
450 const union power_supply_propval *val)
451{
452 struct smb2 *chip = power_supply_get_drvdata(psy);
453 struct smb_charger *chg = &chip->chg;
454 int rc = 0;
455
456 switch (psp) {
457 case POWER_SUPPLY_PROP_VOLTAGE_MIN:
458 rc = smblib_set_prop_usb_voltage_min(chg, val);
459 break;
460 case POWER_SUPPLY_PROP_VOLTAGE_MAX:
461 rc = smblib_set_prop_usb_voltage_max(chg, val);
462 break;
Abhijeet Dharmapurikard92eca62016-10-07 19:04:33 -0700463 case POWER_SUPPLY_PROP_PD_CURRENT_MAX:
464 rc = smblib_set_prop_pd_current_max(chg, val);
465 break;
Nicholas Troast96886052016-02-25 15:42:17 -0800466 case POWER_SUPPLY_PROP_CURRENT_MAX:
467 rc = smblib_set_prop_usb_current_max(chg, val);
468 break;
469 case POWER_SUPPLY_PROP_TYPEC_POWER_ROLE:
470 rc = smblib_set_prop_typec_power_role(chg, val);
471 break;
472 case POWER_SUPPLY_PROP_PD_ACTIVE:
473 rc = smblib_set_prop_pd_active(chg, val);
474 break;
Abhijeet Dharmapurikarf8a7a4a2016-10-07 18:46:45 -0700475 case POWER_SUPPLY_PROP_PD_IN_HARD_RESET:
476 rc = smblib_set_prop_pd_in_hard_reset(chg, val);
477 break;
Abhijeet Dharmapurikard92eca62016-10-07 19:04:33 -0700478 case POWER_SUPPLY_PROP_PD_USB_SUSPEND_SUPPORTED:
479 chg->system_suspend_supported = val->intval;
480 break;
Nicholas Troast96886052016-02-25 15:42:17 -0800481 default:
482 pr_err("set prop %d is not supported\n", psp);
483 rc = -EINVAL;
484 break;
485 }
486
487 return rc;
488}
489
490static int smb2_usb_prop_is_writeable(struct power_supply *psy,
491 enum power_supply_property psp)
492{
493 switch (psp) {
494 case POWER_SUPPLY_PROP_TYPEC_POWER_ROLE:
495 return 1;
496 default:
497 break;
498 }
499
500 return 0;
501}
502
503static int smb2_init_usb_psy(struct smb2 *chip)
504{
505 struct power_supply_config usb_cfg = {};
506 struct smb_charger *chg = &chip->chg;
507
508 chg->usb_psy_desc.name = "usb";
509 chg->usb_psy_desc.type = POWER_SUPPLY_TYPE_UNKNOWN;
510 chg->usb_psy_desc.properties = smb2_usb_props;
511 chg->usb_psy_desc.num_properties = ARRAY_SIZE(smb2_usb_props);
512 chg->usb_psy_desc.get_property = smb2_usb_get_prop;
513 chg->usb_psy_desc.set_property = smb2_usb_set_prop;
514 chg->usb_psy_desc.property_is_writeable = smb2_usb_prop_is_writeable;
515
516 usb_cfg.drv_data = chip;
517 usb_cfg.of_node = chg->dev->of_node;
518 chg->usb_psy = devm_power_supply_register(chg->dev,
519 &chg->usb_psy_desc,
520 &usb_cfg);
521 if (IS_ERR(chg->usb_psy)) {
522 pr_err("Couldn't register USB power supply\n");
523 return PTR_ERR(chg->usb_psy);
524 }
525
526 return 0;
527}
528
529/*************************
Harry Yangf3023592016-07-20 14:56:41 -0700530 * DC PSY REGISTRATION *
531 *************************/
532
533static enum power_supply_property smb2_dc_props[] = {
534 POWER_SUPPLY_PROP_PRESENT,
535 POWER_SUPPLY_PROP_ONLINE,
536 POWER_SUPPLY_PROP_CURRENT_MAX,
537};
538
539static int smb2_dc_get_prop(struct power_supply *psy,
540 enum power_supply_property psp,
541 union power_supply_propval *val)
542{
543 struct smb2 *chip = power_supply_get_drvdata(psy);
544 struct smb_charger *chg = &chip->chg;
545 int rc = 0;
546
547 switch (psp) {
548 case POWER_SUPPLY_PROP_PRESENT:
549 rc = smblib_get_prop_dc_present(chg, val);
550 break;
551 case POWER_SUPPLY_PROP_ONLINE:
552 rc = smblib_get_prop_dc_online(chg, val);
553 break;
554 case POWER_SUPPLY_PROP_CURRENT_MAX:
555 rc = smblib_get_prop_dc_current_max(chg, val);
556 break;
557 default:
558 return -EINVAL;
559 }
Abhijeet Dharmapurikar773d4ab2016-09-09 12:00:19 -0700560 if (rc < 0) {
561 pr_debug("Couldn't get prop %d rc = %d\n", psp, rc);
562 return -ENODATA;
563 }
564 return 0;
Harry Yangf3023592016-07-20 14:56:41 -0700565}
566
567static int smb2_dc_set_prop(struct power_supply *psy,
568 enum power_supply_property psp,
569 const union power_supply_propval *val)
570{
571 struct smb2 *chip = power_supply_get_drvdata(psy);
572 struct smb_charger *chg = &chip->chg;
573 int rc = 0;
574
575 switch (psp) {
576 case POWER_SUPPLY_PROP_CURRENT_MAX:
577 rc = smblib_set_prop_dc_current_max(chg, val);
578 break;
579 default:
580 return -EINVAL;
581 }
582
583 return rc;
584}
585
586static int smb2_dc_prop_is_writeable(struct power_supply *psy,
587 enum power_supply_property psp)
588{
589 int rc;
590
591 switch (psp) {
592 case POWER_SUPPLY_PROP_CURRENT_MAX:
593 rc = 1;
594 break;
595 default:
596 rc = 0;
597 break;
598 }
599
600 return rc;
601}
602
603static const struct power_supply_desc dc_psy_desc = {
604 .name = "dc",
605 .type = POWER_SUPPLY_TYPE_WIPOWER,
606 .properties = smb2_dc_props,
607 .num_properties = ARRAY_SIZE(smb2_dc_props),
608 .get_property = smb2_dc_get_prop,
609 .set_property = smb2_dc_set_prop,
610 .property_is_writeable = smb2_dc_prop_is_writeable,
611};
612
613static int smb2_init_dc_psy(struct smb2 *chip)
614{
615 struct power_supply_config dc_cfg = {};
616 struct smb_charger *chg = &chip->chg;
617
618 dc_cfg.drv_data = chip;
619 dc_cfg.of_node = chg->dev->of_node;
620 chg->dc_psy = devm_power_supply_register(chg->dev,
621 &dc_psy_desc,
622 &dc_cfg);
623 if (IS_ERR(chg->dc_psy)) {
624 pr_err("Couldn't register USB power supply\n");
625 return PTR_ERR(chg->dc_psy);
626 }
627
628 return 0;
629}
630
631/*************************
Nicholas Troast96886052016-02-25 15:42:17 -0800632 * BATT PSY REGISTRATION *
633 *************************/
634
635static enum power_supply_property smb2_batt_props[] = {
636 POWER_SUPPLY_PROP_INPUT_SUSPEND,
637 POWER_SUPPLY_PROP_STATUS,
638 POWER_SUPPLY_PROP_HEALTH,
639 POWER_SUPPLY_PROP_PRESENT,
640 POWER_SUPPLY_PROP_CHARGE_TYPE,
641 POWER_SUPPLY_PROP_CAPACITY,
Abhijeet Dharmapurikar99fb8942016-07-08 11:39:23 -0700642 POWER_SUPPLY_PROP_SYSTEM_TEMP_LEVEL,
Harry Yangba874ce2016-08-19 14:17:01 -0700643 POWER_SUPPLY_PROP_CHARGER_TEMP,
644 POWER_SUPPLY_PROP_CHARGER_TEMP_MAX,
Abhijeet Dharmapurikar0e369002016-09-07 17:25:36 -0700645 POWER_SUPPLY_PROP_INPUT_CURRENT_LIMITED,
Nicholas Troast66b21d72016-09-20 15:33:20 -0700646 POWER_SUPPLY_PROP_VOLTAGE_NOW,
Harry Yang7e66f892016-10-14 09:31:15 -0700647 POWER_SUPPLY_PROP_VOLTAGE_MAX,
Nicholas Troast66b21d72016-09-20 15:33:20 -0700648 POWER_SUPPLY_PROP_CURRENT_NOW,
Harry Yang7e66f892016-10-14 09:31:15 -0700649 POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX,
Nicholas Troast66b21d72016-09-20 15:33:20 -0700650 POWER_SUPPLY_PROP_TEMP,
651 POWER_SUPPLY_PROP_TECHNOLOGY,
Harry Yangbedee332016-08-31 16:14:29 -0700652 POWER_SUPPLY_PROP_STEP_CHARGING_ENABLED,
653 POWER_SUPPLY_PROP_STEP_CHARGING_STEP,
Subbaraman Narayanamurthy270a2652016-10-04 17:08:42 -0700654 POWER_SUPPLY_PROP_CHARGE_DONE,
Abhijeet Dharmapurikarc0b0f592016-10-14 10:55:42 -0700655 POWER_SUPPLY_PROP_PARALLEL_DISABLE,
Nicholas Troast7fe219d2016-10-11 09:24:56 -0700656 POWER_SUPPLY_PROP_PARALLEL_PERCENT,
Nicholas Troast96886052016-02-25 15:42:17 -0800657};
658
659static int smb2_batt_get_prop(struct power_supply *psy,
660 enum power_supply_property psp,
661 union power_supply_propval *val)
662{
Nicholas Troast66b21d72016-09-20 15:33:20 -0700663 struct smb_charger *chg = power_supply_get_drvdata(psy);
Nicholas Troast2ebe6c52016-09-20 13:25:59 -0700664 int rc = 0;
Nicholas Troast96886052016-02-25 15:42:17 -0800665
666 switch (psp) {
667 case POWER_SUPPLY_PROP_STATUS:
Harry Yangba874ce2016-08-19 14:17:01 -0700668 rc = smblib_get_prop_batt_status(chg, val);
Nicholas Troast96886052016-02-25 15:42:17 -0800669 break;
670 case POWER_SUPPLY_PROP_HEALTH:
Harry Yangba874ce2016-08-19 14:17:01 -0700671 rc = smblib_get_prop_batt_health(chg, val);
Nicholas Troast96886052016-02-25 15:42:17 -0800672 break;
673 case POWER_SUPPLY_PROP_PRESENT:
Harry Yangba874ce2016-08-19 14:17:01 -0700674 rc = smblib_get_prop_batt_present(chg, val);
Nicholas Troast96886052016-02-25 15:42:17 -0800675 break;
676 case POWER_SUPPLY_PROP_INPUT_SUSPEND:
Harry Yangba874ce2016-08-19 14:17:01 -0700677 rc = smblib_get_prop_input_suspend(chg, val);
Nicholas Troast96886052016-02-25 15:42:17 -0800678 break;
679 case POWER_SUPPLY_PROP_CHARGE_TYPE:
Harry Yangba874ce2016-08-19 14:17:01 -0700680 rc = smblib_get_prop_batt_charge_type(chg, val);
Nicholas Troast96886052016-02-25 15:42:17 -0800681 break;
682 case POWER_SUPPLY_PROP_CAPACITY:
Harry Yangba874ce2016-08-19 14:17:01 -0700683 rc = smblib_get_prop_batt_capacity(chg, val);
Nicholas Troast96886052016-02-25 15:42:17 -0800684 break;
Abhijeet Dharmapurikar99fb8942016-07-08 11:39:23 -0700685 case POWER_SUPPLY_PROP_SYSTEM_TEMP_LEVEL:
Harry Yangba874ce2016-08-19 14:17:01 -0700686 rc = smblib_get_prop_system_temp_level(chg, val);
687 break;
688 case POWER_SUPPLY_PROP_CHARGER_TEMP:
689 rc = smblib_get_prop_charger_temp(chg, val);
690 break;
691 case POWER_SUPPLY_PROP_CHARGER_TEMP_MAX:
692 rc = smblib_get_prop_charger_temp_max(chg, val);
Abhijeet Dharmapurikar99fb8942016-07-08 11:39:23 -0700693 break;
Abhijeet Dharmapurikar0e369002016-09-07 17:25:36 -0700694 case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMITED:
695 rc = smblib_get_prop_input_current_limited(chg, val);
Abhijeet Dharmapurikar7ebf63c2016-10-18 10:37:23 -0700696 break;
Harry Yangbedee332016-08-31 16:14:29 -0700697 case POWER_SUPPLY_PROP_STEP_CHARGING_ENABLED:
698 val->intval = chg->step_chg_enabled;
699 break;
700 case POWER_SUPPLY_PROP_STEP_CHARGING_STEP:
701 rc = smblib_get_prop_step_chg_step(chg, val);
Abhijeet Dharmapurikar0e369002016-09-07 17:25:36 -0700702 break;
Nicholas Troast66b21d72016-09-20 15:33:20 -0700703 case POWER_SUPPLY_PROP_VOLTAGE_NOW:
704 rc = smblib_get_prop_batt_voltage_now(chg, val);
705 break;
Harry Yang7e66f892016-10-14 09:31:15 -0700706 case POWER_SUPPLY_PROP_VOLTAGE_MAX:
707 val->intval = get_client_vote(chg->fv_votable, DEFAULT_VOTER);
708 break;
Nicholas Troast66b21d72016-09-20 15:33:20 -0700709 case POWER_SUPPLY_PROP_CURRENT_NOW:
710 rc = smblib_get_prop_batt_current_now(chg, val);
711 break;
Harry Yang7e66f892016-10-14 09:31:15 -0700712 case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX:
713 val->intval = get_client_vote(chg->fcc_max_votable,
714 DEFAULT_VOTER);
715 break;
Nicholas Troast66b21d72016-09-20 15:33:20 -0700716 case POWER_SUPPLY_PROP_TEMP:
717 rc = smblib_get_prop_batt_temp(chg, val);
718 break;
719 case POWER_SUPPLY_PROP_TECHNOLOGY:
720 val->intval = POWER_SUPPLY_TECHNOLOGY_LION;
721 break;
Subbaraman Narayanamurthy270a2652016-10-04 17:08:42 -0700722 case POWER_SUPPLY_PROP_CHARGE_DONE:
Subbaraman Narayanamurthyb491d022016-10-10 20:22:48 -0700723 rc = smblib_get_prop_batt_charge_done(chg, val);
Subbaraman Narayanamurthy270a2652016-10-04 17:08:42 -0700724 break;
Abhijeet Dharmapurikarc0b0f592016-10-14 10:55:42 -0700725 case POWER_SUPPLY_PROP_PARALLEL_DISABLE:
726 val->intval = get_client_vote(chg->pl_disable_votable,
727 USER_VOTER);
728 break;
Nicholas Troast7fe219d2016-10-11 09:24:56 -0700729 case POWER_SUPPLY_PROP_PARALLEL_PERCENT:
730 val->intval = chg->pl.slave_pct;
731 break;
Nicholas Troast96886052016-02-25 15:42:17 -0800732 default:
Abhijeet Dharmapurikar99fb8942016-07-08 11:39:23 -0700733 pr_err("batt power supply prop %d not supported\n", psp);
Nicholas Troast96886052016-02-25 15:42:17 -0800734 return -EINVAL;
735 }
Nicholas Troast66b21d72016-09-20 15:33:20 -0700736
Abhijeet Dharmapurikar773d4ab2016-09-09 12:00:19 -0700737 if (rc < 0) {
738 pr_debug("Couldn't get prop %d rc = %d\n", psp, rc);
739 return -ENODATA;
740 }
Nicholas Troast66b21d72016-09-20 15:33:20 -0700741
Abhijeet Dharmapurikar773d4ab2016-09-09 12:00:19 -0700742 return 0;
Nicholas Troast96886052016-02-25 15:42:17 -0800743}
744
745static int smb2_batt_set_prop(struct power_supply *psy,
746 enum power_supply_property prop,
747 const union power_supply_propval *val)
748{
Abhijeet Dharmapurikar99fb8942016-07-08 11:39:23 -0700749 int rc = 0;
Nicholas Troast96886052016-02-25 15:42:17 -0800750 struct smb_charger *chg = power_supply_get_drvdata(psy);
751
752 switch (prop) {
753 case POWER_SUPPLY_PROP_INPUT_SUSPEND:
Abhijeet Dharmapurikar99fb8942016-07-08 11:39:23 -0700754 rc = smblib_set_prop_input_suspend(chg, val);
755 break;
756 case POWER_SUPPLY_PROP_SYSTEM_TEMP_LEVEL:
757 rc = smblib_set_prop_system_temp_level(chg, val);
Nicholas Troast96886052016-02-25 15:42:17 -0800758 break;
Abhijeet Dharmapurikar9e7e48c2016-08-23 12:55:49 -0700759 case POWER_SUPPLY_PROP_CAPACITY:
760 rc = smblib_set_prop_batt_capacity(chg, val);
761 break;
Abhijeet Dharmapurikarc0b0f592016-10-14 10:55:42 -0700762 case POWER_SUPPLY_PROP_PARALLEL_DISABLE:
763 vote(chg->pl_disable_votable, USER_VOTER, (bool)val->intval, 0);
764 break;
Nicholas Troast7fe219d2016-10-11 09:24:56 -0700765 case POWER_SUPPLY_PROP_PARALLEL_PERCENT:
766 if (val->intval < 0 || val->intval > 100)
767 return -EINVAL;
768 chg->pl.slave_pct = val->intval;
769 rerun_election(chg->fcc_votable);
770 break;
Harry Yang7e66f892016-10-14 09:31:15 -0700771 case POWER_SUPPLY_PROP_VOLTAGE_MAX:
772 vote(chg->fv_votable, DEFAULT_VOTER, true, val->intval);
773 break;
774 case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX:
775 vote(chg->fcc_max_votable, DEFAULT_VOTER, true, val->intval);
776 break;
Nicholas Troast96886052016-02-25 15:42:17 -0800777 default:
Abhijeet Dharmapurikar99fb8942016-07-08 11:39:23 -0700778 rc = -EINVAL;
Nicholas Troast96886052016-02-25 15:42:17 -0800779 }
780
Abhijeet Dharmapurikar99fb8942016-07-08 11:39:23 -0700781 return rc;
Nicholas Troast96886052016-02-25 15:42:17 -0800782}
783
784static int smb2_batt_prop_is_writeable(struct power_supply *psy,
785 enum power_supply_property psp)
786{
787 switch (psp) {
788 case POWER_SUPPLY_PROP_INPUT_SUSPEND:
Abhijeet Dharmapurikar99fb8942016-07-08 11:39:23 -0700789 case POWER_SUPPLY_PROP_SYSTEM_TEMP_LEVEL:
Abhijeet Dharmapurikar9e7e48c2016-08-23 12:55:49 -0700790 case POWER_SUPPLY_PROP_CAPACITY:
Abhijeet Dharmapurikarc0b0f592016-10-14 10:55:42 -0700791 case POWER_SUPPLY_PROP_PARALLEL_DISABLE:
Nicholas Troast7fe219d2016-10-11 09:24:56 -0700792 case POWER_SUPPLY_PROP_PARALLEL_PERCENT:
Nicholas Troast96886052016-02-25 15:42:17 -0800793 return 1;
794 default:
795 break;
796 }
797
798 return 0;
799}
800
801static const struct power_supply_desc batt_psy_desc = {
802 .name = "battery",
803 .type = POWER_SUPPLY_TYPE_BATTERY,
804 .properties = smb2_batt_props,
805 .num_properties = ARRAY_SIZE(smb2_batt_props),
806 .get_property = smb2_batt_get_prop,
807 .set_property = smb2_batt_set_prop,
808 .property_is_writeable = smb2_batt_prop_is_writeable,
809};
810
811static int smb2_init_batt_psy(struct smb2 *chip)
812{
813 struct power_supply_config batt_cfg = {};
814 struct smb_charger *chg = &chip->chg;
815 int rc = 0;
816
817 batt_cfg.drv_data = chg;
818 batt_cfg.of_node = chg->dev->of_node;
819 chg->batt_psy = devm_power_supply_register(chg->dev,
820 &batt_psy_desc,
821 &batt_cfg);
822 if (IS_ERR(chg->batt_psy)) {
823 pr_err("Couldn't register battery power supply\n");
824 return PTR_ERR(chg->batt_psy);
825 }
826
827 return rc;
828}
829
830/******************************
831 * VBUS REGULATOR REGISTRATION *
832 ******************************/
833
834struct regulator_ops smb2_vbus_reg_ops = {
835 .enable = smblib_vbus_regulator_enable,
836 .disable = smblib_vbus_regulator_disable,
837 .is_enabled = smblib_vbus_regulator_is_enabled,
838};
839
840static int smb2_init_vbus_regulator(struct smb2 *chip)
841{
842 struct smb_charger *chg = &chip->chg;
843 struct regulator_config cfg = {};
844 int rc = 0;
845
846 chg->vbus_vreg = devm_kzalloc(chg->dev, sizeof(*chg->vbus_vreg),
847 GFP_KERNEL);
848 if (!chg->vbus_vreg)
849 return -ENOMEM;
850
851 cfg.dev = chg->dev;
852 cfg.driver_data = chip;
853
854 chg->vbus_vreg->rdesc.owner = THIS_MODULE;
855 chg->vbus_vreg->rdesc.type = REGULATOR_VOLTAGE;
856 chg->vbus_vreg->rdesc.ops = &smb2_vbus_reg_ops;
857 chg->vbus_vreg->rdesc.of_match = "qcom,smb2-vbus";
858 chg->vbus_vreg->rdesc.name = "qcom,smb2-vbus";
859
860 chg->vbus_vreg->rdev = devm_regulator_register(chg->dev,
861 &chg->vbus_vreg->rdesc, &cfg);
862 if (IS_ERR(chg->vbus_vreg->rdev)) {
863 rc = PTR_ERR(chg->vbus_vreg->rdev);
864 chg->vbus_vreg->rdev = NULL;
865 if (rc != -EPROBE_DEFER)
866 pr_err("Couldn't register VBUS regualtor rc=%d\n", rc);
867 }
868
869 return rc;
870}
871
872/******************************
873 * VCONN REGULATOR REGISTRATION *
874 ******************************/
875
876struct regulator_ops smb2_vconn_reg_ops = {
877 .enable = smblib_vconn_regulator_enable,
878 .disable = smblib_vconn_regulator_disable,
879 .is_enabled = smblib_vconn_regulator_is_enabled,
880};
881
882static int smb2_init_vconn_regulator(struct smb2 *chip)
883{
884 struct smb_charger *chg = &chip->chg;
885 struct regulator_config cfg = {};
886 int rc = 0;
887
888 chg->vconn_vreg = devm_kzalloc(chg->dev, sizeof(*chg->vconn_vreg),
889 GFP_KERNEL);
890 if (!chg->vconn_vreg)
891 return -ENOMEM;
892
893 cfg.dev = chg->dev;
894 cfg.driver_data = chip;
895
896 chg->vconn_vreg->rdesc.owner = THIS_MODULE;
897 chg->vconn_vreg->rdesc.type = REGULATOR_VOLTAGE;
898 chg->vconn_vreg->rdesc.ops = &smb2_vconn_reg_ops;
899 chg->vconn_vreg->rdesc.of_match = "qcom,smb2-vconn";
900 chg->vconn_vreg->rdesc.name = "qcom,smb2-vconn";
901
902 chg->vconn_vreg->rdev = devm_regulator_register(chg->dev,
903 &chg->vconn_vreg->rdesc, &cfg);
904 if (IS_ERR(chg->vconn_vreg->rdev)) {
905 rc = PTR_ERR(chg->vconn_vreg->rdev);
906 chg->vconn_vreg->rdev = NULL;
907 if (rc != -EPROBE_DEFER)
908 pr_err("Couldn't register VCONN regualtor rc=%d\n", rc);
909 }
910
911 return rc;
912}
913
914/***************************
915 * HARDWARE INITIALIZATION *
916 ***************************/
Harry Yangfe913842016-08-10 12:27:28 -0700917static int smb2_config_step_charging(struct smb2 *chip)
918{
919 struct smb_charger *chg = &chip->chg;
920 int rc = 0;
921 int i;
922
923 if (!chg->step_chg_enabled)
924 return rc;
925
926 for (i = 0; i < STEP_CHARGING_MAX_STEPS - 1; i++) {
927 rc = smblib_set_charge_param(chg,
928 &chg->param.step_soc_threshold[i],
929 chip->dt.step_soc_threshold[i]);
930 if (rc < 0) {
931 pr_err("Couldn't configure soc thresholds rc = %d\n",
932 rc);
933 goto err_out;
934 }
935 }
936
937 for (i = 0; i < STEP_CHARGING_MAX_STEPS; i++) {
938 rc = smblib_set_charge_param(chg, &chg->param.step_cc_delta[i],
939 chip->dt.step_cc_delta[i]);
940 if (rc < 0) {
941 pr_err("Couldn't configure cc delta rc = %d\n",
942 rc);
943 goto err_out;
944 }
945 }
946
947 rc = smblib_write(chg, STEP_CHG_UPDATE_REQUEST_TIMEOUT_CFG_REG,
948 STEP_CHG_UPDATE_REQUEST_TIMEOUT_40S);
949 if (rc < 0) {
950 dev_err(chg->dev,
951 "Couldn't configure soc request timeout reg rc=%d\n",
952 rc);
953 goto err_out;
954 }
955
956 rc = smblib_write(chg, STEP_CHG_UPDATE_FAIL_TIMEOUT_CFG_REG,
957 STEP_CHG_UPDATE_FAIL_TIMEOUT_120S);
958 if (rc < 0) {
959 dev_err(chg->dev,
960 "Couldn't configure soc fail timeout reg rc=%d\n",
961 rc);
962 goto err_out;
963 }
964
965 /*
966 * enable step charging, source soc, standard mode, go to final
967 * state in case of failure.
968 */
969 rc = smblib_write(chg, CHGR_STEP_CHG_MODE_CFG_REG,
970 STEP_CHARGING_ENABLE_BIT |
971 STEP_CHARGING_SOURCE_SELECT_BIT |
972 STEP_CHARGING_SOC_FAIL_OPTION_BIT);
973 if (rc < 0) {
974 dev_err(chg->dev, "Couldn't configure charger rc=%d\n", rc);
975 goto err_out;
976 }
977
978 return 0;
979err_out:
980 chg->step_chg_enabled = false;
981 return rc;
982}
983
Abhijeet Dharmapurikar5cf5faf2016-06-21 14:20:24 -0700984static int smb2_config_wipower_input_power(struct smb2 *chip, int uw)
985{
986 int rc;
987 int ua;
988 struct smb_charger *chg = &chip->chg;
989 s64 nw = (s64)uw * 1000;
990
Vic Wei373e0272016-08-11 01:39:11 -0700991 if (uw < 0)
992 return 0;
993
Abhijeet Dharmapurikar5cf5faf2016-06-21 14:20:24 -0700994 ua = div_s64(nw, ZIN_ICL_PT_MAX_MV);
995 rc = smblib_set_charge_param(chg, &chg->param.dc_icl_pt_lv, ua);
996 if (rc < 0) {
997 pr_err("Couldn't configure dc_icl_pt_lv rc = %d\n", rc);
998 return rc;
999 }
1000
1001 ua = div_s64(nw, ZIN_ICL_PT_HV_MAX_MV);
1002 rc = smblib_set_charge_param(chg, &chg->param.dc_icl_pt_hv, ua);
1003 if (rc < 0) {
1004 pr_err("Couldn't configure dc_icl_pt_hv rc = %d\n", rc);
1005 return rc;
1006 }
1007
1008 ua = div_s64(nw, ZIN_ICL_LV_MAX_MV);
1009 rc = smblib_set_charge_param(chg, &chg->param.dc_icl_div2_lv, ua);
1010 if (rc < 0) {
1011 pr_err("Couldn't configure dc_icl_div2_lv rc = %d\n", rc);
1012 return rc;
1013 }
1014
1015 ua = div_s64(nw, ZIN_ICL_MID_LV_MAX_MV);
1016 rc = smblib_set_charge_param(chg, &chg->param.dc_icl_div2_mid_lv, ua);
1017 if (rc < 0) {
1018 pr_err("Couldn't configure dc_icl_div2_mid_lv rc = %d\n", rc);
1019 return rc;
1020 }
1021
1022 ua = div_s64(nw, ZIN_ICL_MID_HV_MAX_MV);
1023 rc = smblib_set_charge_param(chg, &chg->param.dc_icl_div2_mid_hv, ua);
1024 if (rc < 0) {
1025 pr_err("Couldn't configure dc_icl_div2_mid_hv rc = %d\n", rc);
1026 return rc;
1027 }
1028
1029 ua = div_s64(nw, ZIN_ICL_HV_MAX_MV);
1030 rc = smblib_set_charge_param(chg, &chg->param.dc_icl_div2_hv, ua);
1031 if (rc < 0) {
1032 pr_err("Couldn't configure dc_icl_div2_hv rc = %d\n", rc);
1033 return rc;
1034 }
1035
1036 return 0;
1037}
Nicholas Troast96886052016-02-25 15:42:17 -08001038
1039static int smb2_init_hw(struct smb2 *chip)
1040{
1041 struct smb_charger *chg = &chip->chg;
1042 int rc;
1043
Nicholas Troast2ebe6c52016-09-20 13:25:59 -07001044 if (chip->dt.no_battery)
1045 chg->fake_capacity = 50;
1046
Nicholas Troast4f2d7962016-07-27 11:08:10 -07001047 if (chip->dt.fcc_ua < 0)
1048 smblib_get_charge_param(chg, &chg->param.fcc, &chip->dt.fcc_ua);
1049
1050 if (chip->dt.fv_uv < 0)
1051 smblib_get_charge_param(chg, &chg->param.fv, &chip->dt.fv_uv);
1052
1053 if (chip->dt.usb_icl_ua < 0)
1054 smblib_get_charge_param(chg, &chg->param.usb_icl,
1055 &chip->dt.usb_icl_ua);
1056
1057 if (chip->dt.dc_icl_ua < 0)
1058 smblib_get_charge_param(chg, &chg->param.dc_icl,
1059 &chip->dt.dc_icl_ua);
1060
Harry Yang360bd532016-09-26 11:03:22 -07001061 chg->otg_cl_ua = chip->dt.otg_cl_ua;
1062
Nicholas Troast96886052016-02-25 15:42:17 -08001063 /* votes must be cast before configuring software control */
Harry Yang1d1034c2016-06-15 12:09:42 -07001064 vote(chg->pl_disable_votable,
Harry Yangaba1f5f2016-09-28 10:47:29 -07001065 PL_INDIRECT_VOTER, true, 0);
Harry Yang1d1034c2016-06-15 12:09:42 -07001066 vote(chg->pl_disable_votable,
1067 CHG_STATE_VOTER, true, 0);
Harry Yang995b7422016-08-29 16:06:50 -07001068 vote(chg->pl_disable_votable,
1069 PARALLEL_PSY_VOTER, true, 0);
Nicholas Troast96886052016-02-25 15:42:17 -08001070 vote(chg->usb_suspend_votable,
Nicholas Troast2ebe6c52016-09-20 13:25:59 -07001071 DEFAULT_VOTER, chip->dt.no_battery, 0);
Nicholas Troast96886052016-02-25 15:42:17 -08001072 vote(chg->dc_suspend_votable,
Nicholas Troast2ebe6c52016-09-20 13:25:59 -07001073 DEFAULT_VOTER, chip->dt.no_battery, 0);
Abhijeet Dharmapurikar99fb8942016-07-08 11:39:23 -07001074 vote(chg->fcc_max_votable,
Nicholas Troast96886052016-02-25 15:42:17 -08001075 DEFAULT_VOTER, true, chip->dt.fcc_ua);
Abhijeet Dharmapurikarf9805d42016-05-17 18:38:42 -07001076 vote(chg->fv_votable,
1077 DEFAULT_VOTER, true, chip->dt.fv_uv);
Nicholas Troast96886052016-02-25 15:42:17 -08001078 vote(chg->usb_icl_votable,
1079 DEFAULT_VOTER, true, chip->dt.usb_icl_ua);
1080 vote(chg->dc_icl_votable,
1081 DEFAULT_VOTER, true, chip->dt.dc_icl_ua);
Abhijeet Dharmapurikarf0b0a042016-10-10 16:43:43 -07001082 vote(chg->hvdcp_disable_votable, DEFAULT_VOTER,
1083 chip->dt.hvdcp_disable, 0);
Abhijeet Dharmapurikar716cd962016-10-14 12:50:37 -07001084 vote(chg->hvdcp_disable_votable, PD_INACTIVE_VOTER,
1085 true, 0);
Abhijeet Dharmapurikar4b13c6e2016-10-05 15:15:10 -07001086 vote(chg->pd_disallowed_votable_indirect, CC_DETACHED_VOTER,
1087 true, 0);
1088 vote(chg->pd_disallowed_votable_indirect, HVDCP_TIMEOUT_VOTER,
1089 true, 0);
Nicholas Troast96886052016-02-25 15:42:17 -08001090
Subbaraman Narayanamurthy04d3e502016-10-05 15:22:04 -07001091 /* Configure charge enable for software control; active high */
Nicholas Troast96886052016-02-25 15:42:17 -08001092 rc = smblib_masked_write(chg, CHGR_CFG2_REG,
Nicholas Troastfb827ac42016-07-19 15:48:31 -07001093 CHG_EN_POLARITY_BIT |
Subbaraman Narayanamurthy04d3e502016-10-05 15:22:04 -07001094 CHG_EN_SRC_BIT, 0);
Nicholas Troast96886052016-02-25 15:42:17 -08001095 if (rc < 0) {
Nicholas Troastfb827ac42016-07-19 15:48:31 -07001096 dev_err(chg->dev, "Couldn't configure charger rc=%d\n", rc);
Nicholas Troast96886052016-02-25 15:42:17 -08001097 return rc;
1098 }
1099
1100 /* enable the charging path */
Abhijeet Dharmapurikaree54de02016-07-08 14:51:47 -07001101 rc = vote(chg->chg_disable_votable, DEFAULT_VOTER, false, 0);
Nicholas Troast96886052016-02-25 15:42:17 -08001102 if (rc < 0) {
1103 dev_err(chg->dev, "Couldn't enable charging rc=%d\n", rc);
1104 return rc;
1105 }
1106
1107 /*
1108 * trigger the usb-typec-change interrupt only when the CC state
Nicholas Troast31808492016-07-19 15:09:33 -07001109 * changes
Nicholas Troast96886052016-02-25 15:42:17 -08001110 */
1111 rc = smblib_write(chg, TYPE_C_INTRPT_ENB_REG,
Nicholas Troast31808492016-07-19 15:09:33 -07001112 TYPEC_CCSTATE_CHANGE_INT_EN_BIT);
Nicholas Troast96886052016-02-25 15:42:17 -08001113 if (rc < 0) {
1114 dev_err(chg->dev,
1115 "Couldn't configure Type-C interrupts rc=%d\n", rc);
1116 return rc;
1117 }
1118
1119 /* configure VCONN for software control */
1120 rc = smblib_masked_write(chg, TYPE_C_INTRPT_ENB_SOFTWARE_CTRL_REG,
1121 VCONN_EN_SRC_BIT | VCONN_EN_VALUE_BIT,
1122 VCONN_EN_SRC_BIT);
1123 if (rc < 0) {
1124 dev_err(chg->dev,
1125 "Couldn't configure VCONN for SW control rc=%d\n", rc);
1126 return rc;
1127 }
1128
1129 /* configure VBUS for software control */
1130 rc = smblib_masked_write(chg, OTG_CFG_REG, OTG_EN_SRC_CFG_BIT, 0);
1131 if (rc < 0) {
1132 dev_err(chg->dev,
1133 "Couldn't configure VBUS for SW control rc=%d\n", rc);
1134 return rc;
1135 }
1136
1137 /* configure power role for dual-role */
1138 rc = smblib_masked_write(chg, TYPE_C_INTRPT_ENB_SOFTWARE_CTRL_REG,
1139 TYPEC_POWER_ROLE_CMD_MASK, 0);
1140 if (rc < 0) {
1141 dev_err(chg->dev,
1142 "Couldn't configure power role for DRP rc=%d\n", rc);
1143 return rc;
1144 }
1145
Nicholas Troast4ea53ba2016-05-20 16:15:36 -07001146 /* disable Type-C factory mode */
1147 rc = smblib_masked_write(chg, TYPE_C_CFG_REG,
1148 FACTORY_MODE_DETECTION_EN_BIT, 0);
1149 if (rc < 0) {
1150 dev_err(chg->dev,
1151 "Couldn't disable Type-C factory mode rc=%d\n", rc);
1152 return rc;
1153 }
1154
Abhijeet Dharmapurikar9e39a582016-05-27 13:07:39 -07001155 rc = smblib_masked_write(chg, QNOVO_PT_ENABLE_CMD_REG,
1156 QNOVO_PT_ENABLE_CMD_BIT, QNOVO_PT_ENABLE_CMD_BIT);
1157 if (rc < 0) {
1158 dev_err(chg->dev, "Couldn't enable qnovo rc=%d\n", rc);
1159 return rc;
1160 }
1161
Harry Yangfe913842016-08-10 12:27:28 -07001162 /* configure step charging */
1163 rc = smb2_config_step_charging(chip);
1164 if (rc < 0) {
1165 dev_err(chg->dev, "Couldn't configure step charging rc=%d\n",
1166 rc);
1167 return rc;
1168 }
1169
Abhijeet Dharmapurikar5cf5faf2016-06-21 14:20:24 -07001170 /* configure wipower watts */
1171 rc = smb2_config_wipower_input_power(chip, chip->dt.wipower_max_uw);
1172 if (rc < 0) {
1173 dev_err(chg->dev, "Couldn't configure wipower rc=%d\n", rc);
1174 return rc;
1175 }
1176
Harry Yangd57681c2016-08-29 11:46:43 -07001177 /* configure PMI stat output to enable and disable parallel charging */
1178 rc = smblib_masked_write(chg, STAT_CFG_REG,
1179 STAT_PARALLEL_CFG_BIT | STAT_SW_OVERRIDE_CFG_BIT,
1180 STAT_PARALLEL_CFG_BIT);
1181 if (rc < 0) {
1182 dev_err(chg->dev,
1183 "Couldn't configure signal for parallel rc=%d\n", rc);
1184 return rc;
1185 }
1186
Nicholas Troast597acfe2016-07-20 16:03:15 -07001187 /* configure float charger options */
1188 switch (chip->dt.float_option) {
1189 case 1:
1190 rc = smblib_masked_write(chg, USBIN_OPTIONS_2_CFG_REG,
1191 FLOAT_OPTIONS_MASK, 0);
1192 break;
1193 case 2:
1194 rc = smblib_masked_write(chg, USBIN_OPTIONS_2_CFG_REG,
1195 FLOAT_OPTIONS_MASK, FORCE_FLOAT_SDP_CFG_BIT);
1196 break;
1197 case 3:
1198 rc = smblib_masked_write(chg, USBIN_OPTIONS_2_CFG_REG,
1199 FLOAT_OPTIONS_MASK, FLOAT_DIS_CHGING_CFG_BIT);
1200 break;
1201 case 4:
1202 rc = smblib_masked_write(chg, USBIN_OPTIONS_2_CFG_REG,
1203 FLOAT_OPTIONS_MASK, SUSPEND_FLOAT_CFG_BIT);
1204 break;
1205 default:
1206 rc = 0;
1207 break;
1208 }
1209
1210 if (rc < 0) {
1211 dev_err(chg->dev, "Couldn't configure float charger options rc=%d\n",
1212 rc);
1213 return rc;
1214 }
1215
Nicholas Troast96886052016-02-25 15:42:17 -08001216 return rc;
1217}
1218
Harry Yangf7251982016-09-16 11:14:49 -07001219static int smb2_setup_wa_flags(struct smb2 *chip)
1220{
Harry Yang1369b7a2016-09-27 15:59:50 -07001221 struct smb_charger *chg = &chip->chg;
Harry Yangf7251982016-09-16 11:14:49 -07001222 struct pmic_revid_data *pmic_rev_id;
1223 struct device_node *revid_dev_node;
1224
1225 revid_dev_node = of_parse_phandle(chip->chg.dev->of_node,
1226 "qcom,pmic-revid", 0);
1227 if (!revid_dev_node) {
1228 pr_err("Missing qcom,pmic-revid property\n");
1229 return -EINVAL;
1230 }
1231
1232 pmic_rev_id = get_revid_data(revid_dev_node);
1233 if (IS_ERR_OR_NULL(pmic_rev_id)) {
1234 /*
1235 * the revid peripheral must be registered, any failure
1236 * here only indicates that the rev-id module has not
1237 * probed yet.
1238 */
1239 return -EPROBE_DEFER;
1240 }
1241
1242 switch (pmic_rev_id->pmic_subtype) {
1243 case PMICOBALT_SUBTYPE:
Nicholas Troastabedaf72016-09-16 11:07:45 -07001244 chip->chg.wa_flags |= BOOST_BACK_WA;
Harry Yang1369b7a2016-09-27 15:59:50 -07001245 if (pmic_rev_id->rev4 == PMICOBALT_V1P1_REV4) /* PMI rev 1.1 */
1246 chg->wa_flags |= QC_CHARGER_DETECTION_WA_BIT;
Harry Yangf7251982016-09-16 11:14:49 -07001247 break;
1248 default:
1249 pr_err("PMIC subtype %d not supported\n",
1250 pmic_rev_id->pmic_subtype);
1251 return -EINVAL;
1252 }
1253
1254 return 0;
1255}
1256
Nicholas Troast96886052016-02-25 15:42:17 -08001257/****************************
1258 * DETERMINE INITIAL STATUS *
1259 ****************************/
1260
1261static int smb2_determine_initial_status(struct smb2 *chip)
1262{
1263 struct smb_irq_data irq_data = {chip, "determine-initial-status"};
1264
1265 smblib_handle_usb_plugin(0, &irq_data);
1266 smblib_handle_usb_typec_change(0, &irq_data);
1267 smblib_handle_usb_source_change(0, &irq_data);
Harry Yang58a9e7a2016-06-23 14:54:43 -07001268 smblib_handle_chg_state_change(0, &irq_data);
1269 smblib_handle_icl_change(0, &irq_data);
Harry Yangfe913842016-08-10 12:27:28 -07001270 smblib_handle_step_chg_state_change(0, &irq_data);
1271 smblib_handle_step_chg_soc_update_request(0, &irq_data);
Nicholas Troast96886052016-02-25 15:42:17 -08001272
1273 return 0;
1274}
1275
1276/**************************
1277 * INTERRUPT REGISTRATION *
1278 **************************/
1279
1280struct smb2_irq_info {
Nicholas Troast47ae4612016-08-03 09:49:36 -07001281 const char *name;
1282 const irq_handler_t handler;
1283 const bool wake;
1284 const struct storm_watch storm_data;
1285 int irq;
Nicholas Troast96886052016-02-25 15:42:17 -08001286};
1287
Nicholas Troast1ff4dc62016-06-16 12:28:39 -07001288static struct smb2_irq_info smb2_irqs[] = {
Nicholas Troast96886052016-02-25 15:42:17 -08001289/* CHARGER IRQs */
Nicholas Troast47ae4612016-08-03 09:49:36 -07001290 {
1291 .name = "chg-error",
1292 .handler = smblib_handle_debug,
1293 },
1294 {
1295 .name = "chg-state-change",
1296 .handler = smblib_handle_chg_state_change,
1297 .wake = true,
1298 },
1299 {
1300 .name = "step-chg-state-change",
1301 .handler = smblib_handle_step_chg_state_change,
1302 .wake = true,
1303 },
1304 {
1305 .name = "step-chg-soc-update-fail",
1306 .handler = smblib_handle_step_chg_soc_update_fail,
1307 .wake = true,
1308 },
1309 {
1310 .name = "step-chg-soc-update-request",
1311 .handler = smblib_handle_step_chg_soc_update_request,
1312 .wake = true,
1313 },
Nicholas Troast96886052016-02-25 15:42:17 -08001314/* OTG IRQs */
Nicholas Troast47ae4612016-08-03 09:49:36 -07001315 {
1316 .name = "otg-fail",
1317 .handler = smblib_handle_debug,
1318 },
1319 {
1320 .name = "otg-overcurrent",
1321 .handler = smblib_handle_debug,
1322 },
1323 {
1324 .name = "otg-oc-dis-sw-sts",
1325 .handler = smblib_handle_debug,
1326 },
1327 {
1328 .name = "testmode-change-detect",
1329 .handler = smblib_handle_debug,
1330 },
Nicholas Troast96886052016-02-25 15:42:17 -08001331/* BATTERY IRQs */
Nicholas Troast47ae4612016-08-03 09:49:36 -07001332 {
1333 .name = "bat-temp",
1334 .handler = smblib_handle_batt_temp_changed,
1335 },
1336 {
1337 .name = "bat-ocp",
1338 .handler = smblib_handle_batt_psy_changed,
1339 },
1340 {
1341 .name = "bat-ov",
1342 .handler = smblib_handle_batt_psy_changed,
1343 },
1344 {
1345 .name = "bat-low",
1346 .handler = smblib_handle_batt_psy_changed,
1347 },
1348 {
1349 .name = "bat-therm-or-id-missing",
1350 .handler = smblib_handle_batt_psy_changed,
1351 },
1352 {
1353 .name = "bat-terminal-missing",
1354 .handler = smblib_handle_batt_psy_changed,
1355 },
Nicholas Troast96886052016-02-25 15:42:17 -08001356/* USB INPUT IRQs */
Nicholas Troast47ae4612016-08-03 09:49:36 -07001357 {
1358 .name = "usbin-collapse",
1359 .handler = smblib_handle_debug,
1360 },
1361 {
1362 .name = "usbin-lt-3p6v",
1363 .handler = smblib_handle_debug,
1364 },
1365 {
1366 .name = "usbin-uv",
1367 .handler = smblib_handle_debug,
1368 },
1369 {
1370 .name = "usbin-ov",
1371 .handler = smblib_handle_debug,
1372 },
1373 {
1374 .name = "usbin-plugin",
1375 .handler = smblib_handle_usb_plugin,
1376 .wake = true,
1377 },
1378 {
1379 .name = "usbin-src-change",
1380 .handler = smblib_handle_usb_source_change,
1381 .wake = true,
1382 },
1383 {
1384 .name = "usbin-icl-change",
1385 .handler = smblib_handle_icl_change,
1386 .wake = true,
1387 },
1388 {
1389 .name = "type-c-change",
1390 .handler = smblib_handle_usb_typec_change,
1391 .wake = true,
1392 },
Nicholas Troast96886052016-02-25 15:42:17 -08001393/* DC INPUT IRQs */
Nicholas Troast47ae4612016-08-03 09:49:36 -07001394 {
1395 .name = "dcin-collapse",
1396 .handler = smblib_handle_debug,
1397 },
1398 {
1399 .name = "dcin-lt-3p6v",
1400 .handler = smblib_handle_debug,
1401 },
1402 {
1403 .name = "dcin-uv",
1404 .handler = smblib_handle_debug,
1405 },
1406 {
1407 .name = "dcin-ov",
1408 .handler = smblib_handle_debug,
1409 },
1410 {
1411 .name = "dcin-plugin",
Abhijeet Dharmapurikar23916642016-10-03 10:38:50 -07001412 .handler = smblib_handle_dc_plugin,
1413 .wake = true,
Nicholas Troast47ae4612016-08-03 09:49:36 -07001414 },
1415 {
1416 .name = "div2-en-dg",
1417 .handler = smblib_handle_debug,
1418 },
1419 {
1420 .name = "dcin-icl-change",
1421 .handler = smblib_handle_debug,
1422 },
Nicholas Troast96886052016-02-25 15:42:17 -08001423/* MISCELLANEOUS IRQs */
Nicholas Troast47ae4612016-08-03 09:49:36 -07001424 {
1425 .name = "wdog-snarl",
1426 .handler = NULL,
1427 },
1428 {
1429 .name = "wdog-bark",
1430 .handler = NULL,
1431 },
1432 {
1433 .name = "aicl-fail",
1434 .handler = smblib_handle_debug,
1435 },
1436 {
1437 .name = "aicl-done",
1438 .handler = smblib_handle_debug,
1439 },
1440 {
1441 .name = "high-duty-cycle",
1442 .handler = smblib_handle_high_duty_cycle,
1443 .wake = true,
1444 },
1445 {
1446 .name = "input-current-limiting",
1447 .handler = smblib_handle_debug,
1448 },
1449 {
1450 .name = "temperature-change",
1451 .handler = smblib_handle_debug,
1452 },
1453 {
1454 .name = "switcher-power-ok",
Nicholas Troastabedaf72016-09-16 11:07:45 -07001455 .handler = smblib_handle_switcher_power_ok,
1456 .storm_data = {true, 1000, 3},
Nicholas Troast47ae4612016-08-03 09:49:36 -07001457 },
Nicholas Troast96886052016-02-25 15:42:17 -08001458};
1459
1460static int smb2_get_irq_index_byname(const char *irq_name)
1461{
1462 int i;
1463
1464 for (i = 0; i < ARRAY_SIZE(smb2_irqs); i++) {
1465 if (strcmp(smb2_irqs[i].name, irq_name) == 0)
1466 return i;
1467 }
1468
1469 return -ENOENT;
1470}
1471
1472static int smb2_request_interrupt(struct smb2 *chip,
1473 struct device_node *node, const char *irq_name)
1474{
1475 struct smb_charger *chg = &chip->chg;
1476 int rc, irq, irq_index;
1477 struct smb_irq_data *irq_data;
1478
1479 irq = of_irq_get_byname(node, irq_name);
1480 if (irq < 0) {
1481 pr_err("Couldn't get irq %s byname\n", irq_name);
1482 return irq;
1483 }
1484
1485 irq_index = smb2_get_irq_index_byname(irq_name);
1486 if (irq_index < 0) {
1487 pr_err("%s is not a defined irq\n", irq_name);
1488 return irq_index;
1489 }
1490
Harry Yang03bc73b2016-06-23 17:37:21 -07001491 if (!smb2_irqs[irq_index].handler)
1492 return 0;
1493
Nicholas Troast96886052016-02-25 15:42:17 -08001494 irq_data = devm_kzalloc(chg->dev, sizeof(*irq_data), GFP_KERNEL);
1495 if (!irq_data)
1496 return -ENOMEM;
1497
1498 irq_data->parent_data = chip;
1499 irq_data->name = irq_name;
Nicholas Troast47ae4612016-08-03 09:49:36 -07001500 irq_data->storm_data = smb2_irqs[irq_index].storm_data;
Nicholas Troast96886052016-02-25 15:42:17 -08001501
1502 rc = devm_request_threaded_irq(chg->dev, irq, NULL,
1503 smb2_irqs[irq_index].handler,
1504 IRQF_ONESHOT, irq_name, irq_data);
1505 if (rc < 0) {
1506 pr_err("Couldn't request irq %d\n", irq);
1507 return rc;
1508 }
1509
Nicholas Troast1ff4dc62016-06-16 12:28:39 -07001510 smb2_irqs[irq_index].irq = irq;
1511 if (smb2_irqs[irq_index].wake)
1512 enable_irq_wake(irq);
1513
Nicholas Troast96886052016-02-25 15:42:17 -08001514 return rc;
1515}
1516
1517static int smb2_request_interrupts(struct smb2 *chip)
1518{
1519 struct smb_charger *chg = &chip->chg;
1520 struct device_node *node = chg->dev->of_node;
1521 struct device_node *child;
1522 int rc = 0;
1523 const char *name;
1524 struct property *prop;
1525
1526 for_each_available_child_of_node(node, child) {
1527 of_property_for_each_string(child, "interrupt-names",
1528 prop, name) {
1529 rc = smb2_request_interrupt(chip, child, name);
1530 if (rc < 0)
1531 return rc;
1532 }
1533 }
1534
1535 return rc;
1536}
1537
Nicholas Troastfd6729f2016-09-21 17:51:00 -07001538#if defined(CONFIG_DEBUG_FS)
1539
1540static int force_batt_psy_update_write(void *data, u64 val)
1541{
1542 struct smb_charger *chg = data;
1543
1544 power_supply_changed(chg->batt_psy);
1545 return 0;
1546}
1547DEFINE_SIMPLE_ATTRIBUTE(force_batt_psy_update_ops, NULL,
1548 force_batt_psy_update_write, "0x%02llx\n");
1549
1550static int force_usb_psy_update_write(void *data, u64 val)
1551{
1552 struct smb_charger *chg = data;
1553
1554 power_supply_changed(chg->usb_psy);
1555 return 0;
1556}
1557DEFINE_SIMPLE_ATTRIBUTE(force_usb_psy_update_ops, NULL,
1558 force_usb_psy_update_write, "0x%02llx\n");
1559
1560static int force_dc_psy_update_write(void *data, u64 val)
1561{
1562 struct smb_charger *chg = data;
1563
1564 power_supply_changed(chg->dc_psy);
1565 return 0;
1566}
1567DEFINE_SIMPLE_ATTRIBUTE(force_dc_psy_update_ops, NULL,
1568 force_dc_psy_update_write, "0x%02llx\n");
1569
1570static void smb2_create_debugfs(struct smb2 *chip)
1571{
1572 struct dentry *file;
1573
1574 chip->dfs_root = debugfs_create_dir("charger", NULL);
1575 if (IS_ERR_OR_NULL(chip->dfs_root)) {
1576 pr_err("Couldn't create charger debugfs rc=%ld\n",
1577 (long)chip->dfs_root);
1578 return;
1579 }
1580
1581 file = debugfs_create_file("force_batt_psy_update", 0600,
1582 chip->dfs_root, chip, &force_batt_psy_update_ops);
1583 if (IS_ERR_OR_NULL(file))
1584 pr_err("Couldn't create force_batt_psy_update file rc=%ld\n",
1585 (long)file);
1586
1587 file = debugfs_create_file("force_usb_psy_update", 0600,
1588 chip->dfs_root, chip, &force_usb_psy_update_ops);
1589 if (IS_ERR_OR_NULL(file))
1590 pr_err("Couldn't create force_usb_psy_update file rc=%ld\n",
1591 (long)file);
1592
1593 file = debugfs_create_file("force_dc_psy_update", 0600,
1594 chip->dfs_root, chip, &force_dc_psy_update_ops);
1595 if (IS_ERR_OR_NULL(file))
1596 pr_err("Couldn't create force_dc_psy_update file rc=%ld\n",
1597 (long)file);
1598}
1599
1600#else
1601
1602static void smb2_create_debugfs(struct smb2 *chip)
1603{}
1604
1605#endif
Nicholas Troast96886052016-02-25 15:42:17 -08001606
1607static int smb2_probe(struct platform_device *pdev)
1608{
1609 struct smb2 *chip;
1610 struct smb_charger *chg;
1611 int rc = 0;
1612 u8 stat;
1613
1614 chip = devm_kzalloc(&pdev->dev, sizeof(*chip), GFP_KERNEL);
1615 if (!chip)
1616 return -ENOMEM;
1617
1618 chg = &chip->chg;
1619 chg->dev = &pdev->dev;
1620 chg->param = v1_params;
1621 chg->debug_mask = &__debug_mask;
Harry Yang1d1034c2016-06-15 12:09:42 -07001622 chg->mode = PARALLEL_MASTER;
Abhijeet Dharmapurikar31b98f32016-10-14 12:25:23 -07001623 chg->name = "PMI";
Nicholas Troast96886052016-02-25 15:42:17 -08001624
1625 chg->regmap = dev_get_regmap(chg->dev->parent, NULL);
1626 if (!chg->regmap) {
1627 pr_err("parent regmap is missing\n");
1628 return -EINVAL;
1629 }
1630
Harry Yangf7251982016-09-16 11:14:49 -07001631 rc = smb2_setup_wa_flags(chip);
1632 if (rc < 0) {
1633 if (rc != -EPROBE_DEFER)
1634 pr_err("Couldn't setup wa flags rc=%d\n", rc);
1635 return rc;
1636 }
1637
Harry Yangba874ce2016-08-19 14:17:01 -07001638 rc = smblib_init(chg);
1639 if (rc < 0) {
1640 pr_err("Smblib_init failed rc=%d\n", rc);
1641 goto cleanup;
1642 }
Nicholas Troast96886052016-02-25 15:42:17 -08001643
1644 rc = smb2_parse_dt(chip);
1645 if (rc < 0) {
1646 pr_err("Couldn't parse device tree rc=%d\n", rc);
1647 goto cleanup;
1648 }
1649
1650 /* set driver data before resources request it */
1651 platform_set_drvdata(pdev, chip);
1652
1653 rc = smb2_init_vbus_regulator(chip);
1654 if (rc < 0) {
1655 pr_err("Couldn't initialize vbus regulator rc=%d\n",
1656 rc);
1657 goto cleanup;
1658 }
1659
1660 rc = smb2_init_vconn_regulator(chip);
1661 if (rc < 0) {
1662 pr_err("Couldn't initialize vconn regulator rc=%d\n",
1663 rc);
1664 goto cleanup;
1665 }
1666
Harry Yangf3023592016-07-20 14:56:41 -07001667 rc = smb2_init_dc_psy(chip);
1668 if (rc < 0) {
1669 pr_err("Couldn't initialize dc psy rc=%d\n", rc);
1670 goto cleanup;
1671 }
1672
Nicholas Troast96886052016-02-25 15:42:17 -08001673 rc = smb2_init_usb_psy(chip);
1674 if (rc < 0) {
1675 pr_err("Couldn't initialize usb psy rc=%d\n", rc);
1676 goto cleanup;
1677 }
1678
1679 rc = smblib_read(chg, SHDN_CMD_REG, &stat);
1680 if (rc < 0) {
1681 pr_err("Couldn't read MISC_SHDN_CMD_REG rc=%d\n", rc);
1682 return rc;
1683 }
1684
1685 if (stat) {
1686 pr_err("bad charger part; faking USB insertion\n");
1687 chip->bad_part = true;
1688 power_supply_changed(chg->usb_psy);
1689 return 0;
1690 }
1691
Abhijeet Dharmapurikarc0b0f592016-10-14 10:55:42 -07001692 chg->pl.slave_pct = 50;
Nicholas Troast96886052016-02-25 15:42:17 -08001693 rc = smb2_init_batt_psy(chip);
1694 if (rc < 0) {
1695 pr_err("Couldn't initialize batt psy rc=%d\n", rc);
1696 goto cleanup;
1697 }
1698
1699 rc = smb2_init_hw(chip);
1700 if (rc < 0) {
1701 pr_err("Couldn't initialize hardware rc=%d\n", rc);
1702 goto cleanup;
1703 }
1704
1705 rc = smb2_determine_initial_status(chip);
1706 if (rc < 0) {
1707 pr_err("Couldn't determine initial status rc=%d\n",
1708 rc);
1709 goto cleanup;
1710 }
1711
1712 rc = smb2_request_interrupts(chip);
1713 if (rc < 0) {
1714 pr_err("Couldn't request interrupts rc=%d\n", rc);
1715 goto cleanup;
1716 }
1717
Nicholas Troastfd6729f2016-09-21 17:51:00 -07001718 smb2_create_debugfs(chip);
1719
Nicholas Troast96886052016-02-25 15:42:17 -08001720 pr_info("QPNP SMB2 probed successfully\n");
1721 return rc;
1722
1723cleanup:
Abhijeet Dharmapurikar8e9e7572016-06-06 16:13:14 -07001724 smblib_deinit(chg);
Nicholas Troast96886052016-02-25 15:42:17 -08001725 if (chg->usb_psy)
1726 power_supply_unregister(chg->usb_psy);
1727 if (chg->batt_psy)
1728 power_supply_unregister(chg->batt_psy);
1729 if (chg->vconn_vreg && chg->vconn_vreg->rdev)
1730 regulator_unregister(chg->vconn_vreg->rdev);
1731 if (chg->vbus_vreg && chg->vbus_vreg->rdev)
1732 regulator_unregister(chg->vbus_vreg->rdev);
1733 platform_set_drvdata(pdev, NULL);
1734 return rc;
1735}
1736
1737static int smb2_remove(struct platform_device *pdev)
1738{
1739 struct smb2 *chip = platform_get_drvdata(pdev);
1740 struct smb_charger *chg = &chip->chg;
1741
1742 power_supply_unregister(chg->batt_psy);
1743 power_supply_unregister(chg->usb_psy);
1744 regulator_unregister(chg->vconn_vreg->rdev);
1745 regulator_unregister(chg->vbus_vreg->rdev);
1746
1747 platform_set_drvdata(pdev, NULL);
1748 return 0;
1749}
1750
Nicholas Troasta0116842016-10-28 11:02:03 -07001751static void smb2_shutdown(struct platform_device *pdev)
1752{
1753 struct smb2 *chip = platform_get_drvdata(pdev);
1754 struct smb_charger *chg = &chip->chg;
1755
1756 smblib_masked_write(chg, USBIN_OPTIONS_1_CFG_REG,
1757 HVDCP_AUTONOMOUS_MODE_EN_CFG_BIT, 0);
1758 smblib_write(chg, CMD_HVDCP_2_REG, FORCE_5V_BIT);
1759}
1760
Nicholas Troast96886052016-02-25 15:42:17 -08001761static const struct of_device_id match_table[] = {
1762 { .compatible = "qcom,qpnp-smb2", },
1763 { },
1764};
1765
1766static struct platform_driver smb2_driver = {
1767 .driver = {
1768 .name = "qcom,qpnp-smb2",
1769 .owner = THIS_MODULE,
1770 .of_match_table = match_table,
1771 },
1772 .probe = smb2_probe,
1773 .remove = smb2_remove,
Nicholas Troasta0116842016-10-28 11:02:03 -07001774 .shutdown = smb2_shutdown,
Nicholas Troast96886052016-02-25 15:42:17 -08001775};
1776module_platform_driver(smb2_driver);
1777
1778MODULE_DESCRIPTION("QPNP SMB2 Charger Driver");
1779MODULE_LICENSE("GPL v2");