blob: fd4afbbd82a4a527ccf7086a0af8bf6fb9222589 [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 Dharmapurikar716cd962016-10-14 12:50:37 -0700545static int try_rerun_apsd_for_hvdcp(struct smb_charger *chg)
546{
547 const struct apsd_result *apsd_result;
548
549 /*
550 * PD_INACTIVE_VOTER on hvdcp_disable_votable indicates whether
551 * apsd rerun was tried earlier
552 */
Ashay Jaiswal4aa2c0c2016-12-07 19:39:38 +0530553 if (get_client_vote(chg->hvdcp_disable_votable_indirect,
554 PD_INACTIVE_VOTER)) {
555 vote(chg->hvdcp_disable_votable_indirect,
556 PD_INACTIVE_VOTER, false, 0);
Abhijeet Dharmapurikar716cd962016-10-14 12:50:37 -0700557 /* ensure hvdcp is enabled */
Ashay Jaiswal4aa2c0c2016-12-07 19:39:38 +0530558 if (!get_effective_result(
559 chg->hvdcp_disable_votable_indirect)) {
Abhijeet Dharmapurikar716cd962016-10-14 12:50:37 -0700560 apsd_result = smblib_get_apsd_result(chg);
Nicholas Troast7e7e3ef2016-10-28 10:36:45 -0700561 if (apsd_result->bit & (QC_2P0_BIT | QC_3P0_BIT)) {
Nicholas Troast93fb0f02017-03-01 10:17:13 -0800562 smblib_rerun_apsd(chg);
Abhijeet Dharmapurikar716cd962016-10-14 12:50:37 -0700563 }
564 }
565 }
566 return 0;
567}
568
Abhijeet Dharmapurikarb9598872016-10-17 16:58:58 -0700569static const struct apsd_result *smblib_update_usb_type(struct smb_charger *chg)
Nicholas Troast34db5032016-03-28 12:26:44 -0700570{
Abhijeet Dharmapurikareda08222016-11-01 11:35:29 -0700571 const struct apsd_result *apsd_result = smblib_get_apsd_result(chg);
Nicholas Troast34db5032016-03-28 12:26:44 -0700572
Jack Pham9696e252016-05-23 11:15:15 -0700573 /* if PD is active, APSD is disabled so won't have a valid result */
Nicholas Troast93fb0f02017-03-01 10:17:13 -0800574 if (chg->pd_active)
Abhijeet Dharmapurikar76e2af52016-10-06 17:25:01 -0700575 chg->usb_psy_desc.type = POWER_SUPPLY_TYPE_USB_PD;
Nicholas Troast93fb0f02017-03-01 10:17:13 -0800576 else
577 chg->usb_psy_desc.type = apsd_result->pst;
Nicholas Troast34db5032016-03-28 12:26:44 -0700578
Nicholas Troast93fb0f02017-03-01 10:17:13 -0800579 smblib_dbg(chg, PR_MISC, "APSD=%s PD=%d\n",
580 apsd_result->name, chg->pd_active);
Abhijeet Dharmapurikarb9598872016-10-17 16:58:58 -0700581 return apsd_result;
Nicholas Troast34db5032016-03-28 12:26:44 -0700582}
583
Harry Yang5e1a5222016-07-26 15:16:04 -0700584static int smblib_notifier_call(struct notifier_block *nb,
Harry Yang58a9e7a2016-06-23 14:54:43 -0700585 unsigned long ev, void *v)
Harry Yang1d1034c2016-06-15 12:09:42 -0700586{
Harry Yang58a9e7a2016-06-23 14:54:43 -0700587 struct power_supply *psy = v;
Harry Yang5e1a5222016-07-26 15:16:04 -0700588 struct smb_charger *chg = container_of(nb, struct smb_charger, nb);
Harry Yang1d1034c2016-06-15 12:09:42 -0700589
Harry Yang5e1a5222016-07-26 15:16:04 -0700590 if (!strcmp(psy->desc->name, "bms")) {
591 if (!chg->bms_psy)
592 chg->bms_psy = psy;
Ashay Jaiswal2fb369d2017-01-12 21:38:29 +0530593 if (ev == PSY_EVENT_PROP_CHANGED)
Harry Yang5e1a5222016-07-26 15:16:04 -0700594 schedule_work(&chg->bms_update_work);
595 }
596
Ashay Jaiswal8afedfc2017-02-03 11:18:22 +0530597 if (!chg->pl.psy && !strcmp(psy->desc->name, "parallel"))
Harry Yang58a9e7a2016-06-23 14:54:43 -0700598 chg->pl.psy = psy;
Harry Yang1d1034c2016-06-15 12:09:42 -0700599
Harry Yang58a9e7a2016-06-23 14:54:43 -0700600 return NOTIFY_OK;
601}
602
Harry Yang5e1a5222016-07-26 15:16:04 -0700603static int smblib_register_notifier(struct smb_charger *chg)
Harry Yang58a9e7a2016-06-23 14:54:43 -0700604{
605 int rc;
606
Harry Yang5e1a5222016-07-26 15:16:04 -0700607 chg->nb.notifier_call = smblib_notifier_call;
608 rc = power_supply_reg_notifier(&chg->nb);
Harry Yang58a9e7a2016-06-23 14:54:43 -0700609 if (rc < 0) {
Abhijeet Dharmapurikar31b98f32016-10-14 12:25:23 -0700610 smblib_err(chg, "Couldn't register psy notifier rc = %d\n", rc);
Harry Yang58a9e7a2016-06-23 14:54:43 -0700611 return rc;
612 }
613
614 return 0;
Harry Yang1d1034c2016-06-15 12:09:42 -0700615}
616
Harry Yangfe913842016-08-10 12:27:28 -0700617int smblib_mapping_soc_from_field_value(struct smb_chg_param *param,
618 int val_u, u8 *val_raw)
619{
620 if (val_u > param->max_u || val_u < param->min_u)
621 return -EINVAL;
622
623 *val_raw = val_u << 1;
624
625 return 0;
626}
627
628int smblib_mapping_cc_delta_to_field_value(struct smb_chg_param *param,
629 u8 val_raw)
630{
631 int val_u = val_raw * param->step_u + param->min_u;
632
633 if (val_u > param->max_u)
634 val_u -= param->max_u * 2;
635
636 return val_u;
637}
638
639int smblib_mapping_cc_delta_from_field_value(struct smb_chg_param *param,
640 int val_u, u8 *val_raw)
641{
642 if (val_u > param->max_u || val_u < param->min_u - param->max_u)
643 return -EINVAL;
644
645 val_u += param->max_u * 2 - param->min_u;
646 val_u %= param->max_u * 2;
647 *val_raw = val_u / param->step_u;
648
649 return 0;
650}
651
Ashay Jaiswal4aa2c0c2016-12-07 19:39:38 +0530652static void smblib_uusb_removal(struct smb_charger *chg)
653{
654 int rc;
655
656 /* reset both usbin current and voltage votes */
657 vote(chg->pl_enable_votable_indirect, USBIN_I_VOTER, false, 0);
658 vote(chg->pl_enable_votable_indirect, USBIN_V_VOTER, false, 0);
Ashay Jaiswale38fe7e2017-02-13 11:42:19 +0530659 vote(chg->pl_disable_votable, PL_DELAY_HVDCP_VOTER, true, 0);
Ashay Jaiswal4aa2c0c2016-12-07 19:39:38 +0530660
661 cancel_delayed_work_sync(&chg->hvdcp_detect_work);
662
Ashay Jaiswal67ec7072017-02-16 14:14:58 +0530663 if (chg->wa_flags & QC_AUTH_INTERRUPT_WA_BIT) {
664 /* re-enable AUTH_IRQ_EN_CFG_BIT */
665 rc = smblib_masked_write(chg,
666 USBIN_SOURCE_CHANGE_INTRPT_ENB_REG,
667 AUTH_IRQ_EN_CFG_BIT, AUTH_IRQ_EN_CFG_BIT);
668 if (rc < 0)
669 smblib_err(chg,
670 "Couldn't enable QC auth setting rc=%d\n", rc);
671 }
Ashay Jaiswal4aa2c0c2016-12-07 19:39:38 +0530672
673 /* reconfigure allowed voltage for HVDCP */
Ashay Jaiswalb3101012017-03-01 10:18:04 +0530674 rc = smblib_set_adapter_allowance(chg,
675 USBIN_ADAPTER_ALLOW_5V_OR_9V_TO_12V);
Ashay Jaiswal4aa2c0c2016-12-07 19:39:38 +0530676 if (rc < 0)
677 smblib_err(chg, "Couldn't set USBIN_ADAPTER_ALLOW_5V_OR_9V_TO_12V rc=%d\n",
678 rc);
679
680 chg->voltage_min_uv = MICRO_5V;
681 chg->voltage_max_uv = MICRO_5V;
Ashay Jaiswal6d308da2017-02-18 09:59:23 +0530682 chg->usb_icl_delta_ua = 0;
683 chg->pulse_cnt = 0;
Ashay Jaiswal4aa2c0c2016-12-07 19:39:38 +0530684
685 /* clear USB ICL vote for USB_PSY_VOTER */
686 rc = vote(chg->usb_icl_votable, USB_PSY_VOTER, false, 0);
687 if (rc < 0)
688 smblib_err(chg, "Couldn't un-vote for USB ICL rc=%d\n", rc);
Abhijeet Dharmapurikar7442e422017-02-08 13:35:14 -0800689
690 /* clear USB ICL vote for DCP_VOTER */
691 rc = vote(chg->usb_icl_votable, DCP_VOTER, false, 0);
692 if (rc < 0)
693 smblib_err(chg,
694 "Couldn't un-vote DCP from USB ICL rc=%d\n", rc);
695
696 /* clear USB ICL vote for PL_USBIN_USBIN_VOTER */
697 rc = vote(chg->usb_icl_votable, PL_USBIN_USBIN_VOTER, false, 0);
698 if (rc < 0)
699 smblib_err(chg,
700 "Couldn't un-vote PL_USBIN_USBIN from USB ICL rc=%d\n",
701 rc);
Ashay Jaiswal4aa2c0c2016-12-07 19:39:38 +0530702}
703
Ashay Jaiswal2fb369d2017-01-12 21:38:29 +0530704void smblib_suspend_on_debug_battery(struct smb_charger *chg)
705{
706 int rc;
707 union power_supply_propval val;
708
Ashay Jaiswalda8669b2017-02-10 23:24:23 +0530709 if (!chg->suspend_input_on_debug_batt)
710 return;
711
Ashay Jaiswal2fb369d2017-01-12 21:38:29 +0530712 rc = power_supply_get_property(chg->bms_psy,
713 POWER_SUPPLY_PROP_DEBUG_BATTERY, &val);
714 if (rc < 0) {
715 smblib_err(chg, "Couldn't get debug battery prop rc=%d\n", rc);
716 return;
717 }
718
Abhijeet Dharmapurikar5e0bfbe2017-02-12 19:16:15 -0800719 vote(chg->usb_icl_votable, DEBUG_BOARD_VOTER, val.intval, 0);
Ashay Jaiswal2fb369d2017-01-12 21:38:29 +0530720 vote(chg->dc_suspend_votable, DEBUG_BOARD_VOTER, val.intval, 0);
721 if (val.intval)
722 pr_info("Input suspended: Fake battery\n");
723}
724
Abhijeet Dharmapurikar9dd61292017-01-25 16:40:08 -0800725int smblib_rerun_apsd_if_required(struct smb_charger *chg)
726{
727 const struct apsd_result *apsd_result;
728 union power_supply_propval val;
729 int rc;
730
731 rc = smblib_get_prop_usb_present(chg, &val);
732 if (rc < 0) {
733 smblib_err(chg, "Couldn't get usb present rc = %d\n", rc);
734 return rc;
735 }
736
737 if (!val.intval)
738 return 0;
739
740 apsd_result = smblib_get_apsd_result(chg);
Abhijeet Dharmapurikar025e63a2017-02-24 14:06:22 -0800741 if ((apsd_result->pst != POWER_SUPPLY_TYPE_UNKNOWN)
742 && (apsd_result->pst != POWER_SUPPLY_TYPE_USB))
743 /* if type is not usb or unknown no need to rerun apsd */
744 return 0;
745
746 /* fetch the DPDM regulator */
747 if (!chg->dpdm_reg && of_get_property(chg->dev->of_node,
748 "dpdm-supply", NULL)) {
749 chg->dpdm_reg = devm_regulator_get(chg->dev, "dpdm");
750 if (IS_ERR(chg->dpdm_reg)) {
751 smblib_err(chg, "Couldn't get dpdm regulator rc=%ld\n",
752 PTR_ERR(chg->dpdm_reg));
753 chg->dpdm_reg = NULL;
754 }
Abhijeet Dharmapurikar9dd61292017-01-25 16:40:08 -0800755 }
756
Abhijeet Dharmapurikar025e63a2017-02-24 14:06:22 -0800757 if (chg->dpdm_reg && !regulator_is_enabled(chg->dpdm_reg)) {
758 smblib_dbg(chg, PR_MISC, "enabling DPDM regulator\n");
759 rc = regulator_enable(chg->dpdm_reg);
760 if (rc < 0)
761 smblib_err(chg, "Couldn't enable dpdm regulator rc=%d\n",
762 rc);
763 }
764
765 smblib_rerun_apsd(chg);
766
Abhijeet Dharmapurikar9dd61292017-01-25 16:40:08 -0800767 return 0;
768}
769
Ashay Jaiswal6d308da2017-02-18 09:59:23 +0530770static int smblib_get_pulse_cnt(struct smb_charger *chg, int *count)
771{
772 int rc;
773 u8 val[2];
774
775 switch (chg->smb_version) {
776 case PMI8998_SUBTYPE:
777 rc = smblib_read(chg, QC_PULSE_COUNT_STATUS_REG, val);
778 if (rc) {
779 pr_err("failed to read QC_PULSE_COUNT_STATUS_REG rc=%d\n",
780 rc);
781 return rc;
782 }
783 *count = val[0] & QC_PULSE_COUNT_MASK;
784 break;
785 case PM660_SUBTYPE:
786 rc = smblib_multibyte_read(chg,
787 QC_PULSE_COUNT_STATUS_1_REG, val, 2);
788 if (rc) {
789 pr_err("failed to read QC_PULSE_COUNT_STATUS_1_REG rc=%d\n",
790 rc);
791 return rc;
792 }
793 *count = (val[1] << 8) | val[0];
794 break;
795 default:
796 smblib_dbg(chg, PR_PARALLEL, "unknown SMB chip %d\n",
797 chg->smb_version);
798 return -EINVAL;
799 }
800
801 return 0;
802}
803
Nicholas Troast34db5032016-03-28 12:26:44 -0700804/*********************
805 * VOTABLE CALLBACKS *
806 *********************/
807
Abhijeet Dharmapurikar8e9e7572016-06-06 16:13:14 -0700808static int smblib_dc_suspend_vote_callback(struct votable *votable, void *data,
Abhijeet Dharmapurikarebb5e5c2016-05-17 20:09:16 -0700809 int suspend, const char *client)
Nicholas Troast34db5032016-03-28 12:26:44 -0700810{
Abhijeet Dharmapurikar8e9e7572016-06-06 16:13:14 -0700811 struct smb_charger *chg = data;
Nicholas Troast34db5032016-03-28 12:26:44 -0700812
Nicholas Troastabedaf72016-09-16 11:07:45 -0700813 /* resume input if suspend is invalid */
Abhijeet Dharmapurikarc0ff65a2016-06-06 16:45:34 -0700814 if (suspend < 0)
Nicholas Troastabedaf72016-09-16 11:07:45 -0700815 suspend = 0;
Abhijeet Dharmapurikarc0ff65a2016-06-06 16:45:34 -0700816
Nicholas Troastabedaf72016-09-16 11:07:45 -0700817 return smblib_set_dc_suspend(chg, (bool)suspend);
Nicholas Troast34db5032016-03-28 12:26:44 -0700818}
819
Nicholas Troastbb76a142016-09-23 11:23:23 -0700820#define USBIN_25MA 25000
821#define USBIN_100MA 100000
822#define USBIN_150MA 150000
823#define USBIN_500MA 500000
824#define USBIN_900MA 900000
Abhijeet Dharmapurikar5e0bfbe2017-02-12 19:16:15 -0800825
826
827static int set_sdp_current(struct smb_charger *chg, int icl_ua)
Nicholas Troast34db5032016-03-28 12:26:44 -0700828{
Abhijeet Dharmapurikar5e0bfbe2017-02-12 19:16:15 -0800829 int rc;
830 u8 icl_options;
Abhijeet Dharmapurikarc0ff65a2016-06-06 16:45:34 -0700831
Nicholas Troastbb76a142016-09-23 11:23:23 -0700832 /* power source is SDP */
833 switch (icl_ua) {
834 case USBIN_100MA:
835 /* USB 2.0 100mA */
836 icl_options = 0;
837 break;
838 case USBIN_150MA:
839 /* USB 3.0 150mA */
840 icl_options = CFG_USB3P0_SEL_BIT;
841 break;
842 case USBIN_500MA:
843 /* USB 2.0 500mA */
844 icl_options = USB51_MODE_BIT;
845 break;
846 case USBIN_900MA:
847 /* USB 3.0 900mA */
848 icl_options = CFG_USB3P0_SEL_BIT | USB51_MODE_BIT;
849 break;
850 default:
Abhijeet Dharmapurikar31b98f32016-10-14 12:25:23 -0700851 smblib_err(chg, "ICL %duA isn't supported for SDP\n", icl_ua);
Abhijeet Dharmapurikar5e0bfbe2017-02-12 19:16:15 -0800852 return -EINVAL;
Nicholas Troastbb76a142016-09-23 11:23:23 -0700853 }
Nicholas Troast34db5032016-03-28 12:26:44 -0700854
Nicholas Troastbb76a142016-09-23 11:23:23 -0700855 rc = smblib_masked_write(chg, USBIN_ICL_OPTIONS_REG,
Abhijeet Dharmapurikar5e0bfbe2017-02-12 19:16:15 -0800856 CFG_USB3P0_SEL_BIT | USB51_MODE_BIT, icl_options);
Nicholas Troast34db5032016-03-28 12:26:44 -0700857 if (rc < 0) {
Abhijeet Dharmapurikar74021fc2017-02-06 18:39:19 -0800858 smblib_err(chg, "Couldn't set ICL options rc=%d\n", rc);
Nicholas Troast34db5032016-03-28 12:26:44 -0700859 return rc;
860 }
861
Abhijeet Dharmapurikar5e0bfbe2017-02-12 19:16:15 -0800862 return rc;
863}
864
865static int smblib_usb_icl_vote_callback(struct votable *votable, void *data,
866 int icl_ua, const char *client)
867{
868 struct smb_charger *chg = data;
869 int rc = 0;
870 bool override;
871 union power_supply_propval pval;
872
873 /* suspend and return if 25mA or less is requested */
874 if (client && (icl_ua < USBIN_25MA))
875 return smblib_set_usb_suspend(chg, true);
876
877 disable_irq_nosync(chg->irq_info[USBIN_ICL_CHANGE_IRQ].irq);
878 if (!client)
879 goto override_suspend_config;
880
881 rc = smblib_get_prop_typec_mode(chg, &pval);
Nicholas Troast34db5032016-03-28 12:26:44 -0700882 if (rc < 0) {
Abhijeet Dharmapurikar5e0bfbe2017-02-12 19:16:15 -0800883 smblib_err(chg, "Couldn't get typeC mode rc = %d\n", rc);
884 goto enable_icl_changed_interrupt;
Nicholas Troast34db5032016-03-28 12:26:44 -0700885 }
886
Abhijeet Dharmapurikar5e0bfbe2017-02-12 19:16:15 -0800887 /* configure current */
888 if (pval.intval == POWER_SUPPLY_TYPEC_SOURCE_DEFAULT
889 && (chg->usb_psy_desc.type == POWER_SUPPLY_TYPE_USB)) {
890 rc = set_sdp_current(chg, icl_ua);
891 if (rc < 0) {
892 smblib_err(chg, "Couldn't set SDP ICL rc=%d\n", rc);
893 goto enable_icl_changed_interrupt;
894 }
895 } else {
896 rc = smblib_set_charge_param(chg, &chg->param.usb_icl,
897 icl_ua - chg->icl_reduction_ua);
898 if (rc < 0) {
899 smblib_err(chg, "Couldn't set HC ICL rc=%d\n", rc);
900 goto enable_icl_changed_interrupt;
901 }
902 }
903
904override_suspend_config:
905 /* determine if override needs to be enforced */
906 override = true;
907 if (client == NULL) {
908 /* remove override if no voters - hw defaults is desired */
909 override = false;
910 } else if (pval.intval == POWER_SUPPLY_TYPEC_SOURCE_DEFAULT) {
911 if (chg->usb_psy_desc.type == POWER_SUPPLY_TYPE_USB)
912 /* For std cable with type = SDP never override */
913 override = false;
914 else if (chg->usb_psy_desc.type == POWER_SUPPLY_TYPE_USB_CDP
915 && icl_ua - chg->icl_reduction_ua == 1500000)
916 /*
917 * For std cable with type = CDP override only if
918 * current is not 1500mA
919 */
920 override = false;
921 }
922
923 /* enforce override */
924 rc = smblib_masked_write(chg, USBIN_ICL_OPTIONS_REG,
925 USBIN_MODE_CHG_BIT, override ? USBIN_MODE_CHG_BIT : 0);
926
Abhijeet Dharmapurikar74021fc2017-02-06 18:39:19 -0800927 rc = smblib_icl_override(chg, override);
928 if (rc < 0) {
929 smblib_err(chg, "Couldn't set ICL override rc=%d\n", rc);
Abhijeet Dharmapurikar5e0bfbe2017-02-12 19:16:15 -0800930 goto enable_icl_changed_interrupt;
Abhijeet Dharmapurikar74021fc2017-02-06 18:39:19 -0800931 }
932
Abhijeet Dharmapurikar5e0bfbe2017-02-12 19:16:15 -0800933 /* unsuspend after configuring current and override */
934 rc = smblib_set_usb_suspend(chg, false);
935 if (rc < 0) {
936 smblib_err(chg, "Couldn't resume input rc=%d\n", rc);
937 goto enable_icl_changed_interrupt;
938 }
939
940enable_icl_changed_interrupt:
941 enable_irq(chg->irq_info[USBIN_ICL_CHANGE_IRQ].irq);
Nicholas Troast34db5032016-03-28 12:26:44 -0700942 return rc;
943}
944
Abhijeet Dharmapurikar8e9e7572016-06-06 16:13:14 -0700945static int smblib_dc_icl_vote_callback(struct votable *votable, void *data,
Abhijeet Dharmapurikarebb5e5c2016-05-17 20:09:16 -0700946 int icl_ua, const char *client)
Nicholas Troast34db5032016-03-28 12:26:44 -0700947{
Abhijeet Dharmapurikar8e9e7572016-06-06 16:13:14 -0700948 struct smb_charger *chg = data;
Nicholas Troast34db5032016-03-28 12:26:44 -0700949 int rc = 0;
Abhijeet Dharmapurikarc0ff65a2016-06-06 16:45:34 -0700950 bool suspend;
951
952 if (icl_ua < 0) {
953 smblib_dbg(chg, PR_MISC, "No Voter hence suspending\n");
954 icl_ua = 0;
955 }
956
957 suspend = (icl_ua < USBIN_25MA);
958 if (suspend)
959 goto suspend;
Nicholas Troast34db5032016-03-28 12:26:44 -0700960
961 rc = smblib_set_charge_param(chg, &chg->param.dc_icl, icl_ua);
Abhijeet Dharmapurikarc0ff65a2016-06-06 16:45:34 -0700962 if (rc < 0) {
Abhijeet Dharmapurikar31b98f32016-10-14 12:25:23 -0700963 smblib_err(chg, "Couldn't set DC input current limit rc=%d\n",
Abhijeet Dharmapurikarc0ff65a2016-06-06 16:45:34 -0700964 rc);
965 return rc;
966 }
967
968suspend:
969 rc = vote(chg->dc_suspend_votable, USER_VOTER, suspend, 0);
970 if (rc < 0) {
Abhijeet Dharmapurikar31b98f32016-10-14 12:25:23 -0700971 smblib_err(chg, "Couldn't vote to %s DC rc=%d\n",
Abhijeet Dharmapurikarc0ff65a2016-06-06 16:45:34 -0700972 suspend ? "suspend" : "resume", rc);
973 return rc;
974 }
Nicholas Troast34db5032016-03-28 12:26:44 -0700975 return rc;
976}
977
Abhijeet Dharmapurikar4b13c6e2016-10-05 15:15:10 -0700978static int smblib_pd_disallowed_votable_indirect_callback(
979 struct votable *votable, void *data, int disallowed, const char *client)
980{
981 struct smb_charger *chg = data;
982 int rc;
983
984 rc = vote(chg->pd_allowed_votable, PD_DISALLOWED_INDIRECT_VOTER,
985 !disallowed, 0);
986
987 return rc;
988}
989
Harry Yang223c6282016-06-14 15:48:36 -0700990static int smblib_awake_vote_callback(struct votable *votable, void *data,
991 int awake, const char *client)
992{
993 struct smb_charger *chg = data;
994
995 if (awake)
996 pm_stay_awake(chg->dev);
997 else
998 pm_relax(chg->dev);
999
1000 return 0;
1001}
1002
Abhijeet Dharmapurikaree54de02016-07-08 14:51:47 -07001003static int smblib_chg_disable_vote_callback(struct votable *votable, void *data,
1004 int chg_disable, const char *client)
1005{
1006 struct smb_charger *chg = data;
1007 int rc;
1008
1009 rc = smblib_masked_write(chg, CHARGING_ENABLE_CMD_REG,
1010 CHARGING_ENABLE_CMD_BIT,
1011 chg_disable ? 0 : CHARGING_ENABLE_CMD_BIT);
1012 if (rc < 0) {
Abhijeet Dharmapurikar31b98f32016-10-14 12:25:23 -07001013 smblib_err(chg, "Couldn't %s charging rc=%d\n",
Abhijeet Dharmapurikaree54de02016-07-08 14:51:47 -07001014 chg_disable ? "disable" : "enable", rc);
1015 return rc;
1016 }
1017
1018 return 0;
1019}
Harry Yangaba1f5f2016-09-28 10:47:29 -07001020
1021static int smblib_pl_enable_indirect_vote_callback(struct votable *votable,
1022 void *data, int chg_enable, const char *client)
1023{
1024 struct smb_charger *chg = data;
1025
1026 vote(chg->pl_disable_votable, PL_INDIRECT_VOTER, !chg_enable, 0);
1027
1028 return 0;
1029}
1030
Ashay Jaiswal4aa2c0c2016-12-07 19:39:38 +05301031static int smblib_hvdcp_enable_vote_callback(struct votable *votable,
Abhijeet Dharmapurikarf0b0a042016-10-10 16:43:43 -07001032 void *data,
Ashay Jaiswal4aa2c0c2016-12-07 19:39:38 +05301033 int hvdcp_enable, const char *client)
Abhijeet Dharmapurikarf0b0a042016-10-10 16:43:43 -07001034{
1035 struct smb_charger *chg = data;
1036 int rc;
Ashay Jaiswal6d308da2017-02-18 09:59:23 +05301037 u8 val = HVDCP_AUTH_ALG_EN_CFG_BIT | HVDCP_EN_BIT;
1038
1039 /* vote to enable/disable HW autonomous INOV */
1040 vote(chg->hvdcp_hw_inov_dis_votable, client, !hvdcp_enable, 0);
Abhijeet Dharmapurikarf0b0a042016-10-10 16:43:43 -07001041
1042 /*
1043 * Disable the autonomous bit and auth bit for disabling hvdcp.
1044 * This ensures only qc 2.0 detection runs but no vbus
1045 * negotiation happens.
1046 */
Ashay Jaiswal4aa2c0c2016-12-07 19:39:38 +05301047 if (!hvdcp_enable)
Abhijeet Dharmapurikarf0b0a042016-10-10 16:43:43 -07001048 val = HVDCP_EN_BIT;
1049
1050 rc = smblib_masked_write(chg, USBIN_OPTIONS_1_CFG_REG,
Ashay Jaiswal6d308da2017-02-18 09:59:23 +05301051 HVDCP_EN_BIT | HVDCP_AUTH_ALG_EN_CFG_BIT,
Abhijeet Dharmapurikarf0b0a042016-10-10 16:43:43 -07001052 val);
1053 if (rc < 0) {
Abhijeet Dharmapurikar31b98f32016-10-14 12:25:23 -07001054 smblib_err(chg, "Couldn't %s hvdcp rc=%d\n",
Ashay Jaiswal4aa2c0c2016-12-07 19:39:38 +05301055 hvdcp_enable ? "enable" : "disable", rc);
Abhijeet Dharmapurikarf0b0a042016-10-10 16:43:43 -07001056 return rc;
1057 }
1058
1059 return 0;
1060}
1061
Ashay Jaiswal4aa2c0c2016-12-07 19:39:38 +05301062static int smblib_hvdcp_disable_indirect_vote_callback(struct votable *votable,
1063 void *data, int hvdcp_disable, const char *client)
1064{
1065 struct smb_charger *chg = data;
1066
1067 vote(chg->hvdcp_enable_votable, HVDCP_INDIRECT_VOTER,
1068 !hvdcp_disable, 0);
1069
1070 return 0;
1071}
1072
Abhijeet Dharmapurikarf8a7a4a2016-10-07 18:46:45 -07001073static int smblib_apsd_disable_vote_callback(struct votable *votable,
1074 void *data,
1075 int apsd_disable, const char *client)
1076{
1077 struct smb_charger *chg = data;
1078 int rc;
1079
Nicholas Troastec4703c2017-01-30 14:52:33 -08001080 if (apsd_disable) {
Nicholas Troastec4703c2017-01-30 14:52:33 -08001081 rc = smblib_masked_write(chg, USBIN_OPTIONS_1_CFG_REG,
1082 AUTO_SRC_DETECT_BIT,
1083 0);
1084 if (rc < 0) {
1085 smblib_err(chg, "Couldn't disable APSD rc=%d\n", rc);
1086 return rc;
1087 }
1088 } else {
1089 rc = smblib_masked_write(chg, USBIN_OPTIONS_1_CFG_REG,
1090 AUTO_SRC_DETECT_BIT,
1091 AUTO_SRC_DETECT_BIT);
1092 if (rc < 0) {
1093 smblib_err(chg, "Couldn't enable APSD rc=%d\n", rc);
1094 return rc;
1095 }
Abhijeet Dharmapurikarf8a7a4a2016-10-07 18:46:45 -07001096 }
1097
1098 return 0;
1099}
Nicholas Troast8995a702016-12-05 10:22:22 -08001100
Ashay Jaiswal6d308da2017-02-18 09:59:23 +05301101static int smblib_hvdcp_hw_inov_dis_vote_callback(struct votable *votable,
1102 void *data, int disable, const char *client)
1103{
1104 struct smb_charger *chg = data;
1105 int rc;
1106
1107 if (disable) {
1108 /*
1109 * the pulse count register get zeroed when autonomous mode is
1110 * disabled. Track that in variables before disabling
1111 */
1112 rc = smblib_get_pulse_cnt(chg, &chg->pulse_cnt);
1113 if (rc < 0) {
1114 pr_err("failed to read QC_PULSE_COUNT_STATUS_REG rc=%d\n",
1115 rc);
1116 return rc;
1117 }
1118 }
1119
1120 rc = smblib_masked_write(chg, USBIN_OPTIONS_1_CFG_REG,
1121 HVDCP_AUTONOMOUS_MODE_EN_CFG_BIT,
1122 disable ? 0 : HVDCP_AUTONOMOUS_MODE_EN_CFG_BIT);
1123 if (rc < 0) {
1124 smblib_err(chg, "Couldn't %s hvdcp rc=%d\n",
1125 disable ? "disable" : "enable", rc);
1126 return rc;
1127 }
1128
1129 return rc;
1130}
1131
Harry Yang4bf7d962017-03-13 16:51:43 -07001132static int smblib_usb_irq_enable_vote_callback(struct votable *votable,
1133 void *data, int enable, const char *client)
1134{
1135 struct smb_charger *chg = data;
1136
1137 if (!chg->irq_info[INPUT_CURRENT_LIMIT_IRQ].irq ||
1138 !chg->irq_info[HIGH_DUTY_CYCLE_IRQ].irq)
1139 return 0;
1140
1141 if (enable) {
1142 enable_irq(chg->irq_info[INPUT_CURRENT_LIMIT_IRQ].irq);
1143 enable_irq(chg->irq_info[HIGH_DUTY_CYCLE_IRQ].irq);
1144 } else {
1145 disable_irq(chg->irq_info[INPUT_CURRENT_LIMIT_IRQ].irq);
1146 disable_irq(chg->irq_info[HIGH_DUTY_CYCLE_IRQ].irq);
1147 }
1148
1149 return 0;
1150}
1151
Nicholas Troast8995a702016-12-05 10:22:22 -08001152/*******************
1153 * VCONN REGULATOR *
1154 * *****************/
1155
Nicholas Troastb11015f2017-01-17 17:56:45 -08001156#define MAX_OTG_SS_TRIES 2
Nicholas Troast8995a702016-12-05 10:22:22 -08001157static int _smblib_vconn_regulator_enable(struct regulator_dev *rdev)
1158{
1159 struct smb_charger *chg = rdev_get_drvdata(rdev);
1160 u8 otg_stat, stat4;
Nicholas Troastb11015f2017-01-17 17:56:45 -08001161 int rc = 0, i;
Nicholas Troast8995a702016-12-05 10:22:22 -08001162
1163 if (!chg->external_vconn) {
Nicholas Troastb11015f2017-01-17 17:56:45 -08001164 /*
1165 * Hardware based OTG soft start should complete within 1ms, so
1166 * wait for 2ms in the worst case.
1167 */
1168 for (i = 0; i < MAX_OTG_SS_TRIES; ++i) {
1169 usleep_range(1000, 1100);
1170 rc = smblib_read(chg, OTG_STATUS_REG, &otg_stat);
1171 if (rc < 0) {
1172 smblib_err(chg, "Couldn't read OTG status rc=%d\n",
1173 rc);
1174 return rc;
1175 }
1176
1177 if (otg_stat & BOOST_SOFTSTART_DONE_BIT)
1178 break;
Nicholas Troast8995a702016-12-05 10:22:22 -08001179 }
1180
Nicholas Troastb11015f2017-01-17 17:56:45 -08001181 if (!(otg_stat & BOOST_SOFTSTART_DONE_BIT)) {
1182 smblib_err(chg, "Couldn't enable VCONN; OTG soft start failed\n");
Nicholas Troast8995a702016-12-05 10:22:22 -08001183 return -EAGAIN;
1184 }
1185 }
1186
1187 /*
1188 * VCONN_EN_ORIENTATION is overloaded with overriding the CC pin used
1189 * for Vconn, and it should be set with reverse polarity of CC_OUT.
1190 */
1191 rc = smblib_read(chg, TYPE_C_STATUS_4_REG, &stat4);
1192 if (rc < 0) {
1193 smblib_err(chg, "Couldn't read TYPE_C_STATUS_4 rc=%d\n", rc);
1194 return rc;
1195 }
1196
Nicholas Troastb11015f2017-01-17 17:56:45 -08001197 smblib_dbg(chg, PR_OTG, "enabling VCONN\n");
Nicholas Troast8995a702016-12-05 10:22:22 -08001198 stat4 = stat4 & CC_ORIENTATION_BIT ? 0 : VCONN_EN_ORIENTATION_BIT;
1199 rc = smblib_masked_write(chg, TYPE_C_INTRPT_ENB_SOFTWARE_CTRL_REG,
1200 VCONN_EN_VALUE_BIT | VCONN_EN_ORIENTATION_BIT,
1201 VCONN_EN_VALUE_BIT | stat4);
1202 if (rc < 0) {
1203 smblib_err(chg, "Couldn't enable vconn setting rc=%d\n", rc);
1204 return rc;
1205 }
1206
1207 return rc;
1208}
1209
1210int smblib_vconn_regulator_enable(struct regulator_dev *rdev)
1211{
1212 struct smb_charger *chg = rdev_get_drvdata(rdev);
1213 int rc = 0;
1214
Nicholas Troastb11015f2017-01-17 17:56:45 -08001215 mutex_lock(&chg->otg_oc_lock);
Nicholas Troast8995a702016-12-05 10:22:22 -08001216 if (chg->vconn_en)
1217 goto unlock;
1218
1219 rc = _smblib_vconn_regulator_enable(rdev);
1220 if (rc >= 0)
1221 chg->vconn_en = true;
1222
1223unlock:
Nicholas Troastb11015f2017-01-17 17:56:45 -08001224 mutex_unlock(&chg->otg_oc_lock);
Nicholas Troast8995a702016-12-05 10:22:22 -08001225 return rc;
1226}
1227
1228static int _smblib_vconn_regulator_disable(struct regulator_dev *rdev)
1229{
1230 struct smb_charger *chg = rdev_get_drvdata(rdev);
1231 int rc = 0;
1232
Nicholas Troastb11015f2017-01-17 17:56:45 -08001233 smblib_dbg(chg, PR_OTG, "disabling VCONN\n");
Nicholas Troast8995a702016-12-05 10:22:22 -08001234 rc = smblib_masked_write(chg, TYPE_C_INTRPT_ENB_SOFTWARE_CTRL_REG,
1235 VCONN_EN_VALUE_BIT, 0);
1236 if (rc < 0)
1237 smblib_err(chg, "Couldn't disable vconn regulator rc=%d\n", rc);
1238
1239 return rc;
1240}
1241
1242int smblib_vconn_regulator_disable(struct regulator_dev *rdev)
1243{
1244 struct smb_charger *chg = rdev_get_drvdata(rdev);
1245 int rc = 0;
1246
Nicholas Troastb11015f2017-01-17 17:56:45 -08001247 mutex_lock(&chg->otg_oc_lock);
Nicholas Troast8995a702016-12-05 10:22:22 -08001248 if (!chg->vconn_en)
1249 goto unlock;
1250
1251 rc = _smblib_vconn_regulator_disable(rdev);
1252 if (rc >= 0)
1253 chg->vconn_en = false;
1254
1255unlock:
Nicholas Troastb11015f2017-01-17 17:56:45 -08001256 mutex_unlock(&chg->otg_oc_lock);
Nicholas Troast8995a702016-12-05 10:22:22 -08001257 return rc;
1258}
1259
1260int smblib_vconn_regulator_is_enabled(struct regulator_dev *rdev)
1261{
1262 struct smb_charger *chg = rdev_get_drvdata(rdev);
1263 int ret;
1264
Nicholas Troastb11015f2017-01-17 17:56:45 -08001265 mutex_lock(&chg->otg_oc_lock);
Nicholas Troast8995a702016-12-05 10:22:22 -08001266 ret = chg->vconn_en;
Nicholas Troastb11015f2017-01-17 17:56:45 -08001267 mutex_unlock(&chg->otg_oc_lock);
Nicholas Troast8995a702016-12-05 10:22:22 -08001268 return ret;
1269}
1270
Nicholas Troast34db5032016-03-28 12:26:44 -07001271/*****************
1272 * OTG REGULATOR *
1273 *****************/
Ashay Jaiswal7c241382017-03-06 15:26:38 +05301274#define MAX_RETRY 15
1275#define MIN_DELAY_US 2000
1276#define MAX_DELAY_US 9000
Nicholas Troast8995a702016-12-05 10:22:22 -08001277static int _smblib_vbus_regulator_enable(struct regulator_dev *rdev)
Nicholas Troast34db5032016-03-28 12:26:44 -07001278{
1279 struct smb_charger *chg = rdev_get_drvdata(rdev);
Ashay Jaiswal7c241382017-03-06 15:26:38 +05301280 int rc, retry_count = 0, min_delay = MIN_DELAY_US;
1281 u8 stat;
Nicholas Troast34db5032016-03-28 12:26:44 -07001282
Nicholas Troastb11015f2017-01-17 17:56:45 -08001283 smblib_dbg(chg, PR_OTG, "halt 1 in 8 mode\n");
Harry Yang360bd532016-09-26 11:03:22 -07001284 rc = smblib_masked_write(chg, OTG_ENG_OTG_CFG_REG,
1285 ENG_BUCKBOOST_HALT1_8_MODE_BIT,
1286 ENG_BUCKBOOST_HALT1_8_MODE_BIT);
1287 if (rc < 0) {
Abhijeet Dharmapurikar31b98f32016-10-14 12:25:23 -07001288 smblib_err(chg, "Couldn't set OTG_ENG_OTG_CFG_REG rc=%d\n",
Harry Yang360bd532016-09-26 11:03:22 -07001289 rc);
1290 return rc;
1291 }
1292
Nicholas Troastb11015f2017-01-17 17:56:45 -08001293 smblib_dbg(chg, PR_OTG, "enabling OTG\n");
Harry Yang360bd532016-09-26 11:03:22 -07001294 rc = smblib_write(chg, CMD_OTG_REG, OTG_EN_BIT);
1295 if (rc < 0) {
Abhijeet Dharmapurikar31b98f32016-10-14 12:25:23 -07001296 smblib_err(chg, "Couldn't enable OTG regulator rc=%d\n", rc);
Harry Yang360bd532016-09-26 11:03:22 -07001297 return rc;
1298 }
1299
Ashay Jaiswal7c241382017-03-06 15:26:38 +05301300 if (chg->wa_flags & OTG_WA) {
1301 /* check for softstart */
1302 do {
1303 usleep_range(min_delay, min_delay + 100);
1304 rc = smblib_read(chg, OTG_STATUS_REG, &stat);
1305 if (rc < 0) {
1306 smblib_err(chg,
1307 "Couldn't read OTG status rc=%d\n",
1308 rc);
1309 goto out;
1310 }
1311
1312 if (stat & BOOST_SOFTSTART_DONE_BIT) {
1313 rc = smblib_set_charge_param(chg,
1314 &chg->param.otg_cl, chg->otg_cl_ua);
1315 if (rc < 0)
1316 smblib_err(chg,
1317 "Couldn't set otg limit\n");
1318 break;
1319 }
1320
1321 /* increase the delay for following iterations */
1322 if (retry_count > 5)
1323 min_delay = MAX_DELAY_US;
1324 } while (retry_count++ < MAX_RETRY);
1325
1326 if (retry_count >= MAX_RETRY) {
1327 smblib_dbg(chg, PR_OTG, "Boost Softstart not done\n");
1328 goto out;
1329 }
1330 }
1331
1332 return 0;
1333out:
1334 /* disable OTG if softstart failed */
1335 smblib_write(chg, CMD_OTG_REG, 0);
Nicholas Troast34db5032016-03-28 12:26:44 -07001336 return rc;
1337}
1338
Nicholas Troast8995a702016-12-05 10:22:22 -08001339int smblib_vbus_regulator_enable(struct regulator_dev *rdev)
Nicholas Troast34db5032016-03-28 12:26:44 -07001340{
1341 struct smb_charger *chg = rdev_get_drvdata(rdev);
1342 int rc = 0;
1343
Nicholas Troastb11015f2017-01-17 17:56:45 -08001344 mutex_lock(&chg->otg_oc_lock);
Nicholas Troast8995a702016-12-05 10:22:22 -08001345 if (chg->otg_en)
1346 goto unlock;
1347
1348 rc = _smblib_vbus_regulator_enable(rdev);
1349 if (rc >= 0)
1350 chg->otg_en = true;
1351
1352unlock:
Nicholas Troastb11015f2017-01-17 17:56:45 -08001353 mutex_unlock(&chg->otg_oc_lock);
Nicholas Troast8995a702016-12-05 10:22:22 -08001354 return rc;
1355}
1356
1357static int _smblib_vbus_regulator_disable(struct regulator_dev *rdev)
1358{
1359 struct smb_charger *chg = rdev_get_drvdata(rdev);
1360 int rc;
Nicholas Troast8995a702016-12-05 10:22:22 -08001361
Nicholas Troastb11015f2017-01-17 17:56:45 -08001362 if (!chg->external_vconn && chg->vconn_en) {
1363 smblib_dbg(chg, PR_OTG, "Killing VCONN before disabling OTG\n");
1364 rc = _smblib_vconn_regulator_disable(rdev);
Nicholas Troast07a69002017-01-20 13:52:10 -08001365 if (rc < 0)
Nicholas Troastb11015f2017-01-17 17:56:45 -08001366 smblib_err(chg, "Couldn't disable VCONN rc=%d\n", rc);
Nicholas Troast8995a702016-12-05 10:22:22 -08001367 }
1368
Ashay Jaiswal7c241382017-03-06 15:26:38 +05301369 if (chg->wa_flags & OTG_WA) {
1370 /* set OTG current limit to minimum value */
1371 rc = smblib_set_charge_param(chg, &chg->param.otg_cl,
1372 chg->param.otg_cl.min_u);
1373 if (rc < 0) {
1374 smblib_err(chg,
1375 "Couldn't set otg current limit rc=%d\n", rc);
1376 return rc;
1377 }
1378 }
1379
Nicholas Troastb11015f2017-01-17 17:56:45 -08001380 smblib_dbg(chg, PR_OTG, "disabling OTG\n");
Harry Yang360bd532016-09-26 11:03:22 -07001381 rc = smblib_write(chg, CMD_OTG_REG, 0);
1382 if (rc < 0) {
Abhijeet Dharmapurikar31b98f32016-10-14 12:25:23 -07001383 smblib_err(chg, "Couldn't disable OTG regulator rc=%d\n", rc);
Harry Yang360bd532016-09-26 11:03:22 -07001384 return rc;
1385 }
1386
Nicholas Troastb11015f2017-01-17 17:56:45 -08001387 smblib_dbg(chg, PR_OTG, "start 1 in 8 mode\n");
Harry Yang360bd532016-09-26 11:03:22 -07001388 rc = smblib_masked_write(chg, OTG_ENG_OTG_CFG_REG,
1389 ENG_BUCKBOOST_HALT1_8_MODE_BIT, 0);
1390 if (rc < 0) {
Nicholas Troast8995a702016-12-05 10:22:22 -08001391 smblib_err(chg, "Couldn't set OTG_ENG_OTG_CFG_REG rc=%d\n", rc);
Harry Yang360bd532016-09-26 11:03:22 -07001392 return rc;
1393 }
1394
Nicholas Troast8995a702016-12-05 10:22:22 -08001395 return 0;
1396}
Nicholas Troast34db5032016-03-28 12:26:44 -07001397
Nicholas Troast8995a702016-12-05 10:22:22 -08001398int smblib_vbus_regulator_disable(struct regulator_dev *rdev)
1399{
1400 struct smb_charger *chg = rdev_get_drvdata(rdev);
1401 int rc = 0;
1402
Nicholas Troastb11015f2017-01-17 17:56:45 -08001403 mutex_lock(&chg->otg_oc_lock);
Nicholas Troast8995a702016-12-05 10:22:22 -08001404 if (!chg->otg_en)
1405 goto unlock;
1406
1407 rc = _smblib_vbus_regulator_disable(rdev);
1408 if (rc >= 0)
1409 chg->otg_en = false;
1410
1411unlock:
Nicholas Troastb11015f2017-01-17 17:56:45 -08001412 mutex_unlock(&chg->otg_oc_lock);
Nicholas Troast34db5032016-03-28 12:26:44 -07001413 return rc;
1414}
1415
1416int smblib_vbus_regulator_is_enabled(struct regulator_dev *rdev)
1417{
1418 struct smb_charger *chg = rdev_get_drvdata(rdev);
Nicholas Troast8995a702016-12-05 10:22:22 -08001419 int ret;
Nicholas Troast34db5032016-03-28 12:26:44 -07001420
Nicholas Troastb11015f2017-01-17 17:56:45 -08001421 mutex_lock(&chg->otg_oc_lock);
Nicholas Troast8995a702016-12-05 10:22:22 -08001422 ret = chg->otg_en;
Nicholas Troastb11015f2017-01-17 17:56:45 -08001423 mutex_unlock(&chg->otg_oc_lock);
Nicholas Troast8995a702016-12-05 10:22:22 -08001424 return ret;
Nicholas Troast34db5032016-03-28 12:26:44 -07001425}
1426
1427/********************
1428 * BATT PSY GETTERS *
1429 ********************/
1430
1431int smblib_get_prop_input_suspend(struct smb_charger *chg,
1432 union power_supply_propval *val)
1433{
Abhijeet Dharmapurikar5e0bfbe2017-02-12 19:16:15 -08001434 val->intval
1435 = (get_client_vote(chg->usb_icl_votable, USER_VOTER) == 0)
1436 && get_client_vote(chg->dc_suspend_votable, USER_VOTER);
Nicholas Troast34db5032016-03-28 12:26:44 -07001437 return 0;
1438}
1439
1440int smblib_get_prop_batt_present(struct smb_charger *chg,
1441 union power_supply_propval *val)
1442{
1443 int rc;
1444 u8 stat;
1445
1446 rc = smblib_read(chg, BATIF_BASE + INT_RT_STS_OFFSET, &stat);
1447 if (rc < 0) {
Abhijeet Dharmapurikar31b98f32016-10-14 12:25:23 -07001448 smblib_err(chg, "Couldn't read BATIF_INT_RT_STS rc=%d\n", rc);
Nicholas Troast34db5032016-03-28 12:26:44 -07001449 return rc;
1450 }
1451
1452 val->intval = !(stat & (BAT_THERM_OR_ID_MISSING_RT_STS_BIT
1453 | BAT_TERMINAL_MISSING_RT_STS_BIT));
1454
1455 return rc;
1456}
1457
1458int smblib_get_prop_batt_capacity(struct smb_charger *chg,
1459 union power_supply_propval *val)
1460{
Harry Yang5e1a5222016-07-26 15:16:04 -07001461 int rc = -EINVAL;
1462
Abhijeet Dharmapurikar9e7e48c2016-08-23 12:55:49 -07001463 if (chg->fake_capacity >= 0) {
1464 val->intval = chg->fake_capacity;
1465 return 0;
1466 }
1467
Harry Yang5e1a5222016-07-26 15:16:04 -07001468 if (chg->bms_psy)
1469 rc = power_supply_get_property(chg->bms_psy,
1470 POWER_SUPPLY_PROP_CAPACITY, val);
1471 return rc;
Nicholas Troast34db5032016-03-28 12:26:44 -07001472}
1473
1474int smblib_get_prop_batt_status(struct smb_charger *chg,
1475 union power_supply_propval *val)
1476{
Abhijeet Dharmapurikarec43bb42017-01-17 20:00:08 -08001477 union power_supply_propval pval = {0, };
1478 bool usb_online, dc_online;
Nicholas Troast8cb77552016-09-23 11:50:18 -07001479 u8 stat;
1480 int rc;
Nicholas Troast34db5032016-03-28 12:26:44 -07001481
Abhijeet Dharmapurikarec43bb42017-01-17 20:00:08 -08001482 rc = smblib_get_prop_usb_online(chg, &pval);
1483 if (rc < 0) {
1484 smblib_err(chg, "Couldn't get usb online property rc=%d\n",
1485 rc);
1486 return rc;
1487 }
1488 usb_online = (bool)pval.intval;
1489
1490 rc = smblib_get_prop_dc_online(chg, &pval);
1491 if (rc < 0) {
1492 smblib_err(chg, "Couldn't get dc online property rc=%d\n",
1493 rc);
1494 return rc;
1495 }
1496 dc_online = (bool)pval.intval;
1497
Nicholas Troast34db5032016-03-28 12:26:44 -07001498 rc = smblib_read(chg, BATTERY_CHARGER_STATUS_1_REG, &stat);
1499 if (rc < 0) {
Abhijeet Dharmapurikar31b98f32016-10-14 12:25:23 -07001500 smblib_err(chg, "Couldn't read BATTERY_CHARGER_STATUS_1 rc=%d\n",
Nicholas Troast34db5032016-03-28 12:26:44 -07001501 rc);
1502 return rc;
1503 }
Nicholas Troast34db5032016-03-28 12:26:44 -07001504 stat = stat & BATTERY_CHARGER_STATUS_MASK;
Abhijeet Dharmapurikarec43bb42017-01-17 20:00:08 -08001505
1506 if (!usb_online && !dc_online) {
1507 switch (stat) {
1508 case TERMINATE_CHARGE:
1509 case INHIBIT_CHARGE:
1510 val->intval = POWER_SUPPLY_STATUS_FULL;
1511 break;
1512 default:
1513 val->intval = POWER_SUPPLY_STATUS_DISCHARGING;
1514 break;
1515 }
1516 return rc;
1517 }
1518
Nicholas Troast8cb77552016-09-23 11:50:18 -07001519 switch (stat) {
1520 case TRICKLE_CHARGE:
1521 case PRE_CHARGE:
1522 case FAST_CHARGE:
1523 case FULLON_CHARGE:
1524 case TAPER_CHARGE:
Nicholas Troast34db5032016-03-28 12:26:44 -07001525 val->intval = POWER_SUPPLY_STATUS_CHARGING;
Nicholas Troast8cb77552016-09-23 11:50:18 -07001526 break;
1527 case TERMINATE_CHARGE:
1528 case INHIBIT_CHARGE:
1529 val->intval = POWER_SUPPLY_STATUS_FULL;
1530 break;
1531 case DISABLE_CHARGE:
1532 val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING;
1533 break;
1534 default:
1535 val->intval = POWER_SUPPLY_STATUS_UNKNOWN;
1536 break;
1537 }
Nicholas Troast34db5032016-03-28 12:26:44 -07001538
Nicholas Troast8cb77552016-09-23 11:50:18 -07001539 return 0;
Nicholas Troast34db5032016-03-28 12:26:44 -07001540}
1541
1542int smblib_get_prop_batt_charge_type(struct smb_charger *chg,
1543 union power_supply_propval *val)
1544{
1545 int rc;
1546 u8 stat;
1547
1548 rc = smblib_read(chg, BATTERY_CHARGER_STATUS_1_REG, &stat);
1549 if (rc < 0) {
Abhijeet Dharmapurikar31b98f32016-10-14 12:25:23 -07001550 smblib_err(chg, "Couldn't read BATTERY_CHARGER_STATUS_1 rc=%d\n",
Nicholas Troast34db5032016-03-28 12:26:44 -07001551 rc);
1552 return rc;
1553 }
Nicholas Troast34db5032016-03-28 12:26:44 -07001554
1555 switch (stat & BATTERY_CHARGER_STATUS_MASK) {
1556 case TRICKLE_CHARGE:
1557 case PRE_CHARGE:
1558 val->intval = POWER_SUPPLY_CHARGE_TYPE_TRICKLE;
1559 break;
1560 case FAST_CHARGE:
1561 case FULLON_CHARGE:
1562 val->intval = POWER_SUPPLY_CHARGE_TYPE_FAST;
1563 break;
1564 case TAPER_CHARGE:
1565 val->intval = POWER_SUPPLY_CHARGE_TYPE_TAPER;
1566 break;
1567 default:
1568 val->intval = POWER_SUPPLY_CHARGE_TYPE_NONE;
1569 }
1570
1571 return rc;
1572}
1573
1574int smblib_get_prop_batt_health(struct smb_charger *chg,
1575 union power_supply_propval *val)
1576{
Subbaraman Narayanamurthya379c4f2016-10-21 17:30:46 -07001577 union power_supply_propval pval;
Nicholas Troast34db5032016-03-28 12:26:44 -07001578 int rc;
1579 u8 stat;
1580
1581 rc = smblib_read(chg, BATTERY_CHARGER_STATUS_2_REG, &stat);
1582 if (rc < 0) {
Abhijeet Dharmapurikar31b98f32016-10-14 12:25:23 -07001583 smblib_err(chg, "Couldn't read BATTERY_CHARGER_STATUS_2 rc=%d\n",
Nicholas Troast34db5032016-03-28 12:26:44 -07001584 rc);
1585 return rc;
1586 }
1587 smblib_dbg(chg, PR_REGISTER, "BATTERY_CHARGER_STATUS_2 = 0x%02x\n",
1588 stat);
1589
1590 if (stat & CHARGER_ERROR_STATUS_BAT_OV_BIT) {
Subbaraman Narayanamurthya379c4f2016-10-21 17:30:46 -07001591 rc = smblib_get_prop_batt_voltage_now(chg, &pval);
1592 if (!rc) {
1593 /*
1594 * If Vbatt is within 40mV above Vfloat, then don't
1595 * treat it as overvoltage.
1596 */
1597 if (pval.intval >=
1598 get_effective_result(chg->fv_votable) + 40000) {
1599 val->intval = POWER_SUPPLY_HEALTH_OVERVOLTAGE;
1600 smblib_err(chg, "battery over-voltage\n");
1601 goto done;
1602 }
1603 }
Nicholas Troast34db5032016-03-28 12:26:44 -07001604 }
1605
Harry Yang668fc5e2016-07-12 16:51:47 -07001606 if (stat & BAT_TEMP_STATUS_TOO_COLD_BIT)
Nicholas Troast34db5032016-03-28 12:26:44 -07001607 val->intval = POWER_SUPPLY_HEALTH_COLD;
Harry Yang668fc5e2016-07-12 16:51:47 -07001608 else if (stat & BAT_TEMP_STATUS_TOO_HOT_BIT)
Nicholas Troast34db5032016-03-28 12:26:44 -07001609 val->intval = POWER_SUPPLY_HEALTH_OVERHEAT;
Harry Yang668fc5e2016-07-12 16:51:47 -07001610 else if (stat & BAT_TEMP_STATUS_COLD_SOFT_LIMIT_BIT)
Nicholas Troast34db5032016-03-28 12:26:44 -07001611 val->intval = POWER_SUPPLY_HEALTH_COOL;
Harry Yang668fc5e2016-07-12 16:51:47 -07001612 else if (stat & BAT_TEMP_STATUS_HOT_SOFT_LIMIT_BIT)
Nicholas Troast34db5032016-03-28 12:26:44 -07001613 val->intval = POWER_SUPPLY_HEALTH_WARM;
Harry Yang668fc5e2016-07-12 16:51:47 -07001614 else
Nicholas Troast34db5032016-03-28 12:26:44 -07001615 val->intval = POWER_SUPPLY_HEALTH_GOOD;
Nicholas Troast34db5032016-03-28 12:26:44 -07001616
1617done:
1618 return rc;
1619}
1620
Abhijeet Dharmapurikar99fb8942016-07-08 11:39:23 -07001621int smblib_get_prop_system_temp_level(struct smb_charger *chg,
1622 union power_supply_propval *val)
1623{
1624 val->intval = chg->system_temp_level;
1625 return 0;
1626}
1627
Abhijeet Dharmapurikar0e369002016-09-07 17:25:36 -07001628int smblib_get_prop_input_current_limited(struct smb_charger *chg,
1629 union power_supply_propval *val)
1630{
1631 u8 stat;
1632 int rc;
1633
1634 rc = smblib_read(chg, AICL_STATUS_REG, &stat);
1635 if (rc < 0) {
Abhijeet Dharmapurikar31b98f32016-10-14 12:25:23 -07001636 smblib_err(chg, "Couldn't read AICL_STATUS rc=%d\n", rc);
Abhijeet Dharmapurikar0e369002016-09-07 17:25:36 -07001637 return rc;
1638 }
1639 val->intval = (stat & SOFT_ILIMIT_BIT) || chg->is_hdc;
1640 return 0;
1641}
1642
Nicholas Troast66b21d72016-09-20 15:33:20 -07001643int smblib_get_prop_batt_voltage_now(struct smb_charger *chg,
1644 union power_supply_propval *val)
1645{
1646 int rc;
1647
1648 if (!chg->bms_psy)
1649 return -EINVAL;
1650
1651 rc = power_supply_get_property(chg->bms_psy,
1652 POWER_SUPPLY_PROP_VOLTAGE_NOW, val);
1653 return rc;
1654}
1655
1656int smblib_get_prop_batt_current_now(struct smb_charger *chg,
1657 union power_supply_propval *val)
1658{
1659 int rc;
1660
1661 if (!chg->bms_psy)
1662 return -EINVAL;
1663
1664 rc = power_supply_get_property(chg->bms_psy,
1665 POWER_SUPPLY_PROP_CURRENT_NOW, val);
1666 return rc;
1667}
1668
1669int smblib_get_prop_batt_temp(struct smb_charger *chg,
1670 union power_supply_propval *val)
1671{
1672 int rc;
1673
1674 if (!chg->bms_psy)
1675 return -EINVAL;
1676
1677 rc = power_supply_get_property(chg->bms_psy,
1678 POWER_SUPPLY_PROP_TEMP, val);
1679 return rc;
1680}
1681
Harry Yangbedee332016-08-31 16:14:29 -07001682int smblib_get_prop_step_chg_step(struct smb_charger *chg,
1683 union power_supply_propval *val)
1684{
1685 int rc;
1686 u8 stat;
1687
1688 if (!chg->step_chg_enabled) {
1689 val->intval = -1;
1690 return 0;
1691 }
1692
1693 rc = smblib_read(chg, BATTERY_CHARGER_STATUS_1_REG, &stat);
1694 if (rc < 0) {
Abhijeet Dharmapurikar31b98f32016-10-14 12:25:23 -07001695 smblib_err(chg, "Couldn't read BATTERY_CHARGER_STATUS_1 rc=%d\n",
Harry Yangbedee332016-08-31 16:14:29 -07001696 rc);
1697 return rc;
1698 }
1699
1700 val->intval = (stat & STEP_CHARGING_STATUS_MASK) >>
1701 STEP_CHARGING_STATUS_SHIFT;
1702
1703 return rc;
1704}
1705
Subbaraman Narayanamurthyb491d022016-10-10 20:22:48 -07001706int smblib_get_prop_batt_charge_done(struct smb_charger *chg,
1707 union power_supply_propval *val)
1708{
1709 int rc;
1710 u8 stat;
1711
1712 rc = smblib_read(chg, BATTERY_CHARGER_STATUS_1_REG, &stat);
1713 if (rc < 0) {
Abhijeet Dharmapurikar31b98f32016-10-14 12:25:23 -07001714 smblib_err(chg, "Couldn't read BATTERY_CHARGER_STATUS_1 rc=%d\n",
Subbaraman Narayanamurthyb491d022016-10-10 20:22:48 -07001715 rc);
1716 return rc;
1717 }
1718
1719 stat = stat & BATTERY_CHARGER_STATUS_MASK;
1720 val->intval = (stat == TERMINATE_CHARGE);
1721 return 0;
1722}
1723
Harry Yang40192cb2017-02-25 23:25:17 -08001724int smblib_get_prop_charge_qnovo_enable(struct smb_charger *chg,
1725 union power_supply_propval *val)
1726{
1727 int rc;
1728 u8 stat;
1729
1730 rc = smblib_read(chg, QNOVO_PT_ENABLE_CMD_REG, &stat);
1731 if (rc < 0) {
1732 smblib_err(chg, "Couldn't read QNOVO_PT_ENABLE_CMD rc=%d\n",
1733 rc);
1734 return rc;
1735 }
1736
1737 val->intval = (bool)(stat & QNOVO_PT_ENABLE_CMD_BIT);
1738 return 0;
1739}
1740
Nicholas Troast34db5032016-03-28 12:26:44 -07001741/***********************
1742 * BATTERY PSY SETTERS *
1743 ***********************/
1744
1745int smblib_set_prop_input_suspend(struct smb_charger *chg,
1746 const union power_supply_propval *val)
1747{
1748 int rc;
1749
Abhijeet Dharmapurikar5e0bfbe2017-02-12 19:16:15 -08001750 /* vote 0mA when suspended */
1751 rc = vote(chg->usb_icl_votable, USER_VOTER, (bool)val->intval, 0);
Nicholas Troast34db5032016-03-28 12:26:44 -07001752 if (rc < 0) {
Abhijeet Dharmapurikar31b98f32016-10-14 12:25:23 -07001753 smblib_err(chg, "Couldn't vote to %s USB rc=%d\n",
Nicholas Troast34db5032016-03-28 12:26:44 -07001754 (bool)val->intval ? "suspend" : "resume", rc);
1755 return rc;
1756 }
1757
1758 rc = vote(chg->dc_suspend_votable, USER_VOTER, (bool)val->intval, 0);
1759 if (rc < 0) {
Abhijeet Dharmapurikar31b98f32016-10-14 12:25:23 -07001760 smblib_err(chg, "Couldn't vote to %s DC rc=%d\n",
Nicholas Troast34db5032016-03-28 12:26:44 -07001761 (bool)val->intval ? "suspend" : "resume", rc);
1762 return rc;
1763 }
1764
Nicholas Troast61ff40f2016-07-08 10:59:22 -07001765 power_supply_changed(chg->batt_psy);
Nicholas Troast34db5032016-03-28 12:26:44 -07001766 return rc;
1767}
1768
Abhijeet Dharmapurikar9e7e48c2016-08-23 12:55:49 -07001769int smblib_set_prop_batt_capacity(struct smb_charger *chg,
1770 const union power_supply_propval *val)
1771{
1772 chg->fake_capacity = val->intval;
1773
1774 power_supply_changed(chg->batt_psy);
1775
1776 return 0;
1777}
1778
Abhijeet Dharmapurikar99fb8942016-07-08 11:39:23 -07001779int smblib_set_prop_system_temp_level(struct smb_charger *chg,
1780 const union power_supply_propval *val)
1781{
1782 if (val->intval < 0)
1783 return -EINVAL;
1784
1785 if (chg->thermal_levels <= 0)
1786 return -EINVAL;
1787
1788 if (val->intval > chg->thermal_levels)
1789 return -EINVAL;
1790
1791 chg->system_temp_level = val->intval;
1792 if (chg->system_temp_level == chg->thermal_levels)
Harry Yangaba1f5f2016-09-28 10:47:29 -07001793 return vote(chg->chg_disable_votable,
1794 THERMAL_DAEMON_VOTER, true, 0);
Abhijeet Dharmapurikar99fb8942016-07-08 11:39:23 -07001795
Harry Yangaba1f5f2016-09-28 10:47:29 -07001796 vote(chg->chg_disable_votable, THERMAL_DAEMON_VOTER, false, 0);
Abhijeet Dharmapurikar99fb8942016-07-08 11:39:23 -07001797 if (chg->system_temp_level == 0)
Harry Yangaba1f5f2016-09-28 10:47:29 -07001798 return vote(chg->fcc_votable, THERMAL_DAEMON_VOTER, false, 0);
Abhijeet Dharmapurikar99fb8942016-07-08 11:39:23 -07001799
Harry Yangaba1f5f2016-09-28 10:47:29 -07001800 vote(chg->fcc_votable, THERMAL_DAEMON_VOTER, true,
Abhijeet Dharmapurikar99fb8942016-07-08 11:39:23 -07001801 chg->thermal_mitigation[chg->system_temp_level]);
1802 return 0;
1803}
1804
Harry Yang40192cb2017-02-25 23:25:17 -08001805int smblib_set_prop_charge_qnovo_enable(struct smb_charger *chg,
1806 const union power_supply_propval *val)
1807{
1808 int rc = 0;
1809
1810 rc = smblib_masked_write(chg, QNOVO_PT_ENABLE_CMD_REG,
1811 QNOVO_PT_ENABLE_CMD_BIT,
1812 val->intval ? QNOVO_PT_ENABLE_CMD_BIT : 0);
1813 if (rc < 0) {
1814 dev_err(chg->dev, "Couldn't enable qnovo rc=%d\n", rc);
1815 return rc;
1816 }
1817
1818 return rc;
1819}
1820
Ashay Jaiswal6d308da2017-02-18 09:59:23 +05301821int smblib_rerun_aicl(struct smb_charger *chg)
1822{
Nicholas Troast20ae1912017-02-15 10:15:32 -08001823 int rc, settled_icl_ua;
1824 u8 stat;
Ashay Jaiswal6d308da2017-02-18 09:59:23 +05301825
Nicholas Troast20ae1912017-02-15 10:15:32 -08001826 rc = smblib_read(chg, POWER_PATH_STATUS_REG, &stat);
1827 if (rc < 0) {
1828 smblib_err(chg, "Couldn't read POWER_PATH_STATUS rc=%d\n",
1829 rc);
1830 return rc;
1831 }
1832
1833 /* USB is suspended so skip re-running AICL */
1834 if (stat & USBIN_SUSPEND_STS_BIT)
1835 return rc;
1836
1837 smblib_dbg(chg, PR_MISC, "re-running AICL\n");
Ashay Jaiswal6d308da2017-02-18 09:59:23 +05301838 switch (chg->smb_version) {
1839 case PMI8998_SUBTYPE:
Nicholas Troast20ae1912017-02-15 10:15:32 -08001840 rc = smblib_get_charge_param(chg, &chg->param.icl_stat,
1841 &settled_icl_ua);
1842 if (rc < 0) {
1843 smblib_err(chg, "Couldn't get settled ICL rc=%d\n", rc);
1844 return rc;
1845 }
1846
1847 vote(chg->usb_icl_votable, AICL_RERUN_VOTER, true,
1848 max(settled_icl_ua - chg->param.usb_icl.step_u,
1849 chg->param.usb_icl.step_u));
1850 vote(chg->usb_icl_votable, AICL_RERUN_VOTER, false, 0);
1851 break;
Ashay Jaiswal6d308da2017-02-18 09:59:23 +05301852 case PM660_SUBTYPE:
Nicholas Troast20ae1912017-02-15 10:15:32 -08001853 /*
1854 * Use restart_AICL instead of trigger_AICL as it runs the
1855 * complete AICL instead of starting from the last settled
1856 * value.
1857 */
1858 rc = smblib_masked_write(chg, CMD_HVDCP_2_REG,
1859 RESTART_AICL_BIT, RESTART_AICL_BIT);
1860 if (rc < 0)
1861 smblib_err(chg, "Couldn't write to CMD_HVDCP_2_REG rc=%d\n",
1862 rc);
Ashay Jaiswal6d308da2017-02-18 09:59:23 +05301863 break;
1864 default:
1865 smblib_dbg(chg, PR_PARALLEL, "unknown SMB chip %d\n",
1866 chg->smb_version);
1867 return -EINVAL;
1868 }
Ashay Jaiswal6d308da2017-02-18 09:59:23 +05301869
Nicholas Troast20ae1912017-02-15 10:15:32 -08001870 return 0;
Ashay Jaiswal6d308da2017-02-18 09:59:23 +05301871}
1872
1873static int smblib_dp_pulse(struct smb_charger *chg)
1874{
1875 int rc;
1876
1877 /* QC 3.0 increment */
1878 rc = smblib_masked_write(chg, CMD_HVDCP_2_REG, SINGLE_INCREMENT_BIT,
1879 SINGLE_INCREMENT_BIT);
1880 if (rc < 0)
1881 smblib_err(chg, "Couldn't write to CMD_HVDCP_2_REG rc=%d\n",
1882 rc);
1883
1884 return rc;
1885}
1886
1887static int smblib_dm_pulse(struct smb_charger *chg)
1888{
1889 int rc;
1890
1891 /* QC 3.0 decrement */
1892 rc = smblib_masked_write(chg, CMD_HVDCP_2_REG, SINGLE_DECREMENT_BIT,
1893 SINGLE_DECREMENT_BIT);
1894 if (rc < 0)
1895 smblib_err(chg, "Couldn't write to CMD_HVDCP_2_REG rc=%d\n",
1896 rc);
1897
1898 return rc;
1899}
1900
1901int smblib_dp_dm(struct smb_charger *chg, int val)
1902{
1903 int target_icl_ua, rc = 0;
1904
1905 switch (val) {
1906 case POWER_SUPPLY_DP_DM_DP_PULSE:
1907 rc = smblib_dp_pulse(chg);
1908 if (!rc)
1909 chg->pulse_cnt++;
1910 smblib_dbg(chg, PR_PARALLEL, "DP_DM_DP_PULSE rc=%d cnt=%d\n",
1911 rc, chg->pulse_cnt);
1912 break;
1913 case POWER_SUPPLY_DP_DM_DM_PULSE:
1914 rc = smblib_dm_pulse(chg);
1915 if (!rc && chg->pulse_cnt)
1916 chg->pulse_cnt--;
1917 smblib_dbg(chg, PR_PARALLEL, "DP_DM_DM_PULSE rc=%d cnt=%d\n",
1918 rc, chg->pulse_cnt);
1919 break;
1920 case POWER_SUPPLY_DP_DM_ICL_DOWN:
1921 chg->usb_icl_delta_ua -= 100000;
1922 target_icl_ua = get_effective_result(chg->usb_icl_votable);
1923 vote(chg->usb_icl_votable, SW_QC3_VOTER, true,
1924 target_icl_ua + chg->usb_icl_delta_ua);
1925 break;
1926 case POWER_SUPPLY_DP_DM_ICL_UP:
1927 default:
1928 break;
1929 }
1930
1931 return rc;
1932}
1933
Nicholas Troast34db5032016-03-28 12:26:44 -07001934/*******************
Harry Yangf3023592016-07-20 14:56:41 -07001935 * DC PSY GETTERS *
1936 *******************/
1937
1938int smblib_get_prop_dc_present(struct smb_charger *chg,
1939 union power_supply_propval *val)
1940{
Nicholas Troastdeae99c2016-11-14 09:13:01 -08001941 int rc;
Harry Yangf3023592016-07-20 14:56:41 -07001942 u8 stat;
1943
Nicholas Troastdeae99c2016-11-14 09:13:01 -08001944 rc = smblib_read(chg, DCIN_BASE + INT_RT_STS_OFFSET, &stat);
Harry Yangf3023592016-07-20 14:56:41 -07001945 if (rc < 0) {
Nicholas Troastdeae99c2016-11-14 09:13:01 -08001946 smblib_err(chg, "Couldn't read DCIN_RT_STS rc=%d\n", rc);
Harry Yangf3023592016-07-20 14:56:41 -07001947 return rc;
1948 }
Harry Yangf3023592016-07-20 14:56:41 -07001949
1950 val->intval = (bool)(stat & DCIN_PLUGIN_RT_STS_BIT);
Nicholas Troastdeae99c2016-11-14 09:13:01 -08001951 return 0;
Harry Yangf3023592016-07-20 14:56:41 -07001952}
1953
1954int smblib_get_prop_dc_online(struct smb_charger *chg,
1955 union power_supply_propval *val)
1956{
1957 int rc = 0;
1958 u8 stat;
1959
1960 if (get_client_vote(chg->dc_suspend_votable, USER_VOTER)) {
1961 val->intval = false;
1962 return rc;
1963 }
1964
1965 rc = smblib_read(chg, POWER_PATH_STATUS_REG, &stat);
1966 if (rc < 0) {
Abhijeet Dharmapurikar31b98f32016-10-14 12:25:23 -07001967 smblib_err(chg, "Couldn't read POWER_PATH_STATUS rc=%d\n",
Harry Yangf3023592016-07-20 14:56:41 -07001968 rc);
1969 return rc;
1970 }
1971 smblib_dbg(chg, PR_REGISTER, "POWER_PATH_STATUS = 0x%02x\n",
1972 stat);
1973
1974 val->intval = (stat & USE_DCIN_BIT) &&
Vic Wei7ade2842016-12-14 18:47:49 -08001975 (stat & VALID_INPUT_POWER_SOURCE_STS_BIT);
Harry Yangf3023592016-07-20 14:56:41 -07001976
1977 return rc;
1978}
1979
1980int smblib_get_prop_dc_current_max(struct smb_charger *chg,
1981 union power_supply_propval *val)
1982{
1983 val->intval = get_effective_result_locked(chg->dc_icl_votable);
1984 return 0;
1985}
1986
1987/*******************
Harry Yangd89ff1f2016-12-05 14:59:11 -08001988 * DC PSY SETTERS *
Harry Yangf3023592016-07-20 14:56:41 -07001989 * *****************/
1990
1991int smblib_set_prop_dc_current_max(struct smb_charger *chg,
1992 const union power_supply_propval *val)
1993{
1994 int rc;
1995
1996 rc = vote(chg->dc_icl_votable, USER_VOTER, true, val->intval);
1997 return rc;
1998}
1999
2000/*******************
Nicholas Troast34db5032016-03-28 12:26:44 -07002001 * USB PSY GETTERS *
2002 *******************/
2003
2004int smblib_get_prop_usb_present(struct smb_charger *chg,
2005 union power_supply_propval *val)
2006{
Nicholas Troastdeae99c2016-11-14 09:13:01 -08002007 int rc;
Nicholas Troast34db5032016-03-28 12:26:44 -07002008 u8 stat;
2009
Nicholas Troastdeae99c2016-11-14 09:13:01 -08002010 rc = smblib_read(chg, USBIN_BASE + INT_RT_STS_OFFSET, &stat);
Nicholas Troast34db5032016-03-28 12:26:44 -07002011 if (rc < 0) {
Nicholas Troastdeae99c2016-11-14 09:13:01 -08002012 smblib_err(chg, "Couldn't read USBIN_RT_STS rc=%d\n", rc);
Nicholas Troast34db5032016-03-28 12:26:44 -07002013 return rc;
2014 }
Nicholas Troast34db5032016-03-28 12:26:44 -07002015
Nicholas Troastdeae99c2016-11-14 09:13:01 -08002016 val->intval = (bool)(stat & USBIN_PLUGIN_RT_STS_BIT);
2017 return 0;
Nicholas Troast34db5032016-03-28 12:26:44 -07002018}
2019
2020int smblib_get_prop_usb_online(struct smb_charger *chg,
2021 union power_supply_propval *val)
2022{
2023 int rc = 0;
2024 u8 stat;
2025
Abhijeet Dharmapurikar5e0bfbe2017-02-12 19:16:15 -08002026 if (get_client_vote(chg->usb_icl_votable, USER_VOTER) == 0) {
Nicholas Troast34db5032016-03-28 12:26:44 -07002027 val->intval = false;
2028 return rc;
2029 }
2030
2031 rc = smblib_read(chg, POWER_PATH_STATUS_REG, &stat);
2032 if (rc < 0) {
Abhijeet Dharmapurikar31b98f32016-10-14 12:25:23 -07002033 smblib_err(chg, "Couldn't read POWER_PATH_STATUS rc=%d\n",
Nicholas Troast34db5032016-03-28 12:26:44 -07002034 rc);
2035 return rc;
2036 }
2037 smblib_dbg(chg, PR_REGISTER, "POWER_PATH_STATUS = 0x%02x\n",
2038 stat);
2039
2040 val->intval = (stat & USE_USBIN_BIT) &&
Vic Wei7ade2842016-12-14 18:47:49 -08002041 (stat & VALID_INPUT_POWER_SOURCE_STS_BIT);
Nicholas Troast34db5032016-03-28 12:26:44 -07002042 return rc;
2043}
2044
2045int smblib_get_prop_usb_voltage_now(struct smb_charger *chg,
2046 union power_supply_propval *val)
2047{
Harry Yangba874ce2016-08-19 14:17:01 -07002048 int rc = 0;
Nicholas Troast34db5032016-03-28 12:26:44 -07002049
Harry Yangba874ce2016-08-19 14:17:01 -07002050 rc = smblib_get_prop_usb_present(chg, val);
2051 if (rc < 0 || !val->intval)
2052 return rc;
2053
2054 if (!chg->iio.usbin_v_chan ||
2055 PTR_ERR(chg->iio.usbin_v_chan) == -EPROBE_DEFER)
2056 chg->iio.usbin_v_chan = iio_channel_get(chg->dev, "usbin_v");
2057
2058 if (IS_ERR(chg->iio.usbin_v_chan))
2059 return PTR_ERR(chg->iio.usbin_v_chan);
2060
2061 return iio_read_channel_processed(chg->iio.usbin_v_chan, &val->intval);
Nicholas Troast34db5032016-03-28 12:26:44 -07002062}
2063
Abhijeet Dharmapurikard92eca62016-10-07 19:04:33 -07002064int smblib_get_prop_pd_current_max(struct smb_charger *chg,
2065 union power_supply_propval *val)
2066{
2067 val->intval = get_client_vote_locked(chg->usb_icl_votable, PD_VOTER);
2068 return 0;
2069}
2070
Nicholas Troast34db5032016-03-28 12:26:44 -07002071int smblib_get_prop_usb_current_max(struct smb_charger *chg,
2072 union power_supply_propval *val)
2073{
Abhijeet Dharmapurikard92eca62016-10-07 19:04:33 -07002074 val->intval = get_client_vote_locked(chg->usb_icl_votable,
2075 USB_PSY_VOTER);
Nicholas Troast34db5032016-03-28 12:26:44 -07002076 return 0;
2077}
2078
Harry Yangba874ce2016-08-19 14:17:01 -07002079int smblib_get_prop_usb_current_now(struct smb_charger *chg,
2080 union power_supply_propval *val)
2081{
2082 int rc = 0;
2083
2084 rc = smblib_get_prop_usb_present(chg, val);
2085 if (rc < 0 || !val->intval)
2086 return rc;
2087
2088 if (!chg->iio.usbin_i_chan ||
2089 PTR_ERR(chg->iio.usbin_i_chan) == -EPROBE_DEFER)
2090 chg->iio.usbin_i_chan = iio_channel_get(chg->dev, "usbin_i");
2091
2092 if (IS_ERR(chg->iio.usbin_i_chan))
2093 return PTR_ERR(chg->iio.usbin_i_chan);
2094
2095 return iio_read_channel_processed(chg->iio.usbin_i_chan, &val->intval);
2096}
2097
2098int smblib_get_prop_charger_temp(struct smb_charger *chg,
2099 union power_supply_propval *val)
2100{
2101 int rc;
2102
2103 if (!chg->iio.temp_chan ||
2104 PTR_ERR(chg->iio.temp_chan) == -EPROBE_DEFER)
2105 chg->iio.temp_chan = iio_channel_get(chg->dev, "charger_temp");
2106
2107 if (IS_ERR(chg->iio.temp_chan))
2108 return PTR_ERR(chg->iio.temp_chan);
2109
2110 rc = iio_read_channel_processed(chg->iio.temp_chan, &val->intval);
2111 val->intval /= 100;
2112 return rc;
2113}
2114
2115int smblib_get_prop_charger_temp_max(struct smb_charger *chg,
2116 union power_supply_propval *val)
2117{
2118 int rc;
2119
2120 if (!chg->iio.temp_max_chan ||
2121 PTR_ERR(chg->iio.temp_max_chan) == -EPROBE_DEFER)
2122 chg->iio.temp_max_chan = iio_channel_get(chg->dev,
2123 "charger_temp_max");
2124 if (IS_ERR(chg->iio.temp_max_chan))
2125 return PTR_ERR(chg->iio.temp_max_chan);
2126
2127 rc = iio_read_channel_processed(chg->iio.temp_max_chan, &val->intval);
2128 val->intval /= 100;
2129 return rc;
2130}
2131
Nicholas Troast34db5032016-03-28 12:26:44 -07002132int smblib_get_prop_typec_cc_orientation(struct smb_charger *chg,
2133 union power_supply_propval *val)
2134{
2135 int rc = 0;
2136 u8 stat;
2137
2138 rc = smblib_read(chg, TYPE_C_STATUS_4_REG, &stat);
2139 if (rc < 0) {
Abhijeet Dharmapurikar31b98f32016-10-14 12:25:23 -07002140 smblib_err(chg, "Couldn't read TYPE_C_STATUS_4 rc=%d\n", rc);
Nicholas Troast34db5032016-03-28 12:26:44 -07002141 return rc;
2142 }
2143 smblib_dbg(chg, PR_REGISTER, "TYPE_C_STATUS_4 = 0x%02x\n",
2144 stat);
2145
2146 if (stat & CC_ATTACHED_BIT)
2147 val->intval = (bool)(stat & CC_ORIENTATION_BIT) + 1;
2148 else
2149 val->intval = 0;
2150
2151 return rc;
2152}
2153
2154static const char * const smblib_typec_mode_name[] = {
2155 [POWER_SUPPLY_TYPEC_NONE] = "NONE",
2156 [POWER_SUPPLY_TYPEC_SOURCE_DEFAULT] = "SOURCE_DEFAULT",
2157 [POWER_SUPPLY_TYPEC_SOURCE_MEDIUM] = "SOURCE_MEDIUM",
2158 [POWER_SUPPLY_TYPEC_SOURCE_HIGH] = "SOURCE_HIGH",
2159 [POWER_SUPPLY_TYPEC_NON_COMPLIANT] = "NON_COMPLIANT",
2160 [POWER_SUPPLY_TYPEC_SINK] = "SINK",
2161 [POWER_SUPPLY_TYPEC_SINK_POWERED_CABLE] = "SINK_POWERED_CABLE",
2162 [POWER_SUPPLY_TYPEC_SINK_DEBUG_ACCESSORY] = "SINK_DEBUG_ACCESSORY",
2163 [POWER_SUPPLY_TYPEC_SINK_AUDIO_ADAPTER] = "SINK_AUDIO_ADAPTER",
2164 [POWER_SUPPLY_TYPEC_POWERED_CABLE_ONLY] = "POWERED_CABLE_ONLY",
2165};
2166
2167static int smblib_get_prop_ufp_mode(struct smb_charger *chg)
2168{
2169 int rc;
2170 u8 stat;
2171
2172 rc = smblib_read(chg, TYPE_C_STATUS_1_REG, &stat);
2173 if (rc < 0) {
Abhijeet Dharmapurikar31b98f32016-10-14 12:25:23 -07002174 smblib_err(chg, "Couldn't read TYPE_C_STATUS_1 rc=%d\n", rc);
Nicholas Troast34db5032016-03-28 12:26:44 -07002175 return POWER_SUPPLY_TYPEC_NONE;
2176 }
2177 smblib_dbg(chg, PR_REGISTER, "TYPE_C_STATUS_1 = 0x%02x\n", stat);
2178
2179 switch (stat) {
2180 case 0:
2181 return POWER_SUPPLY_TYPEC_NONE;
2182 case UFP_TYPEC_RDSTD_BIT:
2183 return POWER_SUPPLY_TYPEC_SOURCE_DEFAULT;
2184 case UFP_TYPEC_RD1P5_BIT:
2185 return POWER_SUPPLY_TYPEC_SOURCE_MEDIUM;
2186 case UFP_TYPEC_RD3P0_BIT:
2187 return POWER_SUPPLY_TYPEC_SOURCE_HIGH;
2188 default:
2189 break;
2190 }
2191
2192 return POWER_SUPPLY_TYPEC_NON_COMPLIANT;
2193}
2194
2195static int smblib_get_prop_dfp_mode(struct smb_charger *chg)
2196{
2197 int rc;
2198 u8 stat;
2199
2200 rc = smblib_read(chg, TYPE_C_STATUS_2_REG, &stat);
2201 if (rc < 0) {
Abhijeet Dharmapurikar31b98f32016-10-14 12:25:23 -07002202 smblib_err(chg, "Couldn't read TYPE_C_STATUS_2 rc=%d\n", rc);
Nicholas Troast34db5032016-03-28 12:26:44 -07002203 return POWER_SUPPLY_TYPEC_NONE;
2204 }
2205 smblib_dbg(chg, PR_REGISTER, "TYPE_C_STATUS_2 = 0x%02x\n", stat);
2206
2207 switch (stat & DFP_TYPEC_MASK) {
2208 case DFP_RA_RA_BIT:
2209 return POWER_SUPPLY_TYPEC_SINK_AUDIO_ADAPTER;
2210 case DFP_RD_RD_BIT:
2211 return POWER_SUPPLY_TYPEC_SINK_DEBUG_ACCESSORY;
2212 case DFP_RD_RA_VCONN_BIT:
2213 return POWER_SUPPLY_TYPEC_SINK_POWERED_CABLE;
2214 case DFP_RD_OPEN_BIT:
2215 return POWER_SUPPLY_TYPEC_SINK;
2216 case DFP_RA_OPEN_BIT:
2217 return POWER_SUPPLY_TYPEC_POWERED_CABLE_ONLY;
2218 default:
2219 break;
2220 }
2221
2222 return POWER_SUPPLY_TYPEC_NONE;
2223}
2224
2225int smblib_get_prop_typec_mode(struct smb_charger *chg,
2226 union power_supply_propval *val)
2227{
2228 int rc;
2229 u8 stat;
2230
2231 rc = smblib_read(chg, TYPE_C_STATUS_4_REG, &stat);
2232 if (rc < 0) {
Abhijeet Dharmapurikar31b98f32016-10-14 12:25:23 -07002233 smblib_err(chg, "Couldn't read TYPE_C_STATUS_4 rc=%d\n", rc);
Nicholas Troast34db5032016-03-28 12:26:44 -07002234 val->intval = POWER_SUPPLY_TYPEC_NONE;
2235 return rc;
2236 }
2237 smblib_dbg(chg, PR_REGISTER, "TYPE_C_STATUS_4 = 0x%02x\n", stat);
2238
2239 if (!(stat & TYPEC_DEBOUNCE_DONE_STATUS_BIT)) {
2240 val->intval = POWER_SUPPLY_TYPEC_NONE;
2241 return rc;
2242 }
2243
2244 if (stat & UFP_DFP_MODE_STATUS_BIT)
2245 val->intval = smblib_get_prop_dfp_mode(chg);
2246 else
2247 val->intval = smblib_get_prop_ufp_mode(chg);
2248
2249 return rc;
2250}
2251
2252int smblib_get_prop_typec_power_role(struct smb_charger *chg,
2253 union power_supply_propval *val)
2254{
2255 int rc = 0;
2256 u8 ctrl;
2257
2258 rc = smblib_read(chg, TYPE_C_INTRPT_ENB_SOFTWARE_CTRL_REG, &ctrl);
2259 if (rc < 0) {
Abhijeet Dharmapurikar31b98f32016-10-14 12:25:23 -07002260 smblib_err(chg, "Couldn't read TYPE_C_INTRPT_ENB_SOFTWARE_CTRL rc=%d\n",
Nicholas Troast34db5032016-03-28 12:26:44 -07002261 rc);
2262 return rc;
2263 }
2264 smblib_dbg(chg, PR_REGISTER, "TYPE_C_INTRPT_ENB_SOFTWARE_CTRL = 0x%02x\n",
2265 ctrl);
2266
2267 if (ctrl & TYPEC_DISABLE_CMD_BIT) {
2268 val->intval = POWER_SUPPLY_TYPEC_PR_NONE;
2269 return rc;
2270 }
2271
2272 switch (ctrl & (DFP_EN_CMD_BIT | UFP_EN_CMD_BIT)) {
2273 case 0:
2274 val->intval = POWER_SUPPLY_TYPEC_PR_DUAL;
2275 break;
2276 case DFP_EN_CMD_BIT:
2277 val->intval = POWER_SUPPLY_TYPEC_PR_SOURCE;
2278 break;
2279 case UFP_EN_CMD_BIT:
2280 val->intval = POWER_SUPPLY_TYPEC_PR_SINK;
2281 break;
2282 default:
2283 val->intval = POWER_SUPPLY_TYPEC_PR_NONE;
Abhijeet Dharmapurikar31b98f32016-10-14 12:25:23 -07002284 smblib_err(chg, "unsupported power role 0x%02lx\n",
Nicholas Troast34db5032016-03-28 12:26:44 -07002285 ctrl & (DFP_EN_CMD_BIT | UFP_EN_CMD_BIT));
2286 return -EINVAL;
2287 }
2288
2289 return rc;
2290}
2291
2292int smblib_get_prop_pd_allowed(struct smb_charger *chg,
2293 union power_supply_propval *val)
2294{
Abhijeet Dharmapurikarb9598872016-10-17 16:58:58 -07002295 val->intval = get_effective_result(chg->pd_allowed_votable);
Nicholas Troast34db5032016-03-28 12:26:44 -07002296 return 0;
2297}
2298
Nicholas Troast133a7f52016-06-29 13:48:20 -07002299int smblib_get_prop_input_current_settled(struct smb_charger *chg,
2300 union power_supply_propval *val)
2301{
2302 return smblib_get_charge_param(chg, &chg->param.icl_stat, &val->intval);
2303}
2304
Fenglin Wuef4730e2017-01-11 18:16:25 +08002305#define HVDCP3_STEP_UV 200000
2306int smblib_get_prop_input_voltage_settled(struct smb_charger *chg,
2307 union power_supply_propval *val)
2308{
2309 const struct apsd_result *apsd_result = smblib_get_apsd_result(chg);
2310 int rc, pulses;
2311 u8 stat;
2312
2313 val->intval = MICRO_5V;
2314 if (apsd_result == NULL) {
2315 smblib_err(chg, "APSD result is NULL\n");
2316 return 0;
2317 }
2318
2319 switch (apsd_result->pst) {
2320 case POWER_SUPPLY_TYPE_USB_HVDCP_3:
2321 rc = smblib_read(chg, QC_PULSE_COUNT_STATUS_REG, &stat);
2322 if (rc < 0) {
2323 smblib_err(chg,
2324 "Couldn't read QC_PULSE_COUNT rc=%d\n", rc);
2325 return 0;
2326 }
2327 pulses = (stat & QC_PULSE_COUNT_MASK);
2328 val->intval = MICRO_5V + HVDCP3_STEP_UV * pulses;
2329 break;
2330 default:
2331 val->intval = MICRO_5V;
2332 break;
2333 }
2334
2335 return 0;
2336}
2337
Abhijeet Dharmapurikarf8a7a4a2016-10-07 18:46:45 -07002338int smblib_get_prop_pd_in_hard_reset(struct smb_charger *chg,
2339 union power_supply_propval *val)
2340{
2341 int rc;
2342 u8 ctrl;
2343
2344 rc = smblib_read(chg, TYPE_C_INTRPT_ENB_SOFTWARE_CTRL_REG, &ctrl);
2345 if (rc < 0) {
Abhijeet Dharmapurikar31b98f32016-10-14 12:25:23 -07002346 smblib_err(chg, "Couldn't read TYPE_C_INTRPT_ENB_SOFTWARE_CTRL_REG rc=%d\n",
Abhijeet Dharmapurikarf8a7a4a2016-10-07 18:46:45 -07002347 rc);
2348 return rc;
2349 }
2350 val->intval = ctrl & EXIT_SNK_BASED_ON_CC_BIT;
2351 return 0;
2352}
2353
Abhijeet Dharmapurikarb9598872016-10-17 16:58:58 -07002354int smblib_get_pe_start(struct smb_charger *chg,
2355 union power_supply_propval *val)
2356{
2357 /*
2358 * hvdcp timeout voter is the last one to allow pd. Use its vote
2359 * to indicate start of pe engine
2360 */
2361 val->intval
2362 = !get_client_vote_locked(chg->pd_disallowed_votable_indirect,
2363 HVDCP_TIMEOUT_VOTER);
2364 return 0;
2365}
2366
Nicholas Troast7fdbd2e2017-02-08 10:47:37 -08002367int smblib_get_prop_die_health(struct smb_charger *chg,
Nicholas Troastb021dd92017-01-31 18:43:38 -08002368 union power_supply_propval *val)
2369{
Nicholas Troast7fdbd2e2017-02-08 10:47:37 -08002370 int rc;
Nicholas Troastb021dd92017-01-31 18:43:38 -08002371 u8 stat;
2372
2373 rc = smblib_read(chg, TEMP_RANGE_STATUS_REG, &stat);
2374 if (rc < 0) {
2375 smblib_err(chg, "Couldn't read TEMP_RANGE_STATUS_REG rc=%d\n",
2376 rc);
2377 return rc;
2378 }
2379
Nicholas Troast7fdbd2e2017-02-08 10:47:37 -08002380 /* TEMP_RANGE bits are mutually exclusive */
2381 switch (stat & TEMP_RANGE_MASK) {
2382 case TEMP_BELOW_RANGE_BIT:
2383 val->intval = POWER_SUPPLY_HEALTH_COOL;
2384 break;
2385 case TEMP_WITHIN_RANGE_BIT:
2386 val->intval = POWER_SUPPLY_HEALTH_WARM;
2387 break;
2388 case TEMP_ABOVE_RANGE_BIT:
2389 val->intval = POWER_SUPPLY_HEALTH_HOT;
2390 break;
2391 case ALERT_LEVEL_BIT:
2392 val->intval = POWER_SUPPLY_HEALTH_OVERHEAT;
2393 break;
2394 default:
2395 val->intval = POWER_SUPPLY_HEALTH_UNKNOWN;
Nicholas Troastb021dd92017-01-31 18:43:38 -08002396 }
2397
Nicholas Troastb021dd92017-01-31 18:43:38 -08002398 return 0;
2399}
2400
Nicholas Troast34db5032016-03-28 12:26:44 -07002401/*******************
2402 * USB PSY SETTERS *
2403 * *****************/
2404
Abhijeet Dharmapurikard92eca62016-10-07 19:04:33 -07002405int smblib_set_prop_pd_current_max(struct smb_charger *chg,
2406 const union power_supply_propval *val)
2407{
2408 int rc;
2409
2410 if (chg->pd_active)
2411 rc = vote(chg->usb_icl_votable, PD_VOTER, true, val->intval);
2412 else
2413 rc = -EPERM;
2414
2415 return rc;
2416}
2417
Nicholas Troast34db5032016-03-28 12:26:44 -07002418int smblib_set_prop_usb_current_max(struct smb_charger *chg,
2419 const union power_supply_propval *val)
2420{
Nicholas Troast8d33b7d2017-01-16 11:18:38 -08002421 int rc = 0;
Nicholas Troast34db5032016-03-28 12:26:44 -07002422
Abhijeet Dharmapurikard92eca62016-10-07 19:04:33 -07002423 if (!chg->pd_active) {
2424 rc = vote(chg->usb_icl_votable, USB_PSY_VOTER,
2425 true, val->intval);
2426 } else if (chg->system_suspend_supported) {
2427 if (val->intval <= USBIN_25MA)
Abhijeet Dharmapurikar95670872017-02-09 22:55:51 +05302428 rc = vote(chg->usb_icl_votable,
2429 PD_SUSPEND_SUPPORTED_VOTER, true, val->intval);
Abhijeet Dharmapurikard92eca62016-10-07 19:04:33 -07002430 else
Abhijeet Dharmapurikar95670872017-02-09 22:55:51 +05302431 rc = vote(chg->usb_icl_votable,
2432 PD_SUSPEND_SUPPORTED_VOTER, false, 0);
Abhijeet Dharmapurikard92eca62016-10-07 19:04:33 -07002433 }
Nicholas Troast34db5032016-03-28 12:26:44 -07002434 return rc;
2435}
2436
Harry Yangd89ff1f2016-12-05 14:59:11 -08002437int smblib_set_prop_boost_current(struct smb_charger *chg,
2438 const union power_supply_propval *val)
2439{
2440 int rc = 0;
2441
2442 rc = smblib_set_charge_param(chg, &chg->param.freq_boost,
2443 val->intval <= chg->boost_threshold_ua ?
Anirudh Ghayal4da3df92017-01-25 18:55:57 +05302444 chg->chg_freq.freq_below_otg_threshold :
2445 chg->chg_freq.freq_above_otg_threshold);
Harry Yangd89ff1f2016-12-05 14:59:11 -08002446 if (rc < 0) {
2447 dev_err(chg->dev, "Error in setting freq_boost rc=%d\n", rc);
2448 return rc;
2449 }
2450
2451 chg->boost_current_ua = val->intval;
2452 return rc;
2453}
2454
Nicholas Troast34db5032016-03-28 12:26:44 -07002455int smblib_set_prop_typec_power_role(struct smb_charger *chg,
2456 const union power_supply_propval *val)
2457{
2458 int rc = 0;
2459 u8 power_role;
2460
2461 switch (val->intval) {
2462 case POWER_SUPPLY_TYPEC_PR_NONE:
2463 power_role = TYPEC_DISABLE_CMD_BIT;
2464 break;
2465 case POWER_SUPPLY_TYPEC_PR_DUAL:
2466 power_role = 0;
2467 break;
2468 case POWER_SUPPLY_TYPEC_PR_SINK:
2469 power_role = UFP_EN_CMD_BIT;
2470 break;
2471 case POWER_SUPPLY_TYPEC_PR_SOURCE:
2472 power_role = DFP_EN_CMD_BIT;
2473 break;
2474 default:
Abhijeet Dharmapurikar31b98f32016-10-14 12:25:23 -07002475 smblib_err(chg, "power role %d not supported\n", val->intval);
Nicholas Troast34db5032016-03-28 12:26:44 -07002476 return -EINVAL;
2477 }
2478
2479 rc = smblib_masked_write(chg, TYPE_C_INTRPT_ENB_SOFTWARE_CTRL_REG,
2480 TYPEC_POWER_ROLE_CMD_MASK, power_role);
2481 if (rc < 0) {
Abhijeet Dharmapurikar31b98f32016-10-14 12:25:23 -07002482 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 -07002483 power_role, rc);
2484 return rc;
2485 }
2486
2487 return rc;
2488}
2489
2490int smblib_set_prop_usb_voltage_min(struct smb_charger *chg,
2491 const union power_supply_propval *val)
2492{
2493 int rc, min_uv;
2494
2495 min_uv = min(val->intval, chg->voltage_max_uv);
2496 rc = smblib_set_usb_pd_allowed_voltage(chg, min_uv,
2497 chg->voltage_max_uv);
2498 if (rc < 0) {
Abhijeet Dharmapurikar31b98f32016-10-14 12:25:23 -07002499 smblib_err(chg, "invalid max voltage %duV rc=%d\n",
Nicholas Troast34db5032016-03-28 12:26:44 -07002500 val->intval, rc);
2501 return rc;
2502 }
2503
Harry Yangaba1f5f2016-09-28 10:47:29 -07002504 if (chg->mode == PARALLEL_MASTER)
2505 vote(chg->pl_enable_votable_indirect, USBIN_V_VOTER,
2506 min_uv > MICRO_5V, 0);
2507
2508 chg->voltage_min_uv = min_uv;
Nicholas Troast34db5032016-03-28 12:26:44 -07002509 return rc;
2510}
2511
2512int smblib_set_prop_usb_voltage_max(struct smb_charger *chg,
2513 const union power_supply_propval *val)
2514{
2515 int rc, max_uv;
2516
2517 max_uv = max(val->intval, chg->voltage_min_uv);
2518 rc = smblib_set_usb_pd_allowed_voltage(chg, chg->voltage_min_uv,
2519 max_uv);
2520 if (rc < 0) {
Abhijeet Dharmapurikar31b98f32016-10-14 12:25:23 -07002521 smblib_err(chg, "invalid min voltage %duV rc=%d\n",
Nicholas Troast34db5032016-03-28 12:26:44 -07002522 val->intval, rc);
2523 return rc;
2524 }
2525
Harry Yangaba1f5f2016-09-28 10:47:29 -07002526 chg->voltage_max_uv = max_uv;
Nicholas Troast34db5032016-03-28 12:26:44 -07002527 return rc;
2528}
2529
2530int smblib_set_prop_pd_active(struct smb_charger *chg,
2531 const union power_supply_propval *val)
2532{
2533 int rc;
Abhijeet Dharmapurikar716cd962016-10-14 12:50:37 -07002534 u8 stat = 0;
2535 bool cc_debounced;
2536 bool orientation;
2537 bool pd_active = val->intval;
Nicholas Troast34db5032016-03-28 12:26:44 -07002538
2539 if (!get_effective_result(chg->pd_allowed_votable)) {
Abhijeet Dharmapurikar31b98f32016-10-14 12:25:23 -07002540 smblib_err(chg, "PD is not allowed\n");
Nicholas Troast34db5032016-03-28 12:26:44 -07002541 return -EINVAL;
2542 }
2543
Abhijeet Dharmapurikar716cd962016-10-14 12:50:37 -07002544 vote(chg->apsd_disable_votable, PD_VOTER, pd_active, 0);
2545 vote(chg->pd_allowed_votable, PD_VOTER, pd_active, 0);
Harry Yang4bf7d962017-03-13 16:51:43 -07002546 vote(chg->usb_irq_enable_votable, PD_VOTER, pd_active, 0);
Nicholas Troast34db5032016-03-28 12:26:44 -07002547
Harry Yang88acff42016-09-21 14:56:06 -07002548 /*
2549 * VCONN_EN_ORIENTATION_BIT controls whether to use CC1 or CC2 line
2550 * when TYPEC_SPARE_CFG_BIT (CC pin selection s/w override) is set
2551 * or when VCONN_EN_VALUE_BIT is set.
2552 */
Abhijeet Dharmapurikar716cd962016-10-14 12:50:37 -07002553 rc = smblib_read(chg, TYPE_C_STATUS_4_REG, &stat);
2554 if (rc < 0) {
Abhijeet Dharmapurikar31b98f32016-10-14 12:25:23 -07002555 smblib_err(chg, "Couldn't read TYPE_C_STATUS_4 rc=%d\n", rc);
Abhijeet Dharmapurikar716cd962016-10-14 12:50:37 -07002556 return rc;
2557 }
Harry Yang88acff42016-09-21 14:56:06 -07002558
Abhijeet Dharmapurikar716cd962016-10-14 12:50:37 -07002559 if (pd_active) {
2560 orientation = stat & CC_ORIENTATION_BIT;
Harry Yang88acff42016-09-21 14:56:06 -07002561 rc = smblib_masked_write(chg,
Abhijeet Dharmapurikar716cd962016-10-14 12:50:37 -07002562 TYPE_C_INTRPT_ENB_SOFTWARE_CTRL_REG,
2563 VCONN_EN_ORIENTATION_BIT,
2564 orientation ? 0 : VCONN_EN_ORIENTATION_BIT);
2565 if (rc < 0) {
Abhijeet Dharmapurikar31b98f32016-10-14 12:25:23 -07002566 smblib_err(chg,
Harry Yang88acff42016-09-21 14:56:06 -07002567 "Couldn't enable vconn on CC line rc=%d\n", rc);
Abhijeet Dharmapurikar716cd962016-10-14 12:50:37 -07002568 return rc;
2569 }
Abhijeet Dharmapurikar95670872017-02-09 22:55:51 +05302570 /*
2571 * Enforce 500mA for PD until the real vote comes in later.
2572 * It is guaranteed that pd_active is set prior to
2573 * pd_current_max
2574 */
Harry Yangcd995202016-11-07 13:32:52 -08002575 rc = vote(chg->usb_icl_votable, PD_VOTER, true, USBIN_500MA);
2576 if (rc < 0) {
2577 smblib_err(chg, "Couldn't vote for USB ICL rc=%d\n",
2578 rc);
2579 return rc;
2580 }
2581
Nicholas Troastf9e44992017-03-14 09:06:56 -07002582 /* since PD was found the cable must be non-legacy */
2583 vote(chg->usb_icl_votable, LEGACY_UNKNOWN_VOTER, false, 0);
2584
Abhijeet Dharmapurikar7442e422017-02-08 13:35:14 -08002585 /* clear USB ICL vote for DCP_VOTER */
Harry Yang631b99e2016-11-17 11:24:25 -08002586 rc = vote(chg->usb_icl_votable, DCP_VOTER, false, 0);
Abhijeet Dharmapurikar7442e422017-02-08 13:35:14 -08002587 if (rc < 0)
2588 smblib_err(chg,
2589 "Couldn't un-vote DCP from USB ICL rc=%d\n",
2590 rc);
2591
2592 /* clear USB ICL vote for PL_USBIN_USBIN_VOTER */
2593 rc = vote(chg->usb_icl_votable, PL_USBIN_USBIN_VOTER, false, 0);
2594 if (rc < 0)
2595 smblib_err(chg,
2596 "Couldn't un-vote PL_USBIN_USBIN from USB ICL rc=%d\n",
2597 rc);
Abhijeet Dharmapurikar95670872017-02-09 22:55:51 +05302598
2599 /* remove USB_PSY_VOTER */
2600 rc = vote(chg->usb_icl_votable, USB_PSY_VOTER, false, 0);
2601 if (rc < 0) {
2602 smblib_err(chg, "Couldn't unvote USB_PSY rc=%d\n", rc);
Harry Yang631b99e2016-11-17 11:24:25 -08002603 return rc;
2604 }
Ashay Jaiswale38fe7e2017-02-13 11:42:19 +05302605
2606 /* pd active set, parallel charger can be enabled now */
2607 rc = vote(chg->pl_disable_votable, PL_DELAY_HVDCP_VOTER,
2608 false, 0);
2609 if (rc < 0) {
2610 smblib_err(chg,
2611 "Couldn't unvote PL_DELAY_HVDCP_VOTER rc=%d\n",
2612 rc);
2613 return rc;
2614 }
Harry Yang88acff42016-09-21 14:56:06 -07002615 }
2616
2617 /* CC pin selection s/w override in PD session; h/w otherwise. */
2618 rc = smblib_masked_write(chg, TAPER_TIMER_SEL_CFG_REG,
2619 TYPEC_SPARE_CFG_BIT,
Abhijeet Dharmapurikar716cd962016-10-14 12:50:37 -07002620 pd_active ? TYPEC_SPARE_CFG_BIT : 0);
Harry Yang88acff42016-09-21 14:56:06 -07002621 if (rc < 0) {
Abhijeet Dharmapurikar31b98f32016-10-14 12:25:23 -07002622 smblib_err(chg, "Couldn't change cc_out ctrl to %s rc=%d\n",
Abhijeet Dharmapurikar716cd962016-10-14 12:50:37 -07002623 pd_active ? "SW" : "HW", rc);
Harry Yang88acff42016-09-21 14:56:06 -07002624 return rc;
2625 }
2626
Abhijeet Dharmapurikar716cd962016-10-14 12:50:37 -07002627 cc_debounced = (bool)(stat & TYPEC_DEBOUNCE_DONE_STATUS_BIT);
2628 if (!pd_active && cc_debounced)
2629 try_rerun_apsd_for_hvdcp(chg);
2630
2631 chg->pd_active = pd_active;
Harry Yang6607b4a2016-05-17 17:50:09 -07002632 smblib_update_usb_type(chg);
Abhijeet Dharmapurikar76e2af52016-10-06 17:25:01 -07002633 power_supply_changed(chg->usb_psy);
2634
Nicholas Troast34db5032016-03-28 12:26:44 -07002635 return rc;
2636}
2637
Fenglin Wuedd70792016-11-22 13:16:19 +08002638int smblib_set_prop_ship_mode(struct smb_charger *chg,
2639 const union power_supply_propval *val)
2640{
2641 int rc;
2642
2643 smblib_dbg(chg, PR_MISC, "Set ship mode: %d!!\n", !!val->intval);
2644
2645 rc = smblib_masked_write(chg, SHIP_MODE_REG, SHIP_MODE_EN_BIT,
2646 !!val->intval ? SHIP_MODE_EN_BIT : 0);
2647 if (rc < 0)
2648 dev_err(chg->dev, "Couldn't %s ship mode, rc=%d\n",
2649 !!val->intval ? "enable" : "disable", rc);
2650
2651 return rc;
2652}
2653
Harry Yang5e2bb712016-10-18 16:47:48 -07002654int smblib_reg_block_update(struct smb_charger *chg,
2655 struct reg_info *entry)
2656{
2657 int rc = 0;
2658
2659 while (entry && entry->reg) {
2660 rc = smblib_read(chg, entry->reg, &entry->bak);
2661 if (rc < 0) {
2662 dev_err(chg->dev, "Error in reading %s rc=%d\n",
2663 entry->desc, rc);
2664 break;
2665 }
2666 entry->bak &= entry->mask;
2667
2668 rc = smblib_masked_write(chg, entry->reg,
2669 entry->mask, entry->val);
2670 if (rc < 0) {
2671 dev_err(chg->dev, "Error in writing %s rc=%d\n",
2672 entry->desc, rc);
2673 break;
2674 }
2675 entry++;
2676 }
2677
2678 return rc;
2679}
2680
2681int smblib_reg_block_restore(struct smb_charger *chg,
2682 struct reg_info *entry)
2683{
2684 int rc = 0;
2685
2686 while (entry && entry->reg) {
2687 rc = smblib_masked_write(chg, entry->reg,
2688 entry->mask, entry->bak);
2689 if (rc < 0) {
2690 dev_err(chg->dev, "Error in writing %s rc=%d\n",
2691 entry->desc, rc);
2692 break;
2693 }
2694 entry++;
2695 }
2696
2697 return rc;
2698}
2699
Harry Yang755a34b2016-11-01 01:18:51 -07002700static struct reg_info cc2_detach_settings[] = {
2701 {
2702 .reg = TYPE_C_CFG_2_REG,
2703 .mask = TYPE_C_UFP_MODE_BIT | EN_TRY_SOURCE_MODE_BIT,
2704 .val = TYPE_C_UFP_MODE_BIT,
2705 .desc = "TYPE_C_CFG_2_REG",
2706 },
2707 {
2708 .reg = TYPE_C_CFG_3_REG,
2709 .mask = EN_TRYSINK_MODE_BIT,
2710 .val = 0,
2711 .desc = "TYPE_C_CFG_3_REG",
2712 },
2713 {
2714 .reg = TAPER_TIMER_SEL_CFG_REG,
2715 .mask = TYPEC_SPARE_CFG_BIT,
2716 .val = TYPEC_SPARE_CFG_BIT,
2717 .desc = "TAPER_TIMER_SEL_CFG_REG",
2718 },
2719 {
2720 .reg = TYPE_C_INTRPT_ENB_SOFTWARE_CTRL_REG,
2721 .mask = VCONN_EN_ORIENTATION_BIT,
2722 .val = 0,
2723 .desc = "TYPE_C_INTRPT_ENB_SOFTWARE_CTRL_REG",
2724 },
2725 {
2726 .reg = MISC_CFG_REG,
2727 .mask = TCC_DEBOUNCE_20MS_BIT,
2728 .val = TCC_DEBOUNCE_20MS_BIT,
2729 .desc = "Tccdebounce time"
2730 },
2731 {
2732 },
2733};
2734
2735static int smblib_cc2_sink_removal_enter(struct smb_charger *chg)
2736{
2737 int rc = 0;
2738 union power_supply_propval cc2_val = {0, };
2739
2740 if ((chg->wa_flags & TYPEC_CC2_REMOVAL_WA_BIT) == 0)
2741 return rc;
2742
2743 if (chg->cc2_sink_detach_flag != CC2_SINK_NONE)
2744 return rc;
2745
2746 rc = smblib_get_prop_typec_cc_orientation(chg, &cc2_val);
2747 if (rc < 0) {
2748 smblib_err(chg, "Couldn't get cc orientation rc=%d\n", rc);
2749 return rc;
2750 }
2751 if (cc2_val.intval == 1)
2752 return rc;
2753
2754 rc = smblib_get_prop_typec_mode(chg, &cc2_val);
2755 if (rc < 0) {
2756 smblib_err(chg, "Couldn't get prop typec mode rc=%d\n", rc);
2757 return rc;
2758 }
2759
2760 switch (cc2_val.intval) {
2761 case POWER_SUPPLY_TYPEC_SOURCE_DEFAULT:
2762 smblib_reg_block_update(chg, cc2_detach_settings);
2763 chg->cc2_sink_detach_flag = CC2_SINK_STD;
2764 schedule_work(&chg->rdstd_cc2_detach_work);
2765 break;
Harry Yang86e4d852016-11-07 15:08:47 -08002766 case POWER_SUPPLY_TYPEC_SOURCE_MEDIUM:
2767 case POWER_SUPPLY_TYPEC_SOURCE_HIGH:
2768 chg->cc2_sink_detach_flag = CC2_SINK_MEDIUM_HIGH;
2769 break;
Harry Yang755a34b2016-11-01 01:18:51 -07002770 default:
2771 break;
2772 }
2773
2774 return rc;
2775}
2776
2777static int smblib_cc2_sink_removal_exit(struct smb_charger *chg)
2778{
2779 int rc = 0;
2780
2781 if ((chg->wa_flags & TYPEC_CC2_REMOVAL_WA_BIT) == 0)
2782 return rc;
2783
2784 if (chg->cc2_sink_detach_flag == CC2_SINK_STD) {
2785 cancel_work_sync(&chg->rdstd_cc2_detach_work);
2786 smblib_reg_block_restore(chg, cc2_detach_settings);
2787 }
2788
2789 chg->cc2_sink_detach_flag = CC2_SINK_NONE;
2790
2791 return rc;
2792}
2793
Abhijeet Dharmapurikarf8a7a4a2016-10-07 18:46:45 -07002794int smblib_set_prop_pd_in_hard_reset(struct smb_charger *chg,
2795 const union power_supply_propval *val)
2796{
2797 int rc;
2798
2799 rc = smblib_masked_write(chg, TYPE_C_INTRPT_ENB_SOFTWARE_CTRL_REG,
2800 EXIT_SNK_BASED_ON_CC_BIT,
2801 (val->intval) ? EXIT_SNK_BASED_ON_CC_BIT : 0);
Harry Yang755a34b2016-11-01 01:18:51 -07002802 if (rc < 0) {
2803 smblib_err(chg, "Could not set EXIT_SNK_BASED_ON_CC rc=%d\n",
2804 rc);
2805 return rc;
2806 }
Abhijeet Dharmapurikarf8a7a4a2016-10-07 18:46:45 -07002807
2808 vote(chg->apsd_disable_votable, PD_HARD_RESET_VOTER, val->intval, 0);
2809
Harry Yang755a34b2016-11-01 01:18:51 -07002810 if (val->intval)
2811 rc = smblib_cc2_sink_removal_enter(chg);
2812 else
2813 rc = smblib_cc2_sink_removal_exit(chg);
2814
2815 if (rc < 0) {
2816 smblib_err(chg, "Could not detect cc2 removal rc=%d\n", rc);
2817 return rc;
2818 }
2819
Abhijeet Dharmapurikarf8a7a4a2016-10-07 18:46:45 -07002820 return rc;
2821}
2822
Nicholas Troast7dbcad22016-10-05 13:30:18 -07002823/************************
Abhijeet Dharmapurikar7442e422017-02-08 13:35:14 -08002824 * USB MAIN PSY GETTERS *
2825 ************************/
2826int smblib_get_prop_fcc_delta(struct smb_charger *chg,
2827 union power_supply_propval *val)
2828{
2829 int rc, jeita_cc_delta_ua, step_cc_delta_ua, hw_cc_delta_ua = 0;
2830
2831 rc = smblib_get_step_cc_delta(chg, &step_cc_delta_ua);
2832 if (rc < 0) {
2833 smblib_err(chg, "Couldn't get step cc delta rc=%d\n", rc);
2834 step_cc_delta_ua = 0;
2835 } else {
2836 hw_cc_delta_ua = step_cc_delta_ua;
2837 }
2838
2839 rc = smblib_get_jeita_cc_delta(chg, &jeita_cc_delta_ua);
2840 if (rc < 0) {
2841 smblib_err(chg, "Couldn't get jeita cc delta rc=%d\n", rc);
2842 jeita_cc_delta_ua = 0;
2843 } else if (jeita_cc_delta_ua < 0) {
2844 /* HW will take the min between JEITA and step charge */
2845 hw_cc_delta_ua = min(hw_cc_delta_ua, jeita_cc_delta_ua);
2846 }
2847
2848 val->intval = hw_cc_delta_ua;
2849 return 0;
2850}
2851
2852/************************
2853 * USB MAIN PSY SETTERS *
2854 ************************/
2855
2856#define SDP_CURRENT_MA 500000
2857#define CDP_CURRENT_MA 1500000
2858#define DCP_CURRENT_MA 1500000
2859#define HVDCP_CURRENT_MA 3000000
2860#define TYPEC_DEFAULT_CURRENT_MA 900000
2861#define TYPEC_MEDIUM_CURRENT_MA 1500000
2862#define TYPEC_HIGH_CURRENT_MA 3000000
2863static int smblib_get_charge_current(struct smb_charger *chg,
2864 int *total_current_ua)
2865{
2866 const struct apsd_result *apsd_result = smblib_update_usb_type(chg);
2867 union power_supply_propval val = {0, };
2868 int rc, typec_source_rd, current_ua;
2869 bool non_compliant;
2870 u8 stat5;
2871
2872 rc = smblib_read(chg, TYPE_C_STATUS_5_REG, &stat5);
2873 if (rc < 0) {
2874 smblib_err(chg, "Couldn't read TYPE_C_STATUS_5 rc=%d\n", rc);
2875 return rc;
2876 }
2877 non_compliant = stat5 & TYPEC_NONCOMP_LEGACY_CABLE_STATUS_BIT;
2878
2879 /* get settled ICL */
2880 rc = smblib_get_prop_input_current_settled(chg, &val);
2881 if (rc < 0) {
2882 smblib_err(chg, "Couldn't get settled ICL rc=%d\n", rc);
2883 return rc;
2884 }
2885
2886 typec_source_rd = smblib_get_prop_ufp_mode(chg);
2887
2888 /* QC 2.0/3.0 adapter */
2889 if (apsd_result->bit & (QC_3P0_BIT | QC_2P0_BIT)) {
2890 *total_current_ua = HVDCP_CURRENT_MA;
2891 return 0;
2892 }
2893
2894 if (non_compliant) {
2895 switch (apsd_result->bit) {
2896 case CDP_CHARGER_BIT:
2897 current_ua = CDP_CURRENT_MA;
2898 break;
2899 case DCP_CHARGER_BIT:
2900 case OCP_CHARGER_BIT:
2901 case FLOAT_CHARGER_BIT:
2902 current_ua = DCP_CURRENT_MA;
2903 break;
2904 default:
2905 current_ua = 0;
2906 break;
2907 }
2908
2909 *total_current_ua = max(current_ua, val.intval);
2910 return 0;
2911 }
2912
2913 switch (typec_source_rd) {
2914 case POWER_SUPPLY_TYPEC_SOURCE_DEFAULT:
2915 switch (apsd_result->bit) {
2916 case CDP_CHARGER_BIT:
2917 current_ua = CDP_CURRENT_MA;
2918 break;
2919 case DCP_CHARGER_BIT:
2920 case OCP_CHARGER_BIT:
2921 case FLOAT_CHARGER_BIT:
2922 current_ua = chg->default_icl_ua;
2923 break;
2924 default:
2925 current_ua = 0;
2926 break;
2927 }
2928 break;
2929 case POWER_SUPPLY_TYPEC_SOURCE_MEDIUM:
2930 current_ua = TYPEC_MEDIUM_CURRENT_MA;
2931 break;
2932 case POWER_SUPPLY_TYPEC_SOURCE_HIGH:
2933 current_ua = TYPEC_HIGH_CURRENT_MA;
2934 break;
2935 case POWER_SUPPLY_TYPEC_NON_COMPLIANT:
2936 case POWER_SUPPLY_TYPEC_NONE:
2937 default:
2938 current_ua = 0;
2939 break;
2940 }
2941
2942 *total_current_ua = max(current_ua, val.intval);
2943 return 0;
2944}
2945
2946int smblib_set_icl_reduction(struct smb_charger *chg, int reduction_ua)
2947{
2948 int current_ua, rc;
2949
2950 if (reduction_ua == 0) {
Abhijeet Dharmapurikar7442e422017-02-08 13:35:14 -08002951 vote(chg->usb_icl_votable, PL_USBIN_USBIN_VOTER, false, 0);
2952 } else {
2953 /*
2954 * No usb_icl voter means we are defaulting to hw chosen
2955 * max limit. We need a vote from s/w to enforce the reduction.
2956 */
2957 if (get_effective_result(chg->usb_icl_votable) == -EINVAL) {
2958 rc = smblib_get_charge_current(chg, &current_ua);
2959 if (rc < 0) {
2960 pr_err("Failed to get ICL rc=%d\n", rc);
2961 return rc;
2962 }
2963 vote(chg->usb_icl_votable, PL_USBIN_USBIN_VOTER, true,
2964 current_ua);
2965 }
2966 }
2967
Ashay Jaiswal69dd1ad2017-02-16 16:44:08 +05302968 chg->icl_reduction_ua = reduction_ua;
2969
Abhijeet Dharmapurikar7442e422017-02-08 13:35:14 -08002970 return rerun_election(chg->usb_icl_votable);
2971}
2972
2973/************************
Nicholas Troast7dbcad22016-10-05 13:30:18 -07002974 * PARALLEL PSY GETTERS *
2975 ************************/
2976
2977int smblib_get_prop_slave_current_now(struct smb_charger *chg,
2978 union power_supply_propval *pval)
2979{
2980 if (IS_ERR_OR_NULL(chg->iio.batt_i_chan))
2981 chg->iio.batt_i_chan = iio_channel_get(chg->dev, "batt_i");
2982
2983 if (IS_ERR(chg->iio.batt_i_chan))
2984 return PTR_ERR(chg->iio.batt_i_chan);
2985
2986 return iio_read_channel_processed(chg->iio.batt_i_chan, &pval->intval);
2987}
2988
Nicholas Troast34db5032016-03-28 12:26:44 -07002989/**********************
2990 * INTERRUPT HANDLERS *
2991 **********************/
2992
2993irqreturn_t smblib_handle_debug(int irq, void *data)
2994{
2995 struct smb_irq_data *irq_data = data;
2996 struct smb_charger *chg = irq_data->parent_data;
2997
2998 smblib_dbg(chg, PR_INTERRUPT, "IRQ: %s\n", irq_data->name);
Nicholas Troast34db5032016-03-28 12:26:44 -07002999 return IRQ_HANDLED;
3000}
3001
Nicholas Troast8995a702016-12-05 10:22:22 -08003002irqreturn_t smblib_handle_otg_overcurrent(int irq, void *data)
3003{
3004 struct smb_irq_data *irq_data = data;
3005 struct smb_charger *chg = irq_data->parent_data;
3006 int rc;
3007 u8 stat;
3008
3009 rc = smblib_read(chg, OTG_BASE + INT_RT_STS_OFFSET, &stat);
3010 if (rc < 0) {
3011 dev_err(chg->dev, "Couldn't read OTG_INT_RT_STS rc=%d\n", rc);
3012 return IRQ_HANDLED;
3013 }
3014
Ashay Jaiswal7c241382017-03-06 15:26:38 +05303015 if (chg->wa_flags & OTG_WA) {
3016 if (stat & OTG_OC_DIS_SW_STS_RT_STS_BIT)
3017 smblib_err(chg, "OTG disabled by hw\n");
3018
3019 /* not handling software based hiccups for PM660 */
3020 return IRQ_HANDLED;
3021 }
3022
Nicholas Troastb11015f2017-01-17 17:56:45 -08003023 if (stat & OTG_OVERCURRENT_RT_STS_BIT)
3024 schedule_work(&chg->otg_oc_work);
Nicholas Troast8995a702016-12-05 10:22:22 -08003025
Nicholas Troast8995a702016-12-05 10:22:22 -08003026 return IRQ_HANDLED;
3027}
3028
Harry Yang6fe72ab2016-06-14 16:21:39 -07003029irqreturn_t smblib_handle_chg_state_change(int irq, void *data)
3030{
3031 struct smb_irq_data *irq_data = data;
3032 struct smb_charger *chg = irq_data->parent_data;
Nicholas Troast8cb77552016-09-23 11:50:18 -07003033 u8 stat;
Harry Yang1d1034c2016-06-15 12:09:42 -07003034 int rc;
Harry Yang6fe72ab2016-06-14 16:21:39 -07003035
3036 smblib_dbg(chg, PR_INTERRUPT, "IRQ: %s\n", irq_data->name);
3037
Nicholas Troast8cb77552016-09-23 11:50:18 -07003038 rc = smblib_read(chg, BATTERY_CHARGER_STATUS_1_REG, &stat);
Harry Yang1d1034c2016-06-15 12:09:42 -07003039 if (rc < 0) {
Abhijeet Dharmapurikar31b98f32016-10-14 12:25:23 -07003040 smblib_err(chg, "Couldn't read BATTERY_CHARGER_STATUS_1 rc=%d\n",
Nicholas Troast8cb77552016-09-23 11:50:18 -07003041 rc);
Harry Yang1d1034c2016-06-15 12:09:42 -07003042 return IRQ_HANDLED;
3043 }
3044
Nicholas Troast8cb77552016-09-23 11:50:18 -07003045 stat = stat & BATTERY_CHARGER_STATUS_MASK;
Nicholas Troast8cb77552016-09-23 11:50:18 -07003046 power_supply_changed(chg->batt_psy);
Harry Yang6fe72ab2016-06-14 16:21:39 -07003047 return IRQ_HANDLED;
3048}
3049
Harry Yangfe913842016-08-10 12:27:28 -07003050irqreturn_t smblib_handle_step_chg_state_change(int irq, void *data)
3051{
3052 struct smb_irq_data *irq_data = data;
3053 struct smb_charger *chg = irq_data->parent_data;
3054
3055 smblib_dbg(chg, PR_INTERRUPT, "IRQ: %s\n", irq_data->name);
3056
3057 if (chg->step_chg_enabled)
3058 rerun_election(chg->fcc_votable);
3059
3060 return IRQ_HANDLED;
3061}
3062
3063irqreturn_t smblib_handle_step_chg_soc_update_fail(int irq, void *data)
3064{
3065 struct smb_irq_data *irq_data = data;
3066 struct smb_charger *chg = irq_data->parent_data;
3067
3068 smblib_dbg(chg, PR_INTERRUPT, "IRQ: %s\n", irq_data->name);
3069
3070 if (chg->step_chg_enabled)
3071 rerun_election(chg->fcc_votable);
3072
3073 return IRQ_HANDLED;
3074}
3075
3076#define STEP_SOC_REQ_MS 3000
3077irqreturn_t smblib_handle_step_chg_soc_update_request(int irq, void *data)
3078{
3079 struct smb_irq_data *irq_data = data;
3080 struct smb_charger *chg = irq_data->parent_data;
3081 int rc;
3082 union power_supply_propval pval = {0, };
3083
3084 smblib_dbg(chg, PR_INTERRUPT, "IRQ: %s\n", irq_data->name);
3085
3086 if (!chg->bms_psy) {
3087 schedule_delayed_work(&chg->step_soc_req_work,
3088 msecs_to_jiffies(STEP_SOC_REQ_MS));
3089 return IRQ_HANDLED;
3090 }
3091
3092 rc = smblib_get_prop_batt_capacity(chg, &pval);
3093 if (rc < 0)
Abhijeet Dharmapurikar31b98f32016-10-14 12:25:23 -07003094 smblib_err(chg, "Couldn't get batt capacity rc=%d\n", rc);
Harry Yangfe913842016-08-10 12:27:28 -07003095 else
3096 step_charge_soc_update(chg, pval.intval);
3097
3098 return IRQ_HANDLED;
3099}
3100
Abhijeet Dharmapurikar2644cd62016-07-20 16:54:55 -07003101irqreturn_t smblib_handle_batt_temp_changed(int irq, void *data)
3102{
3103 struct smb_irq_data *irq_data = data;
3104 struct smb_charger *chg = irq_data->parent_data;
3105
3106 rerun_election(chg->fcc_votable);
3107 power_supply_changed(chg->batt_psy);
3108 return IRQ_HANDLED;
3109}
3110
Nicholas Troast34db5032016-03-28 12:26:44 -07003111irqreturn_t smblib_handle_batt_psy_changed(int irq, void *data)
3112{
3113 struct smb_irq_data *irq_data = data;
3114 struct smb_charger *chg = irq_data->parent_data;
3115
Nicholas Troast47ae4612016-08-03 09:49:36 -07003116 smblib_dbg(chg, PR_INTERRUPT, "IRQ: %s\n", irq_data->name);
Nicholas Troast34db5032016-03-28 12:26:44 -07003117 power_supply_changed(chg->batt_psy);
3118 return IRQ_HANDLED;
3119}
3120
3121irqreturn_t smblib_handle_usb_psy_changed(int irq, void *data)
3122{
3123 struct smb_irq_data *irq_data = data;
3124 struct smb_charger *chg = irq_data->parent_data;
3125
Nicholas Troast47ae4612016-08-03 09:49:36 -07003126 smblib_dbg(chg, PR_INTERRUPT, "IRQ: %s\n", irq_data->name);
Nicholas Troast34db5032016-03-28 12:26:44 -07003127 power_supply_changed(chg->usb_psy);
3128 return IRQ_HANDLED;
3129}
3130
Subbaraman Narayanamurthy09327482017-02-06 16:33:12 -08003131irqreturn_t smblib_handle_usbin_uv(int irq, void *data)
3132{
3133 struct smb_irq_data *irq_data = data;
3134 struct smb_charger *chg = irq_data->parent_data;
3135 struct storm_watch *wdata;
3136
3137 smblib_dbg(chg, PR_INTERRUPT, "IRQ: %s\n", irq_data->name);
3138 if (!chg->irq_info[SWITCH_POWER_OK_IRQ].irq_data)
3139 return IRQ_HANDLED;
3140
3141 wdata = &chg->irq_info[SWITCH_POWER_OK_IRQ].irq_data->storm_data;
3142 reset_storm_count(wdata);
3143 return IRQ_HANDLED;
3144}
3145
Nicholas Troast34db5032016-03-28 12:26:44 -07003146irqreturn_t smblib_handle_usb_plugin(int irq, void *data)
3147{
3148 struct smb_irq_data *irq_data = data;
3149 struct smb_charger *chg = irq_data->parent_data;
3150 int rc;
3151 u8 stat;
Nicholas Troast7ec38eb2016-11-14 10:28:39 -08003152 bool vbus_rising;
Nicholas Troast34db5032016-03-28 12:26:44 -07003153
Harry Yangcdad2bf2016-10-04 17:03:56 -07003154 rc = smblib_read(chg, USBIN_BASE + INT_RT_STS_OFFSET, &stat);
3155 if (rc < 0) {
3156 dev_err(chg->dev, "Couldn't read USB_INT_RT_STS rc=%d\n", rc);
3157 return IRQ_HANDLED;
3158 }
3159
Nicholas Troast7ec38eb2016-11-14 10:28:39 -08003160 vbus_rising = (bool)(stat & USBIN_PLUGIN_RT_STS_BIT);
Harry Yangcdad2bf2016-10-04 17:03:56 -07003161 smblib_set_opt_freq_buck(chg,
Anirudh Ghayal4da3df92017-01-25 18:55:57 +05303162 vbus_rising ? chg->chg_freq.freq_5V :
3163 chg->chg_freq.freq_removal);
Harry Yangcdad2bf2016-10-04 17:03:56 -07003164
Nicholas Troast34db5032016-03-28 12:26:44 -07003165 /* fetch the DPDM regulator */
3166 if (!chg->dpdm_reg && of_get_property(chg->dev->of_node,
Ashay Jaiswal4aa2c0c2016-12-07 19:39:38 +05303167 "dpdm-supply", NULL)) {
Nicholas Troast34db5032016-03-28 12:26:44 -07003168 chg->dpdm_reg = devm_regulator_get(chg->dev, "dpdm");
3169 if (IS_ERR(chg->dpdm_reg)) {
Abhijeet Dharmapurikar31b98f32016-10-14 12:25:23 -07003170 smblib_err(chg, "Couldn't get dpdm regulator rc=%ld\n",
Nicholas Troast34db5032016-03-28 12:26:44 -07003171 PTR_ERR(chg->dpdm_reg));
3172 chg->dpdm_reg = NULL;
3173 }
3174 }
3175
Nicholas Troast7ec38eb2016-11-14 10:28:39 -08003176 if (vbus_rising) {
Nicholas Troastabedaf72016-09-16 11:07:45 -07003177 if (chg->dpdm_reg && !regulator_is_enabled(chg->dpdm_reg)) {
Abhijeet Dharmapurikar17288f22016-07-05 14:03:31 -07003178 smblib_dbg(chg, PR_MISC, "enabling DPDM regulator\n");
3179 rc = regulator_enable(chg->dpdm_reg);
3180 if (rc < 0)
Abhijeet Dharmapurikar31b98f32016-10-14 12:25:23 -07003181 smblib_err(chg, "Couldn't enable dpdm regulator rc=%d\n",
Abhijeet Dharmapurikar17288f22016-07-05 14:03:31 -07003182 rc);
3183 }
3184 } else {
Abhijeet Dharmapurikar2823fe32016-12-05 17:52:11 -08003185 if (chg->wa_flags & BOOST_BACK_WA)
Abhijeet Dharmapurikar5e0bfbe2017-02-12 19:16:15 -08003186 vote(chg->usb_icl_votable, BOOST_BACK_VOTER, false, 0);
Nicholas Troastabedaf72016-09-16 11:07:45 -07003187
3188 if (chg->dpdm_reg && regulator_is_enabled(chg->dpdm_reg)) {
Abhijeet Dharmapurikar17288f22016-07-05 14:03:31 -07003189 smblib_dbg(chg, PR_MISC, "disabling DPDM regulator\n");
3190 rc = regulator_disable(chg->dpdm_reg);
3191 if (rc < 0)
Abhijeet Dharmapurikar31b98f32016-10-14 12:25:23 -07003192 smblib_err(chg, "Couldn't disable dpdm regulator rc=%d\n",
Abhijeet Dharmapurikar17288f22016-07-05 14:03:31 -07003193 rc);
3194 }
Ashay Jaiswal4aa2c0c2016-12-07 19:39:38 +05303195
3196 if (chg->micro_usb_mode) {
3197 smblib_update_usb_type(chg);
3198 extcon_set_cable_state_(chg->extcon, EXTCON_USB, false);
3199 smblib_uusb_removal(chg);
3200 }
Nicholas Troast34db5032016-03-28 12:26:44 -07003201 }
3202
Nicholas Troast62d86622016-09-22 11:41:33 -07003203 power_supply_changed(chg->usb_psy);
Nicholas Troast34db5032016-03-28 12:26:44 -07003204 smblib_dbg(chg, PR_INTERRUPT, "IRQ: %s %s\n",
Ashay Jaiswal4aa2c0c2016-12-07 19:39:38 +05303205 irq_data->name, vbus_rising ? "attached" : "detached");
Nicholas Troast34db5032016-03-28 12:26:44 -07003206 return IRQ_HANDLED;
3207}
3208
Abhijeet Dharmapurikarc0b0f592016-10-14 10:55:42 -07003209#define USB_WEAK_INPUT_UA 1400000
Ashay Jaiswal4d825782017-02-18 10:11:34 +05303210#define ICL_CHANGE_DELAY_MS 1000
Harry Yang6fe72ab2016-06-14 16:21:39 -07003211irqreturn_t smblib_handle_icl_change(int irq, void *data)
3212{
Ashay Jaiswal4d825782017-02-18 10:11:34 +05303213 u8 stat;
3214 int rc, settled_ua, delay = ICL_CHANGE_DELAY_MS;
Harry Yang6fe72ab2016-06-14 16:21:39 -07003215 struct smb_irq_data *irq_data = data;
3216 struct smb_charger *chg = irq_data->parent_data;
3217
Nicholas Troastbb9e1a32017-02-09 10:57:28 -08003218 if (chg->mode == PARALLEL_MASTER) {
Ashay Jaiswal4d825782017-02-18 10:11:34 +05303219 rc = smblib_read(chg, AICL_STATUS_REG, &stat);
3220 if (rc < 0) {
3221 smblib_err(chg, "Couldn't read AICL_STATUS rc=%d\n",
3222 rc);
3223 return IRQ_HANDLED;
3224 }
3225
3226 rc = smblib_get_charge_param(chg, &chg->param.icl_stat,
3227 &settled_ua);
3228 if (rc < 0) {
3229 smblib_err(chg, "Couldn't get ICL status rc=%d\n", rc);
3230 return IRQ_HANDLED;
3231 }
3232
3233 /* If AICL settled then schedule work now */
3234 if ((settled_ua == get_effective_result(chg->usb_icl_votable))
3235 || (stat & AICL_DONE_BIT))
3236 delay = 0;
3237
Ashay Jaiswalac854862017-03-06 23:58:55 +05303238 cancel_delayed_work_sync(&chg->icl_change_work);
Ashay Jaiswal4d825782017-02-18 10:11:34 +05303239 schedule_delayed_work(&chg->icl_change_work,
3240 msecs_to_jiffies(delay));
Nicholas Troastbb9e1a32017-02-09 10:57:28 -08003241 }
Harry Yang1d1034c2016-06-15 12:09:42 -07003242
Harry Yang6fe72ab2016-06-14 16:21:39 -07003243 return IRQ_HANDLED;
3244}
3245
Nicholas Troast34db5032016-03-28 12:26:44 -07003246static void smblib_handle_slow_plugin_timeout(struct smb_charger *chg,
3247 bool rising)
3248{
3249 smblib_dbg(chg, PR_INTERRUPT, "IRQ: slow-plugin-timeout %s\n",
3250 rising ? "rising" : "falling");
3251}
3252
3253static void smblib_handle_sdp_enumeration_done(struct smb_charger *chg,
3254 bool rising)
3255{
3256 smblib_dbg(chg, PR_INTERRUPT, "IRQ: sdp-enumeration-done %s\n",
3257 rising ? "rising" : "falling");
3258}
3259
Harry Yangcdad2bf2016-10-04 17:03:56 -07003260#define QC3_PULSES_FOR_6V 5
3261#define QC3_PULSES_FOR_9V 20
3262#define QC3_PULSES_FOR_12V 35
3263static void smblib_hvdcp_adaptive_voltage_change(struct smb_charger *chg)
3264{
3265 int rc;
3266 u8 stat;
3267 int pulses;
3268
Fenglin Wuef4730e2017-01-11 18:16:25 +08003269 power_supply_changed(chg->usb_main_psy);
Harry Yangcdad2bf2016-10-04 17:03:56 -07003270 if (chg->usb_psy_desc.type == POWER_SUPPLY_TYPE_USB_HVDCP) {
3271 rc = smblib_read(chg, QC_CHANGE_STATUS_REG, &stat);
3272 if (rc < 0) {
3273 smblib_err(chg,
3274 "Couldn't read QC_CHANGE_STATUS rc=%d\n", rc);
3275 return;
3276 }
3277
3278 switch (stat & QC_2P0_STATUS_MASK) {
3279 case QC_5V_BIT:
Anirudh Ghayal4da3df92017-01-25 18:55:57 +05303280 smblib_set_opt_freq_buck(chg,
3281 chg->chg_freq.freq_5V);
Harry Yangcdad2bf2016-10-04 17:03:56 -07003282 break;
3283 case QC_9V_BIT:
Anirudh Ghayal4da3df92017-01-25 18:55:57 +05303284 smblib_set_opt_freq_buck(chg,
3285 chg->chg_freq.freq_9V);
Harry Yangcdad2bf2016-10-04 17:03:56 -07003286 break;
3287 case QC_12V_BIT:
Anirudh Ghayal4da3df92017-01-25 18:55:57 +05303288 smblib_set_opt_freq_buck(chg,
3289 chg->chg_freq.freq_12V);
Harry Yangcdad2bf2016-10-04 17:03:56 -07003290 break;
3291 default:
Anirudh Ghayal4da3df92017-01-25 18:55:57 +05303292 smblib_set_opt_freq_buck(chg,
3293 chg->chg_freq.freq_removal);
Harry Yangcdad2bf2016-10-04 17:03:56 -07003294 break;
3295 }
3296 }
3297
3298 if (chg->usb_psy_desc.type == POWER_SUPPLY_TYPE_USB_HVDCP_3) {
3299 rc = smblib_read(chg, QC_PULSE_COUNT_STATUS_REG, &stat);
3300 if (rc < 0) {
3301 smblib_err(chg,
3302 "Couldn't read QC_PULSE_COUNT rc=%d\n", rc);
3303 return;
3304 }
3305 pulses = (stat & QC_PULSE_COUNT_MASK);
3306
3307 if (pulses < QC3_PULSES_FOR_6V)
Anirudh Ghayal4da3df92017-01-25 18:55:57 +05303308 smblib_set_opt_freq_buck(chg,
3309 chg->chg_freq.freq_5V);
Harry Yangcdad2bf2016-10-04 17:03:56 -07003310 else if (pulses < QC3_PULSES_FOR_9V)
Anirudh Ghayal4da3df92017-01-25 18:55:57 +05303311 smblib_set_opt_freq_buck(chg,
3312 chg->chg_freq.freq_6V_8V);
Harry Yangcdad2bf2016-10-04 17:03:56 -07003313 else if (pulses < QC3_PULSES_FOR_12V)
Anirudh Ghayal4da3df92017-01-25 18:55:57 +05303314 smblib_set_opt_freq_buck(chg,
3315 chg->chg_freq.freq_9V);
Harry Yangcdad2bf2016-10-04 17:03:56 -07003316 else
Anirudh Ghayal4da3df92017-01-25 18:55:57 +05303317 smblib_set_opt_freq_buck(chg,
3318 chg->chg_freq.freq_12V);
Harry Yangcdad2bf2016-10-04 17:03:56 -07003319 }
3320}
3321
Nicholas Troast34db5032016-03-28 12:26:44 -07003322/* triggers when HVDCP 3.0 authentication has finished */
3323static void smblib_handle_hvdcp_3p0_auth_done(struct smb_charger *chg,
3324 bool rising)
3325{
3326 const struct apsd_result *apsd_result;
Harry Yangcdad2bf2016-10-04 17:03:56 -07003327 int rc;
Nicholas Troast34db5032016-03-28 12:26:44 -07003328
3329 if (!rising)
3330 return;
3331
Ashay Jaiswal67ec7072017-02-16 14:14:58 +05303332 if (chg->wa_flags & QC_AUTH_INTERRUPT_WA_BIT) {
3333 /*
3334 * Disable AUTH_IRQ_EN_CFG_BIT to receive adapter voltage
3335 * change interrupt.
3336 */
3337 rc = smblib_masked_write(chg,
3338 USBIN_SOURCE_CHANGE_INTRPT_ENB_REG,
3339 AUTH_IRQ_EN_CFG_BIT, 0);
3340 if (rc < 0)
3341 smblib_err(chg,
3342 "Couldn't enable QC auth setting rc=%d\n", rc);
3343 }
Harry Yangcdad2bf2016-10-04 17:03:56 -07003344
Harry Yangaba1f5f2016-09-28 10:47:29 -07003345 if (chg->mode == PARALLEL_MASTER)
3346 vote(chg->pl_enable_votable_indirect, USBIN_V_VOTER, true, 0);
3347
Ashay Jaiswalac854862017-03-06 23:58:55 +05303348 /* the APSD done handler will set the USB supply type */
3349 apsd_result = smblib_get_apsd_result(chg);
3350 if (get_effective_result(chg->hvdcp_hw_inov_dis_votable)) {
3351 if (apsd_result->pst == POWER_SUPPLY_TYPE_USB_HVDCP) {
3352 /* force HVDCP2 to 9V if INOV is disabled */
3353 rc = smblib_masked_write(chg, CMD_HVDCP_2_REG,
3354 FORCE_9V_BIT, FORCE_9V_BIT);
3355 if (rc < 0)
3356 smblib_err(chg,
3357 "Couldn't force 9V HVDCP rc=%d\n", rc);
3358 }
3359 }
3360
Ashay Jaiswal1829fcf2017-02-02 22:45:22 +05303361 /* QC authentication done, parallel charger can be enabled now */
Ashay Jaiswale38fe7e2017-02-13 11:42:19 +05303362 vote(chg->pl_disable_votable, PL_DELAY_HVDCP_VOTER, false, 0);
Ashay Jaiswal1829fcf2017-02-02 22:45:22 +05303363
Nicholas Troast34db5032016-03-28 12:26:44 -07003364 smblib_dbg(chg, PR_INTERRUPT, "IRQ: hvdcp-3p0-auth-done rising; %s detected\n",
3365 apsd_result->name);
3366}
3367
Harry Yang1369b7a2016-09-27 15:59:50 -07003368static void smblib_handle_hvdcp_check_timeout(struct smb_charger *chg,
3369 bool rising, bool qc_charger)
3370{
Abhijeet Dharmapurikar95670872017-02-09 22:55:51 +05303371 const struct apsd_result *apsd_result = smblib_update_usb_type(chg);
3372
Abhijeet Dharmapurikar4b13c6e2016-10-05 15:15:10 -07003373 /* Hold off PD only until hvdcp 2.0 detection timeout */
Abhijeet Dharmapurikar716cd962016-10-14 12:50:37 -07003374 if (rising) {
Abhijeet Dharmapurikar4b13c6e2016-10-05 15:15:10 -07003375 vote(chg->pd_disallowed_votable_indirect, HVDCP_TIMEOUT_VOTER,
Abhijeet Dharmapurikar716cd962016-10-14 12:50:37 -07003376 false, 0);
3377 if (get_effective_result(chg->pd_disallowed_votable_indirect))
3378 /* could be a legacy cable, try doing hvdcp */
3379 try_rerun_apsd_for_hvdcp(chg);
Abhijeet Dharmapurikar74021fc2017-02-06 18:39:19 -08003380
Harry Yang4bf7d962017-03-13 16:51:43 -07003381 /* enable HDC and ICL irq for QC2/3 charger */
3382 if (qc_charger)
3383 vote(chg->usb_irq_enable_votable, QC_VOTER, true, 0);
3384
Abhijeet Dharmapurikar74021fc2017-02-06 18:39:19 -08003385 /*
3386 * HVDCP detection timeout done
3387 * If adapter is not QC2.0/QC3.0 - it is a plain old DCP.
3388 */
3389 if (!qc_charger && (apsd_result->bit & DCP_CHARGER_BIT))
3390 /* enforce DCP ICL if specified */
3391 vote(chg->usb_icl_votable, DCP_VOTER,
3392 chg->dcp_icl_ua != -EINVAL, chg->dcp_icl_ua);
Ashay Jaiswal1829fcf2017-02-02 22:45:22 +05303393 /*
3394 * If adapter is not QC2.0/QC3.0 remove vote for parallel
3395 * disable.
3396 * Otherwise if adapter is QC2.0/QC3.0 wait for authentication
3397 * to complete.
3398 */
3399 if (!qc_charger)
Ashay Jaiswale38fe7e2017-02-13 11:42:19 +05303400 vote(chg->pl_disable_votable, PL_DELAY_HVDCP_VOTER,
Ashay Jaiswal1829fcf2017-02-02 22:45:22 +05303401 false, 0);
Abhijeet Dharmapurikar716cd962016-10-14 12:50:37 -07003402 }
Harry Yang1369b7a2016-09-27 15:59:50 -07003403
3404 smblib_dbg(chg, PR_INTERRUPT, "IRQ: smblib_handle_hvdcp_check_timeout %s\n",
3405 rising ? "rising" : "falling");
3406}
3407
Nicholas Troast34db5032016-03-28 12:26:44 -07003408/* triggers when HVDCP is detected */
3409static void smblib_handle_hvdcp_detect_done(struct smb_charger *chg,
3410 bool rising)
3411{
3412 if (!rising)
3413 return;
3414
3415 /* the APSD done handler will set the USB supply type */
3416 cancel_delayed_work_sync(&chg->hvdcp_detect_work);
3417 smblib_dbg(chg, PR_INTERRUPT, "IRQ: hvdcp-detect-done %s\n",
3418 rising ? "rising" : "falling");
3419}
3420
Nicholas Troastf9e44992017-03-14 09:06:56 -07003421static void smblib_force_legacy_icl(struct smb_charger *chg, int pst)
3422{
3423 switch (pst) {
3424 case POWER_SUPPLY_TYPE_USB:
3425 /*
3426 * USB_PSY will vote to increase the current to 500/900mA once
3427 * enumeration is done. Ensure that USB_PSY has at least voted
3428 * for 100mA before releasing the LEGACY_UNKNOWN vote
3429 */
3430 if (!is_client_vote_enabled(chg->usb_icl_votable,
3431 USB_PSY_VOTER))
3432 vote(chg->usb_icl_votable, USB_PSY_VOTER, true, 100000);
3433 vote(chg->usb_icl_votable, LEGACY_UNKNOWN_VOTER, false, 0);
3434 break;
3435 case POWER_SUPPLY_TYPE_USB_CDP:
3436 vote(chg->usb_icl_votable, LEGACY_UNKNOWN_VOTER, true, 1500000);
3437 break;
3438 case POWER_SUPPLY_TYPE_USB_DCP:
3439 vote(chg->usb_icl_votable, LEGACY_UNKNOWN_VOTER, true, 1500000);
3440 break;
3441 case POWER_SUPPLY_TYPE_USB_HVDCP:
3442 case POWER_SUPPLY_TYPE_USB_HVDCP_3:
3443 vote(chg->usb_icl_votable, LEGACY_UNKNOWN_VOTER, true, 3000000);
3444 break;
3445 default:
3446 smblib_err(chg, "Unknown APSD %d; forcing 500mA\n", pst);
3447 vote(chg->usb_icl_votable, LEGACY_UNKNOWN_VOTER, true, 500000);
3448 break;
3449 }
3450}
3451
Nicholas Troast34db5032016-03-28 12:26:44 -07003452#define HVDCP_DET_MS 2500
3453static void smblib_handle_apsd_done(struct smb_charger *chg, bool rising)
3454{
Nicholas Troast34db5032016-03-28 12:26:44 -07003455 const struct apsd_result *apsd_result;
3456
3457 if (!rising)
3458 return;
3459
Abhijeet Dharmapurikarb9598872016-10-17 16:58:58 -07003460 apsd_result = smblib_update_usb_type(chg);
Nicholas Troastf9e44992017-03-14 09:06:56 -07003461
3462 if (!chg->pd_active)
3463 smblib_force_legacy_icl(chg, apsd_result->pst);
3464
Nicholas Troast34db5032016-03-28 12:26:44 -07003465 switch (apsd_result->bit) {
3466 case SDP_CHARGER_BIT:
3467 case CDP_CHARGER_BIT:
Ashay Jaiswal4aa2c0c2016-12-07 19:39:38 +05303468 if (chg->micro_usb_mode)
3469 extcon_set_cable_state_(chg->extcon, EXTCON_USB,
3470 true);
Abhijeet Dharmapurikarbb9505f2017-03-22 18:31:28 -07003471 /* if not DCP then no hvdcp timeout happens. Enable pd here */
3472 vote(chg->pd_disallowed_votable_indirect, HVDCP_TIMEOUT_VOTER,
3473 false, 0);
3474 break;
Nicholas Troast34db5032016-03-28 12:26:44 -07003475 case OCP_CHARGER_BIT:
3476 case FLOAT_CHARGER_BIT:
Ashay Jaiswale38fe7e2017-02-13 11:42:19 +05303477 /*
3478 * if not DCP then no hvdcp timeout happens. Enable
3479 * pd/parallel here.
3480 */
Abhijeet Dharmapurikar4b13c6e2016-10-05 15:15:10 -07003481 vote(chg->pd_disallowed_votable_indirect, HVDCP_TIMEOUT_VOTER,
3482 false, 0);
Ashay Jaiswale38fe7e2017-02-13 11:42:19 +05303483 vote(chg->pl_disable_votable, PL_DELAY_HVDCP_VOTER, false, 0);
Nicholas Troast34db5032016-03-28 12:26:44 -07003484 break;
3485 case DCP_CHARGER_BIT:
Harry Yang1369b7a2016-09-27 15:59:50 -07003486 if (chg->wa_flags & QC_CHARGER_DETECTION_WA_BIT)
3487 schedule_delayed_work(&chg->hvdcp_detect_work,
3488 msecs_to_jiffies(HVDCP_DET_MS));
Nicholas Troast34db5032016-03-28 12:26:44 -07003489 break;
3490 default:
3491 break;
3492 }
3493
Nicholas Troast34db5032016-03-28 12:26:44 -07003494 smblib_dbg(chg, PR_INTERRUPT, "IRQ: apsd-done rising; %s detected\n",
3495 apsd_result->name);
3496}
3497
3498irqreturn_t smblib_handle_usb_source_change(int irq, void *data)
3499{
3500 struct smb_irq_data *irq_data = data;
3501 struct smb_charger *chg = irq_data->parent_data;
3502 int rc = 0;
3503 u8 stat;
3504
3505 rc = smblib_read(chg, APSD_STATUS_REG, &stat);
3506 if (rc < 0) {
Abhijeet Dharmapurikar31b98f32016-10-14 12:25:23 -07003507 smblib_err(chg, "Couldn't read APSD_STATUS rc=%d\n", rc);
Nicholas Troast34db5032016-03-28 12:26:44 -07003508 return IRQ_HANDLED;
3509 }
3510 smblib_dbg(chg, PR_REGISTER, "APSD_STATUS = 0x%02x\n", stat);
3511
3512 smblib_handle_apsd_done(chg,
3513 (bool)(stat & APSD_DTC_STATUS_DONE_BIT));
3514
3515 smblib_handle_hvdcp_detect_done(chg,
3516 (bool)(stat & QC_CHARGER_BIT));
3517
Harry Yang1369b7a2016-09-27 15:59:50 -07003518 smblib_handle_hvdcp_check_timeout(chg,
3519 (bool)(stat & HVDCP_CHECK_TIMEOUT_BIT),
3520 (bool)(stat & QC_CHARGER_BIT));
3521
Nicholas Troast34db5032016-03-28 12:26:44 -07003522 smblib_handle_hvdcp_3p0_auth_done(chg,
3523 (bool)(stat & QC_AUTH_DONE_STATUS_BIT));
3524
Nicholas Troast34db5032016-03-28 12:26:44 -07003525 smblib_handle_sdp_enumeration_done(chg,
3526 (bool)(stat & ENUMERATION_DONE_BIT));
3527
3528 smblib_handle_slow_plugin_timeout(chg,
3529 (bool)(stat & SLOW_PLUGIN_TIMEOUT_BIT));
3530
Harry Yangcdad2bf2016-10-04 17:03:56 -07003531 smblib_hvdcp_adaptive_voltage_change(chg);
3532
Nicholas Troast34db5032016-03-28 12:26:44 -07003533 power_supply_changed(chg->usb_psy);
3534
Abhijeet Dharmapurikar5e0bfbe2017-02-12 19:16:15 -08003535 rc = smblib_read(chg, APSD_STATUS_REG, &stat);
3536 if (rc < 0) {
3537 smblib_err(chg, "Couldn't read APSD_STATUS rc=%d\n", rc);
3538 return IRQ_HANDLED;
3539 }
3540 smblib_dbg(chg, PR_REGISTER, "APSD_STATUS = 0x%02x\n", stat);
3541
Nicholas Troast34db5032016-03-28 12:26:44 -07003542 return IRQ_HANDLED;
3543}
3544
Abhijeet Dharmapurikar99ca0452016-10-13 09:50:41 -07003545static void typec_source_removal(struct smb_charger *chg)
Nicholas Troast34db5032016-03-28 12:26:44 -07003546{
3547 int rc;
3548
Nicholas Troastf9e44992017-03-14 09:06:56 -07003549 /* reset legacy unknown vote */
3550 vote(chg->usb_icl_votable, LEGACY_UNKNOWN_VOTER, false, 0);
3551
Abhijeet Dharmapurikar99ca0452016-10-13 09:50:41 -07003552 /* reset both usbin current and voltage votes */
3553 vote(chg->pl_enable_votable_indirect, USBIN_I_VOTER, false, 0);
3554 vote(chg->pl_enable_votable_indirect, USBIN_V_VOTER, false, 0);
Nicholas Troast34db5032016-03-28 12:26:44 -07003555
Abhijeet Dharmapurikar99ca0452016-10-13 09:50:41 -07003556 cancel_delayed_work_sync(&chg->hvdcp_detect_work);
3557
Ashay Jaiswal67ec7072017-02-16 14:14:58 +05303558 if (chg->wa_flags & QC_AUTH_INTERRUPT_WA_BIT) {
3559 /* re-enable AUTH_IRQ_EN_CFG_BIT */
3560 rc = smblib_masked_write(chg,
3561 USBIN_SOURCE_CHANGE_INTRPT_ENB_REG,
3562 AUTH_IRQ_EN_CFG_BIT, AUTH_IRQ_EN_CFG_BIT);
3563 if (rc < 0)
3564 smblib_err(chg,
3565 "Couldn't enable QC auth setting rc=%d\n", rc);
3566 }
Harry Yangcdad2bf2016-10-04 17:03:56 -07003567
Abhijeet Dharmapurikar99ca0452016-10-13 09:50:41 -07003568 /* reconfigure allowed voltage for HVDCP */
Ashay Jaiswalb3101012017-03-01 10:18:04 +05303569 rc = smblib_set_adapter_allowance(chg,
3570 USBIN_ADAPTER_ALLOW_5V_OR_9V_TO_12V);
Abhijeet Dharmapurikar99ca0452016-10-13 09:50:41 -07003571 if (rc < 0)
Abhijeet Dharmapurikar31b98f32016-10-14 12:25:23 -07003572 smblib_err(chg, "Couldn't set USBIN_ADAPTER_ALLOW_5V_OR_9V_TO_12V rc=%d\n",
Abhijeet Dharmapurikar99ca0452016-10-13 09:50:41 -07003573 rc);
3574
3575 chg->voltage_min_uv = MICRO_5V;
3576 chg->voltage_max_uv = MICRO_5V;
3577
3578 /* clear USB ICL vote for PD_VOTER */
3579 rc = vote(chg->usb_icl_votable, PD_VOTER, false, 0);
3580 if (rc < 0)
Abhijeet Dharmapurikar95670872017-02-09 22:55:51 +05303581 smblib_err(chg, "Couldn't un-vote PD from USB ICL rc=%d\n", rc);
Abhijeet Dharmapurikard92eca62016-10-07 19:04:33 -07003582
3583 /* clear USB ICL vote for USB_PSY_VOTER */
3584 rc = vote(chg->usb_icl_votable, USB_PSY_VOTER, false, 0);
3585 if (rc < 0)
Abhijeet Dharmapurikar95670872017-02-09 22:55:51 +05303586 smblib_err(chg,
3587 "Couldn't un-vote USB_PSY from USB ICL rc=%d\n", rc);
3588
3589 /* clear USB ICL vote for DCP_VOTER */
3590 rc = vote(chg->usb_icl_votable, DCP_VOTER, false, 0);
3591 if (rc < 0)
3592 smblib_err(chg,
3593 "Couldn't un-vote DCP from USB ICL rc=%d\n", rc);
Abhijeet Dharmapurikar7442e422017-02-08 13:35:14 -08003594
3595 /* clear USB ICL vote for PL_USBIN_USBIN_VOTER */
3596 rc = vote(chg->usb_icl_votable, PL_USBIN_USBIN_VOTER, false, 0);
3597 if (rc < 0)
3598 smblib_err(chg,
3599 "Couldn't un-vote PL_USBIN_USBIN from USB ICL rc=%d\n",
3600 rc);
Nicholas Troast34db5032016-03-28 12:26:44 -07003601}
3602
Abhijeet Dharmapurikar99ca0452016-10-13 09:50:41 -07003603static void typec_source_insertion(struct smb_charger *chg)
Nicholas Troast34db5032016-03-28 12:26:44 -07003604{
Nicholas Troastf9e44992017-03-14 09:06:56 -07003605 /*
3606 * at any time we want LEGACY_UNKNOWN, PD, or USB_PSY to be voting for
3607 * ICL, so vote LEGACY_UNKNOWN here if none of the above three have
3608 * casted their votes
3609 */
3610 if (!is_client_vote_enabled(chg->usb_icl_votable, LEGACY_UNKNOWN_VOTER)
3611 && !is_client_vote_enabled(chg->usb_icl_votable, PD_VOTER)
3612 && !is_client_vote_enabled(chg->usb_icl_votable, USB_PSY_VOTER))
3613 vote(chg->usb_icl_votable, LEGACY_UNKNOWN_VOTER, true, 100000);
Abhijeet Dharmapurikar99ca0452016-10-13 09:50:41 -07003614}
Nicholas Troast34db5032016-03-28 12:26:44 -07003615
Abhijeet Dharmapurikar99ca0452016-10-13 09:50:41 -07003616static void typec_sink_insertion(struct smb_charger *chg)
3617{
3618 /* when a sink is inserted we should not wait on hvdcp timeout to
3619 * enable pd
3620 */
3621 vote(chg->pd_disallowed_votable_indirect, HVDCP_TIMEOUT_VOTER,
3622 false, 0);
3623}
Nicholas Troast34db5032016-03-28 12:26:44 -07003624
Harry Yangd89ff1f2016-12-05 14:59:11 -08003625static void typec_sink_removal(struct smb_charger *chg)
3626{
Anirudh Ghayal4da3df92017-01-25 18:55:57 +05303627 smblib_set_charge_param(chg, &chg->param.freq_boost,
3628 chg->chg_freq.freq_above_otg_threshold);
Harry Yangd89ff1f2016-12-05 14:59:11 -08003629 chg->boost_current_ua = 0;
3630}
3631
Abhijeet Dharmapurikar99ca0452016-10-13 09:50:41 -07003632static void smblib_handle_typec_removal(struct smb_charger *chg)
3633{
Nicholas Troastfe74c592017-03-14 09:20:55 -07003634 int rc;
3635
Abhijeet Dharmapurikar99ca0452016-10-13 09:50:41 -07003636 vote(chg->pd_disallowed_votable_indirect, CC_DETACHED_VOTER, true, 0);
3637 vote(chg->pd_disallowed_votable_indirect, HVDCP_TIMEOUT_VOTER, true, 0);
Ashay Jaiswale38fe7e2017-02-13 11:42:19 +05303638 vote(chg->pl_disable_votable, PL_DELAY_HVDCP_VOTER, true, 0);
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
3642 /* reset votes from vbus_cc_short */
Ashay Jaiswal4aa2c0c2016-12-07 19:39:38 +05303643 vote(chg->hvdcp_disable_votable_indirect, VBUS_CC_SHORT_VOTER,
3644 true, 0);
3645 vote(chg->hvdcp_disable_votable_indirect, PD_INACTIVE_VOTER,
3646 true, 0);
Harry Yang1d1034c2016-06-15 12:09:42 -07003647 /*
Abhijeet Dharmapurikar99ca0452016-10-13 09:50:41 -07003648 * cable could be removed during hard reset, remove its vote to
3649 * disable apsd
Harry Yang1d1034c2016-06-15 12:09:42 -07003650 */
Abhijeet Dharmapurikar99ca0452016-10-13 09:50:41 -07003651 vote(chg->apsd_disable_votable, PD_HARD_RESET_VOTER, false, 0);
Harry Yang1d1034c2016-06-15 12:09:42 -07003652
Nicholas Troast8995a702016-12-05 10:22:22 -08003653 chg->vconn_attempts = 0;
3654 chg->otg_attempts = 0;
Ashay Jaiswal6d308da2017-02-18 09:59:23 +05303655 chg->pulse_cnt = 0;
3656 chg->usb_icl_delta_ua = 0;
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 Troastfe74c592017-03-14 09:20:55 -07003664 smblib_update_usb_type(chg);
Abhijeet Dharmapurikar5e0bfbe2017-02-12 19:16:15 -08003665 typec_source_removal(chg);
3666 typec_sink_removal(chg);
Nicholas Troast34db5032016-03-28 12:26:44 -07003667}
3668
Abhijeet Dharmapurikar99ca0452016-10-13 09:50:41 -07003669static void smblib_handle_typec_insertion(struct smb_charger *chg,
3670 bool sink_attached, bool legacy_cable)
Abhijeet Dharmapurikara8075d72016-10-06 12:59:04 -07003671{
Nicholas Troastfe74c592017-03-14 09:20:55 -07003672 int rp, rc;
Abhijeet Dharmapurikara8075d72016-10-06 12:59:04 -07003673
Abhijeet Dharmapurikar99ca0452016-10-13 09:50:41 -07003674 vote(chg->pd_disallowed_votable_indirect, CC_DETACHED_VOTER, false, 0);
Abhijeet Dharmapurikara8075d72016-10-06 12:59:04 -07003675
Nicholas Troastfe74c592017-03-14 09:20:55 -07003676 /* disable APSD CC trigger since CC is attached */
3677 rc = smblib_masked_write(chg, TYPE_C_CFG_REG, APSD_START_ON_CC_BIT, 0);
3678 if (rc < 0)
3679 smblib_err(chg, "Couldn't disable APSD_START_ON_CC rc=%d\n",
3680 rc);
3681
Abhijeet Dharmapurikar99ca0452016-10-13 09:50:41 -07003682 if (sink_attached) {
3683 typec_source_removal(chg);
3684 typec_sink_insertion(chg);
3685 } else {
3686 typec_source_insertion(chg);
Harry Yangd89ff1f2016-12-05 14:59:11 -08003687 typec_sink_removal(chg);
Abhijeet Dharmapurikara8075d72016-10-06 12:59:04 -07003688 }
3689
Nicholas Troastfe1a8452017-03-14 08:20:31 -07003690 rp = smblib_get_prop_ufp_mode(chg);
3691 if (rp == POWER_SUPPLY_TYPEC_SOURCE_HIGH
3692 || rp == POWER_SUPPLY_TYPEC_NON_COMPLIANT) {
3693 smblib_dbg(chg, PR_MISC, "VBUS & CC could be shorted; keeping HVDCP disabled\n");
3694 /* HVDCP is not going to be enabled; enable parallel */
3695 vote(chg->pl_disable_votable, PL_DELAY_HVDCP_VOTER, false, 0);
3696 vote(chg->hvdcp_disable_votable_indirect, VBUS_CC_SHORT_VOTER,
3697 true, 0);
3698 } else {
3699 vote(chg->hvdcp_disable_votable_indirect, VBUS_CC_SHORT_VOTER,
3700 false, 0);
Abhijeet Dharmapurikara8075d72016-10-06 12:59:04 -07003701 }
Abhijeet Dharmapurikara8075d72016-10-06 12:59:04 -07003702}
3703
Abhijeet Dharmapurikar99ca0452016-10-13 09:50:41 -07003704static void smblib_handle_typec_debounce_done(struct smb_charger *chg,
3705 bool rising, bool sink_attached, bool legacy_cable)
3706{
3707 int rc;
3708 union power_supply_propval pval = {0, };
3709
3710 if (rising)
3711 smblib_handle_typec_insertion(chg, sink_attached, legacy_cable);
3712 else
3713 smblib_handle_typec_removal(chg);
3714
3715 rc = smblib_get_prop_typec_mode(chg, &pval);
3716 if (rc < 0)
Abhijeet Dharmapurikar31b98f32016-10-14 12:25:23 -07003717 smblib_err(chg, "Couldn't get prop typec mode rc=%d\n", rc);
Abhijeet Dharmapurikar99ca0452016-10-13 09:50:41 -07003718
Harry Yang86e4d852016-11-07 15:08:47 -08003719 /*
3720 * HW BUG - after cable is removed, medium or high rd reading
3721 * falls to std. Use it for signal of typec cc detachment in
3722 * software WA.
3723 */
3724 if (chg->cc2_sink_detach_flag == CC2_SINK_MEDIUM_HIGH
3725 && pval.intval == POWER_SUPPLY_TYPEC_SOURCE_DEFAULT) {
3726
3727 chg->cc2_sink_detach_flag = CC2_SINK_WA_DONE;
3728
3729 rc = smblib_masked_write(chg,
3730 TYPE_C_INTRPT_ENB_SOFTWARE_CTRL_REG,
3731 EXIT_SNK_BASED_ON_CC_BIT, 0);
3732 if (rc < 0)
3733 smblib_err(chg, "Couldn't get prop typec mode rc=%d\n",
3734 rc);
3735 }
3736
Abhijeet Dharmapurikar99ca0452016-10-13 09:50:41 -07003737 smblib_dbg(chg, PR_INTERRUPT, "IRQ: debounce-done %s; Type-C %s detected\n",
3738 rising ? "rising" : "falling",
3739 smblib_typec_mode_name[pval.intval]);
3740}
3741
Ashay Jaiswal4aa2c0c2016-12-07 19:39:38 +05303742irqreturn_t smblib_handle_usb_typec_change_for_uusb(struct smb_charger *chg)
3743{
3744 int rc;
3745 u8 stat;
3746
3747 rc = smblib_read(chg, TYPE_C_STATUS_3_REG, &stat);
3748 if (rc < 0) {
3749 smblib_err(chg, "Couldn't read TYPE_C_STATUS_3 rc=%d\n", rc);
3750 return IRQ_HANDLED;
3751 }
3752 smblib_dbg(chg, PR_REGISTER, "TYPE_C_STATUS_3 = 0x%02x OTG=%d\n",
3753 stat, !!(stat & (U_USB_GND_NOVBUS_BIT | U_USB_GND_BIT)));
3754
3755 extcon_set_cable_state_(chg->extcon, EXTCON_USB_HOST,
3756 !!(stat & (U_USB_GND_NOVBUS_BIT | U_USB_GND_BIT)));
3757 power_supply_changed(chg->usb_psy);
3758
3759 return IRQ_HANDLED;
3760}
3761
Nicholas Troast34db5032016-03-28 12:26:44 -07003762irqreturn_t smblib_handle_usb_typec_change(int irq, void *data)
3763{
3764 struct smb_irq_data *irq_data = data;
3765 struct smb_charger *chg = irq_data->parent_data;
3766 int rc;
Nicholas Troastb1486552016-11-10 08:20:11 -08003767 u8 stat4, stat5;
Abhijeet Dharmapurikar99ca0452016-10-13 09:50:41 -07003768 bool debounce_done, sink_attached, legacy_cable;
Nicholas Troast34db5032016-03-28 12:26:44 -07003769
Ashay Jaiswal4aa2c0c2016-12-07 19:39:38 +05303770 if (chg->micro_usb_mode)
3771 return smblib_handle_usb_typec_change_for_uusb(chg);
3772
Harry Yang755a34b2016-11-01 01:18:51 -07003773 /* WA - not when PD hard_reset WIP on cc2 in sink mode */
3774 if (chg->cc2_sink_detach_flag == CC2_SINK_STD)
3775 return IRQ_HANDLED;
3776
Nicholas Troastb1486552016-11-10 08:20:11 -08003777 rc = smblib_read(chg, TYPE_C_STATUS_4_REG, &stat4);
Nicholas Troast34db5032016-03-28 12:26:44 -07003778 if (rc < 0) {
Abhijeet Dharmapurikar31b98f32016-10-14 12:25:23 -07003779 smblib_err(chg, "Couldn't read TYPE_C_STATUS_4 rc=%d\n", rc);
Nicholas Troast34db5032016-03-28 12:26:44 -07003780 return IRQ_HANDLED;
3781 }
Nicholas Troast34db5032016-03-28 12:26:44 -07003782
Nicholas Troastb1486552016-11-10 08:20:11 -08003783 rc = smblib_read(chg, TYPE_C_STATUS_5_REG, &stat5);
Abhijeet Dharmapurikar99ca0452016-10-13 09:50:41 -07003784 if (rc < 0) {
Abhijeet Dharmapurikar31b98f32016-10-14 12:25:23 -07003785 smblib_err(chg, "Couldn't read TYPE_C_STATUS_5 rc=%d\n", rc);
Abhijeet Dharmapurikar99ca0452016-10-13 09:50:41 -07003786 return IRQ_HANDLED;
3787 }
Nicholas Troastb1486552016-11-10 08:20:11 -08003788
3789 debounce_done = (bool)(stat4 & TYPEC_DEBOUNCE_DONE_STATUS_BIT);
3790 sink_attached = (bool)(stat4 & UFP_DFP_MODE_STATUS_BIT);
3791 legacy_cable = (bool)(stat5 & TYPEC_LEGACY_CABLE_STATUS_BIT);
Abhijeet Dharmapurikar99ca0452016-10-13 09:50:41 -07003792
Nicholas Troast34db5032016-03-28 12:26:44 -07003793 smblib_handle_typec_debounce_done(chg,
Abhijeet Dharmapurikar99ca0452016-10-13 09:50:41 -07003794 debounce_done, sink_attached, legacy_cable);
Nicholas Troast34db5032016-03-28 12:26:44 -07003795
Nicholas Troastb1486552016-11-10 08:20:11 -08003796 if (stat4 & TYPEC_VBUS_ERROR_STATUS_BIT)
Harry Yangd757c0f2016-09-23 10:52:05 -07003797 smblib_dbg(chg, PR_INTERRUPT, "IRQ: %s vbus-error\n",
Ashay Jaiswal4aa2c0c2016-12-07 19:39:38 +05303798 irq_data->name);
Harry Yangd757c0f2016-09-23 10:52:05 -07003799
Nicholas Troast8995a702016-12-05 10:22:22 -08003800 if (stat4 & TYPEC_VCONN_OVERCURR_STATUS_BIT)
Nicholas Troastb11015f2017-01-17 17:56:45 -08003801 schedule_work(&chg->vconn_oc_work);
Nicholas Troast8995a702016-12-05 10:22:22 -08003802
Nicholas Troastb1486552016-11-10 08:20:11 -08003803 power_supply_changed(chg->usb_psy);
3804 smblib_dbg(chg, PR_REGISTER, "TYPE_C_STATUS_4 = 0x%02x\n", stat4);
3805 smblib_dbg(chg, PR_REGISTER, "TYPE_C_STATUS_5 = 0x%02x\n", stat5);
Nicholas Troast34db5032016-03-28 12:26:44 -07003806 return IRQ_HANDLED;
3807}
3808
Abhijeet Dharmapurikar23916642016-10-03 10:38:50 -07003809irqreturn_t smblib_handle_dc_plugin(int irq, void *data)
3810{
3811 struct smb_irq_data *irq_data = data;
3812 struct smb_charger *chg = irq_data->parent_data;
3813
3814 power_supply_changed(chg->dc_psy);
3815 return IRQ_HANDLED;
3816}
3817
Abhijeet Dharmapurikar0e369002016-09-07 17:25:36 -07003818irqreturn_t smblib_handle_high_duty_cycle(int irq, void *data)
3819{
3820 struct smb_irq_data *irq_data = data;
3821 struct smb_charger *chg = irq_data->parent_data;
3822
3823 chg->is_hdc = true;
3824 schedule_delayed_work(&chg->clear_hdc_work, msecs_to_jiffies(60));
3825
3826 return IRQ_HANDLED;
3827}
3828
Nicholas Troastabedaf72016-09-16 11:07:45 -07003829irqreturn_t smblib_handle_switcher_power_ok(int irq, void *data)
3830{
3831 struct smb_irq_data *irq_data = data;
3832 struct smb_charger *chg = irq_data->parent_data;
3833 int rc;
3834 u8 stat;
3835
3836 if (!(chg->wa_flags & BOOST_BACK_WA))
3837 return IRQ_HANDLED;
3838
3839 rc = smblib_read(chg, POWER_PATH_STATUS_REG, &stat);
3840 if (rc < 0) {
3841 smblib_err(chg, "Couldn't read POWER_PATH_STATUS rc=%d\n", rc);
3842 return IRQ_HANDLED;
3843 }
3844
3845 if ((stat & USE_USBIN_BIT) &&
Abhijeet Dharmapurikar5e0bfbe2017-02-12 19:16:15 -08003846 get_effective_result(chg->usb_icl_votable) < USBIN_25MA)
Nicholas Troastabedaf72016-09-16 11:07:45 -07003847 return IRQ_HANDLED;
3848
Abhijeet Dharmapurikar2823fe32016-12-05 17:52:11 -08003849 if (stat & USE_DCIN_BIT)
Nicholas Troastabedaf72016-09-16 11:07:45 -07003850 return IRQ_HANDLED;
3851
3852 if (is_storming(&irq_data->storm_data)) {
Abhijeet Dharmapurikar5e0bfbe2017-02-12 19:16:15 -08003853 smblib_err(chg, "Reverse boost detected: voting 0mA to suspend input\n");
3854 vote(chg->usb_icl_votable, BOOST_BACK_VOTER, true, 0);
Nicholas Troastabedaf72016-09-16 11:07:45 -07003855 }
3856
3857 return IRQ_HANDLED;
3858}
3859
Nicholas Troast15dc0c82016-10-18 15:15:21 -07003860irqreturn_t smblib_handle_wdog_bark(int irq, void *data)
3861{
3862 struct smb_irq_data *irq_data = data;
3863 struct smb_charger *chg = irq_data->parent_data;
3864 int rc;
3865
3866 rc = smblib_write(chg, BARK_BITE_WDOG_PET_REG, BARK_BITE_WDOG_PET_BIT);
3867 if (rc < 0)
3868 smblib_err(chg, "Couldn't pet the dog rc=%d\n", rc);
3869
3870 return IRQ_HANDLED;
3871}
3872
Nicholas Troast34db5032016-03-28 12:26:44 -07003873/***************
3874 * Work Queues *
3875 ***************/
3876
3877static void smblib_hvdcp_detect_work(struct work_struct *work)
3878{
3879 struct smb_charger *chg = container_of(work, struct smb_charger,
3880 hvdcp_detect_work.work);
Nicholas Troast34db5032016-03-28 12:26:44 -07003881
Abhijeet Dharmapurikar4b13c6e2016-10-05 15:15:10 -07003882 vote(chg->pd_disallowed_votable_indirect, HVDCP_TIMEOUT_VOTER,
3883 false, 0);
Abhijeet Dharmapurikar716cd962016-10-14 12:50:37 -07003884 if (get_effective_result(chg->pd_disallowed_votable_indirect))
3885 /* pd is still disabled, try hvdcp */
3886 try_rerun_apsd_for_hvdcp(chg);
3887 else
3888 /* notify pd now that pd is allowed */
3889 power_supply_changed(chg->usb_psy);
Nicholas Troast34db5032016-03-28 12:26:44 -07003890}
3891
Harry Yangfe913842016-08-10 12:27:28 -07003892static void bms_update_work(struct work_struct *work)
Harry Yang5e1a5222016-07-26 15:16:04 -07003893{
3894 struct smb_charger *chg = container_of(work, struct smb_charger,
3895 bms_update_work);
Ashay Jaiswal2fb369d2017-01-12 21:38:29 +05303896
3897 smblib_suspend_on_debug_battery(chg);
3898
3899 if (chg->batt_psy)
3900 power_supply_changed(chg->batt_psy);
Harry Yang5e1a5222016-07-26 15:16:04 -07003901}
3902
Harry Yangfe913842016-08-10 12:27:28 -07003903static void step_soc_req_work(struct work_struct *work)
3904{
3905 struct smb_charger *chg = container_of(work, struct smb_charger,
3906 step_soc_req_work.work);
3907 union power_supply_propval pval = {0, };
3908 int rc;
3909
3910 rc = smblib_get_prop_batt_capacity(chg, &pval);
3911 if (rc < 0) {
Abhijeet Dharmapurikar31b98f32016-10-14 12:25:23 -07003912 smblib_err(chg, "Couldn't get batt capacity rc=%d\n", rc);
Harry Yangfe913842016-08-10 12:27:28 -07003913 return;
3914 }
3915
3916 step_charge_soc_update(chg, pval.intval);
3917}
3918
Abhijeet Dharmapurikar0e369002016-09-07 17:25:36 -07003919static void clear_hdc_work(struct work_struct *work)
3920{
3921 struct smb_charger *chg = container_of(work, struct smb_charger,
3922 clear_hdc_work.work);
3923
3924 chg->is_hdc = 0;
3925}
3926
Harry Yang755a34b2016-11-01 01:18:51 -07003927static void rdstd_cc2_detach_work(struct work_struct *work)
3928{
3929 int rc;
3930 u8 stat;
3931 struct smb_irq_data irq_data = {NULL, "cc2-removal-workaround"};
3932 struct smb_charger *chg = container_of(work, struct smb_charger,
3933 rdstd_cc2_detach_work);
3934
3935 /*
3936 * WA steps -
3937 * 1. Enable both UFP and DFP, wait for 10ms.
3938 * 2. Disable DFP, wait for 30ms.
3939 * 3. Removal detected if both TYPEC_DEBOUNCE_DONE_STATUS
3940 * and TIMER_STAGE bits are gone, otherwise repeat all by
3941 * work rescheduling.
3942 * Note, work will be cancelled when pd_hard_reset is 0.
3943 */
3944
3945 rc = smblib_masked_write(chg, TYPE_C_INTRPT_ENB_SOFTWARE_CTRL_REG,
3946 UFP_EN_CMD_BIT | DFP_EN_CMD_BIT,
3947 UFP_EN_CMD_BIT | DFP_EN_CMD_BIT);
3948 if (rc < 0) {
3949 smblib_err(chg, "Couldn't write TYPE_C_CTRL_REG rc=%d\n", rc);
3950 return;
3951 }
3952
3953 usleep_range(10000, 11000);
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);
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(30000, 31000);
3964
3965 rc = smblib_read(chg, TYPE_C_STATUS_4_REG, &stat);
3966 if (rc < 0) {
3967 smblib_err(chg, "Couldn't read TYPE_C_STATUS_4 rc=%d\n",
3968 rc);
3969 return;
3970 }
3971 if (stat & TYPEC_DEBOUNCE_DONE_STATUS_BIT)
3972 goto rerun;
3973
3974 rc = smblib_read(chg, TYPE_C_STATUS_5_REG, &stat);
3975 if (rc < 0) {
3976 smblib_err(chg,
3977 "Couldn't read TYPE_C_STATUS_5_REG rc=%d\n", rc);
3978 return;
3979 }
3980 if (stat & TIMER_STAGE_2_BIT)
3981 goto rerun;
3982
3983 /* Bingo, cc2 removal detected */
3984 smblib_reg_block_restore(chg, cc2_detach_settings);
3985 chg->cc2_sink_detach_flag = CC2_SINK_WA_DONE;
3986 irq_data.parent_data = chg;
3987 smblib_handle_usb_typec_change(0, &irq_data);
3988
3989 return;
3990
3991rerun:
3992 schedule_work(&chg->rdstd_cc2_detach_work);
3993}
3994
Nicholas Troastb11015f2017-01-17 17:56:45 -08003995static void smblib_otg_oc_exit(struct smb_charger *chg, bool success)
3996{
3997 int rc;
3998
3999 chg->otg_attempts = 0;
4000 if (!success) {
4001 smblib_err(chg, "OTG soft start failed\n");
4002 chg->otg_en = false;
4003 }
4004
4005 smblib_dbg(chg, PR_OTG, "enabling VBUS < 1V check\n");
4006 rc = smblib_masked_write(chg, OTG_CFG_REG,
4007 QUICKSTART_OTG_FASTROLESWAP_BIT, 0);
4008 if (rc < 0)
4009 smblib_err(chg, "Couldn't enable VBUS < 1V check rc=%d\n", rc);
4010
4011 if (!chg->external_vconn && chg->vconn_en) {
4012 chg->vconn_attempts = 0;
4013 if (success) {
4014 rc = _smblib_vconn_regulator_enable(
4015 chg->vconn_vreg->rdev);
4016 if (rc < 0)
4017 smblib_err(chg, "Couldn't enable VCONN rc=%d\n",
4018 rc);
4019 } else {
4020 chg->vconn_en = false;
4021 }
4022 }
4023}
4024
4025#define MAX_OC_FALLING_TRIES 10
4026static void smblib_otg_oc_work(struct work_struct *work)
4027{
4028 struct smb_charger *chg = container_of(work, struct smb_charger,
4029 otg_oc_work);
4030 int rc, i;
4031 u8 stat;
4032
4033 if (!chg->vbus_vreg || !chg->vbus_vreg->rdev)
4034 return;
4035
4036 smblib_err(chg, "over-current detected on VBUS\n");
4037 mutex_lock(&chg->otg_oc_lock);
4038 if (!chg->otg_en)
4039 goto unlock;
4040
4041 smblib_dbg(chg, PR_OTG, "disabling VBUS < 1V check\n");
4042 smblib_masked_write(chg, OTG_CFG_REG,
4043 QUICKSTART_OTG_FASTROLESWAP_BIT,
4044 QUICKSTART_OTG_FASTROLESWAP_BIT);
4045
4046 /*
4047 * If 500ms has passed and another over-current interrupt has not
4048 * triggered then it is likely that the software based soft start was
4049 * successful and the VBUS < 1V restriction should be re-enabled.
4050 */
4051 schedule_delayed_work(&chg->otg_ss_done_work, msecs_to_jiffies(500));
4052
4053 rc = _smblib_vbus_regulator_disable(chg->vbus_vreg->rdev);
4054 if (rc < 0) {
4055 smblib_err(chg, "Couldn't disable VBUS rc=%d\n", rc);
4056 goto unlock;
4057 }
4058
4059 if (++chg->otg_attempts > OTG_MAX_ATTEMPTS) {
4060 cancel_delayed_work_sync(&chg->otg_ss_done_work);
4061 smblib_err(chg, "OTG failed to enable after %d attempts\n",
4062 chg->otg_attempts - 1);
4063 smblib_otg_oc_exit(chg, false);
4064 goto unlock;
4065 }
4066
4067 /*
4068 * The real time status should go low within 10ms. Poll every 1-2ms to
4069 * minimize the delay when re-enabling OTG.
4070 */
4071 for (i = 0; i < MAX_OC_FALLING_TRIES; ++i) {
4072 usleep_range(1000, 2000);
4073 rc = smblib_read(chg, OTG_BASE + INT_RT_STS_OFFSET, &stat);
4074 if (rc >= 0 && !(stat & OTG_OVERCURRENT_RT_STS_BIT))
4075 break;
4076 }
4077
4078 if (i >= MAX_OC_FALLING_TRIES) {
4079 cancel_delayed_work_sync(&chg->otg_ss_done_work);
4080 smblib_err(chg, "OTG OC did not fall after %dms\n",
4081 2 * MAX_OC_FALLING_TRIES);
4082 smblib_otg_oc_exit(chg, false);
4083 goto unlock;
4084 }
4085
4086 smblib_dbg(chg, PR_OTG, "OTG OC fell after %dms\n", 2 * i + 1);
4087 rc = _smblib_vbus_regulator_enable(chg->vbus_vreg->rdev);
4088 if (rc < 0) {
4089 smblib_err(chg, "Couldn't enable VBUS rc=%d\n", rc);
4090 goto unlock;
4091 }
4092
4093unlock:
4094 mutex_unlock(&chg->otg_oc_lock);
4095}
4096
4097static void smblib_vconn_oc_work(struct work_struct *work)
4098{
4099 struct smb_charger *chg = container_of(work, struct smb_charger,
4100 vconn_oc_work);
4101 int rc, i;
4102 u8 stat;
4103
4104 smblib_err(chg, "over-current detected on VCONN\n");
4105 if (!chg->vconn_vreg || !chg->vconn_vreg->rdev)
4106 return;
4107
4108 mutex_lock(&chg->otg_oc_lock);
4109 rc = _smblib_vconn_regulator_disable(chg->vconn_vreg->rdev);
4110 if (rc < 0) {
4111 smblib_err(chg, "Couldn't disable VCONN rc=%d\n", rc);
4112 goto unlock;
4113 }
4114
4115 if (++chg->vconn_attempts > VCONN_MAX_ATTEMPTS) {
4116 smblib_err(chg, "VCONN failed to enable after %d attempts\n",
4117 chg->otg_attempts - 1);
4118 chg->vconn_en = false;
4119 chg->vconn_attempts = 0;
4120 goto unlock;
4121 }
4122
4123 /*
4124 * The real time status should go low within 10ms. Poll every 1-2ms to
4125 * minimize the delay when re-enabling OTG.
4126 */
4127 for (i = 0; i < MAX_OC_FALLING_TRIES; ++i) {
4128 usleep_range(1000, 2000);
4129 rc = smblib_read(chg, TYPE_C_STATUS_4_REG, &stat);
4130 if (rc >= 0 && !(stat & TYPEC_VCONN_OVERCURR_STATUS_BIT))
4131 break;
4132 }
4133
4134 if (i >= MAX_OC_FALLING_TRIES) {
4135 smblib_err(chg, "VCONN OC did not fall after %dms\n",
4136 2 * MAX_OC_FALLING_TRIES);
4137 chg->vconn_en = false;
4138 chg->vconn_attempts = 0;
4139 goto unlock;
4140 }
4141
4142 smblib_dbg(chg, PR_OTG, "VCONN OC fell after %dms\n", 2 * i + 1);
4143 if (++chg->vconn_attempts > VCONN_MAX_ATTEMPTS) {
4144 smblib_err(chg, "VCONN failed to enable after %d attempts\n",
4145 chg->vconn_attempts - 1);
4146 chg->vconn_en = false;
4147 goto unlock;
4148 }
4149
4150 rc = _smblib_vconn_regulator_enable(chg->vconn_vreg->rdev);
4151 if (rc < 0) {
4152 smblib_err(chg, "Couldn't enable VCONN rc=%d\n", rc);
4153 goto unlock;
4154 }
4155
4156unlock:
4157 mutex_unlock(&chg->otg_oc_lock);
4158}
4159
4160static void smblib_otg_ss_done_work(struct work_struct *work)
4161{
4162 struct smb_charger *chg = container_of(work, struct smb_charger,
4163 otg_ss_done_work.work);
4164 int rc;
4165 bool success = false;
4166 u8 stat;
4167
4168 mutex_lock(&chg->otg_oc_lock);
4169 rc = smblib_read(chg, OTG_STATUS_REG, &stat);
4170 if (rc < 0)
4171 smblib_err(chg, "Couldn't read OTG status rc=%d\n", rc);
4172 else if (stat & BOOST_SOFTSTART_DONE_BIT)
4173 success = true;
4174
4175 smblib_otg_oc_exit(chg, success);
4176 mutex_unlock(&chg->otg_oc_lock);
4177}
4178
Ashay Jaiswal4d825782017-02-18 10:11:34 +05304179static void smblib_icl_change_work(struct work_struct *work)
4180{
4181 struct smb_charger *chg = container_of(work, struct smb_charger,
4182 icl_change_work.work);
4183 int rc, settled_ua;
4184
4185 rc = smblib_get_charge_param(chg, &chg->param.icl_stat, &settled_ua);
4186 if (rc < 0) {
4187 smblib_err(chg, "Couldn't get ICL status rc=%d\n", rc);
4188 return;
4189 }
4190
4191 power_supply_changed(chg->usb_main_psy);
4192 vote(chg->pl_enable_votable_indirect, USBIN_I_VOTER,
4193 settled_ua >= USB_WEAK_INPUT_UA, 0);
4194
4195 smblib_dbg(chg, PR_INTERRUPT, "icl_settled=%d\n", settled_ua);
4196}
4197
Harry Yangba874ce2016-08-19 14:17:01 -07004198static int smblib_create_votables(struct smb_charger *chg)
Nicholas Troast34db5032016-03-28 12:26:44 -07004199{
4200 int rc = 0;
4201
Ashay Jaiswal37b8ea62017-02-03 11:37:28 +05304202 chg->fcc_votable = find_votable("FCC");
4203 if (!chg->fcc_votable) {
4204 rc = -EPROBE_DEFER;
4205 return rc;
4206 }
4207
4208 chg->fv_votable = find_votable("FV");
4209 if (!chg->fv_votable) {
4210 rc = -EPROBE_DEFER;
4211 return rc;
4212 }
4213
4214 chg->pl_disable_votable = find_votable("PL_DISABLE");
4215 if (!chg->pl_disable_votable) {
4216 rc = -EPROBE_DEFER;
4217 return rc;
4218 }
4219 vote(chg->pl_disable_votable, PL_INDIRECT_VOTER, true, 0);
Ashay Jaiswale38fe7e2017-02-13 11:42:19 +05304220 vote(chg->pl_disable_votable, PL_DELAY_HVDCP_VOTER, true, 0);
Ashay Jaiswal37b8ea62017-02-03 11:37:28 +05304221
Abhijeet Dharmapurikar8e9e7572016-06-06 16:13:14 -07004222 chg->dc_suspend_votable = create_votable("DC_SUSPEND", VOTE_SET_ANY,
4223 smblib_dc_suspend_vote_callback,
4224 chg);
Nicholas Troast34db5032016-03-28 12:26:44 -07004225 if (IS_ERR(chg->dc_suspend_votable)) {
4226 rc = PTR_ERR(chg->dc_suspend_votable);
4227 return rc;
4228 }
4229
Abhijeet Dharmapurikar8e9e7572016-06-06 16:13:14 -07004230 chg->usb_icl_votable = create_votable("USB_ICL", VOTE_MIN,
4231 smblib_usb_icl_vote_callback,
4232 chg);
Nicholas Troast34db5032016-03-28 12:26:44 -07004233 if (IS_ERR(chg->usb_icl_votable)) {
4234 rc = PTR_ERR(chg->usb_icl_votable);
4235 return rc;
4236 }
4237
Abhijeet Dharmapurikar8e9e7572016-06-06 16:13:14 -07004238 chg->dc_icl_votable = create_votable("DC_ICL", VOTE_MIN,
4239 smblib_dc_icl_vote_callback,
4240 chg);
Nicholas Troast34db5032016-03-28 12:26:44 -07004241 if (IS_ERR(chg->dc_icl_votable)) {
4242 rc = PTR_ERR(chg->dc_icl_votable);
4243 return rc;
4244 }
4245
Abhijeet Dharmapurikar4b13c6e2016-10-05 15:15:10 -07004246 chg->pd_disallowed_votable_indirect
4247 = create_votable("PD_DISALLOWED_INDIRECT", VOTE_SET_ANY,
4248 smblib_pd_disallowed_votable_indirect_callback, chg);
4249 if (IS_ERR(chg->pd_disallowed_votable_indirect)) {
4250 rc = PTR_ERR(chg->pd_disallowed_votable_indirect);
4251 return rc;
4252 }
4253
4254 chg->pd_allowed_votable = create_votable("PD_ALLOWED",
4255 VOTE_SET_ANY, NULL, NULL);
Nicholas Troast34db5032016-03-28 12:26:44 -07004256 if (IS_ERR(chg->pd_allowed_votable)) {
4257 rc = PTR_ERR(chg->pd_allowed_votable);
4258 return rc;
4259 }
4260
Harry Yang223c6282016-06-14 15:48:36 -07004261 chg->awake_votable = create_votable("AWAKE", VOTE_SET_ANY,
4262 smblib_awake_vote_callback,
4263 chg);
4264 if (IS_ERR(chg->awake_votable)) {
4265 rc = PTR_ERR(chg->awake_votable);
4266 return rc;
4267 }
4268
Abhijeet Dharmapurikaree54de02016-07-08 14:51:47 -07004269 chg->chg_disable_votable = create_votable("CHG_DISABLE", VOTE_SET_ANY,
4270 smblib_chg_disable_vote_callback,
4271 chg);
4272 if (IS_ERR(chg->chg_disable_votable)) {
4273 rc = PTR_ERR(chg->chg_disable_votable);
4274 return rc;
4275 }
4276
Harry Yangaba1f5f2016-09-28 10:47:29 -07004277 chg->pl_enable_votable_indirect = create_votable("PL_ENABLE_INDIRECT",
4278 VOTE_SET_ANY,
4279 smblib_pl_enable_indirect_vote_callback,
4280 chg);
4281 if (IS_ERR(chg->pl_enable_votable_indirect)) {
4282 rc = PTR_ERR(chg->pl_enable_votable_indirect);
4283 return rc;
4284 }
4285
Ashay Jaiswal4aa2c0c2016-12-07 19:39:38 +05304286 chg->hvdcp_disable_votable_indirect = create_votable(
4287 "HVDCP_DISABLE_INDIRECT",
4288 VOTE_SET_ANY,
4289 smblib_hvdcp_disable_indirect_vote_callback,
4290 chg);
4291 if (IS_ERR(chg->hvdcp_disable_votable_indirect)) {
4292 rc = PTR_ERR(chg->hvdcp_disable_votable_indirect);
4293 return rc;
4294 }
4295
4296 chg->hvdcp_enable_votable = create_votable("HVDCP_ENABLE",
Abhijeet Dharmapurikarf0b0a042016-10-10 16:43:43 -07004297 VOTE_SET_ANY,
Ashay Jaiswal4aa2c0c2016-12-07 19:39:38 +05304298 smblib_hvdcp_enable_vote_callback,
Abhijeet Dharmapurikarf0b0a042016-10-10 16:43:43 -07004299 chg);
Ashay Jaiswal4aa2c0c2016-12-07 19:39:38 +05304300 if (IS_ERR(chg->hvdcp_enable_votable)) {
4301 rc = PTR_ERR(chg->hvdcp_enable_votable);
Abhijeet Dharmapurikarf0b0a042016-10-10 16:43:43 -07004302 return rc;
4303 }
Abhijeet Dharmapurikarf8a7a4a2016-10-07 18:46:45 -07004304
4305 chg->apsd_disable_votable = create_votable("APSD_DISABLE",
4306 VOTE_SET_ANY,
4307 smblib_apsd_disable_vote_callback,
4308 chg);
4309 if (IS_ERR(chg->apsd_disable_votable)) {
4310 rc = PTR_ERR(chg->apsd_disable_votable);
4311 return rc;
4312 }
4313
Ashay Jaiswal6d308da2017-02-18 09:59:23 +05304314 chg->hvdcp_hw_inov_dis_votable = create_votable("HVDCP_HW_INOV_DIS",
4315 VOTE_SET_ANY,
4316 smblib_hvdcp_hw_inov_dis_vote_callback,
4317 chg);
4318 if (IS_ERR(chg->hvdcp_hw_inov_dis_votable)) {
4319 rc = PTR_ERR(chg->hvdcp_hw_inov_dis_votable);
4320 return rc;
4321 }
4322
Harry Yang4bf7d962017-03-13 16:51:43 -07004323 chg->usb_irq_enable_votable = create_votable("USB_IRQ_DISABLE",
4324 VOTE_SET_ANY,
4325 smblib_usb_irq_enable_vote_callback,
4326 chg);
4327 if (IS_ERR(chg->usb_irq_enable_votable)) {
4328 rc = PTR_ERR(chg->usb_irq_enable_votable);
4329 return rc;
4330 }
4331
Nicholas Troast320839e2016-06-03 10:18:00 -07004332 return rc;
4333}
4334
Harry Yangba874ce2016-08-19 14:17:01 -07004335static void smblib_destroy_votables(struct smb_charger *chg)
4336{
Harry Yangba874ce2016-08-19 14:17:01 -07004337 if (chg->dc_suspend_votable)
4338 destroy_votable(chg->dc_suspend_votable);
Harry Yangba874ce2016-08-19 14:17:01 -07004339 if (chg->usb_icl_votable)
4340 destroy_votable(chg->usb_icl_votable);
4341 if (chg->dc_icl_votable)
4342 destroy_votable(chg->dc_icl_votable);
Abhijeet Dharmapurikar4b13c6e2016-10-05 15:15:10 -07004343 if (chg->pd_disallowed_votable_indirect)
4344 destroy_votable(chg->pd_disallowed_votable_indirect);
Harry Yangba874ce2016-08-19 14:17:01 -07004345 if (chg->pd_allowed_votable)
4346 destroy_votable(chg->pd_allowed_votable);
4347 if (chg->awake_votable)
4348 destroy_votable(chg->awake_votable);
Harry Yangaba1f5f2016-09-28 10:47:29 -07004349 if (chg->chg_disable_votable)
4350 destroy_votable(chg->chg_disable_votable);
4351 if (chg->pl_enable_votable_indirect)
4352 destroy_votable(chg->pl_enable_votable_indirect);
Abhijeet Dharmapurikarf8a7a4a2016-10-07 18:46:45 -07004353 if (chg->apsd_disable_votable)
4354 destroy_votable(chg->apsd_disable_votable);
Ashay Jaiswal6d308da2017-02-18 09:59:23 +05304355 if (chg->hvdcp_hw_inov_dis_votable)
4356 destroy_votable(chg->hvdcp_hw_inov_dis_votable);
Harry Yangba874ce2016-08-19 14:17:01 -07004357}
4358
4359static void smblib_iio_deinit(struct smb_charger *chg)
4360{
4361 if (!IS_ERR_OR_NULL(chg->iio.temp_chan))
4362 iio_channel_release(chg->iio.temp_chan);
4363 if (!IS_ERR_OR_NULL(chg->iio.temp_max_chan))
4364 iio_channel_release(chg->iio.temp_max_chan);
4365 if (!IS_ERR_OR_NULL(chg->iio.usbin_i_chan))
4366 iio_channel_release(chg->iio.usbin_i_chan);
4367 if (!IS_ERR_OR_NULL(chg->iio.usbin_v_chan))
4368 iio_channel_release(chg->iio.usbin_v_chan);
Nicholas Troast7dbcad22016-10-05 13:30:18 -07004369 if (!IS_ERR_OR_NULL(chg->iio.batt_i_chan))
4370 iio_channel_release(chg->iio.batt_i_chan);
Harry Yangba874ce2016-08-19 14:17:01 -07004371}
4372
Nicholas Troast320839e2016-06-03 10:18:00 -07004373int smblib_init(struct smb_charger *chg)
4374{
4375 int rc = 0;
4376
4377 mutex_init(&chg->write_lock);
Nicholas Troastb11015f2017-01-17 17:56:45 -08004378 mutex_init(&chg->otg_oc_lock);
Harry Yangfe913842016-08-10 12:27:28 -07004379 INIT_WORK(&chg->bms_update_work, bms_update_work);
Harry Yang755a34b2016-11-01 01:18:51 -07004380 INIT_WORK(&chg->rdstd_cc2_detach_work, rdstd_cc2_detach_work);
Nicholas Troast320839e2016-06-03 10:18:00 -07004381 INIT_DELAYED_WORK(&chg->hvdcp_detect_work, smblib_hvdcp_detect_work);
Harry Yangfe913842016-08-10 12:27:28 -07004382 INIT_DELAYED_WORK(&chg->step_soc_req_work, step_soc_req_work);
Abhijeet Dharmapurikar0e369002016-09-07 17:25:36 -07004383 INIT_DELAYED_WORK(&chg->clear_hdc_work, clear_hdc_work);
Nicholas Troastb11015f2017-01-17 17:56:45 -08004384 INIT_WORK(&chg->otg_oc_work, smblib_otg_oc_work);
4385 INIT_WORK(&chg->vconn_oc_work, smblib_vconn_oc_work);
4386 INIT_DELAYED_WORK(&chg->otg_ss_done_work, smblib_otg_ss_done_work);
Ashay Jaiswal4d825782017-02-18 10:11:34 +05304387 INIT_DELAYED_WORK(&chg->icl_change_work, smblib_icl_change_work);
Abhijeet Dharmapurikar9e7e48c2016-08-23 12:55:49 -07004388 chg->fake_capacity = -EINVAL;
Nicholas Troast320839e2016-06-03 10:18:00 -07004389
4390 switch (chg->mode) {
4391 case PARALLEL_MASTER:
Harry Yang603e3802017-02-09 17:45:12 -08004392 chg->qnovo_fcc_ua = -EINVAL;
4393 chg->qnovo_fv_uv = -EINVAL;
Nicholas Troast320839e2016-06-03 10:18:00 -07004394 rc = smblib_create_votables(chg);
4395 if (rc < 0) {
Abhijeet Dharmapurikar31b98f32016-10-14 12:25:23 -07004396 smblib_err(chg, "Couldn't create votables rc=%d\n",
Nicholas Troast320839e2016-06-03 10:18:00 -07004397 rc);
Harry Yang58a9e7a2016-06-23 14:54:43 -07004398 return rc;
Nicholas Troast320839e2016-06-03 10:18:00 -07004399 }
Harry Yang58a9e7a2016-06-23 14:54:43 -07004400
Harry Yang5e1a5222016-07-26 15:16:04 -07004401 rc = smblib_register_notifier(chg);
4402 if (rc < 0) {
Abhijeet Dharmapurikar31b98f32016-10-14 12:25:23 -07004403 smblib_err(chg,
Harry Yang5e1a5222016-07-26 15:16:04 -07004404 "Couldn't register notifier rc=%d\n", rc);
4405 return rc;
Harry Yang58a9e7a2016-06-23 14:54:43 -07004406 }
4407
Harry Yang995b7422016-08-29 16:06:50 -07004408 chg->bms_psy = power_supply_get_by_name("bms");
Ashay Jaiswal8afedfc2017-02-03 11:18:22 +05304409 chg->pl.psy = power_supply_get_by_name("parallel");
Nicholas Troast320839e2016-06-03 10:18:00 -07004410 break;
4411 case PARALLEL_SLAVE:
4412 break;
4413 default:
Abhijeet Dharmapurikar31b98f32016-10-14 12:25:23 -07004414 smblib_err(chg, "Unsupported mode %d\n", chg->mode);
Nicholas Troast320839e2016-06-03 10:18:00 -07004415 return -EINVAL;
4416 }
4417
4418 return rc;
Nicholas Troast34db5032016-03-28 12:26:44 -07004419}
Abhijeet Dharmapurikar8e9e7572016-06-06 16:13:14 -07004420
4421int smblib_deinit(struct smb_charger *chg)
4422{
Harry Yangba874ce2016-08-19 14:17:01 -07004423 switch (chg->mode) {
4424 case PARALLEL_MASTER:
4425 power_supply_unreg_notifier(&chg->nb);
4426 smblib_destroy_votables(chg);
4427 break;
4428 case PARALLEL_SLAVE:
4429 break;
4430 default:
Abhijeet Dharmapurikar31b98f32016-10-14 12:25:23 -07004431 smblib_err(chg, "Unsupported mode %d\n", chg->mode);
Harry Yangba874ce2016-08-19 14:17:01 -07004432 return -EINVAL;
4433 }
Abhijeet Dharmapurikar8e9e7572016-06-06 16:13:14 -07004434
Harry Yangba874ce2016-08-19 14:17:01 -07004435 smblib_iio_deinit(chg);
Harry Yang5e1a5222016-07-26 15:16:04 -07004436
Abhijeet Dharmapurikar8e9e7572016-06-06 16:13:14 -07004437 return 0;
4438}