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