bq24022.c 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  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 platform_device *pdev = rdev_get_drvdata(rdev);
  23. struct bq24022_mach_info *pdata = pdev->dev.platform_data;
  24. dev_dbg(&pdev->dev, "setting current limit to %s mA\n",
  25. max_uA >= 500000 ? "500" : "100");
  26. /* REVISIT: maybe return error if min_uA != 0 ? */
  27. gpio_set_value(pdata->gpio_iset2, max_uA >= 500000);
  28. return 0;
  29. }
  30. static int bq24022_get_current_limit(struct regulator_dev *rdev)
  31. {
  32. struct platform_device *pdev = rdev_get_drvdata(rdev);
  33. struct bq24022_mach_info *pdata = pdev->dev.platform_data;
  34. return gpio_get_value(pdata->gpio_iset2) ? 500000 : 100000;
  35. }
  36. static int bq24022_enable(struct regulator_dev *rdev)
  37. {
  38. struct platform_device *pdev = rdev_get_drvdata(rdev);
  39. struct bq24022_mach_info *pdata = pdev->dev.platform_data;
  40. dev_dbg(&pdev->dev, "enabling charger\n");
  41. gpio_set_value(pdata->gpio_nce, 0);
  42. return 0;
  43. }
  44. static int bq24022_disable(struct regulator_dev *rdev)
  45. {
  46. struct platform_device *pdev = rdev_get_drvdata(rdev);
  47. struct bq24022_mach_info *pdata = pdev->dev.platform_data;
  48. dev_dbg(&pdev->dev, "disabling charger\n");
  49. gpio_set_value(pdata->gpio_nce, 1);
  50. return 0;
  51. }
  52. static int bq24022_is_enabled(struct regulator_dev *rdev)
  53. {
  54. struct platform_device *pdev = rdev_get_drvdata(rdev);
  55. struct bq24022_mach_info *pdata = pdev->dev.platform_data;
  56. return !gpio_get_value(pdata->gpio_nce);
  57. }
  58. static struct regulator_ops bq24022_ops = {
  59. .set_current_limit = bq24022_set_current_limit,
  60. .get_current_limit = bq24022_get_current_limit,
  61. .enable = bq24022_enable,
  62. .disable = bq24022_disable,
  63. .is_enabled = bq24022_is_enabled,
  64. };
  65. static struct regulator_desc bq24022_desc = {
  66. .name = "bq24022",
  67. .ops = &bq24022_ops,
  68. .type = REGULATOR_CURRENT,
  69. };
  70. static int __init bq24022_probe(struct platform_device *pdev)
  71. {
  72. struct bq24022_mach_info *pdata = pdev->dev.platform_data;
  73. struct regulator_dev *bq24022;
  74. int ret;
  75. if (!pdata || !pdata->gpio_nce || !pdata->gpio_iset2)
  76. return -EINVAL;
  77. ret = gpio_request(pdata->gpio_nce, "ncharge_en");
  78. if (ret) {
  79. dev_dbg(&pdev->dev, "couldn't request nCE GPIO: %d\n",
  80. pdata->gpio_nce);
  81. goto err_ce;
  82. }
  83. ret = gpio_request(pdata->gpio_iset2, "charge_mode");
  84. if (ret) {
  85. dev_dbg(&pdev->dev, "couldn't request ISET2 GPIO: %d\n",
  86. pdata->gpio_iset2);
  87. goto err_iset2;
  88. }
  89. ret = gpio_direction_output(pdata->gpio_iset2, 0);
  90. ret = gpio_direction_output(pdata->gpio_nce, 1);
  91. bq24022 = regulator_register(&bq24022_desc, pdev);
  92. if (IS_ERR(bq24022)) {
  93. dev_dbg(&pdev->dev, "couldn't register regulator\n");
  94. ret = PTR_ERR(bq24022);
  95. goto err_reg;
  96. }
  97. platform_set_drvdata(pdev, bq24022);
  98. dev_dbg(&pdev->dev, "registered regulator\n");
  99. return 0;
  100. err_reg:
  101. gpio_free(pdata->gpio_iset2);
  102. err_iset2:
  103. gpio_free(pdata->gpio_nce);
  104. err_ce:
  105. return ret;
  106. }
  107. static int __devexit bq24022_remove(struct platform_device *pdev)
  108. {
  109. struct bq24022_mach_info *pdata = pdev->dev.platform_data;
  110. struct regulator_dev *bq24022 = platform_get_drvdata(pdev);
  111. regulator_unregister(bq24022);
  112. gpio_free(pdata->gpio_iset2);
  113. gpio_free(pdata->gpio_nce);
  114. return 0;
  115. }
  116. static struct platform_driver bq24022_driver = {
  117. .driver = {
  118. .name = "bq24022",
  119. },
  120. .remove = __devexit_p(bq24022_remove),
  121. };
  122. static int __init bq24022_init(void)
  123. {
  124. return platform_driver_probe(&bq24022_driver, bq24022_probe);
  125. }
  126. static void __exit bq24022_exit(void)
  127. {
  128. platform_driver_unregister(&bq24022_driver);
  129. }
  130. /*
  131. * make sure this is probed before gpio_vbus and pda_power,
  132. * but after asic3 or other GPIO expander drivers.
  133. */
  134. subsys_initcall(bq24022_init);
  135. module_exit(bq24022_exit);
  136. MODULE_AUTHOR("Philipp Zabel");
  137. MODULE_DESCRIPTION("TI bq24022 Li-Ion Charger driver");
  138. MODULE_LICENSE("GPL");