[PATCH 09/14] twl4030_charger: only draw USB current as negotiated with host.

2015-03-22 Thread NeilBrown
From: NeilBrown ne...@suse.de

If the phy has been told what current it can draw, it tells us
and now we use that number.

Note that 'vbus_draw' is in mA, while usb_cur is in uA.

Acked-by: Pavel Machek pa...@ucw.cz
Signed-off-by: NeilBrown ne...@suse.de
---
 drivers/power/twl4030_charger.c |5 +
 1 file changed, 5 insertions(+)

diff --git a/drivers/power/twl4030_charger.c b/drivers/power/twl4030_charger.c
index df031b0123d0..2042e7619954 100644
--- a/drivers/power/twl4030_charger.c
+++ b/drivers/power/twl4030_charger.c
@@ -602,6 +602,7 @@ static void twl4030_bci_usb_work(struct work_struct *data)
switch (bci-event) {
case USB_EVENT_VBUS:
case USB_EVENT_CHARGER:
+   case USB_EVENT_ENUMERATED:
twl4030_charger_enable_usb(bci, true);
break;
case USB_EVENT_NONE:
@@ -614,6 +615,7 @@ static int twl4030_bci_usb_ncb(struct notifier_block *nb, 
unsigned long val,
   void *priv)
 {
struct twl4030_bci *bci = container_of(nb, struct twl4030_bci, usb_nb);
+   unsigned int *vbus_draw = priv;
 
dev_dbg(bci-dev, OTG notify %lu\n, val);
 
@@ -624,6 +626,9 @@ static int twl4030_bci_usb_ncb(struct notifier_block *nb, 
unsigned long val,
bci-usb_cur = 10;
 
bci-event = val;
+   if (val == USB_EVENT_ENUMERATED  vbus_draw 
+   *vbus_draw * 1000  bci-usb_cur)
+   bci-usb_cur = *vbus_draw * 1000;
schedule_work(bci-work);
 
return NOTIFY_OK;


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


Re: [PATCH v1.1 13/15] v4l: of: Read lane-polarities endpoint property

2015-03-22 Thread Laurent Pinchart
Hi Sakari,

Thank you for the patch.
On Saturday 21 March 2015 00:08:15 Sakari Ailus wrote:
 Add lane_polarities field to struct v4l2_of_bus_mipi_csi2 and write the
 contents of the lane-polarities property to it. The field tells the polarity
 of the physical lanes starting from the first one. Any unused lanes are
 ignored, i.e. only the polarity of the used lanes is specified.
 
 Also rework reading the data-lanes property a little.
 
 Signed-off-by: Sakari Ailus sakari.ai...@iki.fi

Acked-by: Laurent Pinchart laurent.pinch...@ideasonboard.com

 ---
 since v1:
 
 - Rename lane-polarity property as lane-polarities.
 
  drivers/media/v4l2-core/v4l2-of.c |   41 ++
  include/media/v4l2-of.h   |3 +++
  2 files changed, 35 insertions(+), 9 deletions(-)
 
 diff --git a/drivers/media/v4l2-core/v4l2-of.c
 b/drivers/media/v4l2-core/v4l2-of.c index b4ed9a9..58e401f 100644
 --- a/drivers/media/v4l2-core/v4l2-of.c
 +++ b/drivers/media/v4l2-core/v4l2-of.c
 @@ -19,11 +19,10 @@
 
  #include media/v4l2-of.h
 
 -static void v4l2_of_parse_csi_bus(const struct device_node *node,
 -   struct v4l2_of_endpoint *endpoint)
 +static int v4l2_of_parse_csi_bus(const struct device_node *node,
 +  struct v4l2_of_endpoint *endpoint)
  {
   struct v4l2_of_bus_mipi_csi2 *bus = endpoint-bus.mipi_csi2;
 - u32 data_lanes[ARRAY_SIZE(bus-data_lanes)];
   struct property *prop;
   bool have_clk_lane = false;
   unsigned int flags = 0;
 @@ -32,16 +31,34 @@ static void v4l2_of_parse_csi_bus(const struct
 device_node *node, prop = of_find_property(node, data-lanes, NULL);
   if (prop) {
   const __be32 *lane = NULL;
 - int i;
 + unsigned int i;
 
 - for (i = 0; i  ARRAY_SIZE(data_lanes); i++) {
 - lane = of_prop_next_u32(prop, lane, data_lanes[i]);
 + for (i = 0; i  ARRAY_SIZE(bus-data_lanes); i++) {
 + lane = of_prop_next_u32(prop, lane, v);
   if (!lane)
   break;
 + bus-data_lanes[i] = v;
   }
   bus-num_data_lanes = i;
 - while (i--)
 - bus-data_lanes[i] = data_lanes[i];
 + }
 +
 + prop = of_find_property(node, lane-polarities, NULL);
 + if (prop) {
 + const __be32 *polarity = NULL;
 + unsigned int i;
 +
 + for (i = 0; i  ARRAY_SIZE(bus-lane_polarities); i++) {
 + polarity = of_prop_next_u32(prop, polarity, v);
 + if (!polarity)
 + break;
 + bus-lane_polarities[i] = v;
 + }
 +
 + if (i  1 + bus-num_data_lanes /* clock + data */) {
 + pr_warn(%s: too few lane-polarities entries (need %u, 
 got 
%u)\n,
 + node-full_name, 1 + bus-num_data_lanes, i);
 + return -EINVAL;
 + }
   }
 
   if (!of_property_read_u32(node, clock-lanes, v)) {
 @@ -56,6 +73,8 @@ static void v4l2_of_parse_csi_bus(const struct device_node
 *node,
 
   bus-flags = flags;
   endpoint-bus_type = V4L2_MBUS_CSI2;
 +
 + return 0;
  }
 
  static void v4l2_of_parse_parallel_bus(const struct device_node *node,
 @@ -127,11 +146,15 @@ static void v4l2_of_parse_parallel_bus(const struct
 device_node *node, int v4l2_of_parse_endpoint(const struct device_node
 *node,
  struct v4l2_of_endpoint *endpoint)
  {
 + int rval;
 +
   of_graph_parse_endpoint(node, endpoint-base);
   endpoint-bus_type = 0;
   memset(endpoint-bus, 0, sizeof(endpoint-bus));
 
 - v4l2_of_parse_csi_bus(node, endpoint);
 + rval = v4l2_of_parse_csi_bus(node, endpoint);
 + if (rval)
 + return rval;
   /*
* Parse the parallel video bus properties only if none
* of the MIPI CSI-2 specific properties were found.
 diff --git a/include/media/v4l2-of.h b/include/media/v4l2-of.h
 index 70fa7b7..2de42c5 100644
 --- a/include/media/v4l2-of.h
 +++ b/include/media/v4l2-of.h
 @@ -29,12 +29,15 @@ struct device_node;
   * @data_lanes: an array of physical data lane indexes
   * @clock_lane: physical lane index of the clock lane
   * @num_data_lanes: number of data lanes
 + * @lane_polarities: polarity of the lanes. The order is the same of
 + *  the physical lanes.
   */
  struct v4l2_of_bus_mipi_csi2 {
   unsigned int flags;
   unsigned char data_lanes[4];
   unsigned char clock_lane;
   unsigned short num_data_lanes;
 + bool lane_polarities[5];
  };
 
  /**

-- 
Regards,

Laurent Pinchart

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


[PATCH v1.1 10/15] omap3isp: Move the syscon register out of the ISP register maps

2015-03-22 Thread Sakari Ailus
The syscon register isn't part of the ISP, use it through the syscom driver
regmap instead. The syscom block is considered to be from 343x on ISP
revision 2.0 whereas 15.0 is assumed to have 3630 syscon.

Signed-off-by: Sakari Ailus sakari.ai...@iki.fi
Acked-by: Laurent Pinchart laurent.pinch...@ideasonboard.com
Acked-by: Tony Lindgren t...@atomide.com
---
since v1:

- Depend on MFD_SYSCON in Kconfig

 arch/arm/mach-omap2/devices.c   |   10 --
 drivers/media/platform/Kconfig  |1 +
 drivers/media/platform/omap3isp/isp.c   |   20 
 drivers/media/platform/omap3isp/isp.h   |   19 +--
 drivers/media/platform/omap3isp/ispcsiphy.c |   20 +---
 5 files changed, 43 insertions(+), 27 deletions(-)

diff --git a/arch/arm/mach-omap2/devices.c b/arch/arm/mach-omap2/devices.c
index 1afb50d..e945957 100644
--- a/arch/arm/mach-omap2/devices.c
+++ b/arch/arm/mach-omap2/devices.c
@@ -143,16 +143,6 @@ static struct resource omap3isp_resources[] = {
.flags  = IORESOURCE_MEM,
},
{
-   .start  = OMAP343X_CTRL_BASE + OMAP343X_CONTROL_CSIRXFE,
-   .end= OMAP343X_CTRL_BASE + OMAP343X_CONTROL_CSIRXFE 
+ 3,
-   .flags  = IORESOURCE_MEM,
-   },
-   {
-   .start  = OMAP343X_CTRL_BASE + 
OMAP3630_CONTROL_CAMERA_PHY_CTRL,
-   .end= OMAP343X_CTRL_BASE + 
OMAP3630_CONTROL_CAMERA_PHY_CTRL + 3,
-   .flags  = IORESOURCE_MEM,
-   },
-   {
.start  = 24 + OMAP_INTC_START,
.flags  = IORESOURCE_IRQ,
}
diff --git a/drivers/media/platform/Kconfig b/drivers/media/platform/Kconfig
index 2e30be5..272dc8c 100644
--- a/drivers/media/platform/Kconfig
+++ b/drivers/media/platform/Kconfig
@@ -90,6 +90,7 @@ config VIDEO_OMAP3
select ARM_DMA_USE_IOMMU
select OMAP_IOMMU
select VIDEOBUF2_DMA_CONTIG
+   select MFD_SYSCON
---help---
  Driver for an OMAP 3 camera controller.
 
diff --git a/drivers/media/platform/omap3isp/isp.c 
b/drivers/media/platform/omap3isp/isp.c
index 68d7edfc..83b4368 100644
--- a/drivers/media/platform/omap3isp/isp.c
+++ b/drivers/media/platform/omap3isp/isp.c
@@ -51,6 +51,7 @@
 #include linux/dma-mapping.h
 #include linux/i2c.h
 #include linux/interrupt.h
+#include linux/mfd/syscon.h
 #include linux/module.h
 #include linux/omap-iommu.h
 #include linux/platform_device.h
@@ -94,8 +95,9 @@ static const struct isp_res_mapping isp_res_maps[] = {
   1  OMAP3_ISP_IOMEM_RESZ |
   1  OMAP3_ISP_IOMEM_SBL |
   1  OMAP3_ISP_IOMEM_CSI2A_REGS1 |
-  1  OMAP3_ISP_IOMEM_CSIPHY2 |
-  1  OMAP3_ISP_IOMEM_343X_CONTROL_CSIRXFE,
+  1  OMAP3_ISP_IOMEM_CSIPHY2,
+   .syscon_offset = 0xdc,
+   .phy_type = ISP_PHY_TYPE_3430,
},
{
.isp_rev = ISP_REVISION_15_0,
@@ -112,8 +114,9 @@ static const struct isp_res_mapping isp_res_maps[] = {
   1  OMAP3_ISP_IOMEM_CSI2A_REGS2 |
   1  OMAP3_ISP_IOMEM_CSI2C_REGS1 |
   1  OMAP3_ISP_IOMEM_CSIPHY1 |
-  1  OMAP3_ISP_IOMEM_CSI2C_REGS2 |
-  1  OMAP3_ISP_IOMEM_3630_CONTROL_CAMERA_PHY_CTRL,
+  1  OMAP3_ISP_IOMEM_CSI2C_REGS2,
+   .syscon_offset = 0x2f0,
+   .phy_type = ISP_PHY_TYPE_3630,
},
 };
 
@@ -2352,6 +2355,15 @@ static int isp_probe(struct platform_device *pdev)
}
}
 
+   isp-syscon = syscon_regmap_lookup_by_pdevname(syscon.0);
+   if (IS_ERR(isp-syscon)) {
+   ret = PTR_ERR(isp-syscon);
+   goto error_isp;
+   }
+
+   isp-syscon_offset = isp_res_maps[m].syscon_offset;
+   isp-phy_type = isp_res_maps[m].phy_type;
+
/* IOMMU */
ret = isp_attach_iommu(isp);
if (ret  0) {
diff --git a/drivers/media/platform/omap3isp/isp.h 
b/drivers/media/platform/omap3isp/isp.h
index 9535524..03d2129 100644
--- a/drivers/media/platform/omap3isp/isp.h
+++ b/drivers/media/platform/omap3isp/isp.h
@@ -59,8 +59,6 @@ enum isp_mem_resources {
OMAP3_ISP_IOMEM_CSI2C_REGS1,
OMAP3_ISP_IOMEM_CSIPHY1,
OMAP3_ISP_IOMEM_CSI2C_REGS2,
-   OMAP3_ISP_IOMEM_343X_CONTROL_CSIRXFE,
-   OMAP3_ISP_IOMEM_3630_CONTROL_CAMERA_PHY_CTRL,
OMAP3_ISP_IOMEM_LAST
 };
 
@@ -93,14 +91,25 @@ enum isp_subclk_resource {
 /* ISP2P: OMAP 36xx */
 #define ISP_REVISION_15_0  0xF0
 
+#define ISP_PHY_TYPE_3430  0
+#define ISP_PHY_TYPE_3630  1
+
+struct regmap;
+
 /*
  * struct isp_res_mapping - Map ISP io resources to ISP revision.
  * @isp_rev: ISP_REVISION_x_x
  * @map: bitmap for enum isp_mem_resources
+ * @syscon_offset: offset of 

Re: [PATCH v1.1 14/15] omap3isp: Add support for the Device Tree

2015-03-22 Thread Sakari Ailus
Hi Laurent,

On Sat, Mar 21, 2015 at 12:05:04AM +0200, Sakari Ailus wrote:
 Add the ISP device to omap3 DT include file and add support to the driver to
 use it.
 
 Also obtain information on the external entities and the ISP configuration
 related to them through the Device Tree in addition to the platform data.
 
 Signed-off-by: Sakari Ailus sakari.ai...@iki.fi

If you're happy with this version, please add the set to your tree. The
patches can be also found in here, on top of your histogram DMA changes:

ssh://linuxtv.org/git/sailus/media_tree.git rm696-054-media

-- 
Kind regards,

Sakari Ailus
e-mail: sakari.ai...@iki.fi XMPP: sai...@retiisi.org.uk
--
To unsubscribe from this list: send the line unsubscribe linux-omap in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 32/35 linux-next] clk: constify of_device_id array

2015-03-22 Thread Fabian Frederick


 On 18 March 2015 at 15:15 Michael Turquette mturque...@linaro.org wrote:


 Quoting Fabian Frederick (2015-03-16 12:59:06)
  of_device_id is always used as const.
  (See driver.of_match_table and open firmware functions)
 
  Signed-off-by: Fabian Frederick f...@skynet.be

 Acked-by: Michael Turquette mturque...@linaro.org

Thanks :)

btw, something I forgot to mention in changelog is the __initdata - __initconst
for ti_clkdm_match_table[]

I can send it again with a new changelog if necessary ...

Regards,
Fabian


  ---
   drivers/clk/clk-palmas.c                 | 2 +-
   drivers/clk/st/clkgen-fsyn.c             | 2 +-
   drivers/clk/st/clkgen-mux.c              | 8 
   drivers/clk/st/clkgen-pll.c              | 4 ++--
   drivers/clk/ti/clk-dra7-atl.c            | 2 +-
   drivers/clk/ti/clockdomain.c             | 2 +-
   drivers/clk/versatile/clk-vexpress-osc.c | 2 +-
   7 files changed, 11 insertions(+), 11 deletions(-)
 
  diff --git a/drivers/clk/clk-palmas.c b/drivers/clk/clk-palmas.c
  index 8d45992..45a535a 100644
  --- a/drivers/clk/clk-palmas.c
  +++ b/drivers/clk/clk-palmas.c
  @@ -161,7 +161,7 @@ static struct palmas_clks_of_match_data
  palmas_of_clk32kgaudio = {
          },
   };
  
  -static struct of_device_id palmas_clks_of_match[] = {
  +static const struct of_device_id palmas_clks_of_match[] = {
          {
                  .compatible = ti,palmas-clk32kg,
                  .data = palmas_of_clk32kg,
  diff --git a/drivers/clk/st/clkgen-fsyn.c b/drivers/clk/st/clkgen-fsyn.c
  index af94ed8..a917c4c 100644
  --- a/drivers/clk/st/clkgen-fsyn.c
  +++ b/drivers/clk/st/clkgen-fsyn.c
  @@ -1057,7 +1057,7 @@ static struct clk * __init
  st_clk_register_quadfs_fsynth(
          return clk;
   }
  
  -static struct of_device_id quadfs_of_match[] = {
  +static const struct of_device_id quadfs_of_match[] = {
          {
                  .compatible = st,stih416-quadfs216,
                  .data = st_fs216c65_416
  diff --git a/drivers/clk/st/clkgen-mux.c b/drivers/clk/st/clkgen-mux.c
  index 9a15ec3..fdcff10 100644
  --- a/drivers/clk/st/clkgen-mux.c
  +++ b/drivers/clk/st/clkgen-mux.c
  @@ -341,7 +341,7 @@ static struct clkgena_divmux_data st_divmux_c32odf3 = {
          .fb_start_bit_idx = 24,
   };
  
  -static struct of_device_id clkgena_divmux_of_match[] = {
  +static const struct of_device_id clkgena_divmux_of_match[] = {
          {
                  .compatible = st,clkgena-divmux-c65-hs,
                  .data = st_divmux_c65hs,
  @@ -479,7 +479,7 @@ static struct clkgena_prediv_data prediv_c32_data = {
          .table = prediv_table16,
   };
  
  -static struct of_device_id clkgena_prediv_of_match[] = {
  +static const struct of_device_id clkgena_prediv_of_match[] = {
          { .compatible = st,clkgena-prediv-c65, .data = prediv_c65_data },
          { .compatible = st,clkgena-prediv-c32, .data = prediv_c32_data },
          {}
  @@ -586,7 +586,7 @@ static struct clkgen_mux_data stih407_a9_mux_data = {
          .width = 2,
   };
  
  -static struct of_device_id mux_of_match[] = {
  +static const struct of_device_id mux_of_match[] = {
          {
                  .compatible = st,stih416-clkgenc-vcc-hd,
                  .data = clkgen_mux_c_vcc_hd_416,
  @@ -693,7 +693,7 @@ static struct clkgen_vcc_data st_clkgenf_vcc_416 = {
          .lock = clkgenf_lock,
   };
  
  -static struct of_device_id vcc_of_match[] = {
  +static const struct of_device_id vcc_of_match[] = {
          { .compatible = st,stih416-clkgenc, .data = st_clkgenc_vcc_416 },
          { .compatible = st,stih416-clkgenf, .data = st_clkgenf_vcc_416 },
          {}
  diff --git a/drivers/clk/st/clkgen-pll.c b/drivers/clk/st/clkgen-pll.c
  index 29769d7..d204ba8 100644
  --- a/drivers/clk/st/clkgen-pll.c
  +++ b/drivers/clk/st/clkgen-pll.c
  @@ -593,7 +593,7 @@ static struct clk * __init clkgen_odf_register(const
  char *parent_name,
          return clk;
   }
  
  -static struct of_device_id c32_pll_of_match[] = {
  +static const struct of_device_id c32_pll_of_match[] = {
          {
                  .compatible = st,plls-c32-a1x-0,
                  .data = st_pll3200c32_a1x_0,
  @@ -708,7 +708,7 @@ err:
   }
   CLK_OF_DECLARE(clkgen_c32_pll, st,clkgen-plls-c32, clkgen_c32_pll_setup);
  
  -static struct of_device_id c32_gpu_pll_of_match[] = {
  +static const struct of_device_id c32_gpu_pll_of_match[] = {
          {
                  .compatible = st,stih415-gpu-pll-c32,
                  .data = st_pll1200c32_gpu_415,
  diff --git a/drivers/clk/ti/clk-dra7-atl.c b/drivers/clk/ti/clk-dra7-atl.c
  index 59bb4b3..d86bc46 100644
  --- a/drivers/clk/ti/clk-dra7-atl.c
  +++ b/drivers/clk/ti/clk-dra7-atl.c
  @@ -294,7 +294,7 @@ static int of_dra7_atl_clk_remove(struct platform_device
  *pdev)
          return 0;
   }
  
  -static struct of_device_id of_dra7_atl_clk_match_tbl[] = {
  +static const struct of_device_id of_dra7_atl_clk_match_tbl[] = {
          { .compatible = ti,dra7-atl, },
          {},
  

Re: [PATCH 0/8] gpio: omap: cleanup: get rid of system GPIO - GPIO offset converseations

2015-03-22 Thread Aaro Koskinen
Hi,

On Fri, Mar 20, 2015 at 05:11:23PM +0200, grygorii.stras...@linaro.org wrote:
 On 03/20/2015 01:00 AM, Tony Lindgren wrote:
  * grygorii.stras...@linaro.org grygorii.stras...@linaro.org [150319 
  10:26]:
  From: Grygorii Strashko grygorii.stras...@linaro.org
  Now in TI OMAP GPIO driver there are a lot of places where
  System GPIO number calculated and then converted to GPIO offset.
  What is worse is that in many place such conversation performed twice
  or even three times. But actually, we don't need to do that at all, because
  - gpiolib always passes GPIO offset to GPIO controller
  - OMAP GPIO driver converted to use IRQ domain, so
 struct irq_data-hwirq contains GPIO offset
 
  Hence, it is safe to convert all GPIO OMAP functions to use GPIO
  offset instead of system GPIO numbers. Also, this allows to remove
  unneeded conversations routines
#define GPIO_INDEX(bank, gpio)
#define GPIO_BIT(bank, gpio)
int omap_irq_to_gpio()
  
  Right on! This is excellent news. I've tested this set on top of -rc4
  plus the patch mentioned below, and I'm not seeing regressions on
  the platforms I tested with. Wake up to smsc911x ping with off-idle
  still works on omap3.
  
  I only briefly tested on omap1 (osk5912), so I'like to wait for
  Aaro's ack before this gets merged.
  
  I found one build error, other than that, for the whole series
  please feel free to add:
  
  Tested-by: Tony Lindgren t...@atomide.com
 
 Thanks Tony. 
 Yep. I'll wait for news from Aaro then will re-send if ok.

Works fine on 770 and E3.

Tested-by: Aaro Koskinen aaro.koski...@iki.fi

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


Re: [Gta04-owner] [PATCH 3/4] usb: phy: twl4030: add support for reading restore on ID pin.

2015-03-22 Thread NeilBrown
On Wed, 4 Mar 2015 07:54:41 +0100 Dr. H. Nikolaus Schaller
h...@goldelico.com wrote:

 
 Am 04.03.2015 um 07:35 schrieb NeilBrown ne...@suse.de:
 
  On Mon, 2 Mar 2015 22:04:31 +0100 Pavel Machek pa...@ucw.cz wrote:
  
  Hi!
  
  The twl4030 phy can measure, with low precision, the
  resistance-to-ground of the ID pin.
  
  Add a function to read the value, and export the result
  via sysfs.
  
  If the read fails, which it does sometimes, try again in 50msec.
  
  Signed-off-by: NeilBrown ne...@suse.de
  ---
  drivers/phy/phy-twl4030-usb.c |   63 
  +
  1 file changed, 63 insertions(+)
  
  diff --git a/drivers/phy/phy-twl4030-usb.c b/drivers/phy/phy-twl4030-usb.c
  index 023fe150c7a1..759950898df9 100644
  --- a/drivers/phy/phy-twl4030-usb.c
  +++ b/drivers/phy/phy-twl4030-usb.c
  @@ -374,6 +374,56 @@ static void twl4030_i2c_access(struct twl4030_usb 
  *twl, int on)
}
  }
  
  +enum twl4030_id_status {
  + TWL4030_GROUND,
  + TWL4030_102K,
  + TWL4030_200K,
  + TWL4030_440K,
  + TWL4030_FLOATING,
  + TWL4030_ID_UNKNOWN,
  +};
  +static char *twl4030_id_names[] = {
  + ground,
  + 102k,
  + 200k,
  + 440k,
  
  New /sys files should be documented somewhere...?
  
  Preferably with the code...
  
  
  Does it make sense to change 440k - 440KOhm?
  
  Interesting question.  I prefer to avoid including units in files - bare
  numbers is better.  But there is no number to match floating unless I 
  spell
  it out as infinity, and wouldn't be helpful.
  
  Certainly K would be preferred over k“,
 
 The international standard for kilo = 1000 is a lower case k.
 While it is (non-standard) to use K for 1024:
 
 http://en.wikipedia.org/wiki/Kilobyte
 
 So I would keep the string constants lower case to avoid this potential 
 confusion.

Yes, I got that backwards, didn't I.

I think I'll leave it as lower-case.
I won't include the word ohm - it is very uncommon to have units explicit
in sysfs attribute values.

Thanks,
NeilBrown


pgpTfJsV9eFf0.pgp
Description: OpenPGP digital signature


[PATCH 03/14] twl4030_charger: use runtime_pm to keep usb phy active while charging.

2015-03-22 Thread NeilBrown
From: NeilBrown ne...@suse.de

The twl4030 usb phy needs to be active while we are using
the USB VBUS as a current source for charging.
In particular, the usb3v1 regulator must be enabled and the
PHY_PWR_PHYPWD bit must be set to keep the phy powered.

commit ab37813f4093a5f59cb8e083cde277289dc72ed3
twl4030_charger: Allow charger to control the regulator that feeds it

Gave the charger control over the regulator, but didn't resolve
the PHY_PWR_PHYPWD issue.

Now that both of these are controlled by runtime_pm in
phy-twl4030-usb, we can simply take a runtime_pm reference to the USB
phy whenever the charger wants to use it as a current source.

So this patch reverts the above commit, and adds the necessary
runtime_pm calls.

Acked-by: Lee Jones lee.jo...@linaro.org
Signed-off-by: NeilBrown ne...@suse.de
---
 drivers/mfd/twl-core.c  |9 -
 drivers/power/twl4030_charger.c |   18 +-
 2 files changed, 9 insertions(+), 18 deletions(-)

diff --git a/drivers/mfd/twl-core.c b/drivers/mfd/twl-core.c
index 489674a2497e..831696ee2472 100644
--- a/drivers/mfd/twl-core.c
+++ b/drivers/mfd/twl-core.c
@@ -788,9 +788,8 @@ add_children(struct twl4030_platform_data *pdata, unsigned 
irq_base,
static struct regulator_consumer_supply usb1v8 = {
.supply =   usb1v8,
};
-   static struct regulator_consumer_supply usb3v1[] = {
-   { .supply = usb3v1 },
-   { .supply = bci3v1 },
+   static struct regulator_consumer_supply usb3v1 = {
+   .supply =   usb3v1,
};
 
/* First add the regulators so that they can be used by transceiver */
@@ -818,7 +817,7 @@ add_children(struct twl4030_platform_data *pdata, unsigned 
irq_base,
return PTR_ERR(child);
 
child = add_regulator_linked(TWL4030_REG_VUSB3V1,
- usb_fixed, usb3v1, 2,
+ usb_fixed, usb3v1, 1,
  features);
if (IS_ERR(child))
return PTR_ERR(child);
@@ -838,7 +837,7 @@ add_children(struct twl4030_platform_data *pdata, unsigned 
irq_base,
if (IS_ENABLED(CONFIG_REGULATOR_TWL4030)  child) {
usb1v5.dev_name = dev_name(child);
usb1v8.dev_name = dev_name(child);
-   usb3v1[0].dev_name = dev_name(child);
+   usb3v1.dev_name = dev_name(child);
}
}
 
diff --git a/drivers/power/twl4030_charger.c b/drivers/power/twl4030_charger.c
index 7b6c4000cd30..94c7a4d9400a 100644
--- a/drivers/power/twl4030_charger.c
+++ b/drivers/power/twl4030_charger.c
@@ -22,7 +22,6 @@
 #include linux/power_supply.h
 #include linux/notifier.h
 #include linux/usb/otg.h
-#include linux/regulator/machine.h
 
 #define TWL4030_BCIMSTATEC 0x02
 #define TWL4030_BCIICHG0x08
@@ -94,7 +93,6 @@ struct twl4030_bci {
struct work_struct  work;
int irq_chg;
int irq_bci;
-   struct regulator*usb_reg;
int usb_enabled;
 
unsigned long   event;
@@ -208,7 +206,7 @@ static int twl4030_charger_enable_usb(struct twl4030_bci 
*bci, bool enable)
 {
int ret;
 
-   if (enable) {
+   if (enable  !IS_ERR_OR_NULL(bci-transceiver)) {
/* Check for USB charger connected */
if (!twl4030_bci_have_vbus(bci))
return -ENODEV;
@@ -222,14 +220,9 @@ static int twl4030_charger_enable_usb(struct twl4030_bci 
*bci, bool enable)
return -EACCES;
}
 
-   /* Need to keep regulator on */
+   /* Need to keep phy powered */
if (!bci-usb_enabled) {
-   ret = regulator_enable(bci-usb_reg);
-   if (ret) {
-   dev_err(bci-dev,
-   Failed to enable regulator\n);
-   return ret;
-   }
+   pm_runtime_get_sync(bci-transceiver-dev);
bci-usb_enabled = 1;
}
 
@@ -244,7 +237,8 @@ static int twl4030_charger_enable_usb(struct twl4030_bci 
*bci, bool enable)
} else {
ret = twl4030_clear_set_boot_bci(TWL4030_BCIAUTOUSB, 0);
if (bci-usb_enabled) {
-   regulator_disable(bci-usb_reg);
+   pm_runtime_mark_last_busy(bci-transceiver-dev);
+   pm_runtime_put_autosuspend(bci-transceiver-dev);
bci-usb_enabled = 0;
}
}
@@ -602,8 +596,6 @@ static int 

[PATCH 02/14] twl4030_charger: use devres for power_supply_register and kzalloc.

2015-03-22 Thread NeilBrown
From: NeilBrown ne...@suse.de

Final allocations/registrations are now managed by devres.

Signed-off-by: NeilBrown ne...@suse.de
---
 drivers/power/twl4030_charger.c |   32 +---
 1 file changed, 9 insertions(+), 23 deletions(-)

diff --git a/drivers/power/twl4030_charger.c b/drivers/power/twl4030_charger.c
index 58996d252ecf..7b6c4000cd30 100644
--- a/drivers/power/twl4030_charger.c
+++ b/drivers/power/twl4030_charger.c
@@ -565,7 +565,7 @@ static int __init twl4030_bci_probe(struct platform_device 
*pdev)
int ret;
u32 reg;
 
-   bci = kzalloc(sizeof(*bci), GFP_KERNEL);
+   bci = devm_kzalloc(pdev-dev, sizeof(*bci), GFP_KERNEL);
if (bci == NULL)
return -ENOMEM;
 
@@ -580,7 +580,7 @@ static int __init twl4030_bci_probe(struct platform_device 
*pdev)
ret = twl4030_is_battery_present(bci);
if  (ret) {
dev_crit(pdev-dev, Battery was not detected:%d\n, ret);
-   goto fail_no_battery;
+   return ret;
}
 
platform_set_drvdata(pdev, bci);
@@ -590,10 +590,10 @@ static int __init twl4030_bci_probe(struct 
platform_device *pdev)
bci-ac.num_properties = ARRAY_SIZE(twl4030_charger_props);
bci-ac.get_property = twl4030_bci_get_property;
 
-   ret = power_supply_register(pdev-dev, bci-ac);
+   ret = devm_power_supply_register(pdev-dev, bci-ac);
if (ret) {
dev_err(pdev-dev, failed to register ac: %d\n, ret);
-   goto fail_register_ac;
+   return ret;
}
 
bci-usb.name = twl4030_usb;
@@ -604,10 +604,10 @@ static int __init twl4030_bci_probe(struct 
platform_device *pdev)
 
bci-usb_reg = regulator_get(bci-dev, bci3v1);
 
-   ret = power_supply_register(pdev-dev, bci-usb);
+   ret = devm_power_supply_register(pdev-dev, bci-usb);
if (ret) {
dev_err(pdev-dev, failed to register usb: %d\n, ret);
-   goto fail_register_usb;
+   return ret;
}
 
ret = devm_request_threaded_irq(pdev-dev, bci-irq_chg, NULL,
@@ -616,7 +616,7 @@ static int __init twl4030_bci_probe(struct platform_device 
*pdev)
if (ret  0) {
dev_err(pdev-dev, could not request irq %d, status %d\n,
bci-irq_chg, ret);
-   goto fail;
+   return ret;
}
 
ret = devm_request_threaded_irq(pdev-dev, bci-irq_bci, NULL,
@@ -624,7 +624,7 @@ static int __init twl4030_bci_probe(struct platform_device 
*pdev)
if (ret  0) {
dev_err(pdev-dev, could not request irq %d, status %d\n,
bci-irq_bci, ret);
-   goto fail;
+   return ret;
}
 
INIT_WORK(bci-work, twl4030_bci_usb_work);
@@ -647,7 +647,7 @@ static int __init twl4030_bci_probe(struct platform_device 
*pdev)
   TWL4030_INTERRUPTS_BCIIMR1A);
if (ret  0) {
dev_err(pdev-dev, failed to unmask interrupts: %d\n, ret);
-   goto fail;
+   return ret;
}
 
reg = ~(u32)(TWL4030_VBATOV | TWL4030_VBUSOV | TWL4030_ACCHGOV);
@@ -665,16 +665,6 @@ static int __init twl4030_bci_probe(struct platform_device 
*pdev)
twl4030_charger_enable_backup(0, 0);
 
return 0;
-
-fail:
-   power_supply_unregister(bci-usb);
-fail_register_usb:
-   power_supply_unregister(bci-ac);
-fail_register_ac:
-fail_no_battery:
-   kfree(bci);
-
-   return ret;
 }
 
 static int __exit twl4030_bci_remove(struct platform_device *pdev)
@@ -691,10 +681,6 @@ static int __exit twl4030_bci_remove(struct 
platform_device *pdev)
twl_i2c_write_u8(TWL4030_MODULE_INTERRUPTS, 0xff,
 TWL4030_INTERRUPTS_BCIIMR2A);
 
-   power_supply_unregister(bci-usb);
-   power_supply_unregister(bci-ac);
-   kfree(bci);
-
return 0;
 }
 


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


[PATCH 06/14] twl4030_charger: allow fine control of charger current.

2015-03-22 Thread NeilBrown
From: NeilBrown ne...@suse.de

The twl4030 allows control of the incoming current.
Part of this control is a 'CGAIN' setting which doubles
the range for half the precision.  This control affects
several different current setting, so all need to be updated
at once when CGAIN is changed.

With this patch, all of these current setting are managed
by the driver, but most are left at their default settings.

The current drawn is set to 500mA if the allow_usb module parameter is
set, and to 100mA otherwise.
More fine control will appear in later patches.

Acked-by: Pavel Machek pa...@ucw.cz
Signed-off-by: NeilBrown ne...@suse.de
---
 drivers/power/twl4030_charger.c |  168 +--
 1 file changed, 160 insertions(+), 8 deletions(-)

diff --git a/drivers/power/twl4030_charger.c b/drivers/power/twl4030_charger.c
index c9a7efbb9141..02d677ef63e2 100644
--- a/drivers/power/twl4030_charger.c
+++ b/drivers/power/twl4030_charger.c
@@ -31,6 +31,11 @@
 #define TWL4030_BCIMFSTS4  0x10
 #define TWL4030_BCICTL10x23
 #define TWL4030_BB_CFG 0x12
+#define TWL4030_BCIIREF1   0x27
+#define TWL4030_BCIIREF2   0x28
+#define TWL4030_BCIMFKEY   0x11
+#define TWL4030_BCIMFTH8   0x1d
+#define TWL4030_BCIMFTH9   0x1e
 
 #define TWL4030_BCIMFSTS1  0x01
 
@@ -95,6 +100,12 @@ struct twl4030_bci {
int irq_bci;
int usb_enabled;
 
+   /*
+* ichg values in uA. If any are 'large', we set CGAIN to
+* '1' which doubles the range for half the precision.
+*/
+   unsigned intichg_eoc, ichg_lo, ichg_hi, cur;
+
unsigned long   event;
 };
 
@@ -211,6 +222,146 @@ static int ua2regval(int ua, bool cgain)
return ret;
 }
 
+static int twl4030_charger_update_current(struct twl4030_bci *bci)
+{
+   int status;
+   unsigned reg, cur_reg;
+   u8 bcictl1, oldreg, fullreg;
+   bool cgain = false;
+   u8 boot_bci;
+
+   /* First, check thresholds and see if cgain is needed */
+   if (bci-ichg_eoc = 20)
+   cgain = true;
+   if (bci-ichg_lo = 40)
+   cgain = true;
+   if (bci-ichg_hi = 82)
+   cgain = true;
+   if (bci-cur  852000)
+   cgain = true;
+
+   status = twl4030_bci_read(TWL4030_BCICTL1, bcictl1);
+   if (status  0)
+   return status;
+   if (twl_i2c_read_u8(TWL_MODULE_PM_MASTER, boot_bci,
+   TWL4030_PM_MASTER_BOOT_BCI)  0)
+   boot_bci = 0;
+   boot_bci = 7;
+
+   if ((!!cgain) != !!(bcictl1  TWL4030_CGAIN))
+   /* Need to turn for charging while we change the
+* CGAIN bit.  Leave it off while everything is
+* updated.
+*/
+   twl4030_clear_set_boot_bci(boot_bci, 0);
+
+   /*
+* For ichg_eoc, the hardware only supports reg values matching
+* 100000, and requires the  be stored in the high nibble
+* of TWL4030_BCIMFTH8
+*/
+   reg = ua2regval(bci-ichg_eoc, cgain);
+   if (reg  0x278)
+   reg = 0x278;
+   if (reg  0x200)
+   reg = 0x200;
+   reg = (reg  3)  0xf;
+   fullreg = reg  4;
+
+   /*
+* For ichg_lo, reg value must match 10.
+*  is stored in low nibble of TWL4030_BCIMFTH8
+*/
+   reg = ua2regval(bci-ichg_lo, cgain);
+   if (reg  0x2F0)
+   reg = 0x2F0;
+   if (reg  0x200)
+   reg = 0x200;
+   reg = (reg  4)  0xf;
+   fullreg |= reg;
+
+   /* ichg_eoc and ichg_lo live in same register */
+   status = twl4030_bci_read(TWL4030_BCIMFTH8, oldreg);
+   if (status  0)
+   return status;
+   if (oldreg != fullreg) {
+   status = twl_i2c_write_u8(TWL_MODULE_MAIN_CHARGE, 0xF4,
+ TWL4030_BCIMFKEY);
+   if (status  0)
+   return status;
+   twl_i2c_write_u8(TWL_MODULE_MAIN_CHARGE,
+fullreg, TWL4030_BCIMFTH8);
+   }
+
+   /* ichg_hi threshold must be 101100 (I think) */
+   reg = ua2regval(bci-ichg_hi, cgain);
+   if (reg  0x3E0)
+   reg = 0x3E0;
+   if (reg  0x200)
+   reg = 0x200;
+   fullreg = (reg  5)  0xF;
+   fullreg = 4;
+   status = twl4030_bci_read(TWL4030_BCIMFTH9, oldreg);
+   if (status  0)
+   return status;
+   if ((oldreg  0xF0) != fullreg) {
+   fullreg |= (oldreg  0x0F);
+   status = twl_i2c_write_u8(TWL_MODULE_MAIN_CHARGE, 0xE7,
+ TWL4030_BCIMFKEY);
+   if (status  0)
+   return status;
+   twl_i2c_write_u8(TWL_MODULE_MAIN_CHARGE,
+fullreg, TWL4030_BCIMFTH9);
+ 

[PATCH 05/14] twl4030_charger: split uA calculation into a function.

2015-03-22 Thread NeilBrown
From: NeilBrown ne...@suse.de

We will need this calculation in other places, so
create functions to map between register value and uA value.

Acked-by: Pavel Machek pa...@ucw.cz
Signed-off-by: NeilBrown ne...@suse.de
---
 drivers/power/twl4030_charger.c |   48 ---
 1 file changed, 35 insertions(+), 13 deletions(-)

diff --git a/drivers/power/twl4030_charger.c b/drivers/power/twl4030_charger.c
index 0e62a5ae56a3..c9a7efbb9141 100644
--- a/drivers/power/twl4030_charger.c
+++ b/drivers/power/twl4030_charger.c
@@ -178,6 +178,40 @@ static int twl4030_is_battery_present(struct twl4030_bci 
*bci)
 }
 
 /*
+ * TI provided formulas:
+ * CGAIN == 0: ICHG = (BCIICHG * 1.7) / (2^10 - 1) - 0.85
+ * CGAIN == 1: ICHG = (BCIICHG * 3.4) / (2^10 - 1) - 1.7
+ * Here we use integer approximation of:
+ * CGAIN == 0: val * 1.6618 - 0.85 * 1000
+ * CGAIN == 1: (val * 1.6618 - 0.85 * 1000) * 2
+ */
+/*
+ * convert twl register value for currents into uA
+ */
+static int regval2ua(int regval, bool cgain)
+{
+   if (cgain)
+   return (regval * 16618 - 8500 * 1000) / 5;
+   else
+   return (regval * 16618 - 8500 * 1000) / 10;
+}
+
+/*
+ * convert uA currents into twl register value
+ */
+static int ua2regval(int ua, bool cgain)
+{
+   int ret;
+   if (cgain)
+   ua /= 2;
+   ret = (ua * 10 + 8500 * 1000) / 16618;
+   /* rounding problems */
+   if (ret  512)
+   ret = 512;
+   return ret;
+}
+
+/*
  * Enable/Disable USB Charge functionality.
  */
 static int twl4030_charger_enable_usb(struct twl4030_bci *bci, bool enable)
@@ -366,14 +400,6 @@ static int twl4030_bci_usb_ncb(struct notifier_block *nb, 
unsigned long val,
return NOTIFY_OK;
 }
 
-/*
- * TI provided formulas:
- * CGAIN == 0: ICHG = (BCIICHG * 1.7) / (2^10 - 1) - 0.85
- * CGAIN == 1: ICHG = (BCIICHG * 3.4) / (2^10 - 1) - 1.7
- * Here we use integer approximation of:
- * CGAIN == 0: val * 1.6618 - 0.85
- * CGAIN == 1: (val * 1.6618 - 0.85) * 2
- */
 static int twl4030_charger_get_current(void)
 {
int curr;
@@ -388,11 +414,7 @@ static int twl4030_charger_get_current(void)
if (ret)
return ret;
 
-   ret = (curr * 16618 - 850 * 1) / 10;
-   if (bcictl1  TWL4030_CGAIN)
-   ret *= 2;
-
-   return ret;
+   return regval2ua(curr, bcictl1  TWL4030_CGAIN);
 }
 
 /*


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


[PATCH 04/14] twl4030_charger: trust phy to determine when USB power is available.

2015-03-22 Thread NeilBrown
From: NeilBrown ne...@suse.de

The usb phy driver already determines when VBUS is available,
so repeating the test in the charger driver is pointless duplication.

On probe, process the last event from the phy, and from then on,
do whatever the phy tells us without double-checking.

Signed-off-by: NeilBrown ne...@suse.de
---
 drivers/power/twl4030_charger.c |   33 ++---
 1 file changed, 6 insertions(+), 27 deletions(-)

diff --git a/drivers/power/twl4030_charger.c b/drivers/power/twl4030_charger.c
index 94c7a4d9400a..0e62a5ae56a3 100644
--- a/drivers/power/twl4030_charger.c
+++ b/drivers/power/twl4030_charger.c
@@ -178,28 +178,6 @@ static int twl4030_is_battery_present(struct twl4030_bci 
*bci)
 }
 
 /*
- * Check if VBUS power is present
- */
-static int twl4030_bci_have_vbus(struct twl4030_bci *bci)
-{
-   int ret;
-   u8 hwsts;
-
-   ret = twl_i2c_read_u8(TWL_MODULE_PM_MASTER, hwsts,
- TWL4030_PM_MASTER_STS_HW_CONDITIONS);
-   if (ret  0)
-   return 0;
-
-   dev_dbg(bci-dev, check_vbus: HW_CONDITIONS %02x\n, hwsts);
-
-   /* in case we also have STS_USB_ID, VBUS is driven by TWL itself */
-   if ((hwsts  TWL4030_STS_VBUS)  !(hwsts  TWL4030_STS_USB_ID))
-   return 1;
-
-   return 0;
-}
-
-/*
  * Enable/Disable USB Charge functionality.
  */
 static int twl4030_charger_enable_usb(struct twl4030_bci *bci, bool enable)
@@ -207,10 +185,6 @@ static int twl4030_charger_enable_usb(struct twl4030_bci 
*bci, bool enable)
int ret;
 
if (enable  !IS_ERR_OR_NULL(bci-transceiver)) {
-   /* Check for USB charger connected */
-   if (!twl4030_bci_have_vbus(bci))
-   return -ENODEV;
-
/*
 * Until we can find out what current the device can provide,
 * require a module param to enable USB charging.
@@ -649,7 +623,12 @@ static int __init twl4030_bci_probe(struct platform_device 
*pdev)
dev_warn(pdev-dev, failed to unmask interrupts: %d\n, ret);
 
twl4030_charger_enable_ac(true);
-   twl4030_charger_enable_usb(bci, true);
+   if (!IS_ERR_OR_NULL(bci-transceiver))
+   twl4030_bci_usb_ncb(bci-usb_nb,
+   bci-transceiver-last_event,
+   NULL);
+   else
+   twl4030_charger_enable_usb(bci, false);
if (pdata)
twl4030_charger_enable_backup(pdata-bb_uvolt,
  pdata-bb_uamp);


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


[PATCH 11/14] twl4030_charger: add software controlled linear charging mode.

2015-03-22 Thread NeilBrown
From: NeilBrown ne...@suse.de

Add a 'continuous' option for usb charging which enables
the linear charging mode of the twl4030.

Linear charging does a good job with not-so-reliable power sources.
Auto mode does not work well as it switches off when voltage drops
momentarily.  Care must be taken not to over-charge.

It was used with a bike hub dynamo since a year or so. In that case
there are automatically charging stops when the cyclist needs a break.

Orignal-by: Andreas Kemnade andr...@kemnade.info
Signed-off-by: NeilBrown ne...@suse.de
---
 .../ABI/testing/sysfs-class-power-twl4030  |9 +++
 drivers/power/twl4030_charger.c|   55 ++--
 2 files changed, 59 insertions(+), 5 deletions(-)

diff --git a/Documentation/ABI/testing/sysfs-class-power-twl4030 
b/Documentation/ABI/testing/sysfs-class-power-twl4030
index 390db7a55231..c27e8ca8c9db 100644
--- a/Documentation/ABI/testing/sysfs-class-power-twl4030
+++ b/Documentation/ABI/testing/sysfs-class-power-twl4030
@@ -24,3 +24,12 @@ Description:
auto - draw power as appropriate for detected
 power source and battery status.
off  - do not draw any power.
+   continuous
+  - activate mode described as linear in
+TWL data sheets.  This uses whatever
+current is available and doesn't switch off
+when voltage drops.
+
+This is useful for unstable power sources
+such as bicycle dynamo, but care should
+be taken that battery is not over-charged.
diff --git a/drivers/power/twl4030_charger.c b/drivers/power/twl4030_charger.c
index 802cdd6d3e00..2c8d85102def 100644
--- a/drivers/power/twl4030_charger.c
+++ b/drivers/power/twl4030_charger.c
@@ -24,6 +24,8 @@
 #include linux/usb/otg.h
 #include linux/i2c/twl4030-madc.h
 
+#define TWL4030_BCIMDEN0x00
+#define TWL4030_BCIMDKEY   0x01
 #define TWL4030_BCIMSTATEC 0x02
 #define TWL4030_BCIICHG0x08
 #define TWL4030_BCIVAC 0x0a
@@ -35,13 +37,16 @@
 #define TWL4030_BCIIREF1   0x27
 #define TWL4030_BCIIREF2   0x28
 #define TWL4030_BCIMFKEY   0x11
+#define TWL4030_BCIMFEN3   0x14
 #define TWL4030_BCIMFTH8   0x1d
 #define TWL4030_BCIMFTH9   0x1e
+#define TWL4030_BCIWDKEY   0x21
 
 #define TWL4030_BCIMFSTS1  0x01
 
 #define TWL4030_BCIAUTOWEN BIT(5)
 #define TWL4030_CONFIG_DONEBIT(4)
+#define TWL4030_CVENAC BIT(2)
 #define TWL4030_BCIAUTOUSB BIT(1)
 #define TWL4030_BCIAUTOAC  BIT(0)
 #define TWL4030_CGAIN  BIT(5)
@@ -112,12 +117,13 @@ struct twl4030_bci {
int usb_mode; /* charging mode requested */
 #defineCHARGE_OFF  0
 #defineCHARGE_AUTO 1
+#defineCHARGE_LINEAR   2
 
unsigned long   event;
 };
 
 /* strings for 'usb_mode' values */
-static char *modes[] = { off, auto };
+static char *modes[] = { off, auto, continuous };
 
 /*
  * clear and set bits on an given register on a given module
@@ -404,16 +410,42 @@ static int twl4030_charger_enable_usb(struct twl4030_bci 
*bci, bool enable)
bci-usb_enabled = 1;
}
 
-   /* forcing the field BCIAUTOUSB (BOOT_BCI[1]) to 1 */
-   ret = twl4030_clear_set_boot_bci(0, TWL4030_BCIAUTOUSB);
-   if (ret  0)
-   return ret;
+   if (bci-usb_mode == CHARGE_AUTO)
+   /* forcing the field BCIAUTOUSB (BOOT_BCI[1]) to 1 */
+   ret = twl4030_clear_set_boot_bci(0, TWL4030_BCIAUTOUSB);
 
/* forcing USBFASTMCHG(BCIMFSTS4[2]) to 1 */
ret = twl4030_clear_set(TWL_MODULE_MAIN_CHARGE, 0,
TWL4030_USBFASTMCHG, TWL4030_BCIMFSTS4);
+   if (bci-usb_mode == CHARGE_LINEAR) {
+   
twl4030_clear_set_boot_bci(TWL4030_BCIAUTOAC|TWL4030_CVENAC, 0);
+   /* Watch dog key: WOVF acknowledge */
+   ret = twl_i2c_write_u8(TWL_MODULE_MAIN_CHARGE, 0x33,
+  TWL4030_BCIWDKEY);
+   /* 0x24 + EKEY6: off mode */
+   ret = twl_i2c_write_u8(TWL_MODULE_MAIN_CHARGE, 0x2a,
+  TWL4030_BCIMDKEY);
+   /* EKEY2: Linear charge: USB path */
+   ret = twl_i2c_write_u8(TWL_MODULE_MAIN_CHARGE, 0x26,
+  TWL4030_BCIMDKEY);
+   /* WDKEY5: stop watchdog count */
+   ret = twl_i2c_write_u8(TWL_MODULE_MAIN_CHARGE, 0xf3,
+  TWL4030_BCIWDKEY);
+   /* enable MFEN3 access */
+   ret = 

[PATCH 14/14] twl4030_charger: assume a 'charger' can supply maximum current.

2015-03-22 Thread NeilBrown
From: NeilBrown ne...@suse.de

If it cannot, we will stop pulling more current when voltage drops.

Signed-off-by: NeilBrown ne...@suse.de
---
 drivers/power/twl4030_charger.c |4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/power/twl4030_charger.c b/drivers/power/twl4030_charger.c
index d0199495dddc..6f0dc971d84d 100644
--- a/drivers/power/twl4030_charger.c
+++ b/drivers/power/twl4030_charger.c
@@ -694,8 +694,10 @@ static void twl4030_bci_usb_work(struct work_struct *data)
struct twl4030_bci *bci = container_of(data, struct twl4030_bci, work);
 
switch (bci-event) {
-   case USB_EVENT_VBUS:
case USB_EVENT_CHARGER:
+   bci-usb_cur = USB_MAX_CURRENT;
+   /* FALL THROUGH */
+   case USB_EVENT_VBUS:
case USB_EVENT_ENUMERATED:
twl4030_charger_enable_usb(bci, true);
break;


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


[PATCH 3/3] clk: ti: Implement FAPLL set_rate for the PLL

2015-03-22 Thread Tony Lindgren
Since we have a fractional divider for the synthesizer, just implement
a simple multiply logic for the PLL.

It seems the PLL divider needs to have also the multiplier set for the PLL
to lock. At least I have not yet figured out if divided rates are doable.

So let's just ignore the PLL divider for now as the synthesizer has both
integer and fractional dividers so we don't even need to use the PLL
divider for the rates we know work with PLL locking.

Cc: Brian Hutchinson b.hutch...@gmail.com
Cc: Matthijs van Duin matthijsvand...@gmail.com
Cc: Tero Kristo t-kri...@ti.com
Signed-off-by: Tony Lindgren t...@atomide.com
---
 drivers/clk/ti/fapll.c | 125 +
 1 file changed, 125 insertions(+)

diff --git a/drivers/clk/ti/fapll.c b/drivers/clk/ti/fapll.c
index 4064f7b..b6f5187 100644
--- a/drivers/clk/ti/fapll.c
+++ b/drivers/clk/ti/fapll.c
@@ -18,11 +18,20 @@
 #include linux/clk/ti.h
 
 /* FAPLL Control Register PLL_CTRL */
+#define FAPLL_MAIN_MULT_N_SHIFT16
+#define FAPLL_MAIN_DIV_P_SHIFT 8
 #define FAPLL_MAIN_LOCKBIT(7)
 #define FAPLL_MAIN_PLLEN   BIT(3)
 #define FAPLL_MAIN_BP  BIT(2)
 #define FAPLL_MAIN_LOC_CTL BIT(0)
 
+#define FAPLL_MAIN_MAX_MULT_N  0x
+#define FAPLL_MAIN_MAX_DIV_P   0xff
+#define FAPLL_MAIN_CLEAR_MASK  \
+   ((FAPLL_MAIN_MAX_MULT_N  FAPLL_MAIN_MULT_N_SHIFT) | \
+(FAPLL_MAIN_DIV_P_SHIFT  FAPLL_MAIN_DIV_P_SHIFT) | \
+FAPLL_MAIN_LOC_CTL)
+
 /* FAPLL powerdown register PWD */
 #define FAPLL_PWD_OFFSET   4
 
@@ -82,6 +91,48 @@ static bool ti_fapll_clock_is_bypass(struct fapll_data *fd)
return !!(v  FAPLL_MAIN_BP);
 }
 
+static void ti_fapll_set_bypass(struct fapll_data *fd)
+{
+   u32 v = readl_relaxed(fd-base);
+
+   if (fd-bypass_bit_inverted)
+   v = ~FAPLL_MAIN_BP;
+   else
+   v |= FAPLL_MAIN_BP;
+   writel_relaxed(v, fd-base);
+}
+
+static void ti_fapll_clear_bypass(struct fapll_data *fd)
+{
+   u32 v = readl_relaxed(fd-base);
+
+   if (fd-bypass_bit_inverted)
+   v |= FAPLL_MAIN_BP;
+   else
+   v = ~FAPLL_MAIN_BP;
+   writel_relaxed(v, fd-base);
+}
+
+static int ti_fapll_wait_lock(struct fapll_data *fd)
+{
+   int retries = FAPLL_MAX_RETRIES;
+   u32 v;
+
+   while ((v = readl_relaxed(fd-base))) {
+   if (v  FAPLL_MAIN_LOCK)
+   return 0;
+
+   if (retries-- = 0)
+   break;
+
+   udelay(1);
+   }
+
+   pr_err(%s failed to lock\n, fd-name);
+
+   return -ETIMEDOUT;
+}
+
 static int ti_fapll_enable(struct clk_hw *hw)
 {
struct fapll_data *fd = to_fapll(hw);
@@ -89,6 +140,7 @@ static int ti_fapll_enable(struct clk_hw *hw)
 
v |= FAPLL_MAIN_PLLEN;
writel_relaxed(v, fd-base);
+   ti_fapll_wait_lock(fd);
 
return 0;
 }
@@ -144,12 +196,85 @@ static u8 ti_fapll_get_parent(struct clk_hw *hw)
return 0;
 }
 
+static int ti_fapll_set_div_mult(unsigned long rate,
+unsigned long parent_rate,
+u32 *pre_div_p, u32 *mult_n)
+{
+   /*
+* So far no luck getting decent clock with PLL divider,
+* PLL does not seem to lock and the signal does not look
+* right. It seems the divider can only be used together
+* with the multiplier?
+*/
+   if (rate  parent_rate) {
+   pr_warn(FAPLL main divider rates unsupported\n);
+   return -EINVAL;
+   }
+
+   *mult_n = rate / parent_rate;
+   if (*mult_n  FAPLL_MAIN_MAX_MULT_N)
+   return -EINVAL;
+   *pre_div_p = 1;
+
+   return 0;
+}
+
+static long ti_fapll_round_rate(struct clk_hw *hw, unsigned long rate,
+   unsigned long *parent_rate)
+{
+   u32 pre_div_p, mult_n;
+   int error;
+
+   if (!rate)
+   return -EINVAL;
+
+   error = ti_fapll_set_div_mult(rate, *parent_rate,
+ pre_div_p, mult_n);
+   if (error)
+   return error;
+
+   rate = *parent_rate / pre_div_p;
+   rate *= mult_n;
+
+   return rate;
+}
+
+static int ti_fapll_set_rate(struct clk_hw *hw, unsigned long rate,
+unsigned long parent_rate)
+{
+   struct fapll_data *fd = to_fapll(hw);
+   u32 pre_div_p, mult_n, v;
+   int error;
+
+   if (!rate)
+   return -EINVAL;
+
+   error = ti_fapll_set_div_mult(rate, parent_rate,
+ pre_div_p, mult_n);
+   if (error)
+   return error;
+
+   ti_fapll_set_bypass(fd);
+   v = readl_relaxed(fd-base);
+   v = ~FAPLL_MAIN_CLEAR_MASK;
+   v |= pre_div_p  FAPLL_MAIN_DIV_P_SHIFT;
+   v |= mult_n  FAPLL_MAIN_MULT_N_SHIFT;
+   writel_relaxed(v, fd-base);
+   if (ti_fapll_is_enabled(hw))
+   

[PATCH 2/3] clk: ti: Implement FAPLL set_rate for the synthesizer

2015-03-22 Thread Tony Lindgren
We can pretty much get any rate out of the FAPLL because of the fractional
divider. Let's first try just adjusting the post divider, and if that is
not enough, then reprogram both the fractional divider and the post divider.

Let's also add a define for the fixed SYNTH_PHASE_K instead of using 8.

Cc: Brian Hutchinson b.hutch...@gmail.com
Cc: Matthijs van Duin matthijsvand...@gmail.com
Cc: Tero Kristo t-kri...@ti.com
Signed-off-by: Tony Lindgren t...@atomide.com
---
 drivers/clk/ti/fapll.c | 134 -
 1 file changed, 132 insertions(+), 2 deletions(-)

diff --git a/drivers/clk/ti/fapll.c b/drivers/clk/ti/fapll.c
index 3b5e231..4064f7b 100644
--- a/drivers/clk/ti/fapll.c
+++ b/drivers/clk/ti/fapll.c
@@ -12,6 +12,7 @@
 #include linux/clk-provider.h
 #include linux/delay.h
 #include linux/err.h
+#include linux/math64.h
 #include linux/of.h
 #include linux/of_address.h
 #include linux/clk/ti.h
@@ -47,6 +48,8 @@
 /* Synthesizer frequency register */
 #define SYNTH_LDFREQ   BIT(31)
 
+#define SYNTH_PHASE_K  8
+#define SYNTH_MAX_INT_DIV  0xf
 #define SYNTH_MAX_DIV_M0xff
 
 struct fapll_data {
@@ -204,7 +207,7 @@ static unsigned long ti_fapll_synth_recalc_rate(struct 
clk_hw *hw,
/*
 * Synth frequency integer and fractional divider.
 * Note that the phase output K is 8, so the result needs
-* to be multiplied by 8.
+* to be multiplied by SYNTH_PHASE_K.
 */
if (synth-freq) {
u32 v, synth_int_div, synth_frac_div, synth_div_freq;
@@ -215,7 +218,7 @@ static unsigned long ti_fapll_synth_recalc_rate(struct 
clk_hw *hw,
synth_div_freq = (synth_int_div * 1000) + synth_frac_div;
rate *= 1000;
do_div(rate, synth_div_freq);
-   rate *= 8;
+   rate *= SYNTH_PHASE_K;
}
 
/* Synth post-divider M */
@@ -224,11 +227,138 @@ static unsigned long ti_fapll_synth_recalc_rate(struct 
clk_hw *hw,
return DIV_ROUND_UP_ULL(rate, synth_div_m);
 }
 
+static unsigned long ti_fapll_synth_get_frac_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+   struct fapll_synth *synth = to_synth(hw);
+   unsigned long current_rate, frac_rate;
+   u32 post_div_m;
+
+   current_rate = ti_fapll_synth_recalc_rate(hw, parent_rate);
+   post_div_m = readl_relaxed(synth-div)  SYNTH_MAX_DIV_M;
+   frac_rate = current_rate * post_div_m;
+
+   return frac_rate;
+}
+
+static u32 ti_fapll_synth_set_frac_rate(struct fapll_synth *synth,
+   unsigned long rate,
+   unsigned long parent_rate)
+{
+   u32 post_div_m, synth_int_div, synth_frac_div, v;
+
+   post_div_m = DIV_ROUND_UP_ULL((u64)parent_rate * SYNTH_PHASE_K, rate);
+   post_div_m = post_div_m / SYNTH_MAX_INT_DIV;
+   if (post_div_m  SYNTH_MAX_DIV_M)
+   return -EINVAL;
+   if (!post_div_m)
+   post_div_m = 1;
+
+   for (; post_div_m  SYNTH_MAX_DIV_M; post_div_m++) {
+   synth_int_div = DIV_ROUND_UP_ULL((u64)parent_rate *
+SYNTH_PHASE_K *
+1000,
+rate * post_div_m);
+   synth_frac_div = synth_int_div % 1000;
+   synth_int_div /= 1000;
+
+   if (synth_int_div = SYNTH_MAX_INT_DIV)
+   break;
+   }
+
+   if (synth_int_div  SYNTH_MAX_INT_DIV)
+   return -EINVAL;
+
+   v = readl_relaxed(synth-freq);
+   v = ~0x1fff;
+   v |= (synth_int_div  SYNTH_MAX_INT_DIV)  24;
+   v |= (synth_frac_div  0xff);
+   v |= SYNTH_LDFREQ;
+   writel_relaxed(v, synth-freq);
+
+   return post_div_m;
+}
+
+static long ti_fapll_synth_round_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long *parent_rate)
+{
+   struct fapll_synth *synth = to_synth(hw);
+   struct fapll_data *fd = synth-fd;
+   unsigned long r;
+
+   if (ti_fapll_clock_is_bypass(fd) || !synth-div || !rate)
+   return -EINVAL;
+
+   /* Only post divider m available with no fractional divider? */
+   if (!synth-freq) {
+   unsigned long frac_rate;
+   u32 synth_post_div_m;
+
+   frac_rate = ti_fapll_synth_get_frac_rate(hw, *parent_rate);
+   synth_post_div_m = DIV_ROUND_UP(frac_rate, rate);
+   r = DIV_ROUND_UP(frac_rate, synth_post_div_m);
+   goto out;
+   }
+
+   r = *parent_rate * SYNTH_PHASE_K;
+   if (rate  r)
+   goto out;
+
+   r = DIV_ROUND_UP_ULL(r, SYNTH_MAX_INT_DIV * SYNTH_MAX_DIV_M);
+   if (rate  r)
+   goto out;
+
+   r = rate;
+out:
+  

[PATCH 1/3] clk: ti: Fix FAPLL recalc_rate for rounding errors

2015-03-22 Thread Tony Lindgren
We need to round the calculated value to have it match the requested rate.

While at it, let's fix a typo and use a define for SYNTH_MAX_DIV_M as we
will need it in later patches for set_rate.

And let's remove two unused includes.

Cc: Brian Hutchinson b.hutch...@gmail.com
Cc: Matthijs van Duin matthijsvand...@gmail.com
Cc: Tero Kristo t-kri...@ti.com
Signed-off-by: Tony Lindgren t...@atomide.com
---
 drivers/clk/ti/fapll.c | 11 +--
 1 file changed, 5 insertions(+), 6 deletions(-)

diff --git a/drivers/clk/ti/fapll.c b/drivers/clk/ti/fapll.c
index d216406..3b5e231 100644
--- a/drivers/clk/ti/fapll.c
+++ b/drivers/clk/ti/fapll.c
@@ -11,12 +11,10 @@
 
 #include linux/clk-provider.h
 #include linux/delay.h
-#include linux/slab.h
 #include linux/err.h
 #include linux/of.h
 #include linux/of_address.h
 #include linux/clk/ti.h
-#include asm/div64.h
 
 /* FAPLL Control Register PLL_CTRL */
 #define FAPLL_MAIN_LOCKBIT(7)
@@ -49,6 +47,8 @@
 /* Synthesizer frequency register */
 #define SYNTH_LDFREQ   BIT(31)
 
+#define SYNTH_MAX_DIV_M0xff
+
 struct fapll_data {
struct clk_hw hw;
void __iomem *base;
@@ -218,11 +218,10 @@ static unsigned long ti_fapll_synth_recalc_rate(struct 
clk_hw *hw,
rate *= 8;
}
 
-   /* Synth ost-divider M */
-   synth_div_m = readl_relaxed(synth-div)  0xff;
-   do_div(rate, synth_div_m);
+   /* Synth post-divider M */
+   synth_div_m = readl_relaxed(synth-div)  SYNTH_MAX_DIV_M;
 
-   return rate;
+   return DIV_ROUND_UP_ULL(rate, synth_div_m);
 }
 
 static struct clk_ops ti_fapll_synt_ops = {
-- 
2.1.4

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


[PATCH 0/3] Implement set_rate for FAPLL on dm816x

2015-03-22 Thread Tony Lindgren
Hi all,

Here are few patches to implement set_rate for the FAPLL found
on dm816x.

Regards,

Tony


Tony Lindgren (3):
  clk: ti: Fix FAPLL recalc_rate for rounding errors
  clk: ti: Implement FAPLL set_rate for the synthesizer
  clk: ti: Implement FAPLL set_rate for the PLL

 drivers/clk/ti/fapll.c | 270 +++--
 1 file changed, 262 insertions(+), 8 deletions(-)

-- 
2.1.4

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


Re: [PATCH 13/15] twl4030_charger: add ac/mode to match usb/mode

2015-03-22 Thread NeilBrown
On Fri, 6 Mar 2015 23:59:04 +0200 Grazvydas Ignotas nota...@gmail.com wrote:

 On Tue, Feb 24, 2015 at 6:33 AM, NeilBrown ne...@suse.de wrote:
  This allows AC charging to be turned off, much like usb charging.
 
  continuous (aka linear) mode maps to the CVENAC (constant voltage)
  feature of the twl4030.
 
 Are you sure? Before your patches CVENAC was set at all times and and
 charger still worked in automatic mode.
 
 
  Signed-off-by: NeilBrown ne...@suse.de
  ---
   drivers/power/twl4030_charger.c |   40 
  +--
   1 file changed, 30 insertions(+), 10 deletions(-)
 
  diff --git a/drivers/power/twl4030_charger.c 
  b/drivers/power/twl4030_charger.c
  index 6c53f0b601a4..e5a0225ea87e 100644
  --- a/drivers/power/twl4030_charger.c
  +++ b/drivers/power/twl4030_charger.c
  @@ -112,7 +112,7 @@ struct twl4030_bci {
  int ichg_eoc, ichg_lo, ichg_hi;
  int usb_cur, ac_cur;
  boolac_is_active;
  -   int usb_mode; /* charging mode requested */
  +   int usb_mode, ac_mode; /* charging mode 
  requested */
   #defineCHARGE_OFF  0
   #defineCHARGE_AUTO 1
   #defineCHARGE_LINEAR   2
  @@ -449,12 +449,18 @@ static int twl4030_charger_enable_usb(struct 
  twl4030_bci *bci, bool enable)
   /*
* Enable/Disable AC Charge funtionality.
*/
  -static int twl4030_charger_enable_ac(bool enable)
  +static int twl4030_charger_enable_ac(struct twl4030_bci *bci, bool enable)
   {
  int ret;
 
  -   if (enable)
  -   ret = twl4030_clear_set_boot_bci(0, TWL4030_BCIAUTOAC);
  +   if (bci-ac_mode == CHARGE_OFF)
  +   enable = false;
  +
  +   if (enable  bci-ac_mode == CHARGE_LINEAR)
  +   ret = twl4030_clear_set_boot_bci(0, (TWL4030_CVENAC |
  +TWL4030_BCIAUTOAC));
  +   else if (enable)
  +   ret = twl4030_clear_set_boot_bci(TWL4030_CVENAC, 
  TWL4030_BCIAUTOAC);
  else
  ret = twl4030_clear_set_boot_bci(TWL4030_BCIAUTOAC, 0);
 
 CVENAC is required to be set for operation on AC without battery
 (which works fine on most pandora boards). After this patch, when
 booted without battery,  the board will reset before there is a chance
 to set the linear mode by userspace, because this is called on
 probe...
 

Yes, it looks like I misunderstood CVENAC a bit - thanks.

I've removed 'continuous' mode for AC and no longer clear or set that bit.

Thanks,
NeilBrown


pgplztCo9D_mx.pgp
Description: OpenPGP digital signature


[PATCH 13/14] twl4030_charger: Increase current carefully while watching voltage.

2015-03-22 Thread NeilBrown
From: NeilBrown ne...@suse.de

The USB Battery Charging spec (BC1.2) suggests a dedicated
charging port can deliver from 0.5 to 5.0A at between 4.75 and 5.25
volts.

To choose the correct current voltage setting requires a trial
and error approach: try to draw current and see if the voltage drops
too low.

Even with a configured Standard Downstream Port, it may not be possible
to reliably pull 500mA - depending on cable quality and source
quality I have reports of charging failure due to the voltage dropping
too low.

To address both these concerns, this patch introduce incremental
current setting.
The current pull from VBUS is increased in steps of 20mA every 100ms
until the target is reached or until the measure voltage drops below
4.75V.  If the voltage does go too low, the target current is reduced
by 20mA and kept there.

This applies to currents selected automatically, or to values
set via sysfs.  So setting a large value will cause the maximum
available to be used - up to the limit of 1.7A imposed by the
hardware.

Signed-off-by: NeilBrown ne...@suse.de
---
 drivers/power/twl4030_charger.c |   68 ++-
 1 file changed, 60 insertions(+), 8 deletions(-)

diff --git a/drivers/power/twl4030_charger.c b/drivers/power/twl4030_charger.c
index 73c7cd96ebc1..d0199495dddc 100644
--- a/drivers/power/twl4030_charger.c
+++ b/drivers/power/twl4030_charger.c
@@ -119,6 +119,18 @@ struct twl4030_bci {
 #defineCHARGE_AUTO 1
 #defineCHARGE_LINEAR   2
 
+   /* When setting the USB current we slowly increase the
+* requested current until target is reached or the voltage
+* drops below 4.75V.  In the latter case we step back one
+* step.
+*/
+   unsigned intusb_cur_target;
+   struct delayed_work current_worker;
+#defineUSB_CUR_STEP2   /* 20mA at a time */
+#defineUSB_MIN_VOLT475 /* 4.75V */
+#defineUSB_CUR_DELAY   msecs_to_jiffies(100)
+#defineUSB_MAX_CURRENT 170 /* TWL4030 caps at 1.7A */
+
unsigned long   event;
 };
 
@@ -257,6 +269,12 @@ static int twl4030_charger_update_current(struct 
twl4030_bci *bci)
} else {
cur = bci-usb_cur;
bci-ac_is_active = false;
+   if (cur  bci-usb_cur_target) {
+   cur = bci-usb_cur_target;
+   bci-usb_cur = cur;
+   }
+   if (cur  bci-usb_cur_target)
+   schedule_delayed_work(bci-current_worker, 
USB_CUR_DELAY);
}
 
/* First, check thresholds and see if cgain is needed */
@@ -391,6 +409,38 @@ static int twl4030_charger_update_current(struct 
twl4030_bci *bci)
return 0;
 }
 
+static void twl4030_current_worker(struct work_struct *data)
+{
+   int v;
+   int res;
+   struct twl4030_bci *bci = container_of(data, struct twl4030_bci,
+  current_worker.work);
+
+   res = twl4030bci_read_adc_val(TWL4030_BCIVBUS);
+   if (res  0)
+   v = 0;
+   else
+   /* BCIVBUS uses ADCIN8, 7/1023 V/step */
+   v = res * 6843;
+
+   printk(v=%d cur=%d target=%d\n, v, bci-usb_cur,
+  bci-usb_cur_target);
+
+   if (v  USB_MIN_VOLT) {
+   /* Back up and stop adjusting. */
+   bci-usb_cur -= USB_CUR_STEP;
+   bci-usb_cur_target = bci-usb_cur;
+   } else if (bci-usb_cur = bci-usb_cur_target ||
+  bci-usb_cur + USB_CUR_STEP  USB_MAX_CURRENT) {
+   /* Reached target and voltage is OK - stop */
+   return;
+   } else {
+   bci-usb_cur += USB_CUR_STEP;
+   schedule_delayed_work(bci-current_worker, USB_CUR_DELAY);
+   }
+   twl4030_charger_update_current(bci);
+}
+
 /*
  * Enable/Disable USB Charge functionality.
  */
@@ -451,6 +501,7 @@ static int twl4030_charger_enable_usb(struct twl4030_bci 
*bci, bool enable)
pm_runtime_put_autosuspend(bci-transceiver-dev);
bci-usb_enabled = 0;
}
+   bci-usb_cur = 0;
}
 
return ret;
@@ -599,7 +650,7 @@ twl4030_bci_max_current_store(struct device *dev, struct 
device_attribute *attr,
if (dev == bci-ac.dev)
bci-ac_cur = cur;
else
-   bci-usb_cur = cur;
+   bci-usb_cur_target = cur;
 
twl4030_charger_update_current(bci);
return n;
@@ -621,7 +672,7 @@ static ssize_t twl4030_bci_max_current_show(struct device 
*dev,
cur = bci-ac_cur;
} else {
if (bci-ac_is_active)
-   cur = bci-usb_cur;
+   cur = bci-usb_cur_target;
}
if (cur  0) {
cur = twl4030bci_read_adc_val(TWL4030_BCIIREF1);
@@ -664,14 +715,14 @@ static int 

[PATCH 12/14] twl4030_charger: add ac/mode to match usb/mode

2015-03-22 Thread NeilBrown
From: NeilBrown ne...@suse.de

This allows AC charging to be turned off, much like usb charging.
continuous mode is not available though.

Acked-by: Pavel Machek pa...@ucw.cz
Signed-off-by: NeilBrown ne...@suse.de
---
 .../ABI/testing/sysfs-class-power-twl4030  |   10 ++
 drivers/power/twl4030_charger.c|   35 +++-
 2 files changed, 37 insertions(+), 8 deletions(-)

diff --git a/Documentation/ABI/testing/sysfs-class-power-twl4030 
b/Documentation/ABI/testing/sysfs-class-power-twl4030
index c27e8ca8c9db..35a211b9a172 100644
--- a/Documentation/ABI/testing/sysfs-class-power-twl4030
+++ b/Documentation/ABI/testing/sysfs-class-power-twl4030
@@ -33,3 +33,13 @@ Description:
 This is useful for unstable power sources
 such as bicycle dynamo, but care should
 be taken that battery is not over-charged.
+
+What: /sys/class/power_supply/twl4030_ac/mode
+Description:
+   Changing mode for 'ac' port.
+   Writing to this can disable charging.
+
+   Possible values are:
+   auto - draw power as appropriate for detected
+power source and battery status.
+   off  - do not draw any power.
diff --git a/drivers/power/twl4030_charger.c b/drivers/power/twl4030_charger.c
index 2c8d85102def..73c7cd96ebc1 100644
--- a/drivers/power/twl4030_charger.c
+++ b/drivers/power/twl4030_charger.c
@@ -114,7 +114,7 @@ struct twl4030_bci {
unsigned intichg_eoc, ichg_lo, ichg_hi;
unsigned intusb_cur, ac_cur;
boolac_is_active;
-   int usb_mode; /* charging mode requested */
+   int usb_mode, ac_mode; /* charging mode requested */
 #defineCHARGE_OFF  0
 #defineCHARGE_AUTO 1
 #defineCHARGE_LINEAR   2
@@ -459,10 +459,13 @@ static int twl4030_charger_enable_usb(struct twl4030_bci 
*bci, bool enable)
 /*
  * Enable/Disable AC Charge funtionality.
  */
-static int twl4030_charger_enable_ac(bool enable)
+static int twl4030_charger_enable_ac(struct twl4030_bci *bci, bool enable)
 {
int ret;
 
+   if (bci-ac_mode == CHARGE_OFF)
+   enable = false;
+
if (enable)
ret = twl4030_clear_set_boot_bci(0, TWL4030_BCIAUTOAC);
else
@@ -693,9 +696,17 @@ twl4030_bci_mode_store(struct device *dev, struct 
device_attribute *attr,
mode = 2;
else
return -EINVAL;
-   twl4030_charger_enable_usb(bci, false);
-   bci-usb_mode = mode;
-   status = twl4030_charger_enable_usb(bci, true);
+   if (dev == bci-ac.dev) {
+   if (mode == 2)
+   return -EINVAL;
+   twl4030_charger_enable_ac(bci, false);
+   bci-ac_mode = mode;
+   status = twl4030_charger_enable_ac(bci, true);
+   } else {
+   twl4030_charger_enable_usb(bci, false);
+   bci-usb_mode = mode;
+   status = twl4030_charger_enable_usb(bci, true);
+   }
return (status == 0) ? n : status;
 }
 
@@ -709,9 +720,13 @@ twl4030_bci_mode_show(struct device *dev,
struct twl4030_bci *bci = dev_get_drvdata(dev-parent);
int len = 0;
int i;
+   int mode = bci-usb_mode;
+
+   if (dev == bci-ac.dev)
+   mode = bci-ac_mode;
 
for (i = 0; i  ARRAY_SIZE(modes); i++)
-   if (bci-usb_mode == i)
+   if (mode == i)
len += snprintf(buf+len, PAGE_SIZE-len,
[%s] , modes[i]);
else
@@ -905,6 +920,7 @@ static int __init twl4030_bci_probe(struct platform_device 
*pdev)
else
bci-usb_cur = 10;  /* 100mA */
bci-usb_mode = CHARGE_AUTO;
+   bci-ac_mode = CHARGE_AUTO;
 
bci-dev = pdev-dev;
bci-irq_chg = platform_get_irq(pdev, 0);
@@ -993,10 +1009,12 @@ static int __init twl4030_bci_probe(struct 
platform_device *pdev)
dev_warn(pdev-dev, could not create sysfs file\n);
if (device_create_file(bci-usb.dev, dev_attr_mode))
dev_warn(pdev-dev, could not create sysfs file\n);
+   if (device_create_file(bci-ac.dev, dev_attr_mode))
+   dev_warn(pdev-dev, could not create sysfs file\n);
if (device_create_file(bci-ac.dev, dev_attr_max_current))
dev_warn(pdev-dev, could not create sysfs file\n);
 
-   twl4030_charger_enable_ac(true);
+   twl4030_charger_enable_ac(bci, true);
if (!IS_ERR_OR_NULL(bci-transceiver))
twl4030_bci_usb_ncb(bci-usb_nb,
bci-transceiver-last_event,
@@ -1016,13 +1034,14 @@ static int __exit twl4030_bci_remove(struct 
platform_device *pdev)
 {
struct twl4030_bci *bci = platform_get_drvdata(pdev);
 
-   twl4030_charger_enable_ac(false);

[PATCH 08/14] twl4030_charger: allow max_current to be managed via sysfs.

2015-03-22 Thread NeilBrown
From: NeilBrown ne...@suse.de

'max_current' sysfs attributes are created which allow the
max to be set.
Whenever a current source changes, the default is restored.
This will be followed by a uevent, so user-space can decide to
update again.

Acked-by: Pavel Machek pa...@ucw.cz
Signed-off-by: NeilBrown ne...@suse.de
---
 .../ABI/testing/sysfs-class-power-twl4030  |   15 
 drivers/power/twl4030_charger.c|   72 
 2 files changed, 87 insertions(+)
 create mode 100644 Documentation/ABI/testing/sysfs-class-power-twl4030

diff --git a/Documentation/ABI/testing/sysfs-class-power-twl4030 
b/Documentation/ABI/testing/sysfs-class-power-twl4030
new file mode 100644
index ..06092209d851
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-class-power-twl4030
@@ -0,0 +1,15 @@
+What: /sys/class/power_supply/twl4030_ac/max_current
+  /sys/class/power_supply/twl4030_usb/max_current
+Description:
+   Read/Write limit on current which which may
+   be drawn from the ac (Accessory Charger) or
+   USB port.
+
+   Value is in micro-Amps.
+
+   Value is set automatically to an appropriate
+   value when a cable is plugged on unplugged.
+
+   Value can the set by writing to the attribute.
+   The change will only persist until the next
+   plug event.  These event are reported via udev.
diff --git a/drivers/power/twl4030_charger.c b/drivers/power/twl4030_charger.c
index 37f2f40991ee..df031b0123d0 100644
--- a/drivers/power/twl4030_charger.c
+++ b/drivers/power/twl4030_charger.c
@@ -482,6 +482,8 @@ static irqreturn_t twl4030_charger_interrupt(int irq, void 
*arg)
struct twl4030_bci *bci = arg;
 
dev_dbg(bci-dev, CHG_PRES irq\n);
+   /* reset current on each 'plug' event */
+   bci-ac_cur = 50;
twl4030_charger_update_current(bci);
power_supply_changed(bci-ac);
power_supply_changed(bci-usb);
@@ -536,6 +538,63 @@ static irqreturn_t twl4030_bci_interrupt(int irq, void 
*arg)
return IRQ_HANDLED;
 }
 
+/*
+ * Provide max_current attribute in sysfs.
+ */
+static ssize_t
+twl4030_bci_max_current_store(struct device *dev, struct device_attribute 
*attr,
+   const char *buf, size_t n)
+{
+   struct twl4030_bci *bci = dev_get_drvdata(dev-parent);
+   int cur = 0;
+   int status = 0;
+   status = kstrtoint(buf, 10, cur);
+   if (status)
+   return status;
+   if (cur  0)
+   return -EINVAL;
+   if (dev == bci-ac.dev)
+   bci-ac_cur = cur;
+   else
+   bci-usb_cur = cur;
+
+   twl4030_charger_update_current(bci);
+   return n;
+}
+
+/*
+ * sysfs max_current show
+ */
+static ssize_t twl4030_bci_max_current_show(struct device *dev,
+   struct device_attribute *attr, char *buf)
+{
+   int status = 0;
+   int cur = -1;
+   u8 bcictl1;
+   struct twl4030_bci *bci = dev_get_drvdata(dev-parent);
+
+   if (dev == bci-ac.dev) {
+   if (!bci-ac_is_active)
+   cur = bci-ac_cur;
+   } else {
+   if (bci-ac_is_active)
+   cur = bci-usb_cur;
+   }
+   if (cur  0) {
+   cur = twl4030bci_read_adc_val(TWL4030_BCIIREF1);
+   if (cur  0)
+   return cur;
+   status = twl4030_bci_read(TWL4030_BCICTL1, bcictl1);
+   if (status  0)
+   return status;
+   cur = regval2ua(cur, bcictl1  TWL4030_CGAIN);
+   }
+   return scnprintf(buf, PAGE_SIZE, %u\n, cur);
+}
+
+static DEVICE_ATTR(max_current, 0644, twl4030_bci_max_current_show,
+   twl4030_bci_max_current_store);
+
 static void twl4030_bci_usb_work(struct work_struct *data)
 {
struct twl4030_bci *bci = container_of(data, struct twl4030_bci, work);
@@ -558,6 +617,12 @@ static int twl4030_bci_usb_ncb(struct notifier_block *nb, 
unsigned long val,
 
dev_dbg(bci-dev, OTG notify %lu\n, val);
 
+   /* reset current on each 'plug' event */
+   if (allow_usb)
+   bci-usb_cur = 50;
+   else
+   bci-usb_cur = 10;
+
bci-event = val;
schedule_work(bci-work);
 
@@ -818,6 +883,11 @@ static int __init twl4030_bci_probe(struct platform_device 
*pdev)
dev_warn(pdev-dev, failed to unmask interrupts: %d\n, ret);
 
twl4030_charger_update_current(bci);
+   if (device_create_file(bci-usb.dev, dev_attr_max_current))
+   dev_warn(pdev-dev, could not create sysfs file\n);
+   if (device_create_file(bci-ac.dev, dev_attr_max_current))
+   dev_warn(pdev-dev, could not create sysfs file\n);
+
twl4030_charger_enable_ac(true);
if (!IS_ERR_OR_NULL(bci-transceiver))
twl4030_bci_usb_ncb(bci-usb_nb,
@@ -842,6 +912,8 @@ static int __exit twl4030_bci_remove(struct platform_device 
*pdev)

[PATCH 07/14] twl4030_charger: distinguish between USB current and 'AC' current

2015-03-22 Thread NeilBrown
From: NeilBrown ne...@suse.de

The twl4030 charger has two current sources, 'USB' and 'AC'
(presumably Accessory Charger).

If 'AC' is providing current, we should set the current limit
differently to when it isn't (and so USB is used).
So split 'cur' into 'usb_cur' and 'ac_cur' and use accordingly.

Now we must review the current setting on any interrupt or USB
event which might indicate that the charger-source has changed.

Acked-by: Pavel Machek pa...@ucw.cz
Signed-off-by: NeilBrown ne...@suse.de
---
 drivers/power/twl4030_charger.c |   36 +---
 1 file changed, 29 insertions(+), 7 deletions(-)

diff --git a/drivers/power/twl4030_charger.c b/drivers/power/twl4030_charger.c
index 02d677ef63e2..37f2f40991ee 100644
--- a/drivers/power/twl4030_charger.c
+++ b/drivers/power/twl4030_charger.c
@@ -22,6 +22,7 @@
 #include linux/power_supply.h
 #include linux/notifier.h
 #include linux/usb/otg.h
+#include linux/i2c/twl4030-madc.h
 
 #define TWL4030_BCIMSTATEC 0x02
 #define TWL4030_BCIICHG0x08
@@ -101,10 +102,13 @@ struct twl4030_bci {
int usb_enabled;
 
/*
-* ichg values in uA. If any are 'large', we set CGAIN to
-* '1' which doubles the range for half the precision.
+* ichg_* and *_cur values in uA. If any are 'large', we set
+* CGAIN to '1' which doubles the range for half the
+* precision.
 */
-   unsigned intichg_eoc, ichg_lo, ichg_hi, cur;
+   unsigned intichg_eoc, ichg_lo, ichg_hi;
+   unsigned intusb_cur, ac_cur;
+   boolac_is_active;
 
unsigned long   event;
 };
@@ -225,11 +229,24 @@ static int ua2regval(int ua, bool cgain)
 static int twl4030_charger_update_current(struct twl4030_bci *bci)
 {
int status;
+   int cur;
unsigned reg, cur_reg;
u8 bcictl1, oldreg, fullreg;
bool cgain = false;
u8 boot_bci;
 
+   /*
+* If AC (Accessory Charger) voltage exceeds 4.5V (MADC 11)
+* and AC is enabled, set current for 'ac'
+*/
+   if (twl4030_get_madc_conversion(11)  4500) {
+   cur = bci-ac_cur;
+   bci-ac_is_active = true;
+   } else {
+   cur = bci-usb_cur;
+   bci-ac_is_active = false;
+   }
+
/* First, check thresholds and see if cgain is needed */
if (bci-ichg_eoc = 20)
cgain = true;
@@ -237,7 +254,7 @@ static int twl4030_charger_update_current(struct 
twl4030_bci *bci)
cgain = true;
if (bci-ichg_hi = 82)
cgain = true;
-   if (bci-cur  852000)
+   if (cur  852000)
cgain = true;
 
status = twl4030_bci_read(TWL4030_BCICTL1, bcictl1);
@@ -318,7 +335,7 @@ static int twl4030_charger_update_current(struct 
twl4030_bci *bci)
 * And finally, set the current.  This is stored in
 * two registers.
 */
-   reg = ua2regval(bci-cur, cgain);
+   reg = ua2regval(cur, cgain);
/* we have only 10 bits */
if (reg  0x3ff)
reg = 0x3ff;
@@ -371,6 +388,8 @@ static int twl4030_charger_enable_usb(struct twl4030_bci 
*bci, bool enable)
 
if (enable  !IS_ERR_OR_NULL(bci-transceiver)) {
 
+   twl4030_charger_update_current(bci);
+
/* Need to keep phy powered */
if (!bci-usb_enabled) {
pm_runtime_get_sync(bci-transceiver-dev);
@@ -463,6 +482,7 @@ static irqreturn_t twl4030_charger_interrupt(int irq, void 
*arg)
struct twl4030_bci *bci = arg;
 
dev_dbg(bci-dev, CHG_PRES irq\n);
+   twl4030_charger_update_current(bci);
power_supply_changed(bci-ac);
power_supply_changed(bci-usb);
 
@@ -495,6 +515,7 @@ static irqreturn_t twl4030_bci_interrupt(int irq, void *arg)
power_supply_changed(bci-ac);
power_supply_changed(bci-usb);
}
+   twl4030_charger_update_current(bci);
 
/* various monitoring events, for now we just log them here */
if (irqs1  (TWL4030_TBATOR2 | TWL4030_TBATOR1))
@@ -708,10 +729,11 @@ static int __init twl4030_bci_probe(struct 
platform_device *pdev)
bci-ichg_eoc = 80100; /* Stop charging when current drops to here */
bci-ichg_lo = 241000; /* Low threshold */
bci-ichg_hi = 50; /* High threshold */
+   bci-ac_cur = 50; /* 500mA */
if (allow_usb)
-   bci-cur = 50;  /* 500mA */
+   bci-usb_cur = 50;  /* 500mA */
else
-   bci-cur = 10;  /* 100mA */
+   bci-usb_cur = 10;  /* 100mA */
 
bci-dev = pdev-dev;
bci-irq_chg = platform_get_irq(pdev, 0);


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

[PATCH 10/14] twl4030_charger: enable manual enable/disable of usb charging.

2015-03-22 Thread NeilBrown
From: NeilBrown ne...@suse.de

'off' or 'auto' to

 /sys/class/power/twl4030_usb/mode

will now enable or disable charging from USB port.  Normally this is
enabled on 'plug' and disabled on 'unplug'.
Unplug will still disable charging.  'plug' will only enable it if
'auto' if selected.

Acked-by: Pavel Machek pa...@ucw.cz
Signed-off-by: NeilBrown ne...@suse.de
---
 .../ABI/testing/sysfs-class-power-twl4030  |   11 
 drivers/power/twl4030_charger.c|   59 
 2 files changed, 70 insertions(+)

diff --git a/Documentation/ABI/testing/sysfs-class-power-twl4030 
b/Documentation/ABI/testing/sysfs-class-power-twl4030
index 06092209d851..390db7a55231 100644
--- a/Documentation/ABI/testing/sysfs-class-power-twl4030
+++ b/Documentation/ABI/testing/sysfs-class-power-twl4030
@@ -13,3 +13,14 @@ Description:
Value can the set by writing to the attribute.
The change will only persist until the next
plug event.  These event are reported via udev.
+
+
+What: /sys/class/power_supply/twl4030_usb/mode
+Description:
+   Changing mode for USB port.
+   Writing to this can disable charging.
+
+   Possible values are:
+   auto - draw power as appropriate for detected
+power source and battery status.
+   off  - do not draw any power.
diff --git a/drivers/power/twl4030_charger.c b/drivers/power/twl4030_charger.c
index 2042e7619954..802cdd6d3e00 100644
--- a/drivers/power/twl4030_charger.c
+++ b/drivers/power/twl4030_charger.c
@@ -109,10 +109,16 @@ struct twl4030_bci {
unsigned intichg_eoc, ichg_lo, ichg_hi;
unsigned intusb_cur, ac_cur;
boolac_is_active;
+   int usb_mode; /* charging mode requested */
+#defineCHARGE_OFF  0
+#defineCHARGE_AUTO 1
 
unsigned long   event;
 };
 
+/* strings for 'usb_mode' values */
+static char *modes[] = { off, auto };
+
 /*
  * clear and set bits on an given register on a given module
  */
@@ -386,6 +392,8 @@ static int twl4030_charger_enable_usb(struct twl4030_bci 
*bci, bool enable)
 {
int ret;
 
+   if (bci-usb_mode == CHARGE_OFF)
+   enable = false;
if (enable  !IS_ERR_OR_NULL(bci-transceiver)) {
 
twl4030_charger_update_current(bci);
@@ -634,6 +642,53 @@ static int twl4030_bci_usb_ncb(struct notifier_block *nb, 
unsigned long val,
return NOTIFY_OK;
 }
 
+/*
+ * sysfs charger enabled store
+ */
+static ssize_t
+twl4030_bci_mode_store(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t n)
+{
+   struct twl4030_bci *bci = dev_get_drvdata(dev-parent);
+   int mode;
+   int status;
+
+   if (sysfs_streq(buf, modes[0]))
+   mode = 0;
+   else if (sysfs_streq(buf, modes[1]))
+   mode = 1;
+   else
+   return -EINVAL;
+   twl4030_charger_enable_usb(bci, false);
+   bci-usb_mode = mode;
+   status = twl4030_charger_enable_usb(bci, true);
+   return (status == 0) ? n : status;
+}
+
+/*
+ * sysfs charger enabled show
+ */
+static ssize_t
+twl4030_bci_mode_show(struct device *dev,
+struct device_attribute *attr, char *buf)
+{
+   struct twl4030_bci *bci = dev_get_drvdata(dev-parent);
+   int len = 0;
+   int i;
+
+   for (i = 0; i  ARRAY_SIZE(modes); i++)
+   if (bci-usb_mode == i)
+   len += snprintf(buf+len, PAGE_SIZE-len,
+   [%s] , modes[i]);
+   else
+   len += snprintf(buf+len, PAGE_SIZE-len,
+   %s , modes[i]);
+   buf[len-1] = '\n';
+   return len;
+}
+static DEVICE_ATTR(mode, 0644, twl4030_bci_mode_show,
+  twl4030_bci_mode_store);
+
 static int twl4030_charger_get_current(void)
 {
int curr;
@@ -804,6 +859,7 @@ static int __init twl4030_bci_probe(struct platform_device 
*pdev)
bci-usb_cur = 50;  /* 500mA */
else
bci-usb_cur = 10;  /* 100mA */
+   bci-usb_mode = CHARGE_AUTO;
 
bci-dev = pdev-dev;
bci-irq_chg = platform_get_irq(pdev, 0);
@@ -890,6 +946,8 @@ static int __init twl4030_bci_probe(struct platform_device 
*pdev)
twl4030_charger_update_current(bci);
if (device_create_file(bci-usb.dev, dev_attr_max_current))
dev_warn(pdev-dev, could not create sysfs file\n);
+   if (device_create_file(bci-usb.dev, dev_attr_mode))
+   dev_warn(pdev-dev, could not create sysfs file\n);
if (device_create_file(bci-ac.dev, dev_attr_max_current))
dev_warn(pdev-dev, could not create sysfs file\n);
 
@@ -918,6 +976,7 @@ static int __exit twl4030_bci_remove(struct platform_device 
*pdev)
twl4030_charger_enable_backup(0, 0);
 

[PATCH 00/14] Enhance twl4030_charger functionality. - V2

2015-03-22 Thread NeilBrown
Hi Sebastian,
 here is V2 of my patches to improve the twl4030 charger.
 They include improved documentation and removal of changes
 to the CVENAC bit which I didn't properly understand.

 One patch needs to make a change in drivers/mfd, and that has
 been acked by Lee Jones.

Summary from before:
These patches make a number of improvements to twl4030_charger.

Some are just internal cleanups (e.g. use of devres).  Others allow
better control of charging through both manual and automatic means.

- the maximum current can be configured via sysfs.
- the charger will only draw that current if it can do so without
  the voltage dropping too much
- a 'continuous' mode is available which ignores voltage and just
  takes what it can (to be used with caution, but very useful in
  some circumstances).
- 'ac' and 'usb' power sources can be configured separately.


Thanks,
NeilBrown

---

NeilBrown (14):
  twl4030_charger: use devm_request_threaded_irq
  twl4030_charger: use devres for power_supply_register and kzalloc.
  twl4030_charger: use runtime_pm to keep usb phy active while charging.
  twl4030_charger: trust phy to determine when USB power is available.
  twl4030_charger: split uA calculation into a function.
  twl4030_charger: allow fine control of charger current.
  twl4030_charger: distinguish between USB current and 'AC' current
  twl4030_charger: allow max_current to be managed via sysfs.
  twl4030_charger: only draw USB current as negotiated with host.
  twl4030_charger: enable manual enable/disable of usb charging.
  twl4030_charger: add software controlled linear charging mode.
  twl4030_charger: add ac/mode to match usb/mode
  twl4030_charger: Increase current carefully while watching voltage.
  twl4030_charger: assume a 'charger' can supply maximum current.


 .../ABI/testing/sysfs-class-power-twl4030  |   45 ++
 drivers/mfd/twl-core.c |9 
 drivers/power/twl4030_charger.c|  573 +---
 3 files changed, 536 insertions(+), 91 deletions(-)
 create mode 100644 Documentation/ABI/testing/sysfs-class-power-twl4030

--
Signature

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


[PATCH 01/14] twl4030_charger: use devm_request_threaded_irq

2015-03-22 Thread NeilBrown
From: NeilBrown ne...@suse.de

This simplifies the error paths.

Signed-off-by: NeilBrown ne...@suse.de
---
 drivers/power/twl4030_charger.c |   18 ++
 1 file changed, 6 insertions(+), 12 deletions(-)

diff --git a/drivers/power/twl4030_charger.c b/drivers/power/twl4030_charger.c
index b07f4e2f2dde..58996d252ecf 100644
--- a/drivers/power/twl4030_charger.c
+++ b/drivers/power/twl4030_charger.c
@@ -610,21 +610,21 @@ static int __init twl4030_bci_probe(struct 
platform_device *pdev)
goto fail_register_usb;
}
 
-   ret = request_threaded_irq(bci-irq_chg, NULL,
+   ret = devm_request_threaded_irq(pdev-dev, bci-irq_chg, NULL,
twl4030_charger_interrupt, IRQF_ONESHOT, pdev-name,
bci);
if (ret  0) {
dev_err(pdev-dev, could not request irq %d, status %d\n,
bci-irq_chg, ret);
-   goto fail_chg_irq;
+   goto fail;
}
 
-   ret = request_threaded_irq(bci-irq_bci, NULL,
+   ret = devm_request_threaded_irq(pdev-dev, bci-irq_bci, NULL,
twl4030_bci_interrupt, IRQF_ONESHOT, pdev-name, bci);
if (ret  0) {
dev_err(pdev-dev, could not request irq %d, status %d\n,
bci-irq_bci, ret);
-   goto fail_bci_irq;
+   goto fail;
}
 
INIT_WORK(bci-work, twl4030_bci_usb_work);
@@ -647,7 +647,7 @@ static int __init twl4030_bci_probe(struct platform_device 
*pdev)
   TWL4030_INTERRUPTS_BCIIMR1A);
if (ret  0) {
dev_err(pdev-dev, failed to unmask interrupts: %d\n, ret);
-   goto fail_unmask_interrupts;
+   goto fail;
}
 
reg = ~(u32)(TWL4030_VBATOV | TWL4030_VBUSOV | TWL4030_ACCHGOV);
@@ -666,11 +666,7 @@ static int __init twl4030_bci_probe(struct platform_device 
*pdev)
 
return 0;
 
-fail_unmask_interrupts:
-   free_irq(bci-irq_bci, bci);
-fail_bci_irq:
-   free_irq(bci-irq_chg, bci);
-fail_chg_irq:
+fail:
power_supply_unregister(bci-usb);
 fail_register_usb:
power_supply_unregister(bci-ac);
@@ -695,8 +691,6 @@ static int __exit twl4030_bci_remove(struct platform_device 
*pdev)
twl_i2c_write_u8(TWL4030_MODULE_INTERRUPTS, 0xff,
 TWL4030_INTERRUPTS_BCIIMR2A);
 
-   free_irq(bci-irq_bci, bci);
-   free_irq(bci-irq_chg, bci);
power_supply_unregister(bci-usb);
power_supply_unregister(bci-ac);
kfree(bci);


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


Re: [PATCH v7 5/6] ARM: dts: add wl12xx/wl18xx bindings

2015-03-22 Thread Kalle Valo
Tony Lindgren t...@atomide.com writes:

 After John retired we actually have two set of trees now: mac80211
 maintained by Johannes and wireless-drivers maintained by me. I haven't
 pulled anything from your tree and I'm 100% sure Johannes hasn't either.
 So green light from me.

 OK, I'll set up the new branch then. I take your ack is for the
 whole series? If it's just for the $subject patch, please let
 me know.

It was for the whole series.

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


Re: Patch to parameterize DMA_MIN_BYTES for omap2-mcspi

2015-03-22 Thread Mark Brown
On Fri, Mar 20, 2015 at 03:10:04PM +0200, Peter Ujfalusi wrote:
 On 03/19/2015 08:51 PM, Mark Brown wrote:

  You probably need both - there's often a hard limit where the FIFO size
  in the hardware becomes a limit for DMA as well as a soft limit on top
  of that for performance reasons.

 The FIFO is only going to be enabled when the DMA is used for transfer so we
 should have some lower limit for the PIO/DMA threshold. The FIFO in McSPI is a

Right, that's pretty much what I'm trying to say.

 tricky one anyways, since it has only one FIFO but several channels and the
 FIFO can be enabled for only one channel, if it is enabled for more channels
 it is not going to be used by either channel.

Not sure I follow this - how does this whole multiple channels thing
work for SPI exactly?


signature.asc
Description: Digital signature


Re: Patches to bind the SGTL5000 chip to AM33XX McASP

2015-03-22 Thread Mark Brown
On Thu, Mar 19, 2015 at 01:48:08PM -0400, Greg Knight wrote:

 Is there a straightforward way we could enable the clock on-demand -
 when we're communicating with the codec/mixer or actually using the
 audio subsystem - while keeping it disabled when not in use? We don't
 expect to be using the audio subsystem frequently.

This is what the clock API is there for - the driver can enable the
clock whenver it needs it and disable it when it doesn't.


signature.asc
Description: Digital signature


Re: [alsa-devel] Patches to bind the SGTL5000 chip to AM33XX McASP

2015-03-22 Thread Mark Brown
On Thu, Mar 19, 2015 at 08:06:15PM +0200, Nikolay Dimitrov wrote:

 Correct. And this is a big issue. As far as I know, the kernel drivers
 control separately the clock domains, and separately i2c devices, so
 the basic expectation on the kernel side is that there's no connection
 between these 2. In this specific case, because of the SGTL5000's

Not really - it's simply that it's the responsibility of the driver for
the device with the dependency to ensure that the dependency is
satisfied.  There are no general rules about what the requirements of
devices are.

 2. Add hacks in the DAPM widgets that add control to the codec's
 reference clocks. While this seems the preferred route to many, the
 general feeling is that such approach is not very welcome in upstream.

There is no need for any hacks, we already know when register accesses
are happening so we can easily add clock enables there (by moving the
code from the MMIO layer to the generic layer, this is the first device
with this unusual requirement).

 3. Add explicit support in the kernel's audio subsystem for
 dependencies between i2c devices and clocks, maybe via DAPM clock
 widget or something like this. Provided that the DAPM graphs are
 defined properly, this will work out-of-the-box for all use cases,
 without the hacks (until we see even more twisted cases).

There's nothing audio specific about the idea of a device needing a
clock for register access, doing something at the audio level is the
wrong abstraction layer.


signature.asc
Description: Digital signature


Re: [PATCH v3] omap-rng: Change RNG_CONFIG_REG to RNG_CONTROL_REG when, checking and disabling TRNG

2015-03-22 Thread Lokesh Vutla
Hi Andre,
On Friday 20 February 2015 10:07 AM, Andre Wolokita wrote:
 In omap4_rng_init(), a check of bit 10 of the RNG_CONFIG_REG is done to 
 determine
 whether the RNG is running. This is suspicious firstly due to the use of
 RNG_CONTROL_ENABLE_TRNG_MASK and secondly because the same mask is written to
 RNG_CONTROL_REG after configuration of the FROs. Similar suspicious logic is
 repeated in omap4_rng_cleanup() when RNG_CONTROL_REG masked with
 RNG_CONTROL_ENABLE_TRNG_MASK is read, the same mask bit is cleared, and then
 written to RNG_CONFIG_REG. Unless the TRNG is enabled with one bit in 
 RNG_CONTROL
 and disabled with another in RNG_CONFIG and these bits are mirrored in some 
 way,
 I believe that the TRNG is not really shutting off, leaving the FROs running
 indefinitely which, in an extreme case, could lead to degredation of the
 hardware and potentially reduce the level of entropy generated.
Yes you are correct. Patch looks good to me.
It should be RNG_CONTROL_REG

Acked-by: Lokesh Vutla lokeshvu...@ti.com

Thanks and regards,
Lokesh

 
 Apart from the strange logic, I have reason to suspect that the OMAP4 related
 code in this driver is driving an Inside Secure IP hardware RNG and strongly
 suspect that bit 10 of RNG_CONFIG_REG is one of the bits configuring the
 sampling rate of the FROs. This option is by default set to 0 and is not being
 set anywhere in omap-rng.c. Reading this bit during omap4_rng_init() will
 always return 0. It will remain 0 because ~(value of TRNG_MASK in control) 
 will
 always be 0, because the TRNG is never shut off. This is of course presuming
 that the OMAP4 features the Inside Secure IP, which I strongly suspect.
 
 I'm interested in knowing what the guys at TI think about this, as only they
 can confirm or deny the detailed structure of these registers.
 
 Signed-off-by: Andre Wolokita andre.wolok...@analog.com
 ---
  drivers/char/hw_random/omap-rng.c |4 ++--
  1 file changed, 2 insertions(+), 2 deletions(-)
 
 diff --git a/drivers/char/hw_random/omap-rng.c 
 b/drivers/char/hw_random/omap-rng.c
 index d14dcf7..67151cb 100644
 --- a/drivers/char/hw_random/omap-rng.c
 +++ b/drivers/char/hw_random/omap-rng.c
 @@ -236,7 +236,7 @@ static int omap4_rng_init(struct omap_rng_dev *priv)
 u32 val;
 
 /* Return if RNG is already running. */
 -   if (omap_rng_read(priv, RNG_CONFIG_REG)  
 RNG_CONTROL_ENABLE_TRNG_MASK)
 +   if (omap_rng_read(priv, RNG_CONTROL_REG)  
 RNG_CONTROL_ENABLE_TRNG_MASK)
 return 0;
 
 val = RNG_CONFIG_MIN_REFIL_CYCLES  
 RNG_CONFIG_MIN_REFIL_CYCLES_SHIFT;
 @@ -262,7 +262,7 @@ static void omap4_rng_cleanup(struct omap_rng_dev *priv)
 
 val = omap_rng_read(priv, RNG_CONTROL_REG);
 val = ~RNG_CONTROL_ENABLE_TRNG_MASK;
 -   omap_rng_write(priv, RNG_CONFIG_REG, val);
 +   omap_rng_write(priv, RNG_CONTROL_REG, val);
  }
 
  static irqreturn_t omap4_rng_irq(int irq, void *dev_id)
 

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