sm5414_charger.c 31 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196
  1. /*
  2. * SM5414_charger.c
  3. * SiliconMitus SM5414 Charger Driver
  4. *
  5. * Copyright (C) 2013 SiliconMitus
  6. *
  7. *
  8. * This software is licensed under the terms of the GNU General Public
  9. * License version 2, as published by the Free Software Foundation, and
  10. * may be copied, distributed, and modified under those terms.
  11. *
  12. * This program is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. * GNU General Public License for more details.
  16. *
  17. */
  18. #define DEBUG
  19. #include <linux/battery/sec_charger.h>
  20. #include <linux/seq_file.h>
  21. #include <linux/debugfs.h>
  22. #include <linux/seq_file.h>
  23. #include <linux/gpio.h>
  24. #include <linux/gpio-pxa.h>
  25. #include <linux/of_device.h>
  26. #include <linux/of_gpio.h>
  27. #include <linux/of_irq.h>
  28. static int charger_health = POWER_SUPPLY_HEALTH_GOOD;
  29. static int SM5414_i2c_write(struct i2c_client *client,
  30. int reg, u8 *buf)
  31. {
  32. int ret;
  33. ret = i2c_smbus_write_i2c_block_data(client, reg, 1, buf);
  34. if (ret < 0)
  35. dev_err(&client->dev, "%s: Error(%d)\n", __func__, ret);
  36. return ret;
  37. }
  38. static int SM5414_i2c_read(struct i2c_client *client,
  39. int reg, u8 *buf)
  40. {
  41. int ret;
  42. ret = i2c_smbus_read_i2c_block_data(client, reg, 1, buf);
  43. if (ret < 0)
  44. dev_err(&client->dev, "%s: Error(%d)\n", __func__, ret);
  45. return ret;
  46. }
  47. #if 0
  48. static void SM5414_test_read(struct i2c_client *client)
  49. {
  50. u8 data = 0;
  51. u32 addr = 0;
  52. //0x00~02 are R/C
  53. for (addr = SM5414_INTMASK1; addr <= SM5414_CHGCTRL5; addr++) {
  54. SM5414_i2c_read(client, addr, &data);
  55. dev_info(&client->dev,
  56. "SM5414 addr : 0x%02x data : 0x%02x\n", addr, data);
  57. }
  58. }
  59. #endif
  60. static void SM5414_read_regs(struct i2c_client *client, char *str)
  61. {
  62. u8 data = 0;
  63. u32 addr = 0;
  64. //0x00~02 are R/C (read and clear)
  65. for (addr = SM5414_INTMASK1; addr <= SM5414_CHGCTRL5; addr++) {
  66. SM5414_i2c_read(client, addr, &data);
  67. sprintf(str+strlen(str), "0x%x, ", data);
  68. }
  69. }
  70. static int SM5414_get_charging_status(struct i2c_client *client)
  71. {
  72. int status = POWER_SUPPLY_STATUS_UNKNOWN;
  73. struct sec_charger_info *charger = i2c_get_clientdata(client);
  74. int nCHG;
  75. u8 int2, chg_en;
  76. union power_supply_propval value;
  77. SM5414_i2c_read(client, SM5414_INT2, &int2);
  78. SM5414_i2c_read(client, SM5414_CTRL, &chg_en);
  79. if((int2 & SM5414_INT2_DONE) || (int2 & SM5414_INT2_TOPOFF)) {
  80. psy_do_property(charger->pdata->fuelgauge_name, get,
  81. POWER_SUPPLY_PROP_CAPACITY, value);
  82. if ((value.intval > 96) &&
  83. (charger->cable_type != POWER_SUPPLY_TYPE_BATTERY)) {
  84. status = POWER_SUPPLY_STATUS_FULL;
  85. charger->is_fullcharged = true;
  86. dev_info(&client->dev,
  87. "%s : Power Supply Full\n", __func__);
  88. }
  89. } else if (chg_en & CHARGE_EN) {
  90. nCHG = gpio_get_value(charger->pdata->chg_gpio_en);
  91. if ((nCHG) || (charger_health != POWER_SUPPLY_HEALTH_GOOD))
  92. status = POWER_SUPPLY_STATUS_DISCHARGING;
  93. else
  94. status = POWER_SUPPLY_STATUS_CHARGING;
  95. } else {
  96. status = POWER_SUPPLY_STATUS_DISCHARGING;
  97. }
  98. return (int)status;
  99. }
  100. static int SM5414_get_charging_health(struct i2c_client *client)
  101. {
  102. static int health = POWER_SUPPLY_HEALTH_GOOD;
  103. struct sec_charger_info *charger = i2c_get_clientdata(client);
  104. u8 int1;
  105. SM5414_i2c_read(client, SM5414_INT1, &int1);
  106. dev_info(&client->dev,
  107. "%s : SM5414_INT1 : 0x%02x\n", __func__, int1);
  108. if (int1 & SM5414_INT1_VBUSOVP) {
  109. health = POWER_SUPPLY_HEALTH_OVERVOLTAGE;
  110. charger_health = POWER_SUPPLY_HEALTH_OVERVOLTAGE;
  111. } else if (int1 & SM5414_INT1_VBUSUVLO) {
  112. msleep(1000);
  113. if (charger->cable_type != POWER_SUPPLY_TYPE_BATTERY) {
  114. health = POWER_SUPPLY_HEALTH_OVERVOLTAGE;
  115. charger_health = POWER_SUPPLY_HEALTH_OVERVOLTAGE;
  116. }
  117. } else if (int1 & SM5414_INT1_VBUSINOK) {
  118. health = POWER_SUPPLY_HEALTH_GOOD;
  119. charger_health = POWER_SUPPLY_HEALTH_GOOD;
  120. }
  121. return (int)health;
  122. }
  123. static u8 SM5414_set_float_voltage_data(
  124. struct i2c_client *client, int float_voltage)
  125. {
  126. u8 data, float_reg;
  127. SM5414_i2c_read(client, SM5414_CHGCTRL3, &data);
  128. data &= BATREG_MASK;
  129. if (float_voltage < 4100)
  130. float_voltage = 4100;
  131. else if (float_voltage > 4475)
  132. float_voltage = 4475;
  133. float_reg = (float_voltage - 4100) / 25;
  134. data |= (float_reg << 4);
  135. SM5414_i2c_write(client, SM5414_CHGCTRL3, &data);
  136. SM5414_i2c_read(client, SM5414_CHGCTRL3, &data);
  137. dev_dbg(&client->dev,
  138. "%s : SM5414_CHGCTRL3 (float) : 0x%02x\n", __func__, data);
  139. return data;
  140. }
  141. static u8 SM5414_set_input_current_limit_data(
  142. struct i2c_client *client, int input_current)
  143. {
  144. u8 set_reg, curr_reg = 0;
  145. u8 chg_en;
  146. if(input_current < 100)
  147. input_current = 100;
  148. else if (input_current >= 2050)
  149. input_current = 2050;
  150. set_reg = (input_current - 100) / 50;
  151. curr_reg = ((input_current % 100) >= 50) ? 1 : 0;
  152. SM5414_i2c_read(client, SM5414_CTRL, &chg_en);
  153. if (chg_en & CHARGE_EN) {
  154. SM5414_i2c_write(client, SM5414_VBUSCTRL, &set_reg);
  155. } else {
  156. while (set_reg >= curr_reg) {
  157. SM5414_i2c_write(client, SM5414_VBUSCTRL, &curr_reg);
  158. curr_reg += 2;
  159. msleep(50);
  160. };
  161. }
  162. SM5414_i2c_read(client, SM5414_VBUSCTRL, &curr_reg);
  163. dev_dbg(&client->dev,
  164. "%s : SM5414_VBUSCTRL (Input limit) : 0x%02x\n",
  165. __func__, curr_reg);
  166. return curr_reg;
  167. }
  168. static u8 SM5414_set_topoff_current_limit_data(
  169. struct i2c_client *client, int topoff_current)
  170. {
  171. u8 data;
  172. u8 topoff_reg;
  173. SM5414_i2c_read(client, SM5414_CHGCTRL4, &data);
  174. data &= TOPOFF_MASK;
  175. if(topoff_current < 100)
  176. topoff_current = 100;
  177. else if (topoff_current > 650)
  178. topoff_current = 650;
  179. topoff_reg = (topoff_current - 100) / 50;
  180. data = data | (topoff_reg<<3);
  181. SM5414_i2c_write(client, SM5414_CHGCTRL4, &data);
  182. SM5414_i2c_read(client, SM5414_CHGCTRL4, &data);
  183. dev_dbg(&client->dev,
  184. "%s : SM5414_CHGCTRL4 (Top-off limit) : 0x%02x\n",
  185. __func__, data);
  186. return data;
  187. }
  188. static u8 SM5414_set_fast_charging_current_data(
  189. struct i2c_client *client, int fast_charging_current)
  190. {
  191. u8 data = 0;
  192. if(fast_charging_current < 100)
  193. fast_charging_current = 100;
  194. else if (fast_charging_current > 2500)
  195. fast_charging_current = 2500;
  196. data = (fast_charging_current - 100) / 50;
  197. SM5414_i2c_write(client, SM5414_CHGCTRL2, &data);
  198. SM5414_i2c_read(client, SM5414_CHGCTRL2, &data);
  199. dev_dbg(&client->dev,
  200. "%s : SM5414_CHGCTRL2 (fast) : 0x%02x\n", __func__, data);
  201. return data;
  202. }
  203. static u8 SM5414_set_toggle_charger(struct i2c_client *client, int enable)
  204. {
  205. u8 chg_en=0;
  206. u8 data=0;
  207. SM5414_i2c_read(client, SM5414_CTRL, &chg_en);
  208. if (enable)
  209. chg_en |= CHARGE_EN;
  210. else
  211. chg_en &= ~CHARGE_EN;
  212. SM5414_i2c_write(client, SM5414_CTRL, &chg_en);
  213. dev_info(&client->dev, "%s: SM5414 Charger toggled!! \n", __func__);
  214. SM5414_i2c_read(client, SM5414_CTRL, &chg_en);
  215. dev_info(&client->dev,
  216. "%s : chg_en value(07h register): 0x%02x\n", __func__, chg_en);
  217. SM5414_i2c_read(client, SM5414_CHGCTRL2, &data);
  218. dev_info(&client->dev,
  219. "%s : SM5414_CHGCTRL2 value: 0x%02x", __func__, data);
  220. return chg_en;
  221. }
  222. static void SM5414_charger_function_control(
  223. struct i2c_client *client)
  224. {
  225. struct sec_charger_info *charger = i2c_get_clientdata(client);
  226. union power_supply_propval value;
  227. u8 ctrl;
  228. u8 chg_en;
  229. charger->charging_current_max =
  230. charger->pdata->charging_current[
  231. charger->cable_type].input_current_limit;
  232. charger->charging_current =
  233. charger->pdata->charging_current[
  234. charger->cable_type].fast_charging_current;
  235. if (charger->charging_current < 0) {
  236. dev_info(&client->dev,
  237. "%s : OTG is activated. Ignore command!\n", __func__);
  238. return;
  239. }
  240. if (charger->cable_type == POWER_SUPPLY_TYPE_BATTERY) {
  241. /* Disable Charger */
  242. dev_info(&client->dev,
  243. "%s : Disable Charger, Battery Supply!\n", __func__);
  244. // nCHG_EN is logic low so set 1 to disable charger
  245. charger->is_fullcharged = false;
  246. gpio_direction_output((charger->pdata->chg_gpio_en), 1);
  247. SM5414_set_toggle_charger(client, 0);
  248. } else {
  249. psy_do_property(charger->pdata->fuelgauge_name, get,
  250. POWER_SUPPLY_PROP_CAPACITY, value);
  251. if (value.intval > 0) {
  252. /* Suspend enable for register reset */
  253. ctrl = 0x44;
  254. SM5414_i2c_write(client, SM5414_CTRL, &ctrl);
  255. msleep(20);
  256. ctrl = 0x40;
  257. SM5414_i2c_write(client, SM5414_CTRL, &ctrl);
  258. }
  259. dev_info(&client->dev, "%s : float voltage (%dmV)\n",
  260. __func__, charger->pdata->chg_float_voltage);
  261. /* Set float voltage */
  262. SM5414_set_float_voltage_data(
  263. client, charger->pdata->chg_float_voltage);
  264. dev_info(&client->dev, "%s : topoff current (%dmA)\n",
  265. __func__, charger->pdata->charging_current[
  266. charger->cable_type].full_check_current_1st);
  267. SM5414_set_topoff_current_limit_data(
  268. client, charger->pdata->charging_current[
  269. charger->cable_type].full_check_current_1st);
  270. SM5414_i2c_read(client, SM5414_CTRL, &chg_en);
  271. if (!(chg_en & CHARGE_EN)) {
  272. SM5414_set_input_current_limit_data(client, 100);
  273. // nCHG_EN is logic low so set 0 to enable charger
  274. gpio_direction_output((charger->pdata->chg_gpio_en), 0);
  275. SM5414_set_toggle_charger(client, 1);
  276. msleep(100);
  277. /* Input current limit */
  278. dev_info(&client->dev, "%s : input current (%dmA)\n",
  279. __func__, charger->charging_current_max);
  280. SM5414_set_input_current_limit_data(
  281. client, charger->charging_current_max);
  282. }
  283. /* Set fast charge current */
  284. dev_info(&client->dev, "%s : fast charging current (%dmA), siop_level=%d\n",
  285. __func__, charger->charging_current, charger->siop_level);
  286. SM5414_set_fast_charging_current_data(
  287. client, charger->charging_current);
  288. dev_info(&client->dev,
  289. "%s : Enable Charger!\n", __func__);
  290. }
  291. }
  292. static void SM5414_charger_otg_control(
  293. struct i2c_client *client)
  294. {
  295. struct sec_charger_info *charger = i2c_get_clientdata(client);
  296. u8 data;
  297. //turn on/off ENBOOST
  298. if (charger->cable_type ==
  299. POWER_SUPPLY_TYPE_BATTERY) {
  300. dev_info(&client->dev, "%s : turn off OTG\n", __func__);
  301. /* turn off OTG */
  302. SM5414_i2c_read(client, SM5414_CTRL, &data);
  303. data &= 0xfe;
  304. SM5414_i2c_write(client, SM5414_CTRL, &data);
  305. } else {
  306. dev_info(&client->dev, "%s : turn on OTG\n", __func__);
  307. /* turn on OTG */
  308. SM5414_i2c_read(client, SM5414_CTRL, &data);
  309. data |= 0x01;
  310. SM5414_i2c_write(client, SM5414_CTRL, &data);
  311. }
  312. }
  313. static int SM5414_debugfs_show(struct seq_file *s, void *data)
  314. {
  315. struct sec_charger_info *charger = s->private;
  316. u8 reg;
  317. u8 reg_data;
  318. seq_printf(s, "SM CHARGER IC :\n");
  319. seq_printf(s, "==================\n");
  320. for (reg = SM5414_INTMASK1; reg <= SM5414_CHGCTRL5; reg++) {
  321. SM5414_i2c_read(charger->client, reg, &reg_data);
  322. seq_printf(s, "0x%02x:\t0x%02x\n", reg, reg_data);
  323. }
  324. seq_printf(s, "\n");
  325. return 0;
  326. }
  327. static int SM5414_debugfs_open(struct inode *inode, struct file *file)
  328. {
  329. return single_open(file, SM5414_debugfs_show, inode->i_private);
  330. }
  331. static const struct file_operations SM5414_debugfs_fops = {
  332. .open = SM5414_debugfs_open,
  333. .read = seq_read,
  334. .llseek = seq_lseek,
  335. .release = single_release,
  336. };
  337. bool SM5414_hal_chg_init(struct i2c_client *client)
  338. {
  339. u8 reg_data;
  340. u8 int1 = 0;
  341. struct sec_charger_info *charger = i2c_get_clientdata(client);
  342. dev_info(&client->dev, "%s: SM5414 Charger init (Starting)!! \n", __func__);
  343. charger->is_fullcharged = false;
  344. SM5414_i2c_read(client, SM5414_INT1, &int1);
  345. dev_info(&client->dev,
  346. "%s : SM5414_INT1 : 0x%02x\n", __func__, int1);
  347. reg_data = 0x1F;
  348. SM5414_i2c_write(client, SM5414_INTMASK1, &reg_data);
  349. reg_data = 0xFC;
  350. SM5414_i2c_write(client, SM5414_INTMASK2, &reg_data);
  351. SM5414_i2c_read(client, SM5414_CHGCTRL1, &reg_data);
  352. reg_data &= ~SM5414_CHGCTRL1_AUTOSTOP;
  353. SM5414_i2c_write(client, SM5414_CHGCTRL1, &reg_data);
  354. (void) debugfs_create_file("SM5414_regs",
  355. S_IRUGO, NULL, (void *)charger, &SM5414_debugfs_fops);
  356. return true;
  357. }
  358. bool SM5414_hal_chg_suspend(struct i2c_client *client)
  359. {
  360. dev_info(&client->dev,
  361. "%s: CHARGER - SM5414(suspend mode)!!\n", __func__);
  362. return true;
  363. }
  364. bool SM5414_hal_chg_resume(struct i2c_client *client)
  365. {
  366. dev_info(&client->dev,
  367. "%s: CHARGER - SM5414(resume mode)!!\n", __func__);
  368. return true;
  369. }
  370. bool SM5414_hal_chg_get_property(struct i2c_client *client,
  371. enum power_supply_property psp,
  372. union power_supply_propval *val)
  373. {
  374. struct sec_charger_info *charger = i2c_get_clientdata(client);
  375. u8 data;
  376. switch (psp) {
  377. case POWER_SUPPLY_PROP_ONLINE:
  378. break;
  379. case POWER_SUPPLY_PROP_STATUS:
  380. if (charger->is_fullcharged)
  381. val->intval = POWER_SUPPLY_STATUS_FULL;
  382. else
  383. val->intval = SM5414_get_charging_status(client);
  384. break;
  385. case POWER_SUPPLY_PROP_HEALTH:
  386. val->intval = charger_health;
  387. break;
  388. case POWER_SUPPLY_PROP_CHARGE_TYPE:
  389. val->intval = POWER_SUPPLY_CHARGE_TYPE_UNKNOWN;
  390. break;
  391. // Have to mention the issue about POWER_SUPPLY_PROP_CHARGE_NOW to Marvel
  392. case POWER_SUPPLY_PROP_CHARGE_NOW:
  393. case POWER_SUPPLY_PROP_CURRENT_MAX:
  394. case POWER_SUPPLY_PROP_CURRENT_AVG:
  395. case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN:
  396. case POWER_SUPPLY_PROP_CURRENT_NOW:
  397. if (charger->charging_current) {
  398. SM5414_i2c_read(client, SM5414_VBUSCTRL, &data);
  399. data &= 0x3f;
  400. val->intval = (100 + (data * 50));
  401. if (val->intval < 2050)
  402. val->intval = (100 + (data * 50));
  403. /*dev_dbg(&client->dev,
  404. "%s 1: set-current(%dmA), current now(%dmA)\n",
  405. __func__, charger->charging_current, val->intval);*/
  406. } else {
  407. val->intval = 100;
  408. /*dev_dbg(&client->dev,
  409. "%s 2: set-current(%dmA), current now(%dmA)\n",
  410. __func__, charger->charging_current, val->intval);*/
  411. }
  412. break;
  413. default:
  414. return false;
  415. }
  416. return true;
  417. }
  418. bool SM5414_hal_chg_set_property(struct i2c_client *client,
  419. enum power_supply_property psp,
  420. const union power_supply_propval *val)
  421. {
  422. struct sec_charger_info *charger = i2c_get_clientdata(client);
  423. switch (psp) {
  424. /* val->intval : type */
  425. case POWER_SUPPLY_PROP_ONLINE:
  426. if (charger->cable_type == POWER_SUPPLY_TYPE_OTG) {
  427. SM5414_charger_otg_control(client);
  428. } else if (charger->cable_type == POWER_SUPPLY_TYPE_BATTERY) {
  429. SM5414_charger_function_control(client);
  430. SM5414_charger_otg_control(client);
  431. } else {
  432. SM5414_charger_function_control(client);
  433. }
  434. break;
  435. case POWER_SUPPLY_PROP_CURRENT_MAX: /* input current limit set */
  436. /* calculated input current limit value */
  437. case POWER_SUPPLY_PROP_CURRENT_NOW:
  438. SM5414_set_input_current_limit_data(client, val->intval);
  439. break;
  440. case POWER_SUPPLY_PROP_CURRENT_AVG:
  441. SM5414_set_fast_charging_current_data(client, val->intval);
  442. break;
  443. default:
  444. return false;
  445. }
  446. return true;
  447. }
  448. ssize_t SM5414_hal_chg_show_attrs(struct device *dev,
  449. const ptrdiff_t offset, char *buf)
  450. {
  451. struct power_supply *psy = dev_get_drvdata(dev);
  452. struct sec_charger_info *chg =
  453. container_of(psy, struct sec_charger_info, psy_chg);
  454. int i = 0;
  455. char *str = NULL;
  456. switch (offset) {
  457. /* case CHG_REG: */
  458. /* break; */
  459. case CHG_DATA:
  460. i += scnprintf(buf + i, PAGE_SIZE - i, "%x\n",
  461. chg->reg_data);
  462. break;
  463. case CHG_REGS:
  464. str = kzalloc(sizeof(char)*1024, GFP_KERNEL);
  465. if (!str)
  466. return -ENOMEM;
  467. SM5414_read_regs(chg->client, str);
  468. i += scnprintf(buf + i, PAGE_SIZE - i, "%s\n",
  469. str);
  470. kfree(str);
  471. break;
  472. default:
  473. i = -EINVAL;
  474. break;
  475. }
  476. return i;
  477. }
  478. ssize_t SM5414_hal_chg_store_attrs(struct device *dev,
  479. const ptrdiff_t offset,
  480. const char *buf, size_t count)
  481. {
  482. struct power_supply *psy = dev_get_drvdata(dev);
  483. struct sec_charger_info *chg =
  484. container_of(psy, struct sec_charger_info, psy_chg);
  485. int ret = 0;
  486. int x = 0;
  487. u8 data = 0;
  488. switch (offset) {
  489. case CHG_REG:
  490. if (sscanf(buf, "%x\n", &x) == 1) {
  491. chg->reg_addr = x;
  492. SM5414_i2c_read(chg->client,
  493. chg->reg_addr, &data);
  494. chg->reg_data = data;
  495. dev_dbg(dev, "%s: (read) addr = 0x%x, data = 0x%x\n",
  496. __func__, chg->reg_addr, chg->reg_data);
  497. ret = count;
  498. }
  499. break;
  500. case CHG_DATA:
  501. if (sscanf(buf, "%x\n", &x) == 1) {
  502. data = (u8)x;
  503. dev_dbg(dev, "%s: (write) addr = 0x%x, data = 0x%x\n",
  504. __func__, chg->reg_addr, data);
  505. SM5414_i2c_write(chg->client,
  506. chg->reg_addr, &data);
  507. ret = count;
  508. }
  509. break;
  510. default:
  511. ret = -EINVAL;
  512. break;
  513. }
  514. return ret;
  515. }
  516. static struct device_attribute SM5414_charger_attrs[] = {
  517. SM5414_CHARGER_ATTR(reg),
  518. SM5414_CHARGER_ATTR(data),
  519. SM5414_CHARGER_ATTR(regs),
  520. };
  521. static enum power_supply_property SM5414_charger_props[] = {
  522. POWER_SUPPLY_PROP_STATUS,
  523. POWER_SUPPLY_PROP_CHARGE_TYPE,
  524. POWER_SUPPLY_PROP_HEALTH,
  525. POWER_SUPPLY_PROP_ONLINE,
  526. POWER_SUPPLY_PROP_CURRENT_MAX,
  527. POWER_SUPPLY_PROP_CURRENT_AVG,
  528. POWER_SUPPLY_PROP_CURRENT_NOW,
  529. POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN,
  530. };
  531. static int SM5414_chg_get_property(struct power_supply *psy,
  532. enum power_supply_property psp,
  533. union power_supply_propval *val)
  534. {
  535. struct sec_charger_info *charger =
  536. container_of(psy, struct sec_charger_info, psy_chg);
  537. switch (psp) {
  538. case POWER_SUPPLY_PROP_CURRENT_MAX: /* input current limit set */
  539. val->intval = charger->charging_current_max;
  540. break;
  541. case POWER_SUPPLY_PROP_ONLINE:
  542. case POWER_SUPPLY_PROP_STATUS:
  543. case POWER_SUPPLY_PROP_CHARGE_TYPE:
  544. case POWER_SUPPLY_PROP_HEALTH:
  545. case POWER_SUPPLY_PROP_CURRENT_AVG: /* charging current */
  546. /* calculated input current limit value */
  547. case POWER_SUPPLY_PROP_CURRENT_NOW:
  548. if (!SM5414_hal_chg_get_property(charger->client, psp, val))
  549. return -EINVAL;
  550. break;
  551. default:
  552. return -EINVAL;
  553. }
  554. return 0;
  555. }
  556. static int SM5414_chg_set_property(struct power_supply *psy,
  557. enum power_supply_property psp,
  558. const union power_supply_propval *val)
  559. {
  560. struct sec_charger_info *charger =
  561. container_of(psy, struct sec_charger_info, psy_chg);
  562. union power_supply_propval input_value;
  563. switch (psp) {
  564. case POWER_SUPPLY_PROP_STATUS:
  565. charger->status = val->intval;
  566. break;
  567. /* val->intval : type */
  568. case POWER_SUPPLY_PROP_ONLINE:
  569. charger->cable_type = val->intval;
  570. if (val->intval == POWER_SUPPLY_TYPE_BATTERY || \
  571. val->intval == POWER_SUPPLY_TYPE_OTG) {
  572. charger->is_charging = false;
  573. charger->is_slow_charging = false;
  574. }
  575. else
  576. charger->is_charging = true;
  577. if (!SM5414_hal_chg_set_property(charger->client, psp, val))
  578. return -EINVAL;
  579. break;
  580. /* val->intval : input current limit set */
  581. case POWER_SUPPLY_PROP_CURRENT_MAX:
  582. charger->charging_current_max = val->intval;
  583. /* to control charging current,
  584. * use input current limit and set charging current as much as possible
  585. * so we only control input current limit to control charge current
  586. */
  587. case POWER_SUPPLY_PROP_CURRENT_NOW:
  588. if (!SM5414_hal_chg_set_property(charger->client, psp, val))
  589. return -EINVAL;
  590. break;
  591. /* val->intval : charging current */
  592. case POWER_SUPPLY_PROP_CURRENT_AVG:
  593. charger->charging_current = val->intval;
  594. if (!SM5414_hal_chg_set_property(charger->client, psp, val))
  595. return -EINVAL;
  596. break;
  597. /* val->intval : SIOP level (%)
  598. * SIOP charging current setting
  599. */
  600. case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN:
  601. charger->siop_level = val->intval;
  602. if (charger->is_charging) {
  603. /* change val as charging current by SIOP level
  604. * do NOT change initial charging current setting
  605. */
  606. input_value.intval =
  607. charger->pdata->charging_current[
  608. charger->cable_type].fast_charging_current * val->intval / 100;
  609. /* charging current should be over than USB charging current */
  610. if (charger->pdata->chg_functions_setting &
  611. SEC_CHARGER_MINIMUM_SIOP_CHARGING_CURRENT) {
  612. if (input_value.intval > 0 &&
  613. input_value.intval <
  614. charger->pdata->charging_current[
  615. POWER_SUPPLY_TYPE_USB].fast_charging_current)
  616. input_value.intval =
  617. charger->pdata->charging_current[
  618. POWER_SUPPLY_TYPE_USB].fast_charging_current;
  619. }
  620. /* set charging current as new value */
  621. charger->charging_current = input_value.intval;
  622. if (!SM5414_hal_chg_set_property(charger->client,
  623. POWER_SUPPLY_PROP_CURRENT_AVG, &input_value))
  624. return -EINVAL;
  625. }
  626. break;
  627. default:
  628. return -EINVAL;
  629. }
  630. return 0;
  631. }
  632. static void SM5414_chg_isr_work(struct work_struct *work)
  633. {
  634. struct sec_charger_info *charger =
  635. container_of(work, struct sec_charger_info, isr_work.work);
  636. union power_supply_propval val;
  637. int full_check_type;
  638. dev_info(&charger->client->dev,
  639. "%s: Charger Interrupt\n", __func__);
  640. psy_do_property("battery", get,
  641. POWER_SUPPLY_PROP_CHARGE_NOW, val);
  642. if (val.intval == SEC_BATTERY_CHARGING_1ST)
  643. full_check_type = charger->pdata->full_check_type;
  644. else
  645. full_check_type = charger->pdata->full_check_type_2nd;
  646. if (full_check_type == SEC_BATTERY_FULLCHARGED_CHGINT) {
  647. if (!SM5414_hal_chg_get_property(charger->client,
  648. POWER_SUPPLY_PROP_STATUS, &val))
  649. return;
  650. switch (val.intval) {
  651. case POWER_SUPPLY_STATUS_DISCHARGING:
  652. dev_err(&charger->client->dev,
  653. "%s: Interrupted but Discharging\n", __func__);
  654. break;
  655. case POWER_SUPPLY_STATUS_NOT_CHARGING:
  656. dev_err(&charger->client->dev,
  657. "%s: Interrupted but NOT Charging\n", __func__);
  658. break;
  659. case POWER_SUPPLY_STATUS_FULL:
  660. dev_info(&charger->client->dev,
  661. "%s: Interrupted by Full\n", __func__);
  662. psy_do_property("battery", set,
  663. POWER_SUPPLY_PROP_STATUS, val);
  664. break;
  665. case POWER_SUPPLY_STATUS_CHARGING:
  666. dev_err(&charger->client->dev,
  667. "%s: Interrupted but Charging\n", __func__);
  668. break;
  669. case POWER_SUPPLY_STATUS_UNKNOWN:
  670. default:
  671. dev_err(&charger->client->dev,
  672. "%s: Invalid Charger Status\n", __func__);
  673. break;
  674. }
  675. }
  676. if (charger->pdata->ovp_uvlo_check_type ==
  677. SEC_BATTERY_OVP_UVLO_CHGINT) {
  678. val.intval = SM5414_get_charging_health(charger->client);
  679. switch (val.intval) {
  680. case POWER_SUPPLY_HEALTH_OVERHEAT:
  681. case POWER_SUPPLY_HEALTH_COLD:
  682. dev_err(&charger->client->dev,
  683. "%s: Interrupted but Hot/Cold\n", __func__);
  684. break;
  685. case POWER_SUPPLY_HEALTH_DEAD:
  686. dev_err(&charger->client->dev,
  687. "%s: Interrupted but Dead\n", __func__);
  688. break;
  689. case POWER_SUPPLY_HEALTH_OVERVOLTAGE:
  690. case POWER_SUPPLY_HEALTH_UNDERVOLTAGE:
  691. dev_info(&charger->client->dev,
  692. "%s: Interrupted by OVP/UVLO\n", __func__);
  693. psy_do_property("battery", set,
  694. POWER_SUPPLY_PROP_HEALTH, val);
  695. break;
  696. case POWER_SUPPLY_HEALTH_UNSPEC_FAILURE:
  697. dev_err(&charger->client->dev,
  698. "%s: Interrupted but Unspec\n", __func__);
  699. break;
  700. case POWER_SUPPLY_HEALTH_GOOD:
  701. dev_err(&charger->client->dev,
  702. "%s: Interrupted but Good\n", __func__);
  703. break;
  704. case POWER_SUPPLY_HEALTH_UNKNOWN:
  705. default:
  706. dev_err(&charger->client->dev,
  707. "%s: Invalid Charger Health\n", __func__);
  708. break;
  709. }
  710. }
  711. if (charger->pdata->cable_check_type & SEC_BATTERY_CABLE_CHECK_CHGINT) {
  712. if (!SM5414_hal_chg_get_property(charger->client,
  713. POWER_SUPPLY_PROP_ONLINE, &val))
  714. return;
  715. /* use SEC_BATTERY_CABLE_SOURCE_EXTERNAL for cable_source_type
  716. * charger would call battery driver to set ONLINE property
  717. * check battery driver loaded or not
  718. */
  719. if (get_power_supply_by_name("battery")) {
  720. psy_do_property("battery", set,
  721. POWER_SUPPLY_PROP_ONLINE, val);
  722. } else
  723. charger->pdata->check_cable_result_callback(val.intval);
  724. }
  725. }
  726. static irqreturn_t SM5414_chg_irq_thread(int irq, void *irq_data)
  727. {
  728. struct sec_charger_info *charger = irq_data;
  729. schedule_delayed_work(&charger->isr_work, 0);
  730. return IRQ_HANDLED;
  731. }
  732. static int SM5414_chg_create_attrs(struct device *dev)
  733. {
  734. int i, rc;
  735. for (i = 0; i < ARRAY_SIZE(SM5414_charger_attrs); i++) {
  736. rc = device_create_file(dev, &SM5414_charger_attrs[i]);
  737. if (rc)
  738. goto create_attrs_failed;
  739. }
  740. goto create_attrs_succeed;
  741. create_attrs_failed:
  742. dev_err(dev, "%s: failed (%d)\n", __func__, rc);
  743. while (i--)
  744. device_remove_file(dev, &SM5414_charger_attrs[i]);
  745. create_attrs_succeed:
  746. return rc;
  747. }
  748. ssize_t SM5414_chg_show_attrs(struct device *dev,
  749. struct device_attribute *attr, char *buf)
  750. {
  751. const ptrdiff_t offset = attr - SM5414_charger_attrs;
  752. int i = 0;
  753. switch (offset) {
  754. case CHG_REG:
  755. case CHG_DATA:
  756. case CHG_REGS:
  757. i = SM5414_hal_chg_show_attrs(dev, offset, buf);
  758. break;
  759. default:
  760. i = -EINVAL;
  761. break;
  762. }
  763. return i;
  764. }
  765. ssize_t SM5414_chg_store_attrs(struct device *dev,
  766. struct device_attribute *attr,
  767. const char *buf, size_t count)
  768. {
  769. const ptrdiff_t offset = attr - SM5414_charger_attrs;
  770. int ret = 0;
  771. switch (offset) {
  772. case CHG_REG:
  773. case CHG_DATA:
  774. ret = SM5414_hal_chg_store_attrs(dev, offset, buf, count);
  775. break;
  776. default:
  777. ret = -EINVAL;
  778. break;
  779. }
  780. return ret;
  781. }
  782. #ifdef CONFIG_OF
  783. static int SM5414_charger_read_u32_index_dt(const struct device_node *np,
  784. const char *propname,
  785. u32 index, u32 *out_value)
  786. {
  787. struct property *prop = of_find_property(np, propname, NULL);
  788. u32 len = (index + 1) * sizeof(*out_value);
  789. if (!prop)
  790. return (-EINVAL);
  791. if (!prop->value)
  792. return (-ENODATA);
  793. if (len > prop->length)
  794. return (-EOVERFLOW);
  795. *out_value = be32_to_cpup(((__be32 *)prop->value) + index);
  796. return 0;
  797. }
  798. extern unsigned int system_rev;
  799. static int SM5414_charger_parse_dt(struct sec_charger_info *charger)
  800. {
  801. struct device_node *np = of_find_node_by_name(NULL, "charger");
  802. sec_battery_platform_data_t *pdata = charger->pdata;
  803. int ret = 0;
  804. int i, len;
  805. const u32 *p;
  806. if (np == NULL) {
  807. pr_err("%s np NULL\n", __func__);
  808. return -1;
  809. } else {
  810. ret = of_get_named_gpio(np, "battery,vbus_ctrl_gpio", 0);
  811. if (ret > 0) {
  812. pdata->vbus_ctrl_gpio = ret;
  813. pr_info("%s reading vbus_ctrl_gpio = %d\n", __func__, ret);
  814. } else {
  815. pdata->vbus_ctrl_gpio = 0;
  816. pr_info("%s vbus_ctrl_gpio read fail\n", __func__);
  817. }
  818. ret = of_property_read_u32(np, "battery,chg_float_voltage",
  819. &pdata->chg_float_voltage);
  820. if (ret < 0)
  821. pr_err("%s: chg_float_voltage read failed (%d)\n", __func__, ret);
  822. ret = of_property_read_u32(np, "battery,ovp_uvlo_check_type",
  823. &pdata->ovp_uvlo_check_type);
  824. if (ret < 0)
  825. pr_err("%s: ovp_uvlo_check_type read failed (%d)\n", __func__, ret);
  826. ret = of_property_read_u32(np, "battery,full_check_type",
  827. &pdata->full_check_type);
  828. if (ret < 0)
  829. pr_err("%s: full_check_type read failed (%d)\n", __func__, ret);
  830. p = of_get_property(np, "battery,input_current_limit", &len);
  831. len = len / sizeof(u32);
  832. pdata->charging_current = kzalloc(sizeof(sec_charging_current_t) * len,
  833. GFP_KERNEL);
  834. for(i = 0; i < len; i++) {
  835. ret = SM5414_charger_read_u32_index_dt(np,
  836. "battery,input_current_limit", i,
  837. &pdata->charging_current[i].input_current_limit);
  838. ret = SM5414_charger_read_u32_index_dt(np,
  839. "battery,fast_charging_current", i,
  840. &pdata->charging_current[i].fast_charging_current);
  841. ret = SM5414_charger_read_u32_index_dt(np,
  842. "battery,full_check_current_1st", i,
  843. &pdata->charging_current[i].full_check_current_1st);
  844. ret = SM5414_charger_read_u32_index_dt(np,
  845. "battery,full_check_current_2nd", i,
  846. &pdata->charging_current[i].full_check_current_2nd);
  847. }
  848. ret = of_property_read_string(np, "battery,fuelgauge_name",
  849. (char const **)&pdata->fuelgauge_name);
  850. if (ret)
  851. pr_err("%s: fuelgauge_name read failed\n", __func__);
  852. }
  853. return ret;
  854. }
  855. #else
  856. static int SM5414_charger_parse_dt(struct max77803_charger_data *charger)
  857. {
  858. return 0;
  859. }
  860. #endif
  861. static int __devinit SM5414_charger_probe(
  862. struct i2c_client *client,
  863. const struct i2c_device_id *id)
  864. {
  865. struct i2c_adapter *adapter =
  866. to_i2c_adapter(client->dev.parent);
  867. struct sec_charger_info *charger;
  868. int ret = 0;
  869. dev_info(&client->dev,
  870. "%s: SM5414 Charger Driver Loading\n", __func__);
  871. if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE))
  872. return -EIO;
  873. charger = kzalloc(sizeof(*charger), GFP_KERNEL);
  874. if (!charger)
  875. return -ENOMEM;
  876. charger->client = client;
  877. if (client->dev.of_node) {
  878. void * pdata = kzalloc(sizeof(sec_battery_platform_data_t), GFP_KERNEL);
  879. if (!pdata)
  880. goto err_free1;
  881. charger->pdata = pdata;
  882. if (SM5414_charger_parse_dt(charger))
  883. dev_err(&client->dev,
  884. "%s : Failed to get charger dt\n", __func__);
  885. } else
  886. charger->pdata = client->dev.platform_data;
  887. i2c_set_clientdata(client, charger);
  888. charger->siop_level = 100;
  889. charger->psy_chg.name = "SM5414";
  890. charger->psy_chg.type = POWER_SUPPLY_TYPE_UNKNOWN;
  891. charger->psy_chg.get_property = SM5414_chg_get_property;
  892. charger->psy_chg.set_property = SM5414_chg_set_property;
  893. charger->psy_chg.properties = SM5414_charger_props;
  894. charger->psy_chg.num_properties = ARRAY_SIZE(SM5414_charger_props);
  895. charger->is_slow_charging = false;
  896. if (charger->pdata->chg_gpio_init) {
  897. if (!charger->pdata->chg_gpio_init()) {
  898. dev_err(&client->dev,
  899. "%s: Failed to Initialize GPIO\n", __func__);
  900. goto err_free;
  901. }
  902. }
  903. if (!SM5414_hal_chg_init(charger->client)) {
  904. dev_err(&client->dev,
  905. "%s: Failed to Initialize Charger\n", __func__);
  906. goto err_free;
  907. }
  908. ret = power_supply_register(&client->dev, &charger->psy_chg);
  909. if (ret) {
  910. dev_err(&client->dev,
  911. "%s: Failed to Register psy_chg\n", __func__);
  912. goto err_free;
  913. }
  914. if (charger->pdata->chg_irq) {
  915. INIT_DELAYED_WORK_DEFERRABLE(
  916. &charger->isr_work, SM5414_chg_isr_work);
  917. ret = request_threaded_irq(charger->pdata->chg_irq,
  918. NULL, SM5414_chg_irq_thread,
  919. charger->pdata->chg_irq_attr,
  920. "charger-irq", charger);
  921. if (ret) {
  922. dev_err(&client->dev,
  923. "%s: Failed to Reqeust IRQ\n", __func__);
  924. goto err_supply_unreg;
  925. }
  926. ret = enable_irq_wake(charger->pdata->chg_irq);
  927. if (ret < 0)
  928. dev_err(&client->dev,
  929. "%s: Failed to Enable Wakeup Source(%d)\n",
  930. __func__, ret);
  931. }
  932. ret = SM5414_chg_create_attrs(charger->psy_chg.dev);
  933. if (ret) {
  934. dev_err(&client->dev,
  935. "%s : Failed to create_attrs\n", __func__);
  936. goto err_req_irq;
  937. }
  938. dev_dbg(&client->dev,
  939. "%s: SM5414 Charger Driver Loaded\n", __func__);
  940. return 0;
  941. err_req_irq:
  942. if (charger->pdata->chg_irq)
  943. free_irq(charger->pdata->chg_irq, charger);
  944. err_supply_unreg:
  945. power_supply_unregister(&charger->psy_chg);
  946. err_free:
  947. kfree(charger->pdata);
  948. err_free1:
  949. kfree(charger);
  950. return ret;
  951. }
  952. static int __devexit SM5414_charger_remove(
  953. struct i2c_client *client)
  954. {
  955. return 0;
  956. }
  957. static int SM5414_charger_suspend(struct i2c_client *client,
  958. pm_message_t state)
  959. {
  960. if (!SM5414_hal_chg_suspend(client))
  961. dev_err(&client->dev,
  962. "%s: Failed to Suspend Charger\n", __func__);
  963. return 0;
  964. }
  965. static int SM5414_charger_resume(struct i2c_client *client)
  966. {
  967. dev_info(&client->dev,"%s: start\n", __func__);
  968. if (!SM5414_hal_chg_resume(client))
  969. dev_err(&client->dev,
  970. "%s: Failed to Resume Charger\n", __func__);
  971. return 0;
  972. }
  973. static const struct i2c_device_id SM5414_charger_id[] = {
  974. {"SM5414", 0},
  975. {}
  976. };
  977. MODULE_DEVICE_TABLE(i2c, SM5414_charger_id);
  978. static struct of_device_id SM5414_i2c_match_table[] = {
  979. { .compatible = "SM5414,i2c", },
  980. { },
  981. };
  982. MODULE_DEVICE_TABLE(i2c, SM5414_i2c_match_table);
  983. static struct i2c_driver SM5414_charger_driver = {
  984. .driver = {
  985. .name = "SM5414",
  986. .owner = THIS_MODULE,
  987. .of_match_table = SM5414_i2c_match_table,
  988. },
  989. .probe = SM5414_charger_probe,
  990. .remove = __devexit_p(SM5414_charger_remove),
  991. .suspend = SM5414_charger_suspend,
  992. .resume = SM5414_charger_resume,
  993. .id_table = SM5414_charger_id,
  994. };
  995. static int __init SM5414_charger_init(void)
  996. {
  997. return i2c_add_driver(&SM5414_charger_driver);
  998. }
  999. static void __exit SM5414_charger_exit(void)
  1000. {
  1001. i2c_del_driver(&SM5414_charger_driver);
  1002. }
  1003. module_init(SM5414_charger_init);
  1004. module_exit(SM5414_charger_exit);
  1005. MODULE_DESCRIPTION("Samsung SM5414 Charger Driver");
  1006. MODULE_AUTHOR("Samsung Electronics");
  1007. MODULE_LICENSE("GPL");