summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Documentation/devicetree/bindings/clock/microchip,mpfs-ccc.yaml6
-rw-r--r--Documentation/devicetree/bindings/clock/microchip,mpfs-clkcfg.yaml16
-rw-r--r--drivers/clk/actions/owl-composite.c11
-rw-r--r--drivers/clk/actions/owl-divider.c17
-rw-r--r--drivers/clk/actions/owl-divider.h5
-rw-r--r--drivers/clk/clk-bm1880.c13
-rw-r--r--drivers/clk/clk-loongson1.c5
-rw-r--r--drivers/clk/clk-milbeaut.c15
-rw-r--r--drivers/clk/clk-versaclock3.c7
-rw-r--r--drivers/clk/hisilicon/clkdivider-hi6220.c6
-rw-r--r--drivers/clk/imx/clk-fracn-gppll.c4
-rw-r--r--drivers/clk/microchip/Kconfig4
-rw-r--r--drivers/clk/microchip/clk-core.c36
-rw-r--r--drivers/clk/nuvoton/clk-ma35d1-divider.c7
-rw-r--r--drivers/clk/nxp/clk-lpc32xx.c6
-rw-r--r--drivers/clk/rockchip/clk.c2
-rw-r--r--drivers/clk/sophgo/clk-cv18xx-ip.c154
-rw-r--r--drivers/clk/sophgo/clk-sg2042-clkgen.c15
-rw-r--r--drivers/clk/sprd/div.c6
-rw-r--r--drivers/clk/stm32/clk-stm32-core.c42
-rw-r--r--drivers/clk/sunxi-ng/ccu_div.c25
-rw-r--r--drivers/clk/sunxi-ng/ccu_mp.c26
-rw-r--r--drivers/clk/sunxi-ng/ccu_mult.c16
-rw-r--r--drivers/clk/sunxi-ng/ccu_mux.c49
-rw-r--r--drivers/clk/sunxi-ng/ccu_mux.h8
-rw-r--r--drivers/clk/sunxi-ng/ccu_nkm.c25
-rw-r--r--drivers/clk/x86/clk-cgu.c6
-rw-r--r--drivers/clk/zynqmp/divider.c5
-rw-r--r--drivers/rtc/rtc-ac100.c75
29 files changed, 283 insertions, 329 deletions
diff --git a/Documentation/devicetree/bindings/clock/microchip,mpfs-ccc.yaml b/Documentation/devicetree/bindings/clock/microchip,mpfs-ccc.yaml
index f1770360798f..9a6b50527c42 100644
--- a/Documentation/devicetree/bindings/clock/microchip,mpfs-ccc.yaml
+++ b/Documentation/devicetree/bindings/clock/microchip,mpfs-ccc.yaml
@@ -17,7 +17,11 @@ description: |
properties:
compatible:
- const: microchip,mpfs-ccc
+ oneOf:
+ - items:
+ - const: microchip,pic64gx-ccc
+ - const: microchip,mpfs-ccc
+ - const: microchip,mpfs-ccc
reg:
items:
diff --git a/Documentation/devicetree/bindings/clock/microchip,mpfs-clkcfg.yaml b/Documentation/devicetree/bindings/clock/microchip,mpfs-clkcfg.yaml
index ee4f31596d97..a23703c281d1 100644
--- a/Documentation/devicetree/bindings/clock/microchip,mpfs-clkcfg.yaml
+++ b/Documentation/devicetree/bindings/clock/microchip,mpfs-clkcfg.yaml
@@ -19,7 +19,11 @@ description: |
properties:
compatible:
- const: microchip,mpfs-clkcfg
+ oneOf:
+ - items:
+ - const: microchip,pic64gx-clkcfg
+ - const: microchip,mpfs-clkcfg
+ - const: microchip,mpfs-clkcfg
reg:
oneOf:
@@ -69,6 +73,16 @@ required:
- clocks
- '#clock-cells'
+if:
+ properties:
+ compatible:
+ contains:
+ const: microchip,pic64gx-clkcfg
+then:
+ properties:
+ reg:
+ maxItems: 1
+
additionalProperties: false
examples:
diff --git a/drivers/clk/actions/owl-composite.c b/drivers/clk/actions/owl-composite.c
index 00b74f8bc437..9540444307d6 100644
--- a/drivers/clk/actions/owl-composite.c
+++ b/drivers/clk/actions/owl-composite.c
@@ -57,15 +57,10 @@ static int owl_comp_div_determine_rate(struct clk_hw *hw,
struct clk_rate_request *req)
{
struct owl_composite *comp = hw_to_owl_comp(hw);
- long rate;
-
- rate = owl_divider_helper_round_rate(&comp->common, &comp->rate.div_hw,
- req->rate, &req->best_parent_rate);
- if (rate < 0)
- return rate;
+ struct owl_divider_hw *div = &comp->rate.div_hw;
- req->rate = rate;
- return 0;
+ return divider_determine_rate(&comp->common.hw, req, div->table,
+ div->width, div->div_flags);
}
static unsigned long owl_comp_div_recalc_rate(struct clk_hw *hw,
diff --git a/drivers/clk/actions/owl-divider.c b/drivers/clk/actions/owl-divider.c
index 118f1393c678..316ace80e87e 100644
--- a/drivers/clk/actions/owl-divider.c
+++ b/drivers/clk/actions/owl-divider.c
@@ -13,26 +13,13 @@
#include "owl-divider.h"
-long owl_divider_helper_round_rate(struct owl_clk_common *common,
- const struct owl_divider_hw *div_hw,
- unsigned long rate,
- unsigned long *parent_rate)
-{
- return divider_round_rate(&common->hw, rate, parent_rate,
- div_hw->table, div_hw->width,
- div_hw->div_flags);
-}
-
static int owl_divider_determine_rate(struct clk_hw *hw,
struct clk_rate_request *req)
{
struct owl_divider *div = hw_to_owl_divider(hw);
- req->rate = owl_divider_helper_round_rate(&div->common, &div->div_hw,
- req->rate,
- &req->best_parent_rate);
-
- return 0;
+ return divider_determine_rate(hw, req, div->div_hw.table,
+ div->div_hw.width, div->div_hw.div_flags);
}
unsigned long owl_divider_helper_recalc_rate(struct owl_clk_common *common,
diff --git a/drivers/clk/actions/owl-divider.h b/drivers/clk/actions/owl-divider.h
index d76f58782c52..1d3bb4e5898a 100644
--- a/drivers/clk/actions/owl-divider.h
+++ b/drivers/clk/actions/owl-divider.h
@@ -56,11 +56,6 @@ static inline struct owl_divider *hw_to_owl_divider(struct clk_hw *hw)
return container_of(common, struct owl_divider, common);
}
-long owl_divider_helper_round_rate(struct owl_clk_common *common,
- const struct owl_divider_hw *div_hw,
- unsigned long rate,
- unsigned long *parent_rate);
-
unsigned long owl_divider_helper_recalc_rate(struct owl_clk_common *common,
const struct owl_divider_hw *div_hw,
unsigned long parent_rate);
diff --git a/drivers/clk/clk-bm1880.c b/drivers/clk/clk-bm1880.c
index dac190bc6e19..1bdceb36fa87 100644
--- a/drivers/clk/clk-bm1880.c
+++ b/drivers/clk/clk-bm1880.c
@@ -621,18 +621,11 @@ static int bm1880_clk_div_determine_rate(struct clk_hw *hw,
val = readl(reg_addr) >> div->shift;
val &= clk_div_mask(div->width);
- req->rate = divider_ro_round_rate(hw, req->rate,
- &req->best_parent_rate,
- div->table,
- div->width, div->flags, val);
-
- return 0;
+ return divider_ro_determine_rate(hw, req, div->table,
+ div->width, div->flags, val);
}
- req->rate = divider_round_rate(hw, req->rate, &req->best_parent_rate,
- div->table, div->width, div->flags);
-
- return 0;
+ return divider_determine_rate(hw, req, div->table, div->width, div->flags);
}
static int bm1880_clk_div_set_rate(struct clk_hw *hw, unsigned long rate,
diff --git a/drivers/clk/clk-loongson1.c b/drivers/clk/clk-loongson1.c
index f9f060d08a5f..1674181a1107 100644
--- a/drivers/clk/clk-loongson1.c
+++ b/drivers/clk/clk-loongson1.c
@@ -99,10 +99,7 @@ static int ls1x_divider_determine_rate(struct clk_hw *hw,
struct ls1x_clk *ls1x_clk = to_ls1x_clk(hw);
const struct ls1x_clk_div_data *d = ls1x_clk->data;
- req->rate = divider_round_rate(hw, req->rate, &req->best_parent_rate,
- d->table, d->width, d->flags);
-
- return 0;
+ return divider_determine_rate(hw, req, d->table, d->width, d->flags);
}
static int ls1x_divider_set_rate(struct clk_hw *hw, unsigned long rate,
diff --git a/drivers/clk/clk-milbeaut.c b/drivers/clk/clk-milbeaut.c
index b4f9b7143eaa..45389db652e0 100644
--- a/drivers/clk/clk-milbeaut.c
+++ b/drivers/clk/clk-milbeaut.c
@@ -398,19 +398,12 @@ static int m10v_clk_divider_determine_rate(struct clk_hw *hw,
val = readl(divider->reg) >> divider->shift;
val &= clk_div_mask(divider->width);
- req->rate = divider_ro_round_rate(hw, req->rate,
- &req->best_parent_rate,
- divider->table,
- divider->width,
- divider->flags, val);
-
- return 0;
+ return divider_ro_determine_rate(hw, req, divider->table,
+ divider->width, divider->flags,
+ val);
}
- req->rate = divider_round_rate(hw, req->rate, &req->best_parent_rate,
- divider->table, divider->width, divider->flags);
-
- return 0;
+ return divider_determine_rate(hw, req, divider->table, divider->width, divider->flags);
}
static int m10v_clk_divider_set_rate(struct clk_hw *hw, unsigned long rate,
diff --git a/drivers/clk/clk-versaclock3.c b/drivers/clk/clk-versaclock3.c
index 1849863dbd67..27b6cf70f3ae 100644
--- a/drivers/clk/clk-versaclock3.c
+++ b/drivers/clk/clk-versaclock3.c
@@ -523,11 +523,8 @@ static int vc3_div_determine_rate(struct clk_hw *hw,
return 0;
}
- req->rate = divider_round_rate(hw, req->rate, &req->best_parent_rate,
- div_data->table,
- div_data->width, div_data->flags);
-
- return 0;
+ return divider_determine_rate(hw, req, div_data->table, div_data->width,
+ div_data->flags);
}
static int vc3_div_set_rate(struct clk_hw *hw, unsigned long rate,
diff --git a/drivers/clk/hisilicon/clkdivider-hi6220.c b/drivers/clk/hisilicon/clkdivider-hi6220.c
index 6bae18a84cb6..fd7ceb92d651 100644
--- a/drivers/clk/hisilicon/clkdivider-hi6220.c
+++ b/drivers/clk/hisilicon/clkdivider-hi6220.c
@@ -60,10 +60,8 @@ static int hi6220_clkdiv_determine_rate(struct clk_hw *hw,
{
struct hi6220_clk_divider *dclk = to_hi6220_clk_divider(hw);
- req->rate = divider_round_rate(hw, req->rate, &req->best_parent_rate, dclk->table,
- dclk->width, CLK_DIVIDER_ROUND_CLOSEST);
-
- return 0;
+ return divider_determine_rate(hw, req, dclk->table, dclk->width,
+ CLK_DIVIDER_ROUND_CLOSEST);
}
static int hi6220_clkdiv_set_rate(struct clk_hw *hw, unsigned long rate,
diff --git a/drivers/clk/imx/clk-fracn-gppll.c b/drivers/clk/imx/clk-fracn-gppll.c
index 090d60867250..6de5349adf70 100644
--- a/drivers/clk/imx/clk-fracn-gppll.c
+++ b/drivers/clk/imx/clk-fracn-gppll.c
@@ -88,7 +88,9 @@ static const struct imx_fracn_gppll_rate_table fracn_tbl[] = {
PLL_FRACN_GP(445333333U, 167, 0, 1, 0, 9),
PLL_FRACN_GP(400000000U, 200, 0, 1, 0, 12),
PLL_FRACN_GP(393216000U, 163, 84, 100, 0, 10),
- PLL_FRACN_GP(300000000U, 150, 0, 1, 0, 12)
+ PLL_FRACN_GP(332600000U, 138, 584, 1000, 0, 10),
+ PLL_FRACN_GP(300000000U, 150, 0, 1, 0, 12),
+ PLL_FRACN_GP(241900000U, 201, 584, 1000, 0, 20),
};
struct imx_fracn_gppll_clk imx_fracn_gppll = {
diff --git a/drivers/clk/microchip/Kconfig b/drivers/clk/microchip/Kconfig
index 1b9e43eb5497..0c03b14699bf 100644
--- a/drivers/clk/microchip/Kconfig
+++ b/drivers/clk/microchip/Kconfig
@@ -5,8 +5,8 @@ config COMMON_CLK_PIC32
config MCHP_CLK_MPFS
bool "Clk driver for PolarFire SoC"
- depends on ARCH_MICROCHIP_POLARFIRE || COMPILE_TEST
- default ARCH_MICROCHIP_POLARFIRE
+ depends on ARCH_MICROCHIP || COMPILE_TEST
+ default y
depends on MFD_SYSCON
select AUXILIARY_BUS
select REGMAP_MMIO
diff --git a/drivers/clk/microchip/clk-core.c b/drivers/clk/microchip/clk-core.c
index b34348d491f3..f467d7bc28c8 100644
--- a/drivers/clk/microchip/clk-core.c
+++ b/drivers/clk/microchip/clk-core.c
@@ -10,7 +10,6 @@
#include <linux/io.h>
#include <linux/iopoll.h>
#include <asm/mach-pic32/pic32.h>
-#include <asm/traps.h>
#include "clk-core.h"
@@ -283,14 +282,13 @@ static u8 roclk_get_parent(struct clk_hw *hw)
v = (readl(refo->ctrl_reg) >> REFO_SEL_SHIFT) & REFO_SEL_MASK;
- if (!refo->parent_map)
- return v;
-
- for (i = 0; i < clk_hw_get_num_parents(hw); i++)
- if (refo->parent_map[i] == v)
- return i;
+ if (refo->parent_map) {
+ for (i = 0; i < clk_hw_get_num_parents(hw); i++)
+ if (refo->parent_map[i] == v)
+ return i;
+ }
- return -EINVAL;
+ return v;
}
static unsigned long roclk_calc_rate(unsigned long parent_rate,
@@ -780,15 +778,6 @@ static unsigned long sclk_get_rate(struct clk_hw *hw, unsigned long parent_rate)
return parent_rate / div;
}
-static int sclk_determine_rate(struct clk_hw *hw,
- struct clk_rate_request *req)
-{
- req->rate = calc_best_divided_rate(req->rate, req->best_parent_rate,
- SLEW_SYSDIV, 1);
-
- return 0;
-}
-
static int sclk_set_rate(struct clk_hw *hw,
unsigned long rate, unsigned long parent_rate)
{
@@ -826,13 +815,13 @@ static u8 sclk_get_parent(struct clk_hw *hw)
v = (readl(sclk->mux_reg) >> OSC_CUR_SHIFT) & OSC_CUR_MASK;
- if (!sclk->parent_map)
- return v;
+ if (sclk->parent_map) {
+ for (i = 0; i < clk_hw_get_num_parents(hw); i++)
+ if (sclk->parent_map[i] == v)
+ return i;
+ }
- for (i = 0; i < clk_hw_get_num_parents(hw); i++)
- if (sclk->parent_map[i] == v)
- return i;
- return -EINVAL;
+ return v;
}
static int sclk_set_parent(struct clk_hw *hw, u8 index)
@@ -912,7 +901,6 @@ static int sclk_init(struct clk_hw *hw)
const struct clk_ops pic32_sclk_ops = {
.get_parent = sclk_get_parent,
.set_parent = sclk_set_parent,
- .determine_rate = sclk_determine_rate,
.set_rate = sclk_set_rate,
.recalc_rate = sclk_get_rate,
.init = sclk_init,
diff --git a/drivers/clk/nuvoton/clk-ma35d1-divider.c b/drivers/clk/nuvoton/clk-ma35d1-divider.c
index e39f53d5bf45..e992e7c30341 100644
--- a/drivers/clk/nuvoton/clk-ma35d1-divider.c
+++ b/drivers/clk/nuvoton/clk-ma35d1-divider.c
@@ -44,11 +44,8 @@ static int ma35d1_clkdiv_determine_rate(struct clk_hw *hw,
{
struct ma35d1_adc_clk_div *dclk = to_ma35d1_adc_clk_div(hw);
- req->rate = divider_round_rate(hw, req->rate, &req->best_parent_rate,
- dclk->table, dclk->width,
- CLK_DIVIDER_ROUND_CLOSEST);
-
- return 0;
+ return divider_determine_rate(hw, req, dclk->table, dclk->width,
+ CLK_DIVIDER_ROUND_CLOSEST);
}
static int ma35d1_clkdiv_set_rate(struct clk_hw *hw, unsigned long rate, unsigned long parent_rate)
diff --git a/drivers/clk/nxp/clk-lpc32xx.c b/drivers/clk/nxp/clk-lpc32xx.c
index 23f980cf6a2b..ae2fa5341a2e 100644
--- a/drivers/clk/nxp/clk-lpc32xx.c
+++ b/drivers/clk/nxp/clk-lpc32xx.c
@@ -975,10 +975,8 @@ static int clk_divider_determine_rate(struct clk_hw *hw,
return 0;
}
- req->rate = divider_round_rate(hw, req->rate, &req->best_parent_rate,
- divider->table, divider->width, divider->flags);
-
- return 0;
+ return divider_determine_rate(hw, req, divider->table, divider->width,
+ divider->flags);
}
static int clk_divider_set_rate(struct clk_hw *hw, unsigned long rate,
diff --git a/drivers/clk/rockchip/clk.c b/drivers/clk/rockchip/clk.c
index 2601df3b1066..9ac9d13e87de 100644
--- a/drivers/clk/rockchip/clk.c
+++ b/drivers/clk/rockchip/clk.c
@@ -693,7 +693,7 @@ void rockchip_clk_register_late_branches(struct device *dev,
break;
}
- if (!pdev)
+ if (IS_ERR_OR_NULL(pdev))
dev_err(dev, "failed to register device for clock %s\n", list->name);
}
}
diff --git a/drivers/clk/sophgo/clk-cv18xx-ip.c b/drivers/clk/sophgo/clk-cv18xx-ip.c
index c2b58faf0938..e936e3154003 100644
--- a/drivers/clk/sophgo/clk-cv18xx-ip.c
+++ b/drivers/clk/sophgo/clk-cv18xx-ip.c
@@ -152,28 +152,27 @@ static u32 div_helper_get_clockdiv(struct cv1800_clk_common *common,
return clockdiv;
}
-static u32 div_helper_round_rate(struct cv1800_clk_regfield *div,
- struct clk_hw *hw, struct clk_hw *parent,
- unsigned long rate, unsigned long *prate)
+static int div_helper_determine_rate(struct cv1800_clk_regfield *div,
+ struct clk_hw *hw,
+ struct clk_rate_request *req)
{
if (div->width == 0) {
if (div->initval <= 0)
- return DIV_ROUND_UP_ULL(*prate, 1);
+ req->rate = DIV_ROUND_UP_ULL(req->best_parent_rate, 1);
else
- return DIV_ROUND_UP_ULL(*prate, div->initval);
+ req->rate = DIV_ROUND_UP_ULL(req->best_parent_rate, div->initval);
+
+ return 0;
}
- return divider_round_rate_parent(hw, parent, rate, prate, NULL,
- div->width, div->flags);
+ return divider_determine_rate(hw, req, NULL, div->width, div->flags);
}
-static long div_round_rate(struct clk_hw *parent, unsigned long *parent_rate,
- unsigned long rate, int id, void *data)
+static int do_div_determine_rate(struct clk_rate_request *req, int id, void *data)
{
struct cv1800_clk_div *div = data;
- return div_helper_round_rate(&div->div, &div->common.hw, parent,
- rate, parent_rate);
+ return div_helper_determine_rate(&div->div, &div->common.hw, req);
}
static bool div_is_better_rate(struct cv1800_clk_common *common,
@@ -188,53 +187,60 @@ static bool div_is_better_rate(struct cv1800_clk_common *common,
static int mux_helper_determine_rate(struct cv1800_clk_common *common,
struct clk_rate_request *req,
- long (*round)(struct clk_hw *,
- unsigned long *,
- unsigned long,
- int,
- void *),
+ int (*round)(struct clk_rate_request *,
+ int,
+ void *),
void *data)
{
unsigned long best_parent_rate = 0, best_rate = 0;
struct clk_hw *best_parent, *hw = &common->hw;
unsigned int i;
+ int ret;
if (clk_hw_get_flags(hw) & CLK_SET_RATE_NO_REPARENT) {
- unsigned long adj_parent_rate;
+ struct clk_rate_request tmp_req = *req;
best_parent = clk_hw_get_parent(hw);
- best_parent_rate = clk_hw_get_rate(best_parent);
+ tmp_req.best_parent_hw = best_parent;
+ tmp_req.best_parent_rate = clk_hw_get_rate(best_parent);
- best_rate = round(best_parent, &adj_parent_rate,
- req->rate, -1, data);
+ ret = round(&tmp_req, -1, data);
+ if (ret)
+ return ret;
+
+ best_parent_rate = tmp_req.best_parent_rate;
+ best_rate = tmp_req.rate;
goto find;
}
for (i = 0; i < clk_hw_get_num_parents(hw); i++) {
- unsigned long tmp_rate, parent_rate;
+ struct clk_rate_request tmp_req = *req;
struct clk_hw *parent;
parent = clk_hw_get_parent_by_index(hw, i);
if (!parent)
continue;
- parent_rate = clk_hw_get_rate(parent);
+ tmp_req.best_parent_hw = parent;
+ tmp_req.best_parent_rate = clk_hw_get_rate(parent);
- tmp_rate = round(parent, &parent_rate, req->rate, i, data);
+ ret = round(&tmp_req, i, data);
+ if (ret)
+ continue;
- if (tmp_rate == req->rate) {
+ if (tmp_req.rate == req->rate) {
best_parent = parent;
- best_parent_rate = parent_rate;
- best_rate = tmp_rate;
+ best_parent_rate = tmp_req.best_parent_rate;
+ best_rate = tmp_req.rate;
goto find;
}
if (div_is_better_rate(common, req->rate,
- tmp_rate, best_rate)) {
+ tmp_req.rate, best_rate)) {
best_parent = parent;
- best_parent_rate = parent_rate;
- best_rate = tmp_rate;
+ best_parent_rate = tmp_req.best_parent_rate;
+ best_rate = tmp_req.rate;
}
}
@@ -254,7 +260,7 @@ static int div_determine_rate(struct clk_hw *hw,
struct cv1800_clk_div *div = hw_to_cv1800_clk_div(hw);
return mux_helper_determine_rate(&div->common, req,
- div_round_rate, div);
+ do_div_determine_rate, div);
}
static unsigned long div_recalc_rate(struct clk_hw *hw,
@@ -301,24 +307,28 @@ hw_to_cv1800_clk_bypass_div(struct clk_hw *hw)
return container_of(div, struct cv1800_clk_bypass_div, div);
}
-static long bypass_div_round_rate(struct clk_hw *parent,
- unsigned long *parent_rate,
- unsigned long rate, int id, void *data)
+static int do_bypass_div_determine_rate(struct clk_rate_request *req, int id,
+ void *data)
{
struct cv1800_clk_bypass_div *div = data;
if (id == -1) {
- if (cv1800_clk_checkbit(&div->div.common, &div->bypass))
- return *parent_rate;
- else
- return div_round_rate(parent, parent_rate, rate,
- -1, &div->div);
+ if (cv1800_clk_checkbit(&div->div.common, &div->bypass)) {
+ req->rate = req->best_parent_rate;
+
+ return 0;
+ }
+
+ return do_div_determine_rate(req, -1, &div->div);
}
- if (id == 0)
- return *parent_rate;
+ if (id == 0) {
+ req->rate = req->best_parent_rate;
+
+ return 0;
+ }
- return div_round_rate(parent, parent_rate, rate, id - 1, &div->div);
+ return do_div_determine_rate(req, id - 1, &div->div);
}
static int bypass_div_determine_rate(struct clk_hw *hw,
@@ -327,7 +337,7 @@ static int bypass_div_determine_rate(struct clk_hw *hw,
struct cv1800_clk_bypass_div *div = hw_to_cv1800_clk_bypass_div(hw);
return mux_helper_determine_rate(&div->div.common, req,
- bypass_div_round_rate, div);
+ do_bypass_div_determine_rate, div);
}
static unsigned long bypass_div_recalc_rate(struct clk_hw *hw,
@@ -414,13 +424,11 @@ static int mux_is_enabled(struct clk_hw *hw)
return cv1800_clk_checkbit(&mux->common, &mux->gate);
}
-static long mux_round_rate(struct clk_hw *parent, unsigned long *parent_rate,
- unsigned long rate, int id, void *data)
+static int do_mux_determine_rate(struct clk_rate_request *req, int id, void *data)
{
struct cv1800_clk_mux *mux = data;
- return div_helper_round_rate(&mux->div, &mux->common.hw, parent,
- rate, parent_rate);
+ return div_helper_determine_rate(&mux->div, &mux->common.hw, req);
}
static int mux_determine_rate(struct clk_hw *hw,
@@ -429,7 +437,7 @@ static int mux_determine_rate(struct clk_hw *hw,
struct cv1800_clk_mux *mux = hw_to_cv1800_clk_mux(hw);
return mux_helper_determine_rate(&mux->common, req,
- mux_round_rate, mux);
+ do_mux_determine_rate, mux);
}
static unsigned long mux_recalc_rate(struct clk_hw *hw,
@@ -512,24 +520,28 @@ hw_to_cv1800_clk_bypass_mux(struct clk_hw *hw)
return container_of(mux, struct cv1800_clk_bypass_mux, mux);
}
-static long bypass_mux_round_rate(struct clk_hw *parent,
- unsigned long *parent_rate,
- unsigned long rate, int id, void *data)
+static int do_bypass_mux_determine_rate(struct clk_rate_request *req, int id,
+ void *data)
{
struct cv1800_clk_bypass_mux *mux = data;
if (id == -1) {
- if (cv1800_clk_checkbit(&mux->mux.common, &mux->bypass))
- return *parent_rate;
- else
- return mux_round_rate(parent, parent_rate, rate,
- -1, &mux->mux);
+ if (cv1800_clk_checkbit(&mux->mux.common, &mux->bypass)) {
+ req->rate = req->best_parent_rate;
+
+ return 0;
+ }
+
+ return do_mux_determine_rate(req, -1, &mux->mux);
}
- if (id == 0)
- return *parent_rate;
+ if (id == 0) {
+ req->rate = req->best_parent_rate;
+
+ return 0;
+ }
- return mux_round_rate(parent, parent_rate, rate, id - 1, &mux->mux);
+ return do_mux_determine_rate(req, id - 1, &mux->mux);
}
static int bypass_mux_determine_rate(struct clk_hw *hw,
@@ -538,7 +550,7 @@ static int bypass_mux_determine_rate(struct clk_hw *hw,
struct cv1800_clk_bypass_mux *mux = hw_to_cv1800_clk_bypass_mux(hw);
return mux_helper_determine_rate(&mux->mux.common, req,
- bypass_mux_round_rate, mux);
+ do_bypass_mux_determine_rate, mux);
}
static unsigned long bypass_mux_recalc_rate(struct clk_hw *hw,
@@ -639,27 +651,31 @@ static int mmux_is_enabled(struct clk_hw *hw)
return cv1800_clk_checkbit(&mmux->common, &mmux->gate);
}
-static long mmux_round_rate(struct clk_hw *parent, unsigned long *parent_rate,
- unsigned long rate, int id, void *data)
+static int do_mmux_determine_rate(struct clk_rate_request *req, int id, void *data)
{
struct cv1800_clk_mmux *mmux = data;
s8 div_id;
if (id == -1) {
- if (cv1800_clk_checkbit(&mmux->common, &mmux->bypass))
- return *parent_rate;
+ if (cv1800_clk_checkbit(&mmux->common, &mmux->bypass)) {
+ req->rate = req->best_parent_rate;
+
+ return 0;
+ }
id = mmux_get_parent_id(mmux);
}
div_id = mmux->parent2sel[id];
- if (div_id < 0)
- return *parent_rate;
+ if (div_id < 0) {
+ req->rate = req->best_parent_rate;
+
+ return 0;
+ }
- return div_helper_round_rate(&mmux->div[div_id],
- &mmux->common.hw, parent,
- rate, parent_rate);
+ return div_helper_determine_rate(&mmux->div[div_id], &mmux->common.hw,
+ req);
}
static int mmux_determine_rate(struct clk_hw *hw,
@@ -668,7 +684,7 @@ static int mmux_determine_rate(struct clk_hw *hw,
struct cv1800_clk_mmux *mmux = hw_to_cv1800_clk_mmux(hw);
return mux_helper_determine_rate(&mmux->common, req,
- mmux_round_rate, mmux);
+ do_mmux_determine_rate, mmux);
}
static unsigned long mmux_recalc_rate(struct clk_hw *hw,
diff --git a/drivers/clk/sophgo/clk-sg2042-clkgen.c b/drivers/clk/sophgo/clk-sg2042-clkgen.c
index 683661b71787..9725ac4e050a 100644
--- a/drivers/clk/sophgo/clk-sg2042-clkgen.c
+++ b/drivers/clk/sophgo/clk-sg2042-clkgen.c
@@ -180,7 +180,6 @@ static int sg2042_clk_divider_determine_rate(struct clk_hw *hw,
struct clk_rate_request *req)
{
struct sg2042_divider_clock *divider = to_sg2042_clk_divider(hw);
- unsigned long ret_rate;
u32 bestdiv;
/* if read only, just return current value */
@@ -191,17 +190,13 @@ static int sg2042_clk_divider_determine_rate(struct clk_hw *hw,
bestdiv = readl(divider->reg) >> divider->shift;
bestdiv &= clk_div_mask(divider->width);
}
- ret_rate = DIV_ROUND_UP_ULL((u64)req->best_parent_rate, bestdiv);
- } else {
- ret_rate = divider_round_rate(hw, req->rate, &req->best_parent_rate, NULL,
- divider->width, divider->div_flags);
- }
+ req->rate = DIV_ROUND_UP_ULL((u64)req->best_parent_rate, bestdiv);
- pr_debug("--> %s: divider_round_rate: val = %ld\n",
- clk_hw_get_name(hw), ret_rate);
- req->rate = ret_rate;
+ return 0;
+ }
- return 0;
+ return divider_determine_rate(hw, req, NULL, divider->width,
+ divider->div_flags);
}
static int sg2042_clk_divider_set_rate(struct clk_hw *hw,
diff --git a/drivers/clk/sprd/div.c b/drivers/clk/sprd/div.c
index 013423881968..cd57163a7204 100644
--- a/drivers/clk/sprd/div.c
+++ b/drivers/clk/sprd/div.c
@@ -14,11 +14,7 @@ static int sprd_div_determine_rate(struct clk_hw *hw,
{
struct sprd_div *cd = hw_to_sprd_div(hw);
- req->rate = divider_round_rate(&cd->common.hw, req->rate,
- &req->best_parent_rate,
- NULL, cd->div.width, 0);
-
- return 0;
+ return divider_determine_rate(&cd->common.hw, req, NULL, cd->div.width, 0);
}
unsigned long sprd_div_helper_recalc_rate(struct sprd_clk_common *common,
diff --git a/drivers/clk/stm32/clk-stm32-core.c b/drivers/clk/stm32/clk-stm32-core.c
index 72825b9c36a4..e921c25a929c 100644
--- a/drivers/clk/stm32/clk-stm32-core.c
+++ b/drivers/clk/stm32/clk-stm32-core.c
@@ -369,22 +369,14 @@ static int clk_stm32_divider_determine_rate(struct clk_hw *hw,
val = readl(div->base + divider->offset) >> divider->shift;
val &= clk_div_mask(divider->width);
- req->rate = divider_ro_round_rate(hw, req->rate,
- &req->best_parent_rate,
- divider->table,
- divider->width,
- divider->flags, val);
-
- return 0;
+ return divider_ro_determine_rate(hw, req,
+ divider->table,
+ divider->width,
+ divider->flags, val);
}
- req->rate = divider_round_rate_parent(hw, clk_hw_get_parent(hw),
- req->rate,
- &req->best_parent_rate,
- divider->table,
- divider->width, divider->flags);
-
- return 0;
+ return divider_determine_rate(hw, req, divider->table, divider->width,
+ divider->flags);
}
static unsigned long clk_stm32_divider_recalc_rate(struct clk_hw *hw,
@@ -441,7 +433,6 @@ static int clk_stm32_composite_determine_rate(struct clk_hw *hw,
{
struct clk_stm32_composite *composite = to_clk_stm32_composite(hw);
const struct stm32_div_cfg *divider;
- long rate;
if (composite->div_id == NO_STM32_DIV)
return 0;
@@ -455,24 +446,13 @@ static int clk_stm32_composite_determine_rate(struct clk_hw *hw,
val = readl(composite->base + divider->offset) >> divider->shift;
val &= clk_div_mask(divider->width);
- rate = divider_ro_round_rate(hw, req->rate, &req->best_parent_rate,
- divider->table, divider->width, divider->flags,
- val);
- if (rate < 0)
- return rate;
-
- req->rate = rate;
- return 0;
+ return divider_ro_determine_rate(hw, req, divider->table,
+ divider->width, divider->flags,
+ val);
}
- rate = divider_round_rate_parent(hw, clk_hw_get_parent(hw),
- req->rate, &req->best_parent_rate,
- divider->table, divider->width, divider->flags);
- if (rate < 0)
- return rate;
-
- req->rate = rate;
- return 0;
+ return divider_determine_rate(hw, req, divider->table, divider->width,
+ divider->flags);
}
static u8 clk_stm32_composite_get_parent(struct clk_hw *hw)
diff --git a/drivers/clk/sunxi-ng/ccu_div.c b/drivers/clk/sunxi-ng/ccu_div.c
index 916d6da6d8a3..62d680ccb524 100644
--- a/drivers/clk/sunxi-ng/ccu_div.c
+++ b/drivers/clk/sunxi-ng/ccu_div.c
@@ -10,26 +10,25 @@
#include "ccu_gate.h"
#include "ccu_div.h"
-static unsigned long ccu_div_round_rate(struct ccu_mux_internal *mux,
- struct clk_hw *parent,
- unsigned long *parent_rate,
- unsigned long rate,
- void *data)
+static int ccu_div_determine_rate_helper(struct ccu_mux_internal *mux,
+ struct clk_rate_request *req,
+ void *data)
{
struct ccu_div *cd = data;
+ int ret;
if (cd->common.features & CCU_FEATURE_FIXED_POSTDIV)
- rate *= cd->fixed_post_div;
+ req->rate *= cd->fixed_post_div;
- rate = divider_round_rate_parent(&cd->common.hw, parent,
- rate, parent_rate,
- cd->div.table, cd->div.width,
- cd->div.flags);
+ ret = divider_determine_rate(&cd->common.hw, req, cd->div.table,
+ cd->div.width, cd->div.flags);
+ if (ret)
+ return ret;
if (cd->common.features & CCU_FEATURE_FIXED_POSTDIV)
- rate /= cd->fixed_post_div;
+ req->rate /= cd->fixed_post_div;
- return rate;
+ return 0;
}
static void ccu_div_disable(struct clk_hw *hw)
@@ -82,7 +81,7 @@ static int ccu_div_determine_rate(struct clk_hw *hw,
struct ccu_div *cd = hw_to_ccu_div(hw);
return ccu_mux_helper_determine_rate(&cd->common, &cd->mux,
- req, ccu_div_round_rate, cd);
+ req, ccu_div_determine_rate_helper, cd);
}
static int ccu_div_set_rate(struct clk_hw *hw, unsigned long rate,
diff --git a/drivers/clk/sunxi-ng/ccu_mp.c b/drivers/clk/sunxi-ng/ccu_mp.c
index 4221b1888b38..7cdb0eedc69b 100644
--- a/drivers/clk/sunxi-ng/ccu_mp.c
+++ b/drivers/clk/sunxi-ng/ccu_mp.c
@@ -103,11 +103,9 @@ static unsigned long ccu_mp_find_best_with_parent_adj(struct clk_hw *hw,
return best_rate;
}
-static unsigned long ccu_mp_round_rate(struct ccu_mux_internal *mux,
- struct clk_hw *hw,
- unsigned long *parent_rate,
- unsigned long rate,
- void *data)
+static int ccu_mp_determine_rate_helper(struct ccu_mux_internal *mux,
+ struct clk_rate_request *req,
+ void *data)
{
struct ccu_mp *cmp = data;
unsigned int max_m, max_p;
@@ -115,7 +113,7 @@ static unsigned long ccu_mp_round_rate(struct ccu_mux_internal *mux,
bool shift = true;
if (cmp->common.features & CCU_FEATURE_FIXED_POSTDIV)
- rate *= cmp->fixed_post_div;
+ req->rate *= cmp->fixed_post_div;
if (cmp->common.features & CCU_FEATURE_DUAL_DIV)
shift = false;
@@ -127,17 +125,19 @@ static unsigned long ccu_mp_round_rate(struct ccu_mux_internal *mux,
max_p = cmp->p.max ?: 1 << cmp->p.width;
if (!clk_hw_can_set_rate_parent(&cmp->common.hw)) {
- rate = ccu_mp_find_best(*parent_rate, rate, max_m, max_p, shift,
- &m, &p);
+ req->rate = ccu_mp_find_best(req->best_parent_rate, req->rate,
+ max_m, max_p, shift, &m, &p);
} else {
- rate = ccu_mp_find_best_with_parent_adj(hw, parent_rate, rate,
- max_m, max_p, shift);
+ req->rate = ccu_mp_find_best_with_parent_adj(req->best_parent_hw,
+ &req->best_parent_rate,
+ req->rate, max_m, max_p,
+ shift);
}
if (cmp->common.features & CCU_FEATURE_FIXED_POSTDIV)
- rate /= cmp->fixed_post_div;
+ req->rate /= cmp->fixed_post_div;
- return rate;
+ return 0;
}
static void ccu_mp_disable(struct clk_hw *hw)
@@ -201,7 +201,7 @@ static int ccu_mp_determine_rate(struct clk_hw *hw,
struct ccu_mp *cmp = hw_to_ccu_mp(hw);
return ccu_mux_helper_determine_rate(&cmp->common, &cmp->mux,
- req, ccu_mp_round_rate, cmp);
+ req, ccu_mp_determine_rate_helper, cmp);
}
static int ccu_mp_set_rate(struct clk_hw *hw, unsigned long rate,
diff --git a/drivers/clk/sunxi-ng/ccu_mult.c b/drivers/clk/sunxi-ng/ccu_mult.c
index 8d5720f3dec1..3fc81e7de6e9 100644
--- a/drivers/clk/sunxi-ng/ccu_mult.c
+++ b/drivers/clk/sunxi-ng/ccu_mult.c
@@ -29,11 +29,9 @@ static void ccu_mult_find_best(unsigned long parent, unsigned long rate,
mult->mult = _mult;
}
-static unsigned long ccu_mult_round_rate(struct ccu_mux_internal *mux,
- struct clk_hw *parent,
- unsigned long *parent_rate,
- unsigned long rate,
- void *data)
+static int ccu_mult_determine_rate_helper(struct ccu_mux_internal *mux,
+ struct clk_rate_request *req,
+ void *data)
{
struct ccu_mult *cm = data;
struct _ccu_mult _cm;
@@ -45,9 +43,11 @@ static unsigned long ccu_mult_round_rate(struct ccu_mux_internal *mux,
else
_cm.max = (1 << cm->mult.width) + cm->mult.offset - 1;
- ccu_mult_find_best(*parent_rate, rate, &_cm);
+ ccu_mult_find_best(req->best_parent_rate, req->rate, &_cm);
- return *parent_rate * _cm.mult;
+ req->rate = req->best_parent_rate * _cm.mult;
+
+ return 0;
}
static void ccu_mult_disable(struct clk_hw *hw)
@@ -97,7 +97,7 @@ static int ccu_mult_determine_rate(struct clk_hw *hw,
struct ccu_mult *cm = hw_to_ccu_mult(hw);
return ccu_mux_helper_determine_rate(&cm->common, &cm->mux,
- req, ccu_mult_round_rate, cm);
+ req, ccu_mult_determine_rate_helper, cm);
}
static int ccu_mult_set_rate(struct clk_hw *hw, unsigned long rate,
diff --git a/drivers/clk/sunxi-ng/ccu_mux.c b/drivers/clk/sunxi-ng/ccu_mux.c
index 74f9e98a5d35..766f27cff748 100644
--- a/drivers/clk/sunxi-ng/ccu_mux.c
+++ b/drivers/clk/sunxi-ng/ccu_mux.c
@@ -79,41 +79,46 @@ static unsigned long ccu_mux_helper_unapply_prediv(struct ccu_common *common,
int ccu_mux_helper_determine_rate(struct ccu_common *common,
struct ccu_mux_internal *cm,
struct clk_rate_request *req,
- unsigned long (*round)(struct ccu_mux_internal *,
- struct clk_hw *,
- unsigned long *,
- unsigned long,
- void *),
+ int (*round)(struct ccu_mux_internal *,
+ struct clk_rate_request *,
+ void *),
void *data)
{
unsigned long best_parent_rate = 0, best_rate = 0;
struct clk_hw *best_parent, *hw = &common->hw;
unsigned int i;
+ int ret;
if (clk_hw_get_flags(hw) & CLK_SET_RATE_NO_REPARENT) {
- unsigned long adj_parent_rate;
+ struct clk_rate_request adj_req = *req;
best_parent = clk_hw_get_parent(hw);
best_parent_rate = clk_hw_get_rate(best_parent);
- adj_parent_rate = ccu_mux_helper_apply_prediv(common, cm, -1,
- best_parent_rate);
- best_rate = round(cm, best_parent, &adj_parent_rate,
- req->rate, data);
+ adj_req.best_parent_hw = best_parent;
+ adj_req.best_parent_rate = ccu_mux_helper_apply_prediv(common, cm, -1,
+ best_parent_rate);
+
+ ret = round(cm, &adj_req, data);
+ if (ret)
+ return ret;
+
+ best_rate = adj_req.rate;
/*
- * adj_parent_rate might have been modified by our clock.
+ * best_parent_rate might have been modified by our clock.
* Unapply the pre-divider if there's one, and give
* the actual frequency the parent needs to run at.
*/
best_parent_rate = ccu_mux_helper_unapply_prediv(common, cm, -1,
- adj_parent_rate);
+ adj_req.best_parent_rate);
goto out;
}
for (i = 0; i < clk_hw_get_num_parents(hw); i++) {
- unsigned long tmp_rate, parent_rate;
+ struct clk_rate_request tmp_req = *req;
+ unsigned long parent_rate;
struct clk_hw *parent;
parent = clk_hw_get_parent_by_index(hw, i);
@@ -123,7 +128,12 @@ int ccu_mux_helper_determine_rate(struct ccu_common *common,
parent_rate = ccu_mux_helper_apply_prediv(common, cm, i,
clk_hw_get_rate(parent));
- tmp_rate = round(cm, parent, &parent_rate, req->rate, data);
+ tmp_req.best_parent_hw = parent;
+ tmp_req.best_parent_rate = parent_rate;
+
+ ret = round(cm, &tmp_req, data);
+ if (ret)
+ continue;
/*
* parent_rate might have been modified by our clock.
@@ -131,16 +141,17 @@ int ccu_mux_helper_determine_rate(struct ccu_common *common,
* the actual frequency the parent needs to run at.
*/
parent_rate = ccu_mux_helper_unapply_prediv(common, cm, i,
- parent_rate);
- if (tmp_rate == req->rate) {
+ tmp_req.best_parent_rate);
+
+ if (tmp_req.rate == req->rate) {
best_parent = parent;
best_parent_rate = parent_rate;
- best_rate = tmp_rate;
+ best_rate = tmp_req.rate;
goto out;
}
- if (ccu_is_better_rate(common, req->rate, tmp_rate, best_rate)) {
- best_rate = tmp_rate;
+ if (ccu_is_better_rate(common, req->rate, tmp_req.rate, best_rate)) {
+ best_rate = tmp_req.rate;
best_parent_rate = parent_rate;
best_parent = parent;
}
diff --git a/drivers/clk/sunxi-ng/ccu_mux.h b/drivers/clk/sunxi-ng/ccu_mux.h
index eb1172ebbd94..c94a4bde5d01 100644
--- a/drivers/clk/sunxi-ng/ccu_mux.h
+++ b/drivers/clk/sunxi-ng/ccu_mux.h
@@ -137,11 +137,9 @@ unsigned long ccu_mux_helper_apply_prediv(struct ccu_common *common,
int ccu_mux_helper_determine_rate(struct ccu_common *common,
struct ccu_mux_internal *cm,
struct clk_rate_request *req,
- unsigned long (*round)(struct ccu_mux_internal *,
- struct clk_hw *,
- unsigned long *,
- unsigned long,
- void *),
+ int (*round)(struct ccu_mux_internal *,
+ struct clk_rate_request *,
+ void *),
void *data);
u8 ccu_mux_helper_get_parent(struct ccu_common *common,
struct ccu_mux_internal *cm);
diff --git a/drivers/clk/sunxi-ng/ccu_nkm.c b/drivers/clk/sunxi-ng/ccu_nkm.c
index 784eec9ac997..401fbb752479 100644
--- a/drivers/clk/sunxi-ng/ccu_nkm.c
+++ b/drivers/clk/sunxi-ng/ccu_nkm.c
@@ -162,11 +162,9 @@ static unsigned long ccu_nkm_recalc_rate(struct clk_hw *hw,
return rate;
}
-static unsigned long ccu_nkm_round_rate(struct ccu_mux_internal *mux,
- struct clk_hw *parent_hw,
- unsigned long *parent_rate,
- unsigned long rate,
- void *data)
+static int ccu_nkm_determine_rate_helper(struct ccu_mux_internal *mux,
+ struct clk_rate_request *req,
+ void *data)
{
struct ccu_nkm *nkm = data;
struct _ccu_nkm _nkm;
@@ -179,18 +177,21 @@ static unsigned long ccu_nkm_round_rate(struct ccu_mux_internal *mux,
_nkm.max_m = nkm->m.max ?: 1 << nkm->m.width;
if (nkm->common.features & CCU_FEATURE_FIXED_POSTDIV)
- rate *= nkm->fixed_post_div;
+ req->rate *= nkm->fixed_post_div;
if (!clk_hw_can_set_rate_parent(&nkm->common.hw))
- rate = ccu_nkm_find_best(*parent_rate, rate, &_nkm, &nkm->common);
+ req->rate = ccu_nkm_find_best(req->best_parent_rate, req->rate,
+ &_nkm, &nkm->common);
else
- rate = ccu_nkm_find_best_with_parent_adj(&nkm->common, parent_hw, parent_rate, rate,
- &_nkm);
+ req->rate = ccu_nkm_find_best_with_parent_adj(&nkm->common,
+ req->best_parent_hw,
+ &req->best_parent_rate,
+ req->rate, &_nkm);
if (nkm->common.features & CCU_FEATURE_FIXED_POSTDIV)
- rate /= nkm->fixed_post_div;
+ req->rate /= nkm->fixed_post_div;
- return rate;
+ return 0;
}
static int ccu_nkm_determine_rate(struct clk_hw *hw,
@@ -199,7 +200,7 @@ static int ccu_nkm_determine_rate(struct clk_hw *hw,
struct ccu_nkm *nkm = hw_to_ccu_nkm(hw);
return ccu_mux_helper_determine_rate(&nkm->common, &nkm->mux,
- req, ccu_nkm_round_rate, nkm);
+ req, ccu_nkm_determine_rate_helper, nkm);
}
static int ccu_nkm_set_rate(struct clk_hw *hw, unsigned long rate,
diff --git a/drivers/clk/x86/clk-cgu.c b/drivers/clk/x86/clk-cgu.c
index d099667355f8..92ee05d75af2 100644
--- a/drivers/clk/x86/clk-cgu.c
+++ b/drivers/clk/x86/clk-cgu.c
@@ -137,10 +137,8 @@ static int lgm_clk_divider_determine_rate(struct clk_hw *hw,
{
struct lgm_clk_divider *divider = to_lgm_clk_divider(hw);
- req->rate = divider_round_rate(hw, req->rate, &req->best_parent_rate, divider->table,
- divider->width, divider->flags);
-
- return 0;
+ return divider_determine_rate(hw, req, divider->table, divider->width,
+ divider->flags);
}
static int
diff --git a/drivers/clk/zynqmp/divider.c b/drivers/clk/zynqmp/divider.c
index 5baa967aa7c9..984e577ea671 100644
--- a/drivers/clk/zynqmp/divider.c
+++ b/drivers/clk/zynqmp/divider.c
@@ -150,8 +150,9 @@ static int zynqmp_clk_divider_determine_rate(struct clk_hw *hw,
width = fls(divider->max_div);
- req->rate = divider_round_rate(hw, req->rate, &req->best_parent_rate,
- NULL, width, divider->flags);
+ ret = divider_determine_rate(hw, req, NULL, width, divider->flags);
+ if (ret != 0)
+ return ret;
if (divider->is_frac && (clk_hw_get_flags(hw) & CLK_SET_RATE_PARENT) &&
(req->rate % req->best_parent_rate))
diff --git a/drivers/rtc/rtc-ac100.c b/drivers/rtc/rtc-ac100.c
index 33626311fa78..bba7115ff3ad 100644
--- a/drivers/rtc/rtc-ac100.c
+++ b/drivers/rtc/rtc-ac100.c
@@ -140,42 +140,16 @@ static unsigned long ac100_clkout_recalc_rate(struct clk_hw *hw,
AC100_CLKOUT_DIV_WIDTH);
}
-static long ac100_clkout_round_rate(struct clk_hw *hw, unsigned long rate,
- unsigned long prate)
-{
- unsigned long best_rate = 0, tmp_rate, tmp_prate;
- int i;
-
- if (prate == AC100_RTC_32K_RATE)
- return divider_round_rate(hw, rate, &prate, NULL,
- AC100_CLKOUT_DIV_WIDTH,
- CLK_DIVIDER_POWER_OF_TWO);
-
- for (i = 0; ac100_clkout_prediv[i].div; i++) {
- tmp_prate = DIV_ROUND_UP(prate, ac100_clkout_prediv[i].val);
- tmp_rate = divider_round_rate(hw, rate, &tmp_prate, NULL,
- AC100_CLKOUT_DIV_WIDTH,
- CLK_DIVIDER_POWER_OF_TWO);
-
- if (tmp_rate > rate)
- continue;
- if (rate - tmp_rate < best_rate - tmp_rate)
- best_rate = tmp_rate;
- }
-
- return best_rate;
-}
-
static int ac100_clkout_determine_rate(struct clk_hw *hw,
struct clk_rate_request *req)
{
- struct clk_hw *best_parent;
+ int i, ret, num_parents = clk_hw_get_num_parents(hw);
+ struct clk_hw *best_parent = NULL;
unsigned long best = 0;
- int i, num_parents = clk_hw_get_num_parents(hw);
for (i = 0; i < num_parents; i++) {
struct clk_hw *parent = clk_hw_get_parent_by_index(hw, i);
- unsigned long tmp, prate;
+ unsigned long prate;
/*
* The clock has two parents, one is a fixed clock which is
@@ -199,13 +173,40 @@ static int ac100_clkout_determine_rate(struct clk_hw *hw,
prate = clk_hw_get_rate(parent);
- tmp = ac100_clkout_round_rate(hw, req->rate, prate);
-
- if (tmp > req->rate)
- continue;
- if (req->rate - tmp < req->rate - best) {
- best = tmp;
- best_parent = parent;
+ if (prate == AC100_RTC_32K_RATE) {
+ struct clk_rate_request div_req = *req;
+
+ div_req.best_parent_rate = prate;
+
+ ret = divider_determine_rate(hw, &div_req, NULL,
+ AC100_CLKOUT_DIV_WIDTH,
+ CLK_DIVIDER_POWER_OF_TWO);
+ if (ret != 0 || div_req.rate > req->rate) {
+ continue;
+ } else if (req->rate - div_req.rate < req->rate - best) {
+ best = div_req.rate;
+ best_parent = parent;
+ }
+ } else {
+ int j;
+
+ for (j = 0; ac100_clkout_prediv[j].div; j++) {
+ struct clk_rate_request div_req = *req;
+ unsigned long tmp_prate;
+
+ tmp_prate = DIV_ROUND_UP(prate, ac100_clkout_prediv[j].div);
+ div_req.best_parent_rate = tmp_prate;
+
+ ret = divider_determine_rate(hw, &div_req, NULL,
+ AC100_CLKOUT_DIV_WIDTH,
+ CLK_DIVIDER_POWER_OF_TWO);
+ if (ret != 0 || div_req.rate > req->rate) {
+ continue;
+ } else if (req->rate - div_req.rate < req->rate - best) {
+ best = div_req.rate;
+ best_parent = parent;
+ }
+ }
}
}
@@ -213,7 +214,7 @@ static int ac100_clkout_determine_rate(struct clk_hw *hw,
return -EINVAL;
req->best_parent_hw = best_parent;
- req->best_parent_rate = best;
+ req->best_parent_rate = clk_hw_get_rate(best_parent);
req->rate = best;
return 0;