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:
Stephen Boyd
2026-02-14 10:23:51 -08:00
29 changed files with 282 additions and 328 deletions

View File

@@ -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:

View File

@@ -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:

View File

@@ -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,

View File

@@ -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,

View File

@@ -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);

View File

@@ -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,

View File

@@ -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,

View File

@@ -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,

View File

@@ -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,

View File

@@ -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,

View File

@@ -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 = {

View File

@@ -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

View File

@@ -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,

View File

@@ -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)

View File

@@ -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,

View File

@@ -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);
}
}

View File

@@ -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,

View File

@@ -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,

View File

@@ -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,

View File

@@ -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)

View File

@@ -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,

View File

@@ -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,

View File

@@ -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,

View File

@@ -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;
}

View File

@@ -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);

View File

@@ -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,

View File

@@ -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

View File

@@ -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))

View File

@@ -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;