]> err.no Git - linux-2.6/commitdiff
[Blackfin] arch: Prevent potential Core Hang situation
authorMichael Hennerich <michael.hennerich@analog.com>
Wed, 23 Apr 2008 23:32:41 +0000 (07:32 +0800)
committerBryan Wu <cooloney@kernel.org>
Wed, 23 Apr 2008 23:32:41 +0000 (07:32 +0800)
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>
include/asm-blackfin/mach-bf527/cdefBF52x_base.h
include/asm-blackfin/mach-bf533/cdefBF532.h
include/asm-blackfin/mach-bf537/cdefBF534.h
include/asm-blackfin/mach-bf548/cdefBF54x_base.h
include/asm-blackfin/mach-bf561/cdefBF561.h

index 50e14e7da3ee6c7900f68a81e622ed0c54083ded..9dbdbec8ea1b93187ffb60ff7fbee48848c61911 100644 (file)
  */
 
 #ifndef _CDEF_BF52X_H
+#define _CDEF_BF52X_H
+
+#include <asm/system.h>
+#include <asm/blackfin.h>
 
 #include "defBF52x_base.h"
 
+/* Include core specific register pointer definitions                                                          */
+#include <asm/mach-common/cdef_LPBlackfin.h>
+
 /* ==== begin from cdefBF534.h ==== */
 
 /* Clock and System Control    (0xFFC00000 - 0xFFC000FF)                                                               */
 #define bfin_read_PLL_CTL()                    bfin_read16(PLL_CTL)
-#define bfin_write_PLL_CTL(val)                        bfin_write16(PLL_CTL, val)
+/* Writing to PLL_CTL initiates a PLL relock sequence. */
+static __inline__ void bfin_write_PLL_CTL(unsigned int val)
+{
+       unsigned long flags, iwr0, iwr1;
+
+       if (val == bfin_read_PLL_CTL())
+               return;
+
+       local_irq_save(flags);
+       /* Enable the PLL Wakeup bit in SIC IWR */
+       iwr0 = bfin_read32(SIC_IWR0);
+       iwr1 = bfin_read32(SIC_IWR1);
+       /* Only allow PPL Wakeup) */
+       bfin_write32(SIC_IWR0, IWR_ENABLE(0));
+       bfin_write32(SIC_IWR1, 0);
+
+       bfin_write16(PLL_CTL, val);
+       SSYNC();
+       asm("IDLE;");
+
+       bfin_write32(SIC_IWR0, iwr0);
+       bfin_write32(SIC_IWR1, iwr1);
+       local_irq_restore(flags);
+}
 #define bfin_read_PLL_DIV()                    bfin_read16(PLL_DIV)
 #define bfin_write_PLL_DIV(val)                        bfin_write16(PLL_DIV, val)
 #define bfin_read_VR_CTL()                     bfin_read16(VR_CTL)
-#define bfin_write_VR_CTL(val)                 bfin_write16(VR_CTL, val)
+/* Writing to VR_CTL initiates a PLL relock sequence. */
+static __inline__ void bfin_write_VR_CTL(unsigned int val)
+{
+       unsigned long flags, iwr0, iwr1;
+
+       if (val == bfin_read_VR_CTL())
+               return;
+
+       local_irq_save(flags);
+       /* Enable the PLL Wakeup bit in SIC IWR */
+       iwr0 = bfin_read32(SIC_IWR0);
+       iwr1 = bfin_read32(SIC_IWR1);
+       /* Only allow PPL Wakeup) */
+       bfin_write32(SIC_IWR0, IWR_ENABLE(0));
+       bfin_write32(SIC_IWR1, 0);
+
+       bfin_write16(VR_CTL, val);
+       SSYNC();
+       asm("IDLE;");
+
+       bfin_write32(SIC_IWR0, iwr0);
+       bfin_write32(SIC_IWR1, iwr1);
+       local_irq_restore(flags);
+}
 #define bfin_read_PLL_STAT()                   bfin_read16(PLL_STAT)
 #define bfin_write_PLL_STAT(val)               bfin_write16(PLL_STAT, val)
 #define bfin_read_PLL_LOCKCNT()                        bfin_read16(PLL_LOCKCNT)
index c803e14b529c4aef65cee494d54193e08ae152bb..154655452d4c97d93d1cbe6d6397e1b68c61012b 100644 (file)
 
 /* Clock and System Control (0xFFC0 0400-0xFFC0 07FF) */
 #define bfin_read_PLL_CTL()                  bfin_read16(PLL_CTL)
-#define bfin_write_PLL_CTL(val)              bfin_write16(PLL_CTL,val)
+/* Writing to PLL_CTL initiates a PLL relock sequence. */
+static __inline__ void bfin_write_PLL_CTL(unsigned int val)
+{
+       unsigned long flags, iwr;
+
+       if (val == bfin_read_PLL_CTL())
+               return;
+
+       local_irq_save(flags);
+       /* Enable the PLL Wakeup bit in SIC IWR */
+       iwr = bfin_read32(SIC_IWR);
+       /* Only allow PPL Wakeup) */
+       bfin_write32(SIC_IWR, IWR_ENABLE(0));
+
+       bfin_write16(PLL_CTL, val);
+       SSYNC();
+       asm("IDLE;");
+
+       bfin_write32(SIC_IWR, iwr);
+       local_irq_restore(flags);
+}
 #define bfin_read_PLL_STAT()                 bfin_read16(PLL_STAT)
 #define bfin_write_PLL_STAT(val)             bfin_write16(PLL_STAT,val)
 #define bfin_read_PLL_LOCKCNT()              bfin_read16(PLL_LOCKCNT)
@@ -57,6 +77,10 @@ static __inline__ void bfin_write_VR_CTL(unsigned int val)
 {
        unsigned long flags, iwr;
 
+       if (val == bfin_read_VR_CTL())
+               return;
+
+       local_irq_save(flags);
        /* Enable the PLL Wakeup bit in SIC IWR */
        iwr = bfin_read32(SIC_IWR);
        /* Only allow PPL Wakeup) */
@@ -64,11 +88,10 @@ static __inline__ void bfin_write_VR_CTL(unsigned int val)
 
        bfin_write16(VR_CTL, val);
        SSYNC();
-
-       local_irq_save(flags);
        asm("IDLE;");
-       local_irq_restore(flags);
+
        bfin_write32(SIC_IWR, iwr);
+       local_irq_restore(flags);
 }
 
 /* System Interrupt Controller (0xFFC0 0C00-0xFFC0 0FFF) */
index 048d26a61fd1753ef5dc1ebfe59862ea876381c3..82de526f8097532ecf05ecff23aa0db277316a11 100644 (file)
 
 /* Clock and System Control    (0xFFC00000 - 0xFFC000FF)                                                               */
 #define bfin_read_PLL_CTL()                  bfin_read16(PLL_CTL)
-#define bfin_write_PLL_CTL(val)              bfin_write16(PLL_CTL,val)
+/* Writing to PLL_CTL initiates a PLL relock sequence. */
+static __inline__ void bfin_write_PLL_CTL(unsigned int val)
+{
+       unsigned long flags, iwr;
+
+       if (val == bfin_read_PLL_CTL())
+               return;
+
+       local_irq_save(flags);
+       /* Enable the PLL Wakeup bit in SIC IWR */
+       iwr = bfin_read32(SIC_IWR);
+       /* Only allow PPL Wakeup) */
+       bfin_write32(SIC_IWR, IWR_ENABLE(0));
+
+       bfin_write16(PLL_CTL, val);
+       SSYNC();
+       asm("IDLE;");
+
+       bfin_write32(SIC_IWR, iwr);
+       local_irq_restore(flags);
+}
 #define bfin_read_PLL_DIV()                  bfin_read16(PLL_DIV)
 #define bfin_write_PLL_DIV(val)              bfin_write16(PLL_DIV,val)
 #define bfin_read_VR_CTL()                   bfin_read16(VR_CTL)
@@ -53,6 +73,10 @@ static __inline__ void bfin_write_VR_CTL(unsigned int val)
 {
        unsigned long flags, iwr;
 
+       if (val == bfin_read_VR_CTL())
+               return;
+
+       local_irq_save(flags);
        /* Enable the PLL Wakeup bit in SIC IWR */
        iwr = bfin_read32(SIC_IWR);
        /* Only allow PPL Wakeup) */
@@ -60,11 +84,10 @@ static __inline__ void bfin_write_VR_CTL(unsigned int val)
 
        bfin_write16(VR_CTL, val);
        SSYNC();
-
-       local_irq_save(flags);
        asm("IDLE;");
-       local_irq_restore(flags);
+
        bfin_write32(SIC_IWR, iwr);
+       local_irq_restore(flags);
 }
 #define bfin_read_PLL_STAT()                 bfin_read16(PLL_STAT)
 #define bfin_write_PLL_STAT(val)             bfin_write16(PLL_STAT,val)
index 33c67500717cbe5a3ebab6f06c1308559481e49c..57ac8cb9b1f6be7c968aa28b4e3ca2fbee284d7e 100644 (file)
 /* PLL Registers */
 
 #define bfin_read_PLL_CTL()            bfin_read16(PLL_CTL)
-#define bfin_write_PLL_CTL(val)                bfin_write16(PLL_CTL, val)
+/* Writing to PLL_CTL initiates a PLL relock sequence. */
+static __inline__ void bfin_write_PLL_CTL(unsigned int val)
+{
+       unsigned long flags, iwr0, iwr1, iwr2;
+
+       if (val == bfin_read_PLL_CTL())
+               return;
+
+       local_irq_save(flags);
+       /* Enable the PLL Wakeup bit in SIC IWR */
+       iwr0 = bfin_read32(SIC_IWR0);
+       iwr1 = bfin_read32(SIC_IWR1);
+       iwr2 = bfin_read32(SIC_IWR2);
+       /* Only allow PPL Wakeup) */
+       bfin_write32(SIC_IWR0, IWR_ENABLE(0));
+       bfin_write32(SIC_IWR1, 0);
+       bfin_write32(SIC_IWR2, 0);
+
+       bfin_write16(PLL_CTL, val);
+       SSYNC();
+       asm("IDLE;");
+
+       bfin_write32(SIC_IWR0, iwr0);
+       bfin_write32(SIC_IWR1, iwr1);
+       bfin_write32(SIC_IWR2, iwr2);
+       local_irq_restore(flags);
+}
 #define bfin_read_PLL_DIV()            bfin_read16(PLL_DIV)
 #define bfin_write_PLL_DIV(val)                bfin_write16(PLL_DIV, val)
 #define bfin_read_VR_CTL()             bfin_read16(VR_CTL)
@@ -52,6 +78,10 @@ static __inline__ void bfin_write_VR_CTL(unsigned int val)
 {
        unsigned long flags, iwr0, iwr1, iwr2;
 
+       if (val == bfin_read_VR_CTL())
+               return;
+
+       local_irq_save(flags);
        /* Enable the PLL Wakeup bit in SIC IWR */
        iwr0 = bfin_read32(SIC_IWR0);
        iwr1 = bfin_read32(SIC_IWR1);
@@ -63,13 +93,12 @@ static __inline__ void bfin_write_VR_CTL(unsigned int val)
 
        bfin_write16(VR_CTL, val);
        SSYNC();
-
-       local_irq_save(flags);
        asm("IDLE;");
-       local_irq_restore(flags);
+
        bfin_write32(SIC_IWR0, iwr0);
        bfin_write32(SIC_IWR1, iwr1);
        bfin_write32(SIC_IWR2, iwr2);
+       local_irq_restore(flags);
 }
 #define bfin_read_PLL_STAT()           bfin_read16(PLL_STAT)
 #define bfin_write_PLL_STAT(val)       bfin_write16(PLL_STAT, val)
index 1bc8d2f89cccf7ae69baaa1a29477f20406b7b2d..b07ffccd66dd8a6f960487123895f3cc80d21c07 100644 (file)
 
 /* Clock and System Control (0xFFC00000 - 0xFFC000FF) */
 #define bfin_read_PLL_CTL()                  bfin_read16(PLL_CTL)
-#define bfin_write_PLL_CTL(val)              bfin_write16(PLL_CTL,val)
+/* Writing to PLL_CTL initiates a PLL relock sequence. */
+static __inline__ void bfin_write_PLL_CTL(unsigned int val)
+{
+       unsigned long flags, iwr0, iwr1;
+
+       if (val == bfin_read_PLL_CTL())
+               return;
+
+       local_irq_save(flags);
+       /* Enable the PLL Wakeup bit in SIC IWR */
+       iwr0 = bfin_read32(SICA_IWR0);
+       iwr1 = bfin_read32(SICA_IWR1);
+       /* Only allow PPL Wakeup) */
+       bfin_write32(SICA_IWR0, IWR_ENABLE(0));
+       bfin_write32(SICA_IWR1, 0);
+
+       bfin_write16(PLL_CTL, val);
+       SSYNC();
+       asm("IDLE;");
+
+       bfin_write32(SICA_IWR0, iwr0);
+       bfin_write32(SICA_IWR1, iwr1);
+       local_irq_restore(flags);
+}
 #define bfin_read_PLL_DIV()                  bfin_read16(PLL_DIV)
 #define bfin_write_PLL_DIV(val)              bfin_write16(PLL_DIV,val)
 #define bfin_read_VR_CTL()                   bfin_read16(VR_CTL)
@@ -56,6 +79,10 @@ static __inline__ void bfin_write_VR_CTL(unsigned int val)
 {
        unsigned long flags, iwr0, iwr1;
 
+       if (val == bfin_read_VR_CTL())
+               return;
+
+       local_irq_save(flags);
        /* Enable the PLL Wakeup bit in SIC IWR */
        iwr0 = bfin_read32(SICA_IWR0);
        iwr1 = bfin_read32(SICA_IWR1);
@@ -65,12 +92,11 @@ static __inline__ void bfin_write_VR_CTL(unsigned int val)
 
        bfin_write16(VR_CTL, val);
        SSYNC();
-
-       local_irq_save(flags);
        asm("IDLE;");
-       local_irq_restore(flags);
+
        bfin_write32(SICA_IWR0, iwr0);
        bfin_write32(SICA_IWR1, iwr1);
+       local_irq_restore(flags);
 }
 #define bfin_read_PLL_STAT()                 bfin_read16(PLL_STAT)
 #define bfin_write_PLL_STAT(val)             bfin_write16(PLL_STAT,val)