drivers/mtd/nand/raw/txx9ndfmc.c

Source file repositories/reference/linux-study-clean/drivers/mtd/nand/raw/txx9ndfmc.c

File Facts

System
Linux kernel
Corpus path
drivers/mtd/nand/raw/txx9ndfmc.c
Extension
.c
Size
11473 bytes
Lines
418
Domain
Driver Families
Bucket
drivers/mtd
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

struct txx9ndfmc_priv {
	struct platform_device *dev;
	struct nand_chip chip;
	int cs;
	const char *mtdname;
};

#define MAX_TXX9NDFMC_DEV	4
struct txx9ndfmc_drvdata {
	struct mtd_info *mtds[MAX_TXX9NDFMC_DEV];
	void __iomem *base;
	unsigned char hold;	/* in gbusclock */
	unsigned char spw;	/* in gbusclock */
	struct nand_controller controller;
};

static struct platform_device *mtd_to_platdev(struct mtd_info *mtd)
{
	struct nand_chip *chip = mtd_to_nand(mtd);
	struct txx9ndfmc_priv *txx9_priv = nand_get_controller_data(chip);
	return txx9_priv->dev;
}

static void __iomem *ndregaddr(struct platform_device *dev, unsigned int reg)
{
	struct txx9ndfmc_drvdata *drvdata = platform_get_drvdata(dev);
	struct txx9ndfmc_platform_data *plat = dev_get_platdata(&dev->dev);

	return drvdata->base + (reg << plat->shift);
}

static u32 txx9ndfmc_read(struct platform_device *dev, unsigned int reg)
{
	return __raw_readl(ndregaddr(dev, reg));
}

static void txx9ndfmc_write(struct platform_device *dev,
			    u32 val, unsigned int reg)
{
	__raw_writel(val, ndregaddr(dev, reg));
}

static uint8_t txx9ndfmc_read_byte(struct nand_chip *chip)
{
	struct platform_device *dev = mtd_to_platdev(nand_to_mtd(chip));

	return txx9ndfmc_read(dev, TXX9_NDFDTR);
}

static void txx9ndfmc_write_buf(struct nand_chip *chip, const uint8_t *buf,
				int len)
{
	struct platform_device *dev = mtd_to_platdev(nand_to_mtd(chip));
	void __iomem *ndfdtr = ndregaddr(dev, TXX9_NDFDTR);
	u32 mcr = txx9ndfmc_read(dev, TXX9_NDFMCR);

	txx9ndfmc_write(dev, mcr | TXX9_NDFMCR_WE, TXX9_NDFMCR);
	while (len--)
		__raw_writel(*buf++, ndfdtr);
	txx9ndfmc_write(dev, mcr, TXX9_NDFMCR);
}

static void txx9ndfmc_read_buf(struct nand_chip *chip, uint8_t *buf, int len)
{
	struct platform_device *dev = mtd_to_platdev(nand_to_mtd(chip));
	void __iomem *ndfdtr = ndregaddr(dev, TXX9_NDFDTR);

	while (len--)
		*buf++ = __raw_readl(ndfdtr);
}

static void txx9ndfmc_cmd_ctrl(struct nand_chip *chip, int cmd,
			       unsigned int ctrl)
{
	struct txx9ndfmc_priv *txx9_priv = nand_get_controller_data(chip);
	struct platform_device *dev = txx9_priv->dev;
	struct txx9ndfmc_platform_data *plat = dev_get_platdata(&dev->dev);

	if (ctrl & NAND_CTRL_CHANGE) {
		u32 mcr = txx9ndfmc_read(dev, TXX9_NDFMCR);

		mcr &= ~(TXX9_NDFMCR_CLE | TXX9_NDFMCR_ALE | TXX9_NDFMCR_CE);
		mcr |= ctrl & NAND_CLE ? TXX9_NDFMCR_CLE : 0;
		mcr |= ctrl & NAND_ALE ? TXX9_NDFMCR_ALE : 0;
		/* TXX9_NDFMCR_CE bit is 0:high 1:low */
		mcr |= ctrl & NAND_NCE ? TXX9_NDFMCR_CE : 0;
		if (txx9_priv->cs >= 0 && (ctrl & NAND_NCE)) {
			mcr &= ~TXX9_NDFMCR_CS_MASK;
			mcr |= TXX9_NDFMCR_CS(txx9_priv->cs);
		}

Annotation

Implementation Notes