Merge branch 'master' of git://git.denx.de/u-boot-sunxi

master
Tom Rini 7 years ago
commit 089795090a
  1. 3
      MAINTAINERS
  2. 3
      Makefile
  3. 7
      arch/arm/dts/Makefile
  4. 6
      arch/arm/dts/axp209.dtsi
  5. 266
      arch/arm/dts/sun5i-gr8-chip-pro.dts
  6. 1132
      arch/arm/dts/sun5i-gr8.dtsi
  7. 97
      arch/arm/dts/sun8i-h3-nanopi-neo-air.dts
  8. 380
      arch/arm/dts/sun9i-a80-cx-a99.dts
  9. 8
      arch/arm/dts/sun9i-a80.dtsi
  10. 6
      board/sunxi/MAINTAINERS
  11. 54
      board/sunxi/README.nand
  12. 51
      cmd/Kconfig
  13. 8
      cmd/mtdparts.c
  14. 69
      common/Kconfig
  15. 33
      configs/CHIP_pro_defconfig
  16. 22
      configs/Sunchip_CX-A99_defconfig
  17. 17
      configs/nanopi_neo_air_defconfig
  18. 19
      configs/sun8i_a23_evb_defconfig
  19. 19
      drivers/mtd/nand/Kconfig
  20. 7
      drivers/mtd/nand/sunxi_nand_spl.c
  21. 1
      drivers/mtd/ubi/Kconfig
  22. 86
      drivers/net/sun8i_emac.c
  23. 35
      include/configs/sunxi-common.h
  24. 2
      include/environment.h
  25. 5
      lib/Kconfig
  26. 48
      lib/bch.c
  27. 15
      scripts/Makefile.spl
  28. 1
      tools/.gitignore
  29. 2
      tools/Makefile
  30. 484
      tools/sunxi-spl-image-builder.c

@ -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>

@ -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
@:

@ -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 \

@ -53,6 +53,12 @@
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>;

@ -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";
};

File diff suppressed because it is too large Load Diff

@ -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";
};

@ -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";
};

@ -701,6 +701,14 @@
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",

@ -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

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

@ -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

@ -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

@ -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

@ -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

@ -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

@ -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

@ -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

@ -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

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

@ -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

@ -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,
};

@ -125,6 +125,9 @@
#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
@ -134,9 +137,13 @@
/* 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 */
@ -159,9 +166,6 @@
#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

@ -8,6 +8,8 @@
#ifndef _ENVIRONMENT_H_
#define _ENVIRONMENT_H_
#include <linux/kconfig.h>
/**************************************************************************
*
* The "environment" is stored as a list of '\0' terminated

@ -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

@ -54,10 +54,27 @@
* 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
*/

@ -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 $@

1
tools/.gitignore vendored

@ -16,6 +16,7 @@
/mkexynosspl
/mxsboot
/mksunxiboot
/sunxi-spl-image-builder
/ncb
/proftool
/relocate-rela

@ -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

@ -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);
}
Loading…
Cancel
Save