From b7e0750d8872af4f294ec46533fe5243514dcb59 Mon Sep 17 00:00:00 2001 From: Stefan Herbrechtsmeier Date: Fri, 5 Aug 2022 08:16:28 +0200 Subject: [PATCH 01/42] zynq: Convert arm twd timer to DM driver Move arm twd timer driver from zynq to generic location. DM timer drivers are designed differently to original driver. Timer is counting up and not down. Information about clock rates are find out in timer_pre_probe() that's why there is no need to get any additional information from DT in the driver itself (only register offset). Signed-off-by: Stefan Herbrechtsmeier Link: https://lore.kernel.org/r/20220805061629.1207-1-stefan.herbrechtsmeier-oss@weidmueller.com Signed-off-by: Michal Simek --- arch/arm/Kconfig | 3 + arch/arm/dts/zynq-7000.dtsi | 1 + arch/arm/mach-zynq/Makefile | 1 - arch/arm/mach-zynq/clk.c | 6 +- arch/arm/mach-zynq/timer.c | 113 ---------------------------------- drivers/timer/Kconfig | 6 ++ drivers/timer/Makefile | 1 + drivers/timer/arm_twd_timer.c | 108 ++++++++++++++++++++++++++++++++ 8 files changed, 123 insertions(+), 116 deletions(-) delete mode 100644 arch/arm/mach-zynq/timer.c create mode 100644 drivers/timer/arm_twd_timer.c diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index d6c5658ee8..3649222470 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -1259,6 +1259,7 @@ config ARCH_VF610 config ARCH_ZYNQ bool "Xilinx Zynq based platform" + select ARM_TWD_TIMER select CLK select CLK_ZYNQ select CPU_V7A @@ -1278,7 +1279,9 @@ config ARCH_ZYNQ select SPL_DM_SPI_FLASH if SPL select SPL_OF_CONTROL if SPL select SPL_SEPARATE_BSS if SPL + select SPL_TIMER if SPL select SUPPORT_SPL + select TIMER imply ARCH_EARLY_INIT_R imply BOARD_LATE_INIT imply CMD_CLK diff --git a/arch/arm/dts/zynq-7000.dtsi b/arch/arm/dts/zynq-7000.dtsi index 37155df0fd..a7ca00fb76 100644 --- a/arch/arm/dts/zynq-7000.dtsi +++ b/arch/arm/dts/zynq-7000.dtsi @@ -416,6 +416,7 @@ }; scutimer: timer@f8f00600 { + u-boot,dm-pre-reloc; interrupt-parent = <&intc>; interrupts = <1 13 0x301>; compatible = "arm,cortex-a9-twd-timer"; diff --git a/arch/arm/mach-zynq/Makefile b/arch/arm/mach-zynq/Makefile index 8737f434d9..d9b2b999e1 100644 --- a/arch/arm/mach-zynq/Makefile +++ b/arch/arm/mach-zynq/Makefile @@ -6,7 +6,6 @@ # (C) Copyright 2008 # Guennadi Liakhovetki, DENX Software Engineering, -obj-y := timer.o obj-y += cpu.o obj-y += ddrc.o obj-y += slcr.o diff --git a/arch/arm/mach-zynq/clk.c b/arch/arm/mach-zynq/clk.c index 27f6bf2183..1945f60e08 100644 --- a/arch/arm/mach-zynq/clk.c +++ b/arch/arm/mach-zynq/clk.c @@ -52,10 +52,12 @@ int set_cpu_clk_info(void) return ret; rate = clk_get_rate(&clk) / 1000000; - if (i) + if (i) { gd->bd->bi_ddr_freq = rate; - else + } else { gd->bd->bi_arm_freq = rate; + gd->cpu_clk = clk_get_rate(&clk); + } clk_free(&clk); } diff --git a/arch/arm/mach-zynq/timer.c b/arch/arm/mach-zynq/timer.c deleted file mode 100644 index a51822a530..0000000000 --- a/arch/arm/mach-zynq/timer.c +++ /dev/null @@ -1,113 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -/* - * Copyright (C) 2017 Weidmüller Interface GmbH & Co. KG - * Stefan Herbrechtsmeier - * - * Copyright (C) 2012 Michal Simek - * Copyright (C) 2011-2017 Xilinx, Inc. All rights reserved. - * - * (C) Copyright 2008 - * Guennadi Liakhovetki, DENX Software Engineering, - * - * (C) Copyright 2004 - * Philippe Robin, ARM Ltd. - * - * (C) Copyright 2002-2004 - * Gary Jennejohn, DENX Software Engineering, - * - * (C) Copyright 2003 - * Texas Instruments - * - * (C) Copyright 2002 - * Sysgo Real-Time Solutions, GmbH - * Marius Groeger - * - * (C) Copyright 2002 - * Sysgo Real-Time Solutions, GmbH - * Alex Zuepke - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -DECLARE_GLOBAL_DATA_PTR; - -struct scu_timer { - u32 load; /* Timer Load Register */ - u32 counter; /* Timer Counter Register */ - u32 control; /* Timer Control Register */ -}; - -static struct scu_timer *timer_base = - (struct scu_timer *)ZYNQ_SCUTIMER_BASEADDR; - -#define SCUTIMER_CONTROL_PRESCALER_MASK 0x0000FF00 /* Prescaler */ -#define SCUTIMER_CONTROL_PRESCALER_SHIFT 8 -#define SCUTIMER_CONTROL_AUTO_RELOAD_MASK 0x00000002 /* Auto-reload */ -#define SCUTIMER_CONTROL_ENABLE_MASK 0x00000001 /* Timer enable */ - -#define TIMER_LOAD_VAL 0xFFFFFFFF -#define TIMER_PRESCALE 255 - -int timer_init(void) -{ - const u32 emask = SCUTIMER_CONTROL_AUTO_RELOAD_MASK | - (TIMER_PRESCALE << SCUTIMER_CONTROL_PRESCALER_SHIFT) | - SCUTIMER_CONTROL_ENABLE_MASK; - - struct udevice *dev; - struct clk clk; - int ret; - - ret = uclass_get_device_by_driver(UCLASS_CLK, - DM_DRIVER_GET(zynq_clk), &dev); - if (ret) - return ret; - - clk.id = cpu_6or4x_clk; - ret = clk_request(dev, &clk); - if (ret < 0) - return ret; - - gd->cpu_clk = clk_get_rate(&clk); - - clk_free(&clk); - - gd->arch.timer_rate_hz = (gd->cpu_clk / 2) / (TIMER_PRESCALE + 1); - - /* Load the timer counter register */ - writel(0xFFFFFFFF, &timer_base->load); - - /* - * Start the A9Timer device - * Enable Auto reload mode, Clear prescaler control bits - * Set prescaler value, Enable the decrementer - */ - clrsetbits_le32(&timer_base->control, SCUTIMER_CONTROL_PRESCALER_MASK, - emask); - - /* Reset time */ - gd->arch.lastinc = readl(&timer_base->counter) / - (gd->arch.timer_rate_hz / CONFIG_SYS_HZ); - gd->arch.tbl = 0; - - return 0; -} - -/* - * This function is derived from PowerPC code (timebase clock frequency). - * On ARM it returns the number of timer ticks per second. - */ -ulong get_tbclk(void) -{ - return gd->arch.timer_rate_hz; -} diff --git a/drivers/timer/Kconfig b/drivers/timer/Kconfig index 4049290148..1b49236039 100644 --- a/drivers/timer/Kconfig +++ b/drivers/timer/Kconfig @@ -73,6 +73,12 @@ config ARC_TIMER usually at least one of them exists. Either of them is supported in U-Boot. +config ARM_TWD_TIMER + bool "ARM timer watchdog (TWD) timer support" + depends on TIMER && CLK + help + Select this to enable support for the ARM global timer watchdog timer. + config AST_TIMER bool "Aspeed ast2400/ast2500 timer support" depends on TIMER diff --git a/drivers/timer/Makefile b/drivers/timer/Makefile index 560e2d27e1..7bfb7749e9 100644 --- a/drivers/timer/Makefile +++ b/drivers/timer/Makefile @@ -6,6 +6,7 @@ obj-y += timer-uclass.o obj-$(CONFIG_ALTERA_TIMER) += altera_timer.o obj-$(CONFIG_ANDES_PLMT_TIMER) += andes_plmt_timer.o obj-$(CONFIG_ARC_TIMER) += arc_timer.o +obj-$(CONFIG_ARM_TWD_TIMER) += arm_twd_timer.o obj-$(CONFIG_AST_TIMER) += ast_timer.o obj-$(CONFIG_ATCPIT100_TIMER) += atcpit100_timer.o obj-$(CONFIG_$(SPL_)ATMEL_PIT_TIMER) += atmel_pit_timer.o diff --git a/drivers/timer/arm_twd_timer.c b/drivers/timer/arm_twd_timer.c new file mode 100644 index 0000000000..40ccd16587 --- /dev/null +++ b/drivers/timer/arm_twd_timer.c @@ -0,0 +1,108 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2017-2022 Weidmüller Interface GmbH & Co. KG + * Stefan Herbrechtsmeier + * + * Copyright (C) 2012 Michal Simek + * Copyright (C) 2011-2017 Xilinx, Inc. All rights reserved. + * + * (C) Copyright 2008 + * Guennadi Liakhovetki, DENX Software Engineering, + * + * (C) Copyright 2004 + * Philippe Robin, ARM Ltd. + * + * (C) Copyright 2002-2004 + * Gary Jennejohn, DENX Software Engineering, + * + * (C) Copyright 2003 + * Texas Instruments + * + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH + * Marius Groeger + * + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH + * Alex Zuepke + */ + +#include +#include +#include +#include +#include + +#include + +#define SCUTIMER_CONTROL_PRESCALER_MASK 0x0000FF00 /* Prescaler */ +#define SCUTIMER_CONTROL_AUTO_RELOAD_MASK 0x00000002 /* Auto-reload */ +#define SCUTIMER_CONTROL_ENABLE_MASK 0x00000001 /* Timer enable */ + +#define TIMER_LOAD_VAL 0xFFFFFFFF + +struct arm_twd_timer_regs { + u32 load; /* Timer Load Register */ + u32 counter; /* Timer Counter Register */ + u32 control; /* Timer Control Register */ +}; + +struct arm_twd_timer_priv { + struct arm_twd_timer_regs *base; +}; + +static u64 arm_twd_timer_get_count(struct udevice *dev) +{ + struct arm_twd_timer_priv *priv = dev_get_priv(dev); + struct arm_twd_timer_regs *regs = priv->base; + u32 count = TIMER_LOAD_VAL - readl(®s->counter); + + return timer_conv_64(count); +} + +static int arm_twd_timer_probe(struct udevice *dev) +{ + struct arm_twd_timer_priv *priv = dev_get_priv(dev); + struct arm_twd_timer_regs *regs; + fdt_addr_t addr; + + addr = dev_read_addr(dev); + if (addr == FDT_ADDR_T_NONE) + return -EINVAL; + + priv->base = (struct arm_twd_timer_regs *)addr; + + regs = priv->base; + + /* Load the timer counter register */ + writel(0xFFFFFFFF, ®s->load); + + /* + * Start the A9Timer device + * Enable Auto reload mode, Clear prescaler control bits + * Set prescaler value, Enable the decrementer + */ + clrsetbits_le32(®s->control, SCUTIMER_CONTROL_PRESCALER_MASK, + SCUTIMER_CONTROL_AUTO_RELOAD_MASK | + SCUTIMER_CONTROL_ENABLE_MASK); + + return 0; +} + +static const struct timer_ops arm_twd_timer_ops = { + .get_count = arm_twd_timer_get_count, +}; + +static const struct udevice_id arm_twd_timer_ids[] = { + { .compatible = "arm,cortex-a9-twd-timer" }, + {} +}; + +U_BOOT_DRIVER(arm_twd_timer) = { + .name = "arm_twd_timer", + .id = UCLASS_TIMER, + .of_match = arm_twd_timer_ids, + .priv_auto = sizeof(struct arm_twd_timer_priv), + .probe = arm_twd_timer_probe, + .ops = &arm_twd_timer_ops, +}; From 7a0bc18b6309be421b7968ee70efb54c9e3d59dd Mon Sep 17 00:00:00 2001 From: Stefan Herbrechtsmeier Date: Mon, 8 Aug 2022 16:53:31 +0200 Subject: [PATCH 02/42] fpga: zynq: Remove post config info message for SPL The drivers informs the user that a post config was not run after FPGA configuration. This message is unnecessary in SPL because the ps7_post_config function is called via spl_board_prepare_for_boot function before jump_to_image_no_args function from board_init_r function. Signed-off-by: Stefan Herbrechtsmeier Link: https://lore.kernel.org/r/20220808145331.24723-1-stefan.herbrechtsmeier-oss@weidmueller.com Signed-off-by: Michal Simek --- drivers/fpga/zynqpl.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/fpga/zynqpl.c b/drivers/fpga/zynqpl.c index d8ebd542ab..0c83df46da 100644 --- a/drivers/fpga/zynqpl.c +++ b/drivers/fpga/zynqpl.c @@ -413,7 +413,8 @@ static int zynq_load(xilinx_desc *desc, const void *buf, size_t bsize, if (bstype != BIT_PARTIAL) zynq_slcr_devcfg_enable(); - puts("INFO:post config was not run, please run manually if needed\n"); + if (!IS_ENABLED(CONFIG_SPL_BUILD)) + puts("INFO:post config was not run, please run manually if needed\n"); return FPGA_SUCCESS; } From cf5c48d102bd50eb24eb03ddd5cc1f0c33a3f57a Mon Sep 17 00:00:00 2001 From: Janne Ylalehto Date: Tue, 16 Aug 2022 15:45:25 +0300 Subject: [PATCH 03/42] xilinx: zynqmp: Fix AES with a user provided key The user provided key address was not flushed in struct aes because of the flushing location in the function. Signed-off-by: Janne Ylalehto Link: https://lore.kernel.org/r/20220816124525.19671-1-ylalehto@gmail.com Signed-off-by: Michal Simek --- board/xilinx/zynqmp/cmds.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/board/xilinx/zynqmp/cmds.c b/board/xilinx/zynqmp/cmds.c index 2ab9596248..e20030ecda 100644 --- a/board/xilinx/zynqmp/cmds.c +++ b/board/xilinx/zynqmp/cmds.c @@ -142,9 +142,6 @@ static int do_zynqmp_aes(struct cmd_tbl *cmdtp, int flag, int argc, aes->keysrc = hextoul(argv[6], NULL); aes->dstaddr = hextoul(argv[7], NULL); - flush_dcache_range((ulong)aes, (ulong)(aes) + - roundup(sizeof(struct aes), ARCH_DMA_MINALIGN)); - if (aes->srcaddr && aes->ivaddr && aes->dstaddr) { flush_dcache_range(aes->srcaddr, (aes->srcaddr + @@ -169,6 +166,9 @@ static int do_zynqmp_aes(struct cmd_tbl *cmdtp, int flag, int argc, ARCH_DMA_MINALIGN))); } + flush_dcache_range((ulong)aes, (ulong)(aes) + + roundup(sizeof(struct aes), ARCH_DMA_MINALIGN)); + ret = xilinx_pm_request(PM_SECURE_AES, upper_32_bits((ulong)aes), lower_32_bits((ulong)aes), 0, 0, ret_payload); if (ret || ret_payload[1]) From 86cba52a981ddab898ff4a7b079437fac497c1e6 Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Fri, 5 Aug 2022 11:19:53 +0200 Subject: [PATCH 04/42] xilinx: versal: Enable i2c mux uclass with pca954x driver Xilinx is using pca954x i2c muxes on a lot of boards that's why enable this driver by default. Signed-off-by: Michal Simek Link: https://lore.kernel.org/r/c090aea3436c7a4ebe698da6cbc70e70a14baae3.1659691195.git.michal.simek@amd.com --- configs/xilinx_versal_virt_defconfig | 2 ++ 1 file changed, 2 insertions(+) diff --git a/configs/xilinx_versal_virt_defconfig b/configs/xilinx_versal_virt_defconfig index 6e61abd0c6..c4d7aac7b5 100644 --- a/configs/xilinx_versal_virt_defconfig +++ b/configs/xilinx_versal_virt_defconfig @@ -69,6 +69,8 @@ CONFIG_FPGA_XILINX=y CONFIG_FPGA_VERSALPL=y CONFIG_DM_I2C=y CONFIG_SYS_I2C_CADENCE=y +CONFIG_I2C_MUX=y +CONFIG_I2C_MUX_PCA954x=y CONFIG_DM_MAILBOX=y CONFIG_ZYNQMP_IPI=y CONFIG_MISC=y From 2fb4b5ae54704f8e334a1491c4c9f2f90958456b Mon Sep 17 00:00:00 2001 From: Ashok Reddy Soma Date: Fri, 5 Aug 2022 11:19:54 +0200 Subject: [PATCH 05/42] xilinx: zynqmp: Disable various configs for mini U-Boot With 2022.01-rc3 upgrade, the size of the mini U-Boot increased and is not able to fit in OCM. Hence disable unnecessary configs and make room. Signed-off-by: Ashok Reddy Soma Signed-off-by: Michal Simek Link: https://lore.kernel.org/r/306b57818601fa3571bc75c4182f25aaa3f2a793.1659691195.git.michal.simek@amd.com --- configs/xilinx_zynqmp_mini_qspi_defconfig | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/configs/xilinx_zynqmp_mini_qspi_defconfig b/configs/xilinx_zynqmp_mini_qspi_defconfig index e6d4308347..d0cc0360d2 100644 --- a/configs/xilinx_zynqmp_mini_qspi_defconfig +++ b/configs/xilinx_zynqmp_mini_qspi_defconfig @@ -3,7 +3,7 @@ CONFIG_SYS_CONFIG_NAME="xilinx_zynqmp_mini_qspi" CONFIG_SYS_ICACHE_OFF=y CONFIG_ARCH_ZYNQMP=y CONFIG_SYS_TEXT_BASE=0xFFFC0000 -CONFIG_SYS_MALLOC_LEN=0x1a00 +CONFIG_SYS_MALLOC_LEN=0x1b00 CONFIG_NR_DRAM_BANKS=1 CONFIG_ENV_SIZE=0x80 CONFIG_DEFAULT_DEVICE_TREE="zynqmp-mini-qspi" @@ -19,7 +19,9 @@ CONFIG_CUSTOM_SYS_INIT_SP_ADDR=0xfffe0000 # CONFIG_EXPERT is not set CONFIG_REMAKE_ELF=y # CONFIG_LEGACY_IMAGE_FORMAT is not set +# CONFIG_ARCH_FIXUP_FDT_MEMORY is not set # CONFIG_AUTOBOOT is not set +CONFIG_LOGLEVEL=0 # CONFIG_DISPLAY_CPUINFO is not set # CONFIG_BOARD_LATE_INIT is not set CONFIG_CLOCKS=y @@ -62,6 +64,7 @@ CONFIG_SYS_PBSIZE=1049 # CONFIG_CMD_SOURCE is not set # CONFIG_CMD_SETEXPR is not set # CONFIG_CMD_SLEEP is not set +# CONFIG_CMD_MP is not set CONFIG_SPL_OF_CONTROL=y CONFIG_OF_EMBED=y CONFIG_SYS_RELOC_GD_ENV_ADDR=y @@ -69,17 +72,24 @@ CONFIG_SYS_RELOC_GD_ENV_ADDR=y # CONFIG_DM_WARN is not set # CONFIG_DM_DEVICE_REMOVE is not set CONFIG_SPL_DM_SEQ_ALIAS=y +# CONFIG_FIRMWARE is not set +# CONFIG_GPIO is not set +# CONFIG_I2C is not set +# CONFIG_INPUT is not set # CONFIG_MMC is not set -CONFIG_SPI_FLASH_BAR=y +# CONFIG_SPI_FLASH_SMART_HWCAPS is not set +# CONFIG_SPI_FLASH_UNLOCK_ALL is not set CONFIG_SPI_FLASH_ISSI=y CONFIG_SPI_FLASH_MACRONIX=y CONFIG_SPI_FLASH_SPANSION=y CONFIG_SPI_FLASH_STMICRO=y CONFIG_SPI_FLASH_WINBOND=y # CONFIG_SPI_FLASH_USE_4K_SECTORS is not set +# CONFIG_POWER is not set CONFIG_ARM_DCC=y CONFIG_SPI=y CONFIG_ZYNQMP_GQSPI=y +# CONFIG_FAT_WRITE is not set CONFIG_PANIC_HANG=y # CONFIG_GZIP is not set # CONFIG_LMB is not set From 85007da94bad2d27e40e0258fa5437a35034ee1d Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Wed, 7 Sep 2022 09:52:09 +0200 Subject: [PATCH 06/42] cmd: bdinfo: Enable dumping lmb data when LMB is enabled The commit 9996cea75f5a ("lmb/bdinfo: dump lmb info via bdinfo") added support for dumping LMB information as the part of bdinfo. But code itself should be called only when LMB is enabled. Signed-off-by: Michal Simek Reviewed-by: Simon Glass Link: https://lore.kernel.org/r/3e40c8bb77550dfca9f7eb48fe644a018d971411.1662537127.git.michal.simek@amd.com --- cmd/bdinfo.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/bdinfo.c b/cmd/bdinfo.c index 37cd8a57eb..8a1bea4e34 100644 --- a/cmd/bdinfo.c +++ b/cmd/bdinfo.c @@ -123,7 +123,7 @@ int do_bdinfo(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) #if CONFIG_IS_ENABLED(MULTI_DTB_FIT) bdinfo_print_num_l("multi_dtb_fit", (ulong)gd->multi_dtb_fit); #endif - if (gd->fdt_blob) { + if (IS_ENABLED(CONFIG_LMB) && gd->fdt_blob) { struct lmb lmb; lmb_init_and_reserve(&lmb, gd->bd, (void *)gd->fdt_blob); From d434921defdcde9f858de8e4dd9380156dc60ad1 Mon Sep 17 00:00:00 2001 From: Ashok Reddy Soma Date: Fri, 5 Aug 2022 11:19:55 +0200 Subject: [PATCH 07/42] xilinx: zynqmp: Disable LMB for mini u-boot LMB is not required for mini u-boot which runs out of on chip memory. Disable CONFIG_LMB from mini u-boot defconfig's. Signed-off-by: Ashok Reddy Soma Signed-off-by: Michal Simek Link: https://lore.kernel.org/r/45fad28825f0f236ad45e700aca1f39afbb22236.1659691195.git.michal.simek@amd.com --- configs/xilinx_zynqmp_mini_nand_defconfig | 1 + configs/xilinx_zynqmp_mini_nand_single_defconfig | 1 + 2 files changed, 2 insertions(+) diff --git a/configs/xilinx_zynqmp_mini_nand_defconfig b/configs/xilinx_zynqmp_mini_nand_defconfig index a2405f24ef..e6054fe177 100644 --- a/configs/xilinx_zynqmp_mini_nand_defconfig +++ b/configs/xilinx_zynqmp_mini_nand_defconfig @@ -65,3 +65,4 @@ CONFIG_SYS_NAND_MAX_CHIPS=2 CONFIG_ARM_DCC=y CONFIG_PANIC_HANG=y # CONFIG_GZIP is not set +# CONFIG_LMB is not set diff --git a/configs/xilinx_zynqmp_mini_nand_single_defconfig b/configs/xilinx_zynqmp_mini_nand_single_defconfig index e6ebc12ed7..aa35b48c72 100644 --- a/configs/xilinx_zynqmp_mini_nand_single_defconfig +++ b/configs/xilinx_zynqmp_mini_nand_single_defconfig @@ -64,3 +64,4 @@ CONFIG_SYS_NAND_ONFI_DETECTION=y CONFIG_ARM_DCC=y CONFIG_PANIC_HANG=y # CONFIG_GZIP is not set +# CONFIG_LMB is not set From 91687c4c3c0c919f120f0cc120b739c6fb26b993 Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Tue, 6 Sep 2022 12:41:10 +0200 Subject: [PATCH 08/42] xilinx: zynq: Disable LMB for mini configurations There shouldn't be a reason to have LMB on for these configurations. LMB was already disabled for ZynqMP by commit 0063487a5b60 ("configs: zynqmp: Disable LMB for mini u-boot"). Signed-off-by: Michal Simek Link: https://lore.kernel.org/r/07d95f619a15672d1a234eddcfbb54c0ab382eaa.1662460867.git.michal.simek@amd.com --- configs/zynq_cse_nand_defconfig | 1 + configs/zynq_cse_nor_defconfig | 1 + configs/zynq_cse_qspi_defconfig | 1 + 3 files changed, 3 insertions(+) diff --git a/configs/zynq_cse_nand_defconfig b/configs/zynq_cse_nand_defconfig index b69c8b92a4..22f7456d33 100644 --- a/configs/zynq_cse_nand_defconfig +++ b/configs/zynq_cse_nand_defconfig @@ -79,3 +79,4 @@ CONFIG_NAND_ZYNQ=y CONFIG_SYS_NAND_ONFI_DETECTION=y CONFIG_ARM_DCC=y # CONFIG_GZIP is not set +# CONFIG_LMB is not set diff --git a/configs/zynq_cse_nor_defconfig b/configs/zynq_cse_nor_defconfig index 59cd19ef2d..9f2d33782f 100644 --- a/configs/zynq_cse_nor_defconfig +++ b/configs/zynq_cse_nor_defconfig @@ -81,3 +81,4 @@ CONFIG_SYS_FLASH_CFI=y CONFIG_SYS_FLASH_QUIET_TEST=y CONFIG_ARM_DCC=y # CONFIG_GZIP is not set +# CONFIG_LMB is not set diff --git a/configs/zynq_cse_qspi_defconfig b/configs/zynq_cse_qspi_defconfig index 49dd5ad606..a767224795 100644 --- a/configs/zynq_cse_qspi_defconfig +++ b/configs/zynq_cse_qspi_defconfig @@ -91,3 +91,4 @@ CONFIG_SPI_FLASH_WINBOND=y CONFIG_ARM_DCC=y CONFIG_ZYNQ_QSPI=y # CONFIG_GZIP is not set +# CONFIG_LMB is not set From ad8024e0406404bc63dd4468ac75c87eaec5cca0 Mon Sep 17 00:00:00 2001 From: Ashok Reddy Soma Date: Fri, 5 Aug 2022 11:19:56 +0200 Subject: [PATCH 09/42] firmware: zynqmp: Skip loading config object for Versal SET_CONFIGURATION is not yet implemented for Versal platforms. Skip loading config object for Versal until support is added. Signed-off-by: Ashok Reddy Soma Signed-off-by: Michal Simek Link: https://lore.kernel.org/r/eb7ef6c6de36a1f7d056de43042f96fe3639f18e.1659691195.git.michal.simek@amd.com --- drivers/power/domain/zynqmp-power-domain.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/power/domain/zynqmp-power-domain.c b/drivers/power/domain/zynqmp-power-domain.c index 6943658be4..adbbb5fdd9 100644 --- a/drivers/power/domain/zynqmp-power-domain.c +++ b/drivers/power/domain/zynqmp-power-domain.c @@ -25,7 +25,10 @@ static int zynqmp_power_domain_request(struct power_domain *power_domain) { dev_dbg(power_domain->dev, "Request for id: %ld\n", power_domain->id); - return zynqmp_pmufw_node(power_domain->id); + if (IS_ENABLED(CONFIG_ARCH_ZYNQMP)) + return zynqmp_pmufw_node(power_domain->id); + + return 0; } static int zynqmp_power_domain_free(struct power_domain *power_domain) From 4a72f803686d44a9f2965845b4d931f02b1f23ab Mon Sep 17 00:00:00 2001 From: Ashok Reddy Soma Date: Fri, 5 Aug 2022 11:19:57 +0200 Subject: [PATCH 10/42] xilinx: versal: Enable power domain driver Enable power domain driver to request node for all the IP's that are enabled in DT. Signed-off-by: Ashok Reddy Soma Signed-off-by: Michal Simek Link: https://lore.kernel.org/r/dbed54df622d647b8d520d8ce5289cd69ba66e0b.1659691195.git.michal.simek@amd.com --- configs/xilinx_versal_virt_defconfig | 2 ++ 1 file changed, 2 insertions(+) diff --git a/configs/xilinx_versal_virt_defconfig b/configs/xilinx_versal_virt_defconfig index c4d7aac7b5..762ceb5e9f 100644 --- a/configs/xilinx_versal_virt_defconfig +++ b/configs/xilinx_versal_virt_defconfig @@ -104,6 +104,8 @@ CONFIG_PHY_GIGE=y CONFIG_XILINX_AXIEMAC=y CONFIG_XILINX_AXIMRMAC=y CONFIG_ZYNQ_GEM=y +CONFIG_POWER_DOMAIN=y +CONFIG_ZYNQMP_POWER_DOMAIN=y CONFIG_DM_RESET=y CONFIG_RESET_ZYNQMP=y CONFIG_ARM_DCC=y From 64c71d1c7333cfda99873372874a706becdbcf39 Mon Sep 17 00:00:00 2001 From: Ashok Reddy Soma Date: Fri, 5 Aug 2022 11:19:58 +0200 Subject: [PATCH 11/42] xilinx: versal: Define CONFIG_CQSPI_REF_CLK With commit 55b3ba4c2ba4 ("spi: cadence_qspi: Migrate CONFIG_CQSPI_REF_CLK to Kconfig") CONFIG_CQSPI_REF_CLK is moved to Kconfig. The static value via Kconfig is a fallback option in case of clock framework is not enabled or fails for some reason. Signed-off-by: Ashok Reddy Soma Signed-off-by: Michal Simek Link: https://lore.kernel.org/r/fe7c38a19e878c307d5b75311bbfd8cf6c1f601e.1659691195.git.michal.simek@amd.com --- configs/xilinx_versal_virt_defconfig | 2 ++ 1 file changed, 2 insertions(+) diff --git a/configs/xilinx_versal_virt_defconfig b/configs/xilinx_versal_virt_defconfig index 762ceb5e9f..ffd8bea81c 100644 --- a/configs/xilinx_versal_virt_defconfig +++ b/configs/xilinx_versal_virt_defconfig @@ -115,6 +115,8 @@ CONFIG_SOC_XILINX_VERSAL=y CONFIG_SPI=y CONFIG_DM_SPI=y CONFIG_CADENCE_QSPI=y +CONFIG_HAS_CQSPI_REF_CLK=y +CONFIG_CQSPI_REF_CLK=200000000 CONFIG_CADENCE_OSPI_VERSAL=y CONFIG_ZYNQ_SPI=y CONFIG_USB=y From 79f0151389396f310bd6441d444e2c2a54b6039c Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Tue, 9 Aug 2022 16:32:51 +0200 Subject: [PATCH 12/42] xilinx: zynq: Enable mkeficapsule tools compilation Zynq can use efi capsule infrastructure that's why enable it by default. For capsule generation for zynq you can use: pushd spl ../tools/mkeficapsule -g "1ba29a15-9969-40aa-b424-e86121618664" boot.bin \ --index 1 ../capsule1.bin popd ./tools/mkeficapsule -g "1a5178f0-87d3-4f36-ac63-3b31a23be305" u-boot.img \ --index 2 capsule2.bin Signed-off-by: Michal Simek Link: https://lore.kernel.org/r/a8194ecfa7932f2d8ada5ee508b2a026c782f15e.1660055571.git.michal.simek@amd.com --- configs/xilinx_zynq_virt_defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/configs/xilinx_zynq_virt_defconfig b/configs/xilinx_zynq_virt_defconfig index 7beb5915fc..e6f8e221a5 100644 --- a/configs/xilinx_zynq_virt_defconfig +++ b/configs/xilinx_zynq_virt_defconfig @@ -149,3 +149,4 @@ CONFIG_DISPLAY=y CONFIG_SPL_GZIP=y CONFIG_EFI_RUNTIME_UPDATE_CAPSULE=y CONFIG_EFI_CAPSULE_FIRMWARE_RAW=y +CONFIG_TOOLS_MKEFICAPSULE=y From ce183fd79ce5218a89dd5c73cd77bad6464ee5a2 Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Tue, 9 Aug 2022 16:32:52 +0200 Subject: [PATCH 13/42] xilinx: Fix logic when dfu_alt_info is generated Generate dfu_alt_info only when it is not defined. Signed-off-by: Michal Simek Link: https://lore.kernel.org/r/464e4b325c644e52a660df9cf44eeb4d80427f6a.1660055571.git.michal.simek@amd.com --- board/xilinx/zynq/board.c | 3 +-- board/xilinx/zynqmp/zynqmp.c | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/board/xilinx/zynq/board.c b/board/xilinx/zynq/board.c index 63aff0474b..26ef048835 100644 --- a/board/xilinx/zynq/board.c +++ b/board/xilinx/zynq/board.c @@ -168,8 +168,7 @@ void set_dfu_alt_info(char *interface, char *devstr) { ALLOC_CACHE_ALIGN_BUFFER(char, buf, DFU_ALT_BUF_LEN); - if (!CONFIG_IS_ENABLED(EFI_HAVE_CAPSULE_SUPPORT) && - env_get("dfu_alt_info")) + if (env_get("dfu_alt_info")) return; memset(buf, 0, sizeof(buf)); diff --git a/board/xilinx/zynqmp/zynqmp.c b/board/xilinx/zynqmp/zynqmp.c index 57259b60a0..29a6e3675f 100644 --- a/board/xilinx/zynqmp/zynqmp.c +++ b/board/xilinx/zynqmp/zynqmp.c @@ -641,8 +641,7 @@ void set_dfu_alt_info(char *interface, char *devstr) ALLOC_CACHE_ALIGN_BUFFER(char, buf, DFU_ALT_BUF_LEN); - if (!CONFIG_IS_ENABLED(EFI_HAVE_CAPSULE_SUPPORT) && - env_get("dfu_alt_info")) + if (env_get("dfu_alt_info")) return; memset(buf, 0, sizeof(buf)); From 93020aa3dc2f3428564cfc6ad232077706c508a7 Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Tue, 9 Aug 2022 16:32:53 +0200 Subject: [PATCH 14/42] xilinx: zynq: Use CONFIG_SPL_FS_LOAD_PAYLOAD_NAME for dfu_alt_info CONFIG_SPL_FS_LOAD_PAYLOAD_NAME stores the name of firmware file to be loaded by SPL. Name can be selected via Kconfig that's why use the macro. Signed-off-by: Michal Simek Link: https://lore.kernel.org/r/601fbc2dfd16b4708fc6b5f86954e10add43334e.1660055571.git.michal.simek@amd.com --- board/xilinx/zynq/board.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/board/xilinx/zynq/board.c b/board/xilinx/zynq/board.c index 26ef048835..3ab63fa76e 100644 --- a/board/xilinx/zynq/board.c +++ b/board/xilinx/zynq/board.c @@ -177,12 +177,13 @@ void set_dfu_alt_info(char *interface, char *devstr) case ZYNQ_BM_SD: snprintf(buf, DFU_ALT_BUF_LEN, "mmc 0:1=boot.bin fat 0 1;" - "u-boot.img fat 0 1"); + "%s fat 0 1", CONFIG_SPL_FS_LOAD_PAYLOAD_NAME); break; case ZYNQ_BM_QSPI: snprintf(buf, DFU_ALT_BUF_LEN, "sf 0:0=boot.bin raw 0 0x1500000;" - "u-boot.img raw 0x%x 0x500000", + "%s raw 0x%x 0x500000", + CONFIG_SPL_FS_LOAD_PAYLOAD_NAME, CONFIG_SYS_SPI_U_BOOT_OFFS); break; default: From 88eaca26f6a2d2e591cdc79b71c1dc3e92e6224e Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Tue, 9 Aug 2022 16:32:54 +0200 Subject: [PATCH 15/42] xilinx: Define only mmc devnum not partition The commit 53b406369e9d ("DFU: Check the number of arguments and argument string strictly") added strict control over string that 0:1 partition definition is not valid anymore that's why use only device number without partition ID. Device is specified by 2nd parameter and partition by 3rd. Signed-off-by: Michal Simek Link: https://lore.kernel.org/r/840eca944f4f2abeeb63b5d724f9ba5fe9a9213b.1660055571.git.michal.simek@amd.com --- board/xilinx/zynq/board.c | 2 +- board/xilinx/zynqmp/zynqmp.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/board/xilinx/zynq/board.c b/board/xilinx/zynq/board.c index 3ab63fa76e..c96433be69 100644 --- a/board/xilinx/zynq/board.c +++ b/board/xilinx/zynq/board.c @@ -176,7 +176,7 @@ void set_dfu_alt_info(char *interface, char *devstr) switch ((zynq_slcr_get_boot_mode()) & ZYNQ_BM_MASK) { case ZYNQ_BM_SD: snprintf(buf, DFU_ALT_BUF_LEN, - "mmc 0:1=boot.bin fat 0 1;" + "mmc 0=boot.bin fat 0 1;" "%s fat 0 1", CONFIG_SPL_FS_LOAD_PAYLOAD_NAME); break; case ZYNQ_BM_QSPI: diff --git a/board/xilinx/zynqmp/zynqmp.c b/board/xilinx/zynqmp/zynqmp.c index 29a6e3675f..21bcc26682 100644 --- a/board/xilinx/zynqmp/zynqmp.c +++ b/board/xilinx/zynqmp/zynqmp.c @@ -661,13 +661,13 @@ void set_dfu_alt_info(char *interface, char *devstr) bootseq = mmc_get_env_dev(); if (!multiboot) snprintf(buf, DFU_ALT_BUF_LEN, - "mmc %d:1=boot.bin fat %d 1;" + "mmc %d=boot.bin fat %d 1;" "%s fat %d 1", bootseq, bootseq, CONFIG_SPL_FS_LOAD_PAYLOAD_NAME, bootseq); else snprintf(buf, DFU_ALT_BUF_LEN, - "mmc %d:1=boot%04d.bin fat %d 1;" + "mmc %d=boot%04d.bin fat %d 1;" "%s fat %d 1", bootseq, multiboot, bootseq, CONFIG_SPL_FS_LOAD_PAYLOAD_NAME, bootseq); From c8630167e0dcd816a9ed6870df550aa1270d7b7a Mon Sep 17 00:00:00 2001 From: Amit Kumar Mahapatra Date: Tue, 23 Aug 2022 10:18:03 +0200 Subject: [PATCH 16/42] arm64: zynqmp: Add mtd partition for secure OS storage area Update MTD partitions of Kria device trees to allocate 128KB of QSPI memory for secure OS. Increased "SHA256" partition size & changed starting address of "User" partition to accommodate the new partition "Secure OS Storage" Signed-off-by: Amit Kumar Mahapatra Signed-off-by: Michal Simek Link: https://lore.kernel.org/r/9cc64b8c731d11439de73d0af54c65080068f00b.1661242681.git.michal.simek@amd.com --- arch/arm/dts/zynqmp-sm-k26-revA.dts | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/arch/arm/dts/zynqmp-sm-k26-revA.dts b/arch/arm/dts/zynqmp-sm-k26-revA.dts index ac349a9dcc..bae24aabdb 100644 --- a/arch/arm/dts/zynqmp-sm-k26-revA.dts +++ b/arch/arm/dts/zynqmp-sm-k26-revA.dts @@ -214,13 +214,17 @@ }; partition@2240000 { label = "SHA256"; - reg = <0x2240000 0x10000>; /* 256B but 64KB sector */ + reg = <0x2240000 0x40000>; /* 256B but 256KB sector */ read-only; lock; }; - partition@2250000 { + partition@2280000 { + label = "Secure OS Storage"; + reg = <0x2280000 0x20000>; /* 128KB */ + }; + partition@22A0000 { label = "User"; - reg = <0x2250000 0x1db0000>; /* 29.5 MB */ + reg = <0x22A0000 0x1db0000>; /* 29.5 MB */ }; }; }; From ddcc161c4e161480e5cdd5eea37a05ed290b19bf Mon Sep 17 00:00:00 2001 From: Harini Katakam Date: Tue, 23 Aug 2022 14:59:20 +0200 Subject: [PATCH 17/42] arm: dts: Add xlnx prefix to GEM compatible string cdns,zynq/zynqmp were recentle deprecated in Linux in favour of xlnx prefix. Add this new compatible string and retain the existing string for compatibility with uboot drivers. Signed-off-by: Harini Katakam Signed-off-by: Michal Simek Link: https://lore.kernel.org/r/a38b1b55132fc026cc09224dba61e42fd03b1a36.1661259558.git.michal.simek@amd.com --- arch/arm/dts/zynq-7000.dtsi | 4 ++-- arch/arm/dts/zynqmp.dtsi | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/arch/arm/dts/zynq-7000.dtsi b/arch/arm/dts/zynq-7000.dtsi index a7ca00fb76..b4aa09d149 100644 --- a/arch/arm/dts/zynq-7000.dtsi +++ b/arch/arm/dts/zynq-7000.dtsi @@ -247,7 +247,7 @@ }; gem0: ethernet@e000b000 { - compatible = "cdns,zynq-gem", "cdns,gem"; + compatible = "xlnx,zynq-gem", "cdns,zynq-gem", "cdns,gem"; reg = <0xe000b000 0x1000>; status = "disabled"; interrupts = <0 22 4>; @@ -258,7 +258,7 @@ }; gem1: ethernet@e000c000 { - compatible = "cdns,zynq-gem", "cdns,gem"; + compatible = "xlnx,zynq-gem", "cdns,zynq-gem", "cdns,gem"; reg = <0xe000c000 0x1000>; status = "disabled"; interrupts = <0 45 4>; diff --git a/arch/arm/dts/zynqmp.dtsi b/arch/arm/dts/zynqmp.dtsi index fbc6e752da..2aaec6cf5a 100644 --- a/arch/arm/dts/zynqmp.dtsi +++ b/arch/arm/dts/zynqmp.dtsi @@ -529,7 +529,7 @@ }; gem0: ethernet@ff0b0000 { - compatible = "cdns,zynqmp-gem", "cdns,gem"; + compatible = "xlnx,zynqmp-gem", "cdns,zynqmp-gem", "cdns,gem"; status = "disabled"; interrupt-parent = <&gic>; interrupts = <0 57 4>, <0 57 4>; @@ -543,7 +543,7 @@ }; gem1: ethernet@ff0c0000 { - compatible = "cdns,zynqmp-gem", "cdns,gem"; + compatible = "xlnx,zynqmp-gem", "cdns,zynqmp-gem", "cdns,gem"; status = "disabled"; interrupt-parent = <&gic>; interrupts = <0 59 4>, <0 59 4>; @@ -557,7 +557,7 @@ }; gem2: ethernet@ff0d0000 { - compatible = "cdns,zynqmp-gem", "cdns,gem"; + compatible = "xlnx,zynqmp-gem", "cdns,zynqmp-gem", "cdns,gem"; status = "disabled"; interrupt-parent = <&gic>; interrupts = <0 61 4>, <0 61 4>; @@ -571,7 +571,7 @@ }; gem3: ethernet@ff0e0000 { - compatible = "cdns,zynqmp-gem", "cdns,gem"; + compatible = "xlnx,zynqmp-gem", "cdns,zynqmp-gem", "cdns,gem"; status = "disabled"; interrupt-parent = <&gic>; interrupts = <0 63 4>, <0 63 4>; From fd9c9f293201b4f819b1fbdc5e85e70ca9cdc231 Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Tue, 23 Aug 2022 15:00:25 +0200 Subject: [PATCH 18/42] arm64: zynqmp: Add missing tca6416 to zynqmp SC Add missing tca6416 i2c gpio controller to SC dts file. Signed-off-by: Michal Simek Link: https://lore.kernel.org/r/a19c191d0dffb213d9dc8809d22728d79cf73a22.1661259623.git.michal.simek@amd.com --- arch/arm/dts/zynqmp-e-a2197-00-revA.dts | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/arch/arm/dts/zynqmp-e-a2197-00-revA.dts b/arch/arm/dts/zynqmp-e-a2197-00-revA.dts index 37c56181c9..4940825b00 100644 --- a/arch/arm/dts/zynqmp-e-a2197-00-revA.dts +++ b/arch/arm/dts/zynqmp-e-a2197-00-revA.dts @@ -203,6 +203,18 @@ &i2c0 { /* MIO 34-35 - can't stay here */ status = "okay"; clock-frequency = <400000>; + + tca6416_u233: gpio@20 { /* u233 */ + compatible = "ti,tca6416"; + reg = <0x20>; + gpio-controller; /* interrupt not connected */ + #gpio-cells = <2>; + gpio-line-names = "MAX6643_OT_B", "MAX6643_FANFAIL_B", "", "", /* 0 - 3 */ + "PMBUS2_INA226_ALERT", "", "", "MAX6643_FULLSPD", /* 4 - 7 */ + "FMCP1_FMC_PRSNT_M2C_B", "FMCP2_FMC_PRSNT_M2C_B", "FMCP1_FMCP_PRSNT_M2C_B", "FMCP2_FMCP_PRSNT_M2C_B", /* 10 - 13 */ + "VCCINT_VRHOT_B", "8A34001_EXP_RST_B", "PMBUS_ALERT", "PMBUS1_INA226_ALERT"; /* 14 - 17 */ + }; + i2c-mux@74 { /* u33 */ compatible = "nxp,pca9548"; #address-cells = <1>; From 1bff67eda73dbeec00ae6b8fbf6bd3a824578578 Mon Sep 17 00:00:00 2001 From: Piyush Mehta Date: Tue, 23 Aug 2022 15:03:31 +0200 Subject: [PATCH 19/42] arm64: zynqmp: add ref_clk property for REFCLKPER calculation Added ref_clk 'ref' property for GUCTL_REFCLKPER and GFLADJ_REFCLK_FLADJ calculation. This property configure correct value for SOF/ITP counter and period of ref_clk. This patch adds 'ref' property for both dwc3_0 and dwc3_1 cores. Signed-off-by: Piyush Mehta Signed-off-by: Michal Simek Link: https://lore.kernel.org/r/417545b948ea12a9301a5e80851f98523be2b443.1661259809.git.michal.simek@amd.com --- arch/arm/dts/zynqmp-clk-ccf.dtsi | 8 ++++++++ arch/arm/dts/zynqmp.dtsi | 2 ++ 2 files changed, 10 insertions(+) diff --git a/arch/arm/dts/zynqmp-clk-ccf.dtsi b/arch/arm/dts/zynqmp-clk-ccf.dtsi index 7b09d75151..b99eb07b00 100644 --- a/arch/arm/dts/zynqmp-clk-ccf.dtsi +++ b/arch/arm/dts/zynqmp-clk-ccf.dtsi @@ -260,11 +260,19 @@ assigned-clocks = <&zynqmp_clk USB0_BUS_REF>, <&zynqmp_clk USB3_DUAL_REF>; }; +&dwc3_0 { + clocks = <&zynqmp_clk USB3_DUAL_REF>; +}; + &usb1 { clocks = <&zynqmp_clk USB1_BUS_REF>, <&zynqmp_clk USB3_DUAL_REF>; assigned-clocks = <&zynqmp_clk USB1_BUS_REF>, <&zynqmp_clk USB3_DUAL_REF>; }; +&dwc3_1 { + clocks = <&zynqmp_clk USB3_DUAL_REF>; +}; + &watchdog0 { clocks = <&zynqmp_clk WDT>; }; diff --git a/arch/arm/dts/zynqmp.dtsi b/arch/arm/dts/zynqmp.dtsi index 2aaec6cf5a..f4184f79a5 100644 --- a/arch/arm/dts/zynqmp.dtsi +++ b/arch/arm/dts/zynqmp.dtsi @@ -869,6 +869,7 @@ iommus = <&smmu 0x860>; snps,quirk-frame-length-adjustment = <0x20>; snps,refclk_fladj; + clock-names = "ref"; snps,enable_guctl1_resume_quirk; snps,enable_guctl1_ipd_quirk; snps,xhci-stream-quirk; @@ -900,6 +901,7 @@ iommus = <&smmu 0x861>; snps,quirk-frame-length-adjustment = <0x20>; snps,refclk_fladj; + clock-names = "ref"; snps,enable_guctl1_resume_quirk; snps,enable_guctl1_ipd_quirk; snps,xhci-stream-quirk; From ce8808628e18cd3d71fbc001edb15e59ee824d91 Mon Sep 17 00:00:00 2001 From: T Karthik Reddy Date: Wed, 24 Aug 2022 13:23:26 +0200 Subject: [PATCH 20/42] xilinx: Add env redund offset ENV_OFFSET_REDUND config is by default set to 0 for flashes. Saving the env variables is overwriting data at 0 offset, which is wrong. So add default redund env offset for Zynq, ZynqMP, Versal and microblaze platforms. Configured ENV_OFFSET_REDUND offsets by ENV_OFFSET + (2 * ENV_SIZE). In case of versal, we configured ENV_OFFSET_REDUND at 0x7F00000 instead of 0x7F80000. As BOOT_SCRIPT_OFFSET is already configured at 0x7F80000. Added ENV_OFFSET_REDUND in Kconfig for microblaze due to dependency of ENV_IS_IN_SPI_FLASH config. Below table specifies platform specific env and env redund offsets. PLAT ENV_OFFSET ENV_OFFSET_REDUND ---- ---------- ----------------- ZYNQ 0xE0000 0xE40000 ZYNQMP 0x1E00000 0x1E80000 VERSAL 0x7F40000 0x7F00000 MICROBLAZE 0x1080000 0x10C0000 Signed-off-by: T Karthik Reddy Signed-off-by: Michal Simek Link: https://lore.kernel.org/r/92656dc08f0f5a749d62b71ca6e77fe1be72e9e0.1661340204.git.michal.simek@amd.com --- configs/xilinx_versal_virt_defconfig | 1 + configs/xilinx_zynq_virt_defconfig | 1 + configs/xilinx_zynqmp_virt_defconfig | 1 + env/Kconfig | 1 + 4 files changed, 4 insertions(+) diff --git a/configs/xilinx_versal_virt_defconfig b/configs/xilinx_versal_virt_defconfig index ffd8bea81c..7b96c4fbd9 100644 --- a/configs/xilinx_versal_virt_defconfig +++ b/configs/xilinx_versal_virt_defconfig @@ -7,6 +7,7 @@ CONFIG_SYS_TEXT_BASE=0x8000000 CONFIG_SYS_MALLOC_F_LEN=0x100000 CONFIG_DEFAULT_DEVICE_TREE="xilinx-versal-virt" CONFIG_SYS_PROMPT="Versal> " +CONFIG_ENV_OFFSET_REDUND=0x7F00000 CONFIG_CMD_FRU=y CONFIG_DEFINE_TCM_OCM_MMAP=y CONFIG_SYS_LOAD_ADDR=0x8000000 diff --git a/configs/xilinx_zynq_virt_defconfig b/configs/xilinx_zynq_virt_defconfig index e6f8e221a5..b8e16cab6e 100644 --- a/configs/xilinx_zynq_virt_defconfig +++ b/configs/xilinx_zynq_virt_defconfig @@ -8,6 +8,7 @@ CONFIG_DM_GPIO=y CONFIG_DEFAULT_DEVICE_TREE="zynq-zc706" CONFIG_SPL_STACK_R_ADDR=0x200000 CONFIG_SPL=y +CONFIG_ENV_OFFSET_REDUND=0xE40000 CONFIG_CMD_FRU=y CONFIG_CMD_ZYNQ_AES=y CONFIG_SYS_LOAD_ADDR=0x0 diff --git a/configs/xilinx_zynqmp_virt_defconfig b/configs/xilinx_zynqmp_virt_defconfig index e5ac26e038..e242884d3f 100644 --- a/configs/xilinx_zynqmp_virt_defconfig +++ b/configs/xilinx_zynqmp_virt_defconfig @@ -10,6 +10,7 @@ CONFIG_SPL_STACK_R_ADDR=0x18000000 CONFIG_SPL_SIZE_LIMIT=0x2a000 CONFIG_SPL_SIZE_LIMIT_PROVIDE_STACK=0x0 CONFIG_SPL=y +CONFIG_ENV_OFFSET_REDUND=0x1E80000 CONFIG_SPL_SPI_FLASH_SUPPORT=y CONFIG_SPL_SPI=y CONFIG_ZYNQ_MAC_IN_EEPROM=y diff --git a/env/Kconfig b/env/Kconfig index 238e4c70cf..5329f7585b 100644 --- a/env/Kconfig +++ b/env/Kconfig @@ -570,6 +570,7 @@ config ENV_OFFSET_REDUND hex "Redundant environment offset" depends on (ENV_IS_IN_EEPROM || ENV_IS_IN_MMC || ENV_IS_IN_NAND || \ ENV_IS_IN_SPI_FLASH) && SYS_REDUNDAND_ENVIRONMENT + default 0x10C0000 if MICROBLAZE default 0 help Offset from the start of the device (or partition) of the redundant From a27278f054309aa9192c858154869fa25bdff5ec Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Wed, 24 Aug 2022 13:28:35 +0200 Subject: [PATCH 21/42] xilinx: Enable CMD_GREPENV/SETEXPR by default Enable both of these commands in Xilinx SoCs to be able to use them in boot scripts. Signed-off-by: Michal Simek Link: https://lore.kernel.org/r/1a612be7e09e9bc502f30e1f025441ccf8accba5.1661340513.git.michal.simek@amd.com --- configs/microblaze-generic_defconfig | 2 +- configs/xilinx_versal_virt_defconfig | 1 + configs/xilinx_zynq_virt_defconfig | 2 +- configs/xilinx_zynqmp_virt_defconfig | 1 + 4 files changed, 4 insertions(+), 2 deletions(-) diff --git a/configs/microblaze-generic_defconfig b/configs/microblaze-generic_defconfig index b5c5efe596..01c93d5c4e 100644 --- a/configs/microblaze-generic_defconfig +++ b/configs/microblaze-generic_defconfig @@ -43,9 +43,9 @@ CONFIG_SYS_BOOTM_LEN=0x4000000 CONFIG_CMD_IMLS=y CONFIG_CMD_SPL=y CONFIG_CMD_ASKENV=y +CONFIG_CMD_GREPENV=y CONFIG_CMD_GPIO=y CONFIG_CMD_SAVES=y -# CONFIG_CMD_SETEXPR is not set CONFIG_BOOTP_BOOTFILESIZE=y CONFIG_CMD_TFTPPUT=y CONFIG_CMD_CACHE=y diff --git a/configs/xilinx_versal_virt_defconfig b/configs/xilinx_versal_virt_defconfig index 7b96c4fbd9..c3fa913b20 100644 --- a/configs/xilinx_versal_virt_defconfig +++ b/configs/xilinx_versal_virt_defconfig @@ -26,6 +26,7 @@ CONFIG_SYS_MAXARGS=64 CONFIG_SYS_PBSIZE=2073 CONFIG_SYS_BOOTM_LEN=0x6400000 CONFIG_CMD_BOOTMENU=y +CONFIG_CMD_GREPENV=y CONFIG_CMD_NVEDIT_EFI=y CONFIG_CMD_MEMTEST=y CONFIG_SYS_ALT_MEMTEST=y diff --git a/configs/xilinx_zynq_virt_defconfig b/configs/xilinx_zynq_virt_defconfig index b8e16cab6e..c12a1cbbc8 100644 --- a/configs/xilinx_zynq_virt_defconfig +++ b/configs/xilinx_zynq_virt_defconfig @@ -51,6 +51,7 @@ CONFIG_SYS_PBSIZE=2071 CONFIG_SYS_BOOTM_LEN=0x3c00000 CONFIG_CMD_IMLS=y CONFIG_CMD_THOR_DOWNLOAD=y +CONFIG_CMD_GREPENV=y CONFIG_CMD_MEMTEST=y CONFIG_SYS_ALT_MEMTEST=y CONFIG_CMD_DFU=y @@ -65,7 +66,6 @@ CONFIG_CMD_MTD=y CONFIG_CMD_NAND_LOCK_UNLOCK=y CONFIG_CMD_SF_TEST=y CONFIG_CMD_USB=y -# CONFIG_CMD_SETEXPR is not set CONFIG_BOOTP_MAY_FAIL=y CONFIG_CMD_TFTPPUT=y CONFIG_CMD_CACHE=y diff --git a/configs/xilinx_zynqmp_virt_defconfig b/configs/xilinx_zynqmp_virt_defconfig index e242884d3f..1591f221b5 100644 --- a/configs/xilinx_zynqmp_virt_defconfig +++ b/configs/xilinx_zynqmp_virt_defconfig @@ -57,6 +57,7 @@ CONFIG_SYS_PBSIZE=2073 CONFIG_SYS_BOOTM_LEN=0x6400000 CONFIG_CMD_BOOTMENU=y CONFIG_CMD_THOR_DOWNLOAD=y +CONFIG_CMD_GREPENV=y CONFIG_CMD_NVEDIT_EFI=y CONFIG_CMD_MEMTEST=y CONFIG_SYS_ALT_MEMTEST=y From be3a73c0c42c548bb892faed5b4e8e4fe7cd3295 Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Wed, 31 Aug 2022 11:28:59 +0200 Subject: [PATCH 22/42] ARM: zynq: Align bss and end of u-boot image to 64bits The main reason is that DT memory reserved code is expecting DT to be 64bit aligned. For more information take a look at commit 5bd5ee02b23b ("xilinx: zynqmp: Check that DT is 64bit aligned"). Signed-off-by: Michal Simek Link: https://lore.kernel.org/r/9f3688cda188d8ea0b462df2aa08a10ddcc9c149.1661938136.git.michal.simek@amd.com --- arch/arm/mach-zynq/u-boot.lds | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm/mach-zynq/u-boot.lds b/arch/arm/mach-zynq/u-boot.lds index a5169fd915..3b7c9d515f 100644 --- a/arch/arm/mach-zynq/u-boot.lds +++ b/arch/arm/mach-zynq/u-boot.lds @@ -75,7 +75,7 @@ SECTIONS *(.__efi_runtime_rel_stop) } - . = ALIGN(4); + . = ALIGN(8); .image_copy_end : { *(.__image_copy_end) @@ -114,7 +114,7 @@ SECTIONS .bss __bss_base (OVERLAY) : { *(.bss*) - . = ALIGN(4); + . = ALIGN(8); __bss_limit = .; } From a32c3e9e4fb6932f80a165f56dc52e7afcffb2b2 Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Thu, 25 Aug 2022 14:23:10 +0200 Subject: [PATCH 23/42] arm64: xilinx: Move board_get_usable_ram_top() to common location The commit ce39ee28ec31 ("zynqmp: Do not place u-boot to reserved memory location") adds functionality for ZynqMP to read reserved memory node and do not place U-Boot to reserved location. This functionality is generic across all Xilinx SOCs that's why move it to common location to be used by all Xilinx SOCs. On zynq platform this is also fixing issue where U-Boot was placed to locating which was reserved already which ends up with error message "ERROR: reserving fdt memory region failed (addr=30000000 size=10000000 flags=4)" which is shown when bdinfo is called. Tested on vck190, zcu102, zc706 and kc705 to cover all platforms. Signed-off-by: Michal Simek Link: https://lore.kernel.org/r/b0817807912f7c7af6a8e1cf9ee04e5ab5de5f6a.1661430188.git.michal.simek@amd.com --- board/xilinx/common/board.c | 29 +++++++++++++++++++ .../microblaze-generic/microblaze-generic.c | 21 -------------- board/xilinx/versal/board.c | 23 --------------- board/xilinx/zynqmp/zynqmp.c | 29 ------------------- 4 files changed, 29 insertions(+), 73 deletions(-) diff --git a/board/xilinx/common/board.c b/board/xilinx/common/board.c index 9b4aded466..5e36386361 100644 --- a/board/xilinx/common/board.c +++ b/board/xilinx/common/board.c @@ -8,6 +8,8 @@ #include #include #include +#include +#include #include #include #include @@ -602,3 +604,30 @@ int embedded_dtb_select(void) return 0; } #endif + +#if defined(CONFIG_LMB) +ulong board_get_usable_ram_top(ulong total_size) +{ + phys_size_t size; + phys_addr_t reg; + struct lmb lmb; + + if (!total_size) + return gd->ram_top; + + if (!IS_ALIGNED((ulong)gd->fdt_blob, 0x8)) + panic("Not 64bit aligned DT location: %p\n", gd->fdt_blob); + + /* found enough not-reserved memory to relocated U-Boot */ + lmb_init(&lmb); + lmb_add(&lmb, gd->ram_base, gd->ram_size); + boot_fdt_add_mem_rsv_regions(&lmb, (void *)gd->fdt_blob); + size = ALIGN(CONFIG_SYS_MALLOC_LEN + total_size, MMU_SECTION_SIZE); + reg = lmb_alloc(&lmb, size, MMU_SECTION_SIZE); + + if (!reg) + reg = gd->ram_top - size; + + return reg + size; +} +#endif diff --git a/board/xilinx/microblaze-generic/microblaze-generic.c b/board/xilinx/microblaze-generic/microblaze-generic.c index f58ecd1590..a427ac94a1 100644 --- a/board/xilinx/microblaze-generic/microblaze-generic.c +++ b/board/xilinx/microblaze-generic/microblaze-generic.c @@ -14,8 +14,6 @@ #include #include #include -#include -#include #include #include #include @@ -38,25 +36,6 @@ int dram_init(void) return 0; }; -ulong board_get_usable_ram_top(ulong total_size) -{ - phys_size_t size; - phys_addr_t reg; - struct lmb lmb; - - /* found enough not-reserved memory to relocated U-Boot */ - lmb_init(&lmb); - lmb_add(&lmb, gd->ram_base, gd->ram_size); - boot_fdt_add_mem_rsv_regions(&lmb, (void *)gd->fdt_blob); - size = ALIGN(CONFIG_SYS_MALLOC_LEN + total_size, MMU_SECTION_SIZE); - reg = lmb_alloc(&lmb, size, MMU_SECTION_SIZE); - - if (!reg) - reg = gd->ram_top - size; - - return reg + size; -} - int board_late_init(void) { ulong max_size; diff --git a/board/xilinx/versal/board.c b/board/xilinx/versal/board.c index d8f39be56c..f9f5457ed2 100644 --- a/board/xilinx/versal/board.c +++ b/board/xilinx/versal/board.c @@ -9,7 +9,6 @@ #include #include #include -#include #include #include #include @@ -270,28 +269,6 @@ int dram_init(void) return 0; } -ulong board_get_usable_ram_top(ulong total_size) -{ - phys_size_t size; - phys_addr_t reg; - struct lmb lmb; - - if (!total_size) - return gd->ram_top; - - /* found enough not-reserved memory to relocated U-Boot */ - lmb_init(&lmb); - lmb_add(&lmb, gd->ram_base, gd->ram_size); - boot_fdt_add_mem_rsv_regions(&lmb, (void *)gd->fdt_blob); - size = ALIGN(CONFIG_SYS_MALLOC_LEN + total_size, MMU_SECTION_SIZE); - reg = lmb_alloc(&lmb, size, MMU_SECTION_SIZE); - - if (!reg) - reg = gd->ram_top - size; - - return reg + size; -} - void reset_cpu(void) { } diff --git a/board/xilinx/zynqmp/zynqmp.c b/board/xilinx/zynqmp/zynqmp.c index 21bcc26682..62537760df 100644 --- a/board/xilinx/zynqmp/zynqmp.c +++ b/board/xilinx/zynqmp/zynqmp.c @@ -12,8 +12,6 @@ #include #include #include -#include -#include #include #include #include @@ -256,33 +254,6 @@ int dram_init(void) return 0; } -#if defined(CONFIG_LMB) -ulong board_get_usable_ram_top(ulong total_size) -{ - phys_size_t size; - phys_addr_t reg; - struct lmb lmb; - - if (!total_size) - return gd->ram_top; - - if (!IS_ALIGNED((ulong)gd->fdt_blob, 0x8)) - panic("Not 64bit aligned DT location: %p\n", gd->fdt_blob); - - /* found enough not-reserved memory to relocated U-Boot */ - lmb_init(&lmb); - lmb_add(&lmb, gd->ram_base, gd->ram_size); - boot_fdt_add_mem_rsv_regions(&lmb, (void *)gd->fdt_blob); - size = ALIGN(CONFIG_SYS_MALLOC_LEN + total_size, MMU_SECTION_SIZE); - reg = lmb_alloc(&lmb, size, MMU_SECTION_SIZE); - - if (!reg) - reg = gd->ram_top - size; - - return reg + size; -} -#endif - #else int dram_init_banksize(void) { From aaf0793be36f83f1458623bb1eef0670e02e8b82 Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Tue, 6 Sep 2022 12:41:34 +0200 Subject: [PATCH 24/42] xilinx: versal: Disable LMB for mini configurations There shouldn't be a reason to have LMB on for these configurations. LMB was already disabled for ZynqMP by commit 0063487a5b60 ("configs: zynqmp: Disable LMB for mini u-boot"). Signed-off-by: Michal Simek Link: https://lore.kernel.org/r/17d1e9b50b2fd032352911f94f4f213828e0a3f7.1662460892.git.michal.simek@amd.com --- configs/xilinx_versal_mini_defconfig | 1 + configs/xilinx_versal_mini_emmc0_defconfig | 1 + configs/xilinx_versal_mini_emmc1_defconfig | 1 + 3 files changed, 3 insertions(+) diff --git a/configs/xilinx_versal_mini_defconfig b/configs/xilinx_versal_mini_defconfig index a78ee631e4..7a0557a22e 100644 --- a/configs/xilinx_versal_mini_defconfig +++ b/configs/xilinx_versal_mini_defconfig @@ -66,3 +66,4 @@ CONFIG_SYS_RELOC_GD_ENV_ADDR=y # CONFIG_MMC is not set CONFIG_ARM_DCC=y # CONFIG_GZIP is not set +# CONFIG_LMB is not set diff --git a/configs/xilinx_versal_mini_emmc0_defconfig b/configs/xilinx_versal_mini_emmc0_defconfig index ef73579dca..4b626d3465 100644 --- a/configs/xilinx_versal_mini_emmc0_defconfig +++ b/configs/xilinx_versal_mini_emmc0_defconfig @@ -67,3 +67,4 @@ CONFIG_ARM_DCC=y CONFIG_FAT_WRITE=y # CONFIG_GZIP is not set # CONFIG_EFI_LOADER is not set +# CONFIG_LMB is not set diff --git a/configs/xilinx_versal_mini_emmc1_defconfig b/configs/xilinx_versal_mini_emmc1_defconfig index fb7c5cfdbb..6fe2ebf876 100644 --- a/configs/xilinx_versal_mini_emmc1_defconfig +++ b/configs/xilinx_versal_mini_emmc1_defconfig @@ -67,3 +67,4 @@ CONFIG_ARM_DCC=y CONFIG_FAT_WRITE=y # CONFIG_GZIP is not set # CONFIG_EFI_LOADER is not set +# CONFIG_LMB is not set From bae7d37e526f29504dd7765c80d664c0482c94dd Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Fri, 26 Aug 2022 10:30:47 +0200 Subject: [PATCH 25/42] net: gem: Check rate before setting it up On QEMU setting rate for fixed clock is failing. That's why check a rate first if the rate is the same there is no need to ask for the change. Signed-off-by: Michal Simek Link: https://lore.kernel.org/r/bc465ffd4904bfd65208b782daa06732b915db54.1661502645.git.michal.simek@amd.com --- drivers/net/zynq_gem.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/drivers/net/zynq_gem.c b/drivers/net/zynq_gem.c index 4e8dd4badd..61a6c83e33 100644 --- a/drivers/net/zynq_gem.c +++ b/drivers/net/zynq_gem.c @@ -500,10 +500,13 @@ static int zynq_gem_init(struct udevice *dev) } #endif - ret = clk_set_rate(&priv->tx_clk, clk_rate); - if (IS_ERR_VALUE(ret)) { - dev_err(dev, "failed to set tx clock rate\n"); - return ret; + ret = clk_get_rate(&priv->tx_clk); + if (ret != clk_rate) { + ret = clk_set_rate(&priv->tx_clk, clk_rate); + if (IS_ERR_VALUE(ret)) { + dev_err(dev, "failed to set tx clock rate %ld\n", clk_rate); + return ret; + } } ret = clk_enable(&priv->tx_clk); From 3a6948ce711b8c7692a3e717021cc2b47e69fce7 Mon Sep 17 00:00:00 2001 From: Ovidiu Panait Date: Mon, 29 Aug 2022 20:02:02 +0300 Subject: [PATCH 26/42] microblaze: drop CONFIG_SYS_INIT_RAM_ADDR and CONFIG_SYS_INIT_RAM_SIZE These macros are not used anymore in microblaze code since commit f113d7d303467 ("Convert CONFIG_SPL_STACK to Kconfig"), so remove them. Fixes: f113d7d303467 ("Convert CONFIG_SPL_STACK to Kconfig") Signed-off-by: Ovidiu Panait Link: https://lore.kernel.org/r/20220829170205.1274484-1-ovpanait@gmail.com Signed-off-by: Michal Simek --- include/configs/microblaze-generic.h | 6 ------ 1 file changed, 6 deletions(-) diff --git a/include/configs/microblaze-generic.h b/include/configs/microblaze-generic.h index 8eaac4f8bc..dfae8cea7b 100644 --- a/include/configs/microblaze-generic.h +++ b/include/configs/microblaze-generic.h @@ -97,10 +97,4 @@ #define CONFIG_SYS_UBOOT_BASE CONFIG_SYS_TEXT_BASE -/* SP location before relocation, must use scratch RAM */ -/* BRAM start */ -#define CONFIG_SYS_INIT_RAM_ADDR 0x0 -/* BRAM size - will be generated */ -#define CONFIG_SYS_INIT_RAM_SIZE 0x100000 - #endif /* __CONFIG_H */ From 3f351cd358a3581844f3cacdfe60710bf925d75d Mon Sep 17 00:00:00 2001 From: Ovidiu Panait Date: Mon, 29 Aug 2022 20:02:03 +0300 Subject: [PATCH 27/42] cpu: microblaze: add error handling in microblaze_cpu_get_desc() Check snprintf() return value for errors. Make microblaze_cpu_get_desc() directly return snprintf() error code if ret < 0. Otherwise, if the return value is greater than or equal to size, the resulting string is truncated, so return -ENOSPC. Fixes: 816226d27e ("cpu: add CPU driver for microblaze") Signed-off-by: Ovidiu Panait Link: https://lore.kernel.org/r/20220829170205.1274484-2-ovpanait@gmail.com Signed-off-by: Michal Simek --- drivers/cpu/microblaze_cpu.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/cpu/microblaze_cpu.c b/drivers/cpu/microblaze_cpu.c index 969a1047e5..b9d0792822 100644 --- a/drivers/cpu/microblaze_cpu.c +++ b/drivers/cpu/microblaze_cpu.c @@ -97,8 +97,10 @@ static int microblaze_cpu_get_desc(const struct udevice *dev, char *buf, ret = snprintf(buf, size, "MicroBlaze @ %uMHz, Rev: %s, FPGA family: %s", cpu_freq_mhz, cpu_ver, fpga_family); + if (ret < 0) + return ret; - return 0; + return (ret >= size) ? -ENOSPC : 0; } static int microblaze_cpu_get_info(const struct udevice *dev, From ae90d16ac78a2d7bd0327f71c26b46b5182315d3 Mon Sep 17 00:00:00 2001 From: Ovidiu Panait Date: Mon, 29 Aug 2022 20:02:04 +0300 Subject: [PATCH 28/42] cmd: bdinfo: introduce bdinfo_print_size() helper Add bdinfo_print_size() helper to display size variables (such as cache sizes) in bdinfo format. The size is printed as "xxx Bytes", "xxx KiB", "xxx MiB", "xxx GiB", etc as needed; Reviewed-by: Simon Glass Signed-off-by: Ovidiu Panait Reviewed-by: Jason Liu Link: https://lore.kernel.org/r/20220829170205.1274484-3-ovpanait@gmail.com Signed-off-by: Michal Simek --- cmd/bdinfo.c | 7 +++++++ include/init.h | 13 +++++++++++++ 2 files changed, 20 insertions(+) diff --git a/cmd/bdinfo.c b/cmd/bdinfo.c index 8a1bea4e34..af2e9757db 100644 --- a/cmd/bdinfo.c +++ b/cmd/bdinfo.c @@ -16,9 +16,16 @@ #include #include #include +#include DECLARE_GLOBAL_DATA_PTR; +void bdinfo_print_size(const char *name, uint64_t size) +{ + printf("%-12s= ", name); + print_size(size, "\n"); +} + void bdinfo_print_num_l(const char *name, ulong value) { printf("%-12s= 0x%0*lx\n", name, 2 * (int)sizeof(value), value); diff --git a/include/init.h b/include/init.h index 7b8f62c121..02bb4ce13e 100644 --- a/include/init.h +++ b/include/init.h @@ -343,6 +343,19 @@ void bdinfo_print_num_ll(const char *name, unsigned long long value); /* Print a clock speed in MHz */ void bdinfo_print_mhz(const char *name, unsigned long hz); +/** + * bdinfo_print_size - print size variables in bdinfo format + * @name: string to print before the size + * @size: size to print + * + * Helper function for displaying size variables as properly formatted bdinfo + * entries. The size is printed as "xxx Bytes", "xxx KiB", "xxx MiB", + * "xxx GiB", etc. as needed; + * + * For use in arch_print_bdinfo(). + */ +void bdinfo_print_size(const char *name, uint64_t size); + /* Show arch-specific information for the 'bd' command */ void arch_print_bdinfo(void); From f459986e86458a9980a3d0f4de1d4a44a549c00c Mon Sep 17 00:00:00 2001 From: Ovidiu Panait Date: Mon, 29 Aug 2022 20:02:05 +0300 Subject: [PATCH 29/42] microblaze: add arch_print_bdinfo() implementation Allow bdinfo command to print icache/dcache information: U-Boot-mONStR> bdinfo boot_params = 0x00000000 DRAM bank = 0x00000000 -> start = 0x04000000 -> size = 0x04000000 flashstart = 0x00000000 flashsize = 0x00000000 flashoffset = 0x00000000 baudrate = 9600 bps relocaddr = 0x07f76000 reloc off = 0x02f76000 Build = 32-bit current eth = unknown ethaddr = (not set) IP addr = fdt_blob = 0x07fec7e0 new_fdt = 0x00000000 fdt_size = 0x00000000 lmb_dump_all: memory.cnt = 0x1 memory[0] [0x4000000-0x7ffffff], 0x04000000 bytes flags: 0 reserved.cnt = 0x1 reserved[0] [0x7e94b8c-0x7ffffff], 0x0016b474 bytes flags: 0 devicetree = embed icache = 32 KiB icache line = 4 Bytes dcache = 32 KiB dcache line = 4 Bytes Signed-off-by: Ovidiu Panait Link: https://lore.kernel.org/r/20220829170205.1274484-4-ovpanait@gmail.com Signed-off-by: Michal Simek --- arch/microblaze/lib/Makefile | 1 + arch/microblaze/lib/bdinfo.c | 24 ++++++++++++++++++++++++ 2 files changed, 25 insertions(+) create mode 100644 arch/microblaze/lib/bdinfo.c diff --git a/arch/microblaze/lib/Makefile b/arch/microblaze/lib/Makefile index 05f447abba..dfd8135f4f 100644 --- a/arch/microblaze/lib/Makefile +++ b/arch/microblaze/lib/Makefile @@ -4,4 +4,5 @@ # Wolfgang Denk, DENX Software Engineering, wd@denx.de. obj-$(CONFIG_CMD_BOOTM) += bootm.o +obj-$(CONFIG_CMD_BDI) += bdinfo.o obj-y += muldi3.o diff --git a/arch/microblaze/lib/bdinfo.c b/arch/microblaze/lib/bdinfo.c new file mode 100644 index 0000000000..41b7a216a4 --- /dev/null +++ b/arch/microblaze/lib/bdinfo.c @@ -0,0 +1,24 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2022, Ovidiu Panait + */ +#include +#include +#include + +DECLARE_GLOBAL_DATA_PTR; + +void arch_print_bdinfo(void) +{ + struct microblaze_cpuinfo *ci = gd_cpuinfo(); + + if (ci->icache_size) { + bdinfo_print_size("icache", ci->icache_size); + bdinfo_print_size("icache line", ci->icache_line_length); + } + + if (ci->dcache_size) { + bdinfo_print_size("dcache", ci->dcache_size); + bdinfo_print_size("dcache line", ci->dcache_line_length); + } +} From 68852f3241af7d2f3e7cf85fbcd2268fd8c22b1e Mon Sep 17 00:00:00 2001 From: Ashok Reddy Soma Date: Wed, 24 Aug 2022 05:38:45 -0600 Subject: [PATCH 30/42] spi: cadence-qspi: Correct flash reset function name In cadence_spi_probe, cadence_qspi_versal_flash_reset() is called to reset the flash device. Looks like there is a mistake in previous series of patches where it is defined as cadence_spi_versal_flash_reset() but called as cadence_qspi_versal_flash_reset. Since there is a weak function defined with the same name this issue was not caught. Fix the issue by renaming cadence_spi_versal_flash_reset as cadence_qspi_versal_flash_reset(). Signed-off-by: Ashok Reddy Soma Link: https://lore.kernel.org/r/20220824113847.7482-2-ashok.reddy.soma@xilinx.com Signed-off-by: Michal Simek --- drivers/spi/cadence_ospi_versal.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/spi/cadence_ospi_versal.c b/drivers/spi/cadence_ospi_versal.c index 52bcad053f..c756a854bc 100644 --- a/drivers/spi/cadence_ospi_versal.c +++ b/drivers/spi/cadence_ospi_versal.c @@ -128,7 +128,7 @@ int cadence_qspi_apb_wait_for_dma_cmplt(struct cadence_spi_plat *plat) } #if defined(CONFIG_DM_GPIO) -int cadence_spi_versal_flash_reset(struct udevice *dev) +int cadence_qspi_versal_flash_reset(struct udevice *dev) { struct gpio_desc gpio; u32 reset_gpio; @@ -169,7 +169,7 @@ int cadence_spi_versal_flash_reset(struct udevice *dev) return 0; } #else -int cadence_spi_versal_flash_reset(struct udevice *dev) +int cadence_qspi_versal_flash_reset(struct udevice *dev) { /* CRP WPROT */ writel(0, WPROT_CRP); From d0003b5edf11b0fc2a050e2a0eaac39ba921d85e Mon Sep 17 00:00:00 2001 From: Ashok Reddy Soma Date: Wed, 24 Aug 2022 05:38:46 -0600 Subject: [PATCH 31/42] spi: cadence_qspi: Call read_setup for STIG_READ In cadence_spi_read_id we are using STIG mode to read flash id's. Call cadence_qspi_apb_command_read_setup() to setup cmd, addr and data bus width properly before cadence_qspi_apb_command_read(). Signed-off-by: Ashok Reddy Soma Link: https://lore.kernel.org/r/20220824113847.7482-3-ashok.reddy.soma@xilinx.com Signed-off-by: Michal Simek --- drivers/spi/cadence_qspi.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/spi/cadence_qspi.c b/drivers/spi/cadence_qspi.c index 907f5dadc4..6e50b94e14 100644 --- a/drivers/spi/cadence_qspi.c +++ b/drivers/spi/cadence_qspi.c @@ -59,12 +59,17 @@ static int cadence_spi_write_speed(struct udevice *bus, uint hz) static int cadence_spi_read_id(struct cadence_spi_plat *plat, u8 len, u8 *idcode) { + int err; struct spi_mem_op op = SPI_MEM_OP(SPI_MEM_OP_CMD(0x9F, 1), SPI_MEM_OP_NO_ADDR, SPI_MEM_OP_NO_DUMMY, SPI_MEM_OP_DATA_IN(len, idcode, 1)); - return cadence_qspi_apb_command_read(plat, &op); + err = cadence_qspi_apb_command_read_setup(plat, &op); + if (!err) + err = cadence_qspi_apb_command_read(plat, &op); + + return err; } /* Calibration sequence to determine the read data capture delay register */ From f7d4cab1b3059089e0bb16bc26849b2aad57fa17 Mon Sep 17 00:00:00 2001 From: Ashok Reddy Soma Date: Wed, 24 Aug 2022 05:38:47 -0600 Subject: [PATCH 32/42] spi: cadence-qspi: Use priv instead of plat across the driver As per driver model we should enumerate plat structure only in of_to_plat() and should be used only in probe(). Copy required plat structure info into priv structure in probe() and use priv structure across the driver. So replace plat with priv structure across the driver. Signed-off-by: Ashok Reddy Soma Link: https://lore.kernel.org/r/20220824113847.7482-4-ashok.reddy.soma@xilinx.com Signed-off-by: Michal Simek --- drivers/spi/cadence_ospi_versal.c | 52 +++---- drivers/spi/cadence_qspi.c | 101 +++++++------ drivers/spi/cadence_qspi.h | 56 +++++--- drivers/spi/cadence_qspi_apb.c | 231 +++++++++++++++--------------- 4 files changed, 236 insertions(+), 204 deletions(-) diff --git a/drivers/spi/cadence_ospi_versal.c b/drivers/spi/cadence_ospi_versal.c index c756a854bc..a25c50bc50 100644 --- a/drivers/spi/cadence_ospi_versal.c +++ b/drivers/spi/cadence_ospi_versal.c @@ -21,7 +21,7 @@ #define CMD_4BYTE_READ 0x13 #define CMD_4BYTE_FAST_READ 0x0C -int cadence_qspi_apb_dma_read(struct cadence_spi_plat *plat, +int cadence_qspi_apb_dma_read(struct cadence_spi_priv *priv, const struct spi_mem_op *op) { u32 reg, ret, rx_rem, n_rx, bytes_to_dma, data; @@ -34,86 +34,86 @@ int cadence_qspi_apb_dma_read(struct cadence_spi_plat *plat, if (bytes_to_dma) { cadence_qspi_apb_enable_linear_mode(false); - reg = readl(plat->regbase + CQSPI_REG_CONFIG); + reg = readl(priv->regbase + CQSPI_REG_CONFIG); reg |= CQSPI_REG_CONFIG_ENBL_DMA; - writel(reg, plat->regbase + CQSPI_REG_CONFIG); + writel(reg, priv->regbase + CQSPI_REG_CONFIG); - writel(bytes_to_dma, plat->regbase + CQSPI_REG_INDIRECTRDBYTES); + writel(bytes_to_dma, priv->regbase + CQSPI_REG_INDIRECTRDBYTES); writel(CQSPI_DFLT_INDIR_TRIG_ADDR_RANGE, - plat->regbase + CQSPI_REG_INDIR_TRIG_ADDR_RANGE); + priv->regbase + CQSPI_REG_INDIR_TRIG_ADDR_RANGE); writel(CQSPI_DFLT_DMA_PERIPH_CFG, - plat->regbase + CQSPI_REG_DMA_PERIPH_CFG); - writel((unsigned long)rxbuf, plat->regbase + + priv->regbase + CQSPI_REG_DMA_PERIPH_CFG); + writel((unsigned long)rxbuf, priv->regbase + CQSPI_DMA_DST_ADDR_REG); - writel(plat->trigger_address, plat->regbase + + writel(priv->trigger_address, priv->regbase + CQSPI_DMA_SRC_RD_ADDR_REG); - writel(bytes_to_dma, plat->regbase + + writel(bytes_to_dma, priv->regbase + CQSPI_DMA_DST_SIZE_REG); flush_dcache_range((unsigned long)rxbuf, (unsigned long)rxbuf + bytes_to_dma); writel(CQSPI_DFLT_DST_CTRL_REG_VAL, - plat->regbase + CQSPI_DMA_DST_CTRL_REG); + priv->regbase + CQSPI_DMA_DST_CTRL_REG); /* Start the indirect read transfer */ - writel(CQSPI_REG_INDIRECTRD_START, plat->regbase + + writel(CQSPI_REG_INDIRECTRD_START, priv->regbase + CQSPI_REG_INDIRECTRD); /* Wait for dma to complete transfer */ - ret = cadence_qspi_apb_wait_for_dma_cmplt(plat); + ret = cadence_qspi_apb_wait_for_dma_cmplt(priv); if (ret) return ret; /* Clear indirect completion status */ - writel(CQSPI_REG_INDIRECTRD_DONE, plat->regbase + + writel(CQSPI_REG_INDIRECTRD_DONE, priv->regbase + CQSPI_REG_INDIRECTRD); rxbuf += bytes_to_dma; } if (rx_rem) { - reg = readl(plat->regbase + CQSPI_REG_CONFIG); + reg = readl(priv->regbase + CQSPI_REG_CONFIG); reg &= ~CQSPI_REG_CONFIG_ENBL_DMA; - writel(reg, plat->regbase + CQSPI_REG_CONFIG); + writel(reg, priv->regbase + CQSPI_REG_CONFIG); - reg = readl(plat->regbase + CQSPI_REG_INDIRECTRDSTARTADDR); + reg = readl(priv->regbase + CQSPI_REG_INDIRECTRDSTARTADDR); reg += bytes_to_dma; - writel(reg, plat->regbase + CQSPI_REG_CMDADDRESS); + writel(reg, priv->regbase + CQSPI_REG_CMDADDRESS); - addr_bytes = readl(plat->regbase + CQSPI_REG_SIZE) & + addr_bytes = readl(priv->regbase + CQSPI_REG_SIZE) & CQSPI_REG_SIZE_ADDRESS_MASK; opcode = CMD_4BYTE_FAST_READ; dummy_cycles = 8; writel((dummy_cycles << CQSPI_REG_RD_INSTR_DUMMY_LSB) | opcode, - plat->regbase + CQSPI_REG_RD_INSTR); + priv->regbase + CQSPI_REG_RD_INSTR); reg = opcode << CQSPI_REG_CMDCTRL_OPCODE_LSB; reg |= (0x1 << CQSPI_REG_CMDCTRL_RD_EN_LSB); reg |= (addr_bytes & CQSPI_REG_CMDCTRL_ADD_BYTES_MASK) << CQSPI_REG_CMDCTRL_ADD_BYTES_LSB; reg |= (0x1 << CQSPI_REG_CMDCTRL_ADDR_EN_LSB); - dummy_cycles = (readl(plat->regbase + CQSPI_REG_RD_INSTR) >> + dummy_cycles = (readl(priv->regbase + CQSPI_REG_RD_INSTR) >> CQSPI_REG_RD_INSTR_DUMMY_LSB) & CQSPI_REG_RD_INSTR_DUMMY_MASK; reg |= (dummy_cycles & CQSPI_REG_CMDCTRL_DUMMY_MASK) << CQSPI_REG_CMDCTRL_DUMMY_LSB; reg |= (((rx_rem - 1) & CQSPI_REG_CMDCTRL_RD_BYTES_MASK) << CQSPI_REG_CMDCTRL_RD_BYTES_LSB); - ret = cadence_qspi_apb_exec_flash_cmd(plat->regbase, reg); + ret = cadence_qspi_apb_exec_flash_cmd(priv->regbase, reg); if (ret) return ret; - data = readl(plat->regbase + CQSPI_REG_CMDREADDATALOWER); + data = readl(priv->regbase + CQSPI_REG_CMDREADDATALOWER); memcpy(rxbuf, &data, rx_rem); } return 0; } -int cadence_qspi_apb_wait_for_dma_cmplt(struct cadence_spi_plat *plat) +int cadence_qspi_apb_wait_for_dma_cmplt(struct cadence_spi_priv *priv) { u32 timeout = CQSPI_DMA_TIMEOUT; - while (!(readl(plat->regbase + CQSPI_DMA_DST_I_STS_REG) & + while (!(readl(priv->regbase + CQSPI_DMA_DST_I_STS_REG) & CQSPI_DMA_DST_I_STS_DONE) && timeout--) udelay(1); @@ -122,8 +122,8 @@ int cadence_qspi_apb_wait_for_dma_cmplt(struct cadence_spi_plat *plat) return -ETIMEDOUT; } - writel(readl(plat->regbase + CQSPI_DMA_DST_I_STS_REG), - plat->regbase + CQSPI_DMA_DST_I_STS_REG); + writel(readl(priv->regbase + CQSPI_DMA_DST_I_STS_REG), + priv->regbase + CQSPI_DMA_DST_I_STS_REG); return 0; } diff --git a/drivers/spi/cadence_qspi.c b/drivers/spi/cadence_qspi.c index 6e50b94e14..ab0a681c83 100644 --- a/drivers/spi/cadence_qspi.c +++ b/drivers/spi/cadence_qspi.c @@ -29,7 +29,7 @@ #define CQSPI_READ 2 #define CQSPI_WRITE 3 -__weak int cadence_qspi_apb_dma_read(struct cadence_spi_plat *plat, +__weak int cadence_qspi_apb_dma_read(struct cadence_spi_priv *priv, const struct spi_mem_op *op) { return 0; @@ -42,32 +42,32 @@ __weak int cadence_qspi_versal_flash_reset(struct udevice *dev) static int cadence_spi_write_speed(struct udevice *bus, uint hz) { - struct cadence_spi_plat *plat = dev_get_plat(bus); struct cadence_spi_priv *priv = dev_get_priv(bus); cadence_qspi_apb_config_baudrate_div(priv->regbase, - plat->ref_clk_hz, hz); + priv->ref_clk_hz, hz); /* Reconfigure delay timing if speed is changed. */ - cadence_qspi_apb_delay(priv->regbase, plat->ref_clk_hz, hz, - plat->tshsl_ns, plat->tsd2d_ns, - plat->tchsh_ns, plat->tslch_ns); + cadence_qspi_apb_delay(priv->regbase, priv->ref_clk_hz, hz, + priv->tshsl_ns, priv->tsd2d_ns, + priv->tchsh_ns, priv->tslch_ns); return 0; } -static int cadence_spi_read_id(struct cadence_spi_plat *plat, u8 len, +static int cadence_spi_read_id(struct cadence_spi_priv *priv, u8 len, u8 *idcode) { int err; + struct spi_mem_op op = SPI_MEM_OP(SPI_MEM_OP_CMD(0x9F, 1), SPI_MEM_OP_NO_ADDR, SPI_MEM_OP_NO_DUMMY, SPI_MEM_OP_DATA_IN(len, idcode, 1)); - err = cadence_qspi_apb_command_read_setup(plat, &op); + err = cadence_qspi_apb_command_read_setup(priv, &op); if (!err) - err = cadence_qspi_apb_command_read(plat, &op); + err = cadence_qspi_apb_command_read(priv, &op); return err; } @@ -76,7 +76,6 @@ static int cadence_spi_read_id(struct cadence_spi_plat *plat, u8 len, static int spi_calibration(struct udevice *bus, uint hz) { struct cadence_spi_priv *priv = dev_get_priv(bus); - struct cadence_spi_plat *plat = dev_get_plat(bus); void *base = priv->regbase; unsigned int idcode = 0, temp = 0; int err = 0, i, range_lo = -1, range_hi = -1; @@ -91,7 +90,7 @@ static int spi_calibration(struct udevice *bus, uint hz) cadence_qspi_apb_controller_enable(base); /* read the ID which will be our golden value */ - err = cadence_spi_read_id(plat, 3, (u8 *)&idcode); + err = cadence_spi_read_id(priv, 3, (u8 *)&idcode); if (err) { puts("SF: Calibration failed (read)\n"); return err; @@ -110,7 +109,7 @@ static int spi_calibration(struct udevice *bus, uint hz) cadence_qspi_apb_controller_enable(base); /* issue a RDID to get the ID value */ - err = cadence_spi_read_id(plat, 3, (u8 *)&temp); + err = cadence_spi_read_id(priv, 3, (u8 *)&temp); if (err) { puts("SF: Calibration failed (read)\n"); return err; @@ -152,13 +151,11 @@ static int spi_calibration(struct udevice *bus, uint hz) static int cadence_spi_set_speed(struct udevice *bus, uint hz) { - struct cadence_spi_plat *plat = dev_get_plat(bus); struct cadence_spi_priv *priv = dev_get_priv(bus); int err; - if (!hz || hz > plat->max_hz) - hz = plat->max_hz; - + if (!hz || hz > priv->max_hz) + hz = priv->max_hz; /* Disable QSPI */ cadence_qspi_apb_controller_disable(priv->regbase); @@ -166,10 +163,10 @@ static int cadence_spi_set_speed(struct udevice *bus, uint hz) * If the device tree already provides a read delay value, use that * instead of calibrating. */ - if (plat->read_delay >= 0) { + if (priv->read_delay >= 0) { cadence_spi_write_speed(bus, hz); cadence_qspi_apb_readdata_capture(priv->regbase, 1, - plat->read_delay); + priv->read_delay); } else if (priv->previous_hz != hz || priv->qspi_calibrated_hz != hz || priv->qspi_calibrated_cs != spi_chip_select(bus)) { @@ -200,29 +197,44 @@ static int cadence_spi_probe(struct udevice *bus) struct clk clk; int ret; - priv->regbase = plat->regbase; - priv->ahbbase = plat->ahbbase; + priv->regbase = plat->regbase; + priv->ahbbase = plat->ahbbase; + priv->is_dma = plat->is_dma; + priv->is_decoded_cs = plat->is_decoded_cs; + priv->fifo_depth = plat->fifo_depth; + priv->fifo_width = plat->fifo_width; + priv->trigger_address = plat->trigger_address; + priv->read_delay = plat->read_delay; + priv->ahbsize = plat->ahbsize; + priv->max_hz = plat->max_hz; + + priv->page_size = plat->page_size; + priv->block_size = plat->block_size; + priv->tshsl_ns = plat->tshsl_ns; + priv->tsd2d_ns = plat->tsd2d_ns; + priv->tchsh_ns = plat->tchsh_ns; + priv->tslch_ns = plat->tslch_ns; if (CONFIG_IS_ENABLED(ZYNQMP_FIRMWARE)) xilinx_pm_request(PM_REQUEST_NODE, PM_DEV_OSPI, ZYNQMP_PM_CAPABILITY_ACCESS, ZYNQMP_PM_MAX_QOS, ZYNQMP_PM_REQUEST_ACK_NO, NULL); - if (plat->ref_clk_hz == 0) { + if (priv->ref_clk_hz == 0) { ret = clk_get_by_index(bus, 0, &clk); if (ret) { #ifdef CONFIG_HAS_CQSPI_REF_CLK - plat->ref_clk_hz = CONFIG_CQSPI_REF_CLK; + priv->ref_clk_hz = CONFIG_CQSPI_REF_CLK; #elif defined(CONFIG_ARCH_SOCFPGA) - plat->ref_clk_hz = cm_get_qspi_controller_clk_hz(); + priv->ref_clk_hz = cm_get_qspi_controller_clk_hz(); #else return ret; #endif } else { - plat->ref_clk_hz = clk_get_rate(&clk); + priv->ref_clk_hz = clk_get_rate(&clk); clk_free(&clk); - if (IS_ERR_VALUE(plat->ref_clk_hz)) - return plat->ref_clk_hz; + if (IS_ERR_VALUE(priv->ref_clk_hz)) + return priv->ref_clk_hz; } } @@ -231,16 +243,16 @@ static int cadence_spi_probe(struct udevice *bus) reset_deassert_bulk(priv->resets); if (!priv->qspi_is_init) { - cadence_qspi_apb_controller_init(plat); + cadence_qspi_apb_controller_init(priv); priv->qspi_is_init = 1; } - plat->wr_delay = 50 * DIV_ROUND_UP(NSEC_PER_SEC, plat->ref_clk_hz); + priv->wr_delay = 50 * DIV_ROUND_UP(NSEC_PER_SEC, priv->ref_clk_hz); if (CONFIG_IS_ENABLED(ARCH_VERSAL)) { /* Versal platform uses spi calibration to set read delay */ - if (plat->read_delay >= 0) - plat->read_delay = -1; + if (priv->read_delay >= 0) + priv->read_delay = -1; /* Reset ospi flash device */ ret = cadence_qspi_versal_flash_reset(bus); if (ret) @@ -263,7 +275,6 @@ static int cadence_spi_remove(struct udevice *dev) static int cadence_spi_set_mode(struct udevice *bus, uint mode) { - struct cadence_spi_plat *plat = dev_get_plat(bus); struct cadence_spi_priv *priv = dev_get_priv(bus); /* Disable QSPI */ @@ -273,7 +284,7 @@ static int cadence_spi_set_mode(struct udevice *bus, uint mode) cadence_qspi_apb_set_clk_mode(priv->regbase, mode); /* Enable Direct Access Controller */ - if (plat->use_dac_mode) + if (priv->use_dac_mode) cadence_qspi_apb_dac_mode_enable(priv->regbase); /* Enable QSPI */ @@ -286,7 +297,6 @@ static int cadence_spi_mem_exec_op(struct spi_slave *spi, const struct spi_mem_op *op) { struct udevice *bus = spi->dev->parent; - struct cadence_spi_plat *plat = dev_get_plat(bus); struct cadence_spi_priv *priv = dev_get_priv(bus); void *base = priv->regbase; int err = 0; @@ -294,7 +304,7 @@ static int cadence_spi_mem_exec_op(struct spi_slave *spi, /* Set Chip select */ cadence_qspi_apb_chipselect(base, spi_chip_select(spi->dev), - plat->is_decoded_cs); + priv->is_decoded_cs); if (op->data.dir == SPI_MEM_DATA_IN && op->data.buf.in) { if (!op->addr.nbytes) @@ -310,28 +320,28 @@ static int cadence_spi_mem_exec_op(struct spi_slave *spi, switch (mode) { case CQSPI_STIG_READ: - err = cadence_qspi_apb_command_read_setup(plat, op); + err = cadence_qspi_apb_command_read_setup(priv, op); if (!err) - err = cadence_qspi_apb_command_read(plat, op); + err = cadence_qspi_apb_command_read(priv, op); break; case CQSPI_STIG_WRITE: - err = cadence_qspi_apb_command_write_setup(plat, op); + err = cadence_qspi_apb_command_write_setup(priv, op); if (!err) - err = cadence_qspi_apb_command_write(plat, op); + err = cadence_qspi_apb_command_write(priv, op); break; case CQSPI_READ: - err = cadence_qspi_apb_read_setup(plat, op); + err = cadence_qspi_apb_read_setup(priv, op); if (!err) { - if (plat->is_dma) - err = cadence_qspi_apb_dma_read(plat, op); + if (priv->is_dma) + err = cadence_qspi_apb_dma_read(priv, op); else - err = cadence_qspi_apb_read_execute(plat, op); + err = cadence_qspi_apb_read_execute(priv, op); } break; case CQSPI_WRITE: - err = cadence_qspi_apb_write_setup(plat, op); + err = cadence_qspi_apb_write_setup(priv, op); if (!err) - err = cadence_qspi_apb_write_execute(plat, op); + err = cadence_qspi_apb_write_execute(priv, op); break; default: err = -1; @@ -364,6 +374,7 @@ static bool cadence_spi_mem_supports_op(struct spi_slave *slave, static int cadence_spi_of_to_plat(struct udevice *bus) { struct cadence_spi_plat *plat = dev_get_plat(bus); + struct cadence_spi_priv *priv = dev_get_priv(bus); ofnode subnode; plat->regbase = (void *)devfdt_get_addr_index(bus, 0); @@ -377,7 +388,7 @@ static int cadence_spi_of_to_plat(struct udevice *bus) 0); /* Use DAC mode only when MMIO window is at least 8M wide */ if (plat->ahbsize >= SZ_8M) - plat->use_dac_mode = true; + priv->use_dac_mode = true; plat->is_dma = dev_read_bool(bus, "cdns,is-dma"); diff --git a/drivers/spi/cadence_qspi.h b/drivers/spi/cadence_qspi.h index c8d16bb0e4..1c59d1a9d9 100644 --- a/drivers/spi/cadence_qspi.h +++ b/drivers/spi/cadence_qspi.h @@ -198,7 +198,6 @@ CQSPI_REG_SDRAMLEVEL_WR_LSB) & CQSPI_REG_SDRAMLEVEL_WR_MASK) struct cadence_spi_plat { - unsigned int ref_clk_hz; unsigned int max_hz; void *regbase; void *ahbbase; @@ -209,7 +208,6 @@ struct cadence_spi_plat { fdt_addr_t ahbsize; bool use_dac_mode; int read_delay; - u32 wr_delay; /* Flash parameters */ u32 page_size; @@ -219,17 +217,18 @@ struct cadence_spi_plat { u32 tchsh_ns; u32 tslch_ns; - /* Transaction protocol parameters. */ - u8 inst_width; - u8 addr_width; - u8 data_width; - bool dtr; bool is_dma; }; struct cadence_spi_priv { + unsigned int ref_clk_hz; + unsigned int max_hz; void *regbase; void *ahbbase; + unsigned int fifo_depth; + unsigned int fifo_width; + unsigned int trigger_address; + fdt_addr_t ahbsize; size_t cmd_len; u8 cmd_buf[32]; size_t data_len; @@ -238,32 +237,53 @@ struct cadence_spi_priv { unsigned int qspi_calibrated_hz; unsigned int qspi_calibrated_cs; unsigned int previous_hz; + u32 wr_delay; + int read_delay; struct reset_ctl_bulk *resets; + u32 page_size; + u32 block_size; + u32 tshsl_ns; + u32 tsd2d_ns; + u32 tchsh_ns; + u32 tslch_ns; + u8 edge_mode; + u8 dll_mode; + bool extra_dummy; + bool ddr_init; + bool is_decoded_cs; + bool use_dac_mode; + bool is_dma; + + /* Transaction protocol parameters. */ + u8 inst_width; + u8 addr_width; + u8 data_width; + bool dtr; }; /* Functions call declaration */ -void cadence_qspi_apb_controller_init(struct cadence_spi_plat *plat); +void cadence_qspi_apb_controller_init(struct cadence_spi_priv *priv); void cadence_qspi_apb_controller_enable(void *reg_base_addr); void cadence_qspi_apb_controller_disable(void *reg_base_addr); void cadence_qspi_apb_dac_mode_enable(void *reg_base); -int cadence_qspi_apb_command_read_setup(struct cadence_spi_plat *plat, +int cadence_qspi_apb_command_read_setup(struct cadence_spi_priv *priv, const struct spi_mem_op *op); -int cadence_qspi_apb_command_read(struct cadence_spi_plat *plat, +int cadence_qspi_apb_command_read(struct cadence_spi_priv *priv, const struct spi_mem_op *op); -int cadence_qspi_apb_command_write_setup(struct cadence_spi_plat *plat, +int cadence_qspi_apb_command_write_setup(struct cadence_spi_priv *priv, const struct spi_mem_op *op); -int cadence_qspi_apb_command_write(struct cadence_spi_plat *plat, +int cadence_qspi_apb_command_write(struct cadence_spi_priv *priv, const struct spi_mem_op *op); -int cadence_qspi_apb_read_setup(struct cadence_spi_plat *plat, +int cadence_qspi_apb_read_setup(struct cadence_spi_priv *priv, const struct spi_mem_op *op); -int cadence_qspi_apb_read_execute(struct cadence_spi_plat *plat, +int cadence_qspi_apb_read_execute(struct cadence_spi_priv *priv, const struct spi_mem_op *op); -int cadence_qspi_apb_write_setup(struct cadence_spi_plat *plat, +int cadence_qspi_apb_write_setup(struct cadence_spi_priv *priv, const struct spi_mem_op *op); -int cadence_qspi_apb_write_execute(struct cadence_spi_plat *plat, +int cadence_qspi_apb_write_execute(struct cadence_spi_priv *priv, const struct spi_mem_op *op); void cadence_qspi_apb_chipselect(void *reg_base, @@ -279,9 +299,9 @@ void cadence_qspi_apb_enter_xip(void *reg_base, char xip_dummy); void cadence_qspi_apb_readdata_capture(void *reg_base, unsigned int bypass, unsigned int delay); unsigned int cm_get_qspi_controller_clk_hz(void); -int cadence_qspi_apb_dma_read(struct cadence_spi_plat *plat, +int cadence_qspi_apb_dma_read(struct cadence_spi_priv *priv, const struct spi_mem_op *op); -int cadence_qspi_apb_wait_for_dma_cmplt(struct cadence_spi_plat *plat); +int cadence_qspi_apb_wait_for_dma_cmplt(struct cadence_spi_priv *priv); int cadence_qspi_apb_exec_flash_cmd(void *reg_base, unsigned int reg); int cadence_qspi_versal_flash_reset(struct udevice *dev); void cadence_qspi_apb_enable_linear_mode(bool enable); diff --git a/drivers/spi/cadence_qspi_apb.c b/drivers/spi/cadence_qspi_apb.c index c00755050e..cfae5dcbda 100644 --- a/drivers/spi/cadence_qspi_apb.c +++ b/drivers/spi/cadence_qspi_apb.c @@ -83,13 +83,13 @@ static unsigned int cadence_qspi_calc_dummy(const struct spi_mem_op *op, return dummy_clk; } -static u32 cadence_qspi_calc_rdreg(struct cadence_spi_plat *plat) +static u32 cadence_qspi_calc_rdreg(struct cadence_spi_priv *priv) { u32 rdreg = 0; - rdreg |= plat->inst_width << CQSPI_REG_RD_INSTR_TYPE_INSTR_LSB; - rdreg |= plat->addr_width << CQSPI_REG_RD_INSTR_TYPE_ADDR_LSB; - rdreg |= plat->data_width << CQSPI_REG_RD_INSTR_TYPE_DATA_LSB; + rdreg |= priv->inst_width << CQSPI_REG_RD_INSTR_TYPE_INSTR_LSB; + rdreg |= priv->addr_width << CQSPI_REG_RD_INSTR_TYPE_ADDR_LSB; + rdreg |= priv->data_width << CQSPI_REG_RD_INSTR_TYPE_DATA_LSB; return rdreg; } @@ -115,27 +115,27 @@ static int cadence_qspi_buswidth_to_inst_type(u8 buswidth) } } -static int cadence_qspi_set_protocol(struct cadence_spi_plat *plat, +static int cadence_qspi_set_protocol(struct cadence_spi_priv *priv, const struct spi_mem_op *op) { int ret; - plat->dtr = op->data.dtr && op->cmd.dtr && op->addr.dtr; + priv->dtr = op->data.dtr && op->cmd.dtr && op->addr.dtr; ret = cadence_qspi_buswidth_to_inst_type(op->cmd.buswidth); if (ret < 0) return ret; - plat->inst_width = ret; + priv->inst_width = ret; ret = cadence_qspi_buswidth_to_inst_type(op->addr.buswidth); if (ret < 0) return ret; - plat->addr_width = ret; + priv->addr_width = ret; ret = cadence_qspi_buswidth_to_inst_type(op->data.buswidth); if (ret < 0) return ret; - plat->data_width = ret; + priv->data_width = ret; return 0; } @@ -314,31 +314,31 @@ void cadence_qspi_apb_delay(void *reg_base, cadence_qspi_apb_controller_enable(reg_base); } -void cadence_qspi_apb_controller_init(struct cadence_spi_plat *plat) +void cadence_qspi_apb_controller_init(struct cadence_spi_priv *priv) { unsigned reg; - cadence_qspi_apb_controller_disable(plat->regbase); + cadence_qspi_apb_controller_disable(priv->regbase); /* Configure the device size and address bytes */ - reg = readl(plat->regbase + CQSPI_REG_SIZE); + reg = readl(priv->regbase + CQSPI_REG_SIZE); /* Clear the previous value */ reg &= ~(CQSPI_REG_SIZE_PAGE_MASK << CQSPI_REG_SIZE_PAGE_LSB); reg &= ~(CQSPI_REG_SIZE_BLOCK_MASK << CQSPI_REG_SIZE_BLOCK_LSB); - reg |= (plat->page_size << CQSPI_REG_SIZE_PAGE_LSB); - reg |= (plat->block_size << CQSPI_REG_SIZE_BLOCK_LSB); - writel(reg, plat->regbase + CQSPI_REG_SIZE); + reg |= (priv->page_size << CQSPI_REG_SIZE_PAGE_LSB); + reg |= (priv->block_size << CQSPI_REG_SIZE_BLOCK_LSB); + writel(reg, priv->regbase + CQSPI_REG_SIZE); /* Configure the remap address register, no remap */ - writel(0, plat->regbase + CQSPI_REG_REMAP); + writel(0, priv->regbase + CQSPI_REG_REMAP); /* Indirect mode configurations */ - writel(plat->fifo_depth / 2, plat->regbase + CQSPI_REG_SRAMPARTITION); + writel(priv->fifo_depth / 2, priv->regbase + CQSPI_REG_SRAMPARTITION); /* Disable all interrupts */ - writel(0, plat->regbase + CQSPI_REG_IRQMASK); + writel(0, priv->regbase + CQSPI_REG_IRQMASK); - cadence_qspi_apb_controller_enable(plat->regbase); + cadence_qspi_apb_controller_enable(priv->regbase); } int cadence_qspi_apb_exec_flash_cmd(void *reg_base, unsigned int reg) @@ -370,7 +370,7 @@ int cadence_qspi_apb_exec_flash_cmd(void *reg_base, unsigned int reg) return 0; } -static int cadence_qspi_setup_opcode_ext(struct cadence_spi_plat *plat, +static int cadence_qspi_setup_opcode_ext(struct cadence_spi_priv *priv, const struct spi_mem_op *op, unsigned int shift) { @@ -383,15 +383,15 @@ static int cadence_qspi_setup_opcode_ext(struct cadence_spi_plat *plat, /* Opcode extension is the LSB. */ ext = op->cmd.opcode & 0xff; - reg = readl(plat->regbase + CQSPI_REG_OP_EXT_LOWER); + reg = readl(priv->regbase + CQSPI_REG_OP_EXT_LOWER); reg &= ~(0xff << shift); reg |= ext << shift; - writel(reg, plat->regbase + CQSPI_REG_OP_EXT_LOWER); + writel(reg, priv->regbase + CQSPI_REG_OP_EXT_LOWER); return 0; } -static int cadence_qspi_enable_dtr(struct cadence_spi_plat *plat, +static int cadence_qspi_enable_dtr(struct cadence_spi_priv *priv, const struct spi_mem_op *op, unsigned int shift, bool enable) @@ -399,14 +399,14 @@ static int cadence_qspi_enable_dtr(struct cadence_spi_plat *plat, unsigned int reg; int ret; - reg = readl(plat->regbase + CQSPI_REG_CONFIG); + reg = readl(priv->regbase + CQSPI_REG_CONFIG); if (enable) { reg |= CQSPI_REG_CONFIG_DTR_PROTO; reg |= CQSPI_REG_CONFIG_DUAL_OPCODE; /* Set up command opcode extension. */ - ret = cadence_qspi_setup_opcode_ext(plat, op, shift); + ret = cadence_qspi_setup_opcode_ext(priv, op, shift); if (ret) return ret; } else { @@ -414,37 +414,37 @@ static int cadence_qspi_enable_dtr(struct cadence_spi_plat *plat, reg &= ~CQSPI_REG_CONFIG_DUAL_OPCODE; } - writel(reg, plat->regbase + CQSPI_REG_CONFIG); + writel(reg, priv->regbase + CQSPI_REG_CONFIG); return 0; } -int cadence_qspi_apb_command_read_setup(struct cadence_spi_plat *plat, +int cadence_qspi_apb_command_read_setup(struct cadence_spi_priv *priv, const struct spi_mem_op *op) { int ret; unsigned int reg; - ret = cadence_qspi_set_protocol(plat, op); + ret = cadence_qspi_set_protocol(priv, op); if (ret) return ret; - ret = cadence_qspi_enable_dtr(plat, op, CQSPI_REG_OP_EXT_STIG_LSB, - plat->dtr); + ret = cadence_qspi_enable_dtr(priv, op, CQSPI_REG_OP_EXT_STIG_LSB, + priv->dtr); if (ret) return ret; - reg = cadence_qspi_calc_rdreg(plat); - writel(reg, plat->regbase + CQSPI_REG_RD_INSTR); + reg = cadence_qspi_calc_rdreg(priv); + writel(reg, priv->regbase + CQSPI_REG_RD_INSTR); return 0; } /* For command RDID, RDSR. */ -int cadence_qspi_apb_command_read(struct cadence_spi_plat *plat, +int cadence_qspi_apb_command_read(struct cadence_spi_priv *priv, const struct spi_mem_op *op) { - void *reg_base = plat->regbase; + void *reg_base = priv->regbase; unsigned int reg; unsigned int read_len; int status; @@ -458,7 +458,7 @@ int cadence_qspi_apb_command_read(struct cadence_spi_plat *plat, return -EINVAL; } - if (plat->dtr) + if (priv->dtr) opcode = op->cmd.opcode >> 8; else opcode = op->cmd.opcode; @@ -466,7 +466,7 @@ int cadence_qspi_apb_command_read(struct cadence_spi_plat *plat, reg = opcode << CQSPI_REG_CMDCTRL_OPCODE_LSB; /* Set up dummy cycles. */ - dummy_clk = cadence_qspi_calc_dummy(op, plat->dtr); + dummy_clk = cadence_qspi_calc_dummy(op, priv->dtr); if (dummy_clk > CQSPI_DUMMY_CLKS_MAX) return -ENOTSUPP; @@ -499,29 +499,29 @@ int cadence_qspi_apb_command_read(struct cadence_spi_plat *plat, return 0; } -int cadence_qspi_apb_command_write_setup(struct cadence_spi_plat *plat, +int cadence_qspi_apb_command_write_setup(struct cadence_spi_priv *priv, const struct spi_mem_op *op) { int ret; unsigned int reg; - ret = cadence_qspi_set_protocol(plat, op); + ret = cadence_qspi_set_protocol(priv, op); if (ret) return ret; - ret = cadence_qspi_enable_dtr(plat, op, CQSPI_REG_OP_EXT_STIG_LSB, - plat->dtr); + ret = cadence_qspi_enable_dtr(priv, op, CQSPI_REG_OP_EXT_STIG_LSB, + priv->dtr); if (ret) return ret; - reg = cadence_qspi_calc_rdreg(plat); - writel(reg, plat->regbase + CQSPI_REG_RD_INSTR); + reg = cadence_qspi_calc_rdreg(priv); + writel(reg, priv->regbase + CQSPI_REG_RD_INSTR); return 0; } /* For commands: WRSR, WREN, WRDI, CHIP_ERASE, BE, etc. */ -int cadence_qspi_apb_command_write(struct cadence_spi_plat *plat, +int cadence_qspi_apb_command_write(struct cadence_spi_priv *priv, const struct spi_mem_op *op) { unsigned int reg = 0; @@ -529,7 +529,7 @@ int cadence_qspi_apb_command_write(struct cadence_spi_plat *plat, unsigned int wr_len; unsigned int txlen = op->data.nbytes; const void *txbuf = op->data.buf.out; - void *reg_base = plat->regbase; + void *reg_base = priv->regbase; u32 addr; u8 opcode; @@ -547,7 +547,7 @@ int cadence_qspi_apb_command_write(struct cadence_spi_plat *plat, return -EINVAL; } - if (plat->dtr) + if (priv->dtr) opcode = op->cmd.opcode >> 8; else opcode = op->cmd.opcode; @@ -579,7 +579,7 @@ int cadence_qspi_apb_command_write(struct cadence_spi_plat *plat, } /* Opcode + Address (3/4 bytes) + dummy bytes (0-4 bytes) */ -int cadence_qspi_apb_read_setup(struct cadence_spi_plat *plat, +int cadence_qspi_apb_read_setup(struct cadence_spi_priv *priv, const struct spi_mem_op *op) { unsigned int reg; @@ -589,33 +589,33 @@ int cadence_qspi_apb_read_setup(struct cadence_spi_plat *plat, int ret; u8 opcode; - ret = cadence_qspi_set_protocol(plat, op); + ret = cadence_qspi_set_protocol(priv, op); if (ret) return ret; - ret = cadence_qspi_enable_dtr(plat, op, CQSPI_REG_OP_EXT_READ_LSB, - plat->dtr); + ret = cadence_qspi_enable_dtr(priv, op, CQSPI_REG_OP_EXT_READ_LSB, + priv->dtr); if (ret) return ret; /* Setup the indirect trigger address */ - writel(plat->trigger_address, - plat->regbase + CQSPI_REG_INDIRECTTRIGGER); + writel(priv->trigger_address, + priv->regbase + CQSPI_REG_INDIRECTTRIGGER); /* Configure the opcode */ - if (plat->dtr) + if (priv->dtr) opcode = op->cmd.opcode >> 8; else opcode = op->cmd.opcode; rd_reg = opcode << CQSPI_REG_RD_INSTR_OPCODE_LSB; - rd_reg |= cadence_qspi_calc_rdreg(plat); + rd_reg |= cadence_qspi_calc_rdreg(priv); - writel(op->addr.val, plat->regbase + CQSPI_REG_INDIRECTRDSTARTADDR); + writel(op->addr.val, priv->regbase + CQSPI_REG_INDIRECTRDSTARTADDR); if (dummy_bytes) { /* Convert to clock cycles. */ - dummy_clk = cadence_qspi_calc_dummy(op, plat->dtr); + dummy_clk = cadence_qspi_calc_dummy(op, priv->dtr); if (dummy_clk > CQSPI_DUMMY_CLKS_MAX) return -ENOTSUPP; @@ -625,30 +625,30 @@ int cadence_qspi_apb_read_setup(struct cadence_spi_plat *plat, << CQSPI_REG_RD_INSTR_DUMMY_LSB; } - writel(rd_reg, plat->regbase + CQSPI_REG_RD_INSTR); + writel(rd_reg, priv->regbase + CQSPI_REG_RD_INSTR); /* set device size */ - reg = readl(plat->regbase + CQSPI_REG_SIZE); + reg = readl(priv->regbase + CQSPI_REG_SIZE); reg &= ~CQSPI_REG_SIZE_ADDRESS_MASK; reg |= (op->addr.nbytes - 1); - writel(reg, plat->regbase + CQSPI_REG_SIZE); + writel(reg, priv->regbase + CQSPI_REG_SIZE); return 0; } -static u32 cadence_qspi_get_rd_sram_level(struct cadence_spi_plat *plat) +static u32 cadence_qspi_get_rd_sram_level(struct cadence_spi_priv *priv) { - u32 reg = readl(plat->regbase + CQSPI_REG_SDRAMLEVEL); + u32 reg = readl(priv->regbase + CQSPI_REG_SDRAMLEVEL); reg >>= CQSPI_REG_SDRAMLEVEL_RD_LSB; return reg & CQSPI_REG_SDRAMLEVEL_RD_MASK; } -static int cadence_qspi_wait_for_data(struct cadence_spi_plat *plat) +static int cadence_qspi_wait_for_data(struct cadence_spi_priv *priv) { unsigned int timeout = 10000; u32 reg; while (timeout--) { - reg = cadence_qspi_get_rd_sram_level(plat); + reg = cadence_qspi_get_rd_sram_level(priv); if (reg) return reg; udelay(1); @@ -658,21 +658,21 @@ static int cadence_qspi_wait_for_data(struct cadence_spi_plat *plat) } static int -cadence_qspi_apb_indirect_read_execute(struct cadence_spi_plat *plat, +cadence_qspi_apb_indirect_read_execute(struct cadence_spi_priv *priv, unsigned int n_rx, u8 *rxbuf) { unsigned int remaining = n_rx; unsigned int bytes_to_read = 0; int ret; - writel(n_rx, plat->regbase + CQSPI_REG_INDIRECTRDBYTES); + writel(n_rx, priv->regbase + CQSPI_REG_INDIRECTRDBYTES); /* Start the indirect read transfer */ writel(CQSPI_REG_INDIRECTRD_START, - plat->regbase + CQSPI_REG_INDIRECTRD); + priv->regbase + CQSPI_REG_INDIRECTRD); while (remaining > 0) { - ret = cadence_qspi_wait_for_data(plat); + ret = cadence_qspi_wait_for_data(priv); if (ret < 0) { printf("Indirect write timed out (%i)\n", ret); goto failrd; @@ -681,7 +681,7 @@ cadence_qspi_apb_indirect_read_execute(struct cadence_spi_plat *plat, bytes_to_read = ret; while (bytes_to_read != 0) { - bytes_to_read *= plat->fifo_width; + bytes_to_read *= priv->fifo_width; bytes_to_read = bytes_to_read > remaining ? remaining : bytes_to_read; /* @@ -689,18 +689,18 @@ cadence_qspi_apb_indirect_read_execute(struct cadence_spi_plat *plat, * data abort. */ if (((uintptr_t)rxbuf % 4) || (bytes_to_read % 4)) - readsb(plat->ahbbase, rxbuf, bytes_to_read); + readsb(priv->ahbbase, rxbuf, bytes_to_read); else - readsl(plat->ahbbase, rxbuf, + readsl(priv->ahbbase, rxbuf, bytes_to_read >> 2); rxbuf += bytes_to_read; remaining -= bytes_to_read; - bytes_to_read = cadence_qspi_get_rd_sram_level(plat); + bytes_to_read = cadence_qspi_get_rd_sram_level(priv); } } /* Check indirect done status */ - ret = wait_for_bit_le32(plat->regbase + CQSPI_REG_INDIRECTRD, + ret = wait_for_bit_le32(priv->regbase + CQSPI_REG_INDIRECTRD, CQSPI_REG_INDIRECTRD_DONE, 1, 10, 0); if (ret) { printf("Indirect read completion error (%i)\n", ret); @@ -709,10 +709,10 @@ cadence_qspi_apb_indirect_read_execute(struct cadence_spi_plat *plat, /* Clear indirect completion status */ writel(CQSPI_REG_INDIRECTRD_DONE, - plat->regbase + CQSPI_REG_INDIRECTRD); + priv->regbase + CQSPI_REG_INDIRECTRD); /* Check indirect done status */ - ret = wait_for_bit_le32(plat->regbase + CQSPI_REG_INDIRECTRD, + ret = wait_for_bit_le32(priv->regbase + CQSPI_REG_INDIRECTRD, CQSPI_REG_INDIRECTRD_DONE, 0, 10, 0); if (ret) { printf("Indirect read clear completion error (%i)\n", ret); @@ -724,11 +724,11 @@ cadence_qspi_apb_indirect_read_execute(struct cadence_spi_plat *plat, failrd: /* Cancel the indirect read */ writel(CQSPI_REG_INDIRECTRD_CANCEL, - plat->regbase + CQSPI_REG_INDIRECTRD); + priv->regbase + CQSPI_REG_INDIRECTRD); return ret; } -int cadence_qspi_apb_read_execute(struct cadence_spi_plat *plat, +int cadence_qspi_apb_read_execute(struct cadence_spi_priv *priv, const struct spi_mem_op *op) { u64 from = op->addr.val; @@ -738,57 +738,57 @@ int cadence_qspi_apb_read_execute(struct cadence_spi_plat *plat, if (CONFIG_IS_ENABLED(ARCH_VERSAL)) cadence_qspi_apb_enable_linear_mode(true); - if (plat->use_dac_mode && (from + len < plat->ahbsize)) { + if (priv->use_dac_mode && (from + len < priv->ahbsize)) { if (len < 256 || - dma_memcpy(buf, plat->ahbbase + from, len) < 0) { - memcpy_fromio(buf, plat->ahbbase + from, len); + dma_memcpy(buf, priv->ahbbase + from, len) < 0) { + memcpy_fromio(buf, priv->ahbbase + from, len); } - if (!cadence_qspi_wait_idle(plat->regbase)) + if (!cadence_qspi_wait_idle(priv->regbase)) return -EIO; return 0; } - return cadence_qspi_apb_indirect_read_execute(plat, len, buf); + return cadence_qspi_apb_indirect_read_execute(priv, len, buf); } /* Opcode + Address (3/4 bytes) */ -int cadence_qspi_apb_write_setup(struct cadence_spi_plat *plat, +int cadence_qspi_apb_write_setup(struct cadence_spi_priv *priv, const struct spi_mem_op *op) { unsigned int reg; int ret; u8 opcode; - ret = cadence_qspi_set_protocol(plat, op); + ret = cadence_qspi_set_protocol(priv, op); if (ret) return ret; - ret = cadence_qspi_enable_dtr(plat, op, CQSPI_REG_OP_EXT_WRITE_LSB, - plat->dtr); + ret = cadence_qspi_enable_dtr(priv, op, CQSPI_REG_OP_EXT_WRITE_LSB, + priv->dtr); if (ret) return ret; /* Setup the indirect trigger address */ - writel(plat->trigger_address, - plat->regbase + CQSPI_REG_INDIRECTTRIGGER); + writel(priv->trigger_address, + priv->regbase + CQSPI_REG_INDIRECTTRIGGER); /* Configure the opcode */ - if (plat->dtr) + if (priv->dtr) opcode = op->cmd.opcode >> 8; else opcode = op->cmd.opcode; reg = opcode << CQSPI_REG_WR_INSTR_OPCODE_LSB; - reg |= plat->data_width << CQSPI_REG_WR_INSTR_TYPE_DATA_LSB; - reg |= plat->addr_width << CQSPI_REG_WR_INSTR_TYPE_ADDR_LSB; - writel(reg, plat->regbase + CQSPI_REG_WR_INSTR); + reg |= priv->data_width << CQSPI_REG_WR_INSTR_TYPE_DATA_LSB; + reg |= priv->addr_width << CQSPI_REG_WR_INSTR_TYPE_ADDR_LSB; + writel(reg, priv->regbase + CQSPI_REG_WR_INSTR); - reg = cadence_qspi_calc_rdreg(plat); - writel(reg, plat->regbase + CQSPI_REG_RD_INSTR); + reg = cadence_qspi_calc_rdreg(priv); + writel(reg, priv->regbase + CQSPI_REG_RD_INSTR); - writel(op->addr.val, plat->regbase + CQSPI_REG_INDIRECTWRSTARTADDR); + writel(op->addr.val, priv->regbase + CQSPI_REG_INDIRECTWRSTARTADDR); - if (plat->dtr) { + if (priv->dtr) { /* * Some flashes like the cypress Semper flash expect a 4-byte * dummy address with the Read SR command in DTR mode, but this @@ -797,23 +797,23 @@ int cadence_qspi_apb_write_setup(struct cadence_spi_plat *plat, * controller's side. spi-nor will take care of polling the * status register. */ - reg = readl(plat->regbase + CQSPI_REG_WR_COMPLETION_CTRL); + reg = readl(priv->regbase + CQSPI_REG_WR_COMPLETION_CTRL); reg |= CQSPI_REG_WR_DISABLE_AUTO_POLL; - writel(reg, plat->regbase + CQSPI_REG_WR_COMPLETION_CTRL); + writel(reg, priv->regbase + CQSPI_REG_WR_COMPLETION_CTRL); } - reg = readl(plat->regbase + CQSPI_REG_SIZE); + reg = readl(priv->regbase + CQSPI_REG_SIZE); reg &= ~CQSPI_REG_SIZE_ADDRESS_MASK; reg |= (op->addr.nbytes - 1); - writel(reg, plat->regbase + CQSPI_REG_SIZE); + writel(reg, priv->regbase + CQSPI_REG_SIZE); return 0; } static int -cadence_qspi_apb_indirect_write_execute(struct cadence_spi_plat *plat, +cadence_qspi_apb_indirect_write_execute(struct cadence_spi_priv *priv, unsigned int n_tx, const u8 *txbuf) { - unsigned int page_size = plat->page_size; + unsigned int page_size = priv->page_size; unsigned int remaining = n_tx; const u8 *bb_txbuf = txbuf; void *bounce_buf = NULL; @@ -833,27 +833,27 @@ cadence_qspi_apb_indirect_write_execute(struct cadence_spi_plat *plat, } /* Configure the indirect read transfer bytes */ - writel(n_tx, plat->regbase + CQSPI_REG_INDIRECTWRBYTES); + writel(n_tx, priv->regbase + CQSPI_REG_INDIRECTWRBYTES); /* Start the indirect write transfer */ writel(CQSPI_REG_INDIRECTWR_START, - plat->regbase + CQSPI_REG_INDIRECTWR); + priv->regbase + CQSPI_REG_INDIRECTWR); /* * Some delay is required for the above bit to be internally * synchronized by the QSPI module. */ - ndelay(plat->wr_delay); + ndelay(priv->wr_delay); while (remaining > 0) { write_bytes = remaining > page_size ? page_size : remaining; - writesl(plat->ahbbase, bb_txbuf, write_bytes >> 2); + writesl(priv->ahbbase, bb_txbuf, write_bytes >> 2); if (write_bytes % 4) - writesb(plat->ahbbase, + writesb(priv->ahbbase, bb_txbuf + rounddown(write_bytes, 4), write_bytes % 4); - ret = wait_for_bit_le32(plat->regbase + CQSPI_REG_SDRAMLEVEL, + ret = wait_for_bit_le32(priv->regbase + CQSPI_REG_SDRAMLEVEL, CQSPI_REG_SDRAMLEVEL_WR_MASK << CQSPI_REG_SDRAMLEVEL_WR_LSB, 0, 10, 0); if (ret) { @@ -866,7 +866,7 @@ cadence_qspi_apb_indirect_write_execute(struct cadence_spi_plat *plat, } /* Check indirect done status */ - ret = wait_for_bit_le32(plat->regbase + CQSPI_REG_INDIRECTWR, + ret = wait_for_bit_le32(priv->regbase + CQSPI_REG_INDIRECTWR, CQSPI_REG_INDIRECTWR_DONE, 1, 10, 0); if (ret) { printf("Indirect write completion error (%i)\n", ret); @@ -875,10 +875,10 @@ cadence_qspi_apb_indirect_write_execute(struct cadence_spi_plat *plat, /* Clear indirect completion status */ writel(CQSPI_REG_INDIRECTWR_DONE, - plat->regbase + CQSPI_REG_INDIRECTWR); + priv->regbase + CQSPI_REG_INDIRECTWR); /* Check indirect done status */ - ret = wait_for_bit_le32(plat->regbase + CQSPI_REG_INDIRECTWR, + ret = wait_for_bit_le32(priv->regbase + CQSPI_REG_INDIRECTWR, CQSPI_REG_INDIRECTWR_DONE, 0, 10, 0); if (ret) { printf("Indirect write clear completion error (%i)\n", ret); @@ -892,13 +892,13 @@ cadence_qspi_apb_indirect_write_execute(struct cadence_spi_plat *plat, failwr: /* Cancel the indirect write */ writel(CQSPI_REG_INDIRECTWR_CANCEL, - plat->regbase + CQSPI_REG_INDIRECTWR); + priv->regbase + CQSPI_REG_INDIRECTWR); if (bounce_buf) free(bounce_buf); return ret; } -int cadence_qspi_apb_write_execute(struct cadence_spi_plat *plat, +int cadence_qspi_apb_write_execute(struct cadence_spi_priv *priv, const struct spi_mem_op *op) { u32 to = op->addr.val; @@ -916,14 +916,15 @@ int cadence_qspi_apb_write_execute(struct cadence_spi_plat *plat, * mode. So, we can not use direct mode when in DTR mode for writing * data. */ - if (!plat->dtr && plat->use_dac_mode && (to + len < plat->ahbsize)) { - memcpy_toio(plat->ahbbase + to, buf, len); - if (!cadence_qspi_wait_idle(plat->regbase)) + cadence_qspi_apb_enable_linear_mode(true); + if (!priv->dtr && priv->use_dac_mode && (to + len < priv->ahbsize)) { + memcpy_toio(priv->ahbbase + to, buf, len); + if (!cadence_qspi_wait_idle(priv->regbase)) return -EIO; return 0; } - return cadence_qspi_apb_indirect_write_execute(plat, len, buf); + return cadence_qspi_apb_indirect_write_execute(priv, len, buf); } void cadence_qspi_apb_enter_xip(void *reg_base, char xip_dummy) From f4f1b65cc6b01a787b5efa61bb9be195254d0334 Mon Sep 17 00:00:00 2001 From: Ashok Reddy Soma Date: Thu, 25 Aug 2022 06:59:01 -0600 Subject: [PATCH 33/42] spi: zynqmp_gqspi: Add tap delays for Versal Add tap delays for Versal platform and re-align the tapdelays code. Signed-off-by: Ashok Reddy Soma Link: https://lore.kernel.org/r/20220825125906.11581-2-ashok.reddy.soma@amd.com Signed-off-by: Michal Simek --- drivers/spi/zynqmp_gqspi.c | 60 ++++++++++++++++++++++++-------------- 1 file changed, 38 insertions(+), 22 deletions(-) diff --git a/drivers/spi/zynqmp_gqspi.c b/drivers/spi/zynqmp_gqspi.c index c772bae3cc..958432c08d 100644 --- a/drivers/spi/zynqmp_gqspi.c +++ b/drivers/spi/zynqmp_gqspi.c @@ -22,6 +22,7 @@ #include #include #include +#include #define GQSPI_GFIFO_STRT_MODE_MASK BIT(29) #define GQSPI_CONFIG_MODE_EN_MASK (3 << 30) @@ -102,8 +103,10 @@ #define TAP_DLY_BYPASS_LQSPI_RX_VALUE 0x1 #define TAP_DLY_BYPASS_LQSPI_RX_SHIFT 2 #define GQSPI_DATA_DLY_ADJ_OFST 0x000001F8 -#define IOU_TAPDLY_BYPASS_OFST 0xFF180390 +#define IOU_TAPDLY_BYPASS_OFST !IS_ENABLED(CONFIG_ARCH_VERSAL) ? \ + 0xFF180390 : 0xF103003C #define GQSPI_LPBK_DLY_ADJ_LPBK_MASK 0x00000020 +#define GQSPI_FREQ_37_5MHZ 37500000 #define GQSPI_FREQ_40MHZ 40000000 #define GQSPI_FREQ_100MHZ 100000000 #define GQSPI_FREQ_150MHZ 150000000 @@ -297,28 +300,41 @@ void zynqmp_qspi_set_tapdelay(struct udevice *bus, u32 baudrateval) debug("%s, req_hz:%d, clk_rate:%d, baudrateval:%d\n", __func__, reqhz, clk_rate, baudrateval); - if (reqhz < GQSPI_FREQ_40MHZ) { - zynqmp_mmio_read(IOU_TAPDLY_BYPASS_OFST, &tapdlybypass); - tapdlybypass |= (TAP_DLY_BYPASS_LQSPI_RX_VALUE << - TAP_DLY_BYPASS_LQSPI_RX_SHIFT); - } else if (reqhz <= GQSPI_FREQ_100MHZ) { - zynqmp_mmio_read(IOU_TAPDLY_BYPASS_OFST, &tapdlybypass); - tapdlybypass |= (TAP_DLY_BYPASS_LQSPI_RX_VALUE << - TAP_DLY_BYPASS_LQSPI_RX_SHIFT); - lpbkdlyadj = readl(®s->lpbkdly); - lpbkdlyadj |= (GQSPI_LPBK_DLY_ADJ_LPBK_MASK); - datadlyadj = readl(®s->gqspidlyadj); - datadlyadj |= ((GQSPI_USE_DATA_DLY << GQSPI_USE_DATA_DLY_SHIFT) - | (GQSPI_DATA_DLY_ADJ_VALUE << - GQSPI_DATA_DLY_ADJ_SHIFT)); - } else if (reqhz <= GQSPI_FREQ_150MHZ) { - lpbkdlyadj = readl(®s->lpbkdly); - lpbkdlyadj |= ((GQSPI_LPBK_DLY_ADJ_LPBK_MASK) | - GQSPI_LPBK_DLY_ADJ_DLY_0); + if (!IS_ENABLED(CONFIG_ARCH_VERSAL)) { + if (reqhz <= GQSPI_FREQ_40MHZ) { + tapdlybypass = TAP_DLY_BYPASS_LQSPI_RX_VALUE << + TAP_DLY_BYPASS_LQSPI_RX_SHIFT; + } else if (reqhz <= GQSPI_FREQ_100MHZ) { + tapdlybypass = TAP_DLY_BYPASS_LQSPI_RX_VALUE << + TAP_DLY_BYPASS_LQSPI_RX_SHIFT; + lpbkdlyadj = GQSPI_LPBK_DLY_ADJ_LPBK_MASK; + datadlyadj = (GQSPI_USE_DATA_DLY << + GQSPI_USE_DATA_DLY_SHIFT) | + (GQSPI_DATA_DLY_ADJ_VALUE << + GQSPI_DATA_DLY_ADJ_SHIFT); + } else if (reqhz <= GQSPI_FREQ_150MHZ) { + lpbkdlyadj = GQSPI_LPBK_DLY_ADJ_LPBK_MASK | + GQSPI_LPBK_DLY_ADJ_DLY_0; + } + zynqmp_mmio_write(IOU_TAPDLY_BYPASS_OFST, + IOU_TAPDLY_BYPASS_MASK, tapdlybypass); + } else { + if (reqhz <= GQSPI_FREQ_37_5MHZ) { + tapdlybypass = TAP_DLY_BYPASS_LQSPI_RX_VALUE << + TAP_DLY_BYPASS_LQSPI_RX_SHIFT; + } else if (reqhz <= GQSPI_FREQ_100MHZ) { + tapdlybypass = TAP_DLY_BYPASS_LQSPI_RX_VALUE << + TAP_DLY_BYPASS_LQSPI_RX_SHIFT; + lpbkdlyadj = GQSPI_LPBK_DLY_ADJ_LPBK_MASK; + datadlyadj = GQSPI_USE_DATA_DLY << + GQSPI_USE_DATA_DLY_SHIFT; + } else if (reqhz <= GQSPI_FREQ_150MHZ) { + lpbkdlyadj = GQSPI_LPBK_DLY_ADJ_LPBK_MASK | + (GQSPI_LPBK_DLY_ADJ_DLY_1 << + GQSPI_LPBK_DLY_ADJ_DLY_1_SHIFT); + } + writel(tapdlybypass, IOU_TAPDLY_BYPASS_OFST); } - - zynqmp_mmio_write(IOU_TAPDLY_BYPASS_OFST, IOU_TAPDLY_BYPASS_MASK, - tapdlybypass); writel(lpbkdlyadj, ®s->lpbkdly); writel(datadlyadj, ®s->gqspidlyadj); } From 9e89e30d4de41a687cdff922e410b0a87d663348 Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Thu, 25 Aug 2022 06:59:02 -0600 Subject: [PATCH 34/42] arm64: versal: Define zynqmp_mmio_write() for versal GQSPI driver is using it but this function is never called for Versal because it is removed by linker. But function should be declared to avoid this build warning: drivers/spi/zynqmp_gqspi.c: In function 'zynqmp_qspi_set_tapdelay': drivers/spi/zynqmp_gqspi.c:378:3: warning: implicit declaration of function 'zynqmp_mmio_write' [-Wimplicit-function-declaration] 378 | zynqmp_mmio_write(IOU_TAPDLY_BYPASS_OFST, Signed-off-by: Michal Simek Signed-off-by: Ashok Reddy Soma Link: https://lore.kernel.org/r/20220825125906.11581-3-ashok.reddy.soma@amd.com Signed-off-by: Michal Simek --- arch/arm/mach-versal/include/mach/sys_proto.h | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/arch/arm/mach-versal/include/mach/sys_proto.h b/arch/arm/mach-versal/include/mach/sys_proto.h index 05934c28d6..8e5712e0c9 100644 --- a/arch/arm/mach-versal/include/mach/sys_proto.h +++ b/arch/arm/mach-versal/include/mach/sys_proto.h @@ -3,6 +3,8 @@ * Copyright 2016 - 2018 Xilinx, Inc. */ +#include + enum { TCM_LOCK, TCM_SPLIT, @@ -10,3 +12,9 @@ enum { void tcm_init(u8 mode); void mem_map_fill(void); + +static inline int zynqmp_mmio_write(const u32 address, const u32 mask, const u32 value) +{ + BUILD_BUG(); + return -EINVAL; +} From d91b0f4a1851f5c7c651c6f6204417035c074a0a Mon Sep 17 00:00:00 2001 From: Ashok Reddy Soma Date: Thu, 25 Aug 2022 06:59:03 -0600 Subject: [PATCH 35/42] spi: zynqmp_gqspi: Add support for IO mode Add support for io-mode transfers. This is necessary for UBIFS to work properly with spi-nor devices. The driver will work in IO mode when "has-io-mode" is passed from device tree instead of DMA. Signed-off-by: Ashok Reddy Soma Link: https://lore.kernel.org/r/20220825125906.11581-4-ashok.reddy.soma@amd.com Signed-off-by: Michal Simek --- drivers/spi/zynqmp_gqspi.c | 81 +++++++++++++++++++++++++++++++++++--- 1 file changed, 76 insertions(+), 5 deletions(-) diff --git a/drivers/spi/zynqmp_gqspi.c b/drivers/spi/zynqmp_gqspi.c index 958432c08d..78a1b48731 100644 --- a/drivers/spi/zynqmp_gqspi.c +++ b/drivers/spi/zynqmp_gqspi.c @@ -166,6 +166,7 @@ struct zynqmp_qspi_plat { struct zynqmp_qspi_dma_regs *dma_regs; u32 frequency; u32 speed_hz; + unsigned int io_mode; }; struct zynqmp_qspi_priv { @@ -174,6 +175,7 @@ struct zynqmp_qspi_priv { const void *tx_buf; void *rx_buf; unsigned int len; + unsigned int io_mode; int bytes_to_transfer; int bytes_to_receive; const struct spi_mem_op *op; @@ -190,6 +192,8 @@ static int zynqmp_qspi_of_to_plat(struct udevice *bus) plat->dma_regs = (struct zynqmp_qspi_dma_regs *) (dev_read_addr(bus) + GQSPI_DMA_REG_OFFSET); + plat->io_mode = dev_read_bool(bus, "has-io-mode"); + return 0; } @@ -209,8 +213,11 @@ static void zynqmp_qspi_init_hw(struct zynqmp_qspi_priv *priv) config_reg = readl(®s->confr); config_reg &= ~(GQSPI_GFIFO_STRT_MODE_MASK | GQSPI_CONFIG_MODE_EN_MASK); - config_reg |= GQSPI_CONFIG_DMA_MODE | GQSPI_GFIFO_WP_HOLD | - GQSPI_DFLT_BAUD_RATE_DIV | GQSPI_GFIFO_STRT_MODE_MASK; + config_reg |= GQSPI_GFIFO_WP_HOLD | GQSPI_DFLT_BAUD_RATE_DIV; + config_reg |= GQSPI_GFIFO_STRT_MODE_MASK; + if (!priv->io_mode) + config_reg |= GQSPI_CONFIG_DMA_MODE; + writel(config_reg, ®s->confr); writel(GQSPI_ENABLE_ENABLE_MASK, ®s->enbr); @@ -388,6 +395,7 @@ static int zynqmp_qspi_probe(struct udevice *bus) priv->regs = plat->regs; priv->dma_regs = plat->dma_regs; + priv->io_mode = plat->io_mode; ret = clk_get_by_index(bus, 0, &clk); if (ret < 0) { @@ -592,6 +600,66 @@ static int zynqmp_qspi_genfifo_fill_tx(struct zynqmp_qspi_priv *priv) return ret; } +static int zynqmp_qspi_start_io(struct zynqmp_qspi_priv *priv, + u32 gen_fifo_cmd, u32 *buf) +{ + u32 len; + u32 actuallen = priv->len; + u32 config_reg, ier, isr; + u32 timeout = GQSPI_TIMEOUT; + struct zynqmp_qspi_regs *regs = priv->regs; + u32 last_bits; + u32 *traverse = buf; + + while (priv->len) { + len = zynqmp_qspi_calc_exp(priv, &gen_fifo_cmd); + /* If exponent bit is set, reset immediate to be 2^len */ + if (gen_fifo_cmd & GQSPI_GFIFO_EXP_MASK) + priv->bytes_to_receive = (1 << len); + else + priv->bytes_to_receive = len; + zynqmp_qspi_fill_gen_fifo(priv, gen_fifo_cmd); + debug("GFIFO_CMD_RX:0x%x\n", gen_fifo_cmd); + /* Manual start */ + config_reg = readl(®s->confr); + config_reg |= GQSPI_STRT_GEN_FIFO; + writel(config_reg, ®s->confr); + /* Enable RX interrupts for IO mode */ + ier = readl(®s->ier); + ier |= GQSPI_IXR_ALL_MASK; + writel(ier, ®s->ier); + while (priv->bytes_to_receive && timeout) { + isr = readl(®s->isr); + if (isr & GQSPI_IXR_RXNEMTY_MASK) { + if (priv->bytes_to_receive >= 4) { + *traverse = readl(®s->drxr); + traverse++; + priv->bytes_to_receive -= 4; + } else { + last_bits = readl(®s->drxr); + memcpy(traverse, &last_bits, + priv->bytes_to_receive); + priv->bytes_to_receive = 0; + } + timeout = GQSPI_TIMEOUT; + } else { + udelay(1); + timeout--; + } + } + + debug("buf:0x%lx, rxbuf:0x%lx, *buf:0x%x len: 0x%x\n", + (unsigned long)buf, (unsigned long)priv->rx_buf, + *buf, actuallen); + if (!timeout) { + printf("IO timeout: %d\n", readl(®s->isr)); + return -1; + } + } + + return 0; +} + static int zynqmp_qspi_start_dma(struct zynqmp_qspi_priv *priv, u32 gen_fifo_cmd, u32 *buf) { @@ -649,10 +717,13 @@ static int zynqmp_qspi_genfifo_fill_rx(struct zynqmp_qspi_priv *priv) * Check if receive buffer is aligned to 4 byte and length * is multiples of four byte as we are using dma to receive. */ - if (!((unsigned long)priv->rx_buf & (GQSPI_DMA_ALIGN - 1)) && - !(actuallen % GQSPI_DMA_ALIGN)) { + if ((!((unsigned long)priv->rx_buf & (GQSPI_DMA_ALIGN - 1)) && + !(actuallen % GQSPI_DMA_ALIGN)) || priv->io_mode) { buf = (u32 *)priv->rx_buf; - return zynqmp_qspi_start_dma(priv, gen_fifo_cmd, buf); + if (priv->io_mode) + return zynqmp_qspi_start_io(priv, gen_fifo_cmd, buf); + else + return zynqmp_qspi_start_dma(priv, gen_fifo_cmd, buf); } ALLOC_CACHE_ALIGN_BUFFER(u8, tmp, roundup(priv->len, From a3d4bfb427fb6e8c9396a744879796231deabc3d Mon Sep 17 00:00:00 2001 From: Ashok Reddy Soma Date: Thu, 25 Aug 2022 06:59:04 -0600 Subject: [PATCH 36/42] spi: zynqmp_gqspi: Fix issue of reading more than 32bits length As the flash sizes are increasing day by day, QSPI can have devices of size > 512MB. In qspi driver we are trying to read all the data at once using DMA. The DMA descriptor destination size is only 29bits long. QSPIDMA_DST_SIZE 0xFF0F0804 BITS: 1:0 Reserved to keep word alignment BITS: 28:2 Number of 4-byte words the DMA will transfer BITS: 31:29 Reserved: Returns 0 when read, writes ignored So we can only transfer data of 0x1FFFFFF0(512MB minus 4bytes) bytes. Anything above will overflow this register and will ignore higher bits above 29 bits. Change the DMA functionality if the requested size is greater than or equal to 512MB to read 256MB chunks. Signed-off-by: Ashok Reddy Soma Link: https://lore.kernel.org/r/20220825125906.11581-5-ashok.reddy.soma@amd.com Signed-off-by: Michal Simek --- drivers/spi/zynqmp_gqspi.c | 68 +++++++++++++++++++++++--------------- 1 file changed, 42 insertions(+), 26 deletions(-) diff --git a/drivers/spi/zynqmp_gqspi.c b/drivers/spi/zynqmp_gqspi.c index 78a1b48731..d5ccb48fde 100644 --- a/drivers/spi/zynqmp_gqspi.c +++ b/drivers/spi/zynqmp_gqspi.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #define GQSPI_GFIFO_STRT_MODE_MASK BIT(29) @@ -666,39 +667,54 @@ static int zynqmp_qspi_start_dma(struct zynqmp_qspi_priv *priv, u32 addr; u32 size; u32 actuallen = priv->len; + u32 totallen = priv->len; int ret = 0; struct zynqmp_qspi_dma_regs *dma_regs = priv->dma_regs; - writel((unsigned long)buf, &dma_regs->dmadst); - writel(roundup(priv->len, GQSPI_DMA_ALIGN), &dma_regs->dmasize); - writel(GQSPI_DMA_DST_I_STS_MASK, &dma_regs->dmaier); - addr = (unsigned long)buf; - size = roundup(priv->len, GQSPI_DMA_ALIGN); - flush_dcache_range(addr, addr + size); + while (totallen) { + if (totallen >= SZ_512M) + priv->len = SZ_256M; + else + priv->len = totallen; - while (priv->len) { - zynqmp_qspi_calc_exp(priv, &gen_fifo_cmd); - zynqmp_qspi_fill_gen_fifo(priv, gen_fifo_cmd); + totallen -= priv->len; /* Save remaining bytes length to read */ + actuallen = priv->len; /* Actual number of bytes reading */ - debug("GFIFO_CMD_RX:0x%x\n", gen_fifo_cmd); + writel((unsigned long)buf, &dma_regs->dmadst); + writel(roundup(priv->len, GQSPI_DMA_ALIGN), &dma_regs->dmasize); + writel(GQSPI_DMA_DST_I_STS_MASK, &dma_regs->dmaier); + addr = (unsigned long)buf; + size = roundup(priv->len, GQSPI_DMA_ALIGN); + flush_dcache_range(addr, addr + size); + + while (priv->len) { + zynqmp_qspi_calc_exp(priv, &gen_fifo_cmd); + zynqmp_qspi_fill_gen_fifo(priv, gen_fifo_cmd); + + debug("GFIFO_CMD_RX:0x%x\n", gen_fifo_cmd); + } + + ret = wait_for_bit_le32(&dma_regs->dmaisr, + GQSPI_DMA_DST_I_STS_DONE, 1, + GQSPI_TIMEOUT, 1); + if (ret) { + printf("DMA Timeout:0x%x\n", readl(&dma_regs->dmaisr)); + return -ETIMEDOUT; + } + + writel(GQSPI_DMA_DST_I_STS_DONE, &dma_regs->dmaisr); + + debug("buf:0x%lx, rxbuf:0x%lx, *buf:0x%x len: 0x%x\n", + (unsigned long)buf, (unsigned long)priv->rx_buf, *buf, + actuallen); + + if (buf != priv->rx_buf) + memcpy(priv->rx_buf, buf, actuallen); + + buf = (u32 *)((u8 *)buf + actuallen); + priv->rx_buf = (u8 *)priv->rx_buf + actuallen; } - ret = wait_for_bit_le32(&dma_regs->dmaisr, GQSPI_DMA_DST_I_STS_DONE, - 1, GQSPI_TIMEOUT, 1); - if (ret) { - printf("DMA Timeout:0x%x\n", readl(&dma_regs->dmaisr)); - return -ETIMEDOUT; - } - - writel(GQSPI_DMA_DST_I_STS_DONE, &dma_regs->dmaisr); - - debug("buf:0x%lx, rxbuf:0x%lx, *buf:0x%x len: 0x%x\n", - (unsigned long)buf, (unsigned long)priv->rx_buf, *buf, - actuallen); - - if (buf != priv->rx_buf) - memcpy(priv->rx_buf, buf, actuallen); - return 0; } From afe03866a0f0a95ee6554b404f218b4b69b36f0e Mon Sep 17 00:00:00 2001 From: Ashok Reddy Soma Date: Thu, 25 Aug 2022 06:59:05 -0600 Subject: [PATCH 37/42] spi: zynqmp_qspi: Code alignment Few lines are extented to next line though they can fit in 80 character limit, align them to single line. No functional change. Signed-off-by: Ashok Reddy Soma Link: https://lore.kernel.org/r/20220825125906.11581-6-ashok.reddy.soma@amd.com Signed-off-by: Michal Simek --- drivers/spi/zynqmp_gqspi.c | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/drivers/spi/zynqmp_gqspi.c b/drivers/spi/zynqmp_gqspi.c index d5ccb48fde..4e718c545c 100644 --- a/drivers/spi/zynqmp_gqspi.c +++ b/drivers/spi/zynqmp_gqspi.c @@ -434,8 +434,7 @@ static int zynqmp_qspi_set_mode(struct udevice *bus, uint mode) debug("%s\n", __func__); /* Set the SPI Clock phase and polarities */ confr = readl(®s->confr); - confr &= ~(GQSPI_CONFIG_CPHA_MASK | - GQSPI_CONFIG_CPOL_MASK); + confr &= ~(GQSPI_CONFIG_CPHA_MASK | GQSPI_CONFIG_CPOL_MASK); if (mode & SPI_CPHA) confr |= GQSPI_CONFIG_CPHA_MASK; @@ -579,8 +578,7 @@ static int zynqmp_qspi_genfifo_fill_tx(struct zynqmp_qspi_priv *priv) gen_fifo_cmd = zynqmp_qspi_bus_select(priv); gen_fifo_cmd |= zynqmp_qspi_genfifo_mode(priv->op->data.buswidth); - gen_fifo_cmd |= GQSPI_GFIFO_TX | - GQSPI_GFIFO_DATA_XFR_MASK; + gen_fifo_cmd |= GQSPI_GFIFO_TX | GQSPI_GFIFO_DATA_XFR_MASK; while (priv->len) { len = zynqmp_qspi_calc_exp(priv, &gen_fifo_cmd); @@ -589,11 +587,9 @@ static int zynqmp_qspi_genfifo_fill_tx(struct zynqmp_qspi_priv *priv) debug("GFIFO_CMD_TX:0x%x\n", gen_fifo_cmd); if (gen_fifo_cmd & GQSPI_GFIFO_EXP_MASK) - ret = zynqmp_qspi_fill_tx_fifo(priv, - 1 << len); + ret = zynqmp_qspi_fill_tx_fifo(priv, 1 << len); else - ret = zynqmp_qspi_fill_tx_fifo(priv, - len); + ret = zynqmp_qspi_fill_tx_fifo(priv, len); if (ret) return ret; @@ -726,8 +722,7 @@ static int zynqmp_qspi_genfifo_fill_rx(struct zynqmp_qspi_priv *priv) gen_fifo_cmd = zynqmp_qspi_bus_select(priv); gen_fifo_cmd |= zynqmp_qspi_genfifo_mode(priv->op->data.buswidth); - gen_fifo_cmd |= GQSPI_GFIFO_RX | - GQSPI_GFIFO_DATA_XFR_MASK; + gen_fifo_cmd |= GQSPI_GFIFO_RX | GQSPI_GFIFO_DATA_XFR_MASK; /* * Check if receive buffer is aligned to 4 byte and length @@ -742,8 +737,7 @@ static int zynqmp_qspi_genfifo_fill_rx(struct zynqmp_qspi_priv *priv) return zynqmp_qspi_start_dma(priv, gen_fifo_cmd, buf); } - ALLOC_CACHE_ALIGN_BUFFER(u8, tmp, roundup(priv->len, - GQSPI_DMA_ALIGN)); + ALLOC_CACHE_ALIGN_BUFFER(u8, tmp, roundup(priv->len, GQSPI_DMA_ALIGN)); buf = (u32 *)tmp; return zynqmp_qspi_start_dma(priv, gen_fifo_cmd, buf); } From cac07a4d7c66d4b18acb70c27ebb9a356bf8a6f4 Mon Sep 17 00:00:00 2001 From: Ashok Reddy Soma Date: Thu, 25 Aug 2022 06:59:06 -0600 Subject: [PATCH 38/42] arm64: versal: Enable zynqmp_gqspi driver Versal supports gqspi ip, so enable zynqmp_gqspi driver for Versal platforms. Signed-off-by: Ashok Reddy Soma Link: https://lore.kernel.org/r/20220825125906.11581-7-ashok.reddy.soma@amd.com Signed-off-by: Michal Simek --- configs/xilinx_versal_virt_defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/configs/xilinx_versal_virt_defconfig b/configs/xilinx_versal_virt_defconfig index c3fa913b20..6afd06798d 100644 --- a/configs/xilinx_versal_virt_defconfig +++ b/configs/xilinx_versal_virt_defconfig @@ -121,6 +121,7 @@ CONFIG_HAS_CQSPI_REF_CLK=y CONFIG_CQSPI_REF_CLK=200000000 CONFIG_CADENCE_OSPI_VERSAL=y CONFIG_ZYNQ_SPI=y +CONFIG_ZYNQMP_GQSPI=y CONFIG_USB=y CONFIG_DM_USB_GADGET=y CONFIG_USB_XHCI_HCD=y From 41634fd24b6488889005421ce74394693077b010 Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Tue, 6 Sep 2022 12:35:42 +0200 Subject: [PATCH 39/42] ARM: zynq: Align qspi node name with Linux kernel Nodes should follow generic rules where compatible and reg properties should be listed on the top of node. That's why sync it up. Signed-off-by: Michal Simek Link: https://lore.kernel.org/r/922dca6227cb0aa4f79e6d3595c5f280ba020684.1662460540.git.michal.simek@amd.com --- arch/arm/dts/zynq-7000.dtsi | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/arch/arm/dts/zynq-7000.dtsi b/arch/arm/dts/zynq-7000.dtsi index b4aa09d149..11fa0ef2bf 100644 --- a/arch/arm/dts/zynq-7000.dtsi +++ b/arch/arm/dts/zynq-7000.dtsi @@ -235,13 +235,13 @@ }; qspi: spi@e000d000 { - clock-names = "ref_clk", "pclk"; - clocks = <&clkc 10>, <&clkc 43>; compatible = "xlnx,zynq-qspi-1.0"; - status = "disabled"; + reg = <0xe000d000 0x1000>; interrupt-parent = <&intc>; interrupts = <0 19 4>; - reg = <0xe000d000 0x1000>; + clocks = <&clkc 10>, <&clkc 43>; + clock-names = "ref_clk", "pclk"; + status = "disabled"; #address-cells = <1>; #size-cells = <0>; }; @@ -378,9 +378,9 @@ devcfg: devcfg@f8007000 { compatible = "xlnx,zynq-devcfg-1.0"; + reg = <0xf8007000 0x100>; interrupt-parent = <&intc>; interrupts = <0 8 4>; - reg = <0xf8007000 0x100>; clocks = <&clkc 12>, <&clkc 15>, <&clkc 16>, <&clkc 17>, <&clkc 18>; clock-names = "ref_clk", "fclk0", "fclk1", "fclk2", "fclk3"; syscon = <&slcr>; From 5c341965dd9907203b8ab0b9717a95b2b0f831cd Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Tue, 6 Sep 2022 12:38:34 +0200 Subject: [PATCH 40/42] ARM: zynq: DT: List OCM memory Description OCM with mmio-sram driver. In 99% use cases OCM is mapped high that's why it is placed on fixed location. Signed-off-by: Michal Simek Link: https://lore.kernel.org/r/a951dbe885640197efe3e91bb9fa5caedb54b387.1662460712.git.michal.simek@amd.com --- arch/arm/dts/zynq-7000.dtsi | 11 +++++++++++ arch/arm/dts/zynq-zc702.dts | 13 ------------- 2 files changed, 11 insertions(+), 13 deletions(-) diff --git a/arch/arm/dts/zynq-7000.dtsi b/arch/arm/dts/zynq-7000.dtsi index 11fa0ef2bf..edc147d63f 100644 --- a/arch/arm/dts/zynq-7000.dtsi +++ b/arch/arm/dts/zynq-7000.dtsi @@ -192,6 +192,17 @@ reg = <0xf8006000 0x1000>; }; + ocm: sram@fffc0000 { + compatible = "mmio-sram"; + reg = <0xfffc0000 0x10000>; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0 0xfffc0000 0x10000>; + ocm-sram@0 { + reg = <0x0 0x10000>; + }; + }; + uart0: serial@e0000000 { compatible = "xlnx,xuartps", "cdns,uart-r1p8"; status = "disabled"; diff --git a/arch/arm/dts/zynq-zc702.dts b/arch/arm/dts/zynq-zc702.dts index f2e05a55b9..1bd4f8c9f6 100644 --- a/arch/arm/dts/zynq-zc702.dts +++ b/arch/arm/dts/zynq-zc702.dts @@ -64,19 +64,6 @@ }; }; -&amba { - ocm: sram@fffc0000 { - compatible = "mmio-sram"; - reg = <0xfffc0000 0x10000>; - #address-cells = <1>; - #size-cells = <1>; - ranges = <0 0xfffc0000 0x10000>; - ocm-sram@0 { - reg = <0x0 0x10000>; - }; - }; -}; - &can0 { status = "okay"; pinctrl-names = "default"; From 4e168260281518abbb417dc08ec91d96cca715a1 Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Tue, 6 Sep 2022 12:39:11 +0200 Subject: [PATCH 41/42] xilinx: Fix mdio bus description for vck190-sc Current behavior is that eth_phy_get_mdio_bus Net: FEC: can't find phy-handle ZYNQ GEM: ff0b0000, mdio bus ff0b0000, phyaddr 0, interface sgmii eth0: ethernet@ff0b0000 Net: ZYNQ GEM: ff0b0000, mdio bus ff0b0000, phyaddr 0, interface sgmii eth0: ethernet@ff0b0000 Signed-off-by: Michal Simek Link: https://lore.kernel.org/r/5b7da5808136b3f579c0cf7a3431b56c758655e9.1662460749.git.michal.simek@amd.com --- arch/arm/dts/zynqmp-e-a2197-00-revA.dts | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/arch/arm/dts/zynqmp-e-a2197-00-revA.dts b/arch/arm/dts/zynqmp-e-a2197-00-revA.dts index 4940825b00..3fa18f560c 100644 --- a/arch/arm/dts/zynqmp-e-a2197-00-revA.dts +++ b/arch/arm/dts/zynqmp-e-a2197-00-revA.dts @@ -155,8 +155,12 @@ phy-handle = <&phy0>; phy-mode = "sgmii"; is-internal-pcspma; - phy0: ethernet-phy@0 { /* u131 M88E1512 */ - reg = <0>; + mdio: mdio { + #address-cells = <1>; + #size-cells = <0>; + phy0: ethernet-phy@0 { /* u131 M88E1512 */ + reg = <0>; + }; }; }; From 39d3c3cfaa4f5099a2d687de4530c9ca4bee256d Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Tue, 6 Sep 2022 12:40:41 +0200 Subject: [PATCH 42/42] xilinx: common: Add support for SOC detection Code supports board detection based on information available in EEPROM in legacy or FRU format. But this is not enough for emulation and simulation systems which are lacking these identification EEPROMs. But SOC itself has normally registers for SOC identification. Based on them it is possible to compose detected name. That's why prepare infrastructure in common location for SOC platform detection which is called before board platform detection. SOC platform detection shouldn't detect real silicon and should fallback to current existing mechanism to identify boards based on EEPROMs. Signed-off-by: Michal Simek Link: https://lore.kernel.org/r/329a8da338927b082e26a958bf69bb18af072420.1662460837.git.michal.simek@amd.com --- board/xilinx/common/board.c | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/board/xilinx/common/board.c b/board/xilinx/common/board.c index 5e36386361..e1f7104960 100644 --- a/board/xilinx/common/board.c +++ b/board/xilinx/common/board.c @@ -585,8 +585,33 @@ bool __maybe_unused __weak board_detection(void) return false; } +bool __maybe_unused __weak soc_detection(void) +{ + return false; +} + +char * __maybe_unused __weak soc_name_decode(void) +{ + return NULL; +} + int embedded_dtb_select(void) { + if (soc_detection()) { + char *soc_local_name; + + soc_local_name = soc_name_decode(); + if (soc_local_name) { + board_name = soc_local_name; + printf("Detected SOC name: %s\n", board_name); + + /* Time to change DTB on fly */ + /* Both ways should work here */ + /* fdtdec_resetup(&rescan); */ + return fdtdec_setup(); + } + } + if (board_detection()) { char *board_local_name;