Created
April 16, 2013 03:35
-
-
Save RobertCNelson/5393160 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/arch/arm/mach-omap2/cclock3xxx_data.c b/arch/arm/mach-omap2/cclock3xxx_data.c | |
index 4579c3c..d837d9f 100644 | |
--- a/arch/arm/mach-omap2/cclock3xxx_data.c | |
+++ b/arch/arm/mach-omap2/cclock3xxx_data.c | |
@@ -250,7 +250,9 @@ static struct dpll_data dpll1_dd = { | |
static struct clk dpll1_ck; | |
-static const struct clk_ops dpll1_ck_ops = { | |
+static struct clk_ops dpll1_ck_ops; | |
+ | |
+static struct clk_ops dpll1_ck_ops_omap34xx __initdata = { | |
.init = &omap2_init_clk_clkdm, | |
.enable = &omap3_noncore_dpll_enable, | |
.disable = &omap3_noncore_dpll_disable, | |
@@ -260,6 +262,16 @@ static const struct clk_ops dpll1_ck_ops = { | |
.round_rate = &omap2_dpll_round_rate, | |
}; | |
+static struct clk_ops dpll5_ck_ops_omap3630 __initdata = { | |
+ .init = &omap2_init_clk_clkdm, | |
+ .enable = &omap3_noncore_dpll_enable, | |
+ .disable = &omap3_noncore_dpll_disable, | |
+ .get_parent = &omap2_init_dpll_parent, | |
+ .recalc_rate = &omap3_dpll_recalc, | |
+ .set_rate = &omap3_noncore_dpll_set_rate, | |
+ .round_rate = &omap2_dpll5_round_rate, | |
+}; | |
+ | |
static struct clk_hw_omap dpll1_ck_hw = { | |
.hw = { | |
.clk = &dpll1_ck, | |
@@ -3571,6 +3583,12 @@ int __init omap3xxx_clk_init(void) | |
else | |
dpll4_dd = dpll4_dd_34xx; | |
+ if (cpu_is_omap3630()) | |
+ dpll1_ck_ops = dpll5_ck_ops_omap3630; | |
+ else | |
+ dpll1_ck_ops = dpll1_ck_ops_omap34xx; | |
+ | |
+ | |
for (c = omap3xxx_clks; c < omap3xxx_clks + ARRAY_SIZE(omap3xxx_clks); | |
c++) | |
if (c->cpu & cpu_clkflg) { | |
diff --git a/arch/arm/mach-omap2/clkt_dpll.c b/arch/arm/mach-omap2/clkt_dpll.c | |
index 924c230..b40642f 100644 | |
--- a/arch/arm/mach-omap2/clkt_dpll.c | |
+++ b/arch/arm/mach-omap2/clkt_dpll.c | |
@@ -63,6 +63,15 @@ | |
#define DPLL_FINT_UNDERFLOW -1 | |
#define DPLL_FINT_INVALID -2 | |
+/* copied from clock3xxx.c */ | |
+/* | |
+ * DPLL5_FREQ_FOR_USBHOST: USBHOST and USBTLL are the only clocks | |
+ * that are sourced by DPLL5, and both of these require this clock | |
+ * to be at 120 MHz for proper operation. | |
+ */ | |
+#define DPLL5_FREQ_FOR_USBHOST 120000000 | |
+ | |
+ | |
/* Private functions */ | |
/* | |
@@ -362,3 +371,63 @@ long omap2_dpll_round_rate(struct clk_hw *hw, unsigned long target_rate, | |
return target_rate; | |
} | |
+struct sprz319e_2_1_values { | |
+ unsigned long sys_clk_rate; | |
+ int m, n, div120m; | |
+}; | |
+ | |
+/** | |
+ * omap2_dpll5_round_rate - round a target rate for OMAP DPLL5 | |
+ * according to DM37xx sprz319e 2.1 erratum | |
+ * | |
+ * @clk: struct clk * for a DPLL (presumably DPLL5) | |
+ * @target_rate: desired DPLL clock rate | |
+ * | |
+ * The erratum applies only for DM37xx, desired clock rates of | |
+ * div120m times 120 MHz and specified sys_clks. | |
+ * If any of the above specified condition does not apply, this | |
+ * function will fall back to omap2_dpll_round_rate. | |
+ */ | |
+long omap2_dpll5_round_rate(struct clk_hw *hw, unsigned long target_rate, | |
+ unsigned long *parent_rate) | |
+{ | |
+ struct clk_hw_omap *clk = to_clk_hw_omap(hw); | |
+ struct dpll_data *dd; | |
+ const char *clk_name; | |
+ int i; | |
+ | |
+ /* erratum tables */ | |
+ const struct sprz319e_2_1_values sprz319e_2_1_table[] = { | |
+ /* table 35 */ | |
+ { 12000000, 80, 0, 8 }, | |
+ { 19200000, 50, 0, 8 }, | |
+ { 38400000, 25, 0, 8 }, | |
+ /* table 36 */ | |
+ { 13000000, 443, 5, 8 }, | |
+ { 26000000, 443, 11, 8 }, | |
+ }; | |
+ | |
+ if (!clk || !clk->dpll_data) | |
+ return ~0; | |
+ | |
+ dd = clk->dpll_data; | |
+ | |
+ clk_name = __clk_get_name(hw->clk); | |
+ | |
+ for (i = 0; i < (sizeof(sprz319e_2_1_table)/sizeof(struct sprz319e_2_1_values)); i++) { | |
+ const struct sprz319e_2_1_values *v = &sprz319e_2_1_table[i]; | |
+ | |
+ if (*parent_rate == v->sys_clk_rate && | |
+ target_rate == DPLL5_FREQ_FOR_USBHOST * v->div120m) { | |
+ | |
+ printk(KERN_NOTICE "Applying SPRZ319E 2.1: %8lu, %3d, %3d, %3d\n", | |
+ v->sys_clk_rate, v->m, v->n, v->div120m); | |
+ | |
+ dd->last_rounded_m = v->m; | |
+ dd->last_rounded_n = v->n + 1; | |
+ dd->last_rounded_rate = v->sys_clk_rate * v->m / (v->n + 1); | |
+ | |
+ return dd->last_rounded_rate; | |
+ } | |
+ } | |
+} | |
diff --git a/arch/arm/mach-omap2/clock.h b/arch/arm/mach-omap2/clock.h | |
index 60ddd86..0df6eeb 100644 | |
--- a/arch/arm/mach-omap2/clock.h | |
+++ b/arch/arm/mach-omap2/clock.h | |
@@ -375,6 +375,8 @@ unsigned long omap_fixed_divisor_recalc(struct clk_hw *hw, | |
long omap2_dpll_round_rate(struct clk_hw *hw, unsigned long target_rate, | |
unsigned long *parent_rate); | |
+long omap2_dpll5_round_rate(struct clk_hw *hw, unsigned long target_rate, | |
+ unsigned long *parent_rate); | |
unsigned long omap3_dpll_recalc(struct clk_hw *hw, unsigned long parent_rate); | |
int omap3_noncore_dpll_enable(struct clk_hw *hw); | |
void omap3_noncore_dpll_disable(struct clk_hw *hw); | |
diff --git a/arch/arm/mach-omap2/clock3xxx.c b/arch/arm/mach-omap2/clock3xxx.c | |
index 0b02b41..90dbc25 100644 | |
--- a/arch/arm/mach-omap2/clock3xxx.c | |
+++ b/arch/arm/mach-omap2/clock3xxx.c | |
@@ -60,7 +60,13 @@ void __init omap3_clk_lock_dpll5(void) | |
struct clk *dpll5_m2_clk; | |
dpll5_clk = clk_get(NULL, "dpll5_ck"); | |
- clk_set_rate(dpll5_clk, DPLL5_FREQ_FOR_USBHOST); | |
+ | |
+ if (cpu_is_omap3630()) { | |
+ clk_set_rate(dpll5_clk, DPLL5_FREQ_FOR_USBHOST*8); | |
+ } else { | |
+ clk_set_rate(dpll5_clk, DPLL5_FREQ_FOR_USBHOST); | |
+ } | |
+ | |
clk_prepare_enable(dpll5_clk); | |
/* Program dpll5_m2_clk divider for no division */ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment