drivers/pmdomain/renesas/rmobile-sysc.c

Source file repositories/reference/linux-study-clean/drivers/pmdomain/renesas/rmobile-sysc.c

File Facts

System
Linux kernel
Corpus path
drivers/pmdomain/renesas/rmobile-sysc.c
Extension
.c
Size
8098 bytes
Lines
340
Domain
Driver Families
Bucket
drivers/pmdomain
Inferred role
Driver Families: exported/initcall integration point
Status
integration 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 rmobile_pm_domain {
	struct generic_pm_domain genpd;
	struct dev_power_governor *gov;
	int (*suspend)(void);
	void __iomem *base;
	unsigned int bit_shift;
};

static inline
struct rmobile_pm_domain *to_rmobile_pd(struct generic_pm_domain *d)
{
	return container_of(d, struct rmobile_pm_domain, genpd);
}

static int rmobile_pd_power_down(struct generic_pm_domain *genpd)
{
	struct rmobile_pm_domain *rmobile_pd = to_rmobile_pd(genpd);
	unsigned int mask = BIT(rmobile_pd->bit_shift);
	u32 val;

	if (rmobile_pd->suspend) {
		int ret = rmobile_pd->suspend();

		if (ret)
			return ret;
	}

	if (readl(rmobile_pd->base + PSTR) & mask) {
		writel(mask, rmobile_pd->base + SPDCR);

		readl_poll_timeout_atomic(rmobile_pd->base + SPDCR, val,
					  !(val & mask), 0, PSTR_RETRIES);
	}

	pr_debug("%s: Power off, 0x%08x -> PSTR = 0x%08x\n", genpd->name, mask,
		 readl(rmobile_pd->base + PSTR));

	return 0;
}

static int __rmobile_pd_power_up(struct rmobile_pm_domain *rmobile_pd)
{
	unsigned int val, mask = BIT(rmobile_pd->bit_shift);
	int ret = 0;

	if (readl(rmobile_pd->base + PSTR) & mask)
		return ret;

	writel(mask, rmobile_pd->base + SWUCR);

	ret = readl_poll_timeout_atomic(rmobile_pd->base + SWUCR, val,
					(val & mask), PSTR_DELAY_US,
					PSTR_RETRIES * PSTR_DELAY_US);

	pr_debug("%s: Power on, 0x%08x -> PSTR = 0x%08x\n",
		 rmobile_pd->genpd.name, mask,
		 readl(rmobile_pd->base + PSTR));

	return ret;
}

static int rmobile_pd_power_up(struct generic_pm_domain *genpd)
{
	return __rmobile_pd_power_up(to_rmobile_pd(genpd));
}

static void rmobile_init_pm_domain(struct rmobile_pm_domain *rmobile_pd)
{
	struct generic_pm_domain *genpd = &rmobile_pd->genpd;
	struct dev_power_governor *gov = rmobile_pd->gov;

	genpd->flags |= GENPD_FLAG_PM_CLK | GENPD_FLAG_ACTIVE_WAKEUP |
		GENPD_FLAG_NO_STAY_ON;
	genpd->attach_dev = cpg_mstp_attach_dev;
	genpd->detach_dev = cpg_mstp_detach_dev;

	if (!(genpd->flags & GENPD_FLAG_ALWAYS_ON)) {
		genpd->power_off = rmobile_pd_power_down;
		genpd->power_on = rmobile_pd_power_up;
		__rmobile_pd_power_up(rmobile_pd);
	}

	pm_genpd_init(genpd, gov ? : &simple_qos_governor, false);
}

static int rmobile_pd_suspend_console(void)
{
	/*
	 * Serial consoles make use of SCIF hardware located in this domain,
	 * hence keep the power domain on if "no_console_suspend" is set.

Annotation

Implementation Notes