aboutsummaryrefslogtreecommitdiffstats
path: root/include/asm-blackfin/mach-bf548
diff options
context:
space:
mode:
authorMichael Hennerich <michael.hennerich@analog.com>2008-04-23 19:32:41 -0400
committerBryan Wu <cooloney@kernel.org>2008-04-23 19:32:41 -0400
commita81501af19830ff43688781edad7e9c0cbd668af (patch)
tree856be99eb74bfc5e6cf20369b633107d8d4170f6 /include/asm-blackfin/mach-bf548
parent4bea8b20fded93871c872bb4a0d7c23345318184 (diff)
[Blackfin] arch: Prevent potential Core Hang situation
If the new value written to the PLL_CTL or VR_CTL register is the same as the previous value, the PLL wake-up will occur immediately (PLL is already locked), but the core and system clock will be bypassed for the PLL_LOCKCNT duration. For this interval, code will execute at the CLKIN rate instead of at the expected CCLK rate. Software should guard against this condition by comparing the current value to the new value before writing the new value. Signed-off-by: Michael Hennerich <michael.hennerich@analog.com> Signed-off-by: Bryan Wu <cooloney@kernel.org>
Diffstat (limited to 'include/asm-blackfin/mach-bf548')
-rw-r--r--include/asm-blackfin/mach-bf548/cdefBF54x_base.h37
1 files changed, 33 insertions, 4 deletions
diff --git a/include/asm-blackfin/mach-bf548/cdefBF54x_base.h b/include/asm-blackfin/mach-bf548/cdefBF54x_base.h
index 33c67500717c..57ac8cb9b1f6 100644
--- a/include/asm-blackfin/mach-bf548/cdefBF54x_base.h
+++ b/include/asm-blackfin/mach-bf548/cdefBF54x_base.h
@@ -43,7 +43,33 @@
43/* PLL Registers */ 43/* PLL Registers */
44 44
45#define bfin_read_PLL_CTL() bfin_read16(PLL_CTL) 45#define bfin_read_PLL_CTL() bfin_read16(PLL_CTL)
46#define bfin_write_PLL_CTL(val) bfin_write16(PLL_CTL, val) 46/* Writing to PLL_CTL initiates a PLL relock sequence. */
47static __inline__ void bfin_write_PLL_CTL(unsigned int val)
48{
49 unsigned long flags, iwr0, iwr1, iwr2;
50
51 if (val == bfin_read_PLL_CTL())
52 return;
53
54 local_irq_save(flags);
55 /* Enable the PLL Wakeup bit in SIC IWR */
56 iwr0 = bfin_read32(SIC_IWR0);
57 iwr1 = bfin_read32(SIC_IWR1);
58 iwr2 = bfin_read32(SIC_IWR2);
59 /* Only allow PPL Wakeup) */
60 bfin_write32(SIC_IWR0, IWR_ENABLE(0));
61 bfin_write32(SIC_IWR1, 0);
62 bfin_write32(SIC_IWR2, 0);
63
64 bfin_write16(PLL_CTL, val);
65 SSYNC();
66 asm("IDLE;");
67
68 bfin_write32(SIC_IWR0, iwr0);
69 bfin_write32(SIC_IWR1, iwr1);
70 bfin_write32(SIC_IWR2, iwr2);
71 local_irq_restore(flags);
72}
47#define bfin_read_PLL_DIV() bfin_read16(PLL_DIV) 73#define bfin_read_PLL_DIV() bfin_read16(PLL_DIV)
48#define bfin_write_PLL_DIV(val) bfin_write16(PLL_DIV, val) 74#define bfin_write_PLL_DIV(val) bfin_write16(PLL_DIV, val)
49#define bfin_read_VR_CTL() bfin_read16(VR_CTL) 75#define bfin_read_VR_CTL() bfin_read16(VR_CTL)
@@ -52,6 +78,10 @@ static __inline__ void bfin_write_VR_CTL(unsigned int val)
52{ 78{
53 unsigned long flags, iwr0, iwr1, iwr2; 79 unsigned long flags, iwr0, iwr1, iwr2;
54 80
81 if (val == bfin_read_VR_CTL())
82 return;
83
84 local_irq_save(flags);
55 /* Enable the PLL Wakeup bit in SIC IWR */ 85 /* Enable the PLL Wakeup bit in SIC IWR */
56 iwr0 = bfin_read32(SIC_IWR0); 86 iwr0 = bfin_read32(SIC_IWR0);
57 iwr1 = bfin_read32(SIC_IWR1); 87 iwr1 = bfin_read32(SIC_IWR1);
@@ -63,13 +93,12 @@ static __inline__ void bfin_write_VR_CTL(unsigned int val)
63 93
64 bfin_write16(VR_CTL, val); 94 bfin_write16(VR_CTL, val);
65 SSYNC(); 95 SSYNC();
66
67 local_irq_save(flags);
68 asm("IDLE;"); 96 asm("IDLE;");
69 local_irq_restore(flags); 97
70 bfin_write32(SIC_IWR0, iwr0); 98 bfin_write32(SIC_IWR0, iwr0);
71 bfin_write32(SIC_IWR1, iwr1); 99 bfin_write32(SIC_IWR1, iwr1);
72 bfin_write32(SIC_IWR2, iwr2); 100 bfin_write32(SIC_IWR2, iwr2);
101 local_irq_restore(flags);
73} 102}
74#define bfin_read_PLL_STAT() bfin_read16(PLL_STAT) 103#define bfin_read_PLL_STAT() bfin_read16(PLL_STAT)
75#define bfin_write_PLL_STAT(val) bfin_write16(PLL_STAT, val) 104#define bfin_write_PLL_STAT(val) bfin_write16(PLL_STAT, val)