drivers/pmdomain/mediatek/mtk-mfg-pmdomain.c

Source file repositories/reference/linux-study-clean/drivers/pmdomain/mediatek/mtk-mfg-pmdomain.c

File Facts

System
Linux kernel
Corpus path
drivers/pmdomain/mediatek/mtk-mfg-pmdomain.c
Extension
.c
Size
30076 bytes
Lines
1104
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 mtk_mfg_opp_entry {
	__le32 freq_khz;
	__le32 voltage_core;
	__le32 voltage_sram;
	__le32 posdiv;
	__le32 voltage_margin;
	__le32 power_mw;
} __packed;

struct mtk_mfg_mbox {
	struct mbox_client cl;
	struct completion rx_done;
	struct mtk_mfg *mfg;
	struct mbox_chan *ch;
	void *rx_data;
};

struct mtk_mfg {
	struct generic_pm_domain pd;
	struct platform_device *pdev;
	struct clk *clk_eb;
	struct clk_bulk_data *gpu_clks;
	struct clk_hw clk_core_hw;
	struct clk_hw clk_stack_hw;
	struct regulator_bulk_data *gpu_regs;
	void __iomem *rpc;
	void __iomem *gpr;
	void __iomem *shared_mem;
	phys_addr_t shared_mem_phys;
	unsigned int shared_mem_size;
	u16 ghpm_en_reg;
	u32 ipi_magic;
	unsigned short num_gpu_opps;
	unsigned short num_stack_opps;
	struct dev_pm_opp_data *gpu_opps;
	struct dev_pm_opp_data *stack_opps;
	struct mtk_mfg_mbox *gf_mbox;
	struct mtk_mfg_mbox *slp_mbox;
	const struct mtk_mfg_variant *variant;
};

struct mtk_mfg_variant {
	const char *const *clk_names;
	unsigned int num_clks;
	const char *const *regulator_names;
	unsigned int num_regulators;
	/** @turbo_below: opp indices below this value are considered turbo */
	unsigned int turbo_below;
	int (*init)(struct mtk_mfg *mfg);
};

static inline struct mtk_mfg *mtk_mfg_from_genpd(struct generic_pm_domain *pd)
{
	return container_of(pd, struct mtk_mfg, pd);
}

static inline void mtk_mfg_update_reg_bits(void __iomem *addr, u32 mask, u32 val)
{
	writel((readl(addr) & ~mask) | (val & mask), addr);
}

static inline bool mtk_mfg_is_powered_on(struct mtk_mfg *mfg)
{
	return (readl(mfg->rpc + RPC_PWR_CON) & PWR_ACK_M) == PWR_ACK_M;
}

static unsigned long mtk_mfg_recalc_rate_gpu(struct clk_hw *hw,
					     unsigned long parent_rate)
{
	struct mtk_mfg *mfg = container_of(hw, struct mtk_mfg, clk_core_hw);

	return readl(mfg->shared_mem + GF_REG_FREQ_OUT_GPU) * HZ_PER_KHZ;
}

static int mtk_mfg_determine_rate(struct clk_hw *hw,
				  struct clk_rate_request *req)
{
	/*
	 * The determine_rate callback needs to be implemented to avoid returning
	 * the current clock frequency, rather than something even remotely
	 * close to the frequency that was asked for.
	 *
	 * Instead of writing considerable amounts of possibly slow code just to
	 * somehow figure out which of the three PLLs to round for, or even to
	 * do a search through one of two OPP tables in order to find the closest
	 * OPP of a frequency, just return the rate as-is. This avoids devfreq
	 * "rounding" a request for the lowest frequency to the possibly very
	 * high current frequency, breaking the powersave governor in the process.
	 */

Annotation

Implementation Notes