Merge branches 'sh/serial-rework' and 'sh/oprofile'
[pandora-kernel.git] / arch / avr32 / mach-at32ap / clock.c
index 6c27dda..138a00a 100644 (file)
 #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;
 }