Re: [linux-sunxi] Re: GSL3680 thread

2016-01-25 Thread Gregor Riepl
> It fails before FW loading as below.
> 
> 
> Maybe you could do some testing with https://github.com/rastersoft/gsl1680
>  and
> see if you can get it working by skipping the GPIO stuff?
> 
> 
> I did a try with Joe's one (https://github.com/jabjoe/sunxi-gslx680) but it is
> failling with error
>
>  1. [   91.366514] incomplete xfer (0xff)
>  2. [   91.366532] reset_chip: gsl_ts_write 1 fail!
>  3. [   91.366541] init_chip: reset_chip fail: -70
>  4. [   91.366552] gslx680 1-0040: init_chip failed
> 
>  It seems it's due to I2C bus error and someone on LeMaker forum's pointed to
> me I have probably to switch to 400 khz bus.
>  Another thing I have to do, is to check to which GPIO SHUTDOWN pin is
> connected ... but for that, I need to tears down my device (no time yet : ski
> :) ).
> 
> But if I skip GPIO stuff, how the device will turn on loading phase ? Is
> writing to the device enough ?

If you're interested, there are two new drivers for Silead devices, one by
Robert Dolca (https://lkml.org/lkml/2015/8/25/738) and one by myself.
(https://github.com/onitake/gslx680-acpi) They are mainly intended for
ACPI-based platforms (i.e. Intel Baytrail tablets). I'm very interested in
getting either (or both) of them to work on DeviceTree as well, but this is
difficult without a device to test.

Do you have a DT in human-readable form available? Does it contain any
GPIO/IRQ configuration data for your device?

If you do not use power management, I think the device will respond after
powerup even without the GPIO. At least, I got that impression while working
with a GSL1680. However, if you want to enable power save, I'm pretty sure you
need the pin. Also, you definitely need the IRQ line, unless you want to poll
the chip.

-- 
You received this message because you are subscribed to the Google Groups 
"linux-sunxi" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to linux-sunxi+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


[linux-sunxi] Re: [PATCH sunxi-tools 7/7] fel: Add fel spl command support for Allwinner A64

2016-01-25 Thread Siarhei Siamashka
On Mon, 25 Jan 2016 06:50:54 +0200
Siarhei Siamashka  wrote:

> The SCTLR bits are somewhat different because the V bit is set
> to 0 on A64 (Low exception vectors, base address 0x) and
> the UNK bit (Reads of this bit return an UNKNOWN value) is also not
> the same as on the other SoCs. So the SCTLR check can be relaxed.
> 
> Signed-off-by: Siarhei Siamashka 
> ---
>  fel.c | 23 +--
>  1 file changed, 21 insertions(+), 2 deletions(-)
> 
> diff --git a/fel.c b/fel.c
> index d3d6f62..ee76f98 100644
> --- a/fel.c
> +++ b/fel.c
> @@ -247,6 +247,7 @@ void aw_fel_print_version(libusb_device_handle *usb)
>   case 0x1633: soc_name="A31";break;
>   case 0x1651: soc_name="A20";break;
>   case 0x1650: soc_name="A23";break;
> + case 0x1689: soc_name="A64";break;
>   case 0x1639: soc_name="A80";break;
>   case 0x1667: soc_name="A33";break;
>   case 0x1673: soc_name="A83T";break;
> @@ -492,6 +493,17 @@ sram_swap_buffers a31_sram_swap_buffers[] = {
>  };
>  
>  /*
> + * A64 has a large SRAM C at 0x18000, which we use as a backup storage
> + * for FEL stacks. Also the SPL load address is 0x1 and it makes this
> + * SoC rather unique.
> + */
> +sram_swap_buffers a64_sram_swap_buffers[] = {
> + { .buf1 = 0x11800, .buf2 = 0x18000, .size = 0x800 },
> + { .buf1 = 0x15C00, .buf2 = 0x18800, .size = 0x8000 - 0x5C00 },
> + { 0 }  /* End of the table */
> +};

When creating this patch, I did not notice that the SRAM A1 and SRAM C
don't have a gap between them, but together provide a large contiguous
192 KiB area. So this table should be adjusted to allow having 40 KiB
of SRAM space for the SPL (the 32 KiB - 40 KiB area can be used for
stack).

I'll make an updated patch.

> +/*
>   * Use the SRAM section at 0x44000 as the backup storage. This is the memory,
>   * which is normally shared with the OpenRISC core (should we do an extra 
> check
>   * to ensure that this core is powered off and can't interfere?).
> @@ -542,6 +554,13 @@ soc_sram_info soc_sram_info_table[] = {
>   .swap_buffers = ar100_abusing_sram_swap_buffers,
>   },
>   {
> + .soc_id   = 0x1689, /* Allwinner A64 */
> + .spl_addr = 0x1,
> + .scratch_addr = 0x11000,
> + .thunk_addr   = 0x1AE00, .thunk_size = 0x200,
> + .swap_buffers = a64_sram_swap_buffers,
> + },
> + {
>   .soc_id   = 0x1673, /* Allwinner A83T */
>   .scratch_addr = 0x1000,
>   .thunk_addr   = 0x46E00, .thunk_size = 0x200,
> @@ -840,8 +859,8 @@ uint32_t *aw_backup_and_disable_mmu(libusb_device_handle 
> *usb,
>* checks needs to be relaxed).
>*/
>  
> - /* Basically, ignore M/Z/I bits and expect no TEX remap */
> - if ((sctlr & ~((1 << 12) | (1 << 11) | 1)) != 0x00C52078) {
> + /* Basically, ignore V/M/Z/I/UNK bits and expect no TEX remap */
> + if ((sctlr & ~((3 << 11) | (1 << 6) | 1)) != 0x00C50038) {
>   fprintf(stderr, "Unexpected SCTLR (%08X)\n", sctlr);
>   exit(1);
>   }



-- 
Best regards,
Siarhei Siamashka

-- 
You received this message because you are subscribed to the Google Groups 
"linux-sunxi" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to linux-sunxi+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


[linux-sunxi] [PATCH RFC 06/11] clk: sunxi: factors: Consolidate get_factors parameters into a struct

2016-01-25 Thread Chen-Yu Tsai
The .get_factors callback of factors_clk has 6 parameters. To extend
factors_clk in any way that requires adding parameters to .get_factors
would make that list even longer, not to mention changing all the
function declarations.

Do this once now and consolidate all the parameters into a struct.
Also drop the space before function pointer arguments, since checkpatch
complains.

Signed-off-by: Chen-Yu Tsai 
---
 drivers/clk/sunxi/clk-factors.c|  24 ++--
 drivers/clk/sunxi/clk-factors.h|  13 ++-
 drivers/clk/sunxi/clk-mod0.c   |  20 ++--
 drivers/clk/sunxi/clk-sun8i-mbus.c |  18 +--
 drivers/clk/sunxi/clk-sun9i-core.c |  77 +
 drivers/clk/sunxi/clk-sunxi.c  | 222 +++--
 6 files changed, 155 insertions(+), 219 deletions(-)

diff --git a/drivers/clk/sunxi/clk-factors.c b/drivers/clk/sunxi/clk-factors.c
index b464ca4a232e..47b7d918b74c 100644
--- a/drivers/clk/sunxi/clk-factors.c
+++ b/drivers/clk/sunxi/clk-factors.c
@@ -73,8 +73,13 @@ static long clk_factors_round_rate(struct clk_hw *hw, 
unsigned long rate,
   unsigned long *parent_rate)
 {
struct clk_factors *factors = to_clk_factors(hw);
-   factors->get_factors((u32 *), (u32)*parent_rate,
-NULL, NULL, NULL, NULL);
+   struct factors_request req = {
+   .rate = rate,
+   .parent_rate = *parent_rate,
+   };
+
+   factors->get_factors();
+
 
return rate;
 }
@@ -120,13 +125,16 @@ static int clk_factors_determine_rate(struct clk_hw *hw,
 static int clk_factors_set_rate(struct clk_hw *hw, unsigned long rate,
unsigned long parent_rate)
 {
-   u8 n = 0, k = 0, m = 0, p = 0;
+   struct factors_request req = {
+   .rate = rate,
+   .parent_rate = parent_rate,
+   };
u32 reg;
struct clk_factors *factors = to_clk_factors(hw);
const struct clk_factors_config *config = factors->config;
unsigned long flags = 0;
 
-   factors->get_factors((u32 *), (u32)parent_rate, , , , );
+   factors->get_factors();
 
if (factors->lock)
spin_lock_irqsave(factors->lock, flags);
@@ -135,10 +143,10 @@ static int clk_factors_set_rate(struct clk_hw *hw, 
unsigned long rate,
reg = readl(factors->reg);
 
/* Set up the new factors - macros do not do anything if width is 0 */
-   reg = FACTOR_SET(config->nshift, config->nwidth, reg, n);
-   reg = FACTOR_SET(config->kshift, config->kwidth, reg, k);
-   reg = FACTOR_SET(config->mshift, config->mwidth, reg, m);
-   reg = FACTOR_SET(config->pshift, config->pwidth, reg, p);
+   reg = FACTOR_SET(config->nshift, config->nwidth, reg, req.n);
+   reg = FACTOR_SET(config->kshift, config->kwidth, reg, req.k);
+   reg = FACTOR_SET(config->mshift, config->mwidth, reg, req.m);
+   reg = FACTOR_SET(config->pshift, config->pwidth, reg, req.p);
 
/* Apply them now */
writel(reg, factors->reg);
diff --git a/drivers/clk/sunxi/clk-factors.h b/drivers/clk/sunxi/clk-factors.h
index 7ea1379a7cda..f09d7c214533 100644
--- a/drivers/clk/sunxi/clk-factors.h
+++ b/drivers/clk/sunxi/clk-factors.h
@@ -19,12 +19,21 @@ struct clk_factors_config {
u8 n_start;
 };
 
+struct factors_request {
+   unsigned long rate;
+   unsigned long parent_rate;
+   u8 n;
+   u8 k;
+   u8 m;
+   u8 p;
+};
+
 struct factors_data {
int enable;
int mux;
int muxmask;
const struct clk_factors_config *table;
-   void (*getter) (u32 *rate, u32 parent_rate, u8 *n, u8 *k, u8 *m, u8 *p);
+   void (*getter)(struct factors_request *req);
const char *name;
 };
 
@@ -32,7 +41,7 @@ struct clk_factors {
struct clk_hw hw;
void __iomem *reg;
const struct clk_factors_config *config;
-   void (*get_factors) (u32 *rate, u32 parent, u8 *n, u8 *k, u8 *m, u8 *p);
+   void (*get_factors)(struct factors_request *req);
spinlock_t *lock;
/* for cleanup */
struct clk_mux *mux;
diff --git a/drivers/clk/sunxi/clk-mod0.c b/drivers/clk/sunxi/clk-mod0.c
index c67fea1a128d..578bff0dd251 100644
--- a/drivers/clk/sunxi/clk-mod0.c
+++ b/drivers/clk/sunxi/clk-mod0.c
@@ -28,17 +28,16 @@
  * rate = (parent_rate >> p) / (m + 1);
  */
 
-static void sun4i_a10_get_mod0_factors(u32 *freq, u32 parent_rate,
-  u8 *n, u8 *k, u8 *m, u8 *p)
+static void sun4i_a10_get_mod0_factors(struct factors_request *req)
 {
u8 div, calcm, calcp;
 
/* These clocks can only divide, so we will never be able to achieve
 * frequencies higher than the parent frequency */
-   if (*freq > parent_rate)
-   *freq = parent_rate;
+   if (req->rate > req->parent_rate)
+   req->rate = req->parent_rate;
 
-   div = DIV_ROUND_UP(parent_rate, *freq);
+   div = 

[linux-sunxi] [PATCH RFC 01/11] clk: composite: Add unregister function

2016-01-25 Thread Chen-Yu Tsai
From: Maxime Ripard 

The composite clock didn't have any unregistration function, which forced
us to use clk_unregister directly on it.

While it was already not great from an API point of view, it also meant
that we were leaking the clk_composite structure allocated in
clk_register_composite.

Add a clk_unregister_composite function to fix this.

Signed-off-by: Maxime Ripard 
---
 drivers/clk/clk-composite.c  | 15 +++
 include/linux/clk-provider.h |  1 +
 2 files changed, 16 insertions(+)

diff --git a/drivers/clk/clk-composite.c b/drivers/clk/clk-composite.c
index 4735de0660cc..f4c38f209594 100644
--- a/drivers/clk/clk-composite.c
+++ b/drivers/clk/clk-composite.c
@@ -288,3 +288,18 @@ err:
kfree(composite);
return clk;
 }
+
+void clk_unregister_composite(struct clk *clk)
+{
+   struct clk_composite *composite;
+   struct clk_hw *hw;
+
+   hw = __clk_get_hw(clk);
+   if (!hw)
+   return;
+
+   composite = to_clk_composite(hw);
+
+   clk_unregister(clk);
+   kfree(composite);
+}
diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h
index 1143e38555a4..fa3dd6ba970b 100644
--- a/include/linux/clk-provider.h
+++ b/include/linux/clk-provider.h
@@ -585,6 +585,7 @@ struct clk *clk_register_composite(struct device *dev, 
const char *name,
struct clk_hw *rate_hw, const struct clk_ops *rate_ops,
struct clk_hw *gate_hw, const struct clk_ops *gate_ops,
unsigned long flags);
+void clk_unregister_composite(struct clk *clk);
 
 /***
  * struct clk_gpio_gate - gpio gated clock
-- 
2.7.0

-- 
You received this message because you are subscribed to the Google Groups 
"linux-sunxi" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to linux-sunxi+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


[linux-sunxi] [PATCH RFC 07/11] clk: sunxi: factors: Support custom formulas

2016-01-25 Thread Chen-Yu Tsai
Some clocks cannot be modelled using the standard factors clk formula,
such as clocks with special pre-dividers on one parent, or clocks
with all power-of-two dividers.

Add support for a custom .recalc callback for factors clk. Also pass
the current parent index to the .get_factor and .recalc callbacks.

Signed-off-by: Chen-Yu Tsai 
---
 drivers/clk/sunxi/clk-factors.c | 30 --
 drivers/clk/sunxi/clk-factors.h |  3 +++
 2 files changed, 31 insertions(+), 2 deletions(-)

diff --git a/drivers/clk/sunxi/clk-factors.c b/drivers/clk/sunxi/clk-factors.c
index 47b7d918b74c..ac259305d5d5 100644
--- a/drivers/clk/sunxi/clk-factors.c
+++ b/drivers/clk/sunxi/clk-factors.c
@@ -63,6 +63,26 @@ static unsigned long clk_factors_recalc_rate(struct clk_hw 
*hw,
if (config->pwidth != SUNXI_FACTORS_NOT_APPLICABLE)
p = FACTOR_GET(config->pshift, config->pwidth, reg);
 
+   if (factors->recalc) {
+   struct factors_request factors_req = {
+   .parent_rate = parent_rate,
+   .n = n,
+   .k = k,
+   .m = m,
+   .p = p,
+   };
+
+   /* get mux details from mux clk structure */
+   if (factors->mux)
+   factors_req.parent_index =
+   (reg >> factors->mux->shift) &
+   factors->mux->mask;
+
+   factors->recalc(_req);
+
+   return factors_req.rate;
+   }
+
/* Calculate the rate */
rate = (parent_rate * (n + config->n_start) * (k + 1) >> p) / (m + 1);
 
@@ -87,6 +107,7 @@ static long clk_factors_round_rate(struct clk_hw *hw, 
unsigned long rate,
 static int clk_factors_determine_rate(struct clk_hw *hw,
  struct clk_rate_request *req)
 {
+   struct clk_factors *factors = to_clk_factors(hw);
struct clk_hw *parent, *best_parent = NULL;
int i, num_parents;
unsigned long parent_rate, best = 0, child_rate, best_child_rate = 0;
@@ -94,6 +115,10 @@ static int clk_factors_determine_rate(struct clk_hw *hw,
/* find the parent that can help provide the fastest rate <= rate */
num_parents = clk_hw_get_num_parents(hw);
for (i = 0; i < num_parents; i++) {
+   struct factors_request factors_req = {
+   .rate = req->rate,
+   .parent_index = i,
+   };
parent = clk_hw_get_parent_by_index(hw, i);
if (!parent)
continue;
@@ -102,8 +127,9 @@ static int clk_factors_determine_rate(struct clk_hw *hw,
else
parent_rate = clk_hw_get_rate(parent);
 
-   child_rate = clk_factors_round_rate(hw, req->rate,
-   _rate);
+   factors_req.parent_rate = parent_rate;
+   factors->get_factors(_req);
+   child_rate = factors_req.rate;
 
if (child_rate <= req->rate && child_rate > best_child_rate) {
best_parent = parent;
diff --git a/drivers/clk/sunxi/clk-factors.h b/drivers/clk/sunxi/clk-factors.h
index f09d7c214533..a44a865a6b9e 100644
--- a/drivers/clk/sunxi/clk-factors.h
+++ b/drivers/clk/sunxi/clk-factors.h
@@ -22,6 +22,7 @@ struct clk_factors_config {
 struct factors_request {
unsigned long rate;
unsigned long parent_rate;
+   u8 parent_index;
u8 n;
u8 k;
u8 m;
@@ -34,6 +35,7 @@ struct factors_data {
int muxmask;
const struct clk_factors_config *table;
void (*getter)(struct factors_request *req);
+   void (*recalc)(struct factors_request *req);
const char *name;
 };
 
@@ -42,6 +44,7 @@ struct clk_factors {
void __iomem *reg;
const struct clk_factors_config *config;
void (*get_factors)(struct factors_request *req);
+   void (*recalc)(struct factors_request *req);
spinlock_t *lock;
/* for cleanup */
struct clk_mux *mux;
-- 
2.7.0

-- 
You received this message because you are subscribed to the Google Groups 
"linux-sunxi" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to linux-sunxi+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


[linux-sunxi] [PATCH RFC 04/11] clk: sunxi: factors: Add unregister function

2016-01-25 Thread Chen-Yu Tsai
sunxi's factors clk did not have an unregister function. This means
multiple structs were leaked whenever a factors clk was unregistered.

Add an unregister function for it. Also keep pointers to the mux and
gate structs so they can be freed.

Signed-off-by: Chen-Yu Tsai 
---
 drivers/clk/sunxi/clk-factors.c | 24 
 drivers/clk/sunxi/clk-factors.h |  5 +
 2 files changed, 29 insertions(+)

diff --git a/drivers/clk/sunxi/clk-factors.c b/drivers/clk/sunxi/clk-factors.c
index 1de57c22a358..b464ca4a232e 100644
--- a/drivers/clk/sunxi/clk-factors.c
+++ b/drivers/clk/sunxi/clk-factors.c
@@ -202,6 +202,8 @@ struct clk *sunxi_factors_register(struct device_node *node,
if (!gate)
goto err_gate;
 
+   factors->gate = gate;
+
/* set up gate properties */
gate->reg = reg;
gate->bit_idx = data->enable;
@@ -215,6 +217,8 @@ struct clk *sunxi_factors_register(struct device_node *node,
if (!mux)
goto err_mux;
 
+   factors->mux = mux;
+
/* set up gate properties */
mux->reg = reg;
mux->shift = data->mux;
@@ -254,3 +258,23 @@ err_gate:
 err_factors:
return NULL;
 }
+
+void sunxi_factors_unregister(struct device_node *node, struct clk *clk)
+{
+   struct clk_hw *hw = __clk_get_hw(clk);
+   struct clk_factors *factors;
+   const char *name;
+
+   if (!hw)
+   return;
+
+   factors = to_clk_factors(hw);
+   name = clk_hw_get_name(hw);
+
+   /* No unregister call for clkdev_* */
+   of_clk_del_provider(node);
+   clk_unregister_composite(clk);
+   kfree(factors->mux);
+   kfree(factors->gate);
+   kfree(factors);
+}
diff --git a/drivers/clk/sunxi/clk-factors.h b/drivers/clk/sunxi/clk-factors.h
index 060319be2b99..7ea1379a7cda 100644
--- a/drivers/clk/sunxi/clk-factors.h
+++ b/drivers/clk/sunxi/clk-factors.h
@@ -34,6 +34,9 @@ struct clk_factors {
const struct clk_factors_config *config;
void (*get_factors) (u32 *rate, u32 parent, u8 *n, u8 *k, u8 *m, u8 *p);
spinlock_t *lock;
+   /* for cleanup */
+   struct clk_mux *mux;
+   struct clk_gate *gate;
 };
 
 struct clk *sunxi_factors_register(struct device_node *node,
@@ -41,4 +44,6 @@ struct clk *sunxi_factors_register(struct device_node *node,
   spinlock_t *lock,
   void __iomem *reg);
 
+void sunxi_factors_unregister(struct device_node *node, struct clk *clk);
+
 #endif
-- 
2.7.0

-- 
You received this message because you are subscribed to the Google Groups 
"linux-sunxi" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to linux-sunxi+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


[linux-sunxi] [PATCH RFC 05/11] clk: sunxi: unmap registers in sunxi_factors_clk_setup if register call fails

2016-01-25 Thread Chen-Yu Tsai
sunxi_factors_clk_setup() does not unmap registers when
sunxi_factors_register() fails.

This patch adds proper error handling, and also an error message
when sunxi_factors_register() fails. Also use the full DT node name
in error messages, as the node name is often just "clk", which is
useless.

Signed-off-by: Chen-Yu Tsai 
---
 drivers/clk/sunxi/clk-sunxi.c | 13 +++--
 1 file changed, 11 insertions(+), 2 deletions(-)

diff --git a/drivers/clk/sunxi/clk-sunxi.c b/drivers/clk/sunxi/clk-sunxi.c
index 7e719d089017..5dd927859bc2 100644
--- a/drivers/clk/sunxi/clk-sunxi.c
+++ b/drivers/clk/sunxi/clk-sunxi.c
@@ -747,15 +747,24 @@ static struct clk * __init sunxi_factors_clk_setup(struct 
device_node *node,
   const struct factors_data 
*data)
 {
void __iomem *reg;
+   struct clk *clk;
 
reg = of_iomap(node, 0);
if (!reg) {
pr_err("Could not get registers for factors-clk: %s\n",
-  node->name);
+  of_node_full_name(node));
return NULL;
}
 
-   return sunxi_factors_register(node, data, _lock, reg);
+   clk = sunxi_factors_register(node, data, _lock, reg);
+
+   if (!clk) {
+   pr_err("Could not register factors-clk: %s\n",
+  of_node_full_name(node));
+   iounmap(reg);
+   }
+
+   return clk;
 }
 
 
-- 
2.7.0

-- 
You received this message because you are subscribed to the Google Groups 
"linux-sunxi" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to linux-sunxi+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


[linux-sunxi] [PATCH RFC 09/11] clk: sunxi: rewrite sun6i-a31-ahb1-clk using factors clk with custom recalc

2016-01-25 Thread Chen-Yu Tsai
The factors clk implementation has been extended to support custom
recalc callbacks to support clocks that use one factor for certain
parents only, like a pre-divider.

Signed-off-by: Chen-Yu Tsai 
---
 drivers/clk/sunxi/clk-sunxi.c | 291 --
 1 file changed, 83 insertions(+), 208 deletions(-)

diff --git a/drivers/clk/sunxi/clk-sunxi.c b/drivers/clk/sunxi/clk-sunxi.c
index 56d4fdcf9c89..32d0bfa4913b 100644
--- a/drivers/clk/sunxi/clk-sunxi.c
+++ b/drivers/clk/sunxi/clk-sunxi.c
@@ -28,214 +28,6 @@
 
 static DEFINE_SPINLOCK(clk_lock);
 
-/**
- * sun6i_a31_ahb1_clk_setup() - Setup function for a31 ahb1 composite clk
- */
-
-#define SUN6I_AHB1_MAX_PARENTS 4
-#define SUN6I_AHB1_MUX_PARENT_PLL6 3
-#define SUN6I_AHB1_MUX_SHIFT   12
-/* un-shifted mask is what mux_clk expects */
-#define SUN6I_AHB1_MUX_MASK0x3
-#define SUN6I_AHB1_MUX_GET_PARENT(reg) ((reg >> SUN6I_AHB1_MUX_SHIFT) & \
-SUN6I_AHB1_MUX_MASK)
-
-#define SUN6I_AHB1_DIV_SHIFT   4
-#define SUN6I_AHB1_DIV_MASK(0x3 << SUN6I_AHB1_DIV_SHIFT)
-#define SUN6I_AHB1_DIV_GET(reg)((reg & SUN6I_AHB1_DIV_MASK) >> 
\
-   SUN6I_AHB1_DIV_SHIFT)
-#define SUN6I_AHB1_DIV_SET(reg, div)   ((reg & ~SUN6I_AHB1_DIV_MASK) | \
-   (div << SUN6I_AHB1_DIV_SHIFT))
-#define SUN6I_AHB1_PLL6_DIV_SHIFT  6
-#define SUN6I_AHB1_PLL6_DIV_MASK   (0x3 << SUN6I_AHB1_PLL6_DIV_SHIFT)
-#define SUN6I_AHB1_PLL6_DIV_GET(reg)   ((reg & SUN6I_AHB1_PLL6_DIV_MASK) >> \
-   SUN6I_AHB1_PLL6_DIV_SHIFT)
-#define SUN6I_AHB1_PLL6_DIV_SET(reg, div) ((reg & ~SUN6I_AHB1_PLL6_DIV_MASK) | 
\
-   (div << 
SUN6I_AHB1_PLL6_DIV_SHIFT))
-
-struct sun6i_ahb1_clk {
-   struct clk_hw hw;
-   void __iomem *reg;
-};
-
-#define to_sun6i_ahb1_clk(_hw) container_of(_hw, struct sun6i_ahb1_clk, hw)
-
-static unsigned long sun6i_ahb1_clk_recalc_rate(struct clk_hw *hw,
-   unsigned long parent_rate)
-{
-   struct sun6i_ahb1_clk *ahb1 = to_sun6i_ahb1_clk(hw);
-   unsigned long rate;
-   u32 reg;
-
-   /* Fetch the register value */
-   reg = readl(ahb1->reg);
-
-   /* apply pre-divider first if parent is pll6 */
-   if (SUN6I_AHB1_MUX_GET_PARENT(reg) == SUN6I_AHB1_MUX_PARENT_PLL6)
-   parent_rate /= SUN6I_AHB1_PLL6_DIV_GET(reg) + 1;
-
-   /* clk divider */
-   rate = parent_rate >> SUN6I_AHB1_DIV_GET(reg);
-
-   return rate;
-}
-
-static long sun6i_ahb1_clk_round(unsigned long rate, u8 *divp, u8 *pre_divp,
-u8 parent, unsigned long parent_rate)
-{
-   u8 div, calcp, calcm = 1;
-
-   /*
-* clock can only divide, so we will never be able to achieve
-* frequencies higher than the parent frequency
-*/
-   if (parent_rate && rate > parent_rate)
-   rate = parent_rate;
-
-   div = DIV_ROUND_UP(parent_rate, rate);
-
-   /* calculate pre-divider if parent is pll6 */
-   if (parent == SUN6I_AHB1_MUX_PARENT_PLL6) {
-   if (div < 4)
-   calcp = 0;
-   else if (div / 2 < 4)
-   calcp = 1;
-   else if (div / 4 < 4)
-   calcp = 2;
-   else
-   calcp = 3;
-
-   calcm = DIV_ROUND_UP(div, 1 << calcp);
-   } else {
-   calcp = __roundup_pow_of_two(div);
-   calcp = calcp > 3 ? 3 : calcp;
-   }
-
-   /* we were asked to pass back divider values */
-   if (divp) {
-   *divp = calcp;
-   *pre_divp = calcm - 1;
-   }
-
-   return (parent_rate / calcm) >> calcp;
-}
-
-static int sun6i_ahb1_clk_determine_rate(struct clk_hw *hw,
-struct clk_rate_request *req)
-{
-   struct clk_hw *parent, *best_parent = NULL;
-   int i, num_parents;
-   unsigned long parent_rate, best = 0, child_rate, best_child_rate = 0;
-
-   /* find the parent that can help provide the fastest rate <= rate */
-   num_parents = clk_hw_get_num_parents(hw);
-   for (i = 0; i < num_parents; i++) {
-   parent = clk_hw_get_parent_by_index(hw, i);
-   if (!parent)
-   continue;
-   if (clk_hw_get_flags(hw) & CLK_SET_RATE_PARENT)
-   parent_rate = clk_hw_round_rate(parent, req->rate);
-   else
-   parent_rate = clk_hw_get_rate(parent);
-
-   child_rate = sun6i_ahb1_clk_round(req->rate, NULL, NULL, i,
- parent_rate);
-
-   if (child_rate <= req->rate && child_rate > best_child_rate) {
-   

[linux-sunxi] [PATCH RFC 02/11] clk: sunxi: factors: Make struct clk_factors_config table const

2016-01-25 Thread Chen-Yu Tsai
struct clk_factors_config contains shifts/widths for the factors of
the factors clk. This is used to read out the factors from the register
value. In no case is it written to, so make it const.

Signed-off-by: Chen-Yu Tsai 
---
 drivers/clk/sunxi/clk-factors.c|  4 ++--
 drivers/clk/sunxi/clk-factors.h|  4 ++--
 drivers/clk/sunxi/clk-mod0.c   |  2 +-
 drivers/clk/sunxi/clk-sun9i-core.c |  8 
 drivers/clk/sunxi/clk-sunxi.c  | 16 
 5 files changed, 17 insertions(+), 17 deletions(-)

diff --git a/drivers/clk/sunxi/clk-factors.c b/drivers/clk/sunxi/clk-factors.c
index 59428dbd607a..928c079da193 100644
--- a/drivers/clk/sunxi/clk-factors.c
+++ b/drivers/clk/sunxi/clk-factors.c
@@ -48,7 +48,7 @@ static unsigned long clk_factors_recalc_rate(struct clk_hw 
*hw,
u32 reg;
unsigned long rate;
struct clk_factors *factors = to_clk_factors(hw);
-   struct clk_factors_config *config = factors->config;
+   const struct clk_factors_config *config = factors->config;
 
/* Fetch the register value */
reg = readl(factors->reg);
@@ -123,7 +123,7 @@ static int clk_factors_set_rate(struct clk_hw *hw, unsigned 
long rate,
u8 n = 0, k = 0, m = 0, p = 0;
u32 reg;
struct clk_factors *factors = to_clk_factors(hw);
-   struct clk_factors_config *config = factors->config;
+   const struct clk_factors_config *config = factors->config;
unsigned long flags = 0;
 
factors->get_factors((u32 *), (u32)parent_rate, , , , );
diff --git a/drivers/clk/sunxi/clk-factors.h b/drivers/clk/sunxi/clk-factors.h
index 171085ab5513..060319be2b99 100644
--- a/drivers/clk/sunxi/clk-factors.h
+++ b/drivers/clk/sunxi/clk-factors.h
@@ -23,7 +23,7 @@ struct factors_data {
int enable;
int mux;
int muxmask;
-   struct clk_factors_config *table;
+   const struct clk_factors_config *table;
void (*getter) (u32 *rate, u32 parent_rate, u8 *n, u8 *k, u8 *m, u8 *p);
const char *name;
 };
@@ -31,7 +31,7 @@ struct factors_data {
 struct clk_factors {
struct clk_hw hw;
void __iomem *reg;
-   struct clk_factors_config *config;
+   const struct clk_factors_config *config;
void (*get_factors) (u32 *rate, u32 parent, u8 *n, u8 *k, u8 *m, u8 *p);
spinlock_t *lock;
 };
diff --git a/drivers/clk/sunxi/clk-mod0.c b/drivers/clk/sunxi/clk-mod0.c
index d167e1efb927..c67fea1a128d 100644
--- a/drivers/clk/sunxi/clk-mod0.c
+++ b/drivers/clk/sunxi/clk-mod0.c
@@ -62,7 +62,7 @@ static void sun4i_a10_get_mod0_factors(u32 *freq, u32 
parent_rate,
 }
 
 /* user manual says "n" but it's really "p" */
-static struct clk_factors_config sun4i_a10_mod0_config = {
+static const struct clk_factors_config sun4i_a10_mod0_config = {
.mshift = 0,
.mwidth = 4,
.pshift = 16,
diff --git a/drivers/clk/sunxi/clk-sun9i-core.c 
b/drivers/clk/sunxi/clk-sun9i-core.c
index 6c4c98324d3c..37c85caaef88 100644
--- a/drivers/clk/sunxi/clk-sun9i-core.c
+++ b/drivers/clk/sunxi/clk-sun9i-core.c
@@ -71,7 +71,7 @@ static void sun9i_a80_get_pll4_factors(u32 *freq, u32 
parent_rate,
*p_ret = p;
 }
 
-static struct clk_factors_config sun9i_a80_pll4_config = {
+static const struct clk_factors_config sun9i_a80_pll4_config = {
.mshift = 18,
.mwidth = 1,
.nshift = 8,
@@ -134,7 +134,7 @@ static void sun9i_a80_get_gt_factors(u32 *freq, u32 
parent_rate,
*m = div;
 }
 
-static struct clk_factors_config sun9i_a80_gt_config = {
+static const struct clk_factors_config sun9i_a80_gt_config = {
.mshift = 0,
.mwidth = 2,
 };
@@ -199,7 +199,7 @@ static void sun9i_a80_get_ahb_factors(u32 *freq, u32 
parent_rate,
*p = _p;
 }
 
-static struct clk_factors_config sun9i_a80_ahb_config = {
+static const struct clk_factors_config sun9i_a80_ahb_config = {
.pshift = 0,
.pwidth = 2,
 };
@@ -289,7 +289,7 @@ static void sun9i_a80_get_apb1_factors(u32 *freq, u32 
parent_rate,
*p = calcp;
 }
 
-static struct clk_factors_config sun9i_a80_apb1_config = {
+static const struct clk_factors_config sun9i_a80_apb1_config = {
.mshift = 0,
.mwidth = 5,
.pshift = 16,
diff --git a/drivers/clk/sunxi/clk-sunxi.c b/drivers/clk/sunxi/clk-sunxi.c
index 0d4525365552..7e719d089017 100644
--- a/drivers/clk/sunxi/clk-sunxi.c
+++ b/drivers/clk/sunxi/clk-sunxi.c
@@ -608,7 +608,7 @@ static void sun7i_a20_get_out_factors(u32 *freq, u32 
parent_rate,
  * sunxi_factors_clk_setup() - Setup function for factor clocks
  */
 
-static struct clk_factors_config sun4i_pll1_config = {
+static const struct clk_factors_config sun4i_pll1_config = {
.nshift = 8,
.nwidth = 5,
.kshift = 4,
@@ -619,7 +619,7 @@ static struct clk_factors_config sun4i_pll1_config = {
.pwidth = 2,
 };
 
-static struct clk_factors_config sun6i_a31_pll1_config = {
+static const struct clk_factors_config 

[linux-sunxi] [PATCH RFC 10/11] clk: sunxi: rewrite sun6i-ar100 using factors clk

2016-01-25 Thread Chen-Yu Tsai
sun6i's AR100 clock is a classic factors clk case:

AR100 = ((parent mux) >> p) / (m + 1)

Signed-off-by: Chen-Yu Tsai 
---
 drivers/clk/sunxi/clk-sun6i-ar100.c | 235 ++--
 1 file changed, 61 insertions(+), 174 deletions(-)

diff --git a/drivers/clk/sunxi/clk-sun6i-ar100.c 
b/drivers/clk/sunxi/clk-sun6i-ar100.c
index 20887686bdbe..a7f5777834eb 100644
--- a/drivers/clk/sunxi/clk-sun6i-ar100.c
+++ b/drivers/clk/sunxi/clk-sun6i-ar100.c
@@ -8,211 +8,97 @@
  *
  */
 
+#include 
 #include 
 #include 
 #include 
 #include 
+#include 
 
-#define SUN6I_AR100_MAX_PARENTS4
-#define SUN6I_AR100_SHIFT_MASK 0x3
-#define SUN6I_AR100_SHIFT_MAX  SUN6I_AR100_SHIFT_MASK
-#define SUN6I_AR100_SHIFT_SHIFT4
-#define SUN6I_AR100_DIV_MASK   0x1f
-#define SUN6I_AR100_DIV_MAX(SUN6I_AR100_DIV_MASK + 1)
-#define SUN6I_AR100_DIV_SHIFT  8
-#define SUN6I_AR100_MUX_MASK   0x3
-#define SUN6I_AR100_MUX_SHIFT  16
-
-struct ar100_clk {
-   struct clk_hw hw;
-   void __iomem *reg;
-};
-
-static inline struct ar100_clk *to_ar100_clk(struct clk_hw *hw)
-{
-   return container_of(hw, struct ar100_clk, hw);
-}
-
-static unsigned long ar100_recalc_rate(struct clk_hw *hw,
-  unsigned long parent_rate)
-{
-   struct ar100_clk *clk = to_ar100_clk(hw);
-   u32 val = readl(clk->reg);
-   int shift = (val >> SUN6I_AR100_SHIFT_SHIFT) & SUN6I_AR100_SHIFT_MASK;
-   int div = (val >> SUN6I_AR100_DIV_SHIFT) & SUN6I_AR100_DIV_MASK;
-
-   return (parent_rate >> shift) / (div + 1);
-}
-
-static int ar100_determine_rate(struct clk_hw *hw,
-   struct clk_rate_request *req)
-{
-   int nparents = clk_hw_get_num_parents(hw);
-   long best_rate = -EINVAL;
-   int i;
-
-   req->best_parent_hw = NULL;
-
-   for (i = 0; i < nparents; i++) {
-   unsigned long parent_rate;
-   unsigned long tmp_rate;
-   struct clk_hw *parent;
-   unsigned long div;
-   int shift;
-
-   parent = clk_hw_get_parent_by_index(hw, i);
-   parent_rate = clk_hw_get_rate(parent);
-   div = DIV_ROUND_UP(parent_rate, req->rate);
-
-   /*
-* The AR100 clk contains 2 divisors:
-* - one power of 2 divisor
-* - one regular divisor
-*
-* First check if we can safely shift (or divide by a power
-* of 2) without losing precision on the requested rate.
-*/
-   shift = ffs(div) - 1;
-   if (shift > SUN6I_AR100_SHIFT_MAX)
-   shift = SUN6I_AR100_SHIFT_MAX;
-
-   div >>= shift;
-
-   /*
-* Then if the divisor is still bigger than what the HW
-* actually supports, use a bigger shift (or power of 2
-* divider) value and accept to lose some precision.
-*/
-   while (div > SUN6I_AR100_DIV_MAX) {
-   shift++;
-   div >>= 1;
-   if (shift > SUN6I_AR100_SHIFT_MAX)
-   break;
-   }
-
-   /*
-* If the shift value (or power of 2 divider) is bigger
-* than what the HW actually support, skip this parent.
-*/
-   if (shift > SUN6I_AR100_SHIFT_MAX)
-   continue;
-
-   tmp_rate = (parent_rate >> shift) / div;
-   if (!req->best_parent_hw || tmp_rate > best_rate) {
-   req->best_parent_hw = parent;
-   req->best_parent_rate = parent_rate;
-   best_rate = tmp_rate;
-   }
-   }
-
-   if (best_rate < 0)
-   return best_rate;
-
-   req->rate = best_rate;
-
-   return 0;
-}
-
-static int ar100_set_parent(struct clk_hw *hw, u8 index)
-{
-   struct ar100_clk *clk = to_ar100_clk(hw);
-   u32 val = readl(clk->reg);
-
-   if (index >= SUN6I_AR100_MAX_PARENTS)
-   return -EINVAL;
-
-   val &= ~(SUN6I_AR100_MUX_MASK << SUN6I_AR100_MUX_SHIFT);
-   val |= (index << SUN6I_AR100_MUX_SHIFT);
-   writel(val, clk->reg);
-
-   return 0;
-}
+#include "clk-factors.h"
 
-static u8 ar100_get_parent(struct clk_hw *hw)
-{
-   struct ar100_clk *clk = to_ar100_clk(hw);
-   return (readl(clk->reg) >> SUN6I_AR100_MUX_SHIFT) &
-  SUN6I_AR100_MUX_MASK;
-}
-
-static int ar100_set_rate(struct clk_hw *hw, unsigned long rate,
- unsigned long parent_rate)
+/**
+ * sun6i_get_ar100_factors - Calculates factors p, m for AR100
+ *
+ * AR100 rate is calculated as follows
+ * rate = (parent_rate >> p) / (m + 1);
+ */
+static void sun6i_get_ar100_factors(struct 

[linux-sunxi] [PATCH RFC 11/11] clk: sunxi: rewrite sun8i-a23-mbus-clk using the simpler composite clk

2016-01-25 Thread Chen-Yu Tsai
sun8i-a23-mbus-clk used sunxi's factors clk, which is nice for very
complicated clocks, but is not really needed here.

Convert sun8i-a23-mbus-clk to use clk_composite, as it is a gate + mux
+ divider. This makes the code easier to understand.

Signed-off-by: Chen-Yu Tsai 
---

This patch I'm not so sure about. As stated in the cover letter,
this rewrite actually increases the LoC, but possibly making it
easier to understand.

---
 drivers/clk/sunxi/clk-sun8i-mbus.c | 120 +++--
 1 file changed, 75 insertions(+), 45 deletions(-)

diff --git a/drivers/clk/sunxi/clk-sun8i-mbus.c 
b/drivers/clk/sunxi/clk-sun8i-mbus.c
index 78683f02a37d..d3e385337b8a 100644
--- a/drivers/clk/sunxi/clk-sun8i-mbus.c
+++ b/drivers/clk/sunxi/clk-sun8i-mbus.c
@@ -15,68 +15,98 @@
  */
 
 #include 
+#include 
 #include 
+#include 
+#include 
 #include 
 
-#include "clk-factors.h"
+#define SUN8I_MBUS_ENABLE  31
+#define SUN8I_MBUS_MUX_SHIFT   24
+#define SUN8I_MBUS_MUX_MASK0x3
+#define SUN8I_MBUS_DIV_SHIFT   0
+#define SUN8I_MBUS_DIV_WIDTH   3
+#define SUN8I_MBUS_MAX_PARENTS 4
 
-/**
- * sun8i_a23_get_mbus_factors() - calculates m factor for MBUS clocks
- * MBUS rate is calculated as follows
- * rate = parent_rate / (m + 1);
- */
+static DEFINE_SPINLOCK(sun8i_a23_mbus_lock);
 
-static void sun8i_a23_get_mbus_factors(struct factors_request *req)
+static void __init sun8i_a23_mbus_setup(struct device_node *node)
 {
-   u8 div;
+   int num_parents = of_clk_get_parent_count(node);
+   const char *parents[num_parents];
+   const char *clk_name = node->name;
+   struct resource res;
+   struct clk_divider *div;
+   struct clk_gate *gate;
+   struct clk_mux *mux;
+   struct clk *clk;
+   void __iomem *reg;
+   int err;
 
-   /*
-* These clocks can only divide, so we will never be able to
-* achieve frequencies higher than the parent frequency
-*/
-   if (req->rate > req->parent_rate)
-   req->rate = req->parent_rate;
+   reg = of_io_request_and_map(node, 0, of_node_full_name(node));
+   if (!reg) {
+   pr_err("Could not get registers for sun8i-mbus-clk\n");
+   return;
+   }
 
-   div = DIV_ROUND_UP(req->parent_rate, req->rate);
+   div = kzalloc(sizeof(*div), GFP_KERNEL);
+   if (!div)
+   goto err_unmap;
 
-   if (div > 8)
-   div = 8;
+   mux = kzalloc(sizeof(*mux), GFP_KERNEL);
+   if (!mux)
+   goto err_free_div;
 
-   req->rate = req->parent_rate / div;
-   req->m = div - 1;
-}
+   gate = kzalloc(sizeof(*gate), GFP_KERNEL);
+   if (!gate)
+   goto err_free_mux;
 
-static struct clk_factors_config sun8i_a23_mbus_config = {
-   .mshift = 0,
-   .mwidth = 3,
-};
+   of_property_read_string(node, "clock-output-names", _name);
+   of_clk_parent_fill(node, parents, num_parents);
 
-static const struct factors_data sun8i_a23_mbus_data __initconst = {
-   .enable = 31,
-   .mux = 24,
-   .muxmask = BIT(1) | BIT(0),
-   .table = _a23_mbus_config,
-   .getter = sun8i_a23_get_mbus_factors,
-};
+   gate->reg = reg;
+   gate->bit_idx = SUN8I_MBUS_ENABLE;
+   gate->lock = _a23_mbus_lock;
 
-static DEFINE_SPINLOCK(sun8i_a23_mbus_lock);
+   div->reg = reg;
+   div->shift = SUN8I_MBUS_DIV_SHIFT;
+   div->width = SUN8I_MBUS_DIV_WIDTH;
+   div->lock = _a23_mbus_lock;
 
-static void __init sun8i_a23_mbus_setup(struct device_node *node)
-{
-   struct clk *mbus;
-   void __iomem *reg;
+   mux->reg = reg;
+   mux->shift = SUN8I_MBUS_MUX_SHIFT;
+   mux->mask = SUN8I_MBUS_MUX_MASK;
+   mux->lock = _a23_mbus_lock;
 
-   reg = of_iomap(node, 0);
-   if (!reg) {
-   pr_err("Could not get registers for a23-mbus-clk\n");
-   return;
-   }
+   clk = clk_register_composite(NULL, clk_name, parents, num_parents,
+>hw, _mux_ops,
+>hw, _divider_ops,
+>hw, _gate_ops,
+0);
+   if (IS_ERR(clk))
+   goto err_free_gate;
 
-   mbus = sunxi_factors_register(node, _a23_mbus_data,
- _a23_mbus_lock, reg);
+   err = of_clk_add_provider(node, of_clk_src_simple_get, clk);
+   if (err)
+   goto err_unregister_clk;
 
/* The MBUS clocks needs to be always enabled */
-   __clk_get(mbus);
-   clk_prepare_enable(mbus);
+   __clk_get(clk);
+   clk_prepare_enable(clk);
+
+   return;
+
+err_unregister_clk:
+   clk_unregister_composite(clk);
+err_free_gate:
+   kfree(gate);
+err_free_mux:
+   kfree(mux);
+err_free_div:
+   kfree(div);
+err_unmap:
+   iounmap(reg);
+   of_address_to_resource(node, 0, );
+   release_mem_region(res.start, 

[linux-sunxi] [PATCH RFC 03/11] clk: sunxi: factors: Add clk cleanup in sunxi_factors_register() error path

2016-01-25 Thread Chen-Yu Tsai
sunxi_factors_register() does not check for failures or cleanup after
clk_register_composite() or other clk-related calls.

Signed-off-by: Chen-Yu Tsai 
---
 drivers/clk/sunxi/clk-factors.c | 43 +++--
 1 file changed, 28 insertions(+), 15 deletions(-)

diff --git a/drivers/clk/sunxi/clk-factors.c b/drivers/clk/sunxi/clk-factors.c
index 928c079da193..1de57c22a358 100644
--- a/drivers/clk/sunxi/clk-factors.c
+++ b/drivers/clk/sunxi/clk-factors.c
@@ -172,7 +172,7 @@ struct clk *sunxi_factors_register(struct device_node *node,
struct clk_hw *mux_hw = NULL;
const char *clk_name = node->name;
const char *parents[FACTORS_MAX_PARENTS];
-   int i = 0;
+   int ret, i = 0;
 
/* if we have a mux, we will have >1 parents */
i = of_clk_parent_fill(node, parents, FACTORS_MAX_PARENTS);
@@ -188,7 +188,7 @@ struct clk *sunxi_factors_register(struct device_node *node,
 
factors = kzalloc(sizeof(struct clk_factors), GFP_KERNEL);
if (!factors)
-   return NULL;
+   goto err_factors;
 
/* set up factors properties */
factors->reg = reg;
@@ -199,10 +199,8 @@ struct clk *sunxi_factors_register(struct device_node 
*node,
/* Add a gate if this factor clock can be gated */
if (data->enable) {
gate = kzalloc(sizeof(struct clk_gate), GFP_KERNEL);
-   if (!gate) {
-   kfree(factors);
-   return NULL;
-   }
+   if (!gate)
+   goto err_gate;
 
/* set up gate properties */
gate->reg = reg;
@@ -214,11 +212,8 @@ struct clk *sunxi_factors_register(struct device_node 
*node,
/* Add a mux if this factor clock can be muxed */
if (data->mux) {
mux = kzalloc(sizeof(struct clk_mux), GFP_KERNEL);
-   if (!mux) {
-   kfree(factors);
-   kfree(gate);
-   return NULL;
-   }
+   if (!mux)
+   goto err_mux;
 
/* set up gate properties */
mux->reg = reg;
@@ -233,11 +228,29 @@ struct clk *sunxi_factors_register(struct device_node 
*node,
mux_hw, _mux_ops,
>hw, _factors_ops,
gate_hw, _gate_ops, 0);
+   if (IS_ERR(clk))
+   goto err_register;
 
-   if (!IS_ERR(clk)) {
-   of_clk_add_provider(node, of_clk_src_simple_get, clk);
-   clk_register_clkdev(clk, clk_name, NULL);
-   }
+   ret = of_clk_add_provider(node, of_clk_src_simple_get, clk);
+   if (ret)
+   goto err_provider;
+
+   ret = clk_register_clkdev(clk, clk_name, NULL);
+   if (ret)
+   goto err_clkdev;
 
return clk;
+
+err_clkdev:
+   of_clk_del_provider(node);
+err_provider:
+   clk_unregister_composite(clk);
+err_register:
+   kfree(mux);
+err_mux:
+   kfree(gate);
+err_gate:
+   kfree(factors);
+err_factors:
+   return NULL;
 }
-- 
2.7.0

-- 
You received this message because you are subscribed to the Google Groups 
"linux-sunxi" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to linux-sunxi+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


[linux-sunxi] [PATCH RFC 00/11] clk: sunxi: factors clk clean up and refactor

2016-01-25 Thread Chen-Yu Tsai
Hi everyone,

This series cleans up and reworks parts of sunxi's factors clk. The goal
is to support non-standard formulas for clock rate calculation, such as
pre-dividers on some parents, or all power-of-2 dividers. One such clock
is the AHB1 clock on A31/A31s.

Patch 1 is Maxime's patch adding an unregister function for composite
clocks. Patches 3 and 4 use this, so it is included for completeness.

Patch 2 makes the config tables for factors clk constant. These contain
the shift and width for the factors. They are used to manipulate the
clk register values. There should be no reason to change them in-flight.

Patch 3 adds a proper error path for the factors clk register function(),
so we don't leak memory when a call fails.

Patch 4 adds an unregister function for factors clks.

Patch 5 adds an error patch to sunxi_factors_clk_setup()

Patch 6 packs the parameters passed to get_factors callbacks in a struct.
This makes it easier to extend factors clk without having to edit all
the function definitions, and also makes the lines shorter.

Patch 7 makes factors clk support custom formulas for calculating clock
rates. On the clock rounding/setting side, we only need to teach
get_factors about different parent clocks. On the recalc side, we add
support for custom .recalc callbacks for clocks that need them.

Patch 8 drops .round_rate from factors clk ops. Since only one of
.round_rate and .determine_rate is needed, and the clk core prefers the
latter, remove .round_rate.

Patch 9 rewrites sun6i-a31-ahb1-clk using factors clk with the new custom
formula support. sun6i-a31-ahb1 has a pre-divider on one of its parents.

Patch 10 rewrite sun6i-ar100 using factors clk.

Patch 11 rewrites sun8i-a23-mbus-clk using the simpler composite clk.
While this patch is doing the reverse, i.e. rewriting a factors clk into
a composite clk, it is included because some changes overlap. I'm not
sure whether this approach is worthwhile, as it actually adds more code,
though it might make it easier to understand.


Regards
ChenYu


Chen-Yu Tsai (10):
  clk: sunxi: factors: Make struct clk_factors_config table const
  clk: sunxi: factors: Add clk cleanup in sunxi_factors_register() error
path
  clk: sunxi: factors: Add unregister function
  clk: sunxi: unmap registers in sunxi_factors_clk_setup if register
call fails
  clk: sunxi: factors: Consolidate get_factors parameters into a struct
  clk: sunxi: factors: Support custom formulas
  clk: sunxi: factors: Drop round_rate from clk ops
  clk: sunxi: rewrite sun6i-a31-ahb1-clk using factors clk with custom
recalc
  clk: sunxi: rewrite sun6i-ar100 using factors clk
  clk: sunxi: rewrite sun8i-a23-mbus-clk using the simpler composite clk

Maxime Ripard (1):
  clk: composite: Add unregister function

 drivers/clk/clk-composite.c |  15 +
 drivers/clk/sunxi/clk-factors.c | 127 ++---
 drivers/clk/sunxi/clk-factors.h |  25 +-
 drivers/clk/sunxi/clk-mod0.c|  22 +-
 drivers/clk/sunxi/clk-sun6i-ar100.c | 235 
 drivers/clk/sunxi/clk-sun8i-mbus.c  | 126 +
 drivers/clk/sunxi/clk-sun9i-core.c  |  85 ++
 drivers/clk/sunxi/clk-sunxi.c   | 540 +---
 include/linux/clk-provider.h|   1 +
 9 files changed, 492 insertions(+), 684 deletions(-)

-- 
2.7.0

-- 
You received this message because you are subscribed to the Google Groups 
"linux-sunxi" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to linux-sunxi+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


[linux-sunxi] Re: [PATCH v7 04/10] mfd: axp20x: Add missing copyright notice

2016-01-25 Thread Maxime Ripard
Hi Lee,

On Mon, Jan 25, 2016 at 02:39:57PM +, Lee Jones wrote:
> On Wed, 13 Jan 2016, Chen-Yu Tsai wrote:
> 
> > When the driver was merged, the original author did not include a proper
> > copyright notice. This patch adds the notice, backdated to when the
> > driver was merged.
> 
> This is very wordy. 
> 
> "Supply a backdated copyright notice."
> 
> > Cc: Carlo Caione 
> > Signed-off-by: Chen-Yu Tsai 
> > ---
> > 
> > New patch in v7.
> > 
> > ---
> >  drivers/mfd/axp20x.c | 2 ++
> >  1 file changed, 2 insertions(+)
> 
> Patch looks fine though:
> 
> Acked-by: Lee Jones 

How do you want to merge these patches ?

AFAIK, it's mostly MFD patches that could go through your tree, so
feel free to apply them, I'll apply the DT parts.

Thanks!
Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com

-- 
You received this message because you are subscribed to the Google Groups 
"linux-sunxi" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to linux-sunxi+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


signature.asc
Description: Digital signature


[linux-sunxi] Re: [PATCH v7 04/10] mfd: axp20x: Add missing copyright notice

2016-01-25 Thread Lee Jones
On Wed, 13 Jan 2016, Chen-Yu Tsai wrote:

> When the driver was merged, the original author did not include a proper
> copyright notice. This patch adds the notice, backdated to when the
> driver was merged.

This is very wordy. 

"Supply a backdated copyright notice."

> Cc: Carlo Caione 
> Signed-off-by: Chen-Yu Tsai 
> ---
> 
> New patch in v7.
> 
> ---
>  drivers/mfd/axp20x.c | 2 ++
>  1 file changed, 2 insertions(+)

Patch looks fine though:

Acked-by: Lee Jones 

> diff --git a/drivers/mfd/axp20x.c b/drivers/mfd/axp20x.c
> index 3e186f2dcac3..cec51e689d1d 100644
> --- a/drivers/mfd/axp20x.c
> +++ b/drivers/mfd/axp20x.c
> @@ -5,6 +5,8 @@
>   * converters, LDOs, multiple 12-bit ADCs of voltage, current and temperature
>   * as well as configurable GPIOs.
>   *
> + * Copyright (C) 2014 Carlo Caione
> + *
>   * Author: Carlo Caione 
>   *
>   * This program is free software; you can redistribute it and/or modify

-- 
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org │ Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog

-- 
You received this message because you are subscribed to the Google Groups 
"linux-sunxi" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to linux-sunxi+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


[linux-sunxi] Re: [PATCH v7 05/10] mfd: axp20x: Split the driver into core and i2c bits

2016-01-25 Thread Lee Jones
On Wed, 13 Jan 2016, Chen-Yu Tsai wrote:

> The axp20x driver assumes the device is i2c based. This is not the
> case with later chips, which use a proprietary 2 wire serial bus
> by Allwinner called "Reduced Serial Bus".
> 
> This patch follows the example of mfd/wm831x and splits it into
> an interface independent core, and an i2c specific glue layer.
> MFD_AXP20X and the new MFD_AXP20X_I2C are changed to tristate
> symbols, allowing the driver to be built as modules.
> 
> Whitespace and other style errors in the moved i2c specific code
> have been fixed. Included but unused header files are removed as
> well.
> 
> Signed-off-by: Chen-Yu Tsai 
> ---
> 
> Changes since v6:
> 
>   - Drop filenames from file headers
> 
> ---
>  drivers/mfd/Kconfig|  14 +++---
>  drivers/mfd/Makefile   |   1 +
>  drivers/mfd/axp20x-i2c.c   | 104 
> +
>  drivers/mfd/axp20x.c   |  90 +++
>  include/linux/mfd/axp20x.h |  33 +-
>  5 files changed, 161 insertions(+), 81 deletions(-)
>  create mode 100644 drivers/mfd/axp20x-i2c.c

Acked-by: Lee Jones 

> diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
> index 4d92df6ef9fe..804cd3dcce32 100644
> --- a/drivers/mfd/Kconfig
> +++ b/drivers/mfd/Kconfig
> @@ -91,14 +91,18 @@ config MFD_BCM590XX
> Support for the BCM590xx PMUs from Broadcom
>  
>  config MFD_AXP20X
> - bool "X-Powers AXP20X"
> + tristate
>   select MFD_CORE
> - select REGMAP_I2C
>   select REGMAP_IRQ
> - depends on I2C=y
> +
> +config MFD_AXP20X_I2C
> + tristate "X-Powers AXP series PMICs with I2C"
> + select MFD_AXP20X
> + select REGMAP_I2C
> + depends on I2C
>   help
> -   If you say Y here you get support for the X-Powers AXP202, AXP209 and
> -   AXP288 power management IC (PMIC).
> +   If you say Y here you get support for the X-Powers AXP series power
> +   management ICs (PMICs) controlled with I2C.
> This driver include only the core APIs. You have to select individual
> components like regulators or the PEK (Power Enable Key) under the
> corresponding menus.
> diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
> index a8b76b81b467..a6913007d667 100644
> --- a/drivers/mfd/Makefile
> +++ b/drivers/mfd/Makefile
> @@ -107,6 +107,7 @@ obj-$(CONFIG_PMIC_DA9052) += da9052-core.o
>  obj-$(CONFIG_MFD_DA9052_SPI) += da9052-spi.o
>  obj-$(CONFIG_MFD_DA9052_I2C) += da9052-i2c.o
>  obj-$(CONFIG_MFD_AXP20X) += axp20x.o
> +obj-$(CONFIG_MFD_AXP20X_I2C) += axp20x-i2c.o
>  
>  obj-$(CONFIG_MFD_LP3943) += lp3943.o
>  obj-$(CONFIG_MFD_LP8788) += lp8788.o lp8788-irq.o
> diff --git a/drivers/mfd/axp20x-i2c.c b/drivers/mfd/axp20x-i2c.c
> new file mode 100644
> index ..b1b865822c07
> --- /dev/null
> +++ b/drivers/mfd/axp20x-i2c.c
> @@ -0,0 +1,104 @@
> +/*
> + * I2C driver for the X-Powers' Power Management ICs
> + *
> + * AXP20x typically comprises an adaptive USB-Compatible PWM charger, BUCK 
> DC-DC
> + * converters, LDOs, multiple 12-bit ADCs of voltage, current and temperature
> + * as well as configurable GPIOs.
> + *
> + * This driver supports the I2C variants.
> + *
> + * Copyright (C) 2014 Carlo Caione
> + *
> + * Author: Carlo Caione 
> + *
> + * 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 
> +
> +static int axp20x_i2c_probe(struct i2c_client *i2c,
> + const struct i2c_device_id *id)
> +{
> + struct axp20x_dev *axp20x;
> + int ret;
> +
> + axp20x = devm_kzalloc(>dev, sizeof(*axp20x), GFP_KERNEL);
> + if (!axp20x)
> + return -ENOMEM;
> +
> + axp20x->dev = >dev;
> + axp20x->irq = i2c->irq;
> + dev_set_drvdata(axp20x->dev, axp20x);
> +
> + ret = axp20x_match_device(axp20x);
> + if (ret)
> + return ret;
> +
> + axp20x->regmap = devm_regmap_init_i2c(i2c, axp20x->regmap_cfg);
> + if (IS_ERR(axp20x->regmap)) {
> + ret = PTR_ERR(axp20x->regmap);
> + dev_err(>dev, "regmap init failed: %d\n", ret);
> + return ret;
> + }
> +
> + return axp20x_device_probe(axp20x);
> +}
> +
> +static int axp20x_i2c_remove(struct i2c_client *i2c)
> +{
> + struct axp20x_dev *axp20x = i2c_get_clientdata(i2c);
> +
> + return axp20x_device_remove(axp20x);
> +}
> +
> +static const struct of_device_id axp20x_i2c_of_match[] = {
> + { .compatible = "x-powers,axp152", .data = (void *)AXP152_ID },
> + { .compatible = "x-powers,axp202", .data = (void *)AXP202_ID },
> + { .compatible = "x-powers,axp209", .data = (void *)AXP209_ID },
> + { .compatible = 

[linux-sunxi] Re: [PATCH v2 13/26] drm/fb_cma_helper: Remove implicit call to disable_unused_functions

2016-01-25 Thread Laurent Pinchart
Hi Daniel,

On Monday 25 January 2016 08:29:38 Daniel Vetter wrote:
> On Mon, Jan 25, 2016 at 12:19:27AM +0200, Laurent Pinchart wrote:
> > On Friday 15 January 2016 11:17:30 Daniel Vetter wrote:
> >> On Fri, Jan 15, 2016 at 01:13:05AM +0200, Laurent Pinchart wrote:
> >>> On Thursday 14 January 2016 16:24:56 Maxime Ripard wrote:
>  The drm_fbdev_cma_init function always calls the
>  drm_helper_disable_unused_functions. Since it's part of the usual
>  probe process, all the drivers using that helper will end up having
>  their encoder and CRTC disable functions called at probe if their
>  device has not been reported as enabled.
>  
>  This could be fixed by reading out from the registers the current
>  state of the device if it is enabled, but even that will not handle
>  the case where the device is actually disabled.
>  
>  Moreover, the drivers using the atomic modesetting expect that their
>  enable and disable callback to be called when the device is already
>  enabled or disabled (respectively).
>  
>  We can however fix this issue by moving the call to
>  drm_helper_disable_unused_functions out of drm_fbdev_cma_init and
>  make the drivers needing it (all the drivers calling
>  drm_fbdev_cma_init and not using the atomic modesetting) explicitly
>  call it.
> >>> 
> >>> I'd rather add it to all drivers that call drm_fbdev_cma_init(). All
> >>> the atomic ones must have special code to cope with it that could be
> >>> rendered useless by the removal of the
> >>> drm_helper_disable_unused_functions() call. That code should be
> >>> removed too, and it would be easier to check drivers one by one and
> >>> fixing them individually (outside of this patch series, unless you
> >>> insist ;-)) when removing the explicit
> >>> drm_helper_disable_unused_functions() call.
> >> 
> >> I had the same thought, but figured there's really no good reason ever
> >> to do this. I suspect most of that disable_unused_function stuff we have
> >> all over is supreme cargo-cult anyway ;-)
> > 
> > I'm not sure you got my point. Yes, the
> > drm_helper_disable_unused_functions() call should be removed from atomic
> > drivers, but that will leave support code added for the sole reason of
> > avoiding the crash in the drivers. That code will likely not be noticed
> > and will stay there rotting. If we added
> > drm_helper_disable_unused_functions() calls to all atomic drivers then
> > driver authors will hopefully check carefully if there's any support code
> > that can be removed when removing the function call. It would act as a
> > kind of FIXME reminder.
> 
> drm_helper_disable_unused_functions() already prefers the ->disable
> callbacks over dpms, like atomic helpers. I don't think there's any dead
> code due to this change. The problem was that driver/hw blew up since it
> was disabled when the hw was off already.

The rcar-du-drm driver keeps an internal CRTC enabled state for just this 
purpose. I expect other drivers to implement something similar that can be 
removed after dropping the drm_helper_disable_unused_functions() calls.

-- 
Regards,

Laurent Pinchart

-- 
You received this message because you are subscribed to the Google Groups 
"linux-sunxi" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to linux-sunxi+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: [linux-sunxi] Re: GSL3680 thread

2016-01-25 Thread 'destroyedlolo' via linux-sunxi

Le lundi 25 janvier 2016 19:06:53 UTC+1, Gregor Riepl a écrit :
>
>
> According to the very limited knowledge I have about Silead controllers, 
> the 
> GSL3680 should have roughly the same interface as the GSL1680, even if it 
> doesn't have a control pin. That also applies to the firmware loading 
> process. 
> Are you sure you have the right firmware? 
>

It fails before FW loading as below.


> Maybe you could do some testing with https://github.com/rastersoft/gsl1680 
> and 
> see if you can get it working by skipping the GPIO stuff? 
>

I did a try with Joe's one (https://github.com/jabjoe/sunxi-gslx680) but it 
is failling with error

   1. [   91.366514] incomplete xfer (0xff)
   2. [   91.366532] reset_chip: gsl_ts_write 1 fail!
   3. [   91.366541] init_chip: reset_chip fail: -70
   4. [   91.366552] gslx680 1-0040: init_chip failed

 It seems it's due to I2C bus error and someone on LeMaker forum's pointed 
to me I have probably to switch to 400 khz bus.
 Another thing I have to do, is to check to which GPIO SHUTDOWN pin is 
connected ... but for that, I need to tears down my device (no time yet : 
ski :) ).

But if I skip GPIO stuff, how the device will turn on loading phase ? Is 
writing to the device enough ?

-- 
You received this message because you are subscribed to the Google Groups 
"linux-sunxi" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to linux-sunxi+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


[linux-sunxi] Re: [PATCH v3 00/12] pwm: add support for atomic update

2016-01-25 Thread Thierry Reding
On Mon, Jan 25, 2016 at 08:28:31AM -0800, Doug Anderson wrote:
> Thierry and Boris,
> 
> On Tue, Nov 10, 2015 at 9:34 AM, Thierry Reding
>  wrote:
> > On Mon, Oct 19, 2015 at 12:12:12PM +0200, Heiko Stübner wrote:
> >> Hi Thierry,
> >>
> >> Am Montag, 21. September 2015, 11:33:17 schrieb Boris Brezillon:
> >> > Hello,
> >> >
> >> > This series adds support for atomic PWM update, or IOW, the capability
> >> > to update all the parameters of a PWM device (enabled/disabled, period,
> >> > duty and polarity) in one go.
> >>
> >> is anything more blocking this series? It's now sitting on the lists for
> >> nearly a month and everybody seems happy with it, so it would be really 
> >> nice
> >> to have in mainline :-) .
> >>
> >> Especially as this also makes it possible for Rockchip Chromebooks to 
> >> actually
> >> control the logic-regulator that is implemented as pwm-regulator there.
> >
> > Last time I tried to put this into linux-next I got immediately
> > bombarded by a number of build failures, so I backed things out. The
> > current plan is to give this another try after v4.4-rc1.
> 
> We're now into the 4.5 timeframe.  Does anyone have a concrete set of
> things that need to happen before this patch series makes it into
> mainline?

I think the current status is that we're more or less blocked on the
decision on what the reset state of the PWM should be. The question is
what to do if the PWM hardware readout differs from the settings found
in DT.

> From searching I see that the latest version of this series is v4 and
> there are a smattering of comments on the 24-patch series.  Presumably
> a v5 needs to be posted to address those things.
> 
> ...but it looks like the big sticking point is that Boris is waiting
> for a response to his questions in
> .  Thierry: can you give
> Boris some direction for what else he needs to do?  We need to come up
> with _some_ solution since this series gets us much better support for
> PWM regulators.  Without this series or some other solution, PWM
> regulators aren't usable in mainline on any system that uses them for
> system-critical rails.  Nearly all Rockchip reference boards and
> shipping devices uses a PWM regulator for the system-critidal "logic"
> rail.  That means any patches which need to change this rail in Linux
> are blocked.

I really don't understand this design decision. I presume that the PWM
controlling this system-critical logic is driven by the SoC? So if the
regulator is system-critical, doesn't that make it a chicken and egg
problem? How can the SoC turn the PWM on if it doesn't have power? But
perhaps I'm completely misunderstanding what you're saying. Perhaps if
somebody could summarize how exactly this works, it would help better
understand the requirements or what's the correct thing to do.

> If there's already been off-list discussion and Boris already knows
> what the next steps are then my apologies and I'll wait patiently for
> the next series.  ;)

I don't think we reached a conclusion on this. And to be honest, I'm not
sure what the right way forward is in this situation. So in order to
make some forward progress I suggest we start a discussion, hopefully
that will clarify the situation and help lead to the conclusion. Let me
recap where we are:

Boris' series has two goals: 1) allow seamless hand-off from firmware to
kernel of a PWM channel and 2) apply changes to a regulator in a single
atomic operation. To achieve this the concept of PWM state is introduced
which encapsulates the settings of a PWM channel. On driver probe the
current state will be read from hardware and when one or more parameters
are to be changed, the current state is duplicated, the new values set
in the state and the new state applied.

The problem that we've encountered is that since the PWM parameters are
specified in DT (or board files), there is the possibility of the PWM
hardware state and the board parameters disagreeing. To resolve such
situations there must be a point in time where both hardware state and
software state must be synchronized. Now the most straightforward way to
do that would be to simply apply the software state and be done with it.
However the software state initially lacks the duty cycle because it is
a parameter that usually depends on the use-case (for backlight for
instance it controls the brightness, for regulators it controls the
output voltage, ...).

Applying the software state as-is also means that there's no reason at
all to read out the hardware state in the first place, because it will
simply be discarded.

An alternative would be to discard the software state and trust the
hardware to be configured correctly. That's somewhat risky because we
don't know if the hardware is properly configured. Or Linux might have
different requirements from the firmware and hence needs to configure
the PWM differently.

Neither of the above are very attractive options. 

[linux-sunxi] Re: [PATCH v3 00/12] pwm: add support for atomic update

2016-01-25 Thread 'Doug Anderson' via linux-sunxi
Thierry and Boris,

On Tue, Nov 10, 2015 at 9:34 AM, Thierry Reding
 wrote:
> On Mon, Oct 19, 2015 at 12:12:12PM +0200, Heiko Stübner wrote:
>> Hi Thierry,
>>
>> Am Montag, 21. September 2015, 11:33:17 schrieb Boris Brezillon:
>> > Hello,
>> >
>> > This series adds support for atomic PWM update, or IOW, the capability
>> > to update all the parameters of a PWM device (enabled/disabled, period,
>> > duty and polarity) in one go.
>>
>> is anything more blocking this series? It's now sitting on the lists for
>> nearly a month and everybody seems happy with it, so it would be really nice
>> to have in mainline :-) .
>>
>> Especially as this also makes it possible for Rockchip Chromebooks to 
>> actually
>> control the logic-regulator that is implemented as pwm-regulator there.
>
> Last time I tried to put this into linux-next I got immediately
> bombarded by a number of build failures, so I backed things out. The
> current plan is to give this another try after v4.4-rc1.

We're now into the 4.5 timeframe.  Does anyone have a concrete set of
things that need to happen before this patch series makes it into
mainline?

>From searching I see that the latest version of this series is v4 and
there are a smattering of comments on the 24-patch series.  Presumably
a v5 needs to be posted to address those things.

...but it looks like the big sticking point is that Boris is waiting
for a response to his questions in
.  Thierry: can you give
Boris some direction for what else he needs to do?  We need to come up
with _some_ solution since this series gets us much better support for
PWM regulators.  Without this series or some other solution, PWM
regulators aren't usable in mainline on any system that uses them for
system-critical rails.  Nearly all Rockchip reference boards and
shipping devices uses a PWM regulator for the system-critidal "logic"
rail.  That means any patches which need to change this rail in Linux
are blocked.

If there's already been off-list discussion and Boris already knows
what the next steps are then my apologies and I'll wait patiently for
the next series.  ;)

Thanks!

-Doug

-- 
You received this message because you are subscribed to the Google Groups 
"linux-sunxi" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to linux-sunxi+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


[linux-sunxi] Re: [PATCH v7 07/10] mfd: axp20x: Add support for RSB based AXP223 PMIC

2016-01-25 Thread Lee Jones
On Wed, 13 Jan 2016, Chen-Yu Tsai wrote:

> The AXP223 is a new PMIC commonly paired with Allwinner A23/A33 SoCs.
> It is functionally identical to AXP221; only the regulator default
> voltage/status and the external host interface are different.
> 
> Signed-off-by: Chen-Yu Tsai 
> ---
> 
> Changes since v6:
> 
>   - Drop filename from file header
>   - Use generic dev_set_drvdata()
>   - Properly sort #include statements
>   - Add copyright notice
> 
> ---
>  drivers/mfd/Kconfig| 11 +++
>  drivers/mfd/Makefile   |  1 +
>  drivers/mfd/axp20x-rsb.c   | 80 
> ++
>  drivers/mfd/axp20x.c   |  2 ++
>  include/linux/mfd/axp20x.h |  1 +
>  5 files changed, 95 insertions(+)
>  create mode 100644 drivers/mfd/axp20x-rsb.c

Acked-by: Lee Jones 

> diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
> index 804cd3dcce32..13c565103e96 100644
> --- a/drivers/mfd/Kconfig
> +++ b/drivers/mfd/Kconfig
> @@ -107,6 +107,17 @@ config MFD_AXP20X_I2C
> components like regulators or the PEK (Power Enable Key) under the
> corresponding menus.
>  
> +config MFD_AXP20X_RSB
> + tristate "X-Powers AXP series PMICs with RSB"
> + select MFD_AXP20X
> + depends on SUNXI_RSB
> + help
> +   If you say Y here you get support for the X-Powers AXP series power
> +   management ICs (PMICs) controlled with RSB.
> +   This driver include only the core APIs. You have to select individual
> +   components like regulators or the PEK (Power Enable Key) under the
> +   corresponding menus.
> +
>  config MFD_CROS_EC
>   tristate "ChromeOS Embedded Controller"
>   select MFD_CORE
> diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
> index a6913007d667..caea6637d5e8 100644
> --- a/drivers/mfd/Makefile
> +++ b/drivers/mfd/Makefile
> @@ -108,6 +108,7 @@ obj-$(CONFIG_MFD_DA9052_SPI)  += da9052-spi.o
>  obj-$(CONFIG_MFD_DA9052_I2C) += da9052-i2c.o
>  obj-$(CONFIG_MFD_AXP20X) += axp20x.o
>  obj-$(CONFIG_MFD_AXP20X_I2C) += axp20x-i2c.o
> +obj-$(CONFIG_MFD_AXP20X_RSB) += axp20x-rsb.o
>  
>  obj-$(CONFIG_MFD_LP3943) += lp3943.o
>  obj-$(CONFIG_MFD_LP8788) += lp8788.o lp8788-irq.o
> diff --git a/drivers/mfd/axp20x-rsb.c b/drivers/mfd/axp20x-rsb.c
> new file mode 100644
> index ..28c20247c112
> --- /dev/null
> +++ b/drivers/mfd/axp20x-rsb.c
> @@ -0,0 +1,80 @@
> +/*
> + * RSB driver for the X-Powers' Power Management ICs
> + *
> + * AXP20x typically comprises an adaptive USB-Compatible PWM charger, BUCK 
> DC-DC
> + * converters, LDOs, multiple 12-bit ADCs of voltage, current and temperature
> + * as well as configurable GPIOs.
> + *
> + * This driver supports the RSB variants.
> + *
> + * Copyright (C) 2015 Chen-Yu Tsai
> + *
> + * Author: Chen-Yu Tsai 
> + *
> + * 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 
> +
> +static int axp20x_rsb_probe(struct sunxi_rsb_device *rdev)
> +{
> + struct axp20x_dev *axp20x;
> + int ret;
> +
> + axp20x = devm_kzalloc(>dev, sizeof(*axp20x), GFP_KERNEL);
> + if (!axp20x)
> + return -ENOMEM;
> +
> + axp20x->dev = >dev;
> + axp20x->irq = rdev->irq;
> + dev_set_drvdata(>dev, axp20x);
> +
> + ret = axp20x_match_device(axp20x);
> + if (ret)
> + return ret;
> +
> + axp20x->regmap = devm_regmap_init_sunxi_rsb(rdev, axp20x->regmap_cfg);
> + if (IS_ERR(axp20x->regmap)) {
> + ret = PTR_ERR(axp20x->regmap);
> + dev_err(>dev, "regmap init failed: %d\n", ret);
> + return ret;
> + }
> +
> + return axp20x_device_probe(axp20x);
> +}
> +
> +static int axp20x_rsb_remove(struct sunxi_rsb_device *rdev)
> +{
> + struct axp20x_dev *axp20x = sunxi_rsb_device_get_drvdata(rdev);
> +
> + return axp20x_device_remove(axp20x);
> +}
> +
> +static const struct of_device_id axp20x_rsb_of_match[] = {
> + { .compatible = "x-powers,axp223", .data = (void *)AXP223_ID },
> + { },
> +};
> +MODULE_DEVICE_TABLE(of, axp20x_rsb_of_match);
> +
> +static struct sunxi_rsb_driver axp20x_rsb_driver = {
> + .driver = {
> + .name   = "axp20x-rsb",
> + .of_match_table = of_match_ptr(axp20x_rsb_of_match),
> + },
> + .probe  = axp20x_rsb_probe,
> + .remove = axp20x_rsb_remove,
> +};
> +module_sunxi_rsb_driver(axp20x_rsb_driver);
> +
> +MODULE_DESCRIPTION("PMIC MFD sunXi RSB driver for AXP20X");
> +MODULE_AUTHOR("Chen-Yu Tsai ");
> +MODULE_LICENSE("GPL v2");
> diff --git a/drivers/mfd/axp20x.c b/drivers/mfd/axp20x.c
> index 3054ea4b95e8..a57d6e940610 100644
> --- a/drivers/mfd/axp20x.c
> +++ b/drivers/mfd/axp20x.c
> @@ -35,6 +35,7 @@ static 

[linux-sunxi] Re: [PATCH v3 00/12] pwm: add support for atomic update

2016-01-25 Thread Boris Brezillon
Hi Thierry,

On Mon, 25 Jan 2016 18:08:55 +0100
Thierry Reding  wrote:

> On Mon, Jan 25, 2016 at 08:28:31AM -0800, Doug Anderson wrote:
> > Thierry and Boris,
> > 
> > On Tue, Nov 10, 2015 at 9:34 AM, Thierry Reding
> >  wrote:
> > > On Mon, Oct 19, 2015 at 12:12:12PM +0200, Heiko Stübner wrote:
> > >> Hi Thierry,
> > >>
> > >> Am Montag, 21. September 2015, 11:33:17 schrieb Boris Brezillon:
> > >> > Hello,
> > >> >
> > >> > This series adds support for atomic PWM update, or IOW, the capability
> > >> > to update all the parameters of a PWM device (enabled/disabled, period,
> > >> > duty and polarity) in one go.
> > >>
> > >> is anything more blocking this series? It's now sitting on the lists for
> > >> nearly a month and everybody seems happy with it, so it would be really 
> > >> nice
> > >> to have in mainline :-) .
> > >>
> > >> Especially as this also makes it possible for Rockchip Chromebooks to 
> > >> actually
> > >> control the logic-regulator that is implemented as pwm-regulator there.
> > >
> > > Last time I tried to put this into linux-next I got immediately
> > > bombarded by a number of build failures, so I backed things out. The
> > > current plan is to give this another try after v4.4-rc1.
> > 
> > We're now into the 4.5 timeframe.  Does anyone have a concrete set of
> > things that need to happen before this patch series makes it into
> > mainline?
> 
> I think the current status is that we're more or less blocked on the
> decision on what the reset state of the PWM should be. The question is
> what to do if the PWM hardware readout differs from the settings found
> in DT.

I think I already explained my PoV regarding the default/reference
setting (or what you later call the software state).
To me, this has never matched the state of the PWM device, it's just a
reference duty-cycle and polarity configuration that PWM users can
decide to apply or not. Currently, there's no mechanism to apply the
reference PWM config when a user request a PWM (which is the only
moment we could be able to apply this config, since reference configs
are per users and not attached to the PWM device itself).

All I'm trying to do in this series is teach some PWM users to make use
of hardware read-out state instead of blindly applying a default config
that can generate glitches in the PWM signal.

> 
> > From searching I see that the latest version of this series is v4 and
> > there are a smattering of comments on the 24-patch series.  Presumably
> > a v5 needs to be posted to address those things.
> > 
> > ...but it looks like the big sticking point is that Boris is waiting
> > for a response to his questions in
> > .  Thierry: can you give
> > Boris some direction for what else he needs to do?  We need to come up
> > with _some_ solution since this series gets us much better support for
> > PWM regulators.  Without this series or some other solution, PWM
> > regulators aren't usable in mainline on any system that uses them for
> > system-critical rails.  Nearly all Rockchip reference boards and
> > shipping devices uses a PWM regulator for the system-critidal "logic"
> > rail.  That means any patches which need to change this rail in Linux
> > are blocked.
> 
> I really don't understand this design decision. I presume that the PWM
> controlling this system-critical logic is driven by the SoC? So if the
> regulator is system-critical, doesn't that make it a chicken and egg
> problem? How can the SoC turn the PWM on if it doesn't have power? But
> perhaps I'm completely misunderstanding what you're saying. Perhaps if
> somebody could summarize how exactly this works, it would help better
> understand the requirements or what's the correct thing to do.
> 
> > If there's already been off-list discussion and Boris already knows
> > what the next steps are then my apologies and I'll wait patiently for
> > the next series.  ;)
> 
> I don't think we reached a conclusion on this. And to be honest, I'm not
> sure what the right way forward is in this situation. So in order to
> make some forward progress I suggest we start a discussion, hopefully
> that will clarify the situation and help lead to the conclusion. Let me
> recap where we are:
> 
> Boris' series has two goals: 1) allow seamless hand-off from firmware to
> kernel of a PWM channel and 2) apply changes to a regulator in a single
> atomic operation. To achieve this the concept of PWM state is introduced
> which encapsulates the settings of a PWM channel. On driver probe the
> current state will be read from hardware and when one or more parameters
> are to be changed, the current state is duplicated, the new values set
> in the state and the new state applied.
> 
> The problem that we've encountered is that since the PWM parameters are
> specified in DT (or board files), there is the possibility of the PWM
> hardware state and the board parameters disagreeing. To 

Re: [linux-sunxi] Re: GSL3680 thread

2016-01-25 Thread Gregor Riepl
> The only information I found came from the datasheet I found on your site, I
> have translated using Google and some Chinese friends.
> Clearly, GSL1680's firmware loading procedure doesn't apply as the control pin
> doesn't exists.
> 
> So, for them moment, it's a dead end :(

According to the very limited knowledge I have about Silead controllers, the
GSL3680 should have roughly the same interface as the GSL1680, even if it
doesn't have a control pin. That also applies to the firmware loading process.
Are you sure you have the right firmware?

Maybe you could do some testing with https://github.com/rastersoft/gsl1680 and
see if you can get it working by skipping the GPIO stuff?

-- 
You received this message because you are subscribed to the Google Groups 
"linux-sunxi" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to linux-sunxi+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


[linux-sunxi] Re: [PATCH v3 00/12] pwm: add support for atomic update

2016-01-25 Thread 'Doug Anderson' via linux-sunxi
Hi,

On Mon, Jan 25, 2016 at 9:08 AM, Thierry Reding
 wrote:
> I really don't understand this design decision. I presume that the PWM
> controlling this system-critical logic is driven by the SoC? So if the
> regulator is system-critical, doesn't that make it a chicken and egg
> problem? How can the SoC turn the PWM on if it doesn't have power? But
> perhaps I'm completely misunderstanding what you're saying. Perhaps if
> somebody could summarize how exactly this works, it would help better
> understand the requirements or what's the correct thing to do.

Sure, here's how the dang thing works, as I understand it.

First, an overview of PWM regulator in general (maybe you know this,
but to get us on the same page).  There's an external regulator on the
system.  Looking on at least one board I see a TLV62565 specifically.

>From the docs of TLV62565, I see it describe the situation as the chip
being able to provide an adjustable output voltage configurable via an
external resistor divider.  In simplified terms words you can adjust
the output voltage of the regulator by tweaking the inputs to one of
its pins.  I'm just a software guy so I can't explain all the details
of it, but the net-net of the situation is is that you can hook this
configuration pin up to the output of a PWM (with a bunch of well
balanced resistors and capacitors) and then you can set the voltage
based on the output of the PWM.


OK, so what happens at bootup?  At bootup most of the pins of the
rk3288 (including the PWM) are configured as inputs with a pull.  The
particular pin hooked up to this PWM has a pulldown.  Remember that
we've got this nicely balanced set of resistors and capacitors hooked
up to the output of our PWM pin?  So what happens when we have this
pin configured as an input?  As I understand it / remember it:

* input w/ no pull: equivalent to 50% duty cycle on the PWM
* input w/ pull down: equivalent to slightly higher voltage than 50%
duty cycle on the PWM
* input w/ pull up: equivalent to slightly lower voltage than 50% duty
cycle on the PWM

On our particular board that means that the rail comes up with roughly
1.1V.  If you drive the PWM at 100% (or set the pin to output high)
you get .86V and if you drive the PWM at 0% (or set the pin to output
low) you get 1.36V.

Now, 1.1V is plenty of voltage to boot the system.  In fact most of
the logic within the SoC can run as low as 0.95V I think.  ...but 0.86
V is not enough to run the logic parts of the system (even at their
default bootup frequencies) 1.1V is _definitely_ not enough to run the
SDRAM memory controller at full speed.


So the bootloader wants to run the system fast so it can boot fast.
It increases the CPU rails (as is typical for a bootloader) and moves
the ARM CPU to 1.8GHz (from the relatively slow boot frequency) and
also raises the logic rail to 1.2V (or I think 1.15 V on systems w/
different memory configs) and inits the SDRAM controller to run at
full speed.  Then it boots Linux.

Note: apparently in U-Boot they actually boot system slower (this was
at least true 1.5 years ago with some reference U-Boot Rockchip
provided).  If I understand correctly they _didn't_ init the SDRAM
controller as full speed in the bootloader and just left the logic
rail at its bootup default.  If everyone had done that then our job
would be "easier" because we wouldn't need to read in the voltage
provided by the bootloader (by reading the PWM and cros-referencing
with our table), though even in that case we'd have to be very careful
not to glitch the line (since .86 V is too low).  Of course all of
those systems are stuck running at a very slow memory speed until
Linux gets DDR Frequency support for Rockchip whereas systems with our
bootloader not only boot faster but also get to use the full memory
speed even without any Linux DDRFreq drivers.


In any case: I think I've demonstrated how a critical system rail can
be using a PWM regulator and how glitching that PWM regulator at boot
time can be catastrophic.  Possibly it's not critical to be able to
"read" the voltage that that bootloader left things configured at
(it's mostly nice for debugging purposes), but it's definitely
important to make sure we don't set it to some default and important
to never glitch it.  Said another way, presumably a DDR Freq driver
would be able to switch the memory controller frequency sanely by
reading the memory controller frequency and using that to figure out
whether it needed to up the logic rail before or after the DDR Freq
change.


>> If there's already been off-list discussion and Boris already knows
>> what the next steps are then my apologies and I'll wait patiently for
>> the next series.  ;)
>
> I don't think we reached a conclusion on this. And to be honest, I'm not
> sure what the right way forward is in this situation. So in order to
> make some forward progress I suggest we start a discussion, hopefully
> that will clarify the situation and help 

[linux-sunxi] Re: [PATCH] clk: sunxi: usb: Sort clk providers by chip family and name

2016-01-25 Thread Maxime Ripard
On Mon, Jan 25, 2016 at 01:55:00PM +0800, Chen-Yu Tsai wrote:
> The latest addition of H3 USB clocks placed them at the bottom. Move it
> before A80 (sun9i), so they are sorted by SoC family then name.
> 
> Signed-off-by: Chen-Yu Tsai 

Applied, thanks!

Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com

-- 
You received this message because you are subscribed to the Google Groups 
"linux-sunxi" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to linux-sunxi+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


signature.asc
Description: Digital signature