[PATCH 1/6] clk: sunxi: Let divs clocks read the base factor clock name from devicetree

2,445 views
Skip to first unread message

Jens Kuske

unread,
Oct 21, 2015, 12:13:36 PM10/21/15
to Maxime Ripard, Chen-Yu Tsai, Mike Turquette, Linus Walleij, Rob Herring, Philipp Zabel, Emilio López, Vishnu Patekar, Hans de Goede, devic...@vger.kernel.org, linux-ar...@lists.infradead.org, linux-...@vger.kernel.org, linux...@googlegroups.com, Jens Kuske
Currently, the sunxi clock driver gets the name for the base factor clock
of divs clocks from the name field in factors_data. This prevents reusing
of the factor clock for clocks with same properties, but different name.

This commit makes the divs setup function try to get a name from
clock-output-names in the devicetree. It also removes the name field where
possible and merges the sun4i PLL5 and PLL6 clocks.

Signed-off-by: Jens Kuske <jens...@gmail.com>
---
drivers/clk/sunxi/clk-sunxi.c | 39 ++++++++++++++++++++++++++++-----------
1 file changed, 28 insertions(+), 11 deletions(-)

diff --git a/drivers/clk/sunxi/clk-sunxi.c b/drivers/clk/sunxi/clk-sunxi.c
index 9c79af0c..7c4aee0 100644
--- a/drivers/clk/sunxi/clk-sunxi.c
+++ b/drivers/clk/sunxi/clk-sunxi.c
@@ -704,21 +704,12 @@ static const struct factors_data sun4i_pll5_data __initconst = {
.enable = 31,
.table = &sun4i_pll5_config,
.getter = sun4i_get_pll5_factors,
- .name = "pll5",
-};
-
-static const struct factors_data sun4i_pll6_data __initconst = {
- .enable = 31,
- .table = &sun4i_pll5_config,
- .getter = sun4i_get_pll5_factors,
- .name = "pll6",
};

static const struct factors_data sun6i_a31_pll6_data __initconst = {
.enable = 31,
.table = &sun6i_a31_pll6_config,
.getter = sun6i_a31_get_pll6_factors,
- .name = "pll6x2",
};

static const struct factors_data sun5i_a13_ahb_data __initconst = {
@@ -902,6 +893,7 @@ struct gates_data {

#define SUNXI_DIVS_MAX_QTY 4
#define SUNXI_DIVISOR_WIDTH 2
+#define SUNXI_DIVS_BASE_NAME_MAX_LEN 8

struct divs_data {
const struct factors_data *factors; /* data for the factor clock */
@@ -941,7 +933,7 @@ static const struct divs_data pll5_divs_data __initconst = {
};

static const struct divs_data pll6_divs_data __initconst = {
- .factors = &sun4i_pll6_data,
+ .factors = &sun4i_pll5_data,
.ndivs = 4,
.div = {
{ .shift = 0, .table = pll6_sata_tbl, .gate = 14 }, /* M, SATA */
@@ -983,6 +975,8 @@ static void __init sunxi_divs_clk_setup(struct device_node *node,
struct clk_gate *gate = NULL;
struct clk_fixed_factor *fix_factor;
struct clk_divider *divider;
+ struct factors_data factors = *data->factors;
+ char base_name[SUNXI_DIVS_BASE_NAME_MAX_LEN];
void __iomem *reg;
int ndivs = SUNXI_DIVS_MAX_QTY, i = 0;
int flags, clkflags;
@@ -991,8 +985,31 @@ static void __init sunxi_divs_clk_setup(struct device_node *node,
if (data->ndivs)
ndivs = data->ndivs;

+ /* Try to find a name for base factor clock */
+ for (i = 0; i < ndivs; i++) {
+ if (data->div[i].self) {
+ of_property_read_string_index(node, "clock-output-names",
+ i, &factors.name);
+ break;
+ }
+ }
+ /* If we don't have a .self clk use the first output-name up to '_' */
+ if (factors.name == NULL) {
+ of_property_read_string_index(node, "clock-output-names",
+ 0, &clk_name);
+
+ for (i = 0; i < SUNXI_DIVS_BASE_NAME_MAX_LEN - 1 &&
+ clk_name[i] != '_' &&
+ clk_name[i] != '\0'; i++) {
+ base_name[i] = clk_name[i];
+ }
+
+ base_name[i] = '\0';
+ factors.name = base_name;
+ }
+
/* Set up factor clock that we will be dividing */
- pclk = sunxi_factors_clk_setup(node, data->factors);
+ pclk = sunxi_factors_clk_setup(node, &factors);
parent = __clk_get_name(pclk);

reg = of_iomap(node, 0);
--
2.6.1

Jens Kuske

unread,
Oct 21, 2015, 12:13:36 PM10/21/15
to Maxime Ripard, Chen-Yu Tsai, Mike Turquette, Linus Walleij, Rob Herring, Philipp Zabel, Emilio López, Vishnu Patekar, Hans de Goede, devic...@vger.kernel.org, linux-ar...@lists.infradead.org, linux-...@vger.kernel.org, linux...@googlegroups.com, Jens Kuske
Hi everyone,

This is v3 of my patch series introducing basic kernel support for Allwinner's
H3 SoC. It mainly adds basic clocks and pinctrl. It also adds interrupts,
timers, watchdog, RTC, dmaengine, MMC and UARTs, which are mostly compatible
to those in earlier SoCs like A23 and A31, and can simply be reused.

These patches are based on Maxime's sunxi/for-next branch from
git://git.kernel.org/pub/scm/linux/kernel/git/mripard/linux.git


Patch 1 improves the sunxi divs clock to read the name of the base factor clock
from devicetree instead of hardcoding it, which allows us to reuse sun6i-pll6
for our pll8.

Patch 2 adds support for the basic clocks.

Patch 3 adds the pin sets for the H3 main PIO.

Patch 4 adds a new compatible for the H3 reset controller

Patch 5 adds the DTSI for the H3.

Patch 6 adds a DTS for the Orange Pi Plus SBC, which these patches
were developed and tested with.


Changes since v2:
- add mbus clock
- add Maxime's suggestion to take the substring up to the first "_" as name
for the divs base clock
- use A31 pll6 for H3 pll6
- use a clock similar to the new simple gates for H3 bus gates
- drop the pinctrl-as-module patch since pinctrl and gpio don't seem to be
ready for removable drivers
- documentation and machine support are merged already

Changes since v1:
- Update sunxi README in Documentation
- Add the multiple parents gates and use them for bus-gates instead of
ahb1, ahb2, apb1 and apb2 gates
- Merge the pll8 clock with sun6i pll6
- Merge the ahb12, apb1 and apb2 resets to bus-resets with own compatible
- Add sun6i_timer_init to sun8i machine
- Remove the single SoC names from machine definition, its sun8i family
- Make the pinctrl driver tristate and put its Kconfig entry in the right order
- Rename pinctrl "scr" to "sim" and clock "sim" to "scr" to match user manual
- Remove the address paragraph from GPL in dts and dtsi
- Some style cleanup and line wrapping in dtsi
- Add ARM architected timers
- dmaengine isn't included anymore, it is merged already

Best Regards,
Jens


Jens Kuske (6):
clk: sunxi: Let divs clocks read the base factor clock name from
devicetree
clk: sunxi: Add H3 clocks support
pinctrl: sunxi: Add H3 PIO controller support
reset: sunxi: Add compatible for Allwinner H3 bus resets
ARM: dts: sunxi: Add Allwinner H3 DTSI
ARM: dts: sun8i: Add Orange Pi Plus support

Documentation/devicetree/bindings/clock/sunxi.txt | 2 +
.../bindings/pinctrl/allwinner,sunxi-pinctrl.txt | 1 +
.../bindings/reset/allwinner,sunxi-clock-reset.txt | 1 +
arch/arm/boot/dts/Makefile | 3 +-
arch/arm/boot/dts/sun8i-h3-orangepi-plus.dts | 77 +++
arch/arm/boot/dts/sun8i-h3.dtsi | 499 ++++++++++++++++++++
drivers/clk/sunxi/Makefile | 1 +
drivers/clk/sunxi/clk-bus-gates.c | 105 +++++
drivers/clk/sunxi/clk-sunxi.c | 47 +-
drivers/pinctrl/sunxi/Kconfig | 4 +
drivers/pinctrl/sunxi/Makefile | 1 +
drivers/pinctrl/sunxi/pinctrl-sun8i-h3.c | 516 +++++++++++++++++++++
drivers/reset/reset-sunxi.c | 1 +
13 files changed, 1245 insertions(+), 13 deletions(-)
create mode 100644 arch/arm/boot/dts/sun8i-h3-orangepi-plus.dts
create mode 100644 arch/arm/boot/dts/sun8i-h3.dtsi
create mode 100644 drivers/clk/sunxi/clk-bus-gates.c
create mode 100644 drivers/pinctrl/sunxi/pinctrl-sun8i-h3.c

--
2.6.1

Jens Kuske

unread,
Oct 21, 2015, 12:13:40 PM10/21/15
to Maxime Ripard, Chen-Yu Tsai, Mike Turquette, Linus Walleij, Rob Herring, Philipp Zabel, Emilio López, Vishnu Patekar, Hans de Goede, devic...@vger.kernel.org, linux-ar...@lists.infradead.org, linux-...@vger.kernel.org, linux...@googlegroups.com, Jens Kuske
The H3 clock control unit is similar to the those of other sun8i family
members like the A23.

It adds a new bus gates clock similar to the simple gates, but with a
different parent clock for each single gate.
Some of the gates use the new AHB2 clock as parent, whose clock source
is muxable between AHB1 and PLL6/2. The documentation isn't totally clear
about which devices belong to AHB2 now, especially USB EHIC/OHIC, so it
is mostly based on Allwinner kernel source code.

Signed-off-by: Jens Kuske <jens...@gmail.com>
---
Documentation/devicetree/bindings/clock/sunxi.txt | 2 +
drivers/clk/sunxi/Makefile | 1 +
drivers/clk/sunxi/clk-bus-gates.c | 105 ++++++++++++++++++++++
drivers/clk/sunxi/clk-sunxi.c | 12 ++-
4 files changed, 117 insertions(+), 3 deletions(-)
create mode 100644 drivers/clk/sunxi/clk-bus-gates.c

diff --git a/Documentation/devicetree/bindings/clock/sunxi.txt b/Documentation/devicetree/bindings/clock/sunxi.txt
index 8a47b77..d303dec 100644
--- a/Documentation/devicetree/bindings/clock/sunxi.txt
+++ b/Documentation/devicetree/bindings/clock/sunxi.txt
@@ -28,6 +28,7 @@ Required properties:
"allwinner,sun7i-a20-ahb-gates-clk" - for the AHB gates on A20
"allwinner,sun6i-a31-ar100-clk" - for the AR100 on A31
"allwinner,sun6i-a31-ahb1-clk" - for the AHB1 clock on A31
+ "allwinner,sun8i-h3-ahb2-clk" - for the AHB2 clock on H3
"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
@@ -55,6 +56,7 @@ Required properties:
"allwinner,sun9i-a80-apb1-gates-clk" - for the APB1 gates on A80
"allwinner,sun6i-a31-apb2-gates-clk" - for the APB2 gates on A31
"allwinner,sun8i-a23-apb2-gates-clk" - for the APB2 gates on A23
+ "allwinner,sun8i-h3-bus-gates-clk" - for the bus gates on H3
"allwinner,sun5i-a13-mbus-clk" - for the MBUS clock on A13
"allwinner,sun4i-a10-mmc-clk" - for the MMC clock
"allwinner,sun9i-a80-mmc-clk" - for mmc module clocks on A80
diff --git a/drivers/clk/sunxi/Makefile b/drivers/clk/sunxi/Makefile
index f5a35b8..ecaff7f 100644
--- a/drivers/clk/sunxi/Makefile
+++ b/drivers/clk/sunxi/Makefile
@@ -5,6 +5,7 @@
obj-y += clk-sunxi.o clk-factors.o
obj-y += clk-a10-hosc.o
obj-y += clk-a20-gmac.o
+obj-y += clk-bus-gates.o
obj-y += clk-mod0.o
obj-y += clk-simple-gates.o
obj-y += clk-sun8i-mbus.o
diff --git a/drivers/clk/sunxi/clk-bus-gates.c b/drivers/clk/sunxi/clk-bus-gates.c
new file mode 100644
index 0000000..5bba0b9
--- /dev/null
+++ b/drivers/clk/sunxi/clk-bus-gates.c
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2015 Jens Kuske <jens...@gmail.com>
+ *
+ * Based on clk-simple-gates.c, which is:
+ * Copyright 2015 Maxime Ripard
+ *
+ * Maxime Ripard <maxime...@free-electrons.com>
+ *
+ * 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.h>
+#include <linux/clk-provider.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+
+static DEFINE_SPINLOCK(gates_lock);
+
+static void __init sunxi_bus_gates_setup(struct device_node *node,
+ const int protected[],
+ int nprotected)
+{
+ struct clk_onecell_data *clk_data;
+ const char *clk_parent, *clk_name;
+ struct property *prop;
+ struct resource res;
+ void __iomem *clk_reg;
+ void __iomem *reg;
+ const __be32 *p;
+ int number, i = 0, j;
+ u8 clk_bit;
+ u32 index;
+
+ reg = of_io_request_and_map(node, 0, of_node_full_name(node));
+ if (IS_ERR(reg))
+ return;
+
+ clk_data = kmalloc(sizeof(struct clk_onecell_data), GFP_KERNEL);
+ if (!clk_data)
+ goto err_unmap;
+
+ number = of_property_count_u32_elems(node, "clock-indices");
+ of_property_read_u32_index(node, "clock-indices", number - 1, &number);
+
+ clk_data->clks = kcalloc(number + 1, sizeof(struct clk *), GFP_KERNEL);
+ if (!clk_data->clks)
+ goto err_free_data;
+
+ of_property_for_each_u32(node, "clock-indices", prop, p, index) {
+ of_property_read_string_index(node, "clock-output-names",
+ i, &clk_name);
+
+ clk_parent = of_clk_get_parent_name(node, i);
+
+ clk_reg = reg + 4 * (index / 32);
+ clk_bit = index % 32;
+
+ clk_data->clks[index] = clk_register_gate(NULL, clk_name,
+ clk_parent, 0,
+ clk_reg,
+ clk_bit,
+ 0, &gates_lock);
+ i++;
+
+ if (IS_ERR(clk_data->clks[index])) {
+ WARN_ON(true);
+ continue;
+ }
+
+ for (j = 0; j < nprotected; j++)
+ if (protected[j] == index)
+ clk_prepare_enable(clk_data->clks[index]);
+
+ }
+
+ clk_data->clk_num = number + 1;
+ of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
+
+ return;
+
+err_free_data:
+ kfree(clk_data);
+err_unmap:
+ iounmap(reg);
+ of_address_to_resource(node, 0, &res);
+ release_mem_region(res.start, resource_size(&res));
+}
+
+static void __init sunxi_bus_gates_init(struct device_node *node)
+{
+ sunxi_bus_gates_setup(node, NULL, 0);
+}
+
+CLK_OF_DECLARE(sun8i_h3_bus_gates, "allwinner,sun8i-h3-bus-gates-clk",
+ sunxi_bus_gates_init);
diff --git a/drivers/clk/sunxi/clk-sunxi.c b/drivers/clk/sunxi/clk-sunxi.c
index 7c4aee0..6293c65 100644
--- a/drivers/clk/sunxi/clk-sunxi.c
+++ b/drivers/clk/sunxi/clk-sunxi.c
@@ -769,6 +769,10 @@ static const struct mux_data sun6i_a31_ahb1_mux_data __initconst = {
.shift = 12,
};

+static const struct mux_data sun8i_h3_ahb2_mux_data __initconst = {
+ .shift = 0,
+};
+
static void __init sunxi_mux_clk_setup(struct device_node *node,
struct mux_data *data)
{
@@ -945,10 +949,11 @@ static const struct divs_data pll6_divs_data __initconst = {

static const struct divs_data sun6i_a31_pll6_divs_data __initconst = {
.factors = &sun6i_a31_pll6_data,
- .ndivs = 2,
+ .ndivs = 3,
.div = {
{ .fixed = 2 }, /* normal output */
{ .self = 1 }, /* base factor clock, 2x */
+ { .fixed = 4 }, /* divided output, /2 */
}
};

@@ -1000,9 +1005,8 @@ static void __init sunxi_divs_clk_setup(struct device_node *node,

for (i = 0; i < SUNXI_DIVS_BASE_NAME_MAX_LEN - 1 &&
clk_name[i] != '_' &&
- clk_name[i] != '\0'; i++) {
+ clk_name[i] != '\0'; i++)
base_name[i] = clk_name[i];
- }

base_name[i] = '\0';
factors.name = base_name;
@@ -1147,6 +1151,7 @@ static const struct of_device_id clk_divs_match[] __initconst = {
static const struct of_device_id clk_mux_match[] __initconst = {
{.compatible = "allwinner,sun4i-a10-cpu-clk", .data = &sun4i_cpu_mux_data,},
{.compatible = "allwinner,sun6i-a31-ahb1-mux-clk", .data = &sun6i_a31_ahb1_mux_data,},
+ {.compatible = "allwinner,sun8i-h3-ahb2-clk", .data = &sun8i_h3_ahb2_mux_data,},
{}
};

@@ -1229,6 +1234,7 @@ CLK_OF_DECLARE(sun6i_a31_clk_init, "allwinner,sun6i-a31", sun6i_init_clocks);
CLK_OF_DECLARE(sun6i_a31s_clk_init, "allwinner,sun6i-a31s", sun6i_init_clocks);
CLK_OF_DECLARE(sun8i_a23_clk_init, "allwinner,sun8i-a23", sun6i_init_clocks);
CLK_OF_DECLARE(sun8i_a33_clk_init, "allwinner,sun8i-a33", sun6i_init_clocks);
+CLK_OF_DECLARE(sun8i_h3_clk_init, "allwinner,sun8i-h3", sun6i_init_clocks);

static void __init sun9i_init_clocks(struct device_node *node)
{
--
2.6.1

Code Kipper

unread,
Oct 21, 2015, 1:11:09 PM10/21/15
to jens...@gmail.com, linux-sunxi
On 21 October 2015 at 18:13, Jens Kuske <jens...@gmail.com> wrote:
> Hi everyone,
>
> This is v3 of my patch series introducing basic kernel support for Allwinner's
> H3 SoC. It mainly adds basic clocks and pinctrl. It also adds interrupts,
> timers, watchdog, RTC, dmaengine, MMC and UARTs, which are mostly compatible
> to those in earlier SoCs like A23 and A31, and can simply be reused.
>
> These patches are based on Maxime's sunxi/for-next branch from
> git://git.kernel.org/pub/scm/linux/kernel/git/mripard/linux.git

Thanks for the update...just seconds ago managed to get some chatter
after the "Starting Kernel" prompt on my Orange Pi 2 using the patch
from http://moinejf.free.fr/opi2/ but I will switch over to these new
ones to verify. I'm also using your u-boot so there has been some
progress in the Kipper household this evening.

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

Code Kipper

unread,
Oct 21, 2015, 1:34:31 PM10/21/15
to jens...@gmail.com, linux-sunxi
On 21 October 2015 at 19:11, Code Kipper <codek...@gmail.com> wrote:
> On 21 October 2015 at 18:13, Jens Kuske <jens...@gmail.com> wrote:
>> Hi everyone,
>>
>> This is v3 of my patch series introducing basic kernel support for Allwinner's
>> H3 SoC. It mainly adds basic clocks and pinctrl. It also adds interrupts,
>> timers, watchdog, RTC, dmaengine, MMC and UARTs, which are mostly compatible
>> to those in earlier SoCs like A23 and A31, and can simply be reused.
>>
>> These patches are based on Maxime's sunxi/for-next branch from
>> git://git.kernel.org/pub/scm/linux/kernel/git/mripard/linux.git
>
> Thanks for the update...just seconds ago managed to get some chatter
> after the "Starting Kernel" prompt on my Orange Pi 2 using the patch
> from http://moinejf.free.fr/opi2/ but I will switch over to these new
> ones to verify. I'm also using your u-boot so there has been some
> progress in the Kipper household this evening.
>
> Thanks again,
> CK
Coool....it's booting...now to find me a rootfs!

Hans de Goede

unread,
Oct 21, 2015, 3:19:03 PM10/21/15
to Jens Kuske, Maxime Ripard, Chen-Yu Tsai, Mike Turquette, Linus Walleij, Rob Herring, Philipp Zabel, Emilio López, Vishnu Patekar, devic...@vger.kernel.org, linux-ar...@lists.infradead.org, linux-...@vger.kernel.org, linux...@googlegroups.com, Reinder E.N. de Haan, zhao_...@263.net
Hi Jens,

On 21-10-15 18:13, Jens Kuske wrote:
> Hi everyone,
>
> This is v3 of my patch series introducing basic kernel support for Allwinner's
> H3 SoC. It mainly adds basic clocks and pinctrl. It also adds interrupts,
> timers, watchdog, RTC, dmaengine, MMC and UARTs, which are mostly compatible
> to those in earlier SoCs like A23 and A31, and can simply be reused.
>
> These patches are based on Maxime's sunxi/for-next branch from
> git://git.kernel.org/pub/scm/linux/kernel/git/mripard/linux.git
>
>
> Patch 1 improves the sunxi divs clock to read the name of the base factor clock
> from devicetree instead of hardcoding it, which allows us to reuse sun6i-pll6
> for our pll8.
>
> Patch 2 adds support for the basic clocks.
>
> Patch 3 adds the pin sets for the H3 main PIO.
>
> Patch 4 adds a new compatible for the H3 reset controller
>
> Patch 5 adds the DTSI for the H3.
>
> Patch 6 adds a DTS for the Orange Pi Plus SBC, which these patches
> were developed and tested with.

Great to see that you've started working on this again. Last weekend I
ended up working on this too together with Reinder E.N. de Haan <rei...@mveas.com>
(added to the Cc).

We took a slightly different approach for the gates clocks, see:

https://github.com/jwrdegoede/linux-sunxi/commits/sunxi-wip

And specifically:

https://github.com/jwrdegoede/linux-sunxi/commit/80a1afe319d5d1a0c426d42e75d37f0c64e8ea0b

Combined with:

https://github.com/jwrdegoede/linux-sunxi/commit/d508da5feb5048f6674d6b24b58ac9058fb9d877

This deals with the per gate parents the same way the rockchip
clock code does, and it seems to be quite a bit less code then your solution.

So now we've two solutions to chose from :) Since you seem to be back to
working on this I'll refrain from doing any further work, at least
without coordinating. Maxime, can you let us know which solution for the
gates clock parents is best, or tell us if you think both solutions are
no good :)

(I wanted to get in touch with you about the work done this weekend,
but your posting of this v3 has sorta pre-empted that).

Other then the slightly different solution for the gates, the code in my tree
is a straight forward port of your v2.

Thanks for your work on this!

Regards,

Hans


p.s.

I'm teaching a kernel driver course at my local hackerspace in the netherlands:

https://revspace.nl/KernelDriverProgrammingCourse2015

Which is where our work on this this weekend originated. The next planned
course day is November 1st and I expect Reinder to be working on the H3
again then. I think the plan was to tackle USB next. Reinder can you confirm
this ? If you (Jens) want to work on USB before then, that is fine, but please
coordinate their is plenty to do, so no need for us to be doing (more) double
work.

Hans de Goede

unread,
Oct 21, 2015, 3:24:05 PM10/21/15
to Jens Kuske, Maxime Ripard, Chen-Yu Tsai, Mike Turquette, Linus Walleij, Rob Herring, Philipp Zabel, Emilio López, Vishnu Patekar, devic...@vger.kernel.org, linux-ar...@lists.infradead.org, linux-...@vger.kernel.org, linux...@googlegroups.com
Hi,

On 21-10-15 18:13, Jens Kuske wrote:
> Hi everyone,
>
> This is v3 of my patch series introducing basic kernel support for Allwinner's
> H3 SoC. It mainly adds basic clocks and pinctrl. It also adds interrupts,
> timers, watchdog, RTC, dmaengine, MMC and UARTs, which are mostly compatible
> to those in earlier SoCs like A23 and A31, and can simply be reused.
>
> These patches are based on Maxime's sunxi/for-next branch from
> git://git.kernel.org/pub/scm/linux/kernel/git/mripard/linux.git

p.s.

For the next version you will want to base these on the sunxi-next branch of:

https://github.com/linux-sunxi/linux-sunxi.git

There is at least a conflict with the pio driver due to the addition of
the a83 pio driver which mripard/linux/sunxi/for-next does not have, where
as linux-sunxi/sunxi-next does have that merged in.

Regards,

Hans

Julian Calaby

unread,
Oct 21, 2015, 8:16:02 PM10/21/15
to jens...@gmail.com, Maxime Ripard, Chen-Yu Tsai, Mike Turquette, Linus Walleij, Rob Herring, Philipp Zabel, Emilio López, Vishnu Patekar, Hans de Goede, devicetree, Mailing List, Arm, linux-...@vger.kernel.org, linux-sunxi
Hi Jens,

On Thu, Oct 22, 2015 at 3:13 AM, Jens Kuske <jens...@gmail.com> wrote:
> The H3 clock control unit is similar to the those of other sun8i family
> members like the A23.
>
> It adds a new bus gates clock similar to the simple gates, but with a
> different parent clock for each single gate.
> Some of the gates use the new AHB2 clock as parent, whose clock source
> is muxable between AHB1 and PLL6/2. The documentation isn't totally clear
> about which devices belong to AHB2 now, especially USB EHIC/OHIC, so it
> is mostly based on Allwinner kernel source code.
>
> Signed-off-by: Jens Kuske <jens...@gmail.com>
> ---
> Documentation/devicetree/bindings/clock/sunxi.txt | 2 +
> drivers/clk/sunxi/Makefile | 1 +
> drivers/clk/sunxi/clk-bus-gates.c | 105 ++++++++++++++++++++++
> drivers/clk/sunxi/clk-sunxi.c | 12 ++-
> 4 files changed, 117 insertions(+), 3 deletions(-)
> create mode 100644 drivers/clk/sunxi/clk-bus-gates.c
>
> diff --git a/drivers/clk/sunxi/clk-sunxi.c b/drivers/clk/sunxi/clk-sunxi.c
> index 7c4aee0..6293c65 100644
> --- a/drivers/clk/sunxi/clk-sunxi.c
> +++ b/drivers/clk/sunxi/clk-sunxi.c

This hunk should be in patch 1:

> @@ -1000,9 +1005,8 @@ static void __init sunxi_divs_clk_setup(struct device_node *node,
>
> for (i = 0; i < SUNXI_DIVS_BASE_NAME_MAX_LEN - 1 &&
> clk_name[i] != '_' &&
> - clk_name[i] != '\0'; i++) {
> + clk_name[i] != '\0'; i++)
> base_name[i] = clk_name[i];
> - }
>
> base_name[i] = '\0';
> factors.name = base_name;

Thanks,

--
Julian Calaby

Email: julian...@gmail.com
Profile: http://www.google.com/profiles/julian.calaby/

Jens Kuske

unread,
Oct 22, 2015, 3:49:21 AM10/22/15
to Hans de Goede, Maxime Ripard, Chen-Yu Tsai, Linus Walleij, Rob Herring, Philipp Zabel, Emilio López, Vishnu Patekar, devic...@vger.kernel.org, linux-ar...@lists.infradead.org, linux-...@vger.kernel.org, linux...@googlegroups.com, Reinder E.N. de Haan, zhao_...@263.net
Hi,

On 21/10/15 21:18, Hans de Goede wrote:
>
> Great to see that you've started working on this again. Last weekend I
> ended up working on this too together with Reinder E.N. de Haan <rei...@mveas.com>
> (added to the Cc).
>
> We took a slightly different approach for the gates clocks, see:
>
> https://github.com/jwrdegoede/linux-sunxi/commits/sunxi-wip
>
> And specifically:
>
> https://github.com/jwrdegoede/linux-sunxi/commit/80a1afe319d5d1a0c426d42e75d37f0c64e8ea0b
>
> Combined with:
>
> https://github.com/jwrdegoede/linux-sunxi/commit/d508da5feb5048f6674d6b24b58ac9058fb9d877
>
> This deals with the per gate parents the same way the rockchip
> clock code does, and it seems to be quite a bit less code then your solution.
>
> So now we've two solutions to chose from :) Since you seem to be back to
> working on this I'll refrain from doing any further work, at least
> without coordinating. Maxime, can you let us know which solution for the
> gates clock parents is best, or tell us if you think both solutions are
> no good :)

I'd actually prefer your solution. I duplicated the simple-gates code
when trying a different approach and never revisited that decision.

>
> (I wanted to get in touch with you about the work done this weekend,
> but your posting of this v3 has sorta pre-empted that).
>
> Other then the slightly different solution for the gates, the code in my tree
> is a straight forward port of your v2.
>
> Thanks for your work on this!
>
> Regards,
>
> Hans
>
>
> p.s.
>
> I'm teaching a kernel driver course at my local hackerspace in the netherlands:
>
> https://revspace.nl/KernelDriverProgrammingCourse2015
>
> Which is where our work on this this weekend originated. The next planned
> course day is November 1st and I expect Reinder to be working on the H3
> again then. I think the plan was to tackle USB next. Reinder can you confirm
> this ? If you (Jens) want to work on USB before then, that is fine, but please
> coordinate their is plenty to do, so no need for us to be doing (more) double
> work.
>

I don't plan to work on USB soon, my next step would have been Ethernet
and finishing the basic u-boot support. You know my u-boot H3 wip tree I
hope? Before we duplicate our work there too...
https://github.com/jemk/u-boot-sunxi/tree/sunxi/h3

Jens

Jens Kuske

unread,
Oct 22, 2015, 3:49:43 AM10/22/15
to Julian Calaby, Maxime Ripard, Chen-Yu Tsai, Linus Walleij, Rob Herring, Philipp Zabel, Emilio López, Vishnu Patekar, Hans de Goede, devicetree, Mailing List, Arm, linux-...@vger.kernel.org, linux-sunxi

On 22/10/15 02:15, Julian Calaby wrote:
>
> This hunk should be in patch 1:

Indeed, Thanks.

Jens

Jean-Francois Moine

unread,
Oct 22, 2015, 4:31:44 AM10/22/15
to Hans de Goede, Jens Kuske, Maxime Ripard, Chen-Yu Tsai, Mike Turquette, Linus Walleij, Rob Herring, Philipp Zabel, Emilio López, devic...@vger.kernel.org, Vishnu Patekar, Reinder E.N. de Haan, linux-...@vger.kernel.org, linux...@googlegroups.com, linux-ar...@lists.infradead.org, zhao_...@263.net
On Wed, 21 Oct 2015 21:18:45 +0200
Hans de Goede <hdeg...@redhat.com> wrote:

> Great to see that you've started working on this again. Last weekend I
> ended up working on this too together with Reinder E.N. de Haan <rei...@mveas.com>
> (added to the Cc).
>
> We took a slightly different approach for the gates clocks, see:
>
> https://github.com/jwrdegoede/linux-sunxi/commits/sunxi-wip
>
> And specifically:
>
> https://github.com/jwrdegoede/linux-sunxi/commit/80a1afe319d5d1a0c426d42e75d37f0c64e8ea0b
>
> Combined with:
>
> https://github.com/jwrdegoede/linux-sunxi/commit/d508da5feb5048f6674d6b24b58ac9058fb9d877
>
> This deals with the per gate parents the same way the rockchip
> clock code does, and it seems to be quite a bit less code then your solution.

Here is a simpler patch:

diff --git a/drivers/clk/sunxi/clk-simple-gates.c b/drivers/clk/sunxi/clk-simple-gates.c
index 6ce9118..8fecaeab 100644
--- a/drivers/clk/sunxi/clk-simple-gates.c
+++ b/drivers/clk/sunxi/clk-simple-gates.c
@@ -35,6 +35,7 @@ static void __init sunxi_simple_gates_setup(struct device_node *node,
void __iomem *reg;
const __be32 *p;
int number, i = 0, j;
+ bool parent_per_gate;
u8 clk_bit;
u32 index;

@@ -43,6 +44,7 @@ static void __init sunxi_simple_gates_setup(struct device_node *node,
return;

clk_parent = of_clk_get_parent_name(node, 0);
+ parent_per_gate = of_clk_get_parent_count(node) != 1;

clk_data = kmalloc(sizeof(struct clk_onecell_data), GFP_KERNEL);
if (!clk_data)
@@ -58,6 +60,8 @@ static void __init sunxi_simple_gates_setup(struct device_node *node,
of_property_for_each_u32(node, "clock-indices", prop, p, index) {
of_property_read_string_index(node, "clock-output-names",
i, &clk_name);
+ if (parent_per_gate)
+ clk_parent = of_clk_get_parent_name(node, i);

clk_reg = reg + 4 * (index / 32);
clk_bit = index % 32;


--
Ken ar c'hentañ | ** Breizh ha Linux atav! **
Jef | http://moinejf.free.fr/

Hans de Goede

unread,
Oct 22, 2015, 4:49:25 AM10/22/15
to Jens Kuske, Maxime Ripard, Chen-Yu Tsai, Linus Walleij, Rob Herring, Philipp Zabel, Emilio López, Vishnu Patekar, devic...@vger.kernel.org, linux-ar...@lists.infradead.org, linux-...@vger.kernel.org, linux...@googlegroups.com, Reinder E.N. de Haan, zhao_...@263.net
Hi,

On 22-10-15 09:49, Jens Kuske wrote:
> Hi,
>
> On 21/10/15 21:18, Hans de Goede wrote:
>>
>> Great to see that you've started working on this again. Last weekend I
>> ended up working on this too together with Reinder E.N. de Haan <rei...@mveas.com>
>> (added to the Cc).
>>
>> We took a slightly different approach for the gates clocks, see:
>>
>> https://github.com/jwrdegoede/linux-sunxi/commits/sunxi-wip
>>
>> And specifically:
>>
>> https://github.com/jwrdegoede/linux-sunxi/commit/80a1afe319d5d1a0c426d42e75d37f0c64e8ea0b
>>
>> Combined with:
>>
>> https://github.com/jwrdegoede/linux-sunxi/commit/d508da5feb5048f6674d6b24b58ac9058fb9d877
>>
>> This deals with the per gate parents the same way the rockchip
>> clock code does, and it seems to be quite a bit less code then your solution.
>>
>> So now we've two solutions to chose from :) Since you seem to be back to
>> working on this I'll refrain from doing any further work, at least
>> without coordinating. Maxime, can you let us know which solution for the
>> gates clock parents is best, or tell us if you think both solutions are
>> no good :)
>
> I'd actually prefer your solution. I duplicated the simple-gates code
> when trying a different approach and never revisited that decision.

Ok, note then when you switch to my solution (or the improved version of it
or the improved version Jean-Francois Moine suggests) the dtsi now has a list
of clocks with one per gate, rather then clock indices. You can save yourself
some time by taking that list from the dtsi patch in my tree, rather then
building it yourself manually.

>> (I wanted to get in touch with you about the work done this weekend,
>> but your posting of this v3 has sorta pre-empted that).
>>
>> Other then the slightly different solution for the gates, the code in my tree
>> is a straight forward port of your v2.
>>
>> Thanks for your work on this!
>>
>> Regards,
>>
>> Hans
>>
>>
>> p.s.
>>
>> I'm teaching a kernel driver course at my local hackerspace in the netherlands:
>>
>> https://revspace.nl/KernelDriverProgrammingCourse2015
>>
>> Which is where our work on this this weekend originated. The next planned
>> course day is November 1st and I expect Reinder to be working on the H3
>> again then. I think the plan was to tackle USB next. Reinder can you confirm
>> this ? If you (Jens) want to work on USB before then, that is fine, but please
>> coordinate their is plenty to do, so no need for us to be doing (more) double
>> work.
>>
>
> I don't plan to work on USB soon, my next step would have been Ethernet
> and finishing the basic u-boot support. You know my u-boot H3 wip tree I
> hope? Before we duplicate our work there too...
> https://github.com/jemk/u-boot-sunxi/tree/sunxi/h3

I was not aware of that work, at a first glance it looks good. Can you rebase
this on top of current u-boot/master (or v2015.10) and then submit it upstream ?

2 questions which come to mind immediately:

1) Where does the dram init logic come from, AFAIK Allwinner has not provided
any H3 dram init code ?

2) I see no pmic code in there. I know these boards do not use an axp pmic,
but according to my info at least the Orange Pi 2 (which I have) uses a
sy8106a pmic, it is not entirely clear to me yet if this one needs any
init though, I've mailed the Orange Pi people about this.

Regards,

Hans



Hans de Goede

unread,
Oct 22, 2015, 5:08:50 AM10/22/15
to Jean-Francois Moine, Jens Kuske, Maxime Ripard, Chen-Yu Tsai, Mike Turquette, Linus Walleij, Rob Herring, Philipp Zabel, Emilio López, devic...@vger.kernel.org, Vishnu Patekar, Reinder E.N. de Haan, linux-...@vger.kernel.org, linux...@googlegroups.com, linux-ar...@lists.infradead.org, zhao_...@263.net
Hi,
Yes good one, doing things that way indeed is better.

Regards,

Hans

Jens Kuske

unread,
Oct 22, 2015, 7:52:45 AM10/22/15
to Hans de Goede, Maxime Ripard, Chen-Yu Tsai, Emilio López, Vishnu Patekar, linux...@googlegroups.com, Reinder E.N. de Haan, zhao_...@263.net

On 22/10/15 10:49, Hans de Goede wrote:
> Hi,
>
> On 22-10-15 09:49, Jens Kuske wrote:
[..]
>>
>> I don't plan to work on USB soon, my next step would have been Ethernet
>> and finishing the basic u-boot support. You know my u-boot H3 wip tree I
>> hope? Before we duplicate our work there too...
>> https://github.com/jemk/u-boot-sunxi/tree/sunxi/h3
>
> I was not aware of that work, at a first glance it looks good. Can you rebase
> this on top of current u-boot/master (or v2015.10) and then submit it upstream ?

I will, after fixing some more things (like your question 2).

>
> 2 questions which come to mind immediately:
>
> 1) Where does the dram init logic come from, AFAIK Allwinner has not provided
> any H3 dram init code ?

It's from the Draco H3 TV Stick SDK:

http://www.cnx-software.com/2015/06/14/tronsmart-draco-h3-tv-stick-firmware-and-sdk-released/

>
> 2) I see no pmic code in there. I know these boards do not use an axp pmic,
> but according to my info at least the Orange Pi 2 (which I have) uses a
> sy8106a pmic, it is not entirely clear to me yet if this one needs any
> init though, I've mailed the Orange Pi people about this.

Correct, the CPU voltage is provided by a i2c controllable regulator (sy8106a)
without any datasheet. I've found how to set the voltage in above SDK, but I
first want test this carefully.

There's also the problem that we have to use the OpenRISC core for power
management (especially poweroff), since there is no external PMIC. This can
be done later of course, but we should think about how to do it.

Jens

Jens Kuske

unread,
Oct 27, 2015, 12:50:44 PM10/27/15
to Maxime Ripard, Chen-Yu Tsai, Michael Turquette, Linus Walleij, Rob Herring, Philipp Zabel, Emilio López, Vishnu Patekar, Hans de Goede, devic...@vger.kernel.org, linux-ar...@lists.infradead.org, linux-...@vger.kernel.org, linux...@googlegroups.com, Jens Kuske
Hi everyone,

This is v4 of my patch series introducing basic kernel support for Allwinner's
H3 SoC. It mainly adds basic clocks, resets and pinctrl. It also adds
interrupts, timers, watchdog, RTC, dmaengine, MMC and UARTs, which are mostly
compatible to those in earlier SoCs like A23 and A31, and can simply be reused.

These patches are based on the sunxi-next branch from
git://github.com/linux-sunxi/linux-sunxi.git


Patch 1 improves the sunxi divs clock to read the name of the base factor clock
from devicetree instead of hardcoding it, which allows us to reuse sun6i-pll6
for our pll8.

Patch 2 adds support for the basic clocks.

Patch 3 adds the pin sets for the H3 main PIO.

Patch 4 adds the H3 reset controller

Patch 5 adds the DTSI for the H3.

Patch 6 adds a DTS for the Orange Pi Plus SBC, which these patches
were developed and tested with.


Changes since v3:
- add a clock driver specific to the bus gates instead of listing parents in
the DTSI
- skip the holes in the reset controller with of_xlate()
reset: sunxi: Add Allwinner H3 bus resets
ARM: dts: sunxi: Add Allwinner H3 DTSI
ARM: dts: sun8i: Add Orange Pi Plus support

Documentation/devicetree/bindings/clock/sunxi.txt | 2 +
.../bindings/pinctrl/allwinner,sunxi-pinctrl.txt | 1 +
.../bindings/reset/allwinner,sunxi-clock-reset.txt | 1 +
arch/arm/boot/dts/Makefile | 3 +-
arch/arm/boot/dts/sun8i-h3-orangepi-plus.dts | 77 +++
arch/arm/boot/dts/sun8i-h3.dtsi | 482 +++++++++++++++++++
drivers/clk/sunxi/Makefile | 1 +
drivers/clk/sunxi/clk-sun8i-bus-gates.c | 111 +++++
drivers/clk/sunxi/clk-sunxi.c | 47 +-
drivers/pinctrl/sunxi/Kconfig | 4 +
drivers/pinctrl/sunxi/Makefile | 1 +
drivers/pinctrl/sunxi/pinctrl-sun8i-h3.c | 516 +++++++++++++++++++++
drivers/reset/reset-sunxi.c | 30 +-
13 files changed, 1260 insertions(+), 16 deletions(-)
create mode 100644 arch/arm/boot/dts/sun8i-h3-orangepi-plus.dts
create mode 100644 arch/arm/boot/dts/sun8i-h3.dtsi
create mode 100644 drivers/clk/sunxi/clk-sun8i-bus-gates.c
create mode 100644 drivers/pinctrl/sunxi/pinctrl-sun8i-h3.c

--
2.6.2

Jens Kuske

unread,
Oct 27, 2015, 12:50:44 PM10/27/15
to Maxime Ripard, Chen-Yu Tsai, Michael Turquette, Linus Walleij, Rob Herring, Philipp Zabel, Emilio López, Vishnu Patekar, Hans de Goede, devic...@vger.kernel.org, linux-ar...@lists.infradead.org, linux-...@vger.kernel.org, linux...@googlegroups.com, Jens Kuske
Currently, the sunxi clock driver gets the name for the base factor clock
of divs clocks from the name field in factors_data. This prevents reusing
of the factor clock for clocks with same properties, but different name.

This commit makes the divs setup function try to get a name from
clock-output-names in the devicetree. It also removes the name field where
possible and merges the sun4i PLL5 and PLL6 clocks.

Signed-off-by: Jens Kuske <jens...@gmail.com>
---
drivers/clk/sunxi/clk-sunxi.c | 38 +++++++++++++++++++++++++++-----------
1 file changed, 27 insertions(+), 11 deletions(-)

diff --git a/drivers/clk/sunxi/clk-sunxi.c b/drivers/clk/sunxi/clk-sunxi.c
index 9c79af0c..270de42 100644
--- a/drivers/clk/sunxi/clk-sunxi.c
+++ b/drivers/clk/sunxi/clk-sunxi.c
@@ -991,8 +985,30 @@ static void __init sunxi_divs_clk_setup(struct device_node *node,
if (data->ndivs)
ndivs = data->ndivs;

+ /* Try to find a name for base factor clock */
+ for (i = 0; i < ndivs; i++) {
+ if (data->div[i].self) {
+ of_property_read_string_index(node, "clock-output-names",
+ i, &factors.name);
+ break;
+ }
+ }
+ /* If we don't have a .self clk use the first output-name up to '_' */
+ if (factors.name == NULL) {
+ of_property_read_string_index(node, "clock-output-names",
+ 0, &clk_name);
+
+ for (i = 0; i < SUNXI_DIVS_BASE_NAME_MAX_LEN - 1 &&
+ clk_name[i] != '_' &&
+ clk_name[i] != '\0'; i++)
+ base_name[i] = clk_name[i];
+
+ base_name[i] = '\0';
+ factors.name = base_name;
+ }
+
/* Set up factor clock that we will be dividing */
- pclk = sunxi_factors_clk_setup(node, data->factors);
+ pclk = sunxi_factors_clk_setup(node, &factors);
parent = __clk_get_name(pclk);

reg = of_iomap(node, 0);
--
2.6.2

Jens Kuske

unread,
Oct 27, 2015, 12:50:45 PM10/27/15
to Maxime Ripard, Chen-Yu Tsai, Michael Turquette, Linus Walleij, Rob Herring, Philipp Zabel, Emilio López, Vishnu Patekar, Hans de Goede, devic...@vger.kernel.org, linux-ar...@lists.infradead.org, linux-...@vger.kernel.org, linux...@googlegroups.com, Jens Kuske
The H3 clock control unit is similar to the those of other sun8i family
members like the A23.

It adds a new bus gates clock similar to the simple gates, but with a
different parent clock for each single gate.
Some of the gates use the new AHB2 clock as parent, whose clock source
is muxable between AHB1 and PLL6/2. The documentation isn't totally clear
about which devices belong to AHB2 now, especially USB EHIC/OHIC, so it
is mostly based on Allwinner kernel source code.

Signed-off-by: Jens Kuske <jens...@gmail.com>
---
Documentation/devicetree/bindings/clock/sunxi.txt | 2 +
drivers/clk/sunxi/Makefile | 1 +
drivers/clk/sunxi/clk-sun8i-bus-gates.c | 111 ++++++++++++++++++++++
drivers/clk/sunxi/clk-sunxi.c | 9 +-
4 files changed, 122 insertions(+), 1 deletion(-)
create mode 100644 drivers/clk/sunxi/clk-sun8i-bus-gates.c

diff --git a/Documentation/devicetree/bindings/clock/sunxi.txt b/Documentation/devicetree/bindings/clock/sunxi.txt
index 8a47b77..d303dec 100644
--- a/Documentation/devicetree/bindings/clock/sunxi.txt
+++ b/Documentation/devicetree/bindings/clock/sunxi.txt
@@ -28,6 +28,7 @@ Required properties:
"allwinner,sun7i-a20-ahb-gates-clk" - for the AHB gates on A20
"allwinner,sun6i-a31-ar100-clk" - for the AR100 on A31
"allwinner,sun6i-a31-ahb1-clk" - for the AHB1 clock on A31
+ "allwinner,sun8i-h3-ahb2-clk" - for the AHB2 clock on H3
"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
@@ -55,6 +56,7 @@ Required properties:
"allwinner,sun9i-a80-apb1-gates-clk" - for the APB1 gates on A80
"allwinner,sun6i-a31-apb2-gates-clk" - for the APB2 gates on A31
"allwinner,sun8i-a23-apb2-gates-clk" - for the APB2 gates on A23
+ "allwinner,sun8i-h3-bus-gates-clk" - for the bus gates on H3
"allwinner,sun5i-a13-mbus-clk" - for the MBUS clock on A13
"allwinner,sun4i-a10-mmc-clk" - for the MMC clock
"allwinner,sun9i-a80-mmc-clk" - for mmc module clocks on A80
diff --git a/drivers/clk/sunxi/Makefile b/drivers/clk/sunxi/Makefile
index cb4c299..f520af6 100644
--- a/drivers/clk/sunxi/Makefile
+++ b/drivers/clk/sunxi/Makefile
@@ -10,6 +10,7 @@ obj-y += clk-a10-pll2.o
obj-y += clk-a20-gmac.o
obj-y += clk-mod0.o
obj-y += clk-simple-gates.o
+obj-y += clk-sun8i-bus-gates.o
obj-y += clk-sun8i-mbus.o
obj-y += clk-sun9i-core.o
obj-y += clk-sun9i-mmc.o
diff --git a/drivers/clk/sunxi/clk-sun8i-bus-gates.c b/drivers/clk/sunxi/clk-sun8i-bus-gates.c
new file mode 100644
index 0000000..ad605fa
--- /dev/null
+++ b/drivers/clk/sunxi/clk-sun8i-bus-gates.c
@@ -0,0 +1,111 @@
+static void __init sun8i_h3_bus_gates_init(struct device_node *node)
+{
+ const char *clocks[] = { "ahb1", "ahb2", "apb1", "apb2" };
+ enum { AHB1, AHB2, APB1, APB2 } clk_parent;
+ struct clk_onecell_data *clk_data;
+ const char *clk_name;
+ struct property *prop;
+ struct resource res;
+ void __iomem *clk_reg;
+ void __iomem *reg;
+ const __be32 *p;
+ int number, i;
+ u8 clk_bit;
+ u32 index;
+
+ reg = of_io_request_and_map(node, 0, of_node_full_name(node));
+ if (IS_ERR(reg))
+ return;
+
+ for (i = 0; i < ARRAY_SIZE(clocks); i++) {
+ index = of_property_match_string(node, "clock-names", clocks[i]);
+ if (index < 0)
+ return;
+
+ clocks[i] = of_clk_get_parent_name(node, index);
+ }
+
+ clk_data = kmalloc(sizeof(struct clk_onecell_data), GFP_KERNEL);
+ if (!clk_data)
+ goto err_unmap;
+
+ number = of_property_count_u32_elems(node, "clock-indices");
+ of_property_read_u32_index(node, "clock-indices", number - 1, &number);
+
+ clk_data->clks = kcalloc(number + 1, sizeof(struct clk *), GFP_KERNEL);
+ if (!clk_data->clks)
+ goto err_free_data;
+
+ i = 0;
+ of_property_for_each_u32(node, "clock-indices", prop, p, index) {
+ of_property_read_string_index(node, "clock-output-names",
+ i, &clk_name);
+
+ if (index == 17 || (index >= 29 && index <= 31))
+ clk_parent = AHB2;
+ else if (index <= 63 || index >= 128)
+ clk_parent = AHB1;
+ else if (index >= 64 && index <= 95)
+ clk_parent = APB1;
+ else if (index >= 96 && index <= 127)
+ clk_parent = APB2;
+
+ clk_reg = reg + 4 * (index / 32);
+ clk_bit = index % 32;
+
+ clk_data->clks[index] = clk_register_gate(NULL, clk_name,
+ clocks[clk_parent], 0,
+ clk_reg,
+ clk_bit,
+ 0, &gates_lock);
+ i++;
+
+ if (IS_ERR(clk_data->clks[index])) {
+ WARN_ON(true);
+ continue;
+ }
+ }
+
+ clk_data->clk_num = number + 1;
+ of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
+
+ return;
+
+err_free_data:
+ kfree(clk_data);
+err_unmap:
+ iounmap(reg);
+ of_address_to_resource(node, 0, &res);
+ release_mem_region(res.start, resource_size(&res));
+}
+
+CLK_OF_DECLARE(sun8i_h3_bus_gates, "allwinner,sun8i-h3-bus-gates-clk",
+ sun8i_h3_bus_gates_init);
diff --git a/drivers/clk/sunxi/clk-sunxi.c b/drivers/clk/sunxi/clk-sunxi.c
index 270de42..6293c65 100644
--- a/drivers/clk/sunxi/clk-sunxi.c
+++ b/drivers/clk/sunxi/clk-sunxi.c
@@ -769,6 +769,10 @@ static const struct mux_data sun6i_a31_ahb1_mux_data __initconst = {
.shift = 12,
};

+static const struct mux_data sun8i_h3_ahb2_mux_data __initconst = {
+ .shift = 0,
+};
+
static void __init sunxi_mux_clk_setup(struct device_node *node,
struct mux_data *data)
{
@@ -945,10 +949,11 @@ static const struct divs_data pll6_divs_data __initconst = {

static const struct divs_data sun6i_a31_pll6_divs_data __initconst = {
.factors = &sun6i_a31_pll6_data,
- .ndivs = 2,
+ .ndivs = 3,
.div = {
{ .fixed = 2 }, /* normal output */
{ .self = 1 }, /* base factor clock, 2x */
+ { .fixed = 4 }, /* divided output, /2 */
}
};

@@ -1146,6 +1151,7 @@ static const struct of_device_id clk_divs_match[] __initconst = {
static const struct of_device_id clk_mux_match[] __initconst = {
{.compatible = "allwinner,sun4i-a10-cpu-clk", .data = &sun4i_cpu_mux_data,},
{.compatible = "allwinner,sun6i-a31-ahb1-mux-clk", .data = &sun6i_a31_ahb1_mux_data,},
+ {.compatible = "allwinner,sun8i-h3-ahb2-clk", .data = &sun8i_h3_ahb2_mux_data,},
{}
};

@@ -1228,6 +1234,7 @@ CLK_OF_DECLARE(sun6i_a31_clk_init, "allwinner,sun6i-a31", sun6i_init_clocks);
CLK_OF_DECLARE(sun6i_a31s_clk_init, "allwinner,sun6i-a31s", sun6i_init_clocks);
CLK_OF_DECLARE(sun8i_a23_clk_init, "allwinner,sun8i-a23", sun6i_init_clocks);
CLK_OF_DECLARE(sun8i_a33_clk_init, "allwinner,sun8i-a33", sun6i_init_clocks);
+CLK_OF_DECLARE(sun8i_h3_clk_init, "allwinner,sun8i-h3", sun6i_init_clocks);

static void __init sun9i_init_clocks(struct device_node *node)
{
--
2.6.2

Jens Kuske

unread,
Oct 27, 2015, 12:50:47 PM10/27/15
to Maxime Ripard, Chen-Yu Tsai, Michael Turquette, Linus Walleij, Rob Herring, Philipp Zabel, Emilio López, Vishnu Patekar, Hans de Goede, devic...@vger.kernel.org, linux-ar...@lists.infradead.org, linux-...@vger.kernel.org, linux...@googlegroups.com, Jens Kuske
The H3 uses the same pin controller as previous SoC's from Allwinner.
Add support for the pins controlled by the main PIO controller.

Signed-off-by: Jens Kuske <jens...@gmail.com>
Acked-by: Maxime Ripard <maxime...@free-electrons.com>
---
.../bindings/pinctrl/allwinner,sunxi-pinctrl.txt | 1 +
drivers/pinctrl/sunxi/Kconfig | 4 +
drivers/pinctrl/sunxi/Makefile | 1 +
drivers/pinctrl/sunxi/pinctrl-sun8i-h3.c | 516 +++++++++++++++++++++
4 files changed, 522 insertions(+)
create mode 100644 drivers/pinctrl/sunxi/pinctrl-sun8i-h3.c

diff --git a/Documentation/devicetree/bindings/pinctrl/allwinner,sunxi-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/allwinner,sunxi-pinctrl.txt
index b321b26..e6ba602 100644
--- a/Documentation/devicetree/bindings/pinctrl/allwinner,sunxi-pinctrl.txt
+++ b/Documentation/devicetree/bindings/pinctrl/allwinner,sunxi-pinctrl.txt
@@ -18,6 +18,7 @@ Required properties:
"allwinner,sun8i-a23-r-pinctrl"
"allwinner,sun8i-a33-pinctrl"
"allwinner,sun8i-a83t-pinctrl"
+ "allwinner,sun8i-h3-pinctrl"

- reg: Should contain the register physical address and length for the
pin controller.
diff --git a/drivers/pinctrl/sunxi/Kconfig b/drivers/pinctrl/sunxi/Kconfig
index e68fd95..89ab7f5 100644
--- a/drivers/pinctrl/sunxi/Kconfig
+++ b/drivers/pinctrl/sunxi/Kconfig
@@ -51,6 +51,10 @@ config PINCTRL_SUN8I_A23_R
depends on RESET_CONTROLLER
select PINCTRL_SUNXI_COMMON

+config PINCTRL_SUN8I_H3
+ def_bool MACH_SUN8I
+ select PINCTRL_SUNXI_COMMON
+
config PINCTRL_SUN9I_A80
def_bool MACH_SUN9I
select PINCTRL_SUNXI_COMMON
diff --git a/drivers/pinctrl/sunxi/Makefile b/drivers/pinctrl/sunxi/Makefile
index e080290..6bd818e 100644
--- a/drivers/pinctrl/sunxi/Makefile
+++ b/drivers/pinctrl/sunxi/Makefile
@@ -13,4 +13,5 @@ obj-$(CONFIG_PINCTRL_SUN8I_A23) += pinctrl-sun8i-a23.o
obj-$(CONFIG_PINCTRL_SUN8I_A23_R) += pinctrl-sun8i-a23-r.o
obj-$(CONFIG_PINCTRL_SUN8I_A33) += pinctrl-sun8i-a33.o
obj-$(CONFIG_PINCTRL_SUN8I_A83T) += pinctrl-sun8i-a83t.o
+obj-$(CONFIG_PINCTRL_SUN8I_H3) += pinctrl-sun8i-h3.o
obj-$(CONFIG_PINCTRL_SUN9I_A80) += pinctrl-sun9i-a80.o
diff --git a/drivers/pinctrl/sunxi/pinctrl-sun8i-h3.c b/drivers/pinctrl/sunxi/pinctrl-sun8i-h3.c
new file mode 100644
index 0000000..98d465d
--- /dev/null
+++ b/drivers/pinctrl/sunxi/pinctrl-sun8i-h3.c
@@ -0,0 +1,516 @@
+/*
+ * Allwinner H3 SoCs pinctrl driver.
+ *
+ * Copyright (C) 2015 Jens Kuske <jens...@gmail.com>
+ *
+ * Based on pinctrl-sun8i-a23.c, which is:
+ * Copyright (C) 2014 Chen-Yu Tsai <we...@csie.org>
+ * Copyright (C) 2014 Maxime Ripard <maxime...@free-electrons.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/pinctrl/pinctrl.h>
+
+#include "pinctrl-sunxi.h"
+
+static const struct sunxi_desc_pin sun8i_h3_pins[] = {
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 0),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "uart2"), /* TX */
+ SUNXI_FUNCTION(0x3, "jtag"), /* MS */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 0)), /* PA_EINT0 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 1),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "uart2"), /* RX */
+ SUNXI_FUNCTION(0x3, "jtag"), /* CK */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 1)), /* PA_EINT1 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 2),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "uart2"), /* RTS */
+ SUNXI_FUNCTION(0x3, "jtag"), /* DO */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 2)), /* PA_EINT2 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 3),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "uart2"), /* CTS */
+ SUNXI_FUNCTION(0x3, "jtag"), /* DI */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 3)), /* PA_EINT3 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 4),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "uart0"), /* TX */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 4)), /* PA_EINT4 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 5),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "uart0"), /* RX */
+ SUNXI_FUNCTION(0x3, "pwm0"),
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 5)), /* PA_EINT5 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 6),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "sim"), /* PWREN */
+ SUNXI_FUNCTION(0x3, "pwm1"),
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 6)), /* PA_EINT6 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 7),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "sim"), /* CLK */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 7)), /* PA_EINT7 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 8),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "sim"), /* DATA */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 8)), /* PA_EINT8 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 9),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "sim"), /* RST */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 9)), /* PA_EINT9 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 10),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "sim"), /* DET */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 10)), /* PA_EINT10 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 11),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "i2c0"), /* SCK */
+ SUNXI_FUNCTION(0x3, "di"), /* TX */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 11)), /* PA_EINT11 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 12),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "i2c0"), /* SDA */
+ SUNXI_FUNCTION(0x3, "di"), /* RX */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 12)), /* PA_EINT12 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 13),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "spi1"), /* CS */
+ SUNXI_FUNCTION(0x3, "uart3"), /* TX */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 13)), /* PA_EINT13 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 14),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "spi1"), /* CLK */
+ SUNXI_FUNCTION(0x3, "uart3"), /* RX */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 14)), /* PA_EINT14 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 15),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "spi1"), /* MOSI */
+ SUNXI_FUNCTION(0x3, "uart3"), /* RTS */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 15)), /* PA_EINT15 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 16),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "spi1"), /* MISO */
+ SUNXI_FUNCTION(0x3, "uart3"), /* CTS */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 16)), /* PA_EINT16 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 17),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "spdif"), /* OUT */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 17)), /* PA_EINT17 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 18),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "i2s0"), /* SYNC */
+ SUNXI_FUNCTION(0x3, "i2c1"), /* SCK */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 18)), /* PA_EINT18 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 19),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "i2s0"), /* CLK */
+ SUNXI_FUNCTION(0x3, "i2c1"), /* SDA */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 19)), /* PA_EINT19 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 20),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "i2s0"), /* DOUT */
+ SUNXI_FUNCTION(0x3, "sim"), /* VPPEN */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 20)), /* PA_EINT20 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 21),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "i2s0"), /* DIN */
+ SUNXI_FUNCTION(0x3, "sim"), /* VPPPP */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 21)), /* PA_EINT21 */
+ /* Hole */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 0),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "nand0"), /* WE */
+ SUNXI_FUNCTION(0x3, "spi0")), /* MOSI */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 1),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "nand0"), /* ALE */
+ SUNXI_FUNCTION(0x3, "spi0")), /* MISO */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 2),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "nand0"), /* CLE */
+ SUNXI_FUNCTION(0x3, "spi0")), /* CLK */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 3),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "nand0"), /* CE1 */
+ SUNXI_FUNCTION(0x3, "spi0")), /* CS */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 4),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "nand0")), /* CE0 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 5),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "nand0"), /* RE */
+ SUNXI_FUNCTION(0x3, "mmc2")), /* CLK */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 6),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "nand0"), /* RB0 */
+ SUNXI_FUNCTION(0x3, "mmc2")), /* CMD */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 7),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "nand0")), /* RB1 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 8),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "nand0"), /* DQ0 */
+ SUNXI_FUNCTION(0x3, "mmc2")), /* D0 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 9),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "nand0"), /* DQ1 */
+ SUNXI_FUNCTION(0x3, "mmc2")), /* D1 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 10),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "nand0"), /* DQ2 */
+ SUNXI_FUNCTION(0x3, "mmc2")), /* D2 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 11),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "nand0"), /* DQ3 */
+ SUNXI_FUNCTION(0x3, "mmc2")), /* D3 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 12),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "nand0"), /* DQ4 */
+ SUNXI_FUNCTION(0x3, "mmc2")), /* D4 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 13),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "nand0"), /* DQ5 */
+ SUNXI_FUNCTION(0x3, "mmc2")), /* D5 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 14),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "nand"), /* DQ6 */
+ SUNXI_FUNCTION(0x3, "mmc2")), /* D6 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 15),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "nand"), /* DQ7 */
+ SUNXI_FUNCTION(0x3, "mmc2")), /* D7 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 16),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "nand"), /* DQS */
+ SUNXI_FUNCTION(0x3, "mmc2")), /* RST */
+ /* Hole */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 0),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "emac")), /* RXD3 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 1),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "emac")), /* RXD2 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 2),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "emac")), /* RXD1 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 3),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "emac")), /* RXD0 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 4),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "emac")), /* RXCK */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 5),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "emac")), /* RXCTL/RCDV */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 6),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "emac")), /* RXERR */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 7),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "emac")), /* TXD3 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 8),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "emac")), /* TXD2L */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 9),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "emac")), /* TXD1 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 10),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "emac")), /* TXD0 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 11),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "emac")), /* CRS */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 12),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "emac")), /* TXCK */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 13),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "emac")), /* TXCTL/TXEN */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 14),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "emac")), /* TXERR */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 15),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "emac")), /* CLKIN/COL */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 16),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "emac")), /* MDC */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 17),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "emac")), /* MDIO */
+ /* Hole */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 0),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "csi"), /* PCLK */
+ SUNXI_FUNCTION(0x3, "ts")), /* CLK */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 1),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "csi"), /* MCLK */
+ SUNXI_FUNCTION(0x3, "ts")), /* ERR */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 2),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "csi"), /* HSYNC */
+ SUNXI_FUNCTION(0x3, "ts")), /* SYNC */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 3),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "csi"), /* VSYNC */
+ SUNXI_FUNCTION(0x3, "ts")), /* DVLD */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 4),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "csi"), /* D0 */
+ SUNXI_FUNCTION(0x3, "ts")), /* D0 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 5),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "csi"), /* D1 */
+ SUNXI_FUNCTION(0x3, "ts")), /* D1 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 6),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "csi"), /* D2 */
+ SUNXI_FUNCTION(0x3, "ts")), /* D2 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 7),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "csi"), /* D3 */
+ SUNXI_FUNCTION(0x3, "ts")), /* D3 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 8),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "csi"), /* D4 */
+ SUNXI_FUNCTION(0x3, "ts")), /* D4 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 9),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "csi"), /* D5 */
+ SUNXI_FUNCTION(0x3, "ts")), /* D5 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 10),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "csi"), /* D6 */
+ SUNXI_FUNCTION(0x3, "ts")), /* D6 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 11),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "csi"), /* D7 */
+ SUNXI_FUNCTION(0x3, "ts")), /* D7 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 12),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "csi"), /* SCK */
+ SUNXI_FUNCTION(0x3, "i2c2")), /* SCK */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 13),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "csi"), /* SDA */
+ SUNXI_FUNCTION(0x3, "i2c2")), /* SDA */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 14),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 15),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out")),
+ /* Hole */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 0),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "mmc0"), /* D1 */
+ SUNXI_FUNCTION(0x3, "jtag")), /* MS */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 1),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "mmc0"), /* D0 */
+ SUNXI_FUNCTION(0x3, "jtag")), /* DI */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 2),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "mmc0"), /* CLK */
+ SUNXI_FUNCTION(0x3, "uart0")), /* TX */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 3),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "mmc0"), /* CMD */
+ SUNXI_FUNCTION(0x3, "jtag")), /* DO */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 4),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "mmc0"), /* D3 */
+ SUNXI_FUNCTION(0x3, "uart0")), /* RX */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 5),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "mmc0"), /* D2 */
+ SUNXI_FUNCTION(0x3, "jtag")), /* CK */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 6),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "mmc0")), /* DET */
+ /* Hole */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 0),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "mmc1"), /* CLK */
+ SUNXI_FUNCTION_IRQ_BANK(0x4, 1, 0)), /* PG_EINT0 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 1),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "mmc1"), /* CMD */
+ SUNXI_FUNCTION_IRQ_BANK(0x4, 1, 1)), /* PG_EINT1 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 2),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "mmc1"), /* D0 */
+ SUNXI_FUNCTION_IRQ_BANK(0x4, 1, 2)), /* PG_EINT2 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 3),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "mmc1"), /* D1 */
+ SUNXI_FUNCTION_IRQ_BANK(0x4, 1, 3)), /* PG_EINT3 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 4),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "mmc1"), /* D2 */
+ SUNXI_FUNCTION_IRQ_BANK(0x4, 1, 4)), /* PG_EINT4 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 5),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "mmc1"), /* D3 */
+ SUNXI_FUNCTION_IRQ_BANK(0x4, 1, 5)), /* PG_EINT5 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 6),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "uart1"), /* TX */
+ SUNXI_FUNCTION_IRQ_BANK(0x4, 1, 6)), /* PG_EINT6 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 7),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "uart1"), /* RX */
+ SUNXI_FUNCTION_IRQ_BANK(0x4, 1, 7)), /* PG_EINT7 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 8),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "uart1"), /* RTS */
+ SUNXI_FUNCTION_IRQ_BANK(0x4, 1, 8)), /* PG_EINT8 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 9),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "uart1"), /* CTS */
+ SUNXI_FUNCTION_IRQ_BANK(0x4, 1, 9)), /* PG_EINT9 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 10),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "i2s1"), /* SYNC */
+ SUNXI_FUNCTION_IRQ_BANK(0x4, 1, 10)), /* PG_EINT10 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 11),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "i2s1"), /* CLK */
+ SUNXI_FUNCTION_IRQ_BANK(0x4, 1, 11)), /* PG_EINT11 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 12),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "i2s1"), /* DOUT */
+ SUNXI_FUNCTION_IRQ_BANK(0x4, 1, 12)), /* PG_EINT12 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 13),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "i2s1"), /* DIN */
+ SUNXI_FUNCTION_IRQ_BANK(0x4, 1, 13)), /* PG_EINT13 */
+};
+
+static const struct sunxi_pinctrl_desc sun8i_h3_pinctrl_data = {
+ .pins = sun8i_h3_pins,
+ .npins = ARRAY_SIZE(sun8i_h3_pins),
+ .irq_banks = 2,
+};
+
+static int sun8i_h3_pinctrl_probe(struct platform_device *pdev)
+{
+ return sunxi_pinctrl_init(pdev,
+ &sun8i_h3_pinctrl_data);
+}
+
+static const struct of_device_id sun8i_h3_pinctrl_match[] = {
+ { .compatible = "allwinner,sun8i-h3-pinctrl", },
+ {}
+};
+
+static struct platform_driver sun8i_h3_pinctrl_driver = {
+ .probe = sun8i_h3_pinctrl_probe,
+ .driver = {
+ .name = "sun8i-h3-pinctrl",
+ .of_match_table = sun8i_h3_pinctrl_match,
+ },
+};
+builtin_platform_driver(sun8i_h3_pinctrl_driver);
--
2.6.2

Jens Kuske

unread,
Oct 27, 2015, 12:50:48 PM10/27/15
to Maxime Ripard, Chen-Yu Tsai, Michael Turquette, Linus Walleij, Rob Herring, Philipp Zabel, Emilio López, Vishnu Patekar, Hans de Goede, devic...@vger.kernel.org, linux-ar...@lists.infradead.org, linux-...@vger.kernel.org, linux...@googlegroups.com, Jens Kuske
The H3 bus resets have some holes between the registers, so we add
an of_xlate() function to skip them according to the datasheet.

Signed-off-by: Jens Kuske <jens...@gmail.com>
---
.../bindings/reset/allwinner,sunxi-clock-reset.txt | 1 +
drivers/reset/reset-sunxi.c | 30 +++++++++++++++++++---
2 files changed, 28 insertions(+), 3 deletions(-)

diff --git a/Documentation/devicetree/bindings/reset/allwinner,sunxi-clock-reset.txt b/Documentation/devicetree/bindings/reset/allwinner,sunxi-clock-reset.txt
index c8f7757..e11f023 100644
--- a/Documentation/devicetree/bindings/reset/allwinner,sunxi-clock-reset.txt
+++ b/Documentation/devicetree/bindings/reset/allwinner,sunxi-clock-reset.txt
@@ -8,6 +8,7 @@ Required properties:
- compatible: Should be one of the following:
"allwinner,sun6i-a31-ahb1-reset"
"allwinner,sun6i-a31-clock-reset"
+ "allwinner,sun8i-h3-bus-reset"
- reg: should be register base and length as documented in the
datasheet
- #reset-cells: 1, see below
diff --git a/drivers/reset/reset-sunxi.c b/drivers/reset/reset-sunxi.c
index 3d95c87..c91e146 100644
--- a/drivers/reset/reset-sunxi.c
+++ b/drivers/reset/reset-sunxi.c
@@ -75,7 +75,9 @@ static struct reset_control_ops sunxi_reset_ops = {
.deassert = sunxi_reset_deassert,
};

-static int sunxi_reset_init(struct device_node *np)
+static int sunxi_reset_init(struct device_node *np,
+ int (*of_xlate)(struct reset_controller_dev *rcdev,
+ const struct of_phandle_args *reset_spec))
{
struct sunxi_reset_data *data;
struct resource res;
@@ -108,6 +110,7 @@ static int sunxi_reset_init(struct device_node *np)
data->rcdev.nr_resets = size * 32;
data->rcdev.ops = &sunxi_reset_ops;
data->rcdev.of_node = np;
+ data->rcdev.of_xlate = of_xlate;
reset_controller_register(&data->rcdev);

return 0;
@@ -117,6 +120,21 @@ err_alloc:
return ret;
};

+static int sun8i_h3_bus_reset_xlate(struct reset_controller_dev *rcdev,
+ const struct of_phandle_args *reset_spec)
+{
+ unsigned int index = reset_spec->args[0];
+
+ if (index < 96)
+ return index;
+ else if (index < 128)
+ return index + 32;
+ else if (index < 160)
+ return index + 64;
+ else
+ return -EINVAL;
+}
+
/*
* These are the reset controller we need to initialize early on in
* our system, before we can even think of using a regular device
@@ -124,15 +142,21 @@ err_alloc:
*/
static const struct of_device_id sunxi_early_reset_dt_ids[] __initdata = {
{ .compatible = "allwinner,sun6i-a31-ahb1-reset", },
+ { .compatible = "allwinner,sun8i-h3-bus-reset", .data = sun8i_h3_bus_reset_xlate, },
{ /* sentinel */ },
};

void __init sun6i_reset_init(void)
{
struct device_node *np;
+ const struct of_device_id *match;
+ int (*of_xlate)(struct reset_controller_dev *rcdev,
+ const struct of_phandle_args *reset_spec);

- for_each_matching_node(np, sunxi_early_reset_dt_ids)
- sunxi_reset_init(np);
+ for_each_matching_node_and_match(np, sunxi_early_reset_dt_ids, &match) {
+ of_xlate = match->data;
+ sunxi_reset_init(np, of_xlate);
+ }
}

/*
--
2.6.2

Jens Kuske

unread,
Oct 27, 2015, 12:50:50 PM10/27/15
to Maxime Ripard, Chen-Yu Tsai, Michael Turquette, Linus Walleij, Rob Herring, Philipp Zabel, Emilio López, Vishnu Patekar, Hans de Goede, devic...@vger.kernel.org, linux-ar...@lists.infradead.org, linux-...@vger.kernel.org, linux...@googlegroups.com, Jens Kuske
The Allwinner H3 is a home entertainment system oriented SoC with
four Cortex-A7 cores and a Mali-400MP2 GPU.

Signed-off-by: Jens Kuske <jens...@gmail.com>
---
arch/arm/boot/dts/sun8i-h3.dtsi | 482 ++++++++++++++++++++++++++++++++++++++++
1 file changed, 482 insertions(+)
create mode 100644 arch/arm/boot/dts/sun8i-h3.dtsi

diff --git a/arch/arm/boot/dts/sun8i-h3.dtsi b/arch/arm/boot/dts/sun8i-h3.dtsi
new file mode 100644
index 0000000..c18b5f7
--- /dev/null
+++ b/arch/arm/boot/dts/sun8i-h3.dtsi
@@ -0,0 +1,482 @@
+/*
+ * Copyright (C) 2015 Jens Kuske <jens...@gmail.com>
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ * a) This file 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 file 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.
+ *
+ * Or, alternatively,
+ *
+ * b) Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include "skeleton.dtsi"
+
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <dt-bindings/pinctrl/sun4i-a10.h>
+
+/ {
+ interrupt-parent = <&gic>;
+
+ cpus {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ cpu@0 {
+ compatible = "arm,cortex-a7";
+ device_type = "cpu";
+ reg = <0>;
+ };
+
+ cpu@1 {
+ compatible = "arm,cortex-a7";
+ device_type = "cpu";
+ reg = <1>;
+ };
+
+ cpu@2 {
+ compatible = "arm,cortex-a7";
+ device_type = "cpu";
+ reg = <2>;
+ };
+
+ cpu@3 {
+ compatible = "arm,cortex-a7";
+ device_type = "cpu";
+ reg = <3>;
+ };
+ };
+
+ timer {
+ compatible = "arm,armv7-timer";
+ interrupts = <GIC_PPI 13 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
+ <GIC_PPI 14 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
+ <GIC_PPI 11 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
+ <GIC_PPI 10 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>;
+ clock-frequency = <24000000>;
+ arm,cpu-registers-not-fw-configured;
+ };
+
+ memory {
+ reg = <0x40000000 0x80000000>;
+ };
+
+ clocks {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges;
+
+ osc24M: osc24M_clk {
+ #clock-cells = <0>;
+ compatible = "fixed-clock";
+ clock-frequency = <24000000>;
+ clock-output-names = "osc24M";
+ };
+
+ osc32k: osc32k_clk {
+ #clock-cells = <0>;
+ compatible = "fixed-clock";
+ clock-frequency = <32768>;
+ clock-output-names = "osc32k";
+ };
+
+ pll1: clk@01c20000 {
+ #clock-cells = <0>;
+ compatible = "allwinner,sun8i-a23-pll1-clk";
+ reg = <0x01c20000 0x4>;
+ clocks = <&osc24M>;
+ clock-output-names = "pll1";
+ };
+
+ /* dummy clock until actually implemented */
+ pll5: pll5_clk {
+ #clock-cells = <0>;
+ compatible = "fixed-clock";
+ clock-frequency = <0>;
+ clock-output-names = "pll5";
+ };
+
+ pll6: clk@01c20028 {
+ #clock-cells = <1>;
+ compatible = "allwinner,sun6i-a31-pll6-clk";
+ reg = <0x01c20028 0x4>;
+ clocks = <&osc24M>;
+ clock-output-names = "pll6", "pll6x2", "pll6d2";
+ };
+
+ pll8: clk@01c20044 {
+ #clock-cells = <1>;
+ compatible = "allwinner,sun6i-a31-pll6-clk";
+ reg = <0x01c20044 0x4>;
+ clocks = <&osc24M>;
+ clock-output-names = "pll8", "pll8x2";
+ };
+
+ cpu: cpu_clk@01c20050 {
+ #clock-cells = <0>;
+ compatible = "allwinner,sun4i-a10-cpu-clk";
+ reg = <0x01c20050 0x4>;
+ clocks = <&osc32k>, <&osc24M>, <&pll1>, <&pll1>;
+ clock-output-names = "cpu";
+ };
+
+ axi: axi_clk@01c20050 {
+ #clock-cells = <0>;
+ compatible = "allwinner,sun4i-a10-axi-clk";
+ reg = <0x01c20050 0x4>;
+ clocks = <&cpu>;
+ clock-output-names = "axi";
+ };
+
+ ahb1: ahb1_clk@01c20054 {
+ #clock-cells = <0>;
+ compatible = "allwinner,sun6i-a31-ahb1-clk";
+ reg = <0x01c20054 0x4>;
+ clocks = <&osc32k>, <&osc24M>, <&axi>, <&pll6 0>;
+ clock-output-names = "ahb1";
+ };
+
+ ahb2: ahb2_clk@01c2005c {
+ #clock-cells = <0>;
+ compatible = "allwinner,sun8i-h3-ahb2-clk";
+ reg = <0x01c2005c 0x4>;
+ clocks = <&ahb1>, <&pll6 2>;
+ clock-output-names = "ahb2";
+ };
+
+ apb1: apb1_clk@01c20054 {
+ #clock-cells = <0>;
+ compatible = "allwinner,sun4i-a10-apb0-clk";
+ reg = <0x01c20054 0x4>;
+ clocks = <&ahb1>;
+ clock-output-names = "apb1";
+ };
+
+ apb2: apb2_clk@01c20058 {
+ #clock-cells = <0>;
+ compatible = "allwinner,sun4i-a10-apb1-clk";
+ reg = <0x01c20058 0x4>;
+ clocks = <&osc32k>, <&osc24M>, <&pll6 0>, <&pll6 0>;
+ clock-output-names = "apb2";
+ };
+
+ bus_gates: clk@01c20060 {
+ #clock-cells = <1>;
+ compatible = "allwinner,sun8i-h3-bus-gates-clk";
+ reg = <0x01c20060 0x14>;
+ clocks = <&ahb1>, <&ahb2>, <&apb1>, <&apb2>;
+ clock-names = "ahb1", "ahb2", "apb1", "apb2";
+ clock-indices = <5>, <6>, <8>,
+ <9>, <10>, <13>,
+ <14>, <17>, <18>,
+ <19>, <20>,
+ <21>, <23>,
+ <24>, <25>,
+ <26>, <27>,
+ <28>, <29>,
+ <30>, <31>, <32>,
+ <35>, <36>, <37>,
+ <40>, <41>, <43>,
+ <44>, <52>, <53>,
+ <54>, <64>,
+ <65>, <69>, <72>,
+ <76>, <77>, <78>,
+ <96>, <97>, <98>,
+ <112>, <113>,
+ <114>, <115>, <116>,
+ <128>, <135>;
+ clock-output-names = "ahb1_ce", "ahb1_dma", "ahb1_mmc0",
+ "ahb1_mmc1", "ahb1_mmc2", "ahb1_nand",
+ "ahb1_sdram", "ahb2_gmac", "ahb1_ts",
+ "ahb1_hstimer", "ahb1_spi0",
+ "ahb1_spi1", "ahb1_otg",
+ "ahb1_otg_ehci0", "ahb1_ehic1",
+ "ahb1_ehic2", "ahb1_ehic3",
+ "ahb1_otg_ohci0", "ahb2_ohic1",
+ "ahb2_ohic2", "ahb2_ohic3", "ahb1_ve",
+ "ahb1_lcd0", "ahb1_lcd1", "ahb1_deint",
+ "ahb1_csi", "ahb1_tve", "ahb1_hdmi",
+ "ahb1_de", "ahb1_gpu", "ahb1_msgbox",
+ "ahb1_spinlock", "apb1_codec",
+ "apb1_spdif", "apb1_pio", "apb1_ths",
+ "apb1_i2s0", "apb1_i2s1", "apb1_i2s2",
+ "apb2_i2c0", "apb2_i2c1", "apb2_i2c2",
+ "apb2_uart0", "apb2_uart1",
+ "apb2_uart2", "apb2_uart3", "apb2_scr",
+ "ahb1_ephy", "ahb1_dbg";
+ };
+
+ mmc0_clk: clk@01c20088 {
+ #clock-cells = <1>;
+ compatible = "allwinner,sun4i-a10-mmc-clk";
+ reg = <0x01c20088 0x4>;
+ clocks = <&osc24M>, <&pll6 0>, <&pll8 0>;
+ clock-output-names = "mmc0",
+ "mmc0_output",
+ "mmc0_sample";
+ };
+
+ mmc1_clk: clk@01c2008c {
+ #clock-cells = <1>;
+ compatible = "allwinner,sun4i-a10-mmc-clk";
+ reg = <0x01c2008c 0x4>;
+ clocks = <&osc24M>, <&pll6 0>, <&pll8 0>;
+ clock-output-names = "mmc1",
+ "mmc1_output",
+ "mmc1_sample";
+ };
+
+ mmc2_clk: clk@01c20090 {
+ #clock-cells = <1>;
+ compatible = "allwinner,sun4i-a10-mmc-clk";
+ reg = <0x01c20090 0x4>;
+ clocks = <&osc24M>, <&pll6 0>, <&pll8 0>;
+ clock-output-names = "mmc2",
+ "mmc2_output",
+ "mmc2_sample";
+ };
+
+ mbus_clk: clk@01c2015c {
+ #clock-cells = <0>;
+ compatible = "allwinner,sun8i-a23-mbus-clk";
+ reg = <0x01c2015c 0x4>;
+ clocks = <&osc24M>, <&pll6 1>, <&pll5>;
+ clock-output-names = "mbus";
+ };
+ };
+
+ soc {
+ compatible = "simple-bus";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges;
+
+ dma: dma-controller@01c02000 {
+ compatible = "allwinner,sun8i-h3-dma";
+ reg = <0x01c02000 0x1000>;
+ interrupts = <GIC_SPI 50 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&bus_gates 6>;
+ resets = <&bus_rst 6>;
+ #dma-cells = <1>;
+ };
+
+ mmc0: mmc@01c0f000 {
+ compatible = "allwinner,sun5i-a13-mmc";
+ reg = <0x01c0f000 0x1000>;
+ clocks = <&bus_gates 8>,
+ <&mmc0_clk 0>,
+ <&mmc0_clk 1>,
+ <&mmc0_clk 2>;
+ clock-names = "ahb",
+ "mmc",
+ "output",
+ "sample";
+ resets = <&bus_rst 8>;
+ reset-names = "ahb";
+ interrupts = <GIC_SPI 60 IRQ_TYPE_LEVEL_HIGH>;
+ status = "disabled";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+
+ mmc1: mmc@01c10000 {
+ compatible = "allwinner,sun5i-a13-mmc";
+ reg = <0x01c10000 0x1000>;
+ clocks = <&bus_gates 9>,
+ <&mmc1_clk 0>,
+ <&mmc1_clk 1>,
+ <&mmc1_clk 2>;
+ clock-names = "ahb",
+ "mmc",
+ "output",
+ "sample";
+ resets = <&bus_rst 9>;
+ reset-names = "ahb";
+ interrupts = <GIC_SPI 61 IRQ_TYPE_LEVEL_HIGH>;
+ status = "disabled";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+
+ mmc2: mmc@01c11000 {
+ compatible = "allwinner,sun5i-a13-mmc";
+ reg = <0x01c11000 0x1000>;
+ clocks = <&bus_gates 10>,
+ <&mmc2_clk 0>,
+ <&mmc2_clk 1>,
+ <&mmc2_clk 2>;
+ clock-names = "ahb",
+ "mmc",
+ "output",
+ "sample";
+ resets = <&bus_rst 10>;
+ reset-names = "ahb";
+ interrupts = <GIC_SPI 62 IRQ_TYPE_LEVEL_HIGH>;
+ status = "disabled";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+
+ pio: pinctrl@01c20800 {
+ compatible = "allwinner,sun8i-h3-pinctrl";
+ reg = <0x01c20800 0x400>;
+ interrupts = <GIC_SPI 11 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 17 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&bus_gates 69>;
+ gpio-controller;
+ #gpio-cells = <3>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+
+ uart0_pins_a: uart0@0 {
+ allwinner,pins = "PA4", "PA5";
+ allwinner,function = "uart0";
+ allwinner,drive = <SUN4I_PINCTRL_10_MA>;
+ allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
+ };
+
+ mmc0_pins_a: mmc0@0 {
+ allwinner,pins = "PF0", "PF1", "PF2", "PF3",
+ "PF4", "PF5";
+ allwinner,function = "mmc0";
+ allwinner,drive = <SUN4I_PINCTRL_30_MA>;
+ allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
+ };
+
+ mmc0_cd_pin: mmc0_cd_pin@0 {
+ allwinner,pins = "PF6";
+ allwinner,function = "gpio_in";
+ allwinner,drive = <SUN4I_PINCTRL_10_MA>;
+ allwinner,pull = <SUN4I_PINCTRL_PULL_UP>;
+ };
+
+ mmc1_pins_a: mmc1@0 {
+ allwinner,pins = "PG0", "PG1", "PG2", "PG3",
+ "PG4", "PG5";
+ allwinner,function = "mmc1";
+ allwinner,drive = <SUN4I_PINCTRL_30_MA>;
+ allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
+ };
+ };
+
+ bus_rst: reset@01c202c0 {
+ #reset-cells = <1>;
+ compatible = "allwinner,sun8i-h3-bus-reset";
+ reg = <0x01c202c0 0x1c>;
+ };
+
+ timer@01c20c00 {
+ compatible = "allwinner,sun4i-a10-timer";
+ reg = <0x01c20c00 0xa0>;
+ interrupts = <GIC_SPI 18 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 19 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&osc24M>;
+ };
+
+ wdt0: watchdog@01c20ca0 {
+ compatible = "allwinner,sun6i-a31-wdt";
+ reg = <0x01c20ca0 0x20>;
+ interrupts = <GIC_SPI 25 IRQ_TYPE_LEVEL_HIGH>;
+ };
+
+ uart0: serial@01c28000 {
+ compatible = "snps,dw-apb-uart";
+ reg = <0x01c28000 0x400>;
+ interrupts = <GIC_SPI 0 IRQ_TYPE_LEVEL_HIGH>;
+ reg-shift = <2>;
+ reg-io-width = <4>;
+ clocks = <&bus_gates 112>;
+ resets = <&bus_rst 144>;
+ dmas = <&dma 6>, <&dma 6>;
+ dma-names = "rx", "tx";
+ status = "disabled";
+ };
+
+ uart1: serial@01c28400 {
+ compatible = "snps,dw-apb-uart";
+ reg = <0x01c28400 0x400>;
+ interrupts = <GIC_SPI 1 IRQ_TYPE_LEVEL_HIGH>;
+ reg-shift = <2>;
+ reg-io-width = <4>;
+ clocks = <&bus_gates 113>;
+ resets = <&bus_rst 145>;
+ dmas = <&dma 7>, <&dma 7>;
+ dma-names = "rx", "tx";
+ status = "disabled";
+ };
+
+ uart2: serial@01c28800 {
+ compatible = "snps,dw-apb-uart";
+ reg = <0x01c28800 0x400>;
+ interrupts = <GIC_SPI 2 IRQ_TYPE_LEVEL_HIGH>;
+ reg-shift = <2>;
+ reg-io-width = <4>;
+ clocks = <&bus_gates 114>;
+ resets = <&bus_rst 146>;
+ dmas = <&dma 8>, <&dma 8>;
+ dma-names = "rx", "tx";
+ status = "disabled";
+ };
+
+ uart3: serial@01c28c00 {
+ compatible = "snps,dw-apb-uart";
+ reg = <0x01c28c00 0x400>;
+ interrupts = <GIC_SPI 3 IRQ_TYPE_LEVEL_HIGH>;
+ reg-shift = <2>;
+ reg-io-width = <4>;
+ clocks = <&bus_gates 115>;
+ resets = <&bus_rst 147>;
+ dmas = <&dma 9>, <&dma 9>;
+ dma-names = "rx", "tx";
+ status = "disabled";
+ };
+
+ gic: interrupt-controller@01c81000 {
+ compatible = "arm,cortex-a7-gic", "arm,cortex-a15-gic";
+ reg = <0x01c81000 0x1000>,
+ <0x01c82000 0x1000>,
+ <0x01c84000 0x2000>,
+ <0x01c86000 0x2000>;
+ interrupt-controller;
+ #interrupt-cells = <3>;
+ interrupts = <GIC_PPI 9 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>;
+ };
+
+ rtc: rtc@01f00000 {
+ compatible = "allwinner,sun6i-a31-rtc";
+ reg = <0x01f00000 0x54>;
+ interrupts = <GIC_SPI 40 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 41 IRQ_TYPE_LEVEL_HIGH>;
+ };
+ };
+};
--
2.6.2

Jens Kuske

unread,
Oct 27, 2015, 12:50:51 PM10/27/15
to Maxime Ripard, Chen-Yu Tsai, Michael Turquette, Linus Walleij, Rob Herring, Philipp Zabel, Emilio López, Vishnu Patekar, Hans de Goede, devic...@vger.kernel.org, linux-ar...@lists.infradead.org, linux-...@vger.kernel.org, linux...@googlegroups.com, Jens Kuske
The Orange Pi Plus is a SBC based on the Allwinner H3 SoC
with 8GB eMMC, multiple USB ports through a USB hub chip, SATA through
a USB-SATA bridge, one uSD slot, a 10/100/1000M ethernet port,
WiFi, HDMI, headphone jack, IR receiver, a microphone, a CSI connector
and a 40-pin GPIO header.

Signed-off-by: Jens Kuske <jens...@gmail.com>
---
arch/arm/boot/dts/Makefile | 3 +-
arch/arm/boot/dts/sun8i-h3-orangepi-plus.dts | 77 ++++++++++++++++++++++++++++
2 files changed, 79 insertions(+), 1 deletion(-)
create mode 100644 arch/arm/boot/dts/sun8i-h3-orangepi-plus.dts

diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
index 78ade1a..476658d 100644
--- a/arch/arm/boot/dts/Makefile
+++ b/arch/arm/boot/dts/Makefile
@@ -645,7 +645,8 @@ dtb-$(CONFIG_MACH_SUN8I) += \
sun8i-a33-ga10h-v1.1.dtb \
sun8i-a33-ippo-q8h-v1.2.dtb \
sun8i-a33-q8-tablet.dtb \
- sun8i-a33-sinlinx-sina33.dtb
+ sun8i-a33-sinlinx-sina33.dtb \
+ sun8i-h3-orangepi-plus.dtb
dtb-$(CONFIG_MACH_SUN9I) += \
sun9i-a80-optimus.dtb \
sun9i-a80-cubieboard4.dtb
diff --git a/arch/arm/boot/dts/sun8i-h3-orangepi-plus.dts b/arch/arm/boot/dts/sun8i-h3-orangepi-plus.dts
new file mode 100644
index 0000000..e67df59
--- /dev/null
+++ b/arch/arm/boot/dts/sun8i-h3-orangepi-plus.dts
@@ -0,0 +1,77 @@
+/dts-v1/;
+#include "sun8i-h3.dtsi"
+#include "sunxi-common-regulators.dtsi"
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/pinctrl/sun4i-a10.h>
+
+/ {
+ model = "Xunlong Orange Pi Plus";
+ compatible = "xunlong,orangepi-plus", "allwinner,sun8i-h3";
+
+ aliases {
+ serial0 = &uart0;
+ };
+
+ chosen {
+ stdout-path = "serial0:115200n8";
+ };
+};
+
+&mmc0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin>;
+ vmmc-supply = <&reg_vcc3v3>;
+ bus-width = <4>;
+ cd-gpios = <&pio 5 6 GPIO_ACTIVE_HIGH>; /* PF6 */
+ cd-inverted;
+ status = "okay";
+};
+
+&uart0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&uart0_pins_a>;
+ status = "okay";
+};
--
2.6.2

Jean-Francois Moine

unread,
Oct 27, 2015, 2:04:10 PM10/27/15
to Jens Kuske, Maxime Ripard, Chen-Yu Tsai, Michael Turquette, Linus Walleij, Rob Herring, Philipp Zabel, Emilio López, devic...@vger.kernel.org, Vishnu Patekar, linux-...@vger.kernel.org, Hans de Goede, linux...@googlegroups.com, linux-ar...@lists.infradead.org
On Tue, 27 Oct 2015 17:50:20 +0100
Jens Kuske <jens...@gmail.com> wrote:

> Changes since v3:
> - add a clock driver specific to the bus gates instead of listing parents in
> the DTSI
> - skip the holes in the reset controller with of_xlate()

Hi, Maxime, there we are :(. The H3 description is hardcoded and the
next SoCs will ask for more and more code. I wonder what is the use of
a DT...

Peter Korsgaard

unread,
Oct 27, 2015, 3:24:26 PM10/27/15
to Hans de Goede, Jens Kuske, Maxime Ripard, Chen-Yu Tsai, Linus Walleij, Rob Herring, Philipp Zabel, Emilio López, Vishnu Patekar, devic...@vger.kernel.org, linux-ar...@lists.infradead.org, linux-...@vger.kernel.org, linux...@googlegroups.com, Reinder E.N. de Haan, zhao_...@263.net
>>>>> "Hans" == Hans de Goede <hdeg...@redhat.com> writes:

Hi,

> 2) I see no pmic code in there. I know these boards do not use an axp pmic,
> but according to my info at least the Orange Pi 2 (which I have) uses a
> sy8106a pmic, it is not entirely clear to me yet if this one needs any
> init though, I've mailed the Orange Pi people about this.

Did you hear back from them? I haven't been able to find any datasheet
describing the i2c interface, but the orange pi pc schematics has a note
that Vout is defined by the Ru1 / Ru2 resistors, so it sounds like i2c
configuration isn't critical to get something running.

--
Bye, Peter Korsgaard

Mihail Tommonen

unread,
Oct 27, 2015, 5:34:06 PM10/27/15
to linux-sunxi, hdeg...@redhat.com, jens...@gmail.com, maxime...@free-electrons.com, we...@csie.org, linus....@linaro.org, rob...@kernel.org, p.z...@pengutronix.de, emi...@elopez.com.ar, vishnupa...@gmail.com, devic...@vger.kernel.org, linux-ar...@lists.infradead.org, linux-...@vger.kernel.org, rei...@mveas.com, zhao_...@263.net, pe...@korsgaard.com
I have a feeling that sy8106a could be related to Silergy other pmics. Maybe something custom made, with special voltage, i2c address etc.


-Miskab

Julian Calaby

unread,
Oct 27, 2015, 7:12:34 PM10/27/15
to Jens Kuske, Maxime Ripard, Chen-Yu Tsai, Michael Turquette, Linus Walleij, Rob Herring, Philipp Zabel, Emilio López, Vishnu Patekar, Hans de Goede, devicetree, Mailing List, Arm, linux-...@vger.kernel.org, linux-sunxi
Hi Jens,
A way to make this reusable in the future might be to encode it in a
structure like:

static const struct bus_clock_paths sun8i_h3_bus_clock_paths __initdata = {
{.parent = 2, .min = 17, .max = 17}, /* index 17 is from AHB2 */
{.parent = 2, .min = 29, .max = 31}, /* AHB2 bank */
{.parent = 1, .min = 63, .max = 128}, /* AHB1 bank */
...
{}
};

Then the code here can be reused for other clocks like this in the
future without too much bloat. (And this would potentially could be
generic enough for other platforms.)

zhao_steven

unread,
Oct 28, 2015, 5:51:43 AM10/28/15
to Peter Korsgaard, Hans de Goede, Jens Kuske, Maxime Ripard, Chen-Yu Tsai, Linus Walleij, Rob Herring, Philipp Zabel, EmilioLópez, Vishnu Patekar, devicetree, linux-arm-kernel, linux-kernel, linux-sunxi, Reinder E.N. de Haan
Dear all,
     SY8106 datasheet. 

steven
SY8106A_datasheet.pdf

Philipp Zabel

unread,
Oct 28, 2015, 7:42:52 AM10/28/15
to Jens Kuske, Maxime Ripard, Chen-Yu Tsai, Michael Turquette, Linus Walleij, Rob Herring, Emilio López, Vishnu Patekar, Hans de Goede, devic...@vger.kernel.org, linux-ar...@lists.infradead.org, linux-...@vger.kernel.org, linux...@googlegroups.com
Hi Jens,

Am Dienstag, den 27.10.2015, 17:50 +0100 schrieb Jens Kuske:
[...]
> --- a/drivers/reset/reset-sunxi.c
> +++ b/drivers/reset/reset-sunxi.c
> @@ -75,7 +75,9 @@ static struct reset_control_ops sunxi_reset_ops = {
> .deassert = sunxi_reset_deassert,
> };
>
> -static int sunxi_reset_init(struct device_node *np)
> +static int sunxi_reset_init(struct device_node *np,
> + int (*of_xlate)(struct reset_controller_dev *rcdev,
> + const struct of_phandle_args *reset_spec))

I'd add a tab to the indentation and drop the of_xlate parameter names.
If you agree to this change, I'll fix it up when I apply it.

best regards
Philipp

Chen-Yu Tsai

unread,
Oct 30, 2015, 3:33:30 AM10/30/15
to Jens Kuske, Maxime Ripard, Chen-Yu Tsai, Michael Turquette, Linus Walleij, Rob Herring, Philipp Zabel, Emilio López, Vishnu Patekar, Hans de Goede, devicetree, linux-arm-kernel, linux-kernel, linux-sunxi
Hi,
What's the extra "pll6d2"? If you have an extra output, it's not compatible with
"allwinner,sun6i-a31-pll6-clk".
And this would be wrong if you don't update the pll6 compatible or driver.
There's no output on n = 2.

You could also chain a fixed divider directly in the driver.
ahb1_ehci1? Same for the following 3 lines.

> + "ahb1_ehic2", "ahb1_ehic3",
> + "ahb1_otg_ohci0", "ahb2_ohic1",
> + "ahb2_ohic2", "ahb2_ohic3", "ahb1_ve",
> + "ahb1_lcd0", "ahb1_lcd1", "ahb1_deint",
> + "ahb1_csi", "ahb1_tve", "ahb1_hdmi",
> + "ahb1_de", "ahb1_gpu", "ahb1_msgbox",
> + "ahb1_spinlock", "apb1_codec",
> + "apb1_spdif", "apb1_pio", "apb1_ths",
> + "apb1_i2s0", "apb1_i2s1", "apb1_i2s2",
> + "apb2_i2c0", "apb2_i2c1", "apb2_i2c2",
> + "apb2_uart0", "apb2_uart1",
> + "apb2_uart2", "apb2_uart3", "apb2_scr",
> + "ahb1_ephy", "ahb1_dbg";

If it weren't for the last 2 clocks, we could cleanly split out apb1 and apb2
gates. Having a separate AHB clock gate taking 2 addresses seems messy
as well. :(
This should be in the board DTS, unless this is the reference design,
in which case you should name the label like "mmc0_cd_pin_reference_design".
Aren't you handling the holes in the bus_rst driver? If so,
isn't it supposed to align both bus_gates and bus_rst indexes?

Same for the other UARTs.

Thanks

Regards
ChenYu

Chen-Yu Tsai

unread,
Oct 30, 2015, 3:46:53 AM10/30/15
to Jens Kuske, Maxime Ripard, Chen-Yu Tsai, Michael Turquette, Linus Walleij, Rob Herring, Philipp Zabel, Emilio López, Vishnu Patekar, Hans de Goede, devicetree, linux-arm-kernel, linux-kernel, linux-sunxi
On Wed, Oct 28, 2015 at 12:50 AM, Jens Kuske <jens...@gmail.com> wrote:
> Currently, the sunxi clock driver gets the name for the base factor clock
> of divs clocks from the name field in factors_data. This prevents reusing
> of the factor clock for clocks with same properties, but different name.
>
> This commit makes the divs setup function try to get a name from
> clock-output-names in the devicetree. It also removes the name field where
> possible and merges the sun4i PLL5 and PLL6 clocks.

This patch actually removes all static declarations of the name field,
which is a good thing!
This actually only works for the sun4i divs clocks. sun6i-a31-pll6 uses a
different naming convention. sun4i-a10-pll2 uses yet another, though that's
not a divs clock. Maybe we should work on unifying them. Maxime?

Other than these 2 bits of information, this patch looks good.


Regards
ChenYu

Chen-Yu Tsai

unread,
Oct 30, 2015, 4:08:51 AM10/30/15
to Jens Kuske, Maxime Ripard, Chen-Yu Tsai, Michael Turquette, Linus Walleij, Rob Herring, Philipp Zabel, Emilio López, Vishnu Patekar, Hans de Goede, devicetree, linux-arm-kernel, linux-kernel, linux-sunxi
Hi,

On Wed, Oct 28, 2015 at 12:50 AM, Jens Kuske <jens...@gmail.com> wrote:
<snip>

> + SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 0),
> + SUNXI_FUNCTION(0x0, "gpio_in"),
> + SUNXI_FUNCTION(0x1, "gpio_out"),
> + SUNXI_FUNCTION(0x2, "emac")), /* RXD3 */
> + SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 1),
> + SUNXI_FUNCTION(0x0, "gpio_in"),
> + SUNXI_FUNCTION(0x1, "gpio_out"),
> + SUNXI_FUNCTION(0x2, "emac")), /* RXD2 */
> + SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 2),
> + SUNXI_FUNCTION(0x0, "gpio_in"),
> + SUNXI_FUNCTION(0x1, "gpio_out"),
> + SUNXI_FUNCTION(0x2, "emac")), /* RXD1 */
> + SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 3),
> + SUNXI_FUNCTION(0x0, "gpio_in"),
> + SUNXI_FUNCTION(0x1, "gpio_out"),
> + SUNXI_FUNCTION(0x2, "emac")), /* RXD0 */
> + SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 4),
> + SUNXI_FUNCTION(0x0, "gpio_in"),
> + SUNXI_FUNCTION(0x1, "gpio_out"),
> + SUNXI_FUNCTION(0x2, "emac")), /* RXCK */
> + SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 5),
> + SUNXI_FUNCTION(0x0, "gpio_in"),
> + SUNXI_FUNCTION(0x1, "gpio_out"),
> + SUNXI_FUNCTION(0x2, "emac")), /* RXCTL/RCDV */

RXDV?

> + SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 6),
> + SUNXI_FUNCTION(0x0, "gpio_in"),
> + SUNXI_FUNCTION(0x1, "gpio_out"),
> + SUNXI_FUNCTION(0x2, "emac")), /* RXERR */
> + SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 7),
> + SUNXI_FUNCTION(0x0, "gpio_in"),
> + SUNXI_FUNCTION(0x1, "gpio_out"),
> + SUNXI_FUNCTION(0x2, "emac")), /* TXD3 */
> + SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 8),
> + SUNXI_FUNCTION(0x0, "gpio_in"),
> + SUNXI_FUNCTION(0x1, "gpio_out"),
> + SUNXI_FUNCTION(0x2, "emac")), /* TXD2L */

Trailing "L" there.

> + SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 9),
> + SUNXI_FUNCTION(0x0, "gpio_in"),
> + SUNXI_FUNCTION(0x1, "gpio_out"),
> + SUNXI_FUNCTION(0x2, "emac")), /* TXD1 */

<snip>

> + SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 0),
> + SUNXI_FUNCTION(0x0, "gpio_in"),
> + SUNXI_FUNCTION(0x1, "gpio_out"),
> + SUNXI_FUNCTION(0x2, "mmc1"), /* CLK */
> + SUNXI_FUNCTION_IRQ_BANK(0x4, 1, 0)), /* PG_EINT0 */

Datasheet say EINT is function 0x6. Same for all the other pins in group G.
The rest looks good. Thanks!


Regards
ChenYu

Arnd Bergmann

unread,
Oct 30, 2015, 4:27:19 AM10/30/15
to linux-ar...@lists.infradead.org, Jens Kuske, Maxime Ripard, Chen-Yu Tsai, Michael Turquette, Linus Walleij, Rob Herring, Philipp Zabel, Emilio López, devic...@vger.kernel.org, Vishnu Patekar, linux-...@vger.kernel.org, Hans de Goede, linux...@googlegroups.com
On Tuesday 27 October 2015 17:50:24 Jens Kuske wrote:
>
> +static int sun8i_h3_bus_reset_xlate(struct reset_controller_dev *rcdev,
> + const struct of_phandle_args *reset_spec)
> +{
> + unsigned int index = reset_spec->args[0];
> +
> + if (index < 96)
> + return index;
> + else if (index < 128)
> + return index + 32;
> + else if (index < 160)
> + return index + 64;
> + else
> + return -EINVAL;
> +}
> +
>

This looks like you are doing something wrong and should either
put the actual number into DT, or use a two-cell representation,
with the first cell indicating the block (0, 1 or 2), and the
second cell the index.

Arnd

Arnd Bergmann

unread,
Oct 30, 2015, 4:29:06 AM10/30/15
to linux-ar...@lists.infradead.org, Jens Kuske, Maxime Ripard, Chen-Yu Tsai, Michael Turquette, Linus Walleij, Rob Herring, Philipp Zabel, Emilio López, devic...@vger.kernel.org, Vishnu Patekar, linux-...@vger.kernel.org, Hans de Goede, linux...@googlegroups.com
On Tuesday 27 October 2015 17:50:22 Jens Kuske wrote:
> + of_property_read_string_index(node, "clock-output-names",
> + i, &clk_name);
> +
> + if (index == 17 || (index >= 29 && index <= 31))
> + clk_parent = AHB2;
> + else if (index <= 63 || index >= 128)
> + clk_parent = AHB1;
> + else if (index >= 64 && index <= 95)
> + clk_parent = APB1;
> + else if (index >= 96 && index <= 127)
> + clk_parent = APB2;
> +
> + clk_reg = reg + 4 * (index / 32);
>

Same as for the reset driver, this probably means you should have one
cell to indicate which bus it is for, and another cell for the
index.

Arnd

Jean-Francois Moine

unread,
Oct 30, 2015, 6:34:48 AM10/30/15
to Jens Kuske, Maxime Ripard, Chen-Yu Tsai, Michael Turquette, Linus Walleij, Rob Herring, Philipp Zabel, Emilio López, devic...@vger.kernel.org, Vishnu Patekar, linux-...@vger.kernel.org, Hans de Goede, linux...@googlegroups.com, linux-ar...@lists.infradead.org
On Tue, 27 Oct 2015 17:50:25 +0100
Jens Kuske <jens...@gmail.com> wrote:

> The Allwinner H3 is a home entertainment system oriented SoC with
> four Cortex-A7 cores and a Mali-400MP2 GPU.
>
> Signed-off-by: Jens Kuske <jens...@gmail.com>
> ---
> arch/arm/boot/dts/sun8i-h3.dtsi | 482 ++++++++++++++++++++++++++++++++++++++++
> 1 file changed, 482 insertions(+)
> create mode 100644 arch/arm/boot/dts/sun8i-h3.dtsi
>
> diff --git a/arch/arm/boot/dts/sun8i-h3.dtsi b/arch/arm/boot/dts/sun8i-h3.dtsi
> new file mode 100644
> index 0000000..c18b5f7
> --- /dev/null
> +++ b/arch/arm/boot/dts/sun8i-h3.dtsi
[snip]
> + soc {
> + compatible = "simple-bus";
> + #address-cells = <1>;
> + #size-cells = <1>;
> + ranges;
> +
> + dma: dma-controller@01c02000 {
> + compatible = "allwinner,sun8i-h3-dma";
> + reg = <0x01c02000 0x1000>;
> + interrupts = <GIC_SPI 50 IRQ_TYPE_LEVEL_HIGH>;
> + clocks = <&bus_gates 6>;
> + resets = <&bus_rst 6>;
> + #dma-cells = <1>;
> + };
[snip]
> +
> + bus_rst: reset@01c202c0 {
> + #reset-cells = <1>;
> + compatible = "allwinner,sun8i-h3-bus-reset";
> + reg = <0x01c202c0 0x1c>;
> + };
> +
[snip]
> + uart0: serial@01c28000 {
> + compatible = "snps,dw-apb-uart";
> + reg = <0x01c28000 0x400>;
> + interrupts = <GIC_SPI 0 IRQ_TYPE_LEVEL_HIGH>;
> + reg-shift = <2>;
> + reg-io-width = <4>;
> + clocks = <&bus_gates 112>;
> + resets = <&bus_rst 144>;
> + dmas = <&dma 6>, <&dma 6>;
> + dma-names = "rx", "tx";
> + status = "disabled";
> + };

The reset definitions would be clearer with declarations as the other
Allwinner SoCs and without driver hack:

soc {
compatible = "simple-bus";
#address-cells = <1>;
#size-cells = <1>;
ranges;

dma: dma-controller@01c02000 {
compatible = "allwinner,sun8i-h3-dma";
reg = <0x01c02000 0x1000>;
interrupts = <GIC_SPI 50 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&bus_gates 6>;
resets = <&rst_reg0 6>;
#dma-cells = <1>;
};
...
rst_reg0: reset@01c202c0 {
#reset-cells = <1>;
compatible = "allwinner,sun6i-a31-clock-reset";
reg = <0x01c202c0 0x04>;
};
...
rst_reg4: reset@01c202d8 {
#reset-cells = <1>;
compatible = "allwinner,sun6i-a31-clock-reset";
reg = <0x01c202d8 0x04>;
};
...
uart0: serial@01c28000 {
compatible = "snps,dw-apb-uart";
reg = <0x01c28000 0x400>;
interrupts = <GIC_SPI 0 IRQ_TYPE_LEVEL_HIGH>;
reg-shift = <2>;
reg-io-width = <4>;
clocks = <&bus_gates 112>;
resets = <&rst_reg4 16>;
dmas = <&dma 6>, <&dma 6>;
dma-names = "rx", "tx";
status = "disabled";
};

Maxime Ripard

unread,
Nov 1, 2015, 4:46:14 AM11/1/15
to Chen-Yu Tsai, Jens Kuske, Michael Turquette, Linus Walleij, Rob Herring, Philipp Zabel, Emilio López, Vishnu Patekar, Hans de Goede, devicetree, linux-arm-kernel, linux-kernel, linux-sunxi
Hi,

On Fri, Oct 30, 2015 at 03:33:05PM +0800, Chen-Yu Tsai wrote:
> > + pll6: clk@01c20028 {
> > + #clock-cells = <1>;
> > + compatible = "allwinner,sun6i-a31-pll6-clk";
> > + reg = <0x01c20028 0x4>;
> > + clocks = <&osc24M>;
> > + clock-output-names = "pll6", "pll6x2", "pll6d2";
>
> What's the extra "pll6d2"? If you have an extra output, it's not compatible with
> "allwinner,sun6i-a31-pll6-clk".

[...]

> > +
> > + ahb2: ahb2_clk@01c2005c {
> > + #clock-cells = <0>;
> > + compatible = "allwinner,sun8i-h3-ahb2-clk";
> > + reg = <0x01c2005c 0x4>;
> > + clocks = <&ahb1>, <&pll6 2>;
>
> And this would be wrong if you don't update the pll6 compatible or driver.
> There's no output on n = 2.
>
> You could also chain a fixed divider directly in the driver.

Or in the DT directly.

I'd really like to move away from the various fixed dividers output
that prevents to reuse the clock drivers when it's the only
difference, like what's done here.
Not really, the last reset registers don't have the same organization
than the bus clocks :/

Maxime

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

Maxime Ripard

unread,
Nov 1, 2015, 4:49:07 AM11/1/15
to Jens Kuske, Chen-Yu Tsai, Michael Turquette, Linus Walleij, Rob Herring, Philipp Zabel, Emilio López, Vishnu Patekar, Hans de Goede, devic...@vger.kernel.org, linux-ar...@lists.infradead.org, linux-...@vger.kernel.org, linux...@googlegroups.com
Hi,
Having the bus clocks called bus_* would make more sense I guess, or
at least it would match the datasheet names (as obscure as they are).

Thanks!
signature.asc

Jens Kuske

unread,
Nov 1, 2015, 8:40:43 AM11/1/15
to Arnd Bergmann, linux-ar...@lists.infradead.org, Maxime Ripard, Chen-Yu Tsai, Michael Turquette, Linus Walleij, Rob Herring, Philipp Zabel, Emilio López, devic...@vger.kernel.org, Vishnu Patekar, linux-...@vger.kernel.org, Hans de Goede, linux...@googlegroups.com
Hi,
This is what Maxime suggested in an earlier version:
http://lists.infradead.org/pipermail/linux-arm-kernel/2015-May/344213.html

In between I had another version with the parents in DT, but he
didn't like that too.

Jens

Jens Kuske

unread,
Nov 1, 2015, 8:40:49 AM11/1/15
to Chen-Yu Tsai, Maxime Ripard, Michael Turquette, Linus Walleij, Rob Herring, Philipp Zabel, Emilio López, Vishnu Patekar, Hans de Goede, devicetree, linux-arm-kernel, linux-kernel, linux-sunxi
On 30/10/15 08:46, Chen-Yu Tsai wrote:
> On Wed, Oct 28, 2015 at 12:50 AM, Jens Kuske <jens...@gmail.com> wrote:
[..]
>> @@ -991,8 +985,30 @@ static void __init sunxi_divs_clk_setup(struct device_node *node,
>> if (data->ndivs)
>> ndivs = data->ndivs;
>>
>> + /* Try to find a name for base factor clock */
>> + for (i = 0; i < ndivs; i++) {
>> + if (data->div[i].self) {
>> + of_property_read_string_index(node, "clock-output-names",
>> + i, &factors.name);
>> + break;
>> + }
>> + }
>> + /* If we don't have a .self clk use the first output-name up to '_' */
>
> This actually only works for the sun4i divs clocks. sun6i-a31-pll6 uses a
> different naming convention. sun4i-a10-pll2 uses yet another, though that's
> not a divs clock. Maybe we should work on unifying them. Maxime?

All the divs clocks I could find either have a .self (handled by the
first case above) or follow this naming convention, so it should work.
But if we find a better way to clean up the divs without breaking
devicetree bindings (as far as I understood we must not break them, am I
right there?) I'd be happy with that too.

Jens

Jens Kuske

unread,
Nov 1, 2015, 8:40:53 AM11/1/15
to Arnd Bergmann, linux-ar...@lists.infradead.org, Maxime Ripard, Chen-Yu Tsai, Michael Turquette, Linus Walleij, Rob Herring, Philipp Zabel, Emilio López, devic...@vger.kernel.org, Vishnu Patekar, linux-...@vger.kernel.org, Hans de Goede, linux...@googlegroups.com
Hi,
I tried to fix up the somewhat strange register layout here.

>From the datasheet:
BUS_SOFT_RST_REG0 0x02C0 Bus Software Reset Register 0
BUS_SOFT_RST_REG1 0x02C4 Bus Software Reset Register 1
BUS_SOFT_RST_REG2 0x02C8 Bus Software Reset Register 2
BUS_SOFT_RST_REG3 0x02D0 Bus Software Reset Register 3
BUS_SOFT_RST_REG4 0x02D8 Bus Software Reset Register 4

0x2cc and 0x2d4 are unused for some reason, but the regs are named 0-4,
so it lead to some confusion with the actual numbers in DT.
If we shouldn't do this I would be ok with putting the actual number
into DT too.

Jens

Jens Kuske

unread,
Nov 1, 2015, 8:40:53 AM11/1/15
to Chen-Yu Tsai, Maxime Ripard, Michael Turquette, Linus Walleij, Rob Herring, Philipp Zabel, Emilio López, Vishnu Patekar, Hans de Goede, devicetree, linux-arm-kernel, linux-kernel, linux-sunxi
Thanks. I had checked the whole list at least three times, but one
always overlooks something it seems.

Jens Kuske

unread,
Nov 1, 2015, 8:40:56 AM11/1/15
to Chen-Yu Tsai, Maxime Ripard, Michael Turquette, Linus Walleij, Rob Herring, Philipp Zabel, Emilio López, Vishnu Patekar, Hans de Goede, devicetree, linux-arm-kernel, linux-kernel, linux-sunxi
Hi,
I'll fix them...
>
>> + "ahb1_ehic2", "ahb1_ehic3",
>> + "ahb1_otg_ohci0", "ahb2_ohic1",
>> + "ahb2_ohic2", "ahb2_ohic3", "ahb1_ve",
>> + "ahb1_lcd0", "ahb1_lcd1", "ahb1_deint",
>> + "ahb1_csi", "ahb1_tve", "ahb1_hdmi",
>> + "ahb1_de", "ahb1_gpu", "ahb1_msgbox",
>> + "ahb1_spinlock", "apb1_codec",
>> + "apb1_spdif", "apb1_pio", "apb1_ths",
>> + "apb1_i2s0", "apb1_i2s1", "apb1_i2s2",
>> + "apb2_i2c0", "apb2_i2c1", "apb2_i2c2",
>> + "apb2_uart0", "apb2_uart1",
>> + "apb2_uart2", "apb2_uart3", "apb2_scr",
>> + "ahb1_ephy", "ahb1_dbg";
>
> If it weren't for the last 2 clocks, we could cleanly split out apb1 and apb2
> gates. Having a separate AHB clock gate taking 2 addresses seems messy
> as well. :(

Well, maybe we still should do that, if we split the resets too at least
apb[12] would line up again.

I don't know what to do with these bus things any more, all variants I
sent had issues somewhere...
The datasheet mentions SDC0_DET function on PF6, so I thought this is
sort of fixed to this pin now. All designs I've seen use this pin.

Jens

Chen-Yu Tsai

unread,
Nov 1, 2015, 10:26:11 AM11/1/15
to Jens Kuske, Chen-Yu Tsai, Maxime Ripard, Michael Turquette, Linus Walleij, Rob Herring, Philipp Zabel, Emilio López, Vishnu Patekar, Hans de Goede, devicetree, linux-arm-kernel, linux-kernel, linux-sunxi
As someone who's done this a few times, I can say that it all starts
to look the same after a few rounds. :)

ChenYu

Maxime Ripard

unread,
Nov 1, 2015, 1:36:11 PM11/1/15
to Jens Kuske, Chen-Yu Tsai, Michael Turquette, Linus Walleij, Rob Herring, Philipp Zabel, Emilio López, Vishnu Patekar, Hans de Goede, devic...@vger.kernel.org, linux-ar...@lists.infradead.org, linux-...@vger.kernel.org, linux...@googlegroups.com
On Tue, Oct 27, 2015 at 05:50:25PM +0100, Jens Kuske wrote:
> + timer {
> + compatible = "arm,armv7-timer";
> + interrupts = <GIC_PPI 13 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
> + <GIC_PPI 14 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
> + <GIC_PPI 11 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
> + <GIC_PPI 10 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>;
> + clock-frequency = <24000000>;
> + arm,cpu-registers-not-fw-configured;
> + };
> +
> + memory {
> + reg = <0x40000000 0x80000000>;
> + };

What's the u-boot support like these days?

If it's ready, or at least some patches have been sent, you shouldn't
set both the memory node (that will be overriden anyway) and the
clock-frequency and arm,cpu-registers-not-fw-configured properties in
the timer node, that will prevent the kernel from booting there.
signature.asc

Maxime Ripard

unread,
Nov 4, 2015, 11:24:03 AM11/4/15
to Julian Calaby, Jens Kuske, Chen-Yu Tsai, Michael Turquette, Linus Walleij, Rob Herring, Philipp Zabel, Emilio López, Vishnu Patekar, Hans de Goede, devicetree, Mailing List, Arm, linux-...@vger.kernel.org, linux-sunxi
Hi Julian,

On Wed, Oct 28, 2015 at 10:12:09AM +1100, Julian Calaby wrote:
> > + of_property_for_each_u32(node, "clock-indices", prop, p, index) {
> > + of_property_read_string_index(node, "clock-output-names",
> > + i, &clk_name);
> > +
> > + if (index == 17 || (index >= 29 && index <= 31))
> > + clk_parent = AHB2;
> > + else if (index <= 63 || index >= 128)
> > + clk_parent = AHB1;
> > + else if (index >= 64 && index <= 95)
> > + clk_parent = APB1;
> > + else if (index >= 96 && index <= 127)
> > + clk_parent = APB2;
>
> A way to make this reusable in the future might be to encode it in a
> structure like:
>
> static const struct bus_clock_paths sun8i_h3_bus_clock_paths __initdata = {
> {.parent = 2, .min = 17, .max = 17}, /* index 17 is from AHB2 */
> {.parent = 2, .min = 29, .max = 31}, /* AHB2 bank */
> {.parent = 1, .min = 63, .max = 128}, /* AHB1 bank */
> ...
> {}
> };
>
> Then the code here can be reused for other clocks like this in the
> future without too much bloat. (And this would potentially could be
> generic enough for other platforms.)

We don't really need that at the moment. There's not point in writing
more complicated code to support a use case we don't have yet.

(However, something along these lines will definitely be needed if we
ever have another SoC having the same bus gates madness)
signature.asc

Maxime Ripard

unread,
Nov 4, 2015, 11:25:29 AM11/4/15
to Arnd Bergmann, linux-ar...@lists.infradead.org, Jens Kuske, Chen-Yu Tsai, Michael Turquette, Linus Walleij, Rob Herring, Philipp Zabel, Emilio López, devic...@vger.kernel.org, Vishnu Patekar, linux-...@vger.kernel.org, Hans de Goede, linux...@googlegroups.com
Hi Arnd,
It's not really comparable to the reset driver.

What's happening here is that we have a single set of (contiguous)
registers, controlling gates from different parents.
signature.asc

Maxime Ripard

unread,
Nov 4, 2015, 12:19:43 PM11/4/15
to Arnd Bergmann, linux-ar...@lists.infradead.org, Jens Kuske, Chen-Yu Tsai, Michael Turquette, Linus Walleij, Rob Herring, Philipp Zabel, Emilio López, devic...@vger.kernel.org, Vishnu Patekar, linux-...@vger.kernel.org, Hans de Goede, linux...@googlegroups.com
Hi Arnd,

On Fri, Oct 30, 2015 at 09:27:03AM +0100, Arnd Bergmann wrote:
> On Tuesday 27 October 2015 17:50:24 Jens Kuske wrote:
> >
> > +static int sun8i_h3_bus_reset_xlate(struct reset_controller_dev *rcdev,
> > + const struct of_phandle_args *reset_spec)
> > +{
> > + unsigned int index = reset_spec->args[0];
> > +
> > + if (index < 96)
> > + return index;
> > + else if (index < 128)
> > + return index + 32;
> > + else if (index < 160)
> > + return index + 64;
> > + else
> > + return -EINVAL;
> > +}
> > +
> >
>
> This looks like you are doing something wrong and should either
> put the actual number into DT,

This is the actual number, except that there's some useless registers
in between. Allwinner documents it like that:

0x0 Reset 0
0x4 Reset 1
0xc Reset 2

So we have to adjust the offset to account with the blank register in
between (0x8).

> or use a two-cell representation, with the first cell indicating the
> block (0, 1 or 2), and the second cell the index.

And the missing register is not a block either.

That would also imply either changing the bindings of that driver (and
all the current DTS that are using it), or introducing a whole new
driver just to deal with some extraordinary offset calculation.
signature.asc

Julian Calaby

unread,
Nov 4, 2015, 5:18:09 PM11/4/15
to Maxime Ripard, Jens Kuske, Chen-Yu Tsai, Michael Turquette, Linus Walleij, Rob Herring, Philipp Zabel, Emilio López, Vishnu Patekar, Hans de Goede, devicetree, Mailing List, Arm, linux-...@vger.kernel.org, linux-sunxi
Hi Maxime,
This was a suggestion for the future to address Jens' comment about
having a bus clock driver instead of encoding it in devicetree.

Jean-Francois Moine

unread,
Nov 5, 2015, 1:47:37 AM11/5/15
to Maxime Ripard, Arnd Bergmann, devic...@vger.kernel.org, Vishnu Patekar, Emilio López, Michael Turquette, linux...@googlegroups.com, linux-...@vger.kernel.org, Hans de Goede, Chen-Yu Tsai, Rob Herring, Jens Kuske, Philipp Zabel, Linus Walleij, linux-ar...@lists.infradead.org
In the H3, the holes are not used, but what would occur if these holes
would be used for some other purpose in future SoCs? Double mapping?

Siarhei Siamashka

unread,
Nov 10, 2015, 10:40:30 PM11/10/15
to jens...@gmail.com, Hans de Goede, Maxime Ripard, Chen-Yu Tsai, Emilio López, Vishnu Patekar, linux...@googlegroups.com, Reinder E.N. de Haan, zhao_...@263.net
On Thu, 22 Oct 2015 13:52:38 +0200
Jens Kuske <jens...@gmail.com> wrote:

>
> On 22/10/15 10:49, Hans de Goede wrote:
> > Hi,
> >
> > On 22-10-15 09:49, Jens Kuske wrote:
> [..]
> >>
> >> I don't plan to work on USB soon, my next step would have been Ethernet
> >> and finishing the basic u-boot support. You know my u-boot H3 wip tree I
> >> hope? Before we duplicate our work there too...
> >> https://github.com/jemk/u-boot-sunxi/tree/sunxi/h3
> >
> > I was not aware of that work, at a first glance it looks good. Can you rebase
> > this on top of current u-boot/master (or v2015.10) and then submit it upstream ?
>
> I will, after fixing some more things (like your question 2).

FYI, this branch works mostly OK on my freshly bought Orange Pi PC
board. I only had to reduce the DRAM clock speed from 672MHz to 480MHz
to prevent the kernel from oopsing.

But when the DRAM is initialized by boot0, 672MHz seems to work without
obviously visible problems.

I will try to debug this problem and compare the configuration in the
DRAM controller hardware registers. The FEX files seem to imply that
the DRAM settings should be the same on all H3 based Orange boards,
but there might be still some deliberate difference in the configuration
or a subtle bug in your code.

> > 2 questions which come to mind immediately:
> >
> > 1) Where does the dram init logic come from, AFAIK Allwinner has not provided
> > any H3 dram init code ?
>
> It's from the Draco H3 TV Stick SDK:
>
> http://www.cnx-software.com/2015/06/14/tronsmart-draco-h3-tv-stick-firmware-and-sdk-released/

Could you please provide a bit more details about the location of this
code? I tried to download the SDK and looked around a bit. There are
some directories with the DRAM initialization code:

H3_SDK_20150601_lichee/brandy/basic_loader/bsp_for_a13
H3_SDK_20150601_lichee/brandy/basic_loader/bsp_for_a20
H3_SDK_20150601_lichee/brandy/basic_loader/bsp_for_a31
H3_SDK_20150601_lichee/brandy/basic_loader/bsp_for_a39
H3_SDK_20150601_lichee/brandy/basic_loader/bsp_for_a50
H3_SDK_20150601_lichee/brandy/basic_loader/bsp_for_a67
H3_SDK_20150601_lichee/brandy/basic_loader/bsp_for_a73
H3_SDK_20150601_lichee/brandy/basic_loader/bsp_for_a77
H3_SDK_20150601_lichee/brandy/basic_loader/bsp_for_a81
H3_SDK_20150601_lichee/brandy/basic_loader/bsp_for_i20

The names are a bit strange and nothing obviously looks like H3.
A quick search for some of the relatively unique magic constants
used in your code also was not very successful, but I did not try
too hard yet.

> > 2) I see no pmic code in there. I know these boards do not use an axp pmic,
> > but according to my info at least the Orange Pi 2 (which I have) uses a
> > sy8106a pmic, it is not entirely clear to me yet if this one needs any
> > init though, I've mailed the Orange Pi people about this.
>
> Correct, the CPU voltage is provided by a i2c controllable regulator (sy8106a)
> without any datasheet. I've found how to set the voltage in above SDK, but I
> first want test this carefully.
>
> There's also the problem that we have to use the OpenRISC core for power
> management (especially poweroff), since there is no external PMIC. This can
> be done later of course, but we should think about how to do it.

There was a SY8106A datasheet posted later in the mailing list. It
looks like at least on the Orange Pi PC the default voltage supplied
by SY8106A (and configured via a pair of resistors) is 1.2V which
seems to be safe for the CPU clock frequencies up to 1008MHz according
to the comments in the FEX file. I added some notes to the wiki page:

https://linux-sunxi.org/Orange_Pi_PC

Moreover, people in the Orange Pi forums seem to be complaining about
the SoC easily overheating without a heatsink. It means that enabling
the highest CPU clock speed may be not the brightest idea without
adding support for the temperature sensor first. So it looks like
configuring SY8106A is not the most important feature for the initial
H3 support in U-Boot and it can be postponed until a later date.

Though SY8106A retains the configured voltage after reboot and
the 3.4 kernel from the Allwinner's SDK can potentially reduce
it below 1.2V when sitting at the lowest operating points.
So this definitely has to be addressed eventually.

BTW, is anybody already planning to work on HDMI video support
for U-Boot?

--
Best regards,
Siarhei Siamashka

Hans de Goede

unread,
Nov 11, 2015, 5:05:51 AM11/11/15
to Siarhei Siamashka, jens...@gmail.com, Maxime Ripard, Chen-Yu Tsai, Emilio López, Vishnu Patekar, linux...@googlegroups.com, Reinder E.N. de Haan, zhao_...@263.net
Hi,

On 11-11-15 04:40, Siarhei Siamashka wrote:

> BTW, is anybody already planning to work on HDMI video support
> for U-Boot?

Not that I know of, the H3 (and other new SoCs) have a new display
output pipeline. So it is probably best to just start a whole
new u-boot display driver for this.

People who want to work on this can start with a copy of the existing
one, but I do not think that trying to add more #ifdef-s to the
existing driver for this whole new display pipeline is a good idea.

Allwinner's code for the display pipeline in the H3 can be found here:

https://github.com/allwinner-zh/bootloader/tree/master/u-boot-2011.09/drivers/video_sunxi/sunxi_v3

One option would be to diff this against the sunxi_v1 code, although the
difference may be so big that this gets one nowhere.

Regards,

Hans

Jens Kuske

unread,
Nov 11, 2015, 12:26:59 PM11/11/15
to Siarhei Siamashka, Hans de Goede, Maxime Ripard, Chen-Yu Tsai, Emilio López, Vishnu Patekar, linux...@googlegroups.com, Reinder E.N. de Haan, zhao_...@263.net
Hi Siarhei,

On 11/11/15 04:40, Siarhei Siamashka wrote:
> On Thu, 22 Oct 2015 13:52:38 +0200
> Jens Kuske <jens...@gmail.com> wrote:
>
>>
>> On 22/10/15 10:49, Hans de Goede wrote:
>>> Hi,
>>>
>>> On 22-10-15 09:49, Jens Kuske wrote:
>> [..]
>>>>
>>>> I don't plan to work on USB soon, my next step would have been Ethernet
>>>> and finishing the basic u-boot support. You know my u-boot H3 wip tree I
>>>> hope? Before we duplicate our work there too...
>>>> https://github.com/jemk/u-boot-sunxi/tree/sunxi/h3
>>>
>>> I was not aware of that work, at a first glance it looks good. Can you rebase
>>> this on top of current u-boot/master (or v2015.10) and then submit it upstream ?
>>
>> I will, after fixing some more things (like your question 2).
>
> FYI, this branch works mostly OK on my freshly bought Orange Pi PC
> board. I only had to reduce the DRAM clock speed from 672MHz to 480MHz
> to prevent the kernel from oopsing.
>
> But when the DRAM is initialized by boot0, 672MHz seems to work without
> obviously visible problems.
>
> I will try to debug this problem and compare the configuration in the
> DRAM controller hardware registers. The FEX files seem to imply that
> the DRAM settings should be the same on all H3 based Orange boards,
> but there might be still some deliberate difference in the configuration
> or a subtle bug in your code.

I'd guess it's the ZQ calibration that doesn't work correctly, see below why.
But since I have removed a lot of other code that wasn't used I might
accidentally destroyed something else too, but I have been very careful.

>
>>> 2 questions which come to mind immediately:
>>>
>>> 1) Where does the dram init logic come from, AFAIK Allwinner has not provided
>>> any H3 dram init code ?
>>
>> It's from the Draco H3 TV Stick SDK:
>>
>> http://www.cnx-software.com/2015/06/14/tronsmart-draco-h3-tv-stick-firmware-and-sdk-released/
>
> Could you please provide a bit more details about the location of this
> code? I tried to download the SDK and looked around a bit. There are
> some directories with the DRAM initialization code:
>
> H3_SDK_20150601_lichee/brandy/basic_loader/bsp_for_a13
> H3_SDK_20150601_lichee/brandy/basic_loader/bsp_for_a20
> H3_SDK_20150601_lichee/brandy/basic_loader/bsp_for_a31
> H3_SDK_20150601_lichee/brandy/basic_loader/bsp_for_a39
> H3_SDK_20150601_lichee/brandy/basic_loader/bsp_for_a50
> H3_SDK_20150601_lichee/brandy/basic_loader/bsp_for_a67
> H3_SDK_20150601_lichee/brandy/basic_loader/bsp_for_a73
> H3_SDK_20150601_lichee/brandy/basic_loader/bsp_for_a77
> H3_SDK_20150601_lichee/brandy/basic_loader/bsp_for_a81
> H3_SDK_20150601_lichee/brandy/basic_loader/bsp_for_i20
>
> The names are a bit strange and nothing obviously looks like H3.
> A quick search for some of the relatively unique magic constants
> used in your code also was not very successful, but I did not try
> too hard yet.

Based on some guessing and comparing with the parts I initially started
disassembling (before this SDK appeared), I think it's I20. The I20 dram
init code matched the disassembled parts exactly, except the ZQ
calibration part...
So, looks like it might not be correct to assume I20 == H3.

This is the ZQ calibration function I got by disassembling, but I dropped
it since the SDK version worked well too. Maybe I should have done the
opposite and drop the SDK...
It looks a bit strange, like if they are always calibrating the
first channel and then copying to the others, maybe there is some
hardware bug they work around.

static void mctl_zq_calibration(struct dram_para *para)
{
struct sunxi_mctl_ctl_reg * const mctl_ctl =
(struct sunxi_mctl_ctl_reg *)SUNXI_DRAM_CTL0_BASE;

int i;
u16 zq_val[6];
u32 reg_val, val;

mctl_dbg("ZQ calibration... ");

writel(0x0a0a0a0a, &mctl_ctl->zqdr[2]);

for (i = 0; i < 6; i++)
{
u8 zq = (CONFIG_DRAM_ZQ >> (i * 4)) & 0xf;

writel((zq << 20) | (zq << 16) | (zq << 12) |
(zq << 8) | (zq << 4) | (zq << 0),
&mctl_ctl->zqcr);

writel(PIR_CLRSR, &mctl_ctl->pir);
mctl_phy_init(PIR_ZCAL);

val = readl(&mctl_ctl->zqdr[0]) & 0xff;
writel((val << 24) | (val << 16) | (val << 8) | (val << 0), &mctl_ctl->zqdr[2]);

writel(PIR_CLRSR, &mctl_ctl->pir);
mctl_phy_init(PIR_ZCAL);

zq_val[i] = val | (bin_to_mgray(mgray_to_bin(readl(&mctl_ctl->zqdr[0]) >> 24) - 1) << 8);
}

writel((zq_val[1] << 16) | zq_val[0], &mctl_ctl->zqdr[0]);
writel((zq_val[3] << 16) | zq_val[2], &mctl_ctl->zqdr[1]);
writel((zq_val[5] << 16) | zq_val[4], &mctl_ctl->zqdr[2]);

mctl_dbg((mctl_ctl->zqsr & (1 << 30)) ? "ERROR\n" : "DONE\n");
}

And while trying to figure out what's the reason for this I used the
following debug function, it might help you if you want to debug ZQ cal:

static void dump_zq(void)
{
struct sunxi_mctl_ctl_reg * const mctl_ctl =
(struct sunxi_mctl_ctl_reg *)SUNXI_DRAM_CTL0_BASE;

int i;
static const char *mod[3] = { "control", "DX0/DX1", "DX2/DX3" };
static const char *error[4] = { "\t", "overflow",
"underflow", "in progress" };

printf("== ZQ calibration %s %s ==\n",
(mctl_ctl->zqsr & (1 << 31)) ? "DONE" : "",
(mctl_ctl->zqsr & (1 << 30)) ? "ERROR" : "");

printf("\tODT pull-up\tODT pull-down\tDRV pull-up\tDRV pull-down\n");

for (i = 0; i < 3; i++)
printf("%s\t%2u %s\t%2u %s\t%2u %s\t%2u %s\n", mod[i],
mgray_to_bin((mctl_ctl->zqdr[i] >> 24) & 0x1f),
error[(mctl_ctl->zqsr >> (i * 8 + 6)) & 0x3],
mgray_to_bin((mctl_ctl->zqdr[i] >> 16) & 0x1f),
error[(mctl_ctl->zqsr >> (i * 8 + 4)) & 0x3],
mgray_to_bin((mctl_ctl->zqdr[i] >> 8) & 0x1f),
error[(mctl_ctl->zqsr >> (i * 8 + 2)) & 0x3],
mgray_to_bin((mctl_ctl->zqdr[i] >> 0) & 0x1f),
error[(mctl_ctl->zqsr >> (i * 8 + 0)) & 0x3]);
}

I don't have the time to add more information now, but we can discuss this
later.

>
>>> 2) I see no pmic code in there. I know these boards do not use an axp pmic,
>>> but according to my info at least the Orange Pi 2 (which I have) uses a
>>> sy8106a pmic, it is not entirely clear to me yet if this one needs any
>>> init though, I've mailed the Orange Pi people about this.
>>
>> Correct, the CPU voltage is provided by a i2c controllable regulator (sy8106a)
>> without any datasheet. I've found how to set the voltage in above SDK, but I
>> first want test this carefully.
>>
>> There's also the problem that we have to use the OpenRISC core for power
>> management (especially poweroff), since there is no external PMIC. This can
>> be done later of course, but we should think about how to do it.
>
> There was a SY8106A datasheet posted later in the mailing list. It
> looks like at least on the Orange Pi PC the default voltage supplied
> by SY8106A (and configured via a pair of resistors) is 1.2V which
> seems to be safe for the CPU clock frequencies up to 1008MHz according
> to the comments in the FEX file. I added some notes to the wiki page:
>
> https://linux-sunxi.org/Orange_Pi_PC
>
> Moreover, people in the Orange Pi forums seem to be complaining about
> the SoC easily overheating without a heatsink. It means that enabling
> the highest CPU clock speed may be not the brightest idea

I think, based on the FEX file comments, everything above 1.2GHz is
overclocking, so we might shouldn't do this anyway.

> without
> adding support for the temperature sensor first. So it looks like
> configuring SY8106A is not the most important feature for the initial
> H3 support in U-Boot and it can be postponed until a later date.

I came to this conclusion in the meantime too, especially since I can't
really figure out how to write to this i2c bus in u-boot :D


Regards,
Jens

Siarhei Siamashka

unread,
Nov 13, 2015, 7:36:24 AM11/13/15
to Jens Kuske, Hans de Goede, Maxime Ripard, Chen-Yu Tsai, Emilio López, Vishnu Patekar, linux...@googlegroups.com, Reinder E.N. de Haan, zhao_...@263.net
On Wed, 11 Nov 2015 18:26:54 +0100
Jens Kuske <jens...@gmail.com> wrote:

> Based on some guessing and comparing with the parts I initially started
> disassembling (before this SDK appeared), I think it's I20. The I20 dram
> init code matched the disassembled parts exactly, except the ZQ
> calibration part...
> So, looks like it might not be correct to assume I20 == H3.

The magic constants in mctl_set_master_priority() seem to be a bit
different too. This explains why I could not find the matching code
in the SDK.

> This is the ZQ calibration function I got by disassembling, but I dropped
> it since the SDK version worked well too. Maybe I should have done the
> opposite and drop the SDK...

Agreed, it's safer to prefer the variant of code that is actually
used in production on real devices.
Thanks, using this implementation fixes the reliability problems at
672MHz on my Orange Pi PC board.

> And while trying to figure out what's the reason for this I used the
> following debug function, it might help you if you want to debug ZQ cal:
>
> static void dump_zq(void)
> {
> struct sunxi_mctl_ctl_reg * const mctl_ctl =
> (struct sunxi_mctl_ctl_reg *)SUNXI_DRAM_CTL0_BASE;
>
> int i;
> static const char *mod[3] = { "control", "DX0/DX1", "DX2/DX3" };
> static const char *error[4] = { "\t", "overflow",
> "underflow", "in progress" };
>
> printf("== ZQ calibration %s %s ==\n",
> (mctl_ctl->zqsr & (1 << 31)) ? "DONE" : "",
> (mctl_ctl->zqsr & (1 << 30)) ? "ERROR" : "");
>
> printf("\tODT pull-up\tODT pull-down\tDRV pull-up\tDRV pull-down\n");
>
> for (i = 0; i < 3; i++)
> printf("%s\t%2u %s\t%2u %s\t%2u %s\t%2u %s\n", mod[i],
> mgray_to_bin((mctl_ctl->zqdr[i] >> 24) & 0x1f),
> error[(mctl_ctl->zqsr >> (i * 8 + 6)) & 0x3],
> mgray_to_bin((mctl_ctl->zqdr[i] >> 16) & 0x1f),
> error[(mctl_ctl->zqsr >> (i * 8 + 4)) & 0x3],
> mgray_to_bin((mctl_ctl->zqdr[i] >> 8) & 0x1f),
> error[(mctl_ctl->zqsr >> (i * 8 + 2)) & 0x3],
> mgray_to_bin((mctl_ctl->zqdr[i] >> 0) & 0x1f),
> error[(mctl_ctl->zqsr >> (i * 8 + 0)) & 0x3]);
> }

With your original code from github I get:

== ZQ calibration DONE ERROR ==
ODT pull-up ODT pull-down DRV pull-up DRV pull-down
control 16 underflow 16 12 underflow 12
DX0/DX1 12 underflow 12 12 underflow 12
DX2/DX3 12 12 12 underflow 12

With the implementation from your e-mail I get:

== ZQ calibration DONE ==
ODT pull-up ODT pull-down DRV pull-up DRV pull-down
control 20 17 15 13
DX0/DX1 6 5 15 13
DX2/DX3 6 5 15 13



I'm going to try running lima-memtester on the device and also will
do a detailed review of your code by the end of the weekend. BTW, which
boot0 binary did you use as a reference? It might help to make sure
that we are actually looking at exactly the same thing.


And regarding the patchset itself. There are no conflicts when rebasing
it to v2015.10 and this newer version of U-Boot is preferable because
it has better FEL boot support (automatic 'boot.scr' handling). Also it
would be great to have these H3 patches posted to the U-Boot mailing
list, preferably a week ago while the merge window was still open :-)

Thanks for taking care of U-Boot, it works great so far.

Jens Kuske

unread,
Nov 13, 2015, 12:22:15 PM11/13/15
to Siarhei Siamashka, Hans de Goede, Maxime Ripard, Chen-Yu Tsai, Emilio López, Vishnu Patekar, linux...@googlegroups.com, Reinder E.N. de Haan, zhao_...@263.net
On 13/11/15 13:36, Siarhei Siamashka wrote:
> On Wed, 11 Nov 2015 18:26:54 +0100
> Jens Kuske <jens...@gmail.com> wrote:
>
>> Based on some guessing and comparing with the parts I initially started
>> disassembling (before this SDK appeared), I think it's I20. The I20 dram
>> init code matched the disassembled parts exactly, except the ZQ
>> calibration part...
>> So, looks like it might not be correct to assume I20 == H3.
>
> The magic constants in mctl_set_master_priority() seem to be a bit
> different too. This explains why I could not find the matching code
> in the SDK.

Indeed, didn't remember that.
Ok, I'll replace the SDK version then.
That looks *much* better :)

>
> I'm going to try running lima-memtester on the device and also will
> do a detailed review of your code by the end of the weekend. BTW, which
> boot0 binary did you use as a reference? It might help to make sure
> that we are actually looking at exactly the same thing.

If I remember correctly the libdram came from the SDK offered at the
orange pi downloads. I roughly compared it to the preinstalled android
boot0, it looked the same but had some symbols.
But I dropped most unused codepaths and tried to cleaned up a lot of magic.

>
> And regarding the patchset itself. There are no conflicts when rebasing
> it to v2015.10 and this newer version of U-Boot is preferable because
> it has better FEL boot support (automatic 'boot.scr' handling). Also it
> would be great to have these H3 patches posted to the U-Boot mailing
> list, preferably a week ago while the merge window was still open :-)

I have some more fixes waiting, but I think I can send them this weekend
(without regulator support).

Jens

Hans de Goede

unread,
Nov 15, 2015, 4:13:10 PM11/15/15
to Siarhei Siamashka, Jens Kuske, Maxime Ripard, Chen-Yu Tsai, Emilio López, Vishnu Patekar, linux...@googlegroups.com, Reinder E.N. de Haan, zhao_...@263.net
Hi,
Cool, note I've added Jens' (preliminary) patches to my
github/jwrdegoede/u-boot-sunxi/sunxi-wip branch, as having upstream u-boot
makes testing the kernel a lot easier.

I've replaced the mctl_zq_calibration function there with this one,
as well as did some other small fixes (to properly disable pmic
support with upstream u-boot master).

> Thanks for taking care of U-Boot, it works great so far.

Seconded, thanks a lot for this work Jens, and it works great for
me too.

Regards,

Hans

Chen-Yu Tsai

unread,
Nov 23, 2015, 2:42:17 AM11/23/15
to moi...@free.fr, Maxime Ripard, Arnd Bergmann, devicetree, Vishnu Patekar, Emilio López, Michael Turquette, linux-sunxi, linux-kernel, Hans de Goede, Chen-Yu Tsai, Rob Herring, Jens Kuske, Philipp Zabel, Linus Walleij, linux-arm-kernel
We'd have a different compatible string for it.

My suggestion for the resets is to just split them into 3 nodes: AHB
(since AHB1 and AHB2 devices are mixed together in the bunch), APB1,
and APB2 reset controls.

This follows what we have for existing SoCs, and gets rid of the unused
hole. We can use the existing "allwinner,sun6i-a31-clock-reset" and
"allwinner,sun6i-a31-ahb1-reset" compatibles.


Regards
ChenYu

Maxime Ripard

unread,
Nov 23, 2015, 3:57:22 AM11/23/15
to Jens Kuske, Chen-Yu Tsai, Michael Turquette, Linus Walleij, Rob Herring, Philipp Zabel, Emilio López, Vishnu Patekar, Hans de Goede, devicetree, linux-arm-kernel, linux-kernel, linux-sunxi
Hi,
AFAIK, Arnd had some objections, but he never got back to us when we
explained how the hardware was laid out, so I don't know if they still
apply.
Why is it set as a gpio then if it is a separate function?

Thanks!
signature.asc

Hans de Goede

unread,
Nov 23, 2015, 5:50:58 AM11/23/15
to maxime...@free-electrons.com, Jens Kuske, Chen-Yu Tsai, Michael Turquette, Linus Walleij, Rob Herring, Philipp Zabel, Emilio López, Vishnu Patekar, devicetree, linux-arm-kernel, linux-kernel, linux-sunxi
HI,
Hmm, not in my version, I've "Allwinner_H3_Datasheet_V1.0.pdf" and there
PF6 only has generic input / output functionality.

>> so I thought this is
>> sort of fixed to this pin now. All designs I've seen use this pin.
>
> Why is it set as a gpio then if it is a separate function?

I guess because we do not support this in the mmc driver yet. Also on
older devices the mmc controller has build-in card-detection features
(using the data lines in that case) but we've never supported this since
none of the boards sofar have been using it.

For now we can just treat PF6 as a gpio, until someone figures out how
to do this inside the mmc driver.

Regards,

Hans

Maxime Ripard

unread,
Nov 23, 2015, 6:29:28 AM11/23/15
to Chen-Yu Tsai, moi...@free.fr, Arnd Bergmann, devicetree, Vishnu Patekar, Emilio López, Michael Turquette, linux-sunxi, linux-kernel, Hans de Goede, Rob Herring, Jens Kuske, Philipp Zabel, Linus Walleij, linux-arm-kernel
Hi,
That seems a bit weird to have a single clock and split resets, but as
long as they are not mixed, and you can compute easily the id from the
datasheet, ok.
signature.asc

Jens Kuske

unread,
Nov 23, 2015, 11:25:44 AM11/23/15
to Hans de Goede, maxime...@free-electrons.com, Chen-Yu Tsai, Michael Turquette, Linus Walleij, Rob Herring, Philipp Zabel, Emilio López, Vishnu Patekar, devicetree, linux-arm-kernel, linux-kernel, linux-sunxi
Hm, indeed, it isn't mentioned in the Port Controller documentation, but
the table on page 76 (3.2. GPIO Multiplexing Functions) has it.

>
> >> so I thought this is
>>> sort of fixed to this pin now. All designs I've seen use this pin.
>>
>> Why is it set as a gpio then if it is a separate function?
>
> I guess because we do not support this in the mmc driver yet. Also on
> older devices the mmc controller has build-in card-detection features
> (using the data lines in that case) but we've never supported this since
> none of the boards sofar have been using it.
>
> For now we can just treat PF6 as a gpio, until someone figures out how
> to do this inside the mmc driver.

I could not find any documentation or reference how to use it, probably
because it doesn't exist...

Jens

Chen-Yu Tsai

unread,
Nov 23, 2015, 11:49:01 AM11/23/15
to Hans de Goede, Maxime Ripard, Jens Kuske, Chen-Yu Tsai, Michael Turquette, Linus Walleij, Rob Herring, Philipp Zabel, Emilio López, Vishnu Patekar, devicetree, linux-arm-kernel, linux-kernel, linux-sunxi
v1.1 has an "SDC0_DET" function for PF6 in the GPIO mux functions table.

>>> so I thought this is
>>>
>>> sort of fixed to this pin now. All designs I've seen use this pin.
>>
>>
>> Why is it set as a gpio then if it is a separate function?
>
>
> I guess because we do not support this in the mmc driver yet. Also on
> older devices the mmc controller has build-in card-detection features
> (using the data lines in that case) but we've never supported this since
> none of the boards sofar have been using it.

Unfortunately the H3 datasheet does not include a section for MMC.
I've requested the datasheet be publicly released with MMC and PRCM
sections included:

https://github.com/allwinner-zh/documents/issues/9

ChenYu

Siarhei Siamashka

unread,
Dec 9, 2015, 3:40:31 AM12/9/15
to Jens Kuske, Hans de Goede, Maxime Ripard, Chen-Yu Tsai, Emilio López, Vishnu Patekar, linux...@googlegroups.com, Reinder E.N. de Haan, zhao_...@263.net
On Fri, 13 Nov 2015 18:22:10 +0100
Thanks for the explanations. I finally got lima-memtester up and
running on H3 hardware (not that it was difficult, but just the amount
of unnecessary compatibility breaks in the H3 SDK kernel was a bit
unexpected and really discouraging, they are really doing almost
*everything* in a different way compared to A10/A20 SDK kernel just
for the sake of making things different):

https://github.com/ssvb/lima-memtester/releases/tag/20151207-orange-pi-pc-fel-test

Currently U-Boot v2016.01-rc2 fails the lima-memtester check unless
the DRAM clock speed is reduced to 456 MHz on my Orange Pi PC. But
if I use the boot0 bootloader to boot the same kernel image
(uImage-3.4-sun8i-h3-lima-memtester), then the test works fine.
This means that there must be still something wrong with the H3
DRAM init code in U-Boot, or maybe some clocks are wrong

While the investigation is ongoing, it might be a good idea to
temporarily reduce the DRAM clock speed in U-Boot as a workaround.
So that people are less likely to encounter reliability problems
when using U-Boot instead of boot0.

There is a lot of time before the U-boot v2016.01 release, so
everything should be fine. And I still owe you a review for the
H3 DRAM code.

Jens Kuske

unread,
Dec 9, 2015, 1:29:53 PM12/9/15
to Siarhei Siamashka, Hans de Goede, Maxime Ripard, Chen-Yu Tsai, Emilio López, Vishnu Patekar, linux...@googlegroups.com, Reinder E.N. de Haan, zhao_...@263.net
I tried to compare boot0 and the SDK source again and actually
found another difference.

The read delays (except for dqs) are doubled in boot0 before
writing them to the registers. Looks like they suddenly needed
higher values than possible with 4 bit. The register seems to
take 6 bit wide values.
After fixing that, lima-memtester doesn't fail at 672 MHz anymore
on my Orange Pi Plus. Before it failed at 552 and higher.
Patch below.

Maybe we could also replaced the setbits with writel, because I
don't see a good reason not to overwrite the registers, they are
all zero after reset and have 0x00003f3f mask.

Jens



diff --git a/arch/arm/cpu/armv7/sunxi/dram_sun8i_h3.c b/arch/arm/cpu/armv7/sunxi/dram_sun8i_h3.c
index b721d60..03bd013 100644
--- a/arch/arm/cpu/armv7/sunxi/dram_sun8i_h3.c
+++ b/arch/arm/cpu/armv7/sunxi/dram_sun8i_h3.c
@@ -73,10 +73,10 @@ static void mctl_dq_delay(u32 read, u32 write)

for (i = 0; i < 4; i++) {
val = DATX_IOCR_WRITE_DELAY((write >> (i * 4)) & 0xf) |
- DATX_IOCR_READ_DELAY((read >> (i * 4)) & 0xf);
+ DATX_IOCR_READ_DELAY(((read >> (i * 4)) & 0xf) * 2);

for (j = DATX_IOCR_DQ(0); j <= DATX_IOCR_DM; j++)
- setbits_le32(&mctl_ctl->datx[i].iocr[j], val);
+ writel(val, &mctl_ctl->datx[i].iocr[j]);
}

clrbits_le32(&mctl_ctl->pgcr[0], 1 << 26);
@@ -85,8 +85,8 @@ static void mctl_dq_delay(u32 read, u32 write)
val = DATX_IOCR_WRITE_DELAY((write >> (16 + i * 4)) & 0xf) |
DATX_IOCR_READ_DELAY((read >> (16 + i * 4)) & 0xf);

- setbits_le32(&mctl_ctl->datx[i].iocr[DATX_IOCR_DQS], val);
- setbits_le32(&mctl_ctl->datx[i].iocr[DATX_IOCR_DQSN], val);
+ writel(val, &mctl_ctl->datx[i].iocr[DATX_IOCR_DQS]);
+ writel(val, &mctl_ctl->datx[i].iocr[DATX_IOCR_DQSN]);
}

setbits_le32(&mctl_ctl->pgcr[0], 1 << 26);

Siarhei Siamashka

unread,
Dec 9, 2015, 9:13:08 PM12/9/15
to Jens Kuske, Hans de Goede, Maxime Ripard, Chen-Yu Tsai, Emilio López, Vishnu Patekar, linux...@googlegroups.com, Reinder E.N. de Haan, zhao_...@263.net
Hello,

On Wed, 9 Dec 2015 19:29:49 +0100
Jens Kuske <jens...@gmail.com> wrote:

> On 09/12/15 09:40, Siarhei Siamashka wrote:
> > Thanks for the explanations. I finally got lima-memtester up and
> > running on H3 hardware (not that it was difficult, but just the amount
> > of unnecessary compatibility breaks in the H3 SDK kernel was a bit
> > unexpected and really discouraging, they are really doing almost
> > *everything* in a different way compared to A10/A20 SDK kernel just
> > for the sake of making things different):
> >
> > https://github.com/ssvb/lima-memtester/releases/tag/20151207-orange-pi-pc-fel-test
> >
> > Currently U-Boot v2016.01-rc2 fails the lima-memtester check unless
> > the DRAM clock speed is reduced to 456 MHz on my Orange Pi PC. But
> > if I use the boot0 bootloader to boot the same kernel image
> > (uImage-3.4-sun8i-h3-lima-memtester), then the test works fine.
> > This means that there must be still something wrong with the H3
> > DRAM init code in U-Boot, or maybe some clocks are wrong
> >
>
> I tried to compare boot0 and the SDK source again and actually
> found another difference.

Did you dump the DRAM controller registers to find this difference
between U-Boot and boot0?

> The read delays (except for dqs) are doubled in boot0 before
> writing them to the registers. Looks like they suddenly needed
> higher values than possible with 4 bit. The register seems to
> take 6 bit wide values.

Well, we can always change the layout of data in this struct and
allocate 8 bits per each delay value instead of 4 bits:

struct dram_para para = {
.read_delays = 0x00007979,
.write_delays = 0x6aaa0000,
.dual_rank = 0,
.bus_width = 32,
.row_bits = 15,
.page_size = 4096,
};

Are they originally the 'tpr11' and 'tpr12' parameters from FEX?
Maybe they belong in Kconfig, with a comment about how to do all
the needed conversion from FEX (multiplication by 2)?

BTW, do these delays serve a somewhat similar purpose as the 'tpr3'
parameter in A10/A13/A20? Later we could adapt the a10-tpr3-scan
script and make a h3 variant of it for bruteforce searching optimal
values of these delays.

With the lima-memtester test failures, we have already discovered
in an experimental way that correctly configuring these delays
apparently affects reliability :-)

> After fixing that, lima-memtester doesn't fail at 672 MHz anymore
> on my Orange Pi Plus. Before it failed at 552 and higher.
> Patch below.

Thanks. With this U-Boot patch, lima-memtester does not fail anymore
at 672 MHz on my Orange Pi PC board too. That's a major improvement
over what is in U-boot 2016.01-rc2. If you are going to submit this
patch to U-Boot, you can have my

Tested-by: Siarhei Siamashka <siarhei....@gmail.com>

Still increasing the DRAM clock speed even by one 24 MHz step to
696 MHz makes it fail again. So there does not seem to be much safety
headroom available. I have prepared an updated v3 tarball with your
fix and added a table to the wiki page:

http://linux-sunxi.org/Orange_Pi_PC#DRAM_clock_speed_limit

Maybe other people could test their Orange Pi PC boards too in order
to see if the results are generally similar, better or worse. Your
Orange Pi Plus is a different board and may in theory have a slightly
different DRAM tracks routing.

> Maybe we could also replaced the setbits with writel, because I
> don't see a good reason not to overwrite the registers, they are
> all zero after reset and have 0x00003f3f mask.

Or maybe "clrsetbits_le32"? The use of "setbits_le32" indeed looks
a bit strange here. I'm fine with "writel" too. In fact I would be
fine with any fix that can quickly resolve the problem.

> Jens
>
>
>
> diff --git a/arch/arm/cpu/armv7/sunxi/dram_sun8i_h3.c b/arch/arm/cpu/armv7/sunxi/dram_sun8i_h3.c
> index b721d60..03bd013 100644
> --- a/arch/arm/cpu/armv7/sunxi/dram_sun8i_h3.c
> +++ b/arch/arm/cpu/armv7/sunxi/dram_sun8i_h3.c
> @@ -73,10 +73,10 @@ static void mctl_dq_delay(u32 read, u32 write)
>
> for (i = 0; i < 4; i++) {
> val = DATX_IOCR_WRITE_DELAY((write >> (i * 4)) & 0xf) |
> - DATX_IOCR_READ_DELAY((read >> (i * 4)) & 0xf);
> + DATX_IOCR_READ_DELAY(((read >> (i * 4)) & 0xf) * 2);
>
> for (j = DATX_IOCR_DQ(0); j <= DATX_IOCR_DM; j++)
> - setbits_le32(&mctl_ctl->datx[i].iocr[j], val);
> + writel(val, &mctl_ctl->datx[i].iocr[j]);
> }
>
> clrbits_le32(&mctl_ctl->pgcr[0], 1 << 26);
> @@ -85,8 +85,8 @@ static void mctl_dq_delay(u32 read, u32 write)
> val = DATX_IOCR_WRITE_DELAY((write >> (16 + i * 4)) & 0xf) |
> DATX_IOCR_READ_DELAY((read >> (16 + i * 4)) & 0xf);
>
> - setbits_le32(&mctl_ctl->datx[i].iocr[DATX_IOCR_DQS], val);
> - setbits_le32(&mctl_ctl->datx[i].iocr[DATX_IOCR_DQSN], val);
> + writel(val, &mctl_ctl->datx[i].iocr[DATX_IOCR_DQS]);
> + writel(val, &mctl_ctl->datx[i].iocr[DATX_IOCR_DQSN]);
> }
>
> setbits_le32(&mctl_ctl->pgcr[0], 1 << 26);

Jens Kuske

unread,
Dec 10, 2015, 4:29:56 AM12/10/15
to Siarhei Siamashka, Hans de Goede, Maxime Ripard, Chen-Yu Tsai, Emilio López, Vishnu Patekar, linux...@googlegroups.com, Reinder E.N. de Haan, zhao_...@263.net
On 10/12/15 03:13, Siarhei Siamashka wrote:
> Hello,
>
> On Wed, 9 Dec 2015 19:29:49 +0100
> Jens Kuske <jens...@gmail.com> wrote:
>
>> On 09/12/15 09:40, Siarhei Siamashka wrote:
>>> Thanks for the explanations. I finally got lima-memtester up and
>>> running on H3 hardware (not that it was difficult, but just the amount
>>> of unnecessary compatibility breaks in the H3 SDK kernel was a bit
>>> unexpected and really discouraging, they are really doing almost
>>> *everything* in a different way compared to A10/A20 SDK kernel just
>>> for the sake of making things different):
>>>
>>> https://github.com/ssvb/lima-memtester/releases/tag/20151207-orange-pi-pc-fel-test
>>>
>>> Currently U-Boot v2016.01-rc2 fails the lima-memtester check unless
>>> the DRAM clock speed is reduced to 456 MHz on my Orange Pi PC. But
>>> if I use the boot0 bootloader to boot the same kernel image
>>> (uImage-3.4-sun8i-h3-lima-memtester), then the test works fine.
>>> This means that there must be still something wrong with the H3
>>> DRAM init code in U-Boot, or maybe some clocks are wrong
>>>
>>
>> I tried to compare boot0 and the SDK source again and actually
>> found another difference.
>
> Did you dump the DRAM controller registers to find this difference
> between U-Boot and boot0?

In this case, yes. But also by reviewing the disassembled boot0 again.

>
>> The read delays (except for dqs) are doubled in boot0 before
>> writing them to the registers. Looks like they suddenly needed
>> higher values than possible with 4 bit. The register seems to
>> take 6 bit wide values.
>
> Well, we can always change the layout of data in this struct and
> allocate 8 bits per each delay value instead of 4 bits:
>
> struct dram_para para = {
> .read_delays = 0x00007979,
> .write_delays = 0x6aaa0000,
> .dual_rank = 0,
> .bus_width = 32,
> .row_bits = 15,
> .page_size = 4096,
> };
>
> Are they originally the 'tpr11' and 'tpr12' parameters from FEX?

Yes, they are. I just gave them meaningful names.
Each nibble represents delay of one byte lane, the lower 4 for the DQ
lines, the upper 4 for the DQS/DQS# lines.

> Maybe they belong in Kconfig, with a comment about how to do all
> the needed conversion from FEX (multiplication by 2)?

If it turns out that they should be different between boards, sure. But
all FEX files I checked had the same values. Maybe the board vendors
don't even know about these, Allwinner provided these somewhat strange
numbers (why does lane 4 have a much shorter dqs write delay) and they
adopted them...

Maybe something like this would be a good idea:

CONFIG_DRAM_DQ_READ_DELAY = 0x0e120e12
CONFIG_DRAM_DQS_READ_DELAY = 0x00000000
CONFIG_DRAM_DQ_WRITE_DELAY = 0x00000000
CONFIG_DRAM_DQS_WRITE_DELAY = 0x060a0a0a

Or we find values that work well on all boards.

>
> BTW, do these delays serve a somewhat similar purpose as the 'tpr3'
> parameter in A10/A13/A20? Later we could adapt the a10-tpr3-scan
> script and make a h3 variant of it for bruteforce searching optimal
> values of these delays.

I think they are comparable with tpr3. The hardware would even support
individual delays for each bit, but the combinations get endless then.

>
> With the lima-memtester test failures, we have already discovered
> in an experimental way that correctly configuring these delays
> apparently affects reliability :-)
>
>> After fixing that, lima-memtester doesn't fail at 672 MHz anymore
>> on my Orange Pi Plus. Before it failed at 552 and higher.
>> Patch below.
>
> Thanks. With this U-Boot patch, lima-memtester does not fail anymore
> at 672 MHz on my Orange Pi PC board too. That's a major improvement
> over what is in U-boot 2016.01-rc2. If you are going to submit this
> patch to U-Boot, you can have my
>
> Tested-by: Siarhei Siamashka <siarhei....@gmail.com>

Should I submit it as a fix? I mean, it seems it doesn't really fix it
at least on some Orange Pi PCs, but only improves the situation.
My OPi Plus now passes 744 MHz too (maybe even higher, didn't try), so
there are definitely differences between the boards.

Regards,
Jens

Hans de Goede

unread,
Dec 10, 2015, 5:04:30 AM12/10/15
to jens...@gmail.com, Siarhei Siamashka, Maxime Ripard, Chen-Yu Tsai, Emilio López, Vishnu Patekar, linux...@googlegroups.com, Reinder E.N. de Haan, zhao_...@263.net
Hi,
Yes please, your original version is fine for now, lets wait with
doing something more fancy until we have a good idea how something
more fancy should look like. For now I think that being able
to compare the fex file values 1:1 with our code is good.

Maybe add a comment to where you set the constants in the struct
to which tpr the settings belong, e.g. :

.read_delays = 0x00007979, /* tpr12 */
.write_delays = 0x6aaa0000, /* tpr11 */

> I mean, it seems it doesn't really fix it
> at least on some Orange Pi PCs, but only improves the situation.

? if I understand things correctly your patch make lima-memtester pass
at 672 MHz (which is our current configured speed) on both your
and Siarhei's boards, to me that seems that it fixes things.

Regards,

Hans

Thomas Kaiser

unread,
Dec 10, 2015, 7:31:05 AM12/10/15
to linux-sunxi, jens...@gmail.com, siarhei....@gmail.com, maxime...@free-electrons.com, we...@csie.org, emi...@elopez.com.ar, vishnupa...@gmail.com, rei...@mveas.com, zhao_...@263.net, hdeg...@redhat.com
Hi,

Hans de Goede wrote:
? if I understand things correctly your patch make lima-memtester pass
at 672 MHz (which is our current configured speed) on both your
and Siarhei's boards, to me that seems that it fixes things.

A few more boards were tested but 672 MHz seem still questionable:


(the latter interesting since he uses a huge 35x35x25mm heatsink that covers also DRAM) 

Regards,

Thomas

Siarhei Siamashka

unread,
Dec 16, 2015, 2:35:07 AM12/16/15
to Thomas Kaiser, linux-sunxi, jens...@gmail.com, maxime...@free-electrons.com, we...@csie.org, emi...@elopez.com.ar, vishnupa...@gmail.com, rei...@mveas.com, zhao_...@263.net, hdeg...@redhat.com
On Thu, 10 Dec 2015 04:31:05 -0800 (PST)
Thomas Kaiser <thomas...@phg-online.de> wrote:

> Hi,
>
> Hans de Goede wrote:
> >
> > ? if I understand things correctly your patch make lima-memtester pass
> > at 672 MHz (which is our current configured speed) on both your
> > and Siarhei's boards, to me that seems that it fixes things.
> >
>
> A few more boards were tested but 672 MHz seem still questionable:
>
> http://linux-sunxi.org/Orange_Pi_PC#DRAM_clock_speed_limit
> http://www.orangepi.org/orangepibbsen/forum.php?mod=redirect&goto=findpost&ptid=257&pid=7465

Yes, the 672 MHz DRAM clock speed does not look like a good choice
for Orange Pi PC. Either we find better delays & zq settings and
improve reliability, or the DRAM clock speed needs to be decreased
(also ensuring a little bit of safety headroom).

> (the latter interesting since he uses a huge 35x35x25mm heatsink that
> covers also DRAM)

Some outliers are always possible and we have only one sample, which
can be clocked somewhat higher than the others. It is hard to make any
conclusions with the available data and the heatsink may be unrelated.

Unless we get more test results in a few days which radically change
the statistics, probably using 624 MHz for DRAM on Orange Pi PC would
be reasonable.

Peter Korsgaard

unread,
Dec 16, 2015, 3:02:29 AM12/16/15
to Siarhei Siamashka, Thomas Kaiser, linux-sunxi, jens...@gmail.com, maxime...@free-electrons.com, we...@csie.org, emi...@elopez.com.ar, vishnupa...@gmail.com, rei...@mveas.com, zhao_...@263.net, hdeg...@redhat.com
>>>>> "Siarhei" == Siarhei Siamashka <siarhei....@gmail.com> writes:

Hi,

> Some outliers are always possible and we have only one sample, which
> can be clocked somewhat higher than the others. It is hard to make any
> conclusions with the available data and the heatsink may be unrelated.

Yeah, I'm not sure what makes my board perform better than the rest. The
heatsink is just a cheap 14x14mm rpi one.

> Unless we get more test results in a few days which radically change
> the statistics, probably using 624 MHz for DRAM on Orange Pi PC would
> be reasonable.

Sounds sensible.

--
Bye, Peter Korsgaard

Siarhei Siamashka

unread,
Dec 16, 2015, 3:07:34 AM12/16/15
to Jens Kuske, Hans de Goede, Maxime Ripard, Chen-Yu Tsai, Emilio López, Vishnu Patekar, linux...@googlegroups.com, Reinder E.N. de Haan, zhao_...@263.net
On Thu, 10 Dec 2015 10:29:52 +0100
It looks like exactly the same story as with A10/A13/A20. All the device
vendors are using the same set of settings, while these settings are
not necessarily optimal (or even good) specifically for their hardware.

> Maybe something like this would be a good idea:
>
> CONFIG_DRAM_DQ_READ_DELAY = 0x0e120e12
> CONFIG_DRAM_DQS_READ_DELAY = 0x00000000
> CONFIG_DRAM_DQ_WRITE_DELAY = 0x00000000
> CONFIG_DRAM_DQS_WRITE_DELAY = 0x060a0a0a
>
> Or we find values that work well on all boards.

This may be tricky. H3 still needs some automation. Because just
randomly trying different settings in a manual way is not a very
productive use of anyone's time.

Also active users engagement is critical, or we have no chance to
collect enough statistics from different board samples. Fortunately
Orange Pi PC seems to be quite popular, so it is likely to be one of
the best supported and well configured boards.

Another alternative is the board manufacturer's engagement.

> > BTW, do these delays serve a somewhat similar purpose as the 'tpr3'
> > parameter in A10/A13/A20? Later we could adapt the a10-tpr3-scan
> > script and make a h3 variant of it for bruteforce searching optimal
> > values of these delays.
>
> I think they are comparable with tpr3. The hardware would even support
> individual delays for each bit, but the combinations get endless then.

Yes, A10/A13/A20 also had many configuration knobs. Some configuration
knobs appear to be more important than the others in practice. This
needs to be figured out in an experimental way.

The Orange Pi PC has DDR3L-1600 memory chips. If the H3 DRAM controller
configuration is the only limiting factor, then there may be potentially
a way up to clock DRAM up to 800 MHz. And there is never too much
memory bandwidth for graphics and multimedia :-) Still the first
priority is of course trying to ensure reliable operation at the
specified/advertised ~667 MHz.

But I'm not sure if I want to do any work on this myself, unless enough
people register their interest and at least promise to participate in
testing.

> >
> > With the lima-memtester test failures, we have already discovered
> > in an experimental way that correctly configuring these delays
> > apparently affects reliability :-)
> >
> >> After fixing that, lima-memtester doesn't fail at 672 MHz anymore
> >> on my Orange Pi Plus. Before it failed at 552 and higher.
> >> Patch below.
> >
> > Thanks. With this U-Boot patch, lima-memtester does not fail anymore
> > at 672 MHz on my Orange Pi PC board too. That's a major improvement
> > over what is in U-boot 2016.01-rc2. If you are going to submit this
> > patch to U-Boot, you can have my
> >
> > Tested-by: Siarhei Siamashka <siarhei....@gmail.com>
>
> Should I submit it as a fix? I mean, it seems it doesn't really fix it
> at least on some Orange Pi PCs, but only improves the situation.
> My OPi Plus now passes 744 MHz too (maybe even higher, didn't try), so
> there are definitely differences between the boards.

We can always have this patch and also reduce the DRAM clock speed to
a safer level.

Hans de Goede

unread,
Dec 16, 2015, 4:11:53 AM12/16/15
to siarhei....@gmail.com, Thomas Kaiser, linux-sunxi, jens...@gmail.com, maxime...@free-electrons.com, we...@csie.org, emi...@elopez.com.ar, vishnupa...@gmail.com, rei...@mveas.com, zhao_...@263.net
Hi,
Reducing the DRAM speed to 624 seems like a good idea to me, can someone
send me a patch for this please?

Regards,

Hans

Thomas Kaiser

unread,
Dec 16, 2015, 4:54:26 AM12/16/15
to Siarhei Siamashka, linux-sunxi, jens...@gmail.com, maxime...@free-electrons.com, we...@csie.org, emi...@elopez.com.ar, vishnupa...@gmail.com, rei...@mveas.com, zhao_...@263.net, hdeg...@redhat.com
Siarhei Siamashka wrote:

Unless we get more test results in a few days which radically change
the statistics, probably using 624 MHz for DRAM on Orange Pi PC would
be reasonable.

I second that while also asking the overclocker community for help:


(but doubt that we get any useful feedback from there)

Regards,

Thomas


Siarhei Siamashka

unread,
Dec 22, 2015, 8:35:13 PM12/22/15
to Hans de Goede, Thomas Kaiser, linux-sunxi, jens...@gmail.com, maxime...@free-electrons.com, we...@csie.org, emi...@elopez.com.ar, vishnupa...@gmail.com, rei...@mveas.com, zhao_...@263.net
Hi,

On Wed, 16 Dec 2015 10:11:38 +0100
Hans de Goede <hdeg...@redhat.com> wrote:

We still have a hope to collect more statistics at:
http://linux-sunxi.org/Orange_Pi_PC#DRAM_clock_speed_limit

The Orange Pi PC DRAM clock speed needs to be adjusted before the
U-Boot v2016.01 release, and we still have to decide what would be
the best default. But the time is running out. So if anyone wants
to do a useful contribution by submitting lima-memtester results
from his/her Orange Pi PC board, then now is the last chance.

Steven, if you have access to many Orange Pi PC boards, maybe you
could try to run some tests on them too?
Reply all
Reply to author
Forward
0 new messages