]> git.ipfire.org Git - people/ms/u-boot.git/commitdiff
Merge branch 'master' of git://git.denx.de/u-boot-sunxi
authorTom Rini <trini@konsulko.com>
Sat, 8 Apr 2017 13:28:02 +0000 (09:28 -0400)
committerTom Rini <trini@konsulko.com>
Sat, 8 Apr 2017 13:28:02 +0000 (09:28 -0400)
30 files changed:
MAINTAINERS
Makefile
arch/arm/dts/Makefile
arch/arm/dts/axp209.dtsi
arch/arm/dts/sun5i-gr8-chip-pro.dts [new file with mode: 0644]
arch/arm/dts/sun5i-gr8.dtsi [new file with mode: 0644]
arch/arm/dts/sun8i-h3-nanopi-neo-air.dts [new file with mode: 0644]
arch/arm/dts/sun9i-a80-cx-a99.dts [new file with mode: 0644]
arch/arm/dts/sun9i-a80.dtsi
board/sunxi/MAINTAINERS
board/sunxi/README.nand [new file with mode: 0644]
cmd/Kconfig
cmd/mtdparts.c
common/Kconfig
configs/CHIP_pro_defconfig [new file with mode: 0644]
configs/Sunchip_CX-A99_defconfig [new file with mode: 0644]
configs/nanopi_neo_air_defconfig [new file with mode: 0644]
configs/sun8i_a23_evb_defconfig [new file with mode: 0644]
drivers/mtd/nand/Kconfig
drivers/mtd/nand/sunxi_nand_spl.c
drivers/mtd/ubi/Kconfig
drivers/net/sun8i_emac.c
include/configs/sunxi-common.h
include/environment.h
lib/Kconfig
lib/bch.c
scripts/Makefile.spl
tools/.gitignore
tools/Makefile
tools/sunxi-spl-image-builder.c [new file with mode: 0644]

index 9c88ff2b17e3c967504e640c545236882634fab9..6c702f2ff2ff39637170bc7b11287dba525dd9a6 100644 (file)
@@ -174,9 +174,12 @@ F: arch/arm/include/asm/arch-sti*/
 ARM SUNXI
 M:     Jagan Teki <jagan@openedev.com>
 M:     Maxime Ripard <maxime.ripard@free-electrons.com>
+S:     Maintained
 T:     git git://git.denx.de/u-boot-sunxi.git
 F:     arch/arm/cpu/armv7/sunxi/
 F:     arch/arm/include/asm/arch-sunxi/
+F:     arch/arm/mach-sunxi/
+F:     board/sunxi/
 
 ARM TEGRA
 M:     Tom Warren <twarren@nvidia.com>
index 2638acf838581e4bd507d532ce0946c8efe5d51f..ca7d60d610839ede7be37cee640bd3c969132674 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1345,6 +1345,9 @@ spl/u-boot-spl: tools prepare \
 spl/sunxi-spl.bin: spl/u-boot-spl
        @:
 
+spl/sunxi-spl-with-ecc.bin: spl/sunxi-spl.bin
+       @:
+
 spl/u-boot-spl.sfp: spl/u-boot-spl
        @:
 
index 7378c8843170e1fe2631aa1cf0df11c430d2d923..a2c0717f076711bd2b60e02d847b448d32b2f9e9 100644 (file)
@@ -228,6 +228,7 @@ dtb-$(CONFIG_MACH_SUN5I) += \
        sun5i-a13-olinuxino-micro.dtb \
        sun5i-a13-q8-tablet.dtb \
        sun5i-a13-utoo-p66.dtb \
+       sun5i-gr8-chip-pro.dtb \
        sun5i-r8-chip.dtb
 dtb-$(CONFIG_MACH_SUN6I) += \
        sun6i-a31-app4-evb1.dtb \
@@ -301,7 +302,8 @@ dtb-$(CONFIG_MACH_SUN8I_H3) += \
        sun8i-h3-orangepi-pc-plus.dtb \
        sun8i-h3-orangepi-plus.dtb \
        sun8i-h3-orangepi-plus2e.dtb \
-       sun8i-h3-nanopi-neo.dtb
+       sun8i-h3-nanopi-neo.dtb \
+       sun8i-h3-nanopi-neo-air.dtb
 dtb-$(CONFIG_MACH_SUN50I_H5) += \
        sun50i-h5-orangepi-pc2.dtb
 dtb-$(CONFIG_MACH_SUN50I) += \
@@ -309,7 +311,8 @@ dtb-$(CONFIG_MACH_SUN50I) += \
        sun50i-a64-pine64.dtb
 dtb-$(CONFIG_MACH_SUN9I) += \
        sun9i-a80-optimus.dtb \
-       sun9i-a80-cubieboard4.dtb
+       sun9i-a80-cubieboard4.dtb \
+       sun9i-a80-cx-a99.dtb
 
 dtb-$(CONFIG_VF610) += vf500-colibri.dtb \
        vf610-colibri.dtb \
index afbe89c01df582a45e9480d1d2180dcaf3859935..675bb0f30825b44abf72581aecb4fdd024964eee 100644 (file)
        interrupt-controller;
        #interrupt-cells = <1>;
 
+       axp_gpio: gpio {
+               compatible = "x-powers,axp209-gpio";
+               gpio-controller;
+               #gpio-cells = <2>;
+       };
+
        regulators {
                /* Default work frequency for buck regulators */
                x-powers,dcdc-freq = <1500>;
diff --git a/arch/arm/dts/sun5i-gr8-chip-pro.dts b/arch/arm/dts/sun5i-gr8-chip-pro.dts
new file mode 100644 (file)
index 0000000..92a2dc6
--- /dev/null
@@ -0,0 +1,266 @@
+/*
+ * Copyright 2016 Free Electrons
+ * Copyright 2016 NextThing Co
+ *
+ * Maxime Ripard <maxime.ripard@free-electrons.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.
+ */
+
+/dts-v1/;
+#include "sun5i-gr8.dtsi"
+#include "sunxi-common-regulators.dtsi"
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/input.h>
+#include <dt-bindings/interrupt-controller/irq.h>
+
+/ {
+       model = "NextThing C.H.I.P. Pro";
+       compatible = "nextthing,chip-pro", "nextthing,gr8";
+
+       aliases {
+               i2c0 = &i2c0;
+               i2c1 = &i2c1;
+               serial0 = &uart1;
+               serial1 = &uart2;
+               serial2 = &uart3;
+       };
+
+       chosen {
+               stdout-path = "serial0:115200n8";
+       };
+
+       leds {
+               compatible = "gpio-leds";
+
+               status {
+                       label = "chip-pro:white:status";
+                       gpios = <&axp_gpio 2 GPIO_ACTIVE_HIGH>;
+                       default-state = "on";
+               };
+       };
+
+       mmc0_pwrseq: mmc0_pwrseq {
+               compatible = "mmc-pwrseq-simple";
+               pinctrl-names = "default";
+               pinctrl-0 = <&wifi_reg_on_pin_chip_pro>;
+               reset-gpios = <&pio 1 10 GPIO_ACTIVE_LOW>; /* PB10 */
+       };
+};
+
+&codec {
+       status = "okay";
+};
+
+&ehci0 {
+       status = "okay";
+};
+
+&i2c0 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&i2c0_pins_a>;
+       status = "okay";
+
+       axp209: pmic@34 {
+               reg = <0x34>;
+
+               /*
+               * The interrupt is routed through the "External Fast
+               * Interrupt Request" pin (ball G13 of the module)
+               * directly to the main interrupt controller, without
+               * any other controller interfering.
+               */
+               interrupts = <0>;
+       };
+};
+
+#include "axp209.dtsi"
+
+&i2c1 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&i2c1_pins_a>;
+       status = "disabled";
+};
+
+&i2s0 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&i2s0_mclk_pins_a>, <&i2s0_data_pins_a>;
+       status = "disabled";
+};
+
+&mmc0 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&mmc0_pins_a>;
+       vmmc-supply = <&reg_vcc3v3>;
+       mmc-pwrseq = <&mmc0_pwrseq>;
+       bus-width = <4>;
+       non-removable;
+       status = "okay";
+};
+
+&nfc {
+       pinctrl-names = "default";
+       pinctrl-0 = <&nand_pins_a &nand_cs0_pins_a &nand_rb0_pins_a>;
+       status = "okay";
+
+       nand@0 {
+               #address-cells = <2>;
+               #size-cells = <2>;
+               reg = <0>;
+               allwinner,rb = <0>;
+               nand-ecc-mode = "hw";
+       };
+};
+
+&ohci0 {
+       status = "okay";
+};
+
+&otg_sram {
+       status = "okay";
+};
+
+&pio {
+       usb0_id_pin_chip_pro: usb0-id-pin@0 {
+               allwinner,pins = "PG2";
+               allwinner,function = "gpio_in";
+               allwinner,drive = <SUN4I_PINCTRL_10_MA>;
+               allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
+       };
+
+       wifi_reg_on_pin_chip_pro: wifi-reg-on-pin@0 {
+               allwinner,pins = "PB10";
+               allwinner,function = "gpio_out";
+               allwinner,drive = <SUN4I_PINCTRL_10_MA>;
+               allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
+       };
+};
+
+&pwm {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pwm0_pins_a>, <&pwm1_pins>;
+       status = "disabled";
+};
+
+&reg_dcdc2 {
+       regulator-min-microvolt = <1000000>;
+       regulator-max-microvolt = <1400000>;
+       regulator-name = "vdd-cpu";
+       regulator-always-on;
+};
+
+&reg_dcdc3 {
+       regulator-min-microvolt = <1000000>;
+       regulator-max-microvolt = <1300000>;
+       regulator-name = "vdd-sys";
+       regulator-always-on;
+};
+
+&reg_ldo1 {
+       regulator-name = "vdd-rtc";
+};
+
+&reg_ldo2 {
+       regulator-min-microvolt = <2700000>;
+       regulator-max-microvolt = <3300000>;
+       regulator-name = "avcc";
+       regulator-always-on;
+};
+
+/*
+ * Both LDO3 and LDO4 are used in parallel to power up the
+ * WiFi/BT chip.
+ */
+&reg_ldo3 {
+       regulator-min-microvolt = <3300000>;
+       regulator-max-microvolt = <3300000>;
+       regulator-name = "vcc-wifi-1";
+       regulator-always-on;
+};
+
+&reg_ldo4 {
+       regulator-min-microvolt = <3300000>;
+       regulator-max-microvolt = <3300000>;
+       regulator-name = "vcc-wifi-2";
+       regulator-always-on;
+};
+
+&uart1 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&uart1_pins_a>, <&uart1_cts_rts_pins_a>;
+       status = "okay";
+};
+
+&uart2 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&uart2_pins_a>, <&uart2_cts_rts_pins_a>;
+       status = "disabled";
+};
+
+&uart3 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&uart3_pins_a>, <&uart3_cts_rts_pins_a>;
+       status = "okay";
+};
+
+&usb_otg {
+       /*
+        * The CHIP Pro doesn't have a controllable VBUS, nor does it
+        * have any 5v rail on the board itself.
+        *
+        * If one wants to use it as a true OTG port, it should be
+        * done in the baseboard, and its DT / overlay will add it.
+        */
+       dr_mode = "otg";
+       status = "okay";
+};
+
+&usb_power_supply {
+       status = "okay";
+};
+
+&usbphy {
+       pinctrl-names = "default";
+       pinctrl-0 = <&usb0_id_pin_chip_pro>;
+       usb0_id_det-gpio = <&pio 6 2 GPIO_ACTIVE_HIGH>; /* PG2 */
+       usb0_vbus_power-supply = <&usb_power_supply>;
+       usb1_vbus-supply = <&reg_vcc5v0>;
+       status = "okay";
+};
diff --git a/arch/arm/dts/sun5i-gr8.dtsi b/arch/arm/dts/sun5i-gr8.dtsi
new file mode 100644 (file)
index 0000000..ea86d4d
--- /dev/null
@@ -0,0 +1,1132 @@
+/*
+ * Copyright 2016 Mylène Josserand
+ *
+ * Mylène Josserand <mylene.josserand@free-electrons.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 library 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 library 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 <dt-bindings/clock/sun4i-a10-pll2.h>
+#include <dt-bindings/dma/sun4i-a10.h>
+#include <dt-bindings/pinctrl/sun4i-a10.h>
+
+/ {
+       interrupt-parent = <&intc>;
+       #address-cells = <1>;
+       #size-cells = <1>;
+
+       cpus {
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               cpu0: cpu@0 {
+                       device_type = "cpu";
+                       compatible = "arm,cortex-a8";
+                       reg = <0x0>;
+                       clocks = <&cpu>;
+               };
+       };
+
+       clocks {
+               #address-cells = <1>;
+               #size-cells = <1>;
+               ranges;
+
+               /*
+                * This is a dummy clock, to be used as placeholder on
+                * other mux clocks when a specific parent clock is not
+                * yet implemented. It should be dropped when the driver
+                * is complete.
+                */
+               dummy: dummy {
+                       #clock-cells = <0>;
+                       compatible = "fixed-clock";
+                       clock-frequency = <0>;
+               };
+
+               osc24M: clk@01c20050 {
+                       #clock-cells = <0>;
+                       compatible = "allwinner,sun4i-a10-osc-clk";
+                       reg = <0x01c20050 0x4>;
+                       clock-frequency = <24000000>;
+                       clock-output-names = "osc24M";
+               };
+
+               osc3M: osc3M-clk {
+                       compatible = "fixed-factor-clock";
+                       #clock-cells = <0>;
+                       clock-div = <8>;
+                       clock-mult = <1>;
+                       clocks = <&osc24M>;
+                       clock-output-names = "osc3M";
+               };
+
+               osc32k: clk@0 {
+                       #clock-cells = <0>;
+                       compatible = "fixed-clock";
+                       clock-frequency = <32768>;
+                       clock-output-names = "osc32k";
+               };
+
+               pll1: clk@01c20000 {
+                       #clock-cells = <0>;
+                       compatible = "allwinner,sun4i-a10-pll1-clk";
+                       reg = <0x01c20000 0x4>;
+                       clocks = <&osc24M>;
+                       clock-output-names = "pll1";
+               };
+
+               pll2: clk@01c20008 {
+                       #clock-cells = <1>;
+                       compatible = "allwinner,sun5i-a13-pll2-clk";
+                       reg = <0x01c20008 0x8>;
+                       clocks = <&osc24M>;
+                       clock-output-names = "pll2-1x", "pll2-2x",
+                                            "pll2-4x", "pll2-8x";
+               };
+
+               pll3: clk@01c20010 {
+                       #clock-cells = <0>;
+                       compatible = "allwinner,sun4i-a10-pll3-clk";
+                       reg = <0x01c20010 0x4>;
+                       clocks = <&osc3M>;
+                       clock-output-names = "pll3";
+               };
+
+               pll3x2: pll3x2-clk {
+                       compatible = "allwinner,sun4i-a10-pll3-2x-clk";
+                       #clock-cells = <0>;
+                       clock-div = <1>;
+                       clock-mult = <2>;
+                       clocks = <&pll3>;
+                       clock-output-names = "pll3-2x";
+               };
+
+               pll4: clk@01c20018 {
+                       #clock-cells = <0>;
+                       compatible = "allwinner,sun4i-a10-pll1-clk";
+                       reg = <0x01c20018 0x4>;
+                       clocks = <&osc24M>;
+                       clock-output-names = "pll4";
+               };
+
+               pll5: clk@01c20020 {
+                       #clock-cells = <1>;
+                       compatible = "allwinner,sun4i-a10-pll5-clk";
+                       reg = <0x01c20020 0x4>;
+                       clocks = <&osc24M>;
+                       clock-output-names = "pll5_ddr", "pll5_other";
+               };
+
+               pll6: clk@01c20028 {
+                       #clock-cells = <1>;
+                       compatible = "allwinner,sun4i-a10-pll6-clk";
+                       reg = <0x01c20028 0x4>;
+                       clocks = <&osc24M>;
+                       clock-output-names = "pll6_sata", "pll6_other", "pll6";
+               };
+
+               pll7: clk@01c20030 {
+                       #clock-cells = <0>;
+                       compatible = "allwinner,sun4i-a10-pll3-clk";
+                       reg = <0x01c20030 0x4>;
+                       clocks = <&osc3M>;
+                       clock-output-names = "pll7";
+               };
+
+               pll7x2: pll7x2-clk {
+                       compatible = "allwinner,sun4i-a10-pll3-2x-clk";
+                       #clock-cells = <0>;
+                       clock-div = <1>;
+                       clock-mult = <2>;
+                       clocks = <&pll7>;
+                       clock-output-names = "pll7-2x";
+               };
+
+               /* dummy is 200M */
+               cpu: cpu@01c20054 {
+                       #clock-cells = <0>;
+                       compatible = "allwinner,sun4i-a10-cpu-clk";
+                       reg = <0x01c20054 0x4>;
+                       clocks = <&osc32k>, <&osc24M>, <&pll1>, <&dummy>;
+                       clock-output-names = "cpu";
+               };
+
+               axi: axi@01c20054 {
+                       #clock-cells = <0>;
+                       compatible = "allwinner,sun4i-a10-axi-clk";
+                       reg = <0x01c20054 0x4>;
+                       clocks = <&cpu>;
+                       clock-output-names = "axi";
+               };
+
+               ahb: ahb@01c20054 {
+                       #clock-cells = <0>;
+                       compatible = "allwinner,sun5i-a13-ahb-clk";
+                       reg = <0x01c20054 0x4>;
+                       clocks = <&axi>, <&cpu>, <&pll6 1>;
+                       clock-output-names = "ahb";
+                       /*
+                        * Use PLL6 as parent, instead of CPU/AXI
+                        * which has rate changes due to cpufreq
+                        */
+                       assigned-clocks = <&ahb>;
+                       assigned-clock-parents = <&pll6 1>;
+               };
+
+               apb0: apb0@01c20054 {
+                       #clock-cells = <0>;
+                       compatible = "allwinner,sun4i-a10-apb0-clk";
+                       reg = <0x01c20054 0x4>;
+                       clocks = <&ahb>;
+                       clock-output-names = "apb0";
+               };
+
+               apb1: clk@01c20058 {
+                       #clock-cells = <0>;
+                       compatible = "allwinner,sun4i-a10-apb1-clk";
+                       reg = <0x01c20058 0x4>;
+                       clocks = <&osc24M>, <&pll6 1>, <&osc32k>;
+                       clock-output-names = "apb1";
+               };
+
+               axi_gates: clk@01c2005c {
+                       #clock-cells = <1>;
+                       compatible = "allwinner,sun4i-a10-gates-clk";
+                       reg = <0x01c2005c 0x4>;
+                       clocks = <&axi>;
+                       clock-indices = <0>;
+                       clock-output-names = "axi_dram";
+               };
+
+               ahb_gates: clk@01c20060 {
+                       #clock-cells = <1>;
+                       compatible = "allwinner,sun5i-a13-ahb-gates-clk";
+                       reg = <0x01c20060 0x8>;
+                       clocks = <&ahb>;
+                       clock-indices = <0>, <1>,
+                                       <2>, <5>, <6>,
+                                       <7>, <8>, <9>,
+                                       <10>, <13>,
+                                       <14>, <17>, <20>,
+                                       <21>, <22>,
+                                       <28>, <32>, <34>,
+                                       <36>, <40>, <44>,
+                                       <46>, <51>,
+                                       <52>;
+                       clock-output-names = "ahb_usbotg", "ahb_ehci",
+                                            "ahb_ohci", "ahb_ss", "ahb_dma",
+                                            "ahb_bist", "ahb_mmc0", "ahb_mmc1",
+                                            "ahb_mmc2", "ahb_nand",
+                                            "ahb_sdram", "ahb_emac", "ahb_spi0",
+                                            "ahb_spi1", "ahb_spi2",
+                                            "ahb_hstimer", "ahb_ve", "ahb_tve",
+                                            "ahb_lcd", "ahb_csi", "ahb_de_be",
+                                            "ahb_de_fe", "ahb_iep",
+                                            "ahb_mali400";
+               };
+
+               apb0_gates: clk@01c20068 {
+                       #clock-cells = <1>;
+                       compatible = "allwinner,sun4i-a10-gates-clk";
+                       reg = <0x01c20068 0x4>;
+                       clocks = <&apb0>;
+                       clock-indices = <0>, <3>,
+                                       <5>, <6>;
+                       clock-output-names = "apb0_codec", "apb0_i2s0",
+                                            "apb0_pio", "apb0_ir";
+               };
+
+               apb1_gates: clk@01c2006c {
+                       #clock-cells = <1>;
+                       compatible = "allwinner,sun4i-a10-gates-clk";
+                       reg = <0x01c2006c 0x4>;
+                       clocks = <&apb1>;
+                       clock-indices = <0>, <1>,
+                                       <2>, <17>,
+                                       <18>, <19>;
+                       clock-output-names = "apb1_i2c0", "apb1_i2c1",
+                                            "apb1_i2c2", "apb1_uart1",
+                                            "apb1_uart2", "apb1_uart3";
+               };
+
+               nand_clk: clk@01c20080 {
+                       #clock-cells = <0>;
+                       compatible = "allwinner,sun4i-a10-mod0-clk";
+                       reg = <0x01c20080 0x4>;
+                       clocks = <&osc24M>, <&pll6 1>, <&pll5 1>;
+                       clock-output-names = "nand";
+               };
+
+               ms_clk: clk@01c20084 {
+                       #clock-cells = <0>;
+                       compatible = "allwinner,sun4i-a10-mod0-clk";
+                       reg = <0x01c20084 0x4>;
+                       clocks = <&osc24M>, <&pll6 1>, <&pll5 1>;
+                       clock-output-names = "ms";
+               };
+
+               mmc0_clk: clk@01c20088 {
+                       #clock-cells = <1>;
+                       compatible = "allwinner,sun4i-a10-mmc-clk";
+                       reg = <0x01c20088 0x4>;
+                       clocks = <&osc24M>, <&pll6 1>, <&pll5 1>;
+                       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 1>, <&pll5 1>;
+                       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 1>, <&pll5 1>;
+                       clock-output-names = "mmc2",
+                                            "mmc2_output",
+                                            "mmc2_sample";
+               };
+
+               ts_clk: clk@01c20098 {
+                       #clock-cells = <0>;
+                       compatible = "allwinner,sun4i-a10-mod0-clk";
+                       reg = <0x01c20098 0x4>;
+                       clocks = <&osc24M>, <&pll6 1>, <&pll5 1>;
+                       clock-output-names = "ts";
+               };
+
+               ss_clk: clk@01c2009c {
+                       #clock-cells = <0>;
+                       compatible = "allwinner,sun4i-a10-mod0-clk";
+                       reg = <0x01c2009c 0x4>;
+                       clocks = <&osc24M>, <&pll6 1>, <&pll5 1>;
+                       clock-output-names = "ss";
+               };
+
+               spi0_clk: clk@01c200a0 {
+                       #clock-cells = <0>;
+                       compatible = "allwinner,sun4i-a10-mod0-clk";
+                       reg = <0x01c200a0 0x4>;
+                       clocks = <&osc24M>, <&pll6 1>, <&pll5 1>;
+                       clock-output-names = "spi0";
+               };
+
+               spi1_clk: clk@01c200a4 {
+                       #clock-cells = <0>;
+                       compatible = "allwinner,sun4i-a10-mod0-clk";
+                       reg = <0x01c200a4 0x4>;
+                       clocks = <&osc24M>, <&pll6 1>, <&pll5 1>;
+                       clock-output-names = "spi1";
+               };
+
+               spi2_clk: clk@01c200a8 {
+                       #clock-cells = <0>;
+                       compatible = "allwinner,sun4i-a10-mod0-clk";
+                       reg = <0x01c200a8 0x4>;
+                       clocks = <&osc24M>, <&pll6 1>, <&pll5 1>;
+                       clock-output-names = "spi2";
+               };
+
+               ir0_clk: clk@01c200b0 {
+                       #clock-cells = <0>;
+                       compatible = "allwinner,sun4i-a10-mod0-clk";
+                       reg = <0x01c200b0 0x4>;
+                       clocks = <&osc24M>, <&pll6 1>, <&pll5 1>;
+                       clock-output-names = "ir0";
+               };
+
+               i2s0_clk: clk@01c200b8 {
+                       #clock-cells = <0>;
+                       compatible = "allwinner,sun4i-a10-mod1-clk";
+                       reg = <0x01c200b8 0x4>;
+                       clocks = <&pll2 SUN4I_A10_PLL2_8X>,
+                                <&pll2 SUN4I_A10_PLL2_4X>,
+                                <&pll2 SUN4I_A10_PLL2_2X>,
+                                <&pll2 SUN4I_A10_PLL2_1X>;
+                       clock-output-names = "i2s0";
+               };
+
+               spdif_clk: clk@01c200c0 {
+                       #clock-cells = <0>;
+                       compatible = "allwinner,sun4i-a10-mod1-clk";
+                       reg = <0x01c200c0 0x4>;
+                       clocks = <&pll2 SUN4I_A10_PLL2_8X>,
+                                <&pll2 SUN4I_A10_PLL2_4X>,
+                                <&pll2 SUN4I_A10_PLL2_2X>,
+                                <&pll2 SUN4I_A10_PLL2_1X>;
+                       clock-output-names = "spdif";
+               };
+
+               usb_clk: clk@01c200cc {
+                       #clock-cells = <1>;
+                       #reset-cells = <1>;
+                       compatible = "allwinner,sun5i-a13-usb-clk";
+                       reg = <0x01c200cc 0x4>;
+                       clocks = <&pll6 1>;
+                       clock-output-names = "usb_ohci0", "usb_phy";
+               };
+
+               dram_gates: clk@01c20100 {
+                       #clock-cells = <1>;
+                       compatible = "nextthing,gr8-dram-gates-clk",
+                                    "allwinner,sun4i-a10-gates-clk";
+                       reg = <0x01c20100 0x4>;
+                       clocks = <&pll5 0>;
+                       clock-indices = <0>,
+                                       <1>,
+                                       <25>,
+                                       <26>,
+                                       <29>,
+                                       <31>;
+                       clock-output-names = "dram_ve",
+                                            "dram_csi",
+                                            "dram_de_fe",
+                                            "dram_de_be",
+                                            "dram_ace",
+                                            "dram_iep";
+               };
+
+               de_be_clk: clk@01c20104 {
+                       #clock-cells = <0>;
+                       #reset-cells = <0>;
+                       compatible = "allwinner,sun4i-a10-display-clk";
+                       reg = <0x01c20104 0x4>;
+                       clocks = <&pll3>, <&pll7>, <&pll5 1>;
+                       clock-output-names = "de-be";
+               };
+
+               de_fe_clk: clk@01c2010c {
+                       #clock-cells = <0>;
+                       #reset-cells = <0>;
+                       compatible = "allwinner,sun4i-a10-display-clk";
+                       reg = <0x01c2010c 0x4>;
+                       clocks = <&pll3>, <&pll7>, <&pll5 1>;
+                       clock-output-names = "de-fe";
+               };
+
+               tcon_ch0_clk: clk@01c20118 {
+                       #clock-cells = <0>;
+                       #reset-cells = <1>;
+                       compatible = "allwinner,sun4i-a10-tcon-ch0-clk";
+                       reg = <0x01c20118 0x4>;
+                       clocks = <&pll3>, <&pll7>, <&pll3x2>, <&pll7x2>;
+                       clock-output-names = "tcon-ch0-sclk";
+               };
+
+               tcon_ch1_clk: clk@01c2012c {
+                       #clock-cells = <0>;
+                       compatible = "allwinner,sun4i-a10-tcon-ch1-clk";
+                       reg = <0x01c2012c 0x4>;
+                       clocks = <&pll3>, <&pll7>, <&pll3x2>, <&pll7x2>;
+                       clock-output-names = "tcon-ch1-sclk";
+               };
+
+               codec_clk: clk@01c20140 {
+                       #clock-cells = <0>;
+                       compatible = "allwinner,sun4i-a10-codec-clk";
+                       reg = <0x01c20140 0x4>;
+                       clocks = <&pll2 SUN4I_A10_PLL2_1X>;
+                       clock-output-names = "codec";
+               };
+
+               mbus_clk: clk@01c2015c {
+                       #clock-cells = <0>;
+                       compatible = "allwinner,sun5i-a13-mbus-clk";
+                       reg = <0x01c2015c 0x4>;
+                       clocks = <&osc24M>, <&pll6 1>, <&pll5 1>;
+                       clock-output-names = "mbus";
+               };
+       };
+
+       display-engine {
+               compatible = "allwinner,sun5i-a13-display-engine";
+               allwinner,pipelines = <&fe0>;
+       };
+
+       soc@01c00000 {
+               compatible = "simple-bus";
+               #address-cells = <1>;
+               #size-cells = <1>;
+               ranges;
+
+               sram-controller@01c00000 {
+                       compatible = "allwinner,sun4i-a10-sram-controller";
+                       reg = <0x01c00000 0x30>;
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       ranges;
+
+                       sram_a: sram@00000000 {
+                               compatible = "mmio-sram";
+                               reg = <0x00000000 0xc000>;
+                               #address-cells = <1>;
+                               #size-cells = <1>;
+                               ranges = <0 0x00000000 0xc000>;
+                       };
+
+                       sram_d: sram@00010000 {
+                               compatible = "mmio-sram";
+                               reg = <0x00010000 0x1000>;
+                               #address-cells = <1>;
+                               #size-cells = <1>;
+                               ranges = <0 0x00010000 0x1000>;
+
+                               otg_sram: sram-section@0000 {
+                                       compatible = "allwinner,sun4i-a10-sram-d";
+                                       reg = <0x0000 0x1000>;
+                                       status = "disabled";
+                               };
+                       };
+               };
+
+               dma: dma-controller@01c02000 {
+                       compatible = "allwinner,sun4i-a10-dma";
+                       reg = <0x01c02000 0x1000>;
+                       interrupts = <27>;
+                       clocks = <&ahb_gates 6>;
+                       #dma-cells = <2>;
+               };
+
+               nfc: nand@01c03000 {
+                       compatible = "allwinner,sun4i-a10-nand";
+                       reg = <0x01c03000 0x1000>;
+                       interrupts = <37>;
+                       clocks = <&ahb_gates 13>, <&nand_clk>;
+                       clock-names = "ahb", "mod";
+                       dmas = <&dma SUN4I_DMA_DEDICATED 3>;
+                       dma-names = "rxtx";
+                       status = "disabled";
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+               };
+
+               spi0: spi@01c05000 {
+                       compatible = "allwinner,sun4i-a10-spi";
+                       reg = <0x01c05000 0x1000>;
+                       interrupts = <10>;
+                       clocks = <&ahb_gates 20>, <&spi0_clk>;
+                       clock-names = "ahb", "mod";
+                       dmas = <&dma SUN4I_DMA_DEDICATED 27>,
+                              <&dma SUN4I_DMA_DEDICATED 26>;
+                       dma-names = "rx", "tx";
+                       status = "disabled";
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+               };
+
+               spi1: spi@01c06000 {
+                       compatible = "allwinner,sun4i-a10-spi";
+                       reg = <0x01c06000 0x1000>;
+                       interrupts = <11>;
+                       clocks = <&ahb_gates 21>, <&spi1_clk>;
+                       clock-names = "ahb", "mod";
+                       dmas = <&dma SUN4I_DMA_DEDICATED 9>,
+                              <&dma SUN4I_DMA_DEDICATED 8>;
+                       dma-names = "rx", "tx";
+                       status = "disabled";
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+               };
+
+               tve0: tv-encoder@01c0a000 {
+                       compatible = "allwinner,sun4i-a10-tv-encoder";
+                       reg = <0x01c0a000 0x1000>;
+                       clocks = <&ahb_gates 34>;
+                       resets = <&tcon_ch0_clk 0>;
+                       status = "disabled";
+
+                       port {
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+
+                               tve0_in_tcon0: endpoint@0 {
+                                       reg = <0>;
+                                       remote-endpoint = <&tcon0_out_tve0>;
+                               };
+                       };
+               };
+
+               tcon0: lcd-controller@01c0c000 {
+                       compatible = "allwinner,sun5i-a13-tcon";
+                       reg = <0x01c0c000 0x1000>;
+                       interrupts = <44>;
+                       resets = <&tcon_ch0_clk 1>;
+                       reset-names = "lcd";
+                       clocks = <&ahb_gates 36>,
+                                <&tcon_ch0_clk>,
+                                <&tcon_ch1_clk>;
+                       clock-names = "ahb",
+                                     "tcon-ch0",
+                                     "tcon-ch1";
+                       clock-output-names = "tcon-pixel-clock";
+                       status = "disabled";
+
+                       ports {
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+
+                               tcon0_in: port@0 {
+                                       #address-cells = <1>;
+                                       #size-cells = <0>;
+                                       reg = <0>;
+
+                                       tcon0_in_be0: endpoint@0 {
+                                               reg = <0>;
+                                               remote-endpoint = <&be0_out_tcon0>;
+                                       };
+                               };
+
+                               tcon0_out: port@1 {
+                                       #address-cells = <1>;
+                                       #size-cells = <0>;
+                                       reg = <1>;
+
+                                       tcon0_out_tve0: endpoint@1 {
+                                               reg = <1>;
+                                               remote-endpoint = <&tve0_in_tcon0>;
+                                       };
+                               };
+                       };
+               };
+
+               mmc0: mmc@01c0f000 {
+                       compatible = "allwinner,sun5i-a13-mmc";
+                       reg = <0x01c0f000 0x1000>;
+                       clocks = <&ahb_gates 8>,
+                                <&mmc0_clk 0>,
+                                <&mmc0_clk 1>,
+                                <&mmc0_clk 2>;
+                       clock-names = "ahb",
+                                     "mmc",
+                                     "output",
+                                     "sample";
+                       interrupts = <32>;
+                       status = "disabled";
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+               };
+
+               mmc1: mmc@01c10000 {
+                       compatible = "allwinner,sun5i-a13-mmc";
+                       reg = <0x01c10000 0x1000>;
+                       clocks = <&ahb_gates 9>,
+                                <&mmc1_clk 0>,
+                                <&mmc1_clk 1>,
+                                <&mmc1_clk 2>;
+                       clock-names = "ahb",
+                                     "mmc",
+                                     "output",
+                                     "sample";
+                       interrupts = <33>;
+                       status = "disabled";
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+               };
+
+               mmc2: mmc@01c11000 {
+                       compatible = "allwinner,sun5i-a13-mmc";
+                       reg = <0x01c11000 0x1000>;
+                       clocks = <&ahb_gates 10>,
+                                <&mmc2_clk 0>,
+                                <&mmc2_clk 1>,
+                                <&mmc2_clk 2>;
+                       clock-names = "ahb",
+                                     "mmc",
+                                     "output",
+                                     "sample";
+                       interrupts = <34>;
+                       status = "disabled";
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+               };
+
+               usb_otg: usb@01c13000 {
+                       compatible = "allwinner,sun4i-a10-musb";
+                       reg = <0x01c13000 0x0400>;
+                       clocks = <&ahb_gates 0>;
+                       interrupts = <38>;
+                       interrupt-names = "mc";
+                       phys = <&usbphy 0>;
+                       phy-names = "usb";
+                       extcon = <&usbphy 0>;
+                       allwinner,sram = <&otg_sram 1>;
+                       status = "disabled";
+
+                       dr_mode = "otg";
+               };
+
+               usbphy: phy@01c13400 {
+                       #phy-cells = <1>;
+                       compatible = "allwinner,sun5i-a13-usb-phy";
+                       reg = <0x01c13400 0x10 0x01c14800 0x4>;
+                       reg-names = "phy_ctrl", "pmu1";
+                       clocks = <&usb_clk 8>;
+                       clock-names = "usb_phy";
+                       resets = <&usb_clk 0>, <&usb_clk 1>;
+                       reset-names = "usb0_reset", "usb1_reset";
+                       status = "disabled";
+               };
+
+               ehci0: usb@01c14000 {
+                       compatible = "allwinner,sun5i-a13-ehci", "generic-ehci";
+                       reg = <0x01c14000 0x100>;
+                       interrupts = <39>;
+                       clocks = <&ahb_gates 1>;
+                       phys = <&usbphy 1>;
+                       phy-names = "usb";
+                       status = "disabled";
+               };
+
+               ohci0: usb@01c14400 {
+                       compatible = "allwinner,sun5i-a13-ohci", "generic-ohci";
+                       reg = <0x01c14400 0x100>;
+                       interrupts = <40>;
+                       clocks = <&usb_clk 6>, <&ahb_gates 2>;
+                       phys = <&usbphy 1>;
+                       phy-names = "usb";
+                       status = "disabled";
+               };
+
+               spi2: spi@01c17000 {
+                       compatible = "allwinner,sun4i-a10-spi";
+                       reg = <0x01c17000 0x1000>;
+                       interrupts = <12>;
+                       clocks = <&ahb_gates 22>, <&spi2_clk>;
+                       clock-names = "ahb", "mod";
+                       dmas = <&dma SUN4I_DMA_DEDICATED 29>,
+                              <&dma SUN4I_DMA_DEDICATED 28>;
+                       dma-names = "rx", "tx";
+                       status = "disabled";
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+               };
+
+               intc: interrupt-controller@01c20400 {
+                       compatible = "allwinner,sun4i-a10-ic";
+                       reg = <0x01c20400 0x400>;
+                       interrupt-controller;
+                       #interrupt-cells = <1>;
+               };
+
+               pio: pinctrl@01c20800 {
+                       compatible = "nextthing,gr8-pinctrl";
+                       reg = <0x01c20800 0x400>;
+                       interrupts = <28>;
+                       clocks = <&apb0_gates 5>;
+                       gpio-controller;
+                       interrupt-controller;
+                       #interrupt-cells = <3>;
+                       #gpio-cells = <3>;
+
+                       i2c0_pins_a: i2c0@0 {
+                               allwinner,pins = "PB0", "PB1";
+                               allwinner,function = "i2c0";
+                               allwinner,drive = <SUN4I_PINCTRL_10_MA>;
+                               allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
+                       };
+
+                       i2c1_pins_a: i2c1@0 {
+                               allwinner,pins = "PB15", "PB16";
+                               allwinner,function = "i2c1";
+                               allwinner,drive = <SUN4I_PINCTRL_10_MA>;
+                               allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
+                       };
+
+                       i2c2_pins_a: i2c2@0 {
+                               allwinner,pins = "PB17", "PB18";
+                               allwinner,function = "i2c2";
+                               allwinner,drive = <SUN4I_PINCTRL_10_MA>;
+                               allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
+                       };
+
+                       i2s0_data_pins_a: i2s0-data@0 {
+                               allwinner,pins = "PB6", "PB7", "PB8", "PB9";
+                               allwinner,function = "i2s0";
+                               allwinner,drive = <SUN4I_PINCTRL_10_MA>;
+                               allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
+                       };
+
+                       i2s0_mclk_pins_a: i2s0-mclk@0 {
+                               allwinner,pins = "PB5";
+                               allwinner,function = "i2s0";
+                               allwinner,drive = <SUN4I_PINCTRL_10_MA>;
+                               allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
+                       };
+
+                       ir0_rx_pins_a: ir0@0 {
+                               allwinner,pins = "PB4";
+                               allwinner,function = "ir0";
+                               allwinner,drive = <SUN4I_PINCTRL_10_MA>;
+                               allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
+                       };
+
+                       lcd_rgb666_pins: lcd-rgb666@0 {
+                               allwinner,pins = "PD2", "PD3", "PD4", "PD5", "PD6", "PD7",
+                                                "PD10", "PD11", "PD12", "PD13", "PD14", "PD15",
+                                                "PD18", "PD19", "PD20", "PD21", "PD22", "PD23",
+                                                "PD24", "PD25", "PD26", "PD27";
+                               allwinner,function = "lcd0";
+                               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>;
+                       };
+
+                       nand_pins_a: nand-base0@0 {
+                               allwinner,pins = "PC0", "PC1", "PC2",
+                                               "PC5", "PC8", "PC9", "PC10",
+                                               "PC11", "PC12", "PC13", "PC14",
+                                               "PC15";
+                               allwinner,function = "nand0";
+                               allwinner,drive = <SUN4I_PINCTRL_10_MA>;
+                               allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
+                       };
+
+                       nand_cs0_pins_a: nand-cs@0 {
+                               allwinner,pins = "PC4";
+                               allwinner,function = "nand0";
+                               allwinner,drive = <SUN4I_PINCTRL_10_MA>;
+                               allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
+                       };
+
+                       nand_rb0_pins_a: nand-rb@0 {
+                               allwinner,pins = "PC6";
+                               allwinner,function = "nand0";
+                               allwinner,drive = <SUN4I_PINCTRL_10_MA>;
+                               allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
+                       };
+
+                       pwm0_pins_a: pwm0@0 {
+                               allwinner,pins = "PB2";
+                               allwinner,function = "pwm0";
+                               allwinner,drive = <SUN4I_PINCTRL_10_MA>;
+                               allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
+                       };
+
+                       pwm1_pins: pwm1 {
+                               allwinner,pins = "PG13";
+                               allwinner,function = "pwm1";
+                               allwinner,drive = <SUN4I_PINCTRL_10_MA>;
+                               allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
+                       };
+
+                       spdif_tx_pins_a: spdif@0 {
+                               allwinner,pins = "PB10";
+                               allwinner,function = "spdif";
+                               allwinner,drive = <SUN4I_PINCTRL_10_MA>;
+                               allwinner,pull = <SUN4I_PINCTRL_PULL_UP>;
+                       };
+
+                       uart1_pins_a: uart1@1 {
+                               allwinner,pins = "PG3", "PG4";
+                               allwinner,function = "uart1";
+                               allwinner,drive = <SUN4I_PINCTRL_10_MA>;
+                               allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
+                       };
+
+                       uart1_cts_rts_pins_a: uart1-cts-rts@0 {
+                               allwinner,pins = "PG5", "PG6";
+                               allwinner,function = "uart1";
+                               allwinner,drive = <SUN4I_PINCTRL_10_MA>;
+                               allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
+                       };
+
+                       uart2_pins_a: uart2@1 {
+                               allwinner,pins = "PD2", "PD3";
+                               allwinner,function = "uart2";
+                               allwinner,drive = <SUN4I_PINCTRL_10_MA>;
+                               allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
+                       };
+
+                       uart2_cts_rts_pins_a: uart2-cts-rts@0 {
+                               allwinner,pins = "PD4", "PD5";
+                               allwinner,function = "uart2";
+                               allwinner,drive = <SUN4I_PINCTRL_10_MA>;
+                               allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
+                       };
+
+                       uart3_pins_a: uart3@1 {
+                               allwinner,pins = "PG9", "PG10";
+                               allwinner,function = "uart3";
+                               allwinner,drive = <SUN4I_PINCTRL_10_MA>;
+                               allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
+                       };
+
+                       uart3_cts_rts_pins_a: uart3-cts-rts@0 {
+                               allwinner,pins = "PG11", "PG12";
+                               allwinner,function = "uart3";
+                               allwinner,drive = <SUN4I_PINCTRL_10_MA>;
+                               allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
+                       };
+               };
+
+               pwm: pwm@01c20e00 {
+                       compatible = "allwinner,sun5i-a10s-pwm";
+                       reg = <0x01c20e00 0xc>;
+                       clocks = <&osc24M>;
+                       #pwm-cells = <3>;
+                       status = "disabled";
+               };
+
+               timer@01c20c00 {
+                       compatible = "allwinner,sun4i-a10-timer";
+                       reg = <0x01c20c00 0x90>;
+                       interrupts = <22>;
+                       clocks = <&osc24M>;
+               };
+
+               wdt: watchdog@01c20c90 {
+                       compatible = "allwinner,sun4i-a10-wdt";
+                       reg = <0x01c20c90 0x10>;
+               };
+
+               spdif: spdif@01c21000 {
+                       #sound-dai-cells = <0>;
+                       compatible = "allwinner,sun4i-a10-spdif";
+                       reg = <0x01c21000 0x400>;
+                       interrupts = <13>;
+                       clocks = <&apb0_gates 1>, <&spdif_clk>;
+                       clock-names = "apb", "spdif";
+                       dmas = <&dma SUN4I_DMA_NORMAL 2>,
+                              <&dma SUN4I_DMA_NORMAL 2>;
+                       dma-names = "rx", "tx";
+                       status = "disabled";
+               };
+
+               ir0: ir@01c21800 {
+                       compatible = "allwinner,sun4i-a10-ir";
+                       clocks = <&apb0_gates 6>, <&ir0_clk>;
+                       clock-names = "apb", "ir";
+                       interrupts = <5>;
+                       reg = <0x01c21800 0x40>;
+                       status = "disabled";
+               };
+
+               i2s0: i2s@01c22400 {
+                       #sound-dai-cells = <0>;
+                       compatible = "allwinner,sun4i-a10-i2s";
+                       reg = <0x01c22400 0x400>;
+                       interrupts = <16>;
+                       clocks = <&apb0_gates 3>, <&i2s0_clk>;
+                       clock-names = "apb", "mod";
+                       dmas = <&dma SUN4I_DMA_NORMAL 3>,
+                              <&dma SUN4I_DMA_NORMAL 3>;
+                       dma-names = "rx", "tx";
+                       status = "disabled";
+               };
+
+               lradc: lradc@01c22800 {
+                       compatible = "allwinner,sun4i-a10-lradc-keys";
+                       reg = <0x01c22800 0x100>;
+                       interrupts = <31>;
+                       status = "disabled";
+               };
+
+               codec: codec@01c22c00 {
+                       #sound-dai-cells = <0>;
+                       compatible = "allwinner,sun4i-a10-codec";
+                       reg = <0x01c22c00 0x40>;
+                       interrupts = <30>;
+                       clocks = <&apb0_gates 0>, <&codec_clk>;
+                       clock-names = "apb", "codec";
+                       dmas = <&dma SUN4I_DMA_NORMAL 19>,
+                              <&dma SUN4I_DMA_NORMAL 19>;
+                       dma-names = "rx", "tx";
+                       status = "disabled";
+               };
+
+               rtp: rtp@01c25000 {
+                       compatible = "allwinner,sun5i-a13-ts";
+                       reg = <0x01c25000 0x100>;
+                       interrupts = <29>;
+                       #thermal-sensor-cells = <0>;
+               };
+
+               uart1: serial@01c28400 {
+                       compatible = "snps,dw-apb-uart";
+                       reg = <0x01c28400 0x400>;
+                       interrupts = <2>;
+                       reg-shift = <2>;
+                       reg-io-width = <4>;
+                       clocks = <&apb1_gates 17>;
+                       status = "disabled";
+               };
+
+               uart2: serial@01c28800 {
+                       compatible = "snps,dw-apb-uart";
+                       reg = <0x01c28800 0x400>;
+                       interrupts = <3>;
+                       reg-shift = <2>;
+                       reg-io-width = <4>;
+                       clocks = <&apb1_gates 18>;
+                       status = "disabled";
+               };
+
+               uart3: serial@01c28c00 {
+                       compatible = "snps,dw-apb-uart";
+                       reg = <0x01c28c00 0x400>;
+                       interrupts = <4>;
+                       reg-shift = <2>;
+                       reg-io-width = <4>;
+                       clocks = <&apb1_gates 19>;
+                       status = "disabled";
+               };
+
+               i2c0: i2c@01c2ac00 {
+                       compatible = "allwinner,sun4i-a10-i2c";
+                       reg = <0x01c2ac00 0x400>;
+                       interrupts = <7>;
+                       clocks = <&apb1_gates 0>;
+                       status = "disabled";
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+               };
+
+               i2c1: i2c@01c2b000 {
+                       compatible = "allwinner,sun4i-a10-i2c";
+                       reg = <0x01c2b000 0x400>;
+                       interrupts = <8>;
+                       clocks = <&apb1_gates 1>;
+                       status = "disabled";
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+               };
+
+               i2c2: i2c@01c2b400 {
+                       compatible = "allwinner,sun4i-a10-i2c";
+                       reg = <0x01c2b400 0x400>;
+                       interrupts = <9>;
+                       clocks = <&apb1_gates 2>;
+                       status = "disabled";
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+               };
+
+               timer@01c60000 {
+                       compatible = "allwinner,sun5i-a13-hstimer";
+                       reg = <0x01c60000 0x1000>;
+                       interrupts = <82>, <83>;
+                       clocks = <&ahb_gates 28>;
+               };
+
+               fe0: display-frontend@01e00000 {
+                       compatible = "allwinner,sun5i-a13-display-frontend";
+                       reg = <0x01e00000 0x20000>;
+                       interrupts = <47>;
+                       clocks = <&ahb_gates 46>, <&de_fe_clk>,
+                                <&dram_gates 25>;
+                       clock-names = "ahb", "mod",
+                                     "ram";
+                       resets = <&de_fe_clk>;
+                       status = "disabled";
+
+                       ports {
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+
+                               fe0_out: port@1 {
+                                       #address-cells = <1>;
+                                       #size-cells = <0>;
+                                       reg = <1>;
+
+                                       fe0_out_be0: endpoint@0 {
+                                               reg = <0>;
+                                               remote-endpoint = <&be0_in_fe0>;
+                                       };
+                               };
+                       };
+               };
+
+               be0: display-backend@01e60000 {
+                       compatible = "allwinner,sun5i-a13-display-backend";
+                       reg = <0x01e60000 0x10000>;
+                       clocks = <&ahb_gates 44>, <&de_be_clk>,
+                                <&dram_gates 26>;
+                       clock-names = "ahb", "mod",
+                                     "ram";
+                       resets = <&de_be_clk>;
+                       status = "disabled";
+
+                       assigned-clocks = <&de_be_clk>;
+                       assigned-clock-rates = <300000000>;
+
+                       ports {
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+
+                               be0_in: port@0 {
+                                       #address-cells = <1>;
+                                       #size-cells = <0>;
+                                       reg = <0>;
+
+                                       be0_in_fe0: endpoint@0 {
+                                               reg = <0>;
+                                               remote-endpoint = <&fe0_out_be0>;
+                                       };
+                               };
+
+                               be0_out: port@1 {
+                                       #address-cells = <1>;
+                                       #size-cells = <0>;
+                                       reg = <1>;
+
+                                       be0_out_tcon0: endpoint@0 {
+                                               reg = <0>;
+                                               remote-endpoint = <&tcon0_in_be0>;
+                                       };
+                               };
+                       };
+               };
+       };
+};
diff --git a/arch/arm/dts/sun8i-h3-nanopi-neo-air.dts b/arch/arm/dts/sun8i-h3-nanopi-neo-air.dts
new file mode 100644 (file)
index 0000000..3ba081c
--- /dev/null
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2017 Jelle van der Waa <jelle@vdwaa.nl>
+ *
+ * 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.
+ */
+
+/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 = "FriendlyARM NanoPi NEO Air";
+       compatible = "friendlyarm,nanopi-neo-air", "allwinner,sun8i-h3";
+
+       aliases {
+               serial0 = &uart0;
+       };
+
+       chosen {
+               stdout-path = "serial0:115200n8";
+       };
+
+       leds {
+               compatible = "gpio-leds";
+
+               pwr {
+                       label = "nanopi:green:pwr";
+                       gpios = <&r_pio 0 10 GPIO_ACTIVE_HIGH>; /* PL10 */
+                       default-state = "on";
+               };
+
+               status {
+                       label = "nanopi:blue:status";
+                       gpios = <&pio 0 10 GPIO_ACTIVE_HIGH>; /* PA10 */
+               };
+       };
+};
+
+&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";
+};
+
+&usbphy {
+       /* USB VBUS is always on */
+       status = "okay";
+};
diff --git a/arch/arm/dts/sun9i-a80-cx-a99.dts b/arch/arm/dts/sun9i-a80-cx-a99.dts
new file mode 100644 (file)
index 0000000..a30b6fe
--- /dev/null
@@ -0,0 +1,380 @@
+/*
+ * sun9i-a80-cx-a99.dts - Device Tree file for the Sunchip CX-A99 board.
+ *
+ * Copyright (C) 2017 Rask Ingemann Lambertsen <rask@formelder.dk>
+ *
+ * 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.
+ */
+
+/*
+ * The Sunchip CX-A99 board is found in several similar Android media
+ * players, such as:
+ *
+ * Instabox Fantasy A8 (no external antenna)
+ * Jesurun CS-Q8 (ships with larger remote control)
+ * Jesurun Maxone
+ * Rikomagic (RKM) MK80/MK80LE
+ * Tronsmart Draco AW80 Meta/Telos
+ *
+ * See the Sunchip CX-A99 page on the Linux-sunxi wiki for more information.
+ */
+
+/dts-v1/;
+#include "sun9i-a80.dtsi"
+
+#include <dt-bindings/gpio/gpio.h>
+
+/ {
+       model = "Sunchip CX-A99";
+       compatible = "sunchip,cx-a99", "allwinner,sun9i-a80";
+
+       aliases {
+               serial0 = &uart0;
+       };
+
+       chosen {
+               stdout-path = "serial0:115200n8";
+       };
+
+       leds {
+               compatible = "gpio-leds";
+
+               blue {
+                       gpios = <&pio 6 10 GPIO_ACTIVE_HIGH>;   /* PG10 */
+                       label = "cx-a99:blue:status";
+               };
+
+               red {
+                       gpios = <&pio 6 11 GPIO_ACTIVE_HIGH>;   /* PG11 */
+                       label = "cx-a99:red:status";
+               };
+       };
+
+       powerseq_wifi: powerseq-wifi {
+               compatible = "mmc-pwrseq-simple";
+               clocks = <&ac100_rtc 1>;
+               clock-names = "ext_clock";
+               reset-gpios = <&r_pio 1 0 GPIO_ACTIVE_LOW>;     /* PM0 */
+               post-power-on-delay-ms = <1>;   /* Minimum 2 cycles. */
+       };
+
+       /* USB 2.0 connector closest to the 12 V power connector. */
+       reg_usb1_vbus: regulator-usb1-vbus {
+               compatible = "regulator-fixed";
+               regulator-name = "usb1-vbus";
+               regulator-min-microvolt = <5000000>;
+               regulator-max-microvolt = <5000000>;
+               gpio = <&r_pio 0 7 /* no flag support */ 0>;    /* PL7 */
+               enable-active-high;
+       };
+
+       /* USB 2.0 connector next to the SD card slot. */
+       reg_usb3_vbus: regulator-usb3-vbus {
+               compatible = "regulator-fixed";
+               regulator-name = "usb3-vbus";
+               regulator-min-microvolt = <5000000>;
+               regulator-max-microvolt = <5000000>;
+               gpio = <&r_pio 0 8 /* no flag support */ 0>;    /* PL8 */
+               enable-active-high;
+       };
+
+       /*
+        * OZ80120 voltage regulator for the four Cortex-A15 CPU cores.
+        * Although the regulator can output 750 - 1200 mV, the permissible
+        * range for the CPU cores is only 800 - 1100 mV.
+        */
+       reg_vdd_cpub: regulator-vdd-cpub {
+               compatible = "regulator-gpio";
+
+               regulator-always-on;
+               regulator-min-microvolt = < 800000>;
+               regulator-max-microvolt = <1100000>;
+               regulator-name = "vdd-cpub";
+
+               /* Note: GPIO flags are not supported here . */
+               enable-gpio = <&r_pio 0 2 /* flags n/a */ 0>;   /* PL2 */
+               enable-active-high;
+               gpios = <&r_pio 0 3 /* no flag support */ 0>,   /* PL3 */
+                       <&r_pio 0 4 /* no flag support */ 0>,   /* PL4 */
+                       <&r_pio 0 5 /* no flag support */ 0>;   /* PL5 */
+
+               gpios-states = <1 0 0>;
+               states = <       750000 0x7
+                                800000 0x3
+                                850000 0x5
+                                900000 0x1
+                                950000 0x6
+                               1000000 0x2
+                               1100000 0x4
+                               1200000 0x0>;
+       };
+};
+
+&ehci0 {
+       status = "okay";
+};
+
+&ehci2 {
+       status = "okay";
+};
+
+/*
+ * SD card slot. Although the GPIO pin for card detection is listed as capable
+ * of generating interrupts in the "A80 User Manual", this doesn't work for
+ * some unknown reason, so poll the GPIO for card detection. This is also what
+ * the vendor sys_config.fex file specifies.
+ */
+&mmc0 {
+       bus-width = <4>;
+       cd-gpios = <&pio 7 17 GPIO_ACTIVE_LOW>; /* PH17 */
+       broken-cd;                              /* Poll. */
+       pinctrl-names = "default";
+       pinctrl-0 = <&mmc0_pins>;
+       vmmc-supply = <&reg_dcdce>;
+       status = "okay";
+};
+
+/* Ampak AP6335 IEEE 802.11 a/b/g/n/ac Wifi. */
+&mmc1 {
+       bus-width = <4>;
+       non-removable;
+       pinctrl-names = "default";
+       pinctrl-0 = <&mmc1_pins>;
+       vmmc-supply = <&reg_cldo3>;     /* See cldo2,cldo3 note. */
+       vqmmc-supply = <&reg_aldo2>;
+       mmc-pwrseq = <&powerseq_wifi>;
+       status = "okay";
+};
+
+/* On-board eMMC card. */
+&mmc2 {
+       bus-width = <8>;
+       non-removable;
+       pinctrl-names = "default";
+       pinctrl-0 = <&mmc2_8bit_pins>;
+       vmmc-supply = <&reg_dcdce>;
+       status = "okay";
+};
+
+&osc32k {
+       clocks = <&ac100_rtc 0>;
+};
+
+&r_ir {
+       status = "okay";
+};
+
+&r_rsb {
+       status = "okay";
+
+       ac100: codec@e89 {
+               compatible = "x-powers,ac100";
+               reg = <0xe89>;
+
+               ac100_codec: codec {
+                       compatible = "x-powers,ac100-codec";
+                       interrupt-parent = <&r_pio>;
+                       interrupts = <0 9 IRQ_TYPE_LEVEL_LOW>;  /* PL9 */
+                       #clock-cells = <0>;
+                       clock-output-names = "4M_adda";
+               };
+
+               ac100_rtc: rtc {
+                       compatible = "x-powers,ac100-rtc";
+                       interrupt-parent = <&nmi_intc>;
+                       interrupts = <0 IRQ_TYPE_LEVEL_LOW>;
+                       clocks = <&ac100_codec>;
+                       #clock-cells = <1>;
+                       clock-output-names = "cko1_rtc",
+                                            "cko2_rtc",
+                                            "cko3_rtc";
+               };
+       };
+
+       pmic@745 {
+               compatible = "x-powers,axp808", "x-powers,axp806";
+               x-powers,master-mode;
+               reg = <0x745>;
+               interrupt-parent = <&nmi_intc>;
+               interrupts = <0 IRQ_TYPE_LEVEL_LOW>;
+               interrupt-controller;
+               #interrupt-cells = <1>;
+
+               swin-supply = <&reg_dcdce>;
+
+               regulators {
+                       reg_aldo1: aldo1 {
+                               regulator-boot-on;
+                               regulator-min-microvolt = <3000000>;
+                               regulator-max-microvolt = <3000000>;
+                               regulator-name = "vcc-3v0";
+                       };
+
+                       /* Supplies pin groups G and M. */
+                       reg_aldo2: aldo2 {
+                               regulator-boot-on;
+                               regulator-min-microvolt = <1800000>;
+                               regulator-max-microvolt = <3600000>;
+                               regulator-name = "vddio-wifi-codec";
+                       };
+
+                       reg_aldo3: aldo3 {
+                               regulator-boot-on;
+                               regulator-min-microvolt = <2500000>;
+                               regulator-max-microvolt = <2500000>;
+                               regulator-name = "vddio-gmac";
+                       };
+
+                       reg_bldo1: bldo1 {
+                               regulator-always-on;    /* Hang if disabled */
+                               regulator-min-microvolt = <1700000>;
+                               regulator-max-microvolt = <1900000>;
+                               regulator-name = "vdd18-dll-vcc18-pll";
+                       };
+
+                       reg_bldo2: bldo2 {
+                               regulator-always-on;    /* Hang if disabled */
+                               regulator-min-microvolt = < 800000>;
+                               regulator-max-microvolt = <1100000>;
+                               regulator-name = "vdd-cpus";
+                       };
+
+                       reg_bldo3: bldo3 {
+                               regulator-min-microvolt = <1100000>;
+                               regulator-max-microvolt = <1300000>;
+                               regulator-name = "vcc12-hsic";
+                       };
+
+                       reg_bldo4: bldo4 {
+                               regulator-boot-on;
+                               regulator-min-microvolt = < 800000>;
+                               regulator-max-microvolt = <1100000>;
+                               regulator-name = "vdd09-hdmi";
+                       };
+
+                       /* Supplies PLx pins which control some regulators. */
+                       reg_cldo1: cldo1 {
+                               regulator-always-on;
+                               regulator-min-microvolt = <3300000>;
+                               regulator-max-microvolt = <3300000>;
+                               regulator-name = "vcc-pl-led";
+                       };
+
+                       /*
+                        * cldo2 and cldo3 are connected in parallel.
+                        * There is currently no way to express that.
+                        * For now, use regulator-always-on on cldo2 and lock
+                        * the voltage on both to 3.3 V.
+                        */
+                       reg_cldo2: cldo2 {
+                               regulator-always-on;
+                               regulator-min-microvolt = <3300000>;
+                               regulator-max-microvolt = <3300000>;
+                               regulator-name = "vbat2-wifi+bt";
+                       };
+
+                       reg_cldo3: cldo3 {
+                               regulator-min-microvolt = <3300000>;
+                               regulator-max-microvolt = <3300000>;
+                               regulator-name = "vbat1-wifi+bt";
+                       };
+
+                       reg_dcdca: dcdca {
+                               regulator-always-on;
+                               regulator-min-microvolt = < 800000>;
+                               regulator-max-microvolt = <1100000>;
+                               regulator-name = "vdd-cpua";
+                       };
+
+                       reg_dcdcb: dcdcb {
+                               regulator-always-on;
+                               regulator-min-microvolt = <1450000>;
+                               regulator-max-microvolt = <1550000>;
+                               regulator-name = "vcc-dram";
+                       };
+
+                       reg_dcdcc: dcdcc {
+                               regulator-min-microvolt = < 800000>;
+                               regulator-max-microvolt = <1100000>;
+                               regulator-name = "vdd-gpu";
+                       };
+
+                       reg_dcdcd: dcdcd {
+                               regulator-always-on;    /* Hang if disabled. */
+                               regulator-min-microvolt = < 800000>;
+                               regulator-max-microvolt = <1100000>;
+                               regulator-name = "vdd-sys";
+                       };
+
+                       /* Supplies pin groups B-F and H. */
+                       reg_dcdce: dcdce {
+                               regulator-always-on;
+                               regulator-min-microvolt = <3300000>;
+                               regulator-max-microvolt = <3300000>;
+                               regulator-name = "vcc-io-mmc-spdif";
+                       };
+
+                       reg_sw: sw {
+                               regulator-min-microvolt = <3300000>;
+                               regulator-max-microvolt = <3300000>;
+                               regulator-name = "vcc-gmac-codec";
+                       };
+               };
+       };
+};
+
+/*
+ * 5-pin connector opposite of the SD card slot:
+ * 1 = GND (pointed to by small triangle), 2 = GND, 3 = 3.3 V, 4 = RX, 5 = TX.
+ */
+&uart0 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&uart0_pins_a>;
+       status = "okay";
+};
+
+&usbphy1 {
+       phy-supply = <&reg_usb1_vbus>;
+       status = "okay";
+};
+
+&usbphy3 {
+       phy-supply = <&reg_usb3_vbus>;
+       status = "okay";
+};
index f68b3242b33a09b0ff0c197c817b75525c9d9bb9..92412b2ac1f63e62f19dbf9926cb0eb502e2e2bb 100644 (file)
                                allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
                        };
 
+                       mmc1_pins: mmc1 {
+                               allwinner,pins = "PG0", "PG1" ,"PG2", "PG3",
+                                                "PG4", "PG5";
+                               allwinner,function = "mmc1";
+                               allwinner,drive = <SUN4I_PINCTRL_30_MA>;
+                               allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
+                       };
+
                        mmc2_8bit_pins: mmc2_8bit {
                                allwinner,pins = "PC6", "PC7", "PC8", "PC9",
                                                 "PC10", "PC11", "PC12",
index 3f211293feb65be09be4cee24a1561f7f7ec1af9..91ca6eaf7a6774389e40fe22a8d92ba55635b745 100644 (file)
@@ -269,6 +269,12 @@ M: VishnuPatekar <vishnupatekar0510@gmail.com>
 S:     Maintained
 F:     configs/Sinovoip_BPI_M3_defconfig
 
+SUNCHIP CX-A99 BOARD
+M:     Rask Ingemann Lambertsen <rask@formelder.dk>
+S:     Maintained
+F:     configs/Sunchip_CX-A99_defconfig
+W:     https://linux-sunxi.org/Sunchip_CX-A99
+
 WEXLER-TAB7200 BOARD
 M:     Aleksei Mamlin <mamlinav@gmail.com>
 S:     Maintained
diff --git a/board/sunxi/README.nand b/board/sunxi/README.nand
new file mode 100644 (file)
index 0000000..a5d4ff0
--- /dev/null
@@ -0,0 +1,54 @@
+Allwinner NAND flashing
+=======================
+
+A lot of Allwinner devices, especially the older ones (pre-H3 era),
+comes with a NAND. NANDs storages are a pretty weak choice when it
+comes to the reliability, and it comes with a number of flaws like
+read and write disturbs, data retention issues, bloks becoming
+unusable, etc.
+
+In order to mitigate that, various strategies have been found to be
+able to recover from those issues like ECC, hardware randomization,
+and of course, redundancy for the critical parts.
+
+This is obviously something that we will take into account when
+creating our images. However, the BROM will use a quite weird pattern
+when accessing the NAND, and will access only at most 4kB per page,
+which means that we also have to split that binary accross several
+pages.
+
+In order to accomodate that, we create a tool that will generate an
+SPL image that is ready to be programmed directly embedding the ECCs,
+randomized, and with the necessary bits needed to reduce the number of
+bitflips. The U-Boot build system, when configured for the NAND will
+also generate the image sunxi-spl-with-ecc.bin that will have been
+generated by that tool.
+
+In order to flash your U-Boot image onto a board, assuming that the
+board is in FEL mode, you'll need the sunxi-tools that you can find at
+this repository: https://github.com/linux-sunxi/sunxi-tools
+
+Then, you'll need to first load an SPL to initialise the RAM:
+sunxi-fel spl spl/sunxi-spl.bin
+
+Load the binaries we'll flash into RAM:
+sunxi-fel write 0x4a000000 u-boot-dtb.bin
+sunxi-fel write 0x43000000 spl/sunxi-spl-with-ecc.bin
+
+And execute U-Boot
+sunxi-fel exe 0x4a000000
+
+On your board, you'll now have all the needed binaries into RAM, so
+you only need to erase the NAND...
+
+nand erase.chip
+
+Then write the SPL and its backup:
+
+nand write.raw.noverify 0x43000000 0 40
+nand write.raw.noverify 0x43000000 0x400000 40
+
+And finally write the U-Boot binary:
+nand write 0x4a000000 0x800000 0xc0000
+
+You can now reboot and enjoy your NAND.
\ No newline at end of file
index 4b152f8222aa2228be42f0a97937ebb95cd5e557..661ae7a98c2eb19ebebe1b258cfb9bb4d19e6bcb 100644 (file)
@@ -452,9 +452,29 @@ config CMD_MMC
 
 config CMD_NAND
        bool "nand"
+       default y if NAND_SUNXI
        help
          NAND support.
 
+if CMD_NAND
+config CMD_NAND_TRIMFFS
+       bool "nand write.trimffs"
+       default y if ARCH_SUNXI
+       help
+         Allows one to skip empty pages when flashing something on a NAND.
+
+config CMD_NAND_LOCK_UNLOCK
+       bool "nand lock/unlock"
+       help
+         NAND locking support.
+
+config CMD_NAND_TORTURE
+       bool "nand torture"
+       help
+         NAND torture support.
+
+endif # CMD_NAND
+
 config CMD_PART
        bool "part"
        select PARTITION_UUIDS
@@ -801,12 +821,33 @@ config CMD_FS_GENERIC
        help
          Enables filesystem commands (e.g. load, ls) that work for multiple
          fs types.
+
+config CMD_MTDPARTS
+       depends on ARCH_SUNXI
+       bool "MTD partition support"
+       help
+         MTD partition support
+
+config MTDIDS_DEFAULT
+       string "Default MTD IDs"
+       depends on CMD_MTDPARTS
+       help
+         Defines a default MTD ID
+
+config MTDPARTS_DEFAULT
+       string "Default MTD partition scheme"
+       depends on CMD_MTDPARTS
+       help
+         Defines a default MTD partitioning scheme in the Linux MTD command
+         line partitions format
+
 endmenu
 
 config CMD_UBI
        tristate "Enable UBI - Unsorted block images commands"
        select CRC32
        select MTD_UBI
+       default y if NAND_SUNXI
        help
          UBI is a software layer above MTD layer which admits use of LVM-like
          logical volumes on top of MTD devices, hides some complexities of
@@ -815,4 +856,14 @@ config CMD_UBI
          (www.linux-mtd.infradead.org). Activate this option if you want
          to use U-Boot UBI commands.
 
+config CMD_UBIFS
+       tristate "Enable UBIFS - Unsorted block images filesystem commands"
+       depends on CMD_UBI
+       select CRC32
+       select RBTREE if ARCH_SUNXI
+       select LZO if ARCH_SUNXI
+       default y if NAND_SUNXI
+       help
+         UBIFS is a file system for flash devices which works on top of UBI.
+
 endmenu
index b9b160dc1e2f7f8e1de776d11b2423626cb1330d..112bf1f3e3cd51e5a30d8f941b88d20ee0fae031 100644 (file)
@@ -110,11 +110,19 @@ DECLARE_GLOBAL_DATA_PTR;
 
 /* default values for mtdids and mtdparts variables */
 #if !defined(MTDIDS_DEFAULT)
+#ifdef CONFIG_MTDIDS_DEFAULT
+#define MTDIDS_DEFAULT CONFIG_MTDIDS_DEFAULT
+#else
 #define MTDIDS_DEFAULT NULL
 #endif
+#endif
 #if !defined(MTDPARTS_DEFAULT)
+#ifdef CONFIG_MTDPARTS_DEFAULT
+#define MTDPARTS_DEFAULT CONFIG_MTDPARTS_DEFAULT
+#else
 #define MTDPARTS_DEFAULT NULL
 #endif
+#endif
 #if defined(CONFIG_SYS_MTDPARTS_RUNTIME)
 extern void board_mtdparts_default(const char **mtdids, const char **mtdparts);
 #endif
index ec519d07ccde408ef1d7e682a7ed9ffad4f0a344..1879aefaf83d3e3c5b85a9113879f18cbe767e12 100644 (file)
@@ -158,6 +158,75 @@ config SPI_BOOT
 
 endmenu
 
+menu "Environment"
+
+if ARCH_SUNXI
+
+choice
+       prompt "Environment Device"
+       default ENV_IS_IN_MMC if ARCH_SUNXI
+
+config ENV_IS_IN_MMC
+       bool "Environment in an MMC device"
+       depends on CMD_MMC
+       help
+         Define this if you have an MMC device which you want to use for the
+         environment.
+
+config ENV_IS_IN_NAND
+       bool "Environment in a NAND device"
+       depends on CMD_NAND
+       help
+         Define this if you have a NAND device which you want to use for the
+         environment.
+
+config ENV_IS_IN_UBI
+       bool "Environment in a UBI volume"
+       depends on CMD_UBI
+       depends on CMD_MTDPARTS
+       help
+         Define this if you have a UBI volume which you want to use for the
+         environment.
+
+config ENV_IS_NOWHERE
+       bool "Environment is not stored"
+       help
+         Define this if you don't want to or can't have an environment stored
+         on a storage medium
+
+endchoice
+
+config ENV_OFFSET
+       hex "Environment Offset"
+       depends on !ENV_IS_IN_UBI
+       depends on !ENV_IS_NOWHERE
+       default 0x88000 if ARCH_SUNXI
+       help
+         Offset from the start of the device (or partition)
+
+config ENV_SIZE
+       hex "Environment Size"
+       depends on !ENV_IS_NOWHERE
+       default 0x20000 if ARCH_SUNXI
+       help
+         Size of the environment storage area
+
+config ENV_UBI_PART
+       string "UBI partition name"
+       depends on ENV_IS_IN_UBI
+       help
+         MTD partition containing the UBI device
+
+config ENV_UBI_VOLUME
+       string "UBI volume name"
+       depends on ENV_IS_IN_UBI
+       help
+         Name of the volume that you want to store the environment in.
+
+endif
+
+endmenu
+
 config BOOTDELAY
        int "delay in seconds before automatically booting"
        default 2
diff --git a/configs/CHIP_pro_defconfig b/configs/CHIP_pro_defconfig
new file mode 100644 (file)
index 0000000..df43e5a
--- /dev/null
@@ -0,0 +1,33 @@
+CONFIG_ARM=y
+CONFIG_ARCH_SUNXI=y
+CONFIG_SPL_I2C_SUPPORT=y
+# CONFIG_SPL_MMC_SUPPORT is not set
+CONFIG_SPL_NAND_SUPPORT=y
+CONFIG_MACH_SUN5I=y
+CONFIG_DRAM_TIMINGS_DDR3_800E_1066G_1333J=y
+CONFIG_USB0_VBUS_PIN="PB10"
+CONFIG_DEFAULT_DEVICE_TREE="sun5i-gr8-chip-pro"
+CONFIG_SYS_EXTRA_OPTIONS="CONS_INDEX=2,SYS_NAND_BLOCK_SIZE=0x40000,SYS_NAND_PAGE_SIZE=4096,SYS_NAND_OOBSIZE=256"
+CONFIG_ENV_IS_IN_UBI=y
+CONFIG_ENV_UBI_PART="UBI"
+CONFIG_ENV_UBI_VOLUME="uboot-env"
+CONFIG_SPL=y
+# CONFIG_CMD_IMLS is not set
+# CONFIG_CMD_LOADB is not set
+# CONFIG_CMD_LOADS is not set
+# CONFIG_CMD_FLASH is not set
+# CONFIG_CMD_FPGA is not set
+CONFIG_CMD_MTDPARTS=y
+CONFIG_MTDIDS_DEFAULT="nand0=sunxi-nand.0"
+CONFIG_MTDPARTS_DEFAULT="mtdparts=sunxi-nand.0:256k(spl),256k(spl-backup),2m(uboot),2m(uboot-backup),-(UBI)"
+# CONFIG_MMC is not set
+CONFIG_NAND_SUNXI=y
+CONFIG_AXP_ALDO3_VOLT=3300
+CONFIG_AXP_ALDO4_VOLT=3300
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_MUSB_GADGET=y
+CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_DOWNLOAD=y
+CONFIG_G_DNL_MANUFACTURER="Allwinner Technology"
+CONFIG_G_DNL_VENDOR_NUM=0x1f3a
+CONFIG_G_DNL_PRODUCT_NUM=0x1010
diff --git a/configs/Sunchip_CX-A99_defconfig b/configs/Sunchip_CX-A99_defconfig
new file mode 100644 (file)
index 0000000..7530d7d
--- /dev/null
@@ -0,0 +1,22 @@
+CONFIG_ARM=y
+CONFIG_ARCH_SUNXI=y
+CONFIG_MACH_SUN9I=y
+CONFIG_DRAM_CLK=600
+CONFIG_DRAM_ZQ=3881915
+CONFIG_DRAM_ODT_EN=y
+CONFIG_MMC0_CD_PIN="PH17"
+CONFIG_MMC_SUNXI_SLOT_EXTRA=2
+CONFIG_USB0_VBUS_PIN="PH15"
+CONFIG_USB0_VBUS_DET=""
+CONFIG_USB0_ID_DET=""
+CONFIG_USB1_VBUS_PIN="PL7"
+CONFIG_USB3_VBUS_PIN="PL8"
+CONFIG_DEFAULT_DEVICE_TREE="sun9i-a80-cx-a99"
+# CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
+CONFIG_SPL=y
+# CONFIG_CMD_IMLS is not set
+# CONFIG_CMD_FLASH is not set
+# CONFIG_CMD_FPGA is not set
+# CONFIG_SPL_DOS_PARTITION is not set
+# CONFIG_SPL_ISO_PARTITION is not set
+# CONFIG_SPL_EFI_PARTITION is not set
diff --git a/configs/nanopi_neo_air_defconfig b/configs/nanopi_neo_air_defconfig
new file mode 100644 (file)
index 0000000..9598bd5
--- /dev/null
@@ -0,0 +1,17 @@
+CONFIG_ARM=y
+CONFIG_ARCH_SUNXI=y
+CONFIG_MACH_SUN8I_H3=y
+CONFIG_DRAM_CLK=408
+CONFIG_DRAM_ZQ=3881979
+CONFIG_DRAM_ODT_EN=y
+CONFIG_DEFAULT_DEVICE_TREE="sun8i-h3-nanopi-neo-air"
+# CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
+CONFIG_CONSOLE_MUX=y
+CONFIG_SPL=y
+# CONFIG_CMD_IMLS is not set
+# CONFIG_CMD_FLASH is not set
+# CONFIG_CMD_FPGA is not set
+# CONFIG_SPL_DOS_PARTITION is not set
+# CONFIG_SPL_ISO_PARTITION is not set
+# CONFIG_SPL_EFI_PARTITION is not set
+CONFIG_USB_EHCI_HCD=y
diff --git a/configs/sun8i_a23_evb_defconfig b/configs/sun8i_a23_evb_defconfig
new file mode 100644 (file)
index 0000000..296df00
--- /dev/null
@@ -0,0 +1,19 @@
+CONFIG_ARM=y
+CONFIG_ARCH_SUNXI=y
+CONFIG_MACH_SUN8I_A23=y
+CONFIG_DRAM_CLK=552
+CONFIG_DRAM_ZQ=63351
+CONFIG_USB0_VBUS_PIN="axp_drivebus"
+CONFIG_USB0_VBUS_DET="axp_vbus_detect"
+CONFIG_USB1_VBUS_PIN="PH7"
+CONFIG_DEFAULT_DEVICE_TREE="sun8i-a23-evb"
+# CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
+CONFIG_SYS_EXTRA_OPTIONS="CONS_INDEX=5"
+CONFIG_SPL=y
+# CONFIG_CMD_IMLS is not set
+# CONFIG_CMD_FLASH is not set
+# CONFIG_CMD_FPGA is not set
+# CONFIG_SPL_DOS_PARTITION is not set
+# CONFIG_SPL_ISO_PARTITION is not set
+# CONFIG_SPL_EFI_PARTITION is not set
+CONFIG_USB_EHCI_HCD=y
index a2ea9b1b6dad28e5c2280f45749257dd911eb96d..a7b76f4218c35b16cbd99a70167d03b908e99e45 100644 (file)
@@ -67,12 +67,29 @@ config NAND_SUNXI
        bool "Support for NAND on Allwinner SoCs"
        depends on MACH_SUN4I || MACH_SUN5I || MACH_SUN7I
        select SYS_NAND_SELF_INIT
+       select SYS_NAND_U_BOOT_LOCATIONS
        ---help---
        Enable support for NAND. This option enables the standard and
        SPL drivers.
        The SPL driver only supports reading from the NAND using DMA
        transfers.
 
+if NAND_SUNXI
+
+config NAND_SUNXI_SPL_ECC_STRENGTH
+       int "Allwinner NAND SPL ECC Strength"
+       default 64
+
+config NAND_SUNXI_SPL_ECC_SIZE
+       int "Allwinner NAND SPL ECC Step Size"
+       default 1024
+
+config NAND_SUNXI_SPL_USABLE_PAGE_SIZE
+       int "Allwinner NAND SPL Usable Page Size"
+       default 1024
+
+endif
+
 config NAND_ARASAN
        bool "Configure Arasan Nand"
        help
@@ -127,7 +144,7 @@ config SYS_NAND_U_BOOT_LOCATIONS
 
 config SYS_NAND_U_BOOT_OFFS
        hex "Location in NAND to read U-Boot from"
-       default 0x8000 if NAND_SUNXI
+       default 0x800000 if NAND_SUNXI
        depends on SYS_NAND_U_BOOT_LOCATIONS
        help
        Set the offset from the start of the nand where u-boot should be
index 1ef7366d4c42d0cd4fdcb77af7acd29bc5251d96..eed4472bdc34b60cdb6aa2759bc961f32f70f7f0 100644 (file)
@@ -245,7 +245,7 @@ static int nand_read_page(const struct nfc_config *conf, u32 offs,
 {
        dma_addr_t dst = (dma_addr_t)dest;
        int nsectors = len / conf->ecc_size;
-       u16 rand_seed;
+       u16 rand_seed = 0;
        u32 val;
        int page;
 
@@ -258,8 +258,9 @@ static int nand_read_page(const struct nfc_config *conf, u32 offs,
        /* clear ecc status */
        writel(0, SUNXI_NFC_BASE + NFC_ECC_ST);
 
-       /* Choose correct seed */
-       rand_seed = random_seed[page % conf->nseeds];
+       /* Choose correct seed if randomized */
+       if (conf->randomize)
+               rand_seed = random_seed[page % conf->nseeds];
 
        writel((rand_seed << 16) | (conf->ecc_strength << 12) |
                (conf->randomize ? NFC_ECC_RANDOM_EN : 0) |
index 0c82395317abc1a42e6ca4076325ebff627f9db6..cb9ba78681edef0163945fdbc7e89ca7ad0d369e 100644 (file)
@@ -3,6 +3,7 @@ menu "UBI support"
 config MTD_UBI
        bool "Enable UBI - Unsorted block images"
        select CRC32
+       select RBTREE if ARCH_SUNXI
        help
          UBI is a software layer above MTD layer which admits of LVM-like
          logical volumes on top of MTD devices, hides some complexities of
index abdfada6461cbe8c4d948fbe734ac275f32234d1..a3dbe2823b0e92db5c551b39563a0d0e35077d0a 100644 (file)
@@ -21,6 +21,9 @@
 #include <malloc.h>
 #include <miiphy.h>
 #include <net.h>
+#ifdef CONFIG_DM_GPIO
+#include <asm-generic/gpio.h>
+#endif
 
 #define MDIO_CMD_MII_BUSY              BIT(0)
 #define MDIO_CMD_MII_WRITE             BIT(1)
@@ -128,11 +131,22 @@ struct emac_eth_dev {
        phys_addr_t sysctl_reg;
        struct phy_device *phydev;
        struct mii_dev *bus;
+#ifdef CONFIG_DM_GPIO
+       struct gpio_desc reset_gpio;
+#endif
+};
+
+
+struct sun8i_eth_pdata {
+       struct eth_pdata eth_pdata;
+       u32 reset_delays[3];
 };
 
+
 static int sun8i_mdio_read(struct mii_dev *bus, int addr, int devad, int reg)
 {
-       struct emac_eth_dev *priv = bus->priv;
+       struct udevice *dev = bus->priv;
+       struct emac_eth_dev *priv = dev_get_priv(dev);
        ulong start;
        u32 miiaddr = 0;
        int timeout = CONFIG_MDIO_TIMEOUT;
@@ -164,7 +178,8 @@ static int sun8i_mdio_read(struct mii_dev *bus, int addr, int devad, int reg)
 static int sun8i_mdio_write(struct mii_dev *bus, int addr, int devad, int reg,
                            u16 val)
 {
-       struct emac_eth_dev *priv = bus->priv;
+       struct udevice *dev = bus->priv;
+       struct emac_eth_dev *priv = dev_get_priv(dev);
        ulong start;
        u32 miiaddr = 0;
        int ret = -1, timeout = CONFIG_MDIO_TIMEOUT;
@@ -604,7 +619,41 @@ static void sun8i_emac_board_setup(struct emac_eth_dev *priv)
        setbits_le32(&ccm->ahb_reset0_cfg, BIT(AHB_RESET_OFFSET_GMAC));
 }
 
-static int sun8i_mdio_init(const char *name, struct  emac_eth_dev *priv)
+#if defined(CONFIG_DM_GPIO)
+static int sun8i_mdio_reset(struct mii_dev *bus)
+{
+       struct udevice *dev = bus->priv;
+       struct emac_eth_dev *priv = dev_get_priv(dev);
+       struct sun8i_eth_pdata *pdata = dev_get_platdata(dev);
+       int ret;
+
+       if (!dm_gpio_is_valid(&priv->reset_gpio))
+               return 0;
+
+       /* reset the phy */
+       ret = dm_gpio_set_value(&priv->reset_gpio, 0);
+       if (ret)
+               return ret;
+
+       udelay(pdata->reset_delays[0]);
+
+       ret = dm_gpio_set_value(&priv->reset_gpio, 1);
+       if (ret)
+               return ret;
+
+       udelay(pdata->reset_delays[1]);
+
+       ret = dm_gpio_set_value(&priv->reset_gpio, 0);
+       if (ret)
+               return ret;
+
+       udelay(pdata->reset_delays[2]);
+
+       return 0;
+}
+#endif
+
+static int sun8i_mdio_init(const char *name, struct udevice *priv)
 {
        struct mii_dev *bus = mdio_alloc();
 
@@ -617,6 +666,9 @@ static int sun8i_mdio_init(const char *name, struct  emac_eth_dev *priv)
        bus->write = sun8i_mdio_write;
        snprintf(bus->name, sizeof(bus->name), name);
        bus->priv = (void *)priv;
+#if defined(CONFIG_DM_GPIO)
+       bus->reset = sun8i_mdio_reset;
+#endif
 
        return  mdio_register(bus);
 }
@@ -696,7 +748,7 @@ static int sun8i_emac_eth_probe(struct udevice *dev)
        sun8i_emac_board_setup(priv);
        sun8i_emac_set_syscon(priv);
 
-       sun8i_mdio_init(dev->name, priv);
+       sun8i_mdio_init(dev->name, dev);
        priv->bus = miiphy_get_dev_by_name(dev->name);
 
        return sun8i_phy_init(priv, dev);
@@ -713,11 +765,16 @@ static const struct eth_ops sun8i_emac_eth_ops = {
 
 static int sun8i_emac_eth_ofdata_to_platdata(struct udevice *dev)
 {
-       struct eth_pdata *pdata = dev_get_platdata(dev);
+       struct sun8i_eth_pdata *sun8i_pdata = dev_get_platdata(dev);
+       struct eth_pdata *pdata = &sun8i_pdata->eth_pdata;
        struct emac_eth_dev *priv = dev_get_priv(dev);
        const char *phy_mode;
        int node = dev_of_offset(dev);
        int offset = 0;
+#ifdef CONFIG_DM_GPIO
+       int reset_flags = GPIOD_IS_OUT;
+       int ret = 0;
+#endif
 
        pdata->iobase = dev_get_addr_name(dev, "emac");
        priv->sysctl_reg = dev_get_addr_name(dev, "syscon");
@@ -762,6 +819,23 @@ static int sun8i_emac_eth_ofdata_to_platdata(struct udevice *dev)
        if (!priv->use_internal_phy)
                parse_phy_pins(dev);
 
+#ifdef CONFIG_DM_GPIO
+       if (fdtdec_get_bool(gd->fdt_blob, dev->of_offset,
+                           "snps,reset-active-low"))
+               reset_flags |= GPIOD_ACTIVE_LOW;
+
+       ret = gpio_request_by_name(dev, "snps,reset-gpio", 0,
+                                  &priv->reset_gpio, reset_flags);
+
+       if (ret == 0) {
+               ret = fdtdec_get_int_array(gd->fdt_blob, dev->of_offset,
+                                          "snps,reset-delays-us",
+                                          sun8i_pdata->reset_delays, 3);
+       } else if (ret == -ENOENT) {
+               ret = 0;
+       }
+#endif
+
        return 0;
 }
 
@@ -782,6 +856,6 @@ U_BOOT_DRIVER(eth_sun8i_emac) = {
        .probe  = sun8i_emac_eth_probe,
        .ops    = &sun8i_emac_eth_ops,
        .priv_auto_alloc_size = sizeof(struct emac_eth_dev),
-       .platdata_auto_alloc_size = sizeof(struct eth_pdata),
+       .platdata_auto_alloc_size = sizeof(struct sun8i_eth_pdata),
        .flags = DM_FLAG_ALLOC_PRIV_DMA,
 };
index cda2fec519535decac2de2f9e9a80e484859a473..1d475b10ddf491eca0ecf34bae39bc2c92c9bc60 100644 (file)
 #define CONFIG_SYS_NAND_MAX_ECCPOS 1664
 #define CONFIG_SYS_NAND_ONFI_DETECTION
 #define CONFIG_SYS_MAX_NAND_DEVICE 8
+
+#define CONFIG_MTD_DEVICE
+#define CONFIG_MTD_PARTITIONS
 #endif
 
 #ifdef CONFIG_SPL_SPI_SUNXI
 /* mmc config */
 #ifdef CONFIG_MMC
 #define CONFIG_MMC_SUNXI_SLOT          0
-#define CONFIG_ENV_IS_IN_MMC
+#endif
+
+#if defined(CONFIG_ENV_IS_IN_MMC)
 #define CONFIG_SYS_MMC_ENV_DEV         0       /* first detected MMC controller */
 #define CONFIG_SYS_MMC_MAX_DEVICE      4
+#elif defined(CONFIG_ENV_IS_NOWHERE)
+#define CONFIG_ENV_SIZE                        (128 << 10)
 #endif
 
 /* 64MB of malloc() pool */
 
 #define CONFIG_SYS_MONITOR_LEN         (768 << 10)     /* 768 KiB */
 
-#define CONFIG_ENV_OFFSET              (544 << 10) /* (8 + 24 + 512) KiB */
-#define CONFIG_ENV_SIZE                        (128 << 10)     /* 128 KiB */
-
 #define CONFIG_FAT_WRITE       /* enable write access */
 
 #define CONFIG_SPL_FRAMEWORK
@@ -325,13 +329,6 @@ extern int soft_i2c_gpio_scl;
 #define CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE
 #endif
 
-#if !defined CONFIG_ENV_IS_IN_MMC && \
-    !defined CONFIG_ENV_IS_IN_NAND && \
-    !defined CONFIG_ENV_IS_IN_FAT && \
-    !defined CONFIG_ENV_IS_IN_SPI_FLASH
-#define CONFIG_ENV_IS_NOWHERE
-#endif
-
 #define CONFIG_MISC_INIT_R
 
 #ifndef CONFIG_SPL_BUILD
@@ -461,6 +458,20 @@ extern int soft_i2c_gpio_scl;
        "stderr=serial\0"
 #endif
 
+#ifdef CONFIG_MTDIDS_DEFAULT
+#define SUNXI_MTDIDS_DEFAULT \
+       "mtdids=" CONFIG_MTDIDS_DEFAULT "\0"
+#else
+#define SUNXI_MTDIDS_DEFAULT
+#endif
+
+#ifdef CONFIG_MTDPARTS_DEFAULT
+#define SUNXI_MTDPARTS_DEFAULT \
+       "mtdparts=" CONFIG_MTDPARTS_DEFAULT "\0"
+#else
+#define SUNXI_MTDPARTS_DEFAULT
+#endif
+
 #define CONSOLE_ENV_SETTINGS \
        CONSOLE_STDIN_SETTINGS \
        CONSOLE_STDOUT_SETTINGS
@@ -471,6 +482,8 @@ extern int soft_i2c_gpio_scl;
        DFU_ALT_INFO_RAM \
        "fdtfile=" CONFIG_DEFAULT_DEVICE_TREE ".dtb\0" \
        "console=ttyS0,115200\0" \
+       SUNXI_MTDIDS_DEFAULT \
+       SUNXI_MTDPARTS_DEFAULT \
        BOOTCMD_SUNXI_COMPAT \
        BOOTENV
 
index b602e8ac46b6be055e6811697023006b9f3b48fd..6f94986c6b3e0fca6c4954ed83fb0f9cf148cc78 100644 (file)
@@ -8,6 +8,8 @@
 #ifndef _ENVIRONMENT_H_
 #define _ENVIRONMENT_H_
 
+#include <linux/kconfig.h>
+
 /**************************************************************************
  *
  * The "environment" is stored as a list of '\0' terminated
index 5115d047f86f6c192440705c645d7d4d02140181..a0d5d926eb6875c598fc44ed17c4496dc6521bd5 100644 (file)
@@ -61,6 +61,9 @@ config SPL_TINY_MEMSET
          size-constrained envrionments even this may be too big. Enable this
          option to reduce code size slightly at the cost of some speed.
 
+config RBTREE
+       bool
+
 source lib/dhry/Kconfig
 
 source lib/rsa/Kconfig
@@ -132,6 +135,8 @@ config LZ4
          frame format currently (2015) implemented in the Linux kernel
          (generated by 'lz4 -l'). The two formats are incompatible.
 
+config LZO
+       bool
 endmenu
 
 config ERRNO_STR
index 147715afd06a7a39216d4215e1601e5a5d977917..ec53483774b5babe49437fa79537e4d80a91b13c 100644 (file)
--- a/lib/bch.c
+++ b/lib/bch.c
  * finite fields GF(2^q). In Rapport de recherche INRIA no 2829, 1996.
  */
 
+#ifndef USE_HOSTCC
 #include <common.h>
 #include <ubi_uboot.h>
 
 #include <linux/bitops.h>
+#else
+#include <errno.h>
+#include <endian.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+#undef cpu_to_be32
+#define cpu_to_be32 htobe32
+#define DIV_ROUND_UP(n,d) (((n) + (d) - 1) / (d))
+#define kmalloc(size, flags)   malloc(size)
+#define kzalloc(size, flags)   calloc(1, size)
+#define kfree free
+#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
+#endif
+
 #include <asm/byteorder.h>
 #include <linux/bch.h>
 
@@ -95,6 +112,37 @@ struct gf_poly_deg1 {
        unsigned int   c[2];
 };
 
+#ifdef USE_HOSTCC
+static int fls(int x)
+{
+       int r = 32;
+
+       if (!x)
+               return 0;
+       if (!(x & 0xffff0000u)) {
+               x <<= 16;
+               r -= 16;
+       }
+       if (!(x & 0xff000000u)) {
+               x <<= 8;
+               r -= 8;
+       }
+       if (!(x & 0xf0000000u)) {
+               x <<= 4;
+               r -= 4;
+       }
+       if (!(x & 0xc0000000u)) {
+               x <<= 2;
+               r -= 2;
+       }
+       if (!(x & 0x80000000u)) {
+               x <<= 1;
+               r -= 1;
+       }
+       return r;
+}
+#endif
+
 /*
  * same as encode_bch(), but process input data one byte at a time
  */
index 4485ea88129f0e58d04be2f052121577b60d2b98..760aceea6383dff0cc5b4f6f394c9ddd982840df 100644 (file)
@@ -179,6 +179,10 @@ endif
 
 ifdef CONFIG_ARCH_SUNXI
 ALL-y  += $(obj)/sunxi-spl.bin
+
+ifdef CONFIG_NAND_SUNXI
+ALL-y  += $(obj)/sunxi-spl-with-ecc.bin
+endif
 endif
 
 ifeq ($(CONFIG_SYS_SOC),"at91")
@@ -300,6 +304,17 @@ cmd_mksunxiboot = $(objtree)/tools/mksunxiboot $< $@
 $(obj)/sunxi-spl.bin: $(obj)/$(SPL_BIN).bin FORCE
        $(call if_changed,mksunxiboot)
 
+quiet_cmd_sunxi_spl_image_builder = SUNXI_SPL_IMAGE_BUILDER $@
+cmd_sunxi_spl_image_builder = $(objtree)/tools/sunxi-spl-image-builder \
+                               -c $(CONFIG_NAND_SUNXI_SPL_ECC_STRENGTH)/$(CONFIG_NAND_SUNXI_SPL_ECC_SIZE) \
+                               -p $(CONFIG_SYS_NAND_PAGE_SIZE) \
+                               -o $(CONFIG_SYS_NAND_OOBSIZE) \
+                               -u $(CONFIG_NAND_SUNXI_SPL_USABLE_PAGE_SIZE) \
+                               -e $(CONFIG_SYS_NAND_BLOCK_SIZE) \
+                               -s -b $< $@
+$(obj)/sunxi-spl-with-ecc.bin: $(obj)/sunxi-spl.bin
+       $(call if_changed,sunxi_spl_image_builder)
+
 # Rule to link u-boot-spl
 # May be overridden by arch/$(ARCH)/config.mk
 quiet_cmd_u-boot-spl ?= LD      $@
index 0d1f076d782aa33bc26a9c18c55074d76b272af6..6ec71f5c7fcf0e1bae5db56092378e7b04df743e 100644 (file)
@@ -16,6 +16,7 @@
 /mkexynosspl
 /mxsboot
 /mksunxiboot
+/sunxi-spl-image-builder
 /ncb
 /proftool
 /relocate-rela
index e9cde02c906c56fa4611b6ca440e820484a58953..fa1b85bdae2f4281662b48647249fd5fdc985e89 100644 (file)
@@ -179,6 +179,8 @@ hostprogs-$(CONFIG_MX28) += mxsboot
 HOSTCFLAGS_mxsboot.o := -pedantic
 
 hostprogs-$(CONFIG_ARCH_SUNXI) += mksunxiboot
+hostprogs-$(CONFIG_ARCH_SUNXI) += sunxi-spl-image-builder
+sunxi-spl-image-builder-objs := sunxi-spl-image-builder.o lib/bch.o
 
 hostprogs-$(CONFIG_NETCONSOLE) += ncb
 hostprogs-$(CONFIG_SHA1_CHECK_UB_IMG) += ubsha1
diff --git a/tools/sunxi-spl-image-builder.c b/tools/sunxi-spl-image-builder.c
new file mode 100644 (file)
index 0000000..d538a38
--- /dev/null
@@ -0,0 +1,484 @@
+/*
+ * Allwinner NAND randomizer and image builder implementation:
+ *
+ * Copyright Â© 2016 NextThing Co.
+ * Copyright Â© 2016 Free Electrons
+ *
+ * Author: Boris Brezillon <boris.brezillon@free-electrons.com>
+ *
+ */
+
+#include <linux/bch.h>
+
+#include <getopt.h>
+#include <version.h>
+
+#define BCH_PRIMITIVE_POLY     0x5803
+
+#define ARRAY_SIZE(arr)                (sizeof(arr) / sizeof((arr)[0]))
+#define DIV_ROUND_UP(n,d)      (((n) + (d) - 1) / (d))
+
+struct image_info {
+       int ecc_strength;
+       int ecc_step_size;
+       int page_size;
+       int oob_size;
+       int usable_page_size;
+       int eraseblock_size;
+       int scramble;
+       int boot0;
+       off_t offset;
+       const char *source;
+       const char *dest;
+};
+
+static void swap_bits(uint8_t *buf, int len)
+{
+       int i, j;
+
+       for (j = 0; j < len; j++) {
+               uint8_t byte = buf[j];
+
+               buf[j] = 0;
+               for (i = 0; i < 8; i++) {
+                       if (byte & (1 << i))
+                               buf[j] |= (1 << (7 - i));
+               }
+       }
+}
+
+static uint16_t lfsr_step(uint16_t state, int count)
+{
+       state &= 0x7fff;
+       while (count--)
+               state = ((state >> 1) |
+                        ((((state >> 0) ^ (state >> 1)) & 1) << 14)) & 0x7fff;
+
+       return state;
+}
+
+static uint16_t default_scrambler_seeds[] = {
+       0x2b75, 0x0bd0, 0x5ca3, 0x62d1, 0x1c93, 0x07e9, 0x2162, 0x3a72,
+       0x0d67, 0x67f9, 0x1be7, 0x077d, 0x032f, 0x0dac, 0x2716, 0x2436,
+       0x7922, 0x1510, 0x3860, 0x5287, 0x480f, 0x4252, 0x1789, 0x5a2d,
+       0x2a49, 0x5e10, 0x437f, 0x4b4e, 0x2f45, 0x216e, 0x5cb7, 0x7130,
+       0x2a3f, 0x60e4, 0x4dc9, 0x0ef0, 0x0f52, 0x1bb9, 0x6211, 0x7a56,
+       0x226d, 0x4ea7, 0x6f36, 0x3692, 0x38bf, 0x0c62, 0x05eb, 0x4c55,
+       0x60f4, 0x728c, 0x3b6f, 0x2037, 0x7f69, 0x0936, 0x651a, 0x4ceb,
+       0x6218, 0x79f3, 0x383f, 0x18d9, 0x4f05, 0x5c82, 0x2912, 0x6f17,
+       0x6856, 0x5938, 0x1007, 0x61ab, 0x3e7f, 0x57c2, 0x542f, 0x4f62,
+       0x7454, 0x2eac, 0x7739, 0x42d4, 0x2f90, 0x435a, 0x2e52, 0x2064,
+       0x637c, 0x66ad, 0x2c90, 0x0bad, 0x759c, 0x0029, 0x0986, 0x7126,
+       0x1ca7, 0x1605, 0x386a, 0x27f5, 0x1380, 0x6d75, 0x24c3, 0x0f8e,
+       0x2b7a, 0x1418, 0x1fd1, 0x7dc1, 0x2d8e, 0x43af, 0x2267, 0x7da3,
+       0x4e3d, 0x1338, 0x50db, 0x454d, 0x764d, 0x40a3, 0x42e6, 0x262b,
+       0x2d2e, 0x1aea, 0x2e17, 0x173d, 0x3a6e, 0x71bf, 0x25f9, 0x0a5d,
+       0x7c57, 0x0fbe, 0x46ce, 0x4939, 0x6b17, 0x37bb, 0x3e91, 0x76db,
+};
+
+static uint16_t brom_scrambler_seeds[] = { 0x4a80 };
+
+static void scramble(const struct image_info *info,
+                    int page, uint8_t *data, int datalen)
+{
+       uint16_t state;
+       int i;
+
+       /* Boot0 is always scrambled no matter the command line option. */
+       if (info->boot0) {
+               state = brom_scrambler_seeds[0];
+       } else {
+               unsigned seedmod = info->eraseblock_size / info->page_size;
+
+               /* Bail out earlier if the user didn't ask for scrambling. */
+               if (!info->scramble)
+                       return;
+
+               if (seedmod > ARRAY_SIZE(default_scrambler_seeds))
+                       seedmod = ARRAY_SIZE(default_scrambler_seeds);
+
+               state = default_scrambler_seeds[page % seedmod];
+       }
+
+       /* Prepare the initial state... */
+       state = lfsr_step(state, 15);
+
+       /* and start scrambling data. */
+       for (i = 0; i < datalen; i++) {
+               data[i] ^= state;
+               state = lfsr_step(state, 8);
+       }
+}
+
+static int write_page(const struct image_info *info, uint8_t *buffer,
+                     FILE *src, FILE *rnd, FILE *dst,
+                     struct bch_control *bch, int page)
+{
+       int steps = info->usable_page_size / info->ecc_step_size;
+       int eccbytes = DIV_ROUND_UP(info->ecc_strength * 14, 8);
+       off_t pos = ftell(dst);
+       size_t pad, cnt;
+       int i;
+
+       if (eccbytes % 2)
+               eccbytes++;
+
+       memset(buffer, 0xff, info->page_size + info->oob_size);
+       cnt = fread(buffer, 1, info->usable_page_size, src);
+       if (!cnt) {
+               if (!feof(src)) {
+                       fprintf(stderr,
+                               "Failed to read data from the source\n");
+                       return -1;
+               } else {
+                       return 0;
+               }
+       }
+
+       fwrite(buffer, info->page_size + info->oob_size, 1, dst);
+
+       for (i = 0; i < info->usable_page_size; i++) {
+               if (buffer[i] !=  0xff)
+                       break;
+       }
+
+       /* We leave empty pages at 0xff. */
+       if (i == info->usable_page_size)
+               return 0;
+
+       /* Restore the source pointer to read it again. */
+       fseek(src, -cnt, SEEK_CUR);
+
+       /* Randomize unused space if scrambling is required. */
+       if (info->scramble) {
+               int offs;
+
+               if (info->boot0) {
+                       size_t ret;
+
+                       offs = steps * (info->ecc_step_size + eccbytes + 4);
+                       cnt = info->page_size + info->oob_size - offs;
+                       ret = fread(buffer + offs, 1, cnt, rnd);
+                       if (!ret && !feof(rnd)) {
+                               fprintf(stderr,
+                                       "Failed to read random data\n");
+                               return -1;
+                       }
+               } else {
+                       offs = info->page_size + (steps * (eccbytes + 4));
+                       cnt = info->page_size + info->oob_size - offs;
+                       memset(buffer + offs, 0xff, cnt);
+                       scramble(info, page, buffer + offs, cnt);
+               }
+               fseek(dst, pos + offs, SEEK_SET);
+               fwrite(buffer + offs, cnt, 1, dst);
+       }
+
+       for (i = 0; i < steps; i++) {
+               int ecc_offs, data_offs;
+               uint8_t *ecc;
+
+               memset(buffer, 0xff, info->ecc_step_size + eccbytes + 4);
+               ecc = buffer + info->ecc_step_size + 4;
+               if (info->boot0) {
+                       data_offs = i * (info->ecc_step_size + eccbytes + 4);
+                       ecc_offs = data_offs + info->ecc_step_size + 4;
+               } else {
+                       data_offs = i * info->ecc_step_size;
+                       ecc_offs = info->page_size + 4 + (i * (eccbytes + 4));
+               }
+
+               cnt = fread(buffer, 1, info->ecc_step_size, src);
+               if (!cnt && !feof(src)) {
+                       fprintf(stderr,
+                               "Failed to read data from the source\n");
+                       return -1;
+               }
+
+               pad = info->ecc_step_size - cnt;
+               if (pad) {
+                       if (info->scramble && info->boot0) {
+                               size_t ret;
+
+                               ret = fread(buffer + cnt, 1, pad, rnd);
+                               if (!ret && !feof(rnd)) {
+                                       fprintf(stderr,
+                                               "Failed to read random data\n");
+                                       return -1;
+                               }
+                       } else {
+                               memset(buffer + cnt, 0xff, pad);
+                       }
+               }
+
+               memset(ecc, 0, eccbytes);
+               swap_bits(buffer, info->ecc_step_size + 4);
+               encode_bch(bch, buffer, info->ecc_step_size + 4, ecc);
+               swap_bits(buffer, info->ecc_step_size + 4);
+               swap_bits(ecc, eccbytes);
+               scramble(info, page, buffer, info->ecc_step_size + 4 + eccbytes);
+
+               fseek(dst, pos + data_offs, SEEK_SET);
+               fwrite(buffer, info->ecc_step_size, 1, dst);
+               fseek(dst, pos + ecc_offs - 4, SEEK_SET);
+               fwrite(ecc - 4, eccbytes + 4, 1, dst);
+       }
+
+       /* Fix BBM. */
+       fseek(dst, pos + info->page_size, SEEK_SET);
+       memset(buffer, 0xff, 2);
+       fwrite(buffer, 2, 1, dst);
+
+       /* Make dst pointer point to the next page. */
+       fseek(dst, pos + info->page_size + info->oob_size, SEEK_SET);
+
+       return 0;
+}
+
+static int create_image(const struct image_info *info)
+{
+       off_t page = info->offset / info->page_size;
+       struct bch_control *bch;
+       FILE *src, *dst, *rnd;
+       uint8_t *buffer;
+
+       bch = init_bch(14, info->ecc_strength, BCH_PRIMITIVE_POLY);
+       if (!bch) {
+               fprintf(stderr, "Failed to init the BCH engine\n");
+               return -1;
+       }
+
+       buffer = malloc(info->page_size + info->oob_size);
+       if (!buffer) {
+               fprintf(stderr, "Failed to allocate the NAND page buffer\n");
+               return -1;
+       }
+
+       memset(buffer, 0xff, info->page_size + info->oob_size);
+
+       src = fopen(info->source, "r");
+       if (!src) {
+               fprintf(stderr, "Failed to open source file (%s)\n",
+                       info->source);
+               return -1;
+       }
+
+       dst = fopen(info->dest, "w");
+       if (!dst) {
+               fprintf(stderr, "Failed to open dest file (%s)\n", info->dest);
+               return -1;
+       }
+
+       rnd = fopen("/dev/urandom", "r");
+       if (!rnd) {
+               fprintf(stderr, "Failed to open /dev/urandom\n");
+               return -1;
+       }
+
+       while (!feof(src)) {
+               int ret;
+
+               ret = write_page(info, buffer, src, rnd, dst, bch, page++);
+               if (ret)
+                       return ret;
+       }
+
+       return 0;
+}
+
+static void display_help(int status)
+{
+       fprintf(status == EXIT_SUCCESS ? stdout : stderr,
+               "sunxi-nand-image-builder %s\n"
+               "\n"
+               "Usage: sunxi-nand-image-builder [OPTIONS] source-image output-image\n"
+               "\n"
+               "Creates a raw NAND image that can be read by the sunxi NAND controller.\n"
+               "\n"
+               "-h               --help               Display this help and exit\n"
+               "-c <str>/<step>  --ecc=<str>/<step>   ECC config (strength/step-size)\n"
+               "-p <size>        --page=<size>        Page size\n"
+               "-o <size>        --oob=<size>         OOB size\n"
+               "-u <size>        --usable=<size>      Usable page size\n"
+               "-e <size>        --eraseblock=<size>  Erase block size\n"
+               "-b               --boot0              Build a boot0 image.\n"
+               "-s               --scramble           Scramble data\n"
+               "-a <offset>      --address=<offset>   Where the image will be programmed.\n"
+               "\n"
+               "Notes:\n"
+               "All the information you need to pass to this tool should be part of\n"
+               "the NAND datasheet.\n"
+               "\n"
+               "The NAND controller only supports the following ECC configs\n"
+               "  Valid ECC strengths: 16, 24, 28, 32, 40, 48, 56, 60 and 64\n"
+               "  Valid ECC step size: 512 and 1024\n"
+               "\n"
+               "If you are building a boot0 image, you'll have specify extra options.\n"
+               "These options should be chosen based on the layouts described here:\n"
+               "  http://linux-sunxi.org/NAND#More_information_on_BROM_NAND\n"
+               "\n"
+               "  --usable should be assigned the 'Hardware page' value\n"
+               "  --ecc should be assigned the 'ECC capacity'/'ECC page' values\n"
+               "  --usable should be smaller than --page\n"
+               "\n"
+               "The --address option is only required for non-boot0 images that are \n"
+               "meant to be programmed at a non eraseblock aligned offset.\n"
+               "\n"
+               "Examples:\n"
+               "  The H27UCG8T2BTR-BC NAND exposes\n"
+               "  * 16k pages\n"
+               "  * 1280 OOB bytes per page\n"
+               "  * 4M eraseblocks\n"
+               "  * requires data scrambling\n"
+               "  * expects a minimum ECC of 40bits/1024bytes\n"
+               "\n"
+               "  A normal image can be generated with\n"
+               "    sunxi-nand-image-builder -p 16384 -o 1280 -e 0x400000 -s -c 40/1024\n"
+               "  A boot0 image can be generated with\n"
+               "    sunxi-nand-image-builder -p 16384 -o 1280 -e 0x400000 -s -b -u 4096 -c 64/1024\n",
+               PLAIN_VERSION);
+       exit(status);
+}
+
+static int check_image_info(struct image_info *info)
+{
+       static int valid_ecc_strengths[] = { 16, 24, 28, 32, 40, 48, 56, 60, 64 };
+       int eccbytes, eccsteps;
+       unsigned i;
+
+       if (!info->page_size) {
+               fprintf(stderr, "--page is missing\n");
+               return -EINVAL;
+       }
+
+       if (!info->page_size) {
+               fprintf(stderr, "--oob is missing\n");
+               return -EINVAL;
+       }
+
+       if (!info->eraseblock_size) {
+               fprintf(stderr, "--eraseblock is missing\n");
+               return -EINVAL;
+       }
+
+       if (info->ecc_step_size != 512 && info->ecc_step_size != 1024) {
+               fprintf(stderr, "Invalid ECC step argument: %d\n",
+                       info->ecc_step_size);
+               return -EINVAL;
+       }
+
+       for (i = 0; i < ARRAY_SIZE(valid_ecc_strengths); i++) {
+               if (valid_ecc_strengths[i] == info->ecc_strength)
+                       break;
+       }
+
+       if (i == ARRAY_SIZE(valid_ecc_strengths)) {
+               fprintf(stderr, "Invalid ECC strength argument: %d\n",
+                       info->ecc_strength);
+               return -EINVAL;
+       }
+
+       eccbytes = DIV_ROUND_UP(info->ecc_strength * 14, 8);
+       if (eccbytes % 2)
+               eccbytes++;
+       eccbytes += 4;
+
+       eccsteps = info->usable_page_size / info->ecc_step_size;
+
+       if (info->page_size + info->oob_size <
+           info->usable_page_size + (eccsteps * eccbytes)) {
+               fprintf(stderr,
+                       "ECC bytes do not fit in the NAND page, choose a weaker ECC\n");
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+int main(int argc, char **argv)
+{
+       struct image_info info;
+
+       memset(&info, 0, sizeof(info));
+       /*
+        * Process user arguments
+        */
+       for (;;) {
+               int option_index = 0;
+               char *endptr = NULL;
+               static const struct option long_options[] = {
+                       {"help", no_argument, 0, 'h'},
+                       {"ecc", required_argument, 0, 'c'},
+                       {"page", required_argument, 0, 'p'},
+                       {"oob", required_argument, 0, 'o'},
+                       {"usable", required_argument, 0, 'u'},
+                       {"eraseblock", required_argument, 0, 'e'},
+                       {"boot0", no_argument, 0, 'b'},
+                       {"scramble", no_argument, 0, 's'},
+                       {"address", required_argument, 0, 'a'},
+                       {0, 0, 0, 0},
+               };
+
+               int c = getopt_long(argc, argv, "c:p:o:u:e:ba:sh",
+                               long_options, &option_index);
+               if (c == EOF)
+                       break;
+
+               switch (c) {
+               case 'h':
+                       display_help(0);
+                       break;
+               case 's':
+                       info.scramble = 1;
+                       break;
+               case 'c':
+                       info.ecc_strength = strtol(optarg, &endptr, 0);
+                       if (endptr || *endptr == '/')
+                               info.ecc_step_size = strtol(endptr + 1, NULL, 0);
+                       break;
+               case 'p':
+                       info.page_size = strtol(optarg, NULL, 0);
+                       break;
+               case 'o':
+                       info.oob_size = strtol(optarg, NULL, 0);
+                       break;
+               case 'u':
+                       info.usable_page_size = strtol(optarg, NULL, 0);
+                       break;
+               case 'e':
+                       info.eraseblock_size = strtol(optarg, NULL, 0);
+                       break;
+               case 'b':
+                       info.boot0 = 1;
+                       break;
+               case 'a':
+                       info.offset = strtoull(optarg, NULL, 0);
+                       break;
+               case '?':
+                       display_help(-1);
+                       break;
+               }
+       }
+
+       if ((argc - optind) != 2)
+               display_help(-1);
+
+       info.source = argv[optind];
+       info.dest = argv[optind + 1];
+
+       if (!info.boot0) {
+               info.usable_page_size = info.page_size;
+       } else if (!info.usable_page_size) {
+               if (info.page_size > 8192)
+                       info.usable_page_size = 8192;
+               else if (info.page_size > 4096)
+                       info.usable_page_size = 4096;
+               else
+                       info.usable_page_size = 1024;
+       }
+
+       if (check_image_info(&info))
+               display_help(-1);
+
+       return create_image(&info);
+}