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; diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index 10e9ea557baa9..39e7ad47a209e 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig @@ -791,11 +791,11 @@ 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" - 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 && ARCH_PHYTIUM select SPI_PHYTIUM help This selects a PCI driver for Phytium SPI controller. @@ -831,13 +830,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. diff --git a/drivers/spi/spi-phytium-common.c b/drivers/spi/spi-phytium-common.c index 96a30a01ebe50..9a7e2eb6bad06 100644 --- a/drivers/spi/spi-phytium-common.c +++ b/drivers/spi/spi-phytium-common.c @@ -110,11 +110,15 @@ 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); - ms = wait_for_completion_timeout(&fts->cmd_completion, msecs_to_jiffies(ms)); + 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) { dev_err(&fts->master->dev, "SPI controller timed out\n"); @@ -129,7 +133,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 +145,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 +162,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 +175,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 +188,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); @@ -452,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-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-v2.c b/drivers/spi/spi-phytium-plat-v2.c index fa51765071683..c2686f57da19c 100644 --- a/drivers/spi/spi-phytium-plat-v2.c +++ b/drivers/spi/spi-phytium-plat-v2.c @@ -26,11 +26,9 @@ #include "spi-phytium.h" #define DRIVER_NAME_PHYT "phytium_spi_2.0" -#define DRIVER_VERSION "1.0.8" +#define DRIVER_VERSION "1.0.15" -#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, @@ -201,55 +199,14 @@ 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; - 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-plat.c b/drivers/spi/spi-phytium-plat.c index 1a7f35cdfabb8..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.0" +#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; @@ -46,7 +79,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), @@ -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); } diff --git a/drivers/spi/spi-phytium-v2.c b/drivers/spi/spi-phytium-v2.c index 44da3bbbad757..cce44c393f869 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; } @@ -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; @@ -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, @@ -423,8 +433,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; @@ -433,22 +442,29 @@ 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(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) @@ -472,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; @@ -485,7 +502,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); @@ -531,6 +555,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 +569,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); diff --git a/drivers/spi/spi-phytium.h b/drivers/spi/spi-phytium.h index 7cc05ed53adea..e390031519459 100644 --- a/drivers/spi/spi-phytium.h +++ b/drivers/spi/spi-phytium.h @@ -56,18 +56,30 @@ #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_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_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 +132,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 +184,7 @@ struct phytium_spi { bool global_cs; bool dma_en; + bool half_duplex; unsigned long paddr; int irq; u32 fifo_len; @@ -211,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 */ @@ -338,6 +354,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);