summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristoph Muellner <christoph.muellner@theobroma-systems.com>2019-04-02 16:50:41 +0200
committerChristoph Muellner <christoph.muellner@theobroma-systems.com>2019-10-02 00:39:30 +0200
commit05fe98613710e349ae6f1aa4f43890b6608b90bb (patch)
treee26f766db9e9b10bcca146a00ca27f97569bc58e
parent2b86d8ef434f33093b9942fcb54b32f920c958ab (diff)
rk: clk: Allow clk_i2s0_frac to violate precision restriction.
The fraction approximation code for rockchip frac dividers impose the following requirement (as noted in a driver comment): fractional divider must set that denominator is 20 times larger than numerator to generate precise clock frequency. Additionally the frac driver limits the maximum input frequency to 600 MHz. This limitation can be achieved by using the integer divider (limiting to e.g. 400 MHz). Note, that both restrictions are not stated in the RK3399 TRM. The implication of these restrictions are, that the range of possible output frequencies is reduced quite drastically. This results in the problem, that clk_i2s0_frac cannot generate a clock of 24.56 MHz and thus audio on RK3399-Q7 is broken. Therefore this patch whitelists clk_i2s0_frac from the first restriction, similar to the exception for UART (in the same function). Signed-off-by: Christoph Muellner <christoph.muellner@theobroma-systems.com>
-rw-r--r--drivers/clk/rockchip/clk.c9
1 files changed, 8 insertions, 1 deletions
diff --git a/drivers/clk/rockchip/clk.c b/drivers/clk/rockchip/clk.c
index 3a6994ff9655..b46d3b052025 100644
--- a/drivers/clk/rockchip/clk.c
+++ b/drivers/clk/rockchip/clk.c
@@ -207,7 +207,14 @@ static void rockchip_fractional_approximation(struct clk_hw *hw,
}
}
- if (*parent_rate < rate * 20) {
+ /*
+ * Check again if parent rate < rate x 20.
+ * Note that this is needed, because we might have changed
+ * the parent rate above.
+ */
+ if (*parent_rate < rate * 20 &&
+ /* Whitelist clocks, where we can accept imprecisions. */
+ !strstr(clk_hw_get_name(hw), "clk_i2s0_frac")) {
pr_warn("%s p_rate(%ld) is low than rate(%ld)*20, use integer or half-div\n",
clk_hw_get_name(hw), *parent_rate, rate);
*m = 0;