drivers/soc/tegra/flowctrl.c

Source file repositories/reference/linux-study-clean/drivers/soc/tegra/flowctrl.c

File Facts

System
Linux kernel
Corpus path
drivers/soc/tegra/flowctrl.c
Extension
.c
Size
5743 bytes
Lines
227
Domain
Driver Families
Bucket
drivers/soc
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

if (tegra_get_chip_id() == TEGRA30) {
			/*
			 * The wfi doesn't work well on Tegra30 because
			 * CPU hangs under some odd circumstances after
			 * power-gating (like memory running off PLLP),
			 * hence use wfe that is working perfectly fine.
			 * Note that Tegra30 TRM doc clearly stands that
			 * wfi should be used for the "Cluster Switching",
			 * while wfe for the power-gating, just like it
			 * is done on Tegra20.
			 */
			reg |= TEGRA20_FLOW_CTRL_CSR_WFE_CPU0 << cpuid;
		} else {
			/* pwr gating on wfi */
			reg |= TEGRA30_FLOW_CTRL_CSR_WFI_CPU0 << cpuid;
		}
		break;
	}
	reg |= FLOW_CTRL_CSR_INTR_FLAG;			/* clear intr flag */
	reg |= FLOW_CTRL_CSR_EVENT_FLAG;		/* clear event flag */
	reg |= FLOW_CTRL_CSR_ENABLE;			/* pwr gating */
	flowctrl_write_cpu_csr(cpuid, reg);

	for (i = 0; i < num_possible_cpus(); i++) {
		if (i == cpuid)
			continue;
		reg = flowctrl_read_cpu_csr(i);
		reg |= FLOW_CTRL_CSR_EVENT_FLAG;
		reg |= FLOW_CTRL_CSR_INTR_FLAG;
		flowctrl_write_cpu_csr(i, reg);
	}
}

void flowctrl_cpu_suspend_exit(unsigned int cpuid)
{
	unsigned int reg;

	/* Disable powergating via flow controller for CPU0 */
	reg = flowctrl_read_cpu_csr(cpuid);
	switch (tegra_get_chip_id()) {
	case TEGRA20:
		/* clear wfe bitmap */
		reg &= ~TEGRA20_FLOW_CTRL_CSR_WFE_BITMAP;
		/* clear wfi bitmap */
		reg &= ~TEGRA20_FLOW_CTRL_CSR_WFI_BITMAP;
		break;
	case TEGRA30:
	case TEGRA114:
	case TEGRA124:
		/* clear wfe bitmap */
		reg &= ~TEGRA30_FLOW_CTRL_CSR_WFE_BITMAP;
		/* clear wfi bitmap */
		reg &= ~TEGRA30_FLOW_CTRL_CSR_WFI_BITMAP;
		break;
	}
	reg &= ~FLOW_CTRL_CSR_ENABLE;			/* clear enable */
	reg |= FLOW_CTRL_CSR_INTR_FLAG;			/* clear intr */
	reg |= FLOW_CTRL_CSR_EVENT_FLAG;		/* clear event */
	flowctrl_write_cpu_csr(cpuid, reg);
}

static int tegra_flowctrl_probe(struct platform_device *pdev)
{
	void __iomem *base = tegra_flowctrl_base;

	tegra_flowctrl_base = devm_platform_get_and_ioremap_resource(pdev, 0, NULL);
	if (IS_ERR(tegra_flowctrl_base))
		return PTR_ERR(tegra_flowctrl_base);

	iounmap(base);

	return 0;
}

static const struct of_device_id tegra_flowctrl_match[] = {
	{ .compatible = "nvidia,tegra210-flowctrl" },
	{ .compatible = "nvidia,tegra124-flowctrl" },
	{ .compatible = "nvidia,tegra114-flowctrl" },
	{ .compatible = "nvidia,tegra30-flowctrl" },
	{ .compatible = "nvidia,tegra20-flowctrl" },
	{ }
};

static struct platform_driver tegra_flowctrl_driver = {
	.driver = {
		.name = "tegra-flowctrl",
		.suppress_bind_attrs = true,
		.of_match_table = tegra_flowctrl_match,
	},
	.probe = tegra_flowctrl_probe,

Annotation

Implementation Notes