aml_power.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800
  1. /*
  2. * Common power driver for Amlogic Devices with one or two external
  3. * power supplies (AC/USB) connected to main and backup batteries,
  4. * and optional builtin charger.
  5. *
  6. * Copyright © 2010 Larson Jiang <larson.jiang@amlogic.com>
  7. *
  8. * This program is free software; you can redistribute it and/or modify
  9. * it under the terms of the GNU General Public License version 2 as
  10. * published by the Free Software Foundation.
  11. */
  12. #include <linux/module.h>
  13. #include <linux/platform_device.h>
  14. #include <linux/err.h>
  15. #include <linux/interrupt.h>
  16. #include <linux/power_supply.h>
  17. #include <linux/aml_power.h>
  18. #include <linux/regulator/consumer.h>
  19. #include <linux/timer.h>
  20. #include <linux/jiffies.h>
  21. #include <linux/usb/otg.h>
  22. #ifdef CONFIG_HAS_EARLYSUSPEND
  23. #include <linux/earlysuspend.h>
  24. static struct early_suspend power_early_suspend;
  25. #endif
  26. //#define AML_POWER_DBG
  27. #define BATTERY_ARROW_NUM 20
  28. static inline unsigned int get_irq_flags(struct resource *res)
  29. {
  30. unsigned int flags = IRQF_SAMPLE_RANDOM | IRQF_SHARED;
  31. flags |= res->flags & IRQF_TRIGGER_MASK;
  32. return flags;
  33. }
  34. static struct device *dev;
  35. static struct aml_power_pdata *pdata;
  36. static struct resource *ac_irq, *usb_irq;
  37. static struct timer_list charger_timer;
  38. static struct timer_list supply_timer;
  39. static struct timer_list polling_timer;
  40. static int polling;
  41. #ifdef CONFIG_USB_OTG_UTILS
  42. static struct otg_transceiver *transceiver;
  43. #endif
  44. static struct regulator *ac_draw;
  45. enum {
  46. AML_PSY_OFFLINE = 0,
  47. AML_PSY_ONLINE = 1,
  48. AML_PSY_TO_CHANGE,
  49. };
  50. static int new_ac_status = -1;
  51. static int new_usb_status = 0;
  52. static int ac_status = -1;
  53. static int usb_status = 0;
  54. static int battery_capacity = 100;
  55. static int new_battery_capacity = 100;
  56. static int battery_capacity_pos = -1;
  57. static int charge_status = -1;
  58. static int new_charge_status = -1;
  59. static int bat_debug = 0;
  60. static int aml_power_get_property(struct power_supply *psy,
  61. enum power_supply_property psp,
  62. union power_supply_propval *val)
  63. {
  64. //int capacty;
  65. switch (psp) {
  66. case POWER_SUPPLY_PROP_ONLINE:
  67. #ifdef AML_POWER_DBG
  68. printk(KERN_INFO "get POWER_SUPPLY_TYPE_MAINS\n");
  69. #endif
  70. if (psy->type == POWER_SUPPLY_TYPE_MAINS)
  71. val->intval = pdata->is_ac_online ?
  72. pdata->is_ac_online() : 0;
  73. else
  74. val->intval = pdata->is_usb_online ?
  75. pdata->is_usb_online() : 0;
  76. break;
  77. case POWER_SUPPLY_PROP_VOLTAGE_NOW:
  78. val->intval = pdata->get_bat_vol()*((3300000*3/2)/1024);
  79. #ifdef AML_POWER_DBG
  80. printk(KERN_INFO "curren voltage is :%dmV\n",val->intval);
  81. #endif
  82. break;
  83. case POWER_SUPPLY_PROP_STATUS:
  84. #ifdef AML_POWER_DBG
  85. printk(KERN_INFO "get POWER_SUPPLY_PROP_STATUS\n");
  86. #endif
  87. if((pdata->is_ac_online())
  88. || ((usb_status == AML_PSY_ONLINE)&&(pdata->is_support_usb_charging == 1)))
  89. {
  90. if(pdata->get_charge_status())
  91. val->intval = POWER_SUPPLY_STATUS_FULL;
  92. else
  93. val->intval = POWER_SUPPLY_STATUS_CHARGING;
  94. }
  95. else
  96. val->intval = POWER_SUPPLY_STATUS_DISCHARGING;
  97. break;
  98. case POWER_SUPPLY_PROP_CAPACITY:
  99. val->intval = new_battery_capacity;
  100. #ifdef AML_POWER_DBG
  101. printk(KERN_INFO "current capacity is %d%%\n,",val->intval);
  102. #endif
  103. break;
  104. case POWER_SUPPLY_PROP_HEALTH:
  105. val->intval = POWER_SUPPLY_HEALTH_GOOD;
  106. break;
  107. case POWER_SUPPLY_PROP_PRESENT:
  108. val->intval = 1;
  109. break;
  110. case POWER_SUPPLY_PROP_TECHNOLOGY:
  111. val->intval = POWER_SUPPLY_TECHNOLOGY_LION;
  112. break;
  113. default:
  114. return -EINVAL;
  115. }
  116. return 0;
  117. }
  118. static enum power_supply_property aml_power_props[] = {
  119. POWER_SUPPLY_PROP_ONLINE,
  120. };
  121. static enum power_supply_property aml_battery_props[] = {
  122. POWER_SUPPLY_PROP_STATUS,
  123. POWER_SUPPLY_PROP_HEALTH,
  124. POWER_SUPPLY_PROP_PRESENT,
  125. POWER_SUPPLY_PROP_TECHNOLOGY,
  126. POWER_SUPPLY_PROP_CAPACITY,
  127. POWER_SUPPLY_PROP_VOLTAGE_NOW,
  128. };
  129. static char *aml_power_supplied_to[] = {
  130. "main-battery",
  131. "backup-battery",
  132. };
  133. static struct power_supply aml_psy_ac = {
  134. .name = "ac",
  135. .type = POWER_SUPPLY_TYPE_MAINS,
  136. .supplied_to = aml_power_supplied_to,
  137. .num_supplicants = ARRAY_SIZE(aml_power_supplied_to),
  138. .properties = aml_power_props,
  139. .num_properties = ARRAY_SIZE(aml_power_props),
  140. .get_property = aml_power_get_property,
  141. };
  142. static struct power_supply aml_psy_usb = {
  143. .name = "usb",
  144. .type = POWER_SUPPLY_TYPE_USB,
  145. .supplied_to = aml_power_supplied_to,
  146. .num_supplicants = ARRAY_SIZE(aml_power_supplied_to),
  147. .properties = aml_power_props,
  148. .num_properties = ARRAY_SIZE(aml_power_props),
  149. .get_property = aml_power_get_property,
  150. };
  151. static struct power_supply aml_psy_bat = {
  152. .name = "battery",
  153. .type = POWER_SUPPLY_TYPE_BATTERY,
  154. .properties = aml_battery_props,
  155. .num_properties = ARRAY_SIZE(aml_battery_props),
  156. .get_property = aml_power_get_property,
  157. };
  158. static unsigned bat_matrix[BATTERY_ARROW_NUM] = {0};
  159. static int count = 0;
  160. static void get_bat_capacity(void)
  161. {
  162. int value,i,num,sum;
  163. int min,max;
  164. if(new_ac_status > 0)//dc pluged state
  165. value = pdata->get_bat_vol() - 12;
  166. else
  167. value = pdata->get_bat_vol();
  168. if(bat_debug) printk("get_bat_vol = %d\n",value);
  169. if(value == -1)
  170. return;
  171. bat_matrix[count] = value;
  172. count ++;
  173. if(count > (BATTERY_ARROW_NUM-1)){
  174. count = 0;
  175. }
  176. else if(battery_capacity_pos >=0){//battery_capacity_pos = -1,don't return for boot up read battery level
  177. return ;
  178. }
  179. sum = 0;
  180. num = 0;
  181. min = 0x3ff;
  182. max = 0;
  183. for(i = 0;i<=(BATTERY_ARROW_NUM-1);i++){
  184. if(bat_matrix[i]){
  185. sum += bat_matrix[i];
  186. num ++;
  187. if(max < bat_matrix[i])
  188. max = bat_matrix[i];
  189. if(min > bat_matrix[i])
  190. min = bat_matrix[i];
  191. }
  192. }
  193. if(num>4){
  194. sum = sum - max -min;
  195. num = num -2;
  196. }
  197. else{
  198. return;
  199. }
  200. value = sum/num;
  201. if(new_ac_status > 0){
  202. for(i=0; i<(pdata->bat_table_len -1); i++){
  203. if(((pdata->bat_charge_value_table)[i]<=value)&&((pdata->bat_charge_value_table)[i+1]>value))break;
  204. }
  205. }
  206. else{
  207. for(i=0; i<(pdata->bat_table_len -1); i++){
  208. if(((pdata->bat_value_table)[i]<=value)&&((pdata->bat_value_table)[i+1]>value))break;
  209. }
  210. }
  211. if(bat_debug) printk("AML_POWER_DBG i = %d,battery_capacity_pos = %d,(pdata->bat_level_table)[i] = %d,battery_capacity = %d\n",i,battery_capacity_pos,(pdata->bat_level_table)[i],battery_capacity);
  212. if(battery_capacity_pos >=0){
  213. if((battery_capacity_pos - i) >1){
  214. i = battery_capacity_pos - 1;
  215. }
  216. else if((i - battery_capacity_pos) >1){
  217. i = battery_capacity_pos + 1;
  218. }
  219. if(new_ac_status > 0){//ac plug state,don't report a bat level small than before
  220. if(battery_capacity <= (pdata->bat_level_table)[i]){
  221. new_battery_capacity = (pdata->bat_level_table)[i];
  222. battery_capacity_pos = i;
  223. }
  224. }
  225. if(new_ac_status == 0){//ac unplug state,don't report a bat level big than before
  226. if(battery_capacity >= (pdata->bat_level_table)[i]){
  227. new_battery_capacity = (pdata->bat_level_table)[i];
  228. battery_capacity_pos = i;
  229. }
  230. }
  231. if(bat_debug) printk("AML_POWER_DBG i = %d,battery_capacity_pos = %d\n",i,battery_capacity_pos);
  232. }
  233. else{
  234. new_battery_capacity = (pdata->bat_level_table)[i];
  235. battery_capacity_pos = i;
  236. }
  237. if(bat_debug) printk("battery_capacity = %d,max = %d,min = %d,sum = %d,num = %d,value = %d\n",new_battery_capacity,max,min,sum,num,value);
  238. }
  239. #ifdef CONFIG_HAS_EARLYSUSPEND
  240. static void aml_power_early_suspend(struct early_suspend *h)
  241. {
  242. if (pdata->set_charge) {
  243. pdata->set_charge(AML_POWER_CHARGE_AC);
  244. if(bat_debug) printk("fast charger on early_suspend\n\n");
  245. }
  246. }
  247. static void aml_power_late_resume(struct early_suspend *h)
  248. {
  249. int i;
  250. if (pdata->set_charge) {
  251. pdata->set_charge(0);
  252. if(bat_debug) printk("set slow charge\n");
  253. }
  254. //update real battery level
  255. battery_capacity_pos = -1;
  256. count = 0;
  257. for(i = 0;i <= (BATTERY_ARROW_NUM-1);i++){
  258. bat_matrix[i] = 0;
  259. }
  260. }
  261. #endif
  262. static void update_status(void)
  263. {
  264. int i;
  265. if (pdata->is_ac_online)
  266. new_ac_status = !!pdata->is_ac_online();
  267. if(new_ac_status != ac_status){//unplug&plug ac,clear matrix
  268. count = 0;
  269. for(i = 0;i <= (BATTERY_ARROW_NUM-1);i++){
  270. bat_matrix[i] = 0;
  271. }
  272. }
  273. //if (pdata->is_usb_online) //usb not use polling
  274. //new_usb_status = !!pdata->is_usb_online();
  275. if (pdata->get_charge_status&&pdata->is_ac_online){
  276. if(pdata->is_ac_online())
  277. {
  278. if(pdata->get_charge_status())
  279. new_charge_status = POWER_SUPPLY_STATUS_FULL;
  280. else
  281. new_charge_status = POWER_SUPPLY_STATUS_CHARGING;
  282. }
  283. else
  284. new_charge_status = POWER_SUPPLY_STATUS_DISCHARGING;
  285. }
  286. get_bat_capacity();
  287. }
  288. static void supply_timer_func(unsigned long unused)
  289. {
  290. if (ac_status == AML_PSY_TO_CHANGE) {
  291. if(new_ac_status) {
  292. if(pdata->ic_control)
  293. pdata->ic_control(1);
  294. }
  295. else {
  296. if(pdata->ic_control)
  297. pdata->ic_control(0);
  298. }
  299. ac_status = new_ac_status;
  300. power_supply_changed(&aml_psy_ac);
  301. }
  302. if (usb_status == AML_PSY_TO_CHANGE) {
  303. if(new_usb_status) {
  304. if(pdata->ic_control)
  305. pdata->ic_control(1);
  306. }
  307. else {
  308. if(pdata->ic_control)
  309. pdata->ic_control(0);
  310. }
  311. usb_status = new_usb_status;
  312. power_supply_changed(&aml_psy_usb);
  313. }
  314. if (charge_status == AML_PSY_TO_CHANGE) {
  315. charge_status = new_charge_status;
  316. power_supply_changed(&aml_psy_bat);
  317. }
  318. if (battery_capacity == AML_PSY_TO_CHANGE) {
  319. battery_capacity = new_battery_capacity;
  320. power_supply_changed(&aml_psy_bat);
  321. }
  322. }
  323. static void psy_changed(void)
  324. {
  325. /*
  326. * Okay, charger set. Now wait a bit before notifying supplicants,
  327. * charge power should stabilize.
  328. */
  329. //mcli
  330. if(supply_timer.function==NULL)
  331. return;
  332. if(pdata==NULL)
  333. {
  334. mod_timer(&supply_timer,jiffies + msecs_to_jiffies(500));
  335. return;
  336. }
  337. //mcli end
  338. mod_timer(&supply_timer,
  339. jiffies + msecs_to_jiffies(pdata->wait_for_charger));
  340. }
  341. static void charger_timer_func(unsigned long unused)
  342. {
  343. update_status();
  344. psy_changed();
  345. }
  346. static irqreturn_t power_changed_isr(int irq, void *power_supply)
  347. {
  348. if (power_supply == &aml_psy_ac)
  349. ac_status = AML_PSY_TO_CHANGE;
  350. else if (power_supply == &aml_psy_usb)
  351. usb_status = AML_PSY_TO_CHANGE;
  352. else
  353. return IRQ_NONE;
  354. /*
  355. * Wait a bit before reading ac/usb line status and setting charger,
  356. * because ac/usb status readings may lag from irq.
  357. */
  358. mod_timer(&charger_timer,
  359. jiffies + msecs_to_jiffies(pdata->wait_for_status));
  360. return IRQ_HANDLED;
  361. }
  362. static void polling_timer_func(unsigned long unused)
  363. {
  364. int changed = 0;
  365. dev_dbg(dev, "polling...\n");
  366. update_status();
  367. if (!ac_irq && new_ac_status != ac_status) {
  368. ac_status = AML_PSY_TO_CHANGE;
  369. changed = 1;
  370. }
  371. if (!usb_irq && new_usb_status != usb_status) {
  372. usb_status = AML_PSY_TO_CHANGE;
  373. changed = 1;
  374. }
  375. if (!ac_irq && charge_status != new_charge_status) {
  376. charge_status = AML_PSY_TO_CHANGE;
  377. changed = 1;
  378. }
  379. if(!ac_irq&&new_battery_capacity != battery_capacity){
  380. battery_capacity = AML_PSY_TO_CHANGE;
  381. changed = 1;
  382. }
  383. if (changed)
  384. psy_changed();
  385. mod_timer(&polling_timer,
  386. jiffies + msecs_to_jiffies(pdata->polling_interval));
  387. }
  388. #ifdef CONFIG_USB_OTG_UTILS
  389. static int otg_is_usb_online(void)
  390. {
  391. return (transceiver->state == OTG_STATE_B_PERIPHERAL);
  392. }
  393. #endif
  394. #ifdef CONFIG_USB_ANDROID
  395. int pc_connect(int status)
  396. {
  397. new_usb_status = status;
  398. if(new_usb_status == usb_status)
  399. return 1;
  400. usb_status = AML_PSY_TO_CHANGE;
  401. psy_changed();
  402. return 0;
  403. }
  404. static int gadget_is_usb_online(void)
  405. {
  406. return usb_status;
  407. }
  408. EXPORT_SYMBOL(pc_connect);
  409. #endif
  410. static ssize_t store_powerhold(struct class *class,
  411. struct class_attribute *attr, const char *buf, size_t count)
  412. {
  413. if(buf[0] == 'y'){
  414. if(bat_debug) printk("system off\n");
  415. if(pdata->set_bat_off)
  416. pdata->set_bat_off();
  417. }
  418. return count;
  419. }
  420. static ssize_t store_debug(struct class *class,
  421. struct class_attribute *attr, const char *buf, size_t count)
  422. {
  423. if(buf[0] == '1'){
  424. bat_debug = 1;
  425. }
  426. else{
  427. bat_debug = 0;
  428. }
  429. return count;
  430. }
  431. static ssize_t show_debug(struct class *class,
  432. struct class_attribute *attr, char *buf)
  433. {
  434. return sprintf(buf, "bat-debug value is %d\n", bat_debug);
  435. }
  436. static struct class_attribute powerhold_class_attrs[] = {
  437. __ATTR(bat-off, S_IRUGO | S_IWUSR, NULL, store_powerhold),
  438. __ATTR(bat-debug, S_IRUGO | S_IWUSR, show_debug, store_debug),
  439. __ATTR_NULL
  440. };
  441. static struct class powerhold_class = {
  442. .name = "powerhold",
  443. .class_attrs = powerhold_class_attrs,
  444. };
  445. static int aml_power_probe(struct platform_device *pdev)
  446. {
  447. int ret = 0;
  448. dev = &pdev->dev;
  449. if (pdev->id != -1) {
  450. dev_err(dev, "it's meaningless to register several "
  451. "pda_powers; use id = -1\n");
  452. ret = -EINVAL;
  453. goto wrongid;
  454. }
  455. pdata = pdev->dev.platform_data;
  456. if (pdata->init) {
  457. ret = pdata->init(dev);
  458. if (ret < 0)
  459. goto init_failed;
  460. }
  461. if(pdata->bat_value_table == NULL
  462. ||pdata->bat_charge_value_table == NULL
  463. ||pdata->bat_level_table == NULL
  464. ||pdata->bat_table_len <= 0
  465. ){
  466. goto init_failed;
  467. }
  468. update_status();
  469. if (!pdata->wait_for_status)
  470. pdata->wait_for_status = 500;
  471. if (!pdata->wait_for_charger)
  472. pdata->wait_for_charger = 500;
  473. if (!pdata->polling_interval)
  474. pdata->polling_interval = 2000;
  475. if (!pdata->ac_max_uA)
  476. pdata->ac_max_uA = 500000;
  477. setup_timer(&charger_timer, charger_timer_func, 0);
  478. setup_timer(&supply_timer, supply_timer_func, 0);
  479. ac_irq = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "ac");
  480. usb_irq = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "usb");
  481. if (pdata->supplied_to) {
  482. aml_psy_ac.supplied_to = pdata->supplied_to;
  483. aml_psy_ac.num_supplicants = pdata->num_supplicants;
  484. aml_psy_usb.supplied_to = pdata->supplied_to;
  485. aml_psy_usb.num_supplicants = pdata->num_supplicants;
  486. }
  487. ac_draw = regulator_get(dev, "ac_draw");
  488. if (IS_ERR(ac_draw)) {
  489. dev_dbg(dev, "couldn't get ac_draw regulator\n");
  490. ac_draw = NULL;
  491. ret = PTR_ERR(ac_draw);
  492. }
  493. if (pdata->is_ac_online) {
  494. ret = power_supply_register(&pdev->dev, &aml_psy_ac);
  495. if (ret) {
  496. dev_err(dev, "failed to register %s power supply\n",
  497. aml_psy_ac.name);
  498. goto ac_supply_failed;
  499. }
  500. if (ac_irq) {
  501. ret = request_irq(ac_irq->start, power_changed_isr,
  502. get_irq_flags(ac_irq), ac_irq->name,
  503. &aml_psy_ac);
  504. if (ret) {
  505. dev_err(dev, "request ac irq failed\n");
  506. goto ac_irq_failed;
  507. }
  508. } else {
  509. polling = 1;
  510. }
  511. }
  512. ret = class_register(&powerhold_class);
  513. if(ret){
  514. printk(" class register powerhold_class fail!\n");
  515. }
  516. #ifdef CONFIG_USB_OTG_UTILS
  517. transceiver = otg_get_transceiver();
  518. if (transceiver && !pdata->is_usb_online) {
  519. pdata->is_usb_online = otg_is_usb_online;
  520. }
  521. #endif
  522. #ifdef CONFIG_USB_ANDROID
  523. pdata->is_usb_online = gadget_is_usb_online;
  524. #endif
  525. if (pdata->is_usb_online) {
  526. ret = power_supply_register(&pdev->dev, &aml_psy_usb);
  527. if (ret) {
  528. dev_err(dev, "failed to register %s power supply\n",
  529. aml_psy_usb.name);
  530. goto usb_supply_failed;
  531. }
  532. if (usb_irq) {
  533. ret = request_irq(usb_irq->start, power_changed_isr,
  534. get_irq_flags(usb_irq),
  535. usb_irq->name, &aml_psy_usb);
  536. if (ret) {
  537. dev_err(dev, "request usb irq failed\n");
  538. goto usb_irq_failed;
  539. }
  540. } else {
  541. polling = 1;
  542. }
  543. }
  544. ret = power_supply_register(&pdev->dev, &aml_psy_bat);
  545. if (ret) {
  546. dev_err(dev, "failed to register battery\n");
  547. goto bat_supply_failed;
  548. }
  549. if (polling) {
  550. dev_dbg(dev, "will poll for status\n");
  551. setup_timer(&polling_timer, polling_timer_func, 0);
  552. mod_timer(&polling_timer,
  553. jiffies + msecs_to_jiffies(pdata->polling_interval));
  554. }
  555. if (ac_irq || usb_irq)
  556. device_init_wakeup(&pdev->dev, 1);
  557. #ifdef CONFIG_HAS_EARLYSUSPEND
  558. power_early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN;
  559. power_early_suspend.suspend = aml_power_early_suspend;
  560. power_early_suspend.resume = aml_power_late_resume;
  561. power_early_suspend.param = pdev;
  562. register_early_suspend(&power_early_suspend);
  563. #endif
  564. if (pdata->set_charge) {
  565. pdata->set_charge(0);
  566. }
  567. // //power off when low power
  568. // get_bat_capacity();
  569. // if (pdata->is_ac_online) {
  570. // if((new_battery_capacity <=4)&&(!pdata->is_ac_online())){
  571. // if(pdata->set_bat_off)
  572. // pdata->set_bat_off();
  573. // }
  574. // }
  575. return 0;
  576. bat_supply_failed:
  577. power_supply_unregister(&aml_psy_bat);
  578. usb_irq_failed:
  579. if (pdata->is_usb_online)
  580. power_supply_unregister(&aml_psy_usb);
  581. usb_supply_failed:
  582. if (pdata->is_ac_online && ac_irq)
  583. free_irq(ac_irq->start, &aml_psy_ac);
  584. #ifdef CONFIG_USB_OTG_UTILS
  585. if (transceiver)
  586. otg_put_transceiver(transceiver);
  587. #endif
  588. ac_irq_failed:
  589. if (pdata->is_ac_online)
  590. power_supply_unregister(&aml_psy_ac);
  591. ac_supply_failed:
  592. if (ac_draw) {
  593. regulator_put(ac_draw);
  594. ac_draw = NULL;
  595. }
  596. if (pdata->exit)
  597. pdata->exit(dev);
  598. init_failed:
  599. wrongid:
  600. return ret;
  601. }
  602. static int aml_power_remove(struct platform_device *pdev)
  603. {
  604. if (pdata->is_usb_online && usb_irq)
  605. free_irq(usb_irq->start, &aml_psy_usb);
  606. if (pdata->is_ac_online && ac_irq)
  607. free_irq(ac_irq->start, &aml_psy_ac);
  608. if (polling)
  609. del_timer_sync(&polling_timer);
  610. del_timer_sync(&charger_timer);
  611. del_timer_sync(&supply_timer);
  612. power_supply_unregister(&aml_psy_bat);
  613. if (pdata->is_usb_online)
  614. power_supply_unregister(&aml_psy_usb);
  615. if (pdata->is_ac_online)
  616. power_supply_unregister(&aml_psy_ac);
  617. #ifdef CONFIG_USB_OTG_UTILS
  618. if (transceiver)
  619. otg_put_transceiver(transceiver);
  620. #endif
  621. if (ac_draw) {
  622. regulator_put(ac_draw);
  623. ac_draw = NULL;
  624. }
  625. if (pdata->exit)
  626. pdata->exit(dev);
  627. #ifdef CONFIG_HAS_EARLYSUSPEND
  628. unregister_early_suspend(&power_early_suspend);
  629. #endif
  630. return 0;
  631. }
  632. #ifdef CONFIG_PM
  633. static int ac_wakeup_enabled;
  634. static int usb_wakeup_enabled;
  635. static int aml_power_suspend(struct platform_device *pdev, pm_message_t state)
  636. {
  637. if (device_may_wakeup(&pdev->dev)) {
  638. if (ac_irq)
  639. ac_wakeup_enabled = !enable_irq_wake(ac_irq->start);
  640. if (usb_irq)
  641. usb_wakeup_enabled = !enable_irq_wake(usb_irq->start);
  642. }
  643. return 0;
  644. }
  645. static int aml_power_resume(struct platform_device *pdev)
  646. {
  647. if (device_may_wakeup(&pdev->dev)) {
  648. if (usb_irq && usb_wakeup_enabled)
  649. disable_irq_wake(usb_irq->start);
  650. if (ac_irq && ac_wakeup_enabled)
  651. disable_irq_wake(ac_irq->start);
  652. }
  653. if(pdata->powerkey_led_onoff)
  654. pdata->powerkey_led_onoff(1);
  655. return 0;
  656. }
  657. #else
  658. #define aml_power_suspend NULL
  659. #define aml_power_resume NULL
  660. #endif /* CONFIG_PM */
  661. MODULE_ALIAS("platform:aml-power");
  662. static struct platform_driver aml_power_pdrv = {
  663. .driver = {
  664. .name = "aml-power",
  665. },
  666. .probe = aml_power_probe,
  667. .remove = aml_power_remove,
  668. .suspend = aml_power_suspend,
  669. .resume = aml_power_resume,
  670. };
  671. static int __init aml_power_init(void)
  672. {
  673. printk("amlogic power supply init\n");
  674. return platform_driver_register(&aml_power_pdrv);
  675. }
  676. static void __exit aml_power_exit(void)
  677. {
  678. platform_driver_unregister(&aml_power_pdrv);
  679. }
  680. module_init(aml_power_init);
  681. module_exit(aml_power_exit);
  682. MODULE_LICENSE("GPL");
  683. MODULE_AUTHOR("Larson Jiang");