Re: [RESEND PATCH v3] charger: tps65090: Allow charger module to be used when no irq

2014-07-17 Thread Javier Martinez Canillas
Hello Doug,

On 06/20/2014 11:42 PM, Doug Anderson wrote:
 On the ARM Chromebook tps65090 has two masters: the AP (the main
 processor running linux) and the EC (the embedded controller).  The AP
 is allowed to mess with FETs but the EC is in charge of charge control.
 
 The tps65090 interupt line is routed to both the AP and the EC, which
 can cause quite a headache.  Having two people adjusting masks and
 acking interrupts is a recipe for disaster.
 
 In the shipping kernel we had a hack to have the AP pay attention to
 the IRQ but not to ack it.  It also wasn't supposed to configure the
 IRQ in any way.  That hack allowed us to detect when the device was
 charging without messing with the EC's state.
 
 The current tps65090 infrastructure makes the above difficult, and it
 was a bit of a hack to begin with.  Rather than uglify the driver to
 support it, just extend the driver's existing notion of no irq to
 the charger.  This makes the charger code poll every 2 seconds for AC
 detect, which is sufficient.
 
 For proper functioning, requires (mfd: tps65090: Don't tell child
 devices we have an IRQ if we don't).  If we don't have that patch
 we'll simply fail to probe on devices without an interrupt (just like
 we did before this patch).
 
 Signed-off-by: Doug Anderson diand...@chromium.org
 ---
 Changes in v2:
 - Split noirq (polling mode) changes into MFD and charger
 
 This patch has been sent up a number of times with no response.  It's
 needed to make the charger work on exynos5250-snow,
 exynos5420-peach-pit, and exynos5800-peach-pi.  It was originally part
 of a series as https://patchwork.kernel.org/patch/4042751/ and the
 rest of the series has long since landed.
 

Looks good to me. Also since this patch makes optional to get an IRQ, the
following annoying message is not shown anymore:

[2.132944] tps65090-charger tps65090-charger: Unable to get charger irq = -6

Reviewed-by: Javier Martinez Canillas javier.marti...@collabora.co.uk
Tested-by: Javier Martinez Canillas javier.marti...@collabora.co.uk
--
To unsubscribe from this list: send the line unsubscribe linux-samsung-soc in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [RESEND PATCH v3] charger: tps65090: Allow charger module to be used when no irq

2014-07-17 Thread Sebastian Reichel
Hi,

On Fri, Jun 20, 2014 at 02:42:03PM -0700, Doug Anderson wrote:
 On the ARM Chromebook tps65090 has two masters: the AP (the main
 processor running linux) and the EC (the embedded controller).  The AP
 is allowed to mess with FETs but the EC is in charge of charge control.
 
 The tps65090 interupt line is routed to both the AP and the EC, which
 can cause quite a headache.  Having two people adjusting masks and
 acking interrupts is a recipe for disaster.
 
 In the shipping kernel we had a hack to have the AP pay attention to
 the IRQ but not to ack it.  It also wasn't supposed to configure the
 IRQ in any way.  That hack allowed us to detect when the device was
 charging without messing with the EC's state.
 
 The current tps65090 infrastructure makes the above difficult, and it
 was a bit of a hack to begin with.  Rather than uglify the driver to
 support it, just extend the driver's existing notion of no irq to
 the charger.  This makes the charger code poll every 2 seconds for AC
 detect, which is sufficient.
 
 For proper functioning, requires (mfd: tps65090: Don't tell child
 devices we have an IRQ if we don't).  If we don't have that patch
 we'll simply fail to probe on devices without an interrupt (just like
 we did before this patch).

Applied to the dev branch, which I use until I get access to the
official battery.git:

https://git.kernel.org/cgit/linux/kernel/git/sre/linux-power-supply.git/commit/?h=devid=5a3effdc8877132fd12f97fea0d4756614b911c7

-- Sebastian


signature.asc
Description: Digital signature


[RESEND PATCH v3] charger: tps65090: Allow charger module to be used when no irq

2014-06-20 Thread Doug Anderson
On the ARM Chromebook tps65090 has two masters: the AP (the main
processor running linux) and the EC (the embedded controller).  The AP
is allowed to mess with FETs but the EC is in charge of charge control.

The tps65090 interupt line is routed to both the AP and the EC, which
can cause quite a headache.  Having two people adjusting masks and
acking interrupts is a recipe for disaster.

In the shipping kernel we had a hack to have the AP pay attention to
the IRQ but not to ack it.  It also wasn't supposed to configure the
IRQ in any way.  That hack allowed us to detect when the device was
charging without messing with the EC's state.

The current tps65090 infrastructure makes the above difficult, and it
was a bit of a hack to begin with.  Rather than uglify the driver to
support it, just extend the driver's existing notion of no irq to
the charger.  This makes the charger code poll every 2 seconds for AC
detect, which is sufficient.

For proper functioning, requires (mfd: tps65090: Don't tell child
devices we have an IRQ if we don't).  If we don't have that patch
we'll simply fail to probe on devices without an interrupt (just like
we did before this patch).

Signed-off-by: Doug Anderson diand...@chromium.org
---
Changes in v2:
- Split noirq (polling mode) changes into MFD and charger

This patch has been sent up a number of times with no response.  It's
needed to make the charger work on exynos5250-snow,
exynos5420-peach-pit, and exynos5800-peach-pi.  It was originally part
of a series as https://patchwork.kernel.org/patch/4042751/ and the
rest of the series has long since landed.

This is the third resend.

 drivers/power/tps65090-charger.c | 76 +++-
 1 file changed, 59 insertions(+), 17 deletions(-)

diff --git a/drivers/power/tps65090-charger.c b/drivers/power/tps65090-charger.c
index 1685f63..31a3ba4 100644
--- a/drivers/power/tps65090-charger.c
+++ b/drivers/power/tps65090-charger.c
@@ -17,9 +17,11 @@
  */
 #include linux/delay.h
 #include linux/err.h
+#include linux/freezer.h
 #include linux/init.h
 #include linux/interrupt.h
 #include linux/kernel.h
+#include linux/kthread.h
 #include linux/module.h
 #include linux/of_device.h
 #include linux/platform_device.h
@@ -32,11 +34,15 @@
 #define TPS65090_VACG  BIT(1)
 #define TPS65090_NOITERM   BIT(5)
 
+#define POLL_INTERVAL  (HZ * 2)/* Used when no irq */
+
 struct tps65090_charger {
struct  device  *dev;
int ac_online;
int prev_ac_online;
int irq;
+   struct task_struct  *poll_task;
+   boolpassive_mode;
struct power_supply ac;
struct tps65090_platform_data *pdata;
 };
@@ -49,6 +55,9 @@ static int tps65090_low_chrg_current(struct tps65090_charger 
*charger)
 {
int ret;
 
+   if (charger-passive_mode)
+   return 0;
+
ret = tps65090_write(charger-dev-parent, TPS65090_REG_CG_CTRL5,
TPS65090_NOITERM);
if (ret  0) {
@@ -64,6 +73,9 @@ static int tps65090_enable_charging(struct tps65090_charger 
*charger)
int ret;
uint8_t ctrl0 = 0;
 
+   if (charger-passive_mode)
+   return 0;
+
ret = tps65090_read(charger-dev-parent, TPS65090_REG_CG_CTRL0,
ctrl0);
if (ret  0) {
@@ -87,6 +99,9 @@ static int tps65090_config_charger(struct tps65090_charger 
*charger)
uint8_t intrmask = 0;
int ret;
 
+   if (charger-passive_mode)
+   return 0;
+
if (charger-pdata-enable_low_current_chrg) {
ret = tps65090_low_chrg_current(charger);
if (ret  0) {
@@ -164,10 +179,14 @@ static irqreturn_t tps65090_charger_isr(int irq, void 
*dev_id)
}
 
/* Clear interrupts. */
-   ret = tps65090_write(charger-dev-parent, TPS65090_REG_INTR_STS, 0x00);
-   if (ret  0) {
-   dev_err(charger-dev, %s(): Error in writing reg 0x%x\n,
+   if (!charger-passive_mode) {
+   ret = tps65090_write(charger-dev-parent,
+TPS65090_REG_INTR_STS, 0x00);
+   if (ret  0) {
+   dev_err(charger-dev,
+   %s(): Error in writing reg 0x%x\n,
__func__, TPS65090_REG_INTR_STS);
+   }
}
 
if (charger-prev_ac_online != charger-ac_online)
@@ -198,6 +217,18 @@ static struct tps65090_platform_data *
 
 }
 
+static int tps65090_charger_poll_task(void *data)
+{
+   set_freezable();
+
+   while (!kthread_should_stop()) {
+   schedule_timeout_interruptible(POLL_INTERVAL);
+   try_to_freeze();
+   tps65090_charger_isr(-1, data);
+   }
+   return 0;
+}
+
 static int tps65090_charger_probe(struct platform_device *pdev)
 {
struct tps65090_charger *cdata;
@@ -244,22 +275,10 @@ static int 

[RESEND PATCH v3] charger: tps65090: Allow charger module to be used when no irq

2014-05-29 Thread Doug Anderson
On the ARM Chromebook tps65090 has two masters: the AP (the main
processor running linux) and the EC (the embedded controller).  The AP
is allowed to mess with FETs but the EC is in charge of charge control.

The tps65090 interupt line is routed to both the AP and the EC, which
can cause quite a headache.  Having two people adjusting masks and
acking interrupts is a recipe for disaster.

In the shipping kernel we had a hack to have the AP pay attention to
the IRQ but not to ack it.  It also wasn't supposed to configure the
IRQ in any way.  That hack allowed us to detect when the device was
charging without messing with the EC's state.

The current tps65090 infrastructure makes the above difficult, and it
was a bit of a hack to begin with.  Rather than uglify the driver to
support it, just extend the driver's existing notion of no irq to
the charger.  This makes the charger code poll every 2 seconds for AC
detect, which is sufficient.

For proper functioning, requires (mfd: tps65090: Don't tell child
devices we have an IRQ if we don't).  If we don't have that patch
we'll simply fail to probe on devices without an interrupt (just like
we did before this patch).

Signed-off-by: Doug Anderson diand...@chromium.org
---
This patch has been sent up a number of times with no response.  It's
needed to make the charger work on exynos5250-snow,
exynos5420-peach-pit, and exynos5800-peach-pi.  It was originally part
of a series as https://patchwork.kernel.org/patch/4042751/ and the
rest of the series has landed.

Andrew Morton: would you be willing to take this?

Changes in v3: None
Changes in v2:
- Split noirq (polling mode) changes into MFD and charger

 drivers/power/tps65090-charger.c | 76 +++-
 1 file changed, 59 insertions(+), 17 deletions(-)

diff --git a/drivers/power/tps65090-charger.c b/drivers/power/tps65090-charger.c
index 8fc9d6d..cc26c12 100644
--- a/drivers/power/tps65090-charger.c
+++ b/drivers/power/tps65090-charger.c
@@ -17,9 +17,11 @@
  */
 #include linux/delay.h
 #include linux/err.h
+#include linux/freezer.h
 #include linux/init.h
 #include linux/interrupt.h
 #include linux/kernel.h
+#include linux/kthread.h
 #include linux/module.h
 #include linux/of_device.h
 #include linux/platform_device.h
@@ -43,11 +45,15 @@
 #define TPS65090_VACG  BIT(1)
 #define TPS65090_NOITERM   BIT(5)
 
+#define POLL_INTERVAL  (HZ * 2)/* Used when no irq */
+
 struct tps65090_charger {
struct  device  *dev;
int ac_online;
int prev_ac_online;
int irq;
+   struct task_struct  *poll_task;
+   boolpassive_mode;
struct power_supply ac;
struct tps65090_platform_data *pdata;
 };
@@ -60,6 +66,9 @@ static int tps65090_low_chrg_current(struct tps65090_charger 
*charger)
 {
int ret;
 
+   if (charger-passive_mode)
+   return 0;
+
ret = tps65090_write(charger-dev-parent, TPS65090_REG_CG_CTRL5,
TPS65090_NOITERM);
if (ret  0) {
@@ -75,6 +84,9 @@ static int tps65090_enable_charging(struct tps65090_charger 
*charger)
int ret;
uint8_t ctrl0 = 0;
 
+   if (charger-passive_mode)
+   return 0;
+
ret = tps65090_read(charger-dev-parent, TPS65090_REG_CG_CTRL0,
ctrl0);
if (ret  0) {
@@ -98,6 +110,9 @@ static int tps65090_config_charger(struct tps65090_charger 
*charger)
uint8_t intrmask = 0;
int ret;
 
+   if (charger-passive_mode)
+   return 0;
+
if (charger-pdata-enable_low_current_chrg) {
ret = tps65090_low_chrg_current(charger);
if (ret  0) {
@@ -175,10 +190,14 @@ static irqreturn_t tps65090_charger_isr(int irq, void 
*dev_id)
}
 
/* Clear interrupts. */
-   ret = tps65090_write(charger-dev-parent, TPS65090_REG_INTR_STS, 0x00);
-   if (ret  0) {
-   dev_err(charger-dev, %s(): Error in writing reg 0x%x\n,
+   if (!charger-passive_mode) {
+   ret = tps65090_write(charger-dev-parent,
+TPS65090_REG_INTR_STS, 0x00);
+   if (ret  0) {
+   dev_err(charger-dev,
+   %s(): Error in writing reg 0x%x\n,
__func__, TPS65090_REG_INTR_STS);
+   }
}
 
if (charger-prev_ac_online != charger-ac_online)
@@ -209,6 +228,18 @@ static struct tps65090_platform_data *
 
 }
 
+static int tps65090_charger_poll_task(void *data)
+{
+   set_freezable();
+
+   while (!kthread_should_stop()) {
+   schedule_timeout_interruptible(POLL_INTERVAL);
+   try_to_freeze();
+   tps65090_charger_isr(-1, data);
+   }
+   return 0;
+}
+
 static int tps65090_charger_probe(struct platform_device *pdev)
 {
struct tps65090_charger *cdata;
@@ -255,22 +286,10 @@ 

[RESEND PATCH v3] charger: tps65090: Allow charger module to be used when no irq

2014-05-20 Thread Doug Anderson
On the ARM Chromebook tps65090 has two masters: the AP (the main
processor running linux) and the EC (the embedded controller).  The AP
is allowed to mess with FETs but the EC is in charge of charge control.

The tps65090 interupt line is routed to both the AP and the EC, which
can cause quite a headache.  Having two people adjusting masks and
acking interrupts is a recipe for disaster.

In the shipping kernel we had a hack to have the AP pay attention to
the IRQ but not to ack it.  It also wasn't supposed to configure the
IRQ in any way.  That hack allowed us to detect when the device was
charging without messing with the EC's state.

The current tps65090 infrastructure makes the above difficult, and it
was a bit of a hack to begin with.  Rather than uglify the driver to
support it, just extend the driver's existing notion of no irq to
the charger.  This makes the charger code poll every 2 seconds for AC
detect, which is sufficient.

For proper functioning, requires (mfd: tps65090: Don't tell child
devices we have an IRQ if we don't).  If we don't have that patch
we'll simply fail to probe on devices without an interrupt (just like
we did before this patch).

Signed-off-by: Doug Anderson diand...@chromium.org
---

Note that this patch was part of a larger series
https://patchwork.kernel.org/patch/4042751/.  The rest of the series
has been applied, so just RESENDing this one part.

Changes in v3: None
Changes in v2:
- Split noirq (polling mode) changes into MFD and charger

 drivers/power/tps65090-charger.c | 76 +++-
 1 file changed, 59 insertions(+), 17 deletions(-)

diff --git a/drivers/power/tps65090-charger.c b/drivers/power/tps65090-charger.c
index 8fc9d6d..cc26c12 100644
--- a/drivers/power/tps65090-charger.c
+++ b/drivers/power/tps65090-charger.c
@@ -17,9 +17,11 @@
  */
 #include linux/delay.h
 #include linux/err.h
+#include linux/freezer.h
 #include linux/init.h
 #include linux/interrupt.h
 #include linux/kernel.h
+#include linux/kthread.h
 #include linux/module.h
 #include linux/of_device.h
 #include linux/platform_device.h
@@ -43,11 +45,15 @@
 #define TPS65090_VACG  BIT(1)
 #define TPS65090_NOITERM   BIT(5)
 
+#define POLL_INTERVAL  (HZ * 2)/* Used when no irq */
+
 struct tps65090_charger {
struct  device  *dev;
int ac_online;
int prev_ac_online;
int irq;
+   struct task_struct  *poll_task;
+   boolpassive_mode;
struct power_supply ac;
struct tps65090_platform_data *pdata;
 };
@@ -60,6 +66,9 @@ static int tps65090_low_chrg_current(struct tps65090_charger 
*charger)
 {
int ret;
 
+   if (charger-passive_mode)
+   return 0;
+
ret = tps65090_write(charger-dev-parent, TPS65090_REG_CG_CTRL5,
TPS65090_NOITERM);
if (ret  0) {
@@ -75,6 +84,9 @@ static int tps65090_enable_charging(struct tps65090_charger 
*charger)
int ret;
uint8_t ctrl0 = 0;
 
+   if (charger-passive_mode)
+   return 0;
+
ret = tps65090_read(charger-dev-parent, TPS65090_REG_CG_CTRL0,
ctrl0);
if (ret  0) {
@@ -98,6 +110,9 @@ static int tps65090_config_charger(struct tps65090_charger 
*charger)
uint8_t intrmask = 0;
int ret;
 
+   if (charger-passive_mode)
+   return 0;
+
if (charger-pdata-enable_low_current_chrg) {
ret = tps65090_low_chrg_current(charger);
if (ret  0) {
@@ -175,10 +190,14 @@ static irqreturn_t tps65090_charger_isr(int irq, void 
*dev_id)
}
 
/* Clear interrupts. */
-   ret = tps65090_write(charger-dev-parent, TPS65090_REG_INTR_STS, 0x00);
-   if (ret  0) {
-   dev_err(charger-dev, %s(): Error in writing reg 0x%x\n,
+   if (!charger-passive_mode) {
+   ret = tps65090_write(charger-dev-parent,
+TPS65090_REG_INTR_STS, 0x00);
+   if (ret  0) {
+   dev_err(charger-dev,
+   %s(): Error in writing reg 0x%x\n,
__func__, TPS65090_REG_INTR_STS);
+   }
}
 
if (charger-prev_ac_online != charger-ac_online)
@@ -209,6 +228,18 @@ static struct tps65090_platform_data *
 
 }
 
+static int tps65090_charger_poll_task(void *data)
+{
+   set_freezable();
+
+   while (!kthread_should_stop()) {
+   schedule_timeout_interruptible(POLL_INTERVAL);
+   try_to_freeze();
+   tps65090_charger_isr(-1, data);
+   }
+   return 0;
+}
+
 static int tps65090_charger_probe(struct platform_device *pdev)
 {
struct tps65090_charger *cdata;
@@ -255,22 +286,10 @@ static int tps65090_charger_probe(struct platform_device 
*pdev)
}
 
irq = platform_get_irq(pdev, 0);
-   if (irq = 0) {
-