From 080fa7f60f2ac357a8d18318fae402832eef49df Mon Sep 17 00:00:00 2001 From: Xia Qian Date: Mon, 11 May 2026 10:59:49 +0800 Subject: [PATCH 01/12] spi-v2: phytium: Restricted adaptation platform for SPI driver This driver is exclusively for the PHYTIUM platform and is not compatible with other SoCs. This restriction prevents errors on unsupported platform. Mainline: Open-Source Signed-off-by:Xia Qian Signed-off-by: Peng Min Signed-off-by: Wang Yinfeng --- drivers/spi/Kconfig | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index 10e9ea557baa9..edab99cced3f0 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig @@ -831,13 +831,14 @@ config SPI_PHYTIUM_QSPI config SPI_PHYTIUM_V2 tristate "spi phytium v2" - depends on ARCH_PHYTIUM || COMPILE_TEST + depends on ARCH_PHYTIUM help This config is similar to the "SPI_PHYTIUM" config. config SPI_PHYTIUM_PLAT_V2 tristate "Phytium SPI-v2 controller platform support" select SPI_PHYTIUM_V2 + depends on ARCH_PHYTIUM help This config is similar to the "SPI_PHYTIUM_PLAT" config. From 0386a6b03398938858b514e51f09e404c7a0ce62 Mon Sep 17 00:00:00 2001 From: Xia Qian Date: Mon, 11 May 2026 11:06:27 +0800 Subject: [PATCH 02/12] spi: phytium: Use global cs register to select chip by default The driver uses global-cs register(0x100) for chip selection by default. Slove the problem of not being able to read the device ID when using the internal chip selection register(0x10). Mainline: Open-Source Signed-off-by:Xia Qian Signed-off-by: Peng Min Signed-off-by: Wang Yinfeng --- drivers/spi/Kconfig | 2 +- drivers/spi/spi-phytium-plat.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index edab99cced3f0..b4e238323ec87 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig @@ -791,7 +791,7 @@ config SPI_PCI1XXXX config SPI_PHYTIUM tristate - depends on ARCH_PHYTIUM || COMPILE_TEST + depends on ARCH_PHYTIUM config SPI_PHYTIUM_PLAT tristate "Phytium SPI controller platform support" diff --git a/drivers/spi/spi-phytium-plat.c b/drivers/spi/spi-phytium-plat.c index 1a7f35cdfabb8..af6300dea67a7 100644 --- a/drivers/spi/spi-phytium-plat.c +++ b/drivers/spi/spi-phytium-plat.c @@ -29,7 +29,7 @@ #include "spi-phytium.h" #define DRIVER_NAME "phytium_spi" -#define DRIVER_VERSION "1.0.0" +#define DRIVER_VERSION "1.0.1" #define SPI_PHYTIUM_DEFAULT_CLK_RATE 50000000 @@ -46,7 +46,7 @@ static int phytium_spi_probe(struct platform_device *pdev) struct resource *mem; int ret; int num_cs; - int global_cs = 0; + int global_cs = 1; u32 clk_rate = SPI_PHYTIUM_DEFAULT_CLK_RATE; ftsc = devm_kzalloc(&pdev->dev, sizeof(struct phytium_spi_clk), From 3d960d551155232748b1a3babf43739f1df212d2 Mon Sep 17 00:00:00 2001 From: Xia Qian Date: Mon, 11 May 2026 11:11:41 +0800 Subject: [PATCH 03/12] spi-v2: phytium: Resolve the Resolve the "hung_task" issue during system restart Change the wait_for_completion_timeout function to the wait_for_completion_interruptable_timeout function. To Slove the issue of the "hung_task" during system restart, which will lead to system crash occasionally. Mainline: Open-Source Signed-off-by:Xia Qian Signed-off-by: Peng Min Signed-off-by: Wang Yinfeng --- drivers/spi/spi-phytium-common.c | 2 +- drivers/spi/spi-phytium-plat-v2.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/spi/spi-phytium-common.c b/drivers/spi/spi-phytium-common.c index 96a30a01ebe50..0ba3c3ea92434 100644 --- a/drivers/spi/spi-phytium-common.c +++ b/drivers/spi/spi-phytium-common.c @@ -114,7 +114,7 @@ int spi_phytium_check_result(struct phytium_spi *fts) struct msg *msg = (struct msg *)fts->tx_shmem_addr; reinit_completion(&fts->cmd_completion); - ms = wait_for_completion_timeout(&fts->cmd_completion, msecs_to_jiffies(ms)); + ms = wait_for_completion_interruptible_timeout(&fts->cmd_completion, msecs_to_jiffies(ms)); if (ms == 0) { dev_err(&fts->master->dev, "SPI controller timed out\n"); diff --git a/drivers/spi/spi-phytium-plat-v2.c b/drivers/spi/spi-phytium-plat-v2.c index fa51765071683..9cbee5e608665 100644 --- a/drivers/spi/spi-phytium-plat-v2.c +++ b/drivers/spi/spi-phytium-plat-v2.c @@ -26,7 +26,7 @@ #include "spi-phytium.h" #define DRIVER_NAME_PHYT "phytium_spi_2.0" -#define DRIVER_VERSION "1.0.8" +#define DRIVER_VERSION "1.0.9" #define PHYTIUM_CPU_PART_FTC872 0x872 From 8aaa6b6d819078f76a4540af0b5c16deb331a96f Mon Sep 17 00:00:00 2001 From: Xia Qian Date: Mon, 11 May 2026 11:24:18 +0800 Subject: [PATCH 04/12] spi-v2: phytium: Optimize the timer processing When the SPI device wakes up from sleep mode, it may hang up or timeout at extremely low probability. So We delete the timer during hibernation and restore it upon waking up. Mainline: Open-Source Signed-off-by: Xia Qian Signed-off-by: Peng Min Signed-off-by: Wang Yinfeng --- drivers/spi/spi-phytium-plat-v2.c | 2 +- drivers/spi/spi-phytium-v2.c | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/spi/spi-phytium-plat-v2.c b/drivers/spi/spi-phytium-plat-v2.c index 9cbee5e608665..c9995969014c8 100644 --- a/drivers/spi/spi-phytium-plat-v2.c +++ b/drivers/spi/spi-phytium-plat-v2.c @@ -26,7 +26,7 @@ #include "spi-phytium.h" #define DRIVER_NAME_PHYT "phytium_spi_2.0" -#define DRIVER_VERSION "1.0.9" +#define DRIVER_VERSION "1.0.10" #define PHYTIUM_CPU_PART_FTC872 0x872 diff --git a/drivers/spi/spi-phytium-v2.c b/drivers/spi/spi-phytium-v2.c index 44da3bbbad757..82a8852a0912f 100644 --- a/drivers/spi/spi-phytium-v2.c +++ b/drivers/spi/spi-phytium-v2.c @@ -531,6 +531,7 @@ int spi_phyt_suspend_host(struct phytium_spi *fts) { int ret; + del_timer(&fts->timer); ret = spi_controller_suspend(fts->master); if (ret) return ret; @@ -544,6 +545,7 @@ int spi_phyt_resume_host(struct phytium_spi *fts) { int ret; + mod_timer(&fts->timer, jiffies + msecs_to_jiffies(10)); spi_phyt_hw_init(&fts->master->dev, fts); spi_phyt_enable_chip(fts, 0); From 86ae41e34df3922c54e4d5c8b2cf7dc436702614 Mon Sep 17 00:00:00 2001 From: Xia Qian Date: Mon, 11 May 2026 11:35:07 +0800 Subject: [PATCH 05/12] spi-v2: phytium: Optimize the clearing method of debug-log buffer Replace the original loop assignment with the more standard and efficient memset function to achieve the clearing operation of the debug-log buffer. Mainline: Open-Source Signed-off-by: Xia Qian Signed-off-by: Peng Min Signed-off-by: Wang Yinfeng --- drivers/spi/spi-phytium-plat-v2.c | 2 +- drivers/spi/spi-phytium-v2.c | 8 +++----- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/drivers/spi/spi-phytium-plat-v2.c b/drivers/spi/spi-phytium-plat-v2.c index c9995969014c8..14c9675e97917 100644 --- a/drivers/spi/spi-phytium-plat-v2.c +++ b/drivers/spi/spi-phytium-plat-v2.c @@ -26,7 +26,7 @@ #include "spi-phytium.h" #define DRIVER_NAME_PHYT "phytium_spi_2.0" -#define DRIVER_VERSION "1.0.10" +#define DRIVER_VERSION "1.0.11" #define PHYTIUM_CPU_PART_FTC872 0x872 diff --git a/drivers/spi/spi-phytium-v2.c b/drivers/spi/spi-phytium-v2.c index 82a8852a0912f..777aab555812b 100644 --- a/drivers/spi/spi-phytium-v2.c +++ b/drivers/spi/spi-phytium-v2.c @@ -423,8 +423,7 @@ void spi_handle_debug_err(struct phytium_spi *fts) dev_info(dev, "(log)%.*s\n", SPI_LOG_LINE_MAX_LEN, &fts->log[0]); } - for (i = 0; i < fts->log_size; i++) - fts->log[i] = 0; + memset(fts->log, 0, fts->log_size); } reg &= ~SPI_REGFILE_HAVE_LOG; @@ -440,15 +439,14 @@ static void spi_phyt_hw_init(struct device *dev, struct phytium_spi *fts) reg = phytium_read_regfile(fts, SPI_REGFILE_DEBUG); fts->ddr_paddr = ((reg & SPI_REGFILE_ADDR_MASK) >> 8) << SPI_DDR_ADDR_HIGH; fts->log_size = ((reg & SPI_REGFILE_SIZE_MASK) >> 4) * SPI_DEBUG_LOG_SIZE; - fts->log = devm_ioremap(dev, fts->ddr_paddr, fts->log_size); + fts->log = devm_ioremap_wc(dev, fts->ddr_paddr, fts->log_size); if (IS_ERR(fts->log)) { dev_err(dev, "log_addr is err\n"); return; } - for (i = 0; i < fts->log_size; i++) - fts->log[i] = 0; + memset(fts->log, 0, fts->log_size); } int spi_phyt_add_host(struct device *dev, struct phytium_spi *fts) From a4e187b5d50a089112d2054763a5ff97458e9670 Mon Sep 17 00:00:00 2001 From: Xia Qian Date: Mon, 11 May 2026 11:37:42 +0800 Subject: [PATCH 06/12] spi-v2: phytium: Adjust the position of enable interrupts If the SPI interrupt is enabled before the waiting period is over, it will cause the SPI controller to timeout at low probability. Mainline: Open-Source Signed-off-by: Xia Qian Signed-off-by: Peng Min Signed-off-by: Wang Yinfeng --- drivers/spi/spi-phytium-common.c | 6 +----- drivers/spi/spi-phytium-plat-v2.c | 2 +- drivers/spi/spi-phytium-v2.c | 2 +- 3 files changed, 3 insertions(+), 7 deletions(-) diff --git a/drivers/spi/spi-phytium-common.c b/drivers/spi/spi-phytium-common.c index 0ba3c3ea92434..23861c6193d8a 100644 --- a/drivers/spi/spi-phytium-common.c +++ b/drivers/spi/spi-phytium-common.c @@ -114,6 +114,7 @@ int spi_phytium_check_result(struct phytium_spi *fts) struct msg *msg = (struct msg *)fts->tx_shmem_addr; reinit_completion(&fts->cmd_completion); + phytium_write_regfile(fts, SPI_REGFILE_AP2RV_INTR_STATE, 0x10); ms = wait_for_completion_interruptible_timeout(&fts->cmd_completion, msecs_to_jiffies(ms)); if (ms == 0) { @@ -129,7 +130,6 @@ int spi_phytium_set(struct phytium_spi *fts) int ret; spi_phytium_show_msg(fts->msg); - phytium_write_regfile(fts, SPI_REGFILE_AP2RV_INTR_STATE, 0x10); ret = spi_phytium_check_result(fts); return ret; @@ -142,7 +142,6 @@ void spi_phytium_default(struct phytium_spi *fts) fts->msg->cmd_id = PHYTSPI_MSG_CMD_DEFAULT; spi_phytium_show_msg(fts->msg); - phytium_write_regfile(fts, SPI_REGFILE_AP2RV_INTR_STATE, 0x10); spi_phytium_check_result(fts); } EXPORT_SYMBOL_GPL(spi_phytium_default); @@ -160,7 +159,6 @@ void spi_phytium_set_cmd8(struct phytium_spi *fts, u16 sub_cmd, spi_phytium_set_subid(fts, sub_cmd); fts->msg->data[0] = data; spi_phytium_show_msg(fts->msg); - phytium_write_regfile(fts, SPI_REGFILE_AP2RV_INTR_STATE, 0x10); spi_phytium_check_result(fts); } EXPORT_SYMBOL_GPL(spi_phytium_set_cmd8); @@ -174,7 +172,6 @@ void spi_phytium_set_cmd16(struct phytium_spi *fts, u16 sub_cmd, spi_phytium_set_subid(fts, sub_cmd); *cp_data = data; spi_phytium_show_msg(fts->msg); - phytium_write_regfile(fts, SPI_REGFILE_AP2RV_INTR_STATE, 0x10); spi_phytium_check_result(fts); } EXPORT_SYMBOL_GPL(spi_phytium_set_cmd16); @@ -188,7 +185,6 @@ void spi_phytium_set_cmd32(struct phytium_spi *fts, u16 sub_cmd, spi_phytium_set_subid(fts, sub_cmd); *cp_data = data; spi_phytium_show_msg(fts->msg); - phytium_write_regfile(fts, SPI_REGFILE_AP2RV_INTR_STATE, 0x10); spi_phytium_check_result(fts); } EXPORT_SYMBOL_GPL(spi_phytium_set_cmd32); diff --git a/drivers/spi/spi-phytium-plat-v2.c b/drivers/spi/spi-phytium-plat-v2.c index 14c9675e97917..83363b412f635 100644 --- a/drivers/spi/spi-phytium-plat-v2.c +++ b/drivers/spi/spi-phytium-plat-v2.c @@ -26,7 +26,7 @@ #include "spi-phytium.h" #define DRIVER_NAME_PHYT "phytium_spi_2.0" -#define DRIVER_VERSION "1.0.11" +#define DRIVER_VERSION "1.0.12" #define PHYTIUM_CPU_PART_FTC872 0x872 diff --git a/drivers/spi/spi-phytium-v2.c b/drivers/spi/spi-phytium-v2.c index 777aab555812b..25e10f0b87ddb 100644 --- a/drivers/spi/spi-phytium-v2.c +++ b/drivers/spi/spi-phytium-v2.c @@ -124,9 +124,9 @@ static irqreturn_t spi_phyt_irq(int irq, void *dev_id) struct spi_master *master = dev_id; struct phytium_spi *fts = spi_master_get_devdata(master); - complete(&fts->cmd_completion); writel_relaxed(0, fts->regfile + SPI_REGFILE_RV2AP_INTR_STATE); writel_relaxed(0x10, fts->regfile + SPI_REGFILE_RV2AP_INT_CLEAN); + complete(&fts->cmd_completion); return IRQ_HANDLED; } From a4d94bd512bbea7c2514f12b0440432d90968ca1 Mon Sep 17 00:00:00 2001 From: Xia Qian Date: Mon, 11 May 2026 11:39:29 +0800 Subject: [PATCH 07/12] spi-v2: phytium: Refine the timeout value for SPI driver The time required for most requests is less than 1 second. Only the erase-chip takes a longer time, which will take several minutes. Therefore, it is not appropriate to use a uniform maxmum duration as the timeout period. Mainline: Open-Source Signed-off-by: Xia Qian Signed-off-by: Peng Min Signed-off-by: Wang Yinfeng --- drivers/spi/Kconfig | 5 ++--- drivers/spi/spi-phytium-common.c | 5 ++++- drivers/spi/spi-phytium-plat-v2.c | 2 +- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index b4e238323ec87..2fd1cde643424 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig @@ -795,7 +795,7 @@ config SPI_PHYTIUM config SPI_PHYTIUM_PLAT tristate "Phytium SPI controller platform support" - depends on ARCH_PHYTIUM || COMPILE_TEST + depends on ARCH_PHYTIUM select SPI_PHYTIUM help This selects a platform driver for Phytium SPI controller. @@ -805,8 +805,7 @@ config SPI_PHYTIUM_PLAT config SPI_PHYTIUM_PCI tristate "Phytium SPI controller PCI support" - depends on ARCH_PHYTIUM || COMPILE_TEST - depends on PCI + depends on PCI && SPI_PHYTIUM select SPI_PHYTIUM help This selects a PCI driver for Phytium SPI controller. diff --git a/drivers/spi/spi-phytium-common.c b/drivers/spi/spi-phytium-common.c index 23861c6193d8a..6b666bdaeafab 100644 --- a/drivers/spi/spi-phytium-common.c +++ b/drivers/spi/spi-phytium-common.c @@ -110,9 +110,12 @@ int spi_phytium_print_status(struct phytium_spi *fts, u8 status0, int spi_phytium_check_result(struct phytium_spi *fts) { - unsigned long long ms = 300000; + unsigned long long ms = 20000; struct msg *msg = (struct msg *)fts->tx_shmem_addr; + if (fts->flash_erase == 2) + ms = 200000; + reinit_completion(&fts->cmd_completion); phytium_write_regfile(fts, SPI_REGFILE_AP2RV_INTR_STATE, 0x10); ms = wait_for_completion_interruptible_timeout(&fts->cmd_completion, msecs_to_jiffies(ms)); diff --git a/drivers/spi/spi-phytium-plat-v2.c b/drivers/spi/spi-phytium-plat-v2.c index 83363b412f635..bbcd02ee82160 100644 --- a/drivers/spi/spi-phytium-plat-v2.c +++ b/drivers/spi/spi-phytium-plat-v2.c @@ -26,7 +26,7 @@ #include "spi-phytium.h" #define DRIVER_NAME_PHYT "phytium_spi_2.0" -#define DRIVER_VERSION "1.0.12" +#define DRIVER_VERSION "1.0.13" #define PHYTIUM_CPU_PART_FTC872 0x872 From e4e99108a9edbcae0a838ed8e863361393bbd97e Mon Sep 17 00:00:00 2001 From: Xia Qian Date: Mon, 11 May 2026 14:24:33 +0800 Subject: [PATCH 08/12] spi: phytium: Add ACPI FixedDMA support for DMA channels Enable DMA when the SPI controller is described by ACPI using FixedDMA. The driver now detects the ACPI firmware path, acquires RX/TX channels by index, and arms the DMA path accordingly, while preserving the existing Device Tree behavior. This prevents unintended fallback to PIO on ACPI platforms. Mainline: Open-Source Signed-off-by: Xia Qian Signed-off-by: zhuling Signed-off-by: Wang Yinfeng --- drivers/spi/spi-phytium-dma.c | 13 +++++++++-- drivers/spi/spi-phytium-plat.c | 41 +++++++++++++++++++++++++++++++--- 2 files changed, 49 insertions(+), 5 deletions(-) diff --git a/drivers/spi/spi-phytium-dma.c b/drivers/spi/spi-phytium-dma.c index 4387dadcd8505..ca2f7018b97e2 100644 --- a/drivers/spi/spi-phytium-dma.c +++ b/drivers/spi/spi-phytium-dma.c @@ -14,6 +14,8 @@ #include #include #include "spi-phytium.h" +#include +#include #define RX_BUSY 0 #define RX_BURST_LEVEL 16 @@ -64,11 +66,18 @@ static void phytium_spi_dma_maxburst_init(struct phytium_spi *fts) static int phytium_spi_dma_init(struct device *dev, struct phytium_spi *fts) { - fts->rxchan = dma_request_chan(dev, "rx"); + /* Support ACPI (FixedDMA) and DT (dmas/dma-names) */ + if (has_acpi_companion(dev)) + fts->rxchan = acpi_dma_request_slave_chan_by_index(dev, 0); + else + fts->rxchan = dma_request_chan(dev, "rx"); if (IS_ERR_OR_NULL(fts->rxchan)) return -ENODEV; - fts->txchan = dma_request_chan(dev, "tx"); + if (has_acpi_companion(dev)) + fts->txchan = acpi_dma_request_slave_chan_by_index(dev, 1); + else + fts->txchan = dma_request_chan(dev, "tx"); if (IS_ERR_OR_NULL(fts->txchan)) { dev_err(dev, "can't request chan\n"); dma_release_channel(fts->rxchan); diff --git a/drivers/spi/spi-phytium-plat.c b/drivers/spi/spi-phytium-plat.c index af6300dea67a7..5e20dbaffc5c4 100644 --- a/drivers/spi/spi-phytium-plat.c +++ b/drivers/spi/spi-phytium-plat.c @@ -29,7 +29,7 @@ #include "spi-phytium.h" #define DRIVER_NAME "phytium_spi" -#define DRIVER_VERSION "1.0.1" +#define DRIVER_VERSION "1.0.2" #define SPI_PHYTIUM_DEFAULT_CLK_RATE 50000000 @@ -38,6 +38,39 @@ struct phytium_spi_clk { struct clk *clk; }; +static bool phytium_acpi_has_FixedDMA(struct device *dev) +{ + struct acpi_device *adev; + struct acpi_resource *res; + struct acpi_buffer buf = { ACPI_ALLOCATE_BUFFER, NULL }; + bool found = false; + acpi_status status; + + if (!dev) + return false; + + adev = ACPI_COMPANION(dev); + if (!adev || !adev->handle) + return false; + + /* Get _CRS resource block (kernel allocates buffer) */ + status = acpi_get_current_resources(adev->handle, &buf); + if (ACPI_FAILURE(status) || !buf.pointer) + return false; + + /* Traverse resource list, exit and return true if FixedDMA is found */ + for (res = buf.pointer; res && res->type != ACPI_RESOURCE_TYPE_END_TAG; + res = ACPI_NEXT_RESOURCE(res)) { + if (res->type == ACPI_RESOURCE_TYPE_FIXED_DMA) { + found = true; + break; + } + } + + kfree(buf.pointer); + return found; +} + static int phytium_spi_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; @@ -102,8 +135,10 @@ static int phytium_spi_probe(struct platform_device *pdev) /* check is use dma transfer */ if ((device_property_read_string_array(&pdev->dev, "dma-names", - NULL, 0) > 0) && - device_property_present(&pdev->dev, "dmas")) { + NULL, 0 > 0) && + device_property_present(&pdev->dev, "dmas")) || + (has_acpi_companion(&pdev->dev) && + phytium_acpi_has_FixedDMA(dev))) { fts->dma_en = true; phytium_spi_dmaops_set(fts); } From aad7fa4735c35d41fed52165834af27978ec43f4 Mon Sep 17 00:00:00 2001 From: Xia Qian Date: Mon, 11 May 2026 14:27:59 +0800 Subject: [PATCH 09/12] spi-v2: phytium: Add support for full-duplex transmission mode In order to accommodate devices such as spidev and tpm that support full-duplex transmission, full-duplex support has been added to the spi-v2 driver. Mainline: NA Signed-off-by: Xia Qian Signed-off-by: Peng Min Signed-off-by: Wang Yinfeng --- drivers/spi/spi-phytium-common.c | 70 +++++++++++++++++++++++++++++++ drivers/spi/spi-phytium-plat-v2.c | 2 +- drivers/spi/spi-phytium-v2.c | 21 +++++++++- drivers/spi/spi-phytium.h | 26 ++++++++---- 4 files changed, 108 insertions(+), 11 deletions(-) diff --git a/drivers/spi/spi-phytium-common.c b/drivers/spi/spi-phytium-common.c index 6b666bdaeafab..9a7e2eb6bad06 100644 --- a/drivers/spi/spi-phytium-common.c +++ b/drivers/spi/spi-phytium-common.c @@ -451,6 +451,76 @@ int spi_phytium_read(struct phytium_spi *fts, u8 cs, u8 dfs, u8 mode, } EXPORT_SYMBOL_GPL(spi_phytium_read); +int spi_phytium_xfer(struct phytium_spi *fts, u8 cs, u8 dfs, u8 mode, + u8 tmode, u8 flags) +{ + int ret; + u32 len; + u64 smem_tx, smem_rx; + u8 first = 1; + u64 tx_addr, rx_addr; + u64 *data = (u64 *)fts->tx; + + do { + if (fts->dma_get_ddrdata) + len = min_t(u32, (u32)(fts->rx_end - fts->rx), + (u32)(fts->rx_end - fts->rx)); + else + len = min_t(u32, (u32)(fts->rx_end - fts->rx), 128); + + fts->msg->cmd_id = PHYTSPI_MSG_CMD_DATA; + + smem_tx = (u64)fts->msg + sizeof(struct msg); + smem_rx = (u64)fts->msg + sizeof(struct msg) + 128; + + if (len > 16 && fts->dma_get_ddrdata) { + fts->msg->cmd_subid = PHYTSPI_MSG_CMD_DATA_DMA_XFER; + tx_addr = __virt_to_phys((u64)fts->tx); + if (!tx_addr) { + dev_err(&fts->master->dev, "tx address translation failed\n"); + return -1; + } + rx_addr = __virt_to_phys((u64)fts->rx); + if (!rx_addr) { + dev_err(&fts->master->dev, "rx address translation failed\n"); + return -1; + } + + *(u64 *)&fts->msg->data[0] = tx_addr; + *(u64 *)&fts->msg->data[8] = rx_addr; + } else { + fts->msg->cmd_subid = PHYTSPI_MSG_CMD_DATA_XFER; + memcpy_byte((void *)smem_tx, fts->tx, len); + *(u64 *)&fts->msg->data[0] = sizeof(struct msg); + *(u64 *)&fts->msg->data[8] = sizeof(struct msg) + 128; + } + + *(u32 *)&fts->msg->data[16] = len; + fts->msg->data[20] = cs; + fts->msg->data[21] = dfs; + fts->msg->data[22] = mode; + fts->msg->data[23] = tmode; + if (first == 1) + fts->msg->data[24] = 1; + else + fts->msg->data[24] = flags; + fts->msg->data[24] = first; + ret = spi_phytium_set(fts); + if (ret) { + dev_err(&fts->master->dev, "AP <-> RV interaction failed\n"); + return ret; + } + if (len <= 16 || !fts->dma_get_ddrdata) + memcpy_byte(fts->rx, (void *)smem_rx, len); + + fts->rx += len; + first = 0; + } while (fts->rx_end > fts->rx); + + return ret; +} +EXPORT_SYMBOL_GPL(spi_phytium_xfer); + MODULE_AUTHOR("Peng Min "); MODULE_DESCRIPTION("Phytium SPI adapter core"); MODULE_LICENSE("GPL"); diff --git a/drivers/spi/spi-phytium-plat-v2.c b/drivers/spi/spi-phytium-plat-v2.c index bbcd02ee82160..81a02a49d734c 100644 --- a/drivers/spi/spi-phytium-plat-v2.c +++ b/drivers/spi/spi-phytium-plat-v2.c @@ -26,7 +26,7 @@ #include "spi-phytium.h" #define DRIVER_NAME_PHYT "phytium_spi_2.0" -#define DRIVER_VERSION "1.0.13" +#define DRIVER_VERSION "1.0.14" #define PHYTIUM_CPU_PART_FTC872 0x872 diff --git a/drivers/spi/spi-phytium-v2.c b/drivers/spi/spi-phytium-v2.c index 25e10f0b87ddb..af0b8f12e77c3 100644 --- a/drivers/spi/spi-phytium-v2.c +++ b/drivers/spi/spi-phytium-v2.c @@ -158,7 +158,17 @@ static int spi_phyt_transfer_one(struct spi_master *master, chip->tmode = TMOD_TO; } - if (mem == nor->spimem && fts->tx && fts->len == 1) { + if (fts->tx && fts->rx) { + if (fts->half_duplex) { + dev_err(&master->dev, "SPI-V2 not support full duplex\n"); + return -EPERM; + } + ret = spi_phytium_xfer(fts, spi->chip_select, transfer->bits_per_word, + spi->mode, chip->tmode, 0); + return ret; + } + + if (mem != NULL && nor != NULL && mem == nor->spimem && fts->tx && fts->len == 1) { if ((*(u8 *)fts->tx == SPINOR_OP_WREN) && fts->spi_write_flag == 0) { spi_phytium_write_pre(fts, spi->chip_select, transfer->bits_per_word, spi->mode, @@ -483,7 +493,14 @@ int spi_phyt_add_host(struct device *dev, struct phytium_spi *fts) master->dev.of_node = dev->of_node; master->dev.fwnode = dev->fwnode; master->flags = SPI_CONTROLLER_GPIO_SS; - master->flags |= SPI_CONTROLLER_HALF_DUPLEX; + + fts->half_duplex = false; + if (!(phytium_read_regfile(fts, SPI_REGFILE_SOFTWARE2) + & SPI_REGFILE_FULL_DUPLEX)) { + dev_warn(dev, "SPI-V2 only support half duplex\n"); + fts->half_duplex = true; + master->flags |= SPI_CONTROLLER_HALF_DUPLEX; + } spi_master_set_devdata(master, fts); diff --git a/drivers/spi/spi-phytium.h b/drivers/spi/spi-phytium.h index 7cc05ed53adea..f8f41c0497068 100644 --- a/drivers/spi/spi-phytium.h +++ b/drivers/spi/spi-phytium.h @@ -56,18 +56,23 @@ #define SPI_DMA_TDMAE (1 << 1) #define SPI_WAIT_RETRIES 5 -#define SPI_REGFILE_SIZE (0x48) #define SPI_REGFILE_AP2RV_INTR_STATE (0x24) #define SPI_REGFILE_RV2AP_INTR_STATE (0x2c) -#define SPI_REGFILE_RV2AP_INT_CLEAN (0x74) +#define SPI_REGFILE_SIZE (0x48) +#define SPI_REGFILE_DDR_HIGH_REG (0x4c) + +#define SPI_REGFILE_SOFTWARE2 (0x54) +#define SPI_REGFILE_FULL_DUPLEX BIT(9) + #define SPI_REGFILE_DEBUG (0x58) +#define SPI_REGFILE_DEBUG_VAL BIT(0) +#define SPI_REGFILE_ALIVE_VAL BIT(1) +#define SPI_REGFILE_HEARTBIT_VAL BIT(2) +#define SPI_REGFILE_HAVE_LOG BIT(3) +#define SPI_REGFILE_SIZE_MASK GENMASK(7, 4) +#define SPI_REGFILE_ADDR_MASK GENMASK(27, 8) -#define SPI_REGFILE_DEBUG_VAL BIT(0) -#define SPI_REGFILE_ALIVE_VAL BIT(1) -#define SPI_REGFILE_HEARTBIT_VAL BIT(2) -#define SPI_REGFILE_HAVE_LOG BIT(3) -#define SPI_REGFILE_SIZE_MASK GENMASK(7, 4) -#define SPI_REGFILE_ADDR_MASK GENMASK(27, 8) +#define SPI_REGFILE_RV2AP_INT_CLEAN (0x74) #define SPI_DDR_ADDR_HIGH 12 #define SPI_DEBUG_LOG_SIZE 4096 @@ -120,6 +125,8 @@ enum phytspi_data_subid { PHYTSPI_MSG_CMD_DATA_DMA_TX, PHYTSPI_MSG_CMD_DATA_DMA_RX, PHYTSPI_MSG_CMD_DATA_FLASH_DMA_TX, + PHYTSPI_MSG_CMD_DATA_XFER, + PHYTSPI_MSG_CMD_DATA_DMA_XFER, }; struct msg { @@ -170,6 +177,7 @@ struct phytium_spi { bool global_cs; bool dma_en; + bool half_duplex; unsigned long paddr; int irq; u32 fifo_len; @@ -338,6 +346,8 @@ extern int spi_phytium_write(struct phytium_spi *fts, u8 cs, u8 dfs, u8 mode, u8 tmode, u8 flags, u8 spi_write_flag); extern int spi_phytium_read(struct phytium_spi *fts, u8 cs, u8 dfs, u8 mode, u8 tmode, u8 flags); +extern int spi_phytium_xfer(struct phytium_spi *fts, u8 cs, u8 dfs, u8 mode, + u8 tmode, u8 flags); extern int spi_phyt_add_host(struct device *dev, struct phytium_spi *fts); extern void spi_phyt_remove_host(struct phytium_spi *fts); extern int spi_phyt_suspend_host(struct phytium_spi *fts); From ebde81f584f5e79f4c8a570134765495df90281a Mon Sep 17 00:00:00 2001 From: Xia Qian Date: Mon, 11 May 2026 14:31:07 +0800 Subject: [PATCH 10/12] spi-v2: phytium: Add support ddr addr 0-45bit Determine whether to enable DMA andwhether it is compatible with 32-bit and 45-bit physical memory addresses by reading the regfile version register added to the spi-v2 driver. Mainline: NA Signed-off-by: Xia Qian Signed-off-by: Peng Yao Signed-off-by: Wang Yinfeng --- drivers/spi/spi-phytium-plat-v2.c | 8 ++++---- drivers/spi/spi-phytium-v2.c | 12 ++++++++++-- drivers/spi/spi-phytium.h | 8 ++++++++ 3 files changed, 22 insertions(+), 6 deletions(-) diff --git a/drivers/spi/spi-phytium-plat-v2.c b/drivers/spi/spi-phytium-plat-v2.c index 81a02a49d734c..58128151b2bdb 100644 --- a/drivers/spi/spi-phytium-plat-v2.c +++ b/drivers/spi/spi-phytium-plat-v2.c @@ -28,9 +28,7 @@ #define DRIVER_NAME_PHYT "phytium_spi_2.0" #define DRIVER_VERSION "1.0.14" -#define PHYTIUM_CPU_PART_FTC872 0x872 -#define MIDR_PHYTIUM_FTC872 MIDR_CPU_MODEL(ARM_CPU_IMP_PHYTIUM, PHYTIUM_CPU_PART_FTC872) static ssize_t debug_show(struct device *dev, struct device_attribute *da, @@ -247,9 +245,11 @@ static int spi_phyt_probe(struct platform_device *pdev) device_property_read_u32(&pdev->dev, "global-cs", &global_cs); fts->global_cs = global_cs; - fts->dma_get_ddrdata = false; - if ((read_cpuid_id() & MIDR_CPU_MODEL_MASK) == MIDR_PHYTIUM_FTC872) + fts->regfile_version = phytium_read_regfile(fts, SPI_REGFILE_VERSION_REG); + if (fts->regfile_version & SPI_REGFILE_VERSION_DMA) fts->dma_get_ddrdata = true; + else + fts->dma_get_ddrdata = false; ret = spi_phyt_add_host(&pdev->dev, fts); if (ret) diff --git a/drivers/spi/spi-phytium-v2.c b/drivers/spi/spi-phytium-v2.c index af0b8f12e77c3..4a37e04ef5e96 100644 --- a/drivers/spi/spi-phytium-v2.c +++ b/drivers/spi/spi-phytium-v2.c @@ -442,12 +442,20 @@ void spi_handle_debug_err(struct phytium_spi *fts) static void spi_phyt_hw_init(struct device *dev, struct phytium_spi *fts) { - u32 reg, i; + u32 reg, i, reg_ddr_high; spi_phytium_default(fts); reg = phytium_read_regfile(fts, SPI_REGFILE_DEBUG); - fts->ddr_paddr = ((reg & SPI_REGFILE_ADDR_MASK) >> 8) << SPI_DDR_ADDR_HIGH; + + if (fts->regfile_version & SPI_REGFILE_VERSION_DDR) { + fts->ddr_paddr = ((reg & SPI_REGFILE_ADDR_MASK) >> 8); + reg_ddr_high = phytium_read_regfile(fts, SPI_REGFILE_DDR_HIGH_REG); + fts->ddr_paddr |= ((u64)reg_ddr_high << 20); + } else { + fts->ddr_paddr = ((reg & SPI_REGFILE_ADDR_MASK) >> 8) << SPI_DDR_ADDR_HIGH; + } + fts->log_size = ((reg & SPI_REGFILE_SIZE_MASK) >> 4) * SPI_DEBUG_LOG_SIZE; fts->log = devm_ioremap_wc(dev, fts->ddr_paddr, fts->log_size); diff --git a/drivers/spi/spi-phytium.h b/drivers/spi/spi-phytium.h index f8f41c0497068..e390031519459 100644 --- a/drivers/spi/spi-phytium.h +++ b/drivers/spi/spi-phytium.h @@ -72,6 +72,13 @@ #define SPI_REGFILE_SIZE_MASK GENMASK(7, 4) #define SPI_REGFILE_ADDR_MASK GENMASK(27, 8) +#define SPI_REGFILE_DDR_HIGH_REG (0x4c) +#define SPI_REGFILE_VERSION_REG (0x700) +#define SPI_REGFILE_VERSION_SUB GENMASK(7, 0) +#define SPI_REGFILE_VERSION GENMASK(15, 8) +#define SPI_REGFILE_VERSION_DMA BIT(16) +#define SPI_REGFILE_VERSION_DDR BIT(17) + #define SPI_REGFILE_RV2AP_INT_CLEAN (0x74) #define SPI_DDR_ADDR_HIGH 12 @@ -219,6 +226,7 @@ struct phytium_spi { u32 log_size; void (*watchdog)(struct phytium_spi *fts); void (*handle_debug_err)(struct phytium_spi *fts); + u32 regfile_version; /* DMA info */ u32 current_freq; /* frequency in hz */ From 956c76e521e44f5874deb166873b399e68f87d66 Mon Sep 17 00:00:00 2001 From: Xia Qian Date: Mon, 11 May 2026 14:33:30 +0800 Subject: [PATCH 11/12] spi: mtd: Fixed compile warning issue The warning message 'child_handle is uninitialied' will occur when compiled, owing to uninitialized value for the child_handle parameter. Mainline: NA Signed-off-by: Xia Qian Signed-off-by: Peng Yao Signed-off-by: Wang Yinfeng --- drivers/mtd/parsers/acpipart_core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mtd/parsers/acpipart_core.c b/drivers/mtd/parsers/acpipart_core.c index 7ae9989604bae..501d6f54b2c79 100644 --- a/drivers/mtd/parsers/acpipart_core.c +++ b/drivers/mtd/parsers/acpipart_core.c @@ -24,7 +24,7 @@ static int parse_acpi_fixed_partitions(struct mtd_info *master, const char *partname; int nr_parts, i, ret = 0; struct acpi_device *adev; - struct fwnode_handle *child_handle; + struct fwnode_handle *child_handle = NULL; bool dedicated = true; struct device *dev; From b0df2db493e43b6b2e237a73374260a84053d200 Mon Sep 17 00:00:00 2001 From: Xia Qian Date: Mon, 11 May 2026 14:39:13 +0800 Subject: [PATCH 12/12] spi-v2: phytium: Fix CAN device hardware disconnect issue This patch addresses two issues with Phytium SPI-V2 CAN device handling: 1. Add hardware connection validation before accessing SPI device driver data. When CAN device is described in DTS but not physically connected, prevent crashes by checking spi_device validity before obtaining spi_mem drv data. 2. Enable GPIO-based chip select simulation in SPI subsystem. Implement GPIO CS control by extracting GPIO chip select description from DTS/ACPI configuration and managing GPIO CS state within the SPI subsystem stack. 3.The cs-gpios control is placed in the SPI subsystem,Due to code redundancy,the phytium controller driver code cs-gpios has been removed. This ensures proper handling of disconnected CAN devices and provides flexible chip select control for SPI-based CAN implementations. Mainline: NA Signed-off-by: Xia Qian Signed-off-by: Peng Yao Signed-off-by: Wang Yinfeng --- drivers/spi/Kconfig | 2 +- drivers/spi/spi-phytium-plat-v2.c | 45 +------------------------------ drivers/spi/spi-phytium-v2.c | 3 ++- 3 files changed, 4 insertions(+), 46 deletions(-) diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index 2fd1cde643424..39e7ad47a209e 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig @@ -805,7 +805,7 @@ config SPI_PHYTIUM_PLAT config SPI_PHYTIUM_PCI tristate "Phytium SPI controller PCI support" - depends on PCI && SPI_PHYTIUM + depends on PCI && ARCH_PHYTIUM select SPI_PHYTIUM help This selects a PCI driver for Phytium SPI controller. diff --git a/drivers/spi/spi-phytium-plat-v2.c b/drivers/spi/spi-phytium-plat-v2.c index 58128151b2bdb..c2686f57da19c 100644 --- a/drivers/spi/spi-phytium-plat-v2.c +++ b/drivers/spi/spi-phytium-plat-v2.c @@ -26,7 +26,7 @@ #include "spi-phytium.h" #define DRIVER_NAME_PHYT "phytium_spi_2.0" -#define DRIVER_VERSION "1.0.14" +#define DRIVER_VERSION "1.0.15" @@ -199,49 +199,6 @@ static int spi_phyt_probe(struct platform_device *pdev) fts->num_cs = num_cs; - if (pdev->dev.of_node) { - int i; - - for (i = 0; i < fts->num_cs; i++) { - cs_gpio = of_get_named_gpio(pdev->dev.of_node, - "cs-gpios", i); - - if (cs_gpio == -EPROBE_DEFER) { - ret = cs_gpio; - goto out; - } - - if (gpio_is_valid(cs_gpio)) { - ret = devm_gpio_request(&pdev->dev, cs_gpio, - dev_name(&pdev->dev)); - if (ret) - goto out; - } - } - } else if (has_acpi_companion(&pdev->dev)) { - int n; - int *cs; - struct gpio_desc *gpiod; - - n = gpiod_count(&pdev->dev, "cs"); - - cs = devm_kcalloc(&pdev->dev, n, sizeof(int), GFP_KERNEL); - fts->cs = cs; - - for (i = 0; i < n; i++) { - gpiod = devm_gpiod_get_index_optional(&pdev->dev, "cs", i, - GPIOD_OUT_LOW); - - if (IS_ERR(gpiod)) { - ret = PTR_ERR(gpiod); - goto out; - } - - cs_gpio = desc_to_gpio(gpiod); - cs[i] = cs_gpio; - } - } - device_property_read_u32(&pdev->dev, "global-cs", &global_cs); fts->global_cs = global_cs; diff --git a/drivers/spi/spi-phytium-v2.c b/drivers/spi/spi-phytium-v2.c index 4a37e04ef5e96..cce44c393f869 100644 --- a/drivers/spi/spi-phytium-v2.c +++ b/drivers/spi/spi-phytium-v2.c @@ -140,7 +140,7 @@ static int spi_phyt_transfer_one(struct spi_master *master, struct spi_nor *nor = NULL; int ret; - if (mem) + if (mem && (mem->spi == spi)) nor = spi_mem_get_drvdata(mem); fts->tx = (void *)transfer->tx_buf; @@ -488,6 +488,7 @@ int spi_phyt_add_host(struct device *dev, struct phytium_spi *fts) goto err_free_master; } + master->use_gpio_descriptors = true; master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_LOOP; master->bits_per_word_mask = SPI_BPW_MASK(8) | SPI_BPW_MASK(16); master->bus_num = fts->bus_num;