[OpenWrt-Devel,6/9] uboot-sunxi: add spi driver for pine64 lts
diff mbox series

Message ID 20190114175429.7320-7-oskari@lemmela.net
State New
Delegated to: Hauke Mehrtens
Headers show
Series
  • sunxi: add support for pine64-lts
Related show

Commit Message

Oskari Lemmelä Jan. 14, 2019, 5:54 p.m. UTC
Add support for SPI driver and booting from SPI.

Signed-off-by: Oskari Lemmela <oskari@lemmela.net>
---
 ...i-allwinner-spi-driver-sun6i-support.patch | 311 ++++++++++++++++++
 ...er-sunxi-fix-spurious-timeout-issues.patch |  30 ++
 .../302-sunxi-add-spi-flash-bootcmd.patch     |  81 +++++
 ...03-sunxi-dt-a64-sopine-add-spi-alias.patch |  27 ++
 ...4-sunxi-a64-enable-spi-in-pine64-lts.patch |  32 ++
 ...sunxi-enable-distro-spi-boot-command.patch |  25 ++
 6 files changed, 506 insertions(+)
 create mode 100644 package/boot/uboot-sunxi/patches/300-arm-sunxi-allwinner-spi-driver-sun6i-support.patch
 create mode 100644 package/boot/uboot-sunxi/patches/301-arm-timer-sunxi-fix-spurious-timeout-issues.patch
 create mode 100644 package/boot/uboot-sunxi/patches/302-sunxi-add-spi-flash-bootcmd.patch
 create mode 100644 package/boot/uboot-sunxi/patches/303-sunxi-dt-a64-sopine-add-spi-alias.patch
 create mode 100644 package/boot/uboot-sunxi/patches/304-sunxi-a64-enable-spi-in-pine64-lts.patch
 create mode 100644 package/boot/uboot-sunxi/patches/305-sunxi-enable-distro-spi-boot-command.patch

Comments

Hauke Mehrtens Jan. 26, 2019, 11:15 p.m. UTC | #1
On 1/14/19 6:54 PM, Oskari Lemmela wrote:
> Add support for SPI driver and booting from SPI.
> 
> Signed-off-by: Oskari Lemmela <oskari@lemmela.net>
> ---
>  ...i-allwinner-spi-driver-sun6i-support.patch | 311 ++++++++++++++++++
>  ...er-sunxi-fix-spurious-timeout-issues.patch |  30 ++
>  .../302-sunxi-add-spi-flash-bootcmd.patch     |  81 +++++
>  ...03-sunxi-dt-a64-sopine-add-spi-alias.patch |  27 ++
>  ...4-sunxi-a64-enable-spi-in-pine64-lts.patch |  32 ++
>  ...sunxi-enable-distro-spi-boot-command.patch |  25 ++
>  6 files changed, 506 insertions(+)
>  create mode 100644 package/boot/uboot-sunxi/patches/300-arm-sunxi-allwinner-spi-driver-sun6i-support.patch
>  create mode 100644 package/boot/uboot-sunxi/patches/301-arm-timer-sunxi-fix-spurious-timeout-issues.patch
>  create mode 100644 package/boot/uboot-sunxi/patches/302-sunxi-add-spi-flash-bootcmd.patch
>  create mode 100644 package/boot/uboot-sunxi/patches/303-sunxi-dt-a64-sopine-add-spi-alias.patch
>  create mode 100644 package/boot/uboot-sunxi/patches/304-sunxi-a64-enable-spi-in-pine64-lts.patch
>  create mode 100644 package/boot/uboot-sunxi/patches/305-sunxi-enable-distro-spi-boot-command.patch

Will you upstream these patches into mainline U-Boot?

Hauke
Oskari Lemmelä Jan. 27, 2019, 6:28 p.m. UTC | #2
Hi,

On 27.1.2019 1.15, Hauke Mehrtens wrote:
> On 1/14/19 6:54 PM, Oskari Lemmela wrote:
>> Add support for SPI driver and booting from SPI.
>>
>> Signed-off-by: Oskari Lemmela <oskari@lemmela.net>
>> ---
>>  ...i-allwinner-spi-driver-sun6i-support.patch | 311 ++++++++++++++++++
>>  ...er-sunxi-fix-spurious-timeout-issues.patch |  30 ++
>>  .../302-sunxi-add-spi-flash-bootcmd.patch     |  81 +++++
>>  ...03-sunxi-dt-a64-sopine-add-spi-alias.patch |  27 ++
>>  ...4-sunxi-a64-enable-spi-in-pine64-lts.patch |  32 ++
>>  ...sunxi-enable-distro-spi-boot-command.patch |  25 ++
>>  6 files changed, 506 insertions(+)
>>  create mode 100644 package/boot/uboot-sunxi/patches/300-arm-sunxi-allwinner-spi-driver-sun6i-support.patch
>>  create mode 100644 package/boot/uboot-sunxi/patches/301-arm-timer-sunxi-fix-spurious-timeout-issues.patch
>>  create mode 100644 package/boot/uboot-sunxi/patches/302-sunxi-add-spi-flash-bootcmd.patch
>>  create mode 100644 package/boot/uboot-sunxi/patches/303-sunxi-dt-a64-sopine-add-spi-alias.patch
>>  create mode 100644 package/boot/uboot-sunxi/patches/304-sunxi-a64-enable-spi-in-pine64-lts.patch
>>  create mode 100644 package/boot/uboot-sunxi/patches/305-sunxi-enable-distro-spi-boot-command.patch
> Will you upstream these patches into mainline U-Boot?
>
> Hauke

Most of them are sent to upstream. I'll continue with upstream process.

Thanks,
Oskari

Patch
diff mbox series

diff --git a/package/boot/uboot-sunxi/patches/300-arm-sunxi-allwinner-spi-driver-sun6i-support.patch b/package/boot/uboot-sunxi/patches/300-arm-sunxi-allwinner-spi-driver-sun6i-support.patch
new file mode 100644
index 0000000000..553565501f
--- /dev/null
+++ b/package/boot/uboot-sunxi/patches/300-arm-sunxi-allwinner-spi-driver-sun6i-support.patch
@@ -0,0 +1,311 @@ 
+From 04b54c263c51eb28b50e01946989cc174102af8d Mon Sep 17 00:00:00 2001
+From: Oskari Lemmela <oskari@lemmela.net>
+Date: Sat, 29 Dec 2018 10:55:20 +0200
+Subject: [PATCH] arm: sunxi: Allwinner SPI driver sun6i support
+
+Minimal changes to support sun6i based Allwinner SOCs
+Changes are based to SPL driver arch/arm/mach-sunxi/spl_spi_sunxi.c
+
+Signed-off-by: Oskari Lemmela <oskari@lemmela.net>
+---
+ arch/arm/include/asm/arch-sunxi/clock_sun6i.h |   1 +
+ arch/arm/include/asm/arch-sunxi/clock_sun9i.h |   1 +
+ drivers/spi/Kconfig                           |   4 +-
+ drivers/spi/sun4i_spi.c                       | 116 ++++++++++++++++--
+ 4 files changed, 107 insertions(+), 15 deletions(-)
+
+diff --git a/arch/arm/include/asm/arch-sunxi/clock_sun6i.h b/arch/arm/include/asm/arch-sunxi/clock_sun6i.h
+index ee387127f3..4aaa0932d7 100644
+--- a/arch/arm/include/asm/arch-sunxi/clock_sun6i.h
++++ b/arch/arm/include/asm/arch-sunxi/clock_sun6i.h
+@@ -321,6 +321,7 @@ struct sunxi_ccm_reg {
+ #define AHB_GATE_OFFSET_MMC(n)		(AHB_GATE_OFFSET_MMC0 + (n))
+ #define AHB_GATE_OFFSET_DMA		6
+ #define AHB_GATE_OFFSET_SS		5
++#define AHB_GATE_OFFSET_SPI0		20
+ 
+ /* ahb_gate1 offsets */
+ #define AHB_GATE_OFFSET_DRC0		25
+diff --git a/arch/arm/include/asm/arch-sunxi/clock_sun9i.h b/arch/arm/include/asm/arch-sunxi/clock_sun9i.h
+index 530e0dd73b..9bbd4d319e 100644
+--- a/arch/arm/include/asm/arch-sunxi/clock_sun9i.h
++++ b/arch/arm/include/asm/arch-sunxi/clock_sun9i.h
+@@ -194,6 +194,7 @@ struct sunxi_ccm_reg {
+ 
+ /* ahb gate1 field */
+ #define AHB_GATE_OFFSET_DMA		24
++#define AHB_GATE_OFFSET_SPI0		20
+ 
+ /* apb1_gate fields */
+ #define APB1_GATE_UART_SHIFT		16
+diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
+index 516188ea88..996ec9beb7 100644
+--- a/drivers/spi/Kconfig
++++ b/drivers/spi/Kconfig
+@@ -198,9 +198,9 @@ config STM32_QSPI
+ 	  this ST IP core.
+ 
+ config SUN4I_SPI
+-	bool "Allwinner A10 SoCs SPI controller"
++	bool "Allwinner SoCs SPI driver"
+ 	help
+-	  SPI driver for Allwinner sun4i, sun5i and sun7i SoCs
++	  SPI driver for Allwinner SoCs
+ 
+ config TEGRA114_SPI
+ 	bool "nVidia Tegra114 SPI driver"
+diff --git a/drivers/spi/sun4i_spi.c b/drivers/spi/sun4i_spi.c
+index b86b5a00ad..9bc0b60a4e 100644
+--- a/drivers/spi/sun4i_spi.c
++++ b/drivers/spi/sun4i_spi.c
+@@ -37,6 +37,30 @@
+ 
+ #define SUN4I_TXDATA_REG	0x04
+ 
++#ifdef CONFIG_SUNXI_GEN_SUN6I
++#define SUN4I_CTL_REG		0x04
++#define SUN4I_CTL_ENABLE		BIT(0)
++#define SUN4I_CTL_MASTER		BIT(1)
++#define SUN4I_CTL_TP			BIT(7)
++#define SUN4I_CTL_SRST			BIT(31)
++
++#define SUN4I_CTL_CPHA			BIT(0)
++#define SUN4I_CTL_CPOL			BIT(1)
++#define SUN4I_CTL_CS_ACTIVE_LOW		BIT(2)
++#define SUN4I_CTL_CS_MASK		0x30
++#define SUN4I_CTL_CS(cs)		(((cs) << 4) & SUN4I_CTL_CS_MASK)
++#define SUN4I_CTL_CS_MANUAL		BIT(6)
++#define SUN4I_CTL_CS_LEVEL		BIT(7)
++#define SUN4I_CTL_DHB			BIT(8)
++#define SUN4I_CTL_XCH_MASK		0x80000000
++#define SUN4I_CTL_XCH			BIT(31)
++
++#define SUN4I_CTL_RF_RST		BIT(15)
++#define SUN4I_CTL_TF_RST		BIT(31)
++
++#else
++#define SUN4I_CTL_SRST			0
++
+ #define SUN4I_CTL_REG		0x08
+ #define SUN4I_CTL_ENABLE		BIT(0)
+ #define SUN4I_CTL_MASTER		BIT(1)
+@@ -54,6 +78,7 @@
+ #define SUN4I_CTL_CS_MANUAL		BIT(16)
+ #define SUN4I_CTL_CS_LEVEL		BIT(17)
+ #define SUN4I_CTL_TP			BIT(18)
++#endif
+ 
+ #define SUN4I_INT_CTL_REG	0x0c
+ #define SUN4I_INT_CTL_RF_F34		BIT(4)
+@@ -92,11 +117,39 @@
+ #define SUN4I_SPI_DEFAULT_RATE	1000000
+ #define SUN4I_SPI_TIMEOUT_US	1000000
+ 
++#ifdef CONFIG_SUNXI_GEN_SUN6I
++/* sun6i spi register set */
++struct sun4i_spi_regs {
++	u32 res0;
++	u32 ctl;	/* 0x04 */
++	u32 tctl;	/* 0x08 */
++	u32 res1;
++	u32 intctl;	/* 0x10 */
++	u32 st;		/* 0x14 */
++	u32 fifo_ctl;	/* 0x18 */
++	u32 fifo_sta;	/* 0x1c */
++	u32 wait;	/* 0x20 */
++	u32 cctl;	/* 0x24 */
++	u32 res2[2];
++	u32 bc;		/* 0x30 */
++	u32 tc;		/* 0x34 */
++	u32 bctl;	/* 0x38 */
++	u32 res3[113];
++	u32 txdata;	/* 0x200 */
++	u32 res4[63];
++	u32 rxdata;	/* 0x300 */
++};
++#else
+ /* sun4i spi register set */
+ struct sun4i_spi_regs {
+ 	u32 rxdata;
+ 	u32 txdata;
+-	u32 ctl;
++	union {
++		u32 ctl;
++		u32 tctl;
++		u32 fifo_ctl;
++		u32 bctl;
++	};
+ 	u32 intctl;
+ 	u32 st;
+ 	u32 dmactl;
+@@ -106,6 +159,7 @@ struct sun4i_spi_regs {
+ 	u32 tc;
+ 	u32 fifo_sta;
+ };
++#endif
+ 
+ struct sun4i_spi_platdata {
+ 	u32 base_addr;
+@@ -148,7 +202,7 @@ static void sun4i_spi_set_cs(struct udevice *bus, u8 cs, bool enable)
+ 	struct sun4i_spi_priv *priv = dev_get_priv(bus);
+ 	u32 reg;
+ 
+-	reg = readl(&priv->regs->ctl);
++	reg = readl(&priv->regs->tctl);
+ 
+ 	reg &= ~SUN4I_CTL_CS_MASK;
+ 	reg |= SUN4I_CTL_CS(cs);
+@@ -158,7 +212,7 @@ static void sun4i_spi_set_cs(struct udevice *bus, u8 cs, bool enable)
+ 	else
+ 		reg |= SUN4I_CTL_CS_LEVEL;
+ 
+-	writel(reg, &priv->regs->ctl);
++	writel(reg, &priv->regs->tctl);
+ }
+ 
+ static int sun4i_spi_parse_pins(struct udevice *dev)
+@@ -230,7 +284,10 @@ static int sun4i_spi_parse_pins(struct udevice *dev)
+ 			if (pin < 0)
+ 				break;
+ 
+-			sunxi_gpio_set_cfgpin(pin, SUNXI_GPC_SPI0);
++			if (IS_ENABLED(CONFIG_MACH_SUN50I))
++				sunxi_gpio_set_cfgpin(pin, SUN50I_GPC_SPI0);
++			else
++				sunxi_gpio_set_cfgpin(pin, SUNXI_GPC_SPI0);
+ 			sunxi_gpio_set_drv(pin, drive);
+ 			sunxi_gpio_set_pull(pin, pull);
+ 		}
+@@ -243,10 +300,27 @@ static inline void sun4i_spi_enable_clock(void)
+ 	struct sunxi_ccm_reg *const ccm =
+ 		(struct sunxi_ccm_reg *const)SUNXI_CCM_BASE;
+ 
++#ifdef CONFIG_SUNXI_GEN_SUN6I
++	setbits_le32(&ccm->ahb_reset0_cfg, (1 << AHB_GATE_OFFSET_SPI0));
++#endif
++
+ 	setbits_le32(&ccm->ahb_gate0, (1 << AHB_GATE_OFFSET_SPI0));
+ 	writel((1 << 31), &ccm->spi0_clk_cfg);
+ }
+ 
++static inline void sun4i_spi_disable_clock(void)
++{
++	struct sunxi_ccm_reg *const ccm =
++		(struct sunxi_ccm_reg *const)SUNXI_CCM_BASE;
++
++	writel(0, &ccm->spi0_clk_cfg);
++	clrbits_le32(&ccm->ahb_gate0, (1 << AHB_GATE_OFFSET_SPI0));
++
++#ifdef CONFIG_SUNXI_GEN_SUN6I
++	clrbits_le32(&ccm->ahb_reset0_cfg, (1 << AHB_GATE_OFFSET_SPI0));
++#endif
++}
++
+ static int sun4i_spi_ofdata_to_platdata(struct udevice *bus)
+ {
+ 	struct sun4i_spi_platdata *plat = dev_get_platdata(bus);
+@@ -268,7 +342,6 @@ static int sun4i_spi_probe(struct udevice *bus)
+ 	struct sun4i_spi_platdata *plat = dev_get_platdata(bus);
+ 	struct sun4i_spi_priv *priv = dev_get_priv(bus);
+ 
+-	sun4i_spi_enable_clock();
+ 	sun4i_spi_parse_pins(bus);
+ 
+ 	priv->regs = (struct sun4i_spi_regs *)(uintptr_t)plat->base_addr;
+@@ -281,9 +354,17 @@ static int sun4i_spi_claim_bus(struct udevice *dev)
+ {
+ 	struct sun4i_spi_priv *priv = dev_get_priv(dev->parent);
+ 
++	sun4i_spi_enable_clock();
+ 	writel(SUN4I_CTL_ENABLE | SUN4I_CTL_MASTER | SUN4I_CTL_TP |
+-	       SUN4I_CTL_CS_MANUAL | SUN4I_CTL_CS_ACTIVE_LOW,
++	       SUN4I_CTL_SRST,
+ 	       &priv->regs->ctl);
++
++	if (IS_ENABLED(CONFIG_SUNXI_GEN_SUN6I))
++		while (readl(&priv->regs->ctl) & SUN4I_CTL_SRST)
++			;
++
++	setbits_le32(&priv->regs->tctl, SUN4I_CTL_CS_MANUAL |
++		     SUN4I_CTL_CS_ACTIVE_LOW);
+ 	return 0;
+ }
+ 
+@@ -295,6 +376,7 @@ static int sun4i_spi_release_bus(struct udevice *dev)
+ 	reg = readl(&priv->regs->ctl);
+ 	reg &= ~SUN4I_CTL_ENABLE;
+ 	writel(reg, &priv->regs->ctl);
++	sun4i_spi_disable_clock();
+ 
+ 	return 0;
+ }
+@@ -322,10 +404,10 @@ static int sun4i_spi_xfer(struct udevice *dev, unsigned int bitlen,
+ 	if (flags & SPI_XFER_BEGIN)
+ 		sun4i_spi_set_cs(bus, slave_plat->cs, true);
+ 
+-	reg = readl(&priv->regs->ctl);
++	reg = readl(&priv->regs->fifo_ctl);
+ 
+ 	/* Reset FIFOs */
+-	writel(reg | SUN4I_CTL_RF_RST | SUN4I_CTL_TF_RST, &priv->regs->ctl);
++	writel(reg | SUN4I_CTL_RF_RST | SUN4I_CTL_TF_RST, &priv->regs->fifo_ctl);
+ 
+ 	while (len) {
+ 		/* Setup the transfer now... */
+@@ -334,16 +416,18 @@ static int sun4i_spi_xfer(struct udevice *dev, unsigned int bitlen,
+ 		/* Setup the counters */
+ 		writel(SUN4I_BURST_CNT(nbytes), &priv->regs->bc);
+ 		writel(SUN4I_XMIT_CNT(nbytes), &priv->regs->tc);
++		if (IS_ENABLED(CONFIG_SUNXI_GEN_SUN6I))
++			writel(SUN4I_BURST_CNT(nbytes), &priv->regs->bctl);
+ 
+ 		/* Fill the TX FIFO */
+ 		sun4i_spi_fill_fifo(priv, nbytes);
+ 
+ 		/* Start the transfer */
+-		reg = readl(&priv->regs->ctl);
+-		writel(reg | SUN4I_CTL_XCH, &priv->regs->ctl);
++		reg = readl(&priv->regs->tctl);
++		writel(reg | SUN4I_CTL_XCH, &priv->regs->tctl);
+ 
+ 		/* Wait transfer to complete */
+-		ret = wait_for_bit_le32(&priv->regs->ctl, SUN4I_CTL_XCH_MASK,
++		ret = wait_for_bit_le32(&priv->regs->tctl, SUN4I_CTL_XCH_MASK,
+ 					false, SUN4I_SPI_TIMEOUT_US, false);
+ 		if (ret) {
+ 			printf("ERROR: sun4i_spi: Timeout transferring data\n");
+@@ -416,7 +500,7 @@ static int sun4i_spi_set_mode(struct udevice *dev, uint mode)
+ 	struct sun4i_spi_priv *priv = dev_get_priv(dev);
+ 	u32 reg;
+ 
+-	reg = readl(&priv->regs->ctl);
++	reg = readl(&priv->regs->tctl);
+ 	reg &= ~(SUN4I_CTL_CPOL | SUN4I_CTL_CPHA);
+ 
+ 	if (mode & SPI_CPOL)
+@@ -426,7 +510,7 @@ static int sun4i_spi_set_mode(struct udevice *dev, uint mode)
+ 		reg |= SUN4I_CTL_CPHA;
+ 
+ 	priv->mode = mode;
+-	writel(reg, &priv->regs->ctl);
++	writel(reg, &priv->regs->tctl);
+ 
+ 	return 0;
+ }
+@@ -440,7 +524,13 @@ static const struct dm_spi_ops sun4i_spi_ops = {
+ };
+ 
+ static const struct udevice_id sun4i_spi_ids[] = {
++#ifndef CONFIG_SUNXI_GEN_SUN6I
+ 	{ .compatible = "allwinner,sun4i-a10-spi"  },
++#else
++	{ .compatible = "allwinner,sun6i-a31-spi" },
++	{ .compatible = "allwinner,sun8i-h3-spi" },
++	{ .compatible = "allwinner,sun50i-a64-spi" },
++#endif
+ 	{ }
+ };
+ 
+-- 
+2.17.1
+
diff --git a/package/boot/uboot-sunxi/patches/301-arm-timer-sunxi-fix-spurious-timeout-issues.patch b/package/boot/uboot-sunxi/patches/301-arm-timer-sunxi-fix-spurious-timeout-issues.patch
new file mode 100644
index 0000000000..e5c9a180bd
--- /dev/null
+++ b/package/boot/uboot-sunxi/patches/301-arm-timer-sunxi-fix-spurious-timeout-issues.patch
@@ -0,0 +1,30 @@ 
+From 9d7c4fba1b63d0d175c0dd50910edcf1e261a3ab Mon Sep 17 00:00:00 2001
+From: Oskari Lemmela <oskari@lemmela.net>
+Date: Wed, 2 Jan 2019 17:28:33 +0200
+Subject: [PATCH] arm: timer: sunxi: fix false timeout issues
+
+Fixes false timeouts which have seen during testing SPI driver
+in A64 platform. When reducing number of bits from 11 to 10 no
+more false timeouts are seen.
+
+Signed-off-by: Oskari Lemmela <oskari@lemmela.net>
+---
+ arch/arm/cpu/armv8/generic_timer.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/arch/arm/cpu/armv8/generic_timer.c b/arch/arm/cpu/armv8/generic_timer.c
+index c1706dcec1..2e06ee4ed2 100644
+--- a/arch/arm/cpu/armv8/generic_timer.c
++++ b/arch/arm/cpu/armv8/generic_timer.c
+@@ -66,7 +66,7 @@ unsigned long timer_read_counter(void)
+ 	isb();
+ 	do {
+ 		asm volatile("mrs %0, cntpct_el0" : "=r" (cntpct));
+-	} while (((cntpct + 1) & GENMASK(10, 0)) <= 1);
++	} while (((cntpct + 1) & GENMASK(9, 0)) <= 1);
+ 
+ 	return cntpct;
+ }
+-- 
+2.17.1
+
diff --git a/package/boot/uboot-sunxi/patches/302-sunxi-add-spi-flash-bootcmd.patch b/package/boot/uboot-sunxi/patches/302-sunxi-add-spi-flash-bootcmd.patch
new file mode 100644
index 0000000000..84106d6012
--- /dev/null
+++ b/package/boot/uboot-sunxi/patches/302-sunxi-add-spi-flash-bootcmd.patch
@@ -0,0 +1,81 @@ 
+From a0ef52785699cca21a52fe8519b7580dd37678a3 Mon Sep 17 00:00:00 2001
+From: Oskari Lemmela <oskari@lemmela.net>
+Date: Sun, 13 Jan 2019 19:29:31 +0200
+Subject: [PATCH] distro_bootcmd: add spi flash boot command
+
+Add a boot command to distro boot to support load FIT image
+from SPI flash.
+
+Signed-off-by: Oskari Lemmela <oskari@lemmela.net>
+---
+ Kconfig                         | 26 ++++++++++++++++++++++++++
+ include/config_distro_bootcmd.h | 16 ++++++++++++++++
+ 2 files changed, 42 insertions(+)
+
+diff --git a/Kconfig b/Kconfig
+index dca9bb4e43..68234f39bb 100644
+--- a/Kconfig
++++ b/Kconfig
+@@ -321,6 +321,32 @@ config FIT_IMAGE_POST_PROCESS
+ 	  injected into the FIT creation (i.e. the blobs would have been pre-
+ 	  processed before being added to the FIT image).
+ 
++config FIT_SPI_FLASH_BOOT
++	bool "Distro bootcmd from SPI Flash"
++	depends on DM_SPI_FLASH
++	help
++	  Enable distro bootcmd from SPI flash.
++
++config FIT_FLASH_IMAGE_ADDR
++	hex "FIT Image Memory Addr"
++	depends on FIT_SPI_FLASH_BOOT
++	help
++	  Memory address where to load FIT image from flash device.
++
++config FIT_FLASH_IMAGE_OFFSET
++	hex "FIT Image Offset"
++	depends on FIT_SPI_FLASH_BOOT
++	default 0x100000
++	help
++	  Flash offset from start of device.
++
++config FIT_FLASH_IMAGE_SIZE
++	hex "FIT Image Size"
++	depends on FIT_SPI_FLASH_BOOT
++	default 0x700000
++	help
++	  Size of the FIT image in flash device.
++
+ if SPL
+ 
+ config SPL_FIT
+diff --git a/include/config_distro_bootcmd.h b/include/config_distro_bootcmd.h
+index 373fee78a9..2bc3b4d487 100644
+--- a/include/config_distro_bootcmd.h
++++ b/include/config_distro_bootcmd.h
+@@ -242,6 +242,22 @@
+ 	BOOT_TARGET_DEVICES_references_USB_without_CONFIG_CMD_USB
+ #endif
+ 
++#ifdef CONFIG_FIT_SPI_FLASH_BOOT
++#define BOOT_TARGET_DEVICES_SPI(func) func(SPI, spi, 0)
++#define BOOTENV_DEV_SPI(devtypeu, devtypel, instance) \
++	"image_addr_r=" __stringify(CONFIG_FIT_FLASH_IMAGE_ADDR) "\0" \
++	"image_addr=" __stringify(CONFIG_FIT_FLASH_IMAGE_OFFSET) "\0" \
++	"image_size=" __stringify(CONFIG_FIT_FLASH_IMAGE_SIZE) "\0" \
++	"bootcmd_" #devtypel #instance "=" \
++		"if sf probe " #instance "; then " \
++			"sf read ${image_addr_r} ${image_addr} ${image_size}; " \
++			"bootm ${image_addr_r}; " \
++	"fi\0"
++#define BOOTENV_DEV_NAME_SPI	BOOTENV_DEV_NAME_BLKDEV
++#else
++#define BOOT_TARGET_DEVICES_SPI(func)
++#endif
++
+ #if defined(CONFIG_CMD_DHCP)
+ #if defined(CONFIG_EFI_LOADER)
+ /* http://www.iana.org/assignments/dhcpv6-parameters/dhcpv6-parameters.xml */
+-- 
+2.17.1
+
diff --git a/package/boot/uboot-sunxi/patches/303-sunxi-dt-a64-sopine-add-spi-alias.patch b/package/boot/uboot-sunxi/patches/303-sunxi-dt-a64-sopine-add-spi-alias.patch
new file mode 100644
index 0000000000..0a416b3feb
--- /dev/null
+++ b/package/boot/uboot-sunxi/patches/303-sunxi-dt-a64-sopine-add-spi-alias.patch
@@ -0,0 +1,27 @@ 
+From 5848c493cc3f208897a9212265b286f0da89ac85 Mon Sep 17 00:00:00 2001
+From: Oskari Lemmela <oskari@lemmela.net>
+Date: Wed, 2 Jan 2019 17:30:46 +0200
+Subject: [PATCH] sunxi: dt: a64: sopine add spi alias
+
+Add sopine SPI alias for SPI environment and boot.
+
+Signed-off-by: Oskari Lemmela <oskari@lemmela.net>
+---
+ arch/arm/dts/sun50i-a64-sopine-baseboard.dts | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/arch/arm/dts/sun50i-a64-sopine-baseboard.dts b/arch/arm/dts/sun50i-a64-sopine-baseboard.dts
+index abe179de35..d99c6ed109 100644
+--- a/arch/arm/dts/sun50i-a64-sopine-baseboard.dts
++++ b/arch/arm/dts/sun50i-a64-sopine-baseboard.dts
+@@ -55,6 +55,7 @@
+ 	aliases {
+ 		ethernet0 = &emac;
+ 		serial0 = &uart0;
++		spi0 = &spi0;
+ 	};
+ 
+ 	chosen {
+-- 
+2.17.1
+
diff --git a/package/boot/uboot-sunxi/patches/304-sunxi-a64-enable-spi-in-pine64-lts.patch b/package/boot/uboot-sunxi/patches/304-sunxi-a64-enable-spi-in-pine64-lts.patch
new file mode 100644
index 0000000000..602b825d69
--- /dev/null
+++ b/package/boot/uboot-sunxi/patches/304-sunxi-a64-enable-spi-in-pine64-lts.patch
@@ -0,0 +1,32 @@ 
+From 7ec5cbefba8768d02b9fd91e4fb7275fd06aafe5 Mon Sep 17 00:00:00 2001
+From: Oskari Lemmela <oskari@lemmela.net>
+Date: Sat, 5 Jan 2019 19:02:58 +0200
+Subject: [PATCH] sunxi: a64: enable spi in pine64 lts
+
+Enable SPI driver and boot from SPI flash to pine64 LTS defconfig
+
+Signed-off-by: Oskari Lemmela <oskari@lemmela.net>
+---
+ configs/pine64-lts_defconfig | 9 +++++++++
+ 1 file changed, 9 insertions(+)
+
+diff --git a/configs/pine64-lts_defconfig b/configs/pine64-lts_defconfig
+index fd3cdeec85..82208f8a3e 100644
+--- a/configs/pine64-lts_defconfig
++++ b/configs/pine64-lts_defconfig
+@@ -17,3 +17,12 @@ CONFIG_DEFAULT_DEVICE_TREE="sun50i-a64-pine64-lts"
+ CONFIG_SUN8I_EMAC=y
+ CONFIG_USB_EHCI_HCD=y
+ CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y
++CONFIG_CMD_SF=y
++CONFIG_DM_SPI=y
++CONFIG_DM_SPI_FLASH=y
++CONFIG_FIT_SPI_FLASH_BOOT=y
++CONFIG_FIT_FLASH_IMAGE_ADDR=0x5A000000
++CONFIG_SPI=y
++CONFIG_SPI_FLASH=y
++CONFIG_SPI_FLASH_WINBOND=y
++CONFIG_SUN4I_SPI=y
+-- 
+2.17.1
+
diff --git a/package/boot/uboot-sunxi/patches/305-sunxi-enable-distro-spi-boot-command.patch b/package/boot/uboot-sunxi/patches/305-sunxi-enable-distro-spi-boot-command.patch
new file mode 100644
index 0000000000..d7f508a9be
--- /dev/null
+++ b/package/boot/uboot-sunxi/patches/305-sunxi-enable-distro-spi-boot-command.patch
@@ -0,0 +1,25 @@ 
+From 156337bd9b4241b06cc8f516291eb44824532b92 Mon Sep 17 00:00:00 2001
+From: Oskari Lemmela <oskari@lemmela.net>
+Date: Sun, 13 Jan 2019 19:31:43 +0200
+Subject: [PATCH] sunxi: enable distro spi boot command
+
+Signed-off-by: Oskari Lemmela <oskari@lemmela.net>
+---
+ include/configs/sunxi-common.h | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/include/configs/sunxi-common.h b/include/configs/sunxi-common.h
+index 9819d9980c..9cbf74d9e2 100644
+--- a/include/configs/sunxi-common.h
++++ b/include/configs/sunxi-common.h
+@@ -416,6 +416,7 @@ extern int soft_i2c_gpio_scl;
+ 	BOOT_TARGET_DEVICES_MMC(func) \
+ 	BOOT_TARGET_DEVICES_SCSI(func) \
+ 	BOOT_TARGET_DEVICES_USB(func) \
++	BOOT_TARGET_DEVICES_SPI(func) \
+ 	func(PXE, pxe, na) \
+ 	func(DHCP, dhcp, na)
+ 
+-- 
+2.17.1
+