drivers/mtd/nand/raw/omap_elm.c

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

File Facts

System
Linux kernel
Corpus path
drivers/mtd/nand/raw/omap_elm.c
Extension
.c
Size
15928 bytes
Lines
572
Domain
Driver Families
Bucket
drivers/mtd
Inferred role
Driver Families: exported/initcall integration point
Status
integration 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 elm_registers {
	u32 elm_irqenable;
	u32 elm_sysconfig;
	u32 elm_location_config;
	u32 elm_page_ctrl;
	u32 elm_syndrome_fragment_6[ERROR_VECTOR_MAX];
	u32 elm_syndrome_fragment_5[ERROR_VECTOR_MAX];
	u32 elm_syndrome_fragment_4[ERROR_VECTOR_MAX];
	u32 elm_syndrome_fragment_3[ERROR_VECTOR_MAX];
	u32 elm_syndrome_fragment_2[ERROR_VECTOR_MAX];
	u32 elm_syndrome_fragment_1[ERROR_VECTOR_MAX];
	u32 elm_syndrome_fragment_0[ERROR_VECTOR_MAX];
};

struct elm_info {
	struct device *dev;
	void __iomem *elm_base;
	struct completion elm_completion;
	struct list_head list;
	enum bch_ecc bch_type;
	struct elm_registers elm_regs;
	int ecc_steps;
	int ecc_syndrome_size;
};

static LIST_HEAD(elm_devices);

static void elm_write_reg(struct elm_info *info, int offset, u32 val)
{
	writel(val, info->elm_base + offset);
}

static u32 elm_read_reg(struct elm_info *info, int offset)
{
	return readl(info->elm_base + offset);
}

/**
 * elm_config - Configure ELM module
 * @dev:	ELM device
 * @bch_type:	Type of BCH ecc
 * @ecc_steps:	ECC steps to assign to config
 * @ecc_step_size:	ECC step size to assign to config
 * @ecc_syndrome_size:	ECC syndrome size to assign to config
 */
int elm_config(struct device *dev, enum bch_ecc bch_type,
	int ecc_steps, int ecc_step_size, int ecc_syndrome_size)
{
	u32 reg_val;
	struct elm_info *info = dev_get_drvdata(dev);

	if (!info) {
		dev_err(dev, "Unable to configure elm - device not probed?\n");
		return -EPROBE_DEFER;
	}
	/* ELM cannot detect ECC errors for chunks > 1KB */
	if (ecc_step_size > ((ELM_ECC_SIZE + 1) / 2)) {
		dev_err(dev, "unsupported config ecc-size=%d\n", ecc_step_size);
		return -EINVAL;
	}
	/* ELM support 8 error syndrome process */
	if (ecc_steps > ERROR_VECTOR_MAX && ecc_steps % ERROR_VECTOR_MAX) {
		dev_err(dev, "unsupported config ecc-step=%d\n", ecc_steps);
		return -EINVAL;
	}

	reg_val = (bch_type & ECC_BCH_LEVEL_MASK) | (ELM_ECC_SIZE << 16);
	elm_write_reg(info, ELM_LOCATION_CONFIG, reg_val);
	info->bch_type		= bch_type;
	info->ecc_steps		= ecc_steps;
	info->ecc_syndrome_size	= ecc_syndrome_size;

	return 0;
}
EXPORT_SYMBOL(elm_config);

/**
 * elm_configure_page_mode - Enable/Disable page mode
 * @info:	elm info
 * @index:	index number of syndrome fragment vector
 * @enable:	enable/disable flag for page mode
 *
 * Enable page mode for syndrome fragment index
 */
static void elm_configure_page_mode(struct elm_info *info, int index,
		bool enable)
{
	u32 reg_val;

	reg_val = elm_read_reg(info, ELM_PAGE_CTRL);

Annotation

Implementation Notes