]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
spi: spi-sg2044-nor: Add configurable chip_info
authorZixian Zeng <sycamoremoon376@gmail.com>
Sun, 20 Jul 2025 08:31:44 +0000 (16:31 +0800)
committerMark Brown <broonie@kernel.org>
Thu, 24 Jul 2025 12:28:16 +0000 (13:28 +0100)
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>
drivers/spi/spi-sg2044-nor.c

index a59aa3fc55d277653d01df9c83b3f0aa08edab46..0ef569eb28b7609df1f23d89a6b3e7afc2569c80 100644 (file)
 
 #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);