Re: [PATCH] firmware: zynmp-fpga: drop example bin format header
typo in subject: zynmp-fpga -> zynqmp-fpga On 09.12.19 14:59, Michael Tretter wrote: > Avoid the example bitstream header to validate the bitstream that should > be loaded into the FPGA. The header is mostly 0x with a few > special values at a certain offsets and can be better described with the > offsets and their magic values. > > As a drive by, this fixes/removes a broken check in the header > validation. The != operator has a higher precedence than ?: and this > check should have had parenthesis around the ?: expression: > > bin_header[i] != (byte_order == XILINX_BYTE_ORDER_BIT) ? >bin_format[i] : __swab32(bin_format[i]) > > Signed-off-by: Michael Tretter Reviewed-by: Thomas Haemmerle > --- > drivers/firmware/zynqmp-fpga.c | 121 + > 1 file changed, 62 insertions(+), 59 deletions(-) > > diff --git a/drivers/firmware/zynqmp-fpga.c b/drivers/firmware/zynqmp-fpga.c > index 1728e2a954..e02667355f 100644 > --- a/drivers/firmware/zynqmp-fpga.c > +++ b/drivers/firmware/zynqmp-fpga.c > @@ -24,11 +24,32 @@ > #define ZYNQMP_PM_VERSION_1_1_FEATURES > (ZYNQMP_PM_FEATURE_BYTE_ORDER_IRREL | \ >ZYNQMP_PM_FEATURE_SIZE_NOT_NEEDED) > > +/* > + * Xilinx KU040 Bitstream Composition: > + * > + * Bitstream can be provided with an optinal header (`struct bs_header`). > + * The true bitstream starts with the binary-header composed of 21 words: > + * > + * 0: 0x (Dummy pad word) > + * ... > + * 15: 0x (Dummy pad word) > + * 16: 0x00BB (Bus width auto detect word 1) > + * 17: 0x11220044 (Bus width auto detect word 2) > + * 18: 0x (Dummy pad word) > + * 19: 0x (Dummy pad word) > + * 20: 0xAA995566 (Sync word) > + * > + * See Xilinx UG570 (v1.11) September 30 2019, Chapter 9 "Configuration > + * Details - Bitstream Composition" for further details. > + */ > #define DUMMY_WORD 0x > -#define BUS_WIDTH_WORD_1 0x00BB > -#define BUS_WIDTH_WORD_2 0x11220044 > +#define BUS_WIDTH_AUTO_DETECT1_OFFSET16 > +#define BUS_WIDTH_AUTO_DETECT1 0x00BB > +#define BUS_WIDTH_AUTO_DETECT2_OFFSET17 > +#define BUS_WIDTH_AUTO_DETECT2 0x11220044 > +#define SYNC_WORD_OFFSET 20 > #define SYNC_WORD 0xAA995566 > -#define SYNC_WORD_OFFS 20 > +#define BIN_HEADER_LENGTH21 > > enum xilinx_byte_order { > XILINX_BYTE_ORDER_BIT, > @@ -58,48 +79,6 @@ struct bs_header_entry { > char data[0]; > } __attribute__ ((packed)); > > -/* > - * Xilinx KU040 Bitstream Composition: > - * Bitstream can be provided with an optinal header (`struct bs_header`). > - * The true bitstream starts with the binary-header composed of 21 words: > - * > - * 1: 0x (Dummy pad word) > - * ... > - * 16: 0x (Dummy pad word) > - * 17: 0x00BB (Bus width auto detect word 1) > - * 18: 0x11220044 (Bus width auto detect word 2) > - * 19: 0x (Dummy pad word) > - * 20: 0x (Dummy pad word) > - * 21: 0xAA995566 (Sync word) > - * > - * Please refer to Xilinx UG570 (v1.11) September 30 2019, > - * Chapter 9 Configuration Details - Bitstream Composition > - * for further details! > - */ > -static const u32 bin_format[] = { > - DUMMY_WORD, > - DUMMY_WORD, > - DUMMY_WORD, > - DUMMY_WORD, > - DUMMY_WORD, > - DUMMY_WORD, > - DUMMY_WORD, > - DUMMY_WORD, > - DUMMY_WORD, > - DUMMY_WORD, > - DUMMY_WORD, > - DUMMY_WORD, > - DUMMY_WORD, > - DUMMY_WORD, > - DUMMY_WORD, > - DUMMY_WORD, > - BUS_WIDTH_WORD_1, > - BUS_WIDTH_WORD_2, > - DUMMY_WORD, > - DUMMY_WORD, > - SYNC_WORD, > -}; > - > static void copy_words_swapped(u32 *dst, const u32 *src, size_t size) > { > int i; > @@ -111,36 +90,59 @@ static void copy_words_swapped(u32 *dst, const u32 *src, > size_t size) > static int get_byte_order(const u32 *bin_header, size_t size, > enum xilinx_byte_order *byte_order) > { > - if (size < sizeof(bin_format)) > + if (size < BIN_HEADER_LENGTH * sizeof(*bin_header)) > return -EINVAL; > > - if (bin_header[SYNC_WORD_OFFS] == SYNC_WORD) { > + if (bin_header[SYNC_WORD_OFFSET] == SYNC_WORD) { > *byte_order = XILINX_BYTE_ORDER_BIT; > return 0; > } > > - if (bin_header[SYNC_WORD_OFFS] == __swab32(SYNC_WORD)) { > - *byte_order = XILINX_BYTE_ORDER_BIN; > + if (bin_header[SYNC_WORD_OFFSET] == __swab32(SYNC_WORD)) { > + *byte_order = XILINX_BYTE_ORDER_BIN; > return 0; > } > > return -EINVAL; > } > > -static int is_bin_header_valid(const u32 *bin_header, size_t size, > -enum xilinx_byte_order byte_order) > +static bool is_bin_header_valid(const u32 *bin_header, size_t siz
[PATCH v2 4/4] firmware: zynqmp-fpga: print Xilinx bitstream header
From: Michael Tretter The bitstream header has 5 fields, that start with a char for the type. Four fields have a big-ending length and a null-terminated string for the design name, the part number, and the date and time of creation. The last field is a big-endian 32 bit unsigned int for the size of the bitstream. Print this info when loading the bitstream. Signed-off-by: Michael Tretter --- drivers/firmware/zynqmp-fpga.c | 51 ++ 1 file changed, 51 insertions(+) diff --git a/drivers/firmware/zynqmp-fpga.c b/drivers/firmware/zynqmp-fpga.c index 47862a7..8878658 100644 --- a/drivers/firmware/zynqmp-fpga.c +++ b/drivers/firmware/zynqmp-fpga.c @@ -45,6 +45,19 @@ struct fpgamgr { u32 features; }; +struct bs_header { + __be16 length; + u8 padding[9]; + __be16 size; + char entries[0]; +} __attribute__ ((packed)); + +struct bs_header_entry { + char type; + __be16 length; + char data[0]; +} __attribute__ ((packed)); + /* * Xilinx KU040 Bitstream Composition: * Bitstream can be provided with an optinal header (`struct bs_header`). @@ -143,6 +156,42 @@ static int get_header_length(const char *header, size_t size) return -EINVAL; } +static void zynqmp_fpga_show_header(const struct device_d *dev, +struct bs_header *header, size_t size) +{ + struct bs_header_entry *entry; + unsigned int i; + unsigned int length; + + for (i = 0; i < size - sizeof(*header); i += sizeof(*entry) + length) { + entry = (struct bs_header_entry *)&header->entries[i]; + length = __be16_to_cpu(entry->length); + + switch (entry->type) { + case 'a': + printf("Design: %s\n", entry->data); + break; + case 'b': + printf("Part number: %s\n", entry->data); + break; + case 'c': + printf("Date: %s\n", entry->data); + break; + case 'd': + printf("Time: %s\n", entry->data); + break; + case 'e': + /* Size entry does not have a length but is be32 int */ + printf("Size: %d bytes\n", + (length << 16) + (entry->data[0] << 8) + entry->data[1]); + return; + default: + dev_warn(dev, "Invalid header entry: %c", entry->type); + return; + } + } +} + static int fpgamgr_program_finish(struct firmware_handler *fh) { struct fpgamgr *mgr = container_of(fh, struct fpgamgr, fh); @@ -167,6 +216,8 @@ static int fpgamgr_program_finish(struct firmware_handler *fh) status = header_length; goto err_free; } + zynqmp_fpga_show_header(&mgr->dev, + (struct bs_header *)mgr->buf, header_length); body = (u32 *)&mgr->buf[header_length]; body_length = mgr->size - header_length; -- 2.7.4 ___ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox
[PATCH v2 3/4] firmware: zynqmp-fpga: introduce driver to load bitstream to FPGA
From: Thomas Haemmerle The driver provides functionalities to check and load a bitstream to FPGA. A boolean parameter to check if FPGA is already programmed is added. Signed-off-by: Thomas Haemmerle --- arch/arm/configs/zynqmp_defconfig | 1 + drivers/firmware/Kconfig | 7 + drivers/firmware/Makefile | 1 + drivers/firmware/zynqmp-fpga.c| 359 ++ 4 files changed, 368 insertions(+) create mode 100644 drivers/firmware/zynqmp-fpga.c diff --git a/arch/arm/configs/zynqmp_defconfig b/arch/arm/configs/zynqmp_defconfig index 4dea964..834212e 100644 --- a/arch/arm/configs/zynqmp_defconfig +++ b/arch/arm/configs/zynqmp_defconfig @@ -35,4 +35,5 @@ CONFIG_CMD_OFTREE=y CONFIG_CMD_TIME=y CONFIG_DRIVER_SERIAL_CADENCE=y # CONFIG_SPI is not set +CONFIG_FIRMWARE_ZYNQMP_PL=y CONFIG_DIGEST=y diff --git a/drivers/firmware/Kconfig b/drivers/firmware/Kconfig index 710b500..90b4c0a 100644 --- a/drivers/firmware/Kconfig +++ b/drivers/firmware/Kconfig @@ -14,4 +14,11 @@ config FIRMWARE_ALTERA_SOCFPGA bool "Altera SoCFPGA fpga loader" depends on ARCH_SOCFPGA select FIRMWARE + +config FIRMWARE_ZYNQMP_FPGA + bool "Xilinx ZynqMP FPGA loader" + depends on ARCH_ZYNQMP + select FIRMWARE + help + Load a bitstream to the PL of Zynq Ultrascale+ endmenu diff --git a/drivers/firmware/Makefile b/drivers/firmware/Makefile index c3a3c34..b162b08 100644 --- a/drivers/firmware/Makefile +++ b/drivers/firmware/Makefile @@ -1,2 +1,3 @@ obj-$(CONFIG_FIRMWARE_ALTERA_SERIAL) += altera_serial.o obj-$(CONFIG_FIRMWARE_ALTERA_SOCFPGA) += socfpga.o +obj-$(CONFIG_FIRMWARE_ZYNQMP_FPGA) += zynqmp-fpga.o diff --git a/drivers/firmware/zynqmp-fpga.c b/drivers/firmware/zynqmp-fpga.c new file mode 100644 index 000..47862a7 --- /dev/null +++ b/drivers/firmware/zynqmp-fpga.c @@ -0,0 +1,359 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Xilinx Zynq MPSoC PL loading + * + * Copyright (c) 2018 Thomas Haemmerle + * + * based on U-Boot zynqmppl code + * + * (C) Copyright 2015 - 2016, Xilinx, Inc, + * Michal Simek + * Siva Durga Prasad * + */ + +#include +#include +#include +#include +#include + +#define ZYNQMP_PM_FEATURE_BYTE_ORDER_IRREL BIT(0) +#define ZYNQMP_PM_FEATURE_SIZE_NOT_NEEDED BIT(1) + +#define ZYNQMP_PM_VERSION_1_0_FEATURES 0 +#define ZYNQMP_PM_VERSION_1_1_FEATURES (ZYNQMP_PM_FEATURE_BYTE_ORDER_IRREL | \ +ZYNQMP_PM_FEATURE_SIZE_NOT_NEEDED) + +#define DUMMY_WORD 0x +#define BUS_WIDTH_WORD_1 0x00BB +#define BUS_WIDTH_WORD_2 0x11220044 +#define SYNC_WORD 0xAA995566 +#define SYNC_WORD_OFFS 20 + +enum xilinx_byte_order { + XILINX_BYTE_ORDER_BIT, + XILINX_BYTE_ORDER_BIN, +}; + +struct fpgamgr { + struct firmware_handler fh; + struct device_d dev; + const struct zynqmp_eemi_ops *eemi_ops; + int programmed; + char *buf; + size_t size; + u32 features; +}; + +/* + * Xilinx KU040 Bitstream Composition: + * Bitstream can be provided with an optinal header (`struct bs_header`). + * The true bitstream starts with the binary-header composed of 21 words: + * + * 1: 0x (Dummy pad word) + * ... + * 16: 0x (Dummy pad word) + * 17: 0x00BB (Bus width auto detect word 1) + * 18: 0x11220044 (Bus width auto detect word 2) + * 19: 0x (Dummy pad word) + * 20: 0x (Dummy pad word) + * 21: 0xAA995566 (Sync word) + * + * Please refer to Xilinx UG570 (v1.11) September 30 2019, + * Chapter 9 Configuration Details - Bitstream Composition + * for further details! + */ +static const u32 bin_format[] = { + DUMMY_WORD, + DUMMY_WORD, + DUMMY_WORD, + DUMMY_WORD, + DUMMY_WORD, + DUMMY_WORD, + DUMMY_WORD, + DUMMY_WORD, + DUMMY_WORD, + DUMMY_WORD, + DUMMY_WORD, + DUMMY_WORD, + DUMMY_WORD, + DUMMY_WORD, + DUMMY_WORD, + DUMMY_WORD, + BUS_WIDTH_WORD_1, + BUS_WIDTH_WORD_2, + DUMMY_WORD, + DUMMY_WORD, + SYNC_WORD, +}; + +static void copy_words_swapped(u32 *dst, const u32 *src, size_t size) +{ + int i; + + for (i = 0; i < size; i++) + dst[i] = __swab32(src[i]); +} + +static int get_byte_order(const u32 *bin_header, size_t size, + enum xilinx_byte_order *byte_order) +{ + if (size < sizeof(bin_format)) + return -EINVAL; + + if (bin_header[SYNC_WORD_OFFS] == SYNC_WORD) { + *byte_order = XILINX_BYTE_ORDER_BIT; + return 0; + } + + if (bin_header[SYNC_WORD_OFFS] == __swab32(SYNC_WORD)) { + *byte_order = XILINX_BYTE_ORDER_BIN; + return 0; + } + + return -EINVAL; +} + +static int is_bin_header_valid(const u32 *bin_header, size_t size, +
[PATCH v2 0/4] ARM: zynqmp: add support for bitstream loading
From: Thomas Haemmerle Changes from v1: - remove dts commits - add commit for pmu and trustzone firmware virsion macro - split bin-header validation and byte-order detection - add description for bitstream Michael Tretter (1): firmware: zynqmp-fpga: print Xilinx bitstream header Thomas Haemmerle (3): firmware-zynqmp: add macros for PMU and trustzone firmware versions firmware-zynqmp: extend driver with fpga relavant functions firmware: zynqmp-fpga: introduce driver to load bitstream to FPGA arch/arm/configs/zynqmp_defconfig | 1 + arch/arm/mach-zynqmp/firmware-zynqmp.c | 68 +++- .../arm/mach-zynqmp/include/mach/firmware-zynqmp.h | 14 +- drivers/firmware/Kconfig | 7 + drivers/firmware/Makefile | 1 + drivers/firmware/zynqmp-fpga.c | 410 + 6 files changed, 488 insertions(+), 13 deletions(-) create mode 100644 drivers/firmware/zynqmp-fpga.c -- 2.7.4 ___ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox
[PATCH v2 2/4] firmware-zynqmp: extend driver with fpga relavant functions
From: Thomas Haemmerle Port functions from xlnx-linux to get FPGA status and invoke bitstream loading. Signed-off-by: Thomas Haemmerle --- arch/arm/mach-zynqmp/firmware-zynqmp.c | 48 +- .../arm/mach-zynqmp/include/mach/firmware-zynqmp.h | 14 ++- 2 files changed, 60 insertions(+), 2 deletions(-) diff --git a/arch/arm/mach-zynqmp/firmware-zynqmp.c b/arch/arm/mach-zynqmp/firmware-zynqmp.c index d91dcb0..6123aa1 100644 --- a/arch/arm/mach-zynqmp/firmware-zynqmp.c +++ b/arch/arm/mach-zynqmp/firmware-zynqmp.c @@ -18,7 +18,6 @@ #include -#define ZYNQMP_PM_VERSION(MAJOR, MINOR)((MAJOR << 16) | MINOR) #define ZYNQMP_TZ_VERSION(MAJOR, MINOR)((MAJOR << 16) | MINOR) #define ZYNQMP_PM_VERSION_MAJOR1 @@ -504,6 +503,51 @@ static int zynqmp_pm_ioctl(u32 node_id, u32 ioctl_id, u32 arg1, u32 arg2, arg1, arg2, out); } +/** + * zynqmp_pm_fpga_load - Perform the fpga load + * @address: Address to write to + * @size: pl bitstream size + * @flags: Flags are used to specify the type of Bitstream file - + * defined in ZYNQMP_FPGA_BIT_*-macros + * + * This function provides access to xilfpga library to transfer + * the required bitstream into PL. + * + * Return: Returns status, either success or error+reason + */ +static int zynqmp_pm_fpga_load(u64 address, u32 size, u32 flags) +{ + if (!address || !size) + return -EINVAL; + + return zynqmp_pm_invoke_fn(PM_FPGA_LOAD, + lower_32_bits(address), upper_32_bits(address), + size, flags, NULL); +} + +/** + * zynqmp_pm_fpga_get_status - Read value from PCAP status register + * @value: Value to read + * + * This function provides access to the xilfpga library to get + * the PCAP status + * + * Return: Returns status, either success or error+reason + */ +static int zynqmp_pm_fpga_get_status(u32 *value) +{ + u32 ret_payload[PAYLOAD_ARG_CNT]; + int ret = 0; + + if (!value) + return -EINVAL; + + ret = zynqmp_pm_invoke_fn(PM_FPGA_GET_STATUS, 0, 0, 0, 0, ret_payload); + *value = ret_payload[1]; + + return ret; +} + static const struct zynqmp_eemi_ops eemi_ops = { .get_api_version = zynqmp_pm_get_api_version, .query_data = zynqmp_pm_query_data, @@ -517,6 +561,8 @@ static const struct zynqmp_eemi_ops eemi_ops = { .clock_setparent = zynqmp_pm_clock_setparent, .clock_getparent = zynqmp_pm_clock_getparent, .ioctl = zynqmp_pm_ioctl, + .fpga_getstatus = zynqmp_pm_fpga_get_status, + .fpga_load = zynqmp_pm_fpga_load, }; /** diff --git a/arch/arm/mach-zynqmp/include/mach/firmware-zynqmp.h b/arch/arm/mach-zynqmp/include/mach/firmware-zynqmp.h index 9e7a2e3..a044822 100644 --- a/arch/arm/mach-zynqmp/include/mach/firmware-zynqmp.h +++ b/arch/arm/mach-zynqmp/include/mach/firmware-zynqmp.h @@ -15,7 +15,17 @@ #ifndef FIRMWARE_ZYNQMP_H_ #define FIRMWARE_ZYNQMP_H_ -#define PAYLOAD_ARG_CNT 4 +#define PAYLOAD_ARG_CNT4 + +#define ZYNQMP_PM_VERSION(MAJOR, MINOR)((MAJOR << 16) | MINOR) + +#define ZYNQMP_FPGA_BIT_AUTH_DDR BIT(1) +#define ZYNQMP_FPGA_BIT_AUTH_OCM BIT(2) +#define ZYNQMP_FPGA_BIT_ENC_USR_KEYBIT(3) +#define ZYNQMP_FPGA_BIT_ENC_DEV_KEYBIT(4) +#define ZYNQMP_FPGA_BIT_ONLY_BIN BIT(5) + +#define ZYNQMP_PCAP_STATUS_FPGA_DONE BIT(3) enum pm_ioctl_id { IOCTL_SET_PLL_FRAC_MODE = 8, @@ -61,6 +71,8 @@ struct zynqmp_eemi_ops { int (*clock_setparent)(u32 clock_id, u32 parent_id); int (*clock_getparent)(u32 clock_id, u32 *parent_id); int (*ioctl)(u32 node_id, u32 ioctl_id, u32 arg1, u32 arg2, u32 *out); + int (*fpga_getstatus)(u32 *status); + int (*fpga_load)(u64 address, u32 size, u32 flags); }; const struct zynqmp_eemi_ops *zynqmp_pm_get_eemi_ops(void); -- 2.7.4 ___ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox
[PATCH v2 1/4] firmware-zynqmp: add macros for PMU and trustzone firmware versions
From: Thomas Haemmerle Signed-off-by: Thomas Haemmerle --- arch/arm/mach-zynqmp/firmware-zynqmp.c | 22 ++ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/arch/arm/mach-zynqmp/firmware-zynqmp.c b/arch/arm/mach-zynqmp/firmware-zynqmp.c index f2187e9..d91dcb0 100644 --- a/arch/arm/mach-zynqmp/firmware-zynqmp.c +++ b/arch/arm/mach-zynqmp/firmware-zynqmp.c @@ -18,17 +18,13 @@ #include -#define ZYNQMP_PM_VERSION_MAJOR1 -#define ZYNQMP_PM_VERSION_MINOR0 +#define ZYNQMP_PM_VERSION(MAJOR, MINOR)((MAJOR << 16) | MINOR) +#define ZYNQMP_TZ_VERSION(MAJOR, MINOR)((MAJOR << 16) | MINOR) -#define ZYNQMP_PM_VERSION ((ZYNQMP_PM_VERSION_MAJOR << 16) | \ - ZYNQMP_PM_VERSION_MINOR) - -#define ZYNQMP_TZ_VERSION_MAJOR 1 -#define ZYNQMP_TZ_VERSION_MINOR 0 - -#define ZYNQMP_TZ_VERSION ((ZYNQMP_TZ_VERSION_MAJOR << 16) | \ - ZYNQMP_TZ_VERSION_MINOR) +#define ZYNQMP_PM_VERSION_MAJOR1 +#define ZYNQMP_PM_VERSION_MINOR0 +#define ZYNQMP_TZ_VERSION_MAJOR1 +#define ZYNQMP_TZ_VERSION_MINOR0 /* SMC SIP service Call Function Identifier Prefix */ #define PM_SIP_SVC 0xC200 @@ -544,7 +540,8 @@ static int zynqmp_firmware_probe(struct device_d *dev) goto out; zynqmp_pm_get_api_version(&pm_api_version); - if (pm_api_version < ZYNQMP_PM_VERSION) { + if (pm_api_version < ZYNQMP_PM_VERSION(ZYNQMP_PM_VERSION_MAJOR, + ZYNQMP_PM_VERSION_MINOR)) { dev_err(dev, "Platform Management API version error." "Expected: v%d.%d - Found: v%d.%d\n", ZYNQMP_PM_VERSION_MAJOR, @@ -563,7 +560,8 @@ static int zynqmp_firmware_probe(struct device_d *dev) goto out; } - if (pm_tz_version < ZYNQMP_TZ_VERSION) { + if (pm_tz_version < ZYNQMP_TZ_VERSION(ZYNQMP_TZ_VERSION_MAJOR, + ZYNQMP_TZ_VERSION_MINOR)) { dev_err(dev, "Trustzone version error." "Expected: v%d.%d - Found: v%d.%d\n", ZYNQMP_TZ_VERSION_MAJOR, -- 2.7.4 ___ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox
[PATCH 5/5] firmware: zynqmp-fpga: print Xilinx bitstream header
From: Michael Tretter The bitstream header has 5 fields, that start with a char for the type. Four fields have a big-ending length and a null-terminated string for the design name, the part number, and the date and time of creation. The last field is a big-endian 32 bit unsigned int for the size of the bitstream. Print this info when loading the bitstream. Signed-off-by: Michael Tretter --- drivers/firmware/zynqmp-fpga.c | 51 ++ 1 file changed, 51 insertions(+) diff --git a/drivers/firmware/zynqmp-fpga.c b/drivers/firmware/zynqmp-fpga.c index 6a32d28..7bf880f 100644 --- a/drivers/firmware/zynqmp-fpga.c +++ b/drivers/firmware/zynqmp-fpga.c @@ -39,6 +39,19 @@ struct fpgamgr { u32 features; }; +struct bs_header { + __be16 length; + u8 padding[9]; + __be16 size; + char entries[0]; +} __attribute__ ((packed)); + +struct bs_header_entry { + char type; + __be16 length; + char data[0]; +} __attribute__ ((packed)); + /* Xilinx binary format header */ static const u32 bin_format[] = { DUMMY_WORD, @@ -100,6 +113,42 @@ static int get_header_length(const char *buf, size_t size) return -EINVAL; } +static void zynqmp_fpga_show_header(const struct device_d *dev, +struct bs_header *header, size_t size) +{ + struct bs_header_entry *entry; + unsigned int i; + unsigned int length; + + for (i = 0; i < size - sizeof(*header); i += sizeof(*entry) + length) { + entry = (struct bs_header_entry *)&header->entries[i]; + length = __be16_to_cpu(entry->length); + + switch (entry->type) { + case 'a': + printf("Design: %s\n", entry->data); + break; + case 'b': + printf("Part number: %s\n", entry->data); + break; + case 'c': + printf("Date: %s\n", entry->data); + break; + case 'd': + printf("Time: %s\n", entry->data); + break; + case 'e': + /* Size entry does not have a length but is be32 int */ + printf("Size: %d bytes\n", + (length << 16) + (entry->data[0] << 8) + entry->data[1]); + return; + default: + dev_warn(dev, "Invalid header entry: %c", entry->type); + return; + } + } +} + static int fpgamgr_program_finish(struct firmware_handler *fh) { struct fpgamgr *mgr = container_of(fh, struct fpgamgr, fh); @@ -121,6 +170,8 @@ static int fpgamgr_program_finish(struct firmware_handler *fh) status = header_length; goto err_free; } + zynqmp_fpga_show_header(&mgr->dev, + (struct bs_header *)mgr->buf, header_length); byte_order = get_byte_order((u32 *)&mgr->buf[header_length], mgr->size - header_length); -- 2.7.4 ___ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox
[PATCH 1/5] ARM: zynqmp: dts: move firmware node to src tree
From: Michael Tretter The firmware node will be added to the mainline device tree. As it will eventually enter Barebox via a device tree sync, add it to the src tree already. Signed-off-by: Michael Tretter --- arch/arm/dts/zynqmp-zcu104-revA.dts | 1 - arch/arm/dts/zynqmp.dtsi| 17 - dts/src/arm64/xilinx/zynqmp.dtsi| 7 +++ 3 files changed, 7 insertions(+), 18 deletions(-) delete mode 100644 arch/arm/dts/zynqmp.dtsi diff --git a/arch/arm/dts/zynqmp-zcu104-revA.dts b/arch/arm/dts/zynqmp-zcu104-revA.dts index c03112d..8b8dd84 100644 --- a/arch/arm/dts/zynqmp-zcu104-revA.dts +++ b/arch/arm/dts/zynqmp-zcu104-revA.dts @@ -8,5 +8,4 @@ */ #include -#include "zynqmp.dtsi" #include "zynqmp-clk.dtsi" diff --git a/arch/arm/dts/zynqmp.dtsi b/arch/arm/dts/zynqmp.dtsi deleted file mode 100644 index 59984ee..000 --- a/arch/arm/dts/zynqmp.dtsi +++ /dev/null @@ -1,17 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -/* - * dts file for Xilinx ZynqMP - * - * (C) Copyright 2014 - 2015, Xilinx, Inc. - * - * Michal Simek - */ - -/ { - firmware { - zynqmp_firmware: zynqmp-firmware { - compatible = "xlnx,zynqmp-firmware"; - method = "smc"; - }; - }; -}; diff --git a/dts/src/arm64/xilinx/zynqmp.dtsi b/dts/src/arm64/xilinx/zynqmp.dtsi index 9aa6734..9115eae 100644 --- a/dts/src/arm64/xilinx/zynqmp.dtsi +++ b/dts/src/arm64/xilinx/zynqmp.dtsi @@ -115,6 +115,13 @@ method = "smc"; }; + firmware { + zynqmp_firmware: zynqmp-firmware { + compatible = "xlnx,zynqmp-firmware"; + method = "smc"; + }; + }; + timer { compatible = "arm,armv8-timer"; interrupt-parent = <&gic>; -- 2.7.4 ___ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox
[PATCH 2/5] firmware-zynqmp: extend driver with fpga relavant functions
From: Thomas Haemmerle Port functions from xlnx-linux to get FPGA status and invoke bitstream loading. Signed-off-by: Thomas Haemmerle --- arch/arm/mach-zynqmp/firmware-zynqmp.c | 47 ++ .../arm/mach-zynqmp/include/mach/firmware-zynqmp.h | 8 2 files changed, 55 insertions(+) diff --git a/arch/arm/mach-zynqmp/firmware-zynqmp.c b/arch/arm/mach-zynqmp/firmware-zynqmp.c index f2187e9..18a1a51 100644 --- a/arch/arm/mach-zynqmp/firmware-zynqmp.c +++ b/arch/arm/mach-zynqmp/firmware-zynqmp.c @@ -508,6 +508,51 @@ static int zynqmp_pm_ioctl(u32 node_id, u32 ioctl_id, u32 arg1, u32 arg2, arg1, arg2, out); } +/** + * zynqmp_pm_fpga_load - Perform the fpga load + * @address: Address to write to + * @size: pl bitstream size + * @flags: Flags are used to specify the type of Bitstream file - + * defined in ZYNQMP_FPGA_BIT_*-macros + * + * This function provides access to xilfpga library to transfer + * the required bitstream into PL. + * + * Return: Returns status, either success or error+reason + */ +static int zynqmp_pm_fpga_load(u64 address, u32 size, u32 flags) +{ + if (!address || !size) + return -EINVAL; + + return zynqmp_pm_invoke_fn(PM_FPGA_LOAD, + lower_32_bits(address), upper_32_bits(address), + size, flags, NULL); +} + +/** + * zynqmp_pm_fpga_get_status - Read value from PCAP status register + * @value: Value to read + * + * This function provides access to the xilfpga library to get + * the PCAP status + * + * Return: Returns status, either success or error+reason + */ +static int zynqmp_pm_fpga_get_status(u32 *value) +{ + u32 ret_payload[PAYLOAD_ARG_CNT]; + int ret = 0; + + if (!value) + return -EINVAL; + + ret = zynqmp_pm_invoke_fn(PM_FPGA_GET_STATUS, 0, 0, 0, 0, ret_payload); + *value = ret_payload[1]; + + return ret; +} + static const struct zynqmp_eemi_ops eemi_ops = { .get_api_version = zynqmp_pm_get_api_version, .query_data = zynqmp_pm_query_data, @@ -521,6 +566,8 @@ static const struct zynqmp_eemi_ops eemi_ops = { .clock_setparent = zynqmp_pm_clock_setparent, .clock_getparent = zynqmp_pm_clock_getparent, .ioctl = zynqmp_pm_ioctl, + .fpga_getstatus = zynqmp_pm_fpga_get_status, + .fpga_load = zynqmp_pm_fpga_load, }; /** diff --git a/arch/arm/mach-zynqmp/include/mach/firmware-zynqmp.h b/arch/arm/mach-zynqmp/include/mach/firmware-zynqmp.h index 9e7a2e3..f19d73d 100644 --- a/arch/arm/mach-zynqmp/include/mach/firmware-zynqmp.h +++ b/arch/arm/mach-zynqmp/include/mach/firmware-zynqmp.h @@ -17,6 +17,12 @@ #define PAYLOAD_ARG_CNT 4 +#define ZYNQMP_FPGA_BIT_AUTH_DDR BIT(1) +#define ZYNQMP_FPGA_BIT_AUTH_OCM BIT(2) +#define ZYNQMP_FPGA_BIT_ENC_USR_KEYBIT(3) +#define ZYNQMP_FPGA_BIT_ENC_DEV_KEYBIT(4) +#define ZYNQMP_FPGA_BIT_ONLY_BIN BIT(5) + enum pm_ioctl_id { IOCTL_SET_PLL_FRAC_MODE = 8, IOCTL_GET_PLL_FRAC_MODE, @@ -61,6 +67,8 @@ struct zynqmp_eemi_ops { int (*clock_setparent)(u32 clock_id, u32 parent_id); int (*clock_getparent)(u32 clock_id, u32 *parent_id); int (*ioctl)(u32 node_id, u32 ioctl_id, u32 arg1, u32 arg2, u32 *out); + int (*fpga_getstatus)(u32 *status); + int (*fpga_load)(u64 address, u32 size, u32 flags); }; const struct zynqmp_eemi_ops *zynqmp_pm_get_eemi_ops(void); -- 2.7.4 ___ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox
[PATCH 4/5] ARM: zynqmp: dts: move pcap node to src tree
From: Thomas Haemmerle The pcap node will be added to the mainline device tree. As it will eventually enter Barebox via a device tree sync, add it to the src tree already. Signed-off-by: Thomas Haemmerle --- dts/src/arm64/xilinx/zynqmp.dtsi | 3 +++ 1 file changed, 3 insertions(+) diff --git a/dts/src/arm64/xilinx/zynqmp.dtsi b/dts/src/arm64/xilinx/zynqmp.dtsi index 9115eae..1d1e531 100644 --- a/dts/src/arm64/xilinx/zynqmp.dtsi +++ b/dts/src/arm64/xilinx/zynqmp.dtsi @@ -119,6 +119,9 @@ zynqmp_firmware: zynqmp-firmware { compatible = "xlnx,zynqmp-firmware"; method = "smc"; + zynqmp_pcap: pcap { + compatible = "xlnx,zynqmp-pcap-fpga"; + }; }; }; -- 2.7.4 ___ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox
[PATCH 3/5] firmware: zynqmp-fpga: introduce driver to load bitstream to FPGA
From: Thomas Haemmerle The driver provides functionalities to check and load a bitstream to FPGA. A boolean parameter to check if FPGA is already programmed is added. Signed-off-by: Thomas Haemmerle --- arch/arm/configs/zynqmp_defconfig | 1 + .../arm/mach-zynqmp/include/mach/firmware-zynqmp.h | 2 + drivers/firmware/Kconfig | 5 + drivers/firmware/Makefile | 1 + drivers/firmware/zynqmp-fpga.c | 315 + 5 files changed, 324 insertions(+) create mode 100644 drivers/firmware/zynqmp-fpga.c diff --git a/arch/arm/configs/zynqmp_defconfig b/arch/arm/configs/zynqmp_defconfig index 4dea964..834212e 100644 --- a/arch/arm/configs/zynqmp_defconfig +++ b/arch/arm/configs/zynqmp_defconfig @@ -35,4 +35,5 @@ CONFIG_CMD_OFTREE=y CONFIG_CMD_TIME=y CONFIG_DRIVER_SERIAL_CADENCE=y # CONFIG_SPI is not set +CONFIG_FIRMWARE_ZYNQMP_PL=y CONFIG_DIGEST=y diff --git a/arch/arm/mach-zynqmp/include/mach/firmware-zynqmp.h b/arch/arm/mach-zynqmp/include/mach/firmware-zynqmp.h index f19d73d..6fcfba5 100644 --- a/arch/arm/mach-zynqmp/include/mach/firmware-zynqmp.h +++ b/arch/arm/mach-zynqmp/include/mach/firmware-zynqmp.h @@ -23,6 +23,8 @@ #define ZYNQMP_FPGA_BIT_ENC_DEV_KEYBIT(4) #define ZYNQMP_FPGA_BIT_ONLY_BIN BIT(5) +#define ZYNQMP_PCAP_STATUS_FPGA_DONE BIT(3) + enum pm_ioctl_id { IOCTL_SET_PLL_FRAC_MODE = 8, IOCTL_GET_PLL_FRAC_MODE, diff --git a/drivers/firmware/Kconfig b/drivers/firmware/Kconfig index 710b500..3113f40 100644 --- a/drivers/firmware/Kconfig +++ b/drivers/firmware/Kconfig @@ -14,4 +14,9 @@ config FIRMWARE_ALTERA_SOCFPGA bool "Altera SoCFPGA fpga loader" depends on ARCH_SOCFPGA select FIRMWARE + +config FIRMWARE_ZYNQMP_FPGA + bool "Xilinx ZynqMP FPGA loader" + depends on ARCH_ZYNQMP + select FIRMWARE endmenu diff --git a/drivers/firmware/Makefile b/drivers/firmware/Makefile index c3a3c34..b162b08 100644 --- a/drivers/firmware/Makefile +++ b/drivers/firmware/Makefile @@ -1,2 +1,3 @@ obj-$(CONFIG_FIRMWARE_ALTERA_SERIAL) += altera_serial.o obj-$(CONFIG_FIRMWARE_ALTERA_SOCFPGA) += socfpga.o +obj-$(CONFIG_FIRMWARE_ZYNQMP_FPGA) += zynqmp-fpga.o diff --git a/drivers/firmware/zynqmp-fpga.c b/drivers/firmware/zynqmp-fpga.c new file mode 100644 index 000..6a32d28 --- /dev/null +++ b/drivers/firmware/zynqmp-fpga.c @@ -0,0 +1,315 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Xilinx Zynq MPSoC PL loading + * + * Copyright (c) 2018 Thomas Haemmerle + * + * based on U-Boot zynqmppl code + * + * (C) Copyright 2015 - 2016, Xilinx, Inc, + * Michal Simek + * Siva Durga Prasad * + */ + +#include +#include +#include +#include +#include + +#define ZYNQMP_PM_VERSION_1_1 ((1 << 16) | 1) + +#define ZYNQMP_PM_FEATURE_BYTE_ORDER_IRREL BIT(0) + +#define ZYNQMP_PM_VERSION_1_0_FEATURES 0 +#define ZYNQMP_PM_VERSION_1_1_FEATURES ZYNQMP_PM_FEATURE_BYTE_ORDER_IRREL + +#define DUMMY_WORD 0x + +#define XILINX_BYTE_ORDER_BIT 0 +#define XILINX_BYTE_ORDER_BIN 1 + +struct fpgamgr { + struct firmware_handler fh; + struct device_d dev; + const struct zynqmp_eemi_ops *eemi_ops; + int programmed; + char *buf; + size_t size; + u32 features; +}; + +/* Xilinx binary format header */ +static const u32 bin_format[] = { + DUMMY_WORD, + DUMMY_WORD, + DUMMY_WORD, + DUMMY_WORD, + DUMMY_WORD, + DUMMY_WORD, + DUMMY_WORD, + DUMMY_WORD, + DUMMY_WORD, + DUMMY_WORD, + DUMMY_WORD, + DUMMY_WORD, + DUMMY_WORD, + DUMMY_WORD, + DUMMY_WORD, + DUMMY_WORD, + 0x00bb, + 0x11220044, + DUMMY_WORD, + DUMMY_WORD, + 0xaa995566, +}; + +static void copy_words_swapped(u32 *dst, const u32 *src, size_t size) +{ + int i; + + for (i = 0; i < size; i++) + dst[i] = __swab32(src[i]); +} + +static int get_byte_order(const u32 *buf, size_t size) +{ + u32 buf_check[ARRAY_SIZE(bin_format)]; + + memcpy(buf_check, buf, ARRAY_SIZE(buf_check)); + if (memcmp(buf_check, bin_format, sizeof(buf_check)) == 0) + return XILINX_BYTE_ORDER_BIT; + + copy_words_swapped(buf_check, buf, ARRAY_SIZE(buf_check)); + if (memcmp(buf_check, bin_format, sizeof(buf_check)) == 0) + return XILINX_BYTE_ORDER_BIN; + + return -EINVAL; +} + +static int get_header_length(const char *buf, size_t size) +{ + u32 *buf_u32; + int p; + + for (p = 0; p < size; p++) { + buf_u32 = (u32 *)&buf[p]; + if (*buf_u32 == DUMMY_WORD) + return p; + } + return -EINVAL; +} + +static int fpgamgr_program_finish(struct firmware_handler *fh) +{ + struct fpgamgr *mgr = container_of(fh, struct fpgamgr, fh); + char *buf_align
[PATCH 0/5] ARM: zynqmp: add support for bitstream loading
From: Thomas Haemmerle Michael Tretter (2): ARM: zynqmp: dts: move firmware node to src tree firmware: zynqmp-fpga: print Xilinx bitstream header Thomas Haemmerle (3): firmware-zynqmp: extend driver with fpga relavant functions firmware: zynqmp-fpga: introduce driver to load bitstream to FPGA ARM: zynqmp: dts: move pcap node to src tree arch/arm/configs/zynqmp_defconfig | 1 + arch/arm/dts/zynqmp-zcu104-revA.dts| 1 - arch/arm/dts/zynqmp.dtsi | 17 - arch/arm/mach-zynqmp/firmware-zynqmp.c | 47 +++ .../arm/mach-zynqmp/include/mach/firmware-zynqmp.h | 10 + drivers/firmware/Kconfig | 5 + drivers/firmware/Makefile | 1 + drivers/firmware/zynqmp-fpga.c | 366 + dts/src/arm64/xilinx/zynqmp.dtsi | 10 + 9 files changed, 440 insertions(+), 18 deletions(-) delete mode 100644 arch/arm/dts/zynqmp.dtsi create mode 100644 drivers/firmware/zynqmp-fpga.c -- 2.7.4 ___ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox
[PATCH v2] firmware-zynqmp: port from linux
From: Thomas Haemmerle Changes since v1: - return -EIO (instead of -1) if API version or trustzone version are earlier than v1.0 in probe function Thomas Haemmerle (1): firmware-zynqmp: port from linux arch/arm/Kconfig | 1 + arch/arm/mach-zynqmp/Makefile | 2 +- arch/arm/mach-zynqmp/firmware-zynqmp.c | 601 + .../arm/mach-zynqmp/include/mach/firmware-zynqmp.h | 66 +++ 4 files changed, 669 insertions(+), 1 deletion(-) create mode 100644 arch/arm/mach-zynqmp/firmware-zynqmp.c create mode 100644 arch/arm/mach-zynqmp/include/mach/firmware-zynqmp.h -- 2.7.4 ___ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox
Re: [PATCH] firmware-zynqmp: port from linux
Hi Sascha, On 12.02.19 09:31, Sascha Hauer wrote: > Hi Thomas, > > On Mon, Feb 11, 2019 at 02:10:40PM +0000, Thomas Hämmerle wrote: >> From: Thomas Haemmerle >> >> Port Xilinx Zynq MPSoC Firmware layer driver from linux. >> >> Signed-off-by: Thomas Haemmerle >> --- >> arch/arm/Kconfig | 1 + >> arch/arm/mach-zynqmp/Makefile | 2 +- >> arch/arm/mach-zynqmp/firmware-zynqmp.c | 601 >> + >> .../arm/mach-zynqmp/include/mach/firmware-zynqmp.h | 66 +++ >> 4 files changed, 669 insertions(+), 1 deletion(-) >> create mode 100644 arch/arm/mach-zynqmp/firmware-zynqmp.c >> create mode 100644 arch/arm/mach-zynqmp/include/mach/firmware-zynqmp.h >> >> diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig >> index c1f385b..fdbe5b7 100644 >> --- a/arch/arm/Kconfig >> +++ b/arch/arm/Kconfig >> @@ -250,6 +250,7 @@ config ARCH_ZYNQMP >> select CPU_V8 >> select HAS_DEBUG_LL >> select HAVE_PBL_MULTI_IMAGES >> +select ARM_SMCCC >> select COMMON_CLK >> select COMMON_CLK_OF_PROVIDER >> select CLKDEV_LOOKUP >> diff --git a/arch/arm/mach-zynqmp/Makefile b/arch/arm/mach-zynqmp/Makefile >> index c601374..021efc9 100644 >> --- a/arch/arm/mach-zynqmp/Makefile >> +++ b/arch/arm/mach-zynqmp/Makefile >> @@ -1,2 +1,2 @@ >> # SPDX-License-Identifier: GPL-2.0-or-later >> -obj- := __dummy__.o >> +obj-y += firmware-zynqmp.o >> diff --git a/arch/arm/mach-zynqmp/firmware-zynqmp.c >> b/arch/arm/mach-zynqmp/firmware-zynqmp.c > > > Maybe drivers/firmware/ would be a more appropriate directory to put > this driver in. I was not sure where to put the this driver in: In linux drivers/firmware is the location for drivers which communicate with a firmware (like this one). In barebox, this directory contains drivers to load firmware to devices (socfpga.c for example). Since I will also create a driver to load the PL (programmable logic) of ZynqMP which I will place in drivers/firmware, I decided to put this driver to arch/arm. > >> +static int zynqmp_firmware_probe(struct device_d *dev) >> +{ >> +int ret; >> + >> +ret = get_set_conduit_method(dev->device_node); >> +if (ret) >> +goto out; >> + >> +zynqmp_pm_get_api_version(&pm_api_version); >> +if (pm_api_version < ZYNQMP_PM_VERSION) { >> +dev_err(dev, "Platform Management API version error." >> +"Expected: v%d.%d - Found: v%d.%d\n", >> +ZYNQMP_PM_VERSION_MAJOR, >> +ZYNQMP_PM_VERSION_MINOR, >> +pm_api_version >> 16, pm_api_version & 0x); >> +ret = -1; >> +goto out; > > -1 is -EPERM which is not a meaningful error code here. Please pick > something appropriate from errno.h. Of course - will fix this. > > Otherwise looks good. This looks like clock support. Are you planning to > create a clk driver aswell? Yes, a clk driver is also planned. Thomas ___ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox
[PATCH 5/6] macb: disable second priority queue for zynqmp gem support
Provide descriptors for second priority rx and tx queues and disable the the queues if hardware is GEM. Otherwise the function macb_send() will run into a timeout. Signed-off-by: Thomas Haemmerle --- drivers/net/macb.c | 21 + drivers/net/macb.h | 2 ++ 2 files changed, 23 insertions(+) diff --git a/drivers/net/macb.c b/drivers/net/macb.c index c129282..2a30457 100644 --- a/drivers/net/macb.c +++ b/drivers/net/macb.c @@ -46,9 +46,11 @@ #define RX_BUFFER_MULTIPLE 64 /* bytes */ #define RX_NB_PACKET 10 #define TX_RING_SIZE 2 /* must be power of 2 */ +#define GEM_Q1_DESCS 2 #define RX_RING_BYTES(bp) (sizeof(struct macb_dma_desc) * bp->rx_ring_size) #define TX_RING_BYTES (sizeof(struct macb_dma_desc) * TX_RING_SIZE) +#define GEM_Q1_DESC_BYTES (sizeof(struct macb_dma_desc) * GEM_Q1_DESCS) struct macb_device { void__iomem *regs; @@ -60,6 +62,7 @@ struct macb_device { void*tx_buffer; struct macb_dma_desc*rx_ring; struct macb_dma_desc*tx_ring; + struct macb_dma_desc*gem_q1_descs; int rx_buffer_size; int rx_ring_size; @@ -340,6 +343,20 @@ static void macb_init(struct macb_device *macb) macb_writel(macb, RBQP, (ulong)macb->rx_ring); macb_writel(macb, TBQP, (ulong)macb->tx_ring); + if (macb->is_gem && macb->gem_q1_descs) { + /* Disable the second priority queue */ + macb->gem_q1_descs[0].addr = 0; + macb->gem_q1_descs[0].ctrl = MACB_BIT(TX_WRAP) | + MACB_BIT(TX_LAST) | + MACB_BIT(TX_USED); + macb->gem_q1_descs[1].addr = MACB_BIT(RX_USED) | + MACB_BIT(RX_WRAP); + macb->gem_q1_descs[1].ctrl = 0; + + gem_writel(macb, TQ1, (ulong)&macb->gem_q1_descs[0]); + gem_writel(macb, RQ1, (ulong)&macb->gem_q1_descs[1]); + } + switch(macb->interface) { case PHY_INTERFACE_MODE_RGMII: val = GEM_BIT(RGMII); @@ -689,6 +706,10 @@ static int macb_probe(struct device_d *dev) macb->rx_ring = dma_alloc_coherent(RX_RING_BYTES(macb), DMA_ADDRESS_BROKEN); macb->tx_ring = dma_alloc_coherent(TX_RING_BYTES, DMA_ADDRESS_BROKEN); + if (macb->is_gem) + macb->gem_q1_descs = dma_alloc_coherent(GEM_Q1_DESC_BYTES, + DMA_ADDRESS_BROKEN); + macb_reset_hw(macb); ncfgr = macb_mdc_clk_div(macb); ncfgr |= MACB_BIT(PAE); /* PAuse Enable */ diff --git a/drivers/net/macb.h b/drivers/net/macb.h index 6be9732..979f53c 100644 --- a/drivers/net/macb.h +++ b/drivers/net/macb.h @@ -72,6 +72,8 @@ #define GEM_DCFG5 0x0290 #define GEM_DCFG6 0x0294 #define GEM_DCFG7 0x0298 +#define GEM_TQ10x0440 +#define GEM_RQ10x0480 /* Bitfields in NCR */ #define MACB_LB_OFFSET 0 -- 2.7.4 Thomas Hämmerle Research and Development Wolfvision GmbH | 6833 Klaus | Austria Tel: +43 5523 52250 | Mail: thomas.haemme...@wolfvision.net Webpage: www.wolfvision.com | www.wolfvision.com/green Firmenbuch / Commercial Register: FN283521v Feldkirch/Austria ___ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox
[PATCH 1/6] dp83867: port from linux
phy_write(phydev, MII_BMCR, BMCR_ANENABLE | + BMCR_FULLDPLX | + BMCR_SPEED1000); + + cfg2 = phy_read(phydev, MII_DP83867_CFG2); + cfg2 &= MII_DP83867_CFG2_MASK; + cfg2 |= MII_DP83867_CFG2_SPEEDOPT_10EN | + MII_DP83867_CFG2_SGMII_AUTONEGEN | + MII_DP83867_CFG2_SPEEDOPT_ENH | + MII_DP83867_CFG2_SPEEDOPT_CNT | + MII_DP83867_CFG2_SPEEDOPT_INTLOW; + + phy_write(phydev, MII_DP83867_CFG2, cfg2); + + phy_write_mmd_indirect(phydev, DP83867_RGMIICTL, + DP83867_DEVADDR, 0x0); + + val = DP83867_PHYCTRL_SGMIIEN | + DP83867_MDI_CROSSOVER_MDIX << DP83867_MDI_CROSSOVER | + dp83867->fifo_depth << DP83867_PHYCTRL_RXFIFO_SHIFT | + dp83867->fifo_depth << DP83867_PHYCTRL_TXFIFO_SHIFT; + + phy_write(phydev, MII_DP83867_PHYCTRL, val); + phy_write(phydev, MII_DP83867_BISCR, 0x0); + } + + if (phy_interface_is_rgmii(phydev)) { + val = phy_read_mmd_indirect(phydev, DP83867_RGMIICTL, + DP83867_DEVADDR); + + switch (phydev->interface) { + case PHY_INTERFACE_MODE_RGMII_ID: + val |= (DP83867_RGMII_TX_CLK_DELAY_EN + | DP83867_RGMII_RX_CLK_DELAY_EN); + break; + case PHY_INTERFACE_MODE_RGMII_TXID: + val |= DP83867_RGMII_TX_CLK_DELAY_EN; + break; + case PHY_INTERFACE_MODE_RGMII_RXID: + val |= DP83867_RGMII_RX_CLK_DELAY_EN; + break; + default: + break; + } + phy_write_mmd_indirect(phydev, DP83867_RGMIICTL, + DP83867_DEVADDR, val); + + delay = (dp83867->rx_id_delay | + (dp83867->tx_id_delay << DP83867_RGMII_TX_CLK_DELAY_SHIFT)); + + phy_write_mmd_indirect(phydev, DP83867_RGMIIDCTL, + DP83867_DEVADDR, delay); + + if (dp83867->io_impedance >= 0) { + val = phy_read_mmd_indirect(phydev, DP83867_IO_MUX_CFG, + DP83867_DEVADDR); + val &= ~DP83867_IO_MUX_CFG_IO_IMPEDANCE_CTRL; + val |= dp83867->io_impedance + & DP83867_IO_MUX_CFG_IO_IMPEDANCE_CTRL; + + phy_write_mmd_indirect(phydev, DP83867_IO_MUX_CFG, + DP83867_DEVADDR, val); + } + } + + genphy_config_aneg(phydev); + + if (dp83867->port_mirroring != DP83867_PORT_MIRROING_KEEP) + dp83867_config_port_mirroring(phydev); + + dev_info(&phydev->dev, "DP83867\n"); + + return 0; +} + +static struct phy_driver dp83867_driver[] = { + { + .phy_id = DP83867_PHY_ID, + .phy_id_mask = 0xfff0, + .drv.name = "TI DP83867", + .features = PHY_GBIT_FEATURES, + + .config_init = dp83867_config_init, + + .config_aneg = genphy_config_aneg, + .read_status = genphy_read_status, + }, +}; + +static int dp83867_phy_init(void) +{ + return phy_drivers_register(dp83867_driver, ARRAY_SIZE(dp83867_driver)); +} +fs_initcall(dp83867_phy_init); -- 2.7.4 Thomas Hämmerle Research and Development Wolfvision GmbH | 6833 Klaus | Austria Tel: +43 5523 52250 | Mail: thomas.haemme...@wolfvision.net Webpage: www.wolfvision.com | www.wolfvision.com/green Firmenbuch / Commercial Register: FN283521v Feldkirch/Austria ___ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox
[PATCH 6/6] zynqmp: enable macb Ethernet support
Signed-off-by: Thomas Haemmerle --- arch/arm/configs/zynqmp_defconfig | 1 + drivers/net/macb.c| 1 + 2 files changed, 2 insertions(+) diff --git a/arch/arm/configs/zynqmp_defconfig b/arch/arm/configs/zynqmp_defconfig index 4dea964..a358a50 100644 --- a/arch/arm/configs/zynqmp_defconfig +++ b/arch/arm/configs/zynqmp_defconfig @@ -33,6 +33,7 @@ CONFIG_CMD_TIMEOUT=y CONFIG_CMD_CLK=y CONFIG_CMD_OFTREE=y CONFIG_CMD_TIME=y +CONFIG_DRIVER_NET_MACB=y CONFIG_DRIVER_SERIAL_CADENCE=y # CONFIG_SPI is not set CONFIG_DIGEST=y diff --git a/drivers/net/macb.c b/drivers/net/macb.c index 2a30457..0c0d17e 100644 --- a/drivers/net/macb.c +++ b/drivers/net/macb.c @@ -738,6 +738,7 @@ static void macb_remove(struct device_d *dev) static const struct of_device_id macb_dt_ids[] = { { .compatible = "cdns,at91sam9260-macb",}, { .compatible = "atmel,sama5d3-gem",}, + { .compatible = "cdns,zynqmp-gem",}, { /* sentinel */ } }; -- 2.7.4 Thomas Hämmerle Research and Development Wolfvision GmbH | 6833 Klaus | Austria Tel: +43 5523 52250 | Mail: thomas.haemme...@wolfvision.net Webpage: www.wolfvision.com | www.wolfvision.com/green Firmenbuch / Commercial Register: FN283521v Feldkirch/Austria ___ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox
[PATCH 2/6] macb: fix format specifiers for debug output
Fixes compiler warning "format '%d' expects argument of type 'int', but argument 4 has type 'size_t {aka long unsigned int}' [-Wformat=]". Signed-off-by: Thomas Haemmerle --- drivers/net/macb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/macb.c b/drivers/net/macb.c index 1a8f6da..240802e 100644 --- a/drivers/net/macb.c +++ b/drivers/net/macb.c @@ -596,7 +596,7 @@ static void macb_init_rx_buffer_size(struct macb_device *bp, size_t size) DMA_ADDRESS_BROKEN); } - dev_dbg(bp->dev, "[%d] rx_buffer_size [%d]\n", + dev_dbg(bp->dev, "[%zu] rx_buffer_size [%d]\n", size, bp->rx_buffer_size); } -- 2.7.4 Thomas Hämmerle Research and Development Wolfvision GmbH | 6833 Klaus | Austria Tel: +43 5523 52250 | Mail: thomas.haemme...@wolfvision.net Webpage: www.wolfvision.com | www.wolfvision.com/green Firmenbuch / Commercial Register: FN283521v Feldkirch/Austria ___ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox
[PATCH 3/6] macb: fix check if hw is gem
Fix check for peripheral version in MACB_MID register to treat Xilinx ZynqMP as GEM. All MIDs >= 2 indicate a GEM not only MID == 2. Signed-off-by: Thomas Haemmerle --- drivers/net/macb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/macb.c b/drivers/net/macb.c index 240802e..c776535 100644 --- a/drivers/net/macb.c +++ b/drivers/net/macb.c @@ -86,7 +86,7 @@ static inline bool macb_is_gem(struct macb_device *macb) static inline bool read_is_gem(struct macb_device *macb) { - return MACB_BFEXT(IDNUM, macb_readl(macb, MID)) == 0x2; + return MACB_BFEXT(IDNUM, macb_readl(macb, MID)) >= 0x2; } static int macb_send(struct eth_device *edev, void *packet, -- 2.7.4 Thomas Hämmerle Research and Development Wolfvision GmbH | 6833 Klaus | Austria Tel: +43 5523 52250 | Mail: thomas.haemme...@wolfvision.net Webpage: www.wolfvision.com | www.wolfvision.com/green Firmenbuch / Commercial Register: FN283521v Feldkirch/Austria ___ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox
[PATCH 4/6] macb: fix memory leakage due to double allocation of rx_buffer
Remove memory allocation of rx buffer in function macb_init_rx_buffer_size, which caused a memory leak since it also is alocated in macb_probe(). Signed-off-by: Thomas Haemmerle --- drivers/net/macb.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/net/macb.c b/drivers/net/macb.c index c776535..c129282 100644 --- a/drivers/net/macb.c +++ b/drivers/net/macb.c @@ -592,8 +592,6 @@ static void macb_init_rx_buffer_size(struct macb_device *bp, size_t size) bp->rx_buffer_size = roundup(bp->rx_buffer_size, RX_BUFFER_MULTIPLE); } - bp->rx_buffer = dma_alloc_coherent(bp->rx_buffer_size * bp->rx_ring_size, - DMA_ADDRESS_BROKEN); } dev_dbg(bp->dev, "[%zu] rx_buffer_size [%d]\n", -- 2.7.4 Thomas Hämmerle Research and Development Wolfvision GmbH | 6833 Klaus | Austria Tel: +43 5523 52250 | Mail: thomas.haemme...@wolfvision.net Webpage: www.wolfvision.com | www.wolfvision.com/green Firmenbuch / Commercial Register: FN283521v Feldkirch/Austria ___ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox