diff options
Diffstat (limited to 'arch/avr32/mach-at32ap/clock.c')
| -rw-r--r-- | arch/avr32/mach-at32ap/clock.c | 69 |
1 files changed, 54 insertions, 15 deletions
diff --git a/arch/avr32/mach-at32ap/clock.c b/arch/avr32/mach-at32ap/clock.c index 4642117cc9a..23b1a97fae7 100644 --- a/arch/avr32/mach-at32ap/clock.c +++ b/arch/avr32/mach-at32ap/clock.c @@ -13,26 +13,53 @@ */ #include <linux/clk.h> #include <linux/err.h> +#include <linux/export.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); -struct clk *clk_get(struct device *dev, const char *id) +void at32_clk_register(struct clk *clk) { - int i; + 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); +} - for (i = 0; i < at32_nr_clocks; i++) { - struct clk *clk = at32_clock_list[i]; +static struct clk *__clk_get(struct device *dev, const char *id) +{ + struct clk *clk; - 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) { return clk; + } } return ERR_PTR(-ENOENT); } + +struct clk *clk_get(struct device *dev, const char *id) +{ + struct clk *clk; + + spin_lock(&clk_list_lock); + clk = __clk_get(dev, id); + spin_unlock(&clk_list_lock); + + return clk; +} + EXPORT_SYMBOL(clk_get); void clk_put(struct clk *clk) @@ -180,7 +207,7 @@ dump_clock(struct clk *parent, struct clkinf *r) unsigned i; /* skip clocks coupled to devices that aren't registered */ - if (parent->dev && !parent->dev->bus_id[0] && !parent->users) + if (parent->dev && !dev_name(parent->dev) && !parent->users) return; /* <nest spaces> name <pad to end> */ @@ -196,13 +223,13 @@ dump_clock(struct clk *parent, struct clkinf *r) parent->users ? "on" : "off", /* NOTE: not-paranoid!! */ clk_get_rate(parent)); if (parent->dev) - seq_printf(r->s, ", for %s", parent->dev->bus_id); + seq_printf(r->s, ", for %s", dev_name(parent->dev)); seq_printf(r->s, "\n"); /* 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); } @@ -213,6 +240,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)); @@ -232,14 +260,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; } |
