drivers/pmdomain/actions/owl-sps.c

Source file repositories/reference/linux-study-clean/drivers/pmdomain/actions/owl-sps.c

File Facts

System
Linux kernel
Corpus path
drivers/pmdomain/actions/owl-sps.c
Extension
.c
Size
6427 bytes
Lines
315
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 owl_sps_domain_info {
	const char *name;
	int pwr_bit;
	int ack_bit;
	unsigned int genpd_flags;
};

struct owl_sps_info {
	unsigned num_domains;
	const struct owl_sps_domain_info *domains;
};

struct owl_sps {
	struct device *dev;
	const struct owl_sps_info *info;
	void __iomem *base;
	struct genpd_onecell_data genpd_data;
	struct generic_pm_domain *domains[];
};

#define to_owl_pd(gpd) container_of(gpd, struct owl_sps_domain, genpd)

struct owl_sps_domain {
	struct generic_pm_domain genpd;
	const struct owl_sps_domain_info *info;
	struct owl_sps *sps;
};

static int owl_sps_set_power(struct owl_sps_domain *pd, bool enable)
{
	u32 pwr_mask, ack_mask;

	ack_mask = BIT(pd->info->ack_bit);
	pwr_mask = BIT(pd->info->pwr_bit);

	return owl_sps_set_pg(pd->sps->base, pwr_mask, ack_mask, enable);
}

static int owl_sps_power_on(struct generic_pm_domain *domain)
{
	struct owl_sps_domain *pd = to_owl_pd(domain);

	dev_dbg(pd->sps->dev, "%s power on", pd->info->name);

	return owl_sps_set_power(pd, true);
}

static int owl_sps_power_off(struct generic_pm_domain *domain)
{
	struct owl_sps_domain *pd = to_owl_pd(domain);

	dev_dbg(pd->sps->dev, "%s power off", pd->info->name);

	return owl_sps_set_power(pd, false);
}

static int owl_sps_init_domain(struct owl_sps *sps, int index)
{
	struct owl_sps_domain *pd;

	pd = devm_kzalloc(sps->dev, sizeof(*pd), GFP_KERNEL);
	if (!pd)
		return -ENOMEM;

	pd->info = &sps->info->domains[index];
	pd->sps = sps;

	pd->genpd.name = pd->info->name;
	pd->genpd.power_on = owl_sps_power_on;
	pd->genpd.power_off = owl_sps_power_off;
	pd->genpd.flags = pd->info->genpd_flags;
	pm_genpd_init(&pd->genpd, NULL, false);

	sps->genpd_data.domains[index] = &pd->genpd;

	return 0;
}

static int owl_sps_probe(struct platform_device *pdev)
{
	const struct owl_sps_info *sps_info;
	struct owl_sps *sps;
	int i, ret;

	sps_info = device_get_match_data(&pdev->dev);
	if (!sps_info) {
		dev_err(&pdev->dev, "unknown compatible or missing data\n");
		return -EINVAL;
	}

Annotation

Implementation Notes