mtk_charger.c 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823
  1. /* Copyright Statement:
  2. *
  3. * This software/firmware and related documentation ("MediaTek Software") are
  4. * protected under relevant copyright laws. The information contained herein
  5. * is confidential and proprietary to MediaTek Inc. and/or its licensors.
  6. * Without the prior written permission of MediaTek inc. and/or its licensors,
  7. * any reproduction, modification, use or disclosure of MediaTek Software,
  8. * and information contained herein, in whole or in part, shall be strictly prohibited.
  9. */
  10. /* MediaTek Inc. (C) 2017. All rights reserved.
  11. *
  12. * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
  13. * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
  14. * RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER ON
  15. * AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
  16. * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
  17. * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
  18. * NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
  19. * SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
  20. * SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES TO LOOK ONLY TO SUCH
  21. * THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. RECEIVER EXPRESSLY ACKNOWLEDGES
  22. * THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES
  23. * CONTAINED IN MEDIATEK SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK
  24. * SOFTWARE RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
  25. * STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND
  26. * CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
  27. * AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
  28. * OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY RECEIVER TO
  29. * MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
  30. *
  31. * The following software/firmware and/or related documentation ("MediaTek Software")
  32. * have been modified by MediaTek Inc. All revisions are subject to any receiver\'s
  33. * applicable license agreements with MediaTek Inc.
  34. */
  35. #include <target/board.h>
  36. #include <kernel/thread.h>
  37. #include <platform/mt_typedefs.h>
  38. #include <platform/mt_reg_base.h>
  39. #include <platform/mt_pmic.h>
  40. #include <platform/upmu_hw.h>
  41. #include <platform/upmu_common.h>
  42. #include <platform/boot_mode.h>
  43. #include <platform/mt_gpt.h>
  44. #include <platform/mt_rtc.h>
  45. #include <platform/mt_rtc_hw.h>
  46. #include <platform/mt_pmic_wrap_init.h>
  47. #include <platform/mt_leds.h>
  48. #include <printf.h>
  49. #include <sys/types.h>
  50. #include <target/cust_battery.h>
  51. #include <libfdt.h>
  52. #include <lk_builtin_dtb.h>
  53. #include "mt_pumpexpress.h"
  54. #include "mtk_battery.h"
  55. #include "mtk_charger.h"
  56. #include "mtk_charger_intf.h"
  57. #include "tcpc_subpmic.h"
  58. #define MAX_SLEEP_LOOP 20
  59. #define VBUS_CHECK_COUNT 3
  60. static struct mtk_charger_info *primary_mchr;
  61. /*****************************************************************************
  62. * Global Variable
  63. ****************************************************************************/
  64. bool enable_mtk_charger = false;
  65. bool g_boot_reason_change = false;
  66. struct charger_custom_data chr_cust_data;
  67. /*****************************************************************************
  68. * Externl Variable
  69. ****************************************************************************/
  70. extern bool g_boot_menu;
  71. extern void mtk_wdt_restart(void);
  72. void mt65xx_bat_init(void){}
  73. void __attribute__((weak)) check_bat_status(void)
  74. {
  75. dprintf(CRITICAL, "%s: Please implement check_bat_status() if you don't use mtk charger.\n", __func__);
  76. }
  77. void __attribute__((weak)) enable_charging(bool enable)
  78. {
  79. dprintf(CRITICAL, "%s: Please implement enable_charging() if you don't use mtk charger.\n", __func__);
  80. }
  81. void __attribute__((weak)) enable_power_path(bool enable)
  82. {
  83. dprintf(CRITICAL, "%s: Please implement enable_power_path() if you don't use mtk charger.\n", __func__);
  84. }
  85. void __attribute__((weak)) enable_wdt(bool enable)
  86. {
  87. dprintf(CRITICAL, "%s: Please implement enable_wdt() if you don't use mtk charger.\n", __func__);
  88. }
  89. void __attribute__((weak)) charger_start(void)
  90. {
  91. dprintf(CRITICAL, "%s: Please implement charger_start() if you don't use mtk charger.\n", __func__);
  92. }
  93. int __attribute__((weak)) force_get_tbat(bool update)
  94. {
  95. dprintf(CRITICAL, "%s: T is not ready.\n", __func__);
  96. return 25;
  97. }
  98. int __attribute__((weak)) gauge_get_current(bool *curr_sign, int *bat_current)
  99. {
  100. dprintf(CRITICAL, "%s: IBAT is not ready.\n", __func__);
  101. *curr_sign = 1;
  102. *bat_current = 5000;
  103. return 0;
  104. }
  105. void __attribute__((weak)) mt_disp_show_charging(int index)
  106. {
  107. dprintf(CRITICAL, "%s: logo is not ready.\n", __func__);
  108. }
  109. void __attribute__((weak)) mt_disp_show_plug_charger(void)
  110. {
  111. dprintf(CRITICAL, "%s: logo is not ready.\n", __func__);
  112. }
  113. unsigned int chr_fdt_getprop_bool(const void *fdt, int nodeoffset,
  114. const char *name)
  115. {
  116. const void *data = NULL;
  117. int len = 0;
  118. data = fdt_getprop(fdt, nodeoffset, name, &len);
  119. if (data)
  120. return true;
  121. else
  122. return false;
  123. }
  124. void chr_fdt_getprop_char_array(const void *fdt, int nodeoffset,
  125. const char *name, char *out_value)
  126. {
  127. const void *data = NULL;
  128. int len = 0;
  129. data = fdt_getprop(fdt, nodeoffset, name, &len);
  130. if (len > 0 && data)
  131. memcpy(out_value, data, len);
  132. else
  133. memset(out_value, 0, len);
  134. }
  135. unsigned int chr_fdt_getprop_u32(const void *fdt, int nodeoffset,
  136. const char *name)
  137. {
  138. const void *data = NULL;
  139. int len = 0;
  140. data = fdt_getprop(fdt, nodeoffset, name, &len);
  141. if (len > 0 && data)
  142. return fdt32_to_cpu(*(unsigned int *)data);
  143. else
  144. return 0;
  145. }
  146. void init_charger_custom_data(void)
  147. {
  148. chr_cust_data.disable_charger = false;
  149. chr_cust_data.power_path_support = true;
  150. chr_cust_data.enable_pe_plus = true;
  151. chr_cust_data.max_charger_voltage = 6500;
  152. chr_cust_data.min_charger_voltage = 4000;
  153. chr_cust_data.fast_charge_voltage = 3000;
  154. /* charging current */
  155. chr_cust_data.usb_charger_current = 500;
  156. chr_cust_data.ac_charger_current = 2050;
  157. chr_cust_data.ac_charger_input_current = 3200;
  158. chr_cust_data.non_std_ac_charger_current = 500;
  159. chr_cust_data.charging_host_charger_current = 500;
  160. chr_cust_data.ta_ac_charger_current = 3000;
  161. chr_cust_data.pd_charger_current = 500;
  162. /* temperature protection ref sw jeita */
  163. chr_cust_data.temp_t4_threshold = 50;
  164. chr_cust_data.temp_t3_threshold = 45;
  165. chr_cust_data.temp_t1_threshold = 0;
  166. /* charging anime */
  167. chr_cust_data.enable_anime = false;
  168. chr_cust_data.led_brightness = 20;
  169. chr_cust_data.blinking_times = 6;
  170. chr_cust_data.blinking_period = 1500;
  171. /* vbus resistance */
  172. chr_cust_data.r_charger_1 = 330;
  173. chr_cust_data.r_charger_2 = 39;
  174. }
  175. int init_cust_data_from_dt(void)
  176. {
  177. int offset, val;
  178. offset = fdt_node_offset_by_compatible(get_lk_overlayed_dtb(), -1, "mediatek,lk_charger");
  179. if (offset >= 0) {
  180. val = chr_fdt_getprop_bool(get_lk_overlayed_dtb(), offset, "disable_charger");
  181. if (val)
  182. chr_cust_data.disable_charger = true;
  183. else
  184. chr_cust_data.disable_charger = false;
  185. val = chr_fdt_getprop_bool(get_lk_overlayed_dtb(), offset, "enable_pe_plus");
  186. if (val)
  187. chr_cust_data.enable_pe_plus = true;
  188. else
  189. chr_cust_data.enable_pe_plus = false;
  190. val = chr_fdt_getprop_bool(get_lk_overlayed_dtb(), offset, "enable_pd20_reset");
  191. if (val)
  192. chr_cust_data.enable_pd20_reset = true;
  193. else
  194. chr_cust_data.enable_pd20_reset = false;
  195. val = chr_fdt_getprop_bool(get_lk_overlayed_dtb(), offset, "power_path_support");
  196. if (val)
  197. chr_cust_data.power_path_support = true;
  198. else
  199. chr_cust_data.power_path_support = false;
  200. val = chr_fdt_getprop_u32(get_lk_overlayed_dtb(), offset, "max_charger_voltage");
  201. if (val)
  202. chr_cust_data.max_charger_voltage = val / 1000;
  203. val = chr_fdt_getprop_u32(get_lk_overlayed_dtb(), offset, "min_charger_voltage");
  204. if (val)
  205. chr_cust_data.min_charger_voltage = val / 1000;
  206. val = chr_fdt_getprop_u32(get_lk_overlayed_dtb(), offset, "fast_charge_voltage");
  207. if (val)
  208. chr_cust_data.fast_charge_voltage = val / 1000;
  209. val = chr_fdt_getprop_u32(get_lk_overlayed_dtb(), offset, "usb_charger_current");
  210. if (val)
  211. chr_cust_data.usb_charger_current = val / 1000;
  212. val = chr_fdt_getprop_u32(get_lk_overlayed_dtb(), offset, "ac_charger_current");
  213. if (val)
  214. chr_cust_data.ac_charger_current = val / 1000;
  215. val = chr_fdt_getprop_u32(get_lk_overlayed_dtb(), offset, "ac_charger_input_current");
  216. if (val)
  217. chr_cust_data.ac_charger_input_current = val / 1000;
  218. val = chr_fdt_getprop_u32(get_lk_overlayed_dtb(), offset, "non_std_ac_charger_current");
  219. if (val)
  220. chr_cust_data.non_std_ac_charger_current = val / 1000;
  221. val = chr_fdt_getprop_u32(get_lk_overlayed_dtb(), offset, "charging_host_charger_current");
  222. if (val)
  223. chr_cust_data.charging_host_charger_current = val / 1000;
  224. val = chr_fdt_getprop_u32(get_lk_overlayed_dtb(), offset, "ta_ac_charger_current");
  225. if (val)
  226. chr_cust_data.ta_ac_charger_current = val / 1000;
  227. val = chr_fdt_getprop_u32(get_lk_overlayed_dtb(), offset, "pd_charger_current");
  228. if (val)
  229. chr_cust_data.pd_charger_current = val / 1000;
  230. val = chr_fdt_getprop_u32(get_lk_overlayed_dtb(), offset, "temp_t4_threshold");
  231. if (val)
  232. chr_cust_data.temp_t4_threshold = val;
  233. val = chr_fdt_getprop_u32(get_lk_overlayed_dtb(), offset, "temp_t3_threshold");
  234. if (val)
  235. chr_cust_data.temp_t3_threshold = val;
  236. val = chr_fdt_getprop_u32(get_lk_overlayed_dtb(), offset, "temp_t1_threshold");
  237. if (val)
  238. chr_cust_data.temp_t1_threshold = val;
  239. val = chr_fdt_getprop_bool(get_lk_overlayed_dtb(), offset, "enable_anime");
  240. if (val)
  241. chr_cust_data.enable_anime = true;
  242. else
  243. chr_cust_data.enable_anime = false;
  244. val = chr_fdt_getprop_u32(get_lk_overlayed_dtb(), offset, "led_brightness");
  245. if (val)
  246. chr_cust_data.led_brightness = val;
  247. val = chr_fdt_getprop_u32(get_lk_overlayed_dtb(), offset, "blinking_times");
  248. if (val)
  249. chr_cust_data.blinking_times = val;
  250. val = chr_fdt_getprop_u32(get_lk_overlayed_dtb(), offset, "blinking_period");
  251. if (val)
  252. chr_cust_data.blinking_period = val;
  253. val = chr_fdt_getprop_u32(get_lk_overlayed_dtb(), offset, "r_charger_1");
  254. if (val)
  255. chr_cust_data.r_charger_1 = val;
  256. val = chr_fdt_getprop_u32(get_lk_overlayed_dtb(), offset, "r_charger_2");
  257. if (val)
  258. chr_cust_data.r_charger_2 = val;
  259. dprintf(CRITICAL, "[%s]:chroff:%d,pe:%d,powpath:%d,vchrmax:%d,vchrmin:%d,vfast:%d,"
  260. "usb:%d,ac:%d %d,nac:%d,cdp:%d,ta:%d,pd:%d,t:%d %d %d\n", __func__,
  261. chr_cust_data.disable_charger, chr_cust_data.enable_pe_plus,
  262. chr_cust_data.power_path_support, chr_cust_data.max_charger_voltage,
  263. chr_cust_data.min_charger_voltage, chr_cust_data.fast_charge_voltage,
  264. chr_cust_data.usb_charger_current, chr_cust_data.ac_charger_current,
  265. chr_cust_data.ac_charger_input_current, chr_cust_data.non_std_ac_charger_current,
  266. chr_cust_data.charging_host_charger_current, chr_cust_data.ta_ac_charger_current,
  267. chr_cust_data.pd_charger_current, chr_cust_data.temp_t4_threshold,
  268. chr_cust_data.temp_t3_threshold, chr_cust_data.temp_t1_threshold);
  269. enable_mtk_charger = true;
  270. return 0;
  271. }
  272. else {
  273. dprintf(CRITICAL, "[%s]: lk_charger is not found in dts!\n", __func__);
  274. enable_mtk_charger = false;
  275. return 1;
  276. }
  277. }
  278. void chr_power_off(void)
  279. {
  280. #ifdef MTK_PMIC_POWER_OFF
  281. mt_power_off();
  282. #else
  283. mt6575_power_off();
  284. #endif
  285. }
  286. int get_chr_volt(void)
  287. {
  288. unsigned int val = 0;
  289. #if defined(MACH_TYPE_MT6779) || defined(MACH_TYPE_MT6785) || defined(MACH_TYPE_MT6885)
  290. mtk_charger_get_vbus(primary_mchr, &val);
  291. val /= 1000;
  292. dprintf(CRITICAL, "%s: vbus = %d mV\n", __func__, val);
  293. #else
  294. val = pmic_get_auxadc_value(AUXADC_LIST_VCDT);
  295. val = (((chr_cust_data.r_charger_1 + chr_cust_data.r_charger_2) * 100 * val)
  296. / chr_cust_data.r_charger_2) / 100;
  297. #endif
  298. return val;
  299. }
  300. int get_bat_volt(int times)
  301. {
  302. int bat_vol;
  303. if (chr_cust_data.power_path_support == true)
  304. bat_vol = get_i_sense_volt(times);
  305. else
  306. bat_vol = get_bat_sense_volt(times);
  307. return bat_vol;
  308. }
  309. bool is_power_path_supported(void)
  310. {
  311. return chr_cust_data.power_path_support;
  312. }
  313. bool is_disable_charger(void)
  314. {
  315. return chr_cust_data.disable_charger;
  316. }
  317. bool is_battery_on(void)
  318. {
  319. /* FIXME: Need to replace with general PMIC interface */
  320. pmic_set_register_value(PMIC_RG_BATON_EN, 1);
  321. #if defined(MACH_TYPE_MT6765) || defined(MACH_TYPE_MT6761) || defined(MACH_TYPE_MT8168)
  322. if (pmic_get_register_value(PMIC_RGS_BATON_UNDET) == 1)
  323. #else
  324. if (pmic_get_register_value(PMIC_AD_BATON_UNDET) == 1)
  325. #endif
  326. return false;
  327. else
  328. return true;
  329. }
  330. bool is_low_battery(int val)
  331. {
  332. static unsigned char g_bat_low = 0xFF;
  333. //low battery only just once in lk
  334. if (0 == val) {
  335. if (0xFF != g_bat_low)
  336. return g_bat_low;
  337. else
  338. g_bat_low = false;
  339. val = get_bat_volt(1);
  340. }
  341. if (val < BATTERY_LOWVOL_THRESOLD) {
  342. dprintf(INFO, "%s, TRUE\n", __func__);
  343. g_bat_low = true;
  344. }
  345. else {
  346. dprintf(INFO, "%s, FALSE\n", __func__);
  347. g_bat_low = false;
  348. }
  349. return g_bat_low;
  350. }
  351. static void select_charging_current_limit(void)
  352. {
  353. int input_current_limit;
  354. int charging_current_limit;
  355. CHARGER_TYPE chr_type = g_boot_arg->charger_type;
  356. dprintf(INFO, "charger_type: %d\n", chr_type);
  357. if (chr_type == STANDARD_HOST) {
  358. input_current_limit = chr_cust_data.usb_charger_current;
  359. charging_current_limit = chr_cust_data.usb_charger_current;
  360. } else if (chr_type == NONSTANDARD_CHARGER) {
  361. input_current_limit = chr_cust_data.non_std_ac_charger_current;
  362. charging_current_limit = chr_cust_data.non_std_ac_charger_current;
  363. } else if (chr_type == STANDARD_CHARGER) {
  364. input_current_limit = chr_cust_data.ac_charger_input_current;
  365. charging_current_limit = chr_cust_data.ac_charger_current;
  366. } else if (chr_type == CHARGING_HOST) {
  367. input_current_limit = chr_cust_data.charging_host_charger_current;
  368. charging_current_limit = chr_cust_data.charging_host_charger_current;
  369. } else {
  370. input_current_limit = chr_cust_data.usb_charger_current;
  371. charging_current_limit = chr_cust_data.usb_charger_current;
  372. }
  373. mtk_charger_set_aicr(primary_mchr, input_current_limit);
  374. mtk_charger_set_ichg(primary_mchr, charging_current_limit);
  375. }
  376. static void reset_default_charging_current_limit(void)
  377. {
  378. int input_current_limit;
  379. int charging_current_limit;
  380. input_current_limit = chr_cust_data.usb_charger_current;
  381. charging_current_limit = chr_cust_data.usb_charger_current;
  382. mtk_charger_set_aicr(primary_mchr, input_current_limit);
  383. mtk_charger_set_ichg(primary_mchr, charging_current_limit);
  384. }
  385. static void show_plug_out_notify(void)
  386. {
  387. mt65xx_backlight_on();
  388. mt_disp_show_charger_ov_logo();
  389. thread_sleep(4000);
  390. mt65xx_backlight_off();
  391. }
  392. static void show_low_battery_notify(void)
  393. {
  394. mt65xx_leds_brightness_set(MT65XX_LED_TYPE_LCD, chr_cust_data.led_brightness);
  395. mt_disp_show_plug_charger();
  396. thread_sleep(4000);
  397. mt65xx_backlight_off();
  398. }
  399. static void check_charger_battery_on(void)
  400. {
  401. if (upmu_is_chr_det() == false) {
  402. dprintf(CRITICAL, "[BATTERY] No Charger, Power OFF !\n");
  403. show_low_battery_notify();
  404. chr_power_off();
  405. }
  406. if (!is_battery_on()) {
  407. dprintf(CRITICAL, "[BATTERY] No battry plug-in. Power Off.");
  408. chr_power_off();
  409. }
  410. mtk_charger_check_charging_mode(primary_mchr);
  411. }
  412. static void show_charging_anime(void)
  413. {
  414. int i,j;
  415. bool stop = false;
  416. /* set LCD brightness */
  417. mt65xx_leds_brightness_set(MT65XX_LED_TYPE_LCD, chr_cust_data.led_brightness);
  418. /* set blinking times */
  419. for (i = 0; i < chr_cust_data.blinking_times && !stop; i++) {
  420. mtk_wdt_restart();
  421. mt_disp_show_charging(i % 2);
  422. for (j = 0; j < 2 && !stop; j++) {
  423. /* set blinking period */
  424. thread_sleep(chr_cust_data.blinking_period);
  425. check_charger_battery_on();
  426. if(get_powerkey_pressed_status()) {
  427. clear_powerkey_pressed_status();
  428. stop = true;
  429. }
  430. }
  431. }
  432. mt65xx_backlight_off();
  433. mt_disp_show_charging(0);
  434. mtk_charger_reset_wdt(primary_mchr);
  435. }
  436. void check_charger_volt(void)
  437. {
  438. int i;
  439. int chr_volt;
  440. if (g_boot_mode == KERNEL_POWER_OFF_CHARGING_BOOT ||
  441. g_boot_mode == LOW_POWER_OFF_CHARGING_BOOT) {
  442. for (i = 0; i < VBUS_CHECK_COUNT; i++) {
  443. chr_volt = get_chr_volt();
  444. if (chr_volt < chr_cust_data.min_charger_voltage) {
  445. dprintf(INFO, "vbus is less than %dmv, power off\n",
  446. chr_cust_data.min_charger_voltage);
  447. chr_power_off();
  448. }
  449. }
  450. }
  451. if (chr_cust_data.power_path_support == true) {
  452. chr_volt = get_chr_volt();
  453. if (chr_volt > chr_cust_data.max_charger_voltage) {
  454. dprintf(CRITICAL, "Charger Over Voltage:%d\n, power off...", chr_volt);
  455. show_plug_out_notify();
  456. chr_power_off();
  457. }
  458. }
  459. }
  460. /*
  461. * enter this function when low battery with charger
  462. */
  463. void check_bat_protect_status(void)
  464. {
  465. int ret = 0;
  466. int bat_val = 0;
  467. int i;
  468. int temperature;
  469. int bat_current = 0;
  470. bool curr_sign = 0;
  471. static bool is_first = 1;
  472. if (enable_mtk_charger == false) {
  473. check_bat_status();
  474. return;
  475. }
  476. ret = mtk_charger_enable_charging(primary_mchr, false);
  477. if (ret < 0)
  478. dprintf(CRITICAL, "%s: disable charging failed, ret = %d\n", __func__, ret);
  479. bat_val = get_bat_volt(5);
  480. dprintf(CRITICAL, "[%s]: check VBAT=%d mV with %d mV\n", __func__,
  481. bat_val, BATTERY_LOWVOL_THRESOLD);
  482. clear_powerkey_pressed_status();
  483. unsigned int time_charging;
  484. time_charging = get_timer(0);
  485. //unsigned int time_sleeping;
  486. while (bat_val < BATTERY_LOWVOL_THRESOLD) {
  487. mtk_wdt_restart();
  488. mtk_charger_reset_wdt(primary_mchr);
  489. check_charger_battery_on();
  490. check_charger_volt();
  491. temperature = force_get_tbat(true);
  492. dprintf(INFO, "%s: T=%d\n", __func__, temperature);
  493. if(temperature > chr_cust_data.temp_t4_threshold) {
  494. dprintf(CRITICAL,"[BATTERY] Battery over Temperature or NTC fail %d %d!!\n\r", temperature,
  495. chr_cust_data.temp_t4_threshold);
  496. break;
  497. }
  498. if (bat_val < chr_cust_data.fast_charge_voltage ||
  499. temperature > chr_cust_data.temp_t3_threshold ||
  500. temperature < chr_cust_data.temp_t1_threshold)
  501. reset_default_charging_current_limit();
  502. else
  503. select_charging_current_limit();
  504. ret = mtk_charger_enable_charging(primary_mchr, true);
  505. if (ret < 0)
  506. dprintf(CRITICAL, "%s: enable charging failed, ret = %d\n", __func__, ret);
  507. //time_sleeping = get_timer(0);
  508. if (chr_cust_data.enable_anime && bat_val > chr_cust_data.fast_charge_voltage) {
  509. if (is_first) {
  510. show_charging_anime();
  511. is_first = 0;
  512. }
  513. for (i = 0; i < MAX_SLEEP_LOOP; i++) {
  514. mtk_wdt_restart();
  515. check_charger_battery_on();
  516. /* set polling period */
  517. thread_sleep(1000);
  518. if(get_powerkey_pressed_status()) {
  519. clear_powerkey_pressed_status();
  520. show_charging_anime();
  521. }
  522. }
  523. } else {
  524. for (i = 0; i < MAX_SLEEP_LOOP; i++) {
  525. mtk_wdt_restart();
  526. check_charger_battery_on();
  527. /* set polling period */
  528. thread_sleep(1000);
  529. }
  530. }
  531. //dprintf(CRITICAL, "[PROFILE] ------- charging %d ms -------- \n", (int)get_timer(time_sleeping));
  532. if (is_battery_on()) {
  533. gauge_get_current(&curr_sign, &bat_current);
  534. bat_current = bat_current / 10;
  535. dprintf(INFO, "%s:IBAT=%d\n", __func__, curr_sign ? bat_current : -1 * bat_current);
  536. }
  537. if (g_boot_arg->charger_type == STANDARD_CHARGER && bat_val > chr_cust_data.fast_charge_voltage) {
  538. ret = mtk_charger_enable_charging(primary_mchr, false);
  539. if (ret < 0)
  540. dprintf(INFO, "%s: disable charging failed, ret = %d\n", __func__, ret);
  541. }
  542. bat_val = get_bat_volt(5);
  543. dprintf(INFO, "[%s]: check VBAT=%d mV with %d mV, start charging...\n", __func__,
  544. bat_val, BATTERY_LOWVOL_THRESOLD);
  545. }
  546. dprintf(INFO, "[PROFILE] ------- Charging takes %d ms -------- \n", (int)get_timer(time_charging));
  547. mtk_wdt_restart();
  548. reset_default_charging_current_limit();
  549. }
  550. void check_low_battery(void)
  551. {
  552. int bat_vol;
  553. bat_vol = get_bat_volt(1);
  554. if (is_low_battery(bat_vol)) {
  555. if (g_boot_mode == KERNEL_POWER_OFF_CHARGING_BOOT && upmu_is_chr_det() == true) {
  556. dprintf(CRITICAL, "[%s] Kernel Low Battery Power Off Charging Mode\n", __func__);
  557. g_boot_mode = LOW_POWER_OFF_CHARGING_BOOT;
  558. check_bat_protect_status();
  559. } else {
  560. dprintf(CRITICAL, "[BATTERY] battery voltage(%dmV) <= CLV ! Can not Boot Linux Kernel !! \n\r",bat_vol);
  561. show_low_battery_notify();
  562. chr_power_off();
  563. }
  564. }
  565. }
  566. void reset_pd_adapter(void)
  567. {
  568. int chr_volt;
  569. if (!chr_cust_data.enable_pd20_reset)
  570. return;
  571. chr_volt = get_chr_volt();
  572. /* Try reset pd charger TA */
  573. if (chr_volt > chr_cust_data.max_charger_voltage) {
  574. dprintf(CRITICAL,
  575. "[mt65xx_bat_init] Try reset pd20 charger TA\n");
  576. pd_reset_adapter();
  577. }
  578. }
  579. void reset_pe_adapter(void)
  580. {
  581. if (chr_cust_data.enable_pe_plus == true) {
  582. int chr_volt;
  583. int rc = 0;
  584. /*Try to reset PE+ adapter once abnormal voltage is found*/
  585. chr_volt = get_chr_volt();
  586. while (chr_volt > chr_cust_data.max_charger_voltage) {
  587. dprintf(CRITICAL, "[mt65xx_bat_init] PE+ adpater should be reset to 5V now\n");
  588. pumpex_reset_adapter_enable(1);
  589. mdelay(250);
  590. pumpex_reset_adapter_enable(0);
  591. chr_volt = get_chr_volt();
  592. rc++;
  593. if (rc == 3)
  594. break;
  595. }
  596. }
  597. }
  598. void charger_enable_charging(bool enable)
  599. {
  600. int ret = 0;
  601. if (enable_mtk_charger == false) {
  602. enable_charging(enable);
  603. return;
  604. }
  605. primary_mchr = mtk_charger_get_by_name("primary_charger");
  606. if (!primary_mchr) {
  607. dprintf(CRITICAL, "%s: get primary charger failed\n", __func__);
  608. return;
  609. }
  610. ret = mtk_charger_enable_charging(primary_mchr, enable);
  611. if (ret < 0)
  612. dprintf(CRITICAL, "%s: enable/disable charging failed, ret = %d\n", __func__, ret);
  613. else {
  614. if(enable)
  615. dprintf(INFO, "%s: enable charging\n", __func__);
  616. else
  617. dprintf(INFO, "%s: disable charging\n", __func__);
  618. }
  619. }
  620. void charger_enable_power_path(bool enable)
  621. {
  622. int ret = 0;
  623. if (enable_mtk_charger == false) {
  624. enable_power_path(enable);
  625. return;
  626. }
  627. if (is_battery_on()) {
  628. primary_mchr = mtk_charger_get_by_name("primary_charger");
  629. if (!primary_mchr) {
  630. dprintf(CRITICAL, "%s: get primary charger failed\n", __func__);
  631. return;
  632. }
  633. ret = mtk_charger_enable_power_path(primary_mchr, enable);
  634. if (ret < 0)
  635. dprintf(CRITICAL, "%s: enable/disable power path failed, ret = %d\n", __func__, ret);
  636. }
  637. else
  638. dprintf(CRITICAL, "%s: no battery plug-in, skip power path control\n", __func__);
  639. }
  640. void charger_enable_wdt(bool enable)
  641. {
  642. int ret = 0;
  643. if (enable_mtk_charger == false) {
  644. enable_wdt(enable);
  645. return;
  646. }
  647. primary_mchr = mtk_charger_get_by_name("primary_charger");
  648. if (!primary_mchr) {
  649. dprintf(CRITICAL, "%s: get primary charger failed\n", __func__);
  650. return;
  651. }
  652. ret = mtk_charger_enable_wdt(primary_mchr, enable);
  653. if (ret < 0)
  654. dprintf(CRITICAL, "%s: enable/disable wdt failed, ret = %d\n", __func__, ret);
  655. else {
  656. if(enable)
  657. dprintf(INFO, "%s: enable wdt\n", __func__);
  658. else
  659. dprintf(INFO, "%s: disable wdt\n", __func__);
  660. }
  661. }
  662. void mtk_charger_start(void)
  663. {
  664. if (enable_mtk_charger == false) {
  665. charger_start();
  666. return;
  667. }
  668. if (chr_cust_data.disable_charger == false) {
  669. int ret = 0;
  670. /* Get charger interface */
  671. primary_mchr = mtk_charger_get_by_name("primary_charger");
  672. if (!primary_mchr) {
  673. dprintf(CRITICAL, "%s: get primary charger failed\n", __func__);
  674. return;
  675. }
  676. reset_pe_adapter();
  677. reset_pd_adapter();
  678. check_charger_volt();
  679. if (g_boot_mode == KERNEL_POWER_OFF_CHARGING_BOOT && pmic_detect_powerkey()) {
  680. dprintf(CRITICAL, "[mt65xx_bat_init] KPOC+PWRKEY => change boot mode\n");
  681. g_boot_reason_change = true;
  682. }
  683. check_low_battery();
  684. if (g_boot_mode != META_BOOT && g_boot_mode != FACTORY_BOOT && g_boot_mode != ATE_FACTORY_BOOT) {
  685. if (!is_battery_on()) {
  686. dprintf(CRITICAL, "[BATTERY] No battry plug-in. Power Off.");
  687. chr_power_off();
  688. }
  689. }
  690. /* disable wdt in case entering fastboot later... */
  691. ret = mtk_charger_enable_wdt(primary_mchr, false);
  692. if (ret < 0)
  693. dprintf(CRITICAL, "%s: disable wdt fail\n", __func__);
  694. }
  695. else
  696. dprintf(CRITICAL, "%s: skip mtk_charger_start\n", __func__);
  697. }