bq24022.c 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  1. /*
  2. * Support for TI bq24022 (bqTINY-II) Dual Input (USB/AC Adpater)
  3. * 1-Cell Li-Ion Charger connected via GPIOs.
  4. *
  5. * Copyright (c) 2008 Philipp Zabel
  6. *
  7. * This program is free software; you can redistribute it and/or modify
  8. * it under the terms of the GNU General Public License version 2 as
  9. * published by the Free Software Foundation.
  10. *
  11. */
  12. #include <linux/kernel.h>
  13. #include <linux/init.h>
  14. #include <linux/platform_device.h>
  15. #include <linux/err.h>
  16. #include <linux/gpio.h>
  17. #include <linux/regulator/bq24022.h>
  18. #include <linux/regulator/driver.h>
  19. static int bq24022_set_current_limit(struct regulator_dev *rdev,
  20. int min_uA, int max_uA)
  21. {
  22. struct bq24022_mach_info *pdata = rdev_get_drvdata(rdev);
  23. dev_dbg(rdev_get_dev(rdev), "setting current limit to %s mA\n",
  24. max_uA >= 500000 ? "500" : "100");
  25. /* REVISIT: maybe return error if min_uA != 0 ? */
  26. gpio_set_value(pdata->gpio_iset2, max_uA >= 500000);
  27. return 0;
  28. }
  29. static int bq24022_get_current_limit(struct regulator_dev *rdev)
  30. {
  31. struct bq24022_mach_info *pdata = rdev_get_drvdata(rdev);
  32. return gpio_get_value(pdata->gpio_iset2) ? 500000 : 100000;
  33. }
  34. static int bq24022_enable(struct regulator_dev *rdev)
  35. {
  36. struct bq24022_mach_info *pdata = rdev_get_drvdata(rdev);
  37. dev_dbg(rdev_get_dev(rdev), "enabling charger\n");
  38. gpio_set_value(pdata->gpio_nce, 0);
  39. return 0;
  40. }
  41. static int bq24022_disable(struct regulator_dev *rdev)
  42. {
  43. struct bq24022_mach_info *pdata = rdev_get_drvdata(rdev);
  44. dev_dbg(rdev_get_dev(rdev), "disabling charger\n");
  45. gpio_set_value(pdata->gpio_nce, 1);
  46. return 0;
  47. }
  48. static int bq24022_is_enabled(struct regulator_dev *rdev)
  49. {
  50. struct platform_device *pdev = rdev_get_drvdata(rdev);
  51. struct bq24022_mach_info *pdata = pdev->dev.platform_data;
  52. return !gpio_get_value(pdata->gpio_nce);
  53. }
  54. static struct regulator_ops bq24022_ops = {
  55. .set_current_limit = bq24022_set_current_limit,
  56. .get_current_limit = bq24022_get_current_limit,
  57. .enable = bq24022_enable,
  58. .disable = bq24022_disable,
  59. .is_enabled = bq24022_is_enabled,
  60. };
  61. static struct regulator_desc bq24022_desc = {
  62. .name = "bq24022",
  63. .ops = &bq24022_ops,
  64. .type = REGULATOR_CURRENT,
  65. };
  66. static int __init bq24022_probe(struct platform_device *pdev)
  67. {
  68. struct bq24022_mach_info *pdata = pdev->dev.platform_data;
  69. struct regulator_dev *bq24022;
  70. int ret;
  71. if (!pdata || !pdata->gpio_nce || !pdata->gpio_iset2)
  72. return -EINVAL;
  73. ret = gpio_request(pdata->gpio_nce, "ncharge_en");
  74. if (ret) {
  75. dev_dbg(&pdev->dev, "couldn't request nCE GPIO: %d\n",
  76. pdata->gpio_nce);
  77. goto err_ce;
  78. }
  79. ret = gpio_request(pdata->gpio_iset2, "charge_mode");
  80. if (ret) {
  81. dev_dbg(&pdev->dev, "couldn't request ISET2 GPIO: %d\n",
  82. pdata->gpio_iset2);
  83. goto err_iset2;
  84. }
  85. ret = gpio_direction_output(pdata->gpio_iset2, 0);
  86. ret = gpio_direction_output(pdata->gpio_nce, 1);
  87. bq24022 = regulator_register(&bq24022_desc, &pdev->dev, pdata);
  88. if (IS_ERR(bq24022)) {
  89. dev_dbg(&pdev->dev, "couldn't register regulator\n");
  90. ret = PTR_ERR(bq24022);
  91. goto err_reg;
  92. }
  93. platform_set_drvdata(pdev, bq24022);
  94. dev_dbg(&pdev->dev, "registered regulator\n");
  95. return 0;
  96. err_reg:
  97. gpio_free(pdata->gpio_iset2);
  98. err_iset2:
  99. gpio_free(pdata->gpio_nce);
  100. err_ce:
  101. return ret;
  102. }
  103. static int __devexit bq24022_remove(struct platform_device *pdev)
  104. {
  105. struct bq24022_mach_info *pdata = pdev->dev.platform_data;
  106. struct regulator_dev *bq24022 = platform_get_drvdata(pdev);
  107. regulator_unregister(bq24022);
  108. gpio_free(pdata->gpio_iset2);
  109. gpio_free(pdata->gpio_nce);
  110. return 0;
  111. }
  112. static struct platform_driver bq24022_driver = {
  113. .driver = {
  114. .name = "bq24022",
  115. },
  116. .remove = __devexit_p(bq24022_remove),
  117. };
  118. static int __init bq24022_init(void)
  119. {
  120. return platform_driver_probe(&bq24022_driver, bq24022_probe);
  121. }
  122. static void __exit bq24022_exit(void)
  123. {
  124. platform_driver_unregister(&bq24022_driver);
  125. }
  126. /*
  127. * make sure this is probed before gpio_vbus and pda_power,
  128. * but after asic3 or other GPIO expander drivers.
  129. */
  130. subsys_initcall(bq24022_init);
  131. module_exit(bq24022_exit);
  132. MODULE_AUTHOR("Philipp Zabel");
  133. MODULE_DESCRIPTION("TI bq24022 Li-Ion Charger driver");
  134. MODULE_LICENSE("GPL");