drivers/clk/x86/clk-cgu.c

Source file repositories/reference/linux-study-clean/drivers/clk/x86/clk-cgu.c

File Facts

System
Linux kernel
Corpus path
drivers/clk/x86/clk-cgu.c
Extension
.c
Size
14221 bytes
Lines
586
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

switch (list->type) {
		case CLK_TYPE_FIXED:
			hw = lgm_clk_register_fixed(ctx, list);
			break;
		case CLK_TYPE_MUX:
			hw = lgm_clk_register_mux(ctx, list);
			break;
		case CLK_TYPE_DIVIDER:
			hw = lgm_clk_register_divider(ctx, list);
			break;
		case CLK_TYPE_FIXED_FACTOR:
			hw = lgm_clk_register_fixed_factor(ctx, list);
			break;
		case CLK_TYPE_GATE:
			if (list->gate_flags & GATE_CLK_HW) {
				hw = lgm_clk_register_gate(ctx, list);
			} else {
				/*
				 * GATE_CLKs can be controlled either from
				 * CGU clk driver i.e. this driver or directly
				 * from power management driver/daemon. It is
				 * dependent on the power policy/profile requirements
				 * of the end product. To override control of gate
				 * clks from this driver, provide NULL for this index
				 * of gate clk provider.
				 */
				hw = NULL;
			}
			break;

		default:
			dev_err(ctx->dev, "invalid clk type\n");
			return -EINVAL;
		}

		if (IS_ERR(hw)) {
			dev_err(ctx->dev,
				"register clk: %s, type: %u failed!\n",
				list->name, list->type);
			return -EIO;
		}
		ctx->clk_data.hws[list->id] = hw;
	}

	return 0;
}

static unsigned long
lgm_clk_ddiv_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
{
	struct lgm_clk_ddiv *ddiv = to_lgm_clk_ddiv(hw);
	unsigned int div0, div1, exdiv;
	u64 prate;

	div0 = lgm_get_clk_val(ddiv->membase, ddiv->reg,
			       ddiv->shift0, ddiv->width0) + 1;
	div1 = lgm_get_clk_val(ddiv->membase, ddiv->reg,
			       ddiv->shift1, ddiv->width1) + 1;
	exdiv = lgm_get_clk_val(ddiv->membase, ddiv->reg,
				ddiv->shift2, ddiv->width2);
	prate = (u64)parent_rate;
	do_div(prate, div0);
	do_div(prate, div1);

	if (exdiv) {
		do_div(prate, ddiv->div);
		prate *= ddiv->mult;
	}

	return prate;
}

static int lgm_clk_ddiv_enable(struct clk_hw *hw)
{
	struct lgm_clk_ddiv *ddiv = to_lgm_clk_ddiv(hw);

	lgm_set_clk_val(ddiv->membase, ddiv->reg, ddiv->shift_gate,
			ddiv->width_gate, 1);
	return 0;
}

static void lgm_clk_ddiv_disable(struct clk_hw *hw)
{
	struct lgm_clk_ddiv *ddiv = to_lgm_clk_ddiv(hw);

	lgm_set_clk_val(ddiv->membase, ddiv->reg, ddiv->shift_gate,
			ddiv->width_gate, 0);
}

static int

Annotation

Implementation Notes