blob: 6eb70097a08f4facab2e39253f05b10cb6e6d3f9 [file] [log] [blame]
Harry Yang3b113a52016-12-08 12:37:40 -08001/* Copyright (c) 2016-2017 The Linux Foundation. All rights reserved.
Nicholas Troast34db5032016-03-28 12:26:44 -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
13#include <linux/device.h>
14#include <linux/regmap.h>
Harry Yang360bd532016-09-26 11:03:22 -070015#include <linux/delay.h>
Harry Yangba874ce2016-08-19 14:17:01 -070016#include <linux/iio/consumer.h>
Nicholas Troast34db5032016-03-28 12:26:44 -070017#include <linux/power_supply.h>
18#include <linux/regulator/driver.h>
Abhijeet Dharmapurikar7442e422017-02-08 13:35:14 -080019#include <linux/qpnp/qpnp-revid.h>
Nicholas Troast34db5032016-03-28 12:26:44 -070020#include <linux/irq.h>
21#include "smb-lib.h"
22#include "smb-reg.h"
Nicholas Troast47ae4612016-08-03 09:49:36 -070023#include "storm-watch.h"
Abhijeet Dharmapurikardd119c62017-03-20 15:54:59 -070024#include <linux/pmic-voter.h>
Nicholas Troast34db5032016-03-28 12:26:44 -070025
Abhijeet Dharmapurikar31b98f32016-10-14 12:25:23 -070026#define smblib_err(chg, fmt, ...) \
27 pr_err("%s: %s: " fmt, chg->name, \
28 __func__, ##__VA_ARGS__) \
29
Nicholas Troast34db5032016-03-28 12:26:44 -070030#define smblib_dbg(chg, reason, fmt, ...) \
31 do { \
32 if (*chg->debug_mask & (reason)) \
Abhijeet Dharmapurikar31b98f32016-10-14 12:25:23 -070033 pr_info("%s: %s: " fmt, chg->name, \
34 __func__, ##__VA_ARGS__); \
Nicholas Troast34db5032016-03-28 12:26:44 -070035 else \
Abhijeet Dharmapurikar31b98f32016-10-14 12:25:23 -070036 pr_debug("%s: %s: " fmt, chg->name, \
37 __func__, ##__VA_ARGS__); \
Nicholas Troast34db5032016-03-28 12:26:44 -070038 } while (0)
39
40static bool is_secure(struct smb_charger *chg, int addr)
41{
Anirudh Ghayal4da3df92017-01-25 18:55:57 +053042 if (addr == SHIP_MODE_REG || addr == FREQ_CLK_DIV_REG)
Fenglin Wuedd70792016-11-22 13:16:19 +080043 return true;
Harry Yang47bd3852016-10-17 10:37:12 -070044 /* assume everything above 0xA0 is secure */
45 return (bool)((addr & 0xFF) >= 0xA0);
Nicholas Troast34db5032016-03-28 12:26:44 -070046}
47
48int smblib_read(struct smb_charger *chg, u16 addr, u8 *val)
49{
50 unsigned int temp;
51 int rc = 0;
52
53 rc = regmap_read(chg->regmap, addr, &temp);
54 if (rc >= 0)
55 *val = (u8)temp;
56
57 return rc;
58}
59
Ashay Jaiswal6d308da2017-02-18 09:59:23 +053060int smblib_multibyte_read(struct smb_charger *chg, u16 addr, u8 *val,
61 int count)
62{
63 return regmap_bulk_read(chg->regmap, addr, val, count);
64}
65
Nicholas Troast34db5032016-03-28 12:26:44 -070066int smblib_masked_write(struct smb_charger *chg, u16 addr, u8 mask, u8 val)
67{
Nicholas Troast34db5032016-03-28 12:26:44 -070068 int rc = 0;
69
Harry Yangbacd2222016-05-11 16:43:51 -070070 mutex_lock(&chg->write_lock);
Nicholas Troast34db5032016-03-28 12:26:44 -070071 if (is_secure(chg, addr)) {
72 rc = regmap_write(chg->regmap, (addr & 0xFF00) | 0xD0, 0xA5);
73 if (rc < 0)
74 goto unlock;
75 }
76
77 rc = regmap_update_bits(chg->regmap, addr, mask, val);
78
79unlock:
Harry Yangbacd2222016-05-11 16:43:51 -070080 mutex_unlock(&chg->write_lock);
Nicholas Troast34db5032016-03-28 12:26:44 -070081 return rc;
82}
83
84int smblib_write(struct smb_charger *chg, u16 addr, u8 val)
85{
Nicholas Troast34db5032016-03-28 12:26:44 -070086 int rc = 0;
87
Harry Yangbacd2222016-05-11 16:43:51 -070088 mutex_lock(&chg->write_lock);
Nicholas Troast34db5032016-03-28 12:26:44 -070089
90 if (is_secure(chg, addr)) {
91 rc = regmap_write(chg->regmap, (addr & ~(0xFF)) | 0xD0, 0xA5);
92 if (rc < 0)
93 goto unlock;
94 }
95
96 rc = regmap_write(chg->regmap, addr, val);
97
98unlock:
Harry Yangbacd2222016-05-11 16:43:51 -070099 mutex_unlock(&chg->write_lock);
Nicholas Troast34db5032016-03-28 12:26:44 -0700100 return rc;
101}
102
Abhijeet Dharmapurikarc0b0f592016-10-14 10:55:42 -0700103static int smblib_get_step_cc_delta(struct smb_charger *chg, int *cc_delta_ua)
Harry Yangfe913842016-08-10 12:27:28 -0700104{
Abhijeet Dharmapurikarc0b0f592016-10-14 10:55:42 -0700105 int rc, step_state;
Harry Yangfe913842016-08-10 12:27:28 -0700106 u8 stat;
107
108 if (!chg->step_chg_enabled) {
Abhijeet Dharmapurikarc0b0f592016-10-14 10:55:42 -0700109 *cc_delta_ua = 0;
Harry Yangfe913842016-08-10 12:27:28 -0700110 return 0;
111 }
112
113 rc = smblib_read(chg, BATTERY_CHARGER_STATUS_1_REG, &stat);
114 if (rc < 0) {
Abhijeet Dharmapurikar31b98f32016-10-14 12:25:23 -0700115 smblib_err(chg, "Couldn't read BATTERY_CHARGER_STATUS_1 rc=%d\n",
Harry Yangfe913842016-08-10 12:27:28 -0700116 rc);
117 return rc;
118 }
119
Harry Yangbedee332016-08-31 16:14:29 -0700120 step_state = (stat & STEP_CHARGING_STATUS_MASK) >>
121 STEP_CHARGING_STATUS_SHIFT;
Harry Yangfe913842016-08-10 12:27:28 -0700122 rc = smblib_get_charge_param(chg, &chg->param.step_cc_delta[step_state],
Abhijeet Dharmapurikarc0b0f592016-10-14 10:55:42 -0700123 cc_delta_ua);
124 if (rc < 0) {
125 smblib_err(chg, "Couldn't get step cc delta rc=%d\n", rc);
126 return rc;
Abhijeet Dharmapurikar2644cd62016-07-20 16:54:55 -0700127 }
128
Abhijeet Dharmapurikarc0b0f592016-10-14 10:55:42 -0700129 return 0;
130}
Harry Yangfe913842016-08-10 12:27:28 -0700131
Abhijeet Dharmapurikarc0b0f592016-10-14 10:55:42 -0700132static int smblib_get_jeita_cc_delta(struct smb_charger *chg, int *cc_delta_ua)
133{
134 int rc, cc_minus_ua;
135 u8 stat;
Harry Yangfe913842016-08-10 12:27:28 -0700136
Abhijeet Dharmapurikarc0b0f592016-10-14 10:55:42 -0700137 rc = smblib_read(chg, BATTERY_CHARGER_STATUS_2_REG, &stat);
138 if (rc < 0) {
139 smblib_err(chg, "Couldn't read BATTERY_CHARGER_STATUS_2 rc=%d\n",
140 rc);
141 return rc;
142 }
143
144 if (!(stat & BAT_TEMP_STATUS_SOFT_LIMIT_MASK)) {
145 *cc_delta_ua = 0;
146 return 0;
147 }
148
149 rc = smblib_get_charge_param(chg, &chg->param.jeita_cc_comp,
150 &cc_minus_ua);
151 if (rc < 0) {
152 smblib_err(chg, "Couldn't get jeita cc minus rc=%d\n", rc);
153 return rc;
154 }
155
156 *cc_delta_ua = -cc_minus_ua;
157 return 0;
158}
159
Abhijeet Dharmapurikar74021fc2017-02-06 18:39:19 -0800160int smblib_icl_override(struct smb_charger *chg, bool override)
161{
162 int rc;
Abhijeet Dharmapurikar74021fc2017-02-06 18:39:19 -0800163
Nicholas Troast11af51b2017-03-15 10:45:28 -0700164 rc = smblib_masked_write(chg, USBIN_LOAD_CFG_REG,
165 ICL_OVERRIDE_AFTER_APSD_BIT,
166 override ? ICL_OVERRIDE_AFTER_APSD_BIT : 0);
167 if (rc < 0)
168 smblib_err(chg, "Couldn't override ICL rc=%d\n", rc);
Abhijeet Dharmapurikar7442e422017-02-08 13:35:14 -0800169
Nicholas Troast11af51b2017-03-15 10:45:28 -0700170 return rc;
Abhijeet Dharmapurikar74021fc2017-02-06 18:39:19 -0800171}
172
Nicholas Troast34db5032016-03-28 12:26:44 -0700173/********************
174 * REGISTER GETTERS *
175 ********************/
176
Nicholas Troast4c310492016-05-12 17:56:35 -0700177int smblib_get_charge_param(struct smb_charger *chg,
178 struct smb_chg_param *param, int *val_u)
179{
180 int rc = 0;
181 u8 val_raw;
182
183 rc = smblib_read(chg, param->reg, &val_raw);
184 if (rc < 0) {
Abhijeet Dharmapurikar31b98f32016-10-14 12:25:23 -0700185 smblib_err(chg, "%s: Couldn't read from 0x%04x rc=%d\n",
Nicholas Troast4c310492016-05-12 17:56:35 -0700186 param->name, param->reg, rc);
187 return rc;
188 }
189
Harry Yangf8b41252016-08-10 14:21:10 -0700190 if (param->get_proc)
191 *val_u = param->get_proc(param, val_raw);
192 else
193 *val_u = val_raw * param->step_u + param->min_u;
Nicholas Troast4c310492016-05-12 17:56:35 -0700194 smblib_dbg(chg, PR_REGISTER, "%s = %d (0x%02x)\n",
195 param->name, *val_u, val_raw);
196
197 return rc;
198}
199
200int smblib_get_usb_suspend(struct smb_charger *chg, int *suspend)
201{
202 int rc = 0;
203 u8 temp;
204
205 rc = smblib_read(chg, USBIN_CMD_IL_REG, &temp);
206 if (rc < 0) {
Abhijeet Dharmapurikar31b98f32016-10-14 12:25:23 -0700207 smblib_err(chg, "Couldn't read USBIN_CMD_IL rc=%d\n", rc);
Nicholas Troast4c310492016-05-12 17:56:35 -0700208 return rc;
209 }
210 *suspend = temp & USBIN_SUSPEND_BIT;
211
212 return rc;
213}
214
Nicholas Troast34db5032016-03-28 12:26:44 -0700215struct apsd_result {
216 const char * const name;
217 const u8 bit;
218 const enum power_supply_type pst;
219};
220
Abhijeet Dharmapurikarf0b0a042016-10-10 16:43:43 -0700221enum {
222 UNKNOWN,
223 SDP,
224 CDP,
225 DCP,
226 OCP,
227 FLOAT,
228 HVDCP2,
229 HVDCP3,
230 MAX_TYPES
231};
232
Nicholas Troast34db5032016-03-28 12:26:44 -0700233static const struct apsd_result const smblib_apsd_results[] = {
Abhijeet Dharmapurikarf0b0a042016-10-10 16:43:43 -0700234 [UNKNOWN] = {
235 .name = "UNKNOWN",
236 .bit = 0,
237 .pst = POWER_SUPPLY_TYPE_UNKNOWN
238 },
239 [SDP] = {
240 .name = "SDP",
241 .bit = SDP_CHARGER_BIT,
242 .pst = POWER_SUPPLY_TYPE_USB
243 },
244 [CDP] = {
245 .name = "CDP",
246 .bit = CDP_CHARGER_BIT,
247 .pst = POWER_SUPPLY_TYPE_USB_CDP
248 },
249 [DCP] = {
250 .name = "DCP",
251 .bit = DCP_CHARGER_BIT,
252 .pst = POWER_SUPPLY_TYPE_USB_DCP
253 },
254 [OCP] = {
255 .name = "OCP",
256 .bit = OCP_CHARGER_BIT,
257 .pst = POWER_SUPPLY_TYPE_USB_DCP
258 },
259 [FLOAT] = {
260 .name = "FLOAT",
261 .bit = FLOAT_CHARGER_BIT,
262 .pst = POWER_SUPPLY_TYPE_USB_DCP
263 },
264 [HVDCP2] = {
265 .name = "HVDCP2",
266 .bit = DCP_CHARGER_BIT | QC_2P0_BIT,
267 .pst = POWER_SUPPLY_TYPE_USB_HVDCP
268 },
269 [HVDCP3] = {
270 .name = "HVDCP3",
271 .bit = DCP_CHARGER_BIT | QC_3P0_BIT,
272 .pst = POWER_SUPPLY_TYPE_USB_HVDCP_3,
273 },
Nicholas Troast34db5032016-03-28 12:26:44 -0700274};
275
276static const struct apsd_result *smblib_get_apsd_result(struct smb_charger *chg)
277{
278 int rc, i;
Abhijeet Dharmapurikarf0b0a042016-10-10 16:43:43 -0700279 u8 apsd_stat, stat;
280 const struct apsd_result *result = &smblib_apsd_results[UNKNOWN];
Nicholas Troast34db5032016-03-28 12:26:44 -0700281
Abhijeet Dharmapurikarf0b0a042016-10-10 16:43:43 -0700282 rc = smblib_read(chg, APSD_STATUS_REG, &apsd_stat);
Nicholas Troast34db5032016-03-28 12:26:44 -0700283 if (rc < 0) {
Abhijeet Dharmapurikar31b98f32016-10-14 12:25:23 -0700284 smblib_err(chg, "Couldn't read APSD_STATUS rc=%d\n", rc);
Abhijeet Dharmapurikarf0b0a042016-10-10 16:43:43 -0700285 return result;
Nicholas Troast34db5032016-03-28 12:26:44 -0700286 }
Abhijeet Dharmapurikarf0b0a042016-10-10 16:43:43 -0700287 smblib_dbg(chg, PR_REGISTER, "APSD_STATUS = 0x%02x\n", apsd_stat);
Nicholas Troast34db5032016-03-28 12:26:44 -0700288
Abhijeet Dharmapurikarf0b0a042016-10-10 16:43:43 -0700289 if (!(apsd_stat & APSD_DTC_STATUS_DONE_BIT))
290 return result;
Nicholas Troast34db5032016-03-28 12:26:44 -0700291
292 rc = smblib_read(chg, APSD_RESULT_STATUS_REG, &stat);
293 if (rc < 0) {
Abhijeet Dharmapurikar31b98f32016-10-14 12:25:23 -0700294 smblib_err(chg, "Couldn't read APSD_RESULT_STATUS rc=%d\n",
Nicholas Troast34db5032016-03-28 12:26:44 -0700295 rc);
Abhijeet Dharmapurikarf0b0a042016-10-10 16:43:43 -0700296 return result;
Nicholas Troast34db5032016-03-28 12:26:44 -0700297 }
298 stat &= APSD_RESULT_STATUS_MASK;
299
300 for (i = 0; i < ARRAY_SIZE(smblib_apsd_results); i++) {
301 if (smblib_apsd_results[i].bit == stat)
Abhijeet Dharmapurikarf0b0a042016-10-10 16:43:43 -0700302 result = &smblib_apsd_results[i];
Nicholas Troast34db5032016-03-28 12:26:44 -0700303 }
304
Abhijeet Dharmapurikarf0b0a042016-10-10 16:43:43 -0700305 if (apsd_stat & QC_CHARGER_BIT) {
306 /* since its a qc_charger, either return HVDCP3 or HVDCP2 */
307 if (result != &smblib_apsd_results[HVDCP3])
308 result = &smblib_apsd_results[HVDCP2];
309 }
310
311 return result;
Nicholas Troast34db5032016-03-28 12:26:44 -0700312}
313
Nicholas Troast34db5032016-03-28 12:26:44 -0700314/********************
315 * REGISTER SETTERS *
316 ********************/
317
Anirudh Ghayal4da3df92017-01-25 18:55:57 +0530318static int chg_freq_list[] = {
319 9600, 9600, 6400, 4800, 3800, 3200, 2700, 2400, 2100, 1900, 1700,
320 1600, 1500, 1400, 1300, 1200,
321};
322
323int smblib_set_chg_freq(struct smb_chg_param *param,
324 int val_u, u8 *val_raw)
325{
326 u8 i;
327
328 if (val_u > param->max_u || val_u < param->min_u)
329 return -EINVAL;
330
331 /* Charger FSW is the configured freqency / 2 */
332 val_u *= 2;
333 for (i = 0; i < ARRAY_SIZE(chg_freq_list); i++) {
334 if (chg_freq_list[i] == val_u)
335 break;
336 }
337 if (i == ARRAY_SIZE(chg_freq_list)) {
338 pr_err("Invalid frequency %d Hz\n", val_u / 2);
339 return -EINVAL;
340 }
341
342 *val_raw = i;
343
344 return 0;
345}
346
347static int smblib_set_opt_freq_buck(struct smb_charger *chg, int fsw_khz)
348{
349 union power_supply_propval pval = {0, };
350 int rc = 0;
351
352 rc = smblib_set_charge_param(chg, &chg->param.freq_buck, fsw_khz);
353 if (rc < 0)
354 dev_err(chg->dev, "Error in setting freq_buck rc=%d\n", rc);
355
356 if (chg->mode == PARALLEL_MASTER && chg->pl.psy) {
357 pval.intval = fsw_khz;
Abhijeet Dharmapurikare9fd08d2017-02-27 11:05:28 -0800358 /*
359 * Some parallel charging implementations may not have
360 * PROP_BUCK_FREQ property - they could be running
361 * with a fixed frequency
362 */
363 power_supply_set_property(chg->pl.psy,
Anirudh Ghayal4da3df92017-01-25 18:55:57 +0530364 POWER_SUPPLY_PROP_BUCK_FREQ, &pval);
Anirudh Ghayal4da3df92017-01-25 18:55:57 +0530365 }
366
367 return rc;
368}
369
Nicholas Troast4c310492016-05-12 17:56:35 -0700370int smblib_set_charge_param(struct smb_charger *chg,
371 struct smb_chg_param *param, int val_u)
Nicholas Troast34db5032016-03-28 12:26:44 -0700372{
373 int rc = 0;
374 u8 val_raw;
375
Harry Yangf8b41252016-08-10 14:21:10 -0700376 if (param->set_proc) {
377 rc = param->set_proc(param, val_u, &val_raw);
378 if (rc < 0)
379 return -EINVAL;
380 } else {
381 if (val_u > param->max_u || val_u < param->min_u) {
Abhijeet Dharmapurikar31b98f32016-10-14 12:25:23 -0700382 smblib_err(chg, "%s: %d is out of range [%d, %d]\n",
Harry Yangf8b41252016-08-10 14:21:10 -0700383 param->name, val_u, param->min_u, param->max_u);
384 return -EINVAL;
385 }
386
387 val_raw = (val_u - param->min_u) / param->step_u;
Nicholas Troast34db5032016-03-28 12:26:44 -0700388 }
389
Nicholas Troast34db5032016-03-28 12:26:44 -0700390 rc = smblib_write(chg, param->reg, val_raw);
391 if (rc < 0) {
Abhijeet Dharmapurikar31b98f32016-10-14 12:25:23 -0700392 smblib_err(chg, "%s: Couldn't write 0x%02x to 0x%04x rc=%d\n",
Nicholas Troast34db5032016-03-28 12:26:44 -0700393 param->name, val_raw, param->reg, rc);
394 return rc;
395 }
396
397 smblib_dbg(chg, PR_REGISTER, "%s = %d (0x%02x)\n",
398 param->name, val_u, val_raw);
399
400 return rc;
401}
402
Harry Yangfe913842016-08-10 12:27:28 -0700403static int step_charge_soc_update(struct smb_charger *chg, int capacity)
404{
405 int rc = 0;
406
407 rc = smblib_set_charge_param(chg, &chg->param.step_soc, capacity);
408 if (rc < 0) {
Abhijeet Dharmapurikar31b98f32016-10-14 12:25:23 -0700409 smblib_err(chg, "Error in updating soc, rc=%d\n", rc);
Harry Yangfe913842016-08-10 12:27:28 -0700410 return rc;
411 }
412
413 rc = smblib_write(chg, STEP_CHG_SOC_VBATT_V_UPDATE_REG,
414 STEP_CHG_SOC_VBATT_V_UPDATE_BIT);
415 if (rc < 0) {
Abhijeet Dharmapurikar31b98f32016-10-14 12:25:23 -0700416 smblib_err(chg,
Harry Yangfe913842016-08-10 12:27:28 -0700417 "Couldn't set STEP_CHG_SOC_VBATT_V_UPDATE_REG rc=%d\n",
418 rc);
419 return rc;
420 }
421
422 return rc;
423}
424
Nicholas Troast4c310492016-05-12 17:56:35 -0700425int smblib_set_usb_suspend(struct smb_charger *chg, bool suspend)
Nicholas Troast34db5032016-03-28 12:26:44 -0700426{
427 int rc = 0;
428
429 rc = smblib_masked_write(chg, USBIN_CMD_IL_REG, USBIN_SUSPEND_BIT,
430 suspend ? USBIN_SUSPEND_BIT : 0);
431 if (rc < 0)
Abhijeet Dharmapurikar31b98f32016-10-14 12:25:23 -0700432 smblib_err(chg, "Couldn't write %s to USBIN_SUSPEND_BIT rc=%d\n",
Nicholas Troast34db5032016-03-28 12:26:44 -0700433 suspend ? "suspend" : "resume", rc);
434
435 return rc;
436}
437
Nicholas Troast4c310492016-05-12 17:56:35 -0700438int smblib_set_dc_suspend(struct smb_charger *chg, bool suspend)
Nicholas Troast34db5032016-03-28 12:26:44 -0700439{
440 int rc = 0;
441
442 rc = smblib_masked_write(chg, DCIN_CMD_IL_REG, DCIN_SUSPEND_BIT,
443 suspend ? DCIN_SUSPEND_BIT : 0);
444 if (rc < 0)
Abhijeet Dharmapurikar31b98f32016-10-14 12:25:23 -0700445 smblib_err(chg, "Couldn't write %s to DCIN_SUSPEND_BIT rc=%d\n",
Nicholas Troast34db5032016-03-28 12:26:44 -0700446 suspend ? "suspend" : "resume", rc);
447
448 return rc;
449}
450
Ashay Jaiswalb3101012017-03-01 10:18:04 +0530451static int smblib_set_adapter_allowance(struct smb_charger *chg,
452 u8 allowed_voltage)
453{
454 int rc = 0;
455
456 switch (allowed_voltage) {
457 case USBIN_ADAPTER_ALLOW_12V:
458 case USBIN_ADAPTER_ALLOW_5V_OR_12V:
459 case USBIN_ADAPTER_ALLOW_9V_TO_12V:
460 case USBIN_ADAPTER_ALLOW_5V_OR_9V_TO_12V:
461 case USBIN_ADAPTER_ALLOW_5V_TO_12V:
462 /* PM660 only support max. 9V */
463 if (chg->smb_version == PM660_SUBTYPE) {
464 smblib_dbg(chg, PR_MISC, "voltage not supported=%d\n",
465 allowed_voltage);
466 allowed_voltage = USBIN_ADAPTER_ALLOW_5V_TO_9V;
467 }
468 break;
469 }
470
471 rc = smblib_write(chg, USBIN_ADAPTER_ALLOW_CFG_REG, allowed_voltage);
472 if (rc < 0) {
473 smblib_err(chg, "Couldn't write 0x%02x to USBIN_ADAPTER_ALLOW_CFG rc=%d\n",
474 allowed_voltage, rc);
475 return rc;
476 }
477
478 return rc;
479}
480
Nicholas Troast34db5032016-03-28 12:26:44 -0700481#define MICRO_5V 5000000
482#define MICRO_9V 9000000
483#define MICRO_12V 12000000
484static int smblib_set_usb_pd_allowed_voltage(struct smb_charger *chg,
485 int min_allowed_uv, int max_allowed_uv)
486{
487 int rc;
488 u8 allowed_voltage;
489
490 if (min_allowed_uv == MICRO_5V && max_allowed_uv == MICRO_5V) {
491 allowed_voltage = USBIN_ADAPTER_ALLOW_5V;
Anirudh Ghayal4da3df92017-01-25 18:55:57 +0530492 smblib_set_opt_freq_buck(chg, chg->chg_freq.freq_5V);
Nicholas Troast34db5032016-03-28 12:26:44 -0700493 } else if (min_allowed_uv == MICRO_9V && max_allowed_uv == MICRO_9V) {
494 allowed_voltage = USBIN_ADAPTER_ALLOW_9V;
Anirudh Ghayal4da3df92017-01-25 18:55:57 +0530495 smblib_set_opt_freq_buck(chg, chg->chg_freq.freq_9V);
Nicholas Troast34db5032016-03-28 12:26:44 -0700496 } else if (min_allowed_uv == MICRO_12V && max_allowed_uv == MICRO_12V) {
497 allowed_voltage = USBIN_ADAPTER_ALLOW_12V;
Anirudh Ghayal4da3df92017-01-25 18:55:57 +0530498 smblib_set_opt_freq_buck(chg, chg->chg_freq.freq_12V);
Nicholas Troast34db5032016-03-28 12:26:44 -0700499 } else if (min_allowed_uv < MICRO_9V && max_allowed_uv <= MICRO_9V) {
500 allowed_voltage = USBIN_ADAPTER_ALLOW_5V_TO_9V;
501 } else if (min_allowed_uv < MICRO_9V && max_allowed_uv <= MICRO_12V) {
502 allowed_voltage = USBIN_ADAPTER_ALLOW_5V_TO_12V;
503 } else if (min_allowed_uv < MICRO_12V && max_allowed_uv <= MICRO_12V) {
504 allowed_voltage = USBIN_ADAPTER_ALLOW_9V_TO_12V;
505 } else {
Abhijeet Dharmapurikar31b98f32016-10-14 12:25:23 -0700506 smblib_err(chg, "invalid allowed voltage [%d, %d]\n",
Nicholas Troast34db5032016-03-28 12:26:44 -0700507 min_allowed_uv, max_allowed_uv);
508 return -EINVAL;
509 }
510
Ashay Jaiswalb3101012017-03-01 10:18:04 +0530511 rc = smblib_set_adapter_allowance(chg, allowed_voltage);
Nicholas Troast34db5032016-03-28 12:26:44 -0700512 if (rc < 0) {
Ashay Jaiswalb3101012017-03-01 10:18:04 +0530513 smblib_err(chg, "Couldn't configure adapter allowance rc=%d\n",
514 rc);
Nicholas Troast34db5032016-03-28 12:26:44 -0700515 return rc;
516 }
517
518 return rc;
519}
520
521/********************
522 * HELPER FUNCTIONS *
523 ********************/
524
Nicholas Troast93fb0f02017-03-01 10:17:13 -0800525static void smblib_rerun_apsd(struct smb_charger *chg)
526{
527 int rc;
528
529 smblib_dbg(chg, PR_MISC, "re-running APSD\n");
530 if (chg->wa_flags & QC_AUTH_INTERRUPT_WA_BIT) {
531 rc = smblib_masked_write(chg,
532 USBIN_SOURCE_CHANGE_INTRPT_ENB_REG,
533 AUTH_IRQ_EN_CFG_BIT, AUTH_IRQ_EN_CFG_BIT);
534 if (rc < 0)
535 smblib_err(chg, "Couldn't enable HVDCP auth IRQ rc=%d\n",
536 rc);
537 }
538
539 rc = smblib_masked_write(chg, CMD_APSD_REG,
540 APSD_RERUN_BIT, APSD_RERUN_BIT);
541 if (rc < 0)
542 smblib_err(chg, "Couldn't re-run APSD rc=%d\n", rc);
543}
544
Abhijeet Dharmapurikarb9598872016-10-17 16:58:58 -0700545static const struct apsd_result *smblib_update_usb_type(struct smb_charger *chg)
Nicholas Troast34db5032016-03-28 12:26:44 -0700546{
Abhijeet Dharmapurikareda08222016-11-01 11:35:29 -0700547 const struct apsd_result *apsd_result = smblib_get_apsd_result(chg);
Nicholas Troast34db5032016-03-28 12:26:44 -0700548
Jack Pham9696e252016-05-23 11:15:15 -0700549 /* if PD is active, APSD is disabled so won't have a valid result */
Nicholas Troast93fb0f02017-03-01 10:17:13 -0800550 if (chg->pd_active)
Abhijeet Dharmapurikar76e2af52016-10-06 17:25:01 -0700551 chg->usb_psy_desc.type = POWER_SUPPLY_TYPE_USB_PD;
Nicholas Troast93fb0f02017-03-01 10:17:13 -0800552 else
553 chg->usb_psy_desc.type = apsd_result->pst;
Nicholas Troast34db5032016-03-28 12:26:44 -0700554
Nicholas Troast93fb0f02017-03-01 10:17:13 -0800555 smblib_dbg(chg, PR_MISC, "APSD=%s PD=%d\n",
556 apsd_result->name, chg->pd_active);
Abhijeet Dharmapurikarb9598872016-10-17 16:58:58 -0700557 return apsd_result;
Nicholas Troast34db5032016-03-28 12:26:44 -0700558}
559
Harry Yang5e1a5222016-07-26 15:16:04 -0700560static int smblib_notifier_call(struct notifier_block *nb,
Harry Yang58a9e7a2016-06-23 14:54:43 -0700561 unsigned long ev, void *v)
Harry Yang1d1034c2016-06-15 12:09:42 -0700562{
Harry Yang58a9e7a2016-06-23 14:54:43 -0700563 struct power_supply *psy = v;
Harry Yang5e1a5222016-07-26 15:16:04 -0700564 struct smb_charger *chg = container_of(nb, struct smb_charger, nb);
Harry Yang1d1034c2016-06-15 12:09:42 -0700565
Harry Yang5e1a5222016-07-26 15:16:04 -0700566 if (!strcmp(psy->desc->name, "bms")) {
567 if (!chg->bms_psy)
568 chg->bms_psy = psy;
Ashay Jaiswal2fb369d2017-01-12 21:38:29 +0530569 if (ev == PSY_EVENT_PROP_CHANGED)
Harry Yang5e1a5222016-07-26 15:16:04 -0700570 schedule_work(&chg->bms_update_work);
571 }
572
Ashay Jaiswal8afedfc2017-02-03 11:18:22 +0530573 if (!chg->pl.psy && !strcmp(psy->desc->name, "parallel"))
Harry Yang58a9e7a2016-06-23 14:54:43 -0700574 chg->pl.psy = psy;
Harry Yang1d1034c2016-06-15 12:09:42 -0700575
Harry Yang58a9e7a2016-06-23 14:54:43 -0700576 return NOTIFY_OK;
577}
578
Harry Yang5e1a5222016-07-26 15:16:04 -0700579static int smblib_register_notifier(struct smb_charger *chg)
Harry Yang58a9e7a2016-06-23 14:54:43 -0700580{
581 int rc;
582
Harry Yang5e1a5222016-07-26 15:16:04 -0700583 chg->nb.notifier_call = smblib_notifier_call;
584 rc = power_supply_reg_notifier(&chg->nb);
Harry Yang58a9e7a2016-06-23 14:54:43 -0700585 if (rc < 0) {
Abhijeet Dharmapurikar31b98f32016-10-14 12:25:23 -0700586 smblib_err(chg, "Couldn't register psy notifier rc = %d\n", rc);
Harry Yang58a9e7a2016-06-23 14:54:43 -0700587 return rc;
588 }
589
590 return 0;
Harry Yang1d1034c2016-06-15 12:09:42 -0700591}
592
Harry Yangfe913842016-08-10 12:27:28 -0700593int smblib_mapping_soc_from_field_value(struct smb_chg_param *param,
594 int val_u, u8 *val_raw)
595{
596 if (val_u > param->max_u || val_u < param->min_u)
597 return -EINVAL;
598
599 *val_raw = val_u << 1;
600
601 return 0;
602}
603
604int smblib_mapping_cc_delta_to_field_value(struct smb_chg_param *param,
605 u8 val_raw)
606{
607 int val_u = val_raw * param->step_u + param->min_u;
608
609 if (val_u > param->max_u)
610 val_u -= param->max_u * 2;
611
612 return val_u;
613}
614
615int smblib_mapping_cc_delta_from_field_value(struct smb_chg_param *param,
616 int val_u, u8 *val_raw)
617{
618 if (val_u > param->max_u || val_u < param->min_u - param->max_u)
619 return -EINVAL;
620
621 val_u += param->max_u * 2 - param->min_u;
622 val_u %= param->max_u * 2;
623 *val_raw = val_u / param->step_u;
624
625 return 0;
626}
627
Ashay Jaiswal4aa2c0c2016-12-07 19:39:38 +0530628static void smblib_uusb_removal(struct smb_charger *chg)
629{
630 int rc;
631
Ashay Jaiswalc0361672017-03-21 12:24:16 +0530632 cancel_delayed_work_sync(&chg->pl_enable_work);
633 vote(chg->pl_disable_votable, PL_DELAY_VOTER, true, 0);
634 vote(chg->awake_votable, PL_DELAY_VOTER, false, 0);
635
Ashay Jaiswal4aa2c0c2016-12-07 19:39:38 +0530636 /* reset both usbin current and voltage votes */
637 vote(chg->pl_enable_votable_indirect, USBIN_I_VOTER, false, 0);
638 vote(chg->pl_enable_votable_indirect, USBIN_V_VOTER, false, 0);
Ashay Jaiswal4aa2c0c2016-12-07 19:39:38 +0530639
640 cancel_delayed_work_sync(&chg->hvdcp_detect_work);
641
Ashay Jaiswal67ec7072017-02-16 14:14:58 +0530642 if (chg->wa_flags & QC_AUTH_INTERRUPT_WA_BIT) {
643 /* re-enable AUTH_IRQ_EN_CFG_BIT */
644 rc = smblib_masked_write(chg,
645 USBIN_SOURCE_CHANGE_INTRPT_ENB_REG,
646 AUTH_IRQ_EN_CFG_BIT, AUTH_IRQ_EN_CFG_BIT);
647 if (rc < 0)
648 smblib_err(chg,
649 "Couldn't enable QC auth setting rc=%d\n", rc);
650 }
Ashay Jaiswal4aa2c0c2016-12-07 19:39:38 +0530651
652 /* reconfigure allowed voltage for HVDCP */
Ashay Jaiswalb3101012017-03-01 10:18:04 +0530653 rc = smblib_set_adapter_allowance(chg,
654 USBIN_ADAPTER_ALLOW_5V_OR_9V_TO_12V);
Ashay Jaiswal4aa2c0c2016-12-07 19:39:38 +0530655 if (rc < 0)
656 smblib_err(chg, "Couldn't set USBIN_ADAPTER_ALLOW_5V_OR_9V_TO_12V rc=%d\n",
657 rc);
658
659 chg->voltage_min_uv = MICRO_5V;
660 chg->voltage_max_uv = MICRO_5V;
Ashay Jaiswal6d308da2017-02-18 09:59:23 +0530661 chg->usb_icl_delta_ua = 0;
662 chg->pulse_cnt = 0;
Ashay Jaiswal8507aa52017-04-14 09:42:32 +0530663 chg->uusb_apsd_rerun_done = false;
Ashay Jaiswal4aa2c0c2016-12-07 19:39:38 +0530664
665 /* clear USB ICL vote for USB_PSY_VOTER */
666 rc = vote(chg->usb_icl_votable, USB_PSY_VOTER, false, 0);
667 if (rc < 0)
668 smblib_err(chg, "Couldn't un-vote for USB ICL rc=%d\n", rc);
Abhijeet Dharmapurikar7442e422017-02-08 13:35:14 -0800669
670 /* clear USB ICL vote for DCP_VOTER */
671 rc = vote(chg->usb_icl_votable, DCP_VOTER, false, 0);
672 if (rc < 0)
673 smblib_err(chg,
674 "Couldn't un-vote DCP from USB ICL rc=%d\n", rc);
Ashay Jaiswal4aa2c0c2016-12-07 19:39:38 +0530675}
676
Ashay Jaiswal2fb369d2017-01-12 21:38:29 +0530677void smblib_suspend_on_debug_battery(struct smb_charger *chg)
678{
679 int rc;
680 union power_supply_propval val;
681
Ashay Jaiswalda8669b2017-02-10 23:24:23 +0530682 if (!chg->suspend_input_on_debug_batt)
683 return;
684
Ashay Jaiswal2fb369d2017-01-12 21:38:29 +0530685 rc = power_supply_get_property(chg->bms_psy,
686 POWER_SUPPLY_PROP_DEBUG_BATTERY, &val);
687 if (rc < 0) {
688 smblib_err(chg, "Couldn't get debug battery prop rc=%d\n", rc);
689 return;
690 }
691
Abhijeet Dharmapurikar5e0bfbe2017-02-12 19:16:15 -0800692 vote(chg->usb_icl_votable, DEBUG_BOARD_VOTER, val.intval, 0);
Ashay Jaiswal2fb369d2017-01-12 21:38:29 +0530693 vote(chg->dc_suspend_votable, DEBUG_BOARD_VOTER, val.intval, 0);
694 if (val.intval)
695 pr_info("Input suspended: Fake battery\n");
696}
697
Abhijeet Dharmapurikar9dd61292017-01-25 16:40:08 -0800698int smblib_rerun_apsd_if_required(struct smb_charger *chg)
699{
Abhijeet Dharmapurikar9dd61292017-01-25 16:40:08 -0800700 union power_supply_propval val;
701 int rc;
702
703 rc = smblib_get_prop_usb_present(chg, &val);
704 if (rc < 0) {
705 smblib_err(chg, "Couldn't get usb present rc = %d\n", rc);
706 return rc;
707 }
708
709 if (!val.intval)
710 return 0;
711
Abhijeet Dharmapurikar025e63a2017-02-24 14:06:22 -0800712 /* fetch the DPDM regulator */
713 if (!chg->dpdm_reg && of_get_property(chg->dev->of_node,
714 "dpdm-supply", NULL)) {
715 chg->dpdm_reg = devm_regulator_get(chg->dev, "dpdm");
716 if (IS_ERR(chg->dpdm_reg)) {
717 smblib_err(chg, "Couldn't get dpdm regulator rc=%ld\n",
718 PTR_ERR(chg->dpdm_reg));
719 chg->dpdm_reg = NULL;
720 }
Abhijeet Dharmapurikar9dd61292017-01-25 16:40:08 -0800721 }
722
Abhijeet Dharmapurikar025e63a2017-02-24 14:06:22 -0800723 if (chg->dpdm_reg && !regulator_is_enabled(chg->dpdm_reg)) {
724 smblib_dbg(chg, PR_MISC, "enabling DPDM regulator\n");
725 rc = regulator_enable(chg->dpdm_reg);
726 if (rc < 0)
727 smblib_err(chg, "Couldn't enable dpdm regulator rc=%d\n",
728 rc);
729 }
730
Ashay Jaiswal8507aa52017-04-14 09:42:32 +0530731 chg->uusb_apsd_rerun_done = true;
Abhijeet Dharmapurikar025e63a2017-02-24 14:06:22 -0800732 smblib_rerun_apsd(chg);
733
Abhijeet Dharmapurikar9dd61292017-01-25 16:40:08 -0800734 return 0;
735}
736
Ashay Jaiswal6d308da2017-02-18 09:59:23 +0530737static int smblib_get_pulse_cnt(struct smb_charger *chg, int *count)
738{
739 int rc;
740 u8 val[2];
741
742 switch (chg->smb_version) {
743 case PMI8998_SUBTYPE:
744 rc = smblib_read(chg, QC_PULSE_COUNT_STATUS_REG, val);
745 if (rc) {
746 pr_err("failed to read QC_PULSE_COUNT_STATUS_REG rc=%d\n",
747 rc);
748 return rc;
749 }
750 *count = val[0] & QC_PULSE_COUNT_MASK;
751 break;
752 case PM660_SUBTYPE:
753 rc = smblib_multibyte_read(chg,
754 QC_PULSE_COUNT_STATUS_1_REG, val, 2);
755 if (rc) {
756 pr_err("failed to read QC_PULSE_COUNT_STATUS_1_REG rc=%d\n",
757 rc);
758 return rc;
759 }
760 *count = (val[1] << 8) | val[0];
761 break;
762 default:
763 smblib_dbg(chg, PR_PARALLEL, "unknown SMB chip %d\n",
764 chg->smb_version);
765 return -EINVAL;
766 }
767
768 return 0;
769}
770
Nicholas Troastbb76a142016-09-23 11:23:23 -0700771#define USBIN_25MA 25000
772#define USBIN_100MA 100000
773#define USBIN_150MA 150000
774#define USBIN_500MA 500000
775#define USBIN_900MA 900000
Abhijeet Dharmapurikar5e0bfbe2017-02-12 19:16:15 -0800776
Abhijeet Dharmapurikar5e0bfbe2017-02-12 19:16:15 -0800777static int set_sdp_current(struct smb_charger *chg, int icl_ua)
Nicholas Troast34db5032016-03-28 12:26:44 -0700778{
Abhijeet Dharmapurikar5e0bfbe2017-02-12 19:16:15 -0800779 int rc;
780 u8 icl_options;
Abhijeet Dharmapurikarc0ff65a2016-06-06 16:45:34 -0700781
Nicholas Troastbb76a142016-09-23 11:23:23 -0700782 /* power source is SDP */
783 switch (icl_ua) {
784 case USBIN_100MA:
785 /* USB 2.0 100mA */
786 icl_options = 0;
787 break;
788 case USBIN_150MA:
789 /* USB 3.0 150mA */
790 icl_options = CFG_USB3P0_SEL_BIT;
791 break;
792 case USBIN_500MA:
793 /* USB 2.0 500mA */
794 icl_options = USB51_MODE_BIT;
795 break;
796 case USBIN_900MA:
797 /* USB 3.0 900mA */
798 icl_options = CFG_USB3P0_SEL_BIT | USB51_MODE_BIT;
799 break;
800 default:
Abhijeet Dharmapurikar31b98f32016-10-14 12:25:23 -0700801 smblib_err(chg, "ICL %duA isn't supported for SDP\n", icl_ua);
Abhijeet Dharmapurikar5e0bfbe2017-02-12 19:16:15 -0800802 return -EINVAL;
Nicholas Troastbb76a142016-09-23 11:23:23 -0700803 }
Nicholas Troast34db5032016-03-28 12:26:44 -0700804
Nicholas Troastbb76a142016-09-23 11:23:23 -0700805 rc = smblib_masked_write(chg, USBIN_ICL_OPTIONS_REG,
Abhijeet Dharmapurikar5e0bfbe2017-02-12 19:16:15 -0800806 CFG_USB3P0_SEL_BIT | USB51_MODE_BIT, icl_options);
Nicholas Troast34db5032016-03-28 12:26:44 -0700807 if (rc < 0) {
Abhijeet Dharmapurikar74021fc2017-02-06 18:39:19 -0800808 smblib_err(chg, "Couldn't set ICL options rc=%d\n", rc);
Nicholas Troast34db5032016-03-28 12:26:44 -0700809 return rc;
810 }
811
Abhijeet Dharmapurikar5e0bfbe2017-02-12 19:16:15 -0800812 return rc;
813}
814
Abhijeet Dharmapurikareecf5582017-04-24 13:33:07 -0700815static int get_sdp_current(struct smb_charger *chg, int *icl_ua)
816{
817 int rc;
818 u8 icl_options;
819 bool usb3 = false;
820
821 rc = smblib_read(chg, USBIN_ICL_OPTIONS_REG, &icl_options);
822 if (rc < 0) {
823 smblib_err(chg, "Couldn't get ICL options rc=%d\n", rc);
824 return rc;
825 }
826
827 usb3 = (icl_options & CFG_USB3P0_SEL_BIT);
828
829 if (icl_options & USB51_MODE_BIT)
830 *icl_ua = usb3 ? USBIN_900MA : USBIN_500MA;
831 else
832 *icl_ua = usb3 ? USBIN_150MA : USBIN_100MA;
833
834 return rc;
835}
836
Ashay Jaiswalae1586d2017-03-22 23:18:51 +0530837int smblib_set_icl_current(struct smb_charger *chg, int icl_ua)
Abhijeet Dharmapurikar5e0bfbe2017-02-12 19:16:15 -0800838{
Abhijeet Dharmapurikar5e0bfbe2017-02-12 19:16:15 -0800839 int rc = 0;
840 bool override;
841 union power_supply_propval pval;
842
843 /* suspend and return if 25mA or less is requested */
Ashay Jaiswalae1586d2017-03-22 23:18:51 +0530844 if (icl_ua < USBIN_25MA)
Abhijeet Dharmapurikar5e0bfbe2017-02-12 19:16:15 -0800845 return smblib_set_usb_suspend(chg, true);
846
847 disable_irq_nosync(chg->irq_info[USBIN_ICL_CHANGE_IRQ].irq);
Ashay Jaiswalae1586d2017-03-22 23:18:51 +0530848 if (icl_ua == INT_MAX)
Abhijeet Dharmapurikar5e0bfbe2017-02-12 19:16:15 -0800849 goto override_suspend_config;
850
851 rc = smblib_get_prop_typec_mode(chg, &pval);
Nicholas Troast34db5032016-03-28 12:26:44 -0700852 if (rc < 0) {
Abhijeet Dharmapurikar5e0bfbe2017-02-12 19:16:15 -0800853 smblib_err(chg, "Couldn't get typeC mode rc = %d\n", rc);
854 goto enable_icl_changed_interrupt;
Nicholas Troast34db5032016-03-28 12:26:44 -0700855 }
856
Abhijeet Dharmapurikar5e0bfbe2017-02-12 19:16:15 -0800857 /* configure current */
858 if (pval.intval == POWER_SUPPLY_TYPEC_SOURCE_DEFAULT
859 && (chg->usb_psy_desc.type == POWER_SUPPLY_TYPE_USB)) {
860 rc = set_sdp_current(chg, icl_ua);
861 if (rc < 0) {
862 smblib_err(chg, "Couldn't set SDP ICL rc=%d\n", rc);
863 goto enable_icl_changed_interrupt;
864 }
865 } else {
Abhijeet Dharmapurikarf59c8352017-03-23 14:04:05 -0700866 rc = smblib_set_charge_param(chg, &chg->param.usb_icl, icl_ua);
Abhijeet Dharmapurikar5e0bfbe2017-02-12 19:16:15 -0800867 if (rc < 0) {
868 smblib_err(chg, "Couldn't set HC ICL rc=%d\n", rc);
869 goto enable_icl_changed_interrupt;
870 }
871 }
872
873override_suspend_config:
874 /* determine if override needs to be enforced */
875 override = true;
Ashay Jaiswalae1586d2017-03-22 23:18:51 +0530876 if (icl_ua == INT_MAX) {
Abhijeet Dharmapurikar5e0bfbe2017-02-12 19:16:15 -0800877 /* remove override if no voters - hw defaults is desired */
878 override = false;
879 } else if (pval.intval == POWER_SUPPLY_TYPEC_SOURCE_DEFAULT) {
880 if (chg->usb_psy_desc.type == POWER_SUPPLY_TYPE_USB)
881 /* For std cable with type = SDP never override */
882 override = false;
883 else if (chg->usb_psy_desc.type == POWER_SUPPLY_TYPE_USB_CDP
Abhijeet Dharmapurikarf59c8352017-03-23 14:04:05 -0700884 && icl_ua == 1500000)
Abhijeet Dharmapurikar5e0bfbe2017-02-12 19:16:15 -0800885 /*
886 * For std cable with type = CDP override only if
887 * current is not 1500mA
888 */
889 override = false;
890 }
891
892 /* enforce override */
893 rc = smblib_masked_write(chg, USBIN_ICL_OPTIONS_REG,
894 USBIN_MODE_CHG_BIT, override ? USBIN_MODE_CHG_BIT : 0);
895
Abhijeet Dharmapurikar74021fc2017-02-06 18:39:19 -0800896 rc = smblib_icl_override(chg, override);
897 if (rc < 0) {
898 smblib_err(chg, "Couldn't set ICL override rc=%d\n", rc);
Abhijeet Dharmapurikar5e0bfbe2017-02-12 19:16:15 -0800899 goto enable_icl_changed_interrupt;
Abhijeet Dharmapurikar74021fc2017-02-06 18:39:19 -0800900 }
901
Abhijeet Dharmapurikar5e0bfbe2017-02-12 19:16:15 -0800902 /* unsuspend after configuring current and override */
903 rc = smblib_set_usb_suspend(chg, false);
904 if (rc < 0) {
905 smblib_err(chg, "Couldn't resume input rc=%d\n", rc);
906 goto enable_icl_changed_interrupt;
907 }
908
909enable_icl_changed_interrupt:
910 enable_irq(chg->irq_info[USBIN_ICL_CHANGE_IRQ].irq);
Nicholas Troast34db5032016-03-28 12:26:44 -0700911 return rc;
912}
913
Abhijeet Dharmapurikareecf5582017-04-24 13:33:07 -0700914int smblib_get_icl_current(struct smb_charger *chg, int *icl_ua)
915{
916 int rc = 0;
917 u8 load_cfg;
918 bool override;
919 union power_supply_propval pval;
920
921 rc = smblib_get_prop_typec_mode(chg, &pval);
922 if (rc < 0) {
923 smblib_err(chg, "Couldn't get typeC mode rc = %d\n", rc);
924 return rc;
925 }
926
927 if ((pval.intval == POWER_SUPPLY_TYPEC_SOURCE_DEFAULT
928 || chg->micro_usb_mode)
929 && (chg->usb_psy_desc.type == POWER_SUPPLY_TYPE_USB)) {
930 rc = get_sdp_current(chg, icl_ua);
931 if (rc < 0) {
932 smblib_err(chg, "Couldn't get SDP ICL rc=%d\n", rc);
933 return rc;
934 }
935 } else {
936 rc = smblib_read(chg, USBIN_LOAD_CFG_REG, &load_cfg);
937 if (rc < 0) {
938 smblib_err(chg, "Couldn't get load cfg rc=%d\n", rc);
939 return rc;
940 }
941 override = load_cfg & ICL_OVERRIDE_AFTER_APSD_BIT;
942 if (!override)
943 return INT_MAX;
944
945 /* override is set */
946 rc = smblib_get_charge_param(chg, &chg->param.usb_icl, icl_ua);
947 if (rc < 0) {
948 smblib_err(chg, "Couldn't get HC ICL rc=%d\n", rc);
949 return rc;
950 }
951 }
952
953 return 0;
954}
955
Ashay Jaiswalae1586d2017-03-22 23:18:51 +0530956/*********************
957 * VOTABLE CALLBACKS *
958 *********************/
959
960static int smblib_dc_suspend_vote_callback(struct votable *votable, void *data,
961 int suspend, const char *client)
962{
963 struct smb_charger *chg = data;
964
965 /* resume input if suspend is invalid */
966 if (suspend < 0)
967 suspend = 0;
968
969 return smblib_set_dc_suspend(chg, (bool)suspend);
970}
971
Abhijeet Dharmapurikar8e9e7572016-06-06 16:13:14 -0700972static int smblib_dc_icl_vote_callback(struct votable *votable, void *data,
Abhijeet Dharmapurikarebb5e5c2016-05-17 20:09:16 -0700973 int icl_ua, const char *client)
Nicholas Troast34db5032016-03-28 12:26:44 -0700974{
Abhijeet Dharmapurikar8e9e7572016-06-06 16:13:14 -0700975 struct smb_charger *chg = data;
Nicholas Troast34db5032016-03-28 12:26:44 -0700976 int rc = 0;
Abhijeet Dharmapurikarc0ff65a2016-06-06 16:45:34 -0700977 bool suspend;
978
979 if (icl_ua < 0) {
980 smblib_dbg(chg, PR_MISC, "No Voter hence suspending\n");
981 icl_ua = 0;
982 }
983
984 suspend = (icl_ua < USBIN_25MA);
985 if (suspend)
986 goto suspend;
Nicholas Troast34db5032016-03-28 12:26:44 -0700987
988 rc = smblib_set_charge_param(chg, &chg->param.dc_icl, icl_ua);
Abhijeet Dharmapurikarc0ff65a2016-06-06 16:45:34 -0700989 if (rc < 0) {
Abhijeet Dharmapurikar31b98f32016-10-14 12:25:23 -0700990 smblib_err(chg, "Couldn't set DC input current limit rc=%d\n",
Abhijeet Dharmapurikarc0ff65a2016-06-06 16:45:34 -0700991 rc);
992 return rc;
993 }
994
995suspend:
996 rc = vote(chg->dc_suspend_votable, USER_VOTER, suspend, 0);
997 if (rc < 0) {
Abhijeet Dharmapurikar31b98f32016-10-14 12:25:23 -0700998 smblib_err(chg, "Couldn't vote to %s DC rc=%d\n",
Abhijeet Dharmapurikarc0ff65a2016-06-06 16:45:34 -0700999 suspend ? "suspend" : "resume", rc);
1000 return rc;
1001 }
Nicholas Troast34db5032016-03-28 12:26:44 -07001002 return rc;
1003}
1004
Abhijeet Dharmapurikar4b13c6e2016-10-05 15:15:10 -07001005static int smblib_pd_disallowed_votable_indirect_callback(
1006 struct votable *votable, void *data, int disallowed, const char *client)
1007{
1008 struct smb_charger *chg = data;
1009 int rc;
1010
1011 rc = vote(chg->pd_allowed_votable, PD_DISALLOWED_INDIRECT_VOTER,
1012 !disallowed, 0);
1013
1014 return rc;
1015}
1016
Harry Yang223c6282016-06-14 15:48:36 -07001017static int smblib_awake_vote_callback(struct votable *votable, void *data,
1018 int awake, const char *client)
1019{
1020 struct smb_charger *chg = data;
1021
1022 if (awake)
1023 pm_stay_awake(chg->dev);
1024 else
1025 pm_relax(chg->dev);
1026
1027 return 0;
1028}
1029
Abhijeet Dharmapurikaree54de02016-07-08 14:51:47 -07001030static int smblib_chg_disable_vote_callback(struct votable *votable, void *data,
1031 int chg_disable, const char *client)
1032{
1033 struct smb_charger *chg = data;
1034 int rc;
1035
1036 rc = smblib_masked_write(chg, CHARGING_ENABLE_CMD_REG,
1037 CHARGING_ENABLE_CMD_BIT,
1038 chg_disable ? 0 : CHARGING_ENABLE_CMD_BIT);
1039 if (rc < 0) {
Abhijeet Dharmapurikar31b98f32016-10-14 12:25:23 -07001040 smblib_err(chg, "Couldn't %s charging rc=%d\n",
Abhijeet Dharmapurikaree54de02016-07-08 14:51:47 -07001041 chg_disable ? "disable" : "enable", rc);
1042 return rc;
1043 }
1044
1045 return 0;
1046}
Harry Yangaba1f5f2016-09-28 10:47:29 -07001047
1048static int smblib_pl_enable_indirect_vote_callback(struct votable *votable,
1049 void *data, int chg_enable, const char *client)
1050{
1051 struct smb_charger *chg = data;
1052
1053 vote(chg->pl_disable_votable, PL_INDIRECT_VOTER, !chg_enable, 0);
1054
1055 return 0;
1056}
1057
Ashay Jaiswal4aa2c0c2016-12-07 19:39:38 +05301058static int smblib_hvdcp_enable_vote_callback(struct votable *votable,
Abhijeet Dharmapurikarf0b0a042016-10-10 16:43:43 -07001059 void *data,
Ashay Jaiswal4aa2c0c2016-12-07 19:39:38 +05301060 int hvdcp_enable, const char *client)
Abhijeet Dharmapurikarf0b0a042016-10-10 16:43:43 -07001061{
1062 struct smb_charger *chg = data;
1063 int rc;
Ashay Jaiswal6d308da2017-02-18 09:59:23 +05301064 u8 val = HVDCP_AUTH_ALG_EN_CFG_BIT | HVDCP_EN_BIT;
Abhijeet Dharmapurikar3c93db32017-04-17 17:36:14 -07001065 u8 stat;
Ashay Jaiswal6d308da2017-02-18 09:59:23 +05301066
1067 /* vote to enable/disable HW autonomous INOV */
1068 vote(chg->hvdcp_hw_inov_dis_votable, client, !hvdcp_enable, 0);
Abhijeet Dharmapurikarf0b0a042016-10-10 16:43:43 -07001069
1070 /*
1071 * Disable the autonomous bit and auth bit for disabling hvdcp.
1072 * This ensures only qc 2.0 detection runs but no vbus
1073 * negotiation happens.
1074 */
Ashay Jaiswal4aa2c0c2016-12-07 19:39:38 +05301075 if (!hvdcp_enable)
Abhijeet Dharmapurikarf0b0a042016-10-10 16:43:43 -07001076 val = HVDCP_EN_BIT;
1077
1078 rc = smblib_masked_write(chg, USBIN_OPTIONS_1_CFG_REG,
Ashay Jaiswal6d308da2017-02-18 09:59:23 +05301079 HVDCP_EN_BIT | HVDCP_AUTH_ALG_EN_CFG_BIT,
Abhijeet Dharmapurikarf0b0a042016-10-10 16:43:43 -07001080 val);
1081 if (rc < 0) {
Abhijeet Dharmapurikar31b98f32016-10-14 12:25:23 -07001082 smblib_err(chg, "Couldn't %s hvdcp rc=%d\n",
Ashay Jaiswal4aa2c0c2016-12-07 19:39:38 +05301083 hvdcp_enable ? "enable" : "disable", rc);
Abhijeet Dharmapurikarf0b0a042016-10-10 16:43:43 -07001084 return rc;
1085 }
1086
Abhijeet Dharmapurikar3c93db32017-04-17 17:36:14 -07001087 rc = smblib_read(chg, APSD_STATUS_REG, &stat);
1088 if (rc < 0) {
1089 smblib_err(chg, "Couldn't read APSD status rc=%d\n", rc);
1090 return rc;
1091 }
1092
1093 /* re-run APSD if HVDCP was detected */
1094 if (stat & QC_CHARGER_BIT)
1095 smblib_rerun_apsd(chg);
1096
Abhijeet Dharmapurikarf0b0a042016-10-10 16:43:43 -07001097 return 0;
1098}
1099
Ashay Jaiswal4aa2c0c2016-12-07 19:39:38 +05301100static int smblib_hvdcp_disable_indirect_vote_callback(struct votable *votable,
1101 void *data, int hvdcp_disable, const char *client)
1102{
1103 struct smb_charger *chg = data;
1104
1105 vote(chg->hvdcp_enable_votable, HVDCP_INDIRECT_VOTER,
1106 !hvdcp_disable, 0);
1107
1108 return 0;
1109}
1110
Abhijeet Dharmapurikarf8a7a4a2016-10-07 18:46:45 -07001111static int smblib_apsd_disable_vote_callback(struct votable *votable,
1112 void *data,
1113 int apsd_disable, const char *client)
1114{
1115 struct smb_charger *chg = data;
1116 int rc;
1117
Nicholas Troastec4703c2017-01-30 14:52:33 -08001118 if (apsd_disable) {
Nicholas Troastec4703c2017-01-30 14:52:33 -08001119 rc = smblib_masked_write(chg, USBIN_OPTIONS_1_CFG_REG,
1120 AUTO_SRC_DETECT_BIT,
1121 0);
1122 if (rc < 0) {
1123 smblib_err(chg, "Couldn't disable APSD rc=%d\n", rc);
1124 return rc;
1125 }
1126 } else {
1127 rc = smblib_masked_write(chg, USBIN_OPTIONS_1_CFG_REG,
1128 AUTO_SRC_DETECT_BIT,
1129 AUTO_SRC_DETECT_BIT);
1130 if (rc < 0) {
1131 smblib_err(chg, "Couldn't enable APSD rc=%d\n", rc);
1132 return rc;
1133 }
Abhijeet Dharmapurikarf8a7a4a2016-10-07 18:46:45 -07001134 }
1135
1136 return 0;
1137}
Nicholas Troast8995a702016-12-05 10:22:22 -08001138
Ashay Jaiswal6d308da2017-02-18 09:59:23 +05301139static int smblib_hvdcp_hw_inov_dis_vote_callback(struct votable *votable,
1140 void *data, int disable, const char *client)
1141{
1142 struct smb_charger *chg = data;
1143 int rc;
1144
1145 if (disable) {
1146 /*
1147 * the pulse count register get zeroed when autonomous mode is
1148 * disabled. Track that in variables before disabling
1149 */
1150 rc = smblib_get_pulse_cnt(chg, &chg->pulse_cnt);
1151 if (rc < 0) {
1152 pr_err("failed to read QC_PULSE_COUNT_STATUS_REG rc=%d\n",
1153 rc);
1154 return rc;
1155 }
1156 }
1157
1158 rc = smblib_masked_write(chg, USBIN_OPTIONS_1_CFG_REG,
1159 HVDCP_AUTONOMOUS_MODE_EN_CFG_BIT,
1160 disable ? 0 : HVDCP_AUTONOMOUS_MODE_EN_CFG_BIT);
1161 if (rc < 0) {
1162 smblib_err(chg, "Couldn't %s hvdcp rc=%d\n",
1163 disable ? "disable" : "enable", rc);
1164 return rc;
1165 }
1166
1167 return rc;
1168}
1169
Harry Yang4bf7d962017-03-13 16:51:43 -07001170static int smblib_usb_irq_enable_vote_callback(struct votable *votable,
1171 void *data, int enable, const char *client)
1172{
1173 struct smb_charger *chg = data;
1174
1175 if (!chg->irq_info[INPUT_CURRENT_LIMIT_IRQ].irq ||
1176 !chg->irq_info[HIGH_DUTY_CYCLE_IRQ].irq)
1177 return 0;
1178
1179 if (enable) {
1180 enable_irq(chg->irq_info[INPUT_CURRENT_LIMIT_IRQ].irq);
1181 enable_irq(chg->irq_info[HIGH_DUTY_CYCLE_IRQ].irq);
1182 } else {
1183 disable_irq(chg->irq_info[INPUT_CURRENT_LIMIT_IRQ].irq);
1184 disable_irq(chg->irq_info[HIGH_DUTY_CYCLE_IRQ].irq);
1185 }
1186
1187 return 0;
1188}
1189
Abhijeet Dharmapurikar3c93db32017-04-17 17:36:14 -07001190static int smblib_typec_irq_disable_vote_callback(struct votable *votable,
1191 void *data, int disable, const char *client)
1192{
1193 struct smb_charger *chg = data;
1194
1195 if (!chg->irq_info[TYPE_C_CHANGE_IRQ].irq)
1196 return 0;
1197
1198 if (disable)
1199 disable_irq_nosync(chg->irq_info[TYPE_C_CHANGE_IRQ].irq);
1200 else
1201 enable_irq(chg->irq_info[TYPE_C_CHANGE_IRQ].irq);
1202
1203 return 0;
1204}
1205
Nicholas Troast8995a702016-12-05 10:22:22 -08001206/*******************
1207 * VCONN REGULATOR *
1208 * *****************/
1209
Nicholas Troastb11015f2017-01-17 17:56:45 -08001210#define MAX_OTG_SS_TRIES 2
Nicholas Troast8995a702016-12-05 10:22:22 -08001211static int _smblib_vconn_regulator_enable(struct regulator_dev *rdev)
1212{
1213 struct smb_charger *chg = rdev_get_drvdata(rdev);
Abhijeet Dharmapurikarb0403c42017-04-17 12:26:26 -07001214 u8 otg_stat, val;
Nicholas Troastb11015f2017-01-17 17:56:45 -08001215 int rc = 0, i;
Nicholas Troast8995a702016-12-05 10:22:22 -08001216
1217 if (!chg->external_vconn) {
Nicholas Troastb11015f2017-01-17 17:56:45 -08001218 /*
1219 * Hardware based OTG soft start should complete within 1ms, so
1220 * wait for 2ms in the worst case.
1221 */
1222 for (i = 0; i < MAX_OTG_SS_TRIES; ++i) {
1223 usleep_range(1000, 1100);
1224 rc = smblib_read(chg, OTG_STATUS_REG, &otg_stat);
1225 if (rc < 0) {
1226 smblib_err(chg, "Couldn't read OTG status rc=%d\n",
1227 rc);
1228 return rc;
1229 }
1230
1231 if (otg_stat & BOOST_SOFTSTART_DONE_BIT)
1232 break;
Nicholas Troast8995a702016-12-05 10:22:22 -08001233 }
1234
Nicholas Troastb11015f2017-01-17 17:56:45 -08001235 if (!(otg_stat & BOOST_SOFTSTART_DONE_BIT)) {
1236 smblib_err(chg, "Couldn't enable VCONN; OTG soft start failed\n");
Nicholas Troast8995a702016-12-05 10:22:22 -08001237 return -EAGAIN;
1238 }
1239 }
1240
1241 /*
1242 * VCONN_EN_ORIENTATION is overloaded with overriding the CC pin used
1243 * for Vconn, and it should be set with reverse polarity of CC_OUT.
1244 */
Nicholas Troastb11015f2017-01-17 17:56:45 -08001245 smblib_dbg(chg, PR_OTG, "enabling VCONN\n");
Abhijeet Dharmapurikarb0403c42017-04-17 12:26:26 -07001246 val = chg->typec_status[3] &
1247 CC_ORIENTATION_BIT ? 0 : VCONN_EN_ORIENTATION_BIT;
Nicholas Troast8995a702016-12-05 10:22:22 -08001248 rc = smblib_masked_write(chg, TYPE_C_INTRPT_ENB_SOFTWARE_CTRL_REG,
1249 VCONN_EN_VALUE_BIT | VCONN_EN_ORIENTATION_BIT,
Abhijeet Dharmapurikarb0403c42017-04-17 12:26:26 -07001250 VCONN_EN_VALUE_BIT | val);
Nicholas Troast8995a702016-12-05 10:22:22 -08001251 if (rc < 0) {
1252 smblib_err(chg, "Couldn't enable vconn setting rc=%d\n", rc);
1253 return rc;
1254 }
1255
1256 return rc;
1257}
1258
1259int smblib_vconn_regulator_enable(struct regulator_dev *rdev)
1260{
1261 struct smb_charger *chg = rdev_get_drvdata(rdev);
1262 int rc = 0;
1263
Nicholas Troastb11015f2017-01-17 17:56:45 -08001264 mutex_lock(&chg->otg_oc_lock);
Nicholas Troast8995a702016-12-05 10:22:22 -08001265 if (chg->vconn_en)
1266 goto unlock;
1267
1268 rc = _smblib_vconn_regulator_enable(rdev);
1269 if (rc >= 0)
1270 chg->vconn_en = true;
1271
1272unlock:
Nicholas Troastb11015f2017-01-17 17:56:45 -08001273 mutex_unlock(&chg->otg_oc_lock);
Nicholas Troast8995a702016-12-05 10:22:22 -08001274 return rc;
1275}
1276
1277static int _smblib_vconn_regulator_disable(struct regulator_dev *rdev)
1278{
1279 struct smb_charger *chg = rdev_get_drvdata(rdev);
1280 int rc = 0;
1281
Nicholas Troastb11015f2017-01-17 17:56:45 -08001282 smblib_dbg(chg, PR_OTG, "disabling VCONN\n");
Nicholas Troast8995a702016-12-05 10:22:22 -08001283 rc = smblib_masked_write(chg, TYPE_C_INTRPT_ENB_SOFTWARE_CTRL_REG,
1284 VCONN_EN_VALUE_BIT, 0);
1285 if (rc < 0)
1286 smblib_err(chg, "Couldn't disable vconn regulator rc=%d\n", rc);
1287
1288 return rc;
1289}
1290
1291int smblib_vconn_regulator_disable(struct regulator_dev *rdev)
1292{
1293 struct smb_charger *chg = rdev_get_drvdata(rdev);
1294 int rc = 0;
1295
Nicholas Troastb11015f2017-01-17 17:56:45 -08001296 mutex_lock(&chg->otg_oc_lock);
Nicholas Troast8995a702016-12-05 10:22:22 -08001297 if (!chg->vconn_en)
1298 goto unlock;
1299
1300 rc = _smblib_vconn_regulator_disable(rdev);
1301 if (rc >= 0)
1302 chg->vconn_en = false;
1303
1304unlock:
Nicholas Troastb11015f2017-01-17 17:56:45 -08001305 mutex_unlock(&chg->otg_oc_lock);
Nicholas Troast8995a702016-12-05 10:22:22 -08001306 return rc;
1307}
1308
1309int smblib_vconn_regulator_is_enabled(struct regulator_dev *rdev)
1310{
1311 struct smb_charger *chg = rdev_get_drvdata(rdev);
1312 int ret;
1313
Nicholas Troastb11015f2017-01-17 17:56:45 -08001314 mutex_lock(&chg->otg_oc_lock);
Nicholas Troast8995a702016-12-05 10:22:22 -08001315 ret = chg->vconn_en;
Nicholas Troastb11015f2017-01-17 17:56:45 -08001316 mutex_unlock(&chg->otg_oc_lock);
Nicholas Troast8995a702016-12-05 10:22:22 -08001317 return ret;
1318}
1319
Nicholas Troast34db5032016-03-28 12:26:44 -07001320/*****************
1321 * OTG REGULATOR *
1322 *****************/
Ashay Jaiswal7c241382017-03-06 15:26:38 +05301323#define MAX_RETRY 15
1324#define MIN_DELAY_US 2000
1325#define MAX_DELAY_US 9000
Nicholas Troast8995a702016-12-05 10:22:22 -08001326static int _smblib_vbus_regulator_enable(struct regulator_dev *rdev)
Nicholas Troast34db5032016-03-28 12:26:44 -07001327{
1328 struct smb_charger *chg = rdev_get_drvdata(rdev);
Ashay Jaiswal7c241382017-03-06 15:26:38 +05301329 int rc, retry_count = 0, min_delay = MIN_DELAY_US;
1330 u8 stat;
Nicholas Troast34db5032016-03-28 12:26:44 -07001331
Nicholas Troastb11015f2017-01-17 17:56:45 -08001332 smblib_dbg(chg, PR_OTG, "halt 1 in 8 mode\n");
Harry Yang360bd532016-09-26 11:03:22 -07001333 rc = smblib_masked_write(chg, OTG_ENG_OTG_CFG_REG,
1334 ENG_BUCKBOOST_HALT1_8_MODE_BIT,
1335 ENG_BUCKBOOST_HALT1_8_MODE_BIT);
1336 if (rc < 0) {
Abhijeet Dharmapurikar31b98f32016-10-14 12:25:23 -07001337 smblib_err(chg, "Couldn't set OTG_ENG_OTG_CFG_REG rc=%d\n",
Harry Yang360bd532016-09-26 11:03:22 -07001338 rc);
1339 return rc;
1340 }
1341
Nicholas Troastb11015f2017-01-17 17:56:45 -08001342 smblib_dbg(chg, PR_OTG, "enabling OTG\n");
Harry Yang360bd532016-09-26 11:03:22 -07001343 rc = smblib_write(chg, CMD_OTG_REG, OTG_EN_BIT);
1344 if (rc < 0) {
Abhijeet Dharmapurikar31b98f32016-10-14 12:25:23 -07001345 smblib_err(chg, "Couldn't enable OTG regulator rc=%d\n", rc);
Harry Yang360bd532016-09-26 11:03:22 -07001346 return rc;
1347 }
1348
Ashay Jaiswal7c241382017-03-06 15:26:38 +05301349 if (chg->wa_flags & OTG_WA) {
1350 /* check for softstart */
1351 do {
1352 usleep_range(min_delay, min_delay + 100);
1353 rc = smblib_read(chg, OTG_STATUS_REG, &stat);
1354 if (rc < 0) {
1355 smblib_err(chg,
1356 "Couldn't read OTG status rc=%d\n",
1357 rc);
1358 goto out;
1359 }
1360
1361 if (stat & BOOST_SOFTSTART_DONE_BIT) {
1362 rc = smblib_set_charge_param(chg,
1363 &chg->param.otg_cl, chg->otg_cl_ua);
1364 if (rc < 0)
1365 smblib_err(chg,
1366 "Couldn't set otg limit\n");
1367 break;
1368 }
1369
1370 /* increase the delay for following iterations */
1371 if (retry_count > 5)
1372 min_delay = MAX_DELAY_US;
1373 } while (retry_count++ < MAX_RETRY);
1374
1375 if (retry_count >= MAX_RETRY) {
1376 smblib_dbg(chg, PR_OTG, "Boost Softstart not done\n");
1377 goto out;
1378 }
1379 }
1380
1381 return 0;
1382out:
1383 /* disable OTG if softstart failed */
1384 smblib_write(chg, CMD_OTG_REG, 0);
Nicholas Troast34db5032016-03-28 12:26:44 -07001385 return rc;
1386}
1387
Nicholas Troast8995a702016-12-05 10:22:22 -08001388int smblib_vbus_regulator_enable(struct regulator_dev *rdev)
Nicholas Troast34db5032016-03-28 12:26:44 -07001389{
1390 struct smb_charger *chg = rdev_get_drvdata(rdev);
1391 int rc = 0;
1392
Nicholas Troastb11015f2017-01-17 17:56:45 -08001393 mutex_lock(&chg->otg_oc_lock);
Nicholas Troast8995a702016-12-05 10:22:22 -08001394 if (chg->otg_en)
1395 goto unlock;
1396
Harry Yanga2fb0e32017-03-22 22:45:25 -07001397 if (!chg->usb_icl_votable) {
1398 chg->usb_icl_votable = find_votable("USB_ICL");
1399
1400 if (!chg->usb_icl_votable)
1401 return -EINVAL;
1402 }
1403 vote(chg->usb_icl_votable, USBIN_USBIN_BOOST_VOTER, true, 0);
1404
Nicholas Troast8995a702016-12-05 10:22:22 -08001405 rc = _smblib_vbus_regulator_enable(rdev);
1406 if (rc >= 0)
1407 chg->otg_en = true;
1408
1409unlock:
Nicholas Troastb11015f2017-01-17 17:56:45 -08001410 mutex_unlock(&chg->otg_oc_lock);
Nicholas Troast8995a702016-12-05 10:22:22 -08001411 return rc;
1412}
1413
1414static int _smblib_vbus_regulator_disable(struct regulator_dev *rdev)
1415{
1416 struct smb_charger *chg = rdev_get_drvdata(rdev);
1417 int rc;
Nicholas Troast8995a702016-12-05 10:22:22 -08001418
Nicholas Troastb11015f2017-01-17 17:56:45 -08001419 if (!chg->external_vconn && chg->vconn_en) {
1420 smblib_dbg(chg, PR_OTG, "Killing VCONN before disabling OTG\n");
1421 rc = _smblib_vconn_regulator_disable(rdev);
Nicholas Troast07a69002017-01-20 13:52:10 -08001422 if (rc < 0)
Nicholas Troastb11015f2017-01-17 17:56:45 -08001423 smblib_err(chg, "Couldn't disable VCONN rc=%d\n", rc);
Nicholas Troast8995a702016-12-05 10:22:22 -08001424 }
1425
Ashay Jaiswal7c241382017-03-06 15:26:38 +05301426 if (chg->wa_flags & OTG_WA) {
1427 /* set OTG current limit to minimum value */
1428 rc = smblib_set_charge_param(chg, &chg->param.otg_cl,
1429 chg->param.otg_cl.min_u);
1430 if (rc < 0) {
1431 smblib_err(chg,
1432 "Couldn't set otg current limit rc=%d\n", rc);
1433 return rc;
1434 }
1435 }
1436
Nicholas Troastb11015f2017-01-17 17:56:45 -08001437 smblib_dbg(chg, PR_OTG, "disabling OTG\n");
Harry Yang360bd532016-09-26 11:03:22 -07001438 rc = smblib_write(chg, CMD_OTG_REG, 0);
1439 if (rc < 0) {
Abhijeet Dharmapurikar31b98f32016-10-14 12:25:23 -07001440 smblib_err(chg, "Couldn't disable OTG regulator rc=%d\n", rc);
Harry Yang360bd532016-09-26 11:03:22 -07001441 return rc;
1442 }
1443
Nicholas Troastb11015f2017-01-17 17:56:45 -08001444 smblib_dbg(chg, PR_OTG, "start 1 in 8 mode\n");
Harry Yang360bd532016-09-26 11:03:22 -07001445 rc = smblib_masked_write(chg, OTG_ENG_OTG_CFG_REG,
1446 ENG_BUCKBOOST_HALT1_8_MODE_BIT, 0);
1447 if (rc < 0) {
Nicholas Troast8995a702016-12-05 10:22:22 -08001448 smblib_err(chg, "Couldn't set OTG_ENG_OTG_CFG_REG rc=%d\n", rc);
Harry Yang360bd532016-09-26 11:03:22 -07001449 return rc;
1450 }
1451
Nicholas Troast8995a702016-12-05 10:22:22 -08001452 return 0;
1453}
Nicholas Troast34db5032016-03-28 12:26:44 -07001454
Nicholas Troast8995a702016-12-05 10:22:22 -08001455int smblib_vbus_regulator_disable(struct regulator_dev *rdev)
1456{
1457 struct smb_charger *chg = rdev_get_drvdata(rdev);
1458 int rc = 0;
1459
Nicholas Troastb11015f2017-01-17 17:56:45 -08001460 mutex_lock(&chg->otg_oc_lock);
Nicholas Troast8995a702016-12-05 10:22:22 -08001461 if (!chg->otg_en)
1462 goto unlock;
1463
1464 rc = _smblib_vbus_regulator_disable(rdev);
1465 if (rc >= 0)
1466 chg->otg_en = false;
1467
Harry Yanga2fb0e32017-03-22 22:45:25 -07001468 if (chg->usb_icl_votable)
1469 vote(chg->usb_icl_votable, USBIN_USBIN_BOOST_VOTER, false, 0);
Nicholas Troast8995a702016-12-05 10:22:22 -08001470unlock:
Nicholas Troastb11015f2017-01-17 17:56:45 -08001471 mutex_unlock(&chg->otg_oc_lock);
Nicholas Troast34db5032016-03-28 12:26:44 -07001472 return rc;
1473}
1474
1475int smblib_vbus_regulator_is_enabled(struct regulator_dev *rdev)
1476{
1477 struct smb_charger *chg = rdev_get_drvdata(rdev);
Nicholas Troast8995a702016-12-05 10:22:22 -08001478 int ret;
Nicholas Troast34db5032016-03-28 12:26:44 -07001479
Nicholas Troastb11015f2017-01-17 17:56:45 -08001480 mutex_lock(&chg->otg_oc_lock);
Nicholas Troast8995a702016-12-05 10:22:22 -08001481 ret = chg->otg_en;
Nicholas Troastb11015f2017-01-17 17:56:45 -08001482 mutex_unlock(&chg->otg_oc_lock);
Nicholas Troast8995a702016-12-05 10:22:22 -08001483 return ret;
Nicholas Troast34db5032016-03-28 12:26:44 -07001484}
1485
1486/********************
1487 * BATT PSY GETTERS *
1488 ********************/
1489
1490int smblib_get_prop_input_suspend(struct smb_charger *chg,
1491 union power_supply_propval *val)
1492{
Abhijeet Dharmapurikar5e0bfbe2017-02-12 19:16:15 -08001493 val->intval
1494 = (get_client_vote(chg->usb_icl_votable, USER_VOTER) == 0)
1495 && get_client_vote(chg->dc_suspend_votable, USER_VOTER);
Nicholas Troast34db5032016-03-28 12:26:44 -07001496 return 0;
1497}
1498
1499int smblib_get_prop_batt_present(struct smb_charger *chg,
1500 union power_supply_propval *val)
1501{
1502 int rc;
1503 u8 stat;
1504
1505 rc = smblib_read(chg, BATIF_BASE + INT_RT_STS_OFFSET, &stat);
1506 if (rc < 0) {
Abhijeet Dharmapurikar31b98f32016-10-14 12:25:23 -07001507 smblib_err(chg, "Couldn't read BATIF_INT_RT_STS rc=%d\n", rc);
Nicholas Troast34db5032016-03-28 12:26:44 -07001508 return rc;
1509 }
1510
1511 val->intval = !(stat & (BAT_THERM_OR_ID_MISSING_RT_STS_BIT
1512 | BAT_TERMINAL_MISSING_RT_STS_BIT));
1513
1514 return rc;
1515}
1516
1517int smblib_get_prop_batt_capacity(struct smb_charger *chg,
1518 union power_supply_propval *val)
1519{
Harry Yang5e1a5222016-07-26 15:16:04 -07001520 int rc = -EINVAL;
1521
Abhijeet Dharmapurikar9e7e48c2016-08-23 12:55:49 -07001522 if (chg->fake_capacity >= 0) {
1523 val->intval = chg->fake_capacity;
1524 return 0;
1525 }
1526
Harry Yang5e1a5222016-07-26 15:16:04 -07001527 if (chg->bms_psy)
1528 rc = power_supply_get_property(chg->bms_psy,
1529 POWER_SUPPLY_PROP_CAPACITY, val);
1530 return rc;
Nicholas Troast34db5032016-03-28 12:26:44 -07001531}
1532
1533int smblib_get_prop_batt_status(struct smb_charger *chg,
1534 union power_supply_propval *val)
1535{
Abhijeet Dharmapurikarec43bb42017-01-17 20:00:08 -08001536 union power_supply_propval pval = {0, };
1537 bool usb_online, dc_online;
Nicholas Troast8cb77552016-09-23 11:50:18 -07001538 u8 stat;
1539 int rc;
Nicholas Troast34db5032016-03-28 12:26:44 -07001540
Abhijeet Dharmapurikarec43bb42017-01-17 20:00:08 -08001541 rc = smblib_get_prop_usb_online(chg, &pval);
1542 if (rc < 0) {
1543 smblib_err(chg, "Couldn't get usb online property rc=%d\n",
1544 rc);
1545 return rc;
1546 }
1547 usb_online = (bool)pval.intval;
1548
1549 rc = smblib_get_prop_dc_online(chg, &pval);
1550 if (rc < 0) {
1551 smblib_err(chg, "Couldn't get dc online property rc=%d\n",
1552 rc);
1553 return rc;
1554 }
1555 dc_online = (bool)pval.intval;
1556
Nicholas Troast34db5032016-03-28 12:26:44 -07001557 rc = smblib_read(chg, BATTERY_CHARGER_STATUS_1_REG, &stat);
1558 if (rc < 0) {
Abhijeet Dharmapurikar31b98f32016-10-14 12:25:23 -07001559 smblib_err(chg, "Couldn't read BATTERY_CHARGER_STATUS_1 rc=%d\n",
Nicholas Troast34db5032016-03-28 12:26:44 -07001560 rc);
1561 return rc;
1562 }
Nicholas Troast34db5032016-03-28 12:26:44 -07001563 stat = stat & BATTERY_CHARGER_STATUS_MASK;
Abhijeet Dharmapurikarec43bb42017-01-17 20:00:08 -08001564
1565 if (!usb_online && !dc_online) {
1566 switch (stat) {
1567 case TERMINATE_CHARGE:
1568 case INHIBIT_CHARGE:
1569 val->intval = POWER_SUPPLY_STATUS_FULL;
1570 break;
1571 default:
1572 val->intval = POWER_SUPPLY_STATUS_DISCHARGING;
1573 break;
1574 }
1575 return rc;
1576 }
1577
Nicholas Troast8cb77552016-09-23 11:50:18 -07001578 switch (stat) {
1579 case TRICKLE_CHARGE:
1580 case PRE_CHARGE:
1581 case FAST_CHARGE:
1582 case FULLON_CHARGE:
1583 case TAPER_CHARGE:
Nicholas Troast34db5032016-03-28 12:26:44 -07001584 val->intval = POWER_SUPPLY_STATUS_CHARGING;
Nicholas Troast8cb77552016-09-23 11:50:18 -07001585 break;
1586 case TERMINATE_CHARGE:
1587 case INHIBIT_CHARGE:
1588 val->intval = POWER_SUPPLY_STATUS_FULL;
1589 break;
1590 case DISABLE_CHARGE:
1591 val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING;
1592 break;
1593 default:
1594 val->intval = POWER_SUPPLY_STATUS_UNKNOWN;
1595 break;
1596 }
Nicholas Troast34db5032016-03-28 12:26:44 -07001597
Harry Yang7ecc1a12017-04-06 12:24:56 -07001598 if (val->intval != POWER_SUPPLY_STATUS_CHARGING)
1599 return 0;
1600
Harry Yangc3c28d12017-04-17 16:41:19 -07001601 rc = smblib_read(chg, BATTERY_CHARGER_STATUS_7_REG, &stat);
Harry Yang7ecc1a12017-04-06 12:24:56 -07001602 if (rc < 0) {
1603 smblib_err(chg, "Couldn't read BATTERY_CHARGER_STATUS_2 rc=%d\n",
1604 rc);
1605 return rc;
1606 }
1607
Harry Yangc3c28d12017-04-17 16:41:19 -07001608 stat &= ENABLE_TRICKLE_BIT | ENABLE_PRE_CHARGING_BIT |
1609 ENABLE_FAST_CHARGING_BIT | ENABLE_FULLON_MODE_BIT;
1610 if (!stat)
Harry Yang7ecc1a12017-04-06 12:24:56 -07001611 val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING;
1612
Nicholas Troast8cb77552016-09-23 11:50:18 -07001613 return 0;
Nicholas Troast34db5032016-03-28 12:26:44 -07001614}
1615
1616int smblib_get_prop_batt_charge_type(struct smb_charger *chg,
1617 union power_supply_propval *val)
1618{
1619 int rc;
1620 u8 stat;
1621
1622 rc = smblib_read(chg, BATTERY_CHARGER_STATUS_1_REG, &stat);
1623 if (rc < 0) {
Abhijeet Dharmapurikar31b98f32016-10-14 12:25:23 -07001624 smblib_err(chg, "Couldn't read BATTERY_CHARGER_STATUS_1 rc=%d\n",
Nicholas Troast34db5032016-03-28 12:26:44 -07001625 rc);
1626 return rc;
1627 }
Nicholas Troast34db5032016-03-28 12:26:44 -07001628
1629 switch (stat & BATTERY_CHARGER_STATUS_MASK) {
1630 case TRICKLE_CHARGE:
1631 case PRE_CHARGE:
1632 val->intval = POWER_SUPPLY_CHARGE_TYPE_TRICKLE;
1633 break;
1634 case FAST_CHARGE:
1635 case FULLON_CHARGE:
1636 val->intval = POWER_SUPPLY_CHARGE_TYPE_FAST;
1637 break;
1638 case TAPER_CHARGE:
1639 val->intval = POWER_SUPPLY_CHARGE_TYPE_TAPER;
1640 break;
1641 default:
1642 val->intval = POWER_SUPPLY_CHARGE_TYPE_NONE;
1643 }
1644
1645 return rc;
1646}
1647
1648int smblib_get_prop_batt_health(struct smb_charger *chg,
1649 union power_supply_propval *val)
1650{
Subbaraman Narayanamurthya379c4f2016-10-21 17:30:46 -07001651 union power_supply_propval pval;
Nicholas Troast34db5032016-03-28 12:26:44 -07001652 int rc;
1653 u8 stat;
1654
1655 rc = smblib_read(chg, BATTERY_CHARGER_STATUS_2_REG, &stat);
1656 if (rc < 0) {
Abhijeet Dharmapurikar31b98f32016-10-14 12:25:23 -07001657 smblib_err(chg, "Couldn't read BATTERY_CHARGER_STATUS_2 rc=%d\n",
Nicholas Troast34db5032016-03-28 12:26:44 -07001658 rc);
1659 return rc;
1660 }
1661 smblib_dbg(chg, PR_REGISTER, "BATTERY_CHARGER_STATUS_2 = 0x%02x\n",
1662 stat);
1663
1664 if (stat & CHARGER_ERROR_STATUS_BAT_OV_BIT) {
Subbaraman Narayanamurthya379c4f2016-10-21 17:30:46 -07001665 rc = smblib_get_prop_batt_voltage_now(chg, &pval);
1666 if (!rc) {
1667 /*
1668 * If Vbatt is within 40mV above Vfloat, then don't
1669 * treat it as overvoltage.
1670 */
1671 if (pval.intval >=
1672 get_effective_result(chg->fv_votable) + 40000) {
1673 val->intval = POWER_SUPPLY_HEALTH_OVERVOLTAGE;
1674 smblib_err(chg, "battery over-voltage\n");
1675 goto done;
1676 }
1677 }
Nicholas Troast34db5032016-03-28 12:26:44 -07001678 }
1679
Harry Yang668fc5e2016-07-12 16:51:47 -07001680 if (stat & BAT_TEMP_STATUS_TOO_COLD_BIT)
Nicholas Troast34db5032016-03-28 12:26:44 -07001681 val->intval = POWER_SUPPLY_HEALTH_COLD;
Harry Yang668fc5e2016-07-12 16:51:47 -07001682 else if (stat & BAT_TEMP_STATUS_TOO_HOT_BIT)
Nicholas Troast34db5032016-03-28 12:26:44 -07001683 val->intval = POWER_SUPPLY_HEALTH_OVERHEAT;
Harry Yang668fc5e2016-07-12 16:51:47 -07001684 else if (stat & BAT_TEMP_STATUS_COLD_SOFT_LIMIT_BIT)
Nicholas Troast34db5032016-03-28 12:26:44 -07001685 val->intval = POWER_SUPPLY_HEALTH_COOL;
Harry Yang668fc5e2016-07-12 16:51:47 -07001686 else if (stat & BAT_TEMP_STATUS_HOT_SOFT_LIMIT_BIT)
Nicholas Troast34db5032016-03-28 12:26:44 -07001687 val->intval = POWER_SUPPLY_HEALTH_WARM;
Harry Yang668fc5e2016-07-12 16:51:47 -07001688 else
Nicholas Troast34db5032016-03-28 12:26:44 -07001689 val->intval = POWER_SUPPLY_HEALTH_GOOD;
Nicholas Troast34db5032016-03-28 12:26:44 -07001690
1691done:
1692 return rc;
1693}
1694
Abhijeet Dharmapurikar99fb8942016-07-08 11:39:23 -07001695int smblib_get_prop_system_temp_level(struct smb_charger *chg,
1696 union power_supply_propval *val)
1697{
1698 val->intval = chg->system_temp_level;
1699 return 0;
1700}
1701
Abhijeet Dharmapurikaracf32002017-05-11 11:54:17 -07001702int smblib_get_prop_system_temp_level_max(struct smb_charger *chg,
1703 union power_supply_propval *val)
1704{
1705 val->intval = chg->thermal_levels;
1706 return 0;
1707}
1708
Abhijeet Dharmapurikar0e369002016-09-07 17:25:36 -07001709int smblib_get_prop_input_current_limited(struct smb_charger *chg,
1710 union power_supply_propval *val)
1711{
1712 u8 stat;
1713 int rc;
1714
1715 rc = smblib_read(chg, AICL_STATUS_REG, &stat);
1716 if (rc < 0) {
Abhijeet Dharmapurikar31b98f32016-10-14 12:25:23 -07001717 smblib_err(chg, "Couldn't read AICL_STATUS rc=%d\n", rc);
Abhijeet Dharmapurikar0e369002016-09-07 17:25:36 -07001718 return rc;
1719 }
1720 val->intval = (stat & SOFT_ILIMIT_BIT) || chg->is_hdc;
1721 return 0;
1722}
1723
Nicholas Troast66b21d72016-09-20 15:33:20 -07001724int smblib_get_prop_batt_voltage_now(struct smb_charger *chg,
1725 union power_supply_propval *val)
1726{
1727 int rc;
1728
1729 if (!chg->bms_psy)
1730 return -EINVAL;
1731
1732 rc = power_supply_get_property(chg->bms_psy,
1733 POWER_SUPPLY_PROP_VOLTAGE_NOW, val);
1734 return rc;
1735}
1736
1737int smblib_get_prop_batt_current_now(struct smb_charger *chg,
1738 union power_supply_propval *val)
1739{
1740 int rc;
1741
1742 if (!chg->bms_psy)
1743 return -EINVAL;
1744
1745 rc = power_supply_get_property(chg->bms_psy,
1746 POWER_SUPPLY_PROP_CURRENT_NOW, val);
1747 return rc;
1748}
1749
1750int smblib_get_prop_batt_temp(struct smb_charger *chg,
1751 union power_supply_propval *val)
1752{
1753 int rc;
1754
1755 if (!chg->bms_psy)
1756 return -EINVAL;
1757
1758 rc = power_supply_get_property(chg->bms_psy,
1759 POWER_SUPPLY_PROP_TEMP, val);
1760 return rc;
1761}
1762
Harry Yangbedee332016-08-31 16:14:29 -07001763int smblib_get_prop_step_chg_step(struct smb_charger *chg,
1764 union power_supply_propval *val)
1765{
1766 int rc;
1767 u8 stat;
1768
1769 if (!chg->step_chg_enabled) {
1770 val->intval = -1;
1771 return 0;
1772 }
1773
1774 rc = smblib_read(chg, BATTERY_CHARGER_STATUS_1_REG, &stat);
1775 if (rc < 0) {
Abhijeet Dharmapurikar31b98f32016-10-14 12:25:23 -07001776 smblib_err(chg, "Couldn't read BATTERY_CHARGER_STATUS_1 rc=%d\n",
Harry Yangbedee332016-08-31 16:14:29 -07001777 rc);
1778 return rc;
1779 }
1780
1781 val->intval = (stat & STEP_CHARGING_STATUS_MASK) >>
1782 STEP_CHARGING_STATUS_SHIFT;
1783
1784 return rc;
1785}
1786
Subbaraman Narayanamurthyb491d022016-10-10 20:22:48 -07001787int smblib_get_prop_batt_charge_done(struct smb_charger *chg,
1788 union power_supply_propval *val)
1789{
1790 int rc;
1791 u8 stat;
1792
1793 rc = smblib_read(chg, BATTERY_CHARGER_STATUS_1_REG, &stat);
1794 if (rc < 0) {
Abhijeet Dharmapurikar31b98f32016-10-14 12:25:23 -07001795 smblib_err(chg, "Couldn't read BATTERY_CHARGER_STATUS_1 rc=%d\n",
Subbaraman Narayanamurthyb491d022016-10-10 20:22:48 -07001796 rc);
1797 return rc;
1798 }
1799
1800 stat = stat & BATTERY_CHARGER_STATUS_MASK;
1801 val->intval = (stat == TERMINATE_CHARGE);
1802 return 0;
1803}
1804
Harry Yang40192cb2017-02-25 23:25:17 -08001805int smblib_get_prop_charge_qnovo_enable(struct smb_charger *chg,
1806 union power_supply_propval *val)
1807{
1808 int rc;
1809 u8 stat;
1810
1811 rc = smblib_read(chg, QNOVO_PT_ENABLE_CMD_REG, &stat);
1812 if (rc < 0) {
1813 smblib_err(chg, "Couldn't read QNOVO_PT_ENABLE_CMD rc=%d\n",
1814 rc);
1815 return rc;
1816 }
1817
1818 val->intval = (bool)(stat & QNOVO_PT_ENABLE_CMD_BIT);
1819 return 0;
1820}
1821
Nicholas Troast34db5032016-03-28 12:26:44 -07001822/***********************
1823 * BATTERY PSY SETTERS *
1824 ***********************/
1825
1826int smblib_set_prop_input_suspend(struct smb_charger *chg,
1827 const union power_supply_propval *val)
1828{
1829 int rc;
1830
Abhijeet Dharmapurikar5e0bfbe2017-02-12 19:16:15 -08001831 /* vote 0mA when suspended */
1832 rc = vote(chg->usb_icl_votable, USER_VOTER, (bool)val->intval, 0);
Nicholas Troast34db5032016-03-28 12:26:44 -07001833 if (rc < 0) {
Abhijeet Dharmapurikar31b98f32016-10-14 12:25:23 -07001834 smblib_err(chg, "Couldn't vote to %s USB rc=%d\n",
Nicholas Troast34db5032016-03-28 12:26:44 -07001835 (bool)val->intval ? "suspend" : "resume", rc);
1836 return rc;
1837 }
1838
1839 rc = vote(chg->dc_suspend_votable, USER_VOTER, (bool)val->intval, 0);
1840 if (rc < 0) {
Abhijeet Dharmapurikar31b98f32016-10-14 12:25:23 -07001841 smblib_err(chg, "Couldn't vote to %s DC rc=%d\n",
Nicholas Troast34db5032016-03-28 12:26:44 -07001842 (bool)val->intval ? "suspend" : "resume", rc);
1843 return rc;
1844 }
1845
Nicholas Troast61ff40f2016-07-08 10:59:22 -07001846 power_supply_changed(chg->batt_psy);
Nicholas Troast34db5032016-03-28 12:26:44 -07001847 return rc;
1848}
1849
Abhijeet Dharmapurikar9e7e48c2016-08-23 12:55:49 -07001850int smblib_set_prop_batt_capacity(struct smb_charger *chg,
1851 const union power_supply_propval *val)
1852{
1853 chg->fake_capacity = val->intval;
1854
1855 power_supply_changed(chg->batt_psy);
1856
1857 return 0;
1858}
1859
Abhijeet Dharmapurikar99fb8942016-07-08 11:39:23 -07001860int smblib_set_prop_system_temp_level(struct smb_charger *chg,
1861 const union power_supply_propval *val)
1862{
1863 if (val->intval < 0)
1864 return -EINVAL;
1865
1866 if (chg->thermal_levels <= 0)
1867 return -EINVAL;
1868
1869 if (val->intval > chg->thermal_levels)
1870 return -EINVAL;
1871
1872 chg->system_temp_level = val->intval;
Ashay Jaiswal147a6c32017-03-28 17:19:47 +05301873 /* disable parallel charge in case of system temp level */
1874 vote(chg->pl_disable_votable, THERMAL_DAEMON_VOTER,
1875 chg->system_temp_level ? true : false, 0);
1876
Abhijeet Dharmapurikar99fb8942016-07-08 11:39:23 -07001877 if (chg->system_temp_level == chg->thermal_levels)
Harry Yangaba1f5f2016-09-28 10:47:29 -07001878 return vote(chg->chg_disable_votable,
1879 THERMAL_DAEMON_VOTER, true, 0);
Abhijeet Dharmapurikar99fb8942016-07-08 11:39:23 -07001880
Harry Yangaba1f5f2016-09-28 10:47:29 -07001881 vote(chg->chg_disable_votable, THERMAL_DAEMON_VOTER, false, 0);
Abhijeet Dharmapurikar99fb8942016-07-08 11:39:23 -07001882 if (chg->system_temp_level == 0)
Harry Yangaba1f5f2016-09-28 10:47:29 -07001883 return vote(chg->fcc_votable, THERMAL_DAEMON_VOTER, false, 0);
Abhijeet Dharmapurikar99fb8942016-07-08 11:39:23 -07001884
Harry Yangaba1f5f2016-09-28 10:47:29 -07001885 vote(chg->fcc_votable, THERMAL_DAEMON_VOTER, true,
Abhijeet Dharmapurikar99fb8942016-07-08 11:39:23 -07001886 chg->thermal_mitigation[chg->system_temp_level]);
1887 return 0;
1888}
1889
Harry Yang40192cb2017-02-25 23:25:17 -08001890int smblib_set_prop_charge_qnovo_enable(struct smb_charger *chg,
1891 const union power_supply_propval *val)
1892{
1893 int rc = 0;
1894
1895 rc = smblib_masked_write(chg, QNOVO_PT_ENABLE_CMD_REG,
1896 QNOVO_PT_ENABLE_CMD_BIT,
1897 val->intval ? QNOVO_PT_ENABLE_CMD_BIT : 0);
1898 if (rc < 0) {
1899 dev_err(chg->dev, "Couldn't enable qnovo rc=%d\n", rc);
1900 return rc;
1901 }
1902
1903 return rc;
1904}
1905
Ashay Jaiswal6d308da2017-02-18 09:59:23 +05301906int smblib_rerun_aicl(struct smb_charger *chg)
1907{
Nicholas Troast20ae1912017-02-15 10:15:32 -08001908 int rc, settled_icl_ua;
1909 u8 stat;
Ashay Jaiswal6d308da2017-02-18 09:59:23 +05301910
Nicholas Troast20ae1912017-02-15 10:15:32 -08001911 rc = smblib_read(chg, POWER_PATH_STATUS_REG, &stat);
1912 if (rc < 0) {
1913 smblib_err(chg, "Couldn't read POWER_PATH_STATUS rc=%d\n",
1914 rc);
1915 return rc;
1916 }
1917
1918 /* USB is suspended so skip re-running AICL */
1919 if (stat & USBIN_SUSPEND_STS_BIT)
1920 return rc;
1921
1922 smblib_dbg(chg, PR_MISC, "re-running AICL\n");
Ashay Jaiswal6d308da2017-02-18 09:59:23 +05301923 switch (chg->smb_version) {
1924 case PMI8998_SUBTYPE:
Nicholas Troast20ae1912017-02-15 10:15:32 -08001925 rc = smblib_get_charge_param(chg, &chg->param.icl_stat,
1926 &settled_icl_ua);
1927 if (rc < 0) {
1928 smblib_err(chg, "Couldn't get settled ICL rc=%d\n", rc);
1929 return rc;
1930 }
1931
1932 vote(chg->usb_icl_votable, AICL_RERUN_VOTER, true,
1933 max(settled_icl_ua - chg->param.usb_icl.step_u,
1934 chg->param.usb_icl.step_u));
1935 vote(chg->usb_icl_votable, AICL_RERUN_VOTER, false, 0);
1936 break;
Ashay Jaiswal6d308da2017-02-18 09:59:23 +05301937 case PM660_SUBTYPE:
Nicholas Troast20ae1912017-02-15 10:15:32 -08001938 /*
1939 * Use restart_AICL instead of trigger_AICL as it runs the
1940 * complete AICL instead of starting from the last settled
1941 * value.
1942 */
1943 rc = smblib_masked_write(chg, CMD_HVDCP_2_REG,
1944 RESTART_AICL_BIT, RESTART_AICL_BIT);
1945 if (rc < 0)
1946 smblib_err(chg, "Couldn't write to CMD_HVDCP_2_REG rc=%d\n",
1947 rc);
Ashay Jaiswal6d308da2017-02-18 09:59:23 +05301948 break;
1949 default:
1950 smblib_dbg(chg, PR_PARALLEL, "unknown SMB chip %d\n",
1951 chg->smb_version);
1952 return -EINVAL;
1953 }
Ashay Jaiswal6d308da2017-02-18 09:59:23 +05301954
Nicholas Troast20ae1912017-02-15 10:15:32 -08001955 return 0;
Ashay Jaiswal6d308da2017-02-18 09:59:23 +05301956}
1957
1958static int smblib_dp_pulse(struct smb_charger *chg)
1959{
1960 int rc;
1961
1962 /* QC 3.0 increment */
1963 rc = smblib_masked_write(chg, CMD_HVDCP_2_REG, SINGLE_INCREMENT_BIT,
1964 SINGLE_INCREMENT_BIT);
1965 if (rc < 0)
1966 smblib_err(chg, "Couldn't write to CMD_HVDCP_2_REG rc=%d\n",
1967 rc);
1968
1969 return rc;
1970}
1971
1972static int smblib_dm_pulse(struct smb_charger *chg)
1973{
1974 int rc;
1975
1976 /* QC 3.0 decrement */
1977 rc = smblib_masked_write(chg, CMD_HVDCP_2_REG, SINGLE_DECREMENT_BIT,
1978 SINGLE_DECREMENT_BIT);
1979 if (rc < 0)
1980 smblib_err(chg, "Couldn't write to CMD_HVDCP_2_REG rc=%d\n",
1981 rc);
1982
1983 return rc;
1984}
1985
1986int smblib_dp_dm(struct smb_charger *chg, int val)
1987{
1988 int target_icl_ua, rc = 0;
1989
1990 switch (val) {
1991 case POWER_SUPPLY_DP_DM_DP_PULSE:
1992 rc = smblib_dp_pulse(chg);
1993 if (!rc)
1994 chg->pulse_cnt++;
1995 smblib_dbg(chg, PR_PARALLEL, "DP_DM_DP_PULSE rc=%d cnt=%d\n",
1996 rc, chg->pulse_cnt);
1997 break;
1998 case POWER_SUPPLY_DP_DM_DM_PULSE:
1999 rc = smblib_dm_pulse(chg);
2000 if (!rc && chg->pulse_cnt)
2001 chg->pulse_cnt--;
2002 smblib_dbg(chg, PR_PARALLEL, "DP_DM_DM_PULSE rc=%d cnt=%d\n",
2003 rc, chg->pulse_cnt);
2004 break;
2005 case POWER_SUPPLY_DP_DM_ICL_DOWN:
2006 chg->usb_icl_delta_ua -= 100000;
2007 target_icl_ua = get_effective_result(chg->usb_icl_votable);
2008 vote(chg->usb_icl_votable, SW_QC3_VOTER, true,
2009 target_icl_ua + chg->usb_icl_delta_ua);
2010 break;
2011 case POWER_SUPPLY_DP_DM_ICL_UP:
2012 default:
2013 break;
2014 }
2015
2016 return rc;
2017}
2018
Nicholas Troast34db5032016-03-28 12:26:44 -07002019/*******************
Harry Yangf3023592016-07-20 14:56:41 -07002020 * DC PSY GETTERS *
2021 *******************/
2022
2023int smblib_get_prop_dc_present(struct smb_charger *chg,
2024 union power_supply_propval *val)
2025{
Nicholas Troastdeae99c2016-11-14 09:13:01 -08002026 int rc;
Harry Yangf3023592016-07-20 14:56:41 -07002027 u8 stat;
2028
Nicholas Troastdeae99c2016-11-14 09:13:01 -08002029 rc = smblib_read(chg, DCIN_BASE + INT_RT_STS_OFFSET, &stat);
Harry Yangf3023592016-07-20 14:56:41 -07002030 if (rc < 0) {
Nicholas Troastdeae99c2016-11-14 09:13:01 -08002031 smblib_err(chg, "Couldn't read DCIN_RT_STS rc=%d\n", rc);
Harry Yangf3023592016-07-20 14:56:41 -07002032 return rc;
2033 }
Harry Yangf3023592016-07-20 14:56:41 -07002034
2035 val->intval = (bool)(stat & DCIN_PLUGIN_RT_STS_BIT);
Nicholas Troastdeae99c2016-11-14 09:13:01 -08002036 return 0;
Harry Yangf3023592016-07-20 14:56:41 -07002037}
2038
2039int smblib_get_prop_dc_online(struct smb_charger *chg,
2040 union power_supply_propval *val)
2041{
2042 int rc = 0;
2043 u8 stat;
2044
2045 if (get_client_vote(chg->dc_suspend_votable, USER_VOTER)) {
2046 val->intval = false;
2047 return rc;
2048 }
2049
2050 rc = smblib_read(chg, POWER_PATH_STATUS_REG, &stat);
2051 if (rc < 0) {
Abhijeet Dharmapurikar31b98f32016-10-14 12:25:23 -07002052 smblib_err(chg, "Couldn't read POWER_PATH_STATUS rc=%d\n",
Harry Yangf3023592016-07-20 14:56:41 -07002053 rc);
2054 return rc;
2055 }
2056 smblib_dbg(chg, PR_REGISTER, "POWER_PATH_STATUS = 0x%02x\n",
2057 stat);
2058
2059 val->intval = (stat & USE_DCIN_BIT) &&
Vic Wei7ade2842016-12-14 18:47:49 -08002060 (stat & VALID_INPUT_POWER_SOURCE_STS_BIT);
Harry Yangf3023592016-07-20 14:56:41 -07002061
2062 return rc;
2063}
2064
2065int smblib_get_prop_dc_current_max(struct smb_charger *chg,
2066 union power_supply_propval *val)
2067{
2068 val->intval = get_effective_result_locked(chg->dc_icl_votable);
2069 return 0;
2070}
2071
2072/*******************
Harry Yangd89ff1f2016-12-05 14:59:11 -08002073 * DC PSY SETTERS *
Harry Yangf3023592016-07-20 14:56:41 -07002074 * *****************/
2075
2076int smblib_set_prop_dc_current_max(struct smb_charger *chg,
2077 const union power_supply_propval *val)
2078{
2079 int rc;
2080
2081 rc = vote(chg->dc_icl_votable, USER_VOTER, true, val->intval);
2082 return rc;
2083}
2084
2085/*******************
Nicholas Troast34db5032016-03-28 12:26:44 -07002086 * USB PSY GETTERS *
2087 *******************/
2088
2089int smblib_get_prop_usb_present(struct smb_charger *chg,
2090 union power_supply_propval *val)
2091{
Nicholas Troastdeae99c2016-11-14 09:13:01 -08002092 int rc;
Nicholas Troast34db5032016-03-28 12:26:44 -07002093 u8 stat;
2094
Nicholas Troastdeae99c2016-11-14 09:13:01 -08002095 rc = smblib_read(chg, USBIN_BASE + INT_RT_STS_OFFSET, &stat);
Nicholas Troast34db5032016-03-28 12:26:44 -07002096 if (rc < 0) {
Nicholas Troastdeae99c2016-11-14 09:13:01 -08002097 smblib_err(chg, "Couldn't read USBIN_RT_STS rc=%d\n", rc);
Nicholas Troast34db5032016-03-28 12:26:44 -07002098 return rc;
2099 }
Nicholas Troast34db5032016-03-28 12:26:44 -07002100
Nicholas Troastdeae99c2016-11-14 09:13:01 -08002101 val->intval = (bool)(stat & USBIN_PLUGIN_RT_STS_BIT);
2102 return 0;
Nicholas Troast34db5032016-03-28 12:26:44 -07002103}
2104
2105int smblib_get_prop_usb_online(struct smb_charger *chg,
2106 union power_supply_propval *val)
2107{
2108 int rc = 0;
2109 u8 stat;
2110
Abhijeet Dharmapurikar84923af2017-03-23 14:07:07 -07002111 if (get_client_vote_locked(chg->usb_icl_votable, USER_VOTER) == 0) {
Nicholas Troast34db5032016-03-28 12:26:44 -07002112 val->intval = false;
2113 return rc;
2114 }
2115
2116 rc = smblib_read(chg, POWER_PATH_STATUS_REG, &stat);
2117 if (rc < 0) {
Abhijeet Dharmapurikar31b98f32016-10-14 12:25:23 -07002118 smblib_err(chg, "Couldn't read POWER_PATH_STATUS rc=%d\n",
Nicholas Troast34db5032016-03-28 12:26:44 -07002119 rc);
2120 return rc;
2121 }
2122 smblib_dbg(chg, PR_REGISTER, "POWER_PATH_STATUS = 0x%02x\n",
2123 stat);
2124
2125 val->intval = (stat & USE_USBIN_BIT) &&
Vic Wei7ade2842016-12-14 18:47:49 -08002126 (stat & VALID_INPUT_POWER_SOURCE_STS_BIT);
Nicholas Troast34db5032016-03-28 12:26:44 -07002127 return rc;
2128}
2129
2130int smblib_get_prop_usb_voltage_now(struct smb_charger *chg,
2131 union power_supply_propval *val)
2132{
Harry Yangba874ce2016-08-19 14:17:01 -07002133 int rc = 0;
Nicholas Troast34db5032016-03-28 12:26:44 -07002134
Harry Yangba874ce2016-08-19 14:17:01 -07002135 rc = smblib_get_prop_usb_present(chg, val);
2136 if (rc < 0 || !val->intval)
2137 return rc;
2138
2139 if (!chg->iio.usbin_v_chan ||
2140 PTR_ERR(chg->iio.usbin_v_chan) == -EPROBE_DEFER)
2141 chg->iio.usbin_v_chan = iio_channel_get(chg->dev, "usbin_v");
2142
2143 if (IS_ERR(chg->iio.usbin_v_chan))
2144 return PTR_ERR(chg->iio.usbin_v_chan);
2145
2146 return iio_read_channel_processed(chg->iio.usbin_v_chan, &val->intval);
Nicholas Troast34db5032016-03-28 12:26:44 -07002147}
2148
Abhijeet Dharmapurikard92eca62016-10-07 19:04:33 -07002149int smblib_get_prop_pd_current_max(struct smb_charger *chg,
2150 union power_supply_propval *val)
2151{
2152 val->intval = get_client_vote_locked(chg->usb_icl_votable, PD_VOTER);
2153 return 0;
2154}
2155
Nicholas Troast34db5032016-03-28 12:26:44 -07002156int smblib_get_prop_usb_current_max(struct smb_charger *chg,
2157 union power_supply_propval *val)
2158{
Abhijeet Dharmapurikard92eca62016-10-07 19:04:33 -07002159 val->intval = get_client_vote_locked(chg->usb_icl_votable,
2160 USB_PSY_VOTER);
Nicholas Troast34db5032016-03-28 12:26:44 -07002161 return 0;
2162}
2163
Harry Yangba874ce2016-08-19 14:17:01 -07002164int smblib_get_prop_usb_current_now(struct smb_charger *chg,
2165 union power_supply_propval *val)
2166{
2167 int rc = 0;
2168
2169 rc = smblib_get_prop_usb_present(chg, val);
2170 if (rc < 0 || !val->intval)
2171 return rc;
2172
2173 if (!chg->iio.usbin_i_chan ||
2174 PTR_ERR(chg->iio.usbin_i_chan) == -EPROBE_DEFER)
2175 chg->iio.usbin_i_chan = iio_channel_get(chg->dev, "usbin_i");
2176
2177 if (IS_ERR(chg->iio.usbin_i_chan))
2178 return PTR_ERR(chg->iio.usbin_i_chan);
2179
2180 return iio_read_channel_processed(chg->iio.usbin_i_chan, &val->intval);
2181}
2182
2183int smblib_get_prop_charger_temp(struct smb_charger *chg,
2184 union power_supply_propval *val)
2185{
2186 int rc;
2187
2188 if (!chg->iio.temp_chan ||
2189 PTR_ERR(chg->iio.temp_chan) == -EPROBE_DEFER)
2190 chg->iio.temp_chan = iio_channel_get(chg->dev, "charger_temp");
2191
2192 if (IS_ERR(chg->iio.temp_chan))
2193 return PTR_ERR(chg->iio.temp_chan);
2194
2195 rc = iio_read_channel_processed(chg->iio.temp_chan, &val->intval);
2196 val->intval /= 100;
2197 return rc;
2198}
2199
2200int smblib_get_prop_charger_temp_max(struct smb_charger *chg,
2201 union power_supply_propval *val)
2202{
2203 int rc;
2204
2205 if (!chg->iio.temp_max_chan ||
2206 PTR_ERR(chg->iio.temp_max_chan) == -EPROBE_DEFER)
2207 chg->iio.temp_max_chan = iio_channel_get(chg->dev,
2208 "charger_temp_max");
2209 if (IS_ERR(chg->iio.temp_max_chan))
2210 return PTR_ERR(chg->iio.temp_max_chan);
2211
2212 rc = iio_read_channel_processed(chg->iio.temp_max_chan, &val->intval);
2213 val->intval /= 100;
2214 return rc;
2215}
2216
Nicholas Troast34db5032016-03-28 12:26:44 -07002217int smblib_get_prop_typec_cc_orientation(struct smb_charger *chg,
2218 union power_supply_propval *val)
2219{
Abhijeet Dharmapurikarb0403c42017-04-17 12:26:26 -07002220 if (chg->typec_status[3] & CC_ATTACHED_BIT)
2221 val->intval =
2222 (bool)(chg->typec_status[3] & CC_ORIENTATION_BIT) + 1;
Nicholas Troast34db5032016-03-28 12:26:44 -07002223 else
2224 val->intval = 0;
2225
Abhijeet Dharmapurikarb0403c42017-04-17 12:26:26 -07002226 return 0;
Nicholas Troast34db5032016-03-28 12:26:44 -07002227}
2228
2229static const char * const smblib_typec_mode_name[] = {
2230 [POWER_SUPPLY_TYPEC_NONE] = "NONE",
2231 [POWER_SUPPLY_TYPEC_SOURCE_DEFAULT] = "SOURCE_DEFAULT",
2232 [POWER_SUPPLY_TYPEC_SOURCE_MEDIUM] = "SOURCE_MEDIUM",
2233 [POWER_SUPPLY_TYPEC_SOURCE_HIGH] = "SOURCE_HIGH",
2234 [POWER_SUPPLY_TYPEC_NON_COMPLIANT] = "NON_COMPLIANT",
2235 [POWER_SUPPLY_TYPEC_SINK] = "SINK",
2236 [POWER_SUPPLY_TYPEC_SINK_POWERED_CABLE] = "SINK_POWERED_CABLE",
2237 [POWER_SUPPLY_TYPEC_SINK_DEBUG_ACCESSORY] = "SINK_DEBUG_ACCESSORY",
2238 [POWER_SUPPLY_TYPEC_SINK_AUDIO_ADAPTER] = "SINK_AUDIO_ADAPTER",
2239 [POWER_SUPPLY_TYPEC_POWERED_CABLE_ONLY] = "POWERED_CABLE_ONLY",
2240};
2241
2242static int smblib_get_prop_ufp_mode(struct smb_charger *chg)
2243{
Abhijeet Dharmapurikarb0403c42017-04-17 12:26:26 -07002244 switch (chg->typec_status[0]) {
Nicholas Troast34db5032016-03-28 12:26:44 -07002245 case 0:
2246 return POWER_SUPPLY_TYPEC_NONE;
2247 case UFP_TYPEC_RDSTD_BIT:
2248 return POWER_SUPPLY_TYPEC_SOURCE_DEFAULT;
2249 case UFP_TYPEC_RD1P5_BIT:
2250 return POWER_SUPPLY_TYPEC_SOURCE_MEDIUM;
2251 case UFP_TYPEC_RD3P0_BIT:
2252 return POWER_SUPPLY_TYPEC_SOURCE_HIGH;
2253 default:
2254 break;
2255 }
2256
2257 return POWER_SUPPLY_TYPEC_NON_COMPLIANT;
2258}
2259
2260static int smblib_get_prop_dfp_mode(struct smb_charger *chg)
2261{
Abhijeet Dharmapurikarb0403c42017-04-17 12:26:26 -07002262 switch (chg->typec_status[1] & DFP_TYPEC_MASK) {
Nicholas Troast34db5032016-03-28 12:26:44 -07002263 case DFP_RA_RA_BIT:
2264 return POWER_SUPPLY_TYPEC_SINK_AUDIO_ADAPTER;
2265 case DFP_RD_RD_BIT:
2266 return POWER_SUPPLY_TYPEC_SINK_DEBUG_ACCESSORY;
2267 case DFP_RD_RA_VCONN_BIT:
2268 return POWER_SUPPLY_TYPEC_SINK_POWERED_CABLE;
2269 case DFP_RD_OPEN_BIT:
2270 return POWER_SUPPLY_TYPEC_SINK;
2271 case DFP_RA_OPEN_BIT:
2272 return POWER_SUPPLY_TYPEC_POWERED_CABLE_ONLY;
2273 default:
2274 break;
2275 }
2276
2277 return POWER_SUPPLY_TYPEC_NONE;
2278}
2279
2280int smblib_get_prop_typec_mode(struct smb_charger *chg,
2281 union power_supply_propval *val)
2282{
Abhijeet Dharmapurikarb0403c42017-04-17 12:26:26 -07002283 if (!(chg->typec_status[3] & TYPEC_DEBOUNCE_DONE_STATUS_BIT)) {
Nicholas Troast34db5032016-03-28 12:26:44 -07002284 val->intval = POWER_SUPPLY_TYPEC_NONE;
Abhijeet Dharmapurikarb0403c42017-04-17 12:26:26 -07002285 return 0;
Nicholas Troast34db5032016-03-28 12:26:44 -07002286 }
2287
Abhijeet Dharmapurikarb0403c42017-04-17 12:26:26 -07002288 if (chg->typec_status[3] & UFP_DFP_MODE_STATUS_BIT)
Nicholas Troast34db5032016-03-28 12:26:44 -07002289 val->intval = smblib_get_prop_dfp_mode(chg);
2290 else
2291 val->intval = smblib_get_prop_ufp_mode(chg);
2292
Abhijeet Dharmapurikarb0403c42017-04-17 12:26:26 -07002293 return 0;
Nicholas Troast34db5032016-03-28 12:26:44 -07002294}
2295
2296int smblib_get_prop_typec_power_role(struct smb_charger *chg,
2297 union power_supply_propval *val)
2298{
2299 int rc = 0;
2300 u8 ctrl;
2301
2302 rc = smblib_read(chg, TYPE_C_INTRPT_ENB_SOFTWARE_CTRL_REG, &ctrl);
2303 if (rc < 0) {
Abhijeet Dharmapurikar31b98f32016-10-14 12:25:23 -07002304 smblib_err(chg, "Couldn't read TYPE_C_INTRPT_ENB_SOFTWARE_CTRL rc=%d\n",
Nicholas Troast34db5032016-03-28 12:26:44 -07002305 rc);
2306 return rc;
2307 }
2308 smblib_dbg(chg, PR_REGISTER, "TYPE_C_INTRPT_ENB_SOFTWARE_CTRL = 0x%02x\n",
2309 ctrl);
2310
2311 if (ctrl & TYPEC_DISABLE_CMD_BIT) {
2312 val->intval = POWER_SUPPLY_TYPEC_PR_NONE;
2313 return rc;
2314 }
2315
2316 switch (ctrl & (DFP_EN_CMD_BIT | UFP_EN_CMD_BIT)) {
2317 case 0:
2318 val->intval = POWER_SUPPLY_TYPEC_PR_DUAL;
2319 break;
2320 case DFP_EN_CMD_BIT:
2321 val->intval = POWER_SUPPLY_TYPEC_PR_SOURCE;
2322 break;
2323 case UFP_EN_CMD_BIT:
2324 val->intval = POWER_SUPPLY_TYPEC_PR_SINK;
2325 break;
2326 default:
2327 val->intval = POWER_SUPPLY_TYPEC_PR_NONE;
Abhijeet Dharmapurikar31b98f32016-10-14 12:25:23 -07002328 smblib_err(chg, "unsupported power role 0x%02lx\n",
Nicholas Troast34db5032016-03-28 12:26:44 -07002329 ctrl & (DFP_EN_CMD_BIT | UFP_EN_CMD_BIT));
2330 return -EINVAL;
2331 }
2332
2333 return rc;
2334}
2335
2336int smblib_get_prop_pd_allowed(struct smb_charger *chg,
2337 union power_supply_propval *val)
2338{
Abhijeet Dharmapurikarb9598872016-10-17 16:58:58 -07002339 val->intval = get_effective_result(chg->pd_allowed_votable);
Nicholas Troast34db5032016-03-28 12:26:44 -07002340 return 0;
2341}
2342
Nicholas Troast133a7f52016-06-29 13:48:20 -07002343int smblib_get_prop_input_current_settled(struct smb_charger *chg,
2344 union power_supply_propval *val)
2345{
2346 return smblib_get_charge_param(chg, &chg->param.icl_stat, &val->intval);
2347}
2348
Fenglin Wuef4730e2017-01-11 18:16:25 +08002349#define HVDCP3_STEP_UV 200000
2350int smblib_get_prop_input_voltage_settled(struct smb_charger *chg,
2351 union power_supply_propval *val)
2352{
2353 const struct apsd_result *apsd_result = smblib_get_apsd_result(chg);
2354 int rc, pulses;
2355 u8 stat;
2356
2357 val->intval = MICRO_5V;
2358 if (apsd_result == NULL) {
2359 smblib_err(chg, "APSD result is NULL\n");
2360 return 0;
2361 }
2362
2363 switch (apsd_result->pst) {
2364 case POWER_SUPPLY_TYPE_USB_HVDCP_3:
2365 rc = smblib_read(chg, QC_PULSE_COUNT_STATUS_REG, &stat);
2366 if (rc < 0) {
2367 smblib_err(chg,
2368 "Couldn't read QC_PULSE_COUNT rc=%d\n", rc);
2369 return 0;
2370 }
2371 pulses = (stat & QC_PULSE_COUNT_MASK);
2372 val->intval = MICRO_5V + HVDCP3_STEP_UV * pulses;
2373 break;
2374 default:
2375 val->intval = MICRO_5V;
2376 break;
2377 }
2378
2379 return 0;
2380}
2381
Abhijeet Dharmapurikarf8a7a4a2016-10-07 18:46:45 -07002382int smblib_get_prop_pd_in_hard_reset(struct smb_charger *chg,
2383 union power_supply_propval *val)
2384{
Abhijeet Dharmapurikar0e432812017-04-17 14:52:46 -07002385 val->intval = chg->pd_hard_reset;
Abhijeet Dharmapurikarf8a7a4a2016-10-07 18:46:45 -07002386 return 0;
2387}
2388
Abhijeet Dharmapurikarb9598872016-10-17 16:58:58 -07002389int smblib_get_pe_start(struct smb_charger *chg,
2390 union power_supply_propval *val)
2391{
2392 /*
2393 * hvdcp timeout voter is the last one to allow pd. Use its vote
2394 * to indicate start of pe engine
2395 */
2396 val->intval
2397 = !get_client_vote_locked(chg->pd_disallowed_votable_indirect,
2398 HVDCP_TIMEOUT_VOTER);
2399 return 0;
2400}
2401
Nicholas Troast7fdbd2e2017-02-08 10:47:37 -08002402int smblib_get_prop_die_health(struct smb_charger *chg,
Nicholas Troastb021dd92017-01-31 18:43:38 -08002403 union power_supply_propval *val)
2404{
Nicholas Troast7fdbd2e2017-02-08 10:47:37 -08002405 int rc;
Nicholas Troastb021dd92017-01-31 18:43:38 -08002406 u8 stat;
2407
2408 rc = smblib_read(chg, TEMP_RANGE_STATUS_REG, &stat);
2409 if (rc < 0) {
2410 smblib_err(chg, "Couldn't read TEMP_RANGE_STATUS_REG rc=%d\n",
2411 rc);
2412 return rc;
2413 }
2414
Nicholas Troast7fdbd2e2017-02-08 10:47:37 -08002415 /* TEMP_RANGE bits are mutually exclusive */
2416 switch (stat & TEMP_RANGE_MASK) {
2417 case TEMP_BELOW_RANGE_BIT:
2418 val->intval = POWER_SUPPLY_HEALTH_COOL;
2419 break;
2420 case TEMP_WITHIN_RANGE_BIT:
2421 val->intval = POWER_SUPPLY_HEALTH_WARM;
2422 break;
2423 case TEMP_ABOVE_RANGE_BIT:
2424 val->intval = POWER_SUPPLY_HEALTH_HOT;
2425 break;
2426 case ALERT_LEVEL_BIT:
2427 val->intval = POWER_SUPPLY_HEALTH_OVERHEAT;
2428 break;
2429 default:
2430 val->intval = POWER_SUPPLY_HEALTH_UNKNOWN;
Nicholas Troastb021dd92017-01-31 18:43:38 -08002431 }
2432
Nicholas Troastb021dd92017-01-31 18:43:38 -08002433 return 0;
2434}
2435
Nicholas Troast34db5032016-03-28 12:26:44 -07002436/*******************
2437 * USB PSY SETTERS *
2438 * *****************/
2439
Abhijeet Dharmapurikard92eca62016-10-07 19:04:33 -07002440int smblib_set_prop_pd_current_max(struct smb_charger *chg,
2441 const union power_supply_propval *val)
2442{
2443 int rc;
2444
2445 if (chg->pd_active)
2446 rc = vote(chg->usb_icl_votable, PD_VOTER, true, val->intval);
2447 else
2448 rc = -EPERM;
2449
2450 return rc;
2451}
2452
Nicholas Troast34db5032016-03-28 12:26:44 -07002453int smblib_set_prop_usb_current_max(struct smb_charger *chg,
2454 const union power_supply_propval *val)
2455{
Nicholas Troast8d33b7d2017-01-16 11:18:38 -08002456 int rc = 0;
Nicholas Troast34db5032016-03-28 12:26:44 -07002457
Abhijeet Dharmapurikard92eca62016-10-07 19:04:33 -07002458 if (!chg->pd_active) {
2459 rc = vote(chg->usb_icl_votable, USB_PSY_VOTER,
2460 true, val->intval);
2461 } else if (chg->system_suspend_supported) {
2462 if (val->intval <= USBIN_25MA)
Abhijeet Dharmapurikar95670872017-02-09 22:55:51 +05302463 rc = vote(chg->usb_icl_votable,
2464 PD_SUSPEND_SUPPORTED_VOTER, true, val->intval);
Abhijeet Dharmapurikard92eca62016-10-07 19:04:33 -07002465 else
Abhijeet Dharmapurikar95670872017-02-09 22:55:51 +05302466 rc = vote(chg->usb_icl_votable,
2467 PD_SUSPEND_SUPPORTED_VOTER, false, 0);
Abhijeet Dharmapurikard92eca62016-10-07 19:04:33 -07002468 }
Nicholas Troast34db5032016-03-28 12:26:44 -07002469 return rc;
2470}
2471
Harry Yangd89ff1f2016-12-05 14:59:11 -08002472int smblib_set_prop_boost_current(struct smb_charger *chg,
2473 const union power_supply_propval *val)
2474{
2475 int rc = 0;
2476
2477 rc = smblib_set_charge_param(chg, &chg->param.freq_boost,
2478 val->intval <= chg->boost_threshold_ua ?
Anirudh Ghayal4da3df92017-01-25 18:55:57 +05302479 chg->chg_freq.freq_below_otg_threshold :
2480 chg->chg_freq.freq_above_otg_threshold);
Harry Yangd89ff1f2016-12-05 14:59:11 -08002481 if (rc < 0) {
2482 dev_err(chg->dev, "Error in setting freq_boost rc=%d\n", rc);
2483 return rc;
2484 }
2485
2486 chg->boost_current_ua = val->intval;
2487 return rc;
2488}
2489
Nicholas Troast34db5032016-03-28 12:26:44 -07002490int smblib_set_prop_typec_power_role(struct smb_charger *chg,
2491 const union power_supply_propval *val)
2492{
2493 int rc = 0;
2494 u8 power_role;
2495
2496 switch (val->intval) {
2497 case POWER_SUPPLY_TYPEC_PR_NONE:
2498 power_role = TYPEC_DISABLE_CMD_BIT;
2499 break;
2500 case POWER_SUPPLY_TYPEC_PR_DUAL:
2501 power_role = 0;
2502 break;
2503 case POWER_SUPPLY_TYPEC_PR_SINK:
2504 power_role = UFP_EN_CMD_BIT;
2505 break;
2506 case POWER_SUPPLY_TYPEC_PR_SOURCE:
2507 power_role = DFP_EN_CMD_BIT;
2508 break;
2509 default:
Abhijeet Dharmapurikar31b98f32016-10-14 12:25:23 -07002510 smblib_err(chg, "power role %d not supported\n", val->intval);
Nicholas Troast34db5032016-03-28 12:26:44 -07002511 return -EINVAL;
2512 }
2513
Jack Pham54a39bd2017-03-29 18:59:37 -07002514 if (power_role == UFP_EN_CMD_BIT) {
2515 /* disable PBS workaround when forcing sink mode */
2516 rc = smblib_write(chg, TM_IO_DTEST4_SEL, 0x0);
2517 if (rc < 0) {
2518 smblib_err(chg, "Couldn't write to TM_IO_DTEST4_SEL rc=%d\n",
2519 rc);
2520 }
2521 } else {
2522 /* restore it back to 0xA5 */
2523 rc = smblib_write(chg, TM_IO_DTEST4_SEL, 0xA5);
2524 if (rc < 0) {
2525 smblib_err(chg, "Couldn't write to TM_IO_DTEST4_SEL rc=%d\n",
2526 rc);
2527 }
2528 }
2529
Nicholas Troast34db5032016-03-28 12:26:44 -07002530 rc = smblib_masked_write(chg, TYPE_C_INTRPT_ENB_SOFTWARE_CTRL_REG,
2531 TYPEC_POWER_ROLE_CMD_MASK, power_role);
2532 if (rc < 0) {
Abhijeet Dharmapurikar31b98f32016-10-14 12:25:23 -07002533 smblib_err(chg, "Couldn't write 0x%02x to TYPE_C_INTRPT_ENB_SOFTWARE_CTRL rc=%d\n",
Nicholas Troast34db5032016-03-28 12:26:44 -07002534 power_role, rc);
2535 return rc;
2536 }
2537
2538 return rc;
2539}
2540
2541int smblib_set_prop_usb_voltage_min(struct smb_charger *chg,
2542 const union power_supply_propval *val)
2543{
2544 int rc, min_uv;
2545
2546 min_uv = min(val->intval, chg->voltage_max_uv);
2547 rc = smblib_set_usb_pd_allowed_voltage(chg, min_uv,
2548 chg->voltage_max_uv);
2549 if (rc < 0) {
Abhijeet Dharmapurikar31b98f32016-10-14 12:25:23 -07002550 smblib_err(chg, "invalid max voltage %duV rc=%d\n",
Nicholas Troast34db5032016-03-28 12:26:44 -07002551 val->intval, rc);
2552 return rc;
2553 }
2554
Harry Yangaba1f5f2016-09-28 10:47:29 -07002555 chg->voltage_min_uv = min_uv;
Nicholas Troast34db5032016-03-28 12:26:44 -07002556 return rc;
2557}
2558
2559int smblib_set_prop_usb_voltage_max(struct smb_charger *chg,
2560 const union power_supply_propval *val)
2561{
2562 int rc, max_uv;
2563
2564 max_uv = max(val->intval, chg->voltage_min_uv);
2565 rc = smblib_set_usb_pd_allowed_voltage(chg, chg->voltage_min_uv,
2566 max_uv);
2567 if (rc < 0) {
Abhijeet Dharmapurikar31b98f32016-10-14 12:25:23 -07002568 smblib_err(chg, "invalid min voltage %duV rc=%d\n",
Nicholas Troast34db5032016-03-28 12:26:44 -07002569 val->intval, rc);
2570 return rc;
2571 }
2572
Harry Yangaba1f5f2016-09-28 10:47:29 -07002573 chg->voltage_max_uv = max_uv;
Nicholas Troast34db5032016-03-28 12:26:44 -07002574 return rc;
2575}
2576
2577int smblib_set_prop_pd_active(struct smb_charger *chg,
2578 const union power_supply_propval *val)
2579{
2580 int rc;
Abhijeet Dharmapurikar3c93db32017-04-17 17:36:14 -07002581 bool orientation, cc_debounced, sink_attached, hvdcp;
2582 u8 stat;
Nicholas Troast34db5032016-03-28 12:26:44 -07002583
Nicholas Troast8c28e0f2017-03-22 14:44:49 -07002584 if (!get_effective_result(chg->pd_allowed_votable))
Nicholas Troast34db5032016-03-28 12:26:44 -07002585 return -EINVAL;
Nicholas Troast34db5032016-03-28 12:26:44 -07002586
Abhijeet Dharmapurikar3c93db32017-04-17 17:36:14 -07002587 rc = smblib_read(chg, APSD_STATUS_REG, &stat);
2588 if (rc < 0) {
2589 smblib_err(chg, "Couldn't read APSD status rc=%d\n", rc);
2590 return rc;
2591 }
2592
2593 cc_debounced = (bool)
2594 (chg->typec_status[3] & TYPEC_DEBOUNCE_DONE_STATUS_BIT);
2595 sink_attached = (bool)
2596 (chg->typec_status[3] & UFP_DFP_MODE_STATUS_BIT);
2597 hvdcp = stat & QC_CHARGER_BIT;
2598
Nicholas Troast8c28e0f2017-03-22 14:44:49 -07002599 chg->pd_active = val->intval;
2600 if (chg->pd_active) {
2601 vote(chg->apsd_disable_votable, PD_VOTER, true, 0);
2602 vote(chg->pd_allowed_votable, PD_VOTER, true, 0);
2603 vote(chg->usb_irq_enable_votable, PD_VOTER, true, 0);
2604
2605 /*
2606 * VCONN_EN_ORIENTATION_BIT controls whether to use CC1 or CC2
2607 * line when TYPEC_SPARE_CFG_BIT (CC pin selection s/w override)
2608 * is set or when VCONN_EN_VALUE_BIT is set.
2609 */
Abhijeet Dharmapurikarb0403c42017-04-17 12:26:26 -07002610 orientation = chg->typec_status[3] & CC_ORIENTATION_BIT;
Harry Yang88acff42016-09-21 14:56:06 -07002611 rc = smblib_masked_write(chg,
Abhijeet Dharmapurikar716cd962016-10-14 12:50:37 -07002612 TYPE_C_INTRPT_ENB_SOFTWARE_CTRL_REG,
2613 VCONN_EN_ORIENTATION_BIT,
2614 orientation ? 0 : VCONN_EN_ORIENTATION_BIT);
Nicholas Troast8c28e0f2017-03-22 14:44:49 -07002615 if (rc < 0)
Abhijeet Dharmapurikar31b98f32016-10-14 12:25:23 -07002616 smblib_err(chg,
Harry Yang88acff42016-09-21 14:56:06 -07002617 "Couldn't enable vconn on CC line rc=%d\n", rc);
Nicholas Troast8c28e0f2017-03-22 14:44:49 -07002618
2619 /* SW controlled CC_OUT */
2620 rc = smblib_masked_write(chg, TAPER_TIMER_SEL_CFG_REG,
2621 TYPEC_SPARE_CFG_BIT, TYPEC_SPARE_CFG_BIT);
2622 if (rc < 0)
2623 smblib_err(chg, "Couldn't enable SW cc_out rc=%d\n",
2624 rc);
2625
Abhijeet Dharmapurikar95670872017-02-09 22:55:51 +05302626 /*
2627 * Enforce 500mA for PD until the real vote comes in later.
2628 * It is guaranteed that pd_active is set prior to
2629 * pd_current_max
2630 */
Harry Yangcd995202016-11-07 13:32:52 -08002631 rc = vote(chg->usb_icl_votable, PD_VOTER, true, USBIN_500MA);
Nicholas Troast8c28e0f2017-03-22 14:44:49 -07002632 if (rc < 0)
Harry Yangcd995202016-11-07 13:32:52 -08002633 smblib_err(chg, "Couldn't vote for USB ICL rc=%d\n",
Nicholas Troast8c28e0f2017-03-22 14:44:49 -07002634 rc);
Harry Yangcd995202016-11-07 13:32:52 -08002635
Nicholas Troastf9e44992017-03-14 09:06:56 -07002636 /* since PD was found the cable must be non-legacy */
2637 vote(chg->usb_icl_votable, LEGACY_UNKNOWN_VOTER, false, 0);
2638
Abhijeet Dharmapurikar7442e422017-02-08 13:35:14 -08002639 /* clear USB ICL vote for DCP_VOTER */
Harry Yang631b99e2016-11-17 11:24:25 -08002640 rc = vote(chg->usb_icl_votable, DCP_VOTER, false, 0);
Abhijeet Dharmapurikar7442e422017-02-08 13:35:14 -08002641 if (rc < 0)
Nicholas Troast8c28e0f2017-03-22 14:44:49 -07002642 smblib_err(chg, "Couldn't un-vote DCP from USB ICL rc=%d\n",
2643 rc);
Abhijeet Dharmapurikar7442e422017-02-08 13:35:14 -08002644
Abhijeet Dharmapurikar95670872017-02-09 22:55:51 +05302645 /* remove USB_PSY_VOTER */
2646 rc = vote(chg->usb_icl_votable, USB_PSY_VOTER, false, 0);
Nicholas Troast8c28e0f2017-03-22 14:44:49 -07002647 if (rc < 0)
Abhijeet Dharmapurikar95670872017-02-09 22:55:51 +05302648 smblib_err(chg, "Couldn't unvote USB_PSY rc=%d\n", rc);
Nicholas Troast8c28e0f2017-03-22 14:44:49 -07002649 } else {
2650 vote(chg->apsd_disable_votable, PD_VOTER, false, 0);
2651 vote(chg->pd_allowed_votable, PD_VOTER, true, 0);
2652 vote(chg->usb_irq_enable_votable, PD_VOTER, true, 0);
Abhijeet Dharmapurikar3c93db32017-04-17 17:36:14 -07002653 vote(chg->hvdcp_disable_votable_indirect, PD_INACTIVE_VOTER,
2654 false, 0);
Nicholas Troast8c28e0f2017-03-22 14:44:49 -07002655
2656 /* HW controlled CC_OUT */
2657 rc = smblib_masked_write(chg, TAPER_TIMER_SEL_CFG_REG,
2658 TYPEC_SPARE_CFG_BIT, 0);
2659 if (rc < 0)
2660 smblib_err(chg, "Couldn't enable HW cc_out rc=%d\n",
2661 rc);
2662
Abhijeet Dharmapurikar3c93db32017-04-17 17:36:14 -07002663 /*
2664 * This WA should only run for HVDCP. Non-legacy SDP/CDP could
2665 * draw more, but this WA will remove Rd causing VBUS to drop,
2666 * and data could be interrupted. Non-legacy DCP could also draw
2667 * more, but it may impact compliance.
2668 */
2669 if (!chg->typec_legacy_valid && cc_debounced &&
2670 !sink_attached && hvdcp)
2671 schedule_work(&chg->legacy_detection_work);
Harry Yang88acff42016-09-21 14:56:06 -07002672 }
2673
Harry Yang6607b4a2016-05-17 17:50:09 -07002674 smblib_update_usb_type(chg);
Abhijeet Dharmapurikar76e2af52016-10-06 17:25:01 -07002675 power_supply_changed(chg->usb_psy);
Nicholas Troast34db5032016-03-28 12:26:44 -07002676 return rc;
2677}
2678
Fenglin Wuedd70792016-11-22 13:16:19 +08002679int smblib_set_prop_ship_mode(struct smb_charger *chg,
2680 const union power_supply_propval *val)
2681{
2682 int rc;
2683
2684 smblib_dbg(chg, PR_MISC, "Set ship mode: %d!!\n", !!val->intval);
2685
2686 rc = smblib_masked_write(chg, SHIP_MODE_REG, SHIP_MODE_EN_BIT,
2687 !!val->intval ? SHIP_MODE_EN_BIT : 0);
2688 if (rc < 0)
2689 dev_err(chg->dev, "Couldn't %s ship mode, rc=%d\n",
2690 !!val->intval ? "enable" : "disable", rc);
2691
2692 return rc;
2693}
2694
Harry Yang5e2bb712016-10-18 16:47:48 -07002695int smblib_reg_block_update(struct smb_charger *chg,
2696 struct reg_info *entry)
2697{
2698 int rc = 0;
2699
2700 while (entry && entry->reg) {
2701 rc = smblib_read(chg, entry->reg, &entry->bak);
2702 if (rc < 0) {
2703 dev_err(chg->dev, "Error in reading %s rc=%d\n",
2704 entry->desc, rc);
2705 break;
2706 }
2707 entry->bak &= entry->mask;
2708
2709 rc = smblib_masked_write(chg, entry->reg,
2710 entry->mask, entry->val);
2711 if (rc < 0) {
2712 dev_err(chg->dev, "Error in writing %s rc=%d\n",
2713 entry->desc, rc);
2714 break;
2715 }
2716 entry++;
2717 }
2718
2719 return rc;
2720}
2721
2722int smblib_reg_block_restore(struct smb_charger *chg,
2723 struct reg_info *entry)
2724{
2725 int rc = 0;
2726
2727 while (entry && entry->reg) {
2728 rc = smblib_masked_write(chg, entry->reg,
2729 entry->mask, entry->bak);
2730 if (rc < 0) {
2731 dev_err(chg->dev, "Error in writing %s rc=%d\n",
2732 entry->desc, rc);
2733 break;
2734 }
2735 entry++;
2736 }
2737
2738 return rc;
2739}
2740
Harry Yang755a34b2016-11-01 01:18:51 -07002741static struct reg_info cc2_detach_settings[] = {
2742 {
2743 .reg = TYPE_C_CFG_2_REG,
2744 .mask = TYPE_C_UFP_MODE_BIT | EN_TRY_SOURCE_MODE_BIT,
2745 .val = TYPE_C_UFP_MODE_BIT,
2746 .desc = "TYPE_C_CFG_2_REG",
2747 },
2748 {
2749 .reg = TYPE_C_CFG_3_REG,
2750 .mask = EN_TRYSINK_MODE_BIT,
2751 .val = 0,
2752 .desc = "TYPE_C_CFG_3_REG",
2753 },
2754 {
2755 .reg = TAPER_TIMER_SEL_CFG_REG,
2756 .mask = TYPEC_SPARE_CFG_BIT,
2757 .val = TYPEC_SPARE_CFG_BIT,
2758 .desc = "TAPER_TIMER_SEL_CFG_REG",
2759 },
2760 {
2761 .reg = TYPE_C_INTRPT_ENB_SOFTWARE_CTRL_REG,
2762 .mask = VCONN_EN_ORIENTATION_BIT,
2763 .val = 0,
2764 .desc = "TYPE_C_INTRPT_ENB_SOFTWARE_CTRL_REG",
2765 },
2766 {
2767 .reg = MISC_CFG_REG,
2768 .mask = TCC_DEBOUNCE_20MS_BIT,
2769 .val = TCC_DEBOUNCE_20MS_BIT,
2770 .desc = "Tccdebounce time"
2771 },
2772 {
2773 },
2774};
2775
2776static int smblib_cc2_sink_removal_enter(struct smb_charger *chg)
2777{
Abhijeet Dharmapurikar0e432812017-04-17 14:52:46 -07002778 int rc, ccout, ufp_mode;
2779 u8 stat;
Harry Yang755a34b2016-11-01 01:18:51 -07002780
2781 if ((chg->wa_flags & TYPEC_CC2_REMOVAL_WA_BIT) == 0)
Abhijeet Dharmapurikar0e432812017-04-17 14:52:46 -07002782 return 0;
Harry Yang755a34b2016-11-01 01:18:51 -07002783
Abhijeet Dharmapurikar0e432812017-04-17 14:52:46 -07002784 if (chg->cc2_detach_wa_active)
2785 return 0;
Harry Yang755a34b2016-11-01 01:18:51 -07002786
Abhijeet Dharmapurikar0e432812017-04-17 14:52:46 -07002787 rc = smblib_read(chg, TYPE_C_STATUS_4_REG, &stat);
Harry Yang755a34b2016-11-01 01:18:51 -07002788 if (rc < 0) {
Abhijeet Dharmapurikar0e432812017-04-17 14:52:46 -07002789 smblib_err(chg, "Couldn't read TYPE_C_STATUS_4 rc=%d\n", rc);
Harry Yang755a34b2016-11-01 01:18:51 -07002790 return rc;
2791 }
Abhijeet Dharmapurikar0e432812017-04-17 14:52:46 -07002792 ccout = (stat & CC_ATTACHED_BIT) ?
2793 (!!(stat & CC_ORIENTATION_BIT) + 1) : 0;
2794 ufp_mode = (stat & TYPEC_DEBOUNCE_DONE_STATUS_BIT) ?
2795 !(stat & UFP_DFP_MODE_STATUS_BIT) : 0;
Harry Yang755a34b2016-11-01 01:18:51 -07002796
Abhijeet Dharmapurikar0e432812017-04-17 14:52:46 -07002797 if (ccout != 2)
2798 return 0;
Harry Yang755a34b2016-11-01 01:18:51 -07002799
Abhijeet Dharmapurikar0e432812017-04-17 14:52:46 -07002800 if (!ufp_mode)
2801 return 0;
Harry Yang755a34b2016-11-01 01:18:51 -07002802
Abhijeet Dharmapurikar0e432812017-04-17 14:52:46 -07002803 chg->cc2_detach_wa_active = true;
2804 /* The CC2 removal WA will cause a type-c-change IRQ storm */
2805 smblib_reg_block_update(chg, cc2_detach_settings);
2806 schedule_work(&chg->rdstd_cc2_detach_work);
Harry Yang755a34b2016-11-01 01:18:51 -07002807 return rc;
2808}
2809
2810static int smblib_cc2_sink_removal_exit(struct smb_charger *chg)
2811{
Harry Yang755a34b2016-11-01 01:18:51 -07002812 if ((chg->wa_flags & TYPEC_CC2_REMOVAL_WA_BIT) == 0)
Abhijeet Dharmapurikar0e432812017-04-17 14:52:46 -07002813 return 0;
Harry Yang755a34b2016-11-01 01:18:51 -07002814
Abhijeet Dharmapurikar0e432812017-04-17 14:52:46 -07002815 if (!chg->cc2_detach_wa_active)
2816 return 0;
Harry Yang755a34b2016-11-01 01:18:51 -07002817
Abhijeet Dharmapurikar0e432812017-04-17 14:52:46 -07002818 chg->cc2_detach_wa_active = false;
2819 cancel_work_sync(&chg->rdstd_cc2_detach_work);
2820 smblib_reg_block_restore(chg, cc2_detach_settings);
2821 return 0;
Harry Yang755a34b2016-11-01 01:18:51 -07002822}
2823
Abhijeet Dharmapurikarf8a7a4a2016-10-07 18:46:45 -07002824int smblib_set_prop_pd_in_hard_reset(struct smb_charger *chg,
2825 const union power_supply_propval *val)
2826{
Abhijeet Dharmapurikar0e432812017-04-17 14:52:46 -07002827 int rc = 0;
Abhijeet Dharmapurikarf8a7a4a2016-10-07 18:46:45 -07002828
Abhijeet Dharmapurikar0e432812017-04-17 14:52:46 -07002829 if (chg->pd_hard_reset == val->intval)
2830 return rc;
2831
2832 chg->pd_hard_reset = val->intval;
Abhijeet Dharmapurikarf8a7a4a2016-10-07 18:46:45 -07002833 rc = smblib_masked_write(chg, TYPE_C_INTRPT_ENB_SOFTWARE_CTRL_REG,
Abhijeet Dharmapurikar0e432812017-04-17 14:52:46 -07002834 EXIT_SNK_BASED_ON_CC_BIT,
2835 (chg->pd_hard_reset) ? EXIT_SNK_BASED_ON_CC_BIT : 0);
2836 if (rc < 0)
2837 smblib_err(chg, "Couldn't set EXIT_SNK_BASED_ON_CC rc=%d\n",
Harry Yang755a34b2016-11-01 01:18:51 -07002838 rc);
Abhijeet Dharmapurikarf8a7a4a2016-10-07 18:46:45 -07002839
Abhijeet Dharmapurikar0e432812017-04-17 14:52:46 -07002840 vote(chg->apsd_disable_votable, PD_HARD_RESET_VOTER,
2841 chg->pd_hard_reset, 0);
Harry Yang755a34b2016-11-01 01:18:51 -07002842
Abhijeet Dharmapurikarf8a7a4a2016-10-07 18:46:45 -07002843 return rc;
2844}
2845
Nicholas Troast7dbcad22016-10-05 13:30:18 -07002846/************************
Abhijeet Dharmapurikar7442e422017-02-08 13:35:14 -08002847 * USB MAIN PSY GETTERS *
2848 ************************/
2849int smblib_get_prop_fcc_delta(struct smb_charger *chg,
2850 union power_supply_propval *val)
2851{
2852 int rc, jeita_cc_delta_ua, step_cc_delta_ua, hw_cc_delta_ua = 0;
2853
2854 rc = smblib_get_step_cc_delta(chg, &step_cc_delta_ua);
2855 if (rc < 0) {
2856 smblib_err(chg, "Couldn't get step cc delta rc=%d\n", rc);
2857 step_cc_delta_ua = 0;
2858 } else {
2859 hw_cc_delta_ua = step_cc_delta_ua;
2860 }
2861
2862 rc = smblib_get_jeita_cc_delta(chg, &jeita_cc_delta_ua);
2863 if (rc < 0) {
2864 smblib_err(chg, "Couldn't get jeita cc delta rc=%d\n", rc);
2865 jeita_cc_delta_ua = 0;
2866 } else if (jeita_cc_delta_ua < 0) {
2867 /* HW will take the min between JEITA and step charge */
2868 hw_cc_delta_ua = min(hw_cc_delta_ua, jeita_cc_delta_ua);
2869 }
2870
2871 val->intval = hw_cc_delta_ua;
2872 return 0;
2873}
2874
2875/************************
2876 * USB MAIN PSY SETTERS *
2877 ************************/
2878
2879#define SDP_CURRENT_MA 500000
2880#define CDP_CURRENT_MA 1500000
2881#define DCP_CURRENT_MA 1500000
2882#define HVDCP_CURRENT_MA 3000000
2883#define TYPEC_DEFAULT_CURRENT_MA 900000
2884#define TYPEC_MEDIUM_CURRENT_MA 1500000
2885#define TYPEC_HIGH_CURRENT_MA 3000000
Abhijeet Dharmapurikarf59c8352017-03-23 14:04:05 -07002886int smblib_get_charge_current(struct smb_charger *chg,
Abhijeet Dharmapurikar7442e422017-02-08 13:35:14 -08002887 int *total_current_ua)
2888{
Ashay Jaiswal7b6eb962017-04-26 14:34:29 +05302889 const struct apsd_result *apsd_result = smblib_get_apsd_result(chg);
Abhijeet Dharmapurikar7442e422017-02-08 13:35:14 -08002890 union power_supply_propval val = {0, };
Abhijeet Dharmapurikarf59c8352017-03-23 14:04:05 -07002891 int rc = 0, typec_source_rd, current_ua;
Abhijeet Dharmapurikar7442e422017-02-08 13:35:14 -08002892 bool non_compliant;
2893 u8 stat5;
2894
Abhijeet Dharmapurikarf59c8352017-03-23 14:04:05 -07002895 if (chg->pd_active) {
2896 *total_current_ua =
2897 get_client_vote_locked(chg->usb_icl_votable, PD_VOTER);
2898 return rc;
2899 }
2900
Abhijeet Dharmapurikar7442e422017-02-08 13:35:14 -08002901 rc = smblib_read(chg, TYPE_C_STATUS_5_REG, &stat5);
2902 if (rc < 0) {
2903 smblib_err(chg, "Couldn't read TYPE_C_STATUS_5 rc=%d\n", rc);
2904 return rc;
2905 }
2906 non_compliant = stat5 & TYPEC_NONCOMP_LEGACY_CABLE_STATUS_BIT;
2907
2908 /* get settled ICL */
2909 rc = smblib_get_prop_input_current_settled(chg, &val);
2910 if (rc < 0) {
2911 smblib_err(chg, "Couldn't get settled ICL rc=%d\n", rc);
2912 return rc;
2913 }
2914
2915 typec_source_rd = smblib_get_prop_ufp_mode(chg);
2916
2917 /* QC 2.0/3.0 adapter */
2918 if (apsd_result->bit & (QC_3P0_BIT | QC_2P0_BIT)) {
2919 *total_current_ua = HVDCP_CURRENT_MA;
2920 return 0;
2921 }
2922
2923 if (non_compliant) {
2924 switch (apsd_result->bit) {
2925 case CDP_CHARGER_BIT:
2926 current_ua = CDP_CURRENT_MA;
2927 break;
2928 case DCP_CHARGER_BIT:
2929 case OCP_CHARGER_BIT:
2930 case FLOAT_CHARGER_BIT:
2931 current_ua = DCP_CURRENT_MA;
2932 break;
2933 default:
2934 current_ua = 0;
2935 break;
2936 }
2937
2938 *total_current_ua = max(current_ua, val.intval);
2939 return 0;
2940 }
2941
2942 switch (typec_source_rd) {
2943 case POWER_SUPPLY_TYPEC_SOURCE_DEFAULT:
2944 switch (apsd_result->bit) {
2945 case CDP_CHARGER_BIT:
2946 current_ua = CDP_CURRENT_MA;
2947 break;
2948 case DCP_CHARGER_BIT:
2949 case OCP_CHARGER_BIT:
2950 case FLOAT_CHARGER_BIT:
2951 current_ua = chg->default_icl_ua;
2952 break;
2953 default:
2954 current_ua = 0;
2955 break;
2956 }
2957 break;
2958 case POWER_SUPPLY_TYPEC_SOURCE_MEDIUM:
2959 current_ua = TYPEC_MEDIUM_CURRENT_MA;
2960 break;
2961 case POWER_SUPPLY_TYPEC_SOURCE_HIGH:
2962 current_ua = TYPEC_HIGH_CURRENT_MA;
2963 break;
2964 case POWER_SUPPLY_TYPEC_NON_COMPLIANT:
2965 case POWER_SUPPLY_TYPEC_NONE:
2966 default:
2967 current_ua = 0;
2968 break;
2969 }
2970
2971 *total_current_ua = max(current_ua, val.intval);
2972 return 0;
2973}
2974
Abhijeet Dharmapurikar7442e422017-02-08 13:35:14 -08002975/************************
Nicholas Troast7dbcad22016-10-05 13:30:18 -07002976 * PARALLEL PSY GETTERS *
2977 ************************/
2978
2979int smblib_get_prop_slave_current_now(struct smb_charger *chg,
Abhijeet Dharmapurikarf59c8352017-03-23 14:04:05 -07002980 union power_supply_propval *pval)
Nicholas Troast7dbcad22016-10-05 13:30:18 -07002981{
2982 if (IS_ERR_OR_NULL(chg->iio.batt_i_chan))
2983 chg->iio.batt_i_chan = iio_channel_get(chg->dev, "batt_i");
2984
2985 if (IS_ERR(chg->iio.batt_i_chan))
2986 return PTR_ERR(chg->iio.batt_i_chan);
2987
2988 return iio_read_channel_processed(chg->iio.batt_i_chan, &pval->intval);
2989}
2990
Nicholas Troast34db5032016-03-28 12:26:44 -07002991/**********************
2992 * INTERRUPT HANDLERS *
2993 **********************/
2994
2995irqreturn_t smblib_handle_debug(int irq, void *data)
2996{
2997 struct smb_irq_data *irq_data = data;
2998 struct smb_charger *chg = irq_data->parent_data;
2999
3000 smblib_dbg(chg, PR_INTERRUPT, "IRQ: %s\n", irq_data->name);
Nicholas Troast34db5032016-03-28 12:26:44 -07003001 return IRQ_HANDLED;
3002}
3003
Nicholas Troast8995a702016-12-05 10:22:22 -08003004irqreturn_t smblib_handle_otg_overcurrent(int irq, void *data)
3005{
3006 struct smb_irq_data *irq_data = data;
3007 struct smb_charger *chg = irq_data->parent_data;
3008 int rc;
3009 u8 stat;
3010
3011 rc = smblib_read(chg, OTG_BASE + INT_RT_STS_OFFSET, &stat);
3012 if (rc < 0) {
3013 dev_err(chg->dev, "Couldn't read OTG_INT_RT_STS rc=%d\n", rc);
3014 return IRQ_HANDLED;
3015 }
3016
Ashay Jaiswal7c241382017-03-06 15:26:38 +05303017 if (chg->wa_flags & OTG_WA) {
3018 if (stat & OTG_OC_DIS_SW_STS_RT_STS_BIT)
3019 smblib_err(chg, "OTG disabled by hw\n");
3020
3021 /* not handling software based hiccups for PM660 */
3022 return IRQ_HANDLED;
3023 }
3024
Nicholas Troastb11015f2017-01-17 17:56:45 -08003025 if (stat & OTG_OVERCURRENT_RT_STS_BIT)
3026 schedule_work(&chg->otg_oc_work);
Nicholas Troast8995a702016-12-05 10:22:22 -08003027
Nicholas Troast8995a702016-12-05 10:22:22 -08003028 return IRQ_HANDLED;
3029}
3030
Harry Yang6fe72ab2016-06-14 16:21:39 -07003031irqreturn_t smblib_handle_chg_state_change(int irq, void *data)
3032{
3033 struct smb_irq_data *irq_data = data;
3034 struct smb_charger *chg = irq_data->parent_data;
Nicholas Troast8cb77552016-09-23 11:50:18 -07003035 u8 stat;
Harry Yang1d1034c2016-06-15 12:09:42 -07003036 int rc;
Harry Yang6fe72ab2016-06-14 16:21:39 -07003037
3038 smblib_dbg(chg, PR_INTERRUPT, "IRQ: %s\n", irq_data->name);
3039
Nicholas Troast8cb77552016-09-23 11:50:18 -07003040 rc = smblib_read(chg, BATTERY_CHARGER_STATUS_1_REG, &stat);
Harry Yang1d1034c2016-06-15 12:09:42 -07003041 if (rc < 0) {
Abhijeet Dharmapurikar31b98f32016-10-14 12:25:23 -07003042 smblib_err(chg, "Couldn't read BATTERY_CHARGER_STATUS_1 rc=%d\n",
Abhijeet Dharmapurikarf59c8352017-03-23 14:04:05 -07003043 rc);
Harry Yang1d1034c2016-06-15 12:09:42 -07003044 return IRQ_HANDLED;
3045 }
3046
Nicholas Troast8cb77552016-09-23 11:50:18 -07003047 stat = stat & BATTERY_CHARGER_STATUS_MASK;
Nicholas Troast8cb77552016-09-23 11:50:18 -07003048 power_supply_changed(chg->batt_psy);
Harry Yang6fe72ab2016-06-14 16:21:39 -07003049 return IRQ_HANDLED;
3050}
3051
Harry Yangfe913842016-08-10 12:27:28 -07003052irqreturn_t smblib_handle_step_chg_state_change(int irq, void *data)
3053{
3054 struct smb_irq_data *irq_data = data;
3055 struct smb_charger *chg = irq_data->parent_data;
3056
3057 smblib_dbg(chg, PR_INTERRUPT, "IRQ: %s\n", irq_data->name);
3058
3059 if (chg->step_chg_enabled)
3060 rerun_election(chg->fcc_votable);
3061
3062 return IRQ_HANDLED;
3063}
3064
3065irqreturn_t smblib_handle_step_chg_soc_update_fail(int irq, void *data)
3066{
3067 struct smb_irq_data *irq_data = data;
3068 struct smb_charger *chg = irq_data->parent_data;
3069
3070 smblib_dbg(chg, PR_INTERRUPT, "IRQ: %s\n", irq_data->name);
3071
3072 if (chg->step_chg_enabled)
3073 rerun_election(chg->fcc_votable);
3074
3075 return IRQ_HANDLED;
3076}
3077
3078#define STEP_SOC_REQ_MS 3000
3079irqreturn_t smblib_handle_step_chg_soc_update_request(int irq, void *data)
3080{
3081 struct smb_irq_data *irq_data = data;
3082 struct smb_charger *chg = irq_data->parent_data;
3083 int rc;
3084 union power_supply_propval pval = {0, };
3085
3086 smblib_dbg(chg, PR_INTERRUPT, "IRQ: %s\n", irq_data->name);
3087
3088 if (!chg->bms_psy) {
3089 schedule_delayed_work(&chg->step_soc_req_work,
3090 msecs_to_jiffies(STEP_SOC_REQ_MS));
3091 return IRQ_HANDLED;
3092 }
3093
3094 rc = smblib_get_prop_batt_capacity(chg, &pval);
3095 if (rc < 0)
Abhijeet Dharmapurikar31b98f32016-10-14 12:25:23 -07003096 smblib_err(chg, "Couldn't get batt capacity rc=%d\n", rc);
Harry Yangfe913842016-08-10 12:27:28 -07003097 else
3098 step_charge_soc_update(chg, pval.intval);
3099
3100 return IRQ_HANDLED;
3101}
3102
Abhijeet Dharmapurikar2644cd62016-07-20 16:54:55 -07003103irqreturn_t smblib_handle_batt_temp_changed(int irq, void *data)
3104{
3105 struct smb_irq_data *irq_data = data;
3106 struct smb_charger *chg = irq_data->parent_data;
3107
3108 rerun_election(chg->fcc_votable);
3109 power_supply_changed(chg->batt_psy);
3110 return IRQ_HANDLED;
3111}
3112
Nicholas Troast34db5032016-03-28 12:26:44 -07003113irqreturn_t smblib_handle_batt_psy_changed(int irq, void *data)
3114{
3115 struct smb_irq_data *irq_data = data;
3116 struct smb_charger *chg = irq_data->parent_data;
3117
Nicholas Troast47ae4612016-08-03 09:49:36 -07003118 smblib_dbg(chg, PR_INTERRUPT, "IRQ: %s\n", irq_data->name);
Nicholas Troast34db5032016-03-28 12:26:44 -07003119 power_supply_changed(chg->batt_psy);
3120 return IRQ_HANDLED;
3121}
3122
3123irqreturn_t smblib_handle_usb_psy_changed(int irq, void *data)
3124{
3125 struct smb_irq_data *irq_data = data;
3126 struct smb_charger *chg = irq_data->parent_data;
3127
Nicholas Troast47ae4612016-08-03 09:49:36 -07003128 smblib_dbg(chg, PR_INTERRUPT, "IRQ: %s\n", irq_data->name);
Nicholas Troast34db5032016-03-28 12:26:44 -07003129 power_supply_changed(chg->usb_psy);
3130 return IRQ_HANDLED;
3131}
3132
Subbaraman Narayanamurthy09327482017-02-06 16:33:12 -08003133irqreturn_t smblib_handle_usbin_uv(int irq, void *data)
3134{
3135 struct smb_irq_data *irq_data = data;
3136 struct smb_charger *chg = irq_data->parent_data;
3137 struct storm_watch *wdata;
3138
3139 smblib_dbg(chg, PR_INTERRUPT, "IRQ: %s\n", irq_data->name);
3140 if (!chg->irq_info[SWITCH_POWER_OK_IRQ].irq_data)
3141 return IRQ_HANDLED;
3142
3143 wdata = &chg->irq_info[SWITCH_POWER_OK_IRQ].irq_data->storm_data;
3144 reset_storm_count(wdata);
3145 return IRQ_HANDLED;
3146}
3147
Abhijeet Dharmapurikar0e432812017-04-17 14:52:46 -07003148static void smblib_micro_usb_plugin(struct smb_charger *chg, bool vbus_rising)
3149{
Abhijeet Dharmapurikar11330d92017-04-17 12:15:19 -07003150 if (vbus_rising) {
3151 /* use the typec flag even though its not typec */
3152 chg->typec_present = 1;
3153 } else {
3154 chg->typec_present = 0;
Abhijeet Dharmapurikar0e432812017-04-17 14:52:46 -07003155 smblib_update_usb_type(chg);
3156 extcon_set_cable_state_(chg->extcon, EXTCON_USB, false);
3157 smblib_uusb_removal(chg);
3158 }
3159}
3160
Abhijeet Dharmapurikar95c95082017-04-24 14:06:54 -07003161void smblib_usb_plugin_hard_reset_locked(struct smb_charger *chg)
Abhijeet Dharmapurikar0e432812017-04-17 14:52:46 -07003162{
Abhijeet Dharmapurikar95c95082017-04-24 14:06:54 -07003163 int rc;
3164 u8 stat;
3165 bool vbus_rising;
3166
3167 rc = smblib_read(chg, USBIN_BASE + INT_RT_STS_OFFSET, &stat);
3168 if (rc < 0) {
3169 smblib_err(chg, "Couldn't read USB_INT_RT_STS rc=%d\n", rc);
3170 return;
3171 }
3172
3173 vbus_rising = (bool)(stat & USBIN_PLUGIN_RT_STS_BIT);
3174
Abhijeet Dharmapurikar0e432812017-04-17 14:52:46 -07003175 if (vbus_rising)
3176 smblib_cc2_sink_removal_exit(chg);
3177 else
3178 smblib_cc2_sink_removal_enter(chg);
Abhijeet Dharmapurikar95c95082017-04-24 14:06:54 -07003179
3180 power_supply_changed(chg->usb_psy);
3181 smblib_dbg(chg, PR_INTERRUPT, "IRQ: usbin-plugin %s\n",
3182 vbus_rising ? "attached" : "detached");
Abhijeet Dharmapurikar0e432812017-04-17 14:52:46 -07003183}
3184
Ashay Jaiswalc0361672017-03-21 12:24:16 +05303185#define PL_DELAY_MS 30000
Abhijeet Dharmapurikar11330d92017-04-17 12:15:19 -07003186void smblib_usb_plugin_locked(struct smb_charger *chg)
Nicholas Troast34db5032016-03-28 12:26:44 -07003187{
Nicholas Troast34db5032016-03-28 12:26:44 -07003188 int rc;
3189 u8 stat;
Nicholas Troast7ec38eb2016-11-14 10:28:39 -08003190 bool vbus_rising;
Nicholas Troast34db5032016-03-28 12:26:44 -07003191
Harry Yangcdad2bf2016-10-04 17:03:56 -07003192 rc = smblib_read(chg, USBIN_BASE + INT_RT_STS_OFFSET, &stat);
3193 if (rc < 0) {
Abhijeet Dharmapurikar11330d92017-04-17 12:15:19 -07003194 smblib_err(chg, "Couldn't read USB_INT_RT_STS rc=%d\n", rc);
3195 return;
Harry Yangcdad2bf2016-10-04 17:03:56 -07003196 }
3197
Nicholas Troast7ec38eb2016-11-14 10:28:39 -08003198 vbus_rising = (bool)(stat & USBIN_PLUGIN_RT_STS_BIT);
Abhijeet Dharmapurikar0e432812017-04-17 14:52:46 -07003199 smblib_set_opt_freq_buck(chg, vbus_rising ? chg->chg_freq.freq_5V :
3200 chg->chg_freq.freq_removal);
Harry Yangcdad2bf2016-10-04 17:03:56 -07003201
Nicholas Troast34db5032016-03-28 12:26:44 -07003202 /* fetch the DPDM regulator */
3203 if (!chg->dpdm_reg && of_get_property(chg->dev->of_node,
Ashay Jaiswal4aa2c0c2016-12-07 19:39:38 +05303204 "dpdm-supply", NULL)) {
Nicholas Troast34db5032016-03-28 12:26:44 -07003205 chg->dpdm_reg = devm_regulator_get(chg->dev, "dpdm");
3206 if (IS_ERR(chg->dpdm_reg)) {
Abhijeet Dharmapurikar31b98f32016-10-14 12:25:23 -07003207 smblib_err(chg, "Couldn't get dpdm regulator rc=%ld\n",
Nicholas Troast34db5032016-03-28 12:26:44 -07003208 PTR_ERR(chg->dpdm_reg));
3209 chg->dpdm_reg = NULL;
3210 }
3211 }
3212
Nicholas Troast7ec38eb2016-11-14 10:28:39 -08003213 if (vbus_rising) {
Nicholas Troastabedaf72016-09-16 11:07:45 -07003214 if (chg->dpdm_reg && !regulator_is_enabled(chg->dpdm_reg)) {
Abhijeet Dharmapurikar17288f22016-07-05 14:03:31 -07003215 smblib_dbg(chg, PR_MISC, "enabling DPDM regulator\n");
3216 rc = regulator_enable(chg->dpdm_reg);
3217 if (rc < 0)
Abhijeet Dharmapurikar31b98f32016-10-14 12:25:23 -07003218 smblib_err(chg, "Couldn't enable dpdm regulator rc=%d\n",
Abhijeet Dharmapurikar17288f22016-07-05 14:03:31 -07003219 rc);
3220 }
Ashay Jaiswalc0361672017-03-21 12:24:16 +05303221
3222 /* Schedule work to enable parallel charger */
3223 vote(chg->awake_votable, PL_DELAY_VOTER, true, 0);
3224 schedule_delayed_work(&chg->pl_enable_work,
3225 msecs_to_jiffies(PL_DELAY_MS));
Abhijeet Dharmapurikar17288f22016-07-05 14:03:31 -07003226 } else {
Abhijeet Dharmapurikar2823fe32016-12-05 17:52:11 -08003227 if (chg->wa_flags & BOOST_BACK_WA)
Abhijeet Dharmapurikar5e0bfbe2017-02-12 19:16:15 -08003228 vote(chg->usb_icl_votable, BOOST_BACK_VOTER, false, 0);
Nicholas Troastabedaf72016-09-16 11:07:45 -07003229
3230 if (chg->dpdm_reg && regulator_is_enabled(chg->dpdm_reg)) {
Abhijeet Dharmapurikar17288f22016-07-05 14:03:31 -07003231 smblib_dbg(chg, PR_MISC, "disabling DPDM regulator\n");
3232 rc = regulator_disable(chg->dpdm_reg);
3233 if (rc < 0)
Abhijeet Dharmapurikar31b98f32016-10-14 12:25:23 -07003234 smblib_err(chg, "Couldn't disable dpdm regulator rc=%d\n",
Abhijeet Dharmapurikar17288f22016-07-05 14:03:31 -07003235 rc);
3236 }
Nicholas Troast34db5032016-03-28 12:26:44 -07003237 }
3238
Abhijeet Dharmapurikar0e432812017-04-17 14:52:46 -07003239 if (chg->micro_usb_mode)
3240 smblib_micro_usb_plugin(chg, vbus_rising);
Abhijeet Dharmapurikar0e432812017-04-17 14:52:46 -07003241
Nicholas Troast62d86622016-09-22 11:41:33 -07003242 power_supply_changed(chg->usb_psy);
Abhijeet Dharmapurikar11330d92017-04-17 12:15:19 -07003243 smblib_dbg(chg, PR_INTERRUPT, "IRQ: usbin-plugin %s\n",
3244 vbus_rising ? "attached" : "detached");
3245}
3246
3247irqreturn_t smblib_handle_usb_plugin(int irq, void *data)
3248{
3249 struct smb_irq_data *irq_data = data;
3250 struct smb_charger *chg = irq_data->parent_data;
3251
3252 mutex_lock(&chg->lock);
Abhijeet Dharmapurikar95c95082017-04-24 14:06:54 -07003253 if (chg->pd_hard_reset)
3254 smblib_usb_plugin_hard_reset_locked(chg);
3255 else
3256 smblib_usb_plugin_locked(chg);
Abhijeet Dharmapurikar11330d92017-04-17 12:15:19 -07003257 mutex_unlock(&chg->lock);
Nicholas Troast34db5032016-03-28 12:26:44 -07003258 return IRQ_HANDLED;
3259}
3260
Abhijeet Dharmapurikarc0b0f592016-10-14 10:55:42 -07003261#define USB_WEAK_INPUT_UA 1400000
Ashay Jaiswal4d825782017-02-18 10:11:34 +05303262#define ICL_CHANGE_DELAY_MS 1000
Harry Yang6fe72ab2016-06-14 16:21:39 -07003263irqreturn_t smblib_handle_icl_change(int irq, void *data)
3264{
Ashay Jaiswal4d825782017-02-18 10:11:34 +05303265 u8 stat;
3266 int rc, settled_ua, delay = ICL_CHANGE_DELAY_MS;
Harry Yang6fe72ab2016-06-14 16:21:39 -07003267 struct smb_irq_data *irq_data = data;
3268 struct smb_charger *chg = irq_data->parent_data;
3269
Nicholas Troastbb9e1a32017-02-09 10:57:28 -08003270 if (chg->mode == PARALLEL_MASTER) {
Ashay Jaiswal4d825782017-02-18 10:11:34 +05303271 rc = smblib_read(chg, AICL_STATUS_REG, &stat);
3272 if (rc < 0) {
3273 smblib_err(chg, "Couldn't read AICL_STATUS rc=%d\n",
3274 rc);
3275 return IRQ_HANDLED;
3276 }
3277
3278 rc = smblib_get_charge_param(chg, &chg->param.icl_stat,
3279 &settled_ua);
3280 if (rc < 0) {
3281 smblib_err(chg, "Couldn't get ICL status rc=%d\n", rc);
3282 return IRQ_HANDLED;
3283 }
3284
3285 /* If AICL settled then schedule work now */
3286 if ((settled_ua == get_effective_result(chg->usb_icl_votable))
3287 || (stat & AICL_DONE_BIT))
3288 delay = 0;
3289
Ashay Jaiswalac854862017-03-06 23:58:55 +05303290 cancel_delayed_work_sync(&chg->icl_change_work);
Ashay Jaiswal4d825782017-02-18 10:11:34 +05303291 schedule_delayed_work(&chg->icl_change_work,
3292 msecs_to_jiffies(delay));
Nicholas Troastbb9e1a32017-02-09 10:57:28 -08003293 }
Harry Yang1d1034c2016-06-15 12:09:42 -07003294
Harry Yang6fe72ab2016-06-14 16:21:39 -07003295 return IRQ_HANDLED;
3296}
3297
Nicholas Troast34db5032016-03-28 12:26:44 -07003298static void smblib_handle_slow_plugin_timeout(struct smb_charger *chg,
3299 bool rising)
3300{
3301 smblib_dbg(chg, PR_INTERRUPT, "IRQ: slow-plugin-timeout %s\n",
3302 rising ? "rising" : "falling");
3303}
3304
3305static void smblib_handle_sdp_enumeration_done(struct smb_charger *chg,
3306 bool rising)
3307{
3308 smblib_dbg(chg, PR_INTERRUPT, "IRQ: sdp-enumeration-done %s\n",
3309 rising ? "rising" : "falling");
3310}
3311
Harry Yangcdad2bf2016-10-04 17:03:56 -07003312#define QC3_PULSES_FOR_6V 5
3313#define QC3_PULSES_FOR_9V 20
3314#define QC3_PULSES_FOR_12V 35
3315static void smblib_hvdcp_adaptive_voltage_change(struct smb_charger *chg)
3316{
3317 int rc;
3318 u8 stat;
3319 int pulses;
3320
Fenglin Wuef4730e2017-01-11 18:16:25 +08003321 power_supply_changed(chg->usb_main_psy);
Harry Yangcdad2bf2016-10-04 17:03:56 -07003322 if (chg->usb_psy_desc.type == POWER_SUPPLY_TYPE_USB_HVDCP) {
3323 rc = smblib_read(chg, QC_CHANGE_STATUS_REG, &stat);
3324 if (rc < 0) {
3325 smblib_err(chg,
3326 "Couldn't read QC_CHANGE_STATUS rc=%d\n", rc);
3327 return;
3328 }
3329
3330 switch (stat & QC_2P0_STATUS_MASK) {
3331 case QC_5V_BIT:
Anirudh Ghayal4da3df92017-01-25 18:55:57 +05303332 smblib_set_opt_freq_buck(chg,
3333 chg->chg_freq.freq_5V);
Harry Yangcdad2bf2016-10-04 17:03:56 -07003334 break;
3335 case QC_9V_BIT:
Anirudh Ghayal4da3df92017-01-25 18:55:57 +05303336 smblib_set_opt_freq_buck(chg,
3337 chg->chg_freq.freq_9V);
Harry Yangcdad2bf2016-10-04 17:03:56 -07003338 break;
3339 case QC_12V_BIT:
Anirudh Ghayal4da3df92017-01-25 18:55:57 +05303340 smblib_set_opt_freq_buck(chg,
3341 chg->chg_freq.freq_12V);
Harry Yangcdad2bf2016-10-04 17:03:56 -07003342 break;
3343 default:
Anirudh Ghayal4da3df92017-01-25 18:55:57 +05303344 smblib_set_opt_freq_buck(chg,
3345 chg->chg_freq.freq_removal);
Harry Yangcdad2bf2016-10-04 17:03:56 -07003346 break;
3347 }
3348 }
3349
3350 if (chg->usb_psy_desc.type == POWER_SUPPLY_TYPE_USB_HVDCP_3) {
3351 rc = smblib_read(chg, QC_PULSE_COUNT_STATUS_REG, &stat);
3352 if (rc < 0) {
3353 smblib_err(chg,
3354 "Couldn't read QC_PULSE_COUNT rc=%d\n", rc);
3355 return;
3356 }
3357 pulses = (stat & QC_PULSE_COUNT_MASK);
3358
3359 if (pulses < QC3_PULSES_FOR_6V)
Anirudh Ghayal4da3df92017-01-25 18:55:57 +05303360 smblib_set_opt_freq_buck(chg,
3361 chg->chg_freq.freq_5V);
Harry Yangcdad2bf2016-10-04 17:03:56 -07003362 else if (pulses < QC3_PULSES_FOR_9V)
Anirudh Ghayal4da3df92017-01-25 18:55:57 +05303363 smblib_set_opt_freq_buck(chg,
3364 chg->chg_freq.freq_6V_8V);
Harry Yangcdad2bf2016-10-04 17:03:56 -07003365 else if (pulses < QC3_PULSES_FOR_12V)
Anirudh Ghayal4da3df92017-01-25 18:55:57 +05303366 smblib_set_opt_freq_buck(chg,
3367 chg->chg_freq.freq_9V);
Harry Yangcdad2bf2016-10-04 17:03:56 -07003368 else
Anirudh Ghayal4da3df92017-01-25 18:55:57 +05303369 smblib_set_opt_freq_buck(chg,
3370 chg->chg_freq.freq_12V);
Harry Yangcdad2bf2016-10-04 17:03:56 -07003371 }
3372}
3373
Nicholas Troast34db5032016-03-28 12:26:44 -07003374/* triggers when HVDCP 3.0 authentication has finished */
3375static void smblib_handle_hvdcp_3p0_auth_done(struct smb_charger *chg,
3376 bool rising)
3377{
3378 const struct apsd_result *apsd_result;
Harry Yangcdad2bf2016-10-04 17:03:56 -07003379 int rc;
Nicholas Troast34db5032016-03-28 12:26:44 -07003380
3381 if (!rising)
3382 return;
3383
Ashay Jaiswal67ec7072017-02-16 14:14:58 +05303384 if (chg->wa_flags & QC_AUTH_INTERRUPT_WA_BIT) {
3385 /*
3386 * Disable AUTH_IRQ_EN_CFG_BIT to receive adapter voltage
3387 * change interrupt.
3388 */
3389 rc = smblib_masked_write(chg,
3390 USBIN_SOURCE_CHANGE_INTRPT_ENB_REG,
3391 AUTH_IRQ_EN_CFG_BIT, 0);
3392 if (rc < 0)
3393 smblib_err(chg,
3394 "Couldn't enable QC auth setting rc=%d\n", rc);
3395 }
Harry Yangcdad2bf2016-10-04 17:03:56 -07003396
Harry Yangaba1f5f2016-09-28 10:47:29 -07003397 if (chg->mode == PARALLEL_MASTER)
3398 vote(chg->pl_enable_votable_indirect, USBIN_V_VOTER, true, 0);
3399
Ashay Jaiswalac854862017-03-06 23:58:55 +05303400 /* the APSD done handler will set the USB supply type */
3401 apsd_result = smblib_get_apsd_result(chg);
3402 if (get_effective_result(chg->hvdcp_hw_inov_dis_votable)) {
3403 if (apsd_result->pst == POWER_SUPPLY_TYPE_USB_HVDCP) {
3404 /* force HVDCP2 to 9V if INOV is disabled */
3405 rc = smblib_masked_write(chg, CMD_HVDCP_2_REG,
3406 FORCE_9V_BIT, FORCE_9V_BIT);
3407 if (rc < 0)
3408 smblib_err(chg,
3409 "Couldn't force 9V HVDCP rc=%d\n", rc);
3410 }
3411 }
3412
Nicholas Troast34db5032016-03-28 12:26:44 -07003413 smblib_dbg(chg, PR_INTERRUPT, "IRQ: hvdcp-3p0-auth-done rising; %s detected\n",
3414 apsd_result->name);
3415}
3416
Harry Yang1369b7a2016-09-27 15:59:50 -07003417static void smblib_handle_hvdcp_check_timeout(struct smb_charger *chg,
3418 bool rising, bool qc_charger)
3419{
Ashay Jaiswal7b6eb962017-04-26 14:34:29 +05303420 const struct apsd_result *apsd_result = smblib_get_apsd_result(chg);
Abhijeet Dharmapurikar95670872017-02-09 22:55:51 +05303421
Abhijeet Dharmapurikar4b13c6e2016-10-05 15:15:10 -07003422 /* Hold off PD only until hvdcp 2.0 detection timeout */
Abhijeet Dharmapurikar716cd962016-10-14 12:50:37 -07003423 if (rising) {
Abhijeet Dharmapurikar4b13c6e2016-10-05 15:15:10 -07003424 vote(chg->pd_disallowed_votable_indirect, HVDCP_TIMEOUT_VOTER,
Abhijeet Dharmapurikar716cd962016-10-14 12:50:37 -07003425 false, 0);
Abhijeet Dharmapurikar74021fc2017-02-06 18:39:19 -08003426
Harry Yang4bf7d962017-03-13 16:51:43 -07003427 /* enable HDC and ICL irq for QC2/3 charger */
3428 if (qc_charger)
3429 vote(chg->usb_irq_enable_votable, QC_VOTER, true, 0);
3430
Abhijeet Dharmapurikar74021fc2017-02-06 18:39:19 -08003431 /*
3432 * HVDCP detection timeout done
3433 * If adapter is not QC2.0/QC3.0 - it is a plain old DCP.
3434 */
3435 if (!qc_charger && (apsd_result->bit & DCP_CHARGER_BIT))
3436 /* enforce DCP ICL if specified */
3437 vote(chg->usb_icl_votable, DCP_VOTER,
3438 chg->dcp_icl_ua != -EINVAL, chg->dcp_icl_ua);
Abhijeet Dharmapurikar716cd962016-10-14 12:50:37 -07003439 }
Harry Yang1369b7a2016-09-27 15:59:50 -07003440
3441 smblib_dbg(chg, PR_INTERRUPT, "IRQ: smblib_handle_hvdcp_check_timeout %s\n",
3442 rising ? "rising" : "falling");
3443}
3444
Nicholas Troast34db5032016-03-28 12:26:44 -07003445/* triggers when HVDCP is detected */
3446static void smblib_handle_hvdcp_detect_done(struct smb_charger *chg,
3447 bool rising)
3448{
3449 if (!rising)
3450 return;
3451
3452 /* the APSD done handler will set the USB supply type */
3453 cancel_delayed_work_sync(&chg->hvdcp_detect_work);
3454 smblib_dbg(chg, PR_INTERRUPT, "IRQ: hvdcp-detect-done %s\n",
3455 rising ? "rising" : "falling");
3456}
3457
Nicholas Troastf9e44992017-03-14 09:06:56 -07003458static void smblib_force_legacy_icl(struct smb_charger *chg, int pst)
3459{
Abhijeet Dharmapurikar3c93db32017-04-17 17:36:14 -07003460 /* while PD is active it should have complete ICL control */
3461 if (chg->pd_active)
3462 return;
3463
Nicholas Troastf9e44992017-03-14 09:06:56 -07003464 switch (pst) {
3465 case POWER_SUPPLY_TYPE_USB:
3466 /*
3467 * USB_PSY will vote to increase the current to 500/900mA once
3468 * enumeration is done. Ensure that USB_PSY has at least voted
3469 * for 100mA before releasing the LEGACY_UNKNOWN vote
3470 */
3471 if (!is_client_vote_enabled(chg->usb_icl_votable,
3472 USB_PSY_VOTER))
3473 vote(chg->usb_icl_votable, USB_PSY_VOTER, true, 100000);
3474 vote(chg->usb_icl_votable, LEGACY_UNKNOWN_VOTER, false, 0);
3475 break;
3476 case POWER_SUPPLY_TYPE_USB_CDP:
3477 vote(chg->usb_icl_votable, LEGACY_UNKNOWN_VOTER, true, 1500000);
3478 break;
3479 case POWER_SUPPLY_TYPE_USB_DCP:
3480 vote(chg->usb_icl_votable, LEGACY_UNKNOWN_VOTER, true, 1500000);
3481 break;
3482 case POWER_SUPPLY_TYPE_USB_HVDCP:
3483 case POWER_SUPPLY_TYPE_USB_HVDCP_3:
3484 vote(chg->usb_icl_votable, LEGACY_UNKNOWN_VOTER, true, 3000000);
3485 break;
3486 default:
3487 smblib_err(chg, "Unknown APSD %d; forcing 500mA\n", pst);
3488 vote(chg->usb_icl_votable, LEGACY_UNKNOWN_VOTER, true, 500000);
3489 break;
3490 }
3491}
3492
Nicholas Troast34db5032016-03-28 12:26:44 -07003493#define HVDCP_DET_MS 2500
3494static void smblib_handle_apsd_done(struct smb_charger *chg, bool rising)
3495{
Nicholas Troast34db5032016-03-28 12:26:44 -07003496 const struct apsd_result *apsd_result;
3497
3498 if (!rising)
3499 return;
3500
Abhijeet Dharmapurikarb9598872016-10-17 16:58:58 -07003501 apsd_result = smblib_update_usb_type(chg);
Nicholas Troastf9e44992017-03-14 09:06:56 -07003502
Abhijeet Dharmapurikar3c93db32017-04-17 17:36:14 -07003503 if (!chg->typec_legacy_valid)
Nicholas Troastf9e44992017-03-14 09:06:56 -07003504 smblib_force_legacy_icl(chg, apsd_result->pst);
3505
Nicholas Troast34db5032016-03-28 12:26:44 -07003506 switch (apsd_result->bit) {
3507 case SDP_CHARGER_BIT:
3508 case CDP_CHARGER_BIT:
Ashay Jaiswal4aa2c0c2016-12-07 19:39:38 +05303509 if (chg->micro_usb_mode)
3510 extcon_set_cable_state_(chg->extcon, EXTCON_USB,
3511 true);
Abhijeet Dharmapurikarbb9505f2017-03-22 18:31:28 -07003512 /* if not DCP then no hvdcp timeout happens. Enable pd here */
3513 vote(chg->pd_disallowed_votable_indirect, HVDCP_TIMEOUT_VOTER,
3514 false, 0);
3515 break;
Nicholas Troast34db5032016-03-28 12:26:44 -07003516 case OCP_CHARGER_BIT:
3517 case FLOAT_CHARGER_BIT:
Ashay Jaiswalc0361672017-03-21 12:24:16 +05303518 /* if not DCP then no hvdcp timeout happens, Enable pd here. */
Abhijeet Dharmapurikar4b13c6e2016-10-05 15:15:10 -07003519 vote(chg->pd_disallowed_votable_indirect, HVDCP_TIMEOUT_VOTER,
3520 false, 0);
Nicholas Troast34db5032016-03-28 12:26:44 -07003521 break;
3522 case DCP_CHARGER_BIT:
Harry Yang1369b7a2016-09-27 15:59:50 -07003523 if (chg->wa_flags & QC_CHARGER_DETECTION_WA_BIT)
3524 schedule_delayed_work(&chg->hvdcp_detect_work,
3525 msecs_to_jiffies(HVDCP_DET_MS));
Nicholas Troast34db5032016-03-28 12:26:44 -07003526 break;
3527 default:
3528 break;
3529 }
3530
Nicholas Troast34db5032016-03-28 12:26:44 -07003531 smblib_dbg(chg, PR_INTERRUPT, "IRQ: apsd-done rising; %s detected\n",
3532 apsd_result->name);
3533}
3534
3535irqreturn_t smblib_handle_usb_source_change(int irq, void *data)
3536{
3537 struct smb_irq_data *irq_data = data;
3538 struct smb_charger *chg = irq_data->parent_data;
3539 int rc = 0;
3540 u8 stat;
3541
3542 rc = smblib_read(chg, APSD_STATUS_REG, &stat);
3543 if (rc < 0) {
Abhijeet Dharmapurikar31b98f32016-10-14 12:25:23 -07003544 smblib_err(chg, "Couldn't read APSD_STATUS rc=%d\n", rc);
Nicholas Troast34db5032016-03-28 12:26:44 -07003545 return IRQ_HANDLED;
3546 }
3547 smblib_dbg(chg, PR_REGISTER, "APSD_STATUS = 0x%02x\n", stat);
3548
Ashay Jaiswal8507aa52017-04-14 09:42:32 +05303549 if (chg->micro_usb_mode && (stat & APSD_DTC_STATUS_DONE_BIT)
3550 && !chg->uusb_apsd_rerun_done) {
3551 /*
3552 * Force re-run APSD to handle slow insertion related
3553 * charger-mis-detection.
3554 */
3555 chg->uusb_apsd_rerun_done = true;
3556 smblib_rerun_apsd(chg);
3557 return IRQ_HANDLED;
3558 }
3559
Nicholas Troast34db5032016-03-28 12:26:44 -07003560 smblib_handle_apsd_done(chg,
3561 (bool)(stat & APSD_DTC_STATUS_DONE_BIT));
3562
3563 smblib_handle_hvdcp_detect_done(chg,
3564 (bool)(stat & QC_CHARGER_BIT));
3565
Harry Yang1369b7a2016-09-27 15:59:50 -07003566 smblib_handle_hvdcp_check_timeout(chg,
3567 (bool)(stat & HVDCP_CHECK_TIMEOUT_BIT),
3568 (bool)(stat & QC_CHARGER_BIT));
3569
Nicholas Troast34db5032016-03-28 12:26:44 -07003570 smblib_handle_hvdcp_3p0_auth_done(chg,
3571 (bool)(stat & QC_AUTH_DONE_STATUS_BIT));
3572
Nicholas Troast34db5032016-03-28 12:26:44 -07003573 smblib_handle_sdp_enumeration_done(chg,
3574 (bool)(stat & ENUMERATION_DONE_BIT));
3575
3576 smblib_handle_slow_plugin_timeout(chg,
3577 (bool)(stat & SLOW_PLUGIN_TIMEOUT_BIT));
3578
Harry Yangcdad2bf2016-10-04 17:03:56 -07003579 smblib_hvdcp_adaptive_voltage_change(chg);
3580
Nicholas Troast34db5032016-03-28 12:26:44 -07003581 power_supply_changed(chg->usb_psy);
3582
Abhijeet Dharmapurikar5e0bfbe2017-02-12 19:16:15 -08003583 rc = smblib_read(chg, APSD_STATUS_REG, &stat);
3584 if (rc < 0) {
3585 smblib_err(chg, "Couldn't read APSD_STATUS rc=%d\n", rc);
3586 return IRQ_HANDLED;
3587 }
3588 smblib_dbg(chg, PR_REGISTER, "APSD_STATUS = 0x%02x\n", stat);
3589
Nicholas Troast34db5032016-03-28 12:26:44 -07003590 return IRQ_HANDLED;
3591}
3592
Abhijeet Dharmapurikar99ca0452016-10-13 09:50:41 -07003593static void typec_sink_insertion(struct smb_charger *chg)
3594{
3595 /* when a sink is inserted we should not wait on hvdcp timeout to
3596 * enable pd
3597 */
3598 vote(chg->pd_disallowed_votable_indirect, HVDCP_TIMEOUT_VOTER,
3599 false, 0);
3600}
Nicholas Troast34db5032016-03-28 12:26:44 -07003601
Harry Yangd89ff1f2016-12-05 14:59:11 -08003602static void typec_sink_removal(struct smb_charger *chg)
3603{
Anirudh Ghayal4da3df92017-01-25 18:55:57 +05303604 smblib_set_charge_param(chg, &chg->param.freq_boost,
3605 chg->chg_freq.freq_above_otg_threshold);
Harry Yangd89ff1f2016-12-05 14:59:11 -08003606 chg->boost_current_ua = 0;
3607}
3608
Abhijeet Dharmapurikar99ca0452016-10-13 09:50:41 -07003609static void smblib_handle_typec_removal(struct smb_charger *chg)
3610{
Nicholas Troastfe74c592017-03-14 09:20:55 -07003611 int rc;
3612
Abhijeet Dharmapurikar0e432812017-04-17 14:52:46 -07003613 chg->cc2_detach_wa_active = false;
3614
Nicholas Troast8c28e0f2017-03-22 14:44:49 -07003615 /* reset APSD voters */
3616 vote(chg->apsd_disable_votable, PD_HARD_RESET_VOTER, false, 0);
3617 vote(chg->apsd_disable_votable, PD_VOTER, false, 0);
Ashay Jaiswalc0361672017-03-21 12:24:16 +05303618
Nicholas Troast8c28e0f2017-03-22 14:44:49 -07003619 cancel_delayed_work_sync(&chg->pl_enable_work);
3620 cancel_delayed_work_sync(&chg->hvdcp_detect_work);
3621
3622 /* reset input current limit voters */
3623 vote(chg->usb_icl_votable, LEGACY_UNKNOWN_VOTER, true, 100000);
3624 vote(chg->usb_icl_votable, PD_VOTER, false, 0);
3625 vote(chg->usb_icl_votable, USB_PSY_VOTER, false, 0);
3626 vote(chg->usb_icl_votable, DCP_VOTER, false, 0);
3627 vote(chg->usb_icl_votable, PL_USBIN_USBIN_VOTER, false, 0);
3628
3629 /* reset hvdcp voters */
3630 vote(chg->hvdcp_disable_votable_indirect, VBUS_CC_SHORT_VOTER, true, 0);
3631 vote(chg->hvdcp_disable_votable_indirect, PD_INACTIVE_VOTER, true, 0);
3632
3633 /* reset power delivery voters */
3634 vote(chg->pd_allowed_votable, PD_VOTER, false, 0);
Abhijeet Dharmapurikar99ca0452016-10-13 09:50:41 -07003635 vote(chg->pd_disallowed_votable_indirect, CC_DETACHED_VOTER, true, 0);
3636 vote(chg->pd_disallowed_votable_indirect, HVDCP_TIMEOUT_VOTER, true, 0);
Nicholas Troast8c28e0f2017-03-22 14:44:49 -07003637
3638 /* reset usb irq voters */
Harry Yang4bf7d962017-03-13 16:51:43 -07003639 vote(chg->usb_irq_enable_votable, PD_VOTER, false, 0);
3640 vote(chg->usb_irq_enable_votable, QC_VOTER, false, 0);
Abhijeet Dharmapurikar99ca0452016-10-13 09:50:41 -07003641
Nicholas Troast8c28e0f2017-03-22 14:44:49 -07003642 /* reset parallel voters */
3643 vote(chg->pl_disable_votable, PL_DELAY_VOTER, true, 0);
3644 vote(chg->pl_enable_votable_indirect, USBIN_I_VOTER, false, 0);
3645 vote(chg->pl_enable_votable_indirect, USBIN_V_VOTER, false, 0);
3646 vote(chg->awake_votable, PL_DELAY_VOTER, false, 0);
Harry Yang1d1034c2016-06-15 12:09:42 -07003647
Nicholas Troast8995a702016-12-05 10:22:22 -08003648 chg->vconn_attempts = 0;
3649 chg->otg_attempts = 0;
Ashay Jaiswal6d308da2017-02-18 09:59:23 +05303650 chg->pulse_cnt = 0;
3651 chg->usb_icl_delta_ua = 0;
Nicholas Troast8c28e0f2017-03-22 14:44:49 -07003652 chg->voltage_min_uv = MICRO_5V;
3653 chg->voltage_max_uv = MICRO_5V;
3654 chg->pd_active = 0;
3655 chg->pd_hard_reset = 0;
Abhijeet Dharmapurikar3c93db32017-04-17 17:36:14 -07003656 chg->typec_legacy_valid = false;
Harry Yang3b113a52016-12-08 12:37:40 -08003657
Nicholas Troastfe74c592017-03-14 09:20:55 -07003658 /* enable APSD CC trigger for next insertion */
3659 rc = smblib_masked_write(chg, TYPE_C_CFG_REG,
3660 APSD_START_ON_CC_BIT, APSD_START_ON_CC_BIT);
3661 if (rc < 0)
3662 smblib_err(chg, "Couldn't enable APSD_START_ON_CC rc=%d\n", rc);
Abhijeet Dharmapurikar5e0bfbe2017-02-12 19:16:15 -08003663
Nicholas Troast8c28e0f2017-03-22 14:44:49 -07003664 if (chg->wa_flags & QC_AUTH_INTERRUPT_WA_BIT) {
3665 /* re-enable AUTH_IRQ_EN_CFG_BIT */
3666 rc = smblib_masked_write(chg,
3667 USBIN_SOURCE_CHANGE_INTRPT_ENB_REG,
3668 AUTH_IRQ_EN_CFG_BIT, AUTH_IRQ_EN_CFG_BIT);
3669 if (rc < 0)
3670 smblib_err(chg,
3671 "Couldn't enable QC auth setting rc=%d\n", rc);
3672 }
3673
3674 /* reconfigure allowed voltage for HVDCP */
3675 rc = smblib_set_adapter_allowance(chg,
3676 USBIN_ADAPTER_ALLOW_5V_OR_9V_TO_12V);
3677 if (rc < 0)
3678 smblib_err(chg, "Couldn't set USBIN_ADAPTER_ALLOW_5V_OR_9V_TO_12V rc=%d\n",
3679 rc);
3680
3681 /* enable DRP */
3682 rc = smblib_masked_write(chg, TYPE_C_INTRPT_ENB_SOFTWARE_CTRL_REG,
3683 TYPEC_POWER_ROLE_CMD_MASK, 0);
3684 if (rc < 0)
3685 smblib_err(chg, "Couldn't enable DRP rc=%d\n", rc);
3686
3687 /* HW controlled CC_OUT */
3688 rc = smblib_masked_write(chg, TAPER_TIMER_SEL_CFG_REG,
3689 TYPEC_SPARE_CFG_BIT, 0);
3690 if (rc < 0)
3691 smblib_err(chg, "Couldn't enable HW cc_out rc=%d\n", rc);
3692
3693 /* restore crude sensor */
3694 rc = smblib_write(chg, TM_IO_DTEST4_SEL, 0xA5);
3695 if (rc < 0)
3696 smblib_err(chg, "Couldn't restore crude sensor rc=%d\n", rc);
3697
Abhijeet Dharmapurikar5e0bfbe2017-02-12 19:16:15 -08003698 typec_sink_removal(chg);
Nicholas Troast8c28e0f2017-03-22 14:44:49 -07003699 smblib_update_usb_type(chg);
Nicholas Troast34db5032016-03-28 12:26:44 -07003700}
3701
Abhijeet Dharmapurikar99ca0452016-10-13 09:50:41 -07003702static void smblib_handle_typec_insertion(struct smb_charger *chg,
Abhijeet Dharmapurikar3c93db32017-04-17 17:36:14 -07003703 bool sink_attached)
Abhijeet Dharmapurikara8075d72016-10-06 12:59:04 -07003704{
Abhijeet Dharmapurikar3c93db32017-04-17 17:36:14 -07003705 int rc;
Abhijeet Dharmapurikara8075d72016-10-06 12:59:04 -07003706
Abhijeet Dharmapurikar99ca0452016-10-13 09:50:41 -07003707 vote(chg->pd_disallowed_votable_indirect, CC_DETACHED_VOTER, false, 0);
Abhijeet Dharmapurikara8075d72016-10-06 12:59:04 -07003708
Nicholas Troastfe74c592017-03-14 09:20:55 -07003709 /* disable APSD CC trigger since CC is attached */
3710 rc = smblib_masked_write(chg, TYPE_C_CFG_REG, APSD_START_ON_CC_BIT, 0);
3711 if (rc < 0)
3712 smblib_err(chg, "Couldn't disable APSD_START_ON_CC rc=%d\n",
3713 rc);
3714
Abhijeet Dharmapurikar3c93db32017-04-17 17:36:14 -07003715 if (sink_attached)
Abhijeet Dharmapurikar99ca0452016-10-13 09:50:41 -07003716 typec_sink_insertion(chg);
Abhijeet Dharmapurikar3c93db32017-04-17 17:36:14 -07003717 else
Harry Yangd89ff1f2016-12-05 14:59:11 -08003718 typec_sink_removal(chg);
Abhijeet Dharmapurikara8075d72016-10-06 12:59:04 -07003719}
3720
Abhijeet Dharmapurikar99ca0452016-10-13 09:50:41 -07003721static void smblib_handle_typec_debounce_done(struct smb_charger *chg,
Abhijeet Dharmapurikar3c93db32017-04-17 17:36:14 -07003722 bool rising, bool sink_attached)
Abhijeet Dharmapurikar99ca0452016-10-13 09:50:41 -07003723{
3724 int rc;
3725 union power_supply_propval pval = {0, };
3726
Nicholas Troast8c28e0f2017-03-22 14:44:49 -07003727 if (rising) {
3728 if (!chg->typec_present) {
3729 chg->typec_present = true;
3730 smblib_dbg(chg, PR_MISC, "TypeC insertion\n");
Abhijeet Dharmapurikar3c93db32017-04-17 17:36:14 -07003731 smblib_handle_typec_insertion(chg, sink_attached);
Nicholas Troast8c28e0f2017-03-22 14:44:49 -07003732 }
3733 } else {
3734 if (chg->typec_present) {
3735 chg->typec_present = false;
3736 smblib_dbg(chg, PR_MISC, "TypeC removal\n");
3737 smblib_handle_typec_removal(chg);
3738 }
3739 }
Abhijeet Dharmapurikar99ca0452016-10-13 09:50:41 -07003740
3741 rc = smblib_get_prop_typec_mode(chg, &pval);
3742 if (rc < 0)
Abhijeet Dharmapurikar31b98f32016-10-14 12:25:23 -07003743 smblib_err(chg, "Couldn't get prop typec mode rc=%d\n", rc);
Abhijeet Dharmapurikar99ca0452016-10-13 09:50:41 -07003744
3745 smblib_dbg(chg, PR_INTERRUPT, "IRQ: debounce-done %s; Type-C %s detected\n",
3746 rising ? "rising" : "falling",
3747 smblib_typec_mode_name[pval.intval]);
3748}
3749
Ashay Jaiswal4aa2c0c2016-12-07 19:39:38 +05303750irqreturn_t smblib_handle_usb_typec_change_for_uusb(struct smb_charger *chg)
3751{
3752 int rc;
3753 u8 stat;
3754
3755 rc = smblib_read(chg, TYPE_C_STATUS_3_REG, &stat);
3756 if (rc < 0) {
3757 smblib_err(chg, "Couldn't read TYPE_C_STATUS_3 rc=%d\n", rc);
3758 return IRQ_HANDLED;
3759 }
3760 smblib_dbg(chg, PR_REGISTER, "TYPE_C_STATUS_3 = 0x%02x OTG=%d\n",
3761 stat, !!(stat & (U_USB_GND_NOVBUS_BIT | U_USB_GND_BIT)));
3762
3763 extcon_set_cable_state_(chg->extcon, EXTCON_USB_HOST,
3764 !!(stat & (U_USB_GND_NOVBUS_BIT | U_USB_GND_BIT)));
3765 power_supply_changed(chg->usb_psy);
3766
3767 return IRQ_HANDLED;
3768}
3769
Abhijeet Dharmapurikar11330d92017-04-17 12:15:19 -07003770static void smblib_usb_typec_change(struct smb_charger *chg)
Nicholas Troast34db5032016-03-28 12:26:44 -07003771{
Nicholas Troast34db5032016-03-28 12:26:44 -07003772 int rc;
Abhijeet Dharmapurikar3c93db32017-04-17 17:36:14 -07003773 bool debounce_done, sink_attached;
Nicholas Troast34db5032016-03-28 12:26:44 -07003774
Abhijeet Dharmapurikarb0403c42017-04-17 12:26:26 -07003775 rc = smblib_multibyte_read(chg, TYPE_C_STATUS_1_REG,
3776 chg->typec_status, 5);
Nicholas Troast34db5032016-03-28 12:26:44 -07003777 if (rc < 0) {
Abhijeet Dharmapurikarb0403c42017-04-17 12:26:26 -07003778 smblib_err(chg, "Couldn't cache USB Type-C status rc=%d\n", rc);
Abhijeet Dharmapurikar11330d92017-04-17 12:15:19 -07003779 return;
Nicholas Troast34db5032016-03-28 12:26:44 -07003780 }
Nicholas Troast34db5032016-03-28 12:26:44 -07003781
Abhijeet Dharmapurikarb0403c42017-04-17 12:26:26 -07003782 debounce_done =
3783 (bool)(chg->typec_status[3] & TYPEC_DEBOUNCE_DONE_STATUS_BIT);
3784 sink_attached =
3785 (bool)(chg->typec_status[3] & UFP_DFP_MODE_STATUS_BIT);
Abhijeet Dharmapurikar99ca0452016-10-13 09:50:41 -07003786
Abhijeet Dharmapurikar3c93db32017-04-17 17:36:14 -07003787 smblib_handle_typec_debounce_done(chg, debounce_done, sink_attached);
Nicholas Troast34db5032016-03-28 12:26:44 -07003788
Abhijeet Dharmapurikarb0403c42017-04-17 12:26:26 -07003789 if (chg->typec_status[3] & TYPEC_VBUS_ERROR_STATUS_BIT)
Abhijeet Dharmapurikar11330d92017-04-17 12:15:19 -07003790 smblib_dbg(chg, PR_INTERRUPT, "IRQ: vbus-error\n");
Harry Yangd757c0f2016-09-23 10:52:05 -07003791
Abhijeet Dharmapurikarb0403c42017-04-17 12:26:26 -07003792 if (chg->typec_status[3] & TYPEC_VCONN_OVERCURR_STATUS_BIT)
Nicholas Troastb11015f2017-01-17 17:56:45 -08003793 schedule_work(&chg->vconn_oc_work);
Nicholas Troast8995a702016-12-05 10:22:22 -08003794
Nicholas Troastb1486552016-11-10 08:20:11 -08003795 power_supply_changed(chg->usb_psy);
Abhijeet Dharmapurikar11330d92017-04-17 12:15:19 -07003796}
3797
3798irqreturn_t smblib_handle_usb_typec_change(int irq, void *data)
3799{
3800 struct smb_irq_data *irq_data = data;
3801 struct smb_charger *chg = irq_data->parent_data;
3802
3803 if (chg->micro_usb_mode) {
3804 smblib_handle_usb_typec_change_for_uusb(chg);
3805 return IRQ_HANDLED;
3806 }
3807
Abhijeet Dharmapurikar3c93db32017-04-17 17:36:14 -07003808 if (chg->cc2_detach_wa_active || chg->typec_en_dis_active) {
3809 smblib_dbg(chg, PR_INTERRUPT, "Ignoring since %s active\n",
3810 chg->cc2_detach_wa_active ?
3811 "cc2_detach_wa" : "typec_en_dis");
Abhijeet Dharmapurikar11330d92017-04-17 12:15:19 -07003812 return IRQ_HANDLED;
3813 }
3814
3815 mutex_lock(&chg->lock);
3816 smblib_usb_typec_change(chg);
3817 mutex_unlock(&chg->lock);
Nicholas Troast34db5032016-03-28 12:26:44 -07003818 return IRQ_HANDLED;
3819}
3820
Abhijeet Dharmapurikar23916642016-10-03 10:38:50 -07003821irqreturn_t smblib_handle_dc_plugin(int irq, void *data)
3822{
3823 struct smb_irq_data *irq_data = data;
3824 struct smb_charger *chg = irq_data->parent_data;
3825
3826 power_supply_changed(chg->dc_psy);
3827 return IRQ_HANDLED;
3828}
3829
Abhijeet Dharmapurikar0e369002016-09-07 17:25:36 -07003830irqreturn_t smblib_handle_high_duty_cycle(int irq, void *data)
3831{
3832 struct smb_irq_data *irq_data = data;
3833 struct smb_charger *chg = irq_data->parent_data;
3834
3835 chg->is_hdc = true;
3836 schedule_delayed_work(&chg->clear_hdc_work, msecs_to_jiffies(60));
3837
3838 return IRQ_HANDLED;
3839}
3840
Nicholas Troastabedaf72016-09-16 11:07:45 -07003841irqreturn_t smblib_handle_switcher_power_ok(int irq, void *data)
3842{
3843 struct smb_irq_data *irq_data = data;
3844 struct smb_charger *chg = irq_data->parent_data;
Abhijeet Dharmapurikar3c93db32017-04-17 17:36:14 -07003845 int rc, usb_icl;
Nicholas Troastabedaf72016-09-16 11:07:45 -07003846 u8 stat;
3847
3848 if (!(chg->wa_flags & BOOST_BACK_WA))
3849 return IRQ_HANDLED;
3850
3851 rc = smblib_read(chg, POWER_PATH_STATUS_REG, &stat);
3852 if (rc < 0) {
3853 smblib_err(chg, "Couldn't read POWER_PATH_STATUS rc=%d\n", rc);
3854 return IRQ_HANDLED;
3855 }
3856
Abhijeet Dharmapurikar3c93db32017-04-17 17:36:14 -07003857 /* skip suspending input if its already suspended by some other voter */
3858 usb_icl = get_effective_result(chg->usb_icl_votable);
3859 if ((stat & USE_USBIN_BIT) && usb_icl >= 0 && usb_icl < USBIN_25MA)
Nicholas Troastabedaf72016-09-16 11:07:45 -07003860 return IRQ_HANDLED;
3861
Abhijeet Dharmapurikar2823fe32016-12-05 17:52:11 -08003862 if (stat & USE_DCIN_BIT)
Nicholas Troastabedaf72016-09-16 11:07:45 -07003863 return IRQ_HANDLED;
3864
3865 if (is_storming(&irq_data->storm_data)) {
Abhijeet Dharmapurikar5e0bfbe2017-02-12 19:16:15 -08003866 smblib_err(chg, "Reverse boost detected: voting 0mA to suspend input\n");
3867 vote(chg->usb_icl_votable, BOOST_BACK_VOTER, true, 0);
Nicholas Troastabedaf72016-09-16 11:07:45 -07003868 }
3869
3870 return IRQ_HANDLED;
3871}
3872
Nicholas Troast15dc0c82016-10-18 15:15:21 -07003873irqreturn_t smblib_handle_wdog_bark(int irq, void *data)
3874{
3875 struct smb_irq_data *irq_data = data;
3876 struct smb_charger *chg = irq_data->parent_data;
3877 int rc;
3878
3879 rc = smblib_write(chg, BARK_BITE_WDOG_PET_REG, BARK_BITE_WDOG_PET_BIT);
3880 if (rc < 0)
3881 smblib_err(chg, "Couldn't pet the dog rc=%d\n", rc);
3882
3883 return IRQ_HANDLED;
3884}
3885
Nicholas Troast34db5032016-03-28 12:26:44 -07003886/***************
3887 * Work Queues *
3888 ***************/
3889
3890static void smblib_hvdcp_detect_work(struct work_struct *work)
3891{
3892 struct smb_charger *chg = container_of(work, struct smb_charger,
3893 hvdcp_detect_work.work);
Nicholas Troast34db5032016-03-28 12:26:44 -07003894
Abhijeet Dharmapurikar4b13c6e2016-10-05 15:15:10 -07003895 vote(chg->pd_disallowed_votable_indirect, HVDCP_TIMEOUT_VOTER,
3896 false, 0);
Abhijeet Dharmapurikar3c93db32017-04-17 17:36:14 -07003897 power_supply_changed(chg->usb_psy);
Nicholas Troast34db5032016-03-28 12:26:44 -07003898}
3899
Harry Yangfe913842016-08-10 12:27:28 -07003900static void bms_update_work(struct work_struct *work)
Harry Yang5e1a5222016-07-26 15:16:04 -07003901{
3902 struct smb_charger *chg = container_of(work, struct smb_charger,
3903 bms_update_work);
Ashay Jaiswal2fb369d2017-01-12 21:38:29 +05303904
3905 smblib_suspend_on_debug_battery(chg);
3906
3907 if (chg->batt_psy)
3908 power_supply_changed(chg->batt_psy);
Harry Yang5e1a5222016-07-26 15:16:04 -07003909}
3910
Harry Yangfe913842016-08-10 12:27:28 -07003911static void step_soc_req_work(struct work_struct *work)
3912{
3913 struct smb_charger *chg = container_of(work, struct smb_charger,
3914 step_soc_req_work.work);
3915 union power_supply_propval pval = {0, };
3916 int rc;
3917
3918 rc = smblib_get_prop_batt_capacity(chg, &pval);
3919 if (rc < 0) {
Abhijeet Dharmapurikar31b98f32016-10-14 12:25:23 -07003920 smblib_err(chg, "Couldn't get batt capacity rc=%d\n", rc);
Harry Yangfe913842016-08-10 12:27:28 -07003921 return;
3922 }
3923
3924 step_charge_soc_update(chg, pval.intval);
3925}
3926
Abhijeet Dharmapurikar0e369002016-09-07 17:25:36 -07003927static void clear_hdc_work(struct work_struct *work)
3928{
3929 struct smb_charger *chg = container_of(work, struct smb_charger,
3930 clear_hdc_work.work);
3931
3932 chg->is_hdc = 0;
3933}
3934
Harry Yang755a34b2016-11-01 01:18:51 -07003935static void rdstd_cc2_detach_work(struct work_struct *work)
3936{
3937 int rc;
Abhijeet Dharmapurikar0e432812017-04-17 14:52:46 -07003938 u8 stat4, stat5;
Harry Yang755a34b2016-11-01 01:18:51 -07003939 struct smb_charger *chg = container_of(work, struct smb_charger,
3940 rdstd_cc2_detach_work);
3941
Abhijeet Dharmapurikar0e432812017-04-17 14:52:46 -07003942 if (!chg->cc2_detach_wa_active)
3943 return;
3944
Harry Yang755a34b2016-11-01 01:18:51 -07003945 /*
3946 * WA steps -
3947 * 1. Enable both UFP and DFP, wait for 10ms.
3948 * 2. Disable DFP, wait for 30ms.
3949 * 3. Removal detected if both TYPEC_DEBOUNCE_DONE_STATUS
3950 * and TIMER_STAGE bits are gone, otherwise repeat all by
3951 * work rescheduling.
Abhijeet Dharmapurikar0e432812017-04-17 14:52:46 -07003952 * Note, work will be cancelled when USB_PLUGIN rises.
Harry Yang755a34b2016-11-01 01:18:51 -07003953 */
3954
3955 rc = smblib_masked_write(chg, TYPE_C_INTRPT_ENB_SOFTWARE_CTRL_REG,
3956 UFP_EN_CMD_BIT | DFP_EN_CMD_BIT,
3957 UFP_EN_CMD_BIT | DFP_EN_CMD_BIT);
3958 if (rc < 0) {
3959 smblib_err(chg, "Couldn't write TYPE_C_CTRL_REG rc=%d\n", rc);
3960 return;
3961 }
3962
3963 usleep_range(10000, 11000);
3964
3965 rc = smblib_masked_write(chg, TYPE_C_INTRPT_ENB_SOFTWARE_CTRL_REG,
3966 UFP_EN_CMD_BIT | DFP_EN_CMD_BIT,
3967 UFP_EN_CMD_BIT);
3968 if (rc < 0) {
3969 smblib_err(chg, "Couldn't write TYPE_C_CTRL_REG rc=%d\n", rc);
3970 return;
3971 }
3972
3973 usleep_range(30000, 31000);
3974
Abhijeet Dharmapurikar0e432812017-04-17 14:52:46 -07003975 rc = smblib_read(chg, TYPE_C_STATUS_4_REG, &stat4);
Harry Yang755a34b2016-11-01 01:18:51 -07003976 if (rc < 0) {
Abhijeet Dharmapurikar0e432812017-04-17 14:52:46 -07003977 smblib_err(chg, "Couldn't read TYPE_C_STATUS_4 rc=%d\n", rc);
Harry Yang755a34b2016-11-01 01:18:51 -07003978 return;
3979 }
Harry Yang755a34b2016-11-01 01:18:51 -07003980
Abhijeet Dharmapurikar0e432812017-04-17 14:52:46 -07003981 rc = smblib_read(chg, TYPE_C_STATUS_5_REG, &stat5);
Harry Yang755a34b2016-11-01 01:18:51 -07003982 if (rc < 0) {
3983 smblib_err(chg,
3984 "Couldn't read TYPE_C_STATUS_5_REG rc=%d\n", rc);
3985 return;
3986 }
Harry Yang755a34b2016-11-01 01:18:51 -07003987
Abhijeet Dharmapurikar0e432812017-04-17 14:52:46 -07003988 if ((stat4 & TYPEC_DEBOUNCE_DONE_STATUS_BIT)
3989 || (stat5 & TIMER_STAGE_2_BIT)) {
3990 smblib_dbg(chg, PR_MISC, "rerunning DD=%d TS2BIT=%d\n",
3991 (int)(stat4 & TYPEC_DEBOUNCE_DONE_STATUS_BIT),
3992 (int)(stat5 & TIMER_STAGE_2_BIT));
3993 goto rerun;
3994 }
3995
3996 smblib_dbg(chg, PR_MISC, "Bingo CC2 Removal detected\n");
3997 chg->cc2_detach_wa_active = false;
3998 rc = smblib_masked_write(chg, TYPE_C_INTRPT_ENB_SOFTWARE_CTRL_REG,
3999 EXIT_SNK_BASED_ON_CC_BIT, 0);
Harry Yang755a34b2016-11-01 01:18:51 -07004000 smblib_reg_block_restore(chg, cc2_detach_settings);
Abhijeet Dharmapurikar11330d92017-04-17 12:15:19 -07004001 mutex_lock(&chg->lock);
4002 smblib_usb_typec_change(chg);
4003 mutex_unlock(&chg->lock);
Harry Yang755a34b2016-11-01 01:18:51 -07004004 return;
4005
4006rerun:
4007 schedule_work(&chg->rdstd_cc2_detach_work);
4008}
4009
Nicholas Troastb11015f2017-01-17 17:56:45 -08004010static void smblib_otg_oc_exit(struct smb_charger *chg, bool success)
4011{
4012 int rc;
4013
4014 chg->otg_attempts = 0;
4015 if (!success) {
4016 smblib_err(chg, "OTG soft start failed\n");
4017 chg->otg_en = false;
4018 }
4019
4020 smblib_dbg(chg, PR_OTG, "enabling VBUS < 1V check\n");
4021 rc = smblib_masked_write(chg, OTG_CFG_REG,
4022 QUICKSTART_OTG_FASTROLESWAP_BIT, 0);
4023 if (rc < 0)
4024 smblib_err(chg, "Couldn't enable VBUS < 1V check rc=%d\n", rc);
4025
4026 if (!chg->external_vconn && chg->vconn_en) {
4027 chg->vconn_attempts = 0;
4028 if (success) {
4029 rc = _smblib_vconn_regulator_enable(
4030 chg->vconn_vreg->rdev);
4031 if (rc < 0)
4032 smblib_err(chg, "Couldn't enable VCONN rc=%d\n",
4033 rc);
4034 } else {
4035 chg->vconn_en = false;
4036 }
4037 }
4038}
4039
4040#define MAX_OC_FALLING_TRIES 10
4041static void smblib_otg_oc_work(struct work_struct *work)
4042{
4043 struct smb_charger *chg = container_of(work, struct smb_charger,
4044 otg_oc_work);
4045 int rc, i;
4046 u8 stat;
4047
4048 if (!chg->vbus_vreg || !chg->vbus_vreg->rdev)
4049 return;
4050
4051 smblib_err(chg, "over-current detected on VBUS\n");
4052 mutex_lock(&chg->otg_oc_lock);
4053 if (!chg->otg_en)
4054 goto unlock;
4055
4056 smblib_dbg(chg, PR_OTG, "disabling VBUS < 1V check\n");
4057 smblib_masked_write(chg, OTG_CFG_REG,
4058 QUICKSTART_OTG_FASTROLESWAP_BIT,
4059 QUICKSTART_OTG_FASTROLESWAP_BIT);
4060
4061 /*
4062 * If 500ms has passed and another over-current interrupt has not
4063 * triggered then it is likely that the software based soft start was
4064 * successful and the VBUS < 1V restriction should be re-enabled.
4065 */
4066 schedule_delayed_work(&chg->otg_ss_done_work, msecs_to_jiffies(500));
4067
4068 rc = _smblib_vbus_regulator_disable(chg->vbus_vreg->rdev);
4069 if (rc < 0) {
4070 smblib_err(chg, "Couldn't disable VBUS rc=%d\n", rc);
4071 goto unlock;
4072 }
4073
4074 if (++chg->otg_attempts > OTG_MAX_ATTEMPTS) {
4075 cancel_delayed_work_sync(&chg->otg_ss_done_work);
4076 smblib_err(chg, "OTG failed to enable after %d attempts\n",
4077 chg->otg_attempts - 1);
4078 smblib_otg_oc_exit(chg, false);
4079 goto unlock;
4080 }
4081
4082 /*
4083 * The real time status should go low within 10ms. Poll every 1-2ms to
4084 * minimize the delay when re-enabling OTG.
4085 */
4086 for (i = 0; i < MAX_OC_FALLING_TRIES; ++i) {
4087 usleep_range(1000, 2000);
4088 rc = smblib_read(chg, OTG_BASE + INT_RT_STS_OFFSET, &stat);
4089 if (rc >= 0 && !(stat & OTG_OVERCURRENT_RT_STS_BIT))
4090 break;
4091 }
4092
4093 if (i >= MAX_OC_FALLING_TRIES) {
4094 cancel_delayed_work_sync(&chg->otg_ss_done_work);
4095 smblib_err(chg, "OTG OC did not fall after %dms\n",
4096 2 * MAX_OC_FALLING_TRIES);
4097 smblib_otg_oc_exit(chg, false);
4098 goto unlock;
4099 }
4100
4101 smblib_dbg(chg, PR_OTG, "OTG OC fell after %dms\n", 2 * i + 1);
4102 rc = _smblib_vbus_regulator_enable(chg->vbus_vreg->rdev);
4103 if (rc < 0) {
4104 smblib_err(chg, "Couldn't enable VBUS rc=%d\n", rc);
4105 goto unlock;
4106 }
4107
4108unlock:
4109 mutex_unlock(&chg->otg_oc_lock);
4110}
4111
4112static void smblib_vconn_oc_work(struct work_struct *work)
4113{
4114 struct smb_charger *chg = container_of(work, struct smb_charger,
4115 vconn_oc_work);
4116 int rc, i;
4117 u8 stat;
4118
Ashay Jaiswal15edce42017-03-31 23:29:58 +05304119 if (chg->micro_usb_mode)
4120 return;
4121
Nicholas Troastb11015f2017-01-17 17:56:45 -08004122 smblib_err(chg, "over-current detected on VCONN\n");
4123 if (!chg->vconn_vreg || !chg->vconn_vreg->rdev)
4124 return;
4125
4126 mutex_lock(&chg->otg_oc_lock);
4127 rc = _smblib_vconn_regulator_disable(chg->vconn_vreg->rdev);
4128 if (rc < 0) {
4129 smblib_err(chg, "Couldn't disable VCONN rc=%d\n", rc);
4130 goto unlock;
4131 }
4132
4133 if (++chg->vconn_attempts > VCONN_MAX_ATTEMPTS) {
4134 smblib_err(chg, "VCONN failed to enable after %d attempts\n",
4135 chg->otg_attempts - 1);
4136 chg->vconn_en = false;
4137 chg->vconn_attempts = 0;
4138 goto unlock;
4139 }
4140
4141 /*
4142 * The real time status should go low within 10ms. Poll every 1-2ms to
4143 * minimize the delay when re-enabling OTG.
4144 */
4145 for (i = 0; i < MAX_OC_FALLING_TRIES; ++i) {
4146 usleep_range(1000, 2000);
4147 rc = smblib_read(chg, TYPE_C_STATUS_4_REG, &stat);
4148 if (rc >= 0 && !(stat & TYPEC_VCONN_OVERCURR_STATUS_BIT))
4149 break;
4150 }
4151
4152 if (i >= MAX_OC_FALLING_TRIES) {
4153 smblib_err(chg, "VCONN OC did not fall after %dms\n",
4154 2 * MAX_OC_FALLING_TRIES);
4155 chg->vconn_en = false;
4156 chg->vconn_attempts = 0;
4157 goto unlock;
4158 }
4159
4160 smblib_dbg(chg, PR_OTG, "VCONN OC fell after %dms\n", 2 * i + 1);
4161 if (++chg->vconn_attempts > VCONN_MAX_ATTEMPTS) {
4162 smblib_err(chg, "VCONN failed to enable after %d attempts\n",
4163 chg->vconn_attempts - 1);
4164 chg->vconn_en = false;
4165 goto unlock;
4166 }
4167
4168 rc = _smblib_vconn_regulator_enable(chg->vconn_vreg->rdev);
4169 if (rc < 0) {
4170 smblib_err(chg, "Couldn't enable VCONN rc=%d\n", rc);
4171 goto unlock;
4172 }
4173
4174unlock:
4175 mutex_unlock(&chg->otg_oc_lock);
4176}
4177
4178static void smblib_otg_ss_done_work(struct work_struct *work)
4179{
4180 struct smb_charger *chg = container_of(work, struct smb_charger,
4181 otg_ss_done_work.work);
4182 int rc;
4183 bool success = false;
4184 u8 stat;
4185
4186 mutex_lock(&chg->otg_oc_lock);
4187 rc = smblib_read(chg, OTG_STATUS_REG, &stat);
4188 if (rc < 0)
4189 smblib_err(chg, "Couldn't read OTG status rc=%d\n", rc);
4190 else if (stat & BOOST_SOFTSTART_DONE_BIT)
4191 success = true;
4192
4193 smblib_otg_oc_exit(chg, success);
4194 mutex_unlock(&chg->otg_oc_lock);
4195}
4196
Ashay Jaiswal4d825782017-02-18 10:11:34 +05304197static void smblib_icl_change_work(struct work_struct *work)
4198{
4199 struct smb_charger *chg = container_of(work, struct smb_charger,
4200 icl_change_work.work);
4201 int rc, settled_ua;
4202
4203 rc = smblib_get_charge_param(chg, &chg->param.icl_stat, &settled_ua);
4204 if (rc < 0) {
4205 smblib_err(chg, "Couldn't get ICL status rc=%d\n", rc);
4206 return;
4207 }
4208
4209 power_supply_changed(chg->usb_main_psy);
4210 vote(chg->pl_enable_votable_indirect, USBIN_I_VOTER,
4211 settled_ua >= USB_WEAK_INPUT_UA, 0);
4212
4213 smblib_dbg(chg, PR_INTERRUPT, "icl_settled=%d\n", settled_ua);
4214}
4215
Ashay Jaiswalc0361672017-03-21 12:24:16 +05304216static void smblib_pl_enable_work(struct work_struct *work)
4217{
4218 struct smb_charger *chg = container_of(work, struct smb_charger,
4219 pl_enable_work.work);
4220
4221 smblib_dbg(chg, PR_PARALLEL, "timer expired, enabling parallel\n");
4222 vote(chg->pl_disable_votable, PL_DELAY_VOTER, false, 0);
4223 vote(chg->awake_votable, PL_DELAY_VOTER, false, 0);
4224}
4225
Abhijeet Dharmapurikar3c93db32017-04-17 17:36:14 -07004226static void smblib_legacy_detection_work(struct work_struct *work)
4227{
4228 struct smb_charger *chg = container_of(work, struct smb_charger,
4229 legacy_detection_work);
4230 int rc;
4231 u8 stat;
4232 bool legacy, rp_high;
4233
4234 mutex_lock(&chg->lock);
4235 chg->typec_en_dis_active = 1;
4236 smblib_dbg(chg, PR_MISC, "running legacy unknown workaround\n");
4237 rc = smblib_masked_write(chg,
4238 TYPE_C_INTRPT_ENB_SOFTWARE_CTRL_REG,
4239 TYPEC_DISABLE_CMD_BIT,
4240 TYPEC_DISABLE_CMD_BIT);
4241 if (rc < 0)
4242 smblib_err(chg, "Couldn't disable type-c rc=%d\n", rc);
4243
4244 /* wait for the adapter to turn off VBUS */
4245 msleep(500);
4246
4247 rc = smblib_masked_write(chg,
4248 TYPE_C_INTRPT_ENB_SOFTWARE_CTRL_REG,
4249 TYPEC_DISABLE_CMD_BIT, 0);
4250 if (rc < 0)
4251 smblib_err(chg, "Couldn't enable type-c rc=%d\n", rc);
4252
4253 /* wait for type-c detection to complete */
4254 msleep(100);
4255
4256 rc = smblib_read(chg, TYPE_C_STATUS_5_REG, &stat);
4257 if (rc < 0) {
4258 smblib_err(chg, "Couldn't read typec stat5 rc = %d\n", rc);
4259 goto unlock;
4260 }
4261
4262 chg->typec_legacy_valid = true;
4263 vote(chg->usb_icl_votable, LEGACY_UNKNOWN_VOTER, false, 0);
4264 legacy = stat & TYPEC_LEGACY_CABLE_STATUS_BIT;
4265 rp_high = smblib_get_prop_ufp_mode(chg) ==
4266 POWER_SUPPLY_TYPEC_SOURCE_HIGH;
4267 if (!legacy || !rp_high)
4268 vote(chg->hvdcp_disable_votable_indirect, VBUS_CC_SHORT_VOTER,
4269 false, 0);
4270
4271unlock:
4272 chg->typec_en_dis_active = 0;
4273 mutex_unlock(&chg->lock);
4274}
4275
Harry Yangba874ce2016-08-19 14:17:01 -07004276static int smblib_create_votables(struct smb_charger *chg)
Nicholas Troast34db5032016-03-28 12:26:44 -07004277{
4278 int rc = 0;
4279
Ashay Jaiswal37b8ea62017-02-03 11:37:28 +05304280 chg->fcc_votable = find_votable("FCC");
4281 if (!chg->fcc_votable) {
4282 rc = -EPROBE_DEFER;
4283 return rc;
4284 }
4285
4286 chg->fv_votable = find_votable("FV");
4287 if (!chg->fv_votable) {
4288 rc = -EPROBE_DEFER;
4289 return rc;
4290 }
4291
Ashay Jaiswalae1586d2017-03-22 23:18:51 +05304292 chg->usb_icl_votable = find_votable("USB_ICL");
4293 if (!chg->usb_icl_votable) {
4294 rc = -EPROBE_DEFER;
4295 return rc;
4296 }
4297
Ashay Jaiswal37b8ea62017-02-03 11:37:28 +05304298 chg->pl_disable_votable = find_votable("PL_DISABLE");
4299 if (!chg->pl_disable_votable) {
4300 rc = -EPROBE_DEFER;
4301 return rc;
4302 }
4303 vote(chg->pl_disable_votable, PL_INDIRECT_VOTER, true, 0);
Ashay Jaiswalc0361672017-03-21 12:24:16 +05304304 vote(chg->pl_disable_votable, PL_DELAY_VOTER, true, 0);
Ashay Jaiswal37b8ea62017-02-03 11:37:28 +05304305
Abhijeet Dharmapurikar8e9e7572016-06-06 16:13:14 -07004306 chg->dc_suspend_votable = create_votable("DC_SUSPEND", VOTE_SET_ANY,
4307 smblib_dc_suspend_vote_callback,
4308 chg);
Nicholas Troast34db5032016-03-28 12:26:44 -07004309 if (IS_ERR(chg->dc_suspend_votable)) {
4310 rc = PTR_ERR(chg->dc_suspend_votable);
4311 return rc;
4312 }
4313
Abhijeet Dharmapurikar8e9e7572016-06-06 16:13:14 -07004314 chg->dc_icl_votable = create_votable("DC_ICL", VOTE_MIN,
4315 smblib_dc_icl_vote_callback,
4316 chg);
Nicholas Troast34db5032016-03-28 12:26:44 -07004317 if (IS_ERR(chg->dc_icl_votable)) {
4318 rc = PTR_ERR(chg->dc_icl_votable);
4319 return rc;
4320 }
4321
Abhijeet Dharmapurikar4b13c6e2016-10-05 15:15:10 -07004322 chg->pd_disallowed_votable_indirect
4323 = create_votable("PD_DISALLOWED_INDIRECT", VOTE_SET_ANY,
4324 smblib_pd_disallowed_votable_indirect_callback, chg);
4325 if (IS_ERR(chg->pd_disallowed_votable_indirect)) {
4326 rc = PTR_ERR(chg->pd_disallowed_votable_indirect);
4327 return rc;
4328 }
4329
4330 chg->pd_allowed_votable = create_votable("PD_ALLOWED",
4331 VOTE_SET_ANY, NULL, NULL);
Nicholas Troast34db5032016-03-28 12:26:44 -07004332 if (IS_ERR(chg->pd_allowed_votable)) {
4333 rc = PTR_ERR(chg->pd_allowed_votable);
4334 return rc;
4335 }
4336
Harry Yang223c6282016-06-14 15:48:36 -07004337 chg->awake_votable = create_votable("AWAKE", VOTE_SET_ANY,
4338 smblib_awake_vote_callback,
4339 chg);
4340 if (IS_ERR(chg->awake_votable)) {
4341 rc = PTR_ERR(chg->awake_votable);
4342 return rc;
4343 }
4344
Abhijeet Dharmapurikaree54de02016-07-08 14:51:47 -07004345 chg->chg_disable_votable = create_votable("CHG_DISABLE", VOTE_SET_ANY,
4346 smblib_chg_disable_vote_callback,
4347 chg);
4348 if (IS_ERR(chg->chg_disable_votable)) {
4349 rc = PTR_ERR(chg->chg_disable_votable);
4350 return rc;
4351 }
4352
Harry Yangaba1f5f2016-09-28 10:47:29 -07004353 chg->pl_enable_votable_indirect = create_votable("PL_ENABLE_INDIRECT",
4354 VOTE_SET_ANY,
4355 smblib_pl_enable_indirect_vote_callback,
4356 chg);
4357 if (IS_ERR(chg->pl_enable_votable_indirect)) {
4358 rc = PTR_ERR(chg->pl_enable_votable_indirect);
4359 return rc;
4360 }
4361
Ashay Jaiswal4aa2c0c2016-12-07 19:39:38 +05304362 chg->hvdcp_disable_votable_indirect = create_votable(
4363 "HVDCP_DISABLE_INDIRECT",
4364 VOTE_SET_ANY,
4365 smblib_hvdcp_disable_indirect_vote_callback,
4366 chg);
4367 if (IS_ERR(chg->hvdcp_disable_votable_indirect)) {
4368 rc = PTR_ERR(chg->hvdcp_disable_votable_indirect);
4369 return rc;
4370 }
4371
4372 chg->hvdcp_enable_votable = create_votable("HVDCP_ENABLE",
Abhijeet Dharmapurikarf0b0a042016-10-10 16:43:43 -07004373 VOTE_SET_ANY,
Ashay Jaiswal4aa2c0c2016-12-07 19:39:38 +05304374 smblib_hvdcp_enable_vote_callback,
Abhijeet Dharmapurikarf0b0a042016-10-10 16:43:43 -07004375 chg);
Ashay Jaiswal4aa2c0c2016-12-07 19:39:38 +05304376 if (IS_ERR(chg->hvdcp_enable_votable)) {
4377 rc = PTR_ERR(chg->hvdcp_enable_votable);
Abhijeet Dharmapurikarf0b0a042016-10-10 16:43:43 -07004378 return rc;
4379 }
Abhijeet Dharmapurikarf8a7a4a2016-10-07 18:46:45 -07004380
4381 chg->apsd_disable_votable = create_votable("APSD_DISABLE",
4382 VOTE_SET_ANY,
4383 smblib_apsd_disable_vote_callback,
4384 chg);
4385 if (IS_ERR(chg->apsd_disable_votable)) {
4386 rc = PTR_ERR(chg->apsd_disable_votable);
4387 return rc;
4388 }
4389
Ashay Jaiswal6d308da2017-02-18 09:59:23 +05304390 chg->hvdcp_hw_inov_dis_votable = create_votable("HVDCP_HW_INOV_DIS",
4391 VOTE_SET_ANY,
4392 smblib_hvdcp_hw_inov_dis_vote_callback,
4393 chg);
4394 if (IS_ERR(chg->hvdcp_hw_inov_dis_votable)) {
4395 rc = PTR_ERR(chg->hvdcp_hw_inov_dis_votable);
4396 return rc;
4397 }
4398
Harry Yang4bf7d962017-03-13 16:51:43 -07004399 chg->usb_irq_enable_votable = create_votable("USB_IRQ_DISABLE",
4400 VOTE_SET_ANY,
4401 smblib_usb_irq_enable_vote_callback,
4402 chg);
4403 if (IS_ERR(chg->usb_irq_enable_votable)) {
4404 rc = PTR_ERR(chg->usb_irq_enable_votable);
4405 return rc;
4406 }
4407
Abhijeet Dharmapurikar3c93db32017-04-17 17:36:14 -07004408 chg->typec_irq_disable_votable = create_votable("TYPEC_IRQ_DISABLE",
4409 VOTE_SET_ANY,
4410 smblib_typec_irq_disable_vote_callback,
4411 chg);
4412 if (IS_ERR(chg->typec_irq_disable_votable)) {
4413 rc = PTR_ERR(chg->typec_irq_disable_votable);
4414 return rc;
4415 }
4416
Nicholas Troast320839e2016-06-03 10:18:00 -07004417 return rc;
4418}
4419
Harry Yangba874ce2016-08-19 14:17:01 -07004420static void smblib_destroy_votables(struct smb_charger *chg)
4421{
Harry Yangba874ce2016-08-19 14:17:01 -07004422 if (chg->dc_suspend_votable)
4423 destroy_votable(chg->dc_suspend_votable);
Harry Yangba874ce2016-08-19 14:17:01 -07004424 if (chg->usb_icl_votable)
4425 destroy_votable(chg->usb_icl_votable);
4426 if (chg->dc_icl_votable)
4427 destroy_votable(chg->dc_icl_votable);
Abhijeet Dharmapurikar4b13c6e2016-10-05 15:15:10 -07004428 if (chg->pd_disallowed_votable_indirect)
4429 destroy_votable(chg->pd_disallowed_votable_indirect);
Harry Yangba874ce2016-08-19 14:17:01 -07004430 if (chg->pd_allowed_votable)
4431 destroy_votable(chg->pd_allowed_votable);
4432 if (chg->awake_votable)
4433 destroy_votable(chg->awake_votable);
Harry Yangaba1f5f2016-09-28 10:47:29 -07004434 if (chg->chg_disable_votable)
4435 destroy_votable(chg->chg_disable_votable);
4436 if (chg->pl_enable_votable_indirect)
4437 destroy_votable(chg->pl_enable_votable_indirect);
Abhijeet Dharmapurikarf8a7a4a2016-10-07 18:46:45 -07004438 if (chg->apsd_disable_votable)
4439 destroy_votable(chg->apsd_disable_votable);
Ashay Jaiswal6d308da2017-02-18 09:59:23 +05304440 if (chg->hvdcp_hw_inov_dis_votable)
4441 destroy_votable(chg->hvdcp_hw_inov_dis_votable);
Abhijeet Dharmapurikar3c93db32017-04-17 17:36:14 -07004442 if (chg->typec_irq_disable_votable)
4443 destroy_votable(chg->typec_irq_disable_votable);
Harry Yangba874ce2016-08-19 14:17:01 -07004444}
4445
4446static void smblib_iio_deinit(struct smb_charger *chg)
4447{
4448 if (!IS_ERR_OR_NULL(chg->iio.temp_chan))
4449 iio_channel_release(chg->iio.temp_chan);
4450 if (!IS_ERR_OR_NULL(chg->iio.temp_max_chan))
4451 iio_channel_release(chg->iio.temp_max_chan);
4452 if (!IS_ERR_OR_NULL(chg->iio.usbin_i_chan))
4453 iio_channel_release(chg->iio.usbin_i_chan);
4454 if (!IS_ERR_OR_NULL(chg->iio.usbin_v_chan))
4455 iio_channel_release(chg->iio.usbin_v_chan);
Nicholas Troast7dbcad22016-10-05 13:30:18 -07004456 if (!IS_ERR_OR_NULL(chg->iio.batt_i_chan))
4457 iio_channel_release(chg->iio.batt_i_chan);
Harry Yangba874ce2016-08-19 14:17:01 -07004458}
4459
Nicholas Troast320839e2016-06-03 10:18:00 -07004460int smblib_init(struct smb_charger *chg)
4461{
4462 int rc = 0;
4463
Abhijeet Dharmapurikar11330d92017-04-17 12:15:19 -07004464 mutex_init(&chg->lock);
Nicholas Troast320839e2016-06-03 10:18:00 -07004465 mutex_init(&chg->write_lock);
Nicholas Troastb11015f2017-01-17 17:56:45 -08004466 mutex_init(&chg->otg_oc_lock);
Harry Yangfe913842016-08-10 12:27:28 -07004467 INIT_WORK(&chg->bms_update_work, bms_update_work);
Harry Yang755a34b2016-11-01 01:18:51 -07004468 INIT_WORK(&chg->rdstd_cc2_detach_work, rdstd_cc2_detach_work);
Nicholas Troast320839e2016-06-03 10:18:00 -07004469 INIT_DELAYED_WORK(&chg->hvdcp_detect_work, smblib_hvdcp_detect_work);
Harry Yangfe913842016-08-10 12:27:28 -07004470 INIT_DELAYED_WORK(&chg->step_soc_req_work, step_soc_req_work);
Abhijeet Dharmapurikar0e369002016-09-07 17:25:36 -07004471 INIT_DELAYED_WORK(&chg->clear_hdc_work, clear_hdc_work);
Nicholas Troastb11015f2017-01-17 17:56:45 -08004472 INIT_WORK(&chg->otg_oc_work, smblib_otg_oc_work);
4473 INIT_WORK(&chg->vconn_oc_work, smblib_vconn_oc_work);
4474 INIT_DELAYED_WORK(&chg->otg_ss_done_work, smblib_otg_ss_done_work);
Ashay Jaiswal4d825782017-02-18 10:11:34 +05304475 INIT_DELAYED_WORK(&chg->icl_change_work, smblib_icl_change_work);
Ashay Jaiswalc0361672017-03-21 12:24:16 +05304476 INIT_DELAYED_WORK(&chg->pl_enable_work, smblib_pl_enable_work);
Abhijeet Dharmapurikar3c93db32017-04-17 17:36:14 -07004477 INIT_WORK(&chg->legacy_detection_work, smblib_legacy_detection_work);
Abhijeet Dharmapurikar9e7e48c2016-08-23 12:55:49 -07004478 chg->fake_capacity = -EINVAL;
Nicholas Troast320839e2016-06-03 10:18:00 -07004479
4480 switch (chg->mode) {
4481 case PARALLEL_MASTER:
Harry Yang603e3802017-02-09 17:45:12 -08004482 chg->qnovo_fcc_ua = -EINVAL;
4483 chg->qnovo_fv_uv = -EINVAL;
Nicholas Troast320839e2016-06-03 10:18:00 -07004484 rc = smblib_create_votables(chg);
4485 if (rc < 0) {
Abhijeet Dharmapurikar31b98f32016-10-14 12:25:23 -07004486 smblib_err(chg, "Couldn't create votables rc=%d\n",
Nicholas Troast320839e2016-06-03 10:18:00 -07004487 rc);
Harry Yang58a9e7a2016-06-23 14:54:43 -07004488 return rc;
Nicholas Troast320839e2016-06-03 10:18:00 -07004489 }
Harry Yang58a9e7a2016-06-23 14:54:43 -07004490
Harry Yang5e1a5222016-07-26 15:16:04 -07004491 rc = smblib_register_notifier(chg);
4492 if (rc < 0) {
Abhijeet Dharmapurikar31b98f32016-10-14 12:25:23 -07004493 smblib_err(chg,
Harry Yang5e1a5222016-07-26 15:16:04 -07004494 "Couldn't register notifier rc=%d\n", rc);
4495 return rc;
Harry Yang58a9e7a2016-06-23 14:54:43 -07004496 }
4497
Harry Yang995b7422016-08-29 16:06:50 -07004498 chg->bms_psy = power_supply_get_by_name("bms");
Ashay Jaiswal8afedfc2017-02-03 11:18:22 +05304499 chg->pl.psy = power_supply_get_by_name("parallel");
Nicholas Troast320839e2016-06-03 10:18:00 -07004500 break;
4501 case PARALLEL_SLAVE:
4502 break;
4503 default:
Abhijeet Dharmapurikar31b98f32016-10-14 12:25:23 -07004504 smblib_err(chg, "Unsupported mode %d\n", chg->mode);
Nicholas Troast320839e2016-06-03 10:18:00 -07004505 return -EINVAL;
4506 }
4507
4508 return rc;
Nicholas Troast34db5032016-03-28 12:26:44 -07004509}
Abhijeet Dharmapurikar8e9e7572016-06-06 16:13:14 -07004510
4511int smblib_deinit(struct smb_charger *chg)
4512{
Harry Yangba874ce2016-08-19 14:17:01 -07004513 switch (chg->mode) {
4514 case PARALLEL_MASTER:
4515 power_supply_unreg_notifier(&chg->nb);
4516 smblib_destroy_votables(chg);
4517 break;
4518 case PARALLEL_SLAVE:
4519 break;
4520 default:
Abhijeet Dharmapurikar31b98f32016-10-14 12:25:23 -07004521 smblib_err(chg, "Unsupported mode %d\n", chg->mode);
Harry Yangba874ce2016-08-19 14:17:01 -07004522 return -EINVAL;
4523 }
Abhijeet Dharmapurikar8e9e7572016-06-06 16:13:14 -07004524
Harry Yangba874ce2016-08-19 14:17:01 -07004525 smblib_iio_deinit(chg);
Harry Yang5e1a5222016-07-26 15:16:04 -07004526
Abhijeet Dharmapurikar8e9e7572016-06-06 16:13:14 -07004527 return 0;
4528}