Commit 82f53f9e authored by Andy Shevchenko's avatar Andy Shevchenko Committed by Stephen Boyd
Browse files

clk: fractional-divider: Introduce POWER_OF_TWO_PS flag



The newly introduced POWER_OF_TWO_PS flag, when set, makes the flow
to skip the assumption that the caller will use an additional 2^scale
prescaler to get the desired clock rate.

Reported-by: default avatarLiu Ying <victor.liu@nxp.com>
Signed-off-by: default avatarAndy Shevchenko <andriy.shevchenko@linux.intel.com>
Link: https://lore.kernel.org/r/20210812170025.67074-3-andriy.shevchenko@linux.intel.com


Signed-off-by: default avatarStephen Boyd <sboyd@kernel.org>
parent 928f9e26
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -434,8 +434,8 @@ static int register_device_clock(struct acpi_device *adev,
		if (!clk_name)
			return -ENOMEM;
		clk = clk_register_fractional_divider(NULL, clk_name, parent,
						      0, prv_base,
						      1, 15, 16, 15, 0, NULL);
						      CLK_FRAC_DIVIDER_POWER_OF_TWO_PS,
						      prv_base, 1, 15, 16, 15, 0, NULL);
		parent = clk_name;

		clk_name = kasprintf(GFP_KERNEL, "%s-update", devname);
+6 −4
Original line number Diff line number Diff line
@@ -76,16 +76,18 @@ void clk_fractional_divider_general_approximation(struct clk_hw *hw,
						  unsigned long *m, unsigned long *n)
{
	struct clk_fractional_divider *fd = to_clk_fd(hw);
	unsigned long scale;

	/*
	 * Get rate closer to *parent_rate to guarantee there is no overflow
	 * for m and n. In the result it will be the nearest rate left shifted
	 * by (scale - fd->nwidth) bits.
	 */
	scale = fls_long(*parent_rate / rate - 1);
	if (fd->flags & CLK_FRAC_DIVIDER_POWER_OF_TWO_PS) {
		unsigned long scale = fls_long(*parent_rate / rate - 1);

		if (scale > fd->nwidth)
			rate <<= scale - fd->nwidth;
	}

	rational_best_approximation(rate, *parent_rate,
			GENMASK(fd->mwidth - 1, 0), GENMASK(fd->nwidth - 1, 0),
+2 −1
Original line number Diff line number Diff line
@@ -301,7 +301,8 @@ static int intel_lpss_register_clock_divider(struct intel_lpss *lpss,

	snprintf(name, sizeof(name), "%s-div", devname);
	tmp = clk_register_fractional_divider(NULL, name, __clk_get_name(tmp),
					      0, lpss->priv, 1, 15, 16, 15, 0,
					      CLK_FRAC_DIVIDER_POWER_OF_TWO_PS,
					      lpss->priv, 1, 15, 16, 15, 0,
					      NULL);
	if (IS_ERR(tmp))
		return PTR_ERR(tmp);
+7 −0
Original line number Diff line number Diff line
@@ -1001,6 +1001,12 @@ struct clk_hw *devm_clk_hw_register_fixed_factor(struct device *dev,
 * CLK_FRAC_DIVIDER_BIG_ENDIAN - By default little endian register accesses are
 *	used for the divider register.  Setting this flag makes the register
 *	accesses big endian.
 * CLK_FRAC_DIVIDER_POWER_OF_TWO_PS - By default the resulting fraction might
 *	be saturated and the caller will get quite far from the good enough
 *	approximation. Instead the caller may require, by setting this flag,
 *	to shift left by a few bits in case, when the asked one is quite small
 *	to satisfy the desired range of denominator. It assumes that on the
 *	caller's side the power-of-two capable prescaler exists.
 */
struct clk_fractional_divider {
	struct clk_hw	hw;
@@ -1022,6 +1028,7 @@ struct clk_fractional_divider {

#define CLK_FRAC_DIVIDER_ZERO_BASED		BIT(0)
#define CLK_FRAC_DIVIDER_BIG_ENDIAN		BIT(1)
#define CLK_FRAC_DIVIDER_POWER_OF_TWO_PS	BIT(2)

struct clk *clk_register_fractional_divider(struct device *dev,
		const char *name, const char *parent_name, unsigned long flags,