avr32: Replace static clock list with dynamic linked list
This replaces the at32_clock_list array with a linked list. Clocks can now be registered (added) to the list. Signed-off-by: Alex Raimondi <raimondi@miromico.ch> Signed-off-by: Haavard Skinnemoen <haavard.skinnemoen@atmel.com>
This commit is contained in:
parent
787928e747
commit
300bb76251
3 changed files with 58 additions and 24 deletions
|
@ -2028,7 +2028,7 @@ static struct clk gclk4 = {
|
||||||
.index = 4,
|
.index = 4,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct clk *at32_clock_list[] = {
|
static __initdata struct clk *init_clocks[] = {
|
||||||
&osc32k,
|
&osc32k,
|
||||||
&osc0,
|
&osc0,
|
||||||
&osc1,
|
&osc1,
|
||||||
|
@ -2092,7 +2092,6 @@ struct clk *at32_clock_list[] = {
|
||||||
&gclk3,
|
&gclk3,
|
||||||
&gclk4,
|
&gclk4,
|
||||||
};
|
};
|
||||||
unsigned int at32_nr_clocks = ARRAY_SIZE(at32_clock_list);
|
|
||||||
|
|
||||||
void __init setup_platform(void)
|
void __init setup_platform(void)
|
||||||
{
|
{
|
||||||
|
@ -2123,14 +2122,19 @@ void __init setup_platform(void)
|
||||||
genclk_init_parent(&abdac0_sample_clk);
|
genclk_init_parent(&abdac0_sample_clk);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Turn on all clocks that have at least one user already, and
|
* Build initial dynamic clock list by registering all clocks
|
||||||
* turn off everything else. We only do this for module
|
* from the array.
|
||||||
* clocks, and even though it isn't particularly pretty to
|
* At the same time, turn on all clocks that have at least one
|
||||||
* check the address of the mode function, it should do the
|
* user already, and turn off everything else. We only do this
|
||||||
* trick...
|
* for module clocks, and even though it isn't particularly
|
||||||
|
* pretty to check the address of the mode function, it should
|
||||||
|
* do the trick...
|
||||||
*/
|
*/
|
||||||
for (i = 0; i < ARRAY_SIZE(at32_clock_list); i++) {
|
for (i = 0; i < ARRAY_SIZE(init_clocks); i++) {
|
||||||
struct clk *clk = at32_clock_list[i];
|
struct clk *clk = init_clocks[i];
|
||||||
|
|
||||||
|
/* first, register clock */
|
||||||
|
at32_clk_register(clk);
|
||||||
|
|
||||||
if (clk->users == 0)
|
if (clk->users == 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
|
@ -15,24 +15,40 @@
|
||||||
#include <linux/err.h>
|
#include <linux/err.h>
|
||||||
#include <linux/device.h>
|
#include <linux/device.h>
|
||||||
#include <linux/string.h>
|
#include <linux/string.h>
|
||||||
|
#include <linux/list.h>
|
||||||
|
|
||||||
#include <mach/chip.h>
|
#include <mach/chip.h>
|
||||||
|
|
||||||
#include "clock.h"
|
#include "clock.h"
|
||||||
|
|
||||||
|
/* at32 clock list */
|
||||||
|
static LIST_HEAD(at32_clock_list);
|
||||||
|
|
||||||
static DEFINE_SPINLOCK(clk_lock);
|
static DEFINE_SPINLOCK(clk_lock);
|
||||||
|
static DEFINE_SPINLOCK(clk_list_lock);
|
||||||
|
|
||||||
|
void at32_clk_register(struct clk *clk)
|
||||||
|
{
|
||||||
|
spin_lock(&clk_list_lock);
|
||||||
|
/* add the new item to the end of the list */
|
||||||
|
list_add_tail(&clk->list, &at32_clock_list);
|
||||||
|
spin_unlock(&clk_list_lock);
|
||||||
|
}
|
||||||
|
|
||||||
struct clk *clk_get(struct device *dev, const char *id)
|
struct clk *clk_get(struct device *dev, const char *id)
|
||||||
{
|
{
|
||||||
int i;
|
struct clk *clk;
|
||||||
|
|
||||||
for (i = 0; i < at32_nr_clocks; i++) {
|
spin_lock(&clk_list_lock);
|
||||||
struct clk *clk = at32_clock_list[i];
|
|
||||||
|
|
||||||
if (clk->dev == dev && strcmp(id, clk->name) == 0)
|
list_for_each_entry(clk, &at32_clock_list, list) {
|
||||||
|
if (clk->dev == dev && strcmp(id, clk->name) == 0) {
|
||||||
|
spin_unlock(&clk_list_lock);
|
||||||
return clk;
|
return clk;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
spin_unlock(&clk_list_lock);
|
||||||
return ERR_PTR(-ENOENT);
|
return ERR_PTR(-ENOENT);
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(clk_get);
|
EXPORT_SYMBOL(clk_get);
|
||||||
|
@ -203,8 +219,8 @@ dump_clock(struct clk *parent, struct clkinf *r)
|
||||||
|
|
||||||
/* cost of this scan is small, but not linear... */
|
/* cost of this scan is small, but not linear... */
|
||||||
r->nest = nest + NEST_DELTA;
|
r->nest = nest + NEST_DELTA;
|
||||||
for (i = 3; i < at32_nr_clocks; i++) {
|
|
||||||
clk = at32_clock_list[i];
|
list_for_each_entry(clk, &at32_clock_list, list) {
|
||||||
if (clk->parent == parent)
|
if (clk->parent == parent)
|
||||||
dump_clock(clk, r);
|
dump_clock(clk, r);
|
||||||
}
|
}
|
||||||
|
@ -215,6 +231,7 @@ static int clk_show(struct seq_file *s, void *unused)
|
||||||
{
|
{
|
||||||
struct clkinf r;
|
struct clkinf r;
|
||||||
int i;
|
int i;
|
||||||
|
struct clk *clk;
|
||||||
|
|
||||||
/* show all the power manager registers */
|
/* show all the power manager registers */
|
||||||
seq_printf(s, "MCCTRL = %8x\n", pm_readl(MCCTRL));
|
seq_printf(s, "MCCTRL = %8x\n", pm_readl(MCCTRL));
|
||||||
|
@ -234,14 +251,25 @@ static int clk_show(struct seq_file *s, void *unused)
|
||||||
|
|
||||||
seq_printf(s, "\n");
|
seq_printf(s, "\n");
|
||||||
|
|
||||||
/* show clock tree as derived from the three oscillators
|
|
||||||
* we "know" are at the head of the list
|
|
||||||
*/
|
|
||||||
r.s = s;
|
r.s = s;
|
||||||
r.nest = 0;
|
r.nest = 0;
|
||||||
dump_clock(at32_clock_list[0], &r);
|
/* protected from changes on the list while dumping */
|
||||||
dump_clock(at32_clock_list[1], &r);
|
spin_lock(&clk_list_lock);
|
||||||
dump_clock(at32_clock_list[2], &r);
|
|
||||||
|
/* show clock tree as derived from the three oscillators */
|
||||||
|
clk = clk_get(NULL, "osc32k");
|
||||||
|
dump_clock(clk, &r);
|
||||||
|
clk_put(clk);
|
||||||
|
|
||||||
|
clk = clk_get(NULL, "osc0");
|
||||||
|
dump_clock(clk, &r);
|
||||||
|
clk_put(clk);
|
||||||
|
|
||||||
|
clk = clk_get(NULL, "osc1");
|
||||||
|
dump_clock(clk, &r);
|
||||||
|
clk_put(clk);
|
||||||
|
|
||||||
|
spin_unlock(&clk_list_lock);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,8 +12,13 @@
|
||||||
* published by the Free Software Foundation.
|
* published by the Free Software Foundation.
|
||||||
*/
|
*/
|
||||||
#include <linux/clk.h>
|
#include <linux/clk.h>
|
||||||
|
#include <linux/list.h>
|
||||||
|
|
||||||
|
|
||||||
|
void at32_clk_register(struct clk *clk);
|
||||||
|
|
||||||
struct clk {
|
struct clk {
|
||||||
|
struct list_head list; /* linking element */
|
||||||
const char *name; /* Clock name/function */
|
const char *name; /* Clock name/function */
|
||||||
struct device *dev; /* Device the clock is used by */
|
struct device *dev; /* Device the clock is used by */
|
||||||
struct clk *parent; /* Parent clock, if any */
|
struct clk *parent; /* Parent clock, if any */
|
||||||
|
@ -25,6 +30,3 @@ struct clk {
|
||||||
u16 users; /* Enabled if non-zero */
|
u16 users; /* Enabled if non-zero */
|
||||||
u16 index; /* Sibling index */
|
u16 index; /* Sibling index */
|
||||||
};
|
};
|
||||||
|
|
||||||
extern struct clk *at32_clock_list[];
|
|
||||||
extern unsigned int at32_nr_clocks;
|
|
||||||
|
|
Loading…
Reference in a new issue