Re: [PATCH 0/2] Introduce usb charger framework to deal with the usb gadget power negotation

2015-08-08 Thread Baolin Wang
On 8 August 2015 at 01:52, Greg KH gre...@linuxfoundation.org wrote:
 On Fri, Aug 07, 2015 at 04:19:40PM +0800, Baolin Wang wrote:
 On 7 August 2015 at 13:34, Peter Chen peter.c...@freescale.com wrote:
  On Thu, Aug 06, 2015 at 03:03:47PM +0800, Baolin Wang wrote:
  Currently the Linux kernel does not provide any standard integration of 
  this
  feature that integrates the USB subsystem with the system power regulation
  provided by PMICs meaning that either vendors must add this in their 
  kernels
  or USB gadget devices based on Linux (such as mobile phones) may not 
  behave
  as they should.
 
  Providing a standard framework for doing this in the kernel.
 
  Baolin, thanks for introducing a framework for doing it, we do support
  USB Charger for chipidea driver at internal tree, but it is specific
  for imx, and still have some problems to upstream due to need to
  change some common code.
 
  One suggestion, would you add your user next time? In that case, we can
  know better for this framework.
 

 Peter, Thanks for your reviewing and comments. Now I just introduce
 the framework to review for more feedbacks and do not have a useful
 user to use it. I just can show you some example code to show how to
 use it. Thanks.

 Without a real, in-tree user, I can not accept this code.  We don't add
 frameworks for non-existant things, otherwise it will be instantly
 ripped out the next kernel release.

 Please come up with at least 2 users, ideally 3, otherwise there's no
 real way to know if the framework is sufficient.


OK, I'll try to come up with 2 or 3 users. Thanks.

 thanks,

 greg k-h



-- 
Baolin.wang
Best Regards
--
To unsubscribe from this list: send the line unsubscribe linux-usb in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 2/2] gadget: Support for the usb charger framework

2015-08-08 Thread Baolin Wang
On 8 August 2015 at 01:53, Greg KH gre...@linuxfoundation.org wrote:
 On Fri, Aug 07, 2015 at 05:22:47PM +0800, Baolin Wang wrote:
 On 7 August 2015 at 17:07, Peter Chen peter.c...@freescale.com wrote:
 
/**
 * struct usb_udc - describes one usb device controller @@ -127,12
   +128,45 @@ void usb_gadget_giveback_request(struct usb_ep *ep,  }
   EXPORT_SYMBOL_GPL(usb_gadget_giveback_request);
  
   +int usb_gadget_register_notify(struct usb_gadget *gadget,
   +struct notifier_block *nb) {
   + unsigned long flags;
   + int ret;
   +
   + spin_lock_irqsave(gadget-lock, flags);
  
   I find you use so many spin_lock_irqsave, any reasons for that?
   Why mutex_lock can't be used?
  
 
  The spin_lock_irqsave() can make it as a atomic notifier, that can make 
  sure the
  gadget state event can be quickly reported to the user who register a 
  notifier
  on the gadget device. Is it OK?
 
 
  I don't think it is a good reason, spin_lock_irqsave is usually used for 
  protecting
  data which is accessed at atomic environment.
 

 Yes, we want the notify process is a atomic environment which do not
 want to be interrupted by irq or other things to make the notice can
 be quickly reported to the user.

 No, this is a slow event, you don't need to notify anyone under atomic
 context, that's crazy.

 Also i think the notify process is less cost, thus i use the spinlock. 
 Thanks.

 No, use a mutex please, that's the safe thing.  This is not
 time-critical code at all.


OK, Thanks for your comments and will fix the lock thing.

 thanks,

 greg k-h



-- 
Baolin.wang
Best Regards
--
To unsubscribe from this list: send the line unsubscribe linux-usb in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v2 0/3] Introduce usb charger framework to deal with the usb gadget power negotation

2015-08-17 Thread Baolin Wang
On 17 August 2015 at 16:20, Li Jun b47...@freescale.com wrote:
 On Mon, Aug 17, 2015 at 02:02:08PM +0800, Baolin Wang wrote:
 On 17 August 2015 at 09:15, Li Jun b47...@freescale.com wrote:
  On Fri, Aug 14, 2015 at 07:04:56PM +0800, Baolin Wang wrote:
  On 14 August 2015 at 16:55, Li Jun b47...@freescale.com wrote:
   Hi Baolin,
  
   On Fri, Aug 14, 2015 at 05:47:43PM +0800, Baolin Wang wrote:
   Currently the Linux kernel does not provide any standard integration 
   of this
   feature that integrates the USB subsystem with the system power 
   regulation
   provided by PMICs meaning that either vendors must add this in their 
   kernels
   or USB gadget devices based on Linux (such as mobile phones) may not 
   behave
   as they should.
  
   Providing a standard framework for doing this in the kernel.
  
  
   Why not add power supply class support into this?
  
 
  Hi Jun,
 
  We don't need the power supply class support into the usb charger,
  I suppose usb charger is also a power supply for the system, we can use 
  power
  supply class framework for notify mechanism and get/set many 
  attributes(maybe
  also the current limit), I see those usb charger drivers under 
  ./driver/power/
  are designed with power supply supported.
 

 I don't think so. The usb charger is rely on the usb gadget, which is
 not a complete power supply device and it combines the usb and the
 power supply. Thus we make it into usb gadget system. Thanks.

 Why it cannot be a complete power supply device? I was thinking this
 framework can cover it, I have no doubt on putting this framework
 into gadget system, but still can't understand why we don't need
 power supply class at all for a usb charger, or you think introduce
 power supply into usb gadget is not a right direction from code structure
 point view?


We just do not think the usb charger as a real device, which is only
used to set the current limitation when the usb charger state is
changed detecting by extcon device or usb gadget. So we just need one
message to notify the power user to set the current limitation when
uab charge is added or removed. I also agree with the power supply
framework can cover it, but we don't need to implement it to be
another power supply, cause there is a real device as the power supply
to deal with the power issue in the system. Thanks.

 Li Jun
  Li Jun
  just introduce the notify mechanism for power to set the current limit
  when notifying some events from usb charger. Maybe I misunderstand
  your meanings, please describe it detailedly. Thanks for your
  comments.
 
   Li Jun
  
 
 
 
  --
  Baolin.wang
  Best Regards



 --
 Baolin.wang
 Best Regards



-- 
Baolin.wang
Best Regards
--
To unsubscribe from this list: send the line unsubscribe linux-usb in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v2 2/3] gadget: Introduce the usb charger framework

2015-08-17 Thread Baolin Wang
On 18 August 2015 at 01:24, Mark Brown broo...@kernel.org wrote:
 On Mon, Aug 17, 2015 at 11:03:26AM +0800, Baolin Wang wrote:
 On 14 August 2015 at 23:27, Greg KH gre...@linuxfoundation.org wrote:
  On Fri, Aug 14, 2015 at 05:47:45PM +0800, Baolin Wang wrote:

  + * 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.

  I have to ask, do you really mean any later version?

 I think I did not get your point, could you explain it detailedly?

 Unlike a lot of userspace projects the kernel is normally just licensed
 under GPLv2 without the option to relicense with a later version so the
 ...or any later version is a bit unusual.  There is some controversy
 about some of the changes in GPLv3.

Make sense. Thanks a lot.


-- 
Baolin.wang
Best Regards
--
To unsubscribe from this list: send the line unsubscribe linux-usb in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [Device-mainlining] [PATCH v2 2/3] gadget: Introduce the usb charger framework

2015-08-17 Thread Baolin Wang
On 17 August 2015 at 23:25, Tim Bird tim.b...@sonymobile.com wrote:


 On 08/16/2015 08:03 PM, Baolin Wang via device-mainlining wrote:
 On 14 August 2015 at 23:27, Greg KH gre...@linuxfoundation.org wrote:
 On Fri, Aug 14, 2015 at 05:47:45PM +0800, Baolin Wang wrote:
 + *
 + * 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.

 I have to ask, do you really mean any later version?


 I think I did not get your point, could you explain it detailedly?

 The full kernel is licensed under v2 of the GPL only, not any later version.
 See the second paragraph at the top of the COPYING file in the root directory
 of the kernel source tree. There are differences on individual files, but
 having this file allow any later version makes it different from much of
 rest of the kernel.

 Unless you have a specific reason to allow greater-than-V2 GPL licensing on 
 this
 file, you should change the licensing clause.  The following wording appears
 to be pretty popular:

 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.


Hi Tim,

Make sense of it. Thanks for your explanation.

   -- Tim



-- 
Baolin.wang
Best Regards
--
To unsubscribe from this list: send the line unsubscribe linux-usb in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v3 3/3] power: wm831x_power: Support USB charger current limit management

2015-08-18 Thread Baolin Wang
Integrate with the newly added USB charger interface to limit the current
we draw from the USB input based on the input device configuration
identified by the USB stack, allowing us to charge more quickly from high
current inputs without drawing more current than specified from others.

Signed-off-by: Mark Brown broo...@kernel.org
Signed-off-by: Baolin Wang baolin.w...@linaro.org
---
 drivers/power/wm831x_power.c |   69 ++
 include/linux/mfd/wm831x/pdata.h |3 ++
 2 files changed, 72 insertions(+)

diff --git a/drivers/power/wm831x_power.c b/drivers/power/wm831x_power.c
index db11ae6..72c661f 100644
--- a/drivers/power/wm831x_power.c
+++ b/drivers/power/wm831x_power.c
@@ -13,6 +13,7 @@
 #include linux/platform_device.h
 #include linux/power_supply.h
 #include linux/slab.h
+#include linux/usb/usb_charger.h
 
 #include linux/mfd/wm831x/core.h
 #include linux/mfd/wm831x/auxadc.h
@@ -31,6 +32,8 @@ struct wm831x_power {
char usb_name[20];
char battery_name[20];
bool have_battery;
+   struct usb_charger *usb_charger;
+   struct notifier_block usb_notify;
 };
 
 static int wm831x_power_check_online(struct wm831x *wm831x, int supply,
@@ -125,6 +128,43 @@ static enum power_supply_property wm831x_usb_props[] = {
POWER_SUPPLY_PROP_VOLTAGE_NOW,
 };
 
+/* In miliamps */
+static unsigned int wm831x_usb_limits[] = {
+   0,
+   2,
+   100,
+   500,
+   900,
+   1500,
+   1800,
+   550,
+};
+
+static int wm831x_usb_limit_change(struct notifier_block *nb,
+  unsigned long limit, void *data)
+{
+   struct wm831x_power *wm831x_power = container_of(nb,
+struct wm831x_power,
+usb_notify);
+   int i, best;
+
+   /* Find the highest supported limit */
+   best = 0;
+   for (i = 0; i  ARRAY_SIZE(wm831x_usb_limits); i++) {
+   if (limit  wm831x_usb_limits[i] 
+   wm831x_usb_limits[best]  wm831x_usb_limits[i])
+   best = i;
+   }
+
+   dev_dbg(wm831x_power-wm831x-dev,
+   Limiting USB current to %dmA, wm831x_usb_limits[best]);
+
+   wm831x_set_bits(wm831x_power-wm831x, WM831X_POWER_STATE,
+   WM831X_USB_ILIM_MASK, best);
+
+   return 0;
+}
+
 /*
  * Battery properties
  */
@@ -606,8 +646,31 @@ static int wm831x_power_probe(struct platform_device *pdev)
}
}
 
+   if (wm831x_pdata  wm831x_pdata-usb_gadget) {
+   power-usb_charger =
+   usb_charger_find_by_name(wm831x_pdata-usb_gadget);
+   if (IS_ERR(power-usb_charger)) {
+   ret = PTR_ERR(power-usb_charger);
+   dev_err(pdev-dev,
+   Failed to find USB gadget: %d\n, ret);
+   goto err_bat_irq;
+   }
+
+   power-usb_notify.notifier_call = wm831x_usb_limit_change;
+
+   ret = usb_charger_register_notify(power-usb_charger,
+ power-usb_notify);
+   if (ret != 0) {
+   dev_err(pdev-dev,
+   Failed to register notifier: %d\n, ret);
+   goto err_usb_charger;
+   }
+   }
+
return ret;
 
+err_usb_charger:
+   usb_charger_put(power-usb_charger);
 err_bat_irq:
--i;
for (; i = 0; i--) {
@@ -637,6 +700,12 @@ static int wm831x_power_remove(struct platform_device 
*pdev)
struct wm831x *wm831x = wm831x_power-wm831x;
int irq, i;
 
+   if (wm831x_power-usb_charger) {
+   usb_charger_unregister_notify(wm831x_power-usb_charger,
+ wm831x_power-usb_notify);
+   usb_charger_put(wm831x_power-usb_charger);
+   }
+
for (i = 0; i  ARRAY_SIZE(wm831x_bat_irqs); i++) {
irq = wm831x_irq(wm831x, 
 platform_get_irq_byname(pdev,
diff --git a/include/linux/mfd/wm831x/pdata.h b/include/linux/mfd/wm831x/pdata.h
index dcc9631..5af8399 100644
--- a/include/linux/mfd/wm831x/pdata.h
+++ b/include/linux/mfd/wm831x/pdata.h
@@ -126,6 +126,9 @@ struct wm831x_pdata {
/** The driver should initiate a power off sequence during shutdown */
bool soft_shutdown;
 
+   /** dev_name of USB charger gadget to integrate with */
+   const char *usb_gadget;
+
int irq_base;
int gpio_base;
int gpio_defaults[WM831X_GPIO_NUM];
-- 
1.7.9.5

--
To unsubscribe from this list: send the line unsubscribe linux-usb in
the body of a message to majord...@vger.kernel.org
More majordomo

[PATCH v3 2/3] gadget: Introduce the usb charger framework

2015-08-18 Thread Baolin Wang
This patch introduces the usb charger driver based on usb gadget that
makes an enhancement to a power driver. It works well in practice but
that requires a system with suitable hardware.

The basic conception of the usb charger is that, when one usb charger
is added or removed by reporting from the usb gadget state change or
the extcon device state change, the usb charger will report to power
user to set the current limitation.

The usb charger will register notifiees on the usb gadget or the extcon
device to get notified the usb charger state.

Power user will register a notifiee on the usb charger to get notified
by status changes from the usb charger. It will report to power user
to set the current limitation when detecting the usb charger is added
or removed from extcon device state or usb gadget state.

Signed-off-by: Baolin Wang baolin.w...@linaro.org
---
 drivers/usb/gadget/Kconfig  |7 +
 drivers/usb/gadget/Makefile |1 +
 drivers/usb/gadget/charger.c|  538 +++
 include/linux/usb/usb_charger.h |  138 ++
 4 files changed, 684 insertions(+)
 create mode 100644 drivers/usb/gadget/charger.c
 create mode 100644 include/linux/usb/usb_charger.h

diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig
index bcf83c0..3d2b959 100644
--- a/drivers/usb/gadget/Kconfig
+++ b/drivers/usb/gadget/Kconfig
@@ -127,6 +127,13 @@ config USB_GADGET_STORAGE_NUM_BUFFERS
   a module parameter as well.
   If unsure, say 2.
 
+config USB_CHARGER
+   bool USB charger support
+   help
+ The usb charger driver based on the usb gadget that makes an
+ enhancement to a power driver which can set the current limitation
+ when the usb charger is added or removed.
+
 source drivers/usb/gadget/udc/Kconfig
 
 #
diff --git a/drivers/usb/gadget/Makefile b/drivers/usb/gadget/Makefile
index 598a67d..1e421c1 100644
--- a/drivers/usb/gadget/Makefile
+++ b/drivers/usb/gadget/Makefile
@@ -10,3 +10,4 @@ libcomposite-y:= usbstring.o config.o 
epautoconf.o
 libcomposite-y += composite.o functions.o configfs.o u_f.o
 
 obj-$(CONFIG_USB_GADGET)   += udc/ function/ legacy/
+obj-$(CONFIG_USB_CHARGER)  += charger.o
diff --git a/drivers/usb/gadget/charger.c b/drivers/usb/gadget/charger.c
new file mode 100644
index 000..93fd36f
--- /dev/null
+++ b/drivers/usb/gadget/charger.c
@@ -0,0 +1,538 @@
+/*
+ * charger.c -- USB charger driver
+ *
+ * Copyright (C) 2015 Linaro Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include linux/device.h
+#include linux/err.h
+#include linux/extcon.h
+#include linux/export.h
+#include linux/kernel.h
+#include linux/module.h
+#include linux/of.h
+#include linux/of_device.h
+#include linux/of_address.h
+#include linux/platform_device.h
+#include linux/slab.h
+#include linux/usb.h
+#include linux/usb/ch9.h
+#include linux/usb/gadget.h
+#include linux/usb/usb_charger.h
+
+#define DEFAULT_CUR_PROTECT(50)
+#define DEFAULT_SDP_CUR_LIMIT  (500 - DEFAULT_CUR_PROTECT)
+#define DEFAULT_DCP_CUR_LIMIT  (1500 - DEFAULT_CUR_PROTECT)
+#define DEFAULT_CDP_CUR_LIMIT  (1500 - DEFAULT_CUR_PROTECT)
+#define DEFAULT_ACA_CUR_LIMIT  (1500 - DEFAULT_CUR_PROTECT)
+
+static DEFINE_IDA(usb_charger_ida);
+static struct bus_type usb_charger_subsys = {
+   .name   = usb-charger,
+   .dev_name   = usb-charger,
+};
+
+static struct usb_charger *dev_to_uchger(struct device *udev)
+{
+   return container_of(udev, struct usb_charger, dev);
+}
+
+static ssize_t cur_limit_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+   struct usb_charger *uchger = dev_to_uchger(dev);
+
+   return scnprintf(buf, PAGE_SIZE, %d %d %d %d\n,
+uchger-cur_limit.sdp_cur_limit,
+uchger-cur_limit.dcp_cur_limit,
+uchger-cur_limit.cdp_cur_limit,
+uchger-cur_limit.aca_cur_limit);
+}
+
+static ssize_t cur_limit_store(struct device *dev,
+  struct device_attribute *attr,
+  const char *buf, size_t count)
+{
+   struct usb_charger *uchger = dev_to_uchger(dev);
+   struct usb_charger_cur_limit cur;
+   int ret;
+
+   ret = sscanf(buf, %d %d %d %d,
+cur.sdp_cur_limit, cur.dcp_cur_limit,
+cur.cdp_cur_limit, cur.aca_cur_limit);
+   if (ret == 0)
+   return -EINVAL;
+
+   ret = usb_charger_set_cur_limit(uchger, cur);
+   if (ret  0)
+   return ret;
+
+   return count;
+}
+static DEVICE_ATTR_RW(cur_limit);
+
+static struct attribute *usb_charger_attrs[] = {
+   dev_attr_cur_limit.attr,
+   NULL

[PATCH v3 0/3] Introduce usb charger framework to deal with the usb gadget power negotation

2015-08-18 Thread Baolin Wang
Currently the Linux kernel does not provide any standard integration of this
feature that integrates the USB subsystem with the system power regulation
provided by PMICs meaning that either vendors must add this in their kernels
or USB gadget devices based on Linux (such as mobile phones) may not behave
as they should.

Providing a standard framework for doing this in the kernel.

Now introduce one user with wm831x_power to support and test the usb charger,
which is pending testing. Moreover there may be other potential users will use
it in future.

Changes since v2:
 - Use macro DEVICE_ATTR_RW()/ATTRIBUTE_GROUPS() and change the method to
   register the attruibutes.
 - Remove the 'name' and 'entry' member of struct 'usb_charger'.
 - Replace devm_kzalloc() with kzalloc() to follow the the lifetime rules.
 - Other modifications.

Baolin Wang (3):
  gadget: Support for the usb charger framework
  gadget: Introduce the usb charger framework
  power: wm831x_power: Support USB charger current limit management

 drivers/power/wm831x_power.c  |   69 +
 drivers/usb/gadget/Kconfig|7 +
 drivers/usb/gadget/Makefile   |1 +
 drivers/usb/gadget/charger.c  |  538 +
 drivers/usb/gadget/udc/udc-core.c |   41 ++-
 include/linux/mfd/wm831x/pdata.h  |3 +
 include/linux/usb/gadget.h|   20 ++
 include/linux/usb/usb_charger.h   |  138 ++
 8 files changed, 816 insertions(+), 1 deletion(-)
 create mode 100644 drivers/usb/gadget/charger.c
 create mode 100644 include/linux/usb/usb_charger.h

-- 
1.7.9.5

--
To unsubscribe from this list: send the line unsubscribe linux-usb in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v3 1/3] gadget: Support for the usb charger framework

2015-08-18 Thread Baolin Wang
The usb charger framework is based on usb gadget, and each usb gadget
can be one usb charger to set the current limitation.

This patch adds a notifier mechanism for usb charger to report to usb
charger when the usb gadget state is changed.

Also we introduce a callback 'get_charger_type' which will implemented
by user for usb gadget operations to get the usb charger type.

Signed-off-by: Baolin Wang baolin.w...@linaro.org
---
 drivers/usb/gadget/udc/udc-core.c |   41 -
 include/linux/usb/gadget.h|   20 ++
 2 files changed, 60 insertions(+), 1 deletion(-)

diff --git a/drivers/usb/gadget/udc/udc-core.c 
b/drivers/usb/gadget/udc/udc-core.c
index f660afb..1971218 100644
--- a/drivers/usb/gadget/udc/udc-core.c
+++ b/drivers/usb/gadget/udc/udc-core.c
@@ -28,6 +28,7 @@
 #include linux/usb/ch9.h
 #include linux/usb/gadget.h
 #include linux/usb.h
+#include linux/usb/usb_charger.h
 
 /**
  * struct usb_udc - describes one usb device controller
@@ -129,6 +130,32 @@ void usb_gadget_giveback_request(struct usb_ep *ep,
 }
 EXPORT_SYMBOL_GPL(usb_gadget_giveback_request);
 
+int usb_gadget_register_notify(struct usb_gadget *gadget,
+  struct notifier_block *nb)
+{
+   int ret;
+
+   mutex_lock(gadget-lock);
+   ret = raw_notifier_chain_register(gadget-nh, nb);
+   mutex_unlock(gadget-lock);
+
+   return ret;
+}
+EXPORT_SYMBOL_GPL(usb_gadget_register_notify);
+
+int usb_gadget_unregister_notify(struct usb_gadget *gadget,
+struct notifier_block *nb)
+{
+   int ret;
+
+   mutex_lock(gadget-lock);
+   ret = raw_notifier_chain_unregister(gadget-nh, nb);
+   mutex_unlock(gadget-lock);
+
+   return ret;
+}
+EXPORT_SYMBOL_GPL(usb_gadget_unregister_notify);
+
 /* - */
 
 /**
@@ -226,6 +253,10 @@ static void usb_gadget_state_work(struct work_struct *work)
struct usb_gadget *gadget = work_to_gadget(work);
struct usb_udc *udc = gadget-udc;
 
+   mutex_lock(gadget-lock);
+   raw_notifier_call_chain(gadget-nh, gadget-state, gadget);
+   mutex_unlock(gadget-lock);
+
if (udc)
sysfs_notify(udc-dev.kobj, NULL, state);
 }
@@ -364,6 +395,8 @@ int usb_add_gadget_udc_release(struct device *parent, 
struct usb_gadget *gadget,
 
dev_set_name(gadget-dev, gadget);
INIT_WORK(gadget-work, usb_gadget_state_work);
+   RAW_INIT_NOTIFIER_HEAD(gadget-nh);
+   mutex_init(gadget-lock);
gadget-dev.parent = parent;
 
 #ifdef CONFIG_HAS_DMA
@@ -405,8 +438,13 @@ int usb_add_gadget_udc_release(struct device *parent, 
struct usb_gadget *gadget,
 
mutex_unlock(udc_lock);
 
-   return 0;
+   ret = usb_charger_init(gadget);
+   if (ret)
+   goto err5;
 
+   return 0;
+err5:
+   device_del(udc-dev);
 err4:
list_del(udc-list);
mutex_unlock(udc_lock);
@@ -481,6 +519,7 @@ void usb_del_gadget_udc(struct usb_gadget *gadget)
kobject_uevent(udc-dev.kobj, KOBJ_REMOVE);
flush_work(gadget-work);
device_unregister(udc-dev);
+   usb_charger_exit(gadget);
device_unregister(gadget-dev);
 }
 EXPORT_SYMBOL_GPL(usb_del_gadget_udc);
diff --git a/include/linux/usb/gadget.h b/include/linux/usb/gadget.h
index c14a69b..78cc862 100644
--- a/include/linux/usb/gadget.h
+++ b/include/linux/usb/gadget.h
@@ -537,6 +537,7 @@ struct usb_gadget_ops {
struct usb_ep *(*match_ep)(struct usb_gadget *,
struct usb_endpoint_descriptor *,
struct usb_ss_ep_comp_descriptor *);
+   enum usb_charger_type   (*get_charger_type)(struct usb_gadget *);
 };
 
 /**
@@ -609,6 +610,9 @@ struct usb_gadget {
unsignedout_epnum;
unsignedin_epnum;
struct usb_otg_caps *otg_caps;
+   struct raw_notifier_headnh;
+   struct usb_charger  *uchger;
+   struct mutexlock;
 
unsignedsg_supported:1;
unsignedis_otg:1;
@@ -1183,6 +1187,22 @@ extern void usb_gadget_unmap_request(struct usb_gadget 
*gadget,
 
 /*-*/
 
+/**
+ * Register a notifiee to get notified by any attach status changes from
+ * the usb gadget
+ */
+int usb_gadget_register_notify(struct usb_gadget *gadget,
+  struct notifier_block *nb);
+
+/*-*/
+
+
+/* Unregister a notifiee from the usb gadget */
+int usb_gadget_unregister_notify(struct usb_gadget *gadget,
+struct notifier_block *nb);
+
+/*-*/
+
 /* utility to set gadget state properly

Re: [PATCH v4 5/5] power: wm831x_power: Support USB charger current limit management

2015-08-19 Thread Baolin Wang
On 20 August 2015 at 00:24, Mark Brown broo...@kernel.org wrote:
 On Wed, Aug 19, 2015 at 05:13:48PM +0800, Baolin Wang wrote:
 Integrate with the newly added USB charger interface to limit the current
 we draw from the USB input based on the input device configuration
 identified by the USB stack, allowing us to charge more quickly from high
 current inputs without drawing more current than specified from others.

 Signed-off-by: Mark Brown broo...@kernel.org
 Signed-off-by: Baolin Wang baolin.w...@linaro.org

 When people (like Charles and Lee have) have reviewed a change you
 should add any tags they gave when you resend the change so they don't
 have to duplicate their work and other people know that the review has
 happened.

Make sense. Thanks.


-- 
Baolin.wang
Best Regards
--
To unsubscribe from this list: send the line unsubscribe linux-usb in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v4 3/5] gadget: Support for the usb charger framework

2015-08-19 Thread Baolin Wang
On 19 August 2015 at 20:56, Sergei Shtylyov
sergei.shtyl...@cogentembedded.com wrote:
 Hello.

 On 8/19/2015 12:13 PM, Baolin Wang wrote:

 For supporting the usb charger, it adds the usb_charger_init() and
 usb_charger_exit() functions for usb charger initialization and exit.

 Introduce a callback 'get_charger_type' which will implemented by
 user for usb gadget operations to get the usb charger type.

 Signed-off-by: Baolin Wang baolin.w...@linaro.org

 [...]

 diff --git a/include/linux/usb/gadget.h b/include/linux/usb/gadget.h
 index 755e8bc..44d82f5 100644
 --- a/include/linux/usb/gadget.h
 +++ b/include/linux/usb/gadget.h
 @@ -537,6 +537,7 @@ struct usb_gadget_ops {
 struct usb_ep *(*match_ep)(struct usb_gadget *,
 struct usb_endpoint_descriptor *,
 struct usb_ss_ep_comp_descriptor *);
 +   enum usb_charger_type   (*get_charger_type)(struct usb_gadget *);

  ^^^ please use space, not tab here

OK.


   };

   /**
 @@ -611,6 +612,7 @@ struct usb_gadget {
 struct usb_otg_caps *otg_caps;
 struct raw_notifier_headnh;
 struct mutexlock;
 +   struct usb_charger  *uchger;


Why not simply call the field 'charger'? :-)

I think 'uchger' is the abbreviation of 'usb charger' which is maybe a
little verbous, I'll change it. Thanks for your comments.


 [...]

 WBR, Sergei




-- 
Baolin.wang
Best Regards
--
To unsubscribe from this list: send the line unsubscribe linux-usb in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v4 5/5] power: wm831x_power: Support USB charger current limit management

2015-08-19 Thread Baolin Wang
On 19 August 2015 at 17:56, Lee Jones lee.jo...@linaro.org wrote:
 On Wed, 19 Aug 2015, Baolin Wang wrote:

 Integrate with the newly added USB charger interface to limit the current
 we draw from the USB input based on the input device configuration
 identified by the USB stack, allowing us to charge more quickly from high
 current inputs without drawing more current than specified from others.

 Signed-off-by: Mark Brown broo...@kernel.org
 Signed-off-by: Baolin Wang baolin.w...@linaro.org
 ---
  drivers/power/wm831x_power.c |   69 
 ++
  include/linux/mfd/wm831x/pdata.h |3 ++

 I'm not going to keep reviewing this.  You should carry forward any
 Acks received onto subsequent submissions yourself.


OK, thanks.

  2 files changed, 72 insertions(+)

 diff --git a/drivers/power/wm831x_power.c b/drivers/power/wm831x_power.c
 index db11ae6..72c661f 100644
 --- a/drivers/power/wm831x_power.c
 +++ b/drivers/power/wm831x_power.c
 @@ -13,6 +13,7 @@
  #include linux/platform_device.h
  #include linux/power_supply.h
  #include linux/slab.h
 +#include linux/usb/usb_charger.h

  #include linux/mfd/wm831x/core.h
  #include linux/mfd/wm831x/auxadc.h
 @@ -31,6 +32,8 @@ struct wm831x_power {
   char usb_name[20];
   char battery_name[20];
   bool have_battery;
 + struct usb_charger *usb_charger;
 + struct notifier_block usb_notify;
  };

  static int wm831x_power_check_online(struct wm831x *wm831x, int supply,
 @@ -125,6 +128,43 @@ static enum power_supply_property wm831x_usb_props[] = {
   POWER_SUPPLY_PROP_VOLTAGE_NOW,
  };

 +/* In miliamps */
 +static unsigned int wm831x_usb_limits[] = {
 + 0,
 + 2,
 + 100,
 + 500,
 + 900,
 + 1500,
 + 1800,
 + 550,
 +};
 +
 +static int wm831x_usb_limit_change(struct notifier_block *nb,
 +unsigned long limit, void *data)
 +{
 + struct wm831x_power *wm831x_power = container_of(nb,
 +  struct wm831x_power,
 +  usb_notify);
 + int i, best;
 +
 + /* Find the highest supported limit */
 + best = 0;
 + for (i = 0; i  ARRAY_SIZE(wm831x_usb_limits); i++) {
 + if (limit  wm831x_usb_limits[i] 
 + wm831x_usb_limits[best]  wm831x_usb_limits[i])
 + best = i;
 + }
 +
 + dev_dbg(wm831x_power-wm831x-dev,
 + Limiting USB current to %dmA, wm831x_usb_limits[best]);
 +
 + wm831x_set_bits(wm831x_power-wm831x, WM831X_POWER_STATE,
 + WM831X_USB_ILIM_MASK, best);
 +
 + return 0;
 +}
 +
  /*
   *   Battery properties
   */
 @@ -606,8 +646,31 @@ static int wm831x_power_probe(struct platform_device 
 *pdev)
   }
   }

 + if (wm831x_pdata  wm831x_pdata-usb_gadget) {
 + power-usb_charger =
 + usb_charger_find_by_name(wm831x_pdata-usb_gadget);
 + if (IS_ERR(power-usb_charger)) {
 + ret = PTR_ERR(power-usb_charger);
 + dev_err(pdev-dev,
 + Failed to find USB gadget: %d\n, ret);
 + goto err_bat_irq;
 + }
 +
 + power-usb_notify.notifier_call = wm831x_usb_limit_change;
 +
 + ret = usb_charger_register_notify(power-usb_charger,
 +   power-usb_notify);
 + if (ret != 0) {
 + dev_err(pdev-dev,
 + Failed to register notifier: %d\n, ret);
 + goto err_usb_charger;
 + }
 + }
 +
   return ret;

 +err_usb_charger:
 + usb_charger_put(power-usb_charger);
  err_bat_irq:
   --i;
   for (; i = 0; i--) {
 @@ -637,6 +700,12 @@ static int wm831x_power_remove(struct platform_device 
 *pdev)
   struct wm831x *wm831x = wm831x_power-wm831x;
   int irq, i;

 + if (wm831x_power-usb_charger) {
 + usb_charger_unregister_notify(wm831x_power-usb_charger,
 +   wm831x_power-usb_notify);
 + usb_charger_put(wm831x_power-usb_charger);
 + }
 +
   for (i = 0; i  ARRAY_SIZE(wm831x_bat_irqs); i++) {
   irq = wm831x_irq(wm831x,
platform_get_irq_byname(pdev,
 diff --git a/include/linux/mfd/wm831x/pdata.h 
 b/include/linux/mfd/wm831x/pdata.h
 index dcc9631..5af8399 100644
 --- a/include/linux/mfd/wm831x/pdata.h
 +++ b/include/linux/mfd/wm831x/pdata.h
 @@ -126,6 +126,9 @@ struct wm831x_pdata {
   /** The driver should initiate a power off sequence during shutdown */
   bool soft_shutdown;

 + /** dev_name of USB charger gadget to integrate with */
 + const char *usb_gadget;
 +
   int

[PATCH v4 3/5] gadget: Support for the usb charger framework

2015-08-20 Thread Baolin Wang
For supporting the usb charger, it adds the usb_charger_init() and
usb_charger_exit() functions for usb charger initialization and exit.

Introduce a callback 'get_charger_type' which will implemented by
user for usb gadget operations to get the usb charger type.

Signed-off-by: Baolin Wang baolin.w...@linaro.org
---
 drivers/usb/gadget/udc/udc-core.c |8 
 include/linux/usb/gadget.h|2 ++
 2 files changed, 10 insertions(+)

diff --git a/drivers/usb/gadget/udc/udc-core.c 
b/drivers/usb/gadget/udc/udc-core.c
index 4238fc3..370376e 100644
--- a/drivers/usb/gadget/udc/udc-core.c
+++ b/drivers/usb/gadget/udc/udc-core.c
@@ -28,6 +28,7 @@
 #include linux/usb/ch9.h
 #include linux/usb/gadget.h
 #include linux/usb.h
+#include linux/usb/usb_charger.h
 
 /**
  * struct usb_udc - describes one usb device controller
@@ -437,8 +438,14 @@ int usb_add_gadget_udc_release(struct device *parent, 
struct usb_gadget *gadget,
 
mutex_unlock(udc_lock);
 
+   ret = usb_charger_init(gadget);
+   if (ret)
+   goto err5;
+
return 0;
 
+err5:
+   device_del(udc-dev);
 err4:
list_del(udc-list);
mutex_unlock(udc_lock);
@@ -513,6 +520,7 @@ void usb_del_gadget_udc(struct usb_gadget *gadget)
kobject_uevent(udc-dev.kobj, KOBJ_REMOVE);
flush_work(gadget-work);
device_unregister(udc-dev);
+   usb_charger_exit(gadget);
device_unregister(gadget-dev);
 }
 EXPORT_SYMBOL_GPL(usb_del_gadget_udc);
diff --git a/include/linux/usb/gadget.h b/include/linux/usb/gadget.h
index 755e8bc..451ad32 100644
--- a/include/linux/usb/gadget.h
+++ b/include/linux/usb/gadget.h
@@ -537,6 +537,7 @@ struct usb_gadget_ops {
struct usb_ep *(*match_ep)(struct usb_gadget *,
struct usb_endpoint_descriptor *,
struct usb_ss_ep_comp_descriptor *);
+   enum usb_charger_type (*get_charger_type)(struct usb_gadget *);
 };
 
 /**
@@ -611,6 +612,7 @@ struct usb_gadget {
struct usb_otg_caps *otg_caps;
struct raw_notifier_headnh;
struct mutexlock;
+   struct usb_charger  *charger;
 
unsignedsg_supported:1;
unsignedis_otg:1;
-- 
1.7.9.5

--
To unsubscribe from this list: send the line unsubscribe linux-usb in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v4 5/5] power: wm831x_power: Support USB charger current limit management

2015-08-20 Thread Baolin Wang
Integrate with the newly added USB charger interface to limit the current
we draw from the USB input based on the input device configuration
identified by the USB stack, allowing us to charge more quickly from high
current inputs without drawing more current than specified from others.

Signed-off-by: Mark Brown broo...@kernel.org
Signed-off-by: Baolin Wang baolin.w...@linaro.org
Acked-by: Lee Jones lee.jo...@linaro.org
Acked-by: Charles Keepax ckee...@opensource.wolfsonmicro.com
Acked-by: Peter Chen peter.c...@freescale.com
---
 drivers/power/wm831x_power.c |   69 ++
 include/linux/mfd/wm831x/pdata.h |3 ++
 2 files changed, 72 insertions(+)

diff --git a/drivers/power/wm831x_power.c b/drivers/power/wm831x_power.c
index db11ae6..33ae27a 100644
--- a/drivers/power/wm831x_power.c
+++ b/drivers/power/wm831x_power.c
@@ -13,6 +13,7 @@
 #include linux/platform_device.h
 #include linux/power_supply.h
 #include linux/slab.h
+#include linux/usb/usb_charger.h
 
 #include linux/mfd/wm831x/core.h
 #include linux/mfd/wm831x/auxadc.h
@@ -31,6 +32,8 @@ struct wm831x_power {
char usb_name[20];
char battery_name[20];
bool have_battery;
+   struct usb_charger *usb_charger;
+   struct notifier_block usb_notify;
 };
 
 static int wm831x_power_check_online(struct wm831x *wm831x, int supply,
@@ -125,6 +128,43 @@ static enum power_supply_property wm831x_usb_props[] = {
POWER_SUPPLY_PROP_VOLTAGE_NOW,
 };
 
+/* In milliamps */
+static unsigned int wm831x_usb_limits[] = {
+   0,
+   2,
+   100,
+   500,
+   900,
+   1500,
+   1800,
+   550,
+};
+
+static int wm831x_usb_limit_change(struct notifier_block *nb,
+  unsigned long limit, void *data)
+{
+   struct wm831x_power *wm831x_power = container_of(nb,
+struct wm831x_power,
+usb_notify);
+   int i, best;
+
+   /* Find the highest supported limit */
+   best = 0;
+   for (i = 0; i  ARRAY_SIZE(wm831x_usb_limits); i++) {
+   if (limit = wm831x_usb_limits[i] 
+   wm831x_usb_limits[best]  wm831x_usb_limits[i])
+   best = i;
+   }
+
+   dev_dbg(wm831x_power-wm831x-dev,
+   Limiting USB current to %dmA, wm831x_usb_limits[best]);
+
+   wm831x_set_bits(wm831x_power-wm831x, WM831X_POWER_STATE,
+   WM831X_USB_ILIM_MASK, best);
+
+   return 0;
+}
+
 /*
  * Battery properties
  */
@@ -606,8 +646,31 @@ static int wm831x_power_probe(struct platform_device *pdev)
}
}
 
+   if (wm831x_pdata  wm831x_pdata-usb_gadget) {
+   power-usb_charger =
+   usb_charger_find_by_name(wm831x_pdata-usb_gadget);
+   if (IS_ERR(power-usb_charger)) {
+   ret = PTR_ERR(power-usb_charger);
+   dev_err(pdev-dev,
+   Failed to find USB gadget: %d\n, ret);
+   goto err_bat_irq;
+   }
+
+   power-usb_notify.notifier_call = wm831x_usb_limit_change;
+
+   ret = usb_charger_register_notify(power-usb_charger,
+ power-usb_notify);
+   if (ret != 0) {
+   dev_err(pdev-dev,
+   Failed to register notifier: %d\n, ret);
+   goto err_usb_charger;
+   }
+   }
+
return ret;
 
+err_usb_charger:
+   /* put_device on charger */
 err_bat_irq:
--i;
for (; i = 0; i--) {
@@ -637,6 +700,12 @@ static int wm831x_power_remove(struct platform_device 
*pdev)
struct wm831x *wm831x = wm831x_power-wm831x;
int irq, i;
 
+   if (wm831x_power-usb_charger) {
+   usb_charger_unregister_notify(wm831x_power-usb_charger,
+ wm831x_power-usb_notify);
+   /* Free charger */
+   }
+
for (i = 0; i  ARRAY_SIZE(wm831x_bat_irqs); i++) {
irq = wm831x_irq(wm831x, 
 platform_get_irq_byname(pdev,
diff --git a/include/linux/mfd/wm831x/pdata.h b/include/linux/mfd/wm831x/pdata.h
index dcc9631..5af8399 100644
--- a/include/linux/mfd/wm831x/pdata.h
+++ b/include/linux/mfd/wm831x/pdata.h
@@ -126,6 +126,9 @@ struct wm831x_pdata {
/** The driver should initiate a power off sequence during shutdown */
bool soft_shutdown;
 
+   /** dev_name of USB charger gadget to integrate with */
+   const char *usb_gadget;
+
int irq_base;
int gpio_base;
int gpio_defaults[WM831X_GPIO_NUM];
-- 
1.7.9.5

--
To unsubscribe from

[PATCH v4 4/5] gadget: Integrate with the usb gadget supporting for usb charger

2015-08-20 Thread Baolin Wang
When the usb gadget supporting for usb charger is ready, the usb charger
should get the type by the 'get_charger_type' callback which is implemented
by the usb gadget operations, and get the usb charger pointer from struct
'usb_gadget'.

Signed-off-by: Baolin Wang baolin.w...@linaro.org
---
 drivers/usb/gadget/charger.c |   13 +++--
 1 file changed, 11 insertions(+), 2 deletions(-)

diff --git a/drivers/usb/gadget/charger.c b/drivers/usb/gadget/charger.c
index 35b46c1..a919f38 100644
--- a/drivers/usb/gadget/charger.c
+++ b/drivers/usb/gadget/charger.c
@@ -181,6 +181,13 @@ int usb_charger_unregister_notify(struct usb_charger 
*uchger,
 enum usb_charger_type
 usb_charger_detect_type(struct usb_charger *uchger)
 {
+   if (uchger-gadget  uchger-gadget-ops
+uchger-gadget-ops-get_charger_type)
+   uchger-type =
+   uchger-gadget-ops-get_charger_type(uchger-gadget);
+   else
+   uchger-type = UNKNOWN_TYPE;
+
return uchger-type;
 }
 
@@ -313,7 +320,8 @@ static int
 usb_charger_plug_by_gadget(struct notifier_block *nb,
   unsigned long state, void *data)
 {
-   struct usb_charger *uchger = NULL;
+   struct usb_gadget *gadget = (struct usb_gadget *)data;
+   struct usb_charger *uchger = gadget-charger;
enum usb_charger_state uchger_state;
 
if (!uchger)
@@ -480,6 +488,7 @@ int usb_charger_init(struct usb_gadget *ugadget)
 
/* register a notifier on a usb gadget device */
uchger-gadget = ugadget;
+   ugadget-charger = uchger;
uchger-old_gadget_state = ugadget-state;
uchger-gadget_nb.notifier_call = usb_charger_plug_by_gadget;
usb_gadget_register_notify(ugadget, uchger-gadget_nb);
@@ -503,7 +512,7 @@ fail:
 
 int usb_charger_exit(struct usb_gadget *ugadget)
 {
-   struct usb_charger *uchger = NULL;
+   struct usb_charger *uchger = ugadget-charger;
 
if (!uchger)
return -EINVAL;
-- 
1.7.9.5

--
To unsubscribe from this list: send the line unsubscribe linux-usb in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v2 3/3] power: wm831x_power: Support USB charger current limit management

2015-08-20 Thread Baolin Wang
On 20 August 2015 at 17:02, David Laight david.lai...@aculab.com wrote:
 From: Baolin Wang
 Sent: 14 August 2015 10:48
 +/* In miliamps */

 Spelling police: milliamps


Hi David,

I'll correct it in next patch series. Thanks for your comments.

 +static unsigned int wm831x_usb_limits[] = {
 + 0,
 + 2,
 + 100,
 + 500,
 + 900,
 + 1500,
 + 1800,
 + 550,
 +};

 David




-- 
Baolin.wang
Best Regards
--
To unsubscribe from this list: send the line unsubscribe linux-usb in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v3 1/3] gadget: Support for the usb charger framework

2015-08-18 Thread Baolin Wang
On 19 August 2015 at 00:04, Greg KH gre...@linuxfoundation.org wrote:
 On Tue, Aug 18, 2015 at 07:14:19PM +0800, Baolin Wang wrote:
 The usb charger framework is based on usb gadget, and each usb gadget
 can be one usb charger to set the current limitation.

 This patch adds a notifier mechanism for usb charger to report to usb
 charger when the usb gadget state is changed.

 Also we introduce a callback 'get_charger_type' which will implemented
 by user for usb gadget operations to get the usb charger type.

 Signed-off-by: Baolin Wang baolin.w...@linaro.org
 ---
  drivers/usb/gadget/udc/udc-core.c |   41 
 -
  include/linux/usb/gadget.h|   20 ++
  2 files changed, 60 insertions(+), 1 deletion(-)

 diff --git a/drivers/usb/gadget/udc/udc-core.c 
 b/drivers/usb/gadget/udc/udc-core.c
 index f660afb..1971218 100644
 --- a/drivers/usb/gadget/udc/udc-core.c
 +++ b/drivers/usb/gadget/udc/udc-core.c
 @@ -28,6 +28,7 @@
  #include linux/usb/ch9.h
  #include linux/usb/gadget.h
  #include linux/usb.h
 +#include linux/usb/usb_charger.h

 You just broke the build, which proves you did not properly test this
 patch series, so why should we even consider it?


Oh, I'm very sorry about that. I'll re-check my patch and test it
carefully. Thanks for your comments.

 greg k-h



-- 
Baolin.wang
Best Regards
--
To unsubscribe from this list: send the line unsubscribe linux-usb in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v4 2/5] gadget: Introduce the usb charger framework

2015-08-19 Thread Baolin Wang
This patch introduces the usb charger driver based on usb gadget that
makes an enhancement to a power driver. It works well in practice but
that requires a system with suitable hardware.

The basic conception of the usb charger is that, when one usb charger
is added or removed by reporting from the usb gadget state change or
the extcon device state change, the usb charger will report to power
user to set the current limitation.

The usb charger will register notifiees on the usb gadget or the extcon
device to get notified the usb charger state.

Power user will register a notifiee on the usb charger to get notified
by status changes from the usb charger. It will report to power user
to set the current limitation when detecting the usb charger is added
or removed from extcon device state or usb gadget state.

Signed-off-by: Baolin Wang baolin.w...@linaro.org
---
 drivers/usb/gadget/Kconfig  |7 +
 drivers/usb/gadget/Makefile |1 +
 drivers/usb/gadget/charger.c|  529 +++
 include/linux/usb/usb_charger.h |  138 ++
 4 files changed, 675 insertions(+)
 create mode 100644 drivers/usb/gadget/charger.c
 create mode 100644 include/linux/usb/usb_charger.h

diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig
index bcf83c0..3d2b959 100644
--- a/drivers/usb/gadget/Kconfig
+++ b/drivers/usb/gadget/Kconfig
@@ -127,6 +127,13 @@ config USB_GADGET_STORAGE_NUM_BUFFERS
   a module parameter as well.
   If unsure, say 2.
 
+config USB_CHARGER
+   bool USB charger support
+   help
+ The usb charger driver based on the usb gadget that makes an
+ enhancement to a power driver which can set the current limitation
+ when the usb charger is added or removed.
+
 source drivers/usb/gadget/udc/Kconfig
 
 #
diff --git a/drivers/usb/gadget/Makefile b/drivers/usb/gadget/Makefile
index 598a67d..1e421c1 100644
--- a/drivers/usb/gadget/Makefile
+++ b/drivers/usb/gadget/Makefile
@@ -10,3 +10,4 @@ libcomposite-y:= usbstring.o config.o 
epautoconf.o
 libcomposite-y += composite.o functions.o configfs.o u_f.o
 
 obj-$(CONFIG_USB_GADGET)   += udc/ function/ legacy/
+obj-$(CONFIG_USB_CHARGER)  += charger.o
diff --git a/drivers/usb/gadget/charger.c b/drivers/usb/gadget/charger.c
new file mode 100644
index 000..35b46c1
--- /dev/null
+++ b/drivers/usb/gadget/charger.c
@@ -0,0 +1,529 @@
+/*
+ * charger.c -- USB charger driver
+ *
+ * Copyright (C) 2015 Linaro Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include linux/device.h
+#include linux/err.h
+#include linux/extcon.h
+#include linux/export.h
+#include linux/kernel.h
+#include linux/module.h
+#include linux/of.h
+#include linux/of_device.h
+#include linux/of_address.h
+#include linux/platform_device.h
+#include linux/slab.h
+#include linux/usb.h
+#include linux/usb/ch9.h
+#include linux/usb/gadget.h
+#include linux/usb/usb_charger.h
+
+#define DEFAULT_CUR_PROTECT(50)
+#define DEFAULT_SDP_CUR_LIMIT  (500 - DEFAULT_CUR_PROTECT)
+#define DEFAULT_DCP_CUR_LIMIT  (1500 - DEFAULT_CUR_PROTECT)
+#define DEFAULT_CDP_CUR_LIMIT  (1500 - DEFAULT_CUR_PROTECT)
+#define DEFAULT_ACA_CUR_LIMIT  (1500 - DEFAULT_CUR_PROTECT)
+
+static DEFINE_IDA(usb_charger_ida);
+static struct bus_type usb_charger_subsys = {
+   .name   = usb-charger,
+   .dev_name   = usb-charger,
+};
+
+static struct usb_charger *dev_to_uchger(struct device *udev)
+{
+   return container_of(udev, struct usb_charger, dev);
+}
+
+static ssize_t cur_limit_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+   struct usb_charger *uchger = dev_to_uchger(dev);
+
+   return scnprintf(buf, PAGE_SIZE, %d %d %d %d\n,
+uchger-cur_limit.sdp_cur_limit,
+uchger-cur_limit.dcp_cur_limit,
+uchger-cur_limit.cdp_cur_limit,
+uchger-cur_limit.aca_cur_limit);
+}
+
+static ssize_t cur_limit_store(struct device *dev,
+  struct device_attribute *attr,
+  const char *buf, size_t count)
+{
+   struct usb_charger *uchger = dev_to_uchger(dev);
+   struct usb_charger_cur_limit cur;
+   int ret;
+
+   ret = sscanf(buf, %d %d %d %d,
+cur.sdp_cur_limit, cur.dcp_cur_limit,
+cur.cdp_cur_limit, cur.aca_cur_limit);
+   if (ret == 0)
+   return -EINVAL;
+
+   ret = usb_charger_set_cur_limit(uchger, cur);
+   if (ret  0)
+   return ret;
+
+   return count;
+}
+static DEVICE_ATTR_RW(cur_limit);
+
+static struct attribute *usb_charger_attrs[] = {
+   dev_attr_cur_limit.attr,
+   NULL

[PATCH v4 3/5] gadget: Support for the usb charger framework

2015-08-19 Thread Baolin Wang
For supporting the usb charger, it adds the usb_charger_init() and
usb_charger_exit() functions for usb charger initialization and exit.

Introduce a callback 'get_charger_type' which will implemented by
user for usb gadget operations to get the usb charger type.

Signed-off-by: Baolin Wang baolin.w...@linaro.org
---
 drivers/usb/gadget/udc/udc-core.c |8 
 include/linux/usb/gadget.h|2 ++
 2 files changed, 10 insertions(+)

diff --git a/drivers/usb/gadget/udc/udc-core.c 
b/drivers/usb/gadget/udc/udc-core.c
index 4238fc3..370376e 100644
--- a/drivers/usb/gadget/udc/udc-core.c
+++ b/drivers/usb/gadget/udc/udc-core.c
@@ -28,6 +28,7 @@
 #include linux/usb/ch9.h
 #include linux/usb/gadget.h
 #include linux/usb.h
+#include linux/usb/usb_charger.h
 
 /**
  * struct usb_udc - describes one usb device controller
@@ -437,8 +438,14 @@ int usb_add_gadget_udc_release(struct device *parent, 
struct usb_gadget *gadget,
 
mutex_unlock(udc_lock);
 
+   ret = usb_charger_init(gadget);
+   if (ret)
+   goto err5;
+
return 0;
 
+err5:
+   device_del(udc-dev);
 err4:
list_del(udc-list);
mutex_unlock(udc_lock);
@@ -513,6 +520,7 @@ void usb_del_gadget_udc(struct usb_gadget *gadget)
kobject_uevent(udc-dev.kobj, KOBJ_REMOVE);
flush_work(gadget-work);
device_unregister(udc-dev);
+   usb_charger_exit(gadget);
device_unregister(gadget-dev);
 }
 EXPORT_SYMBOL_GPL(usb_del_gadget_udc);
diff --git a/include/linux/usb/gadget.h b/include/linux/usb/gadget.h
index 755e8bc..44d82f5 100644
--- a/include/linux/usb/gadget.h
+++ b/include/linux/usb/gadget.h
@@ -537,6 +537,7 @@ struct usb_gadget_ops {
struct usb_ep *(*match_ep)(struct usb_gadget *,
struct usb_endpoint_descriptor *,
struct usb_ss_ep_comp_descriptor *);
+   enum usb_charger_type   (*get_charger_type)(struct usb_gadget *);
 };
 
 /**
@@ -611,6 +612,7 @@ struct usb_gadget {
struct usb_otg_caps *otg_caps;
struct raw_notifier_headnh;
struct mutexlock;
+   struct usb_charger  *uchger;
 
unsignedsg_supported:1;
unsignedis_otg:1;
-- 
1.7.9.5

--
To unsubscribe from this list: send the line unsubscribe linux-usb in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v4 4/5] gadget: Integrate with the usb gadget supporting for usb charger

2015-08-19 Thread Baolin Wang
When the usb gadget supporting for usb charger is ready, the usb charger
should get the type by the 'get_charger_type' callback which is implemented
by the usb gadget operations, and get the usb charger pointer from struct
'usb_gadget'.

Signed-off-by: Baolin Wang baolin.w...@linaro.org
---
 drivers/usb/gadget/charger.c |   13 +++--
 1 file changed, 11 insertions(+), 2 deletions(-)

diff --git a/drivers/usb/gadget/charger.c b/drivers/usb/gadget/charger.c
index 35b46c1..93fd36f 100644
--- a/drivers/usb/gadget/charger.c
+++ b/drivers/usb/gadget/charger.c
@@ -181,6 +181,13 @@ int usb_charger_unregister_notify(struct usb_charger 
*uchger,
 enum usb_charger_type
 usb_charger_detect_type(struct usb_charger *uchger)
 {
+   if (uchger-gadget  uchger-gadget-ops
+uchger-gadget-ops-get_charger_type)
+   uchger-type =
+   uchger-gadget-ops-get_charger_type(uchger-gadget);
+   else
+   uchger-type = UNKNOWN_TYPE;
+
return uchger-type;
 }
 
@@ -313,7 +320,8 @@ static int
 usb_charger_plug_by_gadget(struct notifier_block *nb,
   unsigned long state, void *data)
 {
-   struct usb_charger *uchger = NULL;
+   struct usb_gadget *gadget = (struct usb_gadget *)data;
+   struct usb_charger *uchger = gadget-uchger;
enum usb_charger_state uchger_state;
 
if (!uchger)
@@ -480,6 +488,7 @@ int usb_charger_init(struct usb_gadget *ugadget)
 
/* register a notifier on a usb gadget device */
uchger-gadget = ugadget;
+   ugadget-uchger = uchger;
uchger-old_gadget_state = ugadget-state;
uchger-gadget_nb.notifier_call = usb_charger_plug_by_gadget;
usb_gadget_register_notify(ugadget, uchger-gadget_nb);
@@ -503,7 +512,7 @@ fail:
 
 int usb_charger_exit(struct usb_gadget *ugadget)
 {
-   struct usb_charger *uchger = NULL;
+   struct usb_charger *uchger = ugadget-uchger;
 
if (!uchger)
return -EINVAL;
-- 
1.7.9.5

--
To unsubscribe from this list: send the line unsubscribe linux-usb in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v4 1/5] gadget: Introduce the notifier functions

2015-08-19 Thread Baolin Wang
The usb charger framework is based on usb gadget. The usb charger
need to be notified the state changing of usb gadget to confirm the
usb charger state.

Thus this patch adds a notifier mechanism for usb gadget to report a
event to usb charger when the usb gadget state is changed.

Signed-off-by: Baolin Wang baolin.w...@linaro.org
---
 drivers/usb/gadget/udc/udc-core.c |   32 
 include/linux/usb/gadget.h|   18 ++
 2 files changed, 50 insertions(+)

diff --git a/drivers/usb/gadget/udc/udc-core.c 
b/drivers/usb/gadget/udc/udc-core.c
index f660afb..4238fc3 100644
--- a/drivers/usb/gadget/udc/udc-core.c
+++ b/drivers/usb/gadget/udc/udc-core.c
@@ -129,6 +129,32 @@ void usb_gadget_giveback_request(struct usb_ep *ep,
 }
 EXPORT_SYMBOL_GPL(usb_gadget_giveback_request);
 
+int usb_gadget_register_notify(struct usb_gadget *gadget,
+  struct notifier_block *nb)
+{
+   int ret;
+
+   mutex_lock(gadget-lock);
+   ret = raw_notifier_chain_register(gadget-nh, nb);
+   mutex_unlock(gadget-lock);
+
+   return ret;
+}
+EXPORT_SYMBOL_GPL(usb_gadget_register_notify);
+
+int usb_gadget_unregister_notify(struct usb_gadget *gadget,
+struct notifier_block *nb)
+{
+   int ret;
+
+   mutex_lock(gadget-lock);
+   ret = raw_notifier_chain_unregister(gadget-nh, nb);
+   mutex_unlock(gadget-lock);
+
+   return ret;
+}
+EXPORT_SYMBOL_GPL(usb_gadget_unregister_notify);
+
 /* - */
 
 /**
@@ -226,6 +252,10 @@ static void usb_gadget_state_work(struct work_struct *work)
struct usb_gadget *gadget = work_to_gadget(work);
struct usb_udc *udc = gadget-udc;
 
+   mutex_lock(gadget-lock);
+   raw_notifier_call_chain(gadget-nh, gadget-state, gadget);
+   mutex_unlock(gadget-lock);
+
if (udc)
sysfs_notify(udc-dev.kobj, NULL, state);
 }
@@ -364,6 +394,8 @@ int usb_add_gadget_udc_release(struct device *parent, 
struct usb_gadget *gadget,
 
dev_set_name(gadget-dev, gadget);
INIT_WORK(gadget-work, usb_gadget_state_work);
+   RAW_INIT_NOTIFIER_HEAD(gadget-nh);
+   mutex_init(gadget-lock);
gadget-dev.parent = parent;
 
 #ifdef CONFIG_HAS_DMA
diff --git a/include/linux/usb/gadget.h b/include/linux/usb/gadget.h
index c14a69b..755e8bc 100644
--- a/include/linux/usb/gadget.h
+++ b/include/linux/usb/gadget.h
@@ -609,6 +609,8 @@ struct usb_gadget {
unsignedout_epnum;
unsignedin_epnum;
struct usb_otg_caps *otg_caps;
+   struct raw_notifier_headnh;
+   struct mutexlock;
 
unsignedsg_supported:1;
unsignedis_otg:1;
@@ -1183,6 +1185,22 @@ extern void usb_gadget_unmap_request(struct usb_gadget 
*gadget,
 
 /*-*/
 
+/**
+ * Register a notifiee to get notified by any attach status changes from
+ * the usb gadget
+ */
+int usb_gadget_register_notify(struct usb_gadget *gadget,
+  struct notifier_block *nb);
+
+/*-*/
+
+
+/* Unregister a notifiee from the usb gadget */
+int usb_gadget_unregister_notify(struct usb_gadget *gadget,
+struct notifier_block *nb);
+
+/*-*/
+
 /* utility to set gadget state properly */
 
 extern void usb_gadget_set_state(struct usb_gadget *gadget,
-- 
1.7.9.5

--
To unsubscribe from this list: send the line unsubscribe linux-usb in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v4 0/5] Introduce usb charger framework to deal with the usb gadget power negotation

2015-08-19 Thread Baolin Wang
Currently the Linux kernel does not provide any standard integration of this
feature that integrates the USB subsystem with the system power regulation
provided by PMICs meaning that either vendors must add this in their kernels
or USB gadget devices based on Linux (such as mobile phones) may not behave
as they should.

Providing a standard framework for doing this in the kernel.

Now introduce one user with wm831x_power to support and test the usb charger,
which is pending testing. Moreover there may be other potential users will use
it in future.

Changes since v3:
 - Re-order the patch and split the patch to avoid breaking build.
 - Other modifications.

Baolin Wang (5):
  gadget: Introduce the notifier functions
  gadget: Introduce the usb charger framework
  gadget: Support for the usb charger framework
  gadget: Integrate with the usb gadget supporting for usb charger
  power: wm831x_power: Support USB charger current limit management

 drivers/power/wm831x_power.c  |   69 +
 drivers/usb/gadget/Kconfig|7 +
 drivers/usb/gadget/Makefile   |1 +
 drivers/usb/gadget/charger.c  |  538 +
 drivers/usb/gadget/udc/udc-core.c |   40 +++
 include/linux/mfd/wm831x/pdata.h  |3 +
 include/linux/usb/gadget.h|   20 ++
 include/linux/usb/usb_charger.h   |  138 ++
 8 files changed, 816 insertions(+)
 create mode 100644 drivers/usb/gadget/charger.c
 create mode 100644 include/linux/usb/usb_charger.h

-- 
1.7.9.5

--
To unsubscribe from this list: send the line unsubscribe linux-usb in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v4 5/5] power: wm831x_power: Support USB charger current limit management

2015-08-19 Thread Baolin Wang
Integrate with the newly added USB charger interface to limit the current
we draw from the USB input based on the input device configuration
identified by the USB stack, allowing us to charge more quickly from high
current inputs without drawing more current than specified from others.

Signed-off-by: Mark Brown broo...@kernel.org
Signed-off-by: Baolin Wang baolin.w...@linaro.org
---
 drivers/power/wm831x_power.c |   69 ++
 include/linux/mfd/wm831x/pdata.h |3 ++
 2 files changed, 72 insertions(+)

diff --git a/drivers/power/wm831x_power.c b/drivers/power/wm831x_power.c
index db11ae6..72c661f 100644
--- a/drivers/power/wm831x_power.c
+++ b/drivers/power/wm831x_power.c
@@ -13,6 +13,7 @@
 #include linux/platform_device.h
 #include linux/power_supply.h
 #include linux/slab.h
+#include linux/usb/usb_charger.h
 
 #include linux/mfd/wm831x/core.h
 #include linux/mfd/wm831x/auxadc.h
@@ -31,6 +32,8 @@ struct wm831x_power {
char usb_name[20];
char battery_name[20];
bool have_battery;
+   struct usb_charger *usb_charger;
+   struct notifier_block usb_notify;
 };
 
 static int wm831x_power_check_online(struct wm831x *wm831x, int supply,
@@ -125,6 +128,43 @@ static enum power_supply_property wm831x_usb_props[] = {
POWER_SUPPLY_PROP_VOLTAGE_NOW,
 };
 
+/* In miliamps */
+static unsigned int wm831x_usb_limits[] = {
+   0,
+   2,
+   100,
+   500,
+   900,
+   1500,
+   1800,
+   550,
+};
+
+static int wm831x_usb_limit_change(struct notifier_block *nb,
+  unsigned long limit, void *data)
+{
+   struct wm831x_power *wm831x_power = container_of(nb,
+struct wm831x_power,
+usb_notify);
+   int i, best;
+
+   /* Find the highest supported limit */
+   best = 0;
+   for (i = 0; i  ARRAY_SIZE(wm831x_usb_limits); i++) {
+   if (limit  wm831x_usb_limits[i] 
+   wm831x_usb_limits[best]  wm831x_usb_limits[i])
+   best = i;
+   }
+
+   dev_dbg(wm831x_power-wm831x-dev,
+   Limiting USB current to %dmA, wm831x_usb_limits[best]);
+
+   wm831x_set_bits(wm831x_power-wm831x, WM831X_POWER_STATE,
+   WM831X_USB_ILIM_MASK, best);
+
+   return 0;
+}
+
 /*
  * Battery properties
  */
@@ -606,8 +646,31 @@ static int wm831x_power_probe(struct platform_device *pdev)
}
}
 
+   if (wm831x_pdata  wm831x_pdata-usb_gadget) {
+   power-usb_charger =
+   usb_charger_find_by_name(wm831x_pdata-usb_gadget);
+   if (IS_ERR(power-usb_charger)) {
+   ret = PTR_ERR(power-usb_charger);
+   dev_err(pdev-dev,
+   Failed to find USB gadget: %d\n, ret);
+   goto err_bat_irq;
+   }
+
+   power-usb_notify.notifier_call = wm831x_usb_limit_change;
+
+   ret = usb_charger_register_notify(power-usb_charger,
+ power-usb_notify);
+   if (ret != 0) {
+   dev_err(pdev-dev,
+   Failed to register notifier: %d\n, ret);
+   goto err_usb_charger;
+   }
+   }
+
return ret;
 
+err_usb_charger:
+   usb_charger_put(power-usb_charger);
 err_bat_irq:
--i;
for (; i = 0; i--) {
@@ -637,6 +700,12 @@ static int wm831x_power_remove(struct platform_device 
*pdev)
struct wm831x *wm831x = wm831x_power-wm831x;
int irq, i;
 
+   if (wm831x_power-usb_charger) {
+   usb_charger_unregister_notify(wm831x_power-usb_charger,
+ wm831x_power-usb_notify);
+   usb_charger_put(wm831x_power-usb_charger);
+   }
+
for (i = 0; i  ARRAY_SIZE(wm831x_bat_irqs); i++) {
irq = wm831x_irq(wm831x, 
 platform_get_irq_byname(pdev,
diff --git a/include/linux/mfd/wm831x/pdata.h b/include/linux/mfd/wm831x/pdata.h
index dcc9631..5af8399 100644
--- a/include/linux/mfd/wm831x/pdata.h
+++ b/include/linux/mfd/wm831x/pdata.h
@@ -126,6 +126,9 @@ struct wm831x_pdata {
/** The driver should initiate a power off sequence during shutdown */
bool soft_shutdown;
 
+   /** dev_name of USB charger gadget to integrate with */
+   const char *usb_gadget;
+
int irq_base;
int gpio_base;
int gpio_defaults[WM831X_GPIO_NUM];
-- 
1.7.9.5

--
To unsubscribe from this list: send the line unsubscribe linux-usb in
the body of a message to majord...@vger.kernel.org
More majordomo

Re: [PATCH v2 1/3] gadget: Support for the usb charger framework

2015-08-16 Thread Baolin Wang
On 17 August 2015 at 08:40, Peter Chen peter.c...@freescale.com wrote:
 On Fri, Aug 14, 2015 at 05:47:44PM +0800, Baolin Wang wrote:
 The usb charger framework is based on usb gadget, and each usb gadget
 can be one usb charger to set the current limitation.

 This patch adds a notifier mechanism for usb charger to report to usb
 charger when the usb gadget state is changed.

 Also we introduce a callback 'get_charger_type' which will implemented
 by user for usb gadget operations to get the usb charger type.

 Signed-off-by: Baolin Wang baolin.w...@linaro.org
 ---
  drivers/usb/gadget/udc/udc-core.c |   38 
 +
  include/linux/usb/gadget.h|   20 +++
  2 files changed, 58 insertions(+)

 diff --git a/drivers/usb/gadget/udc/udc-core.c 
 b/drivers/usb/gadget/udc/udc-core.c
 index f660afb..47b231c 100644
 --- a/drivers/usb/gadget/udc/udc-core.c
 +++ b/drivers/usb/gadget/udc/udc-core.c
 @@ -28,6 +28,7 @@
  #include linux/usb/ch9.h
  #include linux/usb/gadget.h
  #include linux/usb.h
 +#include linux/usb/usb_charger.h

  /**
   * struct usb_udc - describes one usb device controller
 @@ -129,6 +130,32 @@ void usb_gadget_giveback_request(struct usb_ep *ep,
  }
  EXPORT_SYMBOL_GPL(usb_gadget_giveback_request);

 +int usb_gadget_register_notify(struct usb_gadget *gadget,
 +struct notifier_block *nb)
 +{
 + int ret;
 +
 + mutex_lock(gadget-lock);
 + ret = raw_notifier_chain_register(gadget-nh, nb);
 + mutex_unlock(gadget-lock);
 +
 + return ret;
 +}
 +EXPORT_SYMBOL_GPL(usb_gadget_register_notify);
 +
 +int usb_gadget_unregister_notify(struct usb_gadget *gadget,
 +  struct notifier_block *nb)
 +{
 + int ret;
 +
 + mutex_lock(gadget-lock);
 + ret = raw_notifier_chain_unregister(gadget-nh, nb);
 + mutex_unlock(gadget-lock);
 +
 + return ret;
 +}
 +EXPORT_SYMBOL_GPL(usb_gadget_unregister_notify);
 +
  /* 
 - */

  /**
 @@ -226,6 +253,10 @@ static void usb_gadget_state_work(struct work_struct 
 *work)
   struct usb_gadget *gadget = work_to_gadget(work);
   struct usb_udc *udc = gadget-udc;

 + mutex_lock(gadget-lock);
 + raw_notifier_call_chain(gadget-nh, gadget-state, gadget);
 + mutex_unlock(gadget-lock);
 +
   if (udc)
   sysfs_notify(udc-dev.kobj, NULL, state);
  }
 @@ -364,6 +395,8 @@ int usb_add_gadget_udc_release(struct device *parent, 
 struct usb_gadget *gadget,

   dev_set_name(gadget-dev, gadget);
   INIT_WORK(gadget-work, usb_gadget_state_work);
 + RAW_INIT_NOTIFIER_HEAD(gadget-nh);
 + mutex_init(gadget-lock);
   gadget-dev.parent = parent;

  #ifdef   CONFIG_HAS_DMA
 @@ -405,6 +438,10 @@ int usb_add_gadget_udc_release(struct device *parent, 
 struct usb_gadget *gadget,

   mutex_unlock(udc_lock);

 + ret = usb_charger_init(gadget);
 + if (ret)
 + goto err4;
 +

 If the charger's initialization fails, you may need to
 call device_del(udc-dev).


Yes, I missed that. Thanks for your comments.

 Peter

   return 0;

  err4:
 @@ -481,6 +518,7 @@ void usb_del_gadget_udc(struct usb_gadget *gadget)
   kobject_uevent(udc-dev.kobj, KOBJ_REMOVE);
   flush_work(gadget-work);
   device_unregister(udc-dev);
 + usb_charger_exit(gadget);
   device_unregister(gadget-dev);
  }
  EXPORT_SYMBOL_GPL(usb_del_gadget_udc);
 diff --git a/include/linux/usb/gadget.h b/include/linux/usb/gadget.h
 index c14a69b..78cc862 100644
 --- a/include/linux/usb/gadget.h
 +++ b/include/linux/usb/gadget.h
 @@ -537,6 +537,7 @@ struct usb_gadget_ops {
   struct usb_ep *(*match_ep)(struct usb_gadget *,
   struct usb_endpoint_descriptor *,
   struct usb_ss_ep_comp_descriptor *);
 + enum usb_charger_type   (*get_charger_type)(struct usb_gadget *);
  };

  /**
 @@ -609,6 +610,9 @@ struct usb_gadget {
   unsignedout_epnum;
   unsignedin_epnum;
   struct usb_otg_caps *otg_caps;
 + struct raw_notifier_headnh;
 + struct usb_charger  *uchger;
 + struct mutexlock;

   unsignedsg_supported:1;
   unsignedis_otg:1;
 @@ -1183,6 +1187,22 @@ extern void usb_gadget_unmap_request(struct 
 usb_gadget *gadget,

  
 /*-*/

 +/**
 + * Register a notifiee to get notified by any attach status changes from
 + * the usb gadget
 + */
 +int usb_gadget_register_notify(struct usb_gadget *gadget,
 +struct notifier_block *nb);
 +
 +/*-*/
 +
 +
 +/* Unregister a notifiee from the usb gadget */
 +int usb_gadget_unregister_notify(struct usb_gadget *gadget

Re: [PATCH v2 2/3] gadget: Introduce the usb charger framework

2015-08-16 Thread Baolin Wang
On 14 August 2015 at 23:27, Greg KH gre...@linuxfoundation.org wrote:
 On Fri, Aug 14, 2015 at 05:47:45PM +0800, Baolin Wang wrote:
 This patch introduces the usb charger driver based on usb gadget that
 makes an enhancement to a power driver. It works well in practice but
 that requires a system with suitable hardware.

 The basic conception of the usb charger is that, when one usb charger
 is added or removed by reporting from the usb gadget state change or
 the extcon device state change, the usb charger will report to power
 user to set the current limitation.

 The usb charger will register notifiees on the usb gadget or the extcon
 device to get notified the usb charger state.

 Power user will register a notifiee on the usb charger to get notified
 by status changes from the usb charger. It will report to power user
 to set the current limitation when detecting the usb charger is added
 or removed from extcon device state or usb gadget state.

 Signed-off-by: Baolin Wang baolin.w...@linaro.org
 ---
  drivers/usb/gadget/Kconfig  |7 +
  drivers/usb/gadget/Makefile |1 +
  drivers/usb/gadget/charger.c|  561 
 +++
  include/linux/usb/usb_charger.h |  145 ++
  4 files changed, 714 insertions(+)
  create mode 100644 drivers/usb/gadget/charger.c
  create mode 100644 include/linux/usb/usb_charger.h

 diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig
 index bcf83c0..3d2b959 100644
 --- a/drivers/usb/gadget/Kconfig
 +++ b/drivers/usb/gadget/Kconfig
 @@ -127,6 +127,13 @@ config USB_GADGET_STORAGE_NUM_BUFFERS
  a module parameter as well.
  If unsure, say 2.

 +config USB_CHARGER
 + bool USB charger support
 + help
 +   The usb charger driver based on the usb gadget that makes an
 +   enhancement to a power driver which can set the current limitation
 +   when the usb charger is added or removed.
 +
  source drivers/usb/gadget/udc/Kconfig

  #
 diff --git a/drivers/usb/gadget/Makefile b/drivers/usb/gadget/Makefile
 index 598a67d..1e421c1 100644
 --- a/drivers/usb/gadget/Makefile
 +++ b/drivers/usb/gadget/Makefile
 @@ -10,3 +10,4 @@ libcomposite-y  := usbstring.o 
 config.o epautoconf.o
  libcomposite-y   += composite.o functions.o configfs.o 
 u_f.o

  obj-$(CONFIG_USB_GADGET) += udc/ function/ legacy/
 +obj-$(CONFIG_USB_CHARGER)+= charger.o
 diff --git a/drivers/usb/gadget/charger.c b/drivers/usb/gadget/charger.c
 new file mode 100644
 index 000..f24f7b7
 --- /dev/null
 +++ b/drivers/usb/gadget/charger.c
 @@ -0,0 +1,561 @@
 +/*
 + * usb charger.c -- USB charger driver

 I think your company also wants a copyright line here.  Not that it
 means anything at all, but some lawyers love cargo-cult text blobs.


Hi Greg,

Thanks for your reviewing and comments. I'll add it in next patch.


 + *
 + * 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.

 I have to ask, do you really mean any later version?


I think I did not get your point, could you explain it detailedly?

 + */
 +
 +#include linux/device.h
 +#include linux/err.h
 +#include linux/extcon.h
 +#include linux/export.h
 +#include linux/kernel.h
 +#include linux/module.h
 +#include linux/of.h
 +#include linux/of_device.h
 +#include linux/of_address.h
 +#include linux/platform_device.h
 +#include linux/slab.h
 +#include linux/usb.h
 +#include linux/usb/ch9.h
 +#include linux/usb/gadget.h
 +#include linux/usb/usb_charger.h
 +
 +#define DEFAULT_CUR_PROTECT  (50)
 +#define DEFAULT_SDP_CUR_LIMIT(500 - DEFAULT_CUR_PROTECT)
 +#define DEFAULT_DCP_CUR_LIMIT(1500 - DEFAULT_CUR_PROTECT)
 +#define DEFAULT_CDP_CUR_LIMIT(1500 - DEFAULT_CUR_PROTECT)
 +#define DEFAULT_ACA_CUR_LIMIT(1500 - DEFAULT_CUR_PROTECT)
 +
 +static DEFINE_IDA(usb_charger_ida);
 +static struct bus_type usb_charger_subsys = {
 + .name   = usb-charger,
 + .dev_name   = usb-charger,
 +};
 +
 +static struct usb_charger *dev_to_uchger(struct device *udev)
 +{
 + return container_of(udev, struct usb_charger, dev);
 +}
 +
 +static ssize_t usb_charger_cur_show(struct device *dev,
 + struct device_attribute *attr,
 + char *buf)
 +{
 + struct usb_charger *uchger = dev_to_uchger(dev);
 +
 + return scnprintf(buf, PAGE_SIZE, %d %d %d %d\n,
 +  uchger-cur_limit.sdp_cur_limit,
 +  uchger-cur_limit.dcp_cur_limit,
 +  uchger-cur_limit.cdp_cur_limit,
 +  uchger-cur_limit.aca_cur_limit);
 +}
 +
 +static ssize_t usb_charger_cur_store(struct device *dev,
 +  struct device_attribute *attr

Re: [PATCH v2 0/3] Introduce usb charger framework to deal with the usb gadget power negotation

2015-08-17 Thread Baolin Wang
On 17 August 2015 at 09:15, Li Jun b47...@freescale.com wrote:
 On Fri, Aug 14, 2015 at 07:04:56PM +0800, Baolin Wang wrote:
 On 14 August 2015 at 16:55, Li Jun b47...@freescale.com wrote:
  Hi Baolin,
 
  On Fri, Aug 14, 2015 at 05:47:43PM +0800, Baolin Wang wrote:
  Currently the Linux kernel does not provide any standard integration of 
  this
  feature that integrates the USB subsystem with the system power regulation
  provided by PMICs meaning that either vendors must add this in their 
  kernels
  or USB gadget devices based on Linux (such as mobile phones) may not 
  behave
  as they should.
 
  Providing a standard framework for doing this in the kernel.
 
 
  Why not add power supply class support into this?
 

 Hi Jun,

 We don't need the power supply class support into the usb charger,
 I suppose usb charger is also a power supply for the system, we can use power
 supply class framework for notify mechanism and get/set many attributes(maybe
 also the current limit), I see those usb charger drivers under ./driver/power/
 are designed with power supply supported.


I don't think so. The usb charger is rely on the usb gadget, which is
not a complete power supply device and it combines the usb and the
power supply. Thus we make it into usb gadget system. Thanks.

 Li Jun
 just introduce the notify mechanism for power to set the current limit
 when notifying some events from usb charger. Maybe I misunderstand
 your meanings, please describe it detailedly. Thanks for your
 comments.

  Li Jun
 



 --
 Baolin.wang
 Best Regards



-- 
Baolin.wang
Best Regards
--
To unsubscribe from this list: send the line unsubscribe linux-usb in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 1/2] gadget: Introduce the usb charger framework

2015-08-06 Thread Baolin Wang
This patch introduces the usb charger driver based on usb gadget that
makes an enhancement to a power driver. It works well in practice but
that requires a system with suitable hardware.

The basic conception of the usb charger is that, when one usb charger
is added or removed by reporting from the usb gadget state change or
the extcon device state change, the usb charger will report to power
user to set the current limitation.

The usb charger will register notifiees on the usb gadget or the extcon
device to get notified the usb charger state.

Power user will register a notifiee on the usb charger to get notified
by status changes from the usb charger. It will report to power user
to set the current limitation when detecting the usb charger is added
or removed from extcon device state or usb gadget state.

Signed-off-by: Baolin Wang baolin.w...@linaro.org
---
 drivers/usb/gadget/charger.c|  547 +++
 include/linux/usb/usb_charger.h |  101 
 2 files changed, 648 insertions(+)
 create mode 100644 drivers/usb/gadget/charger.c
 create mode 100644 include/linux/usb/usb_charger.h

diff --git a/drivers/usb/gadget/charger.c b/drivers/usb/gadget/charger.c
new file mode 100644
index 000..3ca0180
--- /dev/null
+++ b/drivers/usb/gadget/charger.c
@@ -0,0 +1,547 @@
+/*
+ * usb charger.c -- USB charger driver
+ *
+ * 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.
+ */
+
+#include linux/device.h
+#include linux/err.h
+#include linux/extcon.h
+#include linux/export.h
+#include linux/kernel.h
+#include linux/module.h
+#include linux/of.h
+#include linux/of_device.h
+#include linux/of_address.h
+#include linux/platform_device.h
+#include linux/slab.h
+#include linux/usb.h
+#include linux/usb/ch9.h
+#include linux/usb/gadget.h
+#include linux/usb/usb_charger.h
+
+#define DEFAULT_CUR_PROTECT(50)
+#define DEFAULT_SDP_CUR_LIMIT  (500 - DEFAULT_CUR_PROTECT)
+#define DEFAULT_DCP_CUR_LIMIT  (1500 - DEFAULT_CUR_PROTECT)
+#define DEFAULT_CDP_CUR_LIMIT  (1500 - DEFAULT_CUR_PROTECT)
+#define DEFAULT_ACA_CUR_LIMIT  (1500 - DEFAULT_CUR_PROTECT)
+
+static LIST_HEAD(usb_charger_list);
+static DEFINE_MUTEX(usb_charger_list_lock);
+
+/*
+ * usb_charger_find_by_name - Get the usb charger device by name.
+ * @name - usb charger device name.
+ *
+ * notes: when this function walks the list and returns a charger
+ * it's dropped the lock which means that something else could come
+ * along and delete the charger before we dereference the pointer.
+ * It's very unlikely but it's a possibility so you should take care
+ * of it.
+ * Thus when you get the usb charger by name, you should call
+ * put_usb_charger() to derease the reference count of the usb charger.
+ *
+ * return the instance of usb charger device.
+ */
+struct usb_charger *usb_charger_find_by_name(char *name)
+{
+   struct usb_charger *uchger;
+
+   if (!name)
+   return ERR_PTR(-EINVAL);
+
+   mutex_lock(usb_charger_list_lock);
+   list_for_each_entry(uchger, usb_charger_list, entry) {
+   if (!strcmp(uchger-name, name)) {
+   get_usb_charger(uchger);
+   mutex_unlock(usb_charger_list_lock);
+   return uchger;
+   }
+   }
+   mutex_unlock(usb_charger_list_lock);
+
+   return NULL;
+}
+
+/*
+ * usb_charger_register_notify() - Register a notifiee to get notified by
+ * any attach status changes from the usb charger type detection.
+ * @uchger - the usb charger device which is monitored.
+ * @nb - a notifier block to be registered.
+ */
+void usb_charger_register_notify(struct usb_charger *uchger,
+struct notifier_block *nb)
+{
+   unsigned long flags;
+
+   spin_lock_irqsave(uchger-lock, flags);
+   raw_notifier_chain_register(uchger-uchger_nh, nb);
+   spin_unlock_irqrestore(uchger-lock, flags);
+}
+
+/*
+ * usb_charger_unregister_notify() - Unregister a notifiee from the usb 
charger.
+ * @uchger - the usb charger device which is monitored.
+ * @nb - a notifier block to be unregistered.
+ */
+void usb_charger_unregister_notify(struct usb_charger *uchger,
+  struct notifier_block *nb)
+{
+   unsigned long flags;
+
+   spin_lock_irqsave(uchger-lock, flags);
+   raw_notifier_chain_unregister(uchger-uchger_nh, nb);
+   spin_unlock_irqrestore(uchger-lock, flags);
+}
+
+/*
+ * usb_charger_register_extcon_notifier() - Register a notifiee of the usb
+ * charger to get notified by any attach status changes from
+ * the extcon device.
+ * @uchger - the usb charger device.
+ * @edev - the extcon device.
+ * @extcon_id - extcon id.
+ */
+int usb_charger_register_extcon_notifier(struct

Re: [PATCH 1/2] gadget: Introduce the usb charger framework

2015-08-06 Thread Baolin Wang
On 7 August 2015 at 00:39, Greg KH gre...@linuxfoundation.org wrote:
 On Thu, Aug 06, 2015 at 03:03:48PM +0800, Baolin Wang wrote:
 This patch introduces the usb charger driver based on usb gadget that
 makes an enhancement to a power driver. It works well in practice but
 that requires a system with suitable hardware.

 The basic conception of the usb charger is that, when one usb charger
 is added or removed by reporting from the usb gadget state change or
 the extcon device state change, the usb charger will report to power
 user to set the current limitation.

 The usb charger will register notifiees on the usb gadget or the extcon
 device to get notified the usb charger state.

 Power user will register a notifiee on the usb charger to get notified
 by status changes from the usb charger. It will report to power user
 to set the current limitation when detecting the usb charger is added
 or removed from extcon device state or usb gadget state.

 Signed-off-by: Baolin Wang baolin.w...@linaro.org
 ---
  drivers/usb/gadget/charger.c|  547 
 +++
  include/linux/usb/usb_charger.h |  101 
  2 files changed, 648 insertions(+)
  create mode 100644 drivers/usb/gadget/charger.c
  create mode 100644 include/linux/usb/usb_charger.h

 diff --git a/drivers/usb/gadget/charger.c b/drivers/usb/gadget/charger.c
 new file mode 100644
 index 000..3ca0180
 --- /dev/null
 +++ b/drivers/usb/gadget/charger.c
 @@ -0,0 +1,547 @@
 +/*
 + * usb charger.c -- USB charger driver
 + *
 + * 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.

 I have to ask, do you really mean any later version?


I'll think about this and modify it.

 + */
 +
 +#include linux/device.h
 +#include linux/err.h
 +#include linux/extcon.h
 +#include linux/export.h
 +#include linux/kernel.h
 +#include linux/module.h
 +#include linux/of.h
 +#include linux/of_device.h
 +#include linux/of_address.h
 +#include linux/platform_device.h
 +#include linux/slab.h
 +#include linux/usb.h
 +#include linux/usb/ch9.h
 +#include linux/usb/gadget.h
 +#include linux/usb/usb_charger.h
 +
 +#define DEFAULT_CUR_PROTECT  (50)
 +#define DEFAULT_SDP_CUR_LIMIT(500 - DEFAULT_CUR_PROTECT)
 +#define DEFAULT_DCP_CUR_LIMIT(1500 - DEFAULT_CUR_PROTECT)
 +#define DEFAULT_CDP_CUR_LIMIT(1500 - DEFAULT_CUR_PROTECT)
 +#define DEFAULT_ACA_CUR_LIMIT(1500 - DEFAULT_CUR_PROTECT)
 +
 +static LIST_HEAD(usb_charger_list);
 +static DEFINE_MUTEX(usb_charger_list_lock);
 +
 +/*
 + * usb_charger_find_by_name - Get the usb charger device by name.
 + * @name - usb charger device name.
 + *
 + * notes: when this function walks the list and returns a charger
 + * it's dropped the lock which means that something else could come
 + * along and delete the charger before we dereference the pointer.
 + * It's very unlikely but it's a possibility so you should take care
 + * of it.
 + * Thus when you get the usb charger by name, you should call
 + * put_usb_charger() to derease the reference count of the usb charger.
 + *
 + * return the instance of usb charger device.
 + */
 +struct usb_charger *usb_charger_find_by_name(char *name)
 +{
 + struct usb_charger *uchger;
 +
 + if (!name)
 + return ERR_PTR(-EINVAL);
 +
 + mutex_lock(usb_charger_list_lock);
 + list_for_each_entry(uchger, usb_charger_list, entry) {
 + if (!strcmp(uchger-name, name)) {
 + get_usb_charger(uchger);
 + mutex_unlock(usb_charger_list_lock);
 + return uchger;
 + }
 + }
 + mutex_unlock(usb_charger_list_lock);
 +
 + return NULL;
 +}
 +
 +/*
 + * usb_charger_register_notify() - Register a notifiee to get notified by
 + *   any attach status changes from the usb charger type detection.
 + * @uchger - the usb charger device which is monitored.
 + * @nb - a notifier block to be registered.
 + */
 +void usb_charger_register_notify(struct usb_charger *uchger,
 +  struct notifier_block *nb)
 +{
 + unsigned long flags;
 +
 + spin_lock_irqsave(uchger-lock, flags);
 + raw_notifier_chain_register(uchger-uchger_nh, nb);
 + spin_unlock_irqrestore(uchger-lock, flags);
 +}
 +
 +/*
 + * usb_charger_unregister_notify() - Unregister a notifiee from the usb 
 charger.
 + * @uchger - the usb charger device which is monitored.
 + * @nb - a notifier block to be unregistered.
 + */
 +void usb_charger_unregister_notify(struct usb_charger *uchger,
 +struct notifier_block *nb)
 +{
 + unsigned long flags;
 +
 + spin_lock_irqsave(uchger-lock, flags);
 + raw_notifier_chain_unregister(uchger-uchger_nh, nb);
 + spin_unlock_irqrestore(uchger-lock, flags

[PATCH 0/2] Introduce usb charger framework to deal with the usb gadget power negotation

2015-08-06 Thread Baolin Wang
Currently the Linux kernel does not provide any standard integration of this
feature that integrates the USB subsystem with the system power regulation
provided by PMICs meaning that either vendors must add this in their kernels
or USB gadget devices based on Linux (such as mobile phones) may not behave
as they should.

Providing a standard framework for doing this in the kernel.

Baolin Wang (2):
  gadget: Introduce the usb charger framework
  gadget: Support for the usb charger framework

 drivers/usb/gadget/charger.c  |  547 +
 drivers/usb/gadget/udc/udc-core.c |   41 +++
 include/linux/usb/gadget.h|   20 ++
 include/linux/usb/usb_charger.h   |  101 +++
 4 files changed, 709 insertions(+)
 create mode 100644 drivers/usb/gadget/charger.c
 create mode 100644 include/linux/usb/usb_charger.h

-- 
1.7.9.5

--
To unsubscribe from this list: send the line unsubscribe linux-usb in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 2/2] gadget: Support for the usb charger framework

2015-08-06 Thread Baolin Wang
The usb charger framework is based on usb gadget, and each usb gadget
can be one usb charger to set the current limitation.

This patch adds a notifier mechanism for usb charger to report to usb
charger when the usb gadget state is changed.

Also we introduce a callback 'get_charger_type' which will implemented
by user for usb gadget operations to get the usb charger type.

Signed-off-by: Baolin Wang baolin.w...@linaro.org
---
 drivers/usb/gadget/udc/udc-core.c |   41 +
 include/linux/usb/gadget.h|   20 ++
 2 files changed, 61 insertions(+)

diff --git a/drivers/usb/gadget/udc/udc-core.c 
b/drivers/usb/gadget/udc/udc-core.c
index d69c355..d5368088 100644
--- a/drivers/usb/gadget/udc/udc-core.c
+++ b/drivers/usb/gadget/udc/udc-core.c
@@ -28,6 +28,7 @@
 #include linux/usb/ch9.h
 #include linux/usb/gadget.h
 #include linux/usb.h
+#include linux/usb/usb_charger.h
 
 /**
  * struct usb_udc - describes one usb device controller
@@ -127,12 +128,45 @@ void usb_gadget_giveback_request(struct usb_ep *ep,
 }
 EXPORT_SYMBOL_GPL(usb_gadget_giveback_request);
 
+int usb_gadget_register_notify(struct usb_gadget *gadget,
+  struct notifier_block *nb)
+{
+   unsigned long flags;
+   int ret;
+
+   spin_lock_irqsave(gadget-lock, flags);
+   ret = raw_notifier_chain_register(gadget-nh, nb);
+   spin_unlock_irqrestore(gadget-lock, flags);
+
+   return ret;
+}
+EXPORT_SYMBOL_GPL(usb_gadget_register_notify);
+
+int usb_gadget_unregister_notify(struct usb_gadget *gadget,
+struct notifier_block *nb)
+{
+   unsigned long flags;
+   int ret;
+
+   spin_lock_irqsave(gadget-lock, flags);
+   ret = raw_notifier_chain_unregister(gadget-nh, nb);
+   spin_unlock_irqrestore(gadget-lock, flags);
+
+   return ret;
+}
+EXPORT_SYMBOL_GPL(usb_gadget_unregister_notify);
+
 /* - */
 
 static void usb_gadget_state_work(struct work_struct *work)
 {
struct usb_gadget *gadget = work_to_gadget(work);
struct usb_udc *udc = gadget-udc;
+   unsigned long flags;
+
+   spin_lock_irqsave(gadget-lock, flags);
+   raw_notifier_call_chain(gadget-nh, gadget-state, gadget);
+   spin_unlock_irqrestore(gadget-lock, flags);
 
if (udc)
sysfs_notify(udc-dev.kobj, NULL, state);
@@ -272,6 +306,8 @@ int usb_add_gadget_udc_release(struct device *parent, 
struct usb_gadget *gadget,
 
dev_set_name(gadget-dev, gadget);
INIT_WORK(gadget-work, usb_gadget_state_work);
+   RAW_INIT_NOTIFIER_HEAD(gadget-nh);
+   spin_lock_init(gadget-lock);
gadget-dev.parent = parent;
 
 #ifdef CONFIG_HAS_DMA
@@ -313,6 +349,10 @@ int usb_add_gadget_udc_release(struct device *parent, 
struct usb_gadget *gadget,
 
mutex_unlock(udc_lock);
 
+   ret = usb_charger_init(gadget);
+   if (ret)
+   goto err4;
+
return 0;
 
 err4:
@@ -388,6 +428,7 @@ void usb_del_gadget_udc(struct usb_gadget *gadget)
kobject_uevent(udc-dev.kobj, KOBJ_REMOVE);
flush_work(gadget-work);
device_unregister(udc-dev);
+   usb_charger_exit(gadget);
device_unregister(gadget-dev);
 }
 EXPORT_SYMBOL_GPL(usb_del_gadget_udc);
diff --git a/include/linux/usb/gadget.h b/include/linux/usb/gadget.h
index 4f3dfb7..f24d6ac 100644
--- a/include/linux/usb/gadget.h
+++ b/include/linux/usb/gadget.h
@@ -492,6 +492,7 @@ struct usb_gadget_ops {
int (*udc_start)(struct usb_gadget *,
struct usb_gadget_driver *);
int (*udc_stop)(struct usb_gadget *);
+   enum usb_charger_type   (*get_charger_type)(struct usb_gadget *);
 };
 
 /**
@@ -559,6 +560,9 @@ struct usb_gadget {
struct device   dev;
unsignedout_epnum;
unsignedin_epnum;
+   struct raw_notifier_headnh;
+   struct usb_charger  *uchger;
+   spinlock_t  lock;
 
unsignedsg_supported:1;
unsignedis_otg:1;
@@ -1014,6 +1018,22 @@ extern void usb_gadget_unmap_request(struct usb_gadget 
*gadget,
 
 /*-*/
 
+/**
+ * Register a notifiee to get notified by any attach status changes from
+ * the usb gadget
+ */
+int usb_gadget_register_notify(struct usb_gadget *gadget,
+  struct notifier_block *nb);
+
+/*-*/
+
+
+/* Unregister a notifiee from the usb gadget */
+int usb_gadget_unregister_notify(struct usb_gadget *gadget,
+struct notifier_block *nb);
+
+/*-*/
+
 /* utility to set gadget state

Re: [PATCH 0/2] Introduce usb charger framework to deal with the usb gadget power negotation

2015-08-07 Thread Baolin Wang
On 7 August 2015 at 16:31, Peter Chen peter.c...@freescale.com wrote:


 Peter, Thanks for your reviewing and comments. Now I just introduce the
 framework to review for more feedbacks and do not have a useful user to use
 it. I just can show you some example code to show how to use it. Thanks.


 Felipe may not accept the code which are no user on it, I remember he said it 
 before.
 Besides, if no user on it, how you test it?


Make sense of it. I'll try to build the user to test it. Thanks for
your reminding.

 Peter



-- 
Baolin.wang
Best Regards
--
To unsubscribe from this list: send the line unsubscribe linux-usb in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 0/2] Introduce usb charger framework to deal with the usb gadget power negotation

2015-08-07 Thread Baolin Wang
On 7 August 2015 at 13:34, Peter Chen peter.c...@freescale.com wrote:
 On Thu, Aug 06, 2015 at 03:03:47PM +0800, Baolin Wang wrote:
 Currently the Linux kernel does not provide any standard integration of this
 feature that integrates the USB subsystem with the system power regulation
 provided by PMICs meaning that either vendors must add this in their kernels
 or USB gadget devices based on Linux (such as mobile phones) may not behave
 as they should.

 Providing a standard framework for doing this in the kernel.

 Baolin, thanks for introducing a framework for doing it, we do support
 USB Charger for chipidea driver at internal tree, but it is specific
 for imx, and still have some problems to upstream due to need to
 change some common code.

 One suggestion, would you add your user next time? In that case, we can
 know better for this framework.


Peter, Thanks for your reviewing and comments. Now I just introduce
the framework to review for more feedbacks and do not have a useful
user to use it. I just can show you some example code to show how to
use it. Thanks.


 Baolin Wang (2):
   gadget: Introduce the usb charger framework
   gadget: Support for the usb charger framework

  drivers/usb/gadget/charger.c  |  547 
 +
  drivers/usb/gadget/udc/udc-core.c |   41 +++
  include/linux/usb/gadget.h|   20 ++
  include/linux/usb/usb_charger.h   |  101 +++
  4 files changed, 709 insertions(+)
  create mode 100644 drivers/usb/gadget/charger.c
  create mode 100644 include/linux/usb/usb_charger.h

 --
 1.7.9.5


 --

 Best Regards,
 Peter Chen



-- 
Baolin.wang
Best Regards
--
To unsubscribe from this list: send the line unsubscribe linux-usb in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 1/2] gadget: Introduce the usb charger framework

2015-08-07 Thread Baolin Wang
On 7 August 2015 at 13:41, Peter Chen peter.c...@freescale.com wrote:
 On Thu, Aug 06, 2015 at 03:03:48PM +0800, Baolin Wang wrote:
 This patch introduces the usb charger driver based on usb gadget that
 makes an enhancement to a power driver. It works well in practice but
 that requires a system with suitable hardware.

 The basic conception of the usb charger is that, when one usb charger
 is added or removed by reporting from the usb gadget state change or
 the extcon device state change, the usb charger will report to power
 user to set the current limitation.

 The usb charger will register notifiees on the usb gadget or the extcon
 device to get notified the usb charger state.

 Power user will register a notifiee on the usb charger to get notified
 by status changes from the usb charger. It will report to power user
 to set the current limitation when detecting the usb charger is added
 or removed from extcon device state or usb gadget state.

 Signed-off-by: Baolin Wang baolin.w...@linaro.org
 ---
  drivers/usb/gadget/charger.c|  547 
 +++
  include/linux/usb/usb_charger.h |  101 
  2 files changed, 648 insertions(+)
  create mode 100644 drivers/usb/gadget/charger.c
  create mode 100644 include/linux/usb/usb_charger.h

 diff --git a/drivers/usb/gadget/charger.c b/drivers/usb/gadget/charger.c
 new file mode 100644
 index 000..3ca0180
 --- /dev/null
 +++ b/drivers/usb/gadget/charger.c
 @@ -0,0 +1,547 @@
 +/*
 + * usb charger.c -- USB charger driver
 + *
 + * 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.
 + */
 +
 +#include linux/device.h
 +#include linux/err.h
 +#include linux/extcon.h
 +#include linux/export.h
 +#include linux/kernel.h
 +#include linux/module.h
 +#include linux/of.h
 +#include linux/of_device.h
 +#include linux/of_address.h
 +#include linux/platform_device.h
 +#include linux/slab.h
 +#include linux/usb.h
 +#include linux/usb/ch9.h
 +#include linux/usb/gadget.h
 +#include linux/usb/usb_charger.h
 +
 +#define DEFAULT_CUR_PROTECT  (50)
 +#define DEFAULT_SDP_CUR_LIMIT(500 - DEFAULT_CUR_PROTECT)
 +#define DEFAULT_DCP_CUR_LIMIT(1500 - DEFAULT_CUR_PROTECT)
 +#define DEFAULT_CDP_CUR_LIMIT(1500 - DEFAULT_CUR_PROTECT)
 +#define DEFAULT_ACA_CUR_LIMIT(1500 - DEFAULT_CUR_PROTECT)
 +
 +static LIST_HEAD(usb_charger_list);
 +static DEFINE_MUTEX(usb_charger_list_lock);
 +
 +/*
 + * usb_charger_find_by_name - Get the usb charger device by name.
 + * @name - usb charger device name.
 + *
 + * notes: when this function walks the list and returns a charger
 + * it's dropped the lock which means that something else could come
 + * along and delete the charger before we dereference the pointer.
 + * It's very unlikely but it's a possibility so you should take care
 + * of it.
 + * Thus when you get the usb charger by name, you should call
 + * put_usb_charger() to derease the reference count of the usb charger.
 + *
 + * return the instance of usb charger device.
 + */
 +struct usb_charger *usb_charger_find_by_name(char *name)
 +{
 + struct usb_charger *uchger;
 +
 + if (!name)
 + return ERR_PTR(-EINVAL);
 +
 + mutex_lock(usb_charger_list_lock);
 + list_for_each_entry(uchger, usb_charger_list, entry) {
 + if (!strcmp(uchger-name, name)) {
 + get_usb_charger(uchger);
 + mutex_unlock(usb_charger_list_lock);
 + return uchger;
 + }
 + }
 + mutex_unlock(usb_charger_list_lock);
 +
 + return NULL;
 +}
 +
 +/*
 + * usb_charger_register_notify() - Register a notifiee to get notified by
 + *   any attach status changes from the usb charger type detection.
 + * @uchger - the usb charger device which is monitored.
 + * @nb - a notifier block to be registered.
 + */
 +void usb_charger_register_notify(struct usb_charger *uchger,
 +  struct notifier_block *nb)
 +{
 + unsigned long flags;
 +
 + spin_lock_irqsave(uchger-lock, flags);
 + raw_notifier_chain_register(uchger-uchger_nh, nb);
 + spin_unlock_irqrestore(uchger-lock, flags);
 +}
 +
 +/*
 + * usb_charger_unregister_notify() - Unregister a notifiee from the usb 
 charger.
 + * @uchger - the usb charger device which is monitored.
 + * @nb - a notifier block to be unregistered.
 + */
 +void usb_charger_unregister_notify(struct usb_charger *uchger,
 +struct notifier_block *nb)
 +{
 + unsigned long flags;
 +
 + spin_lock_irqsave(uchger-lock, flags);
 + raw_notifier_chain_unregister(uchger-uchger_nh, nb);
 + spin_unlock_irqrestore(uchger-lock, flags);
 +}
 +
 +/*
 + * usb_charger_register_extcon_notifier() - Register a notifiee of the usb
 + *   charger

Re: [PATCH 2/2] gadget: Support for the usb charger framework

2015-08-07 Thread Baolin Wang
On 7 August 2015 at 13:45, Peter Chen peter.c...@freescale.com wrote:
 On Thu, Aug 06, 2015 at 03:03:49PM +0800, Baolin Wang wrote:
 The usb charger framework is based on usb gadget, and each usb gadget
 can be one usb charger to set the current limitation.

 This patch adds a notifier mechanism for usb charger to report to usb
 charger when the usb gadget state is changed.

 Also we introduce a callback 'get_charger_type' which will implemented
 by user for usb gadget operations to get the usb charger type.

 Signed-off-by: Baolin Wang baolin.w...@linaro.org
 ---
  drivers/usb/gadget/udc/udc-core.c |   41 
 +
  include/linux/usb/gadget.h|   20 ++
  2 files changed, 61 insertions(+)

 diff --git a/drivers/usb/gadget/udc/udc-core.c 
 b/drivers/usb/gadget/udc/udc-core.c
 index d69c355..d5368088 100644
 --- a/drivers/usb/gadget/udc/udc-core.c
 +++ b/drivers/usb/gadget/udc/udc-core.c
 @@ -28,6 +28,7 @@
  #include linux/usb/ch9.h
  #include linux/usb/gadget.h
  #include linux/usb.h
 +#include linux/usb/usb_charger.h

  /**
   * struct usb_udc - describes one usb device controller
 @@ -127,12 +128,45 @@ void usb_gadget_giveback_request(struct usb_ep *ep,
  }
  EXPORT_SYMBOL_GPL(usb_gadget_giveback_request);

 +int usb_gadget_register_notify(struct usb_gadget *gadget,
 +struct notifier_block *nb)
 +{
 + unsigned long flags;
 + int ret;
 +
 + spin_lock_irqsave(gadget-lock, flags);

 I find you use so many spin_lock_irqsave, any reasons for that?
 Why mutex_lock can't be used?


The spin_lock_irqsave() can make it as a atomic notifier, that can
make sure the gadget state event can be quickly reported to the user
who register a notifier on the gadget device. Is it OK?

 --

 Best Regards,
 Peter Chen



-- 
Baolin.wang
Best Regards
--
To unsubscribe from this list: send the line unsubscribe linux-usb in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 2/2] gadget: Support for the usb charger framework

2015-08-07 Thread Baolin Wang
On 7 August 2015 at 17:07, Peter Chen peter.c...@freescale.com wrote:

   /**
* struct usb_udc - describes one usb device controller @@ -127,12
  +128,45 @@ void usb_gadget_giveback_request(struct usb_ep *ep,  }
  EXPORT_SYMBOL_GPL(usb_gadget_giveback_request);
 
  +int usb_gadget_register_notify(struct usb_gadget *gadget,
  +struct notifier_block *nb) {
  + unsigned long flags;
  + int ret;
  +
  + spin_lock_irqsave(gadget-lock, flags);
 
  I find you use so many spin_lock_irqsave, any reasons for that?
  Why mutex_lock can't be used?
 

 The spin_lock_irqsave() can make it as a atomic notifier, that can make sure 
 the
 gadget state event can be quickly reported to the user who register a 
 notifier
 on the gadget device. Is it OK?


 I don't think it is a good reason, spin_lock_irqsave is usually used for 
 protecting
 data which is accessed at atomic environment.


Yes, we want the notify process is a atomic environment which do not
want to be interrupted by irq or other things to make the notice can
be quickly reported to the user.

Also i think the notify process is less cost, thus i use the spinlock. Thanks.

 Peter



-- 
Baolin.wang
Best Regards
--
To unsubscribe from this list: send the line unsubscribe linux-usb in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v2 0/3] Introduce usb charger framework to deal with the usb gadget power negotation

2015-08-14 Thread Baolin Wang
On 14 August 2015 at 16:55, Li Jun b47...@freescale.com wrote:
 Hi Baolin,

 On Fri, Aug 14, 2015 at 05:47:43PM +0800, Baolin Wang wrote:
 Currently the Linux kernel does not provide any standard integration of this
 feature that integrates the USB subsystem with the system power regulation
 provided by PMICs meaning that either vendors must add this in their kernels
 or USB gadget devices based on Linux (such as mobile phones) may not behave
 as they should.

 Providing a standard framework for doing this in the kernel.


 Why not add power supply class support into this?


Hi Jun,

We don't need the power supply class support into the usb charger,
just introduce the notify mechanism for power to set the current limit
when notifying some events from usb charger. Maybe I misunderstand
your meanings, please describe it detailedly. Thanks for your
comments.

 Li Jun




-- 
Baolin.wang
Best Regards
--
To unsubscribe from this list: send the line unsubscribe linux-usb in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v2 2/3] gadget: Introduce the usb charger framework

2015-08-14 Thread Baolin Wang
This patch introduces the usb charger driver based on usb gadget that
makes an enhancement to a power driver. It works well in practice but
that requires a system with suitable hardware.

The basic conception of the usb charger is that, when one usb charger
is added or removed by reporting from the usb gadget state change or
the extcon device state change, the usb charger will report to power
user to set the current limitation.

The usb charger will register notifiees on the usb gadget or the extcon
device to get notified the usb charger state.

Power user will register a notifiee on the usb charger to get notified
by status changes from the usb charger. It will report to power user
to set the current limitation when detecting the usb charger is added
or removed from extcon device state or usb gadget state.

Signed-off-by: Baolin Wang baolin.w...@linaro.org
---
 drivers/usb/gadget/Kconfig  |7 +
 drivers/usb/gadget/Makefile |1 +
 drivers/usb/gadget/charger.c|  561 +++
 include/linux/usb/usb_charger.h |  145 ++
 4 files changed, 714 insertions(+)
 create mode 100644 drivers/usb/gadget/charger.c
 create mode 100644 include/linux/usb/usb_charger.h

diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig
index bcf83c0..3d2b959 100644
--- a/drivers/usb/gadget/Kconfig
+++ b/drivers/usb/gadget/Kconfig
@@ -127,6 +127,13 @@ config USB_GADGET_STORAGE_NUM_BUFFERS
   a module parameter as well.
   If unsure, say 2.
 
+config USB_CHARGER
+   bool USB charger support
+   help
+ The usb charger driver based on the usb gadget that makes an
+ enhancement to a power driver which can set the current limitation
+ when the usb charger is added or removed.
+
 source drivers/usb/gadget/udc/Kconfig
 
 #
diff --git a/drivers/usb/gadget/Makefile b/drivers/usb/gadget/Makefile
index 598a67d..1e421c1 100644
--- a/drivers/usb/gadget/Makefile
+++ b/drivers/usb/gadget/Makefile
@@ -10,3 +10,4 @@ libcomposite-y:= usbstring.o config.o 
epautoconf.o
 libcomposite-y += composite.o functions.o configfs.o u_f.o
 
 obj-$(CONFIG_USB_GADGET)   += udc/ function/ legacy/
+obj-$(CONFIG_USB_CHARGER)  += charger.o
diff --git a/drivers/usb/gadget/charger.c b/drivers/usb/gadget/charger.c
new file mode 100644
index 000..f24f7b7
--- /dev/null
+++ b/drivers/usb/gadget/charger.c
@@ -0,0 +1,561 @@
+/*
+ * usb charger.c -- USB charger driver
+ *
+ * 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.
+ */
+
+#include linux/device.h
+#include linux/err.h
+#include linux/extcon.h
+#include linux/export.h
+#include linux/kernel.h
+#include linux/module.h
+#include linux/of.h
+#include linux/of_device.h
+#include linux/of_address.h
+#include linux/platform_device.h
+#include linux/slab.h
+#include linux/usb.h
+#include linux/usb/ch9.h
+#include linux/usb/gadget.h
+#include linux/usb/usb_charger.h
+
+#define DEFAULT_CUR_PROTECT(50)
+#define DEFAULT_SDP_CUR_LIMIT  (500 - DEFAULT_CUR_PROTECT)
+#define DEFAULT_DCP_CUR_LIMIT  (1500 - DEFAULT_CUR_PROTECT)
+#define DEFAULT_CDP_CUR_LIMIT  (1500 - DEFAULT_CUR_PROTECT)
+#define DEFAULT_ACA_CUR_LIMIT  (1500 - DEFAULT_CUR_PROTECT)
+
+static DEFINE_IDA(usb_charger_ida);
+static struct bus_type usb_charger_subsys = {
+   .name   = usb-charger,
+   .dev_name   = usb-charger,
+};
+
+static struct usb_charger *dev_to_uchger(struct device *udev)
+{
+   return container_of(udev, struct usb_charger, dev);
+}
+
+static ssize_t usb_charger_cur_show(struct device *dev,
+   struct device_attribute *attr,
+   char *buf)
+{
+   struct usb_charger *uchger = dev_to_uchger(dev);
+
+   return scnprintf(buf, PAGE_SIZE, %d %d %d %d\n,
+uchger-cur_limit.sdp_cur_limit,
+uchger-cur_limit.dcp_cur_limit,
+uchger-cur_limit.cdp_cur_limit,
+uchger-cur_limit.aca_cur_limit);
+}
+
+static ssize_t usb_charger_cur_store(struct device *dev,
+struct device_attribute *attr,
+const char *buf, size_t count)
+{
+   struct usb_charger *uchger = dev_to_uchger(dev);
+   struct usb_charger_cur_limit cur;
+   int ret;
+
+   ret = sscanf(buf, %d %d %d %d,
+cur.sdp_cur_limit, cur.dcp_cur_limit,
+cur.cdp_cur_limit, cur.aca_cur_limit);
+   if (ret == 0)
+   return -EINVAL;
+
+   ret = usb_charger_set_cur_limit(uchger, cur);
+   if (ret  0)
+   return ret;
+
+   return count;
+}
+static DEVICE_ATTR(cur_limit, 0644, usb_charger_cur_show

[PATCH v2 0/3] Introduce usb charger framework to deal with the usb gadget power negotation

2015-08-14 Thread Baolin Wang
Currently the Linux kernel does not provide any standard integration of this
feature that integrates the USB subsystem with the system power regulation
provided by PMICs meaning that either vendors must add this in their kernels
or USB gadget devices based on Linux (such as mobile phones) may not behave
as they should.

Providing a standard framework for doing this in the kernel.

Now introduce one user with wm831x_power to support and test the usb charger,
which is pending testing. Moreover there may be other potential users will use
it in future.

Changes since v1:
 - Rebase my branch and re-create the patch series.
 - Remove the extcon wrappers and gadget wrappers for registering a notifier.
 - Remove the user count in usb charger.
 - Use idr instead of my own logic.
 - Replace the spinlock with mutex.
 - Use the list of driver core to manage the usb charger device.
 - Add the Kconfig and Makefile changes.
 - Add some attribute files to show or store the current limitation.
 - Introduce one user of usb charger by Mark Brown.
 - Other modifications.

Baolin Wang (3):
  gadget: Support for the usb charger framework
  gadget: Introduce the usb charger framework
  power: wm831x_power: Support USB charger current limit management

 drivers/power/wm831x_power.c  |   69 +
 drivers/usb/gadget/Kconfig|7 +
 drivers/usb/gadget/Makefile   |1 +
 drivers/usb/gadget/charger.c  |  561 +
 drivers/usb/gadget/udc/udc-core.c |   38 +++
 include/linux/mfd/wm831x/pdata.h  |3 +
 include/linux/usb/gadget.h|   20 ++
 include/linux/usb/usb_charger.h   |  145 ++
 8 files changed, 844 insertions(+)
 create mode 100644 drivers/usb/gadget/charger.c
 create mode 100644 include/linux/usb/usb_charger.h

-- 
1.7.9.5

--
To unsubscribe from this list: send the line unsubscribe linux-usb in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v2 1/3] gadget: Support for the usb charger framework

2015-08-14 Thread Baolin Wang
The usb charger framework is based on usb gadget, and each usb gadget
can be one usb charger to set the current limitation.

This patch adds a notifier mechanism for usb charger to report to usb
charger when the usb gadget state is changed.

Also we introduce a callback 'get_charger_type' which will implemented
by user for usb gadget operations to get the usb charger type.

Signed-off-by: Baolin Wang baolin.w...@linaro.org
---
 drivers/usb/gadget/udc/udc-core.c |   38 +
 include/linux/usb/gadget.h|   20 +++
 2 files changed, 58 insertions(+)

diff --git a/drivers/usb/gadget/udc/udc-core.c 
b/drivers/usb/gadget/udc/udc-core.c
index f660afb..47b231c 100644
--- a/drivers/usb/gadget/udc/udc-core.c
+++ b/drivers/usb/gadget/udc/udc-core.c
@@ -28,6 +28,7 @@
 #include linux/usb/ch9.h
 #include linux/usb/gadget.h
 #include linux/usb.h
+#include linux/usb/usb_charger.h
 
 /**
  * struct usb_udc - describes one usb device controller
@@ -129,6 +130,32 @@ void usb_gadget_giveback_request(struct usb_ep *ep,
 }
 EXPORT_SYMBOL_GPL(usb_gadget_giveback_request);
 
+int usb_gadget_register_notify(struct usb_gadget *gadget,
+  struct notifier_block *nb)
+{
+   int ret;
+
+   mutex_lock(gadget-lock);
+   ret = raw_notifier_chain_register(gadget-nh, nb);
+   mutex_unlock(gadget-lock);
+
+   return ret;
+}
+EXPORT_SYMBOL_GPL(usb_gadget_register_notify);
+
+int usb_gadget_unregister_notify(struct usb_gadget *gadget,
+struct notifier_block *nb)
+{
+   int ret;
+
+   mutex_lock(gadget-lock);
+   ret = raw_notifier_chain_unregister(gadget-nh, nb);
+   mutex_unlock(gadget-lock);
+
+   return ret;
+}
+EXPORT_SYMBOL_GPL(usb_gadget_unregister_notify);
+
 /* - */
 
 /**
@@ -226,6 +253,10 @@ static void usb_gadget_state_work(struct work_struct *work)
struct usb_gadget *gadget = work_to_gadget(work);
struct usb_udc *udc = gadget-udc;
 
+   mutex_lock(gadget-lock);
+   raw_notifier_call_chain(gadget-nh, gadget-state, gadget);
+   mutex_unlock(gadget-lock);
+
if (udc)
sysfs_notify(udc-dev.kobj, NULL, state);
 }
@@ -364,6 +395,8 @@ int usb_add_gadget_udc_release(struct device *parent, 
struct usb_gadget *gadget,
 
dev_set_name(gadget-dev, gadget);
INIT_WORK(gadget-work, usb_gadget_state_work);
+   RAW_INIT_NOTIFIER_HEAD(gadget-nh);
+   mutex_init(gadget-lock);
gadget-dev.parent = parent;
 
 #ifdef CONFIG_HAS_DMA
@@ -405,6 +438,10 @@ int usb_add_gadget_udc_release(struct device *parent, 
struct usb_gadget *gadget,
 
mutex_unlock(udc_lock);
 
+   ret = usb_charger_init(gadget);
+   if (ret)
+   goto err4;
+
return 0;
 
 err4:
@@ -481,6 +518,7 @@ void usb_del_gadget_udc(struct usb_gadget *gadget)
kobject_uevent(udc-dev.kobj, KOBJ_REMOVE);
flush_work(gadget-work);
device_unregister(udc-dev);
+   usb_charger_exit(gadget);
device_unregister(gadget-dev);
 }
 EXPORT_SYMBOL_GPL(usb_del_gadget_udc);
diff --git a/include/linux/usb/gadget.h b/include/linux/usb/gadget.h
index c14a69b..78cc862 100644
--- a/include/linux/usb/gadget.h
+++ b/include/linux/usb/gadget.h
@@ -537,6 +537,7 @@ struct usb_gadget_ops {
struct usb_ep *(*match_ep)(struct usb_gadget *,
struct usb_endpoint_descriptor *,
struct usb_ss_ep_comp_descriptor *);
+   enum usb_charger_type   (*get_charger_type)(struct usb_gadget *);
 };
 
 /**
@@ -609,6 +610,9 @@ struct usb_gadget {
unsignedout_epnum;
unsignedin_epnum;
struct usb_otg_caps *otg_caps;
+   struct raw_notifier_headnh;
+   struct usb_charger  *uchger;
+   struct mutexlock;
 
unsignedsg_supported:1;
unsignedis_otg:1;
@@ -1183,6 +1187,22 @@ extern void usb_gadget_unmap_request(struct usb_gadget 
*gadget,
 
 /*-*/
 
+/**
+ * Register a notifiee to get notified by any attach status changes from
+ * the usb gadget
+ */
+int usb_gadget_register_notify(struct usb_gadget *gadget,
+  struct notifier_block *nb);
+
+/*-*/
+
+
+/* Unregister a notifiee from the usb gadget */
+int usb_gadget_unregister_notify(struct usb_gadget *gadget,
+struct notifier_block *nb);
+
+/*-*/
+
 /* utility to set gadget state properly */
 
 extern void usb_gadget_set_state(struct usb_gadget *gadget,
-- 
1.7.9.5

--
To unsubscribe from this list: send the line

[PATCH v2 3/3] power: wm831x_power: Support USB charger current limit management

2015-08-14 Thread Baolin Wang
Integrate with the newly added USB charger interface to limit the current
we draw from the USB input based on the input device configuration
identified by the USB stack, allowing us to charge more quickly from high
current inputs without drawing more current than specified from others.

Signed-off-by: Mark Brown broo...@kernel.org
Signed-off-by: Baolin Wang baolin.w...@linaro.org
---
 drivers/power/wm831x_power.c |   69 ++
 include/linux/mfd/wm831x/pdata.h |3 ++
 2 files changed, 72 insertions(+)

diff --git a/drivers/power/wm831x_power.c b/drivers/power/wm831x_power.c
index db11ae6..72c661f 100644
--- a/drivers/power/wm831x_power.c
+++ b/drivers/power/wm831x_power.c
@@ -13,6 +13,7 @@
 #include linux/platform_device.h
 #include linux/power_supply.h
 #include linux/slab.h
+#include linux/usb/usb_charger.h
 
 #include linux/mfd/wm831x/core.h
 #include linux/mfd/wm831x/auxadc.h
@@ -31,6 +32,8 @@ struct wm831x_power {
char usb_name[20];
char battery_name[20];
bool have_battery;
+   struct usb_charger *usb_charger;
+   struct notifier_block usb_notify;
 };
 
 static int wm831x_power_check_online(struct wm831x *wm831x, int supply,
@@ -125,6 +128,43 @@ static enum power_supply_property wm831x_usb_props[] = {
POWER_SUPPLY_PROP_VOLTAGE_NOW,
 };
 
+/* In miliamps */
+static unsigned int wm831x_usb_limits[] = {
+   0,
+   2,
+   100,
+   500,
+   900,
+   1500,
+   1800,
+   550,
+};
+
+static int wm831x_usb_limit_change(struct notifier_block *nb,
+  unsigned long limit, void *data)
+{
+   struct wm831x_power *wm831x_power = container_of(nb,
+struct wm831x_power,
+usb_notify);
+   int i, best;
+
+   /* Find the highest supported limit */
+   best = 0;
+   for (i = 0; i  ARRAY_SIZE(wm831x_usb_limits); i++) {
+   if (limit  wm831x_usb_limits[i] 
+   wm831x_usb_limits[best]  wm831x_usb_limits[i])
+   best = i;
+   }
+
+   dev_dbg(wm831x_power-wm831x-dev,
+   Limiting USB current to %dmA, wm831x_usb_limits[best]);
+
+   wm831x_set_bits(wm831x_power-wm831x, WM831X_POWER_STATE,
+   WM831X_USB_ILIM_MASK, best);
+
+   return 0;
+}
+
 /*
  * Battery properties
  */
@@ -606,8 +646,31 @@ static int wm831x_power_probe(struct platform_device *pdev)
}
}
 
+   if (wm831x_pdata  wm831x_pdata-usb_gadget) {
+   power-usb_charger =
+   usb_charger_find_by_name(wm831x_pdata-usb_gadget);
+   if (IS_ERR(power-usb_charger)) {
+   ret = PTR_ERR(power-usb_charger);
+   dev_err(pdev-dev,
+   Failed to find USB gadget: %d\n, ret);
+   goto err_bat_irq;
+   }
+
+   power-usb_notify.notifier_call = wm831x_usb_limit_change;
+
+   ret = usb_charger_register_notify(power-usb_charger,
+ power-usb_notify);
+   if (ret != 0) {
+   dev_err(pdev-dev,
+   Failed to register notifier: %d\n, ret);
+   goto err_usb_charger;
+   }
+   }
+
return ret;
 
+err_usb_charger:
+   usb_charger_put(power-usb_charger);
 err_bat_irq:
--i;
for (; i = 0; i--) {
@@ -637,6 +700,12 @@ static int wm831x_power_remove(struct platform_device 
*pdev)
struct wm831x *wm831x = wm831x_power-wm831x;
int irq, i;
 
+   if (wm831x_power-usb_charger) {
+   usb_charger_unregister_notify(wm831x_power-usb_charger,
+ wm831x_power-usb_notify);
+   usb_charger_put(wm831x_power-usb_charger);
+   }
+
for (i = 0; i  ARRAY_SIZE(wm831x_bat_irqs); i++) {
irq = wm831x_irq(wm831x, 
 platform_get_irq_byname(pdev,
diff --git a/include/linux/mfd/wm831x/pdata.h b/include/linux/mfd/wm831x/pdata.h
index dcc9631..5af8399 100644
--- a/include/linux/mfd/wm831x/pdata.h
+++ b/include/linux/mfd/wm831x/pdata.h
@@ -126,6 +126,9 @@ struct wm831x_pdata {
/** The driver should initiate a power off sequence during shutdown */
bool soft_shutdown;
 
+   /** dev_name of USB charger gadget to integrate with */
+   const char *usb_gadget;
+
int irq_base;
int gpio_base;
int gpio_defaults[WM831X_GPIO_NUM];
-- 
1.7.9.5

--
To unsubscribe from this list: send the line unsubscribe linux-usb in
the body of a message to majord...@vger.kernel.org
More majordomo

[PATCH] usb: gadget: Add the console support for usb-to-serial port

2015-10-22 Thread Baolin Wang
It dose not work when we want to use the usb-to-serial port based
on one usb gadget as a console. Thus this patch adds the console
initialization to support this request.

Signed-off-by: Baolin Wang <baolin.w...@linaro.org>
---
 drivers/usb/gadget/Kconfig |6 +
 drivers/usb/gadget/function/u_serial.c |  239 
 2 files changed, 245 insertions(+)

diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig
index 33834aa..be5aab9 100644
--- a/drivers/usb/gadget/Kconfig
+++ b/drivers/usb/gadget/Kconfig
@@ -127,6 +127,12 @@ config USB_GADGET_STORAGE_NUM_BUFFERS
   a module parameter as well.
   If unsure, say 2.
 
+config U_SERIAL_CONSOLE
+   bool "Serial gadget console support"
+   depends on USB_G_SERIAL
+   help
+  It supports the serial gadget can be used as a console.
+
 source "drivers/usb/gadget/udc/Kconfig"
 
 #
diff --git a/drivers/usb/gadget/function/u_serial.c 
b/drivers/usb/gadget/function/u_serial.c
index 9cc6a13..343d530 100644
--- a/drivers/usb/gadget/function/u_serial.c
+++ b/drivers/usb/gadget/function/u_serial.c
@@ -27,6 +27,8 @@
 #include 
 #include 
 #include 
+#include 
+#include 
 
 #include "u_serial.h"
 
@@ -79,6 +81,16 @@
  */
 #define QUEUE_SIZE 16
 #define WRITE_BUF_SIZE 8192/* TX only */
+#define GS_BUFFER_SIZE (4096)
+#define GS_CONSOLE_BUF_SIZE(2 * GS_BUFFER_SIZE)
+
+struct gscons_info {
+   struct gs_port  *port;
+   struct tty_driver   *tty_driver;
+   struct work_struct  work;
+   int buf_tail;
+   charbuf[GS_CONSOLE_BUF_SIZE];
+};
 
 /* circular buffer */
 struct gs_buf {
@@ -117,6 +129,7 @@ struct gs_port {
 
/* REVISIT this state ... */
struct usb_cdc_line_coding port_line_coding;/* 8-N-1 etc */
+   struct usb_request  *console_req;
 };
 
 static struct portmaster {
@@ -1052,6 +1065,7 @@ gs_port_alloc(unsigned port_num, struct 
usb_cdc_line_coding *coding)
 
port->port_num = port_num;
port->port_line_coding = *coding;
+   port->console_req = NULL;
 
ports[port_num].port = port;
 out:
@@ -1141,6 +1155,227 @@ err:
 }
 EXPORT_SYMBOL_GPL(gserial_alloc_line);
 
+#ifdef CONFIG_U_SERIAL_CONSOLE
+
+static struct usb_request *gs_request_new(struct usb_ep *ep, int buffer_size)
+{
+   struct usb_request *req = usb_ep_alloc_request(ep, GFP_ATOMIC);
+
+   if (!req)
+   return NULL;
+
+   /* now allocate buffers for the requests */
+   req->buf = kmalloc(buffer_size, GFP_ATOMIC);
+   if (!req->buf) {
+   usb_ep_free_request(ep, req);
+   return NULL;
+   }
+
+   return req;
+}
+
+static void gs_request_free(struct usb_request *req, struct usb_ep *ep)
+{
+   if (req) {
+   kfree(req->buf);
+   usb_ep_free_request(ep, req);
+   }
+}
+
+static void gs_complete_out(struct usb_ep *ep, struct usb_request *req)
+{
+   if (req->status != 0 && req->status != -ECONNRESET)
+   return;
+}
+
+static struct console gserial_cons;
+static int gs_console_connect(void)
+{
+   struct gscons_info *info = gserial_cons.data;
+   int port_num = gserial_cons.index;
+   struct usb_request *req;
+   struct gs_port *port;
+   struct usb_ep *ep;
+
+   if (port_num >= MAX_U_SERIAL_PORTS || port_num < 0) {
+   pr_err("%s: port num [%d] exceeds the range.\n",
+  __func__, port_num);
+   return -ENXIO;
+   }
+
+   port = ports[port_num].port;
+   if (!port) {
+   pr_err("%s: serial line [%d] not allocated.\n",
+  __func__, port_num);
+   return -ENODEV;
+   }
+
+   if (!port->port_usb) {
+   pr_err("%s: no port usb.\n", __func__);
+   return -ENODEV;
+   }
+
+   ep = port->port_usb->in;
+   if (!ep) {
+   pr_err("%s: no usb endpoint.\n", __func__);
+   return -ENXIO;
+   }
+
+   req = port->console_req;
+   if (!req) {
+   req = gs_request_new(ep, GS_BUFFER_SIZE);
+   if (!req) {
+   pr_err("%s: request fail.\n", __func__);
+   return -ENOMEM;
+   }
+   req->complete = gs_complete_out;
+   }
+
+   info->port = port;
+
+   pr_debug("%s: port[%d] console connect!\n", __func__, port_num);
+   return 0;
+}
+
+static void gs_console_work(struct work_struct *work)
+{
+   struct gscons_info *info = container_of(work, struct gscons_info, work);
+   struct gs_port *port = info->port;
+   struct usb_request *req;
+   struct usb_ep *ep;
+   int xfer, ret, count;
+   char *p;

Re: [PATCH v5 1/5] gadget: Introduce the notifier functions

2015-11-08 Thread Baolin Wang
On 7 November 2015 at 00:56, Greg KH <gre...@linuxfoundation.org> wrote:
> On Fri, Nov 06, 2015 at 07:35:10PM +0800, Baolin Wang wrote:

>>  #ifdef   CONFIG_HAS_DMA
>> diff --git a/include/linux/usb/gadget.h b/include/linux/usb/gadget.h
>> index c14a69b..755e8bc 100644
>> --- a/include/linux/usb/gadget.h
>> +++ b/include/linux/usb/gadget.h
>> @@ -609,6 +609,8 @@ struct usb_gadget {
>>   unsignedout_epnum;
>>   unsignedin_epnum;
>>   struct usb_otg_caps *otg_caps;
>> + struct raw_notifier_headnh;
>> + struct mutexlock;
>
> You have to document what this lock protects.

OK.

>
>
>>
>>   unsignedsg_supported:1;
>>   unsignedis_otg:1;
>> @@ -1183,6 +1185,22 @@ extern void usb_gadget_unmap_request(struct 
>> usb_gadget *gadget,
>>
>>  
>> /*-*/
>>
>> +/**
>> + * Register a notifiee to get notified by any attach status changes from
>> + * the usb gadget
>> + */
>
> kerneldoc does not belong in a .h file.
>

I'll remove the comments.

> And the kbuild system found lots of problems with this series, please
> fix those at the very least :(

I'm sorry for that, I'll check the patches again. Thanks for your comments.

>
> thanks,
>
> greg k-h



-- 
Baolin.wang
Best Regards
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v6 1/4] gadget: Introduce the usb charger framework

2015-11-15 Thread Baolin Wang
This patch introduces the usb charger driver based on usb gadget that
makes an enhancement to a power driver. It works well in practice but
that requires a system with suitable hardware.

The basic conception of the usb charger is that, when one usb charger
is added or removed by reporting from the usb gadget state change or
the extcon device state change, the usb charger will report to power
user to set the current limitation.

The usb charger will register notifiees on the usb gadget or the extcon
device to get notified the usb charger state. It also supplies the
notification mechanism to userspace When the usb charger state is changed.

Power user will register a notifiee on the usb charger to get notified
by status changes from the usb charger. It will report to power user
to set the current limitation when detecting the usb charger is added
or removed from extcon device state or usb gadget state.

This patch doesn't yet integrate with the gadget code, so some functions
which rely on the 'gadget' are not completed, that will be implemented
in the following patches.

Signed-off-by: Baolin Wang <baolin.w...@linaro.org>
---
 drivers/usb/gadget/Kconfig  |7 +
 drivers/usb/gadget/Makefile |1 +
 drivers/usb/gadget/charger.c|  574 +++
 include/linux/usb/usb_charger.h |  162 +++
 4 files changed, 744 insertions(+)
 create mode 100644 drivers/usb/gadget/charger.c
 create mode 100644 include/linux/usb/usb_charger.h

diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig
index 33834aa..8d69dca 100644
--- a/drivers/usb/gadget/Kconfig
+++ b/drivers/usb/gadget/Kconfig
@@ -127,6 +127,13 @@ config USB_GADGET_STORAGE_NUM_BUFFERS
   a module parameter as well.
   If unsure, say 2.
 
+config USB_CHARGER
+   bool "USB charger support"
+   help
+ The usb charger driver based on the usb gadget that makes an
+ enhancement to a power driver which can set the current limitation
+ when the usb charger is added or removed.
+
 source "drivers/usb/gadget/udc/Kconfig"
 
 #
diff --git a/drivers/usb/gadget/Makefile b/drivers/usb/gadget/Makefile
index 598a67d..1e421c1 100644
--- a/drivers/usb/gadget/Makefile
+++ b/drivers/usb/gadget/Makefile
@@ -10,3 +10,4 @@ libcomposite-y:= usbstring.o config.o 
epautoconf.o
 libcomposite-y += composite.o functions.o configfs.o u_f.o
 
 obj-$(CONFIG_USB_GADGET)   += udc/ function/ legacy/
+obj-$(CONFIG_USB_CHARGER)  += charger.o
diff --git a/drivers/usb/gadget/charger.c b/drivers/usb/gadget/charger.c
new file mode 100644
index 000..921f8e2
--- /dev/null
+++ b/drivers/usb/gadget/charger.c
@@ -0,0 +1,574 @@
+/*
+ * charger.c -- USB charger driver
+ *
+ * Copyright (C) 2015 Linaro Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define DEFAULT_CUR_PROTECT(50)
+#define DEFAULT_SDP_CUR_LIMIT  (500 - DEFAULT_CUR_PROTECT)
+#define DEFAULT_DCP_CUR_LIMIT  (1500 - DEFAULT_CUR_PROTECT)
+#define DEFAULT_CDP_CUR_LIMIT  (1500 - DEFAULT_CUR_PROTECT)
+#define DEFAULT_ACA_CUR_LIMIT  (1500 - DEFAULT_CUR_PROTECT)
+#define UCHGER_STATE_LENGTH(50)
+
+static DEFINE_IDA(usb_charger_ida);
+static struct bus_type usb_charger_subsys = {
+   .name   = "usb-charger",
+   .dev_name   = "usb-charger",
+};
+
+static struct usb_charger *dev_to_uchger(struct device *udev)
+{
+   return container_of(udev, struct usb_charger, dev);
+}
+
+static ssize_t cur_limit_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+   struct usb_charger *uchger = dev_to_uchger(dev);
+
+   return scnprintf(buf, PAGE_SIZE, "%d %d %d %d\n",
+uchger->cur_limit.sdp_cur_limit,
+uchger->cur_limit.dcp_cur_limit,
+uchger->cur_limit.cdp_cur_limit,
+uchger->cur_limit.aca_cur_limit);
+}
+
+static ssize_t cur_limit_store(struct device *dev,
+  struct device_attribute *attr,
+  const char *buf, size_t count)
+{
+   struct usb_charger *uchger = dev_to_uchger(dev);
+   struct usb_charger_cur_limit cur;
+   int ret;
+
+   ret = sscanf(buf, "%d %d %d %d",
+_cur_limit, _cur_limit,
+_cur_limit, _cur_limit);
+   if (ret == 0)
+   return -EINVAL;
+
+   ret = usb_charger_set_cur_limit(uchger, );
+   if (ret < 0)
+   return re

[PATCH v6 4/4] power: wm831x_power: Support USB charger current limit management

2015-11-15 Thread Baolin Wang
Integrate with the newly added USB charger interface to limit the current
we draw from the USB input based on the input device configuration
identified by the USB stack, allowing us to charge more quickly from high
current inputs without drawing more current than specified from others.

Signed-off-by: Mark Brown <broo...@kernel.org>
Signed-off-by: Baolin Wang <baolin.w...@linaro.org>
Acked-by: Lee Jones <lee.jo...@linaro.org>
Acked-by: Charles Keepax <ckee...@opensource.wolfsonmicro.com>
Acked-by: Peter Chen <peter.c...@freescale.com>
Acked-by: Sebastian Reichel <s...@kernel.org>
---
 drivers/power/wm831x_power.c |   69 ++
 include/linux/mfd/wm831x/pdata.h |3 ++
 2 files changed, 72 insertions(+)

diff --git a/drivers/power/wm831x_power.c b/drivers/power/wm831x_power.c
index 7082301..043f1f4 100644
--- a/drivers/power/wm831x_power.c
+++ b/drivers/power/wm831x_power.c
@@ -13,6 +13,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include 
 #include 
@@ -31,6 +32,8 @@ struct wm831x_power {
char usb_name[20];
char battery_name[20];
bool have_battery;
+   struct usb_charger *usb_charger;
+   struct notifier_block usb_notify;
 };
 
 static int wm831x_power_check_online(struct wm831x *wm831x, int supply,
@@ -125,6 +128,43 @@ static enum power_supply_property wm831x_usb_props[] = {
POWER_SUPPLY_PROP_VOLTAGE_NOW,
 };
 
+/* In milliamps */
+static unsigned int wm831x_usb_limits[] = {
+   0,
+   2,
+   100,
+   500,
+   900,
+   1500,
+   1800,
+   550,
+};
+
+static int wm831x_usb_limit_change(struct notifier_block *nb,
+  unsigned long limit, void *data)
+{
+   struct wm831x_power *wm831x_power = container_of(nb,
+struct wm831x_power,
+usb_notify);
+   int i, best;
+
+   /* Find the highest supported limit */
+   best = 0;
+   for (i = 0; i < ARRAY_SIZE(wm831x_usb_limits); i++) {
+   if (limit >= wm831x_usb_limits[i] &&
+   wm831x_usb_limits[best] < wm831x_usb_limits[i])
+   best = i;
+   }
+
+   dev_dbg(wm831x_power->wm831x->dev,
+   "Limiting USB current to %dmA", wm831x_usb_limits[best]);
+
+   wm831x_set_bits(wm831x_power->wm831x, WM831X_POWER_STATE,
+   WM831X_USB_ILIM_MASK, best);
+
+   return 0;
+}
+
 /*
  * Battery properties
  */
@@ -607,8 +647,31 @@ static int wm831x_power_probe(struct platform_device *pdev)
}
}
 
+   if (wm831x_pdata && wm831x_pdata->usb_gadget) {
+   power->usb_charger =
+   usb_charger_find_by_name(wm831x_pdata->usb_gadget);
+   if (IS_ERR(power->usb_charger)) {
+   ret = PTR_ERR(power->usb_charger);
+   dev_err(>dev,
+   "Failed to find USB gadget: %d\n", ret);
+   goto err_bat_irq;
+   }
+
+   power->usb_notify.notifier_call = wm831x_usb_limit_change;
+
+   ret = usb_charger_register_notify(power->usb_charger,
+ >usb_notify);
+   if (ret != 0) {
+   dev_err(>dev,
+   "Failed to register notifier: %d\n", ret);
+   goto err_usb_charger;
+   }
+   }
+
return ret;
 
+err_usb_charger:
+   /* put_device on charger */
 err_bat_irq:
--i;
for (; i >= 0; i--) {
@@ -637,6 +700,12 @@ static int wm831x_power_remove(struct platform_device 
*pdev)
struct wm831x *wm831x = wm831x_power->wm831x;
int irq, i;
 
+   if (wm831x_power->usb_charger) {
+   usb_charger_unregister_notify(wm831x_power->usb_charger,
+ _power->usb_notify);
+   /* Free charger */
+   }
+
for (i = 0; i < ARRAY_SIZE(wm831x_bat_irqs); i++) {
irq = wm831x_irq(wm831x, 
 platform_get_irq_byname(pdev,
diff --git a/include/linux/mfd/wm831x/pdata.h b/include/linux/mfd/wm831x/pdata.h
index dcc9631..5af8399 100644
--- a/include/linux/mfd/wm831x/pdata.h
+++ b/include/linux/mfd/wm831x/pdata.h
@@ -126,6 +126,9 @@ struct wm831x_pdata {
/** The driver should initiate a power off sequence during shutdown */
bool soft_shutdown;
 
+   /** dev_name of USB charger gadget to integrate with */
+   const char *usb_gadget;
+
int irq_base;
int gpi

[PATCH v6 3/4] gadget: Integrate with the usb gadget supporting for usb charger

2015-11-15 Thread Baolin Wang
When the usb gadget supporting for usb charger is ready, the usb charger
should get the type by the 'get_charger_type' callback which is implemented
by the usb gadget operations, and get the usb charger pointer from struct
'usb_gadget'.

Signed-off-by: Baolin Wang <baolin.w...@linaro.org>
---
 drivers/usb/gadget/charger.c |   43 --
 1 file changed, 41 insertions(+), 2 deletions(-)

diff --git a/drivers/usb/gadget/charger.c b/drivers/usb/gadget/charger.c
index 921f8e2..5d3cda6 100644
--- a/drivers/usb/gadget/charger.c
+++ b/drivers/usb/gadget/charger.c
@@ -183,7 +183,11 @@ int usb_charger_unregister_notify(struct usb_charger 
*uchger,
 enum usb_charger_type
 usb_charger_detect_type(struct usb_charger *uchger)
 {
-   if (uchger->psy) {
+   if (uchger->gadget && uchger->gadget->ops
+   && uchger->gadget->ops->get_charger_type) {
+   uchger->type =
+   uchger->gadget->ops->get_charger_type(uchger->gadget);
+   } else if (uchger->psy) {
union power_supply_propval val;
 
power_supply_get_property(uchger->psy,
@@ -385,6 +389,29 @@ usb_charger_plug_by_extcon(struct notifier_block *nb,
 int usb_charger_plug_by_gadget(struct usb_gadget *gadget,
   unsigned long state)
 {
+   struct usb_charger *uchger = gadget->charger;
+   enum usb_charger_state uchger_state;
+
+   if (!uchger)
+   return -EINVAL;
+
+   /* Report event to power to setting the current limitation
+* for this usb charger when one usb charger state is changed
+* with detecting by usb gadget state.
+*/
+   if (uchger->old_gadget_state != state) {
+   uchger->old_gadget_state = state;
+
+   if (state >= USB_STATE_ATTACHED)
+   uchger_state = USB_CHARGER_PRESENT;
+   else if (state == USB_STATE_NOTATTACHED)
+   uchger_state = USB_CHARGER_REMOVE;
+   else
+   uchger_state = USB_CHARGER_DEFAULT;
+
+   usb_charger_notify_others(uchger, uchger_state);
+   }
+
return 0;
 }
 
@@ -540,6 +567,7 @@ int usb_charger_init(struct usb_gadget *ugadget)
 
/* register a notifier on a usb gadget device */
uchger->gadget = ugadget;
+   ugadget->charger = uchger;
uchger->old_gadget_state = ugadget->state;
 
/* register a new usb charger */
@@ -560,7 +588,18 @@ fail:
 
 int usb_charger_exit(struct usb_gadget *ugadget)
 {
-   return 0;
+   struct usb_charger *uchger = ugadget->charger;
+
+   if (!uchger)
+   return -EINVAL;
+
+   if (uchger->extcon_dev)
+   extcon_unregister_notifier(uchger->extcon_dev,
+  EXTCON_USB, >extcon_nb.nb);
+
+   ida_simple_remove(_charger_ida, uchger->id);
+
+   return usb_charger_unregister(uchger);
 }
 
 static int __init usb_charger_sysfs_init(void)
-- 
1.7.9.5

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v6 0/4] Introduce usb charger framework to deal with the usb gadget power negotation

2015-11-15 Thread Baolin Wang
Currently the Linux kernel does not provide any standard integration of this
feature that integrates the USB subsystem with the system power regulation
provided by PMICs meaning that either vendors must add this in their kernels
or USB gadget devices based on Linux (such as mobile phones) may not behave
as they should. Thus provide a standard framework for doing this in kernel.

Now introduce one user with wm831x_power to support and test the usb charger,
which is pending testing. Moreover there may be other potential users will use
it in future.

Changes since v5:
 - Remove the notifier chain things from the gadget and introduce one callback
 function to report to the usb charger when the gadget state is changed.
 - Flesh out the port type detection which combines the USB negotiation and
 PMICs detection.
 - Supply the notification mechanism to userspace when charger state is changed.
 - Integrate with the vbus staff in the gadget API.

Baolin Wang (4):
  gadget: Introduce the usb charger framework
  gadget: Support for the usb charger framework
  gadget: Integrate with the usb gadget supporting for usb charger
  power: wm831x_power: Support USB charger current limit management

 drivers/power/wm831x_power.c  |   69 +
 drivers/usb/gadget/Kconfig|7 +
 drivers/usb/gadget/Makefile   |1 +
 drivers/usb/gadget/charger.c  |  613 +
 drivers/usb/gadget/udc/udc-core.c |   11 +
 include/linux/mfd/wm831x/pdata.h  |3 +
 include/linux/usb/gadget.h|   10 +
 include/linux/usb/usb_charger.h   |  162 ++
 8 files changed, 876 insertions(+)
 create mode 100644 drivers/usb/gadget/charger.c
 create mode 100644 include/linux/usb/usb_charger.h

-- 
1.7.9.5

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v6 2/4] gadget: Support for the usb charger framework

2015-11-15 Thread Baolin Wang
For supporting the usb charger, it adds the usb_charger_init() and
usb_charger_exit() functions for usb charger initialization and exit.

It will report to the usb charger when the gadget state is changed,
then the usb charger can do the power things.

Introduce a callback 'get_charger_type' which will implemented by
user for usb gadget operations to get the usb charger type.

Signed-off-by: Baolin Wang <baolin.w...@linaro.org>
---
 drivers/usb/gadget/udc/udc-core.c |   11 +++
 include/linux/usb/gadget.h|   10 ++
 2 files changed, 21 insertions(+)

diff --git a/drivers/usb/gadget/udc/udc-core.c 
b/drivers/usb/gadget/udc/udc-core.c
index f660afb..2727f01 100644
--- a/drivers/usb/gadget/udc/udc-core.c
+++ b/drivers/usb/gadget/udc/udc-core.c
@@ -28,6 +28,7 @@
 #include 
 #include 
 #include 
+#include 
 
 /**
  * struct usb_udc - describes one usb device controller
@@ -226,6 +227,9 @@ static void usb_gadget_state_work(struct work_struct *work)
struct usb_gadget *gadget = work_to_gadget(work);
struct usb_udc *udc = gadget->udc;
 
+   /* when the gadget state is changed, then report to USB charger */
+   usb_charger_plug_by_gadget(gadget, gadget->state);
+
if (udc)
sysfs_notify(>dev.kobj, NULL, "state");
 }
@@ -405,8 +409,14 @@ int usb_add_gadget_udc_release(struct device *parent, 
struct usb_gadget *gadget,
 
mutex_unlock(_lock);
 
+   ret = usb_charger_init(gadget);
+   if (ret)
+   goto err5;
+
return 0;
 
+err5:
+   device_del(>dev);
 err4:
list_del(>list);
mutex_unlock(_lock);
@@ -481,6 +491,7 @@ void usb_del_gadget_udc(struct usb_gadget *gadget)
kobject_uevent(>dev.kobj, KOBJ_REMOVE);
flush_work(>work);
device_unregister(>dev);
+   usb_charger_exit(gadget);
device_unregister(>dev);
 }
 EXPORT_SYMBOL_GPL(usb_del_gadget_udc);
diff --git a/include/linux/usb/gadget.h b/include/linux/usb/gadget.h
index 3d583a1..b8a6d38 100644
--- a/include/linux/usb/gadget.h
+++ b/include/linux/usb/gadget.h
@@ -24,6 +24,7 @@
 #include 
 #include 
 #include 
+#include 
 
 struct usb_ep;
 
@@ -560,6 +561,7 @@ struct usb_gadget_ops {
struct usb_ep *(*match_ep)(struct usb_gadget *,
struct usb_endpoint_descriptor *,
struct usb_ss_ep_comp_descriptor *);
+   enum usb_charger_type (*get_charger_type)(struct usb_gadget *);
 };
 
 /**
@@ -632,6 +634,8 @@ struct usb_gadget {
unsignedout_epnum;
unsignedin_epnum;
struct usb_otg_caps *otg_caps;
+   /* negotiate the power with the usb charger */
+   struct usb_charger  *charger;
 
unsignedsg_supported:1;
unsignedis_otg:1;
@@ -836,10 +840,16 @@ static inline int usb_gadget_vbus_connect(struct 
usb_gadget *gadget)
  * reporting how much power the device may consume.  For example, this
  * could affect how quickly batteries are recharged.
  *
+ * It will also notify the USB charger how much power the device may
+ * consume if there is a USB charger linking with the gadget.
+ *
  * Returns zero on success, else negative errno.
  */
 static inline int usb_gadget_vbus_draw(struct usb_gadget *gadget, unsigned mA)
 {
+   if (gadget->charger)
+   usb_charger_set_cur_limit_by_type(gadget->charger, mA);
+
if (!gadget->ops->vbus_draw)
return -EOPNOTSUPP;
return gadget->ops->vbus_draw(gadget, mA);
-- 
1.7.9.5

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH] usb: gadget: Add the console support for usb-to-serial port

2015-11-15 Thread Baolin Wang
It dose not work when we want to use the usb-to-serial port based
on one usb gadget as a console. Thus this patch adds the console
initialization to support this request.

Signed-off-by: Baolin Wang <baolin.w...@linaro.org>
---
 drivers/usb/gadget/Kconfig |6 +
 drivers/usb/gadget/function/u_serial.c |  238 
 2 files changed, 244 insertions(+)

diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig
index 33834aa..be5aab9 100644
--- a/drivers/usb/gadget/Kconfig
+++ b/drivers/usb/gadget/Kconfig
@@ -127,6 +127,12 @@ config USB_GADGET_STORAGE_NUM_BUFFERS
   a module parameter as well.
   If unsure, say 2.
 
+config U_SERIAL_CONSOLE
+   bool "Serial gadget console support"
+   depends on USB_G_SERIAL
+   help
+  It supports the serial gadget can be used as a console.
+
 source "drivers/usb/gadget/udc/Kconfig"
 
 #
diff --git a/drivers/usb/gadget/function/u_serial.c 
b/drivers/usb/gadget/function/u_serial.c
index f7771d8..4ade527 100644
--- a/drivers/usb/gadget/function/u_serial.c
+++ b/drivers/usb/gadget/function/u_serial.c
@@ -27,6 +27,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include "u_serial.h"
 
@@ -79,6 +80,16 @@
  */
 #define QUEUE_SIZE 16
 #define WRITE_BUF_SIZE 8192/* TX only */
+#define GS_BUFFER_SIZE (4096)
+#define GS_CONSOLE_BUF_SIZE(2 * GS_BUFFER_SIZE)
+
+struct gscons_info {
+   struct gs_port  *port;
+   struct tty_driver   *tty_driver;
+   struct work_struct  work;
+   int buf_tail;
+   charbuf[GS_CONSOLE_BUF_SIZE];
+};
 
 /* circular buffer */
 struct gs_buf {
@@ -118,6 +129,7 @@ struct gs_port {
 
/* REVISIT this state ... */
struct usb_cdc_line_coding port_line_coding;/* 8-N-1 etc */
+   struct usb_request  *console_req;
 };
 
 static struct portmaster {
@@ -1054,6 +1066,7 @@ gs_port_alloc(unsigned port_num, struct 
usb_cdc_line_coding *coding)
 
port->port_num = port_num;
port->port_line_coding = *coding;
+   port->console_req = NULL;
 
ports[port_num].port = port;
 out:
@@ -1143,6 +1156,227 @@ err:
 }
 EXPORT_SYMBOL_GPL(gserial_alloc_line);
 
+#ifdef CONFIG_U_SERIAL_CONSOLE
+
+static struct usb_request *gs_request_new(struct usb_ep *ep, int buffer_size)
+{
+   struct usb_request *req = usb_ep_alloc_request(ep, GFP_ATOMIC);
+
+   if (!req)
+   return NULL;
+
+   /* now allocate buffers for the requests */
+   req->buf = kmalloc(buffer_size, GFP_ATOMIC);
+   if (!req->buf) {
+   usb_ep_free_request(ep, req);
+   return NULL;
+   }
+
+   return req;
+}
+
+static void gs_request_free(struct usb_request *req, struct usb_ep *ep)
+{
+   if (req) {
+   kfree(req->buf);
+   usb_ep_free_request(ep, req);
+   }
+}
+
+static void gs_complete_out(struct usb_ep *ep, struct usb_request *req)
+{
+   if (req->status != 0 && req->status != -ECONNRESET)
+   return;
+}
+
+static struct console gserial_cons;
+static int gs_console_connect(void)
+{
+   struct gscons_info *info = gserial_cons.data;
+   int port_num = gserial_cons.index;
+   struct usb_request *req;
+   struct gs_port *port;
+   struct usb_ep *ep;
+
+   if (port_num >= MAX_U_SERIAL_PORTS || port_num < 0) {
+   pr_err("%s: port num [%d] exceeds the range.\n",
+  __func__, port_num);
+   return -ENXIO;
+   }
+
+   port = ports[port_num].port;
+   if (!port) {
+   pr_err("%s: serial line [%d] not allocated.\n",
+  __func__, port_num);
+   return -ENODEV;
+   }
+
+   if (!port->port_usb) {
+   pr_err("%s: no port usb.\n", __func__);
+   return -ENODEV;
+   }
+
+   ep = port->port_usb->in;
+   if (!ep) {
+   pr_err("%s: no usb endpoint.\n", __func__);
+   return -ENXIO;
+   }
+
+   req = port->console_req;
+   if (!req) {
+   req = gs_request_new(ep, GS_BUFFER_SIZE);
+   if (!req) {
+   pr_err("%s: request fail.\n", __func__);
+   return -ENOMEM;
+   }
+   req->complete = gs_complete_out;
+   }
+
+   info->port = port;
+
+   pr_debug("%s: port[%d] console connect!\n", __func__, port_num);
+   return 0;
+}
+
+static void gs_console_work(struct work_struct *work)
+{
+   struct gscons_info *info = container_of(work, struct gscons_info, work);
+   struct gs_port *port = info->port;
+   struct usb_request *req;
+   struct usb_ep *ep;
+   int xfer, ret, count;
+   char *p;

[PATCH v5 5/5] power: wm831x_power: Support USB charger current limit management

2015-11-06 Thread Baolin Wang
Integrate with the newly added USB charger interface to limit the current
we draw from the USB input based on the input device configuration
identified by the USB stack, allowing us to charge more quickly from high
current inputs without drawing more current than specified from others.

Signed-off-by: Mark Brown <broo...@kernel.org>
Signed-off-by: Baolin Wang <baolin.w...@linaro.org>
Acked-by: Lee Jones <lee.jo...@linaro.org>
Acked-by: Charles Keepax <ckee...@opensource.wolfsonmicro.com>
Acked-by: Peter Chen <peter.c...@freescale.com>
Acked-by: Sebastian Reichel <s...@kernel.org>
---
 drivers/power/wm831x_power.c |   69 ++
 include/linux/mfd/wm831x/pdata.h |3 ++
 2 files changed, 72 insertions(+)

diff --git a/drivers/power/wm831x_power.c b/drivers/power/wm831x_power.c
index db11ae6..33ae27a 100644
--- a/drivers/power/wm831x_power.c
+++ b/drivers/power/wm831x_power.c
@@ -13,6 +13,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include 
 #include 
@@ -31,6 +32,8 @@ struct wm831x_power {
char usb_name[20];
char battery_name[20];
bool have_battery;
+   struct usb_charger *usb_charger;
+   struct notifier_block usb_notify;
 };
 
 static int wm831x_power_check_online(struct wm831x *wm831x, int supply,
@@ -125,6 +128,43 @@ static enum power_supply_property wm831x_usb_props[] = {
POWER_SUPPLY_PROP_VOLTAGE_NOW,
 };
 
+/* In milliamps */
+static unsigned int wm831x_usb_limits[] = {
+   0,
+   2,
+   100,
+   500,
+   900,
+   1500,
+   1800,
+   550,
+};
+
+static int wm831x_usb_limit_change(struct notifier_block *nb,
+  unsigned long limit, void *data)
+{
+   struct wm831x_power *wm831x_power = container_of(nb,
+struct wm831x_power,
+usb_notify);
+   int i, best;
+
+   /* Find the highest supported limit */
+   best = 0;
+   for (i = 0; i < ARRAY_SIZE(wm831x_usb_limits); i++) {
+   if (limit >= wm831x_usb_limits[i] &&
+   wm831x_usb_limits[best] < wm831x_usb_limits[i])
+   best = i;
+   }
+
+   dev_dbg(wm831x_power->wm831x->dev,
+   "Limiting USB current to %dmA", wm831x_usb_limits[best]);
+
+   wm831x_set_bits(wm831x_power->wm831x, WM831X_POWER_STATE,
+   WM831X_USB_ILIM_MASK, best);
+
+   return 0;
+}
+
 /*
  * Battery properties
  */
@@ -606,8 +646,31 @@ static int wm831x_power_probe(struct platform_device *pdev)
}
}
 
+   if (wm831x_pdata && wm831x_pdata->usb_gadget) {
+   power->usb_charger =
+   usb_charger_find_by_name(wm831x_pdata->usb_gadget);
+   if (IS_ERR(power->usb_charger)) {
+   ret = PTR_ERR(power->usb_charger);
+   dev_err(>dev,
+   "Failed to find USB gadget: %d\n", ret);
+   goto err_bat_irq;
+   }
+
+   power->usb_notify.notifier_call = wm831x_usb_limit_change;
+
+   ret = usb_charger_register_notify(power->usb_charger,
+ >usb_notify);
+   if (ret != 0) {
+   dev_err(>dev,
+   "Failed to register notifier: %d\n", ret);
+   goto err_usb_charger;
+   }
+   }
+
return ret;
 
+err_usb_charger:
+   /* put_device on charger */
 err_bat_irq:
--i;
for (; i >= 0; i--) {
@@ -637,6 +700,12 @@ static int wm831x_power_remove(struct platform_device 
*pdev)
struct wm831x *wm831x = wm831x_power->wm831x;
int irq, i;
 
+   if (wm831x_power->usb_charger) {
+   usb_charger_unregister_notify(wm831x_power->usb_charger,
+ _power->usb_notify);
+   /* Free charger */
+   }
+
for (i = 0; i < ARRAY_SIZE(wm831x_bat_irqs); i++) {
irq = wm831x_irq(wm831x, 
 platform_get_irq_byname(pdev,
diff --git a/include/linux/mfd/wm831x/pdata.h b/include/linux/mfd/wm831x/pdata.h
index dcc9631..5af8399 100644
--- a/include/linux/mfd/wm831x/pdata.h
+++ b/include/linux/mfd/wm831x/pdata.h
@@ -126,6 +126,9 @@ struct wm831x_pdata {
/** The driver should initiate a power off sequence during shutdown */
bool soft_shutdown;
 
+   /** dev_name of USB charger gadget to integrate with */
+   const char *usb_gadget;
+
int irq_base;
int gpi

[PATCH v5 2/5] gadget: Introduce the usb charger framework

2015-11-06 Thread Baolin Wang
This patch introduces the usb charger driver based on usb gadget that
makes an enhancement to a power driver. It works well in practice but
that requires a system with suitable hardware.

The basic conception of the usb charger is that, when one usb charger
is added or removed by reporting from the usb gadget state change or
the extcon device state change, the usb charger will report to power
user to set the current limitation.

The usb charger will register notifiees on the usb gadget or the extcon
device to get notified the usb charger state. It also supplies the
notification mechanism to userspace When the usb charger state is changed.

Power user will register a notifiee on the usb charger to get notified
by status changes from the usb charger. It will report to power user
to set the current limitation when detecting the usb charger is added
or removed from extcon device state or usb gadget state.

This patch doesn't yet integrate with the gadget code, so some functions
which rely on the 'gadget' are not completed, that will be implemented
in the following patches.

Signed-off-by: Baolin Wang <baolin.w...@linaro.org>
---
 drivers/usb/gadget/Kconfig  |7 +
 drivers/usb/gadget/Makefile |1 +
 drivers/usb/gadget/charger.c|  579 +++
 include/linux/usb/usb_charger.h |  152 ++
 4 files changed, 739 insertions(+)
 create mode 100644 drivers/usb/gadget/charger.c
 create mode 100644 include/linux/usb/usb_charger.h

diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig
index bcf83c0..3d2b959 100644
--- a/drivers/usb/gadget/Kconfig
+++ b/drivers/usb/gadget/Kconfig
@@ -127,6 +127,13 @@ config USB_GADGET_STORAGE_NUM_BUFFERS
   a module parameter as well.
   If unsure, say 2.
 
+config USB_CHARGER
+   bool "USB charger support"
+   help
+ The usb charger driver based on the usb gadget that makes an
+ enhancement to a power driver which can set the current limitation
+ when the usb charger is added or removed.
+
 source "drivers/usb/gadget/udc/Kconfig"
 
 #
diff --git a/drivers/usb/gadget/Makefile b/drivers/usb/gadget/Makefile
index 598a67d..1e421c1 100644
--- a/drivers/usb/gadget/Makefile
+++ b/drivers/usb/gadget/Makefile
@@ -10,3 +10,4 @@ libcomposite-y:= usbstring.o config.o 
epautoconf.o
 libcomposite-y += composite.o functions.o configfs.o u_f.o
 
 obj-$(CONFIG_USB_GADGET)   += udc/ function/ legacy/
+obj-$(CONFIG_USB_CHARGER)  += charger.o
diff --git a/drivers/usb/gadget/charger.c b/drivers/usb/gadget/charger.c
new file mode 100644
index 000..8387820
--- /dev/null
+++ b/drivers/usb/gadget/charger.c
@@ -0,0 +1,579 @@
+/*
+ * charger.c -- USB charger driver
+ *
+ * Copyright (C) 2015 Linaro Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define DEFAULT_CUR_PROTECT(50)
+#define DEFAULT_SDP_CUR_LIMIT  (500 - DEFAULT_CUR_PROTECT)
+#define DEFAULT_DCP_CUR_LIMIT  (1500 - DEFAULT_CUR_PROTECT)
+#define DEFAULT_CDP_CUR_LIMIT  (1500 - DEFAULT_CUR_PROTECT)
+#define DEFAULT_ACA_CUR_LIMIT  (1500 - DEFAULT_CUR_PROTECT)
+#define UCHGER_STATE_LENGTH(50)
+
+static DEFINE_IDA(usb_charger_ida);
+static struct bus_type usb_charger_subsys = {
+   .name   = "usb-charger",
+   .dev_name   = "usb-charger",
+};
+
+static struct usb_charger *dev_to_uchger(struct device *udev)
+{
+   return container_of(udev, struct usb_charger, dev);
+}
+
+static ssize_t cur_limit_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+   struct usb_charger *uchger = dev_to_uchger(dev);
+
+   return scnprintf(buf, PAGE_SIZE, "%d %d %d %d\n",
+uchger->cur_limit.sdp_cur_limit,
+uchger->cur_limit.dcp_cur_limit,
+uchger->cur_limit.cdp_cur_limit,
+uchger->cur_limit.aca_cur_limit);
+}
+
+static ssize_t cur_limit_store(struct device *dev,
+  struct device_attribute *attr,
+  const char *buf, size_t count)
+{
+   struct usb_charger *uchger = dev_to_uchger(dev);
+   struct usb_charger_cur_limit cur;
+   int ret;
+
+   ret = sscanf(buf, "%d %d %d %d",
+_cur_limit, _cur_limit,
+_cur_limit, _cur_limit);
+   if (ret == 0)
+   return -EINVAL;
+
+   ret = usb_charger_set_cur_limit(uchger, );
+   if (ret < 0)
+   return ret;
+
+

[PATCH v5 3/5] gadget: Support for the usb charger framework

2015-11-06 Thread Baolin Wang
For supporting the usb charger, it adds the usb_charger_init() and
usb_charger_exit() functions for usb charger initialization and exit.

Introduce a callback 'get_charger_type' which will implemented by
user for usb gadget operations to get the usb charger type.

Signed-off-by: Baolin Wang <baolin.w...@linaro.org>
---
 drivers/usb/gadget/udc/udc-core.c |8 
 include/linux/usb/gadget.h|9 +
 2 files changed, 17 insertions(+)

diff --git a/drivers/usb/gadget/udc/udc-core.c 
b/drivers/usb/gadget/udc/udc-core.c
index 4238fc3..370376e 100644
--- a/drivers/usb/gadget/udc/udc-core.c
+++ b/drivers/usb/gadget/udc/udc-core.c
@@ -28,6 +28,7 @@
 #include 
 #include 
 #include 
+#include 
 
 /**
  * struct usb_udc - describes one usb device controller
@@ -437,8 +438,14 @@ int usb_add_gadget_udc_release(struct device *parent, 
struct usb_gadget *gadget,
 
mutex_unlock(_lock);
 
+   ret = usb_charger_init(gadget);
+   if (ret)
+   goto err5;
+
return 0;
 
+err5:
+   device_del(>dev);
 err4:
list_del(>list);
mutex_unlock(_lock);
@@ -513,6 +520,7 @@ void usb_del_gadget_udc(struct usb_gadget *gadget)
kobject_uevent(>dev.kobj, KOBJ_REMOVE);
flush_work(>work);
device_unregister(>dev);
+   usb_charger_exit(gadget);
device_unregister(>dev);
 }
 EXPORT_SYMBOL_GPL(usb_del_gadget_udc);
diff --git a/include/linux/usb/gadget.h b/include/linux/usb/gadget.h
index 755e8bc..c2610c4 100644
--- a/include/linux/usb/gadget.h
+++ b/include/linux/usb/gadget.h
@@ -24,6 +24,7 @@
 #include 
 #include 
 #include 
+#include 
 
 struct usb_ep;
 
@@ -537,6 +538,7 @@ struct usb_gadget_ops {
struct usb_ep *(*match_ep)(struct usb_gadget *,
struct usb_endpoint_descriptor *,
struct usb_ss_ep_comp_descriptor *);
+   enum usb_charger_type (*get_charger_type)(struct usb_gadget *);
 };
 
 /**
@@ -611,6 +613,7 @@ struct usb_gadget {
struct usb_otg_caps *otg_caps;
struct raw_notifier_headnh;
struct mutexlock;
+   struct usb_charger  *charger;
 
unsignedsg_supported:1;
unsignedis_otg:1;
@@ -815,10 +818,16 @@ static inline int usb_gadget_vbus_connect(struct 
usb_gadget *gadget)
  * reporting how much power the device may consume.  For example, this
  * could affect how quickly batteries are recharged.
  *
+ * It will also notify the USB charger how much power the device may
+ * consume if there is a USB charger linking with the gadget.
+ *
  * Returns zero on success, else negative errno.
  */
 static inline int usb_gadget_vbus_draw(struct usb_gadget *gadget, unsigned mA)
 {
+   if (gadget->charger)
+   usb_charger_set_cur_limit_by_type(gadget->charger, mA);
+
if (!gadget->ops->vbus_draw)
return -EOPNOTSUPP;
return gadget->ops->vbus_draw(gadget, mA);
-- 
1.7.9.5

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v5 0/5] Introduce usb charger framework to deal with the usb gadget power negotation

2015-11-06 Thread Baolin Wang
Currently the Linux kernel does not provide any standard integration of this
feature that integrates the USB subsystem with the system power regulation
provided by PMICs meaning that either vendors must add this in their kernels
or USB gadget devices based on Linux (such as mobile phones) may not behave
as they should. Thus provide a standard framework for doing this in kernel.

Now introduce one user with wm831x_power to support and test the usb charger,
which is pending testing. Moreover there may be other potential users will use
it in future.

Changes since v4:
 - Flesh out the port type detection which combines the USB negotiation and
 PMICs detection.
 - Supply the notification mechanism to userspace when charger state is changed.
 - Integrate with the vbus staff in the gadget API.

Baolin Wang (5):
  gadget: Introduce the notifier functions
  gadget: Introduce the usb charger framework
  gadget: Support for the usb charger framework
  gadget: Integrate with the usb gadget supporting for usb charger
  power: wm831x_power: Support USB charger current limit management

 drivers/power/wm831x_power.c  |   69 +
 drivers/usb/gadget/Kconfig|7 +
 drivers/usb/gadget/Makefile   |1 +
 drivers/usb/gadget/charger.c  |  620 +
 drivers/usb/gadget/udc/udc-core.c |   40 +++
 include/linux/mfd/wm831x/pdata.h  |3 +
 include/linux/usb/gadget.h|   27 ++
 include/linux/usb/usb_charger.h   |  152 +
 8 files changed, 919 insertions(+)
 create mode 100644 drivers/usb/gadget/charger.c
 create mode 100644 include/linux/usb/usb_charger.h

-- 
1.7.9.5

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v5 4/5] gadget: Integrate with the usb gadget supporting for usb charger

2015-11-06 Thread Baolin Wang
When the usb gadget supporting for usb charger is ready, the usb charger
should get the type by the 'get_charger_type' callback which is implemented
by the usb gadget operations, and get the usb charger pointer from struct
'usb_gadget'.

Signed-off-by: Baolin Wang <baolin.w...@linaro.org>
---
 drivers/usb/gadget/charger.c |   45 --
 1 file changed, 43 insertions(+), 2 deletions(-)

diff --git a/drivers/usb/gadget/charger.c b/drivers/usb/gadget/charger.c
index 8387820..c260317 100644
--- a/drivers/usb/gadget/charger.c
+++ b/drivers/usb/gadget/charger.c
@@ -183,7 +183,11 @@ int usb_charger_unregister_notify(struct usb_charger 
*uchger,
 enum usb_charger_type
 usb_charger_detect_type(struct usb_charger *uchger)
 {
-   if (uchger->psy) {
+   if (uchger->gadget && uchger->gadget->ops
+   && uchger->gadget->ops->get_charger_type) {
+   uchger->type =
+   uchger->gadget->ops->get_charger_type(uchger->gadget);
+   } else if (uchger->psy) {
union power_supply_propval val;
 
power_supply_get_property(uchger->psy,
@@ -387,6 +391,30 @@ static int
 usb_charger_plug_by_gadget(struct notifier_block *nb,
   unsigned long state, void *data)
 {
+   struct usb_gadget *gadget = (struct usb_gadget *)data;
+   struct usb_charger *uchger = gadget->charger;
+   enum usb_charger_state uchger_state;
+
+   if (!uchger)
+   return NOTIFY_BAD;
+
+   /* Report event to power to setting the current limitation
+* for this usb charger when one usb charger state is changed
+* with detecting by usb gadget state.
+*/
+   if (uchger->old_gadget_state != state) {
+   uchger->old_gadget_state = state;
+
+   if (state >= USB_STATE_ATTACHED)
+   uchger_state = USB_CHARGER_PRESENT;
+   else if (state == USB_STATE_NOTATTACHED)
+   uchger_state = USB_CHARGER_REMOVE;
+   else
+   uchger_state = USB_CHARGER_DEFAULT;
+
+   usb_charger_notify_others(uchger, uchger_state);
+   }
+
return NOTIFY_OK;
 }
 
@@ -542,6 +570,7 @@ int usb_charger_init(struct usb_gadget *ugadget)
 
/* register a notifier on a usb gadget device */
uchger->gadget = ugadget;
+   ugadget->charger = uchger;
uchger->old_gadget_state = ugadget->state;
uchger->gadget_nb.notifier_call = usb_charger_plug_by_gadget;
usb_gadget_register_notify(ugadget, >gadget_nb);
@@ -565,7 +594,19 @@ fail:
 
 int usb_charger_exit(struct usb_gadget *ugadget)
 {
-   return 0;
+   struct usb_charger *uchger = ugadget->charger;
+
+   if (!uchger)
+   return -EINVAL;
+
+   if (uchger->extcon_dev)
+   extcon_unregister_notifier(uchger->extcon_dev,
+  EXTCON_USB, >extcon_nb.nb);
+
+   usb_gadget_unregister_notify(uchger->gadget, >gadget_nb);
+   ida_simple_remove(_charger_ida, uchger->id);
+
+   return usb_charger_unregister(uchger);
 }
 
 static int __init usb_charger_sysfs_init(void)
-- 
1.7.9.5

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v5 1/5] gadget: Introduce the notifier functions

2015-11-06 Thread Baolin Wang
The usb charger framework is based on usb gadget. The usb charger
need to be notified the state changing of usb gadget to confirm the
usb charger state.

Thus this patch adds a notifier mechanism for usb gadget to report a
event to usb charger when the usb gadget state is changed.

Signed-off-by: Baolin Wang <baolin.w...@linaro.org>
---
 drivers/usb/gadget/udc/udc-core.c |   32 
 include/linux/usb/gadget.h|   18 ++
 2 files changed, 50 insertions(+)

diff --git a/drivers/usb/gadget/udc/udc-core.c 
b/drivers/usb/gadget/udc/udc-core.c
index f660afb..4238fc3 100644
--- a/drivers/usb/gadget/udc/udc-core.c
+++ b/drivers/usb/gadget/udc/udc-core.c
@@ -129,6 +129,32 @@ void usb_gadget_giveback_request(struct usb_ep *ep,
 }
 EXPORT_SYMBOL_GPL(usb_gadget_giveback_request);
 
+int usb_gadget_register_notify(struct usb_gadget *gadget,
+  struct notifier_block *nb)
+{
+   int ret;
+
+   mutex_lock(>lock);
+   ret = raw_notifier_chain_register(>nh, nb);
+   mutex_unlock(>lock);
+
+   return ret;
+}
+EXPORT_SYMBOL_GPL(usb_gadget_register_notify);
+
+int usb_gadget_unregister_notify(struct usb_gadget *gadget,
+struct notifier_block *nb)
+{
+   int ret;
+
+   mutex_lock(>lock);
+   ret = raw_notifier_chain_unregister(>nh, nb);
+   mutex_unlock(>lock);
+
+   return ret;
+}
+EXPORT_SYMBOL_GPL(usb_gadget_unregister_notify);
+
 /* - */
 
 /**
@@ -226,6 +252,10 @@ static void usb_gadget_state_work(struct work_struct *work)
struct usb_gadget *gadget = work_to_gadget(work);
struct usb_udc *udc = gadget->udc;
 
+   mutex_lock(>lock);
+   raw_notifier_call_chain(>nh, gadget->state, gadget);
+   mutex_unlock(>lock);
+
if (udc)
sysfs_notify(>dev.kobj, NULL, "state");
 }
@@ -364,6 +394,8 @@ int usb_add_gadget_udc_release(struct device *parent, 
struct usb_gadget *gadget,
 
dev_set_name(>dev, "gadget");
INIT_WORK(>work, usb_gadget_state_work);
+   RAW_INIT_NOTIFIER_HEAD(>nh);
+   mutex_init(>lock);
gadget->dev.parent = parent;
 
 #ifdef CONFIG_HAS_DMA
diff --git a/include/linux/usb/gadget.h b/include/linux/usb/gadget.h
index c14a69b..755e8bc 100644
--- a/include/linux/usb/gadget.h
+++ b/include/linux/usb/gadget.h
@@ -609,6 +609,8 @@ struct usb_gadget {
unsignedout_epnum;
unsignedin_epnum;
struct usb_otg_caps *otg_caps;
+   struct raw_notifier_headnh;
+   struct mutexlock;
 
unsignedsg_supported:1;
unsignedis_otg:1;
@@ -1183,6 +1185,22 @@ extern void usb_gadget_unmap_request(struct usb_gadget 
*gadget,
 
 /*-*/
 
+/**
+ * Register a notifiee to get notified by any attach status changes from
+ * the usb gadget
+ */
+int usb_gadget_register_notify(struct usb_gadget *gadget,
+  struct notifier_block *nb);
+
+/*-*/
+
+
+/* Unregister a notifiee from the usb gadget */
+int usb_gadget_unregister_notify(struct usb_gadget *gadget,
+struct notifier_block *nb);
+
+/*-*/
+
 /* utility to set gadget state properly */
 
 extern void usb_gadget_set_state(struct usb_gadget *gadget,
-- 
1.7.9.5

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH] usb: gadget: Add the console support for usb-to-serial port

2015-11-17 Thread Baolin Wang
On 17 November 2015 at 21:34, Andy Shevchenko <andy.shevche...@gmail.com> wrote:
> On Mon, Nov 16, 2015 at 9:05 AM, Baolin Wang <baolin.w...@linaro.org> wrote:
>> It dose not work when we want to use the usb-to-serial port based
>> on one usb gadget as a console. Thus this patch adds the console
>> initialization to support this request.
>
>
>> @@ -79,6 +80,16 @@
>>   */
>>  #define QUEUE_SIZE 16
>>  #define WRITE_BUF_SIZE 8192/* TX only */
>> +#define GS_BUFFER_SIZE (4096)
>
> Redundant parens
>

OK. I'll remove it.

>> +#define GS_CONSOLE_BUF_SIZE(2 * GS_BUFFER_SIZE)
>> +
>> +struct gscons_info {
>> +   struct gs_port  *port;
>> +   struct tty_driver   *tty_driver;
>> +   struct work_struct  work;
>> +   int buf_tail;
>> +   charbuf[GS_CONSOLE_BUF_SIZE];
>
> Can't be malloced once?
>

The 'gscons_info' structure is malloced once.

>
>> +static struct usb_request *gs_request_new(struct usb_ep *ep, int 
>> buffer_size)
>> +{
>> +   struct usb_request *req = usb_ep_alloc_request(ep, GFP_ATOMIC);
>> +
>> +   if (!req)
>
> For sake of readability it's better to have assignment explicitly before 'if'.

But I think it is very easy to understand the assignment here with
saving code lines.

>
>> +   return NULL;
>> +
>> +   /* now allocate buffers for the requests */
>> +   req->buf = kmalloc(buffer_size, GFP_ATOMIC);
>> +   if (!req->buf) {
>> +   usb_ep_free_request(ep, req);
>> +   return NULL;
>> +   }
>> +
>> +   return req;
>> +}
>> +
>> +static void gs_request_free(struct usb_request *req, struct usb_ep *ep)
>> +{
>> +   if (req) {
>
> if (!req)
>  return;
>
> ?

Make sense.

>
>> +   kfree(req->buf);
>> +   usb_ep_free_request(ep, req);
>> +   }
>> +}
>> +
>> +static void gs_complete_out(struct usb_ep *ep, struct usb_request *req)
>> +{
>> +   if (req->status != 0 && req->status != -ECONNRESET)
>> +   return;
>
> Something missed here. Currently it's no-op.
>

Yeah. I didn't realize what need to do in the callback here, so just
leave a callback without anything. But maybe something will be added
if there are some requirements in future.

>> +}
>> +
>> +static struct console gserial_cons;
>> +static int gs_console_connect(void)
>> +{
>> +   struct gscons_info *info = gserial_cons.data;
>> +   int port_num = gserial_cons.index;
>> +   struct usb_request *req;
>> +   struct gs_port *port;
>> +   struct usb_ep *ep;
>> +
>> +   if (port_num >= MAX_U_SERIAL_PORTS || port_num < 0) {
>> +   pr_err("%s: port num [%d] exceeds the range.\n",
>> +  __func__, port_num);
>> +   return -ENXIO;
>> +   }
>> +
>> +   port = ports[port_num].port;
>> +   if (!port) {
>> +   pr_err("%s: serial line [%d] not allocated.\n",
>> +  __func__, port_num);
>> +   return -ENODEV;
>> +   }
>> +
>> +   if (!port->port_usb) {
>> +   pr_err("%s: no port usb.\n", __func__);
>
> Starting from here could it be dev_err and so on?

There are no dev_err things and device things in this file, so pr_xxx
is more reasonable.

>
>> +   return -ENODEV;
>> +   }
>> +
>> +   ep = port->port_usb->in;
>> +   if (!ep) {
>> +   pr_err("%s: no usb endpoint.\n", __func__);
>> +   return -ENXIO;
>> +   }
>> +
>> +   req = port->console_req;
>> +   if (!req) {
>> +   req = gs_request_new(ep, GS_BUFFER_SIZE);
>> +   if (!req) {
>> +   pr_err("%s: request fail.\n", __func__);
>> +   return -ENOMEM;
>> +   }
>> +   req->complete = gs_complete_out;
>> +   }
>> +
>> +   info->port = port;
>> +
>> +   pr_debug("%s: port[%d] console connect!\n", __func__, port_num);
>
> Dynamic debug will add function name if asked.

Sorry, I didn't get your point, you mean print the function name is
redundant here?

>
>> +   return 0;
>> +}
>> +
>> +static voi

[PATCH v4 0/5] Introduce usb charger framework to deal with the usb gadget power negotation

2015-09-24 Thread Baolin Wang
Currently the Linux kernel does not provide any standard integration of this
feature that integrates the USB subsystem with the system power regulation
provided by PMICs meaning that either vendors must add this in their kernels
or USB gadget devices based on Linux (such as mobile phones) may not behave
as they should.

Providing a standard framework for doing this in the kernel.

Now introduce one user with wm831x_power to support and test the usb charger,
which is pending testing. Moreover there may be other potential users will use
it in future.

Changes since v3:
 - Re-order the patch and split the patch to avoid breaking build.
 - Other modifications.

Baolin Wang (5):
  gadget: Introduce the notifier functions
  gadget: Introduce the usb charger framework
  gadget: Support for the usb charger framework
  gadget: Integrate with the usb gadget supporting for usb charger
  power: wm831x_power: Support USB charger current limit management

 drivers/power/wm831x_power.c  |  69 +
 drivers/usb/gadget/Kconfig|   7 +
 drivers/usb/gadget/Makefile   |   1 +
 drivers/usb/gadget/charger.c  | 538 ++
 drivers/usb/gadget/udc/udc-core.c |  40 +++
 include/linux/mfd/wm831x/pdata.h  |   3 +
 include/linux/usb/gadget.h|  20 ++
 include/linux/usb/usb_charger.h   | 138 ++
 8 files changed, 816 insertions(+)
 create mode 100644 drivers/usb/gadget/charger.c
 create mode 100644 include/linux/usb/usb_charger.h

-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v4 5/5] power: wm831x_power: Support USB charger current limit management

2015-09-24 Thread Baolin Wang
Integrate with the newly added USB charger interface to limit the current
we draw from the USB input based on the input device configuration
identified by the USB stack, allowing us to charge more quickly from high
current inputs without drawing more current than specified from others.

Signed-off-by: Mark Brown <broo...@kernel.org>
Signed-off-by: Baolin Wang <baolin.w...@linaro.org>
Acked-by: Lee Jones <lee.jo...@linaro.org>
Acked-by: Charles Keepax <ckee...@opensource.wolfsonmicro.com>
Acked-by: Peter Chen <peter.c...@freescale.com>
Acked-by: Sebastian Reichel <s...@kernel.org>
---
 drivers/power/wm831x_power.c | 69 
 include/linux/mfd/wm831x/pdata.h |  3 ++
 2 files changed, 72 insertions(+)

diff --git a/drivers/power/wm831x_power.c b/drivers/power/wm831x_power.c
index db11ae6..33ae27a 100644
--- a/drivers/power/wm831x_power.c
+++ b/drivers/power/wm831x_power.c
@@ -13,6 +13,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include 
 #include 
@@ -31,6 +32,8 @@ struct wm831x_power {
char usb_name[20];
char battery_name[20];
bool have_battery;
+   struct usb_charger *usb_charger;
+   struct notifier_block usb_notify;
 };
 
 static int wm831x_power_check_online(struct wm831x *wm831x, int supply,
@@ -125,6 +128,43 @@ static enum power_supply_property wm831x_usb_props[] = {
POWER_SUPPLY_PROP_VOLTAGE_NOW,
 };
 
+/* In milliamps */
+static unsigned int wm831x_usb_limits[] = {
+   0,
+   2,
+   100,
+   500,
+   900,
+   1500,
+   1800,
+   550,
+};
+
+static int wm831x_usb_limit_change(struct notifier_block *nb,
+  unsigned long limit, void *data)
+{
+   struct wm831x_power *wm831x_power = container_of(nb,
+struct wm831x_power,
+usb_notify);
+   int i, best;
+
+   /* Find the highest supported limit */
+   best = 0;
+   for (i = 0; i < ARRAY_SIZE(wm831x_usb_limits); i++) {
+   if (limit >= wm831x_usb_limits[i] &&
+   wm831x_usb_limits[best] < wm831x_usb_limits[i])
+   best = i;
+   }
+
+   dev_dbg(wm831x_power->wm831x->dev,
+   "Limiting USB current to %dmA", wm831x_usb_limits[best]);
+
+   wm831x_set_bits(wm831x_power->wm831x, WM831X_POWER_STATE,
+   WM831X_USB_ILIM_MASK, best);
+
+   return 0;
+}
+
 /*
  * Battery properties
  */
@@ -606,8 +646,31 @@ static int wm831x_power_probe(struct platform_device *pdev)
}
}
 
+   if (wm831x_pdata && wm831x_pdata->usb_gadget) {
+   power->usb_charger =
+   usb_charger_find_by_name(wm831x_pdata->usb_gadget);
+   if (IS_ERR(power->usb_charger)) {
+   ret = PTR_ERR(power->usb_charger);
+   dev_err(>dev,
+   "Failed to find USB gadget: %d\n", ret);
+   goto err_bat_irq;
+   }
+
+   power->usb_notify.notifier_call = wm831x_usb_limit_change;
+
+   ret = usb_charger_register_notify(power->usb_charger,
+ >usb_notify);
+   if (ret != 0) {
+   dev_err(>dev,
+   "Failed to register notifier: %d\n", ret);
+   goto err_usb_charger;
+   }
+   }
+
return ret;
 
+err_usb_charger:
+   /* put_device on charger */
 err_bat_irq:
--i;
for (; i >= 0; i--) {
@@ -637,6 +700,12 @@ static int wm831x_power_remove(struct platform_device 
*pdev)
struct wm831x *wm831x = wm831x_power->wm831x;
int irq, i;
 
+   if (wm831x_power->usb_charger) {
+   usb_charger_unregister_notify(wm831x_power->usb_charger,
+ _power->usb_notify);
+   /* Free charger */
+   }
+
for (i = 0; i < ARRAY_SIZE(wm831x_bat_irqs); i++) {
irq = wm831x_irq(wm831x, 
 platform_get_irq_byname(pdev,
diff --git a/include/linux/mfd/wm831x/pdata.h b/include/linux/mfd/wm831x/pdata.h
index dcc9631..5af8399 100644
--- a/include/linux/mfd/wm831x/pdata.h
+++ b/include/linux/mfd/wm831x/pdata.h
@@ -126,6 +126,9 @@ struct wm831x_pdata {
/** The driver should initiate a power off sequence during shutdown */
bool soft_shutdown;
 
+   /** dev_name of USB charger gadget to integrate with */
+   const char *usb_gadget;
+
int irq_base;
int g

[PATCH v4 2/5] gadget: Introduce the usb charger framework

2015-09-24 Thread Baolin Wang
This patch introduces the usb charger driver based on usb gadget that
makes an enhancement to a power driver. It works well in practice but
that requires a system with suitable hardware.

The basic conception of the usb charger is that, when one usb charger
is added or removed by reporting from the usb gadget state change or
the extcon device state change, the usb charger will report to power
user to set the current limitation.

The usb charger will register notifiees on the usb gadget or the extcon
device to get notified the usb charger state.

Power user will register a notifiee on the usb charger to get notified
by status changes from the usb charger. It will report to power user
to set the current limitation when detecting the usb charger is added
or removed from extcon device state or usb gadget state.

Signed-off-by: Baolin Wang <baolin.w...@linaro.org>
---
 drivers/usb/gadget/Kconfig  |   7 +
 drivers/usb/gadget/Makefile |   1 +
 drivers/usb/gadget/charger.c| 529 
 include/linux/usb/usb_charger.h | 138 +++
 4 files changed, 675 insertions(+)
 create mode 100644 drivers/usb/gadget/charger.c
 create mode 100644 include/linux/usb/usb_charger.h

diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig
index bcf83c0..3d2b959 100644
--- a/drivers/usb/gadget/Kconfig
+++ b/drivers/usb/gadget/Kconfig
@@ -127,6 +127,13 @@ config USB_GADGET_STORAGE_NUM_BUFFERS
   a module parameter as well.
   If unsure, say 2.
 
+config USB_CHARGER
+   bool "USB charger support"
+   help
+ The usb charger driver based on the usb gadget that makes an
+ enhancement to a power driver which can set the current limitation
+ when the usb charger is added or removed.
+
 source "drivers/usb/gadget/udc/Kconfig"
 
 #
diff --git a/drivers/usb/gadget/Makefile b/drivers/usb/gadget/Makefile
index 598a67d..1e421c1 100644
--- a/drivers/usb/gadget/Makefile
+++ b/drivers/usb/gadget/Makefile
@@ -10,3 +10,4 @@ libcomposite-y:= usbstring.o config.o 
epautoconf.o
 libcomposite-y += composite.o functions.o configfs.o u_f.o
 
 obj-$(CONFIG_USB_GADGET)   += udc/ function/ legacy/
+obj-$(CONFIG_USB_CHARGER)  += charger.o
diff --git a/drivers/usb/gadget/charger.c b/drivers/usb/gadget/charger.c
new file mode 100644
index 000..35b46c1
--- /dev/null
+++ b/drivers/usb/gadget/charger.c
@@ -0,0 +1,529 @@
+/*
+ * charger.c -- USB charger driver
+ *
+ * Copyright (C) 2015 Linaro Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define DEFAULT_CUR_PROTECT(50)
+#define DEFAULT_SDP_CUR_LIMIT  (500 - DEFAULT_CUR_PROTECT)
+#define DEFAULT_DCP_CUR_LIMIT  (1500 - DEFAULT_CUR_PROTECT)
+#define DEFAULT_CDP_CUR_LIMIT  (1500 - DEFAULT_CUR_PROTECT)
+#define DEFAULT_ACA_CUR_LIMIT  (1500 - DEFAULT_CUR_PROTECT)
+
+static DEFINE_IDA(usb_charger_ida);
+static struct bus_type usb_charger_subsys = {
+   .name   = "usb-charger",
+   .dev_name   = "usb-charger",
+};
+
+static struct usb_charger *dev_to_uchger(struct device *udev)
+{
+   return container_of(udev, struct usb_charger, dev);
+}
+
+static ssize_t cur_limit_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+   struct usb_charger *uchger = dev_to_uchger(dev);
+
+   return scnprintf(buf, PAGE_SIZE, "%d %d %d %d\n",
+uchger->cur_limit.sdp_cur_limit,
+uchger->cur_limit.dcp_cur_limit,
+uchger->cur_limit.cdp_cur_limit,
+uchger->cur_limit.aca_cur_limit);
+}
+
+static ssize_t cur_limit_store(struct device *dev,
+  struct device_attribute *attr,
+  const char *buf, size_t count)
+{
+   struct usb_charger *uchger = dev_to_uchger(dev);
+   struct usb_charger_cur_limit cur;
+   int ret;
+
+   ret = sscanf(buf, "%d %d %d %d",
+_cur_limit, _cur_limit,
+_cur_limit, _cur_limit);
+   if (ret == 0)
+   return -EINVAL;
+
+   ret = usb_charger_set_cur_limit(uchger, );
+   if (ret < 0)
+   return ret;
+
+   return count;
+}
+static DEVICE_ATTR_RW(cur_limit);
+
+static struct attribute *usb_charger_attrs[] = {
+   _attr_cur_limit.attr,
+   NULL
+};
+ATTRIBUTE_GROUPS(usb_charger);
+
+/*
+ * usb_charger_find_by_name - Get the usb charger device by name.
+ * @name - usb charger device name.
+

[PATCH v4 1/5] gadget: Introduce the notifier functions

2015-09-24 Thread Baolin Wang
The usb charger framework is based on usb gadget. The usb charger
need to be notified the state changing of usb gadget to confirm the
usb charger state.

Thus this patch adds a notifier mechanism for usb gadget to report a
event to usb charger when the usb gadget state is changed.

Signed-off-by: Baolin Wang <baolin.w...@linaro.org>
---
 drivers/usb/gadget/udc/udc-core.c | 32 
 include/linux/usb/gadget.h| 18 ++
 2 files changed, 50 insertions(+)

diff --git a/drivers/usb/gadget/udc/udc-core.c 
b/drivers/usb/gadget/udc/udc-core.c
index f660afb..4238fc3 100644
--- a/drivers/usb/gadget/udc/udc-core.c
+++ b/drivers/usb/gadget/udc/udc-core.c
@@ -129,6 +129,32 @@ void usb_gadget_giveback_request(struct usb_ep *ep,
 }
 EXPORT_SYMBOL_GPL(usb_gadget_giveback_request);
 
+int usb_gadget_register_notify(struct usb_gadget *gadget,
+  struct notifier_block *nb)
+{
+   int ret;
+
+   mutex_lock(>lock);
+   ret = raw_notifier_chain_register(>nh, nb);
+   mutex_unlock(>lock);
+
+   return ret;
+}
+EXPORT_SYMBOL_GPL(usb_gadget_register_notify);
+
+int usb_gadget_unregister_notify(struct usb_gadget *gadget,
+struct notifier_block *nb)
+{
+   int ret;
+
+   mutex_lock(>lock);
+   ret = raw_notifier_chain_unregister(>nh, nb);
+   mutex_unlock(>lock);
+
+   return ret;
+}
+EXPORT_SYMBOL_GPL(usb_gadget_unregister_notify);
+
 /* - */
 
 /**
@@ -226,6 +252,10 @@ static void usb_gadget_state_work(struct work_struct *work)
struct usb_gadget *gadget = work_to_gadget(work);
struct usb_udc *udc = gadget->udc;
 
+   mutex_lock(>lock);
+   raw_notifier_call_chain(>nh, gadget->state, gadget);
+   mutex_unlock(>lock);
+
if (udc)
sysfs_notify(>dev.kobj, NULL, "state");
 }
@@ -364,6 +394,8 @@ int usb_add_gadget_udc_release(struct device *parent, 
struct usb_gadget *gadget,
 
dev_set_name(>dev, "gadget");
INIT_WORK(>work, usb_gadget_state_work);
+   RAW_INIT_NOTIFIER_HEAD(>nh);
+   mutex_init(>lock);
gadget->dev.parent = parent;
 
 #ifdef CONFIG_HAS_DMA
diff --git a/include/linux/usb/gadget.h b/include/linux/usb/gadget.h
index c14a69b..755e8bc 100644
--- a/include/linux/usb/gadget.h
+++ b/include/linux/usb/gadget.h
@@ -609,6 +609,8 @@ struct usb_gadget {
unsignedout_epnum;
unsignedin_epnum;
struct usb_otg_caps *otg_caps;
+   struct raw_notifier_headnh;
+   struct mutexlock;
 
unsignedsg_supported:1;
unsignedis_otg:1;
@@ -1183,6 +1185,22 @@ extern void usb_gadget_unmap_request(struct usb_gadget 
*gadget,
 
 /*-*/
 
+/**
+ * Register a notifiee to get notified by any attach status changes from
+ * the usb gadget
+ */
+int usb_gadget_register_notify(struct usb_gadget *gadget,
+  struct notifier_block *nb);
+
+/*-*/
+
+
+/* Unregister a notifiee from the usb gadget */
+int usb_gadget_unregister_notify(struct usb_gadget *gadget,
+struct notifier_block *nb);
+
+/*-*/
+
 /* utility to set gadget state properly */
 
 extern void usb_gadget_set_state(struct usb_gadget *gadget,
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v4 3/5] gadget: Support for the usb charger framework

2015-09-24 Thread Baolin Wang
For supporting the usb charger, it adds the usb_charger_init() and
usb_charger_exit() functions for usb charger initialization and exit.

Introduce a callback 'get_charger_type' which will implemented by
user for usb gadget operations to get the usb charger type.

Signed-off-by: Baolin Wang <baolin.w...@linaro.org>
---
 drivers/usb/gadget/udc/udc-core.c | 8 
 include/linux/usb/gadget.h| 2 ++
 2 files changed, 10 insertions(+)

diff --git a/drivers/usb/gadget/udc/udc-core.c 
b/drivers/usb/gadget/udc/udc-core.c
index 4238fc3..370376e 100644
--- a/drivers/usb/gadget/udc/udc-core.c
+++ b/drivers/usb/gadget/udc/udc-core.c
@@ -28,6 +28,7 @@
 #include 
 #include 
 #include 
+#include 
 
 /**
  * struct usb_udc - describes one usb device controller
@@ -437,8 +438,14 @@ int usb_add_gadget_udc_release(struct device *parent, 
struct usb_gadget *gadget,
 
mutex_unlock(_lock);
 
+   ret = usb_charger_init(gadget);
+   if (ret)
+   goto err5;
+
return 0;
 
+err5:
+   device_del(>dev);
 err4:
list_del(>list);
mutex_unlock(_lock);
@@ -513,6 +520,7 @@ void usb_del_gadget_udc(struct usb_gadget *gadget)
kobject_uevent(>dev.kobj, KOBJ_REMOVE);
flush_work(>work);
device_unregister(>dev);
+   usb_charger_exit(gadget);
device_unregister(>dev);
 }
 EXPORT_SYMBOL_GPL(usb_del_gadget_udc);
diff --git a/include/linux/usb/gadget.h b/include/linux/usb/gadget.h
index 755e8bc..451ad32 100644
--- a/include/linux/usb/gadget.h
+++ b/include/linux/usb/gadget.h
@@ -537,6 +537,7 @@ struct usb_gadget_ops {
struct usb_ep *(*match_ep)(struct usb_gadget *,
struct usb_endpoint_descriptor *,
struct usb_ss_ep_comp_descriptor *);
+   enum usb_charger_type (*get_charger_type)(struct usb_gadget *);
 };
 
 /**
@@ -611,6 +612,7 @@ struct usb_gadget {
struct usb_otg_caps *otg_caps;
struct raw_notifier_headnh;
struct mutexlock;
+   struct usb_charger  *charger;
 
unsignedsg_supported:1;
unsignedis_otg:1;
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v4 4/5] gadget: Integrate with the usb gadget supporting for usb charger

2015-09-24 Thread Baolin Wang
When the usb gadget supporting for usb charger is ready, the usb charger
should get the type by the 'get_charger_type' callback which is implemented
by the usb gadget operations, and get the usb charger pointer from struct
'usb_gadget'.

Signed-off-by: Baolin Wang <baolin.w...@linaro.org>
---
 drivers/usb/gadget/charger.c | 13 +++--
 1 file changed, 11 insertions(+), 2 deletions(-)

diff --git a/drivers/usb/gadget/charger.c b/drivers/usb/gadget/charger.c
index 35b46c1..a919f38 100644
--- a/drivers/usb/gadget/charger.c
+++ b/drivers/usb/gadget/charger.c
@@ -181,6 +181,13 @@ int usb_charger_unregister_notify(struct usb_charger 
*uchger,
 enum usb_charger_type
 usb_charger_detect_type(struct usb_charger *uchger)
 {
+   if (uchger->gadget && uchger->gadget->ops
+   && uchger->gadget->ops->get_charger_type)
+   uchger->type =
+   uchger->gadget->ops->get_charger_type(uchger->gadget);
+   else
+   uchger->type = UNKNOWN_TYPE;
+
return uchger->type;
 }
 
@@ -313,7 +320,8 @@ static int
 usb_charger_plug_by_gadget(struct notifier_block *nb,
   unsigned long state, void *data)
 {
-   struct usb_charger *uchger = NULL;
+   struct usb_gadget *gadget = (struct usb_gadget *)data;
+   struct usb_charger *uchger = gadget->charger;
enum usb_charger_state uchger_state;
 
if (!uchger)
@@ -480,6 +488,7 @@ int usb_charger_init(struct usb_gadget *ugadget)
 
/* register a notifier on a usb gadget device */
uchger->gadget = ugadget;
+   ugadget->charger = uchger;
uchger->old_gadget_state = ugadget->state;
uchger->gadget_nb.notifier_call = usb_charger_plug_by_gadget;
usb_gadget_register_notify(ugadget, >gadget_nb);
@@ -503,7 +512,7 @@ fail:
 
 int usb_charger_exit(struct usb_gadget *ugadget)
 {
-   struct usb_charger *uchger = NULL;
+   struct usb_charger *uchger = ugadget->charger;
 
if (!uchger)
return -EINVAL;
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v7 3/4] gadget: Integrate with the usb gadget supporting for usb charger

2015-12-08 Thread Baolin Wang
When the usb gadget supporting for usb charger is ready, the usb charger
should get the type by the 'get_charger_type' callback which is implemented
by the usb gadget operations, and get the usb charger pointer from struct
'usb_gadget'.

Signed-off-by: Baolin Wang <baolin.w...@linaro.org>
---
 drivers/usb/gadget/charger.c |   43 --
 1 file changed, 41 insertions(+), 2 deletions(-)

diff --git a/drivers/usb/gadget/charger.c b/drivers/usb/gadget/charger.c
index 82a9973..76e1a6f 100644
--- a/drivers/usb/gadget/charger.c
+++ b/drivers/usb/gadget/charger.c
@@ -272,7 +272,11 @@ EXPORT_SYMBOL_GPL(usb_charger_unregister_notify);
 enum usb_charger_type
 usb_charger_detect_type(struct usb_charger *uchger)
 {
-   if (uchger->psy) {
+   if (uchger->gadget && uchger->gadget->ops
+   && uchger->gadget->ops->get_charger_type) {
+   uchger->type =
+   uchger->gadget->ops->get_charger_type(uchger->gadget);
+   } else if (uchger->psy) {
union power_supply_propval val;
 
power_supply_get_property(uchger->psy,
@@ -479,6 +483,29 @@ usb_charger_plug_by_extcon(struct notifier_block *nb,
 int usb_charger_plug_by_gadget(struct usb_gadget *gadget,
   unsigned long state)
 {
+   struct usb_charger *uchger = gadget->charger;
+   enum usb_charger_state uchger_state;
+
+   if (!uchger)
+   return -EINVAL;
+
+   /* Report event to power to setting the current limitation
+* for this usb charger when one usb charger state is changed
+* with detecting by usb gadget state.
+*/
+   if (uchger->old_gadget_state != state) {
+   uchger->old_gadget_state = state;
+
+   if (state >= USB_STATE_ATTACHED)
+   uchger_state = USB_CHARGER_PRESENT;
+   else if (state == USB_STATE_NOTATTACHED)
+   uchger_state = USB_CHARGER_REMOVE;
+   else
+   uchger_state = USB_CHARGER_DEFAULT;
+
+   usb_charger_notify_others(uchger, uchger_state);
+   }
+
return 0;
 }
 EXPORT_SYMBOL_GPL(usb_charger_plug_by_gadget);
@@ -635,6 +662,7 @@ int usb_charger_init(struct usb_gadget *ugadget)
 
/* register a notifier on a usb gadget device */
uchger->gadget = ugadget;
+   ugadget->charger = uchger;
uchger->old_gadget_state = ugadget->state;
 
/* register a new usb charger */
@@ -655,7 +683,18 @@ fail:
 
 int usb_charger_exit(struct usb_gadget *ugadget)
 {
-   return 0;
+   struct usb_charger *uchger = ugadget->charger;
+
+   if (!uchger)
+   return -EINVAL;
+
+   if (uchger->extcon_dev)
+   extcon_unregister_notifier(uchger->extcon_dev,
+  EXTCON_USB, >extcon_nb.nb);
+
+   ida_simple_remove(_charger_ida, uchger->id);
+
+   return usb_charger_unregister(uchger);
 }
 
 static int __init usb_charger_sysfs_init(void)
-- 
1.7.9.5

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v7 1/4] gadget: Introduce the usb charger framework

2015-12-08 Thread Baolin Wang
This patch introduces the usb charger driver based on usb gadget that
makes an enhancement to a power driver. It works well in practice but
that requires a system with suitable hardware.

The basic conception of the usb charger is that, when one usb charger
is added or removed by reporting from the usb gadget state change or
the extcon device state change, the usb charger will report to power
user to set the current limitation.

The usb charger will register notifiees on the usb gadget or the extcon
device to get notified the usb charger state. It also supplies the
notification mechanism to userspace When the usb charger state is changed.

Power user will register a notifiee on the usb charger to get notified
by status changes from the usb charger. It will report to power user
to set the current limitation when detecting the usb charger is added
or removed from extcon device state or usb gadget state.

This patch doesn't yet integrate with the gadget code, so some functions
which rely on the 'gadget' are not completed, that will be implemented
in the following patches.

Signed-off-by: Baolin Wang <baolin.w...@linaro.org>
---
 drivers/usb/gadget/Kconfig  |7 +
 drivers/usb/gadget/Makefile |1 +
 drivers/usb/gadget/charger.c|  669 +++
 include/linux/usb/usb_charger.h |  164 ++
 4 files changed, 841 insertions(+)
 create mode 100644 drivers/usb/gadget/charger.c
 create mode 100644 include/linux/usb/usb_charger.h

diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig
index 33834aa..8d69dca 100644
--- a/drivers/usb/gadget/Kconfig
+++ b/drivers/usb/gadget/Kconfig
@@ -127,6 +127,13 @@ config USB_GADGET_STORAGE_NUM_BUFFERS
   a module parameter as well.
   If unsure, say 2.
 
+config USB_CHARGER
+   bool "USB charger support"
+   help
+ The usb charger driver based on the usb gadget that makes an
+ enhancement to a power driver which can set the current limitation
+ when the usb charger is added or removed.
+
 source "drivers/usb/gadget/udc/Kconfig"
 
 #
diff --git a/drivers/usb/gadget/Makefile b/drivers/usb/gadget/Makefile
index 598a67d..1e421c1 100644
--- a/drivers/usb/gadget/Makefile
+++ b/drivers/usb/gadget/Makefile
@@ -10,3 +10,4 @@ libcomposite-y:= usbstring.o config.o 
epautoconf.o
 libcomposite-y += composite.o functions.o configfs.o u_f.o
 
 obj-$(CONFIG_USB_GADGET)   += udc/ function/ legacy/
+obj-$(CONFIG_USB_CHARGER)  += charger.o
diff --git a/drivers/usb/gadget/charger.c b/drivers/usb/gadget/charger.c
new file mode 100644
index 000..82a9973
--- /dev/null
+++ b/drivers/usb/gadget/charger.c
@@ -0,0 +1,669 @@
+/*
+ * charger.c -- USB charger driver
+ *
+ * Copyright (C) 2015 Linaro Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define DEFAULT_CUR_PROTECT(50)
+#define DEFAULT_SDP_CUR_LIMIT  (500 - DEFAULT_CUR_PROTECT)
+#define DEFAULT_DCP_CUR_LIMIT  (1500 - DEFAULT_CUR_PROTECT)
+#define DEFAULT_CDP_CUR_LIMIT  (1500 - DEFAULT_CUR_PROTECT)
+#define DEFAULT_ACA_CUR_LIMIT  (1500 - DEFAULT_CUR_PROTECT)
+#define UCHGER_STATE_LENGTH(50)
+
+static DEFINE_IDA(usb_charger_ida);
+static struct bus_type usb_charger_subsys = {
+   .name   = "usb-charger",
+   .dev_name   = "usb-charger",
+};
+
+static struct usb_charger *dev_to_uchger(struct device *udev)
+{
+   return container_of(udev, struct usb_charger, dev);
+}
+
+static ssize_t sdp_limit_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+   struct usb_charger *uchger = dev_to_uchger(dev);
+
+   return sprintf(buf, "%d\n", uchger->cur_limit.sdp_cur_limit);
+}
+
+static ssize_t sdp_limit_store(struct device *dev,
+  struct device_attribute *attr,
+  const char *buf, size_t count)
+{
+   struct usb_charger *uchger = dev_to_uchger(dev);
+   unsigned int sdp_limit;
+   int ret;
+
+   ret = kstrtouint(buf, 10, _limit);
+   if (ret < 0)
+   return ret;
+
+   ret = usb_charger_set_cur_limit_by_type(uchger, SDP_TYPE, sdp_limit);
+   if (ret < 0)
+   return ret;
+
+   return count;
+}
+static DEVICE_ATTR_RW(sdp_limit);
+
+static ssize_t dcp_limit_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+   struct usb_charger *uchger = dev_to_uchger(dev);
+
+   return sprintf(buf, "%d\n&qu

[PATCH v7 2/4] gadget: Support for the usb charger framework

2015-12-08 Thread Baolin Wang
For supporting the usb charger, it adds the usb_charger_init() and
usb_charger_exit() functions for usb charger initialization and exit.

It will report to the usb charger when the gadget state is changed,
then the usb charger can do the power things.

Introduce a callback 'get_charger_type' which will implemented by
user for usb gadget operations to get the usb charger type.

Signed-off-by: Baolin Wang <baolin.w...@linaro.org>
---
 drivers/usb/gadget/udc/udc-core.c |   11 +++
 include/linux/usb/gadget.h|   11 +++
 2 files changed, 22 insertions(+)

diff --git a/drivers/usb/gadget/udc/udc-core.c 
b/drivers/usb/gadget/udc/udc-core.c
index f660afb..2727f01 100644
--- a/drivers/usb/gadget/udc/udc-core.c
+++ b/drivers/usb/gadget/udc/udc-core.c
@@ -28,6 +28,7 @@
 #include 
 #include 
 #include 
+#include 
 
 /**
  * struct usb_udc - describes one usb device controller
@@ -226,6 +227,9 @@ static void usb_gadget_state_work(struct work_struct *work)
struct usb_gadget *gadget = work_to_gadget(work);
struct usb_udc *udc = gadget->udc;
 
+   /* when the gadget state is changed, then report to USB charger */
+   usb_charger_plug_by_gadget(gadget, gadget->state);
+
if (udc)
sysfs_notify(>dev.kobj, NULL, "state");
 }
@@ -405,8 +409,14 @@ int usb_add_gadget_udc_release(struct device *parent, 
struct usb_gadget *gadget,
 
mutex_unlock(_lock);
 
+   ret = usb_charger_init(gadget);
+   if (ret)
+   goto err5;
+
return 0;
 
+err5:
+   device_del(>dev);
 err4:
list_del(>list);
mutex_unlock(_lock);
@@ -481,6 +491,7 @@ void usb_del_gadget_udc(struct usb_gadget *gadget)
kobject_uevent(>dev.kobj, KOBJ_REMOVE);
flush_work(>work);
device_unregister(>dev);
+   usb_charger_exit(gadget);
device_unregister(>dev);
 }
 EXPORT_SYMBOL_GPL(usb_del_gadget_udc);
diff --git a/include/linux/usb/gadget.h b/include/linux/usb/gadget.h
index 3d583a1..52c19b1 100644
--- a/include/linux/usb/gadget.h
+++ b/include/linux/usb/gadget.h
@@ -24,6 +24,7 @@
 #include 
 #include 
 #include 
+#include 
 
 struct usb_ep;
 
@@ -560,6 +561,7 @@ struct usb_gadget_ops {
struct usb_ep *(*match_ep)(struct usb_gadget *,
struct usb_endpoint_descriptor *,
struct usb_ss_ep_comp_descriptor *);
+   enum usb_charger_type (*get_charger_type)(struct usb_gadget *);
 };
 
 /**
@@ -632,6 +634,8 @@ struct usb_gadget {
unsignedout_epnum;
unsignedin_epnum;
struct usb_otg_caps *otg_caps;
+   /* negotiate the power with the usb charger */
+   struct usb_charger  *charger;
 
unsignedsg_supported:1;
unsignedis_otg:1;
@@ -836,10 +840,17 @@ static inline int usb_gadget_vbus_connect(struct 
usb_gadget *gadget)
  * reporting how much power the device may consume.  For example, this
  * could affect how quickly batteries are recharged.
  *
+ * It will also notify the USB charger how much power the device may
+ * consume if there is a USB charger linking with the gadget.
+ *
  * Returns zero on success, else negative errno.
  */
 static inline int usb_gadget_vbus_draw(struct usb_gadget *gadget, unsigned mA)
 {
+   if (gadget->charger)
+   usb_charger_set_cur_limit_by_type(gadget->charger,
+   usb_charger_detect_type(gadget->charger), mA);
+
if (!gadget->ops->vbus_draw)
return -EOPNOTSUPP;
return gadget->ops->vbus_draw(gadget, mA);
-- 
1.7.9.5

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v7 4/4] power: wm831x_power: Support USB charger current limit management

2015-12-08 Thread Baolin Wang
Integrate with the newly added USB charger interface to limit the current
we draw from the USB input based on the input device configuration
identified by the USB stack, allowing us to charge more quickly from high
current inputs without drawing more current than specified from others.

Signed-off-by: Mark Brown <broo...@kernel.org>
Signed-off-by: Baolin Wang <baolin.w...@linaro.org>
Acked-by: Lee Jones <lee.jo...@linaro.org>
Acked-by: Charles Keepax <ckee...@opensource.wolfsonmicro.com>
Acked-by: Peter Chen <peter.c...@freescale.com>
Acked-by: Sebastian Reichel <s...@kernel.org>
---
 drivers/power/wm831x_power.c |   69 ++
 include/linux/mfd/wm831x/pdata.h |3 ++
 2 files changed, 72 insertions(+)

diff --git a/drivers/power/wm831x_power.c b/drivers/power/wm831x_power.c
index 7082301..043f1f4 100644
--- a/drivers/power/wm831x_power.c
+++ b/drivers/power/wm831x_power.c
@@ -13,6 +13,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include 
 #include 
@@ -31,6 +32,8 @@ struct wm831x_power {
char usb_name[20];
char battery_name[20];
bool have_battery;
+   struct usb_charger *usb_charger;
+   struct notifier_block usb_notify;
 };
 
 static int wm831x_power_check_online(struct wm831x *wm831x, int supply,
@@ -125,6 +128,43 @@ static enum power_supply_property wm831x_usb_props[] = {
POWER_SUPPLY_PROP_VOLTAGE_NOW,
 };
 
+/* In milliamps */
+static unsigned int wm831x_usb_limits[] = {
+   0,
+   2,
+   100,
+   500,
+   900,
+   1500,
+   1800,
+   550,
+};
+
+static int wm831x_usb_limit_change(struct notifier_block *nb,
+  unsigned long limit, void *data)
+{
+   struct wm831x_power *wm831x_power = container_of(nb,
+struct wm831x_power,
+usb_notify);
+   int i, best;
+
+   /* Find the highest supported limit */
+   best = 0;
+   for (i = 0; i < ARRAY_SIZE(wm831x_usb_limits); i++) {
+   if (limit >= wm831x_usb_limits[i] &&
+   wm831x_usb_limits[best] < wm831x_usb_limits[i])
+   best = i;
+   }
+
+   dev_dbg(wm831x_power->wm831x->dev,
+   "Limiting USB current to %dmA", wm831x_usb_limits[best]);
+
+   wm831x_set_bits(wm831x_power->wm831x, WM831X_POWER_STATE,
+   WM831X_USB_ILIM_MASK, best);
+
+   return 0;
+}
+
 /*
  * Battery properties
  */
@@ -607,8 +647,31 @@ static int wm831x_power_probe(struct platform_device *pdev)
}
}
 
+   if (wm831x_pdata && wm831x_pdata->usb_gadget) {
+   power->usb_charger =
+   usb_charger_find_by_name(wm831x_pdata->usb_gadget);
+   if (IS_ERR(power->usb_charger)) {
+   ret = PTR_ERR(power->usb_charger);
+   dev_err(>dev,
+   "Failed to find USB gadget: %d\n", ret);
+   goto err_bat_irq;
+   }
+
+   power->usb_notify.notifier_call = wm831x_usb_limit_change;
+
+   ret = usb_charger_register_notify(power->usb_charger,
+ >usb_notify);
+   if (ret != 0) {
+   dev_err(>dev,
+   "Failed to register notifier: %d\n", ret);
+   goto err_usb_charger;
+   }
+   }
+
return ret;
 
+err_usb_charger:
+   /* put_device on charger */
 err_bat_irq:
--i;
for (; i >= 0; i--) {
@@ -637,6 +700,12 @@ static int wm831x_power_remove(struct platform_device 
*pdev)
struct wm831x *wm831x = wm831x_power->wm831x;
int irq, i;
 
+   if (wm831x_power->usb_charger) {
+   usb_charger_unregister_notify(wm831x_power->usb_charger,
+ _power->usb_notify);
+   /* Free charger */
+   }
+
for (i = 0; i < ARRAY_SIZE(wm831x_bat_irqs); i++) {
irq = wm831x_irq(wm831x, 
 platform_get_irq_byname(pdev,
diff --git a/include/linux/mfd/wm831x/pdata.h b/include/linux/mfd/wm831x/pdata.h
index dcc9631..5af8399 100644
--- a/include/linux/mfd/wm831x/pdata.h
+++ b/include/linux/mfd/wm831x/pdata.h
@@ -126,6 +126,9 @@ struct wm831x_pdata {
/** The driver should initiate a power off sequence during shutdown */
bool soft_shutdown;
 
+   /** dev_name of USB charger gadget to integrate with */
+   const char *usb_gadget;
+
int irq_base;
int gpi

[PATCH v7 0/4] Introduce usb charger framework to deal with the usb gadget power negotation

2015-12-08 Thread Baolin Wang
Currently the Linux kernel does not provide any standard integration of this
feature that integrates the USB subsystem with the system power regulation
provided by PMICs meaning that either vendors must add this in their kernels
or USB gadget devices based on Linux (such as mobile phones) may not behave
as they should. Thus provide a standard framework for doing this in kernel.

Now introduce one user with wm831x_power to support and test the usb charger,
which is pending testing. Moreover there may be other potential users will use
it in future.

Changes since v5:
 - Remove the notifier chain things from the gadget and introduce one callback
 function to report to the usb charger when the gadget state is changed.
 - Flesh out the port type detection which combines the USB negotiation and
 PMICs detection.
 - Supply the notification mechanism to userspace when charger state is changed.
 - Integrate with the vbus staff in the gadget API.
 - Spilt up the functionality for userspace with one file per USB charger type.

Baolin Wang (4):
  gadget: Introduce the usb charger framework
  gadget: Support for the usb charger framework
  gadget: Integrate with the usb gadget supporting for usb charger
  power: wm831x_power: Support USB charger current limit management

 drivers/power/wm831x_power.c  |   69 
 drivers/usb/gadget/Kconfig|7 +
 drivers/usb/gadget/Makefile   |1 +
 drivers/usb/gadget/charger.c  |  708 +
 drivers/usb/gadget/udc/udc-core.c |   11 +
 include/linux/mfd/wm831x/pdata.h  |3 +
 include/linux/usb/gadget.h|   11 +
 include/linux/usb/usb_charger.h   |  164 +
 8 files changed, 974 insertions(+)
 create mode 100644 drivers/usb/gadget/charger.c
 create mode 100644 include/linux/usb/usb_charger.h

-- 
1.7.9.5

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v6 1/4] gadget: Introduce the usb charger framework

2015-12-06 Thread Baolin Wang
On 6 December 2015 at 00:27, Sebastian Reichel <s...@kernel.org> wrote:
> Hi,
>
> On Mon, Nov 16, 2015 at 02:33:31PM +0800, Baolin Wang wrote:
>> +static ssize_t cur_limit_show(struct device *dev,
>> +   struct device_attribute *attr,
>> +   char *buf)
>> +{
>> + struct usb_charger *uchger = dev_to_uchger(dev);
>> +
>> + return scnprintf(buf, PAGE_SIZE, "%d %d %d %d\n",
>> +  uchger->cur_limit.sdp_cur_limit,
>> +  uchger->cur_limit.dcp_cur_limit,
>> +  uchger->cur_limit.cdp_cur_limit,
>> +  uchger->cur_limit.aca_cur_limit);
>> +}
>> +
>> +static ssize_t cur_limit_store(struct device *dev,
>> +struct device_attribute *attr,
>> +const char *buf, size_t count)
>> +{
>> + struct usb_charger *uchger = dev_to_uchger(dev);
>> + struct usb_charger_cur_limit cur;
>> + int ret;
>> +
>> + ret = sscanf(buf, "%d %d %d %d",
>> +  _cur_limit, _cur_limit,
>> +  _cur_limit, _cur_limit);
>> + if (ret == 0)
>> + return -EINVAL;
>> +
>> + ret = usb_charger_set_cur_limit(uchger, );
>> + if (ret < 0)
>> + return ret;
>> +
>> + return count;
>> +}
>> +static DEVICE_ATTR_RW(cur_limit);
>
> I think this functionality should be provided with one file per
> type. This makes it easier to parse the values from userspace
> and makes it possible to extend the frameworks functionality
> (e.g. when new types are added in a newer revision of the USB
> standard).
>

That sounds reasonable and I'll change that. Thanks.

> -- Sebastian



-- 
Baolin.wang
Best Regards
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v7 0/4] Introduce usb charger framework to deal with the usb gadget power negotation

2016-01-03 Thread Baolin Wang
Currently the Linux kernel does not provide any standard integration of this
feature that integrates the USB subsystem with the system power regulation
provided by PMICs meaning that either vendors must add this in their kernels
or USB gadget devices based on Linux (such as mobile phones) may not behave
as they should. Thus provide a standard framework for doing this in kernel.

Now introduce one user with wm831x_power to support and test the usb charger,
which is pending testing. Moreover there may be other potential users will use
it in future.

Changes since v5:
 - Remove the notifier chain things from the gadget and introduce one callback
 function to report to the usb charger when the gadget state is changed.
 - Flesh out the port type detection which combines the USB negotiation and
 PMICs detection.
 - Supply the notification mechanism to userspace when charger state is changed.
 - Integrate with the vbus staff in the gadget API.
 - Spilt up the functionality for userspace with one file per USB charger type.
 - Rebase on "4.4-rc7". 

Baolin Wang (4):
  gadget: Introduce the usb charger framework
  gadget: Support for the usb charger framework
  gadget: Integrate with the usb gadget supporting for usb charger
  power: wm831x_power: Support USB charger current limit management

 drivers/power/wm831x_power.c  |   69 
 drivers/usb/gadget/Kconfig|7 +
 drivers/usb/gadget/Makefile   |1 +
 drivers/usb/gadget/charger.c  |  708 +
 drivers/usb/gadget/udc/udc-core.c |   11 +
 include/linux/mfd/wm831x/pdata.h  |3 +
 include/linux/usb/gadget.h|   11 +
 include/linux/usb/usb_charger.h   |  164 +
 8 files changed, 974 insertions(+)
 create mode 100644 drivers/usb/gadget/charger.c
 create mode 100644 include/linux/usb/usb_charger.h

-- 
1.7.9.5

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v7 2/4] gadget: Support for the usb charger framework

2016-01-03 Thread Baolin Wang
For supporting the usb charger, it adds the usb_charger_init() and
usb_charger_exit() functions for usb charger initialization and exit.

It will report to the usb charger when the gadget state is changed,
then the usb charger can do the power things.

Introduce a callback 'get_charger_type' which will implemented by
user for usb gadget operations to get the usb charger type.

Signed-off-by: Baolin Wang <baolin.w...@linaro.org>
---
 drivers/usb/gadget/udc/udc-core.c |   11 +++
 include/linux/usb/gadget.h|   11 +++
 2 files changed, 22 insertions(+)

diff --git a/drivers/usb/gadget/udc/udc-core.c 
b/drivers/usb/gadget/udc/udc-core.c
index f660afb..2727f01 100644
--- a/drivers/usb/gadget/udc/udc-core.c
+++ b/drivers/usb/gadget/udc/udc-core.c
@@ -28,6 +28,7 @@
 #include 
 #include 
 #include 
+#include 
 
 /**
  * struct usb_udc - describes one usb device controller
@@ -226,6 +227,9 @@ static void usb_gadget_state_work(struct work_struct *work)
struct usb_gadget *gadget = work_to_gadget(work);
struct usb_udc *udc = gadget->udc;
 
+   /* when the gadget state is changed, then report to USB charger */
+   usb_charger_plug_by_gadget(gadget, gadget->state);
+
if (udc)
sysfs_notify(>dev.kobj, NULL, "state");
 }
@@ -405,8 +409,14 @@ int usb_add_gadget_udc_release(struct device *parent, 
struct usb_gadget *gadget,
 
mutex_unlock(_lock);
 
+   ret = usb_charger_init(gadget);
+   if (ret)
+   goto err5;
+
return 0;
 
+err5:
+   device_del(>dev);
 err4:
list_del(>list);
mutex_unlock(_lock);
@@ -481,6 +491,7 @@ void usb_del_gadget_udc(struct usb_gadget *gadget)
kobject_uevent(>dev.kobj, KOBJ_REMOVE);
flush_work(>work);
device_unregister(>dev);
+   usb_charger_exit(gadget);
device_unregister(>dev);
 }
 EXPORT_SYMBOL_GPL(usb_del_gadget_udc);
diff --git a/include/linux/usb/gadget.h b/include/linux/usb/gadget.h
index 3d583a1..52c19b1 100644
--- a/include/linux/usb/gadget.h
+++ b/include/linux/usb/gadget.h
@@ -24,6 +24,7 @@
 #include 
 #include 
 #include 
+#include 
 
 struct usb_ep;
 
@@ -560,6 +561,7 @@ struct usb_gadget_ops {
struct usb_ep *(*match_ep)(struct usb_gadget *,
struct usb_endpoint_descriptor *,
struct usb_ss_ep_comp_descriptor *);
+   enum usb_charger_type (*get_charger_type)(struct usb_gadget *);
 };
 
 /**
@@ -632,6 +634,8 @@ struct usb_gadget {
unsignedout_epnum;
unsignedin_epnum;
struct usb_otg_caps *otg_caps;
+   /* negotiate the power with the usb charger */
+   struct usb_charger  *charger;
 
unsignedsg_supported:1;
unsignedis_otg:1;
@@ -836,10 +840,17 @@ static inline int usb_gadget_vbus_connect(struct 
usb_gadget *gadget)
  * reporting how much power the device may consume.  For example, this
  * could affect how quickly batteries are recharged.
  *
+ * It will also notify the USB charger how much power the device may
+ * consume if there is a USB charger linking with the gadget.
+ *
  * Returns zero on success, else negative errno.
  */
 static inline int usb_gadget_vbus_draw(struct usb_gadget *gadget, unsigned mA)
 {
+   if (gadget->charger)
+   usb_charger_set_cur_limit_by_type(gadget->charger,
+   usb_charger_detect_type(gadget->charger), mA);
+
if (!gadget->ops->vbus_draw)
return -EOPNOTSUPP;
return gadget->ops->vbus_draw(gadget, mA);
-- 
1.7.9.5

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v7 3/4] gadget: Integrate with the usb gadget supporting for usb charger

2016-01-03 Thread Baolin Wang
When the usb gadget supporting for usb charger is ready, the usb charger
should get the type by the 'get_charger_type' callback which is implemented
by the usb gadget operations, and get the usb charger pointer from struct
'usb_gadget'.

Signed-off-by: Baolin Wang <baolin.w...@linaro.org>
---
 drivers/usb/gadget/charger.c |   43 --
 1 file changed, 41 insertions(+), 2 deletions(-)

diff --git a/drivers/usb/gadget/charger.c b/drivers/usb/gadget/charger.c
index 82a9973..76e1a6f 100644
--- a/drivers/usb/gadget/charger.c
+++ b/drivers/usb/gadget/charger.c
@@ -272,7 +272,11 @@ EXPORT_SYMBOL_GPL(usb_charger_unregister_notify);
 enum usb_charger_type
 usb_charger_detect_type(struct usb_charger *uchger)
 {
-   if (uchger->psy) {
+   if (uchger->gadget && uchger->gadget->ops
+   && uchger->gadget->ops->get_charger_type) {
+   uchger->type =
+   uchger->gadget->ops->get_charger_type(uchger->gadget);
+   } else if (uchger->psy) {
union power_supply_propval val;
 
power_supply_get_property(uchger->psy,
@@ -479,6 +483,29 @@ usb_charger_plug_by_extcon(struct notifier_block *nb,
 int usb_charger_plug_by_gadget(struct usb_gadget *gadget,
   unsigned long state)
 {
+   struct usb_charger *uchger = gadget->charger;
+   enum usb_charger_state uchger_state;
+
+   if (!uchger)
+   return -EINVAL;
+
+   /* Report event to power to setting the current limitation
+* for this usb charger when one usb charger state is changed
+* with detecting by usb gadget state.
+*/
+   if (uchger->old_gadget_state != state) {
+   uchger->old_gadget_state = state;
+
+   if (state >= USB_STATE_ATTACHED)
+   uchger_state = USB_CHARGER_PRESENT;
+   else if (state == USB_STATE_NOTATTACHED)
+   uchger_state = USB_CHARGER_REMOVE;
+   else
+   uchger_state = USB_CHARGER_DEFAULT;
+
+   usb_charger_notify_others(uchger, uchger_state);
+   }
+
return 0;
 }
 EXPORT_SYMBOL_GPL(usb_charger_plug_by_gadget);
@@ -635,6 +662,7 @@ int usb_charger_init(struct usb_gadget *ugadget)
 
/* register a notifier on a usb gadget device */
uchger->gadget = ugadget;
+   ugadget->charger = uchger;
uchger->old_gadget_state = ugadget->state;
 
/* register a new usb charger */
@@ -655,7 +683,18 @@ fail:
 
 int usb_charger_exit(struct usb_gadget *ugadget)
 {
-   return 0;
+   struct usb_charger *uchger = ugadget->charger;
+
+   if (!uchger)
+   return -EINVAL;
+
+   if (uchger->extcon_dev)
+   extcon_unregister_notifier(uchger->extcon_dev,
+  EXTCON_USB, >extcon_nb.nb);
+
+   ida_simple_remove(_charger_ida, uchger->id);
+
+   return usb_charger_unregister(uchger);
 }
 
 static int __init usb_charger_sysfs_init(void)
-- 
1.7.9.5

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v7 1/4] gadget: Introduce the usb charger framework

2016-01-03 Thread Baolin Wang
This patch introduces the usb charger driver based on usb gadget that
makes an enhancement to a power driver. It works well in practice but
that requires a system with suitable hardware.

The basic conception of the usb charger is that, when one usb charger
is added or removed by reporting from the usb gadget state change or
the extcon device state change, the usb charger will report to power
user to set the current limitation.

The usb charger will register notifiees on the usb gadget or the extcon
device to get notified the usb charger state. It also supplies the
notification mechanism to userspace When the usb charger state is changed.

Power user will register a notifiee on the usb charger to get notified
by status changes from the usb charger. It will report to power user
to set the current limitation when detecting the usb charger is added
or removed from extcon device state or usb gadget state.

This patch doesn't yet integrate with the gadget code, so some functions
which rely on the 'gadget' are not completed, that will be implemented
in the following patches.

Signed-off-by: Baolin Wang <baolin.w...@linaro.org>
---
 drivers/usb/gadget/Kconfig  |7 +
 drivers/usb/gadget/Makefile |1 +
 drivers/usb/gadget/charger.c|  669 +++
 include/linux/usb/usb_charger.h |  164 ++
 4 files changed, 841 insertions(+)
 create mode 100644 drivers/usb/gadget/charger.c
 create mode 100644 include/linux/usb/usb_charger.h

diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig
index 33834aa..8d69dca 100644
--- a/drivers/usb/gadget/Kconfig
+++ b/drivers/usb/gadget/Kconfig
@@ -127,6 +127,13 @@ config USB_GADGET_STORAGE_NUM_BUFFERS
   a module parameter as well.
   If unsure, say 2.
 
+config USB_CHARGER
+   bool "USB charger support"
+   help
+ The usb charger driver based on the usb gadget that makes an
+ enhancement to a power driver which can set the current limitation
+ when the usb charger is added or removed.
+
 source "drivers/usb/gadget/udc/Kconfig"
 
 #
diff --git a/drivers/usb/gadget/Makefile b/drivers/usb/gadget/Makefile
index 598a67d..1e421c1 100644
--- a/drivers/usb/gadget/Makefile
+++ b/drivers/usb/gadget/Makefile
@@ -10,3 +10,4 @@ libcomposite-y:= usbstring.o config.o 
epautoconf.o
 libcomposite-y += composite.o functions.o configfs.o u_f.o
 
 obj-$(CONFIG_USB_GADGET)   += udc/ function/ legacy/
+obj-$(CONFIG_USB_CHARGER)  += charger.o
diff --git a/drivers/usb/gadget/charger.c b/drivers/usb/gadget/charger.c
new file mode 100644
index 000..82a9973
--- /dev/null
+++ b/drivers/usb/gadget/charger.c
@@ -0,0 +1,669 @@
+/*
+ * charger.c -- USB charger driver
+ *
+ * Copyright (C) 2015 Linaro Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define DEFAULT_CUR_PROTECT(50)
+#define DEFAULT_SDP_CUR_LIMIT  (500 - DEFAULT_CUR_PROTECT)
+#define DEFAULT_DCP_CUR_LIMIT  (1500 - DEFAULT_CUR_PROTECT)
+#define DEFAULT_CDP_CUR_LIMIT  (1500 - DEFAULT_CUR_PROTECT)
+#define DEFAULT_ACA_CUR_LIMIT  (1500 - DEFAULT_CUR_PROTECT)
+#define UCHGER_STATE_LENGTH(50)
+
+static DEFINE_IDA(usb_charger_ida);
+static struct bus_type usb_charger_subsys = {
+   .name   = "usb-charger",
+   .dev_name   = "usb-charger",
+};
+
+static struct usb_charger *dev_to_uchger(struct device *udev)
+{
+   return container_of(udev, struct usb_charger, dev);
+}
+
+static ssize_t sdp_limit_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+   struct usb_charger *uchger = dev_to_uchger(dev);
+
+   return sprintf(buf, "%d\n", uchger->cur_limit.sdp_cur_limit);
+}
+
+static ssize_t sdp_limit_store(struct device *dev,
+  struct device_attribute *attr,
+  const char *buf, size_t count)
+{
+   struct usb_charger *uchger = dev_to_uchger(dev);
+   unsigned int sdp_limit;
+   int ret;
+
+   ret = kstrtouint(buf, 10, _limit);
+   if (ret < 0)
+   return ret;
+
+   ret = usb_charger_set_cur_limit_by_type(uchger, SDP_TYPE, sdp_limit);
+   if (ret < 0)
+   return ret;
+
+   return count;
+}
+static DEVICE_ATTR_RW(sdp_limit);
+
+static ssize_t dcp_limit_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+   struct usb_charger *uchger = dev_to_uchger(dev);
+
+   return sprintf(buf, "%d\n&qu

[PATCH v7 4/4] power: wm831x_power: Support USB charger current limit management

2016-01-03 Thread Baolin Wang
Integrate with the newly added USB charger interface to limit the current
we draw from the USB input based on the input device configuration
identified by the USB stack, allowing us to charge more quickly from high
current inputs without drawing more current than specified from others.

Signed-off-by: Mark Brown <broo...@kernel.org>
Signed-off-by: Baolin Wang <baolin.w...@linaro.org>
Acked-by: Lee Jones <lee.jo...@linaro.org>
Acked-by: Charles Keepax <ckee...@opensource.wolfsonmicro.com>
Acked-by: Peter Chen <peter.c...@freescale.com>
Acked-by: Sebastian Reichel <s...@kernel.org>
---
 drivers/power/wm831x_power.c |   69 ++
 include/linux/mfd/wm831x/pdata.h |3 ++
 2 files changed, 72 insertions(+)

diff --git a/drivers/power/wm831x_power.c b/drivers/power/wm831x_power.c
index 7082301..043f1f4 100644
--- a/drivers/power/wm831x_power.c
+++ b/drivers/power/wm831x_power.c
@@ -13,6 +13,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include 
 #include 
@@ -31,6 +32,8 @@ struct wm831x_power {
char usb_name[20];
char battery_name[20];
bool have_battery;
+   struct usb_charger *usb_charger;
+   struct notifier_block usb_notify;
 };
 
 static int wm831x_power_check_online(struct wm831x *wm831x, int supply,
@@ -125,6 +128,43 @@ static enum power_supply_property wm831x_usb_props[] = {
POWER_SUPPLY_PROP_VOLTAGE_NOW,
 };
 
+/* In milliamps */
+static unsigned int wm831x_usb_limits[] = {
+   0,
+   2,
+   100,
+   500,
+   900,
+   1500,
+   1800,
+   550,
+};
+
+static int wm831x_usb_limit_change(struct notifier_block *nb,
+  unsigned long limit, void *data)
+{
+   struct wm831x_power *wm831x_power = container_of(nb,
+struct wm831x_power,
+usb_notify);
+   int i, best;
+
+   /* Find the highest supported limit */
+   best = 0;
+   for (i = 0; i < ARRAY_SIZE(wm831x_usb_limits); i++) {
+   if (limit >= wm831x_usb_limits[i] &&
+   wm831x_usb_limits[best] < wm831x_usb_limits[i])
+   best = i;
+   }
+
+   dev_dbg(wm831x_power->wm831x->dev,
+   "Limiting USB current to %dmA", wm831x_usb_limits[best]);
+
+   wm831x_set_bits(wm831x_power->wm831x, WM831X_POWER_STATE,
+   WM831X_USB_ILIM_MASK, best);
+
+   return 0;
+}
+
 /*
  * Battery properties
  */
@@ -607,8 +647,31 @@ static int wm831x_power_probe(struct platform_device *pdev)
}
}
 
+   if (wm831x_pdata && wm831x_pdata->usb_gadget) {
+   power->usb_charger =
+   usb_charger_find_by_name(wm831x_pdata->usb_gadget);
+   if (IS_ERR(power->usb_charger)) {
+   ret = PTR_ERR(power->usb_charger);
+   dev_err(>dev,
+   "Failed to find USB gadget: %d\n", ret);
+   goto err_bat_irq;
+   }
+
+   power->usb_notify.notifier_call = wm831x_usb_limit_change;
+
+   ret = usb_charger_register_notify(power->usb_charger,
+ >usb_notify);
+   if (ret != 0) {
+   dev_err(>dev,
+   "Failed to register notifier: %d\n", ret);
+   goto err_usb_charger;
+   }
+   }
+
return ret;
 
+err_usb_charger:
+   /* put_device on charger */
 err_bat_irq:
--i;
for (; i >= 0; i--) {
@@ -637,6 +700,12 @@ static int wm831x_power_remove(struct platform_device 
*pdev)
struct wm831x *wm831x = wm831x_power->wm831x;
int irq, i;
 
+   if (wm831x_power->usb_charger) {
+   usb_charger_unregister_notify(wm831x_power->usb_charger,
+ _power->usb_notify);
+   /* Free charger */
+   }
+
for (i = 0; i < ARRAY_SIZE(wm831x_bat_irqs); i++) {
irq = wm831x_irq(wm831x, 
 platform_get_irq_byname(pdev,
diff --git a/include/linux/mfd/wm831x/pdata.h b/include/linux/mfd/wm831x/pdata.h
index dcc9631..5af8399 100644
--- a/include/linux/mfd/wm831x/pdata.h
+++ b/include/linux/mfd/wm831x/pdata.h
@@ -126,6 +126,9 @@ struct wm831x_pdata {
/** The driver should initiate a power off sequence during shutdown */
bool soft_shutdown;
 
+   /** dev_name of USB charger gadget to integrate with */
+   const char *usb_gadget;
+
int irq_base;
int gpi

Re: [PATCH v7 0/4] Introduce usb charger framework to deal with the usb gadget power negotation

2016-01-07 Thread Baolin Wang
On 7 January 2016 at 19:25, Alex Shi  wrote:
> Hi, Baolin,
>
> There is similar gadget/charger driver on QC msm tree,
> git://codeaurora.org/quic/la/kernel/msm-3.10 msm-3.10
> You may check that as a reference.
>

OK. Thanks.

-- 
Baolin.wang
Best Regards
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH] usb: gadget: Add the console support for usb-to-serial port

2015-11-18 Thread Baolin Wang
On 18 November 2015 at 17:32, Andy Shevchenko <andy.shevche...@gmail.com> wrote:
> On Wed, Nov 18, 2015 at 4:15 AM, Baolin Wang <baolin.w...@linaro.org> wrote:
>> On 17 November 2015 at 21:34, Andy Shevchenko <andy.shevche...@gmail.com> 
>> wrote:
>>> On Mon, Nov 16, 2015 at 9:05 AM, Baolin Wang <baolin.w...@linaro.org> wrote:
>>>> It dose not work when we want to use the usb-to-serial port based
>>>> on one usb gadget as a console. Thus this patch adds the console
>>>> initialization to support this request.
>>>
>
>>>> +#define GS_BUFFER_SIZE (4096)
>>> Redundant parens
>> OK. I'll remove it.
>>
>>>> +#define GS_CONSOLE_BUF_SIZE(2 * GS_BUFFER_SIZE)
>>>> +
>>>> +struct gscons_info {
>>>> +   struct gs_port  *port;
>>>> +   struct tty_driver   *tty_driver;
>>>> +   struct work_struct  work;
>>>> +   int buf_tail;
>>>> +   charbuf[GS_CONSOLE_BUF_SIZE];
>>>
>>> Can't be malloced once?
>> The 'gscons_info' structure is malloced once.
>
> In state of high fragmentation is quite hard to find big memory chunks.
> I would split it to two allocations, though if maintainers are okay
> with your code, then I'm also okay.
>

Make sense. But I think the major memory of the 'struct gscons_info'
is for the 'buf' member, so I still think no need to allocate it 2
times.

>>>> +static struct usb_request *gs_request_new(struct usb_ep *ep, int 
>>>> buffer_size)
>>>> +{
>>>> +   struct usb_request *req = usb_ep_alloc_request(ep, GFP_ATOMIC);
>>>> +
>>>> +   if (!req)
>>>
>>> For sake of readability it's better to have assignment explicitly before 
>>> 'if'.
>>
>> But I think it is very easy to understand the assignment here with
>> saving code lines.
>
> It's not a function of couple of lines, so, for me makes sense to
> explicitly put the assignment here. Especially that one that does
> allocations (for pointer arithmetic I could agree to place the
> assignment in the definition block).
>

OK. Sounds reasonable.

>>>> +static void gs_complete_out(struct usb_ep *ep, struct usb_request *req)
>>>> +{
>>>> +   if (req->status != 0 && req->status != -ECONNRESET)
>>>> +   return;
>>>
>>> Something missed here. Currently it's no-op.
>>>
>>
>> Yeah. I didn't realize what need to do in the callback here, so just
>> leave a callback without anything. But maybe something will be added
>> if there are some requirements in future.
>
> if ()
> ..
>
> will be optimized away, why not to remove it?

OK. I'll remove it.

>
>>>> +   port = ports[port_num].port;
>>>> +   if (!port) {
>>>> +   pr_err("%s: serial line [%d] not allocated.\n",
>>>> +  __func__, port_num);
>>>> +   return -ENODEV;
>>>> +   }
>>>> +
>>>> +   if (!port->port_usb) {
>>>> +   pr_err("%s: no port usb.\n", __func__);
>>>
>>> Starting from here could it be dev_err and so on?
>>
>> There are no dev_err things and device things in this file, so pr_xxx
>> is more reasonable.
>
> This is understandable, but if in case you have device in place why
> not to use its name?

Yes, that's right.

>
>>>> +   pr_debug("%s: port[%d] console connect!\n", __func__, port_num);
>>>
>>> Dynamic debug will add function name if asked.
>>
>> Sorry, I didn't get your point, you mean print the function name is
>> redundant here?
>
> Right.
>
> Just pr_debug("port[%d] …", …);
>

OK. Very thanks for your suggestions.

> --
> With Best Regards,
> Andy Shevchenko



-- 
Baolin.wang
Best Regards
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH] usb: gadget: Add the console support for usb-to-serial port

2015-11-18 Thread Baolin Wang
On 18 November 2015 at 20:05, David Laight <david.lai...@aculab.com> wrote:
> From: Baolin Wang
>> Sent: 18 November 2015 10:45
>> On 18 November 2015 at 17:32, Andy Shevchenko <andy.shevche...@gmail.com> 
>> wrote:
>> > On Wed, Nov 18, 2015 at 4:15 AM, Baolin Wang <baolin.w...@linaro.org> 
>> > wrote:
>> >> On 17 November 2015 at 21:34, Andy Shevchenko <andy.shevche...@gmail.com> 
>> >> wrote:
>> >>> On Mon, Nov 16, 2015 at 9:05 AM, Baolin Wang <baolin.w...@linaro.org> 
>> >>> wrote:
>> >>>> It dose not work when we want to use the usb-to-serial port based
>> >>>> on one usb gadget as a console. Thus this patch adds the console
>> >>>> initialization to support this request.
>> >>>
>> >
>> >>>> +#define GS_BUFFER_SIZE (4096)
>> >>> Redundant parens
>> >> OK. I'll remove it.
>> >>
>> >>>> +#define GS_CONSOLE_BUF_SIZE(2 * GS_BUFFER_SIZE)
>> >>>> +
>> >>>> +struct gscons_info {
>> >>>> +   struct gs_port  *port;
>> >>>> +   struct tty_driver   *tty_driver;
>> >>>> +   struct work_struct  work;
>> >>>> +   int buf_tail;
>> >>>> +   charbuf[GS_CONSOLE_BUF_SIZE];
>> >>>
>> >>> Can't be malloced once?
>> >> The 'gscons_info' structure is malloced once.
>> >
>> > In state of high fragmentation is quite hard to find big memory chunks.
>> > I would split it to two allocations, though if maintainers are okay
>> > with your code, then I'm also okay.
>> >
>>
>> Make sense. But I think the major memory of the 'struct gscons_info'
>> is for the 'buf' member, so I still think no need to allocate it 2
>> times.
>
> It may be worth just reducing GS_BUFFER_SIZE slightly so that the gscons_info
> structure itself is less than 8k.
> If you can't get 2 adjacent pages then a lot of things will fail.
>

But its allocation is called in early booting time, I think there are
not many memory fragments now.

> David
>



-- 
Baolin.wang
Best Regards
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH] usb: gadget: Add the console support for usb-to-serial port

2015-11-18 Thread Baolin Wang
On 18 November 2015 at 23:32, Peter Hurley <pe...@hurleysoftware.com> wrote:
> Hi Baolin,
>
> On 11/16/2015 02:05 AM, Baolin Wang wrote:
>> It dose not work when we want to use the usb-to-serial port based
>> on one usb gadget as a console. Thus this patch adds the console
>> initialization to support this request.
>
> I have some high level concerns.
>
> 1. I would defer registering the console until the port has at least been
>allocated in gserial_alloc_line(), and unregister when the line is freed.
>That also reduces many of the conditions that you shouldn't need to
>check, like port number range and so on.

The 'setup' callback of 'struct console' is just do some memory
allocation and member initialization, that no need to defer
registering the console in gserial_alloc_line(). But the
'gs_console_connect()' which will use the port need to be called in
gserial_connect().

>
>Further, consider deferring the console registration until 
> gserial_connect();
>that would further simplify things. In this case, unregistration would
>happen at disconnect.

That sounds reasonable. I would try.

>
> 2. Why are you using a kworker for actual device i/o when all of the i/o
>is done with interrupts disabled anyway?
>Getting rid of the work would eliminate using the 8K intermediate buffer
>as well.

If remove the kworker, there are some deadlocks to call the printk()
when in the process of transferring data with usb endpoint. So we need
a async kworker to complete the io or it can not work.

>
> 3. If for some reason i/o deferral is really necessary, consider using a 
> kthread
>kworker instead of the pooled kworker. The scheduler response will be _way_
>better.
>

OK, make sense.

> 4. If for some reason i/o deferral is really necessary, use a circular buffer
>for the intermediate buffer, preferably lockless since there is only
>one producer and one consumer.
>

Yeah, the circular buffer is better but more tricky. I would try.

> Some other review comments below; please ignore anything other reviewers
> have already noted.
>
> Regards,
> Peter Hurley
>
>> Signed-off-by: Baolin Wang <baolin.w...@linaro.org>
>> ---
>>  drivers/usb/gadget/Kconfig |6 +
>>  drivers/usb/gadget/function/u_serial.c |  238 
>> 
>>  2 files changed, 244 insertions(+)
>>
>> diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig
>> index 33834aa..be5aab9 100644
>> --- a/drivers/usb/gadget/Kconfig
>> +++ b/drivers/usb/gadget/Kconfig
>> @@ -127,6 +127,12 @@ config USB_GADGET_STORAGE_NUM_BUFFERS
>>  a module parameter as well.
>>  If unsure, say 2.
>>
>> +config U_SERIAL_CONSOLE
>> + bool "Serial gadget console support"
>> + depends on USB_G_SERIAL
>> + help
>> +It supports the serial gadget can be used as a console.
>> +
>>  source "drivers/usb/gadget/udc/Kconfig"
>>
>>  #
>> diff --git a/drivers/usb/gadget/function/u_serial.c 
>> b/drivers/usb/gadget/function/u_serial.c
>> index f7771d8..4ade527 100644
>> --- a/drivers/usb/gadget/function/u_serial.c
>> +++ b/drivers/usb/gadget/function/u_serial.c
>> @@ -27,6 +27,7 @@
>>  #include 
>>  #include 
>>  #include 
>> +#include 
>>
>>  #include "u_serial.h"
>>
>> @@ -79,6 +80,16 @@
>>   */
>>  #define QUEUE_SIZE   16
>>  #define WRITE_BUF_SIZE   8192/* TX only */
>> +#define GS_BUFFER_SIZE   (4096)
>> +#define GS_CONSOLE_BUF_SIZE  (2 * GS_BUFFER_SIZE)
>> +
>> +struct gscons_info {
>> + struct gs_port  *port;
>> + struct tty_driver   *tty_driver;
>> + struct work_struct  work;
>> + int buf_tail;
>> + charbuf[GS_CONSOLE_BUF_SIZE];
>> +};
>
> Make struct gscons_info a static declaration instead of
> allocating it.

But I think the dynamic allocation is more reasonable with reducing
some global variables.

>
>>
>>  /* circular buffer */
>>  struct gs_buf {
>> @@ -118,6 +129,7 @@ struct gs_port {
>>
>>   /* REVISIT this state ... */
>>   struct usb_cdc_line_coding port_line_coding;/* 8-N-1 etc */
>> + struct usb_request  *console_req;
>>  };
>>
>>  static struct portmaster {
>> @@ -1054,6 +1066,7 @@ gs_port_alloc(unsigned port_num, struct 
>> usb_cdc_line_coding *coding)
>>
>>   port->port_num = port_num;
>>   port->port_line_codi

Re: [PATCH] usb: gadget: Add the console support for usb-to-serial port

2015-11-18 Thread Baolin Wang
>
>> +{
>> + struct gscons_info *info = gserial_cons.data;
>> + int port_num = gserial_cons.index;
>> + struct usb_request *req;
>> + struct gs_port *port;
>> + struct usb_ep *ep;
>> +
>> + if (port_num >= MAX_U_SERIAL_PORTS || port_num < 0) {
>> + pr_err("%s: port num [%d] exceeds the range.\n",
>> +__func__, port_num);
>> + return -ENXIO;
>> + }
>> +
>> + port = ports[port_num].port;
>> + if (!port) {
>> + pr_err("%s: serial line [%d] not allocated.\n",
>> +__func__, port_num);
>> + return -ENODEV;
>> + }
>> +
>> + if (!port->port_usb) {
>> + pr_err("%s: no port usb.\n", __func__);
>> + return -ENODEV;
>> + }
>> +
>> + ep = port->port_usb->in;
>> + if (!ep) {
>> + pr_err("%s: no usb endpoint.\n", __func__);
>> + return -ENXIO;
>> + }
>
> Looking at the caller, gserial_connect(), none of the error
> conditions above look possible.
>

I re-look the code and do some tests, I found the checking is
necessary. Cause we get the port number from the console->index, if
the cmdline is not set the ttyGS0 as the console, the console->index
will be -1 that is a wrong value. Also the serial.c file will create 1
usb-to-seial port as default (default n_ports = 1), so we need to
check the port and the endpoint of the port. So I think here checking
is necessary and I have tested it.



-- 
Baolin.wang
Best Regards
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH] usb: gadget: Add the console support for usb-to-serial port

2015-11-19 Thread Baolin Wang
On 19 November 2015 at 17:36, Peter Hurley <pe...@hurleysoftware.com> wrote:
> On 11/19/2015 01:48 AM, Baolin Wang wrote:
>>>
>>>> +{
>>>> + struct gscons_info *info = gserial_cons.data;
>>>> + int port_num = gserial_cons.index;
>>>> + struct usb_request *req;
>>>> + struct gs_port *port;
>>>> + struct usb_ep *ep;
>>>> +
>>>> + if (port_num >= MAX_U_SERIAL_PORTS || port_num < 0) {
>>>> + pr_err("%s: port num [%d] exceeds the range.\n",
>>>> +__func__, port_num);
>>>> + return -ENXIO;
>>>> + }
>>>> +
>>>> + port = ports[port_num].port;
>>>> + if (!port) {
>>>> + pr_err("%s: serial line [%d] not allocated.\n",
>>>> +__func__, port_num);
>>>> + return -ENODEV;
>>>> + }
>>>> +
>>>> + if (!port->port_usb) {
>>>> + pr_err("%s: no port usb.\n", __func__);
>>>> + return -ENODEV;
>>>> + }
>>>> +
>>>> + ep = port->port_usb->in;
>>>> + if (!ep) {
>>>> + pr_err("%s: no usb endpoint.\n", __func__);
>>>> + return -ENXIO;
>>>> + }
>>>
>>> Looking at the caller, gserial_connect(), none of the error
>>> conditions above look possible.
>>>
>>
>> I re-look the code and do some tests, I found the checking is
>> necessary. Cause we get the port number from the console->index, if
>> the cmdline is not set the ttyGS0 as the console, the console->index
>> will be -1 that is a wrong value. Also the serial.c file will create 1
>> usb-to-seial port as default (default n_ports = 1), so we need to
>> check the port and the endpoint of the port. So I think here checking
>> is necessary and I have tested it.
>
> static void gs_console_connect(int port_num)
> {
> .
> .
> if (port_num != gserial_cons.index)
> return;
> .

OK. Thanks.

> .
>
>
> @@ -1219,6 +1453,7 @@ int gserial_connect(struct gserial *gser, u8 port_num)
> gser->disconnect(gser);
> }
>
> +   status = gs_console_connect(port_num);
> spin_unlock_irqrestore(>port_lock, flags);
>
> return status;
>
>
>
>
>
>
>



-- 
Baolin.wang
Best Regards
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH] usb: gadget: Add the console support for usb-to-serial port

2015-11-19 Thread Baolin Wang
On 19 November 2015 at 18:28, Peter Hurley <pe...@hurleysoftware.com> wrote:
> On 11/18/2015 09:35 PM, Baolin Wang wrote:
>> On 18 November 2015 at 23:32, Peter Hurley <pe...@hurleysoftware.com> wrote:
>>> Hi Baolin,
>>>
>>> On 11/16/2015 02:05 AM, Baolin Wang wrote:
>>>> It dose not work when we want to use the usb-to-serial port based
>>>> on one usb gadget as a console. Thus this patch adds the console
>>>> initialization to support this request.
>>>
>>> I have some high level concerns.
>>>
>>> 1. I would defer registering the console until the port has at least been
>>>allocated in gserial_alloc_line(), and unregister when the line is freed.
>>>That also reduces many of the conditions that you shouldn't need to
>>>check, like port number range and so on.
>>
>> The 'setup' callback of 'struct console' is just do some memory
>> allocation and member initialization, that no need to defer
>> registering the console in gserial_alloc_line(). But the
>> 'gs_console_connect()' which will use the port need to be called in
>> gserial_connect().
>
> My point here was why are you registering the console before the port
> table is even allocated and initialized?  The console can't possibly
> perform i/o that early because the port doesn't even exist.
> Which is why I suggested waiting until gserial_alloc_line() to
> register the console.
>
> A typical console setup() performs the cross-reference linking between
> the console data structure and the port table. The reason for that
> is the console needs to be cleaned up if the port is being torn down.
>
> For example, in gserial_disconnect() the port->port_usb is reset to NULL,
> and later in gserial_console_exit():
>
> if (port && port->port_usb) {
> 
> gs_request_free(req, ep);
> }
>
> which means your leaking the request allocation when the port has been
> disconnected.
>

Yeah, that's right. I'll defer the console registration until
gserial_connect() and unregistration in disconnect.

>
>>>Further, consider deferring the console registration until 
>>> gserial_connect();
>>>that would further simplify things. In this case, unregistration would
>>>happen at disconnect.
>>
>> That sounds reasonable. I would try.
>>
>>>
>>> 2. Why are you using a kworker for actual device i/o when all of the i/o
>>>is done with interrupts disabled anyway?
>>>Getting rid of the work would eliminate using the 8K intermediate buffer
>>>as well.
>>
>> If remove the kworker, there are some deadlocks to call the printk()
>> when in the process of transferring data with usb endpoint. So we need
>> a async kworker to complete the io or it can not work.
>
> The commit log should detail the major design choices, including why you
> used the kworker (because of re-entrancy issues with usb endpoint).
>

OK.

>
>
>>> 3. If for some reason i/o deferral is really necessary, consider using a 
>>> kthread
>>>kworker instead of the pooled kworker. The scheduler response will be 
>>> _way_
>>>better.
>>>
>>
>> OK, make sense.
>>
>>> 4. If for some reason i/o deferral is really necessary, use a circular 
>>> buffer
>>>for the intermediate buffer, preferably lockless since there is only
>>>one producer and one consumer.
>>>
>>
>> Yeah, the circular buffer is better but more tricky. I would try.
>>
>>> Some other review comments below; please ignore anything other reviewers
>>> have already noted.
>>>
>>> Regards,
>>> Peter Hurley
>>>
>>>> Signed-off-by: Baolin Wang <baolin.w...@linaro.org>
>>>> ---
>>>>  drivers/usb/gadget/Kconfig |6 +
>>>>  drivers/usb/gadget/function/u_serial.c |  238 
>>>> 
>>>>  2 files changed, 244 insertions(+)
>>>>
>>>> diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig
>>>> index 33834aa..be5aab9 100644
>>>> --- a/drivers/usb/gadget/Kconfig
>>>> +++ b/drivers/usb/gadget/Kconfig
>>>> @@ -127,6 +127,12 @@ config USB_GADGET_STORAGE_NUM_BUFFERS
>>>>  a module parameter as well.
>>>>  If unsure, say 2.
>>>>
>>>> +config U_SERIAL_CONSOLE
>>>> + bool "Serial gadget console support"
>&

[PATCH v2] usb: gadget: Add the console support for usb-to-serial port

2015-11-20 Thread Baolin Wang
It dose not work when we want to use the usb-to-serial port based
on one usb gadget as a console. Thus this patch adds the console
initialization to support this request.

To avoid the re-entrance when transferring data with usb endpoint,
it introduces a kthread to do the IO transmission.

Signed-off-by: Baolin Wang <baolin.w...@linaro.org>
---
 drivers/usb/gadget/Kconfig |6 +
 drivers/usb/gadget/function/u_serial.c |  258 
 2 files changed, 264 insertions(+)

diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig
index 33834aa..be5aab9 100644
--- a/drivers/usb/gadget/Kconfig
+++ b/drivers/usb/gadget/Kconfig
@@ -127,6 +127,12 @@ config USB_GADGET_STORAGE_NUM_BUFFERS
   a module parameter as well.
   If unsure, say 2.
 
+config U_SERIAL_CONSOLE
+   bool "Serial gadget console support"
+   depends on USB_G_SERIAL
+   help
+  It supports the serial gadget can be used as a console.
+
 source "drivers/usb/gadget/udc/Kconfig"
 
 #
diff --git a/drivers/usb/gadget/function/u_serial.c 
b/drivers/usb/gadget/function/u_serial.c
index f7771d8..6af145f 100644
--- a/drivers/usb/gadget/function/u_serial.c
+++ b/drivers/usb/gadget/function/u_serial.c
@@ -27,6 +27,8 @@
 #include 
 #include 
 #include 
+#include 
+#include 
 
 #include "u_serial.h"
 
@@ -79,6 +81,7 @@
  */
 #define QUEUE_SIZE 16
 #define WRITE_BUF_SIZE 8192/* TX only */
+#define GS_CONSOLE_BUF_SIZE8192
 
 /* circular buffer */
 struct gs_buf {
@@ -88,6 +91,17 @@ struct gs_buf {
char*buf_put;
 };
 
+/* console info */
+struct gscons_info {
+   struct gs_port  *port;
+   struct task_struct  *console_thread;
+   struct gs_buf   con_buf;
+   /* protect the buf and busy flag */
+   spinlock_t  con_lock;
+   int req_busy;
+   struct usb_request  *console_req;
+};
+
 /*
  * The port structure holds info for each port, one for each minor number
  * (and thus for each /dev/ node).
@@ -1023,6 +1037,246 @@ static const struct tty_operations gs_tty_ops = {
 
 static struct tty_driver *gs_tty_driver;
 
+#ifdef CONFIG_U_SERIAL_CONSOLE
+
+static struct gscons_info gscons_info;
+static struct console gserial_cons;
+
+static struct usb_request *gs_request_new(struct usb_ep *ep)
+{
+   struct usb_request *req = usb_ep_alloc_request(ep, GFP_ATOMIC);
+   if (!req)
+   return NULL;
+
+   req->buf = kmalloc(ep->maxpacket, GFP_ATOMIC);
+   if (!req->buf) {
+   usb_ep_free_request(ep, req);
+   return NULL;
+   }
+
+   return req;
+}
+
+static void gs_request_free(struct usb_request *req, struct usb_ep *ep)
+{
+   if (!req)
+   return;
+
+   kfree(req->buf);
+   usb_ep_free_request(ep, req);
+}
+
+static void gs_complete_out(struct usb_ep *ep, struct usb_request *req)
+{
+   struct gscons_info *info = _info;
+
+   switch (req->status) {
+   default:
+   pr_warn("%s: unexpected %s status %d\n",
+   __func__, ep->name, req->status);
+   case 0:
+   /* normal completion */
+   spin_lock(>con_lock);
+   info->req_busy = 0;
+   spin_unlock(>con_lock);
+
+   wake_up_process(info->console_thread);
+   break;
+   case -ESHUTDOWN:
+   /* disconnect */
+   pr_vdebug("%s: %s shutdown\n", __func__, ep->name);
+   break;
+   }
+}
+
+static int gs_console_connect(int port_num)
+{
+   struct gscons_info *info = _info;
+   struct gs_port *port;
+   struct usb_ep *ep;
+
+   if (port_num != gserial_cons.index) {
+   pr_err("%s: port num [%d] is not support console\n",
+  __func__, port_num);
+   return -ENXIO;
+   }
+
+   port = ports[port_num].port;
+   ep = port->port_usb->in;
+   if (!info->console_req) {
+   info->console_req = gs_request_new(ep);
+   if (!info->console_req)
+   return -ENOMEM;
+   info->console_req->complete = gs_complete_out;
+   }
+
+   info->port = port;
+   spin_lock(>con_lock);
+   info->req_busy = 0;
+   spin_unlock(>con_lock);
+   pr_vdebug("port[%d] console connect!\n", port_num);
+   return 0;
+}
+
+static void gs_console_disconnect(struct usb_ep *ep)
+{
+   struct gscons_info *info = _info;
+   struct usb_request *req = info->console_req;
+
+   gs_request_free(req, ep);
+   info->console_req = NULL;
+}
+
+static int gs_console_thread(void *data)
+{
+   struct gscons_info *info = _info;
+   struct gs_port *port;
+   struct usb_request *

Re: [PATCH v2] usb: dwc3: host: Set the dma_ops for xhci device

2016-06-06 Thread Baolin Wang
On 6 June 2016 at 22:59, Felipe Balbi <ba...@kernel.org> wrote:
>
> Hi,
>
> Baolin Wang <baolin.w...@linaro.org> writes:
>> On ARM64 platform, it will set 'dummy_dma_ops' for device dma_ops if
>> it did not call 'arch_setup_dma_ops' at device creation time, that will
>> cause failure when setting the dma mask for device.
>>
>> Thus this patch set the xhci device dma_ops from the parent device if
>> the xhci device dma_ops is 'dummy_dma_ops'.
>>
>> Changes since v1:
>>  - Add CONFIG_ARM64 macro.
>>
>> Signed-off-by: Baolin Wang <baolin.w...@linaro.org>
>> ---
>>  drivers/usb/dwc3/host.c |5 +
>>  1 file changed, 5 insertions(+)
>>
>> diff --git a/drivers/usb/dwc3/host.c b/drivers/usb/dwc3/host.c
>> index c679f63..edb666d 100644
>> --- a/drivers/usb/dwc3/host.c
>> +++ b/drivers/usb/dwc3/host.c
>> @@ -32,6 +32,11 @@ int dwc3_host_init(struct dwc3 *dwc)
>>   return -ENOMEM;
>>   }
>>
>> +#ifdef CONFIG_ARM64
>> + if (get_dma_ops(>dev) == get_dma_ops(NULL))
>> + xhci->dev.archdata.dma_ops = get_dma_ops(dwc->dev);
>> +#endif
>
> I don't like the ifdef and also don't like that this is done in dwc3
> itself. Seems like we need something like this done from the
> platform_bus core.

OK. I will try to fix this issue in platform_bus core. Thanks.

>
> --
> balbi



-- 
Baolin.wang
Best Regards
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v2] usb: dwc3: host: Set the dma_ops for xhci device

2016-06-08 Thread Baolin Wang
Hi,

On 6 June 2016 at 22:59, Felipe Balbi <ba...@kernel.org> wrote:
>
> Hi,
>
> Baolin Wang <baolin.w...@linaro.org> writes:
>> On ARM64 platform, it will set 'dummy_dma_ops' for device dma_ops if
>> it did not call 'arch_setup_dma_ops' at device creation time, that will
>> cause failure when setting the dma mask for device.
>>
>> Thus this patch set the xhci device dma_ops from the parent device if
>> the xhci device dma_ops is 'dummy_dma_ops'.
>>
>> Changes since v1:
>>  - Add CONFIG_ARM64 macro.
>>
>> Signed-off-by: Baolin Wang <baolin.w...@linaro.org>
>> ---
>>  drivers/usb/dwc3/host.c |5 +
>>  1 file changed, 5 insertions(+)
>>
>> diff --git a/drivers/usb/dwc3/host.c b/drivers/usb/dwc3/host.c
>> index c679f63..edb666d 100644
>> --- a/drivers/usb/dwc3/host.c
>> +++ b/drivers/usb/dwc3/host.c
>> @@ -32,6 +32,11 @@ int dwc3_host_init(struct dwc3 *dwc)
>>   return -ENOMEM;
>>   }
>>
>> +#ifdef CONFIG_ARM64
>> + if (get_dma_ops(>dev) == get_dma_ops(NULL))
>> + xhci->dev.archdata.dma_ops = get_dma_ops(dwc->dev);
>> +#endif
>
> I don't like the ifdef and also don't like that this is done in dwc3
> itself. Seems like we need something like this done from the
> platform_bus core.

I've sent one patch to fix this issue in platform_bus core, and Robin
explained "DMA-capable devices are real hardware, therefore don't
spring out of thin air without being described in DT or ACPI."
But the problem is here, how can we handle this issue to make the host
work well? What about below modification? Thanks.

diff --git a/drivers/usb/dwc3/host.c b/drivers/usb/dwc3/host.c
index c679f63..f7c58f9 100644
--- a/drivers/usb/dwc3/host.c
+++ b/drivers/usb/dwc3/host.c
@@ -17,6 +17,7 @@

 #include 
 #include 
+#include 

 #include "core.h"

@@ -37,6 +38,7 @@ int dwc3_host_init(struct dwc3 *dwc)
xhci->dev.parent= dwc->dev;
xhci->dev.dma_mask  = dwc->dev->dma_mask;
xhci->dev.dma_parms = dwc->dev->dma_parms;
+   of_dma_configure(>dev, dwc->dev->of_node);

dwc->xhci = xhci;

-- 
Baolin.wang
Best Regards
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH] usb: dwc3: host: Set the dma_ops for xhci device

2016-06-03 Thread Baolin Wang
It will be failed when xhci device set the dma mask, if the xhci device
dma_ops is dummy. Thus set the xhci device dma_ops from the parent device.

Signed-off-by: Baolin Wang <baolin.w...@linaro.org>
---
 drivers/usb/dwc3/host.c |3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/usb/dwc3/host.c b/drivers/usb/dwc3/host.c
index c679f63..7ce55c9 100644
--- a/drivers/usb/dwc3/host.c
+++ b/drivers/usb/dwc3/host.c
@@ -32,6 +32,9 @@ int dwc3_host_init(struct dwc3 *dwc)
return -ENOMEM;
}
 
+   if (get_dma_ops(>dev) == get_dma_ops(NULL))
+   xhci->dev.archdata.dma_ops = get_dma_ops(dwc->dev);
+
dma_set_coherent_mask(>dev, dwc->dev->coherent_dma_mask);
 
xhci->dev.parent= dwc->dev;
-- 
1.7.9.5

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[RESEND PATCH v11 4/4] power: wm831x_power: Support USB charger current limit management

2016-06-13 Thread Baolin Wang
Integrate with the newly added USB charger interface to limit the current
we draw from the USB input based on the input device configuration
identified by the USB stack, allowing us to charge more quickly from high
current inputs without drawing more current than specified from others.

Signed-off-by: Mark Brown <broo...@kernel.org>
Signed-off-by: Baolin Wang <baolin.w...@linaro.org>
Acked-by: Lee Jones <lee.jo...@linaro.org>
Acked-by: Charles Keepax <ckee...@opensource.wolfsonmicro.com>
Acked-by: Peter Chen <peter.c...@freescale.com>
Acked-by: Sebastian Reichel <s...@kernel.org>
---
 drivers/power/wm831x_power.c |   69 ++
 include/linux/mfd/wm831x/pdata.h |3 ++
 2 files changed, 72 insertions(+)

diff --git a/drivers/power/wm831x_power.c b/drivers/power/wm831x_power.c
index 7082301..cef1812 100644
--- a/drivers/power/wm831x_power.c
+++ b/drivers/power/wm831x_power.c
@@ -13,6 +13,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include 
 #include 
@@ -31,6 +32,8 @@ struct wm831x_power {
char usb_name[20];
char battery_name[20];
bool have_battery;
+   struct usb_charger *usb_charger;
+   struct notifier_block usb_notify;
 };
 
 static int wm831x_power_check_online(struct wm831x *wm831x, int supply,
@@ -125,6 +128,43 @@ static enum power_supply_property wm831x_usb_props[] = {
POWER_SUPPLY_PROP_VOLTAGE_NOW,
 };
 
+/* In milliamps */
+static const unsigned int wm831x_usb_limits[] = {
+   0,
+   2,
+   100,
+   500,
+   900,
+   1500,
+   1800,
+   550,
+};
+
+static int wm831x_usb_limit_change(struct notifier_block *nb,
+  unsigned long limit, void *data)
+{
+   struct wm831x_power *wm831x_power = container_of(nb,
+struct wm831x_power,
+usb_notify);
+   unsigned int i, best;
+
+   /* Find the highest supported limit */
+   best = 0;
+   for (i = 0; i < ARRAY_SIZE(wm831x_usb_limits); i++) {
+   if (limit >= wm831x_usb_limits[i] &&
+   wm831x_usb_limits[best] < wm831x_usb_limits[i])
+   best = i;
+   }
+
+   dev_dbg(wm831x_power->wm831x->dev,
+   "Limiting USB current to %umA", wm831x_usb_limits[best]);
+
+   wm831x_set_bits(wm831x_power->wm831x, WM831X_POWER_STATE,
+   WM831X_USB_ILIM_MASK, best);
+
+   return 0;
+}
+
 /*
  * Battery properties
  */
@@ -607,8 +647,31 @@ static int wm831x_power_probe(struct platform_device *pdev)
}
}
 
+   if (wm831x_pdata && wm831x_pdata->usb_gadget) {
+   power->usb_charger =
+   usb_charger_find_by_name(wm831x_pdata->usb_gadget);
+   if (IS_ERR(power->usb_charger)) {
+   ret = PTR_ERR(power->usb_charger);
+   dev_err(>dev,
+   "Failed to find USB gadget: %d\n", ret);
+   goto err_bat_irq;
+   }
+
+   power->usb_notify.notifier_call = wm831x_usb_limit_change;
+
+   ret = usb_charger_register_notify(power->usb_charger,
+ >usb_notify);
+   if (ret != 0) {
+   dev_err(>dev,
+   "Failed to register notifier: %d\n", ret);
+   goto err_usb_charger;
+   }
+   }
+
return ret;
 
+err_usb_charger:
+   /* put_device on charger */
 err_bat_irq:
--i;
for (; i >= 0; i--) {
@@ -637,6 +700,12 @@ static int wm831x_power_remove(struct platform_device 
*pdev)
struct wm831x *wm831x = wm831x_power->wm831x;
int irq, i;
 
+   if (wm831x_power->usb_charger) {
+   usb_charger_unregister_notify(wm831x_power->usb_charger,
+ _power->usb_notify);
+   /* Free charger */
+   }
+
for (i = 0; i < ARRAY_SIZE(wm831x_bat_irqs); i++) {
irq = wm831x_irq(wm831x, 
 platform_get_irq_byname(pdev,
diff --git a/include/linux/mfd/wm831x/pdata.h b/include/linux/mfd/wm831x/pdata.h
index dcc9631..5af8399 100644
--- a/include/linux/mfd/wm831x/pdata.h
+++ b/include/linux/mfd/wm831x/pdata.h
@@ -126,6 +126,9 @@ struct wm831x_pdata {
/** The driver should initiate a power off sequence during shutdown */
bool soft_shutdown;
 
+   /** dev_name of USB charger gadget to integrate with */
+   const char *usb_gadget;
+
int irq_base

[RESEND PATCH v11 1/4] gadget: Introduce the usb charger framework

2016-06-13 Thread Baolin Wang
This patch introduces the usb charger driver based on usb gadget that
makes an enhancement to a power driver. It works well in practice but
that requires a system with suitable hardware.

The basic conception of the usb charger is that, when one usb charger
is added or removed by reporting from the usb gadget state change or
the extcon device state change, the usb charger will report to power
user to set the current limitation.

The usb charger will register notifiees on the usb gadget or the extcon
device to get notified the usb charger state. It also supplies the
notification mechanism to userspace When the usb charger state is changed.

Power user will register a notifiee on the usb charger to get notified
by status changes from the usb charger. It will report to power user
to set the current limitation when detecting the usb charger is added
or removed from extcon device state or usb gadget state.

This patch doesn't yet integrate with the gadget code, so some functions
which rely on the 'gadget' are not completed, that will be implemented
in the following patches.

Signed-off-by: Baolin Wang <baolin.w...@linaro.org>
---
 drivers/usb/gadget/Kconfig   |7 +
 drivers/usb/gadget/udc/Makefile  |1 +
 drivers/usb/gadget/udc/charger.c |  770 ++
 include/linux/usb/charger.h  |  191 ++
 include/uapi/linux/usb/charger.h |   31 ++
 5 files changed, 1000 insertions(+)
 create mode 100644 drivers/usb/gadget/udc/charger.c
 create mode 100644 include/linux/usb/charger.h
 create mode 100644 include/uapi/linux/usb/charger.h

diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig
index 2057add..89f4e9b 100644
--- a/drivers/usb/gadget/Kconfig
+++ b/drivers/usb/gadget/Kconfig
@@ -134,6 +134,13 @@ config U_SERIAL_CONSOLE
help
   It supports the serial gadget can be used as a console.
 
+config USB_CHARGER
+   bool "USB charger support"
+   help
+ The usb charger driver based on the usb gadget that makes an
+ enhancement to a power driver which can set the current limitation
+ when the usb charger is added or removed.
+
 source "drivers/usb/gadget/udc/Kconfig"
 
 #
diff --git a/drivers/usb/gadget/udc/Makefile b/drivers/usb/gadget/udc/Makefile
index dfee534..0e9564c 100644
--- a/drivers/usb/gadget/udc/Makefile
+++ b/drivers/usb/gadget/udc/Makefile
@@ -2,6 +2,7 @@
 # USB peripheral controller drivers
 #
 obj-$(CONFIG_USB_GADGET)   += udc-core.o
+obj-$(CONFIG_USB_CHARGER)  += charger.o
 obj-$(CONFIG_USB_DUMMY_HCD)+= dummy_hcd.o
 obj-$(CONFIG_USB_NET2272)  += net2272.o
 obj-$(CONFIG_USB_NET2280)  += net2280.o
diff --git a/drivers/usb/gadget/udc/charger.c b/drivers/usb/gadget/udc/charger.c
new file mode 100644
index 000..7be4c76
--- /dev/null
+++ b/drivers/usb/gadget/udc/charger.c
@@ -0,0 +1,770 @@
+/*
+ * charger.c -- USB charger driver
+ *
+ * Copyright (C) 2015 Linaro Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define DEFAULT_SDP_CUR_LIMIT  500
+#define DEFAULT_SDP_CUR_LIMIT_SS   900
+#define DEFAULT_DCP_CUR_LIMIT  1500
+#define DEFAULT_CDP_CUR_LIMIT  1500
+#define DEFAULT_ACA_CUR_LIMIT  1500
+
+static DEFINE_IDA(usb_charger_ida);
+struct class *usb_charger_class;
+static unsigned int usb_charger_get_cur_limit(struct usb_charger *uchger);
+
+static struct usb_charger *dev_to_uchger(struct device *dev)
+{
+   return container_of(dev, struct usb_charger, dev);
+}
+
+/*
+ * charger_current_show() - Show the charger current limit.
+ */
+static ssize_t charger_current_show(struct device *dev,
+   struct device_attribute *attr,
+   char *buf)
+{
+   struct usb_charger *uchger = dev_to_uchger(dev);
+
+   return sprintf(buf, "%u\n", usb_charger_get_cur_limit(uchger));
+}
+static DEVICE_ATTR_RO(charger_current);
+
+/*
+ * charger_type_show() - Show the charger type.
+ *
+ * It can be SDP/DCP/CDP/ACA type, else for unknown type.
+ */
+static ssize_t charger_type_show(struct device *dev,
+struct device_attribute *attr,
+char *buf)
+{
+   struct usb_charger *uchger = dev_to_uchger(dev);
+   int cnt;
+
+   switch (uchger->type) {
+   case SDP_TYPE:
+   cnt = sprintf(buf, "%s\n", "SDP");
+   break;
+   case DCP_TYPE:
+   cnt = sprintf(buf, "%s\n", "DCP");
+   break;
+   case CDP_TYPE:
+   cnt = sprintf(buf, "%s\n", "CDP");
+   break;
+   case 

[RESEND PATCH v11 0/4] Introduce usb charger framework to deal with the usb gadget power negotation

2016-06-13 Thread Baolin Wang
Currently the Linux kernel does not provide any standard integration of this
feature that integrates the USB subsystem with the system power regulation
provided by PMICs meaning that either vendors must add this in their kernels
or USB gadget devices based on Linux (such as mobile phones) may not behave
as they should. Thus provide a standard framework for doing this in kernel.

Now introduce one user with wm831x_power to support and test the usb charger,
which is pending testing. Moreover there may be other potential users will use
it in future.

Changes since v10:
 - Introduce usb_charger_get_state() function to check charger state.
 - Remove the mutex lock in usb_charger_set_cur_limit_by_type() function
 in case will be issued in atomic context.

Baolin Wang (4):
  gadget: Introduce the usb charger framework
  gadget: Support for the usb charger framework
  gadget: Integrate with the usb gadget supporting for usb charger
  power: wm831x_power: Support USB charger current limit management

 drivers/power/wm831x_power.c  |   69 
 drivers/usb/gadget/Kconfig|7 +
 drivers/usb/gadget/udc/Makefile   |1 +
 drivers/usb/gadget/udc/charger.c  |  807 +
 drivers/usb/gadget/udc/udc-core.c |   11 +
 include/linux/mfd/wm831x/pdata.h  |3 +
 include/linux/usb/charger.h   |  191 +
 include/linux/usb/gadget.h|   11 +
 include/uapi/linux/usb/charger.h  |   31 ++
 9 files changed, 1131 insertions(+)
 create mode 100644 drivers/usb/gadget/udc/charger.c
 create mode 100644 include/linux/usb/charger.h
 create mode 100644 include/uapi/linux/usb/charger.h

-- 
1.7.9.5

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[RESEND PATCH v11 2/4] gadget: Support for the usb charger framework

2016-06-13 Thread Baolin Wang
For supporting the usb charger, it adds the usb_charger_init() and
usb_charger_exit() functions for usb charger initialization and exit.

It will report to the usb charger when the gadget state is changed,
then the usb charger can do the power things.

Signed-off-by: Baolin Wang <baolin.w...@linaro.org>
---
 drivers/usb/gadget/udc/udc-core.c |   11 +++
 include/linux/usb/gadget.h|   11 +++
 2 files changed, 22 insertions(+)

diff --git a/drivers/usb/gadget/udc/udc-core.c 
b/drivers/usb/gadget/udc/udc-core.c
index 6e8300d..84c098c 100644
--- a/drivers/usb/gadget/udc/udc-core.c
+++ b/drivers/usb/gadget/udc/udc-core.c
@@ -28,6 +28,7 @@
 #include 
 #include 
 #include 
+#include 
 
 /**
  * struct usb_udc - describes one usb device controller
@@ -242,6 +243,9 @@ static void usb_gadget_state_work(struct work_struct *work)
struct usb_gadget *gadget = work_to_gadget(work);
struct usb_udc *udc = gadget->udc;
 
+   /* when the gadget state is changed, then report to USB charger */
+   usb_charger_plug_by_gadget(gadget, gadget->state);
+
if (udc)
sysfs_notify(>dev.kobj, NULL, "state");
 }
@@ -411,6 +415,10 @@ int usb_add_gadget_udc_release(struct device *parent, 
struct usb_gadget *gadget,
if (ret)
goto err4;
 
+   ret = usb_charger_init(gadget);
+   if (ret)
+   goto err5;
+
usb_gadget_set_state(gadget, USB_STATE_NOTATTACHED);
udc->vbus = true;
 
@@ -431,6 +439,8 @@ int usb_add_gadget_udc_release(struct device *parent, 
struct usb_gadget *gadget,
 
return 0;
 
+err5:
+   device_del(>dev);
 err4:
list_del(>list);
mutex_unlock(_lock);
@@ -539,6 +549,7 @@ void usb_del_gadget_udc(struct usb_gadget *gadget)
kobject_uevent(>dev.kobj, KOBJ_REMOVE);
flush_work(>work);
device_unregister(>dev);
+   usb_charger_exit(gadget);
device_unregister(>dev);
 }
 EXPORT_SYMBOL_GPL(usb_del_gadget_udc);
diff --git a/include/linux/usb/gadget.h b/include/linux/usb/gadget.h
index 457651b..40390ec 100644
--- a/include/linux/usb/gadget.h
+++ b/include/linux/usb/gadget.h
@@ -24,6 +24,7 @@
 #include 
 #include 
 #include 
+#include 
 
 struct usb_ep;
 
@@ -639,6 +640,8 @@ struct usb_gadget {
unsignedout_epnum;
unsignedin_epnum;
struct usb_otg_caps *otg_caps;
+   /* negotiate the power with the usb charger */
+   struct usb_charger  *charger;
 
unsignedsg_supported:1;
unsignedis_otg:1;
@@ -855,10 +858,18 @@ static inline int usb_gadget_vbus_connect(struct 
usb_gadget *gadget)
  * reporting how much power the device may consume.  For example, this
  * could affect how quickly batteries are recharged.
  *
+ * It will also notify the USB charger how much power the device may
+ * consume if there is a USB charger linking with the gadget.
+ *
  * Returns zero on success, else negative errno.
  */
 static inline int usb_gadget_vbus_draw(struct usb_gadget *gadget, unsigned mA)
 {
+   if (gadget->charger)
+   usb_charger_set_cur_limit_by_type(gadget->charger,
+ gadget->charger->type,
+ mA);
+
if (!gadget->ops->vbus_draw)
return -EOPNOTSUPP;
return gadget->ops->vbus_draw(gadget, mA);
-- 
1.7.9.5

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[RESEND PATCH v11 3/4] gadget: Integrate with the usb gadget supporting for usb charger

2016-06-13 Thread Baolin Wang
When the usb gadget supporting for usb charger is ready, the usb charger
can implement the usb_charger_plug_by_gadget() function and usb_charger_exit()
function by getting 'struct usb_charger' from 'struct gadget'.

Signed-off-by: Baolin Wang <baolin.w...@linaro.org>
---
 drivers/usb/gadget/udc/charger.c |   39 +-
 1 file changed, 38 insertions(+), 1 deletion(-)

diff --git a/drivers/usb/gadget/udc/charger.c b/drivers/usb/gadget/udc/charger.c
index 7be4c76..949396f 100644
--- a/drivers/usb/gadget/udc/charger.c
+++ b/drivers/usb/gadget/udc/charger.c
@@ -568,6 +568,30 @@ usb_charger_plug_by_extcon(struct notifier_block *nb,
 int usb_charger_plug_by_gadget(struct usb_gadget *gadget,
   unsigned long state)
 {
+   struct usb_charger *uchger = gadget->charger;
+   enum usb_charger_state uchger_state;
+
+   if (WARN(!uchger, "charger can not be NULL"))
+   return -EINVAL;
+
+   /*
+* Report event to power to setting the current limitation
+* for this usb charger when one usb charger state is changed
+* with detecting by usb gadget state.
+*/
+   if (uchger->old_gadget_state != state) {
+   uchger->old_gadget_state = state;
+
+   if (state >= USB_STATE_ATTACHED)
+   uchger_state = USB_CHARGER_PRESENT;
+   else if (state == USB_STATE_NOTATTACHED)
+   uchger_state = USB_CHARGER_REMOVE;
+   else
+   uchger_state = USB_CHARGER_DEFAULT;
+
+   usb_charger_notify_others(uchger, uchger_state);
+   }
+
return 0;
 }
 EXPORT_SYMBOL_GPL(usb_charger_plug_by_gadget);
@@ -724,6 +748,7 @@ int usb_charger_init(struct usb_gadget *ugadget)
 
/* register a notifier on a usb gadget device */
uchger->gadget = ugadget;
+   ugadget->charger = uchger;
uchger->old_gadget_state = USB_STATE_NOTATTACHED;
 
/* register a new usb charger */
@@ -744,7 +769,19 @@ fail:
 
 int usb_charger_exit(struct usb_gadget *ugadget)
 {
-   return 0;
+   struct usb_charger *uchger = ugadget->charger;
+
+   if (WARN(!uchger, "charger can not be NULL"))
+   return -EINVAL;
+
+   if (uchger->extcon_dev)
+   extcon_unregister_notifier(uchger->extcon_dev,
+  EXTCON_USB,
+  >extcon_nb.nb);
+
+   ida_simple_remove(_charger_ida, uchger->id);
+
+   return usb_charger_unregister(uchger);
 }
 
 static int __init usb_charger_class_init(void)
-- 
1.7.9.5

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[RESEND PATCH v11 0/4] Introduce usb charger framework to deal with the usb gadget power negotation

2016-06-13 Thread Baolin Wang
From: Baolin Wang <baolin.w...@spreadtrum.com>

Currently the Linux kernel does not provide any standard integration of this
feature that integrates the USB subsystem with the system power regulation
provided by PMICs meaning that either vendors must add this in their kernels
or USB gadget devices based on Linux (such as mobile phones) may not behave
as they should. Thus provide a standard framework for doing this in kernel.

Now introduce one user with wm831x_power to support and test the usb charger,
which is pending testing. Moreover there may be other potential users will use
it in future.

Changes since v10:
 - Introduce usb_charger_get_state() function to check charger state.
 - Remove the mutex lock in usb_charger_set_cur_limit_by_type() function
 in case will be issued in atomic context.

Baolin Wang (4):
  gadget: Introduce the usb charger framework
  gadget: Support for the usb charger framework
  gadget: Integrate with the usb gadget supporting for usb charger
  power: wm831x_power: Support USB charger current limit management

 drivers/power/wm831x_power.c  |   69 
 drivers/usb/gadget/Kconfig|7 +
 drivers/usb/gadget/udc/Makefile   |1 +
 drivers/usb/gadget/udc/charger.c  |  807 +
 drivers/usb/gadget/udc/udc-core.c |   11 +
 include/linux/mfd/wm831x/pdata.h  |3 +
 include/linux/usb/charger.h   |  191 +
 include/linux/usb/gadget.h|   11 +
 include/uapi/linux/usb/charger.h  |   31 ++
 9 files changed, 1131 insertions(+)
 create mode 100644 drivers/usb/gadget/udc/charger.c
 create mode 100644 include/linux/usb/charger.h
 create mode 100644 include/uapi/linux/usb/charger.h

-- 
1.7.9.5

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[RESEND PATCH v11 1/4] gadget: Introduce the usb charger framework

2016-06-13 Thread Baolin Wang
This patch introduces the usb charger driver based on usb gadget that
makes an enhancement to a power driver. It works well in practice but
that requires a system with suitable hardware.

The basic conception of the usb charger is that, when one usb charger
is added or removed by reporting from the usb gadget state change or
the extcon device state change, the usb charger will report to power
user to set the current limitation.

The usb charger will register notifiees on the usb gadget or the extcon
device to get notified the usb charger state. It also supplies the
notification mechanism to userspace When the usb charger state is changed.

Power user will register a notifiee on the usb charger to get notified
by status changes from the usb charger. It will report to power user
to set the current limitation when detecting the usb charger is added
or removed from extcon device state or usb gadget state.

This patch doesn't yet integrate with the gadget code, so some functions
which rely on the 'gadget' are not completed, that will be implemented
in the following patches.

Signed-off-by: Baolin Wang <baolin.w...@linaro.org>
---
 drivers/usb/gadget/Kconfig   |7 +
 drivers/usb/gadget/udc/Makefile  |1 +
 drivers/usb/gadget/udc/charger.c |  770 ++
 include/linux/usb/charger.h  |  191 ++
 include/uapi/linux/usb/charger.h |   31 ++
 5 files changed, 1000 insertions(+)
 create mode 100644 drivers/usb/gadget/udc/charger.c
 create mode 100644 include/linux/usb/charger.h
 create mode 100644 include/uapi/linux/usb/charger.h

diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig
index 2057add..89f4e9b 100644
--- a/drivers/usb/gadget/Kconfig
+++ b/drivers/usb/gadget/Kconfig
@@ -134,6 +134,13 @@ config U_SERIAL_CONSOLE
help
   It supports the serial gadget can be used as a console.
 
+config USB_CHARGER
+   bool "USB charger support"
+   help
+ The usb charger driver based on the usb gadget that makes an
+ enhancement to a power driver which can set the current limitation
+ when the usb charger is added or removed.
+
 source "drivers/usb/gadget/udc/Kconfig"
 
 #
diff --git a/drivers/usb/gadget/udc/Makefile b/drivers/usb/gadget/udc/Makefile
index dfee534..0e9564c 100644
--- a/drivers/usb/gadget/udc/Makefile
+++ b/drivers/usb/gadget/udc/Makefile
@@ -2,6 +2,7 @@
 # USB peripheral controller drivers
 #
 obj-$(CONFIG_USB_GADGET)   += udc-core.o
+obj-$(CONFIG_USB_CHARGER)  += charger.o
 obj-$(CONFIG_USB_DUMMY_HCD)+= dummy_hcd.o
 obj-$(CONFIG_USB_NET2272)  += net2272.o
 obj-$(CONFIG_USB_NET2280)  += net2280.o
diff --git a/drivers/usb/gadget/udc/charger.c b/drivers/usb/gadget/udc/charger.c
new file mode 100644
index 000..7be4c76
--- /dev/null
+++ b/drivers/usb/gadget/udc/charger.c
@@ -0,0 +1,770 @@
+/*
+ * charger.c -- USB charger driver
+ *
+ * Copyright (C) 2015 Linaro Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define DEFAULT_SDP_CUR_LIMIT  500
+#define DEFAULT_SDP_CUR_LIMIT_SS   900
+#define DEFAULT_DCP_CUR_LIMIT  1500
+#define DEFAULT_CDP_CUR_LIMIT  1500
+#define DEFAULT_ACA_CUR_LIMIT  1500
+
+static DEFINE_IDA(usb_charger_ida);
+struct class *usb_charger_class;
+static unsigned int usb_charger_get_cur_limit(struct usb_charger *uchger);
+
+static struct usb_charger *dev_to_uchger(struct device *dev)
+{
+   return container_of(dev, struct usb_charger, dev);
+}
+
+/*
+ * charger_current_show() - Show the charger current limit.
+ */
+static ssize_t charger_current_show(struct device *dev,
+   struct device_attribute *attr,
+   char *buf)
+{
+   struct usb_charger *uchger = dev_to_uchger(dev);
+
+   return sprintf(buf, "%u\n", usb_charger_get_cur_limit(uchger));
+}
+static DEVICE_ATTR_RO(charger_current);
+
+/*
+ * charger_type_show() - Show the charger type.
+ *
+ * It can be SDP/DCP/CDP/ACA type, else for unknown type.
+ */
+static ssize_t charger_type_show(struct device *dev,
+struct device_attribute *attr,
+char *buf)
+{
+   struct usb_charger *uchger = dev_to_uchger(dev);
+   int cnt;
+
+   switch (uchger->type) {
+   case SDP_TYPE:
+   cnt = sprintf(buf, "%s\n", "SDP");
+   break;
+   case DCP_TYPE:
+   cnt = sprintf(buf, "%s\n", "DCP");
+   break;
+   case CDP_TYPE:
+   cnt = sprintf(buf, "%s\n", "CDP");
+   break;
+   case 

[PATCH v2] usb: dwc3: host: Set the dma_ops for xhci device

2016-06-05 Thread Baolin Wang
On ARM64 platform, it will set 'dummy_dma_ops' for device dma_ops if
it did not call 'arch_setup_dma_ops' at device creation time, that will
cause failure when setting the dma mask for device.

Thus this patch set the xhci device dma_ops from the parent device if
the xhci device dma_ops is 'dummy_dma_ops'.

Changes since v1:
 - Add CONFIG_ARM64 macro.

Signed-off-by: Baolin Wang <baolin.w...@linaro.org>
---
 drivers/usb/dwc3/host.c |5 +
 1 file changed, 5 insertions(+)

diff --git a/drivers/usb/dwc3/host.c b/drivers/usb/dwc3/host.c
index c679f63..edb666d 100644
--- a/drivers/usb/dwc3/host.c
+++ b/drivers/usb/dwc3/host.c
@@ -32,6 +32,11 @@ int dwc3_host_init(struct dwc3 *dwc)
return -ENOMEM;
}
 
+#ifdef CONFIG_ARM64
+   if (get_dma_ops(>dev) == get_dma_ops(NULL))
+   xhci->dev.archdata.dma_ops = get_dma_ops(dwc->dev);
+#endif
+
dma_set_coherent_mask(>dev, dwc->dev->coherent_dma_mask);
 
xhci->dev.parent= dwc->dev;
-- 
1.7.9.5

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH] dwc3: gadget: Introduce dwc3_endpoint_xfer_xxx() to check endpoint type

2016-05-25 Thread Baolin Wang
When handling the endpoint interrupt handler, it maybe disable the endpoint
from another core user to set the USB endpoint descriptor pointor to be NULL
while issuing usb_gadget_giveback_request() function to release lock. So it
will be one bug to check the endpoint type by usb_endpoint_xfer_xxx() APIs with
one NULL USB endpoint descriptor.

Thus this patch introduces safety dwc3_endpoint_xfer_xxx() APIs to check
endpoint type with checking if the endpoint flag 'DWC3_EP_ENABLED' is set or
not.

[ 4007.812527] c1 init(1) call enable_store(0)
[ 4007.812633] c0 dwc3 2050.dwc3: ep1out disabled while handling ep event
[ 4007.812657] c0 Unable to handle kernel NULL pointer dereference at virtual 
address 0003
[ 4007.812669] c0 pgd = ffc0260a8000
[ 4007.812681] c0 [0003] *pgd=b4ab4003, *pud=b4ab4003, 
*pmd=
[ 4007.812709] c0 Internal error: Oops: 9606 [#1] PREEMPT SMP
[ 4007.818441] c0 Modules linked in: bcmdhd
[ 4007.821854] c3 warning saudio_recv cache is empty!
[ 4007.821860] c3 aud_recv_cmd  ENODATA
[ 4007.821869] c3 aud_send_cmd in,cmd =11 id:10 ret-value:0
[ 4007.821876] c3 saudio_send: dst=1, channel=0, timeout=-1
[ 4007.840767] c0  mali_kbase(O)
[ 4007.843707] c0
[ 4007.843889] c0 CPU: 0 PID: 8126 Comm: adbd Tainted: GW  O   3.18.12+ 
#1
[ 4007.851153] c0 Hardware name: Spreadtrum SP9860g Board (DT)
[ 4007.856693] c0 task: ffc02638a400 ti: ffc026148000 task.ti: 
ffc026148000
[ 4007.864404] c0 PC is at dwc3_interrupt_bh+0x710/0x112c
[ 4007.869503] c0 LR is at dwc3_interrupt_bh+0x70c/0x112c
[ 4007.874604] c0 pc : [] lr : [] pstate: 
21c5
[ 4007.882218] c0 sp : ffc02614b970
[ 4007.885766] c0 x29: ffc02614b970 x28: ffc000c75f90
[ 4007.891044] c0 x27: 0008 x26: 
[ 4007.896323] c0 x25:  x24: 030c
[ 4007.901602] c0 x23: ffc000ff1000 x22: 0004
[ 4007.906881] c0 x21: ffc03d9fb5d8 x20: ffc13e573600
[ 4007.912160] c0 x19: ffc13e133020 x18: 0007
[ 4007.917437] c0 x17: 000e x16: 0001
[ 4007.922717] c0 x15: 0007 x14: 0fff
[ 4007.927996] c0 x13: 0001 x12: 0101010101010101
[ 4007.933274] c0 x11: 000c4f5d x10: 0002
[ 4007.938553] c0 x9 :  x8 : 000c4f5e
[ 4007.943833] c0 x7 : 696c646e61682065 x6 : ffc000fa6cdc
[ 4007.949111] c0 x5 :  x4 : 0105
[ 4007.954390] c0 x3 :  x2 : 
[ 4007.959669] c0 x1 : 5533250a x0 : 
..
[ 4009.150699] c0 Call trace:
[ 4009.153394] c0 [] dwc3_interrupt_bh+0x710/0x112c
[ 4009.159532] c0 [] tasklet_action+0xb0/0x188
[ 4009.165243] c0 [] __do_softirq+0x114/0x3b4
[ 4009.170867] c0 [] irq_exit+0xa8/0xdc
[ 4009.175975] c0 [] __handle_domain_irq+0x90/0xf8
[ 4009.182030] c0 [] gic_handle_irq+0x58/0x1b4
[ 4009.187739] c0 Exception stack(0xffc02614bb70 to 0xffc02614bc90)
[ 4009.194404] c0 bb60: 0140  
3e133108 ffc1
[ 4009.202802] c0 bb80: 2614bcd0 ffc0 009cff0c ffc0 8145  
0018 
[ 4009.211194] c0 bba0: 0400  00459900 ffc0   
00d1aa50 ffc0
[ 4009.219589] c0 bbc0: 2614bc00 ffc0 26148000 ffc0 0001  
3d2ce4e0 ffc1
[ 4009.227984] c0 bbe0: bdc0  0001  2638a980 ffc0 
2614ba40 ffc0
[ 4009.236379] c0 bc00: 0400  0001  1d37bbb0 ffc0 
0013 
[ 4009.244772] c0 bc20: 000e  0007  0001  
000e 
[ 4009.253167] c0 bc40: 0007  0140  3e133108 ffc1 
3e133108 ffc1
[ 4009.261560] c0 bc60: 0140  3eb833c0 ffc1 0018  
0400 
[ 4009.269951] c0 bc80: 1eb29b80 ffc1 3acd7c00 ffc0
[ 4009.275233] c0 [] el1_irq+0x68/0xdc
[ 4009.280255] c0 [] dwc3_gadget_ep_dequeue+0x180/0x1b8
[ 4009.286741] c0 [] ffs_epfile_io+0x330/0x374
[ 4009.292453] c0 [] ffs_epfile_read+0x30/0x40
[ 4009.298169] c0 [] vfs_read+0xa0/0x1dc
[ 4009.303357] c0 [] SyS_read+0x50/0xb0

Signed-off-by: Baolin Wang <baolin.w...@linaro.org>
---
 drivers/usb/dwc3/gadget.c |   95 ++---
 1 file changed, 72 insertions(+), 23 deletions(-)

diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
index 8e4a1b1..5d095f2 100644
--- a/drivers/usb/dwc3/gadget.c
+++ b/drivers/usb/dwc3/gadget.c
@@ -36,6 +36,56 @@
 #include "io.h"
 
 /**
+* dwc3_endpoint_xfer_bulk - check if the endpoint has bulk transfer type
+* @ep: endpoint to be checked
+*
+* Returns true if the endpoint is of type bulk, otherwise it returns false.
+*/
+static inline int dwc3_endpoint_xfer_bulk(struct dwc3_ep *ep)
+{
+   return ((ep->flags & DWC3_EP_ENABLED) &&
+   ep->type == USB_ENDPOINT_XFER_BULK);
+}
+

Re: [PATCH] dwc3: gadget: Introduce dwc3_endpoint_xfer_xxx() to check endpoint type

2016-05-26 Thread Baolin Wang
Hi Felipe,

On 26 May 2016 at 14:22, Felipe Balbi <ba...@kernel.org> wrote:
>
> Hi,
>
> Baolin Wang <baolin.w...@linaro.org> writes:
>> When handling the endpoint interrupt handler, it maybe disable the endpoint
>> from another core user to set the USB endpoint descriptor pointor to be NULL
>> while issuing usb_gadget_giveback_request() function to release lock. So it
>> will be one bug to check the endpoint type by usb_endpoint_xfer_xxx() APIs 
>> with
>> one NULL USB endpoint descriptor.
>
> too complex, Baolin :-) Can you see if this helps:
>
> https://git.kernel.org/cgit/linux/kernel/git/balbi/usb.git/commit/?id=88bf752cfb55e57a78e27c931c9fef63240c739a
>
> The only situation when that can happen is while we drop our lock on
> dwc3_gadget_giveback().

OK, But line 1974 and line 2025 as below may be at risk? So I think
can we have a common place to solve the problem in case
usb_endpoint_xfer_xxx() APIs are issued at this risk? What do you
think? Thanks.

1956 static int dwc3_cleanup_done_reqs(struct dwc3 *dwc, struct dwc3_ep *dep,
1957 const struct dwc3_event_depevt *event, int status)
1958 {
1959 struct dwc3_request *req;
1960 struct dwc3_trb *trb;
1961 unsigned intslot;
1962 unsigned inti;
1963 int ret;
1964
1965 do {
1966 req = next_request(>req_queued);
1967 if (WARN_ON_ONCE(!req))
1968 return 1;
1969
1970 i = 0;
1971 do {
1972 slot = req->start_slot + i;
1973 if ((slot == DWC3_TRB_NUM - 1) &&
1974 usb_endpoint_xfer_isoc(dep->endpoint.desc))
1975 slot++;
1976 slot %= DWC3_TRB_NUM;
1977 trb = >trb_pool[slot];
1978
1979 ret = __dwc3_cleanup_done_trbs(dwc, dep, req, trb,
1980 event, status);
1981 if (ret)
1982 break;
1983 } while (++i < req->request.num_mapped_sgs);
1984
1985 dwc3_gadget_giveback(dep, req, status);
1986
1987 if (ret)
1988 break;
1989 } while (1);
...

2011 static void dwc3_endpoint_transfer_complete(struct dwc3 *dwc,
2012 struct dwc3_ep *dep, const struct dwc3_event_depevt *event)
2013 {
2014 unsignedstatus = 0;
2015 int clean_busy;
2016 u32 is_xfer_complete;
2017
2018 is_xfer_complete = (event->endpoint_event ==
DWC3_DEPEVT_XFERCOMPLETE);
2019
2020 if (event->status & DEPEVT_STATUS_BUSERR)
2021 status = -ECONNRESET;
2022
2023 clean_busy = dwc3_cleanup_done_reqs(dwc, dep, event, status);
2024 if (clean_busy && (is_xfer_complete ||
2025
usb_endpoint_xfer_isoc(dep->endpoint.desc)))
2026 dep->flags &= ~DWC3_EP_BUSY;

>
> --
> balbi



-- 
Baolin.wang
Best Regards
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH] dwc3: gadget: Introduce dwc3_endpoint_xfer_xxx() to check endpoint type

2016-05-26 Thread Baolin Wang
On 26 May 2016 at 18:27, Felipe Balbi <ba...@kernel.org> wrote:
>
> Hi,
>
> Baolin Wang <baolin.w...@linaro.org> writes:
>> On 26 May 2016 at 17:45, Felipe Balbi <ba...@kernel.org> wrote:
>>>
>>> Hi,
>>>
>>> Baolin Wang <baolin.w...@linaro.org> writes:
>>>
>>> 
>>>
>>>>> Also note that the usb_endpoint_xfer_isoc() call on line 2067 of
>>>>> gadget.c (as in my testing/next from today) won't even get executed, so
>>>>> we're safe there.
>>>>
>>>> Never will be executed? then we can remove the
>>>> usb_endpoint_xfer_isoc() (line 2025) at risk?
>>>>
>>>> 2023 clean_busy = dwc3_cleanup_done_reqs(dwc, dep, event, status);
>>>> 2024 if (clean_busy && (is_xfer_complete ||
>>>> 2025
>>>> usb_endpoint_xfer_isoc(dep->endpoint.desc)))
>>>> 2026 dep->flags &= ~DWC3_EP_BUSY;
>>>
>>> hmm, now that I look at this again, in case of XferInProgress, we could
>>> still have a problem.
>>>
>>> I'll fix it up in that commit I pointed you to.
>>
>> Great. Thanks.
>
> fixed now:
>
> https://git.kernel.org/cgit/linux/kernel/git/balbi/usb.git/commit/?h=testing/next=983b84268656ff2686253b05097d28003bbec52f

OK. I'll test it again with applying your patch. Thanks.

>
> --
> balbi



-- 
Baolin.wang
Best Regards
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH] dwc3: gadget: Introduce dwc3_endpoint_xfer_xxx() to check endpoint type

2016-05-26 Thread Baolin Wang
On 26 May 2016 at 17:45, Felipe Balbi <ba...@kernel.org> wrote:
>
> Hi,
>
> Baolin Wang <baolin.w...@linaro.org> writes:
>
> 
>
>>> Also note that the usb_endpoint_xfer_isoc() call on line 2067 of
>>> gadget.c (as in my testing/next from today) won't even get executed, so
>>> we're safe there.
>>
>> Never will be executed? then we can remove the
>> usb_endpoint_xfer_isoc() (line 2025) at risk?
>>
>> 2023 clean_busy = dwc3_cleanup_done_reqs(dwc, dep, event, status);
>> 2024 if (clean_busy && (is_xfer_complete ||
>> 2025
>> usb_endpoint_xfer_isoc(dep->endpoint.desc)))
>> 2026 dep->flags &= ~DWC3_EP_BUSY;
>
> hmm, now that I look at this again, in case of XferInProgress, we could
> still have a problem.
>
> I'll fix it up in that commit I pointed you to.

Great. Thanks.

>
> --
> balbi



-- 
Baolin.wang
Best Regards
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v12 2/4] gadget: Support for the usb charger framework

2016-06-21 Thread Baolin Wang
On 21 June 2016 at 18:27, Felipe Balbi <ba...@kernel.org> wrote:
>
> Hi,
>
> Baolin Wang <baolin.w...@linaro.org> writes:
>> For supporting the usb charger, it adds the usb_charger_init() and
>> usb_charger_exit() functions for usb charger initialization and exit.
>>
>> It will report to the usb charger when the gadget state is changed,
>> then the usb charger can do the power things.
>>
>> Signed-off-by: Baolin Wang <baolin.w...@linaro.org>
>> Reviewed-by: Li Jun <jun...@nxp.com>
>> Tested-by: Li Jun <jun...@nxp.com>
>
> Before anything, I must say that I really liked this patch. It's

Thanks.

> minimaly invasive to udc core and does all the necessary changes. If it
> wasn't for the extra charger class, this would've been perfect.
>
> Can't you just tie a charger to a UDC and avoid the charger class
> completely?

Yeah, I also hope so. But we really want something to manage the
charger devices, do you have any good suggestion to avoid the 'class'
but also can manage the charger devices?

>
>>  static inline int usb_gadget_vbus_draw(struct usb_gadget *gadget, unsigned 
>> mA)
>>  {
>> + if (gadget->charger)
>
> I guess you could do this check inside
> usb_gadget_set_cur_limit_by_type() itself.

OK.

>
> --
> balbi



-- 
Baolin.wang
Best Regards
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v12 4/4] power: wm831x_power: Support USB charger current limit management

2016-06-21 Thread Baolin Wang
On 21 June 2016 at 19:53, Felipe Balbi <ba...@kernel.org> wrote:
>
> Hi,
>
> Baolin Wang <baolin.w...@linaro.org> writes:
>> On 21 June 2016 at 19:03, Mark Brown <broo...@kernel.org> wrote:
>>> On Tue, Jun 21, 2016 at 01:30:49PM +0300, Felipe Balbi wrote:
>>>> Baolin Wang <baolin.w...@linaro.org> writes:
>>>> > @@ -607,8 +647,31 @@ static int wm831x_power_probe(struct 
>>>> > platform_device *pdev)
>>>> > }
>>>> > }
>>>
>>>> > +   if (wm831x_pdata && wm831x_pdata->usb_gadget) {
>>>> > +   power->usb_charger =
>>>> > +   usb_charger_find_by_name(wm831x_pdata->usb_gadget);
>>>
>>>> the fact that you rely on strings and pass them via pdata is an
>>>> indication that you don't have enough description of the HW. Seems like
>>>> we need to come up with a set of DT properties which tie a charger to a
>>>> UDC.
>>>
>>>> I'm thinking a phandle would be enough?
>>>
>>> The wm831x has no DT support currently.
>>
>> Another hand I suppose the usb charger is one virtual device and does
>> not need be described from DT.
>
> Right, I don't think that should be a device at all. But you can pass a
> phandle to the UDC controller and use that to get to struct usb_gadget
> from which you could reach ->charger.

Ah, make sense.

-- 
Baolin.wang
Best Regards
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v12 2/4] gadget: Support for the usb charger framework

2016-06-21 Thread Baolin Wang
On 21 June 2016 at 19:49, Felipe Balbi <ba...@kernel.org> wrote:
>
> Hi,
>
> Baolin Wang <baolin.w...@linaro.org> writes:
>>> Can't you just tie a charger to a UDC and avoid the charger class
>>> completely?
>>
>> Yeah, I also hope so. But we really want something to manage the
>> charger devices, do you have any good suggestion to avoid the 'class'
>> but also can manage the charger devices?
>
> manage in what way? It seems to me that they don't need to be real
> devices, just a handle as part of struct usb_gadget, no?

Although charger device is not one real hardware device, we also use
one 'struct device' to describe it in charger.c file. So we should
manage the 'struct device' with one proper way.

-- 
Baolin.wang
Best Regards
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v12 4/4] power: wm831x_power: Support USB charger current limit management

2016-06-21 Thread Baolin Wang
On 21 June 2016 at 19:03, Mark Brown <broo...@kernel.org> wrote:
> On Tue, Jun 21, 2016 at 01:30:49PM +0300, Felipe Balbi wrote:
>> Baolin Wang <baolin.w...@linaro.org> writes:
>> > @@ -607,8 +647,31 @@ static int wm831x_power_probe(struct platform_device 
>> > *pdev)
>> > }
>> > }
>
>> > +   if (wm831x_pdata && wm831x_pdata->usb_gadget) {
>> > +   power->usb_charger =
>> > +   usb_charger_find_by_name(wm831x_pdata->usb_gadget);
>
>> the fact that you rely on strings and pass them via pdata is an
>> indication that you don't have enough description of the HW. Seems like
>> we need to come up with a set of DT properties which tie a charger to a
>> UDC.
>
>> I'm thinking a phandle would be enough?
>
> The wm831x has no DT support currently.

Another hand I suppose the usb charger is one virtual device and does
not need be described from DT.

-- 
Baolin.wang
Best Regards
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v12 0/4] Introduce usb charger framework to deal with the usb gadget power negotation

2016-06-21 Thread Baolin Wang
Currently the Linux kernel does not provide any standard integration of this
feature that integrates the USB subsystem with the system power regulation
provided by PMICs meaning that either vendors must add this in their kernels
or USB gadget devices based on Linux (such as mobile phones) may not behave
as they should. Thus provide a standard framework for doing this in kernel.

Now introduce one user with wm831x_power to support and test the usb charger,
which is pending testing. Moreover there may be other potential users will use
it in future.

Changes since v11:
 - Reviewed and tested by Li Jun.

Changes since v10:
 - Introduce usb_charger_get_state() function to check charger state.
 - Remove the mutex lock in usb_charger_set_cur_limit_by_type() function
 in case will be issued in atomic context.

Baolin Wang (4):
  gadget: Introduce the usb charger framework
  gadget: Support for the usb charger framework
  gadget: Integrate with the usb gadget supporting for usb charger
  power: wm831x_power: Support USB charger current limit management

 drivers/power/wm831x_power.c  |   69 
 drivers/usb/gadget/Kconfig|7 +
 drivers/usb/gadget/udc/Makefile   |1 +
 drivers/usb/gadget/udc/charger.c  |  807 +
 drivers/usb/gadget/udc/udc-core.c |   11 +
 include/linux/mfd/wm831x/pdata.h  |3 +
 include/linux/usb/charger.h   |  191 +
 include/linux/usb/gadget.h|   11 +
 include/uapi/linux/usb/charger.h  |   31 ++
 9 files changed, 1131 insertions(+)
 create mode 100644 drivers/usb/gadget/udc/charger.c
 create mode 100644 include/linux/usb/charger.h
 create mode 100644 include/uapi/linux/usb/charger.h

-- 
1.7.9.5

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


  1   2   3   4   5   6   >