ml5238.c 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257
  1. #include <string.h>
  2. #include "libs/shark_libs.h"
  3. #include "spi.h"
  4. #include "ml5238.h"
  5. static shark_timer_t irq_task;
  6. static int ml5238_read(uint8_t regaddr, uint8_t *data);
  7. static void ml5238_clear_bits(uint8_t regaddr, uint8_t bit);
  8. static void ml5238_set_bits(uint8_t regaddr, uint8_t bit);
  9. static void irq_hander_in_timer(shark_timer_t *timer);
  10. static ml5238_notify_hander _handler;
  11. void ml5238_init(void){
  12. spi0_init();
  13. ml5238_softreset();
  14. irq_task.handler = irq_hander_in_timer;
  15. }
  16. void ml5238_register_notify_handler(ml5238_notify_hander handler){
  17. _handler = handler;
  18. }
  19. //used to detect charger over current
  20. int ml5238_charger_is_open(void){
  21. uint8_t value = 0;
  22. ml5238_read(ML5238_PSENSE, &value);
  23. return !(value & PSENSE_PSL);
  24. }
  25. int ml5238_enable_load_detect(int enable){
  26. ml5238_clear_bits(ML5238_RSENSE, RSENSE_RRS);
  27. if (enable){
  28. ml5238_set_bits(ML5238_RSENSE, RSENSE_ERS);
  29. }else {
  30. ml5238_clear_bits(ML5238_RSENSE, RSENSE_ERS | RSENSE_IRS);
  31. }
  32. return 0;
  33. }
  34. int ml5238_is_load_disconnect(void){
  35. uint8_t value = 0;
  36. ml5238_read(ML5238_RSENSE, &value);
  37. return (value & RSENSE_RS);
  38. }
  39. #define IRS_IRQ 1 //load disconnectÖжÏ
  40. #define IPSL_IRQ 2 //charger over current
  41. #define ICS_IRQ 3 //¶Ì·ÖжÏ
  42. int ml5238_enable_irq(int enable, int irq){
  43. if (irq == IRS_IRQ){
  44. ml5238_clear_bits(ML5238_RSENSE, RSENSE_RRS);
  45. if (enable){
  46. ml5238_set_bits(ML5238_RSENSE, RSENSE_IRS);
  47. }else {
  48. ml5238_clear_bits(ML5238_RSENSE, RSENSE_IRS);
  49. }
  50. }
  51. if (irq == IPSL_IRQ){
  52. ml5238_clear_bits(ML5238_PSENSE, PSENSE_RPSL);
  53. if (enable){
  54. ml5238_set_bits(ML5238_PSENSE, PSENSE_IPSL);
  55. }else {
  56. ml5238_clear_bits(ML5238_PSENSE, PSENSE_IPSL);
  57. }
  58. }
  59. if (irq == ICS_IRQ){
  60. ml5238_clear_bits(ML5238_RSENSE, RSENSE_RSC);
  61. if (enable){
  62. ml5238_set_bits(ML5238_RSENSE, RSENSE_ISC);
  63. }else {
  64. ml5238_clear_bits(ML5238_RSENSE, RSENSE_ISC);
  65. }
  66. }
  67. return 0;
  68. }
  69. int ml5238_enable_charger_detect(int enable){
  70. uint8_t fet = 0;
  71. ml5238_read(ML5238_FET, &fet);
  72. if (fet & FET_DF){ //discharger is on, used to detect charger over current
  73. ml5238_clear_bits(ML5238_PSENSE, PSENSE_RPSL);
  74. if (enable){
  75. ml5238_set_bits(ML5238_PSENSE, PSENSE_EPSL);
  76. }else {
  77. ml5238_clear_bits(ML5238_PSENSE, PSENSE_EPSL);
  78. }
  79. }else { //discharger if off, used when powerdown, charger is insert
  80. ml5238_clear_bits(ML5238_PSENSE, PSENSE_RPSH);
  81. if (enable){
  82. ml5238_set_bits(ML5238_PSENSE, PSENSE_EPSH);
  83. }else {
  84. ml5238_clear_bits(ML5238_PSENSE, PSENSE_EPSH);
  85. }
  86. }
  87. return 0;
  88. }
  89. static int __inline__ _charger_mosfet_is_open(void){
  90. uint8_t data;
  91. ml5238_read(ML5238_FET, &data);
  92. return (data & FET_CF) != 0;
  93. }
  94. static int __inline__ _discharger_mosfet_is_open(void){
  95. uint8_t data;
  96. ml5238_read(ML5238_FET, &data);
  97. return (data & FET_DF) != 0;
  98. }
  99. void ml5238_cell_start_balance(uint16_t balance_mask){
  100. ml5238_write(ML5238_CBALH, (balance_mask >> 8) & 0xFF);
  101. ml5238_write(ML5238_CBALL, balance_mask & 0xFF);
  102. }
  103. int ml5238_enable_discharger_mosfet(int enable){
  104. uint8_t data;
  105. if (ml5238_read(ML5238_FET, &data) == 0){
  106. if ((data & FET_DF) == enable){
  107. return 0; //alread enable/disabled
  108. }
  109. data &= ~(FET_DF);
  110. if (enable){
  111. data |= (FET_DF | FET_DRV);
  112. }else {
  113. if ((data & FET_CF) == 0){
  114. data &= ~(FET_DRV);
  115. }
  116. }
  117. return ml5238_write(ML5238_FET, data);
  118. }
  119. return -1;
  120. }
  121. /* when enable charger the discharger mosfet also must be enabled for charging */
  122. int ml5238_enable_charger_mosfet(int enable){
  123. uint8_t data;
  124. if (ml5238_read(ML5238_FET, &data) == 0){
  125. if (((data & FET_CF) >> 1) == enable){
  126. return 0; //alread enable/disabled
  127. }
  128. data &= ~(FET_CF);
  129. if (enable){
  130. data |= (FET_CF | FET_DRV);
  131. }else {
  132. if ((data & FET_DF) == 0){
  133. data &= ~(FET_DRV);
  134. }
  135. }
  136. return ml5238_write(ML5238_FET, data);
  137. }
  138. return -1;
  139. }
  140. int ml5238_short_current_detect(int mode){
  141. uint8_t rsense = 0;
  142. if (mode >= SHORT_CURRENT_MODE_33_3A){
  143. if (ml5238_read(ML5238_RSENSE, &rsense) == 0){
  144. if (ml5238_write(ML5238_SETSC, mode) == 0){
  145. if (rsense & (RSENSE_ESC | RSENSE_ISC)){
  146. return 0; //already enabled short current detect
  147. }
  148. rsense |= (RSENSE_ESC | RSENSE_ISC);//enable short current detect && irq
  149. rsense &= ~RSENSE_RSC;
  150. return ml5238_write(ML5238_SETSC, rsense);
  151. }
  152. }
  153. }else {
  154. if (ml5238_read(ML5238_RSENSE, &rsense) == 0){
  155. if ((rsense & RSENSE_ESC) == 0){
  156. return 0; //already disabled
  157. }
  158. rsense &= ~(RSENSE_ESC|RSENSE_ISC|RSENSE_RSC);
  159. return ml5238_write(ML5238_SETSC, rsense);
  160. }
  161. }
  162. return -1;
  163. }
  164. void ml5238_softreset(void)
  165. {
  166. unsigned char i;
  167. for(i=0u;i<0x0Au;i++)
  168. {
  169. ml5238_write((uint8_t)(ML5238_VMON + i), 0x00u);
  170. }
  171. }
  172. static void __inline__ call_handler(int event){
  173. if (_handler) {
  174. _handler(event);
  175. }
  176. }
  177. static void irq_hander_in_timer(shark_timer_t *timer){
  178. uint8_t status = 0;
  179. ml5238_read(ML5238_STATUS, &status);
  180. if (status & STATUS_RPSL){//chargering over current
  181. ml5238_enable_charger_detect(0);
  182. call_handler(ML5238_Event_Charger_Over_Current);
  183. }
  184. if (status & STATUS_RSC) { //short current detect, close charger/discharger mosfet
  185. if (_charger_mosfet_is_open()) {
  186. ml5238_enable_charger_mosfet(0);
  187. }
  188. if (_discharger_mosfet_is_open()) {
  189. ml5238_enable_discharger_mosfet(0);
  190. }
  191. ml5238_enable_irq(0, ICS_IRQ); //disable short current detect
  192. call_handler(ML5238_Event_Short_Current);
  193. }
  194. if (status & STATUS_RRS) {//load disconnect, if short detect, we must wait load disconnected, and then can open discharger
  195. ml5238_enable_irq(0, IRS_IRQ);
  196. call_handler(ML5238_Event_Load_Disconnect);
  197. }
  198. }
  199. void ml5238_irq_handler(void){
  200. shark_timer_post(&irq_task, 0);
  201. }
  202. static void ml5238_set_bits(uint8_t regaddr, uint8_t bit) {
  203. uint8_t value;
  204. ml5238_read(regaddr, &value);
  205. ml5238_write(regaddr, value|bit);
  206. }
  207. static void ml5238_clear_bits(uint8_t regaddr, uint8_t bit) {
  208. uint8_t value;
  209. ml5238_read(regaddr, &value);
  210. ml5238_write(regaddr, value&(~bit));
  211. }
  212. int ml5238_write(uint8_t regaddr, uint8_t data){
  213. uint16_t send_data=(((uint16_t)regaddr)<<(0x09))|((uint16_t)data);
  214. ml5238_cs(0);
  215. int ret = spi0_send_uint16(send_data, NULL);
  216. ml5238_cs(1);
  217. return ret;
  218. }
  219. static int ml5238_read(uint8_t regaddr, uint8_t *data){
  220. uint16_t send_data=((((uint16_t)regaddr)<<(0x09))|0x0100u)|((uint16_t)0x00u);
  221. ml5238_cs(0);
  222. int ret = spi0_send_uint16(send_data, data);
  223. ml5238_cs(1);
  224. return ret;
  225. }