drivers/memory/tegra/tegra186.c

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

File Facts

System
Linux kernel
Corpus path
drivers/memory/tegra/tegra186.c
Extension
.c
Size
18343 bytes
Lines
929
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

if (PTR_ERR(mc->bcast_ch_regs) == -EINVAL) {
			dev_warn(&pdev->dev,
				 "Broadcast channel is missing, please update your device-tree\n");
			mc->bcast_ch_regs = NULL;
			goto populate;
		}

		return PTR_ERR(mc->bcast_ch_regs);
	}

	mc->ch_regs = devm_kcalloc(mc->dev, mc->soc->num_channels, sizeof(*mc->ch_regs),
				   GFP_KERNEL);
	if (!mc->ch_regs)
		return -ENOMEM;

	for (i = 0; i < mc->soc->num_channels; i++) {
		snprintf(name, sizeof(name), "ch%u", i);

		mc->ch_regs[i] = devm_platform_ioremap_resource_byname(pdev, name);
		if (IS_ERR(mc->ch_regs[i]))
			return PTR_ERR(mc->ch_regs[i]);
	}

populate:
	err = of_platform_populate(mc->dev->of_node, NULL, NULL, mc->dev);
	if (err < 0)
		return err;

	return 0;
}

static void tegra186_mc_remove(struct tegra_mc *mc)
{
	of_platform_depopulate(mc->dev);
}

#if IS_ENABLED(CONFIG_IOMMU_API)
static void tegra186_mc_client_sid_override(struct tegra_mc *mc,
					    const struct tegra_mc_client *client,
					    unsigned int sid)
{
	u32 value, old;

	if (client->regs.sid.security == 0 && client->regs.sid.override == 0)
		return;

	value = readl(mc->regs + client->regs.sid.security);
	if ((value & MC_SID_STREAMID_SECURITY_OVERRIDE) == 0) {
		/*
		 * If the secure firmware has locked this down the override
		 * for this memory client, there's nothing we can do here.
		 */
		if (value & MC_SID_STREAMID_SECURITY_WRITE_ACCESS_DISABLED)
			return;

		/*
		 * Otherwise, try to set the override itself. Typically the
		 * secure firmware will never have set this configuration.
		 * Instead, it will either have disabled write access to
		 * this field, or it will already have set an explicit
		 * override itself.
		 */
		WARN_ON((value & MC_SID_STREAMID_SECURITY_OVERRIDE) == 0);

		value |= MC_SID_STREAMID_SECURITY_OVERRIDE;
		writel(value, mc->regs + client->regs.sid.security);
	}

	value = readl(mc->regs + client->regs.sid.override);
	old = value & MC_SID_STREAMID_OVERRIDE_MASK;

	if (old != sid) {
		dev_dbg(mc->dev, "overriding SID %x for %s with %x\n", old,
			client->name, sid);
		writel(sid, mc->regs + client->regs.sid.override);
	}
}
#endif

static int tegra186_mc_probe_device(struct tegra_mc *mc, struct device *dev)
{
#if IS_ENABLED(CONFIG_IOMMU_API)
	struct of_phandle_args args;
	unsigned int i, index = 0;
	u32 sid;

	if (!tegra_dev_iommu_get_stream_id(dev, &sid))
		return 0;

	while (!of_parse_phandle_with_args(dev->of_node, "interconnects", "#interconnect-cells",

Annotation

Implementation Notes