arch/mips/alchemy/common/clock.c

Source file repositories/reference/linux-study-clean/arch/mips/alchemy/common/clock.c

File Facts

System
Linux kernel
Corpus path
arch/mips/alchemy/common/clock.c
Extension
.c
Size
27535 bytes
Lines
1121
Domain
Architecture Layer
Bucket
arch/mips
Inferred role
Architecture Layer: exported/initcall integration point
Status
integration implementation candidate

Why This File Exists

CPU and platform-specific kernel glue: boot entry, traps, syscall entry, interrupts, page tables, context switch, and low-level barriers.

Dependency Surface

Detected Declarations

Annotated Snippet

struct alchemy_auxpll_clk {
	struct clk_hw hw;
	unsigned long reg;	/* au1300 has also AUXPLL2 */
	int maxmult;		/* max multiplier */
};
#define to_auxpll_clk(x) container_of(x, struct alchemy_auxpll_clk, hw)

static unsigned long alchemy_clk_aux_recalc(struct clk_hw *hw,
					    unsigned long parent_rate)
{
	struct alchemy_auxpll_clk *a = to_auxpll_clk(hw);

	return (alchemy_rdsys(a->reg) & 0xff) * parent_rate;
}

static int alchemy_clk_aux_setr(struct clk_hw *hw,
				unsigned long rate,
				unsigned long parent_rate)
{
	struct alchemy_auxpll_clk *a = to_auxpll_clk(hw);
	unsigned long d = rate;

	if (rate)
		d /= parent_rate;
	else
		d = 0;

	/* minimum is 84MHz, max is 756-1032 depending on variant */
	if (((d < 7) && (d != 0)) || (d > a->maxmult))
		return -EINVAL;

	alchemy_wrsys(d, a->reg);
	return 0;
}

static int alchemy_clk_aux_determine_rate(struct clk_hw *hw,
					  struct clk_rate_request *req)
{
	struct alchemy_auxpll_clk *a = to_auxpll_clk(hw);
	unsigned long mult;

	if (!req->rate || !req->best_parent_rate) {
		req->rate = 0;

		return 0;
	}

	mult = req->rate / req->best_parent_rate;

	if (mult && (mult < 7))
		mult = 7;
	if (mult > a->maxmult)
		mult = a->maxmult;

	req->rate = req->best_parent_rate * mult;

	return 0;
}

static const struct clk_ops alchemy_clkops_aux = {
	.recalc_rate	= alchemy_clk_aux_recalc,
	.set_rate	= alchemy_clk_aux_setr,
	.determine_rate = alchemy_clk_aux_determine_rate,
};

static struct clk __init *alchemy_clk_setup_aux(const char *parent_name,
						char *name, int maxmult,
						unsigned long reg)
{
	struct clk_init_data id;
	struct clk *c;
	struct alchemy_auxpll_clk *a;

	a = kzalloc_obj(*a);
	if (!a)
		return ERR_PTR(-ENOMEM);

	id.name = name;
	id.parent_names = &parent_name;
	id.num_parents = 1;
	id.flags = CLK_GET_RATE_NOCACHE;
	id.ops = &alchemy_clkops_aux;

	a->reg = reg;
	a->maxmult = maxmult;
	a->hw.init = &id;

	c = clk_register(NULL, &a->hw);
	if (!IS_ERR(c))
		clk_register_clkdev(c, name, NULL);

Annotation

Implementation Notes