sec_cisd.c 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856
  1. /*
  2. * sec_cisd.c
  3. * Samsung Mobile Battery Driver
  4. *
  5. * Copyright (C) 2012 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 "sec_cisd.h"
  14. #if IS_ENABLED(CONFIG_SEC_ABC)
  15. #include <linux/sti/abc_common.h>
  16. #endif
  17. const char *cisd_data_str[] = {
  18. "RESET_ALG", "ALG_INDEX", "FULL_CNT", "CAP_MAX", "CAP_MIN", "RECHARGING_CNT", "VALERT_CNT",
  19. "BATT_CYCLE", "WIRE_CNT", "WIRELESS_CNT", "HIGH_SWELLING_CNT", "LOW_SWELLING_CNT",
  20. "WC_HIGH_SWELLING_CNT", "SWELLING_FULL_CNT", "SWELLING_RECOVERY_CNT", "AICL_CNT", "BATT_THM_MAX",
  21. "BATT_THM_MIN", "CHG_THM_MAX", "CHG_THM_MIN", "WPC_THM_MAX", "WPC_THM_MIN", "USB_THM_MAX", "USB_THM_MIN",
  22. "CHG_BATT_THM_MAX", "CHG_BATT_THM_MIN", "CHG_CHG_THM_MAX", "CHG_CHG_THM_MIN", "CHG_WPC_THM_MAX",
  23. "CHG_WPC_THM_MIN", "CHG_USB_THM_MAX", "CHG_USB_THM_MIN", "USB_OVERHEAT_CHARGING", "UNSAFETY_VOLT",
  24. "UNSAFETY_TEMP", "SAFETY_TIMER", "VSYS_OVP", "VBAT_OVP", "USB_OVERHEAT_RAPID_CHANGE", "ASOC",
  25. "USB_OVERHEAT_ALONE", "CAP_NOM", "RC0"
  26. };
  27. EXPORT_SYMBOL(cisd_data_str);
  28. const char *cisd_data_str_d[] = {
  29. "FULL_CNT_D", "CAP_MAX_D", "CAP_MIN_D", "RECHARGING_CNT_D", "VALERT_CNT_D", "WIRE_CNT_D", "WIRELESS_CNT_D",
  30. "HIGH_SWELLING_CNT_D", "LOW_SWELLING_CNT_D", "WC_HIGH_SWELLING_CNT_D", "SWELLING_FULL_CNT_D",
  31. "SWELLING_RECOVERY_CNT_D", "AICL_CNT_D", "BATT_THM_MAX_D", "BATT_THM_MIN_D", "SUB_BATT_THM_MAX_D",
  32. "SUB_BATT_THM_MIN_D", "CHG_THM_MAX_D", "CHG_THM_MIN_D", "USB_THM_MAX_D", "USB_THM_MIN_D",
  33. "CHG_BATT_THM_MAX_D", "CHG_BATT_THM_MIN_D", "CHG_SUB_BATT_THM_MAX_D", "CHG_SUB_BATT_THM_MIN_D",
  34. "CHG_CHG_THM_MAX_D", "CHG_CHG_THM_MIN_D", "CHG_USB_THM_MAX_D", "CHG_USB_THM_MIN_D",
  35. "USB_OVERHEAT_CHARGING_D", "UNSAFETY_VOLT_D", "UNSAFETY_TEMP_D",
  36. "SAFETY_TIMER_D", "VSYS_OVP_D", "VBAT_OVP_D", "USB_OVERHEAT_RAPID_CHANGE_D", "BUCK_OFF_D",
  37. "USB_OVERHEAT_ALONE_D", "DROP_SENSOR_D", "CHG_TIME_D", "TOTAL_CHG_TIME_D"
  38. };
  39. EXPORT_SYMBOL(cisd_data_str_d);
  40. const char *cisd_cable_data_str[] = {"TA", "AFC", "AFC_FAIL", "QC", "QC_FAIL", "PD", "PD_HIGH", "HV_WC_20", "FPDO_DC"};
  41. EXPORT_SYMBOL(cisd_cable_data_str);
  42. const char *cisd_tx_data_str[] = {"ON", "OTHER", "GEAR", "PHONE", "BUDS"};
  43. EXPORT_SYMBOL(cisd_tx_data_str);
  44. #if IS_ENABLED(CONFIG_DUAL_BATTERY)
  45. const char *cisd_event_data_str[] = {"DC_ERR", "TA_OCP_DET", "TA_OCP_ON", "OVP_EVENT_POWER", "OVP_EVENT_SIGNAL", "OTG", "D2D", "MAIN_BAT_ERR", "SUB_BAT_ERR", "WA_ERR"};
  46. #else
  47. const char *cisd_event_data_str[] = {"DC_ERR", "TA_OCP_DET", "TA_OCP_ON", "OVP_EVENT_POWER", "OVP_EVENT_SIGNAL", "OTG", "D2D"};
  48. #endif
  49. EXPORT_SYMBOL(cisd_event_data_str);
  50. bool sec_bat_cisd_check(struct sec_battery_info *battery)
  51. {
  52. union power_supply_propval val = {0, };
  53. struct cisd *pcisd = &battery->cisd;
  54. bool ret = false;
  55. int voltage = battery->voltage_now;
  56. if (battery->factory_mode || battery->is_jig_on || battery->skip_cisd) {
  57. dev_info(battery->dev, "%s: No need to check in factory mode\n",
  58. __func__);
  59. return ret;
  60. }
  61. #if IS_ENABLED(CONFIG_DUAL_BATTERY)
  62. voltage = max(battery->voltage_avg_main, battery->voltage_avg_sub);
  63. #endif
  64. if ((battery->status == POWER_SUPPLY_STATUS_CHARGING) ||
  65. (battery->status == POWER_SUPPLY_STATUS_FULL)) {
  66. /* check abnormal vbat */
  67. pcisd->ab_vbat_check_count = voltage > pcisd->max_voltage_thr ?
  68. pcisd->ab_vbat_check_count + 1 : 0;
  69. if ((pcisd->ab_vbat_check_count >= pcisd->ab_vbat_max_count) &&
  70. !(pcisd->state & CISD_STATE_OVER_VOLTAGE)) {
  71. dev_info(battery->dev, "%s : [CISD] Battery Over Voltage Protection !! vbat(%d)mV\n",
  72. __func__, voltage);
  73. val.intval = true;
  74. psy_do_property("battery", set, POWER_SUPPLY_EXT_PROP_VBAT_OVP,
  75. val);
  76. pcisd->data[CISD_DATA_VBAT_OVP]++;
  77. pcisd->data[CISD_DATA_VBAT_OVP_PER_DAY]++;
  78. pcisd->state |= CISD_STATE_OVER_VOLTAGE;
  79. #if IS_ENABLED(CONFIG_SEC_ABC)
  80. #if IS_ENABLED(CONFIG_SEC_FACTORY)
  81. sec_abc_send_event("MODULE=battery@INFO=over_voltage");
  82. #else
  83. sec_abc_send_event("MODULE=battery@WARN=over_voltage");
  84. #endif
  85. #endif
  86. }
  87. if (battery->temperature > pcisd->data[CISD_DATA_CHG_BATT_TEMP_MAX])
  88. pcisd->data[CISD_DATA_CHG_BATT_TEMP_MAX] = battery->temperature;
  89. if (battery->temperature < pcisd->data[CISD_DATA_CHG_BATT_TEMP_MIN])
  90. pcisd->data[CISD_DATA_CHG_BATT_TEMP_MIN] = battery->temperature;
  91. if (battery->chg_temp > pcisd->data[CISD_DATA_CHG_CHG_TEMP_MAX])
  92. pcisd->data[CISD_DATA_CHG_CHG_TEMP_MAX] = battery->chg_temp;
  93. if (battery->chg_temp < pcisd->data[CISD_DATA_CHG_CHG_TEMP_MIN])
  94. pcisd->data[CISD_DATA_CHG_CHG_TEMP_MIN] = battery->chg_temp;
  95. if (battery->wpc_temp > pcisd->data[CISD_DATA_CHG_WPC_TEMP_MAX])
  96. pcisd->data[CISD_DATA_CHG_WPC_TEMP_MAX] = battery->wpc_temp;
  97. if (battery->wpc_temp < pcisd->data[CISD_DATA_CHG_WPC_TEMP_MIN])
  98. pcisd->data[CISD_DATA_CHG_WPC_TEMP_MIN] = battery->wpc_temp;
  99. if (battery->usb_temp > pcisd->data[CISD_DATA_CHG_USB_TEMP_MAX])
  100. pcisd->data[CISD_DATA_CHG_USB_TEMP_MAX] = battery->usb_temp;
  101. if (battery->usb_temp < pcisd->data[CISD_DATA_CHG_USB_TEMP_MIN])
  102. pcisd->data[CISD_DATA_CHG_USB_TEMP_MIN] = battery->usb_temp;
  103. if (battery->temperature > pcisd->data[CISD_DATA_CHG_BATT_TEMP_MAX_PER_DAY])
  104. pcisd->data[CISD_DATA_CHG_BATT_TEMP_MAX_PER_DAY] = battery->temperature;
  105. if (battery->temperature < pcisd->data[CISD_DATA_CHG_BATT_TEMP_MIN_PER_DAY])
  106. pcisd->data[CISD_DATA_CHG_BATT_TEMP_MIN_PER_DAY] = battery->temperature;
  107. if (battery->sub_bat_temp > pcisd->data[CISD_DATA_CHG_SUB_BATT_TEMP_MAX_PER_DAY])
  108. pcisd->data[CISD_DATA_CHG_SUB_BATT_TEMP_MAX_PER_DAY] = battery->sub_bat_temp;
  109. if (battery->sub_bat_temp < pcisd->data[CISD_DATA_CHG_SUB_BATT_TEMP_MIN_PER_DAY])
  110. pcisd->data[CISD_DATA_CHG_SUB_BATT_TEMP_MIN_PER_DAY] = battery->sub_bat_temp;
  111. if (battery->chg_temp > pcisd->data[CISD_DATA_CHG_CHG_TEMP_MAX_PER_DAY])
  112. pcisd->data[CISD_DATA_CHG_CHG_TEMP_MAX_PER_DAY] = battery->chg_temp;
  113. if (battery->chg_temp < pcisd->data[CISD_DATA_CHG_CHG_TEMP_MIN_PER_DAY])
  114. pcisd->data[CISD_DATA_CHG_CHG_TEMP_MIN_PER_DAY] = battery->chg_temp;
  115. if (battery->usb_temp > pcisd->data[CISD_DATA_CHG_USB_TEMP_MAX_PER_DAY])
  116. pcisd->data[CISD_DATA_CHG_USB_TEMP_MAX_PER_DAY] = battery->usb_temp;
  117. if (battery->usb_temp < pcisd->data[CISD_DATA_CHG_USB_TEMP_MIN_PER_DAY])
  118. pcisd->data[CISD_DATA_CHG_USB_TEMP_MIN_PER_DAY] = battery->usb_temp;
  119. if (battery->usb_temp > 800 && !battery->usb_overheat_check) {
  120. battery->cisd.data[CISD_DATA_USB_OVERHEAT_CHARGING]++;
  121. battery->cisd.data[CISD_DATA_USB_OVERHEAT_CHARGING_PER_DAY]++;
  122. battery->usb_overheat_check = true;
  123. }
  124. } else {
  125. /* discharging */
  126. if (battery->status == POWER_SUPPLY_STATUS_NOT_CHARGING) {
  127. /* check abnormal vbat */
  128. pcisd->ab_vbat_check_count = voltage > pcisd->max_voltage_thr ?
  129. pcisd->ab_vbat_check_count + 1 : 0;
  130. if ((pcisd->ab_vbat_check_count >= pcisd->ab_vbat_max_count) &&
  131. !(pcisd->state & CISD_STATE_OVER_VOLTAGE)) {
  132. pcisd->data[CISD_DATA_VBAT_OVP]++;
  133. pcisd->data[CISD_DATA_VBAT_OVP_PER_DAY]++;
  134. pcisd->state |= CISD_STATE_OVER_VOLTAGE;
  135. #if IS_ENABLED(CONFIG_SEC_ABC)
  136. #if IS_ENABLED(CONFIG_SEC_FACTORY)
  137. sec_abc_send_event("MODULE=battery@INFO=over_voltage");
  138. #else
  139. sec_abc_send_event("MODULE=battery@WARN=over_voltage");
  140. #endif
  141. #endif
  142. }
  143. }
  144. val.intval = SEC_BATTERY_CAPACITY_FULL;
  145. psy_do_property(battery->pdata->fuelgauge_name, get,
  146. POWER_SUPPLY_PROP_ENERGY_NOW, val);
  147. if (val.intval == -1) {
  148. dev_info(battery->dev, "%s: [CISD] FG I2C fail. skip cisd check\n", __func__);
  149. return ret;
  150. }
  151. if (val.intval > pcisd->data[CISD_DATA_CAP_MAX])
  152. pcisd->data[CISD_DATA_CAP_MAX] = val.intval;
  153. if (val.intval < pcisd->data[CISD_DATA_CAP_MIN])
  154. pcisd->data[CISD_DATA_CAP_MIN] = val.intval;
  155. if (val.intval > pcisd->data[CISD_DATA_CAP_MAX_PER_DAY])
  156. pcisd->data[CISD_DATA_CAP_MAX_PER_DAY] = val.intval;
  157. if (val.intval < pcisd->data[CISD_DATA_CAP_MIN_PER_DAY])
  158. pcisd->data[CISD_DATA_CAP_MIN_PER_DAY] = val.intval;
  159. val.intval = SEC_BATTERY_CAPACITY_AGEDCELL;
  160. psy_do_property(battery->pdata->fuelgauge_name, get,
  161. POWER_SUPPLY_PROP_ENERGY_NOW, val);
  162. if (val.intval == -1) {
  163. dev_info(battery->dev, "%s: [CISD] FG I2C fail. skip cisd check\n", __func__);
  164. return ret;
  165. }
  166. pcisd->data[CISD_DATA_CAP_NOM] = val.intval;
  167. dev_info(battery->dev, "%s: [CISD] CAP_NOM %dmAh\n", __func__, pcisd->data[CISD_DATA_CAP_NOM]);
  168. val.intval = SEC_BATTERY_CAPACITY_RC0;
  169. psy_do_property(battery->pdata->fuelgauge_name, get,
  170. POWER_SUPPLY_PROP_ENERGY_NOW, val);
  171. if (val.intval == -1) {
  172. dev_info(battery->dev, "%s: [CISD] FG I2C fail. skip cisd check\n", __func__);
  173. return ret;
  174. }
  175. pcisd->data[CISD_DATA_RC0] = val.intval;
  176. dev_info(battery->dev, "%s: [CISD] RC0 0x%x\n", __func__, pcisd->data[CISD_DATA_RC0]);
  177. }
  178. if (battery->temperature > pcisd->data[CISD_DATA_BATT_TEMP_MAX])
  179. pcisd->data[CISD_DATA_BATT_TEMP_MAX] = battery->temperature;
  180. if (battery->temperature < battery->cisd.data[CISD_DATA_BATT_TEMP_MIN])
  181. pcisd->data[CISD_DATA_BATT_TEMP_MIN] = battery->temperature;
  182. if (battery->chg_temp > pcisd->data[CISD_DATA_CHG_TEMP_MAX])
  183. pcisd->data[CISD_DATA_CHG_TEMP_MAX] = battery->chg_temp;
  184. if (battery->chg_temp < pcisd->data[CISD_DATA_CHG_TEMP_MIN])
  185. pcisd->data[CISD_DATA_CHG_TEMP_MIN] = battery->chg_temp;
  186. if (battery->wpc_temp > pcisd->data[CISD_DATA_WPC_TEMP_MAX])
  187. pcisd->data[CISD_DATA_WPC_TEMP_MAX] = battery->wpc_temp;
  188. if (battery->wpc_temp < battery->cisd.data[CISD_DATA_WPC_TEMP_MIN])
  189. pcisd->data[CISD_DATA_WPC_TEMP_MIN] = battery->wpc_temp;
  190. if (battery->usb_temp > pcisd->data[CISD_DATA_USB_TEMP_MAX])
  191. pcisd->data[CISD_DATA_USB_TEMP_MAX] = battery->usb_temp;
  192. if (battery->usb_temp < pcisd->data[CISD_DATA_USB_TEMP_MIN])
  193. pcisd->data[CISD_DATA_USB_TEMP_MIN] = battery->usb_temp;
  194. if (battery->temperature > pcisd->data[CISD_DATA_BATT_TEMP_MAX_PER_DAY])
  195. pcisd->data[CISD_DATA_BATT_TEMP_MAX_PER_DAY] = battery->temperature;
  196. if (battery->temperature < pcisd->data[CISD_DATA_BATT_TEMP_MIN_PER_DAY])
  197. pcisd->data[CISD_DATA_BATT_TEMP_MIN_PER_DAY] = battery->temperature;
  198. if (battery->sub_bat_temp > pcisd->data[CISD_DATA_SUB_BATT_TEMP_MAX_PER_DAY])
  199. pcisd->data[CISD_DATA_SUB_BATT_TEMP_MAX_PER_DAY] = battery->sub_bat_temp;
  200. if (battery->sub_bat_temp < pcisd->data[CISD_DATA_SUB_BATT_TEMP_MIN_PER_DAY])
  201. pcisd->data[CISD_DATA_SUB_BATT_TEMP_MIN_PER_DAY] = battery->sub_bat_temp;
  202. if (battery->chg_temp > pcisd->data[CISD_DATA_CHG_TEMP_MAX_PER_DAY])
  203. pcisd->data[CISD_DATA_CHG_TEMP_MAX_PER_DAY] = battery->chg_temp;
  204. if (battery->chg_temp < pcisd->data[CISD_DATA_CHG_TEMP_MIN_PER_DAY])
  205. pcisd->data[CISD_DATA_CHG_TEMP_MIN_PER_DAY] = battery->chg_temp;
  206. if (battery->usb_temp > pcisd->data[CISD_DATA_USB_TEMP_MAX_PER_DAY])
  207. pcisd->data[CISD_DATA_USB_TEMP_MAX_PER_DAY] = battery->usb_temp;
  208. if (battery->usb_temp < pcisd->data[CISD_DATA_USB_TEMP_MIN_PER_DAY])
  209. pcisd->data[CISD_DATA_USB_TEMP_MIN_PER_DAY] = battery->usb_temp;
  210. return ret;
  211. }
  212. EXPORT_SYMBOL(sec_bat_cisd_check);
  213. static irqreturn_t cisd_irq_thread(int irq, void *data)
  214. {
  215. struct cisd *pcisd = data;
  216. pr_info("%s: irq(%d)\n", __func__, irq);
  217. if (irq == pcisd->irq_ovp_power &&
  218. !gpio_get_value(pcisd->gpio_ovp_power))
  219. pcisd->event_data[EVENT_OVP_POWER]++;
  220. if (irq == pcisd->irq_ovp_signal &&
  221. !gpio_get_value(pcisd->gpio_ovp_signal))
  222. pcisd->event_data[EVENT_OVP_SIGNAL]++;
  223. return IRQ_HANDLED;
  224. }
  225. #ifdef CONFIG_OF
  226. static void sec_cisd_parse_dt(struct cisd *pcisd)
  227. {
  228. struct device_node *np;
  229. int ret = 0;
  230. np = of_find_node_by_name(NULL, "sec-cisd");
  231. if (!np) {
  232. pr_err("%s: np NULL\n", __func__);
  233. return;
  234. }
  235. ret = of_get_named_gpio(np, "ovp_power", 0);
  236. if (ret >= 0) {
  237. pcisd->gpio_ovp_power = ret;
  238. pr_info("%s: set ovp_power gpio(%d)\n", __func__, pcisd->gpio_ovp_power);
  239. pcisd->irq_ovp_power = gpio_to_irq(pcisd->gpio_ovp_power);
  240. ret = request_threaded_irq(pcisd->irq_ovp_power, NULL,
  241. cisd_irq_thread, IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
  242. "cisd-ovp-power", pcisd);
  243. if (ret < 0) {
  244. pr_err("%s: failed to request ovp_power irq(ret = %d)\n",
  245. __func__, ret);
  246. pcisd->irq_ovp_power = 0;
  247. } else
  248. pr_info("%s: set irq_ovp_power(%d)\n", __func__, pcisd->irq_ovp_power);
  249. } else
  250. pr_err("%s: failed to get ovp_power\n", __func__);
  251. ret = of_get_named_gpio(np, "ovp_signal", 0);
  252. if (ret >= 0) {
  253. pcisd->gpio_ovp_signal = ret;
  254. pr_info("%s: set ovp_signal gpio(%d)\n", __func__, pcisd->gpio_ovp_signal);
  255. pcisd->irq_ovp_signal = gpio_to_irq(pcisd->gpio_ovp_signal);
  256. ret = request_threaded_irq(pcisd->irq_ovp_signal, NULL,
  257. cisd_irq_thread, IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
  258. "cisd-ovp-signal", pcisd);
  259. if (ret < 0) {
  260. pr_err("%s: failed to request ovp_signal irq(ret = %d)\n",
  261. __func__, ret);
  262. pcisd->irq_ovp_signal = 0;
  263. } else
  264. pr_info("%s: set irq_ovp_signal(%d)\n", __func__, pcisd->irq_ovp_signal);
  265. } else
  266. pr_err("%s: failed to get ovp_signal\n", __func__);
  267. }
  268. #else
  269. static void sec_cisd_parse_dt(struct cisd *pcisd)
  270. {
  271. }
  272. #endif
  273. struct cisd *gcisd;
  274. EXPORT_SYMBOL(gcisd);
  275. void sec_battery_cisd_init(struct sec_battery_info *battery)
  276. {
  277. /* parse dt */
  278. sec_cisd_parse_dt(&battery->cisd);
  279. /* init cisd data */
  280. battery->cisd.state = CISD_STATE_NONE;
  281. battery->cisd.data[CISD_DATA_ALG_INDEX] = battery->pdata->cisd_alg_index;
  282. battery->cisd.data[CISD_DATA_FULL_COUNT] = 1;
  283. battery->cisd.data[CISD_DATA_BATT_TEMP_MAX] = -300;
  284. battery->cisd.data[CISD_DATA_CHG_TEMP_MAX] = -300;
  285. battery->cisd.data[CISD_DATA_WPC_TEMP_MAX] = -300;
  286. battery->cisd.data[CISD_DATA_USB_TEMP_MAX] = -300;
  287. battery->cisd.data[CISD_DATA_BATT_TEMP_MIN] = 1000;
  288. battery->cisd.data[CISD_DATA_CHG_TEMP_MIN] = 1000;
  289. battery->cisd.data[CISD_DATA_WPC_TEMP_MIN] = 1000;
  290. battery->cisd.data[CISD_DATA_USB_TEMP_MIN] = 1000;
  291. battery->cisd.data[CISD_DATA_CHG_BATT_TEMP_MAX] = -300;
  292. battery->cisd.data[CISD_DATA_CHG_CHG_TEMP_MAX] = -300;
  293. battery->cisd.data[CISD_DATA_CHG_WPC_TEMP_MAX] = -300;
  294. battery->cisd.data[CISD_DATA_CHG_USB_TEMP_MAX] = -300;
  295. battery->cisd.data[CISD_DATA_CHG_BATT_TEMP_MIN] = 1000;
  296. battery->cisd.data[CISD_DATA_CHG_CHG_TEMP_MIN] = 1000;
  297. battery->cisd.data[CISD_DATA_CHG_WPC_TEMP_MIN] = 1000;
  298. battery->cisd.data[CISD_DATA_CHG_USB_TEMP_MIN] = 1000;
  299. battery->cisd.data[CISD_DATA_CAP_MIN] = 0xFFFF;
  300. battery->cisd.data[CISD_DATA_ASOC] = 100;
  301. battery->cisd.data[CISD_DATA_FULL_COUNT_PER_DAY] = 1;
  302. battery->cisd.data[CISD_DATA_BATT_TEMP_MAX_PER_DAY] = -300;
  303. battery->cisd.data[CISD_DATA_SUB_BATT_TEMP_MAX_PER_DAY] = -300;
  304. battery->cisd.data[CISD_DATA_CHG_TEMP_MAX_PER_DAY] = -300;
  305. battery->cisd.data[CISD_DATA_USB_TEMP_MAX_PER_DAY] = -300;
  306. battery->cisd.data[CISD_DATA_BATT_TEMP_MIN_PER_DAY] = 1000;
  307. battery->cisd.data[CISD_DATA_SUB_BATT_TEMP_MIN_PER_DAY] = 1000;
  308. battery->cisd.data[CISD_DATA_CHG_TEMP_MIN_PER_DAY] = 1000;
  309. battery->cisd.data[CISD_DATA_USB_TEMP_MIN_PER_DAY] = 1000;
  310. battery->cisd.data[CISD_DATA_CHG_BATT_TEMP_MAX_PER_DAY] = -300;
  311. battery->cisd.data[CISD_DATA_CHG_SUB_BATT_TEMP_MAX_PER_DAY] = -300;
  312. battery->cisd.data[CISD_DATA_CHG_CHG_TEMP_MAX_PER_DAY] = -300;
  313. battery->cisd.data[CISD_DATA_CHG_USB_TEMP_MAX_PER_DAY] = -300;
  314. battery->cisd.data[CISD_DATA_CHG_BATT_TEMP_MIN_PER_DAY] = 1000;
  315. battery->cisd.data[CISD_DATA_CHG_SUB_BATT_TEMP_MIN_PER_DAY] = 1000;
  316. battery->cisd.data[CISD_DATA_CHG_CHG_TEMP_MIN_PER_DAY] = 1000;
  317. battery->cisd.data[CISD_DATA_CHG_USB_TEMP_MIN_PER_DAY] = 1000;
  318. battery->cisd.data[CISD_DATA_CHG_RETENTION_TIME_PER_DAY] = 0;
  319. battery->cisd.data[CISD_DATA_TOTAL_CHG_RETENTION_TIME_PER_DAY] = 0;
  320. battery->cisd.ab_vbat_max_count = 2; /* should be 2 */
  321. battery->cisd.ab_vbat_check_count = 0;
  322. battery->cisd.max_voltage_thr = battery->pdata->max_voltage_thr;
  323. /* set cisd pointer */
  324. gcisd = &battery->cisd;
  325. /* initialize pad data */
  326. mutex_init(&battery->cisd.padlock);
  327. mutex_init(&battery->cisd.powerlock);
  328. mutex_init(&battery->cisd.pdlock);
  329. init_cisd_pad_data(&battery->cisd);
  330. init_cisd_power_data(&battery->cisd);
  331. init_cisd_pd_data(&battery->cisd);
  332. }
  333. EXPORT_SYMBOL(sec_battery_cisd_init);
  334. static struct pad_data *create_pad_data(unsigned int pad_id, unsigned int pad_count)
  335. {
  336. struct pad_data *temp_data;
  337. temp_data = kzalloc(sizeof(struct pad_data), GFP_KERNEL);
  338. if (temp_data == NULL)
  339. return NULL;
  340. temp_data->id = pad_id;
  341. temp_data->count = pad_count;
  342. temp_data->prev = temp_data->next = NULL;
  343. return temp_data;
  344. }
  345. static struct pad_data *find_pad_data_by_id(struct cisd *cisd, unsigned int pad_id)
  346. {
  347. struct pad_data *temp_data = cisd->pad_array->next;
  348. if (cisd->pad_count <= 0 || temp_data == NULL)
  349. return NULL;
  350. while ((temp_data->id != pad_id) &&
  351. ((temp_data = temp_data->next) != NULL));
  352. return temp_data;
  353. }
  354. static void add_pad_data(struct cisd *cisd, unsigned int pad_id, unsigned int pad_count)
  355. {
  356. struct pad_data *temp_data = cisd->pad_array->next;
  357. struct pad_data *pad_data;
  358. if (pad_id >= MAX_PAD_ID)
  359. return;
  360. pad_data = create_pad_data(pad_id, pad_count);
  361. if (pad_data == NULL)
  362. return;
  363. pr_info("%s: id(0x%x), count(%d)\n", __func__, pad_id, pad_count);
  364. while (temp_data) {
  365. if (temp_data->id > pad_id) {
  366. temp_data->prev->next = pad_data;
  367. pad_data->prev = temp_data->prev;
  368. pad_data->next = temp_data;
  369. temp_data->prev = pad_data;
  370. cisd->pad_count++;
  371. return;
  372. }
  373. temp_data = temp_data->next;
  374. }
  375. pr_info("%s: failed to add pad_data(%d, %d)\n",
  376. __func__, pad_id, pad_count);
  377. kfree(pad_data);
  378. }
  379. void init_cisd_pad_data(struct cisd *cisd)
  380. {
  381. struct pad_data *temp_data = NULL;
  382. mutex_lock(&cisd->padlock);
  383. temp_data = cisd->pad_array;
  384. while (temp_data) {
  385. struct pad_data *next_data = temp_data->next;
  386. kfree(temp_data);
  387. temp_data = next_data;
  388. }
  389. /* create dummy data */
  390. cisd->pad_array = create_pad_data(0, 0);
  391. if (cisd->pad_array == NULL)
  392. goto err_create_dummy_data;
  393. temp_data = create_pad_data(MAX_PAD_ID, 0);
  394. if (temp_data == NULL) {
  395. kfree(cisd->pad_array);
  396. cisd->pad_array = NULL;
  397. goto err_create_dummy_data;
  398. }
  399. cisd->pad_count = 0;
  400. cisd->pad_array->next = temp_data;
  401. temp_data->prev = cisd->pad_array;
  402. err_create_dummy_data:
  403. mutex_unlock(&cisd->padlock);
  404. }
  405. EXPORT_SYMBOL(init_cisd_pad_data);
  406. void count_cisd_pad_data(struct cisd *cisd, unsigned int pad_id)
  407. {
  408. struct pad_data *pad_data;
  409. if (cisd->pad_array == NULL) {
  410. pr_info("%s: can't update the connected count of pad_id(0x%x) because of null\n",
  411. __func__, pad_id);
  412. return;
  413. }
  414. mutex_lock(&cisd->padlock);
  415. pad_data = find_pad_data_by_id(cisd, pad_id);
  416. if (pad_data != NULL)
  417. pad_data->count++;
  418. else
  419. add_pad_data(cisd, pad_id, 1);
  420. mutex_unlock(&cisd->padlock);
  421. }
  422. EXPORT_SYMBOL(count_cisd_pad_data);
  423. void set_cisd_pad_data(struct sec_battery_info *battery, const char *buf)
  424. {
  425. struct cisd *pcisd = &battery->cisd;
  426. unsigned int pad_total_count, pad_id, pad_count;
  427. struct pad_data *pad_data;
  428. int i, x;
  429. pr_info("%s: %s\n", __func__, buf);
  430. if (pcisd->pad_count > 0)
  431. init_cisd_pad_data(pcisd);
  432. if (pcisd->pad_array == NULL) {
  433. pr_info("%s: can't set the pad data because of null\n", __func__);
  434. return;
  435. }
  436. if (sscanf(buf, "%10u %n", &pad_total_count, &x) <= 0) {
  437. pr_info("%s: failed to read pad index\n", __func__);
  438. return;
  439. }
  440. buf += (size_t)x;
  441. pr_info("%s: add pad data(count: %d)\n", __func__, pad_total_count);
  442. for (i = 0; i < pad_total_count; i++) {
  443. if (sscanf(buf, "0x%02x:%10u %n", &pad_id, &pad_count, &x) != 2) {
  444. pr_info("%s: failed to read pad data(0x%x, %d, %d)!!!re-init pad data\n",
  445. __func__, pad_id, pad_count, x);
  446. init_cisd_pad_data(pcisd);
  447. break;
  448. }
  449. buf += (size_t)x;
  450. mutex_lock(&pcisd->padlock);
  451. pad_data = find_pad_data_by_id(pcisd, pad_id);
  452. if (pad_data != NULL)
  453. pad_data->count = pad_count;
  454. else
  455. add_pad_data(pcisd, pad_id, pad_count);
  456. mutex_unlock(&pcisd->padlock);
  457. }
  458. }
  459. EXPORT_SYMBOL(set_cisd_pad_data);
  460. static struct power_data *create_power_data(unsigned int power, unsigned int power_count)
  461. {
  462. struct power_data *temp_data;
  463. temp_data = kzalloc(sizeof(struct power_data), GFP_KERNEL);
  464. if (temp_data == NULL)
  465. return NULL;
  466. temp_data->power = power;
  467. temp_data->count = power_count;
  468. temp_data->prev = temp_data->next = NULL;
  469. return temp_data;
  470. }
  471. static struct power_data *find_data_by_power(struct cisd *cisd, unsigned int power)
  472. {
  473. struct power_data *temp_data = cisd->power_array->next;
  474. if (cisd->power_count <= 0 || temp_data == NULL)
  475. return NULL;
  476. while ((temp_data->power != power) &&
  477. ((temp_data = temp_data->next) != NULL));
  478. return temp_data;
  479. }
  480. static void add_power_data(struct cisd *cisd, unsigned int power, unsigned int power_count)
  481. {
  482. struct power_data *temp_data = cisd->power_array->next;
  483. struct power_data *power_data;
  484. power_data = create_power_data(power, power_count);
  485. if (power_data == NULL)
  486. return;
  487. pr_info("%s: power(%d), count(%d)\n", __func__, power, power_count);
  488. while (temp_data) {
  489. if (temp_data->power > power) {
  490. temp_data->prev->next = power_data;
  491. power_data->prev = temp_data->prev;
  492. power_data->next = temp_data;
  493. temp_data->prev = power_data;
  494. cisd->power_count++;
  495. return;
  496. }
  497. temp_data = temp_data->next;
  498. }
  499. pr_info("%s: failed to add pad_data(%d, %d)\n",
  500. __func__, power, power_count);
  501. kfree(power_data);
  502. }
  503. void init_cisd_power_data(struct cisd *cisd)
  504. {
  505. struct power_data *temp_data = NULL;
  506. mutex_lock(&cisd->powerlock);
  507. temp_data = cisd->power_array;
  508. while (temp_data) {
  509. struct power_data *next_data = temp_data->next;
  510. kfree(temp_data);
  511. temp_data = next_data;
  512. }
  513. /* create dummy data */
  514. cisd->power_array = create_power_data(0, 0);
  515. if (cisd->power_array == NULL)
  516. goto err_create_dummy_data;
  517. temp_data = create_power_data(MAX_CHARGER_POWER, 0);
  518. if (temp_data == NULL) {
  519. kfree(cisd->power_array);
  520. cisd->power_array = NULL;
  521. goto err_create_dummy_data;
  522. }
  523. cisd->power_count = 0;
  524. cisd->power_array->next = temp_data;
  525. temp_data->prev = cisd->power_array;
  526. err_create_dummy_data:
  527. mutex_unlock(&cisd->powerlock);
  528. }
  529. EXPORT_SYMBOL(init_cisd_power_data);
  530. #define FIND_MAX_POWER 45000
  531. #define FIND_POWER_STEP 10000
  532. #define POWER_MARGIN 1000
  533. void count_cisd_power_data(struct cisd *cisd, int power)
  534. {
  535. struct power_data *power_data;
  536. int power_index = 0;
  537. pr_info("%s: power value : %d\n", __func__, power);
  538. if (cisd->power_array == NULL || power < 15000) {
  539. pr_info("%s: can't update the connected count of power(%d) because of null\n",
  540. __func__, power);
  541. return;
  542. }
  543. power_index = FIND_MAX_POWER;
  544. while (power_index >= 14000) {
  545. if (power + POWER_MARGIN - power_index >= 0) {
  546. power_index /= 1000;
  547. break;
  548. }
  549. power_index -= FIND_POWER_STEP;
  550. }
  551. mutex_lock(&cisd->powerlock);
  552. power_data = find_data_by_power(cisd, power_index);
  553. if (power_data != NULL)
  554. power_data->count++;
  555. else
  556. add_power_data(cisd, power_index, 1);
  557. mutex_unlock(&cisd->powerlock);
  558. }
  559. EXPORT_SYMBOL(count_cisd_power_data);
  560. void set_cisd_power_data(struct sec_battery_info *battery, const char *buf)
  561. {
  562. struct cisd *pcisd = &battery->cisd;
  563. unsigned int power_total_count, power_id, power_count;
  564. struct power_data *power_data;
  565. int i, x;
  566. pr_info("%s: %s\n", __func__, buf);
  567. if (pcisd->power_count > 0)
  568. init_cisd_power_data(pcisd);
  569. if (pcisd->power_array == NULL) {
  570. pr_info("%s: can't set the power data because of null\n", __func__);
  571. return;
  572. }
  573. if (sscanf(buf, "%10u %n", &power_total_count, &x) <= 0)
  574. return;
  575. buf += (size_t)x;
  576. pr_info("%s: add power data(count: %d)\n", __func__, power_total_count);
  577. for (i = 0; i < power_total_count; i++) {
  578. if (sscanf(buf, "%10u:%10u %n", &power_id, &power_count, &x) != 2) {
  579. pr_info("%s: failed to read power data(%d, %d, %d)!!!re-init power data\n",
  580. __func__, power_id, power_count, x);
  581. init_cisd_power_data(pcisd);
  582. break;
  583. }
  584. buf += (size_t)x;
  585. mutex_lock(&pcisd->powerlock);
  586. power_data = find_data_by_power(pcisd, power_id);
  587. if (power_data != NULL)
  588. power_data->count = power_count;
  589. else
  590. add_power_data(pcisd, power_id, power_count);
  591. mutex_unlock(&pcisd->powerlock);
  592. }
  593. }
  594. EXPORT_SYMBOL(set_cisd_power_data);
  595. static struct pd_data *create_pd_data(unsigned short pid, unsigned int pd_count)
  596. {
  597. struct pd_data *temp_data;
  598. temp_data = kzalloc(sizeof(struct pd_data), GFP_KERNEL);
  599. if (temp_data == NULL)
  600. return NULL;
  601. temp_data->pid = pid;
  602. temp_data->count = pd_count;
  603. temp_data->prev = temp_data->next = NULL;
  604. return temp_data;
  605. }
  606. static struct pd_data *find_data_by_pd(struct cisd *cisd, unsigned short pid)
  607. {
  608. struct pd_data *temp_data = cisd->pd_array->next;
  609. if (cisd->pd_count <= 0 || temp_data == NULL)
  610. return NULL;
  611. while ((temp_data->pid != pid) &&
  612. ((temp_data = temp_data->next) != NULL))
  613. ;
  614. return temp_data;
  615. }
  616. static void add_pd_data(struct cisd *cisd, unsigned short pid, unsigned int pd_count)
  617. {
  618. struct pd_data *temp_data = cisd->pd_array->next;
  619. struct pd_data *pd_data;
  620. pd_data = create_pd_data(pid, pd_count);
  621. if (pd_data == NULL)
  622. return;
  623. pr_info("%s: pid(0x%04x), count(%d)\n", __func__, pid, pd_count);
  624. while (temp_data) {
  625. if (temp_data->pid > pid) {
  626. temp_data->prev->next = pd_data;
  627. pd_data->prev = temp_data->prev;
  628. pd_data->next = temp_data;
  629. temp_data->prev = pd_data;
  630. cisd->pd_count++;
  631. return;
  632. }
  633. temp_data = temp_data->next;
  634. }
  635. pr_info("%s: failed to add pd_data(0x%04x, %d)\n",
  636. __func__, pid, pd_count);
  637. kfree(pd_data);
  638. }
  639. void init_cisd_pd_data(struct cisd *cisd)
  640. {
  641. struct pd_data *temp_data = NULL;
  642. mutex_lock(&cisd->pdlock);
  643. temp_data = cisd->pd_array;
  644. while (temp_data) {
  645. struct pd_data *next_data = temp_data->next;
  646. kfree(temp_data);
  647. temp_data = next_data;
  648. }
  649. /* create dummy data */
  650. cisd->pd_array = create_pd_data(0, 0);
  651. if (cisd->pd_array == NULL)
  652. goto err_create_dummy_data;
  653. temp_data = create_pd_data(MAX_SS_PD_PID, 0);
  654. if (temp_data == NULL) {
  655. kfree(cisd->pd_array);
  656. cisd->pd_array = NULL;
  657. goto err_create_dummy_data;
  658. }
  659. cisd->pd_count = 0;
  660. cisd->pd_array->next = temp_data;
  661. temp_data->prev = cisd->pd_array;
  662. err_create_dummy_data:
  663. mutex_unlock(&cisd->pdlock);
  664. }
  665. EXPORT_SYMBOL(init_cisd_pd_data);
  666. void count_cisd_pd_data(unsigned short vid, unsigned short pid)
  667. {
  668. struct power_supply *psy = power_supply_get_by_name("battery");
  669. struct sec_battery_info *battery = power_supply_get_drvdata(psy);
  670. struct cisd *cisd = &battery->cisd;
  671. struct pd_data *pd_data;
  672. pr_info("%s: vid : 0x%04x, pid : 0x%04x\n", __func__, vid, pid);
  673. if (cisd->pd_array == NULL) {
  674. pr_info("%s: can't update count of pid(0x%04x) because of null\n",
  675. __func__, pid);
  676. return;
  677. }
  678. if ((vid != SS_PD_VID) || ((vid == SS_PD_VID)
  679. && (pid < MIN_SS_PD_PID || pid > MAX_SS_PD_PID))) {
  680. pr_info("%s: other pd ta(vid_0x%04x, pid_0x%04x). change pid to 0x0000\n",
  681. __func__, vid, pid);
  682. pid = 0x0;
  683. }
  684. mutex_lock(&cisd->pdlock);
  685. pd_data = find_data_by_pd(cisd, pid);
  686. if (pd_data != NULL)
  687. pd_data->count++;
  688. else
  689. add_pd_data(cisd, pid, 1);
  690. mutex_unlock(&cisd->pdlock);
  691. }
  692. EXPORT_SYMBOL(count_cisd_pd_data);
  693. void set_cisd_pd_data(struct sec_battery_info *battery, const char *buf)
  694. {
  695. struct cisd *pcisd = &battery->cisd;
  696. unsigned int pd_total_count, pid, pd_count;
  697. struct pd_data *pd_data;
  698. int i, x;
  699. pr_info("%s: %s\n", __func__, buf);
  700. if (pcisd->pd_count > 0)
  701. init_cisd_pd_data(pcisd);
  702. if (pcisd->pd_array == NULL) {
  703. pr_info("%s: can't set the pd data because of null\n", __func__);
  704. return;
  705. }
  706. if (sscanf(buf, "%10u %n", &pd_total_count, &x) <= 0)
  707. return;
  708. buf += (size_t)x;
  709. pr_info("%s: add pd data(count: %d)\n", __func__, pd_total_count);
  710. for (i = 0; i < pd_total_count; i++) {
  711. if (sscanf(buf, "0x%04x:%10u %n", &pid, &pd_count, &x) != 2) {
  712. pr_info("%s: failed to read pd data(0x%04x, %d, %d)!!!re-init pd data\n",
  713. __func__, pid, pd_count, x);
  714. init_cisd_pd_data(pcisd);
  715. break;
  716. }
  717. buf += (size_t)x;
  718. mutex_lock(&pcisd->pdlock);
  719. pd_data = find_data_by_pd(pcisd, pid);
  720. if (pd_data != NULL)
  721. pd_data->count = pd_count;
  722. else
  723. add_pd_data(pcisd, pid, pd_count);
  724. mutex_unlock(&pcisd->pdlock);
  725. }
  726. }
  727. EXPORT_SYMBOL(set_cisd_pd_data);