mt6360_pmu_charger.c 28 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043
  1. /* Copyright Statement:
  2. *
  3. * This software/firmware and related documentation ("MediaTek Software") are
  4. * protected under relevant copyright laws. The information contained herein
  5. * is confidential and proprietary to MediaTek Inc. and/or its licensors.
  6. * Without the prior written permission of MediaTek inc. and/or its licensors,
  7. * any reproduction, modification, use or disclosure of MediaTek Software,
  8. * and information contained herein, in whole or in part,
  9. * shall be strictly prohibited.
  10. */
  11. /* MediaTek Inc. (C) 2015. All rights reserved.
  12. *
  13. * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
  14. * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
  15. * RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER ON
  16. * AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
  17. * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
  18. * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
  19. * NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
  20. * SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
  21. * SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES TO LOOK ONLY TO SUCH
  22. * THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. RECEIVER EXPRESSLY
  23. * ACKNOWLEDGES THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO OBTAIN FROM ANY
  24. * THIRD PARTY ALL PROPER LICENSES CONTAINED IN MEDIATEK SOFTWARE. MEDIATEK SHALL
  25. * ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE RELEASES MADE TO RECEIVER'S
  26. * SPECIFICATION OR TO CONFORM TO A PARTICULAR STANDARD OR OPEN FORUM.
  27. * RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND CUMULATIVE
  28. * LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
  29. * AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
  30. * OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY RECEIVER TO
  31. * MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
  32. */
  33. #include <platform/mt_typedefs.h>
  34. #include <platform/errno.h>
  35. #include <platform/mt_i2c.h>
  36. #include <printf.h>
  37. #include <debug.h>
  38. #include <platform/timer.h>
  39. #include "mt6360_pmu_charger.h"
  40. #include "mtk_charger_intf.h"
  41. #define MT6360_PMU_CHARGER_LK_DRV_VERSION "1.0.0_MTK"
  42. /* ================= */
  43. /* Internal variable */
  44. /* ================= */
  45. enum mt6360_chg_mode {
  46. MT6360_CHG_MODE_UNKNOWN,
  47. MT6360_CHG_MODE_TRICHG,
  48. MT6360_CHG_MODE_PRECHG,
  49. MT6360_CHG_MODE_FASTCHG,
  50. };
  51. static const char *mt6360_chg_mode_name[] = {
  52. "unknown",
  53. "trickle-charge",
  54. "pre-charge",
  55. "fast-charge",
  56. };
  57. struct mt6360_pmu_chg_info {
  58. struct mtk_charger_info mchr_info;
  59. struct mt_i2c_t i2c;
  60. int i2c_log_level;
  61. u8 vid;
  62. u32 iprec;
  63. u32 ichg;
  64. u32 ichg_dis_chg;
  65. bool chg_en;
  66. u32 aicr;
  67. u32 mivr;
  68. u32 cv;
  69. bool wkard_en;
  70. };
  71. enum mt6360_iinlmtsel {
  72. MT6360_IIMLMTSEL_AICR_3250 = 0,
  73. MT6360_IIMLMTSEL_CHR_TYPE,
  74. MT6360_IINLMTSEL_AICR,
  75. MT6360_IINLMTSEL_LOWER_LEVEL, /* lower of above three */
  76. };
  77. enum mt6360_charging_status {
  78. MT6360_CHG_STATUS_READY = 0,
  79. MT6360_CHG_STATUS_PROGRESS,
  80. MT6360_CHG_STATUS_DONE,
  81. MT6360_CHG_STATUS_FAULT,
  82. MT6360_CHG_STATUS_MAX,
  83. };
  84. /* Charging status name */
  85. static const char *mt6360_chg_status_name[MT6360_CHG_STATUS_MAX] = {
  86. "ready", "progress", "done", "fault",
  87. };
  88. /* ========================= */
  89. /* I2C operations */
  90. /* ========================= */
  91. static int mt6360_i2c_write_byte(struct mt6360_pmu_chg_info *info,
  92. u8 cmd, u8 data)
  93. {
  94. struct mt_i2c_t *i2c = &info->i2c;
  95. int ret = I2C_OK;
  96. u8 write_buf[2] = {cmd, data};
  97. ret = i2c_write(i2c, write_buf, 2);
  98. if (ret != I2C_OK)
  99. dprintf(CRITICAL,
  100. "%s: I2CW[0x%02X] = 0x%02X failed, code = %d\n",
  101. __func__, cmd, data, ret);
  102. else
  103. dprintf(info->i2c_log_level, "%s: I2CW[0x%02X] = 0x%02X\n",
  104. __func__, cmd, data);
  105. return ret;
  106. }
  107. static int mt6360_i2c_read_byte(struct mt6360_pmu_chg_info *info,
  108. u8 cmd, u8 *data)
  109. {
  110. struct mt_i2c_t *i2c = &info->i2c;
  111. int ret = I2C_OK;
  112. u8 ret_data = cmd;
  113. ret = i2c_write_read(i2c, &ret_data, 1, 1);
  114. if (ret != I2C_OK)
  115. dprintf(CRITICAL, "%s: I2CR[0x%02X] failed, code = %d\n",
  116. __func__, cmd, ret);
  117. else {
  118. dprintf(info->i2c_log_level, "%s: I2CR[0x%02X] = 0x%02X\n",
  119. __func__, cmd, ret_data);
  120. *data = ret_data;
  121. }
  122. return ret;
  123. }
  124. static int mt6360_i2c_block_write(struct mt6360_pmu_chg_info *info,
  125. u8 cmd, int len, const u8 *data)
  126. {
  127. struct mt_i2c_t *i2c = &info->i2c;
  128. unsigned char write_buf[len + 1];
  129. write_buf[0] = cmd;
  130. memcpy(&write_buf[1], data, len);
  131. return i2c_write(i2c, write_buf, len + 1);
  132. }
  133. static int mt6360_i2c_block_read(struct mt6360_pmu_chg_info *info,
  134. u8 cmd, int len, u8 *data)
  135. {
  136. struct mt_i2c_t *i2c = &info->i2c;
  137. data[0] = cmd;
  138. return i2c_write_read(i2c, data, 1, len);
  139. }
  140. static int mt6360_i2c_update_bits(struct mt6360_pmu_chg_info *info,
  141. u8 cmd, u8 mask, u8 data)
  142. {
  143. int ret = 0;
  144. u8 reg_data = 0;
  145. ret = mt6360_i2c_read_byte(info, cmd, &reg_data);
  146. if (ret != I2C_OK)
  147. return ret;
  148. reg_data = reg_data & 0xFF;
  149. reg_data &= ~mask;
  150. reg_data |= (data & mask);
  151. return mt6360_i2c_write_byte(info, cmd, reg_data);
  152. }
  153. static inline int mt6360_set_bit(struct mt6360_pmu_chg_info *info,
  154. u8 reg, u8 mask)
  155. {
  156. return mt6360_i2c_update_bits(info, reg, mask, mask);
  157. }
  158. static inline int mt6360_clr_bit(struct mt6360_pmu_chg_info *info,
  159. u8 reg, u8 mask)
  160. {
  161. return mt6360_i2c_update_bits(info, reg, mask, 0x00);
  162. }
  163. /* ================== */
  164. /* internal functions */
  165. /* ================== */
  166. static int mt6360_enable_hidden_mode(struct mt6360_pmu_chg_info *info, bool en)
  167. {
  168. return mt6360_i2c_write_byte(info, MT6360_PMU_TM_PAS_CODE1, en ? 0x69 : 0);
  169. }
  170. static bool mt6360_is_hw_exist(struct mt6360_pmu_chg_info *info)
  171. {
  172. int ret = 0;
  173. u8 vid = 0, rev_id = 0;
  174. u8 data = 0;
  175. ret = mt6360_i2c_read_byte(info, MT6360_PMU_DEV_INFO, &data);
  176. if (ret != I2C_OK)
  177. return false;
  178. vid = data & 0xF0;
  179. rev_id = data & 0x0F;
  180. if (vid != MT6360_VENDOR_ID) {
  181. dprintf(CRITICAL, "%s: vid is not match(%d)\n", __func__, vid);
  182. return false;
  183. }
  184. dprintf(CRITICAL, "%s: rev_id = %d\n", __func__, rev_id);
  185. info->mchr_info.device_id = rev_id;
  186. info->vid = vid;
  187. return true;
  188. }
  189. static int mt6360_enable_ilim(struct mt6360_pmu_chg_info *info, bool enable)
  190. {
  191. dprintf(CRITICAL, "%s: enable ilim = %d\n", __func__, enable);
  192. return (enable ? mt6360_set_bit : mt6360_clr_bit)
  193. (info, MT6360_PMU_CHG_CTRL3, MT6360_MASK_ILIM_EN);
  194. }
  195. /* Select IINLMTSEL to use AICR */
  196. static int mt6360_select_input_current_limit(
  197. struct mt6360_pmu_chg_info *info, enum mt6360_iinlmtsel sel)
  198. {
  199. dprintf(CRITICAL, "%s: select input current limit = %d\n",
  200. __func__, sel);
  201. return mt6360_i2c_update_bits(info,
  202. MT6360_PMU_CHG_CTRL2,
  203. MT6360_MASK_IINLMTSEL,
  204. sel << MT6360_SHFT_IINLMTSEL);
  205. }
  206. static int mt6360_set_cv(struct mt6360_pmu_chg_info *info, u32 uV)
  207. {
  208. u8 data = 0;
  209. if (uV >= 3900)
  210. data = (uV - 3900) / 10;
  211. if (data > MT6360_VOREG_MAXVAL)
  212. data = MT6360_VOREG_MAXVAL;
  213. dprintf(CRITICAL, "%s: cv = %d\n", __func__, uV);
  214. return mt6360_i2c_update_bits(info,
  215. MT6360_PMU_CHG_CTRL4,
  216. MT6360_MASK_VOREG,
  217. data << MT6360_SHFT_VOREG);
  218. }
  219. static int mt6360_enable_wdt(struct mt6360_pmu_chg_info *info, bool en)
  220. {
  221. dprintf(CRITICAL, "%s: en = %d\n", __func__, en);
  222. return (en ? mt6360_set_bit : mt6360_clr_bit)
  223. (info, MT6360_PMU_CHG_CTRL13, MT6360_MASK_CHG_WDT_EN);
  224. }
  225. static int mt6360_get_charging_status(struct mt6360_pmu_chg_info *info,
  226. enum mt6360_charging_status *chg_stat)
  227. {
  228. int ret = 0;
  229. u8 data = 0;
  230. ret = mt6360_i2c_read_byte(info, MT6360_PMU_CHG_STAT, &data);
  231. if (ret != I2C_OK)
  232. return ret;
  233. *chg_stat = (data & MT6360_MASK_CHG_STAT) >> MT6360_SHFT_CHG_STAT;
  234. return ret;
  235. }
  236. static int mt6360_get_mivr(struct mt6360_pmu_chg_info *info, u32 *mivr)
  237. {
  238. int ret = 0;
  239. u8 data = 0;
  240. ret = mt6360_i2c_read_byte(info, MT6360_PMU_CHG_CTRL6, &data);
  241. if (ret != I2C_OK)
  242. return ret;
  243. data = (data & MT6360_MASK_MIVR) >> MT6360_SHFT_MIVR;
  244. *mivr = 3900 + (data * 100);
  245. return ret;
  246. }
  247. static int mt6360_get_ieoc(struct mt6360_pmu_chg_info *info, u32 *ieoc)
  248. {
  249. int ret = 0;
  250. u8 data = 0;
  251. ret = mt6360_i2c_read_byte(info, MT6360_PMU_CHG_CTRL9, &data);
  252. if (ret != I2C_OK)
  253. return ret;
  254. data = (data & MT6360_MASK_IEOC) >> MT6360_SHFT_IEOC;
  255. *ieoc = 100 + (data * 50);
  256. return ret;
  257. }
  258. static int mt6360_is_charging_enable(struct mt6360_pmu_chg_info *info,
  259. bool *enable)
  260. {
  261. int ret = 0;
  262. u8 data = 0;
  263. ret = mt6360_i2c_read_byte(info, MT6360_PMU_CHG_CTRL2, &data);
  264. if (ret != I2C_OK)
  265. return ret;
  266. *enable = (data & MT6360_MASK_CHG_EN) ? true : false;
  267. return ret;
  268. }
  269. /* =========================================================== */
  270. /* The following is implementation for interface of mt_charger */
  271. /* =========================================================== */
  272. static int mt_charger_set_ichg(struct mtk_charger_info *mchr_info, u32 ichg)
  273. {
  274. struct mt6360_pmu_chg_info *info =
  275. (struct mt6360_pmu_chg_info *)mchr_info;
  276. int ret = 0;
  277. u8 data = 0;
  278. dprintf(CRITICAL, "%s: ichg = %d\n", __func__, ichg);
  279. if (ichg >= 100)
  280. data = (ichg - 100) / 100;
  281. if (data > MT6360_ICHG_MAXVAL)
  282. data = MT6360_ICHG_MAXVAL;
  283. ret = mt6360_i2c_update_bits(info,
  284. MT6360_PMU_CHG_CTRL7,
  285. MT6360_MASK_ICHG,
  286. data << MT6360_SHFT_ICHG);
  287. if (ret < 0)
  288. dprintf(CRITICAL, "%s: fail(%d)\n", __func__, ret);
  289. else
  290. info->ichg = ichg;
  291. return ret;
  292. }
  293. static int mt_charger_enable_charging(struct mtk_charger_info *mchr_info,
  294. bool enable)
  295. {
  296. struct mt6360_pmu_chg_info *info =
  297. (struct mt6360_pmu_chg_info *)mchr_info;
  298. int ret = 0;
  299. u32 ichg_ramp_t = 0;
  300. u8 data = 0;
  301. if (info->chg_en == enable) {
  302. dprintf(CRITICAL,
  303. "%s: is the same, en = %d\n", __func__, enable);
  304. return 0;
  305. }
  306. ret = mt6360_i2c_read_byte(info, MT6360_PMU_CHRDET_STAT, &data);
  307. if (ret != I2C_OK)
  308. goto bypass_wkard;
  309. if (!(data & MT6360_MASK_CHRDET_EXT_EVT)) {
  310. dprintf(CRITICAL, "%s: pwr_rdy = 0, bypass wkard\n", __func__);
  311. goto bypass_wkard;
  312. }
  313. if (info->ichg < 500) {
  314. dprintf(CRITICAL, "%s: ichg < 500, bypass wkard\n", __func__);
  315. goto bypass_wkard;
  316. }
  317. /* Workaround for avoid vsys overshoot when charge disable */
  318. if (!enable) {
  319. info->ichg_dis_chg = info->ichg;
  320. ichg_ramp_t = (info->ichg - 500) / 50 * 2;
  321. /* Set ichg 500mA */
  322. ret = mt6360_i2c_update_bits(info,
  323. MT6360_PMU_CHG_CTRL7,
  324. MT6360_MASK_ICHG,
  325. 0x04 << MT6360_SHFT_ICHG);
  326. if (ret < 0) {
  327. dprintf(CRITICAL, "%s: set ichg fail\n", __func__);
  328. return ret;
  329. }
  330. mdelay(ichg_ramp_t);
  331. } else {
  332. if (info->ichg == info->ichg_dis_chg) {
  333. ret = mt_charger_set_ichg(mchr_info, info->ichg);
  334. if (ret < 0) {
  335. dprintf(CRITICAL,
  336. "%s: set ichg fail\n", __func__);
  337. return ret;
  338. }
  339. }
  340. }
  341. bypass_wkard:
  342. ret = (enable ? mt6360_set_bit : mt6360_clr_bit)
  343. (info, MT6360_PMU_CHG_CTRL2, MT6360_MASK_CHG_EN);
  344. if (ret < 0)
  345. dprintf(CRITICAL, "%s: fail, en = %d\n", __func__, enable);
  346. else
  347. info->chg_en = enable;
  348. return ret;
  349. }
  350. static int mt_charger_get_ichg(struct mtk_charger_info *mchr_info, u32 *ichg)
  351. {
  352. struct mt6360_pmu_chg_info *info =
  353. (struct mt6360_pmu_chg_info *)mchr_info;
  354. int ret = 0;
  355. u8 data = 0;
  356. ret = mt6360_i2c_read_byte(info, MT6360_PMU_CHG_CTRL7, &data);
  357. if (ret != I2C_OK)
  358. return ret;
  359. data = (data & MT6360_MASK_ICHG) >> MT6360_SHFT_ICHG;
  360. *ichg = 100 + (data * 100);
  361. return ret;
  362. }
  363. static int mt_charger_set_iprec(struct mtk_charger_info *mchr_info, u32 iprec)
  364. {
  365. struct mt6360_pmu_chg_info *info =
  366. (struct mt6360_pmu_chg_info *)mchr_info;
  367. u8 data = 0;
  368. dprintf(CRITICAL, "%s: iprec = %d\n", __func__, iprec);
  369. if (iprec >= 100)
  370. data = (iprec - 100) / 50;
  371. if (data > MT6360_IPREC_MAXVAL)
  372. data = MT6360_IPREC_MAXVAL;
  373. return mt6360_i2c_update_bits(info,
  374. MT6360_PMU_CHG_CTRL8,
  375. MT6360_MASK_IPREC,
  376. data << MT6360_SHFT_IPREC);
  377. }
  378. static enum mt6360_chg_mode mt6360_get_charging_mode(
  379. struct mt6360_pmu_chg_info *info)
  380. {
  381. int ret = 0;
  382. u8 data = 0;
  383. dprintf(CRITICAL, "%s\n", __func__);
  384. ret = mt6360_i2c_read_byte(info, MT6360_PMU_CHG_STAT, &data);
  385. if (ret < 0)
  386. return MT6360_CHG_MODE_UNKNOWN;
  387. if (data & MT6360_MASK_VBAT_TRI)
  388. return MT6360_CHG_MODE_TRICHG;
  389. return (data & MT6360_MASK_VBAT_LVL) ? MT6360_CHG_MODE_FASTCHG :
  390. MT6360_CHG_MODE_PRECHG;
  391. }
  392. static int mt_charger_set_ichg_ext(struct mtk_charger_info *mchr_info, u32 ichg)
  393. {
  394. struct mt6360_pmu_chg_info *info =
  395. (struct mt6360_pmu_chg_info *)mchr_info;
  396. enum mt6360_chg_mode cur_mode = MT6360_CHG_MODE_UNKNOWN;
  397. dprintf(CRITICAL, "%s: ichg = %u\n", __func__, ichg);
  398. cur_mode = mt6360_get_charging_mode(info);
  399. if (cur_mode == MT6360_CHG_MODE_UNKNOWN) {
  400. dprintf(CRITICAL, "%s: get charging mode fail\n", __func__);
  401. return -EINVAL;
  402. }
  403. info->ichg = ichg;
  404. if (cur_mode != MT6360_CHG_MODE_FASTCHG) {
  405. dprintf(CRITICAL, "%s: not in fast-charge mode\n", __func__);
  406. return 0;
  407. }
  408. if (info->wkard_en) {
  409. dprintf(CRITICAL, "%s: in work around\n", __func__);
  410. return 0;
  411. }
  412. return mt_charger_set_ichg(mchr_info, ichg);
  413. }
  414. static int mt_charger_get_aicr(struct mtk_charger_info *mchr_info, u32 *aicr)
  415. {
  416. struct mt6360_pmu_chg_info *info =
  417. (struct mt6360_pmu_chg_info *)mchr_info;
  418. int ret = 0;
  419. u8 data = 0;
  420. ret = mt6360_i2c_read_byte(info, MT6360_PMU_CHG_CTRL3, &data);
  421. if (ret != I2C_OK)
  422. return ret;
  423. data = (data & MT6360_MASK_AICR) >> MT6360_SHFT_AICR;
  424. *aicr = 100 + (data * 50);
  425. return ret;
  426. }
  427. static int mt6360_adc_get_process_val(struct mt6360_pmu_chg_info *info,
  428. enum mt6360_adc_channel chan, u32 *val)
  429. {
  430. int ret = 0;
  431. u8 data = 0;
  432. switch (chan) {
  433. case MT6360_ADC_USBID:
  434. case MT6360_ADC_VREF_TS:
  435. case MT6360_ADC_TS:
  436. *val *= 1250;
  437. break;
  438. case MT6360_ADC_TEMP_JC:
  439. *val -= 40;
  440. break;
  441. case MT6360_ADC_VBAT:
  442. case MT6360_ADC_VSYS:
  443. case MT6360_ADC_CHG_VDDP:
  444. *val *= 1250;
  445. break;
  446. case MT6360_ADC_VBUSDIV5:
  447. *val *= 6250;
  448. break;
  449. case MT6360_ADC_VBUSDIV2:
  450. case MT6360_ADC_IBAT:
  451. *val *= 2500;
  452. break;
  453. case MT6360_ADC_IBUS:
  454. ret = mt6360_i2c_read_byte(info, MT6360_PMU_CHG_CTRL3, &data);
  455. if (ret < 0)
  456. return ret;
  457. if (((data & 0xfc) >> 2) < 0x6)
  458. *val *= 1900;
  459. else
  460. *val *= 2500;
  461. break;
  462. default:
  463. break;
  464. }
  465. return ret;
  466. }
  467. static int mt_charger_get_adc(struct mtk_charger_info *mchr_info,
  468. int chan, u32 *val)
  469. {
  470. struct mt6360_pmu_chg_info *info =
  471. (struct mt6360_pmu_chg_info *)mchr_info;
  472. u8 tmp[3], rpt[3];
  473. u8 data = 0;
  474. int i, ret = 0, max_retry_cnt = 20;
  475. dprintf(CRITICAL, "%s: ++\n", __func__);
  476. if (chan >= MT6360_ADC_MAX) {
  477. dprintf(CRITICAL, "%s: undeine channel(%d)\n",
  478. __func__, chan);
  479. ret = -EINVAL;
  480. goto err_adc_init;
  481. }
  482. /* first reset all channels and adc en */
  483. memset(tmp, 0, sizeof(tmp));
  484. ret = mt6360_i2c_block_write(info, MT6360_PMU_ADC_CONFIG, 3, tmp);
  485. if (ret < 0) {
  486. dprintf(CRITICAL, "%s: reset all channels fail\n", __func__);
  487. goto err_adc_init;
  488. }
  489. /* enable adc_donei irq */
  490. ret = mt6360_clr_bit(info, MT6360_PMU_CHG_MASK6, MT6360_MASK_ADC_DONE);
  491. if (ret < 0) {
  492. dprintf(CRITICAL, "%s: unmask adc_donei fail\n", __func__);
  493. goto err_adc_conv;
  494. }
  495. /* select preferred channel : vbus */
  496. ret = mt6360_i2c_update_bits(info,
  497. MT6360_PMU_ADC_RPT_1, 0xf0, chan << 4);
  498. if (ret < 0) {
  499. dprintf(CRITICAL, "%s: select prefer channel fail\n", __func__);
  500. goto err_adc_conv;
  501. }
  502. /* enable vbus adc channel and adc_en */
  503. tmp[0] |= (1 << 7);
  504. if ((chan / 8) > 0)
  505. tmp[0] |= (1 << (chan % 8));
  506. else
  507. tmp[1] |= (1 << (chan % 8));
  508. ret = mt6360_i2c_block_write(info, MT6360_PMU_ADC_CONFIG, 2, tmp);
  509. if (ret < 0) {
  510. dprintf(CRITICAL,
  511. "%s: enable vbus adc and adc en fail\n", __func__);
  512. goto err_adc_conv;
  513. }
  514. /* wait adc conversion done */
  515. for (i = 0; i < max_retry_cnt; i++) {
  516. mdelay(30);
  517. /* read adc conversion donei event */
  518. ret = mt6360_i2c_read_byte(info, MT6360_PMU_CHG_IRQ6, &data);
  519. if (ret < 0)
  520. goto err_adc_conv;
  521. if (!(data & MT6360_MASK_ADC_DONE))
  522. continue;
  523. ret = mt6360_set_bit(info, MT6360_PMU_CHG_IRQ6,
  524. MT6360_MASK_ADC_DONE);
  525. if (ret < 0) {
  526. dprintf(CRITICAL,
  527. "%s: clear adc donei irq fail\n", __func__);
  528. goto err_adc_conv;
  529. }
  530. memset(rpt, 0, sizeof(rpt));
  531. ret = mt6360_i2c_block_read(info, MT6360_PMU_ADC_RPT_1, 3, rpt);
  532. if (ret < 0)
  533. goto err_adc_conv;
  534. if ((rpt[0] & 0x0f) != chan) {
  535. dprintf(CRITICAL, "%s: not want channel report(%d)\n",
  536. __func__, rpt[0]);
  537. continue;
  538. }
  539. *val = ((rpt[1] << 8) | rpt[2]);
  540. ret = mt6360_adc_get_process_val(info, chan, val);
  541. break;
  542. }
  543. if (i == max_retry_cnt) {
  544. dprintf(CRITICAL, "%s: reach adc retry cnt\n", __func__);
  545. ret = -EBUSY;
  546. goto err_adc_conv;
  547. }
  548. err_adc_conv:
  549. tmp[0] &= ~(0x7);
  550. tmp[1] = 0;
  551. mt6360_i2c_block_write(info, MT6360_PMU_ADC_CONFIG, 2, tmp);
  552. mt6360_set_bit(info, MT6360_PMU_CHG_MASK6, MT6360_MASK_ADC_DONE);
  553. err_adc_init:
  554. dprintf(CRITICAL, "%s: --\n", __func__);
  555. return ret;
  556. }
  557. static int mt_charger_get_vbus(struct mtk_charger_info *mchr_info, u32 *vbus)
  558. {
  559. return mt_charger_get_adc(mchr_info, MT6360_ADC_VBUSDIV5, vbus);
  560. }
  561. static int mt_charger_set_aicr(struct mtk_charger_info *mchr_info, u32 aicr)
  562. {
  563. struct mt6360_pmu_chg_info *info =
  564. (struct mt6360_pmu_chg_info *)mchr_info;
  565. u8 data = 0;
  566. dprintf(CRITICAL, "%s: aicr = %d\n", __func__, aicr);
  567. if (aicr >= 100)
  568. data = (aicr - 100) / 50;
  569. if (data > MT6360_AICR_MAXVAL)
  570. data = MT6360_AICR_MAXVAL;
  571. return mt6360_i2c_update_bits(info,
  572. MT6360_PMU_CHG_CTRL3,
  573. MT6360_MASK_AICR,
  574. data << MT6360_SHFT_AICR);
  575. }
  576. static int mt_charger_set_aicr_ext(struct mtk_charger_info *mchr_info, u32 aicr)
  577. {
  578. struct mt6360_pmu_chg_info *info =
  579. (struct mt6360_pmu_chg_info *)mchr_info;
  580. enum mt6360_chg_mode cur_mode = MT6360_CHG_MODE_UNKNOWN;
  581. dprintf(CRITICAL, "%s: aicr = %d\n", __func__, aicr);
  582. cur_mode = mt6360_get_charging_mode(info);
  583. if (cur_mode == MT6360_CHG_MODE_UNKNOWN) {
  584. dprintf(CRITICAL, "%s: get charging mode fail\n", __func__);
  585. return -EINVAL;
  586. }
  587. info->aicr = aicr;
  588. if (cur_mode != MT6360_CHG_MODE_FASTCHG) {
  589. dprintf(CRITICAL, "%s: not in fast-charge mode\n", __func__);
  590. return 0;
  591. }
  592. if (info->wkard_en) {
  593. dprintf(CRITICAL, "%s: in work around\n", __func__);
  594. return 0;
  595. }
  596. return mt_charger_set_aicr(mchr_info, aicr);
  597. }
  598. static int mt_charger_set_mivr(struct mtk_charger_info *mchr_info, u32 mivr)
  599. {
  600. struct mt6360_pmu_chg_info *info =
  601. (struct mt6360_pmu_chg_info *)mchr_info;
  602. u8 data = 0;
  603. dprintf(CRITICAL, "%s: mivr = %d\n", __func__, mivr);
  604. if (mivr >= 3900)
  605. data = (mivr - 3900) / 100;
  606. if (data > MT6360_MIVR_MAXVAL)
  607. data = MT6360_MIVR_MAXVAL;
  608. return mt6360_i2c_update_bits(info,
  609. MT6360_PMU_CHG_CTRL6,
  610. MT6360_MASK_MIVR,
  611. data << MT6360_SHFT_MIVR);
  612. }
  613. static int mt_charger_enable_power_path(struct mtk_charger_info *mchr_info,
  614. bool enable)
  615. {
  616. struct mt6360_pmu_chg_info *info =
  617. (struct mt6360_pmu_chg_info *)mchr_info;
  618. dprintf(CRITICAL, "%s: enable = %d\n", __func__, enable);
  619. return (enable ? mt6360_clr_bit : mt6360_set_bit)
  620. (info, MT6360_PMU_CHG_CTRL1, MT6360_MASK_FORCE_SLEEP);
  621. }
  622. static int mt_charger_reset_pumpx(struct mtk_charger_info *mchr_info,
  623. bool reset)
  624. {
  625. struct mt6360_pmu_chg_info *info =
  626. (struct mt6360_pmu_chg_info *)mchr_info;
  627. if (reset)
  628. mt_charger_get_aicr(mchr_info, &info->aicr);
  629. return mt_charger_set_aicr(mchr_info, reset ? 100 : info->aicr);
  630. }
  631. static int mt_charger_enable_wdt(struct mtk_charger_info *mchr_info, bool en)
  632. {
  633. struct mt6360_pmu_chg_info *info =
  634. (struct mt6360_pmu_chg_info *)mchr_info;
  635. return mt6360_enable_wdt(info, en);
  636. }
  637. static int mt_charger_dump_register(struct mtk_charger_info *mchr_info)
  638. {
  639. struct mt6360_pmu_chg_info *info =
  640. (struct mt6360_pmu_chg_info *)mchr_info;
  641. enum mt6360_charging_status chg_status = MT6360_CHG_STATUS_READY;
  642. u32 ichg = 0, aicr = 0, mivr = 0, ieoc = 0;
  643. bool chg_en = 0;
  644. int ret = 0;
  645. ret = mt_charger_get_ichg(mchr_info, &ichg);
  646. ret = mt_charger_get_aicr(mchr_info, &aicr);
  647. ret = mt6360_get_mivr(info, &mivr);
  648. ret = mt6360_get_ieoc(info, &ieoc);
  649. ret = mt6360_is_charging_enable(info, &chg_en);
  650. ret = mt6360_get_charging_status(info, &chg_status);
  651. dprintf(CRITICAL,
  652. "%s: ICHG = %dmA, AICR = %dmA, MIVR = %dmV, IEOC = %dmA\n",
  653. __func__, ichg, aicr, mivr, ieoc);
  654. dprintf(CRITICAL, "%s: CHG_EN = %d, CHG_STATUS = %s\n",
  655. __func__, chg_en, mt6360_chg_status_name[chg_status]);
  656. return ret;
  657. }
  658. static int mt6360_fix_current_accuracy(struct mtk_charger_info *mchr_info,
  659. bool enable)
  660. {
  661. struct mt6360_pmu_chg_info *info =
  662. (struct mt6360_pmu_chg_info *)mchr_info;
  663. u8 swit_feq[3] = { 0x80, 0x20, 0x00 };
  664. int i, ret = 0;
  665. if (!(info->wkard_en ^ enable))
  666. return 0;
  667. ret = mt6360_enable_hidden_mode(info, true);
  668. if (ret < 0) {
  669. dprintf(CRITICAL, "%s: enter hidden mode fail\n", __func__);
  670. return ret;
  671. }
  672. if (enable) {
  673. /* Set chg/otg switch frequence 0.75MHz */
  674. ret = mt6360_set_bit(info, MT6360_PMU_CHG_CTRL1, 0x80);
  675. if (ret < 0) {
  676. dprintf(CRITICAL,
  677. "%s: set switch feq to 0.75MHz fail\n",
  678. __func__);
  679. goto out;
  680. }
  681. /* Set buck slope ratio to 0.6x */
  682. ret = mt6360_i2c_update_bits(info, MT6360_PMU_CHG_HIDDEN_CTRL10,
  683. 0x07, 0);
  684. if (ret < 0) {
  685. dprintf(CRITICAL,
  686. "%s: set buck slope ratio 0.6x fail\n",
  687. __func__);
  688. goto out;
  689. }
  690. /* Set Power path MOS gate driving slew rate to 2x */
  691. ret = mt6360_set_bit(info, MT6360_PMU_CHG_HIDDEN_CTRL11, 0xC0);
  692. if (ret < 0) {
  693. dprintf(CRITICAL,
  694. "%s: set pp gate slew rate fail\n", __func__);
  695. goto out;
  696. }
  697. } else {
  698. /* Clear Power path MOS gate driving slew rate to 1x */
  699. ret = mt6360_clr_bit(info, MT6360_PMU_CHG_HIDDEN_CTRL11, 0xC0);
  700. if (ret < 0) {
  701. dprintf(CRITICAL,
  702. "%s: clr pp gate slew rate fail\n", __func__);
  703. goto out;
  704. }
  705. /* set buck slope ratio step 0.6x to 1.8x */
  706. for (i = 0; i < 7; i++) {
  707. ret = mt6360_i2c_update_bits(info,
  708. MT6360_PMU_CHG_HIDDEN_CTRL10, 0x07, i);
  709. if (ret < 0) {
  710. dprintf(CRITICAL,
  711. "%s: step up buck slope ratio fail\n",
  712. __func__);
  713. goto out;
  714. }
  715. }
  716. /* Set chg/otg switch frequence step 0.75->1.0->1.5MHz */
  717. for (i = 0; i < 3; i++) {
  718. ret = mt6360_i2c_update_bits(info, MT6360_PMU_CHG_CTRL1,
  719. 0xa0, swit_feq[i]);
  720. if (ret < 0) {
  721. dprintf(CRITICAL,
  722. "%s: step down switch feq fail\n",
  723. __func__);
  724. goto out;
  725. }
  726. }
  727. }
  728. info->wkard_en = enable;
  729. out:
  730. mt6360_enable_hidden_mode(info, false);
  731. return (ret < 0) ? ret : 0;
  732. }
  733. static int mt_charger_check_charging_mode(struct mtk_charger_info *mchr_info)
  734. {
  735. struct mt6360_pmu_chg_info *info =
  736. (struct mt6360_pmu_chg_info *)mchr_info;
  737. int ret = 0;
  738. static enum mt6360_chg_mode pre_mode = MT6360_CHG_MODE_UNKNOWN;
  739. enum mt6360_chg_mode cur_mode = MT6360_CHG_MODE_UNKNOWN;
  740. u8 data = 0;
  741. dprintf(CRITICAL, "%s\n", __func__);
  742. ret = mt6360_i2c_read_byte(info, MT6360_PMU_CHRDET_STAT, &data);
  743. if (ret < 0)
  744. return ret;
  745. if (!(data & MT6360_MASK_CHRDET_EXT_EVT)) {
  746. dprintf(CRITICAL, "%s: pwr_rdy = 0\n", __func__);
  747. return 0;
  748. }
  749. ret = mt6360_i2c_read_byte(info, MT6360_PMU_CHG_CTRL2, &data);
  750. if (ret < 0)
  751. return ret;
  752. if (!(data & MT6360_MASK_CFO_EN)) {
  753. dprintf(CRITICAL, "%s: CFO_EN = 0\n", __func__);
  754. return 0;
  755. }
  756. cur_mode = mt6360_get_charging_mode(info);
  757. if (cur_mode == MT6360_CHG_MODE_UNKNOWN) {
  758. dprintf(CRITICAL, "%s: get charging mode fail\n", __func__);
  759. return -EINVAL;
  760. }
  761. dprintf(CRITICAL, "%s: in %s mode, previously in %s mode\n", __func__,
  762. mt6360_chg_mode_name[cur_mode],
  763. mt6360_chg_mode_name[pre_mode]);
  764. if (cur_mode == pre_mode)
  765. return 0;
  766. switch (cur_mode) {
  767. case MT6360_CHG_MODE_TRICHG:
  768. ret = mt_charger_set_ichg(mchr_info, info->iprec);
  769. if (ret < 0) {
  770. dprintf(CRITICAL,
  771. "%s: set ichg to %umA fail\n",
  772. __func__, info->iprec);
  773. return ret;
  774. }
  775. ret = mt6360_fix_current_accuracy(mchr_info, true);
  776. if (ret < 0) {
  777. dprintf(CRITICAL,
  778. "%s: fix current accuracy fail\n", __func__);
  779. return ret;
  780. }
  781. break;
  782. case MT6360_CHG_MODE_PRECHG:
  783. ret = mt_charger_set_ichg(mchr_info, info->iprec);
  784. if (ret < 0) {
  785. dprintf(CRITICAL,
  786. "%s: set ichg to %umA fail\n",
  787. __func__, info->iprec);
  788. return ret;
  789. }
  790. ret = mt6360_fix_current_accuracy(mchr_info,
  791. (info->iprec < 500) ?
  792. true : false);
  793. if (ret < 0) {
  794. dprintf(CRITICAL,
  795. "%s: fix current accuracy fail\n", __func__);
  796. return ret;
  797. }
  798. break;
  799. case MT6360_CHG_MODE_FASTCHG:
  800. ret = mt6360_fix_current_accuracy(mchr_info, false);
  801. if (ret < 0) {
  802. dprintf(CRITICAL,
  803. "%s: fix current accuracy fail\n", __func__);
  804. return ret;
  805. }
  806. ret = mt_charger_set_aicr(mchr_info, info->aicr);
  807. if (ret < 0) {
  808. dprintf(CRITICAL,
  809. "%s: set aicr to %umA fail\n",
  810. __func__, info->aicr);
  811. return ret;
  812. }
  813. ret = mt_charger_set_ichg(mchr_info, info->ichg);
  814. if (ret < 0) {
  815. dprintf(CRITICAL,
  816. "%s: set ichg to %umA fail\n",
  817. __func__, info->ichg);
  818. return ret;
  819. }
  820. break;
  821. default:
  822. dprintf(CRITICAL, "%s: Unkown mode\n", __func__);
  823. break;
  824. }
  825. pre_mode = cur_mode;
  826. return 0;
  827. }
  828. static struct mtk_charger_ops mt6360_mchr_ops = {
  829. .dump_register = mt_charger_dump_register,
  830. .enable_charging = mt_charger_enable_charging,
  831. .get_ichg = mt_charger_get_ichg,
  832. .set_ichg = mt_charger_set_ichg_ext,
  833. .get_aicr = mt_charger_get_aicr,
  834. .get_adc = mt_charger_get_adc,
  835. .get_vbus = mt_charger_get_vbus,
  836. .set_aicr = mt_charger_set_aicr_ext,
  837. .set_mivr = mt_charger_set_mivr,
  838. .enable_power_path = mt_charger_enable_power_path,
  839. .reset_pumpx = mt_charger_reset_pumpx,
  840. .enable_wdt = mt_charger_enable_wdt,
  841. .check_charging_mode = mt_charger_check_charging_mode,
  842. };
  843. /* Info of primary charger */
  844. static struct mt6360_pmu_chg_info g_mpci = {
  845. .mchr_info = {
  846. .name = "primary_charger",
  847. .device_id = -1,
  848. .mchr_ops = &mt6360_mchr_ops,
  849. },
  850. .i2c = {
  851. .id = I2C5,
  852. .addr = MT6360_SLAVE_ADDR,
  853. .mode = HS_MODE,
  854. .speed = 400,
  855. .pushpull = true,
  856. },
  857. .i2c_log_level = INFO,
  858. .vid = 0x00,
  859. .iprec = 150,
  860. .ichg = 2000,
  861. .aicr = 500,
  862. .mivr = 4500,
  863. .cv = 4350,
  864. .wkard_en = false,
  865. .ichg_dis_chg = 2000,
  866. .chg_en = true,
  867. };
  868. static int mt6360_chg_init_setting(struct mt6360_pmu_chg_info *info)
  869. {
  870. int ret = 0;
  871. dprintf(CRITICAL, "%s: starts\n", __func__);
  872. ret = mt6360_enable_wdt(info, true);
  873. if (ret < 0) {
  874. dprintf(CRITICAL, "%s: enable wdt failed\n", __func__);
  875. goto out;
  876. }
  877. /* Select input current limit to referenced from AICR */
  878. ret = mt6360_select_input_current_limit(info,
  879. MT6360_IINLMTSEL_AICR);
  880. if (ret < 0) {
  881. dprintf(CRITICAL, "%s: select input current limit failed\n",
  882. __func__);
  883. goto out;
  884. }
  885. mdelay(5);
  886. /* Disable HW iinlimit, use SW */
  887. ret = mt6360_enable_ilim(info, false);
  888. if (ret < 0) {
  889. dprintf(CRITICAL, "%s: disable ilim failed\n", __func__);
  890. goto out;
  891. }
  892. ret = mt_charger_set_iprec(&info->mchr_info, info->iprec);
  893. if (ret < 0) {
  894. dprintf(CRITICAL, "%s: set iprec failed\n", __func__);
  895. goto out;
  896. }
  897. /* Set ichg 500mA for vsys overshoot */
  898. ret = mt_charger_set_ichg(&info->mchr_info, 500);
  899. if (ret < 0) {
  900. dprintf(CRITICAL, "%s: set ichg failed\n", __func__);
  901. goto out;
  902. }
  903. ret = mt_charger_set_aicr(&info->mchr_info, info->aicr);
  904. if (ret < 0) {
  905. dprintf(CRITICAL, "%s: set aicr failed\n", __func__);
  906. goto out;
  907. }
  908. ret = mt_charger_set_mivr(&info->mchr_info, info->mivr);
  909. if (ret < 0) {
  910. dprintf(CRITICAL, "%s: set mivr failed\n", __func__);
  911. goto out;
  912. }
  913. ret = mt6360_set_cv(info, info->cv);
  914. if (ret < 0) {
  915. dprintf(CRITICAL, "%s: set cv failed\n", __func__);
  916. goto out;
  917. }
  918. /* Fix pre-chg/fast-chg current loop not correct */
  919. ret = mt_charger_check_charging_mode(&info->mchr_info);
  920. if (ret < 0) {
  921. dprintf(CRITICAL, "%s: check charging mode fail\n", __func__);
  922. goto out;
  923. }
  924. /* Disable sys drop improvement for download mode */
  925. ret = mt6360_clr_bit(info, MT6360_PMU_CHG_CTRL20, MT6360_MASK_EN_SDI);
  926. if (ret < 0)
  927. dprintf(CRITICAL,
  928. "%s: disable sys drop improvement fail\n", __func__);
  929. out:
  930. return ret;
  931. }
  932. int mt6360_chg_probe(void)
  933. {
  934. int ret = 0;
  935. /* Check primary charger */
  936. if (!mt6360_is_hw_exist(&g_mpci))
  937. return -ENODEV;
  938. dprintf(CRITICAL, "%s: %s\n",
  939. __func__, MT6360_PMU_CHARGER_LK_DRV_VERSION);
  940. ret = mt6360_chg_init_setting(&g_mpci);
  941. if (ret < 0) {
  942. dprintf(CRITICAL, "%s: init setting fail\n", __func__);
  943. return ret;
  944. }
  945. mtk_charger_set_info(&(g_mpci.mchr_info));
  946. return ret;
  947. }
  948. /*
  949. * Revision Note
  950. * 1.0.0
  951. * (1) Initial release
  952. */