drivers/bus/tegra-gmi.c

Source file repositories/reference/linux-study-clean/drivers/bus/tegra-gmi.c

File Facts

System
Linux kernel
Corpus path
drivers/bus/tegra-gmi.c
Extension
.c
Size
8278 bytes
Lines
318
Domain
Driver Families
Bucket
drivers/bus
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 tegra_gmi {
	struct device *dev;
	void __iomem *base;
	struct clk *clk;
	struct reset_control *rst;

	u32 snor_config;
	u32 snor_timing0;
	u32 snor_timing1;
};

static int tegra_gmi_enable(struct tegra_gmi *gmi)
{
	int err;

	pm_runtime_enable(gmi->dev);
	err = pm_runtime_resume_and_get(gmi->dev);
	if (err) {
		pm_runtime_disable(gmi->dev);
		return err;
	}

	reset_control_assert(gmi->rst);
	usleep_range(2000, 4000);
	reset_control_deassert(gmi->rst);

	writel(gmi->snor_timing0, gmi->base + TEGRA_GMI_TIMING0);
	writel(gmi->snor_timing1, gmi->base + TEGRA_GMI_TIMING1);

	gmi->snor_config |= TEGRA_GMI_CONFIG_GO;
	writel(gmi->snor_config, gmi->base + TEGRA_GMI_CONFIG);

	return 0;
}

static void tegra_gmi_disable(struct tegra_gmi *gmi)
{
	u32 config;

	/* stop GMI operation */
	config = readl(gmi->base + TEGRA_GMI_CONFIG);
	config &= ~TEGRA_GMI_CONFIG_GO;
	writel(config, gmi->base + TEGRA_GMI_CONFIG);

	reset_control_assert(gmi->rst);

	pm_runtime_put_sync_suspend(gmi->dev);
	pm_runtime_force_suspend(gmi->dev);
}

static int tegra_gmi_parse_dt(struct tegra_gmi *gmi)
{
	struct device_node *child;
	u32 property, ranges[4];
	int err;

	child = of_get_next_available_child(gmi->dev->of_node, NULL);
	if (!child) {
		dev_err(gmi->dev, "no child nodes found\n");
		return -ENODEV;
	}

	/*
	 * We currently only support one child device due to lack of
	 * chip-select address decoding. Which means that we only have one
	 * chip-select line from the GMI controller.
	 */
	if (of_get_child_count(gmi->dev->of_node) > 1)
		dev_warn(gmi->dev, "only one child device is supported.");

	if (of_property_read_bool(child, "nvidia,snor-data-width-32bit"))
		gmi->snor_config |= TEGRA_GMI_BUS_WIDTH_32BIT;

	if (of_property_read_bool(child, "nvidia,snor-mux-mode"))
		gmi->snor_config |= TEGRA_GMI_MUX_MODE;

	if (of_property_read_bool(child, "nvidia,snor-rdy-active-before-data"))
		gmi->snor_config |= TEGRA_GMI_RDY_BEFORE_DATA;

	if (of_property_read_bool(child, "nvidia,snor-rdy-active-high"))
		gmi->snor_config |= TEGRA_GMI_RDY_ACTIVE_HIGH;

	if (of_property_read_bool(child, "nvidia,snor-adv-active-high"))
		gmi->snor_config |= TEGRA_GMI_ADV_ACTIVE_HIGH;

	if (of_property_read_bool(child, "nvidia,snor-oe-active-high"))
		gmi->snor_config |= TEGRA_GMI_OE_ACTIVE_HIGH;

	if (of_property_read_bool(child, "nvidia,snor-cs-active-high"))
		gmi->snor_config |= TEGRA_GMI_CS_ACTIVE_HIGH;

Annotation

Implementation Notes