bq24261.c 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143
  1. #include <linux/interrupt.h>
  2. #include <linux/i2c.h>
  3. #include <linux/irq.h>
  4. #include <linux/delay.h>
  5. #include <linux/input.h>
  6. #include <linux/workqueue.h>
  7. #include <linux/platform_device.h>
  8. #include <asm/atomic.h>
  9. #ifdef CONFIG_OF
  10. #include <linux/of.h>
  11. #include <linux/of_irq.h>
  12. #include <linux/of_address.h>
  13. #endif
  14. #include "bq24261.h"
  15. #include "mt_charging.h"
  16. #include <mt-plat/upmu_common.h>
  17. #include <mt-plat/mt_reboot.h>
  18. #include <mt-plat/mt_boot.h>
  19. #define STATUS_OK 0
  20. #define STATUS_UNSUPPORTED -1
  21. /**********************************************************
  22. *
  23. * [I2C Slave Setting]
  24. *
  25. *********************************************************/
  26. #define bq24261_SLAVE_ADDR_WRITE 0xD6
  27. #define bq24261_SLAVE_ADDR_Read 0xD7
  28. /**********************************************************
  29. *
  30. * [Global Variable]
  31. *
  32. *********************************************************/
  33. static u8 bq24261_reg[bq24261_REG_NUM] = { 0 };
  34. static int g_bq24261_hw_exist;
  35. static struct i2c_client *new_client;
  36. static DEFINE_MUTEX(bq24261_i2c_access);
  37. static const u32 INPUT_CS_VTH[] = {
  38. CHARGE_CURRENT_100_00_MA, CHARGE_CURRENT_150_00_MA, CHARGE_CURRENT_500_00_MA,
  39. CHARGE_CURRENT_900_00_MA,
  40. CHARGE_CURRENT_1500_00_MA, CHARGE_CURRENT_1950_00_MA, CHARGE_CURRENT_2500_00_MA,
  41. CHARGE_CURRENT_2000_00_MA,
  42. CHARGE_CURRENT_MAX
  43. };
  44. /* for MT6391 */
  45. static const u32 VCDT_HV_VTH[] = {
  46. BATTERY_VOLT_04_000000_V, BATTERY_VOLT_04_100000_V, BATTERY_VOLT_04_150000_V,
  47. BATTERY_VOLT_04_200000_V,
  48. BATTERY_VOLT_04_250000_V, BATTERY_VOLT_04_300000_V, BATTERY_VOLT_04_350000_V,
  49. BATTERY_VOLT_04_400000_V,
  50. BATTERY_VOLT_04_450000_V, BATTERY_VOLT_04_500000_V, BATTERY_VOLT_04_550000_V,
  51. BATTERY_VOLT_04_600000_V,
  52. BATTERY_VOLT_07_000000_V, BATTERY_VOLT_07_500000_V, BATTERY_VOLT_08_500000_V,
  53. BATTERY_VOLT_10_500000_V
  54. };
  55. /**********************************************************
  56. *
  57. * [I2C Function For Read/Write bq24261]
  58. *
  59. *********************************************************/
  60. int bq24261_read_byte(u8 cmd, u8 *data)
  61. {
  62. int ret;
  63. struct i2c_msg msg[2];
  64. if (!new_client) {
  65. pr_err("error: access bq24261 before driver ready\n");
  66. return 0;
  67. }
  68. msg[0].addr = new_client->addr;
  69. msg[0].buf = &cmd;
  70. msg[0].flags = 0;
  71. msg[0].len = 1;
  72. msg[1].addr = new_client->addr;
  73. msg[1].buf = data;
  74. msg[1].flags = I2C_M_RD;
  75. msg[1].len = 1;
  76. ret = i2c_transfer(new_client->adapter, msg, 2);
  77. if (ret != 2)
  78. pr_err("%s: err=%d\n", __func__, ret);
  79. return ret == 2 ? 1 : 0;
  80. }
  81. int bq24261_write_byte(u8 cmd, u8 data)
  82. {
  83. char buf[2];
  84. int ret;
  85. if (!new_client) {
  86. pr_err("error: access bq24261 before driver ready\n");
  87. return 0;
  88. }
  89. buf[0] = cmd;
  90. buf[1] = data;
  91. ret = i2c_master_send(new_client, buf, 2);
  92. if (ret != 2)
  93. pr_err("%s: err=%d\n", __func__, ret);
  94. return ret == 2 ? 1 : 0;
  95. }
  96. u32 bq24261_read_interface(u8 RegNum, u8 *val, u8 MASK, u8 SHIFT)
  97. {
  98. u8 bq24261_reg = 0;
  99. u32 ret = 0;
  100. ret = bq24261_read_byte(RegNum, &bq24261_reg);
  101. bq24261_reg &= (MASK << SHIFT);
  102. *val = (bq24261_reg >> SHIFT);
  103. return ret;
  104. }
  105. u32 bq24261_config_interface(u8 RegNum, u8 val, u8 MASK, u8 SHIFT)
  106. {
  107. u8 bq24261_reg = 0;
  108. u32 ret = 0;
  109. ret = bq24261_read_byte(RegNum, &bq24261_reg);
  110. bq24261_reg &= ~(MASK << SHIFT);
  111. bq24261_reg |= (val << SHIFT);
  112. if (RegNum == bq24261_CON1 && val == 1 && MASK == CON1_RESET_MASK
  113. && SHIFT == CON1_RESET_SHIFT) {
  114. /* read RESET bit */
  115. } else if (RegNum == bq24261_CON1)
  116. bq24261_reg &= ~0x80; /* RESET bit read always return 1, need clear it */
  117. ret = bq24261_write_byte(RegNum, bq24261_reg);
  118. return ret;
  119. }
  120. /**********************************************************
  121. *
  122. * [Internal Function]
  123. *
  124. *********************************************************/
  125. /* CON0---------------------------------------------------- */
  126. void bq24261_set_tmr_rst(u32 val)
  127. {
  128. u32 ret = 0;
  129. ret = bq24261_config_interface((u8) (bq24261_CON0),
  130. (u8) (val),
  131. (u8) (CON0_TMR_RST_MASK), (u8) (CON0_TMR_RST_SHIFT)
  132. );
  133. }
  134. void bq24261_set_en_boost(u32 val)
  135. {
  136. u32 ret = 0;
  137. ret = bq24261_config_interface((u8) (bq24261_CON0),
  138. (u8) (val),
  139. (u8) (CON0_EN_BOOST_MASK), (u8) (CON0_EN_BOOST_SHIFT)
  140. );
  141. }
  142. u32 bq24261_get_stat(void)
  143. {
  144. u32 ret = 0;
  145. u8 val = 0;
  146. ret = bq24261_read_interface((u8) (bq24261_CON0),
  147. (&val), (u8) (CON0_STAT_MASK), (u8) (CON0_STAT_SHIFT)
  148. );
  149. return val;
  150. }
  151. void bq24261_set_en_shipmode(u32 val)
  152. {
  153. u32 ret = 0;
  154. ret = bq24261_config_interface((u8) (bq24261_CON0),
  155. (u8) (val),
  156. (u8) (CON0_EN_SHIPMODE_MASK), (u8) (CON0_EN_SHIPMODE_SHIFT)
  157. );
  158. }
  159. u32 bq24261_get_fault(void)
  160. {
  161. u32 ret = 0;
  162. u8 val = 0;
  163. ret = bq24261_read_interface((u8) (bq24261_CON0),
  164. (&val), (u8) (CON0_FAULT_MASK), (u8) (CON0_FAULT_SHIFT)
  165. );
  166. return val;
  167. }
  168. /* CON1---------------------------------------------------- */
  169. void bq24261_set_reset(u32 val)
  170. {
  171. u32 ret = 0;
  172. ret = bq24261_config_interface((u8) (bq24261_CON1),
  173. (u8) (val), (u8) (CON1_RESET_MASK), (u8) (CON1_RESET_SHIFT)
  174. );
  175. }
  176. u32 bq24261_get_in_limit(void)
  177. {
  178. u32 ret = 0;
  179. u8 val = 0;
  180. ret = bq24261_read_interface((u8) (bq24261_CON1),
  181. (&val), (u8) (CON1_IN_LIMIT_MASK), (u8) (CON1_IN_LIMIT_SHIFT)
  182. );
  183. return val;
  184. }
  185. void bq24261_set_in_limit(u32 val)
  186. {
  187. u32 ret = 0;
  188. ret = bq24261_config_interface((u8) (bq24261_CON1),
  189. (u8) (val),
  190. (u8) (CON1_IN_LIMIT_MASK), (u8) (CON1_IN_LIMIT_SHIFT)
  191. );
  192. }
  193. void bq24261_set_en_stat(u32 val)
  194. {
  195. u32 ret = 0;
  196. ret = bq24261_config_interface((u8) (bq24261_CON1),
  197. (u8) (val),
  198. (u8) (CON1_EN_STAT_MASK), (u8) (CON1_EN_STAT_SHIFT)
  199. );
  200. }
  201. void bq24261_set_te(u32 val)
  202. {
  203. u32 ret = 0;
  204. ret = bq24261_config_interface((u8) (bq24261_CON1),
  205. (u8) (val), (u8) (CON1_TE_MASK), (u8) (CON1_TE_SHIFT)
  206. );
  207. }
  208. void bq24261_set_dis_ce(u32 val)
  209. {
  210. u32 ret = 0;
  211. ret = bq24261_config_interface((u8) (bq24261_CON1),
  212. (u8) (val), (u8) (CON1_DIS_CE_MASK), (u8) (CON1_DIS_CE_SHIFT)
  213. );
  214. }
  215. void bq24261_set_hz_mode(u32 val)
  216. {
  217. u32 ret = 0;
  218. ret = bq24261_config_interface((u8) (bq24261_CON1),
  219. (u8) (val),
  220. (u8) (CON1_HZ_MODE_MASK), (u8) (CON1_HZ_MODE_SHIFT)
  221. );
  222. }
  223. /* CON2---------------------------------------------------- */
  224. void bq24261_set_vbreg(u32 val)
  225. {
  226. u32 ret = 0;
  227. ret = bq24261_config_interface((u8) (bq24261_CON2),
  228. (u8) (val), (u8) (CON2_VBREG_MASK), (u8) (CON2_VBREG_SHIFT)
  229. );
  230. }
  231. void bq24261_set_mod_freq(u32 val)
  232. {
  233. u32 ret = 0;
  234. ret = bq24261_config_interface((u8) (bq24261_CON2),
  235. (u8) (val),
  236. (u8) (CON2_MOD_FREQ_MASK), (u8) (CON2_MOD_FREQ_SHIFT)
  237. );
  238. }
  239. /* CON3---------------------------------------------------- */
  240. u32 bq24261_get_vender_code(void)
  241. {
  242. u32 ret = 0;
  243. u8 val = 0;
  244. ret = bq24261_read_interface((u8) (bq24261_CON3),
  245. (&val),
  246. (u8) (CON3_VENDER_CODE_MASK), (u8) (CON3_VENDER_CODE_SHIFT)
  247. );
  248. return val;
  249. }
  250. u32 bq24261_get_pn(void)
  251. {
  252. u32 ret = 0;
  253. u8 val = 0;
  254. ret = bq24261_read_interface((u8) (bq24261_CON3),
  255. (&val), (u8) (CON3_PN_MASK), (u8) (CON3_PN_SHIFT)
  256. );
  257. return val;
  258. }
  259. /* CON4---------------------------------------------------- */
  260. u32 bq24261_get_ichg(void)
  261. {
  262. u32 ret = 0;
  263. u8 val = 0;
  264. ret = bq24261_read_interface((u8) (bq24261_CON4),
  265. (&val), (u8) (CON4_ICHRG_MASK), (u8) (CON4_ICHRG_SHIFT)
  266. );
  267. return val;
  268. }
  269. void bq24261_set_ichg(u32 val)
  270. {
  271. u32 ret = 0;
  272. ret = bq24261_config_interface((u8) (bq24261_CON4),
  273. (u8) (val), (u8) (CON4_ICHRG_MASK), (u8) (CON4_ICHRG_SHIFT)
  274. );
  275. }
  276. void bq24261_set_iterm(u32 val)
  277. {
  278. u32 ret = 0;
  279. ret = bq24261_config_interface((u8) (bq24261_CON4),
  280. (u8) (val), (u8) (CON4_ITERM_MASK), (u8) (CON4_ITERM_SHIFT)
  281. );
  282. }
  283. /* CON5---------------------------------------------------- */
  284. u32 bq24261_get_minsys_status(void)
  285. {
  286. u32 ret = 0;
  287. u8 val = 0;
  288. ret = bq24261_read_interface((u8) (bq24261_CON5),
  289. (&val),
  290. (u8) (CON5_MINSYS_STATUS_MASK), (u8) (CON5_MINSYS_STATUS_SHIFT)
  291. );
  292. return val;
  293. }
  294. u32 bq24261_get_vindpm_status(void)
  295. {
  296. u32 ret = 0;
  297. u8 val = 0;
  298. ret = bq24261_read_interface((u8) (bq24261_CON5),
  299. (&val),
  300. (u8) (CON5_VINDPM_STATUS_MASK), (u8) (CON5_VINDPM_STATUS_SHIFT)
  301. );
  302. return val;
  303. }
  304. u32 bq24261_get_low_chg(void)
  305. {
  306. u32 ret = 0;
  307. u8 val = 0;
  308. ret = bq24261_read_interface((u8) (bq24261_CON5),
  309. (&val), (u8) (CON5_LOW_CHG_MASK), (u8) (CON5_LOW_CHG_SHIFT)
  310. );
  311. return val;
  312. }
  313. void bq24261_set_low_chg(u32 val)
  314. {
  315. u32 ret = 0;
  316. ret = bq24261_config_interface((u8) (bq24261_CON5),
  317. (u8) (val),
  318. (u8) (CON5_LOW_CHG_MASK), (u8) (CON5_LOW_CHG_SHIFT)
  319. );
  320. }
  321. void bq24261_set_dpdm_en(u32 val)
  322. {
  323. u32 ret = 0;
  324. ret = bq24261_config_interface((u8) (bq24261_CON5),
  325. (u8) (val),
  326. (u8) (CON5_DPDM_EN_MASK), (u8) (CON5_DPDM_EN_SHIFT)
  327. );
  328. }
  329. u32 bq24261_get_cd_status(void)
  330. {
  331. u32 ret = 0;
  332. u8 val = 0;
  333. ret = bq24261_read_interface((u8) (bq24261_CON5),
  334. (&val), (u8) (CON5_CD_STATUS_MASK), (u8) (CON5_CD_STATUS_SHIFT)
  335. );
  336. return val;
  337. }
  338. void bq24261_set_vindpm(u32 val)
  339. {
  340. u32 ret = 0;
  341. ret = bq24261_config_interface((u8) (bq24261_CON5),
  342. (u8) (val), (u8) (CON5_VINDPM_MASK), (u8) (CON5_VINDPM_SHIFT)
  343. );
  344. }
  345. /* CON6---------------------------------------------------- */
  346. void bq24261_set_2xtmr_en(u32 val)
  347. {
  348. u32 ret = 0;
  349. ret = bq24261_config_interface((u8) (bq24261_CON6),
  350. (u8) (val),
  351. (u8) (CON6_2XTMR_EN_MASK), (u8) (CON6_2XTMR_EN_SHIFT)
  352. );
  353. }
  354. void bq24261_set_tmr(u32 val)
  355. {
  356. u32 ret = 0;
  357. ret = bq24261_config_interface((u8) (bq24261_CON6),
  358. (u8) (val), (u8) (CON6_TMR_MASK), (u8) (CON6_TMR_SHIFT)
  359. );
  360. }
  361. void bq24261_set_boost_ilim(u32 val)
  362. {
  363. u32 ret = 0;
  364. ret = bq24261_config_interface((u8) (bq24261_CON6),
  365. (u8) (val),
  366. (u8) (CON6_BOOST_ILIM_MASK), (u8) (CON6_BOOST_ILIM_SHIFT)
  367. );
  368. }
  369. void bq24261_set_ts_en(u32 val)
  370. {
  371. u32 ret = 0;
  372. ret = bq24261_config_interface((u8) (bq24261_CON6),
  373. (u8) (val), (u8) (CON6_TS_EN_MASK), (u8) (CON6_TS_EN_SHIFT)
  374. );
  375. }
  376. u32 bq24261_get_ts_fault(void)
  377. {
  378. u32 ret = 0;
  379. u8 val = 0;
  380. ret = bq24261_read_interface((u8) (bq24261_CON6),
  381. (&val), (u8) (CON6_TS_FAULT_MASK), (u8) (CON6_TS_FAULT_SHIFT)
  382. );
  383. return val;
  384. }
  385. void bq24261_set_vindpm_off(u32 val)
  386. {
  387. u32 ret = 0;
  388. ret = bq24261_config_interface((u8) (bq24261_CON6),
  389. (u8) (val),
  390. (u8) (CON6_VINDPM_OFF_MASK), (u8) (CON6_VINDPM_OFF_SHIFT)
  391. );
  392. }
  393. void bq24261_dump_register(void)
  394. {
  395. u8 i = 0;
  396. for (i = 0; i < bq24261_REG_NUM; i++) {
  397. bq24261_read_byte(i, &bq24261_reg[i]);
  398. battery_log(BAT_LOG_FULL,
  399. "[bq24261_dump_register] Reg[0x%X]=0x%X\n", i, bq24261_reg[i]);
  400. }
  401. }
  402. static u32 charging_hw_init(void *data)
  403. {
  404. u32 status = STATUS_OK;
  405. bq24261_set_tmr_rst(1); /* wdt reset */
  406. bq24261_set_en_boost(0); /* OTG boost */
  407. bq24261_set_tmr(0x3); /* default disable safety timer */
  408. bq24261_set_iterm(0x3); /* iterm 200mA */
  409. bq24261_set_vindpm_off(0); /* 4.2V offset */
  410. bq24261_set_vindpm(0x3); /* 4.452 VINDPM */
  411. bq24261_set_ts_en(0); /* disable TS function */
  412. return status;
  413. }
  414. static u32 charging_dump_register(void *data)
  415. {
  416. u32 status = STATUS_OK;
  417. battery_log(BAT_LOG_CRTI, "charging_dump_register\r\n");
  418. bq24261_dump_register();
  419. return status;
  420. }
  421. static u32 charging_enable(void *data)
  422. {
  423. u32 status = STATUS_OK;
  424. u32 enable = *(u32 *) (data);
  425. if (true == enable) {
  426. bq24261_set_hz_mode(0x0);
  427. bq24261_set_dis_ce(0);
  428. } else
  429. bq24261_set_dis_ce(0x1);
  430. return status;
  431. }
  432. static u32 charging_set_cv_voltage(void *data)
  433. {
  434. u32 status = STATUS_OK;
  435. u16 register_value;
  436. u32 cv_value = *(u32 *) (data);
  437. register_value = ((cv_value / 1000) - 3500) / 20;
  438. bq24261_set_vbreg(register_value);
  439. return status;
  440. }
  441. static u32 charging_get_current(void *data)
  442. {
  443. u32 status = STATUS_OK;
  444. u32 data_val = 0;
  445. u8 ret_val = 0;
  446. ret_val = bq24261_get_ichg();
  447. data_val = 500 + (ret_val * 100);
  448. ret_val = bq24261_get_low_chg();
  449. /* value in uA */
  450. if (ret_val == 0)
  451. *(u32 *) data = data_val * 1000;
  452. else
  453. *(u32 *) data = 300000;
  454. return status;
  455. }
  456. static u32 charging_set_current(void *data)
  457. {
  458. u32 status = STATUS_OK;
  459. u32 register_value;
  460. u32 current_value = *(u32 *) data;
  461. current_value = current_value / 1000;
  462. if (current_value <= 500)
  463. register_value = 0;
  464. else
  465. register_value = (current_value - 500) / 100;
  466. bq24261_set_ichg(register_value);
  467. return status;
  468. }
  469. static u32 charging_set_input_current(void *data)
  470. {
  471. u32 status = STATUS_OK;
  472. u32 array_size;
  473. u32 current_value = *(u32 *) data;
  474. u32 register_value;
  475. if (current_value >= CHARGE_CURRENT_2500_00_MA)
  476. register_value = 0x6;
  477. else if (current_value == CHARGE_CURRENT_2000_00_MA)
  478. register_value = 0x7;
  479. else {
  480. array_size = ARRAY_SIZE(INPUT_CS_VTH);
  481. for (register_value = 0; register_value < array_size; register_value++)
  482. if (INPUT_CS_VTH[register_value] >= current_value)
  483. break;
  484. }
  485. bq24261_set_in_limit(register_value);
  486. return status;
  487. }
  488. static u32 charging_get_input_current(void *data)
  489. {
  490. u32 register_value;
  491. register_value = bq24261_get_in_limit();
  492. *(u32 *) data = INPUT_CS_VTH[register_value];
  493. return STATUS_OK;
  494. }
  495. static u32 charging_get_charging_status(void *data)
  496. {
  497. u32 status = STATUS_OK;
  498. u32 ret_val;
  499. ret_val = bq24261_get_stat();
  500. if (ret_val == 0x2) /* charge done */
  501. *(u32 *) data = true;
  502. else
  503. *(u32 *) data = false;
  504. return status;
  505. }
  506. static u32 charging_reset_watch_dog_timer(void *data)
  507. {
  508. u32 status = STATUS_OK;
  509. battery_log(BAT_LOG_FULL, "charging_reset_watch_dog_timer\r\n");
  510. bq24261_set_tmr_rst(1);
  511. return status;
  512. }
  513. static u32 charging_set_hv_threshold(void *data)
  514. {
  515. u32 status = STATUS_OK;
  516. u32 array_size;
  517. u32 current_value = *(u32 *) data;
  518. u32 register_value;
  519. array_size = ARRAY_SIZE(VCDT_HV_VTH);
  520. for (register_value = 0; register_value < array_size; register_value++) {
  521. if (VCDT_HV_VTH[register_value] >= current_value)
  522. break;
  523. }
  524. upmu_set_rg_vcdt_hv_vth(register_value);
  525. return status;
  526. }
  527. static u32 charging_get_hv_status(void *data)
  528. {
  529. u32 status = STATUS_OK;
  530. *(bool *) (data) = upmu_get_rgs_vcdt_hv_det();
  531. return status;
  532. }
  533. static u32 charging_get_battery_status(void *data)
  534. {
  535. u32 status = STATUS_OK;
  536. /* upmu_set_baton_tdet_en(1); */
  537. upmu_set_rg_baton_en(1);
  538. *(bool *) (data) = upmu_get_rgs_baton_undet();
  539. return status;
  540. }
  541. static u32 charging_get_charger_det_status(void *data)
  542. {
  543. u32 status = STATUS_OK;
  544. *(bool *) (data) = upmu_get_rgs_chrdet();
  545. return status;
  546. }
  547. static u32 charging_get_charger_type(void *data)
  548. {
  549. u32 status = STATUS_OK;
  550. #if 0 /*defined(CONFIG_POWER_EXT) */
  551. *(CHARGER_TYPE *) (data) = STANDARD_HOST;
  552. #else
  553. *(int *)(data) = hw_charger_type_detection();
  554. #endif
  555. return status;
  556. }
  557. static u32 charging_get_is_pcm_timer_trigger(void *data)
  558. {
  559. u32 status = STATUS_OK;
  560. if (slp_get_wake_reason() == 3)
  561. *(bool *) (data) = true;
  562. else
  563. *(bool *) (data) = false;
  564. battery_log(BAT_LOG_CRTI, "slp_get_wake_reason=%d\n", slp_get_wake_reason());
  565. return status;
  566. }
  567. static u32 charging_set_platform_reset(void *data)
  568. {
  569. u32 status = STATUS_OK;
  570. battery_log(BAT_LOG_CRTI, "charging_set_platform_reset\n");
  571. #if 0 /* need porting of orderly_reboot(). */
  572. if (system_state == SYSTEM_BOOTING)
  573. arch_reset(0, NULL);
  574. else
  575. orderly_reboot(true);
  576. #endif
  577. arch_reset(0, NULL);
  578. return status;
  579. }
  580. static u32 charging_get_platform_boot_mode(void *data)
  581. {
  582. u32 status = STATUS_OK;
  583. *(u32 *) (data) = get_boot_mode();
  584. battery_log(BAT_LOG_CRTI, "get_boot_mode=%d\n", get_boot_mode());
  585. return status;
  586. }
  587. static u32 charging_enable_powerpath(void *data)
  588. {
  589. u32 status = STATUS_OK;
  590. u32 enable = *(u32 *) (data);
  591. if (true == enable)
  592. bq24261_set_hz_mode(0x0);
  593. else
  594. bq24261_set_hz_mode(0x1);
  595. return status;
  596. }
  597. static u32 charging_boost_enable(void *data)
  598. {
  599. u32 status = STATUS_OK;
  600. u32 enable = *(u32 *) (data);
  601. if (true == enable) {
  602. bq24261_set_boost_ilim(0x1); /* 1A on VBUS */
  603. bq24261_set_hz_mode(0x0);
  604. bq24261_set_dis_ce(0x1); /* charge disabled */
  605. bq24261_set_en_boost(0x1);
  606. } else
  607. bq24261_set_en_boost(0x0);
  608. return status;
  609. }
  610. static u32 charging_set_ta_current_pattern(void *data)
  611. {
  612. u32 increase = *(u32 *) (data);
  613. u32 charging_status = false;
  614. #if defined(HIGH_BATTERY_VOLTAGE_SUPPORT)
  615. u32 cv_voltage = BATTERY_VOLT_04_340000_V;
  616. #else
  617. u32 cv_voltage = BATTERY_VOLT_04_200000_V;
  618. #endif
  619. charging_get_charging_status(&charging_status);
  620. if (false == charging_status) {
  621. charging_set_cv_voltage(&cv_voltage); /* Set CV 4.2V */
  622. bq24261_set_ichg(0x0); /* Set charging current 500ma */
  623. bq24261_set_dis_ce(0x0); /* Enable Charging */
  624. }
  625. if (increase == true) {
  626. bq24261_set_in_limit(0x0); /* 100mA */
  627. msleep(85);
  628. bq24261_set_in_limit(0x2); /* 500mA */
  629. battery_log(BAT_LOG_FULL, "mtk_ta_increase() on 1");
  630. msleep(85);
  631. bq24261_set_in_limit(0x0); /* 100mA */
  632. battery_log(BAT_LOG_FULL, "mtk_ta_increase() off 1");
  633. msleep(85);
  634. bq24261_set_in_limit(0x2); /* 500mA */
  635. battery_log(BAT_LOG_FULL, "mtk_ta_increase() on 2");
  636. msleep(85);
  637. bq24261_set_in_limit(0x0); /* 100mA */
  638. battery_log(BAT_LOG_FULL, "mtk_ta_increase() off 2");
  639. msleep(85);
  640. bq24261_set_in_limit(0x2); /* 500mA */
  641. battery_log(BAT_LOG_FULL, "mtk_ta_increase() on 3");
  642. msleep(281);
  643. bq24261_set_in_limit(0x0); /* 100mA */
  644. battery_log(BAT_LOG_FULL, "mtk_ta_increase() off 3");
  645. msleep(85);
  646. bq24261_set_in_limit(0x2); /* 500mA */
  647. battery_log(BAT_LOG_FULL, "mtk_ta_increase() on 4");
  648. msleep(281);
  649. bq24261_set_in_limit(0x0); /* 100mA */
  650. battery_log(BAT_LOG_FULL, "mtk_ta_increase() off 4");
  651. msleep(85);
  652. bq24261_set_in_limit(0x2); /* 500mA */
  653. battery_log(BAT_LOG_FULL, "mtk_ta_increase() on 5");
  654. msleep(281);
  655. bq24261_set_in_limit(0x0); /* 100mA */
  656. battery_log(BAT_LOG_FULL, "mtk_ta_increase() off 5");
  657. msleep(85);
  658. bq24261_set_in_limit(0x2); /* 500mA */
  659. battery_log(BAT_LOG_FULL, "mtk_ta_increase() on 6");
  660. msleep(485);
  661. bq24261_set_in_limit(0x0); /* 100mA */
  662. battery_log(BAT_LOG_FULL, "mtk_ta_increase() off 6");
  663. msleep(50);
  664. battery_log(BAT_LOG_CRTI, "mtk_ta_increase() end\n");
  665. bq24261_set_in_limit(0x2); /* 500mA */
  666. msleep(200);
  667. } else {
  668. bq24261_set_in_limit(0x0); /* 100mA */
  669. msleep(85);
  670. bq24261_set_in_limit(0x2); /* 500mA */
  671. battery_log(BAT_LOG_FULL, "mtk_ta_decrease() on 1");
  672. msleep(281);
  673. bq24261_set_in_limit(0x0); /* 100mA */
  674. battery_log(BAT_LOG_FULL, "mtk_ta_decrease() off 1");
  675. msleep(85);
  676. bq24261_set_in_limit(0x2); /* 500mA */
  677. battery_log(BAT_LOG_FULL, "mtk_ta_decrease() on 2");
  678. msleep(281);
  679. bq24261_set_in_limit(0x0); /* 100mA */
  680. battery_log(BAT_LOG_FULL, "mtk_ta_decrease() off 2");
  681. msleep(85);
  682. bq24261_set_in_limit(0x2); /* 500mA */
  683. battery_log(BAT_LOG_FULL, "mtk_ta_decrease() on 3");
  684. msleep(281);
  685. bq24261_set_in_limit(0x0); /* 100mA */
  686. battery_log(BAT_LOG_FULL, "mtk_ta_decrease() off 3");
  687. msleep(85);
  688. bq24261_set_in_limit(0x2); /* 500mA */
  689. battery_log(BAT_LOG_FULL, "mtk_ta_decrease() on 4");
  690. msleep(85);
  691. bq24261_set_in_limit(0x0); /* 100mA */
  692. battery_log(BAT_LOG_FULL, "mtk_ta_decrease() off 4");
  693. msleep(85);
  694. bq24261_set_in_limit(0x2); /* 500mA */
  695. battery_log(BAT_LOG_FULL, "mtk_ta_decrease() on 5");
  696. msleep(85);
  697. bq24261_set_in_limit(0x0); /* 100mA */
  698. battery_log(BAT_LOG_FULL, "mtk_ta_decrease() off 5");
  699. msleep(85);
  700. bq24261_set_in_limit(0x2); /* 500mA */
  701. battery_log(BAT_LOG_FULL, "mtk_ta_decrease() on 6");
  702. msleep(485);
  703. bq24261_set_in_limit(0x0); /* 100mA */
  704. battery_log(BAT_LOG_FULL, "mtk_ta_decrease() off 6");
  705. msleep(50);
  706. battery_log(BAT_LOG_CRTI, "mtk_ta_decrease() end\n");
  707. bq24261_set_in_limit(0x2); /* 500mA */
  708. }
  709. return STATUS_OK;
  710. }
  711. static u32(*charging_func[CHARGING_CMD_NUMBER]) (void *data);
  712. int bq24261_control_interface(int cmd, void *data)
  713. {
  714. int status;
  715. static bool is_init;
  716. if (is_init == false) {
  717. charging_func[CHARGING_CMD_INIT] = charging_hw_init;
  718. charging_func[CHARGING_CMD_DUMP_REGISTER] = charging_dump_register;
  719. charging_func[CHARGING_CMD_ENABLE] = charging_enable;
  720. charging_func[CHARGING_CMD_SET_CV_VOLTAGE] = charging_set_cv_voltage;
  721. charging_func[CHARGING_CMD_GET_CURRENT] = charging_get_current;
  722. charging_func[CHARGING_CMD_SET_CURRENT] = charging_set_current;
  723. charging_func[CHARGING_CMD_GET_INPUT_CURRENT] = charging_get_input_current;
  724. charging_func[CHARGING_CMD_SET_INPUT_CURRENT] = charging_set_input_current;
  725. charging_func[CHARGING_CMD_GET_CHARGING_STATUS] = charging_get_charging_status;
  726. charging_func[CHARGING_CMD_RESET_WATCH_DOG_TIMER] = charging_reset_watch_dog_timer;
  727. charging_func[CHARGING_CMD_SET_HV_THRESHOLD] = charging_set_hv_threshold;
  728. charging_func[CHARGING_CMD_GET_HV_STATUS] = charging_get_hv_status;
  729. charging_func[CHARGING_CMD_GET_BATTERY_STATUS] = charging_get_battery_status;
  730. charging_func[CHARGING_CMD_GET_CHARGER_DET_STATUS] =
  731. charging_get_charger_det_status;
  732. charging_func[CHARGING_CMD_GET_CHARGER_TYPE] = charging_get_charger_type;
  733. charging_func[CHARGING_CMD_GET_IS_PCM_TIMER_TRIGGER] =
  734. charging_get_is_pcm_timer_trigger;
  735. charging_func[CHARGING_CMD_SET_PLATFORM_RESET] = charging_set_platform_reset;
  736. charging_func[CHARGING_CMD_GET_PLATFORM_BOOT_MODE] =
  737. charging_get_platform_boot_mode;
  738. charging_func[CHARGING_CMD_ENABLE_POWERPATH] = charging_enable_powerpath;
  739. charging_func[CHARGING_CMD_BOOST_ENABLE] = charging_boost_enable;
  740. charging_func[CHARGING_CMD_SET_TA_CURRENT_PATTERN] =
  741. charging_set_ta_current_pattern;
  742. is_init = true;
  743. }
  744. if (cmd < CHARGING_CMD_NUMBER && charging_func[cmd])
  745. status = charging_func[cmd] (data);
  746. else {
  747. pr_err("Unsupported charging command:%d!\n", cmd);
  748. return STATUS_UNSUPPORTED;
  749. }
  750. return status;
  751. }
  752. /**********************************************************
  753. *
  754. * [Internal Function]
  755. *
  756. *********************************************************/
  757. void bq24261_hw_component_detect(void)
  758. {
  759. u32 ret = 0;
  760. u8 val = 0;
  761. ret = bq24261_read_interface(0x03, &val, 0xFF, 0x0);
  762. if (val == 0)
  763. g_bq24261_hw_exist = 0;
  764. else
  765. g_bq24261_hw_exist = 1;
  766. pr_warn("[bq24261_hw_component_detect] exist=%d, Reg[0x03]=0x%x\n", g_bq24261_hw_exist,
  767. val);
  768. if (g_bq24261_hw_exist)
  769. bat_charger_register(bq24261_control_interface);
  770. }
  771. int is_bq24261_exist(void)
  772. {
  773. pr_debug("[is_bq24261_exist] g_bq24261_hw_exist=%d\n", g_bq24261_hw_exist);
  774. return g_bq24261_hw_exist;
  775. }
  776. static int bq24261_driver_probe(struct i2c_client *client, const struct i2c_device_id *id)
  777. {
  778. battery_log(BAT_LOG_CRTI, "[bq24261_driver_probe]\n");
  779. new_client = client;
  780. bq24261_hw_component_detect();
  781. bq24261_dump_register();
  782. return 0;
  783. }
  784. static const struct i2c_device_id bq24261_i2c_id[] = { {"bq24261", 0}, {} };
  785. #ifdef CONFIG_OF
  786. static const struct of_device_id bq24261_of_match[] = {
  787. {.compatible = "ti,bq24261",},
  788. {},
  789. };
  790. MODULE_DEVICE_TABLE(of, bq24261_of_match);
  791. #endif
  792. static struct i2c_driver bq24261_driver = {
  793. .driver = {
  794. .name = "bq24261",
  795. #ifdef CONFIG_OF
  796. .of_match_table = of_match_ptr(bq24261_of_match),
  797. #endif
  798. },
  799. .probe = bq24261_driver_probe,
  800. .id_table = bq24261_i2c_id,
  801. };
  802. /**********************************************************
  803. *
  804. * [platform_driver API]
  805. *
  806. *********************************************************/
  807. u8 g_reg_value_bq24261 = 0;
  808. static ssize_t show_bq24261_access(struct device *dev, struct device_attribute *attr, char *buf)
  809. {
  810. pr_debug("[show_bq24261_access] 0x%x\n", g_reg_value_bq24261);
  811. return sprintf(buf, "%u\n", g_reg_value_bq24261);
  812. }
  813. static ssize_t store_bq24261_access(struct device *dev, struct device_attribute *attr,
  814. const char *buf, size_t size)
  815. {
  816. int ret = 0;
  817. char *pvalue, temp_buf[16];
  818. unsigned int reg_value = 0;
  819. unsigned int reg_address = 0;
  820. if (buf != NULL && size != 0) {
  821. strcpy(temp_buf, buf);
  822. pvalue = temp_buf;
  823. if (size > 4) {
  824. ret = kstrtouint(strsep(&pvalue, " "), 0, &reg_address);
  825. if (ret) {
  826. pr_err("wrong format!\n");
  827. return size;
  828. }
  829. ret = kstrtouint(pvalue, 0, &reg_value);
  830. if (ret) {
  831. pr_err("wrong format!\n");
  832. return size;
  833. }
  834. pr_debug("[store_bq24261_access] write bq24261 reg 0x%x with value 0x%x !\n",
  835. reg_address, reg_value);
  836. bq24261_config_interface(reg_address, reg_value, 0xFF, 0x0);
  837. } else {
  838. ret = kstrtouint(pvalue, 0, &reg_address);
  839. if (ret) {
  840. pr_err("wrong format!\n");
  841. return size;
  842. }
  843. bq24261_read_interface(reg_address, &g_reg_value_bq24261, 0xFF, 0x0);
  844. pr_debug("[store_bq24261_access] read bq24261 reg 0x%x with value 0x%x !\n",
  845. reg_address, g_reg_value_bq24261);
  846. pr_debug
  847. ("[store_bq24261_access] Please use \"cat bq24261_access\" to get value\r\n");
  848. }
  849. }
  850. return size;
  851. }
  852. static DEVICE_ATTR(bq24261_access, S_IWUSR | S_IRUGO, show_bq24261_access, store_bq24261_access);
  853. static int bq24261_user_space_probe(struct platform_device *dev)
  854. {
  855. int ret_device_file = 0;
  856. ret_device_file = device_create_file(&(dev->dev), &dev_attr_bq24261_access);
  857. return 0;
  858. }
  859. struct platform_device bq24261_user_space_device = {
  860. .name = "bq24261-user",
  861. .id = -1,
  862. };
  863. static struct platform_driver bq24261_user_space_driver = {
  864. .probe = bq24261_user_space_probe,
  865. .driver = {
  866. .name = "bq24261-user",
  867. },
  868. };
  869. static int __init bq24261_init(void)
  870. {
  871. int ret = 0;
  872. if (i2c_add_driver(&bq24261_driver) != 0) {
  873. battery_log(BAT_LOG_CRTI,
  874. "[bq24261_init] failed to register bq24261 i2c driver.\n");
  875. } else {
  876. battery_log(BAT_LOG_CRTI,
  877. "[bq24261_init] Success to register bq24261 i2c driver.\n");
  878. }
  879. ret = platform_device_register(&bq24261_user_space_device);
  880. if (ret) {
  881. battery_log(BAT_LOG_CRTI,
  882. "****[bq24261_init] Unable to device register(%d)\n", ret);
  883. return ret;
  884. }
  885. ret = platform_driver_register(&bq24261_user_space_driver);
  886. if (ret) {
  887. battery_log(BAT_LOG_CRTI,
  888. "****[bq24261_init] Unable to register driver (%d)\n", ret);
  889. return ret;
  890. }
  891. return 0;
  892. }
  893. static void __exit bq24261_exit(void)
  894. {
  895. i2c_del_driver(&bq24261_driver);
  896. }
  897. module_init(bq24261_init);
  898. module_exit(bq24261_exit);
  899. MODULE_LICENSE("GPL");
  900. MODULE_DESCRIPTION("I2C bq24261 Driver");
  901. MODULE_AUTHOR("James Lo<james.lo@mediatek.com>");