Merge git://git.denx.de/u-boot-imx

lime2-spi
Tom Rini 6 years ago
commit de76610545
  1. 4
      README
  2. 14
      arch/arm/cpu/arm926ejs/mxs/spl_mem_init.c
  3. 2
      arch/arm/dts/Makefile
  4. 4
      arch/arm/dts/imx53-kp.dts
  5. 0
      arch/arm/dts/imx6ul-geam-u-boot.dtsi
  6. 0
      arch/arm/dts/imx6ul-geam.dts
  7. 28
      arch/arm/dts/imx7-colibri.dts
  8. 491
      arch/arm/dts/imx7s.dtsi
  9. 42
      arch/arm/mach-imx/cache.c
  10. 7
      arch/arm/mach-imx/mx7/soc.c
  11. 4
      board/engicam/common/board.c
  12. 4
      board/engicam/common/spl.c
  13. 1
      board/ge/bx50v3/MAINTAINERS
  14. 6
      board/k+p/bootscripts/tpcboot.cmd
  15. 34
      board/k+p/kp_imx53/kp_imx53.c
  16. 10
      board/liebherr/display5/common.c
  17. 1
      board/liebherr/display5/common.h
  18. 41
      board/liebherr/display5/display5.c
  19. 78
      board/liebherr/display5/spl.c
  20. 182
      board/solidrun/mx6cuboxi/mx6cuboxi.c
  21. 5
      common/spl/Kconfig
  22. 1
      configs/cl-som-imx7_defconfig
  23. 6
      configs/display5_defconfig
  24. 3
      configs/display5_factory_defconfig
  25. 2
      configs/imx6ul_geam_mmc_defconfig
  26. 2
      configs/imx6ul_geam_nand_defconfig
  27. 6
      configs/kp_imx53_defconfig
  28. 2
      drivers/gpio/Kconfig
  29. 16
      drivers/mtd/nand/Kconfig
  30. 2
      drivers/mtd/nand/Makefile
  31. 405
      drivers/mtd/nand/mxs_nand.c
  32. 73
      drivers/mtd/nand/mxs_nand.h
  33. 86
      drivers/mtd/nand/mxs_nand_dt.c
  34. 40
      drivers/mtd/nand/mxs_nand_spl.c
  35. 3
      drivers/mtd/nand/nand_base.c
  36. 3
      drivers/power/pmic/pfuze100.c
  37. 2
      drivers/power/pmic/pmic_pfuze3000.c
  38. 102
      include/configs/display5.h
  39. 1
      include/configs/kp_imx53.h
  40. 24
      include/configs/mx6cuboxi.h
  41. 2
      include/configs/pico-imx7d.h
  42. 2
      include/configs/wandboard.h
  43. 15
      include/dt-bindings/clock/imx7d-clock.h
  44. 16
      include/dt-bindings/power/imx7-power.h
  45. 10
      include/linux/mtd/rawnand.h
  46. 2
      include/power/pfuze3000_pmic.h
  47. 1
      scripts/config_whitelist.txt

@ -2625,6 +2625,10 @@ FIT uImage format:
CONFIG_SPL_NAND_DRIVERS
SPL uses normal NAND drivers, not minimal drivers.
CONFIG_SPL_NAND_IDENT
SPL uses the chip ID list to identify the NAND flash.
Requires CONFIG_SPL_NAND_BASE.
CONFIG_SPL_NAND_ECC
Include standard software ECC in the SPL

@ -15,7 +15,7 @@
#include "mxs_init.h"
static uint32_t dram_vals[] = {
__weak uint32_t mxs_dram_vals[] = {
/*
* i.MX28 DDR2 at 200MHz
*/
@ -100,11 +100,11 @@ static void initialize_dram_values(void)
int i;
debug("SPL: Setting mx28 board specific SDRAM parameters\n");
mxs_adjust_memory_params(dram_vals);
mxs_adjust_memory_params(mxs_dram_vals);
debug("SPL: Applying SDRAM parameters\n");
for (i = 0; i < ARRAY_SIZE(dram_vals); i++)
writel(dram_vals[i], MXS_DRAM_BASE + (4 * i));
for (i = 0; i < ARRAY_SIZE(mxs_dram_vals); i++)
writel(mxs_dram_vals[i], MXS_DRAM_BASE + (4 * i));
}
#else
static void initialize_dram_values(void)
@ -112,7 +112,7 @@ static void initialize_dram_values(void)
int i;
debug("SPL: Setting mx23 board specific SDRAM parameters\n");
mxs_adjust_memory_params(dram_vals);
mxs_adjust_memory_params(mxs_dram_vals);
/*
* HW_DRAM_CTL27, HW_DRAM_CTL28 and HW_DRAM_CTL35 are not initialized as
@ -124,10 +124,10 @@ static void initialize_dram_values(void)
* So skip the initialization of these HW_DRAM_CTL registers.
*/
debug("SPL: Applying SDRAM parameters\n");
for (i = 0; i < ARRAY_SIZE(dram_vals); i++) {
for (i = 0; i < ARRAY_SIZE(mxs_dram_vals); i++) {
if (i == 8 || i == 27 || i == 28 || i == 35)
continue;
writel(dram_vals[i], MXS_DRAM_BASE + (4 * i));
writel(mxs_dram_vals[i], MXS_DRAM_BASE + (4 * i));
}
/*

@ -425,7 +425,7 @@ dtb-$(CONFIG_MX6SX) += \
imx6sx-sdb.dtb
dtb-$(CONFIG_MX6UL) += \
imx6ul-geam-kit.dtb \
imx6ul-geam.dtb \
imx6ul-isiot-emmc.dtb \
imx6ul-isiot-nand.dtb \
imx6ul-opos6uldev.dtb

@ -86,6 +86,10 @@
MX53_PAD_PATA_DA_2__GPIO7_8 0x1e4
/* BOOSTER_OFF */
MX53_PAD_EIM_CS0__GPIO2_23 0x1e4
/* LCD BACKLIGHT */
MX53_PAD_GPIO_1__GPIO1_1 0x1e4
/* KEY1 GPIO */
MX53_PAD_EIM_RW__GPIO2_26 0x1e4
>;
};

@ -16,6 +16,15 @@
};
};
&gpmi {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_gpmi_nand>;
fsl,use-minimum-ecc;
nand-on-flash-bbt;
nand-ecc-mode = "hw";
status = "okay";
};
&i2c1 {
pinctrl-names = "default", "gpio";
pinctrl-0 = <&pinctrl_i2c1>;
@ -48,6 +57,25 @@
};
&iomuxc {
pinctrl_gpmi_nand: gpmi-nand-grp {
fsl,pins = <
MX7D_PAD_SD3_CLK__NAND_CLE 0x71
MX7D_PAD_SD3_CMD__NAND_ALE 0x71
MX7D_PAD_SAI1_TX_BCLK__NAND_CE0_B 0x71
MX7D_PAD_SAI1_TX_DATA__NAND_READY_B 0x74
MX7D_PAD_SD3_STROBE__NAND_RE_B 0x71
MX7D_PAD_SD3_RESET_B__NAND_WE_B 0x71
MX7D_PAD_SD3_DATA0__NAND_DATA00 0x71
MX7D_PAD_SD3_DATA1__NAND_DATA01 0x71
MX7D_PAD_SD3_DATA2__NAND_DATA02 0x71
MX7D_PAD_SD3_DATA3__NAND_DATA03 0x71
MX7D_PAD_SD3_DATA4__NAND_DATA04 0x71
MX7D_PAD_SD3_DATA5__NAND_DATA05 0x71
MX7D_PAD_SD3_DATA6__NAND_DATA06 0x71
MX7D_PAD_SD3_DATA7__NAND_DATA07 0x71
>;
};
pinctrl_i2c4: i2c4-grp {
fsl,pins = <
MX7D_PAD_ENET1_RGMII_TD3__I2C4_SDA 0x4000007f

@ -42,6 +42,7 @@
*/
#include <dt-bindings/clock/imx7d-clock.h>
#include <dt-bindings/power/imx7-power.h>
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/input/input.h>
#include <dt-bindings/interrupt-controller/arm-gic.h>
@ -57,7 +58,7 @@
* Also for U-Boot there must be a pre-existing /memory node.
*/
chosen {};
memory { device_type = "memory"; reg = <0 0>; };
memory { device_type = "memory"; };
aliases {
gpio0 = &gpio1;
@ -115,11 +116,77 @@
clock-output-names = "osc";
};
usbphynop1: usbphynop1 {
compatible = "usb-nop-xceiv";
clocks = <&clks IMX7D_USB_PHY1_CLK>;
clock-names = "main_clk";
#phy-cells = <0>;
};
usbphynop3: usbphynop3 {
compatible = "usb-nop-xceiv";
clocks = <&clks IMX7D_USB_HSIC_ROOT_CLK>;
clock-names = "main_clk";
#phy-cells = <0>;
};
pmu {
compatible = "arm,cortex-a7-pmu";
interrupt-parent = <&gpc>;
interrupts = <GIC_SPI 92 IRQ_TYPE_LEVEL_HIGH>;
interrupt-affinity = <&cpu0>;
};
replicator {
/*
* non-configurable replicators don't show up on the
* AMBA bus. As such no need to add "arm,primecell"
*/
compatible = "arm,coresight-replicator";
ports {
#address-cells = <1>;
#size-cells = <0>;
/* replicator output ports */
port@0 {
reg = <0>;
replicator_out_port0: endpoint {
remote-endpoint = <&tpiu_in_port>;
};
};
port@1 {
reg = <1>;
replicator_out_port1: endpoint {
remote-endpoint = <&etr_in_port>;
};
};
/* replicator input port */
port@2 {
reg = <0>;
replicator_in_port0: endpoint {
slave-mode;
remote-endpoint = <&etf_out_port>;
};
};
};
};
timer {
compatible = "arm,armv7-timer";
interrupt-parent = <&intc>;
interrupts = <GIC_PPI 13 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
<GIC_PPI 14 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
<GIC_PPI 11 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
<GIC_PPI 10 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>;
};
soc {
#address-cells = <1>;
#size-cells = <1>;
compatible = "simple-bus";
interrupt-parent = <&intc>;
interrupt-parent = <&gpc>;
ranges;
funnel@30041000 {
@ -259,62 +326,18 @@
};
};
replicator {
/*
* non-configurable replicators don't show up on the
* AMBA bus. As such no need to add "arm,primecell"
*/
compatible = "arm,coresight-replicator";
ports {
#address-cells = <1>;
#size-cells = <0>;
/* replicator output ports */
port@0 {
reg = <0>;
replicator_out_port0: endpoint {
remote-endpoint = <&tpiu_in_port>;
};
};
port@1 {
reg = <1>;
replicator_out_port1: endpoint {
remote-endpoint = <&etr_in_port>;
};
};
/* replicator input port */
port@2 {
reg = <0>;
replicator_in_port0: endpoint {
slave-mode;
remote-endpoint = <&etf_out_port>;
};
};
};
};
intc: interrupt-controller@31001000 {
compatible = "arm,cortex-a7-gic";
interrupts = <GIC_PPI 9 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>;
#interrupt-cells = <3>;
interrupt-controller;
interrupt-parent = <&intc>;
reg = <0x31001000 0x1000>,
<0x31002000 0x2000>,
<0x31004000 0x2000>,
<0x31006000 0x2000>;
};
timer {
compatible = "arm,armv7-timer";
interrupts = <GIC_PPI 13 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
<GIC_PPI 14 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
<GIC_PPI 11 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
<GIC_PPI 10 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>;
};
aips1: aips-bus@30000000 {
compatible = "fsl,aips-bus", "simple-bus";
#address-cells = <1>;
@ -482,20 +505,49 @@
status = "disabled";
};
kpp: kpp@30320000 {
compatible = "fsl,imx7d-kpp", "fsl,imx21-kpp";
reg = <0x30320000 0x10000>;
interrupts = <GIC_SPI 80 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clks IMX7D_KPP_ROOT_CLK>;
status = "disabled";
};
iomuxc: iomuxc@30330000 {
compatible = "fsl,imx7d-iomuxc";
reg = <0x30330000 0x10000>;
};
gpr: iomuxc-gpr@30340000 {
compatible = "fsl,imx7d-iomuxc-gpr", "syscon";
compatible = "fsl,imx7d-iomuxc-gpr",
"fsl,imx6q-iomuxc-gpr", "syscon";
reg = <0x30340000 0x10000>;
};
ocotp: ocotp-ctrl@30350000 {
#address-cells = <1>;
#size-cells = <1>;
compatible = "fsl,imx7d-ocotp", "syscon";
reg = <0x30350000 0x10000>;
clocks = <&clks IMX7D_OCOTP_CLK>;
tempmon_calib: calib@3c {
reg = <0x3c 0x4>;
};
tempmon_temp_grade: temp-grade@10 {
reg = <0x10 0x4>;
};
};
tempmon: tempmon {
compatible = "fsl,imx7d-tempmon";
interrupts = <GIC_SPI 49 IRQ_TYPE_LEVEL_HIGH>;
fsl,tempmon =<&anatop>;
nvmem-cells = <&tempmon_calib>,
<&tempmon_temp_grade>;
nvmem-cell-names = "calib", "temp_grade";
clocks = <&clks IMX7D_PLL_SYS_MAIN_CLK>;
};
anatop: anatop@30360000 {
@ -504,8 +556,11 @@
reg = <0x30360000 0x10000>;
interrupts = <GIC_SPI 49 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 51 IRQ_TYPE_LEVEL_HIGH>;
#address-cells = <1>;
#size-cells = <0>;
reg_1p0d: regulator-vdd1p0d {
reg_1p0d: regulator-vdd1p0d@30360210 {
reg = <0x30360210>;
compatible = "fsl,anatop-regulator";
regulator-name = "vdd1p0d";
regulator-min-microvolt = <800000>;
@ -516,6 +571,7 @@
anatop-min-bit-val = <8>;
anatop-min-voltage = <800000>;
anatop-max-voltage = <1200000>;
anatop-enable-bit = <0>;
};
};
@ -529,12 +585,15 @@
offset = <0x34>;
interrupts = <GIC_SPI 19 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 20 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clks IMX7D_SNVS_CLK>;
clock-names = "snvs-rtc";
};
snvs_poweroff: snvs-poweroff {
compatible = "syscon-poweroff";
regmap = <&snvs>;
offset = <0x38>;
value = <0x60>;
mask = <0x60>;
};
@ -558,11 +617,32 @@
};
src: src@30390000 {
compatible = "fsl,imx7d-src", "fsl,imx51-src", "syscon";
compatible = "fsl,imx7d-src", "syscon";
reg = <0x30390000 0x10000>;
interrupts = <GIC_SPI 89 IRQ_TYPE_LEVEL_HIGH>;
#reset-cells = <1>;
};
gpc: gpc@303a0000 {
compatible = "fsl,imx7d-gpc";
reg = <0x303a0000 0x10000>;
interrupt-controller;
interrupts = <GIC_SPI 87 IRQ_TYPE_LEVEL_HIGH>;
#interrupt-cells = <3>;
interrupt-parent = <&intc>;
#power-domain-cells = <1>;
pgc {
#address-cells = <1>;
#size-cells = <0>;
pgc_pcie_phy: pgc-power-domain@1 {
#power-domain-cells = <0>;
reg = <1>;
power-supply = <&reg_1p0d>;
};
};
};
};
aips2: aips-bus@30400000 {
@ -609,7 +689,7 @@
clocks = <&clks IMX7D_PWM1_ROOT_CLK>,
<&clks IMX7D_PWM1_ROOT_CLK>;
clock-names = "ipg", "per";
#pwm-cells = <2>;
#pwm-cells = <3>;
status = "disabled";
};
@ -620,7 +700,7 @@
clocks = <&clks IMX7D_PWM2_ROOT_CLK>,
<&clks IMX7D_PWM2_ROOT_CLK>;
clock-names = "ipg", "per";
#pwm-cells = <2>;
#pwm-cells = <3>;
status = "disabled";
};
@ -631,7 +711,7 @@
clocks = <&clks IMX7D_PWM3_ROOT_CLK>,
<&clks IMX7D_PWM3_ROOT_CLK>;
clock-names = "ipg", "per";
#pwm-cells = <2>;
#pwm-cells = <3>;
status = "disabled";
};
@ -642,7 +722,7 @@
clocks = <&clks IMX7D_PWM4_ROOT_CLK>,
<&clks IMX7D_PWM4_ROOT_CLK>;
clock-names = "ipg", "per";
#pwm-cells = <2>;
#pwm-cells = <3>;
status = "disabled";
};
@ -664,118 +744,156 @@
reg = <0x30800000 0x400000>;
ranges;
ecspi1: ecspi@30820000 {
spba-bus@30800000 {
compatible = "fsl,spba-bus", "simple-bus";
#address-cells = <1>;
#size-cells = <0>;
compatible = "fsl,imx7d-ecspi", "fsl,imx51-ecspi";
reg = <0x30820000 0x10000>;
interrupts = <GIC_SPI 31 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clks IMX7D_ECSPI1_ROOT_CLK>,
<&clks IMX7D_ECSPI1_ROOT_CLK>;
clock-names = "ipg", "per";
status = "disabled";
};
#size-cells = <1>;
reg = <0x30800000 0x100000>;
ranges;
ecspi1: ecspi@30820000 {
#address-cells = <1>;
#size-cells = <0>;
compatible = "fsl,imx7d-ecspi", "fsl,imx51-ecspi";
reg = <0x30820000 0x10000>;
interrupts = <GIC_SPI 31 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clks IMX7D_ECSPI1_ROOT_CLK>,
<&clks IMX7D_ECSPI1_ROOT_CLK>;
clock-names = "ipg", "per";
status = "disabled";
};
ecspi2: ecspi@30830000 {
#address-cells = <1>;
#size-cells = <0>;
compatible = "fsl,imx7d-ecspi", "fsl,imx51-ecspi";
reg = <0x30830000 0x10000>;
interrupts = <GIC_SPI 32 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clks IMX7D_ECSPI2_ROOT_CLK>,
<&clks IMX7D_ECSPI2_ROOT_CLK>;
clock-names = "ipg", "per";
status = "disabled";
};
ecspi2: ecspi@30830000 {
#address-cells = <1>;
#size-cells = <0>;
compatible = "fsl,imx7d-ecspi", "fsl,imx51-ecspi";
reg = <0x30830000 0x10000>;
interrupts = <GIC_SPI 32 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clks IMX7D_ECSPI2_ROOT_CLK>,
<&clks IMX7D_ECSPI2_ROOT_CLK>;
clock-names = "ipg", "per";
status = "disabled";
};
ecspi3: ecspi@30840000 {
#address-cells = <1>;
#size-cells = <0>;
compatible = "fsl,imx7d-ecspi", "fsl,imx51-ecspi";
reg = <0x30840000 0x10000>;
interrupts = <GIC_SPI 33 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clks IMX7D_ECSPI3_ROOT_CLK>,
<&clks IMX7D_ECSPI3_ROOT_CLK>;
clock-names = "ipg", "per";
status = "disabled";
};
ecspi3: ecspi@30840000 {
#address-cells = <1>;
#size-cells = <0>;
compatible = "fsl,imx7d-ecspi", "fsl,imx51-ecspi";
reg = <0x30840000 0x10000>;
interrupts = <GIC_SPI 33 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clks IMX7D_ECSPI3_ROOT_CLK>,
<&clks IMX7D_ECSPI3_ROOT_CLK>;
clock-names = "ipg", "per";
status = "disabled";
};
uart1: serial@30860000 {
compatible = "fsl,imx7d-uart",
"fsl,imx6q-uart";
reg = <0x30860000 0x10000>;
interrupts = <GIC_SPI 26 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clks IMX7D_UART1_ROOT_CLK>,
<&clks IMX7D_UART1_ROOT_CLK>;
clock-names = "ipg", "per";
status = "disabled";
};
uart1: serial@30860000 {
compatible = "fsl,imx7d-uart",
"fsl,imx6q-uart";
reg = <0x30860000 0x10000>;
interrupts = <GIC_SPI 26 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clks IMX7D_UART1_ROOT_CLK>,
<&clks IMX7D_UART1_ROOT_CLK>;
clock-names = "ipg", "per";
status = "disabled";
};
uart2: serial@30890000 {
compatible = "fsl,imx7d-uart",
"fsl,imx6q-uart";
reg = <0x30890000 0x10000>;
interrupts = <GIC_SPI 27 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clks IMX7D_UART2_ROOT_CLK>,
<&clks IMX7D_UART2_ROOT_CLK>;
clock-names = "ipg", "per";
status = "disabled";
};
uart2: serial@30890000 {
compatible = "fsl,imx7d-uart",
"fsl,imx6q-uart";
reg = <0x30890000 0x10000>;
interrupts = <GIC_SPI 27 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clks IMX7D_UART2_ROOT_CLK>,
<&clks IMX7D_UART2_ROOT_CLK>;
clock-names = "ipg", "per";
status = "disabled";
};
uart3: serial@30880000 {
compatible = "fsl,imx7d-uart",
"fsl,imx6q-uart";
reg = <0x30880000 0x10000>;
interrupts = <GIC_SPI 28 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clks IMX7D_UART3_ROOT_CLK>,
<&clks IMX7D_UART3_ROOT_CLK>;
clock-names = "ipg", "per";
status = "disabled";
};
uart3: serial@30880000 {
compatible = "fsl,imx7d-uart",
"fsl,imx6q-uart";
reg = <0x30880000 0x10000>;
interrupts = <GIC_SPI 28 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clks IMX7D_UART3_ROOT_CLK>,
<&clks IMX7D_UART3_ROOT_CLK>;
clock-names = "ipg", "per";
status = "disabled";
};
sai1: sai@308a0000 {
#sound-dai-cells = <0>;
compatible = "fsl,imx7d-sai", "fsl,imx6sx-sai";
reg = <0x308a0000 0x10000>;
interrupts = <GIC_SPI 95 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clks IMX7D_SAI1_IPG_CLK>,
<&clks IMX7D_SAI1_ROOT_CLK>,
<&clks IMX7D_CLK_DUMMY>,
<&clks IMX7D_CLK_DUMMY>;
clock-names = "bus", "mclk1", "mclk2", "mclk3";
dma-names = "rx", "tx";
dmas = <&sdma 8 24 0>, <&sdma 9 24 0>;
status = "disabled";
};
sai1: sai@308a0000 {
#sound-dai-cells = <0>;
compatible = "fsl,imx7d-sai", "fsl,imx6sx-sai";
reg = <0x308a0000 0x10000>;
interrupts = <GIC_SPI 95 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clks IMX7D_SAI1_IPG_CLK>,
<&clks IMX7D_SAI1_ROOT_CLK>,
<&clks IMX7D_CLK_DUMMY>,
<&clks IMX7D_CLK_DUMMY>;
clock-names = "bus", "mclk1", "mclk2", "mclk3";
dma-names = "rx", "tx";
dmas = <&sdma 8 24 0>, <&sdma 9 24 0>;
status = "disabled";
};
sai2: sai@308b0000 {
#sound-dai-cells = <0>;
compatible = "fsl,imx7d-sai", "fsl,imx6sx-sai";
reg = <0x308b0000 0x10000>;
interrupts = <GIC_SPI 96 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clks IMX7D_SAI2_IPG_CLK>,
<&clks IMX7D_SAI2_ROOT_CLK>,
<&clks IMX7D_CLK_DUMMY>,
<&clks IMX7D_CLK_DUMMY>;
clock-names = "bus", "mclk1", "mclk2", "mclk3";
dma-names = "rx", "tx";
dmas = <&sdma 10 24 0>, <&sdma 11 24 0>;
status = "disabled";
sai2: sai@308b0000 {
#sound-dai-cells = <0>;
compatible = "fsl,imx7d-sai", "fsl,imx6sx-sai";
reg = <0x308b0000 0x10000>;
interrupts = <GIC_SPI 96 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clks IMX7D_SAI2_IPG_CLK>,
<&clks IMX7D_SAI2_ROOT_CLK>,
<&clks IMX7D_CLK_DUMMY>,
<&clks IMX7D_CLK_DUMMY>;
clock-names = "bus", "mclk1", "mclk2", "mclk3";
dma-names = "rx", "tx";
dmas = <&sdma 10 24 0>, <&sdma 11 24 0>;
status = "disabled";
};
sai3: sai@308c0000 {
#sound-dai-cells = <0>;
compatible = "fsl,imx7d-sai", "fsl,imx6sx-sai";
reg = <0x308c0000 0x10000>;
interrupts = <GIC_SPI 50 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clks IMX7D_SAI3_IPG_CLK>,
<&clks IMX7D_SAI3_ROOT_CLK>,
<&clks IMX7D_CLK_DUMMY>,
<&clks IMX7D_CLK_DUMMY>;
clock-names = "bus", "mclk1", "mclk2", "mclk3";
dma-names = "rx", "tx";
dmas = <&sdma 12 24 0>, <&sdma 13 24 0>;
status = "disabled";
};
};
sai3: sai@308c0000 {
#sound-dai-cells = <0>;
compatible = "fsl,imx7d-sai", "fsl,imx6sx-sai";
reg = <0x308c0000 0x10000>;
interrupts = <GIC_SPI 50 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clks IMX7D_SAI3_IPG_CLK>,
<&clks IMX7D_SAI3_ROOT_CLK>,
<&clks IMX7D_CLK_DUMMY>,
<&clks IMX7D_CLK_DUMMY>;
clock-names = "bus", "mclk1", "mclk2", "mclk3";
dma-names = "rx", "tx";
dmas = <&sdma 12 24 0>, <&sdma 13 24 0>;
status = "disabled";
crypto: caam@30900000 {
compatible = "fsl,sec-v4.0";
#address-cells = <1>;
#size-cells = <1>;
reg = <0x30900000 0x40000>;
ranges = <0 0x30900000 0x40000>;
interrupts = <GIC_SPI 91 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clks IMX7D_CAAM_CLK>,
<&clks IMX7D_AHB_CHANNEL_ROOT_CLK>;
clock-names = "ipg", "aclk";
sec_jr0: jr0@1000 {
compatible = "fsl,sec-v4.0-job-ring";
reg = <0x1000 0x1000>;
interrupts = <GIC_SPI 105 IRQ_TYPE_LEVEL_HIGH>;
};
sec_jr1: jr1@2000 {
compatible = "fsl,sec-v4.0-job-ring";
reg = <0x2000 0x1000>;
interrupts = <GIC_SPI 106 IRQ_TYPE_LEVEL_HIGH>;
};
sec_jr2: jr1@3000 {
compatible = "fsl,sec-v4.0-job-ring";
reg = <0x3000 0x1000>;
interrupts = <GIC_SPI 114 IRQ_TYPE_LEVEL_HIGH>;
};
};
flexcan1: can@30a00000 {
@ -918,24 +1036,12 @@
reg = <0x30b30200 0x200>;
};
usbphynop1: usbphynop1 {
compatible = "usb-nop-xceiv";
clocks = <&clks IMX7D_USB_PHY1_CLK>;
clock-names = "main_clk";
};
usbphynop3: usbphynop3 {
compatible = "usb-nop-xceiv";
clocks = <&clks IMX7D_USB_HSIC_ROOT_CLK>;
clock-names = "main_clk";
};
usdhc1: usdhc@30b40000 {
compatible = "fsl,imx7d-usdhc", "fsl,imx6sl-usdhc";
reg = <0x30b40000 0x10000>;
interrupts = <GIC_SPI 22 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clks IMX7D_CLK_DUMMY>,
<&clks IMX7D_CLK_DUMMY>,
clocks = <&clks IMX7D_IPG_ROOT_CLK>,
<&clks IMX7D_NAND_USDHC_BUS_ROOT_CLK>,
<&clks IMX7D_USDHC1_ROOT_CLK>;
clock-names = "ipg", "ahb", "per";
bus-width = <4>;
@ -946,8 +1052,8 @@
compatible = "fsl,imx7d-usdhc", "fsl,imx6sl-usdhc";
reg = <0x30b50000 0x10000>;
interrupts = <GIC_SPI 23 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clks IMX7D_CLK_DUMMY>,
<&clks IMX7D_CLK_DUMMY>,
clocks = <&clks IMX7D_IPG_ROOT_CLK>,
<&clks IMX7D_NAND_USDHC_BUS_ROOT_CLK>,
<&clks IMX7D_USDHC2_ROOT_CLK>;
clock-names = "ipg", "ahb", "per";
bus-width = <4>;
@ -958,8 +1064,8 @@
compatible = "fsl,imx7d-usdhc", "fsl,imx6sl-usdhc";
reg = <0x30b60000 0x10000>;
interrupts = <GIC_SPI 24 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clks IMX7D_CLK_DUMMY>,
<&clks IMX7D_CLK_DUMMY>,
clocks = <&clks IMX7D_IPG_ROOT_CLK>,
<&clks IMX7D_NAND_USDHC_BUS_ROOT_CLK>,
<&clks IMX7D_USDHC3_ROOT_CLK>;
clock-names = "ipg", "ahb", "per";
bus-width = <4>;
@ -980,9 +1086,11 @@
fec1: ethernet@30be0000 {
compatible = "fsl,imx7d-fec", "fsl,imx6sx-fec";
reg = <0x30be0000 0x10000>;
interrupts = <GIC_SPI 118 IRQ_TYPE_LEVEL_HIGH>,
interrupt-names = "int0", "int1", "int2", "pps";
interrupts = <GIC_SPI 120 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 118 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 119 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 120 IRQ_TYPE_LEVEL_HIGH>;
<GIC_SPI 121 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clks IMX7D_ENET_AXI_ROOT_CLK>,
<&clks IMX7D_ENET_AXI_ROOT_CLK>,
<&clks IMX7D_ENET1_TIME_ROOT_CLK>,
@ -995,5 +1103,36 @@
status = "disabled";
};
};
dma_apbh: dma-apbh@33000000 {
compatible = "fsl,imx7d-dma-apbh", "fsl,imx28-dma-apbh";
reg = <0x33000000 0x2000>;
interrupts = <GIC_SPI 12 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 12 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 12 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 12 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "gpmi0", "gpmi1", "gpmi2", "gpmi3";
#dma-cells = <1>;
dma-channels = <4>;
clocks = <&clks IMX7D_NAND_USDHC_BUS_RAWNAND_CLK>;
};
gpmi: gpmi-nand@33002000{
compatible = "fsl,imx7d-gpmi-nand";
#address-cells = <1>;
#size-cells = <1>;
reg = <0x33002000 0x2000>, <0x33004000 0x4000>;
reg-names = "gpmi-nand", "bch";
interrupts = <GIC_SPI 14 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "bch";
clocks = <&clks IMX7D_NAND_RAWNAND_CLK>,
<&clks IMX7D_NAND_USDHC_BUS_RAWNAND_CLK>;
clock-names = "gpmi_io", "gpmi_bch_apb";
dmas = <&dma_apbh 0>;
dma-names = "rx-tx";
status = "disabled";
assigned-clocks = <&clks IMX7D_NAND_ROOT_SRC>;
assigned-clock-parents = <&clks IMX7D_PLL_ENET_MAIN_500M_CLK>;
};
};
};

@ -9,6 +9,34 @@
#include <asm/io.h>
#include <asm/mach-imx/sys_proto.h>
static void enable_ca7_smp(void)
{
u32 val;
/* Read MIDR */
asm volatile ("mrc p15, 0, %0, c0, c0, 0\n\t" : "=r"(val));
val = (val >> 4);
val &= 0xf;
/* Only set the SMP for Cortex A7 */
if (val == 0x7) {
/* Read auxiliary control register */
asm volatile ("mrc p15, 0, %0, c1, c0, 1\n\t" : "=r"(val));
if (val & (1 << 6))
return;
/* Enable SMP */
val |= (1 << 6);
/* Write auxiliary control register */
asm volatile ("mcr p15, 0, %0, c1, c0, 1\n\t" : : "r"(val));
DSB;
ISB;
}
}
#ifndef CONFIG_SYS_DCACHE_OFF
void enable_caches(void)
{
@ -20,6 +48,9 @@ void enable_caches(void)
/* Avoid random hang when download by usb */
invalidate_dcache_all();
/* Set ACTLR.SMP bit for Cortex-A7 */
enable_ca7_smp();
/* Enable D-cache. I-cache is already enabled in start.S */
dcache_enable();
@ -31,6 +62,17 @@ void enable_caches(void)
IRAM_SIZE,
option);
}
#else
void enable_caches(void)
{
/*
* Set ACTLR.SMP bit for Cortex-A7, even if the caches are
* disabled by u-boot
*/
enable_ca7_smp();
puts("WARNING: Caches not enabled\n");
}
#endif
#ifndef CONFIG_SYS_L2CACHE_OFF

@ -280,13 +280,6 @@ const struct boot_mode soc_boot_modes[] = {
void s_init(void)
{
#if !defined CONFIG_SPL_BUILD
/* Enable SMP mode for CPU0, by setting bit 6 of Auxiliary Ctl reg */
asm volatile(
"mrc p15, 0, r0, c1, c0, 1\n"
"orr r0, r0, #1 << 6\n"
"mcr p15, 0, r0, c1, c0, 1\n");
#endif
/* clock configuration. */
clock_init();

@ -50,8 +50,8 @@ static void setenv_fdt_file(void)
env_set("fdt_file", "imx6q-icore-rqs.dtb");
else if (is_mx6dl() || is_mx6solo())
env_set("fdt_file", "imx6dl-icore-rqs.dtb");
} else if (!strcmp(cmp_dtb, "imx6ul-geam-kit"))
env_set("fdt_file", "imx6ul-geam-kit.dtb");
} else if (!strcmp(cmp_dtb, "imx6ul-geam"))
env_set("fdt_file", "imx6ul-geam.dtb");
else if (!strcmp(cmp_dtb, "imx6ul-isiot-mmc"))
env_set("fdt_file", "imx6ul-isiot-emmc.dtb");
else if (!strcmp(cmp_dtb, "imx6ul-isiot-emmc"))

@ -43,10 +43,14 @@ int board_fit_config_name_match(const char *name)
return 0;
else if (is_mx6dq() && !strcmp(name, "imx6q-icore-rqs"))
return 0;
else if (is_mx6dq() && !strcmp(name, "imx6q-icore-mipi"))
return 0;
else if ((is_mx6dl() || is_mx6solo()) && !strcmp(name, "imx6dl-icore"))
return 0;
else if ((is_mx6dl() || is_mx6solo()) && !strcmp(name, "imx6dl-icore-rqs"))
return 0;
else if ((is_mx6dl() || is_mx6solo()) && !strcmp(name, "imx6dl-icore-mipi"))
return 0;
else
return -1;
}

@ -3,6 +3,7 @@ M: Martin Donnelly <martin.donnelly@ge.com>
S: Maintained
F: board/ge/bx50v3/
F: include/configs/ge_bx50v3.h
F: configs/ge_bx50v3_defconfig
F: configs/ge_b450v3_defconfig
F: configs/ge_b650v3_defconfig
F: configs/ge_b850v3_defconfig

@ -23,6 +23,10 @@ setenv mmcroot "/dev/mmcblk${devnum}p2 rootwait rw"
setenv displayargs ""
setenv mmcargs "setenv bootargs console=${console} ${smp} root=${mmcroot} \
${displayargs}"
setenv miscadj "
if test '${boardsoc}' = 'imx53'; then
setenv bootargs '${bootargs} di=${dig_in} key1=${key1}';
fi;"
setenv boot_fitImage "
setenv fdt_conf 'conf@${boardsoc}-${boardname}.dtb';
setenv itbcfg "\"#\${fdt_conf}\"";
@ -39,6 +43,7 @@ if test -e ${devtype} ${devnum}:${distro_bootpart} ${kernel_file}; then
if load ${devtype} ${devnum}:${distro_bootpart} ${loadaddr} \
${kernel_file}; then
run mmcargs;
run miscadj;
run boot_fitImage;
fi;
fi;"
@ -52,6 +57,7 @@ setenv download_kernel "tftpboot ${loadaddr} ${kernel_file}"
setenv boot_tftp_kernel "
if run download_kernel; then
run mmcargs;
run miscadj;
run boot_fitImage;
fi"

@ -22,6 +22,8 @@
#define VBUS_PWR_EN IMX_GPIO_NR(7, 8)
#define PHY_nRST IMX_GPIO_NR(7, 6)
#define BOOSTER_OFF IMX_GPIO_NR(2, 23)
#define LCD_BACKLIGHT IMX_GPIO_NR(1, 1)
#define KEY1 IMX_GPIO_NR(2, 26)
DECLARE_GLOBAL_DATA_PTR;
@ -43,18 +45,6 @@ int dram_init_banksize(void)
return 0;
}
u32 get_board_rev(void)
{
struct iim_regs *iim = (struct iim_regs *)IMX_IIM_BASE;
struct fuse_bank *bank = &iim->bank[0];
struct fuse_bank0_regs *fuse =
(struct fuse_bank0_regs *)bank->fuse_regs;
int rev = readl(&fuse->gp[6]);
return (get_cpu_rev() & ~(0xF << 8)) | (rev & 0xF) << 8;
}
#ifdef CONFIG_USB_EHCI_MX5
int board_ehci_hcd_init(int port)
{
@ -189,10 +179,28 @@ void eth_phy_reset(void)
udelay(50);
}
void board_disable_display(void)
{
gpio_request(LCD_BACKLIGHT, "LCD_BACKLIGHT");
gpio_direction_output(LCD_BACKLIGHT, 0);
}
void board_misc_setup(void)
{
gpio_request(KEY1, "KEY1_GPIO");
gpio_direction_input(KEY1);
if (gpio_get_value(KEY1))
env_set("key1", "off");
else
env_set("key1", "on");
}
int board_late_init(void)
{
int ret = 0;
board_disable_display();
setup_ups();
if (!power_init())
@ -207,5 +215,7 @@ int board_late_init(void)
show_eeprom();
read_board_id();
board_misc_setup();
return ret;
}

@ -34,6 +34,16 @@ void displ5_set_iomux_uart(void)
SETUP_IOMUX_PADS(uart_pads);
}
iomux_v3_cfg_t const misc_pads_spl[] = {
/* Emergency recovery pin */
MX6_PAD_EIM_D29__GPIO3_IO29 | MUX_PAD_CTRL(NO_PAD_CTRL),
};
void displ5_set_iomux_misc_spl(void)
{
SETUP_IOMUX_PADS(misc_pads_spl);
}
#ifdef CONFIG_MXC_SPI
iomux_v3_cfg_t const ecspi_pads[] = {
/* SPI3 */

@ -37,5 +37,6 @@ void displ5_set_iomux_ecspi_spl(void);
void displ5_set_iomux_ecspi(void);
void displ5_set_iomux_usdhc_spl(void);
void displ5_set_iomux_usdhc(void);
void displ5_set_iomux_misc_spl(void);
#endif /* __DISPL5_COMMON_H_ */

@ -25,6 +25,7 @@
#include <miiphy.h>
#include <netdev.h>
#include <i2c.h>
#include <environment.h>
#include <dm.h>
#include <dm/platform_data/serial_mxc.h>
@ -44,6 +45,7 @@ static bool sw_ids_valid;
static u32 cpu_id;
static u32 unit_id;
#define EM_PAD IMX_GPIO_NR(3, 29)
#define SW0 IMX_GPIO_NR(2, 4)
#define SW1 IMX_GPIO_NR(2, 5)
#define SW2 IMX_GPIO_NR(2, 6)
@ -179,6 +181,9 @@ iomux_v3_cfg_t const misc_pads[] = {
/* XTALOSC */
MX6_PAD_GPIO_3__XTALOSC_REF_CLK_24M | MUX_PAD_CTRL(NO_PAD_CTRL),
/* Emergency recovery pin */
MX6_PAD_EIM_D29__GPIO3_IO29 | MUX_PAD_CTRL(NO_PAD_CTRL),
};
#ifdef CONFIG_FSL_ESDHC
@ -250,6 +255,25 @@ static void setup_iomux_enet(void)
gpio_direction_input(IMX_GPIO_NR(1, 28)); /*INT#_GBE*/
}
static int setup_mac_from_fuse(void)
{
unsigned char enetaddr[6];
int ret;
ret = eth_env_get_enetaddr("ethaddr", enetaddr);
if (ret) /* ethaddr is already set */
return 0;
imx_get_mac_from_fuse(0, enetaddr);
if (is_valid_ethaddr(enetaddr)) {
eth_env_set_enetaddr("ethaddr", enetaddr);
return 0;
}
return 0;
}
int board_eth_init(bd_t *bd)
{
struct phy_device *phydev;
@ -264,6 +288,8 @@ int board_eth_init(bd_t *bd)
if (ret)
return ret;
setup_mac_from_fuse();
bus = fec_get_miibus(IMX_FEC_BASE, -1);
if (!bus)
return -ENODEV;
@ -369,7 +395,22 @@ static inline void setup_boot_modes(void) {}
int misc_init_r(void)
{
int ret;
setup_boot_modes();
ret = gpio_request(EM_PAD, "Emergency_PAD");
if (ret) {
printf("Can't request emergency PAD gpio\n");
return ret;
}
ret = gpio_direction_input(EM_PAD);
if (ret) {
printf("Can't set emergency PAD direction\n");
return ret;
}
return 0;
}

@ -16,10 +16,12 @@
#include <asm/arch/imx-regs.h>
#include "asm/arch/iomux.h"
#include <asm/mach-imx/iomux-v3.h>
#include <asm/gpio.h>
#include <environment.h>
#include <fsl_esdhc.h>
#include <netdev.h>
#include <bootcount.h>
#include <watchdog.h>
#include "common.h"
DECLARE_GLOBAL_DATA_PTR;
@ -115,6 +117,49 @@ static void ccgr_init(void)
writel(0x000003FF, &ccm->CCGR6);
}
#ifdef CONFIG_MX6_DDRCAL
static void spl_dram_print_cal(struct mx6_ddr_sysinfo const *sysinfo)
{
struct mx6_mmdc_calibration calibration = {0};
mmdc_read_calibration(sysinfo, &calibration);
debug(".p0_mpdgctrl0\t= 0x%08X\n", calibration.p0_mpdgctrl0);
debug(".p0_mpdgctrl1\t= 0x%08X\n", calibration.p0_mpdgctrl1);
debug(".p0_mprddlctl\t= 0x%08X\n", calibration.p0_mprddlctl);
debug(".p0_mpwrdlctl\t= 0x%08X\n", calibration.p0_mpwrdlctl);
debug(".p0_mpwldectrl0\t= 0x%08X\n", calibration.p0_mpwldectrl0);
debug(".p0_mpwldectrl1\t= 0x%08X\n", calibration.p0_mpwldectrl1);
debug(".p1_mpdgctrl0\t= 0x%08X\n", calibration.p1_mpdgctrl0);
debug(".p1_mpdgctrl1\t= 0x%08X\n", calibration.p1_mpdgctrl1);
debug(".p1_mprddlctl\t= 0x%08X\n", calibration.p1_mprddlctl);
debug(".p1_mpwrdlctl\t= 0x%08X\n", calibration.p1_mpwrdlctl);
debug(".p1_mpwldectrl0\t= 0x%08X\n", calibration.p1_mpwldectrl0);
debug(".p1_mpwldectrl1\t= 0x%08X\n", calibration.p1_mpwldectrl1);
}
static void spl_dram_perform_cal(struct mx6_ddr_sysinfo const *sysinfo)
{
int ret;
/* Perform DDR DRAM calibration */
udelay(100);
ret = mmdc_do_write_level_calibration(sysinfo);
if (ret) {
printf("DDR: Write level calibration error [%d]\n", ret);
return;
}
ret = mmdc_do_dqs_calibration(sysinfo);
if (ret) {
printf("DDR: DQS calibration error [%d]\n", ret);
return;
}
spl_dram_print_cal(sysinfo);
}
#endif /* CONFIG_MX6_DDRCAL */
static void spl_dram_init(void)
{
struct mx6_ddr_sysinfo sysinfo = {
@ -141,6 +186,10 @@ static void spl_dram_init(void)
mx6dq_dram_iocfg(64, &mx6_ddr_ioregs, &mx6_grp_ioregs);
mx6_dram_cfg(&sysinfo, &mx6_4x256mx16_mmdc_calib, &mt41k128m16jt_125);
#ifdef CONFIG_MX6_DDRCAL
spl_dram_perform_cal(&sysinfo);
#endif
}
#ifdef CONFIG_SPL_SPI_SUPPORT
@ -194,10 +243,28 @@ void board_init_f(ulong dummy)
/* Clear the BSS. */
memset(__bss_start, 0, __bss_end - __bss_start);
displ5_set_iomux_misc_spl();
/* Initialize and reset WDT in SPL */
hw_watchdog_init();
WATCHDOG_RESET();
/* load/boot image from boot device */
board_init_r(NULL, 0);
}
#define EM_PAD IMX_GPIO_NR(3, 29)
int board_check_emergency_pad(void)
{
int ret;
ret = gpio_direction_input(EM_PAD);
if (ret)
return ret;
return !gpio_get_value(EM_PAD);
}
void board_boot_order(u32 *spl_boot_list)
{
/* Default boot sequence SPI -> MMC */
@ -206,12 +273,19 @@ void board_boot_order(u32 *spl_boot_list)
spl_boot_list[2] = BOOT_DEVICE_UART;
spl_boot_list[3] = BOOT_DEVICE_NONE;
/*
* In case of emergency PAD pressed, we always boot
* to proper u-boot and perform recovery tasks there.
*/
if (board_check_emergency_pad())
return;
#ifdef CONFIG_SPL_ENV_SUPPORT
/* 'fastboot' */
const char *s;
env_init();
env_load();
if (env_init() || env_load())
return;
s = env_get("BOOT_FROM");
if (s && !bootcount_error() && strcmp(s, "ACTIVE") == 0) {

@ -57,9 +57,58 @@ DECLARE_GLOBAL_DATA_PTR;
#define ETH_PHY_RESET IMX_GPIO_NR(4, 15)
#define USB_H1_VBUS IMX_GPIO_NR(1, 0)
enum board_type {
CUBOXI = 0x00,
HUMMINGBOARD = 0x01,
HUMMINGBOARD2 = 0x02,
UNKNOWN = 0x03,
};
#define MEM_STRIDE 0x4000000
static u32 get_ram_size_stride_test(u32 *base, u32 maxsize)
{
volatile u32 *addr;
u32 save[64];
u32 cnt;
u32 size;
int i = 0;
/* First save the data */
for (cnt = 0; cnt < maxsize; cnt += MEM_STRIDE) {
addr = (volatile u32 *)((u32)base + cnt); /* pointer arith! */
sync ();
save[i++] = *addr;
sync ();
}
/* First write a signature */
* (volatile u32 *)base = 0x12345678;
for (size = MEM_STRIDE; size < maxsize; size += MEM_STRIDE) {
* (volatile u32 *)((u32)base + size) = size;
sync ();
if (* (volatile u32 *)((u32)base) == size) { /* We reached the overlapping address */
break;
}
}
/* Restore the data */
for (cnt = (maxsize - MEM_STRIDE); i > 0; cnt -= MEM_STRIDE) {
addr = (volatile u32 *)((u32)base + cnt); /* pointer arith! */
sync ();
*addr = save[i--];
sync ();
}
return (size);
}
int dram_init(void)
{
gd->ram_size = imx_ddr_size();
u32 max_size = imx_ddr_size();
gd->ram_size = get_ram_size_stride_test((u32 *) CONFIG_SYS_SDRAM_BASE,
(u32)max_size);
return 0;
}
@ -77,10 +126,17 @@ static iomux_v3_cfg_t const usdhc2_pads[] = {
IOMUX_PADS(PAD_SD2_DAT3__SD2_DATA3 | MUX_PAD_CTRL(USDHC_PAD_CTRL)),
};
static iomux_v3_cfg_t const hb_cbi_sense[] = {
static iomux_v3_cfg_t const board_detect[] = {
/* These pins are for sensing if it is a CuBox-i or a HummingBoard */
IOMUX_PADS(PAD_KEY_ROW1__GPIO4_IO09 | MUX_PAD_CTRL(UART_PAD_CTRL)),
IOMUX_PADS(PAD_EIM_DA4__GPIO3_IO04 | MUX_PAD_CTRL(UART_PAD_CTRL)),
IOMUX_PADS(PAD_SD4_DAT0__GPIO2_IO08 | MUX_PAD_CTRL(UART_PAD_CTRL)),
};
static iomux_v3_cfg_t const som_rev_detect[] = {
/* These pins are for sensing if it is a CuBox-i or a HummingBoard */
IOMUX_PADS(PAD_CSI0_DAT14__GPIO6_IO00 | MUX_PAD_CTRL(UART_PAD_CTRL)),
IOMUX_PADS(PAD_CSI0_DAT18__GPIO6_IO04 | MUX_PAD_CTRL(UART_PAD_CTRL)),
};
static iomux_v3_cfg_t const usb_pads[] = {
@ -333,88 +389,110 @@ int board_init(void)
return ret;
}
static bool is_hummingboard(void)
static enum board_type board_type(void)
{
int val1, val2;
int val1, val2, val3;
SETUP_IOMUX_PADS(hb_cbi_sense);
gpio_direction_input(IMX_GPIO_NR(4, 9));
gpio_direction_input(IMX_GPIO_NR(3, 4));
val1 = gpio_get_value(IMX_GPIO_NR(4, 9));
val2 = gpio_get_value(IMX_GPIO_NR(3, 4));
SETUP_IOMUX_PADS(board_detect);
/*
* Machine selection -
* Machine val1, val2
* -------------------------
* HB2 x x
* HB rev 3.x x 0
* CBi 0 1
* HB 1 1
* Machine val1, val2, val3
* ----------------------------
* HB2 x x 0
* HB rev 3.x x 0 x
* CBi 0 1 x
* HB 1 1 x
*/
if (val2 == 0)
return true;
else if (val1 == 0)
return false;
else
return true;
}
gpio_direction_input(IMX_GPIO_NR(2, 8));
val3 = gpio_get_value(IMX_GPIO_NR(2, 8));
static bool is_hummingboard2(void)
{
int val1;
if (val3 == 0)
return HUMMINGBOARD2;
SETUP_IOMUX_PADS(hb_cbi_sense);
gpio_direction_input(IMX_GPIO_NR(3, 4));
val2 = gpio_get_value(IMX_GPIO_NR(3, 4));
gpio_direction_input(IMX_GPIO_NR(2, 8));
if (val2 == 0)
return HUMMINGBOARD;
val1 = gpio_get_value(IMX_GPIO_NR(2, 8));
gpio_direction_input(IMX_GPIO_NR(4, 9));
val1 = gpio_get_value(IMX_GPIO_NR(4, 9));
/*
* Machine selection -
* Machine val1
* -------------------
* HB2 0
* HB rev 3.x x
* CBi x
* HB x
*/
if (val1 == 0) {
return CUBOXI;
} else {
return HUMMINGBOARD;
}
}
static bool is_rev_15_som(void)
{
int val1, val2;
SETUP_IOMUX_PADS(som_rev_detect);
val1 = gpio_get_value(IMX_GPIO_NR(6, 0));
val2 = gpio_get_value(IMX_GPIO_NR(6, 4));
if (val1 == 0)
if (val1 == 1 && val2 == 0)
return true;
else
return false;
return false;
}
int checkboard(void)
{
if (is_hummingboard2())
puts("Board: MX6 Hummingboard2\n");
else if (is_hummingboard())
puts("Board: MX6 Hummingboard\n");
switch (board_type()) {
case CUBOXI:
puts("Board: MX6 Cubox-i");
break;
case HUMMINGBOARD:
puts("Board: MX6 HummingBoard");
break;
case HUMMINGBOARD2:
puts("Board: MX6 HummingBoard2");
break;
case UNKNOWN:
default:
puts("Board: Unknown\n");
goto out;
}
if (is_rev_15_som())
puts(" (som rev 1.5)\n");
else
puts("Board: MX6 Cubox-i\n");
puts("\n");
out:
return 0;
}
int board_late_init(void)
{
#ifdef CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG
if (is_hummingboard2())
env_set("board_name", "HUMMINGBOARD2");
else if (is_hummingboard())
switch (board_type()) {
case CUBOXI:
env_set("board_name", "CUBOXI");
break;
case HUMMINGBOARD:
env_set("board_name", "HUMMINGBOARD");
else
break;
case HUMMINGBOARD2:
env_set("board_name", "HUMMINGBOARD2");
break;
case UNKNOWN:
default:
env_set("board_name", "CUBOXI");
}
if (is_mx6dq())
env_set("board_rev", "MX6Q");
else
env_set("board_rev", "MX6DL");
if (is_rev_15_som())
env_set("som_rev", "V15");
#endif
return 0;
@ -590,7 +668,7 @@ static struct mx6_ddr3_cfg mem_ddr_4g = {
.density = 4,
.width = 16,
.banks = 8,
.rowaddr = 15,
.rowaddr = 16,
.coladdr = 10,
.pagesz = 2,
.trcd = 1375,

@ -152,7 +152,8 @@ config SPL_DISPLAY_PRINT
config SYS_MMCSD_RAW_MODE_U_BOOT_USE_SECTOR
bool "MMC raw mode: by sector"
default y if ARCH_SUNXI || ARCH_DAVINCI || ARCH_UNIPHIER ||ARCH_MX6 || \
default y if ARCH_SUNXI || ARCH_DAVINCI || ARCH_UNIPHIER || \
ARCH_MX6 || ARCH_MX7 || \
ARCH_ROCKCHIP || ARCH_MVEBU || ARCH_SOCFPGA || \
ARCH_AT91 || ARCH_ZYNQ || ARCH_KEYSTONE || OMAP34XX || \
OMAP44XX || OMAP54XX || AM33XX || AM43XX
@ -165,7 +166,7 @@ config SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR
depends on SYS_MMCSD_RAW_MODE_U_BOOT_USE_SECTOR
default 0x50 if ARCH_SUNXI
default 0x75 if ARCH_DAVINCI
default 0x8a if ARCH_MX6
default 0x8a if ARCH_MX6 || ARCH_MX7
default 0x100 if ARCH_UNIPHIER
default 0x140 if ARCH_MVEBU
default 0x200 if ARCH_SOCFPGA || ARCH_AT91

@ -17,7 +17,6 @@ CONFIG_SYS_EXTRA_OPTIONS="IMX_CONFIG=arch/arm/mach-imx/spl_sd.cfg"
CONFIG_SPI_BOOT=y
CONFIG_BOOTDELAY=3
CONFIG_SPL_BOARD_INIT=y
CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_USE_SECTOR=y
CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR=0x80
CONFIG_SPL_I2C_SUPPORT=y
CONFIG_SPL_SPI_LOAD=y

@ -4,12 +4,14 @@ CONFIG_SYS_TEXT_BASE=0x17800000
CONFIG_SPL_GPIO_SUPPORT=y
CONFIG_SPL_LIBCOMMON_SUPPORT=y
CONFIG_SPL_LIBGENERIC_SUPPORT=y
CONFIG_MX6_DDRCAL=y
CONFIG_TARGET_DISPLAY5=y
CONFIG_SPL_MMC_SUPPORT=y
CONFIG_SPL_SERIAL_SUPPORT=y
CONFIG_SPL=y
CONFIG_SPL_SPI_FLASH_SUPPORT=y
CONFIG_SPL_SPI_SUPPORT=y
CONFIG_SPL_WATCHDOG_SUPPORT=y
CONFIG_DEFAULT_DEVICE_TREE="imx6q-display5"
CONFIG_FIT=y
CONFIG_SPL_LOAD_FIT=y
@ -32,6 +34,7 @@ CONFIG_CMD_ASKENV=y
CONFIG_CRC32_VERIFY=y
CONFIG_CMD_EEPROM=y
CONFIG_CMD_GPIO=y
CONFIG_CMD_GPT=y
CONFIG_CMD_I2C=y
CONFIG_CMD_MMC=y
CONFIG_CMD_PART=y
@ -48,8 +51,7 @@ CONFIG_CMD_FAT=y
CONFIG_CMD_FS_GENERIC=y
CONFIG_CMD_MTDPARTS=y
CONFIG_MTDIDS_DEFAULT="nor0=02008000.spi.1"
CONFIG_MTDPARTS_DEFAULT="mtdparts=02008000.spi.1:128k(SPL),1m(u-boot),64k(env1),64k(env2),8m(lin-recovery),4m(swu-kernel),8m(swu-initramfs),-(reserved)"
CONFIG_EFI_PARTITION=y
CONFIG_MTDPARTS_DEFAULT="mtdparts=02008000.spi.1:128k(SPL),1m(u-boot),64k(env1),64k(env2),4m(swu-kernel),16m(swu-initramfs),1m(factory),-(reserved)"
# CONFIG_SPL_EFI_PARTITION is not set
CONFIG_OF_CONTROL=y
CONFIG_ENV_IS_IN_SPI_FLASH=y

@ -9,6 +9,7 @@ CONFIG_SPL_SERIAL_SUPPORT=y
CONFIG_SPL=y
CONFIG_SPL_SPI_FLASH_SUPPORT=y
CONFIG_SPL_SPI_SUPPORT=y
CONFIG_SPL_WATCHDOG_SUPPORT=y
CONFIG_FIT=y
CONFIG_OF_BOARD_SETUP=y
CONFIG_SYS_EXTRA_OPTIONS="IMX_CONFIG=arch/arm/mach-imx/spl_sd.cfg,MX6Q"
@ -53,7 +54,7 @@ CONFIG_CMD_FAT=y
CONFIG_CMD_FS_GENERIC=y
CONFIG_CMD_MTDPARTS=y
CONFIG_MTDIDS_DEFAULT="nor0=02008000.spi.1"
CONFIG_MTDPARTS_DEFAULT="mtdparts=02008000.spi.1:128k(SPL),1m(u-boot),64k(env1),64k(env2),8m(lin-recovery),4m(swu-kernel),8m(swu-initramfs),-(reserved)"
CONFIG_MTDPARTS_DEFAULT="mtdparts=02008000.spi.1:128k(SPL),1m(u-boot),64k(env1),64k(env2),4m(swu-kernel),16m(swu-initramfs),1m(factory),-(reserved)"
# CONFIG_SPL_EFI_PARTITION is not set
CONFIG_PARTITION_TYPE_GUID=y
CONFIG_ENV_IS_IN_SPI_FLASH=y

@ -10,7 +10,7 @@ CONFIG_SPL_SERIAL_SUPPORT=y
CONFIG_SPL=y
CONFIG_SPL_LIBDISK_SUPPORT=y
# CONFIG_CMD_BMODE is not set
CONFIG_DEFAULT_DEVICE_TREE="imx6ul-geam-kit"
CONFIG_DEFAULT_DEVICE_TREE="imx6ul-geam"
CONFIG_FIT=y
CONFIG_FIT_SIGNATURE=y
CONFIG_FIT_VERBOSE=y

@ -8,7 +8,7 @@ CONFIG_TARGET_MX6UL_ENGICAM=y
CONFIG_SPL_SERIAL_SUPPORT=y
CONFIG_SPL=y
# CONFIG_CMD_BMODE is not set
CONFIG_DEFAULT_DEVICE_TREE="imx6ul-geam-kit"
CONFIG_DEFAULT_DEVICE_TREE="imx6ul-geam"
CONFIG_FIT=y
CONFIG_FIT_SIGNATURE=y
CONFIG_FIT_VERBOSE=y

@ -6,10 +6,14 @@ CONFIG_TARGET_KP_IMX53=y
CONFIG_DEFAULT_DEVICE_TREE="imx53-kp"
CONFIG_FIT=y
CONFIG_SYS_EXTRA_OPTIONS="IMX_CONFIG=board/freescale/mx53loco/imximage.cfg"
CONFIG_SILENT_CONSOLE=y
# CONFIG_SILENT_CONSOLE_UPDATE_ON_SET is not set
CONFIG_SYS_CONSOLE_IS_IN_ENV=y
CONFIG_SYS_CONSOLE_OVERWRITE_ROUTINE=y
CONFIG_SUPPORT_RAW_INITRD=y
CONFIG_HUSH_PARSER=y
CONFIG_AUTOBOOT_KEYED=y
CONFIG_AUTOBOOT_STOP_STR="."
CONFIG_CMD_BOOTZ=y
CONFIG_CMD_I2C=y
CONFIG_CMD_MMC=y
@ -18,6 +22,7 @@ CONFIG_CMD_USB=y
CONFIG_CMD_DHCP=y
CONFIG_CMD_MII=y
CONFIG_CMD_PING=y
CONFIG_CMD_PMIC=y
CONFIG_CMD_EXT2=y
CONFIG_CMD_FAT=y
CONFIG_CMD_FS_GENERIC=y
@ -26,6 +31,7 @@ CONFIG_ENV_IS_IN_MMC=y
CONFIG_I2C_SET_DEFAULT_BUS_NUM=y
CONFIG_I2C_DEFAULT_BUS_NUMBER=0x1
CONFIG_PHYLIB=y
CONFIG_PHY_ADDR=1
CONFIG_PHY_SMSC=y
CONFIG_FEC_MXC=y
CONFIG_PINCTRL=y

@ -109,7 +109,7 @@ config MSM_GPIO
- MSM8916
config MXC_GPIO
bool "Freescale/NXP MXC UART driver"
bool "Freescale/NXP MXC GPIO driver"
help
Support GPIO controllers on various i.MX platforms

@ -143,6 +143,7 @@ config NAND_MXC
config NAND_MXS
bool "MXS NAND support"
depends on MX23 || MX28 || MX6 || MX7
select SYS_NAND_SELF_INIT
imply CMD_NAND
select APBH_DMA
select APBH_DMA_BURST if ARCH_MX6 || ARCH_MX7
@ -151,6 +152,21 @@ config NAND_MXS
This enables NAND driver for the NAND flash controller on the
MXS processors.
if NAND_MXS
config NAND_MXS_DT
bool "Support MXS NAND controller as a DT device"
depends on OF_CONTROL && MTD
help
Enable the driver for MXS NAND flash on platforms using
device tree.
config NAND_MXS_USE_MINIMUM_ECC
bool "Use minimum ECC strength supported by the controller"
default false
endif
config NAND_ZYNQ
bool "Support for Zynq Nand controller"
select SYS_NAND_SELF_INIT

@ -15,6 +15,7 @@ obj-$(CONFIG_SPL_NAND_SIMPLE) += nand_spl_simple.o
obj-$(CONFIG_SPL_NAND_LOAD) += nand_spl_load.o
obj-$(CONFIG_SPL_NAND_ECC) += nand_ecc.o
obj-$(CONFIG_SPL_NAND_BASE) += nand_base.o
obj-$(CONFIG_SPL_NAND_IDENT) += nand_ids.o nand_timings.o
obj-$(CONFIG_SPL_NAND_INIT) += nand.o
ifeq ($(CONFIG_SPL_ENV_SUPPORT),y)
obj-$(CONFIG_ENV_IS_IN_NAND) += nand_util.o
@ -55,6 +56,7 @@ obj-$(CONFIG_NAND_LPC32XX_SLC) += lpc32xx_nand_slc.o
obj-$(CONFIG_NAND_VF610_NFC) += vf610_nfc.o
obj-$(CONFIG_NAND_MXC) += mxc_nand.o
obj-$(CONFIG_NAND_MXS) += mxs_nand.o
obj-$(CONFIG_NAND_MXS_DT) += mxs_nand_dt.o
obj-$(CONFIG_NAND_PXA3XX) += pxa3xx_nand.o
obj-$(CONFIG_NAND_SPEAR) += spr_nand.o
obj-$(CONFIG_TEGRA_NAND) += tegra_nand.o

@ -13,8 +13,9 @@
*/
#include <common.h>
#include <linux/mtd/mtd.h>
#include <dm.h>
#include <linux/mtd/rawnand.h>
#include <linux/sizes.h>
#include <linux/types.h>
#include <malloc.h>
#include <linux/errno.h>
@ -24,11 +25,10 @@
#include <asm/mach-imx/regs-bch.h>
#include <asm/mach-imx/regs-gpmi.h>
#include <asm/arch/sys_proto.h>
#include <asm/mach-imx/dma.h>
#include "mxs_nand.h"
#define MXS_NAND_DMA_DESCRIPTOR_COUNT 4
#define MXS_NAND_CHUNK_DATA_CHUNK_SIZE 512
#if (defined(CONFIG_MX6) || defined(CONFIG_MX7))
#define MXS_NAND_CHUNK_DATA_CHUNK_SIZE_SHIFT 2
#else
@ -45,35 +45,7 @@
#define MXS_NAND_BCH_TIMEOUT 10000
struct mxs_nand_info {
int cur_chip;
uint32_t cmd_queue_len;
uint32_t data_buf_size;
uint8_t *cmd_buf;
uint8_t *data_buf;
uint8_t *oob_buf;
uint8_t marking_block_bad;
uint8_t raw_oob_mode;
/* Functions with altered behaviour */
int (*hooked_read_oob)(struct mtd_info *mtd,
loff_t from, struct mtd_oob_ops *ops);
int (*hooked_write_oob)(struct mtd_info *mtd,
loff_t to, struct mtd_oob_ops *ops);
int (*hooked_block_markbad)(struct mtd_info *mtd,
loff_t ofs);
/* DMA descriptors */
struct mxs_dma_desc **desc;
uint32_t desc_index;
};
struct nand_ecclayout fake_ecc_layout;
static int chunk_data_size = MXS_NAND_CHUNK_DATA_CHUNK_SIZE;
static int galois_field = 13;
/*
* Cache management functions
@ -134,61 +106,21 @@ static void mxs_nand_return_dma_descs(struct mxs_nand_info *info)
info->desc_index = 0;
}
static uint32_t mxs_nand_ecc_chunk_cnt(uint32_t page_data_size)
{
return page_data_size / chunk_data_size;
}
static uint32_t mxs_nand_ecc_size_in_bits(uint32_t ecc_strength)
{
return ecc_strength * galois_field;
}
static uint32_t mxs_nand_aux_status_offset(void)
{
return (MXS_NAND_METADATA_SIZE + 0x3) & ~0x3;
}
static inline uint32_t mxs_nand_get_ecc_strength(uint32_t page_data_size,
uint32_t page_oob_size)
{
int ecc_strength;
int max_ecc_strength_supported;
/* Refer to Chapter 17 for i.MX6DQ, Chapter 18 for i.MX6SX */
if (is_mx6sx() || is_mx7())
max_ecc_strength_supported = 62;
else
max_ecc_strength_supported = 40;
/*
* Determine the ECC layout with the formula:
* ECC bits per chunk = (total page spare data bits) /
* (bits per ECC level) / (chunks per page)
* where:
* total page spare data bits =
* (page oob size - meta data size) * (bits per byte)
*/
ecc_strength = ((page_oob_size - MXS_NAND_METADATA_SIZE) * 8)
/ (galois_field *
mxs_nand_ecc_chunk_cnt(page_data_size));
return min(round_down(ecc_strength, 2), max_ecc_strength_supported);
}
static inline uint32_t mxs_nand_get_mark_offset(uint32_t page_data_size,
uint32_t ecc_strength)
static inline int mxs_nand_calc_mark_offset(struct bch_geometry *geo,
uint32_t page_data_size)
{
uint32_t chunk_data_size_in_bits;
uint32_t chunk_ecc_size_in_bits;
uint32_t chunk_data_size_in_bits = geo->ecc_chunk_size * 8;
uint32_t chunk_ecc_size_in_bits = geo->ecc_strength * geo->gf_len;
uint32_t chunk_total_size_in_bits;
uint32_t block_mark_chunk_number;
uint32_t block_mark_chunk_bit_offset;
uint32_t block_mark_bit_offset;
chunk_data_size_in_bits = chunk_data_size * 8;
chunk_ecc_size_in_bits = mxs_nand_ecc_size_in_bits(ecc_strength);
chunk_total_size_in_bits =
chunk_data_size_in_bits + chunk_ecc_size_in_bits;
@ -213,7 +145,7 @@ static inline uint32_t mxs_nand_get_mark_offset(uint32_t page_data_size,
(block_mark_chunk_number * chunk_total_size_in_bits);
if (block_mark_chunk_bit_offset > chunk_data_size_in_bits)
return 1;
return -EINVAL;
/*
* Now that we know the chunk number in which the block mark appears,
@ -222,36 +154,100 @@ static inline uint32_t mxs_nand_get_mark_offset(uint32_t page_data_size,
block_mark_bit_offset -=
block_mark_chunk_number * chunk_ecc_size_in_bits;
return block_mark_bit_offset;
geo->block_mark_byte_offset = block_mark_bit_offset >> 3;
geo->block_mark_bit_offset = block_mark_bit_offset & 0x7;
return 0;
}
static uint32_t mxs_nand_mark_byte_offset(struct mtd_info *mtd)
static inline int mxs_nand_calc_ecc_layout_by_info(struct bch_geometry *geo,
struct mtd_info *mtd,
unsigned int ecc_strength,
unsigned int ecc_step)
{
uint32_t ecc_strength;
ecc_strength = mxs_nand_get_ecc_strength(mtd->writesize, mtd->oobsize);
return mxs_nand_get_mark_offset(mtd->writesize, ecc_strength) >> 3;
struct nand_chip *chip = mtd_to_nand(mtd);
struct mxs_nand_info *nand_info = nand_get_controller_data(chip);
switch (ecc_step) {
case SZ_512:
geo->gf_len = 13;
break;
case SZ_1K:
geo->gf_len = 14;
break;
default:
return -EINVAL;
}
geo->ecc_chunk_size = ecc_step;
geo->ecc_strength = round_up(ecc_strength, 2);
/* Keep the C >= O */
if (geo->ecc_chunk_size < mtd->oobsize)
return -EINVAL;
if (geo->ecc_strength > nand_info->max_ecc_strength_supported)
return -EINVAL;
geo->ecc_chunk_count = mtd->writesize / geo->ecc_chunk_size;
return 0;
}
static uint32_t mxs_nand_mark_bit_offset(struct mtd_info *mtd)
static inline int mxs_nand_calc_ecc_layout(struct bch_geometry *geo,
struct mtd_info *mtd)
{
uint32_t ecc_strength;
ecc_strength = mxs_nand_get_ecc_strength(mtd->writesize, mtd->oobsize);
return mxs_nand_get_mark_offset(mtd->writesize, ecc_strength) & 0x7;
struct nand_chip *chip = mtd_to_nand(mtd);
struct mxs_nand_info *nand_info = nand_get_controller_data(chip);
/* The default for the length of Galois Field. */
geo->gf_len = 13;
/* The default for chunk size. */
geo->ecc_chunk_size = 512;
if (geo->ecc_chunk_size < mtd->oobsize) {
geo->gf_len = 14;
geo->ecc_chunk_size *= 2;
}
if (mtd->oobsize > geo->ecc_chunk_size) {
printf("Not support the NAND chips whose oob size is larger then %d bytes!\n",
geo->ecc_chunk_size);
return -EINVAL;
}
geo->ecc_chunk_count = mtd->writesize / geo->ecc_chunk_size;
/*
* Determine the ECC layout with the formula:
* ECC bits per chunk = (total page spare data bits) /
* (bits per ECC level) / (chunks per page)
* where:
* total page spare data bits =
* (page oob size - meta data size) * (bits per byte)
*/
geo->ecc_strength = ((mtd->oobsize - MXS_NAND_METADATA_SIZE) * 8)
/ (geo->gf_len * geo->ecc_chunk_count);
geo->ecc_strength = min(round_down(geo->ecc_strength, 2),
nand_info->max_ecc_strength_supported);
return 0;
}
/*
* Wait for BCH complete IRQ and clear the IRQ
*/
static int mxs_nand_wait_for_bch_complete(void)
static int mxs_nand_wait_for_bch_complete(struct mxs_nand_info *nand_info)
{
struct mxs_bch_regs *bch_regs = (struct mxs_bch_regs *)MXS_BCH_BASE;
int timeout = MXS_NAND_BCH_TIMEOUT;
int ret;
ret = mxs_wait_mask_set(&bch_regs->hw_bch_ctrl_reg,
ret = mxs_wait_mask_set(&nand_info->bch_regs->hw_bch_ctrl_reg,
BCH_CTRL_COMPLETE_IRQ, timeout);
writel(BCH_CTRL_COMPLETE_IRQ, &bch_regs->hw_bch_ctrl_clr);
writel(BCH_CTRL_COMPLETE_IRQ, &nand_info->bch_regs->hw_bch_ctrl_clr);
return ret;
}
@ -349,11 +345,9 @@ static int mxs_nand_device_ready(struct mtd_info *mtd)
{
struct nand_chip *chip = mtd_to_nand(mtd);
struct mxs_nand_info *nand_info = nand_get_controller_data(chip);
struct mxs_gpmi_regs *gpmi_regs =
(struct mxs_gpmi_regs *)MXS_GPMI_BASE;
uint32_t tmp;
tmp = readl(&gpmi_regs->hw_gpmi_stat);
tmp = readl(&nand_info->gpmi_regs->hw_gpmi_stat);
tmp >>= (GPMI_STAT_READY_BUSY_OFFSET + nand_info->cur_chip);
return tmp & 1;
@ -377,18 +371,15 @@ static void mxs_nand_select_chip(struct mtd_info *mtd, int chip)
* swapping the block mark, or swapping it *back* -- but it doesn't matter
* because the the operation is the same.
*/
static void mxs_nand_swap_block_mark(struct mtd_info *mtd,
uint8_t *data_buf, uint8_t *oob_buf)
static void mxs_nand_swap_block_mark(struct bch_geometry *geo,
uint8_t *data_buf, uint8_t *oob_buf)
{
uint32_t bit_offset;
uint32_t buf_offset;
uint32_t bit_offset = geo->block_mark_bit_offset;
uint32_t buf_offset = geo->block_mark_byte_offset;
uint32_t src;
uint32_t dst;
bit_offset = mxs_nand_mark_bit_offset(mtd);
buf_offset = mxs_nand_mark_byte_offset(mtd);
/*
* Get the byte from the data area that overlays the block mark. Since
* the ECC engine applies its own view to the bits in the page, the
@ -564,6 +555,7 @@ static int mxs_nand_ecc_read_page(struct mtd_info *mtd, struct nand_chip *nand,
int page)
{
struct mxs_nand_info *nand_info = nand_get_controller_data(nand);
struct bch_geometry *geo = &nand_info->bch_geometry;
struct mxs_dma_desc *d;
uint32_t channel = MXS_DMA_CHANNEL_AHB_APBH_GPMI0 + nand_info->cur_chip;
uint32_t corrected = 0, failed = 0;
@ -652,7 +644,7 @@ static int mxs_nand_ecc_read_page(struct mtd_info *mtd, struct nand_chip *nand,
goto rtn;
}
ret = mxs_nand_wait_for_bch_complete();
ret = mxs_nand_wait_for_bch_complete(nand_info);
if (ret) {
printf("MXS NAND: BCH read timeout\n");
goto rtn;
@ -662,11 +654,11 @@ static int mxs_nand_ecc_read_page(struct mtd_info *mtd, struct nand_chip *nand,
mxs_nand_inval_data_buf(nand_info);
/* Read DMA completed, now do the mark swapping. */
mxs_nand_swap_block_mark(mtd, nand_info->data_buf, nand_info->oob_buf);
mxs_nand_swap_block_mark(geo, nand_info->data_buf, nand_info->oob_buf);
/* Loop over status bytes, accumulating ECC status. */
status = nand_info->oob_buf + mxs_nand_aux_status_offset();
for (i = 0; i < mxs_nand_ecc_chunk_cnt(mtd->writesize); i++) {
for (i = 0; i < geo->ecc_chunk_count; i++) {
if (status[i] == 0x00)
continue;
@ -714,6 +706,7 @@ static int mxs_nand_ecc_write_page(struct mtd_info *mtd,
int oob_required, int page)
{
struct mxs_nand_info *nand_info = nand_get_controller_data(nand);
struct bch_geometry *geo = &nand_info->bch_geometry;
struct mxs_dma_desc *d;
uint32_t channel = MXS_DMA_CHANNEL_AHB_APBH_GPMI0 + nand_info->cur_chip;
int ret;
@ -722,7 +715,7 @@ static int mxs_nand_ecc_write_page(struct mtd_info *mtd,
memcpy(nand_info->oob_buf, nand->oob_poi, mtd->oobsize);
/* Handle block mark swapping. */
mxs_nand_swap_block_mark(mtd, nand_info->data_buf, nand_info->oob_buf);
mxs_nand_swap_block_mark(geo, nand_info->data_buf, nand_info->oob_buf);
/* Compile the DMA descriptor - write data. */
d = mxs_nand_get_dma_desc(nand_info);
@ -759,7 +752,7 @@ static int mxs_nand_ecc_write_page(struct mtd_info *mtd,
goto rtn;
}
ret = mxs_nand_wait_for_bch_complete();
ret = mxs_nand_wait_for_bch_complete(nand_info);
if (ret) {
printf("MXS NAND: BCH write timeout\n");
goto rtn;
@ -970,57 +963,69 @@ static int mxs_nand_block_bad(struct mtd_info *mtd, loff_t ofs)
return 0;
}
static int mxs_nand_set_geometry(struct mtd_info *mtd, struct bch_geometry *geo)
{
struct nand_chip *chip = mtd_to_nand(mtd);
struct nand_chip *nand = mtd_to_nand(mtd);
struct mxs_nand_info *nand_info = nand_get_controller_data(nand);
if (chip->ecc.strength > 0 && chip->ecc.size > 0)
return mxs_nand_calc_ecc_layout_by_info(geo, mtd,
chip->ecc.strength, chip->ecc.size);
if (nand_info->use_minimum_ecc ||
mxs_nand_calc_ecc_layout(geo, mtd)) {
if (!(chip->ecc_strength_ds > 0 && chip->ecc_step_ds > 0))
return -EINVAL;
return mxs_nand_calc_ecc_layout_by_info(geo, mtd,
chip->ecc_strength_ds, chip->ecc_step_ds);
}
return 0;
}
/*
* Nominally, the purpose of this function is to look for or create the bad
* block table. In fact, since the we call this function at the very end of
* the initialization process started by nand_scan(), and we doesn't have a
* more formal mechanism, we "hook" this function to continue init process.
*
* At this point, the physical NAND Flash chips have been identified and
* counted, so we know the physical geometry. This enables us to make some
* important configuration decisions.
*
* The return value of this function propagates directly back to this driver's
* call to nand_scan(). Anything other than zero will cause this driver to
* board_nand_init(). Anything other than zero will cause this driver to
* tear everything down and declare failure.
*/
static int mxs_nand_scan_bbt(struct mtd_info *mtd)
int mxs_nand_setup_ecc(struct mtd_info *mtd)
{
struct nand_chip *nand = mtd_to_nand(mtd);
struct mxs_nand_info *nand_info = nand_get_controller_data(nand);
struct mxs_bch_regs *bch_regs = (struct mxs_bch_regs *)MXS_BCH_BASE;
struct bch_geometry *geo = &nand_info->bch_geometry;
struct mxs_bch_regs *bch_regs = nand_info->bch_regs;
uint32_t tmp;
int ret;
if (mtd->oobsize > MXS_NAND_CHUNK_DATA_CHUNK_SIZE) {
galois_field = 14;
chunk_data_size = MXS_NAND_CHUNK_DATA_CHUNK_SIZE * 2;
}
ret = mxs_nand_set_geometry(mtd, geo);
if (ret)
return ret;
if (mtd->oobsize > chunk_data_size) {
printf("Not support the NAND chips whose oob size is larger then %d bytes!\n", chunk_data_size);
return -EINVAL;
}
mxs_nand_calc_mark_offset(geo, mtd->writesize);
/* Configure BCH and set NFC geometry */
mxs_reset_block(&bch_regs->hw_bch_ctrl_reg);
/* Configure layout 0 */
tmp = (mxs_nand_ecc_chunk_cnt(mtd->writesize) - 1)
<< BCH_FLASHLAYOUT0_NBLOCKS_OFFSET;
tmp = (geo->ecc_chunk_count - 1) << BCH_FLASHLAYOUT0_NBLOCKS_OFFSET;
tmp |= MXS_NAND_METADATA_SIZE << BCH_FLASHLAYOUT0_META_SIZE_OFFSET;
tmp |= (mxs_nand_get_ecc_strength(mtd->writesize, mtd->oobsize) >> 1)
<< BCH_FLASHLAYOUT0_ECC0_OFFSET;
tmp |= chunk_data_size >> MXS_NAND_CHUNK_DATA_CHUNK_SIZE_SHIFT;
tmp |= (14 == galois_field ? 1 : 0) <<
tmp |= (geo->ecc_strength >> 1) << BCH_FLASHLAYOUT0_ECC0_OFFSET;
tmp |= geo->ecc_chunk_size >> MXS_NAND_CHUNK_DATA_CHUNK_SIZE_SHIFT;
tmp |= (geo->gf_len == 14 ? 1 : 0) <<
BCH_FLASHLAYOUT0_GF13_0_GF14_1_OFFSET;
writel(tmp, &bch_regs->hw_bch_flash0layout0);
tmp = (mtd->writesize + mtd->oobsize)
<< BCH_FLASHLAYOUT1_PAGE_SIZE_OFFSET;
tmp |= (mxs_nand_get_ecc_strength(mtd->writesize, mtd->oobsize) >> 1)
<< BCH_FLASHLAYOUT1_ECCN_OFFSET;
tmp |= chunk_data_size >> MXS_NAND_CHUNK_DATA_CHUNK_SIZE_SHIFT;
tmp |= (14 == galois_field ? 1 : 0) <<
tmp |= (geo->ecc_strength >> 1) << BCH_FLASHLAYOUT1_ECCN_OFFSET;
tmp |= geo->ecc_chunk_size >> MXS_NAND_CHUNK_DATA_CHUNK_SIZE_SHIFT;
tmp |= (geo->gf_len == 14 ? 1 : 0) <<
BCH_FLASHLAYOUT1_GF13_0_GF14_1_OFFSET;
writel(tmp, &bch_regs->hw_bch_flash0layout1);
@ -1046,8 +1051,7 @@ static int mxs_nand_scan_bbt(struct mtd_info *mtd)
mtd->_block_markbad = mxs_nand_hook_block_markbad;
}
/* We use the reference implementation for bad block management. */
return nand_default_bbt(mtd);
return 0;
}
/*
@ -1088,12 +1092,8 @@ int mxs_nand_alloc_buffers(struct mxs_nand_info *nand_info)
/*
* Initializes the NFC hardware.
*/
int mxs_nand_init(struct mxs_nand_info *info)
int mxs_nand_init_dma(struct mxs_nand_info *info)
{
struct mxs_gpmi_regs *gpmi_regs =
(struct mxs_gpmi_regs *)MXS_GPMI_BASE;
struct mxs_bch_regs *bch_regs =
(struct mxs_bch_regs *)MXS_BCH_BASE;
int i = 0, j, ret = 0;
info->desc = malloc(sizeof(struct mxs_dma_desc *) *
@ -1122,14 +1122,14 @@ int mxs_nand_init(struct mxs_nand_info *info)
}
/* Reset the GPMI block. */
mxs_reset_block(&gpmi_regs->hw_gpmi_ctrl0_reg);
mxs_reset_block(&bch_regs->hw_bch_ctrl_reg);
mxs_reset_block(&info->gpmi_regs->hw_gpmi_ctrl0_reg);
mxs_reset_block(&info->bch_regs->hw_bch_ctrl_reg);
/*
* Choose NAND mode, set IRQ polarity, disable write protection and
* select BCH ECC.
*/
clrsetbits_le32(&gpmi_regs->hw_gpmi_ctrl1,
clrsetbits_le32(&info->gpmi_regs->hw_gpmi_ctrl1,
GPMI_CTRL1_GPMI_MODE,
GPMI_CTRL1_ATA_IRQRDY_POLARITY | GPMI_CTRL1_DEV_RESET |
GPMI_CTRL1_BCH_MODE);
@ -1149,16 +1149,7 @@ err1:
return ret;
}
/*!
* This function is called during the driver binding process.
*
* @param pdev the device structure used to store device specific
* information that is used by the suspend, resume and
* remove functions
*
* @return The function always returns 0.
*/
int board_nand_init(struct nand_chip *nand)
int mxs_nand_init_spl(struct nand_chip *nand)
{
struct mxs_nand_info *nand_info;
int err;
@ -1170,31 +1161,83 @@ int board_nand_init(struct nand_chip *nand)
}
memset(nand_info, 0, sizeof(struct mxs_nand_info));
nand_info->gpmi_regs = (struct mxs_gpmi_regs *)MXS_GPMI_BASE;
nand_info->bch_regs = (struct mxs_bch_regs *)MXS_BCH_BASE;
err = mxs_nand_alloc_buffers(nand_info);
if (err)
goto err1;
return err;
err = mxs_nand_init_dma(nand_info);
if (err)
return err;
nand_set_controller_data(nand, nand_info);
nand->options |= NAND_NO_SUBPAGE_WRITE;
nand->cmd_ctrl = mxs_nand_cmd_ctrl;
nand->dev_ready = mxs_nand_device_ready;
nand->select_chip = mxs_nand_select_chip;
nand->read_byte = mxs_nand_read_byte;
nand->read_buf = mxs_nand_read_buf;
nand->ecc.read_page = mxs_nand_ecc_read_page;
nand->ecc.mode = NAND_ECC_HW;
nand->ecc.bytes = 9;
nand->ecc.size = 512;
nand->ecc.strength = 8;
return 0;
}
int mxs_nand_init_ctrl(struct mxs_nand_info *nand_info)
{
struct mtd_info *mtd;
struct nand_chip *nand;
int err;
nand = &nand_info->chip;
mtd = nand_to_mtd(nand);
err = mxs_nand_alloc_buffers(nand_info);
if (err)
return err;
err = mxs_nand_init(nand_info);
err = mxs_nand_init_dma(nand_info);
if (err)
goto err2;
goto err_free_buffers;
memset(&fake_ecc_layout, 0, sizeof(fake_ecc_layout));
#ifdef CONFIG_SYS_NAND_USE_FLASH_BBT
nand->bbt_options |= NAND_BBT_USE_FLASH | NAND_BBT_NO_OOB;
#endif
nand_set_controller_data(nand, nand_info);
nand->options |= NAND_NO_SUBPAGE_WRITE;
if (nand_info->dev)
nand->flash_node = dev_of_offset(nand_info->dev);
nand->cmd_ctrl = mxs_nand_cmd_ctrl;
nand->dev_ready = mxs_nand_device_ready;
nand->select_chip = mxs_nand_select_chip;
nand->block_bad = mxs_nand_block_bad;
nand->scan_bbt = mxs_nand_scan_bbt;
nand->read_byte = mxs_nand_read_byte;
nand->read_buf = mxs_nand_read_buf;
nand->write_buf = mxs_nand_write_buf;
/* first scan to find the device and get the page size */
if (nand_scan_ident(mtd, CONFIG_SYS_MAX_NAND_DEVICE, NULL))
goto err_free_buffers;
if (mxs_nand_setup_ecc(mtd))
goto err_free_buffers;
nand->ecc.read_page = mxs_nand_ecc_read_page;
nand->ecc.write_page = mxs_nand_ecc_write_page;
nand->ecc.read_oob = mxs_nand_ecc_read_oob;
@ -1202,16 +1245,58 @@ int board_nand_init(struct nand_chip *nand)
nand->ecc.layout = &fake_ecc_layout;
nand->ecc.mode = NAND_ECC_HW;
nand->ecc.bytes = 9;
nand->ecc.size = 512;
nand->ecc.strength = 8;
nand->ecc.size = nand_info->bch_geometry.ecc_chunk_size;
nand->ecc.strength = nand_info->bch_geometry.ecc_strength;
/* second phase scan */
err = nand_scan_tail(mtd);
if (err)
goto err_free_buffers;
err = nand_register(0, mtd);
if (err)
goto err_free_buffers;
return 0;
err2:
err_free_buffers:
free(nand_info->data_buf);
free(nand_info->cmd_buf);
err1:
free(nand_info);
return err;
}
#ifndef CONFIG_NAND_MXS_DT
void board_nand_init(void)
{
struct mxs_nand_info *nand_info;
nand_info = malloc(sizeof(struct mxs_nand_info));
if (!nand_info) {
printf("MXS NAND: Failed to allocate private data\n");
return;
}
memset(nand_info, 0, sizeof(struct mxs_nand_info));
nand_info->gpmi_regs = (struct mxs_gpmi_regs *)MXS_GPMI_BASE;
nand_info->bch_regs = (struct mxs_bch_regs *)MXS_BCH_BASE;
/* Refer to Chapter 17 for i.MX6DQ, Chapter 18 for i.MX6SX */
if (is_mx6sx() || is_mx7())
nand_info->max_ecc_strength_supported = 62;
else
nand_info->max_ecc_strength_supported = 40;
#ifdef CONFIG_NAND_MXS_USE_MINIMUM_ECC
nand_info->use_minimum_ecc = true;
#endif
if (mxs_nand_init_ctrl(nand_info) < 0)
goto err;
return;
err:
free(nand_info);
}
#endif

@ -0,0 +1,73 @@
/* SPDX-License-Identifier: GPL-2.0+ */
/*
* NXP GPMI NAND flash driver
*
* Copyright (C) 2018 Toradex
* Authors:
* Stefan Agner <stefan.agner@toradex.com>
*/
#include <linux/mtd/mtd.h>
#include <asm/cache.h>
#include <nand.h>
#include <asm/mach-imx/dma.h>
/**
* @gf_len: The length of Galois Field. (e.g., 13 or 14)
* @ecc_strength: A number that describes the strength of the ECC
* algorithm.
* @ecc_chunk_size: The size, in bytes, of a single ECC chunk. Note
* the first chunk in the page includes both data and
* metadata, so it's a bit larger than this value.
* @ecc_chunk_count: The number of ECC chunks in the page,
* @block_mark_byte_offset: The byte offset in the ECC-based page view at
* which the underlying physical block mark appears.
* @block_mark_bit_offset: The bit offset into the ECC-based page view at
* which the underlying physical block mark appears.
*/
struct bch_geometry {
unsigned int gf_len;
unsigned int ecc_strength;
unsigned int ecc_chunk_size;
unsigned int ecc_chunk_count;
unsigned int block_mark_byte_offset;
unsigned int block_mark_bit_offset;
};
struct mxs_nand_info {
struct nand_chip chip;
struct udevice *dev;
unsigned int max_ecc_strength_supported;
bool use_minimum_ecc;
int cur_chip;
uint32_t cmd_queue_len;
uint32_t data_buf_size;
struct bch_geometry bch_geometry;
uint8_t *cmd_buf;
uint8_t *data_buf;
uint8_t *oob_buf;
uint8_t marking_block_bad;
uint8_t raw_oob_mode;
struct mxs_gpmi_regs *gpmi_regs;
struct mxs_bch_regs *bch_regs;
/* Functions with altered behaviour */
int (*hooked_read_oob)(struct mtd_info *mtd,
loff_t from, struct mtd_oob_ops *ops);
int (*hooked_write_oob)(struct mtd_info *mtd,
loff_t to, struct mtd_oob_ops *ops);
int (*hooked_block_markbad)(struct mtd_info *mtd,
loff_t ofs);
/* DMA descriptors */
struct mxs_dma_desc **desc;
uint32_t desc_index;
};
int mxs_nand_init_ctrl(struct mxs_nand_info *nand_info);
int mxs_nand_init_spl(struct nand_chip *nand);
int mxs_nand_setup_ecc(struct mtd_info *mtd);

@ -0,0 +1,86 @@
/*
* NXP GPMI NAND flash driver (DT initialization)
*
* Copyright (C) 2018 Toradex
* Authors:
* Stefan Agner <stefan.agner@toradex.com>
*
* Based on denali_dt.c
*
* SPDX-License-Identifier: GPL-2.0+
*/
#include <dm.h>
#include <linux/io.h>
#include <linux/ioport.h>
#include <linux/printk.h>
#include "mxs_nand.h"
struct mxs_nand_dt_data {
unsigned int max_ecc_strength_supported;
};
static const struct mxs_nand_dt_data mxs_nand_imx7d_data = {
.max_ecc_strength_supported = 62,
};
static const struct udevice_id mxs_nand_dt_ids[] = {
{
.compatible = "fsl,imx7d-gpmi-nand",
.data = (unsigned long)&mxs_nand_imx7d_data,
},
{ /* sentinel */ }
};
static int mxs_nand_dt_probe(struct udevice *dev)
{
struct mxs_nand_info *info = dev_get_priv(dev);
const struct mxs_nand_dt_data *data;
struct resource res;
int ret;
data = (void *)dev_get_driver_data(dev);
if (data)
info->max_ecc_strength_supported = data->max_ecc_strength_supported;
info->dev = dev;
ret = dev_read_resource_byname(dev, "gpmi-nand", &res);
if (ret)
return ret;
info->gpmi_regs = devm_ioremap(dev, res.start, resource_size(&res));
ret = dev_read_resource_byname(dev, "bch", &res);
if (ret)
return ret;
info->bch_regs = devm_ioremap(dev, res.start, resource_size(&res));
info->use_minimum_ecc = dev_read_bool(dev, "fsl,use-minimum-ecc");
return mxs_nand_init_ctrl(info);
}
U_BOOT_DRIVER(mxs_nand_dt) = {
.name = "mxs-nand-dt",
.id = UCLASS_MTD,
.of_match = mxs_nand_dt_ids,
.probe = mxs_nand_dt_probe,
.priv_auto_alloc_size = sizeof(struct mxs_nand_info),
};
void board_nand_init(void)
{
struct udevice *dev;
int ret;
ret = uclass_get_device_by_driver(UCLASS_MTD,
DM_GET_DRIVER(mxs_nand_dt),
&dev);
if (ret && ret != -ENODEV)
pr_err("Failed to initialize MXS NAND controller. (error %d)\n",
ret);
}

@ -6,6 +6,7 @@
#include <common.h>
#include <nand.h>
#include <malloc.h>
#include "mxs_nand.h"
static struct mtd_info *mtd;
static struct nand_chip nand_chip;
@ -48,7 +49,29 @@ static void mxs_nand_command(struct mtd_info *mtd, unsigned int command,
}
}
static int mxs_flash_ident(struct mtd_info *mtd)
#if defined (CONFIG_SPL_NAND_IDENT)
/* Trying to detect the NAND flash using ONFi, JEDEC, and (extended) IDs */
static int mxs_flash_full_ident(struct mtd_info *mtd)
{
int nand_maf_id, nand_dev_id;
struct nand_chip *chip = mtd_to_nand(mtd);
struct nand_flash_dev *type;
type = nand_get_flash_type(mtd, chip, &nand_maf_id, &nand_dev_id, NULL);
if (IS_ERR(type)) {
chip->select_chip(mtd, -1);
return PTR_ERR(type);
}
return 0;
}
#else
/* Trying to detect the NAND flash using ONFi only */
static int mxs_flash_onfi_ident(struct mtd_info *mtd)
{
register struct nand_chip *chip = mtd_to_nand(mtd);
int i;
@ -108,6 +131,19 @@ static int mxs_flash_ident(struct mtd_info *mtd)
return 0;
}
#endif /* CONFIG_SPL_NAND_IDENT */
static int mxs_flash_ident(struct mtd_info *mtd)
{
int ret;
#if defined (CONFIG_SPL_NAND_IDENT)
ret = mxs_flash_full_ident(mtd);
#else
ret = mxs_flash_onfi_ident(mtd);
#endif
return ret;
}
static int mxs_read_page_ecc(struct mtd_info *mtd, void *buf, unsigned int page)
{
register struct nand_chip *chip = mtd_to_nand(mtd);
@ -145,7 +181,7 @@ static int mxs_nand_init(void)
return 0;
/* init mxs nand driver */
board_nand_init(&nand_chip);
mxs_nand_init_spl(&nand_chip);
mtd = nand_to_mtd(&nand_chip);
/* set mtd functions */
nand_chip.cmdfunc = mxs_nand_command;

@ -3755,7 +3755,7 @@ static bool find_full_id_nand(struct mtd_info *mtd, struct nand_chip *chip,
/*
* Get the flash and manufacturer id and lookup if the type is supported.
*/
static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,
struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,
struct nand_chip *chip,
int *maf_id, int *dev_id,
struct nand_flash_dev *type)
@ -3927,6 +3927,7 @@ ident_done:
mtd->erasesize >> 10, mtd->writesize, mtd->oobsize);
return type;
}
EXPORT_SYMBOL(nand_get_flash_type);
#if CONFIG_IS_ENABLED(OF_CONTROL)
DECLARE_GLOBAL_DATA_PTR;

@ -12,6 +12,7 @@
#include <power/pmic.h>
#include <power/regulator.h>
#include <power/pfuze100_pmic.h>
#include <power/pfuze3000_pmic.h>
static const struct pmic_child_info pmic_children_info[] = {
/* sw[x], swbst */
@ -23,7 +24,7 @@ static const struct pmic_child_info pmic_children_info[] = {
static int pfuze100_reg_count(struct udevice *dev)
{
return PFUZE100_NUM_OF_REGS;
return dev->driver_data == PFUZE3000 ? PFUZE3000_NUM_OF_REGS : PFUZE100_NUM_OF_REGS;
}
static int pfuze100_write(struct udevice *dev, uint reg, const uint8_t *buff,

@ -22,7 +22,7 @@ int power_pfuze3000_init(unsigned char bus)
p->name = name;
p->interface = PMIC_I2C;
p->number_of_regs = PMIC_NUM_OF_REGS;
p->number_of_regs = PFUZE3000_NUM_OF_REGS;
p->hw.i2c.addr = CONFIG_POWER_PFUZE3000_I2C_ADDR;
p->hw.i2c.tx_num = 1;
p->bus = bus;

@ -30,9 +30,9 @@
* 0x020000 - 0x120000 : SPI.u-boot (1MiB)
* 0x120000 - 0x130000 : SPI.u-boot-env1 (64KiB)
* 0x130000 - 0x140000 : SPI.u-boot-env2 (64KiB)
* 0x140000 - 0x940000 : SPI.fitImage-recovery (8MiB)
* 0x940000 - 0xD40000 : SPI.swupdate-kernel-FIT (4MiB)
* 0xD40000 - 0x1540000 : SPI.swupdate-initramfs (8MiB)
* 0x140000 - 0x540000 : SPI.swupdate-kernel-FIT (4MiB)
* 0x540000 - 0x1540000 : SPI.swupdate-initramfs (16MiB)
* 0x1540000 - 0x1640000 : SPI.factory (1MiB)
*/
#ifndef CONFIG_SPL_BUILD
@ -100,7 +100,13 @@
#define CONFIG_BAUDRATE 115200
#ifndef CONFIG_BOOTCOMMAND
#define CONFIG_BOOTCOMMAND "run boot_mmc"
#define CONFIG_BOOTCOMMAND "if run check_em_pad; then " \
"run recovery;" \
"else if test ${BOOT_FROM} = FACTORY; then " \
"run factory_nfs;" \
"else " \
"run boot_mmc;" \
"fi;fi"
#endif
#define PARTS_DEFAULT \
@ -110,7 +116,7 @@
"name=kernel_raw1,start=128K,size=8M,uuid=${uuid_gpt_kernel_raw1};" \
"name=rootfs1,size=1528M,uuid=${uuid_gpt_rootfs1};" \
"name=kernel_raw2,size=8M,uuid=${uuid_gpt_kernel_raw2};" \
"name=rootfs2,size=1528M,uuid=${uuid_gpt_rootfs2};" \
"name=rootfs2,size=512M,uuid=${uuid_gpt_rootfs2};" \
"name=data,size=-,uuid=${uuid_gpt_data}\0"
#define FACTORY_PROCEDURE \
@ -123,7 +129,6 @@
"run tftp_sf_SPL;" \
"run tftp_sf_uboot;" \
TFTP_UPDATE_KERNEL \
"run tftp_sf_fitImg_recovery;" \
"run tftp_sf_fitImg_SWU;" \
"run tftp_sf_initramfs_SWU;" \
TFTP_UPDATE_ROOTFS \
@ -139,6 +144,16 @@
"echo '#######################';" \
"echo '# RECOVERY SWUupdate #';" \
"echo '#######################';" \
"echo '#######################';" \
"echo '# GPT verify #';" \
"if gpt verify mmc ${mmcdev} ${partitions}; then " \
"echo '# OK ! #';" \
"else " \
"echo '# FAILED ! #';" \
"echo '# GPT RESTORATION #';" \
"gpt write mmc ${mmcdev} ${partitions};" \
"fi;" \
"echo '#######################';" \
"setenv loadaddr_swu_initramfs 0x14000000;" \
"setenv bootargs console=${console} " \
"ip=${ipaddr}:${serverip}:${gatewayip}:${netmask}" \
@ -146,15 +161,7 @@
"sf probe;" \
"sf read ${loadaddr} swu-kernel;" \
"sf read ${loadaddr_swu_initramfs} swu-initramfs;" \
"bootm ${loadaddr} ${loadaddr_swu_initramfs};"
#define KERNEL_RECOVERY_PROCEDURE \
"echo '#######################';" \
"echo '# RECOVERY KERNEL IMG #';" \
"echo '#######################';" \
"sf probe;" \
"sf read ${loadaddr} lin-recovery;" \
"bootm;"
"bootm ${loadaddr} ${loadaddr_swu_initramfs};reset;"
#define SETUP_BOOTARGS \
"run set_rootfs_part;" \
@ -197,13 +204,11 @@
"mmc write ${loadaddr} ${lba_start} ${fw_sz}; " \
"; fi\0" \
/* To save some considerable time, we only once download the rootfs image */
/* and store it on 'active' and 'backup' rootfs partitions */
#define TFTP_UPDATE_ROOTFS \
"setenv rootfs_part ${rootfs_part_active};" \
"run tftp_mmc_rootfs;" \
"part start mmc ${mmcdev} ${rootfs_part_backup} lba_start;" \
"mmc write ${loadaddr} ${lba_start} ${fw_sz};" \
"run tftp_mmc_rootfs_bkp;" \
#define TFTP_UPDATE_RECOVERY_SWU_KERNEL \
"tftp_sf_fitImg_SWU=" \
@ -214,7 +219,7 @@
"; fi\0" \
#define TFTP_UPDATE_RECOVERY_SWU_INITRAMFS \
"swu_initramfs_file=swupdate-image-display5.ext3.gz.u-boot\0" \
"swu_initramfs_file=swupdate-image-display5.ext4.gz.u-boot\0" \
"tftp_sf_initramfs_SWU=" \
"if tftp ${loadaddr} ${swu_initramfs_file}; then " \
"sf probe;" \
@ -222,15 +227,6 @@
"sf write ${loadaddr} swu-initramfs ${filesize};" \
"; fi\0" \
#define TFTP_UPDATE_RECOVERY_KERNEL_INITRAMFS \
"kernel_recovery_file=fitImage-initramfs\0" \
"tftp_sf_fitImg_recovery=" \
"if tftp ${loadaddr} ${kernel_recovery_file}; then " \
"sf probe;" \
"sf erase lin-recovery +${filesize};" \
"sf write ${loadaddr} lin-recovery ${filesize};" \
"; fi\0" \
#define TFTP_UPDATE_BOOTLOADER \
"ubootfile=u-boot.img\0" \
"ubootfileSPL=SPL\0" \
@ -248,8 +244,20 @@
"sf write ${loadaddr} 0x400 ${filesize};" \
"fi\0" \
#define TFTP_UPDATE_SPINOR \
"spinorfile=core-image-lwn-display5.spinor\0" \
"spinorsize=0x2000000\0" \
"tftp_sf_img=" \
"if tftp ${loadaddr} ${spinorfile}; then " \
"sf probe;" \
"sf erase 0x0 ${spinorsize};" \
"sf write ${loadaddr} 0x0 ${filesize};" \
"fi\0" \
#define CONFIG_EXTRA_ENV_SETTINGS \
PARTS_DEFAULT \
"gpio_recovery=93\0" \
"check_em_pad=gpio input ${gpio_recovery};test $? -eq 0;\0" \
"display=tianma-tm070-800x480\0" \
"board=display5\0" \
"mmcdev=0\0" \
@ -265,7 +273,7 @@
"hostname=display5\0" \
"loadaddr=0x12000000\0" \
"fdtaddr=0x12800000\0" \
"console=ttymxc4,115200 quiet\0" \
"console=ttymxc4,115200 quiet cma=256M\0" \
"fdtfile=imx6q-display5.dtb\0" \
"fdt_high=0xffffffff\0" \
"initrd_high=0xffffffff\0" \
@ -273,21 +281,22 @@
"up=run tftp_sf_SPL; run tftp_sf_uboot\0" \
"download_kernel=" \
"tftpboot ${loadaddr} ${kernel_file};\0" \
"boot_kernel_recovery=" KERNEL_RECOVERY_PROCEDURE "\0" \
"factory_nfs=" \
"setenv ipaddr 192.168.1.102;" \
"setenv gatewayip 192.168.1.1;" \
"setenv netmask 255.255.255.0;" \
"setenv serverip 192.168.1.2;" \
"echo BOOT: FACTORY (LEG);" \
"run boot_nfs\0" \
"boot_swu_recovery=" SWUPDATE_RECOVERY_PROCEDURE "\0" \
"recovery=" \
"if test ${BOOT_FROM_RECOVERY} = SWU; then " \
"echo BOOT: RECOVERY: SWU;" \
"run boot_swu_recovery;" \
"else " \
"echo BOOT: RECOVERY: Linux;" \
"run boot_kernel_recovery;" \
"fi\0" \
"run boot_swu_recovery\0" \
"boot_tftp=" \
"if run download_kernel; then " \
"setenv bootargs console=${console} " \
"root=/dev/mmcblk0p2 rootwait;" \
"bootm ${loadaddr} - ${fdtaddr};" \
"bootm ${loadaddr} - ${fdtaddr};reset;" \
"fi\0" \
"addip=setenv bootargs ${bootargs} " \
"ip=${ipaddr}:${serverip}:${gatewayip}:${netmask}:" \
@ -304,7 +313,7 @@
"run addip;" \
"setenv bootargs ${bootargs} console=${console};" \
"setenv fdt_conf imx6q-${board}-${display}.dtb; " \
"bootm ${loadaddr}#conf@${fdt_conf};" \
"bootm ${loadaddr}#conf@${fdt_conf};reset;" \
"fi\0" \
"falcon_setup=" \
"if mmc dev ${mmcdev}; then " \
@ -318,7 +327,7 @@
"boot_mmc=" \
"if mmc dev ${mmcdev}; then " \
SETUP_BOOTARGS \
"bootm ${loadaddr}#conf@${fdt_conf};" \
"bootm ${loadaddr}#conf@${fdt_conf};reset;" \
"fi\0" \
"set_kernel_part=" \
"if test ${BOOT_FROM} = ACTIVE; then " \
@ -339,16 +348,20 @@
"run recovery;" \
"fi;fi\0" \
"BOOT_FROM=ACTIVE\0" \
"BOOT_FROM_RECOVERY=Linux\0" \
TFTP_UPDATE_BOOTLOADER \
TFTP_UPDATE_SPINOR \
"kernel_part_active=1\0" \
"kernel_part_backup=3\0" \
__TFTP_UPDATE_KERNEL \
"rootfs_part_active=2\0" \
"rootfs_part_backup=4\0" \
"rootfs_file=core-image-lwn-display5.ext4\0" \
"rootfs_file_backup=core-image-lwn-backup-display5.ext4\0" \
__TFTP_UPDATE_ROOTFS \
TFTP_UPDATE_RECOVERY_KERNEL_INITRAMFS \
"tftp_mmc_rootfs_bkp=" \
"setenv rootfs_part ${rootfs_part_backup};" \
"setenv rootfs_file ${rootfs_file_backup};" \
"run tftp_mmc_rootfs\0" \
TFTP_UPDATE_RECOVERY_SWU_KERNEL \
TFTP_UPDATE_RECOVERY_SWU_INITRAMFS \
"\0" \
@ -383,6 +396,11 @@
#define CONFIG_MTD_PARTITIONS
#define CONFIG_MTD_DEVICE
/* Watchdog */
#define CONFIG_HW_WATCHDOG
#define CONFIG_IMX_WATCHDOG
#define CONFIG_WATCHDOG_TIMEOUT_MSECS 15000
/* ENV config */
#ifdef CONFIG_ENV_IS_IN_SPI_FLASH
#define CONFIG_ENV_SIZE (SZ_64K)

@ -46,6 +46,7 @@
"fdt_high=0xffffffff\0" \
"scriptaddr=0x74000000\0" \
"kernel_file=fitImage\0"\
"silent=1\0"\
"rdinit=/sbin/init\0" \
"addinitrd=setenv bootargs ${bootargs} rdinit=${rdinit} ${debug} \0" \
"upd_image=st.4k\0" \

@ -101,18 +101,18 @@
"fi; " \
"fi\0" \
"findfdt="\
"if test $board_name = HUMMINGBOARD2 && test $board_rev = MX6Q ; then " \
"setenv fdtfile imx6q-hummingboard2.dtb; fi; " \
"if test $board_name = HUMMINGBOARD2 && test $board_rev = MX6DL ; then " \
"setenv fdtfile imx6dl-hummingboard2.dtb; fi; " \
"if test $board_name = HUMMINGBOARD && test $board_rev = MX6Q ; then " \
"setenv fdtfile imx6q-hummingboard.dtb; fi; " \
"if test $board_name = HUMMINGBOARD && test $board_rev = MX6DL ; then " \
"setenv fdtfile imx6dl-hummingboard.dtb; fi; " \
"if test $board_name = CUBOXI && test $board_rev = MX6Q ; then " \
"setenv fdtfile imx6q-cubox-i.dtb; fi; " \
"if test $board_name = CUBOXI && test $board_rev = MX6DL ; then " \
"setenv fdtfile imx6dl-cubox-i.dtb; fi; " \
"if test $board_rev = MX6Q ; then " \
"setenv fdtprefix imx6q; fi; " \
"if test $board_rev = MX6DL ; then " \
"setenv fdtprefix imx6dl; fi; " \
"if test $som_rev = V15 ; then " \
"setenv fdtsuffix -som-v15; fi; " \
"if test $board_name = HUMMINGBOARD2 ; then " \
"setenv fdtfile ${fdtprefix}-hummingboard2${fdtsuffix}.dtb; fi; " \
"if test $board_name = HUMMINGBOARD ; then " \
"setenv fdtfile ${fdtprefix}-hummingboard${fdtsuffix}.dtb; fi; " \
"if test $board_name = CUBOXI ; then " \
"setenv fdtfile ${fdtprefix}-cubox-i${fdtsuffix}.dtb; fi; " \
"if test $fdtfile = undefined; then " \
"echo WARNING: Could not determine dtb to use; fi; \0" \
BOOTENV

@ -41,7 +41,7 @@
"console=ttymxc4\0" \
"fdt_high=0xffffffff\0" \
"initrd_high=0xffffffff\0" \
"fdt_file=imx7d-pico.dtb\0" \
"fdt_file=imx7d-pico-pi.dtb\0" \
"fdt_addr=0x83000000\0" \
"ip_dyn=yes\0" \
"mmcdev="__stringify(CONFIG_SYS_MMC_ENV_DEV)"\0" \

@ -78,7 +78,7 @@
#endif
#define CONFIG_EXTRA_ENV_SETTINGS \
"console=ttymxc0,115200\0" \
"console=ttymxc0\0" \
"splashpos=m,m\0" \
"fdtfile=undefined\0" \
"fdt_high=0xffffffff\0" \

@ -80,10 +80,10 @@
#define IMX7D_ARM_M4_ROOT_SRC 67
#define IMX7D_ARM_M4_ROOT_CG 68
#define IMX7D_ARM_M4_ROOT_DIV 69
#define IMX7D_ARM_M0_ROOT_CLK 70
#define IMX7D_ARM_M0_ROOT_SRC 71
#define IMX7D_ARM_M0_ROOT_CG 72
#define IMX7D_ARM_M0_ROOT_DIV 73
#define IMX7D_ARM_M0_ROOT_CLK 70 /* unused */
#define IMX7D_ARM_M0_ROOT_SRC 71 /* unused */
#define IMX7D_ARM_M0_ROOT_CG 72 /* unused */
#define IMX7D_ARM_M0_ROOT_DIV 73 /* unused */
#define IMX7D_MAIN_AXI_ROOT_CLK 74
#define IMX7D_MAIN_AXI_ROOT_SRC 75
#define IMX7D_MAIN_AXI_ROOT_CG 76
@ -450,5 +450,10 @@
#define IMX7D_CLK_ARM 437
#define IMX7D_CKIL 438
#define IMX7D_OCOTP_CLK 439
#define IMX7D_CLK_END 440
#define IMX7D_NAND_RAWNAND_CLK 440
#define IMX7D_NAND_USDHC_BUS_RAWNAND_CLK 441
#define IMX7D_SNVS_CLK 442
#define IMX7D_CAAM_CLK 443
#define IMX7D_KPP_ROOT_CLK 444
#define IMX7D_CLK_END 445
#endif /* __DT_BINDINGS_CLOCK_IMX7D_H */

@ -0,0 +1,16 @@
/*
* Copyright (C) 2017 Impinj
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#ifndef __DT_BINDINGS_IMX7_POWER_H__
#define __DT_BINDINGS_IMX7_POWER_H__
#define IMX7_POWER_DOMAIN_MIPI_PHY 0
#define IMX7_POWER_DOMAIN_PCIE_PHY 1
#define IMX7_POWER_DOMAIN_USB_HSIC_PHY 2
#endif

@ -22,9 +22,16 @@
#include <asm/cache.h>
struct mtd_info;
struct nand_chip;
struct nand_flash_dev;
struct device_node;
/* Get the flash and manufacturer id and lookup if the type is supported. */
struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,
struct nand_chip *chip,
int *maf_id, int *dev_id,
struct nand_flash_dev *type);
/* Scan and identify a NAND device */
int nand_scan(struct mtd_info *mtd, int max_chips);
/*
@ -247,9 +254,6 @@ typedef enum {
#define NAND_CI_CELLTYPE_MSK 0x0C
#define NAND_CI_CELLTYPE_SHIFT 2
/* Keep gcc happy */
struct nand_chip;
/* ONFI features */
#define ONFI_FEATURE_16_BIT_BUS (1 << 0)
#define ONFI_FEATURE_EXT_PARAM_PAGE (1 << 7)

@ -69,7 +69,7 @@ enum {
PFUZE3000_VLDO3CTL = 0x70,
PFUZE3000_VLD4CTL = 0x71,
PMIC_NUM_OF_REGS = 0x7F,
PFUZE3000_NUM_OF_REGS = 0x100,
};
int power_pfuze3000_init(unsigned char bus);

@ -1937,6 +1937,7 @@ CONFIG_SPL_NAND_BASE
CONFIG_SPL_NAND_BOOT
CONFIG_SPL_NAND_DRIVERS
CONFIG_SPL_NAND_ECC
CONFIG_SPL_NAND_IDENT
CONFIG_SPL_NAND_INIT
CONFIG_SPL_NAND_LOAD
CONFIG_SPL_NAND_MINIMAL

Loading…
Cancel
Save