|
@@ -1,6 +1,7 @@
|
|
|
/*
|
|
|
* Copyright (C) 2007 Felix Fietkau <nbd@openwrt.org>
|
|
|
* Copyright (C) 2007 Eugene Konev <ejka@openwrt.org>
|
|
|
+ * Copyright (C) 2009 Florian Fainelli <florian@openwrt.org>
|
|
|
*
|
|
|
* This program is free software; you can redistribute it and/or modify
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
@@ -24,6 +25,8 @@
|
|
|
#include <linux/delay.h>
|
|
|
#include <linux/gcd.h>
|
|
|
#include <linux/io.h>
|
|
|
+#include <linux/err.h>
|
|
|
+#include <linux/clk.h>
|
|
|
|
|
|
#include <asm/addrspace.h>
|
|
|
#include <asm/mach-ar7/ar7.h>
|
|
@@ -94,12 +97,16 @@ struct tnetd7200_clocks {
|
|
|
struct tnetd7200_clock usb;
|
|
|
};
|
|
|
|
|
|
-int ar7_cpu_clock = 150000000;
|
|
|
-EXPORT_SYMBOL(ar7_cpu_clock);
|
|
|
-int ar7_bus_clock = 125000000;
|
|
|
-EXPORT_SYMBOL(ar7_bus_clock);
|
|
|
-int ar7_dsp_clock;
|
|
|
-EXPORT_SYMBOL(ar7_dsp_clock);
|
|
|
+static struct clk bus_clk = {
|
|
|
+ .rate = 125000000,
|
|
|
+};
|
|
|
+
|
|
|
+static struct clk cpu_clk = {
|
|
|
+ .rate = 150000000,
|
|
|
+};
|
|
|
+
|
|
|
+static struct clk dsp_clk;
|
|
|
+static struct clk vbus_clk;
|
|
|
|
|
|
static void approximate(int base, int target, int *prediv,
|
|
|
int *postdiv, int *mul)
|
|
@@ -185,7 +192,7 @@ static int tnetd7300_get_clock(u32 shift, struct tnetd7300_clock *clock,
|
|
|
base_clock = AR7_XTAL_CLOCK;
|
|
|
break;
|
|
|
case BOOT_PLL_SOURCE_CPU:
|
|
|
- base_clock = ar7_cpu_clock;
|
|
|
+ base_clock = cpu_clk.rate;
|
|
|
break;
|
|
|
}
|
|
|
|
|
@@ -212,11 +219,11 @@ static void tnetd7300_set_clock(u32 shift, struct tnetd7300_clock *clock,
|
|
|
u32 *bootcr, u32 frequency)
|
|
|
{
|
|
|
int prediv, postdiv, mul;
|
|
|
- int base_clock = ar7_bus_clock;
|
|
|
+ int base_clock = bus_clk.rate;
|
|
|
|
|
|
switch ((*bootcr & (BOOT_PLL_SOURCE_MASK << shift)) >> shift) {
|
|
|
case BOOT_PLL_SOURCE_BUS:
|
|
|
- base_clock = ar7_bus_clock;
|
|
|
+ base_clock = bus_clk.rate;
|
|
|
break;
|
|
|
case BOOT_PLL_SOURCE_REF:
|
|
|
base_clock = AR7_REF_CLOCK;
|
|
@@ -225,7 +232,7 @@ static void tnetd7300_set_clock(u32 shift, struct tnetd7300_clock *clock,
|
|
|
base_clock = AR7_XTAL_CLOCK;
|
|
|
break;
|
|
|
case BOOT_PLL_SOURCE_CPU:
|
|
|
- base_clock = ar7_cpu_clock;
|
|
|
+ base_clock = cpu_clk.rate;
|
|
|
break;
|
|
|
}
|
|
|
|
|
@@ -247,18 +254,18 @@ static void __init tnetd7300_init_clocks(void)
|
|
|
ioremap_nocache(UR8_REGS_CLOCKS,
|
|
|
sizeof(struct tnetd7300_clocks));
|
|
|
|
|
|
- ar7_bus_clock = tnetd7300_get_clock(BUS_PLL_SOURCE_SHIFT,
|
|
|
+ bus_clk.rate = tnetd7300_get_clock(BUS_PLL_SOURCE_SHIFT,
|
|
|
&clocks->bus, bootcr, AR7_AFE_CLOCK);
|
|
|
|
|
|
if (*bootcr & BOOT_PLL_ASYNC_MODE)
|
|
|
- ar7_cpu_clock = tnetd7300_get_clock(CPU_PLL_SOURCE_SHIFT,
|
|
|
+ cpu_clk.rate = tnetd7300_get_clock(CPU_PLL_SOURCE_SHIFT,
|
|
|
&clocks->cpu, bootcr, AR7_AFE_CLOCK);
|
|
|
else
|
|
|
- ar7_cpu_clock = ar7_bus_clock;
|
|
|
+ cpu_clk.rate = bus_clk.rate;
|
|
|
|
|
|
- if (ar7_dsp_clock == 250000000)
|
|
|
+ if (dsp_clk.rate == 250000000)
|
|
|
tnetd7300_set_clock(DSP_PLL_SOURCE_SHIFT, &clocks->dsp,
|
|
|
- bootcr, ar7_dsp_clock);
|
|
|
+ bootcr, dsp_clk.rate);
|
|
|
|
|
|
iounmap(clocks);
|
|
|
iounmap(bootcr);
|
|
@@ -343,20 +350,20 @@ static void __init tnetd7200_init_clocks(void)
|
|
|
printk(KERN_INFO "Clocks: Setting DSP clock\n");
|
|
|
calculate(dsp_base, TNETD7200_DEF_DSP_CLK,
|
|
|
&dsp_prediv, &dsp_postdiv, &dsp_mul);
|
|
|
- ar7_bus_clock =
|
|
|
+ bus_clk.rate =
|
|
|
((dsp_base / dsp_prediv) * dsp_mul) / dsp_postdiv;
|
|
|
tnetd7200_set_clock(dsp_base, &clocks->dsp,
|
|
|
dsp_prediv, dsp_postdiv * 2, dsp_postdiv, dsp_mul * 2,
|
|
|
- ar7_bus_clock);
|
|
|
+ bus_clk.rate);
|
|
|
|
|
|
printk(KERN_INFO "Clocks: Setting CPU clock\n");
|
|
|
calculate(cpu_base, TNETD7200_DEF_CPU_CLK, &cpu_prediv,
|
|
|
&cpu_postdiv, &cpu_mul);
|
|
|
- ar7_cpu_clock =
|
|
|
+ cpu_clk.rate =
|
|
|
((cpu_base / cpu_prediv) * cpu_mul) / cpu_postdiv;
|
|
|
tnetd7200_set_clock(cpu_base, &clocks->cpu,
|
|
|
cpu_prediv, cpu_postdiv, -1, cpu_mul,
|
|
|
- ar7_cpu_clock);
|
|
|
+ cpu_clk.rate);
|
|
|
|
|
|
} else
|
|
|
if (*bootcr & BOOT_PLL_2TO1_MODE) {
|
|
@@ -365,48 +372,90 @@ static void __init tnetd7200_init_clocks(void)
|
|
|
printk(KERN_INFO "Clocks: Setting CPU clock\n");
|
|
|
calculate(cpu_base, TNETD7200_DEF_CPU_CLK, &cpu_prediv,
|
|
|
&cpu_postdiv, &cpu_mul);
|
|
|
- ar7_cpu_clock = ((cpu_base / cpu_prediv) * cpu_mul)
|
|
|
+ cpu_clk.rate = ((cpu_base / cpu_prediv) * cpu_mul)
|
|
|
/ cpu_postdiv;
|
|
|
tnetd7200_set_clock(cpu_base, &clocks->cpu,
|
|
|
cpu_prediv, cpu_postdiv, -1, cpu_mul,
|
|
|
- ar7_cpu_clock);
|
|
|
+ cpu_clk.rate);
|
|
|
|
|
|
printk(KERN_INFO "Clocks: Setting DSP clock\n");
|
|
|
calculate(dsp_base, TNETD7200_DEF_DSP_CLK, &dsp_prediv,
|
|
|
&dsp_postdiv, &dsp_mul);
|
|
|
- ar7_bus_clock = ar7_cpu_clock / 2;
|
|
|
+ bus_clk.rate = cpu_clk.rate / 2;
|
|
|
tnetd7200_set_clock(dsp_base, &clocks->dsp,
|
|
|
dsp_prediv, dsp_postdiv * 2, dsp_postdiv,
|
|
|
- dsp_mul * 2, ar7_bus_clock);
|
|
|
+ dsp_mul * 2, bus_clk.rate);
|
|
|
} else {
|
|
|
printk(KERN_INFO "Clocks: Sync 1:1 mode\n");
|
|
|
|
|
|
printk(KERN_INFO "Clocks: Setting DSP clock\n");
|
|
|
calculate(dsp_base, TNETD7200_DEF_DSP_CLK, &dsp_prediv,
|
|
|
&dsp_postdiv, &dsp_mul);
|
|
|
- ar7_bus_clock = ((dsp_base / dsp_prediv) * dsp_mul)
|
|
|
+ bus_clk.rate = ((dsp_base / dsp_prediv) * dsp_mul)
|
|
|
/ dsp_postdiv;
|
|
|
tnetd7200_set_clock(dsp_base, &clocks->dsp,
|
|
|
dsp_prediv, dsp_postdiv * 2, dsp_postdiv,
|
|
|
- dsp_mul * 2, ar7_bus_clock);
|
|
|
+ dsp_mul * 2, bus_clk.rate);
|
|
|
|
|
|
- ar7_cpu_clock = ar7_bus_clock;
|
|
|
+ cpu_clk.rate = bus_clk.rate;
|
|
|
}
|
|
|
|
|
|
printk(KERN_INFO "Clocks: Setting USB clock\n");
|
|
|
- usb_base = ar7_bus_clock;
|
|
|
+ usb_base = bus_clk.rate;
|
|
|
calculate(usb_base, TNETD7200_DEF_USB_CLK, &usb_prediv,
|
|
|
&usb_postdiv, &usb_mul);
|
|
|
tnetd7200_set_clock(usb_base, &clocks->usb,
|
|
|
usb_prediv, usb_postdiv, -1, usb_mul,
|
|
|
TNETD7200_DEF_USB_CLK);
|
|
|
|
|
|
- ar7_dsp_clock = ar7_cpu_clock;
|
|
|
+ dsp_clk.rate = cpu_clk.rate;
|
|
|
|
|
|
iounmap(clocks);
|
|
|
iounmap(bootcr);
|
|
|
}
|
|
|
|
|
|
+/*
|
|
|
+ * Linux clock API
|
|
|
+ */
|
|
|
+int clk_enable(struct clk *clk)
|
|
|
+{
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+EXPORT_SYMBOL(clk_enable);
|
|
|
+
|
|
|
+void clk_disable(struct clk *clk)
|
|
|
+{
|
|
|
+}
|
|
|
+EXPORT_SYMBOL(clk_disable);
|
|
|
+
|
|
|
+unsigned long clk_get_rate(struct clk *clk)
|
|
|
+{
|
|
|
+ return clk->rate;
|
|
|
+}
|
|
|
+EXPORT_SYMBOL(clk_get_rate);
|
|
|
+
|
|
|
+struct clk *clk_get(struct device *dev, const char *id)
|
|
|
+{
|
|
|
+ if (!strcmp(id, "bus"))
|
|
|
+ return &bus_clk;
|
|
|
+ /* cpmac and vbus share the same rate */
|
|
|
+ if (!strcmp(id, "cpmac"))
|
|
|
+ return &vbus_clk;
|
|
|
+ if (!strcmp(id, "cpu"))
|
|
|
+ return &cpu_clk;
|
|
|
+ if (!strcmp(id, "dsp"));
|
|
|
+ return &dsp_clk;
|
|
|
+ if (!strcmp(id, "vbus"))
|
|
|
+ return &vbus_clk;
|
|
|
+ return ERR_PTR(-ENOENT);
|
|
|
+}
|
|
|
+EXPORT_SYMBOL(clk_get);
|
|
|
+
|
|
|
+void clk_put(struct clk *clk)
|
|
|
+{
|
|
|
+}
|
|
|
+EXPORT_SYMBOL(clk_put);
|
|
|
+
|
|
|
int __init ar7_init_clocks(void)
|
|
|
{
|
|
|
switch (ar7_chip_id()) {
|
|
@@ -415,12 +464,14 @@ int __init ar7_init_clocks(void)
|
|
|
tnetd7200_init_clocks();
|
|
|
break;
|
|
|
case AR7_CHIP_7300:
|
|
|
- ar7_dsp_clock = tnetd7300_dsp_clock();
|
|
|
+ dsp_clk.rate = tnetd7300_dsp_clock();
|
|
|
tnetd7300_init_clocks();
|
|
|
break;
|
|
|
default:
|
|
|
break;
|
|
|
}
|
|
|
+ /* adjust vbus clock rate */
|
|
|
+ vbus_clk.rate = bus_clk.rate / 2;
|
|
|
|
|
|
return 0;
|
|
|
}
|