drivers/pmdomain/thead/th1520-pm-domains.c

Source file repositories/reference/linux-study-clean/drivers/pmdomain/thead/th1520-pm-domains.c

File Facts

System
Linux kernel
Corpus path
drivers/pmdomain/thead/th1520-pm-domains.c
Extension
.c
Size
7076 bytes
Lines
286
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 th1520_power_domain {
	struct th1520_aon_chan *aon_chan;
	struct generic_pm_domain genpd;
	u32 rsrc;
};

struct th1520_power_info {
	const char *name;
	u32 rsrc;
	bool disabled;
};

/*
 * The AUDIO power domain is marked as disabled to prevent the driver from
 * managing its power state. Direct AON firmware calls to control this power
 * island trigger a firmware bug causing system instability. Until this
 * firmware issue is resolved, the AUDIO power domain must remain disabled
 * to avoid crashes.
 */
static const struct th1520_power_info th1520_pd_ranges[] = {
	[TH1520_AUDIO_PD] = {"audio", TH1520_AON_AUDIO_PD, true },
	[TH1520_VDEC_PD] = { "vdec", TH1520_AON_VDEC_PD, false },
	[TH1520_NPU_PD] = { "npu", TH1520_AON_NPU_PD, false },
	[TH1520_VENC_PD] = { "venc", TH1520_AON_VENC_PD, false },
	[TH1520_GPU_PD] = { "gpu", TH1520_AON_GPU_PD, false },
	[TH1520_DSP0_PD] = { "dsp0", TH1520_AON_DSP0_PD, false },
	[TH1520_DSP1_PD] = { "dsp1", TH1520_AON_DSP1_PD, false }
};

static inline struct th1520_power_domain *
to_th1520_power_domain(struct generic_pm_domain *genpd)
{
	return container_of(genpd, struct th1520_power_domain, genpd);
}

static int th1520_pd_power_on(struct generic_pm_domain *domain)
{
	struct th1520_power_domain *pd = to_th1520_power_domain(domain);

	return th1520_aon_power_update(pd->aon_chan, pd->rsrc, true);
}

static int th1520_pd_power_off(struct generic_pm_domain *domain)
{
	struct th1520_power_domain *pd = to_th1520_power_domain(domain);

	return th1520_aon_power_update(pd->aon_chan, pd->rsrc, false);
}

static struct generic_pm_domain *th1520_pd_xlate(const struct of_phandle_args *spec,
						 void *data)
{
	struct generic_pm_domain *domain = ERR_PTR(-ENOENT);
	struct genpd_onecell_data *pd_data = data;
	unsigned int i;

	for (i = 0; i < ARRAY_SIZE(th1520_pd_ranges); i++) {
		struct th1520_power_domain *pd;

		if (th1520_pd_ranges[i].disabled)
			continue;

		pd = to_th1520_power_domain(pd_data->domains[i]);
		if (pd->rsrc == spec->args[0]) {
			domain = &pd->genpd;
			break;
		}
	}

	return domain;
}

static struct th1520_power_domain *
th1520_add_pm_domain(struct device *dev, const struct th1520_power_info *pi)
{
	struct th1520_power_domain *pd;
	int ret;

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

	pd->rsrc = pi->rsrc;
	pd->genpd.power_on = th1520_pd_power_on;
	pd->genpd.power_off = th1520_pd_power_off;
	pd->genpd.name = pi->name;

	ret = pm_genpd_init(&pd->genpd, NULL, true);
	if (ret)
		return ERR_PTR(ret);

Annotation

Implementation Notes