drivers/memory/emif.c

Source file repositories/reference/linux-study-clean/drivers/memory/emif.c

File Facts

System
Linux kernel
Corpus path
drivers/memory/emif.c
Extension
.c
Size
34974 bytes
Lines
1177
Domain
Driver Families
Bucket
drivers/memory
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 emif_data {
	u8				duplicate;
	u8				temperature_level;
	u8				lpmode;
	struct list_head		node;
	void __iomem			*base;
	struct device			*dev;
	struct emif_regs		*regs_cache[EMIF_MAX_NUM_FREQUENCIES];
	struct emif_regs		*curr_regs;
	struct emif_platform_data	*plat_data;
	struct dentry			*debugfs_root;
	struct device_node		*np_ddr;
};

static struct emif_data *emif1;
static DEFINE_SPINLOCK(emif_lock);
static LIST_HEAD(device_list);

static void do_emif_regdump_show(struct seq_file *s, struct emif_data *emif,
	struct emif_regs *regs)
{
	u32 type = emif->plat_data->device_info->type;
	u32 ip_rev = emif->plat_data->ip_rev;

	seq_printf(s, "EMIF register cache dump for %dMHz\n",
		regs->freq/1000000);

	seq_printf(s, "ref_ctrl_shdw\t: 0x%08x\n", regs->ref_ctrl_shdw);
	seq_printf(s, "sdram_tim1_shdw\t: 0x%08x\n", regs->sdram_tim1_shdw);
	seq_printf(s, "sdram_tim2_shdw\t: 0x%08x\n", regs->sdram_tim2_shdw);
	seq_printf(s, "sdram_tim3_shdw\t: 0x%08x\n", regs->sdram_tim3_shdw);

	if (ip_rev == EMIF_4D) {
		seq_printf(s, "read_idle_ctrl_shdw_normal\t: 0x%08x\n",
			regs->read_idle_ctrl_shdw_normal);
		seq_printf(s, "read_idle_ctrl_shdw_volt_ramp\t: 0x%08x\n",
			regs->read_idle_ctrl_shdw_volt_ramp);
	} else if (ip_rev == EMIF_4D5) {
		seq_printf(s, "dll_calib_ctrl_shdw_normal\t: 0x%08x\n",
			regs->dll_calib_ctrl_shdw_normal);
		seq_printf(s, "dll_calib_ctrl_shdw_volt_ramp\t: 0x%08x\n",
			regs->dll_calib_ctrl_shdw_volt_ramp);
	}

	if (type == DDR_TYPE_LPDDR2_S2 || type == DDR_TYPE_LPDDR2_S4) {
		seq_printf(s, "ref_ctrl_shdw_derated\t: 0x%08x\n",
			regs->ref_ctrl_shdw_derated);
		seq_printf(s, "sdram_tim1_shdw_derated\t: 0x%08x\n",
			regs->sdram_tim1_shdw_derated);
		seq_printf(s, "sdram_tim3_shdw_derated\t: 0x%08x\n",
			regs->sdram_tim3_shdw_derated);
	}
}

static int emif_regdump_show(struct seq_file *s, void *unused)
{
	struct emif_data	*emif	= s->private;
	struct emif_regs	**regs_cache;
	int			i;

	if (emif->duplicate)
		regs_cache = emif1->regs_cache;
	else
		regs_cache = emif->regs_cache;

	for (i = 0; i < EMIF_MAX_NUM_FREQUENCIES && regs_cache[i]; i++) {
		do_emif_regdump_show(s, emif, regs_cache[i]);
		seq_putc(s, '\n');
	}

	return 0;
}

DEFINE_SHOW_ATTRIBUTE(emif_regdump);

static int emif_mr4_show(struct seq_file *s, void *unused)
{
	struct emif_data *emif = s->private;

	seq_printf(s, "MR4=%d\n", emif->temperature_level);
	return 0;
}

DEFINE_SHOW_ATTRIBUTE(emif_mr4);

static void emif_debugfs_init(struct emif_data *emif)
{
	if (IS_ENABLED(CONFIG_DEBUG_FS)) {
		emif->debugfs_root = debugfs_create_dir(dev_name(emif->dev), NULL);
		debugfs_create_file("regcache_dump", S_IRUGO, emif->debugfs_root, emif,

Annotation

Implementation Notes