Commit 5808ae66 authored by Binbin Zhou's avatar Binbin Zhou Committed by Miquel Raynal
Browse files

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: default avatarBinbin Zhou <zhoubinbin@loongson.cn>
Signed-off-by: default avatarMiquel Raynal <miquel.raynal@bootlin.com>
parent 0b1ae648
Loading
Loading
Loading
Loading
+49 −0
Original line number Diff line number Diff line
@@ -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);