drivers/mtd/nand/onenand/onenand_samsung.c

Source file repositories/reference/linux-study-clean/drivers/mtd/nand/onenand/onenand_samsung.c

File Facts

System
Linux kernel
Corpus path
drivers/mtd/nand/onenand/onenand_samsung.c
Extension
.c
Size
25253 bytes
Lines
1002
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 s3c_onenand {
	struct mtd_info	*mtd;
	struct platform_device	*pdev;
	enum soc_type	type;
	void __iomem	*base;
	void __iomem	*ahb_addr;
	int		bootram_command;
	void		*page_buf;
	void		*oob_buf;
	unsigned int	(*mem_addr)(int fba, int fpa, int fsa);
	unsigned int	(*cmd_map)(unsigned int type, unsigned int val);
	void __iomem	*dma_addr;
	unsigned long	phys_base;
	struct completion	complete;
};

#define CMD_MAP_00(dev, addr)		(dev->cmd_map(MAP_00, ((addr) << 1)))
#define CMD_MAP_01(dev, mem_addr)	(dev->cmd_map(MAP_01, (mem_addr)))
#define CMD_MAP_10(dev, mem_addr)	(dev->cmd_map(MAP_10, (mem_addr)))
#define CMD_MAP_11(dev, addr)		(dev->cmd_map(MAP_11, ((addr) << 2)))

static struct s3c_onenand *onenand;

static inline int s3c_read_reg(int offset)
{
	return readl(onenand->base + offset);
}

static inline void s3c_write_reg(int value, int offset)
{
	writel(value, onenand->base + offset);
}

static inline int s3c_read_cmd(unsigned int cmd)
{
	return readl(onenand->ahb_addr + cmd);
}

static inline void s3c_write_cmd(int value, unsigned int cmd)
{
	writel(value, onenand->ahb_addr + cmd);
}

#ifdef SAMSUNG_DEBUG
static void s3c_dump_reg(void)
{
	int i;

	for (i = 0; i < 0x400; i += 0x40) {
		printk(KERN_INFO "0x%08X: 0x%08x 0x%08x 0x%08x 0x%08x\n",
			(unsigned int) onenand->base + i,
			s3c_read_reg(i), s3c_read_reg(i + 0x10),
			s3c_read_reg(i + 0x20), s3c_read_reg(i + 0x30));
	}
}
#endif

static unsigned int s3c64xx_cmd_map(unsigned type, unsigned val)
{
	return (type << S3C64XX_CMD_MAP_SHIFT) | val;
}

static unsigned int s3c6400_mem_addr(int fba, int fpa, int fsa)
{
	return (fba << S3C6400_FBA_SHIFT) | (fpa << S3C6400_FPA_SHIFT) |
		(fsa << S3C6400_FSA_SHIFT);
}

static unsigned int s3c6410_mem_addr(int fba, int fpa, int fsa)
{
	return (fba << S3C6410_FBA_SHIFT) | (fpa << S3C6410_FPA_SHIFT) |
		(fsa << S3C6410_FSA_SHIFT);
}

static void s3c_onenand_reset(void)
{
	unsigned long timeout = 0x10000;
	int stat;

	s3c_write_reg(ONENAND_MEM_RESET_COLD, MEM_RESET_OFFSET);
	while (1 && timeout--) {
		stat = s3c_read_reg(INT_ERR_STAT_OFFSET);
		if (stat & RST_CMP)
			break;
	}
	stat = s3c_read_reg(INT_ERR_STAT_OFFSET);
	s3c_write_reg(stat, INT_ERR_ACK_OFFSET);

	/* Clear interrupt */
	s3c_write_reg(0x0, INT_ERR_ACK_OFFSET);

Annotation

Implementation Notes