drivers/pmdomain/renesas/rcar-gen4-sysc.c

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

File Facts

System
Linux kernel
Corpus path
drivers/pmdomain/renesas/rcar-gen4-sysc.c
Extension
.c
Size
9626 bytes
Lines
379
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 rcar_gen4_sysc_pd {
	struct generic_pm_domain genpd;
	u8 pdr;
	unsigned int flags;
	char name[];
};

static inline struct rcar_gen4_sysc_pd *to_rcar_gen4_pd(struct generic_pm_domain *d)
{
	return container_of(d, struct rcar_gen4_sysc_pd, genpd);
}

static int rcar_gen4_sysc_pd_power_off(struct generic_pm_domain *genpd)
{
	struct rcar_gen4_sysc_pd *pd = to_rcar_gen4_pd(genpd);

	pr_debug("%s: %s\n", __func__, genpd->name);
	return rcar_gen4_sysc_power(pd->pdr, false);
}

static int rcar_gen4_sysc_pd_power_on(struct generic_pm_domain *genpd)
{
	struct rcar_gen4_sysc_pd *pd = to_rcar_gen4_pd(genpd);

	pr_debug("%s: %s\n", __func__, genpd->name);
	return rcar_gen4_sysc_power(pd->pdr, true);
}

static int __init rcar_gen4_sysc_pd_setup(struct rcar_gen4_sysc_pd *pd)
{
	struct generic_pm_domain *genpd = &pd->genpd;
	const char *name = pd->genpd.name;
	int error;

	if (pd->flags & PD_CPU) {
		/*
		 * This domain contains a CPU core and therefore it should
		 * only be turned off if the CPU is not in use.
		 */
		pr_debug("PM domain %s contains %s\n", name, "CPU");
		genpd->flags |= GENPD_FLAG_ALWAYS_ON;
	} else if (pd->flags & PD_SCU) {
		/*
		 * This domain contains an SCU and cache-controller, and
		 * therefore it should only be turned off if the CPU cores are
		 * not in use.
		 */
		pr_debug("PM domain %s contains %s\n", name, "SCU");
		genpd->flags |= GENPD_FLAG_ALWAYS_ON;
	} else if (pd->flags & PD_NO_CR) {
		/*
		 * This domain cannot be turned off.
		 */
		genpd->flags |= GENPD_FLAG_ALWAYS_ON;
	}

	if (!(pd->flags & (PD_CPU | PD_SCU))) {
		/* Enable Clock Domain for I/O devices */
		genpd->flags |= GENPD_FLAG_PM_CLK | GENPD_FLAG_ACTIVE_WAKEUP;
		genpd->attach_dev = cpg_mssr_attach_dev;
		genpd->detach_dev = cpg_mssr_detach_dev;
	}

	genpd->flags |= GENPD_FLAG_NO_STAY_ON;
	genpd->power_off = rcar_gen4_sysc_pd_power_off;
	genpd->power_on = rcar_gen4_sysc_pd_power_on;

	if (pd->flags & (PD_CPU | PD_NO_CR)) {
		/* Skip CPUs (handled by SMP code) and areas without control */
		pr_debug("%s: Not touching %s\n", __func__, genpd->name);
		goto finalize;
	}

	if (!rcar_gen4_sysc_power_is_off(pd->pdr)) {
		pr_debug("%s: %s is already powered\n", __func__, genpd->name);
		goto finalize;
	}

	rcar_gen4_sysc_power(pd->pdr, true);

finalize:
	error = pm_genpd_init(genpd, &simple_qos_governor, false);
	if (error)
		pr_err("Failed to init PM domain %s: %d\n", name, error);

	return error;
}

static const struct of_device_id rcar_gen4_sysc_matches[] __initconst = {
#ifdef CONFIG_SYSC_R8A779A0

Annotation

Implementation Notes