sharpsl_pm.c 28 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021
  1. /*
  2. * Battery and Power Management code for the Sharp SL-C7xx and SL-Cxx00
  3. * series of PDAs
  4. *
  5. * Copyright (c) 2004-2005 Richard Purdie
  6. *
  7. * Based on code written by Sharp for 2.4 kernels
  8. *
  9. * This program is free software; you can redistribute it and/or modify
  10. * it under the terms of the GNU General Public License version 2 as
  11. * published by the Free Software Foundation.
  12. *
  13. */
  14. #undef DEBUG
  15. #include <linux/module.h>
  16. #include <linux/kernel.h>
  17. #include <linux/interrupt.h>
  18. #include <linux/platform_device.h>
  19. #include <linux/apm-emulation.h>
  20. #include <linux/timer.h>
  21. #include <linux/delay.h>
  22. #include <linux/leds.h>
  23. #include <linux/suspend.h>
  24. #include <linux/gpio.h>
  25. #include <asm/mach-types.h>
  26. #include <mach/pm.h>
  27. #include <mach/pxa2xx-regs.h>
  28. #include <mach/regs-rtc.h>
  29. #include <mach/sharpsl.h>
  30. #include <mach/sharpsl_pm.h>
  31. #include "sharpsl.h"
  32. /*
  33. * Constants
  34. */
  35. #define SHARPSL_CHARGE_ON_TIME_INTERVAL (msecs_to_jiffies(1*60*1000)) /* 1 min */
  36. #define SHARPSL_CHARGE_FINISH_TIME (msecs_to_jiffies(10*60*1000)) /* 10 min */
  37. #define SHARPSL_BATCHK_TIME (msecs_to_jiffies(15*1000)) /* 15 sec */
  38. #define SHARPSL_BATCHK_TIME_SUSPEND (60*10) /* 10 min */
  39. #define SHARPSL_WAIT_CO_TIME 15 /* 15 sec */
  40. #define SHARPSL_WAIT_DISCHARGE_ON 100 /* 100 msec */
  41. #define SHARPSL_CHECK_BATTERY_WAIT_TIME_TEMP 10 /* 10 msec */
  42. #define SHARPSL_CHECK_BATTERY_WAIT_TIME_VOLT 10 /* 10 msec */
  43. #define SHARPSL_CHECK_BATTERY_WAIT_TIME_ACIN 10 /* 10 msec */
  44. #define SHARPSL_CHARGE_WAIT_TIME 15 /* 15 msec */
  45. #define SHARPSL_CHARGE_CO_CHECK_TIME 5 /* 5 msec */
  46. #define SHARPSL_CHARGE_RETRY_CNT 1 /* eqv. 10 min */
  47. /*
  48. * Prototypes
  49. */
  50. #ifdef CONFIG_PM
  51. static int sharpsl_off_charge_battery(void);
  52. static int sharpsl_check_battery_voltage(void);
  53. static int sharpsl_fatal_check(void);
  54. #endif
  55. static int sharpsl_check_battery_temp(void);
  56. static int sharpsl_ac_check(void);
  57. static int sharpsl_average_value(int ad);
  58. static void sharpsl_average_clear(void);
  59. static void sharpsl_charge_toggle(struct work_struct *private_);
  60. static void sharpsl_battery_thread(struct work_struct *private_);
  61. /*
  62. * Variables
  63. */
  64. struct sharpsl_pm_status sharpsl_pm;
  65. static DECLARE_DELAYED_WORK(toggle_charger, sharpsl_charge_toggle);
  66. static DECLARE_DELAYED_WORK(sharpsl_bat, sharpsl_battery_thread);
  67. DEFINE_LED_TRIGGER(sharpsl_charge_led_trigger);
  68. struct battery_thresh sharpsl_battery_levels_acin[] = {
  69. { 213, 100},
  70. { 212, 98},
  71. { 211, 95},
  72. { 210, 93},
  73. { 209, 90},
  74. { 208, 88},
  75. { 207, 85},
  76. { 206, 83},
  77. { 205, 80},
  78. { 204, 78},
  79. { 203, 75},
  80. { 202, 73},
  81. { 201, 70},
  82. { 200, 68},
  83. { 199, 65},
  84. { 198, 63},
  85. { 197, 60},
  86. { 196, 58},
  87. { 195, 55},
  88. { 194, 53},
  89. { 193, 50},
  90. { 192, 48},
  91. { 192, 45},
  92. { 191, 43},
  93. { 191, 40},
  94. { 190, 38},
  95. { 190, 35},
  96. { 189, 33},
  97. { 188, 30},
  98. { 187, 28},
  99. { 186, 25},
  100. { 185, 23},
  101. { 184, 20},
  102. { 183, 18},
  103. { 182, 15},
  104. { 181, 13},
  105. { 180, 10},
  106. { 179, 8},
  107. { 178, 5},
  108. { 0, 0},
  109. };
  110. struct battery_thresh sharpsl_battery_levels_noac[] = {
  111. { 213, 100},
  112. { 212, 98},
  113. { 211, 95},
  114. { 210, 93},
  115. { 209, 90},
  116. { 208, 88},
  117. { 207, 85},
  118. { 206, 83},
  119. { 205, 80},
  120. { 204, 78},
  121. { 203, 75},
  122. { 202, 73},
  123. { 201, 70},
  124. { 200, 68},
  125. { 199, 65},
  126. { 198, 63},
  127. { 197, 60},
  128. { 196, 58},
  129. { 195, 55},
  130. { 194, 53},
  131. { 193, 50},
  132. { 192, 48},
  133. { 191, 45},
  134. { 190, 43},
  135. { 189, 40},
  136. { 188, 38},
  137. { 187, 35},
  138. { 186, 33},
  139. { 185, 30},
  140. { 184, 28},
  141. { 183, 25},
  142. { 182, 23},
  143. { 181, 20},
  144. { 180, 18},
  145. { 179, 15},
  146. { 178, 13},
  147. { 177, 10},
  148. { 176, 8},
  149. { 175, 5},
  150. { 0, 0},
  151. };
  152. /* MAX1111 Commands */
  153. #define MAXCTRL_PD0 (1u << 0)
  154. #define MAXCTRL_PD1 (1u << 1)
  155. #define MAXCTRL_SGL (1u << 2)
  156. #define MAXCTRL_UNI (1u << 3)
  157. #define MAXCTRL_SEL_SH 4
  158. #define MAXCTRL_STR (1u << 7)
  159. /*
  160. * Read MAX1111 ADC
  161. */
  162. int sharpsl_pm_pxa_read_max1111(int channel)
  163. {
  164. /* Ugly, better move this function into another module */
  165. if (machine_is_tosa())
  166. return 0;
  167. #ifdef CONFIG_CORGI_SSP_DEPRECATED
  168. return corgi_ssp_max1111_get((channel << MAXCTRL_SEL_SH) | MAXCTRL_PD0 | MAXCTRL_PD1
  169. | MAXCTRL_SGL | MAXCTRL_UNI | MAXCTRL_STR);
  170. #else
  171. extern int max1111_read_channel(int);
  172. /* max1111 accepts channels from 0-3, however,
  173. * it is encoded from 0-7 here in the code.
  174. */
  175. return max1111_read_channel(channel >> 1);
  176. #endif
  177. }
  178. static int get_percentage(int voltage)
  179. {
  180. int i = sharpsl_pm.machinfo->bat_levels - 1;
  181. int bl_status = sharpsl_pm.machinfo->backlight_get_status ? sharpsl_pm.machinfo->backlight_get_status() : 0;
  182. struct battery_thresh *thresh;
  183. if (sharpsl_pm.charge_mode == CHRG_ON)
  184. thresh = bl_status ? sharpsl_pm.machinfo->bat_levels_acin_bl : sharpsl_pm.machinfo->bat_levels_acin;
  185. else
  186. thresh = bl_status ? sharpsl_pm.machinfo->bat_levels_noac_bl : sharpsl_pm.machinfo->bat_levels_noac;
  187. while (i > 0 && (voltage > thresh[i].voltage))
  188. i--;
  189. return thresh[i].percentage;
  190. }
  191. static int get_apm_status(int voltage)
  192. {
  193. int low_thresh, high_thresh;
  194. if (sharpsl_pm.charge_mode == CHRG_ON) {
  195. high_thresh = sharpsl_pm.machinfo->status_high_acin;
  196. low_thresh = sharpsl_pm.machinfo->status_low_acin;
  197. } else {
  198. high_thresh = sharpsl_pm.machinfo->status_high_noac;
  199. low_thresh = sharpsl_pm.machinfo->status_low_noac;
  200. }
  201. if (voltage >= high_thresh)
  202. return APM_BATTERY_STATUS_HIGH;
  203. if (voltage >= low_thresh)
  204. return APM_BATTERY_STATUS_LOW;
  205. return APM_BATTERY_STATUS_CRITICAL;
  206. }
  207. void sharpsl_battery_kick(void)
  208. {
  209. schedule_delayed_work(&sharpsl_bat, msecs_to_jiffies(125));
  210. }
  211. EXPORT_SYMBOL(sharpsl_battery_kick);
  212. static void sharpsl_battery_thread(struct work_struct *private_)
  213. {
  214. int voltage, percent, apm_status, i;
  215. if (!sharpsl_pm.machinfo)
  216. return;
  217. sharpsl_pm.battstat.ac_status = (sharpsl_pm.machinfo->read_devdata(SHARPSL_STATUS_ACIN) ? APM_AC_ONLINE : APM_AC_OFFLINE);
  218. /* Corgi cannot confirm when battery fully charged so periodically kick! */
  219. if (!sharpsl_pm.machinfo->batfull_irq && (sharpsl_pm.charge_mode == CHRG_ON)
  220. && time_after(jiffies, sharpsl_pm.charge_start_time + SHARPSL_CHARGE_ON_TIME_INTERVAL))
  221. schedule_delayed_work(&toggle_charger, 0);
  222. for (i = 0; i < 5; i++) {
  223. voltage = sharpsl_pm.machinfo->read_devdata(SHARPSL_BATT_VOLT);
  224. if (voltage > 0)
  225. break;
  226. }
  227. if (voltage <= 0) {
  228. voltage = sharpsl_pm.machinfo->bat_levels_noac[0].voltage;
  229. dev_warn(sharpsl_pm.dev, "Warning: Cannot read main battery!\n");
  230. }
  231. voltage = sharpsl_average_value(voltage);
  232. apm_status = get_apm_status(voltage);
  233. percent = get_percentage(voltage);
  234. /* At low battery voltages, the voltage has a tendency to start
  235. creeping back up so we try to avoid this here */
  236. if ((sharpsl_pm.battstat.ac_status == APM_AC_ONLINE)
  237. || (apm_status == APM_BATTERY_STATUS_HIGH)
  238. || percent <= sharpsl_pm.battstat.mainbat_percent) {
  239. sharpsl_pm.battstat.mainbat_voltage = voltage;
  240. sharpsl_pm.battstat.mainbat_status = apm_status;
  241. sharpsl_pm.battstat.mainbat_percent = percent;
  242. }
  243. dev_dbg(sharpsl_pm.dev, "Battery: voltage: %d, status: %d, percentage: %d, time: %ld\n", voltage,
  244. sharpsl_pm.battstat.mainbat_status, sharpsl_pm.battstat.mainbat_percent, jiffies);
  245. #ifdef CONFIG_BACKLIGHT_CORGI
  246. /* If battery is low. limit backlight intensity to save power. */
  247. if ((sharpsl_pm.battstat.ac_status != APM_AC_ONLINE)
  248. && ((sharpsl_pm.battstat.mainbat_status == APM_BATTERY_STATUS_LOW)
  249. || (sharpsl_pm.battstat.mainbat_status == APM_BATTERY_STATUS_CRITICAL))) {
  250. if (!(sharpsl_pm.flags & SHARPSL_BL_LIMIT)) {
  251. sharpsl_pm.machinfo->backlight_limit(1);
  252. sharpsl_pm.flags |= SHARPSL_BL_LIMIT;
  253. }
  254. } else if (sharpsl_pm.flags & SHARPSL_BL_LIMIT) {
  255. sharpsl_pm.machinfo->backlight_limit(0);
  256. sharpsl_pm.flags &= ~SHARPSL_BL_LIMIT;
  257. }
  258. #endif
  259. /* Suspend if critical battery level */
  260. if ((sharpsl_pm.battstat.ac_status != APM_AC_ONLINE)
  261. && (sharpsl_pm.battstat.mainbat_status == APM_BATTERY_STATUS_CRITICAL)
  262. && !(sharpsl_pm.flags & SHARPSL_APM_QUEUED)) {
  263. sharpsl_pm.flags |= SHARPSL_APM_QUEUED;
  264. dev_err(sharpsl_pm.dev, "Fatal Off\n");
  265. apm_queue_event(APM_CRITICAL_SUSPEND);
  266. }
  267. schedule_delayed_work(&sharpsl_bat, SHARPSL_BATCHK_TIME);
  268. }
  269. void sharpsl_pm_led(int val)
  270. {
  271. if (val == SHARPSL_LED_ERROR) {
  272. dev_err(sharpsl_pm.dev, "Charging Error!\n");
  273. } else if (val == SHARPSL_LED_ON) {
  274. dev_dbg(sharpsl_pm.dev, "Charge LED On\n");
  275. led_trigger_event(sharpsl_charge_led_trigger, LED_FULL);
  276. } else {
  277. dev_dbg(sharpsl_pm.dev, "Charge LED Off\n");
  278. led_trigger_event(sharpsl_charge_led_trigger, LED_OFF);
  279. }
  280. }
  281. static void sharpsl_charge_on(void)
  282. {
  283. dev_dbg(sharpsl_pm.dev, "Turning Charger On\n");
  284. sharpsl_pm.full_count = 0;
  285. sharpsl_pm.charge_mode = CHRG_ON;
  286. schedule_delayed_work(&toggle_charger, msecs_to_jiffies(250));
  287. schedule_delayed_work(&sharpsl_bat, msecs_to_jiffies(500));
  288. }
  289. static void sharpsl_charge_off(void)
  290. {
  291. dev_dbg(sharpsl_pm.dev, "Turning Charger Off\n");
  292. sharpsl_pm.machinfo->charge(0);
  293. sharpsl_pm_led(SHARPSL_LED_OFF);
  294. sharpsl_pm.charge_mode = CHRG_OFF;
  295. schedule_delayed_work(&sharpsl_bat, 0);
  296. }
  297. static void sharpsl_charge_error(void)
  298. {
  299. sharpsl_pm_led(SHARPSL_LED_ERROR);
  300. sharpsl_pm.machinfo->charge(0);
  301. sharpsl_pm.charge_mode = CHRG_ERROR;
  302. }
  303. static void sharpsl_charge_toggle(struct work_struct *private_)
  304. {
  305. dev_dbg(sharpsl_pm.dev, "Toggling Charger at time: %lx\n", jiffies);
  306. if (!sharpsl_pm.machinfo->read_devdata(SHARPSL_STATUS_ACIN)) {
  307. sharpsl_charge_off();
  308. return;
  309. } else if ((sharpsl_check_battery_temp() < 0) || (sharpsl_ac_check() < 0)) {
  310. sharpsl_charge_error();
  311. return;
  312. }
  313. sharpsl_pm_led(SHARPSL_LED_ON);
  314. sharpsl_pm.machinfo->charge(0);
  315. mdelay(SHARPSL_CHARGE_WAIT_TIME);
  316. sharpsl_pm.machinfo->charge(1);
  317. sharpsl_pm.charge_start_time = jiffies;
  318. }
  319. static void sharpsl_ac_timer(unsigned long data)
  320. {
  321. int acin = sharpsl_pm.machinfo->read_devdata(SHARPSL_STATUS_ACIN);
  322. dev_dbg(sharpsl_pm.dev, "AC Status: %d\n", acin);
  323. sharpsl_average_clear();
  324. if (acin && (sharpsl_pm.charge_mode != CHRG_ON))
  325. sharpsl_charge_on();
  326. else if (sharpsl_pm.charge_mode == CHRG_ON)
  327. sharpsl_charge_off();
  328. schedule_delayed_work(&sharpsl_bat, 0);
  329. }
  330. static irqreturn_t sharpsl_ac_isr(int irq, void *dev_id)
  331. {
  332. /* Delay the event slightly to debounce */
  333. /* Must be a smaller delay than the chrg_full_isr below */
  334. mod_timer(&sharpsl_pm.ac_timer, jiffies + msecs_to_jiffies(250));
  335. return IRQ_HANDLED;
  336. }
  337. static void sharpsl_chrg_full_timer(unsigned long data)
  338. {
  339. dev_dbg(sharpsl_pm.dev, "Charge Full at time: %lx\n", jiffies);
  340. sharpsl_pm.full_count++;
  341. if (!sharpsl_pm.machinfo->read_devdata(SHARPSL_STATUS_ACIN)) {
  342. dev_dbg(sharpsl_pm.dev, "Charge Full: AC removed - stop charging!\n");
  343. if (sharpsl_pm.charge_mode == CHRG_ON)
  344. sharpsl_charge_off();
  345. } else if (sharpsl_pm.full_count < 2) {
  346. dev_dbg(sharpsl_pm.dev, "Charge Full: Count too low\n");
  347. schedule_delayed_work(&toggle_charger, 0);
  348. } else if (time_after(jiffies, sharpsl_pm.charge_start_time + SHARPSL_CHARGE_FINISH_TIME)) {
  349. dev_dbg(sharpsl_pm.dev, "Charge Full: Interrupt generated too slowly - retry.\n");
  350. schedule_delayed_work(&toggle_charger, 0);
  351. } else {
  352. sharpsl_charge_off();
  353. sharpsl_pm.charge_mode = CHRG_DONE;
  354. dev_dbg(sharpsl_pm.dev, "Charge Full: Charging Finished\n");
  355. }
  356. }
  357. /* Charging Finished Interrupt (Not present on Corgi) */
  358. /* Can trigger at the same time as an AC status change so
  359. delay until after that has been processed */
  360. static irqreturn_t sharpsl_chrg_full_isr(int irq, void *dev_id)
  361. {
  362. if (sharpsl_pm.flags & SHARPSL_SUSPENDED)
  363. return IRQ_HANDLED;
  364. /* delay until after any ac interrupt */
  365. mod_timer(&sharpsl_pm.chrg_full_timer, jiffies + msecs_to_jiffies(500));
  366. return IRQ_HANDLED;
  367. }
  368. static irqreturn_t sharpsl_fatal_isr(int irq, void *dev_id)
  369. {
  370. int is_fatal = 0;
  371. if (!sharpsl_pm.machinfo->read_devdata(SHARPSL_STATUS_LOCK)) {
  372. dev_err(sharpsl_pm.dev, "Battery now Unlocked! Suspending.\n");
  373. is_fatal = 1;
  374. }
  375. if (!sharpsl_pm.machinfo->read_devdata(SHARPSL_STATUS_FATAL)) {
  376. dev_err(sharpsl_pm.dev, "Fatal Batt Error! Suspending.\n");
  377. is_fatal = 1;
  378. }
  379. if (!(sharpsl_pm.flags & SHARPSL_APM_QUEUED) && is_fatal) {
  380. sharpsl_pm.flags |= SHARPSL_APM_QUEUED;
  381. apm_queue_event(APM_CRITICAL_SUSPEND);
  382. }
  383. return IRQ_HANDLED;
  384. }
  385. /*
  386. * Maintain an average of the last 10 readings
  387. */
  388. #define SHARPSL_CNV_VALUE_NUM 10
  389. static int sharpsl_ad_index;
  390. static void sharpsl_average_clear(void)
  391. {
  392. sharpsl_ad_index = 0;
  393. }
  394. static int sharpsl_average_value(int ad)
  395. {
  396. int i, ad_val = 0;
  397. static int sharpsl_ad[SHARPSL_CNV_VALUE_NUM+1];
  398. if (sharpsl_pm.battstat.mainbat_status != APM_BATTERY_STATUS_HIGH) {
  399. sharpsl_ad_index = 0;
  400. return ad;
  401. }
  402. sharpsl_ad[sharpsl_ad_index] = ad;
  403. sharpsl_ad_index++;
  404. if (sharpsl_ad_index >= SHARPSL_CNV_VALUE_NUM) {
  405. for (i = 0; i < (SHARPSL_CNV_VALUE_NUM-1); i++)
  406. sharpsl_ad[i] = sharpsl_ad[i+1];
  407. sharpsl_ad_index = SHARPSL_CNV_VALUE_NUM - 1;
  408. }
  409. for (i = 0; i < sharpsl_ad_index; i++)
  410. ad_val += sharpsl_ad[i];
  411. return ad_val / sharpsl_ad_index;
  412. }
  413. /*
  414. * Take an array of 5 integers, remove the maximum and minimum values
  415. * and return the average.
  416. */
  417. static int get_select_val(int *val)
  418. {
  419. int i, j, k, temp, sum = 0;
  420. /* Find MAX val */
  421. temp = val[0];
  422. j = 0;
  423. for (i = 1; i < 5; i++) {
  424. if (temp < val[i]) {
  425. temp = val[i];
  426. j = i;
  427. }
  428. }
  429. /* Find MIN val */
  430. temp = val[4];
  431. k = 4;
  432. for (i = 3; i >= 0; i--) {
  433. if (temp > val[i]) {
  434. temp = val[i];
  435. k = i;
  436. }
  437. }
  438. for (i = 0; i < 5; i++)
  439. if (i != j && i != k)
  440. sum += val[i];
  441. dev_dbg(sharpsl_pm.dev, "Average: %d from values: %d, %d, %d, %d, %d\n", sum/3, val[0], val[1], val[2], val[3], val[4]);
  442. return sum/3;
  443. }
  444. static int sharpsl_check_battery_temp(void)
  445. {
  446. int val, i, buff[5];
  447. /* Check battery temperature */
  448. for (i = 0; i < 5; i++) {
  449. mdelay(SHARPSL_CHECK_BATTERY_WAIT_TIME_TEMP);
  450. sharpsl_pm.machinfo->measure_temp(1);
  451. mdelay(SHARPSL_CHECK_BATTERY_WAIT_TIME_TEMP);
  452. buff[i] = sharpsl_pm.machinfo->read_devdata(SHARPSL_BATT_TEMP);
  453. sharpsl_pm.machinfo->measure_temp(0);
  454. }
  455. val = get_select_val(buff);
  456. dev_dbg(sharpsl_pm.dev, "Temperature: %d\n", val);
  457. if (val > sharpsl_pm.machinfo->charge_on_temp) {
  458. printk(KERN_WARNING "Not charging: temperature out of limits.\n");
  459. return -1;
  460. }
  461. return 0;
  462. }
  463. #ifdef CONFIG_PM
  464. static int sharpsl_check_battery_voltage(void)
  465. {
  466. int val, i, buff[5];
  467. /* disable charge, enable discharge */
  468. sharpsl_pm.machinfo->charge(0);
  469. sharpsl_pm.machinfo->discharge(1);
  470. mdelay(SHARPSL_WAIT_DISCHARGE_ON);
  471. if (sharpsl_pm.machinfo->discharge1)
  472. sharpsl_pm.machinfo->discharge1(1);
  473. /* Check battery voltage */
  474. for (i = 0; i < 5; i++) {
  475. buff[i] = sharpsl_pm.machinfo->read_devdata(SHARPSL_BATT_VOLT);
  476. mdelay(SHARPSL_CHECK_BATTERY_WAIT_TIME_VOLT);
  477. }
  478. if (sharpsl_pm.machinfo->discharge1)
  479. sharpsl_pm.machinfo->discharge1(0);
  480. sharpsl_pm.machinfo->discharge(0);
  481. val = get_select_val(buff);
  482. dev_dbg(sharpsl_pm.dev, "Battery Voltage: %d\n", val);
  483. if (val < sharpsl_pm.machinfo->charge_on_volt)
  484. return -1;
  485. return 0;
  486. }
  487. #endif
  488. static int sharpsl_ac_check(void)
  489. {
  490. int temp, i, buff[5];
  491. for (i = 0; i < 5; i++) {
  492. buff[i] = sharpsl_pm.machinfo->read_devdata(SHARPSL_ACIN_VOLT);
  493. mdelay(SHARPSL_CHECK_BATTERY_WAIT_TIME_ACIN);
  494. }
  495. temp = get_select_val(buff);
  496. dev_dbg(sharpsl_pm.dev, "AC Voltage: %d\n", temp);
  497. if ((temp > sharpsl_pm.machinfo->charge_acin_high) || (temp < sharpsl_pm.machinfo->charge_acin_low)) {
  498. dev_err(sharpsl_pm.dev, "Error: AC check failed: voltage %d.\n", temp);
  499. return -1;
  500. }
  501. return 0;
  502. }
  503. #ifdef CONFIG_PM
  504. static int sharpsl_pm_suspend(struct platform_device *pdev, pm_message_t state)
  505. {
  506. sharpsl_pm.flags |= SHARPSL_SUSPENDED;
  507. flush_scheduled_work();
  508. if (sharpsl_pm.charge_mode == CHRG_ON)
  509. sharpsl_pm.flags |= SHARPSL_DO_OFFLINE_CHRG;
  510. else
  511. sharpsl_pm.flags &= ~SHARPSL_DO_OFFLINE_CHRG;
  512. return 0;
  513. }
  514. static int sharpsl_pm_resume(struct platform_device *pdev)
  515. {
  516. /* Clear the reset source indicators as they break the bootloader upon reboot */
  517. RCSR = 0x0f;
  518. sharpsl_average_clear();
  519. sharpsl_pm.flags &= ~SHARPSL_APM_QUEUED;
  520. sharpsl_pm.flags &= ~SHARPSL_SUSPENDED;
  521. return 0;
  522. }
  523. static void corgi_goto_sleep(unsigned long alarm_time, unsigned int alarm_enable, suspend_state_t state)
  524. {
  525. dev_dbg(sharpsl_pm.dev, "Time is: %08x\n", RCNR);
  526. dev_dbg(sharpsl_pm.dev, "Offline Charge Activate = %d\n", sharpsl_pm.flags & SHARPSL_DO_OFFLINE_CHRG);
  527. /* not charging and AC-IN! */
  528. if ((sharpsl_pm.flags & SHARPSL_DO_OFFLINE_CHRG) && (sharpsl_pm.machinfo->read_devdata(SHARPSL_STATUS_ACIN))) {
  529. dev_dbg(sharpsl_pm.dev, "Activating Offline Charger...\n");
  530. sharpsl_pm.charge_mode = CHRG_OFF;
  531. sharpsl_pm.flags &= ~SHARPSL_DO_OFFLINE_CHRG;
  532. sharpsl_off_charge_battery();
  533. }
  534. sharpsl_pm.machinfo->presuspend();
  535. PEDR = 0xffffffff; /* clear it */
  536. sharpsl_pm.flags &= ~SHARPSL_ALARM_ACTIVE;
  537. if ((sharpsl_pm.charge_mode == CHRG_ON) && ((alarm_enable && ((alarm_time - RCNR) > (SHARPSL_BATCHK_TIME_SUSPEND + 30))) || !alarm_enable)) {
  538. RTSR &= RTSR_ALE;
  539. RTAR = RCNR + SHARPSL_BATCHK_TIME_SUSPEND;
  540. dev_dbg(sharpsl_pm.dev, "Charging alarm at: %08x\n", RTAR);
  541. sharpsl_pm.flags |= SHARPSL_ALARM_ACTIVE;
  542. } else if (alarm_enable) {
  543. RTSR &= RTSR_ALE;
  544. RTAR = alarm_time;
  545. dev_dbg(sharpsl_pm.dev, "User alarm at: %08x\n", RTAR);
  546. } else {
  547. dev_dbg(sharpsl_pm.dev, "No alarms set.\n");
  548. }
  549. pxa_pm_enter(state);
  550. sharpsl_pm.machinfo->postsuspend();
  551. dev_dbg(sharpsl_pm.dev, "Corgi woken up from suspend: %08x\n", PEDR);
  552. }
  553. static int corgi_enter_suspend(unsigned long alarm_time, unsigned int alarm_enable, suspend_state_t state)
  554. {
  555. if (!sharpsl_pm.machinfo->should_wakeup(!(sharpsl_pm.flags & SHARPSL_ALARM_ACTIVE) && alarm_enable)) {
  556. if (!(sharpsl_pm.flags & SHARPSL_ALARM_ACTIVE)) {
  557. dev_dbg(sharpsl_pm.dev, "No user triggered wakeup events and not charging. Strange. Suspend.\n");
  558. corgi_goto_sleep(alarm_time, alarm_enable, state);
  559. return 1;
  560. }
  561. if (sharpsl_off_charge_battery()) {
  562. dev_dbg(sharpsl_pm.dev, "Charging. Suspend...\n");
  563. corgi_goto_sleep(alarm_time, alarm_enable, state);
  564. return 1;
  565. }
  566. dev_dbg(sharpsl_pm.dev, "User triggered wakeup in offline charger.\n");
  567. }
  568. if ((!sharpsl_pm.machinfo->read_devdata(SHARPSL_STATUS_LOCK)) ||
  569. (!sharpsl_pm.machinfo->read_devdata(SHARPSL_STATUS_FATAL))) {
  570. dev_err(sharpsl_pm.dev, "Fatal condition. Suspend.\n");
  571. corgi_goto_sleep(alarm_time, alarm_enable, state);
  572. return 1;
  573. }
  574. return 0;
  575. }
  576. static int corgi_pxa_pm_enter(suspend_state_t state)
  577. {
  578. unsigned long alarm_time = RTAR;
  579. unsigned int alarm_status = ((RTSR & RTSR_ALE) != 0);
  580. dev_dbg(sharpsl_pm.dev, "SharpSL suspending for first time.\n");
  581. corgi_goto_sleep(alarm_time, alarm_status, state);
  582. while (corgi_enter_suspend(alarm_time, alarm_status, state))
  583. {}
  584. if (sharpsl_pm.machinfo->earlyresume)
  585. sharpsl_pm.machinfo->earlyresume();
  586. dev_dbg(sharpsl_pm.dev, "SharpSL resuming...\n");
  587. return 0;
  588. }
  589. /*
  590. * Check for fatal battery errors
  591. * Fatal returns -1
  592. */
  593. static int sharpsl_fatal_check(void)
  594. {
  595. int buff[5], temp, i, acin;
  596. dev_dbg(sharpsl_pm.dev, "sharpsl_fatal_check entered\n");
  597. /* Check AC-Adapter */
  598. acin = sharpsl_pm.machinfo->read_devdata(SHARPSL_STATUS_ACIN);
  599. if (acin && (sharpsl_pm.charge_mode == CHRG_ON)) {
  600. sharpsl_pm.machinfo->charge(0);
  601. udelay(100);
  602. sharpsl_pm.machinfo->discharge(1); /* enable discharge */
  603. mdelay(SHARPSL_WAIT_DISCHARGE_ON);
  604. }
  605. if (sharpsl_pm.machinfo->discharge1)
  606. sharpsl_pm.machinfo->discharge1(1);
  607. /* Check battery : check inserting battery ? */
  608. for (i = 0; i < 5; i++) {
  609. buff[i] = sharpsl_pm.machinfo->read_devdata(SHARPSL_BATT_VOLT);
  610. mdelay(SHARPSL_CHECK_BATTERY_WAIT_TIME_VOLT);
  611. }
  612. if (sharpsl_pm.machinfo->discharge1)
  613. sharpsl_pm.machinfo->discharge1(0);
  614. if (acin && (sharpsl_pm.charge_mode == CHRG_ON)) {
  615. udelay(100);
  616. sharpsl_pm.machinfo->charge(1);
  617. sharpsl_pm.machinfo->discharge(0);
  618. }
  619. temp = get_select_val(buff);
  620. dev_dbg(sharpsl_pm.dev, "sharpsl_fatal_check: acin: %d, discharge voltage: %d, no discharge: %ld\n", acin, temp, sharpsl_pm.machinfo->read_devdata(SHARPSL_BATT_VOLT));
  621. if ((acin && (temp < sharpsl_pm.machinfo->fatal_acin_volt)) ||
  622. (!acin && (temp < sharpsl_pm.machinfo->fatal_noacin_volt)))
  623. return -1;
  624. return 0;
  625. }
  626. static int sharpsl_off_charge_error(void)
  627. {
  628. dev_err(sharpsl_pm.dev, "Offline Charger: Error occurred.\n");
  629. sharpsl_pm.machinfo->charge(0);
  630. sharpsl_pm_led(SHARPSL_LED_ERROR);
  631. sharpsl_pm.charge_mode = CHRG_ERROR;
  632. return 1;
  633. }
  634. /*
  635. * Charging Control while suspended
  636. * Return 1 - go straight to sleep
  637. * Return 0 - sleep or wakeup depending on other factors
  638. */
  639. static int sharpsl_off_charge_battery(void)
  640. {
  641. int time;
  642. dev_dbg(sharpsl_pm.dev, "Charge Mode: %d\n", sharpsl_pm.charge_mode);
  643. if (sharpsl_pm.charge_mode == CHRG_OFF) {
  644. dev_dbg(sharpsl_pm.dev, "Offline Charger: Step 1\n");
  645. /* AC Check */
  646. if ((sharpsl_ac_check() < 0) || (sharpsl_check_battery_temp() < 0))
  647. return sharpsl_off_charge_error();
  648. /* Start Charging */
  649. sharpsl_pm_led(SHARPSL_LED_ON);
  650. sharpsl_pm.machinfo->charge(0);
  651. mdelay(SHARPSL_CHARGE_WAIT_TIME);
  652. sharpsl_pm.machinfo->charge(1);
  653. sharpsl_pm.charge_mode = CHRG_ON;
  654. sharpsl_pm.full_count = 0;
  655. return 1;
  656. } else if (sharpsl_pm.charge_mode != CHRG_ON) {
  657. return 1;
  658. }
  659. if (sharpsl_pm.full_count == 0) {
  660. int time;
  661. dev_dbg(sharpsl_pm.dev, "Offline Charger: Step 2\n");
  662. if ((sharpsl_check_battery_temp() < 0) || (sharpsl_check_battery_voltage() < 0))
  663. return sharpsl_off_charge_error();
  664. sharpsl_pm.machinfo->charge(0);
  665. mdelay(SHARPSL_CHARGE_WAIT_TIME);
  666. sharpsl_pm.machinfo->charge(1);
  667. sharpsl_pm.charge_mode = CHRG_ON;
  668. mdelay(SHARPSL_CHARGE_CO_CHECK_TIME);
  669. time = RCNR;
  670. while (1) {
  671. /* Check if any wakeup event had occurred */
  672. if (sharpsl_pm.machinfo->charger_wakeup() != 0)
  673. return 0;
  674. /* Check for timeout */
  675. if ((RCNR - time) > SHARPSL_WAIT_CO_TIME)
  676. return 1;
  677. if (sharpsl_pm.machinfo->read_devdata(SHARPSL_STATUS_CHRGFULL)) {
  678. dev_dbg(sharpsl_pm.dev, "Offline Charger: Charge full occurred. Retrying to check\n");
  679. sharpsl_pm.full_count++;
  680. sharpsl_pm.machinfo->charge(0);
  681. mdelay(SHARPSL_CHARGE_WAIT_TIME);
  682. sharpsl_pm.machinfo->charge(1);
  683. return 1;
  684. }
  685. }
  686. }
  687. dev_dbg(sharpsl_pm.dev, "Offline Charger: Step 3\n");
  688. mdelay(SHARPSL_CHARGE_CO_CHECK_TIME);
  689. time = RCNR;
  690. while (1) {
  691. /* Check if any wakeup event had occurred */
  692. if (sharpsl_pm.machinfo->charger_wakeup())
  693. return 0;
  694. /* Check for timeout */
  695. if ((RCNR-time) > SHARPSL_WAIT_CO_TIME) {
  696. if (sharpsl_pm.full_count > SHARPSL_CHARGE_RETRY_CNT) {
  697. dev_dbg(sharpsl_pm.dev, "Offline Charger: Not charged sufficiently. Retrying.\n");
  698. sharpsl_pm.full_count = 0;
  699. }
  700. sharpsl_pm.full_count++;
  701. return 1;
  702. }
  703. if (sharpsl_pm.machinfo->read_devdata(SHARPSL_STATUS_CHRGFULL)) {
  704. dev_dbg(sharpsl_pm.dev, "Offline Charger: Charging complete.\n");
  705. sharpsl_pm_led(SHARPSL_LED_OFF);
  706. sharpsl_pm.machinfo->charge(0);
  707. sharpsl_pm.charge_mode = CHRG_DONE;
  708. return 1;
  709. }
  710. }
  711. }
  712. #else
  713. #define sharpsl_pm_suspend NULL
  714. #define sharpsl_pm_resume NULL
  715. #endif
  716. static ssize_t battery_percentage_show(struct device *dev, struct device_attribute *attr, char *buf)
  717. {
  718. return sprintf(buf, "%d\n", sharpsl_pm.battstat.mainbat_percent);
  719. }
  720. static ssize_t battery_voltage_show(struct device *dev, struct device_attribute *attr, char *buf)
  721. {
  722. return sprintf(buf, "%d\n", sharpsl_pm.battstat.mainbat_voltage);
  723. }
  724. static DEVICE_ATTR(battery_percentage, 0444, battery_percentage_show, NULL);
  725. static DEVICE_ATTR(battery_voltage, 0444, battery_voltage_show, NULL);
  726. extern void (*apm_get_power_status)(struct apm_power_info *);
  727. static void sharpsl_apm_get_power_status(struct apm_power_info *info)
  728. {
  729. info->ac_line_status = sharpsl_pm.battstat.ac_status;
  730. if (sharpsl_pm.charge_mode == CHRG_ON)
  731. info->battery_status = APM_BATTERY_STATUS_CHARGING;
  732. else
  733. info->battery_status = sharpsl_pm.battstat.mainbat_status;
  734. info->battery_flag = (1 << info->battery_status);
  735. info->battery_life = sharpsl_pm.battstat.mainbat_percent;
  736. }
  737. #ifdef CONFIG_PM
  738. static struct platform_suspend_ops sharpsl_pm_ops = {
  739. .prepare = pxa_pm_prepare,
  740. .finish = pxa_pm_finish,
  741. .enter = corgi_pxa_pm_enter,
  742. .valid = suspend_valid_only_mem,
  743. };
  744. #endif
  745. static int __devinit sharpsl_pm_probe(struct platform_device *pdev)
  746. {
  747. int ret;
  748. if (!pdev->dev.platform_data)
  749. return -EINVAL;
  750. sharpsl_pm.dev = &pdev->dev;
  751. sharpsl_pm.machinfo = pdev->dev.platform_data;
  752. sharpsl_pm.charge_mode = CHRG_OFF;
  753. sharpsl_pm.flags = 0;
  754. init_timer(&sharpsl_pm.ac_timer);
  755. sharpsl_pm.ac_timer.function = sharpsl_ac_timer;
  756. init_timer(&sharpsl_pm.chrg_full_timer);
  757. sharpsl_pm.chrg_full_timer.function = sharpsl_chrg_full_timer;
  758. led_trigger_register_simple("sharpsl-charge", &sharpsl_charge_led_trigger);
  759. sharpsl_pm.machinfo->init();
  760. gpio_request(sharpsl_pm.machinfo->gpio_acin, "AC IN");
  761. gpio_direction_input(sharpsl_pm.machinfo->gpio_acin);
  762. gpio_request(sharpsl_pm.machinfo->gpio_batfull, "Battery Full");
  763. gpio_direction_input(sharpsl_pm.machinfo->gpio_batfull);
  764. gpio_request(sharpsl_pm.machinfo->gpio_batlock, "Battery Lock");
  765. gpio_direction_input(sharpsl_pm.machinfo->gpio_batlock);
  766. /* Register interrupt handlers */
  767. if (request_irq(IRQ_GPIO(sharpsl_pm.machinfo->gpio_acin), sharpsl_ac_isr, IRQF_DISABLED | IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, "AC Input Detect", sharpsl_ac_isr)) {
  768. dev_err(sharpsl_pm.dev, "Could not get irq %d.\n", IRQ_GPIO(sharpsl_pm.machinfo->gpio_acin));
  769. }
  770. if (request_irq(IRQ_GPIO(sharpsl_pm.machinfo->gpio_batlock), sharpsl_fatal_isr, IRQF_DISABLED | IRQF_TRIGGER_FALLING, "Battery Cover", sharpsl_fatal_isr)) {
  771. dev_err(sharpsl_pm.dev, "Could not get irq %d.\n", IRQ_GPIO(sharpsl_pm.machinfo->gpio_batlock));
  772. }
  773. if (sharpsl_pm.machinfo->gpio_fatal) {
  774. if (request_irq(IRQ_GPIO(sharpsl_pm.machinfo->gpio_fatal), sharpsl_fatal_isr, IRQF_DISABLED | IRQF_TRIGGER_FALLING, "Fatal Battery", sharpsl_fatal_isr)) {
  775. dev_err(sharpsl_pm.dev, "Could not get irq %d.\n", IRQ_GPIO(sharpsl_pm.machinfo->gpio_fatal));
  776. }
  777. }
  778. if (sharpsl_pm.machinfo->batfull_irq) {
  779. /* Register interrupt handler. */
  780. if (request_irq(IRQ_GPIO(sharpsl_pm.machinfo->gpio_batfull), sharpsl_chrg_full_isr, IRQF_DISABLED | IRQF_TRIGGER_RISING, "CO", sharpsl_chrg_full_isr)) {
  781. dev_err(sharpsl_pm.dev, "Could not get irq %d.\n", IRQ_GPIO(sharpsl_pm.machinfo->gpio_batfull));
  782. }
  783. }
  784. ret = device_create_file(&pdev->dev, &dev_attr_battery_percentage);
  785. ret |= device_create_file(&pdev->dev, &dev_attr_battery_voltage);
  786. if (ret != 0)
  787. dev_warn(&pdev->dev, "Failed to register attributes (%d)\n", ret);
  788. apm_get_power_status = sharpsl_apm_get_power_status;
  789. #ifdef CONFIG_PM
  790. suspend_set_ops(&sharpsl_pm_ops);
  791. #endif
  792. mod_timer(&sharpsl_pm.ac_timer, jiffies + msecs_to_jiffies(250));
  793. return 0;
  794. }
  795. static int sharpsl_pm_remove(struct platform_device *pdev)
  796. {
  797. suspend_set_ops(NULL);
  798. device_remove_file(&pdev->dev, &dev_attr_battery_percentage);
  799. device_remove_file(&pdev->dev, &dev_attr_battery_voltage);
  800. led_trigger_unregister_simple(sharpsl_charge_led_trigger);
  801. free_irq(IRQ_GPIO(sharpsl_pm.machinfo->gpio_acin), sharpsl_ac_isr);
  802. free_irq(IRQ_GPIO(sharpsl_pm.machinfo->gpio_batlock), sharpsl_fatal_isr);
  803. if (sharpsl_pm.machinfo->gpio_fatal)
  804. free_irq(IRQ_GPIO(sharpsl_pm.machinfo->gpio_fatal), sharpsl_fatal_isr);
  805. if (sharpsl_pm.machinfo->batfull_irq)
  806. free_irq(IRQ_GPIO(sharpsl_pm.machinfo->gpio_batfull), sharpsl_chrg_full_isr);
  807. gpio_free(sharpsl_pm.machinfo->gpio_batlock);
  808. gpio_free(sharpsl_pm.machinfo->gpio_batfull);
  809. gpio_free(sharpsl_pm.machinfo->gpio_acin);
  810. if (sharpsl_pm.machinfo->exit)
  811. sharpsl_pm.machinfo->exit();
  812. del_timer_sync(&sharpsl_pm.chrg_full_timer);
  813. del_timer_sync(&sharpsl_pm.ac_timer);
  814. return 0;
  815. }
  816. static struct platform_driver sharpsl_pm_driver = {
  817. .probe = sharpsl_pm_probe,
  818. .remove = sharpsl_pm_remove,
  819. .suspend = sharpsl_pm_suspend,
  820. .resume = sharpsl_pm_resume,
  821. .driver = {
  822. .name = "sharpsl-pm",
  823. },
  824. };
  825. static int __devinit sharpsl_pm_init(void)
  826. {
  827. return platform_driver_register(&sharpsl_pm_driver);
  828. }
  829. static void sharpsl_pm_exit(void)
  830. {
  831. platform_driver_unregister(&sharpsl_pm_driver);
  832. }
  833. late_initcall(sharpsl_pm_init);
  834. module_exit(sharpsl_pm_exit);