From 8a96be0266ac1c6c7635b6c9e4d46b14921e64f1 Mon Sep 17 00:00:00 2001 From: Hauke Mehrtens Date: Sat, 13 Jan 2018 21:02:35 +0100 Subject: [PATCH] uboot-sunxi: add spi flash support This adds SPI flash support for the sunxi SoCs to U-boot. This code is taken from here: https://github.com/StephanvanSchaik/u-boot/tree/sunxi-spi Signed-off-by: Hauke Mehrtens --- ...-dependency-on-CONFIG_SPL_SPI_FLASH_.patch | 30 ++ ...g-AHB_GATE_OFFSET_SPIx-defines-for-s.patch | 38 ++ ...register-definitions-for-sun4i-sun7i.patch | 104 +++++ ...gister-definitions-for-sun6i-sun8i-s.patch | 73 ++++ ...I-driver-for-Allwinner-devices-sunxi.patch | 397 ++++++++++++++++++ ...ce-and-use-sunxi_gpio_parse_pin_name.patch | 59 +++ ...uce-and-use-sunxi_gpio_setup_dt_pins.patch | 94 +++++ ...i-spi-set-up-GPIO-pins-using-pinctrl.patch | 60 +++ ...-SPI0-controller-for-A20-OLinuXino-L.patch | 39 ++ ...e-SPI0-controller-for-Orange-Pi-Zero.patch | 57 +++ ...ts-enable-SPI0-controller-for-Pine64.patch | 56 +++ ...t-bootcmd-when-spi-boot-is-activated.patch | 27 ++ 12 files changed, 1034 insertions(+) create mode 100644 package/boot/uboot-sunxi/patches/400-spl-sunxi-remove-dependency-on-CONFIG_SPL_SPI_FLASH_.patch create mode 100644 package/boot/uboot-sunxi/patches/401-sunxi-add-missing-AHB_GATE_OFFSET_SPIx-defines-for-s.patch create mode 100644 package/boot/uboot-sunxi/patches/402-sunxi-add-SPI-register-definitions-for-sun4i-sun7i.patch create mode 100644 package/boot/uboot-sunxi/patches/403-sunxi-add-SPI-register-definitions-for-sun6i-sun8i-s.patch create mode 100644 package/boot/uboot-sunxi/patches/404-sunxi-add-SPI-driver-for-Allwinner-devices-sunxi.patch create mode 100644 package/boot/uboot-sunxi/patches/405-introduce-and-use-sunxi_gpio_parse_pin_name.patch create mode 100644 package/boot/uboot-sunxi/patches/406-introduce-and-use-sunxi_gpio_setup_dt_pins.patch create mode 100644 package/boot/uboot-sunxi/patches/407-sunxi-spi-set-up-GPIO-pins-using-pinctrl.patch create mode 100644 package/boot/uboot-sunxi/patches/408-sunxi-dts-enable-SPI0-controller-for-A20-OLinuXino-L.patch create mode 100644 package/boot/uboot-sunxi/patches/409-sunxi-dts-enable-SPI0-controller-for-Orange-Pi-Zero.patch create mode 100644 package/boot/uboot-sunxi/patches/410-sunxi-dts-enable-SPI0-controller-for-Pine64.patch create mode 100644 package/boot/uboot-sunxi/patches/414-sunxi-set-bootcmd-when-spi-boot-is-activated.patch diff --git a/package/boot/uboot-sunxi/patches/400-spl-sunxi-remove-dependency-on-CONFIG_SPL_SPI_FLASH_.patch b/package/boot/uboot-sunxi/patches/400-spl-sunxi-remove-dependency-on-CONFIG_SPL_SPI_FLASH_.patch new file mode 100644 index 0000000000..4316abb0b5 --- /dev/null +++ b/package/boot/uboot-sunxi/patches/400-spl-sunxi-remove-dependency-on-CONFIG_SPL_SPI_FLASH_.patch @@ -0,0 +1,30 @@ +From d29b588d656e278b1a6153f842d1b2d95a384ba6 Mon Sep 17 00:00:00 2001 +From: "S.J.R. van Schaik" +Date: Thu, 9 Feb 2017 21:11:14 +0000 +Subject: spl: sunxi: remove dependency on CONFIG_SPL_SPI_FLASH_SUPPORT. + +--- + drivers/Makefile | 1 + + drivers/mtd/spi/Makefile | 1 - + 3 files changed, 1 insertion(+), 2 deletions(-) + +--- a/drivers/Makefile ++++ b/drivers/Makefile +@@ -48,6 +48,7 @@ obj-$(CONFIG_OMAP_USB_PHY) += usb/phy/ + obj-$(CONFIG_SPL_SATA_SUPPORT) += block/ + obj-$(CONFIG_SPL_USB_HOST_SUPPORT) += block/ + obj-$(CONFIG_SPL_MMC_SUPPORT) += block/ ++obj-$(CONFIG_SPL_SPI_SUNXI) += mtd/spi/sunxi_spi_spl.o + endif + + ifdef CONFIG_TPL_BUILD +--- a/drivers/mtd/spi/Makefile ++++ b/drivers/mtd/spi/Makefile +@@ -9,7 +9,6 @@ obj-$(CONFIG_DM_SPI_FLASH) += sf-uclass. + + ifdef CONFIG_SPL_BUILD + obj-$(CONFIG_SPL_SPI_BOOT) += fsl_espi_spl.o +-obj-$(CONFIG_SPL_SPI_SUNXI) += sunxi_spi_spl.o + endif + + obj-$(CONFIG_SPI_FLASH) += sf_probe.o spi_flash.o spi_flash_ids.o sf.o diff --git a/package/boot/uboot-sunxi/patches/401-sunxi-add-missing-AHB_GATE_OFFSET_SPIx-defines-for-s.patch b/package/boot/uboot-sunxi/patches/401-sunxi-add-missing-AHB_GATE_OFFSET_SPIx-defines-for-s.patch new file mode 100644 index 0000000000..1b5103a073 --- /dev/null +++ b/package/boot/uboot-sunxi/patches/401-sunxi-add-missing-AHB_GATE_OFFSET_SPIx-defines-for-s.patch @@ -0,0 +1,38 @@ +From bc7fe28b76b7e99a0bfc23bdb7dbcecc82069fa9 Mon Sep 17 00:00:00 2001 +From: "S.J.R. van Schaik" +Date: Fri, 10 Feb 2017 12:04:17 +0000 +Subject: sunxi: add missing AHB_GATE_OFFSET_SPIx defines for sun6i/sun9i + +Added missing AHB_GATE_OFFSET_SPIx defines to enable/disable clock gating for +SPI on the sun6i and sun9i platforms. + +Signed-off-by: S.J.R. van Schaik +--- + arch/arm/include/asm/arch-sunxi/clock_sun6i.h | 2 ++ + arch/arm/include/asm/arch-sunxi/clock_sun9i.h | 4 ++++ + 2 files changed, 6 insertions(+) + +--- a/arch/arm/include/asm/arch-sunxi/clock_sun6i.h ++++ b/arch/arm/include/asm/arch-sunxi/clock_sun6i.h +@@ -290,6 +290,8 @@ struct sunxi_ccm_reg { + #define AHB_GATE_OFFSET_USB0 25 + #define AHB_GATE_OFFSET_SATA 24 + #endif ++#define AHB_GATE_OFFSET_SPI1 21 ++#define AHB_GATE_OFFSET_SPI0 20 + #define AHB_GATE_OFFSET_MCTL 14 + #define AHB_GATE_OFFSET_GMAC 17 + #define AHB_GATE_OFFSET_NAND0 13 +--- a/arch/arm/include/asm/arch-sunxi/clock_sun9i.h ++++ b/arch/arm/include/asm/arch-sunxi/clock_sun9i.h +@@ -195,6 +195,10 @@ struct sunxi_ccm_reg { + + /* ahb gate1 field */ + #define AHB_GATE_OFFSET_DMA 24 ++#define AHB_GATE_OFFSET_SPI3 23 ++#define AHB_GATE_OFFSET_SPI2 22 ++#define AHB_GATE_OFFSET_SPI1 21 ++#define AHB_GATE_OFFSET_SPI0 20 + + /* apb1_gate fields */ + #define APB1_GATE_UART_SHIFT 16 diff --git a/package/boot/uboot-sunxi/patches/402-sunxi-add-SPI-register-definitions-for-sun4i-sun7i.patch b/package/boot/uboot-sunxi/patches/402-sunxi-add-SPI-register-definitions-for-sun4i-sun7i.patch new file mode 100644 index 0000000000..52cbb4c99f --- /dev/null +++ b/package/boot/uboot-sunxi/patches/402-sunxi-add-SPI-register-definitions-for-sun4i-sun7i.patch @@ -0,0 +1,104 @@ +From 14b309992da44fab80fe4552b8f5bdef630f6f1f Mon Sep 17 00:00:00 2001 +From: "S.J.R. van Schaik" +Date: Fri, 10 Feb 2017 11:24:37 +0000 +Subject: sunxi: add SPI register definitions for sun4i/sun7i + +Introduces SPI registers for sun4i/sun7i by adding struct sunxi_spi_regs +and flags. + +Signed-off-by: S.J.R. van Schaik +--- + arch/arm/include/asm/arch-sunxi/spi.h | 29 ++++++++++++++++ + arch/arm/include/asm/arch-sunxi/spi_sun4i.h | 53 +++++++++++++++++++++++++++++ + 2 files changed, 82 insertions(+) + create mode 100644 arch/arm/include/asm/arch-sunxi/spi.h + create mode 100644 arch/arm/include/asm/arch-sunxi/spi_sun4i.h + +--- /dev/null ++++ b/arch/arm/include/asm/arch-sunxi/spi.h +@@ -0,0 +1,29 @@ ++/* ++ * (C) Copyright 2017 Whitebox Systems / Northend Systems B.V. ++ * S.J.R. van Schaik ++ * M.B.W. Wajer ++ * ++ * SPDX-License-Identifier: GPL-2.0+ ++ */ ++ ++#ifndef _SUNXI_SPI_H ++#define _SUNXI_SPI_H ++ ++#if defined(CONFIG_MACH_SUN6I) || defined(CONFIG_MACH_SUN8I) || \ ++ defined(CONFIG_MACH_SUN9I) || defined(CONFIG_MACH_SUN50I) ++#include ++#else ++#include ++#endif ++ ++#define SUNXI_SPI_BURST_CNT(cnt) ((cnt) & 0xffffff) ++#define SUNXI_SPI_XMIT_CNT(cnt) ((cnt) & 0xffffff) ++ ++#define SUNXI_SPI_CLK_CTL_CDR2_MASK 0xff ++#define SUNXI_SPI_CLK_CTL_CDR2(div) ((div) & SUNXI_SPI_CLK_CTL_CDR2_MASK) ++#define SUNXI_SPI_CLK_CTL_CDR1_MASK 0xf ++#define SUNXI_SPI_CLK_CTL_CDR1(div) \ ++ (((div) & SUNXI_SPI_CLK_CTL_CDR1_MASK) << 8) ++#define SUNXI_SPI_CLK_CTL_DRS BIT(12) ++ ++#endif /* _SUNXI_SPI_H */ +--- /dev/null ++++ b/arch/arm/include/asm/arch-sunxi/spi_sun4i.h +@@ -0,0 +1,53 @@ ++/* ++ * (C) Copyright 2017 Whitebox Systems / Northend Systems B.V. ++ * S.J.R. van Schaik ++ * M.B.W. Wajer ++ * ++ * SPDX-License-Identifier: GPL-2.0+ ++ */ ++ ++#ifndef _SUNXI_SPI_SUN4I_H ++#define _SUNXI_SPI_SUN4I_H ++ ++struct sunxi_spi_regs { ++ uint32_t rx_data; /* 0x00 */ ++ uint32_t tx_data; /* 0x04 */ ++ union { ++ uint32_t glb_ctl; ++ uint32_t xfer_ctl; ++ uint32_t fifo_ctl; ++ uint32_t burst_ctl; ++ }; /* 0x08 */ ++ uint32_t int_ctl; /* 0x0c */ ++ uint32_t int_sta; /* 0x10 */ ++ uint32_t dma_ctl; /* 0x14 */ ++ uint32_t wait; /* 0x18 */ ++ uint32_t clk_ctl; /* 0x1c */ ++ uint32_t burst_cnt; /* 0x20 */ ++ uint32_t xmit_cnt; /* 0x24 */ ++ uint32_t fifo_sta; /* 0x28 */ ++}; ++ ++#define SUNXI_SPI_CTL_SRST 0 ++ ++#define SUNXI_SPI_CTL_ENABLE BIT(0) ++#define SUNXI_SPI_CTL_MASTER BIT(1) ++#define SUNXI_SPI_CTL_CPHA BIT(2) ++#define SUNXI_SPI_CTL_CPOL BIT(3) ++#define SUNXI_SPI_CTL_CS_ACTIVE_LOW BIT(4) ++#define SUNXI_SPI_CTL_TF_RST BIT(8) ++#define SUNXI_SPI_CTL_RF_RST BIT(9) ++#define SUNXI_SPI_CTL_XCH BIT(10) ++#define SUNXI_SPI_CTL_CS_MASK 0x3000 ++#define SUNXI_SPI_CTL_CS(cs) (((cs) << 12) & SUNXI_SPI_CTL_CS_MASK) ++#define SUNXI_SPI_CTL_DHB BIT(15) ++#define SUNXI_SPI_CTL_CS_MANUAL BIT(16) ++#define SUNXI_SPI_CTL_CS_LEVEL BIT(17) ++#define SUNXI_SPI_CTL_TP BIT(18) ++ ++#define SUNXI_SPI_FIFO_RF_CNT_MASK 0x7f ++#define SUNXI_SPI_FIFO_RF_CNT_BITS 0 ++#define SUNXI_SPI_FIFO_TF_CNT_MASK 0x7f ++#define SUNXI_SPI_FIFO_TF_CNT_BITS 16 ++ ++#endif /* _SUNXI_SPI_SUN4I_H */ diff --git a/package/boot/uboot-sunxi/patches/403-sunxi-add-SPI-register-definitions-for-sun6i-sun8i-s.patch b/package/boot/uboot-sunxi/patches/403-sunxi-add-SPI-register-definitions-for-sun6i-sun8i-s.patch new file mode 100644 index 0000000000..56f2b971d1 --- /dev/null +++ b/package/boot/uboot-sunxi/patches/403-sunxi-add-SPI-register-definitions-for-sun6i-sun8i-s.patch @@ -0,0 +1,73 @@ +From 2be081c6d037107dd8bc2e824ae61d4429aa64a1 Mon Sep 17 00:00:00 2001 +From: "S.J.R. van Schaik" +Date: Fri, 10 Feb 2017 11:25:56 +0000 +Subject: sunxi: add SPI register definitions for sun6i/sun8i/sun9i/sun50i + +Introduces SPI registers for sun6i/sun8i/sun9i/sun50i by adding struct +sunxi_spi_regs and flags. + +Signed-off-by: S.J.R. van Schaik +--- + arch/arm/include/asm/arch-sunxi/spi_sun6i.h | 56 +++++++++++++++++++++++++++++ + 1 file changed, 56 insertions(+) + create mode 100644 arch/arm/include/asm/arch-sunxi/spi_sun6i.h + +--- /dev/null ++++ b/arch/arm/include/asm/arch-sunxi/spi_sun6i.h +@@ -0,0 +1,56 @@ ++/* ++ * (C) Copyright 2017 Whitebox Systems / Northend Systems B.V. ++ * S.J.R. van Schaik ++ * M.B.W. Wajer ++ * ++ * SPDX-License-Identifier: GPL-2.0+ ++ */ ++ ++#ifndef _SUNXI_SPI_SUN6I_H ++#define _SUNXI_SPI_SUN6I_H ++ ++struct sunxi_spi_regs { ++ uint32_t unused0[1]; ++ uint32_t glb_ctl; /* 0x04 */ ++ uint32_t xfer_ctl; /* 0x08 */ ++ uint32_t unused1[1]; ++ uint32_t int_ctl; /* 0x10 */ ++ uint32_t int_sta; /* 0x14 */ ++ uint32_t fifo_ctl; /* 0x18 */ ++ uint32_t fifo_sta; /* 0x1c */ ++ uint32_t wait; /* 0x20 */ ++ uint32_t clk_ctl; /* 0x24 */ ++ uint32_t unused2[2]; ++ uint32_t burst_cnt; /* 0x30 */ ++ uint32_t xmit_cnt; /* 0x34 */ ++ uint32_t burst_ctl; /* 0x38 */ ++ uint32_t unused3[113]; ++ uint32_t tx_data; /* 0x200 */ ++ uint32_t unused4[63]; ++ uint32_t rx_data; /* 0x300 */ ++}; ++ ++#define SUNXI_SPI_CTL_ENABLE BIT(0) ++#define SUNXI_SPI_CTL_MASTER BIT(1) ++#define SUNXI_SPI_CTL_TP BIT(7) ++#define SUNXI_SPI_CTL_SRST BIT(31) ++ ++#define SUNXI_SPI_CTL_CPHA BIT(0) ++#define SUNXI_SPI_CTL_CPOL BIT(1) ++#define SUNXI_SPI_CTL_CS_ACTIVE_LOW BIT(2) ++#define SUNXI_SPI_CTL_CS_MASK 0x30 ++#define SUNXI_SPI_CTL_CS(cs) (((cs) << 4) & SUNXI_SPI_CTL_CS_MASK) ++#define SUNXI_SPI_CTL_CS_MANUAL BIT(6) ++#define SUNXI_SPI_CTL_CS_LEVEL BIT(7) ++#define SUNXI_SPI_CTL_DHB BIT(8) ++#define SUNXI_SPI_CTL_XCH BIT(31) ++ ++#define SUNXI_SPI_CTL_RF_RST BIT(15) ++#define SUNXI_SPI_CTL_TF_RST BIT(31) ++ ++#define SUNXI_SPI_FIFO_RF_CNT_MASK 0x7f ++#define SUNXI_SPI_FIFO_RF_CNT_BITS 0 ++#define SUNXI_SPI_FIFO_TF_CNT_MASK 0x7f ++#define SUNXI_SPI_FIFO_TF_CNT_BITS 16 ++ ++#endif /* _SUNXI_SPI_SUN6I_H */ diff --git a/package/boot/uboot-sunxi/patches/404-sunxi-add-SPI-driver-for-Allwinner-devices-sunxi.patch b/package/boot/uboot-sunxi/patches/404-sunxi-add-SPI-driver-for-Allwinner-devices-sunxi.patch new file mode 100644 index 0000000000..6645292d54 --- /dev/null +++ b/package/boot/uboot-sunxi/patches/404-sunxi-add-SPI-driver-for-Allwinner-devices-sunxi.patch @@ -0,0 +1,397 @@ +From 34e5d3bc4e50233cdd445ef371f06d33ce71e4b0 Mon Sep 17 00:00:00 2001 +From: "S.J.R. van Schaik" +Date: Fri, 10 Feb 2017 12:32:49 +0000 +Subject: sunxi: add SPI driver for Allwinner devices (sunxi) + +Implements a driver model SPI driver for Allwinner devices (sunxi). + +Signed-off-by: S.J.R. van Schaik +--- + drivers/spi/Kconfig | 5 + + drivers/spi/Makefile | 1 + + drivers/spi/sunxi_spi.c | 355 ++++++++++++++++++++++++++++++++++++++++++++++++ + 3 files changed, 361 insertions(+) + create mode 100644 drivers/spi/sunxi_spi.c + +--- a/drivers/spi/Kconfig ++++ b/drivers/spi/Kconfig +@@ -132,6 +132,11 @@ config STM32_QSPI + used to access the SPI NOR flash chips on platforms embedding + this ST IP core. + ++config SUNXI_SPI ++ bool "Allwinner SPI driver" ++ help ++ Enable the Allwinner SPI driver. ++ + config TEGRA114_SPI + bool "nVidia Tegra114 SPI driver" + help +--- a/drivers/spi/Makefile ++++ b/drivers/spi/Makefile +@@ -42,6 +42,7 @@ obj-$(CONFIG_SANDBOX_SPI) += sandbox_spi + obj-$(CONFIG_SH_SPI) += sh_spi.o + obj-$(CONFIG_SH_QSPI) += sh_qspi.o + obj-$(CONFIG_STM32_QSPI) += stm32_qspi.o ++obj-$(CONFIG_SUNXI_SPI) += sunxi_spi.o + obj-$(CONFIG_TEGRA114_SPI) += tegra114_spi.o + obj-$(CONFIG_TEGRA20_SFLASH) += tegra20_sflash.o + obj-$(CONFIG_TEGRA20_SLINK) += tegra20_slink.o +--- /dev/null ++++ b/drivers/spi/sunxi_spi.c +@@ -0,0 +1,355 @@ ++/* ++ * (C) Copyright 2017 Whitebox Systems / Northend Systems B.V. ++ * S.J.R. van Schaik ++ * M.B.W. Wajer ++ * ++ * SPDX-License-Identifier: GPL-2.0+ ++ */ ++ ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++ ++#include ++#include ++ ++#define SUNXI_SPI_MAX_RATE (24 * 1000 * 1000) ++#define SUNXI_SPI_MIN_RATE (3 * 1000) ++ ++struct sunxi_spi_platdata { ++ struct sunxi_spi_regs *regs; ++ unsigned int activate_delay_us; ++ unsigned int deactivate_delay_us; ++ uint32_t freq; ++}; ++ ++struct sunxi_spi_priv { ++ struct sunxi_spi_regs *regs; ++ unsigned int max_freq; ++ unsigned int last_transaction_us; ++}; ++ ++DECLARE_GLOBAL_DATA_PTR; ++ ++static void sunxi_spi_setup_pinmux(unsigned int pin_func) ++{ ++ unsigned int pin; ++ ++ for (pin = SUNXI_GPC(0); pin <= SUNXI_GPC(2); pin++) ++ sunxi_gpio_set_cfgpin(pin, pin_func); ++ ++ if (IS_ENABLED(CONFIG_MACH_SUN4I) || IS_ENABLED(CONFIG_MACH_SUN7I)) { ++ sunxi_gpio_set_cfgpin(SUNXI_GPC(23), pin_func); ++ } else { ++ sunxi_gpio_set_cfgpin(SUNXI_GPC(3), pin_func); ++ } ++} ++ ++static void sunxi_spi_enable_clock(struct udevice *bus) ++{ ++ struct sunxi_ccm_reg * const ccm = ++ (struct sunxi_ccm_reg * const)SUNXI_CCM_BASE; ++ ++#if defined(CONFIG_MACH_SUN6I) || defined(CONFIG_MACH_SUN8I) || \ ++ defined(CONFIG_MACH_SUN9I) || defined(CONFIG_MACH_SUN50I) ++ 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 void sunxi_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)); ++ ++#if defined(CONFIG_MACH_SUN6I) || defined(CONFIG_MACH_SUN8I) || \ ++ defined(CONFIG_MACH_SUN9I) || defined(CONFIG_MACH_SUN50I) ++ clrbits_le32(&ccm->ahb_reset0_cfg, ++ (1 << AHB_GATE_OFFSET_SPI0)); ++#endif ++} ++ ++static void sunxi_spi_cs_activate(struct udevice *dev, unsigned int cs) ++{ ++ struct udevice *bus = dev->parent; ++ struct sunxi_spi_platdata *plat = dev_get_platdata(bus); ++ struct sunxi_spi_priv *priv = dev_get_priv(bus); ++ uint32_t reg; ++ ++ /* If it is too soon to perform another transaction, wait. */ ++ if (plat->deactivate_delay_us && priv->last_transaction_us) { ++ unsigned int delay_us; ++ ++ delay_us = timer_get_us() - priv->last_transaction_us; ++ ++ if (delay_us < plat->deactivate_delay_us) ++ udelay(plat->deactivate_delay_us - delay_us); ++ } ++ ++ debug("%s: activate cs: %u, bus: '%s'\n", __func__, cs, bus->name); ++ ++ reg = readl(&priv->regs->xfer_ctl); ++ reg &= ~(SUNXI_SPI_CTL_CS_MASK | SUNXI_SPI_CTL_CS_LEVEL); ++ reg |= SUNXI_SPI_CTL_CS(cs); ++ writel(reg, &priv->regs->xfer_ctl); ++ ++ if (plat->activate_delay_us) ++ udelay(plat->activate_delay_us); ++} ++ ++static void sunxi_spi_cs_deactivate(struct udevice *dev, unsigned int cs) ++{ ++ struct udevice *bus = dev->parent; ++ struct sunxi_spi_platdata *plat = dev_get_platdata(bus); ++ struct sunxi_spi_priv *priv = dev_get_priv(bus); ++ uint32_t reg; ++ ++ debug("%s: deactivate cs: %u, bus: '%s'\n", __func__, cs, bus->name); ++ ++ reg = readl(&priv->regs->xfer_ctl); ++ reg &= ~SUNXI_SPI_CTL_CS_MASK; ++ reg |= SUNXI_SPI_CTL_CS_LEVEL; ++ writel(reg, &priv->regs->xfer_ctl); ++ ++ /* ++ * Remember the time of this transaction so that we can honour the bus ++ * delay. ++ */ ++ if (plat->deactivate_delay_us) ++ priv->last_transaction_us = timer_get_us(); ++} ++ ++static int sunxi_spi_ofdata_to_platdata(struct udevice *bus) ++{ ++ struct sunxi_spi_platdata *plat = dev_get_platdata(bus); ++ const void *blob = gd->fdt_blob; ++ int node = dev_of_offset(bus); ++ ++ plat->regs = (struct sunxi_spi_regs *)devfdt_get_addr(bus); ++ plat->activate_delay_us = fdtdec_get_int( ++ blob, node, "spi-activate_delay", 0); ++ plat->deactivate_delay_us = fdtdec_get_int( ++ blob, node, "spi-deactivate-delay", 0); ++ ++ debug("%s: regs=%p, activate-delay=%u, deactivate-delay=%u\n", ++ __func__, plat->regs, plat->activate_delay_us, ++ plat->deactivate_delay_us); ++ ++ return 0; ++} ++ ++static int sunxi_spi_probe(struct udevice *bus) ++{ ++ struct sunxi_spi_platdata *plat = dev_get_platdata(bus); ++ struct sunxi_spi_priv *priv = dev_get_priv(bus); ++ ++ debug("%s: probe\n", __func__); ++ ++ priv->regs = plat->regs; ++ priv->last_transaction_us = timer_get_us(); ++ ++ return 0; ++} ++ ++static int sunxi_spi_claim_bus(struct udevice *dev) ++{ ++ struct udevice *bus = dev->parent; ++ struct sunxi_spi_priv *priv = dev_get_priv(bus); ++ unsigned int pin_func = SUNXI_GPC_SPI0; ++ ++ debug("%s: claiming bus\n", __func__); ++ ++ if (IS_ENABLED(CONFIG_MACH_SUN50I)) ++ pin_func = SUN50I_GPC_SPI0; ++ ++ sunxi_spi_setup_pinmux(pin_func); ++ sunxi_spi_enable_clock(bus); ++ setbits_le32(&priv->regs->glb_ctl, SUNXI_SPI_CTL_MASTER | ++ SUNXI_SPI_CTL_ENABLE | SUNXI_SPI_CTL_TP | SUNXI_SPI_CTL_SRST); ++ ++ if (IS_ENABLED(CONFIG_SUNXI_GEN_SUN6I)) ++ while (readl(&priv->regs->glb_ctl) & SUNXI_SPI_CTL_SRST) ++ ; ++ ++ setbits_le32(&priv->regs->xfer_ctl, SUNXI_SPI_CTL_CS_MANUAL | ++ SUNXI_SPI_CTL_CS_LEVEL); ++ setbits_le32(&priv->regs->fifo_ctl, SUNXI_SPI_CTL_RF_RST | ++ SUNXI_SPI_CTL_TF_RST); ++ ++ return 0; ++} ++ ++static int sunxi_spi_release_bus(struct udevice *dev) ++{ ++ struct udevice *bus = dev->parent; ++ struct sunxi_spi_priv *priv = dev_get_priv(bus); ++ ++ debug("%s: releasing bus\n", __func__); ++ ++ clrbits_le32(&priv->regs->glb_ctl, SUNXI_SPI_CTL_MASTER | ++ SUNXI_SPI_CTL_ENABLE); ++ sunxi_spi_disable_clock(); ++ ++ return 0; ++} ++ ++static void sunxi_spi_write(struct udevice *dev, const char *tx_buf, ++ size_t nbytes) ++{ ++ struct udevice *bus = dev->parent; ++ struct sunxi_spi_priv *priv = dev_get_priv(bus); ++ size_t i; ++ char byte; ++ ++ if (!tx_buf) ++ nbytes = 0; ++ ++ writel(SUNXI_SPI_XMIT_CNT(nbytes), &priv->regs->xmit_cnt); ++ ++ if (IS_ENABLED(CONFIG_SUNXI_GEN_SUN6I)) ++ writel(SUNXI_SPI_BURST_CNT(nbytes), &priv->regs->burst_ctl); ++ ++ for (i = 0; i < nbytes; ++i) { ++ byte = tx_buf ? *tx_buf++ : 0; ++ writeb(byte, &priv->regs->tx_data); ++ } ++} ++ ++static int sunxi_spi_xfer(struct udevice *dev, unsigned int bitlen, ++ const void *dout, void *din, unsigned long flags) ++{ ++ struct udevice *bus = dev->parent; ++ struct sunxi_spi_priv *priv = dev_get_priv(bus); ++ struct dm_spi_slave_platdata *slave_plat = dev_get_parent_platdata(dev); ++ const char *tx_buf = dout; ++ char *rx_buf = din; ++ size_t len = bitlen / 8; ++ size_t i, nbytes; ++ char byte; ++ ++ if (bitlen % 8) { ++ debug("%s: non byte-aligned SPI transfer.\n", __func__); ++ return -1; ++ } ++ ++ if (flags & SPI_XFER_BEGIN) ++ sunxi_spi_cs_activate(dev, slave_plat->cs); ++ ++ while (len) { ++ nbytes = min(len, (size_t)64 - 1); ++ ++ writel(SUNXI_SPI_BURST_CNT(nbytes), &priv->regs->burst_cnt); ++ sunxi_spi_write(dev, tx_buf, nbytes); ++ setbits_le32(&priv->regs->xfer_ctl, SUNXI_SPI_CTL_XCH); ++ ++ while (((readl(&priv->regs->fifo_sta) & ++ SUNXI_SPI_FIFO_RF_CNT_MASK) >> ++ SUNXI_SPI_FIFO_RF_CNT_BITS) < nbytes) ++ ; ++ ++ for (i = 0; i < nbytes; ++i) { ++ byte = readb(&priv->regs->rx_data); ++ ++ if (rx_buf) ++ *rx_buf++ = byte; ++ } ++ ++ len -= nbytes; ++ } ++ ++ if (flags & SPI_XFER_END) ++ sunxi_spi_cs_deactivate(dev, slave_plat->cs); ++ ++ return 0; ++} ++ ++static int sunxi_spi_set_speed(struct udevice *bus, uint speed) ++{ ++ struct sunxi_spi_priv *priv = dev_get_priv(bus); ++ unsigned int div; ++ uint32_t reg; ++ ++ speed = min(speed, (unsigned int)SUNXI_SPI_MAX_RATE); ++ speed = max((unsigned int)SUNXI_SPI_MIN_RATE, speed); ++ ++ div = SUNXI_SPI_MAX_RATE / (2 * speed); ++ ++ if (div <= (SUNXI_SPI_CLK_CTL_CDR2_MASK + 1)) { ++ if (div > 0) ++ div--; ++ ++ reg = SUNXI_SPI_CLK_CTL_CDR2(div) | SUNXI_SPI_CLK_CTL_DRS; ++ } else { ++ div = __ilog2(SUNXI_SPI_MAX_RATE) - __ilog2(speed); ++ reg = SUNXI_SPI_CLK_CTL_CDR1(div); ++ } ++ ++ writel(reg, &priv->regs->clk_ctl); ++ ++ debug("%s: speed=%u\n", __func__, speed); ++ ++ return 0; ++} ++ ++static int sunxi_spi_set_mode(struct udevice *bus, uint mode) ++{ ++ struct sunxi_spi_priv *priv = dev_get_priv(bus); ++ uint32_t reg; ++ ++ reg = readl(&priv->regs->xfer_ctl); ++ reg &= ~(SUNXI_SPI_CTL_CPOL | SUNXI_SPI_CTL_CPHA | ++ SUNXI_SPI_CTL_CS_ACTIVE_LOW); ++ ++ if (mode & SPI_CPOL) ++ reg |= SUNXI_SPI_CTL_CPOL; ++ ++ if (mode & SPI_CPHA) ++ reg |= SUNXI_SPI_CTL_CPHA; ++ ++ if (!(mode & SPI_CS_HIGH)) ++ reg |= SUNXI_SPI_CTL_CS_ACTIVE_LOW; ++ ++ writel(reg, &priv->regs->xfer_ctl); ++ ++ debug("%s: mode=%d\n", __func__, mode); ++ ++ return 0; ++} ++ ++static const struct dm_spi_ops sunxi_spi_ops = { ++ .claim_bus = sunxi_spi_claim_bus, ++ .release_bus = sunxi_spi_release_bus, ++ .xfer = sunxi_spi_xfer, ++ .set_speed = sunxi_spi_set_speed, ++ .set_mode = sunxi_spi_set_mode, ++}; ++ ++static const struct udevice_id sunxi_spi_ids[] = { ++ { .compatible = "allwinner,sun4i-a10-spi" }, ++ { .compatible = "allwinner,sun6i-a31-spi" }, ++ { .compatible = "allwinner,sun8i-h3-spi" }, ++ { .compatible = "allwinner,sun50i-a64-spi" }, ++ { } ++}; ++ ++U_BOOT_DRIVER(sunxi_spi) = { ++ .name = "sunxi_spi", ++ .id = UCLASS_SPI, ++ .of_match = sunxi_spi_ids, ++ .ops = &sunxi_spi_ops, ++ .ofdata_to_platdata = sunxi_spi_ofdata_to_platdata, ++ .platdata_auto_alloc_size = sizeof(struct sunxi_spi_platdata), ++ .priv_auto_alloc_size = sizeof(struct sunxi_spi_priv), ++ .probe = sunxi_spi_probe, ++}; diff --git a/package/boot/uboot-sunxi/patches/405-introduce-and-use-sunxi_gpio_parse_pin_name.patch b/package/boot/uboot-sunxi/patches/405-introduce-and-use-sunxi_gpio_parse_pin_name.patch new file mode 100644 index 0000000000..2d179381e2 --- /dev/null +++ b/package/boot/uboot-sunxi/patches/405-introduce-and-use-sunxi_gpio_parse_pin_name.patch @@ -0,0 +1,59 @@ +From 051559e7cb1ad072277dfeafcebf91632582da1a Mon Sep 17 00:00:00 2001 +From: Andre Przywara +Date: Sun, 12 Feb 2017 14:53:15 +0000 +Subject: introduce and use sunxi_gpio_parse_pin_name() + +--- + arch/arm/include/asm/arch-sunxi/gpio.h | 2 ++ + arch/arm/mach-sunxi/pinmux.c | 16 ++++++++++++++++ + drivers/net/sun8i_emac.c | 7 ++----- + 3 files changed, 20 insertions(+), 5 deletions(-) + +--- a/arch/arm/include/asm/arch-sunxi/gpio.h ++++ b/arch/arm/include/asm/arch-sunxi/gpio.h +@@ -241,4 +241,6 @@ int axp_gpio_init(void); + static inline int axp_gpio_init(void) { return 0; } + #endif + ++int sunxi_gpio_parse_pin_name(const char *pin_name); ++ + #endif /* _SUNXI_GPIO_H */ +--- a/arch/arm/mach-sunxi/pinmux.c ++++ b/arch/arm/mach-sunxi/pinmux.c +@@ -69,3 +69,19 @@ int sunxi_gpio_set_pull(u32 pin, u32 val + + return 0; + } ++ ++int sunxi_gpio_parse_pin_name(const char *pin_name) ++{ ++ int pin; ++ ++ if (pin_name[0] != 'P') ++ return -1; ++ ++ if (pin_name[1] < 'A' || pin_name[1] > 'Z') ++ return -1; ++ ++ pin = (pin_name[1] - 'A') << 5; ++ pin += simple_strtol(&pin_name[2], NULL, 10); ++ ++ return pin; ++} +--- a/drivers/net/sun8i_emac.c ++++ b/drivers/net/sun8i_emac.c +@@ -475,12 +475,9 @@ static int parse_phy_pins(struct udevice + "allwinner,pins", i, NULL); + if (!pin_name) + break; +- if (pin_name[0] != 'P') ++ pin = sunxi_gpio_parse_pin_name(pin_name); ++ if (pin < 0) + continue; +- pin = (pin_name[1] - 'A') << 5; +- if (pin >= 26 << 5) +- continue; +- pin += simple_strtol(&pin_name[2], NULL, 10); + + sunxi_gpio_set_cfgpin(pin, SUN8I_GPD8_GMAC); + sunxi_gpio_set_drv(pin, drive); diff --git a/package/boot/uboot-sunxi/patches/406-introduce-and-use-sunxi_gpio_setup_dt_pins.patch b/package/boot/uboot-sunxi/patches/406-introduce-and-use-sunxi_gpio_setup_dt_pins.patch new file mode 100644 index 0000000000..1d24787eaa --- /dev/null +++ b/package/boot/uboot-sunxi/patches/406-introduce-and-use-sunxi_gpio_setup_dt_pins.patch @@ -0,0 +1,94 @@ +From fa5767ca356bcdfdb1bfa055851579a858a5ed25 Mon Sep 17 00:00:00 2001 +From: Andre Przywara +Date: Sun, 12 Feb 2017 14:53:16 +0000 +Subject: introduce and use sunxi_gpio_setup_dt_pins() + +--- + arch/arm/include/asm/arch-sunxi/gpio.h | 2 ++ + arch/arm/mach-sunxi/pinmux.c | 61 ++++++++++++++++++++++++++++++++++ + 2 files changed, 63 insertions(+) + +--- a/arch/arm/include/asm/arch-sunxi/gpio.h ++++ b/arch/arm/include/asm/arch-sunxi/gpio.h +@@ -242,5 +242,7 @@ static inline int axp_gpio_init(void) { + #endif + + int sunxi_gpio_parse_pin_name(const char *pin_name); ++int sunxi_gpio_setup_dt_pins(const void * volatile fdt_blob, int node, ++ const char * mux_name, int mux_sel); + + #endif /* _SUNXI_GPIO_H */ +--- a/arch/arm/mach-sunxi/pinmux.c ++++ b/arch/arm/mach-sunxi/pinmux.c +@@ -9,6 +9,9 @@ + #include + #include + #include ++#include ++#include ++#include + + void sunxi_gpio_set_cfgbank(struct sunxi_gpio *pio, int bank_offset, u32 val) + { +@@ -85,3 +88,61 @@ int sunxi_gpio_parse_pin_name(const char + + return pin; + } ++ ++int sunxi_gpio_setup_dt_pins(const void * volatile fdt_blob, int node, ++ const char * mux_name, int mux_sel) ++{ ++ int drive, pull, pin, i; ++ const char *pin_name; ++ int offset; ++ ++ offset = fdtdec_lookup_phandle(fdt_blob, node, "pinctrl-0"); ++ if (offset < 0) ++ return offset; ++ ++ drive = fdt_getprop_u32_default_node(fdt_blob, offset, 0, ++ "drive-strength", 0); ++ if (drive) { ++ if (drive <= 10) ++ drive = SUN4I_PINCTRL_10_MA; ++ else if (drive <= 20) ++ drive = SUN4I_PINCTRL_20_MA; ++ else if (drive <= 30) ++ drive = SUN4I_PINCTRL_30_MA; ++ else ++ drive = SUN4I_PINCTRL_40_MA; ++ } else { ++ drive = fdt_getprop_u32_default_node(fdt_blob, offset, 0, ++ "allwinner,drive", 4); ++ } ++ ++ if (fdt_get_property(fdt_blob, offset, "bias-pull-up", NULL)) ++ pull = SUN4I_PINCTRL_PULL_UP; ++ else if (fdt_get_property(fdt_blob, offset, "bias-disable", NULL)) ++ pull = SUN4I_PINCTRL_NO_PULL; ++ else if (fdt_get_property(fdt_blob, offset, "bias-pull-down", NULL)) ++ pull = SUN4I_PINCTRL_PULL_DOWN; ++ else ++ pull = fdt_getprop_u32_default_node(fdt_blob, offset, 0, ++ "allwinner,pull", 0); ++ ++ for (i = 0; ; i++) { ++ pin_name = fdt_stringlist_get(fdt_blob, offset, ++ "allwinner,pins", i, NULL); ++ if (!pin_name) { ++ pin_name = fdt_stringlist_get(fdt_blob, offset, ++ "pins", i, NULL); ++ if (!pin_name) ++ break; ++ } ++ pin = sunxi_gpio_parse_pin_name(pin_name); ++ if (pin < 0) ++ continue; ++ ++ sunxi_gpio_set_cfgpin(pin, mux_sel); ++ sunxi_gpio_set_drv(pin, drive); ++ sunxi_gpio_set_pull(pin, pull); ++ } ++ ++ return i; ++} diff --git a/package/boot/uboot-sunxi/patches/407-sunxi-spi-set-up-GPIO-pins-using-pinctrl.patch b/package/boot/uboot-sunxi/patches/407-sunxi-spi-set-up-GPIO-pins-using-pinctrl.patch new file mode 100644 index 0000000000..dad857454d --- /dev/null +++ b/package/boot/uboot-sunxi/patches/407-sunxi-spi-set-up-GPIO-pins-using-pinctrl.patch @@ -0,0 +1,60 @@ +From 0c87fe5938e5c7c089b84962a7c7ee3505910ffc Mon Sep 17 00:00:00 2001 +From: "S.J.R. van Schaik" +Date: Thu, 23 Feb 2017 12:11:42 +0000 +Subject: sunxi: spi: set up GPIO pins using pinctrl + +--- + drivers/spi/sunxi_spi.c | 31 +++++++++++++++++++------------ + 1 file changed, 19 insertions(+), 12 deletions(-) + +--- a/drivers/spi/sunxi_spi.c ++++ b/drivers/spi/sunxi_spi.c +@@ -36,18 +36,28 @@ struct sunxi_spi_priv { + + DECLARE_GLOBAL_DATA_PTR; + +-static void sunxi_spi_setup_pinmux(unsigned int pin_func) ++static int sunxi_spi_parse_pins(struct udevice *bus) + { +- unsigned int pin; ++ unsigned int pin_func = SUNXI_GPC_SPI0; ++ int ret; ++ ++ if (IS_ENABLED(CONFIG_MACH_SUN50I)) ++ pin_func = SUN50I_GPC_SPI0; ++ ++ ret = sunxi_gpio_setup_dt_pins(gd->fdt_blob, dev_of_offset(bus), NULL, ++ pin_func); + +- for (pin = SUNXI_GPC(0); pin <= SUNXI_GPC(2); pin++) +- sunxi_gpio_set_cfgpin(pin, pin_func); ++ if (ret < 0) { ++ printf("WARNING: sunxi-spi: cannot find pinctrl-0 node\n"); ++ return ret; ++ } + +- if (IS_ENABLED(CONFIG_MACH_SUN4I) || IS_ENABLED(CONFIG_MACH_SUN7I)) { +- sunxi_gpio_set_cfgpin(SUNXI_GPC(23), pin_func); +- } else { +- sunxi_gpio_set_cfgpin(SUNXI_GPC(3), pin_func); ++ if (!ret) { ++ printf("WARNING: sunxi-spi: cannot find pins property\n"); ++ return -2; + } ++ ++ return ret; + } + + static void sunxi_spi_enable_clock(struct udevice *bus) +@@ -170,10 +180,7 @@ static int sunxi_spi_claim_bus(struct ud + + debug("%s: claiming bus\n", __func__); + +- if (IS_ENABLED(CONFIG_MACH_SUN50I)) +- pin_func = SUN50I_GPC_SPI0; +- +- sunxi_spi_setup_pinmux(pin_func); ++ sunxi_spi_parse_pins(bus); + sunxi_spi_enable_clock(bus); + setbits_le32(&priv->regs->glb_ctl, SUNXI_SPI_CTL_MASTER | + SUNXI_SPI_CTL_ENABLE | SUNXI_SPI_CTL_TP | SUNXI_SPI_CTL_SRST); diff --git a/package/boot/uboot-sunxi/patches/408-sunxi-dts-enable-SPI0-controller-for-A20-OLinuXino-L.patch b/package/boot/uboot-sunxi/patches/408-sunxi-dts-enable-SPI0-controller-for-A20-OLinuXino-L.patch new file mode 100644 index 0000000000..a375b06275 --- /dev/null +++ b/package/boot/uboot-sunxi/patches/408-sunxi-dts-enable-SPI0-controller-for-A20-OLinuXino-L.patch @@ -0,0 +1,39 @@ +From 835dd2f28d3f5c88d226622fef283e6ca48f8818 Mon Sep 17 00:00:00 2001 +From: "S.J.R. van Schaik" +Date: Thu, 9 Feb 2017 21:42:16 +0000 +Subject: sunxi: dts: enable SPI0 controller for A20 OLinuXino LIME 2 + +--- + arch/arm/dts/sun7i-a20-olinuxino-lime2.dts | 14 ++++++++++++++ + 1 file changed, 14 insertions(+) + +--- a/arch/arm/dts/sun7i-a20-olinuxino-lime2.dts ++++ b/arch/arm/dts/sun7i-a20-olinuxino-lime2.dts +@@ -54,6 +54,7 @@ + + aliases { + serial0 = &uart0; ++ spi0 = &spi0; + }; + + chosen { +@@ -81,6 +82,19 @@ + }; + }; + ++&pio { ++ spi0_pins: pinctrl { ++ pins = "PC0", "PC1", "PC2", "PC23"; ++ drive-strength = <10>; ++ bias-disable; ++ }; ++}; ++ ++&spi0 { ++ pinctrl-0 = <&spi0_pins>; ++ status = "okay"; ++}; ++ + &ahci { + target-supply = <®_ahci_5v>; + status = "okay"; diff --git a/package/boot/uboot-sunxi/patches/409-sunxi-dts-enable-SPI0-controller-for-Orange-Pi-Zero.patch b/package/boot/uboot-sunxi/patches/409-sunxi-dts-enable-SPI0-controller-for-Orange-Pi-Zero.patch new file mode 100644 index 0000000000..ebe9e93f53 --- /dev/null +++ b/package/boot/uboot-sunxi/patches/409-sunxi-dts-enable-SPI0-controller-for-Orange-Pi-Zero.patch @@ -0,0 +1,57 @@ +From eb2fee739650a8fe5534d6b38d84713817f83c6d Mon Sep 17 00:00:00 2001 +From: "S.J.R. van Schaik" +Date: Thu, 23 Feb 2017 11:49:43 +0000 +Subject: sunxi: dts: enable SPI0 controller for Orange Pi Zero + +--- + arch/arm/dts/sun8i-h2-plus-orangepi-zero.dts | 14 ++++++++++++++ + arch/arm/dts/sun8i-h3.dtsi | 8 ++++++++ + 2 files changed, 22 insertions(+) + +--- a/arch/arm/dts/sun8i-h2-plus-orangepi-zero.dts ++++ b/arch/arm/dts/sun8i-h2-plus-orangepi-zero.dts +@@ -59,6 +59,7 @@ + serial0 = &uart0; + /* ethernet0 is the H3 emac, defined in sun8i-h3.dtsi */ + ethernet1 = &xr819; ++ spi0 = &spi0; + }; + + chosen { +@@ -95,6 +96,19 @@ + }; + }; + ++&pio { ++ spi0_pins: pinctrl { ++ pins = "PC0", "PC1", "PC2", "PC3"; ++ drive-strength = <10>; ++ bias-disable; ++ }; ++}; ++ ++&spi0 { ++ pinctrl-0 = <&spi0_pins>; ++ status = "okay"; ++}; ++ + &ehci1 { + status = "okay"; + }; +--- a/arch/arm/dts/sun8i-h3.dtsi ++++ b/arch/arm/dts/sun8i-h3.dtsi +@@ -158,6 +158,14 @@ + #dma-cells = <1>; + }; + ++ spi0: spi@01c68000 { ++ compatible = "allwinner,sun8i-h3-spi"; ++ reg = <0x01c68000 0x1000>; ++ status = "disabled"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ }; ++ + mmc0: mmc@01c0f000 { + compatible = "allwinner,sun7i-a20-mmc", + "allwinner,sun5i-a13-mmc"; diff --git a/package/boot/uboot-sunxi/patches/410-sunxi-dts-enable-SPI0-controller-for-Pine64.patch b/package/boot/uboot-sunxi/patches/410-sunxi-dts-enable-SPI0-controller-for-Pine64.patch new file mode 100644 index 0000000000..10b38f509c --- /dev/null +++ b/package/boot/uboot-sunxi/patches/410-sunxi-dts-enable-SPI0-controller-for-Pine64.patch @@ -0,0 +1,56 @@ +From 04bfe04a88b8c491e6567d9f779b4d62932b13ad Mon Sep 17 00:00:00 2001 +From: "S.J.R. van Schaik" +Date: Thu, 23 Feb 2017 11:50:04 +0000 +Subject: sunxi: dts: enable SPI0 controller for Pine64+ + +--- + arch/arm/dts/sun50i-a64-orangepi-win.dts | 14 ++++++++++++++ + arch/arm/dts/sun50i-a64.dtsi | 8 ++++++++ + 2 files changed, 22 insertions(+) + +--- a/arch/arm/dts/sun50i-a64-orangepi-win.dts ++++ b/arch/arm/dts/sun50i-a64-orangepi-win.dts +@@ -52,6 +52,7 @@ + + aliases { + serial0 = &uart0; ++ spi0 = &spi0; + }; + + chosen { +@@ -70,6 +71,19 @@ + status = "okay"; + }; + ++&pio { ++ spi0_pins: pinctrl { ++ pins = "PC0", "PC1", "PC2", "PC3"; ++ drive-strength = <10>; ++ bias-disabled; ++ }; ++}; ++ ++&spi0 { ++ pinctrl-0 = <&spi0_pins>; ++ status = "okay"; ++}; ++ + &mmc0 { + pinctrl-names = "default"; + pinctrl-0 = <&mmc0_pins>; +--- a/arch/arm/dts/sun50i-a64.dtsi ++++ b/arch/arm/dts/sun50i-a64.dtsi +@@ -423,5 +423,13 @@ + interrupt-controller; + #interrupt-cells = <3>; + }; ++ ++ spi0: spi@01c68000 { ++ compatible = "allwinner,sun50i-a64-spi"; ++ reg = <0x01c68000 0x1000>; ++ status = "disabled"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ }; + }; + }; diff --git a/package/boot/uboot-sunxi/patches/414-sunxi-set-bootcmd-when-spi-boot-is-activated.patch b/package/boot/uboot-sunxi/patches/414-sunxi-set-bootcmd-when-spi-boot-is-activated.patch new file mode 100644 index 0000000000..ccc2f4533f --- /dev/null +++ b/package/boot/uboot-sunxi/patches/414-sunxi-set-bootcmd-when-spi-boot-is-activated.patch @@ -0,0 +1,27 @@ +From 9e101257c1bc1243495559b255ebdd33929f4fa3 Mon Sep 17 00:00:00 2001 +From: Hauke Mehrtens +Date: Sun, 14 Jan 2018 18:58:47 +0100 +Subject: sunxi: set bootcmd when spi boot is activated + +--- + include/configs/sunxi-common.h | 9 +++++++++ + 1 file changed, 9 insertions(+) + +--- a/include/configs/sunxi-common.h ++++ b/include/configs/sunxi-common.h +@@ -469,6 +469,15 @@ extern int soft_i2c_gpio_scl; + #define BOOTCMD_SUNXI_COMPAT + #endif + ++#if CONFIG_SPI_BOOT ++/* u-boot env in serial flash, by default is bus 0 and cs 0 */ ++#define CONFIG_ENV_SECT_SIZE 0x010000 ++#define CONFIG_BOOTCOMMAND "sf probe 0; " \ ++ "sf read ${fdt_addr_r} 0x90000 0x10000; " \ ++ "sf read ${kernel_addr_r} 0xa0000 0x400000; " \ ++ "bootm ${kernel_addr_r} - ${fdt_addr_r}" ++#endif ++ + #include + + #ifdef CONFIG_USB_KEYBOARD -- 2.30.2