* [PATCH 1/1] power: bq24617: Adding initial charger support
@ 2010-10-20 2:17 rklein
2010-10-20 3:02 ` Mark Brown
0 siblings, 1 reply; 5+ messages in thread
From: rklein @ 2010-10-20 2:17 UTC (permalink / raw)
To: cboutatmailru; +Cc: achew, olof, linux-tegra, linux-kernel, Rhyland Klein
From: Rhyland Klein <rklein@nvidia.com>
Initial checkin adding basic support for the TI BQ24617 battery charger on the
Nvidia Tegra architecture.
Signed-off-by: Rhyland Klein <rklein@nvidia.com>
---
drivers/power/Kconfig | 7 +
drivers/power/Makefile | 1 +
drivers/power/tegra_bq24617.c | 259 +++++++++++++++++++++++++++++++++++++++++
include/linux/tegra_bq24617.h | 10 ++
4 files changed, 277 insertions(+), 0 deletions(-)
create mode 100644 drivers/power/tegra_bq24617.c
create mode 100644 include/linux/tegra_bq24617.h
diff --git a/drivers/power/Kconfig b/drivers/power/Kconfig
index 60d83d9..cec4a63 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_TEGRA
+ tristate "BQ24617 Tegra battery charger"
+ depends on I2C && ARCH_TEGRA
+ help
+ Say Y to include support for the TI BQ24617 battery charger on
+ the Nvidia Tegra platform.
+
endif # POWER_SUPPLY
diff --git a/drivers/power/Makefile b/drivers/power/Makefile
index c75772e..95d8163 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_TEGRA) += tegra_bq24617.o
diff --git a/drivers/power/tegra_bq24617.c b/drivers/power/tegra_bq24617.c
new file mode 100644
index 0000000..02c8a76
--- /dev/null
+++ b/drivers/power/tegra_bq24617.c
@@ -0,0 +1,259 @@
+/*
+ * 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/tegra_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);
+ kobject_uevent(&chip->power_supply.dev->kobj, KOBJ_CHANGE);
+ }
+
+}
+
+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_irq(gpio_to_irq(pdata->gpio_addr),
+ bq24617_irq_switch,
+ IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING,
+ "ac detect", chip);
+ if (rc) {
+ dev_err(&pdev->dev,
+ "%s: Failed to request 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 = "tegra-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/tegra_bq24617.h b/include/linux/tegra_bq24617.h
new file mode 100644
index 0000000..4c58406
--- /dev/null
+++ b/include/linux/tegra_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 [flat|nested] 5+ messages in thread* Re: [PATCH 1/1] power: bq24617: Adding initial charger support
2010-10-20 2:17 [PATCH 1/1] power: bq24617: Adding initial charger support rklein
@ 2010-10-20 3:02 ` Mark Brown
2010-10-20 17:52 ` Rhyland Klein
2010-10-20 17:56 ` Rhyland Klein
0 siblings, 2 replies; 5+ messages in thread
From: Mark Brown @ 2010-10-20 3:02 UTC (permalink / raw)
To: rklein; +Cc: cboutatmailru, achew, olof, linux-tegra, linux-kernel
On Tue, Oct 19, 2010 at 07:17:11PM -0700, rklein@nvidia.com wrote:
> From: Rhyland Klein <rklein@nvidia.com>
>
> Initial checkin adding basic support for the TI BQ24617 battery charger on the
> Nvidia Tegra architecture.
Why is this driver dependant on the CPU? I can't see anything in the
code that makes it so.
> + if (old_status != -1 &&
> + old_status != new_status) {
> + dev_dbg(&chip->pdev->dev,
> + "%s: %i -> %i\n", __func__, old_status,
> + new_status);
> + kobject_uevent(&chip->power_supply.dev->kobj, KOBJ_CHANGE);
power_supply_changed().
> +static irqreturn_t bq24617_irq_switch(int irq, void *devid)
> +{
> + struct bq24617_info *chip = devid;
> +
> + schedule_work(&chip->ac_work);
> +
> + return IRQ_HANDLED;
> +}
You're looking for a threaded IRQ handler here - use
request_threaded_irq() with no primary handler.
^ permalink raw reply [flat|nested] 5+ messages in thread* RE: [PATCH 1/1] power: bq24617: Adding initial charger support
2010-10-20 3:02 ` Mark Brown
@ 2010-10-20 17:52 ` Rhyland Klein
2010-10-20 23:07 ` Rhyland Klein
2010-10-20 17:56 ` Rhyland Klein
1 sibling, 1 reply; 5+ messages in thread
From: Rhyland Klein @ 2010-10-20 17:52 UTC (permalink / raw)
To: Mark Brown; +Cc: cboutatmailru, Andrew Chew, olof, linux-tegra, linux-kernel
> From: Mark Brown [mailto:broonie@opensource.wolfsonmicro.com]
> Sent: Tuesday, October 19, 2010 8:03 PM
> To: Rhyland Klein
> Cc: cboutatmailru@gmail.com; Andrew Chew; olof@lixom.net; linux-
> tegra@vger.kernel.org; linux-kernel@vger.kernel.org
> Subject: Re: [PATCH 1/1] power: bq24617: Adding initial charger support
>
> On Tue, Oct 19, 2010 at 07:17:11PM -0700, rklein@nvidia.com wrote:
> > From: Rhyland Klein <rklein@nvidia.com>
> >
> > Initial checkin adding basic support for the TI BQ24617 battery charger
> on the
> > Nvidia Tegra architecture.
>
> Why is this driver dependant on the CPU? I can't see anything in the
> code that makes it so.
In hindsight this isn't the most accurate statement. The driver itself is not dependent on the CPU, it is dependent on the platform design, and in particular requires the PG line to be piped in through a GPIO. Would it make more sense to make the driver dependent on GPIO instead?
>
> > + if (old_status != -1 &&
> > + old_status != new_status) {
> > + dev_dbg(&chip->pdev->dev,
> > + "%s: %i -> %i\n", __func__, old_status,
> > + new_status);
> > + kobject_uevent(&chip->power_supply.dev->kobj, KOBJ_CHANGE);
>
> power_supply_changed().
Alright.
>
> > +static irqreturn_t bq24617_irq_switch(int irq, void *devid)
> > +{
> > + struct bq24617_info *chip = devid;
> > +
> > + schedule_work(&chip->ac_work);
> > +
> > + return IRQ_HANDLED;
> > +}
>
> You're looking for a threaded IRQ handler here - use
> request_threaded_irq() with no primary handler.
Alright I will look into this.
^ permalink raw reply [flat|nested] 5+ messages in thread* RE: [PATCH 1/1] power: bq24617: Adding initial charger support
2010-10-20 17:52 ` Rhyland Klein
@ 2010-10-20 23:07 ` Rhyland Klein
0 siblings, 0 replies; 5+ messages in thread
From: Rhyland Klein @ 2010-10-20 23:07 UTC (permalink / raw)
To: Rhyland Klein, Mark Brown
Cc: cboutatmailru, Andrew Chew, olof, linux-tegra, linux-kernel
> -----Original Message-----
> From: linux-kernel-owner@vger.kernel.org [mailto:linux-kernel-
> owner@vger.kernel.org] On Behalf Of Rhyland Klein
> Sent: Wednesday, October 20, 2010 10:52 AM
> To: Mark Brown
> Cc: cboutatmailru@gmail.com; Andrew Chew; olof@lixom.net; linux-
> tegra@vger.kernel.org; linux-kernel@vger.kernel.org
> Subject: RE: [PATCH 1/1] power: bq24617: Adding initial charger support
>
> > From: Mark Brown [mailto:broonie@opensource.wolfsonmicro.com]
> > Sent: Tuesday, October 19, 2010 8:03 PM
> > To: Rhyland Klein
> > Cc: cboutatmailru@gmail.com; Andrew Chew; olof@lixom.net; linux-
> > tegra@vger.kernel.org; linux-kernel@vger.kernel.org
> > Subject: Re: [PATCH 1/1] power: bq24617: Adding initial charger support
> >
> > On Tue, Oct 19, 2010 at 07:17:11PM -0700, rklein@nvidia.com wrote:
> > > From: Rhyland Klein <rklein@nvidia.com>
> > >
> > > Initial checkin adding basic support for the TI BQ24617 battery charger
> > on the
> > > Nvidia Tegra architecture.
> >
> > Why is this driver dependant on the CPU? I can't see anything in the
> > code that makes it so.
>
> In hindsight this isn't the most accurate statement. The driver itself is
> not dependent on the CPU, it is dependent on the platform design, and in
> particular requires the PG line to be piped in through a GPIO. Would it
> make more sense to make the driver dependent on GPIO instead?
>
Sorry for the confusion on this, I am removing the TEGRA dependency as it isn't necessary.
> >
> > > + if (old_status != -1 &&
> > > + old_status != new_status) {
> > > + dev_dbg(&chip->pdev->dev,
> > > + "%s: %i -> %i\n", __func__, old_status,
> > > + new_status);
> > > + kobject_uevent(&chip->power_supply.dev->kobj, KOBJ_CHANGE);
> >
> > power_supply_changed().
>
> Alright.
>
> >
> > > +static irqreturn_t bq24617_irq_switch(int irq, void *devid)
> > > +{
> > > + struct bq24617_info *chip = devid;
> > > +
> > > + schedule_work(&chip->ac_work);
> > > +
> > > + return IRQ_HANDLED;
> > > +}
> >
> > You're looking for a threaded IRQ handler here - use
> > request_threaded_irq() with no primary handler.
>
> Alright I will look into this.
> --
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at http://www.tux.org/lkml/
^ permalink raw reply [flat|nested] 5+ messages in thread
* RE: [PATCH 1/1] power: bq24617: Adding initial charger support
2010-10-20 3:02 ` Mark Brown
2010-10-20 17:52 ` Rhyland Klein
@ 2010-10-20 17:56 ` Rhyland Klein
1 sibling, 0 replies; 5+ messages in thread
From: Rhyland Klein @ 2010-10-20 17:56 UTC (permalink / raw)
To: Rhyland Klein, Mark Brown
Cc: cbouatmailru, Andrew Chew, olof, linux-tegra, linux-kernel
> -----Original Message-----
> From: Rhyland Klein
> Sent: Wednesday, October 20, 2010 10:52 AM
> To: 'Mark Brown'
> Cc: cboutatmailru@gmail.com; Andrew Chew; olof@lixom.net; linux-
> tegra@vger.kernel.org; linux-kernel@vger.kernel.org
> Subject: RE: [PATCH 1/1] power: bq24617: Adding initial charger support
>
> > From: Mark Brown [mailto:broonie@opensource.wolfsonmicro.com]
> > Sent: Tuesday, October 19, 2010 8:03 PM
> > To: Rhyland Klein
> > Cc: cboutatmailru@gmail.com; Andrew Chew; olof@lixom.net; linux-
> > tegra@vger.kernel.org; linux-kernel@vger.kernel.org
> > Subject: Re: [PATCH 1/1] power: bq24617: Adding initial charger support
> >
> > On Tue, Oct 19, 2010 at 07:17:11PM -0700, rklein@nvidia.com wrote:
> > > From: Rhyland Klein <rklein@nvidia.com>
> > >
> > > Initial checkin adding basic support for the TI BQ24617 battery charger
> > on the
> > > Nvidia Tegra architecture.
> >
> > Why is this driver dependant on the CPU? I can't see anything in the
> > code that makes it so.
>
> In hindsight this isn't the most accurate statement. The driver itself is
> not dependent on the CPU, it is dependent on the platform design, and in
> particular requires the PG line to be piped in through a GPIO. Would it
> make more sense to make the driver dependent on GPIO instead?
>
> >
> > > + if (old_status != -1 &&
> > > + old_status != new_status) {
> > > + dev_dbg(&chip->pdev->dev,
> > > + "%s: %i -> %i\n", __func__, old_status,
> > > + new_status);
> > > + kobject_uevent(&chip->power_supply.dev->kobj, KOBJ_CHANGE);
> >
> > power_supply_changed().
>
> Alright.
>
> >
> > > +static irqreturn_t bq24617_irq_switch(int irq, void *devid)
> > > +{
> > > + struct bq24617_info *chip = devid;
> > > +
> > > + schedule_work(&chip->ac_work);
> > > +
> > > + return IRQ_HANDLED;
> > > +}
> >
> > You're looking for a threaded IRQ handler here - use
> > request_threaded_irq() with no primary handler.
>
> Alright I will look into this.
Fixing Anton's email address here, I had a typo in it.
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2010-10-20 23:12 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2010-10-20 2:17 [PATCH 1/1] power: bq24617: Adding initial charger support rklein
2010-10-20 3:02 ` Mark Brown
2010-10-20 17:52 ` Rhyland Klein
2010-10-20 23:07 ` Rhyland Klein
2010-10-20 17:56 ` Rhyland Klein
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®