Selaa lähdekoodia

Merge tag 'xilinx-for-v2021.04' of https://gitlab.denx.de/u-boot/custodians/u-boot-microblaze into next

Xilinx changes for v2021.04

arm64:
- DT updates

microblaze:
- Add support for NOR device support

spi:
- Fix unaligned data write issue

nand:
- Minor code change

xilinx:
- Fru fix in limit calculation
- Fill git repo link for all Xilinx boards

video:
- Add support for seps525 spi display

tools:
- Minor Vitis file support

cmd/common
- Minor code indentation fixes

serial:
- Uartlite debug uart initialization fix
Tom Rini 3 vuotta sitten
vanhempi
commit
bc0b99bd8b

+ 2 - 0
MAINTAINERS

@@ -548,6 +548,7 @@ S:	Maintained
 T:	git https://gitlab.denx.de/u-boot/custodians/u-boot-microblaze.git
 F:	arch/arm/mach-zynq/
 F:	doc/board/xilinx/
+F:	doc/device-tree-bindings/video/syncoam,seps525.txt
 F:	drivers/clk/clk_zynq.c
 F:	drivers/fpga/zynqpl.c
 F:	drivers/gpio/zynq_gpio.c
@@ -589,6 +590,7 @@ F:	drivers/spi/zynq_qspi.c
 F:	drivers/spi/zynq_spi.c
 F:	drivers/timer/cadence-ttc.c
 F:	drivers/usb/host/ehci-zynq.c
+F:	drivers/video/seps525.c
 F:	drivers/watchdog/cdns_wdt.c
 F:	include/zynqmppl.h
 F:	include/zynqmp_firmware.h

+ 24 - 0
arch/arm/dts/zynqmp-zcu1275-revB.dts

@@ -23,6 +23,7 @@
 		serial1 = &dcc;
 		spi0 = &qspi;
 		mmc0 = &sdhci1;
+		ethernet0 = &gem1;
 	};
 
 	chosen {
@@ -40,6 +41,29 @@
 	status = "okay";
 };
 
+&gem1 {
+	status = "okay";
+	mdio {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		phy1: ethernet-phy@1 {
+			reg = <1>; /* KSZ9031RNXIC on AES-FMC-NETW1-G */
+			rxc-skew-ps = <1800>; /* Skew control of RX_CLK pad output */
+			txc-skew-ps = <1800>; /* Skew control of GTX_CLK pad input */
+			txen-skew-ps = <900>; /* Skew control of TX_CTL pad input */
+			rxdv-skew-ps = <0>; /* Skew control of RX_CTL pad output */
+			rxd0-skew-ps = <0>; /* Skew control of RXD0 pad output */
+			rxd1-skew-ps = <0>; /* Skew control of RXD1 pad output */
+			rxd2-skew-ps = <0>; /* Skew control of RXD2 pad output */
+			rxd3-skew-ps = <0>; /* Skew control of RXD3 pad output */
+			txd0-skew-ps = <900>; /* Skew control of TXD0 pad input */
+			txd1-skew-ps = <900>; /* Skew control of TXD1 pad input */
+			txd2-skew-ps = <900>; /* Skew control of TXD2 pad input */
+			txd3-skew-ps = <900>; /* Skew control of TXD3 pad input */
+		};
+	};
+};
+
 &qspi {
 	status = "okay";
 	flash@0 {

+ 23 - 0
arch/arm/dts/zynqmp-zcu1285-revA.dts

@@ -23,6 +23,7 @@
 		serial1 = &dcc;
 		spi0 = &qspi;
 		mmc0 = &sdhci1;
+		ethernet0 = &gem1; /* EMIO */
 		i2c = &i2c0; /* EMIO */
 	};
 
@@ -222,6 +223,28 @@
 	};
 };
 
+&gem1 {
+	mdio {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		phy1: ethernet-phy@1 {
+			reg = <1>; /* KSZ9031RNXIC on AES-FMC-NETW1-G */
+			rxc-skew-ps = <1800>; /* Skew control of RX_CLK pad output */
+			txc-skew-ps = <1800>; /* Skew control of GTX_CLK pad input */
+			txen-skew-ps = <900>; /* Skew control of TX_CTL pad input */
+			rxdv-skew-ps = <0>; /* Skew control of RX_CTL pad output */
+			rxd0-skew-ps = <0>; /* Skew control of RXD0 pad output */
+			rxd1-skew-ps = <0>; /* Skew control of RXD1 pad output */
+			rxd2-skew-ps = <0>; /* Skew control of RXD2 pad output */
+			rxd3-skew-ps = <0>; /* Skew control of RXD3 pad output */
+			txd0-skew-ps = <900>; /* Skew control of TXD0 pad input */
+			txd1-skew-ps = <900>; /* Skew control of TXD1 pad input */
+			txd2-skew-ps = <900>; /* Skew control of TXD2 pad input */
+			txd3-skew-ps = <900>; /* Skew control of TXD3 pad input */
+		};
+	};
+};
+
 &qspi {
 	status = "okay";
 	flash@0 {

+ 28 - 33
arch/arm/dts/zynqmp.dtsi

@@ -115,8 +115,10 @@
 			      <0x0 0xff9905e0 0x0 0x20>,
 			      <0x0 0xff990e80 0x0 0x20>,
 			      <0x0 0xff990ea0 0x0 0x20>;
-			reg-names = "local_request_region", "local_response_region",
-				    "remote_request_region", "remote_response_region";
+			reg-names = "local_request_region",
+				    "local_response_region",
+				    "remote_request_region",
+				    "remote_response_region";
 			#mbox-cells = <1>;
 			xlnx,ipi-id = <4>;
 		};
@@ -145,15 +147,10 @@
 	firmware {
 		zynqmp_firmware: zynqmp-firmware {
 			compatible = "xlnx,zynqmp-firmware";
+			#power-domain-cells = <1>;
 			method = "smc";
-			#power-domain-cells = <0x1>;
 			u-boot,dm-pre-reloc;
 
-			zynqmp_pcap: pcap {
-				compatible = "xlnx,zynqmp-pcap-fpga";
-				clock-names = "ref_clk";
-			};
-
 			zynqmp_power: zynqmp-power {
 				u-boot,dm-pre-reloc;
 				compatible = "xlnx,zynqmp-power";
@@ -163,6 +160,11 @@
 				mbox-names = "tx", "rx";
 			};
 
+			zynqmp_pcap: pcap {
+				compatible = "xlnx,zynqmp-pcap-fpga";
+				clock-names = "ref_clk";
+			};
+
 			zynqmp_reset: reset-controller {
 				compatible = "xlnx,zynqmp-reset";
 				#reset-cells = <1>;
@@ -206,26 +208,7 @@
 		};
 	};
 
-	amba_apu: amba-apu@0 {
-		compatible = "simple-bus";
-		#address-cells = <2>;
-		#size-cells = <1>;
-		ranges = <0 0 0 0 0xffffffff>;
-
-		gic: interrupt-controller@f9010000 {
-			compatible = "arm,gic-400";
-			#interrupt-cells = <3>;
-			reg = <0x0 0xf9010000 0x10000>,
-			      <0x0 0xf9020000 0x20000>,
-			      <0x0 0xf9040000 0x20000>,
-			      <0x0 0xf9060000 0x20000>;
-			interrupt-controller;
-			interrupt-parent = <&gic>;
-			interrupts = <1 9 0xf04>;
-		};
-	};
-
-	amba: amba {
+	amba: axi {
 		compatible = "simple-bus";
 		u-boot,dm-pre-reloc;
 		#address-cells = <2>;
@@ -380,6 +363,18 @@
 			power-domains = <&zynqmp_firmware PD_GDMA>;
 		};
 
+		gic: interrupt-controller@f9010000 {
+			compatible = "arm,gic-400";
+			#interrupt-cells = <3>;
+			reg = <0x0 0xf9010000 0x0 0x10000>,
+			      <0x0 0xf9020000 0x0 0x20000>,
+			      <0x0 0xf9040000 0x0 0x20000>,
+			      <0x0 0xf9060000 0x0 0x20000>;
+			interrupt-controller;
+			interrupt-parent = <&gic>;
+			interrupts = <1 9 0xf04>;
+		};
+
 		gpu: gpu@fd4b0000 {
 			status = "disabled";
 			compatible = "arm,mali-400", "arm,mali-utgard";
@@ -590,7 +585,7 @@
 		};
 
 		i2c0: i2c@ff020000 {
-			compatible = "cdns,i2c-r1p14", "cdns,i2c-r1p10";
+			compatible = "cdns,i2c-r1p14";
 			status = "disabled";
 			interrupt-parent = <&gic>;
 			interrupts = <0 17 4>;
@@ -601,7 +596,7 @@
 		};
 
 		i2c1: i2c@ff030000 {
-			compatible = "cdns,i2c-r1p14", "cdns,i2c-r1p10";
+			compatible = "cdns,i2c-r1p14";
 			status = "disabled";
 			interrupt-parent = <&gic>;
 			interrupts = <0 18 4>;
@@ -639,8 +634,8 @@
 			      <0x0 0xfd480000 0x0 0x1000>,
 			      <0x80 0x00000000 0x0 0x1000000>;
 			reg-names = "breg", "pcireg", "cfg";
-			ranges = <0x02000000 0x00000000 0xe0000000 0x00000000 0xe0000000 0x00000000 0x10000000	/* non-prefetchable memory */
-				  0x43000000 0x00000006 0x00000000 0x00000006 0x00000000 0x00000002 0x00000000>;/* prefetchable memory */
+			ranges = <0x02000000 0x00000000 0xe0000000 0x00000000 0xe0000000 0x00000000 0x10000000>,/* non-prefetchable memory */
+				 <0x43000000 0x00000006 0x00000000 0x00000006 0x00000000 0x00000002 0x00000000>;/* prefetchable memory */
 			bus-range = <0x00 0xff>;
 			interrupt-map-mask = <0x0 0x0 0x0 0x7>;
 			interrupt-map = <0x0 0x0 0x0 0x1 &pcie_intc 0x1>,
@@ -770,7 +765,7 @@
 			clock-output-names = "clk_out_sd1", "clk_in_sd1";
 		};
 
-		smmu: smmu@fd800000 {
+		smmu: iommu@fd800000 {
 			compatible = "arm,mmu-500";
 			reg = <0x0 0xfd800000 0x0 0x20000>;
 			#iommu-cells = <1>;

+ 1 - 1
board/xilinx/common/fru_ops.c

@@ -170,7 +170,7 @@ static int fru_parse_board(unsigned long addr)
 	data = (u8 *)&fru_data.brd.manufacturer_type_len;
 
 	/* Record max structure limit not to write data over allocated space */
-	limit = data + sizeof(struct fru_board_data);
+	limit = (u8 *)&fru_data.brd + sizeof(struct fru_board_data);
 
 	for (i = 0; ; i++, data += FRU_BOARD_MAX_LEN) {
 		len = fru_check_type_len(*(u8 *)addr, fru_data.brd.lang_code,

+ 1 - 0
board/xilinx/microblaze-generic/MAINTAINERS

@@ -1,6 +1,7 @@
 MICROBLAZE-GENERIC BOARD
 M:	Michal Simek <monstr@monstr.eu>
 S:	Maintained
+T:	git https://gitlab.denx.de/u-boot/custodians/u-boot-microblaze.git
 F:	board/xilinx/microblaze-generic/
 F:	include/configs/microblaze-generic.h
 F:	configs/microblaze-generic_defconfig

+ 4 - 1
board/xilinx/microblaze-generic/microblaze-generic.c

@@ -67,7 +67,10 @@ int board_late_init(void)
 
 	status |= env_set_hex("ramdisk_addr_r",
 			       gd->ram_base + SZ_32M + SZ_4M + SZ_2M);
-
+	if (IS_ENABLED(CONFIG_MTD_NOR_FLASH))
+		status |= env_set_hex("script_offset_nor",
+				       gd->bd->bi_flashstart +
+				       CONFIG_BOOT_SCRIPT_OFFSET);
 	if (status)
 		printf("%s: Saving run time variables FAILED\n", __func__);
 

+ 1 - 0
board/xilinx/versal/MAINTAINERS

@@ -1,6 +1,7 @@
 XILINX_VERSAL BOARDS
 M:	Michal Simek <michal.simek@xilinx.com>
 S:	Maintained
+T:	git https://gitlab.denx.de/u-boot/custodians/u-boot-microblaze.git
 F:	arch/arm/dts/versal*
 F:	board/xilinx/versal/
 F:	include/configs/xilinx_versal*

+ 1 - 0
board/xilinx/zynq/MAINTAINERS

@@ -1,6 +1,7 @@
 ZYNQ BOARD
 M:	Michal Simek <monstr@monstr.eu>
 S:	Maintained
+T:	git https://gitlab.denx.de/u-boot/custodians/u-boot-microblaze.git
 F:	arch/arm/dts/zynq-*
 F:	board/xilinx/zynq/
 F:	include/configs/zynq*.h

+ 1 - 0
board/xilinx/zynqmp/MAINTAINERS

@@ -1,6 +1,7 @@
 XILINX_ZYNQMP BOARDS
 M:	Michal Simek <michal.simek@xilinx.com>
 S:	Maintained
+T:	git https://gitlab.denx.de/u-boot/custodians/u-boot-microblaze.git
 F:	arch/arm/dts/zynqmp-*
 F:	arch/arm/dts/avnet-ultra96*
 F:	board/xilinx/common/

+ 4 - 5
cmd/load.c

@@ -228,12 +228,11 @@ static int read_record(char *buf, ulong len)
 			*p = c;
 		}
 
-	    /* Check for the console hangup (if any different from serial) */
-	    if (gd->jt->getc != getchar) {
-		if (ctrlc()) {
-		    return (-1);
+		/* Check for the console hangup (if any different from serial) */
+		if (gd->jt->getc != getchar) {
+			if (ctrlc())
+				return (-1);
 		}
-	    }
 	}
 
 	/* line too long - truncate */

+ 2 - 2
common/usb_storage.c

@@ -431,8 +431,8 @@ static int us_one_transfer(struct us_data *us, int pipe, char *buf, int length)
 					return 0;
 				}
 				/* if our try counter reaches 0, bail out */
-					debug(" %ld, data %d\n",
-					      us->pusb_dev->status, partial);
+				debug(" %ld, data %d\n",
+				      us->pusb_dev->status, partial);
 				if (!maxtry--)
 						return result;
 			}

+ 24 - 0
doc/device-tree-bindings/video/syncoam,seps525.txt

@@ -0,0 +1,24 @@
+spi based seps525 framebuffer display driver
+
+Driver for seps525 display controller (in spi mode), This binding supports selection
+of spi chipselect, spi max frequency, gpio to drive dc and reset pin of seps525
+controller and spi transaction bit length.
+
+Required properties:
+- compatible: "syncoam,seps525"
+- reg: Specifies the chip-select the seps525 is connected to on the spi bus
+- reset-gpios: gpio connected to reset pin of seps525 controller.
+- dc-gpios: gpio connected to dc pin of seps525 controller:
+- buswidth: bitlength of each spi transaction
+
+Example:
+	displayspi@0 {
+		compatible = "syncoam,seps525";
+		reg = <0>;
+		spi-max-frequency = <10000000>;
+		spi-cpol;
+		spi-cpha;
+		buswidth = <8>;
+		reset-gpios = <&gpio 0x1c GPIO_ACTIVE_LOW>;
+		dc-gpios = <&gpio 0x1b GPIO_ACTIVE_HIGH>;
+	};

+ 4 - 6
drivers/mtd/nand/raw/zynq_nand.c

@@ -1206,12 +1206,10 @@ static int zynq_nand_probe(struct udevice *dev)
 		nand_chip->options |= NAND_SUBPAGE_READ;
 
 		/* On-Die ECC spare bytes offset 8 is used for ECC codes */
-		if (ondie_ecc_enabled) {
-			nand_chip->ecc.layout = &ondie_nand_oob_64;
-			/* Use the BBT pattern descriptors */
-			nand_chip->bbt_td = &bbt_main_descr;
-			nand_chip->bbt_md = &bbt_mirror_descr;
-		}
+		nand_chip->ecc.layout = &ondie_nand_oob_64;
+		/* Use the BBT pattern descriptors */
+		nand_chip->bbt_td = &bbt_main_descr;
+		nand_chip->bbt_md = &bbt_mirror_descr;
 	} else {
 		/* Hardware ECC generates 3 bytes ECC code for each 512 bytes */
 		nand_chip->ecc.mode = NAND_ECC_HW;

+ 1 - 1
drivers/serial/serial_xuartlite.c

@@ -148,7 +148,7 @@ static inline void _debug_uart_init(void)
 
 	uart_out32(&regs->control, 0);
 	uart_out32(&regs->control, ULITE_CONTROL_RST_RX | ULITE_CONTROL_RST_TX);
-	uart_in32(&regs->status);
+	ret = uart_in32(&regs->status);
 	/* Endianness detection */
 	if ((ret & SR_TX_FIFO_EMPTY) != SR_TX_FIFO_EMPTY) {
 		little_endian = true;

+ 2 - 4
drivers/spi/zynqmp_gqspi.c

@@ -429,10 +429,8 @@ static int zynqmp_qspi_fill_tx_fifo(struct zynqmp_qspi_priv *priv, u32 size)
 				data |= GENMASK(31, 16);
 				break;
 			case 3:
-				data = *((u16 *)buf);
-				buf += 2;
-				data |= (*((u8 *)buf) << 16);
-				buf += 1;
+				data = *buf;
+				buf += 3;
 				data |= GENMASK(31, 24);
 				break;
 			}

+ 7 - 0
drivers/video/Kconfig

@@ -652,6 +652,13 @@ config VIDEO_NX
 	   HDMI. This option enables this support which can be used on devices
 	   which have an eDP display connected.
 
+config VIDEO_SEPS525
+	bool "Enable video support for Seps525"
+	depends on DM_VIDEO
+	help
+	  Enable support for the Syncoam PM-OLED display driver (RGB 160x128).
+	  Currently driver is supporting only SPI interface.
+
 source "drivers/video/nexell/Kconfig"
 
 config VIDEO

+ 1 - 0
drivers/video/Makefile

@@ -70,6 +70,7 @@ obj-$(CONFIG_VIDEO_SIMPLE) += simplefb.o
 obj-$(CONFIG_VIDEO_TEGRA20) += tegra.o
 obj-$(CONFIG_VIDEO_VCXK) += bus_vcxk.o
 obj-$(CONFIG_VIDEO_VESA) += vesa.o
+obj-$(CONFIG_VIDEO_SEPS525) += seps525.o
 
 obj-y += bridge/
 obj-y += sunxi/

+ 327 - 0
drivers/video/seps525.c

@@ -0,0 +1,327 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * FB driver for the WiseChip Semiconductor Inc. (UG-6028GDEBF02) display
+ * using the SEPS525 (Syncoam) LCD Controller
+ *
+ * Copyright (C) 2020 Xilinx Inc.
+ */
+
+#include <common.h>
+#include <command.h>
+#include <cpu_func.h>
+#include <dm.h>
+#include <errno.h>
+#include <spi.h>
+#include <video.h>
+#include <asm/gpio.h>
+#include <dm/device_compat.h>
+#include <linux/delay.h>
+
+#define WIDTH		160
+#define HEIGHT		128
+
+#define SEPS525_INDEX			0x00
+#define SEPS525_STATUS_RD		0x01
+#define SEPS525_OSC_CTL			0x02
+#define SEPS525_IREF			0x80
+#define SEPS525_CLOCK_DIV		0x03
+#define SEPS525_REDUCE_CURRENT		0x04
+#define SEPS525_SOFT_RST		0x05
+#define SEPS525_DISP_ONOFF		0x06
+#define SEPS525_PRECHARGE_TIME_R	0x08
+#define SEPS525_PRECHARGE_TIME_G	0x09
+#define SEPS525_PRECHARGE_TIME_B	0x0A
+#define SEPS525_PRECHARGE_CURRENT_R	0x0B
+#define SEPS525_PRECHARGE_CURRENT_G	0x0C
+#define SEPS525_PRECHARGE_CURRENT_B	0x0D
+#define SEPS525_DRIVING_CURRENT_R	0x10
+#define SEPS525_DRIVING_CURRENT_G	0x11
+#define SEPS525_DRIVING_CURRENT_B	0x12
+#define SEPS525_DISPLAYMODE_SET		0x13
+#define SEPS525_RGBIF			0x14
+#define SEPS525_RGB_POL			0x15
+#define SEPS525_MEMORY_WRITEMODE	0x16
+#define SEPS525_MX1_ADDR		0x17
+#define SEPS525_MX2_ADDR		0x18
+#define SEPS525_MY1_ADDR		0x19
+#define SEPS525_MY2_ADDR		0x1A
+#define SEPS525_MEMORY_ACCESS_POINTER_X	0x20
+#define SEPS525_MEMORY_ACCESS_POINTER_Y	0x21
+#define SEPS525_DDRAM_DATA_ACCESS_PORT	0x22
+#define SEPS525_GRAY_SCALE_TABLE_INDEX	0x50
+#define SEPS525_GRAY_SCALE_TABLE_DATA	0x51
+#define SEPS525_DUTY			0x28
+#define SEPS525_DSL			0x29
+#define SEPS525_D1_DDRAM_FAC		0x2E
+#define SEPS525_D1_DDRAM_FAR		0x2F
+#define SEPS525_D2_DDRAM_SAC		0x31
+#define SEPS525_D2_DDRAM_SAR		0x32
+#define SEPS525_SCR1_FX1		0x33
+#define SEPS525_SCR1_FX2		0x34
+#define SEPS525_SCR1_FY1		0x35
+#define SEPS525_SCR1_FY2		0x36
+#define SEPS525_SCR2_SX1		0x37
+#define SEPS525_SCR2_SX2		0x38
+#define SEPS525_SCR2_SY1		0x39
+#define SEPS525_SCR2_SY2		0x3A
+#define SEPS525_SCREEN_SAVER_CONTEROL	0x3B
+#define SEPS525_SS_SLEEP_TIMER		0x3C
+#define SEPS525_SCREEN_SAVER_MODE	0x3D
+#define SEPS525_SS_SCR1_FU		0x3E
+#define SEPS525_SS_SCR1_MXY		0x3F
+#define SEPS525_SS_SCR2_FU		0x40
+#define SEPS525_SS_SCR2_MXY		0x41
+#define SEPS525_MOVING_DIRECTION	0x42
+#define SEPS525_SS_SCR2_SX1		0x47
+#define SEPS525_SS_SCR2_SX2		0x48
+#define SEPS525_SS_SCR2_SY1		0x49
+#define SEPS525_SS_SCR2_SY2		0x4A
+
+/* SEPS525_DISPLAYMODE_SET */
+#define MODE_SWAP_BGR	BIT(7)
+#define MODE_SM		BIT(6)
+#define MODE_RD		BIT(5)
+#define MODE_CD		BIT(4)
+
+/**
+ * struct seps525_priv - Private structure
+ * @reset_gpio: Reset gpio pin
+ * @dc_gpio: Data/command control gpio pin
+ * @dev: Device uclass for video_ops
+ */
+struct seps525_priv {
+	struct gpio_desc reset_gpio;
+	struct gpio_desc dc_gpio;
+	struct udevice *dev;
+};
+
+static int seps525_spi_write_cmd(struct udevice *dev, u32 reg)
+{
+	struct seps525_priv *priv = dev_get_priv(dev);
+	u8 buf8 = reg;
+	int ret;
+
+	ret = dm_gpio_set_value(&priv->dc_gpio, 0);
+	if (ret) {
+		dev_dbg(dev, "Failed to handle dc\n");
+		return ret;
+	}
+
+	ret = dm_spi_xfer(dev, 8, &buf8, NULL, SPI_XFER_BEGIN | SPI_XFER_END);
+	if (ret)
+		dev_dbg(dev, "Failed to write command\n");
+
+	return ret;
+}
+
+static int seps525_spi_write_data(struct udevice *dev, u32 val)
+{
+	struct seps525_priv *priv = dev_get_priv(dev);
+	u8 buf8 = val;
+	int ret;
+
+	ret = dm_gpio_set_value(&priv->dc_gpio, 1);
+	if (ret) {
+		dev_dbg(dev, "Failed to handle dc\n");
+		return ret;
+	}
+
+	ret = dm_spi_xfer(dev, 8, &buf8, NULL, SPI_XFER_BEGIN | SPI_XFER_END);
+	if (ret)
+		dev_dbg(dev, "Failed to write data\n");
+
+	return ret;
+}
+
+static void seps525_spi_write(struct udevice *dev, u32 reg, u32 val)
+{
+	(void)seps525_spi_write_cmd(dev, reg);
+	(void)seps525_spi_write_data(dev, val);
+}
+
+static int seps525_display_init(struct udevice *dev)
+{
+	/* Disable Oscillator Power Down */
+	seps525_spi_write(dev, SEPS525_REDUCE_CURRENT, 0x03);
+	mdelay(5);
+
+	/* Set Normal Driving Current */
+	seps525_spi_write(dev, SEPS525_REDUCE_CURRENT, 0x00);
+	mdelay(5);
+
+	seps525_spi_write(dev, SEPS525_SCREEN_SAVER_CONTEROL, 0x00);
+	/* Set EXPORT1 Pin at Internal Clock */
+	seps525_spi_write(dev, SEPS525_OSC_CTL, 0x01);
+	/* Set Clock as 120 Frames/Sec */
+	seps525_spi_write(dev, SEPS525_CLOCK_DIV, 0x90);
+	/* Set Reference Voltage Controlled by External Resister */
+	seps525_spi_write(dev, SEPS525_IREF, 0x01);
+
+	/* precharge time R G B */
+	seps525_spi_write(dev, SEPS525_PRECHARGE_TIME_R, 0x04);
+	seps525_spi_write(dev, SEPS525_PRECHARGE_TIME_G, 0x05);
+	seps525_spi_write(dev, SEPS525_PRECHARGE_TIME_B, 0x05);
+
+	/* precharge current R G B (uA) */
+	seps525_spi_write(dev, SEPS525_PRECHARGE_CURRENT_R, 0x9D);
+	seps525_spi_write(dev, SEPS525_PRECHARGE_CURRENT_G, 0x8C);
+	seps525_spi_write(dev, SEPS525_PRECHARGE_CURRENT_B, 0x57);
+
+	/* driving current R G B (uA) */
+	seps525_spi_write(dev, SEPS525_DRIVING_CURRENT_R, 0x56);
+	seps525_spi_write(dev, SEPS525_DRIVING_CURRENT_G, 0x4D);
+	seps525_spi_write(dev, SEPS525_DRIVING_CURRENT_B, 0x46);
+	/* Set Color Sequence */
+	seps525_spi_write(dev, SEPS525_DISPLAYMODE_SET, 0x00);
+	/* Set MCU Interface Mode */
+	seps525_spi_write(dev, SEPS525_RGBIF, 0x01);
+	/* Set Memory Write Mode */
+	seps525_spi_write(dev, SEPS525_MEMORY_WRITEMODE, 0x66);
+	/* 1/128 Duty (0x0F~0x7F) */
+	seps525_spi_write(dev, SEPS525_DUTY, 0x7F);
+	/* Set Mapping RAM Display Start Line (0x00~0x7F) */
+	seps525_spi_write(dev, SEPS525_DSL, 0x00);
+	/* Display On (0x00/0x01) */
+	seps525_spi_write(dev, SEPS525_DISP_ONOFF, 0x01);
+	/* Set All Internal Register Value as Normal Mode */
+	seps525_spi_write(dev, SEPS525_SOFT_RST, 0x00);
+	/* Set RGB Interface Polarity as Active Low */
+	seps525_spi_write(dev, SEPS525_RGB_POL, 0x00);
+
+	/* Enable access for data */
+	(void)seps525_spi_write_cmd(dev, SEPS525_DDRAM_DATA_ACCESS_PORT);
+
+	return 0;
+}
+
+static int seps525_spi_startup(struct udevice *dev)
+{
+	struct seps525_priv *priv = dev_get_priv(dev);
+	int ret;
+
+	ret = dm_gpio_set_value(&priv->reset_gpio, 1);
+	if (ret)
+		return ret;
+
+	ret = dm_gpio_set_value(&priv->reset_gpio, 0);
+	if (ret)
+		return ret;
+
+	ret = dm_spi_claim_bus(dev);
+	if (ret) {
+		dev_err(dev, "Failed to claim SPI bus: %d\n", ret);
+		return ret;
+	}
+
+	ret = seps525_display_init(dev);
+	if (ret)
+		return ret;
+
+	dm_spi_release_bus(dev);
+
+	return 0;
+}
+
+static int seps525_sync(struct udevice *vid)
+{
+	struct video_priv *uc_priv = dev_get_uclass_priv(vid);
+	struct seps525_priv *priv = dev_get_priv(vid);
+	struct udevice *dev = priv->dev;
+	int i, ret;
+	u8 data1, data2;
+	u8 *start = uc_priv->fb;
+
+	ret = dm_spi_claim_bus(dev);
+	if (ret) {
+		dev_err(dev, "Failed to claim SPI bus: %d\n", ret);
+		return ret;
+	}
+
+	/* start position X,Y */
+	seps525_spi_write(dev, SEPS525_MEMORY_ACCESS_POINTER_X, 0);
+	seps525_spi_write(dev, SEPS525_MEMORY_ACCESS_POINTER_Y, 0);
+
+	/* Enable access for data */
+	(void)seps525_spi_write_cmd(dev, SEPS525_DDRAM_DATA_ACCESS_PORT);
+
+	for (i = 0; i < (uc_priv->xsize * uc_priv->ysize); i++) {
+		data2 = *start++;
+		data1 = *start++;
+		(void)seps525_spi_write_data(dev, data1);
+		(void)seps525_spi_write_data(dev, data2);
+	}
+
+	dm_spi_release_bus(dev);
+
+	return 0;
+}
+
+static int seps525_probe(struct udevice *dev)
+{
+	struct video_priv *uc_priv = dev_get_uclass_priv(dev);
+	struct seps525_priv *priv = dev_get_priv(dev);
+	u32 buswidth;
+	int ret;
+
+	buswidth = dev_read_u32_default(dev, "buswidth", 0);
+	if (buswidth != 8) {
+		dev_err(dev, "Only 8bit buswidth is supported now");
+		return -EINVAL;
+	}
+
+	ret = gpio_request_by_name(dev, "reset-gpios", 0,
+				   &priv->reset_gpio, GPIOD_IS_OUT);
+	if (ret) {
+		dev_err(dev, "missing reset GPIO\n");
+		return ret;
+	}
+
+	ret = gpio_request_by_name(dev, "dc-gpios", 0,
+				   &priv->dc_gpio, GPIOD_IS_OUT);
+	if (ret) {
+		dev_err(dev, "missing dc GPIO\n");
+		return ret;
+	}
+
+	uc_priv->bpix = VIDEO_BPP16;
+	uc_priv->xsize = WIDTH;
+	uc_priv->ysize = HEIGHT;
+	uc_priv->rot = 0;
+
+	priv->dev = dev;
+
+	ret = seps525_spi_startup(dev);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+static int seps525_bind(struct udevice *dev)
+{
+	struct video_uc_platdata *plat = dev_get_uclass_platdata(dev);
+
+	plat->size = WIDTH * HEIGHT * 16;
+
+	return 0;
+}
+
+static const struct video_ops seps525_ops = {
+	.video_sync = seps525_sync,
+};
+
+static const struct udevice_id seps525_ids[] = {
+	{ .compatible = "syncoam,seps525" },
+	{ }
+};
+
+U_BOOT_DRIVER(seps525_video) = {
+	.name = "seps525_video",
+	.id = UCLASS_VIDEO,
+	.of_match = seps525_ids,
+	.ops = &seps525_ops,
+	.platdata_auto_alloc_size = sizeof(struct video_uc_platdata),
+	.bind = seps525_bind,
+	.probe = seps525_probe,
+	.priv_auto_alloc_size = sizeof(struct seps525_priv),
+};

+ 29 - 11
drivers/video/vidconsole-uclass.c

@@ -89,9 +89,7 @@ static int vidconsole_back(struct udevice *dev)
 		if (priv->ycur < 0)
 			priv->ycur = 0;
 	}
-	video_sync(dev->parent, false);
-
-	return 0;
+	return video_sync(dev->parent, false);
 }
 
 /* Move to a newline, scrolling the display if necessary */
@@ -101,7 +99,7 @@ static void vidconsole_newline(struct udevice *dev)
 	struct udevice *vid_dev = dev->parent;
 	struct video_priv *vid_priv = dev_get_uclass_priv(vid_dev);
 	const int rows = CONFIG_CONSOLE_SCROLL_LINES;
-	int i;
+	int i, ret;
 
 	priv->xcur_frac = priv->xstart_frac;
 	priv->ycur += priv->y_charsize;
@@ -116,7 +114,12 @@ static void vidconsole_newline(struct udevice *dev)
 	}
 	priv->last_ch = 0;
 
-	video_sync(dev->parent, false);
+	ret = video_sync(dev->parent, false);
+	if (ret) {
+#ifdef DEBUG
+		console_puts_select_stderr(true, "[vc err: video_sync]");
+#endif
+	}
 }
 
 static const struct vid_rgb colors[VID_COLOR_COUNT] = {
@@ -348,8 +351,15 @@ static void vidconsole_escape_char(struct udevice *dev, char ch)
 		parsenum(priv->escape_buf + 1, &mode);
 
 		if (mode == 2) {
+			int ret;
+
 			video_clear(dev->parent);
-			video_sync(dev->parent, false);
+			ret = video_sync(dev->parent, false);
+			if (ret) {
+#ifdef DEBUG
+				console_puts_select_stderr(true, "[vc err: video_sync]");
+#endif
+			}
 			priv->ycur = 0;
 			priv->xcur_frac = priv->xstart_frac;
 		} else {
@@ -565,7 +575,12 @@ static void vidconsole_putc(struct stdio_dev *sdev, const char ch)
 		console_puts_select_stderr(true, "[vc err: putc]");
 #endif
 	}
-	video_sync(dev->parent, false);
+	ret = video_sync(dev->parent, false);
+	if (ret) {
+#ifdef DEBUG
+		console_puts_select_stderr(true, "[vc err: video_sync]");
+#endif
+	}
 }
 
 static void vidconsole_puts(struct stdio_dev *sdev, const char *s)
@@ -582,7 +597,12 @@ static void vidconsole_puts(struct stdio_dev *sdev, const char *s)
 		console_puts_select_stderr(true, str);
 #endif
 	}
-	video_sync(dev->parent, false);
+	ret = video_sync(dev->parent, false);
+	if (ret) {
+#ifdef DEBUG
+		console_puts_select_stderr(true, "[vc err: video_sync]");
+#endif
+	}
 }
 
 /* Set up the number of rows and colours (rotated drivers override this) */
@@ -691,9 +711,7 @@ static int do_video_puts(struct cmd_tbl *cmdtp, int flag, int argc,
 	for (s = argv[1]; *s; s++)
 		vidconsole_put_char(dev, *s);
 
-	video_sync(dev->parent, false);
-
-	return 0;
+	return video_sync(dev->parent, false);
 }
 
 U_BOOT_CMD(

+ 19 - 4
drivers/video/video-uclass.c

@@ -15,6 +15,7 @@
 #include <video_console.h>
 #include <asm/cache.h>
 #include <dm/lists.h>
+#include <dm/device_compat.h>
 #include <dm/device-internal.h>
 #include <dm/uclass-internal.h>
 #ifdef CONFIG_SANDBOX
@@ -142,7 +143,7 @@ int video_clear(struct udevice *dev)
 	if (ret)
 		return ret;
 
-	return 0;
+	return video_sync(dev, false);
 }
 
 void video_set_default_colors(struct udevice *dev, bool invert)
@@ -172,8 +173,17 @@ void video_set_default_colors(struct udevice *dev, bool invert)
 }
 
 /* Flush video activity to the caches */
-void video_sync(struct udevice *vid, bool force)
+int video_sync(struct udevice *vid, bool force)
 {
+	struct video_ops *ops = video_get_ops(vid);
+	int ret;
+
+	if (ops && ops->video_sync) {
+		ret = ops->video_sync(vid);
+		if (ret)
+			return ret;
+	}
+
 	/*
 	 * flush_dcache_range() is declared in common.h but it seems that some
 	 * architectures do not actually implement it. Is there a way to find
@@ -196,17 +206,22 @@ void video_sync(struct udevice *vid, bool force)
 		last_sync = get_timer(0);
 	}
 #endif
+	return 0;
 }
 
 void video_sync_all(void)
 {
 	struct udevice *dev;
+	int ret;
 
 	for (uclass_find_first_device(UCLASS_VIDEO, &dev);
 	     dev;
 	     uclass_find_next_device(&dev)) {
-		if (device_active(dev))
-			video_sync(dev, true);
+		if (device_active(dev)) {
+			ret = video_sync(dev, true);
+			if (ret)
+				dev_dbg(dev, "Video sync failed\n");
+		}
 	}
 }
 

+ 1 - 4
drivers/video/video_bmp.c

@@ -379,8 +379,5 @@ int video_bmp_display(struct udevice *dev, ulong bmp_image, int x, int y,
 	if (ret)
 		return log_ret(ret);
 
-	video_sync(dev, false);
-
-	return 0;
+	return video_sync(dev, false);
 }
-

+ 16 - 1
include/configs/microblaze-generic.h

@@ -81,6 +81,20 @@
 # define BOOT_TARGET_DEVICES_QSPI(func)
 #endif
 
+#if defined(CONFIG_MTD_NOR_FLASH)
+# define BOOT_TARGET_DEVICES_NOR(func)  func(NOR, nor, na)
+#else
+# define BOOT_TARGET_DEVICES_NOR(func)
+#endif
+
+#define BOOTENV_DEV_NOR(devtypeu, devtypel, instance) \
+	"bootcmd_nor=cp.b ${script_offset_nor} ${scriptaddr} ${script_size_f} && " \
+		"echo NOR: Trying to boot script at ${scriptaddr} && " \
+		"source ${scriptaddr}; echo NOR: SCRIPT FAILED: continuing...;\0"
+
+#define BOOTENV_DEV_NAME_NOR(devtypeu, devtypel, instance) \
+	"nor "
+
 #define BOOTENV_DEV_QSPI(devtypeu, devtypel, instance) \
 	"bootcmd_qspi=sf probe 0 0 0 && " \
 	"sf read ${scriptaddr} ${script_offset_f} ${script_size_f} && " \
@@ -101,7 +115,8 @@
 
 #define BOOT_TARGET_DEVICES(func) \
 	BOOT_TARGET_DEVICES_JTAG(func) \
-	BOOT_TARGET_DEVICES_QSPI(func)  \
+	BOOT_TARGET_DEVICES_QSPI(func) \
+	BOOT_TARGET_DEVICES_NOR(func) \
 	BOOT_TARGET_DEVICES_DHCP(func) \
 	BOOT_TARGET_DEVICES_PXE(func)
 

+ 16 - 6
include/video.h

@@ -114,8 +114,16 @@ struct video_priv {
 	u8 bg_col_idx;
 };
 
-/* Placeholder - there are no video operations at present */
+/**
+ * struct video_ops - structure for keeping video operations
+ * @video_sync: Synchronize FB with device. Some device like SPI based LCD
+ *		displays needs synchronization when data in an FB is available.
+ *		For these devices implement video_sync hook to call a sync
+ *		function. vid is pointer to video device udevice. Function
+ *		should return 0 on success video_sync and error code otherwise
+ */
 struct video_ops {
+	int (*video_sync)(struct udevice *vid);
 };
 
 #define video_get_ops(dev)        ((struct video_ops *)(dev)->driver->ops)
@@ -151,15 +159,17 @@ int video_clear(struct udevice *dev);
 /**
  * video_sync() - Sync a device's frame buffer with its hardware
  *
+ * @vid:	Device to sync
+ * @force:	True to force a sync even if there was one recently (this is
+ *		very expensive on sandbox)
+ *
+ * @return: 0 on success, error code otherwise
+ *
  * Some frame buffers are cached or have a secondary frame buffer. This
  * function syncs these up so that the current contents of the U-Boot frame
  * buffer are displayed to the user.
- *
- * @dev:	Device to sync
- * @force:	True to force a sync even if there was one recently (this is
- *		very expensive on sandbox)
  */
-void video_sync(struct udevice *vid, bool force);
+int video_sync(struct udevice *vid, bool force);
 
 /**
  * video_sync_all() - Sync all devices' frame buffers with there hardware

+ 1 - 1
tools/zynqmp_pm_cfg_obj_convert.py

@@ -289,7 +289,7 @@ code = in_file.read()
 code = re.sub('//.*?\n|/\*.*?\*/', '', code, flags=re.DOTALL)
 
 # remove everything outside the XPm_ConfigObject array definition
-code = re.search('const u32 XPm_ConfigObject.*= {\n(.*)};',
+code = re.search('const u32 XPm_ConfigObject.*=.*{\n(.*)};',
                  code, flags=re.DOTALL).group(1)
 
 # Process each comma-separated array item