[ARM] 3026/1: S3C2410 - avoid possible overflow in pll calculations
authorBen Dooks <ben-linux@fluff.org>
Thu, 20 Oct 2005 22:21:18 +0000 (23:21 +0100)
committerRussell King <rmk+kernel@arm.linux.org.uk>
Thu, 20 Oct 2005 22:21:18 +0000 (23:21 +0100)
Patch from Ben Dooks

Avoid the possiblity that if the board is using
a 16.9334 or higher crystal with a high PLL
multiplier, then the pll value could overflow
the capability of an int.

Also fix the value types of the intermediate
variables to unsigned int.

Rewrite of patch from Guillaume Gourat

Signed-off-by: Ben Dooks <ben-linux@fluff.org>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
include/asm-arm/arch-s3c2410/regs-clock.h

index 16f4c3cc1388bd70ce8bfe9a93b16d34a5b5dabf..66794b13e185426eea083df75d8d3d3dfb2eb6f9 100644 (file)
@@ -18,7 +18,8 @@
  *    10-Feb-2005 Ben Dooks        Fixed CAMDIVN address (Guillaume Gourat)
  *    10-Mar-2005 Lucas Villa Real  Changed S3C2410_VA to S3C24XX_VA
  *    27-Aug-2005 Ben Dooks        Add clock-slow info
- */
+ *    20-Oct-2005 Ben Dooks        Fixed overflow in PLL (Guillaume Gourat)
+*/
 
 #ifndef __ASM_ARM_REGS_CLOCK
 #define __ASM_ARM_REGS_CLOCK "$Id: clock.h,v 1.4 2003/04/30 14:50:51 ben Exp $"
 
 #ifndef __ASSEMBLY__
 
+#include <asm/div64.h>
+
 static inline unsigned int
-s3c2410_get_pll(int pllval, int baseclk)
+s3c2410_get_pll(unsigned int pllval, unsigned int baseclk)
 {
-       int mdiv, pdiv, sdiv;
+       unsigned int mdiv, pdiv, sdiv;
+       uint64_t fvco;
 
        mdiv = pllval >> S3C2410_PLLCON_MDIVSHIFT;
        pdiv = pllval >> S3C2410_PLLCON_PDIVSHIFT;
@@ -96,7 +100,10 @@ s3c2410_get_pll(int pllval, int baseclk)
        pdiv &= S3C2410_PLLCON_PDIVMASK;
        sdiv &= S3C2410_PLLCON_SDIVMASK;
 
-       return (baseclk * (mdiv + 8)) / ((pdiv + 2) << sdiv);
+       fvco = (uint64_t)baseclk * (mdiv + 8);
+       do_div(fvco, (pdiv + 2) << sdiv);
+
+       return (unsigned int)fvco;
 }
 
 #endif /* __ASSEMBLY__ */