diff --git a/drivers/Kconfig b/drivers/Kconfig index c72abf8..56536c4 100644 --- a/drivers/Kconfig +++ b/drivers/Kconfig @@ -8,6 +8,8 @@ source "drivers/adc/Kconfig" source "drivers/ata/Kconfig" +source "drivers/axi/Kconfig" + source "drivers/block/Kconfig" source "drivers/bootcount/Kconfig" diff --git a/drivers/Makefile b/drivers/Makefile index d532085..d296354 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -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 diff --git a/drivers/axi/Kconfig b/drivers/axi/Kconfig new file mode 100644 index 0000000..4e4153b --- /dev/null +++ b/drivers/axi/Kconfig @@ -0,0 +1,13 @@ +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. diff --git a/drivers/axi/Makefile b/drivers/axi/Makefile new file mode 100644 index 0000000..100a777 --- /dev/null +++ b/drivers/axi/Makefile @@ -0,0 +1,8 @@ +# +# (C) Copyright 2017 +# Mario Six, Guntermann & Drunck GmbH, mario.six@gdsys.cc +# +# SPDX-License-Identifier: GPL-2.0+ +# + +obj-$(CONFIG_AXI) += axi-uclass.o diff --git a/drivers/axi/axi-uclass.c b/drivers/axi/axi-uclass.c new file mode 100644 index 0000000..af8acd9 --- /dev/null +++ b/drivers/axi/axi-uclass.c @@ -0,0 +1,39 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * (C) Copyright 2017 + * Mario Six, Guntermann & Drunck GmbH, mario.six@gdsys.cc + */ + +#include +#include +#include + +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, +}; + diff --git a/include/axi.h b/include/axi.h new file mode 100644 index 0000000..2ff81c1 --- /dev/null +++ b/include/axi.h @@ -0,0 +1,78 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * (C) Copyright 2017 + * Mario Six, Guntermann & Drunck GmbH, mario.six@gdsys.cc + */ + +#ifndef _AXI_H_ +#define _AXI_H_ + +enum axi_size_t { + AXI_SIZE_8, + AXI_SIZE_16, + AXI_SIZE_32, +}; + +/** + * struct axi_ops - driver operations for AXI uclass + * + * Drivers should support these operations unless otherwise noted. These + * operations are intended to be used by uclass code, not directly from + * other code. + */ +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); +#endif diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h index a39643e..618f43a 100644 --- a/include/dm/uclass-id.h +++ b/include/dm/uclass-id.h @@ -43,6 +43,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) */