drivers/mtd/nand/raw/vf610_nfc.c

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

File Facts

System
Linux kernel
Corpus path
drivers/mtd/nand/raw/vf610_nfc.c
Extension
.c
Size
25845 bytes
Lines
950
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 vf610_nfc {
	struct nand_controller base;
	struct nand_chip chip;
	struct device *dev;
	void __iomem *regs;
	struct completion cmd_done;
	/* Status and ID are in alternate locations. */
	enum vf610_nfc_variant variant;
	struct clk *clk;
	/*
	 * Indicate that user data is accessed (full page/oob). This is
	 * useful to indicate the driver whether to swap byte endianness.
	 * See comments in vf610_nfc_rd_from_sram/vf610_nfc_wr_to_sram.
	 */
	bool data_access;
	u32 ecc_mode;
};

static inline struct vf610_nfc *chip_to_nfc(struct nand_chip *chip)
{
	return container_of(chip, struct vf610_nfc, chip);
}

static inline u32 vf610_nfc_read(struct vf610_nfc *nfc, uint reg)
{
	return readl(nfc->regs + reg);
}

static inline void vf610_nfc_write(struct vf610_nfc *nfc, uint reg, u32 val)
{
	writel(val, nfc->regs + reg);
}

static inline void vf610_nfc_set(struct vf610_nfc *nfc, uint reg, u32 bits)
{
	vf610_nfc_write(nfc, reg, vf610_nfc_read(nfc, reg) | bits);
}

static inline void vf610_nfc_clear(struct vf610_nfc *nfc, uint reg, u32 bits)
{
	vf610_nfc_write(nfc, reg, vf610_nfc_read(nfc, reg) & ~bits);
}

static inline void vf610_nfc_set_field(struct vf610_nfc *nfc, u32 reg,
				       u32 mask, u32 shift, u32 val)
{
	vf610_nfc_write(nfc, reg,
			(vf610_nfc_read(nfc, reg) & (~mask)) | val << shift);
}

static inline bool vf610_nfc_kernel_is_little_endian(void)
{
#ifdef __LITTLE_ENDIAN
	return true;
#else
	return false;
#endif
}

/*
 * Read accessor for internal SRAM buffer
 * @dst: destination address in regular memory
 * @src: source address in SRAM buffer
 * @len: bytes to copy
 * @fix_endian: Fix endianness if required
 *
 * Use this accessor for the internal SRAM buffers. On the ARM
 * Freescale Vybrid SoC it's known that the driver can treat
 * the SRAM buffer as if it's memory. Other platform might need
 * to treat the buffers differently.
 *
 * The controller stores bytes from the NAND chip internally in big
 * endianness. On little endian platforms such as Vybrid this leads
 * to reversed byte order.
 * For performance reason (and earlier probably due to unawareness)
 * the driver avoids correcting endianness where it has control over
 * write and read side (e.g. page wise data access).
 */
static inline void vf610_nfc_rd_from_sram(void *dst, const void __iomem *src,
					  size_t len, bool fix_endian)
{
	if (vf610_nfc_kernel_is_little_endian() && fix_endian) {
		unsigned int i;

		for (i = 0; i < len; i += 4) {
			u32 val = swab32(__raw_readl(src + i));

			memcpy(dst + i, &val, min(sizeof(val), len - i));
		}
	} else {

Annotation

Implementation Notes