drivers/memory/pl172.c

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

File Facts

System
Linux kernel
Corpus path
drivers/memory/pl172.c
Extension
.c
Size
7871 bytes
Lines
301
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 pl172_data {
	void __iomem *base;
	unsigned long rate;
	struct clk *clk;
};

static int pl172_timing_prop(struct amba_device *adev,
			     const struct device_node *np, const char *name,
			     u32 reg_offset, u32 max, int start)
{
	struct pl172_data *pl172 = amba_get_drvdata(adev);
	int cycles;
	u32 val;

	if (!of_property_read_u32(np, name, &val)) {
		cycles = DIV_ROUND_UP(val * pl172->rate, NSEC_PER_MSEC) - start;
		if (cycles < 0) {
			cycles = 0;
		} else if (cycles > max) {
			dev_err(&adev->dev, "%s timing too tight\n", name);
			return -EINVAL;
		}

		writel(cycles, pl172->base + reg_offset);
	}

	dev_dbg(&adev->dev, "%s: %u cycle(s)\n", name, start +
				readl(pl172->base + reg_offset));

	return 0;
}

static int pl172_setup_static(struct amba_device *adev,
			      struct device_node *np, u32 cs)
{
	struct pl172_data *pl172 = amba_get_drvdata(adev);
	u32 cfg;
	int ret;

	/* MPMC static memory configuration */
	if (!of_property_read_u32(np, "mpmc,memory-width", &cfg)) {
		if (cfg == 8) {
			cfg = MPMC_STATIC_CFG_MW_8BIT;
		} else if (cfg == 16) {
			cfg = MPMC_STATIC_CFG_MW_16BIT;
		} else if (cfg == 32) {
			cfg = MPMC_STATIC_CFG_MW_32BIT;
		} else {
			dev_err(&adev->dev, "invalid memory width cs%u\n", cs);
			return -EINVAL;
		}
	} else {
		dev_err(&adev->dev, "memory-width property required\n");
		return -EINVAL;
	}

	if (of_property_read_bool(np, "mpmc,async-page-mode"))
		cfg |= MPMC_STATIC_CFG_PM;

	if (of_property_read_bool(np, "mpmc,cs-active-high"))
		cfg |= MPMC_STATIC_CFG_PC;

	if (of_property_read_bool(np, "mpmc,byte-lane-low"))
		cfg |= MPMC_STATIC_CFG_PB;

	if (of_property_read_bool(np, "mpmc,extended-wait"))
		cfg |= MPMC_STATIC_CFG_EW;

	if (amba_part(adev) == 0x172 &&
	    of_property_read_bool(np, "mpmc,buffer-enable"))
		cfg |= MPMC_STATIC_CFG_B;

	if (of_property_read_bool(np, "mpmc,write-protect"))
		cfg |= MPMC_STATIC_CFG_P;

	writel(cfg, pl172->base + MPMC_STATIC_CFG(cs));
	dev_dbg(&adev->dev, "mpmc static config cs%u: 0x%08x\n", cs, cfg);

	/* MPMC static memory timing */
	ret = pl172_timing_prop(adev, np, "mpmc,write-enable-delay",
				MPMC_STATIC_WAIT_WEN(cs),
				MPMC_STATIC_WAIT_WEN_MAX, 1);
	if (ret)
		goto fail;

	ret = pl172_timing_prop(adev, np, "mpmc,output-enable-delay",
				MPMC_STATIC_WAIT_OEN(cs),
				MPMC_STATIC_WAIT_OEN_MAX, 0);
	if (ret)
		goto fail;

Annotation

Implementation Notes