spi: spi-sg2044-nor: Add configurable chip_info

SG2044 and SG2042 have similar SPI-NOR flash controller design,
but have incompatibility which causes existing driver
not working on SG2042:
1. SPI-NOR flash controller on SG2042 have no OPT register.
2. FIFO trigger level on SG2042 should be strictly less than 8.

So introduce a new configurable chip_info structure to hold the
different configuration.

Link: https://github.com/sophgo/sophgo-doc/blob/main/SG2042/TRM/source/SPI-flash.rst
Signed-off-by: Zixian Zeng <sycamoremoon376@gmail.com>
Reviewed-by: Chen Wang <unicorn_wang@outlook.com> & Tested-by: Chen Wang
Link: https://patch.msgid.link/20250720-sfg-spifmc-v4-2-033188ad801e@gmail.com
Reviewed-by: Chen Wang <unicorn_wang@outlook.com> & Tested-by: Chen Wang 
Signed-off-by: Mark Brown <broonie@kernel.org>
This commit is contained in:
Zixian Zeng 2025-07-20 16:31:44 +08:00 committed by Mark Brown
parent 7438379cfc
commit 5653b4f884

View File

@ -84,12 +84,18 @@
#define SPIFMC_MAX_READ_SIZE 0x10000
struct sg204x_spifmc_chip_info {
bool has_opt_reg;
u32 rd_fifo_int_trigger_level;
};
struct sg2044_spifmc {
struct spi_controller *ctrl;
void __iomem *io_base;
struct device *dev;
struct mutex lock;
struct clk *clk;
const struct sg204x_spifmc_chip_info *chip_info;
};
static int sg2044_spifmc_wait_int(struct sg2044_spifmc *spifmc, u8 int_type)
@ -139,7 +145,7 @@ static ssize_t sg2044_spifmc_read_64k(struct sg2044_spifmc *spifmc,
reg = sg2044_spifmc_init_reg(spifmc);
reg |= (op->addr.nbytes + op->dummy.nbytes) << SPIFMC_TRAN_CSR_ADDR_BYTES_SHIFT;
reg |= SPIFMC_TRAN_CSR_FIFO_TRG_LVL_8_BYTE;
reg |= spifmc->chip_info->rd_fifo_int_trigger_level;
reg |= SPIFMC_TRAN_CSR_WITH_CMD;
reg |= SPIFMC_TRAN_CSR_TRAN_MODE_RX;
@ -335,7 +341,8 @@ static ssize_t sg2044_spifmc_trans_reg(struct sg2044_spifmc *spifmc,
reg |= SPIFMC_TRAN_CSR_TRAN_MODE_RX;
reg |= SPIFMC_TRAN_CSR_TRAN_MODE_TX;
writel(SPIFMC_OPT_DISABLE_FIFO_FLUSH, spifmc->io_base + SPIFMC_OPT);
if (spifmc->chip_info->has_opt_reg)
writel(SPIFMC_OPT_DISABLE_FIFO_FLUSH, spifmc->io_base + SPIFMC_OPT);
} else {
/*
* If write values to the Status Register,
@ -457,6 +464,11 @@ static int sg2044_spifmc_probe(struct platform_device *pdev)
ret = devm_mutex_init(dev, &spifmc->lock);
if (ret)
return ret;
spifmc->chip_info = device_get_match_data(&pdev->dev);
if (!spifmc->chip_info) {
dev_err(&pdev->dev, "Failed to get specific chip info\n");
return -EINVAL;
}
sg2044_spifmc_init(spifmc);
sg2044_spifmc_init_reg(spifmc);
@ -468,8 +480,13 @@ static int sg2044_spifmc_probe(struct platform_device *pdev)
return 0;
}
static const struct sg204x_spifmc_chip_info sg2044_chip_info = {
.has_opt_reg = true,
.rd_fifo_int_trigger_level = SPIFMC_TRAN_CSR_FIFO_TRG_LVL_8_BYTE,
};
static const struct of_device_id sg2044_spifmc_match[] = {
{ .compatible = "sophgo,sg2044-spifmc-nor" },
{ .compatible = "sophgo,sg2044-spifmc-nor", .data = &sg2044_chip_info },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, sg2044_spifmc_match);