drivers/clk/hisilicon/clk-hi3620.c

Source file repositories/reference/linux-study-clean/drivers/clk/hisilicon/clk-hi3620.c

File Facts

System
Linux kernel
Corpus path
drivers/clk/hisilicon/clk-hi3620.c
Extension
.c
Size
22344 bytes
Lines
485
Domain
Driver Families
Bucket
drivers/clk
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 hisi_mmc_clock {
	unsigned int		id;
	const char		*name;
	const char		*parent_name;
	unsigned long		flags;
	u32			clken_reg;
	u32			clken_bit;
	u32			div_reg;
	u32			div_off;
	u32			div_bits;
	u32			drv_reg;
	u32			drv_off;
	u32			drv_bits;
	u32			sam_reg;
	u32			sam_off;
	u32			sam_bits;
};

struct clk_mmc {
	struct clk_hw	hw;
	u32		id;
	void __iomem	*clken_reg;
	u32		clken_bit;
	void __iomem	*div_reg;
	u32		div_off;
	u32		div_bits;
	void __iomem	*drv_reg;
	u32		drv_off;
	u32		drv_bits;
	void __iomem	*sam_reg;
	u32		sam_off;
	u32		sam_bits;
};

#define to_mmc(_hw) container_of(_hw, struct clk_mmc, hw)

static struct hisi_mmc_clock hi3620_mmc_clks[] __initdata = {
	{ HI3620_SD_CIUCLK,	"sd_bclk1", "sd_clk", CLK_SET_RATE_PARENT, 0x1f8, 0, 0x1f8, 1, 3, 0x1f8, 4, 4, 0x1f8, 8, 4},
	{ HI3620_MMC_CIUCLK1,   "mmc_bclk1", "mmc_clk1", CLK_SET_RATE_PARENT, 0x1f8, 12, 0x1f8, 13, 3, 0x1f8, 16, 4, 0x1f8, 20, 4},
	{ HI3620_MMC_CIUCLK2,   "mmc_bclk2", "mmc_clk2", CLK_SET_RATE_PARENT, 0x1f8, 24, 0x1f8, 25, 3, 0x1f8, 28, 4, 0x1fc, 0, 4},
	{ HI3620_MMC_CIUCLK3,   "mmc_bclk3", "mmc_clk3", CLK_SET_RATE_PARENT, 0x1fc, 4, 0x1fc, 5, 3, 0x1fc, 8, 4, 0x1fc, 12, 4},
};

static unsigned long mmc_clk_recalc_rate(struct clk_hw *hw,
		       unsigned long parent_rate)
{
	switch (parent_rate) {
	case 26000000:
		return 13000000;
	case 180000000:
		return 25000000;
	case 360000000:
		return 50000000;
	case 720000000:
		return 100000000;
	case 1440000000:
		return 180000000;
	default:
		return parent_rate;
	}
}

static int mmc_clk_determine_rate(struct clk_hw *hw,
				  struct clk_rate_request *req)
{
	struct clk_mmc *mclk = to_mmc(hw);

	if ((req->rate <= 13000000) && (mclk->id == HI3620_MMC_CIUCLK1)) {
		req->rate = 13000000;
		req->best_parent_rate = 26000000;
	} else if (req->rate <= 26000000) {
		req->rate = 25000000;
		req->best_parent_rate = 180000000;
	} else if (req->rate <= 52000000) {
		req->rate = 50000000;
		req->best_parent_rate = 360000000;
	} else if (req->rate <= 100000000) {
		req->rate = 100000000;
		req->best_parent_rate = 720000000;
	} else {
		/* max is 180M */
		req->rate = 180000000;
		req->best_parent_rate = 1440000000;
	}
	return -EINVAL;
}

static u32 mmc_clk_delay(u32 val, u32 para, u32 off, u32 len)
{
	u32 i;

Annotation

Implementation Notes