drivers/pmdomain/marvell/pxa1908-power-controller.c

Source file repositories/reference/linux-study-clean/drivers/pmdomain/marvell/pxa1908-power-controller.c

File Facts

System
Linux kernel
Corpus path
drivers/pmdomain/marvell/pxa1908-power-controller.c
Extension
.c
Size
8037 bytes
Lines
306
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 pxa1908_pd_ctrl {
	struct generic_pm_domain *domains[NR_DOMAINS];
	struct genpd_onecell_data onecell_data;
	struct regmap *base;
	struct device *dev;
};

struct pxa1908_pd_data {
	u32 reg_clk_res_ctrl;
	u32 pwr_state;
	u32 hw_mode;
	bool keep_on;
	int id;
};

struct pxa1908_pd {
	const struct pxa1908_pd_data data;
	struct pxa1908_pd_ctrl *ctrl;
	struct generic_pm_domain genpd;
	bool initialized;
};

static inline bool pxa1908_pd_is_on(struct pxa1908_pd *pd)
{
	struct pxa1908_pd_ctrl *ctrl = pd->ctrl;

	switch (pd->data.id) {
	case PXA1908_POWER_DOMAIN_AUDIO:
		return regmap_test_bits(ctrl->base, APMU_AUDIO_CLK, AUDIO_ULCX_ENABLE);
	case PXA1908_POWER_DOMAIN_DSI:
		return regmap_test_bits(ctrl->base, APMU_DEBUG, DSI_PHY_DVM_MASK);
	default:
		return regmap_test_bits(ctrl->base, APMU_PWR_STATUS_REG, pd->data.pwr_state);
	}
}

static int pxa1908_pd_power_on(struct generic_pm_domain *genpd)
{
	struct pxa1908_pd *pd = to_pxa1908_pd(genpd);
	const struct pxa1908_pd_data *data = &pd->data;
	struct pxa1908_pd_ctrl *ctrl = pd->ctrl;
	unsigned int status;
	int ret = 0;

	regmap_set_bits(ctrl->base, data->reg_clk_res_ctrl, data->hw_mode);
	if (data->id != PXA1908_POWER_DOMAIN_ISP)
		regmap_write(ctrl->base, APMU_PWR_BLK_TMR_REG, 0x20001fff);
	regmap_set_bits(ctrl->base, APMU_PWR_CTRL_REG, data->pwr_state);

	ret = regmap_read_poll_timeout(ctrl->base, APMU_PWR_STATUS_REG, status,
				       status & data->pwr_state, POWER_POLL_SLEEP_US,
				       POWER_ON_LATENCY_US + POWER_POLL_TIMEOUT_US);
	if (ret == -ETIMEDOUT)
		dev_err(ctrl->dev, "timed out powering on domain '%s'\n", pd->genpd.name);

	return ret;
}

static int pxa1908_pd_power_off(struct generic_pm_domain *genpd)
{
	struct pxa1908_pd *pd = to_pxa1908_pd(genpd);
	const struct pxa1908_pd_data *data = &pd->data;
	struct pxa1908_pd_ctrl *ctrl = pd->ctrl;
	unsigned int status;
	int ret;

	regmap_clear_bits(ctrl->base, APMU_PWR_CTRL_REG, data->pwr_state);

	ret = regmap_read_poll_timeout(ctrl->base, APMU_PWR_STATUS_REG, status,
				       !(status & data->pwr_state), POWER_POLL_SLEEP_US,
				       POWER_OFF_LATENCY_US + POWER_POLL_TIMEOUT_US);
	if (ret == -ETIMEDOUT) {
		dev_err(ctrl->dev, "timed out powering off domain '%s'\n", pd->genpd.name);
		return ret;
	}

	return regmap_clear_bits(ctrl->base, data->reg_clk_res_ctrl, data->hw_mode);
}

static inline int pxa1908_dsi_power_on(struct generic_pm_domain *genpd)
{
	struct pxa1908_pd *pd = to_pxa1908_pd(genpd);
	struct pxa1908_pd_ctrl *ctrl = pd->ctrl;

	return regmap_set_bits(ctrl->base, APMU_DEBUG, DSI_PHY_DVM_MASK);
}

static inline int pxa1908_dsi_power_off(struct generic_pm_domain *genpd)
{
	struct pxa1908_pd *pd = to_pxa1908_pd(genpd);

Annotation

Implementation Notes