ab8500_btemp.c 30 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139
  1. /*
  2. * Copyright (C) ST-Ericsson SA 2012
  3. *
  4. * Battery temperature driver for AB8500
  5. *
  6. * License Terms: GNU General Public License v2
  7. * Author:
  8. * Johan Palsson <johan.palsson@stericsson.com>
  9. * Karl Komierowski <karl.komierowski@stericsson.com>
  10. * Arun R Murthy <arun.murthy@stericsson.com>
  11. */
  12. #include <linux/init.h>
  13. #include <linux/module.h>
  14. #include <linux/device.h>
  15. #include <linux/interrupt.h>
  16. #include <linux/delay.h>
  17. #include <linux/slab.h>
  18. #include <linux/platform_device.h>
  19. #include <linux/power_supply.h>
  20. #include <linux/completion.h>
  21. #include <linux/workqueue.h>
  22. #include <linux/jiffies.h>
  23. #include <linux/of.h>
  24. #include <linux/mfd/core.h>
  25. #include <linux/mfd/abx500.h>
  26. #include <linux/mfd/abx500/ab8500.h>
  27. #include <linux/mfd/abx500/ab8500-bm.h>
  28. #include <linux/mfd/abx500/ab8500-gpadc.h>
  29. #define VTVOUT_V 1800
  30. #define BTEMP_THERMAL_LOW_LIMIT -10
  31. #define BTEMP_THERMAL_MED_LIMIT 0
  32. #define BTEMP_THERMAL_HIGH_LIMIT_52 52
  33. #define BTEMP_THERMAL_HIGH_LIMIT_57 57
  34. #define BTEMP_THERMAL_HIGH_LIMIT_62 62
  35. #define BTEMP_BATCTRL_CURR_SRC_7UA 7
  36. #define BTEMP_BATCTRL_CURR_SRC_20UA 20
  37. #define to_ab8500_btemp_device_info(x) container_of((x), \
  38. struct ab8500_btemp, btemp_psy);
  39. /**
  40. * struct ab8500_btemp_interrupts - ab8500 interrupts
  41. * @name: name of the interrupt
  42. * @isr function pointer to the isr
  43. */
  44. struct ab8500_btemp_interrupts {
  45. char *name;
  46. irqreturn_t (*isr)(int irq, void *data);
  47. };
  48. struct ab8500_btemp_events {
  49. bool batt_rem;
  50. bool btemp_high;
  51. bool btemp_medhigh;
  52. bool btemp_lowmed;
  53. bool btemp_low;
  54. bool ac_conn;
  55. bool usb_conn;
  56. };
  57. struct ab8500_btemp_ranges {
  58. int btemp_high_limit;
  59. int btemp_med_limit;
  60. int btemp_low_limit;
  61. };
  62. /**
  63. * struct ab8500_btemp - ab8500 BTEMP device information
  64. * @dev: Pointer to the structure device
  65. * @node: List of AB8500 BTEMPs, hence prepared for reentrance
  66. * @curr_source: What current source we use, in uA
  67. * @bat_temp: Battery temperature in degree Celcius
  68. * @prev_bat_temp Last dispatched battery temperature
  69. * @parent: Pointer to the struct ab8500
  70. * @gpadc: Pointer to the struct gpadc
  71. * @fg: Pointer to the struct fg
  72. * @bm: Platform specific battery management information
  73. * @btemp_psy: Structure for BTEMP specific battery properties
  74. * @events: Structure for information about events triggered
  75. * @btemp_ranges: Battery temperature range structure
  76. * @btemp_wq: Work queue for measuring the temperature periodically
  77. * @btemp_periodic_work: Work for measuring the temperature periodically
  78. * @initialized: True if battery id read.
  79. */
  80. struct ab8500_btemp {
  81. struct device *dev;
  82. struct list_head node;
  83. int curr_source;
  84. int bat_temp;
  85. int prev_bat_temp;
  86. struct ab8500 *parent;
  87. struct ab8500_gpadc *gpadc;
  88. struct ab8500_fg *fg;
  89. struct abx500_bm_data *bm;
  90. struct power_supply btemp_psy;
  91. struct ab8500_btemp_events events;
  92. struct ab8500_btemp_ranges btemp_ranges;
  93. struct workqueue_struct *btemp_wq;
  94. struct delayed_work btemp_periodic_work;
  95. bool initialized;
  96. };
  97. /* BTEMP power supply properties */
  98. static enum power_supply_property ab8500_btemp_props[] = {
  99. POWER_SUPPLY_PROP_PRESENT,
  100. POWER_SUPPLY_PROP_ONLINE,
  101. POWER_SUPPLY_PROP_TECHNOLOGY,
  102. POWER_SUPPLY_PROP_TEMP,
  103. };
  104. static LIST_HEAD(ab8500_btemp_list);
  105. /**
  106. * ab8500_btemp_get() - returns a reference to the primary AB8500 BTEMP
  107. * (i.e. the first BTEMP in the instance list)
  108. */
  109. struct ab8500_btemp *ab8500_btemp_get(void)
  110. {
  111. struct ab8500_btemp *btemp;
  112. btemp = list_first_entry(&ab8500_btemp_list, struct ab8500_btemp, node);
  113. return btemp;
  114. }
  115. /**
  116. * ab8500_btemp_batctrl_volt_to_res() - convert batctrl voltage to resistance
  117. * @di: pointer to the ab8500_btemp structure
  118. * @v_batctrl: measured batctrl voltage
  119. * @inst_curr: measured instant current
  120. *
  121. * This function returns the battery resistance that is
  122. * derived from the BATCTRL voltage.
  123. * Returns value in Ohms.
  124. */
  125. static int ab8500_btemp_batctrl_volt_to_res(struct ab8500_btemp *di,
  126. int v_batctrl, int inst_curr)
  127. {
  128. int rbs;
  129. if (is_ab8500_1p1_or_earlier(di->parent)) {
  130. /*
  131. * For ABB cut1.0 and 1.1 BAT_CTRL is internally
  132. * connected to 1.8V through a 450k resistor
  133. */
  134. return (450000 * (v_batctrl)) / (1800 - v_batctrl);
  135. }
  136. if (di->bm->adc_therm == ABx500_ADC_THERM_BATCTRL) {
  137. /*
  138. * If the battery has internal NTC, we use the current
  139. * source to calculate the resistance, 7uA or 20uA
  140. */
  141. rbs = (v_batctrl * 1000
  142. - di->bm->gnd_lift_resistance * inst_curr)
  143. / di->curr_source;
  144. } else {
  145. /*
  146. * BAT_CTRL is internally
  147. * connected to 1.8V through a 80k resistor
  148. */
  149. rbs = (80000 * (v_batctrl)) / (1800 - v_batctrl);
  150. }
  151. return rbs;
  152. }
  153. /**
  154. * ab8500_btemp_read_batctrl_voltage() - measure batctrl voltage
  155. * @di: pointer to the ab8500_btemp structure
  156. *
  157. * This function returns the voltage on BATCTRL. Returns value in mV.
  158. */
  159. static int ab8500_btemp_read_batctrl_voltage(struct ab8500_btemp *di)
  160. {
  161. int vbtemp;
  162. static int prev;
  163. vbtemp = ab8500_gpadc_convert(di->gpadc, BAT_CTRL);
  164. if (vbtemp < 0) {
  165. dev_err(di->dev,
  166. "%s gpadc conversion failed, using previous value",
  167. __func__);
  168. return prev;
  169. }
  170. prev = vbtemp;
  171. return vbtemp;
  172. }
  173. /**
  174. * ab8500_btemp_curr_source_enable() - enable/disable batctrl current source
  175. * @di: pointer to the ab8500_btemp structure
  176. * @enable: enable or disable the current source
  177. *
  178. * Enable or disable the current sources for the BatCtrl AD channel
  179. */
  180. static int ab8500_btemp_curr_source_enable(struct ab8500_btemp *di,
  181. bool enable)
  182. {
  183. int curr;
  184. int ret = 0;
  185. /*
  186. * BATCTRL current sources are included on AB8500 cut2.0
  187. * and future versions
  188. */
  189. if (is_ab8500_1p1_or_earlier(di->parent))
  190. return 0;
  191. /* Only do this for batteries with internal NTC */
  192. if (di->bm->adc_therm == ABx500_ADC_THERM_BATCTRL && enable) {
  193. if (di->curr_source == BTEMP_BATCTRL_CURR_SRC_7UA)
  194. curr = BAT_CTRL_7U_ENA;
  195. else
  196. curr = BAT_CTRL_20U_ENA;
  197. dev_dbg(di->dev, "Set BATCTRL %duA\n", di->curr_source);
  198. ret = abx500_mask_and_set_register_interruptible(di->dev,
  199. AB8500_CHARGER, AB8500_BAT_CTRL_CURRENT_SOURCE,
  200. FORCE_BAT_CTRL_CMP_HIGH, FORCE_BAT_CTRL_CMP_HIGH);
  201. if (ret) {
  202. dev_err(di->dev, "%s failed setting cmp_force\n",
  203. __func__);
  204. return ret;
  205. }
  206. /*
  207. * We have to wait one 32kHz cycle before enabling
  208. * the current source, since ForceBatCtrlCmpHigh needs
  209. * to be written in a separate cycle
  210. */
  211. udelay(32);
  212. ret = abx500_set_register_interruptible(di->dev,
  213. AB8500_CHARGER, AB8500_BAT_CTRL_CURRENT_SOURCE,
  214. FORCE_BAT_CTRL_CMP_HIGH | curr);
  215. if (ret) {
  216. dev_err(di->dev, "%s failed enabling current source\n",
  217. __func__);
  218. goto disable_curr_source;
  219. }
  220. } else if (di->bm->adc_therm == ABx500_ADC_THERM_BATCTRL && !enable) {
  221. dev_dbg(di->dev, "Disable BATCTRL curr source\n");
  222. /* Write 0 to the curr bits */
  223. ret = abx500_mask_and_set_register_interruptible(di->dev,
  224. AB8500_CHARGER, AB8500_BAT_CTRL_CURRENT_SOURCE,
  225. BAT_CTRL_7U_ENA | BAT_CTRL_20U_ENA,
  226. ~(BAT_CTRL_7U_ENA | BAT_CTRL_20U_ENA));
  227. if (ret) {
  228. dev_err(di->dev, "%s failed disabling current source\n",
  229. __func__);
  230. goto disable_curr_source;
  231. }
  232. /* Enable Pull-Up and comparator */
  233. ret = abx500_mask_and_set_register_interruptible(di->dev,
  234. AB8500_CHARGER, AB8500_BAT_CTRL_CURRENT_SOURCE,
  235. BAT_CTRL_PULL_UP_ENA | BAT_CTRL_CMP_ENA,
  236. BAT_CTRL_PULL_UP_ENA | BAT_CTRL_CMP_ENA);
  237. if (ret) {
  238. dev_err(di->dev, "%s failed enabling PU and comp\n",
  239. __func__);
  240. goto enable_pu_comp;
  241. }
  242. /*
  243. * We have to wait one 32kHz cycle before disabling
  244. * ForceBatCtrlCmpHigh since this needs to be written
  245. * in a separate cycle
  246. */
  247. udelay(32);
  248. /* Disable 'force comparator' */
  249. ret = abx500_mask_and_set_register_interruptible(di->dev,
  250. AB8500_CHARGER, AB8500_BAT_CTRL_CURRENT_SOURCE,
  251. FORCE_BAT_CTRL_CMP_HIGH, ~FORCE_BAT_CTRL_CMP_HIGH);
  252. if (ret) {
  253. dev_err(di->dev, "%s failed disabling force comp\n",
  254. __func__);
  255. goto disable_force_comp;
  256. }
  257. }
  258. return ret;
  259. /*
  260. * We have to try unsetting FORCE_BAT_CTRL_CMP_HIGH one more time
  261. * if we got an error above
  262. */
  263. disable_curr_source:
  264. /* Write 0 to the curr bits */
  265. ret = abx500_mask_and_set_register_interruptible(di->dev,
  266. AB8500_CHARGER, AB8500_BAT_CTRL_CURRENT_SOURCE,
  267. BAT_CTRL_7U_ENA | BAT_CTRL_20U_ENA,
  268. ~(BAT_CTRL_7U_ENA | BAT_CTRL_20U_ENA));
  269. if (ret) {
  270. dev_err(di->dev, "%s failed disabling current source\n",
  271. __func__);
  272. return ret;
  273. }
  274. enable_pu_comp:
  275. /* Enable Pull-Up and comparator */
  276. ret = abx500_mask_and_set_register_interruptible(di->dev,
  277. AB8500_CHARGER, AB8500_BAT_CTRL_CURRENT_SOURCE,
  278. BAT_CTRL_PULL_UP_ENA | BAT_CTRL_CMP_ENA,
  279. BAT_CTRL_PULL_UP_ENA | BAT_CTRL_CMP_ENA);
  280. if (ret) {
  281. dev_err(di->dev, "%s failed enabling PU and comp\n",
  282. __func__);
  283. return ret;
  284. }
  285. disable_force_comp:
  286. /*
  287. * We have to wait one 32kHz cycle before disabling
  288. * ForceBatCtrlCmpHigh since this needs to be written
  289. * in a separate cycle
  290. */
  291. udelay(32);
  292. /* Disable 'force comparator' */
  293. ret = abx500_mask_and_set_register_interruptible(di->dev,
  294. AB8500_CHARGER, AB8500_BAT_CTRL_CURRENT_SOURCE,
  295. FORCE_BAT_CTRL_CMP_HIGH, ~FORCE_BAT_CTRL_CMP_HIGH);
  296. if (ret) {
  297. dev_err(di->dev, "%s failed disabling force comp\n",
  298. __func__);
  299. return ret;
  300. }
  301. return ret;
  302. }
  303. /**
  304. * ab8500_btemp_get_batctrl_res() - get battery resistance
  305. * @di: pointer to the ab8500_btemp structure
  306. *
  307. * This function returns the battery pack identification resistance.
  308. * Returns value in Ohms.
  309. */
  310. static int ab8500_btemp_get_batctrl_res(struct ab8500_btemp *di)
  311. {
  312. int ret;
  313. int batctrl = 0;
  314. int res;
  315. int inst_curr;
  316. int i;
  317. /*
  318. * BATCTRL current sources are included on AB8500 cut2.0
  319. * and future versions
  320. */
  321. ret = ab8500_btemp_curr_source_enable(di, true);
  322. if (ret) {
  323. dev_err(di->dev, "%s curr source enabled failed\n", __func__);
  324. return ret;
  325. }
  326. if (!di->fg)
  327. di->fg = ab8500_fg_get();
  328. if (!di->fg) {
  329. dev_err(di->dev, "No fg found\n");
  330. return -EINVAL;
  331. }
  332. ret = ab8500_fg_inst_curr_start(di->fg);
  333. if (ret) {
  334. dev_err(di->dev, "Failed to start current measurement\n");
  335. return ret;
  336. }
  337. /*
  338. * Since there is no interrupt when current measurement is done,
  339. * loop for over 250ms (250ms is one sample conversion time
  340. * with 32.768 Khz RTC clock). Note that a stop time must be set
  341. * since the ab8500_btemp_read_batctrl_voltage call can block and
  342. * take an unknown amount of time to complete.
  343. */
  344. i = 0;
  345. do {
  346. batctrl += ab8500_btemp_read_batctrl_voltage(di);
  347. i++;
  348. msleep(20);
  349. } while (!ab8500_fg_inst_curr_done(di->fg));
  350. batctrl /= i;
  351. ret = ab8500_fg_inst_curr_finalize(di->fg, &inst_curr);
  352. if (ret) {
  353. dev_err(di->dev, "Failed to finalize current measurement\n");
  354. return ret;
  355. }
  356. res = ab8500_btemp_batctrl_volt_to_res(di, batctrl, inst_curr);
  357. ret = ab8500_btemp_curr_source_enable(di, false);
  358. if (ret) {
  359. dev_err(di->dev, "%s curr source disable failed\n", __func__);
  360. return ret;
  361. }
  362. dev_dbg(di->dev, "%s batctrl: %d res: %d inst_curr: %d samples: %d\n",
  363. __func__, batctrl, res, inst_curr, i);
  364. return res;
  365. }
  366. /**
  367. * ab8500_btemp_res_to_temp() - resistance to temperature
  368. * @di: pointer to the ab8500_btemp structure
  369. * @tbl: pointer to the resiatance to temperature table
  370. * @tbl_size: size of the resistance to temperature table
  371. * @res: resistance to calculate the temperature from
  372. *
  373. * This function returns the battery temperature in degrees Celcius
  374. * based on the NTC resistance.
  375. */
  376. static int ab8500_btemp_res_to_temp(struct ab8500_btemp *di,
  377. const struct abx500_res_to_temp *tbl, int tbl_size, int res)
  378. {
  379. int i, temp;
  380. /*
  381. * Calculate the formula for the straight line
  382. * Simple interpolation if we are within
  383. * the resistance table limits, extrapolate
  384. * if resistance is outside the limits.
  385. */
  386. if (res > tbl[0].resist)
  387. i = 0;
  388. else if (res <= tbl[tbl_size - 1].resist)
  389. i = tbl_size - 2;
  390. else {
  391. i = 0;
  392. while (!(res <= tbl[i].resist &&
  393. res > tbl[i + 1].resist))
  394. i++;
  395. }
  396. temp = tbl[i].temp + ((tbl[i + 1].temp - tbl[i].temp) *
  397. (res - tbl[i].resist)) / (tbl[i + 1].resist - tbl[i].resist);
  398. return temp;
  399. }
  400. /**
  401. * ab8500_btemp_measure_temp() - measure battery temperature
  402. * @di: pointer to the ab8500_btemp structure
  403. *
  404. * Returns battery temperature (on success) else the previous temperature
  405. */
  406. static int ab8500_btemp_measure_temp(struct ab8500_btemp *di)
  407. {
  408. int temp;
  409. static int prev;
  410. int rbat, rntc, vntc;
  411. u8 id;
  412. id = di->bm->batt_id;
  413. if (di->bm->adc_therm == ABx500_ADC_THERM_BATCTRL &&
  414. id != BATTERY_UNKNOWN) {
  415. rbat = ab8500_btemp_get_batctrl_res(di);
  416. if (rbat < 0) {
  417. dev_err(di->dev, "%s get batctrl res failed\n",
  418. __func__);
  419. /*
  420. * Return out-of-range temperature so that
  421. * charging is stopped
  422. */
  423. return BTEMP_THERMAL_LOW_LIMIT;
  424. }
  425. temp = ab8500_btemp_res_to_temp(di,
  426. di->bm->bat_type[id].r_to_t_tbl,
  427. di->bm->bat_type[id].n_temp_tbl_elements, rbat);
  428. } else {
  429. vntc = ab8500_gpadc_convert(di->gpadc, BTEMP_BALL);
  430. if (vntc < 0) {
  431. dev_err(di->dev,
  432. "%s gpadc conversion failed,"
  433. " using previous value\n", __func__);
  434. return prev;
  435. }
  436. /*
  437. * The PCB NTC is sourced from VTVOUT via a 230kOhm
  438. * resistor.
  439. */
  440. rntc = 230000 * vntc / (VTVOUT_V - vntc);
  441. temp = ab8500_btemp_res_to_temp(di,
  442. di->bm->bat_type[id].r_to_t_tbl,
  443. di->bm->bat_type[id].n_temp_tbl_elements, rntc);
  444. prev = temp;
  445. }
  446. dev_dbg(di->dev, "Battery temperature is %d\n", temp);
  447. return temp;
  448. }
  449. /**
  450. * ab8500_btemp_id() - Identify the connected battery
  451. * @di: pointer to the ab8500_btemp structure
  452. *
  453. * This function will try to identify the battery by reading the ID
  454. * resistor. Some brands use a combined ID resistor with a NTC resistor to
  455. * both be able to identify and to read the temperature of it.
  456. */
  457. static int ab8500_btemp_id(struct ab8500_btemp *di)
  458. {
  459. int res;
  460. u8 i;
  461. di->curr_source = BTEMP_BATCTRL_CURR_SRC_7UA;
  462. di->bm->batt_id = BATTERY_UNKNOWN;
  463. res = ab8500_btemp_get_batctrl_res(di);
  464. if (res < 0) {
  465. dev_err(di->dev, "%s get batctrl res failed\n", __func__);
  466. return -ENXIO;
  467. }
  468. /* BATTERY_UNKNOWN is defined on position 0, skip it! */
  469. for (i = BATTERY_UNKNOWN + 1; i < di->bm->n_btypes; i++) {
  470. if ((res <= di->bm->bat_type[i].resis_high) &&
  471. (res >= di->bm->bat_type[i].resis_low)) {
  472. dev_dbg(di->dev, "Battery detected on %s"
  473. " low %d < res %d < high: %d"
  474. " index: %d\n",
  475. di->bm->adc_therm == ABx500_ADC_THERM_BATCTRL ?
  476. "BATCTRL" : "BATTEMP",
  477. di->bm->bat_type[i].resis_low, res,
  478. di->bm->bat_type[i].resis_high, i);
  479. di->bm->batt_id = i;
  480. break;
  481. }
  482. }
  483. if (di->bm->batt_id == BATTERY_UNKNOWN) {
  484. dev_warn(di->dev, "Battery identified as unknown"
  485. ", resistance %d Ohm\n", res);
  486. return -ENXIO;
  487. }
  488. /*
  489. * We only have to change current source if the
  490. * detected type is Type 1, else we use the 7uA source
  491. */
  492. if (di->bm->adc_therm == ABx500_ADC_THERM_BATCTRL &&
  493. di->bm->batt_id == 1) {
  494. dev_dbg(di->dev, "Set BATCTRL current source to 20uA\n");
  495. di->curr_source = BTEMP_BATCTRL_CURR_SRC_20UA;
  496. }
  497. return di->bm->batt_id;
  498. }
  499. /**
  500. * ab8500_btemp_periodic_work() - Measuring the temperature periodically
  501. * @work: pointer to the work_struct structure
  502. *
  503. * Work function for measuring the temperature periodically
  504. */
  505. static void ab8500_btemp_periodic_work(struct work_struct *work)
  506. {
  507. int interval;
  508. struct ab8500_btemp *di = container_of(work,
  509. struct ab8500_btemp, btemp_periodic_work.work);
  510. if (!di->initialized) {
  511. di->initialized = true;
  512. /* Identify the battery */
  513. if (ab8500_btemp_id(di) < 0)
  514. dev_warn(di->dev, "failed to identify the battery\n");
  515. }
  516. di->bat_temp = ab8500_btemp_measure_temp(di);
  517. if (di->bat_temp != di->prev_bat_temp) {
  518. di->prev_bat_temp = di->bat_temp;
  519. power_supply_changed(&di->btemp_psy);
  520. }
  521. if (di->events.ac_conn || di->events.usb_conn)
  522. interval = di->bm->temp_interval_chg;
  523. else
  524. interval = di->bm->temp_interval_nochg;
  525. /* Schedule a new measurement */
  526. queue_delayed_work(di->btemp_wq,
  527. &di->btemp_periodic_work,
  528. round_jiffies(interval * HZ));
  529. }
  530. /**
  531. * ab8500_btemp_batctrlindb_handler() - battery removal detected
  532. * @irq: interrupt number
  533. * @_di: void pointer that has to address of ab8500_btemp
  534. *
  535. * Returns IRQ status(IRQ_HANDLED)
  536. */
  537. static irqreturn_t ab8500_btemp_batctrlindb_handler(int irq, void *_di)
  538. {
  539. struct ab8500_btemp *di = _di;
  540. dev_err(di->dev, "Battery removal detected!\n");
  541. di->events.batt_rem = true;
  542. power_supply_changed(&di->btemp_psy);
  543. return IRQ_HANDLED;
  544. }
  545. /**
  546. * ab8500_btemp_templow_handler() - battery temp lower than 10 degrees
  547. * @irq: interrupt number
  548. * @_di: void pointer that has to address of ab8500_btemp
  549. *
  550. * Returns IRQ status(IRQ_HANDLED)
  551. */
  552. static irqreturn_t ab8500_btemp_templow_handler(int irq, void *_di)
  553. {
  554. struct ab8500_btemp *di = _di;
  555. if (is_ab8500_2p0_or_earlier(di->parent)) {
  556. dev_dbg(di->dev, "Ignore false btemp low irq"
  557. " for ABB cut 1.0, 1.1 and 2.0\n");
  558. } else {
  559. dev_crit(di->dev, "Battery temperature lower than -10deg c\n");
  560. di->events.btemp_low = true;
  561. di->events.btemp_high = false;
  562. di->events.btemp_medhigh = false;
  563. di->events.btemp_lowmed = false;
  564. power_supply_changed(&di->btemp_psy);
  565. }
  566. return IRQ_HANDLED;
  567. }
  568. /**
  569. * ab8500_btemp_temphigh_handler() - battery temp higher than max temp
  570. * @irq: interrupt number
  571. * @_di: void pointer that has to address of ab8500_btemp
  572. *
  573. * Returns IRQ status(IRQ_HANDLED)
  574. */
  575. static irqreturn_t ab8500_btemp_temphigh_handler(int irq, void *_di)
  576. {
  577. struct ab8500_btemp *di = _di;
  578. dev_crit(di->dev, "Battery temperature is higher than MAX temp\n");
  579. di->events.btemp_high = true;
  580. di->events.btemp_medhigh = false;
  581. di->events.btemp_lowmed = false;
  582. di->events.btemp_low = false;
  583. power_supply_changed(&di->btemp_psy);
  584. return IRQ_HANDLED;
  585. }
  586. /**
  587. * ab8500_btemp_lowmed_handler() - battery temp between low and medium
  588. * @irq: interrupt number
  589. * @_di: void pointer that has to address of ab8500_btemp
  590. *
  591. * Returns IRQ status(IRQ_HANDLED)
  592. */
  593. static irqreturn_t ab8500_btemp_lowmed_handler(int irq, void *_di)
  594. {
  595. struct ab8500_btemp *di = _di;
  596. dev_dbg(di->dev, "Battery temperature is between low and medium\n");
  597. di->events.btemp_lowmed = true;
  598. di->events.btemp_medhigh = false;
  599. di->events.btemp_high = false;
  600. di->events.btemp_low = false;
  601. power_supply_changed(&di->btemp_psy);
  602. return IRQ_HANDLED;
  603. }
  604. /**
  605. * ab8500_btemp_medhigh_handler() - battery temp between medium and high
  606. * @irq: interrupt number
  607. * @_di: void pointer that has to address of ab8500_btemp
  608. *
  609. * Returns IRQ status(IRQ_HANDLED)
  610. */
  611. static irqreturn_t ab8500_btemp_medhigh_handler(int irq, void *_di)
  612. {
  613. struct ab8500_btemp *di = _di;
  614. dev_dbg(di->dev, "Battery temperature is between medium and high\n");
  615. di->events.btemp_medhigh = true;
  616. di->events.btemp_lowmed = false;
  617. di->events.btemp_high = false;
  618. di->events.btemp_low = false;
  619. power_supply_changed(&di->btemp_psy);
  620. return IRQ_HANDLED;
  621. }
  622. /**
  623. * ab8500_btemp_periodic() - Periodic temperature measurements
  624. * @di: pointer to the ab8500_btemp structure
  625. * @enable: enable or disable periodic temperature measurements
  626. *
  627. * Starts of stops periodic temperature measurements. Periodic measurements
  628. * should only be done when a charger is connected.
  629. */
  630. static void ab8500_btemp_periodic(struct ab8500_btemp *di,
  631. bool enable)
  632. {
  633. dev_dbg(di->dev, "Enable periodic temperature measurements: %d\n",
  634. enable);
  635. /*
  636. * Make sure a new measurement is done directly by cancelling
  637. * any pending work
  638. */
  639. cancel_delayed_work_sync(&di->btemp_periodic_work);
  640. if (enable)
  641. queue_delayed_work(di->btemp_wq, &di->btemp_periodic_work, 0);
  642. }
  643. /**
  644. * ab8500_btemp_get_temp() - get battery temperature
  645. * @di: pointer to the ab8500_btemp structure
  646. *
  647. * Returns battery temperature
  648. */
  649. static int ab8500_btemp_get_temp(struct ab8500_btemp *di)
  650. {
  651. int temp = 0;
  652. /*
  653. * The BTEMP events are not reliabe on AB8500 cut2.0
  654. * and prior versions
  655. */
  656. if (is_ab8500_2p0_or_earlier(di->parent)) {
  657. temp = di->bat_temp * 10;
  658. } else {
  659. if (di->events.btemp_low) {
  660. if (temp > di->btemp_ranges.btemp_low_limit)
  661. temp = di->btemp_ranges.btemp_low_limit;
  662. else
  663. temp = di->bat_temp * 10;
  664. } else if (di->events.btemp_high) {
  665. if (temp < di->btemp_ranges.btemp_high_limit)
  666. temp = di->btemp_ranges.btemp_high_limit;
  667. else
  668. temp = di->bat_temp * 10;
  669. } else if (di->events.btemp_lowmed) {
  670. if (temp > di->btemp_ranges.btemp_med_limit)
  671. temp = di->btemp_ranges.btemp_med_limit;
  672. else
  673. temp = di->bat_temp * 10;
  674. } else if (di->events.btemp_medhigh) {
  675. if (temp < di->btemp_ranges.btemp_med_limit)
  676. temp = di->btemp_ranges.btemp_med_limit;
  677. else
  678. temp = di->bat_temp * 10;
  679. } else
  680. temp = di->bat_temp * 10;
  681. }
  682. return temp;
  683. }
  684. /**
  685. * ab8500_btemp_get_batctrl_temp() - get the temperature
  686. * @btemp: pointer to the btemp structure
  687. *
  688. * Returns the batctrl temperature in millidegrees
  689. */
  690. int ab8500_btemp_get_batctrl_temp(struct ab8500_btemp *btemp)
  691. {
  692. return btemp->bat_temp * 1000;
  693. }
  694. /**
  695. * ab8500_btemp_get_property() - get the btemp properties
  696. * @psy: pointer to the power_supply structure
  697. * @psp: pointer to the power_supply_property structure
  698. * @val: pointer to the power_supply_propval union
  699. *
  700. * This function gets called when an application tries to get the btemp
  701. * properties by reading the sysfs files.
  702. * online: presence of the battery
  703. * present: presence of the battery
  704. * technology: battery technology
  705. * temp: battery temperature
  706. * Returns error code in case of failure else 0(on success)
  707. */
  708. static int ab8500_btemp_get_property(struct power_supply *psy,
  709. enum power_supply_property psp,
  710. union power_supply_propval *val)
  711. {
  712. struct ab8500_btemp *di;
  713. di = to_ab8500_btemp_device_info(psy);
  714. switch (psp) {
  715. case POWER_SUPPLY_PROP_PRESENT:
  716. case POWER_SUPPLY_PROP_ONLINE:
  717. if (di->events.batt_rem)
  718. val->intval = 0;
  719. else
  720. val->intval = 1;
  721. break;
  722. case POWER_SUPPLY_PROP_TECHNOLOGY:
  723. val->intval = di->bm->bat_type[di->bm->batt_id].name;
  724. break;
  725. case POWER_SUPPLY_PROP_TEMP:
  726. val->intval = ab8500_btemp_get_temp(di);
  727. break;
  728. default:
  729. return -EINVAL;
  730. }
  731. return 0;
  732. }
  733. static int ab8500_btemp_get_ext_psy_data(struct device *dev, void *data)
  734. {
  735. struct power_supply *psy;
  736. struct power_supply *ext;
  737. struct ab8500_btemp *di;
  738. union power_supply_propval ret;
  739. int i, j;
  740. bool psy_found = false;
  741. psy = (struct power_supply *)data;
  742. ext = dev_get_drvdata(dev);
  743. di = to_ab8500_btemp_device_info(psy);
  744. /*
  745. * For all psy where the name of your driver
  746. * appears in any supplied_to
  747. */
  748. for (i = 0; i < ext->num_supplicants; i++) {
  749. if (!strcmp(ext->supplied_to[i], psy->name))
  750. psy_found = true;
  751. }
  752. if (!psy_found)
  753. return 0;
  754. /* Go through all properties for the psy */
  755. for (j = 0; j < ext->num_properties; j++) {
  756. enum power_supply_property prop;
  757. prop = ext->properties[j];
  758. if (ext->get_property(ext, prop, &ret))
  759. continue;
  760. switch (prop) {
  761. case POWER_SUPPLY_PROP_PRESENT:
  762. switch (ext->type) {
  763. case POWER_SUPPLY_TYPE_MAINS:
  764. /* AC disconnected */
  765. if (!ret.intval && di->events.ac_conn) {
  766. di->events.ac_conn = false;
  767. }
  768. /* AC connected */
  769. else if (ret.intval && !di->events.ac_conn) {
  770. di->events.ac_conn = true;
  771. if (!di->events.usb_conn)
  772. ab8500_btemp_periodic(di, true);
  773. }
  774. break;
  775. case POWER_SUPPLY_TYPE_USB:
  776. /* USB disconnected */
  777. if (!ret.intval && di->events.usb_conn) {
  778. di->events.usb_conn = false;
  779. }
  780. /* USB connected */
  781. else if (ret.intval && !di->events.usb_conn) {
  782. di->events.usb_conn = true;
  783. if (!di->events.ac_conn)
  784. ab8500_btemp_periodic(di, true);
  785. }
  786. break;
  787. default:
  788. break;
  789. }
  790. break;
  791. default:
  792. break;
  793. }
  794. }
  795. return 0;
  796. }
  797. /**
  798. * ab8500_btemp_external_power_changed() - callback for power supply changes
  799. * @psy: pointer to the structure power_supply
  800. *
  801. * This function is pointing to the function pointer external_power_changed
  802. * of the structure power_supply.
  803. * This function gets executed when there is a change in the external power
  804. * supply to the btemp.
  805. */
  806. static void ab8500_btemp_external_power_changed(struct power_supply *psy)
  807. {
  808. struct ab8500_btemp *di = to_ab8500_btemp_device_info(psy);
  809. class_for_each_device(power_supply_class, NULL,
  810. &di->btemp_psy, ab8500_btemp_get_ext_psy_data);
  811. }
  812. /* ab8500 btemp driver interrupts and their respective isr */
  813. static struct ab8500_btemp_interrupts ab8500_btemp_irq[] = {
  814. {"BAT_CTRL_INDB", ab8500_btemp_batctrlindb_handler},
  815. {"BTEMP_LOW", ab8500_btemp_templow_handler},
  816. {"BTEMP_HIGH", ab8500_btemp_temphigh_handler},
  817. {"BTEMP_LOW_MEDIUM", ab8500_btemp_lowmed_handler},
  818. {"BTEMP_MEDIUM_HIGH", ab8500_btemp_medhigh_handler},
  819. };
  820. #if defined(CONFIG_PM)
  821. static int ab8500_btemp_resume(struct platform_device *pdev)
  822. {
  823. struct ab8500_btemp *di = platform_get_drvdata(pdev);
  824. ab8500_btemp_periodic(di, true);
  825. return 0;
  826. }
  827. static int ab8500_btemp_suspend(struct platform_device *pdev,
  828. pm_message_t state)
  829. {
  830. struct ab8500_btemp *di = platform_get_drvdata(pdev);
  831. ab8500_btemp_periodic(di, false);
  832. return 0;
  833. }
  834. #else
  835. #define ab8500_btemp_suspend NULL
  836. #define ab8500_btemp_resume NULL
  837. #endif
  838. static int __devexit ab8500_btemp_remove(struct platform_device *pdev)
  839. {
  840. struct ab8500_btemp *di = platform_get_drvdata(pdev);
  841. int i, irq;
  842. /* Disable interrupts */
  843. for (i = 0; i < ARRAY_SIZE(ab8500_btemp_irq); i++) {
  844. irq = platform_get_irq_byname(pdev, ab8500_btemp_irq[i].name);
  845. free_irq(irq, di);
  846. }
  847. /* Delete the work queue */
  848. destroy_workqueue(di->btemp_wq);
  849. flush_scheduled_work();
  850. power_supply_unregister(&di->btemp_psy);
  851. platform_set_drvdata(pdev, NULL);
  852. return 0;
  853. }
  854. static char *supply_interface[] = {
  855. "ab8500_chargalg",
  856. "ab8500_fg",
  857. };
  858. static int __devinit ab8500_btemp_probe(struct platform_device *pdev)
  859. {
  860. struct device_node *np = pdev->dev.of_node;
  861. struct ab8500_btemp *di;
  862. int irq, i, ret = 0;
  863. u8 val;
  864. di = devm_kzalloc(&pdev->dev, sizeof(*di), GFP_KERNEL);
  865. if (!di) {
  866. dev_err(&pdev->dev, "%s no mem for ab8500_btemp\n", __func__);
  867. return -ENOMEM;
  868. }
  869. di->bm = pdev->mfd_cell->platform_data;
  870. if (!di->bm) {
  871. if (np) {
  872. ret = ab8500_bm_of_probe(&pdev->dev, np, di->bm);
  873. if (ret) {
  874. dev_err(&pdev->dev,
  875. "failed to get battery information\n");
  876. return ret;
  877. }
  878. } else {
  879. dev_err(&pdev->dev, "missing dt node for ab8500_btemp\n");
  880. return -EINVAL;
  881. }
  882. } else {
  883. dev_info(&pdev->dev, "falling back to legacy platform data\n");
  884. }
  885. /* get parent data */
  886. di->dev = &pdev->dev;
  887. di->parent = dev_get_drvdata(pdev->dev.parent);
  888. di->gpadc = ab8500_gpadc_get("ab8500-gpadc.0");
  889. di->initialized = false;
  890. /* BTEMP supply */
  891. di->btemp_psy.name = "ab8500_btemp";
  892. di->btemp_psy.type = POWER_SUPPLY_TYPE_BATTERY;
  893. di->btemp_psy.properties = ab8500_btemp_props;
  894. di->btemp_psy.num_properties = ARRAY_SIZE(ab8500_btemp_props);
  895. di->btemp_psy.get_property = ab8500_btemp_get_property;
  896. di->btemp_psy.supplied_to = supply_interface;
  897. di->btemp_psy.num_supplicants = ARRAY_SIZE(supply_interface);
  898. di->btemp_psy.external_power_changed =
  899. ab8500_btemp_external_power_changed;
  900. /* Create a work queue for the btemp */
  901. di->btemp_wq =
  902. create_singlethread_workqueue("ab8500_btemp_wq");
  903. if (di->btemp_wq == NULL) {
  904. dev_err(di->dev, "failed to create work queue\n");
  905. return -ENOMEM;
  906. }
  907. /* Init work for measuring temperature periodically */
  908. INIT_DEFERRABLE_WORK(&di->btemp_periodic_work,
  909. ab8500_btemp_periodic_work);
  910. /* Set BTEMP thermal limits. Low and Med are fixed */
  911. di->btemp_ranges.btemp_low_limit = BTEMP_THERMAL_LOW_LIMIT;
  912. di->btemp_ranges.btemp_med_limit = BTEMP_THERMAL_MED_LIMIT;
  913. ret = abx500_get_register_interruptible(di->dev, AB8500_CHARGER,
  914. AB8500_BTEMP_HIGH_TH, &val);
  915. if (ret < 0) {
  916. dev_err(di->dev, "%s ab8500 read failed\n", __func__);
  917. goto free_btemp_wq;
  918. }
  919. switch (val) {
  920. case BTEMP_HIGH_TH_57_0:
  921. case BTEMP_HIGH_TH_57_1:
  922. di->btemp_ranges.btemp_high_limit =
  923. BTEMP_THERMAL_HIGH_LIMIT_57;
  924. break;
  925. case BTEMP_HIGH_TH_52:
  926. di->btemp_ranges.btemp_high_limit =
  927. BTEMP_THERMAL_HIGH_LIMIT_52;
  928. break;
  929. case BTEMP_HIGH_TH_62:
  930. di->btemp_ranges.btemp_high_limit =
  931. BTEMP_THERMAL_HIGH_LIMIT_62;
  932. break;
  933. }
  934. /* Register BTEMP power supply class */
  935. ret = power_supply_register(di->dev, &di->btemp_psy);
  936. if (ret) {
  937. dev_err(di->dev, "failed to register BTEMP psy\n");
  938. goto free_btemp_wq;
  939. }
  940. /* Register interrupts */
  941. for (i = 0; i < ARRAY_SIZE(ab8500_btemp_irq); i++) {
  942. irq = platform_get_irq_byname(pdev, ab8500_btemp_irq[i].name);
  943. ret = request_threaded_irq(irq, NULL, ab8500_btemp_irq[i].isr,
  944. IRQF_SHARED | IRQF_NO_SUSPEND,
  945. ab8500_btemp_irq[i].name, di);
  946. if (ret) {
  947. dev_err(di->dev, "failed to request %s IRQ %d: %d\n"
  948. , ab8500_btemp_irq[i].name, irq, ret);
  949. goto free_irq;
  950. }
  951. dev_dbg(di->dev, "Requested %s IRQ %d: %d\n",
  952. ab8500_btemp_irq[i].name, irq, ret);
  953. }
  954. platform_set_drvdata(pdev, di);
  955. /* Kick off periodic temperature measurements */
  956. ab8500_btemp_periodic(di, true);
  957. list_add_tail(&di->node, &ab8500_btemp_list);
  958. return ret;
  959. free_irq:
  960. power_supply_unregister(&di->btemp_psy);
  961. /* We also have to free all successfully registered irqs */
  962. for (i = i - 1; i >= 0; i--) {
  963. irq = platform_get_irq_byname(pdev, ab8500_btemp_irq[i].name);
  964. free_irq(irq, di);
  965. }
  966. free_btemp_wq:
  967. destroy_workqueue(di->btemp_wq);
  968. return ret;
  969. }
  970. static const struct of_device_id ab8500_btemp_match[] = {
  971. { .compatible = "stericsson,ab8500-btemp", },
  972. { },
  973. };
  974. static struct platform_driver ab8500_btemp_driver = {
  975. .probe = ab8500_btemp_probe,
  976. .remove = __devexit_p(ab8500_btemp_remove),
  977. .suspend = ab8500_btemp_suspend,
  978. .resume = ab8500_btemp_resume,
  979. .driver = {
  980. .name = "ab8500-btemp",
  981. .owner = THIS_MODULE,
  982. .of_match_table = ab8500_btemp_match,
  983. },
  984. };
  985. static int __init ab8500_btemp_init(void)
  986. {
  987. return platform_driver_register(&ab8500_btemp_driver);
  988. }
  989. static void __exit ab8500_btemp_exit(void)
  990. {
  991. platform_driver_unregister(&ab8500_btemp_driver);
  992. }
  993. subsys_initcall_sync(ab8500_btemp_init);
  994. module_exit(ab8500_btemp_exit);
  995. MODULE_LICENSE("GPL v2");
  996. MODULE_AUTHOR("Johan Palsson, Karl Komierowski, Arun R Murthy");
  997. MODULE_ALIAS("platform:ab8500-btemp");
  998. MODULE_DESCRIPTION("AB8500 battery temperature driver");