drivers/clk/hisilicon/clk-hix5hd2.c

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

File Facts

System
Linux kernel
Corpus path
drivers/clk/hisilicon/clk-hix5hd2.c
Extension
.c
Size
10075 bytes
Lines
320
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 hix5hd2_complex_clock {
	const char	*name;
	const char	*parent_name;
	u32		id;
	u32		ctrl_reg;
	u32		ctrl_clk_mask;
	u32		ctrl_rst_mask;
	u32		phy_reg;
	u32		phy_clk_mask;
	u32		phy_rst_mask;
	enum hix5hd2_clk_type type;
};

struct hix5hd2_clk_complex {
	struct clk_hw	hw;
	u32		id;
	void __iomem	*ctrl_reg;
	u32		ctrl_clk_mask;
	u32		ctrl_rst_mask;
	void __iomem	*phy_reg;
	u32		phy_clk_mask;
	u32		phy_rst_mask;
};

static struct hix5hd2_complex_clock hix5hd2_complex_clks[] __initdata = {
	{"clk_mac0", "clk_fephy", HIX5HD2_MAC0_CLK,
		0xcc, 0xa, 0x500, 0x120, 0, 0x10, TYPE_ETHER},
	{"clk_mac1", "clk_fwd_sys", HIX5HD2_MAC1_CLK,
		0xcc, 0x14, 0xa00, 0x168, 0x2, 0, TYPE_ETHER},
	{"clk_sata", NULL, HIX5HD2_SATA_CLK,
		0xa8, 0x1f, 0x300, 0xac, 0x1, 0x0, TYPE_COMPLEX},
	{"clk_usb", NULL, HIX5HD2_USB_CLK,
		0xb8, 0xff, 0x3f000, 0xbc, 0x7, 0x3f00, TYPE_COMPLEX},
};

#define to_complex_clk(_hw) container_of(_hw, struct hix5hd2_clk_complex, hw)

static int clk_ether_prepare(struct clk_hw *hw)
{
	struct hix5hd2_clk_complex *clk = to_complex_clk(hw);
	u32 val;

	val = readl_relaxed(clk->ctrl_reg);
	val |= clk->ctrl_clk_mask | clk->ctrl_rst_mask;
	writel_relaxed(val, clk->ctrl_reg);
	val &= ~(clk->ctrl_rst_mask);
	writel_relaxed(val, clk->ctrl_reg);

	val = readl_relaxed(clk->phy_reg);
	val |= clk->phy_clk_mask;
	val &= ~(clk->phy_rst_mask);
	writel_relaxed(val, clk->phy_reg);
	mdelay(10);

	val &= ~(clk->phy_clk_mask);
	val |= clk->phy_rst_mask;
	writel_relaxed(val, clk->phy_reg);
	mdelay(10);

	val |= clk->phy_clk_mask;
	val &= ~(clk->phy_rst_mask);
	writel_relaxed(val, clk->phy_reg);
	mdelay(30);
	return 0;
}

static void clk_ether_unprepare(struct clk_hw *hw)
{
	struct hix5hd2_clk_complex *clk = to_complex_clk(hw);
	u32 val;

	val = readl_relaxed(clk->ctrl_reg);
	val &= ~(clk->ctrl_clk_mask);
	writel_relaxed(val, clk->ctrl_reg);
}

static const struct clk_ops clk_ether_ops = {
	.prepare = clk_ether_prepare,
	.unprepare = clk_ether_unprepare,
};

static int clk_complex_enable(struct clk_hw *hw)
{
	struct hix5hd2_clk_complex *clk = to_complex_clk(hw);
	u32 val;

	val = readl_relaxed(clk->ctrl_reg);
	val |= clk->ctrl_clk_mask;
	val &= ~(clk->ctrl_rst_mask);
	writel_relaxed(val, clk->ctrl_reg);

Annotation

Implementation Notes