Commit 0c06da57 authored by Kamal Dasu's avatar Kamal Dasu Committed by Miquel Raynal
Browse files

mtd: rawnand: brcmnand: Add support for v7.3 controller



This change adds support for brcm NAND v7.3 controller. This controller
uses a newer version of flash_dma engine and change mostly implements
these differences.

Signed-off-by: default avatarKamal Dasu <kdasu.kdev@gmail.com>
Signed-off-by: default avatarMiquel Raynal <miquel.raynal@bootlin.com>
parent 3c7c1e45
Loading
Loading
Loading
Loading
+80 −22
Original line number Diff line number Diff line
@@ -84,6 +84,12 @@ struct brcm_nand_dma_desc {
#define FLASH_DMA_ECC_ERROR	(1 << 8)
#define FLASH_DMA_CORR_ERROR	(1 << 9)

/* Bitfields for DMA_MODE */
#define FLASH_DMA_MODE_STOP_ON_ERROR	BIT(1) /* stop in Uncorr ECC error */
#define FLASH_DMA_MODE_MODE		BIT(0) /* link list */
#define FLASH_DMA_MODE_MASK		(FLASH_DMA_MODE_STOP_ON_ERROR |	\
						FLASH_DMA_MODE_MODE)

/* 512B flash cache in the NAND controller HW */
#define FC_SHIFT		9U
#define FC_BYTES		512U
@@ -96,6 +102,51 @@ struct brcm_nand_dma_desc {
#define NAND_CTRL_RDY			(INTFC_CTLR_READY | INTFC_FLASH_READY)
#define NAND_POLL_STATUS_TIMEOUT_MS	100

/* flash_dma registers */
enum flash_dma_reg {
	FLASH_DMA_REVISION = 0,
	FLASH_DMA_FIRST_DESC,
	FLASH_DMA_FIRST_DESC_EXT,
	FLASH_DMA_CTRL,
	FLASH_DMA_MODE,
	FLASH_DMA_STATUS,
	FLASH_DMA_INTERRUPT_DESC,
	FLASH_DMA_INTERRUPT_DESC_EXT,
	FLASH_DMA_ERROR_STATUS,
	FLASH_DMA_CURRENT_DESC,
	FLASH_DMA_CURRENT_DESC_EXT,
};

/* flash_dma registers v1*/
static const u16 flash_dma_regs_v1[] = {
	[FLASH_DMA_REVISION]		= 0x00,
	[FLASH_DMA_FIRST_DESC]		= 0x04,
	[FLASH_DMA_FIRST_DESC_EXT]	= 0x08,
	[FLASH_DMA_CTRL]		= 0x0c,
	[FLASH_DMA_MODE]		= 0x10,
	[FLASH_DMA_STATUS]		= 0x14,
	[FLASH_DMA_INTERRUPT_DESC]	= 0x18,
	[FLASH_DMA_INTERRUPT_DESC_EXT]	= 0x1c,
	[FLASH_DMA_ERROR_STATUS]	= 0x20,
	[FLASH_DMA_CURRENT_DESC]	= 0x24,
	[FLASH_DMA_CURRENT_DESC_EXT]	= 0x28,
};

/* flash_dma registers v4 */
static const u16 flash_dma_regs_v4[] = {
	[FLASH_DMA_REVISION]		= 0x00,
	[FLASH_DMA_FIRST_DESC]		= 0x08,
	[FLASH_DMA_FIRST_DESC_EXT]	= 0x0c,
	[FLASH_DMA_CTRL]		= 0x10,
	[FLASH_DMA_MODE]		= 0x14,
	[FLASH_DMA_STATUS]		= 0x18,
	[FLASH_DMA_INTERRUPT_DESC]	= 0x20,
	[FLASH_DMA_INTERRUPT_DESC_EXT]	= 0x24,
	[FLASH_DMA_ERROR_STATUS]	= 0x28,
	[FLASH_DMA_CURRENT_DESC]	= 0x30,
	[FLASH_DMA_CURRENT_DESC_EXT]	= 0x34,
};

/* Controller feature flags */
enum {
	BRCMNAND_HAS_1K_SECTORS			= BIT(0),
@@ -128,6 +179,8 @@ struct brcmnand_controller {
	/* List of NAND hosts (one for each chip-select) */
	struct list_head host_list;

	/* flash_dma reg */
	const u16		*flash_dma_offsets;
	struct brcm_nand_dma_desc *dma_desc;
	dma_addr_t		dma_pa;

@@ -463,7 +516,7 @@ static int brcmnand_revision_init(struct brcmnand_controller *ctrl)
	/* Register offsets */
	if (ctrl->nand_version >= 0x0702)
		ctrl->reg_offsets = brcmnand_regs_v72;
	else if (ctrl->nand_version >= 0x0701)
	else if (ctrl->nand_version == 0x0701)
		ctrl->reg_offsets = brcmnand_regs_v71;
	else if (ctrl->nand_version >= 0x0600)
		ctrl->reg_offsets = brcmnand_regs_v60;
@@ -508,7 +561,7 @@ static int brcmnand_revision_init(struct brcmnand_controller *ctrl)
	}

	/* Maximum spare area sector size (per 512B) */
	if (ctrl->nand_version >= 0x0702)
	if (ctrl->nand_version == 0x0702)
		ctrl->max_oob = 128;
	else if (ctrl->nand_version >= 0x0600)
		ctrl->max_oob = 64;
@@ -539,6 +592,15 @@ static int brcmnand_revision_init(struct brcmnand_controller *ctrl)
	return 0;
}

static void brcmnand_flash_dma_revision_init(struct brcmnand_controller *ctrl)
{
	/* flash_dma register offsets */
	if (ctrl->nand_version >= 0x0703)
		ctrl->flash_dma_offsets = flash_dma_regs_v4;
	else
		ctrl->flash_dma_offsets = flash_dma_regs_v1;
}

static inline u32 brcmnand_read_reg(struct brcmnand_controller *ctrl,
		enum brcmnand_reg reg)
{
@@ -661,7 +723,7 @@ static void brcmnand_wr_corr_thresh(struct brcmnand_host *host, u8 val)
	enum brcmnand_reg reg = BRCMNAND_CORR_THRESHOLD;
	int cs = host->cs;

	if (ctrl->nand_version >= 0x0702)
	if (ctrl->nand_version == 0x0702)
		bits = 7;
	else if (ctrl->nand_version >= 0x0600)
		bits = 6;
@@ -715,7 +777,7 @@ enum {

static inline u32 brcmnand_spare_area_mask(struct brcmnand_controller *ctrl)
{
	if (ctrl->nand_version >= 0x0702)
	if (ctrl->nand_version == 0x0702)
		return GENMASK(7, 0);
	else if (ctrl->nand_version >= 0x0600)
		return GENMASK(6, 0);
@@ -845,20 +907,6 @@ static inline void brcmnand_set_wp(struct brcmnand_controller *ctrl, bool en)
 * Flash DMA
 ***********************************************************************/

enum flash_dma_reg {
	FLASH_DMA_REVISION		= 0x00,
	FLASH_DMA_FIRST_DESC		= 0x04,
	FLASH_DMA_FIRST_DESC_EXT	= 0x08,
	FLASH_DMA_CTRL			= 0x0c,
	FLASH_DMA_MODE			= 0x10,
	FLASH_DMA_STATUS		= 0x14,
	FLASH_DMA_INTERRUPT_DESC	= 0x18,
	FLASH_DMA_INTERRUPT_DESC_EXT	= 0x1c,
	FLASH_DMA_ERROR_STATUS		= 0x20,
	FLASH_DMA_CURRENT_DESC		= 0x24,
	FLASH_DMA_CURRENT_DESC_EXT	= 0x28,
};

static inline bool has_flash_dma(struct brcmnand_controller *ctrl)
{
	return ctrl->flash_dma_base;
@@ -884,14 +932,19 @@ static inline bool flash_dma_buf_ok(const void *buf)
		likely(IS_ALIGNED((uintptr_t)buf, 4));
}

static inline void flash_dma_writel(struct brcmnand_controller *ctrl, u8 offs,
				    u32 val)
static inline void flash_dma_writel(struct brcmnand_controller *ctrl,
				    enum flash_dma_reg dma_reg, u32 val)
{
	u16 offs = ctrl->flash_dma_offsets[dma_reg];

	brcmnand_writel(val, ctrl->flash_dma_base + offs);
}

static inline u32 flash_dma_readl(struct brcmnand_controller *ctrl, u8 offs)
static inline u32 flash_dma_readl(struct brcmnand_controller *ctrl,
				  enum flash_dma_reg dma_reg)
{
	u16 offs = ctrl->flash_dma_offsets[dma_reg];

	return brcmnand_readl(ctrl->flash_dma_base + offs);
}

@@ -2472,6 +2525,7 @@ static const struct of_device_id brcmnand_of_match[] = {
	{ .compatible = "brcm,brcmnand-v7.0" },
	{ .compatible = "brcm,brcmnand-v7.1" },
	{ .compatible = "brcm,brcmnand-v7.2" },
	{ .compatible = "brcm,brcmnand-v7.3" },
	{},
};
MODULE_DEVICE_TABLE(of, brcmnand_of_match);
@@ -2558,7 +2612,11 @@ int brcmnand_probe(struct platform_device *pdev, struct brcmnand_soc *soc)
			goto err;
		}

		flash_dma_writel(ctrl, FLASH_DMA_MODE, 1); /* linked-list */
		/* initialize the dma version */
		brcmnand_flash_dma_revision_init(ctrl);

		/* linked-list and stop on error */
		flash_dma_writel(ctrl, FLASH_DMA_MODE, FLASH_DMA_MODE_MASK);
		flash_dma_writel(ctrl, FLASH_DMA_ERROR_STATUS, 0);

		/* Allocate descriptor(s) */