sb_pass_through.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780
  1. /*
  2. * sb_tx.c
  3. * Samsung Mobile Wireless TX Driver
  4. *
  5. * Copyright (C) 2021 Samsung Electronics
  6. *
  7. *
  8. * This program is free software; you can redistribute it and/or modify
  9. * it under the terms of the GNU General Public License version 2 as
  10. * published by the Free Software Foundation.
  11. */
  12. #include <linux/slab.h>
  13. #include <linux/mutex.h>
  14. #include <linux/battery/sb_sysfs.h>
  15. #include <linux/battery/sb_notify.h>
  16. #include "sec_battery.h"
  17. #include "sec_charging_common.h"
  18. #include "sb_pass_through.h"
  19. #define pt_log(str, ...) pr_info("[PASS-THROUGH]:%s: "str, __func__, ##__VA_ARGS__)
  20. #define PT_MODULE_NAME "pass-through"
  21. #define IV_VOTE_NAME "IV"
  22. #define ICL_VOTE_NAME "ICL"
  23. #define FCC_VOTE_NAME "FCC"
  24. #define CHGEN_VOTE_NAME "CHGEN"
  25. struct sb_pt {
  26. struct notifier_block nb;
  27. struct mutex mlock;
  28. struct wakeup_source *ws;
  29. struct workqueue_struct *wq;
  30. struct delayed_work start_work;
  31. struct delayed_work adjust_work;
  32. struct delayed_work step_work;
  33. /* state flags */
  34. int user_mode;
  35. int chg_src;
  36. int step;
  37. int ref_cap;
  38. int adj_state;
  39. unsigned int adj_cnt;
  40. unsigned int adj_op_cnt;
  41. /* battery status */
  42. int cable_type;
  43. int batt_status;
  44. int dc_status;
  45. /* dt data */
  46. bool is_enabled;
  47. unsigned int start_delay;
  48. unsigned int init_delay;
  49. unsigned int adj_delay;
  50. unsigned int adj_max_cnt;
  51. unsigned int min_cap;
  52. unsigned int fixed_sc_cap;
  53. unsigned int max_icl;
  54. unsigned int vfloat;
  55. char *sc_name;
  56. char *dc_name;
  57. char *fg_name;
  58. };
  59. enum pt_step {
  60. PT_STEP_NONE = 0,
  61. PT_STEP_INIT,
  62. PT_STEP_PRESET,
  63. PT_STEP_ADJUST,
  64. PT_STEP_MONITOR,
  65. PT_STEP_RESET,
  66. };
  67. static const char *get_step_str(int step)
  68. {
  69. switch (step) {
  70. case PT_STEP_NONE:
  71. return "None";
  72. case PT_STEP_INIT:
  73. return "Init";
  74. case PT_STEP_PRESET:
  75. return "Preset";
  76. case PT_STEP_ADJUST:
  77. return "Adjust";
  78. case PT_STEP_MONITOR:
  79. return "Monitor";
  80. case PT_STEP_RESET:
  81. return "Reset";
  82. }
  83. return "Unknown";
  84. }
  85. static void set_misc_event(bool state)
  86. {
  87. struct sbn_bit_event misc;
  88. misc.value = (state) ? BATT_MISC_EVENT_PASS_THROUGH : 0;
  89. misc.mask = BATT_MISC_EVENT_PASS_THROUGH;
  90. sb_notify_call(SB_NOTIFY_EVENT_MISC, cast_to_sb_pdata(&misc));
  91. }
  92. static int set_dc_ta_volt(struct sb_pt *pt, int value)
  93. {
  94. union power_supply_propval val = { value, };
  95. return psy_do_property(pt->dc_name, set,
  96. POWER_SUPPLY_EXT_PROP_PASS_THROUGH_MODE_TA_VOL, val);
  97. }
  98. /* don't call the mutex lock in static functions */
  99. static bool check_state(struct sb_pt *pt)
  100. {
  101. if (!pt)
  102. return false;
  103. if (!pt->is_enabled)
  104. return false;
  105. if (pt->user_mode == PTM_NONE)
  106. return false;
  107. if (!is_pd_apdo_wire_type(pt->cable_type))
  108. return false;
  109. if (pt->batt_status != POWER_SUPPLY_STATUS_CHARGING)
  110. return false;
  111. if (pt->step == PT_STEP_NONE) {
  112. union power_supply_propval value = { 0, };
  113. value.intval = SEC_FUELGAUGE_CAPACITY_TYPE_DYNAMIC_SCALE;
  114. psy_do_property(pt->fg_name, get,
  115. POWER_SUPPLY_PROP_CAPACITY, value);
  116. if (pt->min_cap >= value.intval)
  117. return false;
  118. }
  119. return true;
  120. }
  121. static bool check_preset_state(int dc_status)
  122. {
  123. return (dc_status == SEC_DIRECT_CHG_MODE_DIRECT_ON) ||
  124. (dc_status == SEC_DIRECT_CHG_MODE_DIRECT_DONE) ||
  125. (dc_status == SEC_DIRECT_CHG_MODE_DIRECT_BYPASS);
  126. }
  127. #define CAP_HIGH (1)
  128. #define CAP_NORMAL (0)
  129. #define CAP_LOW (-1)
  130. static int check_cap(struct sb_pt *pt)
  131. {
  132. union power_supply_propval value = {0, };
  133. int ncap1, ncap2, rcap1, rcap2;
  134. int delta_cap = 0;
  135. value.intval = SEC_FUELGAUGE_CAPACITY_TYPE_DYNAMIC_SCALE;
  136. psy_do_property(pt->fg_name, get,
  137. POWER_SUPPLY_PROP_CAPACITY, value);
  138. ncap1 = (value.intval / 10);
  139. ncap2 = (value.intval % 10);
  140. rcap1 = (pt->ref_cap / 10);
  141. rcap2 = (pt->ref_cap % 10);
  142. value.intval = SEC_BATTERY_CURRENT_MA;
  143. psy_do_property(pt->fg_name, get,
  144. POWER_SUPPLY_PROP_CURRENT_NOW, value);
  145. if (ncap1 == rcap1)
  146. delta_cap = (((ncap2 >= 6) && (value.intval > 0)) ? CAP_HIGH :
  147. (((ncap2 <= 4) && (value.intval < 0)) ? CAP_LOW : CAP_NORMAL));
  148. else if (ncap1 > rcap1)
  149. delta_cap = (value.intval > 0) ? CAP_HIGH : CAP_NORMAL;
  150. else
  151. delta_cap = (value.intval < 0) ? CAP_LOW : CAP_NORMAL;
  152. pt_log("Now Cap(%03d.%d%%), Ref Cap(%03d.%d%%), Current(%04dmA), delta(%d)\n",
  153. ncap1, ncap2, rcap1, rcap2, value.intval, delta_cap);
  154. return delta_cap;
  155. }
  156. static void clear_state(struct sb_pt *pt, int init_step)
  157. {
  158. if (pt->step == PT_STEP_NONE)
  159. return;
  160. pt_log("latest step = %d, init_step = %d\n", pt->step, init_step);
  161. sec_votef(IV_VOTE_NAME, VOTER_PASS_THROUGH, false, 0);
  162. sec_votef(ICL_VOTE_NAME, VOTER_PASS_THROUGH, false, 0);
  163. sec_votef(FCC_VOTE_NAME, VOTER_PASS_THROUGH, false, 0);
  164. sec_votef(CHGEN_VOTE_NAME, VOTER_PASS_THROUGH, false, 0);
  165. pt->chg_src = SEC_CHARGING_SOURCE_SWITCHING;
  166. pt->adj_state = CAP_NORMAL;
  167. pt->adj_cnt = 0;
  168. pt->adj_op_cnt = 0;
  169. if (init_step == PT_STEP_NONE) {
  170. pt->ref_cap = 0;
  171. /* set charging off before re-starting dc */
  172. sec_votef(CHGEN_VOTE_NAME, VOTER_PASS_THROUGH, true, SEC_BAT_CHG_MODE_CHARGING_OFF);
  173. sec_votef(CHGEN_VOTE_NAME, VOTER_PASS_THROUGH, false, 0);
  174. /* clear event */
  175. set_misc_event(false);
  176. sec_pd_detach_with_cc(0);
  177. }
  178. pt->step = init_step;
  179. }
  180. static void cb_start_work(struct work_struct *work)
  181. {
  182. struct sb_pt *pt = container_of(work,
  183. struct sb_pt, start_work.work);
  184. mutex_lock(&pt->mlock);
  185. pt_log("now step = %s\n", get_step_str(pt->step));
  186. if (!check_state(pt))
  187. goto end_work;
  188. if (pt->step == PT_STEP_NONE)
  189. pt->step = PT_STEP_INIT;
  190. if (pt->step != PT_STEP_INIT)
  191. goto end_work;
  192. __pm_wakeup_event(pt->ws, msecs_to_jiffies(1000));
  193. queue_delayed_work(pt->wq, &pt->step_work, 0);
  194. end_work:
  195. mutex_unlock(&pt->mlock);
  196. }
  197. #define PT_ADJ_OP_MAX_CNT 100
  198. #define PT_ADJ_CURR 500
  199. static void cb_adjust_work(struct work_struct *work)
  200. {
  201. struct sb_pt *pt = container_of(work, struct sb_pt, adjust_work.work);
  202. union power_supply_propval value = {0, };
  203. int now_state = CAP_NORMAL;
  204. mutex_lock(&pt->mlock);
  205. if (!check_state(pt))
  206. goto end_work;
  207. if (pt->step != PT_STEP_ADJUST)
  208. goto end_work;
  209. if (pt->chg_src == SEC_CHARGING_SOURCE_SWITCHING) {
  210. pt->step = PT_STEP_MONITOR;
  211. goto end_work;
  212. }
  213. if (pt->adj_op_cnt++ >= PT_ADJ_OP_MAX_CNT) {
  214. pt_log("over working(%d) !!\n", pt->adj_op_cnt);
  215. pt->step = PT_STEP_MONITOR;
  216. goto end_work;
  217. }
  218. now_state = check_cap(pt);
  219. if (now_state != pt->adj_state) {
  220. pt->adj_cnt = 0;
  221. pt->adj_state = now_state;
  222. goto re_work;
  223. }
  224. value.intval = SEC_BATTERY_CURRENT_MA;
  225. psy_do_property(pt->fg_name, get,
  226. POWER_SUPPLY_PROP_CURRENT_NOW, value);
  227. switch (pt->adj_state) {
  228. case CAP_LOW:
  229. if (value.intval < (-PT_ADJ_CURR)) {
  230. pt->adj_cnt = 0;
  231. set_dc_ta_volt(pt, CAP_LOW);
  232. } else if (value.intval > (PT_ADJ_CURR)) {
  233. pt->adj_cnt = 0;
  234. } else {
  235. pt->adj_cnt++;
  236. }
  237. break;
  238. case CAP_HIGH:
  239. if (value.intval > (PT_ADJ_CURR)) {
  240. pt->adj_cnt = 0;
  241. set_dc_ta_volt(pt, CAP_HIGH);
  242. } else if (value.intval < (-PT_ADJ_CURR)) {
  243. pt->adj_cnt = 0;
  244. } else {
  245. pt->adj_cnt++;
  246. }
  247. break;
  248. case CAP_NORMAL:
  249. if (value.intval < (-PT_ADJ_CURR)) {
  250. pt->adj_cnt = 0;
  251. set_dc_ta_volt(pt, CAP_LOW);
  252. } else if (value.intval > (PT_ADJ_CURR)) {
  253. pt->adj_cnt = 0;
  254. set_dc_ta_volt(pt, CAP_HIGH);
  255. } else {
  256. pt->adj_cnt++;
  257. }
  258. break;
  259. default:
  260. break;
  261. }
  262. pt_log("ADJ STATE(%d, %d), CURR(%d), CNT(%d)\n",
  263. pt->adj_state, now_state, value.intval, pt->adj_cnt);
  264. if (pt->adj_cnt >= pt->adj_max_cnt) {
  265. pt->step = PT_STEP_MONITOR;
  266. goto end_work;
  267. }
  268. re_work:
  269. mutex_unlock(&pt->mlock);
  270. queue_delayed_work(pt->wq, &pt->adjust_work, msecs_to_jiffies(pt->adj_delay));
  271. return;
  272. end_work:
  273. pt->adj_state = CAP_NORMAL;
  274. pt->adj_cnt = 0;
  275. pt->adj_op_cnt = 0;
  276. mutex_unlock(&pt->mlock);
  277. __pm_relax(pt->ws);
  278. }
  279. static void cb_step_work(struct work_struct *work)
  280. {
  281. struct sb_pt *pt = container_of(work, struct sb_pt, step_work.work);
  282. sb_pt_monitor(pt, pt->chg_src);
  283. }
  284. static void push_start_work(struct sb_pt *pt, unsigned int delay)
  285. {
  286. unsigned int work_state;
  287. if (!check_state(pt))
  288. return;
  289. work_state = work_busy(&pt->start_work.work);
  290. pt_log("work_state = 0x%x, delay = %d\n", work_state, delay);
  291. if (!(work_state & (WORK_BUSY_PENDING | WORK_BUSY_RUNNING))) {
  292. __pm_wakeup_event(pt->ws, msecs_to_jiffies(delay + 1000));
  293. queue_delayed_work(pt->wq, &pt->start_work, msecs_to_jiffies(delay));
  294. }
  295. }
  296. static ssize_t show_attrs(struct device *dev,
  297. struct device_attribute *attr, char *buf);
  298. static ssize_t store_attrs(struct device *dev,
  299. struct device_attribute *attr, const char *buf, size_t count);
  300. #define PT_SYSFS_ATTR(_name) \
  301. { \
  302. .attr = {.name = #_name, .mode = 0664}, \
  303. .show = show_attrs, \
  304. .store = store_attrs, \
  305. }
  306. static struct device_attribute pt_attr[] = {
  307. PT_SYSFS_ATTR(pass_through),
  308. };
  309. enum sb_pt_attrs {
  310. PASS_THROUGH = 0,
  311. };
  312. static ssize_t show_attrs(struct device *dev,
  313. struct device_attribute *attr, char *buf)
  314. {
  315. struct sb_pt *pt = sb_sysfs_get_pdata(PT_MODULE_NAME);
  316. const ptrdiff_t offset = attr - pt_attr;
  317. ssize_t count = 0;
  318. switch (offset) {
  319. case PASS_THROUGH:
  320. count += scnprintf(buf + count, PAGE_SIZE - count, "%d\n", pt->user_mode);
  321. break;
  322. default:
  323. break;
  324. }
  325. return count;
  326. }
  327. static ssize_t store_attrs(struct device *dev,
  328. struct device_attribute *attr, const char *buf, size_t count)
  329. {
  330. struct sb_pt *pt = sb_sysfs_get_pdata(PT_MODULE_NAME);
  331. const ptrdiff_t offset = attr - pt_attr;
  332. switch (offset) {
  333. case PASS_THROUGH:
  334. {
  335. int x = 0;
  336. if (sscanf(buf, "%10d\n", &x) == 1) {
  337. mutex_lock(&pt->mlock);
  338. pt_log("user_mode = %d <-> %d, %s\n",
  339. x, pt->user_mode, ((x != PTM_NONE) ? "enabled" : "disabled"));
  340. x = (x) ? PTM_2TO1 : PTM_NONE;
  341. if (pt->user_mode != x) {
  342. pt->user_mode = x;
  343. if (pt->step != PT_STEP_NONE)
  344. clear_state(pt, PT_STEP_NONE);
  345. if (pt->user_mode)
  346. push_start_work(pt, pt->start_delay);
  347. }
  348. mutex_unlock(&pt->mlock);
  349. }
  350. }
  351. break;
  352. default:
  353. break;
  354. }
  355. return count;
  356. }
  357. static int sb_noti_handler(struct notifier_block *nb, unsigned long action, void *data)
  358. {
  359. return 0;
  360. }
  361. static int parse_dt(struct sb_pt *pt, struct device *parent)
  362. {
  363. #if defined(CONFIG_OF)
  364. struct device_node *np;
  365. int ret = 0;
  366. if (!parent)
  367. return -EINVAL;
  368. np = of_find_node_by_name(NULL, PT_MODULE_NAME);
  369. if (!np) {
  370. pt_log("failed to find root node\n");
  371. return -ENODEV;
  372. }
  373. pt->is_enabled = true;
  374. sb_of_parse_u32(np, pt, start_delay, 5000);
  375. sb_of_parse_u32(np, pt, init_delay, 5000);
  376. sb_of_parse_u32(np, pt, adj_delay, 500);
  377. sb_of_parse_u32(np, pt, adj_max_cnt, 3);
  378. sb_of_parse_u32(np, pt, min_cap, 200);
  379. sb_of_parse_u32(np, pt, fixed_sc_cap, 900);
  380. sb_of_parse_u32(np, pt, max_icl, 3000);
  381. sb_of_parse_u32(np, pt, vfloat, 4400);
  382. np = of_find_node_by_name(NULL, "battery");
  383. if (np) {
  384. ret = of_property_read_string(np,
  385. "battery,fuelgauge_name", (const char **)&pt->fg_name);
  386. if (ret)
  387. pt_log("failed to get fg name in battery dt (ret = %d)\n", ret);
  388. }
  389. ret = of_property_read_string(parent->of_node,
  390. "charger,main_charger", (const char **)&pt->sc_name);
  391. if (ret)
  392. pt_log("failed to get sc name in dc drv (ret = %d)\n", ret);
  393. ret = of_property_read_string(parent->of_node,
  394. "charger,direct_charger", (const char **)&pt->dc_name);
  395. if (ret)
  396. pt_log("failed to get dc name in dc drv (ret = %d)\n", ret);
  397. #endif
  398. return 0;
  399. }
  400. struct sb_pt *sb_pt_init(struct device *parent)
  401. {
  402. struct sb_pt *pt;
  403. int ret = 0;
  404. pt = kzalloc(sizeof(struct sb_pt), GFP_KERNEL);
  405. if (!pt)
  406. return ERR_PTR(-ENOMEM);
  407. ret = parse_dt(pt, parent);
  408. pt_log("parse_dt ret = %s\n", (ret) ? "fail" : "success");
  409. if (ret)
  410. goto failed_dt;
  411. pt->wq = create_singlethread_workqueue(PT_MODULE_NAME);
  412. if (!pt->wq) {
  413. ret = -ENOMEM;
  414. goto failed_wq;
  415. }
  416. pt->ws = wakeup_source_register(parent, PT_MODULE_NAME);
  417. INIT_DELAYED_WORK(&pt->start_work, cb_start_work);
  418. INIT_DELAYED_WORK(&pt->adjust_work, cb_adjust_work);
  419. INIT_DELAYED_WORK(&pt->step_work, cb_step_work);
  420. mutex_init(&pt->mlock);
  421. pt->chg_src = SEC_CHARGING_SOURCE_SWITCHING;
  422. pt->step = PT_STEP_NONE;
  423. pt->ref_cap = 0;
  424. pt->user_mode = PTM_NONE;
  425. pt->adj_state = CAP_NORMAL;
  426. pt->adj_cnt = 0;
  427. pt->adj_op_cnt = 0;
  428. ret = sb_sysfs_add_attrs(PT_MODULE_NAME, pt, pt_attr, ARRAY_SIZE(pt_attr));
  429. pt_log("sb_sysfs_add_attrs ret = %s\n", (ret) ? "fail" : "success");
  430. ret = sb_notify_register(&pt->nb, sb_noti_handler, PT_MODULE_NAME, SB_DEV_MODULE);
  431. pt_log("sb_notify_register ret = %s\n", (ret) ? "fail" : "success");
  432. return pt;
  433. failed_wq:
  434. failed_dt:
  435. kfree(pt);
  436. return ERR_PTR(ret);
  437. }
  438. EXPORT_SYMBOL(sb_pt_init);
  439. int sb_pt_psy_set_property(struct sb_pt *pt, enum power_supply_property psp, const union power_supply_propval *value)
  440. {
  441. if (!pt)
  442. return 0;
  443. switch ((int)psp) {
  444. case POWER_SUPPLY_PROP_STATUS:
  445. pt->batt_status = value->intval;
  446. break;
  447. case POWER_SUPPLY_PROP_ONLINE:
  448. pt->cable_type = value->intval;
  449. mutex_lock(&pt->mlock);
  450. if (!is_pd_apdo_wire_type(pt->cable_type) &&
  451. (pt->step != PT_STEP_NONE))
  452. clear_state(pt, PT_STEP_NONE);
  453. mutex_unlock(&pt->mlock);
  454. break;
  455. case POWER_SUPPLY_EXT_PROP_DIRECT_CHARGER_MODE:
  456. /* Caution : dead lock */
  457. pt->dc_status = value->intval;
  458. break;
  459. default:
  460. break;
  461. }
  462. return 0;
  463. }
  464. EXPORT_SYMBOL(sb_pt_psy_set_property);
  465. int sb_pt_psy_get_property(struct sb_pt *pt, enum power_supply_property psp, union power_supply_propval *value)
  466. {
  467. int ret = 0;
  468. if (!pt)
  469. return 0;
  470. switch (psp) {
  471. case POWER_SUPPLY_PROP_STATUS:
  472. mutex_lock(&pt->mlock);
  473. if ((pt->step != PT_STEP_NONE) &&
  474. (pt->chg_src == SEC_CHARGING_SOURCE_SWITCHING)) {
  475. union power_supply_propval val;
  476. val.intval = 0;
  477. psy_do_property(pt->sc_name, get, psp, val);
  478. if (val.intval == POWER_SUPPLY_STATUS_FULL) {
  479. ret = -EBUSY;
  480. pt_log("prevent charging status\n");
  481. value->intval = POWER_SUPPLY_STATUS_CHARGING;
  482. }
  483. }
  484. mutex_unlock(&pt->mlock);
  485. break;
  486. case POWER_SUPPLY_PROP_HEALTH:
  487. mutex_lock(&pt->mlock);
  488. if (pt->step != PT_STEP_NONE) {
  489. union power_supply_propval val;
  490. val.intval = 0;
  491. psy_do_property(pt->dc_name, get, psp, val);
  492. if (val.intval == POWER_SUPPLY_EXT_HEALTH_DC_ERR) {
  493. pt_log("clear pt state because of DC err(%d)\n", val.intval);
  494. clear_state(pt, PT_STEP_NONE);
  495. }
  496. }
  497. mutex_unlock(&pt->mlock);
  498. break;
  499. default:
  500. break;
  501. }
  502. return ret;
  503. }
  504. EXPORT_SYMBOL(sb_pt_psy_get_property);
  505. int sb_pt_monitor(struct sb_pt *pt, int chg_src)
  506. {
  507. if (!pt)
  508. return -EINVAL;
  509. mutex_lock(&pt->mlock);
  510. if (!check_state(pt)) {
  511. clear_state(pt, PT_STEP_NONE);
  512. goto end_monitor;
  513. }
  514. pt_log("start - step = %s, chg_src = %d, dc_status = %d\n", get_step_str(pt->step), chg_src, pt->dc_status);
  515. switch (pt->step) {
  516. case PT_STEP_NONE:
  517. push_start_work(pt, pt->start_delay);
  518. pt->chg_src = chg_src;
  519. break;
  520. case PT_STEP_INIT:
  521. if (pt->ref_cap <= 0) {
  522. union power_supply_propval value = { 0, };
  523. value.intval = SEC_FUELGAUGE_CAPACITY_TYPE_DYNAMIC_SCALE;
  524. psy_do_property(pt->fg_name, get,
  525. POWER_SUPPLY_PROP_CAPACITY, value);
  526. pt->ref_cap = value.intval;
  527. pt_log("update ref_cap = %d\n", pt->ref_cap);
  528. if ((chg_src == SEC_CHARGING_SOURCE_DIRECT) &&
  529. (pt->ref_cap > pt->fixed_sc_cap)) {
  530. /* reset chg src to switching charger */
  531. sec_votef(CHGEN_VOTE_NAME, VOTER_PASS_THROUGH, true, SEC_BAT_CHG_MODE_CHARGING_OFF);
  532. pt->step = PT_STEP_PRESET;
  533. break;
  534. }
  535. }
  536. if (chg_src == SEC_CHARGING_SOURCE_SWITCHING) {
  537. pt->step = PT_STEP_PRESET;
  538. } else {
  539. if (check_preset_state(pt->dc_status))
  540. pt->step = PT_STEP_PRESET;
  541. else
  542. push_start_work(pt, pt->init_delay);
  543. }
  544. pt->chg_src = chg_src;
  545. break;
  546. case PT_STEP_PRESET:
  547. {
  548. union power_supply_propval value = { 0, };
  549. int iv, icl, fcc, chgen;
  550. if ((chg_src == SEC_CHARGING_SOURCE_DIRECT) &&
  551. (pt->ref_cap > pt->fixed_sc_cap))
  552. chg_src = SEC_CHARGING_SOURCE_SWITCHING;
  553. pt->chg_src = chg_src;
  554. pt->step = PT_STEP_ADJUST;
  555. if (chg_src == SEC_CHARGING_SOURCE_SWITCHING) {
  556. iv = SEC_INPUT_VOLTAGE_5V;
  557. icl = fcc = pt->max_icl;
  558. } else {
  559. iv = SEC_INPUT_VOLTAGE_APDO;
  560. icl = fcc = pt->max_icl * pt->user_mode;
  561. }
  562. chgen = SEC_BAT_CHG_MODE_PASS_THROUGH;
  563. sec_votef(IV_VOTE_NAME, VOTER_PASS_THROUGH, true, iv);
  564. sec_votef(ICL_VOTE_NAME, VOTER_PASS_THROUGH, true, icl);
  565. sec_votef(FCC_VOTE_NAME, VOTER_PASS_THROUGH, true, fcc);
  566. sec_votef(CHGEN_VOTE_NAME, VOTER_PASS_THROUGH, true, chgen);
  567. if (chg_src == SEC_CHARGING_SOURCE_SWITCHING) {
  568. value.intval = pt->user_mode;
  569. psy_do_property(pt->sc_name, set,
  570. POWER_SUPPLY_EXT_PROP_PASS_THROUGH_MODE, value);
  571. /* skip adjust work */
  572. pt->step = PT_STEP_MONITOR;
  573. } else {
  574. value.intval = pt->user_mode;
  575. psy_do_property(pt->dc_name, set,
  576. POWER_SUPPLY_EXT_PROP_PASS_THROUGH_MODE, value);
  577. sec_pd_detach_with_cc(1);
  578. value.intval = pt->vfloat;
  579. psy_do_property(pt->dc_name, set,
  580. POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE, value);
  581. /* set adj state */
  582. pt->adj_state = check_cap(pt);
  583. /* start adj work */
  584. __pm_stay_awake(pt->ws);
  585. queue_delayed_work(pt->wq, &pt->adjust_work, msecs_to_jiffies(pt->adj_delay));
  586. }
  587. set_misc_event(true);
  588. }
  589. break;
  590. case PT_STEP_ADJUST:
  591. /* not working */
  592. break;
  593. case PT_STEP_MONITOR:
  594. {
  595. int cap_state = CAP_NORMAL;
  596. if (pt->chg_src != chg_src) {
  597. clear_state(pt, PT_STEP_INIT);
  598. break;
  599. }
  600. cap_state = check_cap(pt);
  601. if (pt->chg_src == SEC_CHARGING_SOURCE_SWITCHING) {
  602. if (cap_state == CAP_LOW)
  603. sec_votef(CHGEN_VOTE_NAME, VOTER_PASS_THROUGH, true, SEC_BAT_CHG_MODE_CHARGING);
  604. else
  605. sec_votef(CHGEN_VOTE_NAME, VOTER_PASS_THROUGH, true, SEC_BAT_CHG_MODE_PASS_THROUGH);
  606. } else {
  607. set_dc_ta_volt(pt, cap_state);
  608. }
  609. }
  610. break;
  611. case PT_STEP_RESET:
  612. break;
  613. default:
  614. break;
  615. }
  616. end_monitor:
  617. pt_log("end - step = %s\n", get_step_str(pt->step));
  618. mutex_unlock(&pt->mlock);
  619. return 0;
  620. }
  621. EXPORT_SYMBOL(sb_pt_monitor);
  622. int sb_pt_check_chg_src(struct sb_pt *pt, int chg_src)
  623. {
  624. if (!pt)
  625. return chg_src;
  626. if ((pt->step != PT_STEP_NONE) &&
  627. (pt->ref_cap > pt->fixed_sc_cap))
  628. return SEC_CHARGING_SOURCE_SWITCHING;
  629. return chg_src;
  630. }
  631. EXPORT_SYMBOL(sb_pt_check_chg_src);