clk: g12a/g12b: fix 32bit set mpll clk overflow [1/1]
PD#SWPL-1933
Problem:
32bit system clk overflow
Solution:
let mpll clock not overflow
Verify:
g12b
Change-Id: Ie1c7c611e637776348bb35a3e0c1624cee57716f
Signed-off-by: shunzhou.jiang <shunzhou.jiang@amlogic.com>
diff --git a/drivers/amlogic/clk/g12a/g12a_clk-mpll.c b/drivers/amlogic/clk/g12a/g12a_clk-mpll.c
index 1d62f34..abd74ea 100644
--- a/drivers/amlogic/clk/g12a/g12a_clk-mpll.c
+++ b/drivers/amlogic/clk/g12a/g12a_clk-mpll.c
@@ -28,7 +28,7 @@
#include "../clkc.h"
/* #undef pr_debug */
/* #define pr_debug pr_info */
-#define SDM_MAX 16384
+#define SDM_MAX 16384ULL
#define MAX_RATE 500000000
#define MIN_RATE 3920000
@@ -87,6 +87,7 @@
struct parm *p;
unsigned long reg, sdm, n2;
unsigned long flags = 0;
+ uint64_t rate64 = parent_rate;
if ((rate > MAX_RATE) || (rate < MIN_RATE)) {
pr_err("Err: can not set rate to %lu!\n", rate);
@@ -98,8 +99,12 @@
spin_lock_irqsave(mpll->lock, flags);
/* calculate new n2 and sdm */
- n2 = parent_rate / rate;
- sdm = DIV_ROUND_UP((parent_rate - n2 * rate) * SDM_MAX, rate);
+ do_div(rate64, rate);
+ n2 = rate64;
+
+ rate64 = (parent_rate - n2 * rate) * SDM_MAX + rate - 1;
+ do_div(rate64, rate);
+ sdm = rate64;
if (sdm >= SDM_MAX)
sdm = SDM_MAX - 1;