MTK 充电知识

相关概念

懒的排版了,直接上图 
MTK 充电知识

相关文件关系

再来一发 
MTK 充电知识

杂项,电池温度检测原理图

发 
MTK 充电知识

充电流程

图样图森破 
MTK 充电知识

核心函数特写

MTK 充电知识


  1. /* 概念:

  2. ZCV:开路电压

  3. OCV: 开路电压

  4. VC:闭路电压

  5. CAR:库伦计

  6. DOD: 放电深度,100-DOD 即电容容量

  7. Cmax/Qmax: 电池容量

  8. 相关文件关系:

  9. Battery_common.c (s:\i841\mediatek\kernel\drivers\power) // 充电逻辑文件

  10. Charging_hw_pmic.c (s:\i841\mediatek\platform\mt6582\kernel\drivers\power) // 具体的充电芯片,相关电池参数检测

  11. Linear_charging.c (s:\i841\mediatek\kernel\drivers\power) // 充电状态控制,内部 PMIC

  12. Switch_charging.c (s:\i841\mediatek\kernel\drivers\power) // 充电状态控制,外部 Charge IC

  13. 硬件原理图:

  14. NTC 检测温度电路原理如下:

  15. Vu Ru:上拉电阻值

  16. --- Rd: 下拉电阻值

  17. | Rntc: NTC 温度电阻 阻值

  18. ||| Ru Vu: 上拉电压值

  19. | Gnd: 地

  20. ---------- -----Vntc Vntc: NTC 电压

  21. | |

  22. Rntc ||| ||| Rd

  23. | |

  24. ---------- Rntc = (Ru*Rd*Vntc) / (Vru * Rd - Vntc * Ru)

  25. |

  26. -----

  27. ---

  28. -

  29. Gnd

  30. 【充电初始化流程】:

  31. module_init(battery_init)

  32. battery_init(void)

  33. // 注册平台设备

  34. platform_device_register(&battery_device)

  35. // 注册平台驱动

  36. platform_driver_register(&battery_driver)

  37. // 二者匹配调用 probe 函数

  38. battery_probe()

  39. /

  40. // 注册字符设备

  41. alloc_chrdev_region(&adc_cali_devno, 0, 1, ADC_CALI_DEVNAME)

  42. cdev_add(adc_cali_cdev, adc_cali_devno, 1)

  43. /

  44. // 创建相关 sys 系统节点

  45. class_create(THIS_MODULE, ADC_CALI_DEVNAME)

  46. device_create(adc_cali_class, NULL, adc_cali_devno, NULL, ADC_CALI_DEVNAME)

  47. // 与特定硬件的入口操作函数关联

  48. get_charging_control()

  49. // 用来绑定内部 PMIC 或者外部充电芯片的操作函数入口

  50. battery_charging_control = chr_control_interface;

  51. 相关充电芯片驱动实现的函数有:

  52. charging_hw_init

  53. charging_dump_register

  54. charging_enable

  55. charging_set_cv_voltage

  56. charging_get_current

  57. charging_set_current

  58. charging_set_input_current

  59. charging_get_charging_status

  60. charging_reset_watch_dog_timer

  61. charging_set_hv_threshold

  62. charging_get_hv_status

  63. charging_get_battery_status

  64. charging_get_charger_det_status

  65. charging_get_charger_type

  66. charging_get_is_pcm_timer_trigger

  67. charging_set_platform_reset

  68. charging_get_platfrom_boot_mode

  69. charging_set_power_off

  70. //

  71. // 获得启动模式

  72. battery_charging_control(CHARGING_CMD_GET_PLATFORM_BOOT_MODE, &g_platform_boot_mode)

  73. // 对应 pmic 的 charging_get_platfrom_boot_mode()

  74. charging_get_platfrom_boot_mode()

  75. get_boot_mode()

  76. /

  77. // Integrate with Android Battery Service

  78. // 一般移动设备的供电可来自外部即 AC 与 usb,内部电池供电 battery,

  79. // 所以需通过 power_supply_register() 函数在 /sys/class/power_supply 下分别

  80. // 注册 ac usb battery,注册完成可发现在设备目录 /sys/class/power_supply 下分别

  81. // 出现 ac usb battery 三个文件夹

  82. power_supply_register(&(dev->dev), &ac_main.psy)

  83. power_supply_register(&(dev->dev), &usb_main.psy)

  84. power_supply_register(&(dev->dev), &wireless_main.psy)

  85. power_supply_register(&(dev->dev), &battery_main.psy)

  86. /

  87. // 初始化电池状态结构体

  88. BMT_status.bat_exist = KAL_TRUE; // phone must have battery

  89. BMT_status.charger_exist = KAL_FALSE; // for default, no charger

  90. BMT_status.bat_vol = 0;

  91. BMT_status.ICharging = 0;

  92. BMT_status.temperature = 0;

  93. BMT_status.charger_vol = 0;

  94. BMT_status.total_charging_time = 0;

  95. BMT_status.PRE_charging_time = 0;

  96. BMT_status.CC_charging_time = 0;

  97. BMT_status.TOPOFF_charging_time = 0;

  98. BMT_status.POSTFULL_charging_time = 0;

  99. BMT_status.SOC = 0;

  100. BMT_status.UI_SOC = 0;

  101. BMT_status.bat_charging_state = CHR_PRE;

  102. BMT_status.bat_in_recharging_state = KAL_FALSE;

  103. BMT_status.bat_full= KAL_FALSE;

  104. BMT_status.nPercent_ZCV = 0;

  105. BMT_status.nPrecent_UI_SOC_check_point= battery_meter_get_battery_nPercent_UI_SOC();

  106. ///

  107. //创建一个定时器,用于定时唤醒下面的内核线程更新电量

  108. battery_kthread_hrtimer_init();

  109. ktime = ktime_set(1, 0); // 3s, 10* 1000 ms

  110. // 高分辨率kernel定时器初始化

  111. hrtimer_init(&battery_kthread_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);

  112. battery_kthread_timer.function = battery_kthread_hrtimer_func;

  113. // 定时器处理函数

  114. battery_kthread_hrtimer_func()

  115. bat_thread_wakeup();

  116. // 唤醒下面的 bat_thread_kthread() 线程

  117. wake_up(&bat_thread_wq);

  118. // 重置定时器

  119. hrtimer_start(&battery_kthread_timer, ktime, HRTIMER_MODE_REL)

  120. //

  121. // 【核心充电线程】

  122. kthread_run(bat_thread_kthread, NULL, "bat_thread_kthread");

  123. // 设置定时器超时时间

  124. ktime_t ktime = ktime_set(3, 0); // 10s, 10* 1000 ms

  125. while (1) {

  126. // 这个是核心算法

  127. BAT_thread();

  128. ///

  129. // 0. 第一次执行时运行,获得开机显示电量,初始化电池算法 oam 参数

  130. // 开机时就会运行,只会运行一次,对电池算法 oam 方案进行初始化, 并获得开机显示电量百分比

  131. if(battery_meter_initilized == KAL_FALSE)

  132. {

  133. // 进行的一系列的电池参数与温度对应关系的表格的初始化,并根据电池当前电压,hw ocv 取一个较合适值,

  134. // 取合适值对应容量,再与 RTC 保存容量比较,选择一个合适量,为开机电池容量,最后初始化 oam 算法参数

  135. battery_meter_initial()

  136. }

  137. // 1. 判断是插入的是否充电器还是电脑 USB,看能不能进行充电

  138. // 如果连接的 USB 线为 USB 充电线,或者电脑 USB 线,则打开 USB,

  139. // 这里会通过 BC1.1 来判断是电脑 USB 还是 USB 充电器,来决定充电电流

  140. // 否则连接的不是充电线或者 USB 作为一个从设备使用,要断开 USB?

  141. mt_battery_charger_detect_check();

  142. ///

  143. // 2. 通过具体的充电芯片来获得电池信息,充电信息, 获得电池电量百分比

  144. // 通过 oam 算法,获得电量百分比

  145. mt_battery_GetBatteryData();

  146. // 3. 电池温度保护

  147. // 电池温度检查,如果温度超过 60 度,关机重启

  148. mt_battery_thermal_check();

  149. /

  150. // 4. 电池状态检查

  151. // 对电池状态进行检查,如果有问题,则会调用 printk() 进行打印

  152. mt_battery_notify_check();

  153. //

  154. // 5. 调用具本的硬件相关函数进行充电,充电时会进行 CC/CV 之类的状态机切换就是在这里进行的

  155. // 如果存在充电线,则调用具体充电芯片相关的函数进行充电

  156. if( BMT_status.charger_exist == KAL_TRUE )

  157. {

  158. // 检查电池状态,设置到 BMT_status.bat_charging_state 中

  159. mt_battery_CheckBatteryStatus();

  160. // 充电策略,这里有两个文件: switch_charging.c 和 linear_charging.c

  161. // 他们的关系是,如果定义了任一外部充电 IC,则选择 switch_charging.c 的函数,否则就是 linear_charging.c 的函数

  162. // 这里就是调用具体的芯片的充电相关函数进行充电

  163. mt_battery_charging_algorithm();

  164. void mt_battery_charging_algorithm()

  165. {

  166. switch(BMT_status.bat_charging_state)

  167. {

  168. case CHR_PRE :

  169. BAT_PreChargeModeAction();

  170. break;

  171. case CHR_CC :

  172. BAT_ConstantCurrentModeAction();

  173. /

  174. // MTK 充电是充 9s 停 1s

  175. // Charging 9s and discharging 1s : start

  176. battery_charging_control(CHARGING_CMD_ENABLE,&charging_enable);

  177. break;

  178. case CHR_TOP_OFF :

  179. BAT_TopOffModeAction();

  180. break;

  181. case CHR_BATFULL:

  182. BAT_BatteryFullAction();

  183. break;

  184. case CHR_HOLD:

  185. BAT_BatteryHoldAction();

  186. break;

  187. case CHR_ERROR:

  188. BAT_BatteryStatusFailAction();

  189. break;

  190. }

  191. }

  192. }

  193. ///

  194. // 6. 更新电池显示状态

  195. // 更新设置节点的内容:

  196. // /sys/class/power_supply/下的文件夹

  197. // wireless_main

  198. // battery_main

  199. // ac_main

  200. // usb_main

  201. mt_battery_update_status();

  202. // 睡眠等待唤醒

  203. wait_event(bat_thread_wq, (bat_thread_timeout == KAL_TRUE));

  204. // 每 10s 启动一次

  205. hrtimer_start(&battery_kthread_timer, ktime, HRTIMER_MODE_REL);

  206. ktime = ktime_set(BAT_TASK_PERIOD, 0); // 10s, 10* 1000 ms

  207. }

  208. /

  209. // 电池过充保护相关检测与初始化,他 2s 检测一次

  210. charger_hv_detect_sw_workaround_init();

  211. charger_hv_detect_thread = kthread_run(charger_hv_detect_sw_thread_handler, 0, "mtk charger_hv_detect_sw_workaround");

  212. // 这个函数是周期来检查电池电压是否超出限制,即过充保护,超出了就不能充电了

  213. charger_hv_detect_sw_thread_handler()

  214. do{

  215. ktime = ktime_set(0, BAT_MS_TO_NS(2000));

  216. if(chargin_hw_init_done)

  217. // 高压检测,应该是电池超过这个电压时,就不可以充电了

  218. battery_charging_control(CHARGING_CMD_SET_HV_THRESHOLD,&hv_voltage);

  219. // 对应 PMIC charging_set_hv_threshold()

  220. wait_event_interruptible(charger_hv_detect_waiter, (charger_hv_detect_flag == KAL_TRUE));

  221. // 如果检测到充电器,则检测下电池是否存在 检测电池是否存在,通过读取 PMIC 的 CHR_CON7

  222. if ((upmu_is_chr_det() == KAL_TRUE))

  223. {

  224. // 检测电池是否存在

  225. check_battery_exist();

  226. }

  227. hrtimer_start(&charger_hv_detect_timer, ktime, HRTIMER_MODE_REL);

  228. }while (!kthread_should_stop());

  229. //

  230. // battery notofy UI

  231. platform_device_register(&MT_batteryNotify_device)

  232. platform_driver_register(&mt_batteryNotify_driver)

  233. mt_batteryNotify_probe()

  234. ret_device_file = device_create_file(&(dev->dev), &dev_attr_BatteryNotify);

  235. ret_device_file = device_create_file(&(dev->dev), &dev_attr_BN_TestMode);

  236. battery_dir = proc_mkdir("mtk_battery_cmd", NULL);

  237. 电池测量模块初始化:

  238. module_init(battery_meter_init);

  239. battery_meter_init(void)

  240. platform_device_register(&battery_meter_device);

  241. platform_driver_register(&battery_meter_driver);

  242. // 调用对应的 probe 函数

  243. battery_meter_probe()

  244. // 测量模块接口设置【核心在于 bm_ctrl_cmd 函数】

  245. battery_meter_ctrl = bm_ctrl_cmd;

  246. */

  247. module_init(battery_init);

  248. static int __init battery_init(void)

  249. {

  250. int ret;

  251. ret = platform_device_register(&battery_device);

  252. struct platform_device battery_device = {

  253. .name = "battery",

  254. .id = -1,

  255. };

  256. if (ret) {

  257. battery_xlog_printk(BAT_LOG_CRTI, "****[battery_driver] Unable to device register(%d)\n", ret);

  258. return ret;

  259. }

  260. ret = platform_driver_register(&battery_driver);

  261. static struct platform_driver battery_driver = {

  262. .probe = battery_probe,

  263. .remove = battery_remove,

  264. .shutdown = battery_shutdown,

  265. .driver = {

  266. .name = "battery",

  267. .pm = &battery_pm_ops

  268. },

  269. };

  270. if (ret) {

  271. battery_xlog_printk(BAT_LOG_CRTI, "****[battery_driver] Unable to register driver (%d)\n", ret);

  272. return ret;

  273. }

  274. // battery notofy UI

  275. ret = platform_device_register(&MT_batteryNotify_device);

  276. struct platform_device MT_batteryNotify_device = {

  277. .name = "mt-battery",

  278. .id = -1,

  279. };

  280. if (ret) {

  281. battery_xlog_printk(BAT_LOG_CRTI, "****[mt_batteryNotify] Unable to device register(%d)\n", ret);

  282. return ret;

  283. }

  284. ret = platform_driver_register(&mt_batteryNotify_driver);

  285. static struct platform_driver mt_batteryNotify_driver = {

  286. .probe = mt_batteryNotify_probe,

  287. .driver = {

  288. .name = "mt-battery",

  289. },

  290. };

  291. if (ret) {

  292. battery_xlog_printk(BAT_LOG_CRTI, "****[mt_batteryNotify] Unable to register driver (%d)\n", ret);

  293. return ret;

  294. }

  295. battery_xlog_printk(BAT_LOG_CRTI, "****[battery_driver] Initialization : DONE !!\n");

  296. return 0;

  297. }

  298. //

  299. // 第一个调用的 probe,充电相关函数初始化

  300. /* 相关文件关系:

  301. Battery_common.c (s:\i841\mediatek\kernel\drivers\power) // 充电逻辑文件

  302. Charging_hw_pmic.c (s:\i841\mediatek\platform\mt6582\kernel\drivers\power) // 具体的充电芯片,相关电池参数检测

  303. Linear_charging.c (s:\i841\mediatek\kernel\drivers\power) // 充电状态控制,内部 PMIC

  304. Switch_charging.c (s:\i841\mediatek\kernel\drivers\power) // 充电状态控制,外部 Charge IC

  305. */

  306. static int battery_probe//(struct platform_device *dev)

  307. {

  308. struct class_device *class_dev = NULL;

  309. int ret=0;

  310. battery_xlog_printk(BAT_LOG_CRTI, "******** battery driver probe!! ********\n" );

  311. /* Integrate with NVRAM */

  312. ret = alloc_chrdev_region(&adc_cali_devno, 0, 1, ADC_CALI_DEVNAME); // #define ADC_CALI_DEVNAME "MT_pmic_adc_cali"

  313. if (ret)

  314. battery_xlog_printk(BAT_LOG_CRTI, "Error: Can't Get Major number for adc_cali \n");

  315. adc_cali_cdev = cdev_alloc();

  316. adc_cali_cdev->owner = THIS_MODULE;

  317. adc_cali_cdev->ops = &adc_cali_fops;

  318. static struct file_operations adc_cali_fops = {

  319. .owner = THIS_MODULE,

  320. .unlocked_ioctl = adc_cali_ioctl,

  321. .open = adc_cali_open,

  322. .release = adc_cali_release,

  323. };

  324. ret = cdev_add(adc_cali_cdev, adc_cali_devno, 1);

  325. if(ret)

  326. battery_xlog_printk(BAT_LOG_CRTI, "adc_cali Error: cdev_add\n");

  327. adc_cali_major = MAJOR(adc_cali_devno);

  328. adc_cali_class = class_create(THIS_MODULE, ADC_CALI_DEVNAME);

  329. class_dev = (struct class_device *)device_create(adc_cali_class,

  330. NULL,

  331. adc_cali_devno,

  332. NULL,

  333. ADC_CALI_DEVNAME);

  334. battery_xlog_printk(BAT_LOG_CRTI, "[BAT_probe] adc_cali prepare : done !!\n ");

  335. /* 与特定硬件的操作函数关联 */

  336. get_charging_control();

  337. static void get_charging_control(void)

  338. {

  339. /* 这是一个函数指针,指向了硬件驱动对应的接口函数,这里指向的是 pmic 为例,后面调用 battery_charging_control(xxx)

  340. 即是调用 chr_control_interface(xxx)

  341. typedef kal_int32 (*CHARGING_CONTROL)(CHARGING_CTRL_CMD cmd, void *data);*/

  342. battery_charging_control = chr_control_interface;

  343. // This function is called to set the charger hw

  344. kal_int32 chr_control_interface//(CHARGING_CTRL_CMD cmd, void *data)

  345. {

  346. kal_int32 status;

  347. if(cmd < CHARGING_CMD_NUMBER)

  348. status = charging_func[cmd](data);

  349. /* 这是在特定充电芯片中实现的,如 pmic 的 */

  350. // static kal_uint32 (*charging_func[CHARGING_CMD_NUMBER])(void *data)=

  351. // {

  352. // charging_hw_init

  353. // ,charging_dump_register

  354. // ,charging_enable

  355. // ,charging_set_cv_voltage

  356. // ,charging_get_current

  357. // ,charging_set_current

  358. // ,charging_set_input_current // not support, empty function

  359. // ,charging_get_charging_status // not support, empty function

  360. // ,charging_reset_watch_dog_timer

  361. // ,charging_set_hv_threshold

  362. // ,charging_get_hv_status

  363. // ,charging_get_battery_status

  364. // ,charging_get_charger_det_status

  365. // ,charging_get_charger_type

  366. // ,charging_get_is_pcm_timer_trigger

  367. // ,charging_set_platform_reset

  368. // ,charging_get_platfrom_boot_mode

  369. // ,charging_set_power_off

  370. // };

  371. else

  372. return STATUS_UNSUPPORTED;

  373. return status;

  374. }

  375. }

  376. /* 获得启动模式 */

  377. battery_charging_control(CHARGING_CMD_GET_PLATFORM_BOOT_MODE, &g_platform_boot_mode);

  378. // 对应 pmic 的 charging_get_platfrom_boot_mode()

  379. static kal_uint32 charging_get_platfrom_boot_mode(void *data)

  380. {

  381. kal_uint32 status = STATUS_OK;

  382. *(kal_uint32*)(data) = get_boot_mode();

  383. BOOTMODE get_boot_mode(void)

  384. {

  385. return g_boot_mode;

  386. }

  387. battery_xlog_printk(BAT_LOG_CRTI, "get_boot_mode=%d\n", get_boot_mode());

  388. return status;

  389. }

  390. battery_xlog_printk(BAT_LOG_CRTI, "[BAT_probe] g_platform_boot_mode = %d\n ", g_platform_boot_mode);

  391. wake_lock_init(&battery_suspend_lock, WAKE_LOCK_SUSPEND, "battery suspend wakelock");

  392. /* Integrate with Android Battery Service

  393. 一般移动设备的供电可来自外部即 AC 与 usb,内部电池供电 battery,所以需通过 power_supply_register 函数在

  394. /sys/class/power_supply 下分别注册 ac usb battery,注册完成可发现在设备目录 /sys/class/power_supply 下分别

  395. 出现 ac usb battery 三个文件夹 */

  396. ret = power_supply_register(&(dev->dev), &ac_main.psy);

  397. /* 相关的核心结构体

  398. struct power_supply {

  399. struct listnode list;

  400. char name[256];

  401. char type[32];

  402. bool online;

  403. bool valid;

  404. char cap_path[PATH_MAX];

  405. };*/

  406. if (ret)

  407. {

  408. battery_xlog_printk(BAT_LOG_CRTI, "[BAT_probe] power_supply_register AC Fail !!\n");

  409. return ret;

  410. }

  411. battery_xlog_printk(BAT_LOG_CRTI, "[BAT_probe] power_supply_register AC Success !!\n");

  412. ret = power_supply_register(&(dev->dev), &usb_main.psy);

  413. if (ret)

  414. {

  415. battery_xlog_printk(BAT_LOG_CRTI, "[BAT_probe] power_supply_register USB Fail !!\n");

  416. return ret;

  417. }

  418. battery_xlog_printk(BAT_LOG_CRTI, "[BAT_probe] power_supply_register USB Success !!\n");

  419. ret = power_supply_register(&(dev->dev), &wireless_main.psy);

  420. if (ret)

  421. {

  422. battery_xlog_printk(BAT_LOG_CRTI, "[BAT_probe] power_supply_register WIRELESS Fail !!\n");

  423. return ret;

  424. }

  425. battery_xlog_printk(BAT_LOG_CRTI, "[BAT_probe] power_supply_register WIRELESS Success !!\n");

  426. ret = power_supply_register(&(dev->dev), &battery_main.psy);

  427. if (ret)

  428. {

  429. battery_xlog_printk(BAT_LOG_CRTI, "[BAT_probe] power_supply_register Battery Fail !!\n");

  430. return ret;

  431. }

  432. battery_xlog_printk(BAT_LOG_CRTI, "[BAT_probe] power_supply_register Battery Success !!\n");

  433. #if !defined(CONFIG_POWER_EXT)

  434. /* For EM */

  435. {

  436. int ret_device_file=0;

  437. ret_device_file = device_create_file(&(dev->dev), &dev_attr_ADC_Charger_Voltage);

  438. ret_device_file = device_create_file(&(dev->dev), &dev_attr_ADC_Channel_0_Slope);

  439. ret_device_file = device_create_file(&(dev->dev), &dev_attr_ADC_Channel_1_Slope);

  440. ret_device_file = device_create_file(&(dev->dev), &dev_attr_ADC_Channel_2_Slope);

  441. ret_device_file = device_create_file(&(dev->dev), &dev_attr_ADC_Channel_3_Slope);

  442. ret_device_file = device_create_file(&(dev->dev), &dev_attr_ADC_Channel_4_Slope);

  443. ret_device_file = device_create_file(&(dev->dev), &dev_attr_ADC_Channel_5_Slope);

  444. ret_device_file = device_create_file(&(dev->dev), &dev_attr_ADC_Channel_6_Slope);

  445. ret_device_file = device_create_file(&(dev->dev), &dev_attr_ADC_Channel_7_Slope);

  446. ret_device_file = device_create_file(&(dev->dev), &dev_attr_ADC_Channel_8_Slope);

  447. ret_device_file = device_create_file(&(dev->dev), &dev_attr_ADC_Channel_9_Slope);

  448. ret_device_file = device_create_file(&(dev->dev), &dev_attr_ADC_Channel_10_Slope);

  449. ret_device_file = device_create_file(&(dev->dev), &dev_attr_ADC_Channel_11_Slope);

  450. ret_device_file = device_create_file(&(dev->dev), &dev_attr_ADC_Channel_12_Slope);

  451. ret_device_file = device_create_file(&(dev->dev), &dev_attr_ADC_Channel_13_Slope);

  452. ret_device_file = device_create_file(&(dev->dev), &dev_attr_ADC_Channel_0_Offset);

  453. ret_device_file = device_create_file(&(dev->dev), &dev_attr_ADC_Channel_1_Offset);

  454. ret_device_file = device_create_file(&(dev->dev), &dev_attr_ADC_Channel_2_Offset);

  455. ret_device_file = device_create_file(&(dev->dev), &dev_attr_ADC_Channel_3_Offset);

  456. ret_device_file = device_create_file(&(dev->dev), &dev_attr_ADC_Channel_4_Offset);

  457. ret_device_file = device_create_file(&(dev->dev), &dev_attr_ADC_Channel_5_Offset);

  458. ret_device_file = device_create_file(&(dev->dev), &dev_attr_ADC_Channel_6_Offset);

  459. ret_device_file = device_create_file(&(dev->dev), &dev_attr_ADC_Channel_7_Offset);

  460. ret_device_file = device_create_file(&(dev->dev), &dev_attr_ADC_Channel_8_Offset);

  461. ret_device_file = device_create_file(&(dev->dev), &dev_attr_ADC_Channel_9_Offset);

  462. ret_device_file = device_create_file(&(dev->dev), &dev_attr_ADC_Channel_10_Offset);

  463. ret_device_file = device_create_file(&(dev->dev), &dev_attr_ADC_Channel_11_Offset);

  464. ret_device_file = device_create_file(&(dev->dev), &dev_attr_ADC_Channel_12_Offset);

  465. ret_device_file = device_create_file(&(dev->dev), &dev_attr_ADC_Channel_13_Offset);

  466. ret_device_file = device_create_file(&(dev->dev), &dev_attr_ADC_Channel_Is_Calibration);

  467. ret_device_file = device_create_file(&(dev->dev), &dev_attr_Power_On_Voltage);

  468. ret_device_file = device_create_file(&(dev->dev), &dev_attr_Power_Off_Voltage);

  469. ret_device_file = device_create_file(&(dev->dev), &dev_attr_Charger_TopOff_Value);

  470. ret_device_file = device_create_file(&(dev->dev), &dev_attr_FG_Battery_CurrentConsumption);

  471. ret_device_file = device_create_file(&(dev->dev), &dev_attr_FG_SW_CoulombCounter);

  472. ret_device_file = device_create_file(&(dev->dev), &dev_attr_Charging_CallState);

  473. }

  474. //battery_meter_initial(); //move to mt_battery_GetBatteryData() to decrease booting time

  475. /* Initialization BMT Struct

  476. 初始化电池状态结构体 */

  477. BMT_status.bat_exist = KAL_TRUE; /* phone must have battery */

  478. BMT_status.charger_exist = KAL_FALSE; /* for default, no charger */

  479. BMT_status.bat_vol = 0;

  480. BMT_status.ICharging = 0;

  481. BMT_status.temperature = 0;

  482. BMT_status.charger_vol = 0;

  483. BMT_status.total_charging_time = 0;

  484. BMT_status.PRE_charging_time = 0;

  485. BMT_status.CC_charging_time = 0;

  486. BMT_status.TOPOFF_charging_time = 0;

  487. BMT_status.POSTFULL_charging_time = 0;

  488. BMT_status.SOC = 0;

  489. BMT_status.UI_SOC = 0;

  490. BMT_status.bat_charging_state = CHR_PRE;

  491. BMT_status.bat_in_recharging_state = KAL_FALSE;

  492. BMT_status.bat_full= KAL_FALSE;

  493. BMT_status.nPercent_ZCV = 0;

  494. BMT_status.nPrecent_UI_SOC_check_point= battery_meter_get_battery_nPercent_UI_SOC();

  495. //battery kernel thread for 10s check and charger in/out event

  496. /* Replace GPT timer by hrtime

  497. 创建一个定时器,用于定时唤醒下面的内核线程更新电量 */

  498. battery_kthread_hrtimer_init();

  499. void battery_kthread_hrtimer_init(void)

  500. {

  501. ktime_t ktime;

  502. ktime = ktime_set(1, 0); // 3s, 10* 1000 ms

  503. // 高分辨率kernel定时器初始化

  504. hrtimer_init(&battery_kthread_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);

  505. battery_kthread_timer.function = battery_kthread_hrtimer_func;

  506. enum hrtimer_restart battery_kthread_hrtimer_func(struct hrtimer *timer)

  507. {

  508. bat_thread_wakeup();

  509. void bat_thread_wakeup(void)

  510. {

  511. battery_xlog_printk(BAT_LOG_CRTI, "******** battery : bat_thread_wakeup ********\n" );

  512. bat_thread_timeout = KAL_TRUE;

  513. bat_meter_timeout = KAL_TRUE;

  514. // 唤醒下面的 bat_thread_kthread() 线程

  515. wake_up(&bat_thread_wq);

  516. }

  517. return HRTIMER_NORESTART;

  518. }

  519. // 重置定时器

  520. hrtimer_start(&battery_kthread_timer, ktime, HRTIMER_MODE_REL);

  521. battery_xlog_printk(BAT_LOG_CRTI, "battery_kthread_hrtimer_init : done\n" );

  522. }

  523. kthread_run(bat_thread_kthread, NULL, "bat_thread_kthread");

  524. ///

  525. Internal API

  526. int bat_thread_kthread(void *x)

  527. {

  528. // 设置定时器超时时间

  529. ktime_t ktime = ktime_set(3, 0); // 10s, 10* 1000 ms

  530. /* Run on a process content */

  531. while (1) {

  532. mutex_lock(&bat_mutex);

  533. if((chargin_hw_init_done == KAL_TRUE) && (battery_suspended == KAL_FALSE))

  534. /

  535. /

  536. /* 这个是核心算法 */

  537. BAT_thread();

  538. void BAT_thread(void)

  539. {

  540. static kal_bool battery_meter_initilized = KAL_FALSE;

  541. _g_bat_sleep_total_time = 0;

  542. // 0. 第一次执行时运行,获得开机显示电量,初始化电池算法 oam 参数

  543. /* 开机时就会运行,只会运行一次,对电池算法 oam 方案进行初始化, 并获得开机显示电量百分比 */

  544. if(battery_meter_initilized == KAL_FALSE)

  545. {

  546. /* 进行的一系列的电池参数与温度对应关系的表格的初始化,并根据电池当前电压,hw ocv 取一个较合适值,

  547. 取合适值对应容量,再与 rtc 容量比较,选择一个合适量,为开机电池容量,最后初始化 oam 算法参数 */

  548. battery_meter_initial(); //move from battery_probe() to decrease booting time

  549. kal_int32 battery_meter_initial(void)

  550. {

  551. #if defined(CONFIG_POWER_EXT)

  552. return 0;

  553. #else

  554. /* 多电池支持 */

  555. #ifdef MTK_MULTI_BAT_PROFILE_SUPPORT

  556. fgauge_get_profile_id();

  557. #endif

  558. /* 针对 AUXADC SW_FG HW_FG 三种不同的电池算法方案,分别初始化,82平台使用的 SW_FG */

  559. #if defined(SOC_BY_AUXADC)

  560. g_auxadc_solution = 1;

  561. table_init();

  562. bm_print(BM_LOG_CRTI, "[battery_meter_initial] SOC_BY_AUXADC done\n");

  563. #endif

  564. #if defined(SOC_BY_HW_FG)

  565. fgauge_initialization();

  566. fgauge_algo_run_init();

  567. bm_print(BM_LOG_CRTI, "[battery_meter_initial] SOC_BY_HW_FG done\n");

  568. #endif

  569. #if defined(SOC_BY_SW_FG)

  570. g_auxadc_solution = 1;

  571. /* 温度-电池容量,温度-电池内阻,温度-NTC阻值表格等初始化,并获得了当前电池温度及所用掉的容量值 */

  572. table_init();

  573. void table_init(void)

  574. {

  575. BATTERY_PROFILE_STRUC_P profile_p;

  576. R_PROFILE_STRUC_P profile_p_r_table;

  577. /* 获得当前电池温度*/

  578. int temperature = force_get_tbat();

  579. /* 通过获得当前 NTC 电压,查表并进行线性插值法,得到当前的温度值 */

  580. int force_get_tbat(void)

  581. {

  582. #if defined(CONFIG_POWER_EXT) || defined(FIXED_TBAT_25)

  583. bm_print(BM_LOG_CRTI, "[force_get_tbat] fixed TBAT=25 t\n");

  584. return 25;

  585. #else

  586. int bat_temperature_volt=0;

  587. int bat_temperature_val=0;

  588. int fg_r_value=0;

  589. kal_int32 fg_current_temp=0;

  590. kal_bool fg_current_state=KAL_FALSE;

  591. int bat_temperature_volt_temp=0;

  592. int ret=0;

  593. /* Get V_BAT_Temperature */

  594. bat_temperature_volt = 2;

  595. /* 对应 PMIC 的硬件接口函数,这个对应的函数是在下面 battery_meter_init 模块中设置的

  596. 获得电池 NTC 对应的电压 */

  597. ret = battery_meter_ctrl(BATTERY_METER_CMD_GET_ADC_V_BAT_TEMP, &bat_temperature_volt);

  598. static kal_int32 read_adc_v_bat_temp(void *data)

  599. {

  600. #if defined(CONFIG_POWER_EXT)

  601. *(kal_int32*)(data) = 0;

  602. #else

  603. #if defined(MTK_PCB_TBAT_FEATURE)

  604. int ret = 0, data[4], i, ret_value = 0, ret_temp = 0;

  605. int Channel=1;

  606. if( IMM_IsAdcInitReady() == 0 )

  607. {

  608. bm_print(BM_LOG_CRTI, "[get_tbat_volt] AUXADC is not ready");

  609. return 0;

  610. }

  611. i = times;

  612. while (i--)

  613. {

  614. ret_value = IMM_GetOneChannelValue(Channel, data, &ret_temp);

  615. ret += ret_temp;

  616. bm_print(BM_LOG_FULL, "[get_tbat_volt] ret_temp=%d\n",ret_temp);

  617. }

  618. ret = ret*1500/4096 ;

  619. ret = ret/times;

  620. bm_print(BM_LOG_CRTI, "[get_tbat_volt] Battery output mV = %d\n",ret);

  621. *(kal_int32*)(data) = ret;

  622. #else

  623. bm_print(BM_LOG_FULL, "[read_adc_v_charger] return PMIC_IMM_GetOneChannelValue(4,times,1);\n");

  624. /* 读 PMIC 对应的 ADC 的值,并将其转化为对应的电压值,这里即读取 BATON 引脚电压 */

  625. *(kal_int32*)(data) = PMIC_IMM_GetOneChannelValue(VBATTEMP_CHANNEL_NUMBER,*(kal_int32*)(data),1);

  626. //==============================================================================

  627. // PMIC-AUXADC

  628. //==============================================================================

  629. int PMIC_IMM_GetOneChannelValue(int dwChannel, int deCount, int trimd)

  630. {

  631. kal_int32 ret_data;

  632. kal_int32 count=0;

  633. kal_int32 u4Sample_times = 0;

  634. kal_int32 u4channel=0;

  635. kal_int32 adc_result_temp=0;

  636. kal_int32 r_val_temp=0;

  637. kal_int32 adc_result=0;

  638. kal_int32 ret=0;

  639. kal_int32 adc_reg_val=0;

  640. /*

  641. 0 : BATON2 **

  642. 1 : CH6

  643. 2 : THR SENSE2 **

  644. 3 : THR SENSE1

  645. 4 : VCDT

  646. 5 : BATON1 // 其实对应的就是硬件 PMIC ADC3

  647. 6 : ISENSE

  648. 7 : BATSNS

  649. 8 : ACCDET

  650. 9-16 : audio

  651. */

  652. //do not suppport BATON2 and THR SENSE2 for sw workaround

  653. if (dwChannel==0 || dwChannel==2)

  654. return 0;

  655. wake_lock(&pmicAuxadc_irq_lock);

  656. /* 采样通道号数,读取对应的 PMIC 寄存器的 ADC 的值 */

  657. do

  658. {

  659. mutex_lock(&pmic_adc_mutex);

  660. /* 硬件上,ADC 通过一个 mux 数据选择器对各路模拟信号进行切换,这里检查哪里通知有数据了 */

  661. PMIC_IMM_PollingAuxadcChannel();

  662. void PMIC_IMM_PollingAuxadcChannel(void)

  663. {

  664. kal_uint32 ret=0;

  665. //xlog_printk(ANDROID_LOG_INFO, "Power/PMIC", "[PMIC_IMM_PollingAuxadcChannel] before:%d ",upmu_get_rg_adc_deci_gdly());

  666. if (upmu_get_rg_adc_deci_gdly()==1)

  667. {

  668. while(upmu_get_rg_adc_deci_gdly()==1)

  669. {

  670. unsigned long flags;

  671. spin_lock_irqsave(&pmic_adc_lock, flags);

  672. if (pmic_is_auxadc_busy()==0)

  673. {

  674. //upmu_set_rg_adc_deci_gdly(0);

  675. ret=pmic_config_interface_nolock(AUXADC_CON19,0,PMIC_RG_ADC_DECI_GDLY_MASK,PMIC_RG_ADC_DECI_GDLY_SHIFT);

  676. }

  677. spin_unlock_irqrestore(&pmic_adc_lock, flags);

  678. }

  679. }

  680. //xlog_printk(ANDROID_LOG_INFO, "Power/PMIC", "[PMIC_IMM_PollingAuxadcChannel] after:%d ",upmu_get_rg_adc_deci_gdly());

  681. }

  682. /* adc */

  683. if (dwChannel<9)

  684. {

  685. upmu_set_rg_vbuf_en(1);

  686. //set 0

  687. ret=pmic_read_interface(AUXADC_CON22,&adc_reg_val,PMIC_RG_AP_RQST_LIST_MASK,PMIC_RG_AP_RQST_LIST_SHIFT);

  688. adc_reg_val = adc_reg_val & (~(1<<dwChannel));

  689. ret=pmic_config_interface(AUXADC_CON22,adc_reg_val,PMIC_RG_AP_RQST_LIST_MASK,PMIC_RG_AP_RQST_LIST_SHIFT);

  690. //set 1

  691. ret=pmic_read_interface(AUXADC_CON22,&adc_reg_val,PMIC_RG_AP_RQST_LIST_MASK,PMIC_RG_AP_RQST_LIST_SHIFT);

  692. adc_reg_val = adc_reg_val | (1<<dwChannel);

  693. ret=pmic_config_interface(AUXADC_CON22,adc_reg_val,PMIC_RG_AP_RQST_LIST_MASK,PMIC_RG_AP_RQST_LIST_SHIFT);

  694. }

  695. /* audio 相关 */

  696. else if(dwChannel>=9 && dwChannel<=16)

  697. {

  698. ret=pmic_read_interface(AUXADC_CON23,&adc_reg_val,PMIC_RG_AP_RQST_LIST_RSV_MASK,PMIC_RG_AP_RQST_LIST_RSV_SHIFT);

  699. adc_reg_val = adc_reg_val & (~(1<<(dwChannel-9)));

  700. ret=pmic_config_interface(AUXADC_CON23,adc_reg_val,PMIC_RG_AP_RQST_LIST_RSV_MASK,PMIC_RG_AP_RQST_LIST_RSV_SHIFT);

  701. //set 1

  702. ret=pmic_read_interface(AUXADC_CON23,&adc_reg_val,PMIC_RG_AP_RQST_LIST_RSV_MASK,PMIC_RG_AP_RQST_LIST_RSV_SHIFT);

  703. adc_reg_val = adc_reg_val | (1<<(dwChannel-9));

  704. ret=pmic_config_interface(AUXADC_CON23,adc_reg_val,PMIC_RG_AP_RQST_LIST_RSV_MASK,PMIC_RG_AP_RQST_LIST_RSV_SHIFT);

  705. }

  706. mutex_unlock(&pmic_adc_mutex);

  707. //Duo to HW limitation

  708. if(dwChannel!=8)

  709. msleep(1);

  710. count=0;

  711. ret_data=0;

  712. /* 根据不同通道选择,来读取对应的 PMIC 寄存器的值 */

  713. switch(dwChannel){

  714. case 0:

  715. while( upmu_get_rg_adc_rdy_baton2() != 1 )

  716. {

  717. msleep(1);

  718. if( (count++) > count_time_out)

  719. {

  720. xlog_printk(ANDROID_LOG_INFO, "Power/PMIC", "[IMM_GetOneChannelValue_PMIC] (%d) Time out!\n", dwChannel);

  721. break;

  722. }

  723. }

  724. ret_data = upmu_get_rg_adc_out_baton2();

  725. break;

  726. case 1:

  727. while( upmu_get_rg_adc_rdy_ch6() != 1 )

  728. {

  729. msleep(1);

  730. if( (count++) > count_time_out)

  731. {

  732. xlog_printk(ANDROID_LOG_INFO, "Power/PMIC", "[IMM_GetOneChannelValue_PMIC] (%d) Time out!\n", dwChannel);

  733. break;

  734. }

  735. }

  736. ret_data = upmu_get_rg_adc_out_ch6();

  737. xlog_printk(ANDROID_LOG_INFO, "Power/PMIC", "[upmu_get_rg_adc_out_ch6] 0x%x\n", ret_data);

  738. break;

  739. case 2:

  740. while( upmu_get_rg_adc_rdy_thr_sense2() != 1 )

  741. {

  742. msleep(1);

  743. if( (count++) > count_time_out)

  744. {

  745. xlog_printk(ANDROID_LOG_INFO, "Power/PMIC", "[IMM_GetOneChannelValue_PMIC] (%d) Time out!\n", dwChannel);

  746. break;

  747. }

  748. }

  749. ret_data = upmu_get_rg_adc_out_thr_sense2();

  750. break;

  751. case 3:

  752. while( upmu_get_rg_adc_rdy_thr_sense1() != 1 )

  753. {

  754. msleep(1);

  755. if( (count++) > count_time_out)

  756. {

  757. xlog_printk(ANDROID_LOG_INFO, "Power/PMIC", "[IMM_GetOneChannelValue_PMIC] (%d) Time out!\n", dwChannel);

  758. break;

  759. }

  760. }

  761. ret_data = upmu_get_rg_adc_out_thr_sense1();

  762. break;

  763. case 4:

  764. while( upmu_get_rg_adc_rdy_vcdt() != 1 )

  765. {

  766. msleep(1);

  767. if( (count++) > count_time_out)

  768. {

  769. xlog_printk(ANDROID_LOG_INFO, "Power/PMIC", "[IMM_GetOneChannelValue_PMIC] (%d) Time out!\n", dwChannel);

  770. break;

  771. }

  772. }

  773. ret_data = upmu_get_rg_adc_out_vcdt();

  774. break;

  775. /* 读取 PMIC 的 VBATON 引用的电压值*/

  776. case 5:

  777. while( upmu_get_rg_adc_rdy_baton1() != 1 )

  778. {

  779. msleep(1);

  780. if( (count++) > count_time_out)

  781. {

  782. xlog_printk(ANDROID_LOG_INFO, "Power/PMIC", "[IMM_GetOneChannelValue_PMIC] (%d) Time out!\n", dwChannel);

  783. break;

  784. }

  785. }

  786. ret_data = upmu_get_rg_adc_out_baton1();

  787. kal_uint32 upmu_get_rg_adc_rdy_baton1(void)

  788. {

  789. kal_uint32 ret=0;

  790. kal_uint32 val=0;

  791. pmic_lock();

  792. ret=pmic_read_interface( (kal_uint32)(AUXADC_ADC3),

  793. (&val),

  794. (kal_uint32)(PMIC_RG_ADC_RDY_BATON1_MASK),

  795. (kal_uint32)(PMIC_RG_ADC_RDY_BATON1_SHIFT)

  796. );

  797. pmic_unlock();

  798. return val;

  799. }

  800. break;

  801. case 6:

  802. while( upmu_get_rg_adc_rdy_isense() != 1 )

  803. {

  804. msleep(1);

  805. if( (count++) > count_time_out)

  806. {

  807. xlog_printk(ANDROID_LOG_INFO, "Power/PMIC", "[IMM_GetOneChannelValue_PMIC] (%d) Time out!\n", dwChannel);

  808. break;

  809. }

  810. }

  811. ret_data = upmu_get_rg_adc_out_isense();

  812. break;

  813. case 7:

  814. while( upmu_get_rg_adc_rdy_batsns() != 1 )

  815. {

  816. msleep(1);

  817. if( (count++) > count_time_out)

  818. {

  819. xlog_printk(ANDROID_LOG_INFO, "Power/PMIC", "[IMM_GetOneChannelValue_PMIC] (%d) Time out!\n", dwChannel);

  820. break;

  821. }

  822. }

  823. ret_data = upmu_get_rg_adc_out_batsns();

  824. break;

  825. case 8:

  826. while( upmu_get_rg_adc_rdy_ch5() != 1 );

  827. ret_data = upmu_get_rg_adc_out_ch5();

  828. break;

  829. case 9:

  830. case 10:

  831. case 11:

  832. case 12:

  833. case 13:

  834. case 14:

  835. case 15:

  836. case 16:

  837. while( upmu_get_rg_adc_rdy_int() != 1 )

  838. {

  839. msleep(1);

  840. if( (count++) > count_time_out)

  841. {

  842. xlog_printk(ANDROID_LOG_INFO, "Power/PMIC", "[IMM_GetOneChannelValue_PMIC] (%d) Time out!\n", dwChannel);

  843. break;

  844. }

  845. }

  846. ret_data = upmu_get_rg_adc_out_int();

  847. break;

  848. default:

  849. xlog_printk(ANDROID_LOG_INFO, "Power/PMIC", "[AUXADC] Invalid channel value(%d,%d)\n", dwChannel, trimd);

  850. wake_unlock(&pmicAuxadc_irq_lock);

  851. return -1;

  852. break;

  853. }

  854. u4channel += ret_data;

  855. u4Sample_times++;

  856. if (Enable_BATDRV_LOG == 2)

  857. {

  858. //debug

  859. xlog_printk(ANDROID_LOG_INFO, "Power/PMIC", "[AUXADC] u4channel[%d]=%d.\n",

  860. dwChannel, ret_data);

  861. }

  862. }while (u4Sample_times < deCount);

  863. /* Value averaging

  864. adc 采样值取平均值 */

  865. adc_result_temp = u4channel / deCount;

  866. /* ADC 分辨率: 即 ADC 数据每加 1 所对应的电压变化,计算公式为 【测量电压范围/(2^AD位数-1)】*/

  867. switch(dwChannel){

  868. case 0:

  869. r_val_temp = 1;

  870. adc_result = (adc_result_temp*r_val_temp*VOLTAGE_FULL_RANGE)/ADC_PRECISE;

  871. break;

  872. case 1:

  873. r_val_temp = 1;

  874. adc_result = (adc_result_temp*r_val_temp*VOLTAGE_FULL_RANGE)/ADC_PRECISE;

  875. break;

  876. case 2:

  877. r_val_temp = 1;

  878. adc_result = (adc_result_temp*r_val_temp*VOLTAGE_FULL_RANGE)/ADC_PRECISE;

  879. break;

  880. case 3:

  881. r_val_temp = 1;

  882. adc_result = (adc_result_temp*r_val_temp*VOLTAGE_FULL_RANGE)/ADC_PRECISE;

  883. break;

  884. case 4:

  885. r_val_temp = 1;

  886. adc_result = (adc_result_temp*r_val_temp*VOLTAGE_FULL_RANGE)/ADC_PRECISE;

  887. break;

  888. /* ADC 分辨率: 即 ADC 数据每加 1 所对应的电压变化,计算公式为

  889. 0-正数表示: 【测量电压范围/(2^AD位数)】

  890. 负数-正数表示: 【测量电压范围/(2^AD位数-1)】

  891. 获得 BATON 电压值

  892. #define VOLTAGE_FULL_RANGE 1800 // 测量的电压范围

  893. #define ADC_PRECISE 32768 // 15 bits 2^15 = 32768

  894. */

  895. case 5:

  896. r_val_temp = 1;

  897. /* 这里得到将数字化数值转换为对应的模拟电压值 */

  898. adc_result = (adc_result_temp*r_val_temp*VOLTAGE_FULL_RANGE)/ADC_PRECISE;

  899. break;

  900. case 6:

  901. r_val_temp = 4; // 电阻分压比,因为测量 adc 量程不够,要采用电阻分压

  902. adc_result = (adc_result_temp*r_val_temp*VOLTAGE_FULL_RANGE)/ADC_PRECISE;

  903. break;

  904. case 7:

  905. r_val_temp = 4; // 电阻分压比,因为测量 adc 量程不够,要采用电阻分压

  906. adc_result = (adc_result_temp*r_val_temp*VOLTAGE_FULL_RANGE)/ADC_PRECISE;

  907. break;

  908. case 8:

  909. r_val_temp = 1;

  910. adc_result = (adc_result_temp*r_val_temp*VOLTAGE_FULL_RANGE)/ADC_PRECISE;

  911. break;

  912. case 9:

  913. case 10:

  914. case 11:

  915. case 12:

  916. case 13:

  917. case 14:

  918. case 15:

  919. case 16:

  920. adc_result = adc_result_temp;

  921. break;

  922. default:

  923. xlog_printk(ANDROID_LOG_INFO, "Power/PMIC", "[AUXADC] Invalid channel value(%d,%d)\n", dwChannel, trimd);

  924. wake_unlock(&pmicAuxadc_irq_lock);

  925. return -1;

  926. break;

  927. }

  928. if (Enable_BATDRV_LOG == 2)

  929. {

  930. //debug

  931. xlog_printk(ANDROID_LOG_INFO, "Power/PMIC", "[AUXADC] adc_result_temp=%d, adc_result=%d, r_val_temp=%d.\n",

  932. adc_result_temp, adc_result, r_val_temp);

  933. }

  934. wake_unlock(&pmicAuxadc_irq_lock);

  935. return adc_result;

  936. }

  937. #endif

  938. #endif

  939. return STATUS_OK;

  940. }

  941. /* 如果获得的 PMIC 的 BATON 引脚电压值不为 0 */

  942. if(bat_temperature_volt != 0)

  943. {

  944. #if defined(SOC_BY_HW_FG)

  945. /* 获得配置的放电电阻值的大小 */

  946. fg_r_value = get_r_fg_value();

  947. int get_r_fg_value(void)

  948. {

  949. return (R_FG_VALUE+CUST_R_FG_OFFSET);

  950. }

  951. ret = battery_meter_ctrl(BATTERY_METER_CMD_GET_HW_FG_CURRENT, &fg_current_temp);

  952. static kal_int32 fgauge_read_current(void *data)

  953. {

  954. return STATUS_OK;

  955. }

  956. ret = battery_meter_ctrl(BATTERY_METER_CMD_GET_HW_FG_CURRENT_SIGN, &fg_current_state);

  957. static kal_int32 fgauge_read_current_sign(void *data)

  958. {

  959. return STATUS_OK;

  960. }

  961. fg_current_temp = fg_current_temp/10;

  962. if(fg_current_state==KAL_TRUE)

  963. {

  964. bat_temperature_volt_temp = bat_temperature_volt;

  965. bat_temperature_volt = bat_temperature_volt - ((fg_current_temp*fg_r_value)/1000);

  966. }

  967. else

  968. {

  969. bat_temperature_volt_temp = bat_temperature_volt;

  970. // 这里对 NTC 电压进行补偿: NTC 实际温度对应电压 = 测量电压 + 负载电压*负载电阻 // 【这里的 1000 是将小数整数化】

  971. bat_temperature_volt = bat_temperature_volt + ((fg_current_temp*fg_r_value)/1000);

  972. }

  973. #endif

  974. ///

  975. /* 将 NTC 的电压通过查表获得对应温度值 */

  976. bat_temperature_val = BattVoltToTemp(bat_temperature_volt);

  977. int BattVoltToTemp(int dwVolt)

  978. {

  979. kal_int64 TRes_temp;

  980. kal_int64 TRes;

  981. int sBaTTMP = -100;

  982. // TRes_temp = ((kal_int64)RBAT_PULL_UP_R*(kal_int64)dwVolt) / (RBAT_PULL_UP_VOLT-dwVolt);

  983. //TRes = (TRes_temp * (kal_int64)RBAT_PULL_DOWN_R)/((kal_int64)RBAT_PULL_DOWN_R - TRes_temp);

  984. /* 电路原理如下:

  985. Vu Ru:上拉电阻值

  986. --- Rd: 下拉电阻值

  987. | Rntc: NTC 温度电阻 阻值

  988. ||| Ru Vu: 上拉电压值

  989. | Gnd: 地

  990. ---------- -----Vntc Vntc: NTC 电压

  991. | |

  992. Rntc ||| ||| Rd

  993. | |

  994. ---------- Rntc = (Ru*Rd*Vntc) / (Vru * Rd - Vntc * Ru)

  995. |

  996. -----

  997. ---

  998. -

  999. Gnd

  1000. */

  1001. /* TRes_temp = 上拉电阻值 * NTC电压 */

  1002. TRes_temp = (RBAT_PULL_UP_R*(kal_int64)dwVolt);

  1003. /* 上拉电阻分压 = 上拉电压 - NTC分压 = RBAT_PULL_UP_VOLT-dwVolt

  1004. do_div(): 做除法

  1005. (上拉电阻值 * NTC电压)/上拉电阻分压 = (上拉电阻值/上拉电压分压)*NTC电压 */

  1006. do_div(TRes_temp, (RBAT_PULL_UP_VOLT-dwVolt));

  1007. /* (上拉电阻值/上拉电压分压)*NTC电压*下拉电阻值 */

  1008. TRes = (TRes_temp * RBAT_PULL_DOWN_R);

  1009. /* (上拉电阻值/上拉电压分压)*NTC电压*下拉电阻值 / (下拉电阻值 - (上拉电阻值/上拉电压分压)*NTC电压)*/

  1010. do_div(TRes, abs(RBAT_PULL_DOWN_R - TRes_temp));

  1011. /* convert register to temperature

  1012. 将得到的 NTC 阻值通过表格换算成温度 */

  1013. sBaTTMP = BattThermistorConverTemp((int)TRes);

  1014. int BattThermistorConverTemp//(int Res)

  1015. {

  1016. int i=0;

  1017. int RES1=0,RES2=0;

  1018. int TBatt_Value=-200,TMP1=0,TMP2=0;

  1019. /* 如果大于最低温度阻值,返回 -20 */

  1020. if(Res>=Batt_Temperature_Table[0].TemperatureR) /* Cust_battery_meter_table.h (s:\i841\mediatek\custom\mt6582\kernel\battery\battery) */

  1021. {

  1022. TBatt_Value = -20;

  1023. }

  1024. /* 如果大于最高温度阻值,返回 60 */

  1025. else if(Res<=Batt_Temperature_Table[16].TemperatureR)

  1026. {

  1027. TBatt_Value = 60;

  1028. }

  1029. /* 其他温度 */

  1030. else

  1031. {

  1032. RES1=Batt_Temperature_Table[0].TemperatureR;

  1033. TMP1=Batt_Temperature_Table[0].BatteryTemp;

  1034. /* 遍历 NTC 阻值与温度对应表,获得当前阻值所对应的表项 */

  1035. for(i=0;i<=16;i++)

  1036. {

  1037. if(Res>=Batt_Temperature_Table[i].TemperatureR)

  1038. {

  1039. RES2=Batt_Temperature_Table[i].TemperatureR;

  1040. TMP2=Batt_Temperature_Table[i].BatteryTemp;

  1041. break;

  1042. }

  1043. else

  1044. {

  1045. RES1=Batt_Temperature_Table[i].TemperatureR;

  1046. TMP1=Batt_Temperature_Table[i].BatteryTemp;

  1047. }

  1048. }

  1049. /* Liner Interpolation Method: 线性插值法,方法详见 Battery_Charging Introduction for Customer.pdf

  1050. 核心就是一条直接函数,已知两个点的 (X0,Y0) (X1,Y1),并知道第三个点的 X,就对应的 Y

  1051. 计算公式为:

  1052. Y = [(X-X0)*Y1 + (X1-X)*Y0] / (X1-X0)

  1053. */

  1054. TBatt_Value = (((Res-RES2)*TMP1)+((RES1-Res)*TMP2))/(RES1-RES2);

  1055. }

  1056. return TBatt_Value;

  1057. }

  1058. return sBaTTMP;

  1059. }

  1060. }

  1061. bm_print(BM_LOG_CRTI, "[force_get_tbat] %d,%d,%d,%d,%d,%d\n",

  1062. bat_temperature_volt_temp, bat_temperature_volt, fg_current_state, fg_current_temp, fg_r_value, bat_temperature_val);

  1063. return bat_temperature_val;

  1064. #endif

  1065. }

  1066. // Re-constructure r-table profile according to current temperature

  1067. /* 获得温度-电池内阻表 */

  1068. profile_p_r_table = fgauge_get_profile_r_table(TEMPERATURE_T);

  1069. R_PROFILE_STRUC_P fgauge_get_profile_r_table(kal_uint32 temperature)

  1070. {

  1071. switch (temperature)

  1072. {

  1073. case TEMPERATURE_T0:

  1074. return &r_profile_t0[0];

  1075. break;

  1076. case TEMPERATURE_T1:

  1077. return &r_profile_t1[0];

  1078. break;

  1079. case TEMPERATURE_T2:

  1080. return &r_profile_t2[0];

  1081. break;

  1082. case TEMPERATURE_T3:

  1083. return &r_profile_t3[0];

  1084. break;

  1085. case TEMPERATURE_T:

  1086. return &r_profile_temperature[0];

  1087. break;

  1088. default:

  1089. return NULL;

  1090. break;

  1091. }

  1092. }

  1093. if (profile_p_r_table == NULL)

  1094. {

  1095. bm_print(BM_LOG_CRTI, "[FGADC] fgauge_get_profile_r_table : create table fail !\r\n");

  1096. }

  1097. /* 获得当前温度使用的 温度-电池内阻 表格*/

  1098. fgauge_construct_r_table_profile(temperature, profile_p_r_table);

  1099. void fgauge_construct_r_table_profile(kal_int32 temperature, R_PROFILE_STRUC_P temp_profile_p)

  1100. {

  1101. R_PROFILE_STRUC_P low_profile_p, high_profile_p;

  1102. kal_int32 low_temperature, high_temperature;

  1103. int i, saddles;

  1104. kal_int32 temp_v_1 = 0, temp_v_2 = 0;

  1105. kal_int32 temp_r_1 = 0, temp_r_2 = 0;

  1106. /* 这里跟 NTC 类似,获得在 温度上下限时的电池内阻表 */

  1107. if (temperature <= TEMPERATURE_T1)

  1108. {

  1109. low_profile_p = fgauge_get_profile_r_table(TEMPERATURE_T0);

  1110. high_profile_p = fgauge_get_profile_r_table(TEMPERATURE_T1);

  1111. low_temperature = (-10);

  1112. high_temperature = TEMPERATURE_T1;

  1113. if(temperature < low_temperature)

  1114. {

  1115. temperature = low_temperature;

  1116. }

  1117. }

  1118. else if (temperature <= TEMPERATURE_T2)

  1119. {

  1120. low_profile_p = fgauge_get_profile_r_table(TEMPERATURE_T1);

  1121. high_profile_p = fgauge_get_profile_r_table(TEMPERATURE_T2);

  1122. low_temperature = TEMPERATURE_T1;

  1123. high_temperature = TEMPERATURE_T2;

  1124. if(temperature < low_temperature)

  1125. {

  1126. temperature = low_temperature;

  1127. }

  1128. }

  1129. else

  1130. {

  1131. low_profile_p = fgauge_get_profile_r_table(TEMPERATURE_T2); // 温度下限温度-电池内阻表

  1132. high_profile_p = fgauge_get_profile_r_table(TEMPERATURE_T3); // 温度上限温度-电池内阻表

  1133. low_temperature = TEMPERATURE_T2; // 温度下限

  1134. high_temperature = TEMPERATURE_T3; // 温度上限

  1135. /* 防溢出温度区间 */

  1136. if(temperature > high_temperature)

  1137. {

  1138. temperature = high_temperature;

  1139. }

  1140. }

  1141. /* 获得 温度-电池内阻表 的表格项数 */

  1142. saddles = fgauge_get_saddles_r_table();

  1143. int fgauge_get_saddles_r_table(void)

  1144. {

  1145. return sizeof(r_profile_t2) / sizeof(R_PROFILE_STRUC);

  1146. }

  1147. /* Interpolation for V_BAT

  1148. 插值得到当前温度对应的电池电压 V_BAT */

  1149. for (i = 0; i < saddles; i++)

  1150. {

  1151. /* 如果表格中温度上限电压 > 温度下限时电压 */

  1152. if( ((high_profile_p + i)->voltage) > ((low_profile_p + i)->voltage) )

  1153. {

  1154. /* 温度上限时电压 */

  1155. temp_v_1 = (high_profile_p + i)->voltage;

  1156. /* 温度下限时电压 */

  1157. temp_v_2 = (low_profile_p + i)->voltage;

  1158. /* 插值得到此时温度对应的电压值 */

  1159. (temp_profile_p + i)->voltage = temp_v_2 +

  1160. (

  1161. (

  1162. (temperature - low_temperature) *

  1163. (temp_v_1 - temp_v_2)

  1164. ) /

  1165. (high_temperature - low_temperature)

  1166. );

  1167. }

  1168. /* 如果表格中温度上限电压 <= 温度下限时电压 */

  1169. else

  1170. {

  1171. temp_v_1 = (low_profile_p + i)->voltage;

  1172. temp_v_2 = (high_profile_p + i)->voltage;

  1173. (temp_profile_p + i)->voltage = temp_v_2 +

  1174. (

  1175. (

  1176. (high_temperature - temperature) *

  1177. (temp_v_1 - temp_v_2)

  1178. ) /

  1179. (high_temperature - low_temperature)

  1180. );

  1181. }

  1182. #if 0

  1183. //(temp_profile_p + i)->resistance = (high_profile_p + i)->resistance;

  1184. (temp_profile_p + i)->voltage = temp_v_2 +

  1185. (

  1186. (

  1187. (temperature - low_temperature) *

  1188. (temp_v_1 - temp_v_2)

  1189. ) /

  1190. (high_temperature - low_temperature)

  1191. );

  1192. #endif

  1193. }

  1194. /* Interpolation for R_BAT

  1195. 插值得到当前温度对应的电池内阻 R_BAT */

  1196. for (i = 0; i < saddles; i++)

  1197. {

  1198. if( ((high_profile_p + i)->resistance) > ((low_profile_p + i)->resistance) )

  1199. {

  1200. /* 温度上限时电池内阻 */

  1201. temp_r_1 = (high_profile_p + i)->resistance;

  1202. /* 温度下限时电池内阻 */

  1203. temp_r_2 = (low_profile_p + i)->resistance;

  1204. /* 插值得到此时温度对应的电池内阻值 */

  1205. (temp_profile_p + i)->resistance = temp_r_2 +

  1206. (

  1207. (

  1208. (temperature - low_temperature) *

  1209. (temp_r_1 - temp_r_2)

  1210. ) /

  1211. (high_temperature - low_temperature)

  1212. );

  1213. }

  1214. else

  1215. {

  1216. temp_r_1 = (low_profile_p + i)->resistance;

  1217. temp_r_2 = (high_profile_p + i)->resistance;

  1218. (temp_profile_p + i)->resistance = temp_r_2 +

  1219. (

  1220. (

  1221. (high_temperature - temperature) *

  1222. (temp_r_1 - temp_r_2)

  1223. ) /

  1224. (high_temperature - low_temperature)

  1225. );

  1226. }

  1227. #if 0

  1228. //(temp_profile_p + i)->voltage = (high_profile_p + i)->voltage;

  1229. (temp_profile_p + i)->resistance = temp_r_2 +

  1230. (

  1231. (

  1232. (temperature - low_temperature) *

  1233. (temp_r_1 - temp_r_2)

  1234. ) /

  1235. (high_temperature - low_temperature)

  1236. );

  1237. #endif

  1238. }

  1239. // Dumpt new r-table profile

  1240. for (i = 0; i < saddles ; i++)

  1241. {

  1242. bm_print(BM_LOG_CRTI, "<Rbat,VBAT> at %d = <%d,%d>\r\n",

  1243. temperature, (temp_profile_p+i)->resistance, (temp_profile_p+i)->voltage);

  1244. }

  1245. }

  1246. // Re-constructure battery profile according to current temperature

  1247. /* 获得当前温度对应的 温度-电池容量表格 */

  1248. profile_p = fgauge_get_profile(TEMPERATURE_T);

  1249. BATTERY_PROFILE_STRUC_P fgauge_get_profile(kal_uint32 temperature)

  1250. {

  1251. switch (temperature)

  1252. {

  1253. case TEMPERATURE_T0:

  1254. return &battery_profile_t0[0];

  1255. break;

  1256. case TEMPERATURE_T1:

  1257. return &battery_profile_t1[0];

  1258. break;

  1259. case TEMPERATURE_T2:

  1260. return &battery_profile_t2[0];

  1261. break;

  1262. case TEMPERATURE_T3:

  1263. return &battery_profile_t3[0];

  1264. break;

  1265. case TEMPERATURE_T:

  1266. return &battery_profile_temperature[0];

  1267. break;

  1268. default:

  1269. return NULL;

  1270. break;

  1271. }

  1272. }

  1273. if (profile_p == NULL)

  1274. {

  1275. bm_print(BM_LOG_CRTI, "[FGADC] fgauge_get_profile : create table fail !\r\n");

  1276. }

  1277. /* 由当前温度,通过 温度-电池容量表格,获得对应的 温度-电池容量 数据,

  1278. 即能得到当前温度所对应的用掉的电池容量 */

  1279. fgauge_construct_battery_profile(temperature, profile_p);

  1280. void fgauge_construct_battery_profile(kal_int32 temperature, BATTERY_PROFILE_STRUC_P temp_profile_p)

  1281. {

  1282. BATTERY_PROFILE_STRUC_P low_profile_p, high_profile_p;

  1283. kal_int32 low_temperature, high_temperature;

  1284. int i, saddles;

  1285. kal_int32 temp_v_1 = 0, temp_v_2 = 0;

  1286. /* 获得对就温度所在温度上限/下限所对应的 温度-电池容量表格 */

  1287. if (temperature <= TEMPERATURE_T1)

  1288. {

  1289. low_profile_p = fgauge_get_profile(TEMPERATURE_T0);

  1290. high_profile_p = fgauge_get_profile(TEMPERATURE_T1);

  1291. low_temperature = (-10);

  1292. high_temperature = TEMPERATURE_T1;

  1293. if(temperature < low_temperature)

  1294. {

  1295. temperature = low_temperature;

  1296. }

  1297. }

  1298. else if (temperature <= TEMPERATURE_T2)

  1299. {

  1300. low_profile_p = fgauge_get_profile(TEMPERATURE_T1);

  1301. high_profile_p = fgauge_get_profile(TEMPERATURE_T2);

  1302. low_temperature = TEMPERATURE_T1;

  1303. high_temperature = TEMPERATURE_T2;

  1304. if(temperature < low_temperature)

  1305. {

  1306. temperature = low_temperature;

  1307. }

  1308. }

  1309. else

  1310. {

  1311. low_profile_p = fgauge_get_profile(TEMPERATURE_T2); // 温度下限所对应的 温度-电池容量表格

  1312. high_profile_p = fgauge_get_profile(TEMPERATURE_T3); // 温度上限所对应的 温度-电池容量表格

  1313. low_temperature = TEMPERATURE_T2; // 温度下限

  1314. high_temperature = TEMPERATURE_T3; // 温度上限

  1315. if(temperature > high_temperature)

  1316. {

  1317. temperature = high_temperature;

  1318. }

  1319. }

  1320. /* 获得 温度-电池容量 表格项数 */

  1321. saddles = fgauge_get_saddles();

  1322. /* 遍历表格,插值获得当前温度对应的容量 */

  1323. for (i = 0; i < saddles; i++)

  1324. {

  1325. if( ((high_profile_p + i)->voltage) > ((low_profile_p + i)->voltage) )

  1326. {

  1327. temp_v_1 = (high_profile_p + i)->voltage;

  1328. temp_v_2 = (low_profile_p + i)->voltage;

  1329. (temp_profile_p + i)->voltage = temp_v_2 +

  1330. (

  1331. (

  1332. (temperature - low_temperature) *

  1333. (temp_v_1 - temp_v_2)

  1334. ) /

  1335. (high_temperature - low_temperature)

  1336. );

  1337. }

  1338. else

  1339. {

  1340. temp_v_1 = (low_profile_p + i)->voltage;

  1341. temp_v_2 = (high_profile_p + i)->voltage;

  1342. (temp_profile_p + i)->voltage = temp_v_2 +

  1343. (

  1344. (

  1345. (high_temperature - temperature) *

  1346. (temp_v_1 - temp_v_2)

  1347. ) /

  1348. (high_temperature - low_temperature)

  1349. );

  1350. }

  1351. (temp_profile_p + i)->percentage = (high_profile_p + i)->percentage;

  1352. #if 0

  1353. (temp_profile_p + i)->voltage = temp_v_2 +

  1354. (

  1355. (

  1356. (temperature - low_temperature) *

  1357. (temp_v_1 - temp_v_2)

  1358. ) /

  1359. (high_temperature - low_temperature)

  1360. );

  1361. #endif

  1362. }

  1363. // Dumpt new battery profile

  1364. for (i = 0; i < saddles ; i++)

  1365. {

  1366. bm_print(BM_LOG_CRTI, "<DOD,Voltage> at %d = <%d,%d>\r\n",

  1367. temperature, (temp_profile_p+i)->percentage, (temp_profile_p+i)->voltage);

  1368. }

  1369. }

  1370. }

  1371. /* 首先获得电池电压,然后获得 hw ocv 电压,两者差值较小时,即 hw ocv 为准,

  1372. 然后以此计算出开机电池容量值,并且与 rtc 中记录的电量值进行比较,如果误差较小(小于 40%)

  1373. 则以 rtc 容量值为准,最后初始化 oam 算法的相关参数 */

  1374. oam_init();

  1375. void oam_init(void)

  1376. {

  1377. int ret=0;

  1378. int vol_bat=0;

  1379. kal_int32 vbat_capacity = 0;

  1380. vol_bat = 5; //set avg times

  1381. /* 读 PMIC 引用 BATSNS 的电压,即电池电压 */

  1382. ret = battery_meter_ctrl(BATTERY_METER_CMD_GET_ADC_V_BAT_SENSE, &vol_bat); // battery_meter_ctrl() 被初化为 bm_ctrl_cmd()

  1383. static kal_int32 read_adc_v_bat_sense(void *data)

  1384. {

  1385. #if defined(CONFIG_POWER_EXT)

  1386. *(kal_int32*)(data) = 4201;

  1387. #else

  1388. /* 读 PMIC 对应的 ADC 的值,并将其转化为对应的电压值,这里即读取 BATSNS 引脚电压 */

  1389. *(kal_int32*)(data) = PMIC_IMM_GetOneChannelValue(VBAT_CHANNEL_NUMBER,*(kal_int32*)(data),1);

  1390. #endif

  1391. return STATUS_OK;

  1392. }

  1393. /* 这里应该是获得 hw ocv 电压 */

  1394. ret = battery_meter_ctrl(BATTERY_METER_CMD_GET_HW_OCV, &gFG_voltage);

  1395. static kal_int32 read_hw_ocv(void *data)

  1396. {

  1397. /* 外部充电器的话直接固定值 */

  1398. #if defined(CONFIG_POWER_EXT)

  1399. *(kal_int32*)(data) = 3999;

  1400. #else

  1401. /* 这里应该是读取相应寄存器, 获得一个 hw ocv 电压 */

  1402. *(kal_int32*)(data) = get_hw_ocv();

  1403. int get_hw_ocv(void)

  1404. {

  1405. #if defined(CONFIG_POWER_EXT)

  1406. return 4001;

  1407. #else

  1408. kal_int32 adc_result_reg=0;

  1409. kal_int32 adc_result=0;

  1410. kal_int32 r_val_temp=4;

  1411. #if defined(SWCHR_POWER_PATH)

  1412. adc_result_reg = upmu_get_rg_adc_out_wakeup_swchr();

  1413. adc_result = (adc_result_reg*r_val_temp*VOLTAGE_FULL_RANGE)/ADC_PRECISE;

  1414. bm_print(BM_LOG_CRTI, "[oam] get_hw_ocv (swchr) : adc_result_reg=%d, adc_result=%d\n",

  1415. adc_result_reg, adc_result);

  1416. #else

  1417. /* 这里应该是读取相应寄存器,获得充电电压值,因为从 PMIC 手册上说,只有在充电电压处于 4.3V <= x <= 7V 时才可以充电*/

  1418. adc_result_reg = upmu_get_rg_adc_out_wakeup_pchr();

  1419. kal_uint32 upmu_get_rg_adc_out_wakeup_pchr(void)

  1420. {

  1421. kal_uint32 ret=0;

  1422. kal_uint32 val=0;

  1423. pmic_lock();

  1424. ret=pmic_read_interface( (kal_uint32)(AUXADC_ADC8),

  1425. (&val),

  1426. (kal_uint32)(PMIC_RG_ADC_OUT_WAKEUP_PCHR_MASK),

  1427. (kal_uint32)(PMIC_RG_ADC_OUT_WAKEUP_PCHR_SHIFT)

  1428. );

  1429. pmic_unlock();

  1430. return val;

  1431. }

  1432. /* 将得到的 adc 数值转换为对应的 模拟电压值 */

  1433. adc_result = (adc_result_reg*r_val_temp*VOLTAGE_FULL_RANGE)/ADC_PRECISE;

  1434. bm_print(BM_LOG_CRTI, "[oam] get_hw_ocv (pchr) : adc_result_reg=%d, adc_result=%d\n",

  1435. adc_result_reg, adc_result);

  1436. #endif

  1437. adc_result += g_hw_ocv_tune_value;

  1438. return adc_result;

  1439. #endif

  1440. }

  1441. #endif

  1442. return STATUS_OK;

  1443. }

  1444. /* 获取 hw ocv 电压对应的的电池剩余容量百分比 */

  1445. gFG_capacity_by_v = fgauge_read_capacity_by_v(gFG_voltage);

  1446. kal_int32 fgauge_read_capacity_by_v(kal_int32 voltage)

  1447. {

  1448. int i = 0, saddles = 0;

  1449. BATTERY_PROFILE_STRUC_P profile_p;

  1450. kal_int32 ret_percent = 0;

  1451. /* 获得当前温度对应的 温度-电池容量表格 */

  1452. profile_p = fgauge_get_profile(TEMPERATURE_T);

  1453. if (profile_p == NULL)

  1454. {

  1455. bm_print(BM_LOG_CRTI, "[FGADC] fgauge get ZCV profile : fail !\r\n");

  1456. return 100;

  1457. }

  1458. /* 获得 温度-电池容量 表格项数 */

  1459. saddles = fgauge_get_saddles();

  1460. if (voltage > (profile_p+0)->voltage)

  1461. {

  1462. return 100; // battery capacity, not dod

  1463. }

  1464. if (voltage < (profile_p+saddles-1)->voltage)

  1465. {

  1466. return 0; // battery capacity, not dod

  1467. }

  1468. /* 遍历表格,插值获得当前电压对应的用掉容量百分比 */

  1469. for (i = 0; i < saddles - 1; i++)

  1470. {

  1471. if ((voltage <= (profile_p+i)->voltage) && (voltage >= (profile_p+i+1)->voltage))

  1472. {

  1473. ret_percent = (profile_p+i)->percentage +

  1474. (

  1475. (

  1476. ( ((profile_p+i)->voltage) - voltage ) *

  1477. ( ((profile_p+i+1)->percentage) - ((profile_p + i)->percentage) )

  1478. ) /

  1479. ( ((profile_p+i)->voltage) - ((profile_p+i+1)->voltage) )

  1480. );

  1481. break;

  1482. }

  1483. }

  1484. /* 获得当前剩余电量值 */

  1485. ret_percent = 100 - ret_percent;

  1486. return ret_percent;

  1487. }

  1488. /* 获得当前电池电压对应的剩余容量百分比 */

  1489. vbat_capacity = fgauge_read_capacity_by_v(vol_bat);

  1490. kal_int32 fgauge_read_capacity_by_v(kal_int32 voltage)

  1491. {

  1492. int i = 0, saddles = 0;

  1493. BATTERY_PROFILE_STRUC_P profile_p;

  1494. kal_int32 ret_percent = 0;

  1495. /* 获得当前温度对应的 温度-电池容量表格 */

  1496. profile_p = fgauge_get_profile(TEMPERATURE_T);

  1497. if (profile_p == NULL)

  1498. {

  1499. bm_print(BM_LOG_CRTI, "[FGADC] fgauge get ZCV profile : fail !\r\n");

  1500. return 100;

  1501. }

  1502. /* 获得 温度-电池容量 表格项数 */

  1503. saddles = fgauge_get_saddles();

  1504. if (voltage > (profile_p+0)->voltage)

  1505. {

  1506. return 100; // battery capacity, not dod

  1507. }

  1508. if (voltage < (profile_p+saddles-1)->voltage)

  1509. {

  1510. return 0; // battery capacity, not dod

  1511. }

  1512. /* 遍历表格,插值获得当前电压对应的用掉容量百分比 */

  1513. for (i = 0; i < saddles - 1; i++)

  1514. {

  1515. if ((voltage <= (profile_p+i)->voltage) && (voltage >= (profile_p+i+1)->voltage))

  1516. {

  1517. ret_percent = (profile_p+i)->percentage +

  1518. (

  1519. (

  1520. ( ((profile_p+i)->voltage) - voltage ) *

  1521. ( ((profile_p+i+1)->percentage) - ((profile_p + i)->percentage) )

  1522. ) /

  1523. ( ((profile_p+i)->voltage) - ((profile_p+i+1)->voltage) )

  1524. );

  1525. break;

  1526. }

  1527. }

  1528. ret_percent = 100 - ret_percent;

  1529. return ret_percent;

  1530. }

  1531. /* 如果充电器插上了,则比较使用当前电压与 hw ocv 电压计算的两都容量差,如果差值较小,继续使用 hw ocv 电压及

  1532. 对应容量为准 */

  1533. if(bat_is_charger_exist() == KAL_TRUE)

  1534. ///

  1535. Pulse Charging Algorithm

  1536. // 判断充电是否插上了

  1537. ///

  1538. kal_bool bat_is_charger_exist(void)

  1539. {

  1540. return get_charger_detect_status();

  1541. int get_charger_detect_status(void)

  1542. {

  1543. kal_bool chr_status;

  1544. /* 对应的充电芯片的硬件函数 */

  1545. battery_charging_control(CHARGING_CMD_GET_CHARGER_DET_STATUS,&chr_status);

  1546. static kal_uint32 charging_get_charger_det_status(void *data)

  1547. {

  1548. kal_uint32 status = STATUS_OK;

  1549. #if defined(CHRDET_SW_MODE_EN)

  1550. kal_uint32 vchr_val=0;

  1551. /* 读 PMIC 对应的 ADC 的值,并将其转化为对应的电压值,这里即读取 VCDT 引脚电压 */

  1552. vchr_val = PMIC_IMM_GetOneChannelValue(4,5,1);

  1553. vchr_val = (((330+39)*100*vchr_val)/39)/100;

  1554. if( vchr_val > 4300 )

  1555. {

  1556. battery_xlog_printk(BAT_LOG_FULL, "[CHRDET_SW_WORKAROUND_EN] upmu_is_chr_det=Y (%d)\n", vchr_val);

  1557. *(kal_uint32 *)data = KAL_TRUE;

  1558. }

  1559. else

  1560. {

  1561. battery_xlog_printk(BAT_LOG_FULL, "[CHRDET_SW_WORKAROUND_EN] upmu_is_chr_det=N (%d)\n", vchr_val);

  1562. *(kal_uint32 *)data = KAL_FALSE;

  1563. }

  1564. #else

  1565. /* 读取 CHR_CON0 寄存器 */

  1566. *(kal_bool*)(data) = upmu_get_rgs_chrdet();

  1567. kal_uint32 upmu_get_rgs_chrdet(void)

  1568. {

  1569. kal_uint32 ret=0;

  1570. kal_uint32 val=0;

  1571. pmic_lock();

  1572. ret=pmic_read_interface( (kal_uint32)(CHR_CON0),

  1573. (&val),

  1574. (kal_uint32)(PMIC_RGS_CHRDET_MASK),

  1575. (kal_uint32)(PMIC_RGS_CHRDET_SHIFT)

  1576. );

  1577. pmic_unlock();

  1578. return val;

  1579. }

  1580. #endif

  1581. /* 读取 CHR_CON0 寄存器 */

  1582. if( upmu_get_rgs_chrdet() == 0 )

  1583. g_charger_type = CHARGER_UNKNOWN;

  1584. return status;

  1585. }

  1586. return chr_status;

  1587. }

  1588. }

  1589. // 如果插入了充电器,hw_ocv 大部分情况是准的,插着 charger 的情况,采集的时候可能会不准

  1590. {

  1591. bm_print(BM_LOG_CRTI, "[oam_init_inf] gFG_capacity_by_v=%d, vbat_capacity=%d, \n",gFG_capacity_by_v,vbat_capacity);

  1592. // to avoid plug in cable without battery, then plug in battery to make hw soc = 100%

  1593. // if the difference bwtween ZCV and vbat is too large, using vbat instead ZCV

  1594. /* 如果两者差值超过 30%,我们认为 hw ocv 存在偏差,会以 Vbat 作为 ocv

  1595. 如果两者差值在 30%,继续以 hw ocv 作为 ocv 的数值 */

  1596. if(((gFG_capacity_by_v == 100) && (vbat_capacity < CUST_POWERON_MAX_VBAT_TOLRANCE)) ||(abs(gFG_capacity_by_v-vbat_capacity)>CUST_POWERON_DELTA_VBAT_TOLRANCE))

  1597. {

  1598. bm_print(BM_LOG_CRTI, "[oam_init] fg_vbat=(%d), vbat=(%d), set fg_vat as vat\n", gFG_voltage,vol_bat);

  1599. gFG_voltage = vol_bat;

  1600. gFG_capacity_by_v = vbat_capacity;

  1601. }

  1602. }

  1603. // 获得的比较真实的开机容量

  1604. gFG_capacity_by_v_init = gFG_capacity_by_v;

  1605. /* 这里与 rtc 中的电量进行比较,确定一个开机显示 UI 电量 */

  1606. dod_init();

  1607. void dod_init(void)

  1608. {

  1609. #if defined(SOC_BY_HW_FG)

  1610. int ret = 0;

  1611. //use get_hw_ocv-----------------------------------------------------------------

  1612. /* 获取 PMIC 硬件上的 hw ocv 电压 */

  1613. ret=battery_meter_ctrl(BATTERY_METER_CMD_GET_HW_OCV, &gFG_voltage);

  1614. // 对应 PMIC 硬件相关操作函数

  1615. read_hw_ocv()

  1616. get_hw_ocv()

  1617. /* 根据 hw ocv 电压,查表获取对应的电池剩余电量百分比*/

  1618. gFG_capacity_by_v = fgauge_read_capacity_by_v(gFG_voltage);

  1619. bm_print(BM_LOG_CRTI, "[FGADC] get_hw_ocv=%d, HW_SOC=%d, SW_SOC = %d\n",

  1620. gFG_voltage, gFG_capacity_by_v, gFG_capacity_by_v_init);

  1621. // compare with hw_ocv & sw_ocv, check if less than or equal to 5% tolerance

  1622. // 将软件 ocv 与硬件 ocv 比较,误差要少于 5%, 才使用之前计算的 sw hov?

  1623. if ((abs(gFG_capacity_by_v_init - gFG_capacity_by_v) > 5) && (bat_is_charger_exist() == KAL_TRUE))

  1624. {

  1625. gFG_capacity_by_v = gFG_capacity_by_v_init;

  1626. }

  1627. //-------------------------------------------------------------------------------

  1628. #endif

  1629. #if defined(CONFIG_POWER_EXT)

  1630. g_rtc_fg_soc = gFG_capacity_by_v;

  1631. #else

  1632. /* 获取 DOD0 的数值,电池电量每 10s 写入 RTC 一次,开机会从 RTC 里面读取 DOD0 的值

  1633. 保存在 rtc 数值,即上次关机的 UI 电量数值 */

  1634. g_rtc_fg_soc = get_rtc_spare_fg_value();

  1635. int get_rtc_spare_fg_value(void)

  1636. {

  1637. //RTC_AL_HOU bit8~14

  1638. u16 temp;

  1639. unsigned long flags;

  1640. spin_lock_irqsave(&rtc_lock, flags);

  1641. temp = hal_rtc_get_register_status("FG");

  1642. spin_unlock_irqrestore(&rtc_lock, flags);

  1643. return temp;

  1644. }

  1645. #endif

  1646. /* g_rtc_fg_soc: 为上次关机前的 UI 电量

  1647. gFG_capacity_by_v: 是经过 oam_init() 初始化后的电池真实电压

  1648. 由于存在换电池的风险, 会去判断两者的差值:

  1649. 1. 40% 以内,采用 rtc 电量,即继续显示上次 UI 的电量

  1650. 2. 如果在 40% 以外,采用真实电池电压的电量,因为有可能更换了电池

  1651. 设计的初衷: 因为电池特性,在确定 dod 会有误差,从而导致开关机电量跳变,

  1652. 因此采用 rtc 是为了防止电量跳变

  1653. */

  1654. if(g_rtc_fg_soc >= gFG_capacity_by_v)

  1655. {

  1656. if(((g_rtc_fg_soc != 0) && ((g_rtc_fg_soc-gFG_capacity_by_v) < CUST_POWERON_DELTA_CAPACITY_TOLRANCE) &&(( gFG_capacity_by_v > CUST_POWERON_LOW_CAPACITY_TOLRANCE || bat_is_charger_exist() == KAL_TRUE)))

  1657. || ((g_rtc_fg_soc != 0) &&(g_boot_reason == BR_WDT_BY_PASS_PWK || g_boot_reason == BR_WDT || g_boot_reason == BR_TOOL_BY_PASS_PWK || g_boot_reason == BR_2SEC_REBOOT || g_boot_mode == RECOVERY_BOOT)))

  1658. {

  1659. gFG_capacity_by_v = g_rtc_fg_soc;

  1660. }

  1661. }

  1662. else

  1663. {

  1664. if(((g_rtc_fg_soc != 0) && ((gFG_capacity_by_v-g_rtc_fg_soc) < CUST_POWERON_DELTA_CAPACITY_TOLRANCE) &&(( gFG_capacity_by_v > CUST_POWERON_LOW_CAPACITY_TOLRANCE || bat_is_charger_exist() == KAL_TRUE)))

  1665. || ((g_rtc_fg_soc != 0) &&(g_boot_reason == BR_WDT_BY_PASS_PWK || g_boot_reason == BR_WDT || g_boot_reason == BR_TOOL_BY_PASS_PWK || g_boot_reason == BR_2SEC_REBOOT || g_boot_mode == RECOVERY_BOOT)))

  1666. {

  1667. gFG_capacity_by_v = g_rtc_fg_soc;

  1668. }

  1669. }

  1670. bm_print(BM_LOG_CRTI, "[FGADC] g_rtc_fg_soc=%d, gFG_capacity_by_v=%d\n",

  1671. g_rtc_fg_soc, gFG_capacity_by_v);

  1672. if (gFG_capacity_by_v == 0 && bat_is_charger_exist() == KAL_TRUE) {

  1673. gFG_capacity_by_v = 1;

  1674. bm_print(BM_LOG_CRTI, "[FGADC] gFG_capacity_by_v=%d\n",

  1675. gFG_capacity_by_v);

  1676. }

  1677. //

  1678. // 在这里最终定义的开机 UI 电量显示

  1679. gFG_capacity = gFG_capacity_by_v; // 电池剩余容量百分比

  1680. gFG_capacity_by_c_init = gFG_capacity;

  1681. gFG_capacity_by_c = gFG_capacity;

  1682. gFG_DOD0 = 100 - gFG_capacity; // 电池使用完电量百分比

  1683. gFG_DOD1=gFG_DOD0; // 电池使用完电量百分比

  1684. gfg_percent_check_point = gFG_capacity; // 容量检测百分比

  1685. #if defined(CHANGE_TRACKING_POINT)

  1686. gFG_15_vlot = fgauge_read_v_by_capacity( (100-g_tracking_point) );

  1687. bm_print(BM_LOG_CRTI, "[FGADC] gFG_15_vlot = %dmV\n", gFG_15_vlot);

  1688. #else

  1689. //gFG_15_vlot = fgauge_read_v_by_capacity(86); //14%

  1690. /* 通过当前使用掉的容量,获取当前电压 */

  1691. gFG_15_vlot = fgauge_read_v_by_capacity( (100-g_tracking_point) );

  1692. bm_print(BM_LOG_CRTI, "[FGADC] gFG_15_vlot = %dmV\n", gFG_15_vlot);

  1693. if( (gFG_15_vlot > 3800) || (gFG_15_vlot < 3600) )

  1694. {

  1695. bm_print(BM_LOG_CRTI, "[FGADC] gFG_15_vlot(%d) over range, reset to 3700\n", gFG_15_vlot);

  1696. gFG_15_vlot = 3700;

  1697. }

  1698. #endif

  1699. }

  1700. /* 先通过 battery_meter_get_battery_temperature() 获得电池温度,再通过 fgauge_get_Q_max() 计算电量

  1701. 这里获得当前温度的电池的最大容量 */

  1702. gFG_BATT_CAPACITY_aging = fgauge_get_Q_max(battery_meter_get_battery_temperature());

  1703. kal_int32 battery_meter_get_battery_temperature(void)

  1704. {

  1705. /* 通过获得当前 NTC 电压,查表并进行线性插值法,得到当前的温度值 */

  1706. return force_get_tbat();

  1707. }

  1708. // 通过当前温度获插值得到当前最大容量

  1709. kal_int32 fgauge_get_Q_max(kal_int16 temperature)

  1710. {

  1711. kal_int32 ret_Q_max=0;

  1712. kal_int32 low_temperature = 0, high_temperature = 0;

  1713. kal_int32 low_Q_max = 0, high_Q_max = 0;

  1714. /* 如果温度位于 -20< x <= 0 */

  1715. if (temperature <= TEMPERATURE_T1)

  1716. {

  1717. low_temperature = (-10);

  1718. low_Q_max = Q_MAX_NEG_10;

  1719. high_temperature = TEMPERATURE_T1;

  1720. high_Q_max = Q_MAX_POS_0;

  1721. if(temperature < low_temperature)

  1722. {

  1723. temperature = low_temperature;

  1724. }

  1725. }

  1726. /* 如果温度位于 0< x <= 25 */

  1727. else if (temperature <= TEMPERATURE_T2)

  1728. {

  1729. low_temperature = TEMPERATURE_T1;

  1730. low_Q_max = Q_MAX_POS_0;

  1731. high_temperature = TEMPERATURE_T2;

  1732. high_Q_max = Q_MAX_POS_25;

  1733. if(temperature < low_temperature)

  1734. {

  1735. temperature = low_temperature;

  1736. }

  1737. }

  1738. /* 如果温度位于 -25< x <=50 */

  1739. else

  1740. {

  1741. low_temperature = TEMPERATURE_T2; // 低温下限

  1742. low_Q_max = Q_MAX_POS_25; // 低温最大容量

  1743. high_temperature = TEMPERATURE_T3; // 高温上限

  1744. high_Q_max = Q_MAX_POS_50; // 高温对应最大容量

  1745. // 防止范围溢出

  1746. if(temperature > high_temperature)

  1747. {

  1748. temperature = high_temperature;

  1749. }

  1750. }

  1751. /*//

  1752. 核心算法:

  1753. 当前容量 = 低温下限最大容量 + (当前温度 - 低温下限) * [(高温容量 - 低温容量)/(高温上限-低温下限)] */

  1754. ret_Q_max = low_Q_max +

  1755. (

  1756. (

  1757. (temperature - low_temperature) *

  1758. (high_Q_max - low_Q_max)

  1759. ) /

  1760. (high_temperature - low_temperature)

  1761. );

  1762. bm_print(BM_LOG_FULL, "[fgauge_get_Q_max] Q_max = %d\r\n", ret_Q_max);

  1763. return ret_Q_max;

  1764. }

  1765. //oam_v_ocv_1 = gFG_voltage;

  1766. //oam_v_ocv_2 = gFG_voltage;

  1767. /* 通过当前使用电池容量的百分比,反换算出当前的电压 */

  1768. oam_v_ocv_init = fgauge_read_v_by_d(gFG_DOD0);

  1769. kal_int32 fgauge_read_v_by_d(int d_val)

  1770. {

  1771. int i = 0, saddles = 0;

  1772. BATTERY_PROFILE_STRUC_P profile_p;

  1773. kal_int32 ret_volt = 0;

  1774. profile_p = fgauge_get_profile(TEMPERATURE_T);

  1775. if (profile_p == NULL)

  1776. {

  1777. bm_print(BM_LOG_CRTI, "[fgauge_read_v_by_capacity] fgauge get ZCV profile : fail !\r\n");

  1778. return 3700;

  1779. }

  1780. saddles = fgauge_get_saddles();

  1781. if (d_val < (profile_p+0)->percentage)

  1782. {

  1783. return 3700;

  1784. }

  1785. if (d_val > (profile_p+saddles-1)->percentage)

  1786. {

  1787. return 3700;

  1788. }

  1789. for (i = 0; i < saddles - 1; i++)

  1790. {

  1791. if ((d_val >= (profile_p+i)->percentage) && (d_val <= (profile_p+i+1)->percentage))

  1792. {

  1793. ret_volt = (profile_p+i)->voltage -

  1794. (

  1795. (

  1796. ( d_val - ((profile_p+i)->percentage) ) *

  1797. ( ((profile_p+i)->voltage) - ((profile_p+i+1)->voltage) )

  1798. ) /

  1799. ( ((profile_p+i+1)->percentage) - ((profile_p+i)->percentage) )

  1800. );

  1801. break;

  1802. }

  1803. }

  1804. return ret_volt;

  1805. }

  1806. oam_v_ocv_2 = oam_v_ocv_1 = oam_v_ocv_init; // 通过当前使用电池容量的百分比,反换算出当前的电压

  1807. g_vol_bat_hw_ocv = gFG_voltage; // hw ocv 电压

  1808. //vbat = 5; //set avg times

  1809. //ret = battery_meter_ctrl(BATTERY_METER_CMD_GET_ADC_V_BAT_SENSE, &vbat);

  1810. //oam_r_1 = fgauge_read_r_bat_by_v(vbat);

  1811. /* 通过当前 hw ocv 电压,获得的当前电池内阻 */

  1812. oam_r_1 = fgauge_read_r_bat_by_v(gFG_voltage);

  1813. oam_r_2 = oam_r_1;

  1814. oam_d0 = gFG_DOD0;

  1815. oam_d_5 = oam_d0;

  1816. oam_i_ori = gFG_current;

  1817. g_d_hw_ocv = oam_d0;

  1818. if(oam_init_i == 0)

  1819. {

  1820. bm_print(BM_LOG_CRTI, "[oam_init] oam_v_ocv_1,oam_v_ocv_2,oam_r_1,oam_r_2,oam_d0,oam_i_ori\n");

  1821. oam_init_i=1;

  1822. }

  1823. bm_print(BM_LOG_CRTI, "[oam_init] %d,%d,%d,%d,%d,%d\n",

  1824. oam_v_ocv_1, oam_v_ocv_2, oam_r_1, oam_r_2, oam_d0, oam_i_ori);

  1825. bm_print(BM_LOG_CRTI, "[oam_init_inf] hw_OCV, hw_D0, RTC, D0, oam_OCV_init, tbat\n");

  1826. bm_print(BM_LOG_CRTI, "[oam_run_inf] oam_OCV1, oam_OCV2, vbat, I1, I2, R1, R2, Car1, Car2,qmax, tbat\n");

  1827. bm_print(BM_LOG_CRTI, "[oam_result_inf] D1, D2, D3, D4, D5, UI_SOC\n");

  1828. bm_print(BM_LOG_CRTI, "[oam_init_inf] %d, %d, %d, %d, %d, %d\n",

  1829. gFG_voltage, (100 - fgauge_read_capacity_by_v(gFG_voltage)), g_rtc_fg_soc, gFG_DOD0 ,oam_v_ocv_init, force_get_tbat());

  1830. }

  1831. bm_print(BM_LOG_CRTI, "[battery_meter_initial] SOC_BY_SW_FG done\n");

  1832. #endif

  1833. return 0;

  1834. #endif

  1835. }

  1836. /* 获得要监控的电量,(用这个电量反换出电压来校验?)*/

  1837. BMT_status.nPercent_ZCV = battery_meter_get_battery_nPercent_zcv();

  1838. kal_int32 battery_meter_get_battery_nPercent_zcv(void)

  1839. {

  1840. #if defined(CONFIG_POWER_EXT)

  1841. return 3700;

  1842. #else

  1843. return gFG_15_vlot; // 15% zcv, 15% can be customized by 100-g_tracking_point

  1844. #endif

  1845. }

  1846. battery_meter_initilized = KAL_TRUE;

  1847. }

  1848. // 1. 判断是插入的是否充电器还是电脑 USB,看能不能进行充电

  1849. /* 如果连接的 USB 线为 USB 充电线,或者电脑 USB 线,则打开 USB,

  1850. 这里会通过 BC1.1 来判断是电脑 USB 还是 USB 充电器,来决定充电电流

  1851. 否则连接的不是充电线或者 USB 作为一个从设备使用,要断开 USB?

  1852. */

  1853. mt_battery_charger_detect_check();

  1854. static void mt_battery_charger_detect_check(void)

  1855. {

  1856. /* 根据 USB 是主从状态,以及外部充电电压是否正常来判断是否允许充电,

  1857. 这里如果是 USB 作为从设备,允许充电 */

  1858. if( upmu_is_chr_det() == KAL_TRUE )

  1859. ///

  1860. PMIC PCHR Related APIs

  1861. ///

  1862. kal_bool upmu_is_chr_det(void)

  1863. {

  1864. #if defined(CONFIG_POWER_EXT)

  1865. //return KAL_TRUE;

  1866. return get_charger_detect_status();

  1867. // 如果是外部充电芯片,则直接会调用外部芯片的充电相关函数,如 charging_hw_bq24196.c 中的

  1868. battery_charging_control(CHARGING_CMD_GET_CHARGER_DET_STATUS,&chr_status);

  1869. #else

  1870. kal_uint32 tmp32;

  1871. /* 这里是 PMIC,调用 PMIC 的充电相关函数 charging_hw_pmic.c,

  1872. 这里查询 PMIC 的 CHR_CON0 寄存器,检查充电状态 */

  1873. tmp32=get_charger_detect_status();

  1874. int get_charger_detect_status(void)

  1875. {

  1876. kal_bool chr_status;

  1877. battery_charging_control(CHARGING_CMD_GET_CHARGER_DET_STATUS,&chr_status);

  1878. static kal_uint32 charging_get_charger_det_status(void *data)

  1879. {

  1880. kal_uint32 status = STATUS_OK;

  1881. #if defined(CHRDET_SW_MODE_EN)

  1882. kal_uint32 vchr_val=0;

  1883. // 获得 PMIC 的 VCDT 充电电压值

  1884. vchr_val = PMIC_IMM_GetOneChannelValue(4,5,1);

  1885. vchr_val = (((330+39)*100*vchr_val)/39)/100;

  1886. if( vchr_val > 4300 )

  1887. {

  1888. battery_xlog_printk(BAT_LOG_FULL, "[CHRDET_SW_WORKAROUND_EN] upmu_is_chr_det=Y (%d)\n", vchr_val);

  1889. *(kal_uint32 *)data = KAL_TRUE;

  1890. }

  1891. else

  1892. {

  1893. battery_xlog_printk(BAT_LOG_FULL, "[CHRDET_SW_WORKAROUND_EN] upmu_is_chr_det=N (%d)\n", vchr_val);

  1894. *(kal_uint32 *)data = KAL_FALSE;

  1895. }

  1896. #else

  1897. *(kal_bool*)(data) = upmu_get_rgs_chrdet();

  1898. #endif

  1899. /* 读取 PMIC CHR_CON0 寄存器 */

  1900. if( upmu_get_rgs_chrdet() == 0 )

  1901. g_charger_type = CHARGER_UNKNOWN;

  1902. return status;

  1903. }

  1904. return chr_status;

  1905. }

  1906. if(tmp32 == 0)

  1907. {

  1908. return KAL_FALSE;

  1909. }

  1910. else

  1911. {

  1912. /* 如果 USB 作为一个不是以从设备运行,是不允许充电的 */

  1913. if( mt_usb_is_device() )

  1914. // Usb20.c (s:\i841\mediatek\platform\mt6582\kernel\drivers\usb20)

  1915. /* ================================ */

  1916. /* connect and disconnect functions */

  1917. /* ================================ */

  1918. bool mt_usb_is_device(void)

  1919. {

  1920. DBG(4,"called\n");

  1921. /* 如果 mtk_musb 为 0 的话,表明 MTK 的 USB 在作为一个主机使用,不允许充电的 */

  1922. if(!mtk_musb){

  1923. DBG(0,"mtk_musb is NULL\n");

  1924. return false; // don't do charger detection when usb is not ready

  1925. } else {

  1926. DBG(4,"is_host=%d\n",mtk_musb->is_host);

  1927. }

  1928. return !mtk_musb->is_host;

  1929. }

  1930. {

  1931. battery_xlog_printk(BAT_LOG_FULL, "[upmu_is_chr_det] Charger exist and USB is not host\n");

  1932. return KAL_TRUE;

  1933. }

  1934. else

  1935. {

  1936. battery_xlog_printk(BAT_LOG_FULL, "[upmu_is_chr_det] Charger exist but USB is host\n");

  1937. return KAL_FALSE;

  1938. }

  1939. }

  1940. #endif

  1941. }

  1942. // 如果插入的是 USB 充电线或者 电脑的 USB 线,则打开 USB ,因为充电时 MTK 作为从设备,是允许充电的

  1943. {

  1944. wake_lock(&battery_suspend_lock);

  1945. BMT_status.charger_exist = KAL_TRUE;

  1946. // 无线充电支持宏

  1947. #if defined(MTK_WIRELESS_CHARGER_SUPPORT)

  1948. mt_charger_type_detection();

  1949. if((BMT_status.charger_type==STANDARD_HOST) || (BMT_status.charger_type==CHARGING_HOST) )

  1950. {

  1951. // 这应该是做为从设备连接到电脑上用的

  1952. mt_usb_connect();

  1953. }

  1954. #else

  1955. /* 这个结构体是在前面初始化的,所以第一次执行,该值未设置 = 0,

  1956. 在这里通过 BC1.1 协议检测外部连接的 USB 线类型,是主是从,还是充电/被充

  1957. 最后根据类型判断要不要启动 USB */

  1958. if(BMT_status.charger_type == CHARGER_UNKNOWN)

  1959. {

  1960. /* 调用 PMIC 硬件相关函数,检测充电类型, 这里应用了 BC1.1 协议来检测 */

  1961. mt_charger_type_detection();

  1962. CHARGER_TYPE mt_charger_type_detection(void)

  1963. {

  1964. CHARGER_TYPE CHR_Type_num = CHARGER_UNKNOWN;

  1965. mutex_lock(&charger_type_mutex);

  1966. #if defined(MTK_WIRELESS_CHARGER_SUPPORT)

  1967. battery_charging_control(CHARGING_CMD_GET_CHARGER_TYPE,&CHR_Type_num);

  1968. BMT_status.charger_type = CHR_Type_num;

  1969. #else

  1970. /* 调用 PMIC 硬件相关函数,检测充电类型, 这里应用了 BC1.1 协议来检测 */

  1971. if(BMT_status.charger_type == CHARGER_UNKNOWN)

  1972. {

  1973. /* 调用 PMIC 硬件相关函数,检测充电类型, 这里应用了 BC1.1 协议来检测 */

  1974. battery_charging_control(CHARGING_CMD_GET_CHARGER_TYPE,&CHR_Type_num);

  1975. static kal_uint32 charging_get_charger_type(void *data)

  1976. {

  1977. kal_uint32 status = STATUS_OK;

  1978. #if defined(CONFIG_POWER_EXT)

  1979. *(CHARGER_TYPE*)(data) = STANDARD_HOST;

  1980. #else

  1981. #if defined(MTK_WIRELESS_CHARGER_SUPPORT)

  1982. int wireless_state = 0;

  1983. /* 无线充电判断引脚,直接拉低就好 */

  1984. wireless_state = mt_get_gpio_in(wireless_charger_gpio_number);

  1985. if(wireless_state == WIRELESS_CHARGER_EXIST_STATE)

  1986. {

  1987. *(CHARGER_TYPE*)(data) = WIRELESS_CHARGER;

  1988. battery_xlog_printk(BAT_LOG_CRTI, "WIRELESS_CHARGER!\r\n");

  1989. return status;

  1990. }

  1991. #endif

  1992. if(g_charger_type!=CHARGER_UNKNOWN && g_charger_type!=WIRELESS_CHARGER)

  1993. {

  1994. *(CHARGER_TYPE*)(data) = g_charger_type;

  1995. battery_xlog_printk(BAT_LOG_CRTI, "return %d!\r\n", g_charger_type);

  1996. return status;

  1997. }

  1998. charging_type_det_done = KAL_FALSE;

  1999. /*//

  2000. BC1.1 充电协议,主要用来区分是插入的是 USB 还是充电器,如果是 USB 只能提供 500ma 充电,

  2001. 如果是充电器,则可以大电流充电 */

  2002. /********* Step initial ***************/

  2003. hw_bc11_init();

  2004. static void hw_bc11_init(void)

  2005. {

  2006. msleep(300);

  2007. Charger_Detect_Init();

  2008. //RG_BC11_BIAS_EN=1

  2009. upmu_set_rg_bc11_bias_en(0x1);

  2010. //RG_BC11_VSRC_EN[1:0]=00

  2011. upmu_set_rg_bc11_vsrc_en(0x0);

  2012. //RG_BC11_VREF_VTH = [1:0]=00

  2013. upmu_set_rg_bc11_vref_vth(0x0);

  2014. //RG_BC11_CMP_EN[1.0] = 00

  2015. upmu_set_rg_bc11_cmp_en(0x0);

  2016. //RG_BC11_IPU_EN[1.0] = 00

  2017. upmu_set_rg_bc11_ipu_en(0x0);

  2018. //RG_BC11_IPD_EN[1.0] = 00

  2019. upmu_set_rg_bc11_ipd_en(0x0);

  2020. //BC11_RST=1

  2021. upmu_set_rg_bc11_rst(0x1);

  2022. //BC11_BB_CTRL=1

  2023. upmu_set_rg_bc11_bb_ctrl(0x1);

  2024. //msleep(10);

  2025. mdelay(50);

  2026. if(Enable_BATDRV_LOG == BAT_LOG_FULL)

  2027. {

  2028. battery_xlog_printk(BAT_LOG_FULL, "hw_bc11_init() \r\n");

  2029. hw_bc11_dump_register();

  2030. }

  2031. }

  2032. /********* Step DCD ***************/

  2033. if(1 == hw_bc11_DCD())

  2034. {

  2035. /********* Step A1 ***************/

  2036. if(1 == hw_bc11_stepA1())

  2037. {

  2038. *(CHARGER_TYPE*)(data) = APPLE_2_1A_CHARGER;

  2039. battery_xlog_printk(BAT_LOG_CRTI, "step A1 : Apple 2.1A CHARGER!\r\n");

  2040. }

  2041. else

  2042. {

  2043. *(CHARGER_TYPE*)(data) = NONSTANDARD_CHARGER;

  2044. battery_xlog_printk(BAT_LOG_CRTI, "step A1 : Non STANDARD CHARGER!\r\n");

  2045. }

  2046. }

  2047. else

  2048. {

  2049. /********* Step A2 ***************/

  2050. if(1 == hw_bc11_stepA2())

  2051. {

  2052. /********* Step B2 ***************/

  2053. if(1 == hw_bc11_stepB2())

  2054. {

  2055. *(CHARGER_TYPE*)(data) = STANDARD_CHARGER;

  2056. battery_xlog_printk(BAT_LOG_CRTI, "step B2 : STANDARD CHARGER!\r\n");

  2057. }

  2058. else

  2059. {

  2060. *(CHARGER_TYPE*)(data) = CHARGING_HOST;

  2061. battery_xlog_printk(BAT_LOG_CRTI, "step B2 : Charging Host!\r\n");

  2062. }

  2063. }

  2064. else

  2065. {

  2066. *(CHARGER_TYPE*)(data) = STANDARD_HOST;

  2067. battery_xlog_printk(BAT_LOG_CRTI, "step A2 : Standard USB Host!\r\n");

  2068. }

  2069. }

  2070. /********* Finally setting *******************************/

  2071. hw_bc11_done();

  2072. static void hw_bc11_done(void)

  2073. {

  2074. //RG_BC11_VSRC_EN[1:0]=00

  2075. upmu_set_rg_bc11_vsrc_en(0x0);

  2076. //RG_BC11_VREF_VTH = [1:0]=0

  2077. upmu_set_rg_bc11_vref_vth(0x0);

  2078. //RG_BC11_CMP_EN[1.0] = 00

  2079. upmu_set_rg_bc11_cmp_en(0x0);

  2080. //RG_BC11_IPU_EN[1.0] = 00

  2081. upmu_set_rg_bc11_ipu_en(0x0);

  2082. //RG_BC11_IPD_EN[1.0] = 00

  2083. upmu_set_rg_bc11_ipd_en(0x0);

  2084. //RG_BC11_BIAS_EN=0

  2085. upmu_set_rg_bc11_bias_en(0x0);

  2086. Charger_Detect_Release();

  2087. void Charger_Detect_Release(void)

  2088. {

  2089. /* RG_USB20_BC11_SW_EN = 1'b0 */

  2090. USBPHY_CLR8(0x1a, 0x80);

  2091. udelay(1);

  2092. //4 14. turn off internal 48Mhz PLL.

  2093. usb_enable_clock(false);

  2094. printk("Charger_Detect_Release\n");

  2095. }

  2096. if(Enable_BATDRV_LOG == BAT_LOG_FULL)

  2097. {

  2098. battery_xlog_printk(BAT_LOG_FULL, "hw_bc11_done() \r\n");

  2099. hw_bc11_dump_register();

  2100. }

  2101. }

  2102. charging_type_det_done = KAL_TRUE;

  2103. g_charger_type = *(CHARGER_TYPE*)(data);

  2104. #endif

  2105. return status;

  2106. }

  2107. BMT_status.charger_type = CHR_Type_num;

  2108. }

  2109. #endif

  2110. mutex_unlock(&charger_type_mutex);

  2111. return BMT_status.charger_type;

  2112. }

  2113. /* 如果充电线是 标准主模式 或者 主充电模式, 连接上 USB */

  2114. if((BMT_status.charger_type==STANDARD_HOST) || (BMT_status.charger_type==CHARGING_HOST) )

  2115. {

  2116. /* 连接 USB,充电时可以连接 USB 的 */

  2117. mt_usb_connect();

  2118. void mt_usb_connect(void)

  2119. {

  2120. printk("[MUSB] USB is ready for connect\n");

  2121. DBG(3, "is ready %d is_host %d power %d\n",mtk_musb->is_ready,mtk_musb->is_host , mtk_musb->power);

  2122. if (!mtk_musb || !mtk_musb->is_ready || mtk_musb->is_host || mtk_musb->power)

  2123. return;

  2124. DBG(0,"cable_mode=%d\n",cable_mode);

  2125. /* CABLE_MODE_CHRG_ONLY = 0, CABLE_MODE_NORMAL, CABLE_MODE_HOST_ONLY, CABLE_MODE_MAX

  2126. 上面这些模式,应该是通过 BC1.1 来判断出来的 */

  2127. if(cable_mode != CABLE_MODE_NORMAL)

  2128. {

  2129. DBG(0,"musb_sync_with_bat, USB_CONFIGURED\n");

  2130. musb_sync_with_bat(mtk_musb,USB_CONFIGURED);

  2131. void musb_sync_with_bat(struct musb *musb,int usb_state)

  2132. {

  2133. #ifndef FPGA_PLATFORM

  2134. DBG(0,"BATTERY_SetUSBState, state=%d\n",usb_state);

  2135. // linear_charging.c,线性充电

  2136. BATTERY_SetUSBState(usb_state);

  2137. void BATTERY_SetUSBState(int usb_state_value)

  2138. {

  2139. #if defined(CONFIG_POWER_EXT)

  2140. battery_xlog_printk(BAT_LOG_CRTI, "[BATTERY_SetUSBState] in FPGA/EVB, no service\r\n");

  2141. #else

  2142. if ( (usb_state_value < USB_SUSPEND) || ((usb_state_value > USB_CONFIGURED))){

  2143. battery_xlog_printk(BAT_LOG_CRTI, "[BATTERY] BAT_SetUSBState Fail! Restore to default value\r\n");

  2144. usb_state_value = USB_UNCONFIGURED;

  2145. } else {

  2146. battery_xlog_printk(BAT_LOG_CRTI, "[BATTERY] BAT_SetUSBState Success! Set %d\r\n", usb_state_value);

  2147. g_usb_state = usb_state_value;

  2148. }

  2149. #endif

  2150. }

  2151. wake_up_bat();

  2152. void wake_up_bat (void)

  2153. {

  2154. battery_xlog_printk(BAT_LOG_CRTI, "[BATTERY] wake_up_bat. \r\n");

  2155. chr_wake_up_bat = KAL_TRUE;

  2156. bat_thread_timeout = KAL_TRUE;

  2157. wake_up(&bat_thread_wq);

  2158. }

  2159. #endif

  2160. }

  2161. mtk_musb->power = true;

  2162. return;

  2163. }

  2164. if (!wake_lock_active(&mtk_musb->usb_lock))

  2165. wake_lock(&mtk_musb->usb_lock);

  2166. // Program the HDRC to start (enable interrupts, dma, etc.).

  2167. // 启动 USB

  2168. musb_start(mtk_musb);

  2169. /*-------------------------------------------------------------------------*/

  2170. /*

  2171. * Program the HDRC to start (enable interrupts, dma, etc.).

  2172. */

  2173. void musb_start(struct musb *musb)

  2174. {

  2175. void __iomem *regs = musb->mregs;

  2176. int vbusdet_retry = 5;

  2177. u8 intrusbe;

  2178. DBG(0, "start, is_host=%d is_active=%d\n", musb->is_host, musb->is_active);

  2179. if(musb->is_active) {

  2180. if(musb->is_host) {

  2181. DBG(0, "we are host now, add more interrupt devctl=%x\n", musb_readb(mtk_musb->mregs,MUSB_DEVCTL));

  2182. musb->intrtxe = 0xffff;

  2183. musb_writew(regs, MUSB_INTRTXE, musb->intrtxe);

  2184. musb->intrrxe = 0xfffe;

  2185. musb_writew(regs, MUSB_INTRRXE, musb->intrrxe);

  2186. musb_writeb(regs,MUSB_INTRUSBE,0xf7);

  2187. return;

  2188. }

  2189. }

  2190. musb_platform_enable(musb);

  2191. musb_generic_disable(musb);

  2192. intrusbe= musb_readb(regs, MUSB_INTRUSBE);

  2193. if (musb->is_host){

  2194. musb->intrtxe = 0xffff;

  2195. musb_writew(regs, MUSB_INTRTXE, musb->intrtxe);

  2196. musb->intrrxe = 0xfffe;

  2197. musb_writew(regs, MUSB_INTRRXE, musb->intrrxe);

  2198. intrusbe = 0xf7;

  2199. while(!musb_platform_get_vbus_status(musb)) {

  2200. mdelay(100);

  2201. if(vbusdet_retry--<=1) {

  2202. DBG(0, "VBUS detection fail!\n");

  2203. break;

  2204. }

  2205. }

  2206. } else if(!musb->is_host){

  2207. intrusbe |= MUSB_INTR_RESET; //device mode enable reset interrupt

  2208. }

  2209. musb_writeb(regs,MUSB_INTRUSBE,intrusbe);

  2210. if (musb_speed) {

  2211. /* put into basic highspeed mode and start session */

  2212. musb_writeb(regs, MUSB_POWER, MUSB_POWER_SOFTCONN

  2213. | MUSB_POWER_HSENAB

  2214. /* ENSUSPEND wedges tusb */

  2215. | MUSB_POWER_ENSUSPEND);

  2216. } else {

  2217. /* put into basic fullspeed mode and start session */

  2218. musb_writeb(regs, MUSB_POWER, MUSB_POWER_SOFTCONN

  2219. /* ENSUSPEND wedges tusb */

  2220. | MUSB_POWER_ENSUSPEND);

  2221. }

  2222. musb->is_active = 1;

  2223. }

  2224. printk("[MUSB] USB connect\n");

  2225. }

  2226. }

  2227. }

  2228. #endif

  2229. battery_xlog_printk(BAT_LOG_CRTI, "[BAT_thread]Cable in, CHR_Type_num=%d\r\n", BMT_status.charger_type);

  2230. }

  2231. // 如果连接入的不是正常的充电线,或者此时 USB 接口以主机状态运行 ,则设置电池状态参数,断开 USB 连接?

  2232. else

  2233. {

  2234. wake_unlock(&battery_suspend_lock);

  2235. BMT_status.charger_exist = KAL_FALSE;

  2236. BMT_status.charger_type = CHARGER_UNKNOWN;

  2237. BMT_status.bat_full = KAL_FALSE;

  2238. BMT_status.bat_in_recharging_state = KAL_FALSE;

  2239. BMT_status.bat_charging_state = CHR_PRE;

  2240. BMT_status.total_charging_time = 0;

  2241. BMT_status.PRE_charging_time = 0;

  2242. BMT_status.CC_charging_time = 0;

  2243. BMT_status.TOPOFF_charging_time = 0;

  2244. BMT_status.POSTFULL_charging_time = 0;

  2245. battery_xlog_printk(BAT_LOG_CRTI, "[BAT_thread]Cable out \r\n");

  2246. // 断开 USB 与电脑的连接

  2247. mt_usb_disconnect();

  2248. void mt_usb_disconnect(void)

  2249. {

  2250. printk("[MUSB] USB is ready for disconnect\n");

  2251. if (!mtk_musb || !mtk_musb->is_ready || mtk_musb->is_host || !mtk_musb->power)

  2252. return;

  2253. musb_stop(mtk_musb);

  2254. if (wake_lock_active(&mtk_musb->usb_lock))

  2255. wake_unlock(&mtk_musb->usb_lock);

  2256. DBG(0,"cable_mode=%d\n",cable_mode);

  2257. if (cable_mode != CABLE_MODE_NORMAL) {

  2258. DBG(0,"musb_sync_with_bat, USB_SUSPEND\n");

  2259. musb_sync_with_bat(mtk_musb,USB_SUSPEND);

  2260. mtk_musb->power = false;

  2261. }

  2262. printk("[MUSB] USB disconnect\n");

  2263. }

  2264. }

  2265. }

  2266. ///

  2267. // 2. 通过具体的充电芯片来获得电池信息,充电信息, 获得电池电量百分比

  2268. /* 通过 oam 算法,获得电量百分比 */

  2269. mt_battery_GetBatteryData();

  2270. void mt_battery_GetBatteryData(void)

  2271. {

  2272. kal_uint32 bat_vol, charger_vol, Vsense, ZCV;

  2273. kal_int32 ICharging, temperature, temperatureR, temperatureV, SOC;

  2274. static kal_int32 bat_sum, icharging_sum, temperature_sum;

  2275. static kal_int32 batteryVoltageBuffer[BATTERY_AVERAGE_SIZE];

  2276. static kal_int32 batteryCurrentBuffer[BATTERY_AVERAGE_SIZE];

  2277. static kal_int32 batteryTempBuffer[BATTERY_AVERAGE_SIZE];

  2278. static kal_uint8 batteryIndex = 0;

  2279. static kal_int32 previous_SOC = -1;

  2280. // 获得 BATSNS 引脚电压

  2281. bat_vol = battery_meter_get_battery_voltage();

  2282. kal_int32 battery_meter_get_battery_voltage(void)

  2283. {

  2284. int ret=0;

  2285. int val=5;

  2286. val = 5; //set avg times

  2287. // 获得 PMIC 的 BATSNS 引脚电压

  2288. ret = battery_meter_ctrl(BATTERY_METER_CMD_GET_ADC_V_BAT_SENSE, &val);

  2289. static kal_int32 read_adc_v_bat_sense(void *data)

  2290. {

  2291. #if defined(CONFIG_POWER_EXT)

  2292. *(kal_int32*)(data) = 4201;

  2293. #else

  2294. *(kal_int32*)(data) = PMIC_IMM_GetOneChannelValue(VBAT_CHANNEL_NUMBER,*(kal_int32*)(data),1);

  2295. #endif

  2296. return STATUS_OK;

  2297. }

  2298. g_sw_vbat_temp = val;

  2299. return val;

  2300. }

  2301. /* 获得 PMIC 的 ISENSE 引脚电压*/

  2302. Vsense = battery_meter_get_VSense();

  2303. kal_int32 battery_meter_get_VSense(void)

  2304. {

  2305. #if defined(CONFIG_POWER_EXT)

  2306. return 0;

  2307. #else

  2308. int ret=0;

  2309. int val=0;

  2310. val = 1; //set avg times

  2311. /* 获得 PMIC 的 ISENSE 引脚电压*/

  2312. ret = battery_meter_ctrl(BATTERY_METER_CMD_GET_ADC_V_I_SENSE, &val);

  2313. read_adc_v_i_sense(void *data)

  2314. *(kal_int32*)(data) = PMIC_IMM_GetOneChannelValue(ISENSE_CHANNEL_NUMBER,*(kal_int32*)(data),1);

  2315. return val;

  2316. #endif

  2317. }

  2318. /* 获得充电电流 */

  2319. ICharging = battery_meter_get_charging_current();

  2320. kal_int32 battery_meter_get_charging_current(void)

  2321. {

  2322. kal_int32 ADC_BAT_SENSE_tmp[20]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};

  2323. kal_int32 ADC_BAT_SENSE_sum=0;

  2324. kal_int32 ADC_BAT_SENSE=0;

  2325. kal_int32 ADC_I_SENSE_tmp[20]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};

  2326. kal_int32 ADC_I_SENSE_sum=0;

  2327. kal_int32 ADC_I_SENSE=0;

  2328. int repeat=20;

  2329. int i=0;

  2330. int j=0;

  2331. kal_int32 temp=0;

  2332. int ICharging=0;

  2333. int ret=0;

  2334. int val=1;

  2335. for(i=0 ; i<repeat ; i++)

  2336. {

  2337. val = 1; //set avg times

  2338. /* 获得 PMIC 的 BATSNS 引脚电压 */

  2339. ret = battery_meter_ctrl(BATTERY_METER_CMD_GET_ADC_V_BAT_SENSE, &val);

  2340. read_adc_v_bat_sense(void *data)

  2341. *(kal_int32*)(data) = PMIC_IMM_GetOneChannelValue(VBAT_CHANNEL_NUMBER,*(kal_int32*)(data),1);

  2342. ADC_BAT_SENSE_tmp[i] = val;

  2343. val = 1; //set avg times

  2344. /* 获得 PMIC 的 ISENSE 引脚电压 */

  2345. ret = battery_meter_ctrl(BATTERY_METER_CMD_GET_ADC_V_I_SENSE, &val);

  2346. read_adc_v_i_sense(void *data)

  2347. *(kal_int32*)(data) = PMIC_IMM_GetOneChannelValue(ISENSE_CHANNEL_NUMBER,*(kal_int32*)(data),1);

  2348. ADC_I_SENSE_tmp[i] = val;

  2349. ADC_BAT_SENSE_sum += ADC_BAT_SENSE_tmp[i];

  2350. ADC_I_SENSE_sum += ADC_I_SENSE_tmp[i];

  2351. }

  2352. //sorting BAT_SENSE

  2353. for(i=0 ; i<repeat ; i++)

  2354. {

  2355. for(j=i; j<repeat ; j++)

  2356. {

  2357. if( ADC_BAT_SENSE_tmp[j] < ADC_BAT_SENSE_tmp[i] )

  2358. {

  2359. temp = ADC_BAT_SENSE_tmp[j];

  2360. ADC_BAT_SENSE_tmp[j] = ADC_BAT_SENSE_tmp[i];

  2361. ADC_BAT_SENSE_tmp[i] = temp;

  2362. }

  2363. }

  2364. }

  2365. bm_print(BM_LOG_FULL, "[g_Get_I_Charging:BAT_SENSE]\r\n");

  2366. for(i=0 ; i<repeat ; i++ )

  2367. {

  2368. bm_print(BM_LOG_FULL, "%d,", ADC_BAT_SENSE_tmp[i]);

  2369. }

  2370. bm_print(BM_LOG_FULL, "\r\n");

  2371. //sorting I_SENSE

  2372. for(i=0 ; i<repeat ; i++)

  2373. {

  2374. for(j=i ; j<repeat ; j++)

  2375. {

  2376. if( ADC_I_SENSE_tmp[j] < ADC_I_SENSE_tmp[i] )

  2377. {

  2378. temp = ADC_I_SENSE_tmp[j];

  2379. ADC_I_SENSE_tmp[j] = ADC_I_SENSE_tmp[i];

  2380. ADC_I_SENSE_tmp[i] = temp;

  2381. }

  2382. }

  2383. }

  2384. bm_print(BM_LOG_FULL, "[g_Get_I_Charging:I_SENSE]\r\n");

  2385. for(i=0 ; i<repeat ; i++ )

  2386. {

  2387. bm_print(BM_LOG_FULL, "%d,", ADC_I_SENSE_tmp[i]);

  2388. }

  2389. bm_print(BM_LOG_FULL, "\r\n");

  2390. ADC_BAT_SENSE_sum -= ADC_BAT_SENSE_tmp[0];

  2391. ADC_BAT_SENSE_sum -= ADC_BAT_SENSE_tmp[1];

  2392. ADC_BAT_SENSE_sum -= ADC_BAT_SENSE_tmp[18];

  2393. ADC_BAT_SENSE_sum -= ADC_BAT_SENSE_tmp[19];

  2394. ADC_BAT_SENSE = ADC_BAT_SENSE_sum / (repeat-4);

  2395. bm_print(BM_LOG_FULL, "[g_Get_I_Charging] ADC_BAT_SENSE=%d\r\n", ADC_BAT_SENSE);

  2396. ADC_I_SENSE_sum -= ADC_I_SENSE_tmp[0];

  2397. ADC_I_SENSE_sum -= ADC_I_SENSE_tmp[1];

  2398. ADC_I_SENSE_sum -= ADC_I_SENSE_tmp[18];

  2399. ADC_I_SENSE_sum -= ADC_I_SENSE_tmp[19];

  2400. ADC_I_SENSE = ADC_I_SENSE_sum / (repeat-4);

  2401. bm_print(BM_LOG_FULL, "[g_Get_I_Charging] ADC_I_SENSE(Before)=%d\r\n", ADC_I_SENSE);

  2402. bm_print(BM_LOG_FULL, "[g_Get_I_Charging] ADC_I_SENSE(After)=%d\r\n", ADC_I_SENSE);

  2403. if(ADC_I_SENSE > ADC_BAT_SENSE)

  2404. {

  2405. ICharging = (ADC_I_SENSE - ADC_BAT_SENSE + g_I_SENSE_offset)*1000/CUST_R_SENSE;

  2406. }

  2407. else

  2408. {

  2409. ICharging = 0;

  2410. }

  2411. return ICharging;

  2412. }

  2413. /* 获得充电器电压 */

  2414. charger_vol = battery_meter_get_charger_voltage();

  2415. kal_int32 battery_meter_get_charger_voltage(void)

  2416. {

  2417. int ret=0;

  2418. int val=0;

  2419. val = 5; // set avg times

  2420. ret = battery_meter_ctrl(BATTERY_METER_CMD_GET_ADC_V_CHARGER, &val);

  2421. static kal_int32 read_adc_v_charger(void *data)

  2422. {

  2423. #if defined(CONFIG_POWER_EXT)

  2424. *(kal_int32*)(data) = 5001;

  2425. #else

  2426. kal_int32 val;

  2427. /* 获取 PMIC 的 VCDT 引脚电压 */

  2428. val = PMIC_IMM_GetOneChannelValue(VCHARGER_CHANNEL_NUMBER,*(kal_int32*)(data),1);

  2429. val = (((R_CHARGER_1+R_CHARGER_2)*100*val)/R_CHARGER_2)/100;

  2430. *(kal_int32*)(data) = val;

  2431. #endif

  2432. return STATUS_OK;

  2433. }

  2434. //val = (((R_CHARGER_1+R_CHARGER_2)*100*val)/R_CHARGER_2)/100;

  2435. return val;

  2436. }

  2437. /* 通过获得当前 NTC 电压,查表并进行线性插值法,得到当前的温度值 */

  2438. temperature = battery_meter_get_battery_temperature();

  2439. return force_get_tbat();

  2440. /* 这里用来获取电池 NTC 的电压 */

  2441. temperatureV = battery_meter_get_tempV();

  2442. ret = battery_meter_ctrl(BATTERY_METER_CMD_GET_ADC_V_BAT_TEMP, &val);

  2443. static kal_int32 read_adc_v_bat_temp(void *data)

  2444. {

  2445. #if defined(CONFIG_POWER_EXT)

  2446. *(kal_int32*)(data) = 0;

  2447. #else

  2448. #if defined(MTK_PCB_TBAT_FEATURE)

  2449. int ret = 0, data[4], i, ret_value = 0, ret_temp = 0;

  2450. int Channel=1;

  2451. if( IMM_IsAdcInitReady() == 0 )

  2452. return g_adc_init_flag;

  2453. {

  2454. bm_print(BM_LOG_CRTI, "[get_tbat_volt] AUXADC is not ready");

  2455. return 0;

  2456. }

  2457. i = times;

  2458. while (i--)

  2459. {

  2460. ret_value = IMM_GetOneChannelValue(Channel, data, &ret_temp);

  2461. ret += ret_temp;

  2462. bm_print(BM_LOG_FULL, "[get_tbat_volt] ret_temp=%d\n",ret_temp);

  2463. }

  2464. ret = ret*1500/4096 ;

  2465. ret = ret/times;

  2466. bm_print(BM_LOG_CRTI, "[get_tbat_volt] Battery output mV = %d\n",ret);

  2467. *(kal_int32*)(data) = ret;

  2468. #else

  2469. bm_print(BM_LOG_FULL, "[read_adc_v_charger] return PMIC_IMM_GetOneChannelValue(4,times,1);\n");

  2470. /* 读取 PMIC 的 BATON1 引脚电压 */

  2471. *(kal_int32*)(data) = PMIC_IMM_GetOneChannelValue(VBATTEMP_CHANNEL_NUMBER,*(kal_int32*)(data),1);

  2472. #endif

  2473. #endif

  2474. return STATUS_OK;

  2475. }

  2476. /* 获得 下拉电阻与 NTC 并并联的电压 */

  2477. temperatureR = battery_meter_get_tempR(temperatureV);

  2478. /* 上拉电压/下拉电压 = 上拉电阻/ 下拉电阻 */

  2479. TRes = (RBAT_PULL_UP_R*dwVolt) / (RBAT_PULL_UP_VOLT-dwVolt);

  2480. /* bat_thread_wakeup() 每 10s 唤醒一次,唤醒时设置 bat_meter_timeout = KAL_TRUE

  2481. 这时候更新电池电量百分比 */

  2482. if(bat_meter_timeout == KAL_TRUE || bat_spm_timeout == TRUE)

  2483. {

  2484. /* oam 算法通过两种方式更新电压,去逼近真实的开路电压,最终查表获取近似真实的电量值百分比,方法 1,查表获得电池百分比,方法 2,库伦积分

  2485. 以方法2获得的参数补偿方法 1 的值,具体方法见 oam_run()*/

  2486. SOC = battery_meter_get_battery_percentage();

  2487. kal_int32 battery_meter_get_battery_percentage(void)

  2488. {

  2489. #if defined(CONFIG_POWER_EXT)

  2490. return 50;

  2491. #else

  2492. if(bat_is_charger_exist() == KAL_FALSE)

  2493. // 这里查询 PMIC 的 CHR_CON0 寄存器,检查充电状态

  2494. return get_charger_detect_status();

  2495. battery_charging_control(CHARGING_CMD_GET_CHARGER_DET_STATUS,&chr_status);

  2496. static kal_uint32 charging_get_charger_det_status(void *data)

  2497. {

  2498. kal_uint32 status = STATUS_OK;

  2499. #if defined(CHRDET_SW_MODE_EN)

  2500. kal_uint32 vchr_val=0;

  2501. vchr_val = PMIC_IMM_GetOneChannelValue(4,5,1);

  2502. vchr_val = (((330+39)*100*vchr_val)/39)/100;

  2503. if( vchr_val > 4300 )

  2504. {

  2505. battery_xlog_printk(BAT_LOG_FULL, "[CHRDET_SW_WORKAROUND_EN] upmu_is_chr_det=Y (%d)\n", vchr_val);

  2506. *(kal_uint32 *)data = KAL_TRUE;

  2507. }

  2508. else

  2509. {

  2510. battery_xlog_printk(BAT_LOG_FULL, "[CHRDET_SW_WORKAROUND_EN] upmu_is_chr_det=N (%d)\n", vchr_val);

  2511. *(kal_uint32 *)data = KAL_FALSE;

  2512. }

  2513. #else

  2514. *(kal_bool*)(data) = upmu_get_rgs_chrdet();

  2515. #endif

  2516. if( upmu_get_rgs_chrdet() == 0 )

  2517. g_charger_type = CHARGER_UNKNOWN;

  2518. return status;

  2519. }

  2520. fg_qmax_update_for_aging_flag = 1;

  2521. // AUX ADC算法指只依赖ADC读值,然后查表读取电量的算法

  2522. #if defined(SOC_BY_AUXADC)

  2523. return auxadc_algo_run();

  2524. #endif

  2525. //通过开路电压查表得到初始电量D0,后续电量通过电流积分累积,通用性强,依赖初始电量的精确度。

  2526. #if defined(SOC_BY_HW_FG)

  2527. if(g_auxadc_solution == 1)

  2528. {

  2529. return auxadc_algo_run();

  2530. }

  2531. else

  2532. {

  2533. fgauge_algo_run();

  2534. return gFG_capacity_by_c; // hw fg, //return gfg_percent_check_point; // voltage mode

  2535. }

  2536. #endif

  2537. /*//

  2538. 6582 平台用的计量方法【在 Battery_Charging_Introduction_for_customer_V1.0.pdf】

  2539. SW FG算法和HW FG算法。事实上MTK平台项目通常采用的是混合型算法。 */

  2540. #if defined(SOC_BY_SW_FG)

  2541. oam_run();

  2542. void oam_run(void)

  2543. {

  2544. /* SW FG的核心 在于 通过两种方式更新电压,去逼近真实开路电压 最终查表获取近似真实的电量值。

  2545. ocv1 被假定为开路电压

  2546. ocv2则是闭路电压,

  2547. D0 D1 D2 D3 D4 D5 代表不同的放电深度*/

  2548. int vol_bat=0;

  2549. //int vol_bat_hw_ocv=0;

  2550. //int d_hw_ocv=0;

  2551. int charging_current=0;

  2552. int ret=0;

  2553. //kal_uint32 now_time;

  2554. struct timespec now_time;

  2555. kal_int32 delta_time = 0;

  2556. //now_time = rtc_read_hw_time();

  2557. getrawmonotonic(&now_time);

  2558. //delta_time = now_time - last_oam_run_time;

  2559. delta_time = now_time.tv_sec - last_oam_run_time.tv_sec;

  2560. bm_print(BM_LOG_FULL, "[oam_run_time] last time=%d, now time=%d, delta time=%d\n",

  2561. last_oam_run_time.tv_sec, now_time.tv_sec, delta_time);

  2562. last_oam_run_time = now_time;

  2563. // Reconstruct table if temp changed;

  2564. fgauge_construct_table_by_temp();

  2565. void fgauge_construct_table_by_temp(void)

  2566. {

  2567. #if defined(CONFIG_POWER_EXT)

  2568. #else

  2569. kal_uint32 i;

  2570. static kal_int32 init_temp = KAL_TRUE;

  2571. static kal_int32 curr_temp, last_temp, avg_temp;

  2572. static kal_int32 battTempBuffer[TEMP_AVERAGE_SIZE];

  2573. static kal_int32 temperature_sum;

  2574. static kal_uint8 tempIndex = 0;

  2575. /* 通过获得当前 NTC 电压,查表并进行线性插值法,得到当前的温度值 */

  2576. curr_temp = battery_meter_get_battery_temperature();

  2577. // Temperature window init

  2578. if (init_temp == KAL_TRUE)

  2579. {

  2580. for (i=0; i<TEMP_AVERAGE_SIZE; i++)

  2581. {

  2582. battTempBuffer[i] = curr_temp;

  2583. }

  2584. last_temp = curr_temp;

  2585. temperature_sum = curr_temp * TEMP_AVERAGE_SIZE;

  2586. init_temp = KAL_FALSE;

  2587. }

  2588. // Temperature sliding window

  2589. temperature_sum -= battTempBuffer[tempIndex];

  2590. temperature_sum += curr_temp;

  2591. battTempBuffer[tempIndex] = curr_temp;

  2592. avg_temp = (temperature_sum)/TEMP_AVERAGE_SIZE;

  2593. if (avg_temp != last_temp)

  2594. {

  2595. bm_print(BM_LOG_FULL, "[fgauge_construct_table_by_temp] reconstruct table by temperature change from (%d) to (%d)\r\n", last_temp, avg_temp);

  2596. /* 获得 温度-电池内阻 表格*/

  2597. fgauge_construct_r_table_profile(curr_temp, fgauge_get_profile_r_table(TEMPERATURE_T));

  2598. /* 由当前温度,通过 温度-电池容量表格,获得对应的 温度-电池容量 数据,

  2599. 即能得到当前温度所对应的用掉的电池容量 */

  2600. fgauge_construct_battery_profile(curr_temp, fgauge_get_profile(TEMPERATURE_T));

  2601. last_temp = avg_temp;

  2602. }

  2603. tempIndex = (tempIndex+1)%TEMP_AVERAGE_SIZE;

  2604. #endif

  2605. }

  2606. vol_bat = 15; //set avg times

  2607. /* 获得 PMIC 的 BATSNS 寄存器值

  2608. 这里获得 v_bat 当前电池电压值,这是有负载时的电压值 */

  2609. ret = battery_meter_ctrl(BATTERY_METER_CMD_GET_ADC_V_BAT_SENSE, &vol_bat);

  2610. read_adc_v_bat_sense(void *data)

  2611. *(kal_int32*)(data) = PMIC_IMM_GetOneChannelValue(VBAT_CHANNEL_NUMBER,*(kal_int32*)(data),1);

  2612. //ret = battery_meter_ctrl(BATTERY_METER_CMD_GET_HW_OCV, &vol_bat_hw_ocv);

  2613. //d_hw_ocv = fgauge_read_d_by_v(vol_bat_hw_ocv);

  2614. /* 通过当前开路电压 - 负载时电压 = 当前电流 * 电池内阻

  2615. 获得当前电流值 */

  2616. oam_i_1 = (((oam_v_ocv_1-vol_bat)*1000)*10) / oam_r_1; //0.1mA

  2617. oam_i_2 = (((oam_v_ocv_2-vol_bat)*1000)*10) / oam_r_2; //0.1mA

  2618. /* 当前的变化电量值 = 当前电流 * 上次运行此函数到现在的时间 + 上次的电量值 */

  2619. oam_car_1 = (oam_i_1*delta_time/3600) + oam_car_1; //0.1mAh

  2620. oam_car_2 = (oam_i_2*delta_time/3600) + oam_car_2; //0.1mAh

  2621. /* 这里使用的就是库伦积分法:

  2622. D1 = D0 + (-CAR)/Cmax

  2623. 获得当前的电池容量百分比 */

  2624. oam_d_1 = oam_d0 + (oam_car_1*100/10)/gFG_BATT_CAPACITY_aging; // gFG_BATT_CAPACITY_aging: 当前温度对应的最大电池容量

  2625. if(oam_d_1 < 0) oam_d_1 = 0;

  2626. if(oam_d_1 > 100) oam_d_1 = 100;

  2627. oam_d_2 = oam_d0 + (oam_car_2*100/10)/gFG_BATT_CAPACITY_aging;

  2628. if(oam_d_2 < 0) oam_d_2 = 0;

  2629. if(oam_d_2 > 100) oam_d_2 = 100;

  2630. /*//

  2631. // 整个程序的核心在这里, 他使用了两种方法更新电量:

  2632. 1. 使用补偿过的闭路电压,查表获得电量 【返回给用户的】

  2633. 2. 使用软件库伦积分,得到电量值 【用来校正的】

  2634. 两个方法相对独立,但是在此处,方法 1 使用了 方法 2 的电流来进行较正!!!!!!!!!!

  2635. //

  2636. mtk_imp_tracking() 对闭合电压补偿后,当作开路电压使用

  2637. 通过对当前有负载的电池电压进行补偿,获得当前开路电压 */

  2638. oam_v_ocv_1 = vol_bat + mtk_imp_tracking(vol_bat, oam_i_2, 5);

  2639. // ============================================================ // SW FG

  2640. // 这个里面返回的是 I*R 的值,即 当前电流 * 当前负载

  2641. kal_int32 mtk_imp_tracking(kal_int32 ori_voltage, kal_int32 ori_current, kal_int32 recursion_time)

  2642. {

  2643. kal_int32 ret_compensate_value = 0;

  2644. kal_int32 temp_voltage_1 = ori_voltage; // 闭路电压

  2645. kal_int32 temp_voltage_2 = temp_voltage_1; // 开路电压,第一次 = 闭路电压,后来都是补偿过 IR 的

  2646. int i = 0;

  2647. /* 迭代 5 次,反复执行 闭合补偿得开路电压,开路电压查表得内阻,内阻补偿闭路电压 */

  2648. for(i=0 ; i < recursion_time ; i++)

  2649. {

  2650. /* 将闭路电压当做开路电压查内阻 */

  2651. gFG_resistance_bat = fgauge_read_r_bat_by_v(temp_voltage_2);

  2652. /* 算出 IR drop */

  2653. ret_compensate_value = ( (ori_current) * (gFG_resistance_bat + R_FG_VALUE)) / 1000;

  2654. // ret_compensate是int型变量 做除法时取整处理 会引入较大误差, 加上这个值使结果四舍五入

  2655. ret_compensate_value = (ret_compensate_value+(10/2)) / 10;

  2656. /* 开路电压 = 当前电压 + IR drop */

  2657. temp_voltage_2 = temp_voltage_1 + ret_compensate_value;

  2658. bm_print(BM_LOG_FULL, "[mtk_imp_tracking] temp_voltage_2=%d,temp_voltage_1=%d,ret_compensate_value=%d,gFG_resistance_bat=%d\n",

  2659. temp_voltage_2,temp_voltage_1,ret_compensate_value,gFG_resistance_bat);

  2660. }

  2661. /* 通过上面获得的开路电压查找最终内阻 */

  2662. gFG_resistance_bat = fgauge_read_r_bat_by_v(temp_voltage_2);

  2663. /* 算出 IR drop */

  2664. ret_compensate_value = ( (ori_current) * (gFG_resistance_bat + R_FG_VALUE + FG_METER_RESISTANCE)) / 1000;

  2665. /* 四舍五入 */

  2666. ret_compensate_value = (ret_compensate_value+(10/2)) / 10;

  2667. gFG_compensate_value = ret_compensate_value; // I*R 补偿负载

  2668. bm_print(BM_LOG_FULL, "[mtk_imp_tracking] temp_voltage_2=%d,temp_voltage_1=%d,ret_compensate_value=%d,gFG_resistance_bat=%d\n",

  2669. temp_voltage_2,temp_voltage_1,ret_compensate_value,gFG_resistance_bat);

  2670. /* 该内阻 R* 电流 I 算出最终的电压补偿值 V

  2671. Vbat 是闭路电压

  2672. SW ocv 是开路电压

  2673. Sw ocv = V + Vbat

  2674. */

  2675. return ret_compensate_value;

  2676. }

  2677. /* 通过补偿的开路电压,获得电池电量百分比 */

  2678. oam_d_3 = fgauge_read_d_by_v(oam_v_ocv_1);

  2679. if(oam_d_3 < 0) oam_d_3 = 0;

  2680. if(oam_d_3 > 100) oam_d_3 = 100;

  2681. /* 通过开路电压,获得电池内阻 */

  2682. oam_r_1 = fgauge_read_r_bat_by_v(oam_v_ocv_1);

  2683. /* 通过库伦积分获得的电池容量百分比,来获得电池开路电压*/

  2684. oam_v_ocv_2 = fgauge_read_v_by_d(oam_d_2);

  2685. /* 通过开路电压,获得电池内阻 */

  2686. oam_r_2 = fgauge_read_r_bat_by_v(oam_v_ocv_2);

  2687. #if 0

  2688. oam_d_4 = (oam_d_2+oam_d_3)/2;

  2689. #else

  2690. oam_d_4 = oam_d_3;

  2691. #endif

  2692. // 从上一次运行本函数到现在当前电量变化的值

  2693. gFG_columb = oam_car_2/10; //mAh

  2694. /* 判断充电状态 */

  2695. if( (oam_i_1 < 0) || (oam_i_2 < 0) )

  2696. gFG_Is_Charging = KAL_TRUE;

  2697. else

  2698. gFG_Is_Charging = KAL_FALSE;

  2699. #if 0

  2700. if(gFG_Is_Charging == KAL_FALSE)

  2701. {

  2702. d5_count_time = 60;

  2703. }

  2704. else

  2705. {

  2706. charging_current = get_charging_setting_current();

  2707. charging_current = charging_current / 100;

  2708. d5_count_time_rate = (((gFG_BATT_CAPACITY_aging*60*60/100/(charging_current-50))*10)+5)/10;

  2709. if(d5_count_time_rate < 1)

  2710. d5_count_time_rate = 1;

  2711. d5_count_time = d5_count_time_rate;

  2712. }

  2713. #else

  2714. d5_count_time = 60;

  2715. #endif

  2716. /

  2717. // D5 与 D3 对比

  2718. /* 对获得的 D3 进行优化,有 1min 的限制,不会跳变,电量变化更平滑

  2719. 1分钟内电量值不会改变,且每分钟电量的变化不会大于1%,这样用户体验会比较好。

  2720. 防止因为低电压时陡峭的电量曲线,以及比较耗电的应用,或突然的大电流引起的电量跳变。

  2721. 当然特殊应用下应该取消这个功能,否则会带来电量变化延时等问题*/

  2722. if(d5_count >= d5_count_time)

  2723. // 60s 执行一次

  2724. {

  2725. /* 限制电量变化,每 1 分钟,只能变化 1% */

  2726. /* 放电状态 */

  2727. if(gFG_Is_Charging == KAL_FALSE)

  2728. {

  2729. if( oam_d_3 > oam_d_5 )

  2730. {

  2731. oam_d_5 = oam_d_5 + 1;

  2732. }

  2733. else

  2734. {

  2735. if(oam_d_4 > oam_d_5)

  2736. {

  2737. oam_d_5 = oam_d_5 + 1;

  2738. }

  2739. }

  2740. }

  2741. /* 充电状态 */

  2742. else

  2743. {

  2744. if( oam_d_5 > oam_d_3 )

  2745. {

  2746. oam_d_5 = oam_d_5 - 1;

  2747. }

  2748. else

  2749. {

  2750. if(oam_d_4 < oam_d_5)

  2751. {

  2752. oam_d_5 = oam_d_5 - 1;

  2753. }

  2754. }

  2755. }

  2756. d5_count = 0;

  2757. oam_d_3_pre = oam_d_3;

  2758. oam_d_4_pre = oam_d_4;

  2759. }

  2760. else

  2761. // 10s 执行一次本函数

  2762. {

  2763. d5_count = d5_count + 10;

  2764. }

  2765. bm_print(BM_LOG_CRTI, "[oam_run] %d,%d,%d,%d,%d,%d,%d,%d\n",

  2766. d5_count, d5_count_time, oam_d_3_pre, oam_d_3, oam_d_4_pre, oam_d_4, oam_d_5, charging_current);

  2767. if(oam_run_i == 0)

  2768. {

  2769. bm_print(BM_LOG_FULL, "[oam_run] oam_i_1,oam_i_2,oam_car_1,oam_car_2,oam_d_1,oam_d_2,oam_v_ocv_1,oam_d_3,oam_r_1,oam_v_ocv_2,oam_r_2,vol_bat,g_vol_bat_hw_ocv,g_d_hw_ocv\n");

  2770. oam_run_i=1;

  2771. }

  2772. bm_print(BM_LOG_FULL, "[oam_run] %d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d\n",

  2773. oam_i_1,oam_i_2,oam_car_1,oam_car_2,oam_d_1,oam_d_2,oam_v_ocv_1,oam_d_3,oam_r_1,oam_v_ocv_2,oam_r_2,vol_bat,g_vol_bat_hw_ocv,g_d_hw_ocv);

  2774. bm_print(BM_LOG_FULL, "[oam_total] %d,%d,%d,%d,%d,%d,%d,%d,%d,%d\n",

  2775. gFG_capacity_by_c, gFG_capacity_by_v, gfg_percent_check_point,

  2776. oam_d_1, oam_d_2, oam_d_3, oam_d_4, oam_d_5, gFG_capacity_by_c_init, g_d_hw_ocv);

  2777. bm_print(BM_LOG_CRTI, "[oam_total_s] %d,%d,%d,%d,%d,%d,%d,%d,%d,%d\n",

  2778. gFG_capacity_by_c, // 1

  2779. gFG_capacity_by_v, // 2

  2780. gfg_percent_check_point, // 3

  2781. (100-oam_d_1), // 4

  2782. (100-oam_d_2), // 5

  2783. (100-oam_d_3), // 6

  2784. (100-oam_d_4), // 9

  2785. (100-oam_d_5), // 10

  2786. gFG_capacity_by_c_init, // 7

  2787. (100-g_d_hw_ocv) // 8

  2788. );

  2789. bm_print(BM_LOG_FULL, "[oam_total_s_err] %d,%d,%d,%d,%d,%d,%d\n",

  2790. (gFG_capacity_by_c - gFG_capacity_by_v),

  2791. (gFG_capacity_by_c - gfg_percent_check_point),

  2792. (gFG_capacity_by_c - (100-oam_d_1)),

  2793. (gFG_capacity_by_c - (100-oam_d_2)),

  2794. (gFG_capacity_by_c - (100-oam_d_3)),

  2795. (gFG_capacity_by_c - (100-oam_d_4)),

  2796. (gFG_capacity_by_c - (100-oam_d_5))

  2797. );

  2798. bm_print(BM_LOG_CRTI, "[oam_init_inf] %d, %d, %d, %d, %d, %d\n",

  2799. gFG_voltage, (100 - fgauge_read_capacity_by_v(gFG_voltage)), g_rtc_fg_soc, gFG_DOD0 ,oam_v_ocv_init, force_get_tbat());

  2800. bm_print(BM_LOG_CRTI, "[oam_run_inf] %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d\n",

  2801. oam_v_ocv_1,oam_v_ocv_2,vol_bat,oam_i_1,oam_i_2,oam_r_1,oam_r_2,oam_car_1,oam_car_2,gFG_BATT_CAPACITY_aging,force_get_tbat(), oam_d0);

  2802. bm_print(BM_LOG_CRTI, "[oam_result_inf] %d, %d, %d, %d, %d, %d\n",

  2803. oam_d_1, oam_d_2, oam_d_3, oam_d_4, oam_d_5, BMT_status.UI_SOC);

  2804. }

  2805. // 这边的返回值将填充BMT_status.SOC ,这个参数再经过优化得到BMT_status.UI_SOC就是菜单栏看到的电池电量了。

  2806. //

  2807. /* D5 是做过平滑,每 1min 电量变化只能是 1% 的,可能会有延时 */

  2808. #if (OAM_D5 == 1)

  2809. return (100-oam_d_5);

  2810. #else

  2811. /* D2 则是原版的,没有做平滑处理,电量变化可能会跳变,但是变化及时 */

  2812. return (100-oam_d_2);

  2813. #endif

  2814. #endif

  2815. #endif

  2816. }

  2817. bat_meter_timeout = KAL_FALSE;

  2818. bat_spm_timeout = FALSE;

  2819. }

  2820. else

  2821. {

  2822. if (previous_SOC == -1)

  2823. /* 通过两种方式更新电压,去逼近真实的开路电压,最终查表获取近似真实的电量值百分比 */

  2824. SOC = battery_meter_get_battery_percentage();

  2825. else

  2826. SOC = previous_SOC;

  2827. }

  2828. ZCV = battery_meter_get_battery_zcv();

  2829. return gFG_voltage; // 返回 hw ocv 电压

  2830. /* 更新电池状态 */

  2831. BMT_status.ICharging = mt_battery_average_method(&batteryCurrentBuffer[0],ICharging, &icharging_sum, batteryIndex);

  2832. BMT_status.bat_vol = mt_battery_average_method(&batteryVoltageBuffer[0],bat_vol, &bat_sum, batteryIndex);

  2833. BMT_status.temperature = mt_battery_average_method(&batteryTempBuffer[0],temperature, &temperature_sum, batteryIndex);

  2834. BMT_status.Vsense = Vsense;

  2835. BMT_status.charger_vol = charger_vol;

  2836. BMT_status.temperatureV = temperatureV;

  2837. BMT_status.temperatureR = temperatureR;

  2838. BMT_status.SOC = SOC;

  2839. BMT_status.ZCV = ZCV;

  2840. if(BMT_status.charger_exist == KAL_FALSE)

  2841. {

  2842. if(BMT_status.SOC > previous_SOC && previous_SOC >= 0)

  2843. BMT_status.SOC = previous_SOC;

  2844. }

  2845. previous_SOC = BMT_status.SOC;

  2846. batteryIndex++;

  2847. if (batteryIndex >= BATTERY_AVERAGE_SIZE)

  2848. batteryIndex = 0;

  2849. battery_xlog_printk(BAT_LOG_CRTI, "AvgVbat=(%d),bat_vol=(%d),AvgI=(%d),I=(%d),VChr=(%d),AvgT=(%d),T=(%d),pre_SOC=(%d),SOC=(%d),ZCV=(%d)\n",

  2850. BMT_status.bat_vol,bat_vol,BMT_status.ICharging,ICharging,BMT_status.charger_vol,BMT_status.temperature,temperature,previous_SOC,BMT_status.SOC,BMT_status.ZCV);

  2851. }

  2852. // 3. 电池温度保护

  2853. /* 电池温度检查,如果温度超过 60 度,关机重启 */

  2854. mt_battery_thermal_check();

  2855. static void mt_battery_thermal_check(void)

  2856. {

  2857. if( (g_battery_thermal_throttling_flag==1) || (g_battery_thermal_throttling_flag==3) )

  2858. {

  2859. if(battery_cmd_thermal_test_mode == 1){

  2860. BMT_status.temperature = battery_cmd_thermal_test_mode_value;

  2861. battery_xlog_printk(BAT_LOG_FULL, "[Battery] In thermal_test_mode , Tbat=%d\n", BMT_status.temperature);

  2862. }

  2863. #if defined(MTK_JEITA_STANDARD_SUPPORT)

  2864. //ignore default rule

  2865. #else

  2866. if(BMT_status.temperature >= 60)

  2867. {

  2868. #if defined(CONFIG_POWER_EXT)

  2869. battery_xlog_printk(BAT_LOG_CRTI, "[BATTERY] CONFIG_POWER_EXT, no update battery update power down.\n");

  2870. #else

  2871. {

  2872. if( (g_platform_boot_mode==META_BOOT) || (g_platform_boot_mode==ADVMETA_BOOT) || (g_platform_boot_mode==ATE_FACTORY_BOOT) )

  2873. {

  2874. battery_xlog_printk(BAT_LOG_FULL, "[BATTERY] boot mode = %d, bypass temperature check\n", g_platform_boot_mode);

  2875. }

  2876. else

  2877. // 正常启动的话,超过温度,系统重启

  2878. {

  2879. struct battery_data *bat_data = &battery_main;

  2880. struct power_supply *bat_psy = &bat_data->psy;

  2881. battery_xlog_printk(BAT_LOG_CRTI, "[Battery] Tbat(%d)>=60, system need power down.\n", BMT_status.temperature);

  2882. bat_data->BAT_CAPACITY = 0;

  2883. power_supply_changed(bat_psy);

  2884. if( BMT_status.charger_exist == KAL_TRUE )

  2885. {

  2886. // can not power down due to charger exist, so need reset system

  2887. //battery_charging_control(CHARGING_CMD_SET_PLATFORM_RESET,NULL);

  2888. }

  2889. //avoid SW no feedback

  2890. battery_charging_control(CHARGING_CMD_SET_POWER_OFF,NULL);

  2891. static kal_uint32 charging_set_power_off(void *data)

  2892. {

  2893. kal_uint32 status = STATUS_OK;

  2894. battery_xlog_printk(BAT_LOG_CRTI, "charging_set_power_off=%d\n");

  2895. /* */

  2896. mt_power_off();

  2897. void mt_power_off(void)

  2898. {

  2899. printk("mt_power_off\n");

  2900. /* pull PWRBB low */

  2901. rtc_bbpu_power_down();

  2902. void rtc_bbpu_power_down(void)

  2903. {

  2904. unsigned long flags;

  2905. spin_lock_irqsave(&rtc_lock, flags);

  2906. hal_rtc_bbpu_pwdn();

  2907. spin_unlock_irqrestore(&rtc_lock, flags);

  2908. }

  2909. while (1) {

  2910. #if defined(CONFIG_POWER_EXT)

  2911. //EVB

  2912. printk("EVB without charger\n");

  2913. #else

  2914. //Phone

  2915. printk("Phone with charger\n");

  2916. if (pmic_chrdet_status() == KAL_TRUE)

  2917. arch_reset(0, "power_off_with_charger");

  2918. #endif

  2919. }

  2920. }

  2921. return status;

  2922. }

  2923. //mt_power_off();

  2924. }

  2925. }

  2926. #endif

  2927. }

  2928. #endif

  2929. }

  2930. }

  2931. /

  2932. // 4. 电池状态检查

  2933. /* 对电池状态进行检查,如果有问题,则会调用 printk() 进行打印 */

  2934. mt_battery_notify_check();

  2935. void mt_battery_notify_check(void)

  2936. {

  2937. g_BatteryNotifyCode = 0x0000;

  2938. if(g_BN_TestMode == 0x0000) /* for normal case */

  2939. {

  2940. battery_xlog_printk(BAT_LOG_FULL, "[BATTERY] mt_battery_notify_check\n");

  2941. mt_battery_notify_VCharger_check();

  2942. mt_battery_notify_VBatTemp_check();

  2943. mt_battery_notify_ICharging_check();

  2944. mt_battery_notify_VBat_check();

  2945. mt_battery_notify_TatalChargingTime_check();

  2946. }

  2947. else /* for UI test */

  2948. {

  2949. mt_battery_notify_UI_test();

  2950. }

  2951. }

  2952. //

  2953. // 5. 调用具本的硬件相关函数进行充电,充电时会进行 CC/CV 之类的状态机切换就是在这里进行的

  2954. /* 如果存在充电线,则调用具体充电芯片相关的函数进行充电 */

  2955. if( BMT_status.charger_exist == KAL_TRUE )

  2956. {

  2957. /* 检查电池状态,设置到 BMT_status.bat_charging_state 中 */

  2958. mt_battery_CheckBatteryStatus();

  2959. /* 充电策略,这里有两个文件: switch_charging.c 和 linear_charging.c

  2960. 他们的关系是,如果定义了任一外部充电 IC,则选择 switch_charging.c 的函数,否则就是 linear_charging.c 的函数

  2961. 这里就是调用具体的芯片的充电相关函数进行充电 */

  2962. mt_battery_charging_algorithm();

  2963. void mt_battery_charging_algorithm()

  2964. {

  2965. switch(BMT_status.bat_charging_state)

  2966. {

  2967. case CHR_PRE :

  2968. BAT_PreChargeModeAction();

  2969. break;

  2970. case CHR_CC :

  2971. BAT_ConstantCurrentModeAction();

  2972. break;

  2973. case CHR_TOP_OFF :

  2974. BAT_TopOffModeAction();

  2975. break;

  2976. case CHR_BATFULL:

  2977. BAT_BatteryFullAction();

  2978. break;

  2979. case CHR_HOLD:

  2980. BAT_BatteryHoldAction();

  2981. break;

  2982. case CHR_ERROR:

  2983. BAT_BatteryStatusFailAction();

  2984. break;

  2985. }

  2986. }

  2987. }

  2988. ///

  2989. // 6. 更新电池显示状态

  2990. /* 更新设置节点的内容:

  2991. /sys/class/power_supply/下的文件夹

  2992. wireless_main

  2993. battery_main

  2994. ac_main

  2995. usb_main

  2996. */

  2997. mt_battery_update_status();

  2998. static void mt_battery_update_status(void)

  2999. {

  3000. #if defined(CONFIG_POWER_EXT)

  3001. battery_xlog_printk(BAT_LOG_CRTI, "[BATTERY] CONFIG_POWER_EXT, no update Android.\n");

  3002. #else

  3003. {

  3004. wireless_update(&wireless_main);

  3005. battery_update(&battery_main);

  3006. ac_update(&ac_main);

  3007. usb_update(&usb_main);

  3008. }

  3009. #endif

  3010. }

  3011. }

  3012. mutex_unlock(&bat_mutex);

  3013. battery_xlog_printk(BAT_LOG_FULL, "wait event \n" );

  3014. /* 睡眠等待唤醒 */

  3015. wait_event(bat_thread_wq, (bat_thread_timeout == KAL_TRUE));

  3016. bat_thread_timeout = KAL_FALSE;

  3017. /* 每 10s 启动一次 */

  3018. hrtimer_start(&battery_kthread_timer, ktime, HRTIMER_MODE_REL);

  3019. ktime = ktime_set(BAT_TASK_PERIOD, 0); // 10s, 10* 1000 ms

  3020. /* 如果有充电线插入且 xxx */

  3021. if( chr_wake_up_bat == KAL_TRUE && g_smartbook_update != 1) // for charger plug in/ out

  3022. {

  3023. g_smartbook_update = 0;

  3024. /* 重新计算当前电池电量,复位 oam 算法相关参数 */

  3025. battery_meter_reset();

  3026. kal_int32 battery_meter_reset(void)

  3027. {

  3028. #if defined(CONFIG_POWER_EXT)

  3029. return 0;

  3030. #else

  3031. /* 获得 ui 显示的百分比 */

  3032. kal_uint32 ui_percentage = bat_get_ui_percentage();

  3033. kal_uint32 bat_get_ui_percentage(void)

  3034. {

  3035. // for plugging out charger in recharge phase, using SOC as UI_SOC

  3036. if(chr_wake_up_bat == KAL_TRUE)

  3037. return BMT_status.SOC;

  3038. else

  3039. return BMT_status.UI_SOC;

  3040. // typedef struct

  3041. // {

  3042. // kal_bool bat_exist;

  3043. // kal_bool bat_full; // 电池是否充满标志

  3044. // INT32 bat_charging_state;

  3045. // UINT32 bat_vol;

  3046. // kal_bool bat_in_recharging_state;

  3047. // kal_uint32 Vsense;

  3048. // kal_bool charger_exist;

  3049. // UINT32 charger_vol;

  3050. // INT32 charger_protect_status;

  3051. // INT32 ICharging;

  3052. // INT32 IBattery;

  3053. // INT32 temperature;

  3054. // INT32 temperatureR;

  3055. // INT32 temperatureV;

  3056. // UINT32 total_charging_time;

  3057. // UINT32 PRE_charging_time;

  3058. // UINT32 CC_charging_time;

  3059. // UINT32 TOPOFF_charging_time;

  3060. // UINT32 POSTFULL_charging_time;

  3061. // UINT32 charger_type;

  3062. // INT32 SOC;

  3063. // INT32 UI_SOC; // ui 显示电量百分比

  3064. // UINT32 nPercent_ZCV;

  3065. // UINT32 nPrecent_UI_SOC_check_point;

  3066. // UINT32 ZCV;

  3067. // } PMU_ChargerStruct;

  3068. }

  3069. /*

  3070. // 如果电池充满了,则更新电池最大容量 */

  3071. if(bat_is_charging_full() == KAL_TRUE) // charge full

  3072. // 判断电池是否充满

  3073. kal_bool bat_is_charging_full(void)

  3074. {

  3075. if((BMT_status.bat_full == KAL_TRUE) && (BMT_status.bat_in_recharging_state == KAL_FALSE))

  3076. return KAL_TRUE;

  3077. else

  3078. return KAL_FALSE;

  3079. }

  3080. {

  3081. /* 如果 fg_qmax_update_for_aging_flag == 1

  3082. 则更新电池电容量,并将 fg_qmax_update_for_aging_flag 置为 0 */

  3083. if(fg_qmax_update_for_aging_flag == 1)

  3084. {

  3085. fg_qmax_update_for_aging();

  3086. void fg_qmax_update_for_aging(void)

  3087. {

  3088. #if defined(CONFIG_POWER_EXT)

  3089. #else

  3090. kal_bool hw_charging_done = bat_is_charging_full();

  3091. /* 如果电池充满了,更新电池最大容量 */

  3092. if(hw_charging_done == KAL_TRUE) // charging full, g_HW_Charging_Done == 1

  3093. {

  3094. /* gFG_DOD0 应该是 100%-ui 显示百分比

  3095. 即当前使用完的容量百分比 */

  3096. if(gFG_DOD0 > 85)

  3097. {

  3098. // 表示在放电

  3099. if(gFG_columb < 0) // gFG_columb: 从上一次运行本函数到现在当前电量变化的值

  3100. gFG_columb = gFG_columb - gFG_columb*2; // absolute value

  3101. gFG_BATT_CAPACITY_aging = ( ( (gFG_columb*1000)+(5*gFG_DOD0) ) / gFG_DOD0 ) / 10; // gFG_BATT_CAPACITY_aging: 当前温度电池最大容量

  3102. // tuning

  3103. gFG_BATT_CAPACITY_aging = (gFG_BATT_CAPACITY_aging * 100) / AGING_TUNING_VALUE;

  3104. /* 如果当前电池容量值为 0 */

  3105. if(gFG_BATT_CAPACITY_aging == 0)

  3106. {

  3107. /* 先通过 battery_meter_get_battery_temperature() 获得电池温度,再通过 fgauge_get_Q_max() 计算电量

  3108. 这里获得当前电池的容量 */

  3109. gFG_BATT_CAPACITY_aging = fgauge_get_Q_max(battery_meter_get_battery_temperature());

  3110. bm_print(BM_LOG_CRTI, "[fg_qmax_update_for_aging] error, restore gFG_BATT_CAPACITY_aging (%d)\n", gFG_BATT_CAPACITY_aging);

  3111. }

  3112. bm_print(BM_LOG_CRTI, "[fg_qmax_update_for_aging] need update : gFG_columb=%d, gFG_DOD0=%d, new_qmax=%d\r\n",

  3113. gFG_columb, gFG_DOD0, gFG_BATT_CAPACITY_aging);

  3114. }

  3115. else

  3116. {

  3117. bm_print(BM_LOG_CRTI, "[fg_qmax_update_for_aging] no update : gFG_columb=%d, gFG_DOD0=%d, new_qmax=%d\r\n",

  3118. gFG_columb, gFG_DOD0, gFG_BATT_CAPACITY_aging);

  3119. }

  3120. }

  3121. /* 如果电池未充满 */

  3122. else

  3123. {

  3124. bm_print(BM_LOG_CRTI, "[fg_qmax_update_for_aging] hw_charging_done=%d\r\n", hw_charging_done);

  3125. }

  3126. #endif

  3127. }

  3128. fg_qmax_update_for_aging_flag=0;

  3129. }

  3130. }

  3131. /* car: 库伦计的缩写

  3132. 这里是复位库伦计 */

  3133. reset_parameter_car();

  3134. void reset_parameter_car(void)

  3135. {

  3136. #if defined(SOC_BY_HW_FG)

  3137. int ret = 0;

  3138. /* 调用对应充电芯片的操作函数,复位硬件,这里对应 PMIC 的函数为 */

  3139. ret = battery_meter_ctrl(BATTERY_METER_CMD_HW_RESET, NULL);

  3140. static kal_int32 fgauge_hw_reset//(void *data)

  3141. {

  3142. return STATUS_OK;

  3143. }

  3144. gFG_columb = 0;

  3145. #endif

  3146. #if defined(SOC_BY_SW_FG)

  3147. oam_car_1 = 0;

  3148. oam_car_2 = 0;

  3149. gFG_columb = 0;

  3150. #endif

  3151. }

  3152. /* DOD: DOD: 放电深度,100-DOD 即电容容量 */

  3153. reset_parameter_dod_full(ui_percentage);

  3154. void reset_parameter_dod_full(kal_uint32 ui_percentage)

  3155. {

  3156. #if defined(SOC_BY_HW_FG)

  3157. bm_print(BM_LOG_CRTI, "[battery_meter_reset]1 DOD0=%d,DOD1=%d,ui=%d\n", gFG_DOD0, gFG_DOD1, ui_percentage);

  3158. gFG_DOD0 = 100 - ui_percentage;

  3159. gFG_DOD1 = gFG_DOD0;

  3160. bm_print(BM_LOG_CRTI, "[battery_meter_reset]2 DOD0=%d,DOD1=%d,ui=%d\n", gFG_DOD0, gFG_DOD1, ui_percentage);

  3161. #endif

  3162. // 我们用的是这种,软件库伦积分

  3163. #if defined(SOC_BY_SW_FG)

  3164. bm_print(BM_LOG_CRTI, "[battery_meter_reset]1 oam_d0=%d,oam_d_5=%d,ui=%d\n", oam_d0, oam_d_5, ui_percentage);

  3165. oam_d0 = 100 - ui_percentage;

  3166. gFG_DOD0 = oam_d0;

  3167. gFG_DOD1 = oam_d0;

  3168. oam_d_1 = oam_d0;

  3169. oam_d_2 = oam_d0;

  3170. oam_d_3 = oam_d0;

  3171. oam_d_4 = oam_d0;

  3172. oam_d_5 = oam_d0; // 相当于平滑处理过的 D3

  3173. bm_print(BM_LOG_CRTI, "[battery_meter_reset]2 oam_d0=%d,oam_d_5=%d,ui=%d\n", oam_d0, oam_d_5, ui_percentage);

  3174. #endif

  3175. }

  3176. return 0;

  3177. #endif

  3178. }

  3179. chr_wake_up_bat = KAL_FALSE;

  3180. battery_xlog_printk(BAT_LOG_CRTI, "[BATTERY] Charger plug in/out, Call battery_meter_reset. (%d)\n", BMT_status.UI_SOC);

  3181. }

  3182. }

  3183. return 0;

  3184. }

  3185. battery_xlog_printk(BAT_LOG_CRTI, "[battery_probe] bat_thread_kthread Done\n");

  3186. // 电池过充保护相关检测与初始化,他 2s 检测一次

  3187. charger_hv_detect_sw_workaround_init();

  3188. void charger_hv_detect_sw_workaround_init(void)

  3189. {

  3190. ktime_t ktime;

  3191. ktime = ktime_set(0, BAT_MS_TO_NS(2000));

  3192. hrtimer_init(&charger_hv_detect_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);

  3193. charger_hv_detect_timer.function = charger_hv_detect_sw_workaround;

  3194. hrtimer_start(&charger_hv_detect_timer, ktime, HRTIMER_MODE_REL);

  3195. // 这个函数是周期来检查电池电压是否超出限制,即过充保护,超出了就不能充电了

  3196. charger_hv_detect_thread = kthread_run(charger_hv_detect_sw_thread_handler, 0, "mtk charger_hv_detect_sw_workaround");

  3197. // 这个函数是周期来检查电池电压是否超出限制,即过充保护,超出了就不能充电了

  3198. int charger_hv_detect_sw_thread_handler(void *unused)

  3199. {

  3200. ktime_t ktime;

  3201. kal_uint32 charging_enable;

  3202. kal_uint32 hv_voltage = BATTERY_VOLT_07_000000_V;

  3203. kal_bool hv_status;

  3204. do

  3205. {

  3206. ktime = ktime_set(0, BAT_MS_TO_NS(2000));

  3207. if(chargin_hw_init_done)

  3208. /* 高压检测,应该是电池超过这个电压时,就不可以充电了 */

  3209. battery_charging_control(CHARGING_CMD_SET_HV_THRESHOLD,&hv_voltage);

  3210. static kal_uint32 charging_set_hv_threshold(void *data)

  3211. {

  3212. kal_uint32 status = STATUS_OK;

  3213. kal_uint32 set_hv_voltage;

  3214. kal_uint32 array_size;

  3215. kal_uint16 register_value;

  3216. kal_uint32 voltage = *(kal_uint32*)(data);

  3217. array_size = GETARRAYNUM(VCDT_HV_VTH);

  3218. set_hv_voltage = bmt_find_closest_level(VCDT_HV_VTH, array_size, voltage);

  3219. register_value = charging_parameter_to_value(VCDT_HV_VTH, array_size ,set_hv_voltage);

  3220. /* 设置 PMIC 的 CHR_CON1 */

  3221. upmu_set_rg_vcdt_hv_vth(register_value);

  3222. return status;

  3223. }

  3224. wait_event_interruptible(charger_hv_detect_waiter, (charger_hv_detect_flag == KAL_TRUE));

  3225. /* 如果检测到充电器,则检测下电池是否存在 */

  3226. if ((upmu_is_chr_det() == KAL_TRUE))

  3227. {

  3228. /* 检测电池是否存在 */

  3229. check_battery_exist();

  3230. void check_battery_exist(void)

  3231. {

  3232. #if defined(CONFIG_DIS_CHECK_BATTERY)

  3233. battery_xlog_printk(BAT_LOG_CRTI, "[BATTERY] Disable check battery exist.\n");

  3234. #else

  3235. kal_uint32 baton_count = 0;

  3236. kal_uint32 charging_enable = KAL_FALSE;

  3237. kal_uint32 battery_status;

  3238. kal_uint32 i;

  3239. for(i=0;i<3;i++)

  3240. {

  3241. /* 检测电池是否存在,通过读取 PMIC 的 CHR_CON7 */

  3242. battery_charging_control(CHARGING_CMD_GET_BATTERY_STATUS,&battery_status);

  3243. static kal_uint32 charging_get_battery_status(void *data)

  3244. {

  3245. kal_uint32 status = STATUS_OK;

  3246. upmu_set_baton_tdet_en(1);

  3247. upmu_set_rg_baton_en(1);

  3248. *(kal_bool*)(data) = upmu_get_rgs_baton_undet();

  3249. return status;

  3250. }

  3251. baton_count += battery_status;

  3252. }

  3253. if( baton_count >= 3)

  3254. {

  3255. if( (g_platform_boot_mode==META_BOOT) || (g_platform_boot_mode==ADVMETA_BOOT) || (g_platform_boot_mode==ATE_FACTORY_BOOT) )

  3256. {

  3257. battery_xlog_printk(BAT_LOG_FULL, "[BATTERY] boot mode = %d, bypass battery check\n", g_platform_boot_mode);

  3258. }

  3259. else

  3260. {

  3261. battery_xlog_printk(BAT_LOG_FULL, "[BATTERY] Battery is not exist, power off FAN5405 and system (%d)\n", baton_count);

  3262. //battery_charging_control(CHARGING_CMD_ENABLE,&charging_enable);

  3263. //battery_charging_control(CHARGING_CMD_SET_PLATFORM_RESET,NULL);

  3264. }

  3265. }

  3266. #endif

  3267. }

  3268. }

  3269. charger_hv_detect_flag = KAL_FALSE;

  3270. if(chargin_hw_init_done)

  3271. /* 查看 PMIC 是否开启了高压保护? */

  3272. battery_charging_control(CHARGING_CMD_GET_HV_STATUS,&hv_status);

  3273. static kal_uint32 charging_get_hv_status(void *data)

  3274. {

  3275. kal_uint32 status = STATUS_OK;

  3276. *(kal_bool*)(data) = upmu_get_rgs_vcdt_hv_det();

  3277. return status;

  3278. }

  3279. if(hv_status == KAL_TRUE)

  3280. {

  3281. battery_xlog_printk(BAT_LOG_CRTI, "[charger_hv_detect_sw_thread_handler] charger hv\n");

  3282. charging_enable = KAL_FALSE;

  3283. if(chargin_hw_init_done)

  3284. battery_charging_control(CHARGING_CMD_ENABLE,&charging_enable);

  3285. }

  3286. else

  3287. {

  3288. battery_xlog_printk(BAT_LOG_FULL, "[charger_hv_detect_sw_thread_handler] upmu_chr_get_vcdt_hv_det() != 1\n");

  3289. }

  3290. if(chargin_hw_init_done)

  3291. battery_charging_control(CHARGING_CMD_RESET_WATCH_DOG_TIMER,NULL);

  3292. hrtimer_start(&charger_hv_detect_timer, ktime, HRTIMER_MODE_REL);

  3293. } while (!kthread_should_stop());

  3294. return 0;

  3295. }

  3296. if (IS_ERR(charger_hv_detect_thread))

  3297. {

  3298. battery_xlog_printk(BAT_LOG_FULL, "[%s]: failed to create charger_hv_detect_sw_workaround thread\n", __FUNCTION__);

  3299. }

  3300. battery_xlog_printk(BAT_LOG_CRTI, "charger_hv_detect_sw_workaround_init : done\n" );

  3301. }

  3302. /*LOG System Set*/

  3303. init_proc_log();

  3304. #endif

  3305. g_bat_init_flag = KAL_TRUE;

  3306. return 0;

  3307. }

  3308. // 第二个调用的 probe

  3309. static int mt_batteryNotify_probe(struct platform_device *dev)

  3310. {

  3311. int ret_device_file = 0;

  3312. //struct proc_dir_entry *entry = NULL;

  3313. struct proc_dir_entry *battery_dir = NULL;

  3314. battery_xlog_printk(BAT_LOG_CRTI, "******** mt_batteryNotify_probe!! ********\n" );

  3315. ret_device_file = device_create_file(&(dev->dev), &dev_attr_BatteryNotify);

  3316. ret_device_file = device_create_file(&(dev->dev), &dev_attr_BN_TestMode);

  3317. battery_dir = proc_mkdir("mtk_battery_cmd", NULL);

  3318. if (!battery_dir)

  3319. {

  3320. pr_err("[%s]: mkdir /proc/mtk_battery_cmd failed\n", __FUNCTION__);

  3321. }

  3322. else

  3323. {

  3324. #if 1

  3325. proc_create("battery_cmd", S_IRUGO | S_IWUSR, battery_dir, &battery_cmd_proc_fops);

  3326. battery_xlog_printk(BAT_LOG_CRTI, "proc_create battery_cmd_proc_fops\n");

  3327. #else

  3328. entry = create_proc_entry("battery_cmd", S_IRUGO | S_IWUSR, battery_dir);

  3329. if (entry)

  3330. {

  3331. entry->read_proc = battery_cmd_read;

  3332. entry->write_proc = battery_cmd_write;

  3333. }

  3334. #endif

  3335. }

  3336. battery_xlog_printk(BAT_LOG_CRTI, "******** mtk_battery_cmd!! ********\n" );

  3337. return 0;

  3338. }

  3339. // 电池测量模块初始化

  3340. module_init(battery_meter_init);

  3341. static int __init battery_meter_init(void)

  3342. {

  3343. int ret;

  3344. ret = platform_device_register(&battery_meter_device);

  3345. struct platform_device battery_meter_device = {

  3346. .name = "battery_meter",

  3347. .id = -1,

  3348. };

  3349. if (ret) {

  3350. bm_print(BM_LOG_CRTI, "[battery_meter_driver] Unable to device register(%d)\n", ret);

  3351. return ret;

  3352. }

  3353. ret = platform_driver_register(&battery_meter_driver);

  3354. static struct platform_driver battery_meter_driver = {

  3355. .probe = battery_meter_probe,

  3356. .remove = battery_meter_remove,

  3357. .shutdown = battery_meter_shutdown,

  3358. .suspend = battery_meter_suspend,

  3359. .resume = battery_meter_resume,

  3360. .driver = {

  3361. .name = "battery_meter",

  3362. },

  3363. };

  3364. if (ret) {

  3365. bm_print(BM_LOG_CRTI, "[battery_meter_driver] Unable to register driver (%d)\n", ret);

  3366. return ret;

  3367. }

  3368. bm_print(BM_LOG_CRTI, "[battery_meter_driver] Initialization : DONE \n");

  3369. return 0;

  3370. }

  3371. /

  3372. // 调用的 probe

  3373. // ============================================================ //

  3374. static int battery_meter_probe(struct platform_device *dev)

  3375. {

  3376. int ret_device_file = 0;

  3377. battery_meter_ctrl = bm_ctrl_cmd;

  3378. bm_print(BM_LOG_CRTI, "[battery_meter_probe] probe\n");

  3379. //select battery meter control method

  3380. battery_meter_ctrl = bm_ctrl_cmd;

  3381. //LOG System Set

  3382. init_proc_log_fg();

  3383. //last_oam_run_time = rtc_read_hw_time();

  3384. getrawmonotonic(&last_oam_run_time);

  3385. //Create File For FG UI DEBUG

  3386. ret_device_file = device_create_file(&(dev->dev), &dev_attr_FG_Current);

  3387. ret_device_file = device_create_file(&(dev->dev), &dev_attr_FG_g_fg_dbg_bat_volt);

  3388. ret_device_file = device_create_file(&(dev->dev), &dev_attr_FG_g_fg_dbg_bat_current);

  3389. ret_device_file = device_create_file(&(dev->dev), &dev_attr_FG_g_fg_dbg_bat_zcv);

  3390. ret_device_file = device_create_file(&(dev->dev), &dev_attr_FG_g_fg_dbg_bat_temp);

  3391. ret_device_file = device_create_file(&(dev->dev), &dev_attr_FG_g_fg_dbg_bat_r);

  3392. ret_device_file = device_create_file(&(dev->dev), &dev_attr_FG_g_fg_dbg_bat_car);

  3393. ret_device_file = device_create_file(&(dev->dev), &dev_attr_FG_g_fg_dbg_bat_qmax);

  3394. ret_device_file = device_create_file(&(dev->dev), &dev_attr_FG_g_fg_dbg_d0);

  3395. ret_device_file = device_create_file(&(dev->dev), &dev_attr_FG_g_fg_dbg_d1);

  3396. ret_device_file = device_create_file(&(dev->dev), &dev_attr_FG_g_fg_dbg_percentage);

  3397. ret_device_file = device_create_file(&(dev->dev), &dev_attr_FG_g_fg_dbg_percentage_fg);

  3398. ret_device_file = device_create_file(&(dev->dev), &dev_attr_FG_g_fg_dbg_percentage_voltmode);

  3399. return 0;

  3400. }


 

什么!还要了解?请看源码

地址:链接: 百度网盘 请输入提取码 密码: uiyb

上一篇:koa2 快速入门


下一篇:koa-static的简单使用