linux-arm-kernel.lists.infradead.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/5] clk: sunxi: Add peripheral bus clock support for A80
@ 2014-10-12  9:40 Chen-Yu Tsai
  2014-10-12  9:40 ` [PATCH 1/5] clk: sunxi: make factors clock mux mask configurable Chen-Yu Tsai
                   ` (5 more replies)
  0 siblings, 6 replies; 16+ messages in thread
From: Chen-Yu Tsai @ 2014-10-12  9:40 UTC (permalink / raw)
  To: linux-arm-kernel

Hi everyone,

This series adds support for the basic bus (AHB/APB) clocks used by
peripherals on the A80 SoC. This series is based on my previous A80
bringup series.

The A80 has 5 peripheral related bus clocks, 1 data bus clock, and 1
CCI bus clock. 2 out of 12 PLLs are used to clock these.

Patch 1 adds support for configurable mux masks in sunxi factors clocks.
This was previously hardcoded to a width of 2 bits, or a 0x3 mask.

Patch 2 adds support for the clocks mentioned above.

Patch 3 adds support for the bus gate clocks for the peripheral modules.

Patch 4 selects ARCH_HAS_RESET_CONTROLLER and RESET_CONTROLLER when building
for sun9i so the user does not forget to enable reset controller support.

Patch 5 adds the clocks and reset controls to the dtsi.

CPU and specific purpose (audio/video/gpu) PLLs have been left out.
These can be added as the need comes. CPU PLLs (PLL1/2) should probably be
added along with cpufreq support.


Cheers
ChenYu


Chen-Yu Tsai (5):
  clk: sunxi: make factors clock mux mask configurable
  clk: sunxi: Add support for A80 basic bus clocks
  clk: sunxi: Add support for bus clock gates on Allwinner A80 SoC
  ARM: sunxi: Select ARCH_HAS_RESET_CONTROLLER and RESET_CONTROLLER for
    sun9i
  ARM: dts: sun9i: Add basic clocks and reset controls

 Documentation/devicetree/bindings/clock/sunxi.txt |  10 +
 arch/arm/boot/dts/sun9i-a80.dtsi                  | 177 +++++++++++++-
 arch/arm/mach-sunxi/Kconfig                       |   2 +
 drivers/clk/sunxi/Makefile                        |   1 +
 drivers/clk/sunxi/clk-factors.c                   |   2 +-
 drivers/clk/sunxi/clk-factors.h                   |   3 +-
 drivers/clk/sunxi/clk-mod0.c                      |   1 +
 drivers/clk/sunxi/clk-sun8i-mbus.c                |   1 +
 drivers/clk/sunxi/clk-sun9i-core.c                | 272 ++++++++++++++++++++++
 drivers/clk/sunxi/clk-sunxi.c                     |  32 +++
 10 files changed, 492 insertions(+), 9 deletions(-)
 create mode 100644 drivers/clk/sunxi/clk-sun9i-core.c

-- 
2.1.1

^ permalink raw reply	[flat|nested] 16+ messages in thread

* [PATCH 1/5] clk: sunxi: make factors clock mux mask configurable
  2014-10-12  9:40 [PATCH 0/5] clk: sunxi: Add peripheral bus clock support for A80 Chen-Yu Tsai
@ 2014-10-12  9:40 ` Chen-Yu Tsai
  2014-10-12  9:40 ` [PATCH 2/5] clk: sunxi: Add support for A80 basic bus clocks Chen-Yu Tsai
                   ` (4 subsequent siblings)
  5 siblings, 0 replies; 16+ messages in thread
From: Chen-Yu Tsai @ 2014-10-12  9:40 UTC (permalink / raw)
  To: linux-arm-kernel

Some of the factors-style clocks on the A80 have different widths
for the mux values in the registers.

Add a .muxmask field to clk_factors_config to make it configurable.
Passing a bitmask instead of a width parameter will allow reuse
in case we support table-based muxes in the future.

Signed-off-by: Chen-Yu Tsai <wens@csie.org>
---
 drivers/clk/sunxi/clk-factors.c    | 2 +-
 drivers/clk/sunxi/clk-factors.h    | 3 +--
 drivers/clk/sunxi/clk-mod0.c       | 1 +
 drivers/clk/sunxi/clk-sun8i-mbus.c | 1 +
 drivers/clk/sunxi/clk-sunxi.c      | 1 +
 5 files changed, 5 insertions(+), 3 deletions(-)

diff --git a/drivers/clk/sunxi/clk-factors.c b/drivers/clk/sunxi/clk-factors.c
index f83ba09..5521e86 100644
--- a/drivers/clk/sunxi/clk-factors.c
+++ b/drivers/clk/sunxi/clk-factors.c
@@ -224,7 +224,7 @@ struct clk * __init sunxi_factors_register(struct device_node *node,
 		/* set up gate properties */
 		mux->reg = reg;
 		mux->shift = data->mux;
-		mux->mask = SUNXI_FACTORS_MUX_MASK;
+		mux->mask = data->muxmask;
 		mux->lock = factors->lock;
 		mux_hw = &mux->hw;
 	}
diff --git a/drivers/clk/sunxi/clk-factors.h b/drivers/clk/sunxi/clk-factors.h
index 9913840..912238f 100644
--- a/drivers/clk/sunxi/clk-factors.h
+++ b/drivers/clk/sunxi/clk-factors.h
@@ -7,8 +7,6 @@
 
 #define SUNXI_FACTORS_NOT_APPLICABLE	(0)
 
-#define SUNXI_FACTORS_MUX_MASK 0x3
-
 struct clk_factors_config {
 	u8 nshift;
 	u8 nwidth;
@@ -24,6 +22,7 @@ struct clk_factors_config {
 struct factors_data {
 	int enable;
 	int mux;
+	int muxmask;
 	struct clk_factors_config *table;
 	void (*getter) (u32 *rate, u32 parent_rate, u8 *n, u8 *k, u8 *m, u8 *p);
 	const char *name;
diff --git a/drivers/clk/sunxi/clk-mod0.c b/drivers/clk/sunxi/clk-mod0.c
index 4a56385..da0524ea 100644
--- a/drivers/clk/sunxi/clk-mod0.c
+++ b/drivers/clk/sunxi/clk-mod0.c
@@ -70,6 +70,7 @@ static struct clk_factors_config sun4i_a10_mod0_config = {
 static const struct factors_data sun4i_a10_mod0_data __initconst = {
 	.enable = 31,
 	.mux = 24,
+	.muxmask = BIT(1) | BIT(0),
 	.table = &sun4i_a10_mod0_config,
 	.getter = sun4i_a10_get_mod0_factors,
 };
diff --git a/drivers/clk/sunxi/clk-sun8i-mbus.c b/drivers/clk/sunxi/clk-sun8i-mbus.c
index 8e49b44..ef49786 100644
--- a/drivers/clk/sunxi/clk-sun8i-mbus.c
+++ b/drivers/clk/sunxi/clk-sun8i-mbus.c
@@ -60,6 +60,7 @@ static struct clk_factors_config sun8i_a23_mbus_config = {
 static const struct factors_data sun8i_a23_mbus_data __initconst = {
 	.enable = 31,
 	.mux = 24,
+	.muxmask = BIT(1) | BIT(0),
 	.table = &sun8i_a23_mbus_config,
 	.getter = sun8i_a23_get_mbus_factors,
 };
diff --git a/drivers/clk/sunxi/clk-sunxi.c b/drivers/clk/sunxi/clk-sunxi.c
index d5dc951..636b8d7 100644
--- a/drivers/clk/sunxi/clk-sunxi.c
+++ b/drivers/clk/sunxi/clk-sunxi.c
@@ -514,6 +514,7 @@ static const struct factors_data sun4i_apb1_data __initconst = {
 static const struct factors_data sun7i_a20_out_data __initconst = {
 	.enable = 31,
 	.mux = 24,
+	.muxmask = BIT(1) | BIT(0),
 	.table = &sun7i_a20_out_config,
 	.getter = sun7i_a20_get_out_factors,
 };
-- 
2.1.1

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH 2/5] clk: sunxi: Add support for A80 basic bus clocks
  2014-10-12  9:40 [PATCH 0/5] clk: sunxi: Add peripheral bus clock support for A80 Chen-Yu Tsai
  2014-10-12  9:40 ` [PATCH 1/5] clk: sunxi: make factors clock mux mask configurable Chen-Yu Tsai
@ 2014-10-12  9:40 ` Chen-Yu Tsai
  2014-10-16  8:31   ` Maxime Ripard
  2014-10-12  9:40 ` [PATCH 3/5] clk: sunxi: Add support for bus clock gates on Allwinner A80 SoC Chen-Yu Tsai
                   ` (3 subsequent siblings)
  5 siblings, 1 reply; 16+ messages in thread
From: Chen-Yu Tsai @ 2014-10-12  9:40 UTC (permalink / raw)
  To: linux-arm-kernel

The A80 SoC has 12 PLL clocks, 3 AHB clocks, 2 APB clocks, and a
new "GT" bus, which I assume is some kind of data bus connecting
the processor cores, memory and various busses. Also there is a
bus clock for a ARM CCI400 module.

As far as I can tell, the GT bus and CCI400 bus clock must be
protected.

This patch adds driver support for peripheral related PLLs and
bus clocks on the A80. The GT and CCI400 clocks are added as well
as these 2 along with the PLLs they are clocked from must not be
disabled.

Signed-off-by: Chen-Yu Tsai <wens@csie.org>
---
 Documentation/devicetree/bindings/clock/sunxi.txt |   5 +
 drivers/clk/sunxi/Makefile                        |   1 +
 drivers/clk/sunxi/clk-sun9i-core.c                | 272 ++++++++++++++++++++++
 3 files changed, 278 insertions(+)
 create mode 100644 drivers/clk/sunxi/clk-sun9i-core.c

diff --git a/Documentation/devicetree/bindings/clock/sunxi.txt b/Documentation/devicetree/bindings/clock/sunxi.txt
index ed116df..7f1c486 100644
--- a/Documentation/devicetree/bindings/clock/sunxi.txt
+++ b/Documentation/devicetree/bindings/clock/sunxi.txt
@@ -10,14 +10,17 @@ Required properties:
 	"allwinner,sun4i-a10-pll1-clk" - for the main PLL clock and PLL4
 	"allwinner,sun6i-a31-pll1-clk" - for the main PLL clock on A31
 	"allwinner,sun8i-a23-pll1-clk" - for the main PLL clock on A23
+	"allwinner,sun9i-a80-pll4-clk" - for the peripheral PLLs on A80
 	"allwinner,sun4i-a10-pll5-clk" - for the PLL5 clock
 	"allwinner,sun4i-a10-pll6-clk" - for the PLL6 clock
 	"allwinner,sun6i-a31-pll6-clk" - for the PLL6 clock on A31
+	"allwinner,sun9i-a80-gt-clk" - for the GT bus clock on A80
 	"allwinner,sun4i-a10-cpu-clk" - for the CPU multiplexer clock
 	"allwinner,sun4i-a10-axi-clk" - for the AXI clock
 	"allwinner,sun8i-a23-axi-clk" - for the AXI clock on A23
 	"allwinner,sun4i-a10-axi-gates-clk" - for the AXI gates
 	"allwinner,sun4i-a10-ahb-clk" - for the AHB clock
+	"allwinner,sun9i-a80-ahb-clk" - for the AHB bus clocks on A80
 	"allwinner,sun4i-a10-ahb-gates-clk" - for the AHB gates on A10
 	"allwinner,sun5i-a13-ahb-gates-clk" - for the AHB gates on A13
 	"allwinner,sun5i-a10s-ahb-gates-clk" - for the AHB gates on A10s
@@ -29,6 +32,7 @@ Required properties:
 	"allwinner,sun4i-a10-apb0-clk" - for the APB0 clock
 	"allwinner,sun6i-a31-apb0-clk" - for the APB0 clock on A31
 	"allwinner,sun8i-a23-apb0-clk" - for the APB0 clock on A23
+	"allwinner,sun9i-a80-apb0-clk" - for the APB0 bus clock on A80
 	"allwinner,sun4i-a10-apb0-gates-clk" - for the APB0 gates on A10
 	"allwinner,sun5i-a13-apb0-gates-clk" - for the APB0 gates on A13
 	"allwinner,sun5i-a10s-apb0-gates-clk" - for the APB0 gates on A10s
@@ -36,6 +40,7 @@ Required properties:
 	"allwinner,sun7i-a20-apb0-gates-clk" - for the APB0 gates on A20
 	"allwinner,sun8i-a23-apb0-gates-clk" - for the APB0 gates on A23
 	"allwinner,sun4i-a10-apb1-clk" - for the APB1 clock
+	"allwinner,sun9i-a80-apb1-clk" - for the APB1 bus clock on A80
 	"allwinner,sun4i-a10-apb1-mux-clk" - for the APB1 clock muxing
 	"allwinner,sun4i-a10-apb1-gates-clk" - for the APB1 gates on A10
 	"allwinner,sun5i-a13-apb1-gates-clk" - for the APB1 gates on A13
diff --git a/drivers/clk/sunxi/Makefile b/drivers/clk/sunxi/Makefile
index 7ddc2b5..a66953c 100644
--- a/drivers/clk/sunxi/Makefile
+++ b/drivers/clk/sunxi/Makefile
@@ -7,6 +7,7 @@ obj-y += clk-a10-hosc.o
 obj-y += clk-a20-gmac.o
 obj-y += clk-mod0.o
 obj-y += clk-sun8i-mbus.o
+obj-y += clk-sun9i-core.o
 
 obj-$(CONFIG_MFD_SUN6I_PRCM) += \
 	clk-sun6i-ar100.o clk-sun6i-apb0.o clk-sun6i-apb0-gates.o \
diff --git a/drivers/clk/sunxi/clk-sun9i-core.c b/drivers/clk/sunxi/clk-sun9i-core.c
new file mode 100644
index 0000000..ba5f091
--- /dev/null
+++ b/drivers/clk/sunxi/clk-sun9i-core.c
@@ -0,0 +1,272 @@
+/*
+ * Copyright 2014 Chen-Yu Tsai
+ *
+ * Chen-Yu Tsai <wens@csie.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/clkdev.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/log2.h>
+
+#include "clk-factors.h"
+
+
+/**
+ * sun9i_a80_get_pll4_factors() - calculates n, p, m factors for PLL1
+ * PLL4 rate is calculated as follows
+ * rate = (parent_rate * n >> p) / (m + 1);
+ * parent_rate is always 24Mhz
+ *
+ * p and m are named div1 and div2 in Allwinner's SDK
+ */
+
+static void sun9i_a80_get_pll4_factors(u32 *freq, u32 parent_rate,
+				       u8 *n, u8 *k, u8 *m, u8 *p)
+{
+	int div;
+
+	/* Normalize value to a 6M multiple */
+	div = *freq / 6000000;
+
+	/* divs above 256 cannot be odd */
+	if (div > 256)
+		div &= ~0x1;
+
+	/* divs above 512 must be a multiple of 4 */
+	if (div > 512)
+		div &= ~0x3;
+
+	*freq = 6000000 * div;
+
+	/* we were called to round the frequency, we can now return */
+	if (n == NULL)
+		return;
+
+	/* p will be 1 for divs under 512 */
+	if (div < 512)
+		*p = 1;
+	else
+		*p = 0;
+
+	/* m will be 1 if div is odd */
+	if (div & 1)
+		*m = 1;
+	else
+		*m = 0;
+
+	/* calculate a suitable n based on m and p */
+	*n = div / (*p + 1) / (*m + 1);
+}
+
+static struct clk_factors_config sun9i_a80_pll4_config = {
+	.mshift = 18,
+	.mwidth = 1,
+	.nshift = 8,
+	.nwidth = 8,
+	.pshift = 16,
+	.pwidth = 1,
+};
+
+static const struct factors_data sun9i_a80_pll4_data __initconst = {
+	.enable = 31,
+	.table = &sun9i_a80_pll4_config,
+	.getter = sun9i_a80_get_pll4_factors,
+};
+
+static DEFINE_SPINLOCK(sun9i_a80_pll4_lock);
+
+static void __init sun9i_a80_pll4_setup(struct device_node *node)
+{
+	sunxi_factors_register(node, &sun9i_a80_pll4_data, &sun9i_a80_pll4_lock);
+}
+CLK_OF_DECLARE(sun9i_a80_pll4, "allwinner,sun9i-a80-pll4-clk", sun9i_a80_pll4_setup);
+
+
+/**
+ * sun9i_a80_get_gt_factors() - calculates m factor for GT
+ * GT rate is calculated as follows
+ * rate = parent_rate / (m + 1);
+ */
+
+static void sun9i_a80_get_gt_factors(u32 *freq, u32 parent_rate,
+				     u8 *n, u8 *k, u8 *m, u8 *p)
+{
+	u32 div;
+
+	if (parent_rate < *freq)
+		*freq = parent_rate;
+
+	div = DIV_ROUND_UP(parent_rate, *freq);
+
+	/* maximum divider is 4 */
+	if (div > 4)
+		div = 4;
+
+	*freq = parent_rate / div;
+
+	/* we were called to round the frequency, we can now return */
+	if (!m)
+		return;
+
+	*m = div;
+}
+
+static struct clk_factors_config sun9i_a80_gt_config = {
+	.mshift = 0,
+	.mwidth = 2,
+};
+
+static const struct factors_data sun9i_a80_gt_data __initconst = {
+	.mux = 24,
+	.muxmask = BIT(1) | BIT(0),
+	.table = &sun9i_a80_gt_config,
+	.getter = sun9i_a80_get_gt_factors,
+};
+
+static DEFINE_SPINLOCK(sun9i_a80_gt_lock);
+
+static void __init sun9i_a80_gt_setup(struct device_node *node)
+{
+	struct clk *gt = sunxi_factors_register(node, &sun9i_a80_gt_data,
+						&sun9i_a80_gt_lock);
+
+	/* The GT bus clock needs to be always enabled */
+	__clk_get(gt);
+	clk_prepare_enable(gt);
+}
+CLK_OF_DECLARE(sun9i_a80_gt, "allwinner,sun9i-a80-gt-clk", sun9i_a80_gt_setup);
+
+
+/**
+ * sun9i_a80_get_ahb_factors() - calculates p factor for AHB0/1/2
+ * AHB rate is calculated as follows
+ * rate = parent_rate >> p;
+ */
+
+static void sun9i_a80_get_ahb_factors(u32 *freq, u32 parent_rate,
+				      u8 *n, u8 *k, u8 *m, u8 *p)
+{
+	u32 _p;
+
+	if (parent_rate < *freq)
+		*freq = parent_rate;
+
+	_p = order_base_2(DIV_ROUND_UP(parent_rate, *freq));
+
+	/* maximum p is 3 */
+	if (_p > 3)
+		_p = 3;
+
+	*freq = parent_rate >> _p;
+
+	/* we were called to round the frequency, we can now return */
+	if (!p)
+		return;
+
+	*p = _p;
+}
+
+static struct clk_factors_config sun9i_a80_ahb_config = {
+	.pshift = 0,
+	.pwidth = 2,
+};
+
+static const struct factors_data sun9i_a80_ahb_data __initconst = {
+	.mux = 24,
+	.muxmask = BIT(1) | BIT(0),
+	.table = &sun9i_a80_ahb_config,
+	.getter = sun9i_a80_get_ahb_factors,
+};
+
+static DEFINE_SPINLOCK(sun9i_a80_ahb_lock);
+
+static void __init sun9i_a80_ahb_setup(struct device_node *node)
+{
+	sunxi_factors_register(node, &sun9i_a80_ahb_data, &sun9i_a80_ahb_lock);
+}
+CLK_OF_DECLARE(sun9i_a80_ahb, "allwinner,sun9i-a80-ahb-clk", sun9i_a80_ahb_setup);
+
+
+static const struct factors_data sun9i_a80_apb0_data __initconst = {
+	.mux = 24,
+	.muxmask = BIT(0),
+	.table = &sun9i_a80_ahb_config,
+	.getter = sun9i_a80_get_ahb_factors,
+};
+
+static DEFINE_SPINLOCK(sun9i_a80_apb0_lock);
+
+static void __init sun9i_a80_apb0_setup(struct device_node *node)
+{
+	sunxi_factors_register(node, &sun9i_a80_apb0_data, &sun9i_a80_apb0_lock);
+}
+CLK_OF_DECLARE(sun9i_a80_apb0, "allwinner,sun9i-a80-apb0-clk", sun9i_a80_apb0_setup);
+
+
+/**
+ * sun9i_a80_get_apb1_factors() - calculates m, p factors for APB1
+ * APB1 rate is calculated as follows
+ * rate = (parent_rate >> p) / (m + 1);
+ */
+
+static void sun9i_a80_get_apb1_factors(u32 *freq, u32 parent_rate,
+				       u8 *n, u8 *k, u8 *m, u8 *p)
+{
+	u32 div;
+	u8 calcm, calcp;
+
+	if (parent_rate < *freq)
+		*freq = parent_rate;
+
+	div = DIV_ROUND_UP(parent_rate, *freq);
+
+	/* Highest possible divider is 256 (p = 3, m = 31) */
+	if (div > 256)
+		div = 256;
+
+	calcp = order_base_2(div);
+	calcm = (parent_rate >> calcp) - 1;
+	*freq = (parent_rate >> calcp) / (calcm + 1);
+
+	/* we were called to round the frequency, we can now return */
+	if (n == NULL)
+		return;
+
+	*m = calcm;
+	*p = calcp;
+}
+
+static struct clk_factors_config sun9i_a80_apb1_config = {
+	.mshift = 0,
+	.mwidth = 5,
+	.pshift = 16,
+	.pwidth = 2,
+};
+
+static const struct factors_data sun9i_a80_apb1_data __initconst = {
+	.mux = 24,
+	.muxmask = BIT(0),
+	.table = &sun9i_a80_apb1_config,
+	.getter = sun9i_a80_get_apb1_factors,
+};
+
+static DEFINE_SPINLOCK(sun9i_a80_apb1_lock);
+
+static void __init sun9i_a80_apb1_setup(struct device_node *node)
+{
+	sunxi_factors_register(node, &sun9i_a80_apb1_data, &sun9i_a80_apb1_lock);
+}
+CLK_OF_DECLARE(sun9i_a80_apb1, "allwinner,sun9i-a80-apb1-clk", sun9i_a80_apb1_setup);
+
-- 
2.1.1

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH 3/5] clk: sunxi: Add support for bus clock gates on Allwinner A80 SoC
  2014-10-12  9:40 [PATCH 0/5] clk: sunxi: Add peripheral bus clock support for A80 Chen-Yu Tsai
  2014-10-12  9:40 ` [PATCH 1/5] clk: sunxi: make factors clock mux mask configurable Chen-Yu Tsai
  2014-10-12  9:40 ` [PATCH 2/5] clk: sunxi: Add support for A80 basic bus clocks Chen-Yu Tsai
@ 2014-10-12  9:40 ` Chen-Yu Tsai
  2014-10-12  9:40 ` [PATCH 4/5] ARM: sunxi: Select ARCH_HAS_RESET_CONTROLLER and RESET_CONTROLLER for sun9i Chen-Yu Tsai
                   ` (2 subsequent siblings)
  5 siblings, 0 replies; 16+ messages in thread
From: Chen-Yu Tsai @ 2014-10-12  9:40 UTC (permalink / raw)
  To: linux-arm-kernel

This adds the gate clocks for AHB/APB busses on the A80 SoC.

Signed-off-by: Chen-Yu Tsai <wens@csie.org>
---
 Documentation/devicetree/bindings/clock/sunxi.txt |  5 ++++
 drivers/clk/sunxi/clk-sunxi.c                     | 31 +++++++++++++++++++++++
 2 files changed, 36 insertions(+)

diff --git a/Documentation/devicetree/bindings/clock/sunxi.txt b/Documentation/devicetree/bindings/clock/sunxi.txt
index 7f1c486..0455cb9 100644
--- a/Documentation/devicetree/bindings/clock/sunxi.txt
+++ b/Documentation/devicetree/bindings/clock/sunxi.txt
@@ -29,6 +29,9 @@ Required properties:
 	"allwinner,sun6i-a31-ahb1-mux-clk" - for the AHB1 multiplexer on A31
 	"allwinner,sun6i-a31-ahb1-gates-clk" - for the AHB1 gates on A31
 	"allwinner,sun8i-a23-ahb1-gates-clk" - for the AHB1 gates on A23
+	"allwinner,sun9i-a80-ahb0-gates-clk" - for the AHB0 gates on A80
+	"allwinner,sun9i-a80-ahb1-gates-clk" - for the AHB1 gates on A80
+	"allwinner,sun9i-a80-ahb2-gates-clk" - for the AHB2 gates on A80
 	"allwinner,sun4i-a10-apb0-clk" - for the APB0 clock
 	"allwinner,sun6i-a31-apb0-clk" - for the APB0 clock on A31
 	"allwinner,sun8i-a23-apb0-clk" - for the APB0 clock on A23
@@ -39,6 +42,7 @@ Required properties:
 	"allwinner,sun6i-a31-apb0-gates-clk" - for the APB0 gates on A31
 	"allwinner,sun7i-a20-apb0-gates-clk" - for the APB0 gates on A20
 	"allwinner,sun8i-a23-apb0-gates-clk" - for the APB0 gates on A23
+	"allwinner,sun9i-a80-apb0-gates-clk" - for the APB0 gates on A80
 	"allwinner,sun4i-a10-apb1-clk" - for the APB1 clock
 	"allwinner,sun9i-a80-apb1-clk" - for the APB1 bus clock on A80
 	"allwinner,sun4i-a10-apb1-mux-clk" - for the APB1 clock muxing
@@ -48,6 +52,7 @@ Required properties:
 	"allwinner,sun6i-a31-apb1-gates-clk" - for the APB1 gates on A31
 	"allwinner,sun7i-a20-apb1-gates-clk" - for the APB1 gates on A20
 	"allwinner,sun8i-a23-apb1-gates-clk" - for the APB1 gates on A23
+	"allwinner,sun9i-a80-apb1-gates-clk" - for the APB1 gates on A80
 	"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,sun8i-a23-apb2-gates-clk" - for the APB2 gates on A23
diff --git a/drivers/clk/sunxi/clk-sunxi.c b/drivers/clk/sunxi/clk-sunxi.c
index 636b8d7..20f47c6 100644
--- a/drivers/clk/sunxi/clk-sunxi.c
+++ b/drivers/clk/sunxi/clk-sunxi.c
@@ -758,6 +758,18 @@ static const struct gates_data sun8i_a23_ahb1_gates_data __initconst = {
 	.mask = {0x25386742, 0x2505111},
 };
 
+static const struct gates_data sun9i_a80_ahb0_gates_data __initconst = {
+	.mask = {0xF5F12B},
+};
+
+static const struct gates_data sun9i_a80_ahb1_gates_data __initconst = {
+	.mask = {0x1E20003},
+};
+
+static const struct gates_data sun9i_a80_ahb2_gates_data __initconst = {
+	.mask = {0x9B7},
+};
+
 static const struct gates_data sun4i_apb0_gates_data __initconst = {
 	.mask = {0x4EF},
 };
@@ -774,6 +786,10 @@ static const struct gates_data sun7i_a20_apb0_gates_data __initconst = {
 	.mask = { 0x4ff },
 };
 
+static const struct gates_data sun9i_a80_apb0_gates_data __initconst = {
+	.mask = {0xEB822},
+};
+
 static const struct gates_data sun4i_apb1_gates_data __initconst = {
 	.mask = {0xFF00F7},
 };
@@ -802,6 +818,10 @@ static const struct gates_data sun7i_a20_apb1_gates_data __initconst = {
 	.mask = { 0xff80ff },
 };
 
+static const struct gates_data sun9i_a80_apb1_gates_data __initconst = {
+	.mask = {0x3F001F},
+};
+
 static const struct gates_data sun8i_a23_apb2_gates_data __initconst = {
 	.mask = {0x1F0007},
 };
@@ -1103,16 +1123,21 @@ static const struct of_device_id clk_gates_match[] __initconst = {
 	{.compatible = "allwinner,sun6i-a31-ahb1-gates-clk", .data = &sun6i_a31_ahb1_gates_data,},
 	{.compatible = "allwinner,sun7i-a20-ahb-gates-clk", .data = &sun7i_a20_ahb_gates_data,},
 	{.compatible = "allwinner,sun8i-a23-ahb1-gates-clk", .data = &sun8i_a23_ahb1_gates_data,},
+	{.compatible = "allwinner,sun9i-a80-ahb0-gates-clk", .data = &sun9i_a80_ahb0_gates_data,},
+	{.compatible = "allwinner,sun9i-a80-ahb1-gates-clk", .data = &sun9i_a80_ahb1_gates_data,},
+	{.compatible = "allwinner,sun9i-a80-ahb2-gates-clk", .data = &sun9i_a80_ahb2_gates_data,},
 	{.compatible = "allwinner,sun4i-a10-apb0-gates-clk", .data = &sun4i_apb0_gates_data,},
 	{.compatible = "allwinner,sun5i-a10s-apb0-gates-clk", .data = &sun5i_a10s_apb0_gates_data,},
 	{.compatible = "allwinner,sun5i-a13-apb0-gates-clk", .data = &sun5i_a13_apb0_gates_data,},
 	{.compatible = "allwinner,sun7i-a20-apb0-gates-clk", .data = &sun7i_a20_apb0_gates_data,},
+	{.compatible = "allwinner,sun9i-a80-apb0-gates-clk", .data = &sun9i_a80_apb0_gates_data,},
 	{.compatible = "allwinner,sun4i-a10-apb1-gates-clk", .data = &sun4i_apb1_gates_data,},
 	{.compatible = "allwinner,sun5i-a10s-apb1-gates-clk", .data = &sun5i_a10s_apb1_gates_data,},
 	{.compatible = "allwinner,sun5i-a13-apb1-gates-clk", .data = &sun5i_a13_apb1_gates_data,},
 	{.compatible = "allwinner,sun6i-a31-apb1-gates-clk", .data = &sun6i_a31_apb1_gates_data,},
 	{.compatible = "allwinner,sun7i-a20-apb1-gates-clk", .data = &sun7i_a20_apb1_gates_data,},
 	{.compatible = "allwinner,sun8i-a23-apb1-gates-clk", .data = &sun8i_a23_apb1_gates_data,},
+	{.compatible = "allwinner,sun9i-a80-apb1-gates-clk", .data = &sun9i_a80_apb1_gates_data,},
 	{.compatible = "allwinner,sun6i-a31-apb2-gates-clk", .data = &sun6i_a31_apb2_gates_data,},
 	{.compatible = "allwinner,sun8i-a23-apb2-gates-clk", .data = &sun8i_a23_apb2_gates_data,},
 	{.compatible = "allwinner,sun4i-a10-usb-clk", .data = &sun4i_a10_usb_gates_data,},
@@ -1201,3 +1226,9 @@ static void __init sun6i_init_clocks(struct device_node *node)
 }
 CLK_OF_DECLARE(sun6i_a31_clk_init, "allwinner,sun6i-a31", sun6i_init_clocks);
 CLK_OF_DECLARE(sun8i_a23_clk_init, "allwinner,sun8i-a23", sun6i_init_clocks);
+
+static void __init sun9i_init_clocks(struct device_node *node)
+{
+	sunxi_init_clocks(NULL, 0);
+}
+CLK_OF_DECLARE(sun9i_a80_clk_init, "allwinner,sun9i-a80", sun9i_init_clocks);
-- 
2.1.1

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH 4/5] ARM: sunxi: Select ARCH_HAS_RESET_CONTROLLER and RESET_CONTROLLER for sun9i
  2014-10-12  9:40 [PATCH 0/5] clk: sunxi: Add peripheral bus clock support for A80 Chen-Yu Tsai
                   ` (2 preceding siblings ...)
  2014-10-12  9:40 ` [PATCH 3/5] clk: sunxi: Add support for bus clock gates on Allwinner A80 SoC Chen-Yu Tsai
@ 2014-10-12  9:40 ` Chen-Yu Tsai
  2014-10-16  8:32   ` Maxime Ripard
  2014-10-12  9:40 ` [PATCH 5/5] ARM: dts: sun9i: Add basic clocks and reset controls Chen-Yu Tsai
  2014-10-12 10:45 ` [linux-sunxi] [PATCH 0/5] clk: sunxi: Add peripheral bus clock support for A80 Hans de Goede
  5 siblings, 1 reply; 16+ messages in thread
From: Chen-Yu Tsai @ 2014-10-12  9:40 UTC (permalink / raw)
  To: linux-arm-kernel

The A80 SoC has reset controls matching bus clock gates.

Signed-off-by: Chen-Yu Tsai <wens@csie.org>
---
 arch/arm/mach-sunxi/Kconfig | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/arch/arm/mach-sunxi/Kconfig b/arch/arm/mach-sunxi/Kconfig
index d04f84b..a77604f 100644
--- a/arch/arm/mach-sunxi/Kconfig
+++ b/arch/arm/mach-sunxi/Kconfig
@@ -45,6 +45,8 @@ config MACH_SUN8I
 config MACH_SUN9I
 	bool "Allwinner (sun9i) SoCs support"
 	default ARCH_SUNXI
+	select ARCH_HAS_RESET_CONTROLLER
 	select ARM_GIC
+	select RESET_CONTROLLER
 
 endif
-- 
2.1.1

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH 5/5] ARM: dts: sun9i: Add basic clocks and reset controls
  2014-10-12  9:40 [PATCH 0/5] clk: sunxi: Add peripheral bus clock support for A80 Chen-Yu Tsai
                   ` (3 preceding siblings ...)
  2014-10-12  9:40 ` [PATCH 4/5] ARM: sunxi: Select ARCH_HAS_RESET_CONTROLLER and RESET_CONTROLLER for sun9i Chen-Yu Tsai
@ 2014-10-12  9:40 ` Chen-Yu Tsai
  2014-10-12 10:45 ` [linux-sunxi] [PATCH 0/5] clk: sunxi: Add peripheral bus clock support for A80 Hans de Goede
  5 siblings, 0 replies; 16+ messages in thread
From: Chen-Yu Tsai @ 2014-10-12  9:40 UTC (permalink / raw)
  To: linux-arm-kernel

Now that we have driver support for the basic clocks, add them to the
dtsi and update existing peripherals. Also add reset controls to match.

Signed-off-by: Chen-Yu Tsai <wens@csie.org>
---
 arch/arm/boot/dts/sun9i-a80.dtsi | 177 +++++++++++++++++++++++++++++++++++++--
 1 file changed, 171 insertions(+), 6 deletions(-)

diff --git a/arch/arm/boot/dts/sun9i-a80.dtsi b/arch/arm/boot/dts/sun9i-a80.dtsi
index 5e2ec4b..7bcab56 100644
--- a/arch/arm/boot/dts/sun9i-a80.dtsi
+++ b/arch/arm/boot/dts/sun9i-a80.dtsi
@@ -142,6 +142,135 @@
 			clock-frequency = <32768>;
 			clock-output-names = "osc32k";
 		};
+
+		pll4: clk at 0600000c {
+			#clock-cells = <0>;
+			compatible = "allwinner,sun9i-a80-pll4-clk";
+			reg = <0x0600000c 0x4>;
+			clocks = <&osc24M>;
+			clock-output-names = "pll4";
+		};
+
+		pll12: clk at 0600002c {
+			#clock-cells = <0>;
+			compatible = "allwinner,sun9i-a80-pll4-clk";
+			reg = <0x0600002c 0x4>;
+			clocks = <&osc24M>;
+			clock-output-names = "pll12";
+		};
+
+		gt_clk: clk at 0600005c {
+			#clock-cells = <0>;
+			compatible = "allwinner,sun9i-a80-gt-clk";
+			reg = <0x0600005c 0x4>;
+			clocks = <&osc24M>, <&pll4>, <&pll12>, <&pll12>;
+			clock-output-names = "gt";
+		};
+
+		ahb0: clk at 06000060 {
+			#clock-cells = <0>;
+			compatible = "allwinner,sun9i-a80-ahb-clk";
+			reg = <0x06000060 0x4>;
+			clocks = <&gt_clk>, <&pll4>, <&pll12>, <&pll12>;
+			clock-output-names = "ahb0";
+		};
+
+		ahb1: clk at 06000064 {
+			#clock-cells = <0>;
+			compatible = "allwinner,sun9i-a80-ahb-clk";
+			reg = <0x06000064 0x4>;
+			clocks = <&gt_clk>, <&pll4>, <&pll12>, <&pll12>;
+			clock-output-names = "ahb1";
+		};
+
+		ahb2: clk at 06000068 {
+			#clock-cells = <0>;
+			compatible = "allwinner,sun9i-a80-ahb-clk";
+			reg = <0x06000068 0x4>;
+			clocks = <&gt_clk>, <&pll4>, <&pll12>, <&pll12>;
+			clock-output-names = "ahb2";
+		};
+
+		apb0: clk at 06000070 {
+			#clock-cells = <0>;
+			compatible = "allwinner,sun9i-a80-apb0-clk";
+			reg = <0x06000070 0x4>;
+			clocks = <&osc24M>, <&pll4>;
+			clock-output-names = "apb0";
+		};
+
+		apb1: clk at 06000074 {
+			#clock-cells = <0>;
+			compatible = "allwinner,sun9i-a80-apb1-clk";
+			reg = <0x06000074 0x4>;
+			clocks = <&osc24M>, <&pll4>;
+			clock-output-names = "apb1";
+		};
+
+		cci400_clk: clk at 06000078 {
+			#clock-cells = <0>;
+			compatible = "allwinner,sun9i-a80-gt-clk";
+			reg = <0x06000078 0x4>;
+			clocks = <&osc24M>, <&pll4>, <&pll12>, <&pll12>;
+			clock-output-names = "cci400";
+		};
+
+		ahb0_gates: clk at 06000580 {
+			#clock-cells = <1>;
+			compatible = "allwinner,sun9i-a80-ahb0-gates-clk";
+			reg = <0x06000580 0x4>;
+			clocks = <&ahb0>;
+			clock-output-names = "ahb0_fd", "ahb0_ve", "ahb0_gpu",
+					"ahb0_ss", "ahb0_sd", "ahb0_nand1",
+					"ahb0_nand0", "ahb0_sdram",
+					"ahb0_mipi_hsi", "ahb0_sata", "ahb0_ts",
+					"ahb0_spi0","ahb0_spi1", "ahb0_spi2",
+					"ahb0_spi3";
+		};
+
+		ahb1_gates: clk at 06000584 {
+			#clock-cells = <1>;
+			compatible = "allwinner,sun9i-a80-ahb1-gates-clk";
+			reg = <0x06000584 0x4>;
+			clocks = <&ahb1>;
+			clock-output-names = "ahb1_usbotg", "ahb1_usbhci",
+					"ahb1_gmac", "ahb1_msgbox",
+					"ahb1_spinlock", "ahb1_hstimer",
+					"ahb1_dma";
+		};
+
+		ahb2_gates: clk at 06000588 {
+			#clock-cells = <1>;
+			compatible = "allwinner,sun9i-a80-ahb2-gates-clk";
+			reg = <0x06000588 0x4>;
+			clocks = <&ahb2>;
+			clock-output-names = "ahb2_lcd0", "ahb2_lcd1",
+					"ahb2_edp", "ahb2_csi", "ahb2_hdmi",
+					"ahb2_de", "ahb2_mp", "ahb2_mipi_dsi";
+		};
+
+		apb0_gates: clk at 06000590 {
+			#clock-cells = <1>;
+			compatible = "allwinner,sun9i-a80-apb0-gates-clk";
+			reg = <0x06000590 0x4>;
+			clocks = <&apb0>;
+			clock-output-names = "apb0_spdif", "apb0_pio",
+					"apb0_ac97", "apb0_i2s0", "apb0_i2s1",
+					"apb0_lradc", "apb0_gpadc", "apb0_twd",
+					"apb0_cirtx";
+		};
+
+		apb1_gates: clk at 06000594 {
+			#clock-cells = <1>;
+			compatible = "allwinner,sun9i-a80-apb1-gates-clk";
+			reg = <0x06000594 0x4>;
+			clocks = <&apb1>;
+			clock-output-names = "apb1_i2c0", "apb1_i2c1",
+					"apb1_i2c2", "apb1_i2c3", "apb1_i2c4",
+					"apb1_uart0", "apb1_uart1",
+					"apb1_uart2", "apb1_uart3",
+					"apb1_uart4", "apb1_uart5";
+		};
 	};
 
 	soc {
@@ -165,6 +294,36 @@
 			interrupts = <1 9 0xf04>;
 		};
 
+		ahb0_resets: reset at 060005a0 {
+			#reset-cells = <1>;
+			compatible = "allwinner,sun6i-a31-clock-reset";
+			reg = <0x060005a0 0x4>;
+		};
+
+		ahb1_resets: reset at 060005a4 {
+			#reset-cells = <1>;
+			compatible = "allwinner,sun6i-a31-clock-reset";
+			reg = <0x060005a4 0x4>;
+		};
+
+		ahb2_resets: reset at 060005a8 {
+			#reset-cells = <1>;
+			compatible = "allwinner,sun6i-a31-clock-reset";
+			reg = <0x060005a8 0x4>;
+		};
+
+		apb0_resets: reset at 060005b0 {
+			#reset-cells = <1>;
+			compatible = "allwinner,sun6i-a31-clock-reset";
+			reg = <0x060005b0 0x4>;
+		};
+
+		apb1_resets: reset at 060005b4 {
+			#reset-cells = <1>;
+			compatible = "allwinner,sun6i-a31-clock-reset";
+			reg = <0x060005b4 0x4>;
+		};
+
 		timer at 06000c00 {
 			compatible = "allwinner,sun4i-a10-timer";
 			reg = <0x06000c00 0xa0>;
@@ -184,7 +343,8 @@
 			interrupts = <0 0 4>;
 			reg-shift = <2>;
 			reg-io-width = <4>;
-			clocks = <&osc24M>;
+			clocks = <&apb1_gates 16>;
+			resets = <&apb1_resets 16>;
 			status = "disabled";
 		};
 
@@ -194,7 +354,8 @@
 			interrupts = <0 1 4>;
 			reg-shift = <2>;
 			reg-io-width = <4>;
-			clocks = <&osc24M>;
+			clocks = <&apb1_gates 17>;
+			resets = <&apb1_resets 17>;
 			status = "disabled";
 		};
 
@@ -204,7 +365,8 @@
 			interrupts = <0 2 4>;
 			reg-shift = <2>;
 			reg-io-width = <4>;
-			clocks = <&osc24M>;
+			clocks = <&apb1_gates 18>;
+			resets = <&apb1_resets 18>;
 			status = "disabled";
 		};
 
@@ -214,7 +376,8 @@
 			interrupts = <0 3 4>;
 			reg-shift = <2>;
 			reg-io-width = <4>;
-			clocks = <&osc24M>;
+			clocks = <&apb1_gates 19>;
+			resets = <&apb1_resets 19>;
 			status = "disabled";
 		};
 
@@ -224,7 +387,8 @@
 			interrupts = <0 4 4>;
 			reg-shift = <2>;
 			reg-io-width = <4>;
-			clocks = <&osc24M>;
+			clocks = <&apb1_gates 20>;
+			resets = <&apb1_resets 20>;
 			status = "disabled";
 		};
 
@@ -234,7 +398,8 @@
 			interrupts = <0 5 4>;
 			reg-shift = <2>;
 			reg-io-width = <4>;
-			clocks = <&osc24M>;
+			clocks = <&apb1_gates 21>;
+			resets = <&apb1_resets 21>;
 			status = "disabled";
 		};
 
-- 
2.1.1

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [linux-sunxi] [PATCH 0/5] clk: sunxi: Add peripheral bus clock support for A80
  2014-10-12  9:40 [PATCH 0/5] clk: sunxi: Add peripheral bus clock support for A80 Chen-Yu Tsai
                   ` (4 preceding siblings ...)
  2014-10-12  9:40 ` [PATCH 5/5] ARM: dts: sun9i: Add basic clocks and reset controls Chen-Yu Tsai
@ 2014-10-12 10:45 ` Hans de Goede
  2014-10-12 15:32   ` Chen-Yu Tsai
  5 siblings, 1 reply; 16+ messages in thread
From: Hans de Goede @ 2014-10-12 10:45 UTC (permalink / raw)
  To: linux-arm-kernel

Hi ChenYu,

On 10/12/2014 11:40 AM, Chen-Yu Tsai wrote:
> Hi everyone,
> 
> This series adds support for the basic bus (AHB/APB) clocks used by
> peripherals on the A80 SoC. This series is based on my previous A80
> bringup series.

Cool stuff, any chance you could write a quick howto for getting an
upstream kernel to run on the Merrii A80 optimus board, for lazy / very
busy people like me? Preferably including a link to an sdcard image
which already has all the bootloader bits in place ?

Regards,

Hans

^ permalink raw reply	[flat|nested] 16+ messages in thread

* [linux-sunxi] [PATCH 0/5] clk: sunxi: Add peripheral bus clock support for A80
  2014-10-12 10:45 ` [linux-sunxi] [PATCH 0/5] clk: sunxi: Add peripheral bus clock support for A80 Hans de Goede
@ 2014-10-12 15:32   ` Chen-Yu Tsai
  2014-12-03 13:11     ` Simos Xenitellis
  0 siblings, 1 reply; 16+ messages in thread
From: Chen-Yu Tsai @ 2014-10-12 15:32 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Hans,

On Sun, Oct 12, 2014 at 6:45 PM, Hans de Goede <hdegoede@redhat.com> wrote:
> Hi ChenYu,
>
> On 10/12/2014 11:40 AM, Chen-Yu Tsai wrote:
>> Hi everyone,
>>
>> This series adds support for the basic bus (AHB/APB) clocks used by
>> peripherals on the A80 SoC. This series is based on my previous A80
>> bringup series.
>
> Cool stuff, any chance you could write a quick howto for getting an
> upstream kernel to run on the Merrii A80 optimus board, for lazy / very
> busy people like me? Preferably including a link to an sdcard image
> which already has all the bootloader bits in place ?

I keep a short status report and howto on my user page on the linux-sunxi wiki:

    http://linux-sunxi.org/User:Wens#A80_Optimus

I will try to expand it this week. Feel free to let me know if something is
fuzzy or doesn't make sense.


ChenYu

^ permalink raw reply	[flat|nested] 16+ messages in thread

* [PATCH 2/5] clk: sunxi: Add support for A80 basic bus clocks
  2014-10-12  9:40 ` [PATCH 2/5] clk: sunxi: Add support for A80 basic bus clocks Chen-Yu Tsai
@ 2014-10-16  8:31   ` Maxime Ripard
  2014-10-16 12:35     ` Chen-Yu Tsai
  0 siblings, 1 reply; 16+ messages in thread
From: Maxime Ripard @ 2014-10-16  8:31 UTC (permalink / raw)
  To: linux-arm-kernel

On Sun, Oct 12, 2014 at 05:40:22PM +0800, Chen-Yu Tsai wrote:
> The A80 SoC has 12 PLL clocks, 3 AHB clocks, 2 APB clocks, and a
> new "GT" bus, which I assume is some kind of data bus connecting
> the processor cores, memory and various busses. Also there is a
> bus clock for a ARM CCI400 module.
> 
> As far as I can tell, the GT bus and CCI400 bus clock must be
> protected.
> 
> This patch adds driver support for peripheral related PLLs and
> bus clocks on the A80. The GT and CCI400 clocks are added as well
> as these 2 along with the PLLs they are clocked from must not be
> disabled.
> 
> Signed-off-by: Chen-Yu Tsai <wens@csie.org>
> ---
>  Documentation/devicetree/bindings/clock/sunxi.txt |   5 +
>  drivers/clk/sunxi/Makefile                        |   1 +
>  drivers/clk/sunxi/clk-sun9i-core.c                | 272 ++++++++++++++++++++++
>  3 files changed, 278 insertions(+)
>  create mode 100644 drivers/clk/sunxi/clk-sun9i-core.c
> 
> diff --git a/Documentation/devicetree/bindings/clock/sunxi.txt b/Documentation/devicetree/bindings/clock/sunxi.txt
> index ed116df..7f1c486 100644
> --- a/Documentation/devicetree/bindings/clock/sunxi.txt
> +++ b/Documentation/devicetree/bindings/clock/sunxi.txt
> @@ -10,14 +10,17 @@ Required properties:
>  	"allwinner,sun4i-a10-pll1-clk" - for the main PLL clock and PLL4
>  	"allwinner,sun6i-a31-pll1-clk" - for the main PLL clock on A31
>  	"allwinner,sun8i-a23-pll1-clk" - for the main PLL clock on A23
> +	"allwinner,sun9i-a80-pll4-clk" - for the peripheral PLLs on A80
>  	"allwinner,sun4i-a10-pll5-clk" - for the PLL5 clock
>  	"allwinner,sun4i-a10-pll6-clk" - for the PLL6 clock
>  	"allwinner,sun6i-a31-pll6-clk" - for the PLL6 clock on A31
> +	"allwinner,sun9i-a80-gt-clk" - for the GT bus clock on A80
>  	"allwinner,sun4i-a10-cpu-clk" - for the CPU multiplexer clock
>  	"allwinner,sun4i-a10-axi-clk" - for the AXI clock
>  	"allwinner,sun8i-a23-axi-clk" - for the AXI clock on A23
>  	"allwinner,sun4i-a10-axi-gates-clk" - for the AXI gates
>  	"allwinner,sun4i-a10-ahb-clk" - for the AHB clock
> +	"allwinner,sun9i-a80-ahb-clk" - for the AHB bus clocks on A80
>  	"allwinner,sun4i-a10-ahb-gates-clk" - for the AHB gates on A10
>  	"allwinner,sun5i-a13-ahb-gates-clk" - for the AHB gates on A13
>  	"allwinner,sun5i-a10s-ahb-gates-clk" - for the AHB gates on A10s
> @@ -29,6 +32,7 @@ Required properties:
>  	"allwinner,sun4i-a10-apb0-clk" - for the APB0 clock
>  	"allwinner,sun6i-a31-apb0-clk" - for the APB0 clock on A31
>  	"allwinner,sun8i-a23-apb0-clk" - for the APB0 clock on A23
> +	"allwinner,sun9i-a80-apb0-clk" - for the APB0 bus clock on A80
>  	"allwinner,sun4i-a10-apb0-gates-clk" - for the APB0 gates on A10
>  	"allwinner,sun5i-a13-apb0-gates-clk" - for the APB0 gates on A13
>  	"allwinner,sun5i-a10s-apb0-gates-clk" - for the APB0 gates on A10s
> @@ -36,6 +40,7 @@ Required properties:
>  	"allwinner,sun7i-a20-apb0-gates-clk" - for the APB0 gates on A20
>  	"allwinner,sun8i-a23-apb0-gates-clk" - for the APB0 gates on A23
>  	"allwinner,sun4i-a10-apb1-clk" - for the APB1 clock
> +	"allwinner,sun9i-a80-apb1-clk" - for the APB1 bus clock on A80
>  	"allwinner,sun4i-a10-apb1-mux-clk" - for the APB1 clock muxing
>  	"allwinner,sun4i-a10-apb1-gates-clk" - for the APB1 gates on A10
>  	"allwinner,sun5i-a13-apb1-gates-clk" - for the APB1 gates on A13
> diff --git a/drivers/clk/sunxi/Makefile b/drivers/clk/sunxi/Makefile
> index 7ddc2b5..a66953c 100644
> --- a/drivers/clk/sunxi/Makefile
> +++ b/drivers/clk/sunxi/Makefile
> @@ -7,6 +7,7 @@ obj-y += clk-a10-hosc.o
>  obj-y += clk-a20-gmac.o
>  obj-y += clk-mod0.o
>  obj-y += clk-sun8i-mbus.o
> +obj-y += clk-sun9i-core.o
>  
>  obj-$(CONFIG_MFD_SUN6I_PRCM) += \
>  	clk-sun6i-ar100.o clk-sun6i-apb0.o clk-sun6i-apb0-gates.o \
> diff --git a/drivers/clk/sunxi/clk-sun9i-core.c b/drivers/clk/sunxi/clk-sun9i-core.c
> new file mode 100644
> index 0000000..ba5f091
> --- /dev/null
> +++ b/drivers/clk/sunxi/clk-sun9i-core.c
> @@ -0,0 +1,272 @@
> +/*
> + * Copyright 2014 Chen-Yu Tsai
> + *
> + * Chen-Yu Tsai <wens@csie.org>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + */
> +
> +#include <linux/clk-provider.h>
> +#include <linux/clkdev.h>
> +#include <linux/of.h>
> +#include <linux/of_address.h>
> +#include <linux/log2.h>
> +
> +#include "clk-factors.h"
> +
> +
> +/**
> + * sun9i_a80_get_pll4_factors() - calculates n, p, m factors for PLL1
> + * PLL4 rate is calculated as follows
> + * rate = (parent_rate * n >> p) / (m + 1);
> + * parent_rate is always 24Mhz
> + *
> + * p and m are named div1 and div2 in Allwinner's SDK
> + */
> +
> +static void sun9i_a80_get_pll4_factors(u32 *freq, u32 parent_rate,
> +				       u8 *n, u8 *k, u8 *m, u8 *p)
> +{
> +	int div;
> +
> +	/* Normalize value to a 6M multiple */
> +	div = *freq / 6000000;
> +
> +	/* divs above 256 cannot be odd */
> +	if (div > 256)
> +		div &= ~0x1;
> +
> +	/* divs above 512 must be a multiple of 4 */
> +	if (div > 512)
> +		div &= ~0x3;

round_up / round_down looks more readable.

> +
> +	*freq = 6000000 * div;

and here as well

> +	/* we were called to round the frequency, we can now return */
> +	if (n == NULL)
> +		return;
> +
> +	/* p will be 1 for divs under 512 */
> +	if (div < 512)
> +		*p = 1;
> +	else
> +		*p = 0;
> +
> +	/* m will be 1 if div is odd */
> +	if (div & 1)
> +		*m = 1;
> +	else
> +		*m = 0;
> +
> +	/* calculate a suitable n based on m and p */
> +	*n = div / (*p + 1) / (*m + 1);
> +}
> +
> +static struct clk_factors_config sun9i_a80_pll4_config = {
> +	.mshift = 18,
> +	.mwidth = 1,
> +	.nshift = 8,
> +	.nwidth = 8,
> +	.pshift = 16,
> +	.pwidth = 1,
> +};
> +
> +static const struct factors_data sun9i_a80_pll4_data __initconst = {
> +	.enable = 31,
> +	.table = &sun9i_a80_pll4_config,
> +	.getter = sun9i_a80_get_pll4_factors,
> +};
> +
> +static DEFINE_SPINLOCK(sun9i_a80_pll4_lock);
> +
> +static void __init sun9i_a80_pll4_setup(struct device_node *node)
> +{
> +	sunxi_factors_register(node, &sun9i_a80_pll4_data, &sun9i_a80_pll4_lock);
> +}
> +CLK_OF_DECLARE(sun9i_a80_pll4, "allwinner,sun9i-a80-pll4-clk", sun9i_a80_pll4_setup);
> +
> +
> +/**
> + * sun9i_a80_get_gt_factors() - calculates m factor for GT
> + * GT rate is calculated as follows
> + * rate = parent_rate / (m + 1);
> + */
> +
> +static void sun9i_a80_get_gt_factors(u32 *freq, u32 parent_rate,
> +				     u8 *n, u8 *k, u8 *m, u8 *p)
> +{
> +	u32 div;
> +
> +	if (parent_rate < *freq)
> +		*freq = parent_rate;
> +
> +	div = DIV_ROUND_UP(parent_rate, *freq);
> +
> +	/* maximum divider is 4 */
> +	if (div > 4)
> +		div = 4;
> +
> +	*freq = parent_rate / div;
> +
> +	/* we were called to round the frequency, we can now return */
> +	if (!m)
> +		return;
> +
> +	*m = div;
> +}
> +
> +static struct clk_factors_config sun9i_a80_gt_config = {
> +	.mshift = 0,
> +	.mwidth = 2,
> +};
> +
> +static const struct factors_data sun9i_a80_gt_data __initconst = {
> +	.mux = 24,
> +	.muxmask = BIT(1) | BIT(0),
> +	.table = &sun9i_a80_gt_config,
> +	.getter = sun9i_a80_get_gt_factors,
> +};
> +
> +static DEFINE_SPINLOCK(sun9i_a80_gt_lock);
> +
> +static void __init sun9i_a80_gt_setup(struct device_node *node)
> +{
> +	struct clk *gt = sunxi_factors_register(node, &sun9i_a80_gt_data,
> +						&sun9i_a80_gt_lock);
> +
> +	/* The GT bus clock needs to be always enabled */
> +	__clk_get(gt);
> +	clk_prepare_enable(gt);
> +}
> +CLK_OF_DECLARE(sun9i_a80_gt, "allwinner,sun9i-a80-gt-clk", sun9i_a80_gt_setup);
> +
> +
> +/**
> + * sun9i_a80_get_ahb_factors() - calculates p factor for AHB0/1/2
> + * AHB rate is calculated as follows
> + * rate = parent_rate >> p;
> + */
> +
> +static void sun9i_a80_get_ahb_factors(u32 *freq, u32 parent_rate,
> +				      u8 *n, u8 *k, u8 *m, u8 *p)
> +{
> +	u32 _p;
> +
> +	if (parent_rate < *freq)
> +		*freq = parent_rate;
> +
> +	_p = order_base_2(DIV_ROUND_UP(parent_rate, *freq));
> +
> +	/* maximum p is 3 */
> +	if (_p > 3)
> +		_p = 3;
> +
> +	*freq = parent_rate >> _p;
> +
> +	/* we were called to round the frequency, we can now return */
> +	if (!p)
> +		return;
> +
> +	*p = _p;
> +}
> +
> +static struct clk_factors_config sun9i_a80_ahb_config = {
> +	.pshift = 0,
> +	.pwidth = 2,
> +};
> +
> +static const struct factors_data sun9i_a80_ahb_data __initconst = {
> +	.mux = 24,
> +	.muxmask = BIT(1) | BIT(0),
> +	.table = &sun9i_a80_ahb_config,
> +	.getter = sun9i_a80_get_ahb_factors,
> +};
> +
> +static DEFINE_SPINLOCK(sun9i_a80_ahb_lock);
> +
> +static void __init sun9i_a80_ahb_setup(struct device_node *node)
> +{
> +	sunxi_factors_register(node, &sun9i_a80_ahb_data, &sun9i_a80_ahb_lock);
> +}
> +CLK_OF_DECLARE(sun9i_a80_ahb, "allwinner,sun9i-a80-ahb-clk", sun9i_a80_ahb_setup);
> +
> +
> +static const struct factors_data sun9i_a80_apb0_data __initconst = {
> +	.mux = 24,
> +	.muxmask = BIT(0),
> +	.table = &sun9i_a80_ahb_config,
> +	.getter = sun9i_a80_get_ahb_factors,
> +};
> +
> +static DEFINE_SPINLOCK(sun9i_a80_apb0_lock);
> +
> +static void __init sun9i_a80_apb0_setup(struct device_node *node)
> +{
> +	sunxi_factors_register(node, &sun9i_a80_apb0_data, &sun9i_a80_apb0_lock);
> +}
> +CLK_OF_DECLARE(sun9i_a80_apb0, "allwinner,sun9i-a80-apb0-clk", sun9i_a80_apb0_setup);
> +
> +
> +/**
> + * sun9i_a80_get_apb1_factors() - calculates m, p factors for APB1
> + * APB1 rate is calculated as follows
> + * rate = (parent_rate >> p) / (m + 1);
> + */
> +
> +static void sun9i_a80_get_apb1_factors(u32 *freq, u32 parent_rate,
> +				       u8 *n, u8 *k, u8 *m, u8 *p)
> +{
> +	u32 div;
> +	u8 calcm, calcp;
> +
> +	if (parent_rate < *freq)
> +		*freq = parent_rate;
> +
> +	div = DIV_ROUND_UP(parent_rate, *freq);
> +
> +	/* Highest possible divider is 256 (p = 3, m = 31) */
> +	if (div > 256)
> +		div = 256;
> +
> +	calcp = order_base_2(div);
> +	calcm = (parent_rate >> calcp) - 1;
> +	*freq = (parent_rate >> calcp) / (calcm + 1);
> +
> +	/* we were called to round the frequency, we can now return */
> +	if (n == NULL)
> +		return;
> +
> +	*m = calcm;
> +	*p = calcp;
> +}
> +
> +static struct clk_factors_config sun9i_a80_apb1_config = {
> +	.mshift = 0,
> +	.mwidth = 5,
> +	.pshift = 16,
> +	.pwidth = 2,
> +};
> +
> +static const struct factors_data sun9i_a80_apb1_data __initconst = {
> +	.mux = 24,
> +	.muxmask = BIT(0),
> +	.table = &sun9i_a80_apb1_config,
> +	.getter = sun9i_a80_get_apb1_factors,
> +};
> +
> +static DEFINE_SPINLOCK(sun9i_a80_apb1_lock);
> +
> +static void __init sun9i_a80_apb1_setup(struct device_node *node)
> +{
> +	sunxi_factors_register(node, &sun9i_a80_apb1_data, &sun9i_a80_apb1_lock);
> +}
> +CLK_OF_DECLARE(sun9i_a80_apb1, "allwinner,sun9i-a80-apb1-clk", sun9i_a80_apb1_setup);
> +

Do these clocks share anything (aside from being for the A80) that
require them to be in the same file?

Thanks for your work!
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: 819 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20141016/ce48b63c/attachment.sig>

^ permalink raw reply	[flat|nested] 16+ messages in thread

* [PATCH 4/5] ARM: sunxi: Select ARCH_HAS_RESET_CONTROLLER and RESET_CONTROLLER for sun9i
  2014-10-12  9:40 ` [PATCH 4/5] ARM: sunxi: Select ARCH_HAS_RESET_CONTROLLER and RESET_CONTROLLER for sun9i Chen-Yu Tsai
@ 2014-10-16  8:32   ` Maxime Ripard
  0 siblings, 0 replies; 16+ messages in thread
From: Maxime Ripard @ 2014-10-16  8:32 UTC (permalink / raw)
  To: linux-arm-kernel

On Sun, Oct 12, 2014 at 05:40:24PM +0800, Chen-Yu Tsai wrote:
> The A80 SoC has reset controls matching bus clock gates.
> 
> Signed-off-by: Chen-Yu Tsai <wens@csie.org>

Applied, 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: 819 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20141016/e62ea9fa/attachment.sig>

^ permalink raw reply	[flat|nested] 16+ messages in thread

* [PATCH 2/5] clk: sunxi: Add support for A80 basic bus clocks
  2014-10-16  8:31   ` Maxime Ripard
@ 2014-10-16 12:35     ` Chen-Yu Tsai
  2014-10-17 13:51       ` Maxime Ripard
  0 siblings, 1 reply; 16+ messages in thread
From: Chen-Yu Tsai @ 2014-10-16 12:35 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Oct 16, 2014 at 4:31 PM, Maxime Ripard
<maxime.ripard@free-electrons.com> wrote:
> On Sun, Oct 12, 2014 at 05:40:22PM +0800, Chen-Yu Tsai wrote:
>> The A80 SoC has 12 PLL clocks, 3 AHB clocks, 2 APB clocks, and a
>> new "GT" bus, which I assume is some kind of data bus connecting
>> the processor cores, memory and various busses. Also there is a
>> bus clock for a ARM CCI400 module.
>>
>> As far as I can tell, the GT bus and CCI400 bus clock must be
>> protected.
>>
>> This patch adds driver support for peripheral related PLLs and
>> bus clocks on the A80. The GT and CCI400 clocks are added as well
>> as these 2 along with the PLLs they are clocked from must not be
>> disabled.
>>
>> Signed-off-by: Chen-Yu Tsai <wens@csie.org>
>> ---
>>  Documentation/devicetree/bindings/clock/sunxi.txt |   5 +
>>  drivers/clk/sunxi/Makefile                        |   1 +
>>  drivers/clk/sunxi/clk-sun9i-core.c                | 272 ++++++++++++++++++++++
>>  3 files changed, 278 insertions(+)
>>  create mode 100644 drivers/clk/sunxi/clk-sun9i-core.c
>>
>> diff --git a/Documentation/devicetree/bindings/clock/sunxi.txt b/Documentation/devicetree/bindings/clock/sunxi.txt
>> index ed116df..7f1c486 100644
>> --- a/Documentation/devicetree/bindings/clock/sunxi.txt
>> +++ b/Documentation/devicetree/bindings/clock/sunxi.txt
>> @@ -10,14 +10,17 @@ Required properties:
>>       "allwinner,sun4i-a10-pll1-clk" - for the main PLL clock and PLL4
>>       "allwinner,sun6i-a31-pll1-clk" - for the main PLL clock on A31
>>       "allwinner,sun8i-a23-pll1-clk" - for the main PLL clock on A23
>> +     "allwinner,sun9i-a80-pll4-clk" - for the peripheral PLLs on A80
>>       "allwinner,sun4i-a10-pll5-clk" - for the PLL5 clock
>>       "allwinner,sun4i-a10-pll6-clk" - for the PLL6 clock
>>       "allwinner,sun6i-a31-pll6-clk" - for the PLL6 clock on A31
>> +     "allwinner,sun9i-a80-gt-clk" - for the GT bus clock on A80
>>       "allwinner,sun4i-a10-cpu-clk" - for the CPU multiplexer clock
>>       "allwinner,sun4i-a10-axi-clk" - for the AXI clock
>>       "allwinner,sun8i-a23-axi-clk" - for the AXI clock on A23
>>       "allwinner,sun4i-a10-axi-gates-clk" - for the AXI gates
>>       "allwinner,sun4i-a10-ahb-clk" - for the AHB clock
>> +     "allwinner,sun9i-a80-ahb-clk" - for the AHB bus clocks on A80
>>       "allwinner,sun4i-a10-ahb-gates-clk" - for the AHB gates on A10
>>       "allwinner,sun5i-a13-ahb-gates-clk" - for the AHB gates on A13
>>       "allwinner,sun5i-a10s-ahb-gates-clk" - for the AHB gates on A10s
>> @@ -29,6 +32,7 @@ Required properties:
>>       "allwinner,sun4i-a10-apb0-clk" - for the APB0 clock
>>       "allwinner,sun6i-a31-apb0-clk" - for the APB0 clock on A31
>>       "allwinner,sun8i-a23-apb0-clk" - for the APB0 clock on A23
>> +     "allwinner,sun9i-a80-apb0-clk" - for the APB0 bus clock on A80
>>       "allwinner,sun4i-a10-apb0-gates-clk" - for the APB0 gates on A10
>>       "allwinner,sun5i-a13-apb0-gates-clk" - for the APB0 gates on A13
>>       "allwinner,sun5i-a10s-apb0-gates-clk" - for the APB0 gates on A10s
>> @@ -36,6 +40,7 @@ Required properties:
>>       "allwinner,sun7i-a20-apb0-gates-clk" - for the APB0 gates on A20
>>       "allwinner,sun8i-a23-apb0-gates-clk" - for the APB0 gates on A23
>>       "allwinner,sun4i-a10-apb1-clk" - for the APB1 clock
>> +     "allwinner,sun9i-a80-apb1-clk" - for the APB1 bus clock on A80
>>       "allwinner,sun4i-a10-apb1-mux-clk" - for the APB1 clock muxing
>>       "allwinner,sun4i-a10-apb1-gates-clk" - for the APB1 gates on A10
>>       "allwinner,sun5i-a13-apb1-gates-clk" - for the APB1 gates on A13
>> diff --git a/drivers/clk/sunxi/Makefile b/drivers/clk/sunxi/Makefile
>> index 7ddc2b5..a66953c 100644
>> --- a/drivers/clk/sunxi/Makefile
>> +++ b/drivers/clk/sunxi/Makefile
>> @@ -7,6 +7,7 @@ obj-y += clk-a10-hosc.o
>>  obj-y += clk-a20-gmac.o
>>  obj-y += clk-mod0.o
>>  obj-y += clk-sun8i-mbus.o
>> +obj-y += clk-sun9i-core.o
>>
>>  obj-$(CONFIG_MFD_SUN6I_PRCM) += \
>>       clk-sun6i-ar100.o clk-sun6i-apb0.o clk-sun6i-apb0-gates.o \
>> diff --git a/drivers/clk/sunxi/clk-sun9i-core.c b/drivers/clk/sunxi/clk-sun9i-core.c
>> new file mode 100644
>> index 0000000..ba5f091
>> --- /dev/null
>> +++ b/drivers/clk/sunxi/clk-sun9i-core.c
>> @@ -0,0 +1,272 @@
>> +/*
>> + * Copyright 2014 Chen-Yu Tsai
>> + *
>> + * Chen-Yu Tsai <wens@csie.org>
>> + *
>> + * This program is free software; you can redistribute it and/or modify
>> + * it under the terms of the GNU General Public License as published by
>> + * the Free Software Foundation; either version 2 of the License, or
>> + * (at your option) any later version.
>> + *
>> + * This program is distributed in the hope that it will be useful,
>> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
>> + * GNU General Public License for more details.
>> + */
>> +
>> +#include <linux/clk-provider.h>
>> +#include <linux/clkdev.h>
>> +#include <linux/of.h>
>> +#include <linux/of_address.h>
>> +#include <linux/log2.h>
>> +
>> +#include "clk-factors.h"
>> +
>> +
>> +/**
>> + * sun9i_a80_get_pll4_factors() - calculates n, p, m factors for PLL1
>> + * PLL4 rate is calculated as follows
>> + * rate = (parent_rate * n >> p) / (m + 1);
>> + * parent_rate is always 24Mhz
>> + *
>> + * p and m are named div1 and div2 in Allwinner's SDK
>> + */
>> +
>> +static void sun9i_a80_get_pll4_factors(u32 *freq, u32 parent_rate,
>> +                                    u8 *n, u8 *k, u8 *m, u8 *p)
>> +{
>> +     int div;
>> +
>> +     /* Normalize value to a 6M multiple */
>> +     div = *freq / 6000000;
>> +
>> +     /* divs above 256 cannot be odd */
>> +     if (div > 256)
>> +             div &= ~0x1;
>> +
>> +     /* divs above 512 must be a multiple of 4 */
>> +     if (div > 512)
>> +             div &= ~0x3;
>
> round_up / round_down looks more readable.

OK.

>> +
>> +     *freq = 6000000 * div;
>
> and here as well

This won't look pretty with round_up/round_down i think.
This function is supposed to return the actual closest supported
frequency, so it depends on the calculated/rounded divider from
the previous section.

>> +     /* we were called to round the frequency, we can now return */
>> +     if (n == NULL)
>> +             return;
>> +
>> +     /* p will be 1 for divs under 512 */
>> +     if (div < 512)
>> +             *p = 1;
>> +     else
>> +             *p = 0;
>> +
>> +     /* m will be 1 if div is odd */
>> +     if (div & 1)
>> +             *m = 1;
>> +     else
>> +             *m = 0;
>> +
>> +     /* calculate a suitable n based on m and p */
>> +     *n = div / (*p + 1) / (*m + 1);
>> +}
>> +
>> +static struct clk_factors_config sun9i_a80_pll4_config = {
>> +     .mshift = 18,
>> +     .mwidth = 1,
>> +     .nshift = 8,
>> +     .nwidth = 8,
>> +     .pshift = 16,
>> +     .pwidth = 1,
>> +};
>> +
>> +static const struct factors_data sun9i_a80_pll4_data __initconst = {
>> +     .enable = 31,
>> +     .table = &sun9i_a80_pll4_config,
>> +     .getter = sun9i_a80_get_pll4_factors,
>> +};
>> +
>> +static DEFINE_SPINLOCK(sun9i_a80_pll4_lock);
>> +
>> +static void __init sun9i_a80_pll4_setup(struct device_node *node)
>> +{
>> +     sunxi_factors_register(node, &sun9i_a80_pll4_data, &sun9i_a80_pll4_lock);
>> +}
>> +CLK_OF_DECLARE(sun9i_a80_pll4, "allwinner,sun9i-a80-pll4-clk", sun9i_a80_pll4_setup);
>> +
>> +
>> +/**
>> + * sun9i_a80_get_gt_factors() - calculates m factor for GT
>> + * GT rate is calculated as follows
>> + * rate = parent_rate / (m + 1);
>> + */
>> +
>> +static void sun9i_a80_get_gt_factors(u32 *freq, u32 parent_rate,
>> +                                  u8 *n, u8 *k, u8 *m, u8 *p)
>> +{
>> +     u32 div;
>> +
>> +     if (parent_rate < *freq)
>> +             *freq = parent_rate;
>> +
>> +     div = DIV_ROUND_UP(parent_rate, *freq);
>> +
>> +     /* maximum divider is 4 */
>> +     if (div > 4)
>> +             div = 4;
>> +
>> +     *freq = parent_rate / div;
>> +
>> +     /* we were called to round the frequency, we can now return */
>> +     if (!m)
>> +             return;
>> +
>> +     *m = div;
>> +}
>> +
>> +static struct clk_factors_config sun9i_a80_gt_config = {
>> +     .mshift = 0,
>> +     .mwidth = 2,
>> +};
>> +
>> +static const struct factors_data sun9i_a80_gt_data __initconst = {
>> +     .mux = 24,
>> +     .muxmask = BIT(1) | BIT(0),
>> +     .table = &sun9i_a80_gt_config,
>> +     .getter = sun9i_a80_get_gt_factors,
>> +};
>> +
>> +static DEFINE_SPINLOCK(sun9i_a80_gt_lock);
>> +
>> +static void __init sun9i_a80_gt_setup(struct device_node *node)
>> +{
>> +     struct clk *gt = sunxi_factors_register(node, &sun9i_a80_gt_data,
>> +                                             &sun9i_a80_gt_lock);
>> +
>> +     /* The GT bus clock needs to be always enabled */
>> +     __clk_get(gt);
>> +     clk_prepare_enable(gt);
>> +}
>> +CLK_OF_DECLARE(sun9i_a80_gt, "allwinner,sun9i-a80-gt-clk", sun9i_a80_gt_setup);
>> +
>> +
>> +/**
>> + * sun9i_a80_get_ahb_factors() - calculates p factor for AHB0/1/2
>> + * AHB rate is calculated as follows
>> + * rate = parent_rate >> p;
>> + */
>> +
>> +static void sun9i_a80_get_ahb_factors(u32 *freq, u32 parent_rate,
>> +                                   u8 *n, u8 *k, u8 *m, u8 *p)
>> +{
>> +     u32 _p;
>> +
>> +     if (parent_rate < *freq)
>> +             *freq = parent_rate;
>> +
>> +     _p = order_base_2(DIV_ROUND_UP(parent_rate, *freq));
>> +
>> +     /* maximum p is 3 */
>> +     if (_p > 3)
>> +             _p = 3;
>> +
>> +     *freq = parent_rate >> _p;
>> +
>> +     /* we were called to round the frequency, we can now return */
>> +     if (!p)
>> +             return;
>> +
>> +     *p = _p;
>> +}
>> +
>> +static struct clk_factors_config sun9i_a80_ahb_config = {
>> +     .pshift = 0,
>> +     .pwidth = 2,
>> +};
>> +
>> +static const struct factors_data sun9i_a80_ahb_data __initconst = {
>> +     .mux = 24,
>> +     .muxmask = BIT(1) | BIT(0),
>> +     .table = &sun9i_a80_ahb_config,
>> +     .getter = sun9i_a80_get_ahb_factors,
>> +};
>> +
>> +static DEFINE_SPINLOCK(sun9i_a80_ahb_lock);
>> +
>> +static void __init sun9i_a80_ahb_setup(struct device_node *node)
>> +{
>> +     sunxi_factors_register(node, &sun9i_a80_ahb_data, &sun9i_a80_ahb_lock);
>> +}
>> +CLK_OF_DECLARE(sun9i_a80_ahb, "allwinner,sun9i-a80-ahb-clk", sun9i_a80_ahb_setup);
>> +
>> +
>> +static const struct factors_data sun9i_a80_apb0_data __initconst = {
>> +     .mux = 24,
>> +     .muxmask = BIT(0),
>> +     .table = &sun9i_a80_ahb_config,
>> +     .getter = sun9i_a80_get_ahb_factors,
>> +};
>> +
>> +static DEFINE_SPINLOCK(sun9i_a80_apb0_lock);
>> +
>> +static void __init sun9i_a80_apb0_setup(struct device_node *node)
>> +{
>> +     sunxi_factors_register(node, &sun9i_a80_apb0_data, &sun9i_a80_apb0_lock);
>> +}
>> +CLK_OF_DECLARE(sun9i_a80_apb0, "allwinner,sun9i-a80-apb0-clk", sun9i_a80_apb0_setup);
>> +
>> +
>> +/**
>> + * sun9i_a80_get_apb1_factors() - calculates m, p factors for APB1
>> + * APB1 rate is calculated as follows
>> + * rate = (parent_rate >> p) / (m + 1);
>> + */
>> +
>> +static void sun9i_a80_get_apb1_factors(u32 *freq, u32 parent_rate,
>> +                                    u8 *n, u8 *k, u8 *m, u8 *p)
>> +{
>> +     u32 div;
>> +     u8 calcm, calcp;
>> +
>> +     if (parent_rate < *freq)
>> +             *freq = parent_rate;
>> +
>> +     div = DIV_ROUND_UP(parent_rate, *freq);
>> +
>> +     /* Highest possible divider is 256 (p = 3, m = 31) */
>> +     if (div > 256)
>> +             div = 256;
>> +
>> +     calcp = order_base_2(div);
>> +     calcm = (parent_rate >> calcp) - 1;
>> +     *freq = (parent_rate >> calcp) / (calcm + 1);
>> +
>> +     /* we were called to round the frequency, we can now return */
>> +     if (n == NULL)
>> +             return;
>> +
>> +     *m = calcm;
>> +     *p = calcp;
>> +}
>> +
>> +static struct clk_factors_config sun9i_a80_apb1_config = {
>> +     .mshift = 0,
>> +     .mwidth = 5,
>> +     .pshift = 16,
>> +     .pwidth = 2,
>> +};
>> +
>> +static const struct factors_data sun9i_a80_apb1_data __initconst = {
>> +     .mux = 24,
>> +     .muxmask = BIT(0),
>> +     .table = &sun9i_a80_apb1_config,
>> +     .getter = sun9i_a80_get_apb1_factors,
>> +};
>> +
>> +static DEFINE_SPINLOCK(sun9i_a80_apb1_lock);
>> +
>> +static void __init sun9i_a80_apb1_setup(struct device_node *node)
>> +{
>> +     sunxi_factors_register(node, &sun9i_a80_apb1_data, &sun9i_a80_apb1_lock);
>> +}
>> +CLK_OF_DECLARE(sun9i_a80_apb1, "allwinner,sun9i-a80-apb1-clk", sun9i_a80_apb1_setup);
>> +
>
> Do these clocks share anything (aside from being for the A80) that
> require them to be in the same file?

They are part of the same tree hierarchy. But otherwise no requirements.

I would put CPU plls and clocks in a different file, module clocks in another,
and the remaining (media related) plls in yet another one.

I think having one file per clock is kind of taking it too far.

> Thanks for your work!
> Maxime

Thanks!
ChenYu

^ permalink raw reply	[flat|nested] 16+ messages in thread

* [PATCH 2/5] clk: sunxi: Add support for A80 basic bus clocks
  2014-10-16 12:35     ` Chen-Yu Tsai
@ 2014-10-17 13:51       ` Maxime Ripard
  2014-10-18 13:35         ` Chen-Yu Tsai
  0 siblings, 1 reply; 16+ messages in thread
From: Maxime Ripard @ 2014-10-17 13:51 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Oct 16, 2014 at 08:35:49PM +0800, Chen-Yu Tsai wrote:
> On Thu, Oct 16, 2014 at 4:31 PM, Maxime Ripard
> <maxime.ripard@free-electrons.com> wrote:
> > On Sun, Oct 12, 2014 at 05:40:22PM +0800, Chen-Yu Tsai wrote:
> >> The A80 SoC has 12 PLL clocks, 3 AHB clocks, 2 APB clocks, and a
> >> new "GT" bus, which I assume is some kind of data bus connecting
> >> the processor cores, memory and various busses. Also there is a
> >> bus clock for a ARM CCI400 module.
> >>
> >> As far as I can tell, the GT bus and CCI400 bus clock must be
> >> protected.
> >>
> >> This patch adds driver support for peripheral related PLLs and
> >> bus clocks on the A80. The GT and CCI400 clocks are added as well
> >> as these 2 along with the PLLs they are clocked from must not be
> >> disabled.
> >>
> >> Signed-off-by: Chen-Yu Tsai <wens@csie.org>
> >> ---
> >>  Documentation/devicetree/bindings/clock/sunxi.txt |   5 +
> >>  drivers/clk/sunxi/Makefile                        |   1 +
> >>  drivers/clk/sunxi/clk-sun9i-core.c                | 272 ++++++++++++++++++++++
> >>  3 files changed, 278 insertions(+)
> >>  create mode 100644 drivers/clk/sunxi/clk-sun9i-core.c
> >>
> >> diff --git a/Documentation/devicetree/bindings/clock/sunxi.txt b/Documentation/devicetree/bindings/clock/sunxi.txt
> >> index ed116df..7f1c486 100644
> >> --- a/Documentation/devicetree/bindings/clock/sunxi.txt
> >> +++ b/Documentation/devicetree/bindings/clock/sunxi.txt
> >> @@ -10,14 +10,17 @@ Required properties:
> >>       "allwinner,sun4i-a10-pll1-clk" - for the main PLL clock and PLL4
> >>       "allwinner,sun6i-a31-pll1-clk" - for the main PLL clock on A31
> >>       "allwinner,sun8i-a23-pll1-clk" - for the main PLL clock on A23
> >> +     "allwinner,sun9i-a80-pll4-clk" - for the peripheral PLLs on A80
> >>       "allwinner,sun4i-a10-pll5-clk" - for the PLL5 clock
> >>       "allwinner,sun4i-a10-pll6-clk" - for the PLL6 clock
> >>       "allwinner,sun6i-a31-pll6-clk" - for the PLL6 clock on A31
> >> +     "allwinner,sun9i-a80-gt-clk" - for the GT bus clock on A80
> >>       "allwinner,sun4i-a10-cpu-clk" - for the CPU multiplexer clock
> >>       "allwinner,sun4i-a10-axi-clk" - for the AXI clock
> >>       "allwinner,sun8i-a23-axi-clk" - for the AXI clock on A23
> >>       "allwinner,sun4i-a10-axi-gates-clk" - for the AXI gates
> >>       "allwinner,sun4i-a10-ahb-clk" - for the AHB clock
> >> +     "allwinner,sun9i-a80-ahb-clk" - for the AHB bus clocks on A80
> >>       "allwinner,sun4i-a10-ahb-gates-clk" - for the AHB gates on A10
> >>       "allwinner,sun5i-a13-ahb-gates-clk" - for the AHB gates on A13
> >>       "allwinner,sun5i-a10s-ahb-gates-clk" - for the AHB gates on A10s
> >> @@ -29,6 +32,7 @@ Required properties:
> >>       "allwinner,sun4i-a10-apb0-clk" - for the APB0 clock
> >>       "allwinner,sun6i-a31-apb0-clk" - for the APB0 clock on A31
> >>       "allwinner,sun8i-a23-apb0-clk" - for the APB0 clock on A23
> >> +     "allwinner,sun9i-a80-apb0-clk" - for the APB0 bus clock on A80
> >>       "allwinner,sun4i-a10-apb0-gates-clk" - for the APB0 gates on A10
> >>       "allwinner,sun5i-a13-apb0-gates-clk" - for the APB0 gates on A13
> >>       "allwinner,sun5i-a10s-apb0-gates-clk" - for the APB0 gates on A10s
> >> @@ -36,6 +40,7 @@ Required properties:
> >>       "allwinner,sun7i-a20-apb0-gates-clk" - for the APB0 gates on A20
> >>       "allwinner,sun8i-a23-apb0-gates-clk" - for the APB0 gates on A23
> >>       "allwinner,sun4i-a10-apb1-clk" - for the APB1 clock
> >> +     "allwinner,sun9i-a80-apb1-clk" - for the APB1 bus clock on A80
> >>       "allwinner,sun4i-a10-apb1-mux-clk" - for the APB1 clock muxing
> >>       "allwinner,sun4i-a10-apb1-gates-clk" - for the APB1 gates on A10
> >>       "allwinner,sun5i-a13-apb1-gates-clk" - for the APB1 gates on A13
> >> diff --git a/drivers/clk/sunxi/Makefile b/drivers/clk/sunxi/Makefile
> >> index 7ddc2b5..a66953c 100644
> >> --- a/drivers/clk/sunxi/Makefile
> >> +++ b/drivers/clk/sunxi/Makefile
> >> @@ -7,6 +7,7 @@ obj-y += clk-a10-hosc.o
> >>  obj-y += clk-a20-gmac.o
> >>  obj-y += clk-mod0.o
> >>  obj-y += clk-sun8i-mbus.o
> >> +obj-y += clk-sun9i-core.o
> >>
> >>  obj-$(CONFIG_MFD_SUN6I_PRCM) += \
> >>       clk-sun6i-ar100.o clk-sun6i-apb0.o clk-sun6i-apb0-gates.o \
> >> diff --git a/drivers/clk/sunxi/clk-sun9i-core.c b/drivers/clk/sunxi/clk-sun9i-core.c
> >> new file mode 100644
> >> index 0000000..ba5f091
> >> --- /dev/null
> >> +++ b/drivers/clk/sunxi/clk-sun9i-core.c
> >> @@ -0,0 +1,272 @@
> >> +/*
> >> + * Copyright 2014 Chen-Yu Tsai
> >> + *
> >> + * Chen-Yu Tsai <wens@csie.org>
> >> + *
> >> + * This program is free software; you can redistribute it and/or modify
> >> + * it under the terms of the GNU General Public License as published by
> >> + * the Free Software Foundation; either version 2 of the License, or
> >> + * (at your option) any later version.
> >> + *
> >> + * This program is distributed in the hope that it will be useful,
> >> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> >> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> >> + * GNU General Public License for more details.
> >> + */
> >> +
> >> +#include <linux/clk-provider.h>
> >> +#include <linux/clkdev.h>
> >> +#include <linux/of.h>
> >> +#include <linux/of_address.h>
> >> +#include <linux/log2.h>
> >> +
> >> +#include "clk-factors.h"
> >> +
> >> +
> >> +/**
> >> + * sun9i_a80_get_pll4_factors() - calculates n, p, m factors for PLL1
> >> + * PLL4 rate is calculated as follows
> >> + * rate = (parent_rate * n >> p) / (m + 1);
> >> + * parent_rate is always 24Mhz
> >> + *
> >> + * p and m are named div1 and div2 in Allwinner's SDK
> >> + */
> >> +
> >> +static void sun9i_a80_get_pll4_factors(u32 *freq, u32 parent_rate,
> >> +                                    u8 *n, u8 *k, u8 *m, u8 *p)
> >> +{
> >> +     int div;
> >> +
> >> +     /* Normalize value to a 6M multiple */
> >> +     div = *freq / 6000000;
> >> +
> >> +     /* divs above 256 cannot be odd */
> >> +     if (div > 256)
> >> +             div &= ~0x1;
> >> +
> >> +     /* divs above 512 must be a multiple of 4 */
> >> +     if (div > 512)
> >> +             div &= ~0x3;
> >
> > round_up / round_down looks more readable.
> 
> OK.
> 
> >> +
> >> +     *freq = 6000000 * div;
> >
> > and here as well
> 
> This won't look pretty with round_up/round_down i think.
> This function is supposed to return the actual closest supported
> frequency, so it depends on the calculated/rounded divider from
> the previous section.

Well, if I understood your code correctly, you want to round the
frequency to 6MHz multiple if div < 256, 12MHz if div < 512 and 24MHz
otherwise right?

I'm confident it can be made prettier.

> >> +     /* we were called to round the frequency, we can now return */
> >> +     if (n == NULL)
> >> +             return;
> >> +
> >> +     /* p will be 1 for divs under 512 */
> >> +     if (div < 512)
> >> +             *p = 1;
> >> +     else
> >> +             *p = 0;
> >> +
> >> +     /* m will be 1 if div is odd */
> >> +     if (div & 1)
> >> +             *m = 1;
> >> +     else
> >> +             *m = 0;
> >> +
> >> +     /* calculate a suitable n based on m and p */
> >> +     *n = div / (*p + 1) / (*m + 1);
> >> +}
> >> +
> >> +static struct clk_factors_config sun9i_a80_pll4_config = {
> >> +     .mshift = 18,
> >> +     .mwidth = 1,
> >> +     .nshift = 8,
> >> +     .nwidth = 8,
> >> +     .pshift = 16,
> >> +     .pwidth = 1,
> >> +};
> >> +
> >> +static const struct factors_data sun9i_a80_pll4_data __initconst = {
> >> +     .enable = 31,
> >> +     .table = &sun9i_a80_pll4_config,
> >> +     .getter = sun9i_a80_get_pll4_factors,
> >> +};
> >> +
> >> +static DEFINE_SPINLOCK(sun9i_a80_pll4_lock);
> >> +
> >> +static void __init sun9i_a80_pll4_setup(struct device_node *node)
> >> +{
> >> +     sunxi_factors_register(node, &sun9i_a80_pll4_data, &sun9i_a80_pll4_lock);
> >> +}
> >> +CLK_OF_DECLARE(sun9i_a80_pll4, "allwinner,sun9i-a80-pll4-clk", sun9i_a80_pll4_setup);
> >> +
> >> +
> >> +/**
> >> + * sun9i_a80_get_gt_factors() - calculates m factor for GT
> >> + * GT rate is calculated as follows
> >> + * rate = parent_rate / (m + 1);
> >> + */
> >> +
> >> +static void sun9i_a80_get_gt_factors(u32 *freq, u32 parent_rate,
> >> +                                  u8 *n, u8 *k, u8 *m, u8 *p)
> >> +{
> >> +     u32 div;
> >> +
> >> +     if (parent_rate < *freq)
> >> +             *freq = parent_rate;
> >> +
> >> +     div = DIV_ROUND_UP(parent_rate, *freq);
> >> +
> >> +     /* maximum divider is 4 */
> >> +     if (div > 4)
> >> +             div = 4;
> >> +
> >> +     *freq = parent_rate / div;
> >> +
> >> +     /* we were called to round the frequency, we can now return */
> >> +     if (!m)
> >> +             return;
> >> +
> >> +     *m = div;
> >> +}
> >> +
> >> +static struct clk_factors_config sun9i_a80_gt_config = {
> >> +     .mshift = 0,
> >> +     .mwidth = 2,
> >> +};
> >> +
> >> +static const struct factors_data sun9i_a80_gt_data __initconst = {
> >> +     .mux = 24,
> >> +     .muxmask = BIT(1) | BIT(0),
> >> +     .table = &sun9i_a80_gt_config,
> >> +     .getter = sun9i_a80_get_gt_factors,
> >> +};
> >> +
> >> +static DEFINE_SPINLOCK(sun9i_a80_gt_lock);
> >> +
> >> +static void __init sun9i_a80_gt_setup(struct device_node *node)
> >> +{
> >> +     struct clk *gt = sunxi_factors_register(node, &sun9i_a80_gt_data,
> >> +                                             &sun9i_a80_gt_lock);
> >> +
> >> +     /* The GT bus clock needs to be always enabled */
> >> +     __clk_get(gt);
> >> +     clk_prepare_enable(gt);
> >> +}
> >> +CLK_OF_DECLARE(sun9i_a80_gt, "allwinner,sun9i-a80-gt-clk", sun9i_a80_gt_setup);
> >> +
> >> +
> >> +/**
> >> + * sun9i_a80_get_ahb_factors() - calculates p factor for AHB0/1/2
> >> + * AHB rate is calculated as follows
> >> + * rate = parent_rate >> p;
> >> + */
> >> +
> >> +static void sun9i_a80_get_ahb_factors(u32 *freq, u32 parent_rate,
> >> +                                   u8 *n, u8 *k, u8 *m, u8 *p)
> >> +{
> >> +     u32 _p;
> >> +
> >> +     if (parent_rate < *freq)
> >> +             *freq = parent_rate;
> >> +
> >> +     _p = order_base_2(DIV_ROUND_UP(parent_rate, *freq));
> >> +
> >> +     /* maximum p is 3 */
> >> +     if (_p > 3)
> >> +             _p = 3;
> >> +
> >> +     *freq = parent_rate >> _p;
> >> +
> >> +     /* we were called to round the frequency, we can now return */
> >> +     if (!p)
> >> +             return;
> >> +
> >> +     *p = _p;
> >> +}
> >> +
> >> +static struct clk_factors_config sun9i_a80_ahb_config = {
> >> +     .pshift = 0,
> >> +     .pwidth = 2,
> >> +};
> >> +
> >> +static const struct factors_data sun9i_a80_ahb_data __initconst = {
> >> +     .mux = 24,
> >> +     .muxmask = BIT(1) | BIT(0),
> >> +     .table = &sun9i_a80_ahb_config,
> >> +     .getter = sun9i_a80_get_ahb_factors,
> >> +};
> >> +
> >> +static DEFINE_SPINLOCK(sun9i_a80_ahb_lock);
> >> +
> >> +static void __init sun9i_a80_ahb_setup(struct device_node *node)
> >> +{
> >> +     sunxi_factors_register(node, &sun9i_a80_ahb_data, &sun9i_a80_ahb_lock);
> >> +}
> >> +CLK_OF_DECLARE(sun9i_a80_ahb, "allwinner,sun9i-a80-ahb-clk", sun9i_a80_ahb_setup);
> >> +
> >> +
> >> +static const struct factors_data sun9i_a80_apb0_data __initconst = {
> >> +     .mux = 24,
> >> +     .muxmask = BIT(0),
> >> +     .table = &sun9i_a80_ahb_config,
> >> +     .getter = sun9i_a80_get_ahb_factors,
> >> +};
> >> +
> >> +static DEFINE_SPINLOCK(sun9i_a80_apb0_lock);
> >> +
> >> +static void __init sun9i_a80_apb0_setup(struct device_node *node)
> >> +{
> >> +     sunxi_factors_register(node, &sun9i_a80_apb0_data, &sun9i_a80_apb0_lock);
> >> +}
> >> +CLK_OF_DECLARE(sun9i_a80_apb0, "allwinner,sun9i-a80-apb0-clk", sun9i_a80_apb0_setup);
> >> +
> >> +
> >> +/**
> >> + * sun9i_a80_get_apb1_factors() - calculates m, p factors for APB1
> >> + * APB1 rate is calculated as follows
> >> + * rate = (parent_rate >> p) / (m + 1);
> >> + */
> >> +
> >> +static void sun9i_a80_get_apb1_factors(u32 *freq, u32 parent_rate,
> >> +                                    u8 *n, u8 *k, u8 *m, u8 *p)
> >> +{
> >> +     u32 div;
> >> +     u8 calcm, calcp;
> >> +
> >> +     if (parent_rate < *freq)
> >> +             *freq = parent_rate;
> >> +
> >> +     div = DIV_ROUND_UP(parent_rate, *freq);
> >> +
> >> +     /* Highest possible divider is 256 (p = 3, m = 31) */
> >> +     if (div > 256)
> >> +             div = 256;
> >> +
> >> +     calcp = order_base_2(div);
> >> +     calcm = (parent_rate >> calcp) - 1;
> >> +     *freq = (parent_rate >> calcp) / (calcm + 1);
> >> +
> >> +     /* we were called to round the frequency, we can now return */
> >> +     if (n == NULL)
> >> +             return;
> >> +
> >> +     *m = calcm;
> >> +     *p = calcp;
> >> +}
> >> +
> >> +static struct clk_factors_config sun9i_a80_apb1_config = {
> >> +     .mshift = 0,
> >> +     .mwidth = 5,
> >> +     .pshift = 16,
> >> +     .pwidth = 2,
> >> +};
> >> +
> >> +static const struct factors_data sun9i_a80_apb1_data __initconst = {
> >> +     .mux = 24,
> >> +     .muxmask = BIT(0),
> >> +     .table = &sun9i_a80_apb1_config,
> >> +     .getter = sun9i_a80_get_apb1_factors,
> >> +};
> >> +
> >> +static DEFINE_SPINLOCK(sun9i_a80_apb1_lock);
> >> +
> >> +static void __init sun9i_a80_apb1_setup(struct device_node *node)
> >> +{
> >> +     sunxi_factors_register(node, &sun9i_a80_apb1_data, &sun9i_a80_apb1_lock);
> >> +}
> >> +CLK_OF_DECLARE(sun9i_a80_apb1, "allwinner,sun9i-a80-apb1-clk", sun9i_a80_apb1_setup);
> >> +
> >
> > Do these clocks share anything (aside from being for the A80) that
> > require them to be in the same file?
> 
> They are part of the same tree hierarchy. But otherwise no requirements.
> 
> I would put CPU plls and clocks in a different file, module clocks in another,
> and the remaining (media related) plls in yet another one.

Yep, it looks better.
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: 819 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20141017/200b04b3/attachment.sig>

^ permalink raw reply	[flat|nested] 16+ messages in thread

* [PATCH 2/5] clk: sunxi: Add support for A80 basic bus clocks
  2014-10-17 13:51       ` Maxime Ripard
@ 2014-10-18 13:35         ` Chen-Yu Tsai
  2014-10-20  9:05           ` Maxime Ripard
  0 siblings, 1 reply; 16+ messages in thread
From: Chen-Yu Tsai @ 2014-10-18 13:35 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, Oct 17, 2014 at 9:51 PM, Maxime Ripard
<maxime.ripard@free-electrons.com> wrote:
> On Thu, Oct 16, 2014 at 08:35:49PM +0800, Chen-Yu Tsai wrote:
>> On Thu, Oct 16, 2014 at 4:31 PM, Maxime Ripard
>> <maxime.ripard@free-electrons.com> wrote:
>> > On Sun, Oct 12, 2014 at 05:40:22PM +0800, Chen-Yu Tsai wrote:
>> >> The A80 SoC has 12 PLL clocks, 3 AHB clocks, 2 APB clocks, and a
>> >> new "GT" bus, which I assume is some kind of data bus connecting
>> >> the processor cores, memory and various busses. Also there is a
>> >> bus clock for a ARM CCI400 module.
>> >>
>> >> As far as I can tell, the GT bus and CCI400 bus clock must be
>> >> protected.
>> >>
>> >> This patch adds driver support for peripheral related PLLs and
>> >> bus clocks on the A80. The GT and CCI400 clocks are added as well
>> >> as these 2 along with the PLLs they are clocked from must not be
>> >> disabled.
>> >>
>> >> Signed-off-by: Chen-Yu Tsai <wens@csie.org>
>> >> ---
>> >>  Documentation/devicetree/bindings/clock/sunxi.txt |   5 +
>> >>  drivers/clk/sunxi/Makefile                        |   1 +
>> >>  drivers/clk/sunxi/clk-sun9i-core.c                | 272 ++++++++++++++++++++++
>> >>  3 files changed, 278 insertions(+)
>> >>  create mode 100644 drivers/clk/sunxi/clk-sun9i-core.c
>> >>
>> >> diff --git a/Documentation/devicetree/bindings/clock/sunxi.txt b/Documentation/devicetree/bindings/clock/sunxi.txt
>> >> index ed116df..7f1c486 100644
>> >> --- a/Documentation/devicetree/bindings/clock/sunxi.txt
>> >> +++ b/Documentation/devicetree/bindings/clock/sunxi.txt
>> >> @@ -10,14 +10,17 @@ Required properties:
>> >>       "allwinner,sun4i-a10-pll1-clk" - for the main PLL clock and PLL4
>> >>       "allwinner,sun6i-a31-pll1-clk" - for the main PLL clock on A31
>> >>       "allwinner,sun8i-a23-pll1-clk" - for the main PLL clock on A23
>> >> +     "allwinner,sun9i-a80-pll4-clk" - for the peripheral PLLs on A80
>> >>       "allwinner,sun4i-a10-pll5-clk" - for the PLL5 clock
>> >>       "allwinner,sun4i-a10-pll6-clk" - for the PLL6 clock
>> >>       "allwinner,sun6i-a31-pll6-clk" - for the PLL6 clock on A31
>> >> +     "allwinner,sun9i-a80-gt-clk" - for the GT bus clock on A80
>> >>       "allwinner,sun4i-a10-cpu-clk" - for the CPU multiplexer clock
>> >>       "allwinner,sun4i-a10-axi-clk" - for the AXI clock
>> >>       "allwinner,sun8i-a23-axi-clk" - for the AXI clock on A23
>> >>       "allwinner,sun4i-a10-axi-gates-clk" - for the AXI gates
>> >>       "allwinner,sun4i-a10-ahb-clk" - for the AHB clock
>> >> +     "allwinner,sun9i-a80-ahb-clk" - for the AHB bus clocks on A80
>> >>       "allwinner,sun4i-a10-ahb-gates-clk" - for the AHB gates on A10
>> >>       "allwinner,sun5i-a13-ahb-gates-clk" - for the AHB gates on A13
>> >>       "allwinner,sun5i-a10s-ahb-gates-clk" - for the AHB gates on A10s
>> >> @@ -29,6 +32,7 @@ Required properties:
>> >>       "allwinner,sun4i-a10-apb0-clk" - for the APB0 clock
>> >>       "allwinner,sun6i-a31-apb0-clk" - for the APB0 clock on A31
>> >>       "allwinner,sun8i-a23-apb0-clk" - for the APB0 clock on A23
>> >> +     "allwinner,sun9i-a80-apb0-clk" - for the APB0 bus clock on A80
>> >>       "allwinner,sun4i-a10-apb0-gates-clk" - for the APB0 gates on A10
>> >>       "allwinner,sun5i-a13-apb0-gates-clk" - for the APB0 gates on A13
>> >>       "allwinner,sun5i-a10s-apb0-gates-clk" - for the APB0 gates on A10s
>> >> @@ -36,6 +40,7 @@ Required properties:
>> >>       "allwinner,sun7i-a20-apb0-gates-clk" - for the APB0 gates on A20
>> >>       "allwinner,sun8i-a23-apb0-gates-clk" - for the APB0 gates on A23
>> >>       "allwinner,sun4i-a10-apb1-clk" - for the APB1 clock
>> >> +     "allwinner,sun9i-a80-apb1-clk" - for the APB1 bus clock on A80
>> >>       "allwinner,sun4i-a10-apb1-mux-clk" - for the APB1 clock muxing
>> >>       "allwinner,sun4i-a10-apb1-gates-clk" - for the APB1 gates on A10
>> >>       "allwinner,sun5i-a13-apb1-gates-clk" - for the APB1 gates on A13
>> >> diff --git a/drivers/clk/sunxi/Makefile b/drivers/clk/sunxi/Makefile
>> >> index 7ddc2b5..a66953c 100644
>> >> --- a/drivers/clk/sunxi/Makefile
>> >> +++ b/drivers/clk/sunxi/Makefile
>> >> @@ -7,6 +7,7 @@ obj-y += clk-a10-hosc.o
>> >>  obj-y += clk-a20-gmac.o
>> >>  obj-y += clk-mod0.o
>> >>  obj-y += clk-sun8i-mbus.o
>> >> +obj-y += clk-sun9i-core.o
>> >>
>> >>  obj-$(CONFIG_MFD_SUN6I_PRCM) += \
>> >>       clk-sun6i-ar100.o clk-sun6i-apb0.o clk-sun6i-apb0-gates.o \
>> >> diff --git a/drivers/clk/sunxi/clk-sun9i-core.c b/drivers/clk/sunxi/clk-sun9i-core.c
>> >> new file mode 100644
>> >> index 0000000..ba5f091
>> >> --- /dev/null
>> >> +++ b/drivers/clk/sunxi/clk-sun9i-core.c
>> >> @@ -0,0 +1,272 @@
>> >> +/*
>> >> + * Copyright 2014 Chen-Yu Tsai
>> >> + *
>> >> + * Chen-Yu Tsai <wens@csie.org>
>> >> + *
>> >> + * This program is free software; you can redistribute it and/or modify
>> >> + * it under the terms of the GNU General Public License as published by
>> >> + * the Free Software Foundation; either version 2 of the License, or
>> >> + * (at your option) any later version.
>> >> + *
>> >> + * This program is distributed in the hope that it will be useful,
>> >> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
>> >> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
>> >> + * GNU General Public License for more details.
>> >> + */
>> >> +
>> >> +#include <linux/clk-provider.h>
>> >> +#include <linux/clkdev.h>
>> >> +#include <linux/of.h>
>> >> +#include <linux/of_address.h>
>> >> +#include <linux/log2.h>
>> >> +
>> >> +#include "clk-factors.h"
>> >> +
>> >> +
>> >> +/**
>> >> + * sun9i_a80_get_pll4_factors() - calculates n, p, m factors for PLL1
>> >> + * PLL4 rate is calculated as follows
>> >> + * rate = (parent_rate * n >> p) / (m + 1);
>> >> + * parent_rate is always 24Mhz
>> >> + *
>> >> + * p and m are named div1 and div2 in Allwinner's SDK
>> >> + */
>> >> +
>> >> +static void sun9i_a80_get_pll4_factors(u32 *freq, u32 parent_rate,
>> >> +                                    u8 *n, u8 *k, u8 *m, u8 *p)
>> >> +{
>> >> +     int div;
>> >> +
>> >> +     /* Normalize value to a 6M multiple */
>> >> +     div = *freq / 6000000;
>> >> +
>> >> +     /* divs above 256 cannot be odd */
>> >> +     if (div > 256)
>> >> +             div &= ~0x1;
>> >> +
>> >> +     /* divs above 512 must be a multiple of 4 */
>> >> +     if (div > 512)
>> >> +             div &= ~0x3;
>> >
>> > round_up / round_down looks more readable.
>>
>> OK.
>>
>> >> +
>> >> +     *freq = 6000000 * div;
>> >
>> > and here as well
>>
>> This won't look pretty with round_up/round_down i think.
>> This function is supposed to return the actual closest supported
>> frequency, so it depends on the calculated/rounded divider from
>> the previous section.
>
> Well, if I understood your code correctly, you want to round the
> frequency to 6MHz multiple if div < 256, 12MHz if div < 512 and 24MHz
> otherwise right?
>
> I'm confident it can be made prettier.

I seem to have responded incorrectly.

What I meant to say is that i can replace the bitmasking with
ROUND_UP/ROUND_DOWN, but the conditionals will still be there.

Is that what you had in mind?

>> >> +     /* we were called to round the frequency, we can now return */
>> >> +     if (n == NULL)
>> >> +             return;
>> >> +
>> >> +     /* p will be 1 for divs under 512 */
>> >> +     if (div < 512)
>> >> +             *p = 1;
>> >> +     else
>> >> +             *p = 0;
>> >> +
>> >> +     /* m will be 1 if div is odd */
>> >> +     if (div & 1)
>> >> +             *m = 1;
>> >> +     else
>> >> +             *m = 0;
>> >> +
>> >> +     /* calculate a suitable n based on m and p */
>> >> +     *n = div / (*p + 1) / (*m + 1);
>> >> +}
>> >> +
>> >> +static struct clk_factors_config sun9i_a80_pll4_config = {
>> >> +     .mshift = 18,
>> >> +     .mwidth = 1,
>> >> +     .nshift = 8,
>> >> +     .nwidth = 8,
>> >> +     .pshift = 16,
>> >> +     .pwidth = 1,
>> >> +};
>> >> +
>> >> +static const struct factors_data sun9i_a80_pll4_data __initconst = {
>> >> +     .enable = 31,
>> >> +     .table = &sun9i_a80_pll4_config,
>> >> +     .getter = sun9i_a80_get_pll4_factors,
>> >> +};
>> >> +
>> >> +static DEFINE_SPINLOCK(sun9i_a80_pll4_lock);
>> >> +
>> >> +static void __init sun9i_a80_pll4_setup(struct device_node *node)
>> >> +{
>> >> +     sunxi_factors_register(node, &sun9i_a80_pll4_data, &sun9i_a80_pll4_lock);
>> >> +}
>> >> +CLK_OF_DECLARE(sun9i_a80_pll4, "allwinner,sun9i-a80-pll4-clk", sun9i_a80_pll4_setup);
>> >> +
>> >> +
>> >> +/**
>> >> + * sun9i_a80_get_gt_factors() - calculates m factor for GT
>> >> + * GT rate is calculated as follows
>> >> + * rate = parent_rate / (m + 1);
>> >> + */
>> >> +
>> >> +static void sun9i_a80_get_gt_factors(u32 *freq, u32 parent_rate,
>> >> +                                  u8 *n, u8 *k, u8 *m, u8 *p)
>> >> +{
>> >> +     u32 div;
>> >> +
>> >> +     if (parent_rate < *freq)
>> >> +             *freq = parent_rate;
>> >> +
>> >> +     div = DIV_ROUND_UP(parent_rate, *freq);
>> >> +
>> >> +     /* maximum divider is 4 */
>> >> +     if (div > 4)
>> >> +             div = 4;
>> >> +
>> >> +     *freq = parent_rate / div;
>> >> +
>> >> +     /* we were called to round the frequency, we can now return */
>> >> +     if (!m)
>> >> +             return;
>> >> +
>> >> +     *m = div;
>> >> +}
>> >> +
>> >> +static struct clk_factors_config sun9i_a80_gt_config = {
>> >> +     .mshift = 0,
>> >> +     .mwidth = 2,
>> >> +};
>> >> +
>> >> +static const struct factors_data sun9i_a80_gt_data __initconst = {
>> >> +     .mux = 24,
>> >> +     .muxmask = BIT(1) | BIT(0),
>> >> +     .table = &sun9i_a80_gt_config,
>> >> +     .getter = sun9i_a80_get_gt_factors,
>> >> +};
>> >> +
>> >> +static DEFINE_SPINLOCK(sun9i_a80_gt_lock);
>> >> +
>> >> +static void __init sun9i_a80_gt_setup(struct device_node *node)
>> >> +{
>> >> +     struct clk *gt = sunxi_factors_register(node, &sun9i_a80_gt_data,
>> >> +                                             &sun9i_a80_gt_lock);
>> >> +
>> >> +     /* The GT bus clock needs to be always enabled */
>> >> +     __clk_get(gt);
>> >> +     clk_prepare_enable(gt);
>> >> +}
>> >> +CLK_OF_DECLARE(sun9i_a80_gt, "allwinner,sun9i-a80-gt-clk", sun9i_a80_gt_setup);
>> >> +
>> >> +
>> >> +/**
>> >> + * sun9i_a80_get_ahb_factors() - calculates p factor for AHB0/1/2
>> >> + * AHB rate is calculated as follows
>> >> + * rate = parent_rate >> p;
>> >> + */
>> >> +
>> >> +static void sun9i_a80_get_ahb_factors(u32 *freq, u32 parent_rate,
>> >> +                                   u8 *n, u8 *k, u8 *m, u8 *p)
>> >> +{
>> >> +     u32 _p;
>> >> +
>> >> +     if (parent_rate < *freq)
>> >> +             *freq = parent_rate;
>> >> +
>> >> +     _p = order_base_2(DIV_ROUND_UP(parent_rate, *freq));
>> >> +
>> >> +     /* maximum p is 3 */
>> >> +     if (_p > 3)
>> >> +             _p = 3;
>> >> +
>> >> +     *freq = parent_rate >> _p;
>> >> +
>> >> +     /* we were called to round the frequency, we can now return */
>> >> +     if (!p)
>> >> +             return;
>> >> +
>> >> +     *p = _p;
>> >> +}
>> >> +
>> >> +static struct clk_factors_config sun9i_a80_ahb_config = {
>> >> +     .pshift = 0,
>> >> +     .pwidth = 2,
>> >> +};
>> >> +
>> >> +static const struct factors_data sun9i_a80_ahb_data __initconst = {
>> >> +     .mux = 24,
>> >> +     .muxmask = BIT(1) | BIT(0),
>> >> +     .table = &sun9i_a80_ahb_config,
>> >> +     .getter = sun9i_a80_get_ahb_factors,
>> >> +};
>> >> +
>> >> +static DEFINE_SPINLOCK(sun9i_a80_ahb_lock);
>> >> +
>> >> +static void __init sun9i_a80_ahb_setup(struct device_node *node)
>> >> +{
>> >> +     sunxi_factors_register(node, &sun9i_a80_ahb_data, &sun9i_a80_ahb_lock);
>> >> +}
>> >> +CLK_OF_DECLARE(sun9i_a80_ahb, "allwinner,sun9i-a80-ahb-clk", sun9i_a80_ahb_setup);
>> >> +
>> >> +
>> >> +static const struct factors_data sun9i_a80_apb0_data __initconst = {
>> >> +     .mux = 24,
>> >> +     .muxmask = BIT(0),
>> >> +     .table = &sun9i_a80_ahb_config,
>> >> +     .getter = sun9i_a80_get_ahb_factors,
>> >> +};
>> >> +
>> >> +static DEFINE_SPINLOCK(sun9i_a80_apb0_lock);
>> >> +
>> >> +static void __init sun9i_a80_apb0_setup(struct device_node *node)
>> >> +{
>> >> +     sunxi_factors_register(node, &sun9i_a80_apb0_data, &sun9i_a80_apb0_lock);
>> >> +}
>> >> +CLK_OF_DECLARE(sun9i_a80_apb0, "allwinner,sun9i-a80-apb0-clk", sun9i_a80_apb0_setup);
>> >> +
>> >> +
>> >> +/**
>> >> + * sun9i_a80_get_apb1_factors() - calculates m, p factors for APB1
>> >> + * APB1 rate is calculated as follows
>> >> + * rate = (parent_rate >> p) / (m + 1);
>> >> + */
>> >> +
>> >> +static void sun9i_a80_get_apb1_factors(u32 *freq, u32 parent_rate,
>> >> +                                    u8 *n, u8 *k, u8 *m, u8 *p)
>> >> +{
>> >> +     u32 div;
>> >> +     u8 calcm, calcp;
>> >> +
>> >> +     if (parent_rate < *freq)
>> >> +             *freq = parent_rate;
>> >> +
>> >> +     div = DIV_ROUND_UP(parent_rate, *freq);
>> >> +
>> >> +     /* Highest possible divider is 256 (p = 3, m = 31) */
>> >> +     if (div > 256)
>> >> +             div = 256;
>> >> +
>> >> +     calcp = order_base_2(div);
>> >> +     calcm = (parent_rate >> calcp) - 1;
>> >> +     *freq = (parent_rate >> calcp) / (calcm + 1);
>> >> +
>> >> +     /* we were called to round the frequency, we can now return */
>> >> +     if (n == NULL)
>> >> +             return;
>> >> +
>> >> +     *m = calcm;
>> >> +     *p = calcp;
>> >> +}
>> >> +
>> >> +static struct clk_factors_config sun9i_a80_apb1_config = {
>> >> +     .mshift = 0,
>> >> +     .mwidth = 5,
>> >> +     .pshift = 16,
>> >> +     .pwidth = 2,
>> >> +};
>> >> +
>> >> +static const struct factors_data sun9i_a80_apb1_data __initconst = {
>> >> +     .mux = 24,
>> >> +     .muxmask = BIT(0),
>> >> +     .table = &sun9i_a80_apb1_config,
>> >> +     .getter = sun9i_a80_get_apb1_factors,
>> >> +};
>> >> +
>> >> +static DEFINE_SPINLOCK(sun9i_a80_apb1_lock);
>> >> +
>> >> +static void __init sun9i_a80_apb1_setup(struct device_node *node)
>> >> +{
>> >> +     sunxi_factors_register(node, &sun9i_a80_apb1_data, &sun9i_a80_apb1_lock);
>> >> +}
>> >> +CLK_OF_DECLARE(sun9i_a80_apb1, "allwinner,sun9i-a80-apb1-clk", sun9i_a80_apb1_setup);
>> >> +
>> >
>> > Do these clocks share anything (aside from being for the A80) that
>> > require them to be in the same file?
>>
>> They are part of the same tree hierarchy. But otherwise no requirements.
>>
>> I would put CPU plls and clocks in a different file, module clocks in another,
>> and the remaining (media related) plls in yet another one.
>
> Yep, it looks better.
> Thanks!

:)


ChenYu

^ permalink raw reply	[flat|nested] 16+ messages in thread

* [PATCH 2/5] clk: sunxi: Add support for A80 basic bus clocks
  2014-10-18 13:35         ` Chen-Yu Tsai
@ 2014-10-20  9:05           ` Maxime Ripard
  0 siblings, 0 replies; 16+ messages in thread
From: Maxime Ripard @ 2014-10-20  9:05 UTC (permalink / raw)
  To: linux-arm-kernel

On Sat, Oct 18, 2014 at 09:35:21PM +0800, Chen-Yu Tsai wrote:
> On Fri, Oct 17, 2014 at 9:51 PM, Maxime Ripard
> <maxime.ripard@free-electrons.com> wrote:
> > On Thu, Oct 16, 2014 at 08:35:49PM +0800, Chen-Yu Tsai wrote:
> >> On Thu, Oct 16, 2014 at 4:31 PM, Maxime Ripard
> >> <maxime.ripard@free-electrons.com> wrote:
> >> > On Sun, Oct 12, 2014 at 05:40:22PM +0800, Chen-Yu Tsai wrote:
> >> >> The A80 SoC has 12 PLL clocks, 3 AHB clocks, 2 APB clocks, and a
> >> >> new "GT" bus, which I assume is some kind of data bus connecting
> >> >> the processor cores, memory and various busses. Also there is a
> >> >> bus clock for a ARM CCI400 module.
> >> >>
> >> >> As far as I can tell, the GT bus and CCI400 bus clock must be
> >> >> protected.
> >> >>
> >> >> This patch adds driver support for peripheral related PLLs and
> >> >> bus clocks on the A80. The GT and CCI400 clocks are added as well
> >> >> as these 2 along with the PLLs they are clocked from must not be
> >> >> disabled.
> >> >>
> >> >> Signed-off-by: Chen-Yu Tsai <wens@csie.org>
> >> >> ---
> >> >>  Documentation/devicetree/bindings/clock/sunxi.txt |   5 +
> >> >>  drivers/clk/sunxi/Makefile                        |   1 +
> >> >>  drivers/clk/sunxi/clk-sun9i-core.c                | 272 ++++++++++++++++++++++
> >> >>  3 files changed, 278 insertions(+)
> >> >>  create mode 100644 drivers/clk/sunxi/clk-sun9i-core.c
> >> >>
> >> >> diff --git a/Documentation/devicetree/bindings/clock/sunxi.txt b/Documentation/devicetree/bindings/clock/sunxi.txt
> >> >> index ed116df..7f1c486 100644
> >> >> --- a/Documentation/devicetree/bindings/clock/sunxi.txt
> >> >> +++ b/Documentation/devicetree/bindings/clock/sunxi.txt
> >> >> @@ -10,14 +10,17 @@ Required properties:
> >> >>       "allwinner,sun4i-a10-pll1-clk" - for the main PLL clock and PLL4
> >> >>       "allwinner,sun6i-a31-pll1-clk" - for the main PLL clock on A31
> >> >>       "allwinner,sun8i-a23-pll1-clk" - for the main PLL clock on A23
> >> >> +     "allwinner,sun9i-a80-pll4-clk" - for the peripheral PLLs on A80
> >> >>       "allwinner,sun4i-a10-pll5-clk" - for the PLL5 clock
> >> >>       "allwinner,sun4i-a10-pll6-clk" - for the PLL6 clock
> >> >>       "allwinner,sun6i-a31-pll6-clk" - for the PLL6 clock on A31
> >> >> +     "allwinner,sun9i-a80-gt-clk" - for the GT bus clock on A80
> >> >>       "allwinner,sun4i-a10-cpu-clk" - for the CPU multiplexer clock
> >> >>       "allwinner,sun4i-a10-axi-clk" - for the AXI clock
> >> >>       "allwinner,sun8i-a23-axi-clk" - for the AXI clock on A23
> >> >>       "allwinner,sun4i-a10-axi-gates-clk" - for the AXI gates
> >> >>       "allwinner,sun4i-a10-ahb-clk" - for the AHB clock
> >> >> +     "allwinner,sun9i-a80-ahb-clk" - for the AHB bus clocks on A80
> >> >>       "allwinner,sun4i-a10-ahb-gates-clk" - for the AHB gates on A10
> >> >>       "allwinner,sun5i-a13-ahb-gates-clk" - for the AHB gates on A13
> >> >>       "allwinner,sun5i-a10s-ahb-gates-clk" - for the AHB gates on A10s
> >> >> @@ -29,6 +32,7 @@ Required properties:
> >> >>       "allwinner,sun4i-a10-apb0-clk" - for the APB0 clock
> >> >>       "allwinner,sun6i-a31-apb0-clk" - for the APB0 clock on A31
> >> >>       "allwinner,sun8i-a23-apb0-clk" - for the APB0 clock on A23
> >> >> +     "allwinner,sun9i-a80-apb0-clk" - for the APB0 bus clock on A80
> >> >>       "allwinner,sun4i-a10-apb0-gates-clk" - for the APB0 gates on A10
> >> >>       "allwinner,sun5i-a13-apb0-gates-clk" - for the APB0 gates on A13
> >> >>       "allwinner,sun5i-a10s-apb0-gates-clk" - for the APB0 gates on A10s
> >> >> @@ -36,6 +40,7 @@ Required properties:
> >> >>       "allwinner,sun7i-a20-apb0-gates-clk" - for the APB0 gates on A20
> >> >>       "allwinner,sun8i-a23-apb0-gates-clk" - for the APB0 gates on A23
> >> >>       "allwinner,sun4i-a10-apb1-clk" - for the APB1 clock
> >> >> +     "allwinner,sun9i-a80-apb1-clk" - for the APB1 bus clock on A80
> >> >>       "allwinner,sun4i-a10-apb1-mux-clk" - for the APB1 clock muxing
> >> >>       "allwinner,sun4i-a10-apb1-gates-clk" - for the APB1 gates on A10
> >> >>       "allwinner,sun5i-a13-apb1-gates-clk" - for the APB1 gates on A13
> >> >> diff --git a/drivers/clk/sunxi/Makefile b/drivers/clk/sunxi/Makefile
> >> >> index 7ddc2b5..a66953c 100644
> >> >> --- a/drivers/clk/sunxi/Makefile
> >> >> +++ b/drivers/clk/sunxi/Makefile
> >> >> @@ -7,6 +7,7 @@ obj-y += clk-a10-hosc.o
> >> >>  obj-y += clk-a20-gmac.o
> >> >>  obj-y += clk-mod0.o
> >> >>  obj-y += clk-sun8i-mbus.o
> >> >> +obj-y += clk-sun9i-core.o
> >> >>
> >> >>  obj-$(CONFIG_MFD_SUN6I_PRCM) += \
> >> >>       clk-sun6i-ar100.o clk-sun6i-apb0.o clk-sun6i-apb0-gates.o \
> >> >> diff --git a/drivers/clk/sunxi/clk-sun9i-core.c b/drivers/clk/sunxi/clk-sun9i-core.c
> >> >> new file mode 100644
> >> >> index 0000000..ba5f091
> >> >> --- /dev/null
> >> >> +++ b/drivers/clk/sunxi/clk-sun9i-core.c
> >> >> @@ -0,0 +1,272 @@
> >> >> +/*
> >> >> + * Copyright 2014 Chen-Yu Tsai
> >> >> + *
> >> >> + * Chen-Yu Tsai <wens@csie.org>
> >> >> + *
> >> >> + * This program is free software; you can redistribute it and/or modify
> >> >> + * it under the terms of the GNU General Public License as published by
> >> >> + * the Free Software Foundation; either version 2 of the License, or
> >> >> + * (at your option) any later version.
> >> >> + *
> >> >> + * This program is distributed in the hope that it will be useful,
> >> >> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> >> >> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> >> >> + * GNU General Public License for more details.
> >> >> + */
> >> >> +
> >> >> +#include <linux/clk-provider.h>
> >> >> +#include <linux/clkdev.h>
> >> >> +#include <linux/of.h>
> >> >> +#include <linux/of_address.h>
> >> >> +#include <linux/log2.h>
> >> >> +
> >> >> +#include "clk-factors.h"
> >> >> +
> >> >> +
> >> >> +/**
> >> >> + * sun9i_a80_get_pll4_factors() - calculates n, p, m factors for PLL1
> >> >> + * PLL4 rate is calculated as follows
> >> >> + * rate = (parent_rate * n >> p) / (m + 1);
> >> >> + * parent_rate is always 24Mhz
> >> >> + *
> >> >> + * p and m are named div1 and div2 in Allwinner's SDK
> >> >> + */
> >> >> +
> >> >> +static void sun9i_a80_get_pll4_factors(u32 *freq, u32 parent_rate,
> >> >> +                                    u8 *n, u8 *k, u8 *m, u8 *p)
> >> >> +{
> >> >> +     int div;
> >> >> +
> >> >> +     /* Normalize value to a 6M multiple */
> >> >> +     div = *freq / 6000000;
> >> >> +
> >> >> +     /* divs above 256 cannot be odd */
> >> >> +     if (div > 256)
> >> >> +             div &= ~0x1;
> >> >> +
> >> >> +     /* divs above 512 must be a multiple of 4 */
> >> >> +     if (div > 512)
> >> >> +             div &= ~0x3;
> >> >
> >> > round_up / round_down looks more readable.
> >>
> >> OK.
> >>
> >> >> +
> >> >> +     *freq = 6000000 * div;
> >> >
> >> > and here as well
> >>
> >> This won't look pretty with round_up/round_down i think.
> >> This function is supposed to return the actual closest supported
> >> frequency, so it depends on the calculated/rounded divider from
> >> the previous section.
> >
> > Well, if I understood your code correctly, you want to round the
> > frequency to 6MHz multiple if div < 256, 12MHz if div < 512 and 24MHz
> > otherwise right?
> >
> > I'm confident it can be made prettier.
> 
> I seem to have responded incorrectly.
> 
> What I meant to say is that i can replace the bitmasking with
> ROUND_UP/ROUND_DOWN, but the conditionals will still be there.
> 
> Is that what you had in mind?

Oh, my bad.

Yes, it's definitely something like that I had in mind :)

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: 819 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20141020/e4789ad9/attachment.sig>

^ permalink raw reply	[flat|nested] 16+ messages in thread

* [linux-sunxi] [PATCH 0/5] clk: sunxi: Add peripheral bus clock support for A80
  2014-10-12 15:32   ` Chen-Yu Tsai
@ 2014-12-03 13:11     ` Simos Xenitellis
  2014-12-03 15:21       ` Chen-Yu Tsai
  0 siblings, 1 reply; 16+ messages in thread
From: Simos Xenitellis @ 2014-12-03 13:11 UTC (permalink / raw)
  To: linux-arm-kernel

On Sun, Oct 12, 2014 at 6:32 PM, Chen-Yu Tsai <wens@csie.org> wrote:
> Hi Hans,
>
> On Sun, Oct 12, 2014 at 6:45 PM, Hans de Goede <hdegoede@redhat.com> wrote:
>> Hi ChenYu,
>>
>> On 10/12/2014 11:40 AM, Chen-Yu Tsai wrote:
>>> Hi everyone,
>>>
>>> This series adds support for the basic bus (AHB/APB) clocks used by
>>> peripherals on the A80 SoC. This series is based on my previous A80
>>> bringup series.
>>
>> Cool stuff, any chance you could write a quick howto for getting an
>> upstream kernel to run on the Merrii A80 optimus board, for lazy / very
>> busy people like me? Preferably including a link to an sdcard image
>> which already has all the bootloader bits in place ?
>
> I keep a short status report and howto on my user page on the linux-sunxi wiki:
>
>     http://linux-sunxi.org/User:Wens#A80_Optimus
>
> I will try to expand it this week. Feel free to let me know if something is
> fuzzy or doesn't make sense.
>
>

Hi ChenYu,

Any update on this? (quick howto to get upstream kernel to boot the A80)

Thanks,
Simos

^ permalink raw reply	[flat|nested] 16+ messages in thread

* [linux-sunxi] [PATCH 0/5] clk: sunxi: Add peripheral bus clock support for A80
  2014-12-03 13:11     ` Simos Xenitellis
@ 2014-12-03 15:21       ` Chen-Yu Tsai
  0 siblings, 0 replies; 16+ messages in thread
From: Chen-Yu Tsai @ 2014-12-03 15:21 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, Dec 3, 2014 at 9:11 PM, Simos Xenitellis
<simos.lists@googlemail.com> wrote:
> On Sun, Oct 12, 2014 at 6:32 PM, Chen-Yu Tsai <wens@csie.org> wrote:
>> Hi Hans,
>>
>> On Sun, Oct 12, 2014 at 6:45 PM, Hans de Goede <hdegoede@redhat.com> wrote:
>>> Hi ChenYu,
>>>
>>> On 10/12/2014 11:40 AM, Chen-Yu Tsai wrote:
>>>> Hi everyone,
>>>>
>>>> This series adds support for the basic bus (AHB/APB) clocks used by
>>>> peripherals on the A80 SoC. This series is based on my previous A80
>>>> bringup series.
>>>
>>> Cool stuff, any chance you could write a quick howto for getting an
>>> upstream kernel to run on the Merrii A80 optimus board, for lazy / very
>>> busy people like me? Preferably including a link to an sdcard image
>>> which already has all the bootloader bits in place ?
>>
>> I keep a short status report and howto on my user page on the linux-sunxi wiki:
>>
>>     http://linux-sunxi.org/User:Wens#A80_Optimus
>>
>> I will try to expand it this week. Feel free to let me know if something is
>> fuzzy or doesn't make sense.
>>
>>
>
> Hi ChenYu,
>
> Any update on this? (quick howto to get upstream kernel to boot the A80)

Nothing has changed for the moment, mainly because I've been busy for the past
month, and haven't tried anything else.

ChenYu

^ permalink raw reply	[flat|nested] 16+ messages in thread

end of thread, other threads:[~2014-12-03 15:21 UTC | newest]

Thread overview: 16+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-10-12  9:40 [PATCH 0/5] clk: sunxi: Add peripheral bus clock support for A80 Chen-Yu Tsai
2014-10-12  9:40 ` [PATCH 1/5] clk: sunxi: make factors clock mux mask configurable Chen-Yu Tsai
2014-10-12  9:40 ` [PATCH 2/5] clk: sunxi: Add support for A80 basic bus clocks Chen-Yu Tsai
2014-10-16  8:31   ` Maxime Ripard
2014-10-16 12:35     ` Chen-Yu Tsai
2014-10-17 13:51       ` Maxime Ripard
2014-10-18 13:35         ` Chen-Yu Tsai
2014-10-20  9:05           ` Maxime Ripard
2014-10-12  9:40 ` [PATCH 3/5] clk: sunxi: Add support for bus clock gates on Allwinner A80 SoC Chen-Yu Tsai
2014-10-12  9:40 ` [PATCH 4/5] ARM: sunxi: Select ARCH_HAS_RESET_CONTROLLER and RESET_CONTROLLER for sun9i Chen-Yu Tsai
2014-10-16  8:32   ` Maxime Ripard
2014-10-12  9:40 ` [PATCH 5/5] ARM: dts: sun9i: Add basic clocks and reset controls Chen-Yu Tsai
2014-10-12 10:45 ` [linux-sunxi] [PATCH 0/5] clk: sunxi: Add peripheral bus clock support for A80 Hans de Goede
2014-10-12 15:32   ` Chen-Yu Tsai
2014-12-03 13:11     ` Simos Xenitellis
2014-12-03 15:21       ` Chen-Yu Tsai

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).