drivers/memory/tegra/tegra124-emc.c

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

File Facts

System
Linux kernel
Corpus path
drivers/memory/tegra/tegra124-emc.c
Extension
.c
Size
37212 bytes
Lines
1426
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_bgbias_ctl0;
	u32 emc_cfg;
	u32 emc_cfg_2;
	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;

	struct clk *clk;

	enum emc_dram_type dram_type;
	unsigned int dram_bus_width;
	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;
};

/* 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)
{
	unsigned int i;
	u32 value;

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

	for (i = 0; i < EMC_STATUS_UPDATE_TIMEOUT; ++i) {
		value = readl(emc->regs + EMC_STATUS);
		if ((value & EMC_STATUS_TIMING_UPDATE_STALLED) == 0)
			return;
		udelay(1);
	}

	dev_err(emc->dev, "timing update timed out\n");
}

static void emc_seq_disable_auto_cal(struct tegra_emc *emc)
{
	unsigned int i;
	u32 value;

	writel(0, emc->regs + EMC_AUTO_CAL_INTERVAL);

	for (i = 0; i < EMC_STATUS_UPDATE_TIMEOUT; ++i) {
		value = readl(emc->regs + EMC_AUTO_CAL_STATUS);
		if ((value & EMC_AUTO_CAL_STATUS_ACTIVE) == 0)
			return;
		udelay(1);

Annotation

Implementation Notes