mtd: rawnand: loongson: Add Loongson-2K1000 NAND controller support

The Loongson-2K1000 NAND controller is also similar to the Loongson-1C.

It supports a maximum capacity of 16GB FLASH per chip with a maximum
page size of 8KB, and it supports up to 4 chip selects and 4 RDY
signals.

The key difference from the Loongson-2K0500 is that it requires explicit
configuration of the DMA control route. Typically, it is configured as
APBDMA0.

Signed-off-by: Binbin Zhou <zhoubinbin@loongson.cn>
Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
Signed-off-by: maoxiaochuan <maoxiaochuan@loongson.cn>
This commit is contained in:
Binbin Zhou
2026-02-04 16:41:12 +08:00
committed by maoxiaochuan
parent e1fc29b581
commit bf3b61946c
@@ -74,6 +74,14 @@
#define BITS_PER_WORD (4 * BITS_PER_BYTE)
/* Loongson-2K1000 NAND DMA routing register */
#define LS2K1000_NAND_DMA_MASK GENMASK(2, 0)
#define LS2K1000_DMA0_CONF 0x0
#define LS2K1000_DMA1_CONF 0x1
#define LS2K1000_DMA2_CONF 0x2
#define LS2K1000_DMA3_CONF 0x3
#define LS2K1000_DMA4_CONF 0x4
struct loongson_nand_host;
struct loongson_nand_op {
@@ -103,6 +111,7 @@ struct loongson_nand_data {
unsigned int wait_cycle;
unsigned int nand_cs;
unsigned int dma_bits;
int (*dma_config)(struct device *dev);
void (*set_addr)(struct loongson_nand_host *host, struct loongson_nand_op *op);
};
@@ -759,6 +768,23 @@ static void loongson_nand_controller_cleanup(struct loongson_nand_host *host)
dma_release_channel(host->dma_chan);
}
static int ls2k1000_nand_apbdma_config(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
void __iomem *regs;
int val;
regs = devm_platform_ioremap_resource_byname(pdev, "dma-config");
if (IS_ERR(regs))
return PTR_ERR(regs);
val = readl(regs);
val |= FIELD_PREP(LS2K1000_NAND_DMA_MASK, LS2K1000_DMA0_CONF);
writel(val, regs);
return 0;
}
static int loongson_nand_controller_init(struct loongson_nand_host *host)
{
struct device *dev = host->dev;
@@ -787,6 +813,12 @@ static int loongson_nand_controller_init(struct loongson_nand_host *host)
regmap_write(host->regmap, LOONGSON_NAND_CS_RDY_MAP, val);
if (host->data->dma_config) {
ret = host->data->dma_config(dev);
if (ret)
return dev_err_probe(dev, ret, "failed to config DMA routing\n");
}
chan = dma_request_chan(dev, "rxtx");
if (IS_ERR(chan))
return dev_err_probe(dev, PTR_ERR(chan), "failed to request DMA channel\n");
@@ -941,6 +973,19 @@ static const struct loongson_nand_data ls2k0500_nand_data = {
.set_addr = ls1c_nand_set_addr,
};
static const struct loongson_nand_data ls2k1000_nand_data = {
.max_id_cycle = 6,
.id_cycle_field = GENMASK(14, 12),
.status_field = GENMASK(23, 16),
.op_scope_field = GENMASK(29, 16),
.hold_cycle = 0x4,
.wait_cycle = 0x12,
.nand_cs = 0x2,
.dma_bits = 64,
.dma_config = ls2k1000_nand_apbdma_config,
.set_addr = ls1c_nand_set_addr,
};
static const struct of_device_id loongson_nand_match[] = {
{
.compatible = "loongson,ls1b-nand-controller",
@@ -954,6 +999,10 @@ static const struct of_device_id loongson_nand_match[] = {
.compatible = "loongson,ls2k0500-nand-controller",
.data = &ls2k0500_nand_data,
},
{
.compatible = "loongson,ls2k1000-nand-controller",
.data = &ls2k1000_nand_data,
},
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, loongson_nand_match);