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
 -----BEGIN PGP SIGNATURE-----
 
 iFsEABECAB0WIQQbPNTMvXmYlBPRwx7KSWXLKUoMIQUCX/ROlgAKCRDKSWXLKUoM
 IRC5AIkBzg4Sz8fQgdCiOK89k7tdFKMAnA9SYhgm4TSCzffZCJwnm78QoGAC
 =4FnY
 -----END PGP SIGNATURE-----

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
This commit is contained in:
Tom Rini 2021-01-06 07:57:33 -05:00
commit bc0b99bd8b
25 changed files with 540 additions and 80 deletions

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -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
drivers/video/seps525.c Normal file
View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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