mt6397_fgadc.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444
  1. #include <linux/delay.h>
  2. #include <linux/errno.h>
  3. #include <mt-plat/upmu_common.h>
  4. #include <mt-plat/mt_reboot.h>
  5. #include "mt_battery_meter_hal.h"
  6. #include "mt_battery_custom_data.h"
  7. #define VOLTAGE_FULL_RANGE 1200
  8. #define ADC_PRECISE 1024 /* 10 bits */
  9. #define UNIT_FGCURRENT (158122) /* 158.122 uA */
  10. static s32 g_hw_ocv_tune_value = 8; /* hwocv chip calibration value */
  11. static bool g_fg_is_charging;
  12. static struct mt_battery_meter_custom_data *bat_meter_data;
  13. s32 use_chip_trim_value(s32 not_trim_val)
  14. {
  15. pr_debug("skip trim value for mt6397.\n");
  16. return not_trim_val;
  17. }
  18. int get_hw_ocv(void)
  19. {
  20. #if defined(CONFIG_POWER_EXT)
  21. return 4001 + g_hw_ocv_tune_value;
  22. #else
  23. s32 adc_result_reg = 0;
  24. s32 adc_result = 0;
  25. s32 r_val_temp = 4;
  26. #if defined(CONFIG_SWCHR_POWER_PATH)
  27. adc_result_reg = upmu_get_rg_adc_out_wakeup_swchr_trim();
  28. adc_result = (adc_result_reg * r_val_temp * VOLTAGE_FULL_RANGE) / ADC_PRECISE;
  29. pr_debug("[oam] get_hw_ocv (swchr) : adc_result_reg=%d, adc_result=%d\n",
  30. adc_result_reg, adc_result);
  31. #else
  32. adc_result_reg = upmu_get_rg_adc_out_wakeup_pchr();
  33. adc_result = (adc_result_reg * r_val_temp * VOLTAGE_FULL_RANGE) / ADC_PRECISE;
  34. pr_debug("[oam] get_hw_ocv (pchr) : adc_result_reg=%d, adc_result=%d\n",
  35. adc_result_reg, adc_result);
  36. #endif
  37. adc_result += g_hw_ocv_tune_value;
  38. return adc_result;
  39. #endif
  40. }
  41. /* ============================================================// */
  42. static u32 fg_get_data_ready_status(void)
  43. {
  44. u32 ret = 0;
  45. u32 temp_val = 0;
  46. ret = pmic_read_interface(FGADC_CON0, &temp_val, 0xFFFF, 0x0);
  47. pr_debug("[fg_get_data_ready_status] Reg[0x%x]=0x%x\r\n", FGADC_CON0, temp_val);
  48. temp_val =
  49. (temp_val & (PMIC_FG_LATCHDATA_ST_MASK << PMIC_FG_LATCHDATA_ST_SHIFT)) >>
  50. PMIC_FG_LATCHDATA_ST_SHIFT;
  51. return temp_val;
  52. }
  53. static s32 fgauge_read_current(void *data);
  54. static s32 fgauge_initialization(void *data)
  55. {
  56. u32 ret = 0;
  57. s32 current_temp = 0;
  58. int m = 0;
  59. bat_meter_data = (struct mt_battery_meter_custom_data *) data;
  60. /* 1. HW initialization */
  61. /* FGADC clock is 32768Hz from RTC */
  62. /* Enable FGADC in current mode at 32768Hz with auto-calibration */
  63. /* (1) Enable VA2 */
  64. /* (2) Enable FGADC clock for digital */
  65. upmu_set_rg_fgadc_ana_ck_pdn(0);
  66. upmu_set_rg_fgadc_ck_pdn(0);
  67. /* (3) Set current mode, auto-calibration mode and 32KHz clock source */
  68. ret = pmic_config_interface(FGADC_CON0, 0x0028, 0x00FF, 0x0);
  69. /* (4) Enable FGADC */
  70. ret = pmic_config_interface(FGADC_CON0, 0x0029, 0x00FF, 0x0);
  71. /* reset HW FG */
  72. ret = pmic_config_interface(FGADC_CON0, 0x7100, 0xFF00, 0x0);
  73. pr_debug("******** [fgauge_initialization] reset HW FG!\n");
  74. /* make sure init finish */
  75. m = 0;
  76. while (current_temp == 0) {
  77. fgauge_read_current(&current_temp);
  78. m++;
  79. if (m > 1000) {
  80. pr_warn("[fgauge_initialization] timeout!\r\n");
  81. break;
  82. }
  83. }
  84. pr_debug("******** [fgauge_initialization] Done!\n");
  85. return 0;
  86. }
  87. static s32 fgauge_read_current(void *data)
  88. {
  89. u16 uvalue16 = 0;
  90. s32 dvalue = 0;
  91. int m = 0;
  92. s64 Temp_Value = 0;
  93. s32 Current_Compensate_Value = 0;
  94. u32 ret = 0;
  95. s32 r_fg_board_slope = bat_meter_data->r_fg_board_slope;
  96. s32 r_fg_board_base = bat_meter_data->r_fg_board_base;
  97. s32 car_tune_value = bat_meter_data->car_tune_value;
  98. s32 r_fg_value = bat_meter_data->r_fg_value;
  99. /* HW Init */
  100. /* (1) i2c_write (0x60, 0xC8, 0x01); // Enable VA2 */
  101. /* (2) i2c_write (0x61, 0x15, 0x00); // Enable FGADC clock for digital */
  102. /* (3) i2c_write (0x61, 0x69, 0x28); // Set current mode, auto-calibration mode and 32KHz clock source */
  103. /* (4) i2c_write (0x61, 0x69, 0x29); // Enable FGADC */
  104. /* Read HW Raw Data */
  105. /* (1) Set READ command */
  106. ret = pmic_config_interface(FGADC_CON0, 0x0200, 0xFF00, 0x0);
  107. /* (2) Keep i2c read when status = 1 (0x06) */
  108. m = 0;
  109. while (fg_get_data_ready_status() == 0) {
  110. m++;
  111. if (m > 1000) {
  112. pr_warn("[fgauge_read_current] fg_get_data_ready_status timeout 1 !\r\n");
  113. break;
  114. }
  115. }
  116. /* (3) Read FG_CURRENT_OUT[15:08] */
  117. /* (4) Read FG_CURRENT_OUT[07:00] */
  118. uvalue16 = upmu_get_fg_current_out();
  119. pr_debug("[fgauge_read_current] : FG_CURRENT = %x\r\n", uvalue16);
  120. /* (5) (Read other data) */
  121. /* (6) Clear status to 0 */
  122. ret = pmic_config_interface(FGADC_CON0, 0x0800, 0xFF00, 0x0);
  123. /* (7) Keep i2c read when status = 0 (0x08) */
  124. /* while ( fg_get_sw_clear_status() != 0 ) */
  125. m = 0;
  126. while (fg_get_data_ready_status() != 0) {
  127. m++;
  128. if (m > 1000) {
  129. pr_warn("[fgauge_read_current] fg_get_data_ready_status timeout 2 !\r\n");
  130. break;
  131. }
  132. }
  133. /* (8) Recover original settings */
  134. ret = pmic_config_interface(FGADC_CON0, 0x0000, 0xFF00, 0x0);
  135. /* calculate the real world data */
  136. dvalue = (u32) uvalue16;
  137. if (dvalue == 0) {
  138. Temp_Value = (s64) dvalue;
  139. g_fg_is_charging = false;
  140. } else if (dvalue > 32767) {
  141. /* > 0x8000 */
  142. Temp_Value = (s64) (dvalue - 65535);
  143. Temp_Value = Temp_Value - (Temp_Value * 2);
  144. g_fg_is_charging = false;
  145. } else {
  146. Temp_Value = (s64) dvalue;
  147. g_fg_is_charging = true;
  148. }
  149. Temp_Value = Temp_Value * UNIT_FGCURRENT;
  150. do_div(Temp_Value, 100000);
  151. dvalue = (u32) Temp_Value;
  152. if (g_fg_is_charging == true)
  153. pr_debug("[fgauge_read_current] current(charging) = %d mA\r\n", dvalue);
  154. else
  155. pr_debug("[fgauge_read_current] current(discharging) = %d mA\r\n", dvalue);
  156. /* Auto adjust value */
  157. if (r_fg_value != 20) {
  158. pr_debug
  159. ("[fgauge_read_current] Auto adjust value due to the Rfg is %d\n Ori current=%d, ",
  160. r_fg_value, dvalue);
  161. dvalue = (dvalue * 20) / r_fg_value;
  162. pr_debug("[fgauge_read_current] new current=%d\n", dvalue);
  163. }
  164. /* K current */
  165. if (r_fg_board_slope != r_fg_board_base)
  166. dvalue = ((dvalue * r_fg_board_base) + (r_fg_board_slope / 2)) / r_fg_board_slope;
  167. /* current compensate */
  168. if (g_fg_is_charging == true)
  169. dvalue = dvalue + Current_Compensate_Value;
  170. else
  171. dvalue = dvalue - Current_Compensate_Value;
  172. pr_debug("[fgauge_read_current] ori current=%d\n", dvalue);
  173. dvalue = ((dvalue * car_tune_value) / 100);
  174. dvalue = use_chip_trim_value(dvalue);
  175. pr_debug("[fgauge_read_current] final current=%d (ratio=%d)\n", dvalue, car_tune_value);
  176. *(s32 *) (data) = dvalue;
  177. return 0;
  178. }
  179. static s32 fgauge_read_current_sign(void *data)
  180. {
  181. *(bool *) (data) = g_fg_is_charging;
  182. return 0;
  183. }
  184. static s32 fgauge_read_columb_internal(void *data, int reset)
  185. {
  186. u32 uvalue32_CAR = 0;
  187. u32 uvalue32_CAR_MSB = 0;
  188. s32 dvalue_CAR = 0;
  189. int m = 0;
  190. int Temp_Value = 0;
  191. u32 ret = 0;
  192. s32 r_fg_value = bat_meter_data->r_fg_value;
  193. s32 car_tune_value = bat_meter_data->car_tune_value;
  194. /* HW Init */
  195. /* (1) i2c_write (0x60, 0xC8, 0x01); // Enable VA2 */
  196. /* (2) i2c_write (0x61, 0x15, 0x00); // Enable FGADC clock for digital */
  197. /* (3) i2c_write (0x61, 0x69, 0x28); // Set current mode, auto-calibration mode and 32KHz clock source */
  198. /* (4) i2c_write (0x61, 0x69, 0x29); // Enable FGADC */
  199. /* Read HW Raw Data */
  200. /* (1) Set READ command */
  201. if (reset == 0)
  202. ret = pmic_config_interface(FGADC_CON0, 0x0200, 0xFF00, 0x0);
  203. else
  204. ret = pmic_config_interface(FGADC_CON0, 0x7300, 0xFF00, 0x0);
  205. /* (2) Keep i2c read when status = 1 (0x06) */
  206. m = 0;
  207. while (fg_get_data_ready_status() == 0) {
  208. m++;
  209. if (m > 1000) {
  210. pr_warn
  211. ("[fgauge_read_columb_internal] fg_get_data_ready_status timeout 1 !\r\n");
  212. break;
  213. }
  214. }
  215. /* (3) Read FG_CURRENT_OUT[28:14] */
  216. /* (4) Read FG_CURRENT_OUT[35] */
  217. uvalue32_CAR = (upmu_get_fg_car_15_00()) >> 14;
  218. uvalue32_CAR |= ((upmu_get_fg_car_31_16()) & 0x3FFF) << 2;
  219. uvalue32_CAR_MSB = (upmu_get_fg_car_35_32() & 0x0F) >> 3;
  220. pr_debug("[fgauge_read_columb_internal] FG_CAR = 0x%x\r\n", uvalue32_CAR);
  221. pr_debug("[fgauge_read_columb_internal] uvalue32_CAR_MSB = 0x%x\r\n", uvalue32_CAR_MSB);
  222. /* (5) (Read other data) */
  223. /* (6) Clear status to 0 */
  224. ret = pmic_config_interface(FGADC_CON0, 0x0800, 0xFF00, 0x0);
  225. /* (7) Keep i2c read when status = 0 (0x08) */
  226. /* while ( fg_get_sw_clear_status() != 0 ) */
  227. m = 0;
  228. while (fg_get_data_ready_status() != 0) {
  229. m++;
  230. if (m > 1000) {
  231. pr_warn
  232. ("[fgauge_read_columb_internal] fg_get_data_ready_status timeout 2 !\r\n");
  233. break;
  234. }
  235. }
  236. /* (8) Recover original settings */
  237. ret = pmic_config_interface(FGADC_CON0, 0x0000, 0xFF00, 0x0);
  238. /* calculate the real world data */
  239. dvalue_CAR = (s32) uvalue32_CAR;
  240. if (uvalue32_CAR == 0) {
  241. Temp_Value = 0;
  242. } else if (uvalue32_CAR == 65535) {
  243. /* 0xffff */
  244. Temp_Value = 0;
  245. } else if (uvalue32_CAR_MSB == 0x1) {
  246. /* dis-charging */
  247. Temp_Value = dvalue_CAR - 65535; /* keep negative value */
  248. } else {
  249. /* charging */
  250. Temp_Value = (int)dvalue_CAR;
  251. }
  252. Temp_Value = (((Temp_Value * 35986) / 10) + (5)) / 10; /* [28:14]'s LSB=359.86 uAh */
  253. dvalue_CAR = Temp_Value / 1000; /* mAh */
  254. pr_debug("[fgauge_read_columb_internal] dvalue_CAR = %d\r\n", dvalue_CAR);
  255. /* Auto adjust value */
  256. if (r_fg_value != 20) {
  257. pr_debug
  258. ("[fgauge_read_columb_internal] Auto adjust value deu to the Rfg is %d\n Ori CAR=%d, ",
  259. r_fg_value, dvalue_CAR);
  260. dvalue_CAR = (dvalue_CAR * 20) / r_fg_value;
  261. pr_debug("[fgauge_read_columb_internal] new CAR=%d\n", dvalue_CAR);
  262. }
  263. dvalue_CAR = ((dvalue_CAR * car_tune_value) / 100);
  264. dvalue_CAR = use_chip_trim_value(dvalue_CAR);
  265. pr_debug("[fgauge_read_columb_internal] final dvalue_CAR = %d\r\n", dvalue_CAR);
  266. *(s32 *) (data) = dvalue_CAR;
  267. return 0;
  268. }
  269. static s32 fgauge_read_columb(void *data)
  270. {
  271. return fgauge_read_columb_internal(data, 0);
  272. }
  273. static s32 fgauge_hw_reset(void *data)
  274. {
  275. u32 val_car = 1;
  276. u32 ret = 0;
  277. pr_debug("[fgauge_hw_reset] : Start \r\n");
  278. while (val_car != 0x0) {
  279. ret = pmic_config_interface(FGADC_CON0, 0x7100, 0xFF00, 0x0);
  280. fgauge_read_columb_internal(&val_car, 1);
  281. pr_debug("#");
  282. }
  283. pr_debug("[fgauge_hw_reset] : End \r\n");
  284. return 0;
  285. }
  286. static s32 read_adc_v_bat_sense(void *data)
  287. {
  288. #if defined(CONFIG_POWER_EXT)
  289. *(s32 *) (data) = 4201;
  290. #else
  291. *(s32 *) (data) =
  292. PMIC_IMM_GetOneChannelValue(bat_meter_data->vbat_channel_number, *(s32 *) (data), 1);
  293. #endif
  294. return 0;
  295. }
  296. static s32 read_adc_v_i_sense(void *data)
  297. {
  298. #if defined(CONFIG_POWER_EXT)
  299. *(s32 *) (data) = 4202;
  300. #else
  301. *(s32 *) (data) =
  302. PMIC_IMM_GetOneChannelValue(bat_meter_data->isense_channel_number, *(s32 *) (data), 1);
  303. #endif
  304. return 0;
  305. }
  306. static s32 read_adc_v_bat_temp(void *data)
  307. {
  308. #if defined(CONFIG_POWER_EXT)
  309. *(s32 *) (data) = 0;
  310. #else
  311. pr_debug("[read_adc_v_bat_temp] return PMIC_IMM_GetOneChannelValue(4,times,1);\n");
  312. *(s32 *) (data) =
  313. PMIC_IMM_GetOneChannelValue(bat_meter_data->vbattemp_channel_number, *(s32 *) (data),
  314. 1);
  315. #endif
  316. return 0;
  317. }
  318. static s32 read_adc_v_charger(void *data)
  319. {
  320. #if defined(CONFIG_POWER_EXT)
  321. *(s32 *) (data) = 5001;
  322. #else
  323. s32 val;
  324. val =
  325. PMIC_IMM_GetOneChannelValue(bat_meter_data->vcharger_channel_number, *(s32 *) (data),
  326. 1);
  327. val = val / 100;
  328. *(s32 *) (data) = val;
  329. #endif
  330. return 0;
  331. }
  332. static s32 read_hw_ocv(void *data)
  333. {
  334. #if defined(CONFIG_POWER_EXT)
  335. *(s32 *) (data) = 3999;
  336. #else
  337. *(s32 *) (data) = get_hw_ocv();
  338. #endif
  339. return 0;
  340. }
  341. static s32 dump_register_fgadc(void *data)
  342. {
  343. return 0;
  344. }
  345. static s32(*const bm_func[BATTERY_METER_CMD_NUMBER]) (void *data) = {
  346. fgauge_initialization,
  347. fgauge_read_current,
  348. fgauge_read_current_sign,
  349. fgauge_read_columb,
  350. fgauge_hw_reset,
  351. read_adc_v_bat_sense,
  352. read_adc_v_i_sense,
  353. read_adc_v_bat_temp, read_adc_v_charger, read_hw_ocv, dump_register_fgadc};
  354. s32 bm_ctrl_cmd(int cmd, void *data)
  355. {
  356. s32 status;
  357. if ((cmd < BATTERY_METER_CMD_NUMBER) && (bm_func[cmd] != NULL))
  358. status = bm_func[cmd] (data);
  359. else
  360. return -1;
  361. return status;
  362. }