linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v2] power: bq24617: Adding initial charger support
@ 2010-10-21  0:56 rklein
  2010-10-21 12:20 ` Lars-Peter Clausen
  0 siblings, 1 reply; 25+ messages in thread
From: rklein @ 2010-10-21  0:56 UTC (permalink / raw)
  To: broonie, cbouatmailru; +Cc: achew, olof, linux-kernel, Rhyland Klein

From: Rhyland Klein <rklein@nvidia.com>

Initial checkin adding basic support for the TI BQ24617 battery charger where
the PG output is directed to the driver via a gpio. This gpio address needs to
be passed in the platform data to the driver.

Signed-off-by: Rhyland Klein <rklein@nvidia.com>
---
Addressed comments by Mark Brown
  * Removed dependency on TEGRA, changed to GPIO
  * now using power_supply_changed()
  * now using request_threaded_irq()

 drivers/power/Kconfig   |    7 ++
 drivers/power/Makefile  |    1 +
 drivers/power/bq24617.c |  262 +++++++++++++++++++++++++++++++++++++++++++++++
 include/linux/bq24617.h |   10 ++
 4 files changed, 280 insertions(+), 0 deletions(-)
 create mode 100644 drivers/power/bq24617.c
 create mode 100644 include/linux/bq24617.h

diff --git a/drivers/power/Kconfig b/drivers/power/Kconfig
index 60d83d9..1901ccf 100644
--- a/drivers/power/Kconfig
+++ b/drivers/power/Kconfig
@@ -185,4 +185,11 @@ config CHARGER_TWL4030
 	help
 	  Say Y here to enable support for TWL4030 Battery Charge Interface.
 
+config CHARGER_BQ24617
+	tristate "BQ24617 battery charger"
+	depends on I2C && GENERIC_GPIO
+	help
+	 Say Y to include support for the TI BQ24617 battery charger where PG
+	 is attached to a gpio.
+
 endif # POWER_SUPPLY
diff --git a/drivers/power/Makefile b/drivers/power/Makefile
index c75772e..45cd557 100644
--- a/drivers/power/Makefile
+++ b/drivers/power/Makefile
@@ -32,3 +32,4 @@ obj-$(CONFIG_BATTERY_JZ4740)	+= jz4740-battery.o
 obj-$(CONFIG_BATTERY_INTEL_MID)	+= intel_mid_battery.o
 obj-$(CONFIG_CHARGER_ISP1704)	+= isp1704_charger.o
 obj-$(CONFIG_CHARGER_TWL4030)	+= twl4030_charger.o
+obj-$(CONFIG_CHARGER_BQ24617)	+= bq24617.o
diff --git a/drivers/power/bq24617.c b/drivers/power/bq24617.c
new file mode 100644
index 0000000..64500e6
--- /dev/null
+++ b/drivers/power/bq24617.c
@@ -0,0 +1,262 @@
+/*
+ * Charger driver for TI's BQ24617
+ *
+ * Copyright (c) 2010, NVIDIA Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/err.h>
+#include <linux/power_supply.h>
+#include <linux/slab.h>
+#include <linux/gpio.h>
+#include <linux/bq24617.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/irq.h>
+
+struct bq24617_info {
+	struct power_supply		power_supply;
+	struct bq24617_platform_data	*pdata;
+	struct platform_device		*pdev;
+	struct mutex			work_lock;
+	struct work_struct		ac_work;
+	int				status;
+};
+
+static enum power_supply_property bq24617_properties[] = {
+	POWER_SUPPLY_PROP_ONLINE,
+};
+
+static void bq24617_batt_update(struct bq24617_info *chip)
+{
+	int old_status = chip->status;
+	int new_status = old_status;
+	struct bq24617_platform_data *pdata;
+	int gpio_value = 0;
+
+	pdata = chip->pdata;
+
+	mutex_lock(&chip->work_lock);
+
+	gpio_value = gpio_get_value(pdata->gpio_addr);
+
+	new_status = !gpio_value;
+	chip->status = new_status;
+
+	mutex_unlock(&chip->work_lock);
+
+	if (old_status != -1 &&
+		old_status != new_status) {
+		dev_dbg(&chip->pdev->dev,
+			"%s: %i -> %i\n", __func__, old_status,
+			new_status);
+		power_supply_changed(&chip->power_supply);
+	}
+
+}
+
+static irqreturn_t bq24617_irq_switch(int irq, void *devid)
+{
+	struct bq24617_info *chip = devid;
+
+	schedule_work(&chip->ac_work);
+
+	return IRQ_HANDLED;
+}
+
+static int bq24617_get_property(struct power_supply *psy,
+	enum power_supply_property psp,
+	union power_supply_propval *val)
+{
+	struct bq24617_info *chip = container_of(psy, struct bq24617_info,
+						power_supply);
+
+	switch (psp) {
+	case POWER_SUPPLY_PROP_ONLINE:
+		bq24617_batt_update(chip);
+		val->intval = chip->status;
+		break;
+	default:
+		dev_err(&chip->pdev->dev,
+			"%s: Unknown property requested.\n", __func__);
+		return -EINVAL;
+		break;
+	}
+	return 0;
+}
+
+static void bq24617_ac_work(struct work_struct *work)
+{
+	struct bq24617_info *chip;
+	chip = container_of(work, struct bq24617_info, ac_work);
+	bq24617_batt_update(chip);
+}
+
+static int bq24617_probe(struct platform_device *pdev)
+{
+	struct bq24617_info *chip;
+	struct bq24617_platform_data *pdata = pdev->dev.platform_data;
+	int rc;
+
+	if (!pdata) {
+		dev_err(&pdev->dev, "No platform data\n");
+		return -ENXIO;
+	}
+
+	if (!(gpio_is_valid(pdata->gpio_addr))) {
+		dev_err(&pdev->dev, "Gpio is not valid\n");
+		return -EINVAL;
+	}
+
+	chip = kzalloc(sizeof(struct bq24617_info), GFP_KERNEL);
+	if (!chip)
+		return -ENOMEM;
+
+	chip->pdata = pdata;
+	chip->pdev = pdev;
+	chip->power_supply.name = "ac";
+	chip->status = -1; /* set status to reflect unset */
+	chip->power_supply.type = POWER_SUPPLY_TYPE_MAINS;
+	chip->power_supply.properties = bq24617_properties;
+	chip->power_supply.num_properties = ARRAY_SIZE(bq24617_properties);
+	chip->power_supply.get_property = bq24617_get_property;
+	chip->power_supply.supplied_to = pdata->batteries;
+	chip->power_supply.num_supplicants = pdata->num_batteries;
+
+	mutex_init(&chip->work_lock);
+
+	platform_set_drvdata(pdev, chip);
+
+	rc = gpio_request(pdata->gpio_addr, "ac online");
+	if (rc) {
+		dev_err(&pdev->dev,
+			"%s: Failed to get gpio\n", __func__);
+		goto free_chip;
+	}
+
+	gpio_direction_input(pdata->gpio_addr);
+	if (rc) {
+		dev_err(&pdev->dev,
+			"%s: Failed to set gpio direction\n",
+			__func__);
+		goto release_gpio;
+	}
+
+	rc = request_threaded_irq (gpio_to_irq(pdata->gpio_addr),
+				NULL,
+				bq24617_irq_switch,
+				IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING,
+				"ac detect",
+				chip);
+
+	if (rc) {
+		dev_err(&pdev->dev,
+			"%s: Failed to request threaded IRQ\n", __func__);
+		goto release_gpio;
+	}
+
+	INIT_WORK(&chip->ac_work, bq24617_ac_work);
+
+	rc = power_supply_register(&pdev->dev, &chip->power_supply);
+	if (rc) {
+		dev_err(&pdev->dev,
+			"%s: Failed to register power supply\n", __func__);
+		goto free_irq;
+	}
+
+	dev_info(&pdev->dev,
+		"%s: battery charger ac device registered\n", pdev->name);
+
+	schedule_work(&chip->ac_work);
+
+	return 0;
+
+free_irq:
+	free_irq(gpio_to_irq(pdata->gpio_addr), chip);
+release_gpio:
+	gpio_free(pdata->gpio_addr);
+free_chip:
+	kfree(chip);
+	return rc;
+}
+
+static int bq24617_remove(struct platform_device *pdev)
+{
+	struct bq24617_info *chip = platform_get_drvdata(pdev);
+	struct bq24617_platform_data *pdata = chip->pdata;
+
+	flush_scheduled_work();
+
+	power_supply_unregister(&chip->power_supply);
+
+	free_irq(gpio_to_irq(pdata->gpio_addr), chip);
+	gpio_free(pdata->gpio_addr);
+	kfree(chip);
+
+	return 0;
+}
+
+#if CONFIG_PM
+static int bq24617_suspend(struct platform_device *pdev, pm_message_t state)
+{
+	flush_scheduled_work();
+
+	return 0;
+}
+
+static int bq24617_resume(struct platform_device *pdev)
+{
+	struct bq24617_info *chip = platform_get_drvdata(pdev);
+
+	schedule_work(&chip->ac_work);
+
+	return 0;
+}
+
+#else
+#define bq24617_suspend         NULL
+#define bq24617_resume          NULL
+#endif
+
+static struct platform_driver bq24617_driver = {
+	.driver = {
+		.name	= "bq24617",
+		.owner	= THIS_MODULE,
+	},
+	.probe		= bq24617_probe,
+	.remove		= __devexit_p(bq24617_remove),
+	.suspend	= bq24617_suspend,
+	.resume		= bq24617_resume,
+};
+
+static int __devinit bq24617_init(void)
+{
+	return platform_driver_register(&bq24617_driver);
+}
+module_init(bq24617_init);
+
+static void __devexit bq24617_exit(void)
+{
+	platform_driver_unregister(&bq24617_driver);
+}
+module_exit(bq24617_exit);
+
+MODULE_AUTHOR("Rhyland Klein <rklein@nvidia.com");
+MODULE_DESCRIPTION("BQ24617 battery charger driver");
+MODULE_LICENSE("GPL");
diff --git a/include/linux/bq24617.h b/include/linux/bq24617.h
new file mode 100644
index 0000000..4c58406
--- /dev/null
+++ b/include/linux/bq24617.h
@@ -0,0 +1,10 @@
+#ifndef _LINUX_BQ24617_H
+#define _LINUX_BQ24617_H
+
+struct bq24617_platform_data {
+	int	gpio_addr;
+	char	**batteries;
+	int	num_batteries;
+};
+
+#endif
-- 
1.7.0.4


^ permalink raw reply related	[flat|nested] 25+ messages in thread

end of thread, other threads:[~2010-11-18 14:42 UTC | newest]

Thread overview: 25+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2010-10-21  0:56 [PATCH v2] power: bq24617: Adding initial charger support rklein
2010-10-21 12:20 ` Lars-Peter Clausen
2010-10-21 12:25   ` [PATCH] POWER: Add gpio chager driver Lars-Peter Clausen
2010-10-21 12:43     ` Piotr Hosowicz
2010-10-21 14:53       ` Lars-Peter Clausen
2010-10-21 14:14     ` Anton Vorontsov
2010-10-21 14:52       ` Lars-Peter Clausen
2010-10-21 15:05         ` Anton Vorontsov
2010-10-21 17:22       ` Rhyland Klein
2010-10-21 15:55     ` [PATCH v2] POWER: Add gpio charger driver Lars-Peter Clausen
2010-10-21 16:00       ` Mark Brown
2010-10-21 16:16         ` Lars-Peter Clausen
2010-10-21 16:19           ` Mark Brown
2010-10-21 16:26       ` Anton Vorontsov
2010-10-21 17:47         ` Lars-Peter Clausen
2010-10-22 21:41           ` Rhyland Klein
2010-10-28 21:17           ` Rhyland Klein
2010-11-04 17:47             ` Anton Vorontsov
2010-11-11  0:53               ` Rhyland Klein
2010-11-11  1:33                 ` Lars-Peter Clausen
2010-11-11  1:46                   ` Rhyland Klein
2010-11-17  1:37                   ` Rhyland Klein
2010-11-18 14:05       ` Anton Vorontsov
2010-11-18 14:30         ` Lars-Peter Clausen
2010-11-18 14:42           ` Anton Vorontsov

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).