xref: /linux/drivers/clk/tegra/clk-utils.c (revision e7d759f31ca295d589f7420719c311870bb3166f)
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Copyright (c) 2018, NVIDIA CORPORATION.  All rights reserved.
4  */
5 
6 #include <asm/div64.h>
7 
8 #include "clk.h"
9 
10 #define div_mask(w) ((1 << (w)) - 1)
11 
12 int div_frac_get(unsigned long rate, unsigned parent_rate, u8 width,
13 		 u8 frac_width, u8 flags)
14 {
15 	u64 divider_ux1 = parent_rate;
16 	int mul;
17 
18 	if (!rate)
19 		return 0;
20 
21 	mul = 1 << frac_width;
22 
23 	if (!(flags & TEGRA_DIVIDER_INT))
24 		divider_ux1 *= mul;
25 
26 	if (flags & TEGRA_DIVIDER_ROUND_UP)
27 		divider_ux1 += rate - 1;
28 
29 	do_div(divider_ux1, rate);
30 
31 	if (flags & TEGRA_DIVIDER_INT)
32 		divider_ux1 *= mul;
33 
34 	if (divider_ux1 < mul)
35 		return 0;
36 
37 	divider_ux1 -= mul;
38 
39 	if (divider_ux1 > div_mask(width))
40 		return div_mask(width);
41 
42 	return divider_ux1;
43 }
44