diff --git a/arch/riscv/boot/dts/starfive/jh7110.dtsi b/arch/riscv/boot/dts/starfive/jh7110.dtsi index b816b2c9abaa..0dcba863e9fc 100644 --- a/arch/riscv/boot/dts/starfive/jh7110.dtsi +++ b/arch/riscv/boot/dts/starfive/jh7110.dtsi @@ -321,24 +321,43 @@ #size-cells = <0>; reg = <0x0 0x13010000 0x0 0x10000 0x0 0x21000000 0x0 0x400000>; - clocks = <&clkgen JH7110_QSPI_CLK_REF>; - clock-names = "clk_ref"; + interrupts = <25>; + clocks = <&clkgen JH7110_QSPI_CLK_REF>, + <&clkgen JH7110_QSPI_CLK_APB>, + <&clkgen JH7110_AHB1>, + <&clkgen JH7110_QSPI_CLK_AHB>; + clock-names = "clk_ref", + "clk_apb", + "ahb1", + "clk_ahb"; resets = <&rstgen RSTN_U0_CDNS_QSPI_APB>, <&rstgen RSTN_U0_CDNS_QSPI_AHB>, <&rstgen RSTN_U0_CDNS_QSPI_REF>; resets-names = "rst_apb", "rst_ahb", "rst_ref"; cdns,fifo-depth = <256>; cdns,fifo-width = <4>; + cdns,trigger-address = <0x0>; spi-max-frequency = <250000000>; nor_flash: nor-flash@0 { compatible = "jedec,spi-nor"; reg=<0>; + cdns,read-delay = <5>; spi-max-frequency = <100000000>; cdns,tshsl-ns = <1>; cdns,tsd2d-ns = <1>; cdns,tchsh-ns = <1>; cdns,tslch-ns = <1>; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + data@f00000 { + reg = <0xf00000 0x100000>; + }; + }; }; }; diff --git a/arch/riscv/configs/starfive_jh7110_defconfig b/arch/riscv/configs/starfive_jh7110_defconfig index 515647d7da4f..d74cb1d86966 100644 --- a/arch/riscv/configs/starfive_jh7110_defconfig +++ b/arch/riscv/configs/starfive_jh7110_defconfig @@ -88,6 +88,9 @@ CONFIG_PCI=y CONFIG_PCIE_PLDA=y CONFIG_DEVTMPFS=y CONFIG_DEVTMPFS_MOUNT=y +CONFIG_MTD=y +CONFIG_MTD_BLOCK=y +CONFIG_MTD_SPI_NOR=y CONFIG_OF_CONFIGFS=y CONFIG_BLK_DEV_LOOP=y CONFIG_VIRTIO_BLK=y @@ -163,6 +166,7 @@ CONFIG_HW_RANDOM_VIRTIO=y CONFIG_I2C_CHARDEV=y CONFIG_I2C_DESIGNWARE_PLATFORM=y CONFIG_SPI=y +CONFIG_SPI_CADENCE_QUADSPI=y CONFIG_SPI_PL022_STARFIVE=y CONFIG_SPI_SIFIVE=y CONFIG_SPI_SPIDEV=y @@ -286,6 +290,7 @@ CONFIG_NTFS_RW=y CONFIG_TMPFS=y CONFIG_TMPFS_POSIX_ACL=y CONFIG_HUGETLBFS=y +CONFIG_JFFS2_FS=y CONFIG_NFS_FS=y CONFIG_NFS_V4=y CONFIG_NFS_V4_1=y diff --git a/drivers/mtd/spi-nor/gigadevice.c b/drivers/mtd/spi-nor/gigadevice.c index 447d84bb2128..70c816ded7fa 100644 --- a/drivers/mtd/spi-nor/gigadevice.c +++ b/drivers/mtd/spi-nor/gigadevice.c @@ -10,13 +10,10 @@ static void gd25q256_default_init(struct spi_nor *nor) { - /* - * Some manufacturer like GigaDevice may use different - * bit to set QE on different memories, so the MFR can't - * indicate the quad_enable method for this case, we need - * to set it in the default_init fixup hook. - */ - nor->params->quad_enable = spi_nor_sr1_bit6_quad_enable; + /* use Quad page program */ + nor->params->hwcaps.mask |= SNOR_HWCAPS_PP_1_1_4; + spi_nor_set_pp_settings(&nor->params->page_programs[SNOR_CMD_PP_1_1_4], + SPINOR_OP_PP_1_1_4, SNOR_PROTO_1_1_4); } static struct spi_nor_fixups gd25q256_fixups = { @@ -40,7 +37,7 @@ static const struct flash_info gigadevice_parts[] = { SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB) }, { "gd25lq128d", INFO(0xc86018, 0, 64 * 1024, 256, - SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | + SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | SPI_NOR_SKIP_SFDP | SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB) }, { "gd25q128", INFO(0xc84018, 0, 64 * 1024, 256, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | @@ -56,4 +53,5 @@ const struct spi_nor_manufacturer spi_nor_gigadevice = { .name = "gigadevice", .parts = gigadevice_parts, .nparts = ARRAY_SIZE(gigadevice_parts), + .fixups = &gd25q256_fixups, }; diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig old mode 100755 new mode 100644 index ed15861a52d9..58ba1d301aab --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig @@ -219,7 +219,7 @@ config SPI_CADENCE config SPI_CADENCE_QUADSPI tristate "Cadence Quad SPI controller" - depends on OF && (ARM || ARM64 || X86 || COMPILE_TEST) + depends on OF && (ARM || ARM64 || X86 || RISCV || COMPILE_TEST) help Enable support for the Cadence Quad SPI Flash controller. diff --git a/drivers/spi/spi-cadence-quadspi.c b/drivers/spi/spi-cadence-quadspi.c index 101cc71bffa7..4b13085ed03d 100644 --- a/drivers/spi/spi-cadence-quadspi.c +++ b/drivers/spi/spi-cadence-quadspi.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include @@ -39,6 +40,14 @@ /* Capabilities */ #define CQSPI_SUPPORTS_OCTAL BIT(0) +enum { + CLK_QSPI_APB = 0, + CLK_AHB1, + CLK_QSPI_AHB, + CLK_QSPI_REF, + CLK_QSPI_NUM, +}; + struct cqspi_st; struct cqspi_flash_pdata { @@ -60,6 +69,7 @@ struct cqspi_st { struct platform_device *pdev; struct clk *clk; + struct clk *clks[CLK_QSPI_NUM]; unsigned int sclk; void __iomem *iobase; @@ -249,7 +259,14 @@ struct cqspi_driver_platdata { CQSPI_REG_IRQ_WATERMARK | \ CQSPI_REG_IRQ_UNDERFLOW) -#define CQSPI_IRQ_STATUS_MASK 0x1FFFF +#define CQSPI_IRQ_STATUS_MASK 0x1FFFF + +#define CQSPI_DEFAULT_FREQ 2000000 +#define CQSPI_READ_ID_FREQ 1000000 +#define CQSPI_WRITE_DATA_FREQ 12000000 + +#define STARFIVE_RESET_REG_BASE_ADDR 0x13020000 +#define QSPI_RESET_REG_OFFSET 0x2fc static int cqspi_wait_for_bit(void __iomem *reg, const u32 mask, bool clr) { @@ -356,6 +373,7 @@ static int cqspi_set_protocol(struct cqspi_flash_pdata *f_pdata, /* Right now we only support 8-8-8 DTR mode. */ if (f_pdata->dtr) { + switch (op->cmd.buswidth) { case 0: break; @@ -1082,6 +1100,7 @@ static ssize_t cqspi_write(struct cqspi_flash_pdata *f_pdata, struct cqspi_st *cqspi = f_pdata->cqspi; loff_t to = op->addr.val; size_t len = op->data.nbytes; + const u_char *buf = op->data.buf.out; int ret; @@ -1205,7 +1224,13 @@ static int cqspi_mem_process(struct spi_mem *mem, const struct spi_mem_op *op) struct cqspi_flash_pdata *f_pdata; f_pdata = &cqspi->f_pdata[mem->spi->chip_select]; - cqspi_configure(f_pdata, mem->spi->max_speed_hz); + + if (op->cmd.opcode == SPINOR_OP_RDID) + cqspi_configure(f_pdata, CQSPI_READ_ID_FREQ); + else if (op->cmd.opcode == SPINOR_OP_PP_1_1_4) + cqspi_configure(f_pdata, CQSPI_WRITE_DATA_FREQ); + else + cqspi_configure(f_pdata, CQSPI_DEFAULT_FREQ); if (op->data.dir == SPI_MEM_DATA_IN && op->data.buf.in) { if (!op->addr.nbytes) @@ -1225,6 +1250,7 @@ static int cqspi_exec_mem_op(struct spi_mem *mem, const struct spi_mem_op *op) int ret; ret = cqspi_mem_process(mem, op); + if (ret) dev_err(&mem->spi->dev, "operation failed with %d\n", ret); @@ -1364,6 +1390,7 @@ static void cqspi_controller_init(struct cqspi_st *cqspi) static int cqspi_request_mmap_dma(struct cqspi_st *cqspi) { + int ret; dma_cap_mask_t mask; dma_cap_zero(mask); @@ -1371,7 +1398,7 @@ static int cqspi_request_mmap_dma(struct cqspi_st *cqspi) cqspi->rx_chan = dma_request_chan_by_mask(&mask); if (IS_ERR(cqspi->rx_chan)) { - int ret = PTR_ERR(cqspi->rx_chan); + ret = PTR_ERR(cqspi->rx_chan); cqspi->rx_chan = NULL; return dev_err_probe(&cqspi->pdev->dev, ret, "No Rx DMA available\n"); } @@ -1432,15 +1459,74 @@ static int cqspi_setup_flash(struct cqspi_st *cqspi) return 0; } +static int cadence_quadspi_clk_init(struct platform_device *pdev, struct cqspi_st *cqspi) +{ + static struct clk_bulk_data qspiclk[] = { + { .id = "clk_apb" }, + { .id = "ahb1" }, + { .id = "clk_ahb" }, + { .id = "clk_ref" }, + }; + + 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_AHB1] = qspiclk[1].clk; + cqspi->clks[CLK_QSPI_AHB] = qspiclk[2].clk; + cqspi->clks[CLK_QSPI_REF] = qspiclk[3].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_AHB1]); + if (ret) { + dev_err(&pdev->dev, "%s: failed to enable CLK_AHB1\n", __func__); + goto disable_apb_clk; + } + + 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_ahb1; + } + + ret = clk_prepare_enable(cqspi->clks[CLK_QSPI_REF]); + if (ret) { + dev_err(&pdev->dev, "%s: failed to enable CLK_QSPI_REF\n", __func__); + goto disable_ahb_clk; + } + + return 0; + +disable_ahb_clk: + clk_disable_unprepare(cqspi->clks[CLK_QSPI_AHB]); +disable_ahb1: + clk_disable_unprepare(cqspi->clks[CLK_AHB1]); +disable_apb_clk: + clk_disable_unprepare(cqspi->clks[CLK_QSPI_APB]); + + return ret; +} + static int cqspi_probe(struct platform_device *pdev) { const struct cqspi_driver_platdata *ddata; - struct reset_control *rstc, *rstc_ocp; + struct reset_control *rst_apb, *rst_ahb, *rst_ref; struct device *dev = &pdev->dev; struct spi_master *master; struct resource *res_ahb; struct cqspi_st *cqspi; struct resource *res; + void __iomem *reset_res; int ret; int irq; @@ -1449,7 +1535,8 @@ static int cqspi_probe(struct platform_device *pdev) dev_err(&pdev->dev, "spi_alloc_master failed\n"); return -ENOMEM; } - master->mode_bits = SPI_RX_QUAD | SPI_RX_DUAL; + master->mode_bits = SPI_RX_QUAD | SPI_TX_QUAD; + master->buswidth_override_bits = SPI_RX_QUAD | SPI_TX_QUAD; master->mem_ops = &cqspi_mem_ops; master->dev.of_node = pdev->dev.of_node; @@ -1466,14 +1553,6 @@ static int cqspi_probe(struct platform_device *pdev) goto probe_master_put; } - /* 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); - goto probe_master_put; - } - /* Obtain and remap controller address. */ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); cqspi->iobase = devm_ioremap_resource(dev, res); @@ -1491,6 +1570,7 @@ static int cqspi_probe(struct platform_device *pdev) ret = PTR_ERR(cqspi->ahb_base); goto probe_master_put; } + cqspi->mmap_phys_base = (dma_addr_t)res_ahb->start; cqspi->ahb_size = resource_size(res_ahb); @@ -1510,42 +1590,52 @@ static int cqspi_probe(struct platform_device *pdev) goto probe_master_put; } - ret = clk_prepare_enable(cqspi->clk); - if (ret) { - dev_err(dev, "Cannot enable QSPI clock.\n"); + /* Obtain QSPI clock. */ + ret = cadence_quadspi_clk_init(pdev, cqspi); + if (ret) goto probe_clk_failed; - } /* Obtain QSPI reset control */ - rstc = devm_reset_control_get_optional_exclusive(dev, "qspi"); - if (IS_ERR(rstc)) { - ret = PTR_ERR(rstc); - dev_err(dev, "Cannot get QSPI reset.\n"); + rst_apb = devm_reset_control_get_optional_exclusive(dev, "rst_apb"); + if (IS_ERR(rst_apb)) { + ret = PTR_ERR(rst_apb); + dev_err(dev, "Cannot get APB reset.\n"); goto probe_reset_failed; } - 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"); + rst_ahb = devm_reset_control_get_optional_exclusive(dev, "rst_ahb"); + if (IS_ERR(rst_ahb)) { + ret = PTR_ERR(rst_ahb); + dev_err(dev, "Cannot get QSPI ahb reset.\n"); goto probe_reset_failed; } - reset_control_assert(rstc); - reset_control_deassert(rstc); + rst_ref = devm_reset_control_get_optional_exclusive(dev, "rst_ref"); + if (IS_ERR(rst_ref)) { + ret = PTR_ERR(rst_ref); + dev_err(dev, "Cannot get QSPI ref reset.\n"); + goto probe_reset_failed; + } - reset_control_assert(rstc_ocp); - reset_control_deassert(rstc_ocp); + /* + * Due to the problem of reset in the current QSPI driver + * we temporarily reset QSPI by writing register + */ + reset_res = ioremap(STARFIVE_RESET_REG_BASE_ADDR, 0x300); + writel(0X7E7FE00, reset_res + QSPI_RESET_REG_OFFSET); + + cqspi->master_ref_clk_hz = clk_get_rate(cqspi->clks[CLK_QSPI_REF]); - cqspi->master_ref_clk_hz = clk_get_rate(cqspi->clk); master->max_speed_hz = cqspi->master_ref_clk_hz; ddata = of_device_get_match_data(dev); if (ddata) { if (ddata->quirks & CQSPI_NEEDS_WR_DELAY) cqspi->wr_delay = 50 * DIV_ROUND_UP(NSEC_PER_SEC, cqspi->master_ref_clk_hz); + if (ddata->hwcaps_mask & CQSPI_SUPPORTS_OCTAL) master->mode_bits |= SPI_RX_OCTAL | SPI_TX_OCTAL; + if (!(ddata->quirks & CQSPI_DISABLE_DAC_MODE)) cqspi->use_direct_mode = true; } @@ -1583,15 +1673,20 @@ static int cqspi_probe(struct platform_device *pdev) } return 0; + probe_setup_failed: cqspi_controller_enable(cqspi, 0); probe_reset_failed: - clk_disable_unprepare(cqspi->clk); + clk_disable_unprepare(cqspi->clks[CLK_QSPI_REF]); + clk_disable_unprepare(cqspi->clks[CLK_QSPI_AHB]); + clk_disable_unprepare(cqspi->clks[CLK_AHB1]); + clk_disable_unprepare(cqspi->clks[CLK_QSPI_APB]); probe_clk_failed: pm_runtime_put_sync(dev); pm_runtime_disable(dev); probe_master_put: spi_master_put(master); + return ret; } @@ -1604,7 +1699,10 @@ static int cqspi_remove(struct platform_device *pdev) if (cqspi->rx_chan) dma_release_channel(cqspi->rx_chan); - clk_disable_unprepare(cqspi->clk); + clk_disable_unprepare(cqspi->clks[CLK_QSPI_REF]); + clk_disable_unprepare(cqspi->clks[CLK_QSPI_AHB]); + clk_disable_unprepare(cqspi->clks[CLK_AHB1]); + clk_disable_unprepare(cqspi->clks[CLK_QSPI_APB]); pm_runtime_put_sync(&pdev->dev); pm_runtime_disable(&pdev->dev);