blob: f8d16f87c431d5382b5f695fe2481c59fd129232 [file] [log] [blame]
Abhijeet Dharmapurikarae1aa822017-01-06 12:16:49 -08001/* Copyright (c) 2016-2017 The Linux Foundation. All rights reserved.
Nicholas Troast5d13c302016-05-12 18:01:06 -07002 *
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 Troastdc6e59a2017-01-30 19:22:22 -080013#define pr_fmt(fmt) "SMB138X: %s: " fmt, __func__
14
Nicholas Troast5d13c302016-05-12 18:01:06 -070015#include <linux/device.h>
Nicholas Troastdc6e59a2017-01-30 19:22:22 -080016#include <linux/iio/consumer.h>
Nicholas Troastdc6e59a2017-01-30 19:22:22 -080017#include <linux/module.h>
Nicholas Troast5d13c302016-05-12 18:01:06 -070018#include <linux/of.h>
19#include <linux/of_device.h>
20#include <linux/of_irq.h>
Nicholas Troastdc6e59a2017-01-30 19:22:22 -080021#include <linux/platform_device.h>
22#include <linux/power_supply.h>
23#include <linux/regmap.h>
Nicholas Troast5d13c302016-05-12 18:01:06 -070024#include <linux/regulator/driver.h>
Nicholas Troast5d13c302016-05-12 18:01:06 -070025#include <linux/regulator/machine.h>
Nicholas Troastdc6e59a2017-01-30 19:22:22 -080026#include <linux/regulator/of_regulator.h>
Abhijeet Dharmapurikarb3022c82016-08-16 16:32:38 -070027#include <linux/qpnp/qpnp-revid.h>
Nicholas Troast5d13c302016-05-12 18:01:06 -070028#include "smb-reg.h"
29#include "smb-lib.h"
Nicholas Troast47ae4612016-08-03 09:49:36 -070030#include "storm-watch.h"
Abhijeet Dharmapurikardd119c62017-03-20 15:54:59 -070031#include <linux/pmic-voter.h>
Nicholas Troast5d13c302016-05-12 18:01:06 -070032
33#define SMB138X_DEFAULT_FCC_UA 1000000
34#define SMB138X_DEFAULT_ICL_UA 1500000
35
Abhijeet Dharmapurikarb3022c82016-08-16 16:32:38 -070036/* Registers that are not common to be mentioned in smb-reg.h */
37#define SMB2CHG_MISC_ENG_SDCDC_CFG2 (MISC_BASE + 0xC1)
Abhijeet Dharmapurikardc5b06f2016-08-18 14:45:59 -070038#define ENG_SDCDC_SEL_OOB_VTH_BIT BIT(0)
39
40#define SMB2CHG_MISC_ENG_SDCDC_CFG6 (MISC_BASE + 0xC5)
41#define DEAD_TIME_MASK GENMASK(7, 4)
42#define HIGH_DEAD_TIME_MASK GENMASK(7, 4)
Abhijeet Dharmapurikarb3022c82016-08-16 16:32:38 -070043
Nicholas Troast420fa832016-12-08 14:23:27 -080044#define SMB2CHG_DC_TM_SREFGEN (DCIN_BASE + 0xE2)
45#define STACKED_DIODE_EN_BIT BIT(2)
46
Abhijeet Dharmapurikard8d82b12017-02-21 19:40:38 -080047#define TDIE_AVG_COUNT 10
Harry Yange8e38ce2017-03-09 11:22:44 -080048#define MAX_SPEED_READING_TIMES 5
Abhijeet Dharmapurikard8d82b12017-02-21 19:40:38 -080049
Abhijeet Dharmapurikarb3022c82016-08-16 16:32:38 -070050enum {
51 OOB_COMP_WA_BIT = BIT(0),
52};
53
Nicholas Troast5d13c302016-05-12 18:01:06 -070054static struct smb_params v1_params = {
55 .fcc = {
56 .name = "fast charge current",
57 .reg = FAST_CHARGE_CURRENT_CFG_REG,
58 .min_u = 0,
Abhijeet Dharmapurikar541b6e72016-10-25 18:40:37 -070059 .max_u = 6000000,
Nicholas Troast74626cb2016-10-06 11:54:13 -070060 .step_u = 25000,
Nicholas Troast5d13c302016-05-12 18:01:06 -070061 },
62 .fv = {
63 .name = "float voltage",
64 .reg = FLOAT_VOLTAGE_CFG_REG,
Abhijeet Dharmapurikar541b6e72016-10-25 18:40:37 -070065 .min_u = 2450000,
66 .max_u = 4950000,
Nicholas Troast5d13c302016-05-12 18:01:06 -070067 .step_u = 10000,
68 },
69 .usb_icl = {
70 .name = "usb input current limit",
71 .reg = USBIN_CURRENT_LIMIT_CFG_REG,
72 .min_u = 0,
73 .max_u = 6000000,
74 .step_u = 25000,
75 },
76 .dc_icl = {
77 .name = "dc input current limit",
78 .reg = DCIN_CURRENT_LIMIT_CFG_REG,
79 .min_u = 0,
80 .max_u = 6000000,
81 .step_u = 25000,
82 },
Harry Yangf6df8b02016-10-05 15:38:03 -070083 .freq_buck = {
84 .name = "buck switching frequency",
85 .reg = CFG_BUCKBOOST_FREQ_SELECT_BUCK_REG,
86 .min_u = 500,
87 .max_u = 2000,
88 .step_u = 100,
89 },
Nicholas Troast5d13c302016-05-12 18:01:06 -070090};
91
92struct smb_dt_props {
93 bool suspend_input;
94 int fcc_ua;
95 int usb_icl_ua;
96 int dc_icl_ua;
Nicholas Troastdc6e59a2017-01-30 19:22:22 -080097 int chg_temp_max_mdegc;
Nicholas Troastae0ea542017-01-31 19:23:10 -080098 int connector_temp_max_mdegc;
Harry Yang81c5fc02017-03-14 12:23:01 -070099 int pl_mode;
Nicholas Troast5d13c302016-05-12 18:01:06 -0700100};
101
102struct smb138x {
103 struct smb_charger chg;
104 struct smb_dt_props dt;
105 struct power_supply *parallel_psy;
Abhijeet Dharmapurikar1407d662016-08-23 11:54:12 -0700106 u32 wa_flags;
Nicholas Troast5d13c302016-05-12 18:01:06 -0700107};
108
109static int __debug_mask;
110module_param_named(
111 debug_mask, __debug_mask, int, 0600
112);
113
Nicholas Troast1f33b0c2017-01-16 14:12:33 -0800114irqreturn_t smb138x_handle_slave_chg_state_change(int irq, void *data)
115{
116 struct smb_irq_data *irq_data = data;
117 struct smb138x *chip = irq_data->parent_data;
118
119 if (chip->parallel_psy)
120 power_supply_changed(chip->parallel_psy);
121
122 return IRQ_HANDLED;
123}
124
Abhijeet Dharmapurikard8d82b12017-02-21 19:40:38 -0800125static int smb138x_get_prop_charger_temp(struct smb138x *chip,
126 union power_supply_propval *val)
127{
128 union power_supply_propval pval;
129 int rc = 0, avg = 0, i;
130 struct smb_charger *chg = &chip->chg;
Harry Yange8e38ce2017-03-09 11:22:44 -0800131 int die_avg_count;
Abhijeet Dharmapurikard8d82b12017-02-21 19:40:38 -0800132
Harry Yange8e38ce2017-03-09 11:22:44 -0800133 if (chg->temp_speed_reading_count < MAX_SPEED_READING_TIMES) {
134 chg->temp_speed_reading_count++;
135 die_avg_count = 1;
136 } else {
137 die_avg_count = TDIE_AVG_COUNT;
138 }
139
140 for (i = 0; i < die_avg_count; i++) {
Abhijeet Dharmapurikard8d82b12017-02-21 19:40:38 -0800141 pval.intval = 0;
142 rc = smblib_get_prop_charger_temp(chg, &pval);
143 if (rc < 0) {
144 pr_err("Couldnt read chg temp at %dth iteration rc = %d\n",
145 i + 1, rc);
146 return rc;
147 }
148 avg += pval.intval;
149 }
Harry Yange8e38ce2017-03-09 11:22:44 -0800150 val->intval = avg / die_avg_count;
Abhijeet Dharmapurikard8d82b12017-02-21 19:40:38 -0800151 return rc;
152}
153
Nicholas Troast5d13c302016-05-12 18:01:06 -0700154static int smb138x_parse_dt(struct smb138x *chip)
155{
156 struct smb_charger *chg = &chip->chg;
157 struct device_node *node = chg->dev->of_node;
158 int rc;
159
160 if (!node) {
161 pr_err("device tree node missing\n");
162 return -EINVAL;
163 }
164
Harry Yang81c5fc02017-03-14 12:23:01 -0700165 rc = of_property_read_u32(node,
166 "qcom,parallel-mode", &chip->dt.pl_mode);
167 if (rc < 0)
168 chip->dt.pl_mode = POWER_SUPPLY_PL_USBMID_USBMID;
169
Nicholas Troast5d13c302016-05-12 18:01:06 -0700170 chip->dt.suspend_input = of_property_read_bool(node,
171 "qcom,suspend-input");
172
173 rc = of_property_read_u32(node,
174 "qcom,fcc-max-ua", &chip->dt.fcc_ua);
175 if (rc < 0)
176 chip->dt.fcc_ua = SMB138X_DEFAULT_FCC_UA;
177
178 rc = of_property_read_u32(node,
179 "qcom,usb-icl-ua", &chip->dt.usb_icl_ua);
180 if (rc < 0)
181 chip->dt.usb_icl_ua = SMB138X_DEFAULT_ICL_UA;
182
183 rc = of_property_read_u32(node,
184 "qcom,dc-icl-ua", &chip->dt.dc_icl_ua);
185 if (rc < 0)
186 chip->dt.dc_icl_ua = SMB138X_DEFAULT_ICL_UA;
187
Nicholas Troastdc6e59a2017-01-30 19:22:22 -0800188 rc = of_property_read_u32(node,
189 "qcom,charger-temp-max-mdegc",
190 &chip->dt.chg_temp_max_mdegc);
191 if (rc < 0)
192 chip->dt.chg_temp_max_mdegc = 80000;
193
Nicholas Troastae0ea542017-01-31 19:23:10 -0800194 rc = of_property_read_u32(node,
195 "qcom,connector-temp-max-mdegc",
Harry Yang62045982017-02-14 12:31:47 -0800196 &chip->dt.connector_temp_max_mdegc);
Nicholas Troastae0ea542017-01-31 19:23:10 -0800197 if (rc < 0)
198 chip->dt.connector_temp_max_mdegc = 105000;
199
Nicholas Troast5d13c302016-05-12 18:01:06 -0700200 return 0;
201}
202
203/************************
204 * USB PSY REGISTRATION *
205 ************************/
206
207static enum power_supply_property smb138x_usb_props[] = {
208 POWER_SUPPLY_PROP_PRESENT,
209 POWER_SUPPLY_PROP_ONLINE,
210 POWER_SUPPLY_PROP_VOLTAGE_MIN,
211 POWER_SUPPLY_PROP_VOLTAGE_MAX,
212 POWER_SUPPLY_PROP_VOLTAGE_NOW,
213 POWER_SUPPLY_PROP_CURRENT_MAX,
214 POWER_SUPPLY_PROP_TYPE,
215 POWER_SUPPLY_PROP_TYPEC_MODE,
216 POWER_SUPPLY_PROP_TYPEC_POWER_ROLE,
217 POWER_SUPPLY_PROP_TYPEC_CC_ORIENTATION,
218};
219
220static int smb138x_usb_get_prop(struct power_supply *psy,
221 enum power_supply_property prop,
222 union power_supply_propval *val)
223{
224 struct smb138x *chip = power_supply_get_drvdata(psy);
225 struct smb_charger *chg = &chip->chg;
226 int rc = 0;
227
228 switch (prop) {
229 case POWER_SUPPLY_PROP_PRESENT:
230 rc = smblib_get_prop_usb_present(chg, val);
231 break;
232 case POWER_SUPPLY_PROP_ONLINE:
233 rc = smblib_get_prop_usb_online(chg, val);
234 break;
235 case POWER_SUPPLY_PROP_VOLTAGE_MIN:
236 val->intval = chg->voltage_min_uv;
237 break;
238 case POWER_SUPPLY_PROP_VOLTAGE_MAX:
239 val->intval = chg->voltage_max_uv;
240 break;
241 case POWER_SUPPLY_PROP_VOLTAGE_NOW:
242 rc = smblib_get_prop_usb_voltage_now(chg, val);
243 break;
244 case POWER_SUPPLY_PROP_CURRENT_MAX:
245 rc = smblib_get_prop_usb_current_max(chg, val);
246 break;
247 case POWER_SUPPLY_PROP_TYPE:
248 val->intval = chg->usb_psy_desc.type;
249 break;
250 case POWER_SUPPLY_PROP_TYPEC_MODE:
Nicholas Troaste1932e42017-04-12 12:38:18 -0700251 val->intval = chg->typec_mode;
Nicholas Troast5d13c302016-05-12 18:01:06 -0700252 break;
253 case POWER_SUPPLY_PROP_TYPEC_POWER_ROLE:
254 rc = smblib_get_prop_typec_power_role(chg, val);
255 break;
256 case POWER_SUPPLY_PROP_TYPEC_CC_ORIENTATION:
257 rc = smblib_get_prop_typec_cc_orientation(chg, val);
258 break;
259 default:
260 pr_err("get prop %d is not supported\n", prop);
261 return -EINVAL;
262 }
Nicholas Troast15dc0c82016-10-18 15:15:21 -0700263
Abhijeet Dharmapurikar773d4ab2016-09-09 12:00:19 -0700264 if (rc < 0) {
265 pr_debug("Couldn't get prop %d rc = %d\n", prop, rc);
266 return -ENODATA;
267 }
Nicholas Troast15dc0c82016-10-18 15:15:21 -0700268
269 return rc;
Nicholas Troast5d13c302016-05-12 18:01:06 -0700270}
271
272static int smb138x_usb_set_prop(struct power_supply *psy,
273 enum power_supply_property prop,
274 const union power_supply_propval *val)
275{
276 struct smb138x *chip = power_supply_get_drvdata(psy);
277 struct smb_charger *chg = &chip->chg;
278 int rc = 0;
279
280 switch (prop) {
281 case POWER_SUPPLY_PROP_VOLTAGE_MIN:
282 rc = smblib_set_prop_usb_voltage_min(chg, val);
283 break;
284 case POWER_SUPPLY_PROP_VOLTAGE_MAX:
285 rc = smblib_set_prop_usb_voltage_max(chg, val);
286 break;
287 case POWER_SUPPLY_PROP_CURRENT_MAX:
288 rc = smblib_set_prop_usb_current_max(chg, val);
289 break;
290 case POWER_SUPPLY_PROP_TYPEC_POWER_ROLE:
291 rc = smblib_set_prop_typec_power_role(chg, val);
292 break;
293 default:
294 pr_err("set prop %d is not supported\n", prop);
295 return -EINVAL;
296 }
297
298 return rc;
299}
300
301static int smb138x_usb_prop_is_writeable(struct power_supply *psy,
302 enum power_supply_property prop)
303{
304 switch (prop) {
305 case POWER_SUPPLY_PROP_TYPEC_POWER_ROLE:
306 return 1;
307 default:
308 break;
309 }
310
311 return 0;
312}
313
314static int smb138x_init_usb_psy(struct smb138x *chip)
315{
316 struct power_supply_config usb_cfg = {};
317 struct smb_charger *chg = &chip->chg;
318
319 chg->usb_psy_desc.name = "usb";
320 chg->usb_psy_desc.type = POWER_SUPPLY_TYPE_UNKNOWN;
321 chg->usb_psy_desc.properties = smb138x_usb_props;
322 chg->usb_psy_desc.num_properties = ARRAY_SIZE(smb138x_usb_props);
323 chg->usb_psy_desc.get_property = smb138x_usb_get_prop;
324 chg->usb_psy_desc.set_property = smb138x_usb_set_prop;
325 chg->usb_psy_desc.property_is_writeable = smb138x_usb_prop_is_writeable;
326
327 usb_cfg.drv_data = chip;
328 usb_cfg.of_node = chg->dev->of_node;
329 chg->usb_psy = devm_power_supply_register(chg->dev,
330 &chg->usb_psy_desc,
331 &usb_cfg);
332 if (IS_ERR(chg->usb_psy)) {
333 pr_err("Couldn't register USB power supply\n");
334 return PTR_ERR(chg->usb_psy);
335 }
336
337 return 0;
338}
339
340/*************************
341 * BATT PSY REGISTRATION *
342 *************************/
343
344static enum power_supply_property smb138x_batt_props[] = {
345 POWER_SUPPLY_PROP_INPUT_SUSPEND,
346 POWER_SUPPLY_PROP_STATUS,
347 POWER_SUPPLY_PROP_HEALTH,
348 POWER_SUPPLY_PROP_PRESENT,
349 POWER_SUPPLY_PROP_CHARGE_TYPE,
350 POWER_SUPPLY_PROP_CAPACITY,
Nicholas Troast6c9fbe02016-09-02 15:01:44 -0700351 POWER_SUPPLY_PROP_CHARGER_TEMP,
352 POWER_SUPPLY_PROP_CHARGER_TEMP_MAX,
Abhijeet Dharmapurikare3d988a2017-02-23 18:38:20 -0800353 POWER_SUPPLY_PROP_SET_SHIP_MODE,
Nicholas Troast5d13c302016-05-12 18:01:06 -0700354};
355
356static int smb138x_batt_get_prop(struct power_supply *psy,
357 enum power_supply_property prop,
358 union power_supply_propval *val)
359{
Abhijeet Dharmapurikar1407d662016-08-23 11:54:12 -0700360 struct smb138x *chip = power_supply_get_drvdata(psy);
361 struct smb_charger *chg = &chip->chg;
Nicholas Troast5d13c302016-05-12 18:01:06 -0700362 int rc = 0;
363
364 switch (prop) {
365 case POWER_SUPPLY_PROP_STATUS:
366 rc = smblib_get_prop_batt_status(chg, val);
367 break;
368 case POWER_SUPPLY_PROP_HEALTH:
369 rc = smblib_get_prop_batt_health(chg, val);
370 break;
371 case POWER_SUPPLY_PROP_PRESENT:
372 rc = smblib_get_prop_batt_present(chg, val);
373 break;
374 case POWER_SUPPLY_PROP_INPUT_SUSPEND:
375 rc = smblib_get_prop_input_suspend(chg, val);
376 break;
377 case POWER_SUPPLY_PROP_CHARGE_TYPE:
378 rc = smblib_get_prop_batt_charge_type(chg, val);
379 break;
380 case POWER_SUPPLY_PROP_CAPACITY:
381 rc = smblib_get_prop_batt_capacity(chg, val);
382 break;
Nicholas Troast6c9fbe02016-09-02 15:01:44 -0700383 case POWER_SUPPLY_PROP_CHARGER_TEMP:
Abhijeet Dharmapurikard8d82b12017-02-21 19:40:38 -0800384 rc = smb138x_get_prop_charger_temp(chip, val);
Nicholas Troast6c9fbe02016-09-02 15:01:44 -0700385 break;
386 case POWER_SUPPLY_PROP_CHARGER_TEMP_MAX:
387 rc = smblib_get_prop_charger_temp_max(chg, val);
388 break;
Abhijeet Dharmapurikare3d988a2017-02-23 18:38:20 -0800389 case POWER_SUPPLY_PROP_SET_SHIP_MODE:
390 /* Not in ship mode as long as device is active */
391 val->intval = 0;
392 break;
Nicholas Troast5d13c302016-05-12 18:01:06 -0700393 default:
Abhijeet Dharmapurikar773d4ab2016-09-09 12:00:19 -0700394 pr_err("batt power supply get prop %d not supported\n", prop);
Nicholas Troast5d13c302016-05-12 18:01:06 -0700395 return -EINVAL;
396 }
Nicholas Troast15dc0c82016-10-18 15:15:21 -0700397
Abhijeet Dharmapurikar773d4ab2016-09-09 12:00:19 -0700398 if (rc < 0) {
399 pr_debug("Couldn't get prop %d rc = %d\n", prop, rc);
400 return -ENODATA;
401 }
Nicholas Troast15dc0c82016-10-18 15:15:21 -0700402
403 return rc;
Nicholas Troast5d13c302016-05-12 18:01:06 -0700404}
405
406static int smb138x_batt_set_prop(struct power_supply *psy,
407 enum power_supply_property prop,
408 const union power_supply_propval *val)
409{
Abhijeet Dharmapurikar1407d662016-08-23 11:54:12 -0700410 struct smb138x *chip = power_supply_get_drvdata(psy);
411 struct smb_charger *chg = &chip->chg;
Nicholas Troast5d13c302016-05-12 18:01:06 -0700412 int rc = 0;
413
414 switch (prop) {
415 case POWER_SUPPLY_PROP_INPUT_SUSPEND:
416 rc = smblib_set_prop_input_suspend(chg, val);
417 break;
Abhijeet Dharmapurikar9e7e48c2016-08-23 12:55:49 -0700418 case POWER_SUPPLY_PROP_CAPACITY:
419 rc = smblib_set_prop_batt_capacity(chg, val);
420 break;
Abhijeet Dharmapurikare3d988a2017-02-23 18:38:20 -0800421 case POWER_SUPPLY_PROP_SET_SHIP_MODE:
422 /* Not in ship mode as long as the device is active */
423 if (!val->intval)
424 break;
425 rc = smblib_set_prop_ship_mode(chg, val);
426 break;
Nicholas Troast5d13c302016-05-12 18:01:06 -0700427 default:
Abhijeet Dharmapurikar9e7e48c2016-08-23 12:55:49 -0700428 pr_err("batt power supply set prop %d not supported\n", prop);
Nicholas Troast5d13c302016-05-12 18:01:06 -0700429 return -EINVAL;
430 }
431
432 return rc;
433}
434
435static int smb138x_batt_prop_is_writeable(struct power_supply *psy,
436 enum power_supply_property prop)
437{
438 switch (prop) {
439 case POWER_SUPPLY_PROP_INPUT_SUSPEND:
Abhijeet Dharmapurikar9e7e48c2016-08-23 12:55:49 -0700440 case POWER_SUPPLY_PROP_CAPACITY:
Nicholas Troast5d13c302016-05-12 18:01:06 -0700441 return 1;
442 default:
443 break;
444 }
445
446 return 0;
447}
448
449static const struct power_supply_desc batt_psy_desc = {
450 .name = "battery",
451 .type = POWER_SUPPLY_TYPE_BATTERY,
452 .properties = smb138x_batt_props,
453 .num_properties = ARRAY_SIZE(smb138x_batt_props),
454 .get_property = smb138x_batt_get_prop,
455 .set_property = smb138x_batt_set_prop,
456 .property_is_writeable = smb138x_batt_prop_is_writeable,
457};
458
459static int smb138x_init_batt_psy(struct smb138x *chip)
460{
461 struct power_supply_config batt_cfg = {};
462 struct smb_charger *chg = &chip->chg;
463 int rc = 0;
464
465 batt_cfg.drv_data = chip;
466 batt_cfg.of_node = chg->dev->of_node;
467 chg->batt_psy = devm_power_supply_register(chg->dev,
468 &batt_psy_desc,
469 &batt_cfg);
470 if (IS_ERR(chg->batt_psy)) {
471 pr_err("Couldn't register battery power supply\n");
472 return PTR_ERR(chg->batt_psy);
473 }
474
475 return rc;
476}
477
478/*****************************
479 * PARALLEL PSY REGISTRATION *
480 *****************************/
481
Nicholas Troastc8434ac2017-02-14 16:11:56 -0800482static int smb138x_get_prop_connector_health(struct smb138x *chip)
483{
484 struct smb_charger *chg = &chip->chg;
485 int rc, lb_mdegc, ub_mdegc, rst_mdegc, connector_mdegc;
486
487 if (!chg->iio.connector_temp_chan ||
488 PTR_ERR(chg->iio.connector_temp_chan) == -EPROBE_DEFER)
489 chg->iio.connector_temp_chan = iio_channel_get(chg->dev,
490 "connector_temp");
491
492 if (IS_ERR(chg->iio.connector_temp_chan))
493 return POWER_SUPPLY_HEALTH_UNKNOWN;
494
495 rc = iio_read_channel_processed(chg->iio.connector_temp_thr1_chan,
496 &lb_mdegc);
497 if (rc < 0) {
498 pr_err("Couldn't read connector lower bound rc=%d\n", rc);
499 return POWER_SUPPLY_HEALTH_UNKNOWN;
500 }
501
502 rc = iio_read_channel_processed(chg->iio.connector_temp_thr2_chan,
503 &ub_mdegc);
504 if (rc < 0) {
505 pr_err("Couldn't read connector upper bound rc=%d\n", rc);
506 return POWER_SUPPLY_HEALTH_UNKNOWN;
507 }
508
509 rc = iio_read_channel_processed(chg->iio.connector_temp_thr3_chan,
510 &rst_mdegc);
511 if (rc < 0) {
512 pr_err("Couldn't read connector reset bound rc=%d\n", rc);
513 return POWER_SUPPLY_HEALTH_UNKNOWN;
514 }
515
516 rc = iio_read_channel_processed(chg->iio.connector_temp_chan,
517 &connector_mdegc);
518 if (rc < 0) {
519 pr_err("Couldn't read connector temperature rc=%d\n", rc);
520 return POWER_SUPPLY_HEALTH_UNKNOWN;
521 }
522
523 if (connector_mdegc < lb_mdegc)
524 return POWER_SUPPLY_HEALTH_COOL;
525 else if (connector_mdegc < ub_mdegc)
526 return POWER_SUPPLY_HEALTH_WARM;
527 else if (connector_mdegc < rst_mdegc)
528 return POWER_SUPPLY_HEALTH_HOT;
529
530 return POWER_SUPPLY_HEALTH_OVERHEAT;
531}
532
Nicholas Troast5d13c302016-05-12 18:01:06 -0700533static enum power_supply_property smb138x_parallel_props[] = {
Nicholas Troast4fd89b772016-11-04 13:42:30 -0700534 POWER_SUPPLY_PROP_CHARGE_TYPE,
Nicholas Troaste63b0432016-07-27 11:29:30 -0700535 POWER_SUPPLY_PROP_CHARGING_ENABLED,
536 POWER_SUPPLY_PROP_PIN_ENABLED,
Nicholas Troast5d13c302016-05-12 18:01:06 -0700537 POWER_SUPPLY_PROP_INPUT_SUSPEND,
Harry Yang5827ba12017-03-23 17:34:46 -0700538 POWER_SUPPLY_PROP_INPUT_CURRENT_LIMITED,
Abhijeet Dharmapurikar0529c432017-04-04 17:29:36 -0700539 POWER_SUPPLY_PROP_CURRENT_MAX,
Abhijeet Dharmapurikar0529c432017-04-04 17:29:36 -0700540 POWER_SUPPLY_PROP_VOLTAGE_MAX,
541 POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX,
Abhijeet Dharmapurikarbb7cf2a2017-05-02 18:05:48 -0700542 POWER_SUPPLY_PROP_CURRENT_NOW,
543 POWER_SUPPLY_PROP_CHARGER_TEMP,
544 POWER_SUPPLY_PROP_CHARGER_TEMP_MAX,
Abhijeet Dharmapurikar0529c432017-04-04 17:29:36 -0700545 POWER_SUPPLY_PROP_MODEL_NAME,
546 POWER_SUPPLY_PROP_PARALLEL_MODE,
547 POWER_SUPPLY_PROP_CONNECTOR_HEALTH,
548 POWER_SUPPLY_PROP_SET_SHIP_MODE,
Nicholas Troast5d13c302016-05-12 18:01:06 -0700549};
550
551static int smb138x_parallel_get_prop(struct power_supply *psy,
552 enum power_supply_property prop,
553 union power_supply_propval *val)
554{
Abhijeet Dharmapurikar1407d662016-08-23 11:54:12 -0700555 struct smb138x *chip = power_supply_get_drvdata(psy);
556 struct smb_charger *chg = &chip->chg;
Nicholas Troast5d13c302016-05-12 18:01:06 -0700557 int rc = 0;
Nicholas Troaste63b0432016-07-27 11:29:30 -0700558 u8 temp;
Nicholas Troast5d13c302016-05-12 18:01:06 -0700559
560 switch (prop) {
Nicholas Troast4fd89b772016-11-04 13:42:30 -0700561 case POWER_SUPPLY_PROP_CHARGE_TYPE:
562 rc = smblib_get_prop_batt_charge_type(chg, val);
563 break;
Nicholas Troaste63b0432016-07-27 11:29:30 -0700564 case POWER_SUPPLY_PROP_CHARGING_ENABLED:
565 rc = smblib_read(chg, BATTERY_CHARGER_STATUS_5_REG,
566 &temp);
567 if (rc >= 0)
568 val->intval = (bool)(temp & CHARGING_ENABLE_BIT);
569 break;
570 case POWER_SUPPLY_PROP_PIN_ENABLED:
571 rc = smblib_read(chg, BATTERY_CHARGER_STATUS_5_REG,
572 &temp);
573 if (rc >= 0)
574 val->intval = !(temp & DISABLE_CHARGING_BIT);
575 break;
Nicholas Troast5d13c302016-05-12 18:01:06 -0700576 case POWER_SUPPLY_PROP_INPUT_SUSPEND:
Abhijeet Dharmapurikar0e1c73b2017-05-02 18:04:54 -0700577 rc = smblib_get_usb_suspend(chg, &val->intval);
Nicholas Troast5d13c302016-05-12 18:01:06 -0700578 break;
Harry Yang5827ba12017-03-23 17:34:46 -0700579 case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMITED:
Abhijeet Dharmapurikar20acdf12017-04-03 15:27:21 -0700580 if ((chip->dt.pl_mode == POWER_SUPPLY_PL_USBIN_USBIN)
581 || (chip->dt.pl_mode == POWER_SUPPLY_PL_USBIN_USBIN_EXT))
Harry Yang5827ba12017-03-23 17:34:46 -0700582 rc = smblib_get_prop_input_current_limited(chg, val);
583 else
584 val->intval = 0;
585 break;
Abhijeet Dharmapurikarbb7cf2a2017-05-02 18:05:48 -0700586 case POWER_SUPPLY_PROP_CURRENT_MAX:
587 if ((chip->dt.pl_mode == POWER_SUPPLY_PL_USBIN_USBIN)
588 || (chip->dt.pl_mode == POWER_SUPPLY_PL_USBIN_USBIN_EXT))
589 rc = smblib_get_charge_param(chg, &chg->param.usb_icl,
590 &val->intval);
591 else
592 val->intval = 0;
593 break;
Nicholas Troast5d13c302016-05-12 18:01:06 -0700594 case POWER_SUPPLY_PROP_VOLTAGE_MAX:
595 rc = smblib_get_charge_param(chg, &chg->param.fv, &val->intval);
596 break;
Abhijeet Dharmapurikara8bd6f02017-01-30 15:43:04 -0800597 case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX:
Nicholas Troast5d13c302016-05-12 18:01:06 -0700598 rc = smblib_get_charge_param(chg, &chg->param.fcc,
599 &val->intval);
600 break;
Abhijeet Dharmapurikarbb7cf2a2017-05-02 18:05:48 -0700601 case POWER_SUPPLY_PROP_CURRENT_NOW:
602 rc = smblib_get_prop_slave_current_now(chg, val);
603 break;
604 case POWER_SUPPLY_PROP_CHARGER_TEMP:
605 rc = smb138x_get_prop_charger_temp(chip, val);
606 break;
607 case POWER_SUPPLY_PROP_CHARGER_TEMP_MAX:
608 rc = smblib_get_prop_charger_temp_max(chg, val);
609 break;
Abhijeet Dharmapurikarae1aa822017-01-06 12:16:49 -0800610 case POWER_SUPPLY_PROP_MODEL_NAME:
Abhijeet Dharmapurikarbb7cf2a2017-05-02 18:05:48 -0700611 val->strval = "smb138x";
Abhijeet Dharmapurikarae1aa822017-01-06 12:16:49 -0800612 break;
Abhijeet Dharmapurikara8bd6f02017-01-30 15:43:04 -0800613 case POWER_SUPPLY_PROP_PARALLEL_MODE:
Harry Yang81c5fc02017-03-14 12:23:01 -0700614 val->intval = chip->dt.pl_mode;
Abhijeet Dharmapurikara8bd6f02017-01-30 15:43:04 -0800615 break;
Nicholas Troast7fdbd2e2017-02-08 10:47:37 -0800616 case POWER_SUPPLY_PROP_CONNECTOR_HEALTH:
Abhijeet Dharmapurikarbb7cf2a2017-05-02 18:05:48 -0700617 val->intval = smb138x_get_prop_connector_health(chip);
Nicholas Troastb021dd92017-01-31 18:43:38 -0800618 break;
Abhijeet Dharmapurikare3d988a2017-02-23 18:38:20 -0800619 case POWER_SUPPLY_PROP_SET_SHIP_MODE:
620 /* Not in ship mode as long as device is active */
621 val->intval = 0;
622 break;
Nicholas Troast5d13c302016-05-12 18:01:06 -0700623 default:
624 pr_err("parallel power supply get prop %d not supported\n",
625 prop);
626 return -EINVAL;
627 }
Nicholas Troast15dc0c82016-10-18 15:15:21 -0700628
Abhijeet Dharmapurikar773d4ab2016-09-09 12:00:19 -0700629 if (rc < 0) {
630 pr_debug("Couldn't get prop %d rc = %d\n", prop, rc);
631 return -ENODATA;
632 }
Nicholas Troast15dc0c82016-10-18 15:15:21 -0700633
634 return rc;
635}
636
Abhijeet Dharmapurikar0e1c73b2017-05-02 18:04:54 -0700637static int smb138x_set_parallel_suspend(struct smb138x *chip, bool suspend)
Nicholas Troast15dc0c82016-10-18 15:15:21 -0700638{
639 struct smb_charger *chg = &chip->chg;
640 int rc = 0;
641
642 rc = smblib_masked_write(chg, WD_CFG_REG, WDOG_TIMER_EN_BIT,
Abhijeet Dharmapurikar0e1c73b2017-05-02 18:04:54 -0700643 suspend ? 0 : WDOG_TIMER_EN_BIT);
Nicholas Troast15dc0c82016-10-18 15:15:21 -0700644 if (rc < 0) {
645 pr_err("Couldn't %s watchdog rc=%d\n",
Abhijeet Dharmapurikar0e1c73b2017-05-02 18:04:54 -0700646 suspend ? "disable" : "enable", rc);
647 suspend = true;
Nicholas Troast15dc0c82016-10-18 15:15:21 -0700648 }
649
Abhijeet Dharmapurikar0e1c73b2017-05-02 18:04:54 -0700650 rc = smblib_masked_write(chg, USBIN_CMD_IL_REG, USBIN_SUSPEND_BIT,
651 suspend ? USBIN_SUSPEND_BIT : 0);
Nicholas Troast15dc0c82016-10-18 15:15:21 -0700652 if (rc < 0) {
Abhijeet Dharmapurikar0e1c73b2017-05-02 18:04:54 -0700653 pr_err("Couldn't %s parallel charger rc=%d\n",
654 suspend ? "suspend" : "resume", rc);
Nicholas Troast15dc0c82016-10-18 15:15:21 -0700655 return rc;
656 }
657
Abhijeet Dharmapurikar0e1c73b2017-05-02 18:04:54 -0700658 return rc;
Nicholas Troast5d13c302016-05-12 18:01:06 -0700659}
660
661static int smb138x_parallel_set_prop(struct power_supply *psy,
662 enum power_supply_property prop,
663 const union power_supply_propval *val)
664{
Abhijeet Dharmapurikar1407d662016-08-23 11:54:12 -0700665 struct smb138x *chip = power_supply_get_drvdata(psy);
666 struct smb_charger *chg = &chip->chg;
Nicholas Troast5d13c302016-05-12 18:01:06 -0700667 int rc = 0;
668
669 switch (prop) {
670 case POWER_SUPPLY_PROP_INPUT_SUSPEND:
Abhijeet Dharmapurikar0e1c73b2017-05-02 18:04:54 -0700671 rc = smb138x_set_parallel_suspend(chip, (bool)val->intval);
Nicholas Troast5d13c302016-05-12 18:01:06 -0700672 break;
Harry Yang5827ba12017-03-23 17:34:46 -0700673 case POWER_SUPPLY_PROP_CURRENT_MAX:
Abhijeet Dharmapurikar20acdf12017-04-03 15:27:21 -0700674 if ((chip->dt.pl_mode == POWER_SUPPLY_PL_USBIN_USBIN)
675 || (chip->dt.pl_mode == POWER_SUPPLY_PL_USBIN_USBIN_EXT))
Harry Yang5827ba12017-03-23 17:34:46 -0700676 rc = smblib_set_charge_param(chg, &chg->param.usb_icl,
677 val->intval);
678 break;
Nicholas Troast5d13c302016-05-12 18:01:06 -0700679 case POWER_SUPPLY_PROP_VOLTAGE_MAX:
680 rc = smblib_set_charge_param(chg, &chg->param.fv, val->intval);
681 break;
Abhijeet Dharmapurikara8bd6f02017-01-30 15:43:04 -0800682 case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX:
Nicholas Troast5d13c302016-05-12 18:01:06 -0700683 rc = smblib_set_charge_param(chg, &chg->param.fcc, val->intval);
684 break;
Abhijeet Dharmapurikare3d988a2017-02-23 18:38:20 -0800685 case POWER_SUPPLY_PROP_SET_SHIP_MODE:
686 /* Not in ship mode as long as the device is active */
687 if (!val->intval)
688 break;
689 rc = smblib_set_prop_ship_mode(chg, val);
690 break;
Nicholas Troast5d13c302016-05-12 18:01:06 -0700691 default:
Abhijeet Dharmapurikare9fd08d2017-02-27 11:05:28 -0800692 pr_debug("parallel power supply set prop %d not supported\n",
Nicholas Troast5d13c302016-05-12 18:01:06 -0700693 prop);
694 return -EINVAL;
695 }
696
697 return rc;
698}
699
700static int smb138x_parallel_prop_is_writeable(struct power_supply *psy,
701 enum power_supply_property prop)
702{
703 return 0;
704}
705
Abhijeet Dharmapurikarbb7cf2a2017-05-02 18:05:48 -0700706static const struct power_supply_desc parallel_psy_desc = {
Nicholas Troast5d13c302016-05-12 18:01:06 -0700707 .name = "parallel",
Abhijeet Dharmapurikar9a3a6c32017-01-06 18:27:29 -0800708 .type = POWER_SUPPLY_TYPE_PARALLEL,
Nicholas Troast5d13c302016-05-12 18:01:06 -0700709 .properties = smb138x_parallel_props,
710 .num_properties = ARRAY_SIZE(smb138x_parallel_props),
711 .get_property = smb138x_parallel_get_prop,
712 .set_property = smb138x_parallel_set_prop,
713 .property_is_writeable = smb138x_parallel_prop_is_writeable,
714};
715
716static int smb138x_init_parallel_psy(struct smb138x *chip)
717{
718 struct power_supply_config parallel_cfg = {};
719 struct smb_charger *chg = &chip->chg;
720
721 parallel_cfg.drv_data = chip;
722 parallel_cfg.of_node = chg->dev->of_node;
723 chip->parallel_psy = devm_power_supply_register(chg->dev,
724 &parallel_psy_desc,
725 &parallel_cfg);
726 if (IS_ERR(chip->parallel_psy)) {
727 pr_err("Couldn't register parallel power supply\n");
728 return PTR_ERR(chip->parallel_psy);
729 }
730
731 return 0;
732}
733
734/******************************
735 * VBUS REGULATOR REGISTRATION *
736 ******************************/
737
738struct regulator_ops smb138x_vbus_reg_ops = {
739 .enable = smblib_vbus_regulator_enable,
740 .disable = smblib_vbus_regulator_disable,
741 .is_enabled = smblib_vbus_regulator_is_enabled,
742};
743
744static int smb138x_init_vbus_regulator(struct smb138x *chip)
745{
746 struct smb_charger *chg = &chip->chg;
747 struct regulator_config cfg = {};
748 int rc = 0;
749
750 chg->vbus_vreg = devm_kzalloc(chg->dev, sizeof(*chg->vbus_vreg),
751 GFP_KERNEL);
752 if (!chg->vbus_vreg)
753 return -ENOMEM;
754
755 cfg.dev = chg->dev;
756 cfg.driver_data = chip;
757
758 chg->vbus_vreg->rdesc.owner = THIS_MODULE;
759 chg->vbus_vreg->rdesc.type = REGULATOR_VOLTAGE;
760 chg->vbus_vreg->rdesc.ops = &smb138x_vbus_reg_ops;
761 chg->vbus_vreg->rdesc.of_match = "qcom,smb138x-vbus";
762 chg->vbus_vreg->rdesc.name = "qcom,smb138x-vbus";
763
764 chg->vbus_vreg->rdev = devm_regulator_register(chg->dev,
765 &chg->vbus_vreg->rdesc, &cfg);
766 if (IS_ERR(chg->vbus_vreg->rdev)) {
767 rc = PTR_ERR(chg->vbus_vreg->rdev);
768 chg->vbus_vreg->rdev = NULL;
769 if (rc != -EPROBE_DEFER)
770 pr_err("Couldn't register VBUS regualtor rc=%d\n", rc);
771 }
772
773 return rc;
774}
775
776/******************************
777 * VCONN REGULATOR REGISTRATION *
778 ******************************/
779
780struct regulator_ops smb138x_vconn_reg_ops = {
781 .enable = smblib_vconn_regulator_enable,
782 .disable = smblib_vconn_regulator_disable,
783 .is_enabled = smblib_vconn_regulator_is_enabled,
784};
785
786static int smb138x_init_vconn_regulator(struct smb138x *chip)
787{
788 struct smb_charger *chg = &chip->chg;
789 struct regulator_config cfg = {};
790 int rc = 0;
791
792 chg->vconn_vreg = devm_kzalloc(chg->dev, sizeof(*chg->vconn_vreg),
793 GFP_KERNEL);
794 if (!chg->vconn_vreg)
795 return -ENOMEM;
796
797 cfg.dev = chg->dev;
798 cfg.driver_data = chip;
799
800 chg->vconn_vreg->rdesc.owner = THIS_MODULE;
801 chg->vconn_vreg->rdesc.type = REGULATOR_VOLTAGE;
802 chg->vconn_vreg->rdesc.ops = &smb138x_vconn_reg_ops;
803 chg->vconn_vreg->rdesc.of_match = "qcom,smb138x-vconn";
804 chg->vconn_vreg->rdesc.name = "qcom,smb138x-vconn";
805
806 chg->vconn_vreg->rdev = devm_regulator_register(chg->dev,
807 &chg->vconn_vreg->rdesc, &cfg);
808 if (IS_ERR(chg->vconn_vreg->rdev)) {
809 rc = PTR_ERR(chg->vconn_vreg->rdev);
810 chg->vconn_vreg->rdev = NULL;
811 if (rc != -EPROBE_DEFER)
812 pr_err("Couldn't register VCONN regualtor rc=%d\n", rc);
813 }
814
815 return rc;
816}
817
818/***************************
819 * HARDWARE INITIALIZATION *
820 ***************************/
821
Nicholas Troastae0ea542017-01-31 19:23:10 -0800822#define MDEGC_3 3000
823#define MDEGC_15 15000
Nicholas Troastdc6e59a2017-01-30 19:22:22 -0800824static int smb138x_init_slave_hw(struct smb138x *chip)
825{
826 struct smb_charger *chg = &chip->chg;
827 int rc;
828
829 if (chip->wa_flags & OOB_COMP_WA_BIT) {
830 rc = smblib_masked_write(chg, SMB2CHG_MISC_ENG_SDCDC_CFG2,
831 ENG_SDCDC_SEL_OOB_VTH_BIT,
832 ENG_SDCDC_SEL_OOB_VTH_BIT);
833 if (rc < 0) {
834 pr_err("Couldn't configure the OOB comp threshold rc = %d\n",
835 rc);
836 return rc;
837 }
838
839 rc = smblib_masked_write(chg, SMB2CHG_MISC_ENG_SDCDC_CFG6,
840 DEAD_TIME_MASK, HIGH_DEAD_TIME_MASK);
841 if (rc < 0) {
842 pr_err("Couldn't configure the sdcdc cfg 6 reg rc = %d\n",
843 rc);
844 return rc;
845 }
846 }
847
848 /* enable watchdog bark and bite interrupts, and disable the watchdog */
849 rc = smblib_masked_write(chg, WD_CFG_REG, WDOG_TIMER_EN_BIT
850 | WDOG_TIMER_EN_ON_PLUGIN_BIT | BITE_WDOG_INT_EN_BIT
851 | BARK_WDOG_INT_EN_BIT,
852 BITE_WDOG_INT_EN_BIT | BARK_WDOG_INT_EN_BIT);
853 if (rc < 0) {
854 pr_err("Couldn't configure the watchdog rc=%d\n", rc);
855 return rc;
856 }
857
858 /* disable charging when watchdog bites */
859 rc = smblib_masked_write(chg, SNARL_BARK_BITE_WD_CFG_REG,
860 BITE_WDOG_DISABLE_CHARGING_CFG_BIT,
861 BITE_WDOG_DISABLE_CHARGING_CFG_BIT);
862 if (rc < 0) {
863 pr_err("Couldn't configure the watchdog bite rc=%d\n", rc);
864 return rc;
865 }
866
Abhijeet Dharmapurikar0e1c73b2017-05-02 18:04:54 -0700867 /* suspend parallel charging */
868 rc = smb138x_set_parallel_suspend(chip, true);
Nicholas Troastdc6e59a2017-01-30 19:22:22 -0800869 if (rc < 0) {
Abhijeet Dharmapurikar0e1c73b2017-05-02 18:04:54 -0700870 pr_err("Couldn't suspend parallel charging rc=%d\n", rc);
Nicholas Troastdc6e59a2017-01-30 19:22:22 -0800871 return rc;
872 }
873
874 /* initialize FCC to 0 */
875 rc = smblib_set_charge_param(chg, &chg->param.fcc, 0);
876 if (rc < 0) {
877 pr_err("Couldn't set 0 FCC rc=%d\n", rc);
878 return rc;
879 }
880
Abhijeet Dharmapurikar0e1c73b2017-05-02 18:04:54 -0700881 /* enable the charging path */
882 rc = smblib_masked_write(chg, CHARGING_ENABLE_CMD_REG,
883 CHARGING_ENABLE_CMD_BIT,
884 CHARGING_ENABLE_CMD_BIT);
885 if (rc < 0) {
886 pr_err("Couldn't enable charging rc=%d\n", rc);
887 return rc;
888 }
889
890 /* configure charge enable for software control; active high */
891 rc = smblib_masked_write(chg, CHGR_CFG2_REG,
892 CHG_EN_POLARITY_BIT | CHG_EN_SRC_BIT, 0);
893 if (rc < 0) {
894 pr_err("Couldn't configure charge enable source rc=%d\n",
895 rc);
896 return rc;
897 }
898
Nicholas Troastdc6e59a2017-01-30 19:22:22 -0800899 /* enable parallel current sensing */
900 rc = smblib_masked_write(chg, CFG_REG,
901 VCHG_EN_CFG_BIT, VCHG_EN_CFG_BIT);
902 if (rc < 0) {
903 pr_err("Couldn't enable parallel current sensing rc=%d\n",
904 rc);
905 return rc;
906 }
907
908 /* enable stacked diode */
909 rc = smblib_write(chg, SMB2CHG_DC_TM_SREFGEN, STACKED_DIODE_EN_BIT);
910 if (rc < 0) {
911 pr_err("Couldn't enable stacked diode rc=%d\n", rc);
912 return rc;
913 }
914
915 /* initialize charger temperature threshold */
916 rc = iio_write_channel_processed(chg->iio.temp_max_chan,
917 chip->dt.chg_temp_max_mdegc);
918 if (rc < 0) {
919 pr_err("Couldn't set charger temp threshold rc=%d\n", rc);
920 return rc;
921 }
922
Nicholas Troastae0ea542017-01-31 19:23:10 -0800923 rc = iio_write_channel_processed(chg->iio.connector_temp_thr1_chan,
924 chip->dt.connector_temp_max_mdegc);
925 if (rc < 0) {
926 pr_err("Couldn't set connector temp threshold1 rc=%d\n", rc);
927 return rc;
928 }
929
930 rc = iio_write_channel_processed(chg->iio.connector_temp_thr2_chan,
931 chip->dt.connector_temp_max_mdegc + MDEGC_3);
932 if (rc < 0) {
933 pr_err("Couldn't set connector temp threshold2 rc=%d\n", rc);
934 return rc;
935 }
936
937 rc = iio_write_channel_processed(chg->iio.connector_temp_thr3_chan,
938 chip->dt.connector_temp_max_mdegc + MDEGC_15);
939 if (rc < 0) {
940 pr_err("Couldn't set connector temp threshold3 rc=%d\n", rc);
941 return rc;
942 }
Nicholas Troast1bcb8a52017-02-01 13:08:06 -0800943
944 rc = smblib_write(chg, THERMREG_SRC_CFG_REG,
945 THERMREG_SKIN_ADC_SRC_EN_BIT);
946 if (rc < 0) {
947 pr_err("Couldn't enable connector thermreg source rc=%d\n", rc);
948 return rc;
949 }
950
Nicholas Troastdc6e59a2017-01-30 19:22:22 -0800951 return 0;
952}
953
Nicholas Troast5d13c302016-05-12 18:01:06 -0700954static int smb138x_init_hw(struct smb138x *chip)
955{
956 struct smb_charger *chg = &chip->chg;
Nicholas Troast15dc0c82016-10-18 15:15:21 -0700957 int rc = 0;
Nicholas Troast5d13c302016-05-12 18:01:06 -0700958
959 /* votes must be cast before configuring software control */
Nicholas Troast5d13c302016-05-12 18:01:06 -0700960 vote(chg->dc_suspend_votable,
961 DEFAULT_VOTER, chip->dt.suspend_input, 0);
962 vote(chg->fcc_votable,
963 DEFAULT_VOTER, true, chip->dt.fcc_ua);
964 vote(chg->usb_icl_votable,
Harry Yang631b99e2016-11-17 11:24:25 -0800965 DCP_VOTER, true, chip->dt.usb_icl_ua);
Nicholas Troast5d13c302016-05-12 18:01:06 -0700966 vote(chg->dc_icl_votable,
967 DEFAULT_VOTER, true, chip->dt.dc_icl_ua);
968
Harry Yang631b99e2016-11-17 11:24:25 -0800969 chg->dcp_icl_ua = chip->dt.usb_icl_ua;
970
Abhijeet Dharmapurikare9fd08d2017-02-27 11:05:28 -0800971 /* configure to a fixed 700khz freq to avoid tdie errors */
972 rc = smblib_set_charge_param(chg, &chg->param.freq_buck, 700);
973 if (rc < 0) {
974 pr_err("Couldn't configure 700Khz switch freq rc=%d\n", rc);
975 return rc;
976 }
977
Nicholas Troast5d13c302016-05-12 18:01:06 -0700978 /* configure charge enable for software control; active high */
979 rc = smblib_masked_write(chg, CHGR_CFG2_REG,
980 CHG_EN_POLARITY_BIT | CHG_EN_SRC_BIT, 0);
981 if (rc < 0) {
Nicholas Troastdc6e59a2017-01-30 19:22:22 -0800982 pr_err("Couldn't configure charge enable source rc=%d\n", rc);
Nicholas Troast5d13c302016-05-12 18:01:06 -0700983 return rc;
984 }
985
986 /* enable the charging path */
Abhijeet Dharmapurikaree54de02016-07-08 14:51:47 -0700987 rc = vote(chg->chg_disable_votable, DEFAULT_VOTER, false, 0);
Nicholas Troast5d13c302016-05-12 18:01:06 -0700988 if (rc < 0) {
Nicholas Troastdc6e59a2017-01-30 19:22:22 -0800989 pr_err("Couldn't enable charging rc=%d\n", rc);
Nicholas Troast5d13c302016-05-12 18:01:06 -0700990 return rc;
991 }
992
993 /*
994 * trigger the usb-typec-change interrupt only when the CC state
995 * changes, or there was a VBUS error
996 */
997 rc = smblib_write(chg, TYPE_C_INTRPT_ENB_REG,
998 TYPEC_CCSTATE_CHANGE_INT_EN_BIT
999 | TYPEC_VBUS_ERROR_INT_EN_BIT);
1000 if (rc < 0) {
Nicholas Troastdc6e59a2017-01-30 19:22:22 -08001001 pr_err("Couldn't configure Type-C interrupts rc=%d\n", rc);
Nicholas Troast5d13c302016-05-12 18:01:06 -07001002 return rc;
1003 }
1004
1005 /* configure VCONN for software control */
1006 rc = smblib_masked_write(chg, TYPE_C_INTRPT_ENB_SOFTWARE_CTRL_REG,
1007 VCONN_EN_SRC_BIT | VCONN_EN_VALUE_BIT,
1008 VCONN_EN_SRC_BIT);
1009 if (rc < 0) {
Nicholas Troastdc6e59a2017-01-30 19:22:22 -08001010 pr_err("Couldn't configure VCONN for SW control rc=%d\n", rc);
Nicholas Troast5d13c302016-05-12 18:01:06 -07001011 return rc;
1012 }
1013
1014 /* configure VBUS for software control */
1015 rc = smblib_masked_write(chg, OTG_CFG_REG, OTG_EN_SRC_CFG_BIT, 0);
1016 if (rc < 0) {
Nicholas Troastdc6e59a2017-01-30 19:22:22 -08001017 pr_err("Couldn't configure VBUS for SW control rc=%d\n", rc);
Nicholas Troast5d13c302016-05-12 18:01:06 -07001018 return rc;
1019 }
1020
1021 /* configure power role for dual-role */
1022 rc = smblib_masked_write(chg, TYPE_C_INTRPT_ENB_SOFTWARE_CTRL_REG,
1023 TYPEC_POWER_ROLE_CMD_MASK, 0);
1024 if (rc < 0) {
Nicholas Troastdc6e59a2017-01-30 19:22:22 -08001025 pr_err("Couldn't configure power role for DRP rc=%d\n", rc);
Nicholas Troast5d13c302016-05-12 18:01:06 -07001026 return rc;
1027 }
1028
Abhijeet Dharmapurikarb3022c82016-08-16 16:32:38 -07001029 if (chip->wa_flags & OOB_COMP_WA_BIT) {
1030 rc = smblib_masked_write(chg, SMB2CHG_MISC_ENG_SDCDC_CFG2,
1031 ENG_SDCDC_SEL_OOB_VTH_BIT,
1032 ENG_SDCDC_SEL_OOB_VTH_BIT);
1033 if (rc < 0) {
Nicholas Troastdc6e59a2017-01-30 19:22:22 -08001034 pr_err("Couldn't configure the OOB comp threshold rc = %d\n",
1035 rc);
Abhijeet Dharmapurikarb3022c82016-08-16 16:32:38 -07001036 return rc;
1037 }
Abhijeet Dharmapurikardc5b06f2016-08-18 14:45:59 -07001038
1039 rc = smblib_masked_write(chg, SMB2CHG_MISC_ENG_SDCDC_CFG6,
1040 DEAD_TIME_MASK, HIGH_DEAD_TIME_MASK);
1041 if (rc < 0) {
Nicholas Troastdc6e59a2017-01-30 19:22:22 -08001042 pr_err("Couldn't configure the sdcdc cfg 6 reg rc = %d\n",
1043 rc);
Abhijeet Dharmapurikardc5b06f2016-08-18 14:45:59 -07001044 return rc;
1045 }
Abhijeet Dharmapurikarb3022c82016-08-16 16:32:38 -07001046 }
1047
Nicholas Troast5d13c302016-05-12 18:01:06 -07001048 return rc;
1049}
1050
Abhijeet Dharmapurikarb3022c82016-08-16 16:32:38 -07001051static int smb138x_setup_wa_flags(struct smb138x *chip)
1052{
Abhijeet Dharmapurikarbb7cf2a2017-05-02 18:05:48 -07001053 struct pmic_revid_data *pmic_rev_id;
Abhijeet Dharmapurikarb3022c82016-08-16 16:32:38 -07001054 struct device_node *revid_dev_node;
1055
1056 revid_dev_node = of_parse_phandle(chip->chg.dev->of_node,
1057 "qcom,pmic-revid", 0);
1058 if (!revid_dev_node) {
1059 pr_err("Missing qcom,pmic-revid property\n");
1060 return -EINVAL;
1061 }
1062
Abhijeet Dharmapurikarbb7cf2a2017-05-02 18:05:48 -07001063 pmic_rev_id = get_revid_data(revid_dev_node);
1064 if (IS_ERR_OR_NULL(pmic_rev_id)) {
Abhijeet Dharmapurikarb3022c82016-08-16 16:32:38 -07001065 /*
1066 * the revid peripheral must be registered, any failure
1067 * here only indicates that the rev-id module has not
1068 * probed yet.
1069 */
1070 return -EPROBE_DEFER;
1071 }
1072
Abhijeet Dharmapurikarbb7cf2a2017-05-02 18:05:48 -07001073 switch (pmic_rev_id->pmic_subtype) {
Abhijeet Dharmapurikarb3022c82016-08-16 16:32:38 -07001074 case SMB1381_SUBTYPE:
Abhijeet Dharmapurikarbb7cf2a2017-05-02 18:05:48 -07001075 if (pmic_rev_id->rev4 < 2) /* SMB1381 rev 1.0 */
Abhijeet Dharmapurikarb3022c82016-08-16 16:32:38 -07001076 chip->wa_flags |= OOB_COMP_WA_BIT;
1077 break;
1078 default:
1079 pr_err("PMIC subtype %d not supported\n",
Abhijeet Dharmapurikarbb7cf2a2017-05-02 18:05:48 -07001080 pmic_rev_id->pmic_subtype);
Abhijeet Dharmapurikarb3022c82016-08-16 16:32:38 -07001081 return -EINVAL;
1082 }
1083
1084 return 0;
1085}
1086
Nicholas Troast5d13c302016-05-12 18:01:06 -07001087/****************************
1088 * DETERMINE INITIAL STATUS *
1089 ****************************/
1090
Nicholas Troast21825e32016-12-16 13:24:43 -08001091static irqreturn_t smb138x_handle_temperature_change(int irq, void *data)
1092{
1093 struct smb_irq_data *irq_data = data;
1094 struct smb138x *chip = irq_data->parent_data;
1095
1096 power_supply_changed(chip->parallel_psy);
1097 return IRQ_HANDLED;
1098}
1099
1100static int smb138x_determine_initial_slave_status(struct smb138x *chip)
1101{
1102 struct smb_irq_data irq_data = {chip, "determine-initial-status"};
1103
1104 smb138x_handle_temperature_change(0, &irq_data);
1105 return 0;
1106}
1107
Nicholas Troast5d13c302016-05-12 18:01:06 -07001108static int smb138x_determine_initial_status(struct smb138x *chip)
1109{
1110 struct smb_irq_data irq_data = {chip, "determine-initial-status"};
1111
1112 smblib_handle_usb_plugin(0, &irq_data);
1113 smblib_handle_usb_typec_change(0, &irq_data);
1114 smblib_handle_usb_source_change(0, &irq_data);
Nicholas Troast5d13c302016-05-12 18:01:06 -07001115 return 0;
1116}
1117
1118/**************************
1119 * INTERRUPT REGISTRATION *
1120 **************************/
1121
Subbaraman Narayanamurthybbd7f452017-02-06 16:22:48 -08001122static struct smb_irq_info smb138x_irqs[] = {
Nicholas Troast5d13c302016-05-12 18:01:06 -07001123/* CHARGER IRQs */
Subbaraman Narayanamurthybbd7f452017-02-06 16:22:48 -08001124 [CHG_ERROR_IRQ] = {
Nicholas Troast47ae4612016-08-03 09:49:36 -07001125 .name = "chg-error",
1126 .handler = smblib_handle_debug,
1127 },
Subbaraman Narayanamurthybbd7f452017-02-06 16:22:48 -08001128 [CHG_STATE_CHANGE_IRQ] = {
Nicholas Troast47ae4612016-08-03 09:49:36 -07001129 .name = "chg-state-change",
Nicholas Troast1f33b0c2017-01-16 14:12:33 -08001130 .handler = smb138x_handle_slave_chg_state_change,
1131 .wake = true,
Nicholas Troast47ae4612016-08-03 09:49:36 -07001132 },
Subbaraman Narayanamurthybbd7f452017-02-06 16:22:48 -08001133 [STEP_CHG_STATE_CHANGE_IRQ] = {
Nicholas Troast47ae4612016-08-03 09:49:36 -07001134 .name = "step-chg-state-change",
1135 .handler = smblib_handle_debug,
1136 },
Subbaraman Narayanamurthybbd7f452017-02-06 16:22:48 -08001137 [STEP_CHG_SOC_UPDATE_FAIL_IRQ] = {
Nicholas Troast47ae4612016-08-03 09:49:36 -07001138 .name = "step-chg-soc-update-fail",
1139 .handler = smblib_handle_debug,
1140 },
Subbaraman Narayanamurthybbd7f452017-02-06 16:22:48 -08001141 [STEP_CHG_SOC_UPDATE_REQ_IRQ] = {
Nicholas Troast47ae4612016-08-03 09:49:36 -07001142 .name = "step-chg-soc-update-request",
1143 .handler = smblib_handle_debug,
1144 },
Nicholas Troast5d13c302016-05-12 18:01:06 -07001145/* OTG IRQs */
Subbaraman Narayanamurthybbd7f452017-02-06 16:22:48 -08001146 [OTG_FAIL_IRQ] = {
Nicholas Troast47ae4612016-08-03 09:49:36 -07001147 .name = "otg-fail",
1148 .handler = smblib_handle_debug,
1149 },
Subbaraman Narayanamurthybbd7f452017-02-06 16:22:48 -08001150 [OTG_OVERCURRENT_IRQ] = {
Nicholas Troast47ae4612016-08-03 09:49:36 -07001151 .name = "otg-overcurrent",
1152 .handler = smblib_handle_debug,
1153 },
Subbaraman Narayanamurthybbd7f452017-02-06 16:22:48 -08001154 [OTG_OC_DIS_SW_STS_IRQ] = {
Nicholas Troast47ae4612016-08-03 09:49:36 -07001155 .name = "otg-oc-dis-sw-sts",
1156 .handler = smblib_handle_debug,
1157 },
Subbaraman Narayanamurthybbd7f452017-02-06 16:22:48 -08001158 [TESTMODE_CHANGE_DET_IRQ] = {
Nicholas Troast47ae4612016-08-03 09:49:36 -07001159 .name = "testmode-change-detect",
1160 .handler = smblib_handle_debug,
1161 },
Nicholas Troast5d13c302016-05-12 18:01:06 -07001162/* BATTERY IRQs */
Subbaraman Narayanamurthybbd7f452017-02-06 16:22:48 -08001163 [BATT_TEMP_IRQ] = {
Nicholas Troast47ae4612016-08-03 09:49:36 -07001164 .name = "bat-temp",
1165 .handler = smblib_handle_batt_psy_changed,
1166 },
Subbaraman Narayanamurthybbd7f452017-02-06 16:22:48 -08001167 [BATT_OCP_IRQ] = {
Nicholas Troast47ae4612016-08-03 09:49:36 -07001168 .name = "bat-ocp",
1169 .handler = smblib_handle_batt_psy_changed,
1170 },
Subbaraman Narayanamurthybbd7f452017-02-06 16:22:48 -08001171 [BATT_OV_IRQ] = {
Nicholas Troast47ae4612016-08-03 09:49:36 -07001172 .name = "bat-ov",
1173 .handler = smblib_handle_batt_psy_changed,
1174 },
Subbaraman Narayanamurthybbd7f452017-02-06 16:22:48 -08001175 [BATT_LOW_IRQ] = {
Nicholas Troast47ae4612016-08-03 09:49:36 -07001176 .name = "bat-low",
1177 .handler = smblib_handle_batt_psy_changed,
1178 },
Subbaraman Narayanamurthybbd7f452017-02-06 16:22:48 -08001179 [BATT_THERM_ID_MISS_IRQ] = {
Nicholas Troast47ae4612016-08-03 09:49:36 -07001180 .name = "bat-therm-or-id-missing",
1181 .handler = smblib_handle_batt_psy_changed,
1182 },
Subbaraman Narayanamurthybbd7f452017-02-06 16:22:48 -08001183 [BATT_TERM_MISS_IRQ] = {
Nicholas Troast47ae4612016-08-03 09:49:36 -07001184 .name = "bat-terminal-missing",
1185 .handler = smblib_handle_batt_psy_changed,
1186 },
Nicholas Troast5d13c302016-05-12 18:01:06 -07001187/* USB INPUT IRQs */
Subbaraman Narayanamurthybbd7f452017-02-06 16:22:48 -08001188 [USBIN_COLLAPSE_IRQ] = {
Nicholas Troast47ae4612016-08-03 09:49:36 -07001189 .name = "usbin-collapse",
1190 .handler = smblib_handle_debug,
1191 },
Subbaraman Narayanamurthybbd7f452017-02-06 16:22:48 -08001192 [USBIN_LT_3P6V_IRQ] = {
Nicholas Troast47ae4612016-08-03 09:49:36 -07001193 .name = "usbin-lt-3p6v",
1194 .handler = smblib_handle_debug,
1195 },
Subbaraman Narayanamurthybbd7f452017-02-06 16:22:48 -08001196 [USBIN_UV_IRQ] = {
Nicholas Troast47ae4612016-08-03 09:49:36 -07001197 .name = "usbin-uv",
1198 .handler = smblib_handle_debug,
1199 },
Subbaraman Narayanamurthybbd7f452017-02-06 16:22:48 -08001200 [USBIN_OV_IRQ] = {
Nicholas Troast47ae4612016-08-03 09:49:36 -07001201 .name = "usbin-ov",
1202 .handler = smblib_handle_debug,
1203 },
Subbaraman Narayanamurthybbd7f452017-02-06 16:22:48 -08001204 [USBIN_PLUGIN_IRQ] = {
Nicholas Troast47ae4612016-08-03 09:49:36 -07001205 .name = "usbin-plugin",
1206 .handler = smblib_handle_usb_plugin,
1207 },
Subbaraman Narayanamurthybbd7f452017-02-06 16:22:48 -08001208 [USBIN_SRC_CHANGE_IRQ] = {
Nicholas Troast47ae4612016-08-03 09:49:36 -07001209 .name = "usbin-src-change",
1210 .handler = smblib_handle_usb_source_change,
1211 },
Subbaraman Narayanamurthybbd7f452017-02-06 16:22:48 -08001212 [USBIN_ICL_CHANGE_IRQ] = {
Nicholas Troast47ae4612016-08-03 09:49:36 -07001213 .name = "usbin-icl-change",
1214 .handler = smblib_handle_debug,
1215 },
Subbaraman Narayanamurthybbd7f452017-02-06 16:22:48 -08001216 [TYPE_C_CHANGE_IRQ] = {
Nicholas Troast47ae4612016-08-03 09:49:36 -07001217 .name = "type-c-change",
1218 .handler = smblib_handle_usb_typec_change,
1219 },
Nicholas Troast5d13c302016-05-12 18:01:06 -07001220/* DC INPUT IRQs */
Subbaraman Narayanamurthybbd7f452017-02-06 16:22:48 -08001221 [DCIN_COLLAPSE_IRQ] = {
Nicholas Troast47ae4612016-08-03 09:49:36 -07001222 .name = "dcin-collapse",
1223 .handler = smblib_handle_debug,
1224 },
Subbaraman Narayanamurthybbd7f452017-02-06 16:22:48 -08001225 [DCIN_LT_3P6V_IRQ] = {
Nicholas Troast47ae4612016-08-03 09:49:36 -07001226 .name = "dcin-lt-3p6v",
1227 .handler = smblib_handle_debug,
1228 },
Subbaraman Narayanamurthybbd7f452017-02-06 16:22:48 -08001229 [DCIN_UV_IRQ] = {
Nicholas Troast47ae4612016-08-03 09:49:36 -07001230 .name = "dcin-uv",
1231 .handler = smblib_handle_debug,
1232 },
Subbaraman Narayanamurthybbd7f452017-02-06 16:22:48 -08001233 [DCIN_OV_IRQ] = {
Nicholas Troast47ae4612016-08-03 09:49:36 -07001234 .name = "dcin-ov",
1235 .handler = smblib_handle_debug,
1236 },
Subbaraman Narayanamurthybbd7f452017-02-06 16:22:48 -08001237 [DCIN_PLUGIN_IRQ] = {
Nicholas Troast47ae4612016-08-03 09:49:36 -07001238 .name = "dcin-plugin",
1239 .handler = smblib_handle_debug,
1240 },
Subbaraman Narayanamurthybbd7f452017-02-06 16:22:48 -08001241 [DIV2_EN_DG_IRQ] = {
Nicholas Troast47ae4612016-08-03 09:49:36 -07001242 .name = "div2-en-dg",
1243 .handler = smblib_handle_debug,
1244 },
Subbaraman Narayanamurthybbd7f452017-02-06 16:22:48 -08001245 [DCIN_ICL_CHANGE_IRQ] = {
Nicholas Troast47ae4612016-08-03 09:49:36 -07001246 .name = "dcin-icl-change",
1247 .handler = smblib_handle_debug,
1248 },
Nicholas Troast5d13c302016-05-12 18:01:06 -07001249/* MISCELLANEOUS IRQs */
Subbaraman Narayanamurthybbd7f452017-02-06 16:22:48 -08001250 [WDOG_SNARL_IRQ] = {
Nicholas Troast47ae4612016-08-03 09:49:36 -07001251 .name = "wdog-snarl",
1252 .handler = smblib_handle_debug,
1253 },
Subbaraman Narayanamurthybbd7f452017-02-06 16:22:48 -08001254 [WDOG_BARK_IRQ] = {
Nicholas Troast47ae4612016-08-03 09:49:36 -07001255 .name = "wdog-bark",
Nicholas Troast15dc0c82016-10-18 15:15:21 -07001256 .handler = smblib_handle_wdog_bark,
1257 .wake = true,
Nicholas Troast47ae4612016-08-03 09:49:36 -07001258 },
Subbaraman Narayanamurthybbd7f452017-02-06 16:22:48 -08001259 [AICL_FAIL_IRQ] = {
Nicholas Troast47ae4612016-08-03 09:49:36 -07001260 .name = "aicl-fail",
1261 .handler = smblib_handle_debug,
1262 },
Subbaraman Narayanamurthybbd7f452017-02-06 16:22:48 -08001263 [AICL_DONE_IRQ] = {
Nicholas Troast47ae4612016-08-03 09:49:36 -07001264 .name = "aicl-done",
1265 .handler = smblib_handle_debug,
1266 },
Subbaraman Narayanamurthybbd7f452017-02-06 16:22:48 -08001267 [HIGH_DUTY_CYCLE_IRQ] = {
Nicholas Troast47ae4612016-08-03 09:49:36 -07001268 .name = "high-duty-cycle",
1269 .handler = smblib_handle_debug,
1270 },
Subbaraman Narayanamurthybbd7f452017-02-06 16:22:48 -08001271 [INPUT_CURRENT_LIMIT_IRQ] = {
Nicholas Troast47ae4612016-08-03 09:49:36 -07001272 .name = "input-current-limiting",
1273 .handler = smblib_handle_debug,
1274 },
Subbaraman Narayanamurthybbd7f452017-02-06 16:22:48 -08001275 [TEMPERATURE_CHANGE_IRQ] = {
Nicholas Troast47ae4612016-08-03 09:49:36 -07001276 .name = "temperature-change",
Nicholas Troast21825e32016-12-16 13:24:43 -08001277 .handler = smb138x_handle_temperature_change,
Nicholas Troast47ae4612016-08-03 09:49:36 -07001278 },
Subbaraman Narayanamurthybbd7f452017-02-06 16:22:48 -08001279 [SWITCH_POWER_OK_IRQ] = {
Nicholas Troast47ae4612016-08-03 09:49:36 -07001280 .name = "switcher-power-ok",
1281 .handler = smblib_handle_debug,
1282 },
Nicholas Troast5d13c302016-05-12 18:01:06 -07001283};
1284
1285static int smb138x_get_irq_index_byname(const char *irq_name)
1286{
1287 int i;
1288
1289 for (i = 0; i < ARRAY_SIZE(smb138x_irqs); i++) {
1290 if (strcmp(smb138x_irqs[i].name, irq_name) == 0)
1291 return i;
1292 }
1293
1294 return -ENOENT;
1295}
1296
1297static int smb138x_request_interrupt(struct smb138x *chip,
1298 struct device_node *node,
1299 const char *irq_name)
1300{
1301 struct smb_charger *chg = &chip->chg;
Nicholas Troast15dc0c82016-10-18 15:15:21 -07001302 int rc = 0, irq, irq_index;
Nicholas Troast5d13c302016-05-12 18:01:06 -07001303 struct smb_irq_data *irq_data;
1304
1305 irq = of_irq_get_byname(node, irq_name);
1306 if (irq < 0) {
1307 pr_err("Couldn't get irq %s byname\n", irq_name);
1308 return irq;
1309 }
1310
1311 irq_index = smb138x_get_irq_index_byname(irq_name);
1312 if (irq_index < 0) {
1313 pr_err("%s is not a defined irq\n", irq_name);
1314 return irq_index;
1315 }
1316
Nicholas Troast15dc0c82016-10-18 15:15:21 -07001317 if (!smb138x_irqs[irq_index].handler)
1318 return 0;
1319
Nicholas Troast5d13c302016-05-12 18:01:06 -07001320 irq_data = devm_kzalloc(chg->dev, sizeof(*irq_data), GFP_KERNEL);
1321 if (!irq_data)
1322 return -ENOMEM;
1323
1324 irq_data->parent_data = chip;
1325 irq_data->name = irq_name;
Nicholas Troast47ae4612016-08-03 09:49:36 -07001326 irq_data->storm_data = smb138x_irqs[irq_index].storm_data;
Subbaraman Narayanamurthyaa414372017-02-06 16:04:32 -08001327 mutex_init(&irq_data->storm_data.storm_lock);
Nicholas Troast5d13c302016-05-12 18:01:06 -07001328
1329 rc = devm_request_threaded_irq(chg->dev, irq, NULL,
1330 smb138x_irqs[irq_index].handler,
1331 IRQF_ONESHOT, irq_name, irq_data);
1332 if (rc < 0) {
1333 pr_err("Couldn't request irq %d\n", irq);
1334 return rc;
1335 }
1336
Nicholas Troast15dc0c82016-10-18 15:15:21 -07001337 if (smb138x_irqs[irq_index].wake)
1338 enable_irq_wake(irq);
1339
Nicholas Troast5d13c302016-05-12 18:01:06 -07001340 return rc;
1341}
1342
1343static int smb138x_request_interrupts(struct smb138x *chip)
1344{
1345 struct smb_charger *chg = &chip->chg;
1346 struct device_node *node = chg->dev->of_node;
1347 struct device_node *child;
1348 int rc = 0;
1349 const char *name;
1350 struct property *prop;
1351
1352 for_each_available_child_of_node(node, child) {
1353 of_property_for_each_string(child, "interrupt-names",
1354 prop, name) {
1355 rc = smb138x_request_interrupt(chip, child, name);
1356 if (rc < 0) {
Nicholas Troast15dc0c82016-10-18 15:15:21 -07001357 pr_err("Couldn't request interrupt %s rc=%d\n",
Nicholas Troast5d13c302016-05-12 18:01:06 -07001358 name, rc);
1359 return rc;
1360 }
1361 }
1362 }
1363
1364 return rc;
1365}
1366
1367/*********
1368 * PROBE *
1369 *********/
1370
1371static int smb138x_master_probe(struct smb138x *chip)
1372{
1373 struct smb_charger *chg = &chip->chg;
1374 int rc = 0;
1375
1376 chg->param = v1_params;
1377
1378 rc = smblib_init(chg);
1379 if (rc < 0) {
1380 pr_err("Couldn't initialize smblib rc=%d\n", rc);
1381 return rc;
1382 }
1383
1384 rc = smb138x_parse_dt(chip);
1385 if (rc < 0) {
1386 pr_err("Couldn't parse device tree rc=%d\n", rc);
1387 return rc;
1388 }
1389
1390 rc = smb138x_init_vbus_regulator(chip);
1391 if (rc < 0) {
1392 pr_err("Couldn't initialize vbus regulator rc=%d\n",
1393 rc);
1394 return rc;
1395 }
1396
1397 rc = smb138x_init_vconn_regulator(chip);
1398 if (rc < 0) {
1399 pr_err("Couldn't initialize vconn regulator rc=%d\n",
1400 rc);
1401 return rc;
1402 }
1403
1404 rc = smb138x_init_usb_psy(chip);
1405 if (rc < 0) {
1406 pr_err("Couldn't initialize usb psy rc=%d\n", rc);
1407 return rc;
1408 }
1409
1410 rc = smb138x_init_batt_psy(chip);
1411 if (rc < 0) {
1412 pr_err("Couldn't initialize batt psy rc=%d\n", rc);
1413 return rc;
1414 }
1415
1416 rc = smb138x_init_hw(chip);
1417 if (rc < 0) {
1418 pr_err("Couldn't initialize hardware rc=%d\n", rc);
1419 return rc;
1420 }
1421
1422 rc = smb138x_determine_initial_status(chip);
1423 if (rc < 0) {
1424 pr_err("Couldn't determine initial status rc=%d\n",
1425 rc);
1426 return rc;
1427 }
1428
1429 rc = smb138x_request_interrupts(chip);
1430 if (rc < 0) {
1431 pr_err("Couldn't request interrupts rc=%d\n", rc);
1432 return rc;
1433 }
1434
1435 return rc;
1436}
1437
Abhijeet Dharmapurikarbb7cf2a2017-05-02 18:05:48 -07001438static int smb138x_slave_probe(struct smb138x *chip)
Nicholas Troast5d13c302016-05-12 18:01:06 -07001439{
1440 struct smb_charger *chg = &chip->chg;
1441 int rc = 0;
1442
1443 chg->param = v1_params;
1444
1445 rc = smblib_init(chg);
1446 if (rc < 0) {
1447 pr_err("Couldn't initialize smblib rc=%d\n", rc);
Nicholas Troast15dc0c82016-10-18 15:15:21 -07001448 goto cleanup;
Nicholas Troast5d13c302016-05-12 18:01:06 -07001449 }
1450
Nicholas Troastdc6e59a2017-01-30 19:22:22 -08001451 chg->iio.temp_max_chan = iio_channel_get(chg->dev, "charger_temp_max");
1452 if (IS_ERR(chg->iio.temp_max_chan)) {
1453 rc = PTR_ERR(chg->iio.temp_max_chan);
Nicholas Troast15dc0c82016-10-18 15:15:21 -07001454 goto cleanup;
1455 }
1456
Nicholas Troastae0ea542017-01-31 19:23:10 -08001457 chg->iio.connector_temp_thr1_chan = iio_channel_get(chg->dev,
1458 "connector_temp_thr1");
1459 if (IS_ERR(chg->iio.connector_temp_thr1_chan)) {
1460 rc = PTR_ERR(chg->iio.connector_temp_thr1_chan);
1461 goto cleanup;
1462 }
1463
1464 chg->iio.connector_temp_thr2_chan = iio_channel_get(chg->dev,
1465 "connector_temp_thr2");
1466 if (IS_ERR(chg->iio.connector_temp_thr2_chan)) {
1467 rc = PTR_ERR(chg->iio.connector_temp_thr2_chan);
1468 goto cleanup;
1469 }
1470
1471 chg->iio.connector_temp_thr3_chan = iio_channel_get(chg->dev,
1472 "connector_temp_thr3");
1473 if (IS_ERR(chg->iio.connector_temp_thr3_chan)) {
1474 rc = PTR_ERR(chg->iio.connector_temp_thr3_chan);
1475 goto cleanup;
1476 }
1477
Nicholas Troastdc6e59a2017-01-30 19:22:22 -08001478 rc = smb138x_parse_dt(chip);
Nicholas Troast15dc0c82016-10-18 15:15:21 -07001479 if (rc < 0) {
Nicholas Troastdc6e59a2017-01-30 19:22:22 -08001480 pr_err("Couldn't parse device tree rc=%d\n", rc);
Nicholas Troast15dc0c82016-10-18 15:15:21 -07001481 goto cleanup;
1482 }
1483
Nicholas Troastdc6e59a2017-01-30 19:22:22 -08001484 rc = smb138x_init_slave_hw(chip);
Nicholas Troast15dc0c82016-10-18 15:15:21 -07001485 if (rc < 0) {
Nicholas Troastdc6e59a2017-01-30 19:22:22 -08001486 pr_err("Couldn't initialize hardware rc=%d\n", rc);
Nicholas Troast15dc0c82016-10-18 15:15:21 -07001487 goto cleanup;
Nicholas Troast5d13c302016-05-12 18:01:06 -07001488 }
1489
Abhijeet Dharmapurikar20acdf12017-04-03 15:27:21 -07001490 if ((chip->dt.pl_mode == POWER_SUPPLY_PL_USBIN_USBIN)
1491 || (chip->dt.pl_mode == POWER_SUPPLY_PL_USBIN_USBIN_EXT)) {
Harry Yang527433e2017-03-14 12:58:32 -07001492 rc = smb138x_init_vbus_regulator(chip);
1493 if (rc < 0) {
1494 pr_err("Couldn't initialize vbus regulator rc=%d\n",
1495 rc);
1496 return rc;
1497 }
1498 }
1499
Harry Yang58a9e7a2016-06-23 14:54:43 -07001500 rc = smb138x_init_parallel_psy(chip);
1501 if (rc < 0) {
1502 pr_err("Couldn't initialize parallel psy rc=%d\n", rc);
Nicholas Troast15dc0c82016-10-18 15:15:21 -07001503 goto cleanup;
Harry Yang58a9e7a2016-06-23 14:54:43 -07001504 }
1505
Nicholas Troast21825e32016-12-16 13:24:43 -08001506 rc = smb138x_determine_initial_slave_status(chip);
1507 if (rc < 0) {
1508 pr_err("Couldn't determine initial status rc=%d\n", rc);
1509 goto cleanup;
1510 }
1511
Nicholas Troast15dc0c82016-10-18 15:15:21 -07001512 rc = smb138x_request_interrupts(chip);
1513 if (rc < 0) {
1514 pr_err("Couldn't request interrupts rc=%d\n", rc);
1515 goto cleanup;
1516 }
1517
Abhijeet Dharmapurikarbb7cf2a2017-05-02 18:05:48 -07001518 return rc;
Nicholas Troast15dc0c82016-10-18 15:15:21 -07001519
1520cleanup:
1521 smblib_deinit(chg);
Abhijeet Dharmapurikarbb7cf2a2017-05-02 18:05:48 -07001522 if (chip->parallel_psy)
1523 power_supply_unregister(chip->parallel_psy);
1524 if (chg->vbus_vreg && chg->vbus_vreg->rdev)
1525 regulator_unregister(chg->vbus_vreg->rdev);
Nicholas Troast5d13c302016-05-12 18:01:06 -07001526 return rc;
1527}
1528
1529static const struct of_device_id match_table[] = {
1530 {
Abhijeet Dharmapurikarbb7cf2a2017-05-02 18:05:48 -07001531 .compatible = "qcom,smb138x-charger",
1532 .data = (void *) PARALLEL_MASTER
Nicholas Troast5d13c302016-05-12 18:01:06 -07001533 },
1534 {
Abhijeet Dharmapurikarbb7cf2a2017-05-02 18:05:48 -07001535 .compatible = "qcom,smb138x-parallel-slave",
1536 .data = (void *) PARALLEL_SLAVE
Nicholas Troast5d13c302016-05-12 18:01:06 -07001537 },
1538 { },
1539};
1540
1541static int smb138x_probe(struct platform_device *pdev)
1542{
1543 struct smb138x *chip;
1544 const struct of_device_id *id;
1545 int rc = 0;
1546
1547 chip = devm_kzalloc(&pdev->dev, sizeof(*chip), GFP_KERNEL);
1548 if (!chip)
1549 return -ENOMEM;
1550
1551 chip->chg.dev = &pdev->dev;
1552 chip->chg.debug_mask = &__debug_mask;
Subbaraman Narayanamurthybbd7f452017-02-06 16:22:48 -08001553 chip->chg.irq_info = smb138x_irqs;
Abhijeet Dharmapurikar31b98f32016-10-14 12:25:23 -07001554 chip->chg.name = "SMB";
Nicholas Troast5d13c302016-05-12 18:01:06 -07001555
1556 chip->chg.regmap = dev_get_regmap(chip->chg.dev->parent, NULL);
1557 if (!chip->chg.regmap) {
1558 pr_err("parent regmap is missing\n");
1559 return -EINVAL;
1560 }
1561
1562 id = of_match_device(of_match_ptr(match_table), chip->chg.dev);
1563 if (!id) {
1564 pr_err("Couldn't find a matching device\n");
1565 return -ENODEV;
1566 }
1567
1568 platform_set_drvdata(pdev, chip);
1569
Abhijeet Dharmapurikarb3022c82016-08-16 16:32:38 -07001570 rc = smb138x_setup_wa_flags(chip);
1571 if (rc < 0) {
1572 if (rc != -EPROBE_DEFER)
1573 pr_err("Couldn't setup wa flags rc = %d\n", rc);
1574 return rc;
1575 }
1576
Nicholas Troast5d13c302016-05-12 18:01:06 -07001577 chip->chg.mode = (enum smb_mode) id->data;
1578 switch (chip->chg.mode) {
1579 case PARALLEL_MASTER:
1580 rc = smb138x_master_probe(chip);
1581 break;
1582 case PARALLEL_SLAVE:
Abhijeet Dharmapurikarbb7cf2a2017-05-02 18:05:48 -07001583 rc = smb138x_slave_probe(chip);
Nicholas Troast5d13c302016-05-12 18:01:06 -07001584 break;
1585 default:
1586 pr_err("Couldn't find a matching mode %d\n", chip->chg.mode);
1587 rc = -EINVAL;
1588 goto cleanup;
1589 }
1590
Nicholas Troastdc6e59a2017-01-30 19:22:22 -08001591 if (rc < 0) {
1592 if (rc != -EPROBE_DEFER)
1593 pr_err("Couldn't probe SMB138X rc=%d\n", rc);
1594 goto cleanup;
1595 }
1596
Abhijeet Dharmapurikarbb7cf2a2017-05-02 18:05:48 -07001597 pr_info("SMB138X probed successfully mode=%d\n", chip->chg.mode);
Nicholas Troast5d13c302016-05-12 18:01:06 -07001598 return rc;
1599
1600cleanup:
1601 platform_set_drvdata(pdev, NULL);
1602 return rc;
1603}
1604
1605static int smb138x_remove(struct platform_device *pdev)
1606{
1607 platform_set_drvdata(pdev, NULL);
1608 return 0;
1609}
1610
1611static struct platform_driver smb138x_driver = {
1612 .driver = {
1613 .name = "qcom,smb138x-charger",
1614 .owner = THIS_MODULE,
1615 .of_match_table = match_table,
1616 },
1617 .probe = smb138x_probe,
1618 .remove = smb138x_remove,
1619};
1620module_platform_driver(smb138x_driver);
1621
1622MODULE_DESCRIPTION("QPNP SMB138X Charger Driver");
1623MODULE_LICENSE("GPL v2");