drivers/pmdomain/imx/imx8m-blk-ctrl.c

Source file repositories/reference/linux-study-clean/drivers/pmdomain/imx/imx8m-blk-ctrl.c

File Facts

System
Linux kernel
Corpus path
drivers/pmdomain/imx/imx8m-blk-ctrl.c
Extension
.c
Size
26154 bytes
Lines
915
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 imx8m_blk_ctrl {
	struct device *dev;
	struct notifier_block power_nb;
	struct device *bus_power_dev;
	struct regmap *regmap;
	struct imx8m_blk_ctrl_domain *domains;
	struct genpd_onecell_data onecell_data;
};

struct imx8m_blk_ctrl_domain_data {
	const char *name;
	const char * const *clk_names;
	const char * const *path_names;
	const char *gpc_name;
	int num_clks;
	int num_paths;
	u32 rst_mask;
	u32 clk_mask;

	/*
	 * i.MX8M Mini, Nano and Plus have a third DISPLAY_BLK_CTRL register
	 * which is used to control the reset for the MIPI Phy.
	 * Since it's only present in certain circumstances,
	 * an if-statement should be used before setting and clearing this
	 * register.
	 */
	u32 mipi_phy_rst_mask;
};

#define DOMAIN_MAX_CLKS 4
#define DOMAIN_MAX_PATHS 4

struct imx8m_blk_ctrl_domain {
	struct generic_pm_domain genpd;
	const struct imx8m_blk_ctrl_domain_data *data;
	struct clk_bulk_data clks[DOMAIN_MAX_CLKS];
	struct icc_bulk_data paths[DOMAIN_MAX_PATHS];
	struct device *power_dev;
	struct imx8m_blk_ctrl *bc;
	int num_paths;
};

struct imx8m_blk_ctrl_data {
	int max_reg;
	notifier_fn_t power_notifier_fn;
	const struct imx8m_blk_ctrl_domain_data *domains;
	int num_domains;
};

static inline struct imx8m_blk_ctrl_domain *
to_imx8m_blk_ctrl_domain(struct generic_pm_domain *genpd)
{
	return container_of(genpd, struct imx8m_blk_ctrl_domain, genpd);
}

static int imx8m_blk_ctrl_power_on(struct generic_pm_domain *genpd)
{
	struct imx8m_blk_ctrl_domain *domain = to_imx8m_blk_ctrl_domain(genpd);
	const struct imx8m_blk_ctrl_domain_data *data = domain->data;
	struct imx8m_blk_ctrl *bc = domain->bc;
	int ret;

	/* make sure bus domain is awake */
	ret = pm_runtime_get_sync(bc->bus_power_dev);
	if (ret < 0) {
		pm_runtime_put_noidle(bc->bus_power_dev);
		dev_err(bc->dev, "failed to power up bus domain\n");
		return ret;
	}

	/* put devices into reset */
	regmap_clear_bits(bc->regmap, BLK_SFT_RSTN, data->rst_mask);
	if (data->mipi_phy_rst_mask)
		regmap_clear_bits(bc->regmap, BLK_MIPI_RESET_DIV, data->mipi_phy_rst_mask);

	/* enable upstream and blk-ctrl clocks to allow reset to propagate */
	ret = clk_bulk_prepare_enable(data->num_clks, domain->clks);
	if (ret) {
		dev_err(bc->dev, "failed to enable clocks\n");
		goto bus_put;
	}
	regmap_set_bits(bc->regmap, BLK_CLK_EN, data->clk_mask);

	/* power up upstream GPC domain */
	ret = pm_runtime_get_sync(domain->power_dev);
	if (ret < 0) {
		dev_err(bc->dev, "failed to power up peripheral domain\n");
		goto clk_disable;
	}

Annotation

Implementation Notes