summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rwxr-xr-xrecipes-kernel/linux/linux-3.0/patch.sh2
-rw-r--r--recipes-kernel/linux/linux-3.0/usb/0001-Fix-sprz319-erratum-2.1.patch210
-rw-r--r--recipes-kernel/linux/linux_3.0.bb4
3 files changed, 214 insertions, 2 deletions
diff --git a/recipes-kernel/linux/linux-3.0/patch.sh b/recipes-kernel/linux/linux-3.0/patch.sh
index dc19a9e5..31bdfe18 100755
--- a/recipes-kernel/linux/linux-3.0/patch.sh
+++ b/recipes-kernel/linux/linux-3.0/patch.sh
@@ -13,7 +13,7 @@ git reset --hard ${TAG}
13rm export -rf 13rm export -rf
14 14
15previous=${TAG} 15previous=${TAG}
16PATCHSET="pm-wip/voltdm pm-wip/cpufreq beagle madc sakoman sgx ulcd omap4 misc" 16PATCHSET="pm-wip/voltdm pm-wip/cpufreq beagle madc sakoman sgx ulcd omap4 misc usb"
17 17
18# apply patches 18# apply patches
19for patchset in ${PATCHSET} ; do 19for patchset in ${PATCHSET} ; do
diff --git a/recipes-kernel/linux/linux-3.0/usb/0001-Fix-sprz319-erratum-2.1.patch b/recipes-kernel/linux/linux-3.0/usb/0001-Fix-sprz319-erratum-2.1.patch
new file mode 100644
index 00000000..8d65b5f0
--- /dev/null
+++ b/recipes-kernel/linux/linux-3.0/usb/0001-Fix-sprz319-erratum-2.1.patch
@@ -0,0 +1,210 @@
1From cf5db5477d8d43f02f4511f3835ab4bec0dcc27c Mon Sep 17 00:00:00 2001
2From: Richard Watts <rrw@kynesim.co.uk>
3Date: Mon, 20 Feb 2012 17:58:26 +0000
4Subject: [PATCH] Fix sprz319 erratum 2.1
5
6There is an erratum in DM3730 which results in the
7EHCI USB PLL (DPLL5) not updating sufficiently frequently; this
8leads to USB PHY clock drift and once the clock has drifted far
9enough, the PHY's ULPI interface stops responding and USB
10drops out. This is manifested on a Beagle xM by having the attached
11SMSC9514 report 'Cannot enable port 2. Maybe the USB cable is bad?'
12or similar.
13
14The fix is to carefully adjust your DPLL5 settings so as to
15keep the PHY clock as close as possible to 120MHz over the long
16term; TI SPRZ319e gives a table of such settings and this patch
17applies that table to systems with a 13MHz or a 26MHz clock,
18thus fixing the issue (inasfar as it can be fixed) on Beagle xM
19and Overo Firestorm.
20
21Signed-off-by: Richard Watts <rrw@kynesim.co.uk>
22---
23 arch/arm/mach-omap2/clkt_clksel.c | 15 ++++++++
24 arch/arm/mach-omap2/clock.h | 7 ++++
25 arch/arm/mach-omap2/clock3xxx.c | 65 +++++++++++++++++++++++++++++----
26 arch/arm/mach-omap2/clock3xxx.h | 1 +
27 arch/arm/mach-omap2/clock3xxx_data.c | 2 +-
28 arch/arm/mach-omap2/dpll3xxx.c | 2 +-
29 6 files changed, 82 insertions(+), 10 deletions(-)
30
31diff --git a/arch/arm/mach-omap2/clkt_clksel.c b/arch/arm/mach-omap2/clkt_clksel.c
32index e25364d..e378fe7 100644
33--- a/arch/arm/mach-omap2/clkt_clksel.c
34+++ b/arch/arm/mach-omap2/clkt_clksel.c
35@@ -460,6 +460,21 @@ int omap2_clksel_set_rate(struct clk *clk, unsigned long rate)
36 return 0;
37 }
38
39+int omap2_clksel_force_divisor(struct clk *clk, int new_div)
40+{
41+ u32 field_val;
42+
43+ field_val = _divisor_to_clksel(clk, new_div);
44+ if (field_val == ~0)
45+ return -EINVAL;
46+
47+ _write_clksel_reg(clk, field_val);
48+
49+ clk->rate = clk->parent->rate / new_div;
50+
51+ return 0;
52+}
53+
54 /*
55 * Clksel parent setting function - not passed in struct clk function
56 * pointer - instead, the OMAP clock code currently assumes that any
57diff --git a/arch/arm/mach-omap2/clock.h b/arch/arm/mach-omap2/clock.h
58index 8bad1c6..ac3d367 100644
59--- a/arch/arm/mach-omap2/clock.h
60+++ b/arch/arm/mach-omap2/clock.h
61@@ -61,6 +61,12 @@ void omap3_dpll_allow_idle(struct clk *clk);
62 void omap3_dpll_deny_idle(struct clk *clk);
63 u32 omap3_dpll_autoidle_read(struct clk *clk);
64 int omap3_noncore_dpll_set_rate(struct clk *clk, unsigned long rate);
65+#if CONFIG_ARCH_OMAP3
66+int omap3_noncore_dpll_program(struct clk *clk, u16 m, u8 n, u16 freqsel);
67+/* If you are using this function and not on OMAP3, you are
68+ * Doing It Wrong(tm), so there is no stub.
69+ */
70+#endif
71 int omap3_noncore_dpll_enable(struct clk *clk);
72 void omap3_noncore_dpll_disable(struct clk *clk);
73 int omap4_dpllmx_gatectrl_read(struct clk *clk);
74@@ -84,6 +90,7 @@ unsigned long omap2_clksel_recalc(struct clk *clk);
75 long omap2_clksel_round_rate(struct clk *clk, unsigned long target_rate);
76 int omap2_clksel_set_rate(struct clk *clk, unsigned long rate);
77 int omap2_clksel_set_parent(struct clk *clk, struct clk *new_parent);
78+int omap2_clksel_force_divisor(struct clk *clk, int new_div);
79
80 /* clkt_iclk.c public functions */
81 extern void omap2_clkt_iclk_allow_idle(struct clk *clk);
82diff --git a/arch/arm/mach-omap2/clock3xxx.c b/arch/arm/mach-omap2/clock3xxx.c
83index 952c3e0..d5be086 100644
84--- a/arch/arm/mach-omap2/clock3xxx.c
85+++ b/arch/arm/mach-omap2/clock3xxx.c
86@@ -40,6 +40,60 @@
87 /* needed by omap3_core_dpll_m2_set_rate() */
88 struct clk *sdrc_ick_p, *arm_fck_p;
89
90+struct dpll_settings {
91+ int rate, m, n, f;
92+};
93+
94+
95+static int omap3_dpll5_apply_erratum21(struct clk *clk, struct clk *dpll5_m2)
96+{
97+ struct clk *sys_clk;
98+ int i, rv;
99+ static const struct dpll_settings precomputed[] = {
100+ /* From DM3730 errata (sprz319e), table 36
101+ * +1 is because the values in the table are register values;
102+ * dpll_program() will subtract one from what we give it,
103+ * so ...
104+ */
105+ { 13000000, 443+1, 5+1, 8 },
106+ { 26000000, 443+1, 11+1, 8 }
107+ };
108+
109+ sys_clk = clk_get(NULL, "sys_ck");
110+
111+ for (i = 0 ; i < (sizeof(precomputed)/sizeof(struct dpll_settings)) ;
112+ ++i) {
113+ const struct dpll_settings *d = &precomputed[i];
114+ if (sys_clk->rate == d->rate) {
115+ rv = omap3_noncore_dpll_program(clk, d->m , d->n, 0);
116+ if (rv)
117+ return 1;
118+ rv = omap2_clksel_force_divisor(dpll5_m2 , d->f);
119+ return 1;
120+ }
121+ }
122+ return 0;
123+}
124+
125+int omap3_dpll5_set_rate(struct clk *clk, unsigned long rate)
126+{
127+ struct clk *dpll5_m2;
128+ int rv;
129+ dpll5_m2 = clk_get(NULL, "dpll5_m2_ck");
130+
131+ if (cpu_is_omap3630() && rate == DPLL5_FREQ_FOR_USBHOST &&
132+ omap3_dpll5_apply_erratum21(clk, dpll5_m2)) {
133+ return 1;
134+ }
135+ rv = omap3_noncore_dpll_set_rate(clk, rate);
136+ if (rv)
137+ goto out;
138+ rv = clk_set_rate(dpll5_m2, rate);
139+
140+out:
141+ return rv;
142+}
143+
144 int omap3_dpll4_set_rate(struct clk *clk, unsigned long rate)
145 {
146 /*
147@@ -59,19 +113,14 @@ int omap3_dpll4_set_rate(struct clk *clk, unsigned long rate)
148 void __init omap3_clk_lock_dpll5(void)
149 {
150 struct clk *dpll5_clk;
151- struct clk *dpll5_m2_clk;
152
153 dpll5_clk = clk_get(NULL, "dpll5_ck");
154 clk_set_rate(dpll5_clk, DPLL5_FREQ_FOR_USBHOST);
155- clk_enable(dpll5_clk);
156
157- /* Program dpll5_m2_clk divider for no division */
158- dpll5_m2_clk = clk_get(NULL, "dpll5_m2_ck");
159- clk_enable(dpll5_m2_clk);
160- clk_set_rate(dpll5_m2_clk, DPLL5_FREQ_FOR_USBHOST);
161+ /* dpll5_m2_ck is now (grottily!) handled by dpll5_clk's set routine,
162+ * to cope with an erratum on DM3730
163+ */
164
165- clk_disable(dpll5_m2_clk);
166- clk_disable(dpll5_clk);
167 return;
168 }
169
170diff --git a/arch/arm/mach-omap2/clock3xxx.h b/arch/arm/mach-omap2/clock3xxx.h
171index 8bbeeaf..0ede513 100644
172--- a/arch/arm/mach-omap2/clock3xxx.h
173+++ b/arch/arm/mach-omap2/clock3xxx.h
174@@ -10,6 +10,7 @@
175
176 int omap3xxx_clk_init(void);
177 int omap3_dpll4_set_rate(struct clk *clk, unsigned long rate);
178+int omap3_dpll5_set_rate(struct clk *clk, unsigned long rate);
179 int omap3_core_dpll_m2_set_rate(struct clk *clk, unsigned long rate);
180 void omap3_clk_lock_dpll5(void);
181
182diff --git a/arch/arm/mach-omap2/clock3xxx_data.c b/arch/arm/mach-omap2/clock3xxx_data.c
183index ffd55b1..dcd7bdc 100644
184--- a/arch/arm/mach-omap2/clock3xxx_data.c
185+++ b/arch/arm/mach-omap2/clock3xxx_data.c
186@@ -942,7 +942,7 @@ static struct clk dpll5_ck = {
187 .parent = &sys_ck,
188 .dpll_data = &dpll5_dd,
189 .round_rate = &omap2_dpll_round_rate,
190- .set_rate = &omap3_noncore_dpll_set_rate,
191+ .set_rate = &omap3_dpll5_set_rate,
192 .clkdm_name = "dpll5_clkdm",
193 .recalc = &omap3_dpll_recalc,
194 };
195diff --git a/arch/arm/mach-omap2/dpll3xxx.c b/arch/arm/mach-omap2/dpll3xxx.c
196index f77022b..1909cd0 100644
197--- a/arch/arm/mach-omap2/dpll3xxx.c
198+++ b/arch/arm/mach-omap2/dpll3xxx.c
199@@ -291,7 +291,7 @@ static void _lookup_sddiv(struct clk *clk, u8 *sd_div, u16 m, u8 n)
200 * Program the DPLL with the supplied M, N values, and wait for the DPLL to
201 * lock.. Returns -EINVAL upon error, or 0 upon success.
202 */
203-static int omap3_noncore_dpll_program(struct clk *clk, u16 m, u8 n, u16 freqsel)
204+int omap3_noncore_dpll_program(struct clk *clk, u16 m, u8 n, u16 freqsel)
205 {
206 struct dpll_data *dd = clk->dpll_data;
207 u8 dco, sd_div;
208--
2091.7.2.5
210
diff --git a/recipes-kernel/linux/linux_3.0.bb b/recipes-kernel/linux/linux_3.0.bb
index 32ef9632..c95542e9 100644
--- a/recipes-kernel/linux/linux_3.0.bb
+++ b/recipes-kernel/linux/linux_3.0.bb
@@ -10,7 +10,7 @@ PV = "3.0.23"
10SRCREV_pn-${PN} = "bf6a68d2a214e07f7c0d6538e00e17b826714160" 10SRCREV_pn-${PN} = "bf6a68d2a214e07f7c0d6538e00e17b826714160"
11 11
12# The main PR is now using MACHINE_KERNEL_PR, for omap3 see conf/machine/include/omap3.inc 12# The main PR is now using MACHINE_KERNEL_PR, for omap3 see conf/machine/include/omap3.inc
13MACHINE_KERNEL_PR_append = "a" 13MACHINE_KERNEL_PR_append = "b"
14 14
15FILESPATH =. "${FILE_DIRNAME}/linux-3.0:${FILE_DIRNAME}/linux-3.0/${MACHINE}:" 15FILESPATH =. "${FILE_DIRNAME}/linux-3.0:${FILE_DIRNAME}/linux-3.0/${MACHINE}:"
16 16
@@ -224,6 +224,8 @@ SRC_URI += "git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.gi
224 \ 224 \
225 file://misc/0001-compiler.h-Undef-before-redefining-__attribute_const.patch \ 225 file://misc/0001-compiler.h-Undef-before-redefining-__attribute_const.patch \
226 \ 226 \
227 file://usb/0001-Fix-sprz319-erratum-2.1.patch \
228 \
227 file://defconfig" 229 file://defconfig"
228 230
229SRC_URI_append_beagleboard = " file://logo_linux_clut224.ppm \ 231SRC_URI_append_beagleboard = " file://logo_linux_clut224.ppm \