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:
Alex Raimondi 2008-09-22 21:40:55 +02:00 committed by Haavard Skinnemoen
parent 787928e747
commit 300bb76251
3 changed files with 58 additions and 24 deletions

View file

@ -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;

View file

@ -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;
}

View file

@ -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;