Merge branch 'CR_2653_QSPI_5.15_ziv.xu' into 'jh7110-5.15.y-devel'

CR 2653 QSPI 5.15 ziv.xu

See merge request sdk/linux!612
This commit is contained in:
andy.hu 2022-12-01 10:37:13 +00:00
commit bb4b157c65
5 changed files with 163 additions and 43 deletions

View file

@ -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>;
};
};
};
};

View file

@ -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

View file

@ -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,
};

2
drivers/spi/Kconfig Executable file → Normal file
View file

@ -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.

View file

@ -19,6 +19,7 @@
#include <linux/jiffies.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/mtd/spi-nor.h>
#include <linux/of_device.h>
#include <linux/of.h>
#include <linux/platform_device.h>
@ -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);