drivers/pmdomain/bcm/bcm2835-power.c

Source file repositories/reference/linux-study-clean/drivers/pmdomain/bcm/bcm2835-power.c

File Facts

System
Linux kernel
Corpus path
drivers/pmdomain/bcm/bcm2835-power.c
Extension
.c
Size
18309 bytes
Lines
705
Domain
Driver Families
Bucket
drivers/pmdomain
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 bcm2835_power_domain {
	struct generic_pm_domain base;
	struct bcm2835_power *power;
	u32 domain;
	struct clk *clk;
};

struct bcm2835_power {
	struct device		*dev;
	/* PM registers. */
	void __iomem		*base;
	/* AXI Async bridge registers. */
	void __iomem		*asb;
	/* RPiVid bridge registers. */
	void __iomem		*rpivid_asb;

	struct genpd_onecell_data pd_xlate;
	struct bcm2835_power_domain domains[BCM2835_POWER_DOMAIN_COUNT];
	struct reset_controller_dev reset;
};

static int bcm2835_asb_control(struct bcm2835_power *power, u32 reg, bool enable)
{
	void __iomem *base = power->asb;
	u32 val;

	switch (reg) {
	case 0:
		return 0;
	case ASB_V3D_S_CTRL:
	case ASB_V3D_M_CTRL:
		if (power->rpivid_asb)
			base = power->rpivid_asb;
		break;
	}

	/* Enable the module's async AXI bridges. */
	if (enable) {
		val = readl(base + reg) & ~ASB_REQ_STOP;
	} else {
		val = readl(base + reg) | ASB_REQ_STOP;
	}
	writel(PM_PASSWORD | val, base + reg);

	if (readl_poll_timeout_atomic(base + reg, val,
				      !!(val & ASB_ACK) != enable, 0, 5))
		return -ETIMEDOUT;

	return 0;
}

static int bcm2835_asb_enable(struct bcm2835_power *power, u32 reg)
{
	return bcm2835_asb_control(power, reg, true);
}

static int bcm2835_asb_disable(struct bcm2835_power *power, u32 reg)
{
	return bcm2835_asb_control(power, reg, false);
}

static int bcm2835_power_power_off(struct bcm2835_power_domain *pd, u32 pm_reg)
{
	struct bcm2835_power *power = pd->power;

	/* We don't run this on BCM2711 */
	if (power->rpivid_asb)
		return 0;

	/* Enable functional isolation */
	PM_WRITE(pm_reg, PM_READ(pm_reg) & ~PM_ISFUNC);

	/* Enable electrical isolation */
	PM_WRITE(pm_reg, PM_READ(pm_reg) & ~PM_ISPOW);

	/* Open the power switches. */
	PM_WRITE(pm_reg, PM_READ(pm_reg) & ~PM_POWUP);

	return 0;
}

static int bcm2835_power_power_on(struct bcm2835_power_domain *pd, u32 pm_reg)
{
	struct bcm2835_power *power = pd->power;
	struct device *dev = power->dev;
	int ret;
	int inrush;
	bool powok;
	u32 val;

Annotation

Implementation Notes