ncp1854.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734
  1. #include <linux/types.h>
  2. #include <linux/init.h> /* For init/exit macros */
  3. #include <linux/module.h> /* For MODULE_ marcros */
  4. #include <linux/platform_device.h>
  5. #include <linux/i2c.h>
  6. #include <linux/slab.h>
  7. #ifdef CONFIG_OF
  8. #include <linux/of.h>
  9. #include <linux/of_irq.h>
  10. #include <linux/of_address.h>
  11. #endif
  12. #include <mt-plat/charging.h>
  13. #include "ncp1854.h"
  14. /**********************************************************
  15. *
  16. * [I2C Slave Setting]
  17. *
  18. *********************************************************/
  19. #define NCP1854_SLAVE_ADDR_WRITE 0x6C
  20. #define NCP1854_SLAVE_ADDR_READ 0x6D
  21. static struct i2c_client *new_client;
  22. static const struct i2c_device_id ncp1854_i2c_id[] = { {"ncp1854", 0}, {} };
  23. kal_bool chargin_hw_init_done = KAL_FALSE;
  24. static int ncp1854_driver_probe(struct i2c_client *client, const struct i2c_device_id *id);
  25. #ifdef CONFIG_OF
  26. static const struct of_device_id ncp1854_of_match[] = {
  27. {.compatible = "ncp1854",},
  28. {},
  29. };
  30. MODULE_DEVICE_TABLE(of, ncp1854_of_match);
  31. #endif
  32. static struct i2c_driver ncp1854_driver = {
  33. .driver = {
  34. .name = "ncp1854",
  35. #ifdef CONFIG_OF
  36. .of_match_table = ncp1854_of_match,
  37. #endif
  38. },
  39. .probe = ncp1854_driver_probe,
  40. .id_table = ncp1854_i2c_id,
  41. };
  42. /**********************************************************
  43. *
  44. * [Global Variable]
  45. *
  46. *********************************************************/
  47. unsigned char ncp1854_reg[ncp1854_REG_NUM] = { 0 };
  48. static DEFINE_MUTEX(ncp1854_i2c_access);
  49. /**********************************************************
  50. *
  51. * [I2C Function For Read/Write ncp1854]
  52. *
  53. *********************************************************/
  54. int ncp1854_read_byte(unsigned char cmd, unsigned char *returnData)
  55. {
  56. char cmd_buf[1] = { 0x00 };
  57. char readData = 0;
  58. int ret = 0;
  59. mutex_lock(&ncp1854_i2c_access);
  60. /* new_client->addr = ((new_client->addr) & I2C_MASK_FLAG) | I2C_WR_FLAG; */
  61. new_client->ext_flag =
  62. ((new_client->ext_flag) & I2C_MASK_FLAG) | I2C_WR_FLAG | I2C_DIRECTION_FLAG;
  63. cmd_buf[0] = cmd;
  64. ret = i2c_master_send(new_client, &cmd_buf[0], (1 << 8 | 1));
  65. if (ret < 0) {
  66. /* new_client->addr = new_client->addr & I2C_MASK_FLAG; */
  67. new_client->ext_flag = 0;
  68. mutex_unlock(&ncp1854_i2c_access);
  69. return 0;
  70. }
  71. readData = cmd_buf[0];
  72. *returnData = readData;
  73. /* new_client->addr = new_client->addr & I2C_MASK_FLAG; */
  74. new_client->ext_flag = 0;
  75. mutex_unlock(&ncp1854_i2c_access);
  76. return 1;
  77. }
  78. int ncp1854_write_byte(unsigned char cmd, unsigned char writeData)
  79. {
  80. char write_data[2] = { 0 };
  81. int ret = 0;
  82. mutex_lock(&ncp1854_i2c_access);
  83. write_data[0] = cmd;
  84. write_data[1] = writeData;
  85. new_client->ext_flag = ((new_client->ext_flag) & I2C_MASK_FLAG) | I2C_DIRECTION_FLAG;
  86. ret = i2c_master_send(new_client, write_data, 2);
  87. if (ret < 0) {
  88. new_client->ext_flag = 0;
  89. mutex_unlock(&ncp1854_i2c_access);
  90. return 0;
  91. }
  92. new_client->ext_flag = 0;
  93. mutex_unlock(&ncp1854_i2c_access);
  94. return 1;
  95. }
  96. /**********************************************************
  97. *
  98. * [Read / Write Function]
  99. *
  100. *********************************************************/
  101. unsigned int ncp1854_read_interface(unsigned char RegNum, unsigned char *val, unsigned char MASK,
  102. unsigned char SHIFT)
  103. {
  104. unsigned char ncp1854_reg = 0;
  105. int ret = 0;
  106. battery_log(BAT_LOG_FULL, "--------------------------------------------------\n");
  107. ret = ncp1854_read_byte(RegNum, &ncp1854_reg);
  108. battery_log(BAT_LOG_FULL, "[ncp1854_read_interface] Reg[%x]=0x%x\n", RegNum, ncp1854_reg);
  109. ncp1854_reg &= (MASK << SHIFT);
  110. *val = (ncp1854_reg >> SHIFT);
  111. battery_log(BAT_LOG_FULL, "[ncp1854_read_interface] Val=0x%x\n", *val);
  112. return ret;
  113. }
  114. unsigned int ncp1854_config_interface(unsigned char RegNum, unsigned char val, unsigned char MASK,
  115. unsigned char SHIFT)
  116. {
  117. unsigned char ncp1854_reg = 0;
  118. int ret = 0;
  119. battery_log(BAT_LOG_FULL, "--------------------------------------------------\n");
  120. ret = ncp1854_read_byte(RegNum, &ncp1854_reg);
  121. battery_log(BAT_LOG_FULL, "[ncp1854_config_interface] Reg[%x]=0x%x\n", RegNum, ncp1854_reg);
  122. ncp1854_reg &= ~(MASK << SHIFT);
  123. ncp1854_reg |= (val << SHIFT);
  124. ret = ncp1854_write_byte(RegNum, ncp1854_reg);
  125. battery_log(BAT_LOG_FULL, "[ncp18546_config_interface] Write Reg[%x]=0x%x\n", RegNum, ncp1854_reg);
  126. /* Check */
  127. /* ncp1854_read_byte(RegNum, &ncp1854_reg); */
  128. /* battery_log(BAT_LOG_FULL, "[ncp1854_config_interface] Check Reg[%x]=0x%x\n", RegNum, ncp1854_reg); */
  129. return ret;
  130. }
  131. /**********************************************************
  132. *
  133. * [Internal Function]
  134. *
  135. *********************************************************/
  136. /* CON0 */
  137. unsigned int ncp1854_get_chip_status(void)
  138. {
  139. unsigned int ret = 0;
  140. unsigned int val = 0;
  141. ret = ncp1854_read_interface((unsigned char) (NCP1854_CON0),
  142. (unsigned char *) (&val),
  143. (unsigned char) (CON0_STATE_MASK), (unsigned char) (CON0_STATE_SHIFT)
  144. );
  145. return val;
  146. }
  147. unsigned int ncp1854_get_batfet(void)
  148. {
  149. unsigned int ret = 0;
  150. unsigned int val = 0;
  151. ret = ncp1854_read_interface((unsigned char) (NCP1854_CON0),
  152. (unsigned char *) (&val),
  153. (unsigned char) (CON0_BATFET_MASK), (unsigned char) (CON0_BATFET_SHIFT)
  154. );
  155. return val;
  156. }
  157. unsigned int ncp1854_get_statint(void)
  158. {
  159. unsigned int ret = 0;
  160. unsigned int val = 0;
  161. ret = ncp1854_read_interface((unsigned char) (NCP1854_CON0),
  162. (unsigned char *) (&val),
  163. (unsigned char) (CON0_STATINT_MASK),
  164. (unsigned char) (CON0_STATINT_SHIFT)
  165. );
  166. return val;
  167. }
  168. unsigned int ncp1854_get_faultint(void)
  169. {
  170. unsigned int ret = 0;
  171. unsigned int val = 0;
  172. ret = ncp1854_read_interface((unsigned char) (NCP1854_CON0),
  173. (unsigned char *) (&val),
  174. (unsigned char) (CON0_FAULTINT_MASK),
  175. (unsigned char) (CON0_FAULTINT_SHIFT)
  176. );
  177. return val;
  178. }
  179. /* CON1 */
  180. void ncp1854_set_reset(unsigned int val)
  181. {
  182. unsigned int ret = 0;
  183. ret = ncp1854_config_interface((unsigned char) (NCP1854_CON1),
  184. (unsigned char) (val),
  185. (unsigned char) (CON1_REG_RST_MASK),
  186. (unsigned char) (CON1_REG_RST_SHIFT)
  187. );
  188. }
  189. void ncp1854_set_chg_en(unsigned int val)
  190. {
  191. unsigned int ret = 0;
  192. ret = ncp1854_config_interface((unsigned char) (NCP1854_CON1),
  193. (unsigned char) (val),
  194. (unsigned char) (CON1_CHG_EN_MASK),
  195. (unsigned char) (CON1_CHG_EN_SHIFT)
  196. );
  197. }
  198. void ncp1854_set_otg_en(unsigned int val)
  199. {
  200. unsigned int ret = 0;
  201. ret = ncp1854_config_interface((unsigned char) (NCP1854_CON1),
  202. (unsigned char) (val),
  203. (unsigned char) (CON1_OTG_EN_MASK),
  204. (unsigned char) (CON1_OTG_EN_SHIFT)
  205. );
  206. }
  207. unsigned int ncp1854_get_otg_en(void)
  208. {
  209. unsigned int ret = 0;
  210. unsigned int val = 0;
  211. ret = ncp1854_read_interface((unsigned char) (NCP1854_CON1),
  212. (unsigned char *) (&val),
  213. (unsigned char) (CON1_OTG_EN_MASK), (unsigned char) (CON1_OTG_EN_SHIFT)
  214. );
  215. return val;
  216. }
  217. void ncp1854_set_fctry_mode(unsigned int val)
  218. {
  219. unsigned int ret = 0;
  220. ret = ncp1854_config_interface((unsigned char) (NCP1854_CON1),
  221. (unsigned char) (val),
  222. (unsigned char) (CON1_FCTRY_MOD_MASK),
  223. (unsigned char) (CON1_FCTRY_MOD_SHIFT)
  224. );
  225. }
  226. void ncp1854_set_tj_warn_opt(unsigned int val)
  227. {
  228. unsigned int ret = 0;
  229. ret = ncp1854_config_interface((unsigned char) (NCP1854_CON1),
  230. (unsigned char) (val),
  231. (unsigned char) (CON1_TJ_WARN_OPT_MASK),
  232. (unsigned char) (CON1_TJ_WARN_OPT_SHIFT)
  233. );
  234. }
  235. unsigned int ncp1854_get_usb_cfg(void)
  236. {
  237. unsigned int ret = 0;
  238. unsigned int val = 0;
  239. ret = ncp1854_read_interface((unsigned char) (NCP1854_CON1),
  240. (unsigned char *) (&val),
  241. (unsigned char) (CON1_JEITA_OPT_MASK),
  242. (unsigned char) (CON1_JEITA_OPT_SHIFT)
  243. );
  244. return val;
  245. }
  246. void ncp1854_set_tchg_rst(unsigned int val)
  247. {
  248. unsigned int ret = 0;
  249. ret = ncp1854_config_interface((unsigned char) (NCP1854_CON1),
  250. (unsigned char) (val),
  251. (unsigned char) (CON1_TCHG_RST_MASK),
  252. (unsigned char) (CON1_TCHG_RST_SHIFT)
  253. );
  254. }
  255. void ncp1854_set_int_mask(unsigned int val)
  256. {
  257. unsigned int ret = 0;
  258. ret = ncp1854_config_interface((unsigned char) (NCP1854_CON1),
  259. (unsigned char) (val),
  260. (unsigned char) (CON1_INT_MASK_MASK),
  261. (unsigned char) (CON1_INT_MASK_SHIFT)
  262. );
  263. }
  264. /* CON2 */
  265. void ncp1854_set_wdto_dis(unsigned int val)
  266. {
  267. unsigned int ret = 0;
  268. ret = ncp1854_config_interface((unsigned char) (NCP1854_CON2),
  269. (unsigned char) (val),
  270. (unsigned char) (CON2_WDTO_DIS_MASK),
  271. (unsigned char) (CON2_WDTO_DIS_SHIFT)
  272. );
  273. }
  274. void ncp1854_set_chgto_dis(unsigned int val)
  275. {
  276. unsigned int ret = 0;
  277. ret = ncp1854_config_interface((unsigned char) (NCP1854_CON2),
  278. (unsigned char) (val),
  279. (unsigned char) (CON2_CHGTO_DIS_MASK),
  280. (unsigned char) (CON2_CHGTO_DIS_SHIFT)
  281. );
  282. }
  283. void ncp1854_set_pwr_path(unsigned int val)
  284. {
  285. unsigned int ret = 0;
  286. ret = ncp1854_config_interface((unsigned char) (NCP1854_CON2),
  287. (unsigned char) (val),
  288. (unsigned char) (CON2_PWR_PATH_MASK),
  289. (unsigned char) (CON2_PWR_PATH_SHIFT)
  290. );
  291. }
  292. void ncp1854_set_trans_en(unsigned int val)
  293. {
  294. unsigned int ret = 0;
  295. ret = ncp1854_config_interface((unsigned char) (NCP1854_CON2),
  296. (unsigned char) (val),
  297. (unsigned char) (CON2_TRANS_EN_MASK),
  298. (unsigned char) (CON2_TRANS_EN_SHIFT)
  299. );
  300. }
  301. void ncp1854_set_iinset_pin_en(unsigned int val)
  302. {
  303. unsigned int ret = 0;
  304. ret = ncp1854_config_interface((unsigned char) (NCP1854_CON2),
  305. (unsigned char) (val),
  306. (unsigned char) (CON2_IINSET_PIN_EN_MASK),
  307. (unsigned char) (CON2_IINSET_PIN_EN_SHIFT)
  308. );
  309. }
  310. void ncp1854_set_iinlim_en(unsigned int val)
  311. {
  312. unsigned int ret = 0;
  313. ret = ncp1854_config_interface((unsigned char) (NCP1854_CON2),
  314. (unsigned char) (val),
  315. (unsigned char) (CON2_IINLIM_EN_MASK),
  316. (unsigned char) (CON2_IINLIM_EN_SHIFT)
  317. );
  318. }
  319. void ncp1854_set_aicl_en(unsigned int val)
  320. {
  321. unsigned int ret = 0;
  322. ret = ncp1854_config_interface((unsigned char) (NCP1854_CON2),
  323. (unsigned char) (val),
  324. (unsigned char) (CON2_AICL_EN_MASK),
  325. (unsigned char) (CON2_AICL_EN_SHIFT)
  326. );
  327. }
  328. /* CON8 */
  329. unsigned int ncp1854_get_vfet_ok(void)
  330. {
  331. unsigned int ret = 0;
  332. unsigned int val = 0;
  333. ret = ncp1854_read_interface((unsigned char) (NCP1854_CON8),
  334. (unsigned char *) (&val),
  335. (unsigned char) (CON8_VFET_OK_MASK),
  336. (unsigned char) (CON8_VFET_OK_SHIFT)
  337. );
  338. return val;
  339. }
  340. /* CON14 */
  341. void ncp1854_set_ctrl_vbat(unsigned int val)
  342. {
  343. unsigned int ret = 0;
  344. ret = ncp1854_config_interface((unsigned char) (NCP1854_CON14),
  345. (unsigned char) (val),
  346. (unsigned char) (CON14_CTRL_VBAT_MASK),
  347. (unsigned char) (CON14_CTRL_VBAT_SHIFT)
  348. );
  349. }
  350. /* CON15 */
  351. void ncp1854_set_ichg_high(unsigned int val)
  352. {
  353. unsigned int ret = 0;
  354. ret = ncp1854_config_interface((unsigned char) (NCP1854_CON15),
  355. (unsigned char) (val),
  356. (unsigned char) (CON15_ICHG_HIGH_MASK),
  357. (unsigned char) (CON15_ICHG_HIGH_SHIFT)
  358. );
  359. }
  360. void ncp1854_set_ieoc(unsigned int val)
  361. {
  362. unsigned int ret = 0;
  363. ret = ncp1854_config_interface((unsigned char) (NCP1854_CON15),
  364. (unsigned char) (val),
  365. (unsigned char) (CON15_IEOC_MASK), (unsigned char) (CON15_IEOC_SHIFT)
  366. );
  367. }
  368. void ncp1854_set_ichg(unsigned int val)
  369. {
  370. unsigned int ret = 0;
  371. ret = ncp1854_config_interface((unsigned char) (NCP1854_CON15),
  372. (unsigned char) (val),
  373. (unsigned char) (CON15_ICHG_MASK), (unsigned char) (CON15_ICHG_SHIFT)
  374. );
  375. }
  376. unsigned int ncp1854_get_ichg(void)
  377. {
  378. unsigned int ret = 0;
  379. unsigned int val = 0;
  380. ret = ncp1854_read_interface((unsigned char) NCP1854_CON15,
  381. (unsigned char *) &val,
  382. (unsigned char) CON15_ICHG_MASK, (unsigned char) CON15_ICHG_SHIFT);
  383. return val;
  384. }
  385. /* CON16 */
  386. void ncp1854_set_iweak(unsigned int val)
  387. {
  388. unsigned int ret = 0;
  389. ret = ncp1854_config_interface((unsigned char) (NCP1854_CON16),
  390. (unsigned char) (val),
  391. (unsigned char) (CON16_IWEAK_MASK),
  392. (unsigned char) (CON16_IWEAK_SHIFT)
  393. );
  394. }
  395. void ncp1854_set_ctrl_vfet(unsigned int val)
  396. {
  397. unsigned int ret = 0;
  398. ret = ncp1854_config_interface((unsigned char) (NCP1854_CON16),
  399. (unsigned char) (val),
  400. (unsigned char) (CON16_CTRL_VFET_MASK),
  401. (unsigned char) (CON16_CTRL_VFET_SHIFT)
  402. );
  403. }
  404. void ncp1854_set_iinlim(unsigned int val)
  405. {
  406. unsigned int ret = 0;
  407. ret = ncp1854_config_interface((unsigned char) (NCP1854_CON16),
  408. (unsigned char) (val),
  409. (unsigned char) (CON16_IINLIM_MASK),
  410. (unsigned char) (CON16_IINLIM_SHIFT)
  411. );
  412. }
  413. /* CON17 */
  414. void ncp1854_set_iinlim_ta(unsigned int val)
  415. {
  416. unsigned int ret = 0;
  417. ret = ncp1854_config_interface((unsigned char) (NCP1854_CON17),
  418. (unsigned char) (val),
  419. (unsigned char) (CON17_IINLIM_TA_MASK),
  420. (unsigned char) (CON17_IINLIM_TA_SHIFT)
  421. );
  422. }
  423. /**********************************************************
  424. *
  425. * [Internal Function]
  426. *
  427. *********************************************************/
  428. void ncp1854_dump_register(void)
  429. {
  430. int i = 0;
  431. for (i = 0; i < ncp1854_REG_NUM; i++) {
  432. if ((i == 3) || (i == 4) || (i == 5) || (i == 6)) /* do not dump read clear status register */
  433. continue;
  434. if ((i == 10) || (i == 11) || (i == 12) || (i == 13)) /* do not dump interrupt mask bit register */
  435. continue;
  436. ncp1854_read_byte(i, &ncp1854_reg[i]);
  437. battery_log(BAT_LOG_FULL, "[ncp1854_dump_register] Reg[0x%X]=0x%X\n", i, ncp1854_reg[i]);
  438. }
  439. }
  440. void ncp1854_read_register(int i)
  441. {
  442. ncp1854_read_byte(i, &ncp1854_reg[i]);
  443. battery_log(BAT_LOG_FULL, "[ncp1854_read_register] Reg[0x%X]=0x%X\n", i, ncp1854_reg[i]);
  444. }
  445. static void ncp1854_parse_customer_setting(void)
  446. {
  447. #ifdef CONFIG_OF
  448. unsigned int val;
  449. struct device_node *np;
  450. struct pinctrl *pinctrl;
  451. struct pinctrl_state *pinctrl_drvvbus_init;
  452. struct pinctrl_state *pinctrl_drvvbus_low;
  453. /* check customer setting */
  454. np = new_client->dev.of_node;
  455. if (np) {
  456. if (of_property_read_u32(np, "disable_ncp1854_fctry_mod", &val) == 0) {
  457. if (val)
  458. ncp1854_set_fctry_mode(0x0);
  459. battery_log(BAT_LOG_FULL, "%s: disable factory mode, %d\n", __func__, val);
  460. }
  461. }
  462. pinctrl = devm_pinctrl_get(&new_client->dev);
  463. if (IS_ERR(pinctrl)) {
  464. battery_log(BAT_LOG_CRTI, "[%s]Cannot find drvvbus pinctrl, err=%d\n",
  465. __func__, (int)PTR_ERR(pinctrl));
  466. return;
  467. }
  468. pinctrl_drvvbus_init = pinctrl_lookup_state(pinctrl, "drvvbus_init");
  469. if (IS_ERR(pinctrl_drvvbus_init)) {
  470. battery_log(BAT_LOG_CRTI, "[%s]Cannot find drvvbus_init state, err=%d\n",
  471. __func__, (int)PTR_ERR(pinctrl_drvvbus_init));
  472. return;
  473. }
  474. pinctrl_drvvbus_low = pinctrl_lookup_state(pinctrl, "drvvbus_low");
  475. if (IS_ERR(pinctrl_drvvbus_low)) {
  476. battery_log(BAT_LOG_CRTI, "[%s]Cannot find drvvbus_low state, err=%d\n",
  477. __func__, (int)PTR_ERR(pinctrl_drvvbus_low));
  478. return;
  479. }
  480. pinctrl_select_state(pinctrl, pinctrl_drvvbus_init);
  481. pinctrl_select_state(pinctrl, pinctrl_drvvbus_low);
  482. devm_pinctrl_put(pinctrl);
  483. battery_log(BAT_LOG_FULL, "[%s]pinctrl_select_state success\n", __func__);
  484. #endif
  485. }
  486. static int ncp1854_driver_probe(struct i2c_client *client, const struct i2c_device_id *id)
  487. {
  488. int err = 0;
  489. battery_log(BAT_LOG_CRTI, "[ncp1854_driver_probe]\n");
  490. new_client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL);
  491. if (!new_client) {
  492. err = -ENOMEM;
  493. goto exit;
  494. }
  495. memset(new_client, 0, sizeof(struct i2c_client));
  496. new_client = client;
  497. chargin_hw_init_done = KAL_TRUE;
  498. ncp1854_parse_customer_setting();
  499. return 0;
  500. exit:
  501. return err;
  502. }
  503. /**********************************************************
  504. *
  505. * [platform_driver API]
  506. *
  507. *********************************************************/
  508. unsigned char g_reg_value_ncp1854 = 0;
  509. static ssize_t show_ncp1854_access(struct device *dev, struct device_attribute *attr, char *buf)
  510. {
  511. battery_log(BAT_LOG_CRTI, "[show_ncp1854_access] 0x%x\n", g_reg_value_ncp1854);
  512. return sprintf(buf, "%u\n", g_reg_value_ncp1854);
  513. }
  514. static ssize_t store_ncp1854_access(struct device *dev, struct device_attribute *attr,
  515. const char *buf, size_t size)
  516. {
  517. int ret = 0;
  518. char *pvalue = NULL, *addr, *val;
  519. unsigned int reg_value = 0;
  520. unsigned int reg_address = 0;
  521. battery_log(BAT_LOG_CRTI, "[store_ncp1854_access]\n");
  522. if (buf != NULL && size != 0) {
  523. battery_log(BAT_LOG_CRTI, "[store_ncp1854_access] buf is %s and size is %d\n", buf, (int)size);
  524. /*reg_address = kstrtoul(buf, &pvalue, 16);*/
  525. pvalue = (char *)buf;
  526. if (size > 3) {
  527. addr = strsep(&pvalue, " ");
  528. ret = kstrtou32(addr, 16, (unsigned int *)&reg_address);
  529. } else
  530. ret = kstrtou32(pvalue, 16, (unsigned int *)&reg_address);
  531. if (size > 3) {
  532. val = strsep(&pvalue, " ");
  533. ret = kstrtou32(val, 16, (unsigned int *)&reg_value);
  534. battery_log(BAT_LOG_CRTI,
  535. "[store_ncp1854_access] write ncp1854 reg 0x%x with value 0x%x !\n",
  536. reg_address, reg_value);
  537. ret = ncp1854_config_interface(reg_address, reg_value, 0xFF, 0x0);
  538. } else {
  539. ret = ncp1854_read_interface(reg_address, &g_reg_value_ncp1854, 0xFF, 0x0);
  540. battery_log(BAT_LOG_CRTI,
  541. "[store_ncp1854_access] read ncp1854 reg 0x%x with value 0x%x !\n",
  542. reg_address, g_reg_value_ncp1854);
  543. battery_log(BAT_LOG_CRTI,
  544. "[store_ncp1854_access] Please use \"cat ncp1854_access\" to get value\r\n");
  545. }
  546. }
  547. return size;
  548. }
  549. static DEVICE_ATTR(ncp1854_access, 0664, show_ncp1854_access, store_ncp1854_access); /* 664 */
  550. static int ncp1854_user_space_probe(struct platform_device *dev)
  551. {
  552. int ret_device_file = 0;
  553. battery_log(BAT_LOG_CRTI, "******** ncp1854_user_space_probe!! ********\n");
  554. ret_device_file = device_create_file(&(dev->dev), &dev_attr_ncp1854_access);
  555. return 0;
  556. }
  557. struct platform_device ncp1854_user_space_device = {
  558. .name = "ncp1854-user",
  559. .id = -1,
  560. };
  561. static struct platform_driver ncp1854_user_space_driver = {
  562. .probe = ncp1854_user_space_probe,
  563. .driver = {
  564. .name = "ncp1854-user",
  565. },
  566. };
  567. static int __init ncp1854_init(void)
  568. {
  569. int ret = 0;
  570. battery_log(BAT_LOG_CRTI, "[ncp1854_init] init start\n");
  571. if (i2c_add_driver(&ncp1854_driver) != 0)
  572. battery_log(BAT_LOG_CRTI, "[ncp1854_init] failed to register ncp1854 i2c driver.\n");
  573. else
  574. battery_log(BAT_LOG_CRTI, "[ncp1854_init] Success to register ncp1854 i2c driver.\n");
  575. /* ncp1854 user space access interface */
  576. ret = platform_device_register(&ncp1854_user_space_device);
  577. if (ret) {
  578. battery_log(BAT_LOG_CRTI, "****[ncp1854_init] Unable to device register(%d)\n", ret);
  579. return ret;
  580. }
  581. ret = platform_driver_register(&ncp1854_user_space_driver);
  582. if (ret) {
  583. battery_log(BAT_LOG_CRTI, "****[ncp1854_init] Unable to register driver (%d)\n", ret);
  584. return ret;
  585. }
  586. return 0;
  587. }
  588. static void __exit ncp1854_exit(void)
  589. {
  590. i2c_del_driver(&ncp1854_driver);
  591. }
  592. module_init(ncp1854_init);
  593. module_exit(ncp1854_exit);
  594. /* subsys_initcall(ncp1854_subsys_init); */
  595. MODULE_LICENSE("GPL");
  596. MODULE_DESCRIPTION("I2C ncp1854 Driver");
  597. MODULE_AUTHOR("YT Lee<yt.lee@mediatek.com>");