mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-04-04 20:32:27 -04:00
Merge branches 'clk-imx', 'clk-divider', 'clk-rockchip' and 'clk-microchip' into clk-next
* clk-imx: clk: imx: fracn-gppll: Add 241.90 MHz Support clk: imx: fracn-gppll: Add 332.60 MHz Support * clk-divider: rtc: ac100: convert from divider_round_rate() to divider_determine_rate() clk: zynqmp: divider: convert from divider_round_rate() to divider_determine_rate() clk: x86: cgu: convert from divider_round_rate() to divider_determine_rate() clk: versaclock3: convert from divider_round_rate() to divider_determine_rate() clk: stm32: stm32-core: convert from divider_round_rate_parent() to divider_determine_rate() clk: stm32: stm32-core: convert from divider_ro_round_rate() to divider_ro_determine_rate() clk: sprd: div: convert from divider_round_rate() to divider_determine_rate() clk: sophgo: sg2042-clkgen: convert from divider_round_rate() to divider_determine_rate() clk: nxp: lpc32xx: convert from divider_round_rate() to divider_determine_rate() clk: nuvoton: ma35d1-divider: convert from divider_round_rate() to divider_determine_rate() clk: milbeaut: convert from divider_round_rate() to divider_determine_rate() clk: milbeaut: convert from divider_ro_round_rate() to divider_ro_determine_rate() clk: loongson1: convert from divider_round_rate() to divider_determine_rate() clk: hisilicon: clkdivider-hi6220: convert from divider_round_rate() to divider_determine_rate() clk: bm1880: convert from divider_round_rate() to divider_determine_rate() clk: bm1880: convert from divider_ro_round_rate() to divider_ro_determine_rate() clk: actions: owl-divider: convert from divider_round_rate() to divider_determine_rate() clk: actions: owl-composite: convert from owl_divider_helper_round_rate() to divider_determine_rate() clk: sunxi-ng: convert from divider_round_rate_parent() to divider_determine_rate() clk: sophgo: cv18xx-ip: convert from divider_round_rate() to divider_determine_rate() * clk-rockchip: clk: rockchip: Fix error pointer check after rockchip_clk_register_gate_link() * clk-microchip: dt-bindings: clock: mpfs-clkcfg: Add pic64gx compatibility dt-bindings: clock: mpfs-ccc: Add pic64gx compatibility clk: microchip: drop POLARFIRE from ARCH_MICROCHIP_POLARFIRE clk: microchip: core: remove unused include asm/traps.h clk: microchip: core: correct return value on *_get_parent() clk: microchip: core: remove duplicate determine_rate on pic32_sclk_ops
This commit is contained in:
@@ -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:
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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;
|
||||
struct owl_divider_hw *div = &comp->rate.div_hw;
|
||||
|
||||
rate = owl_divider_helper_round_rate(&comp->common, &comp->rate.div_hw,
|
||||
req->rate, &req->best_parent_rate);
|
||||
if (rate < 0)
|
||||
return rate;
|
||||
|
||||
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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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 = {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
if (refo->parent_map) {
|
||||
for (i = 0; i < clk_hw_get_num_parents(hw); i++)
|
||||
if (refo->parent_map[i] == v)
|
||||
return i;
|
||||
}
|
||||
|
||||
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,
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 div_round_rate(parent, parent_rate, rate, id - 1, &div->div);
|
||||
return 0;
|
||||
}
|
||||
|
||||
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 mux_round_rate(parent, parent_rate, rate, id - 1, &mux->mux);
|
||||
return 0;
|
||||
}
|
||||
|
||||
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 div_helper_round_rate(&mmux->div[div_id],
|
||||
&mmux->common.hw, parent,
|
||||
rate, parent_rate);
|
||||
return 0;
|
||||
}
|
||||
|
||||
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,
|
||||
|
||||
@@ -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);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
pr_debug("--> %s: divider_round_rate: val = %ld\n",
|
||||
clk_hw_get_name(hw), ret_rate);
|
||||
req->rate = ret_rate;
|
||||
|
||||
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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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 (prate == AC100_RTC_32K_RATE) {
|
||||
struct clk_rate_request div_req = *req;
|
||||
|
||||
if (tmp > req->rate)
|
||||
continue;
|
||||
if (req->rate - tmp < req->rate - best) {
|
||||
best = tmp;
|
||||
best_parent = parent;
|
||||
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;
|
||||
|
||||
Reference in New Issue
Block a user