Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 7a5fe238 authored by Haavard Skinnemoen's avatar Haavard Skinnemoen
Browse files

[AVR32] Make sure all genclocks have a parent



Initialize the parent field of each generic clock by looking at the
PM registers. This means that the genclock operations can always
assume that the parent field is non-null, so they don't have to
check. Also remove a few unnecessary BUG_ON()s.

Extracted from a patch by David Brownell.

Signed-off-by: default avatarHaavard Skinnemoen <hskinnemoen@atmel.com>
parent 160f3453
Loading
Loading
Loading
Loading
+73 −16
Original line number Original line Diff line number Diff line
@@ -310,8 +310,6 @@ static void genclk_mode(struct clk *clk, int enabled)
{
{
	u32 control;
	u32 control;


	BUG_ON(clk->index > 7);

	control = sm_readl(&system_manager, PM_GCCTRL + 4 * clk->index);
	control = sm_readl(&system_manager, PM_GCCTRL + 4 * clk->index);
	if (enabled)
	if (enabled)
		control |= SM_BIT(CEN);
		control |= SM_BIT(CEN);
@@ -325,11 +323,6 @@ static unsigned long genclk_get_rate(struct clk *clk)
	u32 control;
	u32 control;
	unsigned long div = 1;
	unsigned long div = 1;


	BUG_ON(clk->index > 7);

	if (!clk->parent)
		return 0;

	control = sm_readl(&system_manager, PM_GCCTRL + 4 * clk->index);
	control = sm_readl(&system_manager, PM_GCCTRL + 4 * clk->index);
	if (control & SM_BIT(DIVEN))
	if (control & SM_BIT(DIVEN))
		div = 2 * (SM_BFEXT(DIV, control) + 1);
		div = 2 * (SM_BFEXT(DIV, control) + 1);
@@ -342,11 +335,6 @@ static long genclk_set_rate(struct clk *clk, unsigned long rate, int apply)
	u32 control;
	u32 control;
	unsigned long parent_rate, actual_rate, div;
	unsigned long parent_rate, actual_rate, div;


	BUG_ON(clk->index > 7);

	if (!clk->parent)
		return 0;

	parent_rate = clk->parent->get_rate(clk->parent);
	parent_rate = clk->parent->get_rate(clk->parent);
	control = sm_readl(&system_manager, PM_GCCTRL + 4 * clk->index);
	control = sm_readl(&system_manager, PM_GCCTRL + 4 * clk->index);


@@ -373,11 +361,8 @@ int genclk_set_parent(struct clk *clk, struct clk *parent)
{
{
	u32 control;
	u32 control;


	BUG_ON(clk->index > 7);

	printk("clk %s: new parent %s (was %s)\n",
	printk("clk %s: new parent %s (was %s)\n",
	       clk->name, parent->name,
	       clk->name, parent->name, clk->parent->name);
	       clk->parent ? clk->parent->name : "(null)");


	control = sm_readl(&system_manager, PM_GCCTRL + 4 * clk->index);
	control = sm_readl(&system_manager, PM_GCCTRL + 4 * clk->index);


@@ -399,6 +384,22 @@ int genclk_set_parent(struct clk *clk, struct clk *parent)
	return 0;
	return 0;
}
}


static void __init genclk_init_parent(struct clk *clk)
{
	u32 control;
	struct clk *parent;

	BUG_ON(clk->index > 7);

	control = sm_readl(&system_manager, PM_GCCTRL + 4 * clk->index);
	if (control & SM_BIT(OSCSEL))
		parent = (control & SM_BIT(PLLSEL)) ? &pll1 : &osc1;
	else
		parent = (control & SM_BIT(PLLSEL)) ? &pll0 : &osc0;

	clk->parent = parent;
}

/* --------------------------------------------------------------------
/* --------------------------------------------------------------------
 *  System peripherals
 *  System peripherals
 * -------------------------------------------------------------------- */
 * -------------------------------------------------------------------- */
@@ -872,6 +873,50 @@ at32_add_device_lcdc(unsigned int id, struct lcdc_platform_data *data)
	return pdev;
	return pdev;
}
}


/* --------------------------------------------------------------------
 *  GCLK
 * -------------------------------------------------------------------- */
static struct clk gclk0 = {
	.name		= "gclk0",
	.mode		= genclk_mode,
	.get_rate	= genclk_get_rate,
	.set_rate	= genclk_set_rate,
	.set_parent	= genclk_set_parent,
	.index		= 0,
};
static struct clk gclk1 = {
	.name		= "gclk1",
	.mode		= genclk_mode,
	.get_rate	= genclk_get_rate,
	.set_rate	= genclk_set_rate,
	.set_parent	= genclk_set_parent,
	.index		= 1,
};
static struct clk gclk2 = {
	.name		= "gclk2",
	.mode		= genclk_mode,
	.get_rate	= genclk_get_rate,
	.set_rate	= genclk_set_rate,
	.set_parent	= genclk_set_parent,
	.index		= 2,
};
static struct clk gclk3 = {
	.name		= "gclk3",
	.mode		= genclk_mode,
	.get_rate	= genclk_get_rate,
	.set_rate	= genclk_set_rate,
	.set_parent	= genclk_set_parent,
	.index		= 3,
};
static struct clk gclk4 = {
	.name		= "gclk4",
	.mode		= genclk_mode,
	.get_rate	= genclk_get_rate,
	.set_rate	= genclk_set_rate,
	.set_parent	= genclk_set_parent,
	.index		= 4,
};

struct clk *at32_clock_list[] = {
struct clk *at32_clock_list[] = {
	&osc32k,
	&osc32k,
	&osc0,
	&osc0,
@@ -908,6 +953,11 @@ struct clk *at32_clock_list[] = {
	&atmel_spi1_spi_clk,
	&atmel_spi1_spi_clk,
	&lcdc0_hclk,
	&lcdc0_hclk,
	&lcdc0_pixclk,
	&lcdc0_pixclk,
	&gclk0,
	&gclk1,
	&gclk2,
	&gclk3,
	&gclk4,
};
};
unsigned int at32_nr_clocks = ARRAY_SIZE(at32_clock_list);
unsigned int at32_nr_clocks = ARRAY_SIZE(at32_clock_list);


@@ -936,6 +986,13 @@ void __init at32_clock_init(void)
	if (sm_readl(sm, PM_PLL1) & SM_BIT(PLLOSC))
	if (sm_readl(sm, PM_PLL1) & SM_BIT(PLLOSC))
		pll1.parent = &osc1;
		pll1.parent = &osc1;


	genclk_init_parent(&gclk0);
	genclk_init_parent(&gclk1);
	genclk_init_parent(&gclk2);
	genclk_init_parent(&gclk3);
	genclk_init_parent(&gclk4);
	genclk_init_parent(&lcdc0_pixclk);

	/*
	/*
	 * Turn on all clocks that have at least one user already, and
	 * Turn on all clocks that have at least one user already, and
	 * turn off everything else. We only do this for module
	 * turn off everything else. We only do this for module