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
|
@ -2028,7 +2028,7 @@ static struct clk gclk4 = {
|
|||
.index = 4,
|
||||
};
|
||||
|
||||
struct clk *at32_clock_list[] = {
|
||||
static __initdata struct clk *init_clocks[] = {
|
||||
&osc32k,
|
||||
&osc0,
|
||||
&osc1,
|
||||
|
@ -2092,7 +2092,6 @@ struct clk *at32_clock_list[] = {
|
|||
&gclk3,
|
||||
&gclk4,
|
||||
};
|
||||
unsigned int at32_nr_clocks = ARRAY_SIZE(at32_clock_list);
|
||||
|
||||
void __init setup_platform(void)
|
||||
{
|
||||
|
@ -2123,14 +2122,19 @@ void __init setup_platform(void)
|
|||
genclk_init_parent(&abdac0_sample_clk);
|
||||
|
||||
/*
|
||||
* Turn on all clocks that have at least one user already, and
|
||||
* turn off everything else. We only do this for module
|
||||
* clocks, and even though it isn't particularly pretty to
|
||||
* check the address of the mode function, it should do the
|
||||
* trick...
|
||||
* Build initial dynamic clock list by registering all clocks
|
||||
* from the array.
|
||||
* At the same time, turn on all clocks that have at least one
|
||||
* user already, and turn off everything else. We only do this
|
||||
* 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++) {
|
||||
struct clk *clk = at32_clock_list[i];
|
||||
for (i = 0; i < ARRAY_SIZE(init_clocks); i++) {
|
||||
struct clk *clk = init_clocks[i];
|
||||
|
||||
/* first, register clock */
|
||||
at32_clk_register(clk);
|
||||
|
||||
if (clk->users == 0)
|
||||
continue;
|
||||
|
|
|
@ -15,24 +15,40 @@
|
|||
#include <linux/err.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/list.h>
|
||||
|
||||
#include <mach/chip.h>
|
||||
|
||||
#include "clock.h"
|
||||
|
||||
/* at32 clock list */
|
||||
static LIST_HEAD(at32_clock_list);
|
||||
|
||||
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)
|
||||
{
|
||||
int i;
|
||||
struct clk *clk;
|
||||
|
||||
for (i = 0; i < at32_nr_clocks; i++) {
|
||||
struct clk *clk = at32_clock_list[i];
|
||||
spin_lock(&clk_list_lock);
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
spin_unlock(&clk_list_lock);
|
||||
return ERR_PTR(-ENOENT);
|
||||
}
|
||||
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... */
|
||||
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)
|
||||
dump_clock(clk, r);
|
||||
}
|
||||
|
@ -215,6 +231,7 @@ static int clk_show(struct seq_file *s, void *unused)
|
|||
{
|
||||
struct clkinf r;
|
||||
int i;
|
||||
struct clk *clk;
|
||||
|
||||
/* show all the power manager registers */
|
||||
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");
|
||||
|
||||
/* show clock tree as derived from the three oscillators
|
||||
* we "know" are at the head of the list
|
||||
*/
|
||||
r.s = s;
|
||||
r.nest = 0;
|
||||
dump_clock(at32_clock_list[0], &r);
|
||||
dump_clock(at32_clock_list[1], &r);
|
||||
dump_clock(at32_clock_list[2], &r);
|
||||
/* protected from changes on the list while dumping */
|
||||
spin_lock(&clk_list_lock);
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
|
|
@ -12,8 +12,13 @@
|
|||
* published by the Free Software Foundation.
|
||||
*/
|
||||
#include <linux/clk.h>
|
||||
#include <linux/list.h>
|
||||
|
||||
|
||||
void at32_clk_register(struct clk *clk);
|
||||
|
||||
struct clk {
|
||||
struct list_head list; /* linking element */
|
||||
const char *name; /* Clock name/function */
|
||||
struct device *dev; /* Device the clock is used by */
|
||||
struct clk *parent; /* Parent clock, if any */
|
||||
|
@ -25,6 +30,3 @@ struct clk {
|
|||
u16 users; /* Enabled if non-zero */
|
||||
u16 index; /* Sibling index */
|
||||
};
|
||||
|
||||
extern struct clk *at32_clock_list[];
|
||||
extern unsigned int at32_nr_clocks;
|
||||
|
|
Loading…
Reference in a new issue