diff options
| author | Tom Rini <[email protected]> | 2025-12-19 10:30:53 -0600 |
|---|---|---|
| committer | Tom Rini <[email protected]> | 2025-12-19 10:30:53 -0600 |
| commit | 2aeaa3c4f53b11b97e2797eb3a0a7b603f60dc72 (patch) | |
| tree | f815ca39666d1bb8b5be752afcf1f400695ed93b /drivers | |
| parent | adbbf5982d26801224b10cd847dc468f8b5e4095 (diff) | |
| parent | 0b880fc95dbaed88dd55060730857b8f52765c57 (diff) | |
Merge tag 'xilinx-for-v2026.04-rc1' of https://source.denx.de/u-boot/custodians/u-boot-microblaze into next
AMD/Xilinx/FPGA changes for v2026.04-rc1
xilinx:
- Sync ESRT with detected GUID
- DT cleanups
- Add logic for FRU information multiple times
- Enable more drivers pca9541, usb5744
- Enable more commands
- Cleanup firmware DT bindings
firmware:
- Add enhancement SMC format support
clk/versal:
- Various cleanups
- Add support for Versal Gen 2
i2c:
- cdns: Add timeout for RXDV status bit polling
spi:
- cadence: Remove cdns,is-dma DT property
- cadence: Remove duplicated return
- cadence_versal: Update flash reset delay
memtop:
- Update max memory reserved spaces to 64
Versal Gen 2:
- Aligned addresses with default memory map
- Add support for reading multiboot value
MB-V:
- Make SPL smaller
- Add support for SPI
- Move SPL to run out of BRAM
ZynqMP:
- Change default load address for BL32
Diffstat (limited to 'drivers')
| -rw-r--r-- | drivers/clk/Kconfig | 2 | ||||
| -rw-r--r-- | drivers/clk/clk_versal.c | 49 | ||||
| -rw-r--r-- | drivers/firmware/firmware-zynqmp.c | 36 | ||||
| -rw-r--r-- | drivers/i2c/i2c-cdns.c | 11 | ||||
| -rw-r--r-- | drivers/spi/cadence_ospi_versal.c | 7 | ||||
| -rw-r--r-- | drivers/spi/cadence_qspi.c | 23 | ||||
| -rw-r--r-- | drivers/spi/cadence_qspi.h | 2 |
7 files changed, 104 insertions, 26 deletions
diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig index b884a02bdeb..85cc472b4cb 100644 --- a/drivers/clk/Kconfig +++ b/drivers/clk/Kconfig @@ -224,7 +224,7 @@ config CLK_VERSACLOCK config CLK_VERSAL bool "Enable clock driver support for Versal" - depends on (ARCH_VERSAL || ARCH_VERSAL_NET) + depends on (ARCH_VERSAL || ARCH_VERSAL_NET || ARCH_VERSAL2) depends on ZYNQMP_FIRMWARE help This clock driver adds support for clock realted settings for diff --git a/drivers/clk/clk_versal.c b/drivers/clk/clk_versal.c index c62a747036d..78a2410ca21 100644 --- a/drivers/clk/clk_versal.c +++ b/drivers/clk/clk_versal.c @@ -106,8 +106,8 @@ struct versal_clk_priv { struct versal_clock *clk; }; -static ulong pl_alt_ref_clk __section(".data"); -static ulong ref_clk __section(".data"); +static ulong __data pl_alt_ref_clk; +static ulong __data ref_clk; struct versal_pm_query_data { u32 qid; @@ -116,8 +116,8 @@ struct versal_pm_query_data { u32 arg3; }; -static struct versal_clock *clock __section(".data"); -static unsigned int clock_max_idx __section(".data"); +static struct versal_clock __data *clock; +static unsigned int __data clock_max_idx; #define PM_QUERY_DATA 35 @@ -136,6 +136,25 @@ static int versal_pm_query_legacy(struct versal_pm_query_data qdata, return qdata.qid == PM_QID_CLOCK_GET_NAME ? 0 : ret; } +static int versal_pm_query_enhanced(struct versal_pm_query_data qdata, + u32 *ret_payload) +{ + int ret; + + ret = smc_call_handler(PM_QUERY_DATA, qdata.qid, qdata.arg1, qdata.arg2, + qdata.arg3, 0, 0, ret_payload); + + if (qdata.qid == PM_QID_CLOCK_GET_NAME) { + ret_payload[0] = ret_payload[1]; + ret_payload[1] = ret_payload[2]; + ret_payload[2] = ret_payload[3]; + ret_payload[3] = ret_payload[4]; + ret_payload[4] = 0; + } + + return ret; +} + static inline int versal_is_valid_clock(u32 clk_id) { if (clk_id >= clock_max_idx) @@ -712,11 +731,12 @@ static int versal_clk_probe(struct udevice *dev) static ulong versal_clk_get_rate(struct clk *clk) { struct versal_clk_priv *priv = dev_get_priv(clk->dev); - u32 id = clk->id; + u32 id = clk_get_id(clk); u32 clk_id; u64 clk_rate = 0; - debug("%s\n", __func__); + if (id >= clock_max_idx) + return -ENODEV; clk_id = priv->clk[id].clk_id; @@ -728,13 +748,14 @@ static ulong versal_clk_get_rate(struct clk *clk) static ulong versal_clk_set_rate(struct clk *clk, ulong rate) { struct versal_clk_priv *priv = dev_get_priv(clk->dev); - u32 id = clk->id; + u32 id = clk_get_id(clk); u32 clk_id; u64 clk_rate = 0; u32 div; int ret; - debug("%s\n", __func__); + if (id >= clock_max_idx) + return -ENODEV; clk_id = priv->clk[id].clk_id; @@ -758,7 +779,7 @@ static ulong versal_clk_set_rate(struct clk *clk, ulong rate) } while (((clk_id >> NODE_SUBCLASS_SHIFT) & NODE_CLASS_MASK) != NODE_SUBCLASS_CLOCK_REF); - printf("Clock didn't has Divisors:0x%x\n", priv->clk[id].clk_id); + printf("Clock has no divider: 0x%x\n", clk_id); return clk_rate; } @@ -766,14 +787,17 @@ static ulong versal_clk_set_rate(struct clk *clk, ulong rate) static int versal_clk_enable(struct clk *clk) { struct versal_clk_priv *priv = dev_get_priv(clk->dev); + u32 id = clk_get_id(clk); u32 clk_id; - clk_id = priv->clk[clk->id].clk_id; + if (id >= clock_max_idx) + return -ENODEV; + + clk_id = priv->clk[id].clk_id; - if (versal_clock_gate(clk_id)) { + if (versal_clock_gate(clk_id)) return xilinx_pm_request(PM_CLOCK_ENABLE, clk_id, 0, 0, 0, 0, 0, NULL); - } return 0; } @@ -789,6 +813,7 @@ static struct clk_ops versal_clk_ops = { static const struct udevice_id versal_clk_ids[] = { { .compatible = "xlnx,versal-clk", .data = (ulong)versal_pm_query_legacy }, + { .compatible = "xlnx,versal2-clk", .data = (ulong)versal_pm_query_enhanced }, { } }; diff --git a/drivers/firmware/firmware-zynqmp.c b/drivers/firmware/firmware-zynqmp.c index 3742467caee..f8a9945c1da 100644 --- a/drivers/firmware/firmware-zynqmp.c +++ b/drivers/firmware/firmware-zynqmp.c @@ -16,6 +16,7 @@ #include <zynqmp_firmware.h> #include <asm/cache.h> #include <asm/ptrace.h> +#include <linux/bitfield.h> #if defined(CONFIG_ZYNQMP_IPI) #include <mailbox.h> @@ -247,6 +248,7 @@ u32 zynqmp_pm_get_bootmode_reg(void) return ret_payload[1]; } +#if defined(CONFIG_ARCH_VERSAL) || defined(CONFIG_ARCH_VERSAL2) u32 zynqmp_pm_get_pmc_multi_boot_reg(void) { int ret; @@ -270,6 +272,7 @@ u32 zynqmp_pm_get_pmc_multi_boot_reg(void) return ret_payload[1]; } +#endif int zynqmp_pm_feature(const u32 api_id) { @@ -451,6 +454,38 @@ static int smc_call_legacy(u32 api_id, u32 arg0, u32 arg1, u32 arg2, return (ret_payload) ? ret_payload[0] : 0; } +static int smc_call_enhanced(u32 api_id, u32 arg0, u32 arg1, u32 arg2, + u32 arg3, u32 arg4, u32 arg5, u32 *ret_payload) +{ + struct pt_regs regs; + u32 module_id = FIELD_GET(PLM_MODULE_ID_MASK, api_id); + + if (module_id == 0) + module_id = PM_MODULE_ID; + + regs.regs[0] = PM_SIP_SVC | PASS_THROUGH_FW_CMD_ID; + regs.regs[1] = ((u64)arg0 << 32U) | + FIELD_PREP(PLM_MODULE_ID_MASK, module_id) | + (api_id & API_ID_MASK); + regs.regs[2] = arg1 | ((u64)arg2 << 32); + regs.regs[3] = arg3 | ((u64)arg4 << 32); + regs.regs[4] = arg5; + + smc_call(®s); + + if (ret_payload) { + ret_payload[0] = regs.regs[0]; + ret_payload[1] = upper_32_bits(regs.regs[0]); + ret_payload[2] = (u32)regs.regs[1]; + ret_payload[3] = upper_32_bits(regs.regs[1]); + ret_payload[4] = (u32)regs.regs[2]; + ret_payload[5] = upper_32_bits((u32)regs.regs[2]); + ret_payload[6] = (u32)regs.regs[3]; + } + + return regs.regs[0]; +} + int __maybe_unused xilinx_pm_request(u32 api_id, u32 arg0, u32 arg1, u32 arg2, u32 arg3, u32 arg4, u32 arg5, u32 *ret_payload) { @@ -494,6 +529,7 @@ static const struct udevice_id zynqmp_firmware_ids[] = { { .compatible = "xlnx,zynqmp-firmware", .data = (ulong)smc_call_legacy }, { .compatible = "xlnx,versal-firmware", .data = (ulong)smc_call_legacy}, { .compatible = "xlnx,versal-net-firmware", .data = (ulong)smc_call_legacy }, + { .compatible = "xlnx,versal2-firmware", .data = (ulong)smc_call_enhanced}, { } }; diff --git a/drivers/i2c/i2c-cdns.c b/drivers/i2c/i2c-cdns.c index 3f7cf8533ec..4e9d4e44899 100644 --- a/drivers/i2c/i2c-cdns.c +++ b/drivers/i2c/i2c-cdns.c @@ -85,6 +85,8 @@ struct cdns_i2c_regs { #define CDNS_I2C_ARB_LOST_MAX_RETRIES 10 +#define CDNS_I2C_RXDV_TIMEOUT_MS 1000 + #ifdef DEBUG static void cdns_i2c_debug_status(struct cdns_i2c_regs *cdns_i2c) { @@ -349,6 +351,11 @@ static int cdns_i2c_read_data(struct i2c_cdns_bus *i2c_bus, u32 addr, u8 *data, hold_quirk = (i2c_bus->quirks & CDNS_I2C_BROKEN_HOLD_BIT) && updatetx; while (recv_count && !is_arbitration_lost(regs)) { + int err = wait_for_bit_le32(®s->status, CDNS_I2C_STATUS_RXDV, + true, CDNS_I2C_RXDV_TIMEOUT_MS, false); + if (err) + return err; + while (readl(®s->status) & CDNS_I2C_STATUS_RXDV) { if (recv_count < i2c_bus->fifo_depth && !i2c_bus->hold_flag) { @@ -452,6 +459,10 @@ static int cdns_i2c_xfer(struct udevice *dev, struct i2c_msg *msg, ret = cdns_i2c_write_data(i2c_bus, msg->addr, msg->buf, msg->len); } + + if (ret == -ETIMEDOUT) + return ret; + if (ret == -EAGAIN) { msg = message; nmsgs = num_msgs; diff --git a/drivers/spi/cadence_ospi_versal.c b/drivers/spi/cadence_ospi_versal.c index 0efbbf56a5e..a00642d09d3 100644 --- a/drivers/spi/cadence_ospi_versal.c +++ b/drivers/spi/cadence_ospi_versal.c @@ -15,7 +15,6 @@ #include <zynqmp_firmware.h> #include <asm/arch/hardware.h> #include "cadence_qspi.h" -#include <dt-bindings/power/xlnx-versal-power.h> int cadence_qspi_apb_dma_read(struct cadence_spi_priv *priv, const struct spi_mem_op *op) @@ -178,15 +177,15 @@ int cadence_qspi_flash_reset(struct udevice *dev) /* Disable Tri-state */ writel((readl(BANK0_TRI) & ~BIT(FLASH_RESET_GPIO)), BANK0_TRI); - udelay(1); + udelay(5); /* Set value 0 to pin */ writel((readl(BANK0_OUTPUT) & ~BIT(FLASH_RESET_GPIO)), BANK0_OUTPUT); - udelay(10); + udelay(150); /* Set value 1 to pin */ writel((readl(BANK0_OUTPUT) | BIT(FLASH_RESET_GPIO)), BANK0_OUTPUT); - udelay(10); + udelay(1200); return 0; } diff --git a/drivers/spi/cadence_qspi.c b/drivers/spi/cadence_qspi.c index 9b45cab9c04..d1404e13810 100644 --- a/drivers/spi/cadence_qspi.c +++ b/drivers/spi/cadence_qspi.c @@ -20,7 +20,6 @@ #include <linux/time.h> #include <zynqmp_firmware.h> #include "cadence_qspi.h" -#include <dt-bindings/power/xlnx-versal-power.h> #define CQSPI_STIG_READ 0 #define CQSPI_STIG_WRITE 1 @@ -29,6 +28,7 @@ /* Quirks */ #define CQSPI_DISABLE_STIG_MODE BIT(0) +#define CQSPI_DMA_MODE BIT(1) __weak int cadence_qspi_apb_dma_read(struct cadence_spi_priv *priv, const struct spi_mem_op *op) @@ -210,7 +210,6 @@ static int cadence_spi_probe(struct udevice *bus) 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; @@ -227,6 +226,11 @@ static int cadence_spi_probe(struct udevice *bus) priv->tslch_ns = plat->tslch_ns; priv->quirks = plat->quirks; + if (priv->quirks & CQSPI_DMA_MODE) { + priv->is_dma = true; + debug("Cadence QSPI: DMA mode enabled\n"); + } + if (IS_ENABLED(CONFIG_ZYNQMP_FIRMWARE)) xilinx_pm_request(PM_REQUEST_NODE, PM_DEV_OSPI, ZYNQMP_PM_CAPABILITY_ACCESS, ZYNQMP_PM_MAX_QOS, @@ -265,8 +269,6 @@ static int cadence_spi_probe(struct udevice *bus) /* Reset ospi flash device */ return cadence_qspi_flash_reset(bus); - - return 0; } static int cadence_spi_remove(struct udevice *dev) @@ -412,8 +414,6 @@ static int cadence_spi_of_to_plat(struct udevice *bus) if (plat->ahbsize >= SZ_8M) priv->use_dac_mode = true; - plat->is_dma = dev_read_bool(bus, "cdns,is-dma"); - /* All other parameters are embedded in the child node */ subnode = cadence_qspi_get_subnode(bus); if (!ofnode_valid(subnode)) { @@ -473,6 +473,10 @@ static const struct cqspi_driver_platdata cdns_qspi = { .quirks = CQSPI_DISABLE_STIG_MODE, }; +static const struct cqspi_driver_platdata cdns_xilinx_qspi = { + .quirks = CQSPI_DMA_MODE, +}; + static const struct udevice_id cadence_spi_ids[] = { { .compatible = "cdns,qspi-nor", @@ -482,7 +486,12 @@ static const struct udevice_id cadence_spi_ids[] = { .compatible = "ti,am654-ospi" }, { - .compatible = "amd,versal2-ospi" + .compatible = "amd,versal2-ospi", + .data = (ulong)&cdns_xilinx_qspi, + }, + { + .compatible = "xlnx,versal-ospi-1.0", + .data = (ulong)&cdns_xilinx_qspi, }, { } }; diff --git a/drivers/spi/cadence_qspi.h b/drivers/spi/cadence_qspi.h index 879e7f8dbfb..1e9081c2d17 100644 --- a/drivers/spi/cadence_qspi.h +++ b/drivers/spi/cadence_qspi.h @@ -223,8 +223,6 @@ struct cadence_spi_plat { u32 tchsh_ns; u32 tslch_ns; u32 quirks; - - bool is_dma; }; struct cadence_spi_priv { |
