From 55c648a4c367c79e8b1ea9dfeb6f97ea505b9c8f Mon Sep 17 00:00:00 2001 From: Venkateshwar Rao Gannavarapu Date: Thu, 1 Nov 2018 13:53:00 +0530 Subject: [PATCH] clk: Fix compilation errors of silicon labs si5324 driver on zynq platform This patch fixes the following linker errors on zynq(32-bit cpu) platform by replacing the div and mod operations with math lib api. drivers/clk/si5324drv.o: In function `si5324_rate_approx': si5324drv.c:(.text+0xa8): undefined reference to `__aeabi_uldivmod' si5324drv.c:(.text+0xdc): undefined reference to `__aeabi_uldivmod' si5324drv.c:(.text+0x13c): undefined reference to `__aeabi_uldivmod' Signed-off-by: Venkateshwar Rao Gannavarapu Reviewed-by: Sandip Kothari Signed-off-by: Michal Simek --- drivers/clk/si5324drv.c | 67 +++++++++++++++++++++-------------------- 1 file changed, 34 insertions(+), 33 deletions(-) diff --git a/drivers/clk/si5324drv.c b/drivers/clk/si5324drv.c index 3cd498b81644..5c064a329e73 100644 --- a/drivers/clk/si5324drv.c +++ b/drivers/clk/si5324drv.c @@ -28,7 +28,7 @@ void si5324_rate_approx(u64 f, u64 md, u32 *num, u32 *denom) { u64 a, h[3] = { 0, 1, 0 }, k[3] = { 1, 0, 0 }; - u64 x, d, n = 1; + u64 x, d, m, n = 1; int i = 0; if (md <= 1) { @@ -49,16 +49,16 @@ void si5324_rate_approx(u64 f, u64 md, u32 *num, u32 *denom) d = f; for (i = 0; i < 64; i++) { - a = n ? d / n : 0; + a = n ? (div64_u64(d, n)) : 0; if (i && !a) break; x = d; d = n; - n = x % n; - + div64_u64_rem(x, n, &m); + n = m; x = a; if (k[1] * a + k[0] >= md) { - x = (md - k[0]) / k[1]; + x = div64_u64((md - k[0]), k[1]); if (x * 2 >= a || k[1] >= md) i = 65; else @@ -93,28 +93,29 @@ static int si5324_find_n2ls(struct si5324_settingst *settings) u64 fosc_actual; u64 fout_actual; u64 delta_fout; - u64 n2_ls_div_n3; + u64 n2_ls_div_n3, mult_res; u32 mult; - n2_ls_div_n3 = settings->fosc / - (settings->fin >> SI5324_FIN_FOUT_SHIFT) / - settings->n2_hs / 2; + n2_ls_div_n3 = div64_u64(div64_u64(div64_u64(settings->fosc, + (settings->fin >> SI5324_FIN_FOUT_SHIFT)), + (u64)settings->n2_hs), (u64)2); + si5324_rate_approx(n2_ls_div_n3, settings->n31_max, &settings->n2_ls, - &settings->n31); + &settings->n31); settings->n2_ls *= 2; if (settings->n2_ls < settings->n2_ls_min) { - mult = settings->n2_ls_min / settings->n2_ls; - mult = (settings->n2_ls_min % settings->n2_ls) ? - mult + 1 : mult; + mult = div64_u64(settings->n2_ls_min, settings->n2_ls); + div64_u64_rem(settings->n2_ls_min, settings->n2_ls, &mult_res); + mult = mult_res ? mult + 1 : mult; settings->n2_ls *= mult; settings->n31 *= mult; } if (settings->n31 < settings->n31_min) { - mult = settings->n31_min / settings->n31; - mult = (settings->n31_min % settings->n31) ? - mult + 1 : mult; + mult = div64_u64(settings->n31_min, settings->n31); + div64_u64_rem(settings->n31_min, settings->n31, &mult_res); + mult = mult_res ? mult + 1 : mult; settings->n2_ls *= mult; settings->n31 *= mult; } @@ -128,10 +129,10 @@ static int si5324_find_n2ls(struct si5324_settingst *settings) (settings->n31 > settings->n31_max)) { pr_info("N3 out of range.\n"); } else { - f3_actual = settings->fin / settings->n31; + f3_actual = div64_u64(settings->fin, settings->n31); fosc_actual = f3_actual * settings->n2_hs * settings->n2_ls; - fout_actual = fosc_actual / - (settings->n1_hs * settings->nc1_ls); + fout_actual = div64_u64(fosc_actual, + (settings->n1_hs * settings->nc1_ls)); delta_fout = fout_actual - settings->fout; if ((f3_actual < ((u64)SI5324_F3_MIN) << @@ -193,18 +194,17 @@ static int si5324_find_n2(struct si5324_settingst *settings) for (settings->n2_hs = SI5324_N2_HS_MAX; settings->n2_hs >= SI5324_N2_HS_MIN; settings->n2_hs--) { pr_debug("Trying N2_HS = %d.\n", settings->n2_hs); - settings->n2_ls_min = (u32)(settings->fosc / - ((u64)(SI5324_F3_MAX * - settings->n2_hs) << - SI5324_FIN_FOUT_SHIFT)); + settings->n2_ls_min = (u32)(div64_u64(settings->fosc, + ((u64)(SI5324_F3_MAX * settings->n2_hs) + << SI5324_FIN_FOUT_SHIFT))); if (settings->n2_ls_min < SI5324_N2_LS_MIN) settings->n2_ls_min = SI5324_N2_LS_MIN; - settings->n2_ls_max = (u32)(settings->fosc / + settings->n2_ls_max = (u32)(div64_u64(settings->fosc, ((u64)(SI5324_F3_MIN * settings->n2_hs) << - SI5324_FIN_FOUT_SHIFT)); + SI5324_FIN_FOUT_SHIFT))); if (settings->n2_ls_max > SI5324_N2_LS_MAX) settings->n2_ls_max = SI5324_N2_LS_MAX; @@ -228,13 +228,14 @@ static int si5324_find_n2(struct si5324_settingst *settings) */ int si5324_calc_ncls_limits(struct si5324_settingst *settings) { - settings->nc1_ls_min = settings->n1_hs_min / settings->n1_hs; + settings->nc1_ls_min = div64_u64(settings->n1_hs_min, + settings->n1_hs); if (settings->nc1_ls_min < SI5324_NC_LS_MIN) settings->nc1_ls_min = SI5324_NC_LS_MIN; if (settings->nc1_ls_min > 1 && (settings->nc1_ls_min & 0x1) == 1) settings->nc1_ls_min++; - settings->nc1_ls_max = settings->n1_hs_max / settings->n1_hs; + settings->nc1_ls_max = div64_u64(settings->n1_hs_max, settings->n1_hs); if (settings->nc1_ls_max > SI5324_NC_LS_MAX) settings->nc1_ls_max = SI5324_NC_LS_MAX; @@ -271,8 +272,8 @@ static int si5324_find_ncls(struct si5324_settingst *settings) settings->fosc = fosc_1 * settings->nc1_ls; pr_debug("Trying NCn_LS = %d: fosc = %dkHz.\n", settings->nc1_ls, - (u32)((settings->fosc >> SI5324_FIN_FOUT_SHIFT) / - 1000)); + (u32)(div64_u64((settings->fosc >> + SI5324_FIN_FOUT_SHIFT), 1000))); result = si5324_find_n2(settings); if (result) @@ -315,19 +316,19 @@ int si5324_calcfreqsettings(u32 clkinfreq, u32 clkoutfreq, u32 *clkactual, settings.fout = (u64)clkoutfreq << SI5324_FIN_FOUT_SHIFT; settings.best_delta_fout = settings.fout; - settings.n1_hs_min = (int)(SI5324_FOSC_MIN / clkoutfreq); + settings.n1_hs_min = (int)(div64_u64(SI5324_FOSC_MIN, clkoutfreq)); if (settings.n1_hs_min < SI5324_N1_HS_MIN * SI5324_NC_LS_MIN) settings.n1_hs_min = SI5324_N1_HS_MIN * SI5324_NC_LS_MIN; - settings.n1_hs_max = (int)(SI5324_FOSC_MAX / clkoutfreq); + settings.n1_hs_max = (int)(div64_u64(SI5324_FOSC_MAX, clkoutfreq)); if (settings.n1_hs_max > SI5324_N1_HS_MAX * SI5324_NC_LS_MAX) settings.n1_hs_max = SI5324_N1_HS_MAX * SI5324_NC_LS_MAX; - settings.n31_min = clkinfreq / SI5324_F3_MAX; + settings.n31_min = div64_u64(clkinfreq, SI5324_F3_MAX); if (settings.n31_min < SI5324_N3_MIN) settings.n31_min = SI5324_N3_MIN; - settings.n31_max = clkinfreq / SI5324_F3_MIN; + settings.n31_max = div64_u64(clkinfreq, SI5324_F3_MIN); if (settings.n31_max > SI5324_N3_MAX) settings.n31_max = SI5324_N3_MAX; -- 2.39.2