Skip to contentSkip to conversation

clk: sunxi: Add peripheral bus clock support for A80

PATCH New Chen-Yu Tsai 4 participants 16 messages Oct 12, 2014 – Dec 3, 2014

Subsystems (6)
lore
Share & tools
lore
#0 lore raw

cover clk: sunxi: Add peripheral bus clock support for A80

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
Signature · 1 line
2.1.1
#1 lore raw

PATCH 1/5 clk: sunxi: make factors clock mux mask configurable

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.

---
 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(-)
drivers/clk/sunxi/clk-factors.c +1 -1
index f83ba09..5521e86 100644
@@ -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;
 	}
drivers/clk/sunxi/clk-factors.h +1 -2
index 9913840..912238f 100644
@@ -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;
drivers/clk/sunxi/clk-mod0.c +1 -0
index 4a56385..da0524ea 100644
@@ -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,
 };
drivers/clk/sunxi/clk-sun8i-mbus.c +1 -0
index 8e49b44..ef49786 100644
@@ -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,
 };
drivers/clk/sunxi/clk-sunxi.c +1 -0
index d5dc951..636b8d7 100644
@@ -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,
 };
Signature · 1 line
2.1.1
#2 lore raw

PATCH 2/5 clk: sunxi: Add support for A80 basic bus clocks

In reply to Chen-Yu Tsai

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.

---
 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
Documentation/devicetree/bindings/clock/sunxi.txt +5 -0
index ed116df..7f1c486 100644
@@ -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
drivers/clk/sunxi/Makefile +1 -0
index 7ddc2b5..a66953c 100644
@@ -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 \
drivers/clk/sunxi/clk-sun9i-core.c new file +272 -0

272 lines not on this page · raw message

Signature · 1 line
2.1.1
#3 lore raw

PATCH 2/5 clk: sunxi: Add support for A80 basic bus clocks

Quoted 116 lines · Chen-Yu Tsai

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.

---
 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
Documentation/devicetree/bindings/clock/sunxi.txt +5 -0
index ed116df..7f1c486 100644
@@ -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
drivers/clk/sunxi/Makefile +1 -0
index 7ddc2b5..a66953c 100644
@@ -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 \
drivers/clk/sunxi/clk-sun9i-core.c new file +39 -0
new file mode 100644
index 0000000..ba5f091
@@ -0,0 +1,272 @@
+/*
+ * Copyright 2014 Chen-Yu Tsai
+ *
+ * Chen-Yu Tsai <[email protected]>
+ *
+ * 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;
+

drivers/clk/sunxi/clk-sun9i-core.c line 49

Quoted 10 lines
drivers/clk/sunxi/clk-sun9i-core.c new file +10 -0
+	/* 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.

drivers/clk/sunxi/clk-sun9i-core.c line 51

Quoted 2 lines
drivers/clk/sunxi/clk-sun9i-core.c new file +2 -0
+
+	*freq = 6000000 * div;

and here as well

Quoted 210 lines
drivers/clk/sunxi/clk-sun9i-core.c new file +210 -0
+	/* 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,

drivers/clk/sunxi/clk-sun9i-core.c line 272

Quoted 10 lines
drivers/clk/sunxi/clk-sun9i-core.c new file +10 -0
+};
+
+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

Signature · 10 lines
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>
#4 lore raw

PATCH 2/5 clk: sunxi: Add support for A80 basic bus clocks

Quoted 121 lines · Maxime Ripard
Quoted 120 lines · Chen-Yu Tsai

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.

---
 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
Documentation/devicetree/bindings/clock/sunxi.txt +5 -0
index ed116df..7f1c486 100644
@@ -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
drivers/clk/sunxi/Makefile +1 -0
index 7ddc2b5..a66953c 100644
@@ -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 \
drivers/clk/sunxi/clk-sun9i-core.c new file +43 -0
new file mode 100644
index 0000000..ba5f091
@@ -0,0 +1,272 @@
+/*
+ * Copyright 2014 Chen-Yu Tsai
+ *
+ * Chen-Yu Tsai <[email protected]>
+ *
+ * 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 */
Quoted 8 lines

drivers/clk/sunxi/clk-sun9i-core.c line 49

Quoted 6 lines
drivers/clk/sunxi/clk-sun9i-core.c new file +6 -0
+     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.

Quoted 4 lines

drivers/clk/sunxi/clk-sun9i-core.c line 51

Quoted 2 lines
drivers/clk/sunxi/clk-sun9i-core.c new file +2 -0
+
+     *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.

Quoted 215 lines
Quoted 215 lines
drivers/clk/sunxi/clk-sun9i-core.c new file +215 -0
+     /* 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)
Quoted 8 lines

drivers/clk/sunxi/clk-sun9i-core.c line 272

Quoted 5 lines
drivers/clk/sunxi/clk-sun9i-core.c new file +5 -0
+{
+     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.

Quoted 2 lines

Thanks for your work!
Maxime

Thanks!
ChenYu

#5 lore raw

PATCH 2/5 clk: sunxi: Add support for A80 basic bus clocks

Quoted 137 lines · Chen-Yu Tsai
Quoted 121 lines · Maxime Ripard
Quoted 120 lines · Chen-Yu Tsai

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.

---
 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
Documentation/devicetree/bindings/clock/sunxi.txt +5 -0
index ed116df..7f1c486 100644
@@ -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
drivers/clk/sunxi/Makefile +1 -0
index 7ddc2b5..a66953c 100644
@@ -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 \
drivers/clk/sunxi/clk-sun9i-core.c new file +43 -0
new file mode 100644
index 0000000..ba5f091
@@ -0,0 +1,272 @@
+/*
+ * Copyright 2014 Chen-Yu Tsai
+ *
+ * Chen-Yu Tsai <[email protected]>
+ *
+ * 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 */
Quoted 8 lines

drivers/clk/sunxi/clk-sun9i-core.c line 49

Quoted 6 lines
drivers/clk/sunxi/clk-sun9i-core.c new file +6 -0
+     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.

Quoted 3 lines
Quoted 2 lines
drivers/clk/sunxi/clk-sun9i-core.c new file +2 -0
+
+     *freq = 6000000 * div;
Quoted 6 lines
Quoted 1 line

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.

Quoted 224 lines
Quoted 215 lines
Quoted 215 lines
drivers/clk/sunxi/clk-sun9i-core.c new file +215 -0
+     /* 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)
Quoted 8 lines

drivers/clk/sunxi/clk-sun9i-core.c line 272

Quoted 5 lines
drivers/clk/sunxi/clk-sun9i-core.c new file +5 -0
+{
+     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?

Quoted 4 lines

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

Signature · 10 lines
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>
#6 lore raw

PATCH 2/5 clk: sunxi: Add support for A80 basic bus clocks

Quoted 145 lines · Maxime Ripard
Quoted 137 lines · Chen-Yu Tsai
Quoted 121 lines · Maxime Ripard
Quoted 120 lines · Chen-Yu Tsai

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.

---
 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
Documentation/devicetree/bindings/clock/sunxi.txt +5 -0
index ed116df..7f1c486 100644
@@ -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
drivers/clk/sunxi/Makefile +1 -0
index 7ddc2b5..a66953c 100644
@@ -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 \
drivers/clk/sunxi/clk-sun9i-core.c new file +43 -0
new file mode 100644
index 0000000..ba5f091
@@ -0,0 +1,272 @@
+/*
+ * Copyright 2014 Chen-Yu Tsai
+ *
+ * Chen-Yu Tsai <[email protected]>
+ *
+ * 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 */
Quoted 8 lines

drivers/clk/sunxi/clk-sun9i-core.c line 49

Quoted 6 lines
drivers/clk/sunxi/clk-sun9i-core.c new file +6 -0
+     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.

Quoted 3 lines
Quoted 2 lines
drivers/clk/sunxi/clk-sun9i-core.c new file +2 -0
+
+     *freq = 6000000 * div;
Quoted 6 lines
Quoted 1 line

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.

Quoted 5 lines

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?

Quoted 224 lines
Quoted 224 lines
Quoted 223 lines
Quoted 210 lines
drivers/clk/sunxi/clk-sun9i-core.c new file +210 -0
+     /* 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,

drivers/clk/sunxi/clk-sun9i-core.c line 272

Quoted 10 lines
drivers/clk/sunxi/clk-sun9i-core.c new file +10 -0
+};
+
+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?

Quoted 7 lines
Quoted 4 lines

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

#7 lore raw

PATCH 2/5 clk: sunxi: Add support for A80 basic bus clocks

Quoted 151 lines · Chen-Yu Tsai
Quoted 149 lines · Maxime Ripard
Quoted 137 lines · Chen-Yu Tsai
Quoted 121 lines · Maxime Ripard
Quoted 120 lines · Chen-Yu Tsai

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.

---
 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
Documentation/devicetree/bindings/clock/sunxi.txt +5 -0
index ed116df..7f1c486 100644
@@ -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
drivers/clk/sunxi/Makefile +1 -0
index 7ddc2b5..a66953c 100644
@@ -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 \
drivers/clk/sunxi/clk-sun9i-core.c new file +43 -0
new file mode 100644
index 0000000..ba5f091
@@ -0,0 +1,272 @@
+/*
+ * Copyright 2014 Chen-Yu Tsai
+ *
+ * Chen-Yu Tsai <[email protected]>
+ *
+ * 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 */
Quoted 8 lines

drivers/clk/sunxi/clk-sun9i-core.c line 49

Quoted 6 lines
drivers/clk/sunxi/clk-sun9i-core.c new file +6 -0
+     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.

Quoted 3 lines
Quoted 2 lines
drivers/clk/sunxi/clk-sun9i-core.c new file +2 -0
+
+     *freq = 6000000 * div;
Quoted 6 lines
Quoted 1 line

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?

Quoted 8 lines
Quoted 1 line

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

Signature · 10 lines
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>
#8 lore raw

PATCH 3/5 clk: sunxi: Add support for bus clock gates on Allwinner A80 SoC

In reply to Chen-Yu Tsai

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

---
 Documentation/devicetree/bindings/clock/sunxi.txt |  5 ++++
 drivers/clk/sunxi/clk-sunxi.c                     | 31 +++++++++++++++++++++++
 2 files changed, 36 insertions(+)
Documentation/devicetree/bindings/clock/sunxi.txt +5 -0
index 7f1c486..0455cb9 100644
@@ -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
drivers/clk/sunxi/clk-sunxi.c +31 -0
index 636b8d7..20f47c6 100644
@@ -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);
Signature · 1 line
2.1.1
#9 lore raw

PATCH 4/5 ARM: sunxi: Select ARCH_HAS_RESET_CONTROLLER and RESET_CONTROLLER for sun9i

In reply to Chen-Yu Tsai

The A80 SoC has reset controls matching bus clock gates.

---
 arch/arm/mach-sunxi/Kconfig | 2 ++
 1 file changed, 2 insertions(+)
arch/arm/mach-sunxi/Kconfig +2 -0
index d04f84b..a77604f 100644
@@ -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
Signature · 1 line
2.1.1
#10 lore raw

PATCH 4/5 ARM: sunxi: Select ARCH_HAS_RESET_CONTROLLER and RESET_CONTROLLER for sun9i

Quoted 3 lines · Chen-Yu Tsai

The A80 SoC has reset controls matching bus clock gates.

Applied, thanks

Maxime

Signature · 10 lines
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>
#11 lore raw

PATCH 5/5 ARM: dts: sun9i: Add basic clocks and reset controls

In reply to Chen-Yu Tsai

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.

---
 arch/arm/boot/dts/sun9i-a80.dtsi | 177 +++++++++++++++++++++++++++++++++++++--
 1 file changed, 171 insertions(+), 6 deletions(-)
arch/arm/boot/dts/sun9i-a80.dtsi +171 -6
index 5e2ec4b..7bcab56 100644
@@ -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";
 		};
 
Signature · 1 line
2.1.1
#12 lore raw

cover clk: sunxi: Add peripheral bus clock support for A80

In reply to Chen-Yu Tsai

Hi ChenYu,

Quoted 5 lines · Chen-Yu Tsai

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

#13 lore raw

cover clk: sunxi: Add peripheral bus clock support for A80

Hi Hans,

Quoted 5 lines · Hans de Goede

Hi ChenYu,

Quoted 2 lines · Chen-Yu Tsai

Hi everyone,

Quoted 8 lines
Quoted 3 lines

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

#14 lore raw

cover clk: sunxi: Add peripheral bus clock support for A80

Quoted 17 lines · Chen-Yu Tsai

Hi Hans,

Quoted 5 lines · Hans de Goede

Hi ChenYu,

Quoted 2 lines · Chen-Yu Tsai

Hi everyone,

Quoted 8 lines
Quoted 3 lines

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 ?

Quoted 8 lines

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

#15 lore raw

cover clk: sunxi: Add peripheral bus clock support for A80

Quoted 22 lines · Simos Xenitellis
Quoted 21 lines · Chen-Yu Tsai

Hi Hans,

Quoted 5 lines · Hans de Goede

Hi ChenYu,

Quoted 2 lines · Chen-Yu Tsai

Hi everyone,

Quoted 8 lines
Quoted 3 lines

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

Quoted 8 lines
Quoted 4 lines

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