diff options
| -rw-r--r-- | Documentation/devicetree/bindings/spi/cdns,qspi-nor.yaml | 19 | ||||
| -rw-r--r-- | drivers/spi/spi-cadence-quadspi.c | 168 |
2 files changed, 88 insertions, 99 deletions
diff --git a/Documentation/devicetree/bindings/spi/cdns,qspi-nor.yaml b/Documentation/devicetree/bindings/spi/cdns,qspi-nor.yaml index 0d47bd94d67e..891f578b5ac4 100644 --- a/Documentation/devicetree/bindings/spi/cdns,qspi-nor.yaml +++ b/Documentation/devicetree/bindings/spi/cdns,qspi-nor.yaml @@ -61,6 +61,20 @@ allOf: cdns,fifo-depth: enum: [ 128, 256 ] default: 128 + - if: + properties: + compatible: + contains: + const: renesas,rzn1-qspi + then: + properties: + cdns,trigger-address: false + cdns,fifo-depth: false + cdns,fifo-width: false + else: + required: + - cdns,trigger-address + - cdns,fifo-depth properties: compatible: @@ -80,6 +94,9 @@ properties: # controllers are meant to be used with flashes of all kinds, # ie. also NAND flashes, not only NOR flashes. - const: cdns,qspi-nor + - items: + - const: renesas,r9a06g032-qspi + - const: renesas,rzn1-qspi - const: cdns,qspi-nor deprecated: true @@ -163,8 +180,6 @@ required: - reg - interrupts - clocks - - cdns,fifo-width - - cdns,trigger-address - '#address-cells' - '#size-cells' diff --git a/drivers/spi/spi-cadence-quadspi.c b/drivers/spi/spi-cadence-quadspi.c index 2d287950d44c..649ff55333f0 100644 --- a/drivers/spi/spi-cadence-quadspi.c +++ b/drivers/spi/spi-cadence-quadspi.c @@ -57,7 +57,8 @@ static_assert(CQSPI_MAX_CHIPSELECT <= SPI_DEVICE_CS_CNT_MAX); #define CQSPI_OP_WIDTH(part) ((part).nbytes ? ilog2((part).buswidth) : 0) enum { - CLK_QSPI_APB = 0, + CLK_QSPI_REF = 0, + CLK_QSPI_APB, CLK_QSPI_AHB, CLK_QSPI_NUM, }; @@ -78,8 +79,7 @@ struct cqspi_flash_pdata { struct cqspi_st { struct platform_device *pdev; struct spi_controller *host; - struct clk *clk; - struct clk *clks[CLK_QSPI_NUM]; + struct clk_bulk_data clks[CLK_QSPI_NUM]; unsigned int sclk; void __iomem *iobase; @@ -110,6 +110,7 @@ struct cqspi_st { bool apb_ahb_hazard; bool is_jh7110; /* Flag for StarFive JH7110 SoC */ + bool is_rzn1; /* Flag for Renesas RZ/N1 SoC */ bool disable_stig_mode; refcount_t refcount; refcount_t inflight_ops; @@ -123,8 +124,6 @@ struct cqspi_driver_platdata { int (*indirect_read_dma)(struct cqspi_flash_pdata *f_pdata, u_char *rxbuf, loff_t from_addr, size_t n_rx); u32 (*get_dma_status)(struct cqspi_st *cqspi); - int (*jh7110_clk_init)(struct platform_device *pdev, - struct cqspi_st *cqspi); }; /* Operation timeout value */ @@ -1339,8 +1338,9 @@ static ssize_t cqspi_write(struct cqspi_flash_pdata *f_pdata, * mode. So, we can not use direct mode when in DTR mode for writing * data. */ - if (!op->cmd.dtr && cqspi->use_direct_mode && - cqspi->use_direct_mode_wr && ((to + len) <= cqspi->ahb_size)) { + if ((!op->cmd.dtr && cqspi->use_direct_mode && + cqspi->use_direct_mode_wr && ((to + len) <= cqspi->ahb_size)) || + (cqspi->ddata && cqspi->ddata->quirks & CQSPI_NO_INDIRECT_MODE)) { memcpy_toio(cqspi->ahb_base + to, buf, len); return cqspi_wait_idle(cqspi); } @@ -1514,6 +1514,7 @@ static int cqspi_exec_mem_op(struct spi_mem *mem, const struct spi_mem_op *op) static bool cqspi_supports_mem_op(struct spi_mem *mem, const struct spi_mem_op *op) { + struct cqspi_st *cqspi = spi_controller_get_devdata(mem->spi->controller); bool all_true, all_false; /* @@ -1540,6 +1541,9 @@ static bool cqspi_supports_mem_op(struct spi_mem *mem, /* A single opcode is supported, it will be repeated */ if ((op->cmd.opcode >> 8) != (op->cmd.opcode & 0xFF)) return false; + + if (cqspi->is_rzn1) + return false; } else if (!all_false) { /* Mixed DTR modes are not supported. */ return false; @@ -1593,18 +1597,20 @@ static int cqspi_of_get_pdata(struct cqspi_st *cqspi) cqspi->is_decoded_cs = of_property_read_bool(np, "cdns,is-decoded-cs"); - if (of_property_read_u32(np, "cdns,fifo-depth", &cqspi->fifo_depth)) { - /* Zero signals FIFO depth should be runtime detected. */ - cqspi->fifo_depth = 0; - } + if (!(cqspi->ddata && cqspi->ddata->quirks & CQSPI_NO_INDIRECT_MODE)) { + if (of_property_read_u32(np, "cdns,fifo-depth", &cqspi->fifo_depth)) { + /* Zero signals FIFO depth should be runtime detected. */ + cqspi->fifo_depth = 0; + } - if (of_property_read_u32(np, "cdns,fifo-width", &cqspi->fifo_width)) - cqspi->fifo_width = 4; + if (of_property_read_u32(np, "cdns,fifo-width", &cqspi->fifo_width)) + cqspi->fifo_width = 4; - if (of_property_read_u32(np, "cdns,trigger-address", - &cqspi->trigger_address)) { - dev_err(dev, "couldn't determine trigger-address\n"); - return -ENXIO; + if (of_property_read_u32(np, "cdns,trigger-address", + &cqspi->trigger_address)) { + dev_err(dev, "couldn't determine trigger-address\n"); + return -ENXIO; + } } if (of_property_read_u32(np, "num-cs", &cqspi->num_chipselect)) @@ -1668,6 +1674,9 @@ static void cqspi_controller_detect_fifo_depth(struct cqspi_st *cqspi) struct device *dev = &cqspi->pdev->dev; u32 reg, fifo_depth; + if (cqspi->ddata && cqspi->ddata->quirks & CQSPI_NO_INDIRECT_MODE) + return; + /* * Bits N-1:0 are writable while bits 31:N are read as zero, with 2^N * the FIFO depth. @@ -1771,51 +1780,6 @@ static int cqspi_setup_flash(struct cqspi_st *cqspi) return 0; } -static int cqspi_jh7110_clk_init(struct platform_device *pdev, struct cqspi_st *cqspi) -{ - static struct clk_bulk_data qspiclk[] = { - { .id = "apb" }, - { .id = "ahb" }, - }; - - int ret = 0; - - ret = devm_clk_bulk_get(&pdev->dev, ARRAY_SIZE(qspiclk), qspiclk); - if (ret) { - dev_err(&pdev->dev, "%s: failed to get qspi clocks\n", __func__); - return ret; - } - - cqspi->clks[CLK_QSPI_APB] = qspiclk[0].clk; - cqspi->clks[CLK_QSPI_AHB] = qspiclk[1].clk; - - ret = clk_prepare_enable(cqspi->clks[CLK_QSPI_APB]); - if (ret) { - dev_err(&pdev->dev, "%s: failed to enable CLK_QSPI_APB\n", __func__); - return ret; - } - - ret = clk_prepare_enable(cqspi->clks[CLK_QSPI_AHB]); - if (ret) { - dev_err(&pdev->dev, "%s: failed to enable CLK_QSPI_AHB\n", __func__); - goto disable_apb_clk; - } - - cqspi->is_jh7110 = true; - - return 0; - -disable_apb_clk: - clk_disable_unprepare(cqspi->clks[CLK_QSPI_APB]); - - return ret; -} - -static void cqspi_jh7110_disable_clk(struct platform_device *pdev, struct cqspi_st *cqspi) -{ - clk_disable_unprepare(cqspi->clks[CLK_QSPI_AHB]); - clk_disable_unprepare(cqspi->clks[CLK_QSPI_APB]); -} static int cqspi_probe(struct platform_device *pdev) { const struct cqspi_driver_platdata *ddata; @@ -1824,8 +1788,7 @@ static int cqspi_probe(struct platform_device *pdev) struct spi_controller *host; struct resource *res_ahb; struct cqspi_st *cqspi; - int ret; - int irq; + int ret, irq; host = devm_spi_alloc_host(&pdev->dev, sizeof(*cqspi)); if (!host) @@ -1836,10 +1799,13 @@ static int cqspi_probe(struct platform_device *pdev) host->mem_caps = &cqspi_mem_caps; cqspi = spi_controller_get_devdata(host); + if (of_device_is_compatible(pdev->dev.of_node, "starfive,jh7110-qspi")) + cqspi->is_jh7110 = true; + if (of_device_is_compatible(pdev->dev.of_node, "renesas,rzn1-qspi")) + cqspi->is_rzn1 = true; cqspi->pdev = pdev; cqspi->host = host; - cqspi->is_jh7110 = false; cqspi->ddata = ddata = of_device_get_match_data(dev); platform_set_drvdata(pdev, cqspi); @@ -1856,12 +1822,14 @@ static int cqspi_probe(struct platform_device *pdev) return ret; } - /* Obtain QSPI clock. */ - cqspi->clk = devm_clk_get(dev, NULL); - if (IS_ERR(cqspi->clk)) { - dev_err(dev, "Cannot claim QSPI clock.\n"); - ret = PTR_ERR(cqspi->clk); - return ret; + /* Obtain QSPI clocks. */ + ret = devm_clk_bulk_get_optional(dev, CLK_QSPI_NUM, cqspi->clks); + if (ret) + return dev_err_probe(dev, ret, "Failed to get clocks\n"); + + if (!cqspi->clks[CLK_QSPI_REF].clk) { + dev_err(dev, "Cannot claim mandatory QSPI ref clock.\n"); + return -ENODEV; } /* Obtain and remap controller address. */ @@ -1893,10 +1861,9 @@ static int cqspi_probe(struct platform_device *pdev) if (ret) return ret; - - ret = clk_prepare_enable(cqspi->clk); + ret = clk_bulk_prepare_enable(CLK_QSPI_NUM, cqspi->clks); if (ret) { - dev_err(dev, "Cannot enable QSPI clock.\n"); + dev_err(dev, "Cannot enable QSPI clocks.\n"); goto disable_rpm; } @@ -1905,22 +1872,22 @@ static int cqspi_probe(struct platform_device *pdev) if (IS_ERR(rstc)) { ret = PTR_ERR(rstc); dev_err(dev, "Cannot get QSPI reset.\n"); - goto disable_clk; + goto disable_clks; } rstc_ocp = devm_reset_control_get_optional_exclusive(dev, "qspi-ocp"); if (IS_ERR(rstc_ocp)) { ret = PTR_ERR(rstc_ocp); dev_err(dev, "Cannot get QSPI OCP reset.\n"); - goto disable_clk; + goto disable_clks; } - if (of_device_is_compatible(pdev->dev.of_node, "starfive,jh7110-qspi")) { + if (cqspi->is_jh7110) { rstc_ref = devm_reset_control_get_optional_exclusive(dev, "rstc_ref"); if (IS_ERR(rstc_ref)) { ret = PTR_ERR(rstc_ref); dev_err(dev, "Cannot get QSPI REF reset.\n"); - goto disable_clk; + goto disable_clks; } reset_control_assert(rstc_ref); reset_control_deassert(rstc_ref); @@ -1932,8 +1899,13 @@ static int cqspi_probe(struct platform_device *pdev) reset_control_assert(rstc_ocp); reset_control_deassert(rstc_ocp); - cqspi->master_ref_clk_hz = clk_get_rate(cqspi->clk); - host->max_speed_hz = cqspi->master_ref_clk_hz; + cqspi->master_ref_clk_hz = clk_get_rate(cqspi->clks[CLK_QSPI_REF].clk); + if (!cqspi->is_rzn1) { + host->max_speed_hz = cqspi->master_ref_clk_hz; + } else { + host->max_speed_hz = cqspi->master_ref_clk_hz / 2; + host->min_speed_hz = cqspi->master_ref_clk_hz / 32; + } /* write completion is supported by default */ cqspi->wr_completion = true; @@ -1958,12 +1930,6 @@ static int cqspi_probe(struct platform_device *pdev) cqspi->slow_sram = true; if (ddata->quirks & CQSPI_NEEDS_APB_AHB_HAZARD_WAR) cqspi->apb_ahb_hazard = true; - - if (ddata->jh7110_clk_init) { - ret = cqspi_jh7110_clk_init(pdev, cqspi); - if (ret) - goto disable_clk; - } if (ddata->quirks & CQSPI_DISABLE_STIG_MODE) cqspi->disable_stig_mode = true; @@ -2004,7 +1970,7 @@ static int cqspi_probe(struct platform_device *pdev) if (ddata && (ddata->quirks & CQSPI_SUPPORT_DEVICE_RESET)) cqspi_device_reset(cqspi); - if (cqspi->use_direct_mode) { + if (cqspi->use_direct_mode && !cqspi->is_rzn1) { ret = cqspi_request_mmap_dma(cqspi); if (ret == -EPROBE_DEFER) { dev_err_probe(&pdev->dev, ret, "Failed to request mmap DMA\n"); @@ -2029,11 +1995,8 @@ release_dma_chan: disable_controller: cqspi_controller_enable(cqspi, 0); disable_clks: - if (cqspi->is_jh7110) - cqspi_jh7110_disable_clk(pdev, cqspi); -disable_clk: if (pm_runtime_get_sync(&pdev->dev) >= 0) - clk_disable_unprepare(cqspi->clk); + clk_bulk_disable_unprepare(CLK_QSPI_NUM, cqspi->clks); disable_rpm: if (!(ddata && (ddata->quirks & CQSPI_DISABLE_RUNTIME_PM))) pm_runtime_disable(dev); @@ -2062,14 +2025,12 @@ static void cqspi_remove(struct platform_device *pdev) cqspi_controller_enable(cqspi, 0); - if (cqspi->is_jh7110) - cqspi_jh7110_disable_clk(pdev, cqspi); if (!(ddata && (ddata->quirks & CQSPI_DISABLE_RUNTIME_PM))) ret = pm_runtime_get_sync(&pdev->dev); if (ret >= 0) - clk_disable(cqspi->clk); + clk_bulk_disable_unprepare(CLK_QSPI_NUM, cqspi->clks); if (!(ddata && (ddata->quirks & CQSPI_DISABLE_RUNTIME_PM))) { pm_runtime_put_sync(&pdev->dev); @@ -2082,15 +2043,19 @@ static int cqspi_runtime_suspend(struct device *dev) struct cqspi_st *cqspi = dev_get_drvdata(dev); cqspi_controller_enable(cqspi, 0); - clk_disable_unprepare(cqspi->clk); + clk_bulk_disable_unprepare(CLK_QSPI_NUM, cqspi->clks); return 0; } static int cqspi_runtime_resume(struct device *dev) { struct cqspi_st *cqspi = dev_get_drvdata(dev); + int ret; + + ret = clk_bulk_prepare_enable(CLK_QSPI_NUM, cqspi->clks); + if (ret) + return ret; - clk_prepare_enable(cqspi->clk); cqspi_wait_idle(cqspi); cqspi_controller_enable(cqspi, 0); cqspi_controller_init(cqspi); @@ -2173,7 +2138,6 @@ static const struct cqspi_driver_platdata versal2_ospi = { static const struct cqspi_driver_platdata jh7110_qspi = { .quirks = CQSPI_DISABLE_DAC_MODE, - .jh7110_clk_init = cqspi_jh7110_clk_init, }; static const struct cqspi_driver_platdata pensando_cdns_qspi = { @@ -2186,6 +2150,12 @@ static const struct cqspi_driver_platdata mobileye_eyeq5_ospi = { CQSPI_RD_NO_IRQ, }; +static const struct cqspi_driver_platdata renesas_rzn1_qspi = { + .hwcaps_mask = CQSPI_SUPPORTS_QUAD, + .quirks = CQSPI_NO_SUPPORT_WR_COMPLETION | CQSPI_RD_NO_IRQ | + CQSPI_HAS_WR_PROTECT | CQSPI_NO_INDIRECT_MODE, +}; + static const struct of_device_id cqspi_dt_ids[] = { { .compatible = "cdns,qspi-nor", @@ -2227,6 +2197,10 @@ static const struct of_device_id cqspi_dt_ids[] = { .compatible = "amd,versal2-ospi", .data = &versal2_ospi, }, + { + .compatible = "renesas,rzn1-qspi", + .data = &renesas_rzn1_qspi, + }, { /* end of table */ } }; |
