From 06b18e1ed512a3c312f9f04ae25b7966cf9eb909 Mon Sep 17 00:00:00 2001 From: Andre Przywara Date: Wed, 30 Jul 2025 23:38:52 +0100 Subject: pinctrl: sunxi: a523: change Ethernet pin function name The name of the pin function was changed last minute in the DT, from emac0 to gmac0. Adjust the name we use in the pinctrl driver accordingly. Signed-off-by: Andre Przywara Reviewed-by: Jernej Skrabec --- drivers/pinctrl/sunxi/pinctrl-sunxi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/pinctrl/sunxi/pinctrl-sunxi.c b/drivers/pinctrl/sunxi/pinctrl-sunxi.c index 03cfe23aaf8..fd357ab0d4e 100644 --- a/drivers/pinctrl/sunxi/pinctrl-sunxi.c +++ b/drivers/pinctrl/sunxi/pinctrl-sunxi.c @@ -760,7 +760,7 @@ static const struct sunxi_pinctrl_desc __maybe_unused sun50i_h616_pinctrl_desc = }; static const struct sunxi_pinctrl_function sun55i_a523_pinctrl_functions[] = { - { "emac0", 5 }, /* PI0-PI16 */ + { "gmac0", 5 }, /* PI0-PI16 */ { "gpio_in", 0 }, { "gpio_out", 1 }, { "mmc0", 2 }, /* PF0-PF5 */ -- cgit v1.2.3 From fda7bee6468ee5a701e268162aaa7645d98b85f0 Mon Sep 17 00:00:00 2001 From: Andrew Goodbody Date: Wed, 6 Aug 2025 17:55:04 +0100 Subject: phy: qcom: Fix ret is uninitialised In qcom_snps_eusb2_phy_probe after the call to devm_clk_get if an error is found then ret is printed but has not been assigned to by the code. Decode the error from the pointer and assign it to ret. This issue was found by Smatch. Signed-off-by: Andrew Goodbody Reviewed-by: Sumit Garg Link: https://lore.kernel.org/r/20250806-phy_qcom_snps-v1-1-5cda830026c7@linaro.org Signed-off-by: Casey Connolly --- drivers/phy/qcom/phy-qcom-snps-eusb2.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/phy/qcom/phy-qcom-snps-eusb2.c b/drivers/phy/qcom/phy-qcom-snps-eusb2.c index b2655ac007c..28502c46f67 100644 --- a/drivers/phy/qcom/phy-qcom-snps-eusb2.c +++ b/drivers/phy/qcom/phy-qcom-snps-eusb2.c @@ -331,8 +331,9 @@ static int qcom_snps_eusb2_phy_probe(struct udevice *dev) qcom_snps_eusb2->ref_clk = devm_clk_get(dev, "ref"); if (IS_ERR(qcom_snps_eusb2->ref_clk)) { + ret = PTR_ERR(qcom_snps_eusb2->ref_clk); printf("%s: failed to get ref clk %d\n", __func__, ret); - return PTR_ERR(qcom_snps_eusb2->ref_clk); + return ret; } ret = reset_get_bulk(dev, &qcom_snps_eusb2->resets); -- cgit v1.2.3 From f236451cb426fc3edaf756dac6346cd6273179b8 Mon Sep 17 00:00:00 2001 From: Andrew Goodbody Date: Mon, 11 Aug 2025 18:03:39 +0100 Subject: serial: msm-geni: Detect error from get_clk_div_rate In msm_serial_setbrg if the call to get_clk_div_rate fails then there will not have been an assignment to clk_div which will lead to the call to geni_serial_baud using an uninitialised value. Check for an error from get_clk_div_rate and return an error code if so. This issue was found by Smatch. Signed-off-by: Andrew Goodbody Reviewed-by: Casey Connolly Link: https://lore.kernel.org/r/20250811-serial_msm_geni-v1-1-4499179491bc@linaro.org Signed-off-by: Casey Connolly --- drivers/serial/serial_msm_geni.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers') diff --git a/drivers/serial/serial_msm_geni.c b/drivers/serial/serial_msm_geni.c index cb6c09fdd09..33016f0cb53 100644 --- a/drivers/serial/serial_msm_geni.c +++ b/drivers/serial/serial_msm_geni.c @@ -252,6 +252,10 @@ static int msm_serial_setbrg(struct udevice *dev, int baud) priv->baud = baud; clk_rate = get_clk_div_rate(baud, priv->oversampling, &clk_div); + if (!clk_rate) { + pr_err("%s: Couldn't get clock division rate\n", __func__); + return -EINVAL; + } ret = geni_serial_set_clock_rate(dev, clk_rate); if (ret < 0) { pr_err("%s: Couldn't set clock rate: %d\n", __func__, ret); -- cgit v1.2.3 From 10e65926a37d06831fc913221f9eb930c4194060 Mon Sep 17 00:00:00 2001 From: Andrew Goodbody Date: Mon, 11 Aug 2025 18:03:40 +0100 Subject: serial: msm-geni: No need to NULL check priv The NULL check for priv in qcom_geni_serial_poll_bit serves no useful prupose as too much other code surrounding it relies on priv being valid. Remove the NULL check for priv and other related code. This issue was found by Smatch. Signed-off-by: Andrew Goodbody Link: https://lore.kernel.org/r/20250811-serial_msm_geni-v1-2-4499179491bc@linaro.org Signed-off-by: Casey Connolly --- drivers/serial/serial_msm_geni.c | 30 +++++++++++++----------------- 1 file changed, 13 insertions(+), 17 deletions(-) (limited to 'drivers') diff --git a/drivers/serial/serial_msm_geni.c b/drivers/serial/serial_msm_geni.c index 33016f0cb53..0eb90f82a34 100644 --- a/drivers/serial/serial_msm_geni.c +++ b/drivers/serial/serial_msm_geni.c @@ -288,23 +288,19 @@ static bool qcom_geni_serial_poll_bit(const struct udevice *dev, int offset, unsigned int tx_fifo_depth; unsigned int tx_fifo_width; unsigned int fifo_bits; - unsigned long timeout_us = 10000; - - baud = 115200; - - if (priv) { - baud = priv->baud; - if (!baud) - baud = 115200; - tx_fifo_depth = geni_se_get_tx_fifo_depth(priv->base); - tx_fifo_width = geni_se_get_tx_fifo_width(priv->base); - fifo_bits = tx_fifo_depth * tx_fifo_width; - /* - * Total polling iterations based on FIFO worth of bytes to be - * sent at current baud. Add a little fluff to the wait. - */ - timeout_us = ((fifo_bits * USEC_PER_SEC) / baud) + 500; - } + unsigned long timeout_us; + + baud = priv->baud; + if (!baud) + baud = 115200; + tx_fifo_depth = geni_se_get_tx_fifo_depth(priv->base); + tx_fifo_width = geni_se_get_tx_fifo_width(priv->base); + fifo_bits = tx_fifo_depth * tx_fifo_width; + /* + * Total polling iterations based on FIFO worth of bytes to be + * sent at current baud. Add a little fluff to the wait. + */ + timeout_us = ((fifo_bits * USEC_PER_SEC) / baud) + 500; timeout_us = DIV_ROUND_UP(timeout_us, 10) * 10; while (timeout_us) { -- cgit v1.2.3 From 8a0bb0b176069989d645e1edca2737d46770a530 Mon Sep 17 00:00:00 2001 From: Andrew Goodbody Date: Wed, 23 Jul 2025 11:58:04 +0100 Subject: button: qcom-pmic: Fix dereference of uninitialised pointer The pointer 'label' is declared and later dereferenced without ever having a value assigned to it. Add an assignment to this pointer so it will be valid later when dereferenced. This issue was found by Smatch. Signed-off-by: Andrew Goodbody Reviewed-by: Casey Connolly Link: https://lore.kernel.org/r/20250723-button-qcom-pmic-v1-1-9c317ac71167@linaro.org Signed-off-by: Casey Connolly --- drivers/button/button-qcom-pmic.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/button/button-qcom-pmic.c b/drivers/button/button-qcom-pmic.c index 85addfe32a2..b823490d6d5 100644 --- a/drivers/button/button-qcom-pmic.c +++ b/drivers/button/button-qcom-pmic.c @@ -195,8 +195,9 @@ static int button_qcom_pmic_bind(struct udevice *parent) continue; } + label = ofnode_get_name(node); ret = device_bind_driver_to_node(parent, "qcom_pwrkey", - ofnode_get_name(node), + label, node, &dev); if (ret) { printf("Failed to bind %s! %d\n", label, ret); -- cgit v1.2.3 From be12b6e158a06580437f2e4756eb6021cf0cbfbe Mon Sep 17 00:00:00 2001 From: Andrew Goodbody Date: Thu, 7 Aug 2025 12:20:01 +0100 Subject: pinctrl: qcom: sa8775: Limit check for array index not correct In sa8775p_get_pin_name the limit check for the index into msm_special_pins_data allows for more elements than exist. Add code to ensure the array index remains in bounds. This issue was found by Smatch. Signed-off-by: Andrew Goodbody Link: https://lore.kernel.org/r/20250807-pinctrl_qcom-v1-1-42fac6707fd5@linaro.org Signed-off-by: Casey Connolly --- drivers/pinctrl/qcom/pinctrl-sa8775p.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/pinctrl/qcom/pinctrl-sa8775p.c b/drivers/pinctrl/qcom/pinctrl-sa8775p.c index cb2496ff1fb..d4acae15d55 100644 --- a/drivers/pinctrl/qcom/pinctrl-sa8775p.c +++ b/drivers/pinctrl/qcom/pinctrl-sa8775p.c @@ -516,7 +516,9 @@ static const char *sa8775p_get_function_name(struct udevice *dev, static const char *sa8775p_get_pin_name(struct udevice *dev, unsigned int selector) { - if (selector >= 149 && selector <= 155) + if (selector > 153) + strcpy(pin_name, "unknown"); + else if (selector >= 149) snprintf(pin_name, MAX_PIN_NAME_LEN, msm_special_pins_data[selector - 149].name); else -- cgit v1.2.3 From d9fbc1d70bc9d5e7665c9fc1ed71d25e04faba54 Mon Sep 17 00:00:00 2001 From: Andrew Goodbody Date: Thu, 7 Aug 2025 12:20:02 +0100 Subject: pinctrl: qcom: sdm845: Limit check off by 1 The driver specifies 154 pins so should have a maximum selector of 153 to ensure that the index into the array special_pins_names does not overflow. This issue was found by Smatch. Signed-off-by: Andrew Goodbody Link: https://lore.kernel.org/r/20250807-pinctrl_qcom-v1-2-42fac6707fd5@linaro.org Signed-off-by: Casey Connolly --- drivers/pinctrl/qcom/pinctrl-sdm845.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/pinctrl/qcom/pinctrl-sdm845.c b/drivers/pinctrl/qcom/pinctrl-sdm845.c index 3f55fc81c8e..24b42e94c7a 100644 --- a/drivers/pinctrl/qcom/pinctrl-sdm845.c +++ b/drivers/pinctrl/qcom/pinctrl-sdm845.c @@ -72,7 +72,7 @@ static const char *sdm845_get_pin_name(struct udevice *dev, "sdc2_data", }; - if (selector >= 150 && selector <= 154) + if (selector >= 150 && selector <= 153) snprintf(pin_name, MAX_PIN_NAME_LEN, special_pins_names[selector - 150]); else snprintf(pin_name, MAX_PIN_NAME_LEN, "gpio%u", selector); -- cgit v1.2.3 From 111e9bf6a5acc8187c4849cbf4e7516e37496059 Mon Sep 17 00:00:00 2001 From: Jamie Gibbons Date: Fri, 1 Aug 2025 13:36:23 +0100 Subject: mailbox: add PolarFire SoC mailbox driver This driver adds support for the single mailbox channel of the MSS system controller on the Microchip PolarFire SoC. Signed-off-by: Jamie Gibbons Acked-by: Leo Yu-Chi Liang --- drivers/mailbox/Kconfig | 7 ++ drivers/mailbox/Makefile | 1 + drivers/mailbox/mpfs-mbox.c | 177 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 185 insertions(+) create mode 100644 drivers/mailbox/mpfs-mbox.c (limited to 'drivers') diff --git a/drivers/mailbox/Kconfig b/drivers/mailbox/Kconfig index 4d9f004ebad..f9531c1627c 100644 --- a/drivers/mailbox/Kconfig +++ b/drivers/mailbox/Kconfig @@ -28,6 +28,13 @@ config IMX_MU_MBOX Enable support for i.MX Messaging Unit for communication with other processors on the SoC using mailbox interface +config MPFS_MBOX + bool "Enable MPFS system controller support" + depends on DM_MAILBOX && ARCH_RV64I + help + Enable support for the mailboxes that provide a communication + channel with the system controller integrated on PolarFire SoC. + config SANDBOX_MBOX bool "Enable the sandbox mailbox test driver" depends on DM_MAILBOX && SANDBOX diff --git a/drivers/mailbox/Makefile b/drivers/mailbox/Makefile index e8c745f7d79..b54fbdfff15 100644 --- a/drivers/mailbox/Makefile +++ b/drivers/mailbox/Makefile @@ -6,6 +6,7 @@ obj-$(CONFIG_$(PHASE_)DM_MAILBOX) += mailbox-uclass.o obj-$(CONFIG_APPLE_MBOX) += apple-mbox.o obj-$(CONFIG_IMX_MU_MBOX) += imx-mailbox.o +obj-$(CONFIG_MPFS_MBOX) += mpfs-mbox.o obj-$(CONFIG_SANDBOX_MBOX) += sandbox-mbox.o obj-$(CONFIG_SANDBOX_MBOX) += sandbox-mbox-test.o obj-$(CONFIG_STM32_IPCC) += stm32-ipcc.o diff --git a/drivers/mailbox/mpfs-mbox.c b/drivers/mailbox/mpfs-mbox.c new file mode 100644 index 00000000000..55238847ecd --- /dev/null +++ b/drivers/mailbox/mpfs-mbox.c @@ -0,0 +1,177 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Microchip's PolarFire SoC (MPFS) Mailbox Driver + * + * Copyright (C) 2024 Microchip Technology Inc. All rights reserved. + * + * Author: Jamie Gibbons + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define SERVICES_CR_OFFSET 0x50u +#define SERVICES_SR_OFFSET 0x54u + +#define SERVICE_CR_REQ_MASK 0x1u +#define SERVICE_SR_BUSY_MASK 0x2u +#define SERVICE_SR_STATUS_SHIFT 16 +#define SERVICE_CR_COMMAND_SHIFT 16 +#define MASK_8BIT 0xFF + +struct mpfs_mbox { + struct udevice *dev; + void __iomem *ctrl_base; + void __iomem *mbox_base; + struct mbox_chan *chan; +}; + +static bool mpfs_mbox_busy(struct mbox_chan *chan) +{ + struct mpfs_mbox *mbox = dev_get_priv(chan->dev); + uint16_t status; + + status = readl(mbox->ctrl_base + SERVICES_SR_OFFSET); + + return status & SERVICE_SR_BUSY_MASK; +} + +static int mpfs_mbox_send(struct mbox_chan *chan, const void *data) +{ + struct mpfs_mbox *mbox = dev_get_priv(chan->dev); + struct mpfs_mss_msg *msg = (struct mpfs_mss_msg *)data; + u32 mailbox_val, cmd_shifted, value; + u8 *byte_buf; + u8 idx, byte_idx, byte_offset; + + u32 *word_buf = (u32 *)msg->cmd_data; + + if (mpfs_mbox_busy(chan)) + return -EBUSY; + + for (idx = 0; idx < (msg->cmd_data_size / BYTES_4); idx++) + writel(word_buf[idx], mbox->mbox_base + msg->mbox_offset + idx * BYTES_4); + + if ((msg->cmd_data_size % BYTES_4) > 0) { + byte_offset = (msg->cmd_data_size / BYTES_4) * BYTES_4; + byte_buf = (u8 *)(msg->cmd_data + byte_offset); + mailbox_val = readl(mbox->mbox_base + msg->mbox_offset + idx * BYTES_4); + + for (byte_idx = 0; byte_idx < (msg->cmd_data_size % BYTES_4); byte_idx++) { + mailbox_val &= ~(MASK_8BIT << (byte_idx * 0x8u)); + mailbox_val |= (u32)byte_buf[byte_idx] << (byte_idx * 0x8u); + } + writel(mailbox_val, mbox->mbox_base + msg->mbox_offset + idx * BYTES_4); + } + + cmd_shifted = msg->cmd_opcode << SERVICE_CR_COMMAND_SHIFT; + cmd_shifted |= SERVICE_CR_REQ_MASK; + writel(cmd_shifted, mbox->ctrl_base + SERVICES_CR_OFFSET); + + do { + value = readl(mbox->ctrl_base + SERVICES_CR_OFFSET); + } while (SERVICE_CR_REQ_MASK == (value & SERVICE_CR_REQ_MASK)); + + do { + value = readl(mbox->ctrl_base + SERVICES_SR_OFFSET); + } while (SERVICE_SR_BUSY_MASK == (value & SERVICE_SR_BUSY_MASK)); + + msg->response->resp_status = (value >> SERVICE_SR_STATUS_SHIFT); + if (msg->response->resp_status) + return -EBADMSG; + + return 0; +} + +static int mpfs_mbox_recv(struct mbox_chan *chan, void *data) +{ + struct mpfs_mbox *mbox = dev_get_priv(chan->dev); + struct mpfs_mss_msg *msg = data; + struct mpfs_mss_response *response = msg->response; + u8 idx; + + if (!response->resp_msg) { + dev_err(chan->dev, "failed to assign memory for response %d\n", -ENOMEM); + return -EINVAL; + } + + if (mpfs_mbox_busy(chan)) { + dev_err(chan->dev, "mailbox is busy\n"); + response->resp_status = 0xDEAD; + return -EINVAL; + } + + for (idx = 0; idx < response->resp_size; idx++) + *((u8 *)(response->resp_msg) + idx) = readb(mbox->mbox_base + msg->resp_offset + idx); + + return 0; +} + +static const struct mbox_ops mpfs_mbox_ops = { + .send = mpfs_mbox_send, + .recv = mpfs_mbox_recv, +}; + +static int mpfs_mbox_probe(struct udevice *dev) +{ + struct mpfs_mbox *mbox; + struct resource regs; + ofnode node; + int ret; + + node = dev_ofnode(dev); + + mbox = devm_kzalloc(dev, sizeof(*mbox), GFP_KERNEL); + if (!mbox) + return -ENOMEM; + + ret = ofnode_read_resource(node, 0, ®s); + if (ret) { + dev_err(dev, "No reg property for controller base\n"); + return ret; + }; + + mbox->ctrl_base = devm_ioremap(dev, regs.start, regs.start - regs.end); + + ret = ofnode_read_resource(node, 2, ®s); + if (ret) { + dev_err(dev, "No reg property for mailbox base\n"); + return ret; + }; + + mbox->mbox_base = devm_ioremap(dev, regs.start, regs.start - regs.end); + + mbox->dev = dev; + dev_set_priv(dev, mbox); + mbox->chan->con_priv = mbox; + + return 0; +} + +static const struct udevice_id mpfs_mbox_ids[] = { + {.compatible = "microchip,mpfs-mailbox"}, + { } +}; + +U_BOOT_DRIVER(mpfs_mbox) = { + .name = "mpfs-mbox", + .id = UCLASS_MAILBOX, + .of_match = mpfs_mbox_ids, + .probe = mpfs_mbox_probe, + .priv_auto = sizeof(struct mpfs_mbox), + .ops = &mpfs_mbox_ops, +}; -- cgit v1.2.3 From b7a0ad16f9114a7fe648d94e67d943772b8119ab Mon Sep 17 00:00:00 2001 From: Jamie Gibbons Date: Fri, 1 Aug 2025 13:36:24 +0100 Subject: misc: add PolarFire SoC system controller This driver provides an interface to access the functions of the system controller on the Microchip PolarFire SoC. This driver includes functions to use the system controller to read the device serial number. Signed-off-by: Jamie Gibbons Acked-by: Leo Yu-Chi Liang --- drivers/misc/Kconfig | 9 +++ drivers/misc/Makefile | 1 + drivers/misc/mpfs_syscontroller.c | 156 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 166 insertions(+) create mode 100644 drivers/misc/mpfs_syscontroller.c (limited to 'drivers') diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig index 0f753b9dbb9..29b84430ff5 100644 --- a/drivers/misc/Kconfig +++ b/drivers/misc/Kconfig @@ -658,6 +658,15 @@ config MICROCHIP_FLEXCOM Only one function can be used at a time and is chosen at boot time according to the device tree. +config MPFS_SYSCONTROLLER + bool "Enable Microchip PolarFire SoC (MPFS) System Services support" + depends on MISC + depends on MPFS_MBOX + help + This driver adds support for the PolarFire SoC (MPFS) system controller. + + If unsure, say N. + config K3_AVS0 depends on ARCH_K3 && SPL_DM_REGULATOR bool "AVS class 0 support for K3 devices" diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile index f7422c8e95a..dc5eb3af19c 100644 --- a/drivers/misc/Makefile +++ b/drivers/misc/Makefile @@ -86,6 +86,7 @@ obj-$(CONFIG_VEXPRESS_CONFIG) += vexpress_config.o obj-$(CONFIG_WINBOND_W83627) += winbond_w83627.o obj-$(CONFIG_JZ4780_EFUSE) += jz4780_efuse.o obj-$(CONFIG_MICROCHIP_FLEXCOM) += microchip_flexcom.o +obj-$(CONFIG_MPFS_SYSCONTROLLER) += mpfs_syscontroller.o obj-$(CONFIG_K3_AVS0) += k3_avs.o obj-$(CONFIG_ESM_K3) += k3_esm.o obj-$(CONFIG_K3_BIST) += k3_bist.o diff --git a/drivers/misc/mpfs_syscontroller.c b/drivers/misc/mpfs_syscontroller.c new file mode 100644 index 00000000000..41e80815ab5 --- /dev/null +++ b/drivers/misc/mpfs_syscontroller.c @@ -0,0 +1,156 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Microchip's PolarFire SoC (MPFS) System Controller Driver + * + * Copyright (C) 2024 Microchip Technology Inc. All rights reserved. + * + * Author: Jamie Gibbons + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Descriptor table */ +#define CMD_OPCODE 0x0u +#define CMD_DATA_SIZE 0U +#define CMD_DATA NULL +#define MBOX_OFFSET 0x0 +#define RESP_OFFSET 0x0 +#define RESP_BYTES 16U + +/** + * struct mpfs_syscontroller_priv - Structure representing System Controller data. + * @chan: Mailbox channel + * @c: Completion signal + */ +struct mpfs_syscontroller_priv { + struct mbox_chan chan; + struct completion c; +}; + +/** + * mpfs_syscontroller_run_service() - Run the MPFS system service + * @sys_controller: corresponding MPFS system service device + * @msg: Message to send + * + * Return: 0 if all goes good, else appropriate error message. + */ +int mpfs_syscontroller_run_service(struct mpfs_syscontroller_priv *sys_controller, struct mpfs_mss_msg *msg) +{ + int ret; + + reinit_completion(&sys_controller->c); + + /* Run the System Service Request */ + ret = mbox_send(&sys_controller->chan, msg); + if (ret < 0) + dev_warn(sys_controller->chan.dev, "MPFS sys controller service timeout\n"); + + debug("%s: Service successful %s\n", + __func__, sys_controller->chan.dev->name); + + return ret; +} +EXPORT_SYMBOL_GPL(mpfs_syscontroller_run_service); + +/** + * mpfs_syscontroller_read_sernum() - Use system service to read the device serial number + * @sys_serv_priv: system service private data + * @device_serial_number: device serial number + * + * Return: 0 if all went ok, else return appropriate error + */ +int mpfs_syscontroller_read_sernum(struct mpfs_sys_serv *sys_serv_priv, u8 *device_serial_number) +{ + unsigned long timeoutsecs = 300; + int ret; + + struct mpfs_mss_response response = { + .resp_status = 0U, + .resp_msg = (u32 *)device_serial_number, + .resp_size = RESP_BYTES}; + struct mpfs_mss_msg msg = { + .cmd_opcode = CMD_OPCODE, + .cmd_data_size = CMD_DATA_SIZE, + .response = &response, + .cmd_data = CMD_DATA, + .mbox_offset = MBOX_OFFSET, + .resp_offset = RESP_OFFSET}; + + ret = mpfs_syscontroller_run_service(sys_serv_priv->sys_controller, &msg); + if (ret) { + dev_err(sys_serv_priv->sys_controller->chan.dev, "Service failed: %d, abort\n", ret); + return ret; + } + + /* Receive the response */ + ret = mbox_recv(&sys_serv_priv->sys_controller->chan, &msg, timeoutsecs); + if (ret) { + dev_err(sys_serv_priv->sys_controller->chan.dev, "Service failed: %d, abort. Failure: %u\n", ret, msg.response->resp_status); + return ret; + } + + debug("%s: Read successful %s\n", + __func__, sys_serv_priv->sys_controller->chan.dev->name); + + return 0; +} +EXPORT_SYMBOL(mpfs_syscontroller_read_sernum); + +static int mpfs_syscontroller_probe(struct udevice *dev) +{ + struct mpfs_syscontroller_priv *sys_controller = dev_get_priv(dev); + int ret; + + ret = mbox_get_by_index(dev, 0, &sys_controller->chan); + if (ret) { + dev_err(dev, "%s: Acquiring mailbox channel failed. ret = %d\n", + __func__, ret); + return ret; + } + + init_completion(&sys_controller->c); + dev_info(dev, "Registered MPFS system controller\n"); + + return 0; +} + +static const struct udevice_id mpfs_syscontroller_ids[] = { + { .compatible = "microchip,mpfs-sys-controller" }, + { } +}; + +struct mpfs_syscontroller_priv *mpfs_syscontroller_get(struct udevice *dev) +{ + struct mpfs_syscontroller_priv *sys_controller; + + sys_controller = dev_get_priv(dev); + if (!sys_controller) { + debug("%s: MPFS system controller found but could not register as a sub device %p\n", + __func__, sys_controller); + return ERR_PTR(-EPROBE_DEFER); + } + + return sys_controller; +} +EXPORT_SYMBOL(mpfs_syscontroller_get); + +U_BOOT_DRIVER(mpfs_syscontroller) = { + .name = "mpfs_syscontroller", + .id = UCLASS_MISC, + .of_match = mpfs_syscontroller_ids, + .probe = mpfs_syscontroller_probe, + .priv_auto = sizeof(struct mpfs_syscontroller_priv), +}; -- cgit v1.2.3 From 93297f1f9bb5e21149fc344aaddf7cf2b7e1fb8f Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Wed, 6 Aug 2025 21:23:54 +0200 Subject: pci: pcie-rcar-gen4: Fix PHY initialization R-Car V4H Reference Manual R19UH0186EJ0130 Rev.1.30 Apr. 21, 2025 page 4581 Figure 104.3b Initial Setting of PCIEC(example) middle of the figure indicates that fourth write into register 0x148 [2:0] is 0x3 or GENMASK(1, 0). The current code writes GENMASK(11, 0) which is a typo. Fix the typo. Fixes: be3dd0dc2fd9 ("pci: pcie-rcar-gen4: Add Renesas R-Car Gen4 DW PCIe controller driver") Signed-off-by: Marek Vasut --- drivers/pci/pci-rcar-gen4.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/pci/pci-rcar-gen4.c b/drivers/pci/pci-rcar-gen4.c index 87cd69f989d..41f0d958447 100644 --- a/drivers/pci/pci-rcar-gen4.c +++ b/drivers/pci/pci-rcar-gen4.c @@ -235,7 +235,7 @@ static int rcar_gen4_pcie_ltssm_control(struct rcar_gen4_pcie *rcar, bool enable clrsetbits_le32(rcar->phy_base + 0x148, GENMASK(23, 22), BIT(22)); clrsetbits_le32(rcar->phy_base + 0x148, GENMASK(18, 16), GENMASK(17, 16)); clrsetbits_le32(rcar->phy_base + 0x148, GENMASK(7, 6), BIT(6)); - clrsetbits_le32(rcar->phy_base + 0x148, GENMASK(2, 0), GENMASK(11, 0)); + clrsetbits_le32(rcar->phy_base + 0x148, GENMASK(2, 0), GENMASK(1, 0)); clrsetbits_le32(rcar->phy_base + 0x1d4, GENMASK(16, 15), GENMASK(16, 15)); clrsetbits_le32(rcar->phy_base + 0x514, BIT(26), BIT(26)); clrsetbits_le32(rcar->phy_base + 0x0f8, BIT(16), 0); -- cgit v1.2.3 From 45eedb7b8097793242c542b68bc5d37b298808b7 Mon Sep 17 00:00:00 2001 From: Andrew Goodbody Date: Tue, 5 Aug 2025 16:45:47 +0100 Subject: net: octeontx: Remove unneeded code In nicvf_rcv_pkt_handler there is no need to initialise err as it is assigned to immediately after. Also the test for !pkt will return if true meaning that pkt is guaranteed to be true after that code block and so no need to test for it and the redundant test can be removed. This issue was found by Smatch. Signed-off-by: Andrew Goodbody --- drivers/net/octeontx/nicvf_main.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/octeontx/nicvf_main.c b/drivers/net/octeontx/nicvf_main.c index 27d0327c88a..8021cd752b5 100644 --- a/drivers/net/octeontx/nicvf_main.c +++ b/drivers/net/octeontx/nicvf_main.c @@ -232,7 +232,7 @@ static int nicvf_rcv_pkt_handler(struct nicvf *nic, size_t pkt_len; struct cqe_rx_t *cqe_rx = (struct cqe_rx_t *)cq_desc; - int err = 0; + int err; /* Check for errors */ err = nicvf_check_cqe_rx_errs(nic, cq, cq_desc); @@ -245,8 +245,7 @@ static int nicvf_rcv_pkt_handler(struct nicvf *nic, return -1; } - if (pkt) - *ppkt = pkt; + *ppkt = pkt; return pkt_len; } -- cgit v1.2.3 From 62b4a482b943bc8173ac10a6c783e84d939b88bf Mon Sep 17 00:00:00 2001 From: Andrew Goodbody Date: Tue, 5 Aug 2025 16:45:48 +0100 Subject: net: octeontx: Remove unneeded test In nicvf_cq_handler there is a test for !cqe_count which will return if true so it is guaranteed that cqe_count will true after that point. This makes the later test for cqe_count redundant so it can be removed. This issue was found by Smatch. Signed-off-by: Andrew Goodbody --- drivers/net/octeontx/nicvf_main.c | 46 +++++++++++++++++++-------------------- 1 file changed, 22 insertions(+), 24 deletions(-) (limited to 'drivers') diff --git a/drivers/net/octeontx/nicvf_main.c b/drivers/net/octeontx/nicvf_main.c index 8021cd752b5..94e5d827614 100644 --- a/drivers/net/octeontx/nicvf_main.c +++ b/drivers/net/octeontx/nicvf_main.c @@ -273,31 +273,29 @@ int nicvf_cq_handler(struct nicvf *nic, void **ppkt, int *pkt_len) cqe_head >>= 9; cqe_head &= 0xFFFF; - if (cqe_count) { - /* Get the CQ descriptor */ - cq_desc = (struct cqe_rx_t *)GET_CQ_DESC(cq, cqe_head); - cqe_head++; - cqe_head &= (cq->dmem.q_len - 1); - - switch (cq_desc->cqe_type) { - case CQE_TYPE_RX: - debug("%s: Got Rx CQE\n", nic->dev->name); - *pkt_len = nicvf_rcv_pkt_handler(nic, cq, cq_desc, - ppkt, CQE_TYPE_RX); - processed_rq_cqe++; - break; - case CQE_TYPE_SEND: - debug("%s: Got Tx CQE\n", nic->dev->name); - nicvf_snd_pkt_handler(nic, cq, cq_desc, CQE_TYPE_SEND); - processed_sq_cqe++; - break; - default: - debug("%s: Got CQ type %u\n", nic->dev->name, - cq_desc->cqe_type); - break; - } - processed_cqe++; + /* Get the CQ descriptor */ + cq_desc = (struct cqe_rx_t *)GET_CQ_DESC(cq, cqe_head); + cqe_head++; + cqe_head &= (cq->dmem.q_len - 1); + + switch (cq_desc->cqe_type) { + case CQE_TYPE_RX: + debug("%s: Got Rx CQE\n", nic->dev->name); + *pkt_len = nicvf_rcv_pkt_handler(nic, cq, cq_desc, + ppkt, CQE_TYPE_RX); + processed_rq_cqe++; + break; + case CQE_TYPE_SEND: + debug("%s: Got Tx CQE\n", nic->dev->name); + nicvf_snd_pkt_handler(nic, cq, cq_desc, CQE_TYPE_SEND); + processed_sq_cqe++; + break; + default: + debug("%s: Got CQ type %u\n", nic->dev->name, + cq_desc->cqe_type); + break; } + processed_cqe++; /* Dequeue CQE */ nicvf_queue_reg_write(nic, NIC_QSET_CQ_0_7_DOOR, -- cgit v1.2.3 From 0ce7fef9e2154d188bd50ae687fb666faac8fe7b Mon Sep 17 00:00:00 2001 From: Andrew Goodbody Date: Tue, 5 Aug 2025 16:45:49 +0100 Subject: net: octeontx: Free allocated memory on error In octeontx_smi_probe if an error is detected then memory that was allocated is not freed. Small refactor of the code to use a common return and free memory. Also return -ENOMEM for an allocation failure. This issue was found by Smatch. Signed-off-by: Andrew Goodbody --- drivers/net/octeontx/smi.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/octeontx/smi.c b/drivers/net/octeontx/smi.c index 233c26f7319..217bcac2ce2 100644 --- a/drivers/net/octeontx/smi.c +++ b/drivers/net/octeontx/smi.c @@ -338,7 +338,8 @@ int octeontx_smi_probe(struct udevice *dev) if (!bus || !priv) { printf("Failed to allocate OcteonTX MDIO bus # %u\n", dev_seq(dev)); - return -1; + ret = -ENOMEM; + goto error_ret; } bus->read = octeontx_phy_read; @@ -355,9 +356,16 @@ int octeontx_smi_probe(struct udevice *dev) ret = mdio_register(bus); if (ret) - return ret; + goto error_ret; } return 0; + +error_ret: + if (bus) + free(bus); + if (priv) + free(priv); + return ret; } static const struct udevice_id octeontx_smi_ids[] = { -- cgit v1.2.3 From 4b2d64f3885a83fd001993785f74f70cc6045acc Mon Sep 17 00:00:00 2001 From: Andrew Goodbody Date: Wed, 6 Aug 2025 10:37:26 +0100 Subject: net: phy: vitesse: Fix incorrect test for timeout In vsc8514_config there is a while loop for detecting a config failure using a timeout counter with a post-decrement. In the case of a timeout this will result in the loop exiting with timeout == -1 so use that as the test below the loop to detect that the timeout occurred. This issue was found by Smatch. Signed-off-by: Andrew Goodbody Reviewed-by: Quentin Schulz --- drivers/net/phy/vitesse.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/phy/vitesse.c b/drivers/net/phy/vitesse.c index 4867d1931b4..821d3878236 100644 --- a/drivers/net/phy/vitesse.c +++ b/drivers/net/phy/vitesse.c @@ -239,7 +239,7 @@ static int vsc8514_config(struct phy_device *phydev) while ((val & MIIM_VSC8514_18G_CMDSTAT) && timeout--) val = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_VSC8514_GENERAL18); - if (0 == timeout) { + if (timeout == -1) { printf("PHY 8514 config failed\n"); return -1; } -- cgit v1.2.3 From a75c8a4b883108edf19127fca3e6c6c590f9ba8c Mon Sep 17 00:00:00 2001 From: Andrew Goodbody Date: Wed, 6 Aug 2025 17:43:24 +0100 Subject: phy: marvell: Fix off by 1 limit checks The limit checks in get_speed_string and get_type_string are off by 1 as they do not account for the maximum index into an array that can be used is 1 less than the number of elements in that array. Adjust the limit checks to allow for this. This issue was found by Smatch. Signed-off-by: Andrew Goodbody Reviewed-by: Stefan Roese --- drivers/phy/marvell/comphy_core.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/phy/marvell/comphy_core.c b/drivers/phy/marvell/comphy_core.c index a666a4e794e..a4121423873 100644 --- a/drivers/phy/marvell/comphy_core.c +++ b/drivers/phy/marvell/comphy_core.c @@ -28,7 +28,7 @@ static const char *get_speed_string(u32 speed) "10.3125 Gbps" }; - if (speed < 0 || speed > COMPHY_SPEED_MAX) + if (speed < 0 || speed >= COMPHY_SPEED_MAX) return "invalid"; return speed_strings[speed]; @@ -44,7 +44,7 @@ static const char *get_type_string(u32 type) "IGNORE" }; - if (type < 0 || type > COMPHY_TYPE_MAX) + if (type < 0 || type >= COMPHY_TYPE_MAX) return "invalid"; return type_strings[type]; -- cgit v1.2.3 From 2e9155cb9f366a6b9191af0850efad1948b4c785 Mon Sep 17 00:00:00 2001 From: Andrew Goodbody Date: Wed, 6 Aug 2025 17:43:25 +0100 Subject: phy: marvell: Cannot test unsigned field to be negative In comphy_cp110_init_serdes_map in comphy_cp110.c there are two fields in cfg, comphy_lanes_count and comphy_mux_bitcount, which are fetched from the FDT blob with fdtdec_get_int which returns an int. These two fields are then tested for being negative. However the fields are declared as unsigned so those tests must always fail. Change the declaration of those fields to be int instead of u32 and the code will work as expected. This issue was found by Smatch. Signed-off-by: Andrew Goodbody Reviewed-by: Stefan Roese --- drivers/phy/marvell/comphy_core.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/phy/marvell/comphy_core.h b/drivers/phy/marvell/comphy_core.h index f3d04939387..086a4d82f26 100644 --- a/drivers/phy/marvell/comphy_core.h +++ b/drivers/phy/marvell/comphy_core.h @@ -47,8 +47,8 @@ struct chip_serdes_phy_config { int (*rx_training)(struct chip_serdes_phy_config *, u32); void __iomem *comphy_base_addr; void __iomem *hpipe3_base_addr; - u32 comphy_lanes_count; - u32 comphy_mux_bitcount; + int comphy_lanes_count; + int comphy_mux_bitcount; const fdt32_t *comphy_mux_lane_order; u32 cp_index; struct comphy_map comphy_map_data[MAX_LANE_OPTIONS]; -- cgit v1.2.3 From 59ec495f6c645c80d934034ffe48adb2ea75839a Mon Sep 17 00:00:00 2001 From: Jim Liu Date: Thu, 7 Aug 2025 13:28:32 +0800 Subject: net: designware: Fix get_timer value overflow get_timer returns a ulong value representing system time in ms. On a 64-bit system, this ulong value is 64 bits long. However, the driver stores it in a 32-bit unsigned integer, which overflows after 49 days up time, causing the driver to get an incorrect time. Replace the unsigned int variable with a ulong type to properly store the value returned by get_timer. Signed-off-by: Stanley Chu Signed-off-by: Jim Liu --- drivers/net/designware.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/designware.c b/drivers/net/designware.c index fce3ef910cb..7ecedc3d7f0 100644 --- a/drivers/net/designware.c +++ b/drivers/net/designware.c @@ -486,7 +486,7 @@ static int dw_adjust_link(struct dw_eth_dev *priv, struct eth_mac_regs *mac_p, #ifdef CONFIG_ARCH_NPCM8XX if (phydev->interface == PHY_INTERFACE_MODE_SGMII) { - unsigned int start; + ulong start; /* Indirect access to VR_MII_MMD registers */ writew((VR_MII_MMD >> 9), PCS_BA + PCS_IND_AC); @@ -532,7 +532,7 @@ int designware_eth_init(struct dw_eth_dev *priv, u8 *enetaddr) { struct eth_mac_regs *mac_p = priv->mac_regs_p; struct eth_dma_regs *dma_p = priv->dma_regs_p; - unsigned int start; + ulong start; int ret; writel(readl(&dma_p->busmode) | DMAMAC_SRST, &dma_p->busmode); -- cgit v1.2.3 From 0cabbe3235ba91f84495095a7bec693338b3c521 Mon Sep 17 00:00:00 2001 From: Jim Liu Date: Thu, 7 Aug 2025 13:29:31 +0800 Subject: net: phy: broadcom: add support for BCM54612E It's Broadcom PHY simply described as single-port RGMII 10/100/1000BASE-T PHY. Signed-off-by: Jim Liu --- drivers/net/phy/broadcom.c | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) (limited to 'drivers') diff --git a/drivers/net/phy/broadcom.c b/drivers/net/phy/broadcom.c index 0a49015eb89..1c02e3efedc 100644 --- a/drivers/net/phy/broadcom.c +++ b/drivers/net/phy/broadcom.c @@ -134,6 +134,33 @@ static void bcm_phy_write_misc(struct phy_device *phydev, phy_write(phydev, MDIO_DEVAD_NONE, MIIM_BCM54XX_EXP_DATA, value); } +/* Broadcom BCM54612E */ +static int bcm54612e_config(struct phy_device *phydev) +{ + u32 reg = 0; + + genphy_config_aneg(phydev); + + phy_reset(phydev); + + /* 125Mhz Clock Output Enable */ + reg = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_BCM54XX_EXP_SEL); + reg |= 0xD34; + phy_write(phydev, MDIO_DEVAD_NONE, MIIM_BCM54XX_EXP_SEL, reg); + + reg = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_BCM54XX_EXP_DATA); + reg |= (1 << 1); + phy_write(phydev, MDIO_DEVAD_NONE, MIIM_BCM54XX_EXP_DATA, reg); + + reg = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_BCM54XX_EXP_SEL); + reg &= 0xfffff000; + phy_write(phydev, MDIO_DEVAD_NONE, MIIM_BCM54XX_EXP_SEL, reg); + + genphy_restart_aneg(phydev); + + return 0; +} + /* Broadcom BCM5461S */ static int bcm5461_config(struct phy_device *phydev) { @@ -434,6 +461,16 @@ U_BOOT_PHY_DRIVER(bcm5461s) = { .shutdown = &genphy_shutdown, }; +U_BOOT_PHY_DRIVER(bcm54612e) = { + .name = "Broadcom BCM54612E", + .uid = 0x03625e6a, + .mask = 0xfffff0, + .features = PHY_GBIT_FEATURES, + .config = &bcm54612e_config, + .startup = &bcm54xx_startup, + .shutdown = &genphy_shutdown, +}; + U_BOOT_PHY_DRIVER(bcm5464s) = { .name = "Broadcom BCM5464S", .uid = 0x2060b0, -- cgit v1.2.3 From ed3b08874f4c47e287a1f0eb36fc61ff7d778cc9 Mon Sep 17 00:00:00 2001 From: Andrew Goodbody Date: Tue, 5 Aug 2025 11:52:00 +0100 Subject: net: ldpaa_eth: Fix buffer overflow in memset In ldpaa_eth_open a memset is used to initialise a struct to 0 but the size passed is that of a different struct. Correct to pass the sizeof the struct that is being initialised. This issue was found by Smatch. Signed-off-by: Andrew Goodbody --- drivers/net/ldpaa_eth/ldpaa_eth.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ldpaa_eth/ldpaa_eth.c b/drivers/net/ldpaa_eth/ldpaa_eth.c index b72198ca530..94e62748239 100644 --- a/drivers/net/ldpaa_eth/ldpaa_eth.c +++ b/drivers/net/ldpaa_eth/ldpaa_eth.c @@ -458,7 +458,7 @@ static int ldpaa_eth_open(struct udevice *dev) link_state.up == 1 ? printf("up\n") : printf("error state\n"); #endif - memset(&d_queue, 0, sizeof(struct dpni_queue)); + memset(&d_queue, 0, sizeof(struct dpni_queue_id)); err = dpni_get_queue(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpni->dpni_handle, DPNI_QUEUE_RX, 0, 0, &d_queue_cfg, &d_queue); -- cgit v1.2.3 From ff36afe346777f60c461964de1ab00aa6b2edb95 Mon Sep 17 00:00:00 2001 From: Andrew Goodbody Date: Tue, 5 Aug 2025 12:04:00 +0100 Subject: net: mediatek: Use correct variable for return In mtk_eth_of_to_plat, the last error check has the value in 'priv->phy_addr' but returns ret. Correct to return 'priv->phy_addr' instead. This issue was found by Smatch. Signed-off-by: Andrew Goodbody --- drivers/net/mtk_eth/mtk_eth.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/mtk_eth/mtk_eth.c b/drivers/net/mtk_eth/mtk_eth.c index 5d6a42bceb4..b172838ba3a 100644 --- a/drivers/net/mtk_eth/mtk_eth.c +++ b/drivers/net/mtk_eth/mtk_eth.c @@ -1461,7 +1461,7 @@ static int mtk_eth_of_to_plat(struct udevice *dev) priv->phy_addr = ofnode_read_s32_default(args.node, "reg", -1); if (priv->phy_addr < 0) { printf("error: phy address is not specified\n"); - return ret; + return priv->phy_addr; } } -- cgit v1.2.3 From 34bc71f2db6bcd83b718ac9c28c39bd7d788a356 Mon Sep 17 00:00:00 2001 From: Andrew Goodbody Date: Tue, 5 Aug 2025 12:14:14 +0100 Subject: net: mv88e6xxx: Fix logical operator instead of bitwise In mv88e6xxx_port_enable when attempting to mask out the previous settings of two bits a logical operator was used instead of a bitwise operator. Fix this. This issue was found by Smatch. Signed-off-by: Andrew Goodbody --- drivers/net/mv88e6xxx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/mv88e6xxx.c b/drivers/net/mv88e6xxx.c index 557b6b2c8f6..f06c73c20f8 100644 --- a/drivers/net/mv88e6xxx.c +++ b/drivers/net/mv88e6xxx.c @@ -631,7 +631,7 @@ static int mv88e6xxx_port_enable(struct udevice *dev, int port, struct phy_devic dev_dbg(dev, "configure internal RGMII delays\n"); /* RGMII delays */ - val &= ~(PORT_REG_PHYS_CTRL_RGMII_DELAY_RXCLK || + val &= ~(PORT_REG_PHYS_CTRL_RGMII_DELAY_RXCLK | PORT_REG_PHYS_CTRL_RGMII_DELAY_TXCLK); if (phy->interface == PHY_INTERFACE_MODE_RGMII_ID || phy->interface == PHY_INTERFACE_MODE_RGMII_RXID) -- cgit v1.2.3 From b24c89affd9063c3f9f3ca99db075bd3bb1fc4b2 Mon Sep 17 00:00:00 2001 From: Andrew Goodbody Date: Tue, 5 Aug 2025 15:18:16 +0100 Subject: net: mvpp2: Fix impossible test You cannot test an unsigned char to be >= 256. Instead make the variables start and end to be ints. This issue was found by Smatch. Signed-off-by: Andrew Goodbody --- drivers/net/mvpp2.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/mvpp2.c b/drivers/net/mvpp2.c index 184c1f9a46a..c0328345973 100644 --- a/drivers/net/mvpp2.c +++ b/drivers/net/mvpp2.c @@ -1722,8 +1722,7 @@ static struct mvpp2_prs_entry *mvpp2_prs_flow_find(struct mvpp2 *priv, int flow) } /* Return first free tcam index, seeking from start to end */ -static int mvpp2_prs_tcam_first_free(struct mvpp2 *priv, unsigned char start, - unsigned char end) +static int mvpp2_prs_tcam_first_free(struct mvpp2 *priv, int start, int end) { int tid; -- cgit v1.2.3 From 6781b90f89b427ec9445c43f8102ebe0a4330e54 Mon Sep 17 00:00:00 2001 From: Andrew Goodbody Date: Tue, 5 Aug 2025 15:18:17 +0100 Subject: net: mvpp2: Return -ENOMEM for failed alloc Instead of returning -1 on a failed alloc, return -ENOMEM. This issue was found by Smatch. Signed-off-by: Andrew Goodbody --- drivers/net/mvpp2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/mvpp2.c b/drivers/net/mvpp2.c index c0328345973..b68d305a0dc 100644 --- a/drivers/net/mvpp2.c +++ b/drivers/net/mvpp2.c @@ -2329,7 +2329,7 @@ static int mvpp2_prs_mac_da_accept(struct mvpp2 *priv, int port, pe = kzalloc(sizeof(*pe), GFP_KERNEL); if (!pe) - return -1; + return -ENOMEM; mvpp2_prs_tcam_lu_set(pe, MVPP2_PRS_LU_MAC); pe->index = tid; -- cgit v1.2.3 From 3aa3d37282414ea5c19ea415f46d214f4c80d8b6 Mon Sep 17 00:00:00 2001 From: Andrew Goodbody Date: Tue, 5 Aug 2025 15:18:18 +0100 Subject: net: mvpp2: Cannot test unsigned variable to be negative In phy_info_parse all uses of the variable phyaddr are as an int so declaring as u32 is not useful and prevents the test for an error return from fdtdec_get_int ever detecting an error. Change phyaddr to be an int. This issue was found by Smatch. Signed-off-by: Andrew Goodbody --- drivers/net/mvpp2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/mvpp2.c b/drivers/net/mvpp2.c index b68d305a0dc..3a3510f603a 100644 --- a/drivers/net/mvpp2.c +++ b/drivers/net/mvpp2.c @@ -4734,7 +4734,7 @@ static int phy_info_parse(struct udevice *dev, struct mvpp2_port *port) int port_node = dev_of_offset(dev); int phy_node; u32 id; - u32 phyaddr = 0; + int phyaddr = 0; int fixed_link = 0; int ret; -- cgit v1.2.3 From c6561a467c9f9a77717ddc2ef296866a4d8a6843 Mon Sep 17 00:00:00 2001 From: Andrew Goodbody Date: Tue, 5 Aug 2025 15:18:19 +0100 Subject: net: mvpp2: Use field just assigned in error test In mvpp2_probe the code attempts to get a value for "gop-port-id" and assigns it to port->gop_id but it then tests port->id for being equal to -1. That is an impossible test as port->id is a field of type u8 so cannot be negative. Change the test to port->gop_id. This issue was found by Smatch. Signed-off-by: Andrew Goodbody --- drivers/net/mvpp2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/mvpp2.c b/drivers/net/mvpp2.c index 3a3510f603a..f9e979c4d58 100644 --- a/drivers/net/mvpp2.c +++ b/drivers/net/mvpp2.c @@ -5353,7 +5353,7 @@ static int mvpp2_probe(struct udevice *dev) } else { port->gop_id = fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev), "gop-port-id", -1); - if (port->id == -1) { + if (port->gop_id == -1) { dev_err(dev, "missing gop-port-id value\n"); return -EINVAL; } -- cgit v1.2.3 From 6bc6fec3b33f3c14f14493783db9258ac9938062 Mon Sep 17 00:00:00 2001 From: Andrew Goodbody Date: Tue, 5 Aug 2025 15:53:34 +0100 Subject: net: octeontx2: Restore default value for err In nix_lf_setup there is a default value assigned to err in case an error is detected. However this default value will be overwritten in the for loop so that later code does not return an error code from the function. Add a new assignment to restore err to the default error code. This issue was found by Smatch. Signed-off-by: Andrew Goodbody --- drivers/net/octeontx2/nix.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/net/octeontx2/nix.c b/drivers/net/octeontx2/nix.c index f596b6bca87..87d1f7a5dbf 100644 --- a/drivers/net/octeontx2/nix.c +++ b/drivers/net/octeontx2/nix.c @@ -298,6 +298,8 @@ int nix_lf_setup(struct nix *nix) goto error; } + err = -1; + /* Alloc memory for Qints HW contexts */ nix->qint_base = nix_memalloc(nix_af->qints, nix_af->qint_ctx_sz, "Qint CTX"); -- cgit v1.2.3 From 425f9839f3c2922a36efaefa53833f0abe681be0 Mon Sep 17 00:00:00 2001 From: Andrew Goodbody Date: Tue, 5 Aug 2025 15:53:35 +0100 Subject: net: octeontx2: NULL check before dereference In rvu_af_init if the code fails to allocate memory for nix_af it will take the error path with nix_af == NULL which will dereference nix_af. Add the appropriate NULL check. This issue was found by Smatch. Signed-off-by: Andrew Goodbody --- drivers/net/octeontx2/rvu_af.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/octeontx2/rvu_af.c b/drivers/net/octeontx2/rvu_af.c index 0d3a9ffe9ee..7bdfbc52e3b 100644 --- a/drivers/net/octeontx2/rvu_af.c +++ b/drivers/net/octeontx2/rvu_af.c @@ -114,7 +114,7 @@ struct nix_af *rvu_af_init(struct rvu_af *rvu_af) return nix_af; error: - if (nix_af->npa_af) { + if (nix_af && nix_af->npa_af) { free(nix_af->npa_af); memset(nix_af, 0, sizeof(*nix_af)); } -- cgit v1.2.3 From 2cb9fef65bbb7535c1e27cef3122bb0b43e38b68 Mon Sep 17 00:00:00 2001 From: Andrew Goodbody Date: Fri, 1 Aug 2025 12:59:40 +0100 Subject: net: cortina_ni: Fix typo accessing wrong phy In ca_phy_probe when checking for an external phy it uses a field from the internal phy due to what is assumed to be a copy/paste typo. Make the obvious fix to use the field from the external phy. This issue was found by Smatch. Signed-off-by: Andrew Goodbody --- drivers/net/cortina_ni.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/cortina_ni.c b/drivers/net/cortina_ni.c index 79026882800..21b7089176c 100644 --- a/drivers/net/cortina_ni.c +++ b/drivers/net/cortina_ni.c @@ -499,7 +499,7 @@ static int ca_phy_probe(struct udevice *dev) dev, priv->phy_interface); if (ext_phydev) { ext_phydev->supported &= PHY_GBIT_FEATURES; - ext_phydev->advertising = int_phydev->supported; + ext_phydev->advertising = ext_phydev->supported; phy_config(ext_phydev); } else { printf("CA NI %s: There is no external phy device\n", __func__); -- cgit v1.2.3 From 5deb50f749659746233e08060b457c9cf9986f9c Mon Sep 17 00:00:00 2001 From: Andrew Goodbody Date: Tue, 5 Aug 2025 11:34:29 +0100 Subject: net: ks8851_mll: Remove unreachable code In ks8851_mll_detect_chip the if..else code detects the case of (val & 0xfff0) != CIDER_ID and returns if found. So testing for this again will always fail and the code is unreachable. Just remove the test and code block. This issue was found by Smatch. Signed-off-by: Andrew Goodbody --- drivers/net/ks8851_mll.c | 5 ----- 1 file changed, 5 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ks8851_mll.c b/drivers/net/ks8851_mll.c index cc2e826257a..2c956154d09 100644 --- a/drivers/net/ks8851_mll.c +++ b/drivers/net/ks8851_mll.c @@ -347,11 +347,6 @@ static int ks8851_mll_detect_chip(struct ks_net *ks) debug("Read back KS8851 id 0x%x\n", val); - if ((val & 0xfff0) != CIDER_ID) { - printf(DRIVERNAME ": Unknown chip ID %04x\n", val); - return -1; - } - return 0; } -- cgit v1.2.3 From 783ea37c7b52ae088e8c64581fbe412b5dc9a878 Mon Sep 17 00:00:00 2001 From: Andrew Goodbody Date: Mon, 18 Aug 2025 11:44:28 +0100 Subject: phy: cadence: sierra: Remove variable that is not assigned to In cdns_sierra_pll_bind_of_clocks the variable 'i' is declared but never assigned to before its value is used in a dev_err. Replace clk_names[i] by the name passed to device_bind(), i.e., "pll_mux_clk". With that, the clk_names[] array is unused and can therefore be removed. This issue was found by Smatch. Signed-off-by: Andrew Goodbody [jf: update description] Signed-off-by: Jerome Forissier --- drivers/phy/cadence/phy-cadence-sierra.c | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/phy/cadence/phy-cadence-sierra.c b/drivers/phy/cadence/phy-cadence-sierra.c index 2c9d5a12127..bd7ab9d1b77 100644 --- a/drivers/phy/cadence/phy-cadence-sierra.c +++ b/drivers/phy/cadence/phy-cadence-sierra.c @@ -225,11 +225,6 @@ static const struct reg_field pllctrl_lock = static const struct reg_field phy_iso_link_ctrl_1 = REG_FIELD(SIERRA_PHY_ISO_LINK_CTRL, 1, 1); -static const char * const clk_names[] = { - [CDNS_SIERRA_PLL_CMNLC] = "pll_cmnlc", - [CDNS_SIERRA_PLL_CMNLC1] = "pll_cmnlc1", -}; - enum cdns_sierra_cmn_plllc { CMN_PLLLC, CMN_PLLLC1, @@ -602,7 +597,7 @@ static int cdns_sierra_pll_bind_of_clocks(struct cdns_sierra_phy *sp) struct udevice *dev = sp->dev; struct driver *cdns_sierra_clk_drv; struct cdns_sierra_pll_mux_sel *data = pll_clk_mux_sel; - int i, rc; + int rc; cdns_sierra_clk_drv = lists_driver_lookup_name("cdns_sierra_mux_clk"); if (!cdns_sierra_clk_drv) { @@ -612,10 +607,8 @@ static int cdns_sierra_pll_bind_of_clocks(struct cdns_sierra_phy *sp) rc = device_bind(dev, cdns_sierra_clk_drv, "pll_mux_clk", data, dev_ofnode(dev), NULL); - if (rc) { - dev_err(dev, "cannot bind driver for clock %s\n", - clk_names[i]); - } + if (rc) + dev_err(dev, "cannot bind driver for clock pll_mux_clk\n"); return 0; } -- cgit v1.2.3 From c4526c390a3c4ea1c4f244b6436ebbb74902769a Mon Sep 17 00:00:00 2001 From: Andrew Goodbody Date: Mon, 18 Aug 2025 11:44:29 +0100 Subject: phy: cadence: torrent: Set an error code for return In cdns_torrent_phy_probe the test for too many lanes configured does not set an error code before taking the error path. This could lead to a silent failure if the calling code does not detect the error. Add the code to return -EINVAL in this case. This issue was found by Smatch. Signed-off-by: Andrew Goodbody --- drivers/phy/cadence/phy-cadence-torrent.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/phy/cadence/phy-cadence-torrent.c b/drivers/phy/cadence/phy-cadence-torrent.c index 1f566d082f9..28fe026223c 100644 --- a/drivers/phy/cadence/phy-cadence-torrent.c +++ b/drivers/phy/cadence/phy-cadence-torrent.c @@ -719,6 +719,7 @@ static int cdns_torrent_phy_probe(struct udevice *dev) if (total_num_lanes > MAX_NUM_LANES) { dev_err(dev, "Invalid lane configuration\n"); + ret = -EINVAL; goto put_lnk_rst; } -- cgit v1.2.3 From b34b18a2c936c02c42c1c66bee274fcc96e25c57 Mon Sep 17 00:00:00 2001 From: Andrew Goodbody Date: Fri, 8 Aug 2025 12:32:36 +0100 Subject: ram: renesas: dbsc5: Fix off by 1 errors In dbsc5_read_vref_training the arrays dvw_min_byte0_table and dvw_min_byte1_table have 128 elements per channel. The variable vref_stop_index is limited to be a maximum of 128. This means that the index used to access the arrays must use a test of '< vref_stop_index' rather than '<= vref_stop_index' in order to prevent out of bounds accesses to the arrays. This issue was found by Smatch. Signed-off-by: Andrew Goodbody Reviewed-by: Marek Vasut Tested-by: Marek Vasut --- drivers/ram/renesas/dbsc5/dram.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/ram/renesas/dbsc5/dram.c b/drivers/ram/renesas/dbsc5/dram.c index ca8a7fb4783..3ed02e11f9e 100644 --- a/drivers/ram/renesas/dbsc5/dram.c +++ b/drivers/ram/renesas/dbsc5/dram.c @@ -3735,7 +3735,7 @@ static u32 dbsc5_read_vref_training(struct udevice *dev) if (vref_stop_index > 0x80) return 0; - for (i = 0; i <= vref_stop_index; i++) { + for (i = 0; i < vref_stop_index; i++) { r_foreach_vch(dev, ch) { reg = dbsc5_ddr_getval_slice(dev, ch, 0, PHY_PAD_VREF_CTRL_DQ); reg &= 0xF << 10; @@ -3819,7 +3819,7 @@ static u32 dbsc5_read_vref_training(struct udevice *dev) best_vref_byte0_index = 0; best_dvw_min_byte0 = dvw_min_byte0_table[ch][0]; - for (i = 0; i <= vref_stop_index; i++) { + for (i = 0; i < vref_stop_index; i++) { if (best_dvw_min_byte0 >= dvw_min_byte0_table[ch][i]) continue; @@ -3858,7 +3858,7 @@ static u32 dbsc5_read_vref_training(struct udevice *dev) vref_outlier = dbsc5_ddr_getval_slice(dev, ch, 0, PHY_RDLVL_VREF_OUTLIER); best_upper_vref = best_vref_byte0; outlier_cnt = vref_outlier; - for (i = best_vref_byte0_index; i <= vref_stop_index; i++) { + for (i = best_vref_byte0_index; i < vref_stop_index; i++) { if (dvw_min_byte0_table[ch][i] <= 0) break; @@ -3879,7 +3879,7 @@ static u32 dbsc5_read_vref_training(struct udevice *dev) best_vref_byte1 = vref_start; best_vref_byte1_index = 0; best_dvw_min_byte1 = dvw_min_byte1_table[ch][0]; - for (i = 0; i <= vref_stop_index; i++) { + for (i = 0; i < vref_stop_index; i++) { if (best_dvw_min_byte1 >= dvw_min_byte1_table[ch][i]) continue; @@ -3918,7 +3918,7 @@ static u32 dbsc5_read_vref_training(struct udevice *dev) vref_outlier = dbsc5_ddr_getval_slice(dev, ch, 1, PHY_RDLVL_VREF_OUTLIER); best_upper_vref = best_vref_byte1; outlier_cnt = vref_outlier; - for (i = best_vref_byte1_index; i <= vref_stop_index; i++) { + for (i = best_vref_byte1_index; i < vref_stop_index; i++) { if (dvw_min_byte1_table[ch][i] <= 0) break; -- cgit v1.2.3 From 5d542302230fec4edf6443aac25a442b3245306a Mon Sep 17 00:00:00 2001 From: Dinesh Maniyam Date: Tue, 19 Aug 2025 16:35:09 +0800 Subject: mtd: nand: cadence: Fix device assignment to avoid warm reset issue MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The driver currently does: mtd->dev->parent = cadence->dev; This works in Linux because `struct mtd_info` embeds a `struct device`, so `mtd->dev` is always valid and its `.parent` can be set. In U-Boot, however, `mtd->dev` is only a pointer to a `struct udevice`. Dereferencing it before assignment is invalid, which breaks the device hierarchy. As a result, consumers relying on `mtd->dev` (e.g. partition parser, reset and re-init paths) operate on a dangling pointer. This leads to failures during warm reset when the NAND device is accessed again. Fix by assigning the device pointer directly: mtd->dev = cadence->dev; This matches U-Boot’s device model, preserves a valid hierarchy, and resolves the warm reset issue on Cadence NAND. Fixes: ebc41cad ("drivers: mtd: nand: Add driver for Cadence Nand") Signed-off-by: Dinesh Maniyam Signed-off-by: Michael Trimarchi --- drivers/mtd/nand/raw/cadence_nand.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/mtd/nand/raw/cadence_nand.c b/drivers/mtd/nand/raw/cadence_nand.c index 27aa7f97a45..4771440d1de 100644 --- a/drivers/mtd/nand/raw/cadence_nand.c +++ b/drivers/mtd/nand/raw/cadence_nand.c @@ -2196,7 +2196,7 @@ static int cadence_nand_chip_init(struct cadence_nand_info *cadence, ofnode node chip->controller = &cadence->controller; nand_set_flash_node(chip, node); mtd = nand_to_mtd(chip); - mtd->dev->parent = cadence->dev; + mtd->dev = cadence->dev; chip->options |= NAND_BUSWIDTH_AUTO; chip->select_chip = cadence_nand_select_chip; -- cgit v1.2.3 From 6b156c62ced25d3f8aed64c81e471353b56d0f2c Mon Sep 17 00:00:00 2001 From: Andrew Goodbody Date: Thu, 31 Jul 2025 17:21:32 +0100 Subject: mtd: nand: Do not dereference before NULL check In nanddev_init mtd and memorg are assigned values that dereference nand but this happens before a NULL check for nand. Move the assignments after the NULL check. This issue was found by Smatch. Signed-off-by: Andrew Goodbody Signed-off-by: Michael Trimarchi --- drivers/mtd/nand/core.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/mtd/nand/core.c b/drivers/mtd/nand/core.c index 472ad0bdefb..01ff6e3befa 100644 --- a/drivers/mtd/nand/core.c +++ b/drivers/mtd/nand/core.c @@ -201,8 +201,8 @@ EXPORT_SYMBOL_GPL(nanddev_mtd_erase); int nanddev_init(struct nand_device *nand, const struct nand_ops *ops, struct module *owner) { - struct mtd_info *mtd = nanddev_to_mtd(nand); - struct nand_memory_organization *memorg = nanddev_get_memorg(nand); + struct mtd_info *mtd; + struct nand_memory_organization *memorg; if (!nand || !ops) return -EINVAL; @@ -210,6 +210,9 @@ int nanddev_init(struct nand_device *nand, const struct nand_ops *ops, if (!ops->erase || !ops->markbad || !ops->isbad) return -EINVAL; + mtd = nanddev_to_mtd(nand); + memorg = nanddev_get_memorg(nand); + if (!memorg->bits_per_cell || !memorg->pagesize || !memorg->pages_per_eraseblock || !memorg->eraseblocks_per_lun || !memorg->planes_per_lun || !memorg->luns_per_target || -- cgit v1.2.3 From edbcf8e3590fb640b4709841605b0a58ef8aa7f1 Mon Sep 17 00:00:00 2001 From: Tim Harvey Date: Wed, 9 Jul 2025 08:24:08 -0700 Subject: phy: phy-imx8mq-usb: Add support for i.MX95 USB3 PHY Add initial support for i.MX95 USB.30 PHY, which is similar to the i.MX8MQ and i.MX8MP USB PHY. The i.MX95 USB3 PHY has a Type-C Assist block (TCA) consisting of two functional blocks (XBar assist and VBus assist) and is documented in the i.MX95 RM Chapter 163.3.8 Type-C assist (TCA) block. Instead of relying on an external MUX for Type-C plug orientation the XBar can handle the flip internally. Add initial support for i.MX95 by: - allowing the driver to be enabled i.MX95 - resetting the XBar - configuring the TCA in System Configuration mode (which was determined to be necessary to enable the PHY in device-mode) Follow-on support will need to be added to steer the XBar based on either board design (if only one pair is brought out) or if used with a Type-C controller. Signed-off-by: Tim Harvey Tested-by: Alice Guo --- drivers/phy/Kconfig | 6 +-- drivers/phy/phy-imx8mq-usb.c | 91 +++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 93 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig index c297fa03ea7..d36a5f00ef8 100644 --- a/drivers/phy/Kconfig +++ b/drivers/phy/Kconfig @@ -289,11 +289,11 @@ config PHY_NPCM_USB Support the USB PHY in NPCM SoCs config PHY_IMX8MQ_USB - bool "NXP i.MX8MQ/i.MX8MP USB PHY Driver" + bool "NXP i.MX8MQ/i.MX8MP/i.MX95 USB PHY Driver" depends on PHY - depends on IMX8MQ || IMX8MP + depends on IMX8MQ || IMX8MP || IMX95 help - Support the USB3.0 PHY in NXP i.MX8MQ or i.MX8MP SoC + Support the USB3.0 PHY in NXP i.MX8MQ, i.MX8MP, and i.MX95 SoC config PHY_IMX8M_PCIE bool "NXP i.MX8MM/i.MX8MP PCIe PHY Driver" diff --git a/drivers/phy/phy-imx8mq-usb.c b/drivers/phy/phy-imx8mq-usb.c index 75763046adc..387db843c50 100644 --- a/drivers/phy/phy-imx8mq-usb.c +++ b/drivers/phy/phy-imx8mq-usb.c @@ -71,9 +71,57 @@ #define PHY_STS0_FSVPLUS BIT(3) #define PHY_STS0_FSVMINUS BIT(2) +#define TCA_CLK_RST 0x00 +#define TCA_CLK_RST_SW BIT(9) +#define TCA_CLK_RST_REF_CLK_EN BIT(1) +#define TCA_CLK_RST_SUSPEND_CLK_EN BIT(0) + +#define TCA_INTR_EN 0x04 +#define TCA_INTR_STS 0x08 + +#define TCA_GCFG 0x10 +#define TCA_GCFG_ROLE_HSTDEV BIT(4) +#define TCA_GCFG_OP_MODE GENMASK(1, 0) +#define TCA_GCFG_OP_MODE_SYSMODE 0 +#define TCA_GCFG_OP_MODE_SYNCMODE 1 + +#define TCA_TCPC 0x14 +#define TCA_TCPC_VALID BIT(4) +#define TCA_TCPC_LOW_POWER_EN BIT(3) +#define TCA_TCPC_ORIENTATION_NORMAL BIT(2) +#define TCA_TCPC_MUX_CONTRL GENMASK(1, 0) +#define TCA_TCPC_MUX_CONTRL_NO_CONN 0 +#define TCA_TCPC_MUX_CONTRL_USB_CONN 1 + +#define TCA_SYSMODE_CFG 0x18 +#define TCA_SYSMODE_TCPC_DISABLE BIT(3) +#define TCA_SYSMODE_TCPC_FLIP BIT(2) + +#define TCA_CTRLSYNCMODE_CFG0 0x20 +#define TCA_CTRLSYNCMODE_CFG1 0x20 + +#define TCA_PSTATE 0x30 +#define TCA_PSTATE_CM_STS BIT(4) +#define TCA_PSTATE_TX_STS BIT(3) +#define TCA_PSTATE_RX_PLL_STS BIT(2) +#define TCA_PSTATE_PIPE0_POWER_DOWN GENMASK(1, 0) + +#define TCA_GEN_STATUS 0x34 +#define TCA_GEN_DEV_POR BIT(12) +#define TCA_GEN_REF_CLK_SEL BIT(8) +#define TCA_GEN_TYPEC_FLIP_INVERT BIT(4) +#define TCA_GEN_PHY_TYPEC_DISABLE BIT(3) +#define TCA_GEN_PHY_TYPEC_FLIP BIT(2) + +#define TCA_VBUS_CTRL 0x40 +#define TCA_VBUS_STATUS 0x44 + +#define TCA_INFO 0xfc + enum imx8mpq_phy_type { IMX8MQ_PHY, IMX8MP_PHY, + IMX95_PHY, }; struct imx8mq_usb_phy { @@ -81,14 +129,49 @@ struct imx8mq_usb_phy { void __iomem *base; enum imx8mpq_phy_type type; struct udevice *vbus_supply; + void __iomem *tca_base; }; static const struct udevice_id imx8mq_usb_phy_of_match[] = { { .compatible = "fsl,imx8mq-usb-phy", .data = IMX8MQ_PHY }, { .compatible = "fsl,imx8mp-usb-phy", .data = IMX8MP_PHY }, + { .compatible = "fsl,imx95-usb-phy", .data = IMX95_PHY }, {}, }; +static void tca_blk_init(struct phy *usb_phy) +{ + struct udevice *dev = usb_phy->dev; + struct imx8mq_usb_phy *imx_phy = dev_get_priv(dev); + void __iomem *base = imx_phy->tca_base; + u32 val; + + /* reset XBar block */ + val = readl(base + TCA_CLK_RST); + val &= ~TCA_CLK_RST_SW; + writel(val, base + TCA_CLK_RST); + + udelay(100); + + /* clear reset */ + val |= TCA_CLK_RST_SW; + writel(val, base + TCA_CLK_RST); + + /* + * use Controller Synced Mode for TCA low power enable and + * put PHY to USB safe state. + */ + val = FIELD_PREP(TCA_GCFG_OP_MODE, TCA_GCFG_OP_MODE_SYNCMODE); + writel(val, base + TCA_GCFG); + + val = TCA_TCPC_VALID | TCA_TCPC_LOW_POWER_EN; + writel(val, base + TCA_TCPC); + + /* use System Configuration Mode for TCA mux control. */ + val = FIELD_PREP(TCA_GCFG_OP_MODE, TCA_GCFG_OP_MODE_SYSMODE); + writel(val, base + TCA_GCFG); +} + static int imx8mq_usb_phy_init(struct phy *usb_phy) { struct udevice *dev = usb_phy->dev; @@ -154,6 +237,9 @@ static int imx8mp_usb_phy_init(struct phy *usb_phy) value &= ~(PHY_CTRL1_RESET | PHY_CTRL1_ATERESET); writel(value, imx_phy->base + PHY_CTRL1); + if (imx_phy->tca_base) + tca_blk_init(usb_phy); + return 0; } @@ -162,7 +248,7 @@ static int imx8mpq_usb_phy_init(struct phy *usb_phy) struct udevice *dev = usb_phy->dev; struct imx8mq_usb_phy *imx_phy = dev_get_priv(dev); - if (imx_phy->type == IMX8MP_PHY) + if (imx_phy->type == IMX8MP_PHY || imx_phy->type == IMX95_PHY) return imx8mp_usb_phy_init(usb_phy); else return imx8mq_usb_phy_init(usb_phy); @@ -264,6 +350,9 @@ int imx8mq_usb_phy_probe(struct udevice *dev) } } + if (priv->type == IMX95_PHY) + priv->tca_base = dev_read_addr_index_ptr(dev, 1); + return 0; } -- cgit v1.2.3 From 445aad45f47a19860eff5b09c4c570285265318a Mon Sep 17 00:00:00 2001 From: Tim Harvey Date: Mon, 21 Jul 2025 11:02:05 -0700 Subject: usb: ehci-mx6: Add i.MX95 OTG support When the usb node is defined dr_mode="otg" ehci_usb_phy_mode() is called to determine the mode from status registers. The IMX95RM does not currently define the USBNC STATUS register but it is assumed to be an omission as the first three registers are defined. It has been expirimentally verified that the USBNC_PHY_STATUS register at offset 0x23C bit4 (USBNC_PHYSTATUS_ID_DIG) reads 0 when USB_ID is GND and 1 when floating. Use is_imx9() as this driver works for i.MX91, i.MX93 and i.MX95 and all of these determine the role based on the USBNC_PHY_STATUS register. Fixes: 801b5fafd35d "(usb: ehci-mx6: Add i.MX95 support") Signed-off-by: Tim Harvey Reviewed-by: Alice Guo Reviewed-by: Peng Fan Reviewed-by: Fabio Estevam --- drivers/usb/host/ehci-mx6.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/host/ehci-mx6.c b/drivers/usb/host/ehci-mx6.c index a8748cef7ad..25907f22612 100644 --- a/drivers/usb/host/ehci-mx6.c +++ b/drivers/usb/host/ehci-mx6.c @@ -537,7 +537,7 @@ static int ehci_usb_phy_mode(struct udevice *dev) plat->init_type = USB_INIT_DEVICE; else plat->init_type = USB_INIT_HOST; - } else if (is_mx7() || is_imx8mm() || is_imx8mn() || is_imx93()) { + } else if (is_mx7() || is_imx8mm() || is_imx8mn() || is_imx9()) { phy_status = (void __iomem *)(addr + USBNC_PHY_STATUS_OFFSET); val = readl(phy_status); -- cgit v1.2.3 From 332714b905923d9e97a2cc7590dfc41e49980d35 Mon Sep 17 00:00:00 2001 From: Patrick Delaunay Date: Wed, 23 Jul 2025 17:09:16 +0200 Subject: usb: dwc2: fix reset logic in dwc2_core_reset Use GUSBCFG_FORCEHOSTMODE to detected the HOST forced mode as it is done in the Linux driver drivers/usb/dwc2/core.c:dwc2_core_reset(). The host polling must be executed only if the current mode is host, either due to the force HOST mode (which persists after core reset) or the connector id pin. The GUSBCFG_FORCEDEVMODE bits is used to force the device mode (for example used on STM32MP1x platform) and when it is activated the DWC2 reset failed with the trace: "dwc2_core_reset: Waiting for GINTSTS_CURMODE_HOST timeout" Fixes: c5d685b8993c ("usb: dwc2: Unify flush and reset logic with v4.20a support") Signed-off-by: Patrick Delaunay Reviewed-by: Junhui Liu Tested-by: Patrice Chotard Reviewed-by: Marek Vasut --- drivers/usb/common/dwc2_core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/common/dwc2_core.c b/drivers/usb/common/dwc2_core.c index 63062d5cc94..37007134e5b 100644 --- a/drivers/usb/common/dwc2_core.c +++ b/drivers/usb/common/dwc2_core.c @@ -17,7 +17,7 @@ int dwc2_core_reset(struct dwc2_core_regs *regs) bool host_mode = false; if (!(readl(®s->global_regs.gotgctl) & GOTGCTL_CONID_B) || - (readl(®s->global_regs.gusbcfg) & GUSBCFG_FORCEDEVMODE)) + (readl(®s->global_regs.gusbcfg) & GUSBCFG_FORCEHOSTMODE)) host_mode = true; /* Core Soft Reset */ -- cgit v1.2.3 From 0d1c4fd514c13fbda3b3016cfa9ce00b01e42bf9 Mon Sep 17 00:00:00 2001 From: Andrew Goodbody Date: Mon, 28 Jul 2025 16:47:09 +0100 Subject: mailbox: zynqmp: Fix off by 1 errors Use resource_size to correctly calculate the size to pass to devm_ioremap and avoid the off by 1 errors previously present. This issue was found by Smatch. Signed-off-by: Andrew Goodbody Link: https://lore.kernel.org/r/20250728-zynqmp-ipi-v1-1-b2bd144a9521@linaro.org Signed-off-by: Michal Simek --- drivers/mailbox/zynqmp-ipi.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/mailbox/zynqmp-ipi.c b/drivers/mailbox/zynqmp-ipi.c index 851aa737c03..f62277385fb 100644 --- a/drivers/mailbox/zynqmp-ipi.c +++ b/drivers/mailbox/zynqmp-ipi.c @@ -188,7 +188,7 @@ static int zynqmp_ipi_dest_probe(struct udevice *dev) return -EINVAL; }; zynqmp->local_req_regs = devm_ioremap(dev, res.start, - (res.start - res.end)); + resource_size(&res)); if (!zynqmp->local_req_regs) return -EINVAL; @@ -197,7 +197,7 @@ static int zynqmp_ipi_dest_probe(struct udevice *dev) return -EINVAL; }; zynqmp->local_res_regs = devm_ioremap(dev, res.start, - (res.start - res.end)); + resource_size(&res)); if (!zynqmp->local_res_regs) return -EINVAL; @@ -206,7 +206,7 @@ static int zynqmp_ipi_dest_probe(struct udevice *dev) return -EINVAL; }; zynqmp->remote_req_regs = devm_ioremap(dev, res.start, - (res.start - res.end)); + resource_size(&res)); if (!zynqmp->remote_req_regs) return -EINVAL; @@ -215,7 +215,7 @@ static int zynqmp_ipi_dest_probe(struct udevice *dev) return -EINVAL; }; zynqmp->remote_res_regs = devm_ioremap(dev, res.start, - (res.start - res.end)); + resource_size(&res)); if (!zynqmp->remote_res_regs) return -EINVAL; -- cgit v1.2.3 From 7aac8439445793baa9313a7d5139b77f968b2885 Mon Sep 17 00:00:00 2001 From: Andrew Goodbody Date: Thu, 7 Aug 2025 11:04:04 +0100 Subject: pinctrl: zynqmp: Ensure ret is initialised In zynqmp_pinctrl_prepare_func_groups if called with func->ngroups == 0 then ret will not be assigned to before its value is returned on exit. Initialise ret to ensure it is always valid. This issue was found by Smatch. Signed-off-by: Andrew Goodbody Link: https://lore.kernel.org/r/20250807-pinctrl_misc-v1-3-eeb564a1b032@linaro.org Signed-off-by: Michal Simek --- drivers/pinctrl/pinctrl-zynqmp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/pinctrl/pinctrl-zynqmp.c b/drivers/pinctrl/pinctrl-zynqmp.c index 6fa203a3b86..27dadbff8ca 100644 --- a/drivers/pinctrl/pinctrl-zynqmp.c +++ b/drivers/pinctrl/pinctrl-zynqmp.c @@ -204,7 +204,7 @@ static int zynqmp_pinctrl_prepare_func_groups(u32 fid, const char **fgroups; char name[MAX_GROUP_NAME_LEN]; u16 resp[NUM_GROUPS_PER_RESP] = {0}; - int ret, index, i; + int ret = 0, index, i; fgroups = kcalloc(func->ngroups, sizeof(*fgroups), GFP_KERNEL); if (!fgroups) -- cgit v1.2.3 From 6ce599f513172147362e8a2f7424837a2dd60e90 Mon Sep 17 00:00:00 2001 From: Andrew Goodbody Date: Thu, 7 Aug 2025 11:04:05 +0100 Subject: pinctrl: zynqmp: Avoid using uninitialised variable In zynqmp_pinconf_set if param is PIN_CFG_IOSTANDARD or PIN_CONFIG_POWER_SOURCE and zynqmp_pm_pinctrl_get_config returns an error then value will not be assigned to when its value is tested to be not equal to arg. Add code to only test value not equal to arg if ret is false. This issue was found by Smatch. Signed-off-by: Andrew Goodbody Link: https://lore.kernel.org/r/20250807-pinctrl_misc-v1-4-eeb564a1b032@linaro.org Signed-off-by: Michal Simek --- drivers/pinctrl/pinctrl-zynqmp.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/pinctrl/pinctrl-zynqmp.c b/drivers/pinctrl/pinctrl-zynqmp.c index 27dadbff8ca..665b76a7d4d 100644 --- a/drivers/pinctrl/pinctrl-zynqmp.c +++ b/drivers/pinctrl/pinctrl-zynqmp.c @@ -460,14 +460,14 @@ static int zynqmp_pinconf_set(struct udevice *dev, unsigned int pin, case PIN_CFG_IOSTANDARD: param = PM_PINCTRL_CONFIG_VOLTAGE_STATUS; ret = zynqmp_pm_pinctrl_get_config(pin, param, &value); - if (arg != value) + if (!ret && arg != value) dev_warn(dev, "Invalid IO Standard requested for pin %d\n", pin); break; case PIN_CONFIG_POWER_SOURCE: param = PM_PINCTRL_CONFIG_VOLTAGE_STATUS; ret = zynqmp_pm_pinctrl_get_config(pin, param, &value); - if (arg != value) + if (!ret && arg != value) dev_warn(dev, "Invalid IO Standard requested for pin %d\n", pin); break; -- cgit v1.2.3 From 3b765ae05005249b91a737cd620e0577a8d5b9ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Frank=20B=C3=B6wingloh?= Date: Fri, 8 Aug 2025 14:31:34 +0200 Subject: soc: xilinx: zynqmp: Fix zu1cg device detection MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently u-boot displayed a zu1cg soc as "Chip: zu1eg". A value of 0468_8093h in the IDCODE (CSU) Register defines a ZU1 soc not only for the EG family but also for the CG family as described in the Xilinx Zynq UltraScale+ UG1085 documentation in Table 1-2. Signed-off-by: Frank Böwingloh Cc: Michal Simek Link: https://lore.kernel.org/r/20250808123134.636-1-f.boewingloh@beckhoff.com Signed-off-by: Michal Simek --- drivers/soc/soc_xilinx_zynqmp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/soc/soc_xilinx_zynqmp.c b/drivers/soc/soc_xilinx_zynqmp.c index 0c45c781fef..4b69ff3de13 100644 --- a/drivers/soc/soc_xilinx_zynqmp.c +++ b/drivers/soc/soc_xilinx_zynqmp.c @@ -63,7 +63,7 @@ static const struct zynqmp_device zynqmp_devices[] = { { .id = 0x04688093, .device = 1, - .variants = ZYNQMP_VARIANT_EG, + .variants = ZYNQMP_VARIANT_EG | ZYNQMP_VARIANT_CG, }, { .id = 0x04689093, -- cgit v1.2.3 From 818f6002e1429aa42f7efda06d3fe742ebf65e93 Mon Sep 17 00:00:00 2001 From: Alexander Dahl Date: Mon, 4 Aug 2025 11:08:16 +0200 Subject: fpga: cyclon2: Remove message never printed else branch is never reached. Print "Done." anyways to keep behaviour. Addresses-Coverity-ID: 583148 Link: https://lore.kernel.org/u-boot/20250725132645.GA1807455@bill-the-cat/ Fixes: f0ff4692ff33 ("Add FPGA Altera Cyclone 2 support Patch by Heiko Schocher, 15 Aug 2006") Signed-off-by: Alexander Dahl Link: https://lore.kernel.org/r/20250804090816.42603-1-ada@thorsis.com Signed-off-by: Michal Simek --- drivers/fpga/cyclon2.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/fpga/cyclon2.c b/drivers/fpga/cyclon2.c index 7e78d6e2d6c..1c464c1e912 100644 --- a/drivers/fpga/cyclon2.c +++ b/drivers/fpga/cyclon2.c @@ -174,10 +174,7 @@ static int CYC2_ps_load(Altera_desc *desc, const void *buf, size_t bsize) ret_val = FPGA_SUCCESS; #ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK - if (ret_val == FPGA_SUCCESS) - puts("Done.\n"); - else - puts("Fail.\n"); + puts("Done.\n"); #endif /* -- cgit v1.2.3 From 7fc04c9a82e858a1d042d8c7b008831c28d5965e Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Mon, 28 Jul 2025 09:07:52 +0200 Subject: fpga: xilinx: Check valid desc structure FPGA validation can fail and return value needs to be checked. Addresses-Coverity-ID: CID 583150: Null pointer dereferences (NULL_RETURNS) Signed-off-by: Michal Simek Link: https://lore.kernel.org/r/876b6f8dbc99ca305460183dbd18635a35ccc989.1753686468.git.michal.simek@amd.com --- drivers/fpga/xilinx.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/fpga/xilinx.c b/drivers/fpga/xilinx.c index 28c68faba55..25b348648ef 100644 --- a/drivers/fpga/xilinx.c +++ b/drivers/fpga/xilinx.c @@ -50,6 +50,9 @@ int fpga_loadbitstream(int devnum, char *fpgadata, size_t size, dataptr = (unsigned char *)fpgadata; /* Find out fpga_description */ desc = fpga_validate(devnum, dataptr, 0); + if (!desc) + return FPGA_FAIL; + /* Assign xilinx device description */ xdesc = desc->devdesc; -- cgit v1.2.3 From 0870281a415d33b20ca4a2ff072ab55c1b71bcb5 Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Mon, 28 Jul 2025 09:07:53 +0200 Subject: fpga: Remove ancient ACEX1K support Coverity (CID 583149) reports issue on code which is not enabled by any real platform that's why remove it completely. Acked-by: Alexander Dahl Signed-off-by: Michal Simek Link: https://lore.kernel.org/r/20fe425910b6266a2bf0555bda67f60c1dd3aa61.1753686468.git.michal.simek@amd.com --- drivers/fpga/ACEX1K.c | 245 -------------------------------------------------- drivers/fpga/Kconfig | 6 -- drivers/fpga/Makefile | 1 - drivers/fpga/altera.c | 5 +- 4 files changed, 1 insertion(+), 256 deletions(-) delete mode 100644 drivers/fpga/ACEX1K.c (limited to 'drivers') diff --git a/drivers/fpga/ACEX1K.c b/drivers/fpga/ACEX1K.c deleted file mode 100644 index e1514fc56d0..00000000000 --- a/drivers/fpga/ACEX1K.c +++ /dev/null @@ -1,245 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -/* - * (C) Copyright 2003 - * Steven Scholz, imc Measurement & Control, steven.scholz@imc-berlin.de - * - * (C) Copyright 2002 - * Rich Ireland, Enterasys Networks, rireland@enterasys.com. - */ - -#define LOG_CATEGORY UCLASS_FPGA - -#include /* core U-Boot definitions */ -#include -#include -#include /* ACEX device family */ -#include -#include - -/* Note: The assumption is that we cannot possibly run fast enough to - * overrun the device (the Slave Parallel mode can free run at 50MHz). - * If there is a need to operate slower, define CFG_FPGA_DELAY in - * the board config file to slow things down. - */ -#ifndef CFG_FPGA_DELAY -#define CFG_FPGA_DELAY() -#endif - -#ifndef CFG_SYS_FPGA_WAIT -#define CFG_SYS_FPGA_WAIT CONFIG_SYS_HZ/10 /* 100 ms */ -#endif - -static int ACEX1K_ps_load(Altera_desc *desc, const void *buf, size_t bsize); -static int ACEX1K_ps_dump(Altera_desc *desc, const void *buf, size_t bsize); -/* static int ACEX1K_ps_info(Altera_desc *desc); */ - -/* ------------------------------------------------------------------------- */ -/* ACEX1K Generic Implementation */ -int ACEX1K_load(Altera_desc *desc, const void *buf, size_t bsize) -{ - int ret_val = FPGA_FAIL; - - switch (desc->iface) { - case passive_serial: - log_debug("Launching Passive Serial Loader\n"); - ret_val = ACEX1K_ps_load (desc, buf, bsize); - break; - - /* Add new interface types here */ - - default: - printf ("%s: Unsupported interface type, %d\n", - __FUNCTION__, desc->iface); - } - - return ret_val; -} - -int ACEX1K_dump(Altera_desc *desc, const void *buf, size_t bsize) -{ - int ret_val = FPGA_FAIL; - - switch (desc->iface) { - case passive_serial: - log_debug("Launching Passive Serial Dump\n"); - ret_val = ACEX1K_ps_dump (desc, buf, bsize); - break; - - /* Add new interface types here */ - - default: - printf ("%s: Unsupported interface type, %d\n", - __FUNCTION__, desc->iface); - } - - return ret_val; -} - -int ACEX1K_info( Altera_desc *desc ) -{ - return FPGA_SUCCESS; -} - -/* ------------------------------------------------------------------------- */ -/* ACEX1K Passive Serial Generic Implementation */ - -static int ACEX1K_ps_load(Altera_desc *desc, const void *buf, size_t bsize) -{ - int ret_val = FPGA_FAIL; /* assume the worst */ - Altera_ACEX1K_Passive_Serial_fns *fn = desc->iface_fns; - int i; - - log_debug("start with interface functions @ 0x%p\n", fn); - - if (fn) { - size_t bytecount = 0; - unsigned char *data = (unsigned char *) buf; - int cookie = desc->cookie; /* make a local copy */ - unsigned long ts; /* timestamp */ - - log_debug("Function Table:\n" - "ptr:\t0x%p\n" - "struct: 0x%p\n" - "config:\t0x%p\n" - "status:\t0x%p\n" - "clk:\t0x%p\n" - "data:\t0x%p\n" - "done:\t0x%p\n\n", - &fn, fn, fn->config, fn->status, - fn->clk, fn->data, fn->done); -#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK - printf ("Loading FPGA Device %d...", cookie); -#endif - - /* - * Run the pre configuration function if there is one. - */ - if (*fn->pre) { - (*fn->pre) (cookie); - } - - /* Establish the initial state */ - (*fn->config) (true, true, cookie); /* Assert nCONFIG */ - - udelay(2); /* T_cfg > 2us */ - - /* nSTATUS should be asserted now */ - (*fn->done) (cookie); - if ( !(*fn->status) (cookie) ) { - puts ("** nSTATUS is not asserted.\n"); - (*fn->abort) (cookie); - return FPGA_FAIL; - } - - (*fn->config) (false, true, cookie); /* Deassert nCONFIG */ - udelay(2); /* T_cf2st1 < 4us */ - - /* Wait for nSTATUS to be released (i.e. deasserted) */ - ts = get_timer (0); /* get current time */ - do { - CFG_FPGA_DELAY (); - if (get_timer (ts) > CFG_SYS_FPGA_WAIT) { /* check the time */ - puts ("** Timeout waiting for STATUS to go high.\n"); - (*fn->abort) (cookie); - return FPGA_FAIL; - } - (*fn->done) (cookie); - } while ((*fn->status) (cookie)); - - /* Get ready for the burn */ - CFG_FPGA_DELAY (); - - /* Load the data */ - while (bytecount < bsize) { - unsigned char val=0; -#ifdef CONFIG_SYS_FPGA_CHECK_CTRLC - if (ctrlc ()) { - (*fn->abort) (cookie); - return FPGA_FAIL; - } -#endif - /* Altera detects an error if INIT goes low (active) - while DONE is low (inactive) */ -#if 0 /* not yet implemented */ - if ((*fn->done) (cookie) == 0 && (*fn->init) (cookie)) { - puts ("** CRC error during FPGA load.\n"); - (*fn->abort) (cookie); - return (FPGA_FAIL); - } -#endif - val = data [bytecount ++ ]; - i = 8; - do { - /* Deassert the clock */ - (*fn->clk) (false, true, cookie); - CFG_FPGA_DELAY (); - /* Write data */ - (*fn->data) ((val & 0x01), true, cookie); - CFG_FPGA_DELAY (); - /* Assert the clock */ - (*fn->clk) (true, true, cookie); - CFG_FPGA_DELAY (); - val >>= 1; - i --; - } while (i > 0); - -#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK - if (bytecount % (bsize / 40) == 0) - putc ('.'); /* let them know we are alive */ -#endif - } - - CFG_FPGA_DELAY (); - -#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK - putc (' '); /* terminate the dotted line */ -#endif - - /* - * Checking FPGA's CONF_DONE signal - correctly booted ? - */ - - if ( ! (*fn->done) (cookie) ) { - puts ("** Booting failed! CONF_DONE is still deasserted.\n"); - (*fn->abort) (cookie); - return (FPGA_FAIL); - } - - /* - * "DCLK must be clocked an additional 10 times fpr ACEX 1K..." - */ - - for (i = 0; i < 12; i++) { - CFG_FPGA_DELAY (); - (*fn->clk) (true, true, cookie); /* Assert the clock pin */ - CFG_FPGA_DELAY (); - (*fn->clk) (false, true, cookie); /* Deassert the clock pin */ - } - - ret_val = FPGA_SUCCESS; - -#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK - if (ret_val == FPGA_SUCCESS) { - puts ("Done.\n"); - } - else { - puts ("Fail.\n"); - } -#endif - (*fn->post) (cookie); - - } else { - printf ("%s: NULL Interface function table!\n", __FUNCTION__); - } - - return ret_val; -} - -static int ACEX1K_ps_dump(Altera_desc *desc, const void *buf, size_t bsize) -{ - /* Readback is only available through the Slave Parallel and */ - /* boundary-scan interfaces. */ - printf ("%s: Passive Serial Dumping is unavailable\n", - __FUNCTION__); - return FPGA_FAIL; -} diff --git a/drivers/fpga/Kconfig b/drivers/fpga/Kconfig index 9456ca3149a..18e7d7c99a9 100644 --- a/drivers/fpga/Kconfig +++ b/drivers/fpga/Kconfig @@ -34,12 +34,6 @@ config FPGA_STRATIX_V help Say Y here to enable the Altera Stratix V FPGA specific driver. -config FPGA_ACEX1K - bool "Enable Altera ACEX 1K driver" - depends on FPGA_ALTERA - help - Say Y here to enable the Altera ACEX 1K FPGA specific driver. - config FPGA_CYCLON2 bool "Enable Altera FPGA driver for Cyclone II" depends on FPGA_ALTERA diff --git a/drivers/fpga/Makefile b/drivers/fpga/Makefile index 610c168fc35..6c779d5b5df 100644 --- a/drivers/fpga/Makefile +++ b/drivers/fpga/Makefile @@ -17,7 +17,6 @@ obj-$(CONFIG_FPGA_XILINX) += xilinx.o obj-$(CONFIG_FPGA_LATTICE) += ivm_core.o lattice.o ifdef CONFIG_FPGA_ALTERA obj-y += altera.o -obj-$(CONFIG_FPGA_ACEX1K) += ACEX1K.o obj-$(CONFIG_FPGA_CYCLON2) += cyclon2.o obj-$(CONFIG_FPGA_INTEL_SDM_MAILBOX) += intel_sdm_mb.o obj-$(CONFIG_FPGA_STRATIX_II) += stratixII.o diff --git a/drivers/fpga/altera.c b/drivers/fpga/altera.c index 64fda3a307c..4a9aa74357e 100644 --- a/drivers/fpga/altera.c +++ b/drivers/fpga/altera.c @@ -28,10 +28,7 @@ static const struct altera_fpga { int (*dump)(Altera_desc *, const void *, size_t); int (*info)(Altera_desc *); } altera_fpga[] = { -#if defined(CONFIG_FPGA_ACEX1K) - { Altera_ACEX1K, "ACEX1K", ACEX1K_load, ACEX1K_dump, ACEX1K_info }, - { Altera_CYC2, "ACEX1K", ACEX1K_load, ACEX1K_dump, ACEX1K_info }, -#elif defined(CONFIG_FPGA_CYCLON2) +#if defined(CONFIG_FPGA_CYCLON2) { Altera_ACEX1K, "CycloneII", CYC2_load, CYC2_dump, CYC2_info }, { Altera_CYC2, "CycloneII", CYC2_load, CYC2_dump, CYC2_info }, #endif -- cgit v1.2.3 From 34762f6c007c53d8540c1cb8bcf02ccddedb704f Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Mon, 28 Jul 2025 09:07:54 +0200 Subject: fpga: lattice: Remove unused support There is no single platform which is using this driver that's why remove it completely. Some issues regarding this code are also reported by Coverity (CID 583143, 583144, 583145, 583146). Signed-off-by: Michal Simek Link: https://lore.kernel.org/r/367cd55ab8d9fb262ac23fe748babc6b2b59bee0.1753686468.git.michal.simek@amd.com --- drivers/fpga/Kconfig | 6 - drivers/fpga/Makefile | 1 - drivers/fpga/fpga.c | 23 - drivers/fpga/ivm_core.c | 3149 ----------------------------------------------- drivers/fpga/lattice.c | 379 ------ 5 files changed, 3558 deletions(-) delete mode 100644 drivers/fpga/ivm_core.c delete mode 100644 drivers/fpga/lattice.c (limited to 'drivers') diff --git a/drivers/fpga/Kconfig b/drivers/fpga/Kconfig index 18e7d7c99a9..e2593057fac 100644 --- a/drivers/fpga/Kconfig +++ b/drivers/fpga/Kconfig @@ -55,12 +55,6 @@ config FPGA_INTEL_SDM_MAILBOX Enable FPGA driver for writing full bitstream into Intel FPGA devices through SDM (Secure Device Manager) Mailbox. -config FPGA_LATTICE - bool "Enable Lattice FPGA driver" - help - This is used for the lattice FPGAs. Please check the source code as - there is no documentation for this at present. - config FPGA_XILINX bool "Enable Xilinx FPGA drivers" select FPGA diff --git a/drivers/fpga/Makefile b/drivers/fpga/Makefile index 6c779d5b5df..f22d3b3d86e 100644 --- a/drivers/fpga/Makefile +++ b/drivers/fpga/Makefile @@ -14,7 +14,6 @@ obj-$(CONFIG_FPGA_VIRTEX2) += virtex2.o obj-$(CONFIG_FPGA_ZYNQPL) += zynqpl.o obj-$(CONFIG_FPGA_ZYNQMPPL) += zynqmppl.o obj-$(CONFIG_FPGA_XILINX) += xilinx.o -obj-$(CONFIG_FPGA_LATTICE) += ivm_core.o lattice.o ifdef CONFIG_FPGA_ALTERA obj-y += altera.o obj-$(CONFIG_FPGA_CYCLON2) += cyclon2.o diff --git a/drivers/fpga/fpga.c b/drivers/fpga/fpga.c index 2297fefd149..b4e3896d2e8 100644 --- a/drivers/fpga/fpga.c +++ b/drivers/fpga/fpga.c @@ -9,7 +9,6 @@ #include #include /* xilinx specific definitions */ #include /* altera specific definitions */ -#include #include /* Local static data */ @@ -79,14 +78,6 @@ static int fpga_dev_info(int devnum) ret_val = altera_info(desc->devdesc); #else log_err("No support for Altera devices.\n"); -#endif - break; - case fpga_lattice: -#if defined(CONFIG_FPGA_LATTICE) - log_info("Lattice Device\nDescriptor @ 0x%p\n", desc); - ret_val = lattice_info(desc->devdesc); -#else - log_err("No support for Lattice devices.\n"); #endif break; default: @@ -265,13 +256,6 @@ int fpga_load(int devnum, const void *buf, size_t bsize, bitstream_type bstype, ret_val = altera_load(desc->devdesc, buf, bsize); #else log_err("No support for Altera devices.\n"); -#endif - break; - case fpga_lattice: -#if defined(CONFIG_FPGA_LATTICE) - ret_val = lattice_load(desc->devdesc, buf, bsize); -#else - log_err("No support for Lattice devices.\n"); #endif break; default: @@ -310,13 +294,6 @@ int fpga_dump(int devnum, const void *buf, size_t bsize) ret_val = altera_dump(desc->devdesc, buf, bsize); #else log_err("No support for Altera devices.\n"); -#endif - break; - case fpga_lattice: -#if defined(CONFIG_FPGA_LATTICE) - ret_val = lattice_dump(desc->devdesc, buf, bsize); -#else - log_err("No support for Lattice devices.\n"); #endif break; default: diff --git a/drivers/fpga/ivm_core.c b/drivers/fpga/ivm_core.c deleted file mode 100644 index 37d5c5ec9ec..00000000000 --- a/drivers/fpga/ivm_core.c +++ /dev/null @@ -1,3149 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -/* - * Porting to u-boot: - * - * (C) Copyright 2010 - * Stefano Babic, DENX Software Engineering, sbabic@denx.de. - * - * Lattice ispVME Embedded code to load Lattice's FPGA: - * - * Copyright 2009 Lattice Semiconductor Corp. - * - * ispVME Embedded allows programming of Lattice's suite of FPGA - * devices on embedded systems through the JTAG port. The software - * is distributed in source code form and is open to re - distribution - * and modification where applicable. - * - * Revision History of ivm_core.c module: - * 4/25/06 ht Change some variables from unsigned short or int - * to long int to make the code compiler independent. - * 5/24/06 ht Support using RESET (TRST) pin as a special purpose - * control pin such as triggering the loading of known - * state exit. - * 3/6/07 ht added functions to support output to terminals - * - * 09/11/07 NN Type cast mismatch variables - * Moved the sclock() function to hardware.c - * 08/28/08 NN Added Calculate checksum support. - * 4/1/09 Nguyen replaced the recursive function call codes on - * the ispVMLCOUNT function - */ - -#include -#include -#include -#include -#include - -#define vme_out_char(c) printf("%c", c) -#define vme_out_hex(c) printf("%x", c) -#define vme_out_string(s) printf("%s", s) - -/* - * - * Global variables used to specify the flow control and data type. - * - * g_usFlowControl: flow control register. Each bit in the - * register can potentially change the - * personality of the embedded engine. - * g_usDataType: holds the data type of the current row. - * - */ - -static unsigned short g_usFlowControl; -unsigned short g_usDataType; - -/* - * - * Global variables used to specify the ENDDR and ENDIR. - * - * g_ucEndDR: the state that the device goes to after SDR. - * g_ucEndIR: the state that the device goes to after SIR. - * - */ - -unsigned char g_ucEndDR = DRPAUSE; -unsigned char g_ucEndIR = IRPAUSE; - -/* - * - * Global variables used to support header/trailer. - * - * g_usHeadDR: the number of lead devices in bypass. - * g_usHeadIR: the sum of IR length of lead devices. - * g_usTailDR: the number of tail devices in bypass. - * g_usTailIR: the sum of IR length of tail devices. - * - */ - -static unsigned short g_usHeadDR; -static unsigned short g_usHeadIR; -static unsigned short g_usTailDR; -static unsigned short g_usTailIR; - -/* - * - * Global variable to store the number of bits of data or instruction - * to be shifted into or out from the device. - * - */ - -static unsigned short g_usiDataSize; - -/* - * - * Stores the frequency. Default to 1 MHz. - * - */ - -static int g_iFrequency = 1000; - -/* - * - * Stores the maximum amount of ram needed to hold a row of data. - * - */ - -static unsigned short g_usMaxSize; - -/* - * - * Stores the LSH or RSH value. - * - */ - -static unsigned short g_usShiftValue; - -/* - * - * Stores the current repeat loop value. - * - */ - -static unsigned short g_usRepeatLoops; - -/* - * - * Stores the current vendor. - * - */ - -static signed char g_cVendor = LATTICE; - -/* - * - * Stores the VME file CRC. - * - */ - -unsigned short g_usCalculatedCRC; - -/* - * - * Stores the Device Checksum. - * - */ -/* 08/28/08 NN Added Calculate checksum support. */ -unsigned long g_usChecksum; -static unsigned int g_uiChecksumIndex; - -/* - * - * Stores the current state of the JTAG state machine. - * - */ - -static signed char g_cCurrentJTAGState; - -/* - * - * Global variables used to support looping. - * - * g_pucHeapMemory: holds the entire repeat loop. - * g_iHeapCounter: points to the current byte in the repeat loop. - * g_iHEAPSize: the current size of the repeat in bytes. - * - */ - -unsigned char *g_pucHeapMemory; -unsigned short g_iHeapCounter; -unsigned short g_iHEAPSize; -static unsigned short previous_size; - -/* - * - * Global variables used to support intelligent programming. - * - * g_usIntelDataIndex: points to the current byte of the - * intelligent buffer. - * g_usIntelBufferSize: holds the size of the intelligent - * buffer. - * - */ - -unsigned short g_usIntelDataIndex; -unsigned short g_usIntelBufferSize; - -/* - * - * Supported VME versions. - * - */ - -const char *const g_szSupportedVersions[] = { - "__VME2.0", "__VME3.0", "____12.0", "____12.1", 0}; - -/* - * - * Holds the maximum size of each respective buffer. These variables are used - * to write the HEX files when converting VME to HEX. - * -*/ - -static unsigned short g_usTDOSize; -static unsigned short g_usMASKSize; -static unsigned short g_usTDISize; -static unsigned short g_usDMASKSize; -static unsigned short g_usLCOUNTSize; -static unsigned short g_usHDRSize; -static unsigned short g_usTDRSize; -static unsigned short g_usHIRSize; -static unsigned short g_usTIRSize; -static unsigned short g_usHeapSize; - -/* - * - * Global variables used to store data. - * - * g_pucOutMaskData: local RAM to hold one row of MASK data. - * g_pucInData: local RAM to hold one row of TDI data. - * g_pucOutData: local RAM to hold one row of TDO data. - * g_pucHIRData: local RAM to hold the current SIR header. - * g_pucTIRData: local RAM to hold the current SIR trailer. - * g_pucHDRData: local RAM to hold the current SDR header. - * g_pucTDRData: local RAM to hold the current SDR trailer. - * g_pucIntelBuffer: local RAM to hold the current intelligent buffer - * g_pucOutDMaskData: local RAM to hold one row of DMASK data. - * - */ - -unsigned char *g_pucOutMaskData = NULL, - *g_pucInData = NULL, - *g_pucOutData = NULL, - *g_pucHIRData = NULL, - *g_pucTIRData = NULL, - *g_pucHDRData = NULL, - *g_pucTDRData = NULL, - *g_pucIntelBuffer = NULL, - *g_pucOutDMaskData = NULL; - -/* - * - * JTAG state machine transition table. - * - */ - -struct { - unsigned char CurState; /* From this state */ - unsigned char NextState; /* Step to this state */ - unsigned char Pattern; /* The tragetory of TMS */ - unsigned char Pulses; /* The number of steps */ -} g_JTAGTransistions[25] = { -{ RESET, RESET, 0xFC, 6 }, /* Transitions from RESET */ -{ RESET, IDLE, 0x00, 1 }, -{ RESET, DRPAUSE, 0x50, 5 }, -{ RESET, IRPAUSE, 0x68, 6 }, -{ IDLE, RESET, 0xE0, 3 }, /* Transitions from IDLE */ -{ IDLE, DRPAUSE, 0xA0, 4 }, -{ IDLE, IRPAUSE, 0xD0, 5 }, -{ DRPAUSE, RESET, 0xF8, 5 }, /* Transitions from DRPAUSE */ -{ DRPAUSE, IDLE, 0xC0, 3 }, -{ DRPAUSE, IRPAUSE, 0xF4, 7 }, -{ DRPAUSE, DRPAUSE, 0xE8, 6 },/* 06/14/06 Support POLL STATUS LOOP*/ -{ IRPAUSE, RESET, 0xF8, 5 }, /* Transitions from IRPAUSE */ -{ IRPAUSE, IDLE, 0xC0, 3 }, -{ IRPAUSE, DRPAUSE, 0xE8, 6 }, -{ DRPAUSE, SHIFTDR, 0x80, 2 }, /* Extra transitions using SHIFTDR */ -{ IRPAUSE, SHIFTDR, 0xE0, 5 }, -{ SHIFTDR, DRPAUSE, 0x80, 2 }, -{ SHIFTDR, IDLE, 0xC0, 3 }, -{ IRPAUSE, SHIFTIR, 0x80, 2 },/* Extra transitions using SHIFTIR */ -{ SHIFTIR, IRPAUSE, 0x80, 2 }, -{ SHIFTIR, IDLE, 0xC0, 3 }, -{ DRPAUSE, DRCAPTURE, 0xE0, 4 }, /* 11/15/05 Support DRCAPTURE*/ -{ DRCAPTURE, DRPAUSE, 0x80, 2 }, -{ IDLE, DRCAPTURE, 0x80, 2 }, -{ IRPAUSE, DRCAPTURE, 0xE0, 4 } -}; - -/* - * - * List to hold all LVDS pairs. - * - */ - -LVDSPair *g_pLVDSList; -unsigned short g_usLVDSPairCount; - -/* - * - * Function prototypes. - * - */ - -static signed char ispVMDataCode(void); -static long ispVMDataSize(void); -static void ispVMData(unsigned char *Data); -static signed char ispVMShift(signed char Code); -static signed char ispVMAmble(signed char Code); -static signed char ispVMLoop(unsigned short a_usLoopCount); -static signed char ispVMBitShift(signed char mode, unsigned short bits); -static void ispVMComment(unsigned short a_usCommentSize); -static void ispVMHeader(unsigned short a_usHeaderSize); -static signed char ispVMLCOUNT(unsigned short a_usCountSize); -static void ispVMClocks(unsigned short Clocks); -static void ispVMBypass(signed char ScanType, unsigned short Bits); -static void ispVMStateMachine(signed char NextState); -static signed char ispVMSend(unsigned short int); -static signed char ispVMRead(unsigned short int); -static signed char ispVMReadandSave(unsigned short int); -static signed char ispVMProcessLVDS(unsigned short a_usLVDSCount); -static void ispVMMemManager(signed char types, unsigned short size); - -/* - * - * External variables and functions in hardware.c module - * - */ -static signed char g_cCurrentJTAGState; - -#ifdef DEBUG - -/* - * - * GetState - * - * Returns the state as a string based on the opcode. Only used - * for debugging purposes. - * - */ - -const char *GetState(unsigned char a_ucState) -{ - switch (a_ucState) { - case RESET: - return "RESET"; - case IDLE: - return "IDLE"; - case IRPAUSE: - return "IRPAUSE"; - case DRPAUSE: - return "DRPAUSE"; - case SHIFTIR: - return "SHIFTIR"; - case SHIFTDR: - return "SHIFTDR"; - case DRCAPTURE:/* 11/15/05 support DRCAPTURE*/ - return "DRCAPTURE"; - default: - break; - } - - return 0; -} - -/* - * - * PrintData - * - * Prints the data. Only used for debugging purposes. - * - */ - -void PrintData(unsigned short a_iDataSize, unsigned char *a_pucData) -{ - /* 09/11/07 NN added local variables initialization */ - unsigned short usByteSize = 0; - unsigned short usBitIndex = 0; - signed short usByteIndex = 0; - unsigned char ucByte = 0; - unsigned char ucFlipByte = 0; - - if (a_iDataSize % 8) { - /* 09/11/07 NN Type cast mismatch variables */ - usByteSize = (unsigned short)(a_iDataSize / 8 + 1); - } else { - /* 09/11/07 NN Type cast mismatch variables */ - usByteSize = (unsigned short)(a_iDataSize / 8); - } - puts("("); - /* 09/11/07 NN Type cast mismatch variables */ - for (usByteIndex = (signed short)(usByteSize - 1); - usByteIndex >= 0; usByteIndex--) { - ucByte = a_pucData[usByteIndex]; - ucFlipByte = 0x00; - - /* - * - * Flip each byte. - * - */ - - for (usBitIndex = 0; usBitIndex < 8; usBitIndex++) { - ucFlipByte <<= 1; - if (ucByte & 0x1) { - ucFlipByte |= 0x1; - } - - ucByte >>= 1; - } - - /* - * - * Print the flipped byte. - * - */ - - printf("%.02X", ucFlipByte); - if ((usByteSize - usByteIndex) % 40 == 39) { - puts("\n\t\t"); - } - if (usByteIndex < 0) - break; - } - puts(")"); -} -#endif /* DEBUG */ - -void ispVMMemManager(signed char cTarget, unsigned short usSize) -{ - switch (cTarget) { - case XTDI: - case TDI: - if (g_pucInData != NULL) { - if (previous_size == usSize) {/*memory exist*/ - break; - } else { - free(g_pucInData); - g_pucInData = NULL; - } - } - g_pucInData = (unsigned char *) malloc(usSize / 8 + 2); - previous_size = usSize; - case XTDO: - case TDO: - if (g_pucOutData != NULL) { - if (previous_size == usSize) { /*already exist*/ - break; - } else { - free(g_pucOutData); - g_pucOutData = NULL; - } - } - g_pucOutData = (unsigned char *) malloc(usSize / 8 + 2); - previous_size = usSize; - break; - case MASK: - if (g_pucOutMaskData != NULL) { - if (previous_size == usSize) {/*already allocated*/ - break; - } else { - free(g_pucOutMaskData); - g_pucOutMaskData = NULL; - } - } - g_pucOutMaskData = (unsigned char *) malloc(usSize / 8 + 2); - previous_size = usSize; - break; - case HIR: - if (g_pucHIRData != NULL) { - free(g_pucHIRData); - g_pucHIRData = NULL; - } - g_pucHIRData = (unsigned char *) malloc(usSize / 8 + 2); - break; - case TIR: - if (g_pucTIRData != NULL) { - free(g_pucTIRData); - g_pucTIRData = NULL; - } - g_pucTIRData = (unsigned char *) malloc(usSize / 8 + 2); - break; - case HDR: - if (g_pucHDRData != NULL) { - free(g_pucHDRData); - g_pucHDRData = NULL; - } - g_pucHDRData = (unsigned char *) malloc(usSize / 8 + 2); - break; - case TDR: - if (g_pucTDRData != NULL) { - free(g_pucTDRData); - g_pucTDRData = NULL; - } - g_pucTDRData = (unsigned char *) malloc(usSize / 8 + 2); - break; - case HEAP: - if (g_pucHeapMemory != NULL) { - free(g_pucHeapMemory); - g_pucHeapMemory = NULL; - } - g_pucHeapMemory = (unsigned char *) malloc(usSize + 2); - break; - case DMASK: - if (g_pucOutDMaskData != NULL) { - if (previous_size == usSize) { /*already allocated*/ - break; - } else { - free(g_pucOutDMaskData); - g_pucOutDMaskData = NULL; - } - } - g_pucOutDMaskData = (unsigned char *) malloc(usSize / 8 + 2); - previous_size = usSize; - break; - case LHEAP: - if (g_pucIntelBuffer != NULL) { - free(g_pucIntelBuffer); - g_pucIntelBuffer = NULL; - } - g_pucIntelBuffer = (unsigned char *) malloc(usSize + 2); - break; - case LVDS: - if (g_pLVDSList != NULL) { - free(g_pLVDSList); - g_pLVDSList = NULL; - } - g_pLVDSList = (LVDSPair *) malloc(usSize * sizeof(LVDSPair)); - if (g_pLVDSList) - memset(g_pLVDSList, 0, usSize * sizeof(LVDSPair)); - break; - default: - return; - } -} - -void ispVMFreeMem(void) -{ - if (g_pucHeapMemory != NULL) { - free(g_pucHeapMemory); - g_pucHeapMemory = NULL; - } - - if (g_pucOutMaskData != NULL) { - free(g_pucOutMaskData); - g_pucOutMaskData = NULL; - } - - if (g_pucInData != NULL) { - free(g_pucInData); - g_pucInData = NULL; - } - - if (g_pucOutData != NULL) { - free(g_pucOutData); - g_pucOutData = NULL; - } - - if (g_pucHIRData != NULL) { - free(g_pucHIRData); - g_pucHIRData = NULL; - } - - if (g_pucTIRData != NULL) { - free(g_pucTIRData); - g_pucTIRData = NULL; - } - - if (g_pucHDRData != NULL) { - free(g_pucHDRData); - g_pucHDRData = NULL; - } - - if (g_pucTDRData != NULL) { - free(g_pucTDRData); - g_pucTDRData = NULL; - } - - if (g_pucOutDMaskData != NULL) { - free(g_pucOutDMaskData); - g_pucOutDMaskData = NULL; - } - - if (g_pucIntelBuffer != NULL) { - free(g_pucIntelBuffer); - g_pucIntelBuffer = NULL; - } - - if (g_pLVDSList != NULL) { - free(g_pLVDSList); - g_pLVDSList = NULL; - } -} - -/* - * - * ispVMDataSize - * - * Returns a VME-encoded number, usually used to indicate the - * bit length of an SIR/SDR command. - * - */ - -long ispVMDataSize(void) -{ - /* 09/11/07 NN added local variables initialization */ - long int iSize = 0; - signed char cCurrentByte = 0; - signed char cIndex = 0; - cIndex = 0; - while ((cCurrentByte = GetByte()) & 0x80) { - iSize |= ((long int) (cCurrentByte & 0x7F)) << cIndex; - cIndex += 7; - } - iSize |= ((long int) (cCurrentByte & 0x7F)) << cIndex; - return iSize; -} - -/* - * - * ispVMCode - * - * This is the heart of the embedded engine. All the high-level opcodes - * are extracted here. Once they have been identified, then it - * will call other functions to handle the processing. - * - */ - -signed char ispVMCode(void) -{ - /* 09/11/07 NN added local variables initialization */ - unsigned short iRepeatSize = 0; - signed char cOpcode = 0; - signed char cRetCode = 0; - unsigned char ucState = 0; - unsigned short usDelay = 0; - unsigned short usToggle = 0; - unsigned char usByte = 0; - - /* - * - * Check the compression flag only if this is the first time - * this function is entered. Do not check the compression flag if - * it is being called recursively from other functions within - * the embedded engine. - * - */ - - if (!(g_usDataType & LHEAP_IN) && !(g_usDataType & HEAP_IN)) { - usByte = GetByte(); - if (usByte == 0xf1) { - g_usDataType |= COMPRESS; - } else if (usByte == 0xf2) { - g_usDataType &= ~COMPRESS; - } else { - return VME_INVALID_FILE; - } - } - - /* - * - * Begin looping through all the VME opcodes. - * - */ - - while ((cOpcode = GetByte()) >= 0) { - - switch (cOpcode) { - case STATE: - - /* - * Step the JTAG state machine. - */ - - ucState = GetByte(); - - /* - * Step the JTAG state machine to DRCAPTURE - * to support Looping. - */ - - if ((g_usDataType & LHEAP_IN) && - (ucState == DRPAUSE) && - (g_cCurrentJTAGState == ucState)) { - ispVMStateMachine(DRCAPTURE); - } - - ispVMStateMachine(ucState); - -#ifdef DEBUG - if (g_usDataType & LHEAP_IN) { - debug("LDELAY %s ", GetState(ucState)); - } else { - debug("STATE %s;\n", GetState(ucState)); - } -#endif /* DEBUG */ - break; - case SIR: - case SDR: - case XSDR: - -#ifdef DEBUG - switch (cOpcode) { - case SIR: - puts("SIR "); - break; - case SDR: - case XSDR: - if (g_usDataType & LHEAP_IN) { - puts("LSDR "); - } else { - puts("SDR "); - } - break; - } -#endif /* DEBUG */ - /* - * - * Shift in data into the device. - * - */ - - cRetCode = ispVMShift(cOpcode); - if (cRetCode != 0) { - return cRetCode; - } - break; - case WAIT: - - /* - * - * Observe delay. - * - */ - - /* 09/11/07 NN Type cast mismatch variables */ - usDelay = (unsigned short) ispVMDataSize(); - ispVMDelay(usDelay); - -#ifdef DEBUG - if (usDelay & 0x8000) { - - /* - * Since MSB is set, the delay time must be - * decoded to millisecond. The SVF2VME encodes - * the MSB to represent millisecond. - */ - - usDelay &= ~0x8000; - if (g_usDataType & LHEAP_IN) { - printf("%.2E SEC;\n", - (float) usDelay / 1000); - } else { - printf("RUNTEST %.2E SEC;\n", - (float) usDelay / 1000); - } - } else { - /* - * Since MSB is not set, the delay time - * is given as microseconds. - */ - - if (g_usDataType & LHEAP_IN) { - printf("%.2E SEC;\n", - (float) usDelay / 1000000); - } else { - printf("RUNTEST %.2E SEC;\n", - (float) usDelay / 1000000); - } - } -#endif /* DEBUG */ - break; - case TCK: - - /* - * Issue clock toggles. - */ - - /* 09/11/07 NN Type cast mismatch variables */ - usToggle = (unsigned short) ispVMDataSize(); - ispVMClocks(usToggle); - -#ifdef DEBUG - printf("RUNTEST %d TCK;\n", usToggle); -#endif /* DEBUG */ - break; - case ENDDR: - - /* - * - * Set the ENDDR. - * - */ - - g_ucEndDR = GetByte(); - -#ifdef DEBUG - printf("ENDDR %s;\n", GetState(g_ucEndDR)); -#endif /* DEBUG */ - break; - case ENDIR: - - /* - * - * Set the ENDIR. - * - */ - - g_ucEndIR = GetByte(); - -#ifdef DEBUG - printf("ENDIR %s;\n", GetState(g_ucEndIR)); -#endif /* DEBUG */ - break; - case HIR: - case TIR: - case HDR: - case TDR: - -#ifdef DEBUG - switch (cOpcode) { - case HIR: - puts("HIR "); - break; - case TIR: - puts("TIR "); - break; - case HDR: - puts("HDR "); - break; - case TDR: - puts("TDR "); - break; - } -#endif /* DEBUG */ - /* - * Set the header/trailer of the device in order - * to bypass - * successfully. - */ - - cRetCode = ispVMAmble(cOpcode); - if (cRetCode != 0) { - return cRetCode; - } - -#ifdef DEBUG - puts(";\n"); -#endif /* DEBUG */ - break; - case MEM: - - /* - * The maximum RAM required to support - * processing one row of the VME file. - */ - - /* 09/11/07 NN Type cast mismatch variables */ - g_usMaxSize = (unsigned short) ispVMDataSize(); - -#ifdef DEBUG - printf("// MEMSIZE %d\n", g_usMaxSize); -#endif /* DEBUG */ - break; - case VENDOR: - - /* - * - * Set the VENDOR type. - * - */ - - cOpcode = GetByte(); - switch (cOpcode) { - case LATTICE: -#ifdef DEBUG - puts("// VENDOR LATTICE\n"); -#endif /* DEBUG */ - g_cVendor = LATTICE; - break; - case ALTERA: -#ifdef DEBUG - puts("// VENDOR ALTERA\n"); -#endif /* DEBUG */ - g_cVendor = ALTERA; - break; - case XILINX: -#ifdef DEBUG - puts("// VENDOR XILINX\n"); -#endif /* DEBUG */ - g_cVendor = XILINX; - break; - default: - break; - } - break; - case SETFLOW: - - /* - * Set the flow control. Flow control determines - * the personality of the embedded engine. - */ - - /* 09/11/07 NN Type cast mismatch variables */ - g_usFlowControl |= (unsigned short) ispVMDataSize(); - break; - case RESETFLOW: - - /* - * - * Unset the flow control. - * - */ - - /* 09/11/07 NN Type cast mismatch variables */ - g_usFlowControl &= (unsigned short) ~(ispVMDataSize()); - break; - case HEAP: - - /* - * - * Allocate heap size to store loops. - * - */ - - cRetCode = GetByte(); - if (cRetCode != SECUREHEAP) { - return VME_INVALID_FILE; - } - /* 09/11/07 NN Type cast mismatch variables */ - g_iHEAPSize = (unsigned short) ispVMDataSize(); - - /* - * Store the maximum size of the HEAP buffer. - * Used to convert VME to HEX. - */ - - if (g_iHEAPSize > g_usHeapSize) { - g_usHeapSize = g_iHEAPSize; - } - - ispVMMemManager(HEAP, (unsigned short) g_iHEAPSize); - break; - case REPEAT: - - /* - * - * Execute loops. - * - */ - - g_usRepeatLoops = 0; - - /* 09/11/07 NN Type cast mismatch variables */ - iRepeatSize = (unsigned short) ispVMDataSize(); - - cRetCode = ispVMLoop((unsigned short) iRepeatSize); - if (cRetCode != 0) { - return cRetCode; - } - break; - case ENDLOOP: - - /* - * - * Exit point from processing loops. - * - */ - - return cRetCode; - case ENDVME: - - /* - * The only valid exit point that indicates - * end of programming. - */ - - return cRetCode; - case SHR: - - /* - * - * Right-shift address. - * - */ - - g_usFlowControl |= SHIFTRIGHT; - - /* 09/11/07 NN Type cast mismatch variables */ - g_usShiftValue = (unsigned short) (g_usRepeatLoops * - (unsigned short)GetByte()); - break; - case SHL: - - /* - * Left-shift address. - */ - - g_usFlowControl |= SHIFTLEFT; - - /* 09/11/07 NN Type cast mismatch variables */ - g_usShiftValue = (unsigned short) (g_usRepeatLoops * - (unsigned short)GetByte()); - break; - case FREQUENCY: - - /* - * - * Set the frequency. - * - */ - - /* 09/11/07 NN Type cast mismatch variables */ - g_iFrequency = (int) (ispVMDataSize() / 1000); - if (g_iFrequency == 1) - g_iFrequency = 1000; - -#ifdef DEBUG - printf("FREQUENCY %.2E HZ;\n", - (float) g_iFrequency * 1000); -#endif /* DEBUG */ - break; - case LCOUNT: - - /* - * - * Process LCOUNT command. - * - */ - - cRetCode = ispVMLCOUNT((unsigned short)ispVMDataSize()); - if (cRetCode != 0) { - return cRetCode; - } - break; - case VUES: - - /* - * - * Set the flow control to verify USERCODE. - * - */ - - g_usFlowControl |= VERIFYUES; - break; - case COMMENT: - - /* - * - * Display comment. - * - */ - - ispVMComment((unsigned short) ispVMDataSize()); - break; - case LVDS: - - /* - * - * Process LVDS command. - * - */ - - ispVMProcessLVDS((unsigned short) ispVMDataSize()); - break; - case HEADER: - - /* - * - * Discard header. - * - */ - - ispVMHeader((unsigned short) ispVMDataSize()); - break; - /* 03/14/06 Support Toggle ispENABLE signal*/ - case ispEN: - ucState = GetByte(); - if ((ucState == ON) || (ucState == 0x01)) - writePort(g_ucPinENABLE, 0x01); - else - writePort(g_ucPinENABLE, 0x00); - ispVMDelay(1); - break; - /* 05/24/06 support Toggle TRST pin*/ - case TRST: - ucState = GetByte(); - if (ucState == 0x01) - writePort(g_ucPinTRST, 0x01); - else - writePort(g_ucPinTRST, 0x00); - ispVMDelay(1); - break; - default: - - /* - * - * Invalid opcode encountered. - * - */ - -#ifdef DEBUG - printf("\nINVALID OPCODE: 0x%.2X\n", cOpcode); -#endif /* DEBUG */ - - return VME_INVALID_FILE; - } - } - - /* - * - * Invalid exit point. Processing the token 'ENDVME' is the only - * valid way to exit the embedded engine. - * - */ - - return VME_INVALID_FILE; -} - -/* - * - * ispVMDataCode - * - * Processes the TDI/TDO/MASK/DMASK etc of an SIR/SDR command. - * - */ - -signed char ispVMDataCode(void) -{ - /* 09/11/07 NN added local variables initialization */ - signed char cDataByte = 0; - signed char siDataSource = 0; /*source of data from file by default*/ - - if (g_usDataType & HEAP_IN) { - siDataSource = 1; /*the source of data from memory*/ - } - - /* - * - * Clear the data type register. - * - **/ - - g_usDataType &= ~(MASK_DATA + TDI_DATA + - TDO_DATA + DMASK_DATA + CMASK_DATA); - - /* - * Iterate through SIR/SDR command and look for TDI, - * TDO, MASK, etc. - */ - - while ((cDataByte = GetByte()) >= 0) { - ispVMMemManager(cDataByte, g_usMaxSize); - switch (cDataByte) { - case TDI: - - /* - * Store the maximum size of the TDI buffer. - * Used to convert VME to HEX. - */ - - if (g_usiDataSize > g_usTDISize) { - g_usTDISize = g_usiDataSize; - } - /* - * Updated data type register to indicate that - * TDI data is currently being used. Process the - * data in the VME file into the TDI buffer. - */ - - g_usDataType |= TDI_DATA; - ispVMData(g_pucInData); - break; - case XTDO: - - /* - * Store the maximum size of the TDO buffer. - * Used to convert VME to HEX. - */ - - if (g_usiDataSize > g_usTDOSize) { - g_usTDOSize = g_usiDataSize; - } - - /* - * Updated data type register to indicate that - * TDO data is currently being used. - */ - - g_usDataType |= TDO_DATA; - break; - case TDO: - - /* - * Store the maximum size of the TDO buffer. - * Used to convert VME to HEX. - */ - - if (g_usiDataSize > g_usTDOSize) { - g_usTDOSize = g_usiDataSize; - } - - /* - * Updated data type register to indicate - * that TDO data is currently being used. - * Process the data in the VME file into the - * TDO buffer. - */ - - g_usDataType |= TDO_DATA; - ispVMData(g_pucOutData); - break; - case MASK: - - /* - * Store the maximum size of the MASK buffer. - * Used to convert VME to HEX. - */ - - if (g_usiDataSize > g_usMASKSize) { - g_usMASKSize = g_usiDataSize; - } - - /* - * Updated data type register to indicate that - * MASK data is currently being used. Process - * the data in the VME file into the MASK buffer - */ - - g_usDataType |= MASK_DATA; - ispVMData(g_pucOutMaskData); - break; - case DMASK: - - /* - * Store the maximum size of the DMASK buffer. - * Used to convert VME to HEX. - */ - - if (g_usiDataSize > g_usDMASKSize) { - g_usDMASKSize = g_usiDataSize; - } - - /* - * Updated data type register to indicate that - * DMASK data is currently being used. Process - * the data in the VME file into the DMASK - * buffer. - */ - - g_usDataType |= DMASK_DATA; - ispVMData(g_pucOutDMaskData); - break; - case CMASK: - - /* - * Updated data type register to indicate that - * MASK data is currently being used. Process - * the data in the VME file into the MASK buffer - */ - - g_usDataType |= CMASK_DATA; - ispVMData(g_pucOutMaskData); - break; - case CONTINUE: - return 0; - default: - /* - * Encountered invalid opcode. - */ - return VME_INVALID_FILE; - } - - switch (cDataByte) { - case TDI: - - /* - * Left bit shift. Used when performing - * algorithm looping. - */ - - if (g_usFlowControl & SHIFTLEFT) { - ispVMBitShift(SHL, g_usShiftValue); - g_usFlowControl &= ~SHIFTLEFT; - } - - /* - * Right bit shift. Used when performing - * algorithm looping. - */ - - if (g_usFlowControl & SHIFTRIGHT) { - ispVMBitShift(SHR, g_usShiftValue); - g_usFlowControl &= ~SHIFTRIGHT; - } - default: - break; - } - - if (siDataSource) { - g_usDataType |= HEAP_IN; /*restore from memory*/ - } - } - - if (siDataSource) { /*fetch data from heap memory upon return*/ - g_usDataType |= HEAP_IN; - } - - if (cDataByte < 0) { - - /* - * Encountered invalid opcode. - */ - - return VME_INVALID_FILE; - } else { - return 0; - } -} - -/* - * - * ispVMData - * Extract one row of data operand from the current data type opcode. Perform - * the decompression if necessary. Extra RAM is not required for the - * decompression process. The decompression scheme employed in this module - * is on row by row basis. The format of the data stream: - * [compression code][compressed data stream] - * 0x00 --No compression - * 0x01 --Compress by 0x00. - * Example: - * Original stream: 0x000000000000000000000001 - * Compressed stream: 0x01000901 - * Detail: 0x01 is the code, 0x00 is the key, - * 0x09 is the count of 0x00 bytes, - * 0x01 is the uncompressed byte. - * 0x02 --Compress by 0xFF. - * Example: - * Original stream: 0xFFFFFFFFFFFFFFFFFFFFFF01 - * Compressed stream: 0x02FF0901 - * Detail: 0x02 is the code, 0xFF is the key, - * 0x09 is the count of 0xFF bytes, - * 0x01 is the uncompressed byte. - * 0x03 - * : : - * 0xFE -- Compress by nibble blocks. - * Example: - * Original stream: 0x84210842108421084210 - * Compressed stream: 0x0584210 - * Detail: 0x05 is the code, means 5 nibbles block. - * 0x84210 is the 5 nibble blocks. - * The whole row is 80 bits given by g_usiDataSize. - * The number of times the block repeat itself - * is found by g_usiDataSize/(4*0x05) which is 4. - * 0xFF -- Compress by the most frequently happen byte. - * Example: - * Original stream: 0x04020401030904040404 - * Compressed stream: 0xFF04(0,1,0x02,0,1,0x01,1,0x03,1,0x09,0,0,0) - * or: 0xFF044090181C240 - * Detail: 0xFF is the code, 0x04 is the key. - * a bit of 0 represent the key shall be put into - * the current bit position and a bit of 1 - * represent copying the next of 8 bits of data - * in. - * - */ - -void ispVMData(unsigned char *ByteData) -{ - /* 09/11/07 NN added local variables initialization */ - unsigned short size = 0; - unsigned short i, j, m, getData = 0; - unsigned char cDataByte = 0; - unsigned char compress = 0; - unsigned short FFcount = 0; - unsigned char compr_char = 0xFF; - unsigned short index = 0; - signed char compression = 0; - - /*convert number in bits to bytes*/ - if (g_usiDataSize % 8 > 0) { - /* 09/11/07 NN Type cast mismatch variables */ - size = (unsigned short)(g_usiDataSize / 8 + 1); - } else { - /* 09/11/07 NN Type cast mismatch variables */ - size = (unsigned short)(g_usiDataSize / 8); - } - - /* - * If there is compression, then check if compress by key - * of 0x00 or 0xFF or by other keys or by nibble blocks - */ - - if (g_usDataType & COMPRESS) { - compression = 1; - compress = GetByte(); - if ((compress == VAR) && (g_usDataType & HEAP_IN)) { - getData = 1; - g_usDataType &= ~(HEAP_IN); - compress = GetByte(); - } - - switch (compress) { - case 0x00: - /* No compression */ - compression = 0; - break; - case 0x01: - /* Compress by byte 0x00 */ - compr_char = 0x00; - break; - case 0x02: - /* Compress by byte 0xFF */ - compr_char = 0xFF; - break; - case 0xFF: - /* Huffman encoding */ - compr_char = GetByte(); - i = 8; - for (index = 0; index < size; index++) { - ByteData[index] = 0x00; - if (i > 7) { - cDataByte = GetByte(); - i = 0; - } - if ((cDataByte << i++) & 0x80) - m = 8; - else { - ByteData[index] = compr_char; - m = 0; - } - - for (j = 0; j < m; j++) { - if (i > 7) { - cDataByte = GetByte(); - i = 0; - } - ByteData[index] |= - ((cDataByte << i++) & 0x80) >> j; - } - } - size = 0; - break; - default: - for (index = 0; index < size; index++) - ByteData[index] = 0x00; - for (index = 0; index < compress; index++) { - if (index % 2 == 0) - cDataByte = GetByte(); - for (i = 0; i < size * 2 / compress; i++) { - j = (unsigned short)(index + - (i * (unsigned short)compress)); - /*clear the nibble to zero first*/ - if (j%2) { - if (index % 2) - ByteData[j/2] |= - cDataByte & 0xF; - else - ByteData[j/2] |= - cDataByte >> 4; - } else { - if (index % 2) - ByteData[j/2] |= - cDataByte << 4; - else - ByteData[j/2] |= - cDataByte & 0xF0; - } - } - } - size = 0; - break; - } - } - - FFcount = 0; - - /* Decompress by byte 0x00 or 0xFF */ - for (index = 0; index < size; index++) { - if (FFcount <= 0) { - cDataByte = GetByte(); - if ((cDataByte == VAR) && (g_usDataType&HEAP_IN) && - !getData && !(g_usDataType&COMPRESS)) { - getData = 1; - g_usDataType &= ~(HEAP_IN); - cDataByte = GetByte(); - } - ByteData[index] = cDataByte; - if ((compression) && (cDataByte == compr_char)) - /* 09/11/07 NN Type cast mismatch variables */ - FFcount = (unsigned short) ispVMDataSize(); - /*The number of 0xFF or 0x00 bytes*/ - } else { - FFcount--; /*Use up the 0xFF chain first*/ - ByteData[index] = compr_char; - } - } - - if (getData) { - g_usDataType |= HEAP_IN; - getData = 0; - } -} - -/* - * - * ispVMShift - * - * Processes the SDR/XSDR/SIR commands. - * - */ - -signed char ispVMShift(signed char a_cCode) -{ - /* 09/11/07 NN added local variables initialization */ - unsigned short iDataIndex = 0; - unsigned short iReadLoop = 0; - signed char cRetCode = 0; - - cRetCode = 0; - /* 09/11/07 NN Type cast mismatch variables */ - g_usiDataSize = (unsigned short) ispVMDataSize(); - - /*clear the flags first*/ - g_usDataType &= ~(SIR_DATA + EXPRESS + SDR_DATA); - switch (a_cCode) { - case SIR: - g_usDataType |= SIR_DATA; - /* - * 1/15/04 If performing cascading, then go directly to SHIFTIR. - * Else, go to IRPAUSE before going to SHIFTIR - */ - if (g_usFlowControl & CASCADE) { - ispVMStateMachine(SHIFTIR); - } else { - ispVMStateMachine(IRPAUSE); - ispVMStateMachine(SHIFTIR); - if (g_usHeadIR > 0) { - ispVMBypass(HIR, g_usHeadIR); - sclock(); - } - } - break; - case XSDR: - g_usDataType |= EXPRESS; /*mark simultaneous in and out*/ - case SDR: - g_usDataType |= SDR_DATA; - /* - * 1/15/04 If already in SHIFTDR, then do not move state or - * shift in header. This would imply that the previously - * shifted frame was a cascaded frame. - */ - if (g_cCurrentJTAGState != SHIFTDR) { - /* - * 1/15/04 If performing cascading, then go directly - * to SHIFTDR. Else, go to DRPAUSE before going - * to SHIFTDR - */ - if (g_usFlowControl & CASCADE) { - if (g_cCurrentJTAGState == DRPAUSE) { - ispVMStateMachine(SHIFTDR); - /* - * 1/15/04 If cascade flag has been seat - * and the current state is DRPAUSE, - * this implies that the first cascaded - * frame is about to be shifted in. The - * header must be shifted prior to - * shifting the first cascaded frame. - */ - if (g_usHeadDR > 0) { - ispVMBypass(HDR, g_usHeadDR); - sclock(); - } - } else { - ispVMStateMachine(SHIFTDR); - } - } else { - ispVMStateMachine(DRPAUSE); - ispVMStateMachine(SHIFTDR); - if (g_usHeadDR > 0) { - ispVMBypass(HDR, g_usHeadDR); - sclock(); - } - } - } - break; - default: - return VME_INVALID_FILE; - } - - cRetCode = ispVMDataCode(); - - if (cRetCode != 0) { - return VME_INVALID_FILE; - } - -#ifdef DEBUG - printf("%d ", g_usiDataSize); - - if (g_usDataType & TDI_DATA) { - puts("TDI "); - PrintData(g_usiDataSize, g_pucInData); - } - - if (g_usDataType & TDO_DATA) { - puts("\n\t\tTDO "); - PrintData(g_usiDataSize, g_pucOutData); - } - - if (g_usDataType & MASK_DATA) { - puts("\n\t\tMASK "); - PrintData(g_usiDataSize, g_pucOutMaskData); - } - - if (g_usDataType & DMASK_DATA) { - puts("\n\t\tDMASK "); - PrintData(g_usiDataSize, g_pucOutDMaskData); - } - - puts(";\n"); -#endif /* DEBUG */ - - if (g_usDataType & TDO_DATA || g_usDataType & DMASK_DATA) { - if (g_usDataType & DMASK_DATA) { - cRetCode = ispVMReadandSave(g_usiDataSize); - if (!cRetCode) { - if (g_usTailDR > 0) { - sclock(); - ispVMBypass(TDR, g_usTailDR); - } - ispVMStateMachine(DRPAUSE); - ispVMStateMachine(SHIFTDR); - if (g_usHeadDR > 0) { - ispVMBypass(HDR, g_usHeadDR); - sclock(); - } - for (iDataIndex = 0; - iDataIndex < g_usiDataSize / 8 + 1; - iDataIndex++) - g_pucInData[iDataIndex] = - g_pucOutData[iDataIndex]; - g_usDataType &= ~(TDO_DATA + DMASK_DATA); - cRetCode = ispVMSend(g_usiDataSize); - } - } else { - cRetCode = ispVMRead(g_usiDataSize); - if (cRetCode == -1 && g_cVendor == XILINX) { - for (iReadLoop = 0; iReadLoop < 30; - iReadLoop++) { - cRetCode = ispVMRead(g_usiDataSize); - if (!cRetCode) { - break; - } else { - /* Always DRPAUSE */ - ispVMStateMachine(DRPAUSE); - /* - * Bypass other devices - * when appropriate - */ - ispVMBypass(TDR, g_usTailDR); - ispVMStateMachine(g_ucEndDR); - ispVMStateMachine(IDLE); - ispVMDelay(1000); - } - } - } - } - } else { /*TDI only*/ - cRetCode = ispVMSend(g_usiDataSize); - } - - /*transfer the input data to the output buffer for the next verify*/ - if ((g_usDataType & EXPRESS) || (a_cCode == SDR)) { - if (g_pucOutData) { - for (iDataIndex = 0; iDataIndex < g_usiDataSize / 8 + 1; - iDataIndex++) - g_pucOutData[iDataIndex] = - g_pucInData[iDataIndex]; - } - } - - switch (a_cCode) { - case SIR: - /* 1/15/04 If not performing cascading, then shift ENDIR */ - if (!(g_usFlowControl & CASCADE)) { - if (g_usTailIR > 0) { - sclock(); - ispVMBypass(TIR, g_usTailIR); - } - ispVMStateMachine(g_ucEndIR); - } - break; - case XSDR: - case SDR: - /* 1/15/04 If not performing cascading, then shift ENDDR */ - if (!(g_usFlowControl & CASCADE)) { - if (g_usTailDR > 0) { - sclock(); - ispVMBypass(TDR, g_usTailDR); - } - ispVMStateMachine(g_ucEndDR); - } - break; - default: - break; - } - - return cRetCode; -} - -/* - * - * ispVMAmble - * - * This routine is to extract Header and Trailer parameter for SIR and - * SDR operations. - * - * The Header and Trailer parameter are the pre-amble and post-amble bit - * stream need to be shifted into TDI or out of TDO of the devices. Mostly - * is for the purpose of bypassing the leading or trailing devices. ispVM - * supports only shifting data into TDI to bypass the devices. - * - * For a single device, the header and trailer parameters are all set to 0 - * as default by ispVM. If it is for multiple devices, the header and trailer - * value will change as specified by the VME file. - * - */ - -signed char ispVMAmble(signed char Code) -{ - signed char compress = 0; - /* 09/11/07 NN Type cast mismatch variables */ - g_usiDataSize = (unsigned short)ispVMDataSize(); - -#ifdef DEBUG - printf("%d", g_usiDataSize); -#endif /* DEBUG */ - - if (g_usiDataSize) { - - /* - * Discard the TDI byte and set the compression bit in the data - * type register to false if compression is set because TDI data - * after HIR/HDR/TIR/TDR is not compressed. - */ - - GetByte(); - if (g_usDataType & COMPRESS) { - g_usDataType &= ~(COMPRESS); - compress = 1; - } - } - - switch (Code) { - case HIR: - - /* - * Store the maximum size of the HIR buffer. - * Used to convert VME to HEX. - */ - - if (g_usiDataSize > g_usHIRSize) { - g_usHIRSize = g_usiDataSize; - } - - /* - * Assign the HIR value and allocate memory. - */ - - g_usHeadIR = g_usiDataSize; - if (g_usHeadIR) { - ispVMMemManager(HIR, g_usHeadIR); - ispVMData(g_pucHIRData); - -#ifdef DEBUG - puts(" TDI "); - PrintData(g_usHeadIR, g_pucHIRData); -#endif /* DEBUG */ - } - break; - case TIR: - - /* - * Store the maximum size of the TIR buffer. - * Used to convert VME to HEX. - */ - - if (g_usiDataSize > g_usTIRSize) { - g_usTIRSize = g_usiDataSize; - } - - /* - * Assign the TIR value and allocate memory. - */ - - g_usTailIR = g_usiDataSize; - if (g_usTailIR) { - ispVMMemManager(TIR, g_usTailIR); - ispVMData(g_pucTIRData); - -#ifdef DEBUG - puts(" TDI "); - PrintData(g_usTailIR, g_pucTIRData); -#endif /* DEBUG */ - } - break; - case HDR: - - /* - * Store the maximum size of the HDR buffer. - * Used to convert VME to HEX. - */ - - if (g_usiDataSize > g_usHDRSize) { - g_usHDRSize = g_usiDataSize; - } - - /* - * Assign the HDR value and allocate memory. - * - */ - - g_usHeadDR = g_usiDataSize; - if (g_usHeadDR) { - ispVMMemManager(HDR, g_usHeadDR); - ispVMData(g_pucHDRData); - -#ifdef DEBUG - puts(" TDI "); - PrintData(g_usHeadDR, g_pucHDRData); -#endif /* DEBUG */ - } - break; - case TDR: - - /* - * Store the maximum size of the TDR buffer. - * Used to convert VME to HEX. - */ - - if (g_usiDataSize > g_usTDRSize) { - g_usTDRSize = g_usiDataSize; - } - - /* - * Assign the TDR value and allocate memory. - * - */ - - g_usTailDR = g_usiDataSize; - if (g_usTailDR) { - ispVMMemManager(TDR, g_usTailDR); - ispVMData(g_pucTDRData); - -#ifdef DEBUG - puts(" TDI "); - PrintData(g_usTailDR, g_pucTDRData); -#endif /* DEBUG */ - } - break; - default: - break; - } - - /* - * - * Re-enable compression if it was previously set. - * - **/ - - if (compress) { - g_usDataType |= COMPRESS; - } - - if (g_usiDataSize) { - Code = GetByte(); - if (Code == CONTINUE) { - return 0; - } else { - - /* - * Encountered invalid opcode. - */ - - return VME_INVALID_FILE; - } - } - - return 0; -} - -/* - * - * ispVMLoop - * - * Perform the function call upon by the REPEAT opcode. - * Memory is to be allocated to store the entire loop from REPEAT to ENDLOOP. - * After the loop is stored then execution begin. The REPEATLOOP flag is set - * on the g_usFlowControl register to indicate the repeat loop is in session - * and therefore fetch opcode from the memory instead of from the file. - * - */ - -signed char ispVMLoop(unsigned short a_usLoopCount) -{ - /* 09/11/07 NN added local variables initialization */ - signed char cRetCode = 0; - unsigned short iHeapIndex = 0; - unsigned short iLoopIndex = 0; - - g_usShiftValue = 0; - for (iHeapIndex = 0; iHeapIndex < g_iHEAPSize; iHeapIndex++) { - g_pucHeapMemory[iHeapIndex] = GetByte(); - } - - if (g_pucHeapMemory[iHeapIndex - 1] != ENDLOOP) { - return VME_INVALID_FILE; - } - - g_usFlowControl |= REPEATLOOP; - g_usDataType |= HEAP_IN; - - for (iLoopIndex = 0; iLoopIndex < a_usLoopCount; iLoopIndex++) { - g_iHeapCounter = 0; - cRetCode = ispVMCode(); - g_usRepeatLoops++; - if (cRetCode < 0) { - break; - } - } - - g_usDataType &= ~(HEAP_IN); - g_usFlowControl &= ~(REPEATLOOP); - return cRetCode; -} - -/* - * - * ispVMBitShift - * - * Shift the TDI stream left or right by the number of bits. The data in - * *g_pucInData is of the VME format, so the actual shifting is the reverse of - * IEEE 1532 or SVF format. - * - */ - -signed char ispVMBitShift(signed char mode, unsigned short bits) -{ - /* 09/11/07 NN added local variables initialization */ - unsigned short i = 0; - unsigned short size = 0; - unsigned short tmpbits = 0; - - if (g_usiDataSize % 8 > 0) { - /* 09/11/07 NN Type cast mismatch variables */ - size = (unsigned short)(g_usiDataSize / 8 + 1); - } else { - /* 09/11/07 NN Type cast mismatch variables */ - size = (unsigned short)(g_usiDataSize / 8); - } - - switch (mode) { - case SHR: - for (i = 0; i < size; i++) { - if (g_pucInData[i] != 0) { - tmpbits = bits; - while (tmpbits > 0) { - g_pucInData[i] <<= 1; - if (g_pucInData[i] == 0) { - i--; - g_pucInData[i] = 1; - } - tmpbits--; - } - } - } - break; - case SHL: - for (i = 0; i < size; i++) { - if (g_pucInData[i] != 0) { - tmpbits = bits; - while (tmpbits > 0) { - g_pucInData[i] >>= 1; - if (g_pucInData[i] == 0) { - i--; - g_pucInData[i] = 8; - } - tmpbits--; - } - } - } - break; - default: - return VME_INVALID_FILE; - } - - return 0; -} - -/* - * - * ispVMComment - * - * Displays the SVF comments. - * - */ - -void ispVMComment(unsigned short a_usCommentSize) -{ - char cCurByte = 0; - for (; a_usCommentSize > 0; a_usCommentSize--) { - /* - * - * Print character to the terminal. - * - **/ - cCurByte = GetByte(); - vme_out_char(cCurByte); - } - cCurByte = '\n'; - vme_out_char(cCurByte); -} - -/* - * - * ispVMHeader - * - * Iterate the length of the header and discard it. - * - */ - -void ispVMHeader(unsigned short a_usHeaderSize) -{ - for (; a_usHeaderSize > 0; a_usHeaderSize--) { - GetByte(); - } -} - -/* - * - * ispVMCalculateCRC32 - * - * Calculate the 32-bit CRC. - * - */ - -void ispVMCalculateCRC32(unsigned char a_ucData) -{ - /* 09/11/07 NN added local variables initialization */ - unsigned char ucIndex = 0; - unsigned char ucFlipData = 0; - unsigned short usCRCTableEntry = 0; - unsigned int crc_table[16] = { - 0x0000, 0xCC01, 0xD801, - 0x1400, 0xF001, 0x3C00, - 0x2800, 0xE401, 0xA001, - 0x6C00, 0x7800, 0xB401, - 0x5000, 0x9C01, 0x8801, - 0x4400 - }; - - for (ucIndex = 0; ucIndex < 8; ucIndex++) { - ucFlipData <<= 1; - if (a_ucData & 0x01) { - ucFlipData |= 0x01; - } - a_ucData >>= 1; - } - - /* 09/11/07 NN Type cast mismatch variables */ - usCRCTableEntry = (unsigned short)(crc_table[g_usCalculatedCRC & 0xF]); - g_usCalculatedCRC = (unsigned short)((g_usCalculatedCRC >> 4) & 0x0FFF); - g_usCalculatedCRC = (unsigned short)(g_usCalculatedCRC ^ - usCRCTableEntry ^ crc_table[ucFlipData & 0xF]); - usCRCTableEntry = (unsigned short)(crc_table[g_usCalculatedCRC & 0xF]); - g_usCalculatedCRC = (unsigned short)((g_usCalculatedCRC >> 4) & 0x0FFF); - g_usCalculatedCRC = (unsigned short)(g_usCalculatedCRC ^ - usCRCTableEntry ^ crc_table[(ucFlipData >> 4) & 0xF]); -} - -/* - * - * ispVMLCOUNT - * - * Process the intelligent programming loops. - * - */ - -signed char ispVMLCOUNT(unsigned short a_usCountSize) -{ - unsigned short usContinue = 1; - unsigned short usIntelBufferIndex = 0; - unsigned short usCountIndex = 0; - signed char cRetCode = 0; - signed char cRepeatHeap = 0; - signed char cOpcode = 0; - unsigned char ucState = 0; - unsigned short usDelay = 0; - unsigned short usToggle = 0; - - g_usIntelBufferSize = (unsigned short)ispVMDataSize(); - - /* - * Allocate memory for intel buffer. - * - */ - - ispVMMemManager(LHEAP, g_usIntelBufferSize); - - /* - * Store the maximum size of the intelligent buffer. - * Used to convert VME to HEX. - */ - - if (g_usIntelBufferSize > g_usLCOUNTSize) { - g_usLCOUNTSize = g_usIntelBufferSize; - } - - /* - * Copy intel data to the buffer. - */ - - for (usIntelBufferIndex = 0; usIntelBufferIndex < g_usIntelBufferSize; - usIntelBufferIndex++) { - g_pucIntelBuffer[usIntelBufferIndex] = GetByte(); - } - - /* - * Set the data type register to get data from the intelligent - * data buffer. - */ - - g_usDataType |= LHEAP_IN; - - /* - * - * If the HEAP_IN flag is set, temporarily unset the flag so data will be - * retrieved from the status buffer. - * - **/ - - if (g_usDataType & HEAP_IN) { - g_usDataType &= ~HEAP_IN; - cRepeatHeap = 1; - } - -#ifdef DEBUG - printf("LCOUNT %d;\n", a_usCountSize); -#endif /* DEBUG */ - - /* - * Iterate through the intelligent programming command. - */ - - for (usCountIndex = 0; usCountIndex < a_usCountSize; usCountIndex++) { - - /* - * - * Initialize the intel data index to 0 before each iteration. - * - **/ - - g_usIntelDataIndex = 0; - cOpcode = 0; - ucState = 0; - usDelay = 0; - usToggle = 0; - usContinue = 1; - - /* - * - * Begin looping through all the VME opcodes. - * - */ - /* - * 4/1/09 Nguyen replaced the recursive function call codes on - * the ispVMLCOUNT function - * - */ - while (usContinue) { - cOpcode = GetByte(); - switch (cOpcode) { - case HIR: - case TIR: - case HDR: - case TDR: - /* - * Set the header/trailer of the device in order - * to bypass successfully. - */ - - ispVMAmble(cOpcode); - break; - case STATE: - - /* - * Step the JTAG state machine. - */ - - ucState = GetByte(); - /* - * Step the JTAG state machine to DRCAPTURE - * to support Looping. - */ - - if ((g_usDataType & LHEAP_IN) && - (ucState == DRPAUSE) && - (g_cCurrentJTAGState == ucState)) { - ispVMStateMachine(DRCAPTURE); - } - ispVMStateMachine(ucState); -#ifdef DEBUG - printf("LDELAY %s ", GetState(ucState)); -#endif /* DEBUG */ - break; - case SIR: -#ifdef DEBUG - printf("SIR "); -#endif /* DEBUG */ - /* - * Shift in data into the device. - */ - - cRetCode = ispVMShift(cOpcode); - break; - case SDR: - -#ifdef DEBUG - printf("LSDR "); -#endif /* DEBUG */ - /* - * Shift in data into the device. - */ - - cRetCode = ispVMShift(cOpcode); - break; - case WAIT: - - /* - * - * Observe delay. - * - */ - - usDelay = (unsigned short)ispVMDataSize(); - ispVMDelay(usDelay); - -#ifdef DEBUG - if (usDelay & 0x8000) { - - /* - * Since MSB is set, the delay time must - * be decoded to millisecond. The - * SVF2VME encodes the MSB to represent - * millisecond. - */ - - usDelay &= ~0x8000; - printf("%.2E SEC;\n", - (float) usDelay / 1000); - } else { - /* - * Since MSB is not set, the delay time - * is given as microseconds. - */ - - printf("%.2E SEC;\n", - (float) usDelay / 1000000); - } -#endif /* DEBUG */ - break; - case TCK: - - /* - * Issue clock toggles. - */ - - usToggle = (unsigned short)ispVMDataSize(); - ispVMClocks(usToggle); - -#ifdef DEBUG - printf("RUNTEST %d TCK;\n", usToggle); -#endif /* DEBUG */ - break; - case ENDLOOP: - - /* - * Exit point from processing loops. - */ - usContinue = 0; - break; - - case COMMENT: - - /* - * Display comment. - */ - - ispVMComment((unsigned short) ispVMDataSize()); - break; - case ispEN: - ucState = GetByte(); - if ((ucState == ON) || (ucState == 0x01)) - writePort(g_ucPinENABLE, 0x01); - else - writePort(g_ucPinENABLE, 0x00); - ispVMDelay(1); - break; - case TRST: - if (GetByte() == 0x01) - writePort(g_ucPinTRST, 0x01); - else - writePort(g_ucPinTRST, 0x00); - ispVMDelay(1); - break; - default: - - /* - * Invalid opcode encountered. - */ - - debug("\nINVALID OPCODE: 0x%.2X\n", cOpcode); - - return VME_INVALID_FILE; - } - } - if (cRetCode >= 0) { - /* - * Break if intelligent programming is successful. - */ - - break; - } - - } - /* - * If HEAP_IN flag was temporarily disabled, - * re-enable it before exiting - */ - - if (cRepeatHeap) { - g_usDataType |= HEAP_IN; - } - - /* - * Set the data type register to not get data from the - * intelligent data buffer. - */ - - g_usDataType &= ~LHEAP_IN; - return cRetCode; -} -/* - * - * ispVMClocks - * - * Applies the specified number of pulses to TCK. - * - */ - -void ispVMClocks(unsigned short Clocks) -{ - unsigned short iClockIndex = 0; - for (iClockIndex = 0; iClockIndex < Clocks; iClockIndex++) { - sclock(); - } -} - -/* - * - * ispVMBypass - * - * This procedure takes care of the HIR, HDR, TIR, TDR for the - * purpose of putting the other devices into Bypass mode. The - * current state is checked to find out if it is at DRPAUSE or - * IRPAUSE. If it is at DRPAUSE, perform bypass register scan. - * If it is at IRPAUSE, scan into instruction registers the bypass - * instruction. - * - */ - -void ispVMBypass(signed char ScanType, unsigned short Bits) -{ - /* 09/11/07 NN added local variables initialization */ - unsigned short iIndex = 0; - unsigned short iSourceIndex = 0; - unsigned char cBitState = 0; - unsigned char cCurByte = 0; - unsigned char *pcSource = NULL; - - if (Bits <= 0) { - return; - } - - switch (ScanType) { - case HIR: - pcSource = g_pucHIRData; - break; - case TIR: - pcSource = g_pucTIRData; - break; - case HDR: - pcSource = g_pucHDRData; - break; - case TDR: - pcSource = g_pucTDRData; - break; - default: - break; - } - - iSourceIndex = 0; - cBitState = 0; - for (iIndex = 0; iIndex < Bits - 1; iIndex++) { - /* Scan instruction or bypass register */ - if (iIndex % 8 == 0) { - cCurByte = pcSource[iSourceIndex++]; - } - cBitState = (unsigned char) (((cCurByte << iIndex % 8) & 0x80) - ? 0x01 : 0x00); - writePort(g_ucPinTDI, cBitState); - sclock(); - } - - if (iIndex % 8 == 0) { - cCurByte = pcSource[iSourceIndex++]; - } - - cBitState = (unsigned char) (((cCurByte << iIndex % 8) & 0x80) - ? 0x01 : 0x00); - writePort(g_ucPinTDI, cBitState); -} - -/* - * - * ispVMStateMachine - * - * This procedure steps all devices in the daisy chain from a given - * JTAG state to the next desirable state. If the next state is TLR, - * the JTAG state machine is brute forced into TLR by driving TMS - * high and pulse TCK 6 times. - * - */ - -void ispVMStateMachine(signed char cNextJTAGState) -{ - /* 09/11/07 NN added local variables initialization */ - signed char cPathIndex = 0; - signed char cStateIndex = 0; - - if ((g_cCurrentJTAGState == cNextJTAGState) && - (cNextJTAGState != RESET)) { - return; - } - - for (cStateIndex = 0; cStateIndex < 25; cStateIndex++) { - if ((g_cCurrentJTAGState == - g_JTAGTransistions[cStateIndex].CurState) && - (cNextJTAGState == - g_JTAGTransistions[cStateIndex].NextState)) { - break; - } - } - - g_cCurrentJTAGState = cNextJTAGState; - for (cPathIndex = 0; - cPathIndex < g_JTAGTransistions[cStateIndex].Pulses; - cPathIndex++) { - if ((g_JTAGTransistions[cStateIndex].Pattern << cPathIndex) - & 0x80) { - writePort(g_ucPinTMS, (unsigned char) 0x01); - } else { - writePort(g_ucPinTMS, (unsigned char) 0x00); - } - sclock(); - } - - writePort(g_ucPinTDI, 0x00); - writePort(g_ucPinTMS, 0x00); -} - -/* - * - * ispVMStart - * - * Enable the port to the device and set the state to RESET (TLR). - * - */ - -void ispVMStart(void) -{ -#ifdef DEBUG - printf("// ISPVM EMBEDDED ADDED\n"); - printf("STATE RESET;\n"); -#endif - g_usFlowControl = 0; - g_usDataType = g_uiChecksumIndex = g_cCurrentJTAGState = 0; - g_usHeadDR = g_usHeadIR = g_usTailDR = g_usTailIR = 0; - g_usMaxSize = g_usShiftValue = g_usRepeatLoops = 0; - g_usTDOSize = g_usMASKSize = g_usTDISize = 0; - g_usDMASKSize = g_usLCOUNTSize = g_usHDRSize = 0; - g_usTDRSize = g_usHIRSize = g_usTIRSize = g_usHeapSize = 0; - g_pLVDSList = NULL; - g_usLVDSPairCount = 0; - previous_size = 0; - - ispVMStateMachine(RESET); /*step devices to RESET state*/ -} - -/* - * - * ispVMEnd - * - * Set the state of devices to RESET to enable the devices and disable - * the port. - * - */ - -void ispVMEnd(void) -{ -#ifdef DEBUG - printf("// ISPVM EMBEDDED ADDED\n"); - printf("STATE RESET;\n"); - printf("RUNTEST 1.00E-001 SEC;\n"); -#endif - - ispVMStateMachine(RESET); /*step devices to RESET state */ - ispVMDelay(1000); /*wake up devices*/ -} - -/* - * - * ispVMSend - * - * Send the TDI data stream to devices. The data stream can be - * instructions or data. - * - */ - -signed char ispVMSend(unsigned short a_usiDataSize) -{ - /* 09/11/07 NN added local variables initialization */ - unsigned short iIndex = 0; - unsigned short iInDataIndex = 0; - unsigned char cCurByte = 0; - unsigned char cBitState = 0; - - for (iIndex = 0; iIndex < a_usiDataSize - 1; iIndex++) { - if (iIndex % 8 == 0) { - cCurByte = g_pucInData[iInDataIndex++]; - } - cBitState = (unsigned char)(((cCurByte << iIndex % 8) & 0x80) - ? 0x01 : 0x00); - writePort(g_ucPinTDI, cBitState); - sclock(); - } - - if (iIndex % 8 == 0) { - /* Take care of the last bit */ - cCurByte = g_pucInData[iInDataIndex]; - } - - cBitState = (unsigned char) (((cCurByte << iIndex % 8) & 0x80) - ? 0x01 : 0x00); - - writePort(g_ucPinTDI, cBitState); - if (g_usFlowControl & CASCADE) { - /*1/15/04 Clock in last bit for the first n-1 cascaded frames */ - sclock(); - } - - return 0; -} - -/* - * - * ispVMRead - * - * Read the data stream from devices and verify. - * - */ - -signed char ispVMRead(unsigned short a_usiDataSize) -{ - /* 09/11/07 NN added local variables initialization */ - unsigned short usDataSizeIndex = 0; - unsigned short usErrorCount = 0; - unsigned short usLastBitIndex = 0; - unsigned char cDataByte = 0; - unsigned char cMaskByte = 0; - unsigned char cInDataByte = 0; - unsigned char cCurBit = 0; - unsigned char cByteIndex = 0; - unsigned short usBufferIndex = 0; - unsigned char ucDisplayByte = 0x00; - unsigned char ucDisplayFlag = 0x01; - char StrChecksum[256] = {0}; - unsigned char g_usCalculateChecksum = 0x00; - - /* 09/11/07 NN Type cast mismatch variables */ - usLastBitIndex = (unsigned short)(a_usiDataSize - 1); - -#ifndef DEBUG - /* - * If mask is not all zeros, then set the display flag to 0x00, - * otherwise it shall be set to 0x01 to indicate that data read - * from the device shall be displayed. If DEBUG is defined, - * always display data. - */ - - for (usDataSizeIndex = 0; usDataSizeIndex < (a_usiDataSize + 7) / 8; - usDataSizeIndex++) { - if (g_usDataType & MASK_DATA) { - if (g_pucOutMaskData[usDataSizeIndex] != 0x00) { - ucDisplayFlag = 0x00; - break; - } - } else if (g_usDataType & CMASK_DATA) { - g_usCalculateChecksum = 0x01; - ucDisplayFlag = 0x00; - break; - } else { - ucDisplayFlag = 0x00; - break; - } - } -#endif /* DEBUG */ - - /* - * - * Begin shifting data in and out of the device. - * - **/ - - for (usDataSizeIndex = 0; usDataSizeIndex < a_usiDataSize; - usDataSizeIndex++) { - if (cByteIndex == 0) { - - /* - * Grab byte from TDO buffer. - */ - - if (g_usDataType & TDO_DATA) { - cDataByte = g_pucOutData[usBufferIndex]; - } - - /* - * Grab byte from MASK buffer. - */ - - if (g_usDataType & MASK_DATA) { - cMaskByte = g_pucOutMaskData[usBufferIndex]; - } else { - cMaskByte = 0xFF; - } - - /* - * Grab byte from CMASK buffer. - */ - - if (g_usDataType & CMASK_DATA) { - cMaskByte = 0x00; - g_usCalculateChecksum = 0x01; - } - - /* - * Grab byte from TDI buffer. - */ - - if (g_usDataType & TDI_DATA) { - cInDataByte = g_pucInData[usBufferIndex]; - } - - usBufferIndex++; - } - - cCurBit = readPort(); - - if (ucDisplayFlag) { - ucDisplayByte <<= 1; - ucDisplayByte |= cCurBit; - } - - /* - * Check if data read from port matches with expected TDO. - */ - - if (g_usDataType & TDO_DATA) { - /* 08/28/08 NN Added Calculate checksum support. */ - if (g_usCalculateChecksum) { - if (cCurBit == 0x01) - g_usChecksum += - (1 << (g_uiChecksumIndex % 8)); - g_uiChecksumIndex++; - } else { - if ((((cMaskByte << cByteIndex) & 0x80) - ? 0x01 : 0x00)) { - if (cCurBit != (unsigned char) - (((cDataByte << cByteIndex) & 0x80) - ? 0x01 : 0x00)) { - usErrorCount++; - } - } - } - } - - /* - * Write TDI data to the port. - */ - - writePort(g_ucPinTDI, - (unsigned char)(((cInDataByte << cByteIndex) & 0x80) - ? 0x01 : 0x00)); - - if (usDataSizeIndex < usLastBitIndex) { - - /* - * Clock data out from the data shift register. - */ - - sclock(); - } else if (g_usFlowControl & CASCADE) { - - /* - * Clock in last bit for the first N - 1 cascaded frames - */ - - sclock(); - } - - /* - * Increment the byte index. If it exceeds 7, then reset it back - * to zero. - */ - - cByteIndex++; - if (cByteIndex >= 8) { - if (ucDisplayFlag) { - - /* - * Store displayed data in the TDO buffer. By reusing - * the TDO buffer to store displayed data, there is no - * need to allocate a buffer simply to hold display - * data. This will not cause any false verification - * errors because the true TDO byte has already - * been consumed. - */ - - g_pucOutData[usBufferIndex - 1] = ucDisplayByte; - ucDisplayByte = 0; - } - - cByteIndex = 0; - } - /* 09/12/07 Nguyen changed to display the 1 bit expected data */ - else if (a_usiDataSize == 1) { - if (ucDisplayFlag) { - - /* - * Store displayed data in the TDO buffer. - * By reusing the TDO buffer to store displayed - * data, there is no need to allocate - * a buffer simply to hold display data. This - * will not cause any false verification errors - * because the true TDO byte has already - * been consumed. - */ - - /* - * Flip ucDisplayByte and store it in cDataByte. - */ - cDataByte = 0x00; - for (usBufferIndex = 0; usBufferIndex < 8; - usBufferIndex++) { - cDataByte <<= 1; - if (ucDisplayByte & 0x01) { - cDataByte |= 0x01; - } - ucDisplayByte >>= 1; - } - g_pucOutData[0] = cDataByte; - ucDisplayByte = 0; - } - - cByteIndex = 0; - } - } - - if (ucDisplayFlag) { - -#ifdef DEBUG - debug("RECEIVED TDO ("); -#else - vme_out_string("Display Data: 0x"); -#endif /* DEBUG */ - - /* 09/11/07 NN Type cast mismatch variables */ - for (usDataSizeIndex = (unsigned short) - ((a_usiDataSize + 7) / 8); - usDataSizeIndex > 0 ; usDataSizeIndex--) { - cMaskByte = g_pucOutData[usDataSizeIndex - 1]; - cDataByte = 0x00; - - /* - * Flip cMaskByte and store it in cDataByte. - */ - - for (usBufferIndex = 0; usBufferIndex < 8; - usBufferIndex++) { - cDataByte <<= 1; - if (cMaskByte & 0x01) { - cDataByte |= 0x01; - } - cMaskByte >>= 1; - } -#ifdef DEBUG - printf("%.2X", cDataByte); - if ((((a_usiDataSize + 7) / 8) - usDataSizeIndex) - % 40 == 39) { - printf("\n\t\t"); - } -#else - vme_out_hex(cDataByte); -#endif /* DEBUG */ - } - -#ifdef DEBUG - printf(")\n\n"); -#else - vme_out_string("\n\n"); -#endif /* DEBUG */ - /* 09/02/08 Nguyen changed to display the data Checksum */ - if (g_usChecksum != 0) { - g_usChecksum &= 0xFFFF; - sprintf(StrChecksum, "Data Checksum: %.4lX\n\n", - g_usChecksum); - vme_out_string(StrChecksum); - g_usChecksum = 0; - } - } - - if (usErrorCount > 0) { - if (g_usFlowControl & VERIFYUES) { - vme_out_string( - "USERCODE verification failed. " - "Continue programming......\n\n"); - g_usFlowControl &= ~(VERIFYUES); - return 0; - } else { - -#ifdef DEBUG - printf("TOTAL ERRORS: %d\n", usErrorCount); -#endif /* DEBUG */ - - return VME_VERIFICATION_FAILURE; - } - } else { - if (g_usFlowControl & VERIFYUES) { - vme_out_string("USERCODE verification passed. " - "Programming aborted.\n\n"); - g_usFlowControl &= ~(VERIFYUES); - return 1; - } else { - return 0; - } - } -} - -/* - * - * ispVMReadandSave - * - * Support dynamic I/O. - * - */ - -signed char ispVMReadandSave(unsigned short int a_usiDataSize) -{ - /* 09/11/07 NN added local variables initialization */ - unsigned short int usDataSizeIndex = 0; - unsigned short int usLastBitIndex = 0; - unsigned short int usBufferIndex = 0; - unsigned short int usOutBitIndex = 0; - unsigned short int usLVDSIndex = 0; - unsigned char cDataByte = 0; - unsigned char cDMASKByte = 0; - unsigned char cInDataByte = 0; - unsigned char cCurBit = 0; - unsigned char cByteIndex = 0; - signed char cLVDSByteIndex = 0; - - /* 09/11/07 NN Type cast mismatch variables */ - usLastBitIndex = (unsigned short) (a_usiDataSize - 1); - - /* - * - * Iterate through the data bits. - * - */ - - for (usDataSizeIndex = 0; usDataSizeIndex < a_usiDataSize; - usDataSizeIndex++) { - if (cByteIndex == 0) { - - /* - * Grab byte from DMASK buffer. - */ - - if (g_usDataType & DMASK_DATA) { - cDMASKByte = g_pucOutDMaskData[usBufferIndex]; - } else { - cDMASKByte = 0x00; - } - - /* - * Grab byte from TDI buffer. - */ - - if (g_usDataType & TDI_DATA) { - cInDataByte = g_pucInData[usBufferIndex]; - } - - usBufferIndex++; - } - - cCurBit = readPort(); - cDataByte = (unsigned char)(((cInDataByte << cByteIndex) & 0x80) - ? 0x01 : 0x00); - - /* - * Initialize the byte to be zero. - */ - - if (usOutBitIndex % 8 == 0) { - g_pucOutData[usOutBitIndex / 8] = 0x00; - } - - /* - * Use TDI, DMASK, and device TDO to create new TDI (actually - * stored in g_pucOutData). - */ - - if ((((cDMASKByte << cByteIndex) & 0x80) ? 0x01 : 0x00)) { - - if (g_pLVDSList) { - for (usLVDSIndex = 0; - usLVDSIndex < g_usLVDSPairCount; - usLVDSIndex++) { - if (g_pLVDSList[usLVDSIndex]. - usNegativeIndex == - usDataSizeIndex) { - g_pLVDSList[usLVDSIndex]. - ucUpdate = 0x01; - break; - } - } - } - - /* - * DMASK bit is 1, use TDI. - */ - - g_pucOutData[usOutBitIndex / 8] |= (unsigned char) - (((cDataByte & 0x1) ? 0x01 : 0x00) << - (7 - usOutBitIndex % 8)); - } else { - - /* - * DMASK bit is 0, use device TDO. - */ - - g_pucOutData[usOutBitIndex / 8] |= (unsigned char) - (((cCurBit & 0x1) ? 0x01 : 0x00) << - (7 - usOutBitIndex % 8)); - } - - /* - * Shift in TDI in order to get TDO out. - */ - - usOutBitIndex++; - writePort(g_ucPinTDI, cDataByte); - if (usDataSizeIndex < usLastBitIndex) { - sclock(); - } - - /* - * Increment the byte index. If it exceeds 7, then reset it back - * to zero. - */ - - cByteIndex++; - if (cByteIndex >= 8) { - cByteIndex = 0; - } - } - - /* - * If g_pLVDSList exists and pairs need updating, then update - * the negative-pair to receive the flipped positive-pair value. - */ - - if (g_pLVDSList) { - for (usLVDSIndex = 0; usLVDSIndex < g_usLVDSPairCount; - usLVDSIndex++) { - if (g_pLVDSList[usLVDSIndex].ucUpdate) { - - /* - * Read the positive value and flip it. - */ - - cDataByte = (unsigned char) - (((g_pucOutData[g_pLVDSList[usLVDSIndex]. - usPositiveIndex / 8] - << (g_pLVDSList[usLVDSIndex]. - usPositiveIndex % 8)) & 0x80) ? - 0x01 : 0x00); - /* 09/11/07 NN Type cast mismatch variables */ - cDataByte = (unsigned char) (!cDataByte); - - /* - * Get the byte that needs modification. - */ - - cInDataByte = - g_pucOutData[g_pLVDSList[usLVDSIndex]. - usNegativeIndex / 8]; - - if (cDataByte) { - - /* - * Copy over the current byte and - * set the negative bit to 1. - */ - - cDataByte = 0x00; - for (cLVDSByteIndex = 7; - cLVDSByteIndex >= 0; - cLVDSByteIndex--) { - cDataByte <<= 1; - if (7 - - (g_pLVDSList[usLVDSIndex]. - usNegativeIndex % 8) == - cLVDSByteIndex) { - - /* - * Set negative bit to 1 - */ - - cDataByte |= 0x01; - } else if (cInDataByte & 0x80) { - cDataByte |= 0x01; - } - - cInDataByte <<= 1; - } - - /* - * Store the modified byte. - */ - - g_pucOutData[g_pLVDSList[usLVDSIndex]. - usNegativeIndex / 8] = cDataByte; - } else { - - /* - * Copy over the current byte and set - * the negative bit to 0. - */ - - cDataByte = 0x00; - for (cLVDSByteIndex = 7; - cLVDSByteIndex >= 0; - cLVDSByteIndex--) { - cDataByte <<= 1; - if (7 - - (g_pLVDSList[usLVDSIndex]. - usNegativeIndex % 8) == - cLVDSByteIndex) { - - /* - * Set negative bit to 0 - */ - - cDataByte |= 0x00; - } else if (cInDataByte & 0x80) { - cDataByte |= 0x01; - } - - cInDataByte <<= 1; - } - - /* - * Store the modified byte. - */ - - g_pucOutData[g_pLVDSList[usLVDSIndex]. - usNegativeIndex / 8] = cDataByte; - } - - break; - } - } - } - - return 0; -} - -signed char ispVMProcessLVDS(unsigned short a_usLVDSCount) -{ - unsigned short usLVDSIndex = 0; - - /* - * Allocate memory to hold LVDS pairs. - */ - - ispVMMemManager(LVDS, a_usLVDSCount); - g_usLVDSPairCount = a_usLVDSCount; - -#ifdef DEBUG - printf("LVDS %d (", a_usLVDSCount); -#endif /* DEBUG */ - - /* - * Iterate through each given LVDS pair. - */ - - for (usLVDSIndex = 0; usLVDSIndex < g_usLVDSPairCount; usLVDSIndex++) { - - /* - * Assign the positive and negative indices of the LVDS pair. - */ - - /* 09/11/07 NN Type cast mismatch variables */ - g_pLVDSList[usLVDSIndex].usPositiveIndex = - (unsigned short) ispVMDataSize(); - /* 09/11/07 NN Type cast mismatch variables */ - g_pLVDSList[usLVDSIndex].usNegativeIndex = - (unsigned short)ispVMDataSize(); - -#ifdef DEBUG - if (usLVDSIndex < g_usLVDSPairCount - 1) { - printf("%d:%d, ", - g_pLVDSList[usLVDSIndex].usPositiveIndex, - g_pLVDSList[usLVDSIndex].usNegativeIndex); - } else { - printf("%d:%d", - g_pLVDSList[usLVDSIndex].usPositiveIndex, - g_pLVDSList[usLVDSIndex].usNegativeIndex); - } -#endif /* DEBUG */ - - } - -#ifdef DEBUG - printf(");\n"); -#endif /* DEBUG */ - - return 0; -} diff --git a/drivers/fpga/lattice.c b/drivers/fpga/lattice.c deleted file mode 100644 index 29cf2f60974..00000000000 --- a/drivers/fpga/lattice.c +++ /dev/null @@ -1,379 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -/* - * (C) Copyright 2010 - * Stefano Babic, DENX Software Engineering, sbabic@denx.de. - * - * (C) Copyright 2002 - * Rich Ireland, Enterasys Networks, rireland@enterasys.com. - * - * ispVM functions adapted from Lattice's ispmVMEmbedded code: - * Copyright 2009 Lattice Semiconductor Corp. - */ - -#include -#include -#include -#include -#include - -static lattice_board_specific_func *pfns; -static const char *fpga_image; -static unsigned long read_bytes; -static unsigned long bufsize; -static unsigned short expectedCRC; - -/* - * External variables and functions declared in ivm_core.c module. - */ -extern unsigned short g_usCalculatedCRC; -extern unsigned short g_usDataType; -extern unsigned char *g_pucIntelBuffer; -extern unsigned char *g_pucHeapMemory; -extern unsigned short g_iHeapCounter; -extern unsigned short g_iHEAPSize; -extern unsigned short g_usIntelDataIndex; -extern unsigned short g_usIntelBufferSize; -extern char *const g_szSupportedVersions[]; - -/* - * ispVMDelay - * - * Users must implement a delay to observe a_usTimeDelay, where - * bit 15 of the a_usTimeDelay defines the unit. - * 1 = milliseconds - * 0 = microseconds - * Example: - * a_usTimeDelay = 0x0001 = 1 microsecond delay. - * a_usTimeDelay = 0x8001 = 1 millisecond delay. - * - * This subroutine is called upon to provide a delay from 1 millisecond to a few - * hundreds milliseconds each time. - * It is understood that due to a_usTimeDelay is defined as unsigned short, a 16 - * bits integer, this function is restricted to produce a delay to 64000 - * micro-seconds or 32000 milli-second maximum. The VME file will never pass on - * to this function a delay time > those maximum number. If it needs more than - * those maximum, the VME file will launch the delay function several times to - * realize a larger delay time cummulatively. - * It is perfectly alright to provide a longer delay than required. It is not - * acceptable if the delay is shorter. - */ -void ispVMDelay(unsigned short delay) -{ - if (delay & 0x8000) - delay = (delay & ~0x8000) * 1000; - udelay(delay); -} - -void writePort(unsigned char a_ucPins, unsigned char a_ucValue) -{ - a_ucValue = a_ucValue ? 1 : 0; - - switch (a_ucPins) { - case g_ucPinTDI: - pfns->jtag_set_tdi(a_ucValue); - break; - case g_ucPinTCK: - pfns->jtag_set_tck(a_ucValue); - break; - case g_ucPinTMS: - pfns->jtag_set_tms(a_ucValue); - break; - default: - printf("%s: requested unknown pin\n", __func__); - } -} - -unsigned char readPort(void) -{ - return pfns->jtag_get_tdo(); -} - -void sclock(void) -{ - writePort(g_ucPinTCK, 0x01); - writePort(g_ucPinTCK, 0x00); -} - -void calibration(void) -{ - /* Apply 2 pulses to TCK. */ - writePort(g_ucPinTCK, 0x00); - writePort(g_ucPinTCK, 0x01); - writePort(g_ucPinTCK, 0x00); - writePort(g_ucPinTCK, 0x01); - writePort(g_ucPinTCK, 0x00); - - ispVMDelay(0x8001); - - /* Apply 2 pulses to TCK. */ - writePort(g_ucPinTCK, 0x01); - writePort(g_ucPinTCK, 0x00); - writePort(g_ucPinTCK, 0x01); - writePort(g_ucPinTCK, 0x00); -} - -/* - * GetByte - * - * Returns a byte to the caller. The returned byte depends on the - * g_usDataType register. If the HEAP_IN bit is set, then the byte - * is returned from the HEAP. If the LHEAP_IN bit is set, then - * the byte is returned from the intelligent buffer. Otherwise, - * the byte is returned directly from the VME file. - */ -unsigned char GetByte(void) -{ - unsigned char ucData; - unsigned int block_size = 4 * 1024; - - if (g_usDataType & HEAP_IN) { - - /* - * Get data from repeat buffer. - */ - - if (g_iHeapCounter > g_iHEAPSize) { - - /* - * Data over-run. - */ - - return 0xFF; - } - - ucData = g_pucHeapMemory[g_iHeapCounter++]; - } else if (g_usDataType & LHEAP_IN) { - - /* - * Get data from intel buffer. - */ - - if (g_usIntelDataIndex >= g_usIntelBufferSize) { - return 0xFF; - } - - ucData = g_pucIntelBuffer[g_usIntelDataIndex++]; - } else { - if (read_bytes == bufsize) { - return 0xFF; - } - ucData = *fpga_image++; - read_bytes++; - - if (!(read_bytes % block_size)) { - printf("Downloading FPGA %ld/%ld completed\r", - read_bytes, - bufsize); - } - - if (expectedCRC != 0) { - ispVMCalculateCRC32(ucData); - } - } - - return ucData; -} - -signed char ispVM(void) -{ - char szFileVersion[9] = { 0 }; - signed char cRetCode = 0; - signed char cIndex = 0; - signed char cVersionIndex = 0; - unsigned char ucReadByte = 0; - unsigned short crc; - - g_pucHeapMemory = NULL; - g_iHeapCounter = 0; - g_iHEAPSize = 0; - g_usIntelDataIndex = 0; - g_usIntelBufferSize = 0; - g_usCalculatedCRC = 0; - expectedCRC = 0; - ucReadByte = GetByte(); - switch (ucReadByte) { - case FILE_CRC: - crc = (unsigned char)GetByte(); - crc <<= 8; - crc |= GetByte(); - expectedCRC = crc; - - for (cIndex = 0; cIndex < 8; cIndex++) - szFileVersion[cIndex] = GetByte(); - - break; - default: - szFileVersion[0] = (signed char) ucReadByte; - for (cIndex = 1; cIndex < 8; cIndex++) - szFileVersion[cIndex] = GetByte(); - - break; - } - - /* - * - * Compare the VME file version against the supported version. - * - */ - - for (cVersionIndex = 0; g_szSupportedVersions[cVersionIndex] != 0; - cVersionIndex++) { - for (cIndex = 0; cIndex < 8; cIndex++) { - if (szFileVersion[cIndex] != - g_szSupportedVersions[cVersionIndex][cIndex]) { - cRetCode = VME_VERSION_FAILURE; - break; - } - cRetCode = 0; - } - - if (cRetCode == 0) { - break; - } - } - - if (cRetCode < 0) { - return VME_VERSION_FAILURE; - } - - printf("VME file checked: starting downloading to FPGA\n"); - - ispVMStart(); - - cRetCode = ispVMCode(); - - ispVMEnd(); - ispVMFreeMem(); - puts("\n"); - - if (cRetCode == 0 && expectedCRC != 0 && - (expectedCRC != g_usCalculatedCRC)) { - printf("Expected CRC: 0x%.4X\n", expectedCRC); - printf("Calculated CRC: 0x%.4X\n", g_usCalculatedCRC); - return VME_CRC_FAILURE; - } - return cRetCode; -} - -static int lattice_validate(Lattice_desc *desc, const char *fn) -{ - int ret_val = false; - - if (desc) { - if ((desc->family > min_lattice_type) && - (desc->family < max_lattice_type)) { - if ((desc->iface > min_lattice_iface_type) && - (desc->iface < max_lattice_iface_type)) { - if (desc->size) { - ret_val = true; - } else { - printf("%s: NULL part size\n", fn); - } - } else { - printf("%s: Invalid Interface type, %d\n", - fn, desc->iface); - } - } else { - printf("%s: Invalid family type, %d\n", - fn, desc->family); - } - } else { - printf("%s: NULL descriptor!\n", fn); - } - - return ret_val; -} - -int lattice_load(Lattice_desc *desc, const void *buf, size_t bsize) -{ - int ret_val = FPGA_FAIL; - - if (!lattice_validate(desc, (char *)__func__)) { - printf("%s: Invalid device descriptor\n", __func__); - } else { - pfns = desc->iface_fns; - - switch (desc->family) { - case Lattice_XP2: - fpga_image = buf; - read_bytes = 0; - bufsize = bsize; - debug("%s: Launching the Lattice ISPVME Loader:" - " addr %p size 0x%lx...\n", - __func__, fpga_image, bufsize); - ret_val = ispVM(); - if (ret_val) - printf("%s: error %d downloading FPGA image\n", - __func__, ret_val); - else - puts("FPGA downloaded successfully\n"); - break; - default: - printf("%s: Unsupported family type, %d\n", - __func__, desc->family); - } - } - - return ret_val; -} - -int lattice_dump(Lattice_desc *desc, const void *buf, size_t bsize) -{ - puts("Dump not supported for Lattice FPGA\n"); - - return FPGA_FAIL; - -} - -int lattice_info(Lattice_desc *desc) -{ - int ret_val = FPGA_FAIL; - - if (lattice_validate(desc, (char *)__func__)) { - printf("Family: \t"); - switch (desc->family) { - case Lattice_XP2: - puts("XP2\n"); - break; - /* Add new family types here */ - default: - printf("Unknown family type, %d\n", desc->family); - } - - puts("Interface type:\t"); - switch (desc->iface) { - case lattice_jtag_mode: - puts("JTAG Mode\n"); - break; - /* Add new interface types here */ - default: - printf("Unsupported interface type, %d\n", desc->iface); - } - - printf("Device Size: \t%zu bytes\n", - desc->size); - - if (desc->iface_fns) { - printf("Device Function Table @ 0x%p\n", - desc->iface_fns); - switch (desc->family) { - case Lattice_XP2: - break; - /* Add new family types here */ - default: - break; - } - } else { - puts("No Device Function Table.\n"); - } - - if (desc->desc) - printf("Model: \t%s\n", desc->desc); - - ret_val = FPGA_SUCCESS; - } else { - printf("%s: Invalid device descriptor\n", __func__); - } - - return ret_val; -} -- cgit v1.2.3 From 88e3524393fa88dbf675119aa89885bf144592ec Mon Sep 17 00:00:00 2001 From: Andrew Goodbody Date: Mon, 18 Aug 2025 10:24:36 +0100 Subject: net: axi_emac: Fix timeout test The timeout test in axi_dma_init is not correct due to the post-decrement used on the timeout variable which will mean timeout is not 0 if the timeout occurs. Make the timeout variable an int instead of a u32 and then test for timeout being -1. This issue was found by Smatch. Signed-off-by: Andrew Goodbody Link: https://lore.kernel.org/r/20250806-net_xilinx_axi-v2-1-6311cf59451d@linaro.org Signed-off-by: Michal Simek --- drivers/net/xilinx_axi_emac.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/xilinx_axi_emac.c b/drivers/net/xilinx_axi_emac.c index c8038ddef1b..22e119370c8 100644 --- a/drivers/net/xilinx_axi_emac.c +++ b/drivers/net/xilinx_axi_emac.c @@ -558,7 +558,7 @@ static int axiemac_write_hwaddr(struct udevice *dev) /* Reset DMA engine */ static void axi_dma_init(struct axidma_priv *priv) { - u32 timeout = 500; + int timeout = 500; /* Reset the engine so the hardware starts from a known state */ writel(XAXIDMA_CR_RESET_MASK, &priv->dmatx->control); @@ -571,11 +571,11 @@ static void axi_dma_init(struct axidma_priv *priv) if (!((readl(&priv->dmatx->control) | readl(&priv->dmarx->control)) & XAXIDMA_CR_RESET_MASK)) { - break; + return; } } - if (!timeout) - printf("%s: Timeout\n", __func__); + + printf("%s: Timeout\n", __func__); } static int axiemac_start(struct udevice *dev) -- cgit v1.2.3 From bd5036ddf2f3d9198f4054fc1a807c8f8960b281 Mon Sep 17 00:00:00 2001 From: Anshul Dalal Date: Thu, 14 Aug 2025 20:51:43 +0530 Subject: remoteproc: k3: update compatible for am654 syscon The existing compatible name for U-Boot's k3 system controller driver i.e "ti,am625-system-controller" has been added to linux[1] device-tree. This compatible in kernel is meant for configuring the Control Module registers (CTRL_MMR0). However in U-Boot, the matching driver was being used to load the system firmware on the secure M-cores by the R5 SPL and therefore must be updated to a different compatible to avoid conflicts. Therefore, this patch renames all references of the compatible to "ti,am654-tisci-rproc-r5". The "-r5" is appended so as to avoid any future conflicts since r5 specific compatibles should only be useful for U-Boot. [1]: 5959618631fe ("dt-bindings: mfd: ti,j721e-system-controller: Add compatible string for AM654") https://lore.kernel.org/r/20250421214620.3770172-2-afd@ti.com Signed-off-by: Anshul Dalal --- drivers/remoteproc/k3_system_controller.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/remoteproc/k3_system_controller.c b/drivers/remoteproc/k3_system_controller.c index 71238a6058a..e59c010de7e 100644 --- a/drivers/remoteproc/k3_system_controller.c +++ b/drivers/remoteproc/k3_system_controller.c @@ -327,7 +327,7 @@ static const struct k3_sysctrler_desc k3_sysctrler_am654_desc = { static const struct udevice_id k3_sysctrler_ids[] = { { - .compatible = "ti,am654-system-controller", + .compatible = "ti,am654-tisci-rproc-r5", .data = (ulong)&k3_sysctrler_am654_desc, }, {} -- cgit v1.2.3