Merge branch 'master' of git://git.denx.de/u-boot-video

lime2-spi
Tom Rini 6 years ago
commit 282ce6454c
  1. 22
      Documentation/devicetree/bindings/axi/gdsys,ihs_axi.txt
  2. 11
      arch/sandbox/dts/sandbox.dts
  3. 11
      arch/sandbox/dts/test.dts
  4. 66
      arch/sandbox/include/asm/axi.h
  5. 8
      cmd/Kconfig
  6. 1
      cmd/Makefile
  7. 352
      cmd/axi.c
  8. 3
      configs/sandbox_defconfig
  9. 2
      drivers/Kconfig
  10. 1
      drivers/Makefile
  11. 32
      drivers/axi/Kconfig
  12. 12
      drivers/axi/Makefile
  13. 85
      drivers/axi/axi-emul-uclass.c
  14. 39
      drivers/axi/axi-uclass.c
  15. 77
      drivers/axi/axi_sandbox.c
  16. 293
      drivers/axi/ihs_axi.c
  17. 123
      drivers/axi/sandbox_store.c
  18. 11
      drivers/video/Kconfig
  19. 43
      drivers/video/Makefile
  20. 341
      drivers/video/logicore_dp_dpcd.h
  21. 2296
      drivers/video/logicore_dp_tx.c
  22. 54
      drivers/video/logicore_dp_tx.h
  23. 396
      drivers/video/logicore_dp_tx_regif.h
  24. 118
      include/axi.h
  25. 2
      include/dm/uclass-id.h
  26. 1
      test/dm/Makefile
  27. 77
      test/dm/axi.c

@ -0,0 +1,22 @@
gdsys AXI busses of IHS FPGA devices
Certain gdsys IHS FPGAs offer a interface to their built-in AXI bus with which
the connected devices (usually IP cores) can be controlled via software.
Required properties:
- compatible: must be "gdsys,ihs_axi"
- reg: describes the address and length of the AXI bus's register map (within
the FPGA's register space)
Example:
fpga0_axi_video0 {
#address-cells = <1>;
#size-cells = <1>;
compatible = "gdsys,ihs_axi";
reg = <0x170 0x10>;
axi_dev_1 {
...
};
};

@ -11,6 +11,7 @@
i2c0 = &i2c_0;
pci0 = &pci;
rtc0 = &rtc_0;
axi0 = &axi;
};
chosen {
@ -311,6 +312,16 @@
};
};
};
axi: axi@0 {
compatible = "sandbox,axi";
#address-cells = <0x1>;
#size-cells = <0x1>;
store@0 {
compatible = "sandbox,sandbox_store";
reg = <0x0 0x400>;
};
};
};
#include "cros-ec-keyboard.dtsi"

@ -36,6 +36,7 @@
usb0 = &usb_0;
usb1 = &usb_1;
usb2 = &usb_2;
axi0 = &axi;
};
a-test {
@ -552,6 +553,16 @@
compatible = "sandbox,wdt";
};
axi: axi@0 {
compatible = "sandbox,axi";
#address-cells = <0x1>;
#size-cells = <0x1>;
store@0 {
compatible = "sandbox,sandbox_store";
reg = <0x0 0x400>;
};
};
chosen {
#address-cells = <1>;
#size-cells = <1>;

@ -0,0 +1,66 @@
/* SPDX-License-Identifier: GPL-2.0+ */
/*
* (C) Copyright 2018
* Mario Six, Guntermann & Drunck GmbH, mario.six@gdsys.cc
*/
#ifndef __asm_axi_h
#define __asm_axi_h
#define axi_emul_get_ops(dev) ((struct axi_emul_ops *)(dev)->driver->ops)
/**
* axi_sandbox_get_emul() - Retrieve a pointer to a AXI emulation device
* @bus: The AXI bus from which to retrieve a emulation device
* @address: The address of a transfer that should be handled by a emulation
* device
* @length: The data width of a transfer that should be handled by a emulation
* device
* @emulp: Pointer to a buffer receiving the emulation device that handles
* the transfer specified by the address and length parameters
*
* To test the AXI uclass, we implement a simple AXI emulation device, which is
* a virtual device on a AXI bus that exposes a simple storage interface: When
* reading and writing from the device, the addresses are translated to offsets
* within the device's storage. For write accesses the data is written to the
* specified storage offset, and for read accesses the data is read from the
* specified storage offset.
*
* A DTS entry might look like this:
*
* axi: axi@0 {
* compatible = "sandbox,axi";
* #address-cells = <0x1>;
* #size-cells = <0x1>;
* store@0 {
* compatible = "sandbox,sandbox_store";
* reg = <0x0 0x400>;
* };
* };
*
* This function may then be used to retrieve the pointer to the sandbox_store
* emulation device given the AXI bus device, and the data (address, data
* width) of a AXI transfer which should be handled by a emulation device.
*
* Return: 0 of OK, -ENODEV if no device capable of handling the specified
* transfer exists or the device could not be retrieved
*/
int axi_sandbox_get_emul(struct udevice *bus, ulong address, uint length,
struct udevice **emulp);
/**
* axi_get_store() - Get address of internal storage of a emulated AXI device
* @dev: Emulated AXI device to get the pointer of the internal storage
* for.
* @storep: Pointer to the internal storage of the emulated AXI device.
*
* To preset or read back the contents internal storage of the emulated AXI
* device, this function returns the pointer to the storage. Changes to the
* contents of the storage are reflected when using the AXI read/write API
* methods, and vice versa, so by using this method expected read data can be
* set up in advance, and written data can be checked in unit tests.
*
* Return: 0 if OK, -ve on error.
*/
int axi_get_store(struct udevice *dev, u8 **storep);
#endif /* __asm_axi_h */

@ -1027,6 +1027,14 @@ config CMD_USB_MASS_STORAGE
help
USB mass storage support
config CMD_AXI
bool "axi"
depends on AXI
help
Enable the command "axi" for accessing AXI (Advanced eXtensible
Interface) busses, a on-chip interconnect specification for managing
functional blocks in SoC designs, which is also often used in designs
involving FPGAs (e.g. communication with IP cores in Xilinx FPGAs).
endmenu

@ -149,6 +149,7 @@ obj-$(CONFIG_CMD_ZFS) += zfs.o
obj-$(CONFIG_CMD_DFU) += dfu.o
obj-$(CONFIG_CMD_GPT) += gpt.o
obj-$(CONFIG_CMD_ETHSW) += ethsw.o
obj-$(CONFIG_CMD_AXI) += axi.o
# Power
obj-$(CONFIG_CMD_PMIC) += pmic.o

@ -0,0 +1,352 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* (C) Copyright 2016
* Dirk Eibach, Guntermann & Drunck GmbH, dirk.eibach@gdsys.cc
*
* (C) Copyright 2017, 2018
* Mario Six, Guntermann & Drunck GmbH, mario.six@gdsys.cc
*
* SPDX-License-Identifier: GPL-2.0+
*/
#include <common.h>
#include <axi.h>
#include <command.h>
#include <console.h>
#include <dm.h>
/* Currently selected AXI bus device */
static struct udevice *axi_cur_bus;
/* Transmission size from last command */
static uint dp_last_size;
/* Address from last command */
static uint dp_last_addr;
/* Number of bytes to display from last command; default = 64 */
static uint dp_last_length = 0x40;
/**
* show_bus() - Show devices on a single AXI bus
* @bus: The AXI bus device to printt information for
*/
static void show_bus(struct udevice *bus)
{
struct udevice *dev;
printf("Bus %d:\t%s", bus->req_seq, bus->name);
if (device_active(bus))
printf(" (active %d)", bus->seq);
printf("\n");
for (device_find_first_child(bus, &dev);
dev;
device_find_next_child(&dev))
printf(" %s\n", dev->name);
}
/**
* axi_set_cur_bus() - Set the currently active AXI bus
* @busnum: The number of the bus (i.e. its sequence number) that should be
* made active
*
* The operations supplied by this command operate only on the currently active
* bus.
*
* Return: 0 if OK, -ve on error
*/
static int axi_set_cur_bus(unsigned int busnum)
{
struct udevice *bus;
struct udevice *dummy;
int ret;
/* Make sure that all sequence numbers are initialized */
for (uclass_first_device(UCLASS_AXI, &dummy);
dummy;
uclass_next_device(&dummy))
;
ret = uclass_get_device_by_seq(UCLASS_AXI, busnum, &bus);
if (ret) {
debug("%s: No bus %d\n", __func__, busnum);
return ret;
}
axi_cur_bus = bus;
return 0;
}
/**
* axi_get_cur_bus() - Retrieve the currently active AXI bus device
* @busp: Pointer to a struct udevice that receives the currently active bus
* device
*
* Return: 0 if OK, -ve on error
*/
static int axi_get_cur_bus(struct udevice **busp)
{
if (!axi_cur_bus) {
puts("No AXI bus selected\n");
return -ENODEV;
}
*busp = axi_cur_bus;
return 0;
}
/*
* Command handlers
*/
static int do_axi_show_bus(cmd_tbl_t *cmdtp, int flag, int argc,
char * const argv[])
{
struct udevice *dummy;
/* Make sure that all sequence numbers are initialized */
for (uclass_first_device(UCLASS_AXI, &dummy);
dummy;
uclass_next_device(&dummy))
;
if (argc == 1) {
/* show all busses */
struct udevice *bus;
for (uclass_first_device(UCLASS_AXI, &bus);
bus;
uclass_next_device(&bus))
show_bus(bus);
} else {
int i;
/* show specific bus */
i = simple_strtoul(argv[1], NULL, 10);
struct udevice *bus;
int ret;
ret = uclass_get_device_by_seq(UCLASS_AXI, i, &bus);
if (ret) {
printf("Invalid bus %d: err=%d\n", i, ret);
return CMD_RET_FAILURE;
}
show_bus(bus);
}
return 0;
}
static int do_axi_bus_num(cmd_tbl_t *cmdtp, int flag, int argc,
char * const argv[])
{
int ret = 0;
int bus_no;
if (argc == 1) {
/* querying current setting */
struct udevice *bus;
if (!axi_get_cur_bus(&bus))
bus_no = bus->seq;
else
bus_no = -1;
printf("Current bus is %d\n", bus_no);
} else {
bus_no = simple_strtoul(argv[1], NULL, 10);
printf("Setting bus to %d\n", bus_no);
ret = axi_set_cur_bus(bus_no);
if (ret)
printf("Failure changing bus number (%d)\n", ret);
}
return ret ? CMD_RET_FAILURE : 0;
}
static int do_axi_md(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
{
/* Print that many bytes per line */
const uint DISP_LINE_LEN = 16;
u8 linebuf[DISP_LINE_LEN];
unsigned int k;
ulong addr, length, size;
ulong nbytes;
enum axi_size_t axisize;
int unitsize;
/*
* We use the last specified parameters, unless new ones are
* entered.
*/
size = dp_last_size;
addr = dp_last_addr;
length = dp_last_length;
if (argc < 3)
return CMD_RET_USAGE;
if (!axi_cur_bus) {
puts("No AXI bus selected\n");
return CMD_RET_FAILURE;
}
if ((flag & CMD_FLAG_REPEAT) == 0) {
size = simple_strtoul(argv[1], NULL, 10);
/*
* Address is specified since argc >= 3
*/
addr = simple_strtoul(argv[2], NULL, 16);
/*
* If there's another parameter, it is the length to display;
* length is the number of objects, not number of bytes
*/
if (argc > 3)
length = simple_strtoul(argv[3], NULL, 16);
}
switch (size) {
case 8:
axisize = AXI_SIZE_8;
unitsize = 1;
break;
case 16:
axisize = AXI_SIZE_16;
unitsize = 2;
break;
case 32:
axisize = AXI_SIZE_32;
unitsize = 4;
break;
default:
printf("Unknown read size '%lu'\n", size);
return CMD_RET_USAGE;
};
nbytes = length * unitsize;
do {
ulong linebytes = (nbytes > DISP_LINE_LEN) ?
DISP_LINE_LEN : nbytes;
for (k = 0; k < linebytes / unitsize; ++k) {
int ret = axi_read(axi_cur_bus, addr + k * unitsize,
linebuf + k * unitsize, axisize);
if (!ret) /* Continue if axi_read was successful */
continue;
if (ret == -ENOSYS)
printf("axi_read failed; read size not supported?\n");
else
printf("axi_read failed: err = %d\n", ret);
return CMD_RET_FAILURE;
}
print_buffer(addr, (void *)linebuf, unitsize,
linebytes / unitsize,
DISP_LINE_LEN / unitsize);
nbytes -= max(linebytes, 1UL);
addr += linebytes;
if (ctrlc())
break;
} while (nbytes > 0);
dp_last_size = size;
dp_last_addr = addr;
dp_last_length = length;
return 0;
}
static int do_axi_mw(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
{
u32 writeval;
ulong addr, count, size;
enum axi_size_t axisize;
if (argc <= 3 || argc >= 6)
return CMD_RET_USAGE;
size = simple_strtoul(argv[1], NULL, 10);
switch (size) {
case 8:
axisize = AXI_SIZE_8;
break;
case 16:
axisize = AXI_SIZE_16;
break;
case 32:
axisize = AXI_SIZE_32;
break;
default:
printf("Unknown write size '%lu'\n", size);
return CMD_RET_USAGE;
};
/* Address is specified since argc > 4 */
addr = simple_strtoul(argv[2], NULL, 16);
/* Get the value to write */
writeval = simple_strtoul(argv[3], NULL, 16);
/* Count ? */
if (argc == 5)
count = simple_strtoul(argv[4], NULL, 16);
else
count = 1;
while (count-- > 0) {
int ret = axi_write(axi_cur_bus, addr + count * sizeof(u32),
&writeval, axisize);
if (ret) {
printf("axi_write failed: err = %d\n", ret);
return CMD_RET_FAILURE;
}
}
return 0;
}
static cmd_tbl_t cmd_axi_sub[] = {
U_BOOT_CMD_MKENT(bus, 1, 1, do_axi_show_bus, "", ""),
U_BOOT_CMD_MKENT(dev, 1, 1, do_axi_bus_num, "", ""),
U_BOOT_CMD_MKENT(md, 4, 1, do_axi_md, "", ""),
U_BOOT_CMD_MKENT(mw, 5, 1, do_axi_mw, "", ""),
};
static int do_ihs_axi(cmd_tbl_t *cmdtp, int flag, int argc,
char * const argv[])
{
cmd_tbl_t *c;
if (argc < 2)
return CMD_RET_USAGE;
/* Strip off leading 'axi' command argument */
argc--;
argv++;
/* Hand off rest of command line to sub-commands */
c = find_cmd_tbl(argv[0], &cmd_axi_sub[0], ARRAY_SIZE(cmd_axi_sub));
if (c)
return c->cmd(cmdtp, flag, argc, argv);
else
return CMD_RET_USAGE;
}
static char axi_help_text[] =
"bus - show AXI bus info\n"
"axi dev [bus] - show or set current AXI bus to bus number [bus]\n"
"axi md size addr [# of objects] - read from AXI device at address [addr] and data width [size] (one of 8, 16, 32)\n"
"axi mw size addr value [count] - write data [value] to AXI device at address [addr] and data width [size] (one of 8, 16, 32)\n";
U_BOOT_CMD(axi, 7, 1, do_ihs_axi,
"AXI sub-system",
axi_help_text
);

@ -45,6 +45,7 @@ CONFIG_CMD_REMOTEPROC=y
CONFIG_CMD_SF=y
CONFIG_CMD_SPI=y
CONFIG_CMD_USB=y
CONFIG_CMD_AXI=y
CONFIG_CMD_TFTPPUT=y
CONFIG_CMD_TFTPSRV=y
CONFIG_CMD_RARP=y
@ -80,6 +81,8 @@ CONFIG_DEVRES=y
CONFIG_DEBUG_DEVRES=y
CONFIG_ADC=y
CONFIG_ADC_SANDBOX=y
CONFIG_AXI=y
CONFIG_AXI_SANDBOX=y
CONFIG_CLK=y
CONFIG_CPU=y
CONFIG_DM_DEMO=y

@ -8,6 +8,8 @@ source "drivers/adc/Kconfig"
source "drivers/ata/Kconfig"
source "drivers/axi/Kconfig"
source "drivers/block/Kconfig"
source "drivers/bootcount/Kconfig"

@ -103,6 +103,7 @@ obj-y += smem/
obj-y += soc/
obj-$(CONFIG_REMOTEPROC) += remoteproc/
obj-y += thermal/
obj-y += axi/
obj-$(CONFIG_MACH_PIC32) += ddr/microchip/
endif

@ -0,0 +1,32 @@
menuconfig AXI
bool "AXI bus drivers"
help
Support AXI (Advanced eXtensible Interface) busses, a on-chip
interconnect specification for managing functional blocks in SoC
designs, which is also often used in designs involving FPGAs (e.g.
communication with IP cores in Xilinx FPGAs).
These types of busses expose a virtual address space that can be
accessed using different address widths (8, 16, and 32 are supported
for now).
Other similar bus architectures may be compatible as well.
if AXI
config IHS_AXI
bool "Enable IHS AXI driver"
depends on DM
help
Support for gdsys Integrated Hardware Systems Advanced eXtensible
Interface (IHS AXI) bus on a gdsys IHS FPGA used to communicate with
IP cores in the FPGA (e.g. video transmitter cores).
config AXI_SANDBOX
bool "Enable AXI sandbox driver"
depends on DM
help
Support AXI (Advanced eXtensible Interface) emulation for the sandbox
environment.
endif

@ -0,0 +1,12 @@
#
# (C) Copyright 2017
# Mario Six, Guntermann & Drunck GmbH, mario.six@gdsys.cc
#
# SPDX-License-Identifier: GPL-2.0+
#
obj-$(CONFIG_AXI) += axi-uclass.o
obj-$(CONFIG_IHS_AXI) += ihs_axi.o
obj-$(CONFIG_SANDBOX) += axi-emul-uclass.o
obj-$(CONFIG_SANDBOX) += sandbox_store.o
obj-$(CONFIG_AXI_SANDBOX) += axi_sandbox.o

@ -0,0 +1,85 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* (C) Copyright 2018
* Mario Six, Guntermann & Drunck GmbH, mario.six@gdsys.cc
*/
#include <common.h>
#include <axi.h>
#include <dm.h>
#include <dm/device-internal.h>
#include <asm/axi.h>
int axi_sandbox_get_emul(struct udevice *bus, ulong address,
enum axi_size_t size, struct udevice **emulp)
{
struct udevice *dev;
u32 reg[2];
uint offset;
switch (size) {
case AXI_SIZE_8:
offset = 1;
break;
case AXI_SIZE_16:
offset = 2;
break;
case AXI_SIZE_32:
offset = 4;
break;
default:
debug("%s: Unknown AXI transfer size '%d'", bus->name, size);
offset = 0;
}
/*
* Note: device_find_* don't activate the devices; they're activated
* as-needed below.
*/
for (device_find_first_child(bus, &dev);
dev;
device_find_next_child(&dev)) {
int ret;
ret = dev_read_u32_array(dev, "reg", reg, ARRAY_SIZE(reg));
if (ret) {
debug("%s: Could not read 'reg' property of %s\n",
bus->name, dev->name);
continue;
}
/*
* Does the transfer's address fall into this device's address
* space?
*/
if (address >= reg[0] && address <= reg[0] + reg[1] - offset) {
/* If yes, activate it... */
if (device_probe(dev)) {
debug("%s: Could not activate %s\n",
bus->name, dev->name);
return -ENODEV;
}
/* ...and return it */
*emulp = dev;
return 0;
}
}
return -ENODEV;
}
int axi_get_store(struct udevice *dev, u8 **storep)
{
struct axi_emul_ops *ops = axi_emul_get_ops(dev);
if (!ops->get_store)
return -ENOSYS;
return ops->get_store(dev, storep);
}
UCLASS_DRIVER(axi_emul) = {
.id = UCLASS_AXI_EMUL,
.name = "axi_emul",
};

@ -0,0 +1,39 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* (C) Copyright 2017
* Mario Six, Guntermann & Drunck GmbH, mario.six@gdsys.cc
*/
#include <common.h>
#include <dm.h>
#include <axi.h>
int axi_read(struct udevice *dev, ulong address, void *data,
enum axi_size_t size)
{
struct axi_ops *ops = axi_get_ops(dev);
if (!ops->read)
return -ENOSYS;
return ops->read(dev, address, data, size);
}
int axi_write(struct udevice *dev, ulong address, void *data,
enum axi_size_t size)
{
struct axi_ops *ops = axi_get_ops(dev);
if (!ops->write)
return -ENOSYS;
return ops->write(dev, address, data, size);
}
UCLASS_DRIVER(axi) = {
.id = UCLASS_AXI,
.name = "axi",
.post_bind = dm_scan_fdt_dev,
.flags = DM_UC_FLAG_SEQ_ALIAS,
};

@ -0,0 +1,77 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* (C) Copyright 2018
* Mario Six, Guntermann & Drunck GmbH, mario.six@gdsys.cc
*/
#include <common.h>
#include <axi.h>
#include <dm.h>
#include <asm/axi.h>
/*
* This driver implements a AXI bus for the sandbox architecture for testing
* purposes.
*
* The bus forwards every access to it to a special AXI emulation device (which
* it gets via the axi_emul_get_ops function) that implements a simple
* read/write storage.
*
* The emulator device must still be contained in the device tree in the usual
* way, since configuration data for the storage is read from the DT.
*/
static int axi_sandbox_read(struct udevice *bus, ulong address, void *data,
enum axi_size_t size)
{
struct axi_emul_ops *ops;
struct udevice *emul;
int ret;
/* Get emulator device */
ret = axi_sandbox_get_emul(bus, address, size, &emul);
if (ret)
return ret == -ENODEV ? 0 : ret;
/* Forward all reads to the AXI emulator */
ops = axi_emul_get_ops(emul);
if (!ops || !ops->read)
return -ENOSYS;
return ops->read(emul, address, data, size);
}
static int axi_sandbox_write(struct udevice *bus, ulong address, void *data,
enum axi_size_t size)
{
struct axi_emul_ops *ops;
struct udevice *emul;
int ret;
/* Get emulator device */
ret = axi_sandbox_get_emul(bus, address, size, &emul);
if (ret)
return ret == -ENODEV ? 0 : ret;
/* Forward all writes to the AXI emulator */
ops = axi_emul_get_ops(emul);
if (!ops || !ops->write)
return -ENOSYS;
return ops->write(emul, address, data, size);
}
static const struct udevice_id axi_sandbox_ids[] = {
{ .compatible = "sandbox,axi" },
{ /* sentinel */ }
};
static const struct axi_ops axi_sandbox_ops = {
.read = axi_sandbox_read,
.write = axi_sandbox_write,
};
U_BOOT_DRIVER(axi_sandbox_bus) = {
.name = "axi_sandbox_bus",
.id = UCLASS_AXI,
.of_match = axi_sandbox_ids,
.ops = &axi_sandbox_ops,
};

@ -0,0 +1,293 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* (C) Copyright 2016
* Dirk Eibach, Guntermann & Drunck GmbH, dirk.eibach@gdsys.cc
*
* (C) Copyright 2017, 2018
* Mario Six, Guntermann & Drunck GmbH, mario.six@gdsys.cc
*/
#include <common.h>
#include <axi.h>
#include <dm.h>
#include <regmap.h>
/**
* struct ihs_axi_regs - Structure for the register map of a IHS AXI device
* @interrupt_status: Status register to indicate certain events (e.g.
* error during transfer, transfer complete, etc.)
* @interrupt_enable_control: Register to both control which statuses will be
* indicated in the interrupt_status register, and
* to change bus settings
* @address_lsb: Least significant 16-bit word of the address of a
* device to transfer data from/to
* @address_msb: Most significant 16-bit word of the address of a
* device to transfer data from/to
* @write_data_lsb: Least significant 16-bit word of the data to be
* written to a device
* @write_data_msb: Most significant 16-bit word of the data to be
* written to a device
* @read_data_lsb: Least significant 16-bit word of the data read
* from a device
* @read_data_msb: Most significant 16-bit word of the data read
* from a device
*/
struct ihs_axi_regs {
u16 interrupt_status;
u16 interrupt_enable_control;
u16 address_lsb;
u16 address_msb;
u16 write_data_lsb;
u16 write_data_msb;
u16 read_data_lsb;
u16 read_data_msb;
};
/**
* ihs_axi_set() - Convenience macro to set values in register map
* @map: The register map to write to
* @member: The member of the ihs_axi_regs structure to write
* @val: The value to write to the register map
*/
#define ihs_axi_set(map, member, val) \
regmap_set(map, struct ihs_axi_regs, member, val)
/**
* ihs_axi_get() - Convenience macro to read values from register map
* @map: The register map to read from
* @member: The member of the ihs_axi_regs structure to read
* @valp: Pointer to a buffer to receive the value read
*/
#define ihs_axi_get(map, member, valp) \
regmap_get(map, struct ihs_axi_regs, member, valp)
/**
* struct ihs_axi_priv - Private data structure of IHS AXI devices
* @map: Register map for the IHS AXI device
*/
struct ihs_axi_priv {
struct regmap *map;
};
/**
* enum status_reg - Description of bits in the interrupt_status register
* @STATUS_READ_COMPLETE_EVENT: A read transfer was completed
* @STATUS_WRITE_COMPLETE_EVENT: A write transfer was completed
* @STATUS_TIMEOUT_EVENT: A timeout has occurred during the transfer
* @STATUS_ERROR_EVENT: A error has occurred during the transfer
* @STATUS_AXI_INT: A AXI interrupt has occurred
* @STATUS_READ_DATA_AVAILABLE: Data is available to be read
* @STATUS_BUSY: The bus is busy
* @STATUS_INIT_DONE: The bus has finished initializing
*/
enum status_reg {
STATUS_READ_COMPLETE_EVENT = BIT(15),
STATUS_WRITE_COMPLETE_EVENT = BIT(14),
STATUS_TIMEOUT_EVENT = BIT(13),
STATUS_ERROR_EVENT = BIT(12),
STATUS_AXI_INT = BIT(11),
STATUS_READ_DATA_AVAILABLE = BIT(7),
STATUS_BUSY = BIT(6),
STATUS_INIT_DONE = BIT(5),
};
/**
* enum control_reg - Description of bit fields in the interrupt_enable_control
* register
* @CONTROL_READ_COMPLETE_EVENT_ENABLE: STATUS_READ_COMPLETE_EVENT will be
* raised in the interrupt_status register
* @CONTROL_WRITE_COMPLETE_EVENT_ENABLE: STATUS_WRITE_COMPLETE_EVENT will be
* raised in the interrupt_status register
* @CONTROL_TIMEOUT_EVENT_ENABLE: STATUS_TIMEOUT_EVENT will be raised in
* the interrupt_status register
* @CONTROL_ERROR_EVENT_ENABLE: STATUS_ERROR_EVENT will be raised in
* the interrupt_status register
* @CONTROL_AXI_INT_ENABLE: STATUS_AXI_INT will be raised in the
* interrupt_status register
* @CONTROL_CMD_NOP: Configure bus to send a NOP command
* for the next transfer
* @CONTROL_CMD_WRITE: Configure bus to do a write transfer
* @CONTROL_CMD_WRITE_POST_INC: Auto-increment address after write
* transfer
* @CONTROL_CMD_READ: Configure bus to do a read transfer
* @CONTROL_CMD_READ_POST_INC: Auto-increment address after read
* transfer
*/
enum control_reg {
CONTROL_READ_COMPLETE_EVENT_ENABLE = BIT(15),
CONTROL_WRITE_COMPLETE_EVENT_ENABLE = BIT(14),
CONTROL_TIMEOUT_EVENT_ENABLE = BIT(13),
CONTROL_ERROR_EVENT_ENABLE = BIT(12),
CONTROL_AXI_INT_ENABLE = BIT(11),
CONTROL_CMD_NOP = 0x0,
CONTROL_CMD_WRITE = 0x8,
CONTROL_CMD_WRITE_POST_INC = 0x9,
CONTROL_CMD_READ = 0xa,
CONTROL_CMD_READ_POST_INC = 0xb,
};
/**
* enum axi_cmd - Determine if transfer is read or write transfer
* @AXI_CMD_READ: The transfer should be a read transfer
* @AXI_CMD_WRITE: The transfer should be a write transfer
*/
enum axi_cmd {
AXI_CMD_READ,
AXI_CMD_WRITE,
};
/**
* ihs_axi_transfer() - Run transfer on the AXI bus
* @bus: The AXI bus device on which to run the transfer on
* @address: The address to use in the transfer (i.e. which address to
* read/write from/to)
* @cmd: Should the transfer be a read or write transfer?
*
* Return: 0 if OK, -ve on error
*/
static int ihs_axi_transfer(struct udevice *bus, ulong address,
enum axi_cmd cmd)
{
struct ihs_axi_priv *priv = dev_get_priv(bus);
/* Try waiting for events up to 10 times */
const uint WAIT_TRIES = 10;
u16 wait_mask = STATUS_TIMEOUT_EVENT |
STATUS_ERROR_EVENT;
u16 complete_flag;
u16 status;
uint k;
if (cmd == AXI_CMD_READ) {
complete_flag = STATUS_READ_COMPLETE_EVENT;
cmd = CONTROL_CMD_READ;
} else {
complete_flag = STATUS_WRITE_COMPLETE_EVENT;
cmd = CONTROL_CMD_WRITE;
}
wait_mask |= complete_flag;
/* Lower 16 bit */
ihs_axi_set(priv->map, address_lsb, address & 0xffff);
/* Upper 16 bit */
ihs_axi_set(priv->map, address_msb, (address >> 16) & 0xffff);
ihs_axi_set(priv->map, interrupt_status, wait_mask);
ihs_axi_set(priv->map, interrupt_enable_control, cmd);
for (k = WAIT_TRIES; k > 0; --k) {
ihs_axi_get(priv->map, interrupt_status, &status);
if (status & wait_mask)
break;
udelay(1);
}
/*
* k == 0 -> Tries ran out with no event we were waiting for actually
* occurring.
*/
if (!k)
ihs_axi_get(priv->map, interrupt_status, &status);
if (status & complete_flag)
return 0;
if (status & STATUS_ERROR_EVENT) {
debug("%s: Error occurred during transfer\n", bus->name);
return -EIO;
}
debug("%s: Transfer timed out\n", bus->name);
return -ETIMEDOUT;
}
/*
* API
*/
static int ihs_axi_read(struct udevice *dev, ulong address, void *data,
enum axi_size_t size)
{
struct ihs_axi_priv *priv = dev_get_priv(dev);
int ret;
u16 data_lsb, data_msb;
u32 *p = data;
if (size != AXI_SIZE_32) {
debug("%s: transfer size '%d' not supported\n",
dev->name, size);
return -ENOSYS;
}
ret = ihs_axi_transfer(dev, address, AXI_CMD_READ);
if (ret < 0) {
debug("%s: Error during AXI transfer (err = %d)\n",
dev->name, ret);
return ret;
}
ihs_axi_get(priv->map, read_data_lsb, &data_lsb);
ihs_axi_get(priv->map, read_data_msb, &data_msb);
/* Assemble data from two 16-bit words */
*p = (data_msb << 16) | data_lsb;
return 0;
}
static int ihs_axi_write(struct udevice *dev, ulong address, void *data,
enum axi_size_t size)
{
struct ihs_axi_priv *priv = dev_get_priv(dev);
int ret;
u32 *p = data;
if (size != AXI_SIZE_32) {
debug("%s: transfer size '%d' not supported\n",
dev->name, size);
return -ENOSYS;
}
/* Lower 16 bit */
ihs_axi_set(priv->map, write_data_lsb, *p & 0xffff);
/* Upper 16 bit */
ihs_axi_set(priv->map, write_data_msb, (*p >> 16) & 0xffff);
ret = ihs_axi_transfer(dev, address, AXI_CMD_WRITE);
if (ret < 0) {
debug("%s: Error during AXI transfer (err = %d)\n",
dev->name, ret);
return ret;
}
return 0;
}
static const struct udevice_id ihs_axi_ids[] = {
{ .compatible = "gdsys,ihs_axi" },
{ /* sentinel */ }
};
static const struct axi_ops ihs_axi_ops = {
.read = ihs_axi_read,
.write = ihs_axi_write,
};
static int ihs_axi_probe(struct udevice *dev)
{
struct ihs_axi_priv *priv = dev_get_priv(dev);
regmap_init_mem(dev_ofnode(dev), &priv->map);
return 0;
}
U_BOOT_DRIVER(ihs_axi_bus) = {
.name = "ihs_axi_bus",
.id = UCLASS_AXI,
.of_match = ihs_axi_ids,
.ops = &ihs_axi_ops,
.priv_auto_alloc_size = sizeof(struct ihs_axi_priv),
.probe = ihs_axi_probe,
};

@ -0,0 +1,123 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* (C) Copyright 2018
* Mario Six, Guntermann & Drunck GmbH, mario.six@gdsys.cc
*/
#include <common.h>
#include <axi.h>
#include <dm.h>
/**
* struct sandbox_store_priv - Private data structure of a AXI store device
* @store: The buffer holding the device's internal memory, which is read from
* and written to using the driver's methods
*/
struct sandbox_store_priv {
u8 *store;
};
/**
* copy_axi_data() - Copy data from source to destination with a given AXI
* transfer width
* @src: Pointer to the data source from where data will be read
* @dst: Pointer to the data destination where data will be written to
* @size: Size of the data to be copied given by a axi_size_t enum value
*
* Return: 0 if OK, -ve on error
*/
static int copy_axi_data(void *src, void *dst, enum axi_size_t size)
{
switch (size) {
case AXI_SIZE_8:
*((u8 *)dst) = *((u8 *)src);
return 0;
case AXI_SIZE_16:
*((u16 *)dst) = be16_to_cpu(*((u16 *)src));
return 0;
case AXI_SIZE_32:
*((u32 *)dst) = be32_to_cpu(*((u32 *)src));
return 0;
default:
debug("%s: Unknown AXI transfer size '%d'\n", __func__, size);
return -EINVAL;
}
}
static int sandbox_store_read(struct udevice *dev, ulong address, void *data,
enum axi_size_t size)
{
struct sandbox_store_priv *priv = dev_get_priv(dev);
return copy_axi_data(priv->store + address, data, size);
}
static int sandbox_store_write(struct udevice *dev, ulong address, void *data,
enum axi_size_t size)
{
struct sandbox_store_priv *priv = dev_get_priv(dev);
return copy_axi_data(data, priv->store + address, size);
}
static int sandbox_store_get_store(struct udevice *dev, u8 **store)
{
struct sandbox_store_priv *priv = dev_get_priv(dev);
*store = priv->store;
return 0;
}
static const struct udevice_id sandbox_store_ids[] = {
{ .compatible = "sandbox,sandbox_store" },
{ /* sentinel */ }
};
static const struct axi_emul_ops sandbox_store_ops = {
.read = sandbox_store_read,
.write = sandbox_store_write,
.get_store = sandbox_store_get_store,
};
static int sandbox_store_probe(struct udevice *dev)
{
struct sandbox_store_priv *priv = dev_get_priv(dev);
u32 reg[2];
int ret;
ret = dev_read_u32_array(dev, "reg", reg, ARRAY_SIZE(reg));
if (ret) {
debug("%s: Could not read 'reg' property\n", dev->name);
return -EINVAL;
}
/*
* Allocate the device's internal storage that will be read
* from/written to
*/
priv->store = calloc(reg[1], 1);
if (!priv->store)
return -ENOMEM;
return 0;
}
static int sandbox_store_remove(struct udevice *dev)
{
struct sandbox_store_priv *priv = dev_get_priv(dev);
free(priv->store);
return 0;
}
U_BOOT_DRIVER(sandbox_axi_store) = {
.name = "sandbox_axi_store",
.id = UCLASS_AXI_EMUL,
.of_match = sandbox_store_ids,
.ops = &sandbox_store_ops,
.priv_auto_alloc_size = sizeof(struct sandbox_store_priv),
.probe = sandbox_store_probe,
.remove = sandbox_store_remove,
};

@ -431,6 +431,17 @@ config ATMEL_HLCD
help
HLCDC supports video output to an attached LCD panel.
config LOGICORE_DP_TX
bool "Enable Logicore DP TX driver"
depends on DISPLAY
help
Enable the driver for the transmitter part of the Xilinx LogiCORE
DisplayPort, a IP core for Xilinx FPGAs that implements a DisplayPort
video interface as defined by VESA DisplayPort v1.2.
Note that this is a pure transmitter device, and has no display
capabilities by itself.
config VIDEO_BROADWELL_IGD
bool "Enable Intel Broadwell integrated graphics device"
depends on X86

@ -4,57 +4,58 @@
# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
ifdef CONFIG_DM
obj-$(CONFIG_BACKLIGHT_GPIO) += backlight_gpio.o
obj-$(CONFIG_BACKLIGHT_PWM) += pwm_backlight.o
obj-$(CONFIG_CONSOLE_NORMAL) += console_normal.o
obj-$(CONFIG_CONSOLE_ROTATION) += console_rotate.o
obj-$(CONFIG_CONSOLE_TRUETYPE) += console_truetype.o fonts/
obj-$(CONFIG_DISPLAY) += display-uclass.o
obj-$(CONFIG_DM_VIDEO) += backlight-uclass.o
obj-$(CONFIG_DM_VIDEO) += panel-uclass.o simple_panel.o
obj-$(CONFIG_DM_VIDEO) += video-uclass.o vidconsole-uclass.o
obj-$(CONFIG_DM_VIDEO) += video_bmp.o
obj-$(CONFIG_BACKLIGHT_PWM) += pwm_backlight.o
obj-$(CONFIG_BACKLIGHT_GPIO) += backlight_gpio.o
obj-$(CONFIG_CONSOLE_NORMAL) += console_normal.o
obj-$(CONFIG_CONSOLE_ROTATION) += console_rotate.o
obj-$(CONFIG_CONSOLE_TRUETYPE) += console_truetype.o fonts/
endif
obj-$(CONFIG_VIDEO_BROADWELL_IGD) += broadwell_igd.o
obj-$(CONFIG_VIDEO_IVYBRIDGE_IGD) += ivybridge_igd.o
obj-${CONFIG_EXYNOS_FB} += exynos/
obj-${CONFIG_VIDEO_ROCKCHIP} += rockchip/
obj-${CONFIG_VIDEO_STM32} += stm32/
obj-${CONFIG_VIDEO_TEGRA124} += tegra124/
obj-$(CONFIG_AM335X_LCD) += am335x-fb.o
obj-$(CONFIG_ATI_RADEON_FB) += ati_radeon_fb.o videomodes.o
obj-$(CONFIG_ATMEL_HLCD) += atmel_hlcdfb.o
obj-$(CONFIG_ATMEL_LCD) += atmel_lcdfb.o
obj-$(CONFIG_CFB_CONSOLE) += cfb_console.o
obj-$(CONFIG_FORMIKE) += formike.o
obj-$(CONFIG_FSL_DIU_FB) += fsl_diu_fb.o videomodes.o
obj-$(CONFIG_VIDEO_FSL_DCU_FB) += fsl_dcu_fb.o videomodes.o
obj-$(CONFIG_LD9040) += ld9040.o
obj-$(CONFIG_LG4573) += lg4573.o
obj-$(CONFIG_LOGICORE_DP_TX) += logicore_dp_tx.o
obj-$(CONFIG_PXA_LCD) += pxa_lcd.o
obj-$(CONFIG_SCF0403_LCD) += scf0403_lcd.o
obj-$(CONFIG_S6E8AX0) += s6e8ax0.o
obj-$(CONFIG_LD9040) += ld9040.o
obj-$(CONFIG_SCF0403_LCD) += scf0403_lcd.o
obj-$(CONFIG_VIDEO_BCM2835) += bcm2835.o
obj-$(CONFIG_VIDEO_BROADWELL_IGD) += broadwell_igd.o
obj-$(CONFIG_VIDEO_COREBOOT) += coreboot.o
obj-$(CONFIG_VIDEO_DA8XX) += da8xx-fb.o videomodes.o
obj-$(CONFIG_VIDEO_DW_HDMI) += dw_hdmi.o
obj-$(CONFIG_VIDEO_EFI) += efi.o
obj-$(CONFIG_VIDEO_FSL_DCU_FB) += fsl_dcu_fb.o videomodes.o
obj-$(CONFIG_VIDEO_IPUV3) += mxc_ipuv3_fb.o ipu_common.o ipu_disp.o
obj-$(CONFIG_VIDEO_IVYBRIDGE_IGD) += ivybridge_igd.o
obj-$(CONFIG_VIDEO_LCD_ANX9804) += anx9804.o
obj-$(CONFIG_VIDEO_LCD_HITACHI_TX18D42VM) += hitachi_tx18d42vm_lcd.o
obj-$(CONFIG_VIDEO_LCD_SSD2828) += ssd2828.o
obj-$(CONFIG_VIDEO_MB862xx) += mb862xx.o videomodes.o
obj-$(CONFIG_VIDEO_MX3) += mx3fb.o videomodes.o
obj-$(CONFIG_VIDEO_IPUV3) += mxc_ipuv3_fb.o ipu_common.o ipu_disp.o
obj-$(CONFIG_VIDEO_MVEBU) += mvebu_lcd.o
obj-$(CONFIG_VIDEO_MX3) += mx3fb.o videomodes.o
obj-$(CONFIG_VIDEO_MXS) += mxsfb.o videomodes.o
obj-$(CONFIG_VIDEO_OMAP3) += omap3_dss.o
obj-$(CONFIG_VIDEO_SANDBOX_SDL) += sandbox_sdl.o
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_FORMIKE) += formike.o
obj-$(CONFIG_LG4573) += lg4573.o
obj-$(CONFIG_AM335X_LCD) += am335x-fb.o
obj-$(CONFIG_VIDEO_DW_HDMI) += dw_hdmi.o
obj-$(CONFIG_VIDEO_SIMPLE) += simplefb.o
obj-${CONFIG_VIDEO_TEGRA124} += tegra124/
obj-${CONFIG_EXYNOS_FB} += exynos/
obj-${CONFIG_VIDEO_ROCKCHIP} += rockchip/
obj-${CONFIG_VIDEO_STM32} += stm32/
obj-y += bridge/
obj-y += sunxi/

@ -0,0 +1,341 @@
/* SPDX-License-Identifier: GPL-2.0+ */
/*
* logicore_dp_dpcd.h
*
* DPCD interface definition for XILINX LogiCore DisplayPort v6.1
* based on Xilinx dp_v3_1 driver sources
*
* (C) Copyright 2016
* Dirk Eibach, Guntermann & Drunck GmbH, dirk.eibach@gdsys.cc
*/
#ifndef __GDSYS_LOGICORE_DP_DPCD_H__
#define __GDSYS_LOGICORE_DP_DPCD_H__
/* receiver capability field */
#define DPCD_REV 0x00000
#define DPCD_MAX_LINK_RATE 0x00001
#define DPCD_MAX_LANE_COUNT 0x00002
#define DPCD_MAX_DOWNSPREAD 0x00003
#define DPCD_NORP_PWR_V_CAP 0x00004
#define DPCD_DOWNSP_PRESENT 0x00005
#define DPCD_ML_CH_CODING_CAP 0x00006
#define DPCD_DOWNSP_COUNT_MSA_OUI 0x00007
#define DPCD_RX_PORT0_CAP_0 0x00008
#define DPCD_RX_PORT0_CAP_1 0x00009
#define DPCD_RX_PORT1_CAP_0 0x0000A
#define DPCD_RX_PORT1_CAP_1 0x0000B
#define DPCD_I2C_SPEED_CTL_CAP 0x0000C
#define DPCD_EDP_CFG_CAP 0x0000D
#define DPCD_TRAIN_AUX_RD_INTERVAL 0x0000E
#define DPCD_ADAPTER_CAP 0x0000F
#define DPCD_FAUX_CAP 0x00020
#define DPCD_MSTM_CAP 0x00021
#define DPCD_NUM_AUDIO_EPS 0x00022
#define DPCD_AV_GRANULARITY 0x00023
#define DPCD_AUD_DEC_LAT_7_0 0x00024
#define DPCD_AUD_DEC_LAT_15_8 0x00025
#define DPCD_AUD_PP_LAT_7_0 0x00026
#define DPCD_AUD_PP_LAT_15_8 0x00027
#define DPCD_VID_INTER_LAT 0x00028
#define DPCD_VID_PROG_LAT 0x00029
#define DPCD_REP_LAT 0x0002A
#define DPCD_AUD_DEL_INS_7_0 0x0002B
#define DPCD_AUD_DEL_INS_15_8 0x0002C
#define DPCD_AUD_DEL_INS_23_16 0x0002D
#define DPCD_GUID 0x00030
#define DPCD_RX_GTC_VALUE_7_0 0x00054
#define DPCD_RX_GTC_VALUE_15_8 0x00055
#define DPCD_RX_GTC_VALUE_23_16 0x00056
#define DPCD_RX_GTC_VALUE_31_24 0x00057
#define DPCD_RX_GTC_MSTR_REQ 0x00058
#define DPCD_RX_GTC_FREQ_LOCK_DONE 0x00059
#define DPCD_DOWNSP_0_CAP 0x00080
#define DPCD_DOWNSP_1_CAP 0x00081
#define DPCD_DOWNSP_2_CAP 0x00082
#define DPCD_DOWNSP_3_CAP 0x00083
#define DPCD_DOWNSP_0_DET_CAP 0x00080
#define DPCD_DOWNSP_1_DET_CAP 0x00084
#define DPCD_DOWNSP_2_DET_CAP 0x00088
#define DPCD_DOWNSP_3_DET_CAP 0x0008C
/* link configuration field */
#define DPCD_LINK_BW_SET 0x00100
#define DPCD_LANE_COUNT_SET 0x00101
#define DPCD_TP_SET 0x00102
#define DPCD_TRAINING_LANE0_SET 0x00103
#define DPCD_TRAINING_LANE1_SET 0x00104
#define DPCD_TRAINING_LANE2_SET 0x00105
#define DPCD_TRAINING_LANE3_SET 0x00106
#define DPCD_DOWNSPREAD_CTRL 0x00107
#define DPCD_ML_CH_CODING_SET 0x00108
#define DPCD_I2C_SPEED_CTL_SET 0x00109
#define DPCD_EDP_CFG_SET 0x0010A
#define DPCD_LINK_QUAL_LANE0_SET 0x0010B
#define DPCD_LINK_QUAL_LANE1_SET 0x0010C
#define DPCD_LINK_QUAL_LANE2_SET 0x0010D
#define DPCD_LINK_QUAL_LANE3_SET 0x0010E
#define DPCD_TRAINING_LANE0_1_SET2 0x0010F
#define DPCD_TRAINING_LANE2_3_SET2 0x00110
#define DPCD_MSTM_CTRL 0x00111
#define DPCD_AUDIO_DELAY_7_0 0x00112
#define DPCD_AUDIO_DELAY_15_8 0x00113
#define DPCD_AUDIO_DELAY_23_6 0x00114
#define DPCD_UPSTREAM_DEVICE_DP_PWR_NEED 0x00118
#define DPCD_FAUX_MODE_CTRL 0x00120
#define DPCD_FAUX_FORWARD_CH_DRIVE_SET 0x00121
#define DPCD_BACK_CH_STATUS 0x00122
#define DPCD_FAUX_BACK_CH_SYMBOL_ERROR_COUNT 0x00123
#define DPCD_FAUX_BACK_CH_TRAINING_PATTERN_TIME 0x00125
#define DPCD_TX_GTC_VALUE_7_0 0x00154
#define DPCD_TX_GTC_VALUE_15_8 0x00155
#define DPCD_TX_GTC_VALUE_23_16 0x00156
#define DPCD_TX_GTC_VALUE_31_24 0x00157
#define DPCD_RX_GTC_VALUE_PHASE_SKEW_EN 0x00158
#define DPCD_TX_GTC_FREQ_LOCK_DONE 0x00159
#define DPCD_ADAPTER_CTRL 0x001A0
#define DPCD_BRANCH_DEVICE_CTRL 0x001A1
#define DPCD_PAYLOAD_ALLOCATE_SET 0x001C0
#define DPCD_PAYLOAD_ALLOCATE_START_TIME_SLOT 0x001C1
#define DPCD_PAYLOAD_ALLOCATE_TIME_SLOT_COUNT 0x001C2
/* link/sink status field */
#define DPCD_SINK_COUNT 0x00200
#define DPCD_DEVICE_SERVICE_IRQ 0x00201
#define DPCD_STATUS_LANE_0_1 0x00202
#define DPCD_STATUS_LANE_2_3 0x00203
#define DPCD_LANE_ALIGN_STATUS_UPDATED 0x00204
#define DPCD_SINK_STATUS 0x00205
#define DPCD_ADJ_REQ_LANE_0_1 0x00206
#define DPCD_ADJ_REQ_LANE_2_3 0x00207
#define DPCD_TRAINING_SCORE_LANE_0 0x00208
#define DPCD_TRAINING_SCORE_LANE_1 0x00209
#define DPCD_TRAINING_SCORE_LANE_2 0x0020A
#define DPCD_TRAINING_SCORE_LANE_3 0x0020B
#define DPCD_ADJ_REQ_PC2 0x0020C
#define DPCD_FAUX_FORWARD_CH_SYMBOL_ERROR_COUNT 0x0020D
#define DPCD_SYMBOL_ERROR_COUNT_LANE_0 0x00210
#define DPCD_SYMBOL_ERROR_COUNT_LANE_1 0x00212
#define DPCD_SYMBOL_ERROR_COUNT_LANE_2 0x00214
#define DPCD_SYMBOL_ERROR_COUNT_LANE_3 0x00216
/* automated testing sub-field */
#define DPCD_FAUX_FORWARD_CH_STATUS 0x00280
#define DPCD_FAUX_BACK_CH_DRIVE_SET 0x00281
#define DPCD_FAUX_BACK_CH_SYM_ERR_COUNT_CTRL 0x00282
#define DPCD_PAYLOAD_TABLE_UPDATE_STATUS 0x002C0
#define DPCD_VC_PAYLOAD_ID_SLOT(slotnum) \
(DPCD_PAYLOAD_TABLE_UPDATE_STATUS + slotnum)
/* sink control field */
#define DPCD_SET_POWER_DP_PWR_VOLTAGE 0x00600
/* sideband message buffers */
#define DPCD_DOWN_REQ 0x01000
#define DPCD_UP_REP 0x01200
#define DPCD_DOWN_REP 0x01400
#define DPCD_UP_REQ 0x01600
/* event status indicator field */
#define DPCD_SINK_COUNT_ESI 0x02002
#define DPCD_SINK_DEVICE_SERVICE_IRQ_VECTOR_ESI0 0x02003
#define DPCD_SINK_DEVICE_SERVICE_IRQ_VECTOR_ESI1 0x02004
#define DPCD_SINK_LINK_SERVICE_IRQ_VECTOR_ESI0 0x02005
#define DPCD_SINK_LANE0_1_STATUS 0x0200C
#define DPCD_SINK_LANE2_3_STATUS 0x0200D
#define DPCD_SINK_ALIGN_STATUS_UPDATED_ESI 0x0200E
#define DPCD_SINK_STATUS_ESI 0x0200F
/*
* field addresses and sizes.
*/
#define DPCD_RECEIVER_CAP_FIELD_START DPCD_REV
#define DPCD_RECEIVER_CAP_FIELD_SIZE 0x100
#define DPCD_LINK_CFG_FIELD_START DPCD_LINK_BW_SET
#define DPCD_LINK_CFG_FIELD_SIZE 0x100
#define DPCD_LINK_SINK_STATUS_FIELD_START DPCD_SINK_COUNT
#define DPCD_LINK_SINK_STATUS_FIELD_SIZE 0x17
/* 0x00000: DPCD_REV */
#define DPCD_REV_MNR_MASK 0x0F
#define DPCD_REV_MJR_MASK 0xF0
#define DPCD_REV_MJR_SHIFT 4
/* 0x00001: MAX_LINK_RATE */
#define DPCD_MAX_LINK_RATE_162GBPS 0x06
#define DPCD_MAX_LINK_RATE_270GBPS 0x0A
#define DPCD_MAX_LINK_RATE_540GBPS 0x14
/* 0x00002: MAX_LANE_COUNT */
#define DPCD_MAX_LANE_COUNT_MASK 0x1F
#define DPCD_MAX_LANE_COUNT_1 0x01
#define DPCD_MAX_LANE_COUNT_2 0x02
#define DPCD_MAX_LANE_COUNT_4 0x04
#define DPCD_TPS3_SUPPORT_MASK 0x40
#define DPCD_ENHANCED_FRAME_SUPPORT_MASK 0x80
/* 0x00003: MAX_DOWNSPREAD */
#define DPCD_MAX_DOWNSPREAD_MASK 0x01
#define DPCD_NO_AUX_HANDSHAKE_LINK_TRAIN_MASK 0x40
/* 0x00005: DOWNSP_PRESENT */
#define DPCD_DOWNSP_PRESENT_MASK 0x01
#define DPCD_DOWNSP_TYPE_MASK 0x06
#define DPCD_DOWNSP_TYPE_SHIFT 1
#define DPCD_DOWNSP_TYPE_DP 0x0
#define DPCD_DOWNSP_TYPE_AVGA_ADVII 0x1
#define DPCD_DOWNSP_TYPE_DVI_HDMI_DPPP 0x2
#define DPCD_DOWNSP_TYPE_OTHERS 0x3
#define DPCD_DOWNSP_FORMAT_CONV_MASK 0x08
#define DPCD_DOWNSP_DCAP_INFO_AVAIL_MASK 0x10
/* 0x00006, 0x00108: ML_CH_CODING_SUPPORT, ML_CH_CODING_SET */
#define DPCD_ML_CH_CODING_MASK 0x01
/* 0x00007: DOWNSP_COUNT_MSA_OUI */
#define DPCD_DOWNSP_COUNT_MASK 0x0F
#define DPCD_MSA_TIMING_PAR_IGNORED_MASK 0x40
#define DPCD_OUI_SUPPORT_MASK 0x80
/* 0x00008, 0x0000A: RX_PORT[0-1]_CAP_0 */
#define DPCD_RX_PORTX_CAP_0_LOCAL_EDID_PRESENT_MASK 0x02
#define DPCD_RX_PORTX_CAP_0_ASSOC_TO_PRECEDING_PORT_MASK 0x04
/* 0x0000C, 0x00109: I2C_SPEED_CTL_CAP, I2C_SPEED_CTL_SET */
#define DPCD_I2C_SPEED_CTL_NONE 0x00
#define DPCD_I2C_SPEED_CTL_1KBIPS 0x01
#define DPCD_I2C_SPEED_CTL_5KBIPS 0x02
#define DPCD_I2C_SPEED_CTL_10KBIPS 0x04
#define DPCD_I2C_SPEED_CTL_100KBIPS 0x08
#define DPCD_I2C_SPEED_CTL_400KBIPS 0x10
#define DPCD_I2C_SPEED_CTL_1MBIPS 0x20
/* 0x0000E: TRAIN_AUX_RD_INTERVAL */
#define DPCD_TRAIN_AUX_RD_INT_100_400US 0x00
#define DPCD_TRAIN_AUX_RD_INT_4MS 0x01
#define DPCD_TRAIN_AUX_RD_INT_8MS 0x02
#define DPCD_TRAIN_AUX_RD_INT_12MS 0x03
#define DPCD_TRAIN_AUX_RD_INT_16MS 0x04
/* 0x00020: DPCD_FAUX_CAP */
#define DPCD_FAUX_CAP_MASK 0x01
/* 0x00021: MSTM_CAP */
#define DPCD_MST_CAP_MASK 0x01
/* 0x00080, 0x00081|4, 0x00082|8, 0x00083|C: DOWNSP_X_(DET_)CAP */
#define DPCD_DOWNSP_X_CAP_TYPE_MASK 0x07
#define DPCD_DOWNSP_X_CAP_TYPE_DP 0x0
#define DPCD_DOWNSP_X_CAP_TYPE_AVGA 0x1
#define DPCD_DOWNSP_X_CAP_TYPE_DVI 0x2
#define DPCD_DOWNSP_X_CAP_TYPE_HDMI 0x3
#define DPCD_DOWNSP_X_CAP_TYPE_OTHERS 0x4
#define DPCD_DOWNSP_X_CAP_TYPE_DPPP 0x5
#define DPCD_DOWNSP_X_CAP_HPD_MASK 0x80
#define DPCD_DOWNSP_X_CAP_NON_EDID_ATTR_MASK 0xF0
#define DPCD_DOWNSP_X_CAP_NON_EDID_ATTR_SHIFT 4
#define DPCD_DOWNSP_X_CAP_NON_EDID_ATTR_720_480_I_60 0x1
#define DPCD_DOWNSP_X_CAP_NON_EDID_ATTR_720_480_I_50 0x2
#define DPCD_DOWNSP_X_CAP_NON_EDID_ATTR_1920_1080_I_60 0x3
#define DPCD_DOWNSP_X_CAP_NON_EDID_ATTR_1920_1080_I_50 0x4
#define DPCD_DOWNSP_X_CAP_NON_EDID_ATTR_1280_720_P_60 0x5
#define DPCD_DOWNSP_X_CAP_NON_EDID_ATTR_1280_720_P_50 0x7
/* 0x00082, 0x00086, 0x0008A, 0x0008E: DOWNSP_X_(DET_)CAP2 */
#define DPCD_DOWNSP_X_DCAP_MAX_BPC_MASK 0x03
#define DPCD_DOWNSP_X_DCAP_MAX_BPC_8 0x0
#define DPCD_DOWNSP_X_DCAP_MAX_BPC_10 0x1
#define DPCD_DOWNSP_X_DCAP_MAX_BPC_12 0x2
#define DPCD_DOWNSP_X_DCAP_MAX_BPC_16 0x3
/* 0x00082, 0x00086, 0x0008A, 0x0008E: DOWNSP_X_(DET_)CAP2 */
#define DPCD_DOWNSP_X_DCAP_HDMI_DPPP_FS2FP_MASK 0x01
#define DPCD_DOWNSP_X_DCAP_DVI_DL_MASK 0x02
#define DPCD_DOWNSP_X_DCAP_DVI_HCD_MASK 0x04
/* link configuration field masks, shifts, and register values */
/* 0x00100: DPCD_LINK_BW_SET */
#define DPCD_LINK_BW_SET_162GBPS 0x06
#define DPCD_LINK_BW_SET_270GBPS 0x0A
#define DPCD_LINK_BW_SET_540GBPS 0x14
/* 0x00101: LANE_COUNT_SET */
#define DPCD_LANE_COUNT_SET_MASK 0x1F
#define DPCD_LANE_COUNT_SET_1 0x01
#define DPCD_LANE_COUNT_SET_2 0x02
#define DPCD_LANE_COUNT_SET_4 0x04
#define DPCD_ENHANCED_FRAME_EN_MASK 0x80
/* 0x00102: TP_SET */
#define DPCD_TP_SEL_MASK 0x03
#define DPCD_TP_SEL_OFF 0x0
#define DPCD_TP_SEL_TP1 0x1
#define DPCD_TP_SEL_TP2 0x2
#define DPCD_TP_SEL_TP3 0x3
#define DPCD_TP_SET_LQP_MASK 0x06
#define DPCD_TP_SET_LQP_SHIFT 2
#define DPCD_TP_SET_LQP_OFF 0x0
#define DPCD_TP_SET_LQP_D102_TEST 0x1
#define DPCD_TP_SET_LQP_SER_MES 0x2
#define DPCD_TP_SET_LQP_PRBS7 0x3
#define DPCD_TP_SET_REC_CLK_OUT_EN_MASK 0x10
#define DPCD_TP_SET_SCRAMB_DIS_MASK 0x20
#define DPCD_TP_SET_SE_COUNT_SEL_MASK 0xC0
#define DPCD_TP_SET_SE_COUNT_SEL_SHIFT 6
#define DPCD_TP_SET_SE_COUNT_SEL_DE_ISE 0x0
#define DPCD_TP_SET_SE_COUNT_SEL_DE 0x1
#define DPCD_TP_SET_SE_COUNT_SEL_ISE 0x2
/* 0x00103-0x00106: TRAINING_LANE[0-3]_SET */
#define DPCD_TRAINING_LANEX_SET_VS_MASK 0x03
#define DPCD_TRAINING_LANEX_SET_MAX_VS_MASK 0x04
#define DPCD_TRAINING_LANEX_SET_PE_MASK 0x18
#define DPCD_TRAINING_LANEX_SET_PE_SHIFT 3
#define DPCD_TRAINING_LANEX_SET_MAX_PE_MASK 0x20
/* 0x00107: DOWNSPREAD_CTRL */
#define DPCD_SPREAD_AMP_MASK 0x10
#define DPCD_MSA_TIMING_PAR_IGNORED_EN_MASK 0x80
/* 0x00108: ML_CH_CODING_SET - Same as 0x00006: ML_CH_CODING_SUPPORT */
/* 0x00109: I2C_SPEED_CTL_SET - Same as 0x0000C: I2C_SPEED_CTL_CAP */
/* 0x0010F-0x00110: TRAINING_LANE[0_1-2_3]_SET2 */
#define DPCD_TRAINING_LANE_0_2_SET_PC2_MASK 0x03
#define DPCD_TRAINING_LANE_0_2_SET_MAX_PC2_MASK 0x04
#define DPCD_TRAINING_LANE_1_3_SET_PC2_MASK 0x30
#define DPCD_TRAINING_LANE_1_3_SET_PC2_SHIFT 4
#define DPCD_TRAINING_LANE_1_3_SET_MAX_PC2_MASK 0x40
/* 0x00111: MSTM_CTRL */
#define DPCD_MST_EN_MASK 0x01
#define DPCD_UP_REQ_EN_MASK 0x02
#define DPCD_UP_IS_SRC_MASK 0x03
/* link/sink status field masks, shifts, and register values */
/* 0x00200: SINK_COUNT */
#define DPCD_SINK_COUNT_LOW_MASK 0x3F
#define DPCD_SINK_CP_READY_MASK 0x40
#define DPCD_SINK_COUNT_HIGH_MASK 0x80
#define DPCD_SINK_COUNT_HIGH_LOW_SHIFT 1
/* 0x00202: STATUS_LANE_0_1 */
#define DPCD_STATUS_LANE_0_CR_DONE_MASK 0x01
#define DPCD_STATUS_LANE_0_CE_DONE_MASK 0x02
#define DPCD_STATUS_LANE_0_SL_DONE_MASK 0x04
#define DPCD_STATUS_LANE_1_CR_DONE_MASK 0x10
#define DPCD_STATUS_LANE_1_CE_DONE_MASK 0x20
#define DPCD_STATUS_LANE_1_SL_DONE_MASK 0x40
/* 0x00202: STATUS_LANE_2_3 */
#define DPCD_STATUS_LANE_2_CR_DONE_MASK 0x01
#define DPCD_STATUS_LANE_2_CE_DONE_MASK 0x02
#define DPCD_STATUS_LANE_2_SL_DONE_MASK 0x04
#define DPCD_STATUS_LANE_3_CR_DONE_MASK 0x10
#define DPCD_STATUS_LANE_3_CE_DONE_MASK 0x20
#define DPCD_STATUS_LANE_3_SL_DONE_MASK 0x40
/* 0x00204: LANE_ALIGN_STATUS_UPDATED */
#define DPCD_LANE_ALIGN_STATUS_UPDATED_IA_DONE_MASK \
0x01
#define DPCD_LANE_ALIGN_STATUS_UPDATED_DOWNSP_STATUS_CHANGED_MASK \
0x40
#define DPCD_LANE_ALIGN_STATUS_UPDATED_LINK_STATUS_UPDATED_MASK \
0x80
/* 0x00205: SINK_STATUS */
#define DPCD_SINK_STATUS_RX_PORT0_SYNC_STATUS_MASK 0x01
#define DPCD_SINK_STATUS_RX_PORT1_SYNC_STATUS_MASK 0x02
/* 0x00206, 0x00207: ADJ_REQ_LANE_[0,2]_[1,3] */
#define DPCD_ADJ_REQ_LANE_0_2_VS_MASK 0x03
#define DPCD_ADJ_REQ_LANE_0_2_PE_MASK 0x0C
#define DPCD_ADJ_REQ_LANE_0_2_PE_SHIFT 2
#define DPCD_ADJ_REQ_LANE_1_3_VS_MASK 0x30
#define DPCD_ADJ_REQ_LANE_1_3_VS_SHIFT 4
#define DPCD_ADJ_REQ_LANE_1_3_PE_MASK 0xC0
#define DPCD_ADJ_REQ_LANE_1_3_PE_SHIFT 6
/* 0x0020C: ADJ_REQ_PC2 */
#define DPCD_ADJ_REQ_PC2_LANE_0_MASK 0x03
#define DPCD_ADJ_REQ_PC2_LANE_1_MASK 0x0C
#define DPCD_ADJ_REQ_PC2_LANE_1_SHIFT 2
#define DPCD_ADJ_REQ_PC2_LANE_2_MASK 0x30
#define DPCD_ADJ_REQ_PC2_LANE_2_SHIFT 4
#define DPCD_ADJ_REQ_PC2_LANE_3_MASK 0xC0
#define DPCD_ADJ_REQ_PC2_LANE_3_SHIFT 6
#endif /* __GDSYS_LOGICORE_DP_DPCD_H__ */

File diff suppressed because it is too large Load Diff

@ -0,0 +1,54 @@
/* SPDX-License-Identifier: GPL-2.0+ */
/*
* logicore_dp_tx.h
*
* Driver for XILINX LogiCore DisplayPort v6.1 TX (Source)
*
* (C) Copyright 2016
* Dirk Eibach, Guntermann & Drunck GmbH, dirk.eibach@gdsys.cc
*/
#ifndef __GDSYS_LOGICORE_DP_TX_H__
#define __GDSYS_LOGICORE_DP_TX_H__
/*
* struct logicore_dp_tx_msa - Main Stream Attributes (MSA)
* @pixel_clock_hz: The pixel clock of the stream (in Hz)
* @bits_per_color: Number of bits per color component
* @h_active: Horizontal active resolution (pixels)
* @h_start: Horizontal blank start (in pixels)
* @h_sync_polarity: Horizontal sync polarity
* (0 = negative | 1 = positive)
* @h_sync_width: Horizontal sync width (pixels)
* @h_total: Horizontal total (pixels)
* @v_active: Vertical active resolution (lines)
* @v_start: Vertical blank start (in lines).
* @v_sync_polarity: Vertical sync polarity
* (0 = negative | 1 = positive)
* @v_sync_width: Vertical sync width (lines)
* @v_total: Vertical total (lines)
* @override_user_pixel_width: If true, the value stored for user_pixel_width
* will be used as the pixel width.
* @user_pixel_width: The width of the user data input port.
*
* This is a stripped down version of struct main_stream_attributes that
* contains only the parameters that are not set by cfg_msa_recalculate()
*/
struct logicore_dp_tx_msa {
u32 pixel_clock_hz;
u32 bits_per_color;
u16 h_active;
u32 h_start;
bool h_sync_polarity;
u16 h_sync_width;
u16 h_total;
u16 v_active;
u32 v_start;
bool v_sync_polarity;
u16 v_sync_width;
u16 v_total;
bool override_user_pixel_width;
u32 user_pixel_width;
};
#endif /* __GDSYS_LOGICORE_DP_TX_H__ */

@ -0,0 +1,396 @@
/* SPDX-License-Identifier: GPL-2.0+ */
/*
* logicore_dp_tx_regif.h
*
* Register interface definition for XILINX LogiCore DisplayPort v6.1 TX
* (Source) based on Xilinx dp_v3_1 driver sources
*
* (C) Copyright 2016
* Dirk Eibach, Guntermann & Drunck GmbH, dirk.eibach@gdsys.cc
*/
#ifndef __GDSYS_LOGICORE_DP_TX_REGIF_H__
#define __GDSYS_LOGICORE_DP_TX_REGIF_H__
enum {
/* link configuration field */
REG_LINK_BW_SET = 0x000,
REG_LANE_COUNT_SET = 0x004,
REG_ENHANCED_FRAME_EN = 0x008,
REG_TRAINING_PATTERN_SET = 0x00C,
REG_LINK_QUAL_PATTERN_SET = 0x010,
REG_SCRAMBLING_DISABLE = 0x014,
REG_DOWNSPREAD_CTRL = 0x018,
REG_SOFT_RESET = 0x01C,
};
enum {
/* core enables */
REG_ENABLE = 0x080,
REG_ENABLE_MAIN_STREAM = 0x084,
REG_ENABLE_SEC_STREAM = 0x088,
REG_FORCE_SCRAMBLER_RESET = 0x0C0,
REG_MST_CONFIG = 0x0D0,
REG_LINE_RESET_DISABLE = 0x0F0,
};
enum {
/* core ID */
REG_VERSION = 0x0F8,
REG_CORE_ID = 0x0FC,
};
enum {
/* AUX channel interface */
REG_AUX_CMD = 0x100,
REG_AUX_WRITE_FIFO = 0x104,
REG_AUX_ADDRESS = 0x108,
REG_AUX_CLK_DIVIDER = 0x10C,
REG_USER_FIFO_OVERFLOW = 0x110,
REG_INTERRUPT_SIG_STATE = 0x130,
REG_AUX_REPLY_DATA = 0x134,
REG_AUX_REPLY_CODE = 0x138,
REG_AUX_REPLY_COUNT = 0x13C,
REG_INTERRUPT_STATUS = 0x140,
REG_INTERRUPT_MASK = 0x144,
REG_REPLY_DATA_COUNT = 0x148,
REG_REPLY_STATUS = 0x14C,
REG_HPD_DURATION = 0x150,
};
enum {
/* main stream attributes for SST / MST STREAM1 */
REG_STREAM1_MSA_START = 0x180,
REG_MAIN_STREAM_HTOTAL = 0x180,
REG_MAIN_STREAM_VTOTAL = 0x184,
REG_MAIN_STREAM_POLARITY = 0x188,
REG_MAIN_STREAM_HSWIDTH = 0x18C,
REG_MAIN_STREAM_VSWIDTH = 0x190,
REG_MAIN_STREAM_HRES = 0x194,
REG_MAIN_STREAM_VRES = 0x198,
REG_MAIN_STREAM_HSTART = 0x19C,
REG_MAIN_STREAM_VSTART = 0x1A0,
REG_MAIN_STREAM_MISC0 = 0x1A4,
REG_MAIN_STREAM_MISC1 = 0x1A8,
REG_M_VID = 0x1AC,
REG_TU_SIZE = 0x1B0,
REG_N_VID = 0x1B4,
REG_USER_PIXEL_WIDTH = 0x1B8,
REG_USER_DATA_COUNT_PER_LANE = 0x1BC,
REG_MAIN_STREAM_INTERLACED = 0x1C0,
REG_MIN_BYTES_PER_TU = 0x1C4,
REG_FRAC_BYTES_PER_TU = 0x1C8,
REG_INIT_WAIT = 0x1CC,
REG_STREAM1 = 0x1D0,
REG_STREAM2 = 0x1D4,
REG_STREAM3 = 0x1D8,
REG_STREAM4 = 0x1DC,
};
enum {
/* PHY configuration status */
REG_PHY_CONFIG = 0x200,
REG_PHY_VOLTAGE_DIFF_LANE_0 = 0x220,
REG_PHY_VOLTAGE_DIFF_LANE_1 = 0x224,
REG_PHY_VOLTAGE_DIFF_LANE_2 = 0x228,
REG_PHY_VOLTAGE_DIFF_LANE_3 = 0x22C,
REG_PHY_TRANSMIT_PRBS7 = 0x230,
REG_PHY_CLOCK_SELECT = 0x234,
REG_PHY_POWER_DOWN = 0x238,
REG_PHY_PRECURSOR_LANE_0 = 0x23C,
REG_PHY_PRECURSOR_LANE_1 = 0x240,
REG_PHY_PRECURSOR_LANE_2 = 0x244,
REG_PHY_PRECURSOR_LANE_3 = 0x248,
REG_PHY_POSTCURSOR_LANE_0 = 0x24C,
REG_PHY_POSTCURSOR_LANE_1 = 0x250,
REG_PHY_POSTCURSOR_LANE_2 = 0x254,
REG_PHY_POSTCURSOR_LANE_3 = 0x258,
REG_PHY_STATUS = 0x280,
REG_GT_DRP_COMMAND = 0x2A0,
REG_GT_DRP_READ_DATA = 0x2A4,
REG_GT_DRP_CHANNEL_STATUS = 0x2A8,
};
enum {
/* DisplayPort audio */
REG_AUDIO_CONTROL = 0x300,
REG_AUDIO_CHANNELS = 0x304,
REG_AUDIO_INFO_DATA = 0x308,
REG_AUDIO_MAUD = 0x328,
REG_AUDIO_NAUD = 0x32C,
REG_AUDIO_EXT_DATA = 0x330,
};
enum {
/* HDCP */
REG_HDCP_ENABLE = 0x400,
};
enum {
/* main stream attributes for MST STREAM2, 3, and 4 */
REG_STREAM2_MSA_START = 0x500,
REG_STREAM3_MSA_START = 0x550,
REG_STREAM4_MSA_START = 0x5A0,
REG_VC_PAYLOAD_BUFFER_ADDR = 0x800,
};
enum {
LINK_BW_SET_162GBPS = 0x06,
LINK_BW_SET_270GBPS = 0x0A,
LINK_BW_SET_540GBPS = 0x14,
};
enum {
LANE_COUNT_SET_1 = 0x1,
LANE_COUNT_SET_2 = 0x2,
LANE_COUNT_SET_4 = 0x4,
};
enum {
TRAINING_PATTERN_SET_OFF = 0x0,
/* training pattern 1 used for clock recovery */
TRAINING_PATTERN_SET_TP1 = 0x1,
/* training pattern 2 used for channel equalization */
TRAINING_PATTERN_SET_TP2 = 0x2,
/*
* training pattern 3 used for channel equalization for cores with DP
* v1.2
*/
TRAINING_PATTERN_SET_TP3 = 0x3,
};
enum {
LINK_QUAL_PATTERN_SET_OFF = 0x0,
/* D10.2 unscrambled test pattern transmitted */
LINK_QUAL_PATTERN_SET_D102_TEST = 0x1,
/* symbol error rate measurement pattern transmitted */
LINK_QUAL_PATTERN_SET_SER_MES = 0x2,
/* pseudo random bit sequence 7 transmitted */
LINK_QUAL_PATTERN_SET_PRBS7 = 0x3,
};
enum {
SOFT_RESET_VIDEO_STREAM1_MASK = 0x00000001,
SOFT_RESET_VIDEO_STREAM2_MASK = 0x00000002,
SOFT_RESET_VIDEO_STREAM3_MASK = 0x00000004,
SOFT_RESET_VIDEO_STREAM4_MASK = 0x00000008,
SOFT_RESET_AUX_MASK = 0x00000080,
SOFT_RESET_VIDEO_STREAM_ALL_MASK = 0x0000000F,
};
enum {
MST_CONFIG_MST_EN_MASK = 0x00000001,
};
enum {
LINE_RESET_DISABLE_MASK = 0x1,
};
#define AUX_CMD_NBYTES_TRANSFER_MASK 0x0000000F
#define AUX_CMD_SHIFT 8
#define AUX_CMD_MASK 0x00000F00
enum {
AUX_CMD_I2C_WRITE = 0x0,
AUX_CMD_I2C_READ = 0x1,
AUX_CMD_I2C_WRITE_STATUS = 0x2,
AUX_CMD_I2C_WRITE_MOT = 0x4,
AUX_CMD_I2C_READ_MOT = 0x5,
AUX_CMD_I2C_WRITE_STATUS_MOT = 0x6,
AUX_CMD_WRITE = 0x8,
AUX_CMD_READ = 0x9,
};
#define AUX_CLK_DIVIDER_VAL_MASK 0x00FF
#define AUX_CLK_DIVIDER_AUX_SIG_WIDTH_FILT_SHIFT 8
#define AUX_CLK_DIVIDER_AUX_SIG_WIDTH_FILT_MASK 0xFF00
enum {
INTERRUPT_SIG_STATE_HPD_STATE_MASK = 0x00000001,
INTERRUPT_SIG_STATE_REQUEST_STATE_MASK = 0x00000002,
INTERRUPT_SIG_STATE_REPLY_STATE_MASK = 0x00000004,
INTERRUPT_SIG_STATE_REPLY_TIMEOUT_MASK = 0x00000008,
};
enum {
AUX_REPLY_CODE_ACK = 0x0,
AUX_REPLY_CODE_I2C_ACK = 0x0,
AUX_REPLY_CODE_NACK = 0x1,
AUX_REPLY_CODE_DEFER = 0x2,
AUX_REPLY_CODE_I2C_NACK = 0x4,
AUX_REPLY_CODE_I2C_DEFER = 0x8,
};
enum {
INTERRUPT_STATUS_HPD_IRQ_MASK = 0x00000001,
INTERRUPT_STATUS_HPD_EVENT_MASK = 0x00000002,
INTERRUPT_STATUS_REPLY_RECEIVED_MASK = 0x00000004,
INTERRUPT_STATUS_REPLY_TIMEOUT_MASK = 0x00000008,
INTERRUPT_STATUS_HPD_PULSE_DETECTED_MASK = 0x00000010,
INTERRUPT_STATUS_EXT_PKT_TXD_MASK = 0x00000020,
};
enum {
INTERRUPT_MASK_HPD_IRQ_MASK = 0x00000001,
INTERRUPT_MASK_HPD_EVENT_MASK = 0x00000002,
INTERRUPT_MASK_REPLY_RECEIVED_MASK = 0x00000004,
INTERRUPT_MASK_REPLY_TIMEOUT_MASK = 0x00000008,
INTERRUPT_MASK_HPD_PULSE_DETECTED_MASK = 0x00000010,
INTERRUPT_MASK_EXT_PKT_TXD_MASK = 0x00000020,
};
#define REPLY_STATUS_REPLY_STATUS_STATE_SHIFT 4
#define REPLY_STATUS_REPLY_STATUS_STATE_MASK 0x00000FF0
enum {
REPLY_STATUS_REPLY_RECEIVED_MASK = 0x00000001,
REPLY_STATUS_REPLY_IN_PROGRESS_MASK = 0x00000002,
REPLY_STATUS_REQUEST_IN_PROGRESS_MASK = 0x00000004,
REPLY_STATUS_REPLY_ERROR_MASK = 0x00000008,
};
#define MAIN_STREAMX_POLARITY_VSYNC_POL_SHIFT 1
enum {
MAIN_STREAMX_POLARITY_HSYNC_POL_MASK = 0x00000001,
MAIN_STREAMX_POLARITY_VSYNC_POL_MASK = 0x00000002,
};
enum {
MAIN_STREAMX_MISC0_SYNC_CLK_MASK = 0x00000001,
};
#define MAIN_STREAMX_MISC0_COMPONENT_FORMAT_SHIFT 1
#define MAIN_STREAMX_MISC0_COMPONENT_FORMAT_MASK 0x00000006
enum {
MAIN_STREAMX_MISC0_COMPONENT_FORMAT_RGB = 0x0,
MAIN_STREAMX_MISC0_COMPONENT_FORMAT_YCBCR422 = 0x1,
MAIN_STREAMX_MISC0_COMPONENT_FORMAT_YCBCR444 = 0x2,
};
#define MAIN_STREAMX_MISC0_DYNAMIC_RANGE_SHIFT 3
#define MAIN_STREAMX_MISC0_DYNAMIC_RANGE_MASK 0x00000008
#define MAIN_STREAMX_MISC0_YCBCR_COLORIMETRY_SHIFT 4
#define MAIN_STREAMX_MISC0_YCBCR_COLORIMETRY_MASK 0x00000010
#define MAIN_STREAMX_MISC0_BDC_SHIFT 5
#define MAIN_STREAMX_MISC0_BDC_MASK 0x000000E0
enum {
MAIN_STREAMX_MISC0_BDC_6BPC = 0x0,
MAIN_STREAMX_MISC0_BDC_8BPC = 0x1,
MAIN_STREAMX_MISC0_BDC_10BPC = 0x2,
MAIN_STREAMX_MISC0_BDC_12BPC = 0x3,
MAIN_STREAMX_MISC0_BDC_16BPC = 0x4,
};
enum {
PHY_CONFIG_PHY_RESET_ENABLE_MASK = 0x0000000,
PHY_CONFIG_PHY_RESET_MASK = 0x0000001,
PHY_CONFIG_GTTX_RESET_MASK = 0x0000002,
PHY_CONFIG_GT_ALL_RESET_MASK = 0x0000003,
PHY_CONFIG_TX_PHY_PMA_RESET_MASK = 0x0000100,
PHY_CONFIG_TX_PHY_PCS_RESET_MASK = 0x0000200,
PHY_CONFIG_TX_PHY_POLARITY_MASK = 0x0000800,
PHY_CONFIG_TX_PHY_PRBSFORCEERR_MASK = 0x0001000,
PHY_CONFIG_TX_PHY_POLARITY_IND_LANE_MASK = 0x0010000,
PHY_CONFIG_TX_PHY_POLARITY_LANE0_MASK = 0x0020000,
PHY_CONFIG_TX_PHY_POLARITY_LANE1_MASK = 0x0040000,
PHY_CONFIG_TX_PHY_POLARITY_LANE2_MASK = 0x0080000,
PHY_CONFIG_TX_PHY_POLARITY_LANE3_MASK = 0x0100000,
PHY_CONFIG_TX_PHY_8B10BEN_MASK = 0x0200000,
};
#define PHY_CONFIG_TX_PHY_LOOPBACK_SHIFT 13
#define PHY_CONFIG_TX_PHY_LOOPBACK_MASK 0x000E000
enum {
PHY_CLOCK_SELECT_162GBPS = 0x1,
PHY_CLOCK_SELECT_270GBPS = 0x3,
PHY_CLOCK_SELECT_540GBPS = 0x5,
};
enum {
VS_LEVEL_0 = 0x2,
VS_LEVEL_1 = 0x5,
VS_LEVEL_2 = 0x8,
VS_LEVEL_3 = 0xF,
VS_LEVEL_OFFSET = 0x4,
};
enum {
PE_LEVEL_0 = 0x00,
PE_LEVEL_1 = 0x0E,
PE_LEVEL_2 = 0x14,
PE_LEVEL_3 = 0x1B,
};
enum {
PHY_STATUS_RESET_LANE_2_3_DONE_SHIFT = 2,
PHY_STATUS_TX_ERROR_LANE_0_SHIFT = 18,
PHY_STATUS_TX_BUFFER_STATUS_LANE_1_SHIFT = 20,
PHY_STATUS_TX_ERROR_LANE_1_SHIFT = 22,
PHY_STATUS_TX_BUFFER_STATUS_LANE_0_SHIFT = 16,
PHY_STATUS_TX_BUFFER_STATUS_LANE_2_SHIFT = 24,
PHY_STATUS_TX_ERROR_LANE_2_SHIFT = 26,
PHY_STATUS_TX_BUFFER_STATUS_LANE_3_SHIFT = 28,
PHY_STATUS_TX_ERROR_LANE_3_SHIFT = 30,
};
enum {
PHY_STATUS_RESET_LANE_0_DONE_MASK = 0x00000001,
PHY_STATUS_RESET_LANE_1_DONE_MASK = 0x00000002,
PHY_STATUS_RESET_LANE_2_3_DONE_MASK = 0x0000000C,
PHY_STATUS_PLL_LANE0_1_LOCK_MASK = 0x00000010,
PHY_STATUS_PLL_LANE2_3_LOCK_MASK = 0x00000020,
PHY_STATUS_PLL_FABRIC_LOCK_MASK = 0x00000040,
PHY_STATUS_TX_BUFFER_STATUS_LANE_0_MASK = 0x00030000,
PHY_STATUS_TX_ERROR_LANE_0_MASK = 0x000C0000,
PHY_STATUS_TX_BUFFER_STATUS_LANE_1_MASK = 0x00300000,
PHY_STATUS_TX_ERROR_LANE_1_MASK = 0x00C00000,
PHY_STATUS_TX_BUFFER_STATUS_LANE_2_MASK = 0x03000000,
PHY_STATUS_TX_ERROR_LANE_2_MASK = 0x0C000000,
PHY_STATUS_TX_BUFFER_STATUS_LANE_3_MASK = 0x30000000,
PHY_STATUS_TX_ERROR_LANE_3_MASK = 0xC0000000,
};
#define PHY_STATUS_LANE_0_READY_MASK \
(PHY_STATUS_RESET_LANE_0_DONE_MASK | \
PHY_STATUS_PLL_LANE0_1_LOCK_MASK)
#define PHY_STATUS_LANES_0_1_READY_MASK \
(PHY_STATUS_LANE_0_READY_MASK | \
PHY_STATUS_RESET_LANE_1_DONE_MASK)
/*
* PHY_STATUS_ALL_LANES_READY_MASK seems to be missing lanes 0 and 1 in
* Xilinx dp_v3_0 implementation
*/
#define PHY_STATUS_ALL_LANES_READY_MASK \
(PHY_STATUS_LANES_0_1_READY_MASK | \
PHY_STATUS_RESET_LANE_2_3_DONE_MASK | \
PHY_STATUS_PLL_LANE2_3_LOCK_MASK)
/**
* phy_status_lanes_ready_mask() - Generate phy status ready mask
* @lane_count: Number of lanes for which to generate a mask
*
* Return: The generated phy status ready mask
*/
static inline u32 phy_status_lanes_ready_mask(u8 lane_count)
{
if (lane_count > 2)
return PHY_STATUS_ALL_LANES_READY_MASK;
if (lane_count == 2)
return PHY_STATUS_LANES_0_1_READY_MASK;
return PHY_STATUS_LANE_0_READY_MASK;
}
#define GT_DRP_COMMAND_DRP_ADDR_MASK 0x000F
#define GT_DRP_COMMAND_DRP_RW_CMD_MASK 0x0080
#define GT_DRP_COMMAND_DRP_W_DATA_SHIFT 16
#define GT_DRP_COMMAND_DRP_W_DATA_MASK 0xFF00
#define HDCP_ENABLE_BYPASS_DISABLE_MASK 0x0001
#endif /* __GDSYS_LOGICORE_DP_TX_REGIF_H__ */

@ -0,0 +1,118 @@
/* SPDX-License-Identifier: GPL-2.0+ */
/*
* (C) Copyright 2017, 2018
* Mario Six, Guntermann & Drunck GmbH, mario.six@gdsys.cc
*/
#ifndef _AXI_H_
#define _AXI_H_
/**
* enum axi_size_t - Determine size of AXI transfer
* @AXI_SIZE_8: AXI sransfer is 8-bit wide
* @AXI_SIZE_16: AXI sransfer is 16-bit wide
* @AXI_SIZE_32: AXI sransfer is 32-bit wide
*/
enum axi_size_t {
AXI_SIZE_8,
AXI_SIZE_16,
AXI_SIZE_32,
};
struct axi_ops {
/**
* read() - Read a single value from a specified address on a AXI bus
* @dev: AXI bus to read from.
* @address: The address to read from.
* @data: Pointer to a variable that takes the data value read
* from the address on the AXI bus.
* @size: The size of the data to be read.
*
* Return: 0 if OK, -ve on error.
*/
int (*read)(struct udevice *dev, ulong address, void *data,
enum axi_size_t size);
/**
* write() - Write a single value to a specified address on a AXI bus
* @dev: AXI bus to write to.
* @address: The address to write to.
* @data: Pointer to the data value to be written to the address
* on the AXI bus.
* @size: The size of the data to write.
*
* Return 0 if OK, -ve on error.
*/
int (*write)(struct udevice *dev, ulong address, void *data,
enum axi_size_t size);
};
#define axi_get_ops(dev) ((struct axi_ops *)(dev)->driver->ops)
/**
* axi_read() - Read a single value from a specified address on a AXI bus
* @dev: AXI bus to read from.
* @address: The address to read from.
* @data: Pointer to a variable that takes the data value read from the
* address on the AXI bus.
* @size: The size of the data to write.
*
* Return: 0 if OK, -ve on error.
*/
int axi_read(struct udevice *dev, ulong address, void *data,
enum axi_size_t size);
/**
* axi_write() - Write a single value to a specified address on a AXI bus
* @dev: AXI bus to write to.
* @address: The address to write to.
* @data: Pointer to the data value to be written to the address on the
* AXI bus.
* @size: The size of the data to write.
*
* Return: 0 if OK, -ve on error.
*/
int axi_write(struct udevice *dev, ulong address, void *data,
enum axi_size_t size);
struct axi_emul_ops {
/**
* read() - Read a single value from a specified address on a AXI bus
* @dev: AXI bus to read from.
* @address: The address to read from.
* @data: Pointer to a variable that takes the data value read
* from the address on the AXI bus.
* @size: The size of the data to be read.
*
* Return: 0 if OK, -ve on error.
*/
int (*read)(struct udevice *dev, ulong address, void *data,
enum axi_size_t size);
/**
* write() - Write a single value to a specified address on a AXI bus
* @dev: AXI bus to write to.
* @address: The address to write to.
* @data: Pointer to the data value to be written to the address
* on the AXI bus.
* @size: The size of the data to write.
*
* Return: 0 if OK, -ve on error.
*/
int (*write)(struct udevice *dev, ulong address, void *data,
enum axi_size_t size);
/**
* get_store() - Get address of internal storage of a emulated AXI
* device
* @dev: Emulated AXI device to get the pointer of the internal
* storage for.
* @storep: Pointer to the internal storage of the emulated AXI
* device.
*
* Return: 0 if OK, -ve on error.
*/
int (*get_store)(struct udevice *dev, u8 **storep);
};
#endif

@ -23,6 +23,7 @@ enum uclass_id {
UCLASS_I2C_EMUL, /* sandbox I2C device emulator */
UCLASS_PCI_EMUL, /* sandbox PCI device emulator */
UCLASS_USB_EMUL, /* sandbox USB bus device emulator */
UCLASS_AXI_EMUL, /* sandbox AXI bus device emulator */
UCLASS_SIMPLE_BUS, /* bus with child devices */
/* U-Boot uclasses start here - in alphabetical order */
@ -43,6 +44,7 @@ enum uclass_id {
UCLASS_I2C_GENERIC, /* Generic I2C device */
UCLASS_I2C_MUX, /* I2C multiplexer */
UCLASS_IDE, /* IDE device */
UCLASS_AXI, /* AXI bus */
UCLASS_IRQ, /* Interrupt controller */
UCLASS_KEYBOARD, /* Keyboard input device */
UCLASS_LED, /* Light-emitting diode (LED) */

@ -44,4 +44,5 @@ obj-$(CONFIG_DM_VIDEO) += video.o
obj-$(CONFIG_ADC) += adc.o
obj-$(CONFIG_SPMI) += spmi.o
obj-$(CONFIG_WDT) += wdt.o
obj-$(CONFIG_AXI) += axi.o
endif

@ -0,0 +1,77 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* (C) Copyright 2018
* Mario Six, Guntermann & Drunck GmbH, mario.six@gdsys.cc
*/
#include <common.h>
#include <axi.h>
#include <dm.h>
#include <dm/test.h>
#include <test/ut.h>
#include <asm/axi.h>
/* Test that sandbox AXI works correctly */
static int dm_test_axi_base(struct unit_test_state *uts)
{
struct udevice *bus;
ut_assertok(uclass_get_device(UCLASS_AXI, 0, &bus));
return 0;
}
DM_TEST(dm_test_axi_base, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
/* Test that sandbox PCI bus numbering works correctly */
static int dm_test_axi_busnum(struct unit_test_state *uts)
{
struct udevice *bus;
ut_assertok(uclass_get_device_by_seq(UCLASS_AXI, 0, &bus));
return 0;
}
DM_TEST(dm_test_axi_busnum, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
/* Test that we can use the store device correctly */
static int dm_test_axi_store(struct unit_test_state *uts)
{
struct udevice *store;
u8 tdata1[] = {0x55, 0x66, 0x77, 0x88};
u8 tdata2[] = {0xaa, 0xbb, 0xcc, 0xdd};
u32 val;
u8 *data;
/* Check that asking for the device automatically fires up AXI */
ut_assertok(uclass_get_device(UCLASS_AXI_EMUL, 0, &store));
ut_assert(device_active(store));
axi_get_store(store, &data);
/* Test reading */
memcpy(data, tdata1, ARRAY_SIZE(tdata1));
axi_read(store, 0, &val, AXI_SIZE_32);
ut_asserteq(0x55667788, val);
memcpy(data + 3, tdata2, ARRAY_SIZE(tdata2));
axi_read(store, 3, &val, AXI_SIZE_32);
ut_asserteq(0xaabbccdd, val);
/* Reset data store */
memset(data, 0, 16);
/* Test writing */
val = 0x55667788;
axi_write(store, 0, &val, AXI_SIZE_32);
ut_asserteq(0, memcmp(data, tdata1, ARRAY_SIZE(tdata1)));
val = 0xaabbccdd;
axi_write(store, 3, &val, AXI_SIZE_32);
ut_asserteq(0, memcmp(data + 3, tdata2, ARRAY_SIZE(tdata1)));
return 0;
}
DM_TEST(dm_test_axi_store, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
Loading…
Cancel
Save