From 71f07731488e9ade674ee396208317ab2db3cce1 Mon Sep 17 00:00:00 2001 From: Ashok Reddy Soma Date: Mon, 27 Jun 2022 14:22:45 +0530 Subject: mmc: zynq_sdhci: Fix timing macros for MMC High speed Timing macro's are wrong for MMC_HS_52 and MMC_DDR_52. Fix it with correct values of MMC_TIMING_MMC_HS and MMC_TIMING_MMC_DDR52 respectively. Signed-off-by: Ashok Reddy Soma Link: https://lore.kernel.org/r/1656319965-12124-1-git-send-email-ashok.reddy.soma@xilinx.com Signed-off-by: Michal Simek --- drivers/mmc/zynq_sdhci.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/mmc/zynq_sdhci.c b/drivers/mmc/zynq_sdhci.c index e978b679885..8f4071c8c28 100644 --- a/drivers/mmc/zynq_sdhci.c +++ b/drivers/mmc/zynq_sdhci.c @@ -101,8 +101,8 @@ static const u8 mode2timing[] = { [MMC_LEGACY] = MMC_TIMING_LEGACY, [MMC_HS] = MMC_TIMING_MMC_HS, [SD_HS] = MMC_TIMING_SD_HS, - [MMC_HS_52] = MMC_TIMING_UHS_SDR50, - [MMC_DDR_52] = MMC_TIMING_UHS_DDR50, + [MMC_HS_52] = MMC_TIMING_MMC_HS, + [MMC_DDR_52] = MMC_TIMING_MMC_DDR52, [UHS_SDR12] = MMC_TIMING_UHS_SDR12, [UHS_SDR25] = MMC_TIMING_UHS_SDR25, [UHS_SDR50] = MMC_TIMING_UHS_SDR50, -- cgit v1.2.3 From c6bceb4e360d704fb9746541c18a1a08f49353fc Mon Sep 17 00:00:00 2001 From: Kunihiko Hayashi Date: Wed, 13 Jul 2022 10:38:59 +0900 Subject: serial: zynq: Use DIV_ROUND_CLOSEST() to calcurate divider value Since the calulation of "bgen" is rounded down, using a higher baudrate will result in a larger difference from the actual baudrate. Should use DIV_ROUND_CLOSEST() like the Linux driver. Signed-off-by: Kunihiko Hayashi Link: https://lore.kernel.org/r/1657676339-6055-1-git-send-email-hayashi.kunihiko@socionext.com Signed-off-by: Michal Simek --- drivers/serial/serial_zynq.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/serial/serial_zynq.c b/drivers/serial/serial_zynq.c index 83adfb5fb98..295337a8176 100644 --- a/drivers/serial/serial_zynq.c +++ b/drivers/serial/serial_zynq.c @@ -75,7 +75,7 @@ static void _uart_zynq_serial_setbrg(struct uart_zynq *regs, * Find acceptable values for baud generation. */ for (bdiv = 4; bdiv < 255; bdiv++) { - bgen = clock / (baud * (bdiv + 1)); + bgen = DIV_ROUND_CLOSEST(clock, baud * (bdiv + 1)); if (bgen < 2 || bgen > 65535) continue; -- cgit v1.2.3 From 9df50817405b358c5dd8c669030de7b1f8b15cb8 Mon Sep 17 00:00:00 2001 From: T Karthik Reddy Date: Wed, 20 Jul 2022 03:59:57 -0600 Subject: reset: zynqmp: Add reset driver support for versal Add support for versal platform by adding "xlnx,versal-reset" compatible string in zynqmp-reset driver. Reset numbering schema for versal is not same as zynqmp, so nr_reset and reset_id are set to zero. In case of assert/dessert, required device reset id is sent from respective driver through struct reset_ctl. Signed-off-by: T Karthik Reddy Signed-off-by: Ashok Reddy Soma Link: https://lore.kernel.org/r/20220720095959.29610-2-ashok.reddy.soma@xilinx.com Signed-off-by: Michal Simek --- drivers/reset/Kconfig | 6 +++--- drivers/reset/reset-zynqmp.c | 10 +++++++--- 2 files changed, 10 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/reset/Kconfig b/drivers/reset/Kconfig index b57714111b5..69a7b4ccbad 100644 --- a/drivers/reset/Kconfig +++ b/drivers/reset/Kconfig @@ -199,11 +199,11 @@ config RESET_SCMI protocol communication with a SCMI server. config RESET_ZYNQMP - bool "Reset Driver for Xilinx ZynqMP SoC's" + bool "Reset Driver for Xilinx ZynqMP & Versal SoC's" depends on DM_RESET && ZYNQMP_FIRMWARE help - Support for reset controller on Xilinx ZynqMP SoC. Driver is only - passing request via Xilinx firmware interface to TF-A and PMU + Support for reset controller on Xilinx ZynqMP & Versal SoC's. Driver + is only passing request via Xilinx firmware interface to TF-A and PMU firmware. config RESET_DRA7 diff --git a/drivers/reset/reset-zynqmp.c b/drivers/reset/reset-zynqmp.c index 4e3f907980f..52c08c4722d 100644 --- a/drivers/reset/reset-zynqmp.c +++ b/drivers/reset/reset-zynqmp.c @@ -53,7 +53,7 @@ static int zynqmp_reset_request(struct reset_ctl *rst) dev_dbg(rst->dev, "%s(rst=%p) (id=%lu) (nr_reset=%d)\n", __func__, rst, rst->id, priv->nr_reset); - if (rst->id > priv->nr_reset) + if (priv->nr_reset && rst->id > priv->nr_reset) return -EINVAL; return 0; @@ -63,8 +63,11 @@ static int zynqmp_reset_probe(struct udevice *dev) { struct zynqmp_reset_priv *priv = dev_get_priv(dev); - priv->reset_id = ZYNQMP_RESET_ID; - priv->nr_reset = ZYNQMP_NR_RESETS; + if (device_is_compatible(dev, "xlnx,zynqmp-reset")) { + priv->reset_id = ZYNQMP_RESET_ID; + priv->nr_reset = ZYNQMP_NR_RESETS; + } + return 0; } @@ -76,6 +79,7 @@ const struct reset_ops zynqmp_reset_ops = { static const struct udevice_id zynqmp_reset_ids[] = { { .compatible = "xlnx,zynqmp-reset" }, + { .compatible = "xlnx,versal-reset" }, { } }; -- cgit v1.2.3 From c9f12ed9bcb973297a33f50e1fa28506118bcb91 Mon Sep 17 00:00:00 2001 From: Ashok Reddy Soma Date: Fri, 22 Jul 2022 02:46:54 -0600 Subject: firmware: zynqmp: Change prototype of zynqmp_pmufw_load_config_object() zynqmp_pmufw_load_config_object() has some error cases and it is better to return those errors. Change prototype of this function to return errors. Signed-off-by: Ashok Reddy Soma Signed-off-by: Michal Simek Link: https://lore.kernel.org/r/20220722084658.30995-2-ashok.reddy.soma@xilinx.com --- drivers/firmware/firmware-zynqmp.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/firmware/firmware-zynqmp.c b/drivers/firmware/firmware-zynqmp.c index b0cd647aa51..325e4ddea6d 100644 --- a/drivers/firmware/firmware-zynqmp.c +++ b/drivers/firmware/firmware-zynqmp.c @@ -227,7 +227,7 @@ int zynqmp_pm_is_function_supported(const u32 api_id, const u32 id) * @cfg_obj: Pointer to the configuration object * @size: Size of @cfg_obj in bytes */ -void zynqmp_pmufw_load_config_object(const void *cfg_obj, size_t size) +int zynqmp_pmufw_load_config_object(const void *cfg_obj, size_t size) { int err; u32 ret_payload[PAYLOAD_ARG_CNT]; @@ -241,12 +241,12 @@ void zynqmp_pmufw_load_config_object(const void *cfg_obj, size_t size) 0, ret_payload); if (err == XST_PM_NO_ACCESS) { printf("PMUFW no permission to change config object\n"); - return; + return -EACCES; } if (err == XST_PM_ALREADY_CONFIGURED) { debug("PMUFW Node is already configured\n"); - return; + return -ENODEV; } if (err) @@ -257,6 +257,8 @@ void zynqmp_pmufw_load_config_object(const void *cfg_obj, size_t size) if ((err || ret_payload[0]) && IS_ENABLED(CONFIG_SPL_BUILD)) panic("PMUFW config object loading failed in EL3\n"); + + return 0; } static int zynqmp_power_probe(struct udevice *dev) -- cgit v1.2.3 From 2e40ab1f215641c53d2c60baa347892d159cafc9 Mon Sep 17 00:00:00 2001 From: Ashok Reddy Soma Date: Fri, 22 Jul 2022 02:46:55 -0600 Subject: firmware: zynqmp: Load config overlay for core0 to pmufw Try loading pmufw config overlay for core0, if it doesn't return any error it means pmufw is accepting nodes for other IP's. Otherwise dont try to load config object for any other IP, just return from zynqmp_pmufw_node function. Signed-off-by: Ashok Reddy Soma Signed-off-by: Michal Simek Link: https://lore.kernel.org/r/20220722084658.30995-3-ashok.reddy.soma@xilinx.com --- drivers/firmware/firmware-zynqmp.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/firmware/firmware-zynqmp.c b/drivers/firmware/firmware-zynqmp.c index 325e4ddea6d..76ddc6b4f40 100644 --- a/drivers/firmware/firmware-zynqmp.c +++ b/drivers/firmware/firmware-zynqmp.c @@ -70,11 +70,20 @@ int zynqmp_pmufw_config_close(void) int zynqmp_pmufw_node(u32 id) { + static bool skip_config; + int ret; + + if (skip_config) + return 0; + /* Record power domain id */ xpm_configobject[NODE_ID_LOCATION] = id; - zynqmp_pmufw_load_config_object(xpm_configobject, - sizeof(xpm_configobject)); + ret = zynqmp_pmufw_load_config_object(xpm_configobject, + sizeof(xpm_configobject)); + + if (ret && id == NODE_APU_0) + skip_config = true; return 0; } @@ -284,6 +293,9 @@ static int zynqmp_power_probe(struct udevice *dev) ret >> ZYNQMP_PM_VERSION_MAJOR_SHIFT, ret & ZYNQMP_PM_VERSION_MINOR_MASK); + if (IS_ENABLED(CONFIG_ARCH_ZYNQMP)) + zynqmp_pmufw_node(NODE_APU_0); + return 0; }; -- cgit v1.2.3 From cce33515010287a5bd7f4b6f9ebce0f56268a7f1 Mon Sep 17 00:00:00 2001 From: Ashok Reddy Soma Date: Fri, 22 Jul 2022 02:46:57 -0600 Subject: mailbox: zynqmp: Move struct zynqmp_ipi_msg from sys_proto.h Mailbox driver might be need for Versal and other future platforms. To remove the dependency, move struct zynqmp_ipi_msg to zynqmp_firmware.h so that mailbox driver compiles for other platforms easily. Signed-off-by: Ashok Reddy Soma Signed-off-by: Michal Simek Link: https://lore.kernel.org/r/20220722084658.30995-5-ashok.reddy.soma@xilinx.com --- drivers/mailbox/zynqmp-ipi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/mailbox/zynqmp-ipi.c b/drivers/mailbox/zynqmp-ipi.c index 959cce923c5..3e4ec47389f 100644 --- a/drivers/mailbox/zynqmp-ipi.c +++ b/drivers/mailbox/zynqmp-ipi.c @@ -11,10 +11,10 @@ #include #include #include -#include #include #include #include +#include /* IPI bitmasks, register base */ /* TODO: move reg base to DT */ -- cgit v1.2.3 From 5f53e534ac15ad63ee530a43536b8da6c30cd36d Mon Sep 17 00:00:00 2001 From: Ashok Reddy Soma Date: Fri, 22 Jul 2022 02:46:58 -0600 Subject: arm64: versal: Enable power domain driver and its dependencies Enable power domain driver to configure pmufw config object and request node for all the IP's that are enabled in DT. This driver depends on mailbox and IPI driver, hence enable them as well. Add ARCH_VERSAL in the depends on of mailbox Kconfig to compile for Versal platforms. Signed-off-by: Ashok Reddy Soma Signed-off-by: Michal Simek Link: https://lore.kernel.org/r/20220722084658.30995-6-ashok.reddy.soma@xilinx.com --- drivers/mailbox/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/mailbox/Kconfig b/drivers/mailbox/Kconfig index 73db2af0b81..acbdce11b7c 100644 --- a/drivers/mailbox/Kconfig +++ b/drivers/mailbox/Kconfig @@ -54,7 +54,7 @@ config K3_SEC_PROXY config ZYNQMP_IPI bool "Xilinx ZynqMP IPI controller support" - depends on DM_MAILBOX && ARCH_ZYNQMP + depends on DM_MAILBOX && (ARCH_ZYNQMP || ARCH_VERSAL) help This enables support for the Xilinx ZynqMP Inter Processor Interrupt communication controller. -- cgit v1.2.3 From e8ffc1dfcb1b4a7465ae7ec2b45569f0f27ff501 Mon Sep 17 00:00:00 2001 From: Alexander Dahl Date: Thu, 21 Jul 2022 15:31:21 +0200 Subject: fpga: Convert SYS_FPGA_CHECK_CTRLC to Kconfig MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit After commit 8cca60a2cbf2 ("Kconfig: Remove some symbols from the whitelist") downstream builds failed for boards setting this in include/configs/… Signed-off-by: Alexander Dahl Link: https://lore.kernel.org/r/20220721133122.32428-2-ada@thorsis.com Signed-off-by: Michal Simek --- drivers/fpga/Kconfig | 6 ++++++ drivers/fpga/virtex2.c | 7 ------- 2 files changed, 6 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/fpga/Kconfig b/drivers/fpga/Kconfig index 76719517f54..78d9588e4b7 100644 --- a/drivers/fpga/Kconfig +++ b/drivers/fpga/Kconfig @@ -91,4 +91,10 @@ config FPGA_ZYNQPL Enable FPGA driver for loading bitstream in BIT and BIN format on Xilinx Zynq devices. +config SYS_FPGA_CHECK_CTRLC + bool "Allow Control-C to interrupt FPGA configuration" + depends on FPGA + help + User can interrupt FPGA configuration by pressing CTRL+C. + endmenu diff --git a/drivers/fpga/virtex2.c b/drivers/fpga/virtex2.c index b3e0537bab0..0fd2290e3d3 100644 --- a/drivers/fpga/virtex2.c +++ b/drivers/fpga/virtex2.c @@ -45,13 +45,6 @@ #define CONFIG_SYS_FPGA_PROG_FEEDBACK #endif -/* - * Don't allow config cycle to be interrupted - */ -#ifndef CONFIG_SYS_FPGA_CHECK_CTRLC -#undef CONFIG_SYS_FPGA_CHECK_CTRLC -#endif - /* * Check for errors during configuration by default */ -- cgit v1.2.3 From 8c09cb6f4dc5eda57d2e9e76ee8b0f4e2e340071 Mon Sep 17 00:00:00 2001 From: Alexander Dahl Date: Thu, 21 Jul 2022 15:31:22 +0200 Subject: fpga: Convert SYS_FPGA_PROG_FEEDBACK to Kconfig This converts the following to Kconfig: SYS_FPGA_PROG_FEEDBACK Signed-off-by: Alexander Dahl Link: https://lore.kernel.org/r/20220721133122.32428-3-ada@thorsis.com Signed-off-by: Michal Simek --- drivers/fpga/Kconfig | 7 +++++++ drivers/fpga/spartan2.c | 1 - drivers/fpga/virtex2.c | 4 ---- 3 files changed, 7 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/fpga/Kconfig b/drivers/fpga/Kconfig index 78d9588e4b7..696ea92c6e9 100644 --- a/drivers/fpga/Kconfig +++ b/drivers/fpga/Kconfig @@ -97,4 +97,11 @@ config SYS_FPGA_CHECK_CTRLC help User can interrupt FPGA configuration by pressing CTRL+C. +config SYS_FPGA_PROG_FEEDBACK + bool "Progress output during FPGA configuration" + depends on FPGA + default y if FPGA_VIRTEX2 + help + Enable printing of hash marks during FPGA configuration. + endmenu diff --git a/drivers/fpga/spartan2.c b/drivers/fpga/spartan2.c index 3435400e58b..fe37752210b 100644 --- a/drivers/fpga/spartan2.c +++ b/drivers/fpga/spartan2.c @@ -15,7 +15,6 @@ #endif #undef CONFIG_SYS_FPGA_CHECK_BUSY -#undef CONFIG_SYS_FPGA_PROG_FEEDBACK /* Note: The assumption is that we cannot possibly run fast enough to * overrun the device (the Slave Parallel mode can free run at 50MHz). diff --git a/drivers/fpga/virtex2.c b/drivers/fpga/virtex2.c index 0fd2290e3d3..2e764bdcd52 100644 --- a/drivers/fpga/virtex2.c +++ b/drivers/fpga/virtex2.c @@ -41,10 +41,6 @@ #define CONFIG_FPGA_DELAY() #endif -#ifndef CONFIG_SYS_FPGA_PROG_FEEDBACK -#define CONFIG_SYS_FPGA_PROG_FEEDBACK -#endif - /* * Check for errors during configuration by default */ -- cgit v1.2.3 From fb2b88567d3b06095b089e70f75160a107710ea8 Mon Sep 17 00:00:00 2001 From: Oleksandr Suvorov Date: Fri, 22 Jul 2022 17:16:02 +0300 Subject: fpga: add option for loading FPGA secure bitstreams It allows using this feature without enabling the "fpga loads" command. Signed-off-by: Oleksandr Suvorov Co-developed-by: Adrian Fiergolski Signed-off-by: Adrian Fiergolski Tested-by: Ricardo Salveti Tested-by: Adrian Fiergolski Link: https://lore.kernel.org/r/20220722141614.297383-2-oleksandr.suvorov@foundries.io Signed-off-by: Michal Simek --- drivers/fpga/Kconfig | 14 ++++++++++++++ drivers/fpga/fpga.c | 2 +- drivers/fpga/xilinx.c | 2 +- drivers/fpga/zynqmppl.c | 4 ++-- 4 files changed, 18 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/fpga/Kconfig b/drivers/fpga/Kconfig index 696ea92c6e9..e07a9cf80ea 100644 --- a/drivers/fpga/Kconfig +++ b/drivers/fpga/Kconfig @@ -104,4 +104,18 @@ config SYS_FPGA_PROG_FEEDBACK help Enable printing of hash marks during FPGA configuration. +config FPGA_LOAD_SECURE + bool "Enable loading secure bitstreams" + depends on FPGA + help + Enables the fpga loads() functions that are used to load secure + (authenticated or encrypted or both) bitstreams on to FPGA. + +config SPL_FPGA_LOAD_SECURE + bool "Enable loading secure bitstreams for SPL" + depends on SPL_FPGA + help + Enables the fpga loads() functions that are used to load secure + (authenticated or encrypted or both) bitstreams on to FPGA. + endmenu diff --git a/drivers/fpga/fpga.c b/drivers/fpga/fpga.c index fe3dfa12335..3b0a44b2420 100644 --- a/drivers/fpga/fpga.c +++ b/drivers/fpga/fpga.c @@ -220,7 +220,7 @@ int fpga_fsload(int devnum, const void *buf, size_t size, } #endif -#if defined(CONFIG_CMD_FPGA_LOAD_SECURE) +#if CONFIG_IS_ENABLED(FPGA_LOAD_SECURE) int fpga_loads(int devnum, const void *buf, size_t size, struct fpga_secure_info *fpga_sec_info) { diff --git a/drivers/fpga/xilinx.c b/drivers/fpga/xilinx.c index cbebefb55fe..6bc1bc491fb 100644 --- a/drivers/fpga/xilinx.c +++ b/drivers/fpga/xilinx.c @@ -172,7 +172,7 @@ int xilinx_loadfs(xilinx_desc *desc, const void *buf, size_t bsize, } #endif -#if defined(CONFIG_CMD_FPGA_LOAD_SECURE) +#if CONFIG_IS_ENABLED(FPGA_LOAD_SECURE) int xilinx_loads(xilinx_desc *desc, const void *buf, size_t bsize, struct fpga_secure_info *fpga_sec_info) { diff --git a/drivers/fpga/zynqmppl.c b/drivers/fpga/zynqmppl.c index 6b394869dbf..8ff12bf50a0 100644 --- a/drivers/fpga/zynqmppl.c +++ b/drivers/fpga/zynqmppl.c @@ -245,7 +245,7 @@ static int zynqmp_load(xilinx_desc *desc, const void *buf, size_t bsize, return ret; } -#if defined(CONFIG_CMD_FPGA_LOAD_SECURE) && !defined(CONFIG_SPL_BUILD) +#if CONFIG_IS_ENABLED(FPGA_LOAD_SECURE) static int zynqmp_loads(xilinx_desc *desc, const void *buf, size_t bsize, struct fpga_secure_info *fpga_sec_info) { @@ -306,7 +306,7 @@ static int zynqmp_pcap_info(xilinx_desc *desc) struct xilinx_fpga_op zynqmp_op = { .load = zynqmp_load, -#if defined(CONFIG_CMD_FPGA_LOAD_SECURE) && !defined(CONFIG_SPL_BUILD) +#if CONFIG_IS_ENABLED(FPGA_LOAD_SECURE) .loads = zynqmp_loads, #endif .info = zynqmp_pcap_info, -- cgit v1.2.3 From 24307b06b71a3c9b4aa556eefdad1f8fcca116bd Mon Sep 17 00:00:00 2001 From: Oleksandr Suvorov Date: Fri, 22 Jul 2022 17:16:05 +0300 Subject: fpga: zynqmp: add str2flags call Add a call to convert FPGA "compatible" string to a binary flag. Signed-off-by: Oleksandr Suvorov Tested-by: Ricardo Salveti Tested-by: Adrian Fiergolski Link: https://lore.kernel.org/r/20220722141614.297383-5-oleksandr.suvorov@foundries.io Signed-off-by: Michal Simek --- drivers/fpga/zynqmppl.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/fpga/zynqmppl.c b/drivers/fpga/zynqmppl.c index 8ff12bf50a0..19d079c9d9f 100644 --- a/drivers/fpga/zynqmppl.c +++ b/drivers/fpga/zynqmppl.c @@ -304,10 +304,19 @@ static int zynqmp_pcap_info(xilinx_desc *desc) return ret; } +static int __maybe_unused zynqmp_str2flag(xilinx_desc *desc, const char *str) +{ + if (!strncmp(str, "u-boot,fpga-legacy", 18)) + return FPGA_LEGACY; + + return 0; +} + struct xilinx_fpga_op zynqmp_op = { .load = zynqmp_load, + .info = zynqmp_pcap_info, #if CONFIG_IS_ENABLED(FPGA_LOAD_SECURE) .loads = zynqmp_loads, + .str2flag = zynqmp_str2flag, #endif - .info = zynqmp_pcap_info, }; -- cgit v1.2.3 From 7a9a0df89bf1cb9f7e78378f946f1d9c9b002d72 Mon Sep 17 00:00:00 2001 From: Oleksandr Suvorov Date: Fri, 22 Jul 2022 17:16:06 +0300 Subject: fpga: xilinx: pass compatible flags to xilinx_load() This flag is used to check whether a Xilinx FPGA driver is able to load a particular FPGA bitstream image. Signed-off-by: Oleksandr Suvorov Tested-by: Ricardo Salveti Tested-by: Adrian Fiergolski Link: https://lore.kernel.org/r/20220722141614.297383-6-oleksandr.suvorov@foundries.io Signed-off-by: Michal Simek --- drivers/fpga/fpga.c | 2 +- drivers/fpga/xilinx.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/fpga/fpga.c b/drivers/fpga/fpga.c index 3b0a44b2420..efbac9f0c47 100644 --- a/drivers/fpga/fpga.c +++ b/drivers/fpga/fpga.c @@ -263,7 +263,7 @@ int fpga_load(int devnum, const void *buf, size_t bsize, bitstream_type bstype) case fpga_xilinx: #if defined(CONFIG_FPGA_XILINX) ret_val = xilinx_load(desc->devdesc, buf, bsize, - bstype); + bstype, 0); #else fpga_no_sup((char *)__func__, "Xilinx devices"); #endif diff --git a/drivers/fpga/xilinx.c b/drivers/fpga/xilinx.c index 6bc1bc491fb..5dd721575ec 100644 --- a/drivers/fpga/xilinx.c +++ b/drivers/fpga/xilinx.c @@ -139,7 +139,7 @@ int fpga_loadbitstream(int devnum, char *fpgadata, size_t size, } int xilinx_load(xilinx_desc *desc, const void *buf, size_t bsize, - bitstream_type bstype) + bitstream_type bstype, int flags) { if (!xilinx_validate (desc, (char *)__FUNCTION__)) { printf ("%s: Invalid device descriptor\n", __FUNCTION__); -- cgit v1.2.3 From 282eed50ecb73c20dd35bf3ea7a579e79b20cd54 Mon Sep 17 00:00:00 2001 From: Oleksandr Suvorov Date: Fri, 22 Jul 2022 17:16:07 +0300 Subject: fpga: pass compatible flags to fpga_load() These flags may be used to check whether an FPGA driver is able to load a particular FPGA bitstream image. Signed-off-by: Oleksandr Suvorov Tested-by: Ricardo Salveti Tested-by: Adrian Fiergolski Link: https://lore.kernel.org/r/20220722141614.297383-7-oleksandr.suvorov@foundries.io Signed-off-by: Michal Simek --- drivers/fpga/fpga.c | 5 +++-- drivers/fpga/xilinx.c | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/fpga/fpga.c b/drivers/fpga/fpga.c index efbac9f0c47..185bd547cb5 100644 --- a/drivers/fpga/fpga.c +++ b/drivers/fpga/fpga.c @@ -252,7 +252,8 @@ int fpga_loads(int devnum, const void *buf, size_t size, /* * Generic multiplexing code */ -int fpga_load(int devnum, const void *buf, size_t bsize, bitstream_type bstype) +int fpga_load(int devnum, const void *buf, size_t bsize, bitstream_type bstype, + int flags) { int ret_val = FPGA_FAIL; /* assume failure */ const fpga_desc *desc = fpga_validate(devnum, buf, bsize, @@ -263,7 +264,7 @@ int fpga_load(int devnum, const void *buf, size_t bsize, bitstream_type bstype) case fpga_xilinx: #if defined(CONFIG_FPGA_XILINX) ret_val = xilinx_load(desc->devdesc, buf, bsize, - bstype, 0); + bstype, flags); #else fpga_no_sup((char *)__func__, "Xilinx devices"); #endif diff --git a/drivers/fpga/xilinx.c b/drivers/fpga/xilinx.c index 5dd721575ec..d9951ca3ecf 100644 --- a/drivers/fpga/xilinx.c +++ b/drivers/fpga/xilinx.c @@ -135,7 +135,7 @@ int fpga_loadbitstream(int devnum, char *fpgadata, size_t size, dataptr += 4; printf(" bytes in bitstream = %d\n", swapsize); - return fpga_load(devnum, dataptr, swapsize, bstype); + return fpga_load(devnum, dataptr, swapsize, bstype, 0); } int xilinx_load(xilinx_desc *desc, const void *buf, size_t bsize, -- cgit v1.2.3 From 2c60514d9aecf7fbbbe3c4cb3a4a4acc421e5239 Mon Sep 17 00:00:00 2001 From: Oleksandr Suvorov Date: Fri, 22 Jul 2022 17:16:08 +0300 Subject: fpga: add fpga_compatible2flag Add a "compatible" string to binary flag converter, which uses a callback str2flag() of given FPGA driver if available. Signed-off-by: Oleksandr Suvorov Tested-by: Ricardo Salveti Tested-by: Adrian Fiergolski Link: https://lore.kernel.org/r/20220722141614.297383-8-oleksandr.suvorov@foundries.io Signed-off-by: Michal Simek --- drivers/fpga/fpga.c | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) (limited to 'drivers') diff --git a/drivers/fpga/fpga.c b/drivers/fpga/fpga.c index 185bd547cb5..4db5c0a91e9 100644 --- a/drivers/fpga/fpga.c +++ b/drivers/fpga/fpga.c @@ -357,3 +357,29 @@ int fpga_info(int devnum) return fpga_dev_info(devnum); } + +#if CONFIG_IS_ENABLED(FPGA_LOAD_SECURE) +int fpga_compatible2flag(int devnum, const char *compatible) +{ + const fpga_desc * const desc = fpga_get_desc(devnum); + + if (!desc) + return 0; + + switch (desc->devtype) { +#if defined(CONFIG_FPGA_XILINX) + case fpga_xilinx: + { + xilinx_desc *xdesc = (xilinx_desc *)desc->devdesc; + + if (xdesc->operations && xdesc->operations->str2flag) + return xdesc->operations->str2flag(xdesc, compatible); + } +#endif + default: + break; + } + + return 0; +} +#endif -- cgit v1.2.3 From 3e78481de94d94f753bbf05486734b8da394643f Mon Sep 17 00:00:00 2001 From: Oleksandr Suvorov Date: Fri, 22 Jul 2022 17:16:10 +0300 Subject: fpga: xilinx: pass compatible flags to load() callback These flags may be used to check whether an FPGA driver is able to load a particular FPGA bitstream image. Signed-off-by: Oleksandr Suvorov Tested-by: Ricardo Salveti Tested-by: Adrian Fiergolski Link: https://lore.kernel.org/r/20220722141614.297383-10-oleksandr.suvorov@foundries.io Signed-off-by: Michal Simek --- drivers/fpga/spartan2.c | 2 +- drivers/fpga/spartan3.c | 2 +- drivers/fpga/versalpl.c | 2 +- drivers/fpga/virtex2.c | 2 +- drivers/fpga/xilinx.c | 2 +- drivers/fpga/zynqmppl.c | 2 +- drivers/fpga/zynqpl.c | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/fpga/spartan2.c b/drivers/fpga/spartan2.c index fe37752210b..47692e32076 100644 --- a/drivers/fpga/spartan2.c +++ b/drivers/fpga/spartan2.c @@ -40,7 +40,7 @@ static int spartan2_ss_dump(xilinx_desc *desc, const void *buf, size_t bsize); /* ------------------------------------------------------------------------- */ /* Spartan-II Generic Implementation */ static int spartan2_load(xilinx_desc *desc, const void *buf, size_t bsize, - bitstream_type bstype) + bitstream_type bstype, int flags) { int ret_val = FPGA_FAIL; diff --git a/drivers/fpga/spartan3.c b/drivers/fpga/spartan3.c index 4850c99352d..918f6db5065 100644 --- a/drivers/fpga/spartan3.c +++ b/drivers/fpga/spartan3.c @@ -45,7 +45,7 @@ static int spartan3_ss_dump(xilinx_desc *desc, const void *buf, size_t bsize); /* ------------------------------------------------------------------------- */ /* Spartan-II Generic Implementation */ static int spartan3_load(xilinx_desc *desc, const void *buf, size_t bsize, - bitstream_type bstype) + bitstream_type bstype, int flags) { int ret_val = FPGA_FAIL; diff --git a/drivers/fpga/versalpl.c b/drivers/fpga/versalpl.c index c44a7d34557..d3876a8f541 100644 --- a/drivers/fpga/versalpl.c +++ b/drivers/fpga/versalpl.c @@ -27,7 +27,7 @@ static ulong versal_align_dma_buffer(ulong *buf, u32 len) } static int versal_load(xilinx_desc *desc, const void *buf, size_t bsize, - bitstream_type bstype) + bitstream_type bstype, int flags) { ulong bin_buf; int ret; diff --git a/drivers/fpga/virtex2.c b/drivers/fpga/virtex2.c index 2e764bdcd52..51b8d312056 100644 --- a/drivers/fpga/virtex2.c +++ b/drivers/fpga/virtex2.c @@ -83,7 +83,7 @@ static int virtex2_ss_load(xilinx_desc *desc, const void *buf, size_t bsize); static int virtex2_ss_dump(xilinx_desc *desc, const void *buf, size_t bsize); static int virtex2_load(xilinx_desc *desc, const void *buf, size_t bsize, - bitstream_type bstype) + bitstream_type bstype, int flags) { int ret_val = FPGA_FAIL; diff --git a/drivers/fpga/xilinx.c b/drivers/fpga/xilinx.c index d9951ca3ecf..8170c3368ef 100644 --- a/drivers/fpga/xilinx.c +++ b/drivers/fpga/xilinx.c @@ -151,7 +151,7 @@ int xilinx_load(xilinx_desc *desc, const void *buf, size_t bsize, return FPGA_FAIL; } - return desc->operations->load(desc, buf, bsize, bstype); + return desc->operations->load(desc, buf, bsize, bstype, flags); } #if defined(CONFIG_CMD_FPGA_LOADFS) diff --git a/drivers/fpga/zynqmppl.c b/drivers/fpga/zynqmppl.c index 19d079c9d9f..a0624567882 100644 --- a/drivers/fpga/zynqmppl.c +++ b/drivers/fpga/zynqmppl.c @@ -200,7 +200,7 @@ static int zynqmp_validate_bitstream(xilinx_desc *desc, const void *buf, } static int zynqmp_load(xilinx_desc *desc, const void *buf, size_t bsize, - bitstream_type bstype) + bitstream_type bstype, int flags) { ALLOC_CACHE_ALIGN_BUFFER(u32, bsizeptr, 1); u32 swap = 0; diff --git a/drivers/fpga/zynqpl.c b/drivers/fpga/zynqpl.c index 2de40109a81..d8ebd542abd 100644 --- a/drivers/fpga/zynqpl.c +++ b/drivers/fpga/zynqpl.c @@ -371,7 +371,7 @@ static int zynq_validate_bitstream(xilinx_desc *desc, const void *buf, } static int zynq_load(xilinx_desc *desc, const void *buf, size_t bsize, - bitstream_type bstype) + bitstream_type bstype, int flags) { unsigned long ts; /* Timestamp */ u32 isr_status, swap; -- cgit v1.2.3 From fcd91cb782c9c659c5db65c9aa5fb7e0497de1ec Mon Sep 17 00:00:00 2001 From: Oleksandr Suvorov Date: Fri, 22 Jul 2022 17:16:11 +0300 Subject: fpga: zynqmp: reduce zynqmppl_load() code Reduce the function code by calling xilinx_pm_request() once only. Use the same variable bsize_req to store either bstream size in bytes or an address of bstream size according to a type required by the firmware version. Remove obsolete debug(). Signed-off-by: Oleksandr Suvorov Tested-by: Ricardo Salveti Tested-by: Adrian Fiergolski Link: https://lore.kernel.org/r/20220722141614.297383-11-oleksandr.suvorov@foundries.io Signed-off-by: Michal Simek --- drivers/fpga/zynqmppl.c | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/fpga/zynqmppl.c b/drivers/fpga/zynqmppl.c index a0624567882..2791f931861 100644 --- a/drivers/fpga/zynqmppl.c +++ b/drivers/fpga/zynqmppl.c @@ -207,38 +207,33 @@ static int zynqmp_load(xilinx_desc *desc, const void *buf, size_t bsize, ulong bin_buf; int ret; u32 buf_lo, buf_hi; + u32 bsize_req = (u32)bsize; u32 ret_payload[PAYLOAD_ARG_CNT]; - bool xilfpga_old = false; if (zynqmp_firmware_version() <= PMUFW_V1_0) { puts("WARN: PMUFW v1.0 or less is detected\n"); puts("WARN: Not all bitstream formats are supported\n"); puts("WARN: Please upgrade PMUFW\n"); - xilfpga_old = true; if (zynqmp_validate_bitstream(desc, buf, bsize, bsize, &swap)) return FPGA_FAIL; bsizeptr = (u32 *)&bsize; flush_dcache_range((ulong)bsizeptr, (ulong)bsizeptr + sizeof(size_t)); + bsize_req = (u32)(uintptr_t)bsizeptr; bstype |= BIT(ZYNQMP_FPGA_BIT_NS); + } else { + bstype = 0; } bin_buf = zynqmp_align_dma_buffer((u32 *)buf, bsize, swap); - debug("%s called!\n", __func__); flush_dcache_range(bin_buf, bin_buf + bsize); buf_lo = (u32)bin_buf; buf_hi = upper_32_bits(bin_buf); - if (xilfpga_old) - ret = xilinx_pm_request(PM_FPGA_LOAD, buf_lo, - buf_hi, (u32)(uintptr_t)bsizeptr, - bstype, ret_payload); - else - ret = xilinx_pm_request(PM_FPGA_LOAD, buf_lo, - buf_hi, (u32)bsize, 0, ret_payload); - + ret = xilinx_pm_request(PM_FPGA_LOAD, buf_lo, buf_hi, + bsize_req, bstype, ret_payload); if (ret) printf("PL FPGA LOAD failed with err: 0x%08x\n", ret); -- cgit v1.2.3 From 5ab6a846349471be9b640da35d757d55dd8de487 Mon Sep 17 00:00:00 2001 From: Oleksandr Suvorov Date: Fri, 22 Jul 2022 17:16:12 +0300 Subject: fpga: zynqmp: add bitstream compatible checking Check whether the FPGA ZynqMP driver supports the given bitstream image type. Signed-off-by: Oleksandr Suvorov Tested-by: Ricardo Salveti Tested-by: Adrian Fiergolski Link: https://lore.kernel.org/r/20220722141614.297383-12-oleksandr.suvorov@foundries.io Signed-off-by: Michal Simek --- drivers/fpga/zynqmppl.c | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) (limited to 'drivers') diff --git a/drivers/fpga/zynqmppl.c b/drivers/fpga/zynqmppl.c index 2791f931861..feaf34fff11 100644 --- a/drivers/fpga/zynqmppl.c +++ b/drivers/fpga/zynqmppl.c @@ -199,6 +199,28 @@ static int zynqmp_validate_bitstream(xilinx_desc *desc, const void *buf, return 0; } +#if CONFIG_IS_ENABLED(FPGA_LOAD_SECURE) +static int zynqmp_check_compatible(xilinx_desc *desc, int flags) +{ + /* If no flags set, the image is legacy */ + if (!flags) + return 0; + + /* For legacy bitstream images no need for other methods exist */ + if ((flags & desc->flags) && flags == FPGA_LEGACY) + return 0; + + /* + * Other images are handled in secure callback loads(). Check + * callback existence besides image type support. + */ + if (desc->operations->loads && (flags & desc->flags)) + return 0; + + return FPGA_FAIL; +} +#endif + static int zynqmp_load(xilinx_desc *desc, const void *buf, size_t bsize, bitstream_type bstype, int flags) { @@ -210,6 +232,18 @@ static int zynqmp_load(xilinx_desc *desc, const void *buf, size_t bsize, u32 bsize_req = (u32)bsize; u32 ret_payload[PAYLOAD_ARG_CNT]; +#if CONFIG_IS_ENABLED(FPGA_LOAD_SECURE) + ret = zynqmp_check_compatible(desc, flags); + if (ret) { + if (ret != -ENODATA) { + puts("Missing loads() operation or unsupported bitstream type\n"); + return FPGA_FAIL; + } + /* If flags is not set, the image treats as legacy */ + flags = FPGA_LEGACY; + } +#endif + if (zynqmp_firmware_version() <= PMUFW_V1_0) { puts("WARN: PMUFW v1.0 or less is detected\n"); puts("WARN: Not all bitstream formats are supported\n"); -- cgit v1.2.3 From a3a1afb747d4d71c3dd5ba01b2796cebd65c65cd Mon Sep 17 00:00:00 2001 From: Oleksandr Suvorov Date: Fri, 22 Jul 2022 17:16:13 +0300 Subject: fpga: zynqmp: support loading authenticated images Add supporting new compatible string "u-boot,zynqmp-fpga-ddrauth" to handle loading authenticated images (DDR). Based on solution by Jorge Ramirez-Ortiz Signed-off-by: Oleksandr Suvorov Tested-by: Ricardo Salveti Link: https://lore.kernel.org/r/20220722141614.297383-13-oleksandr.suvorov@foundries.io Signed-off-by: Michal Simek --- drivers/fpga/zynqmppl.c | 33 ++++++++++++++++++++++++++++----- 1 file changed, 28 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/fpga/zynqmppl.c b/drivers/fpga/zynqmppl.c index feaf34fff11..fc55d7a388f 100644 --- a/drivers/fpga/zynqmppl.c +++ b/drivers/fpga/zynqmppl.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -202,9 +203,12 @@ static int zynqmp_validate_bitstream(xilinx_desc *desc, const void *buf, #if CONFIG_IS_ENABLED(FPGA_LOAD_SECURE) static int zynqmp_check_compatible(xilinx_desc *desc, int flags) { - /* If no flags set, the image is legacy */ + /* + * If no flags set, the image may be legacy, but we need to + * signal caller this situation with specific error code. + */ if (!flags) - return 0; + return -ENODATA; /* For legacy bitstream images no need for other methods exist */ if ((flags & desc->flags) && flags == FPGA_LEGACY) @@ -217,7 +221,7 @@ static int zynqmp_check_compatible(xilinx_desc *desc, int flags) if (desc->operations->loads && (flags & desc->flags)) return 0; - return FPGA_FAIL; + return -ENODEV; } #endif @@ -231,8 +235,9 @@ static int zynqmp_load(xilinx_desc *desc, const void *buf, size_t bsize, u32 buf_lo, buf_hi; u32 bsize_req = (u32)bsize; u32 ret_payload[PAYLOAD_ARG_CNT]; - #if CONFIG_IS_ENABLED(FPGA_LOAD_SECURE) + struct fpga_secure_info info = { 0 }; + ret = zynqmp_check_compatible(desc, flags); if (ret) { if (ret != -ENODATA) { @@ -242,6 +247,21 @@ static int zynqmp_load(xilinx_desc *desc, const void *buf, size_t bsize, /* If flags is not set, the image treats as legacy */ flags = FPGA_LEGACY; } + + switch (flags) { + case FPGA_LEGACY: + break; /* Handle the legacy image later in this function */ +#if CONFIG_IS_ENABLED(FPGA_LOAD_SECURE) + case FPGA_XILINX_ZYNQMP_DDRAUTH: + /* DDR authentication */ + info.authflag = ZYNQMP_FPGA_AUTH_DDR; + info.encflag = FPGA_NO_ENC_OR_NO_AUTH; + return desc->operations->loads(desc, buf, bsize, &info); +#endif + default: + printf("Unsupported bitstream type %d\n", flags); + return FPGA_FAIL; + } #endif if (zynqmp_firmware_version() <= PMUFW_V1_0) { @@ -337,7 +357,10 @@ static int __maybe_unused zynqmp_str2flag(xilinx_desc *desc, const char *str) { if (!strncmp(str, "u-boot,fpga-legacy", 18)) return FPGA_LEGACY; - +#if CONFIG_IS_ENABLED(FPGA_LOAD_SECURE) + if (!strncmp(str, "u-boot,zynqmp-fpga-ddrauth", 26)) + return FPGA_XILINX_ZYNQMP_DDRAUTH; +#endif return 0; } -- cgit v1.2.3 From b524f8fb1e94a8e649ba06a7cb87e6dcaa96ebc3 Mon Sep 17 00:00:00 2001 From: Adrian Fiergolski Date: Fri, 22 Jul 2022 17:16:14 +0300 Subject: fpga: zynqmp: support loading encrypted bitfiles Add supporting new compatible string "u-boot,zynqmp-fpga-enc" to handle loading encrypted bitfiles. This feature requires encrypted FSBL, as according to UG1085: "The CSU automatically locks out the AES key, stored in either BBRAM or eFUSEs, as a key source to the AES engine if the FSBL is not encrypted. This prevents using the BBRAM or eFUSE as the key source to the AES engine during run-time applications." Signed-off-by: Adrian Fiergolski Co-developed-by: Oleksandr Suvorov Signed-off-by: Oleksandr Suvorov Tested-by: Adrian Fiergolski Link: https://lore.kernel.org/r/20220722141614.297383-14-oleksandr.suvorov@foundries.io Signed-off-by: Michal Simek --- drivers/fpga/zynqmppl.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'drivers') diff --git a/drivers/fpga/zynqmppl.c b/drivers/fpga/zynqmppl.c index fc55d7a388f..d1491da02c3 100644 --- a/drivers/fpga/zynqmppl.c +++ b/drivers/fpga/zynqmppl.c @@ -257,6 +257,11 @@ static int zynqmp_load(xilinx_desc *desc, const void *buf, size_t bsize, info.authflag = ZYNQMP_FPGA_AUTH_DDR; info.encflag = FPGA_NO_ENC_OR_NO_AUTH; return desc->operations->loads(desc, buf, bsize, &info); + case FPGA_XILINX_ZYNQMP_ENC: + /* Encryption using device key */ + info.authflag = FPGA_NO_ENC_OR_NO_AUTH; + info.encflag = FPGA_ENC_DEV_KEY; + return desc->operations->loads(desc, buf, bsize, &info); #endif default: printf("Unsupported bitstream type %d\n", flags); @@ -360,6 +365,9 @@ static int __maybe_unused zynqmp_str2flag(xilinx_desc *desc, const char *str) #if CONFIG_IS_ENABLED(FPGA_LOAD_SECURE) if (!strncmp(str, "u-boot,zynqmp-fpga-ddrauth", 26)) return FPGA_XILINX_ZYNQMP_DDRAUTH; + + if (!strncmp(str, "u-boot,zynqmp-fpga-enc", 22)) + return FPGA_XILINX_ZYNQMP_ENC; #endif return 0; } -- cgit v1.2.3 From f2dd6599df65dd307d7170f1b2fc0d38eb44ad75 Mon Sep 17 00:00:00 2001 From: T Karthik Reddy Date: Sat, 16 Jul 2022 12:28:46 +0530 Subject: spi: xilinx_spi: Add support for spi memory operations Add support for spi memory operations for xilinx AXI qspi driver. This provides an high-level interface to execute SPI memory operations by the controller. Remove existing spi transfer based implementation and use spi memory based exec_op() implementation for qspi IO operations. Simplified existing startup_block implementation. Signed-off-by: T Karthik Reddy Signed-off-by: Ashok Reddy Soma Link: https://lore.kernel.org/r/1657954727-31972-2-git-send-email-ashok.reddy.soma@xilinx.com Signed-off-by: Michal Simek --- drivers/spi/xilinx_spi.c | 194 ++++++++++++++++++++++++++++------------------- 1 file changed, 116 insertions(+), 78 deletions(-) (limited to 'drivers') diff --git a/drivers/spi/xilinx_spi.c b/drivers/spi/xilinx_spi.c index b892cdae9ba..09d4b01631f 100644 --- a/drivers/spi/xilinx_spi.c +++ b/drivers/spi/xilinx_spi.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include @@ -73,7 +74,7 @@ #define XILSPI_MAX_XFER_BITS 8 #define XILSPI_SPICR_DFLT_ON (SPICR_MANUAL_SS | SPICR_MASTER_MODE | \ - SPICR_SPE) + SPICR_SPE | SPICR_MASTER_INHIBIT) #define XILSPI_SPICR_DFLT_OFF (SPICR_MASTER_INHIBIT | SPICR_MANUAL_SS) #define XILINX_SPI_IDLE_VAL GENMASK(7, 0) @@ -119,6 +120,15 @@ static int xilinx_spi_probe(struct udevice *bus) writel(SPISSR_RESET_VALUE, ®s->srr); + /* + * Reset RX & TX FIFO + * Enable Manual Slave Select Assertion, + * Set SPI controller into master mode, and enable it + */ + writel(SPICR_RXFIFO_RESEST | SPICR_TXFIFO_RESEST | + SPICR_MANUAL_SS | SPICR_MASTER_MODE | SPICR_SPE, + ®s->spicr); + return 0; } @@ -136,7 +146,10 @@ static void spi_cs_deactivate(struct udevice *dev) struct udevice *bus = dev_get_parent(dev); struct xilinx_spi_priv *priv = dev_get_priv(bus); struct xilinx_spi_regs *regs = priv->regs; + u32 reg; + reg = readl(®s->spicr) | SPICR_RXFIFO_RESEST | SPICR_TXFIFO_RESEST; + writel(reg, ®s->spicr); writel(SPISSR_OFF, ®s->spissr); } @@ -205,81 +218,24 @@ static u32 xilinx_spi_read_rxfifo(struct udevice *bus, u8 *rxp, u32 rxbytes) return i; } -static void xilinx_spi_startup_block(struct udevice *dev, unsigned int bytes, - const void *dout, void *din) +static int start_transfer(struct spi_slave *spi, const void *dout, void *din, u32 len) { - struct udevice *bus = dev_get_parent(dev); + struct udevice *bus = spi->dev->parent; struct xilinx_spi_priv *priv = dev_get_priv(bus); struct xilinx_spi_regs *regs = priv->regs; - struct dm_spi_slave_plat *slave_plat = dev_get_parent_plat(dev); - const unsigned char *txp = dout; - unsigned char *rxp = din; - u32 reg; - u32 txbytes = bytes; - u32 rxbytes = bytes; - - /* - * This loop runs two times. First time to send the command. - * Second time to transfer data. After transferring data, - * it sets txp to the initial value for the normal operation. - */ - for ( ; priv->startup < 2; priv->startup++) { - xilinx_spi_fill_txfifo(bus, txp, txbytes); - reg = readl(®s->spicr) & ~SPICR_MASTER_INHIBIT; + u32 count, txbytes, rxbytes; + int reg, ret; + const unsigned char *txp = (const unsigned char *)dout; + unsigned char *rxp = (unsigned char *)din; + + txbytes = len; + rxbytes = len; + while (txbytes || rxbytes) { + /* Disable master transaction */ + reg = readl(®s->spicr) | SPICR_MASTER_INHIBIT; writel(reg, ®s->spicr); - xilinx_spi_read_rxfifo(bus, rxp, rxbytes); - txp = din; - - if (priv->startup) { - spi_cs_deactivate(dev); - spi_cs_activate(dev, slave_plat->cs); - txp = dout; - } - } -} - -static int xilinx_spi_xfer(struct udevice *dev, unsigned int bitlen, - const void *dout, void *din, unsigned long flags) -{ - struct udevice *bus = dev_get_parent(dev); - struct xilinx_spi_priv *priv = dev_get_priv(bus); - struct xilinx_spi_regs *regs = priv->regs; - struct dm_spi_slave_plat *slave_plat = dev_get_parent_plat(dev); - /* assume spi core configured to do 8 bit transfers */ - unsigned int bytes = bitlen / XILSPI_MAX_XFER_BITS; - const unsigned char *txp = dout; - unsigned char *rxp = din; - u32 txbytes = bytes; - u32 rxbytes = bytes; - u32 reg, count; - int ret; - - debug("spi_xfer: bus:%i cs:%i bitlen:%i bytes:%i flags:%lx\n", - dev_seq(bus), slave_plat->cs, bitlen, bytes, flags); - - if (bitlen == 0) - goto done; - - if (bitlen % XILSPI_MAX_XFER_BITS) { - printf("XILSPI warning: Not a multiple of %d bits\n", - XILSPI_MAX_XFER_BITS); - flags |= SPI_XFER_END; - goto done; - } - - if (flags & SPI_XFER_BEGIN) - spi_cs_activate(dev, slave_plat->cs); - - /* - * This is the work around for the startup block issue in - * the spi controller. SPI clock is passing through STARTUP - * block to FLASH. STARTUP block don't provide clock as soon - * as QSPI provides command. So first command fails. - */ - xilinx_spi_startup_block(dev, bytes, dout, din); - - while (txbytes && rxbytes) { count = xilinx_spi_fill_txfifo(bus, txp, txbytes); + /* Enable master transaction */ reg = readl(®s->spicr) & ~SPICR_MASTER_INHIBIT; writel(reg, ®s->spicr); txbytes -= count; @@ -293,21 +249,99 @@ static int xilinx_spi_xfer(struct udevice *dev, unsigned int bitlen, return ret; } - debug("txbytes:0x%x,txp:0x%p\n", txbytes, txp); + reg = readl(®s->spicr) | SPICR_MASTER_INHIBIT; + writel(reg, ®s->spicr); count = xilinx_spi_read_rxfifo(bus, rxp, rxbytes); rxbytes -= count; if (rxp) rxp += count; - debug("rxbytes:0x%x rxp:0x%p\n", rxbytes, rxp); } - done: - if (flags & SPI_XFER_END) - spi_cs_deactivate(dev); - return 0; } +static void xilinx_spi_startup_block(struct spi_slave *spi) +{ + struct dm_spi_slave_plat *slave_plat = + dev_get_parent_plat(spi->dev); + unsigned char txp; + unsigned char rxp[8]; + + /* + * Perform a dummy read as a work around for + * the startup block issue. + */ + spi_cs_activate(spi->dev, slave_plat->cs); + txp = 0x9f; + start_transfer(spi, (void *)&txp, NULL, 1); + + start_transfer(spi, NULL, (void *)rxp, 6); + + spi_cs_deactivate(spi->dev); +} + +static int xilinx_spi_mem_exec_op(struct spi_slave *spi, + const struct spi_mem_op *op) +{ + struct dm_spi_slave_plat *slave_plat = + dev_get_parent_plat(spi->dev); + static u32 startup; + u32 dummy_len, ret; + + /* + * This is the work around for the startup block issue in + * the spi controller. SPI clock is passing through STARTUP + * block to FLASH. STARTUP block don't provide clock as soon + * as QSPI provides command. So first command fails. + */ + if (!startup) { + xilinx_spi_startup_block(spi); + startup++; + } + + spi_cs_activate(spi->dev, slave_plat->cs); + + if (op->cmd.opcode) { + ret = start_transfer(spi, (void *)&op->cmd.opcode, NULL, 1); + if (ret) + goto done; + } + if (op->addr.nbytes) { + int i; + u8 addr_buf[4]; + + for (i = 0; i < op->addr.nbytes; i++) + addr_buf[i] = op->addr.val >> + (8 * (op->addr.nbytes - i - 1)); + + ret = start_transfer(spi, (void *)addr_buf, NULL, + op->addr.nbytes); + if (ret) + goto done; + } + if (op->dummy.nbytes) { + dummy_len = op->dummy.nbytes * op->data.buswidth; + ret = start_transfer(spi, NULL, NULL, dummy_len); + if (ret) + goto done; + } + if (op->data.nbytes) { + if (op->data.dir == SPI_MEM_DATA_IN) { + ret = start_transfer(spi, NULL, + op->data.buf.in, op->data.nbytes); + } else { + ret = start_transfer(spi, op->data.buf.out, + NULL, op->data.nbytes); + } + if (ret) + goto done; + } +done: + spi_cs_deactivate(spi->dev); + + return ret; +} + static int xilinx_spi_set_speed(struct udevice *bus, uint speed) { struct xilinx_spi_priv *priv = dev_get_priv(bus); @@ -343,12 +377,16 @@ static int xilinx_spi_set_mode(struct udevice *bus, uint mode) return 0; } +static const struct spi_controller_mem_ops xilinx_spi_mem_ops = { + .exec_op = xilinx_spi_mem_exec_op, +}; + static const struct dm_spi_ops xilinx_spi_ops = { .claim_bus = xilinx_spi_claim_bus, .release_bus = xilinx_spi_release_bus, - .xfer = xilinx_spi_xfer, .set_speed = xilinx_spi_set_speed, .set_mode = xilinx_spi_set_mode, + .mem_ops = &xilinx_spi_mem_ops, }; static const struct udevice_id xilinx_spi_ids[] = { -- cgit v1.2.3 From 557832bd88351ffc0b8e43720b98700fe74f68b2 Mon Sep 17 00:00:00 2001 From: T Karthik Reddy Date: Sat, 16 Jul 2022 12:28:47 +0530 Subject: spi: xilinx_spi: Add support ops to axi qspi driver Add support_ops function to check controller supported operations by spi-mem framework. Current default support ops function does not allow dummy buswidth no more than 1, unless we are using buswidth is 4 for TX. In order to support dummy buswidth > 1 by spi-nor framework we are adding explicit support_ops to check controller supported operations. Fix dummy bytes calculation incase of valid dummy bytes when dummy buswidth is > 1. Current dummy bytes calculation does not provide correct dummy values for dummy buswidth > 1. Signed-off-by: T Karthik Reddy Signed-off-by: Ashok Reddy Soma Link: https://lore.kernel.org/r/1657954727-31972-3-git-send-email-ashok.reddy.soma@xilinx.com Signed-off-by: Michal Simek --- drivers/spi/xilinx_spi.c | 46 +++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 45 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/spi/xilinx_spi.c b/drivers/spi/xilinx_spi.c index 09d4b01631f..4e9115dafee 100644 --- a/drivers/spi/xilinx_spi.c +++ b/drivers/spi/xilinx_spi.c @@ -320,7 +320,9 @@ static int xilinx_spi_mem_exec_op(struct spi_slave *spi, goto done; } if (op->dummy.nbytes) { - dummy_len = op->dummy.nbytes * op->data.buswidth; + dummy_len = (op->dummy.nbytes * op->data.buswidth) / + op->dummy.buswidth; + ret = start_transfer(spi, NULL, NULL, dummy_len); if (ret) goto done; @@ -342,6 +344,47 @@ done: return ret; } +static int xilinx_qspi_check_buswidth(struct spi_slave *slave, u8 width) +{ + u32 mode = slave->mode; + + switch (width) { + case 1: + return 0; + case 2: + if (mode & SPI_RX_DUAL) + return 0; + break; + case 4: + if (mode & SPI_RX_QUAD) + return 0; + break; + } + + return -EOPNOTSUPP; +} + +bool xilinx_qspi_mem_exec_op(struct spi_slave *slave, + const struct spi_mem_op *op) +{ + if (xilinx_qspi_check_buswidth(slave, op->cmd.buswidth)) + return false; + + if (op->addr.nbytes && + xilinx_qspi_check_buswidth(slave, op->addr.buswidth)) + return false; + + if (op->dummy.nbytes && + xilinx_qspi_check_buswidth(slave, op->dummy.buswidth)) + return false; + + if (op->data.dir != SPI_MEM_NO_DATA && + xilinx_qspi_check_buswidth(slave, op->data.buswidth)) + return false; + + return true; +} + static int xilinx_spi_set_speed(struct udevice *bus, uint speed) { struct xilinx_spi_priv *priv = dev_get_priv(bus); @@ -379,6 +422,7 @@ static int xilinx_spi_set_mode(struct udevice *bus, uint mode) static const struct spi_controller_mem_ops xilinx_spi_mem_ops = { .exec_op = xilinx_spi_mem_exec_op, + .supports_op = xilinx_qspi_mem_exec_op, }; static const struct dm_spi_ops xilinx_spi_ops = { -- cgit v1.2.3 From 1acb70393f2719c70d92f52d91be2525fa1db679 Mon Sep 17 00:00:00 2001 From: Siva Durga Prasad Paladugu Date: Fri, 15 Jul 2022 19:31:16 +0530 Subject: spi: zynq_qspi: Add child pre probe function Add child pre probe function in the driver. Update max_hz of priv from spi_slave structure. Signed-off-by: Siva Durga Prasad Paladugu Signed-off-by: Ashok Reddy Soma Link: https://lore.kernel.org/r/1657893679-20039-2-git-send-email-ashok.reddy.soma@xilinx.com Signed-off-by: Michal Simek --- drivers/spi/zynq_qspi.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'drivers') diff --git a/drivers/spi/zynq_qspi.c b/drivers/spi/zynq_qspi.c index b69d992b28a..066a0c60027 100644 --- a/drivers/spi/zynq_qspi.c +++ b/drivers/spi/zynq_qspi.c @@ -94,6 +94,7 @@ struct zynq_qspi_priv { u8 mode; u8 fifo_depth; u32 freq; /* required frequency */ + u32 max_hz; const void *tx_buf; void *rx_buf; unsigned len; @@ -174,6 +175,16 @@ static void zynq_qspi_init_hw(struct zynq_qspi_priv *priv) writel(ZYNQ_QSPI_ENR_SPI_EN_MASK, ®s->enr); } +static int zynq_qspi_child_pre_probe(struct udevice *bus) +{ + struct spi_slave *slave = dev_get_parent_priv(bus); + struct zynq_qspi_priv *priv = dev_get_priv(bus->parent); + + priv->max_hz = slave->max_hz; + + return 0; +} + static int zynq_qspi_probe(struct udevice *bus) { struct zynq_qspi_plat *plat = dev_get_plat(bus); @@ -746,4 +757,5 @@ U_BOOT_DRIVER(zynq_qspi) = { .plat_auto = sizeof(struct zynq_qspi_plat), .priv_auto = sizeof(struct zynq_qspi_priv), .probe = zynq_qspi_probe, + .child_pre_probe = zynq_qspi_child_pre_probe, }; -- cgit v1.2.3 From e09784728689de7949d4cdd559a9590e0bfcc702 Mon Sep 17 00:00:00 2001 From: T Karthik Reddy Date: Fri, 15 Jul 2022 19:31:17 +0530 Subject: spi: zynq_qspi: Use dummy buswidth in dummy byte calculation Fix dummy bytes calculation incase of valid dummy bytes when dummy buswidth is > 1. Current dummy bytes calculation does not provide correct dummy values for dummy buswidth > 1. Signed-off-by: T Karthik Reddy Signed-off-by: Ashok Reddy Soma Link: https://lore.kernel.org/r/1657893679-20039-3-git-send-email-ashok.reddy.soma@xilinx.com Signed-off-by: Michal Simek --- drivers/spi/zynq_qspi.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/spi/zynq_qspi.c b/drivers/spi/zynq_qspi.c index 066a0c60027..b138c3c38a1 100644 --- a/drivers/spi/zynq_qspi.c +++ b/drivers/spi/zynq_qspi.c @@ -679,6 +679,7 @@ static int zynq_qspi_exec_op(struct spi_slave *slave, const struct spi_mem_op *op) { int op_len, pos = 0, ret, i; + u32 dummy_bytes = 0; unsigned int flag = 0; const u8 *tx_buf = NULL; u8 *rx_buf = NULL; @@ -691,6 +692,11 @@ static int zynq_qspi_exec_op(struct spi_slave *slave, } op_len = op->cmd.nbytes + op->addr.nbytes + op->dummy.nbytes; + if (op->dummy.nbytes) { + op_len = op->cmd.nbytes + op->addr.nbytes + + op->dummy.nbytes / op->dummy.buswidth; + dummy_bytes = op->dummy.nbytes / op->dummy.buswidth; + } u8 op_buf[op_len]; @@ -704,8 +710,8 @@ static int zynq_qspi_exec_op(struct spi_slave *slave, pos += op->addr.nbytes; } - if (op->dummy.nbytes) - memset(op_buf + pos, 0xff, op->dummy.nbytes); + if (dummy_bytes) + memset(op_buf + pos, 0xff, dummy_bytes); /* 1st transfer: opcode + address + dummy cycles */ /* Make sure to set END bit if no tx or rx data messages follow */ -- cgit v1.2.3 From bc4795850bdd971fe7ff5014a9283b975368da95 Mon Sep 17 00:00:00 2001 From: Ashok Reddy Soma Date: Fri, 15 Jul 2022 19:31:18 +0530 Subject: spi: zynq_qspi: Add support for zynq_qspi_mem_exec_op Add support_ops function zynq_qspi_mem_exec_op to check controller supported operations by spi-mem framework. Current default support ops function does not allow dummy buswidth no more than 1, unless we are using buswidth is 4 for TX. Signed-off-by: Ashok Reddy Soma Link: https://lore.kernel.org/r/1657893679-20039-4-git-send-email-ashok.reddy.soma@xilinx.com Signed-off-by: Michal Simek --- drivers/spi/zynq_qspi.c | 42 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) (limited to 'drivers') diff --git a/drivers/spi/zynq_qspi.c b/drivers/spi/zynq_qspi.c index b138c3c38a1..52db7b3f219 100644 --- a/drivers/spi/zynq_qspi.c +++ b/drivers/spi/zynq_qspi.c @@ -736,8 +736,50 @@ static int zynq_qspi_exec_op(struct spi_slave *slave, return 0; } +static int zynq_qspi_check_buswidth(struct spi_slave *slave, u8 width) +{ + u32 mode = slave->mode; + + switch (width) { + case 1: + return 0; + case 2: + if (mode & SPI_RX_DUAL) + return 0; + break; + case 4: + if (mode & SPI_RX_QUAD) + return 0; + break; + } + + return -EOPNOTSUPP; +} + +bool zynq_qspi_mem_exec_op(struct spi_slave *slave, + const struct spi_mem_op *op) +{ + if (zynq_qspi_check_buswidth(slave, op->cmd.buswidth)) + return false; + + if (op->addr.nbytes && + zynq_qspi_check_buswidth(slave, op->addr.buswidth)) + return false; + + if (op->dummy.nbytes && + zynq_qspi_check_buswidth(slave, op->dummy.buswidth)) + return false; + + if (op->data.dir != SPI_MEM_NO_DATA && + zynq_qspi_check_buswidth(slave, op->data.buswidth)) + return false; + + return true; +} + static const struct spi_controller_mem_ops zynq_qspi_mem_ops = { .exec_op = zynq_qspi_exec_op, + .supports_op = zynq_qspi_mem_exec_op, }; static const struct dm_spi_ops zynq_qspi_ops = { -- cgit v1.2.3 From 2a75bc1303b34e88745fcecfeacbe94f2a4bd1e2 Mon Sep 17 00:00:00 2001 From: Ashok Reddy Soma Date: Fri, 15 Jul 2022 19:31:19 +0530 Subject: spi: zynq_qspi: Fix programming qspi speed When programming qspi flash speed we need to check the requested flash speed not to exceed the spi max frequency. In the current implementation we are checking qspi ref clk instead. This commit fixes the issue by checking the requested speed and programs the specified max frequency. Signed-off-by: Ashok Reddy Soma Link: https://lore.kernel.org/r/1657893679-20039-5-git-send-email-ashok.reddy.soma@xilinx.com Signed-off-by: Michal Simek --- drivers/spi/zynq_qspi.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/spi/zynq_qspi.c b/drivers/spi/zynq_qspi.c index 52db7b3f219..00e3ffcd1df 100644 --- a/drivers/spi/zynq_qspi.c +++ b/drivers/spi/zynq_qspi.c @@ -622,15 +622,12 @@ static int zynq_qspi_set_speed(struct udevice *bus, uint speed) uint32_t confr; u8 baud_rate_val = 0; - if (speed > plat->frequency) - speed = plat->frequency; + if (!speed || speed > priv->max_hz) + speed = priv->max_hz; /* Set the clock frequency */ confr = readl(®s->cr); - if (speed == 0) { - /* Set baudrate x8, if the freq is 0 */ - baud_rate_val = 0x2; - } else if (plat->speed_hz != speed) { + if (plat->speed_hz != speed) { while ((baud_rate_val < ZYNQ_QSPI_CR_BAUD_MAX) && ((plat->frequency / (2 << baud_rate_val)) > speed)) -- cgit v1.2.3