sb_tx.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511
  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_tx.h"
  19. #define tx_log(str, ...) pr_info("[SB-TX]:%s: "str, __func__, ##__VA_ARGS__)
  20. #define AOV_VOUT_STEP 500
  21. #define AOV_VOUT_MAX 7500
  22. enum sb_tx_aov_state {
  23. AOV_STATE_NONE = 0,
  24. AOV_STATE_PRESET,
  25. AOV_STATE_MONITOR,
  26. AOV_STATE_PHM,
  27. AOV_STATE_ERR,
  28. };
  29. enum sb_tx_chg_state {
  30. AOV_WITH_NONE = 0,
  31. AOV_WITH_NOCHG,
  32. AOV_WITH_CHG,
  33. };
  34. static const char *get_aov_state_str(int state)
  35. {
  36. switch (state) {
  37. case AOV_STATE_NONE:
  38. return "None";
  39. case AOV_STATE_PRESET:
  40. return "Preset";
  41. case AOV_STATE_MONITOR:
  42. return "Monitor";
  43. case AOV_STATE_PHM:
  44. return "PHM";
  45. case AOV_STATE_ERR:
  46. return "Error";
  47. }
  48. return "Unknown";
  49. }
  50. struct sb_tx_aov {
  51. bool enable;
  52. int state;
  53. int tx_chg_state;
  54. /* dt data */
  55. unsigned int start_vout;
  56. unsigned int low_freq;
  57. unsigned int high_freq;
  58. unsigned int delay;
  59. unsigned int preset_delay;
  60. unsigned int phm_icl;
  61. unsigned int phm_icl_full;
  62. unsigned int vout_min;
  63. };
  64. struct sb_tx {
  65. /* temporary attributes */
  66. struct sec_battery_info *battery;
  67. struct notifier_block nb;
  68. struct wakeup_source *ws;
  69. struct workqueue_struct *wq;
  70. struct delayed_work tx_err_work;
  71. bool enable;
  72. unsigned int event;
  73. struct mutex event_lock;
  74. /* option */
  75. struct sb_tx_aov aov;
  76. char *wrl_name;
  77. char *fg_name;
  78. };
  79. struct sb_tx *gtx;
  80. static DEFINE_MUTEX(tx_lock);
  81. static struct sb_tx *get_sb_tx(void)
  82. {
  83. struct sb_tx *tx = NULL;
  84. mutex_lock(&tx_lock);
  85. tx = gtx;
  86. mutex_unlock(&tx_lock);
  87. return tx;
  88. }
  89. static bool check_full_state(struct sb_tx *tx)
  90. {
  91. union power_supply_propval value = {0, };
  92. value.intval = SEC_FUELGAUGE_CAPACITY_TYPE_DYNAMIC_SCALE;
  93. psy_do_property(tx->fg_name, get,
  94. POWER_SUPPLY_PROP_CAPACITY, value);
  95. return (value.intval >= 970);
  96. }
  97. int sb_tx_init_aov(void)
  98. {
  99. struct sb_tx *tx = get_sb_tx();
  100. struct sb_tx_aov *aov;
  101. if (!tx)
  102. return -ENODEV;
  103. aov = &tx->aov;
  104. mutex_lock(&tx_lock);
  105. aov->state = AOV_STATE_NONE;
  106. aov->tx_chg_state = AOV_WITH_NONE;
  107. sec_vote(tx->battery->input_vote, VOTER_WC_TX, false, 0);
  108. mutex_unlock(&tx_lock);
  109. return 0;
  110. }
  111. bool sb_tx_is_aov_enabled(int cable_type)
  112. {
  113. struct sb_tx *tx = get_sb_tx();
  114. struct sb_tx_aov *aov = &tx->aov;
  115. if (!tx)
  116. return false;
  117. if (!tx->aov.enable)
  118. return false;
  119. if (tx->aov.state == AOV_STATE_ERR)
  120. return false;
  121. if (is_pd_apdo_wire_type(cable_type)) {
  122. if (tx->aov.state == AOV_STATE_NONE) {
  123. unsigned int min_iv = aov->vout_min, max_iv = AOV_VOUT_MAX;
  124. if (sec_pd_get_pdo_power(NULL, &min_iv, &max_iv, NULL) <= 0)
  125. return false;
  126. }
  127. aov->tx_chg_state = AOV_WITH_CHG;
  128. } else if (!is_nocharge_type(cable_type)) {
  129. if (tx->aov.state != AOV_STATE_NONE)
  130. sb_tx_init_aov();
  131. return false;
  132. } else {
  133. aov->tx_chg_state = AOV_WITH_NOCHG;
  134. }
  135. return true;
  136. }
  137. int sb_tx_monitor_aov(int vout, bool phm)
  138. {
  139. struct sb_tx *tx = get_sb_tx();
  140. struct sec_battery_info *battery;
  141. struct sb_tx_aov *aov;
  142. int prev_aov_state;
  143. static int prev_tx_chg_state;
  144. if (!tx)
  145. return -ENODEV;
  146. aov = &tx->aov;
  147. battery = tx->battery;
  148. mutex_lock(&tx_lock);
  149. prev_aov_state = aov->state;
  150. switch (aov->state) {
  151. case AOV_STATE_NONE:
  152. prev_tx_chg_state = AOV_WITH_NONE;
  153. aov->state = AOV_STATE_PRESET;
  154. fallthrough;
  155. case AOV_STATE_PRESET:
  156. if (vout < aov->start_vout) {
  157. if (prev_aov_state == AOV_STATE_NONE) {
  158. sec_bat_run_wpc_tx_work(battery, (aov->preset_delay + 1000));
  159. } else {
  160. vout = vout + AOV_VOUT_STEP;
  161. sec_vote(battery->iv_vote, VOTER_WC_TX, true, vout);
  162. sec_bat_wireless_vout_cntl(tx->battery, vout);
  163. sec_bat_run_wpc_tx_work(battery,
  164. ((vout == aov->start_vout) ? (aov->preset_delay * 2) : 500));
  165. }
  166. break;
  167. }
  168. aov->state = AOV_STATE_MONITOR;
  169. fallthrough;
  170. case AOV_STATE_MONITOR:
  171. if (phm) {
  172. int phm_icl = (check_full_state(tx)) ?
  173. aov->phm_icl_full : aov->phm_icl;
  174. sec_vote(battery->iv_vote, VOTER_WC_TX, true, SEC_INPUT_VOLTAGE_5V);
  175. sec_vote(battery->input_vote, VOTER_WC_TX, true, phm_icl);
  176. sec_bat_wireless_vout_cntl(battery, WC_TX_VOUT_5000MV);
  177. sec_bat_wireless_iout_cntl(battery, battery->pdata->tx_uno_iout, 1000);
  178. aov->state = AOV_STATE_PHM;
  179. } else {
  180. union power_supply_propval freq = {0, };
  181. int prev_vout = vout;
  182. psy_do_property(tx->wrl_name, get, POWER_SUPPLY_EXT_PROP_WIRELESS_OP_FREQ, freq);
  183. if ((freq.intval <= aov->low_freq) && (vout < AOV_VOUT_MAX))
  184. vout = vout + AOV_VOUT_STEP;
  185. else if ((freq.intval >= aov->high_freq) && (vout > aov->vout_min))
  186. vout = vout - AOV_VOUT_STEP;
  187. if ((prev_vout != vout) ||
  188. ((prev_tx_chg_state == AOV_WITH_NOCHG) && (aov->tx_chg_state == AOV_WITH_CHG))) {
  189. sec_vote(battery->iv_vote, VOTER_WC_TX, true, vout);
  190. sec_bat_wireless_vout_cntl(battery, vout);
  191. sec_bat_run_wpc_tx_work(battery, aov->delay);
  192. } else {
  193. sec_vote_refresh(battery->iv_vote);
  194. }
  195. }
  196. break;
  197. case AOV_STATE_PHM:
  198. if (!phm) {
  199. vout = aov->start_vout + AOV_VOUT_STEP;
  200. sec_vote(battery->iv_vote, VOTER_WC_TX, true, vout);
  201. if (battery->pdata->icl_by_tx_gear)
  202. sec_vote(battery->input_vote, VOTER_WC_TX, true, battery->pdata->icl_by_tx_gear);
  203. else
  204. sec_vote(battery->input_vote, VOTER_WC_TX, false, 0);
  205. sec_bat_wireless_vout_cntl(battery, vout);
  206. sec_bat_run_wpc_tx_work(battery, aov->delay);
  207. aov->state = AOV_STATE_MONITOR;
  208. } else {
  209. int phm_icl = (check_full_state(tx)) ?
  210. aov->phm_icl_full : aov->phm_icl;
  211. sec_vote(battery->input_vote, VOTER_WC_TX, true, phm_icl);
  212. }
  213. break;
  214. default:
  215. break;
  216. }
  217. prev_tx_chg_state = aov->tx_chg_state;
  218. sec_vote(battery->chgen_vote, VOTER_WC_TX, false, 0);
  219. tx_log("aov state = %s, tx_chg_state = %d, vout = %d\n",
  220. get_aov_state_str(aov->state), aov->tx_chg_state, vout);
  221. mutex_unlock(&tx_lock);
  222. return aov->state;
  223. }
  224. static bool check_tx_err_state(struct sb_tx *tx)
  225. {
  226. union power_supply_propval value = { 0, };
  227. int vout, iout, freq;
  228. psy_do_property(tx->wrl_name, get, POWER_SUPPLY_EXT_PROP_WIRELESS_TX_UNO_VIN, value);
  229. vout = value.intval;
  230. psy_do_property(tx->wrl_name, get, POWER_SUPPLY_EXT_PROP_WIRELESS_TX_UNO_IIN, value);
  231. iout = value.intval;
  232. psy_do_property(tx->wrl_name, get, POWER_SUPPLY_EXT_PROP_WIRELESS_OP_FREQ, value);
  233. freq = value.intval;
  234. return (vout <= 0) && (iout <= 0) && (freq <= 0);
  235. }
  236. static void cb_tx_err_work(struct work_struct *work)
  237. {
  238. struct sb_tx *tx = container_of(work,
  239. struct sb_tx, tx_err_work.work);
  240. tx_log("start!\n");
  241. if (check_tx_err_state(tx)) {
  242. union power_supply_propval value = { 0, };
  243. tx_log("set tx retry!!!\n");
  244. value.intval = BATT_TX_EVENT_WIRELESS_TX_ETC;
  245. psy_do_property("wireless", set, POWER_SUPPLY_EXT_PROP_WIRELESS_TX_ERR, value);
  246. }
  247. __pm_relax(tx->ws);
  248. }
  249. static ssize_t show_attrs(struct device *dev,
  250. struct device_attribute *attr, char *buf);
  251. static ssize_t store_attrs(struct device *dev,
  252. struct device_attribute *attr, const char *buf, size_t count);
  253. #define TX_SYSFS_ATTR(_name) \
  254. { \
  255. .attr = {.name = #_name, .mode = 0664}, \
  256. .show = show_attrs, \
  257. .store = store_attrs, \
  258. }
  259. static struct device_attribute tx_attr[] = {
  260. TX_SYSFS_ATTR(tx_test),
  261. };
  262. enum tx_attrs {
  263. TX_TEST = 0,
  264. };
  265. static ssize_t show_attrs(struct device *dev,
  266. struct device_attribute *attr, char *buf)
  267. {
  268. return 0;
  269. }
  270. static ssize_t store_attrs(struct device *dev,
  271. struct device_attribute *attr, const char *buf, size_t count)
  272. {
  273. return count;
  274. }
  275. static int sb_noti_handler(struct notifier_block *nb, unsigned long action, void *data)
  276. {
  277. return 0;
  278. }
  279. #ifdef CONFIG_OF
  280. static int sb_tx_parse_aov_dt(struct device_node *np, struct sb_tx_aov *aov)
  281. {
  282. if (of_property_read_bool(np, "disable"))
  283. return -1;
  284. sb_of_parse_u32(np, aov, start_vout, WC_TX_VOUT_5500MV);
  285. sb_of_parse_u32(np, aov, phm_icl, 800);
  286. sb_of_parse_u32(np, aov, phm_icl_full, 100);
  287. sb_of_parse_u32(np, aov, low_freq, 131);
  288. sb_of_parse_u32(np, aov, high_freq, 147);
  289. sb_of_parse_u32(np, aov, delay, 3000);
  290. sb_of_parse_u32(np, aov, preset_delay, 3000);
  291. sb_of_parse_u32(np, aov, vout_min, 5000);
  292. return 0;
  293. }
  294. static int sb_tx_parse_dt(struct sb_tx *tx)
  295. {
  296. struct device_node *np, *child;
  297. int ret = 0;
  298. np = of_find_node_by_name(NULL, TX_MODULE_NAME);
  299. if (!np)
  300. return -ENODEV;
  301. for_each_child_of_node(np, child) {
  302. if (!strcmp(child->name, "aov")) {
  303. ret = sb_tx_parse_aov_dt(child, &tx->aov);
  304. tx->aov.enable = !(ret);
  305. tx_log("AOV = %s\n", tx->aov.enable ? "Enable" : "Disable");
  306. }
  307. }
  308. np = of_find_node_by_name(NULL, "battery");
  309. if (np) {
  310. ret = of_property_read_string(np,
  311. "battery,fuelgauge_name", (const char **)&tx->fg_name);
  312. if (ret)
  313. tx_log("failed to get fg name in battery dt (ret = %d)\n", ret);
  314. }
  315. return ret;
  316. }
  317. #else
  318. static int sb_tx_parse_dt(struct sb_tx *tx)
  319. {
  320. return 0;
  321. }
  322. #endif
  323. int sb_tx_init(struct sec_battery_info *battery, char *wrl_name)
  324. {
  325. struct sb_tx *tx;
  326. int ret = 0;
  327. if ((battery == NULL) || (wrl_name == NULL))
  328. return -EINVAL;
  329. /* temporary code */
  330. if (get_sb_tx() != NULL)
  331. return 0;
  332. mutex_lock(&tx_lock);
  333. tx = kzalloc(sizeof(struct sb_tx), GFP_KERNEL);
  334. if (!tx) {
  335. mutex_unlock(&tx_lock);
  336. return -ENOMEM;
  337. }
  338. ret = sb_tx_parse_dt(tx);
  339. if (ret)
  340. goto err_parse_dt;
  341. tx->wq = create_singlethread_workqueue(TX_MODULE_NAME);
  342. if (!tx->wq) {
  343. ret = -ENOMEM;
  344. goto err_parse_dt;
  345. }
  346. tx->ws = wakeup_source_register(battery->dev, TX_MODULE_NAME);
  347. INIT_DELAYED_WORK(&tx->tx_err_work, cb_tx_err_work);
  348. mutex_init(&tx->event_lock);
  349. tx->battery = battery;
  350. tx->wrl_name = wrl_name;
  351. tx->enable = false;
  352. ret = sb_sysfs_add_attrs(TX_MODULE_NAME, tx, tx_attr, ARRAY_SIZE(tx_attr));
  353. tx_log("sb_sysfs_add_attrs ret = %s\n", (ret) ? "fail" : "success");
  354. ret = sb_notify_register(&tx->nb, sb_noti_handler, TX_MODULE_NAME, SB_DEV_MODULE);
  355. tx_log("sb_notify_register ret = %s\n", (ret) ? "fail" : "success");
  356. gtx = tx;
  357. mutex_unlock(&tx_lock);
  358. return 0;
  359. err_parse_dt:
  360. kfree(tx);
  361. mutex_unlock(&tx_lock);
  362. return ret;
  363. }
  364. EXPORT_SYMBOL(sb_tx_init);
  365. int sb_tx_set_enable(bool tx_enable, int cable_type)
  366. {
  367. struct sb_tx *tx = get_sb_tx();
  368. if (tx_enable) {
  369. if (check_tx_err_state(tx)) {
  370. tx_log("abnormal case - run tx err work!\n");
  371. __pm_stay_awake(tx->ws);
  372. queue_delayed_work(tx->wq, &tx->tx_err_work, msecs_to_jiffies(1000));
  373. }
  374. } else {
  375. cancel_delayed_work(&tx->tx_err_work);
  376. __pm_relax(tx->ws);
  377. }
  378. return 0;
  379. }
  380. EXPORT_SYMBOL(sb_tx_set_enable);
  381. bool sb_tx_get_enable(void)
  382. {
  383. struct sb_tx *tx = get_sb_tx();
  384. return (tx != NULL) ? tx->enable : false;
  385. }
  386. EXPORT_SYMBOL(sb_tx_get_enable);
  387. int sb_tx_set_event(int value, int mask)
  388. {
  389. return 0;
  390. }
  391. EXPORT_SYMBOL(sb_tx_set_event);
  392. int sb_tx_psy_set_property(enum power_supply_property psp, const union power_supply_propval *value)
  393. {
  394. return 0;
  395. }
  396. EXPORT_SYMBOL(sb_tx_psy_set_property);
  397. int sb_tx_psy_get_property(enum power_supply_property psp, union power_supply_propval *value)
  398. {
  399. return 0;
  400. }
  401. EXPORT_SYMBOL(sb_tx_psy_get_property);
  402. int sb_tx_monitor(int cable_type, int capacity, int lcd_state)
  403. {
  404. return 0;
  405. }
  406. EXPORT_SYMBOL(sb_tx_monitor);