* [PATCH 00/10] clk: sunxi: PLL4/5/6, mod0 and mbus support
@ 2013-09-29 3:49 Emilio López
2013-09-29 3:49 ` [PATCH 01/10] clk: sunxi: register factors clocks behind composite Emilio López
` (10 more replies)
0 siblings, 11 replies; 20+ messages in thread
From: Emilio López @ 2013-09-29 3:49 UTC (permalink / raw)
To: linux-arm-kernel
Hi everyone,
This is a followup series to my RFC series from some time ago. It adds
PLL4, PLL5, PLL6 and mod0 support on sun4i, sun5i and sun7i. Additionally,
mbus is supported on sun5i and sun7i. I would like to see this merged for
3.13, so all feedback is welcome :)
Cheers,
Emilio
Emilio L?pez (10):
clk: sunxi: register factors clocks behind composite
clk: sunxi: add gating support to PLL1
ARM: sunxi: add PLL4 support
clk: sunxi: add PLL5 and PLL6 support
ARM: sunxi: add PLL5 and PLL6 support
clk: sunxi: mod0 support
ARM: sun4i: dt: mod0 clocks
ARM: sun5i: dt: mod0 clocks
ARM: sun7i: dt: mod0 clocks
ARM: sunxi: dt: add nodes for the mbus clock
Documentation/devicetree/bindings/clock/sunxi.txt | 5 +-
arch/arm/boot/dts/sun4i-a10.dtsi | 131 +++++++++-
arch/arm/boot/dts/sun5i-a10s.dtsi | 110 +++++++-
arch/arm/boot/dts/sun5i-a13.dtsi | 110 +++++++-
arch/arm/boot/dts/sun7i-a20.dtsi | 145 ++++++++++-
drivers/clk/sunxi/clk-factors.c | 63 +----
drivers/clk/sunxi/clk-factors.h | 16 +-
drivers/clk/sunxi/clk-sunxi.c | 297 +++++++++++++++++++++-
8 files changed, 784 insertions(+), 93 deletions(-)
--
1.8.4
^ permalink raw reply [flat|nested] 20+ messages in thread
* [PATCH 01/10] clk: sunxi: register factors clocks behind composite
2013-09-29 3:49 [PATCH 00/10] clk: sunxi: PLL4/5/6, mod0 and mbus support Emilio López
@ 2013-09-29 3:49 ` Emilio López
2013-09-30 17:03 ` Maxime Ripard
2013-09-29 3:49 ` [PATCH 02/10] clk: sunxi: add gating support to PLL1 Emilio López
` (9 subsequent siblings)
10 siblings, 1 reply; 20+ messages in thread
From: Emilio López @ 2013-09-29 3:49 UTC (permalink / raw)
To: linux-arm-kernel
This commit reworks factors clock registration to be done behind a
composite clock. This allows us to additionally add a gate, mux or
divisors, as it will be needed by some future PLLs.
Signed-off-by: Emilio L?pez <emilio@elopez.com.ar>
---
drivers/clk/sunxi/clk-factors.c | 63 +--------------------------------------
drivers/clk/sunxi/clk-factors.h | 16 +++++-----
drivers/clk/sunxi/clk-sunxi.c | 66 ++++++++++++++++++++++++++++++++++++++---
3 files changed, 72 insertions(+), 73 deletions(-)
diff --git a/drivers/clk/sunxi/clk-factors.c b/drivers/clk/sunxi/clk-factors.c
index f05207a..9e23264 100644
--- a/drivers/clk/sunxi/clk-factors.c
+++ b/drivers/clk/sunxi/clk-factors.c
@@ -30,14 +30,6 @@
* parent - fixed parent. No clk_set_parent support
*/
-struct clk_factors {
- struct clk_hw hw;
- void __iomem *reg;
- struct clk_factors_config *config;
- void (*get_factors) (u32 *rate, u32 parent, u8 *n, u8 *k, u8 *m, u8 *p);
- spinlock_t *lock;
-};
-
#define to_clk_factors(_hw) container_of(_hw, struct clk_factors, hw)
#define SETMASK(len, pos) (((1U << (len)) - 1) << (pos))
@@ -120,61 +112,8 @@ static int clk_factors_set_rate(struct clk_hw *hw, unsigned long rate,
return 0;
}
-static const struct clk_ops clk_factors_ops = {
+const struct clk_ops clk_factors_ops = {
.recalc_rate = clk_factors_recalc_rate,
.round_rate = clk_factors_round_rate,
.set_rate = clk_factors_set_rate,
};
-
-/**
- * clk_register_factors - register a factors clock with
- * the clock framework
- * @dev: device registering this clock
- * @name: name of this clock
- * @parent_name: name of clock's parent
- * @flags: framework-specific flags
- * @reg: register address to adjust factors
- * @config: shift and width of factors n, k, m and p
- * @get_factors: function to calculate the factors for a given frequency
- * @lock: shared register lock for this clock
- */
-struct clk *clk_register_factors(struct device *dev, const char *name,
- const char *parent_name,
- unsigned long flags, void __iomem *reg,
- struct clk_factors_config *config,
- void (*get_factors)(u32 *rate, u32 parent,
- u8 *n, u8 *k, u8 *m, u8 *p),
- spinlock_t *lock)
-{
- struct clk_factors *factors;
- struct clk *clk;
- struct clk_init_data init;
-
- /* allocate the factors */
- factors = kzalloc(sizeof(struct clk_factors), GFP_KERNEL);
- if (!factors) {
- pr_err("%s: could not allocate factors clk\n", __func__);
- return ERR_PTR(-ENOMEM);
- }
-
- init.name = name;
- init.ops = &clk_factors_ops;
- init.flags = flags;
- init.parent_names = (parent_name ? &parent_name : NULL);
- init.num_parents = (parent_name ? 1 : 0);
-
- /* struct clk_factors assignments */
- factors->reg = reg;
- factors->config = config;
- factors->lock = lock;
- factors->hw.init = &init;
- factors->get_factors = get_factors;
-
- /* register the clock */
- clk = clk_register(dev, &factors->hw);
-
- if (IS_ERR(clk))
- kfree(factors);
-
- return clk;
-}
diff --git a/drivers/clk/sunxi/clk-factors.h b/drivers/clk/sunxi/clk-factors.h
index f49851c..02e1a43 100644
--- a/drivers/clk/sunxi/clk-factors.h
+++ b/drivers/clk/sunxi/clk-factors.h
@@ -17,11 +17,13 @@ struct clk_factors_config {
u8 pwidth;
};
-struct clk *clk_register_factors(struct device *dev, const char *name,
- const char *parent_name,
- unsigned long flags, void __iomem *reg,
- struct clk_factors_config *config,
- void (*get_factors) (u32 *rate, u32 parent_rate,
- u8 *n, u8 *k, u8 *m, u8 *p),
- spinlock_t *lock);
+struct clk_factors {
+ struct clk_hw hw;
+ void __iomem *reg;
+ struct clk_factors_config *config;
+ void (*get_factors) (u32 *rate, u32 parent, u8 *n, u8 *k, u8 *m, u8 *p);
+ spinlock_t *lock;
+};
+
+extern const struct clk_ops clk_factors_ops;
#endif
diff --git a/drivers/clk/sunxi/clk-sunxi.c b/drivers/clk/sunxi/clk-sunxi.c
index 83d3eac..5491b1a 100644
--- a/drivers/clk/sunxi/clk-sunxi.c
+++ b/drivers/clk/sunxi/clk-sunxi.c
@@ -256,7 +256,11 @@ static void sun4i_get_apb1_factors(u32 *freq, u32 parent_rate,
* sunxi_factors_clk_setup() - Setup function for factor clocks
*/
+#define SUNXI_FACTORS_MUX_MASK 0x3
+
struct factors_data {
+ int enable;
+ int mux;
struct clk_factors_config *table;
void (*getter) (u32 *rate, u32 parent_rate, u8 *n, u8 *k, u8 *m, u8 *p);
};
@@ -307,16 +311,70 @@ static void __init sunxi_factors_clk_setup(struct device_node *node,
struct factors_data *data)
{
struct clk *clk;
+ struct clk_factors *factors;
+ struct clk_gate *gate = NULL;
+ struct clk_mux *mux = NULL;
+ struct clk_hw *gate_hw = NULL;
+ struct clk_hw *mux_hw = NULL;
const char *clk_name = node->name;
- const char *parent;
+ const char *parents[5];
void *reg;
+ int i = 0;
reg = of_iomap(node, 0);
- parent = of_clk_get_parent_name(node, 0);
+ /* if we have a mux, we will have >1 parents */
+ while (i < 5 && (parents[i] = of_clk_get_parent_name(node, i)) != NULL)
+ i++;
+
+ factors = kzalloc(sizeof(struct clk_factors), GFP_KERNEL);
+ if (!factors)
+ return;
- clk = clk_register_factors(NULL, clk_name, parent, 0, reg,
- data->table, data->getter, &clk_lock);
+ /* 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;
+ }
+
+ /* set up gate properties */
+ gate->reg = reg;
+ gate->bit_idx = data->enable;
+ gate->lock = &clk_lock;
+ gate_hw = &gate->hw;
+ }
+
+ /* 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;
+ }
+
+ /* set up gate properties */
+ mux->reg = reg;
+ mux->shift = data->mux;
+ mux->mask = SUNXI_FACTORS_MUX_MASK;
+ mux->lock = &clk_lock;
+ mux_hw = &mux->hw;
+ }
+
+ /* set up factors properties */
+ factors->reg = reg;
+ factors->config = data->table;
+ factors->get_factors = data->getter;
+ factors->lock = &clk_lock;
+
+ clk = clk_register_composite(NULL, clk_name,
+ parents, i,
+ mux_hw, &clk_mux_ops,
+ &factors->hw, &clk_factors_ops,
+ gate_hw, &clk_gate_ops,
+ i ? 0 : CLK_IS_ROOT);
if (!IS_ERR(clk)) {
of_clk_add_provider(node, of_clk_src_simple_get, clk);
--
1.8.4
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH 02/10] clk: sunxi: add gating support to PLL1
2013-09-29 3:49 [PATCH 00/10] clk: sunxi: PLL4/5/6, mod0 and mbus support Emilio López
2013-09-29 3:49 ` [PATCH 01/10] clk: sunxi: register factors clocks behind composite Emilio López
@ 2013-09-29 3:49 ` Emilio López
2013-09-30 17:05 ` Maxime Ripard
2013-09-29 3:49 ` [PATCH 03/10] ARM: sunxi: add PLL4 support Emilio López
` (8 subsequent siblings)
10 siblings, 1 reply; 20+ messages in thread
From: Emilio López @ 2013-09-29 3:49 UTC (permalink / raw)
To: linux-arm-kernel
This commit adds gating support to PLL1 on the clock driver. This makes
the PLL1 implementation fully compatible with PLL4 as well.
Signed-off-by: Emilio L?pez <emilio@elopez.com.ar>
---
Documentation/devicetree/bindings/clock/sunxi.txt | 2 +-
drivers/clk/sunxi/clk-sunxi.c | 2 ++
2 files changed, 3 insertions(+), 1 deletion(-)
diff --git a/Documentation/devicetree/bindings/clock/sunxi.txt b/Documentation/devicetree/bindings/clock/sunxi.txt
index 00a5c264..7d9245f 100644
--- a/Documentation/devicetree/bindings/clock/sunxi.txt
+++ b/Documentation/devicetree/bindings/clock/sunxi.txt
@@ -7,7 +7,7 @@ This binding uses the common clock binding[1].
Required properties:
- compatible : shall be one of the following:
"allwinner,sun4i-osc-clk" - for a gatable oscillator
- "allwinner,sun4i-pll1-clk" - for the main PLL clock
+ "allwinner,sun4i-pll1-clk" - for the main PLL clock and PLL4
"allwinner,sun6i-a31-pll1-clk" - for the main PLL clock on A31
"allwinner,sun4i-cpu-clk" - for the CPU multiplexer clock
"allwinner,sun4i-axi-clk" - for the AXI clock
diff --git a/drivers/clk/sunxi/clk-sunxi.c b/drivers/clk/sunxi/clk-sunxi.c
index 5491b1a..77b9f57 100644
--- a/drivers/clk/sunxi/clk-sunxi.c
+++ b/drivers/clk/sunxi/clk-sunxi.c
@@ -293,11 +293,13 @@ static struct clk_factors_config sun4i_apb1_config = {
};
static const struct factors_data sun4i_pll1_data __initconst = {
+ .enable = 31,
.table = &sun4i_pll1_config,
.getter = sun4i_get_pll1_factors,
};
static const struct factors_data sun6i_a31_pll1_data __initconst = {
+ .enable = 31,
.table = &sun6i_a31_pll1_config,
.getter = sun6i_a31_get_pll1_factors,
};
--
1.8.4
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH 03/10] ARM: sunxi: add PLL4 support
2013-09-29 3:49 [PATCH 00/10] clk: sunxi: PLL4/5/6, mod0 and mbus support Emilio López
2013-09-29 3:49 ` [PATCH 01/10] clk: sunxi: register factors clocks behind composite Emilio López
2013-09-29 3:49 ` [PATCH 02/10] clk: sunxi: add gating support to PLL1 Emilio López
@ 2013-09-29 3:49 ` Emilio López
2013-09-29 3:49 ` [PATCH 04/10] clk: sunxi: add PLL5 and PLL6 support Emilio López
` (7 subsequent siblings)
10 siblings, 0 replies; 20+ messages in thread
From: Emilio López @ 2013-09-29 3:49 UTC (permalink / raw)
To: linux-arm-kernel
This commit adds the PLL4 definition to the sun4i, sun5i and sun7i
device trees. PLL4 is compatible with PLL1.
Signed-off-by: Emilio L?pez <emilio@elopez.com.ar>
---
arch/arm/boot/dts/sun4i-a10.dtsi | 7 +++++++
arch/arm/boot/dts/sun5i-a10s.dtsi | 7 +++++++
arch/arm/boot/dts/sun5i-a13.dtsi | 7 +++++++
arch/arm/boot/dts/sun7i-a20.dtsi | 7 +++++++
4 files changed, 28 insertions(+)
diff --git a/arch/arm/boot/dts/sun4i-a10.dtsi b/arch/arm/boot/dts/sun4i-a10.dtsi
index c32770a..3272536 100644
--- a/arch/arm/boot/dts/sun4i-a10.dtsi
+++ b/arch/arm/boot/dts/sun4i-a10.dtsi
@@ -66,6 +66,13 @@
clocks = <&osc24M>;
};
+ pll4: pll4 at 01c20018 {
+ #clock-cells = <0>;
+ compatible = "allwinner,sun4i-pll1-clk";
+ reg = <0x01c20018 0x4>;
+ clocks = <&osc24M>;
+ };
+
/* dummy is 200M */
cpu: cpu at 01c20054 {
#clock-cells = <0>;
diff --git a/arch/arm/boot/dts/sun5i-a10s.dtsi b/arch/arm/boot/dts/sun5i-a10s.dtsi
index 3b4a057..92a32ab 100644
--- a/arch/arm/boot/dts/sun5i-a10s.dtsi
+++ b/arch/arm/boot/dts/sun5i-a10s.dtsi
@@ -63,6 +63,13 @@
clocks = <&osc24M>;
};
+ pll4: pll4 at 01c20018 {
+ #clock-cells = <0>;
+ compatible = "allwinner,sun4i-pll1-clk";
+ reg = <0x01c20018 0x4>;
+ clocks = <&osc24M>;
+ };
+
/* dummy is 200M */
cpu: cpu at 01c20054 {
#clock-cells = <0>;
diff --git a/arch/arm/boot/dts/sun5i-a13.dtsi b/arch/arm/boot/dts/sun5i-a13.dtsi
index f6091dc..2f9ba4a 100644
--- a/arch/arm/boot/dts/sun5i-a13.dtsi
+++ b/arch/arm/boot/dts/sun5i-a13.dtsi
@@ -67,6 +67,13 @@
clocks = <&osc24M>;
};
+ pll4: pll4 at 01c20018 {
+ #clock-cells = <0>;
+ compatible = "allwinner,sun4i-pll1-clk";
+ reg = <0x01c20018 0x4>;
+ clocks = <&osc24M>;
+ };
+
/* dummy is 200M */
cpu: cpu at 01c20054 {
#clock-cells = <0>;
diff --git a/arch/arm/boot/dts/sun7i-a20.dtsi b/arch/arm/boot/dts/sun7i-a20.dtsi
index 80559cb..bdbf21e 100644
--- a/arch/arm/boot/dts/sun7i-a20.dtsi
+++ b/arch/arm/boot/dts/sun7i-a20.dtsi
@@ -62,6 +62,13 @@
clocks = <&osc24M>;
};
+ pll4: pll4 at 01c20018 {
+ #clock-cells = <0>;
+ compatible = "allwinner,sun4i-pll1-clk";
+ reg = <0x01c20018 0x4>;
+ clocks = <&osc24M>;
+ };
+
/*
* This is a dummy clock, to be used as placeholder on
* other mux clocks when a specific parent clock is not
--
1.8.4
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH 04/10] clk: sunxi: add PLL5 and PLL6 support
2013-09-29 3:49 [PATCH 00/10] clk: sunxi: PLL4/5/6, mod0 and mbus support Emilio López
` (2 preceding siblings ...)
2013-09-29 3:49 ` [PATCH 03/10] ARM: sunxi: add PLL4 support Emilio López
@ 2013-09-29 3:49 ` Emilio López
2013-09-30 17:21 ` Maxime Ripard
2013-09-29 3:49 ` [PATCH 05/10] ARM: " Emilio López
` (6 subsequent siblings)
10 siblings, 1 reply; 20+ messages in thread
From: Emilio López @ 2013-09-29 3:49 UTC (permalink / raw)
To: linux-arm-kernel
This commit implements PLL5 and PLL6 support on the sunxi clock driver.
These PLLs use a similar factor clock, but differ on their outputs.
Signed-off-by: Emilio L?pez <emilio@elopez.com.ar>
---
Documentation/devicetree/bindings/clock/sunxi.txt | 2 +
drivers/clk/sunxi/clk-sunxi.c | 182 +++++++++++++++++++++-
2 files changed, 177 insertions(+), 7 deletions(-)
diff --git a/Documentation/devicetree/bindings/clock/sunxi.txt b/Documentation/devicetree/bindings/clock/sunxi.txt
index 7d9245f..773f3ae 100644
--- a/Documentation/devicetree/bindings/clock/sunxi.txt
+++ b/Documentation/devicetree/bindings/clock/sunxi.txt
@@ -9,6 +9,8 @@ Required properties:
"allwinner,sun4i-osc-clk" - for a gatable oscillator
"allwinner,sun4i-pll1-clk" - for the main PLL clock and PLL4
"allwinner,sun6i-a31-pll1-clk" - for the main PLL clock on A31
+ "allwinner,sun4i-pll5-clk" - for the PLL5 clock
+ "allwinner,sun4i-pll6-clk" - for the PLL6 clock
"allwinner,sun4i-cpu-clk" - for the CPU multiplexer clock
"allwinner,sun4i-axi-clk" - for the AXI clock
"allwinner,sun4i-axi-gates-clk" - for the AXI gates
diff --git a/drivers/clk/sunxi/clk-sunxi.c b/drivers/clk/sunxi/clk-sunxi.c
index 77b9f57..b1210f3 100644
--- a/drivers/clk/sunxi/clk-sunxi.c
+++ b/drivers/clk/sunxi/clk-sunxi.c
@@ -210,6 +210,40 @@ static void sun6i_a31_get_pll1_factors(u32 *freq, u32 parent_rate,
}
/**
+ * sun4i_get_pll5_factors() - calculates n, k factors for PLL5
+ * PLL5 rate is calculated as follows
+ * rate = parent_rate * n * (k + 1)
+ * parent_rate is always 24Mhz
+ */
+
+static void sun4i_get_pll5_factors(u32 *freq, u32 parent_rate,
+ u8 *n, u8 *k, u8 *m, u8 *p)
+{
+ u8 div;
+
+ /* Normalize value to a 24M multiple */
+ div = *freq / 24000000;
+ *freq = 24000000 * div;
+
+ /* we were called to round the frequency, we can now return */
+ if (n == NULL)
+ return;
+
+ if (div < 31)
+ *k = 0;
+ else if (div / 2 < 31)
+ *k = 1;
+ else if (div / 3 < 31)
+ *k = 2;
+ else
+ *k = 3;
+
+ *n = DIV_ROUND_UP(div, (*k+1));
+}
+
+
+
+/**
* sun4i_get_apb1_factors() - calculates m, p factors for APB1
* APB1 rate is calculated as follows
* rate = (parent_rate >> p) / (m + 1);
@@ -285,6 +319,13 @@ static struct clk_factors_config sun6i_a31_pll1_config = {
.mwidth = 2,
};
+static struct clk_factors_config sun4i_pll5_config = {
+ .nshift = 8,
+ .nwidth = 5,
+ .kshift = 4,
+ .kwidth = 2,
+};
+
static struct clk_factors_config sun4i_apb1_config = {
.mshift = 0,
.mwidth = 5,
@@ -304,13 +345,19 @@ static const struct factors_data sun6i_a31_pll1_data __initconst = {
.getter = sun6i_a31_get_pll1_factors,
};
+static const struct factors_data sun4i_pll5_data __initconst = {
+ .enable = 31,
+ .table = &sun4i_pll5_config,
+ .getter = sun4i_get_pll5_factors,
+};
+
static const struct factors_data sun4i_apb1_data __initconst = {
.table = &sun4i_apb1_config,
.getter = sun4i_get_apb1_factors,
};
-static void __init sunxi_factors_clk_setup(struct device_node *node,
- struct factors_data *data)
+static struct clk * __init sunxi_factors_clk_setup(struct device_node *node,
+ const struct factors_data *data)
{
struct clk *clk;
struct clk_factors *factors;
@@ -321,6 +368,7 @@ static void __init sunxi_factors_clk_setup(struct device_node *node,
const char *clk_name = node->name;
const char *parents[5];
void *reg;
+ unsigned long flags;
int i = 0;
reg = of_iomap(node, 0);
@@ -331,14 +379,14 @@ static void __init sunxi_factors_clk_setup(struct device_node *node,
factors = kzalloc(sizeof(struct clk_factors), GFP_KERNEL);
if (!factors)
- return;
+ return NULL;
/* 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;
+ return NULL;
}
/* set up gate properties */
@@ -354,7 +402,7 @@ static void __init sunxi_factors_clk_setup(struct device_node *node,
if (!mux) {
kfree(factors);
kfree(gate);
- return;
+ return NULL;
}
/* set up gate properties */
@@ -371,17 +419,21 @@ static void __init sunxi_factors_clk_setup(struct device_node *node,
factors->get_factors = data->getter;
factors->lock = &clk_lock;
+ /* We should not disable pll5, it powers the RAM */
+ flags = !strcmp("pll5", clk_name) ? CLK_IGNORE_UNUSED : 0;
+
clk = clk_register_composite(NULL, clk_name,
parents, i,
mux_hw, &clk_mux_ops,
&factors->hw, &clk_factors_ops,
- gate_hw, &clk_gate_ops,
- i ? 0 : CLK_IS_ROOT);
+ gate_hw, &clk_gate_ops, flags);
if (!IS_ERR(clk)) {
of_clk_add_provider(node, of_clk_src_simple_get, clk);
clk_register_clkdev(clk, clk_name, NULL);
}
+
+ return clk;
}
@@ -616,6 +668,112 @@ static void __init sunxi_gates_clk_setup(struct device_node *node,
of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
}
+
+
+/**
+ * sunxi_divs_clk_setup() - Setup function for leaf divisors on clocks
+ */
+
+#define SUNXI_DIVS_MAX_QTY 2
+#define SUNXI_DIVISOR_WIDTH 2
+
+struct divs_data {
+ const struct factors_data *factors; /* data for the factor clock */
+ struct {
+ u8 fixed; /* is it a fixed divisor? if not... */
+ struct clk_div_table *table; /* is it a table based divisor? */
+ u8 shift; /* otherwise it's a normal divisor with this shift */
+ u8 pow; /* is it power-of-two based? */
+ } div[SUNXI_DIVS_MAX_QTY];
+};
+
+static struct clk_div_table pll6_sata_table[] = {
+ { .val = 0, .div = 6, },
+ { .val = 1, .div = 12, },
+ { .val = 2, .div = 18, },
+ { .val = 3, .div = 24, },
+ { } /* sentinel */
+};
+
+static const struct divs_data pll5_divs_data __initconst = {
+ .factors = &sun4i_pll5_data,
+ .div = {
+ { .shift = 0, .pow = 0, }, /* M, DDR */
+ { .shift = 16, .pow = 1, }, /* P, other */
+ }
+};
+
+static const struct divs_data pll6_divs_data __initconst = {
+ .factors = &sun4i_pll5_data,
+ .div = {
+ { .shift = 0, .table = pll6_sata_table }, /* M, SATA */
+ { .fixed = 2 }, /* P, other */
+ }
+};
+
+static void __init sunxi_divs_clk_setup(struct device_node *node,
+ struct divs_data *data)
+{
+ struct clk_onecell_data *clk_data;
+ const char *parent = node->name;
+ const char *clk_name;
+ struct clk **clks, *pclk;
+ void *reg;
+ int i = 0;
+ int flags, clkflags;
+
+ /* Set up factor clock that we will be dividing */
+ pclk = sunxi_factors_clk_setup(node, data->factors);
+
+ reg = of_iomap(node, 0);
+
+ clk_data = kmalloc(sizeof(struct clk_onecell_data), GFP_KERNEL);
+ if (!clk_data)
+ return;
+ clks = kzalloc(SUNXI_DIVS_MAX_QTY * sizeof(struct clk *), GFP_KERNEL);
+ if (!clks) {
+ kfree(clk_data);
+ return;
+ }
+ clk_data->clks = clks;
+
+ /* It's not a good idea to have automatic reparenting changing
+ * our RAM clock! */
+ clkflags = !strcmp("pll5", parent) ? 0 : CLK_SET_RATE_PARENT;
+
+ for (i = 0; i < SUNXI_DIVS_MAX_QTY; i++) {
+ if (of_property_read_string_index(node, "clock-output-names",
+ i, &clk_name) != 0)
+ break;
+
+ if (data->div[i].fixed) {
+ clks[i] = clk_register_fixed_factor(NULL, clk_name,
+ parent, clkflags,
+ 1, data->div[i].fixed);
+ } else {
+ flags = data->div[i].pow ? CLK_DIVIDER_POWER_OF_TWO : 0;
+ clks[i] = clk_register_divider_table(NULL, clk_name,
+ parent, clkflags, reg,
+ data->div[i].shift,
+ SUNXI_DIVISOR_WIDTH, flags,
+ data->div[i].table, &clk_lock);
+ }
+
+ WARN_ON(IS_ERR(clk_data->clks[i]));
+ clk_register_clkdev(clks[i], clk_name, NULL);
+ }
+
+ /* The last clock available on the getter is the parent */
+ clks[i++] = pclk;
+
+ /* Adjust to the real max */
+ clk_data->clk_num = i;
+
+ of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
+}
+
+
+
/* Matches for factors clocks */
static const struct of_device_id clk_factors_match[] __initconst = {
{.compatible = "allwinner,sun4i-pll1-clk", .data = &sun4i_pll1_data,},
@@ -633,6 +791,13 @@ static const struct of_device_id clk_div_match[] __initconst = {
{}
};
+/* Matches for divided outputs */
+static const struct of_device_id clk_divs_match[] __initconst = {
+ {.compatible = "allwinner,sun4i-pll5-clk", .data = &pll5_divs_data,},
+ {.compatible = "allwinner,sun4i-pll6-clk", .data = &pll6_divs_data,},
+ {}
+};
+
/* Matches for mux clocks */
static const struct of_device_id clk_mux_match[] __initconst = {
{.compatible = "allwinner,sun4i-cpu-clk", .data = &sun4i_cpu_mux_data,},
@@ -713,6 +878,9 @@ void __init sunxi_init_clocks(void)
/* Register divider clocks */
of_sunxi_table_clock_setup(clk_div_match, sunxi_divider_clk_setup);
+ /* Register divided output clocks */
+ of_sunxi_table_clock_setup(clk_divs_match, sunxi_divs_clk_setup);
+
/* Register mux clocks */
of_sunxi_table_clock_setup(clk_mux_match, sunxi_mux_clk_setup);
--
1.8.4
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH 05/10] ARM: sunxi: add PLL5 and PLL6 support
2013-09-29 3:49 [PATCH 00/10] clk: sunxi: PLL4/5/6, mod0 and mbus support Emilio López
` (3 preceding siblings ...)
2013-09-29 3:49 ` [PATCH 04/10] clk: sunxi: add PLL5 and PLL6 support Emilio López
@ 2013-09-29 3:49 ` Emilio López
2013-09-29 3:49 ` [PATCH 06/10] clk: sunxi: mod0 support Emilio López
` (5 subsequent siblings)
10 siblings, 0 replies; 20+ messages in thread
From: Emilio López @ 2013-09-29 3:49 UTC (permalink / raw)
To: linux-arm-kernel
This commit adds PLL5 and PLL6 nodes to the sun4i, sun5i and sun7i
device trees.
Signed-off-by: Emilio L?pez <emilio@elopez.com.ar>
---
arch/arm/boot/dts/sun4i-a10.dtsi | 19 +++++++++++++++++--
arch/arm/boot/dts/sun5i-a10s.dtsi | 19 +++++++++++++++++--
arch/arm/boot/dts/sun5i-a13.dtsi | 19 +++++++++++++++++--
arch/arm/boot/dts/sun7i-a20.dtsi | 28 ++++++++++++++++------------
4 files changed, 67 insertions(+), 18 deletions(-)
diff --git a/arch/arm/boot/dts/sun4i-a10.dtsi b/arch/arm/boot/dts/sun4i-a10.dtsi
index 3272536..94b6fbb 100644
--- a/arch/arm/boot/dts/sun4i-a10.dtsi
+++ b/arch/arm/boot/dts/sun4i-a10.dtsi
@@ -73,6 +73,22 @@
clocks = <&osc24M>;
};
+ pll5: pll5 at 01c20020 {
+ #clock-cells = <1>;
+ compatible = "allwinner,sun4i-pll5-clk";
+ reg = <0x01c20020 0x4>;
+ clocks = <&osc24M>;
+ clock-output-names = "pll5_ddr", "pll5_other";
+ };
+
+ pll6: pll6 at 01c20028 {
+ #clock-cells = <1>;
+ compatible = "allwinner,sun4i-pll6-clk";
+ reg = <0x01c20028 0x4>;
+ clocks = <&osc24M>;
+ clock-output-names = "pll6_sata", "pll6_other", "pll6";
+ };
+
/* dummy is 200M */
cpu: cpu at 01c20054 {
#clock-cells = <0>;
@@ -138,12 +154,11 @@
"apb0_ir1", "apb0_keypad";
};
- /* dummy is pll62 */
apb1_mux: apb1_mux at 01c20058 {
#clock-cells = <0>;
compatible = "allwinner,sun4i-apb1-mux-clk";
reg = <0x01c20058 0x4>;
- clocks = <&osc24M>, <&dummy>, <&osc32k>;
+ clocks = <&osc24M>, <&pll6 1>, <&osc32k>;
};
apb1: apb1 at 01c20058 {
diff --git a/arch/arm/boot/dts/sun5i-a10s.dtsi b/arch/arm/boot/dts/sun5i-a10s.dtsi
index 92a32ab..1b32a4a 100644
--- a/arch/arm/boot/dts/sun5i-a10s.dtsi
+++ b/arch/arm/boot/dts/sun5i-a10s.dtsi
@@ -70,6 +70,22 @@
clocks = <&osc24M>;
};
+ pll5: pll5 at 01c20020 {
+ #clock-cells = <1>;
+ compatible = "allwinner,sun4i-pll5-clk";
+ reg = <0x01c20020 0x4>;
+ clocks = <&osc24M>;
+ clock-output-names = "pll5_ddr", "pll5_other";
+ };
+
+ pll6: pll6 at 01c20028 {
+ #clock-cells = <1>;
+ compatible = "allwinner,sun4i-pll6-clk";
+ reg = <0x01c20028 0x4>;
+ clocks = <&osc24M>;
+ clock-output-names = "pll6_sata", "pll6_other", "pll6";
+ };
+
/* dummy is 200M */
cpu: cpu at 01c20054 {
#clock-cells = <0>;
@@ -130,12 +146,11 @@
"apb0_ir", "apb0_keypad";
};
- /* dummy is pll62 */
apb1_mux: apb1_mux at 01c20058 {
#clock-cells = <0>;
compatible = "allwinner,sun4i-apb1-mux-clk";
reg = <0x01c20058 0x4>;
- clocks = <&osc24M>, <&dummy>, <&osc32k>;
+ clocks = <&osc24M>, <&pll6 1>, <&osc32k>;
};
apb1: apb1 at 01c20058 {
diff --git a/arch/arm/boot/dts/sun5i-a13.dtsi b/arch/arm/boot/dts/sun5i-a13.dtsi
index 2f9ba4a..de455ee 100644
--- a/arch/arm/boot/dts/sun5i-a13.dtsi
+++ b/arch/arm/boot/dts/sun5i-a13.dtsi
@@ -74,6 +74,22 @@
clocks = <&osc24M>;
};
+ pll5: pll5 at 01c20020 {
+ #clock-cells = <1>;
+ compatible = "allwinner,sun4i-pll5-clk";
+ reg = <0x01c20020 0x4>;
+ clocks = <&osc24M>;
+ clock-output-names = "pll5_ddr", "pll5_other";
+ };
+
+ pll6: pll6 at 01c20028 {
+ #clock-cells = <1>;
+ compatible = "allwinner,sun4i-pll6-clk";
+ reg = <0x01c20028 0x4>;
+ clocks = <&osc24M>;
+ clock-output-names = "pll6_sata", "pll6_other", "pll6";
+ };
+
/* dummy is 200M */
cpu: cpu at 01c20054 {
#clock-cells = <0>;
@@ -132,12 +148,11 @@
clock-output-names = "apb0_codec", "apb0_pio", "apb0_ir";
};
- /* dummy is pll6 */
apb1_mux: apb1_mux at 01c20058 {
#clock-cells = <0>;
compatible = "allwinner,sun4i-apb1-mux-clk";
reg = <0x01c20058 0x4>;
- clocks = <&osc24M>, <&dummy>, <&osc32k>;
+ clocks = <&osc24M>, <&pll6 1>, <&osc32k>;
};
apb1: apb1 at 01c20058 {
diff --git a/arch/arm/boot/dts/sun7i-a20.dtsi b/arch/arm/boot/dts/sun7i-a20.dtsi
index bdbf21e..c622e51 100644
--- a/arch/arm/boot/dts/sun7i-a20.dtsi
+++ b/arch/arm/boot/dts/sun7i-a20.dtsi
@@ -69,23 +69,27 @@
clocks = <&osc24M>;
};
- /*
- * This is a dummy clock, to be used as placeholder on
- * other mux clocks when a specific parent clock is not
- * yet implemented. It should be dropped when the driver
- * is complete.
- */
- pll6: pll6 {
- #clock-cells = <0>;
- compatible = "fixed-clock";
- clock-frequency = <0>;
+ pll5: pll5 at 01c20020 {
+ #clock-cells = <1>;
+ compatible = "allwinner,sun4i-pll5-clk";
+ reg = <0x01c20020 0x4>;
+ clocks = <&osc24M>;
+ clock-output-names = "pll5_ddr", "pll5_other";
+ };
+
+ pll6: pll6 at 01c20028 {
+ #clock-cells = <1>;
+ compatible = "allwinner,sun4i-pll6-clk";
+ reg = <0x01c20028 0x4>;
+ clocks = <&osc24M>;
+ clock-output-names = "pll6_sata", "pll6_other", "pll6";
};
cpu: cpu at 01c20054 {
#clock-cells = <0>;
compatible = "allwinner,sun4i-cpu-clk";
reg = <0x01c20054 0x4>;
- clocks = <&osc32k>, <&osc24M>, <&pll1>, <&pll6>;
+ clocks = <&osc32k>, <&osc24M>, <&pll1>, <&pll6 1>;
};
axi: axi at 01c20054 {
@@ -144,7 +148,7 @@
#clock-cells = <0>;
compatible = "allwinner,sun4i-apb1-mux-clk";
reg = <0x01c20058 0x4>;
- clocks = <&osc24M>, <&pll6>, <&osc32k>;
+ clocks = <&osc24M>, <&pll6 1>, <&osc32k>;
};
apb1: apb1 at 01c20058 {
--
1.8.4
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH 06/10] clk: sunxi: mod0 support
2013-09-29 3:49 [PATCH 00/10] clk: sunxi: PLL4/5/6, mod0 and mbus support Emilio López
` (4 preceding siblings ...)
2013-09-29 3:49 ` [PATCH 05/10] ARM: " Emilio López
@ 2013-09-29 3:49 ` Emilio López
2013-09-30 17:35 ` Maxime Ripard
2013-09-29 3:49 ` [PATCH 07/10] ARM: sun4i: dt: mod0 clocks Emilio López
` (4 subsequent siblings)
10 siblings, 1 reply; 20+ messages in thread
From: Emilio López @ 2013-09-29 3:49 UTC (permalink / raw)
To: linux-arm-kernel
This commit implements support for the "module 0" type of clocks, as
used by MMC, IR, NAND, SATA and other components.
Signed-off-by: Emilio L?pez <emilio@elopez.com.ar>
---
Documentation/devicetree/bindings/clock/sunxi.txt | 1 +
drivers/clk/sunxi/clk-sunxi.c | 57 +++++++++++++++++++++++
2 files changed, 58 insertions(+)
diff --git a/Documentation/devicetree/bindings/clock/sunxi.txt b/Documentation/devicetree/bindings/clock/sunxi.txt
index 773f3ae..ff3f61c 100644
--- a/Documentation/devicetree/bindings/clock/sunxi.txt
+++ b/Documentation/devicetree/bindings/clock/sunxi.txt
@@ -35,6 +35,7 @@ Required properties:
"allwinner,sun7i-a20-apb1-gates-clk" - for the APB1 gates on A20
"allwinner,sun6i-a31-apb2-div-clk" - for the APB2 gates on A31
"allwinner,sun6i-a31-apb2-gates-clk" - for the APB2 gates on A31
+ "allwinner,sun4i-mod0-clk" - for the module 0 family of clocks
Required properties for all clocks:
- reg : shall be the control register address for the clock.
diff --git a/drivers/clk/sunxi/clk-sunxi.c b/drivers/clk/sunxi/clk-sunxi.c
index b1210f3..163a3d8 100644
--- a/drivers/clk/sunxi/clk-sunxi.c
+++ b/drivers/clk/sunxi/clk-sunxi.c
@@ -287,6 +287,47 @@ static void sun4i_get_apb1_factors(u32 *freq, u32 parent_rate,
/**
+ * sun4i_get_mod0_factors() - calculates m, n factors for MOD0-style clocks
+ * MMC rate is calculated as follows
+ * rate = (parent_rate >> p) / (m + 1);
+ */
+
+static void sun4i_get_mod0_factors(u32 *freq, u32 parent_rate,
+ u8 *n, u8 *k, u8 *m, u8 *p)
+{
+ 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;
+
+ div = parent_rate / *freq;
+
+ if (div < 16)
+ calcp = 0;
+ else if (div / 2 < 16)
+ calcp = 1;
+ else if (div / 4 < 16)
+ calcp = 2;
+ else
+ calcp = 3;
+
+ calcm = DIV_ROUND_UP(div, 1 << calcp);
+
+ *freq = (parent_rate >> calcp) / calcm;
+
+ /* we were called to round the frequency, we can now return */
+ if (n == NULL)
+ return;
+
+ *m = calcm - 1;
+ *p = calcp;
+}
+
+
+
+/**
* sunxi_factors_clk_setup() - Setup function for factor clocks
*/
@@ -333,6 +374,14 @@ static struct clk_factors_config sun4i_apb1_config = {
.pwidth = 2,
};
+/* user manual says "n" but it's really "p" */
+static struct clk_factors_config sun4i_mod0_config = {
+ .mshift = 0,
+ .mwidth = 4,
+ .pshift = 16,
+ .pwidth = 2,
+};
+
static const struct factors_data sun4i_pll1_data __initconst = {
.enable = 31,
.table = &sun4i_pll1_config,
@@ -356,6 +405,13 @@ static const struct factors_data sun4i_apb1_data __initconst = {
.getter = sun4i_get_apb1_factors,
};
+static const struct factors_data sun4i_mod0_data __initconst = {
+ .enable = 31,
+ .mux = 24,
+ .table = &sun4i_mod0_config,
+ .getter = sun4i_get_mod0_factors,
+};
+
static struct clk * __init sunxi_factors_clk_setup(struct device_node *node,
const struct factors_data *data)
{
@@ -779,6 +835,7 @@ static const struct of_device_id clk_factors_match[] __initconst = {
{.compatible = "allwinner,sun4i-pll1-clk", .data = &sun4i_pll1_data,},
{.compatible = "allwinner,sun6i-a31-pll1-clk", .data = &sun6i_a31_pll1_data,},
{.compatible = "allwinner,sun4i-apb1-clk", .data = &sun4i_apb1_data,},
+ {.compatible = "allwinner,sun4i-mod0-clk", .data = &sun4i_mod0_data,},
{}
};
--
1.8.4
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH 07/10] ARM: sun4i: dt: mod0 clocks
2013-09-29 3:49 [PATCH 00/10] clk: sunxi: PLL4/5/6, mod0 and mbus support Emilio López
` (5 preceding siblings ...)
2013-09-29 3:49 ` [PATCH 06/10] clk: sunxi: mod0 support Emilio López
@ 2013-09-29 3:49 ` Emilio López
2013-09-29 3:49 ` [PATCH 08/10] ARM: sun5i: " Emilio López
` (3 subsequent siblings)
10 siblings, 0 replies; 20+ messages in thread
From: Emilio López @ 2013-09-29 3:49 UTC (permalink / raw)
To: linux-arm-kernel
This commit adds all the mod0 clocks present on sun4i to its device tree
Signed-off-by: Emilio L?pez <emilio@elopez.com.ar>
---
arch/arm/boot/dts/sun4i-a10.dtsi | 105 +++++++++++++++++++++++++++++++++++++++
1 file changed, 105 insertions(+)
diff --git a/arch/arm/boot/dts/sun4i-a10.dtsi b/arch/arm/boot/dts/sun4i-a10.dtsi
index 94b6fbb..235d078 100644
--- a/arch/arm/boot/dts/sun4i-a10.dtsi
+++ b/arch/arm/boot/dts/sun4i-a10.dtsi
@@ -180,6 +180,111 @@
"apb1_uart4", "apb1_uart5", "apb1_uart6",
"apb1_uart7";
};
+
+ nand: nand at 01c20080 {
+ #clock-cells = <0>;
+ compatible = "allwinner,sun4i-mod0-clk";
+ reg = <0x01c20080 0x4>;
+ clocks = <&osc24M>, <&pll6 1>, <&pll5 1>;
+ };
+
+ ms: ms at 01c20084 {
+ #clock-cells = <0>;
+ compatible = "allwinner,sun4i-mod0-clk";
+ reg = <0x01c20084 0x4>;
+ clocks = <&osc24M>, <&pll6 1>, <&pll5 1>;
+ };
+
+ mmc0: mmc0 at 01c20088 {
+ #clock-cells = <0>;
+ compatible = "allwinner,sun4i-mod0-clk";
+ reg = <0x01c20088 0x4>;
+ clocks = <&osc24M>, <&pll6 1>, <&pll5 1>;
+ };
+
+ mmc1: mmc1 at 01c2008c {
+ #clock-cells = <0>;
+ compatible = "allwinner,sun4i-mod0-clk";
+ reg = <0x01c2008c 0x4>;
+ clocks = <&osc24M>, <&pll6 1>, <&pll5 1>;
+ };
+
+ mmc2: mmc2 at 01c20090 {
+ #clock-cells = <0>;
+ compatible = "allwinner,sun4i-mod0-clk";
+ reg = <0x01c20090 0x4>;
+ clocks = <&osc24M>, <&pll6 1>, <&pll5 1>;
+ };
+
+ mmc3: mmc3 at 01c20094 {
+ #clock-cells = <0>;
+ compatible = "allwinner,sun4i-mod0-clk";
+ reg = <0x01c20094 0x4>;
+ clocks = <&osc24M>, <&pll6 1>, <&pll5 1>;
+ };
+
+ ts: ts at 01c20098 {
+ #clock-cells = <0>;
+ compatible = "allwinner,sun4i-mod0-clk";
+ reg = <0x01c20098 0x4>;
+ clocks = <&osc24M>, <&pll6 1>, <&pll5 1>;
+ };
+
+ ss: ss at 01c2009c {
+ #clock-cells = <0>;
+ compatible = "allwinner,sun4i-mod0-clk";
+ reg = <0x01c2009c 0x4>;
+ clocks = <&osc24M>, <&pll6 1>, <&pll5 1>;
+ };
+
+ spi0: spi0 at 01c200a0 {
+ #clock-cells = <0>;
+ compatible = "allwinner,sun4i-mod0-clk";
+ reg = <0x01c200a0 0x4>;
+ clocks = <&osc24M>, <&pll6 1>, <&pll5 1>;
+ };
+
+ spi1: spi1 at 01c200a4 {
+ #clock-cells = <0>;
+ compatible = "allwinner,sun4i-mod0-clk";
+ reg = <0x01c200a4 0x4>;
+ clocks = <&osc24M>, <&pll6 1>, <&pll5 1>;
+ };
+
+ spi2: spi2 at 01c200a8 {
+ #clock-cells = <0>;
+ compatible = "allwinner,sun4i-mod0-clk";
+ reg = <0x01c200a8 0x4>;
+ clocks = <&osc24M>, <&pll6 1>, <&pll5 1>;
+ };
+
+ pata: pata at 01c200ac {
+ #clock-cells = <0>;
+ compatible = "allwinner,sun4i-mod0-clk";
+ reg = <0x01c200ac 0x4>;
+ clocks = <&osc24M>, <&pll6 1>, <&pll5 1>;
+ };
+
+ ir0: ir0 at 01c200b0 {
+ #clock-cells = <0>;
+ compatible = "allwinner,sun4i-mod0-clk";
+ reg = <0x01c200b0 0x4>;
+ clocks = <&osc24M>, <&pll6 1>, <&pll5 1>;
+ };
+
+ ir1: ir1 at 01c200b4 {
+ #clock-cells = <0>;
+ compatible = "allwinner,sun4i-mod0-clk";
+ reg = <0x01c200b4 0x4>;
+ clocks = <&osc24M>, <&pll6 1>, <&pll5 1>;
+ };
+
+ spi3: spi3 at 01c200d4 {
+ #clock-cells = <0>;
+ compatible = "allwinner,sun4i-mod0-clk";
+ reg = <0x01c200d4 0x4>;
+ clocks = <&osc24M>, <&pll6 1>, <&pll5 1>;
+ };
};
soc at 01c00000 {
--
1.8.4
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH 08/10] ARM: sun5i: dt: mod0 clocks
2013-09-29 3:49 [PATCH 00/10] clk: sunxi: PLL4/5/6, mod0 and mbus support Emilio López
` (6 preceding siblings ...)
2013-09-29 3:49 ` [PATCH 07/10] ARM: sun4i: dt: mod0 clocks Emilio López
@ 2013-09-29 3:49 ` Emilio López
2013-09-29 3:49 ` [PATCH 09/10] ARM: sun7i: " Emilio López
` (2 subsequent siblings)
10 siblings, 0 replies; 20+ messages in thread
From: Emilio López @ 2013-09-29 3:49 UTC (permalink / raw)
To: linux-arm-kernel
This commit adds all the mod0 clocks available on A10 and A13. The list
has been constructed by looking at the Allwinner code release for A10S
and A13.
Signed-off-by: Emilio L?pez <emilio@elopez.com.ar>
---
arch/arm/boot/dts/sun5i-a10s.dtsi | 77 +++++++++++++++++++++++++++++++++++++++
arch/arm/boot/dts/sun5i-a13.dtsi | 77 +++++++++++++++++++++++++++++++++++++++
2 files changed, 154 insertions(+)
diff --git a/arch/arm/boot/dts/sun5i-a10s.dtsi b/arch/arm/boot/dts/sun5i-a10s.dtsi
index 1b32a4a..2756378 100644
--- a/arch/arm/boot/dts/sun5i-a10s.dtsi
+++ b/arch/arm/boot/dts/sun5i-a10s.dtsi
@@ -169,6 +169,83 @@
"apb1_i2c2", "apb1_uart0", "apb1_uart1",
"apb1_uart2", "apb1_uart3";
};
+
+ nand: nand at 01c20080 {
+ #clock-cells = <0>;
+ compatible = "allwinner,sun4i-mod0-clk";
+ reg = <0x01c20080 0x4>;
+ clocks = <&osc24M>, <&pll6 1>, <&pll5 1>;
+ };
+
+ ms: ms at 01c20084 {
+ #clock-cells = <0>;
+ compatible = "allwinner,sun4i-mod0-clk";
+ reg = <0x01c20084 0x4>;
+ clocks = <&osc24M>, <&pll6 1>, <&pll5 1>;
+ };
+
+ mmc0: mmc0 at 01c20088 {
+ #clock-cells = <0>;
+ compatible = "allwinner,sun4i-mod0-clk";
+ reg = <0x01c20088 0x4>;
+ clocks = <&osc24M>, <&pll6 1>, <&pll5 1>;
+ };
+
+ mmc1: mmc1 at 01c2008c {
+ #clock-cells = <0>;
+ compatible = "allwinner,sun4i-mod0-clk";
+ reg = <0x01c2008c 0x4>;
+ clocks = <&osc24M>, <&pll6 1>, <&pll5 1>;
+ };
+
+ mmc2: mmc2 at 01c20090 {
+ #clock-cells = <0>;
+ compatible = "allwinner,sun4i-mod0-clk";
+ reg = <0x01c20090 0x4>;
+ clocks = <&osc24M>, <&pll6 1>, <&pll5 1>;
+ };
+
+ ts: ts at 01c20098 {
+ #clock-cells = <0>;
+ compatible = "allwinner,sun4i-mod0-clk";
+ reg = <0x01c20098 0x4>;
+ clocks = <&osc24M>, <&pll6 1>, <&pll5 1>;
+ };
+
+ ss: ss at 01c2009c {
+ #clock-cells = <0>;
+ compatible = "allwinner,sun4i-mod0-clk";
+ reg = <0x01c2009c 0x4>;
+ clocks = <&osc24M>, <&pll6 1>, <&pll5 1>;
+ };
+
+ spi0: spi0 at 01c200a0 {
+ #clock-cells = <0>;
+ compatible = "allwinner,sun4i-mod0-clk";
+ reg = <0x01c200a0 0x4>;
+ clocks = <&osc24M>, <&pll6 1>, <&pll5 1>;
+ };
+
+ spi1: spi1 at 01c200a4 {
+ #clock-cells = <0>;
+ compatible = "allwinner,sun4i-mod0-clk";
+ reg = <0x01c200a4 0x4>;
+ clocks = <&osc24M>, <&pll6 1>, <&pll5 1>;
+ };
+
+ spi2: spi2 at 01c200a8 {
+ #clock-cells = <0>;
+ compatible = "allwinner,sun4i-mod0-clk";
+ reg = <0x01c200a8 0x4>;
+ clocks = <&osc24M>, <&pll6 1>, <&pll5 1>;
+ };
+
+ ir0: ir0 at 01c200b0 {
+ #clock-cells = <0>;
+ compatible = "allwinner,sun4i-mod0-clk";
+ reg = <0x01c200b0 0x4>;
+ clocks = <&osc24M>, <&pll6 1>, <&pll5 1>;
+ };
};
soc at 01c00000 {
diff --git a/arch/arm/boot/dts/sun5i-a13.dtsi b/arch/arm/boot/dts/sun5i-a13.dtsi
index de455ee..c26cd6d 100644
--- a/arch/arm/boot/dts/sun5i-a13.dtsi
+++ b/arch/arm/boot/dts/sun5i-a13.dtsi
@@ -170,6 +170,83 @@
clock-output-names = "apb1_i2c0", "apb1_i2c1",
"apb1_i2c2", "apb1_uart1", "apb1_uart3";
};
+
+ nand: nand at 01c20080 {
+ #clock-cells = <0>;
+ compatible = "allwinner,sun4i-mod0-clk";
+ reg = <0x01c20080 0x4>;
+ clocks = <&osc24M>, <&pll6 1>, <&pll5 1>;
+ };
+
+ ms: ms at 01c20084 {
+ #clock-cells = <0>;
+ compatible = "allwinner,sun4i-mod0-clk";
+ reg = <0x01c20084 0x4>;
+ clocks = <&osc24M>, <&pll6 1>, <&pll5 1>;
+ };
+
+ mmc0: mmc0 at 01c20088 {
+ #clock-cells = <0>;
+ compatible = "allwinner,sun4i-mod0-clk";
+ reg = <0x01c20088 0x4>;
+ clocks = <&osc24M>, <&pll6 1>, <&pll5 1>;
+ };
+
+ mmc1: mmc1 at 01c2008c {
+ #clock-cells = <0>;
+ compatible = "allwinner,sun4i-mod0-clk";
+ reg = <0x01c2008c 0x4>;
+ clocks = <&osc24M>, <&pll6 1>, <&pll5 1>;
+ };
+
+ mmc2: mmc2 at 01c20090 {
+ #clock-cells = <0>;
+ compatible = "allwinner,sun4i-mod0-clk";
+ reg = <0x01c20090 0x4>;
+ clocks = <&osc24M>, <&pll6 1>, <&pll5 1>;
+ };
+
+ ts: ts at 01c20098 {
+ #clock-cells = <0>;
+ compatible = "allwinner,sun4i-mod0-clk";
+ reg = <0x01c20098 0x4>;
+ clocks = <&osc24M>, <&pll6 1>, <&pll5 1>;
+ };
+
+ ss: ss at 01c2009c {
+ #clock-cells = <0>;
+ compatible = "allwinner,sun4i-mod0-clk";
+ reg = <0x01c2009c 0x4>;
+ clocks = <&osc24M>, <&pll6 1>, <&pll5 1>;
+ };
+
+ spi0: spi0 at 01c200a0 {
+ #clock-cells = <0>;
+ compatible = "allwinner,sun4i-mod0-clk";
+ reg = <0x01c200a0 0x4>;
+ clocks = <&osc24M>, <&pll6 1>, <&pll5 1>;
+ };
+
+ spi1: spi1 at 01c200a4 {
+ #clock-cells = <0>;
+ compatible = "allwinner,sun4i-mod0-clk";
+ reg = <0x01c200a4 0x4>;
+ clocks = <&osc24M>, <&pll6 1>, <&pll5 1>;
+ };
+
+ spi2: spi2 at 01c200a8 {
+ #clock-cells = <0>;
+ compatible = "allwinner,sun4i-mod0-clk";
+ reg = <0x01c200a8 0x4>;
+ clocks = <&osc24M>, <&pll6 1>, <&pll5 1>;
+ };
+
+ ir0: ir0 at 01c200b0 {
+ #clock-cells = <0>;
+ compatible = "allwinner,sun4i-mod0-clk";
+ reg = <0x01c200b0 0x4>;
+ clocks = <&osc24M>, <&pll6 1>, <&pll5 1>;
+ };
};
soc at 01c00000 {
--
1.8.4
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH 09/10] ARM: sun7i: dt: mod0 clocks
2013-09-29 3:49 [PATCH 00/10] clk: sunxi: PLL4/5/6, mod0 and mbus support Emilio López
` (7 preceding siblings ...)
2013-09-29 3:49 ` [PATCH 08/10] ARM: sun5i: " Emilio López
@ 2013-09-29 3:49 ` Emilio López
2013-09-29 3:49 ` [PATCH 10/10] ARM: sunxi: dt: add nodes for the mbus clock Emilio López
2013-09-30 17:38 ` [PATCH 00/10] clk: sunxi: PLL4/5/6, mod0 and mbus support Maxime Ripard
10 siblings, 0 replies; 20+ messages in thread
From: Emilio López @ 2013-09-29 3:49 UTC (permalink / raw)
To: linux-arm-kernel
This commit adds all the mod0 clocks available on A20 to its device
tree. This list was created by looking at AW's code release.
Signed-off-by: Emilio L?pez <emilio@elopez.com.ar>
---
arch/arm/boot/dts/sun7i-a20.dtsi | 105 +++++++++++++++++++++++++++++++++++++++
1 file changed, 105 insertions(+)
diff --git a/arch/arm/boot/dts/sun7i-a20.dtsi b/arch/arm/boot/dts/sun7i-a20.dtsi
index c622e51..d75eb53 100644
--- a/arch/arm/boot/dts/sun7i-a20.dtsi
+++ b/arch/arm/boot/dts/sun7i-a20.dtsi
@@ -170,6 +170,111 @@
"apb1_uart2", "apb1_uart3", "apb1_uart4",
"apb1_uart5", "apb1_uart6", "apb1_uart7";
};
+
+ nand: nand at 01c20080 {
+ #clock-cells = <0>;
+ compatible = "allwinner,sun4i-mod0-clk";
+ reg = <0x01c20080 0x4>;
+ clocks = <&osc24M>, <&pll6 1>, <&pll5 1>;
+ };
+
+ ms: ms at 01c20084 {
+ #clock-cells = <0>;
+ compatible = "allwinner,sun4i-mod0-clk";
+ reg = <0x01c20084 0x4>;
+ clocks = <&osc24M>, <&pll6 1>, <&pll5 1>;
+ };
+
+ mmc0: mmc0 at 01c20088 {
+ #clock-cells = <0>;
+ compatible = "allwinner,sun4i-mod0-clk";
+ reg = <0x01c20088 0x4>;
+ clocks = <&osc24M>, <&pll6 1>, <&pll5 1>;
+ };
+
+ mmc1: mmc1 at 01c2008c {
+ #clock-cells = <0>;
+ compatible = "allwinner,sun4i-mod0-clk";
+ reg = <0x01c2008c 0x4>;
+ clocks = <&osc24M>, <&pll6 1>, <&pll5 1>;
+ };
+
+ mmc2: mmc2 at 01c20090 {
+ #clock-cells = <0>;
+ compatible = "allwinner,sun4i-mod0-clk";
+ reg = <0x01c20090 0x4>;
+ clocks = <&osc24M>, <&pll6 1>, <&pll5 1>;
+ };
+
+ mmc3: mmc3 at 01c20094 {
+ #clock-cells = <0>;
+ compatible = "allwinner,sun4i-mod0-clk";
+ reg = <0x01c20094 0x4>;
+ clocks = <&osc24M>, <&pll6 1>, <&pll5 1>;
+ };
+
+ ts: ts at 01c20098 {
+ #clock-cells = <0>;
+ compatible = "allwinner,sun4i-mod0-clk";
+ reg = <0x01c20098 0x4>;
+ clocks = <&osc24M>, <&pll6 1>, <&pll5 1>;
+ };
+
+ ss: ss at 01c2009c {
+ #clock-cells = <0>;
+ compatible = "allwinner,sun4i-mod0-clk";
+ reg = <0x01c2009c 0x4>;
+ clocks = <&osc24M>, <&pll6 1>, <&pll5 1>;
+ };
+
+ spi0: spi0 at 01c200a0 {
+ #clock-cells = <0>;
+ compatible = "allwinner,sun4i-mod0-clk";
+ reg = <0x01c200a0 0x4>;
+ clocks = <&osc24M>, <&pll6 1>, <&pll5 1>;
+ };
+
+ spi1: spi1 at 01c200a4 {
+ #clock-cells = <0>;
+ compatible = "allwinner,sun4i-mod0-clk";
+ reg = <0x01c200a4 0x4>;
+ clocks = <&osc24M>, <&pll6 1>, <&pll5 1>;
+ };
+
+ spi2: spi2 at 01c200a8 {
+ #clock-cells = <0>;
+ compatible = "allwinner,sun4i-mod0-clk";
+ reg = <0x01c200a8 0x4>;
+ clocks = <&osc24M>, <&pll6 1>, <&pll5 1>;
+ };
+
+ pata: pata at 01c200ac {
+ #clock-cells = <0>;
+ compatible = "allwinner,sun4i-mod0-clk";
+ reg = <0x01c200ac 0x4>;
+ clocks = <&osc24M>, <&pll6 1>, <&pll5 1>;
+ };
+
+ ir0: ir0 at 01c200b0 {
+ #clock-cells = <0>;
+ compatible = "allwinner,sun4i-mod0-clk";
+ reg = <0x01c200b0 0x4>;
+ clocks = <&osc24M>, <&pll6 1>, <&pll5 1>;
+ };
+
+ ir1: ir1 at 01c200b4 {
+ #clock-cells = <0>;
+ compatible = "allwinner,sun4i-mod0-clk";
+ reg = <0x01c200b4 0x4>;
+ clocks = <&osc24M>, <&pll6 1>, <&pll5 1>;
+ };
+
+ spi3: spi3 at 01c200d4 {
+ #clock-cells = <0>;
+ compatible = "allwinner,sun4i-mod0-clk";
+ reg = <0x01c200d4 0x4>;
+ clocks = <&osc24M>, <&pll6 1>, <&pll5 1>;
+ };
};
soc at 01c00000 {
--
1.8.4
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH 10/10] ARM: sunxi: dt: add nodes for the mbus clock
2013-09-29 3:49 [PATCH 00/10] clk: sunxi: PLL4/5/6, mod0 and mbus support Emilio López
` (8 preceding siblings ...)
2013-09-29 3:49 ` [PATCH 09/10] ARM: sun7i: " Emilio López
@ 2013-09-29 3:49 ` Emilio López
2013-09-30 17:38 ` [PATCH 00/10] clk: sunxi: PLL4/5/6, mod0 and mbus support Maxime Ripard
10 siblings, 0 replies; 20+ messages in thread
From: Emilio López @ 2013-09-29 3:49 UTC (permalink / raw)
To: linux-arm-kernel
mbus is the memory bus clock, and it is present on both sun5i and sun7i
machines. Its register layout is compatible with the mod0 one.
Signed-off-by: Emilio L?pez <emilio@elopez.com.ar>
---
arch/arm/boot/dts/sun5i-a10s.dtsi | 7 +++++++
arch/arm/boot/dts/sun5i-a13.dtsi | 7 +++++++
arch/arm/boot/dts/sun7i-a20.dtsi | 7 +++++++
3 files changed, 21 insertions(+)
diff --git a/arch/arm/boot/dts/sun5i-a10s.dtsi b/arch/arm/boot/dts/sun5i-a10s.dtsi
index 2756378..ae5807f 100644
--- a/arch/arm/boot/dts/sun5i-a10s.dtsi
+++ b/arch/arm/boot/dts/sun5i-a10s.dtsi
@@ -246,6 +246,13 @@
reg = <0x01c200b0 0x4>;
clocks = <&osc24M>, <&pll6 1>, <&pll5 1>;
};
+
+ mbus: mbus at 01c2015c {
+ #clock-cells = <0>;
+ compatible = "allwinner,sun4i-mod0-clk";
+ reg = <0x01c2015c 0x4>;
+ clocks = <&osc24M>, <&pll6 1>, <&pll5 1>;
+ };
};
soc at 01c00000 {
diff --git a/arch/arm/boot/dts/sun5i-a13.dtsi b/arch/arm/boot/dts/sun5i-a13.dtsi
index c26cd6d..efa941a 100644
--- a/arch/arm/boot/dts/sun5i-a13.dtsi
+++ b/arch/arm/boot/dts/sun5i-a13.dtsi
@@ -247,6 +247,13 @@
reg = <0x01c200b0 0x4>;
clocks = <&osc24M>, <&pll6 1>, <&pll5 1>;
};
+
+ mbus: mbus at 01c2015c {
+ #clock-cells = <0>;
+ compatible = "allwinner,sun4i-mod0-clk";
+ reg = <0x01c2015c 0x4>;
+ clocks = <&osc24M>, <&pll6 1>, <&pll5 1>;
+ };
};
soc at 01c00000 {
diff --git a/arch/arm/boot/dts/sun7i-a20.dtsi b/arch/arm/boot/dts/sun7i-a20.dtsi
index d75eb53..73a21a1 100644
--- a/arch/arm/boot/dts/sun7i-a20.dtsi
+++ b/arch/arm/boot/dts/sun7i-a20.dtsi
@@ -275,6 +275,13 @@
reg = <0x01c200d4 0x4>;
clocks = <&osc24M>, <&pll6 1>, <&pll5 1>;
};
+
+ mbus: mbus at 01c2015c {
+ #clock-cells = <0>;
+ compatible = "allwinner,sun4i-mod0-clk";
+ reg = <0x01c2015c 0x4>;
+ clocks = <&osc24M>, <&pll6 2>, <&pll5 1>;
+ };
};
soc at 01c00000 {
--
1.8.4
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH 01/10] clk: sunxi: register factors clocks behind composite
2013-09-29 3:49 ` [PATCH 01/10] clk: sunxi: register factors clocks behind composite Emilio López
@ 2013-09-30 17:03 ` Maxime Ripard
0 siblings, 0 replies; 20+ messages in thread
From: Maxime Ripard @ 2013-09-30 17:03 UTC (permalink / raw)
To: linux-arm-kernel
On Sun, Sep 29, 2013 at 12:49:30AM -0300, Emilio L?pez wrote:
> This commit reworks factors clock registration to be done behind a
> composite clock. This allows us to additionally add a gate, mux or
> divisors, as it will be needed by some future PLLs.
>
> Signed-off-by: Emilio L?pez <emilio@elopez.com.ar>
Acked-by: Maxime Ripard <maxime.ripard@free-electrons.com>
Thanks!
Maxime
--
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20130930/fb77a3f2/attachment-0001.sig>
^ permalink raw reply [flat|nested] 20+ messages in thread
* [PATCH 02/10] clk: sunxi: add gating support to PLL1
2013-09-29 3:49 ` [PATCH 02/10] clk: sunxi: add gating support to PLL1 Emilio López
@ 2013-09-30 17:05 ` Maxime Ripard
0 siblings, 0 replies; 20+ messages in thread
From: Maxime Ripard @ 2013-09-30 17:05 UTC (permalink / raw)
To: linux-arm-kernel
On Sun, Sep 29, 2013 at 12:49:31AM -0300, Emilio L?pez wrote:
> This commit adds gating support to PLL1 on the clock driver. This makes
> the PLL1 implementation fully compatible with PLL4 as well.
>
> Signed-off-by: Emilio L?pez <emilio@elopez.com.ar>
Acked-by: Maxime Ripard <maxime.ripard@free-electrons.com>
Thanks!
Maxime
--
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20130930/a3f92ed2/attachment.sig>
^ permalink raw reply [flat|nested] 20+ messages in thread
* [PATCH 04/10] clk: sunxi: add PLL5 and PLL6 support
2013-09-29 3:49 ` [PATCH 04/10] clk: sunxi: add PLL5 and PLL6 support Emilio López
@ 2013-09-30 17:21 ` Maxime Ripard
2013-09-30 23:29 ` Emilio López
0 siblings, 1 reply; 20+ messages in thread
From: Maxime Ripard @ 2013-09-30 17:21 UTC (permalink / raw)
To: linux-arm-kernel
Hi Emilio,
On Sun, Sep 29, 2013 at 12:49:33AM -0300, Emilio L?pez wrote:
> This commit implements PLL5 and PLL6 support on the sunxi clock driver.
> These PLLs use a similar factor clock, but differ on their outputs.
>
> Signed-off-by: Emilio L?pez <emilio@elopez.com.ar>
> ---
> Documentation/devicetree/bindings/clock/sunxi.txt | 2 +
> drivers/clk/sunxi/clk-sunxi.c | 182 +++++++++++++++++++++-
> 2 files changed, 177 insertions(+), 7 deletions(-)
>
> diff --git a/Documentation/devicetree/bindings/clock/sunxi.txt b/Documentation/devicetree/bindings/clock/sunxi.txt
> index 7d9245f..773f3ae 100644
> --- a/Documentation/devicetree/bindings/clock/sunxi.txt
> +++ b/Documentation/devicetree/bindings/clock/sunxi.txt
> @@ -9,6 +9,8 @@ Required properties:
> "allwinner,sun4i-osc-clk" - for a gatable oscillator
> "allwinner,sun4i-pll1-clk" - for the main PLL clock and PLL4
> "allwinner,sun6i-a31-pll1-clk" - for the main PLL clock on A31
> + "allwinner,sun4i-pll5-clk" - for the PLL5 clock
> + "allwinner,sun4i-pll6-clk" - for the PLL6 clock
> "allwinner,sun4i-cpu-clk" - for the CPU multiplexer clock
> "allwinner,sun4i-axi-clk" - for the AXI clock
> "allwinner,sun4i-axi-gates-clk" - for the AXI gates
> diff --git a/drivers/clk/sunxi/clk-sunxi.c b/drivers/clk/sunxi/clk-sunxi.c
> index 77b9f57..b1210f3 100644
> --- a/drivers/clk/sunxi/clk-sunxi.c
> +++ b/drivers/clk/sunxi/clk-sunxi.c
> @@ -210,6 +210,40 @@ static void sun6i_a31_get_pll1_factors(u32 *freq, u32 parent_rate,
> }
>
> /**
> + * sun4i_get_pll5_factors() - calculates n, k factors for PLL5
> + * PLL5 rate is calculated as follows
> + * rate = parent_rate * n * (k + 1)
> + * parent_rate is always 24Mhz
> + */
> +
> +static void sun4i_get_pll5_factors(u32 *freq, u32 parent_rate,
> + u8 *n, u8 *k, u8 *m, u8 *p)
> +{
> + u8 div;
> +
> + /* Normalize value to a 24M multiple */
> + div = *freq / 24000000;
> + *freq = 24000000 * div;
parent_rate here maybe ?
> +
> + /* we were called to round the frequency, we can now return */
> + if (n == NULL)
> + return;
> +
> + if (div < 31)
> + *k = 0;
> + else if (div / 2 < 31)
> + *k = 1;
> + else if (div / 3 < 31)
> + *k = 2;
> + else
> + *k = 3;
> +
> + *n = DIV_ROUND_UP(div, (*k+1));
> +}
> +
> +
> +
> +/**
> * sun4i_get_apb1_factors() - calculates m, p factors for APB1
> * APB1 rate is calculated as follows
> * rate = (parent_rate >> p) / (m + 1);
> @@ -285,6 +319,13 @@ static struct clk_factors_config sun6i_a31_pll1_config = {
> .mwidth = 2,
> };
>
> +static struct clk_factors_config sun4i_pll5_config = {
> + .nshift = 8,
> + .nwidth = 5,
> + .kshift = 4,
> + .kwidth = 2,
> +};
> +
The spacing between your functions and structures looks odd. You were
using 3 newlines the change just above, and now just one?
> static struct clk_factors_config sun4i_apb1_config = {
> .mshift = 0,
> .mwidth = 5,
> @@ -304,13 +345,19 @@ static const struct factors_data sun6i_a31_pll1_data __initconst = {
> .getter = sun6i_a31_get_pll1_factors,
> };
>
> +static const struct factors_data sun4i_pll5_data __initconst = {
> + .enable = 31,
> + .table = &sun4i_pll5_config,
> + .getter = sun4i_get_pll5_factors,
> +};
> +
> static const struct factors_data sun4i_apb1_data __initconst = {
> .table = &sun4i_apb1_config,
> .getter = sun4i_get_apb1_factors,
> };
>
> -static void __init sunxi_factors_clk_setup(struct device_node *node,
> - struct factors_data *data)
> +static struct clk * __init sunxi_factors_clk_setup(struct device_node *node,
> + const struct factors_data *data)
While this change is probably useful, I don't see how it relates to the
change described in your commit log. Either split these patches, or
explain why it's needed.
> {
> struct clk *clk;
> struct clk_factors *factors;
> @@ -321,6 +368,7 @@ static void __init sunxi_factors_clk_setup(struct device_node *node,
> const char *clk_name = node->name;
> const char *parents[5];
> void *reg;
> + unsigned long flags;
> int i = 0;
>
> reg = of_iomap(node, 0);
> @@ -331,14 +379,14 @@ static void __init sunxi_factors_clk_setup(struct device_node *node,
>
> factors = kzalloc(sizeof(struct clk_factors), GFP_KERNEL);
> if (!factors)
> - return;
> + return NULL;
>
> /* 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;
> + return NULL;
> }
>
> /* set up gate properties */
> @@ -354,7 +402,7 @@ static void __init sunxi_factors_clk_setup(struct device_node *node,
> if (!mux) {
> kfree(factors);
> kfree(gate);
> - return;
> + return NULL;
> }
>
> /* set up gate properties */
> @@ -371,17 +419,21 @@ static void __init sunxi_factors_clk_setup(struct device_node *node,
> factors->get_factors = data->getter;
> factors->lock = &clk_lock;
>
> + /* We should not disable pll5, it powers the RAM */
> + flags = !strcmp("pll5", clk_name) ? CLK_IGNORE_UNUSED : 0;
> +
> clk = clk_register_composite(NULL, clk_name,
> parents, i,
> mux_hw, &clk_mux_ops,
> &factors->hw, &clk_factors_ops,
> - gate_hw, &clk_gate_ops,
> - i ? 0 : CLK_IS_ROOT);
> + gate_hw, &clk_gate_ops, flags);
>
> if (!IS_ERR(clk)) {
> of_clk_add_provider(node, of_clk_src_simple_get, clk);
> clk_register_clkdev(clk, clk_name, NULL);
> }
> +
> + return clk;
> }
>
>
> @@ -616,6 +668,112 @@ static void __init sunxi_gates_clk_setup(struct device_node *node,
> of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
> }
>
> +
> +
> +/**
> + * sunxi_divs_clk_setup() - Setup function for leaf divisors on clocks
> + */
This comment doesn't seem to be at the right place in your code.
> +#define SUNXI_DIVS_MAX_QTY 2
> +#define SUNXI_DIVISOR_WIDTH 2
> +
> +struct divs_data {
> + const struct factors_data *factors; /* data for the factor clock */
> + struct {
> + u8 fixed; /* is it a fixed divisor? if not... */
> + struct clk_div_table *table; /* is it a table based divisor? */
> + u8 shift; /* otherwise it's a normal divisor with this shift */
> + u8 pow; /* is it power-of-two based? */
> + } div[SUNXI_DIVS_MAX_QTY];
> +};
> +
> +static struct clk_div_table pll6_sata_table[] = {
> + { .val = 0, .div = 6, },
> + { .val = 1, .div = 12, },
> + { .val = 2, .div = 18, },
> + { .val = 3, .div = 24, },
> + { } /* sentinel */
> +};
> +
> +static const struct divs_data pll5_divs_data __initconst = {
> + .factors = &sun4i_pll5_data,
> + .div = {
> + { .shift = 0, .pow = 0, }, /* M, DDR */
> + { .shift = 16, .pow = 1, }, /* P, other */
> + }
> +};
> +
> +static const struct divs_data pll6_divs_data __initconst = {
> + .factors = &sun4i_pll5_data,
> + .div = {
> + { .shift = 0, .table = pll6_sata_table }, /* M, SATA */
> + { .fixed = 2 }, /* P, other */
> + }
> +};
> +
> +static void __init sunxi_divs_clk_setup(struct device_node *node,
> + struct divs_data *data)
> +{
> + struct clk_onecell_data *clk_data;
> + const char *parent = node->name;
> + const char *clk_name;
> + struct clk **clks, *pclk;
> + void *reg;
> + int i = 0;
> + int flags, clkflags;
> +
> + /* Set up factor clock that we will be dividing */
> + pclk = sunxi_factors_clk_setup(node, data->factors);
> +
> + reg = of_iomap(node, 0);
> +
> + clk_data = kmalloc(sizeof(struct clk_onecell_data), GFP_KERNEL);
> + if (!clk_data)
> + return;
An extra newline would be great here.
> + clks = kzalloc(SUNXI_DIVS_MAX_QTY * sizeof(struct clk *), GFP_KERNEL);
> + if (!clks) {
> + kfree(clk_data);
> + return;
> + }
> + clk_data->clks = clks;
> +
> + /* It's not a good idea to have automatic reparenting changing
> + * our RAM clock! */
> + clkflags = !strcmp("pll5", parent) ? 0 : CLK_SET_RATE_PARENT;
> +
> + for (i = 0; i < SUNXI_DIVS_MAX_QTY; i++) {
> + if (of_property_read_string_index(node, "clock-output-names",
> + i, &clk_name) != 0)
> + break;
> +
> + if (data->div[i].fixed) {
> + clks[i] = clk_register_fixed_factor(NULL, clk_name,
> + parent, clkflags,
> + 1, data->div[i].fixed);
> + } else {
> + flags = data->div[i].pow ? CLK_DIVIDER_POWER_OF_TWO : 0;
> + clks[i] = clk_register_divider_table(NULL, clk_name,
> + parent, clkflags, reg,
> + data->div[i].shift,
> + SUNXI_DIVISOR_WIDTH, flags,
> + data->div[i].table, &clk_lock);
> + }
Hmmm, I don't get why you were calling sunxi_clk_factors_setup
unconditionally, and now you put a condition on the registration?
(Plus, your indentation here looks a bit odd.)
> +
> + WARN_ON(IS_ERR(clk_data->clks[i]));
> + clk_register_clkdev(clks[i], clk_name, NULL);
> + }
> +
> + /* The last clock available on the getter is the parent */
> + clks[i++] = pclk;
> +
> + /* Adjust to the real max */
> + clk_data->clk_num = i;
> +
> + of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
> +}
> +
> +
> +
> /* Matches for factors clocks */
> static const struct of_device_id clk_factors_match[] __initconst = {
> {.compatible = "allwinner,sun4i-pll1-clk", .data = &sun4i_pll1_data,},
> @@ -633,6 +791,13 @@ static const struct of_device_id clk_div_match[] __initconst = {
> {}
> };
>
> +/* Matches for divided outputs */
> +static const struct of_device_id clk_divs_match[] __initconst = {
> + {.compatible = "allwinner,sun4i-pll5-clk", .data = &pll5_divs_data,},
> + {.compatible = "allwinner,sun4i-pll6-clk", .data = &pll6_divs_data,},
> + {}
> +};
> +
> /* Matches for mux clocks */
> static const struct of_device_id clk_mux_match[] __initconst = {
> {.compatible = "allwinner,sun4i-cpu-clk", .data = &sun4i_cpu_mux_data,},
> @@ -713,6 +878,9 @@ void __init sunxi_init_clocks(void)
> /* Register divider clocks */
> of_sunxi_table_clock_setup(clk_div_match, sunxi_divider_clk_setup);
>
> + /* Register divided output clocks */
> + of_sunxi_table_clock_setup(clk_divs_match, sunxi_divs_clk_setup);
> +
> /* Register mux clocks */
> of_sunxi_table_clock_setup(clk_mux_match, sunxi_mux_clk_setup);
>
> --
> 1.8.4
>
Thanks!
Maxime
--
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20130930/389134af/attachment-0001.sig>
^ permalink raw reply [flat|nested] 20+ messages in thread
* [PATCH 06/10] clk: sunxi: mod0 support
2013-09-29 3:49 ` [PATCH 06/10] clk: sunxi: mod0 support Emilio López
@ 2013-09-30 17:35 ` Maxime Ripard
2013-09-30 23:37 ` Emilio López
0 siblings, 1 reply; 20+ messages in thread
From: Maxime Ripard @ 2013-09-30 17:35 UTC (permalink / raw)
To: linux-arm-kernel
Hi Emilio,
Overall, it looks fine, I just have a small question.
On Sun, Sep 29, 2013 at 12:49:35AM -0300, Emilio L?pez wrote:
> This commit implements support for the "module 0" type of clocks, as
> used by MMC, IR, NAND, SATA and other components.
>
> Signed-off-by: Emilio L?pez <emilio@elopez.com.ar>
> ---
> Documentation/devicetree/bindings/clock/sunxi.txt | 1 +
> drivers/clk/sunxi/clk-sunxi.c | 57 +++++++++++++++++++++++
> 2 files changed, 58 insertions(+)
>
> diff --git a/Documentation/devicetree/bindings/clock/sunxi.txt b/Documentation/devicetree/bindings/clock/sunxi.txt
> index 773f3ae..ff3f61c 100644
> --- a/Documentation/devicetree/bindings/clock/sunxi.txt
> +++ b/Documentation/devicetree/bindings/clock/sunxi.txt
> @@ -35,6 +35,7 @@ Required properties:
> "allwinner,sun7i-a20-apb1-gates-clk" - for the APB1 gates on A20
> "allwinner,sun6i-a31-apb2-div-clk" - for the APB2 gates on A31
> "allwinner,sun6i-a31-apb2-gates-clk" - for the APB2 gates on A31
> + "allwinner,sun4i-mod0-clk" - for the module 0 family of clocks
>
> Required properties for all clocks:
> - reg : shall be the control register address for the clock.
> diff --git a/drivers/clk/sunxi/clk-sunxi.c b/drivers/clk/sunxi/clk-sunxi.c
> index b1210f3..163a3d8 100644
> --- a/drivers/clk/sunxi/clk-sunxi.c
> +++ b/drivers/clk/sunxi/clk-sunxi.c
> @@ -287,6 +287,47 @@ static void sun4i_get_apb1_factors(u32 *freq, u32 parent_rate,
>
>
> /**
> + * sun4i_get_mod0_factors() - calculates m, n factors for MOD0-style clocks
> + * MMC rate is calculated as follows
> + * rate = (parent_rate >> p) / (m + 1);
> + */
> +
> +static void sun4i_get_mod0_factors(u32 *freq, u32 parent_rate,
> + u8 *n, u8 *k, u8 *m, u8 *p)
> +{
> + 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;
> +
> + div = parent_rate / *freq;
> +
> + if (div < 16)
> + calcp = 0;
> + else if (div / 2 < 16)
> + calcp = 1;
> + else if (div / 4 < 16)
> + calcp = 2;
> + else
> + calcp = 3;
> +
> + calcm = DIV_ROUND_UP(div, 1 << calcp);
> +
> + *freq = (parent_rate >> calcp) / calcm;
> +
> + /* we were called to round the frequency, we can now return */
> + if (n == NULL)
> + return;
> +
> + *m = calcm - 1;
> + *p = calcp;
> +}
> +
> +
> +
> +/**
> * sunxi_factors_clk_setup() - Setup function for factor clocks
> */
>
> @@ -333,6 +374,14 @@ static struct clk_factors_config sun4i_apb1_config = {
> .pwidth = 2,
> };
>
> +/* user manual says "n" but it's really "p" */
> +static struct clk_factors_config sun4i_mod0_config = {
> + .mshift = 0,
> + .mwidth = 4,
> + .pshift = 16,
> + .pwidth = 2,
> +};
> +
> static const struct factors_data sun4i_pll1_data __initconst = {
> .enable = 31,
> .table = &sun4i_pll1_config,
> @@ -356,6 +405,13 @@ static const struct factors_data sun4i_apb1_data __initconst = {
> .getter = sun4i_get_apb1_factors,
> };
>
> +static const struct factors_data sun4i_mod0_data __initconst = {
> + .enable = 31,
> + .mux = 24,
> + .table = &sun4i_mod0_config,
> + .getter = sun4i_get_mod0_factors,
> +};
How are the parents handled here for the mux part? Do you expect the
different parents in a precise order in the device tree, so that you
have a direct mapping to the value to put in the muxing registers, or do
you have a smarter way to do it?
Thanks,
Maxime
--
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20130930/91612c54/attachment-0001.sig>
^ permalink raw reply [flat|nested] 20+ messages in thread
* [PATCH 00/10] clk: sunxi: PLL4/5/6, mod0 and mbus support
2013-09-29 3:49 [PATCH 00/10] clk: sunxi: PLL4/5/6, mod0 and mbus support Emilio López
` (9 preceding siblings ...)
2013-09-29 3:49 ` [PATCH 10/10] ARM: sunxi: dt: add nodes for the mbus clock Emilio López
@ 2013-09-30 17:38 ` Maxime Ripard
10 siblings, 0 replies; 20+ messages in thread
From: Maxime Ripard @ 2013-09-30 17:38 UTC (permalink / raw)
To: linux-arm-kernel
Hi Emilio,
On Sun, Sep 29, 2013 at 12:49:29AM -0300, Emilio L?pez wrote:
> Hi everyone,
>
> This is a followup series to my RFC series from some time ago. It adds
> PLL4, PLL5, PLL6 and mod0 support on sun4i, sun5i and sun7i. Additionally,
> mbus is supported on sun5i and sun7i. I would like to see this merged for
> 3.13, so all feedback is welcome :)
>
> Cheers,
I'm fine with all the patches I didn't comment on.
You can add my Acked-by on those.
Thanks!
Maxime
--
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20130930/3bfe0869/attachment.sig>
^ permalink raw reply [flat|nested] 20+ messages in thread
* [PATCH 04/10] clk: sunxi: add PLL5 and PLL6 support
2013-09-30 17:21 ` Maxime Ripard
@ 2013-09-30 23:29 ` Emilio López
2013-10-03 10:32 ` Maxime Ripard
0 siblings, 1 reply; 20+ messages in thread
From: Emilio López @ 2013-09-30 23:29 UTC (permalink / raw)
To: linux-arm-kernel
Hi Maxime,
El 30/09/13 14:21, Maxime Ripard escribi?:
> Hi Emilio,
>
> On Sun, Sep 29, 2013 at 12:49:33AM -0300, Emilio L?pez wrote:
>> This commit implements PLL5 and PLL6 support on the sunxi clock driver.
>> These PLLs use a similar factor clock, but differ on their outputs.
>>
>> Signed-off-by: Emilio L?pez <emilio@elopez.com.ar>
>> ---
>> Documentation/devicetree/bindings/clock/sunxi.txt | 2 +
>> drivers/clk/sunxi/clk-sunxi.c | 182 +++++++++++++++++++++-
>> 2 files changed, 177 insertions(+), 7 deletions(-)
>>
>> diff --git a/Documentation/devicetree/bindings/clock/sunxi.txt b/Documentation/devicetree/bindings/clock/sunxi.txt
>> index 7d9245f..773f3ae 100644
>> --- a/Documentation/devicetree/bindings/clock/sunxi.txt
>> +++ b/Documentation/devicetree/bindings/clock/sunxi.txt
>> @@ -9,6 +9,8 @@ Required properties:
>> "allwinner,sun4i-osc-clk" - for a gatable oscillator
>> "allwinner,sun4i-pll1-clk" - for the main PLL clock and PLL4
>> "allwinner,sun6i-a31-pll1-clk" - for the main PLL clock on A31
>> + "allwinner,sun4i-pll5-clk" - for the PLL5 clock
>> + "allwinner,sun4i-pll6-clk" - for the PLL6 clock
>> "allwinner,sun4i-cpu-clk" - for the CPU multiplexer clock
>> "allwinner,sun4i-axi-clk" - for the AXI clock
>> "allwinner,sun4i-axi-gates-clk" - for the AXI gates
>> diff --git a/drivers/clk/sunxi/clk-sunxi.c b/drivers/clk/sunxi/clk-sunxi.c
>> index 77b9f57..b1210f3 100644
>> --- a/drivers/clk/sunxi/clk-sunxi.c
>> +++ b/drivers/clk/sunxi/clk-sunxi.c
>> @@ -210,6 +210,40 @@ static void sun6i_a31_get_pll1_factors(u32 *freq, u32 parent_rate,
>> }
>>
>> /**
>> + * sun4i_get_pll5_factors() - calculates n, k factors for PLL5
>> + * PLL5 rate is calculated as follows
>> + * rate = parent_rate * n * (k + 1)
>> + * parent_rate is always 24Mhz
>> + */
>> +
>> +static void sun4i_get_pll5_factors(u32 *freq, u32 parent_rate,
>> + u8 *n, u8 *k, u8 *m, u8 *p)
>> +{
>> + u8 div;
>> +
>> + /* Normalize value to a 24M multiple */
>> + div = *freq / 24000000;
>> + *freq = 24000000 * div;
>
> parent_rate here maybe ?
I'll change it, makes sense even if parent is always 24M.
>> +
>> + /* we were called to round the frequency, we can now return */
>> + if (n == NULL)
>> + return;
>> +
>> + if (div < 31)
>> + *k = 0;
>> + else if (div / 2 < 31)
>> + *k = 1;
>> + else if (div / 3 < 31)
>> + *k = 2;
>> + else
>> + *k = 3;
>> +
>> + *n = DIV_ROUND_UP(div, (*k+1));
>> +}
>> +
>> +
>> +
>> +/**
>> * sun4i_get_apb1_factors() - calculates m, p factors for APB1
>> * APB1 rate is calculated as follows
>> * rate = (parent_rate >> p) / (m + 1);
>> @@ -285,6 +319,13 @@ static struct clk_factors_config sun6i_a31_pll1_config = {
>> .mwidth = 2,
>> };
>>
>> +static struct clk_factors_config sun4i_pll5_config = {
>> + .nshift = 8,
>> + .nwidth = 5,
>> + .kshift = 4,
>> + .kwidth = 2,
>> +};
>> +
>
> The spacing between your functions and structures looks odd. You were
> using 3 newlines the change just above, and now just one?
I'll review the spacing, I use one newline in between elements of the
same set, and three to separate blocks (eg factor related code from
divisor related code)
>> static struct clk_factors_config sun4i_apb1_config = {
>> .mshift = 0,
>> .mwidth = 5,
>> @@ -304,13 +345,19 @@ static const struct factors_data sun6i_a31_pll1_data __initconst = {
>> .getter = sun6i_a31_get_pll1_factors,
>> };
>>
>> +static const struct factors_data sun4i_pll5_data __initconst = {
>> + .enable = 31,
>> + .table = &sun4i_pll5_config,
>> + .getter = sun4i_get_pll5_factors,
>> +};
>> +
>> static const struct factors_data sun4i_apb1_data __initconst = {
>> .table = &sun4i_apb1_config,
>> .getter = sun4i_get_apb1_factors,
>> };
>>
>> -static void __init sunxi_factors_clk_setup(struct device_node *node,
>> - struct factors_data *data)
>> +static struct clk * __init sunxi_factors_clk_setup(struct device_node *node,
>> + const struct factors_data *data)
>
> While this change is probably useful, I don't see how it relates to the
> change described in your commit log. Either split these patches, or
> explain why it's needed.
I'll split this into another patch. The change is needed to run
sunxi_factors_clk_setup() in sunxi_divs_clk_setup() while being able to
get the struct clk *
>
>> {
>> struct clk *clk;
>> struct clk_factors *factors;
>> @@ -321,6 +368,7 @@ static void __init sunxi_factors_clk_setup(struct device_node *node,
>> const char *clk_name = node->name;
>> const char *parents[5];
>> void *reg;
>> + unsigned long flags;
>> int i = 0;
>>
>> reg = of_iomap(node, 0);
>> @@ -331,14 +379,14 @@ static void __init sunxi_factors_clk_setup(struct device_node *node,
>>
>> factors = kzalloc(sizeof(struct clk_factors), GFP_KERNEL);
>> if (!factors)
>> - return;
>> + return NULL;
>>
>> /* 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;
>> + return NULL;
>> }
>>
>> /* set up gate properties */
>> @@ -354,7 +402,7 @@ static void __init sunxi_factors_clk_setup(struct device_node *node,
>> if (!mux) {
>> kfree(factors);
>> kfree(gate);
>> - return;
>> + return NULL;
>> }
>>
>> /* set up gate properties */
>> @@ -371,17 +419,21 @@ static void __init sunxi_factors_clk_setup(struct device_node *node,
>> factors->get_factors = data->getter;
>> factors->lock = &clk_lock;
>>
>> + /* We should not disable pll5, it powers the RAM */
>> + flags = !strcmp("pll5", clk_name) ? CLK_IGNORE_UNUSED : 0;
>> +
>> clk = clk_register_composite(NULL, clk_name,
>> parents, i,
>> mux_hw, &clk_mux_ops,
>> &factors->hw, &clk_factors_ops,
>> - gate_hw, &clk_gate_ops,
>> - i ? 0 : CLK_IS_ROOT);
>> + gate_hw, &clk_gate_ops, flags);
>>
>> if (!IS_ERR(clk)) {
>> of_clk_add_provider(node, of_clk_src_simple_get, clk);
>> clk_register_clkdev(clk, clk_name, NULL);
>> }
>> +
>> + return clk;
>> }
>>
>>
>> @@ -616,6 +668,112 @@ static void __init sunxi_gates_clk_setup(struct device_node *node,
>> of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
>> }
>>
>> +
>> +
>> +/**
>> + * sunxi_divs_clk_setup() - Setup function for leaf divisors on clocks
>> + */
>
> This comment doesn't seem to be at the right place in your code.
I use these comments as kind of a delimiter too, all the struct
definitions done below are used on sunxi_divs_clk_setup, which is
immediately after. Factors, mux, dividers and gates have the comment
that way too.
>> +#define SUNXI_DIVS_MAX_QTY 2
>> +#define SUNXI_DIVISOR_WIDTH 2
>> +
>> +struct divs_data {
>> + const struct factors_data *factors; /* data for the factor clock */
>> + struct {
>> + u8 fixed; /* is it a fixed divisor? if not... */
>> + struct clk_div_table *table; /* is it a table based divisor? */
>> + u8 shift; /* otherwise it's a normal divisor with this shift */
>> + u8 pow; /* is it power-of-two based? */
>> + } div[SUNXI_DIVS_MAX_QTY];
>> +};
>> +
>> +static struct clk_div_table pll6_sata_table[] = {
>> + { .val = 0, .div = 6, },
>> + { .val = 1, .div = 12, },
>> + { .val = 2, .div = 18, },
>> + { .val = 3, .div = 24, },
>> + { } /* sentinel */
>> +};
>> +
>> +static const struct divs_data pll5_divs_data __initconst = {
>> + .factors = &sun4i_pll5_data,
>> + .div = {
>> + { .shift = 0, .pow = 0, }, /* M, DDR */
>> + { .shift = 16, .pow = 1, }, /* P, other */
>> + }
>> +};
>> +
>> +static const struct divs_data pll6_divs_data __initconst = {
>> + .factors = &sun4i_pll5_data,
>> + .div = {
>> + { .shift = 0, .table = pll6_sata_table }, /* M, SATA */
>> + { .fixed = 2 }, /* P, other */
>> + }
>> +};
>> +
>> +static void __init sunxi_divs_clk_setup(struct device_node *node,
>> + struct divs_data *data)
>> +{
>> + struct clk_onecell_data *clk_data;
>> + const char *parent = node->name;
>> + const char *clk_name;
>> + struct clk **clks, *pclk;
>> + void *reg;
>> + int i = 0;
>> + int flags, clkflags;
>> +
>> + /* Set up factor clock that we will be dividing */
>> + pclk = sunxi_factors_clk_setup(node, data->factors);
>> +
>> + reg = of_iomap(node, 0);
>> +
>> + clk_data = kmalloc(sizeof(struct clk_onecell_data), GFP_KERNEL);
>> + if (!clk_data)
>> + return;
>
> An extra newline would be great here.
Ok
>> + clks = kzalloc(SUNXI_DIVS_MAX_QTY * sizeof(struct clk *), GFP_KERNEL);
>> + if (!clks) {
>> + kfree(clk_data);
>> + return;
>> + }
>> + clk_data->clks = clks;
>> +
>> + /* It's not a good idea to have automatic reparenting changing
>> + * our RAM clock! */
>> + clkflags = !strcmp("pll5", parent) ? 0 : CLK_SET_RATE_PARENT;
>> +
>> + for (i = 0; i < SUNXI_DIVS_MAX_QTY; i++) {
>> + if (of_property_read_string_index(node, "clock-output-names",
>> + i, &clk_name) != 0)
>> + break;
>> +
>> + if (data->div[i].fixed) {
>> + clks[i] = clk_register_fixed_factor(NULL, clk_name,
>> + parent, clkflags,
>> + 1, data->div[i].fixed);
>> + } else {
>> + flags = data->div[i].pow ? CLK_DIVIDER_POWER_OF_TWO : 0;
>> + clks[i] = clk_register_divider_table(NULL, clk_name,
>> + parent, clkflags, reg,
>> + data->div[i].shift,
>> + SUNXI_DIVISOR_WIDTH, flags,
>> + data->div[i].table, &clk_lock);
>> + }
>
> Hmmm, I don't get why you were calling sunxi_clk_factors_setup
> unconditionally, and now you put a condition on the registration?
The factor clock is the 'parent' part and the condition is there to
decide which kind of divisor gets registered under it. For example
PLL6 CLOCK
________________________
| ___pll6_sata---|----> to consumer
osc24M->--| pll6--/___pll6_other--|----> to consumer
| \_______________|____> to consumer
|________________________|
pll6 is the factor part, pll6_sata is a table divider, and pll6_other is
a fixed factor
> (Plus, your indentation here looks a bit odd.)
If I align the parameters with the starting (, I can fit at most 1
parameter per line and I end up with a pile of mostly unreadable
parameters which uses a lot of lines (and still some don't fit in under
80 cols). I thought using one tab less was a good compromise, and
preferable to going over 80 chars. If you have any better suggestion,
I'm all ears :)
>> +
>> + WARN_ON(IS_ERR(clk_data->clks[i]));
>> + clk_register_clkdev(clks[i], clk_name, NULL);
>> + }
>> +
>> + /* The last clock available on the getter is the parent */
>> + clks[i++] = pclk;
>> +
>> + /* Adjust to the real max */
>> + clk_data->clk_num = i;
>> +
>> + of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
>> +}
>> +
>> +
>> +
>> /* Matches for factors clocks */
>> static const struct of_device_id clk_factors_match[] __initconst = {
>> {.compatible = "allwinner,sun4i-pll1-clk", .data = &sun4i_pll1_data,},
>> @@ -633,6 +791,13 @@ static const struct of_device_id clk_div_match[] __initconst = {
>> {}
>> };
>>
>> +/* Matches for divided outputs */
>> +static const struct of_device_id clk_divs_match[] __initconst = {
>> + {.compatible = "allwinner,sun4i-pll5-clk", .data = &pll5_divs_data,},
>> + {.compatible = "allwinner,sun4i-pll6-clk", .data = &pll6_divs_data,},
>> + {}
>> +};
>> +
>> /* Matches for mux clocks */
>> static const struct of_device_id clk_mux_match[] __initconst = {
>> {.compatible = "allwinner,sun4i-cpu-clk", .data = &sun4i_cpu_mux_data,},
>> @@ -713,6 +878,9 @@ void __init sunxi_init_clocks(void)
>> /* Register divider clocks */
>> of_sunxi_table_clock_setup(clk_div_match, sunxi_divider_clk_setup);
>>
>> + /* Register divided output clocks */
>> + of_sunxi_table_clock_setup(clk_divs_match, sunxi_divs_clk_setup);
>> +
>> /* Register mux clocks */
>> of_sunxi_table_clock_setup(clk_mux_match, sunxi_mux_clk_setup);
>>
>> --
>> 1.8.4
>>
Thanks for reviewing this!
Emilio
^ permalink raw reply [flat|nested] 20+ messages in thread
* [PATCH 06/10] clk: sunxi: mod0 support
2013-09-30 17:35 ` Maxime Ripard
@ 2013-09-30 23:37 ` Emilio López
2013-10-02 14:38 ` Maxime Ripard
0 siblings, 1 reply; 20+ messages in thread
From: Emilio López @ 2013-09-30 23:37 UTC (permalink / raw)
To: linux-arm-kernel
Hi Maxime,
El 30/09/13 14:35, Maxime Ripard escribi?:
> Hi Emilio,
>
> Overall, it looks fine, I just have a small question.
>
> On Sun, Sep 29, 2013 at 12:49:35AM -0300, Emilio L?pez wrote:
>> This commit implements support for the "module 0" type of clocks, as
>> used by MMC, IR, NAND, SATA and other components.
>>
>> Signed-off-by: Emilio L?pez <emilio@elopez.com.ar>
>> ---
>> Documentation/devicetree/bindings/clock/sunxi.txt | 1 +
>> drivers/clk/sunxi/clk-sunxi.c | 57 +++++++++++++++++++++++
>> 2 files changed, 58 insertions(+)
>>
>> diff --git a/Documentation/devicetree/bindings/clock/sunxi.txt b/Documentation/devicetree/bindings/clock/sunxi.txt
>> index 773f3ae..ff3f61c 100644
>> --- a/Documentation/devicetree/bindings/clock/sunxi.txt
>> +++ b/Documentation/devicetree/bindings/clock/sunxi.txt
>> @@ -35,6 +35,7 @@ Required properties:
>> "allwinner,sun7i-a20-apb1-gates-clk" - for the APB1 gates on A20
>> "allwinner,sun6i-a31-apb2-div-clk" - for the APB2 gates on A31
>> "allwinner,sun6i-a31-apb2-gates-clk" - for the APB2 gates on A31
>> + "allwinner,sun4i-mod0-clk" - for the module 0 family of clocks
>>
>> Required properties for all clocks:
>> - reg : shall be the control register address for the clock.
>> diff --git a/drivers/clk/sunxi/clk-sunxi.c b/drivers/clk/sunxi/clk-sunxi.c
>> index b1210f3..163a3d8 100644
>> --- a/drivers/clk/sunxi/clk-sunxi.c
>> +++ b/drivers/clk/sunxi/clk-sunxi.c
>> @@ -287,6 +287,47 @@ static void sun4i_get_apb1_factors(u32 *freq, u32 parent_rate,
>>
>>
>> /**
>> + * sun4i_get_mod0_factors() - calculates m, n factors for MOD0-style clocks
>> + * MMC rate is calculated as follows
>> + * rate = (parent_rate >> p) / (m + 1);
>> + */
>> +
>> +static void sun4i_get_mod0_factors(u32 *freq, u32 parent_rate,
>> + u8 *n, u8 *k, u8 *m, u8 *p)
>> +{
>> + 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;
>> +
>> + div = parent_rate / *freq;
>> +
>> + if (div < 16)
>> + calcp = 0;
>> + else if (div / 2 < 16)
>> + calcp = 1;
>> + else if (div / 4 < 16)
>> + calcp = 2;
>> + else
>> + calcp = 3;
>> +
>> + calcm = DIV_ROUND_UP(div, 1 << calcp);
>> +
>> + *freq = (parent_rate >> calcp) / calcm;
>> +
>> + /* we were called to round the frequency, we can now return */
>> + if (n == NULL)
>> + return;
>> +
>> + *m = calcm - 1;
>> + *p = calcp;
>> +}
>> +
>> +
>> +
>> +/**
>> * sunxi_factors_clk_setup() - Setup function for factor clocks
>> */
>>
>> @@ -333,6 +374,14 @@ static struct clk_factors_config sun4i_apb1_config = {
>> .pwidth = 2,
>> };
>>
>> +/* user manual says "n" but it's really "p" */
>> +static struct clk_factors_config sun4i_mod0_config = {
>> + .mshift = 0,
>> + .mwidth = 4,
>> + .pshift = 16,
>> + .pwidth = 2,
>> +};
>> +
>> static const struct factors_data sun4i_pll1_data __initconst = {
>> .enable = 31,
>> .table = &sun4i_pll1_config,
>> @@ -356,6 +405,13 @@ static const struct factors_data sun4i_apb1_data __initconst = {
>> .getter = sun4i_get_apb1_factors,
>> };
>>
>> +static const struct factors_data sun4i_mod0_data __initconst = {
>> + .enable = 31,
>> + .mux = 24,
>> + .table = &sun4i_mod0_config,
>> + .getter = sun4i_get_mod0_factors,
>> +};
>
> How are the parents handled here for the mux part? Do you expect the
> different parents in a precise order in the device tree, so that you
> have a direct mapping to the value to put in the muxing registers, or do
> you have a smarter way to do it?
Indeed, the parents must be indicated on the DT using the same order as
on the register. In other words, it works the same as all the other
muxes we have implemented so far. The clock corresponding to bits 00
goes first, then the one corresponding to 01, etc.
Cheers,
Emilio
^ permalink raw reply [flat|nested] 20+ messages in thread
* [PATCH 06/10] clk: sunxi: mod0 support
2013-09-30 23:37 ` Emilio López
@ 2013-10-02 14:38 ` Maxime Ripard
0 siblings, 0 replies; 20+ messages in thread
From: Maxime Ripard @ 2013-10-02 14:38 UTC (permalink / raw)
To: linux-arm-kernel
Hi Emilio
On Mon, Sep 30, 2013 at 08:37:46PM -0300, Emilio L?pez wrote:
> >>+static const struct factors_data sun4i_mod0_data __initconst = {
> >>+ .enable = 31,
> >>+ .mux = 24,
> >>+ .table = &sun4i_mod0_config,
> >>+ .getter = sun4i_get_mod0_factors,
> >>+};
> >
> >How are the parents handled here for the mux part? Do you expect the
> >different parents in a precise order in the device tree, so that you
> >have a direct mapping to the value to put in the muxing registers, or do
> >you have a smarter way to do it?
>
> Indeed, the parents must be indicated on the DT using the same order
> as on the register. In other words, it works the same as all the
> other muxes we have implemented so far. The clock corresponding to
> bits 00 goes first, then the one corresponding to 01, etc.
Ok. It should be documented in the bindings doc then.
Thanks!
Maxime
--
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20131002/0d81db3f/attachment.sig>
^ permalink raw reply [flat|nested] 20+ messages in thread
* [PATCH 04/10] clk: sunxi: add PLL5 and PLL6 support
2013-09-30 23:29 ` Emilio López
@ 2013-10-03 10:32 ` Maxime Ripard
0 siblings, 0 replies; 20+ messages in thread
From: Maxime Ripard @ 2013-10-03 10:32 UTC (permalink / raw)
To: linux-arm-kernel
On Mon, Sep 30, 2013 at 08:29:30PM -0300, Emilio L?pez wrote:
> El 30/09/13 14:21, Maxime Ripard escribi?:
> >On Sun, Sep 29, 2013 at 12:49:33AM -0300, Emilio L?pez wrote:
> >>+/**
> >>+ * sunxi_divs_clk_setup() - Setup function for leaf divisors on clocks
> >>+ */
> >
> >This comment doesn't seem to be at the right place in your code.
>
> I use these comments as kind of a delimiter too, all the struct
> definitions done below are used on sunxi_divs_clk_setup, which is
> immediately after. Factors, mux, dividers and gates have the comment
> that way too.
Still, it looks odd that you're mostly commenting a function here, while
the function is 20-ish lines below. Maybe you can just add a small
comment here saying something like "Here come drag^Wclock dividers".
> >>+ clks = kzalloc(SUNXI_DIVS_MAX_QTY * sizeof(struct clk *), GFP_KERNEL);
> >>+ if (!clks) {
> >>+ kfree(clk_data);
> >>+ return;
> >>+ }
> >>+ clk_data->clks = clks;
> >>+
> >>+ /* It's not a good idea to have automatic reparenting changing
> >>+ * our RAM clock! */
> >>+ clkflags = !strcmp("pll5", parent) ? 0 : CLK_SET_RATE_PARENT;
> >>+
> >>+ for (i = 0; i < SUNXI_DIVS_MAX_QTY; i++) {
> >>+ if (of_property_read_string_index(node, "clock-output-names",
> >>+ i, &clk_name) != 0)
> >>+ break;
> >>+
> >>+ if (data->div[i].fixed) {
> >>+ clks[i] = clk_register_fixed_factor(NULL, clk_name,
> >>+ parent, clkflags,
> >>+ 1, data->div[i].fixed);
> >>+ } else {
> >>+ flags = data->div[i].pow ? CLK_DIVIDER_POWER_OF_TWO : 0;
> >>+ clks[i] = clk_register_divider_table(NULL, clk_name,
> >>+ parent, clkflags, reg,
> >>+ data->div[i].shift,
> >>+ SUNXI_DIVISOR_WIDTH, flags,
> >>+ data->div[i].table, &clk_lock);
> >>+ }
> >
> >Hmmm, I don't get why you were calling sunxi_clk_factors_setup
> >unconditionally, and now you put a condition on the registration?
>
> The factor clock is the 'parent' part and the condition is there to
> decide which kind of divisor gets registered under it. For example
>
> PLL6 CLOCK
> ________________________
> | ___pll6_sata---|----> to consumer
> osc24M->--| pll6--/___pll6_other--|----> to consumer
> | \_______________|____> to consumer
> |________________________|
>
>
> pll6 is the factor part, pll6_sata is a table divider, and
> pll6_other is a fixed factor
That should definitely go in the comments :)
>
> >(Plus, your indentation here looks a bit odd.)
>
> If I align the parameters with the starting (, I can fit at most 1
> parameter per line and I end up with a pile of mostly unreadable
> parameters which uses a lot of lines (and still some don't fit in
> under 80 cols). I thought using one tab less was a good compromise,
> and preferable to going over 80 chars. If you have any better
> suggestion, I'm all ears :)
Ok, whatever you feel best in that case.
Thanks!
Maxime
--
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20131003/0c450dcc/attachment-0001.sig>
^ permalink raw reply [flat|nested] 20+ messages in thread
end of thread, other threads:[~2013-10-03 10:32 UTC | newest]
Thread overview: 20+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2013-09-29 3:49 [PATCH 00/10] clk: sunxi: PLL4/5/6, mod0 and mbus support Emilio López
2013-09-29 3:49 ` [PATCH 01/10] clk: sunxi: register factors clocks behind composite Emilio López
2013-09-30 17:03 ` Maxime Ripard
2013-09-29 3:49 ` [PATCH 02/10] clk: sunxi: add gating support to PLL1 Emilio López
2013-09-30 17:05 ` Maxime Ripard
2013-09-29 3:49 ` [PATCH 03/10] ARM: sunxi: add PLL4 support Emilio López
2013-09-29 3:49 ` [PATCH 04/10] clk: sunxi: add PLL5 and PLL6 support Emilio López
2013-09-30 17:21 ` Maxime Ripard
2013-09-30 23:29 ` Emilio López
2013-10-03 10:32 ` Maxime Ripard
2013-09-29 3:49 ` [PATCH 05/10] ARM: " Emilio López
2013-09-29 3:49 ` [PATCH 06/10] clk: sunxi: mod0 support Emilio López
2013-09-30 17:35 ` Maxime Ripard
2013-09-30 23:37 ` Emilio López
2013-10-02 14:38 ` Maxime Ripard
2013-09-29 3:49 ` [PATCH 07/10] ARM: sun4i: dt: mod0 clocks Emilio López
2013-09-29 3:49 ` [PATCH 08/10] ARM: sun5i: " Emilio López
2013-09-29 3:49 ` [PATCH 09/10] ARM: sun7i: " Emilio López
2013-09-29 3:49 ` [PATCH 10/10] ARM: sunxi: dt: add nodes for the mbus clock Emilio López
2013-09-30 17:38 ` [PATCH 00/10] clk: sunxi: PLL4/5/6, mod0 and mbus support Maxime Ripard
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).