drivers/memory/tegra/tegra114-emc.c

Source file repositories/reference/linux-study-clean/drivers/memory/tegra/tegra114-emc.c

File Facts

System
Linux kernel
Corpus path
drivers/memory/tegra/tegra114-emc.c
Extension
.c
Size
35059 bytes
Lines
1352
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 emc_timing {
	unsigned long rate;

	u32 emc_burst_data[ARRAY_SIZE(emc_burst_regs)];

	u32 emc_auto_cal_config;
	u32 emc_auto_cal_config2;
	u32 emc_auto_cal_config3;
	u32 emc_auto_cal_interval;
	u32 emc_cfg;
	u32 emc_ctt_term_ctrl;
	u32 emc_mode_1;
	u32 emc_mode_2;
	u32 emc_mode_4;
	u32 emc_mode_reset;
	u32 emc_mrs_wait_cnt;
	u32 emc_sel_dpd_ctrl;
	u32 emc_xm2dqspadctrl2;
	u32 emc_zcal_cnt_long;
	u32 emc_zcal_interval;
};

struct tegra_emc {
	struct device *dev;
	struct tegra_mc *mc;
	void __iomem *regs;
	unsigned int irq;
	struct clk *clk;

	enum emc_dram_type dram_type;
	unsigned int dram_num;

	struct emc_timing last_timing;
	struct emc_timing *timings;
	unsigned int num_timings;

	struct {
		struct dentry *root;
		unsigned long min_rate;
		unsigned long max_rate;
	} debugfs;

	struct icc_provider provider;
	struct tegra_emc_rate_requests reqs;
};

static irqreturn_t tegra114_emc_isr(int irq, void *data)
{
	struct tegra_emc *emc = data;
	u32 intmask = EMC_INTSTATUS_REFRESH_OVERFLOW;
	u32 status;

	status = readl_relaxed(emc->regs + EMC_INTSTATUS) & intmask;
	if (!status)
		return IRQ_NONE;

	/* notify about HW problem */
	if (status & EMC_INTSTATUS_REFRESH_OVERFLOW)
		dev_err_ratelimited(emc->dev,
				    "refresh request overflow timeout\n");

	/* clear interrupts */
	writel_relaxed(status, emc->regs + EMC_INTSTATUS);

	return IRQ_HANDLED;
}

/* Timing change sequence functions */

static void emc_ccfifo_writel(struct tegra_emc *emc, u32 value,
			      unsigned long offset)
{
	writel(value, emc->regs + EMC_CCFIFO_DATA);
	writel(offset, emc->regs + EMC_CCFIFO_ADDR);
}

static void emc_seq_update_timing(struct tegra_emc *emc)
{
	int ret;
	u32 value;

	writel(1, emc->regs + EMC_TIMING_CONTROL);

	ret = readl_poll_timeout_atomic(emc->regs + EMC_STATUS, value,
					!(value & EMC_STATUS_TIMING_UPDATE_STALLED),
					1, EMC_STATUS_UPDATE_TIMEOUT);
	if (ret)
		dev_err(emc->dev, "timing update timed out\n");
}

Annotation

Implementation Notes