sec_battery_wc.c 60 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698
  1. /*
  2. * sec_battery_wc.c
  3. * Samsung Mobile Battery Driver
  4. *
  5. * Copyright (C) 2020 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 "sec_battery.h"
  13. #include "sb_tx.h"
  14. #if defined(CONFIG_SEC_KUNIT)
  15. #include <kunit/mock.h>
  16. #else
  17. #define __visible_for_testing static
  18. #endif
  19. #if defined(CONFIG_WIRELESS_FIRMWARE_UPDATE)
  20. bool sec_bat_check_boost_mfc_condition(struct sec_battery_info *battery, int mode)
  21. {
  22. union power_supply_propval value = {0, };
  23. int boost_status = 0, wpc_det = 0, mst_pwr_en = 0;
  24. pr_info("%s\n", __func__);
  25. if (mode == SEC_WIRELESS_FW_UPDATE_AUTO_MODE) {
  26. psy_do_property(battery->pdata->wireless_charger_name, get,
  27. POWER_SUPPLY_EXT_PROP_WIRELESS_INITIAL_WC_CHECK, value);
  28. wpc_det = value.intval;
  29. }
  30. psy_do_property(battery->pdata->wireless_charger_name, get,
  31. POWER_SUPPLY_EXT_PROP_WIRELESS_MST_PWR_EN, value);
  32. mst_pwr_en = value.intval;
  33. psy_do_property(battery->pdata->charger_name, get,
  34. POWER_SUPPLY_EXT_PROP_CHARGE_BOOST, value);
  35. boost_status = value.intval;
  36. pr_info("%s wpc_det(%d), mst_pwr_en(%d), boost_status(%d)\n",
  37. __func__, wpc_det, mst_pwr_en, boost_status);
  38. if (!boost_status && !wpc_det && !mst_pwr_en)
  39. return true;
  40. return false;
  41. }
  42. void sec_bat_fw_update(struct sec_battery_info *battery, int mode)
  43. {
  44. union power_supply_propval value = {0, };
  45. int ret = 0;
  46. pr_info("%s\n", __func__);
  47. __pm_wakeup_event(battery->vbus_ws, jiffies_to_msecs(HZ * 10));
  48. switch (mode) {
  49. case SEC_WIRELESS_FW_UPDATE_SDCARD_MODE:
  50. case SEC_WIRELESS_FW_UPDATE_BUILTIN_MODE:
  51. case SEC_WIRELESS_FW_UPDATE_AUTO_MODE:
  52. case SEC_WIRELESS_FW_UPDATE_SPU_MODE:
  53. case SEC_WIRELESS_FW_UPDATE_SPU_VERIFY_MODE:
  54. battery->mfc_fw_update = true;
  55. sec_vote(battery->chgen_vote, VOTER_FW, true, SEC_BAT_CHG_MODE_BUCK_OFF);
  56. msleep(500);
  57. sec_vote(battery->iv_vote, VOTER_FW, true, SEC_INPUT_VOLTAGE_5V);
  58. #if IS_ENABLED(CONFIG_MUIC_NOTIFIER)
  59. #if !IS_ENABLED(CONFIG_MTK_CHARGER) || !IS_ENABLED(CONFIG_AFC_CHARGER)
  60. muic_afc_request_voltage(AFC_REQUEST_MFC, SEC_INPUT_VOLTAGE_5V / 1000);
  61. #endif
  62. #endif
  63. msleep(2000);
  64. value.intval = mode;
  65. ret = psy_do_property(battery->pdata->wireless_charger_name, set,
  66. POWER_SUPPLY_EXT_PROP_CHARGE_POWERED_OTG_CONTROL, value);
  67. if (ret < 0) {
  68. battery->mfc_fw_update = false;
  69. sec_vote(battery->chgen_vote, VOTER_FW, false, 0);
  70. sec_vote(battery->iv_vote, VOTER_FW, false, 0);
  71. #if IS_ENABLED(CONFIG_MUIC_NOTIFIER)
  72. #if !IS_ENABLED(CONFIG_MTK_CHARGER) || !IS_ENABLED(CONFIG_AFC_CHARGER)
  73. muic_afc_request_voltage(AFC_REQUEST_MFC, SEC_INPUT_VOLTAGE_9V / 1000);
  74. #endif
  75. #endif
  76. }
  77. break;
  78. default:
  79. break;
  80. }
  81. }
  82. #endif
  83. int sec_bat_check_wpc_vout(struct sec_battery_info *battery, int ct, unsigned int chg_limit,
  84. int pre_vout, unsigned int evt)
  85. {
  86. union power_supply_propval value = {0, };
  87. int vout = 0;
  88. bool check_flicker_wa = false;
  89. if (!is_hv_wireless_type(ct))
  90. return 0;
  91. if ((ct == SEC_BATTERY_CABLE_HV_WIRELESS_20) || (ct == SEC_BATTERY_CABLE_WIRELESS_EPP))
  92. vout = battery->wpc_max_vout_level;
  93. else
  94. vout = WIRELESS_VOUT_10V;
  95. mutex_lock(&battery->voutlock);
  96. if (battery->pdata->wpc_vout_ctrl_lcd_on) {
  97. psy_do_property(battery->pdata->wireless_charger_name, get,
  98. POWER_SUPPLY_EXT_PROP_WIRELESS_TX_ID, value);
  99. if ((value.intval != WC_PAD_ID_UNKNOWN) &&
  100. (value.intval != WC_PAD_ID_SNGL_DREAM) &&
  101. (value.intval != WC_PAD_ID_STAND_DREAM)) {
  102. if (battery->wpc_vout_ctrl_mode && battery->lcd_status) {
  103. pr_info("%s: trigger flicker wa\n", __func__);
  104. check_flicker_wa = true;
  105. } else {
  106. value.intval = 0;
  107. psy_do_property(battery->pdata->wireless_charger_name, get,
  108. POWER_SUPPLY_EXT_PROP_PAD_VOLT_CTRL, value);
  109. if (!value.intval) {
  110. pr_info("%s: recover flicker wa\n", __func__);
  111. value.intval = battery->lcd_status;
  112. psy_do_property(battery->pdata->wireless_charger_name, set,
  113. POWER_SUPPLY_EXT_PROP_PAD_VOLT_CTRL, value);
  114. }
  115. }
  116. }
  117. }
  118. /* get vout level */
  119. psy_do_property(battery->pdata->wireless_charger_name, get,
  120. POWER_SUPPLY_EXT_PROP_WIRELESS_RX_VOUT, value);
  121. if (value.intval == WIRELESS_VOUT_5_5V_STEP)
  122. pre_vout = WIRELESS_VOUT_5_5V_STEP;
  123. if ((evt & (SEC_BAT_CURRENT_EVENT_HIGH_TEMP_SWELLING | SEC_BAT_CURRENT_EVENT_ISDB)) ||
  124. battery->sleep_mode || chg_limit || check_flicker_wa)
  125. vout = WIRELESS_VOUT_5_5V_STEP;
  126. pr_info("%s: prev_vout(%d) => vout(%d)\n", __func__, pre_vout, vout);
  127. if (vout != pre_vout) {
  128. if (evt & SEC_BAT_CURRENT_EVENT_WPC_VOUT_LOCK) {
  129. vout = pre_vout;
  130. pr_info("%s: block to set wpc vout level(%d) because otg on\n",
  131. __func__, vout);
  132. } else {
  133. value.intval = vout;
  134. psy_do_property(battery->pdata->wireless_charger_name, set,
  135. POWER_SUPPLY_EXT_PROP_INPUT_VOLTAGE_REGULATION, value);
  136. pr_info("%s: change vout level(%d)", __func__, vout);
  137. sec_vote(battery->input_vote, VOTER_AICL, false, 0);
  138. }
  139. } else if ((vout == WIRELESS_VOUT_10V ||
  140. vout == battery->wpc_max_vout_level)) {
  141. /* reset aicl current to recover current for unexpected aicl during */
  142. /* before vout boosting completion */
  143. sec_vote(battery->input_vote, VOTER_AICL, false, 0);
  144. }
  145. mutex_unlock(&battery->voutlock);
  146. return vout;
  147. }
  148. EXPORT_SYMBOL_KUNIT(sec_bat_check_wpc_vout);
  149. void sec_wireless_otg_vout_control(struct sec_battery_info *battery, int enable)
  150. {
  151. union power_supply_propval value = {0, };
  152. if (enable) {
  153. sec_bat_set_current_event(battery, SEC_BAT_CURRENT_EVENT_WPC_VOUT_LOCK,
  154. SEC_BAT_CURRENT_EVENT_WPC_VOUT_LOCK);
  155. } else {
  156. sec_bat_set_current_event(battery, 0,
  157. SEC_BAT_CURRENT_EVENT_WPC_VOUT_LOCK);
  158. }
  159. value.intval = enable;
  160. psy_do_property(battery->pdata->wireless_charger_name, set,
  161. POWER_SUPPLY_EXT_PROP_CHARGE_OTG_CONTROL, value);
  162. if (enable) {
  163. if (battery->wc_tx_enable) {
  164. /* TX power should turn off during otg on */
  165. pr_info("@Tx_Mode %s: OTG is going to work, TX power should off\n", __func__);
  166. /* set tx event */
  167. sec_bat_set_tx_event(battery, BATT_TX_EVENT_WIRELESS_TX_OTG_ON, BATT_TX_EVENT_WIRELESS_TX_OTG_ON);
  168. sec_wireless_set_tx_enable(battery, false);
  169. } else {
  170. battery->wpc_vout_level = WIRELESS_VOUT_5V;
  171. }
  172. } else if (is_wireless_all_type(battery->cable_type)) {
  173. if ((battery->status == POWER_SUPPLY_STATUS_FULL) &&
  174. ((battery->charging_mode == SEC_BATTERY_CHARGING_2ND) || battery->is_recharging)) {
  175. psy_do_property(battery->pdata->wireless_charger_name, get,
  176. POWER_SUPPLY_EXT_PROP_INPUT_VOLTAGE_REGULATION, value);
  177. if (value.intval >= MFC_VOUT_5_5V)
  178. battery->wpc_vout_level = WIRELESS_VOUT_5_5V_STEP;
  179. else
  180. battery->wpc_vout_level = WIRELESS_VOUT_CC_CV_VOUT;
  181. value.intval = WIRELESS_VOUT_CC_CV_VOUT;
  182. psy_do_property(battery->pdata->wireless_charger_name, set,
  183. POWER_SUPPLY_EXT_PROP_WIRELESS_1ST_DONE, value);
  184. } else {
  185. battery->wpc_vout_level = sec_bat_check_wpc_vout(battery, battery->cable_type, battery->chg_limit,
  186. battery->wpc_vout_level, battery->current_event);
  187. }
  188. sec_wireless_otg_icl_control(battery);
  189. }
  190. }
  191. unsigned int get_wc20_vout(unsigned int vout)
  192. {
  193. unsigned int ret = 0;
  194. switch (vout) {
  195. case WIRELESS_VOUT_5V:
  196. ret = 5000;
  197. break;
  198. case WIRELESS_VOUT_5_5V:
  199. ret = 5500;
  200. break;
  201. case WIRELESS_VOUT_9V:
  202. ret = 9000;
  203. break;
  204. case WIRELESS_VOUT_10V:
  205. ret = 10000;
  206. break;
  207. case WIRELESS_VOUT_11V:
  208. ret = 11000;
  209. break;
  210. case WIRELESS_VOUT_12V:
  211. ret = 12000;
  212. break;
  213. default:
  214. pr_err("%s vout is not supported\n", __func__);
  215. break;
  216. }
  217. pr_info("%s vout(%d) - idx(%d)\n", __func__, vout, ret);
  218. return ret;
  219. }
  220. void sec_bat_set_wc20_current(struct sec_battery_info *battery)
  221. {
  222. int icl = 0, fcc = 0;
  223. pr_info("%s: wc_status(%d), rx_power(%d), vout(%d)\n", __func__,
  224. battery->wc_status, battery->wc20_rx_power, battery->wc20_vout);
  225. if (is_pwr_nego_wireless_type(battery->wc_status)) {
  226. icl = (battery->wc20_rx_power / battery->wc20_vout);
  227. fcc = battery->pdata->charging_current[battery->wc_status].fast_charging_current;
  228. if (battery->wc20_rx_power <= SEC_WIRELESS_RX_POWER_5W) {
  229. battery->wc20_power_class = 0;
  230. } else if (battery->wc20_rx_power <= SEC_WIRELESS_RX_POWER_7_5W) {
  231. battery->wc20_power_class = SEC_WIRELESS_RX_POWER_CLASS_1;
  232. } else if (battery->wc20_rx_power <= SEC_WIRELESS_RX_POWER_12W) {
  233. battery->wc20_power_class = SEC_WIRELESS_RX_POWER_CLASS_2;
  234. } else if (battery->wc20_rx_power <= SEC_WIRELESS_RX_POWER_20W) {
  235. battery->wc20_power_class = SEC_WIRELESS_RX_POWER_CLASS_3;
  236. if (battery->pdata->wc21_icl > 0)
  237. icl = battery->pdata->wc21_icl;
  238. } else {
  239. battery->wc20_power_class = SEC_WIRELESS_RX_POWER_CLASS_4;
  240. }
  241. sec_bat_change_default_current(battery, battery->wc_status, icl, fcc);
  242. sec_vote(battery->input_vote, VOTER_CABLE, true, icl);
  243. sec_vote(battery->fcc_vote, VOTER_CABLE, true, fcc);
  244. if (is_wired_type(battery->cable_type)) {
  245. int wl_power = battery->wc20_rx_power;
  246. pr_info("%s: check power(%d <--> %d)\n",
  247. __func__, battery->max_charge_power, wl_power);
  248. if (battery->max_charge_power < wl_power) {
  249. __pm_stay_awake(battery->cable_ws);
  250. queue_delayed_work(battery->monitor_wqueue,
  251. &battery->cable_work, 0);
  252. }
  253. } else {
  254. sec_bat_set_charging_current(battery);
  255. }
  256. }
  257. }
  258. void sec_wireless_otg_icl_control(struct sec_battery_info *battery)
  259. {
  260. bool need_vote_refresh = false;
  261. pr_info("%s: is_otg_on=%s\n", __func__, battery->is_otg_on ? "ON" : "OFF");
  262. if (battery->is_otg_on) {
  263. if (get_sec_vote_result(battery->input_vote) <= battery->pdata->wireless_otg_input_current)
  264. need_vote_refresh = true;
  265. sec_vote(battery->input_vote, VOTER_OTG, true, battery->pdata->wireless_otg_input_current);
  266. if (need_vote_refresh)
  267. sec_vote_refresh(battery->input_vote);
  268. } else {
  269. sec_vote(battery->input_vote, VOTER_OTG, false, 0);
  270. }
  271. sec_vote(battery->input_vote, VOTER_AICL, false, 0);
  272. }
  273. void sec_bat_set_mfc_off(struct sec_battery_info *battery, char flag, bool need_ept)
  274. {
  275. union power_supply_propval value = {0, };
  276. char wpc_en_status[2];
  277. if (need_ept) {
  278. psy_do_property(battery->pdata->wireless_charger_name, set,
  279. POWER_SUPPLY_PROP_ONLINE, value);
  280. msleep(300);
  281. }
  282. wpc_en_status[0] = flag;
  283. wpc_en_status[1] = false;
  284. value.strval = wpc_en_status;
  285. psy_do_property(battery->pdata->wireless_charger_name, set,
  286. POWER_SUPPLY_EXT_PROP_WPC_EN, value);
  287. pr_info("@DIS_MFC %s: WC CONTROL: Disable %d\n", __func__, flag);
  288. }
  289. void sec_bat_set_mfc_on(struct sec_battery_info *battery, char flag)
  290. {
  291. union power_supply_propval value = {0, };
  292. char wpc_en_status[2];
  293. wpc_en_status[0] = flag;
  294. wpc_en_status[1] = true;
  295. value.strval = wpc_en_status;
  296. psy_do_property(battery->pdata->wireless_charger_name, set,
  297. POWER_SUPPLY_EXT_PROP_WPC_EN, value);
  298. pr_info("%s: WC CONTROL: Enable %d\n", __func__, flag);
  299. }
  300. void sec_bat_mfc_ldo_cntl(struct sec_battery_info *battery, bool en)
  301. {
  302. union power_supply_propval value = {0, };
  303. battery->wc_need_ldo_on = !en;
  304. value.intval = en;
  305. psy_do_property(battery->pdata->wireless_charger_name, set,
  306. POWER_SUPPLY_PROP_CHARGE_EMPTY, value);
  307. if (en) {
  308. battery->wpc_vout_level = WIRELESS_VOUT_5V;
  309. } else {
  310. battery->wpc_vout_level = sec_bat_check_wpc_vout(battery, battery->cable_type, battery->chg_limit,
  311. battery->wpc_vout_level, battery->current_event);
  312. }
  313. if (battery->disable_mfc) {
  314. pr_info("%s : set mfc %s\n", __func__, (en ? "on" : "off"));
  315. if (en)
  316. sec_bat_set_mfc_on(battery, WPC_EN_CHARGING);
  317. else
  318. sec_bat_set_mfc_off(battery, WPC_EN_CHARGING, false);
  319. }
  320. }
  321. __visible_for_testing int sec_bat_get_wire_power(struct sec_battery_info *battery, int wr_sts)
  322. {
  323. int wr_pwr = 0;
  324. int wr_icl = 0, wr_vol = 0;
  325. if (!is_wired_type(wr_sts))
  326. return 0;
  327. if (is_pd_wire_type(wr_sts))
  328. return battery->pd_max_charge_power;
  329. wr_icl = (wr_sts == SEC_BATTERY_CABLE_PREPARE_TA ?
  330. battery->pdata->charging_current[SEC_BATTERY_CABLE_TA].input_current_limit :
  331. battery->pdata->charging_current[wr_sts].input_current_limit);
  332. wr_vol = is_hv_wire_type(wr_sts) ?
  333. (wr_sts == SEC_BATTERY_CABLE_12V_TA ? SEC_INPUT_VOLTAGE_12V : SEC_INPUT_VOLTAGE_9V)
  334. : SEC_INPUT_VOLTAGE_5V;
  335. wr_pwr = mW_by_mVmA(wr_vol, wr_icl);
  336. pr_info("%s: wr_power(%d), wire_cable_type(%d)\n", __func__, wr_pwr, wr_sts);
  337. return wr_pwr;
  338. }
  339. __visible_for_testing int sec_bat_get_wireless_power(struct sec_battery_info *battery, int wrl_sts)
  340. {
  341. int wrl_icl = 0, wrl_pwr = 0;
  342. if (wrl_sts == SEC_BATTERY_CABLE_PREPARE_WIRELESS_HV)
  343. wrl_sts = SEC_BATTERY_CABLE_HV_WIRELESS;
  344. else if (wrl_sts == SEC_BATTERY_CABLE_PREPARE_WIRELESS_20)
  345. wrl_sts = SEC_BATTERY_CABLE_HV_WIRELESS_20;
  346. wrl_icl = battery->pdata->charging_current[wrl_sts].input_current_limit;
  347. if (battery->sleep_mode)
  348. wrl_pwr = mW_by_mVmA(SEC_INPUT_VOLTAGE_5_5V, battery->pdata->sleep_mode_limit_current);
  349. else if (is_nv_wireless_type(wrl_sts) || (wrl_sts == SEC_BATTERY_CABLE_WIRELESS_FAKE))
  350. wrl_pwr = mW_by_mVmA(SEC_INPUT_VOLTAGE_5_5V, wrl_icl);
  351. else if (is_pwr_nego_wireless_type(wrl_sts) || (wrl_sts == SEC_BATTERY_CABLE_WIRELESS_EPP_FAKE))
  352. wrl_pwr = mW_by_mVmA(battery->wc20_vout, wrl_icl);
  353. else
  354. wrl_pwr = mW_by_mVmA(SEC_INPUT_VOLTAGE_10V, wrl_icl);
  355. return wrl_pwr;
  356. }
  357. __visible_for_testing void sec_bat_switch_to_wr(struct sec_battery_info *battery, int wrl_sts, int prev_ct)
  358. {
  359. union power_supply_propval val = {0, };
  360. pr_info("%s\n", __func__);
  361. if (wrl_sts == SEC_BATTERY_CABLE_PREPARE_WIRELESS_20)
  362. wrl_sts = SEC_BATTERY_CABLE_HV_WIRELESS_20;
  363. /* limit charging current before change path between chgin and wcin */
  364. if (is_pwr_nego_wireless_type(prev_ct) &&
  365. is_pwr_nego_wireless_type(wrl_sts)) {
  366. /* limit charging current before change path between chgin and wcin */
  367. pr_info("%s: set charging current %dmA for a moment in case of TA OCP\n",
  368. __func__, battery->pdata->wpc_charging_limit_current);
  369. sec_vote(battery->fcc_vote, VOTER_CABLE, true, battery->pdata->wpc_charging_limit_current);
  370. msleep(100);
  371. }
  372. sec_bat_mfc_ldo_cntl(battery, MFC_LDO_OFF);
  373. /* Turn off TX to charge by cable charging having more power */
  374. if (wrl_sts == SEC_BATTERY_CABLE_WIRELESS_TX) {
  375. pr_info("@Tx_Mode %s: RX device with TA, notify TX device of this info\n",
  376. __func__);
  377. val.intval = true;
  378. psy_do_property(battery->pdata->wireless_charger_name, set,
  379. POWER_SUPPLY_EXT_PROP_WIRELESS_SWITCH, val);
  380. }
  381. }
  382. __visible_for_testing void sec_bat_switch_to_wrl(struct sec_battery_info *battery, int wr_sts, int prev_ct)
  383. {
  384. pr_info("%s\n", __func__);
  385. if (!is_wireless_type(prev_ct)) {
  386. /* limit charging current before change path between chgin and wcin */
  387. pr_info("%s: set charging current %dmA for a moment in case of TA OCP\n",
  388. __func__, battery->pdata->wpc_charging_limit_current);
  389. sec_vote(battery->fcc_vote, VOTER_CABLE, true, battery->pdata->wpc_charging_limit_current);
  390. msleep(100);
  391. }
  392. /* turn on ldo when ldo was off because of TA, */
  393. /* ldo is supposed to turn on automatically except force off by sw. */
  394. /* do not turn on ldo every wireless connection just in case ldo re-toggle by ic */
  395. if (!is_nocharge_type(wr_sts)) {
  396. sec_bat_mfc_ldo_cntl(battery, MFC_LDO_ON);
  397. }
  398. }
  399. int sec_bat_choose_cable_type(struct sec_battery_info *battery)
  400. {
  401. int wr_sts = battery->wire_status;
  402. int cur_ct = wr_sts;
  403. int prev_ct = battery->cable_type;
  404. int wrl_sts = battery->wc_status;
  405. union power_supply_propval value = {0, };
  406. if (wrl_sts != SEC_BATTERY_CABLE_NONE) {
  407. cur_ct = wrl_sts;
  408. if (!is_nocharge_type(wr_sts)) {
  409. int wrl_pwr, wr_pwr;
  410. wr_pwr = sec_bat_get_wire_power(battery, wr_sts);
  411. wrl_pwr = sec_bat_get_wireless_power(battery, wrl_sts);
  412. if (wrl_pwr <= wr_pwr)
  413. cur_ct = wr_sts;
  414. pr_info("%s: wrl_pwr(%d), wr_pwr(%d), wc_sts(%d), wr_sts(%d), cur_ct(%d)\n",
  415. __func__, wrl_pwr, wr_pwr, wrl_sts, wr_sts, cur_ct);
  416. if (is_wireless_type(cur_ct))
  417. sec_bat_switch_to_wrl(battery, wr_sts, prev_ct);
  418. else {
  419. if (is_hv_wireless_type(wrl_sts)) {
  420. value.intval = WIRELESS_VOUT_FORCE_9V;
  421. psy_do_property(battery->pdata->wireless_charger_name, set,
  422. POWER_SUPPLY_EXT_PROP_INPUT_VOLTAGE_REGULATION, value);
  423. msleep(200);
  424. value.intval = WIRELESS_VOUT_5V;
  425. psy_do_property(battery->pdata->wireless_charger_name, set,
  426. POWER_SUPPLY_EXT_PROP_INPUT_VOLTAGE_REGULATION, value);
  427. }
  428. if (is_wireless_all_type(prev_ct)) {
  429. msleep(200);
  430. sec_vote(battery->fcc_vote, VOTER_WL_TO_W, true, 300);
  431. msleep(200);
  432. sec_vote(battery->fcc_vote, VOTER_WL_TO_W, true, 100);
  433. msleep(200);
  434. sec_vote(battery->chgen_vote, VOTER_WL_TO_W, true, SEC_BAT_CHG_MODE_BUCK_OFF);
  435. value.intval = WL_TO_W;
  436. psy_do_property(battery->pdata->charger_name, set,
  437. POWER_SUPPLY_EXT_PROP_CHGINSEL, value);
  438. }
  439. sec_bat_switch_to_wr(battery, wrl_sts, prev_ct);
  440. sec_vote(battery->input_vote, VOTER_WPC_CUR, false, 0);
  441. sec_vote(battery->fcc_vote, VOTER_WL_TO_W, false, 0);
  442. sec_vote(battery->chgen_vote, VOTER_WL_TO_W, false, 0);
  443. }
  444. } else {
  445. if (battery->wc_need_ldo_on)
  446. sec_bat_mfc_ldo_cntl(battery, MFC_LDO_ON);
  447. }
  448. } else if (is_nocharge_type(wr_sts) && battery->disable_mfc) {
  449. pr_info("%s : sec_bat_set_mfc_on because of CABLE_NONE\n", __func__);
  450. sec_bat_set_mfc_on(battery, WPC_EN_CHARGING);
  451. }
  452. return cur_ct;
  453. }
  454. void sec_bat_get_wireless_current(struct sec_battery_info *battery)
  455. {
  456. int incurr = INT_MAX;
  457. union power_supply_propval value = {0, };
  458. /* WPC_SLEEP_MODE */
  459. if (is_hv_wireless_type(battery->cable_type) && battery->sleep_mode) {
  460. if (incurr > battery->pdata->sleep_mode_limit_current)
  461. incurr = battery->pdata->sleep_mode_limit_current;
  462. pr_info("%s: sleep_mode = %d, chg_limit = %d, in_curr = %d\n",
  463. __func__, battery->sleep_mode, battery->chg_limit, incurr);
  464. if (!battery->auto_mode) {
  465. /* send cmd once */
  466. battery->auto_mode = true;
  467. value.intval = WIRELESS_SLEEP_MODE_ENABLE;
  468. psy_do_property(battery->pdata->wireless_charger_name, set,
  469. POWER_SUPPLY_EXT_PROP_WIRELESS_RX_CONTROL, value);
  470. }
  471. }
  472. /* WPC_TEMP_MODE */
  473. if (is_wireless_type(battery->cable_type) && battery->chg_limit) {
  474. if ((battery->siop_level >= 100 && !battery->lcd_status) &&
  475. (incurr > battery->pdata->wpc_input_limit_current)) {
  476. if (battery->cable_type == SEC_BATTERY_CABLE_WIRELESS_TX &&
  477. battery->pdata->wpc_input_limit_by_tx_check)
  478. incurr = battery->pdata->wpc_input_limit_current_by_tx;
  479. else
  480. incurr = battery->pdata->wpc_input_limit_current;
  481. } else if ((battery->siop_level < 100 || battery->lcd_status) &&
  482. (incurr > battery->pdata->wpc_lcd_on_input_limit_current))
  483. incurr = battery->pdata->wpc_lcd_on_input_limit_current;
  484. }
  485. /* Display flicker W/A */
  486. if (battery->pdata->wpc_vout_ctrl_lcd_on && battery->wpc_vout_ctrl_mode && battery->lcd_status) {
  487. if (is_wireless_type(battery->cable_type) && battery->pdata->wpc_flicker_wa_input_limit_current) {
  488. psy_do_property(battery->pdata->wireless_charger_name, get,
  489. POWER_SUPPLY_EXT_PROP_WIRELESS_TX_ID, value);
  490. if ((value.intval != WC_PAD_ID_UNKNOWN) &&
  491. (value.intval != WC_PAD_ID_SNGL_DREAM) &&
  492. (value.intval != WC_PAD_ID_STAND_DREAM)) {
  493. pr_info("%s: trigger flicker wa\n", __func__);
  494. if (incurr > battery->pdata->wpc_flicker_wa_input_limit_current)
  495. incurr = battery->pdata->wpc_flicker_wa_input_limit_current;
  496. }
  497. }
  498. }
  499. /* Full-Additional state */
  500. if (battery->status == POWER_SUPPLY_STATUS_FULL) {
  501. if ((incurr > battery->pdata->siop_hv_wpc_icl) &&
  502. (battery->charging_mode == SEC_BATTERY_CHARGING_2ND))
  503. incurr = battery->pdata->siop_hv_wpc_icl;
  504. if ((incurr > battery->pdata->rechg_hv_wpc_icl) && battery->is_recharging)
  505. incurr = battery->pdata->rechg_hv_wpc_icl;
  506. }
  507. /* Hero Stand Pad CV */
  508. if (battery->capacity >= battery->pdata->wc_hero_stand_cc_cv) {
  509. if (battery->cable_type == SEC_BATTERY_CABLE_WIRELESS_STAND) {
  510. if (incurr > battery->pdata->wc_hero_stand_cv_current)
  511. incurr = battery->pdata->wc_hero_stand_cv_current;
  512. } else if (battery->cable_type == SEC_BATTERY_CABLE_WIRELESS_HV_STAND) {
  513. if (battery->chg_limit &&
  514. incurr > battery->pdata->wc_hero_stand_cv_current) {
  515. incurr = battery->pdata->wc_hero_stand_cv_current;
  516. } else if (!battery->chg_limit &&
  517. incurr > battery->pdata->wc_hero_stand_hv_cv_current) {
  518. incurr = battery->pdata->wc_hero_stand_hv_cv_current;
  519. }
  520. }
  521. }
  522. /* Full-None state && SIOP_LEVEL 100 */
  523. if ((battery->siop_level >= 100 && !battery->lcd_status) &&
  524. battery->status == POWER_SUPPLY_STATUS_FULL && battery->charging_mode == SEC_BATTERY_CHARGING_NONE) {
  525. incurr = battery->pdata->wc_full_input_limit_current;
  526. }
  527. if (incurr != INT_MAX)
  528. sec_vote(battery->input_vote, VOTER_WPC_CUR, true, incurr);
  529. else
  530. sec_vote(battery->input_vote, VOTER_WPC_CUR, false, incurr);
  531. }
  532. int sec_bat_check_wc_available(struct sec_battery_info *battery)
  533. {
  534. mutex_lock(&battery->wclock);
  535. if (!battery->wc_enable) {
  536. pr_info("%s: wc_enable(%d), cnt(%d)\n", __func__, battery->wc_enable, battery->wc_enable_cnt);
  537. if (battery->wc_enable_cnt > battery->wc_enable_cnt_value) {
  538. union power_supply_propval val = {0, };
  539. char wpc_en_status[2];
  540. battery->wc_enable = true;
  541. battery->wc_enable_cnt = 0;
  542. wpc_en_status[0] = WPC_EN_SYSFS;
  543. wpc_en_status[1] = true;
  544. val.strval = wpc_en_status;
  545. psy_do_property(battery->pdata->wireless_charger_name, set,
  546. POWER_SUPPLY_EXT_PROP_WPC_EN, val);
  547. pr_info("%s: WC CONTROL: Enable\n", __func__);
  548. }
  549. battery->wc_enable_cnt++;
  550. }
  551. mutex_unlock(&battery->wclock);
  552. return 0;
  553. }
  554. /* OTG during HV wireless charging or sleep mode have 4.5W normal wireless charging UI */
  555. bool sec_bat_hv_wc_normal_mode_check(struct sec_battery_info *battery)
  556. {
  557. union power_supply_propval value = {0, };
  558. psy_do_property(battery->pdata->charger_name, get,
  559. POWER_SUPPLY_EXT_PROP_CHARGE_OTG_CONTROL, value);
  560. if (value.intval || battery->sleep_mode) {
  561. pr_info("%s: otg(%d), sleep_mode(%d)\n", __func__, value.intval, battery->sleep_mode);
  562. return true;
  563. }
  564. return false;
  565. }
  566. EXPORT_SYMBOL_KUNIT(sec_bat_hv_wc_normal_mode_check);
  567. void sec_bat_ext_event_work_content(struct sec_battery_info *battery)
  568. {
  569. union power_supply_propval value = {0, };
  570. if (battery->wc_tx_enable) { /* TX ON state */
  571. if (battery->ext_event & BATT_EXT_EVENT_CAMERA) {
  572. pr_info("@Tx_Mode %s: Camera ON, TX OFF\n", __func__);
  573. sec_bat_set_tx_event(battery,
  574. BATT_TX_EVENT_WIRELESS_TX_CAMERA_ON, BATT_TX_EVENT_WIRELESS_TX_CAMERA_ON);
  575. sec_wireless_set_tx_enable(battery, false);
  576. } else if (battery->ext_event & BATT_EXT_EVENT_DEX) {
  577. pr_info("@Tx_Mode %s: Dex ON, TX OFF\n", __func__);
  578. sec_bat_set_tx_event(battery,
  579. BATT_TX_EVENT_WIRELESS_TX_OTG_ON, BATT_TX_EVENT_WIRELESS_TX_OTG_ON);
  580. sec_wireless_set_tx_enable(battery, false);
  581. } else if (battery->ext_event & BATT_EXT_EVENT_CALL) {
  582. pr_info("@Tx_Mode %s: Call ON, TX OFF\n", __func__);
  583. battery->tx_retry_case |= SEC_BAT_TX_RETRY_CALL;
  584. /* clear tx all event */
  585. sec_bat_set_tx_event(battery, 0, BATT_TX_EVENT_WIRELESS_ALL_MASK);
  586. sec_wireless_set_tx_enable(battery, false);
  587. }
  588. } else { /* TX OFF state, it has only call scenario */
  589. if (battery->ext_event & BATT_EXT_EVENT_CALL) {
  590. pr_info("@Tx_Mode %s: Call ON\n", __func__);
  591. value.intval = BATT_EXT_EVENT_CALL;
  592. psy_do_property(battery->pdata->wireless_charger_name, set,
  593. POWER_SUPPLY_EXT_PROP_CALL_EVENT, value);
  594. #if !defined(CONFIG_WIRELESS_RX_PHM_CTRL)
  595. if (battery->cable_type == SEC_BATTERY_CABLE_WIRELESS_PACK ||
  596. battery->cable_type == SEC_BATTERY_CABLE_WIRELESS_HV_PACK ||
  597. battery->cable_type == SEC_BATTERY_CABLE_WIRELESS_TX) {
  598. pr_info("%s: Call is on during Wireless Pack or TX\n", __func__);
  599. battery->wc_rx_phm_mode = true;
  600. }
  601. #endif
  602. if (battery->tx_retry_case != SEC_BAT_TX_RETRY_NONE) {
  603. pr_info("@Tx_Mode %s: TX OFF because of other reason(retry:0x%x), save call retry case\n",
  604. __func__, battery->tx_retry_case);
  605. battery->tx_retry_case |= SEC_BAT_TX_RETRY_CALL;
  606. }
  607. } else if (!(battery->ext_event & BATT_EXT_EVENT_CALL)) {
  608. pr_info("@Tx_Mode %s: Call OFF\n", __func__);
  609. value.intval = BATT_EXT_EVENT_NONE;
  610. psy_do_property(battery->pdata->wireless_charger_name, set,
  611. POWER_SUPPLY_EXT_PROP_CALL_EVENT, value);
  612. /* check the diff between current and previous ext_event state */
  613. if (battery->tx_retry_case & SEC_BAT_TX_RETRY_CALL) {
  614. battery->tx_retry_case &= ~SEC_BAT_TX_RETRY_CALL;
  615. if (!battery->tx_retry_case) {
  616. pr_info("@Tx_Mode %s: Call OFF, TX Retry\n", __func__);
  617. sec_bat_set_tx_event(battery,
  618. BATT_TX_EVENT_WIRELESS_TX_RETRY,
  619. BATT_TX_EVENT_WIRELESS_TX_RETRY);
  620. }
  621. }
  622. #if !defined(CONFIG_WIRELESS_RX_PHM_CTRL)
  623. /* process escape phm */
  624. if (battery->wc_rx_phm_mode) {
  625. pr_info("%s: ESCAPE PHM STEP 1\n", __func__);
  626. sec_bat_set_mfc_on(battery, WPC_EN_CHARGING);
  627. msleep(100);
  628. pr_info("%s: ESCAPE PHM STEP 2\n", __func__);
  629. sec_bat_set_mfc_off(battery, WPC_EN_CHARGING, false);
  630. msleep(510);
  631. pr_info("%s: ESCAPE PHM STEP 3\n", __func__);
  632. sec_bat_set_mfc_on(battery, WPC_EN_CHARGING);
  633. }
  634. battery->wc_rx_phm_mode = false;
  635. #endif
  636. }
  637. }
  638. __pm_relax(battery->ext_event_ws);
  639. }
  640. void sec_bat_wireless_minduty_cntl(struct sec_battery_info *battery, unsigned int duty_val)
  641. {
  642. union power_supply_propval value = {0, };
  643. if (duty_val != battery->tx_minduty) {
  644. value.intval = duty_val;
  645. psy_do_property(battery->pdata->wireless_charger_name, set,
  646. POWER_SUPPLY_EXT_PROP_WIRELESS_MIN_DUTY, value);
  647. pr_info("@Tx_Mode %s: Min duty changed (%d -> %d)\n", __func__, battery->tx_minduty, duty_val);
  648. battery->tx_minduty = duty_val;
  649. }
  650. }
  651. void sec_bat_wireless_set_ping_duty(struct sec_battery_info *battery, unsigned int ping_duty_val)
  652. {
  653. union power_supply_propval value = {0, };
  654. if (ping_duty_val != battery->tx_ping_duty) {
  655. value.intval = ping_duty_val;
  656. psy_do_property(battery->pdata->wireless_charger_name, set,
  657. POWER_SUPPLY_EXT_PROP_WIRELESS_PING_DUTY, value);
  658. pr_info("@Tx_Mode %s: Ping duty changed (%d -> %d)\n",
  659. __func__, battery->tx_ping_duty, ping_duty_val);
  660. battery->tx_ping_duty = ping_duty_val;
  661. }
  662. }
  663. void sec_bat_wireless_uno_cntl(struct sec_battery_info *battery, bool en)
  664. {
  665. union power_supply_propval value = {0, };
  666. value.intval = en;
  667. battery->uno_en = en;
  668. pr_info("@Tx_Mode %s: Uno control %d\n", __func__, en);
  669. psy_do_property(battery->pdata->wireless_charger_name, set,
  670. POWER_SUPPLY_EXT_PROP_WIRELESS_TX_ENABLE, value);
  671. sb_tx_set_enable(en, 0);
  672. }
  673. void sec_bat_wireless_iout_cntl(struct sec_battery_info *battery, int uno_iout, int mfc_iout)
  674. {
  675. union power_supply_propval value = {0, };
  676. if (battery->tx_uno_iout != uno_iout) {
  677. pr_info("@Tx_Mode %s: set uno iout(%d) -> (%d)\n", __func__, battery->tx_uno_iout, uno_iout);
  678. value.intval = battery->tx_uno_iout = uno_iout;
  679. psy_do_property("otg", set,
  680. POWER_SUPPLY_EXT_PROP_WIRELESS_TX_IOUT, value);
  681. } else {
  682. pr_info("@Tx_Mode %s: Already set Uno Iout(%d == %d)\n", __func__, battery->tx_uno_iout, uno_iout);
  683. }
  684. #if !defined(CONFIG_SEC_FACTORY)
  685. if (battery->lcd_status && (mfc_iout == battery->pdata->tx_mfc_iout_phone)) {
  686. pr_info("@Tx_Mode %s: Reduce Tx MFC Iout. LCD ON\n", __func__);
  687. mfc_iout = battery->pdata->tx_mfc_iout_lcd_on;
  688. }
  689. #endif
  690. if (battery->tx_mfc_iout != mfc_iout) {
  691. pr_info("@Tx_Mode %s: set mfc iout(%d) -> (%d)\n", __func__, battery->tx_mfc_iout, mfc_iout);
  692. value.intval = battery->tx_mfc_iout = mfc_iout;
  693. psy_do_property(battery->pdata->wireless_charger_name, set,
  694. POWER_SUPPLY_EXT_PROP_WIRELESS_TX_IOUT, value);
  695. } else {
  696. pr_info("@Tx_Mode %s: Already set MFC Iout(%d == %d)\n", __func__, battery->tx_mfc_iout, mfc_iout);
  697. }
  698. }
  699. void sec_bat_wireless_vout_cntl(struct sec_battery_info *battery, int vout_now)
  700. {
  701. union power_supply_propval value = {0, };
  702. pr_info("@Tx_Mode %s: set uno & mfc vout (%dmV -> %dmV)\n", __func__, battery->wc_tx_vout, vout_now);
  703. if (battery->wc_tx_vout >= vout_now) {
  704. battery->wc_tx_vout = value.intval = vout_now;
  705. psy_do_property(battery->pdata->wireless_charger_name, set,
  706. POWER_SUPPLY_EXT_PROP_WIRELESS_TX_VOUT, value);
  707. psy_do_property("otg", set,
  708. POWER_SUPPLY_EXT_PROP_WIRELESS_TX_VOUT, value);
  709. } else if (vout_now > battery->wc_tx_vout) {
  710. battery->wc_tx_vout = value.intval = vout_now;
  711. psy_do_property("otg", set,
  712. POWER_SUPPLY_EXT_PROP_WIRELESS_TX_VOUT, value);
  713. psy_do_property(battery->pdata->wireless_charger_name, set,
  714. POWER_SUPPLY_EXT_PROP_WIRELESS_TX_VOUT, value);
  715. }
  716. }
  717. #if defined(CONFIG_WIRELESS_TX_MODE)
  718. #if !defined(CONFIG_SEC_FACTORY)
  719. static void sec_bat_check_tx_battery_drain(struct sec_battery_info *battery)
  720. {
  721. if (battery->capacity <= battery->pdata->tx_stop_capacity &&
  722. is_nocharge_type(battery->cable_type)) {
  723. pr_info("@Tx_Mode %s: battery level is drained, TX mode should turn off\n", __func__);
  724. /* set tx event */
  725. sec_bat_set_tx_event(battery, BATT_TX_EVENT_WIRELESS_TX_SOC_DRAIN, BATT_TX_EVENT_WIRELESS_TX_SOC_DRAIN);
  726. sec_wireless_set_tx_enable(battery, false);
  727. }
  728. }
  729. static void sec_bat_check_tx_current(struct sec_battery_info *battery)
  730. {
  731. if (battery->lcd_status && (battery->tx_mfc_iout > battery->pdata->tx_mfc_iout_lcd_on)) {
  732. sec_bat_wireless_iout_cntl(battery, battery->pdata->tx_uno_iout, battery->pdata->tx_mfc_iout_lcd_on);
  733. pr_info("@Tx_Mode %s: Reduce Tx MFC Iout. LCD ON\n", __func__);
  734. } else if (!battery->lcd_status && (battery->tx_mfc_iout == battery->pdata->tx_mfc_iout_lcd_on)) {
  735. union power_supply_propval value = {0, };
  736. sec_bat_wireless_iout_cntl(battery, battery->pdata->tx_uno_iout, battery->pdata->tx_mfc_iout_phone);
  737. pr_info("@Tx_Mode %s: Recovery Tx MFC Iout. LCD OFF\n", __func__);
  738. value.intval = true;
  739. psy_do_property(battery->pdata->wireless_charger_name, set,
  740. POWER_SUPPLY_EXT_PROP_WIRELESS_SEND_FSK, value);
  741. }
  742. }
  743. #endif
  744. static void sec_bat_check_tx_switch_mode(struct sec_battery_info *battery)
  745. {
  746. union power_supply_propval value = {0, };
  747. /* temporary mode */
  748. if (battery->tx_switch_mode == TX_SWITCH_GEAR_PPS) {
  749. pr_info("@Tx_mode %s: skip routine in gear pps mode.\n", __func__);
  750. return;
  751. }
  752. if (battery->current_event & SEC_BAT_CURRENT_EVENT_AFC) {
  753. pr_info("@Tx_mode %s: Do not switch switch mode! AFC Event set\n", __func__);
  754. return;
  755. }
  756. value.intval = SEC_FUELGAUGE_CAPACITY_TYPE_CAPACITY_POINT;
  757. psy_do_property(battery->pdata->fuelgauge_name, get,
  758. POWER_SUPPLY_PROP_CAPACITY, value);
  759. if ((battery->tx_switch_mode == TX_SWITCH_UNO_ONLY) && (!battery->buck_cntl_by_tx)) {
  760. battery->buck_cntl_by_tx = true;
  761. sec_vote(battery->chgen_vote, VOTER_WC_TX, true, SEC_BAT_CHG_MODE_BUCK_OFF);
  762. sec_bat_wireless_iout_cntl(battery, battery->pdata->tx_uno_iout, battery->pdata->tx_mfc_iout_phone);
  763. sec_bat_wireless_vout_cntl(battery, battery->pdata->tx_uno_vout);
  764. sec_bat_wireless_minduty_cntl(battery, battery->pdata->tx_minduty_default);
  765. } else if ((battery->tx_switch_mode == TX_SWITCH_CHG_ONLY) && (battery->buck_cntl_by_tx)) {
  766. sec_bat_wireless_iout_cntl(battery, battery->pdata->tx_uno_iout, battery->pdata->tx_mfc_iout_phone_5v);
  767. sec_bat_wireless_vout_cntl(battery, battery->pdata->tx_ping_vout);
  768. sec_bat_wireless_minduty_cntl(battery, battery->pdata->tx_minduty_5V);
  769. battery->buck_cntl_by_tx = false;
  770. sec_vote(battery->chgen_vote, VOTER_WC_TX, false, 0);
  771. }
  772. if (battery->status == POWER_SUPPLY_STATUS_FULL) {
  773. if (battery->charging_mode == SEC_BATTERY_CHARGING_NONE) {
  774. if (battery->tx_switch_mode == TX_SWITCH_CHG_ONLY)
  775. battery->tx_switch_mode_change = true;
  776. } else {
  777. if (battery->tx_switch_mode == TX_SWITCH_UNO_ONLY) {
  778. if (battery->tx_switch_start_soc >= 100) {
  779. if (battery->capacity < 99 || (battery->capacity == 99 && value.intval <= 1))
  780. battery->tx_switch_mode_change = true;
  781. } else {
  782. if ((battery->capacity == battery->tx_switch_start_soc && value.intval <= 1) ||
  783. (battery->capacity < battery->tx_switch_start_soc))
  784. battery->tx_switch_mode_change = true;
  785. }
  786. } else if (battery->tx_switch_mode == TX_SWITCH_CHG_ONLY) {
  787. if (battery->capacity >= 100)
  788. battery->tx_switch_mode_change = true;
  789. }
  790. }
  791. } else {
  792. if (battery->tx_switch_mode == TX_SWITCH_UNO_ONLY) {
  793. if (((battery->capacity == battery->tx_switch_start_soc) && (value.intval <= 1)) ||
  794. (battery->capacity < battery->tx_switch_start_soc))
  795. battery->tx_switch_mode_change = true;
  796. } else if (battery->tx_switch_mode == TX_SWITCH_CHG_ONLY) {
  797. if (((battery->capacity == (battery->tx_switch_start_soc + 1)) && (value.intval >= 8)) ||
  798. (battery->capacity > (battery->tx_switch_start_soc + 1)))
  799. battery->tx_switch_mode_change = true;
  800. }
  801. }
  802. pr_info("@Tx_mode Tx mode(%d) tx_switch_mode_change(%d) start soc(%d) now soc(%d.%d)\n",
  803. battery->tx_switch_mode, battery->tx_switch_mode_change,
  804. battery->tx_switch_start_soc, battery->capacity, value.intval);
  805. }
  806. #endif
  807. void sec_bat_txpower_calc(struct sec_battery_info *battery)
  808. {
  809. if (delayed_work_pending(&battery->wpc_txpower_calc_work)) {
  810. pr_info("%s: keep average tx power(%5d mA)\n", __func__, battery->tx_avg_curr);
  811. } else if (battery->wc_tx_enable) {
  812. int tx_vout = 0, tx_iout = 0, vbatt = 0;
  813. union power_supply_propval value = {0, };
  814. psy_do_property(battery->pdata->wireless_charger_name, get,
  815. POWER_SUPPLY_EXT_PROP_WIRELESS_TX_UNO_VIN, value);
  816. tx_vout = value.intval;
  817. psy_do_property(battery->pdata->wireless_charger_name, get,
  818. POWER_SUPPLY_EXT_PROP_WIRELESS_TX_UNO_IIN, value);
  819. tx_iout = value.intval;
  820. value.intval = SEC_BATTERY_VOLTAGE_MV;
  821. psy_do_property(battery->pdata->fuelgauge_name, get,
  822. POWER_SUPPLY_PROP_VOLTAGE_NOW, value);
  823. vbatt = value.intval;
  824. battery->tx_time_cnt++;
  825. /* AVG curr will be calculated only when the battery is discharged */
  826. if (battery->current_avg <= 0 && vbatt > 0 && tx_vout > 0 && tx_iout > 0)
  827. tx_iout = (tx_vout / vbatt) * tx_iout;
  828. else
  829. tx_iout = 0;
  830. /* monitor work will be scheduled every 10s when wc_tx_enable is true */
  831. battery->tx_avg_curr =
  832. ((battery->tx_avg_curr * battery->tx_time_cnt) + tx_iout) / (battery->tx_time_cnt + 1);
  833. battery->tx_total_power =
  834. (battery->tx_avg_curr * battery->tx_time_cnt) / (60 * 60 / 10);
  835. if (battery->tx_total_power > ((battery->pdata->battery_full_capacity * 7) / 10)) {
  836. pr_info("%s: tx_total_power(%dmAh) is wrong\n", __func__, battery->tx_total_power);
  837. battery->tx_total_power = (battery->pdata->battery_full_capacity * 7) / 10;
  838. }
  839. pr_info("%s: tx_time_cnt(%ds), UNO_Vin(%dV), UNO_Iin(%dmA), tx_avg_curr(%dmA), tx_total_power(%dmAh)\n",
  840. __func__, battery->tx_time_cnt * 10, tx_vout, tx_iout, battery->tx_avg_curr, battery->tx_total_power);
  841. }
  842. }
  843. void sec_bat_tx_off_by_misalign_ocp(struct sec_battery_info *battery)
  844. {
  845. battery->tx_retry_case &= ~(SEC_BAT_TX_RETRY_MISALIGN | SEC_BAT_TX_RETRY_OCP);
  846. battery->tx_misalign_start_time = 0;
  847. battery->tx_misalign_cnt = 0;
  848. battery->tx_ocp_start_time = 0;
  849. battery->tx_ocp_cnt = 0;
  850. }
  851. void sec_bat_handle_tx_misalign(struct sec_battery_info *battery, bool trigger_misalign)
  852. {
  853. struct timespec64 ts = {0, };
  854. if (trigger_misalign && battery->wc_tx_enable) {
  855. if (battery->tx_misalign_start_time == 0) {
  856. ts = ktime_to_timespec64(ktime_get_boottime());
  857. battery->tx_misalign_start_time = ts.tv_sec;
  858. }
  859. pr_info("@Tx_Mode %s: misalign is triggered!!(%d)\n", __func__, ++battery->tx_misalign_cnt);
  860. /* Attention!! in this case, 0x00(TX_OFF) is sent first */
  861. /* and then 0x8000(RETRY) is sent */
  862. if (battery->tx_misalign_cnt < MISALIGN_TX_TRY_CNT) {
  863. battery->tx_retry_case |= SEC_BAT_TX_RETRY_MISALIGN;
  864. sec_wireless_set_tx_enable(battery, false);
  865. msleep(1000);
  866. /* clear tx all event */
  867. sec_bat_set_tx_event(battery, 0, BATT_TX_EVENT_WIRELESS_ALL_MASK);
  868. sec_bat_set_tx_event(battery,
  869. BATT_TX_EVENT_WIRELESS_TX_RETRY, BATT_TX_EVENT_WIRELESS_TX_RETRY);
  870. msleep(1000);
  871. } else {
  872. pr_info("@Tx_Mode %s: Misalign over %d times, TX OFF (cancel misalign)\n",
  873. __func__, MISALIGN_TX_TRY_CNT);
  874. sec_bat_tx_off_by_misalign_ocp(battery);
  875. sec_bat_set_tx_event(battery,
  876. BATT_TX_EVENT_WIRELESS_TX_MISALIGN, BATT_TX_EVENT_WIRELESS_TX_MISALIGN);
  877. sec_wireless_set_tx_enable(battery, false);
  878. }
  879. } else if (battery->tx_retry_case & SEC_BAT_TX_RETRY_MISALIGN) {
  880. ts = ktime_to_timespec64(ktime_get_boottime());
  881. if (ts.tv_sec >= battery->tx_misalign_start_time) {
  882. battery->tx_misalign_passed_time = ts.tv_sec - battery->tx_misalign_start_time;
  883. } else {
  884. battery->tx_misalign_passed_time = 0xFFFFFFFF - battery->tx_misalign_start_time
  885. + ts.tv_sec;
  886. }
  887. pr_info("@Tx_Mode %s: already misaligned, passed time(%ld)\n",
  888. __func__, battery->tx_misalign_passed_time);
  889. if (battery->tx_misalign_passed_time >= 60) {
  890. pr_info("@Tx_Mode %s: after 1min\n", __func__);
  891. if (battery->wc_tx_enable) {
  892. if (battery->wc_rx_connected) {
  893. pr_info("@Tx_Mode %s: RX Dev, Keep TX ON status (cancel misalign)\n", __func__);
  894. } else {
  895. pr_info("@Tx_Mode %s: NO RX Dev, TX OFF (cancel misalign)\n", __func__);
  896. sec_bat_tx_off_by_misalign_ocp(battery);
  897. sec_bat_set_tx_event(battery,
  898. BATT_TX_EVENT_WIRELESS_TX_MISALIGN, BATT_TX_EVENT_WIRELESS_TX_MISALIGN);
  899. sec_wireless_set_tx_enable(battery, false);
  900. }
  901. } else {
  902. pr_info("@Tx_Mode %s: Keep TX OFF status (cancel misalign)\n", __func__);
  903. }
  904. battery->tx_retry_case &= ~SEC_BAT_TX_RETRY_MISALIGN;
  905. battery->tx_misalign_start_time = 0;
  906. battery->tx_misalign_cnt = 0;
  907. }
  908. }
  909. }
  910. EXPORT_SYMBOL_KUNIT(sec_bat_handle_tx_misalign);
  911. void sec_bat_handle_tx_ocp(struct sec_battery_info *battery, bool trigger_ocp)
  912. {
  913. struct timespec64 ts = {0, };
  914. if (trigger_ocp && battery->wc_tx_enable) {
  915. if (battery->tx_ocp_start_time == 0) {
  916. ts = ktime_to_timespec64(ktime_get_boottime());
  917. battery->tx_ocp_start_time = ts.tv_sec;
  918. }
  919. pr_info("@Tx_Mode %s: ocp is triggered!!(%d)\n", __func__, ++battery->tx_ocp_cnt);
  920. /* Attention!! in this case, 0x00(TX_OFF) is sent first */
  921. /* and then 0x8000(RETRY) is sent */
  922. if (battery->tx_ocp_cnt < 3) {
  923. battery->tx_retry_case |= SEC_BAT_TX_RETRY_OCP;
  924. sec_wireless_set_tx_enable(battery, false);
  925. msleep(1000);
  926. /* clear tx all event */
  927. sec_bat_set_tx_event(battery, 0, BATT_TX_EVENT_WIRELESS_ALL_MASK);
  928. sec_bat_set_tx_event(battery,
  929. BATT_TX_EVENT_WIRELESS_TX_RETRY, BATT_TX_EVENT_WIRELESS_TX_RETRY);
  930. msleep(1000);
  931. } else {
  932. pr_info("@Tx_Mode %s: ocp over 3 times, TX OFF (cancel ocp)\n", __func__);
  933. sec_bat_tx_off_by_misalign_ocp(battery);
  934. sec_bat_set_tx_event(battery,
  935. BATT_TX_EVENT_WIRELESS_TX_OCP, BATT_TX_EVENT_WIRELESS_TX_OCP);
  936. sec_wireless_set_tx_enable(battery, false);
  937. }
  938. } else if (battery->tx_retry_case & SEC_BAT_TX_RETRY_OCP) {
  939. ts = ktime_to_timespec64(ktime_get_boottime());
  940. if (ts.tv_sec >= battery->tx_ocp_start_time) {
  941. battery->tx_ocp_passed_time = ts.tv_sec - battery->tx_ocp_start_time;
  942. } else {
  943. battery->tx_ocp_passed_time = 0xFFFFFFFF - battery->tx_ocp_start_time
  944. + ts.tv_sec;
  945. }
  946. pr_info("@Tx_Mode %s: already ocp, passed time(%ld)\n",
  947. __func__, battery->tx_ocp_passed_time);
  948. if (battery->tx_ocp_passed_time >= 60) {
  949. pr_info("@Tx_Mode %s: after 1min\n", __func__);
  950. if (battery->wc_tx_enable) {
  951. if (battery->wc_rx_connected) {
  952. pr_info("@Tx_Mode %s: RX Dev, Keep TX ON status (cancel ocp)\n", __func__);
  953. } else {
  954. pr_info("@Tx_Mode %s: NO RX Dev, TX OFF (cancel ocp)\n", __func__);
  955. sec_bat_tx_off_by_misalign_ocp(battery);
  956. sec_bat_set_tx_event(battery,
  957. BATT_TX_EVENT_WIRELESS_TX_OCP, BATT_TX_EVENT_WIRELESS_TX_OCP);
  958. sec_wireless_set_tx_enable(battery, false);
  959. }
  960. } else {
  961. pr_info("@Tx_Mode %s: Keep TX OFF status (cancel ocp)\n", __func__);
  962. }
  963. battery->tx_retry_case &= ~SEC_BAT_TX_RETRY_OCP;
  964. battery->tx_ocp_start_time = 0;
  965. battery->tx_ocp_cnt = 0;
  966. }
  967. }
  968. }
  969. void sec_bat_check_wc_re_auth(struct sec_battery_info *battery)
  970. {
  971. union power_supply_propval value = {0, };
  972. int tx_id = 0, auth_stat = 0;
  973. psy_do_property(battery->pdata->wireless_charger_name, get,
  974. POWER_SUPPLY_EXT_PROP_WIRELESS_TX_ID, value);
  975. tx_id = value.intval;
  976. psy_do_property(battery->pdata->wireless_charger_name, get,
  977. POWER_SUPPLY_EXT_PROP_WIRELESS_AUTH_ADT_STATUS, value);
  978. auth_stat = value.intval;
  979. pr_info("%s %s: tx_id(0x%x), cable(%d), soc(%d), auth_stat(%d)\n", WC_AUTH_MSG, __func__,
  980. tx_id, battery->cable_type, battery->capacity, auth_stat);
  981. if ((auth_stat == WIRELESS_AUTH_FAIL) && (battery->capacity >= 5)) {
  982. pr_info("%s %s: EPT Unknown for re-auth\n", WC_AUTH_MSG, __func__);
  983. value.intval = 1;
  984. psy_do_property(battery->pdata->wireless_charger_name, set,
  985. POWER_SUPPLY_EXT_PROP_WC_EPT_UNKNOWN, value);
  986. battery->wc_auth_retried = true;
  987. } else if (auth_stat == WIRELESS_AUTH_PASS) {
  988. pr_info("%s %s: auth success\n", WC_AUTH_MSG, __func__);
  989. battery->wc_auth_retried = true;
  990. } else if (((tx_id != 0) && (tx_id < WC_PAD_ID_AUTH_PAD))
  991. || (tx_id > WC_PAD_ID_AUTH_PAD_END)
  992. || ((tx_id == 0) && is_hv_wireless_type(battery->cable_type))) {
  993. pr_info("%s %s: re-auth is unnecessary\n", WC_AUTH_MSG, __func__);
  994. battery->wc_auth_retried = true;
  995. }
  996. }
  997. #if defined(CONFIG_WIRELESS_TX_MODE)
  998. void sec_bat_check_tx_mode(struct sec_battery_info *battery)
  999. {
  1000. if (battery->wc_tx_enable) {
  1001. pr_info("@Tx_Mode %s: tx_retry(0x%x), tx_switch(0x%x)",
  1002. __func__, battery->tx_retry_case, battery->tx_switch_mode);
  1003. #if !defined(CONFIG_SEC_FACTORY)
  1004. sec_bat_check_tx_battery_drain(battery);
  1005. sec_bat_check_tx_temperature(battery);
  1006. if ((battery->wc_rx_type == SS_PHONE) ||
  1007. (battery->wc_rx_type == OTHER_DEV) ||
  1008. (battery->wc_rx_type == SS_BUDS))
  1009. sec_bat_check_tx_current(battery);
  1010. #endif
  1011. sec_bat_txpower_calc(battery);
  1012. sec_bat_handle_tx_misalign(battery, false);
  1013. sec_bat_handle_tx_ocp(battery, false);
  1014. battery->tx_retry_case &= ~SEC_BAT_TX_RETRY_AC_MISSING;
  1015. if (battery->tx_switch_mode != TX_SWITCH_MODE_OFF && battery->tx_switch_start_soc != 0)
  1016. sec_bat_check_tx_switch_mode(battery);
  1017. } else if (battery->tx_retry_case != SEC_BAT_TX_RETRY_NONE) {
  1018. pr_info("@Tx_Mode %s: tx_retry(0x%x)", __func__, battery->tx_retry_case);
  1019. #if !defined(CONFIG_SEC_FACTORY)
  1020. sec_bat_check_tx_temperature(battery);
  1021. #endif
  1022. sec_bat_handle_tx_misalign(battery, false);
  1023. sec_bat_handle_tx_ocp(battery, false);
  1024. battery->tx_retry_case &= ~SEC_BAT_TX_RETRY_AC_MISSING;
  1025. }
  1026. }
  1027. #endif
  1028. void sec_bat_wc_cv_mode_check(struct sec_battery_info *battery)
  1029. {
  1030. union power_supply_propval value = {0, };
  1031. int is_otg_on = 0;
  1032. psy_do_property(battery->pdata->charger_name, get,
  1033. POWER_SUPPLY_EXT_PROP_CHARGE_OTG_CONTROL, value);
  1034. is_otg_on = value.intval;
  1035. pr_info("%s: battery->wc_cv_mode = %d, otg(%d), cable_type(%d)\n", __func__,
  1036. battery->wc_cv_mode, is_otg_on, battery->cable_type);
  1037. if (battery->capacity >= battery->pdata->wireless_cc_cv && !is_otg_on) {
  1038. battery->wc_cv_mode = true;
  1039. if (is_nv_wireless_type(battery->cable_type)) {
  1040. if ((battery->cable_type == SEC_BATTERY_CABLE_WIRELESS ||
  1041. battery->cable_type == SEC_BATTERY_CABLE_WIRELESS_STAND ||
  1042. battery->cable_type == SEC_BATTERY_CABLE_WIRELESS_TX)) {
  1043. value.intval = WIRELESS_CLAMP_ENABLE;
  1044. psy_do_property(battery->pdata->wireless_charger_name, set,
  1045. POWER_SUPPLY_EXT_PROP_WIRELESS_RX_CONTROL, value);
  1046. }
  1047. }
  1048. /* Change FOD values for CV mode */
  1049. value.intval = POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE;
  1050. psy_do_property(battery->pdata->wireless_charger_name, set,
  1051. POWER_SUPPLY_PROP_STATUS, value);
  1052. /* Change Vrect headroom for CV mode */
  1053. if (battery->pdata->p2p_cv_headroom && battery->cable_type == SEC_BATTERY_CABLE_WIRELESS_TX) {
  1054. value.intval = WIRELESS_VRECT_ADJ_ROOM_2;
  1055. psy_do_property(battery->pdata->wireless_charger_name, set,
  1056. POWER_SUPPLY_EXT_PROP_WIRELESS_RX_CONTROL, value);
  1057. }
  1058. }
  1059. }
  1060. EXPORT_SYMBOL_KUNIT(sec_bat_wc_cv_mode_check);
  1061. static int is_5v_charger(struct sec_battery_info *battery, int wr_sts)
  1062. {
  1063. if ((is_pd_wire_type(wr_sts) && battery->pd_list.max_pd_count > 1)
  1064. || is_hv_wire_12v_type(wr_sts)
  1065. || is_hv_wire_type(wr_sts)
  1066. || (wr_sts == SEC_BATTERY_CABLE_HV_TA_CHG_LIMIT)
  1067. || (wr_sts == SEC_BATTERY_CABLE_PREPARE_TA)
  1068. || (battery->current_event & SEC_BAT_CURRENT_EVENT_AFC))
  1069. return false;
  1070. else if (is_wired_type(wr_sts))
  1071. return true;
  1072. return false;
  1073. }
  1074. void sec_bat_run_wpc_tx_work(struct sec_battery_info *battery, int work_delay)
  1075. {
  1076. if (delayed_work_pending(&battery->wpc_tx_work)) {
  1077. pr_info("%s: did not push the tx_work because of already in queue.\n", __func__);
  1078. return;
  1079. }
  1080. cancel_delayed_work(&battery->wpc_tx_work);
  1081. __pm_stay_awake(battery->wpc_tx_ws);
  1082. queue_delayed_work(battery->monitor_wqueue,
  1083. &battery->wpc_tx_work, msecs_to_jiffies(work_delay));
  1084. }
  1085. static void sec_bat_wpc_tx_iv(struct sec_vote *target_vote, int target_voltage, bool need_refresh)
  1086. {
  1087. int voter_val = get_sec_vote_result(target_vote);
  1088. pr_info("@Tx_mode %s : present iv = %d. target iv = %d\n", __func__, voter_val, target_voltage);
  1089. sec_vote(target_vote, VOTER_WC_TX, true, target_voltage);
  1090. if (need_refresh && (voter_val == target_voltage))
  1091. sec_vote_refresh(target_vote);
  1092. }
  1093. static void sec_bat_tx_work_nodev(struct sec_battery_info *battery)
  1094. {
  1095. if (battery->pdata->fcc_by_tx)
  1096. sec_vote(battery->fcc_vote, VOTER_WC_TX, true,
  1097. battery->pdata->fcc_by_tx);
  1098. if (is_hv_wire_type(battery->wire_status) ||
  1099. (is_pd_wire_type(battery->wire_status) && battery->hv_pdo)) {
  1100. sec_bat_wpc_tx_iv(battery->iv_vote, SEC_INPUT_VOLTAGE_5V, true);
  1101. return;
  1102. }
  1103. battery->buck_cntl_by_tx = true;
  1104. sec_vote(battery->chgen_vote, VOTER_WC_TX, true, SEC_BAT_CHG_MODE_BUCK_OFF);
  1105. if (!battery->uno_en)
  1106. sec_bat_wireless_uno_cntl(battery, true);
  1107. sec_bat_wireless_vout_cntl(battery, battery->pdata->tx_ping_vout);
  1108. sec_bat_wireless_iout_cntl(battery, battery->pdata->tx_uno_iout_aov_gear, battery->pdata->tx_mfc_iout_aov_gear);
  1109. sec_bat_wireless_minduty_cntl(battery, battery->pdata->tx_minduty_default);
  1110. }
  1111. static void sec_bat_tx_work_with_nv_charger(struct sec_battery_info *battery)
  1112. {
  1113. union power_supply_propval value = {0, };
  1114. if (battery->pdata->tx_5v_disable)
  1115. return;
  1116. if (battery->current_event & SEC_BAT_CURRENT_EVENT_AFC) {
  1117. if (!battery->buck_cntl_by_tx) {
  1118. battery->buck_cntl_by_tx = true;
  1119. sec_vote(battery->chgen_vote, VOTER_WC_TX, true, SEC_BAT_CHG_MODE_BUCK_OFF);
  1120. }
  1121. battery->tx_switch_mode = TX_SWITCH_MODE_OFF;
  1122. battery->tx_switch_start_soc = 0;
  1123. battery->tx_switch_mode_change = false;
  1124. sec_bat_wireless_iout_cntl(battery,
  1125. battery->pdata->tx_uno_iout, battery->pdata->tx_mfc_iout_phone);
  1126. sec_bat_wireless_vout_cntl(battery, battery->pdata->tx_uno_vout);
  1127. sec_bat_wireless_minduty_cntl(battery, battery->pdata->tx_minduty_default);
  1128. } else if (battery->tx_switch_mode == TX_SWITCH_MODE_OFF) {
  1129. battery->tx_switch_mode = TX_SWITCH_UNO_ONLY;
  1130. battery->tx_switch_start_soc = battery->capacity;
  1131. if (!battery->buck_cntl_by_tx) {
  1132. battery->buck_cntl_by_tx = true;
  1133. sec_vote(battery->chgen_vote, VOTER_WC_TX, true, SEC_BAT_CHG_MODE_BUCK_OFF);
  1134. }
  1135. sec_bat_wireless_iout_cntl(battery,
  1136. battery->pdata->tx_uno_iout, battery->pdata->tx_mfc_iout_phone);
  1137. sec_bat_wireless_vout_cntl(battery, battery->pdata->tx_uno_vout);
  1138. sec_bat_wireless_minduty_cntl(battery, battery->pdata->tx_minduty_default);
  1139. } else if (battery->tx_switch_mode_change == true) {
  1140. battery->tx_switch_start_soc = battery->capacity;
  1141. pr_info("@Tx_mode: Switch Mode Change(%d -> %d)\n",
  1142. battery->tx_switch_mode,
  1143. battery->tx_switch_mode == TX_SWITCH_UNO_ONLY ?
  1144. TX_SWITCH_CHG_ONLY : TX_SWITCH_UNO_ONLY);
  1145. if (battery->tx_switch_mode == TX_SWITCH_UNO_ONLY) {
  1146. battery->tx_switch_mode = TX_SWITCH_CHG_ONLY;
  1147. sec_bat_wireless_iout_cntl(battery,
  1148. battery->pdata->tx_uno_iout,
  1149. battery->pdata->tx_mfc_iout_phone_5v);
  1150. sec_bat_wireless_vout_cntl(battery, battery->pdata->tx_ping_vout);
  1151. sec_bat_wireless_minduty_cntl(battery, battery->pdata->tx_minduty_5V);
  1152. if (battery->buck_cntl_by_tx) {
  1153. battery->buck_cntl_by_tx = false;
  1154. sec_vote(battery->chgen_vote, VOTER_WC_TX, false, 0);
  1155. }
  1156. } else if (battery->tx_switch_mode == TX_SWITCH_CHG_ONLY) {
  1157. battery->tx_switch_mode = TX_SWITCH_UNO_ONLY;
  1158. if (!battery->buck_cntl_by_tx) {
  1159. battery->buck_cntl_by_tx = true;
  1160. sec_vote(battery->chgen_vote,
  1161. VOTER_WC_TX, true, SEC_BAT_CHG_MODE_BUCK_OFF);
  1162. }
  1163. sec_bat_wireless_iout_cntl(battery,
  1164. battery->pdata->tx_uno_iout,
  1165. battery->pdata->tx_mfc_iout_phone);
  1166. sec_bat_wireless_vout_cntl(battery, battery->pdata->tx_uno_vout);
  1167. sec_bat_wireless_minduty_cntl(battery, battery->pdata->tx_minduty_default);
  1168. value.intval = true;
  1169. psy_do_property(battery->pdata->wireless_charger_name, set,
  1170. POWER_SUPPLY_EXT_PROP_WIRELESS_SEND_FSK, value);
  1171. }
  1172. battery->tx_switch_mode_change = false;
  1173. }
  1174. }
  1175. void sec_bat_wireless_proc_ping_duty(struct sec_battery_info *battery, int wr_sts)
  1176. {
  1177. if (wr_sts != SEC_BATTERY_CABLE_NONE)
  1178. sec_bat_wireless_set_ping_duty(battery, battery->pdata->tx_ping_duty_default);
  1179. else
  1180. sec_bat_wireless_set_ping_duty(battery, battery->pdata->tx_ping_duty_no_ta);
  1181. }
  1182. void sec_bat_wpc_tx_work_content(struct sec_battery_info *battery)
  1183. {
  1184. int wr_sts = battery->wire_status;
  1185. unsigned int tx_uno_vout = battery->pdata->tx_uno_vout;
  1186. if (battery->wc_rx_type == SS_GEAR)
  1187. tx_uno_vout = battery->pdata->tx_gear_vout;
  1188. else if (battery->wc_rx_type == SS_BUDS)
  1189. tx_uno_vout = battery->pdata->tx_buds_vout;
  1190. dev_info(battery->dev, "@Tx_Mode %s: Start: %d\n", __func__, battery->wc_rx_type);
  1191. if (!battery->wc_tx_enable) {
  1192. pr_info("@Tx_Mode %s : exit wpc_tx_work. Because Tx is already off\n", __func__);
  1193. goto end_of_tx_work;
  1194. }
  1195. if (battery->pdata->tx_5v_disable && is_5v_charger(battery, wr_sts)) {
  1196. pr_info("@Tx_Mode %s : 5V charger(%d) connected, disable TX\n", __func__, battery->cable_type);
  1197. sec_bat_set_tx_event(battery, BATT_TX_EVENT_WIRELESS_TX_5V_TA, BATT_TX_EVENT_WIRELESS_TX_5V_TA);
  1198. sec_wireless_set_tx_enable(battery, false);
  1199. goto end_of_tx_work;
  1200. }
  1201. if (battery->uno_en) {
  1202. sec_bat_wireless_proc_ping_duty(battery, wr_sts);
  1203. }
  1204. switch (battery->wc_rx_type) {
  1205. case NO_DEV:
  1206. sec_bat_tx_work_nodev(battery);
  1207. sec_bat_wireless_proc_ping_duty(battery, wr_sts);
  1208. sb_tx_init_aov();
  1209. break;
  1210. case SS_GEAR:
  1211. {
  1212. if (battery->pdata->icl_by_tx_gear)
  1213. sec_vote(battery->input_vote, VOTER_WC_TX, true,
  1214. battery->pdata->icl_by_tx_gear);
  1215. if (battery->pdata->fcc_by_tx_gear)
  1216. sec_vote(battery->fcc_vote, VOTER_WC_TX, true,
  1217. battery->pdata->fcc_by_tx_gear);
  1218. if (sb_tx_is_aov_enabled(battery->wire_status)) {
  1219. sb_tx_monitor_aov(battery->wc_tx_vout, battery->wc_tx_phm_mode);
  1220. battery->buck_cntl_by_tx = false;
  1221. battery->tx_switch_mode = TX_SWITCH_GEAR_PPS;
  1222. battery->tx_switch_mode_change = true;
  1223. sec_bat_wireless_iout_cntl(battery, battery->pdata->tx_uno_iout_aov_gear,
  1224. battery->pdata->tx_mfc_iout_aov_gear);
  1225. if (delayed_work_pending(&battery->wpc_tx_work))
  1226. return;
  1227. break;
  1228. } else {
  1229. if (battery->pdata->phm_vout_ctrl_dev & SEC_WIRELESS_PHM_VOUT_CTRL_GEAR) {
  1230. if (battery->wc_tx_phm_mode) {
  1231. if (is_hv_wire_type(battery->wire_status) ||
  1232. (is_pd_wire_type(battery->wire_status) && battery->hv_pdo)) {
  1233. pr_info("@Tx_Mode %s : change iv(9V -> 5V).\n", __func__);
  1234. sec_bat_wireless_vout_cntl(battery, WC_TX_VOUT_5000MV);
  1235. sec_bat_wpc_tx_iv(battery->iv_vote, SEC_INPUT_VOLTAGE_5V, true);
  1236. break;
  1237. }
  1238. } else {
  1239. if ((battery->wire_status == SEC_BATTERY_CABLE_HV_TA_CHG_LIMIT) ||
  1240. (is_pd_wire_type(battery->wire_status) && !battery->hv_pdo)) {
  1241. pr_info("@Tx_Mode %s : charging voltage change(5V -> 9V)\n", __func__);
  1242. /* prevent ocp */
  1243. if (!battery->buck_cntl_by_tx) {
  1244. sec_bat_wireless_vout_cntl(battery, WC_TX_VOUT_5000MV);
  1245. sec_bat_wireless_iout_cntl(battery, battery->pdata->tx_uno_iout_gear, 1000);
  1246. battery->buck_cntl_by_tx = true;
  1247. sec_vote(battery->chgen_vote, VOTER_WC_TX,
  1248. true, SEC_BAT_CHG_MODE_BUCK_OFF);
  1249. sec_bat_run_wpc_tx_work(battery, 500);
  1250. return;
  1251. } else if (battery->wc_tx_vout < WC_TX_VOUT_8500MV) {
  1252. sec_bat_wireless_vout_cntl(battery,
  1253. battery->wc_tx_vout + WC_TX_VOUT_STEP_AOV);
  1254. sec_bat_run_wpc_tx_work(battery, 500);
  1255. return;
  1256. }
  1257. sec_bat_wpc_tx_iv(battery->iv_vote, SEC_INPUT_VOLTAGE_9V, true);
  1258. break;
  1259. }
  1260. }
  1261. } else {
  1262. if (is_hv_wire_type(battery->wire_status) ||
  1263. (is_pd_wire_type(battery->wire_status) && battery->hv_pdo)) {
  1264. pr_info("@Tx_Mode %s : change iv(9V -> 5V).\n", __func__);
  1265. sec_bat_wireless_vout_cntl(battery, WC_TX_VOUT_5000MV);
  1266. sec_bat_wpc_tx_iv(battery->iv_vote, SEC_INPUT_VOLTAGE_5V, true);
  1267. break;
  1268. }
  1269. }
  1270. }
  1271. if (is_wired_type(battery->wire_status) && battery->buck_cntl_by_tx) {
  1272. battery->buck_cntl_by_tx = false;
  1273. sec_vote(battery->chgen_vote, VOTER_WC_TX, false, 0);
  1274. } else if ((battery->wire_status == SEC_BATTERY_CABLE_NONE) && (!battery->buck_cntl_by_tx)) {
  1275. battery->buck_cntl_by_tx = true;
  1276. sec_vote(battery->chgen_vote, VOTER_WC_TX, true, SEC_BAT_CHG_MODE_BUCK_OFF);
  1277. }
  1278. sec_bat_wireless_vout_cntl(battery, tx_uno_vout);
  1279. sec_bat_wireless_iout_cntl(battery, battery->pdata->tx_uno_iout_gear,
  1280. battery->pdata->tx_mfc_iout_gear);
  1281. }
  1282. break;
  1283. default: /* SS_BUDS, SS_PHONE, OTHER_DEV */
  1284. if (battery->pdata->phm_vout_ctrl_dev & SEC_WIRELESS_PHM_VOUT_CTRL_BUDS) {
  1285. if (battery->wc_tx_phm_mode) {
  1286. pr_info("@Tx_Mode %s : phm on status.\n", __func__);
  1287. sec_bat_wireless_vout_cntl(battery, WC_TX_VOUT_5000MV);
  1288. if (is_hv_wire_type(battery->wire_status) ||
  1289. (is_pd_wire_type(battery->wire_status) && battery->hv_pdo)) {
  1290. pr_info("@Tx_Mode %s : change iv(9V -> 5V).\n", __func__);
  1291. sec_bat_wpc_tx_iv(battery->iv_vote, SEC_INPUT_VOLTAGE_5V, true);
  1292. } else {
  1293. pr_info("@Tx_Mode %s : change iv(%dV -> 5V).\n",
  1294. __func__, battery->pdata->tx_uno_vout);
  1295. }
  1296. battery->prev_tx_phm_mode = battery->wc_tx_phm_mode;
  1297. break;
  1298. } else {
  1299. if (battery->prev_tx_phm_mode) {
  1300. pr_info("@Tx_Mode %s : keep phm off status concept before tx off\n", __func__);
  1301. break;
  1302. }
  1303. }
  1304. }
  1305. if ((battery->wire_status == SEC_BATTERY_CABLE_HV_TA_CHG_LIMIT) ||
  1306. (is_pd_wire_type(battery->wire_status) && !battery->hv_pdo)) {
  1307. if (battery->wc_tx_vout < tx_uno_vout) {
  1308. sec_bat_wireless_vout_cntl(battery, tx_uno_vout);
  1309. if (!battery->buck_cntl_by_tx) {
  1310. battery->buck_cntl_by_tx = true;
  1311. sec_vote(battery->chgen_vote, VOTER_WC_TX,
  1312. true, SEC_BAT_CHG_MODE_BUCK_OFF);
  1313. }
  1314. sec_bat_run_wpc_tx_work(battery, 500);
  1315. return;
  1316. }
  1317. pr_info("@Tx_Mode %s : change iv(5V -> 9V)\n", __func__);
  1318. sec_bat_wpc_tx_iv(battery->iv_vote, SEC_INPUT_VOLTAGE_9V, true);
  1319. break;
  1320. }
  1321. if (battery->wire_status == SEC_BATTERY_CABLE_NONE) {
  1322. battery->tx_switch_mode = TX_SWITCH_MODE_OFF;
  1323. battery->tx_switch_start_soc = 0;
  1324. battery->tx_switch_mode_change = false;
  1325. if (!battery->buck_cntl_by_tx) {
  1326. battery->buck_cntl_by_tx = true;
  1327. sec_vote(battery->chgen_vote, VOTER_WC_TX, true, SEC_BAT_CHG_MODE_BUCK_OFF);
  1328. }
  1329. sec_bat_wireless_vout_cntl(battery, tx_uno_vout);
  1330. sec_bat_wireless_iout_cntl(battery,
  1331. battery->pdata->tx_uno_iout, battery->pdata->tx_mfc_iout_phone);
  1332. sec_bat_wireless_minduty_cntl(battery, battery->pdata->tx_minduty_default);
  1333. } else if (is_hv_wire_type(battery->wire_status) ||
  1334. (is_pd_wire_type(battery->wire_status) && battery->hv_pdo)) {
  1335. battery->tx_switch_mode = TX_SWITCH_MODE_OFF;
  1336. battery->tx_switch_start_soc = 0;
  1337. battery->tx_switch_mode_change = false;
  1338. if (battery->buck_cntl_by_tx) {
  1339. battery->buck_cntl_by_tx = false;
  1340. sec_vote(battery->chgen_vote, VOTER_WC_TX, false, 0);
  1341. }
  1342. sec_bat_wireless_iout_cntl(battery,
  1343. battery->pdata->tx_uno_iout, battery->pdata->tx_mfc_iout_phone);
  1344. sec_bat_wireless_minduty_cntl(battery, battery->pdata->tx_minduty_default);
  1345. } else if (is_pd_wire_type(battery->wire_status) && battery->hv_pdo) {
  1346. pr_info("@Tx_Mode %s: PD cable attached. HV PDO(%d)\n", __func__, battery->hv_pdo);
  1347. battery->tx_switch_mode = TX_SWITCH_MODE_OFF;
  1348. battery->tx_switch_start_soc = 0;
  1349. battery->tx_switch_mode_change = false;
  1350. if (battery->buck_cntl_by_tx) {
  1351. battery->buck_cntl_by_tx = false;
  1352. sec_vote(battery->chgen_vote, VOTER_WC_TX, false, 0);
  1353. }
  1354. sec_bat_wireless_iout_cntl(battery,
  1355. battery->pdata->tx_uno_iout, battery->pdata->tx_mfc_iout_phone);
  1356. sec_bat_wireless_minduty_cntl(battery, battery->pdata->tx_minduty_default);
  1357. } else if (is_wired_type(battery->wire_status) && !is_hv_wire_type(battery->wire_status) &&
  1358. (battery->wire_status != SEC_BATTERY_CABLE_HV_TA_CHG_LIMIT)) {
  1359. sec_bat_tx_work_with_nv_charger(battery);
  1360. }
  1361. break;
  1362. }
  1363. end_of_tx_work:
  1364. dev_info(battery->dev, "@Tx_Mode %s End\n", __func__);
  1365. __pm_relax(battery->wpc_tx_ws);
  1366. }
  1367. #define EN_RETRY_DELAY 100
  1368. #define EN_RETRY_CNT 20
  1369. void sec_bat_wpc_tx_en_work_content(struct sec_battery_info *battery)
  1370. {
  1371. int wr_sts = battery->wire_status;
  1372. int selected_pdo;
  1373. static unsigned int cnt;
  1374. pr_info("@Tx_Mode %s: tx %s\n", __func__,
  1375. battery->wc_tx_enable ? "on" : "off");
  1376. battery->tx_minduty = battery->pdata->tx_minduty_default;
  1377. battery->tx_switch_mode = TX_SWITCH_MODE_OFF;
  1378. battery->tx_switch_start_soc = 0;
  1379. battery->tx_switch_mode_change = false;
  1380. battery->tx_ping_duty = 0;
  1381. if (battery->wc_tx_enable) {
  1382. /* set tx event */
  1383. sec_bat_set_tx_event(battery, BATT_TX_EVENT_WIRELESS_TX_STATUS,
  1384. (BATT_TX_EVENT_WIRELESS_TX_STATUS | BATT_TX_EVENT_WIRELESS_TX_RETRY));
  1385. if (is_pd_wire_type(wr_sts)) {
  1386. sec_pd_get_selected_pdo(&selected_pdo);
  1387. if (selected_pdo == battery->sink_status.current_pdo_num) {
  1388. if (battery->sink_status.power_list[battery->sink_status.current_pdo_num].max_voltage
  1389. == SEC_INPUT_VOLTAGE_5V) {
  1390. pr_info("@Tx_Mode %s: 5V PDO. Tx Start\n", __func__);
  1391. sec_bat_wpc_tx_iv(battery->iv_vote, SEC_INPUT_VOLTAGE_5V, false);
  1392. sec_bat_run_wpc_tx_work(battery, 0);
  1393. } else {
  1394. pr_info("@Tx_Mode %s: Wait to decrease 5V (%d / %d)\n",
  1395. __func__, ++cnt, EN_RETRY_CNT);
  1396. sec_bat_wpc_tx_iv(battery->iv_vote, SEC_INPUT_VOLTAGE_5V, false);
  1397. __pm_stay_awake(battery->wpc_tx_en_ws);
  1398. queue_delayed_work(battery->monitor_wqueue,
  1399. &battery->wpc_tx_en_work, msecs_to_jiffies(EN_RETRY_DELAY));
  1400. return;
  1401. }
  1402. } else {
  1403. if (cnt >= EN_RETRY_CNT) {
  1404. pr_info("@Tx_Mode %s: No response for 5V. Error case\n", __func__);
  1405. cnt = 0;
  1406. } else {
  1407. pr_info("@Tx_Mode %s: Wait to decrease 5V (%d / %d)\n",
  1408. __func__, ++cnt, EN_RETRY_CNT);
  1409. __pm_stay_awake(battery->wpc_tx_en_ws);
  1410. queue_delayed_work(battery->monitor_wqueue,
  1411. &battery->wpc_tx_en_work, msecs_to_jiffies(EN_RETRY_DELAY));
  1412. return;
  1413. }
  1414. }
  1415. } else if (is_hv_wire_type(wr_sts)) {
  1416. if (cnt >= EN_RETRY_CNT) {
  1417. pr_info("@Tx_Mode %s: No response for 5V. Error case\n", __func__);
  1418. cnt = 0;
  1419. } else {
  1420. pr_info("@Tx_Mode %s: Wait to decrease 5V (%d / %d)\n",
  1421. __func__, ++cnt, EN_RETRY_CNT);
  1422. sec_bat_wpc_tx_iv(battery->iv_vote, SEC_INPUT_VOLTAGE_5V, false);
  1423. __pm_stay_awake(battery->wpc_tx_en_ws);
  1424. queue_delayed_work(battery->monitor_wqueue,
  1425. &battery->wpc_tx_en_work, msecs_to_jiffies(EN_RETRY_DELAY));
  1426. return;
  1427. }
  1428. } else {
  1429. pr_info("@Tx_Mode %s: 5V AFC. Tx Start\n", __func__);
  1430. sec_bat_wpc_tx_iv(battery->iv_vote, SEC_INPUT_VOLTAGE_5V, false);
  1431. sec_bat_run_wpc_tx_work(battery, 0);
  1432. }
  1433. pr_info("@Tx_Mode %s: TX Power Calculation start.\n", __func__);
  1434. queue_delayed_work(battery->monitor_wqueue,
  1435. &battery->wpc_txpower_calc_work, 0);
  1436. } else {
  1437. cancel_delayed_work(&battery->wpc_tx_work);
  1438. cancel_delayed_work(&battery->wpc_txpower_calc_work);
  1439. __pm_relax(battery->wpc_tx_ws);
  1440. sec_bat_wireless_minduty_cntl(battery, battery->pdata->tx_minduty_default);
  1441. battery->wc_rx_type = NO_DEV;
  1442. battery->wc_rx_connected = false;
  1443. battery->tx_uno_iout = 0;
  1444. battery->tx_mfc_iout = 0;
  1445. battery->buck_cntl_by_tx = false;
  1446. sec_bat_wireless_uno_cntl(battery, false);
  1447. sec_bat_wireless_vout_cntl(battery, WC_TX_VOUT_5000MV);
  1448. sec_vote(battery->chgen_vote, VOTER_WC_TX, false, 0);
  1449. sec_vote(battery->fcc_vote, VOTER_WC_TX, false, 0);
  1450. sec_vote(battery->input_vote, VOTER_WC_TX, false, 0);
  1451. /* for 1) not supporting DC and charging bia PD20/DC on Tx */
  1452. /* 2) supporting DC and charging bia PD20 on Tx */
  1453. /* 3) During retrying, maintain iv_vote */
  1454. if (battery->tx_retry_case == SEC_BAT_TX_RETRY_NONE)
  1455. sec_vote(battery->iv_vote, VOTER_WC_TX, false, 0);
  1456. cnt = 0;
  1457. }
  1458. pr_info("@Tx_Mode %s Done\n", __func__);
  1459. __pm_relax(battery->wpc_tx_en_ws);
  1460. }
  1461. void sec_wireless_set_tx_enable(struct sec_battery_info *battery, bool wc_tx_enable)
  1462. {
  1463. int wr_sts = battery->wire_status;
  1464. pr_info("@Tx_Mode %s: TX Power enable ? (%d)\n", __func__, wc_tx_enable);
  1465. if (battery->pdata->tx_5v_disable && wc_tx_enable && is_5v_charger(battery, wr_sts)) {
  1466. pr_info("@Tx_Mode %s : 5V charger(%d) connected, do not turn on TX\n", __func__, wr_sts);
  1467. sec_bat_set_tx_event(battery, BATT_TX_EVENT_WIRELESS_TX_5V_TA, BATT_TX_EVENT_WIRELESS_TX_5V_TA);
  1468. return;
  1469. }
  1470. /* temporary code */
  1471. sb_tx_init(battery, battery->pdata->wireless_charger_name);
  1472. sb_tx_init_aov();
  1473. battery->wc_tx_enable = wc_tx_enable;
  1474. battery->wc_tx_phm_mode = false;
  1475. battery->prev_tx_phm_mode = false;
  1476. /* FPDO DC concept */
  1477. if (wr_sts == SEC_BATTERY_CABLE_FPDO_DC && battery->wc_tx_enable) {
  1478. union power_supply_propval value = {0, };
  1479. value.intval = 0;
  1480. psy_do_property(battery->pdata->charger_name, set,
  1481. POWER_SUPPLY_EXT_PROP_REFRESH_CHARGING_SOURCE, value);
  1482. }
  1483. cancel_delayed_work(&battery->wpc_tx_en_work);
  1484. __pm_stay_awake(battery->wpc_tx_en_ws);
  1485. queue_delayed_work(battery->monitor_wqueue,
  1486. &battery->wpc_tx_en_work, 0);
  1487. }
  1488. EXPORT_SYMBOL(sec_wireless_set_tx_enable);